<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Ethereum EIPs</title>
    <description>A feed of all EIPs</description>
    <link>https://eips.ethereum.org</link>
    <atom:link href="https://eips.ethereum.org/all.xml" rel="self" type="application/rss+xml" />
    <lastBuildDate>Sat, 18 Apr 2026 01:18:00 +0000</lastBuildDate>
    
    
      <item>
        <title></title>
        <category>/</category>
        
        <description>&lt;style type=&quot;text/css&quot; media=&quot;screen&quot;&gt;
  .container {
    margin: 10px auto;
    max-width: 600px;
    text-align: center;
  }
  h1 {
    margin: 30px 0;
    font-size: 4em;
    line-height: 1;
    letter-spacing: -1px;
  }
&lt;/style&gt;

&lt;div class=&quot;container&quot;&gt;
  &lt;h1&gt;404&lt;/h1&gt;
  &lt;p&gt;&lt;strong&gt;Page not found :(&lt;/strong&gt;&lt;/p&gt;
  &lt;p&gt;The requested page could not be found.&lt;/p&gt;
&lt;/div&gt;
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/404</link>
        <guid isPermaLink="true">https://eips.ethereum.org/404</guid>
      </item>
    
      <item>
        <title></title>
        <category>/</category>
        
        <description>&lt;p&gt;This set of interfaces and contracts are all related to the &lt;a href=&quot;https://eips.ethereum.org/EIPS/eip-1155&quot;&gt;ERC1155 Multi Token Standard&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The EIP consists of two interfaces which fulfill different roles, found here as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IERC1155&lt;/code&gt;  and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IERC1155TokenReceiver&lt;/code&gt;. Only &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IERC1155&lt;/code&gt; is required for a contract to be ERC1155 compliant. The basic functionality is implemented in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ERC1155&lt;/code&gt;.&lt;/p&gt;
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-3267/contracts/ERC1155/README</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-3267/contracts/ERC1155/README</guid>
      </item>
    
      <item>
        <title>All</title>
        <category>/</category>
        
        <description>&lt;style type=&quot;text/css&quot;&gt;
  .eiptable .title {
    width: 67%;
  }

  .eiptable .author {
    width: 33%;
  }
&lt;/style&gt;

  
  
  
    &lt;h2 id=&quot;living&quot;&gt;Living&lt;/h2&gt;
    &lt;table class=&quot;eiptable&quot;&gt;
      &lt;thead&gt;
        
          &lt;tr&gt;&lt;th class=&quot;eipnum&quot;&gt;Number&lt;/th&gt;&lt;th class=&quot;title&quot;&gt;Title&lt;/th&gt;&lt;th class=&quot;author&quot;&gt;Author&lt;/th&gt;&lt;/tr&gt;
        
      &lt;/thead&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1&quot;&gt;1&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EIP Purpose and Guidelines&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Martin Becze&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:mb@ethereum.org&quot;&gt;mb@ethereum.org&lt;/a&gt;&amp;gt;, Hudson Jameson&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:hudson@ethereum.org&quot;&gt;hudson@ethereum.org&lt;/a&gt;&amp;gt;,  et al.&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5069&quot;&gt;5069&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EIP Editor Handbook&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Pooja Ranjan&amp;nbsp;(&lt;a href=&quot;https://github.com/poojaranjan&quot;&gt;@poojaranjan&lt;/a&gt;), Gavin John&amp;nbsp;(&lt;a href=&quot;https://github.com/Pandapip1&quot;&gt;@Pandapip1&lt;/a&gt;), Sam Wilson&amp;nbsp;(&lt;a href=&quot;https://github.com/SamWilsn&quot;&gt;@SamWilsn&lt;/a&gt;),  et al.&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7870&quot;&gt;7870&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hardware and Bandwidth Recommendations&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Parithosh Jayanthi&amp;nbsp;(&lt;a href=&quot;https://github.com/parithosh&quot;&gt;@parithosh&lt;/a&gt;), Kevaundray Wedderburn&amp;nbsp;(&lt;a href=&quot;https://github.com/kevaundray&quot;&gt;@kevaundray&lt;/a&gt;), Josh Rudolf&amp;nbsp;(&lt;a href=&quot;https://github.com/jrudolf&quot;&gt;@jrudolf&lt;/a&gt;), Dankrad Feist&amp;nbsp;(&lt;a href=&quot;https://github.com/dankrad&quot;&gt;@dankrad&lt;/a&gt;), Justin Traglia&amp;nbsp;(&lt;a href=&quot;https://github.com/jtraglia&quot;&gt;@jtraglia&lt;/a&gt;), Ignacio Hagopian&amp;nbsp;(&lt;a href=&quot;https://github.com/jsign&quot;&gt;@jsign&lt;/a&gt;), George Kadianakis&amp;nbsp;(&lt;a href=&quot;https://github.com/asn-d6&quot;&gt;@asn-d6&lt;/a&gt;), Fredrik Svantes&amp;nbsp;(&lt;a href=&quot;https://github.com/fredriksvantes&quot;&gt;@fredriksvantes&lt;/a&gt;), Carl Beekhuizen&amp;nbsp;(&lt;a href=&quot;https://github.com/carlbeek&quot;&gt;@carlbeek&lt;/a&gt;), Toni Wahrstätter&amp;nbsp;(&lt;a href=&quot;https://github.com/nerolation&quot;&gt;@nerolation&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
    &lt;/table&gt;
  

  
  
  
    &lt;h2 id=&quot;final&quot;&gt;Final&lt;/h2&gt;
    &lt;table class=&quot;eiptable&quot;&gt;
      &lt;thead&gt;
        
          &lt;tr&gt;&lt;th class=&quot;eipnum&quot;&gt;Number&lt;/th&gt;&lt;th class=&quot;title&quot;&gt;Title&lt;/th&gt;&lt;th class=&quot;author&quot;&gt;Author&lt;/th&gt;&lt;/tr&gt;
        
      &lt;/thead&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2&quot;&gt;2&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Homestead Hard-fork Changes&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4&quot;&gt;4&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EIP Classification&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Joseph Chow&amp;nbsp;(&lt;a href=&quot;https://github.com/ethers&quot;&gt;@ethers&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5&quot;&gt;5&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Gas Usage for `RETURN` and `CALL*`&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Christian Reitwiessner&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:c@ethdev.com&quot;&gt;c@ethdev.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6&quot;&gt;6&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Renaming SUICIDE opcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Hudson Jameson&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:hudson@hudsonjameson.com&quot;&gt;hudson@hudsonjameson.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7&quot;&gt;7&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;DELEGATECALL&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8&quot;&gt;8&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;devp2p Forward Compatibility Requirements for Homestead&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Felix Lange&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:felix@ethdev.com&quot;&gt;felix@ethdev.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-20&quot;&gt;20&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Token Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Fabian Vogelsteller&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:fabian@ethereum.org&quot;&gt;fabian@ethereum.org&lt;/a&gt;&amp;gt;, Vitalik Buterin&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:vitalik.buterin@ethereum.org&quot;&gt;vitalik.buterin@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-55&quot;&gt;55&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Mixed-case checksum address encoding&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:vitalik.buterin@ethereum.org&quot;&gt;vitalik.buterin@ethereum.org&lt;/a&gt;&amp;gt;, Alex Van de Sande&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:avsa@ethereum.org&quot;&gt;avsa@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-100&quot;&gt;100&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Change difficulty adjustment to target mean block time including uncles&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-137&quot;&gt;137&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Ethereum Domain Name Service - Specification&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Johnson&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:arachnid@notdot.net&quot;&gt;arachnid@notdot.net&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-140&quot;&gt;140&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;REVERT instruction&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Nikolai Mushegian&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:nikolai@nexusdev.us&quot;&gt;nikolai@nexusdev.us&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-141&quot;&gt;141&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Designated invalid EVM instruction&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-145&quot;&gt;145&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Bitwise shifting instructions in EVM&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-150&quot;&gt;150&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Gas cost changes for IO-heavy operations&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-152&quot;&gt;152&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Add BLAKE2 compression function `F` precompile&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Tjaden Hess&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:tah83@cornell.edu&quot;&gt;tah83@cornell.edu&lt;/a&gt;&amp;gt;, Matt Luongo&amp;nbsp;(&lt;a href=&quot;https://github.com/mhluongo&quot;&gt;@mhluongo&lt;/a&gt;), Piotr Dyraga&amp;nbsp;(&lt;a href=&quot;https://github.com/pdyraga&quot;&gt;@pdyraga&lt;/a&gt;), James Hancock&amp;nbsp;(&lt;a href=&quot;https://github.com/MadeOfTin&quot;&gt;@MadeOfTin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-155&quot;&gt;155&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Simple replay attack protection&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-158&quot;&gt;158&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;State clearing&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-160&quot;&gt;160&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EXP cost increase&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-161&quot;&gt;161&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;State trie clearing (invariant-preserving alternative)&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gavin Wood&amp;nbsp;(&lt;a href=&quot;https://github.com/gavofyork&quot;&gt;@gavofyork&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-162&quot;&gt;162&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Initial ENS Hash Registrar&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Maurelian, Nick Johnson&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:nick@ethereum.org&quot;&gt;nick@ethereum.org&lt;/a&gt;&amp;gt;, Alex Van de Sande&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:avsa@ethereum.org&quot;&gt;avsa@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-165&quot;&gt;165&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Standard Interface Detection&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Christian Reitwießner&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:chris@ethereum.org&quot;&gt;chris@ethereum.org&lt;/a&gt;&amp;gt;, Nick Johnson&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:nick@ethereum.org&quot;&gt;nick@ethereum.org&lt;/a&gt;&amp;gt;, Fabian Vogelsteller&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:fabian@lukso.network&quot;&gt;fabian@lukso.network&lt;/a&gt;&amp;gt;, Jordi Baylina&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jordi@baylina.cat&quot;&gt;jordi@baylina.cat&lt;/a&gt;&amp;gt;, Konrad Feldmeier&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:konrad.feldmeier@brainbot.com&quot;&gt;konrad.feldmeier@brainbot.com&lt;/a&gt;&amp;gt;, William Entriken&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:github.com@phor.net&quot;&gt;github.com@phor.net&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-170&quot;&gt;170&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Contract code size limit&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-173&quot;&gt;173&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Contract Ownership Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Mudge&amp;nbsp;(&lt;a href=&quot;https://github.com/mudgen&quot;&gt;@mudgen&lt;/a&gt;), Dan Finlay&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:dan@danfinlay.com&quot;&gt;dan@danfinlay.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-181&quot;&gt;181&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ENS support for reverse resolution of Ethereum addresses&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Johnson&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:arachnid@notdot.net&quot;&gt;arachnid@notdot.net&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-190&quot;&gt;190&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Ethereum Smart Contract Packaging Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Piper Merriam&amp;nbsp;(&lt;a href=&quot;https://github.com/pipermerriam&quot;&gt;@pipermerriam&lt;/a&gt;), Tim Coulter&amp;nbsp;(&lt;a href=&quot;https://github.com/tcoulter&quot;&gt;@tcoulter&lt;/a&gt;), Denis Erfurt&amp;nbsp;(&lt;a href=&quot;https://github.com/mhhf&quot;&gt;@mhhf&lt;/a&gt;), RJ Catalano&amp;nbsp;(&lt;a href=&quot;https://github.com/VoR0220&quot;&gt;@VoR0220&lt;/a&gt;), Iuri Matias&amp;nbsp;(&lt;a href=&quot;https://github.com/iurimatias&quot;&gt;@iurimatias&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-191&quot;&gt;191&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Signed Data Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Martin Holst Swende&amp;nbsp;(&lt;a href=&quot;https://github.com/holiman&quot;&gt;@holiman&lt;/a&gt;), Nick Johnson&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:arachnid@notdot.net&quot;&gt;arachnid@notdot.net&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-196&quot;&gt;196&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Precompiled contracts for addition and scalar multiplication on the elliptic curve alt_bn128&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Christian Reitwiessner&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:chris@ethereum.org&quot;&gt;chris@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-197&quot;&gt;197&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Precompiled contracts for optimal ate pairing check on the elliptic curve alt_bn128&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:vitalik@ethereum.org&quot;&gt;vitalik@ethereum.org&lt;/a&gt;&amp;gt;, Christian Reitwiessner&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:chris@ethereum.org&quot;&gt;chris@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-198&quot;&gt;198&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Big integer modular exponentiation&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-211&quot;&gt;211&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;New opcodes: RETURNDATASIZE and RETURNDATACOPY&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Christian Reitwiessner&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:chris@ethereum.org&quot;&gt;chris@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-214&quot;&gt;214&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;New opcode STATICCALL&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:vitalik@ethereum.org&quot;&gt;vitalik@ethereum.org&lt;/a&gt;&amp;gt;, Christian Reitwiessner&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:chris@ethereum.org&quot;&gt;chris@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-223&quot;&gt;223&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Token with transaction handling model&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Dexaran (@Dexaran)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:dexaran@ethereumclassic.org&quot;&gt;dexaran@ethereumclassic.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-225&quot;&gt;225&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Clique proof-of-authority consensus protocol&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Péter Szilágyi&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:peterke@gmail.com&quot;&gt;peterke@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-234&quot;&gt;234&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Add `blockHash` to JSON-RPC filter options.&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Micah Zoltu&amp;nbsp;(&lt;a href=&quot;https://github.com/MicahZoltu&quot;&gt;@MicahZoltu&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-600&quot;&gt;600&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Ethereum purpose allocation for Deterministic Wallets&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Johnson&amp;nbsp;(&lt;a href=&quot;https://github.com/arachnid&quot;&gt;@arachnid&lt;/a&gt;), Micah Zoltu&amp;nbsp;(&lt;a href=&quot;https://github.com/micahzoltu&quot;&gt;@micahzoltu&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-601&quot;&gt;601&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Ethereum hierarchy for deterministic wallets&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Johnson&amp;nbsp;(&lt;a href=&quot;https://github.com/arachnid&quot;&gt;@arachnid&lt;/a&gt;), Micah Zoltu&amp;nbsp;(&lt;a href=&quot;https://github.com/micahzoltu&quot;&gt;@micahzoltu&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-606&quot;&gt;606&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hardfork Meta: Homestead&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-607&quot;&gt;607&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hardfork Meta: Spurious Dragon&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-608&quot;&gt;608&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hardfork Meta: Tangerine Whistle&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-609&quot;&gt;609&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hardfork Meta: Byzantium&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-627&quot;&gt;627&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Whisper Specification&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vlad Gluhovsky&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:gluk256@gmail.com&quot;&gt;gluk256@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-649&quot;&gt;649&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Metropolis Difficulty Bomb Delay and Block Reward Reduction&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Afri Schoedon&amp;nbsp;(&lt;a href=&quot;https://github.com/5chdn&quot;&gt;@5chdn&lt;/a&gt;), Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-658&quot;&gt;658&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Embedding transaction status code in receipts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Johnson&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:nick@ethereum.org&quot;&gt;nick@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-681&quot;&gt;681&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;URL Format for Transaction Requests&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Daniel A. Nagy&amp;nbsp;(&lt;a href=&quot;https://github.com/nagydani&quot;&gt;@nagydani&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-684&quot;&gt;684&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Revert creation in case of collision&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Renan Rodrigues de Souza&amp;nbsp;(&lt;a href=&quot;https://github.com/RenanSouza2&quot;&gt;@RenanSouza2&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-695&quot;&gt;695&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Create `eth_chainId` method for JSON-RPC&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Isaac Ardis&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:isaac.ardis@gmail.com&quot;&gt;isaac.ardis@gmail.com&lt;/a&gt;&amp;gt;, Wei Tang&amp;nbsp;(&lt;a href=&quot;https://github.com/sorpaas&quot;&gt;@sorpaas&lt;/a&gt;), Fan Torchz&amp;nbsp;(&lt;a href=&quot;https://github.com/tcz001&quot;&gt;@tcz001&lt;/a&gt;), Erik Marks&amp;nbsp;(&lt;a href=&quot;https://github.com/rekmarks&quot;&gt;@rekmarks&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-706&quot;&gt;706&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;DEVp2p snappy compression&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Péter Szilágyi&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:peter@ethereum.org&quot;&gt;peter@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-712&quot;&gt;712&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Typed structured data hashing and signing&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Remco Bloemen&amp;nbsp;(&lt;a href=&quot;https://github.com/Recmo&quot;&gt;@Recmo&lt;/a&gt;), Leonid Logvinov&amp;nbsp;(&lt;a href=&quot;https://github.com/LogvinovLeon&quot;&gt;@LogvinovLeon&lt;/a&gt;), Jacob Evans&amp;nbsp;(&lt;a href=&quot;https://github.com/dekz&quot;&gt;@dekz&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-721&quot;&gt;721&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Non-Fungible Token Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;William Entriken&amp;nbsp;(&lt;a href=&quot;https://github.com/fulldecent&quot;&gt;@fulldecent&lt;/a&gt;), Dieter Shirley&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:dete@axiomzen.co&quot;&gt;dete@axiomzen.co&lt;/a&gt;&amp;gt;, Jacob Evans&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jacob@dekz.net&quot;&gt;jacob@dekz.net&lt;/a&gt;&amp;gt;, Nastassia Sachs&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:nastassia.sachs@protonmail.com&quot;&gt;nastassia.sachs@protonmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-747&quot;&gt;747&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;wallet_watchAsset RPC Method&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Dan Finlay&amp;nbsp;(&lt;a href=&quot;https://github.com/danfinlay&quot;&gt;@danfinlay&lt;/a&gt;), Esteban Mino&amp;nbsp;(&lt;a href=&quot;https://github.com/estebanmino&quot;&gt;@estebanmino&lt;/a&gt;), Gavin John&amp;nbsp;(&lt;a href=&quot;https://github.com/Pandapip1&quot;&gt;@Pandapip1&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-777&quot;&gt;777&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Token Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jacques Dafflon&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:mail@0xjac.com&quot;&gt;mail@0xjac.com&lt;/a&gt;&amp;gt;, Jordi Baylina&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jordi@baylina.cat&quot;&gt;jordi@baylina.cat&lt;/a&gt;&amp;gt;, Thomas Shababi&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:tom@truelevel.io&quot;&gt;tom@truelevel.io&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-778&quot;&gt;778&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Ethereum Node Records (ENR)&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Felix Lange&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:fjl@ethereum.org&quot;&gt;fjl@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-779&quot;&gt;779&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hardfork Meta: DAO Fork&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Casey Detrio&amp;nbsp;(&lt;a href=&quot;https://github.com/cdetrio&quot;&gt;@cdetrio&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-820&quot;&gt;820&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Pseudo-introspection Registry Contract&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jordi Baylina&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jordi@baylina.cat&quot;&gt;jordi@baylina.cat&lt;/a&gt;&amp;gt;, Jacques Dafflon&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jacques@dafflon.tech&quot;&gt;jacques@dafflon.tech&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-868&quot;&gt;868&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Node Discovery v4 ENR Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Felix Lange&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:fjl@ethereum.org&quot;&gt;fjl@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1013&quot;&gt;1013&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hardfork Meta: Constantinople&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Savers&amp;nbsp;(&lt;a href=&quot;https://github.com/nicksavers&quot;&gt;@nicksavers&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1014&quot;&gt;1014&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Skinny CREATE2&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1046&quot;&gt;1046&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;tokenURI Interoperability&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Tommy Nicholas&amp;nbsp;(&lt;a href=&quot;https://github.com/tomasienrbc&quot;&gt;@tomasienrbc&lt;/a&gt;), Matt Russo&amp;nbsp;(&lt;a href=&quot;https://github.com/mateosu&quot;&gt;@mateosu&lt;/a&gt;), John Zettler&amp;nbsp;(&lt;a href=&quot;https://github.com/JohnZettler&quot;&gt;@JohnZettler&lt;/a&gt;), Matt Condon&amp;nbsp;(&lt;a href=&quot;https://github.com/shrugs&quot;&gt;@shrugs&lt;/a&gt;), Gavin John&amp;nbsp;(&lt;a href=&quot;https://github.com/Pandapip1&quot;&gt;@Pandapip1&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1052&quot;&gt;1052&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EXTCODEHASH opcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Johnson&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:arachnid@notdot.net&quot;&gt;arachnid@notdot.net&lt;/a&gt;&amp;gt;, Paweł Bylica&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:pawel@ethereum.org&quot;&gt;pawel@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1108&quot;&gt;1108&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Reduce alt_bn128 precompile gas costs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Antonio Salazar Cardozo&amp;nbsp;(&lt;a href=&quot;https://github.com/shadowfiend&quot;&gt;@shadowfiend&lt;/a&gt;), Zachary Williamson&amp;nbsp;(&lt;a href=&quot;https://github.com/zac-williamson&quot;&gt;@zac-williamson&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1153&quot;&gt;1153&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Transient storage opcodes&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alexey Akhunov&amp;nbsp;(&lt;a href=&quot;https://github.com/AlexeyAkhunov&quot;&gt;@AlexeyAkhunov&lt;/a&gt;), Moody Salem&amp;nbsp;(&lt;a href=&quot;https://github.com/moodysalem&quot;&gt;@moodysalem&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1155&quot;&gt;1155&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Multi Token Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Witek Radomski&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:witek@enjin.io&quot;&gt;witek@enjin.io&lt;/a&gt;&amp;gt;, Andrew Cooke&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:ac0dem0nk3y@gmail.com&quot;&gt;ac0dem0nk3y@gmail.com&lt;/a&gt;&amp;gt;, Philippe Castonguay (@phabc)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:pc@horizongames.net&quot;&gt;pc@horizongames.net&lt;/a&gt;&amp;gt;, James Therien&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:james@turing-complete.com&quot;&gt;james@turing-complete.com&lt;/a&gt;&amp;gt;, Eric Binet&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:eric@enjin.io&quot;&gt;eric@enjin.io&lt;/a&gt;&amp;gt;, Ronan Sandford (@wighawag)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:wighawag@gmail.com&quot;&gt;wighawag@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1167&quot;&gt;1167&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Minimal Proxy Contract&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Peter Murray&amp;nbsp;(&lt;a href=&quot;https://github.com/yarrumretep&quot;&gt;@yarrumretep&lt;/a&gt;), Nate Welch&amp;nbsp;(&lt;a href=&quot;https://github.com/flygoing&quot;&gt;@flygoing&lt;/a&gt;), Joe Messerman&amp;nbsp;(&lt;a href=&quot;https://github.com/JAMesserman&quot;&gt;@JAMesserman&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1193&quot;&gt;1193&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Ethereum Provider JavaScript API&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Fabian Vogelsteller&amp;nbsp;(&lt;a href=&quot;https://github.com/frozeman&quot;&gt;@frozeman&lt;/a&gt;), Ryan Ghods&amp;nbsp;(&lt;a href=&quot;https://github.com/ryanio&quot;&gt;@ryanio&lt;/a&gt;), Victor Maia&amp;nbsp;(&lt;a href=&quot;https://github.com/MaiaVictor&quot;&gt;@MaiaVictor&lt;/a&gt;), Marc Garreau&amp;nbsp;(&lt;a href=&quot;https://github.com/wolovim&quot;&gt;@wolovim&lt;/a&gt;), Erik Marks&amp;nbsp;(&lt;a href=&quot;https://github.com/rekmarks&quot;&gt;@rekmarks&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1234&quot;&gt;1234&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Constantinople Difficulty Bomb Delay and Block Reward Adjustment&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Afri Schoedon&amp;nbsp;(&lt;a href=&quot;https://github.com/5chdn&quot;&gt;@5chdn&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1271&quot;&gt;1271&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Standard Signature Validation Method for Contracts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Francisco Giordano&amp;nbsp;(&lt;a href=&quot;https://github.com/frangio&quot;&gt;@frangio&lt;/a&gt;), Matt Condon&amp;nbsp;(&lt;a href=&quot;https://github.com/shrugs&quot;&gt;@shrugs&lt;/a&gt;), Philippe Castonguay&amp;nbsp;(&lt;a href=&quot;https://github.com/PhABC&quot;&gt;@PhABC&lt;/a&gt;), Amir Bandeali&amp;nbsp;(&lt;a href=&quot;https://github.com/abandeali1&quot;&gt;@abandeali1&lt;/a&gt;), Jorge Izquierdo&amp;nbsp;(&lt;a href=&quot;https://github.com/izqui&quot;&gt;@izqui&lt;/a&gt;), Bertrand Masius&amp;nbsp;(&lt;a href=&quot;https://github.com/catageek&quot;&gt;@catageek&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1283&quot;&gt;1283&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Net gas metering for SSTORE without dirty maps&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Wei Tang&amp;nbsp;(&lt;a href=&quot;https://github.com/sorpaas&quot;&gt;@sorpaas&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1328&quot;&gt;1328&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;WalletConnect URI Format&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;ligi&amp;nbsp;(&lt;a href=&quot;https://github.com/ligi&quot;&gt;@ligi&lt;/a&gt;), Pedro Gomes&amp;nbsp;(&lt;a href=&quot;https://github.com/pedrouid&quot;&gt;@pedrouid&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1344&quot;&gt;1344&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ChainID opcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Richard Meissner&amp;nbsp;(&lt;a href=&quot;https://github.com/rmeissner&quot;&gt;@rmeissner&lt;/a&gt;), Bryant Eisenbach&amp;nbsp;(&lt;a href=&quot;https://github.com/fubuloubu&quot;&gt;@fubuloubu&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1363&quot;&gt;1363&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Payable Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vittorio Minacori&amp;nbsp;(&lt;a href=&quot;https://github.com/vittominacori&quot;&gt;@vittominacori&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1559&quot;&gt;1559&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Fee market change for ETH 1.0 chain&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Eric Conner&amp;nbsp;(&lt;a href=&quot;https://github.com/econoar&quot;&gt;@econoar&lt;/a&gt;), Rick Dudley&amp;nbsp;(&lt;a href=&quot;https://github.com/AFDudley&quot;&gt;@AFDudley&lt;/a&gt;), Matthew Slipper&amp;nbsp;(&lt;a href=&quot;https://github.com/mslipper&quot;&gt;@mslipper&lt;/a&gt;), Ian Norden&amp;nbsp;(&lt;a href=&quot;https://github.com/i-norden&quot;&gt;@i-norden&lt;/a&gt;), Abdelhamid Bakhta&amp;nbsp;(&lt;a href=&quot;https://github.com/abdelhamidbakhta&quot;&gt;@abdelhamidbakhta&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1679&quot;&gt;1679&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hardfork Meta: Istanbul&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Afri Schoedon&amp;nbsp;(&lt;a href=&quot;https://github.com/5chdn&quot;&gt;@5chdn&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1716&quot;&gt;1716&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hardfork Meta: Petersburg&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Afri Schoedon&amp;nbsp;(&lt;a href=&quot;https://github.com/5chdn&quot;&gt;@5chdn&lt;/a&gt;), Marius van der Wijden&amp;nbsp;(&lt;a href=&quot;https://github.com/MariusVanDerWijden&quot;&gt;@MariusVanDerWijden&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1820&quot;&gt;1820&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Pseudo-introspection Registry Contract&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jordi Baylina&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jordi@baylina.cat&quot;&gt;jordi@baylina.cat&lt;/a&gt;&amp;gt;, Jacques Dafflon&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:mail@0xjac.com&quot;&gt;mail@0xjac.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1884&quot;&gt;1884&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Repricing for trie-size-dependent opcodes&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Martin Holst Swende&amp;nbsp;(&lt;a href=&quot;https://github.com/holiman&quot;&gt;@holiman&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1898&quot;&gt;1898&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Add `blockHash` to defaultBlock methods&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Charles Cooper&amp;nbsp;(&lt;a href=&quot;https://github.com/charles-cooper&quot;&gt;@charles-cooper&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1967&quot;&gt;1967&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Proxy Storage Slots&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Santiago Palladino&amp;nbsp;(&lt;a href=&quot;https://github.com/spalladino&quot;&gt;@spalladino&lt;/a&gt;), Francisco Giordano&amp;nbsp;(&lt;a href=&quot;https://github.com/frangio&quot;&gt;@frangio&lt;/a&gt;), Hadrien Croubois&amp;nbsp;(&lt;a href=&quot;https://github.com/Amxx&quot;&gt;@Amxx&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2028&quot;&gt;2028&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Transaction data gas cost reduction&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alexey Akhunov&amp;nbsp;(&lt;a href=&quot;https://github.com/AlexeyAkhunov&quot;&gt;@AlexeyAkhunov&lt;/a&gt;), Eli Ben Sasson&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:eli@starkware.co&quot;&gt;eli@starkware.co&lt;/a&gt;&amp;gt;, Tom Brand&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:tom@starkware.co&quot;&gt;tom@starkware.co&lt;/a&gt;&amp;gt;, Louis Guthmann&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:louis@starkware.co&quot;&gt;louis@starkware.co&lt;/a&gt;&amp;gt;, Avihu Levy&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:avihu@starkware.co&quot;&gt;avihu@starkware.co&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2098&quot;&gt;2098&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Compact Signature Representation&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Richard Moore&amp;nbsp;(&lt;a href=&quot;https://github.com/ricmoo&quot;&gt;@ricmoo&lt;/a&gt;), Nick Johnson&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:nick@ethereum.org&quot;&gt;nick@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2124&quot;&gt;2124&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Fork identifier for chain compatibility checks&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Péter Szilágyi&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:peterke@gmail.com&quot;&gt;peterke@gmail.com&lt;/a&gt;&amp;gt;, Felix Lange&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:fjl@ethereum.org&quot;&gt;fjl@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2135&quot;&gt;2135&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Consumable Interface (Tickets, etc)&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Zainan Victor Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/xinbenlv&quot;&gt;@xinbenlv&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2159&quot;&gt;2159&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Common Prometheus Metrics Names for Clients&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Adrian Sutton&amp;nbsp;(&lt;a href=&quot;https://github.com/ajsutton&quot;&gt;@ajsutton&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2200&quot;&gt;2200&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Structured Definitions for Net Gas Metering&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Wei Tang&amp;nbsp;(&lt;a href=&quot;https://github.com/sorpaas&quot;&gt;@sorpaas&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2228&quot;&gt;2228&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Canonicalize the name of network ID 1 and chain ID 1&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;William Entriken&amp;nbsp;(&lt;a href=&quot;https://github.com/fulldecent&quot;&gt;@fulldecent&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2255&quot;&gt;2255&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Wallet Permissions System&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Dan Finlay&amp;nbsp;(&lt;a href=&quot;https://github.com/danfinlay&quot;&gt;@danfinlay&lt;/a&gt;), Erik Marks&amp;nbsp;(&lt;a href=&quot;https://github.com/rekmarks&quot;&gt;@rekmarks&lt;/a&gt;), Gavin John&amp;nbsp;(&lt;a href=&quot;https://github.com/Pandapip1&quot;&gt;@Pandapip1&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2309&quot;&gt;2309&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-721 Consecutive Transfer Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Sean Papanikolas&amp;nbsp;(&lt;a href=&quot;https://github.com/pizzarob&quot;&gt;@pizzarob&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2364&quot;&gt;2364&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;eth/64: forkid-extended protocol handshake&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Péter Szilágyi&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:peterke@gmail.com&quot;&gt;peterke@gmail.com&lt;/a&gt;&amp;gt;, Péter Szilágyi&amp;nbsp;(&lt;a href=&quot;https://github.com/karalabe&quot;&gt;@karalabe&lt;/a&gt;), Tim Beiko&amp;nbsp;(&lt;a href=&quot;https://github.com/timbeiko&quot;&gt;@timbeiko&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2384&quot;&gt;2384&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Muir Glacier Difficulty Bomb Delay&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Eric Conner&amp;nbsp;(&lt;a href=&quot;https://github.com/econoar&quot;&gt;@econoar&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2387&quot;&gt;2387&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hardfork Meta: Muir Glacier&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;James Hancock&amp;nbsp;(&lt;a href=&quot;https://github.com/madeoftin&quot;&gt;@madeoftin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2464&quot;&gt;2464&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;eth/65: transaction announcements and retrievals&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Péter Szilágyi&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:peterke@gmail.com&quot;&gt;peterke@gmail.com&lt;/a&gt;&amp;gt;, Péter Szilágyi&amp;nbsp;(&lt;a href=&quot;https://github.com/karalabe&quot;&gt;@karalabe&lt;/a&gt;), Gary Rong&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:garyrong0905@gmail.com&quot;&gt;garyrong0905@gmail.com&lt;/a&gt;&amp;gt;, Tim Beiko&amp;nbsp;(&lt;a href=&quot;https://github.com/timbeiko&quot;&gt;@timbeiko&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2481&quot;&gt;2481&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;eth/66 request identifier&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Christoph Burgdorf&amp;nbsp;(&lt;a href=&quot;https://github.com/cburgdorf&quot;&gt;@cburgdorf&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2535&quot;&gt;2535&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Diamonds, Multi-Facet Proxy&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Mudge&amp;nbsp;(&lt;a href=&quot;https://github.com/mudgen&quot;&gt;@mudgen&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2537&quot;&gt;2537&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Precompile for BLS12-381 curve operations&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Vlasov&amp;nbsp;(&lt;a href=&quot;https://github.com/shamatar&quot;&gt;@shamatar&lt;/a&gt;), Kelly Olson&amp;nbsp;(&lt;a href=&quot;https://github.com/ineffectualproperty&quot;&gt;@ineffectualproperty&lt;/a&gt;), Alex Stokes&amp;nbsp;(&lt;a href=&quot;https://github.com/ralexstokes&quot;&gt;@ralexstokes&lt;/a&gt;), Antonio Sanso&amp;nbsp;(&lt;a href=&quot;https://github.com/asanso&quot;&gt;@asanso&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2565&quot;&gt;2565&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ModExp Gas Cost&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Kelly Olson&amp;nbsp;(&lt;a href=&quot;https://github.com/ineffectualproperty&quot;&gt;@ineffectualproperty&lt;/a&gt;), Sean Gulley&amp;nbsp;(&lt;a href=&quot;https://github.com/sean-sn&quot;&gt;@sean-sn&lt;/a&gt;), Simon Peffers&amp;nbsp;(&lt;a href=&quot;https://github.com/simonatsn&quot;&gt;@simonatsn&lt;/a&gt;), Justin Drake&amp;nbsp;(&lt;a href=&quot;https://github.com/justindrake&quot;&gt;@justindrake&lt;/a&gt;), Dankrad Feist&amp;nbsp;(&lt;a href=&quot;https://github.com/dankrad&quot;&gt;@dankrad&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2612&quot;&gt;2612&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Permit Extension for EIP-20 Signed Approvals&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Martin Lundfall&amp;nbsp;(&lt;a href=&quot;https://github.com/Mrchico&quot;&gt;@Mrchico&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2678&quot;&gt;2678&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Revised Ethereum Smart Contract Packaging Standard (EthPM v3)&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;g. nicholas d’andrea&amp;nbsp;(&lt;a href=&quot;https://github.com/gnidan&quot;&gt;@gnidan&lt;/a&gt;), Piper Merriam&amp;nbsp;(&lt;a href=&quot;https://github.com/pipermerriam&quot;&gt;@pipermerriam&lt;/a&gt;), Nick Gheorghita&amp;nbsp;(&lt;a href=&quot;https://github.com/njgheorghita&quot;&gt;@njgheorghita&lt;/a&gt;), Christian Reitwiessner&amp;nbsp;(&lt;a href=&quot;https://github.com/chriseth&quot;&gt;@chriseth&lt;/a&gt;), Ben Hauser&amp;nbsp;(&lt;a href=&quot;https://github.com/iamdefinitelyahuman&quot;&gt;@iamdefinitelyahuman&lt;/a&gt;), Bryant Eisenbach&amp;nbsp;(&lt;a href=&quot;https://github.com/fubuloubu&quot;&gt;@fubuloubu&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2681&quot;&gt;2681&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Limit account nonce to 2^64-1&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2696&quot;&gt;2696&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;JavaScript `request` method RPC transport&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Micah Zoltu&amp;nbsp;(&lt;a href=&quot;https://github.com/MicahZoltu&quot;&gt;@MicahZoltu&lt;/a&gt;), Erik Marks&amp;nbsp;(&lt;a href=&quot;https://github.com/rekmarks&quot;&gt;@rekmarks&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2700&quot;&gt;2700&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;JavaScript Provider Event Emitter&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Micah Zoltu&amp;nbsp;(&lt;a href=&quot;https://github.com/MicahZoltu&quot;&gt;@MicahZoltu&lt;/a&gt;), Erik Marks&amp;nbsp;(&lt;a href=&quot;https://github.com/rekmarks&quot;&gt;@rekmarks&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2718&quot;&gt;2718&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Typed Transaction Envelope&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Micah Zoltu&amp;nbsp;(&lt;a href=&quot;https://github.com/MicahZoltu&quot;&gt;@MicahZoltu&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2771&quot;&gt;2771&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Secure Protocol for Native Meta Transactions&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ronan Sandford&amp;nbsp;(&lt;a href=&quot;https://github.com/wighawag&quot;&gt;@wighawag&lt;/a&gt;), Liraz Siri&amp;nbsp;(&lt;a href=&quot;https://github.com/lirazsiri&quot;&gt;@lirazsiri&lt;/a&gt;), Dror Tirosh&amp;nbsp;(&lt;a href=&quot;https://github.com/drortirosh&quot;&gt;@drortirosh&lt;/a&gt;), Yoav Weiss&amp;nbsp;(&lt;a href=&quot;https://github.com/yoavw&quot;&gt;@yoavw&lt;/a&gt;), Alex Forshtat&amp;nbsp;(&lt;a href=&quot;https://github.com/forshtat&quot;&gt;@forshtat&lt;/a&gt;), Hadrien Croubois&amp;nbsp;(&lt;a href=&quot;https://github.com/Amxx&quot;&gt;@Amxx&lt;/a&gt;), Sachin Tomar&amp;nbsp;(&lt;a href=&quot;https://github.com/tomarsachin2271&quot;&gt;@tomarsachin2271&lt;/a&gt;), Patrick McCorry&amp;nbsp;(&lt;a href=&quot;https://github.com/stonecoldpat&quot;&gt;@stonecoldpat&lt;/a&gt;), Nicolas Venturo&amp;nbsp;(&lt;a href=&quot;https://github.com/nventuro&quot;&gt;@nventuro&lt;/a&gt;), Fabian Vogelsteller&amp;nbsp;(&lt;a href=&quot;https://github.com/frozeman&quot;&gt;@frozeman&lt;/a&gt;), Gavin John&amp;nbsp;(&lt;a href=&quot;https://github.com/Pandapip1&quot;&gt;@Pandapip1&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2929&quot;&gt;2929&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Gas cost increases for state access opcodes&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Martin Swende&amp;nbsp;(&lt;a href=&quot;https://github.com/holiman&quot;&gt;@holiman&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2930&quot;&gt;2930&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Optional access lists&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Martin Swende&amp;nbsp;(&lt;a href=&quot;https://github.com/holiman&quot;&gt;@holiman&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2935&quot;&gt;2935&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Serve historical block hashes from state&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Tomasz Stanczak&amp;nbsp;(&lt;a href=&quot;https://github.com/tkstanczak&quot;&gt;@tkstanczak&lt;/a&gt;), Guillaume Ballet&amp;nbsp;(&lt;a href=&quot;https://github.com/gballet&quot;&gt;@gballet&lt;/a&gt;), Gajinder Singh&amp;nbsp;(&lt;a href=&quot;https://github.com/g11tech&quot;&gt;@g11tech&lt;/a&gt;), Tanishq Jasoria&amp;nbsp;(&lt;a href=&quot;https://github.com/tanishqjasoria&quot;&gt;@tanishqjasoria&lt;/a&gt;), Ignacio Hagopian&amp;nbsp;(&lt;a href=&quot;https://github.com/jsign&quot;&gt;@jsign&lt;/a&gt;), Jochem Brouwer&amp;nbsp;(&lt;a href=&quot;https://github.com/jochem-brouwer&quot;&gt;@jochem-brouwer&lt;/a&gt;), Sina Mahmoodi&amp;nbsp;(&lt;a href=&quot;https://github.com/s1na&quot;&gt;@s1na&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2976&quot;&gt;2976&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Typed Transactions over Gossip&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Micah Zoltu&amp;nbsp;(&lt;a href=&quot;https://github.com/MicahZoltu&quot;&gt;@MicahZoltu&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2981&quot;&gt;2981&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;NFT Royalty Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Zach Burks&amp;nbsp;(&lt;a href=&quot;https://github.com/vexycats&quot;&gt;@vexycats&lt;/a&gt;), James Morgan&amp;nbsp;(&lt;a href=&quot;https://github.com/jamesmorgan&quot;&gt;@jamesmorgan&lt;/a&gt;), Blaine Malone&amp;nbsp;(&lt;a href=&quot;https://github.com/blmalone&quot;&gt;@blmalone&lt;/a&gt;), James Seibel&amp;nbsp;(&lt;a href=&quot;https://github.com/seibelj&quot;&gt;@seibelj&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2982&quot;&gt;2982&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Serenity Phase 0&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Danny Ryan&amp;nbsp;(&lt;a href=&quot;https://github.com/djrtwo&quot;&gt;@djrtwo&lt;/a&gt;), Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3156&quot;&gt;3156&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Flash Loans&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alberto Cuesta Cañada&amp;nbsp;(&lt;a href=&quot;https://github.com/alcueca&quot;&gt;@alcueca&lt;/a&gt;), Fiona Kobayashi&amp;nbsp;(&lt;a href=&quot;https://github.com/fifikobayashi&quot;&gt;@fifikobayashi&lt;/a&gt;), fubuloubu&amp;nbsp;(&lt;a href=&quot;https://github.com/fubuloubu&quot;&gt;@fubuloubu&lt;/a&gt;), Austin Williams&amp;nbsp;(&lt;a href=&quot;https://github.com/onewayfunction&quot;&gt;@onewayfunction&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3198&quot;&gt;3198&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;BASEFEE opcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Abdelhamid Bakhta&amp;nbsp;(&lt;a href=&quot;https://github.com/abdelhamidbakhta&quot;&gt;@abdelhamidbakhta&lt;/a&gt;), Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3448&quot;&gt;3448&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;MetaProxy Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;pinkiebell&amp;nbsp;(&lt;a href=&quot;https://github.com/pinkiebell&quot;&gt;@pinkiebell&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3475&quot;&gt;3475&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Abstract Storage Bonds&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Yu Liu&amp;nbsp;(&lt;a href=&quot;https://github.com/yuliu-debond&quot;&gt;@yuliu-debond&lt;/a&gt;), Varun Deshpande&amp;nbsp;(&lt;a href=&quot;https://github.com/dr-chain&quot;&gt;@dr-chain&lt;/a&gt;), Cedric Ngakam&amp;nbsp;(&lt;a href=&quot;https://github.com/drikssy&quot;&gt;@drikssy&lt;/a&gt;), Dhruv Malik&amp;nbsp;(&lt;a href=&quot;https://github.com/dhruvmalik007&quot;&gt;@dhruvmalik007&lt;/a&gt;), Samuel Gwlanold Edoumou&amp;nbsp;(&lt;a href=&quot;https://github.com/Edoumou&quot;&gt;@Edoumou&lt;/a&gt;), Toufic Batrice&amp;nbsp;(&lt;a href=&quot;https://github.com/toufic0710&quot;&gt;@toufic0710&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3525&quot;&gt;3525&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Semi-Fungible Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Will Wang&amp;nbsp;(&lt;a href=&quot;https://github.com/will42w&quot;&gt;@will42w&lt;/a&gt;), Mike Meng&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:myan@solv.finance&quot;&gt;myan@solv.finance&lt;/a&gt;&amp;gt;, Yi Cai (@YeeTsai)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:yee.tsai@gmail.com&quot;&gt;yee.tsai@gmail.com&lt;/a&gt;&amp;gt;, Ryan Chow&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:ryanchow@solv.finance&quot;&gt;ryanchow@solv.finance&lt;/a&gt;&amp;gt;, Zhongxin Wu&amp;nbsp;(&lt;a href=&quot;https://github.com/Nerverwind&quot;&gt;@Nerverwind&lt;/a&gt;), AlvisDu&amp;nbsp;(&lt;a href=&quot;https://github.com/AlvisDu&quot;&gt;@AlvisDu&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3529&quot;&gt;3529&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Reduction in refunds&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Martin Swende&amp;nbsp;(&lt;a href=&quot;https://github.com/holiman&quot;&gt;@holiman&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3541&quot;&gt;3541&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Reject new contract code starting with the 0xEF byte&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;), Andrei Maiboroda&amp;nbsp;(&lt;a href=&quot;https://github.com/gumb0&quot;&gt;@gumb0&lt;/a&gt;), Alexey Akhunov&amp;nbsp;(&lt;a href=&quot;https://github.com/AlexeyAkhunov&quot;&gt;@AlexeyAkhunov&lt;/a&gt;), Christian Reitwiessner&amp;nbsp;(&lt;a href=&quot;https://github.com/chriseth&quot;&gt;@chriseth&lt;/a&gt;), Martin Swende&amp;nbsp;(&lt;a href=&quot;https://github.com/holiman&quot;&gt;@holiman&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3554&quot;&gt;3554&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Difficulty Bomb Delay to December 2021&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;James Hancock&amp;nbsp;(&lt;a href=&quot;https://github.com/madeoftin&quot;&gt;@madeoftin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3607&quot;&gt;3607&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Reject transactions from senders with deployed code&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Dankrad Feist&amp;nbsp;(&lt;a href=&quot;https://github.com/dankrad&quot;&gt;@dankrad&lt;/a&gt;), Dmitry Khovratovich&amp;nbsp;(&lt;a href=&quot;https://github.com/khovratovich&quot;&gt;@khovratovich&lt;/a&gt;), Marius van der Wijden&amp;nbsp;(&lt;a href=&quot;https://github.com/MariusVanDerWijden&quot;&gt;@MariusVanDerWijden&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3643&quot;&gt;3643&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;T-REX - Token for Regulated EXchanges&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Joachim Lebrun&amp;nbsp;(&lt;a href=&quot;https://github.com/Joachim-Lebrun&quot;&gt;@Joachim-Lebrun&lt;/a&gt;), Tony Malghem&amp;nbsp;(&lt;a href=&quot;https://github.com/TonyMalghem&quot;&gt;@TonyMalghem&lt;/a&gt;), Kevin Thizy&amp;nbsp;(&lt;a href=&quot;https://github.com/Nakasar&quot;&gt;@Nakasar&lt;/a&gt;), Luc Falempin&amp;nbsp;(&lt;a href=&quot;https://github.com/lfalempin&quot;&gt;@lfalempin&lt;/a&gt;), Adam Boudjemaa&amp;nbsp;(&lt;a href=&quot;https://github.com/Aboudjem&quot;&gt;@Aboudjem&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3651&quot;&gt;3651&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Warm COINBASE&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;William Morriss&amp;nbsp;(&lt;a href=&quot;https://github.com/wjmelements&quot;&gt;@wjmelements&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3668&quot;&gt;3668&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;CCIP Read—Secure offchain data retrieval&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Johnson&amp;nbsp;(&lt;a href=&quot;https://github.com/arachnid&quot;&gt;@arachnid&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3675&quot;&gt;3675&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Upgrade consensus to Proof-of-Stake&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Mikhail Kalinin&amp;nbsp;(&lt;a href=&quot;https://github.com/mkalinin&quot;&gt;@mkalinin&lt;/a&gt;), Danny Ryan&amp;nbsp;(&lt;a href=&quot;https://github.com/djrtwo&quot;&gt;@djrtwo&lt;/a&gt;), Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3855&quot;&gt;3855&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;PUSH0 instruction&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Hugo De la cruz&amp;nbsp;(&lt;a href=&quot;https://github.com/hugo-dc&quot;&gt;@hugo-dc&lt;/a&gt;), Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3860&quot;&gt;3860&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Limit and meter initcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Martin Holst Swende&amp;nbsp;(&lt;a href=&quot;https://github.com/holiman&quot;&gt;@holiman&lt;/a&gt;), Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;), Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Andrei Maiboroda&amp;nbsp;(&lt;a href=&quot;https://github.com/gumb0&quot;&gt;@gumb0&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4345&quot;&gt;4345&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Difficulty Bomb Delay to June 2022&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Tim Beiko&amp;nbsp;(&lt;a href=&quot;https://github.com/timbeiko&quot;&gt;@timbeiko&lt;/a&gt;), James Hancock&amp;nbsp;(&lt;a href=&quot;https://github.com/MadeOfTin&quot;&gt;@MadeOfTin&lt;/a&gt;), Thomas Jay Rush&amp;nbsp;(&lt;a href=&quot;https://github.com/tjayrush&quot;&gt;@tjayrush&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4361&quot;&gt;4361&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Sign-In with Ethereum&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Wayne Chang&amp;nbsp;(&lt;a href=&quot;https://github.com/wyc&quot;&gt;@wyc&lt;/a&gt;), Gregory Rocco&amp;nbsp;(&lt;a href=&quot;https://github.com/obstropolos&quot;&gt;@obstropolos&lt;/a&gt;), Brantly Millegan&amp;nbsp;(&lt;a href=&quot;https://github.com/brantlymillegan&quot;&gt;@brantlymillegan&lt;/a&gt;), Nick Johnson&amp;nbsp;(&lt;a href=&quot;https://github.com/Arachnid&quot;&gt;@Arachnid&lt;/a&gt;), Oliver Terbu&amp;nbsp;(&lt;a href=&quot;https://github.com/awoie&quot;&gt;@awoie&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4399&quot;&gt;4399&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Supplant DIFFICULTY opcode with PREVRANDAO&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Mikhail Kalinin&amp;nbsp;(&lt;a href=&quot;https://github.com/mkalinin&quot;&gt;@mkalinin&lt;/a&gt;), Danny Ryan&amp;nbsp;(&lt;a href=&quot;https://github.com/djrtwo&quot;&gt;@djrtwo&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4400&quot;&gt;4400&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EIP-721 Consumable Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Daniel Ivanov&amp;nbsp;(&lt;a href=&quot;https://github.com/Daniel-K-Ivanov&quot;&gt;@Daniel-K-Ivanov&lt;/a&gt;), George Spasov&amp;nbsp;(&lt;a href=&quot;https://github.com/Perseverance&quot;&gt;@Perseverance&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4519&quot;&gt;4519&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Non-Fungible Tokens Tied to Physical Assets&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Javier Arcenegui&amp;nbsp;(&lt;a href=&quot;https://github.com/Hardblock-IMSE-CNM&quot;&gt;@Hardblock-IMSE-CNM&lt;/a&gt;), Rosario Arjona&amp;nbsp;(&lt;a href=&quot;https://github.com/RosarioArjona&quot;&gt;@RosarioArjona&lt;/a&gt;), Roberto Román&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:roman@imse-cnm.csic.es&quot;&gt;roman@imse-cnm.csic.es&lt;/a&gt;&amp;gt;, Iluminada Baturone&amp;nbsp;(&lt;a href=&quot;https://github.com/lumi2018&quot;&gt;@lumi2018&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4626&quot;&gt;4626&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Tokenized Vaults&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Joey Santoro&amp;nbsp;(&lt;a href=&quot;https://github.com/joeysantoro&quot;&gt;@joeysantoro&lt;/a&gt;), t11s&amp;nbsp;(&lt;a href=&quot;https://github.com/transmissions11&quot;&gt;@transmissions11&lt;/a&gt;), Jet Jadeja&amp;nbsp;(&lt;a href=&quot;https://github.com/JetJadeja&quot;&gt;@JetJadeja&lt;/a&gt;), Alberto Cuesta Cañada&amp;nbsp;(&lt;a href=&quot;https://github.com/alcueca&quot;&gt;@alcueca&lt;/a&gt;), Señor Doggo&amp;nbsp;(&lt;a href=&quot;https://github.com/fubuloubu&quot;&gt;@fubuloubu&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4736&quot;&gt;4736&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Consensus Layer Withdrawal Protection&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Benjamin Chodroff&amp;nbsp;(&lt;a href=&quot;https://github.com/benjaminchodroff&quot;&gt;@benjaminchodroff&lt;/a&gt;), Jim McDonald&amp;nbsp;(&lt;a href=&quot;https://github.com/mcdee&quot;&gt;@mcdee&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4788&quot;&gt;4788&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Beacon block root in the EVM&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Stokes&amp;nbsp;(&lt;a href=&quot;https://github.com/ralexstokes&quot;&gt;@ralexstokes&lt;/a&gt;), Ansgar Dietrichs&amp;nbsp;(&lt;a href=&quot;https://github.com/adietrichs&quot;&gt;@adietrichs&lt;/a&gt;), Danny Ryan&amp;nbsp;(&lt;a href=&quot;https://github.com/djrtwo&quot;&gt;@djrtwo&lt;/a&gt;), Martin Holst Swende&amp;nbsp;(&lt;a href=&quot;https://github.com/holiman&quot;&gt;@holiman&lt;/a&gt;), lightclient&amp;nbsp;(&lt;a href=&quot;https://github.com/lightclient&quot;&gt;@lightclient&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4804&quot;&gt;4804&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Web3 URL to EVM Call Message Translation&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Qi Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/qizhou&quot;&gt;@qizhou&lt;/a&gt;), Chao Pi&amp;nbsp;(&lt;a href=&quot;https://github.com/pichaoqkc&quot;&gt;@pichaoqkc&lt;/a&gt;), Sam Wilson&amp;nbsp;(&lt;a href=&quot;https://github.com/SamWilsn&quot;&gt;@SamWilsn&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4834&quot;&gt;4834&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hierarchical Domains&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gavin John&amp;nbsp;(&lt;a href=&quot;https://github.com/Pandapip1&quot;&gt;@Pandapip1&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4844&quot;&gt;4844&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Shard Blob Transactions&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Dankrad Feist&amp;nbsp;(&lt;a href=&quot;https://github.com/dankrad&quot;&gt;@dankrad&lt;/a&gt;), Diederik Loerakker&amp;nbsp;(&lt;a href=&quot;https://github.com/protolambda&quot;&gt;@protolambda&lt;/a&gt;), George Kadianakis&amp;nbsp;(&lt;a href=&quot;https://github.com/asn-d6&quot;&gt;@asn-d6&lt;/a&gt;), Matt Garnett&amp;nbsp;(&lt;a href=&quot;https://github.com/lightclient&quot;&gt;@lightclient&lt;/a&gt;), Mofi Taiwo&amp;nbsp;(&lt;a href=&quot;https://github.com/Inphi&quot;&gt;@Inphi&lt;/a&gt;), Ansgar Dietrichs&amp;nbsp;(&lt;a href=&quot;https://github.com/adietrichs&quot;&gt;@adietrichs&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4881&quot;&gt;4881&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Deposit Contract Snapshot Interface&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Mark Mackey&amp;nbsp;(&lt;a href=&quot;https://github.com/ethDreamer&quot;&gt;@ethDreamer&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4895&quot;&gt;4895&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Beacon chain push withdrawals as operations&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Stokes&amp;nbsp;(&lt;a href=&quot;https://github.com/ralexstokes&quot;&gt;@ralexstokes&lt;/a&gt;), Danny Ryan&amp;nbsp;(&lt;a href=&quot;https://github.com/djrtwo&quot;&gt;@djrtwo&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4906&quot;&gt;4906&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EIP-721 Metadata Update Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Anders&amp;nbsp;(&lt;a href=&quot;https://github.com/0xanders&quot;&gt;@0xanders&lt;/a&gt;), Lance&amp;nbsp;(&lt;a href=&quot;https://github.com/LanceSnow&quot;&gt;@LanceSnow&lt;/a&gt;), Shrug&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:shrug@emojidao.org&quot;&gt;shrug@emojidao.org&lt;/a&gt;&amp;gt;, Nathan&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:nathan.gang@gemini.com&quot;&gt;nathan.gang@gemini.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4907&quot;&gt;4907&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Rental NFT, an Extension of EIP-721&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Anders&amp;nbsp;(&lt;a href=&quot;https://github.com/0xanders&quot;&gt;@0xanders&lt;/a&gt;), Lance&amp;nbsp;(&lt;a href=&quot;https://github.com/LanceSnow&quot;&gt;@LanceSnow&lt;/a&gt;), Shrug&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:shrug@emojidao.org&quot;&gt;shrug@emojidao.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4910&quot;&gt;4910&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Royalty Bearing NFTs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Andreas Freund&amp;nbsp;(&lt;a href=&quot;https://github.com/Therecanbeonlyone1969&quot;&gt;@Therecanbeonlyone1969&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4938&quot;&gt;4938&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;eth/67 - Removal of GetNodeData&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Marius van der Wijden&amp;nbsp;(&lt;a href=&quot;https://github.com/MariusVanDerWijden&quot;&gt;@MariusVanDerWijden&lt;/a&gt;), Felix Lange&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:fjl@ethereum.org&quot;&gt;fjl@ethereum.org&lt;/a&gt;&amp;gt;, Gary Rong&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:garyrong@ethereum.org&quot;&gt;garyrong@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4955&quot;&gt;4955&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Vendor Metadata Extension for NFTs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ignacio Mazzara&amp;nbsp;(&lt;a href=&quot;https://github.com/nachomazzara&quot;&gt;@nachomazzara&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5006&quot;&gt;5006&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Rental NFT, NFT User Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Lance&amp;nbsp;(&lt;a href=&quot;https://github.com/LanceSnow&quot;&gt;@LanceSnow&lt;/a&gt;), Anders&amp;nbsp;(&lt;a href=&quot;https://github.com/0xanders&quot;&gt;@0xanders&lt;/a&gt;), Shrug&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:shrug@emojidao.org&quot;&gt;shrug@emojidao.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5007&quot;&gt;5007&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Time NFT, ERC-721 Time Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Anders&amp;nbsp;(&lt;a href=&quot;https://github.com/0xanders&quot;&gt;@0xanders&lt;/a&gt;), Lance&amp;nbsp;(&lt;a href=&quot;https://github.com/LanceSnow&quot;&gt;@LanceSnow&lt;/a&gt;), Shrug&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:shrug@emojidao.org&quot;&gt;shrug@emojidao.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5023&quot;&gt;5023&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Shareable Non-Fungible Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jarno Marttila&amp;nbsp;(&lt;a href=&quot;https://github.com/yaruno&quot;&gt;@yaruno&lt;/a&gt;), Martin Moravek&amp;nbsp;(&lt;a href=&quot;https://github.com/mmartinmo&quot;&gt;@mmartinmo&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5133&quot;&gt;5133&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Delaying Difficulty Bomb to mid-September 2022&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Tomasz Kajetan Stanczak&amp;nbsp;(&lt;a href=&quot;https://github.com/tkstanczak&quot;&gt;@tkstanczak&lt;/a&gt;), Eric Marti Haynes&amp;nbsp;(&lt;a href=&quot;https://github.com/ericmartihaynes&quot;&gt;@ericmartihaynes&lt;/a&gt;), Josh Klopfenstein&amp;nbsp;(&lt;a href=&quot;https://github.com/joshklop&quot;&gt;@joshklop&lt;/a&gt;), Abhimanyu Nag&amp;nbsp;(&lt;a href=&quot;https://github.com/AbhiMan1601&quot;&gt;@AbhiMan1601&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5169&quot;&gt;5169&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Client Script URI for Token Contracts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;James&amp;nbsp;(&lt;a href=&quot;https://github.com/JamesSmartCell&quot;&gt;@JamesSmartCell&lt;/a&gt;), Weiwu&amp;nbsp;(&lt;a href=&quot;https://github.com/weiwu-zhang&quot;&gt;@weiwu-zhang&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5192&quot;&gt;5192&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Minimal Soulbound NFTs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Tim Daubenschütz&amp;nbsp;(&lt;a href=&quot;https://github.com/TimDaub&quot;&gt;@TimDaub&lt;/a&gt;), Anders&amp;nbsp;(&lt;a href=&quot;https://github.com/0xanders&quot;&gt;@0xanders&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5202&quot;&gt;5202&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Blueprint contract format&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Charles Cooper&amp;nbsp;(&lt;a href=&quot;https://github.com/charles-cooper&quot;&gt;@charles-cooper&lt;/a&gt;), Edward Amor&amp;nbsp;(&lt;a href=&quot;https://github.com/skellet0r&quot;&gt;@skellet0r&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5219&quot;&gt;5219&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Contract Resource Requests&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gavin John&amp;nbsp;(&lt;a href=&quot;https://github.com/Pandapip1&quot;&gt;@Pandapip1&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5267&quot;&gt;5267&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Retrieval of EIP-712 domain&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Francisco Giordano&amp;nbsp;(&lt;a href=&quot;https://github.com/frangio&quot;&gt;@frangio&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5313&quot;&gt;5313&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Light Contract Ownership&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;William Entriken&amp;nbsp;(&lt;a href=&quot;https://github.com/fulldecent&quot;&gt;@fulldecent&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5375&quot;&gt;5375&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;NFT Author Information and Consent&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Samuele Marro&amp;nbsp;(&lt;a href=&quot;https://github.com/samuelemarro&quot;&gt;@samuelemarro&lt;/a&gt;), Luca Donno&amp;nbsp;(&lt;a href=&quot;https://github.com/lucadonnoh&quot;&gt;@lucadonnoh&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5380&quot;&gt;5380&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-721 Entitlement Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gavin John&amp;nbsp;(&lt;a href=&quot;https://github.com/Pandapip1&quot;&gt;@Pandapip1&lt;/a&gt;), Tim Daubenschütz&amp;nbsp;(&lt;a href=&quot;https://github.com/TimDaub&quot;&gt;@TimDaub&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5484&quot;&gt;5484&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Consensual Soulbound Tokens&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Buzz Cai&amp;nbsp;(&lt;a href=&quot;https://github.com/buzzcai&quot;&gt;@buzzcai&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5489&quot;&gt;5489&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;NFT Hyperlink Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;IronMan_CH&amp;nbsp;(&lt;a href=&quot;https://github.com/coderfengyun&quot;&gt;@coderfengyun&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5507&quot;&gt;5507&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Refundable Tokens&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;elie222&amp;nbsp;(&lt;a href=&quot;https://github.com/elie222&quot;&gt;@elie222&lt;/a&gt;), Gavin John&amp;nbsp;(&lt;a href=&quot;https://github.com/Pandapip1&quot;&gt;@Pandapip1&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5521&quot;&gt;5521&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Referable NFT&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Saber Yu&amp;nbsp;(&lt;a href=&quot;https://github.com/OniReimu&quot;&gt;@OniReimu&lt;/a&gt;), Qin Wang&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:qin.wang@data61.csiro.au&quot;&gt;qin.wang@data61.csiro.au&lt;/a&gt;&amp;gt;, Shange Fu&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:shange.fu@monash.edu&quot;&gt;shange.fu@monash.edu&lt;/a&gt;&amp;gt;, Yilin Sai&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:yilin.sai@data61.csiro.au&quot;&gt;yilin.sai@data61.csiro.au&lt;/a&gt;&amp;gt;, Shiping Chen&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:shiping.chen@data61.csiro.au&quot;&gt;shiping.chen@data61.csiro.au&lt;/a&gt;&amp;gt;, Sherry Xu&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:xiwei.xu@data61.csiro.au&quot;&gt;xiwei.xu@data61.csiro.au&lt;/a&gt;&amp;gt;, Jiangshan Yu&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jiangshan.yu@monash.edu&quot;&gt;jiangshan.yu@monash.edu&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5528&quot;&gt;5528&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Refundable Fungible Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;StartfundInc&amp;nbsp;(&lt;a href=&quot;https://github.com/StartfundInc&quot;&gt;@StartfundInc&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5564&quot;&gt;5564&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Stealth Addresses&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Toni Wahrstätter&amp;nbsp;(&lt;a href=&quot;https://github.com/nerolation&quot;&gt;@nerolation&lt;/a&gt;), Matt Solomon&amp;nbsp;(&lt;a href=&quot;https://github.com/mds1&quot;&gt;@mds1&lt;/a&gt;), Ben DiFrancesco&amp;nbsp;(&lt;a href=&quot;https://github.com/apbendi&quot;&gt;@apbendi&lt;/a&gt;), Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5570&quot;&gt;5570&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Digital Receipt Non-Fungible Tokens&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Sean Darcy&amp;nbsp;(&lt;a href=&quot;https://github.com/darcys22&quot;&gt;@darcys22&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5585&quot;&gt;5585&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-721 NFT Authorization&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Veega Labs&amp;nbsp;(&lt;a href=&quot;https://github.com/VeegaLabsOfficial&quot;&gt;@VeegaLabsOfficial&lt;/a&gt;), Sean NG&amp;nbsp;(&lt;a href=&quot;https://github.com/ngveega&quot;&gt;@ngveega&lt;/a&gt;), Tiger&amp;nbsp;(&lt;a href=&quot;https://github.com/tiger0x&quot;&gt;@tiger0x&lt;/a&gt;), Fred&amp;nbsp;(&lt;a href=&quot;https://github.com/apan826&quot;&gt;@apan826&lt;/a&gt;), Fov Cao&amp;nbsp;(&lt;a href=&quot;https://github.com/fovcao&quot;&gt;@fovcao&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5606&quot;&gt;5606&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Multiverse NFTs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gaurang Torvekar&amp;nbsp;(&lt;a href=&quot;https://github.com/gaurangtorvekar&quot;&gt;@gaurangtorvekar&lt;/a&gt;), Khemraj Adhawade&amp;nbsp;(&lt;a href=&quot;https://github.com/akhemraj&quot;&gt;@akhemraj&lt;/a&gt;), Nikhil Asrani&amp;nbsp;(&lt;a href=&quot;https://github.com/nikhilasrani&quot;&gt;@nikhilasrani&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5615&quot;&gt;5615&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-1155 Supply Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gavin John&amp;nbsp;(&lt;a href=&quot;https://github.com/Pandapip1&quot;&gt;@Pandapip1&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5625&quot;&gt;5625&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;NFT Metadata JSON Schema dStorage Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gavin Fu&amp;nbsp;(&lt;a href=&quot;https://github.com/gavfu&quot;&gt;@gavfu&lt;/a&gt;), Leo Wang&amp;nbsp;(&lt;a href=&quot;https://github.com/wanglie1986&quot;&gt;@wanglie1986&lt;/a&gt;), Bova Chen&amp;nbsp;(&lt;a href=&quot;https://github.com/appoipp&quot;&gt;@appoipp&lt;/a&gt;), Guang Han&amp;nbsp;(&lt;a href=&quot;https://github.com/pangwa&quot;&gt;@pangwa&lt;/a&gt;), Brian Wu&amp;nbsp;(&lt;a href=&quot;https://github.com/wuhaixian1984&quot;&gt;@wuhaixian1984&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5646&quot;&gt;5646&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Token State Fingerprint&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Naim Ashhab&amp;nbsp;(&lt;a href=&quot;https://github.com/ashhanai&quot;&gt;@ashhanai&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5656&quot;&gt;5656&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;MCOPY - Memory copying instruction&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Paul Dworzanski&amp;nbsp;(&lt;a href=&quot;https://github.com/poemm&quot;&gt;@poemm&lt;/a&gt;), Jared Wasinger&amp;nbsp;(&lt;a href=&quot;https://github.com/jwasinger&quot;&gt;@jwasinger&lt;/a&gt;), Casey Detrio&amp;nbsp;(&lt;a href=&quot;https://github.com/cdetrio&quot;&gt;@cdetrio&lt;/a&gt;), Pawel Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;), Charles Cooper&amp;nbsp;(&lt;a href=&quot;https://github.com/charles-cooper&quot;&gt;@charles-cooper&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5679&quot;&gt;5679&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Token Minting and Burning&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Zainan Victor Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/xinbenlv&quot;&gt;@xinbenlv&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5725&quot;&gt;5725&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Transferable Vesting NFT&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Apeguru&amp;nbsp;(&lt;a href=&quot;https://github.com/Apegurus&quot;&gt;@Apegurus&lt;/a&gt;), Marco De Vries&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:marco@paladinsec.co&quot;&gt;marco@paladinsec.co&lt;/a&gt;&amp;gt;, Mario&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:mario@paladinsec.co&quot;&gt;mario@paladinsec.co&lt;/a&gt;&amp;gt;, DeFiFoFum&amp;nbsp;(&lt;a href=&quot;https://github.com/DeFiFoFum&quot;&gt;@DeFiFoFum&lt;/a&gt;), Elliott Green&amp;nbsp;(&lt;a href=&quot;https://github.com/elliott-green&quot;&gt;@elliott-green&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5732&quot;&gt;5732&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Commit Interface&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Zainan Victor Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/xinbenlv&quot;&gt;@xinbenlv&lt;/a&gt;), Matt Stam&amp;nbsp;(&lt;a href=&quot;https://github.com/mattstam&quot;&gt;@mattstam&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5749&quot;&gt;5749&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;The &amp;apos;window.evmproviders&amp;apos; object&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Kosala Hemachandra&amp;nbsp;(&lt;a href=&quot;https://github.com/kvhnuke&quot;&gt;@kvhnuke&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5750&quot;&gt;5750&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;General Extensibility for Method Behaviors&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Zainan Victor Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/xinbenlv&quot;&gt;@xinbenlv&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5757&quot;&gt;5757&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Process for Approving External Resources&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Sam Wilson&amp;nbsp;(&lt;a href=&quot;https://github.com/SamWilsn&quot;&gt;@SamWilsn&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5773&quot;&gt;5773&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Context-Dependent Multi-Asset Tokens&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Bruno Škvorc&amp;nbsp;(&lt;a href=&quot;https://github.com/Swader&quot;&gt;@Swader&lt;/a&gt;), Cicada&amp;nbsp;(&lt;a href=&quot;https://github.com/CicadaNCR&quot;&gt;@CicadaNCR&lt;/a&gt;), Steven Pineda&amp;nbsp;(&lt;a href=&quot;https://github.com/steven2308&quot;&gt;@steven2308&lt;/a&gt;), Stevan Bogosavljevic&amp;nbsp;(&lt;a href=&quot;https://github.com/stevyhacker&quot;&gt;@stevyhacker&lt;/a&gt;), Jan Turk&amp;nbsp;(&lt;a href=&quot;https://github.com/ThunderDeliverer&quot;&gt;@ThunderDeliverer&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5792&quot;&gt;5792&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Wallet Call API&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Moody Salem&amp;nbsp;(&lt;a href=&quot;https://github.com/moodysalem&quot;&gt;@moodysalem&lt;/a&gt;), Lukas Rosario&amp;nbsp;(&lt;a href=&quot;https://github.com/lukasrosario&quot;&gt;@lukasrosario&lt;/a&gt;), Wilson Cusack&amp;nbsp;(&lt;a href=&quot;https://github.com/wilsoncusack&quot;&gt;@wilsoncusack&lt;/a&gt;), Dror Tirosh&amp;nbsp;(&lt;a href=&quot;https://github.com/drortirosh&quot;&gt;@drortirosh&lt;/a&gt;), Jake Moxey&amp;nbsp;(&lt;a href=&quot;https://github.com/jxom&quot;&gt;@jxom&lt;/a&gt;), Derek Rein&amp;nbsp;(&lt;a href=&quot;https://github.com/arein&quot;&gt;@arein&lt;/a&gt;), Alex Forshtat&amp;nbsp;(&lt;a href=&quot;https://github.com/forshtat&quot;&gt;@forshtat&lt;/a&gt;), Sam Wilson (@SamWilsn)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:sam@binarycake.ca&quot;&gt;sam@binarycake.ca&lt;/a&gt;&amp;gt;, Borislav Itskov&amp;nbsp;(&lt;a href=&quot;https://github.com/Oxbobby&quot;&gt;@Oxbobby&lt;/a&gt;), Joao Tavares&amp;nbsp;(&lt;a href=&quot;https://github.com/cryptotavares&quot;&gt;@cryptotavares&lt;/a&gt;), Adam Fuller&amp;nbsp;(&lt;a href=&quot;https://github.com/azf20&quot;&gt;@azf20&lt;/a&gt;), Philip Liao&amp;nbsp;(&lt;a href=&quot;https://github.com/phil-ociraptor&quot;&gt;@phil-ociraptor&lt;/a&gt;), bumblefudge&amp;nbsp;(&lt;a href=&quot;https://github.com/bumblefudge&quot;&gt;@bumblefudge&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5793&quot;&gt;5793&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;eth/68 - Add tx type to tx announcement&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Marius van der Wijden&amp;nbsp;(&lt;a href=&quot;https://github.com/MariusVanDerWijden&quot;&gt;@MariusVanDerWijden&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6049&quot;&gt;6049&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Deprecate SELFDESTRUCT&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;William Entriken&amp;nbsp;(&lt;a href=&quot;https://github.com/fulldecent&quot;&gt;@fulldecent&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6059&quot;&gt;6059&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Parent-Governed Nestable Non-Fungible Tokens&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Bruno Škvorc&amp;nbsp;(&lt;a href=&quot;https://github.com/Swader&quot;&gt;@Swader&lt;/a&gt;), Cicada&amp;nbsp;(&lt;a href=&quot;https://github.com/CicadaNCR&quot;&gt;@CicadaNCR&lt;/a&gt;), Steven Pineda&amp;nbsp;(&lt;a href=&quot;https://github.com/steven2308&quot;&gt;@steven2308&lt;/a&gt;), Stevan Bogosavljevic&amp;nbsp;(&lt;a href=&quot;https://github.com/stevyhacker&quot;&gt;@stevyhacker&lt;/a&gt;), Jan Turk&amp;nbsp;(&lt;a href=&quot;https://github.com/ThunderDeliverer&quot;&gt;@ThunderDeliverer&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6066&quot;&gt;6066&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Signature Validation Method for NFTs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jack Boyuan Xu&amp;nbsp;(&lt;a href=&quot;https://github.com/boyuanx&quot;&gt;@boyuanx&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6093&quot;&gt;6093&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Custom errors for commonly-used tokens&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ernesto García&amp;nbsp;(&lt;a href=&quot;https://github.com/ernestognw&quot;&gt;@ernestognw&lt;/a&gt;), Francisco Giordano&amp;nbsp;(&lt;a href=&quot;https://github.com/frangio&quot;&gt;@frangio&lt;/a&gt;), Hadrien Croubois&amp;nbsp;(&lt;a href=&quot;https://github.com/Amxx&quot;&gt;@Amxx&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6105&quot;&gt;6105&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;No Intermediary NFT Trading Protocol&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;5660-eth&amp;nbsp;(&lt;a href=&quot;https://github.com/5660-eth&quot;&gt;@5660-eth&lt;/a&gt;), Silvere Heraudeau&amp;nbsp;(&lt;a href=&quot;https://github.com/lambdalf-dev&quot;&gt;@lambdalf-dev&lt;/a&gt;), Martin McConnell&amp;nbsp;(&lt;a href=&quot;https://github.com/offgridgecko&quot;&gt;@offgridgecko&lt;/a&gt;), Abu&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:team10kuni@gmail.com&quot;&gt;team10kuni@gmail.com&lt;/a&gt;&amp;gt;,  Wizard Wang&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6110&quot;&gt;6110&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Supply validator deposits on chain&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Mikhail Kalinin&amp;nbsp;(&lt;a href=&quot;https://github.com/mkalinin&quot;&gt;@mkalinin&lt;/a&gt;), Danny Ryan&amp;nbsp;(&lt;a href=&quot;https://github.com/djrtwo&quot;&gt;@djrtwo&lt;/a&gt;), Peter Davies&amp;nbsp;(&lt;a href=&quot;https://github.com/petertdavies&quot;&gt;@petertdavies&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6122&quot;&gt;6122&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Forkid checks based on timestamps&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Marius van der Wijden&amp;nbsp;(&lt;a href=&quot;https://github.com/MariusVanDerWijden&quot;&gt;@MariusVanDerWijden&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6147&quot;&gt;6147&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Guard of NFT/SBT, an Extension of ERC-721&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;5660-eth&amp;nbsp;(&lt;a href=&quot;https://github.com/5660-eth&quot;&gt;@5660-eth&lt;/a&gt;),  Wizard Wang&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6150&quot;&gt;6150&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hierarchical NFTs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Keegan Lee&amp;nbsp;(&lt;a href=&quot;https://github.com/keeganlee&quot;&gt;@keeganlee&lt;/a&gt;), msfew&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:msfew@hyperoracle.io&quot;&gt;msfew@hyperoracle.io&lt;/a&gt;&amp;gt;, Kartin&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:kartin@hyperoracle.io&quot;&gt;kartin@hyperoracle.io&lt;/a&gt;&amp;gt;, qizhou&amp;nbsp;(&lt;a href=&quot;https://github.com/qizhou&quot;&gt;@qizhou&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6220&quot;&gt;6220&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Composable NFTs utilizing Equippable Parts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Bruno Škvorc&amp;nbsp;(&lt;a href=&quot;https://github.com/Swader&quot;&gt;@Swader&lt;/a&gt;), Cicada&amp;nbsp;(&lt;a href=&quot;https://github.com/CicadaNCR&quot;&gt;@CicadaNCR&lt;/a&gt;), Steven Pineda&amp;nbsp;(&lt;a href=&quot;https://github.com/steven2308&quot;&gt;@steven2308&lt;/a&gt;), Stevan Bogosavljevic&amp;nbsp;(&lt;a href=&quot;https://github.com/stevyhacker&quot;&gt;@stevyhacker&lt;/a&gt;), Jan Turk&amp;nbsp;(&lt;a href=&quot;https://github.com/ThunderDeliverer&quot;&gt;@ThunderDeliverer&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6239&quot;&gt;6239&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Semantic Soulbound Tokens&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jessica Chang&amp;nbsp;(&lt;a href=&quot;https://github.com/JessicaChg&quot;&gt;@JessicaChg&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6381&quot;&gt;6381&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Public Non-Fungible Token Emote Repository&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Bruno Škvorc&amp;nbsp;(&lt;a href=&quot;https://github.com/Swader&quot;&gt;@Swader&lt;/a&gt;), Steven Pineda&amp;nbsp;(&lt;a href=&quot;https://github.com/steven2308&quot;&gt;@steven2308&lt;/a&gt;), Stevan Bogosavljevic&amp;nbsp;(&lt;a href=&quot;https://github.com/stevyhacker&quot;&gt;@stevyhacker&lt;/a&gt;), Jan Turk&amp;nbsp;(&lt;a href=&quot;https://github.com/ThunderDeliverer&quot;&gt;@ThunderDeliverer&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6454&quot;&gt;6454&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Minimal Transferable NFT detection interface&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Bruno Škvorc&amp;nbsp;(&lt;a href=&quot;https://github.com/Swader&quot;&gt;@Swader&lt;/a&gt;), Francesco Sullo&amp;nbsp;(&lt;a href=&quot;https://github.com/sullof&quot;&gt;@sullof&lt;/a&gt;), Steven Pineda&amp;nbsp;(&lt;a href=&quot;https://github.com/steven2308&quot;&gt;@steven2308&lt;/a&gt;), Stevan Bogosavljevic&amp;nbsp;(&lt;a href=&quot;https://github.com/stevyhacker&quot;&gt;@stevyhacker&lt;/a&gt;), Jan Turk&amp;nbsp;(&lt;a href=&quot;https://github.com/ThunderDeliverer&quot;&gt;@ThunderDeliverer&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6492&quot;&gt;6492&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Signature Validation for Predeploy Contracts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ivo Georgiev&amp;nbsp;(&lt;a href=&quot;https://github.com/Ivshti&quot;&gt;@Ivshti&lt;/a&gt;), Agustin Aguilar&amp;nbsp;(&lt;a href=&quot;https://github.com/Agusx1211&quot;&gt;@Agusx1211&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6538&quot;&gt;6538&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Stealth Meta-Address Registry&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Matt Solomon&amp;nbsp;(&lt;a href=&quot;https://github.com/mds1&quot;&gt;@mds1&lt;/a&gt;), Toni Wahrstätter&amp;nbsp;(&lt;a href=&quot;https://github.com/nerolation&quot;&gt;@nerolation&lt;/a&gt;), Ben DiFrancesco&amp;nbsp;(&lt;a href=&quot;https://github.com/apbendi&quot;&gt;@apbendi&lt;/a&gt;), Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Gary Ghayrat&amp;nbsp;(&lt;a href=&quot;https://github.com/garyghayrat&quot;&gt;@garyghayrat&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6672&quot;&gt;6672&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Multi-redeemable NFTs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;RE:DREAMER Lab&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:dev@redreamer.io&quot;&gt;dev@redreamer.io&lt;/a&gt;&amp;gt;, Archie Chang (@ArchieR7)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:archie@redreamer.io&quot;&gt;archie@redreamer.io&lt;/a&gt;&amp;gt;, Kai Yu (@chihkaiyu)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:kai@redreamer.io&quot;&gt;kai@redreamer.io&lt;/a&gt;&amp;gt;, Yonathan Randyanto (@Randyanto)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:randy@redreamer.io&quot;&gt;randy@redreamer.io&lt;/a&gt;&amp;gt;, Boyu Chu (@chuboyu)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:boyu@redreamer.io&quot;&gt;boyu@redreamer.io&lt;/a&gt;&amp;gt;, Boxi Li (@boxi79)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:boxi@redreamer.io&quot;&gt;boxi@redreamer.io&lt;/a&gt;&amp;gt;, Jason Cheng (@JasonCheng0729)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jason@redreamer.io&quot;&gt;jason@redreamer.io&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6780&quot;&gt;6780&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;SELFDESTRUCT only in same transaction&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Guillaume Ballet&amp;nbsp;(&lt;a href=&quot;https://github.com/gballet&quot;&gt;@gballet&lt;/a&gt;), Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Dankrad Feist&amp;nbsp;(&lt;a href=&quot;https://github.com/dankrad&quot;&gt;@dankrad&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6808&quot;&gt;6808&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Fungible Key Bound Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Mihai Onila&amp;nbsp;(&lt;a href=&quot;https://github.com/MihaiORO&quot;&gt;@MihaiORO&lt;/a&gt;), Nick Zeman&amp;nbsp;(&lt;a href=&quot;https://github.com/NickZCZ&quot;&gt;@NickZCZ&lt;/a&gt;), Narcis Cotaie&amp;nbsp;(&lt;a href=&quot;https://github.com/NarcisCRO&quot;&gt;@NarcisCRO&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6809&quot;&gt;6809&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Non-Fungible Key Bound Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Mihai Onila&amp;nbsp;(&lt;a href=&quot;https://github.com/MihaiORO&quot;&gt;@MihaiORO&lt;/a&gt;), Nick Zeman&amp;nbsp;(&lt;a href=&quot;https://github.com/NickZCZ&quot;&gt;@NickZCZ&lt;/a&gt;), Narcis Cotaie&amp;nbsp;(&lt;a href=&quot;https://github.com/NarcisCRO&quot;&gt;@NarcisCRO&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6909&quot;&gt;6909&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Minimal Multi-Token Interface&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;JT Riley&amp;nbsp;(&lt;a href=&quot;https://github.com/jtriley2p&quot;&gt;@jtriley2p&lt;/a&gt;), Dillon&amp;nbsp;(&lt;a href=&quot;https://github.com/d1ll0n&quot;&gt;@d1ll0n&lt;/a&gt;), Sara&amp;nbsp;(&lt;a href=&quot;https://github.com/snreynolds&quot;&gt;@snreynolds&lt;/a&gt;), Vectorized&amp;nbsp;(&lt;a href=&quot;https://github.com/Vectorized&quot;&gt;@Vectorized&lt;/a&gt;), Neodaoist&amp;nbsp;(&lt;a href=&quot;https://github.com/neodaoist&quot;&gt;@neodaoist&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6916&quot;&gt;6916&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Automatically Reset Testnet&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Mário Havel&amp;nbsp;(&lt;a href=&quot;https://github.com/taxmeifyoucan&quot;&gt;@taxmeifyoucan&lt;/a&gt;), pk910&amp;nbsp;(&lt;a href=&quot;https://github.com/pk910&quot;&gt;@pk910&lt;/a&gt;), Rémy Roy&amp;nbsp;(&lt;a href=&quot;https://github.com/remyroy&quot;&gt;@remyroy&lt;/a&gt;), Holly Atkinson&amp;nbsp;(&lt;a href=&quot;https://github.com/atkinsonholly&quot;&gt;@atkinsonholly&lt;/a&gt;), Tereza Burianova&amp;nbsp;(&lt;a href=&quot;https://github.com/T-ess&quot;&gt;@T-ess&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6953&quot;&gt;6953&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Network Upgrade Activation Triggers&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Tim Beiko&amp;nbsp;(&lt;a href=&quot;https://github.com/timbeiko&quot;&gt;@timbeiko&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6963&quot;&gt;6963&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Multi Injected Provider Discovery&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Pedro Gomes&amp;nbsp;(&lt;a href=&quot;https://github.com/pedrouid&quot;&gt;@pedrouid&lt;/a&gt;), Kosala Hemachandra&amp;nbsp;(&lt;a href=&quot;https://github.com/kvhnuke&quot;&gt;@kvhnuke&lt;/a&gt;), Richard Moore&amp;nbsp;(&lt;a href=&quot;https://github.com/ricmoo&quot;&gt;@ricmoo&lt;/a&gt;), Gregory Markou&amp;nbsp;(&lt;a href=&quot;https://github.com/GregTheGreek&quot;&gt;@GregTheGreek&lt;/a&gt;), Kyle Den Hartog&amp;nbsp;(&lt;a href=&quot;https://github.com/kdenhartog&quot;&gt;@kdenhartog&lt;/a&gt;), Glitch&amp;nbsp;(&lt;a href=&quot;https://github.com/glitch-txs&quot;&gt;@glitch-txs&lt;/a&gt;), Jake Moxey&amp;nbsp;(&lt;a href=&quot;https://github.com/jxom&quot;&gt;@jxom&lt;/a&gt;), Pierre Bertet&amp;nbsp;(&lt;a href=&quot;https://github.com/bpierre&quot;&gt;@bpierre&lt;/a&gt;), Darryl Yeo&amp;nbsp;(&lt;a href=&quot;https://github.com/darrylyeo&quot;&gt;@darrylyeo&lt;/a&gt;), Yaroslav Sergievsky&amp;nbsp;(&lt;a href=&quot;https://github.com/everdimension&quot;&gt;@everdimension&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6982&quot;&gt;6982&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Efficient Default Lockable Tokens&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Francesco Sullo&amp;nbsp;(&lt;a href=&quot;https://github.com/sullof&quot;&gt;@sullof&lt;/a&gt;), Alexe Spataru&amp;nbsp;(&lt;a href=&quot;https://github.com/urataps&quot;&gt;@urataps&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7002&quot;&gt;7002&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Execution layer triggerable withdrawals&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Danny Ryan&amp;nbsp;(&lt;a href=&quot;https://github.com/djrtwo&quot;&gt;@djrtwo&lt;/a&gt;), Mikhail Kalinin&amp;nbsp;(&lt;a href=&quot;https://github.com/mkalinin&quot;&gt;@mkalinin&lt;/a&gt;), Ansgar Dietrichs&amp;nbsp;(&lt;a href=&quot;https://github.com/adietrichs&quot;&gt;@adietrichs&lt;/a&gt;), Hsiao-Wei Wang&amp;nbsp;(&lt;a href=&quot;https://github.com/hwwhww&quot;&gt;@hwwhww&lt;/a&gt;), lightclient&amp;nbsp;(&lt;a href=&quot;https://github.com/lightclient&quot;&gt;@lightclient&lt;/a&gt;), Felix Lange&amp;nbsp;(&lt;a href=&quot;https://github.com/fjl&quot;&gt;@fjl&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7007&quot;&gt;7007&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Verifiable AI-Generated Content Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Cathie So&amp;nbsp;(&lt;a href=&quot;https://github.com/socathie&quot;&gt;@socathie&lt;/a&gt;), Xiaohang Yu&amp;nbsp;(&lt;a href=&quot;https://github.com/xhyumiracle&quot;&gt;@xhyumiracle&lt;/a&gt;), Conway&amp;nbsp;(&lt;a href=&quot;https://github.com/0x1cc&quot;&gt;@0x1cc&lt;/a&gt;), Lee Ting Ting&amp;nbsp;(&lt;a href=&quot;https://github.com/tina1998612&quot;&gt;@tina1998612&lt;/a&gt;), Kartin&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:kartin@hyperoracle.io&quot;&gt;kartin@hyperoracle.io&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7044&quot;&gt;7044&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Perpetually Valid Signed Voluntary Exits&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Lion&amp;nbsp;(&lt;a href=&quot;https://github.com/dapplion&quot;&gt;@dapplion&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7045&quot;&gt;7045&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Increase max attestation inclusion slot&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Danny Ryan&amp;nbsp;(&lt;a href=&quot;https://github.com/djrtwo&quot;&gt;@djrtwo&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7053&quot;&gt;7053&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Interoperable Digital Media Indexing&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Bofu Chen&amp;nbsp;(&lt;a href=&quot;https://github.com/bafu&quot;&gt;@bafu&lt;/a&gt;), Tammy Yang&amp;nbsp;(&lt;a href=&quot;https://github.com/tammyyang&quot;&gt;@tammyyang&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7066&quot;&gt;7066&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Lockable Extension for ERC-721&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Piyush Chittara&amp;nbsp;(&lt;a href=&quot;https://github.com/piyush-chittara&quot;&gt;@piyush-chittara&lt;/a&gt;), StreamNFT&amp;nbsp;(&lt;a href=&quot;https://github.com/streamnft-tech&quot;&gt;@streamnft-tech&lt;/a&gt;), Srinivas Joshi&amp;nbsp;(&lt;a href=&quot;https://github.com/SrinivasJoshi&quot;&gt;@SrinivasJoshi&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7092&quot;&gt;7092&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Financial Bonds&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Samuel Gwlanold Edoumou&amp;nbsp;(&lt;a href=&quot;https://github.com/Edoumou&quot;&gt;@Edoumou&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7160&quot;&gt;7160&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-721 Multi-Metadata Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;0xG&amp;nbsp;(&lt;a href=&quot;https://github.com/0xGh&quot;&gt;@0xGh&lt;/a&gt;), Marco Peyfuss&amp;nbsp;(&lt;a href=&quot;https://github.com/mpeyfuss&quot;&gt;@mpeyfuss&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7201&quot;&gt;7201&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Namespaced Storage Layout&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Francisco Giordano&amp;nbsp;(&lt;a href=&quot;https://github.com/frangio&quot;&gt;@frangio&lt;/a&gt;), Hadrien Croubois&amp;nbsp;(&lt;a href=&quot;https://github.com/Amxx&quot;&gt;@Amxx&lt;/a&gt;), Ernesto García&amp;nbsp;(&lt;a href=&quot;https://github.com/ernestognw&quot;&gt;@ernestognw&lt;/a&gt;), Eric Lau&amp;nbsp;(&lt;a href=&quot;https://github.com/ericglau&quot;&gt;@ericglau&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7208&quot;&gt;7208&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;On-Chain Data Containers&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Rachid Ajaja&amp;nbsp;(&lt;a href=&quot;https://github.com/abrajaja&quot;&gt;@abrajaja&lt;/a&gt;), Matthijs de Vries&amp;nbsp;(&lt;a href=&quot;https://github.com/sudomati&quot;&gt;@sudomati&lt;/a&gt;), Alexandros Athanasopulos&amp;nbsp;(&lt;a href=&quot;https://github.com/Xaleee&quot;&gt;@Xaleee&lt;/a&gt;), Pavel Rubin&amp;nbsp;(&lt;a href=&quot;https://github.com/pash7ka&quot;&gt;@pash7ka&lt;/a&gt;), Sebastian Galimberti Romano&amp;nbsp;(&lt;a href=&quot;https://github.com/galimba&quot;&gt;@galimba&lt;/a&gt;), Daniel Berbesi&amp;nbsp;(&lt;a href=&quot;https://github.com/berbex&quot;&gt;@berbex&lt;/a&gt;), Apostolos Mavropoulos&amp;nbsp;(&lt;a href=&quot;https://github.com/ApostolosMavro&quot;&gt;@ApostolosMavro&lt;/a&gt;), Barbara Marcano&amp;nbsp;(&lt;a href=&quot;https://github.com/Barbara-Marcano&quot;&gt;@Barbara-Marcano&lt;/a&gt;), Daniel Ortega&amp;nbsp;(&lt;a href=&quot;https://github.com/xdaniortega&quot;&gt;@xdaniortega&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7231&quot;&gt;7231&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Identity-aggregated NFT&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Chloe Gu&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:chloe@carv.io&quot;&gt;chloe@carv.io&lt;/a&gt;&amp;gt;, Navid X.&amp;nbsp;(&lt;a href=&quot;https://github.com/xuxinlai2002&quot;&gt;@xuxinlai2002&lt;/a&gt;), Victor Yu&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:victor@carv.io&quot;&gt;victor@carv.io&lt;/a&gt;&amp;gt;,  Archer H.&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7251&quot;&gt;7251&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Increase the MAX_EFFECTIVE_BALANCE&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;mike&amp;nbsp;(&lt;a href=&quot;https://github.com/michaelneuder&quot;&gt;@michaelneuder&lt;/a&gt;), Francesco&amp;nbsp;(&lt;a href=&quot;https://github.com/fradamt&quot;&gt;@fradamt&lt;/a&gt;), dapplion&amp;nbsp;(&lt;a href=&quot;https://github.com/dapplion&quot;&gt;@dapplion&lt;/a&gt;), Mikhail&amp;nbsp;(&lt;a href=&quot;https://github.com/mkalinin&quot;&gt;@mkalinin&lt;/a&gt;), Aditya&amp;nbsp;(&lt;a href=&quot;https://github.com/adiasg&quot;&gt;@adiasg&lt;/a&gt;), Justin&amp;nbsp;(&lt;a href=&quot;https://github.com/justindrake&quot;&gt;@justindrake&lt;/a&gt;), lightclient&amp;nbsp;(&lt;a href=&quot;https://github.com/lightclient&quot;&gt;@lightclient&lt;/a&gt;), Felix Lange&amp;nbsp;(&lt;a href=&quot;https://github.com/fjl&quot;&gt;@fjl&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7291&quot;&gt;7291&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Purpose bound money&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Orchid-Dev&amp;nbsp;(&lt;a href=&quot;https://github.com/proj-orchid-straitsx&quot;&gt;@proj-orchid-straitsx&lt;/a&gt;), Victor Liew&amp;nbsp;(&lt;a href=&quot;https://github.com/alcedo&quot;&gt;@alcedo&lt;/a&gt;), Wong Tse Jian&amp;nbsp;(&lt;a href=&quot;https://github.com/wongtsejian&quot;&gt;@wongtsejian&lt;/a&gt;), Jacob Shan&amp;nbsp;(&lt;a href=&quot;https://github.com/Jacobshan429&quot;&gt;@Jacobshan429&lt;/a&gt;), Chin Sin Ong&amp;nbsp;(&lt;a href=&quot;https://github.com/chinsinong&quot;&gt;@chinsinong&lt;/a&gt;), Praveen Kumar&amp;nbsp;(&lt;a href=&quot;https://github.com/veenkumarr&quot;&gt;@veenkumarr&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7329&quot;&gt;7329&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC/EIP Repository split&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Lightclient&amp;nbsp;(&lt;a href=&quot;https://github.com/lightclient&quot;&gt;@lightclient&lt;/a&gt;), Danno Ferrin&amp;nbsp;(&lt;a href=&quot;https://github.com/shemnon&quot;&gt;@shemnon&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7401&quot;&gt;7401&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Parent-Governed Non-Fungible Tokens Nesting&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Bruno Škvorc&amp;nbsp;(&lt;a href=&quot;https://github.com/Swader&quot;&gt;@Swader&lt;/a&gt;), Cicada&amp;nbsp;(&lt;a href=&quot;https://github.com/CicadaNCR&quot;&gt;@CicadaNCR&lt;/a&gt;), Steven Pineda&amp;nbsp;(&lt;a href=&quot;https://github.com/steven2308&quot;&gt;@steven2308&lt;/a&gt;), Stevan Bogosavljevic&amp;nbsp;(&lt;a href=&quot;https://github.com/stevyhacker&quot;&gt;@stevyhacker&lt;/a&gt;), Jan Turk&amp;nbsp;(&lt;a href=&quot;https://github.com/ThunderDeliverer&quot;&gt;@ThunderDeliverer&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7409&quot;&gt;7409&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Public Non-Fungible Tokens Emote Repository&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Bruno Škvorc&amp;nbsp;(&lt;a href=&quot;https://github.com/Swader&quot;&gt;@Swader&lt;/a&gt;), Steven Pineda&amp;nbsp;(&lt;a href=&quot;https://github.com/steven2308&quot;&gt;@steven2308&lt;/a&gt;), Stevan Bogosavljevic&amp;nbsp;(&lt;a href=&quot;https://github.com/stevyhacker&quot;&gt;@stevyhacker&lt;/a&gt;), Jan Turk&amp;nbsp;(&lt;a href=&quot;https://github.com/ThunderDeliverer&quot;&gt;@ThunderDeliverer&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7432&quot;&gt;7432&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Non-Fungible Token Roles&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ernani São Thiago&amp;nbsp;(&lt;a href=&quot;https://github.com/ernanirst&quot;&gt;@ernanirst&lt;/a&gt;), Daniel Lima&amp;nbsp;(&lt;a href=&quot;https://github.com/karacurt&quot;&gt;@karacurt&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7439&quot;&gt;7439&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Prevent ticket touting&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;LeadBest Consulting Group&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:service@getoken.io&quot;&gt;service@getoken.io&lt;/a&gt;&amp;gt;, Sandy Sung&amp;nbsp;(&lt;a href=&quot;https://github.com/sandy-sung-lb&quot;&gt;@sandy-sung-lb&lt;/a&gt;), Mars Peng&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:mars.peng@getoken.io&quot;&gt;mars.peng@getoken.io&lt;/a&gt;&amp;gt;, Taien Wang&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:taien.wang@getoken.io&quot;&gt;taien.wang@getoken.io&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7514&quot;&gt;7514&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Add Max Epoch Churn Limit&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;dapplion&amp;nbsp;(&lt;a href=&quot;https://github.com/dapplion&quot;&gt;@dapplion&lt;/a&gt;), Tim Beiko&amp;nbsp;(&lt;a href=&quot;https://github.com/timbeiko&quot;&gt;@timbeiko&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7516&quot;&gt;7516&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;BLOBBASEFEE instruction&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Carl Beekhuizen&amp;nbsp;(&lt;a href=&quot;https://github.com/carlbeek&quot;&gt;@carlbeek&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7528&quot;&gt;7528&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ETH (Native Asset) Address Convention&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Joey Santoro&amp;nbsp;(&lt;a href=&quot;https://github.com/joeysantoro&quot;&gt;@joeysantoro&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7535&quot;&gt;7535&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Native Asset ERC-4626 Tokenized Vault&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Joey Santoro&amp;nbsp;(&lt;a href=&quot;https://github.com/joeysantoro&quot;&gt;@joeysantoro&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7540&quot;&gt;7540&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Asynchronous ERC-4626 Tokenized Vaults&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jeroen Offerijns&amp;nbsp;(&lt;a href=&quot;https://github.com/hieronx&quot;&gt;@hieronx&lt;/a&gt;), Alina Sinelnikova&amp;nbsp;(&lt;a href=&quot;https://github.com/ilinzweilin&quot;&gt;@ilinzweilin&lt;/a&gt;), Vikram Arun&amp;nbsp;(&lt;a href=&quot;https://github.com/vikramarun&quot;&gt;@vikramarun&lt;/a&gt;), Joey Santoro&amp;nbsp;(&lt;a href=&quot;https://github.com/joeysantoro&quot;&gt;@joeysantoro&lt;/a&gt;), Farhaan Ali&amp;nbsp;(&lt;a href=&quot;https://github.com/0xfarhaan&quot;&gt;@0xfarhaan&lt;/a&gt;), João Martins&amp;nbsp;(&lt;a href=&quot;https://github.com/0xTimepunk&quot;&gt;@0xTimepunk&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7549&quot;&gt;7549&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Move committee index outside Attestation&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;dapplion&amp;nbsp;(&lt;a href=&quot;https://github.com/dapplion&quot;&gt;@dapplion&lt;/a&gt;), Mikhail Kalinin&amp;nbsp;(&lt;a href=&quot;https://github.com/mkalinin&quot;&gt;@mkalinin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7568&quot;&gt;7568&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hardfork Meta Backfill - Berlin to Shapella&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Tim Beiko&amp;nbsp;(&lt;a href=&quot;https://github.com/timbeiko&quot;&gt;@timbeiko&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7569&quot;&gt;7569&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hardfork Meta - Dencun&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Tim Beiko&amp;nbsp;(&lt;a href=&quot;https://github.com/timbeiko&quot;&gt;@timbeiko&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7575&quot;&gt;7575&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Multi-Asset ERC-4626 Vaults&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jeroen Offerijns&amp;nbsp;(&lt;a href=&quot;https://github.com/hieronx&quot;&gt;@hieronx&lt;/a&gt;), Alina Sinelnikova&amp;nbsp;(&lt;a href=&quot;https://github.com/ilinzweilin&quot;&gt;@ilinzweilin&lt;/a&gt;), Vikram Arun&amp;nbsp;(&lt;a href=&quot;https://github.com/vikramarun&quot;&gt;@vikramarun&lt;/a&gt;), Joey Santoro&amp;nbsp;(&lt;a href=&quot;https://github.com/joeysantoro&quot;&gt;@joeysantoro&lt;/a&gt;), Farhaan Ali&amp;nbsp;(&lt;a href=&quot;https://github.com/0xfarhaan&quot;&gt;@0xfarhaan&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7578&quot;&gt;7578&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Physical Asset Redemption&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Lee Vidor&amp;nbsp;(&lt;a href=&quot;https://github.com/V1d0r&quot;&gt;@V1d0r&lt;/a&gt;), David Tan&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:david@emergentx.org&quot;&gt;david@emergentx.org&lt;/a&gt;&amp;gt;, Lee Smith&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:lee@emergentx.org&quot;&gt;lee@emergentx.org&lt;/a&gt;&amp;gt;, Gabriel Stoica&amp;nbsp;(&lt;a href=&quot;https://github.com/gabrielstoica&quot;&gt;@gabrielstoica&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7587&quot;&gt;7587&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Reserve Precompile Address Range for RIPs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Carl Beekhuizen&amp;nbsp;(&lt;a href=&quot;https://github.com/carlbeek&quot;&gt;@carlbeek&lt;/a&gt;), Ansgar Dietrichs&amp;nbsp;(&lt;a href=&quot;https://github.com/adietrichs&quot;&gt;@adietrichs&lt;/a&gt;), Danny Ryan&amp;nbsp;(&lt;a href=&quot;https://github.com/djrtwo&quot;&gt;@djrtwo&lt;/a&gt;), Tim Beiko&amp;nbsp;(&lt;a href=&quot;https://github.com/timbeiko&quot;&gt;@timbeiko&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7588&quot;&gt;7588&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Blob Transactions Metadata JSON Schema&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gavin Fu&amp;nbsp;(&lt;a href=&quot;https://github.com/gavfu&quot;&gt;@gavfu&lt;/a&gt;), Leo Wang&amp;nbsp;(&lt;a href=&quot;https://github.com/wanglie1986&quot;&gt;@wanglie1986&lt;/a&gt;), Bova Chen&amp;nbsp;(&lt;a href=&quot;https://github.com/appoipp&quot;&gt;@appoipp&lt;/a&gt;), Aiden X&amp;nbsp;(&lt;a href=&quot;https://github.com/4ever9&quot;&gt;@4ever9&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7594&quot;&gt;7594&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;PeerDAS - Peer Data Availability Sampling&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Danny Ryan&amp;nbsp;(&lt;a href=&quot;https://github.com/djrtwo&quot;&gt;@djrtwo&lt;/a&gt;), Dankrad Feist&amp;nbsp;(&lt;a href=&quot;https://github.com/dankrad&quot;&gt;@dankrad&lt;/a&gt;), Francesco D&apos;Amato&amp;nbsp;(&lt;a href=&quot;https://github.com/fradamt&quot;&gt;@fradamt&lt;/a&gt;), Hsiao-Wei Wang&amp;nbsp;(&lt;a href=&quot;https://github.com/hwwhww&quot;&gt;@hwwhww&lt;/a&gt;), Alex Stokes&amp;nbsp;(&lt;a href=&quot;https://github.com/ralexstokes&quot;&gt;@ralexstokes&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7600&quot;&gt;7600&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hardfork Meta - Pectra&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Tim Beiko&amp;nbsp;(&lt;a href=&quot;https://github.com/timbeiko&quot;&gt;@timbeiko&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7607&quot;&gt;7607&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hardfork Meta - Fusaka&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Tim Beiko&amp;nbsp;(&lt;a href=&quot;https://github.com/timbeiko&quot;&gt;@timbeiko&lt;/a&gt;), Alex Stokes&amp;nbsp;(&lt;a href=&quot;https://github.com/ralexstokes&quot;&gt;@ralexstokes&lt;/a&gt;), Ansgar Dietrichs&amp;nbsp;(&lt;a href=&quot;https://github.com/adietrichs&quot;&gt;@adietrichs&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7623&quot;&gt;7623&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Increase calldata cost&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Toni Wahrstätter&amp;nbsp;(&lt;a href=&quot;https://github.com/nerolation&quot;&gt;@nerolation&lt;/a&gt;), Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7627&quot;&gt;7627&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Secure Messaging Protocol&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Chen Liaoyuan (@chenly)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:cly@kip.pro&quot;&gt;cly@kip.pro&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7631&quot;&gt;7631&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Dual Nature Token Pair&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;vectorized&amp;nbsp;(&lt;a href=&quot;https://github.com/vectorized&quot;&gt;@vectorized&lt;/a&gt;), Thomas&amp;nbsp;(&lt;a href=&quot;https://github.com/0xth0mas&quot;&gt;@0xth0mas&lt;/a&gt;), Quit&amp;nbsp;(&lt;a href=&quot;https://github.com/quitcrypto&quot;&gt;@quitcrypto&lt;/a&gt;), Michael Amadi&amp;nbsp;(&lt;a href=&quot;https://github.com/AmadiMichael&quot;&gt;@AmadiMichael&lt;/a&gt;), cygaar&amp;nbsp;(&lt;a href=&quot;https://github.com/cygaar&quot;&gt;@cygaar&lt;/a&gt;), Harrison&amp;nbsp;(&lt;a href=&quot;https://github.com/pop-punk&quot;&gt;@pop-punk&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7634&quot;&gt;7634&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Limited Transfer Count NFT&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Qin Wang&amp;nbsp;(&lt;a href=&quot;https://github.com/qinwang-git&quot;&gt;@qinwang-git&lt;/a&gt;), Saber Yu&amp;nbsp;(&lt;a href=&quot;https://github.com/OniReimu&quot;&gt;@OniReimu&lt;/a&gt;), Shiping Chen&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:shiping.chen@data61.csiro.au&quot;&gt;shiping.chen@data61.csiro.au&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7642&quot;&gt;7642&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;eth/69 - history expiry and simpler receipts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Marius van der Wijden&amp;nbsp;(&lt;a href=&quot;https://github.com/MariusVanDerWijden&quot;&gt;@MariusVanDerWijden&lt;/a&gt;), Felix Lange&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:fjl@ethereum.org&quot;&gt;fjl@ethereum.org&lt;/a&gt;&amp;gt;, Ahmad Bitar (@smartprogrammer93)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:smartprogrammer@windowslive.com&quot;&gt;smartprogrammer@windowslive.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7656&quot;&gt;7656&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Generalized Contract-Linked Services&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Francesco Sullo&amp;nbsp;(&lt;a href=&quot;https://github.com/sullof&quot;&gt;@sullof&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7685&quot;&gt;7685&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;General purpose execution layer requests&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;lightclient&amp;nbsp;(&lt;a href=&quot;https://github.com/lightclient&quot;&gt;@lightclient&lt;/a&gt;), Felix Lange&amp;nbsp;(&lt;a href=&quot;https://github.com/fjl&quot;&gt;@fjl&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7691&quot;&gt;7691&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Blob throughput increase&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Parithosh Jayanthi&amp;nbsp;(&lt;a href=&quot;https://github.com/parithosh&quot;&gt;@parithosh&lt;/a&gt;), Toni Wahrstätter&amp;nbsp;(&lt;a href=&quot;https://github.com/nerolation&quot;&gt;@nerolation&lt;/a&gt;), Sam Calder-Mason&amp;nbsp;(&lt;a href=&quot;https://github.com/samcm&quot;&gt;@samcm&lt;/a&gt;), Andrew Davis&amp;nbsp;(&lt;a href=&quot;https://github.com/savid&quot;&gt;@savid&lt;/a&gt;), Ansgar Dietrichs&amp;nbsp;(&lt;a href=&quot;https://github.com/adietrichs&quot;&gt;@adietrichs&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7702&quot;&gt;7702&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Set Code for EOAs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Sam Wilson&amp;nbsp;(&lt;a href=&quot;https://github.com/SamWilsn&quot;&gt;@SamWilsn&lt;/a&gt;), Ansgar Dietrichs&amp;nbsp;(&lt;a href=&quot;https://github.com/adietrichs&quot;&gt;@adietrichs&lt;/a&gt;), lightclient&amp;nbsp;(&lt;a href=&quot;https://github.com/lightclient&quot;&gt;@lightclient&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7734&quot;&gt;7734&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Decentralized Identity Verification (DID)&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Anushka Yadav (@64anushka)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:64anushka@gmail.com&quot;&gt;64anushka@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7743&quot;&gt;7743&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Multi-Owner Non-Fungible Tokens (MO-NFT)&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Cheng Qian (@jamesavechives)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:james.walstonn@gmail.com&quot;&gt;james.walstonn@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7751&quot;&gt;7751&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Wrapping of bubbled up reverts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Daniel Gretzke&amp;nbsp;(&lt;a href=&quot;https://github.com/gretzke&quot;&gt;@gretzke&lt;/a&gt;), Sara Reynolds&amp;nbsp;(&lt;a href=&quot;https://github.com/snreynolds&quot;&gt;@snreynolds&lt;/a&gt;), Alice Henshaw&amp;nbsp;(&lt;a href=&quot;https://github.com/hensha256&quot;&gt;@hensha256&lt;/a&gt;), Marko Veniger&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:marko.veniger@tenderly.co&quot;&gt;marko.veniger@tenderly.co&lt;/a&gt;&amp;gt;, Hadrien Croubois&amp;nbsp;(&lt;a href=&quot;https://github.com/Amxx&quot;&gt;@Amxx&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7786&quot;&gt;7786&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Cross-Chain Messaging Gateway&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Francisco Giordano&amp;nbsp;(&lt;a href=&quot;https://github.com/frangio&quot;&gt;@frangio&lt;/a&gt;), Hadrien Croubois&amp;nbsp;(&lt;a href=&quot;https://github.com/Amxx&quot;&gt;@Amxx&lt;/a&gt;), Ernesto García&amp;nbsp;(&lt;a href=&quot;https://github.com/ernestognw&quot;&gt;@ernestognw&lt;/a&gt;), CJ Cobb&amp;nbsp;(&lt;a href=&quot;https://github.com/cjcobb23&quot;&gt;@cjcobb23&lt;/a&gt;), Sergey Gorbunov&amp;nbsp;(&lt;a href=&quot;https://github.com/sergeynog&quot;&gt;@sergeynog&lt;/a&gt;), joxes&amp;nbsp;(&lt;a href=&quot;https://github.com/Joxess&quot;&gt;@Joxess&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7818&quot;&gt;7818&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Expirable ERC-20&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;sirawt&amp;nbsp;(&lt;a href=&quot;https://github.com/MASDXI&quot;&gt;@MASDXI&lt;/a&gt;), ADISAKBOONMARK&amp;nbsp;(&lt;a href=&quot;https://github.com/ADISAKBOONMARK&quot;&gt;@ADISAKBOONMARK&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7820&quot;&gt;7820&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Access Control Registry&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Shubham Khandelwal&amp;nbsp;(&lt;a href=&quot;https://github.com/shubh-ta&quot;&gt;@shubh-ta&lt;/a&gt;), Anushka Yadav&amp;nbsp;(&lt;a href=&quot;https://github.com/anushka642000&quot;&gt;@anushka642000&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7823&quot;&gt;7823&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Set upper bounds for MODEXP&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Radoslaw Zagorowicz&amp;nbsp;(&lt;a href=&quot;https://github.com/rodiazet&quot;&gt;@rodiazet&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7825&quot;&gt;7825&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Transaction Gas Limit Cap&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Giulio Rebuffo&amp;nbsp;(&lt;a href=&quot;https://github.com/Giulio2002&quot;&gt;@Giulio2002&lt;/a&gt;), Toni Wahrstätter&amp;nbsp;(&lt;a href=&quot;https://github.com/nerolation&quot;&gt;@nerolation&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7837&quot;&gt;7837&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Diffusive Tokens&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Cheng Qian (@jamesavechives)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:james.walstonn@gmail.com&quot;&gt;james.walstonn@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7840&quot;&gt;7840&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Add blob schedule to EL config files&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;lightclient&amp;nbsp;(&lt;a href=&quot;https://github.com/lightclient&quot;&gt;@lightclient&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7857&quot;&gt;7857&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;AI Agents NFT with Private Metadata&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ming Wu&amp;nbsp;(&lt;a href=&quot;https://github.com/sparkmiw&quot;&gt;@sparkmiw&lt;/a&gt;), Jason Zeng&amp;nbsp;(&lt;a href=&quot;https://github.com/zenghbo&quot;&gt;@zenghbo&lt;/a&gt;), Wei Wu&amp;nbsp;(&lt;a href=&quot;https://github.com/Wilbert957&quot;&gt;@Wilbert957&lt;/a&gt;), Michael Heinrich&amp;nbsp;(&lt;a href=&quot;https://github.com/michaelomg&quot;&gt;@michaelomg&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7858&quot;&gt;7858&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Expirable NFTs and SBTs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;sirawt&amp;nbsp;(&lt;a href=&quot;https://github.com/MASDXI&quot;&gt;@MASDXI&lt;/a&gt;), ADISAKBOONMARK&amp;nbsp;(&lt;a href=&quot;https://github.com/ADISAKBOONMARK&quot;&gt;@ADISAKBOONMARK&lt;/a&gt;), parametprame&amp;nbsp;(&lt;a href=&quot;https://github.com/parametprame&quot;&gt;@parametprame&lt;/a&gt;), Nacharoen&amp;nbsp;(&lt;a href=&quot;https://github.com/najaroen&quot;&gt;@najaroen&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7878&quot;&gt;7878&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Bequeathable Contracts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Wamith Mockbill&amp;nbsp;(&lt;a href=&quot;https://github.com/wamith&quot;&gt;@wamith&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7883&quot;&gt;7883&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ModExp Gas Cost Increase&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Marcin Sobczak&amp;nbsp;(&lt;a href=&quot;https://github.com/marcindsobczak&quot;&gt;@marcindsobczak&lt;/a&gt;), Marek Moraczyński&amp;nbsp;(&lt;a href=&quot;https://github.com/MarekM25&quot;&gt;@MarekM25&lt;/a&gt;), Marcos Maceo&amp;nbsp;(&lt;a href=&quot;https://github.com/stdevMac&quot;&gt;@stdevMac&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7892&quot;&gt;7892&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Blob Parameter Only Hardforks&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Mark Mackey&amp;nbsp;(&lt;a href=&quot;https://github.com/ethDreamer&quot;&gt;@ethDreamer&lt;/a&gt;), Raúl Kripalani&amp;nbsp;(&lt;a href=&quot;https://github.com/raulk&quot;&gt;@raulk&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7893&quot;&gt;7893&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;DeFi Protocol Solvency Proof Mechanism&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Sean Luis Guada Rodríguez (@SeanLuis)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:seanluis47@gmail.com&quot;&gt;seanluis47@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7908&quot;&gt;7908&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;HD wallet In Treasury Management&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Xiaoyu Liu (@elizabethxiaoyu)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jiushi.lxy@antgroup.com&quot;&gt;jiushi.lxy@antgroup.com&lt;/a&gt;&amp;gt;, Yuxiang Fu (@tmac4096)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:kunfu.fyx@antgroup.com&quot;&gt;kunfu.fyx@antgroup.com&lt;/a&gt;&amp;gt;, Yanyi Liang&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:eason.lyy@antgroup.com&quot;&gt;eason.lyy@antgroup.com&lt;/a&gt;&amp;gt;, Hao Zou (@BruceZH0915)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:situ.zh@antgroup.com&quot;&gt;situ.zh@antgroup.com&lt;/a&gt;&amp;gt;, Siyuan Zheng (@andrewcoder666)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:zhengsiyuan.zsy@antgroup.com&quot;&gt;zhengsiyuan.zsy@antgroup.com&lt;/a&gt;&amp;gt;, yuanshanhshan (@xunayuan)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:yuanshanshan.yss@antgroup.com&quot;&gt;yuanshanshan.yss@antgroup.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7910&quot;&gt;7910&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;eth_config JSON-RPC Method&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Danno Ferrin&amp;nbsp;(&lt;a href=&quot;https://github.com/shemnon&quot;&gt;@shemnon&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7913&quot;&gt;7913&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Signature Verifiers&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Hadrien Croubois&amp;nbsp;(&lt;a href=&quot;https://github.com/Amxx&quot;&gt;@Amxx&lt;/a&gt;), Ernesto García&amp;nbsp;(&lt;a href=&quot;https://github.com/ernestognw&quot;&gt;@ernestognw&lt;/a&gt;), Francisco Giordano&amp;nbsp;(&lt;a href=&quot;https://github.com/frangio&quot;&gt;@frangio&lt;/a&gt;), Aryeh Greenberg&amp;nbsp;(&lt;a href=&quot;https://github.com/arr00&quot;&gt;@arr00&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7917&quot;&gt;7917&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Deterministic proposer lookahead&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Lin Oshitani (@linoscope)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:lin@nethermind.io&quot;&gt;lin@nethermind.io&lt;/a&gt;&amp;gt;, Justin Drake (@JustinDrake)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:justin@ethereum.org&quot;&gt;justin@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7918&quot;&gt;7918&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Blob base fee bounded by execution cost&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Anders Elowsson&amp;nbsp;(&lt;a href=&quot;https://github.com/anderselowsson&quot;&gt;@anderselowsson&lt;/a&gt;), Ben Adams&amp;nbsp;(&lt;a href=&quot;https://github.com/benaadams&quot;&gt;@benaadams&lt;/a&gt;), Francesco D&apos;Amato&amp;nbsp;(&lt;a href=&quot;https://github.com/fradamt&quot;&gt;@fradamt&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7934&quot;&gt;7934&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;RLP Execution Block Size Limit&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Giulio Rebuffo&amp;nbsp;(&lt;a href=&quot;https://github.com/Giulio2002&quot;&gt;@Giulio2002&lt;/a&gt;), Ben Adams&amp;nbsp;(&lt;a href=&quot;https://github.com/benaadams&quot;&gt;@benaadams&lt;/a&gt;), Storm Slivkoff&amp;nbsp;(&lt;a href=&quot;https://github.com/sslivkoff&quot;&gt;@sslivkoff&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7935&quot;&gt;7935&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Set default gas limit to 60M&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Sophia Gold&amp;nbsp;(&lt;a href=&quot;https://github.com/sophia-gold&quot;&gt;@sophia-gold&lt;/a&gt;), Parithosh Jayanthi&amp;nbsp;(&lt;a href=&quot;https://github.com/parithoshj&quot;&gt;@parithoshj&lt;/a&gt;), Toni Wahrstätter&amp;nbsp;(&lt;a href=&quot;https://github.com/nerolation&quot;&gt;@nerolation&lt;/a&gt;), Carl Beekhuizen&amp;nbsp;(&lt;a href=&quot;https://github.com/CarlBeek&quot;&gt;@CarlBeek&lt;/a&gt;), Ansgar Dietrichs&amp;nbsp;(&lt;a href=&quot;https://github.com/adietrichs&quot;&gt;@adietrichs&lt;/a&gt;), Dankrad Feist&amp;nbsp;(&lt;a href=&quot;https://github.com/dankrad&quot;&gt;@dankrad&lt;/a&gt;), Alex Stokes&amp;nbsp;(&lt;a href=&quot;https://github.com/ralexstokes&quot;&gt;@ralexstokes&lt;/a&gt;), Josh Rudolph&amp;nbsp;(&lt;a href=&quot;https://github.com/jrudolph&quot;&gt;@jrudolph&lt;/a&gt;), Giulio Rebuffo&amp;nbsp;(&lt;a href=&quot;https://github.com/Giulio2002&quot;&gt;@Giulio2002&lt;/a&gt;), Storm Slivkoff&amp;nbsp;(&lt;a href=&quot;https://github.com/sslivkoff&quot;&gt;@sslivkoff&lt;/a&gt;), Kamil Chodoła&amp;nbsp;(&lt;a href=&quot;https://github.com/kamilchodola&quot;&gt;@kamilchodola&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7939&quot;&gt;7939&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Count leading zeros (CLZ) opcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vectorized&amp;nbsp;(&lt;a href=&quot;https://github.com/Vectorized&quot;&gt;@Vectorized&lt;/a&gt;), Georgios Konstantopoulos&amp;nbsp;(&lt;a href=&quot;https://github.com/gakonst&quot;&gt;@gakonst&lt;/a&gt;), Jochem Brouwer&amp;nbsp;(&lt;a href=&quot;https://github.com/jochem-brouwer&quot;&gt;@jochem-brouwer&lt;/a&gt;), Ben Adams&amp;nbsp;(&lt;a href=&quot;https://github.com/benaadams&quot;&gt;@benaadams&lt;/a&gt;), Giulio Rebuffo&amp;nbsp;(&lt;a href=&quot;https://github.com/Giulio2002&quot;&gt;@Giulio2002&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7950&quot;&gt;7950&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Encode chain id with transaction hash&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Lauri Peltonen&amp;nbsp;(&lt;a href=&quot;https://github.com/microbecode&quot;&gt;@microbecode&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7951&quot;&gt;7951&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Precompile for secp256r1 Curve Support&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Carl Beekhuizen&amp;nbsp;(&lt;a href=&quot;https://github.com/carlbeek&quot;&gt;@carlbeek&lt;/a&gt;), Ulaş Erdoğan&amp;nbsp;(&lt;a href=&quot;https://github.com/ulerdogan&quot;&gt;@ulerdogan&lt;/a&gt;), Doğan Alpaslan&amp;nbsp;(&lt;a href=&quot;https://github.com/doganalpaslan&quot;&gt;@doganalpaslan&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7994&quot;&gt;7994&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Purpose-Bound ERC-20 with Conditional Unlock&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Anushka Yadav&amp;nbsp;(&lt;a href=&quot;https://github.com/64anushka&quot;&gt;@64anushka&lt;/a&gt;), Akash Kothawade&amp;nbsp;(&lt;a href=&quot;https://github.com/akash3927&quot;&gt;@akash3927&lt;/a&gt;), Atishek Singh&amp;nbsp;(&lt;a href=&quot;https://github.com/atisheksingh&quot;&gt;@atisheksingh&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8001&quot;&gt;8001&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Agent Coordination Framework&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Kwame Bryan&amp;nbsp;(&lt;a href=&quot;https://github.com/KBryan&quot;&gt;@KBryan&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8034&quot;&gt;8034&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Referable NFT Royalties&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ruiqiang Li (@richard-620)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:richard.620.research@gmail.com&quot;&gt;richard.620.research@gmail.com&lt;/a&gt;&amp;gt;, Qin Wang&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:qin.wang@data61.csiro.au&quot;&gt;qin.wang@data61.csiro.au&lt;/a&gt;&amp;gt;, Shiping Chen&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:shiping.chen@data61.csiro.au&quot;&gt;shiping.chen@data61.csiro.au&lt;/a&gt;&amp;gt;, Saber Yu&amp;nbsp;(&lt;a href=&quot;https://github.com/OniReimu&quot;&gt;@OniReimu&lt;/a&gt;), Brian Yecies&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:byecies@uow.edu.au&quot;&gt;byecies@uow.edu.au&lt;/a&gt;&amp;gt;, John Le&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:johnle@uow.edu.au&quot;&gt;johnle@uow.edu.au&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8042&quot;&gt;8042&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Diamond Storage&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Mudge&amp;nbsp;(&lt;a href=&quot;https://github.com/mudgen&quot;&gt;@mudgen&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8063&quot;&gt;8063&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Groups - Membership Tokens&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Cheng Qian (@jamesavechives)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:contact@deakee.com&quot;&gt;contact@deakee.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8134&quot;&gt;8134&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hardfork Meta - BPO1&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Pooja Ranjan&amp;nbsp;(&lt;a href=&quot;https://github.com/poojaranjan&quot;&gt;@poojaranjan&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8135&quot;&gt;8135&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hardfork Meta - BPO2&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Pooja Ranjan&amp;nbsp;(&lt;a href=&quot;https://github.com/poojaranjan&quot;&gt;@poojaranjan&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
    &lt;/table&gt;
  

  
  
  
    &lt;h2 id=&quot;last-call&quot;&gt;Last Call&lt;/h2&gt;
    &lt;table class=&quot;eiptable&quot;&gt;
      &lt;thead&gt;
        
          &lt;tr&gt;
          &lt;th class=&quot;eipnum&quot;&gt;Number&lt;/th&gt;&lt;th class=&quot;date&quot;&gt;Review ends&lt;/th&gt;&lt;th class=&quot;title&quot;&gt;Title&lt;/th&gt;&lt;th class=&quot;author&quot;&gt;Author&lt;/th&gt;&lt;/tr&gt;
        
      &lt;/thead&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1191&quot;&gt;1191&lt;/a&gt;&lt;/td&gt;
          
            &lt;td class=&quot;date&quot;&gt;2019-11-18&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Add chain id to mixed-case checksum address encoding&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Juliano Rizzo&amp;nbsp;(&lt;a href=&quot;https://github.com/juli&quot;&gt;@juli&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2266&quot;&gt;2266&lt;/a&gt;&lt;/td&gt;
          
            &lt;td class=&quot;date&quot;&gt;2020-12-31&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Atomic Swap-based American Call Option Contract Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Runchao Han&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:runchao.han@monash.edu&quot;&gt;runchao.han@monash.edu&lt;/a&gt;&amp;gt;, Haoyu Lin&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:chris.haoyul@gmail.com&quot;&gt;chris.haoyul@gmail.com&lt;/a&gt;&amp;gt;, Jiangshan Yu&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jiangshan.yu@monash.edu&quot;&gt;jiangshan.yu@monash.edu&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3076&quot;&gt;3076&lt;/a&gt;&lt;/td&gt;
          
            &lt;td class=&quot;date&quot;&gt;2021-11-03&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Slashing Protection Interchange Format&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Michael Sproul&amp;nbsp;(&lt;a href=&quot;https://github.com/michaelsproul&quot;&gt;@michaelsproul&lt;/a&gt;), Sacha Saint-Leger&amp;nbsp;(&lt;a href=&quot;https://github.com/sachayves&quot;&gt;@sachayves&lt;/a&gt;), Danny Ryan&amp;nbsp;(&lt;a href=&quot;https://github.com/djrtwo&quot;&gt;@djrtwo&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3155&quot;&gt;3155&lt;/a&gt;&lt;/td&gt;
          
            &lt;td class=&quot;date&quot;&gt;2025-03-01&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EVM trace specification&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Martin Holst Swende&amp;nbsp;(&lt;a href=&quot;https://github.com/holiman&quot;&gt;@holiman&lt;/a&gt;), Marius van der Wijden&amp;nbsp;(&lt;a href=&quot;https://github.com/MariusVanDerWijden&quot;&gt;@MariusVanDerWijden&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5008&quot;&gt;5008&lt;/a&gt;&lt;/td&gt;
          
            &lt;td class=&quot;date&quot;&gt;2023-08-15&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-721 Nonce Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Anders&amp;nbsp;(&lt;a href=&quot;https://github.com/0xanders&quot;&gt;@0xanders&lt;/a&gt;), Lance&amp;nbsp;(&lt;a href=&quot;https://github.com/LanceSnow&quot;&gt;@LanceSnow&lt;/a&gt;), Shrug&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:shrug@emojidao.org&quot;&gt;shrug@emojidao.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5114&quot;&gt;5114&lt;/a&gt;&lt;/td&gt;
          
            &lt;td class=&quot;date&quot;&gt;2023-09-19&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Soulbound Badge&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Micah Zoltu&amp;nbsp;(&lt;a href=&quot;https://github.com/MicahZoltu&quot;&gt;@MicahZoltu&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5164&quot;&gt;5164&lt;/a&gt;&lt;/td&gt;
          
            &lt;td class=&quot;date&quot;&gt;2023-11-15&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Cross-Chain Execution&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Brendan Asselstine&amp;nbsp;(&lt;a href=&quot;https://github.com/asselstine&quot;&gt;@asselstine&lt;/a&gt;), Pierrick Turelier&amp;nbsp;(&lt;a href=&quot;https://github.com/PierrickGT&quot;&gt;@PierrickGT&lt;/a&gt;), Chris Whinfrey&amp;nbsp;(&lt;a href=&quot;https://github.com/cwhinfrey&quot;&gt;@cwhinfrey&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5216&quot;&gt;5216&lt;/a&gt;&lt;/td&gt;
          
            &lt;td class=&quot;date&quot;&gt;2022-11-12&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-1155 Allowance Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Iván Mañús&amp;nbsp;(&lt;a href=&quot;https://github.com/ivanmmurciaua&quot;&gt;@ivanmmurciaua&lt;/a&gt;), Juan Carlos Cantó&amp;nbsp;(&lt;a href=&quot;https://github.com/EscuelaCryptoES&quot;&gt;@EscuelaCryptoES&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5453&quot;&gt;5453&lt;/a&gt;&lt;/td&gt;
          
            &lt;td class=&quot;date&quot;&gt;2023-09-27&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Endorsement - Permit for Any Functions&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Zainan Victor Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/xinbenlv&quot;&gt;@xinbenlv&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5496&quot;&gt;5496&lt;/a&gt;&lt;/td&gt;
          
            &lt;td class=&quot;date&quot;&gt;2022-11-29&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Multi-privilege Management NFT Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jeremy Z&amp;nbsp;(&lt;a href=&quot;https://github.com/wnft&quot;&gt;@wnft&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6224&quot;&gt;6224&lt;/a&gt;&lt;/td&gt;
          
            &lt;td class=&quot;date&quot;&gt;2025-07-31&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Contracts Dependencies Registry&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Artem Chystiakov&amp;nbsp;(&lt;a href=&quot;https://github.com/arvolear&quot;&gt;@arvolear&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6357&quot;&gt;6357&lt;/a&gt;&lt;/td&gt;
          
            &lt;td class=&quot;date&quot;&gt;2023-11-10&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Single-contract Multi-delegatecall&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gavin John&amp;nbsp;(&lt;a href=&quot;https://github.com/Pandapip1&quot;&gt;@Pandapip1&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7523&quot;&gt;7523&lt;/a&gt;&lt;/td&gt;
          
            &lt;td class=&quot;date&quot;&gt;2024-03-26&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Empty accounts deprecation&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Peter Davies&amp;nbsp;(&lt;a href=&quot;https://github.com/petertdavies&quot;&gt;@petertdavies&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7610&quot;&gt;7610&lt;/a&gt;&lt;/td&gt;
          
            &lt;td class=&quot;date&quot;&gt;2024-11-20&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Revert creation in case of non-empty storage&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gary Rong&amp;nbsp;(&lt;a href=&quot;https://github.com/rjl493456442&quot;&gt;@rjl493456442&lt;/a&gt;), Martin Holst Swende&amp;nbsp;(&lt;a href=&quot;https://github.com/holiman&quot;&gt;@holiman&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7723&quot;&gt;7723&lt;/a&gt;&lt;/td&gt;
          
            &lt;td class=&quot;date&quot;&gt;2025-04-01&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Network Upgrade Inclusion Stages&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Tim Beiko&amp;nbsp;(&lt;a href=&quot;https://github.com/timbeiko&quot;&gt;@timbeiko&lt;/a&gt;), Alex Stokes&amp;nbsp;(&lt;a href=&quot;https://github.com/ralexstokes&quot;&gt;@ralexstokes&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7744&quot;&gt;7744&lt;/a&gt;&lt;/td&gt;
          
            &lt;td class=&quot;date&quot;&gt;2025-07-29&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Code Index&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Tim Pechersky (@peersky)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:t@peersky.xyz&quot;&gt;t@peersky.xyz&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7746&quot;&gt;7746&lt;/a&gt;&lt;/td&gt;
          
            &lt;td class=&quot;date&quot;&gt;2025-07-29&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Composable Security Middleware Hooks&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Tim Pechersky&amp;nbsp;(&lt;a href=&quot;https://github.com/peersky&quot;&gt;@peersky&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7943&quot;&gt;7943&lt;/a&gt;&lt;/td&gt;
          
            &lt;td class=&quot;date&quot;&gt;2026-01-30&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;uRWA - Universal Real World Asset Interface&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Dario Lo Buglio&amp;nbsp;(&lt;a href=&quot;https://github.com/xaler5&quot;&gt;@xaler5&lt;/a&gt;), Tino Martinez Molina&amp;nbsp;(&lt;a href=&quot;https://github.com/tinom9&quot;&gt;@tinom9&lt;/a&gt;), Mihai Colceriu&amp;nbsp;(&lt;a href=&quot;https://github.com/mihaic195&quot;&gt;@mihaic195&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
    &lt;/table&gt;
  

  
  
  
    &lt;h2 id=&quot;review&quot;&gt;Review&lt;/h2&gt;
    &lt;table class=&quot;eiptable&quot;&gt;
      &lt;thead&gt;
        
          &lt;tr&gt;&lt;th class=&quot;eipnum&quot;&gt;Number&lt;/th&gt;&lt;th class=&quot;title&quot;&gt;Title&lt;/th&gt;&lt;th class=&quot;author&quot;&gt;Author&lt;/th&gt;&lt;/tr&gt;
        
      &lt;/thead&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1185&quot;&gt;1185&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Storage of DNS Records in ENS&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jim McDonald&amp;nbsp;(&lt;a href=&quot;https://github.com/mcdee&quot;&gt;@mcdee&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1202&quot;&gt;1202&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Voting Interface&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Zainan Victor Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/xinbenlv&quot;&gt;@xinbenlv&lt;/a&gt;), ERC-1202 Working Group&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:erc1202@googlegroups.com&quot;&gt;erc1202@googlegroups.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2333&quot;&gt;2333&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;BLS12-381 Key Generation&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Carl Beekhuizen (@CarlBeek)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:carl@ethereum.org&quot;&gt;carl@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2334&quot;&gt;2334&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;BLS12-381 Deterministic Account Hierarchy&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Carl Beekhuizen (@CarlBeek)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:carl@ethereum.org&quot;&gt;carl@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2335&quot;&gt;2335&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;BLS12-381 Keystore&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Carl Beekhuizen (@CarlBeek)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:carl@ethereum.org&quot;&gt;carl@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4337&quot;&gt;4337&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Account Abstraction Using Alt Mempool&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Yoav Weiss&amp;nbsp;(&lt;a href=&quot;https://github.com/yoavw&quot;&gt;@yoavw&lt;/a&gt;), Dror Tirosh&amp;nbsp;(&lt;a href=&quot;https://github.com/drortirosh&quot;&gt;@drortirosh&lt;/a&gt;), Shahaf Nacson&amp;nbsp;(&lt;a href=&quot;https://github.com/shahafn&quot;&gt;@shahafn&lt;/a&gt;), Alex Forshtat&amp;nbsp;(&lt;a href=&quot;https://github.com/forshtat&quot;&gt;@forshtat&lt;/a&gt;), Kristof Gazso&amp;nbsp;(&lt;a href=&quot;https://github.com/kristofgazso&quot;&gt;@kristofgazso&lt;/a&gt;), Tjaden Hess&amp;nbsp;(&lt;a href=&quot;https://github.com/tjade273&quot;&gt;@tjade273&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4824&quot;&gt;4824&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Common Interfaces for DAOs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Joshua Tan&amp;nbsp;(&lt;a href=&quot;https://github.com/thelastjosh&quot;&gt;@thelastjosh&lt;/a&gt;), Isaac Patka&amp;nbsp;(&lt;a href=&quot;https://github.com/ipatka&quot;&gt;@ipatka&lt;/a&gt;), Ido Gershtein&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:ido@daostack.io&quot;&gt;ido@daostack.io&lt;/a&gt;&amp;gt;, Eyal Eithcowich&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:eyal@deepdao.io&quot;&gt;eyal@deepdao.io&lt;/a&gt;&amp;gt;, Michael Zargham&amp;nbsp;(&lt;a href=&quot;https://github.com/mzargham&quot;&gt;@mzargham&lt;/a&gt;), Sam Furter&amp;nbsp;(&lt;a href=&quot;https://github.com/nivida&quot;&gt;@nivida&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4973&quot;&gt;4973&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Account-bound Tokens&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Tim Daubenschütz&amp;nbsp;(&lt;a href=&quot;https://github.com/TimDaub&quot;&gt;@TimDaub&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5247&quot;&gt;5247&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Smart Contract Executable Proposal Interface&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Zainan Victor Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/xinbenlv&quot;&gt;@xinbenlv&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5269&quot;&gt;5269&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC Detection and Discovery&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Zainan Victor Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/xinbenlv&quot;&gt;@xinbenlv&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5289&quot;&gt;5289&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Ethereum Notary Interface&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gavin John&amp;nbsp;(&lt;a href=&quot;https://github.com/Pandapip1&quot;&gt;@Pandapip1&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5485&quot;&gt;5485&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Jurisdiction, Accreditation, and Enforcement&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Zainan Victor Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/xinbenlv&quot;&gt;@xinbenlv&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5568&quot;&gt;5568&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Well-Known Format for Required Actions&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gavin John&amp;nbsp;(&lt;a href=&quot;https://github.com/Pandapip1&quot;&gt;@Pandapip1&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5639&quot;&gt;5639&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Delegation Registry&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;foobar&amp;nbsp;(&lt;a href=&quot;https://github.com/0xfoobar&quot;&gt;@0xfoobar&lt;/a&gt;), Wilkins Chung (@wwhchung)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:wilkins@manifold.xyz&quot;&gt;wilkins@manifold.xyz&lt;/a&gt;&amp;gt;, ryley-o&amp;nbsp;(&lt;a href=&quot;https://github.com/ryley-o&quot;&gt;@ryley-o&lt;/a&gt;), Jake Rockland&amp;nbsp;(&lt;a href=&quot;https://github.com/jakerockland&quot;&gt;@jakerockland&lt;/a&gt;), andy8052&amp;nbsp;(&lt;a href=&quot;https://github.com/andy8052&quot;&gt;@andy8052&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5982&quot;&gt;5982&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Role-based Access Control&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Zainan Victor Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/xinbenlv&quot;&gt;@xinbenlv&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6065&quot;&gt;6065&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Real Estate Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex&amp;nbsp;(&lt;a href=&quot;https://github.com/Alex-Klasma&quot;&gt;@Alex-Klasma&lt;/a&gt;), Ben Fusek&amp;nbsp;(&lt;a href=&quot;https://github.com/bfusek&quot;&gt;@bfusek&lt;/a&gt;), Daniel Fallon-Cyr&amp;nbsp;(&lt;a href=&quot;https://github.com/dfalloncyr&quot;&gt;@dfalloncyr&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6120&quot;&gt;6120&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Universal Token Router&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Derion&amp;nbsp;(&lt;a href=&quot;https://github.com/derion-io&quot;&gt;@derion-io&lt;/a&gt;), Zergity&amp;nbsp;(&lt;a href=&quot;https://github.com/Zergity&quot;&gt;@Zergity&lt;/a&gt;), Ngo Quang Anh&amp;nbsp;(&lt;a href=&quot;https://github.com/anhnq82&quot;&gt;@anhnq82&lt;/a&gt;), BerlinP&amp;nbsp;(&lt;a href=&quot;https://github.com/BerlinP&quot;&gt;@BerlinP&lt;/a&gt;), Khanh Pham&amp;nbsp;(&lt;a href=&quot;https://github.com/blackskin18&quot;&gt;@blackskin18&lt;/a&gt;), Hal Blackburn&amp;nbsp;(&lt;a href=&quot;https://github.com/h4l&quot;&gt;@h4l&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6315&quot;&gt;6315&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-2771 Namespaced Account Abstraction&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gavin John&amp;nbsp;(&lt;a href=&quot;https://github.com/Pandapip1&quot;&gt;@Pandapip1&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6358&quot;&gt;6358&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Cross-Chain Token States Synchronization&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Shawn Zheng&amp;nbsp;(&lt;a href=&quot;https://github.com/xiyu1984&quot;&gt;@xiyu1984&lt;/a&gt;), Jason Cheng&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:chengjingxx@gmail.com&quot;&gt;chengjingxx@gmail.com&lt;/a&gt;&amp;gt;, George Huang&amp;nbsp;(&lt;a href=&quot;https://github.com/virgil2019&quot;&gt;@virgil2019&lt;/a&gt;), Kay Lin&amp;nbsp;(&lt;a href=&quot;https://github.com/kay404&quot;&gt;@kay404&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6366&quot;&gt;6366&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Permission Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Chiro&amp;nbsp;(&lt;a href=&quot;https://github.com/chiro-hiro&quot;&gt;@chiro-hiro&lt;/a&gt;), Victor Dusart&amp;nbsp;(&lt;a href=&quot;https://github.com/vdusart&quot;&gt;@vdusart&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6372&quot;&gt;6372&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Contract clock&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Hadrien Croubois&amp;nbsp;(&lt;a href=&quot;https://github.com/Amxx&quot;&gt;@Amxx&lt;/a&gt;), Francisco Giordano&amp;nbsp;(&lt;a href=&quot;https://github.com/frangio&quot;&gt;@frangio&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6551&quot;&gt;6551&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Non-fungible Token Bound Accounts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jayden Windle&amp;nbsp;(&lt;a href=&quot;https://github.com/jaydenwindle&quot;&gt;@jaydenwindle&lt;/a&gt;), Benny Giang&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:bg@futureprimitive.xyz&quot;&gt;bg@futureprimitive.xyz&lt;/a&gt;&amp;gt;,  Steve Jang, Druzy Downs&amp;nbsp;(&lt;a href=&quot;https://github.com/druzydowns&quot;&gt;@druzydowns&lt;/a&gt;), Raymond Huynh&amp;nbsp;(&lt;a href=&quot;https://github.com/huynhr&quot;&gt;@huynhr&lt;/a&gt;), Alanah Lam&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:alanah@futureprimitive.xyz&quot;&gt;alanah@futureprimitive.xyz&lt;/a&gt;&amp;gt;, Wilkins Chung (@wwhchung)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:wilkins@manifold.xyz&quot;&gt;wilkins@manifold.xyz&lt;/a&gt;&amp;gt;, Paul Sullivan (@sullivph)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:paul.sullivan@manifold.xyz&quot;&gt;paul.sullivan@manifold.xyz&lt;/a&gt;&amp;gt;, Auryn Macmillan&amp;nbsp;(&lt;a href=&quot;https://github.com/auryn-macmillan&quot;&gt;@auryn-macmillan&lt;/a&gt;), Jan-Felix Schwarz&amp;nbsp;(&lt;a href=&quot;https://github.com/jfschwarz&quot;&gt;@jfschwarz&lt;/a&gt;), Anton Bukov&amp;nbsp;(&lt;a href=&quot;https://github.com/k06a&quot;&gt;@k06a&lt;/a&gt;), Mikhail Melnik&amp;nbsp;(&lt;a href=&quot;https://github.com/ZumZoom&quot;&gt;@ZumZoom&lt;/a&gt;), Josh Weintraub (@jhweintraub)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jhweintraub@gmail.com&quot;&gt;jhweintraub@gmail.com&lt;/a&gt;&amp;gt;, Rob Montgomery (@RobAnon)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:rob@revest.finance&quot;&gt;rob@revest.finance&lt;/a&gt;&amp;gt;, vectorized&amp;nbsp;(&lt;a href=&quot;https://github.com/vectorized&quot;&gt;@vectorized&lt;/a&gt;), Víctor Martínez&amp;nbsp;(&lt;a href=&quot;https://github.com/vnmrtz&quot;&gt;@vnmrtz&lt;/a&gt;), Adrián Pajares&amp;nbsp;(&lt;a href=&quot;https://github.com/0xadrii&quot;&gt;@0xadrii&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6596&quot;&gt;6596&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Cultural and Historical Asset Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Phillip Pon&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:phillip@artifactlabs.com&quot;&gt;phillip@artifactlabs.com&lt;/a&gt;&amp;gt;, Gary Liu&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:gary@artifactlabs.com&quot;&gt;gary@artifactlabs.com&lt;/a&gt;&amp;gt;, Henry Chan&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:henry@artifactlabs.com&quot;&gt;henry@artifactlabs.com&lt;/a&gt;&amp;gt;, Joey Liu&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:joey@artifactlabs.com&quot;&gt;joey@artifactlabs.com&lt;/a&gt;&amp;gt;, Lauren Ho&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:lauren@artifactlabs.com&quot;&gt;lauren@artifactlabs.com&lt;/a&gt;&amp;gt;, Jeff Leung&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jeff@artifactlabs.com&quot;&gt;jeff@artifactlabs.com&lt;/a&gt;&amp;gt;, Brian Liang&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:brian@artifactlabs.com&quot;&gt;brian@artifactlabs.com&lt;/a&gt;&amp;gt;, Joyce Li&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:joyce@artifactlabs.com&quot;&gt;joyce@artifactlabs.com&lt;/a&gt;&amp;gt;, Avir Mahtani&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:avir@artifactlabs.com&quot;&gt;avir@artifactlabs.com&lt;/a&gt;&amp;gt;, Antoine Cote&amp;nbsp;(&lt;a href=&quot;https://github.com/acote88&quot;&gt;@acote88&lt;/a&gt;), David Leung&amp;nbsp;(&lt;a href=&quot;https://github.com/dhl&quot;&gt;@dhl&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6617&quot;&gt;6617&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Bit Based Permission&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Chiro&amp;nbsp;(&lt;a href=&quot;https://github.com/chiro-hiro&quot;&gt;@chiro-hiro&lt;/a&gt;), Victor Dusart&amp;nbsp;(&lt;a href=&quot;https://github.com/vdusart&quot;&gt;@vdusart&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6734&quot;&gt;6734&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;L2 Token List&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Kelvin Fichter&amp;nbsp;(&lt;a href=&quot;https://github.com/smartcontracts&quot;&gt;@smartcontracts&lt;/a&gt;), Andreas Freund&amp;nbsp;(&lt;a href=&quot;https://github.com/Therecanbeonlyone1969&quot;&gt;@Therecanbeonlyone1969&lt;/a&gt;), Pavel Sinelnikov&amp;nbsp;(&lt;a href=&quot;https://github.com/psinelnikov&quot;&gt;@psinelnikov&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6735&quot;&gt;6735&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;L2 Aliasing of EVM-based Addresses&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Kelvin Fichter&amp;nbsp;(&lt;a href=&quot;https://github.com/smartcontracts&quot;&gt;@smartcontracts&lt;/a&gt;), Andreas Freund&amp;nbsp;(&lt;a href=&quot;https://github.com/Therecanbeonlyone1969&quot;&gt;@Therecanbeonlyone1969&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6956&quot;&gt;6956&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Asset-bound Non-Fungible Tokens&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Thomas Bergmueller&amp;nbsp;(&lt;a href=&quot;https://github.com/tbergmueller&quot;&gt;@tbergmueller&lt;/a&gt;), Lukas Meyer&amp;nbsp;(&lt;a href=&quot;https://github.com/ibex-technology&quot;&gt;@ibex-technology&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6997&quot;&gt;6997&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-721 with transaction validation step.&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Eduard López i Fina&amp;nbsp;(&lt;a href=&quot;https://github.com/eduardfina&quot;&gt;@eduardfina&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7015&quot;&gt;7015&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;NFT Creator Attribution&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;indreams&amp;nbsp;(&lt;a href=&quot;https://github.com/strollinghome&quot;&gt;@strollinghome&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7144&quot;&gt;7144&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-20 with transaction validation step.&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Eduard López i Fina&amp;nbsp;(&lt;a href=&quot;https://github.com/eduardfina&quot;&gt;@eduardfina&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7246&quot;&gt;7246&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Encumber - Splitting Ownership &amp;amp; Guarantees&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Coburn Berry&amp;nbsp;(&lt;a href=&quot;https://github.com/coburncoburn&quot;&gt;@coburncoburn&lt;/a&gt;), Mykel Pereira&amp;nbsp;(&lt;a href=&quot;https://github.com/mykelp&quot;&gt;@mykelp&lt;/a&gt;), Scott Silver&amp;nbsp;(&lt;a href=&quot;https://github.com/scott-silver&quot;&gt;@scott-silver&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7399&quot;&gt;7399&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;⚡ Flash Loans ⚡&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alberto Cuesta Cañada&amp;nbsp;(&lt;a href=&quot;https://github.com/alcueca&quot;&gt;@alcueca&lt;/a&gt;), Michael Amadi&amp;nbsp;(&lt;a href=&quot;https://github.com/AmadiMichaels&quot;&gt;@AmadiMichaels&lt;/a&gt;), Devtooligan&amp;nbsp;(&lt;a href=&quot;https://github.com/devtooligan&quot;&gt;@devtooligan&lt;/a&gt;), Ultrasecr.eth&amp;nbsp;(&lt;a href=&quot;https://github.com/ultrasecreth&quot;&gt;@ultrasecreth&lt;/a&gt;), Sam Bacha&amp;nbsp;(&lt;a href=&quot;https://github.com/sambacha&quot;&gt;@sambacha&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7417&quot;&gt;7417&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Token Converter&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Dexaran (@Dexaran)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:dexaran@ethereumclassic.org&quot;&gt;dexaran@ethereumclassic.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7495&quot;&gt;7495&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;SSZ ProgressiveContainer&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Etan Kissling&amp;nbsp;(&lt;a href=&quot;https://github.com/etan-status&quot;&gt;@etan-status&lt;/a&gt;), Cayman&amp;nbsp;(&lt;a href=&quot;https://github.com/wemeetagain&quot;&gt;@wemeetagain&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7518&quot;&gt;7518&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Dynamic Compliant Interop Security Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Abhinav (@abhinav-d3v)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:abhinav@zoniqx.com&quot;&gt;abhinav@zoniqx.com&lt;/a&gt;&amp;gt;, Prithvish Baidya (@d4mr)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:pbaidya@zoniqx.com&quot;&gt;pbaidya@zoniqx.com&lt;/a&gt;&amp;gt;, Rajat Kumar (@rajatwasan)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:rwasan@zoniqx.com&quot;&gt;rwasan@zoniqx.com&lt;/a&gt;&amp;gt;, Prasanth Kalangi&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:pkalangi@zoniqx.com&quot;&gt;pkalangi@zoniqx.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7531&quot;&gt;7531&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Staked ERC-721 Ownership Recognition&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Francesco Sullo&amp;nbsp;(&lt;a href=&quot;https://github.com/sullof&quot;&gt;@sullof&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7586&quot;&gt;7586&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Interest Rate Swaps&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Samuel Gwlanold Edoumou&amp;nbsp;(&lt;a href=&quot;https://github.com/Edoumou&quot;&gt;@Edoumou&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7590&quot;&gt;7590&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-20 Holder Extension for NFTs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Steven Pineda&amp;nbsp;(&lt;a href=&quot;https://github.com/steven2308&quot;&gt;@steven2308&lt;/a&gt;), Jan Turk&amp;nbsp;(&lt;a href=&quot;https://github.com/ThunderDeliverer&quot;&gt;@ThunderDeliverer&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7628&quot;&gt;7628&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-721 Ownership Shares Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Chen Liaoyuan (@chenly)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:cly@kip.pro&quot;&gt;cly@kip.pro&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7673&quot;&gt;7673&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Distinguishable base256emoji Addresses&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;William Morriss&amp;nbsp;(&lt;a href=&quot;https://github.com/wjmelements&quot;&gt;@wjmelements&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7674&quot;&gt;7674&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Temporary Approval Extension for ERC-20&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Xenia Shape&amp;nbsp;(&lt;a href=&quot;https://github.com/byshape&quot;&gt;@byshape&lt;/a&gt;), Mikhail Melnik&amp;nbsp;(&lt;a href=&quot;https://github.com/ZumZoom&quot;&gt;@ZumZoom&lt;/a&gt;), Hadrien Croubois&amp;nbsp;(&lt;a href=&quot;https://github.com/Amxx&quot;&gt;@Amxx&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7677&quot;&gt;7677&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Paymaster Web Service Capability&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Lukas Rosario&amp;nbsp;(&lt;a href=&quot;https://github.com/lukasrosario&quot;&gt;@lukasrosario&lt;/a&gt;), Dror Tirosh&amp;nbsp;(&lt;a href=&quot;https://github.com/drortirosh&quot;&gt;@drortirosh&lt;/a&gt;), Wilson Cusack&amp;nbsp;(&lt;a href=&quot;https://github.com/wilsoncusack&quot;&gt;@wilsoncusack&lt;/a&gt;), Kristof Gazso&amp;nbsp;(&lt;a href=&quot;https://github.com/kristofgazso&quot;&gt;@kristofgazso&lt;/a&gt;), Hazim Jumali&amp;nbsp;(&lt;a href=&quot;https://github.com/hazim-j&quot;&gt;@hazim-j&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7688&quot;&gt;7688&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Forward compatible consensus data structures&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Etan Kissling&amp;nbsp;(&lt;a href=&quot;https://github.com/etan-status&quot;&gt;@etan-status&lt;/a&gt;), Cayman&amp;nbsp;(&lt;a href=&quot;https://github.com/wemeetagain&quot;&gt;@wemeetagain&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7750&quot;&gt;7750&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Decentralized Employment System&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;James Savechives (@jamesavechives)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:james.walstonn@gmail.com&quot;&gt;james.walstonn@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7758&quot;&gt;7758&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Transfer With Authorization&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Peter Jihoon Kim&amp;nbsp;(&lt;a href=&quot;https://github.com/petejkim&quot;&gt;@petejkim&lt;/a&gt;), Kevin Britz&amp;nbsp;(&lt;a href=&quot;https://github.com/kbrizzle&quot;&gt;@kbrizzle&lt;/a&gt;), David Knott&amp;nbsp;(&lt;a href=&quot;https://github.com/DavidLKnott&quot;&gt;@DavidLKnott&lt;/a&gt;), Dongri Jin&amp;nbsp;(&lt;a href=&quot;https://github.com/dongri&quot;&gt;@dongri&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7776&quot;&gt;7776&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Transparent Financial Statements&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ignacio Ceaglio (@Nachoxt17)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:ignacioceaglio@gmail.com&quot;&gt;ignacioceaglio@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7777&quot;&gt;7777&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Governance for Human Robot Societies&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;OpenMind, Jan Liphardt&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jan@openmind.org&quot;&gt;jan@openmind.org&lt;/a&gt;&amp;gt;, Shaohong Zhong&amp;nbsp;(&lt;a href=&quot;https://github.com/ShaohongZ&quot;&gt;@ShaohongZ&lt;/a&gt;), Boyuan Chen&amp;nbsp;(&lt;a href=&quot;https://github.com/bchen-dev&quot;&gt;@bchen-dev&lt;/a&gt;), Paige Xu&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:paige@openmind.org&quot;&gt;paige@openmind.org&lt;/a&gt;&amp;gt;, James Ball&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:james.ball@nethermind.io&quot;&gt;james.ball@nethermind.io&lt;/a&gt;&amp;gt;, Thamer Dridi&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:thamer.dridi@nethermind.io&quot;&gt;thamer.dridi@nethermind.io&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7812&quot;&gt;7812&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ZK Identity Registry&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Artem Chystiakov (@arvolear)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:artem@rarilabs.com&quot;&gt;artem@rarilabs.com&lt;/a&gt;&amp;gt;, Oleksandr Kurbatov&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:oleksandr@rarilabs.com&quot;&gt;oleksandr@rarilabs.com&lt;/a&gt;&amp;gt;, Yaroslav Panasenko&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:yaroslav@rarilabs.com&quot;&gt;yaroslav@rarilabs.com&lt;/a&gt;&amp;gt;, Michael Elliot (@michaelelliot)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:mike@zkpassport.id&quot;&gt;mike@zkpassport.id&lt;/a&gt;&amp;gt;, Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7813&quot;&gt;7813&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Store, Table-Based Introspectable Storage&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;alvarius&amp;nbsp;(&lt;a href=&quot;https://github.com/alvrs&quot;&gt;@alvrs&lt;/a&gt;), dk1a&amp;nbsp;(&lt;a href=&quot;https://github.com/dk1a&quot;&gt;@dk1a&lt;/a&gt;), frolic&amp;nbsp;(&lt;a href=&quot;https://github.com/frolic&quot;&gt;@frolic&lt;/a&gt;), ludens&amp;nbsp;(&lt;a href=&quot;https://github.com/ludns&quot;&gt;@ludns&lt;/a&gt;), vdrg&amp;nbsp;(&lt;a href=&quot;https://github.com/vdrg&quot;&gt;@vdrg&lt;/a&gt;), yonada&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:yonada@proton.me&quot;&gt;yonada@proton.me&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7829&quot;&gt;7829&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Data Asset NFT&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Allen Dong&amp;nbsp;(&lt;a href=&quot;https://github.com/Allen2730&quot;&gt;@Allen2730&lt;/a&gt;), Lonika Zhang&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:lonika@memolabs.net&quot;&gt;lonika@memolabs.net&lt;/a&gt;&amp;gt;, Steven He&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:steven@memolabs.net&quot;&gt;steven@memolabs.net&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7832&quot;&gt;7832&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Sustainable collaborative NFT collections&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gustavo Lobo&amp;nbsp;(&lt;a href=&quot;https://github.com/gflobo&quot;&gt;@gflobo&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7834&quot;&gt;7834&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Separate Metadata Section for EOF&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Kaan Uzdogan&amp;nbsp;(&lt;a href=&quot;https://github.com/kuzdogan&quot;&gt;@kuzdogan&lt;/a&gt;), Marco Castignoli&amp;nbsp;(&lt;a href=&quot;https://github.com/marcocastignoli&quot;&gt;@marcocastignoli&lt;/a&gt;), Manuel Wedler&amp;nbsp;(&lt;a href=&quot;https://github.com/manuelwedler&quot;&gt;@manuelwedler&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7866&quot;&gt;7866&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Decentralised User Profiles&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Kumar Anirudha&amp;nbsp;(&lt;a href=&quot;https://github.com/anistark&quot;&gt;@anistark&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7872&quot;&gt;7872&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Max blob flag for local builders&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Francesco D&apos;Amato&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:francesco.damato@ethereum.org&quot;&gt;francesco.damato@ethereum.org&lt;/a&gt;&amp;gt;, Kevaundray Wedderburn&amp;nbsp;(&lt;a href=&quot;https://github.com/kevaundray&quot;&gt;@kevaundray&lt;/a&gt;), Toni Wahrstätter&amp;nbsp;(&lt;a href=&quot;https://github.com/nerolation&quot;&gt;@nerolation&lt;/a&gt;), Alex Stokes&amp;nbsp;(&lt;a href=&quot;https://github.com/ralexstokes&quot;&gt;@ralexstokes&lt;/a&gt;), Ben Adams&amp;nbsp;(&lt;a href=&quot;https://github.com/benaadams&quot;&gt;@benaadams&lt;/a&gt;), Gajinder Singh&amp;nbsp;(&lt;a href=&quot;https://github.com/g11tech&quot;&gt;@g11tech&lt;/a&gt;), Dustin&amp;nbsp;(&lt;a href=&quot;https://github.com/tersec&quot;&gt;@tersec&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7880&quot;&gt;7880&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EOF - EXTCODEADDRESS instruction&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Danno Ferrin&amp;nbsp;(&lt;a href=&quot;https://github.com/shemnon&quot;&gt;@shemnon&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7916&quot;&gt;7916&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;SSZ ProgressiveList&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Zsolt Felföldi&amp;nbsp;(&lt;a href=&quot;https://github.com/zsfelfoldi&quot;&gt;@zsfelfoldi&lt;/a&gt;), Cayman&amp;nbsp;(&lt;a href=&quot;https://github.com/wemeetagain&quot;&gt;@wemeetagain&lt;/a&gt;), Etan Kissling&amp;nbsp;(&lt;a href=&quot;https://github.com/etan-status&quot;&gt;@etan-status&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7936&quot;&gt;7936&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Versioned Proxy Contract Interface&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Raphina Liu&amp;nbsp;(&lt;a href=&quot;https://github.com/Stamp9&quot;&gt;@Stamp9&lt;/a&gt;), Monica Jin&amp;nbsp;(&lt;a href=&quot;https://github.com/mokita-j&quot;&gt;@mokita-j&lt;/a&gt;), Martin Monperrus&amp;nbsp;(&lt;a href=&quot;https://github.com/monperrus&quot;&gt;@monperrus&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7945&quot;&gt;7945&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Confidential Transactions Supported Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Siyuan Zheng (@andrewcoder666)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:zhengsiyuan.zsy@antgroup.com&quot;&gt;zhengsiyuan.zsy@antgroup.com&lt;/a&gt;&amp;gt;, Zhe Han (@iampkuhz)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:hanzhe.hz@ant-intl.com&quot;&gt;hanzhe.hz@ant-intl.com&lt;/a&gt;&amp;gt;, Xiaoyu Liu (@elizabethxiaoyu)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jiushi.lxy@antgroup.com&quot;&gt;jiushi.lxy@antgroup.com&lt;/a&gt;&amp;gt;, Wenwei Ma (@madyinglight)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:huiwei.mww@antgroup.com&quot;&gt;huiwei.mww@antgroup.com&lt;/a&gt;&amp;gt;, Jun Meng Tan (@chadxeth)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:junmeng.t@antgroup.com&quot;&gt;junmeng.t@antgroup.com&lt;/a&gt;&amp;gt;, Yuxiang Fu (@tmac4096)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:kunfu.fyx@antgroup.com&quot;&gt;kunfu.fyx@antgroup.com&lt;/a&gt;&amp;gt;, Kecheng Gao (@thanks-v-me-50)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:gaokecheng.gkc@antgroup.com&quot;&gt;gaokecheng.gkc@antgroup.com&lt;/a&gt;&amp;gt;, Alwin Ng Jun Wei (@alwinngjw)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:alwin.ng@antgroup.com&quot;&gt;alwin.ng@antgroup.com&lt;/a&gt;&amp;gt;, Chenxin Wang (@3235773541)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:wcx465603@antgroup.com&quot;&gt;wcx465603@antgroup.com&lt;/a&gt;&amp;gt;, Xiang Gao (@GaoYiRu)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:gaoxiang.gao@antgroup.com&quot;&gt;gaoxiang.gao@antgroup.com&lt;/a&gt;&amp;gt;, yuanshanhshan (@xunayuan)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:yuanshanshan.yss@antgroup.com&quot;&gt;yuanshanshan.yss@antgroup.com&lt;/a&gt;&amp;gt;, Hao Zou (@BruceZH0915)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:situ.zh@antgroup.com&quot;&gt;situ.zh@antgroup.com&lt;/a&gt;&amp;gt;, Yanyi Liang&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:eason.lyy@antgroup.com&quot;&gt;eason.lyy@antgroup.com&lt;/a&gt;&amp;gt;, Yuehua Zhang (@astroyhzcc)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:ruoying.zyh@antgroup.com&quot;&gt;ruoying.zyh@antgroup.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8019&quot;&gt;8019&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Minimal Wallet-Managed Auto-Login for SIWE&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ivo Georgiev&amp;nbsp;(&lt;a href=&quot;https://github.com/Ivshti&quot;&gt;@Ivshti&lt;/a&gt;), Vijay Krishnavanshi&amp;nbsp;(&lt;a href=&quot;https://github.com/vijaykrishnavanshi&quot;&gt;@vijaykrishnavanshi&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8024&quot;&gt;8024&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Backward compatible SWAPN, DUPN, EXCHANGE&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Francisco Giordano&amp;nbsp;(&lt;a href=&quot;https://github.com/frangio&quot;&gt;@frangio&lt;/a&gt;), Charles Cooper&amp;nbsp;(&lt;a href=&quot;https://github.com/charles-cooper&quot;&gt;@charles-cooper&lt;/a&gt;), Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8111&quot;&gt;8111&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Bound Signatures&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;William Morriss&amp;nbsp;(&lt;a href=&quot;https://github.com/wjmelements&quot;&gt;@wjmelements&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8126&quot;&gt;8126&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;AI Agent Verification&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Leigh Cronian (@cybercentry)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:leigh.cronian@cybercentry.co.uk&quot;&gt;leigh.cronian@cybercentry.co.uk&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8161&quot;&gt;8161&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Transferable Tokenized Vault Requests&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Cain O&apos;Sullivan&amp;nbsp;(&lt;a href=&quot;https://github.com/cosullivan&quot;&gt;@cosullivan&lt;/a&gt;), Jeroen Offerijns&amp;nbsp;(&lt;a href=&quot;https://github.com/hieronx&quot;&gt;@hieronx&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8167&quot;&gt;8167&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Modular Dispatch Proxies&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;William Morriss&amp;nbsp;(&lt;a href=&quot;https://github.com/wjmelements&quot;&gt;@wjmelements&lt;/a&gt;), Radek Svarz&amp;nbsp;(&lt;a href=&quot;https://github.com/radeksvarz&quot;&gt;@radeksvarz&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
    &lt;/table&gt;
  

  
  
  
    &lt;h2 id=&quot;draft&quot;&gt;Draft&lt;/h2&gt;
    &lt;table class=&quot;eiptable&quot;&gt;
      &lt;thead&gt;
        
          &lt;tr&gt;&lt;th class=&quot;eipnum&quot;&gt;Number&lt;/th&gt;&lt;th class=&quot;title&quot;&gt;Title&lt;/th&gt;&lt;th class=&quot;author&quot;&gt;Author&lt;/th&gt;&lt;/tr&gt;
        
      &lt;/thead&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/assets/eip-7932/template-eip&quot;&gt;&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Example EIP to add generic algorithm as an algorithmic type&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-725&quot;&gt;725&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;General data key/value store and execution&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Fabian Vogelsteller&amp;nbsp;(&lt;a href=&quot;https://github.com/frozeman&quot;&gt;@frozeman&lt;/a&gt;), Tyler Yasaka&amp;nbsp;(&lt;a href=&quot;https://github.com/tyleryasaka&quot;&gt;@tyleryasaka&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-838&quot;&gt;838&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ABI specification for REVERT reason string&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Federico Bond&amp;nbsp;(&lt;a href=&quot;https://github.com/federicobond&quot;&gt;@federicobond&lt;/a&gt;), Renan Rodrigues de Souza&amp;nbsp;(&lt;a href=&quot;https://github.com/RenanSouza2&quot;&gt;@RenanSouza2&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-998&quot;&gt;998&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Composable Non-Fungible Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Matt Lockyer&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:mattdlockyer@gmail.com&quot;&gt;mattdlockyer@gmail.com&lt;/a&gt;&amp;gt;, Nick Mudge&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:nick@perfectabstractions.com&quot;&gt;nick@perfectabstractions.com&lt;/a&gt;&amp;gt;, Jordan Schalm&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jordan.schalm@gmail.com&quot;&gt;jordan.schalm@gmail.com&lt;/a&gt;&amp;gt;, sebastian echeverry&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:sebastian.echeverry@robotouniverse.com&quot;&gt;sebastian.echeverry@robotouniverse.com&lt;/a&gt;&amp;gt;, Zainan Victor Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/xinbenlv&quot;&gt;@xinbenlv&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2780&quot;&gt;2780&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Reduce intrinsic transaction gas&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Matt Garnett&amp;nbsp;(&lt;a href=&quot;https://github.com/lightclient&quot;&gt;@lightclient&lt;/a&gt;), Uri Klarman&amp;nbsp;(&lt;a href=&quot;https://github.com/uriklarman&quot;&gt;@uriklarman&lt;/a&gt;), Ben Adams&amp;nbsp;(&lt;a href=&quot;https://github.com/benaadams&quot;&gt;@benaadams&lt;/a&gt;), Maria Inês Silva&amp;nbsp;(&lt;a href=&quot;https://github.com/misilva73&quot;&gt;@misilva73&lt;/a&gt;), Anders Elowsson&amp;nbsp;(&lt;a href=&quot;https://github.com/anderselowsson&quot;&gt;@anderselowsson&lt;/a&gt;), Anthony Sassano&amp;nbsp;(&lt;a href=&quot;https://github.com/sassal&quot;&gt;@sassal&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2926&quot;&gt;2926&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Chunk-Based Code Merkleization&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Sina Mahmoodi&amp;nbsp;(&lt;a href=&quot;https://github.com/s1na&quot;&gt;@s1na&lt;/a&gt;), Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Guillaume Ballet&amp;nbsp;(&lt;a href=&quot;https://github.com/gballet&quot;&gt;@gballet&lt;/a&gt;), Jochem Brouwer&amp;nbsp;(&lt;a href=&quot;https://github.com/jochem-brouwer&quot;&gt;@jochem-brouwer&lt;/a&gt;), Ignacio Hagopian&amp;nbsp;(&lt;a href=&quot;https://github.com/jsign&quot;&gt;@jsign&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3009&quot;&gt;3009&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Transfer With Authorization&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Peter Jihoon Kim&amp;nbsp;(&lt;a href=&quot;https://github.com/petejkim&quot;&gt;@petejkim&lt;/a&gt;), Kevin Britz&amp;nbsp;(&lt;a href=&quot;https://github.com/kbrizzle&quot;&gt;@kbrizzle&lt;/a&gt;), David Knott&amp;nbsp;(&lt;a href=&quot;https://github.com/DavidLKnott&quot;&gt;@DavidLKnott&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3770&quot;&gt;3770&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Chain-specific addresses&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Lukas Schor&amp;nbsp;(&lt;a href=&quot;https://github.com/lukasschor&quot;&gt;@lukasschor&lt;/a&gt;), Richard Meissner&amp;nbsp;(&lt;a href=&quot;https://github.com/rmeissner&quot;&gt;@rmeissner&lt;/a&gt;), Pedro Gomes&amp;nbsp;(&lt;a href=&quot;https://github.com/pedrouid&quot;&gt;@pedrouid&lt;/a&gt;), ligi&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:ligi@ligi.de&quot;&gt;ligi@ligi.de&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4762&quot;&gt;4762&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Statelessness gas cost changes&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Guillaume Ballet&amp;nbsp;(&lt;a href=&quot;https://github.com/gballet&quot;&gt;@gballet&lt;/a&gt;), Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Dankrad Feist&amp;nbsp;(&lt;a href=&quot;https://github.com/dankrad&quot;&gt;@dankrad&lt;/a&gt;), Ignacio Hagopian&amp;nbsp;(&lt;a href=&quot;https://github.com/jsign&quot;&gt;@jsign&lt;/a&gt;), Tanishq Jasoria&amp;nbsp;(&lt;a href=&quot;https://github.com/tanishqjasoria&quot;&gt;@tanishqjasoria&lt;/a&gt;), Gajinder Singh&amp;nbsp;(&lt;a href=&quot;https://github.com/g11tech&quot;&gt;@g11tech&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4883&quot;&gt;4883&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Composable SVG NFT&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Andrew B Coathup&amp;nbsp;(&lt;a href=&quot;https://github.com/abcoathup&quot;&gt;@abcoathup&lt;/a&gt;), Alex&amp;nbsp;(&lt;a href=&quot;https://github.com/AlexPartyPanda&quot;&gt;@AlexPartyPanda&lt;/a&gt;), Damian Martinelli&amp;nbsp;(&lt;a href=&quot;https://github.com/damianmarti&quot;&gt;@damianmarti&lt;/a&gt;), blockdev&amp;nbsp;(&lt;a href=&quot;https://github.com/0xbok&quot;&gt;@0xbok&lt;/a&gt;), Austin Griffith&amp;nbsp;(&lt;a href=&quot;https://github.com/austintgriffith&quot;&gt;@austintgriffith&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4972&quot;&gt;4972&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Name-Owned Account&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Shu Dong&amp;nbsp;(&lt;a href=&quot;https://github.com/dongshu2013&quot;&gt;@dongshu2013&lt;/a&gt;), Qi Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/qizhou&quot;&gt;@qizhou&lt;/a&gt;), Zihao Chen&amp;nbsp;(&lt;a href=&quot;https://github.com/zihaoccc&quot;&gt;@zihaoccc&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5115&quot;&gt;5115&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;SY Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vu Nguyen&amp;nbsp;(&lt;a href=&quot;https://github.com/mrenoon&quot;&gt;@mrenoon&lt;/a&gt;), Long Vuong&amp;nbsp;(&lt;a href=&quot;https://github.com/UncleGrandpa925&quot;&gt;@UncleGrandpa925&lt;/a&gt;), Anton Buenavista&amp;nbsp;(&lt;a href=&quot;https://github.com/ayobuenavista&quot;&gt;@ayobuenavista&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5173&quot;&gt;5173&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;NFT Future Rewards (nFR)&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Yale ReiSoleil&amp;nbsp;(&lt;a href=&quot;https://github.com/longnshort&quot;&gt;@longnshort&lt;/a&gt;), dRadiant&amp;nbsp;(&lt;a href=&quot;https://github.com/dRadiant&quot;&gt;@dRadiant&lt;/a&gt;),  D Wang, PhD&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:david@iob.fi&quot;&gt;david@iob.fi&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5189&quot;&gt;5189&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Account Abstraction via Endorsed Operations&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Agustín Aguilar&amp;nbsp;(&lt;a href=&quot;https://github.com/agusx1211&quot;&gt;@agusx1211&lt;/a&gt;), Philippe Castonguay&amp;nbsp;(&lt;a href=&quot;https://github.com/phabc&quot;&gt;@phabc&lt;/a&gt;), Michael Standen&amp;nbsp;(&lt;a href=&quot;https://github.com/ScreamingHawk&quot;&gt;@ScreamingHawk&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5516&quot;&gt;5516&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Soulbound Multi-owner Tokens&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Lucas Martín Grasso Ramos&amp;nbsp;(&lt;a href=&quot;https://github.com/LucasGrasso&quot;&gt;@LucasGrasso&lt;/a&gt;), Matias Arazi&amp;nbsp;(&lt;a href=&quot;https://github.com/MatiArazi&quot;&gt;@MatiArazi&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5573&quot;&gt;5573&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Sign-In with Ethereum Capabilities, ReCaps&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Oliver Terbu&amp;nbsp;(&lt;a href=&quot;https://github.com/awoie&quot;&gt;@awoie&lt;/a&gt;), Jacob Ward&amp;nbsp;(&lt;a href=&quot;https://github.com/cobward&quot;&gt;@cobward&lt;/a&gt;), Charles Lehner&amp;nbsp;(&lt;a href=&quot;https://github.com/clehner&quot;&gt;@clehner&lt;/a&gt;), Sam Gbafa&amp;nbsp;(&lt;a href=&quot;https://github.com/skgbafa&quot;&gt;@skgbafa&lt;/a&gt;), Wayne Chang&amp;nbsp;(&lt;a href=&quot;https://github.com/wyc&quot;&gt;@wyc&lt;/a&gt;), Charles Cunningham&amp;nbsp;(&lt;a href=&quot;https://github.com/chunningham&quot;&gt;@chunningham&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5604&quot;&gt;5604&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;NFT Lien&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Zainan Victor Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/xinbenlv&quot;&gt;@xinbenlv&lt;/a&gt;), Allen Zhou&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:allen@ubiloan.io&quot;&gt;allen@ubiloan.io&lt;/a&gt;&amp;gt;, Alex Qin&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:alex@ubiloan.io&quot;&gt;alex@ubiloan.io&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5630&quot;&gt;5630&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;New approach for encryption / decryption&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Firn Protocol&amp;nbsp;(&lt;a href=&quot;https://github.com/firnprotocol&quot;&gt;@firnprotocol&lt;/a&gt;),  Fried L. Trout, Weiji Guo&amp;nbsp;(&lt;a href=&quot;https://github.com/weijiguo&quot;&gt;@weijiguo&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5700&quot;&gt;5700&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Bindable Token Interface&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Leeren&amp;nbsp;(&lt;a href=&quot;https://github.com/leeren&quot;&gt;@leeren&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5727&quot;&gt;5727&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Semi-Fungible Soulbound Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Austin Zhu&amp;nbsp;(&lt;a href=&quot;https://github.com/AustinZhu&quot;&gt;@AustinZhu&lt;/a&gt;), Terry Chen&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:terry.chen@phaneroz.io&quot;&gt;terry.chen@phaneroz.io&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5791&quot;&gt;5791&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Physical Backed Tokens&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;2pmflow&amp;nbsp;(&lt;a href=&quot;https://github.com/2pmflow&quot;&gt;@2pmflow&lt;/a&gt;), locationtba&amp;nbsp;(&lt;a href=&quot;https://github.com/locationtba&quot;&gt;@locationtba&lt;/a&gt;), Cameron Robertson&amp;nbsp;(&lt;a href=&quot;https://github.com/ccamrobertson&quot;&gt;@ccamrobertson&lt;/a&gt;), cygaar&amp;nbsp;(&lt;a href=&quot;https://github.com/cygaar&quot;&gt;@cygaar&lt;/a&gt;), Brian Weick&amp;nbsp;(&lt;a href=&quot;https://github.com/bweick&quot;&gt;@bweick&lt;/a&gt;), vectorized&amp;nbsp;(&lt;a href=&quot;https://github.com/vectorized&quot;&gt;@vectorized&lt;/a&gt;), djdabs&amp;nbsp;(&lt;a href=&quot;https://github.com/djdabs&quot;&gt;@djdabs&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6123&quot;&gt;6123&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Smart Derivative Contract&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Christian Fries&amp;nbsp;(&lt;a href=&quot;https://github.com/cfries&quot;&gt;@cfries&lt;/a&gt;), Peter Kohl-Landgraf&amp;nbsp;(&lt;a href=&quot;https://github.com/pekola&quot;&gt;@pekola&lt;/a&gt;), Alexandros Korpis&amp;nbsp;(&lt;a href=&quot;https://github.com/kourouta&quot;&gt;@kourouta&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6170&quot;&gt;6170&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Cross-Chain Messaging Interface&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Sujith Somraaj&amp;nbsp;(&lt;a href=&quot;https://github.com/sujithsomraaj&quot;&gt;@sujithsomraaj&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6229&quot;&gt;6229&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Tokenized Vaults with Lock-in Period&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Anderson Chen&amp;nbsp;(&lt;a href=&quot;https://github.com/Ankarrr&quot;&gt;@Ankarrr&lt;/a&gt;), Martinet Lee&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:martinetlee@gmail.com&quot;&gt;martinetlee@gmail.com&lt;/a&gt;&amp;gt;, Anton Cheng&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:antonassocareer@gmail.com&quot;&gt;antonassocareer@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6327&quot;&gt;6327&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Elastic Signature&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;George&amp;nbsp;(&lt;a href=&quot;https://github.com/JXRow&quot;&gt;@JXRow&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6404&quot;&gt;6404&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;SSZ transactions&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Etan Kissling&amp;nbsp;(&lt;a href=&quot;https://github.com/etan-status&quot;&gt;@etan-status&lt;/a&gt;), Gajinder Singh&amp;nbsp;(&lt;a href=&quot;https://github.com/g11tech&quot;&gt;@g11tech&lt;/a&gt;), Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6465&quot;&gt;6465&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;SSZ withdrawals root&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Etan Kissling&amp;nbsp;(&lt;a href=&quot;https://github.com/etan-status&quot;&gt;@etan-status&lt;/a&gt;), Mikhail Kalinin&amp;nbsp;(&lt;a href=&quot;https://github.com/mkalinin&quot;&gt;@mkalinin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6466&quot;&gt;6466&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;SSZ receipts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Etan Kissling&amp;nbsp;(&lt;a href=&quot;https://github.com/etan-status&quot;&gt;@etan-status&lt;/a&gt;), Gajinder Singh&amp;nbsp;(&lt;a href=&quot;https://github.com/g11tech&quot;&gt;@g11tech&lt;/a&gt;), Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6493&quot;&gt;6493&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;SSZ transaction signature scheme&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Etan Kissling&amp;nbsp;(&lt;a href=&quot;https://github.com/etan-status&quot;&gt;@etan-status&lt;/a&gt;), Gajinder Singh&amp;nbsp;(&lt;a href=&quot;https://github.com/g11tech&quot;&gt;@g11tech&lt;/a&gt;), Matt Garnett&amp;nbsp;(&lt;a href=&quot;https://github.com/lightclient&quot;&gt;@lightclient&lt;/a&gt;), Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6604&quot;&gt;6604&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Abstract Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Chris Walker (@cr-walker)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:chris@ckwalker.com&quot;&gt;chris@ckwalker.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6662&quot;&gt;6662&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;AA Account Metadata For Authentication&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Shu Dong&amp;nbsp;(&lt;a href=&quot;https://github.com/dongshu2013&quot;&gt;@dongshu2013&lt;/a&gt;), Zihao Chen&amp;nbsp;(&lt;a href=&quot;https://github.com/zihaoccc&quot;&gt;@zihaoccc&lt;/a&gt;), Peter Chen&amp;nbsp;(&lt;a href=&quot;https://github.com/pette1999&quot;&gt;@pette1999&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6682&quot;&gt;6682&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;NFT Flashloans&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;out.eth&amp;nbsp;(&lt;a href=&quot;https://github.com/outdoteth&quot;&gt;@outdoteth&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6785&quot;&gt;6785&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-721 Utilities Information Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Otniel Nicola&amp;nbsp;(&lt;a href=&quot;https://github.com/OT-kthd&quot;&gt;@OT-kthd&lt;/a&gt;), Bogdan Popa&amp;nbsp;(&lt;a href=&quot;https://github.com/BogdanKTHD&quot;&gt;@BogdanKTHD&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6786&quot;&gt;6786&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Registry for royalties payment for NFTs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Otniel Nicola&amp;nbsp;(&lt;a href=&quot;https://github.com/OT-kthd&quot;&gt;@OT-kthd&lt;/a&gt;), Bogdan Popa&amp;nbsp;(&lt;a href=&quot;https://github.com/BogdanKTHD&quot;&gt;@BogdanKTHD&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6787&quot;&gt;6787&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Order Book DEX with Two Phase Withdrawal&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jessica&amp;nbsp;(&lt;a href=&quot;https://github.com/qizheng09&quot;&gt;@qizheng09&lt;/a&gt;), Roy&amp;nbsp;(&lt;a href=&quot;https://github.com/royshang&quot;&gt;@royshang&lt;/a&gt;), Jun&amp;nbsp;(&lt;a href=&quot;https://github.com/SniperUsopp&quot;&gt;@SniperUsopp&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6806&quot;&gt;6806&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-721 Holding Time Tracking&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Saitama&amp;nbsp;(&lt;a href=&quot;https://github.com/saitama2009&quot;&gt;@saitama2009&lt;/a&gt;), Combo&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:combo@1combo.io&quot;&gt;combo@1combo.io&lt;/a&gt;&amp;gt;, Luigi&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:luigi@1combo.io&quot;&gt;luigi@1combo.io&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6821&quot;&gt;6821&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Support ENS Name for Web3 URL&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Qi Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/qizhou&quot;&gt;@qizhou&lt;/a&gt;), Qiang Zhu&amp;nbsp;(&lt;a href=&quot;https://github.com/qzhodl&quot;&gt;@qzhodl&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6823&quot;&gt;6823&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Token Mapping Slot Retrieval Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;qdqd (@qd-qd)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:qdqdqdqdqd@protonmail.com&quot;&gt;qdqdqdqdqd@protonmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6860&quot;&gt;6860&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Web3 URL to EVM Call Message Translation&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Qi Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/qizhou&quot;&gt;@qizhou&lt;/a&gt;), Chao Pi&amp;nbsp;(&lt;a href=&quot;https://github.com/pichaoqkc&quot;&gt;@pichaoqkc&lt;/a&gt;), Sam Wilson&amp;nbsp;(&lt;a href=&quot;https://github.com/SamWilsn&quot;&gt;@SamWilsn&lt;/a&gt;), Nicolas Deschildre&amp;nbsp;(&lt;a href=&quot;https://github.com/nand2&quot;&gt;@nand2&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6864&quot;&gt;6864&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Upgradable Fungible Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jeff Huang&amp;nbsp;(&lt;a href=&quot;https://github.com/jeffishjeff&quot;&gt;@jeffishjeff&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6865&quot;&gt;6865&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;On-Chain EIP-712 Visualization&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Abderrahmen Hanafi&amp;nbsp;(&lt;a href=&quot;https://github.com/a6-dou&quot;&gt;@a6-dou&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6900&quot;&gt;6900&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Modular Smart Contract Accounts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Adam Egyed&amp;nbsp;(&lt;a href=&quot;https://github.com/adamegyed&quot;&gt;@adamegyed&lt;/a&gt;), Fangting Liu&amp;nbsp;(&lt;a href=&quot;https://github.com/trinity-0111&quot;&gt;@trinity-0111&lt;/a&gt;), Jay Paik&amp;nbsp;(&lt;a href=&quot;https://github.com/jaypaik&quot;&gt;@jaypaik&lt;/a&gt;), Yoav Weiss&amp;nbsp;(&lt;a href=&quot;https://github.com/yoavw&quot;&gt;@yoavw&lt;/a&gt;), Huawei Gu&amp;nbsp;(&lt;a href=&quot;https://github.com/huaweigu&quot;&gt;@huaweigu&lt;/a&gt;), Daniel Lim&amp;nbsp;(&lt;a href=&quot;https://github.com/dlim-circle&quot;&gt;@dlim-circle&lt;/a&gt;), Ruben Koch&amp;nbsp;(&lt;a href=&quot;https://github.com/0xrubes&quot;&gt;@0xrubes&lt;/a&gt;), David Philipson&amp;nbsp;(&lt;a href=&quot;https://github.com/dphilipson&quot;&gt;@dphilipson&lt;/a&gt;), Howy Ho&amp;nbsp;(&lt;a href=&quot;https://github.com/howydev&quot;&gt;@howydev&lt;/a&gt;), Nikita Belenkov&amp;nbsp;(&lt;a href=&quot;https://github.com/nikita-quantstamp&quot;&gt;@nikita-quantstamp&lt;/a&gt;), zer0dot&amp;nbsp;(&lt;a href=&quot;https://github.com/zer0dot&quot;&gt;@zer0dot&lt;/a&gt;), David Kim&amp;nbsp;(&lt;a href=&quot;https://github.com/PowerStream3604&quot;&gt;@PowerStream3604&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6932&quot;&gt;6932&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Subscription-Based Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;360 Core&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:hello@360coreinc.com&quot;&gt;hello@360coreinc.com&lt;/a&gt;&amp;gt;, Robin Rajput&amp;nbsp;(&lt;a href=&quot;https://github.com/0xRobinR&quot;&gt;@0xRobinR&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6944&quot;&gt;6944&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-5219 Resolve Mode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gavin John&amp;nbsp;(&lt;a href=&quot;https://github.com/Pandapip1&quot;&gt;@Pandapip1&lt;/a&gt;), Qi Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/qizhou&quot;&gt;@qizhou&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6960&quot;&gt;6960&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Dual Layer Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Adam Boudjemaa&amp;nbsp;(&lt;a href=&quot;https://github.com/aboudjem&quot;&gt;@aboudjem&lt;/a&gt;), Mohamad Hammoud&amp;nbsp;(&lt;a href=&quot;https://github.com/mohamadhammoud&quot;&gt;@mohamadhammoud&lt;/a&gt;), Nawar Hisso&amp;nbsp;(&lt;a href=&quot;https://github.com/nawar-hisso&quot;&gt;@nawar-hisso&lt;/a&gt;), Khawla Hassan&amp;nbsp;(&lt;a href=&quot;https://github.com/khawlahssn&quot;&gt;@khawlahssn&lt;/a&gt;), Mohammad Zakeri Rad&amp;nbsp;(&lt;a href=&quot;https://github.com/zakrad&quot;&gt;@zakrad&lt;/a&gt;), Ashish Sood&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:soodgen@gmail.com&quot;&gt;soodgen@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6981&quot;&gt;6981&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Reserved Ownership Accounts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Paul Sullivan (@sullivph)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:paul.sullivan@manifold.xyz&quot;&gt;paul.sullivan@manifold.xyz&lt;/a&gt;&amp;gt;, Wilkins Chung (@wwchung)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:wilkins@manifold.xyz&quot;&gt;wilkins@manifold.xyz&lt;/a&gt;&amp;gt;, Kartik Patel (@Slokh)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:kartik@manifold.xyz&quot;&gt;kartik@manifold.xyz&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7085&quot;&gt;7085&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;NFT Relationship Enhancement&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Guang&amp;nbsp;(&lt;a href=&quot;https://github.com/xg1990&quot;&gt;@xg1990&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7087&quot;&gt;7087&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;MIME type for Web3 URL in Auto Mode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Qi Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/qizhou&quot;&gt;@qizhou&lt;/a&gt;), Nicolas Deschildre&amp;nbsp;(&lt;a href=&quot;https://github.com/nand2&quot;&gt;@nand2&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7093&quot;&gt;7093&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Social Recovery Interface&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;John Zhang&amp;nbsp;(&lt;a href=&quot;https://github.com/johnz1019&quot;&gt;@johnz1019&lt;/a&gt;), Davis Xiang&amp;nbsp;(&lt;a href=&quot;https://github.com/xcshuan&quot;&gt;@xcshuan&lt;/a&gt;), Kyle Xu&amp;nbsp;(&lt;a href=&quot;https://github.com/kylexyxu&quot;&gt;@kylexyxu&lt;/a&gt;), George Zhang&amp;nbsp;(&lt;a href=&quot;https://github.com/odysseus0&quot;&gt;@odysseus0&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7196&quot;&gt;7196&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Simple token, Simplified ERC-20&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Xiang&amp;nbsp;(&lt;a href=&quot;https://github.com/wenzhenxiang&quot;&gt;@wenzhenxiang&lt;/a&gt;), Ben77&amp;nbsp;(&lt;a href=&quot;https://github.com/ben2077&quot;&gt;@ben2077&lt;/a&gt;), Mingshi S.&amp;nbsp;(&lt;a href=&quot;https://github.com/newnewsms&quot;&gt;@newnewsms&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7204&quot;&gt;7204&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Contract wallet management token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Xiang&amp;nbsp;(&lt;a href=&quot;https://github.com/wenzhenxiang&quot;&gt;@wenzhenxiang&lt;/a&gt;), Ben77&amp;nbsp;(&lt;a href=&quot;https://github.com/ben2077&quot;&gt;@ben2077&lt;/a&gt;), Mingshi S.&amp;nbsp;(&lt;a href=&quot;https://github.com/newnewsms&quot;&gt;@newnewsms&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7254&quot;&gt;7254&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Token Revenue Sharing&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Quy Phan&amp;nbsp;(&lt;a href=&quot;https://github.com/quyphandang&quot;&gt;@quyphandang&lt;/a&gt;), Quy Phan&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:quy.phan@cryptoviet.info&quot;&gt;quy.phan@cryptoviet.info&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7272&quot;&gt;7272&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Ethereum Access Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Chris Chung&amp;nbsp;(&lt;a href=&quot;https://github.com/0xpApaSmURf&quot;&gt;@0xpApaSmURf&lt;/a&gt;), Raphael Roullet&amp;nbsp;(&lt;a href=&quot;https://github.com/ra-phael&quot;&gt;@ra-phael&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7280&quot;&gt;7280&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;NFT Metadata Extension like JSON-LD&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Yohei Nishikubo&amp;nbsp;(&lt;a href=&quot;https://github.com/yoheinishikubo&quot;&gt;@yoheinishikubo&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7303&quot;&gt;7303&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Token-Controlled Token Circulation&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ko Fujimura&amp;nbsp;(&lt;a href=&quot;https://github.com/kofujimura&quot;&gt;@kofujimura&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7390&quot;&gt;7390&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Vanilla Options for ERC-20 Tokens&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ewan Humbert (@Xeway)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:xeway@protonmail.com&quot;&gt;xeway@protonmail.com&lt;/a&gt;&amp;gt;, Lassi Maksimainen (@mlalma)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:lassi.maksimainen@gmail.com&quot;&gt;lassi.maksimainen@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7405&quot;&gt;7405&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Portable Smart Contract Accounts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Aaron Yee&amp;nbsp;(&lt;a href=&quot;https://github.com/aaronyee-eth&quot;&gt;@aaronyee-eth&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7406&quot;&gt;7406&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Multi-Namespace Onchain Registry&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Mengshi Zhang&amp;nbsp;(&lt;a href=&quot;https://github.com/MengshiZhang&quot;&gt;@MengshiZhang&lt;/a&gt;), Zihao Chen&amp;nbsp;(&lt;a href=&quot;https://github.com/zihaoccc&quot;&gt;@zihaoccc&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7410&quot;&gt;7410&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-20 Update Allowance By Spender&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Mohammad Zakeri Rad&amp;nbsp;(&lt;a href=&quot;https://github.com/zakrad&quot;&gt;@zakrad&lt;/a&gt;), Adam Boudjemaa&amp;nbsp;(&lt;a href=&quot;https://github.com/aboudjem&quot;&gt;@aboudjem&lt;/a&gt;), Mohamad Hammoud&amp;nbsp;(&lt;a href=&quot;https://github.com/mohamadhammoud&quot;&gt;@mohamadhammoud&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7412&quot;&gt;7412&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;On-Demand Off-Chain Data Retrieval&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Noah Litvin&amp;nbsp;(&lt;a href=&quot;https://github.com/noahlitvin&quot;&gt;@noahlitvin&lt;/a&gt;), db&amp;nbsp;(&lt;a href=&quot;https://github.com/dbeal-eth&quot;&gt;@dbeal-eth&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7425&quot;&gt;7425&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Tokenized Reserve&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jimmy Debe&amp;nbsp;(&lt;a href=&quot;https://github.com/jimstir&quot;&gt;@jimstir&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7444&quot;&gt;7444&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Time Locks Maturity&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Thanh Trinh (@thanhtrinh2003)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:thanh@revest.finance&quot;&gt;thanh@revest.finance&lt;/a&gt;&amp;gt;, Joshua Weintraub (@jhweintraub)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:josh@revest.finance&quot;&gt;josh@revest.finance&lt;/a&gt;&amp;gt;, Rob Montgomery (@RobAnon)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:rob@revest.finance&quot;&gt;rob@revest.finance&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7484&quot;&gt;7484&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Registry Extension for ERC-7579&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Konrad Kopp&amp;nbsp;(&lt;a href=&quot;https://github.com/kopy-kat&quot;&gt;@kopy-kat&lt;/a&gt;), zeroknots&amp;nbsp;(&lt;a href=&quot;https://github.com/zeroknots&quot;&gt;@zeroknots&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7496&quot;&gt;7496&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;NFT Dynamic Traits&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Adam Montgomery&amp;nbsp;(&lt;a href=&quot;https://github.com/montasaurus&quot;&gt;@montasaurus&lt;/a&gt;), Ryan Ghods&amp;nbsp;(&lt;a href=&quot;https://github.com/ryanio&quot;&gt;@ryanio&lt;/a&gt;), 0age&amp;nbsp;(&lt;a href=&quot;https://github.com/0age&quot;&gt;@0age&lt;/a&gt;), James Wenzel&amp;nbsp;(&lt;a href=&quot;https://github.com/emo-eth&quot;&gt;@emo-eth&lt;/a&gt;), Stephan Min&amp;nbsp;(&lt;a href=&quot;https://github.com/stephankmin&quot;&gt;@stephankmin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7498&quot;&gt;7498&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;NFT Redeemables&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ryan Ghods&amp;nbsp;(&lt;a href=&quot;https://github.com/ryanio&quot;&gt;@ryanio&lt;/a&gt;), 0age&amp;nbsp;(&lt;a href=&quot;https://github.com/0age&quot;&gt;@0age&lt;/a&gt;), Adam Montgomery&amp;nbsp;(&lt;a href=&quot;https://github.com/montasaurus&quot;&gt;@montasaurus&lt;/a&gt;), Stephan Min&amp;nbsp;(&lt;a href=&quot;https://github.com/stephankmin&quot;&gt;@stephankmin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7506&quot;&gt;7506&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Trusted Hint Registry&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Philipp Bolte&amp;nbsp;(&lt;a href=&quot;https://github.com/strumswell&quot;&gt;@strumswell&lt;/a&gt;), Dennis von der Bey&amp;nbsp;(&lt;a href=&quot;https://github.com/DennisVonDerBey&quot;&gt;@DennisVonDerBey&lt;/a&gt;), Lauritz Leifermann&amp;nbsp;(&lt;a href=&quot;https://github.com/lleifermann&quot;&gt;@lleifermann&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7507&quot;&gt;7507&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Multi-User NFT Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ming Jiang&amp;nbsp;(&lt;a href=&quot;https://github.com/minkyn&quot;&gt;@minkyn&lt;/a&gt;), Zheng Han&amp;nbsp;(&lt;a href=&quot;https://github.com/hanbsd&quot;&gt;@hanbsd&lt;/a&gt;), Fan Yang&amp;nbsp;(&lt;a href=&quot;https://github.com/fayang&quot;&gt;@fayang&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7508&quot;&gt;7508&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Dynamic On-Chain Token Attributes Repository&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Steven Pineda&amp;nbsp;(&lt;a href=&quot;https://github.com/steven2308&quot;&gt;@steven2308&lt;/a&gt;), Jan Turk&amp;nbsp;(&lt;a href=&quot;https://github.com/ThunderDeliverer&quot;&gt;@ThunderDeliverer&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7509&quot;&gt;7509&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Entity Component System&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Rickey&amp;nbsp;(&lt;a href=&quot;https://github.com/HelloRickey&quot;&gt;@HelloRickey&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7510&quot;&gt;7510&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Cross-Contract Hierarchical NFT&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ming Jiang&amp;nbsp;(&lt;a href=&quot;https://github.com/minkyn&quot;&gt;@minkyn&lt;/a&gt;), Zheng Han&amp;nbsp;(&lt;a href=&quot;https://github.com/hanbsd&quot;&gt;@hanbsd&lt;/a&gt;), Fan Yang&amp;nbsp;(&lt;a href=&quot;https://github.com/fayang&quot;&gt;@fayang&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7511&quot;&gt;7511&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Minimal Proxy Contract with PUSH0&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;0xAA&amp;nbsp;(&lt;a href=&quot;https://github.com/AmazingAng&quot;&gt;@AmazingAng&lt;/a&gt;), vectorized&amp;nbsp;(&lt;a href=&quot;https://github.com/Vectorized&quot;&gt;@Vectorized&lt;/a&gt;), 0age&amp;nbsp;(&lt;a href=&quot;https://github.com/0age&quot;&gt;@0age&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7512&quot;&gt;7512&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Onchain Representation for Audits&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Richard Meissner - Safe&amp;nbsp;(&lt;a href=&quot;https://github.com/rmeissner&quot;&gt;@rmeissner&lt;/a&gt;), Robert Chen - OtterSec&amp;nbsp;(&lt;a href=&quot;https://github.com/chen-robert&quot;&gt;@chen-robert&lt;/a&gt;), Matthias Egli - ChainSecurity&amp;nbsp;(&lt;a href=&quot;https://github.com/MatthiasEgli&quot;&gt;@MatthiasEgli&lt;/a&gt;), Jan Kalivoda - Ackee Blockchain&amp;nbsp;(&lt;a href=&quot;https://github.com/jaczkal&quot;&gt;@jaczkal&lt;/a&gt;), Michael Lewellen - OpenZeppelin&amp;nbsp;(&lt;a href=&quot;https://github.com/cylon56&quot;&gt;@cylon56&lt;/a&gt;), Shay Zluf - Hats Finance&amp;nbsp;(&lt;a href=&quot;https://github.com/shayzluf&quot;&gt;@shayzluf&lt;/a&gt;), Alex Papageorgiou - Omniscia&amp;nbsp;(&lt;a href=&quot;https://github.com/alex-ppg&quot;&gt;@alex-ppg&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7513&quot;&gt;7513&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Smart NFT - A Component for Intent-Centric&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;MJ Tseng (@TsengMJ)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:tsngmj@gmail.com&quot;&gt;tsngmj@gmail.com&lt;/a&gt;&amp;gt;, Clay (@Clay2018)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:clay.uw@outlook.com&quot;&gt;clay.uw@outlook.com&lt;/a&gt;&amp;gt;, Jeffery.c&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jeffery.c@a3sprotocol.xyz&quot;&gt;jeffery.c@a3sprotocol.xyz&lt;/a&gt;&amp;gt;, Johnny.c&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:johnny.c@a3sprotocol.xyz&quot;&gt;johnny.c@a3sprotocol.xyz&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7517&quot;&gt;7517&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Content Consent for AI/ML Data Mining&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Bofu Chen&amp;nbsp;(&lt;a href=&quot;https://github.com/bafu&quot;&gt;@bafu&lt;/a&gt;), Tammy Yang&amp;nbsp;(&lt;a href=&quot;https://github.com/tammyyang&quot;&gt;@tammyyang&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7521&quot;&gt;7521&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;General Intents for Smart Contract Wallets&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Stephen Monn&amp;nbsp;(&lt;a href=&quot;https://github.com/pixelcircuits&quot;&gt;@pixelcircuits&lt;/a&gt;), Bikem Bengisu&amp;nbsp;(&lt;a href=&quot;https://github.com/supiket&quot;&gt;@supiket&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7522&quot;&gt;7522&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;OIDC ZK Verifier for AA Account&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Shu Dong (@dongshu2013)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:shu@hexlink.io&quot;&gt;shu@hexlink.io&lt;/a&gt;&amp;gt;, Yudao Yan&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:dean@dauth.network&quot;&gt;dean@dauth.network&lt;/a&gt;&amp;gt;, Song Z&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:s@misfit.id&quot;&gt;s@misfit.id&lt;/a&gt;&amp;gt;, Kai Chen&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:kai@dauth.network&quot;&gt;kai@dauth.network&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7524&quot;&gt;7524&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;PLUME Signature in Wallets&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Yush G (@Divide-By-0)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:aayushg@mit.edu&quot;&gt;aayushg@mit.edu&lt;/a&gt;&amp;gt;, Kobi Gurkan&amp;nbsp;(&lt;a href=&quot;https://github.com/kobigurk&quot;&gt;@kobigurk&lt;/a&gt;), Richard Liu&amp;nbsp;(&lt;a href=&quot;https://github.com/rrrliu&quot;&gt;@rrrliu&lt;/a&gt;), Vivek Bhupatiraju&amp;nbsp;(&lt;a href=&quot;https://github.com/vb7401&quot;&gt;@vb7401&lt;/a&gt;), Barry Whitehat&amp;nbsp;(&lt;a href=&quot;https://github.com/barryWhiteHat&quot;&gt;@barryWhiteHat&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7527&quot;&gt;7527&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Token Bound Function Oracle AMM&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Elaine Zhang (@lanyinzly)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:lz8aj@virginia.edu&quot;&gt;lz8aj@virginia.edu&lt;/a&gt;&amp;gt;, Jerry&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jerrymindflow@gmail.com&quot;&gt;jerrymindflow@gmail.com&lt;/a&gt;&amp;gt;, Amandafanny&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:amandafanny200@gmail.com&quot;&gt;amandafanny200@gmail.com&lt;/a&gt;&amp;gt;, Shouhao Wong (@wangshouh)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:wongshouhao@outlook.com&quot;&gt;wongshouhao@outlook.com&lt;/a&gt;&amp;gt;, 0xPoet&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:0xpoets@gmail.com&quot;&gt;0xpoets@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7529&quot;&gt;7529&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Contract Discovery and eTLD+1 Association&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Todd Chapman&amp;nbsp;(&lt;a href=&quot;https://github.com/tthebc01&quot;&gt;@tthebc01&lt;/a&gt;), Charlie Sibbach&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:charlie@cwsoftware.com&quot;&gt;charlie@cwsoftware.com&lt;/a&gt;&amp;gt;, Sean Sing&amp;nbsp;(&lt;a href=&quot;https://github.com/seansing&quot;&gt;@seansing&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7533&quot;&gt;7533&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Public Cross Port&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;George&amp;nbsp;(&lt;a href=&quot;https://github.com/JXRow&quot;&gt;@JXRow&lt;/a&gt;), Zisu&amp;nbsp;(&lt;a href=&quot;https://github.com/lazy1523&quot;&gt;@lazy1523&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7538&quot;&gt;7538&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Multiplicative Tokens&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gavin John&amp;nbsp;(&lt;a href=&quot;https://github.com/Pandapip1&quot;&gt;@Pandapip1&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7546&quot;&gt;7546&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Upgradeable Clone for Scalable Contracts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Shogo Ochiai (@shogochiai)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:shogo.ochiai@pm.me&quot;&gt;shogo.ochiai@pm.me&lt;/a&gt;&amp;gt;, Kai Hiroi (@KaiHiroi)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:kai.hiroi@pm.me&quot;&gt;kai.hiroi@pm.me&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7548&quot;&gt;7548&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Open IP Protocol built on NFTs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Combo&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:combo@1combo.io&quot;&gt;combo@1combo.io&lt;/a&gt;&amp;gt;, Saitama&amp;nbsp;(&lt;a href=&quot;https://github.com/saitama2009&quot;&gt;@saitama2009&lt;/a&gt;), CT29&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:CT29@1combo.io&quot;&gt;CT29@1combo.io&lt;/a&gt;&amp;gt;, Luigi&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:luigi@1combo.io&quot;&gt;luigi@1combo.io&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7555&quot;&gt;7555&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Single Sign-On for Account Discovery&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alexander Müller&amp;nbsp;(&lt;a href=&quot;https://github.com/alexmmueller&quot;&gt;@alexmmueller&lt;/a&gt;), Gregory Markou&amp;nbsp;(&lt;a href=&quot;https://github.com/GregTheGreek&quot;&gt;@GregTheGreek&lt;/a&gt;), Willem Olding&amp;nbsp;(&lt;a href=&quot;https://github.com/Wollum&quot;&gt;@Wollum&lt;/a&gt;), Belma Gutlic&amp;nbsp;(&lt;a href=&quot;https://github.com/morrigan&quot;&gt;@morrigan&lt;/a&gt;), Marin Petrunić&amp;nbsp;(&lt;a href=&quot;https://github.com/mpetrunic&quot;&gt;@mpetrunic&lt;/a&gt;), Pedro Gomes&amp;nbsp;(&lt;a href=&quot;https://github.com/pedrouid&quot;&gt;@pedrouid&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7561&quot;&gt;7561&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Simple NFT, Simplified ERC-721&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Xiang&amp;nbsp;(&lt;a href=&quot;https://github.com/wenzhenxiang&quot;&gt;@wenzhenxiang&lt;/a&gt;), Ben77&amp;nbsp;(&lt;a href=&quot;https://github.com/ben2077&quot;&gt;@ben2077&lt;/a&gt;), Mingshi S.&amp;nbsp;(&lt;a href=&quot;https://github.com/newnewsms&quot;&gt;@newnewsms&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7562&quot;&gt;7562&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Account Abstraction Validation Scope Rules&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Yoav Weiss&amp;nbsp;(&lt;a href=&quot;https://github.com/yoavw&quot;&gt;@yoavw&lt;/a&gt;), Dror Tirosh&amp;nbsp;(&lt;a href=&quot;https://github.com/drortirosh&quot;&gt;@drortirosh&lt;/a&gt;), Alex Forshtat&amp;nbsp;(&lt;a href=&quot;https://github.com/forshtat&quot;&gt;@forshtat&lt;/a&gt;), Shahaf Nacson&amp;nbsp;(&lt;a href=&quot;https://github.com/shahafn&quot;&gt;@shahafn&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7564&quot;&gt;7564&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Contract wallet management NFT&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Xiang&amp;nbsp;(&lt;a href=&quot;https://github.com/wenzhenxiang&quot;&gt;@wenzhenxiang&lt;/a&gt;), Ben77&amp;nbsp;(&lt;a href=&quot;https://github.com/ben2077&quot;&gt;@ben2077&lt;/a&gt;), Mingshi S.&amp;nbsp;(&lt;a href=&quot;https://github.com/newnewsms&quot;&gt;@newnewsms&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7565&quot;&gt;7565&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Perpetual Contract NFTs as Collateral&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Hyoungsung Kim (@HyoungsungKim)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:hyougnsung@keti.re.kr&quot;&gt;hyougnsung@keti.re.kr&lt;/a&gt;&amp;gt;, Yong-Suk Park&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:yspark@keti.re.kr&quot;&gt;yspark@keti.re.kr&lt;/a&gt;&amp;gt;, Hyun-Sik Kim&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:hskim@keti.re.kr&quot;&gt;hskim@keti.re.kr&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7566&quot;&gt;7566&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Multiplayer Game Communication&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Rickey&amp;nbsp;(&lt;a href=&quot;https://github.com/HelloRickey&quot;&gt;@HelloRickey&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7572&quot;&gt;7572&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Contract-level metadata via `contractURI()`&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Devin Finzer&amp;nbsp;(&lt;a href=&quot;https://github.com/dfinzer&quot;&gt;@dfinzer&lt;/a&gt;), Alex Atallah&amp;nbsp;(&lt;a href=&quot;https://github.com/alexanderatallah&quot;&gt;@alexanderatallah&lt;/a&gt;), Ryan Ghods&amp;nbsp;(&lt;a href=&quot;https://github.com/ryanio&quot;&gt;@ryanio&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7573&quot;&gt;7573&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Conditional-upon-Transfer-Decryption for DvP&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Christian Fries&amp;nbsp;(&lt;a href=&quot;https://github.com/cfries&quot;&gt;@cfries&lt;/a&gt;), Peter Kohl-Landgraf&amp;nbsp;(&lt;a href=&quot;https://github.com/pekola&quot;&gt;@pekola&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7579&quot;&gt;7579&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Minimal Modular Smart Accounts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;zeroknots&amp;nbsp;(&lt;a href=&quot;https://github.com/zeroknots&quot;&gt;@zeroknots&lt;/a&gt;), Konrad Kopp&amp;nbsp;(&lt;a href=&quot;https://github.com/kopy-kat&quot;&gt;@kopy-kat&lt;/a&gt;), Taek Lee&amp;nbsp;(&lt;a href=&quot;https://github.com/leekt&quot;&gt;@leekt&lt;/a&gt;), Fil Makarov&amp;nbsp;(&lt;a href=&quot;https://github.com/filmakarov&quot;&gt;@filmakarov&lt;/a&gt;), Elim Poon&amp;nbsp;(&lt;a href=&quot;https://github.com/yaonam&quot;&gt;@yaonam&lt;/a&gt;), Lyu Min&amp;nbsp;(&lt;a href=&quot;https://github.com/rockmin216&quot;&gt;@rockmin216&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7580&quot;&gt;7580&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Advertisement Tracking Interface&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;wart&amp;nbsp;(&lt;a href=&quot;https://github.com/wartstone&quot;&gt;@wartstone&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7582&quot;&gt;7582&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Modular Accounts with Delegated Validation&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Shivanshi Tyagi&amp;nbsp;(&lt;a href=&quot;https://github.com/nerderlyne&quot;&gt;@nerderlyne&lt;/a&gt;), Ross Campbell&amp;nbsp;(&lt;a href=&quot;https://github.com/z0r0z&quot;&gt;@z0r0z&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7585&quot;&gt;7585&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;MixHash and Public Data Storage Proofs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Liu Zhicong&amp;nbsp;(&lt;a href=&quot;https://github.com/waterflier&quot;&gt;@waterflier&lt;/a&gt;), William Entriken&amp;nbsp;(&lt;a href=&quot;https://github.com/fulldecent&quot;&gt;@fulldecent&lt;/a&gt;), Wei Qiushi&amp;nbsp;(&lt;a href=&quot;https://github.com/weiqiushi&quot;&gt;@weiqiushi&lt;/a&gt;), Si Changjun&amp;nbsp;(&lt;a href=&quot;https://github.com/photosssa&quot;&gt;@photosssa&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7589&quot;&gt;7589&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Semi-Fungible Token Roles&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ernani São Thiago&amp;nbsp;(&lt;a href=&quot;https://github.com/ernanirst&quot;&gt;@ernanirst&lt;/a&gt;), Daniel Lima&amp;nbsp;(&lt;a href=&quot;https://github.com/karacurt&quot;&gt;@karacurt&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7595&quot;&gt;7595&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Collateralized NFT&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;571nKY&amp;nbsp;(&lt;a href=&quot;https://github.com/571nKY&quot;&gt;@571nKY&lt;/a&gt;), Cosmos&amp;nbsp;(&lt;a href=&quot;https://github.com/Cosmos4k&quot;&gt;@Cosmos4k&lt;/a&gt;), f4t50&amp;nbsp;(&lt;a href=&quot;https://github.com/f4t50&quot;&gt;@f4t50&lt;/a&gt;), Harpocrates&amp;nbsp;(&lt;a href=&quot;https://github.com/harpocrates555&quot;&gt;@harpocrates555&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7597&quot;&gt;7597&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Signature Validation Extension for Permit&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Yvonne Zhang&amp;nbsp;(&lt;a href=&quot;https://github.com/yvonnezhangc&quot;&gt;@yvonnezhangc&lt;/a&gt;), Aloysius Chan&amp;nbsp;(&lt;a href=&quot;https://github.com/circle-aloychan&quot;&gt;@circle-aloychan&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7598&quot;&gt;7598&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Use contract signature for signed transfer&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Yvonne Zhang&amp;nbsp;(&lt;a href=&quot;https://github.com/yvonnezhangc&quot;&gt;@yvonnezhangc&lt;/a&gt;), Aloysius Chan&amp;nbsp;(&lt;a href=&quot;https://github.com/circle-aloychan&quot;&gt;@circle-aloychan&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7603&quot;&gt;7603&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-1155 Multi-Asset extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Haru&amp;nbsp;(&lt;a href=&quot;https://github.com/haruu8&quot;&gt;@haruu8&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7604&quot;&gt;7604&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-1155 Permit Approvals&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;calvbore&amp;nbsp;(&lt;a href=&quot;https://github.com/calvbore&quot;&gt;@calvbore&lt;/a&gt;), emiliolanzalaco&amp;nbsp;(&lt;a href=&quot;https://github.com/emiliolanzalaco&quot;&gt;@emiliolanzalaco&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7613&quot;&gt;7613&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Puppet Proxy Contract&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Igor Żuk&amp;nbsp;(&lt;a href=&quot;https://github.com/CodeSandwich&quot;&gt;@CodeSandwich&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7615&quot;&gt;7615&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Atomic Push-based Data Feed Among Contracts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Elaine Zhang (@lanyinzly)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:lz8aj@virginia.edu&quot;&gt;lz8aj@virginia.edu&lt;/a&gt;&amp;gt;, Jerry&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jerrymindflow@gmail.com&quot;&gt;jerrymindflow@gmail.com&lt;/a&gt;&amp;gt;, Amandafanny&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:amandafanny200@gmail.com&quot;&gt;amandafanny200@gmail.com&lt;/a&gt;&amp;gt;, Shouhao Wong (@wangshouh)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:wongshouhao@outlook.com&quot;&gt;wongshouhao@outlook.com&lt;/a&gt;&amp;gt;, Doris Che (@Cheyukj)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:dorischeyy@gmail.com&quot;&gt;dorischeyy@gmail.com&lt;/a&gt;&amp;gt;, Henry Yuan (@onehumanbeing)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:hy2878@nyu.edu&quot;&gt;hy2878@nyu.edu&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7617&quot;&gt;7617&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Chunk support for ERC-5219 mode in Web3 URL&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Qi Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/qizhou&quot;&gt;@qizhou&lt;/a&gt;), Nicolas Deschildre&amp;nbsp;(&lt;a href=&quot;https://github.com/nand2&quot;&gt;@nand2&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7618&quot;&gt;7618&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Content encoding in ERC-5219 mode Web3 URL&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Qi Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/qizhou&quot;&gt;@qizhou&lt;/a&gt;), Nicolas Deschildre&amp;nbsp;(&lt;a href=&quot;https://github.com/nand2&quot;&gt;@nand2&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7619&quot;&gt;7619&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Precompile Falcon512 generic verifier&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Erick Pacheco Pedraza&amp;nbsp;(&lt;a href=&quot;https://github.com/eum602&quot;&gt;@eum602&lt;/a&gt;), Marcos Allende&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:mallende@lacnet.com&quot;&gt;mallende@lacnet.com&lt;/a&gt;&amp;gt;, Diego Lopez León&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:dieguitoll@gmail.com&quot;&gt;dieguitoll@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7621&quot;&gt;7621&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Basket Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Dominic Ryder&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:dom@alvara.xyz&quot;&gt;dom@alvara.xyz&lt;/a&gt;&amp;gt;, Michael Ryder&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:mike@alvara.xyz&quot;&gt;mike@alvara.xyz&lt;/a&gt;&amp;gt;, Callum Mitchell-Clark (@AlvaraProtocol)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:cal@alvara.xyz&quot;&gt;cal@alvara.xyz&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7629&quot;&gt;7629&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-20/ERC-721 Unified Token Interface&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;0xZeus1111&amp;nbsp;(&lt;a href=&quot;https://github.com/0xZeus1111&quot;&gt;@0xZeus1111&lt;/a&gt;), Nvuwa&amp;nbsp;(&lt;a href=&quot;https://github.com/Nvuwa&quot;&gt;@Nvuwa&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7632&quot;&gt;7632&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Interfaces for Named Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Zainan Victor Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/xinbenlv&quot;&gt;@xinbenlv&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7638&quot;&gt;7638&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Batch Calls Encoding in SCA&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;George&amp;nbsp;(&lt;a href=&quot;https://github.com/JXRow&quot;&gt;@JXRow&lt;/a&gt;), Zisu&amp;nbsp;(&lt;a href=&quot;https://github.com/lazy1523&quot;&gt;@lazy1523&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7641&quot;&gt;7641&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Intrinsic RevShare Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Conway&amp;nbsp;(&lt;a href=&quot;https://github.com/0x1cc&quot;&gt;@0x1cc&lt;/a&gt;), Cathie So&amp;nbsp;(&lt;a href=&quot;https://github.com/socathie&quot;&gt;@socathie&lt;/a&gt;), Xiaohang Yu&amp;nbsp;(&lt;a href=&quot;https://github.com/xhyumiracle&quot;&gt;@xhyumiracle&lt;/a&gt;), Suning Yao&amp;nbsp;(&lt;a href=&quot;https://github.com/fewwwww&quot;&gt;@fewwwww&lt;/a&gt;), Kartin&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:kartin@hyperoracle.io&quot;&gt;kartin@hyperoracle.io&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7644&quot;&gt;7644&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-721 Name Registry Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Chen Liaoyuan&amp;nbsp;(&lt;a href=&quot;https://github.com/chenly&quot;&gt;@chenly&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7649&quot;&gt;7649&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Bonding curve-embedded liquidity for NFTs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Arif Khan&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:arif@alethea.ai&quot;&gt;arif@alethea.ai&lt;/a&gt;&amp;gt;, Ahmad Matyana&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:ahmad@alethea.ai&quot;&gt;ahmad@alethea.ai&lt;/a&gt;&amp;gt;, Basil Gorin&amp;nbsp;(&lt;a href=&quot;https://github.com/vgorin&quot;&gt;@vgorin&lt;/a&gt;), Vijay Bhayani&amp;nbsp;(&lt;a href=&quot;https://github.com/unblocktechie&quot;&gt;@unblocktechie&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7651&quot;&gt;7651&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Fractionally Represented Non-Fungible Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Acme&amp;nbsp;(&lt;a href=&quot;https://github.com/0xacme&quot;&gt;@0xacme&lt;/a&gt;), Calder&amp;nbsp;(&lt;a href=&quot;https://github.com/caldereth&quot;&gt;@caldereth&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7652&quot;&gt;7652&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-721 Guarantee Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Liu.C.Dao (@CDao)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:iunknow@163.com&quot;&gt;iunknow@163.com&lt;/a&gt;&amp;gt;, Sam&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:1047180870@qq.com&quot;&gt;1047180870@qq.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7654&quot;&gt;7654&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Request Method Types&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Rickey&amp;nbsp;(&lt;a href=&quot;https://github.com/HelloRickey&quot;&gt;@HelloRickey&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7662&quot;&gt;7662&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;AI Agent NFTs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Greg Marlin&amp;nbsp;(&lt;a href=&quot;https://github.com/marleymarl&quot;&gt;@marleymarl&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7679&quot;&gt;7679&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;UserOperation Builder&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Derek Chiang&amp;nbsp;(&lt;a href=&quot;https://github.com/derekchiang&quot;&gt;@derekchiang&lt;/a&gt;), Garvit Khatri&amp;nbsp;(&lt;a href=&quot;https://github.com/plusminushalf&quot;&gt;@plusminushalf&lt;/a&gt;), Fil Makarov&amp;nbsp;(&lt;a href=&quot;https://github.com/filmakarov&quot;&gt;@filmakarov&lt;/a&gt;), Kristof Gazso&amp;nbsp;(&lt;a href=&quot;https://github.com/kristofgazso&quot;&gt;@kristofgazso&lt;/a&gt;), Derek Rein&amp;nbsp;(&lt;a href=&quot;https://github.com/arein&quot;&gt;@arein&lt;/a&gt;), Tomas Rocchi&amp;nbsp;(&lt;a href=&quot;https://github.com/tomiir&quot;&gt;@tomiir&lt;/a&gt;), bumblefudge&amp;nbsp;(&lt;a href=&quot;https://github.com/bumblefudge&quot;&gt;@bumblefudge&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7681&quot;&gt;7681&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Dual Nature Multi Token Protocol&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Sennett Lau&amp;nbsp;(&lt;a href=&quot;https://github.com/sennett-lau&quot;&gt;@sennett-lau&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7682&quot;&gt;7682&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Auxiliary Funds Capability&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Lukas Rosario&amp;nbsp;(&lt;a href=&quot;https://github.com/lukasrosario&quot;&gt;@lukasrosario&lt;/a&gt;), Wilson Cusack&amp;nbsp;(&lt;a href=&quot;https://github.com/wilsoncusack&quot;&gt;@wilsoncusack&lt;/a&gt;), Alex Donesky&amp;nbsp;(&lt;a href=&quot;https://github.com/adonesky1&quot;&gt;@adonesky1&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7683&quot;&gt;7683&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Cross Chain Intents&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Mark Toda&amp;nbsp;(&lt;a href=&quot;https://github.com/marktoda&quot;&gt;@marktoda&lt;/a&gt;), Matt Rice&amp;nbsp;(&lt;a href=&quot;https://github.com/mrice32&quot;&gt;@mrice32&lt;/a&gt;), Nick Pai&amp;nbsp;(&lt;a href=&quot;https://github.com/nicholaspai&quot;&gt;@nicholaspai&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7694&quot;&gt;7694&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Solana Storage Router&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Avneet Singh&amp;nbsp;(&lt;a href=&quot;https://github.com/sshmatrix&quot;&gt;@sshmatrix&lt;/a&gt;), 0xc0de4c0ffee&amp;nbsp;(&lt;a href=&quot;https://github.com/0xc0de4c0ffee&quot;&gt;@0xc0de4c0ffee&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7695&quot;&gt;7695&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Ownership Delegation and Context for ERC-721&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Duc Tho Tran&amp;nbsp;(&lt;a href=&quot;https://github.com/ducthotran2010&quot;&gt;@ducthotran2010&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7699&quot;&gt;7699&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-20 Transfer Reference Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Radek Svarz&amp;nbsp;(&lt;a href=&quot;https://github.com/radeksvarz&quot;&gt;@radeksvarz&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7700&quot;&gt;7700&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Cross-chain Storage Router Protocol&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Avneet Singh&amp;nbsp;(&lt;a href=&quot;https://github.com/sshmatrix&quot;&gt;@sshmatrix&lt;/a&gt;), 0xc0de4c0ffee&amp;nbsp;(&lt;a href=&quot;https://github.com/0xc0de4c0ffee&quot;&gt;@0xc0de4c0ffee&lt;/a&gt;), Nick Johnson&amp;nbsp;(&lt;a href=&quot;https://github.com/arachnid&quot;&gt;@arachnid&lt;/a&gt;), Makoto Inoue&amp;nbsp;(&lt;a href=&quot;https://github.com/makoto&quot;&gt;@makoto&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7708&quot;&gt;7708&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ETH transfers and burns emit a log&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Peter Davies&amp;nbsp;(&lt;a href=&quot;https://github.com/petertdavies&quot;&gt;@petertdavies&lt;/a&gt;), Etan Kissling&amp;nbsp;(&lt;a href=&quot;https://github.com/etan-status&quot;&gt;@etan-status&lt;/a&gt;), Gajinder Singh&amp;nbsp;(&lt;a href=&quot;https://github.com/g11tech&quot;&gt;@g11tech&lt;/a&gt;), Carson&amp;nbsp;(&lt;a href=&quot;https://github.com/carsons-eels&quot;&gt;@carsons-eels&lt;/a&gt;), Jared Wasinger&amp;nbsp;(&lt;a href=&quot;https://github.com/jwasinger&quot;&gt;@jwasinger&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7710&quot;&gt;7710&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Smart Contract Delegation&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ryan McPeck&amp;nbsp;(&lt;a href=&quot;https://github.com/McOso&quot;&gt;@McOso&lt;/a&gt;), Dan Finlay&amp;nbsp;(&lt;a href=&quot;https://github.com/DanFinlay&quot;&gt;@DanFinlay&lt;/a&gt;), Rob Dawson&amp;nbsp;(&lt;a href=&quot;https://github.com/rojotek&quot;&gt;@rojotek&lt;/a&gt;), Derek Chiang&amp;nbsp;(&lt;a href=&quot;https://github.com/derekchiang&quot;&gt;@derekchiang&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7715&quot;&gt;7715&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Request Permissions from Wallets&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Luka Isailovic&amp;nbsp;(&lt;a href=&quot;https://github.com/lukaisailovic&quot;&gt;@lukaisailovic&lt;/a&gt;), Derek Rein&amp;nbsp;(&lt;a href=&quot;https://github.com/arein&quot;&gt;@arein&lt;/a&gt;), Dan Finlay&amp;nbsp;(&lt;a href=&quot;https://github.com/danfinlay&quot;&gt;@danfinlay&lt;/a&gt;), Derek Chiang&amp;nbsp;(&lt;a href=&quot;https://github.com/derekchiang&quot;&gt;@derekchiang&lt;/a&gt;), Fil Makarov&amp;nbsp;(&lt;a href=&quot;https://github.com/filmakarov&quot;&gt;@filmakarov&lt;/a&gt;), Pedro Gomes&amp;nbsp;(&lt;a href=&quot;https://github.com/pedrouid&quot;&gt;@pedrouid&lt;/a&gt;), Conner Swenberg&amp;nbsp;(&lt;a href=&quot;https://github.com/ilikesymmetry&quot;&gt;@ilikesymmetry&lt;/a&gt;), Lukas Rosario&amp;nbsp;(&lt;a href=&quot;https://github.com/lukasrosario&quot;&gt;@lukasrosario&lt;/a&gt;), Idris Bowman&amp;nbsp;(&lt;a href=&quot;https://github.com/V00D00-child&quot;&gt;@V00D00-child&lt;/a&gt;), Jeff Smale&amp;nbsp;(&lt;a href=&quot;https://github.com/jeffsmale90&quot;&gt;@jeffsmale90&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7720&quot;&gt;7720&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Deferred Token Transfer&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Chen Liaoyuan (@chenly)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:cly@kip.pro&quot;&gt;cly@kip.pro&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7721&quot;&gt;7721&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Lockable Extension for ERC-1155&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Piyush Chittara&amp;nbsp;(&lt;a href=&quot;https://github.com/piyush-chittara&quot;&gt;@piyush-chittara&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7722&quot;&gt;7722&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Opaque Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ivica Aračić&amp;nbsp;(&lt;a href=&quot;https://github.com/ivica7&quot;&gt;@ivica7&lt;/a&gt;), Ante Bešlić&amp;nbsp;(&lt;a href=&quot;https://github.com/ethSplit&quot;&gt;@ethSplit&lt;/a&gt;), Mirko Katanić&amp;nbsp;(&lt;a href=&quot;https://github.com/mkatanic&quot;&gt;@mkatanic&lt;/a&gt;),  SWIAT&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7726&quot;&gt;7726&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Common Quote Oracle&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;alcueca&amp;nbsp;(&lt;a href=&quot;https://github.com/alcueca&quot;&gt;@alcueca&lt;/a&gt;), ruvaag&amp;nbsp;(&lt;a href=&quot;https://github.com/ruvaag&quot;&gt;@ruvaag&lt;/a&gt;), totomanov&amp;nbsp;(&lt;a href=&quot;https://github.com/totomanov&quot;&gt;@totomanov&lt;/a&gt;), r0ohafza&amp;nbsp;(&lt;a href=&quot;https://github.com/r0ohafza&quot;&gt;@r0ohafza&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7729&quot;&gt;7729&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Token with Metadata&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;msfew&amp;nbsp;(&lt;a href=&quot;https://github.com/fewwwww&quot;&gt;@fewwwww&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7730&quot;&gt;7730&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Structured Data Clear Signing Format&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Laurent Castillo&amp;nbsp;(&lt;a href=&quot;https://github.com/lcastillo-ledger&quot;&gt;@lcastillo-ledger&lt;/a&gt;), Derek Rein&amp;nbsp;(&lt;a href=&quot;https://github.com/arein&quot;&gt;@arein&lt;/a&gt;), Pierre Aoun&amp;nbsp;(&lt;a href=&quot;https://github.com/paoun-ledger&quot;&gt;@paoun-ledger&lt;/a&gt;), Arik Galansky&amp;nbsp;(&lt;a href=&quot;https://github.com/arikg&quot;&gt;@arikg&lt;/a&gt;), Bartosz Rozwarski&amp;nbsp;(&lt;a href=&quot;https://github.com/llbartekll&quot;&gt;@llbartekll&lt;/a&gt;), Kaan Uzdogan&amp;nbsp;(&lt;a href=&quot;https://github.com/kuzdogan&quot;&gt;@kuzdogan&lt;/a&gt;), Fredrik&amp;nbsp;(&lt;a href=&quot;https://github.com/Fredrik0x&quot;&gt;@Fredrik0x&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7732&quot;&gt;7732&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Enshrined Proposer-Builder Separation&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Francesco D&apos;Amato&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:francesco.damato@ethereum.org&quot;&gt;francesco.damato@ethereum.org&lt;/a&gt;&amp;gt;, Nico Flaig&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:nflaig@protonmail.com&quot;&gt;nflaig@protonmail.com&lt;/a&gt;&amp;gt;, Barnabé Monnot&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:barnabe.monnot@ethereum.org&quot;&gt;barnabe.monnot@ethereum.org&lt;/a&gt;&amp;gt;, Michael Neuder&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:michael.neuder@ethereum.org&quot;&gt;michael.neuder@ethereum.org&lt;/a&gt;&amp;gt;, Potuz&amp;nbsp;(&lt;a href=&quot;https://github.com/potuz&quot;&gt;@potuz&lt;/a&gt;), Justin Traglia&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jtraglia@ethereum.org&quot;&gt;jtraglia@ethereum.org&lt;/a&gt;&amp;gt;, Terence Tsao&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:ttsao@offchainlabs.com&quot;&gt;ttsao@offchainlabs.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7738&quot;&gt;7738&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Permissionless Script Registry&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Victor Zhang&amp;nbsp;(&lt;a href=&quot;https://github.com/zhangzhongnan928&quot;&gt;@zhangzhongnan928&lt;/a&gt;), James Brown&amp;nbsp;(&lt;a href=&quot;https://github.com/JamesSmartCell&quot;&gt;@JamesSmartCell&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7739&quot;&gt;7739&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Readable Typed Signatures for Smart Accounts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;vectorized&amp;nbsp;(&lt;a href=&quot;https://github.com/vectorized&quot;&gt;@vectorized&lt;/a&gt;), Sihoon Lee&amp;nbsp;(&lt;a href=&quot;https://github.com/push0ebp&quot;&gt;@push0ebp&lt;/a&gt;), Francisco Giordano&amp;nbsp;(&lt;a href=&quot;https://github.com/frangio&quot;&gt;@frangio&lt;/a&gt;), Hadrien Croubois&amp;nbsp;(&lt;a href=&quot;https://github.com/Amxx&quot;&gt;@Amxx&lt;/a&gt;), Ernesto García&amp;nbsp;(&lt;a href=&quot;https://github.com/ernestognw&quot;&gt;@ernestognw&lt;/a&gt;), Im Juno&amp;nbsp;(&lt;a href=&quot;https://github.com/junomonster&quot;&gt;@junomonster&lt;/a&gt;), howydev&amp;nbsp;(&lt;a href=&quot;https://github.com/howydev&quot;&gt;@howydev&lt;/a&gt;), Atarpara&amp;nbsp;(&lt;a href=&quot;https://github.com/Atarpara&quot;&gt;@Atarpara&lt;/a&gt;), 0xcuriousapple&amp;nbsp;(&lt;a href=&quot;https://github.com/0xcuriousapple&quot;&gt;@0xcuriousapple&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7741&quot;&gt;7741&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Authorize Operator&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jeroen Offerijns&amp;nbsp;(&lt;a href=&quot;https://github.com/hieronx&quot;&gt;@hieronx&lt;/a&gt;), João Martins&amp;nbsp;(&lt;a href=&quot;https://github.com/0xTimepunk&quot;&gt;@0xTimepunk&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7745&quot;&gt;7745&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Trustless log and transaction index&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Zsolt Felföldi&amp;nbsp;(&lt;a href=&quot;https://github.com/zsfelfoldi&quot;&gt;@zsfelfoldi&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7748&quot;&gt;7748&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;State conversion to Verkle Tree&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Guillaume Ballet&amp;nbsp;(&lt;a href=&quot;https://github.com/gballet&quot;&gt;@gballet&lt;/a&gt;), Ignacio Hagopian&amp;nbsp;(&lt;a href=&quot;https://github.com/jsign&quot;&gt;@jsign&lt;/a&gt;), Gajinder Singh&amp;nbsp;(&lt;a href=&quot;https://github.com/g11tech&quot;&gt;@g11tech&lt;/a&gt;), Ansgar Dietrichs&amp;nbsp;(&lt;a href=&quot;https://github.com/adietrichs&quot;&gt;@adietrichs&lt;/a&gt;), Gottfried Herold&amp;nbsp;(&lt;a href=&quot;https://github.com/GottfriedHerold&quot;&gt;@GottfriedHerold&lt;/a&gt;), Jamie Lokier&amp;nbsp;(&lt;a href=&quot;https://github.com/jlokier&quot;&gt;@jlokier&lt;/a&gt;), Tanishq Jasoria&amp;nbsp;(&lt;a href=&quot;https://github.com/tanishqjasoria&quot;&gt;@tanishqjasoria&lt;/a&gt;), Parithosh Jayanthi&amp;nbsp;(&lt;a href=&quot;https://github.com/parithosh&quot;&gt;@parithosh&lt;/a&gt;), Gabriel Rocheleau&amp;nbsp;(&lt;a href=&quot;https://github.com/gabrocheleau&quot;&gt;@gabrocheleau&lt;/a&gt;), Karim Taam&amp;nbsp;(&lt;a href=&quot;https://github.com/matkt&quot;&gt;@matkt&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7749&quot;&gt;7749&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Add wallet_signIntendedValidatorData method&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Yamen Merhi&amp;nbsp;(&lt;a href=&quot;https://github.com/YamenMerhi&quot;&gt;@YamenMerhi&lt;/a&gt;), Patronum Labs&amp;nbsp;(&lt;a href=&quot;https://github.com/Patronum-Labs&quot;&gt;@Patronum-Labs&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7754&quot;&gt;7754&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Tamperproof Extension Wallets API (TWIST)&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Erik Marks&amp;nbsp;(&lt;a href=&quot;https://github.com/remarks&quot;&gt;@remarks&lt;/a&gt;), Guillaume Grosbois&amp;nbsp;(&lt;a href=&quot;https://github.com/uni-guillaume&quot;&gt;@uni-guillaume&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7760&quot;&gt;7760&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Minimal Upgradeable Proxies&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Atarpara&amp;nbsp;(&lt;a href=&quot;https://github.com/Atarpara&quot;&gt;@Atarpara&lt;/a&gt;), JT Riley&amp;nbsp;(&lt;a href=&quot;https://github.com/jtriley-eth&quot;&gt;@jtriley-eth&lt;/a&gt;), Thomas&amp;nbsp;(&lt;a href=&quot;https://github.com/0xth0mas&quot;&gt;@0xth0mas&lt;/a&gt;), xiaobaiskill&amp;nbsp;(&lt;a href=&quot;https://github.com/xiaobaiskill&quot;&gt;@xiaobaiskill&lt;/a&gt;), Vectorized&amp;nbsp;(&lt;a href=&quot;https://github.com/Vectorized&quot;&gt;@Vectorized&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7765&quot;&gt;7765&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Privileged Non-Fungible Tokens Tied To RWA&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;frank (@frankmint2024)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:frank@mintchain.io&quot;&gt;frank@mintchain.io&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7766&quot;&gt;7766&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Signature Aggregation for ERC-4337&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Yoav Weiss&amp;nbsp;(&lt;a href=&quot;https://github.com/yoavw&quot;&gt;@yoavw&lt;/a&gt;), Dror Tirosh&amp;nbsp;(&lt;a href=&quot;https://github.com/drortirosh&quot;&gt;@drortirosh&lt;/a&gt;), Shahaf Nacson&amp;nbsp;(&lt;a href=&quot;https://github.com/shahafn&quot;&gt;@shahafn&lt;/a&gt;), Alex Forshtat&amp;nbsp;(&lt;a href=&quot;https://github.com/forshtat&quot;&gt;@forshtat&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7769&quot;&gt;7769&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;JSON-RPC API for ERC-4337&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Yoav Weiss&amp;nbsp;(&lt;a href=&quot;https://github.com/yoavw&quot;&gt;@yoavw&lt;/a&gt;), Dror Tirosh&amp;nbsp;(&lt;a href=&quot;https://github.com/drortirosh&quot;&gt;@drortirosh&lt;/a&gt;), Shahaf Nacson&amp;nbsp;(&lt;a href=&quot;https://github.com/shahafn&quot;&gt;@shahafn&lt;/a&gt;), Alex Forshtat&amp;nbsp;(&lt;a href=&quot;https://github.com/forshtat&quot;&gt;@forshtat&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7770&quot;&gt;7770&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Fractional Reserve Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Yaron Velner&amp;nbsp;(&lt;a href=&quot;https://github.com/yaronvel&quot;&gt;@yaronvel&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7773&quot;&gt;7773&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hardfork Meta - Glamsterdam&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Tim Beiko&amp;nbsp;(&lt;a href=&quot;https://github.com/timbeiko&quot;&gt;@timbeiko&lt;/a&gt;), Alex Stokes&amp;nbsp;(&lt;a href=&quot;https://github.com/ralexstokes&quot;&gt;@ralexstokes&lt;/a&gt;), Ansgar Dietrichs&amp;nbsp;(&lt;a href=&quot;https://github.com/adietrichs&quot;&gt;@adietrichs&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7774&quot;&gt;7774&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Cache invalidation in ERC-5219 mode Web3 URL&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nicolas Deschildre&amp;nbsp;(&lt;a href=&quot;https://github.com/nand2&quot;&gt;@nand2&lt;/a&gt;), Sam Wilson&amp;nbsp;(&lt;a href=&quot;https://github.com/SamWilsn&quot;&gt;@SamWilsn&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7778&quot;&gt;7778&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Block Gas Accounting without Refunds&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ben Adams&amp;nbsp;(&lt;a href=&quot;https://github.com/benaadams&quot;&gt;@benaadams&lt;/a&gt;), Toni Wahrstätter&amp;nbsp;(&lt;a href=&quot;https://github.com/nerolation&quot;&gt;@nerolation&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7779&quot;&gt;7779&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Interoperable Delegated Accounts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;David Kim&amp;nbsp;(&lt;a href=&quot;https://github.com/PowerStream3604&quot;&gt;@PowerStream3604&lt;/a&gt;), Richard Meissner&amp;nbsp;(&lt;a href=&quot;https://github.com/rmeissner&quot;&gt;@rmeissner&lt;/a&gt;), Akshay Patel&amp;nbsp;(&lt;a href=&quot;https://github.com/akshay-ap&quot;&gt;@akshay-ap&lt;/a&gt;), Joshua Kim&amp;nbsp;(&lt;a href=&quot;https://github.com/LightningHun&quot;&gt;@LightningHun&lt;/a&gt;), Fangting&amp;nbsp;(&lt;a href=&quot;https://github.com/trinity-0111&quot;&gt;@trinity-0111&lt;/a&gt;), Yoav Weiss&amp;nbsp;(&lt;a href=&quot;https://github.com/yoavw&quot;&gt;@yoavw&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7780&quot;&gt;7780&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Validation Module Extension for ERC-7579&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;zeroknots&amp;nbsp;(&lt;a href=&quot;https://github.com/zeroknots&quot;&gt;@zeroknots&lt;/a&gt;), Konrad Kopp&amp;nbsp;(&lt;a href=&quot;https://github.com/kopy-kat&quot;&gt;@kopy-kat&lt;/a&gt;), Taek Lee&amp;nbsp;(&lt;a href=&quot;https://github.com/leekt&quot;&gt;@leekt&lt;/a&gt;), Fil Makarov&amp;nbsp;(&lt;a href=&quot;https://github.com/filmakarov&quot;&gt;@filmakarov&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7782&quot;&gt;7782&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Reduce Block Latency&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ben Adams&amp;nbsp;(&lt;a href=&quot;https://github.com/benaadams&quot;&gt;@benaadams&lt;/a&gt;), Dankrad Feist&amp;nbsp;(&lt;a href=&quot;https://github.com/dankrad&quot;&gt;@dankrad&lt;/a&gt;), Maria Inês Silva&amp;nbsp;(&lt;a href=&quot;https://github.com/misilva73&quot;&gt;@misilva73&lt;/a&gt;), Paul Harris&amp;nbsp;(&lt;a href=&quot;https://github.com/rolfyone&quot;&gt;@rolfyone&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7785&quot;&gt;7785&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Onchain registration of chain identifiers&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Marco Stronati&amp;nbsp;(&lt;a href=&quot;https://github.com/paracetamolo&quot;&gt;@paracetamolo&lt;/a&gt;), Jeff Lau&amp;nbsp;(&lt;a href=&quot;https://github.com/jefflau&quot;&gt;@jefflau&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7787&quot;&gt;7787&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Soulbound Degradable Governance&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Guilherme Neves&amp;nbsp;(&lt;a href=&quot;https://github.com/0xneves&quot;&gt;@0xneves&lt;/a&gt;), Rafael Castaneda&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:rafaelcastaneda@gmail.com&quot;&gt;rafaelcastaneda@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7791&quot;&gt;7791&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;GAS2ETH opcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Charles Cooper&amp;nbsp;(&lt;a href=&quot;https://github.com/charles-cooper&quot;&gt;@charles-cooper&lt;/a&gt;), pcaversaccio&amp;nbsp;(&lt;a href=&quot;https://github.com/pcaversaccio&quot;&gt;@pcaversaccio&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7794&quot;&gt;7794&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Grant Registry&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Guilherme Neves&amp;nbsp;(&lt;a href=&quot;https://github.com/0xneves&quot;&gt;@0xneves&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7795&quot;&gt;7795&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Wallet Call Token Capabilities&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Agustín Aguilar&amp;nbsp;(&lt;a href=&quot;https://github.com/agusx1211&quot;&gt;@agusx1211&lt;/a&gt;), Michael Standen&amp;nbsp;(&lt;a href=&quot;https://github.com/ScreamingHawk&quot;&gt;@ScreamingHawk&lt;/a&gt;), Peter Kieltyka&amp;nbsp;(&lt;a href=&quot;https://github.com/pkieltyka&quot;&gt;@pkieltyka&lt;/a&gt;), William Hua&amp;nbsp;(&lt;a href=&quot;https://github.com/attente&quot;&gt;@attente&lt;/a&gt;), Philippe Castonguay&amp;nbsp;(&lt;a href=&quot;https://github.com/PhABC&quot;&gt;@PhABC&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7796&quot;&gt;7796&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Conditional send transaction RPC&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Dror Tirosh&amp;nbsp;(&lt;a href=&quot;https://github.com/drortirosh&quot;&gt;@drortirosh&lt;/a&gt;), Yoav Weiss&amp;nbsp;(&lt;a href=&quot;https://github.com/yoavw&quot;&gt;@yoavw&lt;/a&gt;), Alex Forshtat&amp;nbsp;(&lt;a href=&quot;https://github.com/forshtat&quot;&gt;@forshtat&lt;/a&gt;), Shahaf Nacson&amp;nbsp;(&lt;a href=&quot;https://github.com/shahafn&quot;&gt;@shahafn&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7799&quot;&gt;7799&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;System logs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Etan Kissling&amp;nbsp;(&lt;a href=&quot;https://github.com/etan-status&quot;&gt;@etan-status&lt;/a&gt;), Gajinder Singh&amp;nbsp;(&lt;a href=&quot;https://github.com/g11tech&quot;&gt;@g11tech&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7801&quot;&gt;7801&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;etha - Sharded Blocks Subprotocol&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ahmad Bitar (@smartprogrammer93)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:smartprogrammer@windowslive.com&quot;&gt;smartprogrammer@windowslive.com&lt;/a&gt;&amp;gt;, Giulio Rebuffo&amp;nbsp;(&lt;a href=&quot;https://github.com/Giulio2002&quot;&gt;@Giulio2002&lt;/a&gt;), Gary Schulte (@garyschulte)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:garyschulte@gmail.com&quot;&gt;garyschulte@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7802&quot;&gt;7802&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Token With Mint/Burn Access Across Chains&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;skeletor&amp;nbsp;(&lt;a href=&quot;https://github.com/skeletor-spaceman&quot;&gt;@skeletor-spaceman&lt;/a&gt;), parti&amp;nbsp;(&lt;a href=&quot;https://github.com/0xParticle&quot;&gt;@0xParticle&lt;/a&gt;), joxes&amp;nbsp;(&lt;a href=&quot;https://github.com/Joxess&quot;&gt;@Joxess&lt;/a&gt;), ng&amp;nbsp;(&lt;a href=&quot;https://github.com/0xng&quot;&gt;@0xng&lt;/a&gt;), agus duha&amp;nbsp;(&lt;a href=&quot;https://github.com/agusduha&quot;&gt;@agusduha&lt;/a&gt;), disco&amp;nbsp;(&lt;a href=&quot;https://github.com/0xDiscotech&quot;&gt;@0xDiscotech&lt;/a&gt;), gotzen&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:gotzen@defi.sucks&quot;&gt;gotzen@defi.sucks&lt;/a&gt;&amp;gt;, 0age&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:0age@uniswap.org&quot;&gt;0age@uniswap.org&lt;/a&gt;&amp;gt;, Mark Tyneway&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:mark@oplabs.co&quot;&gt;mark@oplabs.co&lt;/a&gt;&amp;gt;, Zain Bacchus&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:zain@oplabs.co&quot;&gt;zain@oplabs.co&lt;/a&gt;&amp;gt;, Matt Solomon&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:msolomon@oplabs.co&quot;&gt;msolomon@oplabs.co&lt;/a&gt;&amp;gt;, Maurelian&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:maurelian@protonmail.ch&quot;&gt;maurelian@protonmail.ch&lt;/a&gt;&amp;gt;, Blaine Malone&amp;nbsp;(&lt;a href=&quot;https://github.com/blmalone&quot;&gt;@blmalone&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7803&quot;&gt;7803&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EIP-712 Extensions for Account Abstraction&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Francisco Giordano&amp;nbsp;(&lt;a href=&quot;https://github.com/frangio&quot;&gt;@frangio&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7804&quot;&gt;7804&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Withdrawal Credential Update Request&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Lucas Saldanha&amp;nbsp;(&lt;a href=&quot;https://github.com/lucassaldanha&quot;&gt;@lucassaldanha&lt;/a&gt;), Mikhail Kalinin&amp;nbsp;(&lt;a href=&quot;https://github.com/mkalinin&quot;&gt;@mkalinin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7805&quot;&gt;7805&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Fork-choice enforced Inclusion Lists (FOCIL)&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Thomas Thiery (@soispoke)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:thomas.thiery@ethereum.org&quot;&gt;thomas.thiery@ethereum.org&lt;/a&gt;&amp;gt;, Francesco D&apos;Amato&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:francesco.damato@ethereum.org&quot;&gt;francesco.damato@ethereum.org&lt;/a&gt;&amp;gt;, Julian Ma&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:julian.ma@ethereum.org&quot;&gt;julian.ma@ethereum.org&lt;/a&gt;&amp;gt;, Barnabé Monnot&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:barnabe.monnot@ethereum.org&quot;&gt;barnabe.monnot@ethereum.org&lt;/a&gt;&amp;gt;, Terence Tsao&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:ttsao@offchainlabs.com&quot;&gt;ttsao@offchainlabs.com&lt;/a&gt;&amp;gt;, Jacob Kaufmann&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jacob.kaufmann@ethereum.org&quot;&gt;jacob.kaufmann@ethereum.org&lt;/a&gt;&amp;gt;, Jihoon Song&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jihoon.song@ethereum.org&quot;&gt;jihoon.song@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7806&quot;&gt;7806&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Minimal intent-centric EOA smart account&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;hellohanchen&amp;nbsp;(&lt;a href=&quot;https://github.com/hellohanchen&quot;&gt;@hellohanchen&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7807&quot;&gt;7807&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;SSZ execution blocks&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Etan Kissling&amp;nbsp;(&lt;a href=&quot;https://github.com/etan-status&quot;&gt;@etan-status&lt;/a&gt;), Gajinder Singh&amp;nbsp;(&lt;a href=&quot;https://github.com/g11tech&quot;&gt;@g11tech&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7811&quot;&gt;7811&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Wallet Asset Discovery&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Luka Isailovic&amp;nbsp;(&lt;a href=&quot;https://github.com/lukaisailovic&quot;&gt;@lukaisailovic&lt;/a&gt;), Konrad Kopp&amp;nbsp;(&lt;a href=&quot;https://github.com/kopy-kat&quot;&gt;@kopy-kat&lt;/a&gt;), Derek Rein&amp;nbsp;(&lt;a href=&quot;https://github.com/arein&quot;&gt;@arein&lt;/a&gt;), Chris Smith&amp;nbsp;(&lt;a href=&quot;https://github.com/chris13524&quot;&gt;@chris13524&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7819&quot;&gt;7819&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;SETDELEGATE instruction&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Hadrien Croubois&amp;nbsp;(&lt;a href=&quot;https://github.com/amxx&quot;&gt;@amxx&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7821&quot;&gt;7821&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Minimal Batch Executor Interface&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vectorized&amp;nbsp;(&lt;a href=&quot;https://github.com/Vectorized&quot;&gt;@Vectorized&lt;/a&gt;), Jake Moxey&amp;nbsp;(&lt;a href=&quot;https://github.com/jxom&quot;&gt;@jxom&lt;/a&gt;), Hadrien Croubois&amp;nbsp;(&lt;a href=&quot;https://github.com/Amxx&quot;&gt;@Amxx&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7827&quot;&gt;7827&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;JSON Contract with Value Version Control&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;lex-clinic&amp;nbsp;(&lt;a href=&quot;https://github.com/lex-clinic&quot;&gt;@lex-clinic&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7828&quot;&gt;7828&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Interoperable Names&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Sam Kaufman&amp;nbsp;(&lt;a href=&quot;https://github.com/SampkaML&quot;&gt;@SampkaML&lt;/a&gt;), Marco Stronati&amp;nbsp;(&lt;a href=&quot;https://github.com/paracetamolo&quot;&gt;@paracetamolo&lt;/a&gt;), Yuliya Alexiev&amp;nbsp;(&lt;a href=&quot;https://github.com/yuliyaalexiev&quot;&gt;@yuliyaalexiev&lt;/a&gt;), Jeff Lau&amp;nbsp;(&lt;a href=&quot;https://github.com/jefflau&quot;&gt;@jefflau&lt;/a&gt;), Sam Wilson&amp;nbsp;(&lt;a href=&quot;https://github.com/samwilsn&quot;&gt;@samwilsn&lt;/a&gt;), Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Teddy&amp;nbsp;(&lt;a href=&quot;https://github.com/0xteddybear&quot;&gt;@0xteddybear&lt;/a&gt;), Joxes&amp;nbsp;(&lt;a href=&quot;https://github.com/Joxess&quot;&gt;@Joxess&lt;/a&gt;), Racu&amp;nbsp;(&lt;a href=&quot;https://github.com/0xRacoon&quot;&gt;@0xRacoon&lt;/a&gt;), Skeletor Spaceman&amp;nbsp;(&lt;a href=&quot;https://github.com/0xskeletor-spaceman&quot;&gt;@0xskeletor-spaceman&lt;/a&gt;), TiTi&amp;nbsp;(&lt;a href=&quot;https://github.com/0xtiti&quot;&gt;@0xtiti&lt;/a&gt;), Gori&amp;nbsp;(&lt;a href=&quot;https://github.com/0xGorilla&quot;&gt;@0xGorilla&lt;/a&gt;), Ardy&amp;nbsp;(&lt;a href=&quot;https://github.com/0xArdy&quot;&gt;@0xArdy&lt;/a&gt;), Onizuka&amp;nbsp;(&lt;a href=&quot;https://github.com/onizuka-wl&quot;&gt;@onizuka-wl&lt;/a&gt;), Lumi&amp;nbsp;(&lt;a href=&quot;https://github.com/oxlumi&quot;&gt;@oxlumi&lt;/a&gt;), Moebius&amp;nbsp;(&lt;a href=&quot;https://github.com/0xmoebius&quot;&gt;@0xmoebius&lt;/a&gt;), Thomas Clowes&amp;nbsp;(&lt;a href=&quot;https://github.com/clowestab&quot;&gt;@clowestab&lt;/a&gt;), Prem Makeig&amp;nbsp;(&lt;a href=&quot;https://github.com/nxt3d&quot;&gt;@nxt3d&lt;/a&gt;), Mono&amp;nbsp;(&lt;a href=&quot;https://github.com/0xMonoAx&quot;&gt;@0xMonoAx&lt;/a&gt;), Orca&amp;nbsp;(&lt;a href=&quot;https://github.com/0xrcinus&quot;&gt;@0xrcinus&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7831&quot;&gt;7831&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Multi-Chain Addressing&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Sam Wilson (@SamWilsn)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:sam@binarycake.ca&quot;&gt;sam@binarycake.ca&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7836&quot;&gt;7836&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Wallet Call Preparation API&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Lukas Rosario&amp;nbsp;(&lt;a href=&quot;https://github.com/lukasrosario&quot;&gt;@lukasrosario&lt;/a&gt;), Conner Swenberg&amp;nbsp;(&lt;a href=&quot;https://github.com/ilikesymmetry&quot;&gt;@ilikesymmetry&lt;/a&gt;), Adam Hodges&amp;nbsp;(&lt;a href=&quot;https://github.com/ajhodges&quot;&gt;@ajhodges&lt;/a&gt;), Paaras Bhandari&amp;nbsp;(&lt;a href=&quot;https://github.com/paarasbhandari&quot;&gt;@paarasbhandari&lt;/a&gt;), Jake Moxey&amp;nbsp;(&lt;a href=&quot;https://github.com/jxom&quot;&gt;@jxom&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7841&quot;&gt;7841&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Cross-chain Message Format and Mailbox&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ellie Davidson&amp;nbsp;(&lt;a href=&quot;https://github.com/elliedavidson&quot;&gt;@elliedavidson&lt;/a&gt;), Alex Xiong&amp;nbsp;(&lt;a href=&quot;https://github.com/alxiong&quot;&gt;@alxiong&lt;/a&gt;), Philippe Camacho&amp;nbsp;(&lt;a href=&quot;https://github.com/philippecamacho&quot;&gt;@philippecamacho&lt;/a&gt;), and Ben Fisch&amp;nbsp;(&lt;a href=&quot;https://github.com/benafisch&quot;&gt;@benafisch&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7843&quot;&gt;7843&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;SLOTNUM opcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Marc Harvey-Hill&amp;nbsp;(&lt;a href=&quot;https://github.com/Marchhill&quot;&gt;@Marchhill&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7845&quot;&gt;7845&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Universal Orchestrator RPC&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Kieran Goodary&amp;nbsp;(&lt;a href=&quot;https://github.com/IAmKio&quot;&gt;@IAmKio&lt;/a&gt;), Pillar Wallet&amp;nbsp;(&lt;a href=&quot;https://github.com/pillarwallet&quot;&gt;@pillarwallet&lt;/a&gt;), Luke Wickens&amp;nbsp;(&lt;a href=&quot;https://github.com/lbw33&quot;&gt;@lbw33&lt;/a&gt;), Rana Khoury&amp;nbsp;(&lt;a href=&quot;https://github.com/RanaBug&quot;&gt;@RanaBug&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7846&quot;&gt;7846&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Wallet Connection API&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Conner Swenberg&amp;nbsp;(&lt;a href=&quot;https://github.com/ilikesymmetry&quot;&gt;@ilikesymmetry&lt;/a&gt;), Jake Moxey&amp;nbsp;(&lt;a href=&quot;https://github.com/jxom&quot;&gt;@jxom&lt;/a&gt;), Lukas Rosario&amp;nbsp;(&lt;a href=&quot;https://github.com/lukasrosario&quot;&gt;@lukasrosario&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7847&quot;&gt;7847&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Social Media NFTs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Juntilla (@nickjuntilla)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:nick@ownerfy.com&quot;&gt;nick@ownerfy.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7848&quot;&gt;7848&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;On-chain upgrade signaling&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;William Entriken&amp;nbsp;(&lt;a href=&quot;https://github.com/fulldecent&quot;&gt;@fulldecent&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7851&quot;&gt;7851&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Deactivate a Delegated EOA&amp;apos;s Key&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Liyi Guo&amp;nbsp;(&lt;a href=&quot;https://github.com/colinlyguo&quot;&gt;@colinlyguo&lt;/a&gt;), Nicolas Consigny&amp;nbsp;(&lt;a href=&quot;https://github.com/nconsigny&quot;&gt;@nconsigny&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7856&quot;&gt;7856&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Chain-Specific Payment Requests&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jack Chuma&amp;nbsp;(&lt;a href=&quot;https://github.com/jackchuma&quot;&gt;@jackchuma&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7861&quot;&gt;7861&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-721 Verifiable Credential Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Valerio Massimo Camaiani&amp;nbsp;(&lt;a href=&quot;https://github.com/vmc-crossmint&quot;&gt;@vmc-crossmint&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7862&quot;&gt;7862&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Delayed State Root&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Charlie Noyes&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:charlie@paradigm.xyz&quot;&gt;charlie@paradigm.xyz&lt;/a&gt;&amp;gt;, Dan Robinson&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:dan@paradigm.xyz&quot;&gt;dan@paradigm.xyz&lt;/a&gt;&amp;gt;, Justin Drake&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:justin@ethereum.org&quot;&gt;justin@ethereum.org&lt;/a&gt;&amp;gt;, Toni Wahrstätter&amp;nbsp;(&lt;a href=&quot;https://github.com/nerolation&quot;&gt;@nerolation&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7863&quot;&gt;7863&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Block-level Warming&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Toni Wahrstätter&amp;nbsp;(&lt;a href=&quot;https://github.com/nerolation&quot;&gt;@nerolation&lt;/a&gt;), Jochem Brouwer&amp;nbsp;(&lt;a href=&quot;https://github.com/jochem-brouwer&quot;&gt;@jochem-brouwer&lt;/a&gt;), Alex Stokes&amp;nbsp;(&lt;a href=&quot;https://github.com/ralexstokes&quot;&gt;@ralexstokes&lt;/a&gt;), Ansgar Dietrichs&amp;nbsp;(&lt;a href=&quot;https://github.com/adietrichs&quot;&gt;@adietrichs&lt;/a&gt;), Yoav Weiss&amp;nbsp;(&lt;a href=&quot;https://github.com/yoavw&quot;&gt;@yoavw&lt;/a&gt;), Alex Forshtat&amp;nbsp;(&lt;a href=&quot;https://github.com/forshtat&quot;&gt;@forshtat&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7864&quot;&gt;7864&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Ethereum state using a unified binary tree&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Guillaume Ballet&amp;nbsp;(&lt;a href=&quot;https://github.com/gballet&quot;&gt;@gballet&lt;/a&gt;), Dankrad Feist&amp;nbsp;(&lt;a href=&quot;https://github.com/dankrad&quot;&gt;@dankrad&lt;/a&gt;), Ignacio Hagopian&amp;nbsp;(&lt;a href=&quot;https://github.com/jsign&quot;&gt;@jsign&lt;/a&gt;), Kevaundray Wedderburn&amp;nbsp;(&lt;a href=&quot;https://github.com/kevaundray&quot;&gt;@kevaundray&lt;/a&gt;), Tanishq Jasoria&amp;nbsp;(&lt;a href=&quot;https://github.com/tanishqjasoria&quot;&gt;@tanishqjasoria&lt;/a&gt;), Gajinder Singh&amp;nbsp;(&lt;a href=&quot;https://github.com/g11tech&quot;&gt;@g11tech&lt;/a&gt;), Danno Ferrin&amp;nbsp;(&lt;a href=&quot;https://github.com/shemnon&quot;&gt;@shemnon&lt;/a&gt;), Piper Merriam&amp;nbsp;(&lt;a href=&quot;https://github.com/pipermerriam&quot;&gt;@pipermerriam&lt;/a&gt;), Gottfried Herold&amp;nbsp;(&lt;a href=&quot;https://github.com/GottfriedHerold&quot;&gt;@GottfriedHerold&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7871&quot;&gt;7871&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Wallet Signing API&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Lukas Rosario&amp;nbsp;(&lt;a href=&quot;https://github.com/lukasrosario&quot;&gt;@lukasrosario&lt;/a&gt;), Jake Moxey&amp;nbsp;(&lt;a href=&quot;https://github.com/jxom&quot;&gt;@jxom&lt;/a&gt;), Cody Crozier&amp;nbsp;(&lt;a href=&quot;https://github.com/wcrozier12&quot;&gt;@wcrozier12&lt;/a&gt;), Conner Swenberg&amp;nbsp;(&lt;a href=&quot;https://github.com/ilikesymmetry&quot;&gt;@ilikesymmetry&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7876&quot;&gt;7876&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Ethereum Network Configuration for DApps&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Bogdan Gusiev&amp;nbsp;(&lt;a href=&quot;https://github.com/bogdan&quot;&gt;@bogdan&lt;/a&gt;), Sergey Bomko&amp;nbsp;(&lt;a href=&quot;https://github.com/aquiladev&quot;&gt;@aquiladev&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7884&quot;&gt;7884&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Operation Router&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Lucas Picollo&amp;nbsp;(&lt;a href=&quot;https://github.com/pikonha&quot;&gt;@pikonha&lt;/a&gt;), Alex Netto&amp;nbsp;(&lt;a href=&quot;https://github.com/alextnetto&quot;&gt;@alextnetto&lt;/a&gt;), Nick Johnson&amp;nbsp;(&lt;a href=&quot;https://github.com/arachnid&quot;&gt;@arachnid&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7885&quot;&gt;7885&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Precompile for NTT operations&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Renaud Dubois&amp;nbsp;(&lt;a href=&quot;https://github.com/rdubois-crypto&quot;&gt;@rdubois-crypto&lt;/a&gt;), Simon Masson&amp;nbsp;(&lt;a href=&quot;https://github.com/simonmasson&quot;&gt;@simonmasson&lt;/a&gt;), Yoon Hyoung Lee&amp;nbsp;(&lt;a href=&quot;https://github.com/yhl125&quot;&gt;@yhl125&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7887&quot;&gt;7887&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Cancelation for ERC-7540 Tokenized Vaults&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jeroen Offerijns&amp;nbsp;(&lt;a href=&quot;https://github.com/hieronx&quot;&gt;@hieronx&lt;/a&gt;), Vikram Arun&amp;nbsp;(&lt;a href=&quot;https://github.com/vikramarun&quot;&gt;@vikramarun&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7888&quot;&gt;7888&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Crosschain Broadcaster&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Henry Arneson&amp;nbsp;(&lt;a href=&quot;https://github.com/godzillaba&quot;&gt;@godzillaba&lt;/a&gt;), Chris Buckland&amp;nbsp;(&lt;a href=&quot;https://github.com/yahgwai&quot;&gt;@yahgwai&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7891&quot;&gt;7891&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Splitting and Merging of NFTs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nitin Bhagat (@nitin312)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:bhagatnitin312@gmail.com&quot;&gt;bhagatnitin312@gmail.com&lt;/a&gt;&amp;gt;, JongWook Bae&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:bae@cwnu.ac.kr&quot;&gt;bae@cwnu.ac.kr&lt;/a&gt;&amp;gt;, Su-Hyun Lee&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:sleepl@changwon.ac.kr&quot;&gt;sleepl@changwon.ac.kr&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7895&quot;&gt;7895&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;API for Hierarchical Accounts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Wilson Cusack&amp;nbsp;(&lt;a href=&quot;https://github.com/wilsoncusack&quot;&gt;@wilsoncusack&lt;/a&gt;), Jake Feldman&amp;nbsp;(&lt;a href=&quot;https://github.com/jakefeldman&quot;&gt;@jakefeldman&lt;/a&gt;), Montana Wong&amp;nbsp;(&lt;a href=&quot;https://github.com/montycheese&quot;&gt;@montycheese&lt;/a&gt;), Felix Zhang&amp;nbsp;(&lt;a href=&quot;https://github.com/fan-zhang-sv&quot;&gt;@fan-zhang-sv&lt;/a&gt;), Jake Moxey&amp;nbsp;(&lt;a href=&quot;https://github.com/jxom&quot;&gt;@jxom&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7902&quot;&gt;7902&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Wallet Capabilities for Account Abstraction&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Yoav Weiss&amp;nbsp;(&lt;a href=&quot;https://github.com/yoavw&quot;&gt;@yoavw&lt;/a&gt;), Alex Forshtat&amp;nbsp;(&lt;a href=&quot;https://github.com/forshtat&quot;&gt;@forshtat&lt;/a&gt;), Dror Tirosh&amp;nbsp;(&lt;a href=&quot;https://github.com/drortirosh&quot;&gt;@drortirosh&lt;/a&gt;), Shahaf Nacson&amp;nbsp;(&lt;a href=&quot;https://github.com/shahafn&quot;&gt;@shahafn&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7904&quot;&gt;7904&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Compute Gas Cost Increase&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jacek Glen&amp;nbsp;(&lt;a href=&quot;https://github.com/JacekGlen&quot;&gt;@JacekGlen&lt;/a&gt;), Lukasz Glen&amp;nbsp;(&lt;a href=&quot;https://github.com/lukasz-glen&quot;&gt;@lukasz-glen&lt;/a&gt;), Maria Silva&amp;nbsp;(&lt;a href=&quot;https://github.com/misilva73&quot;&gt;@misilva73&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7906&quot;&gt;7906&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Transaction Assertions via State Diff Opcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Forshtat&amp;nbsp;(&lt;a href=&quot;https://github.com/forshtat&quot;&gt;@forshtat&lt;/a&gt;), Shahaf Nacson&amp;nbsp;(&lt;a href=&quot;https://github.com/shahafn&quot;&gt;@shahafn&lt;/a&gt;), Dror Tirosh&amp;nbsp;(&lt;a href=&quot;https://github.com/drortirosh&quot;&gt;@drortirosh&lt;/a&gt;), Yoav Weiss&amp;nbsp;(&lt;a href=&quot;https://github.com/yoavw&quot;&gt;@yoavw&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7907&quot;&gt;7907&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Meter Contract Code Size And Increase Limit&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Charles Cooper&amp;nbsp;(&lt;a href=&quot;https://github.com/charles-cooper&quot;&gt;@charles-cooper&lt;/a&gt;), Qi Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/qizhou&quot;&gt;@qizhou&lt;/a&gt;), Matt&amp;nbsp;(&lt;a href=&quot;https://github.com/lightclient&quot;&gt;@lightclient&lt;/a&gt;), Dragan Rakita&amp;nbsp;(&lt;a href=&quot;https://github.com/rakita&quot;&gt;@rakita&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7911&quot;&gt;7911&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Scaling Ethereum with a Perceptron Tree ZKP&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ryo Ha (@sopia19910)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:sopia19910@gmail.com&quot;&gt;sopia19910@gmail.com&lt;/a&gt;&amp;gt;, Khajiev Nizomjon (@khajievN)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:nizom7812@gmail.com&quot;&gt;nizom7812@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7920&quot;&gt;7920&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Composite EIP-712 Signatures&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Sola Ogunsakin&amp;nbsp;(&lt;a href=&quot;https://github.com/sola92&quot;&gt;@sola92&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7923&quot;&gt;7923&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Linear, Page-Based Memory Costing&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Charles Cooper&amp;nbsp;(&lt;a href=&quot;https://github.com/charles-cooper&quot;&gt;@charles-cooper&lt;/a&gt;), Qi Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/qizhou&quot;&gt;@qizhou&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7928&quot;&gt;7928&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Block-Level Access Lists&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Toni Wahrstätter&amp;nbsp;(&lt;a href=&quot;https://github.com/nerolation&quot;&gt;@nerolation&lt;/a&gt;), Dankrad Feist&amp;nbsp;(&lt;a href=&quot;https://github.com/dankrad&quot;&gt;@dankrad&lt;/a&gt;), Francesco D`Amato&amp;nbsp;(&lt;a href=&quot;https://github.com/fradamt&quot;&gt;@fradamt&lt;/a&gt;), Jochem Brouwer&amp;nbsp;(&lt;a href=&quot;https://github.com/jochem-brouwer&quot;&gt;@jochem-brouwer&lt;/a&gt;), Ignacio Hagopian&amp;nbsp;(&lt;a href=&quot;https://github.com/jsign&quot;&gt;@jsign&lt;/a&gt;), Felipe Selmo&amp;nbsp;(&lt;a href=&quot;https://github.com/fselmo&quot;&gt;@fselmo&lt;/a&gt;), Rahul&amp;nbsp;(&lt;a href=&quot;https://github.com/raxhvl&quot;&gt;@raxhvl&lt;/a&gt;), Stefan&amp;nbsp;(&lt;a href=&quot;https://github.com/qu0b&quot;&gt;@qu0b&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7929&quot;&gt;7929&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;PermaLink Asset Bound Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Mihai Onila&amp;nbsp;(&lt;a href=&quot;https://github.com/MihaiORO&quot;&gt;@MihaiORO&lt;/a&gt;), Nick Zeman&amp;nbsp;(&lt;a href=&quot;https://github.com/NickZCZ&quot;&gt;@NickZCZ&lt;/a&gt;), Narcis Cotaie&amp;nbsp;(&lt;a href=&quot;https://github.com/NarcisCRO&quot;&gt;@NarcisCRO&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7930&quot;&gt;7930&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Interoperable Addresses&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Teddy&amp;nbsp;(&lt;a href=&quot;https://github.com/0xteddybear&quot;&gt;@0xteddybear&lt;/a&gt;), Joxes&amp;nbsp;(&lt;a href=&quot;https://github.com/0xJoxess&quot;&gt;@0xJoxess&lt;/a&gt;), Nick Johnson&amp;nbsp;(&lt;a href=&quot;https://github.com/Arachnid&quot;&gt;@Arachnid&lt;/a&gt;), Francisco Giordano&amp;nbsp;(&lt;a href=&quot;https://github.com/frangio&quot;&gt;@frangio&lt;/a&gt;), Skeletor Spaceman&amp;nbsp;(&lt;a href=&quot;https://github.com/skeletor-spaceman&quot;&gt;@skeletor-spaceman&lt;/a&gt;), Racu&amp;nbsp;(&lt;a href=&quot;https://github.com/0xRacoon&quot;&gt;@0xRacoon&lt;/a&gt;), TiTi&amp;nbsp;(&lt;a href=&quot;https://github.com/0xtiti&quot;&gt;@0xtiti&lt;/a&gt;), Gori&amp;nbsp;(&lt;a href=&quot;https://github.com/0xGorilla&quot;&gt;@0xGorilla&lt;/a&gt;), Ardy&amp;nbsp;(&lt;a href=&quot;https://github.com/0xArdy&quot;&gt;@0xArdy&lt;/a&gt;), Onizuka&amp;nbsp;(&lt;a href=&quot;https://github.com/onizuka-wl&quot;&gt;@onizuka-wl&lt;/a&gt;), Sam Kaufman&amp;nbsp;(&lt;a href=&quot;https://github.com/SampkaML&quot;&gt;@SampkaML&lt;/a&gt;), Marco Stronati&amp;nbsp;(&lt;a href=&quot;https://github.com/paracetamolo&quot;&gt;@paracetamolo&lt;/a&gt;), Yuliya Alexiev&amp;nbsp;(&lt;a href=&quot;https://github.com/yuliyaalexiev&quot;&gt;@yuliyaalexiev&lt;/a&gt;), Jeff Lau&amp;nbsp;(&lt;a href=&quot;https://github.com/jefflau&quot;&gt;@jefflau&lt;/a&gt;), Sam Wilson&amp;nbsp;(&lt;a href=&quot;https://github.com/samwilsn&quot;&gt;@samwilsn&lt;/a&gt;), Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Thomas Clowes&amp;nbsp;(&lt;a href=&quot;https://github.com/clowestab&quot;&gt;@clowestab&lt;/a&gt;), Mono&amp;nbsp;(&lt;a href=&quot;https://github.com/0xMonoAx&quot;&gt;@0xMonoAx&lt;/a&gt;), Prem Makeig&amp;nbsp;(&lt;a href=&quot;https://github.com/nxt3d&quot;&gt;@nxt3d&lt;/a&gt;), Orca&amp;nbsp;(&lt;a href=&quot;https://github.com/0xrcinus&quot;&gt;@0xrcinus&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7932&quot;&gt;7932&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Secondary Signature Algorithms&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;James Kempton&amp;nbsp;(&lt;a href=&quot;https://github.com/SirSpudlington&quot;&gt;@SirSpudlington&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7937&quot;&gt;7937&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EVM64 - 64-bit mode EVM opcodes&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Wei Tang&amp;nbsp;(&lt;a href=&quot;https://github.com/sorpaas&quot;&gt;@sorpaas&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7940&quot;&gt;7940&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Ethereum Shah&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ameen Soleimani&amp;nbsp;(&lt;a href=&quot;https://github.com/ameensol&quot;&gt;@ameensol&lt;/a&gt;),  Gregory Markou&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7942&quot;&gt;7942&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Available Attestation&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Mingfei Zhang (@Mart1i1n)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:mingfei.zh@outlook.com&quot;&gt;mingfei.zh@outlook.com&lt;/a&gt;&amp;gt;, Rujia Li&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:rujia@tsinghua.edu.cn&quot;&gt;rujia@tsinghua.edu.cn&lt;/a&gt;&amp;gt;, Xueqian Lu&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:xueqian.lu@bitheart.org&quot;&gt;xueqian.lu@bitheart.org&lt;/a&gt;&amp;gt;, Sisi Duan&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:duansisi@tsinghua.edu.cn&quot;&gt;duansisi@tsinghua.edu.cn&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7946&quot;&gt;7946&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Unidirectional Wallet Uplink aka UWULink&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Moody Salem&amp;nbsp;(&lt;a href=&quot;https://github.com/moodysalem&quot;&gt;@moodysalem&lt;/a&gt;), Tina Zheng&amp;nbsp;(&lt;a href=&quot;https://github.com/tinaszheng&quot;&gt;@tinaszheng&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7947&quot;&gt;7947&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Account Abstraction Recovery Interface&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Artem Chystiakov (@arvolear)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:artem@rarilabs.com&quot;&gt;artem@rarilabs.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7949&quot;&gt;7949&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Genesis File Format&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Justin Florentine (@jflo)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:justin@florentine.us&quot;&gt;justin@florentine.us&lt;/a&gt;&amp;gt;, Jochem Brouwer (@jochem-brouwer)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jochem@ethereum.org&quot;&gt;jochem@ethereum.org&lt;/a&gt;&amp;gt;, Barnabas Busa (@barnabasbusa)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:bbusa@ethereum.org&quot;&gt;bbusa@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7954&quot;&gt;7954&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Increase Maximum Contract Size&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Giulio Rebuffo&amp;nbsp;(&lt;a href=&quot;https://github.com/Giulio2002&quot;&gt;@Giulio2002&lt;/a&gt;), Ben Adams&amp;nbsp;(&lt;a href=&quot;https://github.com/benaadams&quot;&gt;@benaadams&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7955&quot;&gt;7955&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Permissionless CREATE2 Factory&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nicholas Rodrigues Lordello&amp;nbsp;(&lt;a href=&quot;https://github.com/nlordell&quot;&gt;@nlordell&lt;/a&gt;), Richard Meissner&amp;nbsp;(&lt;a href=&quot;https://github.com/rmeissner&quot;&gt;@rmeissner&lt;/a&gt;), Valentin Seehausen&amp;nbsp;(&lt;a href=&quot;https://github.com/vseehausen&quot;&gt;@vseehausen&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7960&quot;&gt;7960&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EOF - Extended types section&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Wei Tang&amp;nbsp;(&lt;a href=&quot;https://github.com/sorpaas&quot;&gt;@sorpaas&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7961&quot;&gt;7961&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EVM64 - EOF code section&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Wei Tang&amp;nbsp;(&lt;a href=&quot;https://github.com/sorpaas&quot;&gt;@sorpaas&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7962&quot;&gt;7962&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Key Hash Based Tokens&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Tian&amp;nbsp;(&lt;a href=&quot;https://github.com/dugubuyan&quot;&gt;@dugubuyan&lt;/a&gt;), Zhixiong Pan&amp;nbsp;(&lt;a href=&quot;https://github.com/nake13&quot;&gt;@nake13&lt;/a&gt;), Geoffrey (@stbrahms)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:geoffrey@datadance.ai&quot;&gt;geoffrey@datadance.ai&lt;/a&gt;&amp;gt;, liyingxuan (@LiYingxuan)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:liyingxuan@datadance.ai&quot;&gt;liyingxuan@datadance.ai&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7964&quot;&gt;7964&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Crosschain EIP-712 Signatures&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ernesto García&amp;nbsp;(&lt;a href=&quot;https://github.com/ernestognw&quot;&gt;@ernestognw&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7965&quot;&gt;7965&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Proof-based Broadcast in ERC-7786 Gateways&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ernesto García&amp;nbsp;(&lt;a href=&quot;https://github.com/ernestognw&quot;&gt;@ernestognw&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7966&quot;&gt;7966&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;eth_sendRawTransactionSync Method&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Sam Battenally&amp;nbsp;(&lt;a href=&quot;https://github.com/SmoothBot&quot;&gt;@SmoothBot&lt;/a&gt;), Hai Nguyen&amp;nbsp;(&lt;a href=&quot;https://github.com/hai-rise&quot;&gt;@hai-rise&lt;/a&gt;), Thanh Nguyen&amp;nbsp;(&lt;a href=&quot;https://github.com/LampardNguyen234&quot;&gt;@LampardNguyen234&lt;/a&gt;), Loc Nguyen&amp;nbsp;(&lt;a href=&quot;https://github.com/silver-rise&quot;&gt;@silver-rise&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7968&quot;&gt;7968&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Owner-Authorized Token Transfer Protocol&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Julius Lauterbach&amp;nbsp;(&lt;a href=&quot;https://github.com/Julius278&quot;&gt;@Julius278&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7969&quot;&gt;7969&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;DomainKeys Identified Mail (DKIM) Registry&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Mike Fu&amp;nbsp;(&lt;a href=&quot;https://github.com/fumeng00mike&quot;&gt;@fumeng00mike&lt;/a&gt;), Matthew Yu&amp;nbsp;(&lt;a href=&quot;https://github.com/0xknon&quot;&gt;@0xknon&lt;/a&gt;), Ernesto García&amp;nbsp;(&lt;a href=&quot;https://github.com/ernestognw&quot;&gt;@ernestognw&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7971&quot;&gt;7971&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hard Limits for Transient Storage&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Charles Cooper&amp;nbsp;(&lt;a href=&quot;https://github.com/charles-cooper&quot;&gt;@charles-cooper&lt;/a&gt;), Ben Adams&amp;nbsp;(&lt;a href=&quot;https://github.com/benaadams&quot;&gt;@benaadams&lt;/a&gt;), Maria Silva&amp;nbsp;(&lt;a href=&quot;https://github.com/misilva73&quot;&gt;@misilva73&lt;/a&gt;), Jochem Brouwer&amp;nbsp;(&lt;a href=&quot;https://github.com/jochem-brouwer&quot;&gt;@jochem-brouwer&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7973&quot;&gt;7973&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Warm Account Write Metering&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Charles Cooper&amp;nbsp;(&lt;a href=&quot;https://github.com/charles-cooper&quot;&gt;@charles-cooper&lt;/a&gt;), Maria Silva&amp;nbsp;(&lt;a href=&quot;https://github.com/misilva73&quot;&gt;@misilva73&lt;/a&gt;), Ben Adams&amp;nbsp;(&lt;a href=&quot;https://github.com/benaadams&quot;&gt;@benaadams&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7975&quot;&gt;7975&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;eth/70 - partial block receipt lists&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Felix Lange&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:fjl@ethereum.org&quot;&gt;fjl@ethereum.org&lt;/a&gt;&amp;gt;, Jochem Brouwer&amp;nbsp;(&lt;a href=&quot;https://github.com/jochem-brouwer&quot;&gt;@jochem-brouwer&lt;/a&gt;), Giulio Rebuffo&amp;nbsp;(&lt;a href=&quot;https://github.com/Giulio2002&quot;&gt;@Giulio2002&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7976&quot;&gt;7976&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Increase Calldata Floor Cost&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Toni Wahrstätter&amp;nbsp;(&lt;a href=&quot;https://github.com/nerolation&quot;&gt;@nerolation&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7979&quot;&gt;7979&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Call and Return Opcodes for the EVM&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Greg Colvin&amp;nbsp;(&lt;a href=&quot;https://github.com/gcolvin&quot;&gt;@gcolvin&lt;/a&gt;), Martin Holst Swende&amp;nbsp;(&lt;a href=&quot;https://github.com/holiman&quot;&gt;@holiman&lt;/a&gt;), Brooklyn Zelenka&amp;nbsp;(&lt;a href=&quot;https://github.com/expede&quot;&gt;@expede&lt;/a&gt;), John Max Skaller&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:skaller@internode.on.net&quot;&gt;skaller@internode.on.net&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7981&quot;&gt;7981&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Increase Access List Cost&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Toni Wahrstätter&amp;nbsp;(&lt;a href=&quot;https://github.com/nerolation&quot;&gt;@nerolation&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7984&quot;&gt;7984&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Confidential Fungible Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Aryeh Greenberg&amp;nbsp;(&lt;a href=&quot;https://github.com/arr00&quot;&gt;@arr00&lt;/a&gt;), Ernesto García&amp;nbsp;(&lt;a href=&quot;https://github.com/ernestognw&quot;&gt;@ernestognw&lt;/a&gt;), Hadrien Croubois&amp;nbsp;(&lt;a href=&quot;https://github.com/Amxx&quot;&gt;@Amxx&lt;/a&gt;), Ghazi Ben Amor&amp;nbsp;(&lt;a href=&quot;https://github.com/GBAZama&quot;&gt;@GBAZama&lt;/a&gt;), Clement Danjou&amp;nbsp;(&lt;a href=&quot;https://github.com/immortal-tofu&quot;&gt;@immortal-tofu&lt;/a&gt;), Joseph Andre Turk&amp;nbsp;(&lt;a href=&quot;https://github.com/jatZama&quot;&gt;@jatZama&lt;/a&gt;), Silas Davis&amp;nbsp;(&lt;a href=&quot;https://github.com/silasdavis&quot;&gt;@silasdavis&lt;/a&gt;), Nicolas Pasquier&amp;nbsp;(&lt;a href=&quot;https://github.com/npasquie&quot;&gt;@npasquie&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7985&quot;&gt;7985&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Gateway Attributes for Message Control&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ernesto García&amp;nbsp;(&lt;a href=&quot;https://github.com/ernestognw&quot;&gt;@ernestognw&lt;/a&gt;), Kalman Lajko&amp;nbsp;(&lt;a href=&quot;https://github.com/LajkoKalman&quot;&gt;@LajkoKalman&lt;/a&gt;), Valera Grinenko&amp;nbsp;(&lt;a href=&quot;https://github.com/0xValera&quot;&gt;@0xValera&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7988&quot;&gt;7988&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Minimal Avatar Smart Wallet (MASW)&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;0xMostafas (@MostafaS)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:0xmostafas@proton.me&quot;&gt;0xmostafas@proton.me&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7992&quot;&gt;7992&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Verifiable ML Model Inference (ZKML)&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Aryaethn&amp;nbsp;(&lt;a href=&quot;https://github.com/aryaethn&quot;&gt;@aryaethn&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7996&quot;&gt;7996&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Contract Feature Detection&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;raffy.eth&amp;nbsp;(&lt;a href=&quot;https://github.com/adraffy&quot;&gt;@adraffy&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7997&quot;&gt;7997&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Deterministic Factory Predeploy&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Francisco Giordano&amp;nbsp;(&lt;a href=&quot;https://github.com/frangio&quot;&gt;@frangio&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7998&quot;&gt;7998&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Turn `randao_reveal` into a VRF&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alberto La Rocca&amp;nbsp;(&lt;a href=&quot;https://github.com/71104&quot;&gt;@71104&lt;/a&gt;), Aryaethn&amp;nbsp;(&lt;a href=&quot;https://github.com/aryaethn&quot;&gt;@aryaethn&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7999&quot;&gt;7999&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Unified multidimensional fee market&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Anders Elowsson&amp;nbsp;(&lt;a href=&quot;https://github.com/anderselowsson&quot;&gt;@anderselowsson&lt;/a&gt;), Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8000&quot;&gt;8000&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Operator contract for non delegated EOAs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Marcelo Morgado&amp;nbsp;(&lt;a href=&quot;https://github.com/marcelomorgado&quot;&gt;@marcelomorgado&lt;/a&gt;), Manoj Patidar&amp;nbsp;(&lt;a href=&quot;https://github.com/patidarmanoj10&quot;&gt;@patidarmanoj10&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8002&quot;&gt;8002&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Simplified Payment Verification Gateway&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Artem Chystiakov&amp;nbsp;(&lt;a href=&quot;https://github.com/arvolear&quot;&gt;@arvolear&lt;/a&gt;), Oleh Komendant&amp;nbsp;(&lt;a href=&quot;https://github.com/Hrom131&quot;&gt;@Hrom131&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8004&quot;&gt;8004&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Trustless Agents&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Marco De Rossi&amp;nbsp;(&lt;a href=&quot;https://github.com/MarcoMetaMask&quot;&gt;@MarcoMetaMask&lt;/a&gt;), Davide Crapis (@dcrapis)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:davide@ethereum.org&quot;&gt;davide@ethereum.org&lt;/a&gt;&amp;gt;, Jordan Ellis&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jordanellis@google.com&quot;&gt;jordanellis@google.com&lt;/a&gt;&amp;gt;, Erik Reppel&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:erik.reppel@coinbase.com&quot;&gt;erik.reppel@coinbase.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8007&quot;&gt;8007&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Glamsterdam Gas Repricings&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Maria Silva&amp;nbsp;(&lt;a href=&quot;https://github.com/misilva73&quot;&gt;@misilva73&lt;/a&gt;), Ansgar Dietrichs&amp;nbsp;(&lt;a href=&quot;https://github.com/adietrichs&quot;&gt;@adietrichs&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8011&quot;&gt;8011&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Multidimensional Gas Metering&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Maria Silva&amp;nbsp;(&lt;a href=&quot;https://github.com/misilva73&quot;&gt;@misilva73&lt;/a&gt;), Davide Crapis&amp;nbsp;(&lt;a href=&quot;https://github.com/dcrapis&quot;&gt;@dcrapis&lt;/a&gt;), Anders Elowsson&amp;nbsp;(&lt;a href=&quot;https://github.com/anderselowsson&quot;&gt;@anderselowsson&lt;/a&gt;), Toni Wahrstätter&amp;nbsp;(&lt;a href=&quot;https://github.com/nerolation&quot;&gt;@nerolation&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8012&quot;&gt;8012&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Generalized consolidation requests&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Potuz&amp;nbsp;(&lt;a href=&quot;https://github.com/potuz&quot;&gt;@potuz&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8016&quot;&gt;8016&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;SSZ CompatibleUnion&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Etan Kissling&amp;nbsp;(&lt;a href=&quot;https://github.com/etan-status&quot;&gt;@etan-status&lt;/a&gt;), Cayman&amp;nbsp;(&lt;a href=&quot;https://github.com/wemeetagain&quot;&gt;@wemeetagain&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8017&quot;&gt;8017&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Payout Race&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Kyle Thornton (@kyle)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:kyle@cowrie.io&quot;&gt;kyle@cowrie.io&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8023&quot;&gt;8023&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Multi-step Contract Ownership&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;David Kim&amp;nbsp;(&lt;a href=&quot;https://github.com/PowerStream3604&quot;&gt;@PowerStream3604&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8025&quot;&gt;8025&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Optional Execution Proofs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Kevaundray Wedderburn&amp;nbsp;(&lt;a href=&quot;https://github.com/kevaundray&quot;&gt;@kevaundray&lt;/a&gt;), Justin Drake (@JustinDrake)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:justin@ethereum.org&quot;&gt;justin@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8030&quot;&gt;8030&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;P256 algorithm support&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;James Kempton&amp;nbsp;(&lt;a href=&quot;https://github.com/SirSpudlington&quot;&gt;@SirSpudlington&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8032&quot;&gt;8032&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Size-Based Storage Gas Pricing&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Guillaume Ballet&amp;nbsp;(&lt;a href=&quot;https://github.com/gballet&quot;&gt;@gballet&lt;/a&gt;), Carlos Perez&amp;nbsp;(&lt;a href=&quot;https://github.com/CPerezz&quot;&gt;@CPerezz&lt;/a&gt;), Matan Prasma&amp;nbsp;(&lt;a href=&quot;https://github.com/KanExtension&quot;&gt;@KanExtension&lt;/a&gt;), Wei Han Ng&amp;nbsp;(&lt;a href=&quot;https://github.com/weiihann&quot;&gt;@weiihann&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8033&quot;&gt;8033&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Agent Council Oracles&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Rohan Parikh&amp;nbsp;(&lt;a href=&quot;https://github.com/phiraml&quot;&gt;@phiraml&lt;/a&gt;), Jon Michael Ross&amp;nbsp;(&lt;a href=&quot;https://github.com/jonmross&quot;&gt;@jonmross&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8037&quot;&gt;8037&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;State Creation Gas Cost Increase&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Maria Silva&amp;nbsp;(&lt;a href=&quot;https://github.com/misilva73&quot;&gt;@misilva73&lt;/a&gt;), Carlos Perez&amp;nbsp;(&lt;a href=&quot;https://github.com/CPerezz&quot;&gt;@CPerezz&lt;/a&gt;), Jochem Brouwer&amp;nbsp;(&lt;a href=&quot;https://github.com/jochem-brouwer&quot;&gt;@jochem-brouwer&lt;/a&gt;), Ansgar Dietrichs&amp;nbsp;(&lt;a href=&quot;https://github.com/adietrichs&quot;&gt;@adietrichs&lt;/a&gt;), Łukasz Rozmej&amp;nbsp;(&lt;a href=&quot;https://github.com/LukaszRozmej&quot;&gt;@LukaszRozmej&lt;/a&gt;), Anders Elowsson&amp;nbsp;(&lt;a href=&quot;https://github.com/anderselowsson&quot;&gt;@anderselowsson&lt;/a&gt;), Francesco D&apos;Amato&amp;nbsp;(&lt;a href=&quot;https://github.com/fradamt&quot;&gt;@fradamt&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8038&quot;&gt;8038&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;State-access gas cost update&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Maria Silva&amp;nbsp;(&lt;a href=&quot;https://github.com/misilva73&quot;&gt;@misilva73&lt;/a&gt;), Wei Han Ng&amp;nbsp;(&lt;a href=&quot;https://github.com/weiihann&quot;&gt;@weiihann&lt;/a&gt;), Ansgar Dietrichs&amp;nbsp;(&lt;a href=&quot;https://github.com/adietrichs&quot;&gt;@adietrichs&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8041&quot;&gt;8041&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Fixed-Supply Agent NFT Collections&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Prem Makeig&amp;nbsp;(&lt;a href=&quot;https://github.com/nxt3d&quot;&gt;@nxt3d&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8045&quot;&gt;8045&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Exclude slashed validators from proposing&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Francesco D&apos;Amato&amp;nbsp;(&lt;a href=&quot;https://github.com/fradamt&quot;&gt;@fradamt&lt;/a&gt;), Barnabas Busa&amp;nbsp;(&lt;a href=&quot;https://github.com/barnabasbusa&quot;&gt;@barnabasbusa&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8046&quot;&gt;8046&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Uniform price auction over inclusion lists&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Anders Elowsson&amp;nbsp;(&lt;a href=&quot;https://github.com/anderselowsson&quot;&gt;@anderselowsson&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8048&quot;&gt;8048&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Onchain Metadata for Token Registries&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Prem Makeig&amp;nbsp;(&lt;a href=&quot;https://github.com/nxt3d&quot;&gt;@nxt3d&lt;/a&gt;), Rafael Abuawad&amp;nbsp;(&lt;a href=&quot;https://github.com/rafael-abuawad&quot;&gt;@rafael-abuawad&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8049&quot;&gt;8049&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Contract-Level Onchain Metadata&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Prem Makeig&amp;nbsp;(&lt;a href=&quot;https://github.com/nxt3d&quot;&gt;@nxt3d&lt;/a&gt;), Rafael Abuawad&amp;nbsp;(&lt;a href=&quot;https://github.com/rafael-abuawad&quot;&gt;@rafael-abuawad&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8051&quot;&gt;8051&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Precompile for ML-DSA signature verification&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Renaud Dubois&amp;nbsp;(&lt;a href=&quot;https://github.com/rdubois-crypto&quot;&gt;@rdubois-crypto&lt;/a&gt;), Simon Masson&amp;nbsp;(&lt;a href=&quot;https://github.com/simonmasson&quot;&gt;@simonmasson&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8052&quot;&gt;8052&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Precompile for Falcon support&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Renaud Dubois&amp;nbsp;(&lt;a href=&quot;https://github.com/rdubois-crypto&quot;&gt;@rdubois-crypto&lt;/a&gt;), Simon Masson&amp;nbsp;(&lt;a href=&quot;https://github.com/simonmasson&quot;&gt;@simonmasson&lt;/a&gt;), Antonio Sanso&amp;nbsp;(&lt;a href=&quot;https://github.com/asanso&quot;&gt;@asanso&lt;/a&gt;), Marius van der Wijden&amp;nbsp;(&lt;a href=&quot;https://github.com/mariusvanderwijden&quot;&gt;@mariusvanderwijden&lt;/a&gt;), Kevaundray Wedderburn&amp;nbsp;(&lt;a href=&quot;https://github.com/kevaundray&quot;&gt;@kevaundray&lt;/a&gt;), Zhenfei Zhang&amp;nbsp;(&lt;a href=&quot;https://github.com/zhenfeizhang&quot;&gt;@zhenfeizhang&lt;/a&gt;), Nicolas Consigny&amp;nbsp;(&lt;a href=&quot;https://github.com/nconsigny&quot;&gt;@nconsigny&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8053&quot;&gt;8053&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Milli-gas for High-precision Gas Metering&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Maria Silva&amp;nbsp;(&lt;a href=&quot;https://github.com/misilva73&quot;&gt;@misilva73&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8056&quot;&gt;8056&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Scaled UI Amount Extension for ERC-20 Tokens&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Chris Ridmann (@cridmann)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:chris@superstate.co&quot;&gt;chris@superstate.co&lt;/a&gt;&amp;gt;, Daniel Gretzke&amp;nbsp;(&lt;a href=&quot;https://github.com/gretzke&quot;&gt;@gretzke&lt;/a&gt;), Gilbert Shih&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:chung.shih@robinhood.com&quot;&gt;chung.shih@robinhood.com&lt;/a&gt;&amp;gt;, Tino Martinez Molina&amp;nbsp;(&lt;a href=&quot;https://github.com/tinom9&quot;&gt;@tinom9&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8057&quot;&gt;8057&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Inter-Block Temporal Locality Gas Discounts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ben Adams&amp;nbsp;(&lt;a href=&quot;https://github.com/benaadams&quot;&gt;@benaadams&lt;/a&gt;), Toni Wahrstätter&amp;nbsp;(&lt;a href=&quot;https://github.com/nerolation&quot;&gt;@nerolation&lt;/a&gt;), Maria Inês Silva&amp;nbsp;(&lt;a href=&quot;https://github.com/misilva73&quot;&gt;@misilva73&lt;/a&gt;), Amirul Ashraf&amp;nbsp;(&lt;a href=&quot;https://github.com/asdacap&quot;&gt;@asdacap&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8058&quot;&gt;8058&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Contract Bytecode Deduplication Discount&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Carlos Perez&amp;nbsp;(&lt;a href=&quot;https://github.com/CPerezz&quot;&gt;@CPerezz&lt;/a&gt;), Wei Han Ng&amp;nbsp;(&lt;a href=&quot;https://github.com/weiihann&quot;&gt;@weiihann&lt;/a&gt;), Guillaume Ballet&amp;nbsp;(&lt;a href=&quot;https://github.com/gballet&quot;&gt;@gballet&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8059&quot;&gt;8059&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Gas Units Rebase for High-precision Metering&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Maria Silva&amp;nbsp;(&lt;a href=&quot;https://github.com/misilva73&quot;&gt;@misilva73&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8061&quot;&gt;8061&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Increase exit and consolidation churn&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Francesco D&apos;Amato&amp;nbsp;(&lt;a href=&quot;https://github.com/fradamt&quot;&gt;@fradamt&lt;/a&gt;), Anders Elowsson&amp;nbsp;(&lt;a href=&quot;https://github.com/anderselowsson&quot;&gt;@anderselowsson&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8062&quot;&gt;8062&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Add sweep withdrawal fee for 0x01 validators&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Anders Elowsson&amp;nbsp;(&lt;a href=&quot;https://github.com/anderselowsson&quot;&gt;@anderselowsson&lt;/a&gt;), Toni Wahrstätter&amp;nbsp;(&lt;a href=&quot;https://github.com/nerolation&quot;&gt;@nerolation&lt;/a&gt;), Francesco D&apos;Amato&amp;nbsp;(&lt;a href=&quot;https://github.com/fradamt&quot;&gt;@fradamt&lt;/a&gt;), Ben Adams&amp;nbsp;(&lt;a href=&quot;https://github.com/benaadams&quot;&gt;@benaadams&lt;/a&gt;), Maria Inês Silva&amp;nbsp;(&lt;a href=&quot;https://github.com/misilva73&quot;&gt;@misilva73&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8065&quot;&gt;8065&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Zero Knowledge Token Wrapper&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jiahui Cui&amp;nbsp;(&lt;a href=&quot;https://github.com/doublespending&quot;&gt;@doublespending&lt;/a&gt;), 0xZPL&amp;nbsp;(&lt;a href=&quot;https://github.com/0xZPL&quot;&gt;@0xZPL&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8066&quot;&gt;8066&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Upgrade Mascots&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jordan Holberg&amp;nbsp;(&lt;a href=&quot;https://github.com/eviljordan&quot;&gt;@eviljordan&lt;/a&gt;), Andrew B Coathup&amp;nbsp;(&lt;a href=&quot;https://github.com/abcoathup&quot;&gt;@abcoathup&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8068&quot;&gt;8068&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Neutral effective balance design&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Anders Elowsson&amp;nbsp;(&lt;a href=&quot;https://github.com/anderselowsson&quot;&gt;@anderselowsson&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8070&quot;&gt;8070&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;eth/72 - Sparse Blobpool&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Raúl Kripalani&amp;nbsp;(&lt;a href=&quot;https://github.com/raulk&quot;&gt;@raulk&lt;/a&gt;), Bosul Mun&amp;nbsp;(&lt;a href=&quot;https://github.com/healthykim&quot;&gt;@healthykim&lt;/a&gt;), Francesco D&apos;Amato&amp;nbsp;(&lt;a href=&quot;https://github.com/fradamt&quot;&gt;@fradamt&lt;/a&gt;), Csaba Kiraly&amp;nbsp;(&lt;a href=&quot;https://github.com/cskiraly&quot;&gt;@cskiraly&lt;/a&gt;), Felix Lange&amp;nbsp;(&lt;a href=&quot;https://github.com/fjl&quot;&gt;@fjl&lt;/a&gt;), Marios Ioannou&amp;nbsp;(&lt;a href=&quot;https://github.com/mariosioannou-create&quot;&gt;@mariosioannou-create&lt;/a&gt;), Alex Stokes&amp;nbsp;(&lt;a href=&quot;https://github.com/ralexstokes&quot;&gt;@ralexstokes&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8071&quot;&gt;8071&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Prevent using consolidations as withdrawals&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Mikhail Kalinin&amp;nbsp;(&lt;a href=&quot;https://github.com/mkalinin&quot;&gt;@mkalinin&lt;/a&gt;), Francesco D&apos;Amato&amp;nbsp;(&lt;a href=&quot;https://github.com/fradamt&quot;&gt;@fradamt&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8072&quot;&gt;8072&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Transaction Inclusion Subscription&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Łukasz Rozmej&amp;nbsp;(&lt;a href=&quot;https://github.com/LukaszRozmej&quot;&gt;@LukaszRozmej&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8074&quot;&gt;8074&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Self-Describing Bytes via EIP-712 Selectors&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Andrew Richardson&amp;nbsp;(&lt;a href=&quot;https://github.com/awrichar&quot;&gt;@awrichar&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8075&quot;&gt;8075&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Adaptive state cost to cap growth &amp;amp; scale L1&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Anders Elowsson&amp;nbsp;(&lt;a href=&quot;https://github.com/anderselowsson&quot;&gt;@anderselowsson&lt;/a&gt;), Francesco D&apos;Amato&amp;nbsp;(&lt;a href=&quot;https://github.com/fradamt&quot;&gt;@fradamt&lt;/a&gt;), Maria Silva&amp;nbsp;(&lt;a href=&quot;https://github.com/misilva73&quot;&gt;@misilva73&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8077&quot;&gt;8077&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;eth/XX - announce transactions with nonce&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Csaba Kiraly&amp;nbsp;(&lt;a href=&quot;https://github.com/cskiraly&quot;&gt;@cskiraly&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8079&quot;&gt;8079&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Native rollups&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Luca Donno (@lucadonnoh)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:donnoh@l2beat.com&quot;&gt;donnoh@l2beat.com&lt;/a&gt;&amp;gt;, Justin Drake (@JustinDrake)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:justin@ethereum.org&quot;&gt;justin@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8080&quot;&gt;8080&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Let exits use the consolidation queue&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Francesco D&apos;Amato&amp;nbsp;(&lt;a href=&quot;https://github.com/fradamt&quot;&gt;@fradamt&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8081&quot;&gt;8081&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hardfork Meta - Hegotá&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Tim Beiko&amp;nbsp;(&lt;a href=&quot;https://github.com/timbeiko&quot;&gt;@timbeiko&lt;/a&gt;), Alex Stokes&amp;nbsp;(&lt;a href=&quot;https://github.com/ralexstokes&quot;&gt;@ralexstokes&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8092&quot;&gt;8092&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Associated Accounts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Steve Katzman&amp;nbsp;(&lt;a href=&quot;https://github.com/stevieraykatz&quot;&gt;@stevieraykatz&lt;/a&gt;), Amie Corso&amp;nbsp;(&lt;a href=&quot;https://github.com/amiecorso&quot;&gt;@amiecorso&lt;/a&gt;), Stephan Cilliers&amp;nbsp;(&lt;a href=&quot;https://github.com/stephancill&quot;&gt;@stephancill&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8094&quot;&gt;8094&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;eth/vhash - Blob-Aware Mempool&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Csaba Kiraly&amp;nbsp;(&lt;a href=&quot;https://github.com/cskiraly&quot;&gt;@cskiraly&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8096&quot;&gt;8096&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Increase Gas Cost of Point Evaluation&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Marcin Sobczak&amp;nbsp;(&lt;a href=&quot;https://github.com/marcindsobczak&quot;&gt;@marcindsobczak&lt;/a&gt;), Kamil Chodoła&amp;nbsp;(&lt;a href=&quot;https://github.com/kamilchodola&quot;&gt;@kamilchodola&lt;/a&gt;), Marek Moraczyński&amp;nbsp;(&lt;a href=&quot;https://github.com/MarekM25&quot;&gt;@MarekM25&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8099&quot;&gt;8099&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;MEVless Protocol&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Lawliet Chan&amp;nbsp;(&lt;a href=&quot;https://github.com/lawliet-chan&quot;&gt;@lawliet-chan&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8101&quot;&gt;8101&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Payload Chunking with Chunk Access Lists&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Toni Wahrstätter&amp;nbsp;(&lt;a href=&quot;https://github.com/nerolation&quot;&gt;@nerolation&lt;/a&gt;), Milos Stankovic&amp;nbsp;(&lt;a href=&quot;https://github.com/morph-dev&quot;&gt;@morph-dev&lt;/a&gt;), Jihoon Song&amp;nbsp;(&lt;a href=&quot;https://github.com/jihoonsong&quot;&gt;@jihoonsong&lt;/a&gt;), Bharath Vedartham&amp;nbsp;(&lt;a href=&quot;https://github.com/bharath-123&quot;&gt;@bharath-123&lt;/a&gt;), Raúl Kripalani&amp;nbsp;(&lt;a href=&quot;https://github.com/raulk&quot;&gt;@raulk&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8105&quot;&gt;8105&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Universal Enshrined Encrypted Mempool&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jannik Luhn&amp;nbsp;(&lt;a href=&quot;https://github.com/jannikluhn&quot;&gt;@jannikluhn&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8106&quot;&gt;8106&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;RWA Event-based Compliance Framework&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Andrew Wang (@wz14)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:zhuowangy2k@outlook.com&quot;&gt;zhuowangy2k@outlook.com&lt;/a&gt;&amp;gt;, Jack Yin (@0xjackey)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:0xjackey@gmail.com&quot;&gt;0xjackey@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8107&quot;&gt;8107&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ENS Trust Registry for Agent Coordination&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Kwame Bryan&amp;nbsp;(&lt;a href=&quot;https://github.com/KBryan&quot;&gt;@KBryan&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8110&quot;&gt;8110&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Domain Architecture for Diamonds&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Hoang&amp;nbsp;(&lt;a href=&quot;https://github.com/0x76agabond&quot;&gt;@0x76agabond&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8113&quot;&gt;8113&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Series Accounting for Incentivized Vaults&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Yash Saraswat&amp;nbsp;(&lt;a href=&quot;https://github.com/0xpanicError&quot;&gt;@0xpanicError&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8115&quot;&gt;8115&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Batch priority fees at end of block&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Etan Kissling&amp;nbsp;(&lt;a href=&quot;https://github.com/etan-status&quot;&gt;@etan-status&lt;/a&gt;), Gajinder Singh&amp;nbsp;(&lt;a href=&quot;https://github.com/g11tech&quot;&gt;@g11tech&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8116&quot;&gt;8116&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Replace cumulative receipt fields&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Etan Kissling&amp;nbsp;(&lt;a href=&quot;https://github.com/etan-status&quot;&gt;@etan-status&lt;/a&gt;), Gajinder Singh&amp;nbsp;(&lt;a href=&quot;https://github.com/g11tech&quot;&gt;@g11tech&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8117&quot;&gt;8117&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Anti-Poisoning Compact EVM Address Format&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Zainan Victor Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/xinbenlv&quot;&gt;@xinbenlv&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8119&quot;&gt;8119&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Parameterized Storage Keys&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Prem Makeig&amp;nbsp;(&lt;a href=&quot;https://github.com/nxt3d&quot;&gt;@nxt3d&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8120&quot;&gt;8120&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;MLOAD8 and CALLDATALOAD8 Opcodes&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Helkomine&amp;nbsp;(&lt;a href=&quot;https://github.com/Helkomine&quot;&gt;@Helkomine&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8121&quot;&gt;8121&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Cross-Chain Function Calls via Hooks&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Prem Makeig&amp;nbsp;(&lt;a href=&quot;https://github.com/nxt3d&quot;&gt;@nxt3d&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8122&quot;&gt;8122&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Minimal Agent Registry&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Prem Makeig&amp;nbsp;(&lt;a href=&quot;https://github.com/nxt3d&quot;&gt;@nxt3d&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8123&quot;&gt;8123&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;RPC Method for Transaction Gas Limit Cap&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Paul Razvan Berg&amp;nbsp;(&lt;a href=&quot;https://github.com/PaulRBerg&quot;&gt;@PaulRBerg&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8125&quot;&gt;8125&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Temporary Contract Storage&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Wei Han Ng&amp;nbsp;(&lt;a href=&quot;https://github.com/weiihann&quot;&gt;@weiihann&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8127&quot;&gt;8127&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Human Readable Token Identifiers&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Prem Makeig&amp;nbsp;(&lt;a href=&quot;https://github.com/nxt3d&quot;&gt;@nxt3d&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8130&quot;&gt;8130&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Account Abstraction by Account Configuration&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Chris Hunter (@chunter-cb)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:chris.hunter@coinbase.com&quot;&gt;chris.hunter@coinbase.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8131&quot;&gt;8131&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Add Auth Data to EIP-7623 Floor&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Toni Wahrstätter&amp;nbsp;(&lt;a href=&quot;https://github.com/nerolation&quot;&gt;@nerolation&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8133&quot;&gt;8133&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Upgrade Nomenclature&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Pooja Ranjan&amp;nbsp;(&lt;a href=&quot;https://github.com/poojaranjan&quot;&gt;@poojaranjan&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8136&quot;&gt;8136&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Cell-Level Deltas for Data Column Broadcast&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Marco Munizaga (@MarcoPolo)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:git@marcopolo.io&quot;&gt;git@marcopolo.io&lt;/a&gt;&amp;gt;, Daniel Knopik (@dknopik)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:daniel@dknopik.de&quot;&gt;daniel@dknopik.de&lt;/a&gt;&amp;gt;, Sukun Tarachandani (@sukunrt)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:sukunrt@gmail.com&quot;&gt;sukunrt@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8138&quot;&gt;8138&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hardfork Meta - BPO3&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Pooja Ranjan&amp;nbsp;(&lt;a href=&quot;https://github.com/poojaranjan&quot;&gt;@poojaranjan&lt;/a&gt;), Barnabas Busa&amp;nbsp;(&lt;a href=&quot;https://github.com/barnabasbusa&quot;&gt;@barnabasbusa&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8141&quot;&gt;8141&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Frame Transaction&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), lightclient&amp;nbsp;(&lt;a href=&quot;https://github.com/lightclient&quot;&gt;@lightclient&lt;/a&gt;), Felix Lange&amp;nbsp;(&lt;a href=&quot;https://github.com/fjl&quot;&gt;@fjl&lt;/a&gt;), Yoav Weiss&amp;nbsp;(&lt;a href=&quot;https://github.com/yoavw&quot;&gt;@yoavw&lt;/a&gt;), Alex Forshtat&amp;nbsp;(&lt;a href=&quot;https://github.com/forshtat&quot;&gt;@forshtat&lt;/a&gt;), Dror Tirosh&amp;nbsp;(&lt;a href=&quot;https://github.com/drortirosh&quot;&gt;@drortirosh&lt;/a&gt;), Shahaf Nacson&amp;nbsp;(&lt;a href=&quot;https://github.com/shahafn&quot;&gt;@shahafn&lt;/a&gt;), Derek Chiang&amp;nbsp;(&lt;a href=&quot;https://github.com/derekchiang&quot;&gt;@derekchiang&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8142&quot;&gt;8142&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Block-in-Blobs (BiB)&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Kevaundray Wedderburn&amp;nbsp;(&lt;a href=&quot;https://github.com/kevaundray&quot;&gt;@kevaundray&lt;/a&gt;), Ignacio Hagopian&amp;nbsp;(&lt;a href=&quot;https://github.com/jsign&quot;&gt;@jsign&lt;/a&gt;), Jihoon Song&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jihoon.song@ethereum.org&quot;&gt;jihoon.song@ethereum.org&lt;/a&gt;&amp;gt;, Francesco Risitano&amp;nbsp;(&lt;a href=&quot;https://github.com/frisitano&quot;&gt;@frisitano&lt;/a&gt;), Thomas Thiery (@soispoke)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:thomas.thiery@ethereum.org&quot;&gt;thomas.thiery@ethereum.org&lt;/a&gt;&amp;gt;, Toni Wahrstätter&amp;nbsp;(&lt;a href=&quot;https://github.com/nerolation&quot;&gt;@nerolation&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8146&quot;&gt;8146&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Block Access List Sidecars&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Toni Wahrstätter&amp;nbsp;(&lt;a href=&quot;https://github.com/nerolation&quot;&gt;@nerolation&lt;/a&gt;), Raúl Kripalani&amp;nbsp;(&lt;a href=&quot;https://github.com/raulk&quot;&gt;@raulk&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8148&quot;&gt;8148&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Custom sweep threshold for validators&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Dmitry Gusakov&amp;nbsp;(&lt;a href=&quot;https://github.com/dgusakov&quot;&gt;@dgusakov&lt;/a&gt;), Dmitry Chernukhin&amp;nbsp;(&lt;a href=&quot;https://github.com/madlabman&quot;&gt;@madlabman&lt;/a&gt;), Greg Koumoutsos&amp;nbsp;(&lt;a href=&quot;https://github.com/gkoumout&quot;&gt;@gkoumout&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8149&quot;&gt;8149&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Multi KZG Point Evaluation Precompile&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Chris Mata&amp;nbsp;(&lt;a href=&quot;https://github.com/protocolwhisper&quot;&gt;@protocolwhisper&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8151&quot;&gt;8151&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Private Key Deactivation Aware ecRecover&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Liyi Guo&amp;nbsp;(&lt;a href=&quot;https://github.com/colinlyguo&quot;&gt;@colinlyguo&lt;/a&gt;), Nicolas Consigny&amp;nbsp;(&lt;a href=&quot;https://github.com/nconsigny&quot;&gt;@nconsigny&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8152&quot;&gt;8152&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Content-Addressable Logic Modules (CALM)&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Radek Svarz&amp;nbsp;(&lt;a href=&quot;https://github.com/radeksvarz&quot;&gt;@radeksvarz&lt;/a&gt;), Nick Mudge&amp;nbsp;(&lt;a href=&quot;https://github.com/mudgen&quot;&gt;@mudgen&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8153&quot;&gt;8153&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Facet-Based Diamonds&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Mudge&amp;nbsp;(&lt;a href=&quot;https://github.com/mudgen&quot;&gt;@mudgen&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8159&quot;&gt;8159&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;eth/71 - Block Access List Exchange&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Toni Wahrstätter&amp;nbsp;(&lt;a href=&quot;https://github.com/nerolation&quot;&gt;@nerolation&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8163&quot;&gt;8163&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Reserve `EXTENSION (0xae)` opcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Bruce Collie&amp;nbsp;(&lt;a href=&quot;https://github.com/Baltoli&quot;&gt;@Baltoli&lt;/a&gt;), Piotr Dobaczewski&amp;nbsp;(&lt;a href=&quot;https://github.com/pdobacz&quot;&gt;@pdobacz&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8164&quot;&gt;8164&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Native Key Delegation for EOAs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gregory Markou (@GregTheGreek)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:gregorymarkou@gmail.com&quot;&gt;gregorymarkou@gmail.com&lt;/a&gt;&amp;gt;, James Prestwich (@prestwich)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:james@prestwi.ch&quot;&gt;james@prestwi.ch&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8175&quot;&gt;8175&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Composable Transaction&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Dragan Rakita&amp;nbsp;(&lt;a href=&quot;https://github.com/rakita&quot;&gt;@rakita&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8178&quot;&gt;8178&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Binary SSZ Transport for the Engine API&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Giulio Rebuffo&amp;nbsp;(&lt;a href=&quot;https://github.com/Giulio2002&quot;&gt;@Giulio2002&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8182&quot;&gt;8182&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Private ETH and ERC-20 Transfers&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Tom Lehman&amp;nbsp;(&lt;a href=&quot;https://github.com/RogerPodacter&quot;&gt;@RogerPodacter&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8183&quot;&gt;8183&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Agentic Commerce&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Davide Crapis&amp;nbsp;(&lt;a href=&quot;https://github.com/dcrapis&quot;&gt;@dcrapis&lt;/a&gt;), Bryan Lim&amp;nbsp;(&lt;a href=&quot;https://github.com/ai-virtual-b&quot;&gt;@ai-virtual-b&lt;/a&gt;), Tay Weixiong&amp;nbsp;(&lt;a href=&quot;https://github.com/twx-virtuals&quot;&gt;@twx-virtuals&lt;/a&gt;), Chooi Zuhwa&amp;nbsp;(&lt;a href=&quot;https://github.com/Zuhwa&quot;&gt;@Zuhwa&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8184&quot;&gt;8184&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;LUCID encrypted mempool&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Anders Elowsson&amp;nbsp;(&lt;a href=&quot;https://github.com/anderselowsson&quot;&gt;@anderselowsson&lt;/a&gt;), Justin Florentine&amp;nbsp;(&lt;a href=&quot;https://github.com/jflo&quot;&gt;@jflo&lt;/a&gt;), Julian Ma&amp;nbsp;(&lt;a href=&quot;https://github.com/ma-julian&quot;&gt;@ma-julian&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8189&quot;&gt;8189&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;snap/2 - BAL-Based State Healing&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Toni Wahrstätter&amp;nbsp;(&lt;a href=&quot;https://github.com/nerolation&quot;&gt;@nerolation&lt;/a&gt;), Gary Rong&amp;nbsp;(&lt;a href=&quot;https://github.com/rjl493456442&quot;&gt;@rjl493456442&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8198&quot;&gt;8198&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Quick Slots&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Carl Beekhuizen&amp;nbsp;(&lt;a href=&quot;https://github.com/carlbeek&quot;&gt;@carlbeek&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8199&quot;&gt;8199&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Sandboxed Smart Wallet&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;David Kim&amp;nbsp;(&lt;a href=&quot;https://github.com/PowerStream3604&quot;&gt;@PowerStream3604&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8200&quot;&gt;8200&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EVMification&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Kevaundray Wedderburn&amp;nbsp;(&lt;a href=&quot;https://github.com/kevaundray&quot;&gt;@kevaundray&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8205&quot;&gt;8205&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Withdrawal credentials preregistration&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;George Avsetsin&amp;nbsp;(&lt;a href=&quot;https://github.com/avsetsin&quot;&gt;@avsetsin&lt;/a&gt;), Dmitry Gusakov&amp;nbsp;(&lt;a href=&quot;https://github.com/dgusakov&quot;&gt;@dgusakov&lt;/a&gt;), Greg Koumoutsos&amp;nbsp;(&lt;a href=&quot;https://github.com/gkoumout&quot;&gt;@gkoumout&lt;/a&gt;), Eugene Mamin&amp;nbsp;(&lt;a href=&quot;https://github.com/TheDZhon&quot;&gt;@TheDZhon&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8209&quot;&gt;8209&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Commit-Reveal Transaction Frames&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Forshtat&amp;nbsp;(&lt;a href=&quot;https://github.com/forshtat&quot;&gt;@forshtat&lt;/a&gt;), Shahaf Nacson&amp;nbsp;(&lt;a href=&quot;https://github.com/shahafn&quot;&gt;@shahafn&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
    &lt;/table&gt;
  

  
  
  
    &lt;h2 id=&quot;stagnant&quot;&gt;Stagnant&lt;/h2&gt;
    &lt;table class=&quot;eiptable&quot;&gt;
      &lt;thead&gt;
        
          &lt;tr&gt;&lt;th class=&quot;eipnum&quot;&gt;Number&lt;/th&gt;&lt;th class=&quot;title&quot;&gt;Title&lt;/th&gt;&lt;th class=&quot;author&quot;&gt;Author&lt;/th&gt;&lt;/tr&gt;
        
      &lt;/thead&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-86&quot;&gt;86&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Abstraction of transaction origin and signature&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-101&quot;&gt;101&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Serenity Currency and Crypto Abstraction&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-107&quot;&gt;107&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;safe &amp;quot;eth_sendTransaction&amp;quot; authorization via html popup&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ronan Sandford&amp;nbsp;(&lt;a href=&quot;https://github.com/wighawag&quot;&gt;@wighawag&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-205&quot;&gt;205&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ENS support for contract ABIs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Johnson&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:nick@ethereum.org&quot;&gt;nick@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-210&quot;&gt;210&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Blockhash refactoring&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-233&quot;&gt;233&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Formal process of hard forks&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-615&quot;&gt;615&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Subroutines and Static Jumps for the EVM&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Greg Colvin&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:greg@colvin.org&quot;&gt;greg@colvin.org&lt;/a&gt;&amp;gt;, Brooklyn Zelenka&amp;nbsp;(&lt;a href=&quot;https://github.com/expede&quot;&gt;@expede&lt;/a&gt;), Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;), Christian Reitwiessner&amp;nbsp;(&lt;a href=&quot;https://github.com/chriseth&quot;&gt;@chriseth&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-616&quot;&gt;616&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;SIMD Operations for the EVM&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Greg Colvin&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:greg@colvin.org&quot;&gt;greg@colvin.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-634&quot;&gt;634&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Storage of text records in ENS&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Richard Moore&amp;nbsp;(&lt;a href=&quot;https://github.com/ricmoo&quot;&gt;@ricmoo&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-663&quot;&gt;663&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;SWAPN, DUPN and EXCHANGE instructions&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Charles Cooper&amp;nbsp;(&lt;a href=&quot;https://github.com/charles-cooper&quot;&gt;@charles-cooper&lt;/a&gt;), Danno Ferrin&amp;nbsp;(&lt;a href=&quot;https://github.com/shemnon&quot;&gt;@shemnon&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-665&quot;&gt;665&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Add precompiled contract for Ed25519 signature verification&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Tobias Oberstein&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:tobias.oberstein@crossbario.com&quot;&gt;tobias.oberstein@crossbario.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-689&quot;&gt;689&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Address Collision of Contract Address Causes Exceptional Halt&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Yoichi Hirai&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:i@yoichihirai.com&quot;&gt;i@yoichihirai.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-698&quot;&gt;698&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;OPCODE 0x46 BLOCKREWARD&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Cody Burns&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:dontPanic@codywburns.com&quot;&gt;dontPanic@codywburns.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-758&quot;&gt;758&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Subscriptions and filters for completed transactions&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jack Peterson&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jack@tinybike.net&quot;&gt;jack@tinybike.net&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-801&quot;&gt;801&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Canary Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;ligi&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:ligi@ligi.de&quot;&gt;ligi@ligi.de&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-823&quot;&gt;823&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Token Exchange Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Kashish Khullar&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:kkhullar7@gmail.com&quot;&gt;kkhullar7@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-831&quot;&gt;831&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;URI Format for Ethereum&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;ligi&amp;nbsp;(&lt;a href=&quot;https://github.com/ligi&quot;&gt;@ligi&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-858&quot;&gt;858&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Reduce block reward and delay difficulty bomb&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Carl Larson&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:cslarson@gmail.com&quot;&gt;cslarson@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-867&quot;&gt;867&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Standardized Ethereum Recovery Proposals&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Dan Phifer&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:dp@musiconomi.com&quot;&gt;dp@musiconomi.com&lt;/a&gt;&amp;gt;, James Levy&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:james@taptrust.com&quot;&gt;james@taptrust.com&lt;/a&gt;&amp;gt;, Reuben Youngblom&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:reuben@taptrust.com&quot;&gt;reuben@taptrust.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-884&quot;&gt;884&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;DGCL Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Dave Sag&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:davesag@gmail.com&quot;&gt;davesag@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-897&quot;&gt;897&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;DelegateProxy&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jorge Izquierdo&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jorge@aragon.one&quot;&gt;jorge@aragon.one&lt;/a&gt;&amp;gt;, Manuel Araoz&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:manuel@zeppelin.solutions&quot;&gt;manuel@zeppelin.solutions&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-900&quot;&gt;900&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Simple Staking Interface&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Dean Eigenmann&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:dean@tokenate.io&quot;&gt;dean@tokenate.io&lt;/a&gt;&amp;gt;, Jorge Izquierdo&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jorge@aragon.one&quot;&gt;jorge@aragon.one&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-902&quot;&gt;902&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Token Validation&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Brooklyn Zelenka&amp;nbsp;(&lt;a href=&quot;https://github.com/expede&quot;&gt;@expede&lt;/a&gt;), Tom Carchrae&amp;nbsp;(&lt;a href=&quot;https://github.com/carchrae&quot;&gt;@carchrae&lt;/a&gt;), Gleb Naumenko&amp;nbsp;(&lt;a href=&quot;https://github.com/naumenkogs&quot;&gt;@naumenkogs&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-918&quot;&gt;918&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Mineable Token Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jay Logelin&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jlogelin@alumni.harvard.edu&quot;&gt;jlogelin@alumni.harvard.edu&lt;/a&gt;&amp;gt;, Infernal_toast&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:admin@0xbitcoin.org&quot;&gt;admin@0xbitcoin.org&lt;/a&gt;&amp;gt;, Michael Seiler&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:mgs33@cornell.edu&quot;&gt;mgs33@cornell.edu&lt;/a&gt;&amp;gt;, Brandon Grill&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:bg2655@columbia.edu&quot;&gt;bg2655@columbia.edu&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-926&quot;&gt;926&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Address metadata registry&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Johnson&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:nick@ethereum.org&quot;&gt;nick@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-927&quot;&gt;927&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Generalised authorisations&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Johnson&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:nick@ethereum.org&quot;&gt;nick@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-969&quot;&gt;969&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Modifications to ethash to invalidate existing dedicated hardware implementations&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;David Stanfill&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:david@airsquirrels.com&quot;&gt;david@airsquirrels.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1010&quot;&gt;1010&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Uniformity Between 0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B and 0x15E55EF43efA8348dDaeAa455F16C43B64917e3c&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Anderson Wesley&amp;nbsp;(&lt;a href=&quot;https://github.com/andywesley&quot;&gt;@andywesley&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1011&quot;&gt;1011&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hybrid Casper FFG&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Danny Ryan&amp;nbsp;(&lt;a href=&quot;https://github.com/djrtwo&quot;&gt;@djrtwo&lt;/a&gt;), Chih-Cheng Liang&amp;nbsp;(&lt;a href=&quot;https://github.com/ChihChengLiang&quot;&gt;@ChihChengLiang&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1015&quot;&gt;1015&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Configurable On Chain Issuance&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Van de Sande&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:avsa@ethereum.org&quot;&gt;avsa@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1051&quot;&gt;1051&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Overflow checking for the EVM&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Johnson&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:arachnid@notdot.net&quot;&gt;arachnid@notdot.net&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1056&quot;&gt;1056&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Ethereum Lightweight Identity&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Pelle Braendgaard&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:pelle.braendgaard@consensys.net&quot;&gt;pelle.braendgaard@consensys.net&lt;/a&gt;&amp;gt;, Joel Torstensson&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:oed@consensys.net&quot;&gt;oed@consensys.net&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1057&quot;&gt;1057&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ProgPoW, a Programmatic Proof-of-Work&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Greg Colvin&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:greg@colvin.org&quot;&gt;greg@colvin.org&lt;/a&gt;&amp;gt;, Andrea Lanfranchi&amp;nbsp;(&lt;a href=&quot;https://github.com/AndreaLanfranchi&quot;&gt;@AndreaLanfranchi&lt;/a&gt;), Michael Carter&amp;nbsp;(&lt;a href=&quot;https://github.com/bitsbetrippin&quot;&gt;@bitsbetrippin&lt;/a&gt;), IfDefElse&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:ifdefelse@protonmail.com&quot;&gt;ifdefelse@protonmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1062&quot;&gt;1062&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Formalize IPFS hash into ENS(Ethereum Name Service) resolver&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Phyrex Tsai&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:phyrex@portal.network&quot;&gt;phyrex@portal.network&lt;/a&gt;&amp;gt;,  Portal Network Team&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1066&quot;&gt;1066&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Status Codes&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Brooklyn Zelenka&amp;nbsp;(&lt;a href=&quot;https://github.com/expede&quot;&gt;@expede&lt;/a&gt;), Tom Carchrae&amp;nbsp;(&lt;a href=&quot;https://github.com/carchrae&quot;&gt;@carchrae&lt;/a&gt;), Gleb Naumenko&amp;nbsp;(&lt;a href=&quot;https://github.com/naumenkogs&quot;&gt;@naumenkogs&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1077&quot;&gt;1077&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Gas relay for contract calls&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Van de Sande&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:avsa@ethereum.org&quot;&gt;avsa@ethereum.org&lt;/a&gt;&amp;gt;, Ricardo Guilherme Schmidt&amp;nbsp;(&lt;a href=&quot;https://github.com/3esmit&quot;&gt;@3esmit&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1078&quot;&gt;1078&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Universal login / signup using ENS subdomains&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Van de Sande&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:avsa@ethereum.org&quot;&gt;avsa@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1080&quot;&gt;1080&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Recoverable Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Bradley Leatherwood&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:bradleat@inkibra.com&quot;&gt;bradleat@inkibra.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1081&quot;&gt;1081&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Standard Bounties&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Mark Beylin&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:mark.beylin@consensys.net&quot;&gt;mark.beylin@consensys.net&lt;/a&gt;&amp;gt;, Kevin Owocki&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:kevin.owocki@consensys.net&quot;&gt;kevin.owocki@consensys.net&lt;/a&gt;&amp;gt;, Ricardo Guilherme Schmidt&amp;nbsp;(&lt;a href=&quot;https://github.com/3esmit&quot;&gt;@3esmit&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1087&quot;&gt;1087&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Net gas metering for SSTORE operations&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Johnson&amp;nbsp;(&lt;a href=&quot;https://github.com/arachnid&quot;&gt;@arachnid&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1102&quot;&gt;1102&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Opt-in account exposure&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Paul Bouchon&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:mail@bitpshr.net&quot;&gt;mail@bitpshr.net&lt;/a&gt;&amp;gt;, Erik Marks&amp;nbsp;(&lt;a href=&quot;https://github.com/rekmarks&quot;&gt;@rekmarks&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1109&quot;&gt;1109&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;PRECOMPILEDCALL opcode (Remove CALL costs for precompiled contracts)&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jordi Baylina&amp;nbsp;(&lt;a href=&quot;https://github.com/jbaylina&quot;&gt;@jbaylina&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1129&quot;&gt;1129&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Standardised DAPP announcements&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jan Turk&amp;nbsp;(&lt;a href=&quot;https://github.com/ThunderDeliverer&quot;&gt;@ThunderDeliverer&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1132&quot;&gt;1132&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Extending ERC20 with token locking capability&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;nitika-goel&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:nitika@govblocks.io&quot;&gt;nitika@govblocks.io&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1175&quot;&gt;1175&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Wallet &amp;amp; shop standard for all tokens (erc20)&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jet Lim&amp;nbsp;(&lt;a href=&quot;https://github.com/Nitro888&quot;&gt;@Nitro888&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1178&quot;&gt;1178&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Multi-class Token Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Albert Chon&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:achon@stanford.edu&quot;&gt;achon@stanford.edu&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1186&quot;&gt;1186&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;RPC-Method to get Merkle Proofs - eth_getProof&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Simon Jentzsch&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:simon.jentzsch@slock.it&quot;&gt;simon.jentzsch@slock.it&lt;/a&gt;&amp;gt;, Christoph Jentzsch&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:christoph.jentzsch@slock.it&quot;&gt;christoph.jentzsch@slock.it&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1203&quot;&gt;1203&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-1203 Multi-Class Token Standard (ERC-20 Extension)&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jeff Huang&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:jeffishjeff@gmail.com&quot;&gt;jeffishjeff@gmail.com&lt;/a&gt;&amp;gt;, Min Zu&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:crawlregister@gmail.com&quot;&gt;crawlregister@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1207&quot;&gt;1207&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;DAuth Access Delegation Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Xiaoyu Wang&amp;nbsp;(&lt;a href=&quot;https://github.com/wxygeek&quot;&gt;@wxygeek&lt;/a&gt;), Bicong Wang&amp;nbsp;(&lt;a href=&quot;https://github.com/Wangbicong&quot;&gt;@Wangbicong&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1227&quot;&gt;1227&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Defuse Difficulty Bomb and Reset Block Reward&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;SmeargleUsedFly&amp;nbsp;(&lt;a href=&quot;https://github.com/SmeargleUsedFly&quot;&gt;@SmeargleUsedFly&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1261&quot;&gt;1261&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Membership Verification Token (MVT)&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Chaitanya Potti&amp;nbsp;(&lt;a href=&quot;https://github.com/chaitanyapotti&quot;&gt;@chaitanyapotti&lt;/a&gt;), Partha Bhattacharya&amp;nbsp;(&lt;a href=&quot;https://github.com/pb25193&quot;&gt;@pb25193&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1276&quot;&gt;1276&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Eliminate Difficulty Bomb and Adjust Block Reward on Constantinople Shift&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;EOS Classic&amp;nbsp;(&lt;a href=&quot;https://github.com/eosclassicteam&quot;&gt;@eosclassicteam&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1285&quot;&gt;1285&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Increase Gcallstipend gas in the CALL opcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ben Kaufman&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:ben@daostack.io&quot;&gt;ben@daostack.io&lt;/a&gt;&amp;gt;, Adam Levi&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:adam@daostack.io&quot;&gt;adam@daostack.io&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1295&quot;&gt;1295&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Modify Ethereum PoW Incentive Structure and Delay Difficulty Bomb&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Brian Venturo&amp;nbsp;(&lt;a href=&quot;https://github.com/atlanticcrypto&quot;&gt;@atlanticcrypto&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1319&quot;&gt;1319&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Smart Contract Package Registry Interface&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Piper Merriam&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:piper@ethereum.org&quot;&gt;piper@ethereum.org&lt;/a&gt;&amp;gt;, Christopher Gewecke&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:christophergewecke@gmail.com&quot;&gt;christophergewecke@gmail.com&lt;/a&gt;&amp;gt;, g. nicholas d&apos;andrea&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:nick.dandrea@consensys.net&quot;&gt;nick.dandrea@consensys.net&lt;/a&gt;&amp;gt;, Nick Gheorghita&amp;nbsp;(&lt;a href=&quot;https://github.com/njgheorghita&quot;&gt;@njgheorghita&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1337&quot;&gt;1337&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Subscriptions on the blockchain&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Kevin Owocki&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:kevin@gitcoin.co&quot;&gt;kevin@gitcoin.co&lt;/a&gt;&amp;gt;, Andrew Redden&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:andrew@blockcrushr.com&quot;&gt;andrew@blockcrushr.com&lt;/a&gt;&amp;gt;, Scott Burke&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:scott@blockcrushr.com&quot;&gt;scott@blockcrushr.com&lt;/a&gt;&amp;gt;, Kevin Seagraves&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:k.s.seagraves@gmail.com&quot;&gt;k.s.seagraves@gmail.com&lt;/a&gt;&amp;gt;, Luka Kacil&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:luka.kacil@gmail.com&quot;&gt;luka.kacil@gmail.com&lt;/a&gt;&amp;gt;, Štefan Šimec&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:stefan.simec@gmail.com&quot;&gt;stefan.simec@gmail.com&lt;/a&gt;&amp;gt;, Piotr Kosiński&amp;nbsp;(&lt;a href=&quot;https://github.com/kosecki123&quot;&gt;@kosecki123&lt;/a&gt;), ankit raj&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:tradeninja7@gmail.com&quot;&gt;tradeninja7@gmail.com&lt;/a&gt;&amp;gt;, John Griffin&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:john@atchai.com&quot;&gt;john@atchai.com&lt;/a&gt;&amp;gt;, Nathan Creswell&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:nathantr@gmail.com&quot;&gt;nathantr@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1352&quot;&gt;1352&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Specify restricted address range for precompiles/system contracts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1380&quot;&gt;1380&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Reduced gas cost for call to self&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Jacques Wagener&amp;nbsp;(&lt;a href=&quot;https://github.com/jacqueswww&quot;&gt;@jacqueswww&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1386&quot;&gt;1386&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Attestation management contract&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Weiwu Zhang&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:a@colourful.land&quot;&gt;a@colourful.land&lt;/a&gt;&amp;gt;, James Sangalli&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:j.l.sangalli@gmail.com&quot;&gt;j.l.sangalli@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1387&quot;&gt;1387&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Merkle Tree Attestations with Privacy enabled&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Weiwu Zhang&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:a@colourful.land&quot;&gt;a@colourful.land&lt;/a&gt;&amp;gt;, James Sangalli&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:j.l.sangalli@gmail.com&quot;&gt;j.l.sangalli@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1388&quot;&gt;1388&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Attestation Issuers Management List&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Weiwu Zhang&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:a@colourful.land&quot;&gt;a@colourful.land&lt;/a&gt;&amp;gt;, James Sangalli&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:j.l.sangalli@gmail.com&quot;&gt;j.l.sangalli@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1417&quot;&gt;1417&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Poll Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Chaitanya Potti&amp;nbsp;(&lt;a href=&quot;https://github.com/chaitanyapotti&quot;&gt;@chaitanyapotti&lt;/a&gt;), Partha Bhattacharya&amp;nbsp;(&lt;a href=&quot;https://github.com/pb25193&quot;&gt;@pb25193&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1418&quot;&gt;1418&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Blockchain Storage Rent Payment&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;William Entriken&amp;nbsp;(&lt;a href=&quot;https://github.com/fulldecent&quot;&gt;@fulldecent&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1438&quot;&gt;1438&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;dApp Components (avatar) &amp;amp; Universal Wallet&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jet Lim&amp;nbsp;(&lt;a href=&quot;https://github.com/Nitro888&quot;&gt;@Nitro888&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1444&quot;&gt;1444&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Localized Messaging with Signal-to-Text&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Brooklyn Zelenka&amp;nbsp;(&lt;a href=&quot;https://github.com/expede&quot;&gt;@expede&lt;/a&gt;), Jennifer Cooper&amp;nbsp;(&lt;a href=&quot;https://github.com/jenncoop&quot;&gt;@jenncoop&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1450&quot;&gt;1450&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-1450 A compatible security token for issuing and trading SEC-compliant securities&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;John Shiple&amp;nbsp;(&lt;a href=&quot;https://github.com/johnshiple&quot;&gt;@johnshiple&lt;/a&gt;), Howard Marks&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:howard@startengine.com&quot;&gt;howard@startengine.com&lt;/a&gt;&amp;gt;, David Zhang&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:david@startengine.com&quot;&gt;david@startengine.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1459&quot;&gt;1459&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Node Discovery via DNS&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Felix Lange&amp;nbsp;(&lt;a href=&quot;https://github.com/fjl&quot;&gt;@fjl&lt;/a&gt;), Péter Szilágyi&amp;nbsp;(&lt;a href=&quot;https://github.com/karalabe&quot;&gt;@karalabe&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1462&quot;&gt;1462&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Base Security Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Maxim Kupriianov&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:mk@atlant.io&quot;&gt;mk@atlant.io&lt;/a&gt;&amp;gt;, Julian Svirsky&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:js@atlant.io&quot;&gt;js@atlant.io&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1470&quot;&gt;1470&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Smart Contract Weakness Classification (SWC)&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gerhard Wagner&amp;nbsp;(&lt;a href=&quot;https://github.com/thec00n&quot;&gt;@thec00n&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1474&quot;&gt;1474&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Remote procedure call specification&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Paul Bouchon&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:mail@bitpshr.net&quot;&gt;mail@bitpshr.net&lt;/a&gt;&amp;gt;, Erik Marks&amp;nbsp;(&lt;a href=&quot;https://github.com/rekmarks&quot;&gt;@rekmarks&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1482&quot;&gt;1482&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Define a maximum block timestamp drift&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Maurelian&amp;nbsp;(&lt;a href=&quot;https://github.com/Maurelian&quot;&gt;@Maurelian&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1484&quot;&gt;1484&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Digital Identity Aggregator&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Anurag Angara&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:anurag.angara@gmail.com&quot;&gt;anurag.angara@gmail.com&lt;/a&gt;&amp;gt;, Andy Chorlian&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:andychorlian@gmail.com&quot;&gt;andychorlian@gmail.com&lt;/a&gt;&amp;gt;, Shane Hampton&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:shanehampton1@gmail.com&quot;&gt;shanehampton1@gmail.com&lt;/a&gt;&amp;gt;, Noah Zinsmeister&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:noahwz@gmail.com&quot;&gt;noahwz@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1485&quot;&gt;1485&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;TEthashV1&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;trustfarm&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:trustfarm.info@gmail.com&quot;&gt;trustfarm.info@gmail.com&lt;/a&gt;&amp;gt;, trustfarm&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:cpplover@trustfarm.net&quot;&gt;cpplover@trustfarm.net&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1491&quot;&gt;1491&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Human Cost Accounting Standard (Like Gas but for humans)&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Iamnot Chris&amp;nbsp;(&lt;a href=&quot;https://github.com/cohabo&quot;&gt;@cohabo&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1504&quot;&gt;1504&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Upgradable Smart Contract&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Kaidong Wu&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:wukd94@pku.edu.cn&quot;&gt;wukd94@pku.edu.cn&lt;/a&gt;&amp;gt;, Chuqiao Ren&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:cr025@bucknell.edu&quot;&gt;cr025@bucknell.edu&lt;/a&gt;&amp;gt;, Ruthia He&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:rujiahe@gmail.com&quot;&gt;rujiahe@gmail.com&lt;/a&gt;&amp;gt;, Yun Ma&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:mayun@pku.edu.cn&quot;&gt;mayun@pku.edu.cn&lt;/a&gt;&amp;gt;, Xuanzhe Liu&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:liuxuanzhe@pku.edu.cn&quot;&gt;liuxuanzhe@pku.edu.cn&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1523&quot;&gt;1523&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Standard for Insurance Policies as ERC-721 Non Fungible Tokens&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Christoph Mussenbrock&amp;nbsp;(&lt;a href=&quot;https://github.com/christoph2806&quot;&gt;@christoph2806&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1571&quot;&gt;1571&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EthereumStratum/2.0.0&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Andrea Lanfranchi&amp;nbsp;(&lt;a href=&quot;https://github.com/AndreaLanfranchi&quot;&gt;@AndreaLanfranchi&lt;/a&gt;), Pawel Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;), Marius Van Der Wijden&amp;nbsp;(&lt;a href=&quot;https://github.com/MariusVanDerWijden&quot;&gt;@MariusVanDerWijden&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1577&quot;&gt;1577&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;contenthash field for ENS&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Dean Eigenmann&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:dean@ens.domains&quot;&gt;dean@ens.domains&lt;/a&gt;&amp;gt;, Nick Johnson&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:nick@ens.domains&quot;&gt;nick@ens.domains&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1581&quot;&gt;1581&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Non-wallet usage of keys derived from BIP-32 trees&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Michele Balistreri&amp;nbsp;(&lt;a href=&quot;https://github.com/bitgamma&quot;&gt;@bitgamma&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1588&quot;&gt;1588&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hardfork Meta: Ethereum ProgPoW&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ikmyeong Na&amp;nbsp;(&lt;a href=&quot;https://github.com/naikmyeong&quot;&gt;@naikmyeong&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1592&quot;&gt;1592&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Address and ERC20-compliant transfer rules&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Cyril Lapinte&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:cyril.lapinte@mtpelerin.com&quot;&gt;cyril.lapinte@mtpelerin.com&lt;/a&gt;&amp;gt;, Laurent Aapro&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:laurent.aapro@mtpelerin.com&quot;&gt;laurent.aapro@mtpelerin.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1613&quot;&gt;1613&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Gas stations network&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Yoav Weiss&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:yoav@tabookey.com&quot;&gt;yoav@tabookey.com&lt;/a&gt;&amp;gt;, Dror Tirosh&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:dror@tabookey.com&quot;&gt;dror@tabookey.com&lt;/a&gt;&amp;gt;, Alex Forshtat&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:alex@tabookey.com&quot;&gt;alex@tabookey.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1616&quot;&gt;1616&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Attribute Registry Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;0age&amp;nbsp;(&lt;a href=&quot;https://github.com/0age&quot;&gt;@0age&lt;/a&gt;), Santiago Palladino&amp;nbsp;(&lt;a href=&quot;https://github.com/spalladino&quot;&gt;@spalladino&lt;/a&gt;), Leo Arias&amp;nbsp;(&lt;a href=&quot;https://github.com/elopio&quot;&gt;@elopio&lt;/a&gt;), Alejo Salles&amp;nbsp;(&lt;a href=&quot;https://github.com/fiiiu&quot;&gt;@fiiiu&lt;/a&gt;), Stephane Gosselin&amp;nbsp;(&lt;a href=&quot;https://github.com/thegostep&quot;&gt;@thegostep&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1620&quot;&gt;1620&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Money Streaming&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Paul Berg&amp;nbsp;(&lt;a href=&quot;https://github.com/PaulRBerg&quot;&gt;@PaulRBerg&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1633&quot;&gt;1633&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Re-Fungible Token Standard (RFT)&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Billy Rennekamp&amp;nbsp;(&lt;a href=&quot;https://github.com/okwme&quot;&gt;@okwme&lt;/a&gt;), Dan Long&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:dan@artblx.com&quot;&gt;dan@artblx.com&lt;/a&gt;&amp;gt;, Kiryl Yermakou&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:kiryl@artblx.com&quot;&gt;kiryl@artblx.com&lt;/a&gt;&amp;gt;, Nate van der Ende&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:nate@artblx.com&quot;&gt;nate@artblx.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1681&quot;&gt;1681&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Temporal Replay Protection&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Martin Holst Swende&amp;nbsp;(&lt;a href=&quot;https://github.com/holiman&quot;&gt;@holiman&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1702&quot;&gt;1702&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Generalized Account Versioning Scheme&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Wei Tang&amp;nbsp;(&lt;a href=&quot;https://github.com/sorpaas&quot;&gt;@sorpaas&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1710&quot;&gt;1710&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;URL Format for Web3 Browsers&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Bruno Barbieri&amp;nbsp;(&lt;a href=&quot;https://github.com/brunobar79&quot;&gt;@brunobar79&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1753&quot;&gt;1753&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Smart Contract Interface for Licences&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Lucas Cullen&amp;nbsp;(&lt;a href=&quot;https://github.com/BitcoinBrisbane&quot;&gt;@BitcoinBrisbane&lt;/a&gt;), Kai Yeung&amp;nbsp;(&lt;a href=&quot;https://github.com/CivicKai&quot;&gt;@CivicKai&lt;/a&gt;), Anna Crowley&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:annaelizabethcrowley@gmail.com&quot;&gt;annaelizabethcrowley@gmail.com&lt;/a&gt;&amp;gt;, Caroline Marshall&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:caroline.marshall888@gmail.com&quot;&gt;caroline.marshall888@gmail.com&lt;/a&gt;&amp;gt;, Katrina Donaghy&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:katrina@civicledger.com&quot;&gt;katrina@civicledger.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1761&quot;&gt;1761&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Scoped Approval Interface&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Witek Radomski&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:witek@enjin.io&quot;&gt;witek@enjin.io&lt;/a&gt;&amp;gt;, Andrew Cooke&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:ac0dem0nk3y@gmail.com&quot;&gt;ac0dem0nk3y@gmail.com&lt;/a&gt;&amp;gt;, James Therien&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:james@enjin.io&quot;&gt;james@enjin.io&lt;/a&gt;&amp;gt;, Eric Binet&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:eric@enjin.io&quot;&gt;eric@enjin.io&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1767&quot;&gt;1767&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;GraphQL interface to Ethereum node data&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Johnson&amp;nbsp;(&lt;a href=&quot;https://github.com/arachnid&quot;&gt;@arachnid&lt;/a&gt;), Raúl Kripalani&amp;nbsp;(&lt;a href=&quot;https://github.com/raulk&quot;&gt;@raulk&lt;/a&gt;), Kris Shinn&amp;nbsp;(&lt;a href=&quot;https://github.com/kshinn&quot;&gt;@kshinn&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1775&quot;&gt;1775&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;App Keys, application specific wallet accounts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vincent Eli&amp;nbsp;(&lt;a href=&quot;https://github.com/Bunjin&quot;&gt;@Bunjin&lt;/a&gt;), Dan Finlay&amp;nbsp;(&lt;a href=&quot;https://github.com/DanFinlay&quot;&gt;@DanFinlay&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1803&quot;&gt;1803&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Rename opcodes for clarity&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1812&quot;&gt;1812&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Ethereum Verifiable Claims&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Pelle Braendgaard&amp;nbsp;(&lt;a href=&quot;https://github.com/pelle&quot;&gt;@pelle&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1822&quot;&gt;1822&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Universal Upgradeable Proxy Standard (UUPS)&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gabriel Barros&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:gabriel@terminal.co&quot;&gt;gabriel@terminal.co&lt;/a&gt;&amp;gt;, Patrick Gallagher&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:blockchainbuddha@gmail.com&quot;&gt;blockchainbuddha@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1829&quot;&gt;1829&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Precompile for Elliptic Curve Linear Combinations&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Remco Bloemen&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:Recmo@0x.org&quot;&gt;Recmo@0x.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1844&quot;&gt;1844&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ENS Interface Discovery&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Johnson&amp;nbsp;(&lt;a href=&quot;https://github.com/arachnid&quot;&gt;@arachnid&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1872&quot;&gt;1872&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Ethereum Network Upgrade Windows&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Danno Ferrin&amp;nbsp;(&lt;a href=&quot;https://github.com/shemnon&quot;&gt;@shemnon&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1895&quot;&gt;1895&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Support for an Elliptic Curve Cycle&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alexandre Belling&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:alexandrebelling8@gmail.com&quot;&gt;alexandrebelling8@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1900&quot;&gt;1900&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;dType - Decentralized Type System for EVM&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Loredana Cirstea&amp;nbsp;(&lt;a href=&quot;https://github.com/loredanacirstea&quot;&gt;@loredanacirstea&lt;/a&gt;), Christian Tzurcanu&amp;nbsp;(&lt;a href=&quot;https://github.com/ctzurcanu&quot;&gt;@ctzurcanu&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1901&quot;&gt;1901&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Add OpenRPC Service Discovery To JSON-RPC Services&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Shane Jonas&amp;nbsp;(&lt;a href=&quot;https://github.com/shanejonas&quot;&gt;@shanejonas&lt;/a&gt;), Zachary Belford&amp;nbsp;(&lt;a href=&quot;https://github.com/belfordz&quot;&gt;@belfordz&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1921&quot;&gt;1921&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;dType Functions Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Loredana Cirstea&amp;nbsp;(&lt;a href=&quot;https://github.com/loredanacirstea&quot;&gt;@loredanacirstea&lt;/a&gt;), Christian Tzurcanu&amp;nbsp;(&lt;a href=&quot;https://github.com/ctzurcanu&quot;&gt;@ctzurcanu&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1922&quot;&gt;1922&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;zk-SNARK Verifier Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Michael Connor&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:michael.connor@uk.ey.com&quot;&gt;michael.connor@uk.ey.com&lt;/a&gt;&amp;gt;, Chaitanya Konda&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:chaitanya.konda@uk.ey.com&quot;&gt;chaitanya.konda@uk.ey.com&lt;/a&gt;&amp;gt;, Duncan Westland&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:duncan.westland@uk.ey.com&quot;&gt;duncan.westland@uk.ey.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1923&quot;&gt;1923&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;zk-SNARK Verifier Registry Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Michael Connor&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:michael.connor@uk.ey.com&quot;&gt;michael.connor@uk.ey.com&lt;/a&gt;&amp;gt;, Chaitanya Konda&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:chaitanya.konda@uk.ey.com&quot;&gt;chaitanya.konda@uk.ey.com&lt;/a&gt;&amp;gt;, Duncan Westland&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:duncan.westland@uk.ey.com&quot;&gt;duncan.westland@uk.ey.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1930&quot;&gt;1930&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;CALLs with strict gas semantic. Revert if not enough gas available.&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ronan Sandford&amp;nbsp;(&lt;a href=&quot;https://github.com/wighawag&quot;&gt;@wighawag&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1948&quot;&gt;1948&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Non-fungible Data Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Johann Barbie&amp;nbsp;(&lt;a href=&quot;https://github.com/johannbarbie&quot;&gt;@johannbarbie&lt;/a&gt;), Ben Bollen&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:ben@ost.com&quot;&gt;ben@ost.com&lt;/a&gt;&amp;gt;, pinkiebell&amp;nbsp;(&lt;a href=&quot;https://github.com/pinkiebell&quot;&gt;@pinkiebell&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1959&quot;&gt;1959&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;New Opcode to check if a chainID is part of the history of chainIDs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ronan Sandford&amp;nbsp;(&lt;a href=&quot;https://github.com/wighawag&quot;&gt;@wighawag&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1962&quot;&gt;1962&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EC arithmetic and pairings with runtime definitions&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Vlasov&amp;nbsp;(&lt;a href=&quot;https://github.com/shamatar&quot;&gt;@shamatar&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1965&quot;&gt;1965&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Method to check if a chainID is valid at a specific block Number&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ronan Sandford&amp;nbsp;(&lt;a href=&quot;https://github.com/wighawag&quot;&gt;@wighawag&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1973&quot;&gt;1973&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Scalable Rewards&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Lee Raj&amp;nbsp;(&lt;a href=&quot;https://github.com/lerajk&quot;&gt;@lerajk&lt;/a&gt;), Qin Jian&amp;nbsp;(&lt;a href=&quot;https://github.com/qinjian&quot;&gt;@qinjian&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1985&quot;&gt;1985&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Sane limits for certain EVM parameters&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1996&quot;&gt;1996&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Holdable Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Julio Faura&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:julio@adhara.io&quot;&gt;julio@adhara.io&lt;/a&gt;&amp;gt;, Fernando Paris&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:fer@io.builders&quot;&gt;fer@io.builders&lt;/a&gt;&amp;gt;, Daniel Lehrner&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:daniel@io.builders&quot;&gt;daniel@io.builders&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2003&quot;&gt;2003&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EVMC modules for implementations of precompiled contracts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;), Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2009&quot;&gt;2009&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Compliance Service&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Daniel Lehrner&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:daniel@io.builders&quot;&gt;daniel@io.builders&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2014&quot;&gt;2014&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Extended State Oracle&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2015&quot;&gt;2015&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;wallet_updateEthereumChain RPC Method&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Pedro Gomes&amp;nbsp;(&lt;a href=&quot;https://github.com/pedrouid&quot;&gt;@pedrouid&lt;/a&gt;), Erik Marks&amp;nbsp;(&lt;a href=&quot;https://github.com/rekmarks&quot;&gt;@rekmarks&lt;/a&gt;), Pandapip1&amp;nbsp;(&lt;a href=&quot;https://github.com/Pandapip1&quot;&gt;@Pandapip1&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2018&quot;&gt;2018&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Clearable Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Julio Faura&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:julio@adhara.io&quot;&gt;julio@adhara.io&lt;/a&gt;&amp;gt;, Fernando Paris&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:fer@io.builders&quot;&gt;fer@io.builders&lt;/a&gt;&amp;gt;, Daniel Lehrner&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:daniel@io.builders&quot;&gt;daniel@io.builders&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2019&quot;&gt;2019&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Fundable Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Fernando Paris&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:fer@io.builders&quot;&gt;fer@io.builders&lt;/a&gt;&amp;gt;, Julio Faura&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:julio@adhara.io&quot;&gt;julio@adhara.io&lt;/a&gt;&amp;gt;, Daniel Lehrner&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:daniel@io.builders&quot;&gt;daniel@io.builders&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2020&quot;&gt;2020&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;E-Money Standard Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Julio Faura&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:julio@adhara.io&quot;&gt;julio@adhara.io&lt;/a&gt;&amp;gt;, Fernando Paris&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:fer@io.builders&quot;&gt;fer@io.builders&lt;/a&gt;&amp;gt;, Daniel Lehrner&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:daniel@io.builders&quot;&gt;daniel@io.builders&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2021&quot;&gt;2021&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Payoutable Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Fernando Paris&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:fer@io.builders&quot;&gt;fer@io.builders&lt;/a&gt;&amp;gt;, Julio Faura&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:julio@adhara.io&quot;&gt;julio@adhara.io&lt;/a&gt;&amp;gt;, Daniel Lehrner&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:daniel@io.builders&quot;&gt;daniel@io.builders&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2026&quot;&gt;2026&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;State Rent H - Fixed Prepayment for accounts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alexey Akhunov&amp;nbsp;(&lt;a href=&quot;https://github.com/AlexeyAkhunov&quot;&gt;@AlexeyAkhunov&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2027&quot;&gt;2027&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;State Rent C - Net contract size accounting&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alexey Akhunov&amp;nbsp;(&lt;a href=&quot;https://github.com/AlexeyAkhunov&quot;&gt;@AlexeyAkhunov&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2029&quot;&gt;2029&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;State Rent A - State counters contract&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alexey Akhunov&amp;nbsp;(&lt;a href=&quot;https://github.com/AlexeyAkhunov&quot;&gt;@AlexeyAkhunov&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2031&quot;&gt;2031&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;State Rent B - Net transaction counter&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alexey Akhunov&amp;nbsp;(&lt;a href=&quot;https://github.com/AlexeyAkhunov&quot;&gt;@AlexeyAkhunov&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2035&quot;&gt;2035&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Stateless Clients - Repricing SLOAD and SSTORE to pay for block proofs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alexey Akhunov&amp;nbsp;(&lt;a href=&quot;https://github.com/AlexeyAkhunov&quot;&gt;@AlexeyAkhunov&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2045&quot;&gt;2045&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Particle gas costs for EVM opcodes&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Casey Detrio&amp;nbsp;(&lt;a href=&quot;https://github.com/cdetrio&quot;&gt;@cdetrio&lt;/a&gt;), Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2046&quot;&gt;2046&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Reduced gas cost for static calls made to precompiles&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2069&quot;&gt;2069&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Recommendation for using YAML ABI in ERCs/EIPs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2157&quot;&gt;2157&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;dType Storage Extension - Decentralized Type System for EVM&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Loredana Cirstea&amp;nbsp;(&lt;a href=&quot;https://github.com/loredanacirstea&quot;&gt;@loredanacirstea&lt;/a&gt;), Christian Tzurcanu&amp;nbsp;(&lt;a href=&quot;https://github.com/ctzurcanu&quot;&gt;@ctzurcanu&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2193&quot;&gt;2193&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;dType Alias Extension - Decentralized Type System&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Loredana Cirstea&amp;nbsp;(&lt;a href=&quot;https://github.com/loredanacirstea&quot;&gt;@loredanacirstea&lt;/a&gt;), Christian Tzurcanu&amp;nbsp;(&lt;a href=&quot;https://github.com/ctzurcanu&quot;&gt;@ctzurcanu&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2242&quot;&gt;2242&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Transaction Postdata&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;John Adler&amp;nbsp;(&lt;a href=&quot;https://github.com/adlerjohn&quot;&gt;@adlerjohn&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2256&quot;&gt;2256&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;wallet_getOwnedAssets JSON-RPC Method&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Loredana Cirstea&amp;nbsp;(&lt;a href=&quot;https://github.com/loredanacirstea&quot;&gt;@loredanacirstea&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2294&quot;&gt;2294&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Explicit bound to Chain ID size&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Zainan Victor Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/xinbenlv&quot;&gt;@xinbenlv&lt;/a&gt;), Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Bryant Eisenbach&amp;nbsp;(&lt;a href=&quot;https://github.com/fubuloubu&quot;&gt;@fubuloubu&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2304&quot;&gt;2304&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Multichain address resolution for ENS&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Johnson&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:nick@ens.domains&quot;&gt;nick@ens.domains&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2327&quot;&gt;2327&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;BEGINDATA opcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Martin Lundfall&amp;nbsp;(&lt;a href=&quot;https://github.com/MrChico&quot;&gt;@MrChico&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2330&quot;&gt;2330&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EXTSLOAD opcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Dominic Letz&amp;nbsp;(&lt;a href=&quot;https://github.com/dominicletz&quot;&gt;@dominicletz&lt;/a&gt;), Santiago Palladino&amp;nbsp;(&lt;a href=&quot;https://github.com/spalladino&quot;&gt;@spalladino&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2378&quot;&gt;2378&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EIPs Eligible for Inclusion&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;James Hancock&amp;nbsp;(&lt;a href=&quot;https://github.com/MadeofTin&quot;&gt;@MadeofTin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2386&quot;&gt;2386&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Ethereum 2 Hierarchical Deterministic Walletstore&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jim McDonald&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:Jim@mcdee.net&quot;&gt;Jim@mcdee.net&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2390&quot;&gt;2390&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Geo-ENS&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;James Choncholas&amp;nbsp;(&lt;a href=&quot;https://github.com/james-choncholas&quot;&gt;@james-choncholas&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2400&quot;&gt;2400&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Transaction Receipt URI&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ricardo Guilherme Schmidt&amp;nbsp;(&lt;a href=&quot;https://github.com/3esmit&quot;&gt;@3esmit&lt;/a&gt;), Eric Dvorsak&amp;nbsp;(&lt;a href=&quot;https://github.com/yenda&quot;&gt;@yenda&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2470&quot;&gt;2470&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Singleton Factory&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ricardo Guilherme Schmidt&amp;nbsp;(&lt;a href=&quot;https://github.com/3esmit&quot;&gt;@3esmit&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2474&quot;&gt;2474&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Coinbase calls&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ricardo Guilherme Schmidt&amp;nbsp;(&lt;a href=&quot;https://github.com/3esmit&quot;&gt;@3esmit&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2477&quot;&gt;2477&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Token Metadata Integrity&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Kristijan Sedlak&amp;nbsp;(&lt;a href=&quot;https://github.com/xpepermint&quot;&gt;@xpepermint&lt;/a&gt;), William Entriken&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:github.com@phor.net&quot;&gt;github.com@phor.net&lt;/a&gt;&amp;gt;, Witek Radomski&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:witek@enjin.io&quot;&gt;witek@enjin.io&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2488&quot;&gt;2488&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Deprecate the CALLCODE opcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2494&quot;&gt;2494&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Baby Jubjub Elliptic Curve&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Barry WhiteHat&amp;nbsp;(&lt;a href=&quot;https://github.com/barryWhiteHat&quot;&gt;@barryWhiteHat&lt;/a&gt;), Marta Bellés&amp;nbsp;(&lt;a href=&quot;https://github.com/bellesmarta&quot;&gt;@bellesmarta&lt;/a&gt;), Jordi Baylina&amp;nbsp;(&lt;a href=&quot;https://github.com/jbaylina&quot;&gt;@jbaylina&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2515&quot;&gt;2515&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Implement Difficulty Freeze&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;James Hancock&amp;nbsp;(&lt;a href=&quot;https://github.com/madeoftin&quot;&gt;@madeoftin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2520&quot;&gt;2520&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Multiple contenthash records for ENS&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Filip Štamcar&amp;nbsp;(&lt;a href=&quot;https://github.com/filips123&quot;&gt;@filips123&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2525&quot;&gt;2525&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ENSLogin&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Hadrien Croubois&amp;nbsp;(&lt;a href=&quot;https://github.com/amxx&quot;&gt;@amxx&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2539&quot;&gt;2539&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;BLS12-377 curve operations&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Vlasov&amp;nbsp;(&lt;a href=&quot;https://github.com/shamatar&quot;&gt;@shamatar&lt;/a&gt;), hujw77&amp;nbsp;(&lt;a href=&quot;https://github.com/hujw77&quot;&gt;@hujw77&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2542&quot;&gt;2542&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;New opcodes TXGASLIMIT and CALLGASLIMIT&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Forshtat&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:forshtat1@gmail.com&quot;&gt;forshtat1@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2544&quot;&gt;2544&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ENS Wildcard Resolution&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Johnson&amp;nbsp;(&lt;a href=&quot;https://github.com/arachnid&quot;&gt;@arachnid&lt;/a&gt;), 0age&amp;nbsp;(&lt;a href=&quot;https://github.com/0age&quot;&gt;@0age&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2566&quot;&gt;2566&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Human Readable Parameters for Contract Function Execution&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Joseph Stockermans&amp;nbsp;(&lt;a href=&quot;https://github.com/jstoxrocky&quot;&gt;@jstoxrocky&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2569&quot;&gt;2569&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Saving and Displaying Image Onchain for Universal Tokens&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Hua Zhang&amp;nbsp;(&lt;a href=&quot;https://github.com/dgczhh&quot;&gt;@dgczhh&lt;/a&gt;), Yuefei Tan&amp;nbsp;(&lt;a href=&quot;https://github.com/whtyfhas&quot;&gt;@whtyfhas&lt;/a&gt;), Derek Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/zhous&quot;&gt;@zhous&lt;/a&gt;), Ran Xing&amp;nbsp;(&lt;a href=&quot;https://github.com/lemontreeran&quot;&gt;@lemontreeran&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2583&quot;&gt;2583&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Penalty for account trie misses&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Martin Holst Swende&amp;nbsp;(&lt;a href=&quot;https://github.com/holiman&quot;&gt;@holiman&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2584&quot;&gt;2584&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Trie format transition with overlay trees&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Guillaume Ballet&amp;nbsp;(&lt;a href=&quot;https://github.com/gballet&quot;&gt;@gballet&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2593&quot;&gt;2593&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Escalator fee market change for ETH 1.0 chain&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Dan Finlay&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:dan@danfinlay.com&quot;&gt;dan@danfinlay.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2615&quot;&gt;2615&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Non-Fungible Token with mortgage and rental functions&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Kohshi Shiba&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:kohshi.shiba@gmail.com&quot;&gt;kohshi.shiba@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2645&quot;&gt;2645&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hierarchical Deterministic Wallet for Layer-2&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Tom Brand&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:tom@starkware.co&quot;&gt;tom@starkware.co&lt;/a&gt;&amp;gt;, Louis Guthmann&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:louis@starkware.co&quot;&gt;louis@starkware.co&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2657&quot;&gt;2657&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Ephemeral Testnet Yolo&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;James Hancock&amp;nbsp;(&lt;a href=&quot;https://github.com/madeoftin&quot;&gt;@madeoftin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2666&quot;&gt;2666&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Repricing of precompiles and Keccak256 function&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Vlasov&amp;nbsp;(&lt;a href=&quot;https://github.com/shamatar&quot;&gt;@shamatar&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2680&quot;&gt;2680&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Ethereum 2 wallet layout&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jim McDonald&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:Jim@mcdee.net&quot;&gt;Jim@mcdee.net&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2746&quot;&gt;2746&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Rules Engine Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Aaron Kendall&amp;nbsp;(&lt;a href=&quot;https://github.com/jaerith&quot;&gt;@jaerith&lt;/a&gt;), Juan Blanco&amp;nbsp;(&lt;a href=&quot;https://github.com/juanfranblanco&quot;&gt;@juanfranblanco&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2767&quot;&gt;2767&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Contract Ownership Governance&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Soham Zemse&amp;nbsp;(&lt;a href=&quot;https://github.com/zemse&quot;&gt;@zemse&lt;/a&gt;), Nick Mudge&amp;nbsp;(&lt;a href=&quot;https://github.com/mudgen&quot;&gt;@mudgen&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2770&quot;&gt;2770&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Meta-Transactions Forwarder Contract&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Forshtat&amp;nbsp;(&lt;a href=&quot;https://github.com/forshtat&quot;&gt;@forshtat&lt;/a&gt;), Dror Tirosh&amp;nbsp;(&lt;a href=&quot;https://github.com/drortirosh&quot;&gt;@drortirosh&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2803&quot;&gt;2803&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Rich Transactions&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Micah Zoltu&amp;nbsp;(&lt;a href=&quot;https://github.com/MicahZoltu&quot;&gt;@MicahZoltu&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2831&quot;&gt;2831&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Transaction Replacement Message Type&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gregory Markou&amp;nbsp;(&lt;a href=&quot;https://github.com/GregTheGreek&quot;&gt;@GregTheGreek&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2844&quot;&gt;2844&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Add DID related methods to the JSON-RPC&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Joel Thorstensson&amp;nbsp;(&lt;a href=&quot;https://github.com/oed&quot;&gt;@oed&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2848&quot;&gt;2848&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;My Own Messages (MOM)&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Giuseppe Bertone&amp;nbsp;(&lt;a href=&quot;https://github.com/Neurone&quot;&gt;@Neurone&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2876&quot;&gt;2876&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Deposit contract and address standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jonathan Underwood&amp;nbsp;(&lt;a href=&quot;https://github.com/junderw&quot;&gt;@junderw&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2917&quot;&gt;2917&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Staking Reward Calculation&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Tony Carson&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:tony.carsonn@gmail.com&quot;&gt;tony.carsonn@gmail.com&lt;/a&gt;&amp;gt;, Mehmet Sabir Kiraz&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:m.kiraz@gmail.com&quot;&gt;m.kiraz@gmail.com&lt;/a&gt;&amp;gt;, Süleyman Kardaş&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:skardas@gmail.com&quot;&gt;skardas@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2936&quot;&gt;2936&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EXTCLEAR Opcode For SELFDESTRUCTed contracts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;William Morriss&amp;nbsp;(&lt;a href=&quot;https://github.com/wjmelements&quot;&gt;@wjmelements&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2937&quot;&gt;2937&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;SET_INDESTRUCTIBLE opcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2942&quot;&gt;2942&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EthPM URI Specification&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Gheorghita&amp;nbsp;(&lt;a href=&quot;https://github.com/njgheorghita&quot;&gt;@njgheorghita&lt;/a&gt;), Piper Merriam&amp;nbsp;(&lt;a href=&quot;https://github.com/pipermerriam&quot;&gt;@pipermerriam&lt;/a&gt;), g. nicholas d&apos;andrea&amp;nbsp;(&lt;a href=&quot;https://github.com/gnidan&quot;&gt;@gnidan&lt;/a&gt;), Benjamin Hauser&amp;nbsp;(&lt;a href=&quot;https://github.com/iamdefinitelyahuman&quot;&gt;@iamdefinitelyahuman&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2970&quot;&gt;2970&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;IS_STATIC opcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2980&quot;&gt;2980&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Swiss Compliant Asset Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gianluca Perletti&amp;nbsp;(&lt;a href=&quot;https://github.com/Perlets9&quot;&gt;@Perlets9&lt;/a&gt;), Alan Scarpellini&amp;nbsp;(&lt;a href=&quot;https://github.com/alanscarpellini&quot;&gt;@alanscarpellini&lt;/a&gt;), Roberto Gorini&amp;nbsp;(&lt;a href=&quot;https://github.com/robertogorini&quot;&gt;@robertogorini&lt;/a&gt;), Manuel Olivi&amp;nbsp;(&lt;a href=&quot;https://github.com/manvel79&quot;&gt;@manvel79&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2997&quot;&gt;2997&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;IMPERSONATECALL Opcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Sergio Demian Lerner&amp;nbsp;(&lt;a href=&quot;https://github.com/SergioDemianLerner&quot;&gt;@SergioDemianLerner&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3000&quot;&gt;3000&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Optimistic enactment governance standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jorge Izquierdo&amp;nbsp;(&lt;a href=&quot;https://github.com/izqui&quot;&gt;@izqui&lt;/a&gt;), Fabien Marino&amp;nbsp;(&lt;a href=&quot;https://github.com/bonustrack&quot;&gt;@bonustrack&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3005&quot;&gt;3005&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Batched meta transactions&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Matt&amp;nbsp;(&lt;a href=&quot;https://github.com/defifuture&quot;&gt;@defifuture&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3014&quot;&gt;3014&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;eth_symbol JSON-RPC method&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Peter Grassberger&amp;nbsp;(&lt;a href=&quot;https://github.com/PeterTheOne&quot;&gt;@PeterTheOne&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3026&quot;&gt;3026&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;BW6-761 curve operations&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Youssef El Housni&amp;nbsp;(&lt;a href=&quot;https://github.com/yelhousni&quot;&gt;@yelhousni&lt;/a&gt;), Michael Connor&amp;nbsp;(&lt;a href=&quot;https://github.com/iAmMichaelConnor&quot;&gt;@iAmMichaelConnor&lt;/a&gt;), Aurore Guillevic&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:aurore.guillevic@inria.fr&quot;&gt;aurore.guillevic@inria.fr&lt;/a&gt;&amp;gt;, hujw77&amp;nbsp;(&lt;a href=&quot;https://github.com/hujw77&quot;&gt;@hujw77&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3030&quot;&gt;3030&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;BLS Remote Signer HTTP API&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Herman Junge&amp;nbsp;(&lt;a href=&quot;https://github.com/hermanjunge&quot;&gt;@hermanjunge&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3041&quot;&gt;3041&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Adds `baseFee` to `eth_getBlockByHash`&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Abdelhamid Bakhta&amp;nbsp;(&lt;a href=&quot;https://github.com/abdelhamidbakhta&quot;&gt;@abdelhamidbakhta&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3044&quot;&gt;3044&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Adds `baseFee` to `eth_getBlockByNumber`&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Abdelhamid Bakhta&amp;nbsp;(&lt;a href=&quot;https://github.com/abdelhamidbakhta&quot;&gt;@abdelhamidbakhta&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3045&quot;&gt;3045&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Adds `baseFee` to `eth_getUncleByBlockHashAndIndex`&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Abdelhamid Bakhta&amp;nbsp;(&lt;a href=&quot;https://github.com/abdelhamidbakhta&quot;&gt;@abdelhamidbakhta&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3046&quot;&gt;3046&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Adds `baseFee` to `eth_getUncleByBlockNumberAndIndex`&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Abdelhamid Bakhta&amp;nbsp;(&lt;a href=&quot;https://github.com/abdelhamidbakhta&quot;&gt;@abdelhamidbakhta&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3068&quot;&gt;3068&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Precompile for BN256 HashToCurve Algorithms&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Dr. Christopher Gorman&amp;nbsp;(&lt;a href=&quot;https://github.com/chgormanMH&quot;&gt;@chgormanMH&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3085&quot;&gt;3085&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;wallet_addEthereumChain RPC Method&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Erik Marks&amp;nbsp;(&lt;a href=&quot;https://github.com/rekmarks&quot;&gt;@rekmarks&lt;/a&gt;), Pedro Gomes&amp;nbsp;(&lt;a href=&quot;https://github.com/pedrouid&quot;&gt;@pedrouid&lt;/a&gt;), Pandapip1&amp;nbsp;(&lt;a href=&quot;https://github.com/Pandapip1&quot;&gt;@Pandapip1&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3091&quot;&gt;3091&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Block Explorer API Routes&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Pedro Gomes&amp;nbsp;(&lt;a href=&quot;https://github.com/pedrouid&quot;&gt;@pedrouid&lt;/a&gt;), ligi&amp;nbsp;(&lt;a href=&quot;https://github.com/ligi&quot;&gt;@ligi&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3102&quot;&gt;3102&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Binary trie structure&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Guillaume Ballet&amp;nbsp;(&lt;a href=&quot;https://github.com/gballet&quot;&gt;@gballet&lt;/a&gt;), Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3135&quot;&gt;3135&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Exclusive Claimable Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Zhenyu Sun&amp;nbsp;(&lt;a href=&quot;https://github.com/Ungigdu&quot;&gt;@Ungigdu&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3143&quot;&gt;3143&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Increase block rewards to 5 ETH&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ben Tinner&amp;nbsp;(&lt;a href=&quot;https://github.com/Terra854&quot;&gt;@Terra854&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3220&quot;&gt;3220&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Crosschain Identifier Specification&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Weijia Zhang&amp;nbsp;(&lt;a href=&quot;https://github.com/weijia31415&quot;&gt;@weijia31415&lt;/a&gt;), Peter Robinson&amp;nbsp;(&lt;a href=&quot;https://github.com/drinkcoffee&quot;&gt;@drinkcoffee&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3224&quot;&gt;3224&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Described Data&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Richard Moore&amp;nbsp;(&lt;a href=&quot;https://github.com/ricmoo&quot;&gt;@ricmoo&lt;/a&gt;), Nick Johnson&amp;nbsp;(&lt;a href=&quot;https://github.com/arachnid&quot;&gt;@arachnid&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3234&quot;&gt;3234&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Batch Flash Loans&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alberto Cuesta Cañada&amp;nbsp;(&lt;a href=&quot;https://github.com/albertocuestacanada&quot;&gt;@albertocuestacanada&lt;/a&gt;), Fiona Kobayashi&amp;nbsp;(&lt;a href=&quot;https://github.com/fifikobayashi&quot;&gt;@fifikobayashi&lt;/a&gt;), fubuloubu&amp;nbsp;(&lt;a href=&quot;https://github.com/fubuloubu&quot;&gt;@fubuloubu&lt;/a&gt;), Austin Williams&amp;nbsp;(&lt;a href=&quot;https://github.com/onewayfunction&quot;&gt;@onewayfunction&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3238&quot;&gt;3238&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Difficulty Bomb Delay to Q2/2022&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Afri Schoedon&amp;nbsp;(&lt;a href=&quot;https://github.com/q9f&quot;&gt;@q9f&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3267&quot;&gt;3267&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Giving Ethereum fees to Future Salaries&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Victor Porton&amp;nbsp;(&lt;a href=&quot;https://github.com/vporton&quot;&gt;@vporton&lt;/a&gt;), Victor Porton&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:porton@narod.ru&quot;&gt;porton@narod.ru&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3298&quot;&gt;3298&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Removal of refunds&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Martin Swende&amp;nbsp;(&lt;a href=&quot;https://github.com/holiman&quot;&gt;@holiman&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3300&quot;&gt;3300&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Phase out refunds&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;William Morriss&amp;nbsp;(&lt;a href=&quot;https://github.com/wjmelements&quot;&gt;@wjmelements&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3322&quot;&gt;3322&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Account gas storage opcodes&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;William Morriss&amp;nbsp;(&lt;a href=&quot;https://github.com/wjmelements&quot;&gt;@wjmelements&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3326&quot;&gt;3326&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Wallet Switch Ethereum Chain RPC Method (`wallet_switchEthereumChain`)&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Erik Marks&amp;nbsp;(&lt;a href=&quot;https://github.com/rekmarks&quot;&gt;@rekmarks&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3336&quot;&gt;3336&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Paged memory allocation for the EVM&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Johnson&amp;nbsp;(&lt;a href=&quot;https://github.com/arachnid&quot;&gt;@arachnid&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3337&quot;&gt;3337&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Frame pointer support for memory load and store operations&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Johnson&amp;nbsp;(&lt;a href=&quot;https://github.com/arachnid&quot;&gt;@arachnid&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3368&quot;&gt;3368&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Increase block rewards to 3 ETH, with 2 Year Decay to 1 ETH Scheduled&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Michael D. Carter&amp;nbsp;(&lt;a href=&quot;https://github.com/BitsBeTrippin&quot;&gt;@BitsBeTrippin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3372&quot;&gt;3372&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;5 FNV primes for ethash&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;mineruniter969&amp;nbsp;(&lt;a href=&quot;https://github.com/mineruniter969&quot;&gt;@mineruniter969&lt;/a&gt;), mineruniter969&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:mineruniter969@tutanota.com&quot;&gt;mineruniter969@tutanota.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3386&quot;&gt;3386&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-721 and ERC-1155 to ERC-20 Wrapper&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Calvin Koder&amp;nbsp;(&lt;a href=&quot;https://github.com/ashrowz&quot;&gt;@ashrowz&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3403&quot;&gt;3403&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Partial removal of refunds&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Martin Swende&amp;nbsp;(&lt;a href=&quot;https://github.com/holiman&quot;&gt;@holiman&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3416&quot;&gt;3416&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Median Gas Premium&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;HexZorro&amp;nbsp;(&lt;a href=&quot;https://github.com/hexzorro&quot;&gt;@hexzorro&lt;/a&gt;), Mojtaba Tefagh&amp;nbsp;(&lt;a href=&quot;https://github.com/mtefagh&quot;&gt;@mtefagh&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3436&quot;&gt;3436&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Expanded Clique Block Choice Rule&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Danno Ferrin&amp;nbsp;(&lt;a href=&quot;https://github.com/shemnon&quot;&gt;@shemnon&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3440&quot;&gt;3440&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-721 Editions Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nathan Ginnever&amp;nbsp;(&lt;a href=&quot;https://github.com/nginnever&quot;&gt;@nginnever&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3450&quot;&gt;3450&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Standardized Shamir Secret Sharing Scheme for BIP-39 Mnemonics&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Daniel Streit&amp;nbsp;(&lt;a href=&quot;https://github.com/danielstreit&quot;&gt;@danielstreit&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3455&quot;&gt;3455&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;SUDO Opcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;William Morriss&amp;nbsp;(&lt;a href=&quot;https://github.com/wjmelements&quot;&gt;@wjmelements&lt;/a&gt;), Baptiste Vauthey&amp;nbsp;(&lt;a href=&quot;https://github.com/thabaptiser&quot;&gt;@thabaptiser&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3508&quot;&gt;3508&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Transaction Data Opcodes&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Papageorgiou&amp;nbsp;(&lt;a href=&quot;https://github.com/alex-ppg&quot;&gt;@alex-ppg&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3520&quot;&gt;3520&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Transaction Destination Opcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Papageorgiou&amp;nbsp;(&lt;a href=&quot;https://github.com/alex-ppg&quot;&gt;@alex-ppg&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3521&quot;&gt;3521&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Reduce access list cost&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Matt Garnett&amp;nbsp;(&lt;a href=&quot;https://github.com/lightclient&quot;&gt;@lightclient&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3534&quot;&gt;3534&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Restricted Chain Context Type Transactions&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Isaac Ardis&amp;nbsp;(&lt;a href=&quot;https://github.com/whilei&quot;&gt;@whilei&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3540&quot;&gt;3540&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EOF - EVM Object Format v1&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;), Andrei Maiboroda&amp;nbsp;(&lt;a href=&quot;https://github.com/gumb0&quot;&gt;@gumb0&lt;/a&gt;), Matt Garnett&amp;nbsp;(&lt;a href=&quot;https://github.com/lightclient&quot;&gt;@lightclient&lt;/a&gt;), Piotr Dobaczewski&amp;nbsp;(&lt;a href=&quot;https://github.com/pdobacz&quot;&gt;@pdobacz&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3561&quot;&gt;3561&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Trust Minimized Upgradeability Proxy&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Sam Porter&amp;nbsp;(&lt;a href=&quot;https://github.com/SamPorter1984&quot;&gt;@SamPorter1984&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3569&quot;&gt;3569&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Sealed NFT Metadata Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Sean Papanikolas&amp;nbsp;(&lt;a href=&quot;https://github.com/pizzarob&quot;&gt;@pizzarob&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3584&quot;&gt;3584&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Block Access List&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gajinder Singh&amp;nbsp;(&lt;a href=&quot;https://github.com/g11in&quot;&gt;@g11in&lt;/a&gt;), Piper Merriam&amp;nbsp;(&lt;a href=&quot;https://github.com/pipermerriam&quot;&gt;@pipermerriam&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3589&quot;&gt;3589&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Assemble assets into NFTs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Zhenyu Sun&amp;nbsp;(&lt;a href=&quot;https://github.com/Ungigdu&quot;&gt;@Ungigdu&lt;/a&gt;), Xinqi Yang&amp;nbsp;(&lt;a href=&quot;https://github.com/xinqiyang&quot;&gt;@xinqiyang&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3670&quot;&gt;3670&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EOF - Code Validation&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Andrei Maiboroda&amp;nbsp;(&lt;a href=&quot;https://github.com/gumb0&quot;&gt;@gumb0&lt;/a&gt;), Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3690&quot;&gt;3690&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EOF - JUMPDEST Table&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;), Andrei Maiboroda&amp;nbsp;(&lt;a href=&quot;https://github.com/gumb0&quot;&gt;@gumb0&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3709&quot;&gt;3709&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Remove Support for Type 1 Transactions&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gregory Markou&amp;nbsp;(&lt;a href=&quot;https://github.com/GregTheGreek&quot;&gt;@GregTheGreek&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3722&quot;&gt;3722&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Poster&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Auryn Macmillan&amp;nbsp;(&lt;a href=&quot;https://github.com/auryn-macmillan&quot;&gt;@auryn-macmillan&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3754&quot;&gt;3754&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;A Vanilla Non-Fungible Token Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Simon Tian&amp;nbsp;(&lt;a href=&quot;https://github.com/simontianx&quot;&gt;@simontianx&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3756&quot;&gt;3756&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Gas Limit Cap&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;lightclient&amp;nbsp;(&lt;a href=&quot;https://github.com/lightclient&quot;&gt;@lightclient&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3772&quot;&gt;3772&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Compressed Integers&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Soham Zemse&amp;nbsp;(&lt;a href=&quot;https://github.com/zemse&quot;&gt;@zemse&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3788&quot;&gt;3788&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Strict enforcement of chainId&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gregory Markou&amp;nbsp;(&lt;a href=&quot;https://github.com/GregTheGreek&quot;&gt;@GregTheGreek&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3978&quot;&gt;3978&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Gas refunds on reverts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Anton Bukov&amp;nbsp;(&lt;a href=&quot;https://github.com/k06a&quot;&gt;@k06a&lt;/a&gt;), Mikhail Melnik&amp;nbsp;(&lt;a href=&quot;https://github.com/ZumZoom&quot;&gt;@ZumZoom&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4200&quot;&gt;4200&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EOF - Static relative jumps&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Andrei Maiboroda&amp;nbsp;(&lt;a href=&quot;https://github.com/gumb0&quot;&gt;@gumb0&lt;/a&gt;), Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4341&quot;&gt;4341&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Ordered NFT Batch Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Simon Tian&amp;nbsp;(&lt;a href=&quot;https://github.com/simontianx&quot;&gt;@simontianx&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4353&quot;&gt;4353&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Interface for Staked Tokens in NFTs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Rex Creed&amp;nbsp;(&lt;a href=&quot;https://github.com/aug2uag&quot;&gt;@aug2uag&lt;/a&gt;), Dane Scarborough&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:dane@nftapps.us&quot;&gt;dane@nftapps.us&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4393&quot;&gt;4393&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Micropayments for NFTs and Multi Tokens&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jules Lai&amp;nbsp;(&lt;a href=&quot;https://github.com/julesl23&quot;&gt;@julesl23&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4396&quot;&gt;4396&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Time-Aware Base Fee Calculation&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ansgar Dietrichs&amp;nbsp;(&lt;a href=&quot;https://github.com/adietrichs&quot;&gt;@adietrichs&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4430&quot;&gt;4430&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Described Transactions&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Richard Moore&amp;nbsp;(&lt;a href=&quot;https://github.com/ricmoo&quot;&gt;@ricmoo&lt;/a&gt;), Nick Johnson&amp;nbsp;(&lt;a href=&quot;https://github.com/arachnid&quot;&gt;@arachnid&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4444&quot;&gt;4444&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Bound Historical Data in Execution Clients&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;George Kadianakis&amp;nbsp;(&lt;a href=&quot;https://github.com/asn-d6&quot;&gt;@asn-d6&lt;/a&gt;), lightclient&amp;nbsp;(&lt;a href=&quot;https://github.com/lightclient&quot;&gt;@lightclient&lt;/a&gt;), Alex Stokes&amp;nbsp;(&lt;a href=&quot;https://github.com/ralexstokes&quot;&gt;@ralexstokes&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4488&quot;&gt;4488&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Transaction calldata gas cost reduction with total calldata limit&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Ansgar Dietrichs&amp;nbsp;(&lt;a href=&quot;https://github.com/adietrichs&quot;&gt;@adietrichs&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4494&quot;&gt;4494&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Permit for ERC-721 NFTs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Simon Fremaux&amp;nbsp;(&lt;a href=&quot;https://github.com/dievardump&quot;&gt;@dievardump&lt;/a&gt;), William Schwab&amp;nbsp;(&lt;a href=&quot;https://github.com/wschwab&quot;&gt;@wschwab&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4520&quot;&gt;4520&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Multi-byte opcodes prefixed by EB and EC.&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Brayton Goodall&amp;nbsp;(&lt;a href=&quot;https://github.com/Spore-Druid-Bray&quot;&gt;@Spore-Druid-Bray&lt;/a&gt;), Mihir Faujdar&amp;nbsp;(&lt;a href=&quot;https://github.com/uink45&quot;&gt;@uink45&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4521&quot;&gt;4521&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;721/20-compatible transfer&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ross Campbell&amp;nbsp;(&lt;a href=&quot;https://github.com/z0r0z&quot;&gt;@z0r0z&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4524&quot;&gt;4524&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Safer ERC-20&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;William Schwab&amp;nbsp;(&lt;a href=&quot;https://github.com/wschwab&quot;&gt;@wschwab&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4527&quot;&gt;4527&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;QR Code transmission protocol for wallets&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Aaron Chen&amp;nbsp;(&lt;a href=&quot;https://github.com/aaronisme&quot;&gt;@aaronisme&lt;/a&gt;), Sora Lee&amp;nbsp;(&lt;a href=&quot;https://github.com/soralit&quot;&gt;@soralit&lt;/a&gt;), ligi&amp;nbsp;(&lt;a href=&quot;https://github.com/ligi&quot;&gt;@ligi&lt;/a&gt;), Dan Miller&amp;nbsp;(&lt;a href=&quot;https://github.com/danjm&quot;&gt;@danjm&lt;/a&gt;), AndreasGassmann&amp;nbsp;(&lt;a href=&quot;https://github.com/andreasgassmann&quot;&gt;@andreasgassmann&lt;/a&gt;), xardass&amp;nbsp;(&lt;a href=&quot;https://github.com/xardass&quot;&gt;@xardass&lt;/a&gt;), Lixin Liu&amp;nbsp;(&lt;a href=&quot;https://github.com/BitcoinLixin&quot;&gt;@BitcoinLixin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4546&quot;&gt;4546&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Wrapped Deposits&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Justice Hudson&amp;nbsp;(&lt;a href=&quot;https://github.com/jchancehud&quot;&gt;@jchancehud&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4573&quot;&gt;4573&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Procedures for the EVM&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Greg Colvin&amp;nbsp;(&lt;a href=&quot;https://github.com/gcolvin&quot;&gt;@gcolvin&lt;/a&gt;), Greg Colvin&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:greg@colvin.org&quot;&gt;greg@colvin.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4671&quot;&gt;4671&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Non-Tradable Tokens Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Omar Aflak&amp;nbsp;(&lt;a href=&quot;https://github.com/omaraflak&quot;&gt;@omaraflak&lt;/a&gt;),  Pol-Malo Le Bris, Marvin Martin&amp;nbsp;(&lt;a href=&quot;https://github.com/MarvinMartin24&quot;&gt;@MarvinMartin24&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4675&quot;&gt;4675&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Multi-Fractional Non-Fungible Tokens&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;David Kim&amp;nbsp;(&lt;a href=&quot;https://github.com/powerstream3604&quot;&gt;@powerstream3604&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4747&quot;&gt;4747&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Simplify EIP-161&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Peter Davies&amp;nbsp;(&lt;a href=&quot;https://github.com/petertdavies&quot;&gt;@petertdavies&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4750&quot;&gt;4750&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EOF - Functions&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Andrei Maiboroda&amp;nbsp;(&lt;a href=&quot;https://github.com/gumb0&quot;&gt;@gumb0&lt;/a&gt;), Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4758&quot;&gt;4758&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Deactivate SELFDESTRUCT&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Guillaume Ballet&amp;nbsp;(&lt;a href=&quot;https://github.com/gballet&quot;&gt;@gballet&lt;/a&gt;), Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Dankrad Feist&amp;nbsp;(&lt;a href=&quot;https://github.com/dankrad&quot;&gt;@dankrad&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4760&quot;&gt;4760&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;SELFDESTRUCT bomb&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Guillaume Ballet&amp;nbsp;(&lt;a href=&quot;https://github.com/gballet&quot;&gt;@gballet&lt;/a&gt;), Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Dankrad Feist&amp;nbsp;(&lt;a href=&quot;https://github.com/dankrad&quot;&gt;@dankrad&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4799&quot;&gt;4799&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Non-Fungible Token Ownership Designation Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;David Buckman&amp;nbsp;(&lt;a href=&quot;https://github.com/davidbuckman&quot;&gt;@davidbuckman&lt;/a&gt;), Isaac Buckman&amp;nbsp;(&lt;a href=&quot;https://github.com/isaacbuckman&quot;&gt;@isaacbuckman&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4803&quot;&gt;4803&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Limit transaction gas to a maximum of 2^63-1&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4863&quot;&gt;4863&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Beacon chain push withdrawals&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Stokes&amp;nbsp;(&lt;a href=&quot;https://github.com/ralexstokes&quot;&gt;@ralexstokes&lt;/a&gt;), Danny Ryan&amp;nbsp;(&lt;a href=&quot;https://github.com/djrtwo&quot;&gt;@djrtwo&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4885&quot;&gt;4885&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Subscription NFTs and Multi Tokens&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jules Lai&amp;nbsp;(&lt;a href=&quot;https://github.com/julesl23&quot;&gt;@julesl23&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4886&quot;&gt;4886&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Proxy Ownership Register&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Omnus Sunmo&amp;nbsp;(&lt;a href=&quot;https://github.com/omnus&quot;&gt;@omnus&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4931&quot;&gt;4931&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Generic Token Upgrade Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;John Peterson&amp;nbsp;(&lt;a href=&quot;https://github.com/John-peterson-coinbase&quot;&gt;@John-peterson-coinbase&lt;/a&gt;), Roberto Bayardo&amp;nbsp;(&lt;a href=&quot;https://github.com/roberto-bayardo&quot;&gt;@roberto-bayardo&lt;/a&gt;), David Núñez&amp;nbsp;(&lt;a href=&quot;https://github.com/cygnusv&quot;&gt;@cygnusv&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4944&quot;&gt;4944&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Contract with Exactly One Non-fungible Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Víctor Muñoz&amp;nbsp;(&lt;a href=&quot;https://github.com/victormunoz&quot;&gt;@victormunoz&lt;/a&gt;), Josep Lluis de la Rosa&amp;nbsp;(&lt;a href=&quot;https://github.com/peplluis7&quot;&gt;@peplluis7&lt;/a&gt;), Andres El-Fakdi&amp;nbsp;(&lt;a href=&quot;https://github.com/Bluezfish&quot;&gt;@Bluezfish&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4950&quot;&gt;4950&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Entangled Tokens&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Víctor Muñoz&amp;nbsp;(&lt;a href=&quot;https://github.com/victormunoz&quot;&gt;@victormunoz&lt;/a&gt;), Josep Lluis de la Rosa&amp;nbsp;(&lt;a href=&quot;https://github.com/peplluis7&quot;&gt;@peplluis7&lt;/a&gt;), Easy Innova&amp;nbsp;(&lt;a href=&quot;https://github.com/easyinnova&quot;&gt;@easyinnova&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4974&quot;&gt;4974&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Ratings&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Daniel Tedesco&amp;nbsp;(&lt;a href=&quot;https://github.com/dtedesco1&quot;&gt;@dtedesco1&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-4987&quot;&gt;4987&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Held token interface&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Devin Conley&amp;nbsp;(&lt;a href=&quot;https://github.com/devinaconley&quot;&gt;@devinaconley&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5000&quot;&gt;5000&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;MULDIV instruction&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Harikrishnan Mulackal&amp;nbsp;(&lt;a href=&quot;https://github.com/hrkrshnn&quot;&gt;@hrkrshnn&lt;/a&gt;), Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5005&quot;&gt;5005&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Zodiac Modular Accounts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Auryn Macmillan&amp;nbsp;(&lt;a href=&quot;https://github.com/auryn-macmillan&quot;&gt;@auryn-macmillan&lt;/a&gt;), Kei Kreutler&amp;nbsp;(&lt;a href=&quot;https://github.com/keikreutler&quot;&gt;@keikreutler&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5018&quot;&gt;5018&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Filesystem-like Interface for Contracts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Qi Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/qizhou&quot;&gt;@qizhou&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5022&quot;&gt;5022&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Increase price of SSTORE from zero to non-zero to 40k gas&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Green&amp;nbsp;(&lt;a href=&quot;https://github.com/greenlucid&quot;&gt;@greenlucid&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5027&quot;&gt;5027&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Remove the limit on contract code size&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Qi Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/qizhou&quot;&gt;@qizhou&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5050&quot;&gt;5050&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Interactive NFTs with Modular Environments&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alexi&amp;nbsp;(&lt;a href=&quot;https://github.com/alexi&quot;&gt;@alexi&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5058&quot;&gt;5058&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Lockable Non-Fungible Tokens&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Tyler&amp;nbsp;(&lt;a href=&quot;https://github.com/radiocaca&quot;&gt;@radiocaca&lt;/a&gt;), Alex&amp;nbsp;(&lt;a href=&quot;https://github.com/gojazdev&quot;&gt;@gojazdev&lt;/a&gt;), John&amp;nbsp;(&lt;a href=&quot;https://github.com/sfumato00&quot;&gt;@sfumato00&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5065&quot;&gt;5065&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Instruction for transferring ether&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Mudit Gupta&amp;nbsp;(&lt;a href=&quot;https://github.com/maxsam4&quot;&gt;@maxsam4&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5081&quot;&gt;5081&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Expirable Transaction&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Zainan Victor Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/xinbenlv&quot;&gt;@xinbenlv&lt;/a&gt;), Nick Johnson&amp;nbsp;(&lt;a href=&quot;https://github.com/Arachnid&quot;&gt;@Arachnid&lt;/a&gt;), Konrad Feldmeier&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:konrad@brainbot.com&quot;&gt;konrad@brainbot.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5094&quot;&gt;5094&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;URL Format for Ethereum Network Switching&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Luc van Kampen&amp;nbsp;(&lt;a href=&quot;https://github.com/lucemans&quot;&gt;@lucemans&lt;/a&gt;), Jakob Helgesson&amp;nbsp;(&lt;a href=&quot;https://github.com/svemat01&quot;&gt;@svemat01&lt;/a&gt;), Joshua Hendrix&amp;nbsp;(&lt;a href=&quot;https://github.com/thejoshuahendrix&quot;&gt;@thejoshuahendrix&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5095&quot;&gt;5095&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Principal Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Julian Traversa&amp;nbsp;(&lt;a href=&quot;https://github.com/JTraversa&quot;&gt;@JTraversa&lt;/a&gt;), Robert Robbins&amp;nbsp;(&lt;a href=&quot;https://github.com/robrobbins&quot;&gt;@robrobbins&lt;/a&gt;), Alberto Cuesta Cañada&amp;nbsp;(&lt;a href=&quot;https://github.com/alcueca&quot;&gt;@alcueca&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5131&quot;&gt;5131&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;SAFE Authentication For ENS&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Wilkins Chung (@wwhchung)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:wilkins@manifold.xyz&quot;&gt;wilkins@manifold.xyz&lt;/a&gt;&amp;gt;, Jalil Wahdatehagh&amp;nbsp;(&lt;a href=&quot;https://github.com/jwahdatehagh&quot;&gt;@jwahdatehagh&lt;/a&gt;), Cry&amp;nbsp;(&lt;a href=&quot;https://github.com/crydoteth&quot;&gt;@crydoteth&lt;/a&gt;), Sillytuna&amp;nbsp;(&lt;a href=&quot;https://github.com/sillytuna&quot;&gt;@sillytuna&lt;/a&gt;), Cyberpnk&amp;nbsp;(&lt;a href=&quot;https://github.com/CyberpnkWin&quot;&gt;@CyberpnkWin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5139&quot;&gt;5139&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Remote Procedure Call Provider Lists&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Sam Wilson&amp;nbsp;(&lt;a href=&quot;https://github.com/SamWilsn&quot;&gt;@SamWilsn&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5143&quot;&gt;5143&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Slippage Protection for Tokenized Vault&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Hadrien Croubois&amp;nbsp;(&lt;a href=&quot;https://github.com/amxx&quot;&gt;@amxx&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5185&quot;&gt;5185&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;NFT Updatable Metadata Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Christophe Le Bars&amp;nbsp;(&lt;a href=&quot;https://github.com/clbrge&quot;&gt;@clbrge&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5187&quot;&gt;5187&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Extend EIP-1155 with rentable usage rights&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;DerivStudio&amp;nbsp;(&lt;a href=&quot;https://github.com/DerivStudio&quot;&gt;@DerivStudio&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5218&quot;&gt;5218&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;NFT Rights Management&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;James Grimmelmann&amp;nbsp;(&lt;a href=&quot;https://github.com/grimmelm&quot;&gt;@grimmelm&lt;/a&gt;), Yan Ji&amp;nbsp;(&lt;a href=&quot;https://github.com/iseriohn&quot;&gt;@iseriohn&lt;/a&gt;), Tyler Kell&amp;nbsp;(&lt;a href=&quot;https://github.com/relyt29&quot;&gt;@relyt29&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5252&quot;&gt;5252&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Account-bound Finance&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Hyungsuk Kang&amp;nbsp;(&lt;a href=&quot;https://github.com/hskang9&quot;&gt;@hskang9&lt;/a&gt;), Viktor Pernjek&amp;nbsp;(&lt;a href=&quot;https://github.com/smuxx&quot;&gt;@smuxx&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5283&quot;&gt;5283&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Semaphore for Reentrancy Protection&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Sergio D. Lerner&amp;nbsp;(&lt;a href=&quot;https://github.com/SergioDemianLerner&quot;&gt;@SergioDemianLerner&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5298&quot;&gt;5298&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ENS Trust to hold NFTs under ENS name&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Zainan Victor Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/xinbenlv&quot;&gt;@xinbenlv&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5334&quot;&gt;5334&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EIP-721 User And Expires And Level Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Yan&amp;nbsp;(&lt;a href=&quot;https://github.com/yan253319066&quot;&gt;@yan253319066&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5345&quot;&gt;5345&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Silent Signing Extension for JSON-RPC&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Stanley Wu&amp;nbsp;(&lt;a href=&quot;https://github.com/fruit37&quot;&gt;@fruit37&lt;/a&gt;), Mücahit Büyükyılmaz&amp;nbsp;(&lt;a href=&quot;https://github.com/anndro&quot;&gt;@anndro&lt;/a&gt;), Muhammed Emin Aydın&amp;nbsp;(&lt;a href=&quot;https://github.com/muhammedea&quot;&gt;@muhammedea&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5409&quot;&gt;5409&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EIP-1155 Non-Fungible Token extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ronan Sandford&amp;nbsp;(&lt;a href=&quot;https://github.com/wighawag&quot;&gt;@wighawag&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5437&quot;&gt;5437&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Security Contact Interface&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Zainan Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/xinbenlv&quot;&gt;@xinbenlv&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5450&quot;&gt;5450&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EOF - Stack Validation&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Andrei Maiboroda&amp;nbsp;(&lt;a href=&quot;https://github.com/gumb0&quot;&gt;@gumb0&lt;/a&gt;), Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;), Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Danno Ferrin&amp;nbsp;(&lt;a href=&quot;https://github.com/shemnon&quot;&gt;@shemnon&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5478&quot;&gt;5478&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;CREATE2COPY Opcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Qi Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/qizhou&quot;&gt;@qizhou&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5501&quot;&gt;5501&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Rental &amp;amp; Delegation NFT - EIP-721 Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jan Smrža&amp;nbsp;(&lt;a href=&quot;https://github.com/smrza&quot;&gt;@smrza&lt;/a&gt;), David Rábel&amp;nbsp;(&lt;a href=&quot;https://github.com/rabeles11&quot;&gt;@rabeles11&lt;/a&gt;), Tomáš Janča&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:tomas.janca@jtbstorage.eu&quot;&gt;tomas.janca@jtbstorage.eu&lt;/a&gt;&amp;gt;, Jan Bureš&amp;nbsp;(&lt;a href=&quot;https://github.com/JohnyX89&quot;&gt;@JohnyX89&lt;/a&gt;), DOBBYLABS&amp;nbsp;(&lt;a href=&quot;https://github.com/DOBBYLABS&quot;&gt;@DOBBYLABS&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5505&quot;&gt;5505&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EIP-1155 asset backed NFT extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;liszechung&amp;nbsp;(&lt;a href=&quot;https://github.com/liszechung&quot;&gt;@liszechung&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5539&quot;&gt;5539&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Revocation List Registry&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Philipp Bolte&amp;nbsp;(&lt;a href=&quot;https://github.com/strumswell&quot;&gt;@strumswell&lt;/a&gt;), Lauritz Leifermann&amp;nbsp;(&lt;a href=&quot;https://github.com/lleifermann&quot;&gt;@lleifermann&lt;/a&gt;), Dennis von der Bey&amp;nbsp;(&lt;a href=&quot;https://github.com/DennisVonDerBey&quot;&gt;@DennisVonDerBey&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5553&quot;&gt;5553&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Representing IP and its Royalty Structure&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Roy Osherove&amp;nbsp;(&lt;a href=&quot;https://github.com/royosherove&quot;&gt;@royosherove&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5554&quot;&gt;5554&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;NFT Legal Use, Repurposing, and Remixing&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Isaac Patka&amp;nbsp;(&lt;a href=&quot;https://github.com/ipatka&quot;&gt;@ipatka&lt;/a&gt;), COALA Licensing Taskforce&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:info@coala.org&quot;&gt;info@coala.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5559&quot;&gt;5559&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Cross Chain Write Deferral Protocol&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Paul Gauvreau&amp;nbsp;(&lt;a href=&quot;https://github.com/0xpaulio&quot;&gt;@0xpaulio&lt;/a&gt;), Nick Johnson&amp;nbsp;(&lt;a href=&quot;https://github.com/arachnid&quot;&gt;@arachnid&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5560&quot;&gt;5560&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Redeemable NFTs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Olivier Fernandez&amp;nbsp;(&lt;a href=&quot;https://github.com/fernandezOli&quot;&gt;@fernandezOli&lt;/a&gt;), Frédéric Le Coidic&amp;nbsp;(&lt;a href=&quot;https://github.com/FredLC29&quot;&gt;@FredLC29&lt;/a&gt;), Julien Béranger&amp;nbsp;(&lt;a href=&quot;https://github.com/julienbrg&quot;&gt;@julienbrg&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5593&quot;&gt;5593&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Restrict Ethereum Provider API Injection&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Yan Zhu&amp;nbsp;(&lt;a href=&quot;https://github.com/diracdeltas&quot;&gt;@diracdeltas&lt;/a&gt;), Brian R. Bondy&amp;nbsp;(&lt;a href=&quot;https://github.com/bbondy&quot;&gt;@bbondy&lt;/a&gt;), Andrea  Brancaleoni&amp;nbsp;(&lt;a href=&quot;https://github.com/thypon&quot;&gt;@thypon&lt;/a&gt;), Kyle Den Hartog&amp;nbsp;(&lt;a href=&quot;https://github.com/kdenhartog&quot;&gt;@kdenhartog&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5633&quot;&gt;5633&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Composable Soulbound NFT, EIP-1155 Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;HonorLabs&amp;nbsp;(&lt;a href=&quot;https://github.com/honorworldio&quot;&gt;@honorworldio&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5635&quot;&gt;5635&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;NFT Licensing Agreements&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Timi&amp;nbsp;(&lt;a href=&quot;https://github.com/0xTimi&quot;&gt;@0xTimi&lt;/a&gt;), 0xTriple7&amp;nbsp;(&lt;a href=&quot;https://github.com/ysqi&quot;&gt;@ysqi&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5643&quot;&gt;5643&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Subscription NFTs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;cygaar&amp;nbsp;(&lt;a href=&quot;https://github.com/cygaar&quot;&gt;@cygaar&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5719&quot;&gt;5719&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Signature replacement interface&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Agustin Aguilar&amp;nbsp;(&lt;a href=&quot;https://github.com/Agusx1211&quot;&gt;@Agusx1211&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5744&quot;&gt;5744&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Latent Fungible Token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Cozy Finance&amp;nbsp;(&lt;a href=&quot;https://github.com/cozyfinance&quot;&gt;@cozyfinance&lt;/a&gt;), Tony Sheng&amp;nbsp;(&lt;a href=&quot;https://github.com/tonysheng&quot;&gt;@tonysheng&lt;/a&gt;), Matt Solomon&amp;nbsp;(&lt;a href=&quot;https://github.com/mds1&quot;&gt;@mds1&lt;/a&gt;), David Laprade&amp;nbsp;(&lt;a href=&quot;https://github.com/davidlaprade&quot;&gt;@davidlaprade&lt;/a&gt;), Payom Dousti&amp;nbsp;(&lt;a href=&quot;https://github.com/payomdousti&quot;&gt;@payomdousti&lt;/a&gt;), Chad Fleming&amp;nbsp;(&lt;a href=&quot;https://github.com/chad-js&quot;&gt;@chad-js&lt;/a&gt;), Franz Chen&amp;nbsp;(&lt;a href=&quot;https://github.com/Dendrimer&quot;&gt;@Dendrimer&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5753&quot;&gt;5753&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Lockable Extension for EIP-721&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Filipp Makarov&amp;nbsp;(&lt;a href=&quot;https://github.com/filmakarov&quot;&gt;@filmakarov&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5805&quot;&gt;5805&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Voting with delegation&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Hadrien Croubois&amp;nbsp;(&lt;a href=&quot;https://github.com/Amxx&quot;&gt;@Amxx&lt;/a&gt;), Francisco Giordano&amp;nbsp;(&lt;a href=&quot;https://github.com/frangio&quot;&gt;@frangio&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5806&quot;&gt;5806&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Delegate transaction&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Hadrien Croubois&amp;nbsp;(&lt;a href=&quot;https://github.com/Amxx&quot;&gt;@Amxx&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5827&quot;&gt;5827&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Auto-renewable allowance extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;zlace&amp;nbsp;(&lt;a href=&quot;https://github.com/zlace0x&quot;&gt;@zlace0x&lt;/a&gt;), zhongfu&amp;nbsp;(&lt;a href=&quot;https://github.com/zhongfu&quot;&gt;@zhongfu&lt;/a&gt;), edison0xyz&amp;nbsp;(&lt;a href=&quot;https://github.com/edison0xyz&quot;&gt;@edison0xyz&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5850&quot;&gt;5850&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Complex Numbers stored in `bytes32` types&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Paul Edge&amp;nbsp;(&lt;a href=&quot;https://github.com/genkifs&quot;&gt;@genkifs&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5851&quot;&gt;5851&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;On-Chain Verifiable Credentials&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Yu Liu&amp;nbsp;(&lt;a href=&quot;https://github.com/yuliu-debond&quot;&gt;@yuliu-debond&lt;/a&gt;), Junyi Zhong&amp;nbsp;(&lt;a href=&quot;https://github.com/Jooeys&quot;&gt;@Jooeys&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5883&quot;&gt;5883&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Token Transfer by Social Recovery&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Erhard Dinhobl&amp;nbsp;(&lt;a href=&quot;https://github.com/mrqc&quot;&gt;@mrqc&lt;/a&gt;), Kevin Riedl&amp;nbsp;(&lt;a href=&quot;https://github.com/wsdt&quot;&gt;@wsdt&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5902&quot;&gt;5902&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Smart Contract Event Hooks&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Simon Brown&amp;nbsp;(&lt;a href=&quot;https://github.com/orbmis&quot;&gt;@orbmis&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5920&quot;&gt;5920&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;PAY opcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gavin John&amp;nbsp;(&lt;a href=&quot;https://github.com/Pandapip1&quot;&gt;@Pandapip1&lt;/a&gt;), Zainan Victor Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/xinbenlv&quot;&gt;@xinbenlv&lt;/a&gt;), Sam Wilson&amp;nbsp;(&lt;a href=&quot;https://github.com/SamWilsn&quot;&gt;@SamWilsn&lt;/a&gt;), Jochem Brouwer&amp;nbsp;(&lt;a href=&quot;https://github.com/jochem-brouwer&quot;&gt;@jochem-brouwer&lt;/a&gt;), Charles Cooper&amp;nbsp;(&lt;a href=&quot;https://github.com/charles-cooper&quot;&gt;@charles-cooper&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5988&quot;&gt;5988&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Add Poseidon hash function precompile&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Abdelhamid Bakhta&amp;nbsp;(&lt;a href=&quot;https://github.com/abdelhamidbakhta&quot;&gt;@abdelhamidbakhta&lt;/a&gt;), Eli Ben Sasson&amp;nbsp;(&lt;a href=&quot;https://github.com/Elistark&quot;&gt;@Elistark&lt;/a&gt;), Avihu Levy&amp;nbsp;(&lt;a href=&quot;https://github.com/avihu28&quot;&gt;@avihu28&lt;/a&gt;), David Levit Gurevich&amp;nbsp;(&lt;a href=&quot;https://github.com/DavidLevitGurevich&quot;&gt;@DavidLevitGurevich&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6046&quot;&gt;6046&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Replace SELFDESTRUCT with DEACTIVATE&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6047&quot;&gt;6047&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ERC-721 Balance indexing via Transfer event&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Zainan Victor Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/xinbenlv&quot;&gt;@xinbenlv&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6051&quot;&gt;6051&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Private Key Encapsulation&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Base Labs&amp;nbsp;(&lt;a href=&quot;https://github.com/Base-Labs&quot;&gt;@Base-Labs&lt;/a&gt;), Weiji Guo&amp;nbsp;(&lt;a href=&quot;https://github.com/weiji-cryptonatty&quot;&gt;@weiji-cryptonatty&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6188&quot;&gt;6188&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Nonce Cap&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gavin John&amp;nbsp;(&lt;a href=&quot;https://github.com/Pandapip1&quot;&gt;@Pandapip1&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6189&quot;&gt;6189&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Alias Contracts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gavin John&amp;nbsp;(&lt;a href=&quot;https://github.com/Pandapip1&quot;&gt;@Pandapip1&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6190&quot;&gt;6190&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Verkle-compatible SELFDESTRUCT&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gavin John&amp;nbsp;(&lt;a href=&quot;https://github.com/Pandapip1&quot;&gt;@Pandapip1&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6206&quot;&gt;6206&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EOF - JUMPF and non-returning functions&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Andrei Maiboroda&amp;nbsp;(&lt;a href=&quot;https://github.com/gumb0&quot;&gt;@gumb0&lt;/a&gt;), Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;), Matt Garnett&amp;nbsp;(&lt;a href=&quot;https://github.com/lightclient&quot;&gt;@lightclient&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6268&quot;&gt;6268&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Untransferability Indicator for EIP-1155&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Yuki Aoki&amp;nbsp;(&lt;a href=&quot;https://github.com/yuki-js&quot;&gt;@yuki-js&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6353&quot;&gt;6353&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Charity token&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Aubay&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:blockchain-team@aubay.com&quot;&gt;blockchain-team@aubay.com&lt;/a&gt;&amp;gt;, BOCA Jeabby&amp;nbsp;(&lt;a href=&quot;https://github.com/bjeabby1507&quot;&gt;@bjeabby1507&lt;/a&gt;), EL MERSHATI Laith&amp;nbsp;(&lt;a href=&quot;https://github.com/lth-elm&quot;&gt;@lth-elm&lt;/a&gt;), KEMP Elia&amp;nbsp;(&lt;a href=&quot;https://github.com/eliakemp&quot;&gt;@eliakemp&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6384&quot;&gt;6384&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Human-readable offline signatures&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Tal Be&apos;ery&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:tal@zengo.com&quot;&gt;tal@zengo.com&lt;/a&gt;&amp;gt;, RoiV&amp;nbsp;(&lt;a href=&quot;https://github.com/DeVaz1&quot;&gt;@DeVaz1&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6464&quot;&gt;6464&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Multi-operator, per-token ERC-721 approvals.&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Cristian Espinoza&amp;nbsp;(&lt;a href=&quot;https://github.com/crisgarner&quot;&gt;@crisgarner&lt;/a&gt;), Simon Fremaux&amp;nbsp;(&lt;a href=&quot;https://github.com/dievardump&quot;&gt;@dievardump&lt;/a&gt;), David Huber&amp;nbsp;(&lt;a href=&quot;https://github.com/cxkoda&quot;&gt;@cxkoda&lt;/a&gt;), and Arran Schlosberg&amp;nbsp;(&lt;a href=&quot;https://github.com/aschlosberg&quot;&gt;@aschlosberg&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6475&quot;&gt;6475&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;SSZ Optional&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Etan Kissling&amp;nbsp;(&lt;a href=&quot;https://github.com/etan-status&quot;&gt;@etan-status&lt;/a&gt;), Zahary Karadjov&amp;nbsp;(&lt;a href=&quot;https://github.com/zah&quot;&gt;@zah&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6506&quot;&gt;6506&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;P2P Escrowed Governance Incentives&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Josh Weintraub&amp;nbsp;(&lt;a href=&quot;https://github.com/jhweintraub&quot;&gt;@jhweintraub&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6690&quot;&gt;6690&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EVM Modular Arithmetic Extensions&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jared Wasinger&amp;nbsp;(&lt;a href=&quot;https://github.com/jwasinger&quot;&gt;@jwasinger&lt;/a&gt;), Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Radosław Zagórowicz&amp;nbsp;(&lt;a href=&quot;https://github.com/rodiazet&quot;&gt;@rodiazet&lt;/a&gt;), Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6789&quot;&gt;6789&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Rename gas to mana&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;pcaversaccio&amp;nbsp;(&lt;a href=&quot;https://github.com/pcaversaccio&quot;&gt;@pcaversaccio&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6800&quot;&gt;6800&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Ethereum state using a unified verkle tree&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Dankrad Feist&amp;nbsp;(&lt;a href=&quot;https://github.com/dankrad&quot;&gt;@dankrad&lt;/a&gt;), Kevaundray Wedderburn&amp;nbsp;(&lt;a href=&quot;https://github.com/kevaundray&quot;&gt;@kevaundray&lt;/a&gt;), Guillaume Ballet&amp;nbsp;(&lt;a href=&quot;https://github.com/gballet&quot;&gt;@gballet&lt;/a&gt;), Piper Merriam&amp;nbsp;(&lt;a href=&quot;https://github.com/pipermerriam&quot;&gt;@pipermerriam&lt;/a&gt;), Gottfried Herold&amp;nbsp;(&lt;a href=&quot;https://github.com/GottfriedHerold&quot;&gt;@GottfriedHerold&lt;/a&gt;), Ignacio Hagopian&amp;nbsp;(&lt;a href=&quot;https://github.com/jsign&quot;&gt;@jsign&lt;/a&gt;), Tanishq Jasoria&amp;nbsp;(&lt;a href=&quot;https://github.com/tanishqjasoria&quot;&gt;@tanishqjasoria&lt;/a&gt;), Gajinder Singh&amp;nbsp;(&lt;a href=&quot;https://github.com/g11tech&quot;&gt;@g11tech&lt;/a&gt;), Danno Ferrin&amp;nbsp;(&lt;a href=&quot;https://github.com/shemnon&quot;&gt;@shemnon&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6810&quot;&gt;6810&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Ex Post Facto Cascading Revert&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;William Morriss&amp;nbsp;(&lt;a href=&quot;https://github.com/wjmelements&quot;&gt;@wjmelements&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6811&quot;&gt;6811&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;To The Moon—10 Minute Blocks&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Pandapip1&amp;nbsp;(&lt;a href=&quot;https://github.com/Pandapip1&quot;&gt;@Pandapip1&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6873&quot;&gt;6873&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Preimage retention&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Guillaume Ballet&amp;nbsp;(&lt;a href=&quot;https://github.com/gballet&quot;&gt;@gballet&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6888&quot;&gt;6888&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Arithmetic verification at EVM level&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Renan Rodrigues de Souza&amp;nbsp;(&lt;a href=&quot;https://github.com/RenanSouza2&quot;&gt;@RenanSouza2&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6914&quot;&gt;6914&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Reuse Withdrawn Validator Indices&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Lion&amp;nbsp;(&lt;a href=&quot;https://github.com/dapplion&quot;&gt;@dapplion&lt;/a&gt;), Danny Ryan&amp;nbsp;(&lt;a href=&quot;https://github.com/djrtwo&quot;&gt;@djrtwo&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6968&quot;&gt;6968&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Contract Secured Revenue on an EVM based L2&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Zak Cole&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:zak@numbergroup.xyz&quot;&gt;zak@numbergroup.xyz&lt;/a&gt;&amp;gt;, Zak Cole&amp;nbsp;(&lt;a href=&quot;https://github.com/zscole&quot;&gt;@zscole&lt;/a&gt;), Kevin Owocki&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:kevin@supermodular.xyz&quot;&gt;kevin@supermodular.xyz&lt;/a&gt;&amp;gt;, lightclient&amp;nbsp;(&lt;a href=&quot;https://github.com/lightclient&quot;&gt;@lightclient&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6988&quot;&gt;6988&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Elected block proposer has not been slashed&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Mikhail Kalinin&amp;nbsp;(&lt;a href=&quot;https://github.com/mkalinin&quot;&gt;@mkalinin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7039&quot;&gt;7039&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Scheme-Handler Discovery Option for Wallets&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Sam Wilson&amp;nbsp;(&lt;a href=&quot;https://github.com/SamWilsn&quot;&gt;@SamWilsn&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7069&quot;&gt;7069&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Revamped CALL instructions&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;), Danno Ferrin&amp;nbsp;(&lt;a href=&quot;https://github.com/shemnon&quot;&gt;@shemnon&lt;/a&gt;), Andrei Maiboroda&amp;nbsp;(&lt;a href=&quot;https://github.com/gumb0&quot;&gt;@gumb0&lt;/a&gt;), Charles Cooper&amp;nbsp;(&lt;a href=&quot;https://github.com/charles-cooper&quot;&gt;@charles-cooper&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7266&quot;&gt;7266&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Remove BLAKE2 compression precompile&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;pcaversaccio&amp;nbsp;(&lt;a href=&quot;https://github.com/pcaversaccio&quot;&gt;@pcaversaccio&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7377&quot;&gt;7377&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Migration Transaction&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;lightclient&amp;nbsp;(&lt;a href=&quot;https://github.com/lightclient&quot;&gt;@lightclient&lt;/a&gt;), Sam Wilson&amp;nbsp;(&lt;a href=&quot;https://github.com/samwilsn&quot;&gt;@samwilsn&lt;/a&gt;), Ansgar Dietrichs&amp;nbsp;(&lt;a href=&quot;https://github.com/adietrichs&quot;&gt;@adietrichs&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7378&quot;&gt;7378&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Add time-weighted averaging to the base fee&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Guy Goren (@guy-goren)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:guy.nahsholim@gmail.com&quot;&gt;guy.nahsholim@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7441&quot;&gt;7441&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Upgrade block proposer election to Whisk&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;George Kadianakis&amp;nbsp;(&lt;a href=&quot;https://github.com/asn-d6&quot;&gt;@asn-d6&lt;/a&gt;), Justin Drake&amp;nbsp;(&lt;a href=&quot;https://github.com/JustinDrake&quot;&gt;@JustinDrake&lt;/a&gt;), dapplion&amp;nbsp;(&lt;a href=&quot;https://github.com/dapplion&quot;&gt;@dapplion&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7480&quot;&gt;7480&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EOF - Data section access instructions&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Andrei Maiboroda&amp;nbsp;(&lt;a href=&quot;https://github.com/gumb0&quot;&gt;@gumb0&lt;/a&gt;), Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7503&quot;&gt;7503&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Zero-Knowledge Wormholes&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Keyvan Kambakhsh&amp;nbsp;(&lt;a href=&quot;https://github.com/keyvank&quot;&gt;@keyvank&lt;/a&gt;), Hamid Bateni&amp;nbsp;(&lt;a href=&quot;https://github.com/irnb&quot;&gt;@irnb&lt;/a&gt;), Amir Kahoori&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:a.kahoorizadeh@gmail.com&quot;&gt;a.kahoorizadeh@gmail.com&lt;/a&gt;&amp;gt;, Nobitex Labs&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:labs@nobitex.ir&quot;&gt;labs@nobitex.ir&lt;/a&gt;&amp;gt;, 0xwormhole&amp;nbsp;(&lt;a href=&quot;https://github.com/0xwormhole&quot;&gt;@0xwormhole&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7519&quot;&gt;7519&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Atomic Storage Operations SCREDIT and SDEBIT&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Danno Ferrin&amp;nbsp;(&lt;a href=&quot;https://github.com/shemnon&quot;&gt;@shemnon&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7543&quot;&gt;7543&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EVM arbitrary precision decimal math&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;1m1&amp;nbsp;(&lt;a href=&quot;https://github.com/1m1-github&quot;&gt;@1m1-github&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7545&quot;&gt;7545&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Verkle proof verification precompile&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Guillaume Ballet&amp;nbsp;(&lt;a href=&quot;https://github.com/gballet&quot;&gt;@gballet&lt;/a&gt;), Diederik Loerakker&amp;nbsp;(&lt;a href=&quot;https://github.com/protolambda&quot;&gt;@protolambda&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7547&quot;&gt;7547&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Inclusion lists&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;mike&amp;nbsp;(&lt;a href=&quot;https://github.com/michaelneuder&quot;&gt;@michaelneuder&lt;/a&gt;), Vitalik&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Francesco&amp;nbsp;(&lt;a href=&quot;https://github.com/fradamt&quot;&gt;@fradamt&lt;/a&gt;), Terence&amp;nbsp;(&lt;a href=&quot;https://github.com/terencechain&quot;&gt;@terencechain&lt;/a&gt;), potuz&amp;nbsp;(&lt;a href=&quot;https://github.com/potuz&quot;&gt;@potuz&lt;/a&gt;), Manav&amp;nbsp;(&lt;a href=&quot;https://github.com/manav2401&quot;&gt;@manav2401&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7557&quot;&gt;7557&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Block-level Warming with fair cost savings&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Yoav Weiss&amp;nbsp;(&lt;a href=&quot;https://github.com/yoavw&quot;&gt;@yoavw&lt;/a&gt;), Alex Forshtat&amp;nbsp;(&lt;a href=&quot;https://github.com/forshtat&quot;&gt;@forshtat&lt;/a&gt;), Dror Tirosh&amp;nbsp;(&lt;a href=&quot;https://github.com/drortirosh&quot;&gt;@drortirosh&lt;/a&gt;), Shahaf Nacson&amp;nbsp;(&lt;a href=&quot;https://github.com/shahafn&quot;&gt;@shahafn&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7577&quot;&gt;7577&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Versioning Scheme for EIPs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;danceratopz&amp;nbsp;(&lt;a href=&quot;https://github.com/danceratopz&quot;&gt;@danceratopz&lt;/a&gt;), Ahmad Bitar&amp;nbsp;(&lt;a href=&quot;https://github.com/smartprogrammer93&quot;&gt;@smartprogrammer93&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7591&quot;&gt;7591&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;BLS signed transactions&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Marius van der Wijden&amp;nbsp;(&lt;a href=&quot;https://github.com/MariusVanDerWijden&quot;&gt;@MariusVanDerWijden&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7609&quot;&gt;7609&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Decrease base cost of TLOAD/TSTORE&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Charles Cooper&amp;nbsp;(&lt;a href=&quot;https://github.com/charles-cooper&quot;&gt;@charles-cooper&lt;/a&gt;), James Prestwich&amp;nbsp;(&lt;a href=&quot;https://github.com/prestwich&quot;&gt;@prestwich&lt;/a&gt;), brockelmore&amp;nbsp;(&lt;a href=&quot;https://github.com/brockelmore&quot;&gt;@brockelmore&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7612&quot;&gt;7612&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Verkle state transition via an overlay tree&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Guillaume Ballet&amp;nbsp;(&lt;a href=&quot;https://github.com/gballet&quot;&gt;@gballet&lt;/a&gt;), Ansgar Dietrichs&amp;nbsp;(&lt;a href=&quot;https://github.com/adietrichs&quot;&gt;@adietrichs&lt;/a&gt;), Ignacio Hagopian&amp;nbsp;(&lt;a href=&quot;https://github.com/jsign&quot;&gt;@jsign&lt;/a&gt;), Gottfried Herold&amp;nbsp;(&lt;a href=&quot;https://github.com/GottfriedHerold&quot;&gt;@GottfriedHerold&lt;/a&gt;), Jamie Lokier&amp;nbsp;(&lt;a href=&quot;https://github.com/jlokier&quot;&gt;@jlokier&lt;/a&gt;), Tanishq Jasoria&amp;nbsp;(&lt;a href=&quot;https://github.com/tanishqjasoria&quot;&gt;@tanishqjasoria&lt;/a&gt;), Parithosh Jayanthi&amp;nbsp;(&lt;a href=&quot;https://github.com/parithosh&quot;&gt;@parithosh&lt;/a&gt;), Gabriel Rocheleau&amp;nbsp;(&lt;a href=&quot;https://github.com/gabrocheleau&quot;&gt;@gabrocheleau&lt;/a&gt;), Karim Taam&amp;nbsp;(&lt;a href=&quot;https://github.com/matkt&quot;&gt;@matkt&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7620&quot;&gt;7620&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EOF Contract Creation&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;), Andrei Maiboroda&amp;nbsp;(&lt;a href=&quot;https://github.com/gumb0&quot;&gt;@gumb0&lt;/a&gt;), Piotr Dobaczewski&amp;nbsp;(&lt;a href=&quot;https://github.com/pdobacz&quot;&gt;@pdobacz&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7637&quot;&gt;7637&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Optimize EOA EXTCODEHASH&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Jame&amp;nbsp;(&lt;a href=&quot;https://github.com/ZWJKFLC&quot;&gt;@ZWJKFLC&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7639&quot;&gt;7639&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;eth/70 - Cease serving history before PoS&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;lightclient&amp;nbsp;(&lt;a href=&quot;https://github.com/lightclient&quot;&gt;@lightclient&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7643&quot;&gt;7643&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;History accumulator for pre-PoS data&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;lightclient&amp;nbsp;(&lt;a href=&quot;https://github.com/lightclient&quot;&gt;@lightclient&lt;/a&gt;), kdeme&amp;nbsp;(&lt;a href=&quot;https://github.com/kdeme&quot;&gt;@kdeme&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7645&quot;&gt;7645&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Alias ORIGIN to SENDER&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Cyrus Adkisson&amp;nbsp;(&lt;a href=&quot;https://github.com/cyrusadkisson&quot;&gt;@cyrusadkisson&lt;/a&gt;), Eirik Ulversøy&amp;nbsp;(&lt;a href=&quot;https://github.com/EirikUlversoy&quot;&gt;@EirikUlversoy&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7650&quot;&gt;7650&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Programmable access lists&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Qi Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/qizhou&quot;&gt;@qizhou&lt;/a&gt;), Zhiqiang Xu&amp;nbsp;(&lt;a href=&quot;https://github.com/zhiqiangxu&quot;&gt;@zhiqiangxu&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7657&quot;&gt;7657&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Sync committee slashings&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Etan Kissling&amp;nbsp;(&lt;a href=&quot;https://github.com/etan-status&quot;&gt;@etan-status&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7658&quot;&gt;7658&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Light client data backfill&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Etan Kissling&amp;nbsp;(&lt;a href=&quot;https://github.com/etan-status&quot;&gt;@etan-status&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7666&quot;&gt;7666&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EVM-ify the identity precompile&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7667&quot;&gt;7667&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Raise gas costs of hash functions&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7668&quot;&gt;7668&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Remove bloom filters&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7676&quot;&gt;7676&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EOF - Prepare for Address Space Extension&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Danno Ferrin&amp;nbsp;(&lt;a href=&quot;https://github.com/shemnon&quot;&gt;@shemnon&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7684&quot;&gt;7684&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Return deposits for distinct credentials&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Lion&amp;nbsp;(&lt;a href=&quot;https://github.com/dapplion&quot;&gt;@dapplion&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7686&quot;&gt;7686&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Linear EVM memory limits&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7692&quot;&gt;7692&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EVM Object Format (EOFv1) Meta&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;), Andrei Maiboroda&amp;nbsp;(&lt;a href=&quot;https://github.com/gumb0&quot;&gt;@gumb0&lt;/a&gt;), Piotr Dobaczewski&amp;nbsp;(&lt;a href=&quot;https://github.com/pdobacz&quot;&gt;@pdobacz&lt;/a&gt;), Danno Ferrin&amp;nbsp;(&lt;a href=&quot;https://github.com/shemnon&quot;&gt;@shemnon&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7698&quot;&gt;7698&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EOF - Creation transaction&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Piotr Dobaczewski&amp;nbsp;(&lt;a href=&quot;https://github.com/pdobacz&quot;&gt;@pdobacz&lt;/a&gt;), Andrei Maiboroda&amp;nbsp;(&lt;a href=&quot;https://github.com/gumb0&quot;&gt;@gumb0&lt;/a&gt;), Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;), Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7701&quot;&gt;7701&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Native Account Abstraction&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Yoav Weiss&amp;nbsp;(&lt;a href=&quot;https://github.com/yoavw&quot;&gt;@yoavw&lt;/a&gt;), Alex Forshtat&amp;nbsp;(&lt;a href=&quot;https://github.com/forshtat&quot;&gt;@forshtat&lt;/a&gt;), Dror Tirosh&amp;nbsp;(&lt;a href=&quot;https://github.com/drortirosh&quot;&gt;@drortirosh&lt;/a&gt;), Shahaf Nacson&amp;nbsp;(&lt;a href=&quot;https://github.com/shahafn&quot;&gt;@shahafn&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7703&quot;&gt;7703&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Increase calldata cost&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;William Morriss&amp;nbsp;(&lt;a href=&quot;https://github.com/wjmelements&quot;&gt;@wjmelements&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7705&quot;&gt;7705&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;NONREENTRANT and REENTRANT opcodes&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Charles Cooper&amp;nbsp;(&lt;a href=&quot;https://github.com/charles-cooper&quot;&gt;@charles-cooper&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7706&quot;&gt;7706&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Separate gas type for calldata&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7707&quot;&gt;7707&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Incentivize Access List Provisioning&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ben Adams&amp;nbsp;(&lt;a href=&quot;https://github.com/benaadams&quot;&gt;@benaadams&lt;/a&gt;), Oleg Iakushkin&amp;nbsp;(&lt;a href=&quot;https://github.com/OlegJakushkin&quot;&gt;@OlegJakushkin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7709&quot;&gt;7709&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Read BLOCKHASH from storage and update cost&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Tomasz Stanczak&amp;nbsp;(&lt;a href=&quot;https://github.com/tkstanczak&quot;&gt;@tkstanczak&lt;/a&gt;), Guillaume Ballet&amp;nbsp;(&lt;a href=&quot;https://github.com/gballet&quot;&gt;@gballet&lt;/a&gt;), Gajinder Singh&amp;nbsp;(&lt;a href=&quot;https://github.com/g11tech&quot;&gt;@g11tech&lt;/a&gt;), Tanishq Jasoria&amp;nbsp;(&lt;a href=&quot;https://github.com/tanishqjasoria&quot;&gt;@tanishqjasoria&lt;/a&gt;), Ignacio Hagopian&amp;nbsp;(&lt;a href=&quot;https://github.com/jsign&quot;&gt;@jsign&lt;/a&gt;), Jochem Brouwer&amp;nbsp;(&lt;a href=&quot;https://github.com/jochem-brouwer&quot;&gt;@jochem-brouwer&lt;/a&gt;), Gabriel Rocheleau&amp;nbsp;(&lt;a href=&quot;https://github.com/gabrocheleau&quot;&gt;@gabrocheleau&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7713&quot;&gt;7713&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Box type for EIP-712 messages&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Francisco Giordano&amp;nbsp;(&lt;a href=&quot;https://github.com/frangio&quot;&gt;@frangio&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7716&quot;&gt;7716&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Anti-correlation attestation penalties&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;dapplion&amp;nbsp;(&lt;a href=&quot;https://github.com/dapplion&quot;&gt;@dapplion&lt;/a&gt;), Toni Wahrstätter&amp;nbsp;(&lt;a href=&quot;https://github.com/nerolation&quot;&gt;@nerolation&lt;/a&gt;), Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7727&quot;&gt;7727&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EVM Transaction Bundles&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Lily Johnson&amp;nbsp;(&lt;a href=&quot;https://github.com/lilyjjo&quot;&gt;@lilyjjo&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7736&quot;&gt;7736&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Leaf-level state expiry in verkle trees&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Guillaume Ballet&amp;nbsp;(&lt;a href=&quot;https://github.com/gballet&quot;&gt;@gballet&lt;/a&gt;), Wei Han Ng&amp;nbsp;(&lt;a href=&quot;https://github.com/weiihann&quot;&gt;@weiihann&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7742&quot;&gt;7742&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Uncouple blob count between CL and EL&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Stokes&amp;nbsp;(&lt;a href=&quot;https://github.com/ralexstokes&quot;&gt;@ralexstokes&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7756&quot;&gt;7756&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EOF/EVM Trace Specification&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Martin Holst Swende&amp;nbsp;(&lt;a href=&quot;https://github.com/holiman&quot;&gt;@holiman&lt;/a&gt;), Marius van der Wijden&amp;nbsp;(&lt;a href=&quot;https://github.com/MariusVanDerWijden&quot;&gt;@MariusVanDerWijden&lt;/a&gt;), Danno Ferrin&amp;nbsp;(&lt;a href=&quot;https://github.com/shemnon&quot;&gt;@shemnon&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7761&quot;&gt;7761&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EXTCODETYPE instruction&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Andrei Maiboroda&amp;nbsp;(&lt;a href=&quot;https://github.com/gumb0&quot;&gt;@gumb0&lt;/a&gt;), Piotr Dobaczewski&amp;nbsp;(&lt;a href=&quot;https://github.com/pdobacz&quot;&gt;@pdobacz&lt;/a&gt;), Danno Ferrin&amp;nbsp;(&lt;a href=&quot;https://github.com/shemnon&quot;&gt;@shemnon&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7762&quot;&gt;7762&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Increase MIN_BASE_FEE_PER_BLOB_GAS&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Max Resnick&amp;nbsp;(&lt;a href=&quot;https://github.com/MaxResnick&quot;&gt;@MaxResnick&lt;/a&gt;), Davide Crapis&amp;nbsp;(&lt;a href=&quot;https://github.com/dcrapis&quot;&gt;@dcrapis&lt;/a&gt;), Ansgar Dietrichs&amp;nbsp;(&lt;a href=&quot;https://github.com/adietrichs&quot;&gt;@adietrichs&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7768&quot;&gt;7768&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;No-Ether transactions with free-for-all tips&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;William Entriken&amp;nbsp;(&lt;a href=&quot;https://github.com/fulldecent&quot;&gt;@fulldecent&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7775&quot;&gt;7775&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;BURN opcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Dev Bear&amp;nbsp;(&lt;a href=&quot;https://github.com/itsdevbear&quot;&gt;@itsdevbear&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7783&quot;&gt;7783&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Add Controlled Gas Limit Increase Strategy&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Giulio Rebuffo&amp;nbsp;(&lt;a href=&quot;https://github.com/Giulio2002&quot;&gt;@Giulio2002&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7784&quot;&gt;7784&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;GETCONTRACT opcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Tim Pechersky&amp;nbsp;(&lt;a href=&quot;https://github.com/peersky&quot;&gt;@peersky&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7790&quot;&gt;7790&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Controlled Gas Limit Increase Guidelines&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Giulio Rebuffo&amp;nbsp;(&lt;a href=&quot;https://github.com/Giulio2002&quot;&gt;@Giulio2002&lt;/a&gt;), Ben Adams&amp;nbsp;(&lt;a href=&quot;https://github.com/benaadams&quot;&gt;@benaadams&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7792&quot;&gt;7792&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Verifiable logs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Etan Kissling&amp;nbsp;(&lt;a href=&quot;https://github.com/etan-status&quot;&gt;@etan-status&lt;/a&gt;), Gajinder Singh&amp;nbsp;(&lt;a href=&quot;https://github.com/g11tech&quot;&gt;@g11tech&lt;/a&gt;), Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7793&quot;&gt;7793&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Conditional Transactions&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Marc Harvey-Hill&amp;nbsp;(&lt;a href=&quot;https://github.com/Marchhill&quot;&gt;@Marchhill&lt;/a&gt;), Ahmad Bitar&amp;nbsp;(&lt;a href=&quot;https://github.com/smartprogrammer93&quot;&gt;@smartprogrammer93&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7797&quot;&gt;7797&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Double speed for hash_tree_root&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Etan Kissling&amp;nbsp;(&lt;a href=&quot;https://github.com/etan-status&quot;&gt;@etan-status&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7808&quot;&gt;7808&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Reserve Tx-Type Range for RIPs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Carl Beekhuizen&amp;nbsp;(&lt;a href=&quot;https://github.com/carlbeek&quot;&gt;@carlbeek&lt;/a&gt;), Yoav Weiss&amp;nbsp;(&lt;a href=&quot;https://github.com/yoavw&quot;&gt;@yoavw&lt;/a&gt;), Ansgar Dietrichs&amp;nbsp;(&lt;a href=&quot;https://github.com/adietrichs&quot;&gt;@adietrichs&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7830&quot;&gt;7830&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Contract size limit increase for EOF&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Danno Ferrin&amp;nbsp;(&lt;a href=&quot;https://github.com/shemnon&quot;&gt;@shemnon&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7833&quot;&gt;7833&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Scheduled function calls&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Keyvan Kambakhsh&amp;nbsp;(&lt;a href=&quot;https://github.com/keyvank&quot;&gt;@keyvank&lt;/a&gt;), Nobitex Labs&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:labs@nobitex.ir&quot;&gt;labs@nobitex.ir&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7867&quot;&gt;7867&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Flow Control Wallet Call Capability&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Sam Wilson (@SamWilsn)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:sam@binarycake.ca&quot;&gt;sam@binarycake.ca&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7873&quot;&gt;7873&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EOF - TXCREATE and InitcodeTransaction type&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Piotr Dobaczewski&amp;nbsp;(&lt;a href=&quot;https://github.com/pdobacz&quot;&gt;@pdobacz&lt;/a&gt;), Andrei Maiboroda&amp;nbsp;(&lt;a href=&quot;https://github.com/gumb0&quot;&gt;@gumb0&lt;/a&gt;), Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;), Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Danno Ferrin&amp;nbsp;(&lt;a href=&quot;https://github.com/shemnon&quot;&gt;@shemnon&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7877&quot;&gt;7877&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Enhanced RETURN opcodes&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Josh Weintraub&amp;nbsp;(&lt;a href=&quot;https://github.com/jhweintraub&quot;&gt;@jhweintraub&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7886&quot;&gt;7886&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Delayed execution&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Francesco D&apos;Amato&amp;nbsp;(&lt;a href=&quot;https://github.com/fradamt&quot;&gt;@fradamt&lt;/a&gt;), Toni Wahrstätter&amp;nbsp;(&lt;a href=&quot;https://github.com/nerolation&quot;&gt;@nerolation&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7889&quot;&gt;7889&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Emit log on revert&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Shoham Chakraborty&amp;nbsp;(&lt;a href=&quot;https://github.com/shohamc1&quot;&gt;@shohamc1&lt;/a&gt;), Alex Forshtat&amp;nbsp;(&lt;a href=&quot;https://github.com/forshtat&quot;&gt;@forshtat&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7896&quot;&gt;7896&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;ABI attachment in `wallet_sendCalls`&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Francisco Giordano&amp;nbsp;(&lt;a href=&quot;https://github.com/frangio&quot;&gt;@frangio&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7898&quot;&gt;7898&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Uncouple execution payload from beacon block&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gajinder Singh&amp;nbsp;(&lt;a href=&quot;https://github.com/g11tech&quot;&gt;@g11tech&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7903&quot;&gt;7903&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Remove Initcode Size Limit&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Charles Cooper&amp;nbsp;(&lt;a href=&quot;https://github.com/charles-cooper&quot;&gt;@charles-cooper&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7912&quot;&gt;7912&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Pragmatic stack manipulation tools&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;lightclient&amp;nbsp;(&lt;a href=&quot;https://github.com/lightclient&quot;&gt;@lightclient&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7915&quot;&gt;7915&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Adaptive mean reversion blob pricing&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Anders Elowsson&amp;nbsp;(&lt;a href=&quot;https://github.com/anderselowsson&quot;&gt;@anderselowsson&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7919&quot;&gt;7919&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Pureth Meta&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Etan Kissling&amp;nbsp;(&lt;a href=&quot;https://github.com/etan-status&quot;&gt;@etan-status&lt;/a&gt;), Gajinder Singh&amp;nbsp;(&lt;a href=&quot;https://github.com/g11tech&quot;&gt;@g11tech&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7921&quot;&gt;7921&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Skip `JUMPDEST` immediate argument check&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;William Morriss&amp;nbsp;(&lt;a href=&quot;https://github.com/wjmelements&quot;&gt;@wjmelements&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7922&quot;&gt;7922&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Dynamic exit queue rate limit&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Mikhail Kalinin&amp;nbsp;(&lt;a href=&quot;https://github.com/mkalinin&quot;&gt;@mkalinin&lt;/a&gt;), Mike Neuder&amp;nbsp;(&lt;a href=&quot;https://github.com/michaelneuder&quot;&gt;@michaelneuder&lt;/a&gt;), Mallesh Pai&amp;nbsp;(&lt;a href=&quot;https://github.com/Mmp610&quot;&gt;@Mmp610&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7927&quot;&gt;7927&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;History Expiry Meta&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Piper Merriam&amp;nbsp;(&lt;a href=&quot;https://github.com/pipermerriam&quot;&gt;@pipermerriam&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7938&quot;&gt;7938&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Exponential Gas Limit Increase&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Dankrad Feist&amp;nbsp;(&lt;a href=&quot;https://github.com/dankrad&quot;&gt;@dankrad&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7956&quot;&gt;7956&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Tx Ordering via Block-level Randomness&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Aryaethn&amp;nbsp;(&lt;a href=&quot;https://github.com/aryaethn&quot;&gt;@aryaethn&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7957&quot;&gt;7957&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EVM64 - EOF support&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Wei Tang&amp;nbsp;(&lt;a href=&quot;https://github.com/sorpaas&quot;&gt;@sorpaas&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7958&quot;&gt;7958&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;EVM64 - Little endian opcodes&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Wei Tang&amp;nbsp;(&lt;a href=&quot;https://github.com/sorpaas&quot;&gt;@sorpaas&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8013&quot;&gt;8013&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Static relative jumps and calls for the EVM&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Greg Colvin&amp;nbsp;(&lt;a href=&quot;https://github.com/gcolvin&quot;&gt;@gcolvin&lt;/a&gt;), Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;), Andrei Maiboroda&amp;nbsp;(&lt;a href=&quot;https://github.com/gumb0&quot;&gt;@gumb0&lt;/a&gt;), Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8015&quot;&gt;8015&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Remove `deposit` and `eth1data` fields&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Terence&amp;nbsp;(&lt;a href=&quot;https://github.com/terencechain&quot;&gt;@terencechain&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
    &lt;/table&gt;
  

  
  
  
    &lt;h2 id=&quot;withdrawn&quot;&gt;Withdrawn&lt;/h2&gt;
    &lt;table class=&quot;eiptable&quot;&gt;
      &lt;thead&gt;
        
        &lt;tr&gt;
          &lt;th class=&quot;eipnum&quot;&gt;Number&lt;/th&gt;&lt;th class=&quot;withdrawn-reason&quot;&gt;Withdrawn Reason&lt;/th&gt;&lt;th class=&quot;title&quot;&gt;Title&lt;/th&gt;&lt;th class=&quot;author&quot;&gt;Author&lt;/th&gt;&lt;/tr&gt;      
        
      &lt;/thead&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3&quot;&gt;3&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Addition of CALLDEPTH opcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Martin Holst Swende&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:martin@swende.se&quot;&gt;martin@swende.se&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-67&quot;&gt;67&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;URI Scheme with Metadata, Value and Bytecode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Van de Sande&amp;nbsp;(&lt;a href=&quot;https://github.com/alexvansande&quot;&gt;@alexvansande&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-875&quot;&gt;875&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Simpler NFT standard with batching and native atomic swaps&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Weiwu Zhang&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:a@colourful.land&quot;&gt;a@colourful.land&lt;/a&gt;&amp;gt;, James Sangalli&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:j.l.sangalli@gmail.com&quot;&gt;j.l.sangalli@gmail.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-908&quot;&gt;908&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Reward clients for a sustainable network&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;James Ray&amp;nbsp;(&lt;a href=&quot;https://github.com/jamesray1&quot;&gt;@jamesray1&lt;/a&gt;), Micah Zoltu&amp;nbsp;(&lt;a href=&quot;https://github.com/MicahZoltu&quot;&gt;@MicahZoltu&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-999&quot;&gt;999&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Restore Contract Code at 0x863DF6BFa4469f3ead0bE8f9F2AAE51c91A907b4&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Afri Schoedon&amp;nbsp;(&lt;a href=&quot;https://github.com/5chdn&quot;&gt;@5chdn&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1123&quot;&gt;1123&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Revised Ethereum Smart Contract Packaging Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;g. nicholas d’andrea&amp;nbsp;(&lt;a href=&quot;https://github.com/gnidan&quot;&gt;@gnidan&lt;/a&gt;), Piper Merriam&amp;nbsp;(&lt;a href=&quot;https://github.com/pipermerriam&quot;&gt;@pipermerriam&lt;/a&gt;), Nick Gheorghita&amp;nbsp;(&lt;a href=&quot;https://github.com/njgheorghita&quot;&gt;@njgheorghita&lt;/a&gt;), Danny Ryan&amp;nbsp;(&lt;a href=&quot;https://github.com/djrtwo&quot;&gt;@djrtwo&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1154&quot;&gt;1154&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Oracle Interface&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alan Lu&amp;nbsp;(&lt;a href=&quot;https://github.com/cag&quot;&gt;@cag&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1240&quot;&gt;1240&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Remove Difficulty Bomb&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Micah Zoltu&amp;nbsp;(&lt;a href=&quot;https://github.com/MicahZoltu&quot;&gt;@MicahZoltu&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1355&quot;&gt;1355&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Ethash 1a&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;), Jean M. Cyr&amp;nbsp;(&lt;a href=&quot;https://github.com/jean-m-cyr&quot;&gt;@jean-m-cyr&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1538&quot;&gt;1538&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Transparent Contract Standard&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Mudge&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:nick@perfectabstractions.com&quot;&gt;nick@perfectabstractions.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1682&quot;&gt;1682&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Storage Rent&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Felix J Lange&amp;nbsp;(&lt;a href=&quot;https://github.com/fjl&quot;&gt;@fjl&lt;/a&gt;), Martin Holst Swende&amp;nbsp;(&lt;a href=&quot;https://github.com/holiman&quot;&gt;@holiman&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1706&quot;&gt;1706&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Disable SSTORE with gasleft lower than call stipend&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Forshtat&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:alex@tabookey.com&quot;&gt;alex@tabookey.com&lt;/a&gt;&amp;gt;, Yoav Weiss&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:yoav@tabookey.com&quot;&gt;yoav@tabookey.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-1890&quot;&gt;1890&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Commitment to Sustainable Ecosystem Funding&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Gregory Markou&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:greg@chainsafe.io&quot;&gt;greg@chainsafe.io&lt;/a&gt;&amp;gt;, Kevin Owocki&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:kevin@gitcoin.co&quot;&gt;kevin@gitcoin.co&lt;/a&gt;&amp;gt;, Lane Rettig&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:lane@ethereum.org&quot;&gt;lane@ethereum.org&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2025&quot;&gt;2025&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Block Rewards Proposal for funding Eth1.x&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;James Hancock&amp;nbsp;(&lt;a href=&quot;https://github.com/madeoftin&quot;&gt;@madeoftin&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2070&quot;&gt;2070&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hardfork Meta: Berlin&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2315&quot;&gt;2315&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Simple Subroutines for the EVM&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Greg Colvin&amp;nbsp;(&lt;a href=&quot;https://github.com/gcolvin&quot;&gt;@gcolvin&lt;/a&gt;), Martin Holst Swende&amp;nbsp;(&lt;a href=&quot;https://github.com/holiman&quot;&gt;@holiman&lt;/a&gt;), Brooklyn Zelenka&amp;nbsp;(&lt;a href=&quot;https://github.com/expede&quot;&gt;@expede&lt;/a&gt;), John Max Skaller&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:skaller@internode.on.net&quot;&gt;skaller@internode.on.net&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2458&quot;&gt;2458&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Updates and Updated-by Header&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Edson Ayllon&amp;nbsp;(&lt;a href=&quot;https://github.com/edsonayllon&quot;&gt;@edsonayllon&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2677&quot;&gt;2677&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Limit size of `initcode`&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Martin Holst Swende&amp;nbsp;(&lt;a href=&quot;https://github.com/holiman&quot;&gt;@holiman&lt;/a&gt;), Paweł Bylica&amp;nbsp;(&lt;a href=&quot;https://github.com/chfast&quot;&gt;@chfast&lt;/a&gt;), Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2711&quot;&gt;2711&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Sponsored, expiring and batch transactions.&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Micah Zoltu&amp;nbsp;(&lt;a href=&quot;https://github.com/MicahZoltu&quot;&gt;@MicahZoltu&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2733&quot;&gt;2733&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Transaction Package&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Matt Garnett&amp;nbsp;(&lt;a href=&quot;https://github.com/lightclient&quot;&gt;@lightclient&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2786&quot;&gt;2786&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Ethereum Provider Connect/Disconnect Events&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Micah Zoltu&amp;nbsp;(&lt;a href=&quot;https://github.com/MicahZoltu&quot;&gt;@MicahZoltu&lt;/a&gt;), Erik Marks&amp;nbsp;(&lt;a href=&quot;https://github.com/rekmarks&quot;&gt;@rekmarks&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2938&quot;&gt;2938&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Account Abstraction&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Vitalik Buterin&amp;nbsp;(&lt;a href=&quot;https://github.com/vbuterin&quot;&gt;@vbuterin&lt;/a&gt;), Ansgar Dietrichs&amp;nbsp;(&lt;a href=&quot;https://github.com/adietrichs&quot;&gt;@adietrichs&lt;/a&gt;), Matt Garnett&amp;nbsp;(&lt;a href=&quot;https://github.com/lightclient&quot;&gt;@lightclient&lt;/a&gt;), Will Villanueva&amp;nbsp;(&lt;a href=&quot;https://github.com/villanuevawill&quot;&gt;@villanuevawill&lt;/a&gt;), Sam Wilson&amp;nbsp;(&lt;a href=&quot;https://github.com/SamWilsn&quot;&gt;@SamWilsn&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-2972&quot;&gt;2972&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Wrapped Legacy Transactions&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Micah Zoltu&amp;nbsp;(&lt;a href=&quot;https://github.com/MicahZoltu&quot;&gt;@MicahZoltu&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3074&quot;&gt;3074&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;AUTH and AUTHCALL opcodes&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Sam Wilson&amp;nbsp;(&lt;a href=&quot;https://github.com/SamWilsn&quot;&gt;@SamWilsn&lt;/a&gt;), Ansgar Dietrichs&amp;nbsp;(&lt;a href=&quot;https://github.com/adietrichs&quot;&gt;@adietrichs&lt;/a&gt;), Matt Garnett&amp;nbsp;(&lt;a href=&quot;https://github.com/lightclient&quot;&gt;@lightclient&lt;/a&gt;), Micah Zoltu&amp;nbsp;(&lt;a href=&quot;https://github.com/micahzoltu&quot;&gt;@micahzoltu&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3332&quot;&gt;3332&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;MEDGASPRICE Opcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Justice Hudson&amp;nbsp;(&lt;a href=&quot;https://github.com/jchancehud&quot;&gt;@jchancehud&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3338&quot;&gt;3338&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Limit account nonce to 2^52&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Micah Zoltu&amp;nbsp;(&lt;a href=&quot;https://github.com/MicahZoltu&quot;&gt;@MicahZoltu&lt;/a&gt;), Alex Beregszaszi&amp;nbsp;(&lt;a href=&quot;https://github.com/axic&quot;&gt;@axic&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3374&quot;&gt;3374&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Predictable Proof-of-Work (POW) Sunsetting&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Query0x&amp;nbsp;(&lt;a href=&quot;https://github.com/Query0x&quot;&gt;@Query0x&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3382&quot;&gt;3382&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Hardcoded Block Gas Limit&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Philippe Castonguay&amp;nbsp;(&lt;a href=&quot;https://github.com/PhABC&quot;&gt;@PhABC&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-3779&quot;&gt;3779&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Safer Control Flow for the EVM&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Greg Colvin&amp;nbsp;(&lt;a href=&quot;https://github.com/gcolvin&quot;&gt;@gcolvin&lt;/a&gt;), Greg Colvin&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:greg@colvin.org&quot;&gt;greg@colvin.org&lt;/a&gt;&amp;gt;, Brooklyn Zelenka&amp;nbsp;(&lt;a href=&quot;https://github.com/expede&quot;&gt;@expede&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-5003&quot;&gt;5003&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Insert Code into EOAs with AUTHUSURP&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Dan Finlay&amp;nbsp;(&lt;a href=&quot;https://github.com/danfinlay&quot;&gt;@danfinlay&lt;/a&gt;), Sam Wilson&amp;nbsp;(&lt;a href=&quot;https://github.com/SamWilsn&quot;&gt;@SamWilsn&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-6913&quot;&gt;6913&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;SETCODE instruction&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;William Morriss&amp;nbsp;(&lt;a href=&quot;https://github.com/wjmelements&quot;&gt;@wjmelements&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7199&quot;&gt;7199&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Linter Scope&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Zainan Victor Zhou&amp;nbsp;(&lt;a href=&quot;https://github.com/xinbenlv&quot;&gt;@xinbenlv&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7542&quot;&gt;7542&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;eth/70 - available-blocks-extended protocol&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Ahmad Bitar (@smartprogrammer93)&amp;nbsp;&amp;lt;&lt;a href=&quot;mailto:smartprogrammer@windowslive.com&quot;&gt;smartprogrammer@windowslive.com&lt;/a&gt;&amp;gt;&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7636&quot;&gt;7636&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Extension of EIP-778 for &amp;quot;client&amp;quot; ENR Entry&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;James Kempton&amp;nbsp;(&lt;a href=&quot;https://github.com/SirSpudlington&quot;&gt;@SirSpudlington&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7664&quot;&gt;7664&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Access-Key opcode&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Diederik Loerakker&amp;nbsp;(&lt;a href=&quot;https://github.com/protolambda&quot;&gt;@protolambda&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7675&quot;&gt;7675&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Retroactively Included EIPs&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Tim Beiko&amp;nbsp;(&lt;a href=&quot;https://github.com/timbeiko&quot;&gt;@timbeiko&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7788&quot;&gt;7788&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Dynamic target blob count&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Marc Harvey-Hill&amp;nbsp;(&lt;a href=&quot;https://github.com/Marchhill&quot;&gt;@Marchhill&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7897&quot;&gt;7897&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Wallet-Linked Services for Smart Accounts&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Francesco Sullo&amp;nbsp;(&lt;a href=&quot;https://github.com/sullof&quot;&gt;@sullof&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-7980&quot;&gt;7980&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Ed25519 transaction support&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;James Kempton&amp;nbsp;(&lt;a href=&quot;https://github.com/SirSpudlington&quot;&gt;@SirSpudlington&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
        &lt;tr&gt;
          &lt;td class=&quot;eipnum&quot;&gt;&lt;a href=&quot;/EIPs/EIPS/eip-8109&quot;&gt;8109&lt;/a&gt;&lt;/td&gt;
          
          &lt;td class=&quot;title&quot;&gt;Diamonds, Simplified&lt;/td&gt;
          &lt;td class=&quot;author&quot;&gt;Nick Mudge&amp;nbsp;(&lt;a href=&quot;https://github.com/mudgen&quot;&gt;@mudgen&lt;/a&gt;)&lt;/td&gt;
        &lt;/tr&gt;
      
    &lt;/table&gt;
  


</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/all</link>
        <guid isPermaLink="true">https://eips.ethereum.org/all</guid>
      </item>
    
      <item>
        <title></title>
        <category>/</category>
        
        <description>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;rss version=&quot;2.0&quot; xmlns:atom=&quot;http://www.w3.org/2005/Atom&quot;&gt;
  &lt;channel&gt;
    &lt;title&gt;Ethereum EIPs&lt;/title&gt;
    &lt;description&gt;A feed of all EIPs&lt;/description&gt;
    &lt;link&gt;{{ site.url }}&lt;/link&gt;
    &lt;atom:link href=&quot;{{ site.url }}/all.xml&quot; rel=&quot;self&quot; type=&quot;application/rss+xml&quot; /&gt;
    &lt;lastBuildDate&gt;{{ site.time | date_to_rfc822 }}&lt;/lastBuildDate&gt;
    {% assign eips = site.pages | sort: &apos;eip&apos; %}
    {% for eip in eips %}
      &lt;item&gt;
        &lt;title&gt;{{ eip.title | xml_escape }}&lt;/title&gt;
        &lt;category&gt;{{ eip.type | xml_escape }}/{{ eip.category | xml_escape }}&lt;/category&gt;
        {% if eip.discussions-to %}
          &lt;comments&gt;{{ eip.discussions-to | xml_escape }}&lt;/comments&gt;
        {% endif %}
        &lt;description&gt;{{ eip.content | xml_escape }}&lt;/description&gt;
        &lt;pubDate&gt;{{ eip.created | date_to_rfc822 }}&lt;/pubDate&gt;
        &lt;link&gt;{{ site.url }}{{ eip.url }}&lt;/link&gt;
        &lt;guid isPermaLink=&quot;true&quot;&gt;{{ site.url }}{{ eip.url }}&lt;/guid&gt;
      &lt;/item&gt;
    {% endfor %}
  &lt;/channel&gt;
&lt;/rss&gt;
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/rss/all.xml</link>
        <guid isPermaLink="true">https://eips.ethereum.org/rss/all.xml</guid>
      </item>
    
      <item>
        <title>Core</title>
        <category>/</category>
        
        <description>{% assign eips=site.pages|where:&quot;type&quot;,&quot;Standards Track&quot;|where:&quot;category&quot;,&quot;Core&quot; %}
{% include eiptable.html eips=eips %}
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/core</link>
        <guid isPermaLink="true">https://eips.ethereum.org/core</guid>
      </item>
    
      <item>
        <title></title>
        <category>/</category>
        
        <description>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;rss version=&quot;2.0&quot; xmlns:atom=&quot;http://www.w3.org/2005/Atom&quot;&gt;
  &lt;channel&gt;
    &lt;title&gt;Ethereum EIPs - Last Call Review&lt;/title&gt;
    &lt;description&gt;All EIPs which are in the &quot;last call&quot; status, please help review these and provide your feedback!&lt;/description&gt;
    &lt;link&gt;{{ site.url }}&lt;/link&gt;
    &lt;atom:link href=&quot;{{ site.url }}/rss/last-call.xml&quot; rel=&quot;self&quot; type=&quot;application/rss+xml&quot; /&gt;
    &lt;lastBuildDate&gt;{{ site.time | date_to_rfc822 }}&lt;/lastBuildDate&gt;
    {% assign eips = site.pages | sort: &apos;eip&apos; %}
    {% for eip in eips %}
      {% if eip.category == &quot;ERC&quot; %}
      {% if eip.status == &quot;Last Call&quot; %}
      {% capture description %}
        &lt;p&gt;&lt;strong&gt;EIP #{{ eip.eip }} - {{eip.title }}&lt;/strong&gt; is in Last Call status. It is authored by {{ eip.author }} and was originally created {{ eip.created }}. It is in the {{ eip.category }} category of type {{ eip.type }}. Please review and note any changes that should block acceptance.&lt;/p&gt;
        {% if eip.discussions-to %}
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;{{ eip.discussions-to }}&quot;&gt;{{ eip.discussions-to }}&lt;/a&gt;&lt;/p&gt;
        {% endif %}
        &lt;hr /&gt;
        {{ eip.content }}
      {% endcapture %}
      &lt;item&gt;
        &lt;title&gt;{{ eip.title | xml_escape }}&lt;/title&gt;
        &lt;description&gt;{{ description | xml_escape }}&lt;/description&gt;
        &lt;pubDate&gt;{{ eip.created | date_to_rfc822 }}&lt;/pubDate&gt;
        &lt;link&gt;{{ site.url }}/{{ eip.url }}&lt;/link&gt;
        &lt;guid isPermaLink=&quot;true&quot;&gt;{{ site.url }}/{{ eip.url }}&lt;/guid&gt;
      &lt;/item&gt;
      {% endif %}
      {% endif %}
    {% endfor %}
  &lt;/channel&gt;
&lt;/rss&gt;
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/rss/erc-last-call.xml</link>
        <guid isPermaLink="true">https://eips.ethereum.org/rss/erc-last-call.xml</guid>
      </item>
    
      <item>
        <title>ERC</title>
        <category>/</category>
        
        <description>{% assign eips=site.pages|where:&quot;type&quot;,&quot;Standards Track&quot;|where:&quot;category&quot;,&quot;ERC&quot; %}
{% include eiptable.html eips=eips %}
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/erc</link>
        <guid isPermaLink="true">https://eips.ethereum.org/erc</guid>
      </item>
    
      <item>
        <title></title>
        <category>/</category>
        
        <description>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;rss version=&quot;2.0&quot; xmlns:atom=&quot;http://www.w3.org/2005/Atom&quot;&gt;
  &lt;channel&gt;
    &lt;title&gt;Ethereum ERCs&lt;/title&gt;
    &lt;description&gt;All updates for ERCs&lt;/description&gt;
    &lt;link&gt;{{ site.url }}&lt;/link&gt;
    &lt;atom:link href=&quot;{{ site.url }}/rss/erc.xml&quot; rel=&quot;self&quot; type=&quot;application/rss+xml&quot; /&gt;
    &lt;lastBuildDate&gt;{{ site.time | date_to_rfc822 }}&lt;/lastBuildDate&gt;
    {% assign eips = site.pages | sort: &apos;eip&apos; %}
    {% for eip in eips %}
      {% if eip.category == &quot;ERC&quot; %}
      {% capture description %}
        &lt;p&gt;&lt;strong&gt;EIP #{{ eip.eip }} - {{eip.title }}&lt;/strong&gt; is in the {{ eip.category }} category of type {{ eip.type }} and was just updated.&lt;/p&gt;
        {% if eip.discussions-to %}
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;{{ eip.discussions-to }}&quot;&gt;{{ eip.discussions-to }}&lt;/a&gt;&lt;/p&gt;
        {% endif %}
        &lt;hr /&gt;
        {{ eip.content }}
      {% endcapture %}
      &lt;item&gt;
        &lt;title&gt;{{ eip.title | xml_escape }}&lt;/title&gt;
        &lt;description&gt;{{ description | xml_escape }}&lt;/description&gt;
        &lt;pubDate&gt;{{ eip.created | date_to_rfc822 }}&lt;/pubDate&gt;
        &lt;link&gt;{{ site.url }}/{{ eip.url }}&lt;/link&gt;
        &lt;guid isPermaLink=&quot;true&quot;&gt;{{ site.url }}/{{ eip.url }}&lt;/guid&gt;
      &lt;/item&gt;
      {% endif %}
    {% endfor %}
  &lt;/channel&gt;
&lt;/rss&gt;
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/rss/erc.xml</link>
        <guid isPermaLink="true">https://eips.ethereum.org/rss/erc.xml</guid>
      </item>
    
      <item>
        <title>Home</title>
        <category>/</category>
        
        <description>&lt;h1 class=&quot;page-heading&quot;&gt;EIPs
  &lt;a href=&quot;https://discord.gg/Nz6rtfJ8Cu&quot;&gt;&lt;img src=&quot;https://dcbadge.limes.pink/api/server/Nz6rtfJ8Cu?style=flat&quot; alt=&quot;Discord channel for ECH eip-editer&quot;&gt;&lt;/a&gt;
  &lt;a href=&quot;https://discord.gg/EVTQ9crVgQ&quot;&gt;&lt;img src=&quot;https://dcbadge.limes.pink/api/server/EVTQ9crVgQ?style=flat&quot; alt=&quot;Discord channel for Eth R&amp;D eip-editing&quot;&gt;&lt;/a&gt;
  &lt;a href=&quot;https://discord.gg/mRzPXmmYEA&quot;&gt;&lt;img src=&quot;https://dcbadge.limes.pink/api/server/mRzPXmmYEA?style=flat&quot; alt=&quot;Discord server for discussions about proposals that impact Ethereum wallets&quot;&gt;&lt;/a&gt;
  &lt;a href=&quot;rss/all.xml&quot;&gt;&lt;img src=&quot;https://img.shields.io/badge/rss-Everything-red.svg&quot; alt=&quot;RSS&quot;&gt;&lt;/a&gt;
  &lt;a href=&quot;rss/last-call.xml&quot;&gt;&lt;img src=&quot;https://img.shields.io/badge/rss-Last Calls-red.svg&quot; alt=&quot;RSS&quot;&gt;&lt;/a&gt;
  &lt;a href=&quot;rss/nonerc.xml&quot;&gt;&lt;img src=&quot;https://img.shields.io/badge/rss-All except ERC-red.svg&quot; alt=&quot;RSS&quot;&gt;&lt;/a&gt;
  &lt;a href=&quot;https://eepurl.com/ikqNIP&quot;&gt;&lt;img src=&quot;https://img.shields.io/badge/-email%20alerts-red.svg&quot; alt=&quot;RSS&quot;&gt;&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;Ethereum Improvement Proposals (EIPs) describe standards for the Ethereum platform, including core protocol specifications, client APIs, and contract standards. Network upgrades are discussed separately in the &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/ethereum/pm/&quot;&gt;Ethereum Project Management&lt;/a&gt; repository.&lt;/p&gt;

&lt;h2&gt;Contributing&lt;/h2&gt;
&lt;p&gt;First review &lt;a href=&quot;EIPS/eip-1&quot;&gt;EIP-1&lt;/a&gt;. Then clone the repository and add your EIP to it. There is a &lt;a href=&quot;https://github.com/ethereum/EIPs/blob/master/eip-template.md?plain=1&quot;&gt;template EIP here&lt;/a&gt;. Then submit a Pull Request to Ethereum&apos;s &lt;a href=&quot;https://github.com/ethereum/EIPs&quot;&gt;EIPs repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;EIP status terms&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Idea&lt;/strong&gt; - An idea that is pre-draft. This is not tracked within the EIP Repository.
  &lt;li&gt;&lt;strong&gt;Draft&lt;/strong&gt; - The first formally tracked stage of an EIP in development. An EIP is merged by an EIP Editor into the EIP repository when properly formatted.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Review&lt;/strong&gt; - An EIP Author marks an EIP as ready for and requesting Peer Review.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Last Call&lt;/strong&gt; - This is the final review window for an EIP before moving to FINAL. An EIP editor will assign Last Call status and set a review end date (`last-call-deadline`), typically 14 days later. If this period results in necessary normative changes it will revert the EIP to Review.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Final&lt;/strong&gt; - This EIP represents the final standard. A Final EIP exists in a state of finality and should only be updated to correct errata and add non-normative clarifications.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Stagnant&lt;/strong&gt; - Any EIP in Draft or Review if inactive for a period of 6 months or greater is moved to Stagnant. An EIP may be resurrected from this state by Authors or EIP Editors through moving it back to Draft.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Withdrawn&lt;/strong&gt; - The EIP Author(s) have withdrawn the proposed EIP. This state has finality and can no longer be resurrected using this EIP number. If the idea is pursued at later date it is considered a new proposal.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Living&lt;/strong&gt; - A special status for EIPs that are designed to be continually updated and not reach a state of finality. This includes most notably EIP-1.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;EIP Types&lt;/h2&gt;

&lt;p&gt;EIPs are separated into a number of types, and each has its own list of EIPs.&lt;/p&gt;

&lt;h3&gt;Standards Track ({{site.pages|where:&quot;type&quot;,&quot;Standards Track&quot;|size}})&lt;/h3&gt;
&lt;p&gt;Describes any change that affects most or all Ethereum implementations, such as a change to the network protocol, a change in block or transaction validity rules, proposed application standards/conventions, or any change or addition that affects the interoperability of applications using Ethereum. Furthermore Standard EIPs can be broken down into the following categories.&lt;/p&gt;

&lt;h4&gt;&lt;a href=&quot;{{&quot;core&quot;|relative_url}}&quot;&gt;Core&lt;/a&gt; ({{site.pages|where:&quot;type&quot;,&quot;Standards Track&quot;|where:&quot;category&quot;,&quot;Core&quot;|size}})&lt;/h4&gt;
&lt;p&gt;Improvements requiring a consensus fork (e.g. &lt;a href=&quot;./EIPS/eip-5&quot;&gt;EIP-5&lt;/a&gt;, &lt;a href=&quot;./EIPS/eip-211&quot;&gt;EIP-211&lt;/a&gt;), as well as changes that are not necessarily consensus critical but may be relevant to “core dev” discussions (for example, the PoA algorithm for testnets described in &lt;a href=&quot;./EIPS/eip-225&quot;&gt;EIP-225&lt;/a&gt;).&lt;/p&gt;

&lt;h4&gt;&lt;a href=&quot;{{&quot;networking&quot;|relative_url}}&quot;&gt;Networking&lt;/a&gt; ({{site.pages|where:&quot;type&quot;,&quot;Standards Track&quot;|where:&quot;category&quot;,&quot;Networking&quot;|size}})&lt;/h4&gt;
&lt;p&gt;Includes improvements around devp2p (&lt;a href=&quot;./EIPS/eip-8&quot;&gt;EIP-8&lt;/a&gt;) and Light Ethereum Subprotocol, as well as proposed improvements to network protocol specifications of whisper and swarm.&lt;/p&gt;

&lt;h4&gt;&lt;a href=&quot;{{&quot;interface&quot;|relative_url}}&quot;&gt;Interface&lt;/a&gt; ({{site.pages|where:&quot;type&quot;,&quot;Standards Track&quot;|where:&quot;category&quot;,&quot;Interface&quot;|size}})&lt;/h4&gt;
&lt;p&gt;Includes improvements around client API/RPC specifications and standards, and also certain language-level standards like method names (&lt;a href=&quot;./EIPS/eip-6&quot;&gt;EIP-6&lt;/a&gt;) and contract ABIs. The label “interface” aligns with the interfaces repo and discussion should primarily occur in that repository before an EIP is submitted to the EIPs repository.&lt;/p&gt;

&lt;h4&gt;&lt;a href=&quot;{{&quot;erc&quot;|relative_url}}&quot;&gt;ERC&lt;/a&gt; ({{site.pages|where:&quot;type&quot;,&quot;Standards Track&quot;|where:&quot;category&quot;,&quot;ERC&quot;|size}})&lt;/h4&gt;
&lt;p&gt;Application-level standards and conventions, including contract standards such as token standards (&lt;a href=&quot;./EIPS/eip-20&quot;&gt;EIP-20&lt;/a&gt;), name registries (&lt;a href=&quot;./EIPS/eip-137&quot;&gt;EIP-137&lt;/a&gt;), URI schemes (&lt;a href=&quot;./EIPS/eip-681&quot;&gt;EIP-681&lt;/a&gt;), library/package formats (&lt;a href=&quot;./EIPS/eip-190&quot;&gt;EIP-190&lt;/a&gt;), and account abstraction (&lt;a href=&quot;./EIPS/eip-4337&quot;&gt;EIP-4337&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;&lt;a href=&quot;{{&quot;meta&quot;|relative_url}}&quot;&gt;Meta&lt;/a&gt; ({{site.pages|where:&quot;type&quot;,&quot;Meta&quot;|size}})&lt;/h3&gt;
&lt;p&gt;Describes a process surrounding Ethereum or proposes a change to (or an event in) a process. Process EIPs are like Standards Track EIPs but apply to areas other than the Ethereum protocol itself. They may propose an implementation, but not to Ethereum&apos;s codebase; they often require community consensus; unlike Informational EIPs, they are more than recommendations, and users are typically not free to ignore them. Examples include procedures, guidelines, changes to the decision-making process, and changes to the tools or environment used in Ethereum development. Any meta-EIP is also considered a Process EIP.&lt;/p&gt;

&lt;h3&gt;&lt;a href=&quot;{{&quot;informational&quot;|relative_url}}&quot;&gt;Informational&lt;/a&gt; ({{site.pages|where:&quot;type&quot;,&quot;Informational&quot;|size}})&lt;/h3&gt;
&lt;p&gt;Describes a Ethereum design issue, or provides general guidelines or information to the Ethereum community, but does not propose a new feature. Informational EIPs do not necessarily represent Ethereum community consensus or a recommendation, so users and implementers are free to ignore Informational EIPs or follow their advice.&lt;/p&gt;
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/</guid>
      </item>
    
      <item>
        <title>Informational</title>
        <category>/</category>
        
        <description>{% assign eips=site.pages|where:&quot;type&quot;,&quot;Informational&quot; %}
{% include eiptable.html eips=eips %}
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/informational</link>
        <guid isPermaLink="true">https://eips.ethereum.org/informational</guid>
      </item>
    
      <item>
        <title>Interface</title>
        <category>/</category>
        
        <description>{% assign eips=site.pages|where:&quot;type&quot;,&quot;Standards Track&quot;|where:&quot;category&quot;,&quot;Interface&quot; %}
{% include eiptable.html eips=eips %}
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/interface</link>
        <guid isPermaLink="true">https://eips.ethereum.org/interface</guid>
      </item>
    
      <item>
        <title></title>
        <category>/</category>
        
        <description>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;rss version=&quot;2.0&quot; xmlns:atom=&quot;http://www.w3.org/2005/Atom&quot;&gt;
  &lt;channel&gt;
    &lt;title&gt;Ethereum EIPs - Last Call Review&lt;/title&gt;
    &lt;description&gt;All EIPs which are in the two-week &quot;last call&quot; status, please help review these and provide your feedback!&lt;/description&gt;
    &lt;link&gt;{{ site.url }}&lt;/link&gt;
    &lt;atom:link href=&quot;{{ site.url }}/rss/last-call.xml&quot; rel=&quot;self&quot; type=&quot;application/rss+xml&quot; /&gt;
    &lt;lastBuildDate&gt;{{ site.time | date_to_rfc822 }}&lt;/lastBuildDate&gt;
    {% assign eips = site.pages | sort: &apos;eip&apos; %}
    {% for eip in eips %}
      {% if eip.status == &quot;Last Call&quot; %}
      {% capture description %}
        &lt;p&gt;&lt;strong&gt;EIP #{{ eip.eip }} - {{eip.title }}&lt;/strong&gt; is in Last Call status. It is authored by {{ eip.author }} and was originally created {{ eip.created }}. It is in the {{ eip.category }} category of type {{ eip.type }}. Please review and note any changes that should block acceptance.&lt;/p&gt;
        {% if eip.discussions-to %}
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;{{ eip.discussions-to }}&quot;&gt;{{ eip.discussions-to }}&lt;/a&gt;&lt;/p&gt;
        {% endif %}
        &lt;hr /&gt;
        {{ eip.content }}
      {% endcapture %}
      &lt;item&gt;
        &lt;title&gt;{{ eip.title | xml_escape }}&lt;/title&gt;
        &lt;description&gt;{{ description | xml_escape }}&lt;/description&gt;
        &lt;pubDate&gt;{{ eip.created | date_to_rfc822 }}&lt;/pubDate&gt;
        &lt;link&gt;{{ site.url }}/{{ eip.url }}&lt;/link&gt;
        &lt;guid isPermaLink=&quot;true&quot;&gt;{{ site.url }}/{{ eip.url }}&lt;/guid&gt;
      &lt;/item&gt;
      {% endif %}
    {% endfor %}
  &lt;/channel&gt;
&lt;/rss&gt;
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/rss/last-call.xml</link>
        <guid isPermaLink="true">https://eips.ethereum.org/rss/last-call.xml</guid>
      </item>
    
      <item>
        <title>Meta</title>
        <category>/</category>
        
        <description>{% assign eips=site.pages|where:&quot;type&quot;,&quot;Meta&quot; %}
{% include eiptable.html eips=eips %}
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/meta</link>
        <guid isPermaLink="true">https://eips.ethereum.org/meta</guid>
      </item>
    
      <item>
        <title>Networking</title>
        <category>/</category>
        
        <description>{% assign eips=site.pages|where:&quot;type&quot;,&quot;Standards Track&quot;|where:&quot;category&quot;,&quot;Networking&quot; %}
{% include eiptable.html eips=eips %}
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/networking</link>
        <guid isPermaLink="true">https://eips.ethereum.org/networking</guid>
      </item>
    
      <item>
        <title></title>
        <category>/</category>
        
        <description>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;rss version=&quot;2.0&quot; xmlns:atom=&quot;http://www.w3.org/2005/Atom&quot;&gt;
  &lt;channel&gt;
    &lt;title&gt;Ethereum EIPs - Last Call Review&lt;/title&gt;
    &lt;description&gt;All EIPs which are in the two-week &quot;last call&quot; status, please help review these and provide your feedback!&lt;/description&gt;
    &lt;link&gt;{{ site.url }}&lt;/link&gt;
    &lt;atom:link href=&quot;{{ site.url }}/rss/last-call.xml&quot; rel=&quot;self&quot; type=&quot;application/rss+xml&quot; /&gt;
    &lt;lastBuildDate&gt;{{ site.time | date_to_rfc822 }}&lt;/lastBuildDate&gt;
    {% assign eips = site.pages | sort: &apos;eip&apos; %}
    {% for eip in eips %}
      {% unless eip.category == &quot;ERC&quot; %}
      {% if eip.status == &quot;Last Call&quot; %}
      {% capture description %}
        &lt;p&gt;&lt;strong&gt;EIP #{{ eip.eip }} - {{eip.title }}&lt;/strong&gt; is in Last Call status. It is authored by {{ eip.author }} and was originally created {{ eip.created }}. It is in the {{ eip.category }} category of type {{ eip.type }}. Please review and note any changes that should block acceptance.&lt;/p&gt;
        {% if eip.discussions-to %}
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;{{ eip.discussions-to }}&quot;&gt;{{ eip.discussions-to }}&lt;/a&gt;&lt;/p&gt;
        {% endif %}
        &lt;hr /&gt;
        {{ eip.content }}
      {% endcapture %}
      &lt;item&gt;
        &lt;title&gt;{{ eip.title | xml_escape }}&lt;/title&gt;
        &lt;description&gt;{{ description | xml_escape }}&lt;/description&gt;
        &lt;pubDate&gt;{{ eip.created | date_to_rfc822 }}&lt;/pubDate&gt;
        &lt;link&gt;{{ site.url }}/{{ eip.url }}&lt;/link&gt;
        &lt;guid isPermaLink=&quot;true&quot;&gt;{{ site.url }}/{{ eip.url }}&lt;/guid&gt;
      &lt;/item&gt;
      {% endif %}
      {% endunless %}
    {% endfor %}
  &lt;/channel&gt;
&lt;/rss&gt;
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/rss/nonerc-last-call.xml</link>
        <guid isPermaLink="true">https://eips.ethereum.org/rss/nonerc-last-call.xml</guid>
      </item>
    
      <item>
        <title></title>
        <category>/</category>
        
        <description>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;rss version=&quot;2.0&quot; xmlns:atom=&quot;http://www.w3.org/2005/Atom&quot;&gt;
  &lt;channel&gt;
    &lt;title&gt;Ethereum EIPs&lt;/title&gt;
    &lt;description&gt;All EIPs that are not ERCs&lt;/description&gt;
    &lt;link&gt;{{ site.url }}&lt;/link&gt;
    &lt;atom:link href=&quot;{{ site.url }}/rss/last-call.xml&quot; rel=&quot;self&quot; type=&quot;application/rss+xml&quot; /&gt;
    &lt;lastBuildDate&gt;{{ site.time | date_to_rfc822 }}&lt;/lastBuildDate&gt;
    {% assign eips = site.pages | sort: &apos;eip&apos; %}
    {% for eip in eips %}
      {% unless eip.category == &quot;ERC&quot; %}
      {% if eip.status == &quot;Last Call&quot; %}
      {% capture description %}
        &lt;p&gt;&lt;strong&gt;EIP #{{ eip.eip }} - {{eip.title }}&lt;/strong&gt; is in Last Call status. It is authored by {{ eip.author }} and was originally created {{ eip.created }}. It is in the {{ eip.category }} category of type {{ eip.type }}. Please review and note any changes that should block acceptance.&lt;/p&gt;
        {% if eip.discussions-to %}
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;{{ eip.discussions-to }}&quot;&gt;{{ eip.discussions-to }}&lt;/a&gt;&lt;/p&gt;
        {% endif %}
        &lt;hr /&gt;
        {{ eip.content }}
      {% endcapture %}
      &lt;item&gt;
        &lt;title&gt;{{ eip.title | xml_escape }}&lt;/title&gt;
        &lt;description&gt;{{ description | xml_escape }}&lt;/description&gt;
        &lt;pubDate&gt;{{ eip.created | date_to_rfc822 }}&lt;/pubDate&gt;
        &lt;link&gt;{{ site.url }}/{{ eip.url }}&lt;/link&gt;
        &lt;guid isPermaLink=&quot;true&quot;&gt;{{ site.url }}/{{ eip.url }}&lt;/guid&gt;
      &lt;/item&gt;
      {% endif %}
      {% endunless %}
    {% endfor %}
  &lt;/channel&gt;
&lt;/rss&gt;
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/rss/nonerc.xml</link>
        <guid isPermaLink="true">https://eips.ethereum.org/rss/nonerc.xml</guid>
      </item>
    
      <item>
        <title></title>
        <category>/</category>
        
        <description>$content-width: 1152px;

@import &apos;minima&apos;;

.site-header {
  .wrapper {
    display: flex;
    flex-direction: column;
    align-items: center;
  }
}

.page-content {
  a.anchor-link {
    width: 16px;
    height: 16px;
    display: inline-block;
    margin-left: -22px;
    &amp;:hover {
      background-image: url(&quot;data:image/svg+xml,%3Csvg xmlns=&apos;http://www.w3.org/2000/svg&apos; class=&apos;anchor-link-icon&apos; viewBox=&apos;0 0 16 16&apos; version=&apos;1.1&apos; width=&apos;16&apos; height=&apos;16&apos; aria-hidden=&apos;true&apos;%3E%3Cpath fill-rule=&apos;evenodd&apos; d=&apos;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&apos;%3E%3C/path%3E%3C/svg%3E&quot;);
    }
  }
}

.footer-col-wrapper {
  color: #111;
}

.table-borderless, .table-borderless * {
  border-style : hidden !important; // !important To override Jekyll styling
  background-color: rgba(0,0,0,0) !important;
}

table.preamble &gt; tbody &gt; tr &gt; :not(:first-child) {
  width: 100%;
}

table.preamble &gt; tbody &gt; tr &gt; :first-child {
  white-space: nowrap;
}

a, a:link {
  color: #726E97;
  text-decoration: none;
}

a:visited {
  color: #8E6680;
}

a:hover, a:active {
  color: #7F557D;
  text-decoration: underline;
}

.site-footer, .site-footer * {
  box-sizing: content-box !important; // !important To override bootstrap styling
}

.no-underline {
  text-decoration: none !important; // !important To override previous &lt;a&gt; styling
}

.badge:hover {
  filter: brightness(75%);
  transition: all 0.25s ease;
}

h1 {
  vertical-align: middle;
}

h1 a {
  height: 1em;
  display: inline-block;
  vertical-align: baseline;
}

.inline-svg {
  display: inline-block;
  vertical-align: bottom;
  fill: currentColor;
  width: 1.5ex;
  height: 100%;
  object-fit: cover;
}

@media print {

  header,
  footer {
    display: none;
  }
}

// This will make ALL tables scrollable
.page-content table {
  display: inline-block;
  width: auto !important;   /* shrink-to-fit its contents */
  max-width: 100%; /* never exceed the width of its container */
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

// Fix text overflow in EIP content
.home {
  max-width: 100%;
  overflow-x: hidden;

  // Target all content that could overflow
  p, li, td, div {
    word-wrap: break-word;
    overflow-wrap: break-word;
    word-break: break-word;
  }

  // Specifically handle URLs in links
  a {
    word-wrap: break-word;
    overflow-wrap: break-word;
    word-break: break-all;
    display: inline-block;
    max-width: 100%;
  }

  // Handle code blocks that might contain long strings
  pre {
    overflow-x: auto;
    max-width: 100%;
  }

  // Inline code should wrap
  code {
    word-wrap: break-word;
    overflow-wrap: break-word;
  }
}

// Specifically target lists (where references usually are)
.home ul, .home ol {
  max-width: 100%;
  padding-right: 20px; // Give some breathing room

  li {
    word-wrap: break-word;
    overflow-wrap: break-word;
    word-break: break-word;

    // Extra aggressive breaking for URLs
    a {
      word-break: break-all;
      hyphens: auto;
    }
  }
}

// makes an exception to code inside tables allowing them to expand the table&apos;s width since it has overflow scrolling
.page-content table code {
  white-space: nowrap;
  word-break: normal;
  overflow-wrap: normal;
}
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/css/style.css</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/css/style.css</guid>
      </item>
    
      <item>
        <title>Example EIP to add generic algorithm as an algorithmic type</title>
        <category>Standards Track/Core</category>
        
          <comments>fakeurl</comments>
        
        <description>## Abstract
This example EIP adds generic algorithm as an algorithmic type.

## Motivation
Generic algorithm has a good reason to be in Ethereum, therefore it should be.

## Specification

This EIP defines a new [EIP-7932](/EIPs/EIPS/eip-7932) algorithmic type with the following parameters.

```python
ALG_TYPE = 0xFA
SIZE = 128

def gas_cost(signing_data: Bytes) -&gt; Uint64:
    return Uint64(128 + len(signing_data))

def validate(signature: Bytes) -&gt; None | Error:
    # ...
    # Simple cryptography here
    # ...
    return None

def verify(signature: Bytes, signing_data: Bytes) -&gt; Bytes | Error:
    # ...
    # Complicated cryptography here
    # ...
    return public_key

def merge_detached_signature(detached_signature: bytes, public_key: bytes) -&gt; bytes:
    # ...
    # Either concatenation or a no-op here
    # ...
    return detached_signature + public_key
```

## Rationale
Generic algorithm has a good reason to be in Ethereum, therefore it should be.

## Backwards Compatibility
No backward compatibility issues found.

## Security Considerations
Needs discussion.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 12 Apr 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/assets/eip-7932/template-eip</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7932/template-eip</guid>
      </item>
    
      <item>
        <title></title>
        <category>/</category>
        
        <description>---
- deposit_data:
    pubkey: &quot;0xa99a76ed7796f7be22d5b7e85deeb7c5677e88e511e0b337618f8c4eb61349b4bf2d153f649f7b53359fe8b94a38e44c&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x97af5a5e14a033c35ec6489c585df8975026af431b2c5e9e3e6fd66089575bdffaf41c0a196d9b2ef822226c49d16214146f8a79b6ffa400109cd6c63c73afc7649d25533a3619547bc333b0cb3f303432fcd4951333b656d64d7b46a7ba764f&quot;
  deposit_data_root: &quot;0x7af7da533b0dc64b690cb0604f5a81e40ed83796dd14037ea3a55383b8f0976a&quot;
  eth1_data:
    deposit_root: &quot;0x253f73460b66ba0b490a8f17029566b03c0690a584e262acc2be97c969bc65a6&quot;
    deposit_count: &quot;1&quot;
    block_hash: &quot;0xab6f0411b911f0d66539663dc6b41ed58bb4870cd3ae879e25c7bee8cd6d6f22&quot;
  block_height: 2
  snapshot:
    finalized:
      - &quot;0x7af7da533b0dc64b690cb0604f5a81e40ed83796dd14037ea3a55383b8f0976a&quot;
    deposit_root: &quot;0x253f73460b66ba0b490a8f17029566b03c0690a584e262acc2be97c969bc65a6&quot;
    deposit_count: 1
    execution_block_hash: &quot;0xab6f0411b911f0d66539663dc6b41ed58bb4870cd3ae879e25c7bee8cd6d6f22&quot;
    execution_block_height: 2
- deposit_data:
    pubkey: &quot;0xb89bebc699769726a318c8e9971bd3171297c61aea4a6578a7a4f94b547dcba5bac16a89108b6b6a1fe3695d1a874a0b&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb24d74bd23b52c41567305b6aecdc73dd53aea59fa997c0d6205531ce70cc32282dbf9963dde89297522fdc2c541eb0909472145805953a2298aa56160784c23b3905ed0ec17c4775b61cecb922a0d0e5241521387fc38184afe735c2ce399ad&quot;
  deposit_data_root: &quot;0xb7dfec33825ba4dd8f6f8c2498c7202f07cbcf995a6de4b0abc71f1b1c46b2b2&quot;
  eth1_data:
    deposit_root: &quot;0x072080f22bf66504d6aa2b978c581e34637912ac191442af4f090dc5773d8936&quot;
    deposit_count: &quot;2&quot;
    block_hash: &quot;0x4e41a313cb3461e3154e76f87ec1bda35a48876529eaf3b99e335f43280c8d66&quot;
  block_height: 3
  snapshot:
    finalized:
      - &quot;0xb6a04fb079b0153e6e555fd79bb89187c9386b2230f4020bd81558feca702982&quot;
    deposit_root: &quot;0x072080f22bf66504d6aa2b978c581e34637912ac191442af4f090dc5773d8936&quot;
    deposit_count: 2
    execution_block_hash: &quot;0x4e41a313cb3461e3154e76f87ec1bda35a48876529eaf3b99e335f43280c8d66&quot;
    execution_block_height: 3
- deposit_data:
    pubkey: &quot;0xa3a32b0f8b4ddb83f1a0a853d81dd725dfe577d4f4c3db8ece52ce2b026eca84815c1a7e8e92a4de3d755733bf7e4a9b&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xae64ef1d479919aa5cbd146559f366877298757843112239646d75658dc89d066e401be202a3198ffb7261b393b7f8c01901e36e3bfa17f7ae2620d5e44750fd983e3b97d9c44248689f81d6a0508501f2dadfbbc1c7ddcec307a4d6da42c59f&quot;
  deposit_data_root: &quot;0x7b14766c0e7eddb146fc2a5bfd91e6d358d71995d2dc3c60d0c326607e39f7f2&quot;
  eth1_data:
    deposit_root: &quot;0x5e493befc0eb8dd0162eb48e5c3430882eefae51cb3fa757f11853b28387acdb&quot;
    deposit_count: &quot;3&quot;
    block_hash: &quot;0xb06534c2390ed7d7ec1d2630c6e8a340570a1a63df72c5cb81bb6ad65dce0692&quot;
  block_height: 4
  snapshot:
    finalized:
      - &quot;0xb6a04fb079b0153e6e555fd79bb89187c9386b2230f4020bd81558feca702982&quot;
      - &quot;0x7b14766c0e7eddb146fc2a5bfd91e6d358d71995d2dc3c60d0c326607e39f7f2&quot;
    deposit_root: &quot;0x5e493befc0eb8dd0162eb48e5c3430882eefae51cb3fa757f11853b28387acdb&quot;
    deposit_count: 3
    execution_block_hash: &quot;0xb06534c2390ed7d7ec1d2630c6e8a340570a1a63df72c5cb81bb6ad65dce0692&quot;
    execution_block_height: 4
- deposit_data:
    pubkey: &quot;0x88c141df77cd9d8d7a71a75c826c41a9c9f03c6ee1b180f3e7852f6a280099ded351b58d66e653af8e42816a4d8f532e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa0b938a2e4cd395ca6f24b410ac60af8af115f93d869839d76d8ef5aaeee52350636d72ef264c25b20442a55b24cc82d09a21d416a3e957bb0d35baf53efb18ac274e2e744644d42fa8f17beb7b2b6baae5342fa06eb394da73dd45b1643f3e2&quot;
  deposit_data_root: &quot;0x4760922c3a4ed6d321fc97355c4e8f7b7aa9e9771cb258095e52702c40170337&quot;
  eth1_data:
    deposit_root: &quot;0xe7d648159438c55bd12bbfea58ae16b9f9692d3fb05b0eac1729c67687dabe11&quot;
    deposit_count: &quot;4&quot;
    block_hash: &quot;0x63289eb1794f3ccd7536ce19023625e04777f84bd147c72b70eafcc6131b2f03&quot;
  block_height: 5
  snapshot:
    finalized:
      - &quot;0x33ac367f73d5318defd4d79d1b16c69046401691739f1aac0753a84e0ea28d22&quot;
    deposit_root: &quot;0xe7d648159438c55bd12bbfea58ae16b9f9692d3fb05b0eac1729c67687dabe11&quot;
    deposit_count: 4
    execution_block_hash: &quot;0x63289eb1794f3ccd7536ce19023625e04777f84bd147c72b70eafcc6131b2f03&quot;
    execution_block_height: 5
- deposit_data:
    pubkey: &quot;0x81283b7a20e1ca460ebd9bbd77005d557370cabb1f9a44f530c4c4c66230f675f8df8b4c2818851aa7d77a80ca5a4a5e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xaee3bec0f7786baae3a143131ea26d8ef62a8e17f7fade7355e42fb40a2717355d180c895f4de195523d3002d33ed60d10ba3b4285e8e712eb1612298051bdda70650966db509a104f374f45b16dfe06b21e6c385f0ff7d9c275b69dd193eef3&quot;
  deposit_data_root: &quot;0xfba947b41bd711feba3294ddaf1a6a87b888472f08a6c06d48afa702881409cd&quot;
  eth1_data:
    deposit_root: &quot;0x1004652bf7077a95c5a7ad7f2abd71565b750dcfbb1748d9489f3cae54c961fb&quot;
    deposit_count: &quot;5&quot;
    block_hash: &quot;0xc6aab9995fee61fde7d100a4f3aea2e8c9091501179943781dd50049ba57723d&quot;
  block_height: 6
  snapshot:
    finalized:
      - &quot;0x33ac367f73d5318defd4d79d1b16c69046401691739f1aac0753a84e0ea28d22&quot;
      - &quot;0xfba947b41bd711feba3294ddaf1a6a87b888472f08a6c06d48afa702881409cd&quot;
    deposit_root: &quot;0x1004652bf7077a95c5a7ad7f2abd71565b750dcfbb1748d9489f3cae54c961fb&quot;
    deposit_count: 5
    execution_block_hash: &quot;0xc6aab9995fee61fde7d100a4f3aea2e8c9091501179943781dd50049ba57723d&quot;
    execution_block_height: 6
- deposit_data:
    pubkey: &quot;0xab0bdda0f85f842f431beaccf1250bf1fd7ba51b4100fd64364b6401fda85bb0069b3e715b58819684e7fc0b10a72a34&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa28c8ad9d6cece980f888fe350f28ca3a4163f67f84c46053290e91134598fcba9fa7f4797c6cecdd435f44f65870e950a3b14c1d2ae162ee7958be3104e0489dd1a2f92482e30541abbd660e95d6476ad1373c19a64281b4057efdf36679758&quot;
  deposit_data_root: &quot;0x277ce49d97fb149180999892fe334e8d4701430aa5e76b7539e9593edc74209d&quot;
  eth1_data:
    deposit_root: &quot;0x82219812154553443de49dc85542aad6702f3b7ddb12e12be143a83028a5254a&quot;
    deposit_count: &quot;6&quot;
    block_hash: &quot;0x9ea53b7ec3ca5c5668b6b100e4463b93bd76d888ca846fbbb08d8db9596a3bf3&quot;
  block_height: 7
  snapshot:
    finalized:
      - &quot;0x33ac367f73d5318defd4d79d1b16c69046401691739f1aac0753a84e0ea28d22&quot;
      - &quot;0x9c8cf1935559cf32ca28a3677d41dea8cbc511ba16d99d7b5ab5610ee22c9eb2&quot;
    deposit_root: &quot;0x82219812154553443de49dc85542aad6702f3b7ddb12e12be143a83028a5254a&quot;
    deposit_count: 6
    execution_block_hash: &quot;0x9ea53b7ec3ca5c5668b6b100e4463b93bd76d888ca846fbbb08d8db9596a3bf3&quot;
    execution_block_height: 7
- deposit_data:
    pubkey: &quot;0x9977f1c8b731a8d5558146bfb86caea26434f3c5878b589bf280a42c9159e700e9df0e4086296c20b011d2e78c27d373&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x91d3bbe5ec01f47565f1b62e93b78fe084216a875154a6cb21cc521be15a548d3e28446c82fcf7214f484433abb2a0bb07c951cd3af2e2849e9e2456b4e53afbc122016e9f87a76269d307e02c495ef189a9bb48bf8a042a3a06676f82689000&quot;
  deposit_data_root: &quot;0x7d552eeb22d6a4fa593784ebc22fbd2c400d922dc806def9d8899c06b301125d&quot;
  eth1_data:
    deposit_root: &quot;0x2e079bcdc6905fcdf19041d355d17dd5a74f0749ac2cb178e81b648aafef3908&quot;
    deposit_count: &quot;7&quot;
    block_hash: &quot;0x8b5a2c44e11f46011c61e43cd768efbfc5610381caea1968397dc3ef50e83d9f&quot;
  block_height: 8
  snapshot:
    finalized:
      - &quot;0x33ac367f73d5318defd4d79d1b16c69046401691739f1aac0753a84e0ea28d22&quot;
      - &quot;0x9c8cf1935559cf32ca28a3677d41dea8cbc511ba16d99d7b5ab5610ee22c9eb2&quot;
      - &quot;0x7d552eeb22d6a4fa593784ebc22fbd2c400d922dc806def9d8899c06b301125d&quot;
    deposit_root: &quot;0x2e079bcdc6905fcdf19041d355d17dd5a74f0749ac2cb178e81b648aafef3908&quot;
    deposit_count: 7
    execution_block_hash: &quot;0x8b5a2c44e11f46011c61e43cd768efbfc5610381caea1968397dc3ef50e83d9f&quot;
    execution_block_height: 8
- deposit_data:
    pubkey: &quot;0xa8d4c7c27795a725961317ef5953a7032ed6d83739db8b0e8a72353d1b8b4439427f7efa2c89caa03cc9f28f8cbab8ac&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb3f76d7804668895192dd3fae3ccf101aa077da7c2678aefb8e92764e3bb0a32ef4592a62d8083aa0ca91f4cdefc745a0187fabd0f48fffc3213ccb9fca432a5c9c190d0d30f7c32f45e0ec4578eafad9a3f40e9a927e6cc1e0b5547cb54c0dc&quot;
  deposit_data_root: &quot;0xad041a1626deaccb4f11900595eaaab0f5b35d3ad16c3f1e5155181421348c11&quot;
  eth1_data:
    deposit_root: &quot;0xdd303f6f720a21ca45aebdaaf06a051ef6ad0b86b786b8a671e67652f5b32846&quot;
    deposit_count: &quot;8&quot;
    block_hash: &quot;0xe736c69176be57cfecb91f6e5c56fd5ed0b1537a9cac8229e30eb1b86abac543&quot;
  block_height: 9
  snapshot:
    finalized:
      - &quot;0x24b5bc14c80886b849880b846493fef7c12b8eb723461442d52129ffdf7af6a1&quot;
    deposit_root: &quot;0xdd303f6f720a21ca45aebdaaf06a051ef6ad0b86b786b8a671e67652f5b32846&quot;
    deposit_count: 8
    execution_block_hash: &quot;0xe736c69176be57cfecb91f6e5c56fd5ed0b1537a9cac8229e30eb1b86abac543&quot;
    execution_block_height: 9
- deposit_data:
    pubkey: &quot;0xa6d310dbbfab9a22450f59993f87a4ce5db6223f3b5f1f30d2c4ec718922d400e0b3c7741de8e59960f72411a0ee10a7&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8be64cfe0334b009be7c2d7c601e561976c201551d27b79747fc11fcbee6b22b9bd87552f8d492ec383e8bec11045b8f0c91ac28995f5c4b1c56b4953bb7fa0144d32f2464e8990342c907a42221b2a5ff69b8301259fa87e0bcb5f4bdaa16de&quot;
  deposit_data_root: &quot;0x9fb936887340fdde0663bc9811bc80c8939d4f1fda005a3d8d4d1e5803c65d43&quot;
  eth1_data:
    deposit_root: &quot;0x03d7883c2e63951bb4df714a7a0ceb389441999562dfa1fa98818b5791cf4c16&quot;
    deposit_count: &quot;9&quot;
    block_hash: &quot;0x597ffaa8cce4435d23a8f9dc28500422ce3d0e68fd5be5989eb032fb276b8293&quot;
  block_height: 10
  snapshot:
    finalized:
      - &quot;0x24b5bc14c80886b849880b846493fef7c12b8eb723461442d52129ffdf7af6a1&quot;
      - &quot;0x9fb936887340fdde0663bc9811bc80c8939d4f1fda005a3d8d4d1e5803c65d43&quot;
    deposit_root: &quot;0x03d7883c2e63951bb4df714a7a0ceb389441999562dfa1fa98818b5791cf4c16&quot;
    deposit_count: 9
    execution_block_hash: &quot;0x597ffaa8cce4435d23a8f9dc28500422ce3d0e68fd5be5989eb032fb276b8293&quot;
    execution_block_height: 10
- deposit_data:
    pubkey: &quot;0x9893413c00283a3f9ed9fd9845dda1cea38228d22567f9541dccc357e54a2d6a6e204103c92564cbc05f4905ac7c493a&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x938c03a718bf6e456ec84d88a118939dec03dbdce3697b8ef0f52208835d3221b4a103997264e064b13ecb05bb4b8ef910f4f3446a3b1524549f53ed9e744c41c3bf0350c4bc9b29f2b223ab1a91abe1a153d80bda8cee1b4f2f8fe3e6409ff9&quot;
  deposit_data_root: &quot;0xb6855e0bdbf1972d7a4571e6259cd589fe1baa3fa7ef569b9554c8e293b553dd&quot;
  eth1_data:
    deposit_root: &quot;0x2bba0e22d698d0e3cfa8374379f6c1a031a2aa0554cff8fa752936bc2ab8cdfd&quot;
    deposit_count: &quot;10&quot;
    block_hash: &quot;0x2e783a4e0b676caf552408ed8faf35f9e3e68dd2d82f71538ecf5c067dab6107&quot;
  block_height: 11
  snapshot:
    finalized:
      - &quot;0x24b5bc14c80886b849880b846493fef7c12b8eb723461442d52129ffdf7af6a1&quot;
      - &quot;0x30a5058eb6db4b120d6c07b995376d1e1f013ccd24d52b1327d7528d2e50c970&quot;
    deposit_root: &quot;0x2bba0e22d698d0e3cfa8374379f6c1a031a2aa0554cff8fa752936bc2ab8cdfd&quot;
    deposit_count: 10
    execution_block_hash: &quot;0x2e783a4e0b676caf552408ed8faf35f9e3e68dd2d82f71538ecf5c067dab6107&quot;
    execution_block_height: 11
- deposit_data:
    pubkey: &quot;0x876dd4705157eb66dc71bc2e07fb151ea53e1a62a0bb980a7ce72d15f58944a8a3752d754f52f4a60dbfc7b18169f268&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb7bffc1c83d9294af5df83f9889bd9c8d60f020b87d2a2a4235e8b0385b11b42a61432817210f7ca05cdfa074989fb57181a5a63b899402822c9f5dd33d1f199f441886cd6b753ff9fa87b72146f05c51b20d39c31a666dfdd00ea961accf1a3&quot;
  deposit_data_root: &quot;0xc27c2db393fa0a74669bb5d2148ead286bec2fffc8c993e24a1c633221b0a91a&quot;
  eth1_data:
    deposit_root: &quot;0x697b75797e3f93acb334632bcd4af10979b12e10fa3f1b2dd7813bc31963f2aa&quot;
    deposit_count: &quot;11&quot;
    block_hash: &quot;0x3b9b8b3100433523f9b04ad853d9772795403b9610f58c71746f18280e7f1c97&quot;
  block_height: 12
  snapshot:
    finalized:
      - &quot;0x24b5bc14c80886b849880b846493fef7c12b8eb723461442d52129ffdf7af6a1&quot;
      - &quot;0x30a5058eb6db4b120d6c07b995376d1e1f013ccd24d52b1327d7528d2e50c970&quot;
      - &quot;0xc27c2db393fa0a74669bb5d2148ead286bec2fffc8c993e24a1c633221b0a91a&quot;
    deposit_root: &quot;0x697b75797e3f93acb334632bcd4af10979b12e10fa3f1b2dd7813bc31963f2aa&quot;
    deposit_count: 11
    execution_block_hash: &quot;0x3b9b8b3100433523f9b04ad853d9772795403b9610f58c71746f18280e7f1c97&quot;
    execution_block_height: 12
- deposit_data:
    pubkey: &quot;0xaec922bd7a9b7b1dc21993133b586b0c3041c1e2e04b513e862227b9d7aecaf9444222f7e78282a449622ffc6278915d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8f2128ebe0cfc2ca5b6df5071b2960717a0b068dc4694d697af2589307ff0c4502e9faa5f7c5093ab8c214bce4f820db12336ea8853704fa050442ed6b513d68c6c18a33734d558658662c39174bb69be31b78d87eea4602292cda97fc2651ea&quot;
  deposit_data_root: &quot;0x9ce8e449715c5c2b4f0d7da4de574f18ce429f44c4b1f648e23b8ece0c24bcc8&quot;
  eth1_data:
    deposit_root: &quot;0xa990ca5f9f41f0b305051de710d8b2fe78f63e369f408977a2cf19dcee718b60&quot;
    deposit_count: &quot;12&quot;
    block_hash: &quot;0xcec38f21aef8ce25842b3db7e9f5cb708a1aa9b3bad17c04f31ef963657f81b5&quot;
  block_height: 13
  snapshot:
    finalized:
      - &quot;0x24b5bc14c80886b849880b846493fef7c12b8eb723461442d52129ffdf7af6a1&quot;
      - &quot;0x660335330368071f958f6fa763caa16650c7e3051733f84ce6bfa410f2052bf9&quot;
    deposit_root: &quot;0xa990ca5f9f41f0b305051de710d8b2fe78f63e369f408977a2cf19dcee718b60&quot;
    deposit_count: 12
    execution_block_hash: &quot;0xcec38f21aef8ce25842b3db7e9f5cb708a1aa9b3bad17c04f31ef963657f81b5&quot;
    execution_block_height: 13
- deposit_data:
    pubkey: &quot;0x9314c6de0386635e2799af798884c2ea09c63b9f079e572acc00b06a7faccce501ea4dfc0b1a23b8603680a5e3481327&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xac36c7e15cd45f9f7c0e2672286513e03de301aff537460351bc1ccfa777139bfce29c6f441df8d7cbee4fdaea159cda1309a563ef28e9630ce1d022f8378046978fbb55e2f67dc708aa923e86bbfbd2487bf9f7b537a23ee1fd6c30043b6270&quot;
  deposit_data_root: &quot;0x079946bfcb7488e966144acd500b247b685896812cdb13c138742dfaad33ce88&quot;
  eth1_data:
    deposit_root: &quot;0x96906b941533a885ac57be9f765f90b0c880174286913c515552167b0154a116&quot;
    deposit_count: &quot;13&quot;
    block_hash: &quot;0xe9ebca52836019409c578724469684df7ddbf2a3f1a106c66e3af1dae3b24ad8&quot;
  block_height: 14
  snapshot:
    finalized:
      - &quot;0x24b5bc14c80886b849880b846493fef7c12b8eb723461442d52129ffdf7af6a1&quot;
      - &quot;0x660335330368071f958f6fa763caa16650c7e3051733f84ce6bfa410f2052bf9&quot;
      - &quot;0x079946bfcb7488e966144acd500b247b685896812cdb13c138742dfaad33ce88&quot;
    deposit_root: &quot;0x96906b941533a885ac57be9f765f90b0c880174286913c515552167b0154a116&quot;
    deposit_count: 13
    execution_block_hash: &quot;0xe9ebca52836019409c578724469684df7ddbf2a3f1a106c66e3af1dae3b24ad8&quot;
    execution_block_height: 14
- deposit_data:
    pubkey: &quot;0x903e2989e7442ee0a8958d020507a8bd985d3974f5e8273093be00db3935f0500e141b252bd09e3728892c7a8443863c&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x86c8283b6c4c8c6f01ff005c62d0199583c99a81ca9207f3a539b63f1732a06eae9e16e601ebf7ac0ac6cb0c0d0f147d0e10c8a3f7877814ac6291ee8fe4c83591dc2a82680bcce53c09b0c41b71fa84be2f799257c020ae2c41c801953345db&quot;
  deposit_data_root: &quot;0x8fe2405c8ed0d927f7c71d710879a4037b27409d0939074d040e88153245c1ad&quot;
  eth1_data:
    deposit_root: &quot;0x5d9c3452b70ec17728332003cf3d2e11d4f16151aef226ed799a837f4453e7a9&quot;
    deposit_count: &quot;14&quot;
    block_hash: &quot;0xa868c9bc5ac184f30ac39df5e5a5fdf0778575aad44b10e835968170c2183b7d&quot;
  block_height: 15
  snapshot:
    finalized:
      - &quot;0x24b5bc14c80886b849880b846493fef7c12b8eb723461442d52129ffdf7af6a1&quot;
      - &quot;0x660335330368071f958f6fa763caa16650c7e3051733f84ce6bfa410f2052bf9&quot;
      - &quot;0xb9d45d47c8373b0a9a2fe9c21bca36bf2a5fa9609c22e7699107a7d4fe8d39f1&quot;
    deposit_root: &quot;0x5d9c3452b70ec17728332003cf3d2e11d4f16151aef226ed799a837f4453e7a9&quot;
    deposit_count: 14
    execution_block_hash: &quot;0xa868c9bc5ac184f30ac39df5e5a5fdf0778575aad44b10e835968170c2183b7d&quot;
    execution_block_height: 15
- deposit_data:
    pubkey: &quot;0x84398f539a64cbe01cfcd8c485ea51cd6657b94df93ee9b5dc61e1f18f69da6ca9d4dba63c956a81c68d5d4d4277a60f&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8268676a3c7170a291d346859266a729b205077f7bd6c3b73d32ef63e420422aff7137abd008b22ae77db39803ff1c2a16990fd382d9ac7ea535daf73510fb9ad7b11c678bbec586a01ab0072ec47abc5adb498e1e8bf7bd957184b2c73d2a95&quot;
  deposit_data_root: &quot;0x22d0b48ba191226ea3c0a8eb8f05dcc26a66678bd7b2e8f90e43b0a6afd57ab3&quot;
  eth1_data:
    deposit_root: &quot;0x17b149f19cec86287f4b6ff785698cc55366b29e5a3042df3548a6cc4b9256f8&quot;
    deposit_count: &quot;15&quot;
    block_hash: &quot;0xda2b6d573ca1a9f707971321b1a1c65ab93916f4b984d621f4368302e94ab102&quot;
  block_height: 16
  snapshot:
    finalized:
      - &quot;0x24b5bc14c80886b849880b846493fef7c12b8eb723461442d52129ffdf7af6a1&quot;
      - &quot;0x660335330368071f958f6fa763caa16650c7e3051733f84ce6bfa410f2052bf9&quot;
      - &quot;0xb9d45d47c8373b0a9a2fe9c21bca36bf2a5fa9609c22e7699107a7d4fe8d39f1&quot;
      - &quot;0x22d0b48ba191226ea3c0a8eb8f05dcc26a66678bd7b2e8f90e43b0a6afd57ab3&quot;
    deposit_root: &quot;0x17b149f19cec86287f4b6ff785698cc55366b29e5a3042df3548a6cc4b9256f8&quot;
    deposit_count: 15
    execution_block_hash: &quot;0xda2b6d573ca1a9f707971321b1a1c65ab93916f4b984d621f4368302e94ab102&quot;
    execution_block_height: 16
- deposit_data:
    pubkey: &quot;0x872c61b4a7f8510ec809e5b023f5fdda2105d024c470ddbbeca4bc74e8280af0d178d749853e8f6a841083ac1b4db98f&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9939cc7ccebfe4172d92680c74859e3f1d8de2e2a9bb494e9bec8306a5fb492bdab09f136f8f174d0bd5680991dc61970b5b7651ec3ffebe439b03df13e9259760bcfb1896795645796362856cd241b077d4d5e578bed13f7833cdee6135a7ce&quot;
  deposit_data_root: &quot;0x72d791ecc2dc99d82f29f4cebc5df93a493091b4cd6d6b92b31fc92cac128bad&quot;
  eth1_data:
    deposit_root: &quot;0x1eceb67da690c4ae9c9664c51630c2094e3dc517c7473f2659babbe496366483&quot;
    deposit_count: &quot;16&quot;
    block_hash: &quot;0x0698420ee3e7ac4f8c314c740c2df8ddd50e3de679bd57b55e62c53b1d00bbe6&quot;
  block_height: 17
  snapshot:
    finalized:
      - &quot;0x5f652df37d6370cd7a4267959f0b885e201b293a69f57a8769c92d797050967e&quot;
    deposit_root: &quot;0x1eceb67da690c4ae9c9664c51630c2094e3dc517c7473f2659babbe496366483&quot;
    deposit_count: 16
    execution_block_hash: &quot;0x0698420ee3e7ac4f8c314c740c2df8ddd50e3de679bd57b55e62c53b1d00bbe6&quot;
    execution_block_height: 17
- deposit_data:
    pubkey: &quot;0x8f467e5723deac7659e1ca273e28410cbaa6d495ab66ae77014f4cd21c64b6b5ab9987c9b5537fe0279bd063fe609be7&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x95c61f4b48792bf54197d2f5db308ae3315901f4419b5a1823784fc85190adf17824aa80d884b1813a1ca3792d55612d04e28951014e7e573b0baf51fe7c956c8c6e37e25d353187a1c8633c37cb1d91bf0a90544c26fe5bf562dc99f1a52bb2&quot;
  deposit_data_root: &quot;0x8df60288a3a0e60180b6026dcf71a62c5f88ae0714b433026155c49ab9f9a2b3&quot;
  eth1_data:
    deposit_root: &quot;0x6e612e99981156dbcf528144f5a661a3fec2092d32cf8276174a9f112d6f2694&quot;
    deposit_count: &quot;17&quot;
    block_hash: &quot;0x78f5fafef1f3dbc6ccde8362063b0ee74528976ef4f57407dbd3606fc87fa592&quot;
  block_height: 18
  snapshot:
    finalized:
      - &quot;0x5f652df37d6370cd7a4267959f0b885e201b293a69f57a8769c92d797050967e&quot;
      - &quot;0x8df60288a3a0e60180b6026dcf71a62c5f88ae0714b433026155c49ab9f9a2b3&quot;
    deposit_root: &quot;0x6e612e99981156dbcf528144f5a661a3fec2092d32cf8276174a9f112d6f2694&quot;
    deposit_count: 17
    execution_block_hash: &quot;0x78f5fafef1f3dbc6ccde8362063b0ee74528976ef4f57407dbd3606fc87fa592&quot;
    execution_block_height: 18
- deposit_data:
    pubkey: &quot;0x8dde8306920812b32def3b663f7c540b49180345d3bcb8d3770790b7dc80030ebc06497feebd1bcf017d918f00bfa88f&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa055036c86894b46ef0ef8e734b0a93cbeae393db9de264e57f03766ac1126ce21371a49dbb3d19c1da17e4f1c80eb1103e48c4ad44b778991ade181955b39928ca274a0625fe21bdb1ac79d8046a37a6066afc2e1fad405271efb80c4cec998&quot;
  deposit_data_root: &quot;0x822c94e13fb37ecca034fabe44e24e06fd5e14685ffc98fc01dfb5d1b2ae8634&quot;
  eth1_data:
    deposit_root: &quot;0x4da8765913d4a494b45f34c4a4cc928e2be2e7e9c41dc13d69f5c0581f5bc628&quot;
    deposit_count: &quot;18&quot;
    block_hash: &quot;0xfdf087208f15f7cfbd0e777ee67d5a1224210c7095ec5a93201d1a042db10d27&quot;
  block_height: 19
  snapshot:
    finalized:
      - &quot;0x5f652df37d6370cd7a4267959f0b885e201b293a69f57a8769c92d797050967e&quot;
      - &quot;0xd834f7120ed8a3f465b6484186992815aef250168d7c624b508c177ecbddb102&quot;
    deposit_root: &quot;0x4da8765913d4a494b45f34c4a4cc928e2be2e7e9c41dc13d69f5c0581f5bc628&quot;
    deposit_count: 18
    execution_block_hash: &quot;0xfdf087208f15f7cfbd0e777ee67d5a1224210c7095ec5a93201d1a042db10d27&quot;
    execution_block_height: 19
- deposit_data:
    pubkey: &quot;0xab8d3a9bcc160e518fac0756d3e192c74789588ed4a2b1debf0c78f78479ca8edb05b12ce21103076df6af4eb8756ff9&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x923fcfc77cf65ae29aa7771f9152140af8dfdf7301889aa52d5f1221b3ef8e7186b3dce969db0b6824308c657978952f01a4b2193d385fdd42ed107332b6714e4e10f70ad07919aadbf51d4f50ce0da40317bf8bc5d55b7d2e1bd8a77ff24a67&quot;
  deposit_data_root: &quot;0x89be43c5944c2e25e15e930dd1c4572501359f2ae617eb829e96b83890517ae9&quot;
  eth1_data:
    deposit_root: &quot;0x2da633fb33c672f3348e994d49a8637935c8bf5db9c8e4524a19625f5c9bdb0f&quot;
    deposit_count: &quot;19&quot;
    block_hash: &quot;0x9b0e02e7dc57fb2c4178c55aa82cddd698a9eb91690a4ce1ce3508a3cb2589c0&quot;
  block_height: 20
  snapshot:
    finalized:
      - &quot;0x5f652df37d6370cd7a4267959f0b885e201b293a69f57a8769c92d797050967e&quot;
      - &quot;0xd834f7120ed8a3f465b6484186992815aef250168d7c624b508c177ecbddb102&quot;
      - &quot;0x89be43c5944c2e25e15e930dd1c4572501359f2ae617eb829e96b83890517ae9&quot;
    deposit_root: &quot;0x2da633fb33c672f3348e994d49a8637935c8bf5db9c8e4524a19625f5c9bdb0f&quot;
    deposit_count: 19
    execution_block_hash: &quot;0x9b0e02e7dc57fb2c4178c55aa82cddd698a9eb91690a4ce1ce3508a3cb2589c0&quot;
    execution_block_height: 20
- deposit_data:
    pubkey: &quot;0x8d5d3672a233db513df7ad1e8beafeae99a9f0199ed4d949bbedbb6f394030c0416bd99b910e14f73c65b6a11fe6b62e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8c0b2b26e5d9672cc95c0fa6d23ca6aa02a7163054a5492b95d5f4470083e4c2aca64e5d38972e13dceeea88996a1fca196e7e540fc05c96c195b3f27b421b38efa3c24f4fe6905c40eab900552531063f00b45718660179d36fa1daeb7e08e0&quot;
  deposit_data_root: &quot;0x8c75a76c9c9892a587d7b0bc8c224d8a6e49d0513ee7f65f59b668d9108deca3&quot;
  eth1_data:
    deposit_root: &quot;0x6dee02182764197fb5be9df0535dbe15ca556b26e628d5aba8b080de4b92049b&quot;
    deposit_count: &quot;20&quot;
    block_hash: &quot;0xf32ee96bf62b97336de0e8846fc0d5ad58cf5b5cf899790859545d40644d00c4&quot;
  block_height: 21
  snapshot:
    finalized:
      - &quot;0x5f652df37d6370cd7a4267959f0b885e201b293a69f57a8769c92d797050967e&quot;
      - &quot;0x0e15a983c4aaa8cb3676b532c0dae58a86e1a329e2be55baa4e9bf8728bf7698&quot;
    deposit_root: &quot;0x6dee02182764197fb5be9df0535dbe15ca556b26e628d5aba8b080de4b92049b&quot;
    deposit_count: 20
    execution_block_hash: &quot;0xf32ee96bf62b97336de0e8846fc0d5ad58cf5b5cf899790859545d40644d00c4&quot;
    execution_block_height: 21
- deposit_data:
    pubkey: &quot;0xa1c76af1545d7901214bb6be06be5d9e458f8e989c19373a920f0018327c83982f6a2ac138260b8def732cb366411ddc&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9072a23d7159f70dcf6cda33337ded68b59d1caaa9b94b708d06736a8bdf9d414d126ccd9c53aa8baf5c3aa22163a1b013874c29db01d164c3a3632dc7ce73fdbd5d43ca64646418f4412f6d462122c115468faa4371836fcd43150daa696e1e&quot;
  deposit_data_root: &quot;0x428fe5a8d16366f972a52daa8e2eba40bedf30360ecfa2d81efc2d68ee21c80d&quot;
  eth1_data:
    deposit_root: &quot;0x46ffc1bb9ee82fcf871ecdd525f8db26a0616c46644a150ef293d3a969af249f&quot;
    deposit_count: &quot;21&quot;
    block_hash: &quot;0x551285bb963663cc97445ab83591ca6e33d02ae26092c1897804438be2afa704&quot;
  block_height: 22
  snapshot:
    finalized:
      - &quot;0x5f652df37d6370cd7a4267959f0b885e201b293a69f57a8769c92d797050967e&quot;
      - &quot;0x0e15a983c4aaa8cb3676b532c0dae58a86e1a329e2be55baa4e9bf8728bf7698&quot;
      - &quot;0x428fe5a8d16366f972a52daa8e2eba40bedf30360ecfa2d81efc2d68ee21c80d&quot;
    deposit_root: &quot;0x46ffc1bb9ee82fcf871ecdd525f8db26a0616c46644a150ef293d3a969af249f&quot;
    deposit_count: 21
    execution_block_hash: &quot;0x551285bb963663cc97445ab83591ca6e33d02ae26092c1897804438be2afa704&quot;
    execution_block_height: 22
- deposit_data:
    pubkey: &quot;0x8dd74e1bb5228fc1fca274fda02b971c1003a4f409bbdfbcfec6426bf2f52addcbbebccdbf45eee6ae11eb5b5ee7244d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8bc79ba412ff7d26f58dcfa5b7f6c2b05570e1ac9c3671a9e2f22f11615b9fa5658a4532a35f5c42b5ffa136f796e04218d279e01990d6591daac0b7cb1481b5c7efe1264f39919dcf56e4b155ba162b7096ba9dd44805868793ab8440eac0a7&quot;
  deposit_data_root: &quot;0x2862ae99f44e6fdb1d9ea652c10832e10334563e8873cc92af000703ee501849&quot;
  eth1_data:
    deposit_root: &quot;0xbb0311909b43eb5cc96107607d54315d84d24a552a27569a0992384417314e30&quot;
    deposit_count: &quot;22&quot;
    block_hash: &quot;0xd903cd669f26d87ed4d754ad13d3e8426505180dd67d9c3b44c3341fd2d33d8c&quot;
  block_height: 23
  snapshot:
    finalized:
      - &quot;0x5f652df37d6370cd7a4267959f0b885e201b293a69f57a8769c92d797050967e&quot;
      - &quot;0x0e15a983c4aaa8cb3676b532c0dae58a86e1a329e2be55baa4e9bf8728bf7698&quot;
      - &quot;0xdf659f3a3a39eda83bcbebb3a7ce225bda424b28d47ad4fd78a187e94150474e&quot;
    deposit_root: &quot;0xbb0311909b43eb5cc96107607d54315d84d24a552a27569a0992384417314e30&quot;
    deposit_count: 22
    execution_block_hash: &quot;0xd903cd669f26d87ed4d754ad13d3e8426505180dd67d9c3b44c3341fd2d33d8c&quot;
    execution_block_height: 23
- deposit_data:
    pubkey: &quot;0x954eb88ed1207f891dc3c28fa6cfdf8f53bf0ed3d838f3476c0900a61314d22d4f0a300da3cd010444dd5183e35a593c&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x942f0eacead041b7fb92f1917f46e3a884beded26a90aed33b571ea20a88a2b6c2b3bfb39bb961e8d5a9003ae9f95d0e00f5c405ede3135de09749dae540fbd5bc3c89ff1c3494676298caca4a29277aa3f3633fa827fa3b32f3ce9fb71b2486&quot;
  deposit_data_root: &quot;0x171d4e93ba95da64b2a59446bcba72a5af8cb33cd002d8db1774111b851b4c2f&quot;
  eth1_data:
    deposit_root: &quot;0xe1367c132b2c346fb43358ed1d2c392c535070c065450c8cc45c387ba99eeb6a&quot;
    deposit_count: &quot;23&quot;
    block_hash: &quot;0x457a64cc460ff02516925473033c4f5a16a0be8c98f5db1c6cfd4aa9001ebaa9&quot;
  block_height: 24
  snapshot:
    finalized:
      - &quot;0x5f652df37d6370cd7a4267959f0b885e201b293a69f57a8769c92d797050967e&quot;
      - &quot;0x0e15a983c4aaa8cb3676b532c0dae58a86e1a329e2be55baa4e9bf8728bf7698&quot;
      - &quot;0xdf659f3a3a39eda83bcbebb3a7ce225bda424b28d47ad4fd78a187e94150474e&quot;
      - &quot;0x171d4e93ba95da64b2a59446bcba72a5af8cb33cd002d8db1774111b851b4c2f&quot;
    deposit_root: &quot;0xe1367c132b2c346fb43358ed1d2c392c535070c065450c8cc45c387ba99eeb6a&quot;
    deposit_count: 23
    execution_block_hash: &quot;0x457a64cc460ff02516925473033c4f5a16a0be8c98f5db1c6cfd4aa9001ebaa9&quot;
    execution_block_height: 24
- deposit_data:
    pubkey: &quot;0xaf344fce60dbd5fb850070e6e76a065e1a32485245ef4f413135a86ae703da88407c5d01c71f6bb06a151ff96cca7191&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x968b1f4d64fbec9c8b5599eb9f3ebf64ea9f5cda3cde3c463cd714022efad0653563a2f24581f2f6c019567abd4801400b79d097b925d363aed6e995f9d1869dbd4ae52ea3542a6a2258094867c767c7e9951e80df872dce35904b6d8eb13c49&quot;
  deposit_data_root: &quot;0x4f24e0bcfcbf2a0e0828b5b63fed6f175c939c6332d622d5959b683ff5a986ba&quot;
  eth1_data:
    deposit_root: &quot;0x75580add56b9161b8747e19faba42030d70994396de5ab95b6b86f61262d86ae&quot;
    deposit_count: &quot;24&quot;
    block_hash: &quot;0x8d44620a0a0ff3d00477c7735e28cfb742a10619664a017f8800ea13dcdcef9a&quot;
  block_height: 25
  snapshot:
    finalized:
      - &quot;0x5f652df37d6370cd7a4267959f0b885e201b293a69f57a8769c92d797050967e&quot;
      - &quot;0xf411283523e35f406ed67667dab5e352fc257052ddac82c3bb78c1cf157884aa&quot;
    deposit_root: &quot;0x75580add56b9161b8747e19faba42030d70994396de5ab95b6b86f61262d86ae&quot;
    deposit_count: 24
    execution_block_hash: &quot;0x8d44620a0a0ff3d00477c7735e28cfb742a10619664a017f8800ea13dcdcef9a&quot;
    execution_block_height: 25
- deposit_data:
    pubkey: &quot;0xae241af60691fda1cf8ca44d49573c55818c53b6141800cca2d488b9a3fba71c0f869179fff50c084657831fbeb42bf4&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa439766948de7ba95f03ae54671d0c71bf34538405554f9a6b52e4b3672ab8f8b484841844652fa2573a3473fbd6d5d2046f6776ae161384da704df0b0dd8d800b4b0179e88ce193f84bf022fb81490bb4697f331eebdbfcab1c09b76c5f798a&quot;
  deposit_data_root: &quot;0x98c8fddae908c9740b1e57526c08791223bf0fa2d03cee0855a62ba3af995483&quot;
  eth1_data:
    deposit_root: &quot;0x17ab1dfcb9c9438066726df5d532f91d74290292887618fdb5392f7a4da88d3f&quot;
    deposit_count: &quot;25&quot;
    block_hash: &quot;0x0d92259ff68bc51a4dad01a711927f941fcde206c05ef405d37f44e602ca0513&quot;
  block_height: 26
  snapshot:
    finalized:
      - &quot;0x5f652df37d6370cd7a4267959f0b885e201b293a69f57a8769c92d797050967e&quot;
      - &quot;0xf411283523e35f406ed67667dab5e352fc257052ddac82c3bb78c1cf157884aa&quot;
      - &quot;0x98c8fddae908c9740b1e57526c08791223bf0fa2d03cee0855a62ba3af995483&quot;
    deposit_root: &quot;0x17ab1dfcb9c9438066726df5d532f91d74290292887618fdb5392f7a4da88d3f&quot;
    deposit_count: 25
    execution_block_hash: &quot;0x0d92259ff68bc51a4dad01a711927f941fcde206c05ef405d37f44e602ca0513&quot;
    execution_block_height: 26
- deposit_data:
    pubkey: &quot;0x96746aaba64dc87835ba709332f4d5d7837ada092b439c49d251aecf92aab5dc132e917bf6f59799bc093f976a7bc021&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xaa147ee89efcadbe1c8ae5dd2309b9153966d57d0c69b47f33f1a2a0bfa47821956ea5b20ffdfd77602509e7c92b4cf70ac7e16593c9325e41869af6e6844a09f20273001cbd00f413690c913b8c61390e40181c3c78d0605db457b17165535b&quot;
  deposit_data_root: &quot;0xc220f1e62f775aa20f6783a08ede02364bb656aa3aea8a53b566cc3f5780ce20&quot;
  eth1_data:
    deposit_root: &quot;0x28533734876a9a4da9bc4518a561f124e9c09a3c52e727707cbbb2bae1a8afd4&quot;
    deposit_count: &quot;26&quot;
    block_hash: &quot;0xc11cc9313a9f6f28d1f4b6f06a0f4871efcc548df79c90c77b10b6bd6af073b7&quot;
  block_height: 27
  snapshot:
    finalized:
      - &quot;0x5f652df37d6370cd7a4267959f0b885e201b293a69f57a8769c92d797050967e&quot;
      - &quot;0xf411283523e35f406ed67667dab5e352fc257052ddac82c3bb78c1cf157884aa&quot;
      - &quot;0x16bdf648ff50bb5f33cab70a7cff595ba63caaff4fcb670610e802cc344dffc2&quot;
    deposit_root: &quot;0x28533734876a9a4da9bc4518a561f124e9c09a3c52e727707cbbb2bae1a8afd4&quot;
    deposit_count: 26
    execution_block_hash: &quot;0xc11cc9313a9f6f28d1f4b6f06a0f4871efcc548df79c90c77b10b6bd6af073b7&quot;
    execution_block_height: 27
- deposit_data:
    pubkey: &quot;0xb9d1d914df3d4565465c3fd52b5b96e637f9980570cabf5b5d4aadf5a329ac36ad672819d997e735f5052e28b1f0c104&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb2a21801a7ddd00d4b1df1c571b74b95b7cb92d484712349c612438183e4d486113f51e356343be7835a0f6c88e7de5a0978cb3815b3ca044fe741c25b02eade6fb36500b2264305b5954cc4f5ad451c6f43d552405def57a07411a32016097b&quot;
  deposit_data_root: &quot;0x6db78e60584351fc046ce86f6f56c1ec42ecc5526677d4a1b3bb720280277f38&quot;
  eth1_data:
    deposit_root: &quot;0xf18ab78c3cfee43fc0c09c7c1101d655b86b30809149134e0fd6603247b48650&quot;
    deposit_count: &quot;27&quot;
    block_hash: &quot;0x6381e5f3e249642bb56562bb2cd645d77578491d8b22b4de49976c606f10b275&quot;
  block_height: 28
  snapshot:
    finalized:
      - &quot;0x5f652df37d6370cd7a4267959f0b885e201b293a69f57a8769c92d797050967e&quot;
      - &quot;0xf411283523e35f406ed67667dab5e352fc257052ddac82c3bb78c1cf157884aa&quot;
      - &quot;0x16bdf648ff50bb5f33cab70a7cff595ba63caaff4fcb670610e802cc344dffc2&quot;
      - &quot;0x6db78e60584351fc046ce86f6f56c1ec42ecc5526677d4a1b3bb720280277f38&quot;
    deposit_root: &quot;0xf18ab78c3cfee43fc0c09c7c1101d655b86b30809149134e0fd6603247b48650&quot;
    deposit_count: 27
    execution_block_hash: &quot;0x6381e5f3e249642bb56562bb2cd645d77578491d8b22b4de49976c606f10b275&quot;
    execution_block_height: 28
- deposit_data:
    pubkey: &quot;0x963528adb5322c2e2c54dc296ffddd2861bb103cbf64646781dfa8a3c2d8a8eda7079d2b3e95600028c44365afbf8879&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa52e6582b3f70257211e96a5023f5f860d6c9a236ddd1362f8bf354a3621cee74500682ef4e10f725f19a15527c086320fe2714745b54b4be4cbf1d6ff3f84821bd9e789717ad9fcfc36f9a96509fe4889c0c7824f4e0ce21108744f369d1c07&quot;
  deposit_data_root: &quot;0x7e238e9a9674ddc5e0913d2f698cb776a64392c390353e42287f7c5f4098168a&quot;
  eth1_data:
    deposit_root: &quot;0x4fa046ca0d14d29f272ee56ef063b382a46a04b30cf2826dd0c832152a48d476&quot;
    deposit_count: &quot;28&quot;
    block_hash: &quot;0xf6c4330660f686d3c0549237f8331f78fdb99653b72a25d5b88b7a26be512ae3&quot;
  block_height: 29
  snapshot:
    finalized:
      - &quot;0x5f652df37d6370cd7a4267959f0b885e201b293a69f57a8769c92d797050967e&quot;
      - &quot;0xf411283523e35f406ed67667dab5e352fc257052ddac82c3bb78c1cf157884aa&quot;
      - &quot;0xf7068f7d6c4ca26e61c3ea98cde4d5de184da7fba2f5a99ea5de37c719e27a07&quot;
    deposit_root: &quot;0x4fa046ca0d14d29f272ee56ef063b382a46a04b30cf2826dd0c832152a48d476&quot;
    deposit_count: 28
    execution_block_hash: &quot;0xf6c4330660f686d3c0549237f8331f78fdb99653b72a25d5b88b7a26be512ae3&quot;
    execution_block_height: 29
- deposit_data:
    pubkey: &quot;0xb245d63d3f9d8ea1807a629fcb1b328cb4d542f35a3d5bc478be0df389dddd712fc4c816ba3fede9a96320ae6b24a7d8&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8a177ab3d2b199d3f8bd8dea6b896e1456559e2205064eca589ff1150ad4a4cefb3307fbe1eab515b1caae1d9bd4181f106e1371e3f11d22dd76d90589dcad6b9d9317c7a403dcee09b5074bed807fe6e57c85d688956ad439232d20bdcfc069&quot;
  deposit_data_root: &quot;0xe71a456a9faa68cca752c81c90d954138a586b0f8166c8870ea89b54b01313b3&quot;
  eth1_data:
    deposit_root: &quot;0xc71512461c08e8fab3ad7d23413a46e9c47f3d133ce181800484b6f4603bcd55&quot;
    deposit_count: &quot;29&quot;
    block_hash: &quot;0xd11a018e251c410ef7672f160087e677d29da1b591e14ac632fa2a1c9e00b62f&quot;
  block_height: 30
  snapshot:
    finalized:
      - &quot;0x5f652df37d6370cd7a4267959f0b885e201b293a69f57a8769c92d797050967e&quot;
      - &quot;0xf411283523e35f406ed67667dab5e352fc257052ddac82c3bb78c1cf157884aa&quot;
      - &quot;0xf7068f7d6c4ca26e61c3ea98cde4d5de184da7fba2f5a99ea5de37c719e27a07&quot;
      - &quot;0xe71a456a9faa68cca752c81c90d954138a586b0f8166c8870ea89b54b01313b3&quot;
    deposit_root: &quot;0xc71512461c08e8fab3ad7d23413a46e9c47f3d133ce181800484b6f4603bcd55&quot;
    deposit_count: 29
    execution_block_hash: &quot;0xd11a018e251c410ef7672f160087e677d29da1b591e14ac632fa2a1c9e00b62f&quot;
    execution_block_height: 30
- deposit_data:
    pubkey: &quot;0xa98ed496c2f464226500a6ce04602ff9ef133ed6316f372f6c744aee165149f7e578b12780e0eacec307ae6907351d99&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa12d7c9738f2e443bb7226e03631847b82b84fa2a77426b101dd4c0574da816abfbd0905df5e00d4217ac9ea10b0213c09f6ed2fe8628f8e15c8e07d7d7809cefebb0d9dc515b2f2603e6fba7854c8c842b70137e0f5dea4e2f37ca6b116d8dc&quot;
  deposit_data_root: &quot;0x9e5bfab0b9bd4cbf7232f3a004074c87974e1e1c98838a99775355443426bb6c&quot;
  eth1_data:
    deposit_root: &quot;0xc0108c1784340504324dc235e2214f51603386e6d7d1a36a36adf67148a19a66&quot;
    deposit_count: &quot;30&quot;
    block_hash: &quot;0xf50b59b6a0f164a687d5388bc590467f68a874769b2e320a0c83f4a01dcd663c&quot;
  block_height: 31
  snapshot:
    finalized:
      - &quot;0x5f652df37d6370cd7a4267959f0b885e201b293a69f57a8769c92d797050967e&quot;
      - &quot;0xf411283523e35f406ed67667dab5e352fc257052ddac82c3bb78c1cf157884aa&quot;
      - &quot;0xf7068f7d6c4ca26e61c3ea98cde4d5de184da7fba2f5a99ea5de37c719e27a07&quot;
      - &quot;0x011f1eb3813fb8ee88932f9e3ab2781c9c085105658ba15559994d2e26a1d8dd&quot;
    deposit_root: &quot;0xc0108c1784340504324dc235e2214f51603386e6d7d1a36a36adf67148a19a66&quot;
    deposit_count: 30
    execution_block_hash: &quot;0xf50b59b6a0f164a687d5388bc590467f68a874769b2e320a0c83f4a01dcd663c&quot;
    execution_block_height: 31
- deposit_data:
    pubkey: &quot;0xae00fc3de831b09661a0ac02873c45c84cb2b58cffb6430a3f607e4c3fa1e0932397f11307cd169cdc6f79c463527260&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x84ea7a055239b25ec73f3ac4f12e92941c3cd05a35a72f9a1ee8267cdbc8b97e9ee32e52262b87563186d716ead86d2f01d7ae34575579a6348d9085154b0ea1f186374f169c251e621e1fd177a7fffcb1af3feac4555092ef628a090de37a85&quot;
  deposit_data_root: &quot;0x661bd0e0ddbd2ba4acb89aa575180637c85f5413ed1bcdc028ab1abd0cfc2b47&quot;
  eth1_data:
    deposit_root: &quot;0x832e7610fb4663859d3d72f21510c20aede5e3a5dfc5ac4434c5800ebfd78444&quot;
    deposit_count: &quot;31&quot;
    block_hash: &quot;0x5eceb3df2ef05c68164fa475e0e0e0e2ec5f5613dd8bfe1c486a172dbf0ae594&quot;
  block_height: 32
  snapshot:
    finalized:
      - &quot;0x5f652df37d6370cd7a4267959f0b885e201b293a69f57a8769c92d797050967e&quot;
      - &quot;0xf411283523e35f406ed67667dab5e352fc257052ddac82c3bb78c1cf157884aa&quot;
      - &quot;0xf7068f7d6c4ca26e61c3ea98cde4d5de184da7fba2f5a99ea5de37c719e27a07&quot;
      - &quot;0x011f1eb3813fb8ee88932f9e3ab2781c9c085105658ba15559994d2e26a1d8dd&quot;
      - &quot;0x661bd0e0ddbd2ba4acb89aa575180637c85f5413ed1bcdc028ab1abd0cfc2b47&quot;
    deposit_root: &quot;0x832e7610fb4663859d3d72f21510c20aede5e3a5dfc5ac4434c5800ebfd78444&quot;
    deposit_count: 31
    execution_block_hash: &quot;0x5eceb3df2ef05c68164fa475e0e0e0e2ec5f5613dd8bfe1c486a172dbf0ae594&quot;
    execution_block_height: 32
- deposit_data:
    pubkey: &quot;0xa4855c83d868f772a579133d9f23818008417b743e8447e235d8eb78b1d8f8a9f63f98c551beb7de254400f89592314d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x95e0bd85c20f14f8eb05bb4f2d6a5a0297c78c6598fcc886fa93d2bee73b52c8913a848f690be3094883fbe31200bae90a1401d4c8b11dc82c635f63a3f42cef8fb19f04b27e7ec67c03811327614242d407b157b852e008df78fe482c3496ac&quot;
  deposit_data_root: &quot;0xc8d8e9014b8fd00b885838bd0e71fcec16dbdef5b5b5cae3b09176d8e6bf7883&quot;
  eth1_data:
    deposit_root: &quot;0x2def103e29ea70f435350e0a77e1f8cafe671db9d9f43a1d20621abc7f85c73a&quot;
    deposit_count: &quot;32&quot;
    block_hash: &quot;0x6476bebf6ce3c9e8cbc630a58962e9891b99320d548ea03e527ebd3d23f3c35c&quot;
  block_height: 33
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
    deposit_root: &quot;0x2def103e29ea70f435350e0a77e1f8cafe671db9d9f43a1d20621abc7f85c73a&quot;
    deposit_count: 32
    execution_block_hash: &quot;0x6476bebf6ce3c9e8cbc630a58962e9891b99320d548ea03e527ebd3d23f3c35c&quot;
    execution_block_height: 33
- deposit_data:
    pubkey: &quot;0xa9cf360aa15fb1d1d30ee2b578dc5884823c19661886ae8b892775ccb3bd96b7d7345569a2aa0b14e4d015c54a6a0c54&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x87e60e3980d5d71bcc9983c3317ea8a1a60862ea9f4a4d3c3c710ddbd90db3dac49d6ff7c9d2f8c447a02f9310d7e2eb119e06b83543bc0918c87199ba2724624ece384c336e69743850dd4b3b92f560423279bf50252546d612107a03bab3d8&quot;
  deposit_data_root: &quot;0x1051a6ad73280cee0f10ba9c5762e001a23aef44269a7eae9b2050d17ac1b2cd&quot;
  eth1_data:
    deposit_root: &quot;0x2260d0f4b57dd958fdc8badd66391e11e13bfdb64563ce7904bec1ddc4f8ece1&quot;
    deposit_count: &quot;33&quot;
    block_hash: &quot;0x0268dec10d6ad09835aa9a0a2fe971f4b4ef81f59aaf8a9d43d99f17c186964a&quot;
  block_height: 34
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0x1051a6ad73280cee0f10ba9c5762e001a23aef44269a7eae9b2050d17ac1b2cd&quot;
    deposit_root: &quot;0x2260d0f4b57dd958fdc8badd66391e11e13bfdb64563ce7904bec1ddc4f8ece1&quot;
    deposit_count: 33
    execution_block_hash: &quot;0x0268dec10d6ad09835aa9a0a2fe971f4b4ef81f59aaf8a9d43d99f17c186964a&quot;
    execution_block_height: 34
- deposit_data:
    pubkey: &quot;0xaef9162ee6f29ee82fbfe387756d84f9ac472eb8709217aaf28f5ef0ea273f6210e531496470b30d2b7747216e3672d5&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb5dc53467b3e5826af953385e83f5a21858c7019c6c87aad005509038379db54e0d7d48453bb00394f78e1895a3af296147c45f766f4eafad06e60e7d2b206d628ba2cc61db59a472c68cf48b28979bfccf28a4cafac63271bfcce7461450b5e&quot;
  deposit_data_root: &quot;0x6c24e556eec47c66d6b2a3ec29e013ba206ea34e8d3685b90ff823b06aa80b4b&quot;
  eth1_data:
    deposit_root: &quot;0x9268f23209182ea5393b84731c67d205b50dd541b590548479d816be20fdee70&quot;
    deposit_count: &quot;34&quot;
    block_hash: &quot;0x69ef65f0294564315ef609e7b5bf76420ced3fe110c763dd8bcd348760b1a267&quot;
  block_height: 35
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0x70918d35011dbe3749fad7b8ca02046cb69b4893834ff0f71cfe11a17f2fde0c&quot;
    deposit_root: &quot;0x9268f23209182ea5393b84731c67d205b50dd541b590548479d816be20fdee70&quot;
    deposit_count: 34
    execution_block_hash: &quot;0x69ef65f0294564315ef609e7b5bf76420ced3fe110c763dd8bcd348760b1a267&quot;
    execution_block_height: 35
- deposit_data:
    pubkey: &quot;0xb7e6e187ed813d950a9a17d1e70c03e4de2903596c4c5ff326848515c985deee38198efebc265300cd4f1d6bd7b5d264&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x886d08aca274c127f741d249a865851818a8bd387d1eec83f2d702c4ce78e6ba93d3ddc629d0269f43a91b2a56074797044f37c528b10344cd08808f829867577aa8aed839f6066922ed4953376b65ea14ba725478674bf32a37e337563774cc&quot;
  deposit_data_root: &quot;0x72c9a1bdb8a1deaae1c4007567257ebad96b664c27c9accfab8ad9f9d10b8ca1&quot;
  eth1_data:
    deposit_root: &quot;0x5261a6f04d75e281c1c83bd3a443746b643d0956a23cb2ce69d39c0504072038&quot;
    deposit_count: &quot;35&quot;
    block_hash: &quot;0xd54072d4f8010162a877d38f5d814d9a05ec3ffacdf04128c86205cbc9de92aa&quot;
  block_height: 36
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0x70918d35011dbe3749fad7b8ca02046cb69b4893834ff0f71cfe11a17f2fde0c&quot;
      - &quot;0x72c9a1bdb8a1deaae1c4007567257ebad96b664c27c9accfab8ad9f9d10b8ca1&quot;
    deposit_root: &quot;0x5261a6f04d75e281c1c83bd3a443746b643d0956a23cb2ce69d39c0504072038&quot;
    deposit_count: 35
    execution_block_hash: &quot;0xd54072d4f8010162a877d38f5d814d9a05ec3ffacdf04128c86205cbc9de92aa&quot;
    execution_block_height: 36
- deposit_data:
    pubkey: &quot;0x81054bd51ce57a8415f0c8e0f2fbf94f5a8464552baa33263c20a4da062e5ed994a4d32c171106d2008cd063f48f6fe2&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x97cc963e23ecd9b21bdea8cfebaa2b4d1a47caef4f6c404ce40849fc20ac2337116fab977fc21104491435e6301d499203d6d33b70e389ff42264891d422a79f76d20ec6d501af2d03fdf2d44d00894db77955b19a91823e665a4fe7cff2e9a7&quot;
  deposit_data_root: &quot;0x4a985ca67543ab0f8e8510fc74fcd3efc4eb46e4590c60f415a568b4253701ad&quot;
  eth1_data:
    deposit_root: &quot;0x82c0b3acf41d802658accffa90b6991181cfe9ea6163104cffe745280e17831f&quot;
    deposit_count: &quot;36&quot;
    block_hash: &quot;0x3f9eb6bfe92c16a2bfd72bd6f5a7464255400c39a5ca46e0f50b91d3908fa0a8&quot;
  block_height: 37
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0x98b240f56117c7974d324f09c387e28e5acced1186003fe8df875e1c7377d7a5&quot;
    deposit_root: &quot;0x82c0b3acf41d802658accffa90b6991181cfe9ea6163104cffe745280e17831f&quot;
    deposit_count: 36
    execution_block_hash: &quot;0x3f9eb6bfe92c16a2bfd72bd6f5a7464255400c39a5ca46e0f50b91d3908fa0a8&quot;
    execution_block_height: 37
- deposit_data:
    pubkey: &quot;0xaecc56f2b1c4011d450214d3e1254479d583a6a5c2c06fbc049512731f76227d140df9f36a3f76b4ccb4df1342403573&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb609cc73d220819290cb6f814295b01aeaa044a83105a7df712ab659e9368d3291b55f1b611bd28edc40c5694b5786a6068616edd2cdcac6104d0342b70b1aa0005bfb6828813d58fde482972f8c837d0650945b56e41ab157bbc4e1e7928351&quot;
  deposit_data_root: &quot;0x6466d5d6da2e21242c13f72238a6796c78b52decddb11ed4e3b5e489b96317f0&quot;
  eth1_data:
    deposit_root: &quot;0x1cfd89cb2db15e0811b5a9cf5047e0e0b561afced194bb0a102a2ba155319600&quot;
    deposit_count: &quot;37&quot;
    block_hash: &quot;0xbd8cb6544b20968a1b580dcc4f70cfd241f736bb1c399063a7c25e077e734d15&quot;
  block_height: 38
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0x98b240f56117c7974d324f09c387e28e5acced1186003fe8df875e1c7377d7a5&quot;
      - &quot;0x6466d5d6da2e21242c13f72238a6796c78b52decddb11ed4e3b5e489b96317f0&quot;
    deposit_root: &quot;0x1cfd89cb2db15e0811b5a9cf5047e0e0b561afced194bb0a102a2ba155319600&quot;
    deposit_count: 37
    execution_block_hash: &quot;0xbd8cb6544b20968a1b580dcc4f70cfd241f736bb1c399063a7c25e077e734d15&quot;
    execution_block_height: 38
- deposit_data:
    pubkey: &quot;0x9243ef5ed3bd28892d1ef4f7aaf29faeb9c0e725673cd38e308bd756f20a9ee09de5cd9822e5e77bd03b734ef8a92695&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa19c19c9d1d616f7d3f57393d9ce5230dc2502f6764612a0911227811bea8688fb1f7ffcfb680ea21dd60a3a8faf596b0edaef49936901ae891d7f2266ef937731bb2fb34fd1e30bb161ab8b8e6ee389759519079ebdab9f1500fdb3b633d110&quot;
  deposit_data_root: &quot;0xe430fb5af8b28239457fecf2ea0106ca1cf1e68e5d22ddc64adbb4b5167254be&quot;
  eth1_data:
    deposit_root: &quot;0x7580110cf5b8a5450a42ea097b2fcab6ad4cdb58a2100f8274e486b62ce673e2&quot;
    deposit_count: &quot;38&quot;
    block_hash: &quot;0xed447968de652c510595235a85ad711d39cb1d767bb247d94e82b63be69155ba&quot;
  block_height: 39
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0x98b240f56117c7974d324f09c387e28e5acced1186003fe8df875e1c7377d7a5&quot;
      - &quot;0x5240648c484242305f1ff513c043647c24fc5e5d61cd4196ebf3c2c86402f1f0&quot;
    deposit_root: &quot;0x7580110cf5b8a5450a42ea097b2fcab6ad4cdb58a2100f8274e486b62ce673e2&quot;
    deposit_count: 38
    execution_block_hash: &quot;0xed447968de652c510595235a85ad711d39cb1d767bb247d94e82b63be69155ba&quot;
    execution_block_height: 39
- deposit_data:
    pubkey: &quot;0x925b1fb57c06b5668567bd5aa196531032d6f8918dd4f702017c11b59288e3bdb98e3820ac22780f73580a4119de4bbc&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x81c25d6edbe71803bd57c92c073be629bae323c28ff1a6f30ed5c507493d8271591b46581467cdd92f5847d20a1bc2760bc351838dbf690d90e06af696c7e9e46b943189b2aef29115e1c6e4ea83ec724c7955736e42c611859afebaf622a1a1&quot;
  deposit_data_root: &quot;0xfa7f084e644997f1640e3568bd2400fa26cf9fd43e37275cc6578db139d9921a&quot;
  eth1_data:
    deposit_root: &quot;0xab72caf415667e76d99579f3cd9f5092c19470ce7e2267e9d7dc6d1c42c1401f&quot;
    deposit_count: &quot;39&quot;
    block_hash: &quot;0xd7ecbd540da29e0e617261e2b901815fc05c912a34d91df31de54e91eba6f49b&quot;
  block_height: 40
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0x98b240f56117c7974d324f09c387e28e5acced1186003fe8df875e1c7377d7a5&quot;
      - &quot;0x5240648c484242305f1ff513c043647c24fc5e5d61cd4196ebf3c2c86402f1f0&quot;
      - &quot;0xfa7f084e644997f1640e3568bd2400fa26cf9fd43e37275cc6578db139d9921a&quot;
    deposit_root: &quot;0xab72caf415667e76d99579f3cd9f5092c19470ce7e2267e9d7dc6d1c42c1401f&quot;
    deposit_count: 39
    execution_block_hash: &quot;0xd7ecbd540da29e0e617261e2b901815fc05c912a34d91df31de54e91eba6f49b&quot;
    execution_block_height: 40
- deposit_data:
    pubkey: &quot;0x9648b83a4f09b4ca2021f0c193c5c41df1465715761bca52671ca790a3e92d67686b97b3d54c6110409779df887bd9c6&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa4a58b0ccdc9ba7bd7ac424e1e8b961ffc3839ce06f200551b7302a33d96a8c047f1184889c21711fc2de482c8a9ac05043ff957bee33046cdb77ec386225bf885776275e0643b155d528ba24ceab1c96e2c2da2d64021f7a26f742341f1c6f4&quot;
  deposit_data_root: &quot;0x1edbb8a2956dd6fe52e14a004566f29757e212de7f64c8d98070f33ba78a78d6&quot;
  eth1_data:
    deposit_root: &quot;0x3c6fcce34339d0a97e566eb15d960c2b79440eb5a55a2a2e66dee1a3f63e515f&quot;
    deposit_count: &quot;40&quot;
    block_hash: &quot;0xfdb11831fe4c2fc8596455800b8420cce083f2ff92552d4255876432038a335c&quot;
  block_height: 41
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0xd499ae9a9b57a50ee29e23a5f5130a7ae9dd46ac336b2741be8f300c7ff363e4&quot;
    deposit_root: &quot;0x3c6fcce34339d0a97e566eb15d960c2b79440eb5a55a2a2e66dee1a3f63e515f&quot;
    deposit_count: 40
    execution_block_hash: &quot;0xfdb11831fe4c2fc8596455800b8420cce083f2ff92552d4255876432038a335c&quot;
    execution_block_height: 41
- deposit_data:
    pubkey: &quot;0xa34febc12af07316580b480364f90a76313ccce7927bbe263e27ea270853b02ad4d1428caf55363f3ebebac622cb9fd6&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xadbf354b18eaaed15a3191ee9dc053d250fb54b59959eaba812b8a589797d5c310170da7b98b0448d4a3aaf3091305bc07b6c077b5973fcf0c7d5aefaacea5b6988b297f336841215a5bbed37f0271b325b178a4bf0835bfceae150ae6b3de37&quot;
  deposit_data_root: &quot;0xcde3ed824c06263d6e165d50f2781de0f8e4b36f6e4167427a3e9b90ff45f7be&quot;
  eth1_data:
    deposit_root: &quot;0x3fdfcce325e69c97df3b47c43925e4ff58f633e9c1a4fcd6997c98a4d6931406&quot;
    deposit_count: &quot;41&quot;
    block_hash: &quot;0x4b93ca227181f17fc7c4f95ec672f19a1485d4ebc1981de852066119ede6f989&quot;
  block_height: 42
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0xd499ae9a9b57a50ee29e23a5f5130a7ae9dd46ac336b2741be8f300c7ff363e4&quot;
      - &quot;0xcde3ed824c06263d6e165d50f2781de0f8e4b36f6e4167427a3e9b90ff45f7be&quot;
    deposit_root: &quot;0x3fdfcce325e69c97df3b47c43925e4ff58f633e9c1a4fcd6997c98a4d6931406&quot;
    deposit_count: 41
    execution_block_hash: &quot;0x4b93ca227181f17fc7c4f95ec672f19a1485d4ebc1981de852066119ede6f989&quot;
    execution_block_height: 42
- deposit_data:
    pubkey: &quot;0xb8cd1cef89aa1567a6058957442a698cf1b267130606f749451152959a5dfb50d243890d4adc2c3309f7696d54af1260&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x95031abea421c3997538c779d67489c04c635449f753f8836400532d70e6c4c7d0e42117b773da9b365dd9590cd01ad6079cdaa62e7ce21911bd519218064200e3d15ad252a072eac4554da519bb23f609b63684045b209933a5398606ba8aaa&quot;
  deposit_data_root: &quot;0xdc998298cb82156f077de9a7289d8e92e3270653d4c5388f6ff11102dfa75a15&quot;
  eth1_data:
    deposit_root: &quot;0x60ad801fc6a68abf39ce5ee6db6913e019e9370ea744c3d4b7436f1bd1b7befe&quot;
    deposit_count: &quot;42&quot;
    block_hash: &quot;0xdd485eb08d480f2e25f7ae196f4eb69eaad495bf76be1c9c1d237f92ca6c0d40&quot;
  block_height: 43
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0xd499ae9a9b57a50ee29e23a5f5130a7ae9dd46ac336b2741be8f300c7ff363e4&quot;
      - &quot;0xe3897ec112ed55cfe802be2b7c9dfcc1b5a274736d0a8d8588d28b93bc2e26c9&quot;
    deposit_root: &quot;0x60ad801fc6a68abf39ce5ee6db6913e019e9370ea744c3d4b7436f1bd1b7befe&quot;
    deposit_count: 42
    execution_block_hash: &quot;0xdd485eb08d480f2e25f7ae196f4eb69eaad495bf76be1c9c1d237f92ca6c0d40&quot;
    execution_block_height: 43
- deposit_data:
    pubkey: &quot;0x92a93728c252a45ef587ca53a037593912599d82e2b8aa1b734b99d500a0ac8c142092ea8b3c2c34a28dc8ddf337a249&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb2efbb211e85d2a8cd924085571ab0637583a0fbe41a4f2f4e5b173631067f69fa0eebd2910673afe6bd59bb6f34fce60a974adacb5c1edf47bf8d81084a26e9cc16c553c1601594a393172613cdde131b96434801b6b77ca08f00db29294ecb&quot;
  deposit_data_root: &quot;0xd038d18b6d28712d26bfefef79e3df36a9f5502e066f1a6667b0a0aca21322f6&quot;
  eth1_data:
    deposit_root: &quot;0xf82bbce9e12b06f122b0c9db7b2a24484f78772401aaf5056610de1071de7829&quot;
    deposit_count: &quot;43&quot;
    block_hash: &quot;0x65a8f07cef0dc9e98a8b3c685ed6a36bd6ad5fb6e97b57d202074839fd857e10&quot;
  block_height: 44
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0xd499ae9a9b57a50ee29e23a5f5130a7ae9dd46ac336b2741be8f300c7ff363e4&quot;
      - &quot;0xe3897ec112ed55cfe802be2b7c9dfcc1b5a274736d0a8d8588d28b93bc2e26c9&quot;
      - &quot;0xd038d18b6d28712d26bfefef79e3df36a9f5502e066f1a6667b0a0aca21322f6&quot;
    deposit_root: &quot;0xf82bbce9e12b06f122b0c9db7b2a24484f78772401aaf5056610de1071de7829&quot;
    deposit_count: 43
    execution_block_hash: &quot;0x65a8f07cef0dc9e98a8b3c685ed6a36bd6ad5fb6e97b57d202074839fd857e10&quot;
    execution_block_height: 44
- deposit_data:
    pubkey: &quot;0xb7ee0ef26144de04d9cc80864b869b7ecafbf1b7c0050403cc3c3b514368713b8bb708c464568a18c837e1fd21d09063&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa356193c75dfb2c15995650552d0ca9df6d9adc19dd19dcd26d79e88420fd0b1ad7a923e6c44ec5de81b5306b93f36040341b2393d40a3b0cd70f6f71dabac60bf2d1948a8e2da190316b56ebd84d9ecb7fd6d894380331070885da41c9b6277&quot;
  deposit_data_root: &quot;0x433ac5e37040ef1005e56991ecc42a7207b1557a9d446e5b56a3bb8a617f52fb&quot;
  eth1_data:
    deposit_root: &quot;0x9d13195b240044e78fe982d51b31223feef1d8997e9f8231ac727a05343c55cc&quot;
    deposit_count: &quot;44&quot;
    block_hash: &quot;0x3615ed6ba3c2eac9dfb051aa571d6275395111b6eb80f82acd4da05cfd687f5b&quot;
  block_height: 45
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0xd499ae9a9b57a50ee29e23a5f5130a7ae9dd46ac336b2741be8f300c7ff363e4&quot;
      - &quot;0x7d41f8f8048c87f844b352ae9a9900997fe13c3cb8786346e55ba2c5affb00d2&quot;
    deposit_root: &quot;0x9d13195b240044e78fe982d51b31223feef1d8997e9f8231ac727a05343c55cc&quot;
    deposit_count: 44
    execution_block_hash: &quot;0x3615ed6ba3c2eac9dfb051aa571d6275395111b6eb80f82acd4da05cfd687f5b&quot;
    execution_block_height: 45
- deposit_data:
    pubkey: &quot;0xafc0fa2ed6a270de6122a19d4600380b7f9b5e974d16f095f1702f55792ecab0128b155a69f17ad64a6de0a7063642ec&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8c256c7242c520d646b3cb21d1fbf19097b8131857e7dc246fc81dfe8389b2335d9e1c2e394051a8293ec33bddb006c018696be5402901b5f9446d97cb9f8c5fe48c501e13382801e4e96dfae1df99471df39cc82741590c6915624f63d8bfaf&quot;
  deposit_data_root: &quot;0x2522ea9a8f9dd6862e56af3f38827a80813082b521d43b7e21903c5b81fc1290&quot;
  eth1_data:
    deposit_root: &quot;0x1815da8f5d53ed18c0db0942e6e06bbc1e1e87cc21dd186b66d3a654fbb2aae4&quot;
    deposit_count: &quot;45&quot;
    block_hash: &quot;0x2ee3c9a0d2109d8544754a4d3771e393d9f15c55211c92be0f486e7478840805&quot;
  block_height: 46
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0xd499ae9a9b57a50ee29e23a5f5130a7ae9dd46ac336b2741be8f300c7ff363e4&quot;
      - &quot;0x7d41f8f8048c87f844b352ae9a9900997fe13c3cb8786346e55ba2c5affb00d2&quot;
      - &quot;0x2522ea9a8f9dd6862e56af3f38827a80813082b521d43b7e21903c5b81fc1290&quot;
    deposit_root: &quot;0x1815da8f5d53ed18c0db0942e6e06bbc1e1e87cc21dd186b66d3a654fbb2aae4&quot;
    deposit_count: 45
    execution_block_hash: &quot;0x2ee3c9a0d2109d8544754a4d3771e393d9f15c55211c92be0f486e7478840805&quot;
    execution_block_height: 46
- deposit_data:
    pubkey: &quot;0xa5869ba554d1432b09ee677c117511291b9901f169e870831f457caa6ccfab376cb1fe33813bdb495cf4afec9ea35fdf&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x91cd39a6714d4851e7927c03e5039fed3725573cc1e6005bb20ba21e47ee63ead1defd93963ad5905c6f8074b1197c131011daa8be473190c83523e3028db2f8dae5ff7daf1f708f2830b0ab70916a20154e8135a20972109cfcc1f76bb05caa&quot;
  deposit_data_root: &quot;0xd716729370e1d97244f1758c3f5540e29461b31686c30dd333abbbae979e43a4&quot;
  eth1_data:
    deposit_root: &quot;0xda383b51baf43274f4bc3a1f6573a660a0f49feda6d3cfedf3aec0050a8bff02&quot;
    deposit_count: &quot;46&quot;
    block_hash: &quot;0xdc9667ffa9917e167974cac3e67dd0845657c81556dbf51e77b6915a2741bbb2&quot;
  block_height: 47
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0xd499ae9a9b57a50ee29e23a5f5130a7ae9dd46ac336b2741be8f300c7ff363e4&quot;
      - &quot;0x7d41f8f8048c87f844b352ae9a9900997fe13c3cb8786346e55ba2c5affb00d2&quot;
      - &quot;0xbd3a8edc6db6b9fe322ca4af975e44750c273e56b1a6730a29adc004939ae9a8&quot;
    deposit_root: &quot;0xda383b51baf43274f4bc3a1f6573a660a0f49feda6d3cfedf3aec0050a8bff02&quot;
    deposit_count: 46
    execution_block_hash: &quot;0xdc9667ffa9917e167974cac3e67dd0845657c81556dbf51e77b6915a2741bbb2&quot;
    execution_block_height: 47
- deposit_data:
    pubkey: &quot;0x92f43d79d9f488010b310a54f3fc2e7f4be191ca06d93e588c30c8abf59a52190e060b285ac626eb13cd95bbcc3a0a2a&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x921608298683b15a514c05fb08f39958123498b48d8bbfad1fdd62fc84556aaba3b363e3a20c8423c9b8a157690241bb0ecfeeff3393f4502a2cd14cd8e2fa2373ddba64b573e1ec4c6941ba7cc423248878b9d46444ad8c10bd6f4bea2234e6&quot;
  deposit_data_root: &quot;0xd5d100cccf8847fdf9b03e33e030d4a7dfc868e3c3b6107c4849bd78140bb87b&quot;
  eth1_data:
    deposit_root: &quot;0x62b97e8c2969a6f0d48a9f61a762561a8c7189af1c178b9215771e614909e7f8&quot;
    deposit_count: &quot;47&quot;
    block_hash: &quot;0x75bd1deec6fafccc3cf68485f19eba3c5e0edbeec29ae9f7c59b44f5c44a6f0b&quot;
  block_height: 48
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0xd499ae9a9b57a50ee29e23a5f5130a7ae9dd46ac336b2741be8f300c7ff363e4&quot;
      - &quot;0x7d41f8f8048c87f844b352ae9a9900997fe13c3cb8786346e55ba2c5affb00d2&quot;
      - &quot;0xbd3a8edc6db6b9fe322ca4af975e44750c273e56b1a6730a29adc004939ae9a8&quot;
      - &quot;0xd5d100cccf8847fdf9b03e33e030d4a7dfc868e3c3b6107c4849bd78140bb87b&quot;
    deposit_root: &quot;0x62b97e8c2969a6f0d48a9f61a762561a8c7189af1c178b9215771e614909e7f8&quot;
    deposit_count: 47
    execution_block_hash: &quot;0x75bd1deec6fafccc3cf68485f19eba3c5e0edbeec29ae9f7c59b44f5c44a6f0b&quot;
    execution_block_height: 48
- deposit_data:
    pubkey: &quot;0x9698d9519a02b64f230e5a2520401799c2ca7d69ab23a6d9817943147264bf00d409264b928718245efff4f7ee97dd5c&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xae3dcc94f04909fa6d3c8b56c6af1e037064eea73a5ee9300b2bb4655cd50e4e082108b3009c13d1deb4b94f7ff4c7cf028cb95f86c1e354892263d43826de017601f20c5fd99eadf42e1cacae7c2698715be3582d3cba2d2962891fb1dc58bd&quot;
  deposit_data_root: &quot;0xbc47514e4e62c58f75742971af992d758dad75cf523eccbdaa33bee01a290794&quot;
  eth1_data:
    deposit_root: &quot;0xc36afe52bbbc41a91a58ee9e37deb448edd44992b00cb0bc8b5a32d46ce5dfff&quot;
    deposit_count: &quot;48&quot;
    block_hash: &quot;0x296842ff1c8cdd3e7729800191fe9a1da0209b1f554709867dadc6942510d3ab&quot;
  block_height: 49
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0xdb1b9444d0f397f37f74bfcd3cc45beb343c4fe728174c624eaeb3647745b17b&quot;
    deposit_root: &quot;0xc36afe52bbbc41a91a58ee9e37deb448edd44992b00cb0bc8b5a32d46ce5dfff&quot;
    deposit_count: 48
    execution_block_hash: &quot;0x296842ff1c8cdd3e7729800191fe9a1da0209b1f554709867dadc6942510d3ab&quot;
    execution_block_height: 49
- deposit_data:
    pubkey: &quot;0xa852816b8e463178eea5acebb4b86d0acb6d8c6812cf313296bd271ea4d2fd89d281e5fc296df4df49019169bdf96922&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xaa562944e5476538903b89274c26eebf2bf87547968022140c4c950fcf9c02140ca064cdfa79aeb3bb0d0f738b2f56f401501fe791231633153ce1a56ccec8b8ba3b3d104b00b6477c89cf887b65d4ebc32c7f8d4d692288068941131d50c286&quot;
  deposit_data_root: &quot;0x15e2e2026f0b8722f28569cf3752f02eec3d115c7a58947559fb0d40bc70f211&quot;
  eth1_data:
    deposit_root: &quot;0xe8659b62077801e4e285d99cb0f7df9eee6332af5d7173211c5119e89bfe98c7&quot;
    deposit_count: &quot;49&quot;
    block_hash: &quot;0x2ad547b4552b0d033398b10c76a224ea4e27af714a7d40208a1bcad524bd3de9&quot;
  block_height: 50
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0xdb1b9444d0f397f37f74bfcd3cc45beb343c4fe728174c624eaeb3647745b17b&quot;
      - &quot;0x15e2e2026f0b8722f28569cf3752f02eec3d115c7a58947559fb0d40bc70f211&quot;
    deposit_root: &quot;0xe8659b62077801e4e285d99cb0f7df9eee6332af5d7173211c5119e89bfe98c7&quot;
    deposit_count: 49
    execution_block_hash: &quot;0x2ad547b4552b0d033398b10c76a224ea4e27af714a7d40208a1bcad524bd3de9&quot;
    execution_block_height: 50
- deposit_data:
    pubkey: &quot;0x8a298ee1ac0466ecaa04d5798048c6e192409af63217f32fd7e07794cfcdcd8deca055b9782dd1ad45a578a9ec10606c&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa14f099ef773a2282a7c0d664557897c48aa594015e05373a5fef26c8dc848ae0c25718d3a9be982117159c908abcc1e0aab94110824c8410ea08039398a8569a844cafd9002ef319a2e6a0717a5b340a4d153e6f136be7a57ee5abd73cf7017&quot;
  deposit_data_root: &quot;0xc46f9746cf62672d7d8ed56c05a7dc880f2475a6bd8a73151abef6f88907d53c&quot;
  eth1_data:
    deposit_root: &quot;0xc30f240a494e623caab8bc918828d31feea930902c6e3dca2c3a423f3f0bf102&quot;
    deposit_count: &quot;50&quot;
    block_hash: &quot;0xdcf96433eba5c4c5877afce8ecd730c943b0b3b02c6b36593fda5839cc095d7d&quot;
  block_height: 51
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0xdb1b9444d0f397f37f74bfcd3cc45beb343c4fe728174c624eaeb3647745b17b&quot;
      - &quot;0xe74828c6edb30e3e4bf54de63aeab6c3f97f7d6f3a558705eaedef064b8645ce&quot;
    deposit_root: &quot;0xc30f240a494e623caab8bc918828d31feea930902c6e3dca2c3a423f3f0bf102&quot;
    deposit_count: 50
    execution_block_hash: &quot;0xdcf96433eba5c4c5877afce8ecd730c943b0b3b02c6b36593fda5839cc095d7d&quot;
    execution_block_height: 51
- deposit_data:
    pubkey: &quot;0xae4d49364e4a36760cc74a675500055b9aed99bc19d31abb953ea156bb5a76dcf36769d15341b850114a30ffc8057780&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa8fd33d2856c669b84efb3465006ba799fd3c680a56b104edc738107913fe0f91a6f99b7a69c337a493d8ea43791127211de5d964d1840fc403151a92d7b28cf8b141caa76807a06b673421effffa1d4e718ebe7fd27e59f1525126a01ab4bc4&quot;
  deposit_data_root: &quot;0x9330e615cf2658bb9b5039e5c6eea90714a76b3b8f3759dff1e295c364f695db&quot;
  eth1_data:
    deposit_root: &quot;0x0e258dde53879f7f68ee782954ca2b25d222447991919c685f637409175252be&quot;
    deposit_count: &quot;51&quot;
    block_hash: &quot;0x9678505c7aacb038cfe8edc0a224c5eb2d1abfdd5775bc6d6260189c247e3443&quot;
  block_height: 52
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0xdb1b9444d0f397f37f74bfcd3cc45beb343c4fe728174c624eaeb3647745b17b&quot;
      - &quot;0xe74828c6edb30e3e4bf54de63aeab6c3f97f7d6f3a558705eaedef064b8645ce&quot;
      - &quot;0x9330e615cf2658bb9b5039e5c6eea90714a76b3b8f3759dff1e295c364f695db&quot;
    deposit_root: &quot;0x0e258dde53879f7f68ee782954ca2b25d222447991919c685f637409175252be&quot;
    deposit_count: 51
    execution_block_hash: &quot;0x9678505c7aacb038cfe8edc0a224c5eb2d1abfdd5775bc6d6260189c247e3443&quot;
    execution_block_height: 52
- deposit_data:
    pubkey: &quot;0xb397692ccbf442bfe078174c85dbad7fd605e4ff1caf2904b31e4a4c79d6444813ad9b2093ac8fbd4dd59ec7a4c8c006&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa10cd137f49972e2e2a053abc96a1e356a4a65b9beac4b910a867c5e150e77a8b66cf7e32dae3ddcc1be9643a1ed775d0e6ab93def5f8685f756a014d6d6b721ce5b7d17cc85d8fefdf89276bbf67cf0b5775ef535bdea61a5fbe40b32d318ae&quot;
  deposit_data_root: &quot;0x3170a57af6642be1e018dba7471b811acfb9ec1b9a66eddd3f28666e0001c492&quot;
  eth1_data:
    deposit_root: &quot;0x1b23c0123f7e5de30edcc56f34eef43f3dec1cee9374fc72a9f8d92b34111b1c&quot;
    deposit_count: &quot;52&quot;
    block_hash: &quot;0x2d4a16997b0e306d3e8f22dfd9b465ec6532273d54608973da7900e7223be426&quot;
  block_height: 53
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0xdb1b9444d0f397f37f74bfcd3cc45beb343c4fe728174c624eaeb3647745b17b&quot;
      - &quot;0x7d1f34ae9db53b9a029e24b8d766e0e54a464ac4eade9210f96eb71d77dbe9c0&quot;
    deposit_root: &quot;0x1b23c0123f7e5de30edcc56f34eef43f3dec1cee9374fc72a9f8d92b34111b1c&quot;
    deposit_count: 52
    execution_block_hash: &quot;0x2d4a16997b0e306d3e8f22dfd9b465ec6532273d54608973da7900e7223be426&quot;
    execution_block_height: 53
- deposit_data:
    pubkey: &quot;0x87c9f7605d07550b46c79add5ea4e39de5014c03833669257bd6666b7ec838f53800104779940d8cdd884275a0f6a3ef&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb6a8b8d4ea3c51c1e53f1eb8eaca900db9c70a2c7c11f555856b6aff737c972c9f5871bbc8fb46d6ca3f33b271c8a7e20976ca805666b41bbe38a576167466db0f8beaa28995aba1ff250fa3e4f87a0843d3941ff477528dc7daad37f5a720a1&quot;
  deposit_data_root: &quot;0x0c0f4d2950ee7d4b8062761154cfe0c1d6f13d9a4d5e2fef701ea38614add54b&quot;
  eth1_data:
    deposit_root: &quot;0x89aeb5a6e924afe40fa404ce4c31a09ad222c9f3dddfa1df9f4946ba81243754&quot;
    deposit_count: &quot;53&quot;
    block_hash: &quot;0x5279517c77c4fbf7e0c19cae59db917ff0ec55bc62ec2254df5cc945eb415daf&quot;
  block_height: 54
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0xdb1b9444d0f397f37f74bfcd3cc45beb343c4fe728174c624eaeb3647745b17b&quot;
      - &quot;0x7d1f34ae9db53b9a029e24b8d766e0e54a464ac4eade9210f96eb71d77dbe9c0&quot;
      - &quot;0x0c0f4d2950ee7d4b8062761154cfe0c1d6f13d9a4d5e2fef701ea38614add54b&quot;
    deposit_root: &quot;0x89aeb5a6e924afe40fa404ce4c31a09ad222c9f3dddfa1df9f4946ba81243754&quot;
    deposit_count: 53
    execution_block_hash: &quot;0x5279517c77c4fbf7e0c19cae59db917ff0ec55bc62ec2254df5cc945eb415daf&quot;
    execution_block_height: 54
- deposit_data:
    pubkey: &quot;0xb08f7feb86786c37661afb9951a959c9b465fd11ca98fcbc908fcf49144084051f6c363e2eb4459da2c2d03d84175692&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x86fb9f4c6ca3c5453646471e6393f1260f04f25bae62541203f6dfbfaf226dee57b0b6a1b2d698d3630a4ae418f7986b0273299006e4488f835612311eccb1fecaf576e1740d29b0c26478ec11eaf644b3e3c696ebe562e6942d282bef29f82b&quot;
  deposit_data_root: &quot;0x04e2ccad9538abe82e053c1414dcd8083d20206e84a3ce294036e271bf391e7a&quot;
  eth1_data:
    deposit_root: &quot;0xd749a15bc781e795b4e88adce9dbd068f0350586391f8170e025a4a671c7be06&quot;
    deposit_count: &quot;54&quot;
    block_hash: &quot;0x7a5b1937cf1cf319c059b24ac4d7a905d841d3c725da9597f32cd609159f1e04&quot;
  block_height: 55
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0xdb1b9444d0f397f37f74bfcd3cc45beb343c4fe728174c624eaeb3647745b17b&quot;
      - &quot;0x7d1f34ae9db53b9a029e24b8d766e0e54a464ac4eade9210f96eb71d77dbe9c0&quot;
      - &quot;0x45ae70157fb3f9a80f56cedf94dd1211a7bb8fe79527c7077097c766dc4fcc92&quot;
    deposit_root: &quot;0xd749a15bc781e795b4e88adce9dbd068f0350586391f8170e025a4a671c7be06&quot;
    deposit_count: 54
    execution_block_hash: &quot;0x7a5b1937cf1cf319c059b24ac4d7a905d841d3c725da9597f32cd609159f1e04&quot;
    execution_block_height: 55
- deposit_data:
    pubkey: &quot;0xa48cc260df1df875176cb17493a5b53d669c091da74d5075acb8952a641b1b7ef68d01f009c1a365d2fa80937c79dd6b&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb3c12fa96e2938a28f872bdf1e62a037dcbe3d5fb0e7cee58bcd2d2c6d82ffdc6428a5ec997a8ae26d113f30959fddb407f319ef49f989fdee215aa96d2fcf30b6154590ee9f856daaccd20c344fa5d4b4cb6678a3409aa619af35bed6f5259e&quot;
  deposit_data_root: &quot;0xfefb7de90e7a23e87b7df79ef2b97df376a89aab301014112ce01f2362515d7e&quot;
  eth1_data:
    deposit_root: &quot;0x92e91d9cb729330a946dea613ffd50ed1911c3b7cdb92a7e400d486310a77c6a&quot;
    deposit_count: &quot;55&quot;
    block_hash: &quot;0xfb4bb38d9560af55e012e04dc652fe291826bbd4dd8fdc350300f9d97e463ec1&quot;
  block_height: 56
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0xdb1b9444d0f397f37f74bfcd3cc45beb343c4fe728174c624eaeb3647745b17b&quot;
      - &quot;0x7d1f34ae9db53b9a029e24b8d766e0e54a464ac4eade9210f96eb71d77dbe9c0&quot;
      - &quot;0x45ae70157fb3f9a80f56cedf94dd1211a7bb8fe79527c7077097c766dc4fcc92&quot;
      - &quot;0xfefb7de90e7a23e87b7df79ef2b97df376a89aab301014112ce01f2362515d7e&quot;
    deposit_root: &quot;0x92e91d9cb729330a946dea613ffd50ed1911c3b7cdb92a7e400d486310a77c6a&quot;
    deposit_count: 55
    execution_block_hash: &quot;0xfb4bb38d9560af55e012e04dc652fe291826bbd4dd8fdc350300f9d97e463ec1&quot;
    execution_block_height: 56
- deposit_data:
    pubkey: &quot;0xac9f4df3f20a16a9fefad08817fcbc9a6ee17f7512db006414b4aa6f234c2313585ef72c5776df55fa6284af4bc3f631&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa5d0be0b159b75f2524e1bc1243bb8f1272716daa2a1c635f0b34004b30d9038450cbd9b72f29a17d1fb4d99857fdbd710e2edb2036aa89589d1344b6e3984fbaa44ee0409fa048d0dd86aa1aa0164663b187e0ec9f798b490dc4b34b095152f&quot;
  deposit_data_root: &quot;0x5568cb23722d865d414baf5f7ee92234383e175fb3e5b7cae390244f9735987b&quot;
  eth1_data:
    deposit_root: &quot;0x565ce384ec4ca0d45ab8c20b895996f4dd15f01f00497b24cdaf6378602efed7&quot;
    deposit_count: &quot;56&quot;
    block_hash: &quot;0x13a0c8bcd47c1e4d208515dfb6e9773ee2d5f894691e7986bb8d8699f33d9495&quot;
  block_height: 57
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0xdb1b9444d0f397f37f74bfcd3cc45beb343c4fe728174c624eaeb3647745b17b&quot;
      - &quot;0xcc3b81ef99612124c28a53fdad6aef205b53c82843c080b9f269b80313fe7481&quot;
    deposit_root: &quot;0x565ce384ec4ca0d45ab8c20b895996f4dd15f01f00497b24cdaf6378602efed7&quot;
    deposit_count: 56
    execution_block_hash: &quot;0x13a0c8bcd47c1e4d208515dfb6e9773ee2d5f894691e7986bb8d8699f33d9495&quot;
    execution_block_height: 57
- deposit_data:
    pubkey: &quot;0x94f0c8535601596eb2165adb28ebe495891a3e4ea77ef501e7790cccb281827d377a5a8d4c200e3595d3f38f8633b480&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x87d4271630df8e3780900e5171d3642a781205154f11be812e923c87d19a3224213b9dad62ed42f1126a0b52157afa9e16acfecf96c7f8c2345bc1f744e491136cb100d82f549467f595fa6393ff0f8d0dd83cf5c95d88c47d0023bf0796fd6f&quot;
  deposit_data_root: &quot;0x6adfa7ccc8b757b108c02b37ee27bc04e83e9c7538b1c07ebcf342d564c56135&quot;
  eth1_data:
    deposit_root: &quot;0x352eee8320a9c83dc4f9b5086b92df7ab3d1844f77cde7f3c3daf8905d91c4d0&quot;
    deposit_count: &quot;57&quot;
    block_hash: &quot;0x1023685ab1df034f7762e46035d995d87f972c29ffaa097a5b6301da756398cf&quot;
  block_height: 58
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0xdb1b9444d0f397f37f74bfcd3cc45beb343c4fe728174c624eaeb3647745b17b&quot;
      - &quot;0xcc3b81ef99612124c28a53fdad6aef205b53c82843c080b9f269b80313fe7481&quot;
      - &quot;0x6adfa7ccc8b757b108c02b37ee27bc04e83e9c7538b1c07ebcf342d564c56135&quot;
    deposit_root: &quot;0x352eee8320a9c83dc4f9b5086b92df7ab3d1844f77cde7f3c3daf8905d91c4d0&quot;
    deposit_count: 57
    execution_block_hash: &quot;0x1023685ab1df034f7762e46035d995d87f972c29ffaa097a5b6301da756398cf&quot;
    execution_block_height: 58
- deposit_data:
    pubkey: &quot;0xb5bb0162a4f27d1bab4c7dc3d20f5a75d6ee98c56bcd309a1f0f307685ad47ffb8a35bfdf8431b9b954b59662a74c478&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb091cd5476b2bceec9f6cba38b3787fb080d9ea63cd6ed19eebd72be7ab0887e44f233e993b9ded4fe33353a9aba5a9206b8a9da387d222e58bf05cf333b25f6559557cf95645c785c75683317a1c97dec807770e57d581107e9fbca03069eff&quot;
  deposit_data_root: &quot;0x9fad5a196b6ac7c47a1fd191fe4eac56bd9b9fed5d275ad0311e165059d7d40e&quot;
  eth1_data:
    deposit_root: &quot;0x349bbbc8e21e10251fcfceec3821ea9dd2806526e71fe472bb8b84d8d5458f5f&quot;
    deposit_count: &quot;58&quot;
    block_hash: &quot;0xdeaa8a27fbc74fcbda0b7a30da9c4e4392a9f961b90c45a272a204bbfb5d8d4e&quot;
  block_height: 59
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0xdb1b9444d0f397f37f74bfcd3cc45beb343c4fe728174c624eaeb3647745b17b&quot;
      - &quot;0xcc3b81ef99612124c28a53fdad6aef205b53c82843c080b9f269b80313fe7481&quot;
      - &quot;0x2ef9c25463a9664b369b20321671d2fec217ea4c64ee3a714e5983a0be95acd0&quot;
    deposit_root: &quot;0x349bbbc8e21e10251fcfceec3821ea9dd2806526e71fe472bb8b84d8d5458f5f&quot;
    deposit_count: 58
    execution_block_hash: &quot;0xdeaa8a27fbc74fcbda0b7a30da9c4e4392a9f961b90c45a272a204bbfb5d8d4e&quot;
    execution_block_height: 59
- deposit_data:
    pubkey: &quot;0x8826e820179fd321819e78ffee16f50ac528db2da71ad8c269f60b878bc4887c79c0545b3d750e86e490d5ba9083cb70&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x95622cabae0c3d62f58fba1302e207d5ce92aa3df653968f020dce42b84d49ac928f7ebce159b2b5fa55115bcd0895820269879dd4ebea6359d5c9d8b9c209cac6891552985da1e64a60e6b0959b2bf0ed81d97381ef9b1e0aa59217e9dbd280&quot;
  deposit_data_root: &quot;0x80ecb93497e9a21c4e6d48528adc8d32ec4808a275fcdb2ecab6fc052e6936a3&quot;
  eth1_data:
    deposit_root: &quot;0x56f2b33a48de69dc2f0652bb1d6d4a63de86b9db2319b51f59f93225d93787e8&quot;
    deposit_count: &quot;59&quot;
    block_hash: &quot;0xecfb4b768d48d31ac3d30f640d00d0afb9c932ba7316c9f21ede2ece7e4a65c1&quot;
  block_height: 60
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0xdb1b9444d0f397f37f74bfcd3cc45beb343c4fe728174c624eaeb3647745b17b&quot;
      - &quot;0xcc3b81ef99612124c28a53fdad6aef205b53c82843c080b9f269b80313fe7481&quot;
      - &quot;0x2ef9c25463a9664b369b20321671d2fec217ea4c64ee3a714e5983a0be95acd0&quot;
      - &quot;0x80ecb93497e9a21c4e6d48528adc8d32ec4808a275fcdb2ecab6fc052e6936a3&quot;
    deposit_root: &quot;0x56f2b33a48de69dc2f0652bb1d6d4a63de86b9db2319b51f59f93225d93787e8&quot;
    deposit_count: 59
    execution_block_hash: &quot;0xecfb4b768d48d31ac3d30f640d00d0afb9c932ba7316c9f21ede2ece7e4a65c1&quot;
    execution_block_height: 60
- deposit_data:
    pubkey: &quot;0x92977e71396633d442f61e16a0cfcf8ffad0af93c9f1b7fdf4f7ccb816de052925fc192922d6252d325ef9fa2e0595d2&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8645569a7d2c3a844a0215c163fb2e247b4201161e2399f213c0985b568ac98961398f0c712c05892857cddf384a12e007ad9412dbbc26b18b7e76b9a5d5735db8dd0142e879b7b46f8d42dc05be19ec9cc9bd42b741cffbbc250d576f86232f&quot;
  deposit_data_root: &quot;0xb4fc5adc460335413f7ddc9f38007ca12c841212a86961b3190b566e371b6fcd&quot;
  eth1_data:
    deposit_root: &quot;0x2badea58e40583186b7ad89ed366eb9fe85cd849309ca43bf5f4703b45c7c9bd&quot;
    deposit_count: &quot;60&quot;
    block_hash: &quot;0xb6a0eed143a5b2bd2ccace6a5f28ec0b9ef819eb82a781b12f82ff9e717077c7&quot;
  block_height: 61
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0xdb1b9444d0f397f37f74bfcd3cc45beb343c4fe728174c624eaeb3647745b17b&quot;
      - &quot;0xcc3b81ef99612124c28a53fdad6aef205b53c82843c080b9f269b80313fe7481&quot;
      - &quot;0xc7acab11e9b20b4a85bafee152a8fc5314df74b63c324dd84a917f89c3c5bf0a&quot;
    deposit_root: &quot;0x2badea58e40583186b7ad89ed366eb9fe85cd849309ca43bf5f4703b45c7c9bd&quot;
    deposit_count: 60
    execution_block_hash: &quot;0xb6a0eed143a5b2bd2ccace6a5f28ec0b9ef819eb82a781b12f82ff9e717077c7&quot;
    execution_block_height: 61
- deposit_data:
    pubkey: &quot;0x91ae4686b0d20470409f020eaca826c3efc6c1926ed25d05e6f0f7916391ec89c2341917277c437ac8fffffe94b68111&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa88873293cce3d3e180c98a6e973057873578ee51480e5d2a821c6137aa143ab8ccf64dcb131013b6203fdbbbb848efe015949a431ff7b401b131ab6d33ce9dcc698c00e3503c5cd98d935d2040952dc9a863fa7e8ff60e52088ae198773b740&quot;
  deposit_data_root: &quot;0x75dac1ed3a104cdfa3e93c4b91e85ff6bd7a309a3f881fedf48219657ba71993&quot;
  eth1_data:
    deposit_root: &quot;0x243b61a30048fd9847aa0c1424feffee5876462556952e6120800137cdfca8cc&quot;
    deposit_count: &quot;61&quot;
    block_hash: &quot;0x3febb45aaa3b77bf4190c51f349ae02ab28df9c090a727294f2d6850feaf71fd&quot;
  block_height: 62
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0xdb1b9444d0f397f37f74bfcd3cc45beb343c4fe728174c624eaeb3647745b17b&quot;
      - &quot;0xcc3b81ef99612124c28a53fdad6aef205b53c82843c080b9f269b80313fe7481&quot;
      - &quot;0xc7acab11e9b20b4a85bafee152a8fc5314df74b63c324dd84a917f89c3c5bf0a&quot;
      - &quot;0x75dac1ed3a104cdfa3e93c4b91e85ff6bd7a309a3f881fedf48219657ba71993&quot;
    deposit_root: &quot;0x243b61a30048fd9847aa0c1424feffee5876462556952e6120800137cdfca8cc&quot;
    deposit_count: 61
    execution_block_hash: &quot;0x3febb45aaa3b77bf4190c51f349ae02ab28df9c090a727294f2d6850feaf71fd&quot;
    execution_block_height: 62
- deposit_data:
    pubkey: &quot;0x8a0d241955104bedacb3b829162f2b457915c2beb9018ede8ef8ea80f401b471c42354358da9e62b51c38d54263a78a9&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa073c1da30c9555dde136f86879936cbf247828ad39b688058b8dad95781651379dfce772fb5aa93d60e50d0d2374ada00e3ebc42e2b1d732512f990dafa34dc7dd1553bff38a171b06f0b215f40bcf5fb354d914bb595acb8dc49d042896ff7&quot;
  deposit_data_root: &quot;0x3274fb1171cb037b6242c298f1680eaf23f01ef807669e9b00f65eafe0640a1a&quot;
  eth1_data:
    deposit_root: &quot;0x52e5a1f96b0f8c69423bfbeb7ed3888cfb9c9098eafd0eeb14a9a8c21d77d245&quot;
    deposit_count: &quot;62&quot;
    block_hash: &quot;0x8fbc1f4ff163d89df6143c66f1df08196d0313df09ff0b062925ec33e48415bf&quot;
  block_height: 63
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0xdb1b9444d0f397f37f74bfcd3cc45beb343c4fe728174c624eaeb3647745b17b&quot;
      - &quot;0xcc3b81ef99612124c28a53fdad6aef205b53c82843c080b9f269b80313fe7481&quot;
      - &quot;0xc7acab11e9b20b4a85bafee152a8fc5314df74b63c324dd84a917f89c3c5bf0a&quot;
      - &quot;0x997db7123f404f063da7db4a2d3952d11f30820ec8445b5da03eccfde69e946f&quot;
    deposit_root: &quot;0x52e5a1f96b0f8c69423bfbeb7ed3888cfb9c9098eafd0eeb14a9a8c21d77d245&quot;
    deposit_count: 62
    execution_block_hash: &quot;0x8fbc1f4ff163d89df6143c66f1df08196d0313df09ff0b062925ec33e48415bf&quot;
    execution_block_height: 63
- deposit_data:
    pubkey: &quot;0x80a2be2c7dbce8ddc2eba03522697587c375a5a9e92d4b31ed9e3c34bee047095d93e3c70b1662b3faa301f5b19978e5&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x81e2f7ffe007e2d6b121ec976d7a9d3cd053d82cf07f2411184522664755306185dbb3352c5bd7e83154fafb34a56f2601c164f280e447e64655ba7e9457f5967f15eb4d6080af7ef971b9067a498266fb3afd979a251169402cb4d80205b9e0&quot;
  deposit_data_root: &quot;0x75169d67108dcd4c68492847c39c0f7b24ecbb2a0240e62dd5f72518e142df11&quot;
  eth1_data:
    deposit_root: &quot;0x8ffd6666bccbb0269e2df5e53b91844c9bdbac57d3089d6d9a4d91c1963a61c9&quot;
    deposit_count: &quot;63&quot;
    block_hash: &quot;0x4d7818aafb46a6f055359d6d7c664c3b36599a2dcab8cf332ff896345bc0cab1&quot;
  block_height: 64
  snapshot:
    finalized:
      - &quot;0x378775a69829a0b8467bf331f4815d2ab91c796f5eb14cd9c08347421a245f2f&quot;
      - &quot;0xdb1b9444d0f397f37f74bfcd3cc45beb343c4fe728174c624eaeb3647745b17b&quot;
      - &quot;0xcc3b81ef99612124c28a53fdad6aef205b53c82843c080b9f269b80313fe7481&quot;
      - &quot;0xc7acab11e9b20b4a85bafee152a8fc5314df74b63c324dd84a917f89c3c5bf0a&quot;
      - &quot;0x997db7123f404f063da7db4a2d3952d11f30820ec8445b5da03eccfde69e946f&quot;
      - &quot;0x75169d67108dcd4c68492847c39c0f7b24ecbb2a0240e62dd5f72518e142df11&quot;
    deposit_root: &quot;0x8ffd6666bccbb0269e2df5e53b91844c9bdbac57d3089d6d9a4d91c1963a61c9&quot;
    deposit_count: 63
    execution_block_hash: &quot;0x4d7818aafb46a6f055359d6d7c664c3b36599a2dcab8cf332ff896345bc0cab1&quot;
    execution_block_height: 64
- deposit_data:
    pubkey: &quot;0x86a73886aa0114bbdbba346cb7c07376c81b549a4802c24d98ebbc54a6a1b5d2ac874ef657cfb27c3644fcb85f97a2b5&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb697a8a9e4d724302efb08e88ec4308b803fe8544cd5d53324dce4b601a18a66fd612318734d520d5909051f62e9e9e90823a7bcb951c2b5b9d349f0c5b57ff748ec93a1750df96e212f39900eac541d0753683d46a375a421300c0434c3fa88&quot;
  deposit_data_root: &quot;0x1418de3c263fa52285b93a809f16134cf4e008bebd2d81da7eb7d6f2a22c61a2&quot;
  eth1_data:
    deposit_root: &quot;0x5c7e3d0e9ac6cd2613e89748ec650d1ec5d44bf936c7761a0f5fc9526f263e17&quot;
    deposit_count: &quot;64&quot;
    block_hash: &quot;0xab873b4514bca399da91a00dc630df65bf37f53517b54c075f2f40a01e47661c&quot;
  block_height: 65
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
    deposit_root: &quot;0x5c7e3d0e9ac6cd2613e89748ec650d1ec5d44bf936c7761a0f5fc9526f263e17&quot;
    deposit_count: 64
    execution_block_hash: &quot;0xab873b4514bca399da91a00dc630df65bf37f53517b54c075f2f40a01e47661c&quot;
    execution_block_height: 65
- deposit_data:
    pubkey: &quot;0xa98c264dfc3bc3ed635df5dbfd54909e77600cd68480ec201d9f5c416580591daaa9735b04743e10e7fc6370a8189775&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa946b360375c6dea0c890263ccdefeb4f4a815bea7ebb6513de80f7932fb34ed36f3d5e41f26a9ef1550531d7ae807cc1094b7b5cdf2682ca713658ee8ffe4de45a0a20d8ea3a10b141e4d831030339e78936f04363529be77fcee46d4a9642a&quot;
  deposit_data_root: &quot;0xb484b20a0bc7eb410b062c857ecce9460c3aa86b2b81133ef727507bb60c6f9e&quot;
  eth1_data:
    deposit_root: &quot;0x5744f4e817aaa5221b70a045adde9f74069f40880a4646630c0417afc759a267&quot;
    deposit_count: &quot;65&quot;
    block_hash: &quot;0x9f358a6ec47032ba2fd6e11f79da1ef89cde8d1cdfdc3f8f21006fc056a1ad61&quot;
  block_height: 66
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0xb484b20a0bc7eb410b062c857ecce9460c3aa86b2b81133ef727507bb60c6f9e&quot;
    deposit_root: &quot;0x5744f4e817aaa5221b70a045adde9f74069f40880a4646630c0417afc759a267&quot;
    deposit_count: 65
    execution_block_hash: &quot;0x9f358a6ec47032ba2fd6e11f79da1ef89cde8d1cdfdc3f8f21006fc056a1ad61&quot;
    execution_block_height: 66
- deposit_data:
    pubkey: &quot;0x8bb7aa61aa8bbd2b7825d28c340da89b625381232dcf2742276b4e3a2e4a0f42ef68794fdf005d94014636732fba2f40&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8adda613ebf39f91333958b18dfb271b5b75d97342a9447e5371e31af7fdbec354687868cbf1f2e57a71c3aee43e623f0a6161ff94eebb064cf57aec311e0f638b24b864c1433622b5236e5d33e410626c34784e8409a90bcf855192fc1ae0b5&quot;
  deposit_data_root: &quot;0xebac12ca39e81dcea9e7c2de29be0ffed4b4b560c5cf4539f3c3d7789ddf03df&quot;
  eth1_data:
    deposit_root: &quot;0xce3f915b2665672a9e96e35249fd4a07a0ff010b8f455995fb4d9d4d383d5921&quot;
    deposit_count: &quot;66&quot;
    block_hash: &quot;0x4fe81ed058f82fd3308a29454b21d44d977963ab016f3aa161803a909fe20768&quot;
  block_height: 67
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0xb74da2b05b56d5a84748b4616151668e0b0bf38c880acdbe71451e62bd7306f9&quot;
    deposit_root: &quot;0xce3f915b2665672a9e96e35249fd4a07a0ff010b8f455995fb4d9d4d383d5921&quot;
    deposit_count: 66
    execution_block_hash: &quot;0x4fe81ed058f82fd3308a29454b21d44d977963ab016f3aa161803a909fe20768&quot;
    execution_block_height: 67
- deposit_data:
    pubkey: &quot;0x8bb9e1693eab1496d7583bf22fb1f2a475934c63b4d94118940617aa187bc277f738223e0ec1ce8a5566035d9bcc5470&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb00b5a95db40dd1b1bdbd364519b03447ed232d3c88dfad68203892523509831131f21b819260be2554d0e627f113f831477f83c9fc1948a451f4dab078c05376608168964fda9b8d033f8768f008fa1db2d0c61c47a9adb3812ef5e25f42889&quot;
  deposit_data_root: &quot;0xedbc4b624f488b096f5cce8386dc735682a0d890193dddc47273a3f8e9587c4f&quot;
  eth1_data:
    deposit_root: &quot;0x8039f6582e426da6ad47fa64f2b0c5927b11f9980914d12174d0d4c883ab1c21&quot;
    deposit_count: &quot;67&quot;
    block_hash: &quot;0x3dbbf6de20c3b31947160ee99b05fca4cb77b35ef72f7bd5ef183b57dde0f4bd&quot;
  block_height: 68
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0xb74da2b05b56d5a84748b4616151668e0b0bf38c880acdbe71451e62bd7306f9&quot;
      - &quot;0xedbc4b624f488b096f5cce8386dc735682a0d890193dddc47273a3f8e9587c4f&quot;
    deposit_root: &quot;0x8039f6582e426da6ad47fa64f2b0c5927b11f9980914d12174d0d4c883ab1c21&quot;
    deposit_count: 67
    execution_block_hash: &quot;0x3dbbf6de20c3b31947160ee99b05fca4cb77b35ef72f7bd5ef183b57dde0f4bd&quot;
    execution_block_height: 68
- deposit_data:
    pubkey: &quot;0xafe6eface52fb6de91055a81abf9aa6e42ce2ef36fd8ae0d09aec6e5d8bd40a065dfccda6104af94df3f7a5854559ef4&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x966e020128302f799fa32f954776a47b6e40fbf346c8055427254918a88c39609ead584b770a03a4425dfcf57fd79aff17f0ac1e364a383823fef8a7aaa06d3a252c6c8843ab9bd156bbb5ce8ecb542c5459c9d587e5e29e90f640c8fb1a16bb&quot;
  deposit_data_root: &quot;0x678f9a3c3a59f9118d5f278fefa238950ea26786faaf42d3d17096c81c89a78e&quot;
  eth1_data:
    deposit_root: &quot;0x4e422cc0aaad3a3a9f4e415a68f1286df79ea6a95326f73b6822bad8eeae6508&quot;
    deposit_count: &quot;68&quot;
    block_hash: &quot;0x64bb0a98a090f4763a6709b870b3366512db0c089547e1d2bfdefb531e7d08ba&quot;
  block_height: 69
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x59fc60d715f9f381f553928b5bab510c59f2b5763bc27115827930abc8fa06e1&quot;
    deposit_root: &quot;0x4e422cc0aaad3a3a9f4e415a68f1286df79ea6a95326f73b6822bad8eeae6508&quot;
    deposit_count: 68
    execution_block_hash: &quot;0x64bb0a98a090f4763a6709b870b3366512db0c089547e1d2bfdefb531e7d08ba&quot;
    execution_block_height: 69
- deposit_data:
    pubkey: &quot;0xaa241b2afbb33f92a5d281aec9c8bac8997c1dddc051455fc0f334de48320f160b5029b552495aed21ed9ce252aab499&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x96e8e6ad4c9339471b4133f16fa80c48183a4bb54ae9f7097766112005375693dcbc459050d4a20a88a4d72601ea171402dbb3b934fecfc4e90c8aa8d9a20818086b126f0c72bf8eff58008aabec8834f8b252660289b818c1724b8fe6f75fbb&quot;
  deposit_data_root: &quot;0x27dfc1b46bf479c37bdfd8fdd34ab1f760dd118b031edd608a5b09e217f67bc1&quot;
  eth1_data:
    deposit_root: &quot;0x1878ee9b4d268fd60d60bbfa65e807f1e45331dfb13dcacc489de9dfc27f4a23&quot;
    deposit_count: &quot;69&quot;
    block_hash: &quot;0x899a35f3d719b2eb46085aea5820429a4ea164cc9092f096418df37fc8d5b3c4&quot;
  block_height: 70
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x59fc60d715f9f381f553928b5bab510c59f2b5763bc27115827930abc8fa06e1&quot;
      - &quot;0x27dfc1b46bf479c37bdfd8fdd34ab1f760dd118b031edd608a5b09e217f67bc1&quot;
    deposit_root: &quot;0x1878ee9b4d268fd60d60bbfa65e807f1e45331dfb13dcacc489de9dfc27f4a23&quot;
    deposit_count: 69
    execution_block_hash: &quot;0x899a35f3d719b2eb46085aea5820429a4ea164cc9092f096418df37fc8d5b3c4&quot;
    execution_block_height: 70
- deposit_data:
    pubkey: &quot;0x974b2aed17665e51c1c091998ca9649875330947de3d2733a5bd2eda69b0c593cdac2e416993a87f9a17aec1ccdc2368&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9695b7d689cb75c10edc7a6e7b9e03b802ed7e9256d589a7f5f2d192454a4b58000972109d812ca067b62caace91281714a783bcd8233414a5ca9abd3ff3e8b59d51b383079a61e3a5f9529f279d9e1f4fd818ad3daea046e883a9c0bbdd1b6c&quot;
  deposit_data_root: &quot;0xa827f1f12751ca75d95a814694177e948d61bb11d675d3730f8cdc8889329c71&quot;
  eth1_data:
    deposit_root: &quot;0x93fe27d7e2eb9366225f56a794563f4dfcf3696253dc58eb25eb54d0c0eb9def&quot;
    deposit_count: &quot;70&quot;
    block_hash: &quot;0x1ba29709a4d5765dd8ffdee19aa7407fd25c7173a3f71e5c7920f3f5ca941b49&quot;
  block_height: 71
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x59fc60d715f9f381f553928b5bab510c59f2b5763bc27115827930abc8fa06e1&quot;
      - &quot;0xee50b240458527c727db7672bbeebac6a3d40f017fabafb80c39bc12ad50df21&quot;
    deposit_root: &quot;0x93fe27d7e2eb9366225f56a794563f4dfcf3696253dc58eb25eb54d0c0eb9def&quot;
    deposit_count: 70
    execution_block_hash: &quot;0x1ba29709a4d5765dd8ffdee19aa7407fd25c7173a3f71e5c7920f3f5ca941b49&quot;
    execution_block_height: 71
- deposit_data:
    pubkey: &quot;0xa3177a98f653cea646f525f0f13348efb27e0d3d0cd824704c91d8d959096d259c9e577298f444acc629920c9619be50&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9985fe391e73d35c8044754de668b3113d8c341bcb04acbd6eddf8b683ea0fe5dc163b434243cb6ff5588a2d4146b1151851bd39edfe532a31a3b81afc644f3ae781ff2f6e73bca955fe47fa4029f8759ab2a6784e1eade8f34c97223bab6af2&quot;
  deposit_data_root: &quot;0x679b8078ff958c2a06ded461b6891f5a8038dc16adc475ba5867998a7d14adfa&quot;
  eth1_data:
    deposit_root: &quot;0x5173afe39bf20d7f26ab0d805059f50e0024f037cbc446e12171978d8d87e863&quot;
    deposit_count: &quot;71&quot;
    block_hash: &quot;0x7ed23cf2347fbaf8084d0c9b4acd2a88a5b793a68c7dd50d00627d4d6ad91457&quot;
  block_height: 72
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x59fc60d715f9f381f553928b5bab510c59f2b5763bc27115827930abc8fa06e1&quot;
      - &quot;0xee50b240458527c727db7672bbeebac6a3d40f017fabafb80c39bc12ad50df21&quot;
      - &quot;0x679b8078ff958c2a06ded461b6891f5a8038dc16adc475ba5867998a7d14adfa&quot;
    deposit_root: &quot;0x5173afe39bf20d7f26ab0d805059f50e0024f037cbc446e12171978d8d87e863&quot;
    deposit_count: 71
    execution_block_hash: &quot;0x7ed23cf2347fbaf8084d0c9b4acd2a88a5b793a68c7dd50d00627d4d6ad91457&quot;
    execution_block_height: 72
- deposit_data:
    pubkey: &quot;0xa8a18565733e70663c77bc0c80e08f50de908cc048152f1e7dae85d8cc218afbdd337d7d33a44e25400be2f06907c64a&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x905cb27fd1bed206b261cb543ffd3fbed57f5b9d938c4dc488e1bd34d198395bbaf1237cf183cc73f5c8e2e31d20d4c40e191278661c85adfb507024b5e9a5dc3ebbed92e8aaa85c0cfc6df6b05375c26b2f49a8f695ac156bff342bf16fc4cc&quot;
  deposit_data_root: &quot;0x8bc78f4a029e716370a431e7034b9fa1991e36246d00fbf41a1dfeaba5748f67&quot;
  eth1_data:
    deposit_root: &quot;0xd09cddcb5675f6c5affff8a42f1fe425994bbe9133443d3f5516f8b34a9d0ba9&quot;
    deposit_count: &quot;72&quot;
    block_hash: &quot;0x16925bb1988c358148331ce34f247a985c829d8c14bed9481998942083cfe783&quot;
  block_height: 73
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0xa1e9ca708d13a0c759703ba39fd1bcb39b5114273ca6dfff1e76d5c2c687b2c9&quot;
    deposit_root: &quot;0xd09cddcb5675f6c5affff8a42f1fe425994bbe9133443d3f5516f8b34a9d0ba9&quot;
    deposit_count: 72
    execution_block_hash: &quot;0x16925bb1988c358148331ce34f247a985c829d8c14bed9481998942083cfe783&quot;
    execution_block_height: 73
- deposit_data:
    pubkey: &quot;0x902ff56a7a4c5b6cc57708ea7b0b72cb54e4b821c95373f503648185f15208f6ca6281677fa0ecc14f911d7b7ca04f4e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x84b716bac859e61b80e0cfd3fc484d59c2865794d11e3264d58d6c4d2af2e2eef12a94944f331a4b3c83221a5d1fba2e10fa236515db3d9eaf92c4ff9c118cf73f0cb59b4c7b14f253e7c7b7b2cd0d23f659c24bd4f37a99ac82bed18c56e8cb&quot;
  deposit_data_root: &quot;0xa23bbf261e1427b5532adfeba387f89d35f66f776af44be7f183d06af0e55828&quot;
  eth1_data:
    deposit_root: &quot;0x44c70c125786b9ab6f938ecab3227d21da2ed26f1a1677f8f78e4058dc721403&quot;
    deposit_count: &quot;73&quot;
    block_hash: &quot;0x869606a66fc329f9076cc7257a61018e04b6a6c658298c65de81f67bf6990a4c&quot;
  block_height: 74
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0xa1e9ca708d13a0c759703ba39fd1bcb39b5114273ca6dfff1e76d5c2c687b2c9&quot;
      - &quot;0xa23bbf261e1427b5532adfeba387f89d35f66f776af44be7f183d06af0e55828&quot;
    deposit_root: &quot;0x44c70c125786b9ab6f938ecab3227d21da2ed26f1a1677f8f78e4058dc721403&quot;
    deposit_count: 73
    execution_block_hash: &quot;0x869606a66fc329f9076cc7257a61018e04b6a6c658298c65de81f67bf6990a4c&quot;
    execution_block_height: 74
- deposit_data:
    pubkey: &quot;0x98f011f9a4dff94eb0352ff6e21b7df45e2a112bd5d789b5729111b89b368e7ed554e4d1c16b72f4d105090173cafed2&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x89641c38182c333a0485aeb0c4eb6f399a3581d19b33370522623d4c827de1cd5dc79c510a7e5bcd33f4d7a12bc6ef101630d2e4bfdf28c89b974c3927c314d118a345a3c424d0b3680c2de454e0e95f1d9c96565c2a7d771af7e8baddd25f02&quot;
  deposit_data_root: &quot;0x65569e8f6db92744dd0abfbbc30a083986f842aa23cc02408099f2b586a3ed1d&quot;
  eth1_data:
    deposit_root: &quot;0x727ba31c7148e93fea338887cb4cc053a8eaa60dbd3dfc15607e837a845b38e8&quot;
    deposit_count: &quot;74&quot;
    block_hash: &quot;0xa68c064f8ee59d1857ae8a3a8eea5b59bce083fcde164fed763ac2ab30e51f90&quot;
  block_height: 75
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0xa1e9ca708d13a0c759703ba39fd1bcb39b5114273ca6dfff1e76d5c2c687b2c9&quot;
      - &quot;0x8b4eb1bbcf79beaf6350d27870239dac66f0155fb7f8807a1f2b96afbba18f03&quot;
    deposit_root: &quot;0x727ba31c7148e93fea338887cb4cc053a8eaa60dbd3dfc15607e837a845b38e8&quot;
    deposit_count: 74
    execution_block_hash: &quot;0xa68c064f8ee59d1857ae8a3a8eea5b59bce083fcde164fed763ac2ab30e51f90&quot;
    execution_block_height: 75
- deposit_data:
    pubkey: &quot;0xabef42538a17a55804b634aac9d211b92b5768c4cc1263342ca287323bb3d5c768080451d1b5d652e9f8646fbb35f57c&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa7bc665e4424cf5e48e6b1dcc5f9d85e9f44ccb12690969a548fc0835b2fcdb6d587c997696e19fdc16ecb8c9b8a9d4810795c716232c2a2839845cabb70ff78aedab16d3ae55751c4b75a64dcbd5b630b652308300313457176c99889436d94&quot;
  deposit_data_root: &quot;0x2da83bfca1b961cbe477157ccb844db21392e1fb44822b1b330c686984e85586&quot;
  eth1_data:
    deposit_root: &quot;0xc7a1f21839a10b008b4503cfd0e8f57dc67b83642e8ed9aa1d9f042821f22b01&quot;
    deposit_count: &quot;75&quot;
    block_hash: &quot;0xf7b4c7f12fe8c83d3546300a2bbf4a01034fc10eaf79295db8dc9e1b36c9a20e&quot;
  block_height: 76
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0xa1e9ca708d13a0c759703ba39fd1bcb39b5114273ca6dfff1e76d5c2c687b2c9&quot;
      - &quot;0x8b4eb1bbcf79beaf6350d27870239dac66f0155fb7f8807a1f2b96afbba18f03&quot;
      - &quot;0x2da83bfca1b961cbe477157ccb844db21392e1fb44822b1b330c686984e85586&quot;
    deposit_root: &quot;0xc7a1f21839a10b008b4503cfd0e8f57dc67b83642e8ed9aa1d9f042821f22b01&quot;
    deposit_count: 75
    execution_block_hash: &quot;0xf7b4c7f12fe8c83d3546300a2bbf4a01034fc10eaf79295db8dc9e1b36c9a20e&quot;
    execution_block_height: 76
- deposit_data:
    pubkey: &quot;0xa8e3c2d3ac4e0e3c83380577ff7b7b5b2a98571e0d04ddebc0a6c472ce3bc5cc6a6733be728a0ee17da74b7691d2679d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb2719b1ed9259b55d519158388e8cfd749a186c6247c2a637848e133d761ad6b105e27d3f1a950455d8abaaccb756e6016c838c3ed0abbb9a0bc966ef6f58e681d232cedd792c2b19cb3d17a5240a16b97c62ce29682c078131b67143878d02f&quot;
  deposit_data_root: &quot;0xbd2182e7a29009df9034c125e8e09f7f6e3b862944aab607f84d64545ab002e4&quot;
  eth1_data:
    deposit_root: &quot;0xee5ee677dd7394ae7c9548383112262e9af48b1f84a109a1e42ca1a1fc57e527&quot;
    deposit_count: &quot;76&quot;
    block_hash: &quot;0xdd2ed41e4e3336c4afb390d9c8572db1a2d5d403b470eb88a3a85df3bbbd107f&quot;
  block_height: 77
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0xa1e9ca708d13a0c759703ba39fd1bcb39b5114273ca6dfff1e76d5c2c687b2c9&quot;
      - &quot;0xee021dc6246d96e341b4df28f5db26a62e2d9716eb92394f5bd7fa7e246fa85e&quot;
    deposit_root: &quot;0xee5ee677dd7394ae7c9548383112262e9af48b1f84a109a1e42ca1a1fc57e527&quot;
    deposit_count: 76
    execution_block_hash: &quot;0xdd2ed41e4e3336c4afb390d9c8572db1a2d5d403b470eb88a3a85df3bbbd107f&quot;
    execution_block_height: 77
- deposit_data:
    pubkey: &quot;0x98f620aadc4e58392b5b583fed96c452b54c39ba3a9fe8c277f625fae7e1317d034f732995fd88c1461463edd0f2b86d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xabd8b07d34a93e4dc68fe6115af72218e56ad477e848d0d1036114aee03cba10ab561d1570bae237d94ff4d6aa029c760cf2ceda174bbce181ca2e9ede9b7f6a466d2e2d4a38b7367124bc70c887b69770938d3f82c7263b70d0ab960438afa8&quot;
  deposit_data_root: &quot;0xdaa5f5480bd46b815e89b67e6ccb84dab0b44ccdc687017785f0b26647eb2da9&quot;
  eth1_data:
    deposit_root: &quot;0x85ee92997d8c724afd6bfd6078f6b2fa8aacf96a8e98018ea21832f3b4df7d56&quot;
    deposit_count: &quot;77&quot;
    block_hash: &quot;0xf3f609e1b0e8c5ce0c404929cf2146d97e053f2a7c4dc186701fca3c81c79424&quot;
  block_height: 78
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0xa1e9ca708d13a0c759703ba39fd1bcb39b5114273ca6dfff1e76d5c2c687b2c9&quot;
      - &quot;0xee021dc6246d96e341b4df28f5db26a62e2d9716eb92394f5bd7fa7e246fa85e&quot;
      - &quot;0xdaa5f5480bd46b815e89b67e6ccb84dab0b44ccdc687017785f0b26647eb2da9&quot;
    deposit_root: &quot;0x85ee92997d8c724afd6bfd6078f6b2fa8aacf96a8e98018ea21832f3b4df7d56&quot;
    deposit_count: 77
    execution_block_hash: &quot;0xf3f609e1b0e8c5ce0c404929cf2146d97e053f2a7c4dc186701fca3c81c79424&quot;
    execution_block_height: 78
- deposit_data:
    pubkey: &quot;0xa7f5d408af436d71ec7acfe9a4592679649d326c00ac92c6f3332423be30c3601d232f265078f1f2a5d6d6cde08de7d7&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb3b301cd266d7dd40fed80f8f1609ca35256d263b00b16eed767dfe5ea8116eef1f6cb7f25028c98a9b28357b56ae1890b418858a4500034887ef60b7cf0f8b0f7a8718d450687316f7397632a3c167ecdb2db26694a8608ae06b0dc782e9c7b&quot;
  deposit_data_root: &quot;0x19f237b217967fe4d2ddbc826bf6e2c33687cea82a120e7b85e412d7e137d579&quot;
  eth1_data:
    deposit_root: &quot;0x5ad46efc2ae1bd120b59461c83d8799b741ad5000b754d6f9c20de9115890054&quot;
    deposit_count: &quot;78&quot;
    block_hash: &quot;0xbf4d50dea5661ab07e15967d8fa2c51cc55395749405ccb6a252ee68f8be1e01&quot;
  block_height: 79
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0xa1e9ca708d13a0c759703ba39fd1bcb39b5114273ca6dfff1e76d5c2c687b2c9&quot;
      - &quot;0xee021dc6246d96e341b4df28f5db26a62e2d9716eb92394f5bd7fa7e246fa85e&quot;
      - &quot;0x1d7bb861e983c4afb9abbd3c0f7546b0b8e381c2d7679f6993d4ef95f55f8127&quot;
    deposit_root: &quot;0x5ad46efc2ae1bd120b59461c83d8799b741ad5000b754d6f9c20de9115890054&quot;
    deposit_count: 78
    execution_block_hash: &quot;0xbf4d50dea5661ab07e15967d8fa2c51cc55395749405ccb6a252ee68f8be1e01&quot;
    execution_block_height: 79
- deposit_data:
    pubkey: &quot;0xa8be337b3d0e6be415dcb037b246831f9966aacef62b69d6b609e4ff8208bc536c6473bc9fe9e3bec9a8665c8caa05c5&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xac120d0e117e12d4af2ed041f4f7bac11ccafbdfdc4047808b83defc328196994afab43ec6581e6e88ce3eade65dab2a11618290151258cfb017fe15ea630f10d3c388c8b8e86a391a82f34c58974509e1b476876bba5b9d5f2c2a6b4682418d&quot;
  deposit_data_root: &quot;0xaf7bcef44525d9887a3a9982947bcf876e369190201ca2ea096bedf13edf353f&quot;
  eth1_data:
    deposit_root: &quot;0x8949d7d74a871960abf40a678878aa93c2d2a3e38bb9fcc9a055d19f434d9cbc&quot;
    deposit_count: &quot;79&quot;
    block_hash: &quot;0x881de104237f77e44ad277325f56e42735a577d9ea660124ecb08597585991ee&quot;
  block_height: 80
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0xa1e9ca708d13a0c759703ba39fd1bcb39b5114273ca6dfff1e76d5c2c687b2c9&quot;
      - &quot;0xee021dc6246d96e341b4df28f5db26a62e2d9716eb92394f5bd7fa7e246fa85e&quot;
      - &quot;0x1d7bb861e983c4afb9abbd3c0f7546b0b8e381c2d7679f6993d4ef95f55f8127&quot;
      - &quot;0xaf7bcef44525d9887a3a9982947bcf876e369190201ca2ea096bedf13edf353f&quot;
    deposit_root: &quot;0x8949d7d74a871960abf40a678878aa93c2d2a3e38bb9fcc9a055d19f434d9cbc&quot;
    deposit_count: 79
    execution_block_hash: &quot;0x881de104237f77e44ad277325f56e42735a577d9ea660124ecb08597585991ee&quot;
    execution_block_height: 80
- deposit_data:
    pubkey: &quot;0x93bb1c86717fa7303f65cb8c45c9fcc8fecb88428b7cd1dd59967a132109c25ab5c97888e46c5d471ff911c573f45a34&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb4ac35f3fb67d9a5ee84dbafbbe9fc2cc173b4198d3369a3ea40b745ff645c269ab3e8742b4033763d59aa88042ed040189f8093e55e38d0e202093c73bf469a35af5a340647247ce3377b213c6b2505bba028436173fd09ee845305a906af95&quot;
  deposit_data_root: &quot;0x65440def2a2b71e4e27356ec9dc2a661d5f937f8f0543a8e76c7a8dcb7d8e500&quot;
  eth1_data:
    deposit_root: &quot;0x2a8a1fb507e33b36be62ba505ce068295dbf1d40538474fb1446b02643b8dd4f&quot;
    deposit_count: &quot;80&quot;
    block_hash: &quot;0x53a3edf49a1a316d10285385209c510be04cde3a50f816beeb5da44196e426ac&quot;
  block_height: 81
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x9cdee5c9ecd1ef9a54feb904550ef7271277dcbc43318688b0b0f4b0454c5a95&quot;
    deposit_root: &quot;0x2a8a1fb507e33b36be62ba505ce068295dbf1d40538474fb1446b02643b8dd4f&quot;
    deposit_count: 80
    execution_block_hash: &quot;0x53a3edf49a1a316d10285385209c510be04cde3a50f816beeb5da44196e426ac&quot;
    execution_block_height: 81
- deposit_data:
    pubkey: &quot;0x815042c33c1a43c1ee58a58ee074bc93a13c23a035dedee6879730220379d0c03ff4a3829240b6c34e56feb55cd322df&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x951ce0fb4767567fdc4ac1c2b999d39624eb1915b3f74939685a99a30b99212f57eb17b163e3544d1524ada89d3d4fc9195163d5877a53b1d62fa210327eddb6b42150527df562ac5a67a0de3e59e3696a129c3c71c21240b584fe60cae66142&quot;
  deposit_data_root: &quot;0x6a9f3213a02e902c041ba8261f093e6c100dceca1ce46fc91420ca0c0a900f20&quot;
  eth1_data:
    deposit_root: &quot;0xcec66765569321e99f2a977b9ea2864097333eed6bc258e903142b60a8605ea8&quot;
    deposit_count: &quot;81&quot;
    block_hash: &quot;0x4a84e0118e1e4ec671bc23c123591f08b2ad83363a68941d1fcc2073a50d715f&quot;
  block_height: 82
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x9cdee5c9ecd1ef9a54feb904550ef7271277dcbc43318688b0b0f4b0454c5a95&quot;
      - &quot;0x6a9f3213a02e902c041ba8261f093e6c100dceca1ce46fc91420ca0c0a900f20&quot;
    deposit_root: &quot;0xcec66765569321e99f2a977b9ea2864097333eed6bc258e903142b60a8605ea8&quot;
    deposit_count: 81
    execution_block_hash: &quot;0x4a84e0118e1e4ec671bc23c123591f08b2ad83363a68941d1fcc2073a50d715f&quot;
    execution_block_height: 82
- deposit_data:
    pubkey: &quot;0x8be11e9ead2e1bb5be7e2ec066ff83589558a5d9373666b3fc518a6a6639b3baecb87f8f34895f63e8d09d270d93ce04&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8a9863487be81d3b7a8fb0ce2d141843c43751e3f030529f2cd271968671da68c520bf86e8ad56786cf4df9023bd80380bbe0bf6eea87b99a2dc70d3de0d4bb1507fd4fb8f3aca17ac37b71bb11c0cb003cea26a38fd84a2da2e6a9922ef8472&quot;
  deposit_data_root: &quot;0x27dc8639ac98670dc00960901ffe78d2ac05ef71bebf1734b839f89f24137300&quot;
  eth1_data:
    deposit_root: &quot;0xf34475554a62ca5b35a9a0c54a8abab231ae1f7db3098144154435c6d5d51d23&quot;
    deposit_count: &quot;82&quot;
    block_hash: &quot;0xdc459617e7f73073e5134da264c9ddad3ea4fed09245b90f13ba139a899bbb85&quot;
  block_height: 83
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x9cdee5c9ecd1ef9a54feb904550ef7271277dcbc43318688b0b0f4b0454c5a95&quot;
      - &quot;0xe1af0aab0c08eb08233a563ec4bff65ad501d92c9a40ce2dc785d145c76117b2&quot;
    deposit_root: &quot;0xf34475554a62ca5b35a9a0c54a8abab231ae1f7db3098144154435c6d5d51d23&quot;
    deposit_count: 82
    execution_block_hash: &quot;0xdc459617e7f73073e5134da264c9ddad3ea4fed09245b90f13ba139a899bbb85&quot;
    execution_block_height: 83
- deposit_data:
    pubkey: &quot;0x8bf2630491d2a480ec243b00d65d76e69615e67d3df5d8c14ca7506edd8e896a9083e8ee9e4129af0f6d896a3225c08c&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa12d975029e83dba3b911bea41a5f1090fbd2129472a2244171f57ad1fe0f44043d36cd99501aade7f9ed8ce2b36b567025b63e075edf6ebfa4ea3b262ada83fa8872244bb5fcd4f61faf576bfd704bbbf7c1729610a10f1b316a2edcab8f2a1&quot;
  deposit_data_root: &quot;0x1657e7e852988d74eadcdd365213af142142f68dfb32ae071af7b9640a7b1724&quot;
  eth1_data:
    deposit_root: &quot;0xfcaec4c59f62d7cb9fdc1539228db986aaeaf6ce6182e9356d0d7ac9554cc5b7&quot;
    deposit_count: &quot;83&quot;
    block_hash: &quot;0x1b1fcd8f43efc0746a5c9a5e6069bcad198f4fb06ea4aa27fb2099886f74ea92&quot;
  block_height: 84
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x9cdee5c9ecd1ef9a54feb904550ef7271277dcbc43318688b0b0f4b0454c5a95&quot;
      - &quot;0xe1af0aab0c08eb08233a563ec4bff65ad501d92c9a40ce2dc785d145c76117b2&quot;
      - &quot;0x1657e7e852988d74eadcdd365213af142142f68dfb32ae071af7b9640a7b1724&quot;
    deposit_root: &quot;0xfcaec4c59f62d7cb9fdc1539228db986aaeaf6ce6182e9356d0d7ac9554cc5b7&quot;
    deposit_count: 83
    execution_block_hash: &quot;0x1b1fcd8f43efc0746a5c9a5e6069bcad198f4fb06ea4aa27fb2099886f74ea92&quot;
    execution_block_height: 84
- deposit_data:
    pubkey: &quot;0x914b56f41c411fbfca9dc9763f44daf253c103b162457d07954fd0af768b5e74692b4639c22455fb81d71f7ed6144514&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xabbd26d91fb83232422509d6ca45b721185fa61fe610027a06c510dec708eea6cf54d1d955b676f5b77b141a6696f18d18b7336ede4da02504ca96e3363ce3c91698ffcf904c9f3c9d31648c79263acacb9747d7069d79016791b4facce83555&quot;
  deposit_data_root: &quot;0x4123a31554edb843e51c2c6d3d608693fda4d5def338ade6425f1790fb511774&quot;
  eth1_data:
    deposit_root: &quot;0x15754d151c1cae6449d10e2e95489aeab66d5defa0f19c29635f0319ff830a28&quot;
    deposit_count: &quot;84&quot;
    block_hash: &quot;0xa18fcf7a630b971e354e7c3661f21b45306ba7ff6d02a67a7a9fdce708a97805&quot;
  block_height: 85
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x9cdee5c9ecd1ef9a54feb904550ef7271277dcbc43318688b0b0f4b0454c5a95&quot;
      - &quot;0x78b501b3fa5475f83b94eafea06a4d859d98ca9dd9efb1f7c9f440868791c620&quot;
    deposit_root: &quot;0x15754d151c1cae6449d10e2e95489aeab66d5defa0f19c29635f0319ff830a28&quot;
    deposit_count: 84
    execution_block_hash: &quot;0xa18fcf7a630b971e354e7c3661f21b45306ba7ff6d02a67a7a9fdce708a97805&quot;
    execution_block_height: 85
- deposit_data:
    pubkey: &quot;0x8794388915e86e4988363cdd4289ad19182209c873cbbbf5a80ff5c99f93acb839807787a77ad2b603f074405d7ed08b&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x87e0e8c98f9e186d31d992634611b6d08376911636fd1d689b01330e70b4a9c819ddaef93128bb333bfdaf9e6e2697550897b9be994b5033b6397989e1db1b7db9d889083f4ad1c763192da282943f571d77781ef46364757151aeae27740ac8&quot;
  deposit_data_root: &quot;0x55aa7b5a4c6d119979913fa560116bd32289f6636e12f6056017cdef97b55682&quot;
  eth1_data:
    deposit_root: &quot;0xfa36dc4e7091338e1af1a655d7f73c8a4a31453769962a8335196409cdd05552&quot;
    deposit_count: &quot;85&quot;
    block_hash: &quot;0x6706a23dd2a500b2856ef97cdee6757a46ab118f06df889d50afc259c7938558&quot;
  block_height: 86
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x9cdee5c9ecd1ef9a54feb904550ef7271277dcbc43318688b0b0f4b0454c5a95&quot;
      - &quot;0x78b501b3fa5475f83b94eafea06a4d859d98ca9dd9efb1f7c9f440868791c620&quot;
      - &quot;0x55aa7b5a4c6d119979913fa560116bd32289f6636e12f6056017cdef97b55682&quot;
    deposit_root: &quot;0xfa36dc4e7091338e1af1a655d7f73c8a4a31453769962a8335196409cdd05552&quot;
    deposit_count: 85
    execution_block_hash: &quot;0x6706a23dd2a500b2856ef97cdee6757a46ab118f06df889d50afc259c7938558&quot;
    execution_block_height: 86
- deposit_data:
    pubkey: &quot;0xa3862121db5914d7272b0b705e6e3c5336b79e316735661873566245207329c30f9a33d4fb5f5857fc6fd0a368186972&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x86fc69a33aaa4221dd112b9c1d69633430d803b55fd0e046d17e9ecc02a53d05429034baeb7d235bc76573449bdd7d0d05c80a3cb7e785f1a06b40cea3fbf66ceefc0a542983a92a609051580f48980a42f3cd43703b810f0f5ee8b5c2a5e556&quot;
  deposit_data_root: &quot;0xead7c5895bcb78cb6bf3b7dd8c3e984cd33de92cedafcbfb11821d725a1a7008&quot;
  eth1_data:
    deposit_root: &quot;0x55993260810877f669acb1d186a3b2e6715d9ff9d948cdc4da03a0515dd3fb03&quot;
    deposit_count: &quot;86&quot;
    block_hash: &quot;0xa2ec2792a7481050df8e4c66e3049fa01b122a59b4b0da16eefb2160122bd887&quot;
  block_height: 87
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x9cdee5c9ecd1ef9a54feb904550ef7271277dcbc43318688b0b0f4b0454c5a95&quot;
      - &quot;0x78b501b3fa5475f83b94eafea06a4d859d98ca9dd9efb1f7c9f440868791c620&quot;
      - &quot;0x05fdfe681bbf2653770a5add8d5a186497090b0852abfc6d2b5c7cd9c2cd48b4&quot;
    deposit_root: &quot;0x55993260810877f669acb1d186a3b2e6715d9ff9d948cdc4da03a0515dd3fb03&quot;
    deposit_count: 86
    execution_block_hash: &quot;0xa2ec2792a7481050df8e4c66e3049fa01b122a59b4b0da16eefb2160122bd887&quot;
    execution_block_height: 87
- deposit_data:
    pubkey: &quot;0x96ef954b331a534199f4f113d993a50ec7a781fc5aa2a181ea0bdbfd4c5c557abfebfcc02604d5aef52ba64afbe0ff18&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb64dc6b6527edca3c16cf0dd04aeda244d69cb84a96e951ed1a7286c0a8ee24b56d4651e14e03d472ae3ed0cc9928dc40c5947e185e67716db8e8bd4c85bb5ee4bd14102347117b90276620bda17f0a68b6ff225842814a7e0f15e920350725a&quot;
  deposit_data_root: &quot;0xf962e2d35918b11c748e47d10d66e0e052bfb45965a88ca185044e820b33f0e4&quot;
  eth1_data:
    deposit_root: &quot;0x1e14f4e10d68971bf523b164e176f135b1304cfa07c88a57233d8b39a6c83456&quot;
    deposit_count: &quot;87&quot;
    block_hash: &quot;0x3a5d185a584fc74290efc7f9f7781c00d96708e925061731d5e083d44ee009f7&quot;
  block_height: 88
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x9cdee5c9ecd1ef9a54feb904550ef7271277dcbc43318688b0b0f4b0454c5a95&quot;
      - &quot;0x78b501b3fa5475f83b94eafea06a4d859d98ca9dd9efb1f7c9f440868791c620&quot;
      - &quot;0x05fdfe681bbf2653770a5add8d5a186497090b0852abfc6d2b5c7cd9c2cd48b4&quot;
      - &quot;0xf962e2d35918b11c748e47d10d66e0e052bfb45965a88ca185044e820b33f0e4&quot;
    deposit_root: &quot;0x1e14f4e10d68971bf523b164e176f135b1304cfa07c88a57233d8b39a6c83456&quot;
    deposit_count: 87
    execution_block_hash: &quot;0x3a5d185a584fc74290efc7f9f7781c00d96708e925061731d5e083d44ee009f7&quot;
    execution_block_height: 88
- deposit_data:
    pubkey: &quot;0x96c8d3dd08724624017f178393d176b425dab9dfa1cc3f62c7669337446baa601e0aa261c00c76bde07ba9a1a3582c0a&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb37b23e995a74a1c72a6e5d0dc75aa44d3e560c5c3aeaac78648ccdd38380e68b321cfc39555af65cdc2dbaadf3eace20011622070f90f2e782e5edff8330c8b3d8623fbf58fb878e0645f3588b3f75b293fc5f8051d7c324ccb9df12b48a07c&quot;
  deposit_data_root: &quot;0x0b8d152337bd30a81e3353cd2ef3767d4a3f6b84c124010ec8eb784591158e17&quot;
  eth1_data:
    deposit_root: &quot;0x4800ae85e0ddc8eb4927b7c3ac52f3718e7a47eee6b9490d4d974deff6b09f16&quot;
    deposit_count: &quot;88&quot;
    block_hash: &quot;0x6bf5193552720db315898ec262ab1cfd7590e13a88ae86efc702243acfc001b8&quot;
  block_height: 89
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x9cdee5c9ecd1ef9a54feb904550ef7271277dcbc43318688b0b0f4b0454c5a95&quot;
      - &quot;0xe78ee87ce4f2c19b2b27b0e4d875fb21bf9580e9b8e683f34db124274f263dc5&quot;
    deposit_root: &quot;0x4800ae85e0ddc8eb4927b7c3ac52f3718e7a47eee6b9490d4d974deff6b09f16&quot;
    deposit_count: 88
    execution_block_hash: &quot;0x6bf5193552720db315898ec262ab1cfd7590e13a88ae86efc702243acfc001b8&quot;
    execution_block_height: 89
- deposit_data:
    pubkey: &quot;0x92bd81b8e9099b9ca87a2033fdd84475752dc34a0fae0a8e50aabf4d3baff9cd45ed56508c837023944350f53dbc4ac7&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x88835cc0416f137bf06133717762b9bda8e31f66b6910eb55a8eae0a4d97bb8d51284a8c4038da5e2b15b77e3beaee6b09d1561bb5bf1ff2cd2f7e6396cb80c520f161f43fb01dc259f5e2c2f33dc632ff1a6a14b46cade75b0850d3841e666c&quot;
  deposit_data_root: &quot;0xd3fbf626f2db8d53f0cfa2e8ab199e5633cbc1b1bc01dd5579000ae8b4c59525&quot;
  eth1_data:
    deposit_root: &quot;0xe83ff8243a690675111ffaa012be7ff8931efd74d0d29c99f7c543db94fb2e68&quot;
    deposit_count: &quot;89&quot;
    block_hash: &quot;0x1b93e72ce9ac8a2eaf1c6b6e8ceb0d413e084b62ab3b65a33414f794c6bca144&quot;
  block_height: 90
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x9cdee5c9ecd1ef9a54feb904550ef7271277dcbc43318688b0b0f4b0454c5a95&quot;
      - &quot;0xe78ee87ce4f2c19b2b27b0e4d875fb21bf9580e9b8e683f34db124274f263dc5&quot;
      - &quot;0xd3fbf626f2db8d53f0cfa2e8ab199e5633cbc1b1bc01dd5579000ae8b4c59525&quot;
    deposit_root: &quot;0xe83ff8243a690675111ffaa012be7ff8931efd74d0d29c99f7c543db94fb2e68&quot;
    deposit_count: 89
    execution_block_hash: &quot;0x1b93e72ce9ac8a2eaf1c6b6e8ceb0d413e084b62ab3b65a33414f794c6bca144&quot;
    execution_block_height: 90
- deposit_data:
    pubkey: &quot;0x83802cd575a3cea7e3e38fc1a73d94a9e4fdb999b8494e7929309c009d79a23edb1ba091ac02588f130e0585fb106540&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x90b696dc285957fee877e14c40dcd159622b4522ddb9e31d10f5d89d83af25c7a65de87deb816ec3fea86251c38247bd03e0e4e083e8ce7b63ed5917fd5b7a8bcea01ed61b3234b62eb0baeaf253cc04655cd5b64e7d642a3bc7be5e4a32634a&quot;
  deposit_data_root: &quot;0x58ea01dac688f2b29e401e7edb6319c7017d12c8adc57b372865b40d907be8d6&quot;
  eth1_data:
    deposit_root: &quot;0xd8b0fc873ba2d2d52ef3e7985d6ef0cc924ce56c852970823814b95892805127&quot;
    deposit_count: &quot;90&quot;
    block_hash: &quot;0x666278a6a24e797f1040470692822b240b2630b0af2a38c26da23f727af7780d&quot;
  block_height: 91
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x9cdee5c9ecd1ef9a54feb904550ef7271277dcbc43318688b0b0f4b0454c5a95&quot;
      - &quot;0xe78ee87ce4f2c19b2b27b0e4d875fb21bf9580e9b8e683f34db124274f263dc5&quot;
      - &quot;0xe2fdce2d1fdc2fe192bb4aa9293cebebd50dc5e78e38a1bbc1b9b4fd39e22985&quot;
    deposit_root: &quot;0xd8b0fc873ba2d2d52ef3e7985d6ef0cc924ce56c852970823814b95892805127&quot;
    deposit_count: 90
    execution_block_hash: &quot;0x666278a6a24e797f1040470692822b240b2630b0af2a38c26da23f727af7780d&quot;
    execution_block_height: 91
- deposit_data:
    pubkey: &quot;0xb451eb0ff4990917aba6e3d80c34aee91ea1ce49053f38ae174cef107cb9acc595d0ca3fefcb804c9dd04510c630cabe&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xaa5e3f58c8249a0d3c8269f16af4a8fb42b20b821c1554e51443c897ff00389cb8b85cd953236bc22430ddb49e3b1d8b018926d1e5b87a614e1b9257838cecf59eac47ecfb8648c930d839b8524ade0b68036e9e9987c554cfa24417a00ffc40&quot;
  deposit_data_root: &quot;0xf11f85f05b6d4b0d8ff3bfdc09e03ece905ba6452e2e45f20c78e62652a71f6e&quot;
  eth1_data:
    deposit_root: &quot;0xc1dc1c55036f14ded17a34c5d6c82a3df5c704a067ab5d0f9d50481679c9345b&quot;
    deposit_count: &quot;91&quot;
    block_hash: &quot;0xcf447d1821972d4a820ab84a95dafa442735e577290d6f110ee498567a0a1662&quot;
  block_height: 92
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x9cdee5c9ecd1ef9a54feb904550ef7271277dcbc43318688b0b0f4b0454c5a95&quot;
      - &quot;0xe78ee87ce4f2c19b2b27b0e4d875fb21bf9580e9b8e683f34db124274f263dc5&quot;
      - &quot;0xe2fdce2d1fdc2fe192bb4aa9293cebebd50dc5e78e38a1bbc1b9b4fd39e22985&quot;
      - &quot;0xf11f85f05b6d4b0d8ff3bfdc09e03ece905ba6452e2e45f20c78e62652a71f6e&quot;
    deposit_root: &quot;0xc1dc1c55036f14ded17a34c5d6c82a3df5c704a067ab5d0f9d50481679c9345b&quot;
    deposit_count: 91
    execution_block_hash: &quot;0xcf447d1821972d4a820ab84a95dafa442735e577290d6f110ee498567a0a1662&quot;
    execution_block_height: 92
- deposit_data:
    pubkey: &quot;0xa7f711233af57440e9ea700113fc4dbaef97e7da7741dd2e38ae668a7f2685d4585d54a9e6712ff1b87c69dbb181abf7&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa2e034a05c1d3cac573a3cd1a4d76584fe1c12dc828aa85fe6b14958efb476d2e5afe6df9f7f7b8af02f19c0f74d93fc0e94911f2152659c11246ad51e5174d1fbcd9335c60fb3097c8168793238d0e0ff710b70f7bfe7f321131271bdff8dc7&quot;
  deposit_data_root: &quot;0x548e5a3a2012b86724762a43fc45047e7e8092914d1b2188a583ca9903f96ca0&quot;
  eth1_data:
    deposit_root: &quot;0x6d4e79bc326336e3a6c8e6c421a29d877c8daa3956aa1e55a63257ab6f5f43af&quot;
    deposit_count: &quot;92&quot;
    block_hash: &quot;0x631ee71ad7fec6f24ca2a56cd1c45f6c860b4ca487b28365f65860caed0614fd&quot;
  block_height: 93
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x9cdee5c9ecd1ef9a54feb904550ef7271277dcbc43318688b0b0f4b0454c5a95&quot;
      - &quot;0xe78ee87ce4f2c19b2b27b0e4d875fb21bf9580e9b8e683f34db124274f263dc5&quot;
      - &quot;0xf5e222e2ec0403f08a8f04b439d8af9798f665fcc237f672d6e5e7484a024866&quot;
    deposit_root: &quot;0x6d4e79bc326336e3a6c8e6c421a29d877c8daa3956aa1e55a63257ab6f5f43af&quot;
    deposit_count: 92
    execution_block_hash: &quot;0x631ee71ad7fec6f24ca2a56cd1c45f6c860b4ca487b28365f65860caed0614fd&quot;
    execution_block_height: 93
- deposit_data:
    pubkey: &quot;0xaca5e4979f281b5ab0ea0f549d6dcc34989607c335e94efedeffc7e73b393f42c7b11d76144a750f82600b21d10b6777&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x90374711b91d6b7385cf3f099f5ed3a93d79383968645d9bdbb191bc461b3559df4a7bef411c33a692590ffa1aaaa91f1870a5c0d20df79f2cfaf2d5482f49f380679168f47affe35a4fac018692f5f0f007031bb3d8fef31e23a922a444d8b5&quot;
  deposit_data_root: &quot;0xfd4f2e7d7c027a545467d3a3295b2ab5ccfebc669330a533243db77cd3e8cf4c&quot;
  eth1_data:
    deposit_root: &quot;0xdda9d42bf636ae45f5c4376a0cb0b56e15846bc9119dffda44e196de5ba747e4&quot;
    deposit_count: &quot;93&quot;
    block_hash: &quot;0xcb69ea6fddd200d561ac5e304e8b08abc9b6ec65c3f0e4cccdda7f523facdd6f&quot;
  block_height: 94
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x9cdee5c9ecd1ef9a54feb904550ef7271277dcbc43318688b0b0f4b0454c5a95&quot;
      - &quot;0xe78ee87ce4f2c19b2b27b0e4d875fb21bf9580e9b8e683f34db124274f263dc5&quot;
      - &quot;0xf5e222e2ec0403f08a8f04b439d8af9798f665fcc237f672d6e5e7484a024866&quot;
      - &quot;0xfd4f2e7d7c027a545467d3a3295b2ab5ccfebc669330a533243db77cd3e8cf4c&quot;
    deposit_root: &quot;0xdda9d42bf636ae45f5c4376a0cb0b56e15846bc9119dffda44e196de5ba747e4&quot;
    deposit_count: 93
    execution_block_hash: &quot;0xcb69ea6fddd200d561ac5e304e8b08abc9b6ec65c3f0e4cccdda7f523facdd6f&quot;
    execution_block_height: 94
- deposit_data:
    pubkey: &quot;0x984620db3658a19769475080998db9e7f5bcd4255a89a70b5ecf7db01226f213836d091a3b37eb96e4937966b094a291&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x96f074fc891b637e18eb0b3c5908f94d4e71f76243914e3b3a88348b7a7ec85289d322e24f14ce75a7d193dece4c7cb5150aca3dae194839807c09039304a894c9e5b70735b88c437f9c6043e495201f58a28683d2eb528e3e81fe14b3ce867c&quot;
  deposit_data_root: &quot;0xeaad4c2435c42339d3f2248def6f6d44a0da2237d6eb6092016e5b9a47b3fa9f&quot;
  eth1_data:
    deposit_root: &quot;0x026d58bd6b7169617f62fc8725cebcafd8b3f352d63060d3b3326ff6e9d2d3da&quot;
    deposit_count: &quot;94&quot;
    block_hash: &quot;0x562a78b2c5ec97a0b4fa413f57885311a457155372bbf630a434d8c243d21036&quot;
  block_height: 95
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x9cdee5c9ecd1ef9a54feb904550ef7271277dcbc43318688b0b0f4b0454c5a95&quot;
      - &quot;0xe78ee87ce4f2c19b2b27b0e4d875fb21bf9580e9b8e683f34db124274f263dc5&quot;
      - &quot;0xf5e222e2ec0403f08a8f04b439d8af9798f665fcc237f672d6e5e7484a024866&quot;
      - &quot;0x621b699cf7502853da163711315ae56eac3eca5afb2c480325bb9a35e3c9f37f&quot;
    deposit_root: &quot;0x026d58bd6b7169617f62fc8725cebcafd8b3f352d63060d3b3326ff6e9d2d3da&quot;
    deposit_count: 94
    execution_block_hash: &quot;0x562a78b2c5ec97a0b4fa413f57885311a457155372bbf630a434d8c243d21036&quot;
    execution_block_height: 95
- deposit_data:
    pubkey: &quot;0x8f1ef3639aea57fef705847e251b785bb608a848f42d9107c494cbc696be35642f6552fb83174ca2e73632568a5667f4&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa733bafcafc2ba319538ce6af3de20976c5ebd8040a8a3628f7e69a16baeb95566b0cefc55472fba696aa023001b52f605d8824f7dbf2dba9ff2a53554c155815da39e3f27ebd7022a52412b9a793468cb1a1c6469aae7750a1d36a0010fc8b8&quot;
  deposit_data_root: &quot;0x93614f1ff88e971226eb167a407e0afe4d236a82e2eaf43259946edbc8af576d&quot;
  eth1_data:
    deposit_root: &quot;0x511e1b6a894a5783751f3eac7f79d3f52c94a76f29686ebe7eaac7a854d490d1&quot;
    deposit_count: &quot;95&quot;
    block_hash: &quot;0x723848008dec04dc63b5a521c38e95c5f2598053fb5a756022d3a85906128eee&quot;
  block_height: 96
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x9cdee5c9ecd1ef9a54feb904550ef7271277dcbc43318688b0b0f4b0454c5a95&quot;
      - &quot;0xe78ee87ce4f2c19b2b27b0e4d875fb21bf9580e9b8e683f34db124274f263dc5&quot;
      - &quot;0xf5e222e2ec0403f08a8f04b439d8af9798f665fcc237f672d6e5e7484a024866&quot;
      - &quot;0x621b699cf7502853da163711315ae56eac3eca5afb2c480325bb9a35e3c9f37f&quot;
      - &quot;0x93614f1ff88e971226eb167a407e0afe4d236a82e2eaf43259946edbc8af576d&quot;
    deposit_root: &quot;0x511e1b6a894a5783751f3eac7f79d3f52c94a76f29686ebe7eaac7a854d490d1&quot;
    deposit_count: 95
    execution_block_hash: &quot;0x723848008dec04dc63b5a521c38e95c5f2598053fb5a756022d3a85906128eee&quot;
    execution_block_height: 96
- deposit_data:
    pubkey: &quot;0x8967da3c8071ba2bf632cd40ae08fbbf0a203c47c02af1948fc232a7a743c0c0cfbe51606b89f102f2f6de7f039fb155&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x913fdc3ce1efa57fc787572b38a1682a411548e5707daf8e7b9e6a6126ab172c33226e21dff8bbd48b2a8d22f1a8b0e51540166b4c6f8cdf978f69a04a3ec48ebbf64d9640e20b834b56362b0bab8ad1793f72bce5d6afe74588a6f6efdd7267&quot;
  deposit_data_root: &quot;0x6b4666b947e91abcf56197ff3e4c918aee6289bb0dade7a5788d7032ac026acc&quot;
  eth1_data:
    deposit_root: &quot;0x083b92e2d2cee3120c5fdc9d2ab492d7563bec65eb27aa5013465136f7eebe41&quot;
    deposit_count: &quot;96&quot;
    block_hash: &quot;0xc566f29d941053e9c2881d01fc9b1314c714fdc6d6ef63d842e557e6a347884b&quot;
  block_height: 97
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
    deposit_root: &quot;0x083b92e2d2cee3120c5fdc9d2ab492d7563bec65eb27aa5013465136f7eebe41&quot;
    deposit_count: 96
    execution_block_hash: &quot;0xc566f29d941053e9c2881d01fc9b1314c714fdc6d6ef63d842e557e6a347884b&quot;
    execution_block_height: 97
- deposit_data:
    pubkey: &quot;0x8d58f7e2e58471b46d20a66a61f4cde3c78ab6c0505517c615e08d8ef5adf59b65fa2b01ea2395c84584a6f10d6cee2f&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x892b60039b6e05f3f82b460d9360e1f1121adc5974a7c75f8cb723d597f764fb26aaf21bbd6a08b36078d6acc00a355607888b4838f9a1d007a4d0d0db5650e36ca498d6d074bf14a0a33ef13c34a419d7f99c6ebe0eca5001263cbb26f299b4&quot;
  deposit_data_root: &quot;0x34e3e3e0c13a79cd9e7e8826d9d20c106a9401f253750a68869eb8d31fd8d03a&quot;
  eth1_data:
    deposit_root: &quot;0xc33b108e1f20262d0bd6dde0604c39e305ecf07eb8c390070cf586395b6050ff&quot;
    deposit_count: &quot;97&quot;
    block_hash: &quot;0x01a6a54f02fad6d7168ef158896c42874a9696b7d6b33b6a90fba4e9892723a2&quot;
  block_height: 98
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x34e3e3e0c13a79cd9e7e8826d9d20c106a9401f253750a68869eb8d31fd8d03a&quot;
    deposit_root: &quot;0xc33b108e1f20262d0bd6dde0604c39e305ecf07eb8c390070cf586395b6050ff&quot;
    deposit_count: 97
    execution_block_hash: &quot;0x01a6a54f02fad6d7168ef158896c42874a9696b7d6b33b6a90fba4e9892723a2&quot;
    execution_block_height: 98
- deposit_data:
    pubkey: &quot;0x8db9f236d3483af79703244c7034b5267a0546c3c840d4e91fdcdd466373d62d960553982225ca5f7666dd7375a29c19&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9395087be80e3bc55d623f4d5bdfe6de200064e27d862d731c0c3dcf60a7c73fc6ad5c59177f788b5ce4ad6c2053fcea0950ec9196c8deae651f8cf3042a87b234bb4f201fe0d852708c332d0efe4323a7f6b3782ee919b365479cb5aa90bcc3&quot;
  deposit_data_root: &quot;0x57a75df5bd0f09fbaa3bbd2ad872fd0704d94d51ddcefad7ad9af438b9d63ce2&quot;
  eth1_data:
    deposit_root: &quot;0x99b08e97b9635d5ce40146efae53e688f53a8910a0357fe211440987b63f86c9&quot;
    deposit_count: &quot;98&quot;
    block_hash: &quot;0xff6e581a1f58dd834e095b5dc6cd14940a0b5148a7d0b6d94944ee324750abeb&quot;
  block_height: 99
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x9c30281da5fd2d7a8bd8e4c8c3a19ee28bb8a08c97e386825abf49429dfc8492&quot;
    deposit_root: &quot;0x99b08e97b9635d5ce40146efae53e688f53a8910a0357fe211440987b63f86c9&quot;
    deposit_count: 98
    execution_block_hash: &quot;0xff6e581a1f58dd834e095b5dc6cd14940a0b5148a7d0b6d94944ee324750abeb&quot;
    execution_block_height: 99
- deposit_data:
    pubkey: &quot;0xb7721412ae5a793f34ac8866698b221c67ef8272eba44d3030512ec3f7ed8ffcb620b58f17809690d5276423e849827f&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8967a6b4490020cee91b6554b3aadb730da19f1dc9ab10629014f1b6221bb3f5827dafab1c48d97a5e0f55577708dad613724b60700424854c38a14aae340d8fd20ed7145e95dc458cc3d298192aad68c112bccd7f5574594a6d5a5b5401bd63&quot;
  deposit_data_root: &quot;0xc14a33eb96c6282e934f2944a23bafc7813ab96c21dee6ec6b2ad8c4c10ec4e4&quot;
  eth1_data:
    deposit_root: &quot;0xcaa6c2f895d078431ed03bc0d16ff9cae6eab44c2675a42de52820216f647f0e&quot;
    deposit_count: &quot;99&quot;
    block_hash: &quot;0xaf681b414bf20e9775a4c897373013a58d6db4e23c2a394b25cd9dab40ca6c53&quot;
  block_height: 100
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x9c30281da5fd2d7a8bd8e4c8c3a19ee28bb8a08c97e386825abf49429dfc8492&quot;
      - &quot;0xc14a33eb96c6282e934f2944a23bafc7813ab96c21dee6ec6b2ad8c4c10ec4e4&quot;
    deposit_root: &quot;0xcaa6c2f895d078431ed03bc0d16ff9cae6eab44c2675a42de52820216f647f0e&quot;
    deposit_count: 99
    execution_block_hash: &quot;0xaf681b414bf20e9775a4c897373013a58d6db4e23c2a394b25cd9dab40ca6c53&quot;
    execution_block_height: 100
- deposit_data:
    pubkey: &quot;0x99f6e5b80dc52407f0436d3474bd5da5ff23a19cb188b933af6312d9793cbfd54f9e72596c5d481a1ed8d705b81c1f0e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa0de9fe9ab9d8fa0b287ca0c7335bca94a79a888e67a7e0a933d38b5dfca2cb30d77f75398652a3c787af48b0707ebb20d3fd2e3f78c459235bd0eb17f550964e6d2638470728499f59cca4c041846d433e9095b5d2cc83c633cc728f3683db8&quot;
  deposit_data_root: &quot;0xc6f502475ac7546b770905653f9c9da144d8721ebf626232259099df44d67793&quot;
  eth1_data:
    deposit_root: &quot;0xe346f5cfac0d8834bbdf80742e9de3418f612bc03fa79a9be61a9a201070673e&quot;
    deposit_count: &quot;100&quot;
    block_hash: &quot;0x40078f8026a5491a9530ebc2bdc366535d4c6a7c37c1df6515c4074508849187&quot;
  block_height: 101
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x2c03f5ec194e16617790b85ceb15755990f694b3fb90b74d26812f265b90d33d&quot;
    deposit_root: &quot;0xe346f5cfac0d8834bbdf80742e9de3418f612bc03fa79a9be61a9a201070673e&quot;
    deposit_count: 100
    execution_block_hash: &quot;0x40078f8026a5491a9530ebc2bdc366535d4c6a7c37c1df6515c4074508849187&quot;
    execution_block_height: 101
- deposit_data:
    pubkey: &quot;0x8931cd39ec3133b6ec91f26eec4de555cd7966086b1993dfe69c2b16e80adc62ce82d353b3356d8cc249e4e2d4254122&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa1e9f2cddc66b67063b4caecedc4093ecb9241a751da05b6219b5062a5311590d0b4f8b258377a6696316d7808e10c6502542f3a14c00693a70ea8adf2bb74b79d0a15613058c521b50882007b85a0ca26b0bf888695d0a03dcdf0139364c849&quot;
  deposit_data_root: &quot;0x61a0ce23d0255c07b5f1f85771735ffc18dd898b056d00d5e72431c9ab4526c8&quot;
  eth1_data:
    deposit_root: &quot;0xd5db7d15947a7d071f2809c8e827e9ca01511010e1af5e50e59ed2eae150fab5&quot;
    deposit_count: &quot;101&quot;
    block_hash: &quot;0xbfa88dac097016410b459589b3d5703070fb2da3419661138f0e3e9bc868e49b&quot;
  block_height: 102
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x2c03f5ec194e16617790b85ceb15755990f694b3fb90b74d26812f265b90d33d&quot;
      - &quot;0x61a0ce23d0255c07b5f1f85771735ffc18dd898b056d00d5e72431c9ab4526c8&quot;
    deposit_root: &quot;0xd5db7d15947a7d071f2809c8e827e9ca01511010e1af5e50e59ed2eae150fab5&quot;
    deposit_count: 101
    execution_block_hash: &quot;0xbfa88dac097016410b459589b3d5703070fb2da3419661138f0e3e9bc868e49b&quot;
    execution_block_height: 102
- deposit_data:
    pubkey: &quot;0xad01d0f23cb74fcc4c39a2d0827d22f4722f02076196350dff5dcc6be765009c66e29001001959d77b277c2f0fba0425&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb3ffc0107b268976d973c779f1682eb3b92fa5988a72a169d6b959472a72b9ea48c30132bbfac1dbde2a1b658007025011969607d97747e6bca0a852a0c0a03d0fdee3550f22f4052fae270a373b92d40f14c86ff0f79d7570335e16269b034a&quot;
  deposit_data_root: &quot;0x7fbb1660d3859504d5652fb48a640e3a0852b9087209abc9e9a641a3b0bc526c&quot;
  eth1_data:
    deposit_root: &quot;0x2a0a58d87c8644cff8c8b70ca8c8e698376bed37ba7f9b4ed5f5e9058b3e4017&quot;
    deposit_count: &quot;102&quot;
    block_hash: &quot;0x2617746c889290b55facaa523ef25b1bf1bfad0be77797ffa78bf2fd44217fad&quot;
  block_height: 103
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x2c03f5ec194e16617790b85ceb15755990f694b3fb90b74d26812f265b90d33d&quot;
      - &quot;0xde2e3c85af638e1c1b8581fd99aafbb0b9e0e2d638a96c2037814fba4940ddad&quot;
    deposit_root: &quot;0x2a0a58d87c8644cff8c8b70ca8c8e698376bed37ba7f9b4ed5f5e9058b3e4017&quot;
    deposit_count: 102
    execution_block_hash: &quot;0x2617746c889290b55facaa523ef25b1bf1bfad0be77797ffa78bf2fd44217fad&quot;
    execution_block_height: 103
- deposit_data:
    pubkey: &quot;0xb300303a03b8eff26a25449169d1946b208d5240f011ca6f5db23cd7f2c004b63f60afe3c9e047b67f9e4c8970c71cf0&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x88d4150448307f43753ee083124754d8c18b2c4eadb170e741e828b61b356b8cf3c69caadbdcae96f3353ba068f2c2da00596d5ba1f5dae9ec4c305ee7c5069ba5c71ea6ac5cde50bdee887233c18a85928a066802d5b4b38f3295c706860d93&quot;
  deposit_data_root: &quot;0xaccb652fae17e3c73511c9d3065377183aa4cc46b7f0f57b0e7d821b2b2ce99d&quot;
  eth1_data:
    deposit_root: &quot;0x7154ee203a0ef6d25aba1c8473290a20ff6db1147cf850f848d8641e25d872ac&quot;
    deposit_count: &quot;103&quot;
    block_hash: &quot;0xb082be3f6319b71f9235dd3320af6ac53a7211bd652c673eecd70fa2443d9b76&quot;
  block_height: 104
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x2c03f5ec194e16617790b85ceb15755990f694b3fb90b74d26812f265b90d33d&quot;
      - &quot;0xde2e3c85af638e1c1b8581fd99aafbb0b9e0e2d638a96c2037814fba4940ddad&quot;
      - &quot;0xaccb652fae17e3c73511c9d3065377183aa4cc46b7f0f57b0e7d821b2b2ce99d&quot;
    deposit_root: &quot;0x7154ee203a0ef6d25aba1c8473290a20ff6db1147cf850f848d8641e25d872ac&quot;
    deposit_count: 103
    execution_block_hash: &quot;0xb082be3f6319b71f9235dd3320af6ac53a7211bd652c673eecd70fa2443d9b76&quot;
    execution_block_height: 104
- deposit_data:
    pubkey: &quot;0xaca096c7f41cfa6b9317dff26c6c96878c9e5d5eed50afde44d8df206372ad4b4c45568f6671552029f4c3509e295bef&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa200bef0c9ca2a3efafb7d75dd19be1f621a50b1f5d3eaa688a6d02119a1c08125c4d9dd71cc388e2dfac5544d466bf618293c90e396b56e0d7ab9714a386e0f9685cd4aa07de369cee98ef3912281f438c7ae29146a199c94d2542889d9f898&quot;
  deposit_data_root: &quot;0x70ee28dadd98103e531ac6f411f1798bec743246fe66be847efe6fc26bf530bf&quot;
  eth1_data:
    deposit_root: &quot;0x548bfd5b5eced68eb9fdbabb484a6145d518a234cd7626ab7bcde2752dc878eb&quot;
    deposit_count: &quot;104&quot;
    block_hash: &quot;0x1cf1756c5ffc73b0f80fc2a242fedcdeed357eff548826f5b81a765f69f98a9b&quot;
  block_height: 105
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x6cd8d51fa9ddfe114bb7f25d29576b6a72602063f2c1a541ac3e767dc0bd28f4&quot;
    deposit_root: &quot;0x548bfd5b5eced68eb9fdbabb484a6145d518a234cd7626ab7bcde2752dc878eb&quot;
    deposit_count: 104
    execution_block_hash: &quot;0x1cf1756c5ffc73b0f80fc2a242fedcdeed357eff548826f5b81a765f69f98a9b&quot;
    execution_block_height: 105
- deposit_data:
    pubkey: &quot;0x87bbd5574c17dbf80463d11f812a77306f67913c510b1b234f5bd80478c7da8e69476cd6711cd1f4c0e228a4e2e99636&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x982d4f21d196dd1c646180e68e831f730e596980de02297deb7a91a2d1b5fdf82fe7bd7dd9e2d301ef25481814e763b505f8183b996e08e363c27fc6e6d08538ee37898ac5ea10f9ab9b6f70265ad3b214613e643c9c047333bbaf95053eb3f6&quot;
  deposit_data_root: &quot;0x16c89707a34efa444cf234654f40c446d1dc61cd8f9868668df3b1ab87eaea8e&quot;
  eth1_data:
    deposit_root: &quot;0xef70ec141be46e60cb179e2b7dfa8f061a0ed3cdf8b1f8b67e0f410f3a6af678&quot;
    deposit_count: &quot;105&quot;
    block_hash: &quot;0xda9c4714b0ab8c1befb967e12d9f677e7c536aca4750647e6302a6c5687460f2&quot;
  block_height: 106
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x6cd8d51fa9ddfe114bb7f25d29576b6a72602063f2c1a541ac3e767dc0bd28f4&quot;
      - &quot;0x16c89707a34efa444cf234654f40c446d1dc61cd8f9868668df3b1ab87eaea8e&quot;
    deposit_root: &quot;0xef70ec141be46e60cb179e2b7dfa8f061a0ed3cdf8b1f8b67e0f410f3a6af678&quot;
    deposit_count: 105
    execution_block_hash: &quot;0xda9c4714b0ab8c1befb967e12d9f677e7c536aca4750647e6302a6c5687460f2&quot;
    execution_block_height: 106
- deposit_data:
    pubkey: &quot;0x89a80c9263a21ebb9b7b99e59e53edc9ac766a55da86a52d1098d57572999ebad7cb92800b1f15be8d7c43889ab71c5d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb6ca12b56b3beb9f9c785f8f865ae5d33ae5d432c34b580907c56ea252be219553c87e3a6d2eb3d93bf29b16c0c522b303c289933ace190bcc666cf3cbcc22f5f516d2ecad7bf29ceef55f8911b33a9c9f7bdde58876e6c02522925d0de0e444&quot;
  deposit_data_root: &quot;0xe9b136c1ca2fcb6d303f551b646a882b36d377989a217239b68534d1afc9fca0&quot;
  eth1_data:
    deposit_root: &quot;0xaeae251b14d94efe7aa55639a1387528a1e5ef2769b05e8286a661d147e06cb3&quot;
    deposit_count: &quot;106&quot;
    block_hash: &quot;0x5669324d92acbdd26d268054be610287bae0b19c33fc941fd3096db48833448d&quot;
  block_height: 107
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x6cd8d51fa9ddfe114bb7f25d29576b6a72602063f2c1a541ac3e767dc0bd28f4&quot;
      - &quot;0xa2000cb687523633d740002d63b1deb735701652a6d1053a8e859b2a2b17ca0b&quot;
    deposit_root: &quot;0xaeae251b14d94efe7aa55639a1387528a1e5ef2769b05e8286a661d147e06cb3&quot;
    deposit_count: 106
    execution_block_hash: &quot;0x5669324d92acbdd26d268054be610287bae0b19c33fc941fd3096db48833448d&quot;
    execution_block_height: 107
- deposit_data:
    pubkey: &quot;0x802408c2a1901d316637a3ec6d20447bb9ee105c8c088510bfbcf8cda3ffa9376779f36e12e960e7efa5f2aba45e6483&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x91efe4ad425f9226a32e6c2bb04e47bd7adb4ebbbfcb20bf4119e046f22aa714264dcfaa8a1744d02d959e6719fbb245013230f209524365c2b2f418abb365a439883f89abce8896f4463dee7e9b08629b06bf1a1e8704cee65bad429c0a5757&quot;
  deposit_data_root: &quot;0x43e5a791b6ea536132e9b7c2e9e154eb7228704fb1749d76474dccf2cffb2c2e&quot;
  eth1_data:
    deposit_root: &quot;0x97284fc411333bd602aef2ebd5cf41ced3b2d7b27ae5de0d97a0b23f1a352ee6&quot;
    deposit_count: &quot;107&quot;
    block_hash: &quot;0xb1f82e537255e3d8c6607a9e5acf26cab9c71cc10145c2295012c650f67a3476&quot;
  block_height: 108
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x6cd8d51fa9ddfe114bb7f25d29576b6a72602063f2c1a541ac3e767dc0bd28f4&quot;
      - &quot;0xa2000cb687523633d740002d63b1deb735701652a6d1053a8e859b2a2b17ca0b&quot;
      - &quot;0x43e5a791b6ea536132e9b7c2e9e154eb7228704fb1749d76474dccf2cffb2c2e&quot;
    deposit_root: &quot;0x97284fc411333bd602aef2ebd5cf41ced3b2d7b27ae5de0d97a0b23f1a352ee6&quot;
    deposit_count: 107
    execution_block_hash: &quot;0xb1f82e537255e3d8c6607a9e5acf26cab9c71cc10145c2295012c650f67a3476&quot;
    execution_block_height: 108
- deposit_data:
    pubkey: &quot;0xaccc213c82702adfd5c32b24a68863f16ab6ab46947d1d7b3829bc62cd5f2a87bcd0d3ef27d442f07ad4363be9fc12f8&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa2e689452fd1534510fd42ff1e2dab4addf50492d66518836649ddf9ca206953fbd0ada1f727d14fb05e2041e3d786e308f06f5cb5f610fb8c8bea08730f4f35cf4ce8e12dbfe2d86f5be234b765373fccf1d2e167d2e14051aabf6c563822d5&quot;
  deposit_data_root: &quot;0x834c7ef796fc324ee3d09a5c35fdc887d317b6e6fb166403b37f9672736f83c8&quot;
  eth1_data:
    deposit_root: &quot;0x0d890ddd7f83f43cdc1bd1888b4b514892240f854310148d31fd0cd36e577d0e&quot;
    deposit_count: &quot;108&quot;
    block_hash: &quot;0x3859945b847ee6c8bda15345167cd845984f63fa80b59abd02e47f305ab1859b&quot;
  block_height: 109
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x6cd8d51fa9ddfe114bb7f25d29576b6a72602063f2c1a541ac3e767dc0bd28f4&quot;
      - &quot;0x3f0c046faed71f3fab856fcaf43a55a7865e4f8054998ea1b7b0ac4b2ec62d03&quot;
    deposit_root: &quot;0x0d890ddd7f83f43cdc1bd1888b4b514892240f854310148d31fd0cd36e577d0e&quot;
    deposit_count: 108
    execution_block_hash: &quot;0x3859945b847ee6c8bda15345167cd845984f63fa80b59abd02e47f305ab1859b&quot;
    execution_block_height: 109
- deposit_data:
    pubkey: &quot;0xb0af0bfa83f0922e6cbfd2bc8ec19ff0f692fcb87c4e35f30e1353b342ae2fdaea6056bc2759970fc2a1f561826f564e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xac48afbc00ea959cf42b12f84d934ebaa6411c2ef6543b9551795d44b9c0ad242892330217978991c010250104e9b3d702107985f4f3f470ea555d9995fdf2c53549f3f4577e1893cccce684b9f13961730dccab982e8ffc56013ddec229e145&quot;
  deposit_data_root: &quot;0xa366a29df760de23293716136774c56eb8d31fc5c2ab2ad91235305fffff9ab2&quot;
  eth1_data:
    deposit_root: &quot;0x4c52ffd886c8668450508977adb286c525f48706688f364dcd0a7197b08b6dc0&quot;
    deposit_count: &quot;109&quot;
    block_hash: &quot;0xd5bebc34ca9da5a4ee194fec1c3efdf56a070520be6dbfd87f08862e7909ad5e&quot;
  block_height: 110
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x6cd8d51fa9ddfe114bb7f25d29576b6a72602063f2c1a541ac3e767dc0bd28f4&quot;
      - &quot;0x3f0c046faed71f3fab856fcaf43a55a7865e4f8054998ea1b7b0ac4b2ec62d03&quot;
      - &quot;0xa366a29df760de23293716136774c56eb8d31fc5c2ab2ad91235305fffff9ab2&quot;
    deposit_root: &quot;0x4c52ffd886c8668450508977adb286c525f48706688f364dcd0a7197b08b6dc0&quot;
    deposit_count: 109
    execution_block_hash: &quot;0xd5bebc34ca9da5a4ee194fec1c3efdf56a070520be6dbfd87f08862e7909ad5e&quot;
    execution_block_height: 110
- deposit_data:
    pubkey: &quot;0xa626de0451397075bf145e720691c9d5ed92eddf1f4e48155b455aac7a8e920d042f5635c7a74fe3a9175ffbfb7ce12e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb34e59e6935eafbe65e52e28c5f311f381b303f479ec2a6e9fba488e514de0eb6e1079f033cc8dcdd839675a6ef00869132aaa13dae6179fa88d01620af6cdf890258219b7bd4e374f82712cab8aec4de54ea403f2807c20ff8587ba9740de6c&quot;
  deposit_data_root: &quot;0x225e8673c5a0ede3e15885c408c04c2468c223f1fff0a87b08cc74887dd3a56f&quot;
  eth1_data:
    deposit_root: &quot;0x7c63909e1401449ed1e5773863d7629fbc8396468b85476a75d7e637b5f9f7a0&quot;
    deposit_count: &quot;110&quot;
    block_hash: &quot;0xfdee2ad0a738d5c9a2f063b80fce04b5e61df04fd595155dc5509d45ee6495b5&quot;
  block_height: 111
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x6cd8d51fa9ddfe114bb7f25d29576b6a72602063f2c1a541ac3e767dc0bd28f4&quot;
      - &quot;0x3f0c046faed71f3fab856fcaf43a55a7865e4f8054998ea1b7b0ac4b2ec62d03&quot;
      - &quot;0xac07404027d09239f2784ec2873ccb9baf4212a432cce6626f56e80f1e99ea5f&quot;
    deposit_root: &quot;0x7c63909e1401449ed1e5773863d7629fbc8396468b85476a75d7e637b5f9f7a0&quot;
    deposit_count: 110
    execution_block_hash: &quot;0xfdee2ad0a738d5c9a2f063b80fce04b5e61df04fd595155dc5509d45ee6495b5&quot;
    execution_block_height: 111
- deposit_data:
    pubkey: &quot;0xb0933ec64b73c49071fb92028a8e3d1ad18019e177370d335fa03c61de5d01e1a7e154812f720c44109701e2b07068b0&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa4070a873b52b119a63ecfd68300d7f2f359963cdcdb4b7e6764647975b2fcf6ac0682c37690493d3078794ee680c0490381f85b20b8c0ff33f9642dad0064e0ab84eced4a8e38bacdcc4a068a7c5742d67e64b9019bbaf2f2a64a7e525b2198&quot;
  deposit_data_root: &quot;0x5242358df16ac3f92030b1fbbdb91f85d477b50d2d33a2f59dcf4bce046ee698&quot;
  eth1_data:
    deposit_root: &quot;0xa277f7cb6c03e9087666ea431b99d82c13b4d5ee95ccd73b1b627bacb236486a&quot;
    deposit_count: &quot;111&quot;
    block_hash: &quot;0xe89d23f1eaca58026acc006eff84e317245838800cd5c1be08a8564284c75a6f&quot;
  block_height: 112
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x6cd8d51fa9ddfe114bb7f25d29576b6a72602063f2c1a541ac3e767dc0bd28f4&quot;
      - &quot;0x3f0c046faed71f3fab856fcaf43a55a7865e4f8054998ea1b7b0ac4b2ec62d03&quot;
      - &quot;0xac07404027d09239f2784ec2873ccb9baf4212a432cce6626f56e80f1e99ea5f&quot;
      - &quot;0x5242358df16ac3f92030b1fbbdb91f85d477b50d2d33a2f59dcf4bce046ee698&quot;
    deposit_root: &quot;0xa277f7cb6c03e9087666ea431b99d82c13b4d5ee95ccd73b1b627bacb236486a&quot;
    deposit_count: 111
    execution_block_hash: &quot;0xe89d23f1eaca58026acc006eff84e317245838800cd5c1be08a8564284c75a6f&quot;
    execution_block_height: 112
- deposit_data:
    pubkey: &quot;0x8b47707a1f563d3b1034e20be2a663587f17fece6581fca156cf660575fde4b8de4d45f1fda7ade9167b953d4c93417d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x94c71b0489c2e7cc1041a4971b92bf507c78b868d58de47fa10f673952fffa15edbf42cff7dc09f55ded92069023ed31049a7b917ac3629560e1a1ab6dd936a8e846a36cc5a691cb0cdcc1ac61a47565778aa9c8ddecb41e2cacca4fa7a9a093&quot;
  deposit_data_root: &quot;0xecb5c27e0bd4dfba545e4be285416d20eea78a0c894c97542ead3e70cf3a0788&quot;
  eth1_data:
    deposit_root: &quot;0x98e76adf146e3608cd2e4f340d4d646e8f43a211e2326a454a86e2a2ffa8442f&quot;
    deposit_count: &quot;112&quot;
    block_hash: &quot;0x6803694b96704cf8b5a7b731ab9497fc091064132096166e8852ad5de1d23aa3&quot;
  block_height: 113
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x0ff1cd5c2a584c83b12d7ad77a2e309ba97738719c0876302ce0ca1e9b02892e&quot;
    deposit_root: &quot;0x98e76adf146e3608cd2e4f340d4d646e8f43a211e2326a454a86e2a2ffa8442f&quot;
    deposit_count: 112
    execution_block_hash: &quot;0x6803694b96704cf8b5a7b731ab9497fc091064132096166e8852ad5de1d23aa3&quot;
    execution_block_height: 113
- deposit_data:
    pubkey: &quot;0x8ce551755078927147bae52f683f962ca09cd68e2a14dc7444f98739fe5d27e3596314d78deedc87beb705bcf9532182&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa68afbb096250d43a72588cf6db83f6be6413f0d7350056cba7d11df6fc7efa07107dd925130c0d1ab55b510e5e39b29151649e8f371e113a83c7e2518c4a0d6d16b17c7209396a5bd9653f78f357528e277071f03bb9abfdb10580e919b84a8&quot;
  deposit_data_root: &quot;0x54af1e6596ebc505cb6c1eb2c2a58d137f0ab4ff9e8919495631a9c6ce02e185&quot;
  eth1_data:
    deposit_root: &quot;0x28d6d95d118088e83779c9030adbbd5faebcd35e8168a1d8c3f675a80ae7aa83&quot;
    deposit_count: &quot;113&quot;
    block_hash: &quot;0xaaf1b5f2693fb64143ababcc4d377385cc37a7f6a87c989b5c21ee9dd1578fbf&quot;
  block_height: 114
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x0ff1cd5c2a584c83b12d7ad77a2e309ba97738719c0876302ce0ca1e9b02892e&quot;
      - &quot;0x54af1e6596ebc505cb6c1eb2c2a58d137f0ab4ff9e8919495631a9c6ce02e185&quot;
    deposit_root: &quot;0x28d6d95d118088e83779c9030adbbd5faebcd35e8168a1d8c3f675a80ae7aa83&quot;
    deposit_count: 113
    execution_block_hash: &quot;0xaaf1b5f2693fb64143ababcc4d377385cc37a7f6a87c989b5c21ee9dd1578fbf&quot;
    execution_block_height: 114
- deposit_data:
    pubkey: &quot;0xb363a57c600a0037d54d738037358aa686e27da3ea65be95f95fc04d5736fba6338c5d544c3cf2b11262bd20e7a42dd1&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa8fb0e367ac8eeceeccc271b8abb3f6a51ac714bc0837d919ee3cd56df40f2b3020fa79592035cd9b4b59e428620b1fc0ef0b62804119288362814074b2247be97106821cbe2e5ee077d4935a853c17730701c0b9eafc83ff08656b8ec2fa7a2&quot;
  deposit_data_root: &quot;0xd6fdfa51b7eb29f6327bd5f283e43b584dde088d09df4378e58b244b871c4dbe&quot;
  eth1_data:
    deposit_root: &quot;0x4f43eee61db70c0290a3ec3eeed96b98d38fa1fddb21149808760133b9f7a385&quot;
    deposit_count: &quot;114&quot;
    block_hash: &quot;0x9184c85f99de9e7302c25f18b814f557e5ed7363677ce9fa97dd727f1c9c01b6&quot;
  block_height: 115
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x0ff1cd5c2a584c83b12d7ad77a2e309ba97738719c0876302ce0ca1e9b02892e&quot;
      - &quot;0xc2d2d3ec8e50223aa7c20032356d3d4a3be3ecfd18471318d91192e20bca4cd9&quot;
    deposit_root: &quot;0x4f43eee61db70c0290a3ec3eeed96b98d38fa1fddb21149808760133b9f7a385&quot;
    deposit_count: 114
    execution_block_hash: &quot;0x9184c85f99de9e7302c25f18b814f557e5ed7363677ce9fa97dd727f1c9c01b6&quot;
    execution_block_height: 115
- deposit_data:
    pubkey: &quot;0xa5e05143d5034740cb9ad524bec81678b07223989d4534ad44ffad33ee2fc73e4ee6b297b68aef9de33f98e5487467b5&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa44866b3ac0b41fb89fd7a51f4963bceab4b31e92f963aea80979a8a96835067eac75868f59c7ad204f00e117bb3cded053e6d2334e626634d0cee0120234658f7cc1e0c68f0c7d1f23327db2bf91d86b56ce7131012b0db84266bf624f0b599&quot;
  deposit_data_root: &quot;0x72a8893e5155db8e97031c2de604a4ea3b0d3323a6a242a4253c7a539dc72ddf&quot;
  eth1_data:
    deposit_root: &quot;0xa9ddf7428ca9cb8ffa10cf3f1ac2e56066e9f962e8cef91aedd841f0c0b3a6c5&quot;
    deposit_count: &quot;115&quot;
    block_hash: &quot;0x0343f11c8b2cb94cf8cce1b1f0e6dafcc956a4d6ba21a0010ae204a4e50d8171&quot;
  block_height: 116
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x0ff1cd5c2a584c83b12d7ad77a2e309ba97738719c0876302ce0ca1e9b02892e&quot;
      - &quot;0xc2d2d3ec8e50223aa7c20032356d3d4a3be3ecfd18471318d91192e20bca4cd9&quot;
      - &quot;0x72a8893e5155db8e97031c2de604a4ea3b0d3323a6a242a4253c7a539dc72ddf&quot;
    deposit_root: &quot;0xa9ddf7428ca9cb8ffa10cf3f1ac2e56066e9f962e8cef91aedd841f0c0b3a6c5&quot;
    deposit_count: 115
    execution_block_hash: &quot;0x0343f11c8b2cb94cf8cce1b1f0e6dafcc956a4d6ba21a0010ae204a4e50d8171&quot;
    execution_block_height: 116
- deposit_data:
    pubkey: &quot;0xaf14e8626e043caed52d9dfe62046eaa698f8b95d25cedc8c63e472def8b6a59e64febfa00e95568538c1a382ac91d2b&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa8a07f9a5faf428d95a6924d2e4d9aab65e9756b878d548a9ab04b57257c56c3878e1d451b36f264f6fdb1521162ccda089ad9e5c250738c983827e64dfd21b9b3662ce1c5fff45b2f73bbe47d0b1a6b208b4f2fbf78447ad5e12bf6e7a4596e&quot;
  deposit_data_root: &quot;0xab893bbeb9c8f1b0aeb760b31be1696736b2f7ee05edff8dcc6183d76adae267&quot;
  eth1_data:
    deposit_root: &quot;0x03d68d623a18dd6af2380829bcb89709b8024f8ba83771ac3f5135bdcdee00ee&quot;
    deposit_count: &quot;116&quot;
    block_hash: &quot;0x73d9f83ad8851e59c41c2b25e0e568dbb0ef8c23f37a006dcade3329a8d6f0f9&quot;
  block_height: 117
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x0ff1cd5c2a584c83b12d7ad77a2e309ba97738719c0876302ce0ca1e9b02892e&quot;
      - &quot;0x97906a31d1ca59143dc947a1f048242f4c67382be296dcdf43a03951553464ed&quot;
    deposit_root: &quot;0x03d68d623a18dd6af2380829bcb89709b8024f8ba83771ac3f5135bdcdee00ee&quot;
    deposit_count: 116
    execution_block_hash: &quot;0x73d9f83ad8851e59c41c2b25e0e568dbb0ef8c23f37a006dcade3329a8d6f0f9&quot;
    execution_block_height: 117
- deposit_data:
    pubkey: &quot;0xb41a0d9f8f19be13395aa09711b492d20eaf4a56d2360cd6daa2fd665532d852cb9224a5a39e5abff389882f961f12a6&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9976e20aca195ad464d2e5bdff8f89100d8fa42357588bffae1c3ebce0af6ab593fdbb83b6e316fde942bad4dca225520e3aa856e5e5adb167c7fee7a1f022a9caaa0f199b5e5a2f7a2ecda1f016c02845f2168f0a144a1de33890ec8480441b&quot;
  deposit_data_root: &quot;0xc970a40ac721ba0ea1adff1e2f0a10b8dc9529a25bf867f8eb22359655eb5c66&quot;
  eth1_data:
    deposit_root: &quot;0x1e0d48b0764fedc0a118aea5976361d0612144be975699f762b00c0365b22cae&quot;
    deposit_count: &quot;117&quot;
    block_hash: &quot;0x1f8c317ca00006c5468170bb2ad996fc5264a4622b30ff4feabf2c3a923a622b&quot;
  block_height: 118
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x0ff1cd5c2a584c83b12d7ad77a2e309ba97738719c0876302ce0ca1e9b02892e&quot;
      - &quot;0x97906a31d1ca59143dc947a1f048242f4c67382be296dcdf43a03951553464ed&quot;
      - &quot;0xc970a40ac721ba0ea1adff1e2f0a10b8dc9529a25bf867f8eb22359655eb5c66&quot;
    deposit_root: &quot;0x1e0d48b0764fedc0a118aea5976361d0612144be975699f762b00c0365b22cae&quot;
    deposit_count: 117
    execution_block_hash: &quot;0x1f8c317ca00006c5468170bb2ad996fc5264a4622b30ff4feabf2c3a923a622b&quot;
    execution_block_height: 118
- deposit_data:
    pubkey: &quot;0xb242e56475dca34fe92de09daee3951d647c04ed7a483a5c5c5613676f5ca88d54ec64d1aee81fb0f085aa67c88ee6db&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb0e8b1ab87c739db7149b5e2756e3fec4cb8ca9ce14cd17af4064c85e0917dfdd4c40c13f6c48cbffe760a45f63567fa13272ef95f73c5fafbfe62336292af7c1cf68d2ea3a399729e330feccc375c237c6630a031c1badee92d8d463bf2c3e4&quot;
  deposit_data_root: &quot;0x458248ac4f1676159c16889a98e42e86fcb36615a646d1f3e8c0d56a5c5710a4&quot;
  eth1_data:
    deposit_root: &quot;0x1331f96e0caa629377f330bbad76213870a7d46ea84f70f3211344cd2864ff22&quot;
    deposit_count: &quot;118&quot;
    block_hash: &quot;0xa2c8860839e76bdc3c39ffe65914b4fe29936c31f0218c0ec7b1096f086e6066&quot;
  block_height: 119
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x0ff1cd5c2a584c83b12d7ad77a2e309ba97738719c0876302ce0ca1e9b02892e&quot;
      - &quot;0x97906a31d1ca59143dc947a1f048242f4c67382be296dcdf43a03951553464ed&quot;
      - &quot;0xa325f304db3245c0b82c9770d2cb6ee122a7a8ee7b7d02568fcba7c3d74cd1c4&quot;
    deposit_root: &quot;0x1331f96e0caa629377f330bbad76213870a7d46ea84f70f3211344cd2864ff22&quot;
    deposit_count: 118
    execution_block_hash: &quot;0xa2c8860839e76bdc3c39ffe65914b4fe29936c31f0218c0ec7b1096f086e6066&quot;
    execution_block_height: 119
- deposit_data:
    pubkey: &quot;0x894798d09babc765b3ba22473d820465e713c1d7f78f3eaeade3d957bd412a742f498a9b91e55cba8e08c36c8ad4788f&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb3fe3f86d154a803bfbbcdf25da35ae7293e7a67ed8a486b2178424cf4dc4cd580419276d833bf6aebf02d5c59fb85c70e69fa7718448e6e590c5a88f81078982243ebc70eca16a8c65983d367597d9af062c7bec6e0657ed33c7caab044a6b9&quot;
  deposit_data_root: &quot;0x84bc2d2d601a86cf3f07e155e5fbf2c6a24a838c35c6f5aeb1cf8ec9f54076a3&quot;
  eth1_data:
    deposit_root: &quot;0xc711c10ca8badf31bce9ca6b0ef21a3aad8c94218e594891dbc49e5de5ef0480&quot;
    deposit_count: &quot;119&quot;
    block_hash: &quot;0x09861bc26ec9b9b75d164cba54b6b8f81256b16a0b8d4fad05c0bcb2368cef02&quot;
  block_height: 120
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x0ff1cd5c2a584c83b12d7ad77a2e309ba97738719c0876302ce0ca1e9b02892e&quot;
      - &quot;0x97906a31d1ca59143dc947a1f048242f4c67382be296dcdf43a03951553464ed&quot;
      - &quot;0xa325f304db3245c0b82c9770d2cb6ee122a7a8ee7b7d02568fcba7c3d74cd1c4&quot;
      - &quot;0x84bc2d2d601a86cf3f07e155e5fbf2c6a24a838c35c6f5aeb1cf8ec9f54076a3&quot;
    deposit_root: &quot;0xc711c10ca8badf31bce9ca6b0ef21a3aad8c94218e594891dbc49e5de5ef0480&quot;
    deposit_count: 119
    execution_block_hash: &quot;0x09861bc26ec9b9b75d164cba54b6b8f81256b16a0b8d4fad05c0bcb2368cef02&quot;
    execution_block_height: 120
- deposit_data:
    pubkey: &quot;0x93c65ba88f12ad22c761003cef7ffb155b9b17134ed871c0703fac60e80dbd2dd8d163bd28eba9dff88b1e9bd1ae4a76&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8358f8f27f66caf3abf2ab7ebead7028bd465266a29d6d465e94ed3bf4a26e7820379f90db0ddd4eef534a8fba0257691579607ef99b3e8cc06dd9994ac7b226a5cdf3b2e2c691ac805a26045d984fdcfdda393fdff9d27db2d8e6f58d49e364&quot;
  deposit_data_root: &quot;0xa702f084aa633619824587a2a5aa49dbe17cdf12bfa499bcc15fb2139f2773a6&quot;
  eth1_data:
    deposit_root: &quot;0x490811983daeadcb303ff1b7ff46fd6cfcd36dd23b0ce7949b4ee1db7ad695ea&quot;
    deposit_count: &quot;120&quot;
    block_hash: &quot;0xa6354e31dc8b76a24c330aa6be59b256b11155ac456a21d04e4bdfd3a0e56ba9&quot;
  block_height: 121
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x0ff1cd5c2a584c83b12d7ad77a2e309ba97738719c0876302ce0ca1e9b02892e&quot;
      - &quot;0x750fa31940eac308088042d159ae2a9895b1c22f1b3aaf2faaaaf448dac52668&quot;
    deposit_root: &quot;0x490811983daeadcb303ff1b7ff46fd6cfcd36dd23b0ce7949b4ee1db7ad695ea&quot;
    deposit_count: 120
    execution_block_hash: &quot;0xa6354e31dc8b76a24c330aa6be59b256b11155ac456a21d04e4bdfd3a0e56ba9&quot;
    execution_block_height: 121
- deposit_data:
    pubkey: &quot;0x8ab4d3a78c54107bd7e71a0a006cb90dec379d6d86c9b6e4b3b010ceb37236cf2566febe76f955dbf0512884215f9f86&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x80ea3f9c01a6c761102737733f9e2f0911fafe3bededf9704e219c4537de0ad1cbc4e60a67447e1d25d53c24511ba3640d7aba5362c465042b7dbf40a7a8e0a5e8c002c511c36f7a45411e5770ceefa0571a5670fdf9fd2c0b6a4ca453866f73&quot;
  deposit_data_root: &quot;0x838301a371b334dc75bce42fbac042a519866b7fbd0741fdcacd54b584f1110a&quot;
  eth1_data:
    deposit_root: &quot;0x2d26430bf9f104f9295c2318bb2bd619f41f538ddb1407718bde5af1aa789926&quot;
    deposit_count: &quot;121&quot;
    block_hash: &quot;0x46004bd96b147395928f4342db995e0e5f8c84f6be8479f1713553bbfb32dc2a&quot;
  block_height: 122
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x0ff1cd5c2a584c83b12d7ad77a2e309ba97738719c0876302ce0ca1e9b02892e&quot;
      - &quot;0x750fa31940eac308088042d159ae2a9895b1c22f1b3aaf2faaaaf448dac52668&quot;
      - &quot;0x838301a371b334dc75bce42fbac042a519866b7fbd0741fdcacd54b584f1110a&quot;
    deposit_root: &quot;0x2d26430bf9f104f9295c2318bb2bd619f41f538ddb1407718bde5af1aa789926&quot;
    deposit_count: 121
    execution_block_hash: &quot;0x46004bd96b147395928f4342db995e0e5f8c84f6be8479f1713553bbfb32dc2a&quot;
    execution_block_height: 122
- deposit_data:
    pubkey: &quot;0x982d829cab4f09be252a2c57b77c166679b7e9fdf6f5cc882462b8f4dc9a90beb303c85af56304fb79b975d3643e2ed1&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa49e810bb59cc1194a7ccbd85e6571d2b3fb04372071e9f520bbc6a89f17ce2b4ea4e2efdd7566736e7415c2bb2d5cae19efa75295819f670b2e1a152e8eddda18de95518f2d8ff615f131030635b766504b98a0b72e8470f476ed70c86f3ace&quot;
  deposit_data_root: &quot;0xc8fe237e6c86c9da4429095bdfacab4dc1fd6a8145fb01abad35d9746e44ce9f&quot;
  eth1_data:
    deposit_root: &quot;0x46c5bd8627005a4b9e42e3844469187bec02232d2005a380c126d0c652cab644&quot;
    deposit_count: &quot;122&quot;
    block_hash: &quot;0x3472792b86ec4d8fcb0eafa369176a7c2f0836c1e258a0b136f20dc78c6fb5cc&quot;
  block_height: 123
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x0ff1cd5c2a584c83b12d7ad77a2e309ba97738719c0876302ce0ca1e9b02892e&quot;
      - &quot;0x750fa31940eac308088042d159ae2a9895b1c22f1b3aaf2faaaaf448dac52668&quot;
      - &quot;0x7504f9b600c756a12aa0e36a3cdeb84baf7704f65c12284994facedb4cb7130d&quot;
    deposit_root: &quot;0x46c5bd8627005a4b9e42e3844469187bec02232d2005a380c126d0c652cab644&quot;
    deposit_count: 122
    execution_block_hash: &quot;0x3472792b86ec4d8fcb0eafa369176a7c2f0836c1e258a0b136f20dc78c6fb5cc&quot;
    execution_block_height: 123
- deposit_data:
    pubkey: &quot;0x908ad5c41ba5fc8bea0cd8f028806a823bda814fcf6c2c32b5656c42b5d3061cfb077ecde2a50bf374e055e8d5dad4c7&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb557348bd23fe03c42a128cb692187bc5b6ad278a205080fb475e6fd80ae7ab4fa5d212e3124631fb3c8ba457cb8dfc009e3909b741811b93aa5cd82d8a79e6570c1bc7e21cb62cb4540d7588b1c09803fb8a5c5994b30b8e0675567a94db604&quot;
  deposit_data_root: &quot;0x5f3f0fad8eb6c5f9e0775ec949cdab9b768e3a35ff9f275dfba030661917ee01&quot;
  eth1_data:
    deposit_root: &quot;0x53ae75a6909e9c71ac74676e3a6d8b65f375b54444b70820da477d70eb3146d4&quot;
    deposit_count: &quot;123&quot;
    block_hash: &quot;0x731a443bb391702a1b35eedf368fe11f2707e192e5fa7f0c76cd4b3450486e39&quot;
  block_height: 124
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x0ff1cd5c2a584c83b12d7ad77a2e309ba97738719c0876302ce0ca1e9b02892e&quot;
      - &quot;0x750fa31940eac308088042d159ae2a9895b1c22f1b3aaf2faaaaf448dac52668&quot;
      - &quot;0x7504f9b600c756a12aa0e36a3cdeb84baf7704f65c12284994facedb4cb7130d&quot;
      - &quot;0x5f3f0fad8eb6c5f9e0775ec949cdab9b768e3a35ff9f275dfba030661917ee01&quot;
    deposit_root: &quot;0x53ae75a6909e9c71ac74676e3a6d8b65f375b54444b70820da477d70eb3146d4&quot;
    deposit_count: 123
    execution_block_hash: &quot;0x731a443bb391702a1b35eedf368fe11f2707e192e5fa7f0c76cd4b3450486e39&quot;
    execution_block_height: 124
- deposit_data:
    pubkey: &quot;0xab4de8ffccf7b19aa6d7d4ccc4c82f091ebd5715b5dd6680edf9eb4f0dfc312e8999b89a78a8d4ed4512aec75a5e5906&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9789f3948b7b284a5082da4e971859ab6d11ebd59bba14e25a5fe9f933148d151f7e831dbbb1d2219a3548aa77b64a970b630ff661ef87608c446c8ee87eefb8728afcc9d3f062955e2059dc22cbe43120777fcc0bc080adf513864869b53a1d&quot;
  deposit_data_root: &quot;0x5968e76b664c7a893bd1d6b4770e2ab6c367986489cb078bf9ebe15a7c37bcf0&quot;
  eth1_data:
    deposit_root: &quot;0xe61360c04f1c6070915102cc3c8e1da6f83689c00802a0a4d9421b597712b380&quot;
    deposit_count: &quot;124&quot;
    block_hash: &quot;0xe7d04b58be7cc09e2efaec16fc8acde80caf3dfe208a1f399464ef1e01c7c6a6&quot;
  block_height: 125
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x0ff1cd5c2a584c83b12d7ad77a2e309ba97738719c0876302ce0ca1e9b02892e&quot;
      - &quot;0x750fa31940eac308088042d159ae2a9895b1c22f1b3aaf2faaaaf448dac52668&quot;
      - &quot;0x000a10f9b9b70f1743febe640ecb94109a63a9e80299df2f72bf1882689e6293&quot;
    deposit_root: &quot;0xe61360c04f1c6070915102cc3c8e1da6f83689c00802a0a4d9421b597712b380&quot;
    deposit_count: 124
    execution_block_hash: &quot;0xe7d04b58be7cc09e2efaec16fc8acde80caf3dfe208a1f399464ef1e01c7c6a6&quot;
    execution_block_height: 125
- deposit_data:
    pubkey: &quot;0xb544d0df633f2334845f73a3921f2a716b9694baa6abcd7cedfa359ba3448029d5b874eef8b3f9f324f1ff4c0f997e97&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8fb8d58d8be318a8b649c3a74593aeb6c83698850be4571509ef5e2b053e3ace87583b89330b63a804fc56fec750be74030a530602fc80566be34a22b5a37389d036796f48619842b4b4169421c8deef8e745b2873e37fff345fedf94a395823&quot;
  deposit_data_root: &quot;0x69c57f789da4ec1bc1c89fd375a62a159775a522bb17763f98317770d40ae9a0&quot;
  eth1_data:
    deposit_root: &quot;0x0e122e727cad3ae0d09e532df6103c967179b5f7841b6e19b9d224e2abe11a40&quot;
    deposit_count: &quot;125&quot;
    block_hash: &quot;0x2ac76d9635e62e48f43779725791bc2955641b541ce279dfd8a1d4ee43242664&quot;
  block_height: 126
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x0ff1cd5c2a584c83b12d7ad77a2e309ba97738719c0876302ce0ca1e9b02892e&quot;
      - &quot;0x750fa31940eac308088042d159ae2a9895b1c22f1b3aaf2faaaaf448dac52668&quot;
      - &quot;0x000a10f9b9b70f1743febe640ecb94109a63a9e80299df2f72bf1882689e6293&quot;
      - &quot;0x69c57f789da4ec1bc1c89fd375a62a159775a522bb17763f98317770d40ae9a0&quot;
    deposit_root: &quot;0x0e122e727cad3ae0d09e532df6103c967179b5f7841b6e19b9d224e2abe11a40&quot;
    deposit_count: 125
    execution_block_hash: &quot;0x2ac76d9635e62e48f43779725791bc2955641b541ce279dfd8a1d4ee43242664&quot;
    execution_block_height: 126
- deposit_data:
    pubkey: &quot;0xab77bbaf0047e03ef4bb1ddaefb777f263c9dd556502f3078d51790653a59452f1455d23002e175ec5b541cb69007f8a&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x892fdcc974b84026d23901f0772bfcaaf8ed4817e8dd529525658a3f422e8248cad7fa34e9c6d12b3203fe211340b2a90ff420761424d417a446a66c8317f8b120e89c72b7a6ea0e822bfdeaa43fc4efee6568c7f0ce860c9c8499406ba58825&quot;
  deposit_data_root: &quot;0xae683dcb55578a08ab4cc416cbf6f9a4d400f611555ae3572f5be428049c264e&quot;
  eth1_data:
    deposit_root: &quot;0x2d75c60ef0c030b2cf8b18fa80490294476ed31bda31c346ba6c408d54bfb741&quot;
    deposit_count: &quot;126&quot;
    block_hash: &quot;0xea2226b57df5f18306352ff56c91e325260868a83fea4af3100d2adad1cad128&quot;
  block_height: 127
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x0ff1cd5c2a584c83b12d7ad77a2e309ba97738719c0876302ce0ca1e9b02892e&quot;
      - &quot;0x750fa31940eac308088042d159ae2a9895b1c22f1b3aaf2faaaaf448dac52668&quot;
      - &quot;0x000a10f9b9b70f1743febe640ecb94109a63a9e80299df2f72bf1882689e6293&quot;
      - &quot;0xeb193fa7b29a3c6c580bb7006a016eb539a1f3c2d0b529d8ca69462e48200c6b&quot;
    deposit_root: &quot;0x2d75c60ef0c030b2cf8b18fa80490294476ed31bda31c346ba6c408d54bfb741&quot;
    deposit_count: 126
    execution_block_hash: &quot;0xea2226b57df5f18306352ff56c91e325260868a83fea4af3100d2adad1cad128&quot;
    execution_block_height: 127
- deposit_data:
    pubkey: &quot;0xb56c50c51aa1ba14062d9a477ae78646c459bfe12fc1fa3362f0652077a0ba090a0b780ee0b58085ad2b885fa4a37d4e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x85654b45a591e3ef272bf2d4f55ea861e6c06781b79059c0e3a56c07f86d7eef1ceae1d61cdba178078852d34103fc160a9499a05792e08759d15b414a6e174d7d01495fceda5a13517da3b020f4bbf54aadee63765fd78834ba3d6e99a003f5&quot;
  deposit_data_root: &quot;0x1aafc611bf508823603b5049d2bf7238853a3e19edf7af77fb8fd0d4d0057214&quot;
  eth1_data:
    deposit_root: &quot;0xe9a1d8e3b5b5bce6fdcd79c03f4acb7efdd73eb1071a1974af2cfa6f02d40f91&quot;
    deposit_count: &quot;127&quot;
    block_hash: &quot;0xf1097ac5fc5fb25e73c35efe2e9e75acb6cbf842cded0e5912d59f67433c92e0&quot;
  block_height: 128
  snapshot:
    finalized:
      - &quot;0x7a8435cc00762702eb56b993adbe7f3b4f2e490152838e57fbbd87920ffc66d2&quot;
      - &quot;0x09a2fea2eb2470fc221e82ba026e7e9fe417bde2e54fafb68c804dc2a598cd59&quot;
      - &quot;0x0ff1cd5c2a584c83b12d7ad77a2e309ba97738719c0876302ce0ca1e9b02892e&quot;
      - &quot;0x750fa31940eac308088042d159ae2a9895b1c22f1b3aaf2faaaaf448dac52668&quot;
      - &quot;0x000a10f9b9b70f1743febe640ecb94109a63a9e80299df2f72bf1882689e6293&quot;
      - &quot;0xeb193fa7b29a3c6c580bb7006a016eb539a1f3c2d0b529d8ca69462e48200c6b&quot;
      - &quot;0x1aafc611bf508823603b5049d2bf7238853a3e19edf7af77fb8fd0d4d0057214&quot;
    deposit_root: &quot;0xe9a1d8e3b5b5bce6fdcd79c03f4acb7efdd73eb1071a1974af2cfa6f02d40f91&quot;
    deposit_count: 127
    execution_block_hash: &quot;0xf1097ac5fc5fb25e73c35efe2e9e75acb6cbf842cded0e5912d59f67433c92e0&quot;
    execution_block_height: 128
- deposit_data:
    pubkey: &quot;0x8bc5c1b16286219f479f6d00b0b31b193811b499a86139c45ff4350d8c9b492421e854cf75fba1a0dd566e6ead8ad667&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8c322ba5f9cfaffd49ce18217a4351f2bff820017197a676657a1d29d140d41697adb960d340ebf075808ca553bd594713c290beac55aecdc63f96f1da3ea0945360cc8ce7a8de60186ca7a25386a09b17f01d0f3f98c084ff9f998a2ac5fbdb&quot;
  deposit_data_root: &quot;0xfd64f7c42aff4433793cc1eceb1a97ed7e3dbd2f5588cd2c613b99fb2dd7ac03&quot;
  eth1_data:
    deposit_root: &quot;0x8aea1ce3d5cf89b67db5f909d4d50f4db94bd65fe6dba209e245d440a7723c71&quot;
    deposit_count: &quot;128&quot;
    block_hash: &quot;0x87ccd43a65dd5d36c0607edfaef9c6bd9d772e1b41da8140b5f93f23cf5a2c79&quot;
  block_height: 129
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
    deposit_root: &quot;0x8aea1ce3d5cf89b67db5f909d4d50f4db94bd65fe6dba209e245d440a7723c71&quot;
    deposit_count: 128
    execution_block_hash: &quot;0x87ccd43a65dd5d36c0607edfaef9c6bd9d772e1b41da8140b5f93f23cf5a2c79&quot;
    execution_block_height: 129
- deposit_data:
    pubkey: &quot;0xb7eaf282595bd590bde41f67783d12ccf7666aea2f1efbaeaa80c8478a157cf59ca7bf009e5a125163212b0b9f51c876&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb5c648bb5cf946f279dd63efdbc85bb7567aeb488fa82fc07094fc2a06306a9bafa1eb70f96d767d1a183838866704cd18157b2e00c7c3ab7c8e97b75533ea364042359d5860aeb6aac63fc88ab600d73e66e10056da3b3149056731fe71f228&quot;
  deposit_data_root: &quot;0xc72d087b5d20cfd70d9183225d0617b9829513337759db9764a466e391605f30&quot;
  eth1_data:
    deposit_root: &quot;0x4e1a7a0cdaa453f648dd2eee6e210e5ce1ced22668c8389b14b69cf390d06e41&quot;
    deposit_count: &quot;129&quot;
    block_hash: &quot;0x1daf3d0631736aff5da169b0fbfaaf76670e04bfb5f1d582847873089630a2c8&quot;
  block_height: 130
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xc72d087b5d20cfd70d9183225d0617b9829513337759db9764a466e391605f30&quot;
    deposit_root: &quot;0x4e1a7a0cdaa453f648dd2eee6e210e5ce1ced22668c8389b14b69cf390d06e41&quot;
    deposit_count: 129
    execution_block_hash: &quot;0x1daf3d0631736aff5da169b0fbfaaf76670e04bfb5f1d582847873089630a2c8&quot;
    execution_block_height: 130
- deposit_data:
    pubkey: &quot;0xb404c5cda4dad57827e456beecf745b1ed9f2bf776ca0eb806010b80b8912b683c288b4f231bb67c29ddfcdeb16ca909&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x89c8d47b8ef9e3282d2e9ba98c4d4cdf0fd362f210564e00a8531640fbbe574206826502ec05ea941cd31a5e591aa1b416230bf0aa78cdf74694681653c2b4e36286aa8d92d4086232d58e6b52096a526d4bbb476961d94202c63182b76b3ab0&quot;
  deposit_data_root: &quot;0xb38f387c64b9c9322cb74515298703ce4922ef2997c1064e4429f037f1609ebf&quot;
  eth1_data:
    deposit_root: &quot;0x5399bcc9eb6e3af50e9fba6c24424fa4df66ae4a13f6b03f7d50045c7c0c434f&quot;
    deposit_count: &quot;130&quot;
    block_hash: &quot;0x80ecd955e11b7c0379a794762c9e233d40df9af56efee83dcade1a18cad09982&quot;
  block_height: 131
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xc712b8c0610483895c01d4680ed4421cc67ee49d0792102971ff4642b82e36c3&quot;
    deposit_root: &quot;0x5399bcc9eb6e3af50e9fba6c24424fa4df66ae4a13f6b03f7d50045c7c0c434f&quot;
    deposit_count: 130
    execution_block_hash: &quot;0x80ecd955e11b7c0379a794762c9e233d40df9af56efee83dcade1a18cad09982&quot;
    execution_block_height: 131
- deposit_data:
    pubkey: &quot;0x944c4c5147a6b263898f335d2d59177c829d55901e5a4e394c9253cfbba6f0f3ce6ac393aa7b123f7a15db2909aaa37d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa46121a7594f41556fea16a1b3292312880391bce6deb315f12f445e326a2ed77b4a74007b876eaef7c8da205e00e6830bf6436dd332fa280ca379ede2c334279309527b076f1385c9e55da6319b3a534053cd4598a4979b35e136e81f7f2dda&quot;
  deposit_data_root: &quot;0xfc30a2ec2eb7b30f13ac732834306398cda4fc65e4677ef007bec1a3d5dbf18c&quot;
  eth1_data:
    deposit_root: &quot;0x8a0505df56a0bc3b337baea7a403e6076f751267b9b0b32eb3f377a4c7464098&quot;
    deposit_count: &quot;131&quot;
    block_hash: &quot;0x1a51a4d2db3c6a25fac8e8df0962130e493850d808d3a798dbaa7b3cdaea01f5&quot;
  block_height: 132
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xc712b8c0610483895c01d4680ed4421cc67ee49d0792102971ff4642b82e36c3&quot;
      - &quot;0xfc30a2ec2eb7b30f13ac732834306398cda4fc65e4677ef007bec1a3d5dbf18c&quot;
    deposit_root: &quot;0x8a0505df56a0bc3b337baea7a403e6076f751267b9b0b32eb3f377a4c7464098&quot;
    deposit_count: 131
    execution_block_hash: &quot;0x1a51a4d2db3c6a25fac8e8df0962130e493850d808d3a798dbaa7b3cdaea01f5&quot;
    execution_block_height: 132
- deposit_data:
    pubkey: &quot;0x97dfc5eb14556d1a85e34c069da71fc5e1bb5e17b421d9503f25d76a8f3cd0f2f9c5a1937e785e1c0e73edb6561dd176&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x82d599849169580c5cfe93e84ecf5935ab27dc88447836eb4f9d9d1875d8d5131356e5b220d6ef92de2cc8eb93e6301c0ca1107e2b33a0cfe4a82dcb0cea523bb223e47b91eeb8fda927ac6b951d5741004e2e2340a451649b266df4dcbcb38b&quot;
  deposit_data_root: &quot;0x0efa199eadc389a2e5876ed70eabd6fdb57b124fef39391a43197a06d4d12a9a&quot;
  eth1_data:
    deposit_root: &quot;0x6ff97ae565976870078e1d2df2f544fa9a9f52e522445e9613cbb9d6d0e0ae34&quot;
    deposit_count: &quot;132&quot;
    block_hash: &quot;0x5b5b8e0f913eb2cff3476e7e7cba6efc247b50f863093abe9184daa9c43ffffe&quot;
  block_height: 133
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x21919d31feaad9b4f0198aa85b8c92b9162acdb2be06e4fbb76488dce29f6409&quot;
    deposit_root: &quot;0x6ff97ae565976870078e1d2df2f544fa9a9f52e522445e9613cbb9d6d0e0ae34&quot;
    deposit_count: 132
    execution_block_hash: &quot;0x5b5b8e0f913eb2cff3476e7e7cba6efc247b50f863093abe9184daa9c43ffffe&quot;
    execution_block_height: 133
- deposit_data:
    pubkey: &quot;0x9145e0920e276f19fe65b9ea81339a41dee6e21ca12512005701a014426322be4fe504f853d6ae48314902fe9ff50a43&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xafaab29ec6f5ea64ebde52ec7d3fc4ec1eca00c799f9b73b51f40a59d8047d2623c7bc92456c3754a79c0b62c722db85113cb8bdcede6b95093a591f43f63098f9d558fb898f4098d6c731534288343e6b23fe04b1b0d36e49cdc03b6a097a51&quot;
  deposit_data_root: &quot;0x8e2528c2d652e704bf50d274aa2f813cab8038b2f0c6242556fe38e4ee1342a7&quot;
  eth1_data:
    deposit_root: &quot;0xc9c06b3a8f036dac268ac85aca78bc258b292b53bb870d6bb65d2e4400eee5a3&quot;
    deposit_count: &quot;133&quot;
    block_hash: &quot;0x5668a8e6259e5716d8988973626760ed0f8f381d0553230e5b74a5a9f01dcebe&quot;
  block_height: 134
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x21919d31feaad9b4f0198aa85b8c92b9162acdb2be06e4fbb76488dce29f6409&quot;
      - &quot;0x8e2528c2d652e704bf50d274aa2f813cab8038b2f0c6242556fe38e4ee1342a7&quot;
    deposit_root: &quot;0xc9c06b3a8f036dac268ac85aca78bc258b292b53bb870d6bb65d2e4400eee5a3&quot;
    deposit_count: 133
    execution_block_hash: &quot;0x5668a8e6259e5716d8988973626760ed0f8f381d0553230e5b74a5a9f01dcebe&quot;
    execution_block_height: 134
- deposit_data:
    pubkey: &quot;0x836c4b67713b082c060003d8fc839e265c1aca7f9bb82ce07f71a459d39073ebfdca87609859c70e55a1b0e7a613b395&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa04db5e044437271fd78d17b8f68970582937d883f11957506eb5a03e751ee98b10788be39acaa54ac43fdaf233d17470e7cbdaa7696e13a095e4cc2f1198e080f7d263b0e2f94f987d111ff479a24707b426aadee55e9df8aed27cf2f214c87&quot;
  deposit_data_root: &quot;0x3a112eabe9f6e71d1909cef64d68d32ff8ceeeed9247f628babab96f83f4c748&quot;
  eth1_data:
    deposit_root: &quot;0xff0787b73d84f56a8d8c4f58ee259b2a799758380be7452d30200be34a2b1697&quot;
    deposit_count: &quot;134&quot;
    block_hash: &quot;0xf158ad39fac4114d21115c72d76ef1486378b8bb3972904973e3bf415093e86f&quot;
  block_height: 135
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x21919d31feaad9b4f0198aa85b8c92b9162acdb2be06e4fbb76488dce29f6409&quot;
      - &quot;0x27ef184d8974736eab9799399f71b459bd5a849f57939017510488c06a92471a&quot;
    deposit_root: &quot;0xff0787b73d84f56a8d8c4f58ee259b2a799758380be7452d30200be34a2b1697&quot;
    deposit_count: 134
    execution_block_hash: &quot;0xf158ad39fac4114d21115c72d76ef1486378b8bb3972904973e3bf415093e86f&quot;
    execution_block_height: 135
- deposit_data:
    pubkey: &quot;0xb5217af9139deb6be95a106c7651e1d8dcd8eaa04f3c6196dd52abad84c862724603686f90c7c2a985f2d75a1c8facdc&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x85a96d2f00884fe1e363e875256bccc230716611daa78efc84425b051008e606401bf9b5413b9b8f806b2177cf7d1cf20cd75f895c8a69c7cb59ff553af9fcc1dbb33c360a1834daa1efb5fe57322303fabde1f93e692c96b4bbfed668ab6268&quot;
  deposit_data_root: &quot;0xaa6054d15854b80f7ec7eaae6dee3a436a3fbc7a5b960d5a63b87cda94d45467&quot;
  eth1_data:
    deposit_root: &quot;0x450e75beff47dda09d642c64023e985bb9b4084c3ebb3fd93cee4ff6ecedca3f&quot;
    deposit_count: &quot;135&quot;
    block_hash: &quot;0x768e4089d2988baf80e8a20e391ae3827a2018cf543e42831949ee31d9abcb51&quot;
  block_height: 136
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x21919d31feaad9b4f0198aa85b8c92b9162acdb2be06e4fbb76488dce29f6409&quot;
      - &quot;0x27ef184d8974736eab9799399f71b459bd5a849f57939017510488c06a92471a&quot;
      - &quot;0xaa6054d15854b80f7ec7eaae6dee3a436a3fbc7a5b960d5a63b87cda94d45467&quot;
    deposit_root: &quot;0x450e75beff47dda09d642c64023e985bb9b4084c3ebb3fd93cee4ff6ecedca3f&quot;
    deposit_count: 135
    execution_block_hash: &quot;0x768e4089d2988baf80e8a20e391ae3827a2018cf543e42831949ee31d9abcb51&quot;
    execution_block_height: 136
- deposit_data:
    pubkey: &quot;0xa38b021855057c62bac15b2de83156dc8649bad858327b10cbab68c8fa3613a3de698322826d2644652ca9ef92664cb3&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xaa8634b7543bd89635688f7842e0202b9430332a39d6ad9670277543387708e06466c21747af713f1c6cdf62f78e96411191d7bbd079322d3c6bbf1fc4f739ca4f6a77b304566a3a77768188efde4e240fa78245d5943a3a601192112a334a76&quot;
  deposit_data_root: &quot;0xfef7a5178631d697d14133c15287f33d6a2ccb3e6efe5dd46022965eca0f23fb&quot;
  eth1_data:
    deposit_root: &quot;0x9825f4b4b017dde1e6fda6ebb8a809409d57cc060bf19d44a9a898a26f75d50e&quot;
    deposit_count: &quot;136&quot;
    block_hash: &quot;0x051c8ee04d7535b585729a7ead7016d35ccd323e274e39a000a4d302bf454de5&quot;
  block_height: 137
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x52228e1e54f9b75dbb4c3e67d77e36c395d945cb6a4b5494c18eb1218db1ebb2&quot;
    deposit_root: &quot;0x9825f4b4b017dde1e6fda6ebb8a809409d57cc060bf19d44a9a898a26f75d50e&quot;
    deposit_count: 136
    execution_block_hash: &quot;0x051c8ee04d7535b585729a7ead7016d35ccd323e274e39a000a4d302bf454de5&quot;
    execution_block_height: 137
- deposit_data:
    pubkey: &quot;0x828b5be17d71a278644b6fbe7ab5fd3a065312d1b03734e0b9d74703a566dc99815c81fc50b13725961376edc2f54405&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x89235bcafefc07c6ed61bc483071b76d22e0881272925d61d8178942b701797d907ad10a3ef967df5f647863540e70d6052ba3814abffac5acb8bcadeb41b9c393dd2d664871535e6984725c7cdac5c1433abb7e05f06adcf75fd2c3a8e096f3&quot;
  deposit_data_root: &quot;0xae3d1bd187858e08287ed35692a78547ca791719a1cab975707b4c4c023d1f12&quot;
  eth1_data:
    deposit_root: &quot;0xf52b85738cb675d5d8f894f5653ed2e05cf513faae7dbec06e9b1841510d3bdc&quot;
    deposit_count: &quot;137&quot;
    block_hash: &quot;0x0bfaadbce1850c4917a8e7b161d3c926ce11488ae996ade89332e76c3c26e30b&quot;
  block_height: 138
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x52228e1e54f9b75dbb4c3e67d77e36c395d945cb6a4b5494c18eb1218db1ebb2&quot;
      - &quot;0xae3d1bd187858e08287ed35692a78547ca791719a1cab975707b4c4c023d1f12&quot;
    deposit_root: &quot;0xf52b85738cb675d5d8f894f5653ed2e05cf513faae7dbec06e9b1841510d3bdc&quot;
    deposit_count: 137
    execution_block_hash: &quot;0x0bfaadbce1850c4917a8e7b161d3c926ce11488ae996ade89332e76c3c26e30b&quot;
    execution_block_height: 138
- deposit_data:
    pubkey: &quot;0x956aeb449c6e00e75a7795ea552bb0a2c14e065bfc9fee78c5a337f9d0c1814045802ad4f2e3c60868e54cd381809cca&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x819db83518bfe3262416f3592dc4a98a7811decc1c2e3b75adbec61e503cf31adc93bb0ab7167f5cb5659a4836dbb047141c61f810b392c68f8abba9699131fef029ad3ed054895b35c599460a3c3c25a9c0290bd3d4a51806cacef247589af9&quot;
  deposit_data_root: &quot;0x7863ebf9d15b7d7faf3eaa9c5921396b467c452ae27d2a17cf873fd03ebeb5b4&quot;
  eth1_data:
    deposit_root: &quot;0xa5000d5a716be585c7263959af46459fe207ccfee4b131e340db755d7841b6e3&quot;
    deposit_count: &quot;138&quot;
    block_hash: &quot;0x7e3ff3c5214e2e9d1bf033fbd58772d2df71241ff00f285e467559ba2c435729&quot;
  block_height: 139
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x52228e1e54f9b75dbb4c3e67d77e36c395d945cb6a4b5494c18eb1218db1ebb2&quot;
      - &quot;0x4e197bcd1ccf6d1ef8b4b3c658d14cb45b72045390d6afc86479c562d99290ee&quot;
    deposit_root: &quot;0xa5000d5a716be585c7263959af46459fe207ccfee4b131e340db755d7841b6e3&quot;
    deposit_count: 138
    execution_block_hash: &quot;0x7e3ff3c5214e2e9d1bf033fbd58772d2df71241ff00f285e467559ba2c435729&quot;
    execution_block_height: 139
- deposit_data:
    pubkey: &quot;0xa0ab6917fd4c65ff95b1a5ed5f3c0d7cef103de58a90f2cc5383b4914566aa085f04e8505c862a29a0c914072746f83a&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8b99987e93032d8d9d07d726957fe4394b818ee34dec214aa6dcdb1469f0ed7aa0dfeb4ed805baf48ef287f97b9058140262f05105769e65decbac6d3df02f712cfb0ad7a2ff65eba13fcc167d94d993f8c3148143731d4eb028ec23902443a9&quot;
  deposit_data_root: &quot;0x4fc27de5f8c8d68da0bb0258d0151521fbac62e4967c08b8876cd976ba113e59&quot;
  eth1_data:
    deposit_root: &quot;0x270aab20e630999f0ebe072b5f955d7d0b6f0919157002eab351eef7873a9b1a&quot;
    deposit_count: &quot;139&quot;
    block_hash: &quot;0x294cb83538800d76ddc52bd16c33ff956de7f5b94d9419178b50824aefeed6b5&quot;
  block_height: 140
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x52228e1e54f9b75dbb4c3e67d77e36c395d945cb6a4b5494c18eb1218db1ebb2&quot;
      - &quot;0x4e197bcd1ccf6d1ef8b4b3c658d14cb45b72045390d6afc86479c562d99290ee&quot;
      - &quot;0x4fc27de5f8c8d68da0bb0258d0151521fbac62e4967c08b8876cd976ba113e59&quot;
    deposit_root: &quot;0x270aab20e630999f0ebe072b5f955d7d0b6f0919157002eab351eef7873a9b1a&quot;
    deposit_count: 139
    execution_block_hash: &quot;0x294cb83538800d76ddc52bd16c33ff956de7f5b94d9419178b50824aefeed6b5&quot;
    execution_block_height: 140
- deposit_data:
    pubkey: &quot;0x93e08f94b3c1e5e9e7454185c5493111db66673fa0f1ba86d7a395858a32fd2c2ccd0c4838affb453112f0e9a8e3a370&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xadf8d364f8bfd7352b5423ec6e9891d9dda14132bb5fca8ec977b3eebda7df0e67a3dbf69e7c470714ef28028cb4190b18c5c998b8ec2d65089e4f1e89ef078c3b3d20f8a1c223a4d19cf7b6fe94be511c6633da6d64f2c60148926bb05f284f&quot;
  deposit_data_root: &quot;0x394d27e70621db71ab9db062b080a827591c330679e0db882e6086d1ce0004df&quot;
  eth1_data:
    deposit_root: &quot;0x6a884aaac611577d4a3e6b1beda285d44e45c7908553df6142fcf83dfb30dfe2&quot;
    deposit_count: &quot;140&quot;
    block_hash: &quot;0x2ce6dbcabe45faa4be2c1f491500699fab5011beb8f8edfa6125188d5c75f474&quot;
  block_height: 141
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x52228e1e54f9b75dbb4c3e67d77e36c395d945cb6a4b5494c18eb1218db1ebb2&quot;
      - &quot;0x94db8bffb5c1311bba8a0713a8cb1ae95ce40c9b0dc482ffc6273482df8a11eb&quot;
    deposit_root: &quot;0x6a884aaac611577d4a3e6b1beda285d44e45c7908553df6142fcf83dfb30dfe2&quot;
    deposit_count: 140
    execution_block_hash: &quot;0x2ce6dbcabe45faa4be2c1f491500699fab5011beb8f8edfa6125188d5c75f474&quot;
    execution_block_height: 141
- deposit_data:
    pubkey: &quot;0x907c4f53d28167c96d711746d338b7428e7ffa389ec76497920c25445df3b1ce7e88648a5fa9f4e1b5d2d254938bb65a&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb718c98631b6896423bc477b0c6b6c38aad77af35657008c27a760225c17f1d83244c9e67b031d1ff54696774c9e03a70397a5377b9ee1a4f05b4086659fefcad9e8e8992feefa489b51e35063789424dda7cef6c87a5a52ffedd58f87e9e1dc&quot;
  deposit_data_root: &quot;0x27c015fcfe5104cd1c8d15aefb823bde65e61ea352c3b2d2886eb671caa5e700&quot;
  eth1_data:
    deposit_root: &quot;0x34867700acac7b229aa98c88283ca0967e781d7640ffe43521d8f32a43b44521&quot;
    deposit_count: &quot;141&quot;
    block_hash: &quot;0xdd2ca2e628c5fe5f8e641e57a076568b40c0a85522cc2e0860f38eeff295e68f&quot;
  block_height: 142
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x52228e1e54f9b75dbb4c3e67d77e36c395d945cb6a4b5494c18eb1218db1ebb2&quot;
      - &quot;0x94db8bffb5c1311bba8a0713a8cb1ae95ce40c9b0dc482ffc6273482df8a11eb&quot;
      - &quot;0x27c015fcfe5104cd1c8d15aefb823bde65e61ea352c3b2d2886eb671caa5e700&quot;
    deposit_root: &quot;0x34867700acac7b229aa98c88283ca0967e781d7640ffe43521d8f32a43b44521&quot;
    deposit_count: 141
    execution_block_hash: &quot;0xdd2ca2e628c5fe5f8e641e57a076568b40c0a85522cc2e0860f38eeff295e68f&quot;
    execution_block_height: 142
- deposit_data:
    pubkey: &quot;0x987b620dd2ade22c44ac3a642d17ac9009da6c2d989028957da877e5178668216cb9ad2314a520ebeeb8b032614ca2f7&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb5294d4bad5d63db39d236813cbc1032093b8c7649d28b4b2515c03855f56d78ee8b243e6b29935d83d6a9ce344d2ae618894c91dd7cd82eebe2020938f55ee77b95118ecfc2a80792b23e75251396cb09edad531138fc2129d3442934472fea&quot;
  deposit_data_root: &quot;0x55bcef5f8cc010243428b8c8d96fa0cade22f5df82fdd813c337482189f7d33e&quot;
  eth1_data:
    deposit_root: &quot;0x6343479ad51df7360082d3c7736a119a9cf461dfe40f749490b98cd60c48b1d8&quot;
    deposit_count: &quot;142&quot;
    block_hash: &quot;0x3fdc183d26e681a76cb366df8540c48422832c01893da752c20c02764f3e42ef&quot;
  block_height: 143
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x52228e1e54f9b75dbb4c3e67d77e36c395d945cb6a4b5494c18eb1218db1ebb2&quot;
      - &quot;0x94db8bffb5c1311bba8a0713a8cb1ae95ce40c9b0dc482ffc6273482df8a11eb&quot;
      - &quot;0x61ecb3ba1163a8bd70a0c91060a0d7df5c5f1d429222c6da2628d42f51140b8b&quot;
    deposit_root: &quot;0x6343479ad51df7360082d3c7736a119a9cf461dfe40f749490b98cd60c48b1d8&quot;
    deposit_count: 142
    execution_block_hash: &quot;0x3fdc183d26e681a76cb366df8540c48422832c01893da752c20c02764f3e42ef&quot;
    execution_block_height: 143
- deposit_data:
    pubkey: &quot;0xb4bb3db19f9162fb238ddbdbf5b8e819696e90783775249825d64767625f2b6e9c52edd859bf8afac8a87371e9100d24&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xadbff5ad606002d50ac669f878194974fb3f338b8301fb46426e92b4e65309b1eabf85441ddd75dadd6eec5293ee05df0860040dbf875e698cb23cadd960b8eb23674a86795bca545385e8b03b847ab4ac7970a6b2a73b960e54866b11fbd1ab&quot;
  deposit_data_root: &quot;0x79b12382ebfde996e7dc957b826c432d14eb7f3a3b61c61800707f60c4bf193a&quot;
  eth1_data:
    deposit_root: &quot;0x4095812eaf8df557e3e6c36dd16b99952769d623281342926d22b6d07d270553&quot;
    deposit_count: &quot;143&quot;
    block_hash: &quot;0xc782ae505c8831621b6d9afd7fff61d359f1d39248aae61504d561695fbb8d10&quot;
  block_height: 144
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x52228e1e54f9b75dbb4c3e67d77e36c395d945cb6a4b5494c18eb1218db1ebb2&quot;
      - &quot;0x94db8bffb5c1311bba8a0713a8cb1ae95ce40c9b0dc482ffc6273482df8a11eb&quot;
      - &quot;0x61ecb3ba1163a8bd70a0c91060a0d7df5c5f1d429222c6da2628d42f51140b8b&quot;
      - &quot;0x79b12382ebfde996e7dc957b826c432d14eb7f3a3b61c61800707f60c4bf193a&quot;
    deposit_root: &quot;0x4095812eaf8df557e3e6c36dd16b99952769d623281342926d22b6d07d270553&quot;
    deposit_count: 143
    execution_block_hash: &quot;0xc782ae505c8831621b6d9afd7fff61d359f1d39248aae61504d561695fbb8d10&quot;
    execution_block_height: 144
- deposit_data:
    pubkey: &quot;0xaa083a83471b7938693e54b673d98f90340fe5cd2556b27eeb9c9069b7150e853391d47543dab155f6fdc8ab7f2e185a&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xaf55c3b8d00ede905a7e5a546aef5e817f540950cfcb04fd86a16f4574897c7118d1a971cb06018ea5a8d59b673a6e19060462b839135255e8790d9c2152fe2497f090027242091f0fa19d957524046f920b4e980631216d9ad88ffae00894ab&quot;
  deposit_data_root: &quot;0x62f0c56109eaf759c780578e7fa47725568ac9c4b417a79f75e0778b98f8dac6&quot;
  eth1_data:
    deposit_root: &quot;0xaab06426f70faa1c4f596a4f42f15dcfff709218d7f4c479835e15d0f7612f82&quot;
    deposit_count: &quot;144&quot;
    block_hash: &quot;0xa8bd5909dae96b248a94193373f3ebc4050994aee8ec82e5eaf61530e66ba126&quot;
  block_height: 145
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xaf12585229c24dfcac5f5fa3ac66011dabdfd39529f6d98c07abfa998c1b4e52&quot;
    deposit_root: &quot;0xaab06426f70faa1c4f596a4f42f15dcfff709218d7f4c479835e15d0f7612f82&quot;
    deposit_count: 144
    execution_block_hash: &quot;0xa8bd5909dae96b248a94193373f3ebc4050994aee8ec82e5eaf61530e66ba126&quot;
    execution_block_height: 145
- deposit_data:
    pubkey: &quot;0x916d306c24956c1a97678695330d240cb492062889dbfbaa6349cf53259c719ef83748b065e4a30fa6edf8a171af326b&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8c8963319e8e7e3dab0c8048410b8818fa648f4a4e337d06d2226e5732ce99e8089103886812055eee70315a028ea5b3044691168068d150967f6dd432e585fdfc9ac2d5b593add5e671ec6a1ef1fecf265fbe43f564b1d63ca3ed6dc1d1d49d&quot;
  deposit_data_root: &quot;0xb779d0910d0c595a2fe92c63c2e8882f2e0db6c55f749864cda06e9ab53a1175&quot;
  eth1_data:
    deposit_root: &quot;0xd41b2fb56eabbe8a5494e16f53677b85e8329a31bc1b106c57e0d67ec4f08c2b&quot;
    deposit_count: &quot;145&quot;
    block_hash: &quot;0x59e61e4cbfabe9ebff9d7632bd4946b9b34b40bd189866c9d3a300f7e88584ff&quot;
  block_height: 146
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xaf12585229c24dfcac5f5fa3ac66011dabdfd39529f6d98c07abfa998c1b4e52&quot;
      - &quot;0xb779d0910d0c595a2fe92c63c2e8882f2e0db6c55f749864cda06e9ab53a1175&quot;
    deposit_root: &quot;0xd41b2fb56eabbe8a5494e16f53677b85e8329a31bc1b106c57e0d67ec4f08c2b&quot;
    deposit_count: 145
    execution_block_hash: &quot;0x59e61e4cbfabe9ebff9d7632bd4946b9b34b40bd189866c9d3a300f7e88584ff&quot;
    execution_block_height: 146
- deposit_data:
    pubkey: &quot;0x89d9aef34711c5ea0787f591e4683f34727391729c0a402702a51de4d6a36a9324e1c77890a1b34c70a06d30bf9cb0c9&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa558bdece7dc28e7a68298edb2b4d9277e21c590ec58c8e9cbf85560ce442eb91b5d35be159961dded127f612a232bff0b8df1043e6d592a498d2f672032a443e3a235337b2aeb596cc24bd20aab9001357399c450dd911107e6860e061bc6b2&quot;
  deposit_data_root: &quot;0x952e03098c3a3e617b2085b2f360883902c7560615ef16f06ad87aeef11d4b13&quot;
  eth1_data:
    deposit_root: &quot;0x42a6aa131d749068ece539bb5dd92c0b35abadaf3fdd09e6dbbfbe3a9864a4de&quot;
    deposit_count: &quot;146&quot;
    block_hash: &quot;0xdbdcb5286172a0827e2cf09afb3ec1a5edf6210eceed78570a82ec9b985793ef&quot;
  block_height: 147
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xaf12585229c24dfcac5f5fa3ac66011dabdfd39529f6d98c07abfa998c1b4e52&quot;
      - &quot;0xfcb2cabbd2e78c7299e4090c745a5f70f964f9609e16ef7dbf822ec6be390b5a&quot;
    deposit_root: &quot;0x42a6aa131d749068ece539bb5dd92c0b35abadaf3fdd09e6dbbfbe3a9864a4de&quot;
    deposit_count: 146
    execution_block_hash: &quot;0xdbdcb5286172a0827e2cf09afb3ec1a5edf6210eceed78570a82ec9b985793ef&quot;
    execution_block_height: 147
- deposit_data:
    pubkey: &quot;0xa3cc6919919abf050a3e64b6c5d826148ee3f766e6b67e7e8000645e51ebed1b9c6a20b9b7413a4eb835529cbe4f77a9&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb5eebafdde0dcf96d9ed536932dac3368f11890a1c9047ce33777dd864b8edb96d627c643dc10a1ad25704bdc94a10d81163c449b7cb1298523fe6817f78d6c99a89bea5c444452057a26a8002b66129b895f24ca1e5594b07fcff0734df654d&quot;
  deposit_data_root: &quot;0x416f86acf71961090832d765a7a736ecf18cbb6a1fd9f1e42ba0ba99abcc5a1c&quot;
  eth1_data:
    deposit_root: &quot;0xd0c5fe81027e3262bf1682a130fb3952371006f707a02c98cef95952e116b566&quot;
    deposit_count: &quot;147&quot;
    block_hash: &quot;0x762506294eb00ae05c84543d9b495e2b0b24047aa0ff1d747ff474498d1176eb&quot;
  block_height: 148
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xaf12585229c24dfcac5f5fa3ac66011dabdfd39529f6d98c07abfa998c1b4e52&quot;
      - &quot;0xfcb2cabbd2e78c7299e4090c745a5f70f964f9609e16ef7dbf822ec6be390b5a&quot;
      - &quot;0x416f86acf71961090832d765a7a736ecf18cbb6a1fd9f1e42ba0ba99abcc5a1c&quot;
    deposit_root: &quot;0xd0c5fe81027e3262bf1682a130fb3952371006f707a02c98cef95952e116b566&quot;
    deposit_count: 147
    execution_block_hash: &quot;0x762506294eb00ae05c84543d9b495e2b0b24047aa0ff1d747ff474498d1176eb&quot;
    execution_block_height: 148
- deposit_data:
    pubkey: &quot;0xaa70cfdc554a8e67bbd3e6f3d2a0ef61c2a7ce1784acef01e9d7f08ee3a4723c2b7bd789c4bb687f19466a58e6e7bb34&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x937471d746fdc9d2bdc43b70133bf53b8c934685e3a220b02d6615648ff1c2d17afe93e5e8844825a1e71e30269e703d02cf89a01ea5737c58964ecbb42ec4736721f66cf549231b1baf839ad3775665ee3db8f5af6c7abc76fe4985e881f3d9&quot;
  deposit_data_root: &quot;0x11fa92b165b8cdd90432e623dd16b219357f7258304be89741c3748fc2b07281&quot;
  eth1_data:
    deposit_root: &quot;0xabbeb3c7c12ac8ea30a18ca7f4953f788c6d7b6d28375d597ab8188ae4750442&quot;
    deposit_count: &quot;148&quot;
    block_hash: &quot;0x49319e6b9bd5b42ee760b78a016ff8c3472c40c0aa015f6f64c26f8ec9b73da4&quot;
  block_height: 149
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xaf12585229c24dfcac5f5fa3ac66011dabdfd39529f6d98c07abfa998c1b4e52&quot;
      - &quot;0x2f36ad9e26bd49169087381023a518ca363e37b699bea22fb07fe8fc2da3721a&quot;
    deposit_root: &quot;0xabbeb3c7c12ac8ea30a18ca7f4953f788c6d7b6d28375d597ab8188ae4750442&quot;
    deposit_count: 148
    execution_block_hash: &quot;0x49319e6b9bd5b42ee760b78a016ff8c3472c40c0aa015f6f64c26f8ec9b73da4&quot;
    execution_block_height: 149
- deposit_data:
    pubkey: &quot;0xa1a1b99827c25c1079d4ed035a31478a38c2141db49291d0fcd10b64eb6ee5b0d9e758a9b47f40b2092f1c150bc28e11&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa843d0ca06dc76c42f57ccc9a5f50b5c17f39135ed33d3eef9a9b88826c3cf5dae2e1991f40163184ed4cf375d37ac2f147c75eb8b4e3790ff510008c0960eec1c5bca5af9c7e4ddf81277acdfe4f264cbd5d1cc1608b0f3db2fe000e2edb789&quot;
  deposit_data_root: &quot;0x1bc04fb54834e25adfacf21f8408527b4ada1fb47d5355cf0024436cadb5df12&quot;
  eth1_data:
    deposit_root: &quot;0x4165f4725bc2e58cef28e6a287ba3fd6bf46f445fc65b67d383d7d6b7bf709cd&quot;
    deposit_count: &quot;149&quot;
    block_hash: &quot;0xc5a9ec49e34f270b82dd423e53c924b72387fe2987f8b0ba039efaea92a57b63&quot;
  block_height: 150
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xaf12585229c24dfcac5f5fa3ac66011dabdfd39529f6d98c07abfa998c1b4e52&quot;
      - &quot;0x2f36ad9e26bd49169087381023a518ca363e37b699bea22fb07fe8fc2da3721a&quot;
      - &quot;0x1bc04fb54834e25adfacf21f8408527b4ada1fb47d5355cf0024436cadb5df12&quot;
    deposit_root: &quot;0x4165f4725bc2e58cef28e6a287ba3fd6bf46f445fc65b67d383d7d6b7bf709cd&quot;
    deposit_count: 149
    execution_block_hash: &quot;0xc5a9ec49e34f270b82dd423e53c924b72387fe2987f8b0ba039efaea92a57b63&quot;
    execution_block_height: 150
- deposit_data:
    pubkey: &quot;0x87af7702ff5e6e9a4416bbb516c3aeec7827408b75e3d1a8d420031157ba7a5a4d1eb565d29f100c5cdaddc05399bce1&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xad97e9253436103fbb79067fea41d3db0b36abbbf2c9a345ac838a16b93ebc6fa0414bbe4c96514c67dfb5e4d207df200bb413b4ea1be94dbaf9d008c49aeb2fdd0552dbcf171e0f8a6fa89bfb6139d606b5ed0765b4047c489999bcbac53c24&quot;
  deposit_data_root: &quot;0x1d331b2e13e8ff1333f00c80b5de05a294bfeb904d782e6636461a4ec01cca24&quot;
  eth1_data:
    deposit_root: &quot;0x5f04ee7b040e36e61c3abf826d86c178cadd08541f545298c02d6fcfe7defae5&quot;
    deposit_count: &quot;150&quot;
    block_hash: &quot;0xe44b8c19d80353eaaebdbad5689d94f2c68ce2977dd2c687ee64560e75bd46e4&quot;
  block_height: 151
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xaf12585229c24dfcac5f5fa3ac66011dabdfd39529f6d98c07abfa998c1b4e52&quot;
      - &quot;0x2f36ad9e26bd49169087381023a518ca363e37b699bea22fb07fe8fc2da3721a&quot;
      - &quot;0xdecd5c32fc1a5a55f4b2dff4cefc1b493884d7c78f74b3d9c399f3a583ba4aa8&quot;
    deposit_root: &quot;0x5f04ee7b040e36e61c3abf826d86c178cadd08541f545298c02d6fcfe7defae5&quot;
    deposit_count: 150
    execution_block_hash: &quot;0xe44b8c19d80353eaaebdbad5689d94f2c68ce2977dd2c687ee64560e75bd46e4&quot;
    execution_block_height: 151
- deposit_data:
    pubkey: &quot;0x8db57d195b1216309f3182f522ee9c6a724af5eebfc8faf058edb4e444a74f7ca9fb0f227a7960887abf8ec4697ef4d2&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xac2c9dfc4a9bfb53a71b7647109bcf478924d240e2501655e30e4fa4db22bd7f004513f5600dc19cd66141ecd1ff775904b8085d23885c3a414fb8883bd7676b32f008dd84beb2e32ff444a9e7c047cb2884ff998644aa5ffde04acb7a1a952a&quot;
  deposit_data_root: &quot;0x664b99054c780ab51854845d95d8ccad24d1f9a45fbadf4f04664f9e533da249&quot;
  eth1_data:
    deposit_root: &quot;0x1bece2bb88b659bbafbd110cbc8d8765c5488f30389cc03a4b48730f8324f501&quot;
    deposit_count: &quot;151&quot;
    block_hash: &quot;0xc5ed7232fa2461e41d333f13bfd2e3e7f113aef12fe4e465f1c9ad345f140679&quot;
  block_height: 152
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xaf12585229c24dfcac5f5fa3ac66011dabdfd39529f6d98c07abfa998c1b4e52&quot;
      - &quot;0x2f36ad9e26bd49169087381023a518ca363e37b699bea22fb07fe8fc2da3721a&quot;
      - &quot;0xdecd5c32fc1a5a55f4b2dff4cefc1b493884d7c78f74b3d9c399f3a583ba4aa8&quot;
      - &quot;0x664b99054c780ab51854845d95d8ccad24d1f9a45fbadf4f04664f9e533da249&quot;
    deposit_root: &quot;0x1bece2bb88b659bbafbd110cbc8d8765c5488f30389cc03a4b48730f8324f501&quot;
    deposit_count: 151
    execution_block_hash: &quot;0xc5ed7232fa2461e41d333f13bfd2e3e7f113aef12fe4e465f1c9ad345f140679&quot;
    execution_block_height: 152
- deposit_data:
    pubkey: &quot;0x8cd26495562e8fa526dd3dd5ccf7706e0b802747a2858ca76e4be7e9188ecaaf095b7ba58cf504057c4039e990f88618&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa8370ace5a4fcd6231c5bab72652d4f508a407e5d7b177ff034ca82a1efd0d06b23b618f17268d7ab67f5a964beec59e0d929c6b611092e67099be102b77782d704d63da4e6137bdff977eed1e526332624e5c052bfa16e71b9296ffd5f4e1ad&quot;
  deposit_data_root: &quot;0x82ae1b44b3e9bdcf2b48fdf000acbfbb762153634aac9d5ed5663bd6fe57ddd5&quot;
  eth1_data:
    deposit_root: &quot;0xa0a5548e34617b4b07307f5e80a50b88320c59ad0b655a8b3d01f7e77b96cedc&quot;
    deposit_count: &quot;152&quot;
    block_hash: &quot;0x42f0b6cc26d7613b3658fa113804dfc7624a3672887ca41229f9000a5f1eade3&quot;
  block_height: 153
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xaf12585229c24dfcac5f5fa3ac66011dabdfd39529f6d98c07abfa998c1b4e52&quot;
      - &quot;0xb691ba9f86444f0a58a7e0becd7c3bad9b44e5bf6a88b85a7cfc6f243f6e2fb8&quot;
    deposit_root: &quot;0xa0a5548e34617b4b07307f5e80a50b88320c59ad0b655a8b3d01f7e77b96cedc&quot;
    deposit_count: 152
    execution_block_hash: &quot;0x42f0b6cc26d7613b3658fa113804dfc7624a3672887ca41229f9000a5f1eade3&quot;
    execution_block_height: 153
- deposit_data:
    pubkey: &quot;0x95d668e777610672265275332a570af04c1a6090d9caae5152b66d476a7ac895c120e68724bdf30d3a51ece24a76b225&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb0bd20a856159c8ce771848cc33ca90aebe6bd56f8537a2ceed4a3a043cb448d489342b299bfcca3333a3f10c7c483780b335c78197a348eb2d0d28cf16e2a50368478693799d9b46076fbae6981732deacabac0bfe9747c5642477fa3718e59&quot;
  deposit_data_root: &quot;0xf952d77f6747501c8f12ac319fc9b537ffeb20e38afc5ff9046521c27076607a&quot;
  eth1_data:
    deposit_root: &quot;0x77bd65842bb2ab1513449bbe102333c0bd621424fde5d37257a32c3d26eaeb5f&quot;
    deposit_count: &quot;153&quot;
    block_hash: &quot;0x9af33652ee1b895df878aec4adb356e1bee86181c4c6117a1bf4ad21c1258669&quot;
  block_height: 154
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xaf12585229c24dfcac5f5fa3ac66011dabdfd39529f6d98c07abfa998c1b4e52&quot;
      - &quot;0xb691ba9f86444f0a58a7e0becd7c3bad9b44e5bf6a88b85a7cfc6f243f6e2fb8&quot;
      - &quot;0xf952d77f6747501c8f12ac319fc9b537ffeb20e38afc5ff9046521c27076607a&quot;
    deposit_root: &quot;0x77bd65842bb2ab1513449bbe102333c0bd621424fde5d37257a32c3d26eaeb5f&quot;
    deposit_count: 153
    execution_block_hash: &quot;0x9af33652ee1b895df878aec4adb356e1bee86181c4c6117a1bf4ad21c1258669&quot;
    execution_block_height: 154
- deposit_data:
    pubkey: &quot;0xb37c32301c15cf9a62fdf10ac221d751918f78ca95cf7f79b5a3828fe77c88561cdf863454133bc4bf56e6209b53d0d8&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8938e16203e369321f5e88d883f7ee521005230d74981fc6ccde25b775982cefbe88888ca720bfb48b2f77aed3d849221874fb97dde7bbe699cb17b397bdf72fbe580302fdcde9dff66c2567a1c518c63eb4a923619918ff18e76167c184c017&quot;
  deposit_data_root: &quot;0xbcb802dd617c023460f14a9e490207b829016a9b88cbb44b87fbd9fed9a00452&quot;
  eth1_data:
    deposit_root: &quot;0xece431b6b5a2d074c528e73dd8a1fc686e167dcf3575e118deb1c012e2beba56&quot;
    deposit_count: &quot;154&quot;
    block_hash: &quot;0xacd9c61ebeadae453909aac86b39107821848a4c7e85e7ae99fad8f46c09c5dd&quot;
  block_height: 155
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xaf12585229c24dfcac5f5fa3ac66011dabdfd39529f6d98c07abfa998c1b4e52&quot;
      - &quot;0xb691ba9f86444f0a58a7e0becd7c3bad9b44e5bf6a88b85a7cfc6f243f6e2fb8&quot;
      - &quot;0x11665987a6e900976d175d96c7ec5ddf750a00e89237cba75d596b7355553279&quot;
    deposit_root: &quot;0xece431b6b5a2d074c528e73dd8a1fc686e167dcf3575e118deb1c012e2beba56&quot;
    deposit_count: 154
    execution_block_hash: &quot;0xacd9c61ebeadae453909aac86b39107821848a4c7e85e7ae99fad8f46c09c5dd&quot;
    execution_block_height: 155
- deposit_data:
    pubkey: &quot;0xb923cab7abb3e0b5a8ca7b841662262014e59dd8ab24ef4513ef5fc1c85dc1860bf4fee2565a732a7df4dd73ff638403&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x89fb7bcb413178f88f843949a819180630d0651d184fea6bbba521e241c52834e9c9b1ab7496d6791f99b3cd4c0d23cc15b3ccb9893badbc524e1e67b027961c3d43661348c6a938c87f573d0f59919db632ef38279b28e03593e4bb9d1587bd&quot;
  deposit_data_root: &quot;0x0c4afbd64a8f690f413bb4eb4ba458f8af3c57cb27ef5043155e5ae329db963b&quot;
  eth1_data:
    deposit_root: &quot;0x5699749c403acccf444931ff8920ea52316ce8ba01b47566db967ac82998be4b&quot;
    deposit_count: &quot;155&quot;
    block_hash: &quot;0x5b56da2713e1546d90efde2fce7553310399d03774f4495e3ddfab74615c91e1&quot;
  block_height: 156
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xaf12585229c24dfcac5f5fa3ac66011dabdfd39529f6d98c07abfa998c1b4e52&quot;
      - &quot;0xb691ba9f86444f0a58a7e0becd7c3bad9b44e5bf6a88b85a7cfc6f243f6e2fb8&quot;
      - &quot;0x11665987a6e900976d175d96c7ec5ddf750a00e89237cba75d596b7355553279&quot;
      - &quot;0x0c4afbd64a8f690f413bb4eb4ba458f8af3c57cb27ef5043155e5ae329db963b&quot;
    deposit_root: &quot;0x5699749c403acccf444931ff8920ea52316ce8ba01b47566db967ac82998be4b&quot;
    deposit_count: 155
    execution_block_hash: &quot;0x5b56da2713e1546d90efde2fce7553310399d03774f4495e3ddfab74615c91e1&quot;
    execution_block_height: 156
- deposit_data:
    pubkey: &quot;0xa25d1dd7f5dc5ed5aaba0187d33ee72921d6455b6052c657d87e108aaeee9c31c53701e7b288ae0f9ca74cae34a1f49c&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x918558e2fb2ed8d33bc35cbb6794dce54fdc363d07eb66d2b8def16d8ff28be953d0d2b9d4207e6f1b4157aecfba99810472a8ad6fcb41a6f968a83c82cb140ba8bf1bb947f742ad470f4f3b83d447e38b925578e07f421c6a518a57b23dc84c&quot;
  deposit_data_root: &quot;0x069c4690e4914d5b8fb41fbd74c9205c5ef329affcaf903ec8293ccbf3943bcf&quot;
  eth1_data:
    deposit_root: &quot;0xf287114b93614b301a10c43ed09504c14298377eef05000f902e4cc5ec7daef6&quot;
    deposit_count: &quot;156&quot;
    block_hash: &quot;0x9bdce9e95c9fb72c2018eddd357e19ad47107c224bae328531bdd0716e7e500f&quot;
  block_height: 157
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xaf12585229c24dfcac5f5fa3ac66011dabdfd39529f6d98c07abfa998c1b4e52&quot;
      - &quot;0xb691ba9f86444f0a58a7e0becd7c3bad9b44e5bf6a88b85a7cfc6f243f6e2fb8&quot;
      - &quot;0x5cf0c39a7fa083994f7baf809c387f9ab82024f5f1bb1e9badc5d3b26c5c2973&quot;
    deposit_root: &quot;0xf287114b93614b301a10c43ed09504c14298377eef05000f902e4cc5ec7daef6&quot;
    deposit_count: 156
    execution_block_hash: &quot;0x9bdce9e95c9fb72c2018eddd357e19ad47107c224bae328531bdd0716e7e500f&quot;
    execution_block_height: 157
- deposit_data:
    pubkey: &quot;0x824904d20a5620ca46c015ff630e1e26fead9df53243354ace937f01a971916e8883687a8e5f087598c633a91d0d6fbd&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb238a8b1da5862bfce25d25b502130c2809263d257efdf8eef3da05a7b75b70f463f57a7c14e21b5853dfb404a6e3e66017f1d987fb634500fe403fe0ee06f0a329108af069c05b429dfc2b0ef87d7a384dfd10ed0d7b0ab82d335ed33bef84d&quot;
  deposit_data_root: &quot;0x1147a26009ddb6d159aad698f440619d7503b848807e09679dcbd58bf1b3a899&quot;
  eth1_data:
    deposit_root: &quot;0xc7307a5a78027139f9a0fcb9ec77193528b7067f2468b26ba79f6155fa579205&quot;
    deposit_count: &quot;157&quot;
    block_hash: &quot;0x1f02f863183c9f6f57bf3146745f7461290f64f73065bcd52e065e97ca1f4ecb&quot;
  block_height: 158
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xaf12585229c24dfcac5f5fa3ac66011dabdfd39529f6d98c07abfa998c1b4e52&quot;
      - &quot;0xb691ba9f86444f0a58a7e0becd7c3bad9b44e5bf6a88b85a7cfc6f243f6e2fb8&quot;
      - &quot;0x5cf0c39a7fa083994f7baf809c387f9ab82024f5f1bb1e9badc5d3b26c5c2973&quot;
      - &quot;0x1147a26009ddb6d159aad698f440619d7503b848807e09679dcbd58bf1b3a899&quot;
    deposit_root: &quot;0xc7307a5a78027139f9a0fcb9ec77193528b7067f2468b26ba79f6155fa579205&quot;
    deposit_count: 157
    execution_block_hash: &quot;0x1f02f863183c9f6f57bf3146745f7461290f64f73065bcd52e065e97ca1f4ecb&quot;
    execution_block_height: 158
- deposit_data:
    pubkey: &quot;0xaed2a3ef693d13698e77966b8125442ac40ee0a62e8d97f71493c966da3c8604932dcee09606c2394afed25f8ad4f31c&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8e2b32b5180bba930cd1d405258ec2cd4a7dcc0bba374a4da4e57ba6084db5341db349348413d6385fd336cd476eb1e41396bfb8201727239547f3f175b8baa7b0c98de9aca97fe7226a5fc354e7d16c39275ac3ce5bd36f3fa5ffbbbba1e4ab&quot;
  deposit_data_root: &quot;0x1e35604482803af5afed89b925dcb5e9f41ab291388918e7b317d467e8bf2aa8&quot;
  eth1_data:
    deposit_root: &quot;0x6858813a05b486da3ccdcc7c09b56d5a96b1396a594ecf561ca209e7273d2153&quot;
    deposit_count: &quot;158&quot;
    block_hash: &quot;0xd52fe7ca49fb3425010be4c5fc698606361cdbecd68ef63800d013391b53939c&quot;
  block_height: 159
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xaf12585229c24dfcac5f5fa3ac66011dabdfd39529f6d98c07abfa998c1b4e52&quot;
      - &quot;0xb691ba9f86444f0a58a7e0becd7c3bad9b44e5bf6a88b85a7cfc6f243f6e2fb8&quot;
      - &quot;0x5cf0c39a7fa083994f7baf809c387f9ab82024f5f1bb1e9badc5d3b26c5c2973&quot;
      - &quot;0x431fb43239425b2f4faf58bbfc2e8bf64202d513954ef412ee9154052f667c4b&quot;
    deposit_root: &quot;0x6858813a05b486da3ccdcc7c09b56d5a96b1396a594ecf561ca209e7273d2153&quot;
    deposit_count: 158
    execution_block_hash: &quot;0xd52fe7ca49fb3425010be4c5fc698606361cdbecd68ef63800d013391b53939c&quot;
    execution_block_height: 159
- deposit_data:
    pubkey: &quot;0x8f8ac057107bc490de273453730753b9e2b69df03917a0addbfb13c5152d93fa05702cf21d8b58ed7c08ac3295c1de3e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb799bc548db09f68b31bc25159d865b5925ace14d63cfa21af51f8e822d85b6221ad968839f1bc57e8218e5a8c093fe6030098d5c8c43a59bea334048bedcc511b3ffb6c1d64876d0214238f70b27267e606afb1747423b1aa254209bea36e8e&quot;
  deposit_data_root: &quot;0xcc6561589f174b04b6adcf0b2a893667c65f3443bed0e5c8a3af84d3157c3baf&quot;
  eth1_data:
    deposit_root: &quot;0x28bfff0f74194d7bfcc9ba76c21cfe0c2908f605b8017e023792ece9d9b1c1eb&quot;
    deposit_count: &quot;159&quot;
    block_hash: &quot;0xe93ddeb537374b4dbb453dc08411c26a02c36c9d3b77f4b9679a89bd75b70dae&quot;
  block_height: 160
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xaf12585229c24dfcac5f5fa3ac66011dabdfd39529f6d98c07abfa998c1b4e52&quot;
      - &quot;0xb691ba9f86444f0a58a7e0becd7c3bad9b44e5bf6a88b85a7cfc6f243f6e2fb8&quot;
      - &quot;0x5cf0c39a7fa083994f7baf809c387f9ab82024f5f1bb1e9badc5d3b26c5c2973&quot;
      - &quot;0x431fb43239425b2f4faf58bbfc2e8bf64202d513954ef412ee9154052f667c4b&quot;
      - &quot;0xcc6561589f174b04b6adcf0b2a893667c65f3443bed0e5c8a3af84d3157c3baf&quot;
    deposit_root: &quot;0x28bfff0f74194d7bfcc9ba76c21cfe0c2908f605b8017e023792ece9d9b1c1eb&quot;
    deposit_count: 159
    execution_block_hash: &quot;0xe93ddeb537374b4dbb453dc08411c26a02c36c9d3b77f4b9679a89bd75b70dae&quot;
    execution_block_height: 160
- deposit_data:
    pubkey: &quot;0x8fe63d0f0da14a975a69446571eaa08409b6b4d091c720ca26519156a1cbd9e0fd44de574d8486ff98ad4086e0d96f59&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa80cc551d9eb7d869858e173eb701e706fa8bb1fd82e798bf19085c1b07d1b4807681fa0fa34ab3f802ddb664933a43513a14975a33d720b949c4873ce646f8f80ea6e8a645e404c81441b7ef30076650694972b8cbc3ff2062ff4772dca91c2&quot;
  deposit_data_root: &quot;0x59822146ece6a1e35fa5c3b0b38f1a7ccfb6cea652ae7d6d6867a0cd2298276c&quot;
  eth1_data:
    deposit_root: &quot;0xf125f86aaf7df54e79f43355d6be50d55daab4addaaabae4c58e7a977f3b1cc2&quot;
    deposit_count: &quot;160&quot;
    block_hash: &quot;0xb6bbba5e6a9fd9d2972588347d65cfc8633717b19e2c059aeae1c55f790b6ea0&quot;
  block_height: 161
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
    deposit_root: &quot;0xf125f86aaf7df54e79f43355d6be50d55daab4addaaabae4c58e7a977f3b1cc2&quot;
    deposit_count: 160
    execution_block_hash: &quot;0xb6bbba5e6a9fd9d2972588347d65cfc8633717b19e2c059aeae1c55f790b6ea0&quot;
    execution_block_height: 161
- deposit_data:
    pubkey: &quot;0xb249899bfe2b0b123c7a151b5041d5e994c57568a6b427e38b25f2ef04ef0c30b4577e66fa7b499ef14d8d24563ef06e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8ea309386ac878fe5d5b3e6c4dadd85302bc9432ceeb7ddaa95ec3414d7f2cccd0792606dd481c49dd4f1d3455847b9b0e07bc4726118afe68116701d4641e0ecf9caf7be829cd0dcb7651801c9bc0ad18b7592b5f95012802f1e7b14e9cdefd&quot;
  deposit_data_root: &quot;0xe3149b68de3b804bb8ecdfaf36696dd76fcb801e7e47142e5beafd06b8c96c31&quot;
  eth1_data:
    deposit_root: &quot;0xaee25dee2d482203030ad50d3f0731d4b215bf84f1c60b875e88e19125482a75&quot;
    deposit_count: &quot;161&quot;
    block_hash: &quot;0x13c72c657d79ba0f34266ace9d2e195cfb91257db5853010df831bde22774d4a&quot;
  block_height: 162
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0xe3149b68de3b804bb8ecdfaf36696dd76fcb801e7e47142e5beafd06b8c96c31&quot;
    deposit_root: &quot;0xaee25dee2d482203030ad50d3f0731d4b215bf84f1c60b875e88e19125482a75&quot;
    deposit_count: 161
    execution_block_hash: &quot;0x13c72c657d79ba0f34266ace9d2e195cfb91257db5853010df831bde22774d4a&quot;
    execution_block_height: 162
- deposit_data:
    pubkey: &quot;0x965ce54aa0e435602fe222441ea4ac7b227948ea37e927f9816d89d779dbeba426dc68ba6829ab8da33a565a6b879c65&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb0352350082b57df3eb8cacc48bd3e999a1b2719ef218cb2a5189291e0234f4678b21b037392c37b724ff82a6a42727b103809bea4cc34cf9c8f86675d0a40adbf65b467e9128358802e0079a0cdb100b9206a4475b97e7129272a8c36e51b9c&quot;
  deposit_data_root: &quot;0x8b1968fceaf4e3214998a64db92e35e11a383ca34a1e8d37a4f07588debb444c&quot;
  eth1_data:
    deposit_root: &quot;0x81cbc850d30b5486ca44fc0f2368100fa3673575e87fb5635485fbd553ceb59a&quot;
    deposit_count: &quot;162&quot;
    block_hash: &quot;0x95088152d0c1114f167cb7b65078019b8bd5f2023e889e18c201c0bf6cca138c&quot;
  block_height: 163
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x2e6b570d265740ee405e8ebdf6c5e228efe005294f62cf1af23affc7b72a38e6&quot;
    deposit_root: &quot;0x81cbc850d30b5486ca44fc0f2368100fa3673575e87fb5635485fbd553ceb59a&quot;
    deposit_count: 162
    execution_block_hash: &quot;0x95088152d0c1114f167cb7b65078019b8bd5f2023e889e18c201c0bf6cca138c&quot;
    execution_block_height: 163
- deposit_data:
    pubkey: &quot;0xaea84e54336d09257061a8b23f419438c2e3d2659de36b993033bb30e396d9c9ee8b6f1b66261a6a060c3ab706827afb&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x82804e80f3e381cec665c1f51b1015500a0eb2b35085c1b1365156e4fbb5ab82d7d4af7af12e8cfc2a73026e6aa8e3440cc9babfa8480efd255b15f1097fc8a2283d76b02f225a1d7105e44f9daffe9794208e97bbb19907dd83a0608095c127&quot;
  deposit_data_root: &quot;0xe374e9bd5c51394fcdc6852e98614127fe095a5192cf53d340cf519bf20cfb59&quot;
  eth1_data:
    deposit_root: &quot;0xdcd46c40bcbbde1ad6887dc6099f6109980c4dd6bb67d03e7534dd7d87038867&quot;
    deposit_count: &quot;163&quot;
    block_hash: &quot;0xdbc232ce7aff4b99b9ae5e05a47ef313d62affb1f08328157161c00a218575b2&quot;
  block_height: 164
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x2e6b570d265740ee405e8ebdf6c5e228efe005294f62cf1af23affc7b72a38e6&quot;
      - &quot;0xe374e9bd5c51394fcdc6852e98614127fe095a5192cf53d340cf519bf20cfb59&quot;
    deposit_root: &quot;0xdcd46c40bcbbde1ad6887dc6099f6109980c4dd6bb67d03e7534dd7d87038867&quot;
    deposit_count: 163
    execution_block_hash: &quot;0xdbc232ce7aff4b99b9ae5e05a47ef313d62affb1f08328157161c00a218575b2&quot;
    execution_block_height: 164
- deposit_data:
    pubkey: &quot;0xa90dfa8114a00b3fde7cdddfb2fab9a6d113500aee32f08786634bc5c99ccd7730417e4ae4a05299b62342c1ab98ada3&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x993aaf734e6ea9848eb8b581d8349a780dcd2689bd341c984ed7f291efb035c1bb6a7be47bd9904aeb1d9bc595596b670b011d2e36bf1b4a1e3f83bd87ee5d1a2b8e10d93825bdafe498155fa3b39cd1d929e858e14cae16dccac990a918b407&quot;
  deposit_data_root: &quot;0x7b4c8cd4bdd1696c9acee551bc67972ee101a70a05d7e80e327867bf9c2cca75&quot;
  eth1_data:
    deposit_root: &quot;0xcbe12098660ef62edb564991133409b98044b1f3e79ad49c9b26a29d990694ff&quot;
    deposit_count: &quot;164&quot;
    block_hash: &quot;0xe2797260931e52abe1abde79d64ef6760785f83401180a0799ef7688f4118150&quot;
  block_height: 165
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x582e9a6fd990c0d996070550f2ed7e8e8cd420dd85740a5a6e53f4f0c300d47c&quot;
    deposit_root: &quot;0xcbe12098660ef62edb564991133409b98044b1f3e79ad49c9b26a29d990694ff&quot;
    deposit_count: 164
    execution_block_hash: &quot;0xe2797260931e52abe1abde79d64ef6760785f83401180a0799ef7688f4118150&quot;
    execution_block_height: 165
- deposit_data:
    pubkey: &quot;0x9346419f620830d6535546fe2ddd827b69156ea9c29194780c63a8f07b6fdcb0568282914ce3cc06a2ba44e2ee1a6e9e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb243d10f9864d3abcc933b7ca0cdb2e40fa08a1631ecb702c41dab1113f0e689677ba1e8b078618989b65548103adc5d0d7531c102f22f4d502504c64148b8aded9cf314ea6d8336b5f36329e90f79298efe0d48fe6f84647dbf3952247b1f93&quot;
  deposit_data_root: &quot;0x9843715212db9556a5ae4aebc9cd03db21467bdb82a6b0b7c8aad1e03e7c0db9&quot;
  eth1_data:
    deposit_root: &quot;0x62657a90eb6dda61c00c5b33dca2b652a03fba9f0aa4090c0711418945d8444e&quot;
    deposit_count: &quot;165&quot;
    block_hash: &quot;0x8090b1b61be967d73abea99aabd3a2df3ea098eee99126ff117aa1e3b0581543&quot;
  block_height: 166
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x582e9a6fd990c0d996070550f2ed7e8e8cd420dd85740a5a6e53f4f0c300d47c&quot;
      - &quot;0x9843715212db9556a5ae4aebc9cd03db21467bdb82a6b0b7c8aad1e03e7c0db9&quot;
    deposit_root: &quot;0x62657a90eb6dda61c00c5b33dca2b652a03fba9f0aa4090c0711418945d8444e&quot;
    deposit_count: 165
    execution_block_hash: &quot;0x8090b1b61be967d73abea99aabd3a2df3ea098eee99126ff117aa1e3b0581543&quot;
    execution_block_height: 166
- deposit_data:
    pubkey: &quot;0xa399755dad117a369409206196a9e3a1637a625dc22d0da18583827dbc487ab9a2ba6c995927df9d8560e07860ae8b0f&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa6f0fc1f51494308f876cb2391f625009d4761871c69af305712751e35cf0f3c026e06c159e3c82988b9f97fff4d1d99078f3bd6c8b7d3d308e36eae49ac1b79ace6e04656b0fcd3d8daaf2ce6333c0ec0ca998ce3c08ea86e73fda1c8d25bbd&quot;
  deposit_data_root: &quot;0x4e25083e3dccff55e85eaef37ccc737c720ecc898a98e8ca0c52b897431a315a&quot;
  eth1_data:
    deposit_root: &quot;0x4619beded7d11311791dcef425b8027ea14e383d8c2cd5c742879c134637ee91&quot;
    deposit_count: &quot;166&quot;
    block_hash: &quot;0x3c684054459e115db8518ed799e879a579a049bc9994c1727e568d3e9dbe2767&quot;
  block_height: 167
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x582e9a6fd990c0d996070550f2ed7e8e8cd420dd85740a5a6e53f4f0c300d47c&quot;
      - &quot;0xd9c72e2b3770f12ee0e9f7d83243ab36680e0b9483eaf7a537848aae96531edd&quot;
    deposit_root: &quot;0x4619beded7d11311791dcef425b8027ea14e383d8c2cd5c742879c134637ee91&quot;
    deposit_count: 166
    execution_block_hash: &quot;0x3c684054459e115db8518ed799e879a579a049bc9994c1727e568d3e9dbe2767&quot;
    execution_block_height: 167
- deposit_data:
    pubkey: &quot;0xa4695dc25f6cd20e48edd948321a09ebe2884b1d6ebf622aa02a023e96f9a1d365be7f2c6668444b347aee678fc7bc5d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x93375360b97a238600161ddf1096b86637d2bb9cf4453450804fca3b16bbc74e1aac6d9a9ece486250461b0492a68470164b8f779c6eb89f59233ec304af5cf3f76d4d5ad6508599bf569927eb97096f422051e33c4137df737eb4db9a4e421b&quot;
  deposit_data_root: &quot;0x468fd4b82322e73a7470baa353b8931947a2bf6fe3cb62cb1b0f126973a2df1a&quot;
  eth1_data:
    deposit_root: &quot;0xb2d04fea4f590b0f56e5a7fa576d4b2cd2d88b99c09dccb2b4aa560eb0885c9b&quot;
    deposit_count: &quot;167&quot;
    block_hash: &quot;0x06c9e6315169cf6fbbb198a180cc67111550846dcc2b78e2265dbcb5d29b17f3&quot;
  block_height: 168
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x582e9a6fd990c0d996070550f2ed7e8e8cd420dd85740a5a6e53f4f0c300d47c&quot;
      - &quot;0xd9c72e2b3770f12ee0e9f7d83243ab36680e0b9483eaf7a537848aae96531edd&quot;
      - &quot;0x468fd4b82322e73a7470baa353b8931947a2bf6fe3cb62cb1b0f126973a2df1a&quot;
    deposit_root: &quot;0xb2d04fea4f590b0f56e5a7fa576d4b2cd2d88b99c09dccb2b4aa560eb0885c9b&quot;
    deposit_count: 167
    execution_block_hash: &quot;0x06c9e6315169cf6fbbb198a180cc67111550846dcc2b78e2265dbcb5d29b17f3&quot;
    execution_block_height: 168
- deposit_data:
    pubkey: &quot;0xa8c0966a8c0869e28110ea5587321cb26af1bc49591fdaab24b37c77feed399439515d2aca8f2483a3d666be8b4eeef5&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xace818afa05a123b98626d805d1b747f09b1d2e41c826b607da97cd28c41ca78d2514e2d4e4a0a1a98cb6034a1ace05f033e4091dfbe40eb7eb6943b682c7ed8b26b8a68f731f908ca7c18f5f8568a1c39648bb94870066275245e42e44ecd03&quot;
  deposit_data_root: &quot;0x9dae7719d40b642b28d8de5358c902e0e7b6dcddeb88a29cc2583600c15ad2eb&quot;
  eth1_data:
    deposit_root: &quot;0x847f32ad10d7b3de3275fc8a8730008ec5f12a89142209a4ba63c8cbdb022ea3&quot;
    deposit_count: &quot;168&quot;
    block_hash: &quot;0x619b700d81b9b1216b6b9ff1f0eb4f7b11c4ffd3c4cf781af2a9cd47ef42a7e5&quot;
  block_height: 169
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x51ed246dd0a98ad17d95eb60d315ce5433d7a022cd5db0a6d4f1be5b3bbae2c1&quot;
    deposit_root: &quot;0x847f32ad10d7b3de3275fc8a8730008ec5f12a89142209a4ba63c8cbdb022ea3&quot;
    deposit_count: 168
    execution_block_hash: &quot;0x619b700d81b9b1216b6b9ff1f0eb4f7b11c4ffd3c4cf781af2a9cd47ef42a7e5&quot;
    execution_block_height: 169
- deposit_data:
    pubkey: &quot;0xb210d799f2cc4d87df36b60fe1d7408d9e4b5124aeed740eb42227dc1f456d9e13bcecf309e068f9775996c71b55ca8d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa59636627fd11a272aac90b9ae21cbe3156c8e347f34c6a92d6078f1a130864026c4fd8149df5c0808c9d8be6e7257960c627011fa459fed2d513ac91bc10ef3858e27ea6b88aa3d1f566ada6075daf2f3306fed983353dc6593375f9a2af410&quot;
  deposit_data_root: &quot;0xd2ff2f73a25e4c4de82d2bc2f1fe937bdaecc03fddfb5f971df8c65a6fd9d93f&quot;
  eth1_data:
    deposit_root: &quot;0x7e03a31121d9081c87abc7e9789a6ba49abf30fa5e5b0e2245cd75c76869ad5a&quot;
    deposit_count: &quot;169&quot;
    block_hash: &quot;0x307cdbb86ebbce74ab00d13e63aaf58c789c1fe21b037234c2798cf2e44ac41b&quot;
  block_height: 170
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x51ed246dd0a98ad17d95eb60d315ce5433d7a022cd5db0a6d4f1be5b3bbae2c1&quot;
      - &quot;0xd2ff2f73a25e4c4de82d2bc2f1fe937bdaecc03fddfb5f971df8c65a6fd9d93f&quot;
    deposit_root: &quot;0x7e03a31121d9081c87abc7e9789a6ba49abf30fa5e5b0e2245cd75c76869ad5a&quot;
    deposit_count: 169
    execution_block_hash: &quot;0x307cdbb86ebbce74ab00d13e63aaf58c789c1fe21b037234c2798cf2e44ac41b&quot;
    execution_block_height: 170
- deposit_data:
    pubkey: &quot;0x83af2f04a869d856df934893edd7f15dae94ef74d78139e0556e1166e81f8ab2c294708af67f194e854946f2da4e87da&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x944859b17259fedb50e94bf3fbee57b0d5c7f43401fb611258a599696f24d94622a71d179d540fb83b475122c406c85113f84ba8684096c38accf6d171ae2abefb725a638207dd12d12099a7bdeddb832a05f4707797d724deea9570679dab0e&quot;
  deposit_data_root: &quot;0x9aad59fe2860067c1859e09c5a0cbd41a482389f2457b3ddf246b065d2b797e5&quot;
  eth1_data:
    deposit_root: &quot;0x0507a6d86c34e8fb6f2e644d93bea484d395eb00f747aa4185e15e67741708f8&quot;
    deposit_count: &quot;170&quot;
    block_hash: &quot;0x4840cbf1750adce5ef26a3b6e0251a60f5998a1bb4109a3918410e2f459edd2c&quot;
  block_height: 171
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x51ed246dd0a98ad17d95eb60d315ce5433d7a022cd5db0a6d4f1be5b3bbae2c1&quot;
      - &quot;0x0243f87cc01998a622e06a46d90ff0e2c2f4e0457b4e0c418a13a3183743df4e&quot;
    deposit_root: &quot;0x0507a6d86c34e8fb6f2e644d93bea484d395eb00f747aa4185e15e67741708f8&quot;
    deposit_count: 170
    execution_block_hash: &quot;0x4840cbf1750adce5ef26a3b6e0251a60f5998a1bb4109a3918410e2f459edd2c&quot;
    execution_block_height: 171
- deposit_data:
    pubkey: &quot;0xad69af5d2ee0d68b32e6c4ebafc348a0c509aeed7e4f5c24c236dad4a8f91129cb9f8ee521de07c8199807e36e6a84f9&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8a8c6e627da5d712418638f0a31f9671f753d44f5b9439ba0ebacd3a4cfbe41b6ec1c75eb70e0e57bc3535409e7f949f01dbafa227b0b87d44ebc5dd63083e3848b36f4b1821f0f3c1ff2a9878c5ba2cdcc16e39b01e0f4a924aa8c14278c447&quot;
  deposit_data_root: &quot;0x41deea4572826ab6dba52032eeabd9996d80e3a5725ebba8a8a20726fd16d10a&quot;
  eth1_data:
    deposit_root: &quot;0x73170edf9923bea7b1203c4701f3023cb42ab5a8c15e7a5310fdae89f49a10e8&quot;
    deposit_count: &quot;171&quot;
    block_hash: &quot;0x409571a87e6260ebf8a4b04e70a01d1276eb29c3ea26ec4f85561f1b15089ea6&quot;
  block_height: 172
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x51ed246dd0a98ad17d95eb60d315ce5433d7a022cd5db0a6d4f1be5b3bbae2c1&quot;
      - &quot;0x0243f87cc01998a622e06a46d90ff0e2c2f4e0457b4e0c418a13a3183743df4e&quot;
      - &quot;0x41deea4572826ab6dba52032eeabd9996d80e3a5725ebba8a8a20726fd16d10a&quot;
    deposit_root: &quot;0x73170edf9923bea7b1203c4701f3023cb42ab5a8c15e7a5310fdae89f49a10e8&quot;
    deposit_count: 171
    execution_block_hash: &quot;0x409571a87e6260ebf8a4b04e70a01d1276eb29c3ea26ec4f85561f1b15089ea6&quot;
    execution_block_height: 172
- deposit_data:
    pubkey: &quot;0x93568c9c40bb362329367dfc26a65567481a03c35fcaab51f781c9f364b7e676cfc3d2c08633888b29715a6731dfb6b0&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa8afaca7a98ed1bbe7d5ad827d9dfb25e22983515a8cb7bbf9660b8bc965dbd22cddcf301be0b8ea07773716cd6bb40c0939ee4236b1048b327b51dc56eeec3333296519c33ba8b42671c2e64941d3c0274204eff17c255729a6ff036dca11d2&quot;
  deposit_data_root: &quot;0x3ce86437d73f789ed89cc006c250d5ae9ebe44e25ce3df3b8a87c511f3252ab3&quot;
  eth1_data:
    deposit_root: &quot;0x5f0c1f7e6a02232a6a1d7aa1c7a94f9d46700a5715138165282542665559fe6a&quot;
    deposit_count: &quot;172&quot;
    block_hash: &quot;0x4f2e4afd489e40fdb8ecfe276f4a028e550ae9f2224c29aff14670bff6732ac1&quot;
  block_height: 173
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x51ed246dd0a98ad17d95eb60d315ce5433d7a022cd5db0a6d4f1be5b3bbae2c1&quot;
      - &quot;0x6706f41e298f5bf853c88ba459952003db6fa9dd7a4c36b72fdca4b7d831d42f&quot;
    deposit_root: &quot;0x5f0c1f7e6a02232a6a1d7aa1c7a94f9d46700a5715138165282542665559fe6a&quot;
    deposit_count: 172
    execution_block_hash: &quot;0x4f2e4afd489e40fdb8ecfe276f4a028e550ae9f2224c29aff14670bff6732ac1&quot;
    execution_block_height: 173
- deposit_data:
    pubkey: &quot;0x8509086b192c039cc84d145fd6a2b2cc3e3a3d46092e928cc1ca9a66dd663550a2782ab32d677785e02c23b6637df70d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9055741c269436e5cb5eb9560441a9dd62dc3605913b6b83b207e49eb2c9f3837b2c877c8e937ce326ddfda973a031920f60331a5eaadc52555cf37c6a0216ca8ac3ba965a2c0060b1b9729472e977a5fd23b23c0a39286b849a7ee22d76fe5e&quot;
  deposit_data_root: &quot;0xc9ca71afaa9631f5c9645212720807c19c302df3a5911504c49fc87f78011862&quot;
  eth1_data:
    deposit_root: &quot;0xda5ea898120a262741057304c7596b6a34af9ca93abc2a162c738cbf30613c57&quot;
    deposit_count: &quot;173&quot;
    block_hash: &quot;0xd53d21964f2af07692e1fa7c1886d583dd28693ea39b391d4ebb18e603d0ecb2&quot;
  block_height: 174
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x51ed246dd0a98ad17d95eb60d315ce5433d7a022cd5db0a6d4f1be5b3bbae2c1&quot;
      - &quot;0x6706f41e298f5bf853c88ba459952003db6fa9dd7a4c36b72fdca4b7d831d42f&quot;
      - &quot;0xc9ca71afaa9631f5c9645212720807c19c302df3a5911504c49fc87f78011862&quot;
    deposit_root: &quot;0xda5ea898120a262741057304c7596b6a34af9ca93abc2a162c738cbf30613c57&quot;
    deposit_count: 173
    execution_block_hash: &quot;0xd53d21964f2af07692e1fa7c1886d583dd28693ea39b391d4ebb18e603d0ecb2&quot;
    execution_block_height: 174
- deposit_data:
    pubkey: &quot;0x89494e98d8cc4c763b3b138e21d6cc1c86f7eeb69315cf6a4b8b5b7018dd59e3b82c0b7c785a381ffd1b809e5bbf4625&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa937d3c9c04bf31b388af13d98636e1339e5e9cf3d8dfe50dff7722be110fb42e68efd406af92b5e3c0ed4f73959c89502c84a8ef20410120d5344b7441872686652f642ccc7b2d944e3a6937670e166795535e65fc66204fbc61a9e846a9950&quot;
  deposit_data_root: &quot;0x000a7e1720ce430ce6344f7add0f7e4b43ca5ca57be2a8efbf63c0746787cea2&quot;
  eth1_data:
    deposit_root: &quot;0xb349cf11fad3f0efcc1b018ea084cc30ff6ce11e8c13ff066a548ca67bb03906&quot;
    deposit_count: &quot;174&quot;
    block_hash: &quot;0x446efd92f90c3861d7acb8deccea5b7c28036a54dd441584508a5c8a52f905c2&quot;
  block_height: 175
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x51ed246dd0a98ad17d95eb60d315ce5433d7a022cd5db0a6d4f1be5b3bbae2c1&quot;
      - &quot;0x6706f41e298f5bf853c88ba459952003db6fa9dd7a4c36b72fdca4b7d831d42f&quot;
      - &quot;0xdc8f10386657c08bb0d17aba01f7647252ad4c6db5a36fe938283fe819b0c9d0&quot;
    deposit_root: &quot;0xb349cf11fad3f0efcc1b018ea084cc30ff6ce11e8c13ff066a548ca67bb03906&quot;
    deposit_count: 174
    execution_block_hash: &quot;0x446efd92f90c3861d7acb8deccea5b7c28036a54dd441584508a5c8a52f905c2&quot;
    execution_block_height: 175
- deposit_data:
    pubkey: &quot;0x8451860d32c95e30f685cf31fccb967b0cd172566ff7b7d2c5ff35130bd1232cb1a216c9f0cd355ad69a93469b78e8ba&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xaaeaad75e6abb6123819f1f01b636a91f85f28c38fe57833e38e555f0a78546a151c02dad44fce569eb89212879c381c18a516d9256ca79afde66a5fc334005b470dd2e3d704248cd7f61203ede9fffe343dfbd0b55f0a24b1c832be7ae68cd6&quot;
  deposit_data_root: &quot;0x38d3cf596f6aff5b5603a02e0cab7770a129d72499ec88ae2cf89bf01ba15b8a&quot;
  eth1_data:
    deposit_root: &quot;0xa927a1cd6a0fd5bfcbdc12921e8197df198e82b0fd4ec52051885184f7105703&quot;
    deposit_count: &quot;175&quot;
    block_hash: &quot;0xbce83de010f32cd9de9e1af87710aa65227fb59b04ae6825ffe42bbca51ad8fe&quot;
  block_height: 176
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x51ed246dd0a98ad17d95eb60d315ce5433d7a022cd5db0a6d4f1be5b3bbae2c1&quot;
      - &quot;0x6706f41e298f5bf853c88ba459952003db6fa9dd7a4c36b72fdca4b7d831d42f&quot;
      - &quot;0xdc8f10386657c08bb0d17aba01f7647252ad4c6db5a36fe938283fe819b0c9d0&quot;
      - &quot;0x38d3cf596f6aff5b5603a02e0cab7770a129d72499ec88ae2cf89bf01ba15b8a&quot;
    deposit_root: &quot;0xa927a1cd6a0fd5bfcbdc12921e8197df198e82b0fd4ec52051885184f7105703&quot;
    deposit_count: 175
    execution_block_hash: &quot;0xbce83de010f32cd9de9e1af87710aa65227fb59b04ae6825ffe42bbca51ad8fe&quot;
    execution_block_height: 176
- deposit_data:
    pubkey: &quot;0xb48c495c19082d892f38227bced89f7199f4e9b642bf94c7f2f1ccf29c0e6a6f54d653002513aa7cd3b56c88368797ec&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xab221d4174ca55a27aa072b675ee700d63edd048d4f417b79bce310c3bc3f5aa214eca529c4624accb014bad5d1f79e50ea67c82e4b3daea65dda4de263c0131eff1ab811e5716eca36bc2409495ae2795abbeb161311df4a3289cf1aff624e8&quot;
  deposit_data_root: &quot;0x960ceb47ae45f726f760f1a6e4c501a1e539f332f3cfad2dcd22be596fc8c126&quot;
  eth1_data:
    deposit_root: &quot;0xe95f5528ca45a8860a620ea21eda926f6f153cbaaa6b9324ae5ea82aff8dc2b3&quot;
    deposit_count: &quot;176&quot;
    block_hash: &quot;0x3f7e984a3ba436e0ed8fbfdb1bca8308e6ec5b1060400a1c5156af6ef110bc5d&quot;
  block_height: 177
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x3bdcdb12a251d536acdb1af1c54acb37cd882c8fefa579587efd7828584f5422&quot;
    deposit_root: &quot;0xe95f5528ca45a8860a620ea21eda926f6f153cbaaa6b9324ae5ea82aff8dc2b3&quot;
    deposit_count: 176
    execution_block_hash: &quot;0x3f7e984a3ba436e0ed8fbfdb1bca8308e6ec5b1060400a1c5156af6ef110bc5d&quot;
    execution_block_height: 177
- deposit_data:
    pubkey: &quot;0x8bd22839c85ec58af4303cde58674394247fbe1f51b4e30ebcdf86aa861ebef2ac9239aa21bd9b07fd03f28dc4806780&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x81fb9baf8c52a4888566448ed653d4e199b40bbf4053c34ea0105554f96a4dd245df81a2ed37e900b73ac954c7001f7009a2240737f034d9e4ca6874f3913d06efbfc2eea789f86ad5a353b37b755ba73aae5dcb5f3f44fb155410807d44bbc0&quot;
  deposit_data_root: &quot;0xfe4956baff4bc251951ba1c955db9f46821ab844d6a031ef7db7b68de6959856&quot;
  eth1_data:
    deposit_root: &quot;0x76342485c471517c60dce8cf762fffbf3f06f93202e98682c7078618c4eb0e88&quot;
    deposit_count: &quot;177&quot;
    block_hash: &quot;0x66c1f5247e10372a47af81e6e30ffdccc3f0d64f7fde478420394289c435dec7&quot;
  block_height: 178
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x3bdcdb12a251d536acdb1af1c54acb37cd882c8fefa579587efd7828584f5422&quot;
      - &quot;0xfe4956baff4bc251951ba1c955db9f46821ab844d6a031ef7db7b68de6959856&quot;
    deposit_root: &quot;0x76342485c471517c60dce8cf762fffbf3f06f93202e98682c7078618c4eb0e88&quot;
    deposit_count: 177
    execution_block_hash: &quot;0x66c1f5247e10372a47af81e6e30ffdccc3f0d64f7fde478420394289c435dec7&quot;
    execution_block_height: 178
- deposit_data:
    pubkey: &quot;0xaace874118a4ea9cfec8d7979dbb4618f4833dde4cfc493a403ee5cedb67f294bcac4aaa2d626ff25f4fc7ee9fa61401&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x859e833217c0fd90fc641745e75e0d100d6b3cdfc1fc98dcd92dd0838a22c3bb3508ffbfc41662ec93134881f4a75a7d01661c1eb91d302c8ad28463703fa445276f9a7ce810a0fe475e18631ba1b81084f2b0c65008b37eccffbc01eca98143&quot;
  deposit_data_root: &quot;0x2325c1ee7ee609107dc5df1c7445e7d02a00e48798fe06f73e48705e0357e8b4&quot;
  eth1_data:
    deposit_root: &quot;0x95111c86ff2b172022650c8d000331c7c57d98b2f330aa9bd6bd417f94547739&quot;
    deposit_count: &quot;178&quot;
    block_hash: &quot;0x0c95d8c50c7fa3299c3ffd7ac683ef683fc907c39997b8b606bc8210c71c1b9b&quot;
  block_height: 179
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x3bdcdb12a251d536acdb1af1c54acb37cd882c8fefa579587efd7828584f5422&quot;
      - &quot;0x452e7913b4f3ad6bc209cce6fc61588821ad6494282520a51e00926d913aac94&quot;
    deposit_root: &quot;0x95111c86ff2b172022650c8d000331c7c57d98b2f330aa9bd6bd417f94547739&quot;
    deposit_count: 178
    execution_block_hash: &quot;0x0c95d8c50c7fa3299c3ffd7ac683ef683fc907c39997b8b606bc8210c71c1b9b&quot;
    execution_block_height: 179
- deposit_data:
    pubkey: &quot;0x956851460cb809871966cc4dd44d0b58dc68a1c22110864f374cd3aca743ee63b0743999d35b473e3f95ea38a276eaea&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa22edc0fab4e7099060fb062f9ac88bc08e2903dba9c9243dae581b169e91a3a8a823fe5a429d0d459d6499fd70c1c240d33cd4f5d7053ba9278234fbced8df69ed82849f3fd8510658918a00720c80d8453044bad1c4bdbdb20ca5ff75ffa5f&quot;
  deposit_data_root: &quot;0x9567c1a847009105673244cbcccff11184117f0b3e465f48e1771ead7976779b&quot;
  eth1_data:
    deposit_root: &quot;0x358b5a17f9a64b0a891cf6741ceebd0b615dfb89490550c9b601551d13781068&quot;
    deposit_count: &quot;179&quot;
    block_hash: &quot;0xd6917e5c5a35c21ea97cb5bd1f9070427106bf4980bb247d8a25fed86a6d09cb&quot;
  block_height: 180
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x3bdcdb12a251d536acdb1af1c54acb37cd882c8fefa579587efd7828584f5422&quot;
      - &quot;0x452e7913b4f3ad6bc209cce6fc61588821ad6494282520a51e00926d913aac94&quot;
      - &quot;0x9567c1a847009105673244cbcccff11184117f0b3e465f48e1771ead7976779b&quot;
    deposit_root: &quot;0x358b5a17f9a64b0a891cf6741ceebd0b615dfb89490550c9b601551d13781068&quot;
    deposit_count: 179
    execution_block_hash: &quot;0xd6917e5c5a35c21ea97cb5bd1f9070427106bf4980bb247d8a25fed86a6d09cb&quot;
    execution_block_height: 180
- deposit_data:
    pubkey: &quot;0xb8cd27d87c94a69cecd953999908640b437f6215ddae069a1ad403f995dfde6e4ac46e5c85fdd8bd4fa655f74cc2bc80&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x986d671909e02d5efe0689ec87b8add58331b963e14b4ed9d989b586f1bbd1c5f119360e1bff27fe64e598601545c52d08386c175a1fff8acf5f6760d12acfb51027523ae9e7afd69ff4db75a1e580904ecf93a22da7ef83c5cbf08f92bc85cd&quot;
  deposit_data_root: &quot;0x9c0182b4b9d2a650eee485c0a5b6c743d4377dfb2dad1094972ecb50271f65a6&quot;
  eth1_data:
    deposit_root: &quot;0xfa89ade12d8c6d2a1d9800b7bb254622b424c40067e2b0b9e569bab078c024e6&quot;
    deposit_count: &quot;180&quot;
    block_hash: &quot;0x6c27c6e514081d3f51296640528a1da12d22a3462cb44810dad190c782f7cbde&quot;
  block_height: 181
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x3bdcdb12a251d536acdb1af1c54acb37cd882c8fefa579587efd7828584f5422&quot;
      - &quot;0x2d162bc4799fcfca576dc1ddf85c96c62bf3506922863de03d99b21d5d57b1fc&quot;
    deposit_root: &quot;0xfa89ade12d8c6d2a1d9800b7bb254622b424c40067e2b0b9e569bab078c024e6&quot;
    deposit_count: 180
    execution_block_hash: &quot;0x6c27c6e514081d3f51296640528a1da12d22a3462cb44810dad190c782f7cbde&quot;
    execution_block_height: 181
- deposit_data:
    pubkey: &quot;0xae37d415dda04db4f1abcf52c080c1c7a1921a819181161c4c2c18f809cdcf695de3f0f793c78802bacc1f4a32bd921a&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x97d0c9476aeb800a3e27f0b60f371679789e6bb03919bd65503eea6ee138275da5ea35f8a21352d68f1e5cde6be870d50c5356047cca0a2f043d83acfe44d3732e19f2aa54e844ccc57bb72b2061b00100cd28593eeab5601f35a594a2e82a98&quot;
  deposit_data_root: &quot;0x0da07a675920dd21e72440e13ac21d1d8d9864c92db43ffbb3bb100d6d112923&quot;
  eth1_data:
    deposit_root: &quot;0x46cb3dd3672791d77dadce6782dff84a88f34d594a9dd8441473f26bbff0e3fb&quot;
    deposit_count: &quot;181&quot;
    block_hash: &quot;0x7e23db8c0087f9044534d05457249a8f3bf7d50496eb005325709a44bc102b32&quot;
  block_height: 182
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x3bdcdb12a251d536acdb1af1c54acb37cd882c8fefa579587efd7828584f5422&quot;
      - &quot;0x2d162bc4799fcfca576dc1ddf85c96c62bf3506922863de03d99b21d5d57b1fc&quot;
      - &quot;0x0da07a675920dd21e72440e13ac21d1d8d9864c92db43ffbb3bb100d6d112923&quot;
    deposit_root: &quot;0x46cb3dd3672791d77dadce6782dff84a88f34d594a9dd8441473f26bbff0e3fb&quot;
    deposit_count: 181
    execution_block_hash: &quot;0x7e23db8c0087f9044534d05457249a8f3bf7d50496eb005325709a44bc102b32&quot;
    execution_block_height: 182
- deposit_data:
    pubkey: &quot;0xa7c674e6660a1930c546b4a7e345265a51527fbd53327f90cf7edce01ec2a9c9470c9d9f0a2e4dcfe4c0c5df4382aafa&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9765a98cfa6c562e97d0d18e26d20649229ecc001700852fcebdc804c14ad8fd6a9e4169972e16c0abcc07912469267d0f62d285abb659530eaac69c14dbace530e4f3d37b89ff58242c534c1e87a993dd0e53e52151f0021a699827196ab3fb&quot;
  deposit_data_root: &quot;0x3c02d11665be2b3121a49de3fc627ae4d2728050be2857acab0ab6800d30702f&quot;
  eth1_data:
    deposit_root: &quot;0xc2bd6a75ddac26bebb1dedff17e01e7388ba0d1daacad735c06dadf4d1497ab8&quot;
    deposit_count: &quot;182&quot;
    block_hash: &quot;0x24b5eec3f6b3ca56fe7e893edabe438ac14e338fae43ac6ad28b231a79e66768&quot;
  block_height: 183
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x3bdcdb12a251d536acdb1af1c54acb37cd882c8fefa579587efd7828584f5422&quot;
      - &quot;0x2d162bc4799fcfca576dc1ddf85c96c62bf3506922863de03d99b21d5d57b1fc&quot;
      - &quot;0x3a0f8fa7a03d6c1c8c53c26f944126d830c08b1cea4019c7980dc8d3cca5aeaf&quot;
    deposit_root: &quot;0xc2bd6a75ddac26bebb1dedff17e01e7388ba0d1daacad735c06dadf4d1497ab8&quot;
    deposit_count: 182
    execution_block_hash: &quot;0x24b5eec3f6b3ca56fe7e893edabe438ac14e338fae43ac6ad28b231a79e66768&quot;
    execution_block_height: 183
- deposit_data:
    pubkey: &quot;0xb2c9669a6f3e64a5f8b37c210c88adb507ce396042921b1aefd5bf52a3089f0ab0b5695cddf9b1a1157fe5dd43558e54&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8602ae96ab5650a7e477de5f00e10cb53826e3a268d96dbc0bd925e7370ff3f3fa7258261eb75a58d74c4de64db6713d19293e04d0cab40c1bd0c4669a7dd87a2b6272b8dd3c8f6414290843a4fbb945638eaf09594d44f502e2da1229d0ec3b&quot;
  deposit_data_root: &quot;0x68d5efabced0e3a67465028e2e9786d3626da8f47164112799f6280044e1da6d&quot;
  eth1_data:
    deposit_root: &quot;0x0e02f967291a37a27493d09d2cd5b530d83b67accb29fa7378acb5294b878af2&quot;
    deposit_count: &quot;183&quot;
    block_hash: &quot;0x392303f20a0d6202e844fffb6ac069f6a9dbaaa3f4447a7997afc74f1a83ee13&quot;
  block_height: 184
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x3bdcdb12a251d536acdb1af1c54acb37cd882c8fefa579587efd7828584f5422&quot;
      - &quot;0x2d162bc4799fcfca576dc1ddf85c96c62bf3506922863de03d99b21d5d57b1fc&quot;
      - &quot;0x3a0f8fa7a03d6c1c8c53c26f944126d830c08b1cea4019c7980dc8d3cca5aeaf&quot;
      - &quot;0x68d5efabced0e3a67465028e2e9786d3626da8f47164112799f6280044e1da6d&quot;
    deposit_root: &quot;0x0e02f967291a37a27493d09d2cd5b530d83b67accb29fa7378acb5294b878af2&quot;
    deposit_count: 183
    execution_block_hash: &quot;0x392303f20a0d6202e844fffb6ac069f6a9dbaaa3f4447a7997afc74f1a83ee13&quot;
    execution_block_height: 184
- deposit_data:
    pubkey: &quot;0xb00c6d2cf271b167f17135bf7bd14b7df669194045eb6f09b9dec787c7b608dcd42613dab0f857fbfa3fb84792a3e63e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x81bf33d08664f53464ad3fffff9475069948094c54b61edba63fb435969b7e621f7349991d72b43c8dd1bc48f20ccf1800e20a812f9996e115e9a98c98024186c4ba49722dbe463ea6c1c897105f24f5f983b2bf911c3af59123e43edfffefc0&quot;
  deposit_data_root: &quot;0xe2a3b3697c4174b669c5c9c3ce72ee244719fad0e9f198234cc3a13b7afcf5ef&quot;
  eth1_data:
    deposit_root: &quot;0x35db931e35f47dd387ae57bba681831b91a6579f034a754e7df92a8616679861&quot;
    deposit_count: &quot;184&quot;
    block_hash: &quot;0xa3d47fe70c8d2099b59a84c9f42bbc91c5bffe370010d5e535657fa3a1c4c816&quot;
  block_height: 185
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x3bdcdb12a251d536acdb1af1c54acb37cd882c8fefa579587efd7828584f5422&quot;
      - &quot;0xc81cb8f54677d5a3e4f8f079429f97cf7ea6fb35b82afc3d691763085cb8c78e&quot;
    deposit_root: &quot;0x35db931e35f47dd387ae57bba681831b91a6579f034a754e7df92a8616679861&quot;
    deposit_count: 184
    execution_block_hash: &quot;0xa3d47fe70c8d2099b59a84c9f42bbc91c5bffe370010d5e535657fa3a1c4c816&quot;
    execution_block_height: 185
- deposit_data:
    pubkey: &quot;0xa5e5e5af2ef8b65bf9b7575606f81e99d1fa645078544b0fcd4e0b506670e6a75504e6ba4001e6cec25632633d050276&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb05a3fcac399a997e7ada5181638bdd95668dbef59f2a62b9c45a85857a42afa5f885748f6d07ecdefcae45e736ec3b512a94bccd7be7bbaec688d9449f586ffb48a82f3c693d1248932d7b7026082ccd7c0a97aae7e714f39484614690abd72&quot;
  deposit_data_root: &quot;0x2c3e00b8923d7c7bba4859372c106c9aa052b00d19a1cd9fa3aedab4a5511741&quot;
  eth1_data:
    deposit_root: &quot;0x87e828349d121957dab0e13448ba28216514999e6dfff614978f171578e27e2b&quot;
    deposit_count: &quot;185&quot;
    block_hash: &quot;0xc2320a2fc8b6dd2243c3abcdde3847e2598ffb7aaf303ce46cb2416d8e3be4cb&quot;
  block_height: 186
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x3bdcdb12a251d536acdb1af1c54acb37cd882c8fefa579587efd7828584f5422&quot;
      - &quot;0xc81cb8f54677d5a3e4f8f079429f97cf7ea6fb35b82afc3d691763085cb8c78e&quot;
      - &quot;0x2c3e00b8923d7c7bba4859372c106c9aa052b00d19a1cd9fa3aedab4a5511741&quot;
    deposit_root: &quot;0x87e828349d121957dab0e13448ba28216514999e6dfff614978f171578e27e2b&quot;
    deposit_count: 185
    execution_block_hash: &quot;0xc2320a2fc8b6dd2243c3abcdde3847e2598ffb7aaf303ce46cb2416d8e3be4cb&quot;
    execution_block_height: 186
- deposit_data:
    pubkey: &quot;0xb7ad21b3cc61c96c4ea90e81cb5a39836f114dc477bb63da54af20f60d42dffb99aac4ae12ecb70288b1d226ca7c2522&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x80714ff567371483af7418f8d43a7e4adfd10d8d464e3fad6f72ca3d981920aa58d71235f1ffc6296b89a8744b66b23519367b3f5691e4410ca3bd068d28d88b4fedfdd91ac4ebbfe5a176827576c3a7176d4bb04f28c854051354db197d4112&quot;
  deposit_data_root: &quot;0x56f3cf8c6f87ca6f6298746c6aebf716e8d2387075aa400a69746cc5dbc31815&quot;
  eth1_data:
    deposit_root: &quot;0x7ac99b76e5fc809c4327f6edf9142d7bc55e12c3f9089a53066ec41500dfb5a0&quot;
    deposit_count: &quot;186&quot;
    block_hash: &quot;0x92708be0274d0ac8798c19482761e0a59edeb96edaf6e5fc2c1588a3365394b0&quot;
  block_height: 187
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x3bdcdb12a251d536acdb1af1c54acb37cd882c8fefa579587efd7828584f5422&quot;
      - &quot;0xc81cb8f54677d5a3e4f8f079429f97cf7ea6fb35b82afc3d691763085cb8c78e&quot;
      - &quot;0x9856919205a162db29485432bba026c979f7d89cfce702fc09657632a7a4f14a&quot;
    deposit_root: &quot;0x7ac99b76e5fc809c4327f6edf9142d7bc55e12c3f9089a53066ec41500dfb5a0&quot;
    deposit_count: 186
    execution_block_hash: &quot;0x92708be0274d0ac8798c19482761e0a59edeb96edaf6e5fc2c1588a3365394b0&quot;
    execution_block_height: 187
- deposit_data:
    pubkey: &quot;0xb3eea1ef03b3cd28709513f691d9b7aefcb9908efc7114e20e302598cc8dfcea02fd9423045f246112e4db1bdcfa9e14&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9576775970091bad8e182acfa971d69815b901f7818738490d7a94bf3b7fd5de9810aface9670ad6d4074295cd91c3fe073a989aaaf4143cdb6da3a0a6545e749cdbb914b38c9d3dddbcc5b57552ac5711f91fa2c59fe7ee52fca41c248dd7d4&quot;
  deposit_data_root: &quot;0x0fcd143f7e8ffc456987f9c887bb46743be683a31a84fbbfead37a6929f1d0be&quot;
  eth1_data:
    deposit_root: &quot;0x4a796a1cd10ad42e890c811c5261325c80df56afcfdb45b36ca98eca59d1cc1d&quot;
    deposit_count: &quot;187&quot;
    block_hash: &quot;0x8f679f6f3487c47c32be42dc94ca7d0bdad809ac30d9c8c38ad5010c046af1e1&quot;
  block_height: 188
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x3bdcdb12a251d536acdb1af1c54acb37cd882c8fefa579587efd7828584f5422&quot;
      - &quot;0xc81cb8f54677d5a3e4f8f079429f97cf7ea6fb35b82afc3d691763085cb8c78e&quot;
      - &quot;0x9856919205a162db29485432bba026c979f7d89cfce702fc09657632a7a4f14a&quot;
      - &quot;0x0fcd143f7e8ffc456987f9c887bb46743be683a31a84fbbfead37a6929f1d0be&quot;
    deposit_root: &quot;0x4a796a1cd10ad42e890c811c5261325c80df56afcfdb45b36ca98eca59d1cc1d&quot;
    deposit_count: 187
    execution_block_hash: &quot;0x8f679f6f3487c47c32be42dc94ca7d0bdad809ac30d9c8c38ad5010c046af1e1&quot;
    execution_block_height: 188
- deposit_data:
    pubkey: &quot;0xb0f147fdb3e17379f4933c18e6dd3e3c9e9414ed5920ab029dc5907c01f671f664e4bfde8a4bcfa273a57daeb824f695&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xadcea3abcac1ad298bc1711dd9555c2f9802e83e406debfc65ba54af21f99d652f440ebcf584d55915905dc5608c8e8a03081a51dd172d8cb0d11739ed1d6ffc7e9c0100cc4c565cdf7ca8d287f121dc7892583490629aaa93d2da2b8cc57d8e&quot;
  deposit_data_root: &quot;0x35cb7c2582792d09b08d2b5da3edb333de2b9074576999f0bbb0891adf6fb9b1&quot;
  eth1_data:
    deposit_root: &quot;0xab52ed24e0e69808c8d21fb5ca3ad3ec64c02344b953dd830261b97e3d7356d5&quot;
    deposit_count: &quot;188&quot;
    block_hash: &quot;0xe762ae9acb10f13c7f8e344c9fef7ee760577fe56c516050e1921cfa41e339c1&quot;
  block_height: 189
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x3bdcdb12a251d536acdb1af1c54acb37cd882c8fefa579587efd7828584f5422&quot;
      - &quot;0xc81cb8f54677d5a3e4f8f079429f97cf7ea6fb35b82afc3d691763085cb8c78e&quot;
      - &quot;0x1ad4ff6de258418fe600f0c8dabec3d6665177e5929c3570071111e85c21a90c&quot;
    deposit_root: &quot;0xab52ed24e0e69808c8d21fb5ca3ad3ec64c02344b953dd830261b97e3d7356d5&quot;
    deposit_count: 188
    execution_block_hash: &quot;0xe762ae9acb10f13c7f8e344c9fef7ee760577fe56c516050e1921cfa41e339c1&quot;
    execution_block_height: 189
- deposit_data:
    pubkey: &quot;0xae04fca0e06b256e03d4173d7f772e2106efe6f72d469243dba695179b5d2be8b61052c2844247ce49ec3b6cfd18c73d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb32e41533c45bff774de491d8b06cf576a27225dcd8b7713e980a7f61eb6bd4e53ba34484c0e061e38448e4bd4859868172fd3f4da5ebedcc4cb322f675ace60d7272cef4e7c27afaf8aa6f46d2b575bc14208ce19c6d1a29e759b883d70f590&quot;
  deposit_data_root: &quot;0x9426eb1a7383fe76d2759e9482e7cb6aca0b0b7afe88bde72a55c4a1c54d56b1&quot;
  eth1_data:
    deposit_root: &quot;0xe4ac94ad06eaff8884701227e53fc6cc79a3471f92bd7891f31432c1ad4b1e6d&quot;
    deposit_count: &quot;189&quot;
    block_hash: &quot;0x167dbceea97680bfd280469520320efcef8881d4f735bbee384fd13f0b8b6d48&quot;
  block_height: 190
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x3bdcdb12a251d536acdb1af1c54acb37cd882c8fefa579587efd7828584f5422&quot;
      - &quot;0xc81cb8f54677d5a3e4f8f079429f97cf7ea6fb35b82afc3d691763085cb8c78e&quot;
      - &quot;0x1ad4ff6de258418fe600f0c8dabec3d6665177e5929c3570071111e85c21a90c&quot;
      - &quot;0x9426eb1a7383fe76d2759e9482e7cb6aca0b0b7afe88bde72a55c4a1c54d56b1&quot;
    deposit_root: &quot;0xe4ac94ad06eaff8884701227e53fc6cc79a3471f92bd7891f31432c1ad4b1e6d&quot;
    deposit_count: 189
    execution_block_hash: &quot;0x167dbceea97680bfd280469520320efcef8881d4f735bbee384fd13f0b8b6d48&quot;
    execution_block_height: 190
- deposit_data:
    pubkey: &quot;0x98c4e0f20616fa174bb221011e731650cb841ec29305f074fdafbed1d04b761c107a854722d4a6d69d6a15f7bf85c7d0&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x974f103ca1b3e597a8edb9ddc0a26388902a3d016d25322bbbd3f8160117472cf6a8642f9ba00b40a364463e2598226607ddd490c88f48878dfe288bfd1eafeb1216d7702b80180afce9c3c891fb566795a6cf7a29ebabbcd729e735ae999c15&quot;
  deposit_data_root: &quot;0xa35b4a77af8ce0b6db5f6d71cfea7feae8cb334d1d8bf25b954c9c5e46ca812b&quot;
  eth1_data:
    deposit_root: &quot;0x3f7a7f8f15b24ce7b68da0583b9a3ea05e4eb68a97db64aecaf1be63dda51842&quot;
    deposit_count: &quot;190&quot;
    block_hash: &quot;0xc6adc26aa6328f1ba0efacfa64978e016f0cb79732f8d0030e5c5a908cde788f&quot;
  block_height: 191
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x3bdcdb12a251d536acdb1af1c54acb37cd882c8fefa579587efd7828584f5422&quot;
      - &quot;0xc81cb8f54677d5a3e4f8f079429f97cf7ea6fb35b82afc3d691763085cb8c78e&quot;
      - &quot;0x1ad4ff6de258418fe600f0c8dabec3d6665177e5929c3570071111e85c21a90c&quot;
      - &quot;0xd3cdd6fba6102cf506ca28a01aff74996a181dadaa9bf9819ff0fbffa9461e53&quot;
    deposit_root: &quot;0x3f7a7f8f15b24ce7b68da0583b9a3ea05e4eb68a97db64aecaf1be63dda51842&quot;
    deposit_count: 190
    execution_block_hash: &quot;0xc6adc26aa6328f1ba0efacfa64978e016f0cb79732f8d0030e5c5a908cde788f&quot;
    execution_block_height: 191
- deposit_data:
    pubkey: &quot;0x8800aa633b5ab60ea1da84e04e4a2fe6fb19c1d90197791ae6212e5349d306ff58afe02d4dfad739b07171ab5757d26b&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x98f03706cdb826e0909662f03081bd021f6c9e45eee0ca23ee0d99af23b1aee1b89f7f416a54ec69060f8ae12e28da4411cb16e3395d670c2ec8391e334a7de5691c5b2580f60929ec0c6b3cbefd4c98af66fbe609461338aced45e3e78b7c6a&quot;
  deposit_data_root: &quot;0xe0b69fa6a6be23e2f39b421d4f53ca95608f755be6f1e6f3cd131e4845a9557e&quot;
  eth1_data:
    deposit_root: &quot;0x3f9f9fcb0d2dddda55497b58cadb8ea93f1f3b741656a4849bb7fb0fa6722521&quot;
    deposit_count: &quot;191&quot;
    block_hash: &quot;0xc5f1e8d399f145ef92628f2d687619db3d5981fbf51dae54ff28b1f6641dce22&quot;
  block_height: 192
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0x01a4a7e7ce6c883eaa125ca6fd50f1342b9d35c305634bf843d7a609cc8b36f8&quot;
      - &quot;0x3bdcdb12a251d536acdb1af1c54acb37cd882c8fefa579587efd7828584f5422&quot;
      - &quot;0xc81cb8f54677d5a3e4f8f079429f97cf7ea6fb35b82afc3d691763085cb8c78e&quot;
      - &quot;0x1ad4ff6de258418fe600f0c8dabec3d6665177e5929c3570071111e85c21a90c&quot;
      - &quot;0xd3cdd6fba6102cf506ca28a01aff74996a181dadaa9bf9819ff0fbffa9461e53&quot;
      - &quot;0xe0b69fa6a6be23e2f39b421d4f53ca95608f755be6f1e6f3cd131e4845a9557e&quot;
    deposit_root: &quot;0x3f9f9fcb0d2dddda55497b58cadb8ea93f1f3b741656a4849bb7fb0fa6722521&quot;
    deposit_count: 191
    execution_block_hash: &quot;0xc5f1e8d399f145ef92628f2d687619db3d5981fbf51dae54ff28b1f6641dce22&quot;
    execution_block_height: 192
- deposit_data:
    pubkey: &quot;0x9474c26852bc2adfc52d093351dbf7ea822a2639d99db5b0d344e440e0ebbd1e856ae37daf3d91a05cf62f33342bd790&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x906782c06b770529831187f04df19f8c727112b36499e90e0ad918cfb44318fc0c3eb8e76184c0b5e40b088d93ff645a1903c216805754913fccff7f99c705fa735ef28f0343a7fc0f416bff0855368ab5d168e5b1a4002d149dddf9a7fbfe6c&quot;
  deposit_data_root: &quot;0x36a01af91aeb0f7858b003955815f552bdec183db519e9c8210c18560fdb8d1b&quot;
  eth1_data:
    deposit_root: &quot;0xa0fb785cecda8d27d5ce055f5cab99945fd8fb66281532c8d8b51e7596117bc0&quot;
    deposit_count: &quot;192&quot;
    block_hash: &quot;0x69d947eb6e6297a9449d82c807920062fc057f18e168cc0bc06bf5a89a8aa275&quot;
  block_height: 193
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
    deposit_root: &quot;0xa0fb785cecda8d27d5ce055f5cab99945fd8fb66281532c8d8b51e7596117bc0&quot;
    deposit_count: 192
    execution_block_hash: &quot;0x69d947eb6e6297a9449d82c807920062fc057f18e168cc0bc06bf5a89a8aa275&quot;
    execution_block_height: 193
- deposit_data:
    pubkey: &quot;0x86c82451f5ea5981c9031b3871e1463b10875934eda1c2520752d03bd51e71d943037b1a902979b6821eee7bd5779f78&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa9fe9f4af4705bda5e0ce2a369ebeef5ee8cde8cd9a66303e0f8100f282b23a5441a9c5be3c4ba6462d28117626fbdb6157951056078532b6e1717b5d5e44fc0839cefc1e34983900027caddcbffa2404014a35b16a3f6adf6cdcf35d8cdb396&quot;
  deposit_data_root: &quot;0x165cd78151e962dad0f4d9de56e66436d07d08beca179d0bf92a9b534791aab8&quot;
  eth1_data:
    deposit_root: &quot;0xc9fe80c8ecada066e8d0fdb2edec4b23b5f6d116bd65b980a9000c9fc251031e&quot;
    deposit_count: &quot;193&quot;
    block_hash: &quot;0xe2aade60b0fbbbad2f998e5badd1b8d3ced7fc0f7ec6f52ad7be45be91f38ec7&quot;
  block_height: 194
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x165cd78151e962dad0f4d9de56e66436d07d08beca179d0bf92a9b534791aab8&quot;
    deposit_root: &quot;0xc9fe80c8ecada066e8d0fdb2edec4b23b5f6d116bd65b980a9000c9fc251031e&quot;
    deposit_count: 193
    execution_block_hash: &quot;0xe2aade60b0fbbbad2f998e5badd1b8d3ced7fc0f7ec6f52ad7be45be91f38ec7&quot;
    execution_block_height: 194
- deposit_data:
    pubkey: &quot;0x864a08f5f022ce7757cb73be7ebf54e387fb3d5d4b0371d01ed493270be3236c5bc3b1272e42d2628f8f3c000d60eeaf&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x91b20dfe5a0f41fc5e8cb0b591faeed60ccf42c7d7ead8c17ba7075c6349bef80a3f263f175a57b6b3a4a1fc2ebb1a800d2f1c4f5d45713d1ee418fd903c01c168c507a01c207d182cfe012342bc0f57707a24c7c0df942e247540bb97fd824d&quot;
  deposit_data_root: &quot;0xdc1915b04568269a1f5dc65e91d8b380c104621822d27c6e4233a878ae0fef5e&quot;
  eth1_data:
    deposit_root: &quot;0x5f5a8158ce7e1a776c1b6187d70abb5f6676b608626c8d051abe7795c8435946&quot;
    deposit_count: &quot;194&quot;
    block_hash: &quot;0x32c72593ddc2739d5eae88440cee25dd36d46751816d1e6f8eed0ef30de97fcf&quot;
  block_height: 195
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x735a400964fac7b2378423de5960b50eaa02589ac565a271de0129a009f66614&quot;
    deposit_root: &quot;0x5f5a8158ce7e1a776c1b6187d70abb5f6676b608626c8d051abe7795c8435946&quot;
    deposit_count: 194
    execution_block_hash: &quot;0x32c72593ddc2739d5eae88440cee25dd36d46751816d1e6f8eed0ef30de97fcf&quot;
    execution_block_height: 195
- deposit_data:
    pubkey: &quot;0xa38e925dd3c45de24e8d73e9170168dc8206035ea711741d91a35c24fa71bb7981b89bdca545ee68e8680307a754e801&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x86bb5e37880c4338cf71f6e8712bb644c536d42369c715067ccbf57195781d66d6c321343cc2012d8384d22de7d1b1ff16d9cf7f6c4fbd3c0a5c78bfd15e3c88c3177d54b8967dba46627ab28f2ce2a0c7864d73364be3459fda509352129739&quot;
  deposit_data_root: &quot;0xf0715cc57042701d7d885798175984ad28a7034f132792da09509aa9df0ddc57&quot;
  eth1_data:
    deposit_root: &quot;0x2215ed2c63f505ac6fa32a11161d46f18db19bd56aed182298505b91366adb61&quot;
    deposit_count: &quot;195&quot;
    block_hash: &quot;0x04f7e15ab5591a7e1931772b057c38e3e385c6376d0e78dc0487be63de1d0ae9&quot;
  block_height: 196
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x735a400964fac7b2378423de5960b50eaa02589ac565a271de0129a009f66614&quot;
      - &quot;0xf0715cc57042701d7d885798175984ad28a7034f132792da09509aa9df0ddc57&quot;
    deposit_root: &quot;0x2215ed2c63f505ac6fa32a11161d46f18db19bd56aed182298505b91366adb61&quot;
    deposit_count: 195
    execution_block_hash: &quot;0x04f7e15ab5591a7e1931772b057c38e3e385c6376d0e78dc0487be63de1d0ae9&quot;
    execution_block_height: 196
- deposit_data:
    pubkey: &quot;0xa626ce67a47dea646ca21759fb026c6a258cc6ea8db330ee68cbd2455d1c347bbab51f3c08423eedecfa9e36920ef80e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xaf63ef6fdc71c6e3adb00df9284be7862cd48ce1a48e8c46b8d2640f72de9a290e160ff1535277594ff03785112e245514287bda41fcde5e4f41099b651467c5e1e580ce2de799e2740a074386c99c7778ef7e4c2a945e40f6e553e152db4f1a&quot;
  deposit_data_root: &quot;0x11c9f14e452b20440a56ff34917760d8dcd5a8e630dc7287357181cd486facb8&quot;
  eth1_data:
    deposit_root: &quot;0x0fa3a4dc90fb01188e00d9df9f45687f0c8a947228db2d315bcf554f2f4244e0&quot;
    deposit_count: &quot;196&quot;
    block_hash: &quot;0x5c247a56ac7270505ea91e5701c596d8ca2ff96acc269238ad57898ec20b900e&quot;
  block_height: 197
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x7a988bd4f4f2f44e82e3b09c2bfc32c9b2eeea372287b0222e2b1d9aaf4aa6d3&quot;
    deposit_root: &quot;0x0fa3a4dc90fb01188e00d9df9f45687f0c8a947228db2d315bcf554f2f4244e0&quot;
    deposit_count: 196
    execution_block_hash: &quot;0x5c247a56ac7270505ea91e5701c596d8ca2ff96acc269238ad57898ec20b900e&quot;
    execution_block_height: 197
- deposit_data:
    pubkey: &quot;0xaae22c365554eb37e2f402f6e6e4bfb0aa9416d8dda0a2f8ea5647ba7dd32023089f4dcc111121e56b52b1fdc29067b3&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb2f3d0bd66262806b2e9d0683f26016d1b7aa719d3f2739b43516900f126fa7b05f45376bf968769bf9d23cc47124f961960c17f9ce4e1b8f32544aefcedb5711327128e0d54ab20c31c7e11bc6b16dc8360107276385a30180b225aaa3a5cce&quot;
  deposit_data_root: &quot;0xdcd3b1b400746a2b3933c4a326f05ae8eab21177b548c9a4b23991d67221db2b&quot;
  eth1_data:
    deposit_root: &quot;0xf0767d7bb07aac096d4fc126f24e653dae0ed20d2e78a537239aeb416bd9f61c&quot;
    deposit_count: &quot;197&quot;
    block_hash: &quot;0x9e2658d320b979325eaefb9a6bc7f8bb8d993ffe01dc5048a598f5532a2f7868&quot;
  block_height: 198
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x7a988bd4f4f2f44e82e3b09c2bfc32c9b2eeea372287b0222e2b1d9aaf4aa6d3&quot;
      - &quot;0xdcd3b1b400746a2b3933c4a326f05ae8eab21177b548c9a4b23991d67221db2b&quot;
    deposit_root: &quot;0xf0767d7bb07aac096d4fc126f24e653dae0ed20d2e78a537239aeb416bd9f61c&quot;
    deposit_count: 197
    execution_block_hash: &quot;0x9e2658d320b979325eaefb9a6bc7f8bb8d993ffe01dc5048a598f5532a2f7868&quot;
    execution_block_height: 198
- deposit_data:
    pubkey: &quot;0xa5c3572c3b770214c14beb4d403d00ffa981480eb850195c99f3b6a2418cef98df28b7f1543d48a2500bfbe25e18ad80&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8c50c39e613fa154f1f7b0afd09e716982aa305d5b14fa151a387ecbf172ddb5072311ba32e850725bef0fbacd85fb701822a16e22c408af47500cc33b52c1f40c4ca15d2fb23b90da304e5d4c14ee828ba64556f0e3a4ba95b949ad0b050613&quot;
  deposit_data_root: &quot;0xd4386ba3269154bcebcf9be99f15c4a3c5cbb29f1233f4c8392610bf378bc7b1&quot;
  eth1_data:
    deposit_root: &quot;0xb900dfc08320f9c098a4eada49948bcd336be1f0b018ad9e741049dfb7b8ed93&quot;
    deposit_count: &quot;198&quot;
    block_hash: &quot;0xb7d727f382dcbb633b6354371ba93f697e4ee8974356879ad1e9071d041cab9e&quot;
  block_height: 199
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x7a988bd4f4f2f44e82e3b09c2bfc32c9b2eeea372287b0222e2b1d9aaf4aa6d3&quot;
      - &quot;0xd6fd367da921cad3a94901ae5bd5b3cbc3dfd1462326a6d78aa556797d2a4637&quot;
    deposit_root: &quot;0xb900dfc08320f9c098a4eada49948bcd336be1f0b018ad9e741049dfb7b8ed93&quot;
    deposit_count: 198
    execution_block_hash: &quot;0xb7d727f382dcbb633b6354371ba93f697e4ee8974356879ad1e9071d041cab9e&quot;
    execution_block_height: 199
- deposit_data:
    pubkey: &quot;0x8e793a86453b578e9b2f4c252e9ff18a8fb1af36fdd09d9144aea8e2b172738fde30faff3e9391d00827df5efb534821&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x80b57d9e5602fdf0ea42b3ed7eec2f69921264575bd8a63a685cb796db3eb8009bd89f080548ccf9982aca0e475990b90e89e0f2ee025eb3a28f3a928924e79025d6f123bfefc6739685068bb7c41d44c39101612cd65f779c64e9b94b3aae80&quot;
  deposit_data_root: &quot;0x705b49ff60a831179dc633062c11329e0fc800bffd91cd2162ee5f9824bd436d&quot;
  eth1_data:
    deposit_root: &quot;0x90211ebb48dc63aec0f43b619b9de255f716983c02de0f14a5b22e002cf8e2bd&quot;
    deposit_count: &quot;199&quot;
    block_hash: &quot;0x7889af3b1bec5acaba75ac39a3d3b9e95ca78aca797f305510409b9b468719c9&quot;
  block_height: 200
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x7a988bd4f4f2f44e82e3b09c2bfc32c9b2eeea372287b0222e2b1d9aaf4aa6d3&quot;
      - &quot;0xd6fd367da921cad3a94901ae5bd5b3cbc3dfd1462326a6d78aa556797d2a4637&quot;
      - &quot;0x705b49ff60a831179dc633062c11329e0fc800bffd91cd2162ee5f9824bd436d&quot;
    deposit_root: &quot;0x90211ebb48dc63aec0f43b619b9de255f716983c02de0f14a5b22e002cf8e2bd&quot;
    deposit_count: 199
    execution_block_hash: &quot;0x7889af3b1bec5acaba75ac39a3d3b9e95ca78aca797f305510409b9b468719c9&quot;
    execution_block_height: 200
- deposit_data:
    pubkey: &quot;0x969ca05ea6e49aa9b35d41c3354096f022e9a86718ac454cc8140419dd2ef5c19af37d42733a434a0e77970117ab884f&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa809d95bf1d42854575411ce2e535ea3b3cb263c07dffb715044442b196cd701ab25c79a5ae2440783f447c542f518680bbf949ba63ebd1f67bdbe832731a70fcfc6c3b549d2b160239ac852b41b4bd2bd23c88328bcbc6a20590a3fdaa8a3c2&quot;
  deposit_data_root: &quot;0xb2150789ea91596d6a1e50fe9841761330fdb7d4a8ad45528f7646684d9cc52a&quot;
  eth1_data:
    deposit_root: &quot;0xad8875e0af2f6d20643e3670fe9b991c24f3c0fecc85a59a41fb25c0e791fa17&quot;
    deposit_count: &quot;200&quot;
    block_hash: &quot;0xe9365f98552e964ec79bc2c5d2b0c741b2579c9558480d9ffaa1ee1d3df642b2&quot;
  block_height: 201
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x1edb1ff214185dbce83d685ff59906b779b360f07616112aa60e2d2dc8508c51&quot;
    deposit_root: &quot;0xad8875e0af2f6d20643e3670fe9b991c24f3c0fecc85a59a41fb25c0e791fa17&quot;
    deposit_count: 200
    execution_block_hash: &quot;0xe9365f98552e964ec79bc2c5d2b0c741b2579c9558480d9ffaa1ee1d3df642b2&quot;
    execution_block_height: 201
- deposit_data:
    pubkey: &quot;0x8b4ff71ee947785f545c017bbb9ce84c3f6a90097368cf79663b2e11acc53e18e8f7159919784f4d28282cb39a7113f7&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa4d04ea08df7c81fd63b7c08aabfc91858eeeebf022ee8dc1eb85b2d092555df04d55cc4c1c4994dc040493b1e310ea10afaf3631c04556b99c22cca3f4b51fc07b63d8eafc136d9dc25729de2b157493277de3ce6427a7828c7aee03ea73c54&quot;
  deposit_data_root: &quot;0xd543fb17cd7258052cfa9c1f3fba1a8a858ca4228f5d612b517030a0bf95badd&quot;
  eth1_data:
    deposit_root: &quot;0x15a652c1b3b70a8a66292accc0392096462bb6655e9d8528afb93d25732e75a7&quot;
    deposit_count: &quot;201&quot;
    block_hash: &quot;0xae4a7f8e521201b9b74056012a8bdb16a12ca537009ee7b2825cbf5277efbcd6&quot;
  block_height: 202
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x1edb1ff214185dbce83d685ff59906b779b360f07616112aa60e2d2dc8508c51&quot;
      - &quot;0xd543fb17cd7258052cfa9c1f3fba1a8a858ca4228f5d612b517030a0bf95badd&quot;
    deposit_root: &quot;0x15a652c1b3b70a8a66292accc0392096462bb6655e9d8528afb93d25732e75a7&quot;
    deposit_count: 201
    execution_block_hash: &quot;0xae4a7f8e521201b9b74056012a8bdb16a12ca537009ee7b2825cbf5277efbcd6&quot;
    execution_block_height: 202
- deposit_data:
    pubkey: &quot;0x984a6c8f4b7545aabbe9e0341c5ff990a05508c94e3757da474daf1d70124c8213ba2457718ec2d1fc562fc0bb36213d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xaf9e0247ecdab1f08ffeabf0b753f08007a14506b72377dbfb7d08069b43537995bee0d17a36be683d1d76d1f31218760ed3d72a992bcc4b8e33e1fee223c0614cca7f850d80e651628a3f1f0a129e5a2154e87e6f4c98978063f329eaeecf6f&quot;
  deposit_data_root: &quot;0xd4ff330e73b1afb26efcd9f7db884f99e14121b778ff54ed0f4cfdf5585d821d&quot;
  eth1_data:
    deposit_root: &quot;0x9c5993864595eabaeff8b60957115c80be20df7e4077c9799bc2718b85d31af4&quot;
    deposit_count: &quot;202&quot;
    block_hash: &quot;0x034d3912b8d10a6c82bff870992b671dd6053602d8b2ec63f5da2d533bbec9cd&quot;
  block_height: 203
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x1edb1ff214185dbce83d685ff59906b779b360f07616112aa60e2d2dc8508c51&quot;
      - &quot;0xd74dd49dc28c9adbab7fb5dd05c11f09a6c2ef7289e6d45b56462a2dc7879a0e&quot;
    deposit_root: &quot;0x9c5993864595eabaeff8b60957115c80be20df7e4077c9799bc2718b85d31af4&quot;
    deposit_count: 202
    execution_block_hash: &quot;0x034d3912b8d10a6c82bff870992b671dd6053602d8b2ec63f5da2d533bbec9cd&quot;
    execution_block_height: 203
- deposit_data:
    pubkey: &quot;0xa14cc20155f6fce0f248f9c306a32cbff425272829f7d920073c599b48168fb018c82b2aaf7cbb8b5f6449340023c37b&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa993e3a47f18a67b4c866ef09bc402471a32422eb2181c53dfbfe6636f8a67bda4ba86ed22d3c480f796f70a56c6b20914c4b80a014199f8b35ea115a9f6f2539283479d545d9a33dd5f6babc3d861d5b03cec90bac204239f074c08dbe9cce0&quot;
  deposit_data_root: &quot;0xd1a0715f2f749515ed034ed6a16583a2ba0276f53db1a55aa6cc9b3d795e99b5&quot;
  eth1_data:
    deposit_root: &quot;0x8d2051b62cacffd2a701ca5212d26832f0f4e0dec045d5c9a996fc1f3e3d4afa&quot;
    deposit_count: &quot;203&quot;
    block_hash: &quot;0xd4833843972af8732196ca814e0ea093f8113431a00b6173b899a1907f449971&quot;
  block_height: 204
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x1edb1ff214185dbce83d685ff59906b779b360f07616112aa60e2d2dc8508c51&quot;
      - &quot;0xd74dd49dc28c9adbab7fb5dd05c11f09a6c2ef7289e6d45b56462a2dc7879a0e&quot;
      - &quot;0xd1a0715f2f749515ed034ed6a16583a2ba0276f53db1a55aa6cc9b3d795e99b5&quot;
    deposit_root: &quot;0x8d2051b62cacffd2a701ca5212d26832f0f4e0dec045d5c9a996fc1f3e3d4afa&quot;
    deposit_count: 203
    execution_block_hash: &quot;0xd4833843972af8732196ca814e0ea093f8113431a00b6173b899a1907f449971&quot;
    execution_block_height: 204
- deposit_data:
    pubkey: &quot;0x89737986b89c213367ab0fb9a4eb998d9b0b713143cc8b0f209c9355607daa4f6e6c925dac3026890e291a9480463395&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb2a249d89d206c1e335bffc3838497ab0a8162bb827aff7ced1f08b819ac0e13583a6857eeb5c6eeeead7510062febaf0e142ab4c56a00802bea141e09e8708e750e3049cdbe91bb1448ffa1d2ec4f2c09a1626a774ceb0d0cbfe2e3a3c86207&quot;
  deposit_data_root: &quot;0x75b338b16d27eb10fbd28510660fe5816d30c5b2770abf69bf55aba29378746c&quot;
  eth1_data:
    deposit_root: &quot;0x1a2c95f781f6e6bc105146aa1405aa3a157e835e3159aae5e06a90fdb5e2c3e5&quot;
    deposit_count: &quot;204&quot;
    block_hash: &quot;0xadeb61523c297ae6488924eeb397706fbd36b90460ba258d39eddcc162bd32b9&quot;
  block_height: 205
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x1edb1ff214185dbce83d685ff59906b779b360f07616112aa60e2d2dc8508c51&quot;
      - &quot;0x81af419186b40e88c6b75d4a7e50d2eb478b523a890245e90a5a8666c14d8920&quot;
    deposit_root: &quot;0x1a2c95f781f6e6bc105146aa1405aa3a157e835e3159aae5e06a90fdb5e2c3e5&quot;
    deposit_count: 204
    execution_block_hash: &quot;0xadeb61523c297ae6488924eeb397706fbd36b90460ba258d39eddcc162bd32b9&quot;
    execution_block_height: 205
- deposit_data:
    pubkey: &quot;0xacd8a33698c0b95294943f0642c8b8919bdfbf1e92c61f26107f0f9ad989497742b58363e3d885e4d41a3bcfcc9c073c&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x88acce1b8ddba924e58450a9bbb256fc8cde985dcf0c13fad60a248adc6bcbefd26846db5bb49401baef27fd3599074e09a7b18cc4c7b509585febf85dc56d346462b209359ec2cb16d2684a23d744ef4fa0c24e25078408b73f31aaec0256a7&quot;
  deposit_data_root: &quot;0x96fc4bac61a6cd54baa17b7434ff2d25eb1d0e3442a602af6d484cb1db9cc6e4&quot;
  eth1_data:
    deposit_root: &quot;0xd50f56058861337da0c947bcdb625f96a40d3ca4621c58b07eaf8f311aef09db&quot;
    deposit_count: &quot;205&quot;
    block_hash: &quot;0xcc2b772737ecdf295382ee2a1ee8894aa42f33bea847e41e308728a0f31ed472&quot;
  block_height: 206
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x1edb1ff214185dbce83d685ff59906b779b360f07616112aa60e2d2dc8508c51&quot;
      - &quot;0x81af419186b40e88c6b75d4a7e50d2eb478b523a890245e90a5a8666c14d8920&quot;
      - &quot;0x96fc4bac61a6cd54baa17b7434ff2d25eb1d0e3442a602af6d484cb1db9cc6e4&quot;
    deposit_root: &quot;0xd50f56058861337da0c947bcdb625f96a40d3ca4621c58b07eaf8f311aef09db&quot;
    deposit_count: 205
    execution_block_hash: &quot;0xcc2b772737ecdf295382ee2a1ee8894aa42f33bea847e41e308728a0f31ed472&quot;
    execution_block_height: 206
- deposit_data:
    pubkey: &quot;0x964e84e1272dcea0fd79d698c1db18e847a5abe1406ef7988e61f39e3f1ef46371be5c25b6c2bf7e53788730f702b735&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x80f6d4e14705862b42e0ba0ab0a063488d8c2a68a61294029529e0eeccf938a0521d81a06147fc84ed867d1ac90b61b613446206fb88cabb7d1dba91eb9808e0dcc82e474e57be768868aa76e2be21dc777ce6ae0c083fa2ddc5abea3325bed0&quot;
  deposit_data_root: &quot;0xb0cb5384d711a5179c1c0fae14f4b843321abdce75b4203796e838cb6bd8f9ef&quot;
  eth1_data:
    deposit_root: &quot;0x750757bba12b4098e68006661bb2504a51ecd34f699881f9ed0191f0ff10f694&quot;
    deposit_count: &quot;206&quot;
    block_hash: &quot;0xc030e84c7c82778ecb278a7970d6f0d1b453a126fc97b57b964aff30e0f4d0c3&quot;
  block_height: 207
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x1edb1ff214185dbce83d685ff59906b779b360f07616112aa60e2d2dc8508c51&quot;
      - &quot;0x81af419186b40e88c6b75d4a7e50d2eb478b523a890245e90a5a8666c14d8920&quot;
      - &quot;0x177af982879e5f9786c25fcc42e0a20e48e09419dda7d03e71c6fe190adaeb5e&quot;
    deposit_root: &quot;0x750757bba12b4098e68006661bb2504a51ecd34f699881f9ed0191f0ff10f694&quot;
    deposit_count: 206
    execution_block_hash: &quot;0xc030e84c7c82778ecb278a7970d6f0d1b453a126fc97b57b964aff30e0f4d0c3&quot;
    execution_block_height: 207
- deposit_data:
    pubkey: &quot;0xb406b1521362c206669d15b4e5448aae2f1854c707592abc612973b4726d47edf3bcd9ecea1a4b6cffc6a9f7b039921f&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa8122c635f73ce71fa05d9680c5c48c39085864af2e811c324c233c73fd12aec80390bb306a6103bfdada9a2679874261462273f765cc1c5ebce0dff42cd9e80ff21fed9fb53e755602db2646742013a4e6ea25470da6fc11a3ad90b06651f43&quot;
  deposit_data_root: &quot;0xf74d5d7d3af4a3bf5f6695b1f34ab4d5336c9ef290b8a1794f44db60a1d85b7f&quot;
  eth1_data:
    deposit_root: &quot;0xe39b947702ff8af4cc4e50acaa3fc0d9ab834dd60237e134122f4a5b3690644d&quot;
    deposit_count: &quot;207&quot;
    block_hash: &quot;0xc3dbea25648a192a58491607281a486afb876647edf3523a4ae7cbebbe7067e2&quot;
  block_height: 208
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x1edb1ff214185dbce83d685ff59906b779b360f07616112aa60e2d2dc8508c51&quot;
      - &quot;0x81af419186b40e88c6b75d4a7e50d2eb478b523a890245e90a5a8666c14d8920&quot;
      - &quot;0x177af982879e5f9786c25fcc42e0a20e48e09419dda7d03e71c6fe190adaeb5e&quot;
      - &quot;0xf74d5d7d3af4a3bf5f6695b1f34ab4d5336c9ef290b8a1794f44db60a1d85b7f&quot;
    deposit_root: &quot;0xe39b947702ff8af4cc4e50acaa3fc0d9ab834dd60237e134122f4a5b3690644d&quot;
    deposit_count: 207
    execution_block_hash: &quot;0xc3dbea25648a192a58491607281a486afb876647edf3523a4ae7cbebbe7067e2&quot;
    execution_block_height: 208
- deposit_data:
    pubkey: &quot;0x8ca1bfff2cea25ae77249cb18146a39b9630be5947b65d15044a5e5816b6d29dac9da83504083bb8e87dbe97dfb6451f&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb83a7cf087d9dc1d5d587b103b84f2dbbfaa07d9385861937d2733eacb7c1e291336214aa6eea4b38377fb2a2a7de2170edf187e150125be3d3f8dee35f71b86be7bf4e8b390bfec55f15330dba9eefa1003fa9cc5122fa5c97d8d699f2e0a2b&quot;
  deposit_data_root: &quot;0xa0a33dd10f90a1ae86de6926edb1c128943a276b0532426521d187c1d5d363c6&quot;
  eth1_data:
    deposit_root: &quot;0xd2fe6e21e57ccfe1ededd19b56161b95e46022936207835b5563617107574558&quot;
    deposit_count: &quot;208&quot;
    block_hash: &quot;0x04a5433ddf3ad6d7dc52c745d96e863204f6f5add434e7d3a34cef73dd92e34e&quot;
  block_height: 209
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0xdc8256156a85778064cc0f46fab037bebc4ea0f98abe602270d370a7938cc711&quot;
    deposit_root: &quot;0xd2fe6e21e57ccfe1ededd19b56161b95e46022936207835b5563617107574558&quot;
    deposit_count: 208
    execution_block_hash: &quot;0x04a5433ddf3ad6d7dc52c745d96e863204f6f5add434e7d3a34cef73dd92e34e&quot;
    execution_block_height: 209
- deposit_data:
    pubkey: &quot;0x8c2e07abba50e0e1c624bae0dfff418f8f00502e377840f72e067cd33917a209c525fea7dcc7c44f0195a3b9a5dabbb5&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8b9f750ad5ca21b49bee7a975da855675f22904ed9bfc52d8a9491e6d96e8ba58fd67270d3084e91e3cc7ee7321d683d10864550590818c393d4c2a0003926e2e5a73164336c216babe5a0fef22ed447aa51c67cd4704762da4302e1f7d3b49b&quot;
  deposit_data_root: &quot;0xbdab20d7935a00c76b38e589b2073a6304eeed96e201423a7e420619edbbe893&quot;
  eth1_data:
    deposit_root: &quot;0x99fb82c1633a127efca032676fae7239a258b230c9323ec75644c7e659cbb231&quot;
    deposit_count: &quot;209&quot;
    block_hash: &quot;0x4d98b647dfe4547b79591778779136b4586160a163f5af4162fff546817ce4c4&quot;
  block_height: 210
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0xdc8256156a85778064cc0f46fab037bebc4ea0f98abe602270d370a7938cc711&quot;
      - &quot;0xbdab20d7935a00c76b38e589b2073a6304eeed96e201423a7e420619edbbe893&quot;
    deposit_root: &quot;0x99fb82c1633a127efca032676fae7239a258b230c9323ec75644c7e659cbb231&quot;
    deposit_count: 209
    execution_block_hash: &quot;0x4d98b647dfe4547b79591778779136b4586160a163f5af4162fff546817ce4c4&quot;
    execution_block_height: 210
- deposit_data:
    pubkey: &quot;0xa4c11513391dd190b1ac0cf8a1c2c1b9c39d925b38aecb950d357283beee49ab97b1d7dfb34396bcaf1c25658fdf7713&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb82675644e2826c0d7f77f6e4579d2ba98d37330591e05c3e87c5de32a8c97ff1fa48902289ec52d990fb81d2172a5590c569bdc5da0f0f7b9e7e07d86433f54197a37457ad65cec11b8028e88c8e175e45530910925fa6720be77a7b5323d8f&quot;
  deposit_data_root: &quot;0x49b40e35773ce653a0d51a6a45e20d9490df06160eb3059830a1f7ac9fb7393a&quot;
  eth1_data:
    deposit_root: &quot;0x10530b32816c9a5d1213ecba4ea82e0746d706721bd5dd14441b32050a6c33e4&quot;
    deposit_count: &quot;210&quot;
    block_hash: &quot;0xf35c48ec777e6646c99c7e1a873e949bf426354e55c2f115fe9670914e249af4&quot;
  block_height: 211
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0xdc8256156a85778064cc0f46fab037bebc4ea0f98abe602270d370a7938cc711&quot;
      - &quot;0xa94a6052c766a8599b6c20b938f754be5554f1b7a7ce0c8d337160a8b5c5fa68&quot;
    deposit_root: &quot;0x10530b32816c9a5d1213ecba4ea82e0746d706721bd5dd14441b32050a6c33e4&quot;
    deposit_count: 210
    execution_block_hash: &quot;0xf35c48ec777e6646c99c7e1a873e949bf426354e55c2f115fe9670914e249af4&quot;
    execution_block_height: 211
- deposit_data:
    pubkey: &quot;0x92afb506a8345b325a4fc1cf1135455eac709fe1c623bd8f0972cd9e51a763cc1e80bab1f7e01976d1c4f13af3c57caa&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xabd9696dd03623a4c7ee8eaba9dd7d40a3e2658d14c46ad3ba0e07fb6a8003788a6b22cde39b54b38e41549d4b278b270d4423ae1cf28228b92d29763200a97e454f66a2eb84e4596fa5b1776d288639c6ba9e2b8f07c6695e25d6369f59d9f6&quot;
  deposit_data_root: &quot;0xeb7df9a089860361315c6c55ed2695cad55caa92a751329b1c7f07e2c8055ccf&quot;
  eth1_data:
    deposit_root: &quot;0x30c2e1bb452f52ccf55edb7abc1ec4774dc3058e166ac655d79640f1226a7943&quot;
    deposit_count: &quot;211&quot;
    block_hash: &quot;0x7fa99b674a69b2752edf65932a26abdb23109fd68632de579ee075271fb91e80&quot;
  block_height: 212
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0xdc8256156a85778064cc0f46fab037bebc4ea0f98abe602270d370a7938cc711&quot;
      - &quot;0xa94a6052c766a8599b6c20b938f754be5554f1b7a7ce0c8d337160a8b5c5fa68&quot;
      - &quot;0xeb7df9a089860361315c6c55ed2695cad55caa92a751329b1c7f07e2c8055ccf&quot;
    deposit_root: &quot;0x30c2e1bb452f52ccf55edb7abc1ec4774dc3058e166ac655d79640f1226a7943&quot;
    deposit_count: 211
    execution_block_hash: &quot;0x7fa99b674a69b2752edf65932a26abdb23109fd68632de579ee075271fb91e80&quot;
    execution_block_height: 212
- deposit_data:
    pubkey: &quot;0x978b5194d96515146754465533db2d854e58371f26e78fe0eebc5c5b65917a3611947cab3bf7fc645e3cb870e4826019&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa7a1cbd47302acfa136a0114abe23123670fa4ad08e76fa4bc86007e6d941c71ce51dd92cbf1bf0d8836b4ae49b762a609559b7e798e3652a1eda20d89ace8606fff2ca5b1fe83c7783bed9267a18cc29e119c361329c574cc64fd8d209221d7&quot;
  deposit_data_root: &quot;0x4715ee6c9d226f8fa5da1140ef6cd9f7f2f67a417c24498377025d176df07ddb&quot;
  eth1_data:
    deposit_root: &quot;0x64f8471778ca893643db2d0be9bf4ba437611a0bc61cdcef451da8250e30baca&quot;
    deposit_count: &quot;212&quot;
    block_hash: &quot;0x0176fbf110c6da3ef4495909cdc1928eb1d9c77a7f41444b89c73dfaab805caf&quot;
  block_height: 213
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0xdc8256156a85778064cc0f46fab037bebc4ea0f98abe602270d370a7938cc711&quot;
      - &quot;0x80be627c56fc721728d409e5f72984eb86cf51276c72be17a7def353b43a0c36&quot;
    deposit_root: &quot;0x64f8471778ca893643db2d0be9bf4ba437611a0bc61cdcef451da8250e30baca&quot;
    deposit_count: 212
    execution_block_hash: &quot;0x0176fbf110c6da3ef4495909cdc1928eb1d9c77a7f41444b89c73dfaab805caf&quot;
    execution_block_height: 213
- deposit_data:
    pubkey: &quot;0xa3f841f04d3410b06a4b4eb31b3fd92eadcf486af60986723d34ef7b8a9908541ab6e7e0ecf421f593f86afdf8cbe894&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa810363310e7254b59997009c7b4739bf34856e5b16b7bbcebc61c23efdf727e36d9be21eaf4cffd2eaf4563d9fe6b060eb81f52882047c188136b132f34cdd5d9b67b04acdce7684aa16e9e378de9162c5886bb48cfa76435655b099d5190a7&quot;
  deposit_data_root: &quot;0x8a2db165a79f35c68b6f84336b364a56a68eb231908eec22d8b32dd85fcc731e&quot;
  eth1_data:
    deposit_root: &quot;0xee9bc848d593ff36992ed82fa51763caa78d4e5efd3a1fc7ae9f0fa7e19a8e94&quot;
    deposit_count: &quot;213&quot;
    block_hash: &quot;0x51c836750936babe4616f3402135e0ab0dd470e1151c44879a4d7662b9b08be3&quot;
  block_height: 214
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0xdc8256156a85778064cc0f46fab037bebc4ea0f98abe602270d370a7938cc711&quot;
      - &quot;0x80be627c56fc721728d409e5f72984eb86cf51276c72be17a7def353b43a0c36&quot;
      - &quot;0x8a2db165a79f35c68b6f84336b364a56a68eb231908eec22d8b32dd85fcc731e&quot;
    deposit_root: &quot;0xee9bc848d593ff36992ed82fa51763caa78d4e5efd3a1fc7ae9f0fa7e19a8e94&quot;
    deposit_count: 213
    execution_block_hash: &quot;0x51c836750936babe4616f3402135e0ab0dd470e1151c44879a4d7662b9b08be3&quot;
    execution_block_height: 214
- deposit_data:
    pubkey: &quot;0x81fba887a59873ac21711818cc8a63b2d4be1a69627f8c70586a56328a96aff64b880f1a07c125eda24784dfea0bacd4&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x93595db7bb94204b0825b54a3feaa6fbbbd2b7b2500eff772129f5d1633e5d3aabf48d138d91a11f3432fa45d49a7a2708ff91c8e53bffd0da37f03b03aebe01626d67ae5388a38325056e0ee9419f511520511fc772a51f4d512df91d562f24&quot;
  deposit_data_root: &quot;0x25cead55a29f7e5da33987cb5519bfbca4e10d14b747ec5d0e0a5d20f92a59cb&quot;
  eth1_data:
    deposit_root: &quot;0x0a6f0bafcc040a1296ff468e4ee75a20d5d26cc395113fefb164f4367ba017e5&quot;
    deposit_count: &quot;214&quot;
    block_hash: &quot;0x16b04fa33d14e124eb5a40a6af1b01daf48c86937982ae4d208f63bfbc4c7d7a&quot;
  block_height: 215
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0xdc8256156a85778064cc0f46fab037bebc4ea0f98abe602270d370a7938cc711&quot;
      - &quot;0x80be627c56fc721728d409e5f72984eb86cf51276c72be17a7def353b43a0c36&quot;
      - &quot;0x3785e11a23b4330f60f96e5dad69c55dab1a4c26c521e1c02f31f53639928bb7&quot;
    deposit_root: &quot;0x0a6f0bafcc040a1296ff468e4ee75a20d5d26cc395113fefb164f4367ba017e5&quot;
    deposit_count: 214
    execution_block_hash: &quot;0x16b04fa33d14e124eb5a40a6af1b01daf48c86937982ae4d208f63bfbc4c7d7a&quot;
    execution_block_height: 215
- deposit_data:
    pubkey: &quot;0xa9da8f5d1d62844df8f6fae763aa653127d6eaad1b4d8ba0b3b3417e9c486be3cc879ebad7fb182dcb364d3a292ab07f&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8748cde6cce3b3b7ad6b0a606e3bbefcfd26794817699117b7ba4993df77ebb656954eab6d0563447620584f04d08fd7106462757153f4ee774ebfc316c9a79836dc02beae801f29c1da0933928a8fe0f326a01538e3e32a6f10f728edb34eac&quot;
  deposit_data_root: &quot;0x884ed496077a53a281f0d0b56028a6d3947753cee6ab57d9bbb71cd9bee577db&quot;
  eth1_data:
    deposit_root: &quot;0xdd69faeaad85b4e2093afd6b377c9bc01987a0ae95ce1ca8f7dcc05407cdf147&quot;
    deposit_count: &quot;215&quot;
    block_hash: &quot;0x7b4865729e81f44da4be1ba22a9dcc7e422c9532974f5a9062ec67ac9bd62cb8&quot;
  block_height: 216
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0xdc8256156a85778064cc0f46fab037bebc4ea0f98abe602270d370a7938cc711&quot;
      - &quot;0x80be627c56fc721728d409e5f72984eb86cf51276c72be17a7def353b43a0c36&quot;
      - &quot;0x3785e11a23b4330f60f96e5dad69c55dab1a4c26c521e1c02f31f53639928bb7&quot;
      - &quot;0x884ed496077a53a281f0d0b56028a6d3947753cee6ab57d9bbb71cd9bee577db&quot;
    deposit_root: &quot;0xdd69faeaad85b4e2093afd6b377c9bc01987a0ae95ce1ca8f7dcc05407cdf147&quot;
    deposit_count: 215
    execution_block_hash: &quot;0x7b4865729e81f44da4be1ba22a9dcc7e422c9532974f5a9062ec67ac9bd62cb8&quot;
    execution_block_height: 216
- deposit_data:
    pubkey: &quot;0xadeb5ccef7679c5d26e97ac5d2c8222058bf8b7c5eaebd31db3f3ecbb8d00987e2b921711dc6953eff6852601c57b198&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb6b988317f7e9f48abbe85d6719ab37ed5abc8e98d31a4a37120767a70b9e1cf4a5e3b391b9941a201cc7a1f004fa97a0a1e3c8767e0fdac133d9292a8eb6da59e5ab28473bf87d0ea514ac69c60f1b56f9d31aea615fa48ac7feb17e1ebb4b4&quot;
  deposit_data_root: &quot;0x8699f7dfd9049a9383abc845a33cbce20d6bccd88b08cfb4166e298ead4e2dd9&quot;
  eth1_data:
    deposit_root: &quot;0x5bd775b2a763bac39331c22c5a1fb189221e22f7be74fb91dc7de0eeb7fcbfb6&quot;
    deposit_count: &quot;216&quot;
    block_hash: &quot;0x3660dc622cb11cd94846055fbeb73df41c3a088242dd96c2e5159de3f1cadc48&quot;
  block_height: 217
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0xdc8256156a85778064cc0f46fab037bebc4ea0f98abe602270d370a7938cc711&quot;
      - &quot;0x500bcd7598a4378a5c0ab9ae9ed217c3ca4c47ae0e0d34b7f5d9c987780cc413&quot;
    deposit_root: &quot;0x5bd775b2a763bac39331c22c5a1fb189221e22f7be74fb91dc7de0eeb7fcbfb6&quot;
    deposit_count: 216
    execution_block_hash: &quot;0x3660dc622cb11cd94846055fbeb73df41c3a088242dd96c2e5159de3f1cadc48&quot;
    execution_block_height: 217
- deposit_data:
    pubkey: &quot;0xa4e2f5a419590f3d30cbcf9cac0b4a89b636458dd6d38aa763694d4edd787056536089077d8e71cc4b182f8e87dc7916&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xaa4c51bc0d55bfc64de2f5123bb685777f33784bd632b61e65166ca8eb8084d8effe9e93e4a7359b88f4d03644fba521028e45f33996189e216637655ac2de55dcb0266289b81cd8b4e83c9e2bf0b7bd53d95942f66c7ee9d85776c8ff7af6ce&quot;
  deposit_data_root: &quot;0x1c3dd97d82fd3cc85dfedad67f70b39cd7bc2df5d376eee91cdb3137e1f420da&quot;
  eth1_data:
    deposit_root: &quot;0xebbdfeb489d87fc3cd7e79ae85adbb1ca2237cc64b6e4d37a6de996f32f6ea3e&quot;
    deposit_count: &quot;217&quot;
    block_hash: &quot;0x861a80af90e9a9b72718b0f49dac71c9c100cf0d00ecd0816b52278ce534e106&quot;
  block_height: 218
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0xdc8256156a85778064cc0f46fab037bebc4ea0f98abe602270d370a7938cc711&quot;
      - &quot;0x500bcd7598a4378a5c0ab9ae9ed217c3ca4c47ae0e0d34b7f5d9c987780cc413&quot;
      - &quot;0x1c3dd97d82fd3cc85dfedad67f70b39cd7bc2df5d376eee91cdb3137e1f420da&quot;
    deposit_root: &quot;0xebbdfeb489d87fc3cd7e79ae85adbb1ca2237cc64b6e4d37a6de996f32f6ea3e&quot;
    deposit_count: 217
    execution_block_hash: &quot;0x861a80af90e9a9b72718b0f49dac71c9c100cf0d00ecd0816b52278ce534e106&quot;
    execution_block_height: 218
- deposit_data:
    pubkey: &quot;0xa365251e868fae8780f009c14c7ddc349389230b75c79e11628b798dad880d9704a10f3358bea40f4136fe37fdec13ca&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8ec3bda16c205360636e42958f2076ed5e245cb48f3ea395d7680c689f62eb2bce4839b78129884aac0dab5345706f560310654681b3542f364b7aa4e426109ec7a772070be08997e80a890e2c1e8a4606f50cddc1fa8298ccb038719561bcc6&quot;
  deposit_data_root: &quot;0xbc2cf0159a36545c3dee043c7c612029a41ba7e4ac055d4c63ec9eb5b6564738&quot;
  eth1_data:
    deposit_root: &quot;0x7bc4420c8f3a21b553c643f7f33d830cfc6a658e9c5e53c24828403d3f487b82&quot;
    deposit_count: &quot;218&quot;
    block_hash: &quot;0x1fbb6ad18010df3607676411ede951c80c862b09db67219380cccdeed7d01422&quot;
  block_height: 219
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0xdc8256156a85778064cc0f46fab037bebc4ea0f98abe602270d370a7938cc711&quot;
      - &quot;0x500bcd7598a4378a5c0ab9ae9ed217c3ca4c47ae0e0d34b7f5d9c987780cc413&quot;
      - &quot;0x555908f2ac7299a40b5bb9269ac6d4ea86a65af7b648d63181f59cfa8314d17a&quot;
    deposit_root: &quot;0x7bc4420c8f3a21b553c643f7f33d830cfc6a658e9c5e53c24828403d3f487b82&quot;
    deposit_count: 218
    execution_block_hash: &quot;0x1fbb6ad18010df3607676411ede951c80c862b09db67219380cccdeed7d01422&quot;
    execution_block_height: 219
- deposit_data:
    pubkey: &quot;0x91ad339cd616316e79470c8695cd83b3811eb762f292c9a67c802b84e8e074ef5d208704dc1d5fb4a8343e0e44b25807&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x85d02a1704c8fcdcce59ac1ec6868f282d66839ea77e3673cabcbc178b8cefa93b4dec28167f38a83dacfed4b543f1260375c743bd25e015d8450ae0503594afd8eb394411dbd377f67b16436b6fafe1133e5012c474158aaf2881c040f27716&quot;
  deposit_data_root: &quot;0x0407440d40aec95c78548e7f9cfe22144f11166bd468e553a150733962098bd2&quot;
  eth1_data:
    deposit_root: &quot;0xadfa2dc986c1769723c3007c92843f9fba2a30d162548bfd2c5073a0520ef59b&quot;
    deposit_count: &quot;219&quot;
    block_hash: &quot;0x274170cd5f2790ae9938185e411eeb46d258cc7a1d13a3db5be028cc55a832ee&quot;
  block_height: 220
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0xdc8256156a85778064cc0f46fab037bebc4ea0f98abe602270d370a7938cc711&quot;
      - &quot;0x500bcd7598a4378a5c0ab9ae9ed217c3ca4c47ae0e0d34b7f5d9c987780cc413&quot;
      - &quot;0x555908f2ac7299a40b5bb9269ac6d4ea86a65af7b648d63181f59cfa8314d17a&quot;
      - &quot;0x0407440d40aec95c78548e7f9cfe22144f11166bd468e553a150733962098bd2&quot;
    deposit_root: &quot;0xadfa2dc986c1769723c3007c92843f9fba2a30d162548bfd2c5073a0520ef59b&quot;
    deposit_count: 219
    execution_block_hash: &quot;0x274170cd5f2790ae9938185e411eeb46d258cc7a1d13a3db5be028cc55a832ee&quot;
    execution_block_height: 220
- deposit_data:
    pubkey: &quot;0xa2d7d0d6f85894bda115022811b35ed5689143187a911fee5bcd0d6b1c78f4db3542223f496024fb2279b8ee76b5ea79&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa3d3e4034783206e696e6ed0fe1bb3d85b3ff78892422daf8f73b60c3526e862463c0ebec3f57fee778adadac8c4e096016430f0e39659ce5cb4ff72e377ef585b0e5fc06502fe030cc19c6ea3b63c475c4f151c698758f3ab55c6a757ca004d&quot;
  deposit_data_root: &quot;0x4ff35fdd7abcb307af9cd011f196a1dcc2383905c9f5267ccd8e12729932ded0&quot;
  eth1_data:
    deposit_root: &quot;0x6c54753ac7f623632b80b673c081a8aaef63506b1e4125e3d37557e191c911dc&quot;
    deposit_count: &quot;220&quot;
    block_hash: &quot;0x75b5f98560bcca1d3ef1f0ec2409dbe6ade0e7c167446aeaaa2834c4edbda673&quot;
  block_height: 221
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0xdc8256156a85778064cc0f46fab037bebc4ea0f98abe602270d370a7938cc711&quot;
      - &quot;0x500bcd7598a4378a5c0ab9ae9ed217c3ca4c47ae0e0d34b7f5d9c987780cc413&quot;
      - &quot;0x4615edc70a037bfbbe30e36784fc579c02930a553305855c6201fa479683dbd9&quot;
    deposit_root: &quot;0x6c54753ac7f623632b80b673c081a8aaef63506b1e4125e3d37557e191c911dc&quot;
    deposit_count: 220
    execution_block_hash: &quot;0x75b5f98560bcca1d3ef1f0ec2409dbe6ade0e7c167446aeaaa2834c4edbda673&quot;
    execution_block_height: 221
- deposit_data:
    pubkey: &quot;0x80029a26a45145f67892bfb25783d04f700e8917afc2b406695d4443fc3a45ab9c2c0572c357a33a9ed3877ebc479822&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb7f1069867daaee8b61e9e4494feb875e7192624aa37058b3862f796ef13e72df222abc75b902324af95af6baa62b5c40fbb70f59aeadcd4eb4a22a2591aeb150e9b04fbce014b4bebff2af4a7f38aa17ceb65c01cfb2aaab6f290703d12f878&quot;
  deposit_data_root: &quot;0x8d9db83da28ca8c0edf22485af80afc1f19b144a3b44797cff3f9b11fc580f0f&quot;
  eth1_data:
    deposit_root: &quot;0x994cebba4398a53a0b2acfe1754f7e26ad34f11cbdaa520bf72099e5ba45cfcb&quot;
    deposit_count: &quot;221&quot;
    block_hash: &quot;0x9f3818b078a804575ae9a09ac84ef7268274b564cb832e78662d8febb4b9e81b&quot;
  block_height: 222
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0xdc8256156a85778064cc0f46fab037bebc4ea0f98abe602270d370a7938cc711&quot;
      - &quot;0x500bcd7598a4378a5c0ab9ae9ed217c3ca4c47ae0e0d34b7f5d9c987780cc413&quot;
      - &quot;0x4615edc70a037bfbbe30e36784fc579c02930a553305855c6201fa479683dbd9&quot;
      - &quot;0x8d9db83da28ca8c0edf22485af80afc1f19b144a3b44797cff3f9b11fc580f0f&quot;
    deposit_root: &quot;0x994cebba4398a53a0b2acfe1754f7e26ad34f11cbdaa520bf72099e5ba45cfcb&quot;
    deposit_count: 221
    execution_block_hash: &quot;0x9f3818b078a804575ae9a09ac84ef7268274b564cb832e78662d8febb4b9e81b&quot;
    execution_block_height: 222
- deposit_data:
    pubkey: &quot;0xb6c8c112c7802a29579e14b228ae6a33fd7f0a3d33d06708b0f07cf7ec18f48e5ed7d5c47e7942c2aea2d1f4dd95557b&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x82d56bd4b5cf49b4aa037a0fac68e16f6285b7e2156e52267b15a0f424c60f6df11456d6ee28dd6e48782c52fdae8690062b82574903fe2f1a0b6a502f9667957022fb4685f9d77576cb580148448f1a8d223e2d3809c55d52314b33033053e7&quot;
  deposit_data_root: &quot;0x9c5e003d673975a5d0dd59c797238f6699c03098dafaf05c841725e13f2211e7&quot;
  eth1_data:
    deposit_root: &quot;0x3190b4adb59dba145f8bbcc6e138e92173e69a57b657bd09822f0dc4699bbd6d&quot;
    deposit_count: &quot;222&quot;
    block_hash: &quot;0xd35aa31fa61ada5bdfafd207b08316b9cf404bbbbb655756be1654367a556dea&quot;
  block_height: 223
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0xdc8256156a85778064cc0f46fab037bebc4ea0f98abe602270d370a7938cc711&quot;
      - &quot;0x500bcd7598a4378a5c0ab9ae9ed217c3ca4c47ae0e0d34b7f5d9c987780cc413&quot;
      - &quot;0x4615edc70a037bfbbe30e36784fc579c02930a553305855c6201fa479683dbd9&quot;
      - &quot;0x9d39bef25d1cb967f1c2afc70f08d3b10fa353154698513f0516f4a2326ef1c2&quot;
    deposit_root: &quot;0x3190b4adb59dba145f8bbcc6e138e92173e69a57b657bd09822f0dc4699bbd6d&quot;
    deposit_count: 222
    execution_block_hash: &quot;0xd35aa31fa61ada5bdfafd207b08316b9cf404bbbbb655756be1654367a556dea&quot;
    execution_block_height: 223
- deposit_data:
    pubkey: &quot;0xad4beca6ee84273739c03792e0a2096337c92fb096f7a902e0b09b8bf38d3f67c27a00b05d3ca69a0c9a43b491e8af4b&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x83afd2f9eee050a9e4f27651dca18b4ac1a4a48523aaa8d41fd7c87b26e288a07e4ff33ffd243fc053204b10a9abe3cc02b014ab31cdea51e94094d670dc9f6c830dc0c04f078cfcd74cb3cafa0bad02d99433d67a2377b53908062267573dc5&quot;
  deposit_data_root: &quot;0xa2c62c2afa8009d90ee3f7ded14aee4bf2d35ecea17026a011447c433f42986c&quot;
  eth1_data:
    deposit_root: &quot;0x21511637fa74488b88e6b0831a941619772a0679c69c43f0c7a91ec5ecda1b6b&quot;
    deposit_count: &quot;223&quot;
    block_hash: &quot;0x4320d44ec19761231557697186b0c02d807a9980a0a55c0af4b308bf9276fb65&quot;
  block_height: 224
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0xdc8256156a85778064cc0f46fab037bebc4ea0f98abe602270d370a7938cc711&quot;
      - &quot;0x500bcd7598a4378a5c0ab9ae9ed217c3ca4c47ae0e0d34b7f5d9c987780cc413&quot;
      - &quot;0x4615edc70a037bfbbe30e36784fc579c02930a553305855c6201fa479683dbd9&quot;
      - &quot;0x9d39bef25d1cb967f1c2afc70f08d3b10fa353154698513f0516f4a2326ef1c2&quot;
      - &quot;0xa2c62c2afa8009d90ee3f7ded14aee4bf2d35ecea17026a011447c433f42986c&quot;
    deposit_root: &quot;0x21511637fa74488b88e6b0831a941619772a0679c69c43f0c7a91ec5ecda1b6b&quot;
    deposit_count: 223
    execution_block_hash: &quot;0x4320d44ec19761231557697186b0c02d807a9980a0a55c0af4b308bf9276fb65&quot;
    execution_block_height: 224
- deposit_data:
    pubkey: &quot;0xa9ec8e4f705f27e6991a43ce006155825776666664d03be89929c4e5c9a01c7b759c1751e16b7a5d12084c419e97878d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa7b8b994844e1f99366d6b36e6802dc9e9c9e93898bbe2856b17b47f3ee086dead8413745f983d2d02aacbc58c623faf096201428d8cb54a5632334e9e486279e1c055fbb7b993827ee6823dbd633b3f5adc742133f2835470e2c047410d0218&quot;
  deposit_data_root: &quot;0x757bda9525f7bf25b15158d2eb44382b9271d489703752c15c79f2022e8bf9c0&quot;
  eth1_data:
    deposit_root: &quot;0x7abe7feec57fc014c31f919a1706868a569b15e5721201500f8a502f2c38ca73&quot;
    deposit_count: &quot;224&quot;
    block_hash: &quot;0x2e1d1bd56695914502d3d69e874b7969503fd2bddd90402671ae2e58210e30e4&quot;
  block_height: 225
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
    deposit_root: &quot;0x7abe7feec57fc014c31f919a1706868a569b15e5721201500f8a502f2c38ca73&quot;
    deposit_count: 224
    execution_block_hash: &quot;0x2e1d1bd56695914502d3d69e874b7969503fd2bddd90402671ae2e58210e30e4&quot;
    execution_block_height: 225
- deposit_data:
    pubkey: &quot;0x801a35e02410c44a3d81b564980738fc5a1d4d15b887c9477c8835c9038233fceddfac4c572226599b25fe3faefa85b1&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xafcafcad14dcb0b9aa9cbd21fefdee102e9da1439d676e7721edd62641b218dcb43264f361e56e2aecaffc31865c0f9304c7ebe5ce98f2c8dc230029bc681d9282b80ee0a4b1f18e8bdbcb80e6963608bc9d02182afed40ae381347577395f9c&quot;
  deposit_data_root: &quot;0xb0c1df18776f2378e753ae8937bce428eeed11559e3e00da552ad63fcebdefca&quot;
  eth1_data:
    deposit_root: &quot;0x3f5c02cdafa88b492e4e0e4a424dbe520959a048044e2c214460d9aea2fb203a&quot;
    deposit_count: &quot;225&quot;
    block_hash: &quot;0xb382a1b5dbb7b22d33c0000937f48cc9d2a1902576c2f789b2e13eeac8e295d0&quot;
  block_height: 226
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0xb0c1df18776f2378e753ae8937bce428eeed11559e3e00da552ad63fcebdefca&quot;
    deposit_root: &quot;0x3f5c02cdafa88b492e4e0e4a424dbe520959a048044e2c214460d9aea2fb203a&quot;
    deposit_count: 225
    execution_block_hash: &quot;0xb382a1b5dbb7b22d33c0000937f48cc9d2a1902576c2f789b2e13eeac8e295d0&quot;
    execution_block_height: 226
- deposit_data:
    pubkey: &quot;0xa38b922e79533b5fbec5f710ad90837cfce8073c982c57597027e5b6facaabc1edac06c7014fb1bcf8e11aaca4049dbb&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x813753be7c3419e592c33627668db7e74bae071c775b069194853355f9b91755d7dcc77672ebc011f313c8e3dafecc900f63260e6247d7a1b3c08ff3a6f1c9ff5b805b073049d1d197867d66cf9d356a3f6200041b4722d72564aeb29a0d4a7a&quot;
  deposit_data_root: &quot;0xb7c0ab5e3995215280d9af900c21a86dbb5d2cf9ff454f7a762b699358e9558c&quot;
  eth1_data:
    deposit_root: &quot;0x3e59ddbdc9744648e98694f1fb660d80bed43d554cee48dd274b482847d8c1c7&quot;
    deposit_count: &quot;226&quot;
    block_hash: &quot;0x6a3c9dafcc60d22e4747369ddd595545dacdf29926f2d3d6d4344ccb76fd8760&quot;
  block_height: 227
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0xcb67f19e86fe3c871884bd661d1a82b3780ca2e36b225490607b2a6eaf66a552&quot;
    deposit_root: &quot;0x3e59ddbdc9744648e98694f1fb660d80bed43d554cee48dd274b482847d8c1c7&quot;
    deposit_count: 226
    execution_block_hash: &quot;0x6a3c9dafcc60d22e4747369ddd595545dacdf29926f2d3d6d4344ccb76fd8760&quot;
    execution_block_height: 227
- deposit_data:
    pubkey: &quot;0xaf4cb80f788305b5c22f5a16bd3f5d2f2f50a403e4171b78e267a4e2d15b14beb04735b9ec206751a8163dae9ef3e96f&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x828d01fe50f60180f2639e9337a79c130615172a25692bb29c0e21b7a6644c63820b38840fd2dce4c425faa1c8ae96bc19d7761cf0db0493413ab186acb3fe78dae6c3db6d815d91f817645646d54ea03738db3b2ca686344bbbfadd06299c45&quot;
  deposit_data_root: &quot;0xd8a2270f803bc660d2ae17e446ea8a47d59fbac4662232c48d7093b28bf4446a&quot;
  eth1_data:
    deposit_root: &quot;0xb1d7530096f2c5173ff8c3568bdc8dc0eccff29e5697ee803b488a9b1c89c451&quot;
    deposit_count: &quot;227&quot;
    block_hash: &quot;0x1c539da3e3764a8e1dd17e19451b72437daeb6f8fe45e592e8d96a7970efad4b&quot;
  block_height: 228
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0xcb67f19e86fe3c871884bd661d1a82b3780ca2e36b225490607b2a6eaf66a552&quot;
      - &quot;0xd8a2270f803bc660d2ae17e446ea8a47d59fbac4662232c48d7093b28bf4446a&quot;
    deposit_root: &quot;0xb1d7530096f2c5173ff8c3568bdc8dc0eccff29e5697ee803b488a9b1c89c451&quot;
    deposit_count: 227
    execution_block_hash: &quot;0x1c539da3e3764a8e1dd17e19451b72437daeb6f8fe45e592e8d96a7970efad4b&quot;
    execution_block_height: 228
- deposit_data:
    pubkey: &quot;0x8e0d2214a6f4364590a4acbe3db7b3757b6f2f1eee526babc383e68fee4a7c9735a672f83aff5e9384d66b2fe264c9b1&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb07f7ee9cae121e1482ad8cf0855b4ea785bf039f3c09032e417f9b6418b83ad4c7e68f9b68ae015953f5519fd47c8a604d61acf88b0a10c6bb0061f99320be1ea016e3e07e5d6078574ff97d5e9fc315f5156cc6d4f79c541cec94cd5872dc5&quot;
  deposit_data_root: &quot;0x6bef5bde9f19342720ad3e132be8e8b9f7bf1508882bfe3f8ab56e1d11faf7db&quot;
  eth1_data:
    deposit_root: &quot;0xdce8bfad47155a9784cd497dcbc4dc3e96f262261246701c7792d45689a4e44b&quot;
    deposit_count: &quot;228&quot;
    block_hash: &quot;0x80caca4755897203f034dc16b609c1c2f4564cddad11ba383e79803dfc8b00e0&quot;
  block_height: 229
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0x5fb54637467f4b1e7fef955014bb48a73937a490562092a7bd1b99dac451fde4&quot;
    deposit_root: &quot;0xdce8bfad47155a9784cd497dcbc4dc3e96f262261246701c7792d45689a4e44b&quot;
    deposit_count: 228
    execution_block_hash: &quot;0x80caca4755897203f034dc16b609c1c2f4564cddad11ba383e79803dfc8b00e0&quot;
    execution_block_height: 229
- deposit_data:
    pubkey: &quot;0xb110c3a2e0100ca6338d66f81c4fa6eb5cdf0aaaf839ea8e0a67645d958fba5f13bba8b66f7f9d069d571f25cdb8e47f&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb8381b33e5ebec8010aec019e024668752bcebaa27b7ec938fe9e2a27d13f56c0e14c7fe115583ef230b5d0fb2d9a59c19f681fbc38f34b2aa9f63a58763f9804a01098031e66e2f7399482719c1729d07c25b852ca442dc620a69054de8e739&quot;
  deposit_data_root: &quot;0xbde6b47792e6754679c58260381c259bbd16097042b3d1c24404f6618b902e52&quot;
  eth1_data:
    deposit_root: &quot;0x9be8f309e2977f393617ff08549158f8185a24bf719001070d47e4fc19ab8806&quot;
    deposit_count: &quot;229&quot;
    block_hash: &quot;0xd9dda4f35c9c3edc515d03b9513be176d9420527d9ca62f2d7f484560d68985a&quot;
  block_height: 230
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0x5fb54637467f4b1e7fef955014bb48a73937a490562092a7bd1b99dac451fde4&quot;
      - &quot;0xbde6b47792e6754679c58260381c259bbd16097042b3d1c24404f6618b902e52&quot;
    deposit_root: &quot;0x9be8f309e2977f393617ff08549158f8185a24bf719001070d47e4fc19ab8806&quot;
    deposit_count: 229
    execution_block_hash: &quot;0xd9dda4f35c9c3edc515d03b9513be176d9420527d9ca62f2d7f484560d68985a&quot;
    execution_block_height: 230
- deposit_data:
    pubkey: &quot;0x879db2b2da4652de6f12a5a9e5f8665daaffa2e4c25fc8609af45b428dd2a35244b66ac2a910dd76c0961e56c660cf59&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa14756fbc7bfaa2c851472eddf1c887d18c23fcbb3d2594e9dc085ed3236ffcd19529ea1905a48a9c666a61c8571958a17bd95397ba545381da98689290fc8e359aaa24397ed33279e739e23ce2eb0f6de4b8c3e5ce1f4d15ed433429300f380&quot;
  deposit_data_root: &quot;0xefc249e2faad07106c09333b4cbb73a021b753a9e13c8eb611b495829b22d501&quot;
  eth1_data:
    deposit_root: &quot;0x71fc589ae852643220368a3ded27a2aced2490b2405e2c7746a1ded7037cf662&quot;
    deposit_count: &quot;230&quot;
    block_hash: &quot;0x58025631a377c39ec1ff81899fc7574e3e918af2fe5b6cbd52afc269b69f27b4&quot;
  block_height: 231
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0x5fb54637467f4b1e7fef955014bb48a73937a490562092a7bd1b99dac451fde4&quot;
      - &quot;0x00515eda2b4aff0be9224f7d22352562c340830ab164489eee65b44431d623b1&quot;
    deposit_root: &quot;0x71fc589ae852643220368a3ded27a2aced2490b2405e2c7746a1ded7037cf662&quot;
    deposit_count: 230
    execution_block_hash: &quot;0x58025631a377c39ec1ff81899fc7574e3e918af2fe5b6cbd52afc269b69f27b4&quot;
    execution_block_height: 231
- deposit_data:
    pubkey: &quot;0xa4cc78a560437549a4924c1d355e81a3467aaf9d7e7e1b4c7df6b39528345bb950c51c5316abe27f8618e5c7ca7dc5b7&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xae747862da82759f24af4f9103c1ed3f87f235a89fa77853050c607e11a10f4bff05de215e6c6aaaf5b9d6b539451d1003c8531ba3bd379edb89a0ee7b5219f011336fd8232d40a10238559263bcfe81da3f31fd29397f8e0b9cff013b9da2ba&quot;
  deposit_data_root: &quot;0x9e5b59deb9c620e5218e2064db2836bff8fd7cadcee035ee762f8db7c574cae5&quot;
  eth1_data:
    deposit_root: &quot;0x30d14127c55bfb5dbcd6adc091e29a155cea9657dcc190ce17d57875fb723556&quot;
    deposit_count: &quot;231&quot;
    block_hash: &quot;0x6b95be192a6c1967572f0e532c52335f7c273cdbe805373da35ab2ee78f7ddef&quot;
  block_height: 232
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0x5fb54637467f4b1e7fef955014bb48a73937a490562092a7bd1b99dac451fde4&quot;
      - &quot;0x00515eda2b4aff0be9224f7d22352562c340830ab164489eee65b44431d623b1&quot;
      - &quot;0x9e5b59deb9c620e5218e2064db2836bff8fd7cadcee035ee762f8db7c574cae5&quot;
    deposit_root: &quot;0x30d14127c55bfb5dbcd6adc091e29a155cea9657dcc190ce17d57875fb723556&quot;
    deposit_count: 231
    execution_block_hash: &quot;0x6b95be192a6c1967572f0e532c52335f7c273cdbe805373da35ab2ee78f7ddef&quot;
    execution_block_height: 232
- deposit_data:
    pubkey: &quot;0xb0959a30fabda6f21ccfff1b9a4854fbd869e767b253c2f9bc08c4cbbaa3c24f37a7124dd8e67e2b0bdf4b052c2c9873&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb64885eaff19de38042492a996f157cca5fcf0194227e2d06b6aac66c8dd851806072acc35516a314384b5a11acedc2709ff085e2a236ee9b1a7c2247d229fb709c012daf6d0b3a8e1cfcaffd6f7d205d8feb2464cfa4d2c99c2b225d7b179cc&quot;
  deposit_data_root: &quot;0x7f90ce698e743d4711e8b9b3f6ab4461dc9f08f24f98e9a89319c3b0a526f37f&quot;
  eth1_data:
    deposit_root: &quot;0x53f5b42be17a65b15e69dedbb6555c8c16807de1e45febdf338ad2cca4172620&quot;
    deposit_count: &quot;232&quot;
    block_hash: &quot;0x7de5afd9e8b8fee40adb38fb6fae15c8bd6270fa7c2985eeab19ba6cba7f8084&quot;
  block_height: 233
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0xcfbab008757754f57710fd99c573283e4cbb498498c07b5f6d1a5c1102ee3bd5&quot;
    deposit_root: &quot;0x53f5b42be17a65b15e69dedbb6555c8c16807de1e45febdf338ad2cca4172620&quot;
    deposit_count: 232
    execution_block_hash: &quot;0x7de5afd9e8b8fee40adb38fb6fae15c8bd6270fa7c2985eeab19ba6cba7f8084&quot;
    execution_block_height: 233
- deposit_data:
    pubkey: &quot;0xa050c5180ee6cd9daef723caa6367112bc4b06636c3da59c3377e5e7b536942417a29cd5d1dad73011db4492032caff6&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9208506ad4ad676f471b05fb33ab7d87b7b1fb7d4a8ef630c87407a568150aa88df852bde74fa50dbcaf3b9f81211c4c1759eed3952f470772d2dbe2c57ed35886530659cf3838ac540d9be98309549ff7121eb959d9f6deed0c25a63fb2a944&quot;
  deposit_data_root: &quot;0xba747d4e778466e602ce18816cff1e7c36f7a8c16531a624a3920df6d7650441&quot;
  eth1_data:
    deposit_root: &quot;0x29f2b6c06fc3cfa95c9960525011a1ec1ea97bcb65ece736ac0714e6699a308e&quot;
    deposit_count: &quot;233&quot;
    block_hash: &quot;0x046a47e1afbda13b44861a64c6013262ce2d2bbd3afc4c0e72f55a049acc2acc&quot;
  block_height: 234
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0xcfbab008757754f57710fd99c573283e4cbb498498c07b5f6d1a5c1102ee3bd5&quot;
      - &quot;0xba747d4e778466e602ce18816cff1e7c36f7a8c16531a624a3920df6d7650441&quot;
    deposit_root: &quot;0x29f2b6c06fc3cfa95c9960525011a1ec1ea97bcb65ece736ac0714e6699a308e&quot;
    deposit_count: 233
    execution_block_hash: &quot;0x046a47e1afbda13b44861a64c6013262ce2d2bbd3afc4c0e72f55a049acc2acc&quot;
    execution_block_height: 234
- deposit_data:
    pubkey: &quot;0x96dddc7430e5f035c0c4d005ef950eea0b3cb8188fa1db85b947bfa69745d4cc0f8ca522b3880823154796fcfedd970b&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x88df1ad86744a29bc86506d348e9e3f1f762a1a266ddb6a655a34cc45ea7897cb5467d267022e8e8c9f280ca2aecec081652fc8ac2a3de171c6e240687fe0564bbb5671e46ee029cb3ae63b900838793b89913966a4823499fcc2be104c8b177&quot;
  deposit_data_root: &quot;0x40f5c80a61e389915cd4d3e5f80ab4db55c85a2f4b2e57bf758f445538dcd272&quot;
  eth1_data:
    deposit_root: &quot;0xbfa95468dce6817d6393887438d0a90146367ced8533a2667f78b841e6c4a9d8&quot;
    deposit_count: &quot;234&quot;
    block_hash: &quot;0x28781e828d46a57b76c052c4b3ef44160cac67098a057a94faebc2f4e3540d74&quot;
  block_height: 235
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0xcfbab008757754f57710fd99c573283e4cbb498498c07b5f6d1a5c1102ee3bd5&quot;
      - &quot;0xaba4968db31e01e16a317caeaa2d3bc79f6efbe46926a9f8bf6576931d120e34&quot;
    deposit_root: &quot;0xbfa95468dce6817d6393887438d0a90146367ced8533a2667f78b841e6c4a9d8&quot;
    deposit_count: 234
    execution_block_hash: &quot;0x28781e828d46a57b76c052c4b3ef44160cac67098a057a94faebc2f4e3540d74&quot;
    execution_block_height: 235
- deposit_data:
    pubkey: &quot;0xb1eef7970c10f8bb2a2d70f566657cc0209b198011ee3a4aaec9e7ddaf571fecc03db1042997b1554286e52ea95cce27&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa6274df964c6175a7c789c2244c212bebda8c658fc21f3cc9cc2aaa81294785c9f3985bdf9203709b4bf4b945d25e60e02cc06cc6d9a5a1b88785ab48488d820458986e9561c4e45ec3f5627573fb7e499ca98c5b9461448a1e8c78f77dbe104&quot;
  deposit_data_root: &quot;0x3f6f7e82534853f2c9d372660aa30baf5c68749d16f7e01a4a208b2bb735d102&quot;
  eth1_data:
    deposit_root: &quot;0x000d046fe7ebb4a367257dd30536ddce1ba46896bf412d3b4315ff19c62a17cf&quot;
    deposit_count: &quot;235&quot;
    block_hash: &quot;0xde2f782bde063ebce8d17a6ffb690e59eef61c57854fae148a85d05a1d062c45&quot;
  block_height: 236
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0xcfbab008757754f57710fd99c573283e4cbb498498c07b5f6d1a5c1102ee3bd5&quot;
      - &quot;0xaba4968db31e01e16a317caeaa2d3bc79f6efbe46926a9f8bf6576931d120e34&quot;
      - &quot;0x3f6f7e82534853f2c9d372660aa30baf5c68749d16f7e01a4a208b2bb735d102&quot;
    deposit_root: &quot;0x000d046fe7ebb4a367257dd30536ddce1ba46896bf412d3b4315ff19c62a17cf&quot;
    deposit_count: 235
    execution_block_hash: &quot;0xde2f782bde063ebce8d17a6ffb690e59eef61c57854fae148a85d05a1d062c45&quot;
    execution_block_height: 236
- deposit_data:
    pubkey: &quot;0x85f65540cda46d23cf0ef948b5793b46a81771b4621ffb4b98c6dfa222208ffe3215bfdd436eed5ab124969704752e18&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x82b2f53b7b688fe92b7f3c0f991e2a8877c7da12806e596d2a36fe3d444a5e7fb2ab90b3989d2e0e7e3bd1af6086cc1a05281be5c581ac36e4a888f10460e6b1a5dc9f1de72580932df9a88fab6d0aa1646fd580dc54118bb08670569df173b0&quot;
  deposit_data_root: &quot;0x14f05f69965b40e8362e9ccedea325ba0686bbe2777dcfa7db391cf2176e9dd7&quot;
  eth1_data:
    deposit_root: &quot;0xfc113b844286b5723c0470bacc323281edcb6c74aa79e716649bce8785ac4bbc&quot;
    deposit_count: &quot;236&quot;
    block_hash: &quot;0xad091a6f9838ac87857dc11a206927e15fe263591c391d3aee5ddf3ab5cd19f0&quot;
  block_height: 237
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0xcfbab008757754f57710fd99c573283e4cbb498498c07b5f6d1a5c1102ee3bd5&quot;
      - &quot;0x0f7262bce5861c90229709693935a8f977f19c7ea94b4e8bd1f12985baecf8bf&quot;
    deposit_root: &quot;0xfc113b844286b5723c0470bacc323281edcb6c74aa79e716649bce8785ac4bbc&quot;
    deposit_count: 236
    execution_block_hash: &quot;0xad091a6f9838ac87857dc11a206927e15fe263591c391d3aee5ddf3ab5cd19f0&quot;
    execution_block_height: 237
- deposit_data:
    pubkey: &quot;0x8d016fd1936593cb41b3e94c01ae213a770cfcc1e94e06bf90dd77dfb8721090cd17255aeb4b4da53bc2a70257d2bc5c&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xac1c8006b0200c3dd436b477bb2b280bb786f28790bf5da9fe4011ac3fadd996d6409642ec024fd238e46c1f3aa84a4716752ece5f09fe5f595a257c2eaa516375f9911255f91e938cf27ba02ee75abb5dcd22d2f25659d1212dc0bf5dc4b9d4&quot;
  deposit_data_root: &quot;0x9cfa02a46e3cc3e3f5aad20774b3f64b1cb9808321b3604b55b87e0868c9bb95&quot;
  eth1_data:
    deposit_root: &quot;0xa18458316c22446c517019010eb193e2277fde1eb5aad56e1e42df9c231b2e31&quot;
    deposit_count: &quot;237&quot;
    block_hash: &quot;0x691970c03abbade8133576a1253209024f4bc0139674b807e6204bc3e23793a2&quot;
  block_height: 238
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0xcfbab008757754f57710fd99c573283e4cbb498498c07b5f6d1a5c1102ee3bd5&quot;
      - &quot;0x0f7262bce5861c90229709693935a8f977f19c7ea94b4e8bd1f12985baecf8bf&quot;
      - &quot;0x9cfa02a46e3cc3e3f5aad20774b3f64b1cb9808321b3604b55b87e0868c9bb95&quot;
    deposit_root: &quot;0xa18458316c22446c517019010eb193e2277fde1eb5aad56e1e42df9c231b2e31&quot;
    deposit_count: 237
    execution_block_hash: &quot;0x691970c03abbade8133576a1253209024f4bc0139674b807e6204bc3e23793a2&quot;
    execution_block_height: 238
- deposit_data:
    pubkey: &quot;0x953e4c8ef12a42ae5376ba23e06cfabf11c5e3fa773a98b487723225f1a2df60be50a54a7d5621bd85be25ddeb73af38&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x933a3fe4013d7669896335b2c866b160b31b1032bf990ffc350d94c747effc2c2e29f189f875246ef57dc6a0bbd143a200c2c48be3182476725fa3844a52f2a069ee18900e1c2b039d11bdfecb4ac068e3a1dd5c73b3d69db0f1b51b240c4f9e&quot;
  deposit_data_root: &quot;0xcd3264430f4abf9cd490f8f5712b274a53c4a32c3333624f39ec75bae8fabe98&quot;
  eth1_data:
    deposit_root: &quot;0x9e37fd0fc2fd4db56f06797479f91b79ddead19653a7aa07c766429cea8bf45d&quot;
    deposit_count: &quot;238&quot;
    block_hash: &quot;0x866e5ee2515e964c4254798b6ad79900f96759665c738b22e7ece20d6e286b50&quot;
  block_height: 239
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0xcfbab008757754f57710fd99c573283e4cbb498498c07b5f6d1a5c1102ee3bd5&quot;
      - &quot;0x0f7262bce5861c90229709693935a8f977f19c7ea94b4e8bd1f12985baecf8bf&quot;
      - &quot;0x9cf3b21fcd49adade498b802a1debdb7d2beec431c1aa4372eef06deec2bc955&quot;
    deposit_root: &quot;0x9e37fd0fc2fd4db56f06797479f91b79ddead19653a7aa07c766429cea8bf45d&quot;
    deposit_count: 238
    execution_block_hash: &quot;0x866e5ee2515e964c4254798b6ad79900f96759665c738b22e7ece20d6e286b50&quot;
    execution_block_height: 239
- deposit_data:
    pubkey: &quot;0x90b3bf8ea91bae7c8d0e33974c65e1ce677328030cf63111d9ee5cbf6d300c72fc033c3c70d6afc21858fb9d2964875a&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8462a3226ea043966c38f560258a0628da44dd4ca7daeaf82bbc64b77c21a5a34f2ded52a1ff0c012b6538e8e49d7801045b3705d346fcef4d6cbfdd694f784b4a557ebf6354c0e64554a31ccd8bb0be35c6aabbd8f0be2f02face2853211013&quot;
  deposit_data_root: &quot;0xaeb3b2cc80454c6e05ea47a0511b3a569f488624dca56695d4f984414a0ab986&quot;
  eth1_data:
    deposit_root: &quot;0x3148e7f341bb5610dcaf8209f84e28569aa86f787a4992e1c530fa35ec25851b&quot;
    deposit_count: &quot;239&quot;
    block_hash: &quot;0x1eadc81c31cc7f4b5c446bd88dcba2fa748773b9c6f847b1f81b254a9db5cd29&quot;
  block_height: 240
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0xcfbab008757754f57710fd99c573283e4cbb498498c07b5f6d1a5c1102ee3bd5&quot;
      - &quot;0x0f7262bce5861c90229709693935a8f977f19c7ea94b4e8bd1f12985baecf8bf&quot;
      - &quot;0x9cf3b21fcd49adade498b802a1debdb7d2beec431c1aa4372eef06deec2bc955&quot;
      - &quot;0xaeb3b2cc80454c6e05ea47a0511b3a569f488624dca56695d4f984414a0ab986&quot;
    deposit_root: &quot;0x3148e7f341bb5610dcaf8209f84e28569aa86f787a4992e1c530fa35ec25851b&quot;
    deposit_count: 239
    execution_block_hash: &quot;0x1eadc81c31cc7f4b5c446bd88dcba2fa748773b9c6f847b1f81b254a9db5cd29&quot;
    execution_block_height: 240
- deposit_data:
    pubkey: &quot;0x9412476b39b4c36ba977e5aa1bda710a773b48c95a6486d0201a978eaf58c51bce7c8b37e34f3bd61322c2f7caf53bc5&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa8c5224f300841a22377468fa8aa7a8c5d1ddb596c6ec85c7139724cf83c6b0707ec61f9a02a1aa185e553c260835f860f599d2c4afb79bd5506e8f077dee4cedaee36cd6ecf67dc5183110b1d00cdcc6b2fc98a61d41acaf5c207330bb535d6&quot;
  deposit_data_root: &quot;0x65bd202a5b6f083b0e57a1d1a1d99e2cd60a71071788a0ebf89723cf1f98430c&quot;
  eth1_data:
    deposit_root: &quot;0x8e9055eb4be6187b776047300d22266af54af5aa362e78bfe60b8815d30d06a3&quot;
    deposit_count: &quot;240&quot;
    block_hash: &quot;0x6f0584cc8761c8739652bd61a2e7c6f89e6a3e0c748b8555f6c900d566081bad&quot;
  block_height: 241
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0x15e5ab79d2e91316abac7981530e445f4c70332f1628d1883a21d17a699c1b4e&quot;
    deposit_root: &quot;0x8e9055eb4be6187b776047300d22266af54af5aa362e78bfe60b8815d30d06a3&quot;
    deposit_count: 240
    execution_block_hash: &quot;0x6f0584cc8761c8739652bd61a2e7c6f89e6a3e0c748b8555f6c900d566081bad&quot;
    execution_block_height: 241
- deposit_data:
    pubkey: &quot;0x8202a977e0d543f09f5f4b010fe308031db9c022058591b4ecc22205853f96fab8a906e31659cec3f20c23deced33fb0&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x819cac5109e38a3e23be784a0803836ae5892a7ebf529d5b69ec3483f0765955d21453a7c8c9dbd48a67c6f6137484c9125a886a9562a70333f4a4643c2cf0a74899bd1b6f50501b25b73919a81b3a590e432af6d9d1649c484fd58d38a80446&quot;
  deposit_data_root: &quot;0x3c87bafbdd6e4bd6fd9c9b911859197b0d4e77215d1f0b4a76cb53dfd9a0bee3&quot;
  eth1_data:
    deposit_root: &quot;0xfecc08150b61a8fd00bef193f76e8b08a35b1e230a8fbe5fe8386821042dc30e&quot;
    deposit_count: &quot;241&quot;
    block_hash: &quot;0xffd46f6cca04a453afaaab6759ce73a0883c43146bd59559c0e3547b03104bee&quot;
  block_height: 242
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0x15e5ab79d2e91316abac7981530e445f4c70332f1628d1883a21d17a699c1b4e&quot;
      - &quot;0x3c87bafbdd6e4bd6fd9c9b911859197b0d4e77215d1f0b4a76cb53dfd9a0bee3&quot;
    deposit_root: &quot;0xfecc08150b61a8fd00bef193f76e8b08a35b1e230a8fbe5fe8386821042dc30e&quot;
    deposit_count: 241
    execution_block_hash: &quot;0xffd46f6cca04a453afaaab6759ce73a0883c43146bd59559c0e3547b03104bee&quot;
    execution_block_height: 242
- deposit_data:
    pubkey: &quot;0xa6071c891f8c353b0ed693c039c54f8ceaef1862c23904ecfbd88b3ca9180a52d7c4ce95bb9673e98ba6ac93a2d5b462&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8492293596dd1459367cc4ed401f6b3c2dab0c4c58045157a782a359483588f7fc072c8fab68311956fcecca8dca20ad0208bf6106be93330bb2c8f188924827efbf388ed1196f0a36c57751ba9241f9e888287f28c08f6f466f14ae39b7a471&quot;
  deposit_data_root: &quot;0xfaf043c9b1a28720d15e0878bf714c21ff2f25732db766df36c30f2294edc890&quot;
  eth1_data:
    deposit_root: &quot;0x25d55cb11a780617ff862a96f6a5d28b03553d6ad721b3fd9b2a969516092366&quot;
    deposit_count: &quot;242&quot;
    block_hash: &quot;0xdc1ba0aeca3dc68376239c9dc4291a18b77e5a6e073c2ce216f78cf916b1bfc7&quot;
  block_height: 243
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0x15e5ab79d2e91316abac7981530e445f4c70332f1628d1883a21d17a699c1b4e&quot;
      - &quot;0x6ca839b6db690b690cfcecf7cc14423bb1fd7b32d682e21d2e2ac03494a37935&quot;
    deposit_root: &quot;0x25d55cb11a780617ff862a96f6a5d28b03553d6ad721b3fd9b2a969516092366&quot;
    deposit_count: 242
    execution_block_hash: &quot;0xdc1ba0aeca3dc68376239c9dc4291a18b77e5a6e073c2ce216f78cf916b1bfc7&quot;
    execution_block_height: 243
- deposit_data:
    pubkey: &quot;0xb722d39c1d7d9c5ec39961f903efbf7bfd5faa1a3af41749874b52d9a6ecf554b022beebfd42b5d4bc00ecdc726a1c69&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8cd8f6b02f810e9b408185e8d25e0739f91a10d1091f0af98641b558598e8cb0f447f07dcaa702c40ffd3fd50e2fcb1e13fd81b3e6b5541d2c73facd4b1ee023578075d09356b8428e94cf257ebc725b94c13cf383ca033adb26f458477806f9&quot;
  deposit_data_root: &quot;0x084781b3e9bd75b87361a1f8441b80da9923d7c8668720ad8e5755482ef29649&quot;
  eth1_data:
    deposit_root: &quot;0x5e30bf9c714431e60981eb475a64bf5f497cb20bee164b4c2c77fcf330d5cf1f&quot;
    deposit_count: &quot;243&quot;
    block_hash: &quot;0x650a223ced62d289d54524b7d13cf38a72a713b7d76a950da2127bb06567174f&quot;
  block_height: 244
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0x15e5ab79d2e91316abac7981530e445f4c70332f1628d1883a21d17a699c1b4e&quot;
      - &quot;0x6ca839b6db690b690cfcecf7cc14423bb1fd7b32d682e21d2e2ac03494a37935&quot;
      - &quot;0x084781b3e9bd75b87361a1f8441b80da9923d7c8668720ad8e5755482ef29649&quot;
    deposit_root: &quot;0x5e30bf9c714431e60981eb475a64bf5f497cb20bee164b4c2c77fcf330d5cf1f&quot;
    deposit_count: 243
    execution_block_hash: &quot;0x650a223ced62d289d54524b7d13cf38a72a713b7d76a950da2127bb06567174f&quot;
    execution_block_height: 244
- deposit_data:
    pubkey: &quot;0x98bed18337602301002525627e99e62911e6bc491e2c2bbfa2eef2f4bcf173eb60e493b74e95c3b5256555f20535694e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa30352b10445dccc53569ef6a776814dd6bd35bca75d4960a97108c2ef05e896fc1218863e091e349eafa964df4252cc04aad236601220b9a047fdd8b61cc370514e05c427f83215b19beef3672008bf441e58bc9e848f68617e580d8a3851c3&quot;
  deposit_data_root: &quot;0x714f0a4796ecb56128e81e1fd76733314b4f8d9876254793390161eed47581ad&quot;
  eth1_data:
    deposit_root: &quot;0x58b247bf9a29620b5b3c182f0a579da72ad4126fe2ba57300f6fd58f32aba0e2&quot;
    deposit_count: &quot;244&quot;
    block_hash: &quot;0x84da630cce06cc7ab9def7b0e4ccb64c267d8d2be50f211f991cf5e4e4ce6e5f&quot;
  block_height: 245
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0x15e5ab79d2e91316abac7981530e445f4c70332f1628d1883a21d17a699c1b4e&quot;
      - &quot;0xa46deb2a2056ceaf788d88266b62aab355e7755244c7ea45646a731284b588b7&quot;
    deposit_root: &quot;0x58b247bf9a29620b5b3c182f0a579da72ad4126fe2ba57300f6fd58f32aba0e2&quot;
    deposit_count: 244
    execution_block_hash: &quot;0x84da630cce06cc7ab9def7b0e4ccb64c267d8d2be50f211f991cf5e4e4ce6e5f&quot;
    execution_block_height: 245
- deposit_data:
    pubkey: &quot;0xb499f66668919d5f1d82e55171c5961e78aaa70e0fab3a2ccf14aa402379ac66e05d542060e550d8a1d03796ce703a3c&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb52925ffbd2205903de239cc9abdfba52c6940f45cfc9f8c0d6998c074022c32fefd229d464724fb372a157a0c74bc87015c05f9b331b96b9354a9060a31cb1a92ceab4e91a689e5aa4156c8dbec1785a319cd74d370a3bf86aa56a431033d66&quot;
  deposit_data_root: &quot;0xdab69f68d68d19729a7255e07d59760c7b6ba098132c4d5d5a1c87af8e5ec222&quot;
  eth1_data:
    deposit_root: &quot;0xf1bd510bc2186b7e3cf6246ba45b1a8be2ec957093caa0f825d8d2ee898b11f7&quot;
    deposit_count: &quot;245&quot;
    block_hash: &quot;0x958e63436b683ab4d02c33db4495fcd0dfd5a72b445e3274b9efc508d4d797c7&quot;
  block_height: 246
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0x15e5ab79d2e91316abac7981530e445f4c70332f1628d1883a21d17a699c1b4e&quot;
      - &quot;0xa46deb2a2056ceaf788d88266b62aab355e7755244c7ea45646a731284b588b7&quot;
      - &quot;0xdab69f68d68d19729a7255e07d59760c7b6ba098132c4d5d5a1c87af8e5ec222&quot;
    deposit_root: &quot;0xf1bd510bc2186b7e3cf6246ba45b1a8be2ec957093caa0f825d8d2ee898b11f7&quot;
    deposit_count: 245
    execution_block_hash: &quot;0x958e63436b683ab4d02c33db4495fcd0dfd5a72b445e3274b9efc508d4d797c7&quot;
    execution_block_height: 246
- deposit_data:
    pubkey: &quot;0x92c237d7fb491bcf70aa4e50e71b305bcf71bf5a438b0e08f03fc4f74d5c3c9b8c823049e314d15f8266179b1a90841d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa2bb7c6a1ee2ec8368539cccfb5b2a8588e5e479fda223410cd15341dd5c865dd22695a2a0ef27757b2545adf353df0e0b51f9c9c12b19a7fd0e22cacc81c28a0fad805cd19feb808be5ca4867eabee207e2f38e089b6097f66809b04cd41797&quot;
  deposit_data_root: &quot;0x1cc0cbc5cf5550036124427fca2b43440d4c574e10da612c1b6c583a6febe147&quot;
  eth1_data:
    deposit_root: &quot;0x4ba339c19953b83d57a0600cc2a325b4ab96d46eecbd4b6b483d42b6c3035122&quot;
    deposit_count: &quot;246&quot;
    block_hash: &quot;0x4194ca1e0c55ccaa492a55535bebacaa185efcc8ab9f5fb8ea60ffd90461d3c2&quot;
  block_height: 247
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0x15e5ab79d2e91316abac7981530e445f4c70332f1628d1883a21d17a699c1b4e&quot;
      - &quot;0xa46deb2a2056ceaf788d88266b62aab355e7755244c7ea45646a731284b588b7&quot;
      - &quot;0xfe1c7788bf7f661ff91503ec1352ef2ba4d8ad3653fe69110da96218c90b32ab&quot;
    deposit_root: &quot;0x4ba339c19953b83d57a0600cc2a325b4ab96d46eecbd4b6b483d42b6c3035122&quot;
    deposit_count: 246
    execution_block_hash: &quot;0x4194ca1e0c55ccaa492a55535bebacaa185efcc8ab9f5fb8ea60ffd90461d3c2&quot;
    execution_block_height: 247
- deposit_data:
    pubkey: &quot;0xa1f2eb8596281b7e85285bcee8a4156140e069c6f50c02a0dd3b0f40ed62b8e15e7b9c40f6755496e13a94d91faaa194&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa3b72e3ec51a30a080e36fb0ad1c350a6f4df753de841d2626581c2f3573b3ceab177708cfe9a64d3c6d243a26df1e6700b014c3f09636bd0911addd3db4be6b8893568c0e1e92b88badec7a7c86e0c0921cb07ad48e3c7f6c27a6c6cb1ea8af&quot;
  deposit_data_root: &quot;0x571c10a7c40e7c4a5f15db4ff249f1e1b90fc1ed392d6dc2c359de9c887950f9&quot;
  eth1_data:
    deposit_root: &quot;0xc8f68085a6d6b9ea9ab9389235e301c66d605c6a1648e659e512d10a340f6dad&quot;
    deposit_count: &quot;247&quot;
    block_hash: &quot;0x86ca50c675d6f26df298aec00b900a9693d04a765494714b8a2c6da02d310338&quot;
  block_height: 248
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0x15e5ab79d2e91316abac7981530e445f4c70332f1628d1883a21d17a699c1b4e&quot;
      - &quot;0xa46deb2a2056ceaf788d88266b62aab355e7755244c7ea45646a731284b588b7&quot;
      - &quot;0xfe1c7788bf7f661ff91503ec1352ef2ba4d8ad3653fe69110da96218c90b32ab&quot;
      - &quot;0x571c10a7c40e7c4a5f15db4ff249f1e1b90fc1ed392d6dc2c359de9c887950f9&quot;
    deposit_root: &quot;0xc8f68085a6d6b9ea9ab9389235e301c66d605c6a1648e659e512d10a340f6dad&quot;
    deposit_count: 247
    execution_block_hash: &quot;0x86ca50c675d6f26df298aec00b900a9693d04a765494714b8a2c6da02d310338&quot;
    execution_block_height: 248
- deposit_data:
    pubkey: &quot;0x8f4d945fafc936414122945190a1983192259705205fa3e92b72443a93183eb140ad527d4b1449507a18cd64764c89b8&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x89f9fb93f365aa814e9939d47d12e479a941b124428a3ea45ff751b336fbfc4e918be34e1f8e1006f011a1182f3fa4530ffd887727627586a9d090ba05c5f035a69fe7da7f3747d9018eff61f281ebcef266db93e508b22273173d7e59337234&quot;
  deposit_data_root: &quot;0xd752ab6ab4c095111b65b97cef47817f4ce89cf1025672ca33053c1c5cc8e856&quot;
  eth1_data:
    deposit_root: &quot;0x9888c051a7c8320f413b98a66f0f4d86d2161c649550a898f3a05d547072e2ef&quot;
    deposit_count: &quot;248&quot;
    block_hash: &quot;0xab019baaf509e52a456129c7b9628360234c5c99d73059d5f3a6f1c320affeec&quot;
  block_height: 249
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0x15e5ab79d2e91316abac7981530e445f4c70332f1628d1883a21d17a699c1b4e&quot;
      - &quot;0x151d5a637c3241cca69bf3658d39f77db74646866a4dc1a1d762fbe89eb8f459&quot;
    deposit_root: &quot;0x9888c051a7c8320f413b98a66f0f4d86d2161c649550a898f3a05d547072e2ef&quot;
    deposit_count: 248
    execution_block_hash: &quot;0xab019baaf509e52a456129c7b9628360234c5c99d73059d5f3a6f1c320affeec&quot;
    execution_block_height: 249
- deposit_data:
    pubkey: &quot;0x98a8e7af1994e3d8f383dc4ee6d32a01077694ec93ecfd7ffbc5cd9448938a6c6d35cbbbe8e01a49fa4782f389757b06&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x96b654ae3c1bbef1c62c4dbb5ff4a174dd66d699660b3fddb0393dc3f8b675611a8f7c92c9d64a55c70c59c81ec61d9c0630b6609ee9185b075931251f5bfc63be9b5741cd1bff31d08bf63232ea95a3652ddf2012932c617741afb9417c1797&quot;
  deposit_data_root: &quot;0x1b3ff046f35984553c7bc5e78b4ef9633fbd4955e81438f836224ad1a35537fd&quot;
  eth1_data:
    deposit_root: &quot;0xa1477aaa9d366844c18a57e9c0f5281dbc35d8a27c7178e36a78943f2af1f4ce&quot;
    deposit_count: &quot;249&quot;
    block_hash: &quot;0xefe08745ea4a98e988389f4896dec09001efcd92fde1b157958b2a7b5bea1e1f&quot;
  block_height: 250
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0x15e5ab79d2e91316abac7981530e445f4c70332f1628d1883a21d17a699c1b4e&quot;
      - &quot;0x151d5a637c3241cca69bf3658d39f77db74646866a4dc1a1d762fbe89eb8f459&quot;
      - &quot;0x1b3ff046f35984553c7bc5e78b4ef9633fbd4955e81438f836224ad1a35537fd&quot;
    deposit_root: &quot;0xa1477aaa9d366844c18a57e9c0f5281dbc35d8a27c7178e36a78943f2af1f4ce&quot;
    deposit_count: 249
    execution_block_hash: &quot;0xefe08745ea4a98e988389f4896dec09001efcd92fde1b157958b2a7b5bea1e1f&quot;
    execution_block_height: 250
- deposit_data:
    pubkey: &quot;0xa7c051843950c482ea373ca3aa30e523911ccfe061c681b16fb8a35ec6e4ff0ada5a25fb2ae70433b18913652cc3c181&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x98eebdf73162c70581f7325614bb7110c6cba9351ca1dd4e275557a9cf71ac8fcd64071791780806cee2e37c18f98e2313e8adfec420bfbf20b35a79cfad2eddcd664a557b3b566437f567f1a5a03deeb48b0c0ce31ba57531f594ca8317fe2f&quot;
  deposit_data_root: &quot;0x357d15b4cce193ddfc397cdd46ab0a749f8a579ab81cd19f1100e041b1147c57&quot;
  eth1_data:
    deposit_root: &quot;0x11c2be42ec7670fab1675225953d5079ce0571d96393b911904526f6be98cf25&quot;
    deposit_count: &quot;250&quot;
    block_hash: &quot;0x65b114ab411f03138a6610b8edf979ba983e536afb438e62fb80ffffbc3cf124&quot;
  block_height: 251
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0x15e5ab79d2e91316abac7981530e445f4c70332f1628d1883a21d17a699c1b4e&quot;
      - &quot;0x151d5a637c3241cca69bf3658d39f77db74646866a4dc1a1d762fbe89eb8f459&quot;
      - &quot;0xcf504f082f480bc2de32cc4c299b0fd96b1ed6919af3b090f0a9f3f3ecc10430&quot;
    deposit_root: &quot;0x11c2be42ec7670fab1675225953d5079ce0571d96393b911904526f6be98cf25&quot;
    deposit_count: 250
    execution_block_hash: &quot;0x65b114ab411f03138a6610b8edf979ba983e536afb438e62fb80ffffbc3cf124&quot;
    execution_block_height: 251
- deposit_data:
    pubkey: &quot;0x8f14a40f502a87214891c922345fc2abc6795c28d72f9deb7ebffd7b805888222f7b1d479db1142ed013902987394cad&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x85f4239f73421ff5d28f31481729632e20bf4ed4b3ea0a91961dec198922dc1be61be0623b85365dd6db9cec094dad9217683da190c4be92b5d1bb00491314472e3a412f13d651c4c98f054219e621538c9465cd42fd2851950e0ac9a42e62b0&quot;
  deposit_data_root: &quot;0x5be2cc49961bb2f24b8e89e5e9bacc33efb9cb9f9a455e1bb91fff7bc5b6656a&quot;
  eth1_data:
    deposit_root: &quot;0x0df7d0d38d74a5cb89be95258e7c60ce0b9200342553536b064f33ea923255df&quot;
    deposit_count: &quot;251&quot;
    block_hash: &quot;0xb243d9ace275e844a2335d262010f8b3cf19d045bc930d89bb6e6ec738865cb6&quot;
  block_height: 252
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0x15e5ab79d2e91316abac7981530e445f4c70332f1628d1883a21d17a699c1b4e&quot;
      - &quot;0x151d5a637c3241cca69bf3658d39f77db74646866a4dc1a1d762fbe89eb8f459&quot;
      - &quot;0xcf504f082f480bc2de32cc4c299b0fd96b1ed6919af3b090f0a9f3f3ecc10430&quot;
      - &quot;0x5be2cc49961bb2f24b8e89e5e9bacc33efb9cb9f9a455e1bb91fff7bc5b6656a&quot;
    deposit_root: &quot;0x0df7d0d38d74a5cb89be95258e7c60ce0b9200342553536b064f33ea923255df&quot;
    deposit_count: 251
    execution_block_hash: &quot;0xb243d9ace275e844a2335d262010f8b3cf19d045bc930d89bb6e6ec738865cb6&quot;
    execution_block_height: 252
- deposit_data:
    pubkey: &quot;0x8e486d8c9ca07b6c4dc1181161ab52508b70980e9af31c97286b55be3df3701d73891bf0aecc6eb7d2e028572bb5c25a&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa87d84736b8a674718e17bcabfd512e8a6ccb52eaf11776e2aaec8cb0d9bf91fa59b46b3c21a0023443a9911ba1f6e9f192e18b88ea8cc96362a537f98bac4de9883e4a8b46ce99f8c5407b4fa748a9bd6c438ea076b8eff66a34c43243f1030&quot;
  deposit_data_root: &quot;0x94423ecf41a112308585b194e910a68273a90cb12434e82d0cd936a3b92309c9&quot;
  eth1_data:
    deposit_root: &quot;0xabdddf0fbff2f71cace266b85d33a05b0621daae752c693fe9027725d863a1b8&quot;
    deposit_count: &quot;252&quot;
    block_hash: &quot;0x8c746ea8ee851c0ce8552221531374c1a73ca48d07c2da85ad95328836cde732&quot;
  block_height: 253
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0x15e5ab79d2e91316abac7981530e445f4c70332f1628d1883a21d17a699c1b4e&quot;
      - &quot;0x151d5a637c3241cca69bf3658d39f77db74646866a4dc1a1d762fbe89eb8f459&quot;
      - &quot;0x5ba7e2c0ce36932281840d77f2cff6b2fc9b10b24953346e039e8d0576ba01d8&quot;
    deposit_root: &quot;0xabdddf0fbff2f71cace266b85d33a05b0621daae752c693fe9027725d863a1b8&quot;
    deposit_count: 252
    execution_block_hash: &quot;0x8c746ea8ee851c0ce8552221531374c1a73ca48d07c2da85ad95328836cde732&quot;
    execution_block_height: 253
- deposit_data:
    pubkey: &quot;0x91402ee72dd351a735017f11da3176ae5fce3e92369972d0eee22a45d1cc2badd77f627c4a0a9d9c480d65464442599d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa1eb19f9f0c9fe4962b82a001fe8c99c3ecf7b2133202c655275af9ba4581d7715abafb9d9835340a14c52ee7a1a449c0ba1d35ad7bb6ab37fe54d05c644a577c5b86ef3e036c46c0c4ccb3829205e0b4c717d2392abf2ac92e770747643c26a&quot;
  deposit_data_root: &quot;0x00c52950b4b8050d147aeca91703761b297e5d91ab496ac1161f1fef79f7528e&quot;
  eth1_data:
    deposit_root: &quot;0x39b19f70b06e4cdaa2c3e1c87ef0b8039022ac99b00d68deca929ae4f7ba95f6&quot;
    deposit_count: &quot;253&quot;
    block_hash: &quot;0xc0d6735edb092ab85379457c91496c754307a70cab6e50494f858ee371eb649b&quot;
  block_height: 254
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0x15e5ab79d2e91316abac7981530e445f4c70332f1628d1883a21d17a699c1b4e&quot;
      - &quot;0x151d5a637c3241cca69bf3658d39f77db74646866a4dc1a1d762fbe89eb8f459&quot;
      - &quot;0x5ba7e2c0ce36932281840d77f2cff6b2fc9b10b24953346e039e8d0576ba01d8&quot;
      - &quot;0x00c52950b4b8050d147aeca91703761b297e5d91ab496ac1161f1fef79f7528e&quot;
    deposit_root: &quot;0x39b19f70b06e4cdaa2c3e1c87ef0b8039022ac99b00d68deca929ae4f7ba95f6&quot;
    deposit_count: 253
    execution_block_hash: &quot;0xc0d6735edb092ab85379457c91496c754307a70cab6e50494f858ee371eb649b&quot;
    execution_block_height: 254
- deposit_data:
    pubkey: &quot;0xaa5b90007d36de7c57235756d39aac060ee48e8a910f0a0c815e71414a0d53e7b0659242079253fdeb32ad18ab90beb9&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x85e04b0dd29327c3b6509673add484f5236e2fc68e0d3411f7ac5070b5d171b8800cf366a8cc632d9e9b9ea49bad527f0105dc4600d55dff610464d15d70c1103218824db85b2c13a898279e777f843cb3c32afea2ab7dd46494c942fc857da2&quot;
  deposit_data_root: &quot;0xeec4762f004c245237202597a1172ba2594a24318eab15dc61519909d761035d&quot;
  eth1_data:
    deposit_root: &quot;0xcb2db903b62421b1add0e3747dff29b0eaa2046f7e8aea0c22777804c1931533&quot;
    deposit_count: &quot;254&quot;
    block_hash: &quot;0xb3df67d8050a51998dde8c9c9a2ebb92c608018a2c32b1bb4835769bc7303160&quot;
  block_height: 255
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0x15e5ab79d2e91316abac7981530e445f4c70332f1628d1883a21d17a699c1b4e&quot;
      - &quot;0x151d5a637c3241cca69bf3658d39f77db74646866a4dc1a1d762fbe89eb8f459&quot;
      - &quot;0x5ba7e2c0ce36932281840d77f2cff6b2fc9b10b24953346e039e8d0576ba01d8&quot;
      - &quot;0xc9bd7dd686e17ced16ded792dbb1565f93d9d01b2e551b237d8674891756d761&quot;
    deposit_root: &quot;0xcb2db903b62421b1add0e3747dff29b0eaa2046f7e8aea0c22777804c1931533&quot;
    deposit_count: 254
    execution_block_hash: &quot;0xb3df67d8050a51998dde8c9c9a2ebb92c608018a2c32b1bb4835769bc7303160&quot;
    execution_block_height: 255
- deposit_data:
    pubkey: &quot;0x851faec0a50c3df9918d1ab44fe7f63f8105d671d8fb83f3a59d291e6d4dc86cf47a6e9402973bfbd7db535b3dc4350b&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xabf53104df47484b8c876216dec49ae4c6805c0c7c866fb3794f0699db316ef4e60ed588cd3a2865217db953a640fa61118325f454eb4d2768f2372bc8325b5a979a722faee2bd818d9bf944c89abbefc3328441ecdcbcab2a9f0830bad57a3b&quot;
  deposit_data_root: &quot;0x3fe14e2e6126bae3261e24ff9119ea5b74664a19426da0d091193ae3bb736dd5&quot;
  eth1_data:
    deposit_root: &quot;0xad9929ce3da3cccb228d8f69211d8493147a6df93daed02e410bcbdecbeaca60&quot;
    deposit_count: &quot;255&quot;
    block_hash: &quot;0xff6935719c772b51352c991341ff30606fee102d3dfd07859a2930212e75800e&quot;
  block_height: 256
  snapshot:
    finalized:
      - &quot;0x5424209b0511223b880af7362d8fe72bc0f268f4aa37dbcced5b872a30a1265e&quot;
      - &quot;0xbbe623353e1418ef9492c6e1ca72e9a73bc4d28b00d17bae94476c70ae774043&quot;
      - &quot;0x8b839672af192e30144c2c46a2d14842b4620d58405e9094689262016f3b1ff7&quot;
      - &quot;0x15e5ab79d2e91316abac7981530e445f4c70332f1628d1883a21d17a699c1b4e&quot;
      - &quot;0x151d5a637c3241cca69bf3658d39f77db74646866a4dc1a1d762fbe89eb8f459&quot;
      - &quot;0x5ba7e2c0ce36932281840d77f2cff6b2fc9b10b24953346e039e8d0576ba01d8&quot;
      - &quot;0xc9bd7dd686e17ced16ded792dbb1565f93d9d01b2e551b237d8674891756d761&quot;
      - &quot;0x3fe14e2e6126bae3261e24ff9119ea5b74664a19426da0d091193ae3bb736dd5&quot;
    deposit_root: &quot;0xad9929ce3da3cccb228d8f69211d8493147a6df93daed02e410bcbdecbeaca60&quot;
    deposit_count: 255
    execution_block_hash: &quot;0xff6935719c772b51352c991341ff30606fee102d3dfd07859a2930212e75800e&quot;
    execution_block_height: 256
- deposit_data:
    pubkey: &quot;0x933dc2f8d407d4f85a1d54953ac47a89c19808eca0d38b0ec85b376ce17c3ef1edebb518a4dce8e976155cb6561a849f&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9694a8b0268e018870eb146f9d2a4dda7b9c341b4c82a73d950101d534f167fc0c8d902f37f9589c056108b1b6a3d41a0d815100b4db1232c4393e5f7bdbb23925aa043d68f95ba7b4edd2d4e58465ec63aadc831f99eb06278e067fc68325c5&quot;
  deposit_data_root: &quot;0xb71c9023acf8ceebefff85ec63ced2d0a535e3af465941895e0679b0fc692f0a&quot;
  eth1_data:
    deposit_root: &quot;0xd49c9ff7d98a8d5cdab9ddf57c558dc9d203d282d7ec7faa5c7d11aae81b790f&quot;
    deposit_count: &quot;256&quot;
    block_hash: &quot;0x1fe7203f9539f6116aabb762433e3ec9692de44bdb1342b1b1653afc271b04b5&quot;
  block_height: 257
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
    deposit_root: &quot;0xd49c9ff7d98a8d5cdab9ddf57c558dc9d203d282d7ec7faa5c7d11aae81b790f&quot;
    deposit_count: 256
    execution_block_hash: &quot;0x1fe7203f9539f6116aabb762433e3ec9692de44bdb1342b1b1653afc271b04b5&quot;
    execution_block_height: 257
- deposit_data:
    pubkey: &quot;0x8f7069f51912347df8b721903bd9340ff49e9d436239ea0f4f176e360c4a91aede7657037ae00dcb08a9d7abe9b48d5a&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x833313916a5da51c5ba85ecb314c687384faf62db7872fd000ca32a0ee7f4778bb2e5f7a5f4139aac884a7f4a0a1c40808a766bd7acb02c5ee4d6ead05a622b6d20a818649ed08c41afe600e1710f1b5532aee603618c828ee50cc62dc51f964&quot;
  deposit_data_root: &quot;0xb7292e597a4316db41b1ee81280941feb78554bd77861d9b4e4ee85ceb83f536&quot;
  eth1_data:
    deposit_root: &quot;0xd254aeef26718bb674401e75886471ce4a088120fab90318c6e55d063aa04a3c&quot;
    deposit_count: &quot;257&quot;
    block_hash: &quot;0x1df4e3eafb6484a050b5168586d648e4191d90ecdf846800fd0b41ddde11edbc&quot;
  block_height: 258
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xb7292e597a4316db41b1ee81280941feb78554bd77861d9b4e4ee85ceb83f536&quot;
    deposit_root: &quot;0xd254aeef26718bb674401e75886471ce4a088120fab90318c6e55d063aa04a3c&quot;
    deposit_count: 257
    execution_block_hash: &quot;0x1df4e3eafb6484a050b5168586d648e4191d90ecdf846800fd0b41ddde11edbc&quot;
    execution_block_height: 258
- deposit_data:
    pubkey: &quot;0xb876db47bf1d1868b3a39cdba4171adde47eae91b3631dcb5c59d28cb100ecda604a446ffcb000448c462d72526ebdf1&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb7302e880887ee702f55cc3fbfa2a8ec3b422317eda123538723588e7119d6111d80457a3805912bd4f07f16cb71c32c09a2bf0ade7ca11fa2303136bcd493c8b8a7c7fff3b94be38684b019cb515d4759574323015b9d53d0c92ce374a5311d&quot;
  deposit_data_root: &quot;0x40f31b70761cdda3e491f945fcfada69d0d985503e705ff9e0db0fde1d58c7fc&quot;
  eth1_data:
    deposit_root: &quot;0xd5c029480bf22b310991b6964481ff2e3e156e9d9a39556026ef809cf282d77c&quot;
    deposit_count: &quot;258&quot;
    block_hash: &quot;0xbc87b56c9955290b90555dfdfcfe36d95abf388b957b8b004ab7aa8682a48c26&quot;
  block_height: 259
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x33caef79ba14b442d517fa8bc4c617b1a5c595ab103f2baff90a65a7f03c8564&quot;
    deposit_root: &quot;0xd5c029480bf22b310991b6964481ff2e3e156e9d9a39556026ef809cf282d77c&quot;
    deposit_count: 258
    execution_block_hash: &quot;0xbc87b56c9955290b90555dfdfcfe36d95abf388b957b8b004ab7aa8682a48c26&quot;
    execution_block_height: 259
- deposit_data:
    pubkey: &quot;0x9666598b3eaade229b7b255866d279009ac0b42dc55cbec207f3842d51501e2fcd318ce7d2fc40a766382703c8a0ef00&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x960b98ed5f4aec48beaf813e61048411a345de0d5b99593d5017f7a18651567b7d3038e4665fd186c868a4b4b8da865f175ef0158fba21bdf10c0890cd1fa32dc3105da9f295925b96d090516bace0c6e9a168206a21a11b30f8fefce22fbb5d&quot;
  deposit_data_root: &quot;0xc0a4d26a15ce052fbb2873df1b178b41192e4cdeb45895acf94f55d5d58636c9&quot;
  eth1_data:
    deposit_root: &quot;0xda795c832687a92b18a304a4a68190b021082edac866a12e283b6cc4c3eee27e&quot;
    deposit_count: &quot;259&quot;
    block_hash: &quot;0x2ec63ba8ef1e86b8428bb223e6aaed2e3193f59a65de1ddaaeb3cbd96653530d&quot;
  block_height: 260
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x33caef79ba14b442d517fa8bc4c617b1a5c595ab103f2baff90a65a7f03c8564&quot;
      - &quot;0xc0a4d26a15ce052fbb2873df1b178b41192e4cdeb45895acf94f55d5d58636c9&quot;
    deposit_root: &quot;0xda795c832687a92b18a304a4a68190b021082edac866a12e283b6cc4c3eee27e&quot;
    deposit_count: 259
    execution_block_hash: &quot;0x2ec63ba8ef1e86b8428bb223e6aaed2e3193f59a65de1ddaaeb3cbd96653530d&quot;
    execution_block_height: 260
- deposit_data:
    pubkey: &quot;0xb2b4c1b1777970826b6683ceed5b72da7bec1f6f7cdfae6a599ae0d0d6d912098678327ee31fe383fc2b95bfed48bfce&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa0495982b6c281a33c67883658f6c32a94268ede93853331bae3e492f71ac4514f05b0e89ffddb1e1a8dff4b83dc807219c69ac11d5a2515c845023c566dca7dbcde3ca08855dae961242680efe3f84de27fd04ee3d8c580bacd625ce1618f7a&quot;
  deposit_data_root: &quot;0x6944628944cbac12207257df3a7d14936c9bc8f267eec1e24d18543b00b9c413&quot;
  eth1_data:
    deposit_root: &quot;0x7db45a47b3b9ef4cf211c695fe5682e6e79078b72f4b758d7db497ef4f3c7abd&quot;
    deposit_count: &quot;260&quot;
    block_hash: &quot;0x2d162a08fa97029565b3f57c18af38429a5a4a3f7deefde7b843f481fb7fd0a5&quot;
  block_height: 261
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xe4b758cad7a082639814a7aae047e94921d416986d98b6dfcbc234966bc973ef&quot;
    deposit_root: &quot;0x7db45a47b3b9ef4cf211c695fe5682e6e79078b72f4b758d7db497ef4f3c7abd&quot;
    deposit_count: 260
    execution_block_hash: &quot;0x2d162a08fa97029565b3f57c18af38429a5a4a3f7deefde7b843f481fb7fd0a5&quot;
    execution_block_height: 261
- deposit_data:
    pubkey: &quot;0x91cecc34498496a68dc7630a6184b1cd7b977772a94d7d704c64284cdc14aa3f4d7c6eadb3bf62eda1a43f2f8d547a2d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa2e8b32322fbe08e071a3100c7f55efa12fedb60e61d10adf35599ad6dff551e7cb22f16882c76e5a5fc03cfbb7cac2916770030f9049ab5075e8371745bfeb58d944bb0cfd9ec44e29e57ab441f96fad3b71a42ed1a3f7a8f13107a5e09ca8f&quot;
  deposit_data_root: &quot;0x709db664502b7eb538adc5890972def651e1e2c0f4fed2b14b473022f3676bf5&quot;
  eth1_data:
    deposit_root: &quot;0x36baa65b71d95dada8a8da1cb67eb6656fa616b6645db7870b07060afdfcbdb4&quot;
    deposit_count: &quot;261&quot;
    block_hash: &quot;0x771faf677259330b1949d0d57781f6ae7745117adb1f2c748b42ba20ec3c599d&quot;
  block_height: 262
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xe4b758cad7a082639814a7aae047e94921d416986d98b6dfcbc234966bc973ef&quot;
      - &quot;0x709db664502b7eb538adc5890972def651e1e2c0f4fed2b14b473022f3676bf5&quot;
    deposit_root: &quot;0x36baa65b71d95dada8a8da1cb67eb6656fa616b6645db7870b07060afdfcbdb4&quot;
    deposit_count: 261
    execution_block_hash: &quot;0x771faf677259330b1949d0d57781f6ae7745117adb1f2c748b42ba20ec3c599d&quot;
    execution_block_height: 262
- deposit_data:
    pubkey: &quot;0x89dc8480e9d48c7e5a39c3ced17e65170f56f86a96e4bb131e88c3d6eda3daa65265df5445e0ce52090cf34d7fd1116e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x945d9ac700cadcbad052484acb2eb9702915bbcfa44222866ece07891edd00d8ce873f17704412e338f39893af82ce54115bd1e184b11cdfa51937164a1d3576f359c14a903ef669a016cc5398e9e5c6af03730ea0534a737f8457c237141f36&quot;
  deposit_data_root: &quot;0x70c4d026dc4ce6566e02ddb3085517df6d5c742910fe7a36500d76e7badf82b3&quot;
  eth1_data:
    deposit_root: &quot;0x05fb7d7e57be47dd87666d6198c4e197ae9fd0922fb4100535592ac7e0900bab&quot;
    deposit_count: &quot;262&quot;
    block_hash: &quot;0x132a1b9db503b80713fc5a34717cd51069fa6f145340ffee8c0b283c8c2e0606&quot;
  block_height: 263
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xe4b758cad7a082639814a7aae047e94921d416986d98b6dfcbc234966bc973ef&quot;
      - &quot;0x6cf83a85c4c666e9efb82ff97d8cf8fd2d6f4442b0c6c7e029dcf8ae80c981df&quot;
    deposit_root: &quot;0x05fb7d7e57be47dd87666d6198c4e197ae9fd0922fb4100535592ac7e0900bab&quot;
    deposit_count: 262
    execution_block_hash: &quot;0x132a1b9db503b80713fc5a34717cd51069fa6f145340ffee8c0b283c8c2e0606&quot;
    execution_block_height: 263
- deposit_data:
    pubkey: &quot;0x8219db7b86441850836ae4e27a030e8378e594e5f1d7ee08dac7bc054653d178e6949476887c83a20a213b2bf39e16f7&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8c53a5ea1061f892c20cf93c1b97c42250908b3e299700090713f36a45421c619b06570d18e2b96168e71dcaafb820bd17331ed302480153fb48a685d679c829ea12e7c93ee5999aa0812ba19da8b8c60899b980401fb17312ae9db58046ae20&quot;
  deposit_data_root: &quot;0x819ccfe405e7220a1d9c053a8676a88332980aef5215f5076f1a3f5033235532&quot;
  eth1_data:
    deposit_root: &quot;0xcca4cb084ab65bb8629ae4dcc8b2fcbe56db2cae8859e206c4da24a4014d139a&quot;
    deposit_count: &quot;263&quot;
    block_hash: &quot;0x27aa5166ec5f9d13e6be7009abc9114701756eb96a5a9110ca40a3e593b0fc27&quot;
  block_height: 264
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xe4b758cad7a082639814a7aae047e94921d416986d98b6dfcbc234966bc973ef&quot;
      - &quot;0x6cf83a85c4c666e9efb82ff97d8cf8fd2d6f4442b0c6c7e029dcf8ae80c981df&quot;
      - &quot;0x819ccfe405e7220a1d9c053a8676a88332980aef5215f5076f1a3f5033235532&quot;
    deposit_root: &quot;0xcca4cb084ab65bb8629ae4dcc8b2fcbe56db2cae8859e206c4da24a4014d139a&quot;
    deposit_count: 263
    execution_block_hash: &quot;0x27aa5166ec5f9d13e6be7009abc9114701756eb96a5a9110ca40a3e593b0fc27&quot;
    execution_block_height: 264
- deposit_data:
    pubkey: &quot;0xb9ea48794c02725e69d9f6435382b31b3e975de5ead999a09e13746e0ae5a63115af3a3043cd71ebc94c9b051b5b595e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8964f0aaa92e1cd2a2e0df07b02766725afe98d100e863fa5364feaaec05c4159eb6efd5d9409d47ab037a5fdc41ba5300ddd8f1626f81b384a6a3793a70a5bcc8c4361c19540bf923cf6f2f5058832f8c188fbff56be3141d24fb9abd829561&quot;
  deposit_data_root: &quot;0xca07d9e3d7bab36f22f9362f73c6302b8c8fc9c41ee856fb2c0fde28702d6672&quot;
  eth1_data:
    deposit_root: &quot;0xf051452baf67b48585468b8af81fea65efe163d4752bc57fe502dedaebc9595a&quot;
    deposit_count: &quot;264&quot;
    block_hash: &quot;0x7c9c165d2d0ad76293cb31edc3195d7de80f5cff9d5ba5bbd9bf0f384dff028e&quot;
  block_height: 265
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xa175806ecd8f45f5b8a87219a9c345e9e612bcdfc850bf0b51c2b6a60813d7e3&quot;
    deposit_root: &quot;0xf051452baf67b48585468b8af81fea65efe163d4752bc57fe502dedaebc9595a&quot;
    deposit_count: 264
    execution_block_hash: &quot;0x7c9c165d2d0ad76293cb31edc3195d7de80f5cff9d5ba5bbd9bf0f384dff028e&quot;
    execution_block_height: 265
- deposit_data:
    pubkey: &quot;0xadae379b50e15e5f80810abfc544eb28e26301438cfaf8a8a5569f9bfd76c4e653d0da710bb5d34687d47669f6999257&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa56c12741c2b28f868708a31c9cde178d724fc2da24acc2538f54068937fb2d7e76cd4bef53818af4ab71908f3feeb0d17527506fed49643fab936ee040061ec66bd43ae9dc1e414d9ff03f7392a9d26daadcc789117c2e66596c2235fd98f8b&quot;
  deposit_data_root: &quot;0x6449a8db47ed59b97b28d2cdc174f12232041fc3231f388d48cc5ed141ccd2a7&quot;
  eth1_data:
    deposit_root: &quot;0xe077d704ae5725c0d46ff39053c1ae7e15b456333bf520cefdef620ac331c134&quot;
    deposit_count: &quot;265&quot;
    block_hash: &quot;0xeb71722b0fe110a64ecccdb9ecba95d7fb7b7c832086cd5bc67e25196be9232f&quot;
  block_height: 266
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xa175806ecd8f45f5b8a87219a9c345e9e612bcdfc850bf0b51c2b6a60813d7e3&quot;
      - &quot;0x6449a8db47ed59b97b28d2cdc174f12232041fc3231f388d48cc5ed141ccd2a7&quot;
    deposit_root: &quot;0xe077d704ae5725c0d46ff39053c1ae7e15b456333bf520cefdef620ac331c134&quot;
    deposit_count: 265
    execution_block_hash: &quot;0xeb71722b0fe110a64ecccdb9ecba95d7fb7b7c832086cd5bc67e25196be9232f&quot;
    execution_block_height: 266
- deposit_data:
    pubkey: &quot;0xb451fc2c4236ca2393853980019f5da0e5f7d93df90bab1ae34ddb583d0ce3cdece25f23bc1736e065a1f2af1ee2bd34&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x93bcb192ee34cf2cb34310583c6ed82b12baa1388f5e85d3e74ef7c9dff413f69f00eff132a686eb786f33bd918fc8870ee0337447202ff82024b20ac35bcd931c34869d33f9e594da910891722146b65e3858be3f6142d1ddafcff50f159b95&quot;
  deposit_data_root: &quot;0xf6e781e7f4285fb05464464c41580de16dcd370ae346a5462bb5791d38808f89&quot;
  eth1_data:
    deposit_root: &quot;0x91a3cef7fd152d3aab06e1f156a428c7f3b19697a7bf32bcbf076c37b4379230&quot;
    deposit_count: &quot;266&quot;
    block_hash: &quot;0xb87c760b0c73bb51052f5a77555e27d38ec417e21af5851664153cc71ea1b7f2&quot;
  block_height: 267
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xa175806ecd8f45f5b8a87219a9c345e9e612bcdfc850bf0b51c2b6a60813d7e3&quot;
      - &quot;0x48170ce125065a69a3020c11a7f1aa34ecfaf772a3a13be6737bcba5157f2553&quot;
    deposit_root: &quot;0x91a3cef7fd152d3aab06e1f156a428c7f3b19697a7bf32bcbf076c37b4379230&quot;
    deposit_count: 266
    execution_block_hash: &quot;0xb87c760b0c73bb51052f5a77555e27d38ec417e21af5851664153cc71ea1b7f2&quot;
    execution_block_height: 267
- deposit_data:
    pubkey: &quot;0xb8c6b853d7f3766c881f4eb0c9986b800188b9f9ab40a492d49e64e8c1e98cefc27ecfe225ff9d5781c0193bca2f77e3&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xab4f31e234441c6eb8fc1f41628ff056226de0b0b3016bb48e2d02eb41ae39f7774bf6c6bf7f8e5088504d962e2045fb0acae329fb2e80eea51f332b76cb2f1d08339b6c230c6ca47b4837f5ebed0c087b51c0c29154e5c4e0b587a0a304cb03&quot;
  deposit_data_root: &quot;0x1e826f811c943eec59894f7b90ff11deefdcc1449ee3dd9186a01e14e07f6c15&quot;
  eth1_data:
    deposit_root: &quot;0x480831312704cf1ebb18ce99d3d5d14aee83c31dee4a7768dc84b8f44a8f815e&quot;
    deposit_count: &quot;267&quot;
    block_hash: &quot;0xf65f73d8ffe1df07acfa02b5297f43c4652c159a3cfcdd3bb9f3f1bac7d7ce98&quot;
  block_height: 268
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xa175806ecd8f45f5b8a87219a9c345e9e612bcdfc850bf0b51c2b6a60813d7e3&quot;
      - &quot;0x48170ce125065a69a3020c11a7f1aa34ecfaf772a3a13be6737bcba5157f2553&quot;
      - &quot;0x1e826f811c943eec59894f7b90ff11deefdcc1449ee3dd9186a01e14e07f6c15&quot;
    deposit_root: &quot;0x480831312704cf1ebb18ce99d3d5d14aee83c31dee4a7768dc84b8f44a8f815e&quot;
    deposit_count: 267
    execution_block_hash: &quot;0xf65f73d8ffe1df07acfa02b5297f43c4652c159a3cfcdd3bb9f3f1bac7d7ce98&quot;
    execution_block_height: 268
- deposit_data:
    pubkey: &quot;0x923b10adafbd70ac83cfde90a85bd38e5e919348285b311e020721bc96adc9e9b7e45f8052d1b3ef97301947cbc6d3e9&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb8dbe590fe70f90ffcb0e4d7156fb9a763e0a5812a18fb900eb224dbfc1006ea53fe2995beeb8c68de87186093102daa072044fa2c7599d0ddff864035c094435b4bd4159157b8c5c2bb68b713313c33daed3f059742bf74bf9ee140996a8030&quot;
  deposit_data_root: &quot;0xb230a394c34aa022260b632113aac600d6adda8c634e99c4a0ca133d01ae895c&quot;
  eth1_data:
    deposit_root: &quot;0xa94dd2d608ad39920b3d4d36983bcf3fcbf847bfba0fd6efb0f9392538d9508b&quot;
    deposit_count: &quot;268&quot;
    block_hash: &quot;0xf02da506c532e1e1fd10587045c93575c15526820e5ceacab2119c401979948d&quot;
  block_height: 269
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xa175806ecd8f45f5b8a87219a9c345e9e612bcdfc850bf0b51c2b6a60813d7e3&quot;
      - &quot;0xe199368557ff186641e9a7d5cb05acac6d482b97df62a1011f0b9fd5c03f5734&quot;
    deposit_root: &quot;0xa94dd2d608ad39920b3d4d36983bcf3fcbf847bfba0fd6efb0f9392538d9508b&quot;
    deposit_count: 268
    execution_block_hash: &quot;0xf02da506c532e1e1fd10587045c93575c15526820e5ceacab2119c401979948d&quot;
    execution_block_height: 269
- deposit_data:
    pubkey: &quot;0x8860a33d75543d49ad04bdcffdfdf7fcef7228076d4e8150d80c3cda14651963544a683355e256166d995dd3f6b4ad35&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x986c60f5e748e02284435fdd37c2a72a5247e0784ebc99677490e9095f2665b1685a16d7dd48261c922897faa2273fc6030db1b871f208a56e20602b337ef10921b8a3164b128fbfef2566fc0db86c27f392eaddf4745aba700d9a69af3d0ad7&quot;
  deposit_data_root: &quot;0x1c37b6d2caaa5c7bb785e5cf0f444edc230bf9836cf1c8a27f1a0c5665c50c37&quot;
  eth1_data:
    deposit_root: &quot;0xd021c86513c1fd866c766cdedb99464a5c9a2abcb4f6a5563ccd8178cc778b0d&quot;
    deposit_count: &quot;269&quot;
    block_hash: &quot;0x27cdcf3f09175210019c23eac0ac9309bfd56a6654eb9523900ae387500fd99e&quot;
  block_height: 270
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xa175806ecd8f45f5b8a87219a9c345e9e612bcdfc850bf0b51c2b6a60813d7e3&quot;
      - &quot;0xe199368557ff186641e9a7d5cb05acac6d482b97df62a1011f0b9fd5c03f5734&quot;
      - &quot;0x1c37b6d2caaa5c7bb785e5cf0f444edc230bf9836cf1c8a27f1a0c5665c50c37&quot;
    deposit_root: &quot;0xd021c86513c1fd866c766cdedb99464a5c9a2abcb4f6a5563ccd8178cc778b0d&quot;
    deposit_count: 269
    execution_block_hash: &quot;0x27cdcf3f09175210019c23eac0ac9309bfd56a6654eb9523900ae387500fd99e&quot;
    execution_block_height: 270
- deposit_data:
    pubkey: &quot;0x805de41e2e03f52993f465c0cba3886c40488c0ebe7fbbbe65f016e5e6ff971efe2968e09b0d62263cde4c70f6cf8540&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x830ed2435dc71a80676f51b674be560ecd4d7f0b7d2328ccfee8bc207f4480fac75aa62926c2665a00cfdf2a9b5f18cf00313aa3eab4cb83f3224417cbe42a1591ba0260afb464481391930abfb206db57230757da96e033d25ad57ca15cefb3&quot;
  deposit_data_root: &quot;0xd00dd9ec8defab31ac1699c60512ddb92c0b66fdb722eeb8f889ce3f9a36e198&quot;
  eth1_data:
    deposit_root: &quot;0xf20d2b6626fa9a2412b80217d55810beaa23b9d42c0a386624fc99f04622d1d6&quot;
    deposit_count: &quot;270&quot;
    block_hash: &quot;0x0f3d50198252da6bcdd9fa7a62accd5b21e2c3236ed4434a6e30ecfa9a31c349&quot;
  block_height: 271
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xa175806ecd8f45f5b8a87219a9c345e9e612bcdfc850bf0b51c2b6a60813d7e3&quot;
      - &quot;0xe199368557ff186641e9a7d5cb05acac6d482b97df62a1011f0b9fd5c03f5734&quot;
      - &quot;0xc68746b2b174136c95a60d0312e6eb45b1d289447eeec15e7126fcdf8a85da9e&quot;
    deposit_root: &quot;0xf20d2b6626fa9a2412b80217d55810beaa23b9d42c0a386624fc99f04622d1d6&quot;
    deposit_count: 270
    execution_block_hash: &quot;0x0f3d50198252da6bcdd9fa7a62accd5b21e2c3236ed4434a6e30ecfa9a31c349&quot;
    execution_block_height: 271
- deposit_data:
    pubkey: &quot;0xa367b7c50ce66726561d5f4190607e9c1d3feab41f624b9ecfadb6f52e1b300ef98e8913e8fffb2b65cdbb889ff5fb6b&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x918fe57e516de9e415db3fd4f1a78843da0f6f76b71ab4ec9d8f91bea748fcab31a90e25b22d69e98cf83f43502cf4ac08a0cec4a3e7aa21d5b876b9728b079c0640becf699ff07b023431d6f872561c7e35f86e15d3abe0c9b2bbdc452fdad0&quot;
  deposit_data_root: &quot;0xa29deb39e17dec8af0ce7d25156ecabd1ebae33d3076a29b4ea8d8b127335672&quot;
  eth1_data:
    deposit_root: &quot;0xe92c7ae8c37c06c234eed3d64804cec30984b01ae852511077750a8e5ce8e9e2&quot;
    deposit_count: &quot;271&quot;
    block_hash: &quot;0x4a4ae702e70fa102e90e05e95bc8163f7cee4224b9a8ade2c97c4ad04d2f104c&quot;
  block_height: 272
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xa175806ecd8f45f5b8a87219a9c345e9e612bcdfc850bf0b51c2b6a60813d7e3&quot;
      - &quot;0xe199368557ff186641e9a7d5cb05acac6d482b97df62a1011f0b9fd5c03f5734&quot;
      - &quot;0xc68746b2b174136c95a60d0312e6eb45b1d289447eeec15e7126fcdf8a85da9e&quot;
      - &quot;0xa29deb39e17dec8af0ce7d25156ecabd1ebae33d3076a29b4ea8d8b127335672&quot;
    deposit_root: &quot;0xe92c7ae8c37c06c234eed3d64804cec30984b01ae852511077750a8e5ce8e9e2&quot;
    deposit_count: 271
    execution_block_hash: &quot;0x4a4ae702e70fa102e90e05e95bc8163f7cee4224b9a8ade2c97c4ad04d2f104c&quot;
    execution_block_height: 272
- deposit_data:
    pubkey: &quot;0xaf379c89e4f4bec6b942c9e2d8fa6ccd2ec13cf421d80c987af53d5217c932483c4ed17cd1a9c9d7174e2546ab16ebb4&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa49410f5cc90cc268e78c2afa27c8cf129f4da16397953dc383e3eafb1e797faa9bb0e9649502829df2c2cf2b7cd715d0d8be34d1e8cc2706933290ce42bdd8bc1a1bcbab9defcdbb0e85309ca92a7c7c0df00b1ba01dd13e74834ff17788d0b&quot;
  deposit_data_root: &quot;0x677f04382b7df90d9e30533f0fea1e1193e6a71e0f3d2fc6621957b406a2d39e&quot;
  eth1_data:
    deposit_root: &quot;0x734e5eceb4244b23ed80e4a9d91f6830c403c9e37a27c8501368ddc1b9bc1b25&quot;
    deposit_count: &quot;272&quot;
    block_hash: &quot;0x615eaf0c08bbd375884ea9de1f7261253ab51971c2b1d8407fa63982d4d6feae&quot;
  block_height: 273
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x004f564bddfe12ca7aeb4708f48538e1d5fe4b3ad2c8b08be819236aa2c67ec2&quot;
    deposit_root: &quot;0x734e5eceb4244b23ed80e4a9d91f6830c403c9e37a27c8501368ddc1b9bc1b25&quot;
    deposit_count: 272
    execution_block_hash: &quot;0x615eaf0c08bbd375884ea9de1f7261253ab51971c2b1d8407fa63982d4d6feae&quot;
    execution_block_height: 273
- deposit_data:
    pubkey: &quot;0xb6c5b136625178a485ee2eba1ddadc84b55e42c0e5a7ebfc8e5e2db651baf3c0a7cff6fb8e94dfccb1ca0a0d48b7496f&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8dba1b2ce9ddb0488fbd27b8f0e760844e5242b4a70d188a0fe5e7602161ca591f09b3ddeae404795f02df26930d00e80ef42e30d4d09fd5632c9dde165519725ff4442dc3eb9d86056a5afbe401a5568674ee6f7dbc7f1ef9d5e7e8ec6d4a74&quot;
  deposit_data_root: &quot;0x984f88c7b8523c5a9c9268002fa51558131645074051f28869233e59bba2bb64&quot;
  eth1_data:
    deposit_root: &quot;0x0b1169b7908d522037d597df82f0e4821a3f141ae329527275e975e1f06b44f3&quot;
    deposit_count: &quot;273&quot;
    block_hash: &quot;0x9a12613dd49a16c089530e40aa1c8f06f77c852479a90a28387d068d5884ba45&quot;
  block_height: 274
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x004f564bddfe12ca7aeb4708f48538e1d5fe4b3ad2c8b08be819236aa2c67ec2&quot;
      - &quot;0x984f88c7b8523c5a9c9268002fa51558131645074051f28869233e59bba2bb64&quot;
    deposit_root: &quot;0x0b1169b7908d522037d597df82f0e4821a3f141ae329527275e975e1f06b44f3&quot;
    deposit_count: 273
    execution_block_hash: &quot;0x9a12613dd49a16c089530e40aa1c8f06f77c852479a90a28387d068d5884ba45&quot;
    execution_block_height: 274
- deposit_data:
    pubkey: &quot;0xac210cfd8d8d9547120ba0a786a93318beb172471e9711b764db71376898bc28037160396e32be311a1823e585e8f524&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9917a489a4d766025fe21104187d687a191ab135e68f44282e597ab9bee1197d4cd037d59051d36197be3854c2429964138486367635adc03360ac053251a06df519237d2fa0b72b8540feeb5bb5e6180f137bbbcdc250aa191a62fb9294f33e&quot;
  deposit_data_root: &quot;0x6d90c6f3641efb6dce19f2efb93fc24439111dbbcc6cdcdf60a2f4c0019af2dd&quot;
  eth1_data:
    deposit_root: &quot;0x9604fd80f34acd50e4b641e866a440bfd4697939c358ac3bc91bf25352a8057a&quot;
    deposit_count: &quot;274&quot;
    block_hash: &quot;0x439db7c4143f986853029b0ce493c55804bf4a38e08c9f2bbc19ff22b1a185e5&quot;
  block_height: 275
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x004f564bddfe12ca7aeb4708f48538e1d5fe4b3ad2c8b08be819236aa2c67ec2&quot;
      - &quot;0xafc140dc42b75f6f96d56352af93e6d41d56ab68fe4b90981a6ef2aca4a11b4f&quot;
    deposit_root: &quot;0x9604fd80f34acd50e4b641e866a440bfd4697939c358ac3bc91bf25352a8057a&quot;
    deposit_count: 274
    execution_block_hash: &quot;0x439db7c4143f986853029b0ce493c55804bf4a38e08c9f2bbc19ff22b1a185e5&quot;
    execution_block_height: 275
- deposit_data:
    pubkey: &quot;0x8771e8df435244648533c638f725d292deaa9ef3e098ccce30255f860156f9101aea2ab56199d5a8cd2042af7ea57e33&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x813560e954b791856c97ff6bf3bc645f75d58e88a405d804957362b901ff360f625839be68c9c612da31cac55f41b7d009dd46e7847de8ff5c78594ac44dc2a5c91ff1330e1f44e3c8398e44a0021e5508afc438bc3f2d88fc9fee40b6171386&quot;
  deposit_data_root: &quot;0x6cab9ec916767574e8a430f9d5eba9d27c0a90902ca458bb94ce0f50c6d6ebf0&quot;
  eth1_data:
    deposit_root: &quot;0xd55236a200b36a4aa5e760c3135bd62b4ac05255ee43580b5d5bf16322ac92b2&quot;
    deposit_count: &quot;275&quot;
    block_hash: &quot;0xd095a783f5860659c4fbd8e22b2bbb739d9fe8b974da64831e52c4839bc2f8b8&quot;
  block_height: 276
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x004f564bddfe12ca7aeb4708f48538e1d5fe4b3ad2c8b08be819236aa2c67ec2&quot;
      - &quot;0xafc140dc42b75f6f96d56352af93e6d41d56ab68fe4b90981a6ef2aca4a11b4f&quot;
      - &quot;0x6cab9ec916767574e8a430f9d5eba9d27c0a90902ca458bb94ce0f50c6d6ebf0&quot;
    deposit_root: &quot;0xd55236a200b36a4aa5e760c3135bd62b4ac05255ee43580b5d5bf16322ac92b2&quot;
    deposit_count: 275
    execution_block_hash: &quot;0xd095a783f5860659c4fbd8e22b2bbb739d9fe8b974da64831e52c4839bc2f8b8&quot;
    execution_block_height: 276
- deposit_data:
    pubkey: &quot;0xa3c94a3ec9d463a4929513b426cc91887c7e09fd038314ada8e5e7a8ce204a7a20247319f91c0746de0e241550aef4bb&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x99b1d155a15927ce6ca47e70b7ded4d286509f134e2c58a85595e7bedf9eb7d27408cf7638df5cc64969ee5a502644d20486af547bf3518937fe1253259f9d0bb2e509b1c6b1b0f8510950345522a82927de2d8191aab3bb4bb0ec1cb94a03f9&quot;
  deposit_data_root: &quot;0xe237d745c0911cc07e84746c0e519b09b08b97b06b530a9ddc4e887d53bf8b81&quot;
  eth1_data:
    deposit_root: &quot;0x5df671c2350221cbf76630d9cf5d5ba52a568e846e24a45f2631a577507011c1&quot;
    deposit_count: &quot;276&quot;
    block_hash: &quot;0xa5113dab93745a4a0e8e65ef5f666109d653178cc86cf033bbdedffe8de244a0&quot;
  block_height: 277
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x004f564bddfe12ca7aeb4708f48538e1d5fe4b3ad2c8b08be819236aa2c67ec2&quot;
      - &quot;0xd2f50982286bcc1b17c7402df3f3c8e5ccb7ac8516cae8783aa22d003b1838ce&quot;
    deposit_root: &quot;0x5df671c2350221cbf76630d9cf5d5ba52a568e846e24a45f2631a577507011c1&quot;
    deposit_count: 276
    execution_block_hash: &quot;0xa5113dab93745a4a0e8e65ef5f666109d653178cc86cf033bbdedffe8de244a0&quot;
    execution_block_height: 277
- deposit_data:
    pubkey: &quot;0xa647de716dfe7d82e529344bf832f2ac603d7067a515ebb7148fe69cc4330c1c12d3caaf16d6df3a3483574d49a296dd&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x93620e7602b38582df7080d48213f86a395186fe16197167e99e8c555d0a7a2f8b818bf2cc884608059212ae1090fc21135cdd2285e1a96271dc200bae45d68bc30a6053a68c5387557827685bdc3717b1754a22473b9193b2ed08fe12936e4b&quot;
  deposit_data_root: &quot;0x454bf4695084db5d52745a0c0fcf55d46b16d40fd982c40df3e64ca30abf2eff&quot;
  eth1_data:
    deposit_root: &quot;0x2cb46c5f7addaa0c11d5f2a617f116ee53714804de67624d12aaed20ee03e07d&quot;
    deposit_count: &quot;277&quot;
    block_hash: &quot;0xc16cb9437067b34e14b0db82231c2466967cf85459de2d923b92fc39afedbcb0&quot;
  block_height: 278
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x004f564bddfe12ca7aeb4708f48538e1d5fe4b3ad2c8b08be819236aa2c67ec2&quot;
      - &quot;0xd2f50982286bcc1b17c7402df3f3c8e5ccb7ac8516cae8783aa22d003b1838ce&quot;
      - &quot;0x454bf4695084db5d52745a0c0fcf55d46b16d40fd982c40df3e64ca30abf2eff&quot;
    deposit_root: &quot;0x2cb46c5f7addaa0c11d5f2a617f116ee53714804de67624d12aaed20ee03e07d&quot;
    deposit_count: 277
    execution_block_hash: &quot;0xc16cb9437067b34e14b0db82231c2466967cf85459de2d923b92fc39afedbcb0&quot;
    execution_block_height: 278
- deposit_data:
    pubkey: &quot;0x97dae6c47e2b695734163c4e12ff709e7d63879fda8192ca26a35501dce45fd8748b5ed04519e829d61e5e7a3e379dfd&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8419026bb209d08a2db619c23985a483e4a42af20e10715893985ee289a000c990c4f33693780a3640ded33dd21fd2200781677f590164d65528a4f1c047443e619930b7a3ab3be00e7a6c0df70fa505da34862fb9a539a531c237792dc0ab79&quot;
  deposit_data_root: &quot;0xdd6f4ed981c18b7b2e7bb2f4e0688708fd069d405b0b087315ff02eefe2984c5&quot;
  eth1_data:
    deposit_root: &quot;0x3ecdd5c5beb8def23312392aae577b8950c66c902af8bf99de73b96656be003b&quot;
    deposit_count: &quot;278&quot;
    block_hash: &quot;0x8bd6fb2e4d0410f8eae7eedcffbc2f9ae0e0a31b9dc9d6de94b0bf7668691eb1&quot;
  block_height: 279
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x004f564bddfe12ca7aeb4708f48538e1d5fe4b3ad2c8b08be819236aa2c67ec2&quot;
      - &quot;0xd2f50982286bcc1b17c7402df3f3c8e5ccb7ac8516cae8783aa22d003b1838ce&quot;
      - &quot;0xd795029ab5b69d8e37a9ff4be1b60af4cf9805d75bb3e2b61fa05fb9decb98d4&quot;
    deposit_root: &quot;0x3ecdd5c5beb8def23312392aae577b8950c66c902af8bf99de73b96656be003b&quot;
    deposit_count: 278
    execution_block_hash: &quot;0x8bd6fb2e4d0410f8eae7eedcffbc2f9ae0e0a31b9dc9d6de94b0bf7668691eb1&quot;
    execution_block_height: 279
- deposit_data:
    pubkey: &quot;0x897c752e1ed45c3ab22146fe595fd08175a828c69e1e3243e6e1e644792b0bc979924123c0cca7dea405b074e214880e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xafd9fdd20324edeeb6283b1a45e7178f6419260b0581cd71ea46b392d6ddb5ee3b7dcef33bf889f401e6b78c5d3766370f25200d87ace14ebc81992a6c0c7552bced661cf33b1ec285d89ebe94c7159e0f0d78543e1d1362789e54729bce5834&quot;
  deposit_data_root: &quot;0xbefaf00ec4412758aba9bbd73a7a8f4c56dec0523ca462ae5dc6c1f553100248&quot;
  eth1_data:
    deposit_root: &quot;0xa3e6322b128ba1eb9cab42f9e9de032e5ef934e3395e3c070c2e3877a9262640&quot;
    deposit_count: &quot;279&quot;
    block_hash: &quot;0x00ed7d8bb7cdd6256ac0d7f1ad7b9e34302d9e119e9db4078fbb19b8d3541685&quot;
  block_height: 280
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x004f564bddfe12ca7aeb4708f48538e1d5fe4b3ad2c8b08be819236aa2c67ec2&quot;
      - &quot;0xd2f50982286bcc1b17c7402df3f3c8e5ccb7ac8516cae8783aa22d003b1838ce&quot;
      - &quot;0xd795029ab5b69d8e37a9ff4be1b60af4cf9805d75bb3e2b61fa05fb9decb98d4&quot;
      - &quot;0xbefaf00ec4412758aba9bbd73a7a8f4c56dec0523ca462ae5dc6c1f553100248&quot;
    deposit_root: &quot;0xa3e6322b128ba1eb9cab42f9e9de032e5ef934e3395e3c070c2e3877a9262640&quot;
    deposit_count: 279
    execution_block_hash: &quot;0x00ed7d8bb7cdd6256ac0d7f1ad7b9e34302d9e119e9db4078fbb19b8d3541685&quot;
    execution_block_height: 280
- deposit_data:
    pubkey: &quot;0x90e6673aa3258396ea9b5e5d4c53b076fc93d4f408008343e44f5d4e49e408942c764d454b435be080ed8e4328ddcf1f&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xad7a438ba41385b1078bae963e814a92e922a83efebe6aca14ce1a0a1754ec7d882211ef71ef55bcaa4d87e75b20f9b611837e28ab711d1874863a151a5ebfee310b649ce58aeee5fe7809dbf813a0d1e5786cbcf9286fbb6d649939c781339c&quot;
  deposit_data_root: &quot;0xdc9c1d97e917f6e25ae888d726fca078b28921a5bb9f1ea669ba53b18caaa5c0&quot;
  eth1_data:
    deposit_root: &quot;0x7b3c923bef540d0db79619c5bfb8a2abf74f57c23a1cfd4dec6410feacb6b943&quot;
    deposit_count: &quot;280&quot;
    block_hash: &quot;0x0067d9ff3bd86de63d54114d41770e5b0cb7c8c5120b19530eab3d3bdfe79836&quot;
  block_height: 281
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x004f564bddfe12ca7aeb4708f48538e1d5fe4b3ad2c8b08be819236aa2c67ec2&quot;
      - &quot;0xb96037b213deff69adf6fc2ef3ff23ef01b2a19f085f6cdc4395ef55d13f1eb3&quot;
    deposit_root: &quot;0x7b3c923bef540d0db79619c5bfb8a2abf74f57c23a1cfd4dec6410feacb6b943&quot;
    deposit_count: 280
    execution_block_hash: &quot;0x0067d9ff3bd86de63d54114d41770e5b0cb7c8c5120b19530eab3d3bdfe79836&quot;
    execution_block_height: 281
- deposit_data:
    pubkey: &quot;0xa7f7669994d4503c6390a44e7b64103861f78d60283580e19d0898948ed55a0b16b6c8fcd86e14341fd9a5974e4eda5d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x837a5a91adc8bd9b06a5b116769ad796b673f5230741af2e8ce61d59c7f3eb80b1a896f36af0f7b1d72c612cdf51eec7154395d1cebf833e0329d4ebc118a0708b2d2429d13324157ee8056eba25c5e0ff6a3b4212c19e437666151de56a0e46&quot;
  deposit_data_root: &quot;0xc760b2ad57feef344b258de4d1ecb020fc392a45187f5aab606d97a308a63ebd&quot;
  eth1_data:
    deposit_root: &quot;0xa06cf7368dcd4b336a8769c80e7ade8ef0d8900f5abe104cececdef2a22f73dc&quot;
    deposit_count: &quot;281&quot;
    block_hash: &quot;0xd67c87e9d0958db9609fdb7e4a3246578abbbc9e36517a6c224196c1d726207d&quot;
  block_height: 282
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x004f564bddfe12ca7aeb4708f48538e1d5fe4b3ad2c8b08be819236aa2c67ec2&quot;
      - &quot;0xb96037b213deff69adf6fc2ef3ff23ef01b2a19f085f6cdc4395ef55d13f1eb3&quot;
      - &quot;0xc760b2ad57feef344b258de4d1ecb020fc392a45187f5aab606d97a308a63ebd&quot;
    deposit_root: &quot;0xa06cf7368dcd4b336a8769c80e7ade8ef0d8900f5abe104cececdef2a22f73dc&quot;
    deposit_count: 281
    execution_block_hash: &quot;0xd67c87e9d0958db9609fdb7e4a3246578abbbc9e36517a6c224196c1d726207d&quot;
    execution_block_height: 282
- deposit_data:
    pubkey: &quot;0xb8ad8a758c02b9a1769a5f883a41eee5a516165cd2ae19749d60ff634f1175940ea569244830265b2f59b2aeaa434478&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb55d9ffeab85b135b7e21166db97d4defbea12b1beebc795a694062cfcdc5de3db44e1810539c8b22bbc2a930b4cc0fe102a8b233c45b958a7db52b28bcbe9192e191b967ba76f9fce60d4bd30ebfcf0c156b298ed99cbf1df359da8f9b089c7&quot;
  deposit_data_root: &quot;0xd224e7399aef34aebab912dd931e8029d849a75e46d52d3e7af7ef795089aba5&quot;
  eth1_data:
    deposit_root: &quot;0x41e107ab1e7255ca23c4f66b6afaa812e789a822664683cf158c481a32a62e10&quot;
    deposit_count: &quot;282&quot;
    block_hash: &quot;0x8e6819b492671a514f3da060880e5379b0b42de61df7089d479d883c2f25e4a6&quot;
  block_height: 283
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x004f564bddfe12ca7aeb4708f48538e1d5fe4b3ad2c8b08be819236aa2c67ec2&quot;
      - &quot;0xb96037b213deff69adf6fc2ef3ff23ef01b2a19f085f6cdc4395ef55d13f1eb3&quot;
      - &quot;0x5f703e4b8197692608370e14e3f2f2ae87e4817939d05d095009486de7ebe0ed&quot;
    deposit_root: &quot;0x41e107ab1e7255ca23c4f66b6afaa812e789a822664683cf158c481a32a62e10&quot;
    deposit_count: 282
    execution_block_hash: &quot;0x8e6819b492671a514f3da060880e5379b0b42de61df7089d479d883c2f25e4a6&quot;
    execution_block_height: 283
- deposit_data:
    pubkey: &quot;0x95037a05a0a6a90acadb5cc2156117378faa1c1eb79cacf3b91835e268d7855960e638dc34bbc192cc6b8ca6b942be04&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x96ffe4fec99f4e61dfeddeb4e0ce1db5d3f2ec1c7b5608a27dbea3a684705aadd979a4c48ed703904b1afdab4ec410e717a8d892b8c881d95fc0cea3df434f4a2a736b75e12cbfa65354d1452f1c1494679b0c2f82e0278bac0e727cca54ae5f&quot;
  deposit_data_root: &quot;0xa84635d4c80545e945a05b992bf4e018466bf90ce77efbc6c4afcd86e7c40480&quot;
  eth1_data:
    deposit_root: &quot;0xf45ea7c111196d94551e75f4827dc54da7b27159b61f0157001cc501e449ab11&quot;
    deposit_count: &quot;283&quot;
    block_hash: &quot;0x208b9d89c955086f385701344c89f0f7f36d8a12f8126654ff46fffac19738cb&quot;
  block_height: 284
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x004f564bddfe12ca7aeb4708f48538e1d5fe4b3ad2c8b08be819236aa2c67ec2&quot;
      - &quot;0xb96037b213deff69adf6fc2ef3ff23ef01b2a19f085f6cdc4395ef55d13f1eb3&quot;
      - &quot;0x5f703e4b8197692608370e14e3f2f2ae87e4817939d05d095009486de7ebe0ed&quot;
      - &quot;0xa84635d4c80545e945a05b992bf4e018466bf90ce77efbc6c4afcd86e7c40480&quot;
    deposit_root: &quot;0xf45ea7c111196d94551e75f4827dc54da7b27159b61f0157001cc501e449ab11&quot;
    deposit_count: 283
    execution_block_hash: &quot;0x208b9d89c955086f385701344c89f0f7f36d8a12f8126654ff46fffac19738cb&quot;
    execution_block_height: 284
- deposit_data:
    pubkey: &quot;0xab152bc78eada258d68785ad491422f64ffece7e462ac59ba92ca919f6e2ecb3c3707b34d6159a967b4dd7590c4321e0&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa62cef8f23182080da9f5566785c5f614bb68b7ed2480551ff248ba0ff398af1125437bb1703598a3726757e6aa242f30c73e7f1833a07e3944fa370bb35a17bca08a6a65988a8cca0cc544489bebc4f7089ac288694483aa3f0d14913d11bde&quot;
  deposit_data_root: &quot;0x7a9db3084c5390172ef580652bd82ec524081fa698d216f8680acddf3598b5a9&quot;
  eth1_data:
    deposit_root: &quot;0xb14450ae34030b8e3b7357bcd9b403267d507c15e5006ee4df1d5fa5dcf8dafc&quot;
    deposit_count: &quot;284&quot;
    block_hash: &quot;0x705a548444db8857275b1e4daff4e049715ba5c3cd31e9c9ea40d7aa767f76cb&quot;
  block_height: 285
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x004f564bddfe12ca7aeb4708f48538e1d5fe4b3ad2c8b08be819236aa2c67ec2&quot;
      - &quot;0xb96037b213deff69adf6fc2ef3ff23ef01b2a19f085f6cdc4395ef55d13f1eb3&quot;
      - &quot;0xd2b6e86410a770e340ffb7de6ee5cf863a85940c79573f83f25f86aea119f640&quot;
    deposit_root: &quot;0xb14450ae34030b8e3b7357bcd9b403267d507c15e5006ee4df1d5fa5dcf8dafc&quot;
    deposit_count: 284
    execution_block_hash: &quot;0x705a548444db8857275b1e4daff4e049715ba5c3cd31e9c9ea40d7aa767f76cb&quot;
    execution_block_height: 285
- deposit_data:
    pubkey: &quot;0x847230d7b775a10cb13cbe8b80b7d2e5e613043af2913729fde2404485cb4dcff11fbb08487c860125c9d4828686818e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa97dcbec769d32f79ab1ffb179002460cf80afd587cd7f19c6f8761af07a8819cd82a64d82917e208dede5fdda3392e008516c97578f0fa1f56201f010b00e3a7dcde2d8ce22cd02d24663540889087ba0f7011af978035591f41a26b00d4455&quot;
  deposit_data_root: &quot;0x71aa303f97c1545130a878320efceac5ac755201d7435beb0a6a5bbbd9f76432&quot;
  eth1_data:
    deposit_root: &quot;0x89e2e3db69c005b9af9f2f52537e98e4d99b15078574bfbb0542230f161d7bf4&quot;
    deposit_count: &quot;285&quot;
    block_hash: &quot;0x70ce0316c6eb65c0b81f178a0f234dd62a88b9f1f751b77974158bc26cd78152&quot;
  block_height: 286
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x004f564bddfe12ca7aeb4708f48538e1d5fe4b3ad2c8b08be819236aa2c67ec2&quot;
      - &quot;0xb96037b213deff69adf6fc2ef3ff23ef01b2a19f085f6cdc4395ef55d13f1eb3&quot;
      - &quot;0xd2b6e86410a770e340ffb7de6ee5cf863a85940c79573f83f25f86aea119f640&quot;
      - &quot;0x71aa303f97c1545130a878320efceac5ac755201d7435beb0a6a5bbbd9f76432&quot;
    deposit_root: &quot;0x89e2e3db69c005b9af9f2f52537e98e4d99b15078574bfbb0542230f161d7bf4&quot;
    deposit_count: 285
    execution_block_hash: &quot;0x70ce0316c6eb65c0b81f178a0f234dd62a88b9f1f751b77974158bc26cd78152&quot;
    execution_block_height: 286
- deposit_data:
    pubkey: &quot;0x811f122742c9f58ceff4b9b75ef59d8a8b5553313c027e18a21f417206d72b66d225c30d9f9f5dbb648d68e537a95cd8&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8d64c45dec8fd9624e5a673b4be330985f42fb04e32ddcb14f8463e92c8534e8c9dc7ce6dd324d9e46d08535d67024bd0f3d2eb8afe1c571969f7054eee365376b6ef65dd2d79aeaf4b9e065fab99a08f54f7aa4eaa608f542be51155c97c943&quot;
  deposit_data_root: &quot;0x8c2d9422f7f6da9f58a22bf2958c28614b38612f6599a09dbbfb3b6b05a2c9de&quot;
  eth1_data:
    deposit_root: &quot;0x39ed089d07634871eab8445a2e27720f969a75194f7e739b28632596d51afd4c&quot;
    deposit_count: &quot;286&quot;
    block_hash: &quot;0x0ad81ac5b5624db6ae564e1e55a039c9ff07abbfad8541f36b1499a38e34ff01&quot;
  block_height: 287
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x004f564bddfe12ca7aeb4708f48538e1d5fe4b3ad2c8b08be819236aa2c67ec2&quot;
      - &quot;0xb96037b213deff69adf6fc2ef3ff23ef01b2a19f085f6cdc4395ef55d13f1eb3&quot;
      - &quot;0xd2b6e86410a770e340ffb7de6ee5cf863a85940c79573f83f25f86aea119f640&quot;
      - &quot;0xd8e36fc1ec59065a6d776496630ecf9de9417b10f4fba2873ba760bf445dfe59&quot;
    deposit_root: &quot;0x39ed089d07634871eab8445a2e27720f969a75194f7e739b28632596d51afd4c&quot;
    deposit_count: 286
    execution_block_hash: &quot;0x0ad81ac5b5624db6ae564e1e55a039c9ff07abbfad8541f36b1499a38e34ff01&quot;
    execution_block_height: 287
- deposit_data:
    pubkey: &quot;0x875b740b7de5cd6db43823c3dabb3e0652b132a2b0c7593383420f31c452c3e772885f083932eee347c94ff2411367fe&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x870a4c9e1e8bad7573ca85cf96c85fcee530e3918c0fd5231945d44b93668b09dfe394fee7df5f34641f9a2100d7f8c100758148ba94822633c24ce5c8abfa4922f9dc83ec659a471cb791d2c8f50bb63879125bb240da3f3ddf073034022974&quot;
  deposit_data_root: &quot;0x95dae1cb1d3ceb2b954761d7e3994dfcf890f0af2d932c8ae16a0305f4172e7c&quot;
  eth1_data:
    deposit_root: &quot;0x091a9d9c1cb63e60b98a645f4b92cb819e69c9d72a1a22bbf4ce0aab06fd8f4e&quot;
    deposit_count: &quot;287&quot;
    block_hash: &quot;0x0a2ee6676a0013c27224c31e35877a9f41c87bfcd451d50a496f62094cdddf59&quot;
  block_height: 288
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x004f564bddfe12ca7aeb4708f48538e1d5fe4b3ad2c8b08be819236aa2c67ec2&quot;
      - &quot;0xb96037b213deff69adf6fc2ef3ff23ef01b2a19f085f6cdc4395ef55d13f1eb3&quot;
      - &quot;0xd2b6e86410a770e340ffb7de6ee5cf863a85940c79573f83f25f86aea119f640&quot;
      - &quot;0xd8e36fc1ec59065a6d776496630ecf9de9417b10f4fba2873ba760bf445dfe59&quot;
      - &quot;0x95dae1cb1d3ceb2b954761d7e3994dfcf890f0af2d932c8ae16a0305f4172e7c&quot;
    deposit_root: &quot;0x091a9d9c1cb63e60b98a645f4b92cb819e69c9d72a1a22bbf4ce0aab06fd8f4e&quot;
    deposit_count: 287
    execution_block_hash: &quot;0x0a2ee6676a0013c27224c31e35877a9f41c87bfcd451d50a496f62094cdddf59&quot;
    execution_block_height: 288
- deposit_data:
    pubkey: &quot;0xacbfea617a3cbc5df59da38133fee49b25a4a27aee878184acbd8cad6c72a2ffd5cf31812e4ded11d7a73c6c7a9a7cb8&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb261f12cd1af634ddd037f62c1930120938421469681c3e4ad8abed21ba550a1b60d91fec994000e28bd880da3de709c0af2408c80150b438cf318791dc169983785152bed21b01117f698ee6853bf23948501289e4ccd63d7d87b70d82484a2&quot;
  deposit_data_root: &quot;0xc5c4f40555719fb6d08ab90de29f01a80adde2ede7f5a2338ec0ae24980480a6&quot;
  eth1_data:
    deposit_root: &quot;0x313a8e2fec006ca89b4e20c0945b2f7ba336aed9695b4b03bc06608712cde390&quot;
    deposit_count: &quot;288&quot;
    block_hash: &quot;0x7895648d903ca4cfc86649eb22f8d1c758141f8d3aa89f938f2f25016481435e&quot;
  block_height: 289
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
    deposit_root: &quot;0x313a8e2fec006ca89b4e20c0945b2f7ba336aed9695b4b03bc06608712cde390&quot;
    deposit_count: 288
    execution_block_hash: &quot;0x7895648d903ca4cfc86649eb22f8d1c758141f8d3aa89f938f2f25016481435e&quot;
    execution_block_height: 289
- deposit_data:
    pubkey: &quot;0xaae696196c2730c93099a70860ca5efa86f84e5841e05aaeab2619a772f23eec46d4c72a31b0e458c85409b511b498a3&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa99138f2331c3cf13064847011cece90e314742f897c5a629912cf2339ae8e2ee5375bd3a2bd33e164a03b3adde0d40f0243c57233e12f7d5f61328bb6f4e2516bbc784dd6fcd3ca814cb8658499516267b4b1aed34eee7dfcc1b9920efcbe4c&quot;
  deposit_data_root: &quot;0x844286999134010ba50c2a62fbe3af61cb39b66dcb6c74fbd58a9aad32331c73&quot;
  eth1_data:
    deposit_root: &quot;0x1aaf2dc02a54384847050da49a834ff3a3474b4419885b2e37092c885c2a5764&quot;
    deposit_count: &quot;289&quot;
    block_hash: &quot;0x74d07cd3aacb5ed6004cc7a76696a60a64fd2f8a1367d1070b3e9e70316cbc58&quot;
  block_height: 290
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0x844286999134010ba50c2a62fbe3af61cb39b66dcb6c74fbd58a9aad32331c73&quot;
    deposit_root: &quot;0x1aaf2dc02a54384847050da49a834ff3a3474b4419885b2e37092c885c2a5764&quot;
    deposit_count: 289
    execution_block_hash: &quot;0x74d07cd3aacb5ed6004cc7a76696a60a64fd2f8a1367d1070b3e9e70316cbc58&quot;
    execution_block_height: 290
- deposit_data:
    pubkey: &quot;0xae0825786e4f5ada18f212b067a394b52e60b37c98bb22ccdf0416d27b33029678de976370eea92c384ae44bca79386c&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb27632627c427944c2fc88f3cf387c3ae3b01bcbdd66fca2e0342c8d99608e86943a7f85783609c2f52bca77c4c703561734b382e423db9b639655ad298c1278d906259b9d73d8a050e78ce06433a6ad5c0e18f22edfdd6e59f8bcc4eff47262&quot;
  deposit_data_root: &quot;0xd4fb8486399925af6ee9cb0675686bf197754b6115bb082560b529ee4b0bc6af&quot;
  eth1_data:
    deposit_root: &quot;0x799fbeae76281fc3802633b4e9cf0e96fccd7cdfeef10763f38d71a9362264f1&quot;
    deposit_count: &quot;290&quot;
    block_hash: &quot;0x7394bcdc109326766ef4bbbc9a79a2e3a0ec7ca68af666caee2628105e29da04&quot;
  block_height: 291
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0x7705b49fc5157cced1429cc52e57d903c5bef2f85f33041d5cfb966557058b7c&quot;
    deposit_root: &quot;0x799fbeae76281fc3802633b4e9cf0e96fccd7cdfeef10763f38d71a9362264f1&quot;
    deposit_count: 290
    execution_block_hash: &quot;0x7394bcdc109326766ef4bbbc9a79a2e3a0ec7ca68af666caee2628105e29da04&quot;
    execution_block_height: 291
- deposit_data:
    pubkey: &quot;0x95ef906a741f50b59bf8fb77c134abc0534fbe7d0c432832d2d1c0ff9bd20090b424df54ffadebb9cc43e5f3812a7968&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x86e9c1163ad77136831a5a21680ae3b20e22ea656c108e3db81c698526b2a0f453df4b18c563a6491b4b627f8885e79611a4d5b71a2c2dc72812fd0219314c4ff2cd561cb8acb01fb6b03dc4052b7bcd5231053cbcb28d47da3e6bb3442b5018&quot;
  deposit_data_root: &quot;0x6edb20c206b0c315233ef2716988f6043c49f1a557b934ca778841f252256d33&quot;
  eth1_data:
    deposit_root: &quot;0x87c3659d83ea26cbde44dcc3b5b4c4afab70c1c3c1345cd11514aa7a325b66f0&quot;
    deposit_count: &quot;291&quot;
    block_hash: &quot;0xcf1ebd89ed9130987c74ec2d4af8d83006364bf28784baaadd4c169ecc03ac75&quot;
  block_height: 292
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0x7705b49fc5157cced1429cc52e57d903c5bef2f85f33041d5cfb966557058b7c&quot;
      - &quot;0x6edb20c206b0c315233ef2716988f6043c49f1a557b934ca778841f252256d33&quot;
    deposit_root: &quot;0x87c3659d83ea26cbde44dcc3b5b4c4afab70c1c3c1345cd11514aa7a325b66f0&quot;
    deposit_count: 291
    execution_block_hash: &quot;0xcf1ebd89ed9130987c74ec2d4af8d83006364bf28784baaadd4c169ecc03ac75&quot;
    execution_block_height: 292
- deposit_data:
    pubkey: &quot;0xac3a33ffd0eb0ecdb7baf1a5a4d8fdbd7c2e7558aa073269d2f9b7e9e5c7a1402c30efdb34fd7d268ec5f64db92a76c3&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xad36e7b3da78886b41f5e61ad0bec7a5a7f68fb9b6d5bfd0ba5b75c59dfc6ada6b33da3729215c23122d812abc4e8eda06f88f7e414e79224eefcb4bae2f798512cab1cb96f5f1c1ed5e8b81c97967098a3a38b96a1bb2e19bbc819de9342342&quot;
  deposit_data_root: &quot;0x7e435b81ff4fcb487b26cff3b131c5453c05d167c6617c8865879b51bf8fb04c&quot;
  eth1_data:
    deposit_root: &quot;0x53252143b0ff828eec2c69855e5ca87dd5153f5df8a7a24603031e62fc7a2980&quot;
    deposit_count: &quot;292&quot;
    block_hash: &quot;0x1dec0f6cbd0fdfaeb411d008ff1b21c4cab80e38ddab4385464828921e8903d7&quot;
  block_height: 293
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0x0730794fdc9fa73177b77e150edf2e164ec8d1917f76a71e085eefdaf0bd3835&quot;
    deposit_root: &quot;0x53252143b0ff828eec2c69855e5ca87dd5153f5df8a7a24603031e62fc7a2980&quot;
    deposit_count: 292
    execution_block_hash: &quot;0x1dec0f6cbd0fdfaeb411d008ff1b21c4cab80e38ddab4385464828921e8903d7&quot;
    execution_block_height: 293
- deposit_data:
    pubkey: &quot;0x8b1d9ba63bdc005529f0f6e2f442e6649adcec11e0db1d643b3d3e09307cc8c5b3fb84049941b8692f10799011c246c9&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb331295d92ea1dde46a7149810b7348a1cfc004b760326a35e61c95afde55c3e1c9798b3e94d8dc8b8a4101746600b470d2b693074eec42f90347e22ddb6dcf539de7b4c9d0bc2ad6d21e59d81228831df635658789f3d1dacea605ddc391719&quot;
  deposit_data_root: &quot;0xaa148346b9b8d2c5c24672977c58e8c35edacef56bfd81028f3fecba2b2442c5&quot;
  eth1_data:
    deposit_root: &quot;0x34e1e67726ccca66adad1c4d54baba739c7c52955a01b7cba29c3d8f2317f5e2&quot;
    deposit_count: &quot;293&quot;
    block_hash: &quot;0x5808234c115cc61500e2a564049a17037ee5108aec392d429f03f58ba8d16443&quot;
  block_height: 294
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0x0730794fdc9fa73177b77e150edf2e164ec8d1917f76a71e085eefdaf0bd3835&quot;
      - &quot;0xaa148346b9b8d2c5c24672977c58e8c35edacef56bfd81028f3fecba2b2442c5&quot;
    deposit_root: &quot;0x34e1e67726ccca66adad1c4d54baba739c7c52955a01b7cba29c3d8f2317f5e2&quot;
    deposit_count: 293
    execution_block_hash: &quot;0x5808234c115cc61500e2a564049a17037ee5108aec392d429f03f58ba8d16443&quot;
    execution_block_height: 294
- deposit_data:
    pubkey: &quot;0x8f9ec3c7b0f5793f3056fee53b16af2874bef12a90bd0ecf6282d55ce6ba70a07071df4e3861ad99da8753677a2a74a3&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa81d1bd6fb813b55c286bae7e79f9ad080e65865bc0c34f8309876e22f1db6e06b87abf4b0fbda1ade851d0914f8c4270d2abb19efd831a116a040180a9eae89daa1ef6a69748984c1b8029d33ed4e278d26226833a0d05762f94c389b758b83&quot;
  deposit_data_root: &quot;0xea2af2f7a4f8409ff112a26b16f36e6192581fd5c633f90b165668999c1f9e1e&quot;
  eth1_data:
    deposit_root: &quot;0x21ec4811b4490a5d9c97b40830607f18ed6decc77cafc3328b487ea076ec4520&quot;
    deposit_count: &quot;294&quot;
    block_hash: &quot;0xf86216620bf16f8591322c0b32fe4c594de559b382aae1c535be72771d8dba24&quot;
  block_height: 295
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0x0730794fdc9fa73177b77e150edf2e164ec8d1917f76a71e085eefdaf0bd3835&quot;
      - &quot;0x7bad1e86995476e6d8c7a8a05d659145ff02c84f1b0eac70e5964c395c14f8e3&quot;
    deposit_root: &quot;0x21ec4811b4490a5d9c97b40830607f18ed6decc77cafc3328b487ea076ec4520&quot;
    deposit_count: 294
    execution_block_hash: &quot;0xf86216620bf16f8591322c0b32fe4c594de559b382aae1c535be72771d8dba24&quot;
    execution_block_height: 295
- deposit_data:
    pubkey: &quot;0xb083923ec58581ce049677eb0df25ff6ea0e29938881a9e03ecedf4c7482ccd25dbd2f8a15d6bbdf8eca74a74f444e40&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa7ed5863f832a1b984ce9993b33cdded121815178c70538b0926a3f17452142ba546cb751861f739c4303940664348f908ab344bee4e62aacdf26d25ba25cb32b1269f3fd2defd2b740788f2000021c07f0ac20ed927745641f3ea74464ff433&quot;
  deposit_data_root: &quot;0x450d67be526c8cc2dc5b23a24ffbd79a03dc5b4e9685285e381e598bb478b958&quot;
  eth1_data:
    deposit_root: &quot;0x331ae72b1a07010b6967e88090dcf730d1c721b54900e636c7bcf23a4b511e7b&quot;
    deposit_count: &quot;295&quot;
    block_hash: &quot;0x5e382493002589f3487d5ef95d6933de04c0b65a592691966854d900eaf32f74&quot;
  block_height: 296
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0x0730794fdc9fa73177b77e150edf2e164ec8d1917f76a71e085eefdaf0bd3835&quot;
      - &quot;0x7bad1e86995476e6d8c7a8a05d659145ff02c84f1b0eac70e5964c395c14f8e3&quot;
      - &quot;0x450d67be526c8cc2dc5b23a24ffbd79a03dc5b4e9685285e381e598bb478b958&quot;
    deposit_root: &quot;0x331ae72b1a07010b6967e88090dcf730d1c721b54900e636c7bcf23a4b511e7b&quot;
    deposit_count: 295
    execution_block_hash: &quot;0x5e382493002589f3487d5ef95d6933de04c0b65a592691966854d900eaf32f74&quot;
    execution_block_height: 296
- deposit_data:
    pubkey: &quot;0xa41e4e990ba7effeb504f4f0c27924c90c76ec433f2cc59d65619ce9796b80db1b2a6c3fdcd3a3b5ae798c65433ff911&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa3eb87a76711659f7821c30c915d68c8853d948e1ca08da89c5f20b390f1c65feea7374c2040b3bbf9c6496af37afbaf09ef6a060d5370a06318053d845a4aaf99e82852a8ccb4dfab2ee3980f8cfda07b08dfdca5c15ce73a67fcd4d5979ca7&quot;
  deposit_data_root: &quot;0x056b0a462a8e8ab1f9cd2d1a3428e3a102de98b075968c605d95bb65dd516095&quot;
  eth1_data:
    deposit_root: &quot;0xc16e10784846d8fdd7bb158f065db835af24031e348baeae33ae24ede22ec3e1&quot;
    deposit_count: &quot;296&quot;
    block_hash: &quot;0x8ffaa2662024d089a5006527ba28bb380b041cc2e81e2421d4deaededb9d3d61&quot;
  block_height: 297
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0x5b1f9c36b45f9d1e8495781e9d8290f328e09b9ec8f382b801aa6354b25b2e27&quot;
    deposit_root: &quot;0xc16e10784846d8fdd7bb158f065db835af24031e348baeae33ae24ede22ec3e1&quot;
    deposit_count: 296
    execution_block_hash: &quot;0x8ffaa2662024d089a5006527ba28bb380b041cc2e81e2421d4deaededb9d3d61&quot;
    execution_block_height: 297
- deposit_data:
    pubkey: &quot;0x8fb481a72fde68d6b21d0f679bcf64c9986e88acd27874cdfb4d2ae7a84e7dac89ca6afd072bdc503b15342ddc899b94&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x83f4b1f8e47b6c688f1068e9ecfe223b53090656d44396b24f7192e6fd7cdfd66f96760b8fca2b01c57e0c01c323952008d6e33dbb0fbee95c36dda724fbecfb07dd99ce251bce32d22e2ce36bc45b9e59ffec6ac9aa2e67a94953ea1deab2c4&quot;
  deposit_data_root: &quot;0x8bc82d0cf82a2499dd2b717cfde2c3e68bfc128763e250a4fb50e3f0122accf8&quot;
  eth1_data:
    deposit_root: &quot;0x1add0cbc74e152fa595c6dc87e2d5df9699025429dc658682c635977d03fcd6a&quot;
    deposit_count: &quot;297&quot;
    block_hash: &quot;0xf305397aeec554ea12622d5b37c601710070c0f4856e2b0170856c55f80e07a9&quot;
  block_height: 298
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0x5b1f9c36b45f9d1e8495781e9d8290f328e09b9ec8f382b801aa6354b25b2e27&quot;
      - &quot;0x8bc82d0cf82a2499dd2b717cfde2c3e68bfc128763e250a4fb50e3f0122accf8&quot;
    deposit_root: &quot;0x1add0cbc74e152fa595c6dc87e2d5df9699025429dc658682c635977d03fcd6a&quot;
    deposit_count: 297
    execution_block_hash: &quot;0xf305397aeec554ea12622d5b37c601710070c0f4856e2b0170856c55f80e07a9&quot;
    execution_block_height: 298
- deposit_data:
    pubkey: &quot;0x9792ac6f48e8f90fdabf06dd862bfa48612c72685f259f7f69ce201889daf43e220bbe3795554d1973b497360b81311d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x83ed426c80869348bf799aece915aa4c3ecd715df0d83c443758db8d74be8dfec2707bb8cd41a65117b7f484998f59d715cca0f03903248374af59f3013d9a0ea7ec0dff855c632ad47c695186736c62ad52d3c0131f5227bd8d2a977e4b574f&quot;
  deposit_data_root: &quot;0x377acb0a185e15e235bb479f2c7a6eadcdebbe04e96282510656c1c8643c8f08&quot;
  eth1_data:
    deposit_root: &quot;0x90beacf75d211ca5fa19ea7a78d25c2e9a72a9b59652192d5b37368a66d7f71a&quot;
    deposit_count: &quot;298&quot;
    block_hash: &quot;0x141e6a356ffe9bce0d90886c27b5460df7ad03c69635cf28c3a3ffa99dd524b7&quot;
  block_height: 299
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0x5b1f9c36b45f9d1e8495781e9d8290f328e09b9ec8f382b801aa6354b25b2e27&quot;
      - &quot;0xc60a40ade74fa8bc78d964bb75dbe9e361b8468980dcf4ef30f5712a8e06f20a&quot;
    deposit_root: &quot;0x90beacf75d211ca5fa19ea7a78d25c2e9a72a9b59652192d5b37368a66d7f71a&quot;
    deposit_count: 298
    execution_block_hash: &quot;0x141e6a356ffe9bce0d90886c27b5460df7ad03c69635cf28c3a3ffa99dd524b7&quot;
    execution_block_height: 299
- deposit_data:
    pubkey: &quot;0x8db6b709638a90a292ecc760d425bd26855a8b67e34286987f3c6aefa0811573e106f54b088b3afa8436156fb36f783e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xae4ead5a15f81287a7c7c20d4265d95345637980d27bf0d8edfdb1d7ca2099c9283916e09eae340be93f7db49d76d89b19ae467cecc02bee4d8f47a82a9609db4ed4f5c915c910babbc35d885799b6d6e5e70b9025a6e2e192f8dabe61109028&quot;
  deposit_data_root: &quot;0xddc96174c52bb3bdd22b83e73bda24cafc7203e6166d0ede60c079a367d5ac08&quot;
  eth1_data:
    deposit_root: &quot;0x31dae0097efd30f99ca3f1582a55545fc31326f4046ce06adce7b926155b60b6&quot;
    deposit_count: &quot;299&quot;
    block_hash: &quot;0x34c74dd45b01879ff4a0508fefbf6fc9adccc408bffa5cfe13e68655115226e0&quot;
  block_height: 300
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0x5b1f9c36b45f9d1e8495781e9d8290f328e09b9ec8f382b801aa6354b25b2e27&quot;
      - &quot;0xc60a40ade74fa8bc78d964bb75dbe9e361b8468980dcf4ef30f5712a8e06f20a&quot;
      - &quot;0xddc96174c52bb3bdd22b83e73bda24cafc7203e6166d0ede60c079a367d5ac08&quot;
    deposit_root: &quot;0x31dae0097efd30f99ca3f1582a55545fc31326f4046ce06adce7b926155b60b6&quot;
    deposit_count: 299
    execution_block_hash: &quot;0x34c74dd45b01879ff4a0508fefbf6fc9adccc408bffa5cfe13e68655115226e0&quot;
    execution_block_height: 300
- deposit_data:
    pubkey: &quot;0x93ad251e308b778815f925a6de6b11bb7f3d4d8d710cafd66cab8be0b91ef0ada350c2ca2d8f5fbc3ff4f002445680f9&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa3cf73c28799277452db8bb4e7c5944f029c8228321a655325aac140baf67884f24dd459356818857341088afda6828b06149d514d5b2ff3caf8993ed07129b111798a35a9dc28f526752e6002cee205127893ceea458afb5da8698d0eb4902b&quot;
  deposit_data_root: &quot;0xa01227f9122459ac47d9a6b110e72f74ea18ae68b62ca95a0b76bb4166269eda&quot;
  eth1_data:
    deposit_root: &quot;0x8c2f6e57502350b5d9f26e44419267b541ad91471cab8d5db5ff4184f5bb33a0&quot;
    deposit_count: &quot;300&quot;
    block_hash: &quot;0x193c858804c50b4119d959c31820b38c2beb2bc36f0e0595213c4030cac59626&quot;
  block_height: 301
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0x5b1f9c36b45f9d1e8495781e9d8290f328e09b9ec8f382b801aa6354b25b2e27&quot;
      - &quot;0xb8f534205d4b218cd717bddf06a06cae872d995a165506cff2e8c12af6a71afa&quot;
    deposit_root: &quot;0x8c2f6e57502350b5d9f26e44419267b541ad91471cab8d5db5ff4184f5bb33a0&quot;
    deposit_count: 300
    execution_block_hash: &quot;0x193c858804c50b4119d959c31820b38c2beb2bc36f0e0595213c4030cac59626&quot;
    execution_block_height: 301
- deposit_data:
    pubkey: &quot;0xa31e15bea68f0f555e2eb0552f74bb78a755ee77e242799cfeb8a380507d994cf24f46fd86568f46c4ecc7ddcf359ba6&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb3e700ee6b7fcd21fe53dee2c22d4da8ca914be0adebfd496396edff50068679a17410d9afbcfffd5f6b0add9d2523e90cdf840ba008e4d58ebe9ebea0115305155c5d3f7b566cbde5f7dd511fef9d543c1fab467e91bac3d4a27ac9ad87957f&quot;
  deposit_data_root: &quot;0xdcf69aa4fa002dbef4af6017e7a178c9c553c68e3f3d9352563491ab58bd82b5&quot;
  eth1_data:
    deposit_root: &quot;0x7615cbc219a8c6a9fb950d887fd850185534967b2a5441902215e584dd2151a5&quot;
    deposit_count: &quot;301&quot;
    block_hash: &quot;0x79363266a5cff13e09297e640ced33e737db69fdc4e8a649939e36578099a9e3&quot;
  block_height: 302
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0x5b1f9c36b45f9d1e8495781e9d8290f328e09b9ec8f382b801aa6354b25b2e27&quot;
      - &quot;0xb8f534205d4b218cd717bddf06a06cae872d995a165506cff2e8c12af6a71afa&quot;
      - &quot;0xdcf69aa4fa002dbef4af6017e7a178c9c553c68e3f3d9352563491ab58bd82b5&quot;
    deposit_root: &quot;0x7615cbc219a8c6a9fb950d887fd850185534967b2a5441902215e584dd2151a5&quot;
    deposit_count: 301
    execution_block_hash: &quot;0x79363266a5cff13e09297e640ced33e737db69fdc4e8a649939e36578099a9e3&quot;
    execution_block_height: 302
- deposit_data:
    pubkey: &quot;0xafb329bae0ec756fd1be3ee1eac93550b77177d96558deeec2a6a131e35ccdee653189d4f5bb744f492371605c44a9bc&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x81839fd0a1d6bcb75751f1c9a3d3b2a8c7812c4e2933d52c0327d69ca7fea84c9ad7c1a4475c88e46d25baeacd41e4e60c5f3ea05c16ec768e011d41c0e3b2edac0d9ae16b4b410313470283ed4086634c080bb7e676493763c459c6d246e15a&quot;
  deposit_data_root: &quot;0x3d5f8d118ae4e4fca8223b2b819c1931cd041443d278b6823c9b4aea22bd57f7&quot;
  eth1_data:
    deposit_root: &quot;0xa80eedd04962726c155bf13aa99c6c56457c99e3d4533ab74a4abe2e961fe9f8&quot;
    deposit_count: &quot;302&quot;
    block_hash: &quot;0x1c6191f59c7eb6f4c8cc5837ccd23de7600c2dffb62c9e1133248baf3cc4e363&quot;
  block_height: 303
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0x5b1f9c36b45f9d1e8495781e9d8290f328e09b9ec8f382b801aa6354b25b2e27&quot;
      - &quot;0xb8f534205d4b218cd717bddf06a06cae872d995a165506cff2e8c12af6a71afa&quot;
      - &quot;0xa93353e7b0d909e8d19d5d6c466cae15e8e5f2b929758e88d8c35f6ac180c0c2&quot;
    deposit_root: &quot;0xa80eedd04962726c155bf13aa99c6c56457c99e3d4533ab74a4abe2e961fe9f8&quot;
    deposit_count: 302
    execution_block_hash: &quot;0x1c6191f59c7eb6f4c8cc5837ccd23de7600c2dffb62c9e1133248baf3cc4e363&quot;
    execution_block_height: 303
- deposit_data:
    pubkey: &quot;0xb62df9c59793d5e3a553e9f5b9da4c928105e221898f11847e7ec9a60c091a1a56e0f141d64bb5bac13d424a49798917&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x822390897c4b8d9e0f2d0868afe9cfe5efc14f7290a48717071de84200fdf96d5f4aecf2c577d003f4af4c4f59bbbfc802166746f52794eecdc656c4ec845085d053c4d021d45c639567e24825bbc60572747900e54452fb052f45895ed97e14&quot;
  deposit_data_root: &quot;0x888daeb2cf145994cbd3f25806c306082dd402d4b4420f0817c5a5a19132cb36&quot;
  eth1_data:
    deposit_root: &quot;0x334dbf7b9b0cd5d22f79c7dca388d3baf541e430bdd31883fd7402852febf29a&quot;
    deposit_count: &quot;303&quot;
    block_hash: &quot;0x42bc399b54a8e566243c3ba4e2e1ceeca8eea2b7cd84462b8814229d9f459796&quot;
  block_height: 304
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0x5b1f9c36b45f9d1e8495781e9d8290f328e09b9ec8f382b801aa6354b25b2e27&quot;
      - &quot;0xb8f534205d4b218cd717bddf06a06cae872d995a165506cff2e8c12af6a71afa&quot;
      - &quot;0xa93353e7b0d909e8d19d5d6c466cae15e8e5f2b929758e88d8c35f6ac180c0c2&quot;
      - &quot;0x888daeb2cf145994cbd3f25806c306082dd402d4b4420f0817c5a5a19132cb36&quot;
    deposit_root: &quot;0x334dbf7b9b0cd5d22f79c7dca388d3baf541e430bdd31883fd7402852febf29a&quot;
    deposit_count: 303
    execution_block_hash: &quot;0x42bc399b54a8e566243c3ba4e2e1ceeca8eea2b7cd84462b8814229d9f459796&quot;
    execution_block_height: 304
- deposit_data:
    pubkey: &quot;0x810ab821a4d4a0707e0f70eb7dbf78a528e2503749e462fda69969ef1aeee9ad2b8d37c77056bdb0feecdf206313d2e9&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8899dcaccd1c167c69c6e4d5ab42f03f5a6e9bf1a1d664dbf07fac6de06b59e651147cf78a2924acedb33944a8d11d451189e78c32a646260d0401ebe79dda5c35d00688cc0d024a2f12248b47fe5d4a7a04fdd420aca97e85f86497998f66fc&quot;
  deposit_data_root: &quot;0x0c6eefdd540468d0e9e72aa9c1394441e05788e7f0998cf6f5157466fdde05d2&quot;
  eth1_data:
    deposit_root: &quot;0x3fddb8ccad286ee5c85d0e2d851ee3d45dd7b03bef1a980c60ba49166465af93&quot;
    deposit_count: &quot;304&quot;
    block_hash: &quot;0xb0338e285f4f8d5621dfb6894d21095a58cc89d5d8b0e574edf8efe7ca30ad26&quot;
  block_height: 305
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0xd332180e48743692efc13e599dedfd063f73963ababcf12ee1dbcddab376bcd5&quot;
    deposit_root: &quot;0x3fddb8ccad286ee5c85d0e2d851ee3d45dd7b03bef1a980c60ba49166465af93&quot;
    deposit_count: 304
    execution_block_hash: &quot;0xb0338e285f4f8d5621dfb6894d21095a58cc89d5d8b0e574edf8efe7ca30ad26&quot;
    execution_block_height: 305
- deposit_data:
    pubkey: &quot;0x80f23973b414503e2ba0a53f67463f332b23fe5fd5466f1a770a6d548fdf4421d9370ae890b54be1cbeacb7a9e31d166&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x85a60518498341146050685aefe04587f4f9cbb7210bee705e2018c351d358d357330ca0a81da886788228eb0a3688d202024a72a5c378ccbba3c7fc7fbfcf84d630c0a8cac56ee029b8348d83b6b73b1e7019dadd34ed0272e7e6f0ea8b36b5&quot;
  deposit_data_root: &quot;0x7562d64a4e031ff5e46a3319de670de403d8b14c256ade2aa6c3f69b2e0ae077&quot;
  eth1_data:
    deposit_root: &quot;0x567a327092d5109af0a5b29ad3c445d7444dd00fa1e34b678db5e04b48a54917&quot;
    deposit_count: &quot;305&quot;
    block_hash: &quot;0x30f7bf7c4b84b1e0e14234732b33fd5eaa755838404fd7a9558a0d52b29a072d&quot;
  block_height: 306
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0xd332180e48743692efc13e599dedfd063f73963ababcf12ee1dbcddab376bcd5&quot;
      - &quot;0x7562d64a4e031ff5e46a3319de670de403d8b14c256ade2aa6c3f69b2e0ae077&quot;
    deposit_root: &quot;0x567a327092d5109af0a5b29ad3c445d7444dd00fa1e34b678db5e04b48a54917&quot;
    deposit_count: 305
    execution_block_hash: &quot;0x30f7bf7c4b84b1e0e14234732b33fd5eaa755838404fd7a9558a0d52b29a072d&quot;
    execution_block_height: 306
- deposit_data:
    pubkey: &quot;0x95ce181db92ea8695c006896d2bb9faada9e157a896cf06b5466c304ccc6b09f7b8b10044b9b0689265ee97a6388dcd7&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb5911e4df04e991fe79576339db9eabcdaa7a691fcf6a07e86666b81f4176fb2cf7bdcd93f7512f3d8a0bef4725c30680e6ee5439ac60e013ea0cdfc8c11c0a044f0a64c7393bd12927b9c51b45b2862311ca1169fcd83b798c1653d1131d98d&quot;
  deposit_data_root: &quot;0x88d50a861161dc2f5a2fd41cc69eca91e1e251d29224d3e813937860204f93f8&quot;
  eth1_data:
    deposit_root: &quot;0x3e8177de3da30a03e473faa90d01ef262563526c5a28c17d22c4bba44430eef5&quot;
    deposit_count: &quot;306&quot;
    block_hash: &quot;0x0168559f9953fd501450a3ff14cd7b48b0b75663a319abd9766d4d9fc514a2e0&quot;
  block_height: 307
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0xd332180e48743692efc13e599dedfd063f73963ababcf12ee1dbcddab376bcd5&quot;
      - &quot;0x2685dc940c27a8289d56e5cf4246afc27ad50baf0abef93caa8e379dcb39b41e&quot;
    deposit_root: &quot;0x3e8177de3da30a03e473faa90d01ef262563526c5a28c17d22c4bba44430eef5&quot;
    deposit_count: 306
    execution_block_hash: &quot;0x0168559f9953fd501450a3ff14cd7b48b0b75663a319abd9766d4d9fc514a2e0&quot;
    execution_block_height: 307
- deposit_data:
    pubkey: &quot;0x8e322c2995e2472a7981466eb4b890d753b2016798cf640ed4b7ea7a3d53e5644361f404c5eec4baa1a55da860b7981c&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xaeb741e937c13a7f8dfa2b7603c902719786f247a25b0eedf6327921d09486afb8ef66c30b232d6032d4ab5475dd54f407c702a09cad1bfd675ff57f44d100a996af265c6c275c69f0593da7832a81cad4417b82fbfc6a088482b3aa1d856a4f&quot;
  deposit_data_root: &quot;0xc275ba69111f046f57da439d9b3d3e52a7124328b5909b40655e1afe75bfbbf1&quot;
  eth1_data:
    deposit_root: &quot;0xf228d693edc9dde11a393ab4191a7b47ad4eabe0839bba4fcdc6a63cda49f729&quot;
    deposit_count: &quot;307&quot;
    block_hash: &quot;0x6d3facdb3a92f45bf9f2d65576346739d524e703d4057c1d8474b3fe9de8667f&quot;
  block_height: 308
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0xd332180e48743692efc13e599dedfd063f73963ababcf12ee1dbcddab376bcd5&quot;
      - &quot;0x2685dc940c27a8289d56e5cf4246afc27ad50baf0abef93caa8e379dcb39b41e&quot;
      - &quot;0xc275ba69111f046f57da439d9b3d3e52a7124328b5909b40655e1afe75bfbbf1&quot;
    deposit_root: &quot;0xf228d693edc9dde11a393ab4191a7b47ad4eabe0839bba4fcdc6a63cda49f729&quot;
    deposit_count: 307
    execution_block_hash: &quot;0x6d3facdb3a92f45bf9f2d65576346739d524e703d4057c1d8474b3fe9de8667f&quot;
    execution_block_height: 308
- deposit_data:
    pubkey: &quot;0xb6f68789c60d1348b5e24bd6b7ccc18500be7b6ef0099895547a83f63eca37ca4f26fa3517d5bc71bc4a2fb186149179&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8888f11eaefbd7bee2d93a8713415d0452b6cdf794f5095a7f4b7913556b17e969d6b1137048e2fa94af582d4fea848e185cd3df47f5071d49ec86d21389443e4771f31fc466c3bdf211cca260f677769c90d5493b6a0e8a230c455a9f6539cd&quot;
  deposit_data_root: &quot;0xc5256c0995975cc0953677c36413969b40e96b3921007fd975bdb7d5cc883d5c&quot;
  eth1_data:
    deposit_root: &quot;0x301dd53110abda16d11eee1d46ccbc839f8e9adc1c0f0592aa010242f123397f&quot;
    deposit_count: &quot;308&quot;
    block_hash: &quot;0x4c2a9c39824275f99a4ef57cff7778b6fb793cd493d7e96da426f9f5c50b19f0&quot;
  block_height: 309
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0xd332180e48743692efc13e599dedfd063f73963ababcf12ee1dbcddab376bcd5&quot;
      - &quot;0x428b54bb40a87f83657cfb7998905b4deaad55f2d092f13b0365b11847bd984b&quot;
    deposit_root: &quot;0x301dd53110abda16d11eee1d46ccbc839f8e9adc1c0f0592aa010242f123397f&quot;
    deposit_count: 308
    execution_block_hash: &quot;0x4c2a9c39824275f99a4ef57cff7778b6fb793cd493d7e96da426f9f5c50b19f0&quot;
    execution_block_height: 309
- deposit_data:
    pubkey: &quot;0xb50d3fc8e36d2f2eb544c16b959b500160c2b176298e4e16ae5d928856406c86605b8ea6bd802ca1a2d1c9210d6bce61&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa88f8ea391dcba3fbbf6a4ffb58bcb8135d0001207c3656f671fab5669903a3d1fbf1150e856abd0c2d180f5518205d707692aa6a239ab2bea39338b11b0a04cb078bc61fe966feb25b905b1629067a6107bb858393339002119592d03d60395&quot;
  deposit_data_root: &quot;0x768bb277eec0d74fe504242f61cd37bd63a76417f860ea154d89bf1e9209318e&quot;
  eth1_data:
    deposit_root: &quot;0x03403e71434239fc6cf3c51e014029b6dce79899d189cb789ca41ec8c76870df&quot;
    deposit_count: &quot;309&quot;
    block_hash: &quot;0x142755a334e7b0f2ecd19714918edfc8fc49e591dbe27a072f98b929914795c2&quot;
  block_height: 310
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0xd332180e48743692efc13e599dedfd063f73963ababcf12ee1dbcddab376bcd5&quot;
      - &quot;0x428b54bb40a87f83657cfb7998905b4deaad55f2d092f13b0365b11847bd984b&quot;
      - &quot;0x768bb277eec0d74fe504242f61cd37bd63a76417f860ea154d89bf1e9209318e&quot;
    deposit_root: &quot;0x03403e71434239fc6cf3c51e014029b6dce79899d189cb789ca41ec8c76870df&quot;
    deposit_count: 309
    execution_block_hash: &quot;0x142755a334e7b0f2ecd19714918edfc8fc49e591dbe27a072f98b929914795c2&quot;
    execution_block_height: 310
- deposit_data:
    pubkey: &quot;0xa72612ca8f454d74489512d0637191bcac72124f4111f7cd52de8920ee3ea804ee895201ed74527407159220ed00712b&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x988ee0d14e460e614b4db31aa0edce326450745ae33898a67f59279ca125a60a420e3fef3440be1502b173cf3b6cf75f16e427739cc02e79804a5533453b752962eb695656c5f7eadb3c13588762fcc743978bd3d6ccd4feeadedbb9bf2b989d&quot;
  deposit_data_root: &quot;0x0275c66e7493040447a4a1ce248051418acdc6c62cbe2e5de0a6ab4737f1c6c7&quot;
  eth1_data:
    deposit_root: &quot;0x80a4bb6bffb48e9c359242c260546b21e0b52020788e5a30a6c06a4ac8728d4f&quot;
    deposit_count: &quot;310&quot;
    block_hash: &quot;0x626aa2fd2714dfff5d15b35def25420116d8ccb50a602513f9596ed98e06040b&quot;
  block_height: 311
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0xd332180e48743692efc13e599dedfd063f73963ababcf12ee1dbcddab376bcd5&quot;
      - &quot;0x428b54bb40a87f83657cfb7998905b4deaad55f2d092f13b0365b11847bd984b&quot;
      - &quot;0xeb3f38ea9f413e0b73256ebd08ed8be2b639aced165911e48656e44330d03d5a&quot;
    deposit_root: &quot;0x80a4bb6bffb48e9c359242c260546b21e0b52020788e5a30a6c06a4ac8728d4f&quot;
    deposit_count: 310
    execution_block_hash: &quot;0x626aa2fd2714dfff5d15b35def25420116d8ccb50a602513f9596ed98e06040b&quot;
    execution_block_height: 311
- deposit_data:
    pubkey: &quot;0xabdcd975ccfab19f10d7ec535f7c0e9e269a34f5eeb653d15ee0505f383274e5a20b3b71bdba0f369e36cea0eae1f5b1&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x80039f2345c88aeb006695982d70543e37c8cf5a1622b589326d215ff2687396eba8797e896c590878aff20bcdfeecdb0e4e9534df8429e3cc8c585d0a1821c9c9378d4f2335f4dacb7d59794539c7d77306da1f065a126593bfcce78465d8e9&quot;
  deposit_data_root: &quot;0x12463230892e22766c8e4be4bde2f242553e7b213843ef3cb46c4ef6612cab71&quot;
  eth1_data:
    deposit_root: &quot;0xa0dffba4c6f35f9ce7e1e951a12c523651b6aa4bfb17e2323cf26324cce04330&quot;
    deposit_count: &quot;311&quot;
    block_hash: &quot;0xfb60531376af074a51de3a1bbceb7df9fab77acaca749ee4f779abf774252092&quot;
  block_height: 312
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0xd332180e48743692efc13e599dedfd063f73963ababcf12ee1dbcddab376bcd5&quot;
      - &quot;0x428b54bb40a87f83657cfb7998905b4deaad55f2d092f13b0365b11847bd984b&quot;
      - &quot;0xeb3f38ea9f413e0b73256ebd08ed8be2b639aced165911e48656e44330d03d5a&quot;
      - &quot;0x12463230892e22766c8e4be4bde2f242553e7b213843ef3cb46c4ef6612cab71&quot;
    deposit_root: &quot;0xa0dffba4c6f35f9ce7e1e951a12c523651b6aa4bfb17e2323cf26324cce04330&quot;
    deposit_count: 311
    execution_block_hash: &quot;0xfb60531376af074a51de3a1bbceb7df9fab77acaca749ee4f779abf774252092&quot;
    execution_block_height: 312
- deposit_data:
    pubkey: &quot;0x83dbae1b08eea5bf0a89eb1d0b61e9e0c4e1142610ac8d88d9f3bdef550e3264b54bd47052d481738b92ffbcf6e36f67&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xabec6694b693a184bc5720f1d0c4d8dd8630609076af52ae7fa62c04fa7df7cc3c793d1eb776199a8755e861c9bd35410c3e225f31912cd2fb21694fcf444db989aa5e4eacc3434ac4ecb894fd4f203f1514e3034e328cf5d174ee896be4e26e&quot;
  deposit_data_root: &quot;0x627fbf478b052d8b09b47b17598cb372ef316a9e2df9fee7e04639f9f23a9060&quot;
  eth1_data:
    deposit_root: &quot;0x5c072d54c707ccbcd880507073f57cc01b6f162aea0a100c4523deb9508f357a&quot;
    deposit_count: &quot;312&quot;
    block_hash: &quot;0x4a09a6f7522d4793a3c0f56fd21714035a19d37f18d975a218b34952df576c9b&quot;
  block_height: 313
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0xd332180e48743692efc13e599dedfd063f73963ababcf12ee1dbcddab376bcd5&quot;
      - &quot;0xb1125c174cf98e6ea57e02bfb8108d15da2cc5c7f1d49167551a9bf8bc37a7df&quot;
    deposit_root: &quot;0x5c072d54c707ccbcd880507073f57cc01b6f162aea0a100c4523deb9508f357a&quot;
    deposit_count: 312
    execution_block_hash: &quot;0x4a09a6f7522d4793a3c0f56fd21714035a19d37f18d975a218b34952df576c9b&quot;
    execution_block_height: 313
- deposit_data:
    pubkey: &quot;0xb628c432d9d76dd6483ed50938fc4c369bd24b6e3c1a41cc4620f7b513148fb242a76c7577f8766a14770ae597c36aa4&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x90be83d06747ca26fd1d38a4847a9fbb02f2433ba940b51f364ca9bacb3924a2ffbc0d6e23366eeccfafaed746e29bce12589c80fb49db1b11df5da16a75aa4605b571efd142c59c07e0607cbbf6c16d989461a515e2a44b4f3c4c561fba0505&quot;
  deposit_data_root: &quot;0x74cc9ddae3f91c1b4bd274ed0ed14c29daaba30aed1632521ef60ca123ce2d09&quot;
  eth1_data:
    deposit_root: &quot;0x7789482c357af66154948684754c641d23d0d2556cbe3f017a9680aabb46934e&quot;
    deposit_count: &quot;313&quot;
    block_hash: &quot;0xad05a4ad4a1dd8968ce13df5c3a6fed1f0899849372b26285fc4288bab0e2b65&quot;
  block_height: 314
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0xd332180e48743692efc13e599dedfd063f73963ababcf12ee1dbcddab376bcd5&quot;
      - &quot;0xb1125c174cf98e6ea57e02bfb8108d15da2cc5c7f1d49167551a9bf8bc37a7df&quot;
      - &quot;0x74cc9ddae3f91c1b4bd274ed0ed14c29daaba30aed1632521ef60ca123ce2d09&quot;
    deposit_root: &quot;0x7789482c357af66154948684754c641d23d0d2556cbe3f017a9680aabb46934e&quot;
    deposit_count: 313
    execution_block_hash: &quot;0xad05a4ad4a1dd8968ce13df5c3a6fed1f0899849372b26285fc4288bab0e2b65&quot;
    execution_block_height: 314
- deposit_data:
    pubkey: &quot;0xa36425294d9fe4f803acb3ce90947ea5f20cb1c06c4899b80129d8fd7e491f0128d86f98aa987a1578ec1244ae3d5f17&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb19797920d1e40e85dafd881d1193e1b347dc252974d55d0187abfd6e0f2a195746fc24527529581c1f59f3d3bea4d2d0ef3080d515468c273d216711cb3b618d9f7f25f7da3ef789d060cb1811a747a3ec0ab93c149bb8656825451426dc668&quot;
  deposit_data_root: &quot;0x955a4d69a457b02106c01614769dfb29fe7d5c6672da037a22e16619edb5c06e&quot;
  eth1_data:
    deposit_root: &quot;0x627b60a6d46949a3c8dfde03b024118cf57f0b8e3590ab48c2523715e48b9011&quot;
    deposit_count: &quot;314&quot;
    block_hash: &quot;0x2ddf1d0ff89d425c64c78796ae3826cd030caa6ae70fbaa29c24a0d81abcdfb3&quot;
  block_height: 315
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0xd332180e48743692efc13e599dedfd063f73963ababcf12ee1dbcddab376bcd5&quot;
      - &quot;0xb1125c174cf98e6ea57e02bfb8108d15da2cc5c7f1d49167551a9bf8bc37a7df&quot;
      - &quot;0x69106b127afcf2e4ddba6429779d04030f20a0ae7eab086bb65958c789430cd4&quot;
    deposit_root: &quot;0x627b60a6d46949a3c8dfde03b024118cf57f0b8e3590ab48c2523715e48b9011&quot;
    deposit_count: 314
    execution_block_hash: &quot;0x2ddf1d0ff89d425c64c78796ae3826cd030caa6ae70fbaa29c24a0d81abcdfb3&quot;
    execution_block_height: 315
- deposit_data:
    pubkey: &quot;0xac55318cef8cd8f015f2493d09be7556066e235f618971a3325368f3deba029bae60fba85171762827f1f70c6883a467&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8b4f261038c4bff210d1a0925059e46cd0d830b16b6a20da2a8ac9bdde1239f15b21d20550fd5d1878977bf0e0358fec155a9cbd51112d9ecaabaa5d3a56100afe4f18a3a0ade34698d2e84e52e164fe83c4b1140ad4a6d048a09e658c57f8b0&quot;
  deposit_data_root: &quot;0x7dbeb694af44e130ec3a9390893a798e86e787ed494bacfc10a3ef49d8e85889&quot;
  eth1_data:
    deposit_root: &quot;0xc8cc34185cb292295e96bbb5ab092b69eacb7984aebe7f0d88ae077aa6c71e20&quot;
    deposit_count: &quot;315&quot;
    block_hash: &quot;0x48396fede67f0d87fdb841ae3f8dd588552fc1b43141ff5c2dae2f143a305a65&quot;
  block_height: 316
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0xd332180e48743692efc13e599dedfd063f73963ababcf12ee1dbcddab376bcd5&quot;
      - &quot;0xb1125c174cf98e6ea57e02bfb8108d15da2cc5c7f1d49167551a9bf8bc37a7df&quot;
      - &quot;0x69106b127afcf2e4ddba6429779d04030f20a0ae7eab086bb65958c789430cd4&quot;
      - &quot;0x7dbeb694af44e130ec3a9390893a798e86e787ed494bacfc10a3ef49d8e85889&quot;
    deposit_root: &quot;0xc8cc34185cb292295e96bbb5ab092b69eacb7984aebe7f0d88ae077aa6c71e20&quot;
    deposit_count: 315
    execution_block_hash: &quot;0x48396fede67f0d87fdb841ae3f8dd588552fc1b43141ff5c2dae2f143a305a65&quot;
    execution_block_height: 316
- deposit_data:
    pubkey: &quot;0x9966dc1de264da86652de12f70b4d6c7271026be0b081797589ba126108809b6264e2ec18cd59e90dd2c639bcd9986c2&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x97dd0583026f23df048ceccb8815d9ae93a5a61cc8ae0e57ef7bee0e0c16f146ba1e0b31c5490f61697c83dd8eabab7f025d724669389df5fcf1abc54f0d7715885d5db3c0f2dda0ecf1ec51fcbf613a9531894f9bec308782b73441a1f29ad3&quot;
  deposit_data_root: &quot;0x0f9245219098e059529bd695cb6a8409d6a7b771146e799ea918c4bc4778aaac&quot;
  eth1_data:
    deposit_root: &quot;0xd275e61f8ffd78a24684a3e46425d38e6dffa2babf29bbf98d3521ef0d6891e4&quot;
    deposit_count: &quot;316&quot;
    block_hash: &quot;0xb4bd7e404339b1e80030772dc8b8f1721d29b9b31516b26eb094eac84d8f36d1&quot;
  block_height: 317
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0xd332180e48743692efc13e599dedfd063f73963ababcf12ee1dbcddab376bcd5&quot;
      - &quot;0xb1125c174cf98e6ea57e02bfb8108d15da2cc5c7f1d49167551a9bf8bc37a7df&quot;
      - &quot;0x587c330aecf776f443ed580dc13abd4d0a36e4f8617e25366dce8a28e796d9e2&quot;
    deposit_root: &quot;0xd275e61f8ffd78a24684a3e46425d38e6dffa2babf29bbf98d3521ef0d6891e4&quot;
    deposit_count: 316
    execution_block_hash: &quot;0xb4bd7e404339b1e80030772dc8b8f1721d29b9b31516b26eb094eac84d8f36d1&quot;
    execution_block_height: 317
- deposit_data:
    pubkey: &quot;0xb5a83ace1a9e683361435bb484295c11e371316800c073c8beaf1ee1900d5589966ac8266ee11b10b24f671231584302&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9029f10262639dc7a78130c1e0d924531a0939ce02c93df4171d9bda8a055dd270588fb54bc87c0a19a8ae1a3b93f02d1471907debb2c43e052a2bc6c71dc80751c96e46ecdb6e64ee5dbd86669b821e4fb7ef1a863af73a25207391e92c2f15&quot;
  deposit_data_root: &quot;0x2eea6ad287847510e3abaacdd5d8b21bf4c3cb317cee848b5150d76c7eee2326&quot;
  eth1_data:
    deposit_root: &quot;0xf7814cef15936b64805475bca92a6a37105312c8fdb4b6088bbf8d02aaf03a78&quot;
    deposit_count: &quot;317&quot;
    block_hash: &quot;0xb1baae047525e7438d4e06c776b9c14549a2bb0539275ce2d43a54605802105a&quot;
  block_height: 318
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0xd332180e48743692efc13e599dedfd063f73963ababcf12ee1dbcddab376bcd5&quot;
      - &quot;0xb1125c174cf98e6ea57e02bfb8108d15da2cc5c7f1d49167551a9bf8bc37a7df&quot;
      - &quot;0x587c330aecf776f443ed580dc13abd4d0a36e4f8617e25366dce8a28e796d9e2&quot;
      - &quot;0x2eea6ad287847510e3abaacdd5d8b21bf4c3cb317cee848b5150d76c7eee2326&quot;
    deposit_root: &quot;0xf7814cef15936b64805475bca92a6a37105312c8fdb4b6088bbf8d02aaf03a78&quot;
    deposit_count: 317
    execution_block_hash: &quot;0xb1baae047525e7438d4e06c776b9c14549a2bb0539275ce2d43a54605802105a&quot;
    execution_block_height: 318
- deposit_data:
    pubkey: &quot;0x8428f1acb3bf75a11ca3ff7b9fcb2af1f0c43ae22f08d4ceb586c96f97f5d999273739d348900e2424cd375e5ef68f35&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb7a7faad5149b6e8b901414c37b01b5955033c7b7b29aab827b29cdd0a7bb32bcaebe1c67bdc1de99a972cfa52defdf518084a465c3804241e9d3915b441a8a108770f557e5b372ec2f4d7bb127b03585ce8ea85ab35506c51fbdd91ac109403&quot;
  deposit_data_root: &quot;0x37f7ed384f323053073d09ba424f7fcba44ae6b1f50464f210cf880df9ec4e8c&quot;
  eth1_data:
    deposit_root: &quot;0xf1b373962ed896fb473e2e0625acad818126834046cd4f36d43ef3c3fe15a589&quot;
    deposit_count: &quot;318&quot;
    block_hash: &quot;0xe756598b26a44670dfd997e1be73332113f9605d5d8d7f07ee3162f04d72ccd1&quot;
  block_height: 319
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0xd332180e48743692efc13e599dedfd063f73963ababcf12ee1dbcddab376bcd5&quot;
      - &quot;0xb1125c174cf98e6ea57e02bfb8108d15da2cc5c7f1d49167551a9bf8bc37a7df&quot;
      - &quot;0x587c330aecf776f443ed580dc13abd4d0a36e4f8617e25366dce8a28e796d9e2&quot;
      - &quot;0xfef52200f08b898e7c1909fe36e281e60093f925aa8400431e6f2fad81571ce1&quot;
    deposit_root: &quot;0xf1b373962ed896fb473e2e0625acad818126834046cd4f36d43ef3c3fe15a589&quot;
    deposit_count: 318
    execution_block_hash: &quot;0xe756598b26a44670dfd997e1be73332113f9605d5d8d7f07ee3162f04d72ccd1&quot;
    execution_block_height: 319
- deposit_data:
    pubkey: &quot;0x8e73eafaa8fb6863473e55ef578c4764d9330996a62132a9329ab43f2a45ef2e68637cf48f674c8a0d127d9fb2738229&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x93dd39078da197a9ed00edf9ddff70017afad6b5cf9c9c3eb139bd61b362152c6d1d2bfce66fb93445eef99d2ddbbd041371aa6178eeb511229633be0e31fd692628a383b42e11a3e8a219c66bf15942c34658c1cffe86b97857145b0cf14f8d&quot;
  deposit_data_root: &quot;0xaa707e0428d7847f2f87e9dd478d34b093aa50c6bd025d7152f7fc48b5e61f5f&quot;
  eth1_data:
    deposit_root: &quot;0x24873485c0d733699f5309721201310f38e8e8a3fdd5c63dcab7f918a360e9a7&quot;
    deposit_count: &quot;319&quot;
    block_hash: &quot;0x703e8869ebd982b635b6f7f298cddff7ee58d5f8d9518c80c0d5aa0cd5bea3df&quot;
  block_height: 320
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0x22c8f83b80ba6d15c5d143935e2decb02783c33299c81a81495369e44fd7f121&quot;
      - &quot;0xd332180e48743692efc13e599dedfd063f73963ababcf12ee1dbcddab376bcd5&quot;
      - &quot;0xb1125c174cf98e6ea57e02bfb8108d15da2cc5c7f1d49167551a9bf8bc37a7df&quot;
      - &quot;0x587c330aecf776f443ed580dc13abd4d0a36e4f8617e25366dce8a28e796d9e2&quot;
      - &quot;0xfef52200f08b898e7c1909fe36e281e60093f925aa8400431e6f2fad81571ce1&quot;
      - &quot;0xaa707e0428d7847f2f87e9dd478d34b093aa50c6bd025d7152f7fc48b5e61f5f&quot;
    deposit_root: &quot;0x24873485c0d733699f5309721201310f38e8e8a3fdd5c63dcab7f918a360e9a7&quot;
    deposit_count: 319
    execution_block_hash: &quot;0x703e8869ebd982b635b6f7f298cddff7ee58d5f8d9518c80c0d5aa0cd5bea3df&quot;
    execution_block_height: 320
- deposit_data:
    pubkey: &quot;0xae451c6d18b7a14585dc96423f078be6b46742dde9be4d52907fff934956ebb2332e82c66cc2354eeb2da821e80ab7bb&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x89bb72ea77d8cf12f08050fe005f9da2e6d31b5348ec1e6e7b46e1084664c5b2f486c7c44773df37ecbdf1ab7c3f86e00fc35ebd2f4d470d929deda82847570be28c6191631235ce4901ea75920638210cdc92f2776889addfefdc77023ec196&quot;
  deposit_data_root: &quot;0x7407798bee346eb5f23e00cdc0fbf7fddfbc35a0ab4c6573296cc0d58fe5dbb3&quot;
  eth1_data:
    deposit_root: &quot;0x2b537afcf4a0b123429379355ab08f2ed8e1f5a15311d37e6dfdb7436d78bf87&quot;
    deposit_count: &quot;320&quot;
    block_hash: &quot;0x4e38625114a763d73cb04258b94c92eda5b6eee0507e18e9f4b562cbfb2060e6&quot;
  block_height: 321
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
    deposit_root: &quot;0x2b537afcf4a0b123429379355ab08f2ed8e1f5a15311d37e6dfdb7436d78bf87&quot;
    deposit_count: 320
    execution_block_hash: &quot;0x4e38625114a763d73cb04258b94c92eda5b6eee0507e18e9f4b562cbfb2060e6&quot;
    execution_block_height: 321
- deposit_data:
    pubkey: &quot;0x953ecb430dfe4f91510dbb8166f07a557881c19112e41a8b1b8b0aa2c3d95c061cdff951044255a3e4df6f529302beff&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x90650885698e776deaeb845e2582dc5a60770c20f08563c429ee2e6657d01e4ae4e0a6464e9669341f3b04f64846a02f05b00b950fb4c5b10363582bce2ac313ec4534758bc293b3b9eab0149217e45b761952b6a894e3f42226d9392d33219a&quot;
  deposit_data_root: &quot;0xc978fe6c6f919724950edef3008541909ddc2965bf9bdd297aa98ff6760919c9&quot;
  eth1_data:
    deposit_root: &quot;0x0d9593241269b53b9aab5168a1db67f2ac6afb5e1811ca34627e5f510fa47c27&quot;
    deposit_count: &quot;321&quot;
    block_hash: &quot;0x101e4774d651227e02db01e67dd883d7ecfa1762fc5773639bdec3394fec49b8&quot;
  block_height: 322
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0xc978fe6c6f919724950edef3008541909ddc2965bf9bdd297aa98ff6760919c9&quot;
    deposit_root: &quot;0x0d9593241269b53b9aab5168a1db67f2ac6afb5e1811ca34627e5f510fa47c27&quot;
    deposit_count: 321
    execution_block_hash: &quot;0x101e4774d651227e02db01e67dd883d7ecfa1762fc5773639bdec3394fec49b8&quot;
    execution_block_height: 322
- deposit_data:
    pubkey: &quot;0xae629cdd3ee2278a8993feb4e163a9127c4a09857981704fad31e3fbf2e7668136f2943987c7b5619d7e362d1bf9d9ee&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa4700ecbc23a35301973959072651da1963b1ec856c7d210e4bf165d7a306c501b9e31fa34e73b4001a1ab3a9b0acdaa0c62ba65f79e3ccfeebee512fdf980dc937a1c34a59bf67f323de0753ffc974ac8047948d924cd9204827b0587fef031&quot;
  deposit_data_root: &quot;0xa35ac1d1af9eab97f2679f3dfaef4a934ab6de575cadb245a45d754ff1c696df&quot;
  eth1_data:
    deposit_root: &quot;0xe3ab2d88fbc1cf4b39a86b71ea1d020c2d8231c69cc6d6eb2523c08b7fba9426&quot;
    deposit_count: &quot;322&quot;
    block_hash: &quot;0xc581458176fa41f0363a1ca199b1926a761489bf6dfacfa6cecbecffac82995a&quot;
  block_height: 323
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x909fdc4a762e835a5b890dc4b1c41ca41b65df75770ac25537840d618375a2b5&quot;
    deposit_root: &quot;0xe3ab2d88fbc1cf4b39a86b71ea1d020c2d8231c69cc6d6eb2523c08b7fba9426&quot;
    deposit_count: 322
    execution_block_hash: &quot;0xc581458176fa41f0363a1ca199b1926a761489bf6dfacfa6cecbecffac82995a&quot;
    execution_block_height: 323
- deposit_data:
    pubkey: &quot;0x963564994c2f8935ab03230c47dbd3596ca372a892a616c28ed80a582b9ca4a43e6ef58cd2fb2a3f3c03ac02eb272a82&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa470adad0a49fb8d863a31f7a942901ad76014898fb519d0df83215bf4df02db3348d42ffd4dd12c8e2ac0b421994e1b00325ccecfdc0ee8319fa5c135df27fdca2295568890a024178ec4c4b60fe9354c384792f0e61c8949461c8f0f211d19&quot;
  deposit_data_root: &quot;0x2aa0578a29fb670faca20939e663b953e70177df3cc91ba85d38332b4178b9d7&quot;
  eth1_data:
    deposit_root: &quot;0xaedca7ce962cb7ef634eae179f6f58c38f2dc6ea6121c41cdda7ec9438a27514&quot;
    deposit_count: &quot;323&quot;
    block_hash: &quot;0xfa06fa004648cc64acc6bd93a8a309d9494409f073f19d07d8a8221fbcc49635&quot;
  block_height: 324
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x909fdc4a762e835a5b890dc4b1c41ca41b65df75770ac25537840d618375a2b5&quot;
      - &quot;0x2aa0578a29fb670faca20939e663b953e70177df3cc91ba85d38332b4178b9d7&quot;
    deposit_root: &quot;0xaedca7ce962cb7ef634eae179f6f58c38f2dc6ea6121c41cdda7ec9438a27514&quot;
    deposit_count: 323
    execution_block_hash: &quot;0xfa06fa004648cc64acc6bd93a8a309d9494409f073f19d07d8a8221fbcc49635&quot;
    execution_block_height: 324
- deposit_data:
    pubkey: &quot;0x893f6809ed7bfd91951ba78b29c2eed9e8147ed63f01749380a0b6bba9bfd3c7654f05d2aa77fb7a096b981745615055&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xaffa69acb9ec862c2e6a48e490ac305a1f7b9ea17b95c5aa416bb4f8f7682abcb8fd9f1074f989f99b780eeb8ba2f03015f8901fb0b0c2c90570452da90c0ecf591a739d6bf8e6e1ec13ce9d4644a4517e44a8bc923d1688732af77cf4e3a2bd&quot;
  deposit_data_root: &quot;0x5b62379e4f53e1806f256162f584ccac600b1b11d21ea858bcd61d8cea1b168b&quot;
  eth1_data:
    deposit_root: &quot;0x637c3e9b84ad5037a6e90a895f20d1b5ec49a3266ee9e3b3c4c632ce3f3f012b&quot;
    deposit_count: &quot;324&quot;
    block_hash: &quot;0x104902e1b47f88b3220f39f473f2f47d0e5b8f12041e12b6f1796ddaf70b962c&quot;
  block_height: 325
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x829bab24c40bf37b3bed73fa4dd76eca6f03f8cdc0d73ec6decd58c56626fdca&quot;
    deposit_root: &quot;0x637c3e9b84ad5037a6e90a895f20d1b5ec49a3266ee9e3b3c4c632ce3f3f012b&quot;
    deposit_count: 324
    execution_block_hash: &quot;0x104902e1b47f88b3220f39f473f2f47d0e5b8f12041e12b6f1796ddaf70b962c&quot;
    execution_block_height: 325
- deposit_data:
    pubkey: &quot;0x868207372934c6e8133df3c6a1d4a993cca26a06616d8f3de0c593a4cca3005d6e1a73b41620b05a31eb44841fc20932&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8485459f5c442443a0075bce597ec6428477bc1f2634fe463397f35b39fab15fe876f1d9c22dc0a9eea20a546f92c39f175ff8402decdffda89f03d074d0c6abd9b95ead19f2b015e9cd6637c505131a38f94c0cc1f39e79152ab5fded97d295&quot;
  deposit_data_root: &quot;0xc19bad7ae315d2679d0a9a44b416955031393874ad7d4f86924ab2e7412dd86c&quot;
  eth1_data:
    deposit_root: &quot;0xd7162fb64e8276d1d722de19732d3d13cc63963606dd5afd722c901721b001ad&quot;
    deposit_count: &quot;325&quot;
    block_hash: &quot;0xf56c5c31b8721f20db972d51c8dc999755b33f49f051f8ecc343a6ce30ba1695&quot;
  block_height: 326
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x829bab24c40bf37b3bed73fa4dd76eca6f03f8cdc0d73ec6decd58c56626fdca&quot;
      - &quot;0xc19bad7ae315d2679d0a9a44b416955031393874ad7d4f86924ab2e7412dd86c&quot;
    deposit_root: &quot;0xd7162fb64e8276d1d722de19732d3d13cc63963606dd5afd722c901721b001ad&quot;
    deposit_count: 325
    execution_block_hash: &quot;0xf56c5c31b8721f20db972d51c8dc999755b33f49f051f8ecc343a6ce30ba1695&quot;
    execution_block_height: 326
- deposit_data:
    pubkey: &quot;0xafa8898fca81793be528c433c00c9838be077b05b7fee5c82c2ff1bea10834f3aae64e2d5b8e3cb3e4a8104127f2b99e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x83536ec416710222ad12669bf77c64062b11d01bbf986d900efb37174e45673764941a630a641d4971bcc1ef031bf6110f7f65599ae492f7e2581af7fbe532aae11882007c3f89736eb7c840b21d194f2805e4016b0cb554255ca59343d741ea&quot;
  deposit_data_root: &quot;0x119dec41ef12a9e3fb28da1a750b117e63d1d0f59a65668984336eec709b8061&quot;
  eth1_data:
    deposit_root: &quot;0xa6f2b846a99b787bfd81acf69ffafca4811ab7c97ba50fbd2ddcf2dc508cd5b9&quot;
    deposit_count: &quot;326&quot;
    block_hash: &quot;0x5d0b737eb0d181195028dd01961a295c8e2baaf0d9aefd647bf884032089245e&quot;
  block_height: 327
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x829bab24c40bf37b3bed73fa4dd76eca6f03f8cdc0d73ec6decd58c56626fdca&quot;
      - &quot;0x6352a5698a39b09b04e0d89ee74b46a579de3e4176cb60ec11c6aad278f2e0ce&quot;
    deposit_root: &quot;0xa6f2b846a99b787bfd81acf69ffafca4811ab7c97ba50fbd2ddcf2dc508cd5b9&quot;
    deposit_count: 326
    execution_block_hash: &quot;0x5d0b737eb0d181195028dd01961a295c8e2baaf0d9aefd647bf884032089245e&quot;
    execution_block_height: 327
- deposit_data:
    pubkey: &quot;0x9685e2fb1018a705d32745ac6bd64d7bc5861679753d5f886a9439c1f8f85cc247b392035fcae82233aa39a6be24515a&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8d766fcb28fe1c2c80c93cfb974f700b2b413dc9abcf0621f623fc8f7059e7d2ede209c75a426c7cbc264a08435790831645cbf7f6f977d9dde8e1382db0ca6f8d7c153e47c7f9a2bd5afc1c09b2d5a0d60b4c7357fad005c53d6e29ed369d57&quot;
  deposit_data_root: &quot;0xd469915f8ff96a6b4944ac2cfb6cfaf5086b4502819e279ddc3d079da18351a9&quot;
  eth1_data:
    deposit_root: &quot;0xefe013b8db2bc21b289a80f7eac2d726307ff64d7182c92d3c38f8bf5b070ed3&quot;
    deposit_count: &quot;327&quot;
    block_hash: &quot;0x7e26828262c78521add66b854b9f6202f38c1b9425f93b7bbe786da0ca6a9d41&quot;
  block_height: 328
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x829bab24c40bf37b3bed73fa4dd76eca6f03f8cdc0d73ec6decd58c56626fdca&quot;
      - &quot;0x6352a5698a39b09b04e0d89ee74b46a579de3e4176cb60ec11c6aad278f2e0ce&quot;
      - &quot;0xd469915f8ff96a6b4944ac2cfb6cfaf5086b4502819e279ddc3d079da18351a9&quot;
    deposit_root: &quot;0xefe013b8db2bc21b289a80f7eac2d726307ff64d7182c92d3c38f8bf5b070ed3&quot;
    deposit_count: 327
    execution_block_hash: &quot;0x7e26828262c78521add66b854b9f6202f38c1b9425f93b7bbe786da0ca6a9d41&quot;
    execution_block_height: 328
- deposit_data:
    pubkey: &quot;0xb41c965012fdbf74f551e0a1372202f5814cedfe541336f5954020ee2ef23043efa6baa200cbd22b34acc5462ca3e9cd&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x86db0292465a7a813f4e6da0d9dc4df20852b088a096b5b569251f544f4e98d2e3125926f1ed97fbcddc356de8461ca1173e9466d181b5f7fc63f772313bc3bb5e37b681c845b5cec8954762565b0614c0413da52147e461bda26ac718afd166&quot;
  deposit_data_root: &quot;0x2a5c7ed2c0ef2938c1edeaa39bbe965c3b7ddfbf544553892c02c2b502c19f33&quot;
  eth1_data:
    deposit_root: &quot;0xa7a049ceb8533aaaee37c8540f1ad14e400ce325de95ef3ff6d9a5a30277aa80&quot;
    deposit_count: &quot;328&quot;
    block_hash: &quot;0x7368b2a4ec10255ec111a7b79ef69efee937e637da93706c68907df2eb5ec722&quot;
  block_height: 329
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x68037963cd0454c7fca9c176f22dd9e308d606acf005cb7b2c5c800b9d443189&quot;
    deposit_root: &quot;0xa7a049ceb8533aaaee37c8540f1ad14e400ce325de95ef3ff6d9a5a30277aa80&quot;
    deposit_count: 328
    execution_block_hash: &quot;0x7368b2a4ec10255ec111a7b79ef69efee937e637da93706c68907df2eb5ec722&quot;
    execution_block_height: 329
- deposit_data:
    pubkey: &quot;0xa8a7015ac1ac3ec6678478167302dade9eedced09f899a60decc8060f972141a88be910f959aa155cceea322f375ae72&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa3b80ecbaf373ff93624739d4fe040d037ebcf3ef906b294b3b908325547aa217b930b0663b2d9589aab52084a028b370c455a452f4ca2ac2156bc7f4283f96c1b3a770d05d9570dfd57844142aa167091359e2a2364de250d22ba06533e4736&quot;
  deposit_data_root: &quot;0x59397bf83c3fc9c58074f1e8139affd9df65b46dd060f498562079145f499f34&quot;
  eth1_data:
    deposit_root: &quot;0x638a7dd7929e0e9ce2efd35226d44a66c555379ddb234e778244064ed44fb3a1&quot;
    deposit_count: &quot;329&quot;
    block_hash: &quot;0x32438de8960d5072d117ed3497e8c3ae169df2c634103b6e708bc04bce0de62c&quot;
  block_height: 330
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x68037963cd0454c7fca9c176f22dd9e308d606acf005cb7b2c5c800b9d443189&quot;
      - &quot;0x59397bf83c3fc9c58074f1e8139affd9df65b46dd060f498562079145f499f34&quot;
    deposit_root: &quot;0x638a7dd7929e0e9ce2efd35226d44a66c555379ddb234e778244064ed44fb3a1&quot;
    deposit_count: 329
    execution_block_hash: &quot;0x32438de8960d5072d117ed3497e8c3ae169df2c634103b6e708bc04bce0de62c&quot;
    execution_block_height: 330
- deposit_data:
    pubkey: &quot;0x83a7860b2ff27518453860637b50ed63adfbda9a2f36432e949268cdbd5a6cc10985acf9bbb57391393823d71328c85a&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x973582f2e9868c13e6f8f5bf798e2111c785281e0659e1adce01524406daaa5d2da5a70c141e84da6891941b632a22af157d1239c5d8a03dbdea8157d7c3f86cd0b316ce06150e18986aca9c84740b1a389bd60234e8f95c9a3d5bcd7f4ca6b1&quot;
  deposit_data_root: &quot;0x249592161dbff13774225e1fb6d8a41c4bdc86213ff6ad2fd5bfaa0b4c9b814d&quot;
  eth1_data:
    deposit_root: &quot;0x2676fba7f7791a8dc588e76fda0a40390988f860b6fcf543d91bdaab3f889344&quot;
    deposit_count: &quot;330&quot;
    block_hash: &quot;0x1c1926c17a2879fb7535863b86d080bfdb32f0213e74ba6895ab8801771bb20a&quot;
  block_height: 331
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x68037963cd0454c7fca9c176f22dd9e308d606acf005cb7b2c5c800b9d443189&quot;
      - &quot;0x491c63b1a2fc1989cb6be00597134cd056a4ccbcc142850c5834a24da3a58686&quot;
    deposit_root: &quot;0x2676fba7f7791a8dc588e76fda0a40390988f860b6fcf543d91bdaab3f889344&quot;
    deposit_count: 330
    execution_block_hash: &quot;0x1c1926c17a2879fb7535863b86d080bfdb32f0213e74ba6895ab8801771bb20a&quot;
    execution_block_height: 331
- deposit_data:
    pubkey: &quot;0xb7458d704a414e012c62a3d19c27da6b0ed9dc77dbc1a328e736043e156eef0af395853ba915bb246a2a4178febc7ad9&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8d51031827dc04649b8825a745eb56f32168064ec6efeadbf8e6d639b21e826ef5c61f890e816bfc66e87bbf85759d240d9c5a95d602ec1ba173fca94959c3a84b164b1d7bc6098bcdead65318f9900c79f9cda30584fd450914613cd174b425&quot;
  deposit_data_root: &quot;0x579accbbe17b59ac71d9923a7cf7b851ccfd509caeb9fccda56c538dacf1744e&quot;
  eth1_data:
    deposit_root: &quot;0x24d257c531f4a7c0979f1778496a0e422e76f120dd5e6f97af72ba9c19b30369&quot;
    deposit_count: &quot;331&quot;
    block_hash: &quot;0x5d1c3942268956fbe23bac62b814488414664aaeff9a047078a2790f0ccbec6d&quot;
  block_height: 332
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x68037963cd0454c7fca9c176f22dd9e308d606acf005cb7b2c5c800b9d443189&quot;
      - &quot;0x491c63b1a2fc1989cb6be00597134cd056a4ccbcc142850c5834a24da3a58686&quot;
      - &quot;0x579accbbe17b59ac71d9923a7cf7b851ccfd509caeb9fccda56c538dacf1744e&quot;
    deposit_root: &quot;0x24d257c531f4a7c0979f1778496a0e422e76f120dd5e6f97af72ba9c19b30369&quot;
    deposit_count: 331
    execution_block_hash: &quot;0x5d1c3942268956fbe23bac62b814488414664aaeff9a047078a2790f0ccbec6d&quot;
    execution_block_height: 332
- deposit_data:
    pubkey: &quot;0x8a6785d9912cb5be712bf51c08da89f9a3c7942869176d1a24f114f430715064f48c35d37c1c1d1eb9b9322ecfdcedb0&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa19c204bfe842f321b5eb4921bfeaaf7275ccbe56531bff038b7e534ab98b13179245d804cbfe08eaa635b1f0c9271ed09754a00cbc617ce22610a78c7a621e92be914288e5412bf2568f784273c59e3d2a529c45c72689a2817a19489fdc109&quot;
  deposit_data_root: &quot;0x3998111d43f8546fc032329d81489551501ccd9b835b0c738866336f442f675f&quot;
  eth1_data:
    deposit_root: &quot;0xcf48923ed77d78c9655d703dc1920f4824c269dd652f2999757e589abbad0247&quot;
    deposit_count: &quot;332&quot;
    block_hash: &quot;0xa0bbc1be8518265a9f0c090c6a3011529e0066b978151c1751962b6ee6439fe5&quot;
  block_height: 333
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x68037963cd0454c7fca9c176f22dd9e308d606acf005cb7b2c5c800b9d443189&quot;
      - &quot;0xfad232bae67341101a570b10f6192e9d46fd997037d7350c72506c8ff80f9c2e&quot;
    deposit_root: &quot;0xcf48923ed77d78c9655d703dc1920f4824c269dd652f2999757e589abbad0247&quot;
    deposit_count: 332
    execution_block_hash: &quot;0xa0bbc1be8518265a9f0c090c6a3011529e0066b978151c1751962b6ee6439fe5&quot;
    execution_block_height: 333
- deposit_data:
    pubkey: &quot;0xb855cac3f2635d485914e4b25b953b066dd5942215b38677d16d3fa6aac5b7f8d0849398ef946674e88514fc83c42491&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa1a4a04d87aa7051d721623609478467070098d8ee9310292a5c98ce5c49185d2fbeb8225a964906f23b4b8d864a47dc0025a10d94953de9b4846ed342fc3e97485d278f9c286417a54eee5496b9f3c1f1e51cfd3396688931f888c241f95552&quot;
  deposit_data_root: &quot;0x6566a16b18a8c515bff85c5cfaa9d0dd7873c39afd6a50e7655d15198fc3d37f&quot;
  eth1_data:
    deposit_root: &quot;0x601f76fb38837cf4733da9f152e37859b1be5e1d18d341ca181b87df6b56320c&quot;
    deposit_count: &quot;333&quot;
    block_hash: &quot;0x2b03e78da06e7a66393fa47a4713ecd2f0eb79a016ad42e2e57350e9a6c1340d&quot;
  block_height: 334
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x68037963cd0454c7fca9c176f22dd9e308d606acf005cb7b2c5c800b9d443189&quot;
      - &quot;0xfad232bae67341101a570b10f6192e9d46fd997037d7350c72506c8ff80f9c2e&quot;
      - &quot;0x6566a16b18a8c515bff85c5cfaa9d0dd7873c39afd6a50e7655d15198fc3d37f&quot;
    deposit_root: &quot;0x601f76fb38837cf4733da9f152e37859b1be5e1d18d341ca181b87df6b56320c&quot;
    deposit_count: 333
    execution_block_hash: &quot;0x2b03e78da06e7a66393fa47a4713ecd2f0eb79a016ad42e2e57350e9a6c1340d&quot;
    execution_block_height: 334
- deposit_data:
    pubkey: &quot;0xae8aa6029e2318a91b3b6ff77e2792905a690d7ad0ac1f97a7887ca4891642d267b7e208f6bddf407fd8c4e10caab2a5&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9077969feb76785e0c70a27f1cbbe4ddf95a0d492ded0730d542b4efd8194b44761f9af983f5169a3b04894db5ec0b620f20b332626a3a41451bd2fa7699750a7422b7c3adb2886bf009cc361b35ecea393d2e6539f16af3cc29b12adc52b007&quot;
  deposit_data_root: &quot;0x212acb543447a951ec9bc344e0dd2816b7cf8292ed26e09341b39c463bf2c1d7&quot;
  eth1_data:
    deposit_root: &quot;0x17ad9aa2ffcb568adfee07a4ea93693926ef5e196f325c0c0b1e282433e2526e&quot;
    deposit_count: &quot;334&quot;
    block_hash: &quot;0xeac3f8860c586f736f0bfbb5132027e74d76b0060a0751e96ffee1d90eb57707&quot;
  block_height: 335
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x68037963cd0454c7fca9c176f22dd9e308d606acf005cb7b2c5c800b9d443189&quot;
      - &quot;0xfad232bae67341101a570b10f6192e9d46fd997037d7350c72506c8ff80f9c2e&quot;
      - &quot;0x98ad3ff4a62e454b2468ff55af20008d2d05198840dd8fa50ef9c637bf07086a&quot;
    deposit_root: &quot;0x17ad9aa2ffcb568adfee07a4ea93693926ef5e196f325c0c0b1e282433e2526e&quot;
    deposit_count: 334
    execution_block_hash: &quot;0xeac3f8860c586f736f0bfbb5132027e74d76b0060a0751e96ffee1d90eb57707&quot;
    execution_block_height: 335
- deposit_data:
    pubkey: &quot;0x98a5e4ffd62c3b8eb39f6230d242efb74701f42380663af26fcbf106ad1b0f02339aa6d9eb5f2f073b01f2c85062d89c&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa611b0ecfe36d86f891951236a218d1f9a64abd697b4e861b2c8849b6b9b1f23287dfdfa1c2c45ca6fec8dae2e1163d1022836eb27982c328955eff7643e031c407ed8629b8c39c8d30bf3b115d0629baa493ead81959b962e42c4ea44b69403&quot;
  deposit_data_root: &quot;0x4b2e8ce40e43537b4a92f303966172fa604c02f1c1747d558f561c4a9915e649&quot;
  eth1_data:
    deposit_root: &quot;0x6b407936ac387168556937334d1fd4d42efc8b83e2979abc7b9440264dd81e8f&quot;
    deposit_count: &quot;335&quot;
    block_hash: &quot;0x642c02da32878eeec84d0c17ff498fba2173c61acf4f268b1f4d937a8261d92e&quot;
  block_height: 336
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x68037963cd0454c7fca9c176f22dd9e308d606acf005cb7b2c5c800b9d443189&quot;
      - &quot;0xfad232bae67341101a570b10f6192e9d46fd997037d7350c72506c8ff80f9c2e&quot;
      - &quot;0x98ad3ff4a62e454b2468ff55af20008d2d05198840dd8fa50ef9c637bf07086a&quot;
      - &quot;0x4b2e8ce40e43537b4a92f303966172fa604c02f1c1747d558f561c4a9915e649&quot;
    deposit_root: &quot;0x6b407936ac387168556937334d1fd4d42efc8b83e2979abc7b9440264dd81e8f&quot;
    deposit_count: 335
    execution_block_hash: &quot;0x642c02da32878eeec84d0c17ff498fba2173c61acf4f268b1f4d937a8261d92e&quot;
    execution_block_height: 336
- deposit_data:
    pubkey: &quot;0xa7723c37795ac53e3ebc25b9dd55af10080490e872a18724b0bd3c7fecf8ab18f7d6abd1b49bc755048a3f9b1bb136ed&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x82d29cd5f8a497b898dcf8d03b7b4e43e2ab362898d80f1b8cedfce878eda388aab81dd2249c4ea11f0359ca666ecdcf12dc23fb637063a23a42f6f0140d74040faf4cedf86ffde4d4ad31a3115a652c53e3e69b8c6041341976bba45451319b&quot;
  deposit_data_root: &quot;0xaafd33e6d9e12cd2b3c9b01a65440dd47914a24fa5ec0a54f1a8fdc04d2a4cce&quot;
  eth1_data:
    deposit_root: &quot;0xb16b2f7f6c0d8dad74c340492d57d24b032a221ae10d86ee1525f0221fcc690f&quot;
    deposit_count: &quot;336&quot;
    block_hash: &quot;0x0671e4bb3a224e145648e03b323fc2034eae6d285f280842370bffc9b75211b8&quot;
  block_height: 337
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2be3d691d07573381ecaa9be38f015a03ca00046e7433389a53d83968989b137&quot;
    deposit_root: &quot;0xb16b2f7f6c0d8dad74c340492d57d24b032a221ae10d86ee1525f0221fcc690f&quot;
    deposit_count: 336
    execution_block_hash: &quot;0x0671e4bb3a224e145648e03b323fc2034eae6d285f280842370bffc9b75211b8&quot;
    execution_block_height: 337
- deposit_data:
    pubkey: &quot;0x865f9a725b49135bae6c011f778bb311a514a73911924e4630a5fedac29e1b4d127308ac8b0d623e7f246c668b827f35&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x98df5e77c8ea74dcc876e84a85bfb829d3f8e6349e1295daae0f7817e47d62788ef5509ef4c7cfe12ca4928c2f8708380b880cff39db85f02a3ae414529cf8ea708d745cdffaec6785a09f78e31a38b6eda8a1849c987e16a896d1fac4baa936&quot;
  deposit_data_root: &quot;0x4c1a708c3fd48341741103c34da6335e37373ce7706ce809aaac4ac88d1a8253&quot;
  eth1_data:
    deposit_root: &quot;0x796573ea2cfd71631491eb7a44bfd33ad6d1be1b3e446549409773724d8990ff&quot;
    deposit_count: &quot;337&quot;
    block_hash: &quot;0x76f57ebaa44d6bf4b4edd91f646b8f872bc1386822617d4e438412858e69fd19&quot;
  block_height: 338
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2be3d691d07573381ecaa9be38f015a03ca00046e7433389a53d83968989b137&quot;
      - &quot;0x4c1a708c3fd48341741103c34da6335e37373ce7706ce809aaac4ac88d1a8253&quot;
    deposit_root: &quot;0x796573ea2cfd71631491eb7a44bfd33ad6d1be1b3e446549409773724d8990ff&quot;
    deposit_count: 337
    execution_block_hash: &quot;0x76f57ebaa44d6bf4b4edd91f646b8f872bc1386822617d4e438412858e69fd19&quot;
    execution_block_height: 338
- deposit_data:
    pubkey: &quot;0xa663aaabc4aae867b7bc4feb03558f9c906be74fbd1cfa931b88191a1817c8393778ef45b5cb107cbf860e9cce540212&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8b7e2a3f92460dfc0e12f13ae76c2949a08fb6407ef52ca0b5059def233c0764955401253ef03f2bed3fc6feea5a09f008969ab976cfaf7a649a930b552285f4441f0d06c0234b81ee37dbf8eac19a50c8276979ade3c7bf773249a45c477e31&quot;
  deposit_data_root: &quot;0x1500846f0a4b55b0ed41b84c3028f1df35be19bb4f82dd1a84c6b5fde4d9dc21&quot;
  eth1_data:
    deposit_root: &quot;0x955590f03dfa34324c77e65b555d2dab80e5d4da4594deb99c7564eed667b840&quot;
    deposit_count: &quot;338&quot;
    block_hash: &quot;0x1d34b11fbd4c5364cd26c59d0d39dab70bb4406ab876409eb98a505f474c12ab&quot;
  block_height: 339
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2be3d691d07573381ecaa9be38f015a03ca00046e7433389a53d83968989b137&quot;
      - &quot;0x02937359af82fb5ab508a78d0a5455edc12d42abc01d457cb808ae23ffe4f3b9&quot;
    deposit_root: &quot;0x955590f03dfa34324c77e65b555d2dab80e5d4da4594deb99c7564eed667b840&quot;
    deposit_count: 338
    execution_block_hash: &quot;0x1d34b11fbd4c5364cd26c59d0d39dab70bb4406ab876409eb98a505f474c12ab&quot;
    execution_block_height: 339
- deposit_data:
    pubkey: &quot;0x970d2002cd899a503a0a007d6b5cc6f8ea9fc7e7db1de06b5297daa7f365d066e69cfd179197229508bdf93161904330&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb286275d11239f69f057de9e85f5f26466f0b316dd0a904a4ea87def5aec3808f7c5379d8303666902819449fab7efab1564ee7e1fabddb6f475530fee84042b76ccff7eb8a1c4788fef17ce15aba2ecdf8aac1ba25af4f9c47bf66491dc6e4d&quot;
  deposit_data_root: &quot;0x7fd3c53f7f63b048832cf0492598920d87f4a205dbd16e53c4bb6bc9c9c9d43e&quot;
  eth1_data:
    deposit_root: &quot;0xf75235a060b1c539b96b12e4d23245f341777cac99f556f4d686c0cf44688538&quot;
    deposit_count: &quot;339&quot;
    block_hash: &quot;0xaedd455c7e89005ce8a0cd34b997eb55456eb21d7dfd08b0c1978717614285af&quot;
  block_height: 340
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2be3d691d07573381ecaa9be38f015a03ca00046e7433389a53d83968989b137&quot;
      - &quot;0x02937359af82fb5ab508a78d0a5455edc12d42abc01d457cb808ae23ffe4f3b9&quot;
      - &quot;0x7fd3c53f7f63b048832cf0492598920d87f4a205dbd16e53c4bb6bc9c9c9d43e&quot;
    deposit_root: &quot;0xf75235a060b1c539b96b12e4d23245f341777cac99f556f4d686c0cf44688538&quot;
    deposit_count: 339
    execution_block_hash: &quot;0xaedd455c7e89005ce8a0cd34b997eb55456eb21d7dfd08b0c1978717614285af&quot;
    execution_block_height: 340
- deposit_data:
    pubkey: &quot;0x81fc32376cd95ab4456f645030a9ccba182da956571ee1136916fe655c8bf08f05244e204bfbc87f696472b3cf3bab83&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8e625f0c45db2539e488bd2272774e46699e690e45fd6e88fa42204d9798a24aa1ea432498172c25671d65450b2ff8d008bc9d87276592803f9568cd46e4d46e1da49db778158256fdc10d8e4dede5194cc51d684887f31a4ff2725113deff26&quot;
  deposit_data_root: &quot;0x8d6754cda9a15e4c2b26cd6c030a76af60e0dec4e17a008f30164ed9ba746cff&quot;
  eth1_data:
    deposit_root: &quot;0xcb7ce227d926f427218766a5fca5311ec8111498381867d4fa68212857ec0e41&quot;
    deposit_count: &quot;340&quot;
    block_hash: &quot;0xdc73d2399512a4f010ac368d10034f9ec2ca191af40dc0be3c768a0c56bcf02b&quot;
  block_height: 341
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2be3d691d07573381ecaa9be38f015a03ca00046e7433389a53d83968989b137&quot;
      - &quot;0x691d6c3d1788448165cd972951b94cca4485afc7571864393cb986aca78a99bb&quot;
    deposit_root: &quot;0xcb7ce227d926f427218766a5fca5311ec8111498381867d4fa68212857ec0e41&quot;
    deposit_count: 340
    execution_block_hash: &quot;0xdc73d2399512a4f010ac368d10034f9ec2ca191af40dc0be3c768a0c56bcf02b&quot;
    execution_block_height: 341
- deposit_data:
    pubkey: &quot;0xa42f4e4ec8732b5a4fbffea9e17a6c208db024f36a899f90671b1910a1dff4b18996b517050f4aacb548640bdf8fe844&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa9bd07d645a9db4c36bf8bb92478ee618c92414a1619a04cf6d39f5ca4fe37fed016b0332d9e9ba62247180f26b001d40c7ffdd2522fa4316e5f1980b14259b279e98da54c01a65d1355d6ba3e827b36476854eef5fce97f01690bd45c9eb7bc&quot;
  deposit_data_root: &quot;0x0cb2bb82034b6d90b373320449a801ae41fdc49cb4610e8bde86a2073cf91e3b&quot;
  eth1_data:
    deposit_root: &quot;0xc8efa837e5b208a1252d1c5caa6e2da3377532093f952df3d8a655cf0960144c&quot;
    deposit_count: &quot;341&quot;
    block_hash: &quot;0x281cce8e3af1cba285ad4a6533cbbdd4b16f7c646351d2594c47a54d84685a01&quot;
  block_height: 342
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2be3d691d07573381ecaa9be38f015a03ca00046e7433389a53d83968989b137&quot;
      - &quot;0x691d6c3d1788448165cd972951b94cca4485afc7571864393cb986aca78a99bb&quot;
      - &quot;0x0cb2bb82034b6d90b373320449a801ae41fdc49cb4610e8bde86a2073cf91e3b&quot;
    deposit_root: &quot;0xc8efa837e5b208a1252d1c5caa6e2da3377532093f952df3d8a655cf0960144c&quot;
    deposit_count: 341
    execution_block_hash: &quot;0x281cce8e3af1cba285ad4a6533cbbdd4b16f7c646351d2594c47a54d84685a01&quot;
    execution_block_height: 342
- deposit_data:
    pubkey: &quot;0xb4368a6946801366550e764247f27c24bed3c5830a49be21ddeee79a67d71e0aff3d5cc0a9b1e18bad5c9e655ad23502&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa4e0e77af815e173a20d602fbc5148918012820754d736dd34549761392b3d8a81af062830ee3d851125ae056201dbab1246b20bbe4d92a3e11f913fff280acefb6dd64508591e1ab9b02a300bad6ebb54e205c80923d892a8db4564c3945856&quot;
  deposit_data_root: &quot;0x3c15bff5b52d7d846681e0cd70606a0ee32b276c9408b42601fde515b35f196b&quot;
  eth1_data:
    deposit_root: &quot;0xa10f1b573d7d012d556954b1fb79a14483d8d45db59f475f2ed8bd0dd38a2f79&quot;
    deposit_count: &quot;342&quot;
    block_hash: &quot;0xfcef96a865323635b735de16d7a4e79e58e00efb50920ae9b7f55cbec4dc42c4&quot;
  block_height: 343
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2be3d691d07573381ecaa9be38f015a03ca00046e7433389a53d83968989b137&quot;
      - &quot;0x691d6c3d1788448165cd972951b94cca4485afc7571864393cb986aca78a99bb&quot;
      - &quot;0xe8c655eec2a2badc6e31a521cd3847d22c7d67433e11aa8304ba846ef1b4616e&quot;
    deposit_root: &quot;0xa10f1b573d7d012d556954b1fb79a14483d8d45db59f475f2ed8bd0dd38a2f79&quot;
    deposit_count: 342
    execution_block_hash: &quot;0xfcef96a865323635b735de16d7a4e79e58e00efb50920ae9b7f55cbec4dc42c4&quot;
    execution_block_height: 343
- deposit_data:
    pubkey: &quot;0xa4a216ff9a365d29e027a557ae3d4f52bf4fa11654c4314d65a319810fd799c8fb2d129692d7d68f6c134cde9de5d2c6&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb62b67e03a9b18faa69f527953e53ca8dc3c14ff793e274314c0495118e52e01651bf43cbce50daf8c93756a43a32f6d10f697c1a37842f1def52372e984fab30010f35b5105f1079563979690d46edc71c80fa6bae135b49a2d7b0a01aad0bd&quot;
  deposit_data_root: &quot;0x0f433740b767093be9a8d4e8ee049901f378187296b76b352595542022e6bc19&quot;
  eth1_data:
    deposit_root: &quot;0x0cccf3ad07bb6129c55118f363f08f6a7eab37150d087d713ab9e4b93c9e3825&quot;
    deposit_count: &quot;343&quot;
    block_hash: &quot;0xfa34f90576211ca0acfb7db7cbf1529ddb54a8f319986a7c133b79e15c65f945&quot;
  block_height: 344
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2be3d691d07573381ecaa9be38f015a03ca00046e7433389a53d83968989b137&quot;
      - &quot;0x691d6c3d1788448165cd972951b94cca4485afc7571864393cb986aca78a99bb&quot;
      - &quot;0xe8c655eec2a2badc6e31a521cd3847d22c7d67433e11aa8304ba846ef1b4616e&quot;
      - &quot;0x0f433740b767093be9a8d4e8ee049901f378187296b76b352595542022e6bc19&quot;
    deposit_root: &quot;0x0cccf3ad07bb6129c55118f363f08f6a7eab37150d087d713ab9e4b93c9e3825&quot;
    deposit_count: 343
    execution_block_hash: &quot;0xfa34f90576211ca0acfb7db7cbf1529ddb54a8f319986a7c133b79e15c65f945&quot;
    execution_block_height: 344
- deposit_data:
    pubkey: &quot;0xa814035503cb1adcfdef259521573a5193dfa1e8d74e22649ad1b2b01a44fc6c2352100bc42d6c48584ff1d3a430537d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8c4f917adb8706a169c9f93c6bbe2186fd84a81e86f9adaec27391a485afc8e9130f5d940129208437ac6be31ddb50b50eeefceb47751b664ff119be7aee930df8bff802a819c3e9d08e0cc453b7544bc8089b8b9f63c8dc7e2411d997aaecaa&quot;
  deposit_data_root: &quot;0xea73c129f0be1b4bb10e06fbbe409b22e94e0e4ad06411ee5ef1142fd61b3c64&quot;
  eth1_data:
    deposit_root: &quot;0x5a82e52a1ed416eee15a1c097092f7518b4c53a89bf44c76046cbdb4866aee0d&quot;
    deposit_count: &quot;344&quot;
    block_hash: &quot;0x625d21649e1542510b4fa7f2570067aec4ecdbaade993f1b33f7fc0448ada465&quot;
  block_height: 345
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2be3d691d07573381ecaa9be38f015a03ca00046e7433389a53d83968989b137&quot;
      - &quot;0x61af53fab3c4897138fbefac5b631a96d505678a097ecfe9a2f9a7905c8d9683&quot;
    deposit_root: &quot;0x5a82e52a1ed416eee15a1c097092f7518b4c53a89bf44c76046cbdb4866aee0d&quot;
    deposit_count: 344
    execution_block_hash: &quot;0x625d21649e1542510b4fa7f2570067aec4ecdbaade993f1b33f7fc0448ada465&quot;
    execution_block_height: 345
- deposit_data:
    pubkey: &quot;0xaaa334a2fb779ce6de3c557025ff9bf17243deb3f09a37f6719356b54afd9be09a7b82cd589758779544a08cfd3ed5cc&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x951f84c57cf1242ce760108e8b5e6ab1b9ea7bbf8ce40198f6a10f2d55838320c9f6e0c2bed2d9eaa4aa3837a9394fcd1562efaa6daeb5b8e0b183924d9786bd2eb94b31952577611f3e1eec834e44fcfab0cacec4632aba7d1ba5a15880f339&quot;
  deposit_data_root: &quot;0xb6d2d582e7c0f6d7dab60416797b7c84771fe30cb380b25be8c6c0ca12d7c54c&quot;
  eth1_data:
    deposit_root: &quot;0x9c2315289da9d6fa488347b4856f84fe558e5e7e186b44256496a538a126f880&quot;
    deposit_count: &quot;345&quot;
    block_hash: &quot;0x51046db7f7057439306e943428b8271dceee739b9c2473f00c516959dbec5bfe&quot;
  block_height: 346
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2be3d691d07573381ecaa9be38f015a03ca00046e7433389a53d83968989b137&quot;
      - &quot;0x61af53fab3c4897138fbefac5b631a96d505678a097ecfe9a2f9a7905c8d9683&quot;
      - &quot;0xb6d2d582e7c0f6d7dab60416797b7c84771fe30cb380b25be8c6c0ca12d7c54c&quot;
    deposit_root: &quot;0x9c2315289da9d6fa488347b4856f84fe558e5e7e186b44256496a538a126f880&quot;
    deposit_count: 345
    execution_block_hash: &quot;0x51046db7f7057439306e943428b8271dceee739b9c2473f00c516959dbec5bfe&quot;
    execution_block_height: 346
- deposit_data:
    pubkey: &quot;0xaac004b4b25584ba8c906671196db57d7a4f159cfb430b1590d61d94c5c22cb694c25bb6ee850421db260d063e096145&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xac4f0ad93d329006d74a5e51870edd9038900d3e080f74ad8e3362fff86e616566dde3416b752f7b900e235bcf01f58b06862f9678a0dd11d481224afdca5ee9fdaff661e74b4cb70cefb7f691b76a822fa278008f9b611ba9cbb5a0234ccff9&quot;
  deposit_data_root: &quot;0x8b7c5eb357e9e4abb96dc68302fa6e93c3067abd623b9338a1afa7ac8e16d63b&quot;
  eth1_data:
    deposit_root: &quot;0x5ce81fb6b5ba660b0fd450e1c1d8ce22f1b02dbfa8d4f1df5062d70e3aeb66e4&quot;
    deposit_count: &quot;346&quot;
    block_hash: &quot;0x51050db6a05c59f2dfcdf79b39dc420a5d52ad575ce0f08b436f6ea02325d0fe&quot;
  block_height: 347
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2be3d691d07573381ecaa9be38f015a03ca00046e7433389a53d83968989b137&quot;
      - &quot;0x61af53fab3c4897138fbefac5b631a96d505678a097ecfe9a2f9a7905c8d9683&quot;
      - &quot;0x5a89c435553780c594308fa4372c85b8ac39ab611cbdd7ada19bb99116c7cb4f&quot;
    deposit_root: &quot;0x5ce81fb6b5ba660b0fd450e1c1d8ce22f1b02dbfa8d4f1df5062d70e3aeb66e4&quot;
    deposit_count: 346
    execution_block_hash: &quot;0x51050db6a05c59f2dfcdf79b39dc420a5d52ad575ce0f08b436f6ea02325d0fe&quot;
    execution_block_height: 347
- deposit_data:
    pubkey: &quot;0xad7b6b1ba1f7950cc8e2b5b0cb9041666361eb023b1deff783420482970cf58213497d64cfc91cf06762dd511b0aac31&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb5abc0b6d2aeeb6156bd77d50cb67115abe5b519e46a9275f60d02128e2048da62556ff24746037f710a4d5cae3d924c1916f896829525603a9c8a4f7c737c7e9255344686fdb590bf8dc9a6ed3e4803727ace8ac5346cdc650aaf87444cf316&quot;
  deposit_data_root: &quot;0xcca6725f342e727e05d46aacf15407b225f054ee8edcde7c1e46554ab4d258d8&quot;
  eth1_data:
    deposit_root: &quot;0x46aad6ffcc251664c097e6d284162dc501d4d1625ac3585cc2bee8bee47ad946&quot;
    deposit_count: &quot;347&quot;
    block_hash: &quot;0x9660d6f0d6d69745bc825562e29c177a86f4ce447e9d90f417f66696454551b2&quot;
  block_height: 348
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2be3d691d07573381ecaa9be38f015a03ca00046e7433389a53d83968989b137&quot;
      - &quot;0x61af53fab3c4897138fbefac5b631a96d505678a097ecfe9a2f9a7905c8d9683&quot;
      - &quot;0x5a89c435553780c594308fa4372c85b8ac39ab611cbdd7ada19bb99116c7cb4f&quot;
      - &quot;0xcca6725f342e727e05d46aacf15407b225f054ee8edcde7c1e46554ab4d258d8&quot;
    deposit_root: &quot;0x46aad6ffcc251664c097e6d284162dc501d4d1625ac3585cc2bee8bee47ad946&quot;
    deposit_count: 347
    execution_block_hash: &quot;0x9660d6f0d6d69745bc825562e29c177a86f4ce447e9d90f417f66696454551b2&quot;
    execution_block_height: 348
- deposit_data:
    pubkey: &quot;0x846f3af6ac23b648a5ea3cdb60b2086e18e42b2837a9d689625af534792f9489a1b22cab64476533993f34149fed1a0b&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xae4c2827395dc47a9303a2ec5f5337b5fadb67e813e4bdf0bee32ea1f0a0377e50f1f381313d4d8db576797ce1f1edbc1924e110278ce87761774b7fa6250f81f0563a2c757ce24b7e57143a396087a2a14dae9f06c2787cfb247e8726df18f3&quot;
  deposit_data_root: &quot;0xb6be3a5becdd7330a4e3fe5176fc77cc1cc107629421a6c373ccf5cf89d12546&quot;
  eth1_data:
    deposit_root: &quot;0x473a9d413c0619796c3ffa906b9ba7774339cc08d3f30d468d868ac3ea1fef6e&quot;
    deposit_count: &quot;348&quot;
    block_hash: &quot;0x25df98dc1923be776e2e9732e5e667a77f6dee8af43bc1f198dcd43025da3589&quot;
  block_height: 349
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2be3d691d07573381ecaa9be38f015a03ca00046e7433389a53d83968989b137&quot;
      - &quot;0x61af53fab3c4897138fbefac5b631a96d505678a097ecfe9a2f9a7905c8d9683&quot;
      - &quot;0x08b50aac114125944b1e0be249589266d73343598f6094b9e13f1c04c4f895fe&quot;
    deposit_root: &quot;0x473a9d413c0619796c3ffa906b9ba7774339cc08d3f30d468d868ac3ea1fef6e&quot;
    deposit_count: 348
    execution_block_hash: &quot;0x25df98dc1923be776e2e9732e5e667a77f6dee8af43bc1f198dcd43025da3589&quot;
    execution_block_height: 349
- deposit_data:
    pubkey: &quot;0xa8784f36c1a8c6e739b090d982480712ff04c9231190b97121c86c84a35cbd561d3372902017ea71fb99ce2a6582f362&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xaff0df82cd7d8b804a9f5f62f493936e0d77be3631c1f0d9d295dac98c3d019f534774519582503694a723820031ddb8184de493e5df34c2fb875ee4a0be4c82571b6623546b666d1ce1c539175662b42dc963e6205a243d758f7e1e6c040449&quot;
  deposit_data_root: &quot;0x8920aa96089e1b189ba5b62754537f9ae53cf2e3f6d0d9c18385bc2566712a24&quot;
  eth1_data:
    deposit_root: &quot;0x69b38abb0d6cb1a2914ed20b9c04e2110e2374dcae202360845a9f730e2005b4&quot;
    deposit_count: &quot;349&quot;
    block_hash: &quot;0x74905823b1a94f841f1763c2b21604f9ddd31727e12a0c4405a50b70903c105d&quot;
  block_height: 350
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2be3d691d07573381ecaa9be38f015a03ca00046e7433389a53d83968989b137&quot;
      - &quot;0x61af53fab3c4897138fbefac5b631a96d505678a097ecfe9a2f9a7905c8d9683&quot;
      - &quot;0x08b50aac114125944b1e0be249589266d73343598f6094b9e13f1c04c4f895fe&quot;
      - &quot;0x8920aa96089e1b189ba5b62754537f9ae53cf2e3f6d0d9c18385bc2566712a24&quot;
    deposit_root: &quot;0x69b38abb0d6cb1a2914ed20b9c04e2110e2374dcae202360845a9f730e2005b4&quot;
    deposit_count: 349
    execution_block_hash: &quot;0x74905823b1a94f841f1763c2b21604f9ddd31727e12a0c4405a50b70903c105d&quot;
    execution_block_height: 350
- deposit_data:
    pubkey: &quot;0xa398c76ca4aff66b20dfea97e1bbea311a5491b6de44cbcc979bd368818eaef834f188ad6fb413c3120b1af141637cdc&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb345cf97868f004b66e78cce43b072e515e647c10b7a06970bf335d4eb67d423977bcbae4ddd3479fc243117a639443a0f730fa27c9173a1fe9c1a336d99aad931e813fc84f11112453bae446b01a363f5a8962bb2fda2957f5cadd0bdbcc840&quot;
  deposit_data_root: &quot;0xe1e4024334ffdcc89d3c6bb0f633afb6b8cf63e1bf0624dd29e980035a80b1e1&quot;
  eth1_data:
    deposit_root: &quot;0x249ae18bac8cbeb1bfb2970234b73368a09d8a2ed6fab14c1a0608887b22c95f&quot;
    deposit_count: &quot;350&quot;
    block_hash: &quot;0xe55ef2c7c927098d257769da87f33354267c4f720bd31ee699cae6fe6c23b9ab&quot;
  block_height: 351
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2be3d691d07573381ecaa9be38f015a03ca00046e7433389a53d83968989b137&quot;
      - &quot;0x61af53fab3c4897138fbefac5b631a96d505678a097ecfe9a2f9a7905c8d9683&quot;
      - &quot;0x08b50aac114125944b1e0be249589266d73343598f6094b9e13f1c04c4f895fe&quot;
      - &quot;0x540b74da4539ce3fc72ade01431e3b30606bc85b85cc5cba0c12c3a166746e9b&quot;
    deposit_root: &quot;0x249ae18bac8cbeb1bfb2970234b73368a09d8a2ed6fab14c1a0608887b22c95f&quot;
    deposit_count: 350
    execution_block_hash: &quot;0xe55ef2c7c927098d257769da87f33354267c4f720bd31ee699cae6fe6c23b9ab&quot;
    execution_block_height: 351
- deposit_data:
    pubkey: &quot;0xaf54a32535604e042dc5a7e296a762f3ddc1fe00741eda9acb8f54be49a8244750d6d8f15a10d9384afbd26bccb662af&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa6286e34d6eabfd35e2e69f1541ce7574229d152a95b693b1073874d7505399babd68b1e5d373c5e3a60bb85360d43a51715914324b85b6d52ecb42f129bb1658959ee201c581e717a1ec40e281fa2ba26e2d93f1def180d2d13a58ff9b875e4&quot;
  deposit_data_root: &quot;0xb1c68778c0ec68fe070016e011f0efe683dcf0d5ccc5ce4a41506027de9409ab&quot;
  eth1_data:
    deposit_root: &quot;0xf653f23a48facb6c1c9b5d7df3387f77ed798e75556b335237fcfe8e40e6832b&quot;
    deposit_count: &quot;351&quot;
    block_hash: &quot;0x22fbc60289a0213fd65514e255963d148ffac49400e25fc2fec770a6abc36890&quot;
  block_height: 352
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2be3d691d07573381ecaa9be38f015a03ca00046e7433389a53d83968989b137&quot;
      - &quot;0x61af53fab3c4897138fbefac5b631a96d505678a097ecfe9a2f9a7905c8d9683&quot;
      - &quot;0x08b50aac114125944b1e0be249589266d73343598f6094b9e13f1c04c4f895fe&quot;
      - &quot;0x540b74da4539ce3fc72ade01431e3b30606bc85b85cc5cba0c12c3a166746e9b&quot;
      - &quot;0xb1c68778c0ec68fe070016e011f0efe683dcf0d5ccc5ce4a41506027de9409ab&quot;
    deposit_root: &quot;0xf653f23a48facb6c1c9b5d7df3387f77ed798e75556b335237fcfe8e40e6832b&quot;
    deposit_count: 351
    execution_block_hash: &quot;0x22fbc60289a0213fd65514e255963d148ffac49400e25fc2fec770a6abc36890&quot;
    execution_block_height: 352
- deposit_data:
    pubkey: &quot;0xaa41628c60365750c75cf91a8d4097047d61c624b01d4f298ac90a66409cada1bb99cf42a2577ba173a94745dd73d6d2&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x96b47d0a7ea06103c1ccf89698c71e8e05bb361aa564c6a0ddde8cb35ca0827d4c6fc03ef762f9f8919907deb4b7e2c10210757f9a0e03c7edc7e93afe48c3049841940bb352d015fcc404dd065d9aa947aba87074344fa29e126d83165f9e10&quot;
  deposit_data_root: &quot;0x5809f4140599df5900ef54b70e678188108fcb84993cdf92f63734e016683a36&quot;
  eth1_data:
    deposit_root: &quot;0x8fbfbcd57a3f6f5dc37eb7ec56d7e273892dc5e321c1365d220becc4ae65eda2&quot;
    deposit_count: &quot;352&quot;
    block_hash: &quot;0x5fa4ed804971ad0bc19fd3038282bb697dca9c7aaca9b413f54fb261e843352e&quot;
  block_height: 353
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
    deposit_root: &quot;0x8fbfbcd57a3f6f5dc37eb7ec56d7e273892dc5e321c1365d220becc4ae65eda2&quot;
    deposit_count: 352
    execution_block_hash: &quot;0x5fa4ed804971ad0bc19fd3038282bb697dca9c7aaca9b413f54fb261e843352e&quot;
    execution_block_height: 353
- deposit_data:
    pubkey: &quot;0xa4623cedd189249799b7c9afb49960dd86f31572a6edd594dc9d147bd11b368b66afaff6a2dcdecfa873f88991e5a8d6&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa53f69cf2e224bfff70ba77e95b49525e4222ff8f3967a79bcc6244995e48501db0556fc79fba5fb32bcf1cf45c1ba8f17c0eb25eb5fbffc63344807e2627b49e03f8d8e8e9017c0a65f35702f2353eb576141fb10970655d63ac5d89a2e87b8&quot;
  deposit_data_root: &quot;0x79ac2faba3df339c9a4c1035da2b4319b9b6e007a70479b528b6eb6008281e2a&quot;
  eth1_data:
    deposit_root: &quot;0x3d14a58b5cbc0e3146ad1778955f955c855ae299c4dbb24494e291aac4bca411&quot;
    deposit_count: &quot;353&quot;
    block_hash: &quot;0xd45a6c4a1391e32940ab1a47bde642ebbeb12849a6909615c317474252c04075&quot;
  block_height: 354
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0x79ac2faba3df339c9a4c1035da2b4319b9b6e007a70479b528b6eb6008281e2a&quot;
    deposit_root: &quot;0x3d14a58b5cbc0e3146ad1778955f955c855ae299c4dbb24494e291aac4bca411&quot;
    deposit_count: 353
    execution_block_hash: &quot;0xd45a6c4a1391e32940ab1a47bde642ebbeb12849a6909615c317474252c04075&quot;
    execution_block_height: 354
- deposit_data:
    pubkey: &quot;0xa58a5d3d29c1331b6f4f977ee08afdf95c067db26c21a591b15db682f93d223acd4e031c98434ec7be34922496ec8ec1&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8b2019cbdc2fb49df3257128d61a4e0fa63f451b09a86ef0e5b3084d42a7647d076f03771c996322ce65a4ee05a9bbbc0e7a108e2b816bdb39db1ebe2cc10856864cd8dfa2a042d42fed42236d88b37ef286bff4c5e3176140f140773ccd5505&quot;
  deposit_data_root: &quot;0x4e2e9ae16bcb8f83129a723e664b4e2d1dbb436655d0c2bfcacf416ca71b3bd0&quot;
  eth1_data:
    deposit_root: &quot;0xfc17404478ee17d526ec0e6d7b7f392f0cd2edf08cd20ea72a6b7cafb0bc5d1b&quot;
    deposit_count: &quot;354&quot;
    block_hash: &quot;0x48e867e23f93afbce5c768c3e7b24afc6f67bbf23b03ed35f673daaa22e150cb&quot;
  block_height: 355
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0x0e5edf133dd9d31c962d3c832701f118549e950098920f374a8a7f4b1503424c&quot;
    deposit_root: &quot;0xfc17404478ee17d526ec0e6d7b7f392f0cd2edf08cd20ea72a6b7cafb0bc5d1b&quot;
    deposit_count: 354
    execution_block_hash: &quot;0x48e867e23f93afbce5c768c3e7b24afc6f67bbf23b03ed35f673daaa22e150cb&quot;
    execution_block_height: 355
- deposit_data:
    pubkey: &quot;0xa31ecb88e06673a2c3ea98a969827babdd0c6a8fc9569d70c024640f31084c7fc2bc8f00eb65023a008e0b47b3d2e364&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9212c805e5710672e72e9cbf49ab23f0b8849bda05c2eb97599849b0966e814956cceff71141ee1c90a5090e7388e6ce167364b1a5a843e08ab11e42fcb452e70a9b34cde657637ba57002054819440d51b7fefc316897c2dc396e36e3052251&quot;
  deposit_data_root: &quot;0xe29cc36e9033d65ab7c3214886e01b4071597f461fba82ca0d5b6e2716a96c2e&quot;
  eth1_data:
    deposit_root: &quot;0xbc150ef54a71de32ae1cdc80595d7102bcfb75391a31596cd08f93ac573f82db&quot;
    deposit_count: &quot;355&quot;
    block_hash: &quot;0x91e6f47ff5874c78e63536737ed9fba1fd13418ad4adafe5d8afa6b6096d7175&quot;
  block_height: 356
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0x0e5edf133dd9d31c962d3c832701f118549e950098920f374a8a7f4b1503424c&quot;
      - &quot;0xe29cc36e9033d65ab7c3214886e01b4071597f461fba82ca0d5b6e2716a96c2e&quot;
    deposit_root: &quot;0xbc150ef54a71de32ae1cdc80595d7102bcfb75391a31596cd08f93ac573f82db&quot;
    deposit_count: 355
    execution_block_hash: &quot;0x91e6f47ff5874c78e63536737ed9fba1fd13418ad4adafe5d8afa6b6096d7175&quot;
    execution_block_height: 356
- deposit_data:
    pubkey: &quot;0xae32f510734cfe1a05f1a49888185191777008667a62a3b5d71f4b249a5a0421d762c98c0dd0626e17f6326ff525e63b&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb278d4156302165853f5a95e5a38a57aad92e6388d231f1616c024ece355b83f9b4ba41f1bb60fc0ae5aca0c1457b5090e84bd06d28288890b17a2244288e4421a4fc1534b190ed3e520a471701e5142eb4374f3e372f4e7b0d754e943455b54&quot;
  deposit_data_root: &quot;0xea9cace5a73c0c0a4cfc34fe161fe4a0aa802729c46451cd375a524f84032e1b&quot;
  eth1_data:
    deposit_root: &quot;0x4ece22540ed44b8d7e55a580ef7afcd709ada5004c4505db558a4fa0ef39e949&quot;
    deposit_count: &quot;356&quot;
    block_hash: &quot;0xf9854d07f70ef80e24c9dae43433d2a284b89ee66e5e8912a4ebb92246a268da&quot;
  block_height: 357
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0xec97a0de415ce5348ebe21219a3cbe17938f07344276f64ec40e1dced411c131&quot;
    deposit_root: &quot;0x4ece22540ed44b8d7e55a580ef7afcd709ada5004c4505db558a4fa0ef39e949&quot;
    deposit_count: 356
    execution_block_hash: &quot;0xf9854d07f70ef80e24c9dae43433d2a284b89ee66e5e8912a4ebb92246a268da&quot;
    execution_block_height: 357
- deposit_data:
    pubkey: &quot;0x9407a54a336fb7632ed16da2929c6ed1e2a8a969990d15f9f322734ee60c00757dec74e4c0224e813efeb1c9be42c09e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xafd6a5b56011fdc9d506d7c468993d690e2416b8322a5117fbfaeba9e4f15a6518d1f6b4b6917f381e96e396f8a5ff0c13eb33425c2247af685cc4723322d0e1596a3e1d0013871ac6603ef6fa4c74eddf2707f60e19fbb84073113afaa9ce5a&quot;
  deposit_data_root: &quot;0xa27fecc07480ce7de9e8fdcab0a5371632f26446c6a1a7e5594cd3b05f91c879&quot;
  eth1_data:
    deposit_root: &quot;0xb6e2c6e1112b2143ea4480f062c4c7c648307419c43032304281f44bcfe04578&quot;
    deposit_count: &quot;357&quot;
    block_hash: &quot;0x624663feb3f1449b2b425c886c243ab42cb4bbe01a06f1d47421134df7b63475&quot;
  block_height: 358
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0xec97a0de415ce5348ebe21219a3cbe17938f07344276f64ec40e1dced411c131&quot;
      - &quot;0xa27fecc07480ce7de9e8fdcab0a5371632f26446c6a1a7e5594cd3b05f91c879&quot;
    deposit_root: &quot;0xb6e2c6e1112b2143ea4480f062c4c7c648307419c43032304281f44bcfe04578&quot;
    deposit_count: 357
    execution_block_hash: &quot;0x624663feb3f1449b2b425c886c243ab42cb4bbe01a06f1d47421134df7b63475&quot;
    execution_block_height: 358
- deposit_data:
    pubkey: &quot;0x8fe3971515fb25cbe62a03e4a593dfb4cc3563bc5b7866dfe300b958a53f07fdde463fc7abfe349a2eedf38d569cd126&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8f51e38f6033d91644cd646777b584c8ee985d18951ea4f184e5f321806b111881584c65d411542e99899832620664c60c6bee1be977e63041276f81f6daaf7b1931cdd4c725faf85b5186f2001b18e4e6cfb2c562cf5360bf76f1783ad54b7b&quot;
  deposit_data_root: &quot;0x28cf518415e14159c030d4c9ce4e1737eb8dafd10f8c9f3668c1a157b5f5ec3e&quot;
  eth1_data:
    deposit_root: &quot;0x0b066def513f0615242e17a3fe521dcd78226abfbfa040203591f1f9587b3877&quot;
    deposit_count: &quot;358&quot;
    block_hash: &quot;0x3492958f15fa544dbe4eac07ce27c1ade01e53ce22cff0aa6e5688a50a53af73&quot;
  block_height: 359
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0xec97a0de415ce5348ebe21219a3cbe17938f07344276f64ec40e1dced411c131&quot;
      - &quot;0xd34bdde7bf541ae5af14a22f182fe4a5087d292e96c952ec405b9c04fd71645c&quot;
    deposit_root: &quot;0x0b066def513f0615242e17a3fe521dcd78226abfbfa040203591f1f9587b3877&quot;
    deposit_count: 358
    execution_block_hash: &quot;0x3492958f15fa544dbe4eac07ce27c1ade01e53ce22cff0aa6e5688a50a53af73&quot;
    execution_block_height: 359
- deposit_data:
    pubkey: &quot;0xae99451101dde8ce7d7f1b784fe2a1fe0974cd3d7e8d2d3c775892cdc2dfc021eb9f7a5b60681fe7369ec88884e6299a&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa9e4c4aa80a317292a1d42a7dd6d18cfb04c7087a078332b7ca9c1fdac29b8019a2f6f2cb3034362a63ac7ceed7616510b6c45212fd0ebc2b7851293c4c46d1aa3eb99b7df62891c30e83d2a1a58f5bc91ad4278655f8482dd14bb0941ab37c9&quot;
  deposit_data_root: &quot;0x69b84b7fa3b0dda0b7eaf825ac386bd2416359a1c076743901c727adfbad4022&quot;
  eth1_data:
    deposit_root: &quot;0x0a872a65e20b1d6eb13282886f5082a99b3ac36e5636c6b7667d6f7b454c136f&quot;
    deposit_count: &quot;359&quot;
    block_hash: &quot;0x05f878ea1b32f42d1b5eb823c090f2789b19a062bc3495d80402a3077ccab36d&quot;
  block_height: 360
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0xec97a0de415ce5348ebe21219a3cbe17938f07344276f64ec40e1dced411c131&quot;
      - &quot;0xd34bdde7bf541ae5af14a22f182fe4a5087d292e96c952ec405b9c04fd71645c&quot;
      - &quot;0x69b84b7fa3b0dda0b7eaf825ac386bd2416359a1c076743901c727adfbad4022&quot;
    deposit_root: &quot;0x0a872a65e20b1d6eb13282886f5082a99b3ac36e5636c6b7667d6f7b454c136f&quot;
    deposit_count: 359
    execution_block_hash: &quot;0x05f878ea1b32f42d1b5eb823c090f2789b19a062bc3495d80402a3077ccab36d&quot;
    execution_block_height: 360
- deposit_data:
    pubkey: &quot;0xb5dd36fb996d68fb9dff117081435088b54509db6c3bdcbe58bb3711fd21b62f22f7ffef9b8ead2031c0c187717ca738&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa704de41a3d802906eaa920016df241c8e6a483b25b6a144811305341d631c9159b7453c16fc7266c005d20a362b52ea1322e545ccb84f995f863b30f5b31d0af2824cbd21cf7dfce43fb369cb77cd92dfa58ea2c515d99c4b1e82b30a4001ba&quot;
  deposit_data_root: &quot;0xe392df1901cb47c60f7a23312f4938957258d1e4552775a6c9e1716318ebc23c&quot;
  eth1_data:
    deposit_root: &quot;0x566ee27dc76d160c182b89a8152d85644ad00ae1a6dffa89e096d383f612e4f0&quot;
    deposit_count: &quot;360&quot;
    block_hash: &quot;0xe3a5318a234c6d5ceddb72a5dbcdd3d1424a17d8ca7b08bc7bbdd55b6aa0d9c3&quot;
  block_height: 361
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0xc93d9dcfae7c9e728958d0b093f1fe4ae72fb7d51eb5bc91a9a106e417426fc1&quot;
    deposit_root: &quot;0x566ee27dc76d160c182b89a8152d85644ad00ae1a6dffa89e096d383f612e4f0&quot;
    deposit_count: 360
    execution_block_hash: &quot;0xe3a5318a234c6d5ceddb72a5dbcdd3d1424a17d8ca7b08bc7bbdd55b6aa0d9c3&quot;
    execution_block_height: 361
- deposit_data:
    pubkey: &quot;0x9376161dba759909776ec807351e1cdafbff9a9d817babba680c953344a80dcaa38378ac6a7fb3079d909f5907310336&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8b38fdafe54fb8e27ad780c4fa0910777e6d0f8ece579bfbd4a0cf121eca3de1e1e19dfdf284db7516d25265f9c989210ed3894e1c6c6e3365d99e9f3357b39bcf791ea2e08c43059e2adc753ea6c96a68ca0134395f7b8cb25662d87339157b&quot;
  deposit_data_root: &quot;0xb1df04177e3328845d9af042b46eb4b7b5d4d0c8c884a28c2ad183ed23801013&quot;
  eth1_data:
    deposit_root: &quot;0x77959d8e2c2c5ce3fda7eb96f376f88a281224e3eaf3fe232d20d35eef2d4f2e&quot;
    deposit_count: &quot;361&quot;
    block_hash: &quot;0x42046b4ccdbc910edab7da07038bb06f7cf7a9f01da446b7896260e2fb0a797a&quot;
  block_height: 362
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0xc93d9dcfae7c9e728958d0b093f1fe4ae72fb7d51eb5bc91a9a106e417426fc1&quot;
      - &quot;0xb1df04177e3328845d9af042b46eb4b7b5d4d0c8c884a28c2ad183ed23801013&quot;
    deposit_root: &quot;0x77959d8e2c2c5ce3fda7eb96f376f88a281224e3eaf3fe232d20d35eef2d4f2e&quot;
    deposit_count: 361
    execution_block_hash: &quot;0x42046b4ccdbc910edab7da07038bb06f7cf7a9f01da446b7896260e2fb0a797a&quot;
    execution_block_height: 362
- deposit_data:
    pubkey: &quot;0x8d92d91ccf259f1c3df11d2e4e92cbe047a9b278ab9ee1341835a08da4c957950a70f51d62bbefd4c6f3c01511e39796&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x83b14219e42c4389f315892b1f7bf34a7d9649aa91086b2a3a5d06fa5822af504b9f46364e39a5406a33bb8feb3baa540f90dda0d091ca6cd9df322bb81e1220af8a63a3ac9f5bea4db7ea883d8e7b39df07c59f7d478c9754455e84f556d1dc&quot;
  deposit_data_root: &quot;0xb65dfed61fae9bb5cfe7b84bb94b11aed1949d8c0f2ab1bad962aa2639ee9ea5&quot;
  eth1_data:
    deposit_root: &quot;0x8ce66b4067fd288192b5cf456c79dbf793d86adf144f0ded5837fa2f916330dd&quot;
    deposit_count: &quot;362&quot;
    block_hash: &quot;0x30caf55961a0afa34e0ea7fe1c82badaf3bcb966c3e27b5f6d28f5dc90cdac8f&quot;
  block_height: 363
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0xc93d9dcfae7c9e728958d0b093f1fe4ae72fb7d51eb5bc91a9a106e417426fc1&quot;
      - &quot;0xededa6672e4f4f520b91640b5d0e396d02af2d267ed8a7f99ec6844a81bd3197&quot;
    deposit_root: &quot;0x8ce66b4067fd288192b5cf456c79dbf793d86adf144f0ded5837fa2f916330dd&quot;
    deposit_count: 362
    execution_block_hash: &quot;0x30caf55961a0afa34e0ea7fe1c82badaf3bcb966c3e27b5f6d28f5dc90cdac8f&quot;
    execution_block_height: 363
- deposit_data:
    pubkey: &quot;0xa95aa6bfc756de15cb1a21d05b465afd5bf806faee4e662ec335d1e093299632f9498dff50c71844e28d98b0d2cb9e29&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xab509e72eb0293f13ff2cb2dea99e6289562f8315b1f70c913f1a7705b45c6398150df3cc1991edd1ef7d0c72cd0925712a04bf9161f3f7d5548ec6f0ec4c2271054fcca875d6258a204d5478a4396dafcb2d99083ef2c990111cbe6c9b62b07&quot;
  deposit_data_root: &quot;0xf0a5d8ef855f6d121a251189ad5dfe512c221f0f27e4f7225fc37e163001359c&quot;
  eth1_data:
    deposit_root: &quot;0x8c048d62dd48e2676a75bf37278cf8a81934a702809656d92f153568b81893a6&quot;
    deposit_count: &quot;363&quot;
    block_hash: &quot;0x7dbc675b430d7c2de00d444ad4babab187b9590770a385b9c34b97f8f9db8bf7&quot;
  block_height: 364
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0xc93d9dcfae7c9e728958d0b093f1fe4ae72fb7d51eb5bc91a9a106e417426fc1&quot;
      - &quot;0xededa6672e4f4f520b91640b5d0e396d02af2d267ed8a7f99ec6844a81bd3197&quot;
      - &quot;0xf0a5d8ef855f6d121a251189ad5dfe512c221f0f27e4f7225fc37e163001359c&quot;
    deposit_root: &quot;0x8c048d62dd48e2676a75bf37278cf8a81934a702809656d92f153568b81893a6&quot;
    deposit_count: 363
    execution_block_hash: &quot;0x7dbc675b430d7c2de00d444ad4babab187b9590770a385b9c34b97f8f9db8bf7&quot;
    execution_block_height: 364
- deposit_data:
    pubkey: &quot;0x89f4dc26316e4037269b4afd3d92f7aa9d768be37dd951829657941f2220f7546071ac46a72d715a1af71689982afe61&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb7be13f710902b118aabf1b4e84f6e67bb72bb4df89a9444dffcdc9db966fd451b4f16cebfa6546a41f0b7ec4a52baa206133d4190cbcf26b266d5f0dda6231d720a0cfb21c671008b84b230f851a4e9bdb87c78f81a2c4cee31bea858596c68&quot;
  deposit_data_root: &quot;0xbbd775efe2df031eb9719e580ea4259844d508dcaeb723b6698c3896dee27771&quot;
  eth1_data:
    deposit_root: &quot;0xf5ed206c675198fb290d0298805bdd34ecb569f3a14bcddba8343424118d0609&quot;
    deposit_count: &quot;364&quot;
    block_hash: &quot;0x8969f759d3bd762bf45f15e4a30f4c733ac0a822a698027610cac5618cb35e91&quot;
  block_height: 365
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0xc93d9dcfae7c9e728958d0b093f1fe4ae72fb7d51eb5bc91a9a106e417426fc1&quot;
      - &quot;0x6ad91868ba8f36bf1cf9fc3a3226e8fa1b5b3182911ab1db6c7bfd830938d689&quot;
    deposit_root: &quot;0xf5ed206c675198fb290d0298805bdd34ecb569f3a14bcddba8343424118d0609&quot;
    deposit_count: 364
    execution_block_hash: &quot;0x8969f759d3bd762bf45f15e4a30f4c733ac0a822a698027610cac5618cb35e91&quot;
    execution_block_height: 365
- deposit_data:
    pubkey: &quot;0x812c4ef835a77db7ead5b86773755711051cbc34cfdc4be7eb41a99ce5094f7d12412a7215275cd9ae8d8426eb91dfb4&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa6785218f754ef90bb5d5b308a6b1bd2078c6d1c03845c874515ae4fb2da4b44dd4d34dcfaf5a5057b8f90d0e9154e56155038a0dd687eca319de2270b634a6d0038f72a05b6c89e85c00c53a4ef259dbe3f1300c7bf4c63c2fd1e7b62488abd&quot;
  deposit_data_root: &quot;0xdae505a2425fa70ac7714c907d1918d77c0ef04f4654bc884353791f0b148071&quot;
  eth1_data:
    deposit_root: &quot;0xbab7a3b70441e52c82a2a43408ca1f6957abf9f2189daca60838341f23a14cbc&quot;
    deposit_count: &quot;365&quot;
    block_hash: &quot;0xc56ca86bea734411f9a9a8ce247094bbd5d632888cdbe1938df31acb880e662d&quot;
  block_height: 366
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0xc93d9dcfae7c9e728958d0b093f1fe4ae72fb7d51eb5bc91a9a106e417426fc1&quot;
      - &quot;0x6ad91868ba8f36bf1cf9fc3a3226e8fa1b5b3182911ab1db6c7bfd830938d689&quot;
      - &quot;0xdae505a2425fa70ac7714c907d1918d77c0ef04f4654bc884353791f0b148071&quot;
    deposit_root: &quot;0xbab7a3b70441e52c82a2a43408ca1f6957abf9f2189daca60838341f23a14cbc&quot;
    deposit_count: 365
    execution_block_hash: &quot;0xc56ca86bea734411f9a9a8ce247094bbd5d632888cdbe1938df31acb880e662d&quot;
    execution_block_height: 366
- deposit_data:
    pubkey: &quot;0x8cfd6c4fe7aee61657f1d6e5cff1d41d24bafab7ceea78d2f5d680f8b51aeea83ddbb39bf6978bbf1327a2d240012551&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa8e2e30e4d30c5401f9fa6260da87b0468c53580f230c36255690955f4fddf3433da05d174390d687b79749afac5870c19b33d828ee655d6084b4a346df8d0aef3ef8491e99855e80d9e6413d0e28ae091303e3af2148166eace0d828eecf868&quot;
  deposit_data_root: &quot;0x2873cca6fb60ed389212d5624bc18fdd882ccfb57d60c6fa5858bcee68ce8f8d&quot;
  eth1_data:
    deposit_root: &quot;0x31afd21b630f676a5b7673355f85afc5c2b4206ff10a7200586b0a61e918c632&quot;
    deposit_count: &quot;366&quot;
    block_hash: &quot;0x6d39ef06bbcadfcc1889b64112e7060c1f2065d6b254466e765603decd8b505d&quot;
  block_height: 367
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0xc93d9dcfae7c9e728958d0b093f1fe4ae72fb7d51eb5bc91a9a106e417426fc1&quot;
      - &quot;0x6ad91868ba8f36bf1cf9fc3a3226e8fa1b5b3182911ab1db6c7bfd830938d689&quot;
      - &quot;0xca7eee30dc4dae479488e27d2be31d92c9f9e2e3cd1b76c56bd8c0f895399c1c&quot;
    deposit_root: &quot;0x31afd21b630f676a5b7673355f85afc5c2b4206ff10a7200586b0a61e918c632&quot;
    deposit_count: 366
    execution_block_hash: &quot;0x6d39ef06bbcadfcc1889b64112e7060c1f2065d6b254466e765603decd8b505d&quot;
    execution_block_height: 367
- deposit_data:
    pubkey: &quot;0xae7c6ebb4d7b5f462da2004698a6dc54f1e55ef0f3ecd0bc155c9b58f67a038422e209492c86c986d8f24f5261126f51&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb5e4a27b8a2a022d4f4748b6277a7a3400866ccbef70d8b13578af0227c4491a9fb4934e23342bef47277ebbecebbcf101334a722540f70c1d3d768c870cfbf2cc3fba8cb7260dcb794b455083f4a092e54d441d5acee80b57d9d9ca8ee34057&quot;
  deposit_data_root: &quot;0x0b99abe0654b3fdb3e10c60bf63da44170f75887fb61a4be8119ac5d7f84f7e0&quot;
  eth1_data:
    deposit_root: &quot;0x25e729835c195d00e120e374d28e26a9e19eeab013878aebbc5b37b29f2c61a0&quot;
    deposit_count: &quot;367&quot;
    block_hash: &quot;0xb187bb0435d4f02e62beaaf1833b7ae3cd93e1acc0fc9dbfdf24f6d0b48d3d1b&quot;
  block_height: 368
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0xc93d9dcfae7c9e728958d0b093f1fe4ae72fb7d51eb5bc91a9a106e417426fc1&quot;
      - &quot;0x6ad91868ba8f36bf1cf9fc3a3226e8fa1b5b3182911ab1db6c7bfd830938d689&quot;
      - &quot;0xca7eee30dc4dae479488e27d2be31d92c9f9e2e3cd1b76c56bd8c0f895399c1c&quot;
      - &quot;0x0b99abe0654b3fdb3e10c60bf63da44170f75887fb61a4be8119ac5d7f84f7e0&quot;
    deposit_root: &quot;0x25e729835c195d00e120e374d28e26a9e19eeab013878aebbc5b37b29f2c61a0&quot;
    deposit_count: 367
    execution_block_hash: &quot;0xb187bb0435d4f02e62beaaf1833b7ae3cd93e1acc0fc9dbfdf24f6d0b48d3d1b&quot;
    execution_block_height: 368
- deposit_data:
    pubkey: &quot;0xa4ee2d6f77a08089c71194ab48c338632c6b1041c326a483033aecd1bac1baf5de221053ea15c9fbdb8584edec6a731f&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa868efa2a6b92d1cc547bf3352b67b142dcb106cffd3510caa09eca8071bac276d217af7aec4551b8da80f1dd7c5d62117c74d40e9204580cf0d68ef795e9c226ca17a0cc54f8da1fd5c9ed4a9721c27f646d3c8166cf711de031d1442793bd7&quot;
  deposit_data_root: &quot;0x8ecabb629b1e1da971d5edf0f68c6f7e56a15adf30f5a224ced581e1307efa17&quot;
  eth1_data:
    deposit_root: &quot;0x71a7e69529e1627bebfe2eb84e5387960b67bfb45ea7c73b36e9f26b039abb48&quot;
    deposit_count: &quot;368&quot;
    block_hash: &quot;0x24625a939c0317893b0a4ff7e485998efedcc1219caf706cdcf98a955ac6eed0&quot;
  block_height: 369
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0x7472f8762e7585ee829a64478023f69abff5f1a3c9c0b7eb37c5e0e530fd27cb&quot;
    deposit_root: &quot;0x71a7e69529e1627bebfe2eb84e5387960b67bfb45ea7c73b36e9f26b039abb48&quot;
    deposit_count: 368
    execution_block_hash: &quot;0x24625a939c0317893b0a4ff7e485998efedcc1219caf706cdcf98a955ac6eed0&quot;
    execution_block_height: 369
- deposit_data:
    pubkey: &quot;0x82d62ceb1242d6dc6527d8f885fe301f4313b87e7e336a34a8d3a898ffca180dbc624f45e1dc07695cecc54023207400&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xafe8ea26e0356b1ffe34ee1f6e50d8f046ab3d7eaa3decae78fede0b56b8b04903031de2fb45a877b80ad5baca8dc6d900adf83f4617563bf9658627a40b601f5ee3e53980bc51584ee4c05ce88c3ca720b1214697668104dae210e7cbffaaaa&quot;
  deposit_data_root: &quot;0x73aa59f819c871ac6651030e64fbeb030153e12d230d516c22b768230dd7c65c&quot;
  eth1_data:
    deposit_root: &quot;0x427c76f57c454b3d1154f3df3f645e88551b6d51f544aef9789dd63f26dfb705&quot;
    deposit_count: &quot;369&quot;
    block_hash: &quot;0x791a39d5642a805a00de9be73ed412bb5870ca828e2b8bd41e1ef0919336860a&quot;
  block_height: 370
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0x7472f8762e7585ee829a64478023f69abff5f1a3c9c0b7eb37c5e0e530fd27cb&quot;
      - &quot;0x73aa59f819c871ac6651030e64fbeb030153e12d230d516c22b768230dd7c65c&quot;
    deposit_root: &quot;0x427c76f57c454b3d1154f3df3f645e88551b6d51f544aef9789dd63f26dfb705&quot;
    deposit_count: 369
    execution_block_hash: &quot;0x791a39d5642a805a00de9be73ed412bb5870ca828e2b8bd41e1ef0919336860a&quot;
    execution_block_height: 370
- deposit_data:
    pubkey: &quot;0x9337d74573784dae1f5badff018e4f1c5a2f19d1b57ac07a2f12dd628ed97a4b3a4c84ff4c7d291063f78ec15ec163ca&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x96eb75a5657091aa6019a5b6755aca55b675e7ea964b4e88c4f3528d47768cf37b5edc524325b3f969ccfab550d0e3f4027ea30bb3a2ba00c9cb850a7391a7d37175b5f790ef21b710b25bfa0e48b18ea67d8f51c77fda44da5356750a1d77da&quot;
  deposit_data_root: &quot;0x0bf34b47edadc088a1567b156f78bf0b3ba212689efb7262d3e992f106b79228&quot;
  eth1_data:
    deposit_root: &quot;0xa7bda8ebefccf3bf5ec32d0a67a48d1266fdcc537bea36a2c2e721aa2149be77&quot;
    deposit_count: &quot;370&quot;
    block_hash: &quot;0x47a677735c1aa41443778a8f1d010fd55ec000d87ea1b41d9f7b06e3ae6108f3&quot;
  block_height: 371
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0x7472f8762e7585ee829a64478023f69abff5f1a3c9c0b7eb37c5e0e530fd27cb&quot;
      - &quot;0x415cb916cdf12ea2e3a80a5a17730fb71ba09e3dee19953b2144ff451717f33a&quot;
    deposit_root: &quot;0xa7bda8ebefccf3bf5ec32d0a67a48d1266fdcc537bea36a2c2e721aa2149be77&quot;
    deposit_count: 370
    execution_block_hash: &quot;0x47a677735c1aa41443778a8f1d010fd55ec000d87ea1b41d9f7b06e3ae6108f3&quot;
    execution_block_height: 371
- deposit_data:
    pubkey: &quot;0x91fa5a8682921fa6dce932b8a9cd3e58ac485c03ef81202f69635f463ced2b366a85a3b6aff905542840c05b5739d7d4&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8360efa2ef67875dd7e4ec4d36b39f47adcee01a71d891c61a398413a3fd4e4d26f47f4dd72e4eb193f309d65409567302f99039c476d4f43a03d47285af9d9cd4ae8ab5ee1b9f6f0fc2c90511704414619a4de063ae1248fafc7d0c3822ec6b&quot;
  deposit_data_root: &quot;0xde1d11e466b6199447c8461b2b04c55cc78b3d53aba3dd0f663c2eaa0e6f3d8d&quot;
  eth1_data:
    deposit_root: &quot;0xa6897fb6ab9ffb723e0af72cf18a2f1baa6356017f5931ac3a96050d0a02a0ba&quot;
    deposit_count: &quot;371&quot;
    block_hash: &quot;0xb6ea6ec5773f90cd394c362390e482e0526049017d7027be09902e00dd800d05&quot;
  block_height: 372
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0x7472f8762e7585ee829a64478023f69abff5f1a3c9c0b7eb37c5e0e530fd27cb&quot;
      - &quot;0x415cb916cdf12ea2e3a80a5a17730fb71ba09e3dee19953b2144ff451717f33a&quot;
      - &quot;0xde1d11e466b6199447c8461b2b04c55cc78b3d53aba3dd0f663c2eaa0e6f3d8d&quot;
    deposit_root: &quot;0xa6897fb6ab9ffb723e0af72cf18a2f1baa6356017f5931ac3a96050d0a02a0ba&quot;
    deposit_count: 371
    execution_block_hash: &quot;0xb6ea6ec5773f90cd394c362390e482e0526049017d7027be09902e00dd800d05&quot;
    execution_block_height: 372
- deposit_data:
    pubkey: &quot;0x8631b733c42dcdc91e0852655e1513864b50fd75ca1078a205205afd3d2c0de2cb2da63c06f4f547212132fd66bd7d16&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa4258cf976f155bb4eb8566777cf34184a34b1c8090f931c9160c0b616afae1182256741674af7df73e11ff1db5dad7e165d952269a1aa8a68a523e87a9de14d00c3a928e97a1e7e74aab45331d12f23ec55fface9826bec0c71d3d985624b49&quot;
  deposit_data_root: &quot;0xf449648967e51c3ddd171deffae8afbbd69753f29f5f65659a6a2c6bfe4191db&quot;
  eth1_data:
    deposit_root: &quot;0x96fb5489ed0128e41f8d22f65a9e02b05e3febfa35b4a0c2ead831cb68e0f1dd&quot;
    deposit_count: &quot;372&quot;
    block_hash: &quot;0xe7dba8e784a1897ee5404a1cfb172fd5e5897c784e72596431b8b6cd7caf0fa6&quot;
  block_height: 373
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0x7472f8762e7585ee829a64478023f69abff5f1a3c9c0b7eb37c5e0e530fd27cb&quot;
      - &quot;0xfdb57c8fa36c5390b466ad79c9bcd9f3991ab173af3c339170f8c82eb63f0251&quot;
    deposit_root: &quot;0x96fb5489ed0128e41f8d22f65a9e02b05e3febfa35b4a0c2ead831cb68e0f1dd&quot;
    deposit_count: 372
    execution_block_hash: &quot;0xe7dba8e784a1897ee5404a1cfb172fd5e5897c784e72596431b8b6cd7caf0fa6&quot;
    execution_block_height: 373
- deposit_data:
    pubkey: &quot;0x965258ea99b6f1eefc8d8196fad346c44b559e00fb31baf7cdda18e25b185eaafa91e3e366712514ab3ab855f41c9600&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb70f284e086d2d8d95b2fc7adf1937e52732e39294ef3b836df58c7cd8cb3fbada21137cd66070b82799cce72a4d741f0b66bfc892c5c3ec6ae1aa6e583f2abc05994af795607753085b556955cbd33df389e9ed86addc952a78a8f959c42711&quot;
  deposit_data_root: &quot;0xb2b1703e6974ab25bd10e04e11c2e1f427cae39f2a5cade05266982616651ec6&quot;
  eth1_data:
    deposit_root: &quot;0x5af7c0eefdca4998093fee555e6b38acaf0ab646a17afb02712b2fc83f405d20&quot;
    deposit_count: &quot;373&quot;
    block_hash: &quot;0x5967feb20145233cf4deb33b3595e0f074a8c3af859acde36bf21d8d412020f6&quot;
  block_height: 374
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0x7472f8762e7585ee829a64478023f69abff5f1a3c9c0b7eb37c5e0e530fd27cb&quot;
      - &quot;0xfdb57c8fa36c5390b466ad79c9bcd9f3991ab173af3c339170f8c82eb63f0251&quot;
      - &quot;0xb2b1703e6974ab25bd10e04e11c2e1f427cae39f2a5cade05266982616651ec6&quot;
    deposit_root: &quot;0x5af7c0eefdca4998093fee555e6b38acaf0ab646a17afb02712b2fc83f405d20&quot;
    deposit_count: 373
    execution_block_hash: &quot;0x5967feb20145233cf4deb33b3595e0f074a8c3af859acde36bf21d8d412020f6&quot;
    execution_block_height: 374
- deposit_data:
    pubkey: &quot;0xaff02f3635554e57d140069596a9c3463e85408521b2349b6d1d5c4223874086dfa5a58f8ca73256ebfccc63fb88e58b&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa04bb8b421c6e3a97b2d678db62adffaded29db686da4adfe0e05dbb50e55cb95631a5298136778ac5d0fed413b291cf042ea8fd3406cb4cb196bdf190eac79e2e3526943df94b58465e40925255d38fcf6238069bfab4a3349d7e02490ce24d&quot;
  deposit_data_root: &quot;0xb2bf57e882657383825bc6f7228e5a6c1c518c48de44a855ac853b521d8d28a2&quot;
  eth1_data:
    deposit_root: &quot;0xc88fceb356cfdc6fd64eb70a98fb873d921cbe2bfa77f357695682a1db122bfb&quot;
    deposit_count: &quot;374&quot;
    block_hash: &quot;0x4cbd9a54874e2dff03520d5313f7d0f436fd15e2e6adf2010430159f3c884345&quot;
  block_height: 375
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0x7472f8762e7585ee829a64478023f69abff5f1a3c9c0b7eb37c5e0e530fd27cb&quot;
      - &quot;0xfdb57c8fa36c5390b466ad79c9bcd9f3991ab173af3c339170f8c82eb63f0251&quot;
      - &quot;0xaa4ae80e4b97e7e7234fbf9b4581551d8b01473b0e06b9ae16eda5add93de3b1&quot;
    deposit_root: &quot;0xc88fceb356cfdc6fd64eb70a98fb873d921cbe2bfa77f357695682a1db122bfb&quot;
    deposit_count: 374
    execution_block_hash: &quot;0x4cbd9a54874e2dff03520d5313f7d0f436fd15e2e6adf2010430159f3c884345&quot;
    execution_block_height: 375
- deposit_data:
    pubkey: &quot;0xa166c85614c5b0d5af165a42ab98515c009b6eccb740213e6ec1268e35aebaa73b8c9b22711aac0d5087f2534604eb36&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb2f0a3f9d23101580d45e327cb58559a0eb0da2ef98ba8296040c0189c32cf5d400e49e45d408961a44ec1755f303be516949f3ed899d1b0afaa4cf3c237f7c1dcf538539d48c8b013601db131b2753b456bfa683922a1be60f306c491958146&quot;
  deposit_data_root: &quot;0x635116788f81411826a4bab6c7b0c4d22d8a100053efca983cafed46f19c1128&quot;
  eth1_data:
    deposit_root: &quot;0x41e8cec2e3a73c8bf38474b5ca18043b11f11c9ee9eb0cacc2ffb740e5a57c12&quot;
    deposit_count: &quot;375&quot;
    block_hash: &quot;0xafa631155e92b5e36aa357fdcb2c59894f96d85f0cd7e7704da84c28de104088&quot;
  block_height: 376
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0x7472f8762e7585ee829a64478023f69abff5f1a3c9c0b7eb37c5e0e530fd27cb&quot;
      - &quot;0xfdb57c8fa36c5390b466ad79c9bcd9f3991ab173af3c339170f8c82eb63f0251&quot;
      - &quot;0xaa4ae80e4b97e7e7234fbf9b4581551d8b01473b0e06b9ae16eda5add93de3b1&quot;
      - &quot;0x635116788f81411826a4bab6c7b0c4d22d8a100053efca983cafed46f19c1128&quot;
    deposit_root: &quot;0x41e8cec2e3a73c8bf38474b5ca18043b11f11c9ee9eb0cacc2ffb740e5a57c12&quot;
    deposit_count: 375
    execution_block_hash: &quot;0xafa631155e92b5e36aa357fdcb2c59894f96d85f0cd7e7704da84c28de104088&quot;
    execution_block_height: 376
- deposit_data:
    pubkey: &quot;0x967633e5396683a4d51ac8e531194d8243fb808b3237c5ff635afcc0c6ab3fab8443cf9bc7268c25c85d5c9d3b42463c&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x920074fe4578a343f3c10a152857b1301b3bd370b5fdc6e9f806f46f59360c24cc06b6736572613ec332d06032280b2117f89e75a93ce3102032f5326382113bbb300c6b3e5ce36921f661212338f5342683ede2eb3505bb4ac720cc3c60263a&quot;
  deposit_data_root: &quot;0xfd47af7a32eeeebd5d5e99faf7988bc11d295a16351dd61802acf29bb7c7c48d&quot;
  eth1_data:
    deposit_root: &quot;0xc334c97c33e4fbbd1cb28802b5845db45ba26f0583b88374f650c08f577a4629&quot;
    deposit_count: &quot;376&quot;
    block_hash: &quot;0x0477978ff52a8aadcc642ebf3e523c6fab4b2be5cd8e92abaf545f1f4974aabc&quot;
  block_height: 377
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0x7472f8762e7585ee829a64478023f69abff5f1a3c9c0b7eb37c5e0e530fd27cb&quot;
      - &quot;0x14503e81d68b81b6107b25a5cff097ac43e0ded9988b742805a287d02c1ac8ec&quot;
    deposit_root: &quot;0xc334c97c33e4fbbd1cb28802b5845db45ba26f0583b88374f650c08f577a4629&quot;
    deposit_count: 376
    execution_block_hash: &quot;0x0477978ff52a8aadcc642ebf3e523c6fab4b2be5cd8e92abaf545f1f4974aabc&quot;
    execution_block_height: 377
- deposit_data:
    pubkey: &quot;0xb3dab04913697100af2268f8d71e4daaa6475d08785b4ab816d1a9d209703abdb3e890dcec518c88cb5983d30e977408&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x84f73f81a47107e055c2332123f547da1c2d16e3434b8f2a2cfc18d2f23c17257cd047b6bc12cef2c1e32473afa897f802ada46f50d4c910ff4048927c64c3983e42c8c5e3681da8ed296589b8481314ddf847049451cdc7e429520f2a2f5ef3&quot;
  deposit_data_root: &quot;0x6dad28a69491a04e60893860dba1bc4be2ddc602499a2c1893fbbc9f3a24ebd6&quot;
  eth1_data:
    deposit_root: &quot;0x2817a89668f5bbc79855acf38ecd0089aebd5aed31a3a919aae56f2609d16eb4&quot;
    deposit_count: &quot;377&quot;
    block_hash: &quot;0x5e0a1b630591445514724260df8d60a7c36529f0d6c532b19b8115681c754df6&quot;
  block_height: 378
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0x7472f8762e7585ee829a64478023f69abff5f1a3c9c0b7eb37c5e0e530fd27cb&quot;
      - &quot;0x14503e81d68b81b6107b25a5cff097ac43e0ded9988b742805a287d02c1ac8ec&quot;
      - &quot;0x6dad28a69491a04e60893860dba1bc4be2ddc602499a2c1893fbbc9f3a24ebd6&quot;
    deposit_root: &quot;0x2817a89668f5bbc79855acf38ecd0089aebd5aed31a3a919aae56f2609d16eb4&quot;
    deposit_count: 377
    execution_block_hash: &quot;0x5e0a1b630591445514724260df8d60a7c36529f0d6c532b19b8115681c754df6&quot;
    execution_block_height: 378
- deposit_data:
    pubkey: &quot;0xa4bdf84013dca6a9af8d56d0bec9767a969d7b0b88802ef0eac99a9551dcbc7e03336e63943d8cd072be2d2915d9db25&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8da17c87dc9aad2a3ac17331e00065d70a1c5351f063d22e23f9047d45938cec61ce0f0eba5966a85694dc30298fce9f1726b82286483f93c9ee867095eb398daa696e6ff40d0b525c1d249f48359d70f7f115c53f45a517d1dc1d024a40991b&quot;
  deposit_data_root: &quot;0xd9d6dd6ace596c76d133833e081bfb09dae6f0b3fb68ff016b2c3157e19ecc16&quot;
  eth1_data:
    deposit_root: &quot;0x0c72dbb6dec2b4a4f0b06aff6b28e5d323de1238e9c38b01414d588302cf341c&quot;
    deposit_count: &quot;378&quot;
    block_hash: &quot;0x613eb202e2e6e48ddab9d97aa5bc39164d7dac1613890ea7840783b6abc54c58&quot;
  block_height: 379
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0x7472f8762e7585ee829a64478023f69abff5f1a3c9c0b7eb37c5e0e530fd27cb&quot;
      - &quot;0x14503e81d68b81b6107b25a5cff097ac43e0ded9988b742805a287d02c1ac8ec&quot;
      - &quot;0xe1fb9fc453a915b6bddc83453cbc120de96754c37d0aabe33eae0320527ced59&quot;
    deposit_root: &quot;0x0c72dbb6dec2b4a4f0b06aff6b28e5d323de1238e9c38b01414d588302cf341c&quot;
    deposit_count: 378
    execution_block_hash: &quot;0x613eb202e2e6e48ddab9d97aa5bc39164d7dac1613890ea7840783b6abc54c58&quot;
    execution_block_height: 379
- deposit_data:
    pubkey: &quot;0xb83a5503f8875dba99bfb8077c50b56120456f836cbb8b89a24e17d88c76071ed9b08a54500ad8e24382a43fa67df89a&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb5eeec2defcdfb4015ec6f688f641a597f533106ab62765585e59e86a27e807cf322008469bd8e3649fd7ae4a367ff8a05956b65081161d7f227bc72a5385696e36a77a1c9b77d4bd553be66e1166efa80b9708605f6480dbf72ffa229a43c29&quot;
  deposit_data_root: &quot;0x174145bc6f9323ff01709c7c767c1a2f3e2608a17e8393966c64a5f1a34ad0b3&quot;
  eth1_data:
    deposit_root: &quot;0x32dc12145beb7653b4766efb4d84b1590f50be40852bb4281f0f29c0e1c5d874&quot;
    deposit_count: &quot;379&quot;
    block_hash: &quot;0x76901b62737505430cab3df9d5e8bcf58ec8f86c3db8c95a3cd14838a28a923b&quot;
  block_height: 380
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0x7472f8762e7585ee829a64478023f69abff5f1a3c9c0b7eb37c5e0e530fd27cb&quot;
      - &quot;0x14503e81d68b81b6107b25a5cff097ac43e0ded9988b742805a287d02c1ac8ec&quot;
      - &quot;0xe1fb9fc453a915b6bddc83453cbc120de96754c37d0aabe33eae0320527ced59&quot;
      - &quot;0x174145bc6f9323ff01709c7c767c1a2f3e2608a17e8393966c64a5f1a34ad0b3&quot;
    deposit_root: &quot;0x32dc12145beb7653b4766efb4d84b1590f50be40852bb4281f0f29c0e1c5d874&quot;
    deposit_count: 379
    execution_block_hash: &quot;0x76901b62737505430cab3df9d5e8bcf58ec8f86c3db8c95a3cd14838a28a923b&quot;
    execution_block_height: 380
- deposit_data:
    pubkey: &quot;0x83e32149769b6c9091f8921195802c8948cfd2b6c9bf9760e70641757719e028d0e65c85bd0fccbc10b81cbad1c87d9a&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x93b8c60e836c5181647760ae65b7b5f14a89c2b09dbfbfd96aad5dcd2f569414e50e0008e821b9abf0b7b7e7c7e389a00b7cd596c6410826d484d31aa303a134c4f518d7351abf82d8d745944924bb3240ffa81d2bbfb4b2ebe1cc241aa9bf65&quot;
  deposit_data_root: &quot;0x8970139619fc0b0d1fcb5f385618ce7d725d20c55c85a77aea8b749d5ae5dd33&quot;
  eth1_data:
    deposit_root: &quot;0x1fcd7cba4e2a28308ec039550a5044e24d2e76576f39e7e5d6d08325cd8f820d&quot;
    deposit_count: &quot;380&quot;
    block_hash: &quot;0x941b810b7df953ef1c939599bf5f91fa02b40c02ecdbc9db3b835903b85b4ee9&quot;
  block_height: 381
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0x7472f8762e7585ee829a64478023f69abff5f1a3c9c0b7eb37c5e0e530fd27cb&quot;
      - &quot;0x14503e81d68b81b6107b25a5cff097ac43e0ded9988b742805a287d02c1ac8ec&quot;
      - &quot;0x05b6bbc7f807ab0dcc2cc1033e4743bfa978b4068e735ef860846a4ef71e4ef3&quot;
    deposit_root: &quot;0x1fcd7cba4e2a28308ec039550a5044e24d2e76576f39e7e5d6d08325cd8f820d&quot;
    deposit_count: 380
    execution_block_hash: &quot;0x941b810b7df953ef1c939599bf5f91fa02b40c02ecdbc9db3b835903b85b4ee9&quot;
    execution_block_height: 381
- deposit_data:
    pubkey: &quot;0xb3b60189b0b7dec69db000719fc89cc811c60e70b80d764af86a9dde1c4becba8e561d9f4ca5437481f01b0d7d1fc807&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x959a30b65aafdc7e021fecd8d5eba6e2b0a4d0dd63aff40824a6a3b9b1b63804be39acce4df08e4025ed5445c606761d0f0090182aaed4727b7d5da87b0437e3a5ff8b395e9e4d241fc3f822ce92717733c58d54172fb14e7ca07aaa85243835&quot;
  deposit_data_root: &quot;0x4282b4b40da830d37635588ea701f4837f32e70f1a4177192b5f3f9e53991a86&quot;
  eth1_data:
    deposit_root: &quot;0x391f2ad9469d6191d978da35b42beddd2f61857f0ca40c88b395913d472c1b83&quot;
    deposit_count: &quot;381&quot;
    block_hash: &quot;0xdc138b7ce041cc906320c6e6180e0410b939b18fa470ad5531bb3eb5484dad2c&quot;
  block_height: 382
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0x7472f8762e7585ee829a64478023f69abff5f1a3c9c0b7eb37c5e0e530fd27cb&quot;
      - &quot;0x14503e81d68b81b6107b25a5cff097ac43e0ded9988b742805a287d02c1ac8ec&quot;
      - &quot;0x05b6bbc7f807ab0dcc2cc1033e4743bfa978b4068e735ef860846a4ef71e4ef3&quot;
      - &quot;0x4282b4b40da830d37635588ea701f4837f32e70f1a4177192b5f3f9e53991a86&quot;
    deposit_root: &quot;0x391f2ad9469d6191d978da35b42beddd2f61857f0ca40c88b395913d472c1b83&quot;
    deposit_count: 381
    execution_block_hash: &quot;0xdc138b7ce041cc906320c6e6180e0410b939b18fa470ad5531bb3eb5484dad2c&quot;
    execution_block_height: 382
- deposit_data:
    pubkey: &quot;0xa290656399af969e0a3c03ab8529b6b0173e40c049101115120628fc09d549256f3a358f4cd858e02a9bd025a3e01dd7&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa3cc5bb444b669055ebe709357821e7e18e273b2bef53252325b7dba386016c718cf01557b29f1bb465d3fbf13f7fe1a090b1d24145d090c89e8d6a4ad67b0f23b0bb60fa897bbd65b020c97450e34d7ae4ee61e0685727fab624af4d866ecc7&quot;
  deposit_data_root: &quot;0x1d58a6e4b2fe07612286e5452c9c0bcf810331fdcf21e40471e007178d7ec239&quot;
  eth1_data:
    deposit_root: &quot;0xf40cb049da0e82cda435267314359e780d03f4490204998272fa00a9bd6dc6b5&quot;
    deposit_count: &quot;382&quot;
    block_hash: &quot;0xe1768f362d8733dc9330f62b62842ae31dd708e9d58a0ef208fcb174527cddc5&quot;
  block_height: 383
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0x7472f8762e7585ee829a64478023f69abff5f1a3c9c0b7eb37c5e0e530fd27cb&quot;
      - &quot;0x14503e81d68b81b6107b25a5cff097ac43e0ded9988b742805a287d02c1ac8ec&quot;
      - &quot;0x05b6bbc7f807ab0dcc2cc1033e4743bfa978b4068e735ef860846a4ef71e4ef3&quot;
      - &quot;0x1c38bcf92acf3077bcb07ca54de94f552d3128d9f5abc93eabaabef945993183&quot;
    deposit_root: &quot;0xf40cb049da0e82cda435267314359e780d03f4490204998272fa00a9bd6dc6b5&quot;
    deposit_count: 382
    execution_block_hash: &quot;0xe1768f362d8733dc9330f62b62842ae31dd708e9d58a0ef208fcb174527cddc5&quot;
    execution_block_height: 383
- deposit_data:
    pubkey: &quot;0x8633815ef4ecf32dfd3e6221d877176ef1460f7147edae206349cc816431f1a2d60fc547e6dcf0bd31111fce6a822328&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x877082c5d8d68ce8a2547eb2fa81d42c67b1a0a0da9f62ca4f3ebb6a9f3f5853a627b3cff7e8700a801af5f81e9fd42f0f6dd0952a070a88b3c2ee73adf17e72cc8751ec6dc2f1a513bbe86e25eefd129d532e50ad77223116fb5912233bb858&quot;
  deposit_data_root: &quot;0xc11805cef7cb401d83cfcf73cee9526e60d319d708fb6d19761dfe576352f404&quot;
  eth1_data:
    deposit_root: &quot;0xb93ebaadc7951cd5056e2f900ee21ff1b94a0ef410be2345e9daa5798ee47321&quot;
    deposit_count: &quot;383&quot;
    block_hash: &quot;0x12fcdcd7f54e4f71eadbf4f1c91ab1b40ef47344411169c930298858a1bca8fa&quot;
  block_height: 384
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xc9521569f6cd236e7893e6e538cfe9b294455c57d6738e0d5402dfb51e9edcfb&quot;
      - &quot;0x2e17dc08bed4ab4138ea54b4389d7956de63422e1f873bac51997acd6fc8a70a&quot;
      - &quot;0x7472f8762e7585ee829a64478023f69abff5f1a3c9c0b7eb37c5e0e530fd27cb&quot;
      - &quot;0x14503e81d68b81b6107b25a5cff097ac43e0ded9988b742805a287d02c1ac8ec&quot;
      - &quot;0x05b6bbc7f807ab0dcc2cc1033e4743bfa978b4068e735ef860846a4ef71e4ef3&quot;
      - &quot;0x1c38bcf92acf3077bcb07ca54de94f552d3128d9f5abc93eabaabef945993183&quot;
      - &quot;0xc11805cef7cb401d83cfcf73cee9526e60d319d708fb6d19761dfe576352f404&quot;
    deposit_root: &quot;0xb93ebaadc7951cd5056e2f900ee21ff1b94a0ef410be2345e9daa5798ee47321&quot;
    deposit_count: 383
    execution_block_hash: &quot;0x12fcdcd7f54e4f71eadbf4f1c91ab1b40ef47344411169c930298858a1bca8fa&quot;
    execution_block_height: 384
- deposit_data:
    pubkey: &quot;0xad5539f19d8358478970caa4fb524b274867ca7449141a21fbd07e6b6291177200e9dca369b665e12ed40dea80b69cce&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x99788b2afa65fba3d50ac737cc372707a61a66423e03ca9a96b2bad066a3e939d61ea38ff6abcce5d89dacddde104e701318854c92d09513078171314dfd7f894e818db650e6385bf42748af1b6775d3c7f78f0e344ba1f2e7e01bd812da6c85&quot;
  deposit_data_root: &quot;0xd381809adc653a2cd994826ee024c272920803b10751c15699eeb345a8640448&quot;
  eth1_data:
    deposit_root: &quot;0xb7dd432c5408611d1368a238e7a462ba9294b34e29406a499ead95c513360199&quot;
    deposit_count: &quot;384&quot;
    block_hash: &quot;0xdee05ca3f55492ca6f2e09310db9339bfe0dc2e250f129950c5a430178c04398&quot;
  block_height: 385
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
    deposit_root: &quot;0xb7dd432c5408611d1368a238e7a462ba9294b34e29406a499ead95c513360199&quot;
    deposit_count: 384
    execution_block_hash: &quot;0xdee05ca3f55492ca6f2e09310db9339bfe0dc2e250f129950c5a430178c04398&quot;
    execution_block_height: 385
- deposit_data:
    pubkey: &quot;0x981a72fc476e4f532a10da80f235deb940e4cb6597c8e0f868171488f0eeb5fcc988048dd9ea3bef015aaec0cd79081a&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x84dd84cfaf29083c34505098112ad7f439c066376256a5869e77cb6e702070d864684ac093e37eb26759aca78505bcf5189047ded56671cb09b0eb630ffce2d6407747fbed2530efeb0dd07beab083eaed840e3e8440319f97aad670cefc83fd&quot;
  deposit_data_root: &quot;0x298c5a5474ec0f8a9a1e151a9ee7fc14ea9597803b32884678851dab464385ba&quot;
  eth1_data:
    deposit_root: &quot;0xfc0287e35ac5abcb9e2eac1a295d56d943c303bbb69ed02009c816a1e95ea769&quot;
    deposit_count: &quot;385&quot;
    block_hash: &quot;0xe9257489f72b1836a2f5243c212386fe13e7f1302fde45c66355f7f053ef088d&quot;
  block_height: 386
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x298c5a5474ec0f8a9a1e151a9ee7fc14ea9597803b32884678851dab464385ba&quot;
    deposit_root: &quot;0xfc0287e35ac5abcb9e2eac1a295d56d943c303bbb69ed02009c816a1e95ea769&quot;
    deposit_count: 385
    execution_block_hash: &quot;0xe9257489f72b1836a2f5243c212386fe13e7f1302fde45c66355f7f053ef088d&quot;
    execution_block_height: 386
- deposit_data:
    pubkey: &quot;0x9282d6526651dc5e7caf69877a2209d4346bb231b3caed98fec1c95ce3eed284da0617c4d1722e7c316eecebf73601f4&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8a07056d6cbc4955204e276e443ff9d0b7a22247a7481efd0329dd3f40f7935a8d1a7057ae628f58e4979550025eeb310ac822934b696c3f1988586a32b3b050f4bd34a74b522fbd8e94d6ac66b0127b95d3ff2e0a4d721c2564cead9c8714ab&quot;
  deposit_data_root: &quot;0xc39e707c0c1997a5199a59f529dac27feaa0591599dade101c6bc98e39c500d0&quot;
  eth1_data:
    deposit_root: &quot;0x531ee9c8985bee7183a5dc8fa5639fdf10c28f326426db8a657b0a5750cdbd51&quot;
    deposit_count: &quot;386&quot;
    block_hash: &quot;0x7f66e053d87f7f7b0687a29bcb1b42034b3a318d2918fb763a75a2f7e252cf4a&quot;
  block_height: 387
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x6eb578b1e3f55c300c0071b7f22d0ee4d4a1b7a8415e8756521f9f68caca8852&quot;
    deposit_root: &quot;0x531ee9c8985bee7183a5dc8fa5639fdf10c28f326426db8a657b0a5750cdbd51&quot;
    deposit_count: 386
    execution_block_hash: &quot;0x7f66e053d87f7f7b0687a29bcb1b42034b3a318d2918fb763a75a2f7e252cf4a&quot;
    execution_block_height: 387
- deposit_data:
    pubkey: &quot;0x836f2b3e00dfa069e4f315454cca69a56a36b6d32514ac81d168e34beabc42ea8a27918d60fe14a8c93ccf040faab02d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8d45bf64b1cdfabf3d9d5f86008ed55b03b2e8ca881d85c0131ebde4834c423a8da16e0abb9e963b7b7a3b5e8229dfbe04c89313f74b9e8f319a5f27d19af4c01605129e6bad45047308c4e5d024e47f69a1f84863a770927434625853032b70&quot;
  deposit_data_root: &quot;0xe21a86f0256ac65cb7260bbf774eafa1ca0467dacb31a1fbe35aeb795000470a&quot;
  eth1_data:
    deposit_root: &quot;0x897cea6ff0ca2f5472bbae1583e7d256c8fb1cb9729a415ed2d6fd497ecb83ec&quot;
    deposit_count: &quot;387&quot;
    block_hash: &quot;0x1a8b424e0faa53f76a7a87fb68d980aae685c81c9e79734f883c5a3116bfddcc&quot;
  block_height: 388
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x6eb578b1e3f55c300c0071b7f22d0ee4d4a1b7a8415e8756521f9f68caca8852&quot;
      - &quot;0xe21a86f0256ac65cb7260bbf774eafa1ca0467dacb31a1fbe35aeb795000470a&quot;
    deposit_root: &quot;0x897cea6ff0ca2f5472bbae1583e7d256c8fb1cb9729a415ed2d6fd497ecb83ec&quot;
    deposit_count: 387
    execution_block_hash: &quot;0x1a8b424e0faa53f76a7a87fb68d980aae685c81c9e79734f883c5a3116bfddcc&quot;
    execution_block_height: 388
- deposit_data:
    pubkey: &quot;0xb4d3e8864dc26809ed314a03e60c7fbe63ce8921dcb52affa19837e59639513782a1e526823f77fc9564d8fcc15bb0ba&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8768e4401b70479e0e321cf92cc78d75b597714854e2b28ebe847e50090e3a0c9dfa3e226f80b6b44e070bda975b11a10990f572268d88d9a0060051998c3151bf839bf91b05e417ce5d98978dfdaea0166cac0b3bccddbe52133c47cc5b3917&quot;
  deposit_data_root: &quot;0x67c70be65243658ef363ce8536fd2c09c653a3cd1be0cb7673f8a103ae07b7dd&quot;
  eth1_data:
    deposit_root: &quot;0x707a55c126befe50ff91b08a62770102096b0a4c87aca8ea8821733237f9b4fa&quot;
    deposit_count: &quot;388&quot;
    block_hash: &quot;0x016e4d950de17f13291f14596645de6ae51e40614ce2e39c02159e18a7c9414e&quot;
  block_height: 389
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xafae78b562f726681144ff9aa2563edbda5e907e1eb32ee2babf8792cca6c552&quot;
    deposit_root: &quot;0x707a55c126befe50ff91b08a62770102096b0a4c87aca8ea8821733237f9b4fa&quot;
    deposit_count: 388
    execution_block_hash: &quot;0x016e4d950de17f13291f14596645de6ae51e40614ce2e39c02159e18a7c9414e&quot;
    execution_block_height: 389
- deposit_data:
    pubkey: &quot;0xb35c3469a78ea17878cbb166377b8aaea461a0f7d58cc5f77862cb9a232c5a95452d523362808b661cd24a1e0baa67ab&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x93c7d303f1562b87c5f15c0d45026ba2f5ac22a3ccba6a96310a8962192e0577f6464223375100a8f053cb9fdc03f3e40a91ebe2014116b316a79bed10235831dad5c2886e0cee562b06f2098c70a652196cfa73585d4850f16853eac161d702&quot;
  deposit_data_root: &quot;0xa9dbd218ea842ca62f1647881f4fc2e3bf1dd7a67a4b99eef47d43d74c34ce59&quot;
  eth1_data:
    deposit_root: &quot;0xd9d9f4dadee20fe6a1213a8e4919fe470c34b5315061c12c3326281be071b803&quot;
    deposit_count: &quot;389&quot;
    block_hash: &quot;0x6ebdc4ce688958aa6c4d76d6ee80bed95457f73964cbfa10b2553a44158e1a94&quot;
  block_height: 390
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xafae78b562f726681144ff9aa2563edbda5e907e1eb32ee2babf8792cca6c552&quot;
      - &quot;0xa9dbd218ea842ca62f1647881f4fc2e3bf1dd7a67a4b99eef47d43d74c34ce59&quot;
    deposit_root: &quot;0xd9d9f4dadee20fe6a1213a8e4919fe470c34b5315061c12c3326281be071b803&quot;
    deposit_count: 389
    execution_block_hash: &quot;0x6ebdc4ce688958aa6c4d76d6ee80bed95457f73964cbfa10b2553a44158e1a94&quot;
    execution_block_height: 390
- deposit_data:
    pubkey: &quot;0x800044ce43a3eec0738b16300361bc744173822642fdf7184a7ac58f6b315478c03f8b57efc36b37c262e08b66260dbc&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb0515fc2450c616acbe03511afc4c02b85e0e2ca0793135a3926fa0b55665f37a181379c67f0bfbca09743436891a3a012b8d06ddbadd8ae84a7526b52168b3c19c075917482b5e6347dd134c5a4304d3d4f69310c4a51f611b61756a732acde&quot;
  deposit_data_root: &quot;0x86f5cf1fcdedaef646198af6429d7bfd31f55700f6f9c39625d93b6de78b01bb&quot;
  eth1_data:
    deposit_root: &quot;0xa62e54acb14771006dd11ca8e80ccb43520f1921a58c955e555cef5e45750ee5&quot;
    deposit_count: &quot;390&quot;
    block_hash: &quot;0x1a7e29fe5e78f36f6249c8d0afb846a437d99ec96465d6c64a8bd1fdca8640c0&quot;
  block_height: 391
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xafae78b562f726681144ff9aa2563edbda5e907e1eb32ee2babf8792cca6c552&quot;
      - &quot;0x879021b47e1a1c0942dad2c1b18300857aff607246ec88ae3ff1558391e07509&quot;
    deposit_root: &quot;0xa62e54acb14771006dd11ca8e80ccb43520f1921a58c955e555cef5e45750ee5&quot;
    deposit_count: 390
    execution_block_hash: &quot;0x1a7e29fe5e78f36f6249c8d0afb846a437d99ec96465d6c64a8bd1fdca8640c0&quot;
    execution_block_height: 391
- deposit_data:
    pubkey: &quot;0xa3fe94ea52c28c985a901f8d895f8d2493dd1d939da8f775c7e595379431d557b83efce814b3f2d9b5a463c8ab5234d0&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x84653812b348ba58c6eeddbd85870a0a3109da32bada6c5fb0ccb4f360c1d63866cc3548b03b066c0ff568f82b6bc4ee0e0b6665459569329878cb2a9cf5ee6169ff8b47ebefdc104e5cc3abb9caedd508bce5d02e6a5997b0f2c75f3b31781a&quot;
  deposit_data_root: &quot;0xf4f62e401aa56826818ca1a510a840ef08f374eb55e4c193fc58c64d15dfd9b6&quot;
  eth1_data:
    deposit_root: &quot;0xbb7338e44b9b1773d9a2537d33916a39047df59cf8a83b83ee15c4ebd7061f17&quot;
    deposit_count: &quot;391&quot;
    block_hash: &quot;0xc54fa15d7cf7e89fe249a3d43dc9aa194d89b7ed0709a9c453d63725a36b4bb0&quot;
  block_height: 392
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xafae78b562f726681144ff9aa2563edbda5e907e1eb32ee2babf8792cca6c552&quot;
      - &quot;0x879021b47e1a1c0942dad2c1b18300857aff607246ec88ae3ff1558391e07509&quot;
      - &quot;0xf4f62e401aa56826818ca1a510a840ef08f374eb55e4c193fc58c64d15dfd9b6&quot;
    deposit_root: &quot;0xbb7338e44b9b1773d9a2537d33916a39047df59cf8a83b83ee15c4ebd7061f17&quot;
    deposit_count: 391
    execution_block_hash: &quot;0xc54fa15d7cf7e89fe249a3d43dc9aa194d89b7ed0709a9c453d63725a36b4bb0&quot;
    execution_block_height: 392
- deposit_data:
    pubkey: &quot;0xb04bbe642a86b34459811d60affa8c72efaa288a34d4f2e5799807ced34747ef09ca47f90645d36c0a43fd9ce592e41f&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x87b573600a6f5a6af8a6c8493ee98b9b179cf34aebd27ff4f063982a34464ea2faea6896f599dd885b0812f2829529e8066a5ef915c4b756ffe094a5c9e33c12ceb27daa3f272e2b8532bfda9724b799662a8c9030d4671f03224c391e283977&quot;
  deposit_data_root: &quot;0x08525bcafc67d143769778c202899f3bef45d03b0b4c47f40782dbd2d714ecf6&quot;
  eth1_data:
    deposit_root: &quot;0xa3b155eea9ce7c9e359bdfeaaa3226882a88b472ebc2f6dc20d63249f87fc31a&quot;
    deposit_count: &quot;392&quot;
    block_hash: &quot;0x54ddd2ee62cb4efc55efbf284b7c86b390754e6f0ebbb8a92c3546648444f7f6&quot;
  block_height: 393
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x7e5837337e12008bc00095f95c4579a110096a154443242630b70a200c8eb25d&quot;
    deposit_root: &quot;0xa3b155eea9ce7c9e359bdfeaaa3226882a88b472ebc2f6dc20d63249f87fc31a&quot;
    deposit_count: 392
    execution_block_hash: &quot;0x54ddd2ee62cb4efc55efbf284b7c86b390754e6f0ebbb8a92c3546648444f7f6&quot;
    execution_block_height: 393
- deposit_data:
    pubkey: &quot;0x80609da89da3d8a011674d17aacc7378a9ed907455c914c3adfe80d9d5ff1b903cf0195f7999cd27af91de5177af295d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa38c302d9ccd055c116a22a63757dc3cf5a4dbe498beaf638f0d90446ee263292b388036081585309c41b39c6d88622819cf63b6a5fcf985d5b6c01190b5d08627bf7d13dbf0ad9bd4b2489e1f4f1eb970c1e29c9f76406e49e04275b2bc65e2&quot;
  deposit_data_root: &quot;0x55cc13b5b52558f81535da2bf312b7430662936ea5e8f78f1042d174acfae930&quot;
  eth1_data:
    deposit_root: &quot;0xc4950b3e40fadc566118b3124e334889bd809244c4fbd2fb4e2e00dd940c6052&quot;
    deposit_count: &quot;393&quot;
    block_hash: &quot;0xc9e0def5a794986bc01573227a104a80465d774957b94c3fb5f66f6507226276&quot;
  block_height: 394
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x7e5837337e12008bc00095f95c4579a110096a154443242630b70a200c8eb25d&quot;
      - &quot;0x55cc13b5b52558f81535da2bf312b7430662936ea5e8f78f1042d174acfae930&quot;
    deposit_root: &quot;0xc4950b3e40fadc566118b3124e334889bd809244c4fbd2fb4e2e00dd940c6052&quot;
    deposit_count: 393
    execution_block_hash: &quot;0xc9e0def5a794986bc01573227a104a80465d774957b94c3fb5f66f6507226276&quot;
    execution_block_height: 394
- deposit_data:
    pubkey: &quot;0xb929600f99e80e834dd9220a02e8b395bdd8cdfd9f93f201e6cd89ae1950e0789f93862082f0c7efd45e4b69224bd92a&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x98aba9f2310ac87434cb6e273c5bf0854789024046d4eecdd20edc20d59e9c9585e3be1a9197a928444de4ed37e582720dfc1fbf5a765c7cab9bbccf5d91b27413b681e853690ebea5aa8b757f69b9c2bcb704a9bbe9667573f1820ab1ebc524&quot;
  deposit_data_root: &quot;0xe6c9a1e53fa2bc6dfb3a0efcb15d5b61a0b00d40c05e85fdc7c73c22c0f1fb2c&quot;
  eth1_data:
    deposit_root: &quot;0xbb0d4f28737877ea198db2552a20e83fa21712d68f256fb4c47b00bc79a6e725&quot;
    deposit_count: &quot;394&quot;
    block_hash: &quot;0x07a4841aeadb48375c77cc7bbb85952ed2a2d8590b379cbc8296b93e5bea89fa&quot;
  block_height: 395
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x7e5837337e12008bc00095f95c4579a110096a154443242630b70a200c8eb25d&quot;
      - &quot;0x0d997180aceeb9c78bfd8dff8c8f847e603e9ef4da82207e9ef96fa26dd60c18&quot;
    deposit_root: &quot;0xbb0d4f28737877ea198db2552a20e83fa21712d68f256fb4c47b00bc79a6e725&quot;
    deposit_count: 394
    execution_block_hash: &quot;0x07a4841aeadb48375c77cc7bbb85952ed2a2d8590b379cbc8296b93e5bea89fa&quot;
    execution_block_height: 395
- deposit_data:
    pubkey: &quot;0x9052bae965368c78db0d638faf2ea9beb0e42b469adabbba09f85936f948a1cd77cf811a20ae759498770855068adae3&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8fd3066f0eb12e45912dad9e0f03999efd048f5c3a7cd0ef0c1b28469d734e0900faa8208d9f3c2ea4475c4b0edef88f01a0b0c265ff4adda81d58422b1512db9e12fadc2ee56a87d17f98cb1d403321af314954be68de1ef1626645c9d0b58b&quot;
  deposit_data_root: &quot;0x8041edc01aaaba30de8f64e99b463e7884fe5d7927a8e1ac0f8c26e4eeefac63&quot;
  eth1_data:
    deposit_root: &quot;0x159cb3175d894680b3f9885f0bd4fdf130731ae6fbed0bb8ef6c8ae22d3c141b&quot;
    deposit_count: &quot;395&quot;
    block_hash: &quot;0x6f29a9e99967a5b3ae5da3eca55e429b68e12c0a3ccf3765743baef29c1509aa&quot;
  block_height: 396
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x7e5837337e12008bc00095f95c4579a110096a154443242630b70a200c8eb25d&quot;
      - &quot;0x0d997180aceeb9c78bfd8dff8c8f847e603e9ef4da82207e9ef96fa26dd60c18&quot;
      - &quot;0x8041edc01aaaba30de8f64e99b463e7884fe5d7927a8e1ac0f8c26e4eeefac63&quot;
    deposit_root: &quot;0x159cb3175d894680b3f9885f0bd4fdf130731ae6fbed0bb8ef6c8ae22d3c141b&quot;
    deposit_count: 395
    execution_block_hash: &quot;0x6f29a9e99967a5b3ae5da3eca55e429b68e12c0a3ccf3765743baef29c1509aa&quot;
    execution_block_height: 396
- deposit_data:
    pubkey: &quot;0xa7c693916f59a0ee41b13d045632d4c5e8703a0e1431b50ba0450834747e41a6634ab9c0c1efa6af140f2072c29cf7a6&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb2b6db61ed48e65d9b02339ec3dce5b65082ddb6e88f2a9d68bb008213c2f413e884df2e36a2df4ef4872a1d7918d8d60b4b0cecf20345016d9fb90f823950b40b56686cfd73a60f366e89c0664b512fa6b1fa7e03d10407e5391a01a793f180&quot;
  deposit_data_root: &quot;0x58e50fcd08de046408f42ef030f88327a7090e3f28d86b90c33226f625d8591d&quot;
  eth1_data:
    deposit_root: &quot;0x5659e739fa58f5bac4607770ad5735be507757cc931e78a32971dba1062f9f79&quot;
    deposit_count: &quot;396&quot;
    block_hash: &quot;0x98492c4ba8ab648f0b7347fd237f6c97e28f8c9276202b7ceeceb4e2b55a4caf&quot;
  block_height: 397
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x7e5837337e12008bc00095f95c4579a110096a154443242630b70a200c8eb25d&quot;
      - &quot;0xf317c693e0d6b8255336757d18a3edf61408bfb581694def9ea146abfe6ee676&quot;
    deposit_root: &quot;0x5659e739fa58f5bac4607770ad5735be507757cc931e78a32971dba1062f9f79&quot;
    deposit_count: 396
    execution_block_hash: &quot;0x98492c4ba8ab648f0b7347fd237f6c97e28f8c9276202b7ceeceb4e2b55a4caf&quot;
    execution_block_height: 397
- deposit_data:
    pubkey: &quot;0x83a40895d9005f007df9ed7fdb17d820d3d66fe419480cede7518e1f54e4c1e2a97ffd71fe2f01187c3707cde5bf9915&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x96d6a5708588333bbad7bf98de64425be3f93c823588a7f30a2391d2fea7a68d4d46572edf9b5884a3669648b6233f970049e50e232746643e3e7edbdc733853ecff22492cb6d7befaf83f4f9331a9d8f1b4bcb7e28f2d1bdfd94903f7c121ba&quot;
  deposit_data_root: &quot;0x4b89dcec503cf535c9cb9f034604ad431a3baa5f8ad939a9fee0f17a518c58e7&quot;
  eth1_data:
    deposit_root: &quot;0xfe07bcc8cf3812b6959665a4d69ac7dc10210db6de6b5cb3cc3ab4e3731a553c&quot;
    deposit_count: &quot;397&quot;
    block_hash: &quot;0x9adc7e62cd440bc4c77546efdeb7d185348964c8b7d899634d8c442ae02f0cf3&quot;
  block_height: 398
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x7e5837337e12008bc00095f95c4579a110096a154443242630b70a200c8eb25d&quot;
      - &quot;0xf317c693e0d6b8255336757d18a3edf61408bfb581694def9ea146abfe6ee676&quot;
      - &quot;0x4b89dcec503cf535c9cb9f034604ad431a3baa5f8ad939a9fee0f17a518c58e7&quot;
    deposit_root: &quot;0xfe07bcc8cf3812b6959665a4d69ac7dc10210db6de6b5cb3cc3ab4e3731a553c&quot;
    deposit_count: 397
    execution_block_hash: &quot;0x9adc7e62cd440bc4c77546efdeb7d185348964c8b7d899634d8c442ae02f0cf3&quot;
    execution_block_height: 398
- deposit_data:
    pubkey: &quot;0x8ee8e926da165b8f34d249d194864a3994278aa4b829295480edac18395167fa016b2a4ffb0b0f3c89d18622bec2409c&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x96e64eb4225338a95db3620d53f114ce50c67c76f2775479d43b43dc99cc49203bf4cdb0a2f32ae8bc38871d5ea159f71573f7f17cff542489bcf03f71757e447cb1d3a88fbcb1849d406547f2ea18acdda8999dec66c611c66572435d27843b&quot;
  deposit_data_root: &quot;0x6f8c0bddde78f7897c2d2fa74c01ad7d54767bad64e1a110cecd9a13ffb11f31&quot;
  eth1_data:
    deposit_root: &quot;0xb10c6eb035b9b3ceaf4c5fabef893bc0e20d0fc473677948cab48835462cc8eb&quot;
    deposit_count: &quot;398&quot;
    block_hash: &quot;0x1aafe4f6b5beb8fefa9b9f17b11e8c330f1485d6b915bba56cd48ee2fd300ffa&quot;
  block_height: 399
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x7e5837337e12008bc00095f95c4579a110096a154443242630b70a200c8eb25d&quot;
      - &quot;0xf317c693e0d6b8255336757d18a3edf61408bfb581694def9ea146abfe6ee676&quot;
      - &quot;0x2a66533bacc64203fa52d8f62fd219a28a45bcbb7c0e29db839a9d9b19a5f91a&quot;
    deposit_root: &quot;0xb10c6eb035b9b3ceaf4c5fabef893bc0e20d0fc473677948cab48835462cc8eb&quot;
    deposit_count: 398
    execution_block_hash: &quot;0x1aafe4f6b5beb8fefa9b9f17b11e8c330f1485d6b915bba56cd48ee2fd300ffa&quot;
    execution_block_height: 399
- deposit_data:
    pubkey: &quot;0xadd60d6bf2abc6935ffebfe463c9b305ed2c898a00e2a84b997c014e140a7b254dfddc5be39e406ef0a893c4d67dd1ba&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x956032f3c008672890406790f1f6df66918c5b34b5c99bdd3e9e573b5c9eeb38457dad357d91bf63a5b40712f033196717c67639a675074a273d807ed38cfff57d5ae0a5da85425cc5e09a4fba69ef1ac8fde490e2acfcccf84593275ac13b6e&quot;
  deposit_data_root: &quot;0x9af6c4251177b012f498c5a6444e89a07f3b1f99c0c47c4370943fb4a19875a8&quot;
  eth1_data:
    deposit_root: &quot;0x2986d1af8658f87aab3fc101470d46c5875124b69e93da963cd7ed8a0815db27&quot;
    deposit_count: &quot;399&quot;
    block_hash: &quot;0x3f9fb82bf76f4d04409151836ea7e82696193cab3ba0a6505f8fea426708f118&quot;
  block_height: 400
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x7e5837337e12008bc00095f95c4579a110096a154443242630b70a200c8eb25d&quot;
      - &quot;0xf317c693e0d6b8255336757d18a3edf61408bfb581694def9ea146abfe6ee676&quot;
      - &quot;0x2a66533bacc64203fa52d8f62fd219a28a45bcbb7c0e29db839a9d9b19a5f91a&quot;
      - &quot;0x9af6c4251177b012f498c5a6444e89a07f3b1f99c0c47c4370943fb4a19875a8&quot;
    deposit_root: &quot;0x2986d1af8658f87aab3fc101470d46c5875124b69e93da963cd7ed8a0815db27&quot;
    deposit_count: 399
    execution_block_hash: &quot;0x3f9fb82bf76f4d04409151836ea7e82696193cab3ba0a6505f8fea426708f118&quot;
    execution_block_height: 400
- deposit_data:
    pubkey: &quot;0x8f48795cda6795e9af514489989a9f9e8b6db2b52a36881e4ba166327153d6db922e5148db044b27efe1831b54e16270&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x89b774642bd7faeefc6435c7184df11dd2fb34464f7ece0430b69d220032f77eccf6187839c5d7e233d463b48640bba211cd063cc9b638a954ea2c782919656980c7491ca632a83538146d9e6156ddf6f7260fb5ad1b4756549ba7a1b1f2cc1b&quot;
  deposit_data_root: &quot;0x70721ee8848f77b3243c3ea7b1193970abadc48446a2f47116cc9371f55745e7&quot;
  eth1_data:
    deposit_root: &quot;0x452498ecbea92a19db703d3e4544acfa45d9890b43883f5f88081533a826f236&quot;
    deposit_count: &quot;400&quot;
    block_hash: &quot;0x604f66f12e19e8be5538632835dc419e722d35e3e15b6bc7ba305348680a4ec9&quot;
  block_height: 401
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xec52edc11cb65e2c16d2dfd0ab3223c608e768e70c9e808e0a0196c82ad1736f&quot;
    deposit_root: &quot;0x452498ecbea92a19db703d3e4544acfa45d9890b43883f5f88081533a826f236&quot;
    deposit_count: 400
    execution_block_hash: &quot;0x604f66f12e19e8be5538632835dc419e722d35e3e15b6bc7ba305348680a4ec9&quot;
    execution_block_height: 401
- deposit_data:
    pubkey: &quot;0xb43ccddb32f15baaa32d69abf4b298d38e835607fd74aac5b25b5b161e8c865744a06526594faf39521e51fe44d66658&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb35daff1750c7ab2ff3ec29d401f83dfcc035bd5e0de5e45bc7ef789558349839da1c3588a263359ba86b4812b6c28360c960dd5aa762c7ef6123dc3e2ce63064f9ef2ed74eb9efbdbda96d87cfc2b50f4947e66ecd0244c546b9450277e6861&quot;
  deposit_data_root: &quot;0x0f94bc880af7f796e05590236751522502362f586d3bcf4d42799a6931676193&quot;
  eth1_data:
    deposit_root: &quot;0x9c53aafb0bf05b211e3d12a2771506145ca19774733164e549865501fb0f26a9&quot;
    deposit_count: &quot;401&quot;
    block_hash: &quot;0x897487f0b6c2ee25dee391c9b855ac06fcbbcf4f8ced76cceda3081c27d461bc&quot;
  block_height: 402
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xec52edc11cb65e2c16d2dfd0ab3223c608e768e70c9e808e0a0196c82ad1736f&quot;
      - &quot;0x0f94bc880af7f796e05590236751522502362f586d3bcf4d42799a6931676193&quot;
    deposit_root: &quot;0x9c53aafb0bf05b211e3d12a2771506145ca19774733164e549865501fb0f26a9&quot;
    deposit_count: 401
    execution_block_hash: &quot;0x897487f0b6c2ee25dee391c9b855ac06fcbbcf4f8ced76cceda3081c27d461bc&quot;
    execution_block_height: 402
- deposit_data:
    pubkey: &quot;0x83249b11efc76fba2ab77df9b5ffc607e6e2265c7f761dbb3099f3b4ff74ad8b9570036cb04942898f8c33b8442adfcc&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa7e93b3bc24dddcd889bcb9d313f632eeeea863ac36f6bf45cdf2aa3817eea3d58f8e133f3d7c52318370ca3d51458e3195aaf7dfb8affbf789e294893b93e1420a5417e2bfd42ef06d3a0a93d35e6ae4a89aa4a3887c53fecc5a5784951a7b8&quot;
  deposit_data_root: &quot;0xe1f17fc61185cdbeb20440550c2bbee0b02afd1bbcdda44938f893fe92e6d2ed&quot;
  eth1_data:
    deposit_root: &quot;0x636af0f0424726b4060828f72a3186c6b7dfaaea3591c5e7691d3a62fe183a7f&quot;
    deposit_count: &quot;402&quot;
    block_hash: &quot;0x6cae019fcf9937f0efea9dc1ab3a9550aaf34af27f8e63b644f9329e61176a02&quot;
  block_height: 403
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xec52edc11cb65e2c16d2dfd0ab3223c608e768e70c9e808e0a0196c82ad1736f&quot;
      - &quot;0xd120ef8988987a3de5b82d1b73dbf94fd20b9ab5bf7b3297255bc0ea59ffcd70&quot;
    deposit_root: &quot;0x636af0f0424726b4060828f72a3186c6b7dfaaea3591c5e7691d3a62fe183a7f&quot;
    deposit_count: 402
    execution_block_hash: &quot;0x6cae019fcf9937f0efea9dc1ab3a9550aaf34af27f8e63b644f9329e61176a02&quot;
    execution_block_height: 403
- deposit_data:
    pubkey: &quot;0xb049dc45fd585ef8bc67831dc47690f95e466cf11127def6ef9fdfc43017518752aff3df93c3e5f68083f590f554f3dc&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9411afc1b608ca75c7e4af02d1688588ca24b611b9b7250ee87dc7504f1c60543932bf50745b64c363537ce553234a62195d605f970744979913756525764b61e274665c5811d56b13928fb1bee16a35269bc2a466726ddbff0ebde348680e50&quot;
  deposit_data_root: &quot;0x11af26393dac3ce8fb05c12d6ece2cfceec9489fd2d915646bb4840993138571&quot;
  eth1_data:
    deposit_root: &quot;0x9c778cae240d62b556752b616662c7ac895a162e9a7730ff0d52b82bf469883c&quot;
    deposit_count: &quot;403&quot;
    block_hash: &quot;0x40daf225c72e6c2923e9ad5544c472bed26439a283682bb93688fe3d88d2e76d&quot;
  block_height: 404
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xec52edc11cb65e2c16d2dfd0ab3223c608e768e70c9e808e0a0196c82ad1736f&quot;
      - &quot;0xd120ef8988987a3de5b82d1b73dbf94fd20b9ab5bf7b3297255bc0ea59ffcd70&quot;
      - &quot;0x11af26393dac3ce8fb05c12d6ece2cfceec9489fd2d915646bb4840993138571&quot;
    deposit_root: &quot;0x9c778cae240d62b556752b616662c7ac895a162e9a7730ff0d52b82bf469883c&quot;
    deposit_count: 403
    execution_block_hash: &quot;0x40daf225c72e6c2923e9ad5544c472bed26439a283682bb93688fe3d88d2e76d&quot;
    execution_block_height: 404
- deposit_data:
    pubkey: &quot;0xb0f4dcd488f6725946e1a384d9ae9cd6a12824dafb426e15f4b848b6dabd46ec1177fccd0fa5c0c2260fc57aaadf1e7d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x91ca8e45fc3d7c4003d0ec4602231b3f86e119931a1c8d605b86d36191a2d32193bd10741920bff28e2d2d2964f01b9c034ddaf18f30d326b6f91be845c9c75ef0201cd50ff50f39c29430b7492a1e4537926c786525091e1c2c238ad4698b49&quot;
  deposit_data_root: &quot;0x686a7b22bebf76249ffc853c5122014578f3cb65dd2c6b70909ffce37e88150d&quot;
  eth1_data:
    deposit_root: &quot;0x2a08f81dd020438f364a87bf7dab7624c404e0934662a5588c924c5fa10abab1&quot;
    deposit_count: &quot;404&quot;
    block_hash: &quot;0xd4e4fc76c0e27a2f700ade91f2510b65de7045289c1c22f964ea29e2a7dca632&quot;
  block_height: 405
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xec52edc11cb65e2c16d2dfd0ab3223c608e768e70c9e808e0a0196c82ad1736f&quot;
      - &quot;0x84a7921ef234cafc908a09e2bbbdd215ec6e0c4aa800834f18fd8592b86fb2cc&quot;
    deposit_root: &quot;0x2a08f81dd020438f364a87bf7dab7624c404e0934662a5588c924c5fa10abab1&quot;
    deposit_count: 404
    execution_block_hash: &quot;0xd4e4fc76c0e27a2f700ade91f2510b65de7045289c1c22f964ea29e2a7dca632&quot;
    execution_block_height: 405
- deposit_data:
    pubkey: &quot;0xb400b2f5705dbd2905c5d9fe3b2f29cedb380954a60b4fab0e55009c47e1908a30bf286f7e01b7125985c9007015f37c&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb8303c6fe8a1f35b218d48f838cd459dee1422b6f202c1b710c0179817f1085c8556cb71e6b0a97ad0484349fe854f6b0d4da3f69c0e3d5708843d4c0ad4d3f2bdc1cdb40db8a654a1f708b4318274ea613e75be4d0f6c9a26a1d52d950c1f5a&quot;
  deposit_data_root: &quot;0x54285447a3b3f65166091d937d7557f012b904d001e24cc43c8f0899522bab1a&quot;
  eth1_data:
    deposit_root: &quot;0x2964d0b869c2a6da631d3e589eca0125be3775f099f3cd1e6b7013ae66384abd&quot;
    deposit_count: &quot;405&quot;
    block_hash: &quot;0x227229f14dc54a592bdd03b2d84df40d64d0e6f51dcdfdf1c42ff87a1291c6a3&quot;
  block_height: 406
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xec52edc11cb65e2c16d2dfd0ab3223c608e768e70c9e808e0a0196c82ad1736f&quot;
      - &quot;0x84a7921ef234cafc908a09e2bbbdd215ec6e0c4aa800834f18fd8592b86fb2cc&quot;
      - &quot;0x54285447a3b3f65166091d937d7557f012b904d001e24cc43c8f0899522bab1a&quot;
    deposit_root: &quot;0x2964d0b869c2a6da631d3e589eca0125be3775f099f3cd1e6b7013ae66384abd&quot;
    deposit_count: 405
    execution_block_hash: &quot;0x227229f14dc54a592bdd03b2d84df40d64d0e6f51dcdfdf1c42ff87a1291c6a3&quot;
    execution_block_height: 406
- deposit_data:
    pubkey: &quot;0x97580566e3ddcde5b3e0cedf688aede17a8b738a21f96a0c2efff77061e232ad877e6bc71649d0fbb3ec0dde584bb8e8&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb680f12cff8dff209469f418f731a144cade0471dff2ee7b656baa3d0b2ada286bafcf1487ec3ec47b1fa83823fc237211352f5d3c28842d50124206019b16a9f7baf7c22405fbfcb49123aec9289fe8a2a6d894634a936297f0bd08d591074c&quot;
  deposit_data_root: &quot;0x5db3228f5c2c952907c045dbb394ae8e84db47a0e25ffa40de6b58e9c6ab257c&quot;
  eth1_data:
    deposit_root: &quot;0x056d0f3598f7c612c9d73dd3adcb0dc54a8861b4c3df6b4df8ff7511a3966207&quot;
    deposit_count: &quot;406&quot;
    block_hash: &quot;0x5b1c9467bdfcf4b7555e748b80e684419a23798fa52716ac92aaa14186dd85b2&quot;
  block_height: 407
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xec52edc11cb65e2c16d2dfd0ab3223c608e768e70c9e808e0a0196c82ad1736f&quot;
      - &quot;0x84a7921ef234cafc908a09e2bbbdd215ec6e0c4aa800834f18fd8592b86fb2cc&quot;
      - &quot;0x85117723172be560339b88739cf982d8b35cb46f757778b547dbc224ef314c78&quot;
    deposit_root: &quot;0x056d0f3598f7c612c9d73dd3adcb0dc54a8861b4c3df6b4df8ff7511a3966207&quot;
    deposit_count: 406
    execution_block_hash: &quot;0x5b1c9467bdfcf4b7555e748b80e684419a23798fa52716ac92aaa14186dd85b2&quot;
    execution_block_height: 407
- deposit_data:
    pubkey: &quot;0x9504350e6a3ad1a5f711d9e5904bd25b1f6571bcaa66403f1da9fc8200ebd8073308dcf462371073bd8b076fd25df949&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x97cf502d6ce9a1a4dadfa044a55404625dce825856a24d235e58e31726d6c656c6848a4f614289ffdf2ce52b065780a60f2ed591833b178369bf7b84e6d7f0a5bba85e79c5a37f7d7087b54f12f78dc94fedb49668d62cf052d3d36ba14cfc6a&quot;
  deposit_data_root: &quot;0x1a6a9e33d429de9d71c1f84e4476edfea7c21cabaaff5663bf0737e75d503644&quot;
  eth1_data:
    deposit_root: &quot;0x45ce45d9a35f5bacc28372385bd446592e1198cd983a9cabf423ae68844aca63&quot;
    deposit_count: &quot;407&quot;
    block_hash: &quot;0xe25780387a9c484c23c6252bd8518d02fca68bbef3de900bb192b8bda868017f&quot;
  block_height: 408
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xec52edc11cb65e2c16d2dfd0ab3223c608e768e70c9e808e0a0196c82ad1736f&quot;
      - &quot;0x84a7921ef234cafc908a09e2bbbdd215ec6e0c4aa800834f18fd8592b86fb2cc&quot;
      - &quot;0x85117723172be560339b88739cf982d8b35cb46f757778b547dbc224ef314c78&quot;
      - &quot;0x1a6a9e33d429de9d71c1f84e4476edfea7c21cabaaff5663bf0737e75d503644&quot;
    deposit_root: &quot;0x45ce45d9a35f5bacc28372385bd446592e1198cd983a9cabf423ae68844aca63&quot;
    deposit_count: 407
    execution_block_hash: &quot;0xe25780387a9c484c23c6252bd8518d02fca68bbef3de900bb192b8bda868017f&quot;
    execution_block_height: 408
- deposit_data:
    pubkey: &quot;0x94184bf24da31a8ca6561c17aa36b6933f07d4966063972bfcc6c97d8daeefd05b7c22d41fa5133327cc0dd000139175&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb2147f430cef90e44d212f911fb86e018b4757593fc5830f5df7c227d66c3f9498ea97f5d74fad123e7a1485589d17d90297d6203e5a815a8e154d548daa55b9f13901bc297b8fd4e6ccb909dbc8fd2f93a889d64186fc2f9a4be67496d97b61&quot;
  deposit_data_root: &quot;0x687e4fa71fd82af6ccca467fb6b5e48f142ad7fc09fd986e2d2c12bc08e2e318&quot;
  eth1_data:
    deposit_root: &quot;0x85996ca4642a553cc8fcf6d1c797c38df7fa374a2a8a420064114c4b7b576779&quot;
    deposit_count: &quot;408&quot;
    block_hash: &quot;0xa1d4a35fa123ddccc268e408c9c03c5351b323e42eeae7b8415b67725957f8dd&quot;
  block_height: 409
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xec52edc11cb65e2c16d2dfd0ab3223c608e768e70c9e808e0a0196c82ad1736f&quot;
      - &quot;0x0901c3b3e1bacfae214532d21ac897c470123fae6d333b9af964c91ea57d286b&quot;
    deposit_root: &quot;0x85996ca4642a553cc8fcf6d1c797c38df7fa374a2a8a420064114c4b7b576779&quot;
    deposit_count: 408
    execution_block_hash: &quot;0xa1d4a35fa123ddccc268e408c9c03c5351b323e42eeae7b8415b67725957f8dd&quot;
    execution_block_height: 409
- deposit_data:
    pubkey: &quot;0xb88add150c36e8c338f7ff8efa8efb4e302a5a01afb8e331282eb075ffc3f2f5e5e783a4cef6a0d9c65dbedea48cc093&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xadc8bcc68efed61ce4039fba63c806c6e59282810427369f0967c765e052048304bcb76104660d30ca2667f406c445160240514f7b07c762a83e1f7a27e5cb7b4fc81b40b5a4f8d24fb3cb1640129132578819e404da56557e5f6988e8064708&quot;
  deposit_data_root: &quot;0x99422ecd07eaabd6d3d3380ff689d77656e191b82317f01a8ca95cbc98210d4c&quot;
  eth1_data:
    deposit_root: &quot;0x8d152a557390c7b500d1a4eda65c8491268e58d25a936cb8e032eb06be13de35&quot;
    deposit_count: &quot;409&quot;
    block_hash: &quot;0x864f7b84cd151b4359c1767fd03f15e94769a4a96b65a3e299b7984d6cd397e6&quot;
  block_height: 410
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xec52edc11cb65e2c16d2dfd0ab3223c608e768e70c9e808e0a0196c82ad1736f&quot;
      - &quot;0x0901c3b3e1bacfae214532d21ac897c470123fae6d333b9af964c91ea57d286b&quot;
      - &quot;0x99422ecd07eaabd6d3d3380ff689d77656e191b82317f01a8ca95cbc98210d4c&quot;
    deposit_root: &quot;0x8d152a557390c7b500d1a4eda65c8491268e58d25a936cb8e032eb06be13de35&quot;
    deposit_count: 409
    execution_block_hash: &quot;0x864f7b84cd151b4359c1767fd03f15e94769a4a96b65a3e299b7984d6cd397e6&quot;
    execution_block_height: 410
- deposit_data:
    pubkey: &quot;0xb25827b6746a0ed3bf133beb7e465ba08c39e1960c4555a81384502d6c244bdd7ca19f521c6d192436d71dfafa64b4a6&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x96aa871044bff32644f18d02e67e8dc0755621ed06eed2928626f653aa927e8976f39447954e3e0737533488633a319f16e573f70137eb877bc792b12df25b72847efa7c334309070109492bdd07b6f12641ef30895d71503755f6bd186a373d&quot;
  deposit_data_root: &quot;0xbe183759a8073454fc423aba202855bb3537be2a6772f75617206143e492583c&quot;
  eth1_data:
    deposit_root: &quot;0x3e6105f13f3575420640b86bf5967844ef363dbd91cd6d2f3d7b55bb2cafa1cb&quot;
    deposit_count: &quot;410&quot;
    block_hash: &quot;0xf59f3ccc775a6fd25443c8bd4d39aee5653b9399d8db7028a1244b2b36fa601a&quot;
  block_height: 411
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xec52edc11cb65e2c16d2dfd0ab3223c608e768e70c9e808e0a0196c82ad1736f&quot;
      - &quot;0x0901c3b3e1bacfae214532d21ac897c470123fae6d333b9af964c91ea57d286b&quot;
      - &quot;0x8938612c24e370ad407b03900d58216a3677570a6393d86c1199e168ac50d0f4&quot;
    deposit_root: &quot;0x3e6105f13f3575420640b86bf5967844ef363dbd91cd6d2f3d7b55bb2cafa1cb&quot;
    deposit_count: 410
    execution_block_hash: &quot;0xf59f3ccc775a6fd25443c8bd4d39aee5653b9399d8db7028a1244b2b36fa601a&quot;
    execution_block_height: 411
- deposit_data:
    pubkey: &quot;0xb5ed6e77bd6f1661a5ab3f2e13743385c7ee99dc240e9575b3e7639b4f73a017cf4edbd0932e02577acd2bec274be3fc&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9304d4d21d94213e2e17afba7d41167249086d34837591a7ebaa998ad31dc2085f1f11cfc01b9a0651dc5bbc4785a9f6084549527e1d9f4a256d9d6b73a1cebcbd10c9e88984acc11ca85eb8d5ff5b53cecb6bc4a366bb5cc3a82db259accf9d&quot;
  deposit_data_root: &quot;0x56410aabb7658f5072e9d3caaafc6d06931ecd574f6af0b0c6780765b81b2efe&quot;
  eth1_data:
    deposit_root: &quot;0xf81fa25a4547d3ea55b14e7ac66c2e4d9f96c32c843d3ccf32efc7e625142204&quot;
    deposit_count: &quot;411&quot;
    block_hash: &quot;0x2ed4ba87f94e8bf64d8fa37d0b7cb7a67eeddfd408a8838ee62cdf8b63e36533&quot;
  block_height: 412
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xec52edc11cb65e2c16d2dfd0ab3223c608e768e70c9e808e0a0196c82ad1736f&quot;
      - &quot;0x0901c3b3e1bacfae214532d21ac897c470123fae6d333b9af964c91ea57d286b&quot;
      - &quot;0x8938612c24e370ad407b03900d58216a3677570a6393d86c1199e168ac50d0f4&quot;
      - &quot;0x56410aabb7658f5072e9d3caaafc6d06931ecd574f6af0b0c6780765b81b2efe&quot;
    deposit_root: &quot;0xf81fa25a4547d3ea55b14e7ac66c2e4d9f96c32c843d3ccf32efc7e625142204&quot;
    deposit_count: 411
    execution_block_hash: &quot;0x2ed4ba87f94e8bf64d8fa37d0b7cb7a67eeddfd408a8838ee62cdf8b63e36533&quot;
    execution_block_height: 412
- deposit_data:
    pubkey: &quot;0xa25579ff3efe83b344ac7ca26d45d5aac4fd4fdb1809f20e4e48026e154e95d7ea8c7abf6e91628f8448a6a798dd07f3&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8915d4d355035a608f37b9c2402a9c3b95ef8c68209b0607cc8bcdc4f10a47a12b0708da53442b82348470e179f128bb02192b872b8ea16d388ed77ac173e4b9ae9456734fc33cc05b6bce98dbcb8f69bfae7583286ed548b4711916eb059055&quot;
  deposit_data_root: &quot;0xb55d26ad397fe717b187f5c40e5103bee6c3ba6d8a2b0d73a357f950fd172c34&quot;
  eth1_data:
    deposit_root: &quot;0x1d2b4ebde6a17b6badc11d3f4a4d67e5938f2b536fed42e015b6ae501b88bbe9&quot;
    deposit_count: &quot;412&quot;
    block_hash: &quot;0x616b1268dbde68f7f9ba43b43cbd7f721c94d1ae793f0101334af4ad8d8e82ec&quot;
  block_height: 413
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xec52edc11cb65e2c16d2dfd0ab3223c608e768e70c9e808e0a0196c82ad1736f&quot;
      - &quot;0x0901c3b3e1bacfae214532d21ac897c470123fae6d333b9af964c91ea57d286b&quot;
      - &quot;0xa1c5ec665c8d856db67a8496e9dc6082278b339bf70b3a4f35f6d79670fa00e7&quot;
    deposit_root: &quot;0x1d2b4ebde6a17b6badc11d3f4a4d67e5938f2b536fed42e015b6ae501b88bbe9&quot;
    deposit_count: 412
    execution_block_hash: &quot;0x616b1268dbde68f7f9ba43b43cbd7f721c94d1ae793f0101334af4ad8d8e82ec&quot;
    execution_block_height: 413
- deposit_data:
    pubkey: &quot;0x81dc3529a283023f70fec5eb65ef8e3b394b0239bfe40095574a881c5dbe536a6b119e6cc95668b62d6e5944386c07ca&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x89053f18cbf904592529a1710bd771229ebf0709d2c637684eae158bdd5821469dcbe1263d3649a8e04b92d2d7e326ba1895598c591a69fd1048f58d2d34c1cc432dab87f8f0bed2afee9500f92ea000462b9ffb80f5ca409e0d05ab8b821aca&quot;
  deposit_data_root: &quot;0x315194fcfff6c0dc8855f81729f8993f67b38330dbec183119694e330fec78af&quot;
  eth1_data:
    deposit_root: &quot;0x3801e05532040093e13e5b25b9afb7ebc97618181c41afec4e929e7cf8458a24&quot;
    deposit_count: &quot;413&quot;
    block_hash: &quot;0xc49c428e319c98556fa261f9a6a3184d5149ea8cb773b47fef238c2f8d696641&quot;
  block_height: 414
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xec52edc11cb65e2c16d2dfd0ab3223c608e768e70c9e808e0a0196c82ad1736f&quot;
      - &quot;0x0901c3b3e1bacfae214532d21ac897c470123fae6d333b9af964c91ea57d286b&quot;
      - &quot;0xa1c5ec665c8d856db67a8496e9dc6082278b339bf70b3a4f35f6d79670fa00e7&quot;
      - &quot;0x315194fcfff6c0dc8855f81729f8993f67b38330dbec183119694e330fec78af&quot;
    deposit_root: &quot;0x3801e05532040093e13e5b25b9afb7ebc97618181c41afec4e929e7cf8458a24&quot;
    deposit_count: 413
    execution_block_hash: &quot;0xc49c428e319c98556fa261f9a6a3184d5149ea8cb773b47fef238c2f8d696641&quot;
    execution_block_height: 414
- deposit_data:
    pubkey: &quot;0x93da5217b698dcee39d36c25bd79f2a152e5053add9e4b17cf60cc5dadc0e2d1713d05f7b5917840b6748d25d68f4878&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xaeebc4af4e5b90582f890827b760f39de6f9adf57afe53e74fa7dc7718e1a1ff4f70eb119c2f1042ee9d06264c07347b0d052699ba9145d7c3e38ffbc2d23d75f15c169b88e35810317e80281889f5a86248d05110ac7ce727996de71967cb29&quot;
  deposit_data_root: &quot;0x38ae0e785551cf674706d6ec349cb2a8061d5a6175b87857f9c9a9f51631cd71&quot;
  eth1_data:
    deposit_root: &quot;0x64149d892f598e8b77cb82d9ec6795bb77780c16ec7519ba12d9a3dce230179c&quot;
    deposit_count: &quot;414&quot;
    block_hash: &quot;0xa79d343f7dca460ec92a84fe1186ecbee2f9bef1270a4cf1999cf944a86f85ae&quot;
  block_height: 415
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xec52edc11cb65e2c16d2dfd0ab3223c608e768e70c9e808e0a0196c82ad1736f&quot;
      - &quot;0x0901c3b3e1bacfae214532d21ac897c470123fae6d333b9af964c91ea57d286b&quot;
      - &quot;0xa1c5ec665c8d856db67a8496e9dc6082278b339bf70b3a4f35f6d79670fa00e7&quot;
      - &quot;0x48e639af938e1404ea96c354be4721b397a5acce7ffa49d37f8573ee8158a522&quot;
    deposit_root: &quot;0x64149d892f598e8b77cb82d9ec6795bb77780c16ec7519ba12d9a3dce230179c&quot;
    deposit_count: 414
    execution_block_hash: &quot;0xa79d343f7dca460ec92a84fe1186ecbee2f9bef1270a4cf1999cf944a86f85ae&quot;
    execution_block_height: 415
- deposit_data:
    pubkey: &quot;0xb54437d1547e9a87476f03c094c86465f36376c09ef3c8fba0c8906fdeb0421d523a20ab6ce6ee18da9fbab39ede3bee&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9334c266b645d6cc2dc62f8dd0e6ec5224dacee0db27c912db0b41422bcbc20f85589fb41bfd51d22ee7030c75b52c6c0a54185c8385f95a36e97d241f32f0b903caaaea7e2cf27ec93870c1264f2ed07d73e84fac7402f03ebf77b9b5464321&quot;
  deposit_data_root: &quot;0xaf029eb95db881e01d26610b29fb72f3e787f515905568178e89caadffceafe5&quot;
  eth1_data:
    deposit_root: &quot;0x3f34a92f21f233bbf81b0c43288483f2e79ce0d95351eecc830a97b3dcec3eac&quot;
    deposit_count: &quot;415&quot;
    block_hash: &quot;0x455ef1eda7e29f3ed4bbb1c6d34330abd172c4626032644f0242b4d4defa1835&quot;
  block_height: 416
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xec52edc11cb65e2c16d2dfd0ab3223c608e768e70c9e808e0a0196c82ad1736f&quot;
      - &quot;0x0901c3b3e1bacfae214532d21ac897c470123fae6d333b9af964c91ea57d286b&quot;
      - &quot;0xa1c5ec665c8d856db67a8496e9dc6082278b339bf70b3a4f35f6d79670fa00e7&quot;
      - &quot;0x48e639af938e1404ea96c354be4721b397a5acce7ffa49d37f8573ee8158a522&quot;
      - &quot;0xaf029eb95db881e01d26610b29fb72f3e787f515905568178e89caadffceafe5&quot;
    deposit_root: &quot;0x3f34a92f21f233bbf81b0c43288483f2e79ce0d95351eecc830a97b3dcec3eac&quot;
    deposit_count: 415
    execution_block_hash: &quot;0x455ef1eda7e29f3ed4bbb1c6d34330abd172c4626032644f0242b4d4defa1835&quot;
    execution_block_height: 416
- deposit_data:
    pubkey: &quot;0xaa5367fff8db3ba5017bc601e9f9ceb867d54c3b17ade967b0bc905f644f6aadc8aa53d3e9ed0e278bf3fc2b0b56a7b2&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8b8a5f542223fdd7170978a36e904c31ec430dd68cd608a3aaac5b6514f1e817e1bb2374aa7359e85d0c280f17c99daa0049c57e853088b8ae3a23d77911c12d6094558aec8dff5a9dc917d7799e6a86d06bb54b394473fd4fdcd273868581f3&quot;
  deposit_data_root: &quot;0xd202196054c6e1cfa6f16d82399ef65d80f0765564b15c5111da4720bec9b495&quot;
  eth1_data:
    deposit_root: &quot;0x2bbfa716fadba6b4b1d4d2b4cbd5b031bad662ad0a18d60f8fae3a9ff2238c8f&quot;
    deposit_count: &quot;416&quot;
    block_hash: &quot;0x376a52185e4457c7d3536a168e21870ecbb58babc27d4a74189316e089e4a69c&quot;
  block_height: 417
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
    deposit_root: &quot;0x2bbfa716fadba6b4b1d4d2b4cbd5b031bad662ad0a18d60f8fae3a9ff2238c8f&quot;
    deposit_count: 416
    execution_block_hash: &quot;0x376a52185e4457c7d3536a168e21870ecbb58babc27d4a74189316e089e4a69c&quot;
    execution_block_height: 417
- deposit_data:
    pubkey: &quot;0x874305f7d11e69b74164cad10ab88ea7df22208c954fcb6872f34a5f9c8292341f85a6250716270563a19b5a112761d4&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xae8bde36d9ebdb5a259f005703d09b72d1828bb4b4dffbab5e145f1bc0cc857b24ba1365ead8ce0953aa67e3afa4c9a40fc79fc0da93c7a5b350e0c528f91fe7a1b124c27d0d622711be2a85abe3078010c584576b919e438721dcfe7a5f6d1c&quot;
  deposit_data_root: &quot;0x0e431cf7531088ea8e7aa4b2ad1e3a2971548ab2fc6967219a91861599293180&quot;
  eth1_data:
    deposit_root: &quot;0x0cc28d5ecfca85f1d141d409373c12e5ef93e7fab9d3d667737b8e3e8b9d567d&quot;
    deposit_count: &quot;417&quot;
    block_hash: &quot;0xcc9737753a8b74792a5df80adaa5eeeb97c6d8656eaee16fcfb04a63bddd791a&quot;
  block_height: 418
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0x0e431cf7531088ea8e7aa4b2ad1e3a2971548ab2fc6967219a91861599293180&quot;
    deposit_root: &quot;0x0cc28d5ecfca85f1d141d409373c12e5ef93e7fab9d3d667737b8e3e8b9d567d&quot;
    deposit_count: 417
    execution_block_hash: &quot;0xcc9737753a8b74792a5df80adaa5eeeb97c6d8656eaee16fcfb04a63bddd791a&quot;
    execution_block_height: 418
- deposit_data:
    pubkey: &quot;0x96917c5ff8bd2debf697fbc64455d19cf1efc4e1327b3dde2eef7db7cab762effb43025c4162db0008a0b43b4d060748&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa16d8a141171087108c9f042e0915736a0eb801ccaf8b889a124bd6d53eaffef6518a982b0214e9b6c9a95860d5a2da50f5b3eef099489a927545bbbba3d9e0126f7720c367e93bbb64353d8b7b86363792c35e1d812fedc3495921910051be7&quot;
  deposit_data_root: &quot;0x3dab6d15efd096307e6d2f0f3465f10a35147b60564a52e9a69c2a9d20c16a2d&quot;
  eth1_data:
    deposit_root: &quot;0xcb8c6981b53a98be40422412d265fd54abc7329f49ba6028981465210544c9c0&quot;
    deposit_count: &quot;418&quot;
    block_hash: &quot;0x3fb793716ced3b8a456415e801d6e847ee18b269ae9600bb2b42d698d23c6d17&quot;
  block_height: 419
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0x696db144fa18876c4f737f199bf14a3d8922bd7a5c7469f783cd255b766ac02b&quot;
    deposit_root: &quot;0xcb8c6981b53a98be40422412d265fd54abc7329f49ba6028981465210544c9c0&quot;
    deposit_count: 418
    execution_block_hash: &quot;0x3fb793716ced3b8a456415e801d6e847ee18b269ae9600bb2b42d698d23c6d17&quot;
    execution_block_height: 419
- deposit_data:
    pubkey: &quot;0xae77044f5f689ef3c59fbb1afc7fa2e33c5406121f9c2eb1dd089cb320b9d82ab51d6fadb545327dfcc2688c201e9e07&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb2229d26b8942b36b25e0231246148d635c4abf51fbab950efea2e4f0e4a9b7f6f9ee366636bc42801930330fd7b197a11cac3cec7abfccfa29323a2810f2d209ba953a45bf11058bf438d66cec626c4c6be647cc6c0c88fe372e333863d5766&quot;
  deposit_data_root: &quot;0xb1532d97dbb8c85040e1ebc08649670b8980fd97cae2e23ab7f1b5af06c1f597&quot;
  eth1_data:
    deposit_root: &quot;0x76d0915685d7293f2ad3c227cfd6208d198fc11d6eb154dca9ebf9f08b57a863&quot;
    deposit_count: &quot;419&quot;
    block_hash: &quot;0x08a0fbfdd1c3183824d6f51a123e89b1a8dd1c208dea3a167bb8c47ff7697390&quot;
  block_height: 420
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0x696db144fa18876c4f737f199bf14a3d8922bd7a5c7469f783cd255b766ac02b&quot;
      - &quot;0xb1532d97dbb8c85040e1ebc08649670b8980fd97cae2e23ab7f1b5af06c1f597&quot;
    deposit_root: &quot;0x76d0915685d7293f2ad3c227cfd6208d198fc11d6eb154dca9ebf9f08b57a863&quot;
    deposit_count: 419
    execution_block_hash: &quot;0x08a0fbfdd1c3183824d6f51a123e89b1a8dd1c208dea3a167bb8c47ff7697390&quot;
    execution_block_height: 420
- deposit_data:
    pubkey: &quot;0xa174a13601df492b77a263ff54d9e30a0d9b248a1bfc559a4bbeb251fead9b72790f08bed89dbf224c1cb5548c44abab&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8a8d011198c4e426421f2563dbf5552ba950849f6b404a77de5f397f470ad349fc35c62df521f34d4ce8e5135f514df11654c7868da1b45d6d10193597cb0e1c33b8bff2f005c2eba783f1e7f5526cc85be30fda5d481ecc526b5a0a5733815d&quot;
  deposit_data_root: &quot;0xb5100ee2bc58e4bcbeb35010d28c99f25f30db2dee32e8d8be5abfff81c6b980&quot;
  eth1_data:
    deposit_root: &quot;0x4fbb0a4745d73910a0e83ed47c036e561d5a974ba373106f4be04ee184f68009&quot;
    deposit_count: &quot;420&quot;
    block_hash: &quot;0x8644b9495ba9e4ea664a3d613b9aceb7e8a7efb507635cf2eea237ccfb3eeb5c&quot;
  block_height: 421
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0xfb785265dae57039dc1b110d2edb8556f05c9f2013e0cd5b57982be1642c2375&quot;
    deposit_root: &quot;0x4fbb0a4745d73910a0e83ed47c036e561d5a974ba373106f4be04ee184f68009&quot;
    deposit_count: 420
    execution_block_hash: &quot;0x8644b9495ba9e4ea664a3d613b9aceb7e8a7efb507635cf2eea237ccfb3eeb5c&quot;
    execution_block_height: 421
- deposit_data:
    pubkey: &quot;0x88a09d6756a015068efa04c8fca73dd96e2314e4f6e9d1aefdf19ef139eccb2000c3f382a18a3ade202641ed2c4b4267&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8bae90cb3fad0db9242b14e40a799f7ad163ca2a720864f4abdb6e28a352d19655d557420a4f4965108d247c82d3cf050224c04aecf9a351e57cfc008e27b60c991b02446d19ef1f3bb6f6bc932010d9bf6c54b4b09afd8131fd2d95fac89c11&quot;
  deposit_data_root: &quot;0x87c39cef2326f57395a3143b07c46e7077d23cab48b40a25631ba38381e3f15a&quot;
  eth1_data:
    deposit_root: &quot;0x1bf71fb13806bd931b817a8be4dc90de192c8f2baafc12d99eb8ed922bcf53a3&quot;
    deposit_count: &quot;421&quot;
    block_hash: &quot;0xad379a83ea80b1aae55e118cdadfb133bbcedb14842e6a1a1fe4cdae049d0739&quot;
  block_height: 422
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0xfb785265dae57039dc1b110d2edb8556f05c9f2013e0cd5b57982be1642c2375&quot;
      - &quot;0x87c39cef2326f57395a3143b07c46e7077d23cab48b40a25631ba38381e3f15a&quot;
    deposit_root: &quot;0x1bf71fb13806bd931b817a8be4dc90de192c8f2baafc12d99eb8ed922bcf53a3&quot;
    deposit_count: 421
    execution_block_hash: &quot;0xad379a83ea80b1aae55e118cdadfb133bbcedb14842e6a1a1fe4cdae049d0739&quot;
    execution_block_height: 422
- deposit_data:
    pubkey: &quot;0xb41b17006e2a6a6bce8055ee459557cf835fccaa851885903846dc190adc223f6cad199446ca225b6a65d40382344227&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8c1ba3a40657d6fc08753d00115125acec2821bfcdb6e272758086cf5eb38f6653924da5b296a24ec4099958edb6c42d1539bafe103f62c926d09f03424abb0cf189985dfbf042fee90cdc4efb1204eb251825a9b5771862686271c0744ea62f&quot;
  deposit_data_root: &quot;0xdcfe0566760412e34ef921467df75a7ab63ba33709d01ec51509c229ea7f1f8b&quot;
  eth1_data:
    deposit_root: &quot;0x7ea9a20183569c27fa282cf8f41035a826ad1a4055bc201b03bfffd70a4ebf7d&quot;
    deposit_count: &quot;422&quot;
    block_hash: &quot;0x623deab0585c9ba3256328022621d3ea83974a0e95bd98cb4974fab7ff84c458&quot;
  block_height: 423
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0xfb785265dae57039dc1b110d2edb8556f05c9f2013e0cd5b57982be1642c2375&quot;
      - &quot;0xaab1605a8179a12b1e4e07684af74b5398445a216df5219be25801f44d75d56e&quot;
    deposit_root: &quot;0x7ea9a20183569c27fa282cf8f41035a826ad1a4055bc201b03bfffd70a4ebf7d&quot;
    deposit_count: 422
    execution_block_hash: &quot;0x623deab0585c9ba3256328022621d3ea83974a0e95bd98cb4974fab7ff84c458&quot;
    execution_block_height: 423
- deposit_data:
    pubkey: &quot;0xaf9a969a70272ac2871fd689f13c0b478e27bdc5127f02c41efabd5814a902dc1e3ed8b3ca1786aafb8f112aa3c87db7&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa4b4f5e4b3bab060290c43259af77f83aab46b0d5b47cf7ec63e252bc1a1cbf4473bc03b6e0d70cd822d80b93a5d686109087af68ec598e991234c5692ca91844404d7be411ed10fe57100f9d29a89fbca2b3869ab58177079fb916d7a488573&quot;
  deposit_data_root: &quot;0xed7664e9d1230b810ae66e70f7216a6cfc8dd8dfffb6781b25a724317713c991&quot;
  eth1_data:
    deposit_root: &quot;0xd4d4345b1ff711661fd8c50cb40512e1535b1e50b1abc36db5ca5ddc1d998963&quot;
    deposit_count: &quot;423&quot;
    block_hash: &quot;0x76d7667e463891a1f70c269d1a0113126715969b01f74733050cf0fed12f1f41&quot;
  block_height: 424
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0xfb785265dae57039dc1b110d2edb8556f05c9f2013e0cd5b57982be1642c2375&quot;
      - &quot;0xaab1605a8179a12b1e4e07684af74b5398445a216df5219be25801f44d75d56e&quot;
      - &quot;0xed7664e9d1230b810ae66e70f7216a6cfc8dd8dfffb6781b25a724317713c991&quot;
    deposit_root: &quot;0xd4d4345b1ff711661fd8c50cb40512e1535b1e50b1abc36db5ca5ddc1d998963&quot;
    deposit_count: 423
    execution_block_hash: &quot;0x76d7667e463891a1f70c269d1a0113126715969b01f74733050cf0fed12f1f41&quot;
    execution_block_height: 424
- deposit_data:
    pubkey: &quot;0x8faef0de1c486a7638c2a50af8f34e42b7f11bc1168c03678408702f8d11637f1faf893955a39897d797c851d1e6267e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa03d1ab7e650e5b593fc076f109653b6ab3bcbd4ab214a638c91c182073d90e44dadd8243ec6b6055a08d7876d67231d11be579189b12e04ae0f6aa2071fbfa25680102c2cd9612955bd5ccd11e6924acc1aca90f17939eb50e364484707d58a&quot;
  deposit_data_root: &quot;0x618c9f801c71c3abb9c4a6b58ecd7bb0ee58537066ab15c04b86466d53acc316&quot;
  eth1_data:
    deposit_root: &quot;0x0ff9c5f8f3fce635e0c513c911e919396b682a34471d7a6d95f709fdd15c8713&quot;
    deposit_count: &quot;424&quot;
    block_hash: &quot;0x987c1a8ce6e27f94a0bac01816f3f4f54c057350d36bee07c00d83a62555e92b&quot;
  block_height: 425
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0x60f09c9d72bd6a4e2cbb2f9f54623e280baddba85f8c51e5a07912c0782c2997&quot;
    deposit_root: &quot;0x0ff9c5f8f3fce635e0c513c911e919396b682a34471d7a6d95f709fdd15c8713&quot;
    deposit_count: 424
    execution_block_hash: &quot;0x987c1a8ce6e27f94a0bac01816f3f4f54c057350d36bee07c00d83a62555e92b&quot;
    execution_block_height: 425
- deposit_data:
    pubkey: &quot;0x95bff09876e40fee59003b08bab452d9bd2dfae2c6411e153c4fc531f4aa26af8966049cf303865472d56643e3a3ad70&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa74bde4e1b2c55840198a66fd62671eee5e81c69c0d8418eb07c16c2003ba3eef1b8a7454b4fe1df5108e22bd8710288053fc45216787688320c3bebda2fb6e0402035ec9aa54f3f23e27c541e602f7fbbd4a259f5e359592486d027da49df31&quot;
  deposit_data_root: &quot;0x370e5d74a292574246d28b1c7e721565b32b960f041768ff4727d395b42de7d7&quot;
  eth1_data:
    deposit_root: &quot;0x1e3367c89e570fe259bed5fe2dcaaf6cdf1130c88b0cbdbe3880cb020a578772&quot;
    deposit_count: &quot;425&quot;
    block_hash: &quot;0xaad57c3a976f49af3a86b03765169a35d6d785bb020ff2cf5ce6e6725d4e5669&quot;
  block_height: 426
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0x60f09c9d72bd6a4e2cbb2f9f54623e280baddba85f8c51e5a07912c0782c2997&quot;
      - &quot;0x370e5d74a292574246d28b1c7e721565b32b960f041768ff4727d395b42de7d7&quot;
    deposit_root: &quot;0x1e3367c89e570fe259bed5fe2dcaaf6cdf1130c88b0cbdbe3880cb020a578772&quot;
    deposit_count: 425
    execution_block_hash: &quot;0xaad57c3a976f49af3a86b03765169a35d6d785bb020ff2cf5ce6e6725d4e5669&quot;
    execution_block_height: 426
- deposit_data:
    pubkey: &quot;0xa186ad3532db69f509d3f38223e388c9300031630ae02c5e13e6b55db6094554647fe52dbad51f931678c43d97f6b4c6&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9464130c7ad45c27345e3383ba1e3a94ef7e5691fd9abd97b0cbd7c253a744ed2e953c561aa7196d2326a75c7a2410c4115b0968abf336ca7fa9414ab9580aa12b42e5bf991863df7ac526b8b00624704f025e6f8cdbdfb21411492fc0f30b38&quot;
  deposit_data_root: &quot;0x7d7cc85629154e45c92dcc1032aea2cb10f384ef24c4d8903cf3f6f7f4140a11&quot;
  eth1_data:
    deposit_root: &quot;0x2b3611ca950982c5bef154794766299407c48416ca3e3326072e108f83081f01&quot;
    deposit_count: &quot;426&quot;
    block_hash: &quot;0x34b26f56bc1b5b8b92acee8b5514178a4e1262479ba3c67294330a2d9dab14c8&quot;
  block_height: 427
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0x60f09c9d72bd6a4e2cbb2f9f54623e280baddba85f8c51e5a07912c0782c2997&quot;
      - &quot;0x7f0c9697e17536d1ed08f791074bb7a4acf1a34de4a9d0e99d8e5057c1cd13f3&quot;
    deposit_root: &quot;0x2b3611ca950982c5bef154794766299407c48416ca3e3326072e108f83081f01&quot;
    deposit_count: 426
    execution_block_hash: &quot;0x34b26f56bc1b5b8b92acee8b5514178a4e1262479ba3c67294330a2d9dab14c8&quot;
    execution_block_height: 427
- deposit_data:
    pubkey: &quot;0x976ecc14c14c93f8d0bcd6ee0a6f829de29fc13e167204e83d9c13d69065994af9c38424443114913e3142ca96138094&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x891aaeebcf8b8e5fbf12ae568c2782ac6ef3d42856d9476d12e7638bebd5f669bbaae802a46d7b9a41ea456547434ed806b583f696903bcc2a032961e7f123b4c0dc71356edb0db37de478452407fb48984e3d174fc821f707de94a67ef81100&quot;
  deposit_data_root: &quot;0x3e4beb332aee13ce0e48353814b5368e9571a2467f070677265eb9b41c1514d3&quot;
  eth1_data:
    deposit_root: &quot;0x3b62cf4ee50ca126c3da8052bae1db595a921d5aa400aa5a4e7b14750e8aaa5b&quot;
    deposit_count: &quot;427&quot;
    block_hash: &quot;0xfee92ed291741bf5c0e55f66775aa3b61a501b735d0b4b1c633dc48a1da857d5&quot;
  block_height: 428
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0x60f09c9d72bd6a4e2cbb2f9f54623e280baddba85f8c51e5a07912c0782c2997&quot;
      - &quot;0x7f0c9697e17536d1ed08f791074bb7a4acf1a34de4a9d0e99d8e5057c1cd13f3&quot;
      - &quot;0x3e4beb332aee13ce0e48353814b5368e9571a2467f070677265eb9b41c1514d3&quot;
    deposit_root: &quot;0x3b62cf4ee50ca126c3da8052bae1db595a921d5aa400aa5a4e7b14750e8aaa5b&quot;
    deposit_count: 427
    execution_block_hash: &quot;0xfee92ed291741bf5c0e55f66775aa3b61a501b735d0b4b1c633dc48a1da857d5&quot;
    execution_block_height: 428
- deposit_data:
    pubkey: &quot;0x847ec3a8b963b0a40506ad2e2a2f9119456d36150eeb64856f12c85a85e12d59b295d953d845246be5aeccfb70c1dc04&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb9cb0dfb5fcb39c230277f2574438a7c19d54a4ec2e3e2ffe7129f492ddca723f92f30e73dcd08649dbd534ca2cf2adf1002df9dadd275afc05f4043b5ff7dbe6e85db48ccc1b2939652c7c2dd67553d40935ec4c8f6af52125096afaea8bdaf&quot;
  deposit_data_root: &quot;0x7246ac04b767468d6e6962003af7f3c181600a6061e568046b7d4674a8cb6ba9&quot;
  eth1_data:
    deposit_root: &quot;0xd644b836a3cddf49cc1de8df9b2147a89e2cfcfe1eb18ea7d5af3415d20c5adc&quot;
    deposit_count: &quot;428&quot;
    block_hash: &quot;0x50f3f0653ab23862d6539b59676e3f7b9d7af24750232050ac04473e7d14c2ca&quot;
  block_height: 429
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0x60f09c9d72bd6a4e2cbb2f9f54623e280baddba85f8c51e5a07912c0782c2997&quot;
      - &quot;0xabd7629e265df3c45f91829f510911e1a6dc607cf1967e4cf7a6a1978741a35e&quot;
    deposit_root: &quot;0xd644b836a3cddf49cc1de8df9b2147a89e2cfcfe1eb18ea7d5af3415d20c5adc&quot;
    deposit_count: 428
    execution_block_hash: &quot;0x50f3f0653ab23862d6539b59676e3f7b9d7af24750232050ac04473e7d14c2ca&quot;
    execution_block_height: 429
- deposit_data:
    pubkey: &quot;0xa6be6fc30a561b92e84333e413ce5be1d83de64ff5cef73611840fde672bf26763901912b37dfd8f1af85c3af87c8718&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x97b2556b101e1c5b723317713a0bc7ec78848d693b16475f1d0ef7679a75189510913cd7e211a9347242dfaae7ebd71e05010b840b2920cc1a36b4402ddbbab8d299b67cf49a171c8a39b30c75880a455f2055717a5021e390f1073d398825f4&quot;
  deposit_data_root: &quot;0x28bacf6966c371a93169d29ba14a8a7f29b578c65832e521502eec860369c813&quot;
  eth1_data:
    deposit_root: &quot;0xbfc44c7d1d7f6b4df91c5cf86fa7b578915638c69752caa00aac61cc88f2531d&quot;
    deposit_count: &quot;429&quot;
    block_hash: &quot;0xd6afed7b6d18bb3524ad6fb17e2c46acdbcfbb3197f82e2b287d17e945a2b8cd&quot;
  block_height: 430
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0x60f09c9d72bd6a4e2cbb2f9f54623e280baddba85f8c51e5a07912c0782c2997&quot;
      - &quot;0xabd7629e265df3c45f91829f510911e1a6dc607cf1967e4cf7a6a1978741a35e&quot;
      - &quot;0x28bacf6966c371a93169d29ba14a8a7f29b578c65832e521502eec860369c813&quot;
    deposit_root: &quot;0xbfc44c7d1d7f6b4df91c5cf86fa7b578915638c69752caa00aac61cc88f2531d&quot;
    deposit_count: 429
    execution_block_hash: &quot;0xd6afed7b6d18bb3524ad6fb17e2c46acdbcfbb3197f82e2b287d17e945a2b8cd&quot;
    execution_block_height: 430
- deposit_data:
    pubkey: &quot;0xb1ea18e5c0a7424d06a9e77c65f2ff5047b5c4530e34e700c0d1bf15579e2afad228a8213c68eff8c14353d2e1f10053&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa965b7ec3ba5eb7d723ae622732f9398f875bffb7941b121c14daace185523a42e662151832132b8b296903c4432f77b02e06400a84268834eae712813f6bd4af66e571fd397c2dca316dba4c5ef7091ada36ddd5726d1db8e1e1f8ef6c40f6e&quot;
  deposit_data_root: &quot;0x81e40c00c14deb34eb65e0a158104b60554fd0624bfa86b560cddcd29eb66750&quot;
  eth1_data:
    deposit_root: &quot;0x46bb5f072f410bcb56d1f87830a0db231802265dec6ac59acd451360db8f3eab&quot;
    deposit_count: &quot;430&quot;
    block_hash: &quot;0xefef471cb7829f27db63a66917e6141f86a58f90c076f54a2ea35302ac6bb5d3&quot;
  block_height: 431
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0x60f09c9d72bd6a4e2cbb2f9f54623e280baddba85f8c51e5a07912c0782c2997&quot;
      - &quot;0xabd7629e265df3c45f91829f510911e1a6dc607cf1967e4cf7a6a1978741a35e&quot;
      - &quot;0x3bbb471bc80341245a119253a0bd27206485c8d671ce2ab1904d70b635c83297&quot;
    deposit_root: &quot;0x46bb5f072f410bcb56d1f87830a0db231802265dec6ac59acd451360db8f3eab&quot;
    deposit_count: 430
    execution_block_hash: &quot;0xefef471cb7829f27db63a66917e6141f86a58f90c076f54a2ea35302ac6bb5d3&quot;
    execution_block_height: 431
- deposit_data:
    pubkey: &quot;0x8fff13510ac685f51ae914b7177bdf296ecd757385442ea0dbfc8841685b79b7d52c780a40e07723ea34d6179c6f3ee8&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb501c7b840d94f74b23e82caa150fd57a830cc20a665a84267e069fb8a93ccc56e7faae237f875e910a533a8eaa20cce06783be38427523d18ceb88bb4fef649c256ea05bd54cde8e05bf82826857e023afdfad82da136a1586ff0cd23435430&quot;
  deposit_data_root: &quot;0xabffe715ca708ebf5bebea360ea9c27f48e040dccc482bce560d84cf0c0f364f&quot;
  eth1_data:
    deposit_root: &quot;0x19e7f6f59f1a6bfc99344743800d79127bfa93e93118783888f7fd6bc3d23087&quot;
    deposit_count: &quot;431&quot;
    block_hash: &quot;0xe61cdc39257cdd0b1d973ef37bde4c7ad35fd8b5bd245be06da6a869f3be5364&quot;
  block_height: 432
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0x60f09c9d72bd6a4e2cbb2f9f54623e280baddba85f8c51e5a07912c0782c2997&quot;
      - &quot;0xabd7629e265df3c45f91829f510911e1a6dc607cf1967e4cf7a6a1978741a35e&quot;
      - &quot;0x3bbb471bc80341245a119253a0bd27206485c8d671ce2ab1904d70b635c83297&quot;
      - &quot;0xabffe715ca708ebf5bebea360ea9c27f48e040dccc482bce560d84cf0c0f364f&quot;
    deposit_root: &quot;0x19e7f6f59f1a6bfc99344743800d79127bfa93e93118783888f7fd6bc3d23087&quot;
    deposit_count: 431
    execution_block_hash: &quot;0xe61cdc39257cdd0b1d973ef37bde4c7ad35fd8b5bd245be06da6a869f3be5364&quot;
    execution_block_height: 432
- deposit_data:
    pubkey: &quot;0xad2d0e0c00b5a16d50a4ae56a3c0cf2e1b2263e2dd53ddad54679cdbf338300e1003af5ecb73ac3dacb8636661e142d5&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x841c98171049ea19762d010391bf195c097c130667801133259262d06ab7464e26cf14bf0dac3c8d08890db416a3301519474ab35920fd9ea961ebe80ae7a076f609fcf8cadf99c3bd46aac91456c6f543783cd042525bad6fe94730755330da&quot;
  deposit_data_root: &quot;0xa2a0f194432b58ec992b183815bfd4f21a1acdde93677175ec830dc8ada25092&quot;
  eth1_data:
    deposit_root: &quot;0x83784abcabf728772306f379a348e2329b6b03428e8120b6deb3ba1aefba2407&quot;
    deposit_count: &quot;432&quot;
    block_hash: &quot;0x98b16968453d04262b7c05ee1a2b09bcbcf8e29473c6d1a74bcaa3d03af6eccb&quot;
  block_height: 433
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0xbe065ffe4f04afdfe075ddd6d51b69a8b470abe91f51e18845e3dd959b272134&quot;
    deposit_root: &quot;0x83784abcabf728772306f379a348e2329b6b03428e8120b6deb3ba1aefba2407&quot;
    deposit_count: 432
    execution_block_hash: &quot;0x98b16968453d04262b7c05ee1a2b09bcbcf8e29473c6d1a74bcaa3d03af6eccb&quot;
    execution_block_height: 433
- deposit_data:
    pubkey: &quot;0xb854086bc1f668ad8ccc4ed3a7a52eab65210717c3f8b9e6ebc27c1cf27ccba0a4056311c69cfefe875fa45e2cd26e69&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa94b7daed00dd9fdacdb5cdc0635b588e5c3ab124438d7a1a59b068708e2fc3de327e35ce66800db13f100ca332db93219ff60525e13d868c66b5920d76c38c4264b9e68ada4586642ca4f02ec33438989c7f1d00cb9b02dd49dfc47d401d8f8&quot;
  deposit_data_root: &quot;0xda7276d3cd6c2ea2db69550570f8721ecb14d9e122e35c2d6090c600ad286bd9&quot;
  eth1_data:
    deposit_root: &quot;0x25028b90b69a3ff62a7a3cb3e67cf58130aa8868027f3b41613d71e8156162c8&quot;
    deposit_count: &quot;433&quot;
    block_hash: &quot;0xa783b7745e047a84c6270ab3910a09b000044ee37bca6caa2446153767236733&quot;
  block_height: 434
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0xbe065ffe4f04afdfe075ddd6d51b69a8b470abe91f51e18845e3dd959b272134&quot;
      - &quot;0xda7276d3cd6c2ea2db69550570f8721ecb14d9e122e35c2d6090c600ad286bd9&quot;
    deposit_root: &quot;0x25028b90b69a3ff62a7a3cb3e67cf58130aa8868027f3b41613d71e8156162c8&quot;
    deposit_count: 433
    execution_block_hash: &quot;0xa783b7745e047a84c6270ab3910a09b000044ee37bca6caa2446153767236733&quot;
    execution_block_height: 434
- deposit_data:
    pubkey: &quot;0x95000d5a88212033fcc30690e930c2128685b97f26a9e2c52b75e1fb562a1db1b9af071207823ef1927db3ca65ee00ef&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8444dfc139521e5236c5f5637cfa17c87b6fd06e5ca8d4e33e522f02cf9fee562903dcd42f173696c981e1113be5bee5102f84730a31c9e03b45b753178c65d87335bf82cd600384fc4d03151ca94880b0df31bad1ab4f09d760c604ca16487a&quot;
  deposit_data_root: &quot;0x184c58ea01f5c0c47d5dec98d30cfd9edeb11060b1c931cb3d117fd5cd6d7c4a&quot;
  eth1_data:
    deposit_root: &quot;0xbd639adce24d58cfbc0f226d6a045f400506c30d3388b4e520816c2ad1a5776d&quot;
    deposit_count: &quot;434&quot;
    block_hash: &quot;0xa36bde80ad1b5c6fa8848e656ef5c9c95411042e1fff4ffc23b4bc2bcb7e6bee&quot;
  block_height: 435
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0xbe065ffe4f04afdfe075ddd6d51b69a8b470abe91f51e18845e3dd959b272134&quot;
      - &quot;0x923555fa4c1bad92de2ae74472f84089b9f15bfcf562d84eb249313dc6bb6ae2&quot;
    deposit_root: &quot;0xbd639adce24d58cfbc0f226d6a045f400506c30d3388b4e520816c2ad1a5776d&quot;
    deposit_count: 434
    execution_block_hash: &quot;0xa36bde80ad1b5c6fa8848e656ef5c9c95411042e1fff4ffc23b4bc2bcb7e6bee&quot;
    execution_block_height: 435
- deposit_data:
    pubkey: &quot;0x929ab4e52386b139d32da163a4e1be5760f1d97bcfdaaa146f8b0348c94896b33fdbc3083ff3a41063e1b969a1f84080&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x81b4e7bf1ea952ddeba8fdf3e4b81162e5f7481fa9f59a95604fb0b8f8e4edd17e114d264ce0a236ce2459880a68c11317ac8aa2faeca6f80eb2e5cb53f106dd992e687c7b86536de330630e0c7de7ae16ef04646f05e98340d689157b704f0c&quot;
  deposit_data_root: &quot;0x27578550b83a805d25278e7004eb819236d723c8e1be90d61b65d3fc50314abc&quot;
  eth1_data:
    deposit_root: &quot;0x27d9b9761517e56e0c390781d9e7e967a7376a27a09380615594f756608ab48d&quot;
    deposit_count: &quot;435&quot;
    block_hash: &quot;0x51f5137c853e6e77ec221f4c6185e11aa1f03537aa9c94d91d4a58ec8287466d&quot;
  block_height: 436
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0xbe065ffe4f04afdfe075ddd6d51b69a8b470abe91f51e18845e3dd959b272134&quot;
      - &quot;0x923555fa4c1bad92de2ae74472f84089b9f15bfcf562d84eb249313dc6bb6ae2&quot;
      - &quot;0x27578550b83a805d25278e7004eb819236d723c8e1be90d61b65d3fc50314abc&quot;
    deposit_root: &quot;0x27d9b9761517e56e0c390781d9e7e967a7376a27a09380615594f756608ab48d&quot;
    deposit_count: 435
    execution_block_hash: &quot;0x51f5137c853e6e77ec221f4c6185e11aa1f03537aa9c94d91d4a58ec8287466d&quot;
    execution_block_height: 436
- deposit_data:
    pubkey: &quot;0xb126e91bd72a3289a04fa01e108f3ab4b77f2d20a93edc1c70f8ceda1df286461e92f73b7d2f85874abb1454ae1ef535&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa7f2a03af6e7075f289910a5b4348a6b2ff4d2f02633a44faeaccb965e6c2eb77647bc1489e6a8e39746fe29cabfaa92065161485194301a25617f81b96b7fc420eba955e13b04df59214faee482a439c3a2dd7cf5e3c9ba31a0309150b7d545&quot;
  deposit_data_root: &quot;0x5ed3598bdbce2f0bc4a26dd562b02fdc5c80ee35c013ee7c28610ae954b6b5e4&quot;
  eth1_data:
    deposit_root: &quot;0x6dff34424e745612aca561b1be1d10859787245ad98e2447b7bc9fa7bde0f008&quot;
    deposit_count: &quot;436&quot;
    block_hash: &quot;0x4820d0b8cf715941790bcc4e7ee618bbbace730c2bdba686471fac3746020dc1&quot;
  block_height: 437
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0xbe065ffe4f04afdfe075ddd6d51b69a8b470abe91f51e18845e3dd959b272134&quot;
      - &quot;0x7aa625d524b4796a9c8870fee5a28d37b822d5a6c4a9959b084e764ffa123a94&quot;
    deposit_root: &quot;0x6dff34424e745612aca561b1be1d10859787245ad98e2447b7bc9fa7bde0f008&quot;
    deposit_count: 436
    execution_block_hash: &quot;0x4820d0b8cf715941790bcc4e7ee618bbbace730c2bdba686471fac3746020dc1&quot;
    execution_block_height: 437
- deposit_data:
    pubkey: &quot;0x8fe3f04f04422bb2c76f5cfddf80a7a2b01bef7170af5f52c94e64ba1f8f523ff18d09af9235e37d10b3ac8ba3cc6ac4&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x94c9697875b08a8f6dd31af84ba20b702f8ac2a3488b6ea694bc1a3afd582bc5d52dff92b0c9dfa4ab6ab7080ed434b6047e3743f1007c560cdb7482eb09147d49c79f3118dc1fac66e918d25e86226042ede65d1ed7a262b8c165b78df81e3e&quot;
  deposit_data_root: &quot;0xb40085a98ecff79943839d4d2cdd7ab9bbb72f90e94daf08c50efd26eba09c72&quot;
  eth1_data:
    deposit_root: &quot;0xf52ca6c22904e0ebef5336e0f010308fd124d5caed6a6043da92e1cbdd7afc56&quot;
    deposit_count: &quot;437&quot;
    block_hash: &quot;0x7692a6ca9efd1b0796eb01fcdb2b08fbc1739837e6f24eeefadf8cdad2a8062f&quot;
  block_height: 438
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0xbe065ffe4f04afdfe075ddd6d51b69a8b470abe91f51e18845e3dd959b272134&quot;
      - &quot;0x7aa625d524b4796a9c8870fee5a28d37b822d5a6c4a9959b084e764ffa123a94&quot;
      - &quot;0xb40085a98ecff79943839d4d2cdd7ab9bbb72f90e94daf08c50efd26eba09c72&quot;
    deposit_root: &quot;0xf52ca6c22904e0ebef5336e0f010308fd124d5caed6a6043da92e1cbdd7afc56&quot;
    deposit_count: 437
    execution_block_hash: &quot;0x7692a6ca9efd1b0796eb01fcdb2b08fbc1739837e6f24eeefadf8cdad2a8062f&quot;
    execution_block_height: 438
- deposit_data:
    pubkey: &quot;0xaaf6cc6cfc559ca26b82790935d4919ccc630438032b76874a40c25d77e4b87db2401cef8ad1871011569061ec7badcc&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa47e64f4d650537e9cb7d858267ee6862b97504ed46d11def724be28d05bd9c08e34420d5f06a1342536a47f120e8a540eb453b08c94fdb4c2deb3400f9cf87ce90a7cc1b14c8dea450111fb91f54fe4460e238588a6b4ab8778d48b99438a84&quot;
  deposit_data_root: &quot;0x99e08ee836bfaf2e9ccdcbfb308c88826e060edae11e3248a155049d4eaa772d&quot;
  eth1_data:
    deposit_root: &quot;0xb54a726ffc39347df5841efcdcdd4936894b92463db82208a447cf0071dcc95f&quot;
    deposit_count: &quot;438&quot;
    block_hash: &quot;0x3f48bbc9894a9a76b6faf91af106f773ade4285ed0b2e82591ff87514e41720b&quot;
  block_height: 439
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0xbe065ffe4f04afdfe075ddd6d51b69a8b470abe91f51e18845e3dd959b272134&quot;
      - &quot;0x7aa625d524b4796a9c8870fee5a28d37b822d5a6c4a9959b084e764ffa123a94&quot;
      - &quot;0xb3aeed2eb2f5e99db75fa362a4e6c7dccfcff20b110983ffd36ad0aaa1783e50&quot;
    deposit_root: &quot;0xb54a726ffc39347df5841efcdcdd4936894b92463db82208a447cf0071dcc95f&quot;
    deposit_count: 438
    execution_block_hash: &quot;0x3f48bbc9894a9a76b6faf91af106f773ade4285ed0b2e82591ff87514e41720b&quot;
    execution_block_height: 439
- deposit_data:
    pubkey: &quot;0x8533f1c4e38a4f72c3593ab28ccb163bfb429242a8c23e731478e57950f563b62101b06882f25c8133ea357fad66522c&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x861858db0f3721f816791c002f9d8f09254d0ba5015fc2fc609783cff8a36efc267392c0525e4e0fb4bfa96d58626732091853af4c16b9fa309e5295331a32f84b2c3be61d2c2dfc34bd9e59117c54a8c46ee50f9291ba2793450fc960e14530&quot;
  deposit_data_root: &quot;0xbbb5ada0d7f4efa62bf0ba927747f1af9d4cfcbd76eb084f24ace3c8b0167fe5&quot;
  eth1_data:
    deposit_root: &quot;0xf75c37a1a191b865e14c6dac867208ae436a48d454410ad13cc9410bd8e3bdc9&quot;
    deposit_count: &quot;439&quot;
    block_hash: &quot;0x00c49ac28a1512771b4a976e03f723442c209b14068daba22e931c5b7e357594&quot;
  block_height: 440
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0xbe065ffe4f04afdfe075ddd6d51b69a8b470abe91f51e18845e3dd959b272134&quot;
      - &quot;0x7aa625d524b4796a9c8870fee5a28d37b822d5a6c4a9959b084e764ffa123a94&quot;
      - &quot;0xb3aeed2eb2f5e99db75fa362a4e6c7dccfcff20b110983ffd36ad0aaa1783e50&quot;
      - &quot;0xbbb5ada0d7f4efa62bf0ba927747f1af9d4cfcbd76eb084f24ace3c8b0167fe5&quot;
    deposit_root: &quot;0xf75c37a1a191b865e14c6dac867208ae436a48d454410ad13cc9410bd8e3bdc9&quot;
    deposit_count: 439
    execution_block_hash: &quot;0x00c49ac28a1512771b4a976e03f723442c209b14068daba22e931c5b7e357594&quot;
    execution_block_height: 440
- deposit_data:
    pubkey: &quot;0xa20e3bcb6b38b66c2de7a7b3d1731cf430ebb94e38897d9ab9a9463bfe813ecf65f39297d2a3daa803f66bff80d6b653&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x880a58b82783d37fac7f207c9ad45e6c7fe7f98cf843bd52733e328a87ab81a4b585f598907d594b2abfc03913e0983b00cba405f0478ec3ff59954244f36467b5002354dc3f56001cf0c06fe12535dfd3813a03e561f27d0fe475153a7cc46e&quot;
  deposit_data_root: &quot;0x05bb8954b6ae43cbaf05ef800efe85d1755df3df92888c1390ac7524d332f2f1&quot;
  eth1_data:
    deposit_root: &quot;0xee960dbb2cb5694f6bd15e8fbe5d67369629cfcb89920dd6e05dd8c95ed484df&quot;
    deposit_count: &quot;440&quot;
    block_hash: &quot;0xd597af80422338ab6dff2432fe3d82e43c817e4512bb29e120492a6dfe622bd2&quot;
  block_height: 441
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0xbe065ffe4f04afdfe075ddd6d51b69a8b470abe91f51e18845e3dd959b272134&quot;
      - &quot;0xb009f607491090689f616596852977e7f2617f96388353655e0b01bb9e3c5477&quot;
    deposit_root: &quot;0xee960dbb2cb5694f6bd15e8fbe5d67369629cfcb89920dd6e05dd8c95ed484df&quot;
    deposit_count: 440
    execution_block_hash: &quot;0xd597af80422338ab6dff2432fe3d82e43c817e4512bb29e120492a6dfe622bd2&quot;
    execution_block_height: 441
- deposit_data:
    pubkey: &quot;0x8cd7d05a46ad2e98ea82c438f12dc9fad70fa0b8cff2a731847efedc0efadef9a3f4d9e12cf8e9469d157d106f12626d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa580ca98af67b935e7b896aa223bb2ae6fc23313da1d47595e244f5f9f6aac65b7b396a196be2722d6cf036f8c293de81736674e13303d5a6c8d8893ae1fc5b572edd9a84bb0feefe7ec293f6d9050f9687bf930ef42dffabb554094c24962b1&quot;
  deposit_data_root: &quot;0x4c2f5d2c7521c2fa4bc78d77d66c44bc032f688fdeae2a216221fb20f49645ab&quot;
  eth1_data:
    deposit_root: &quot;0x03e6ba3922640836649ecbb7649e8b5361eed51edc0e24919c4a2f258350be34&quot;
    deposit_count: &quot;441&quot;
    block_hash: &quot;0xf4a32ac25eb43a2dee79b2620ab6d79fcecfe26f5b4d1743a6c6e47057f8f478&quot;
  block_height: 442
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0xbe065ffe4f04afdfe075ddd6d51b69a8b470abe91f51e18845e3dd959b272134&quot;
      - &quot;0xb009f607491090689f616596852977e7f2617f96388353655e0b01bb9e3c5477&quot;
      - &quot;0x4c2f5d2c7521c2fa4bc78d77d66c44bc032f688fdeae2a216221fb20f49645ab&quot;
    deposit_root: &quot;0x03e6ba3922640836649ecbb7649e8b5361eed51edc0e24919c4a2f258350be34&quot;
    deposit_count: 441
    execution_block_hash: &quot;0xf4a32ac25eb43a2dee79b2620ab6d79fcecfe26f5b4d1743a6c6e47057f8f478&quot;
    execution_block_height: 442
- deposit_data:
    pubkey: &quot;0xab5fec7f75687d50f35f4336b7ac78108834f98d9979f0327cd11b1557b6ad9dc119889003384b3940b10f0af7b8314e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb71c223a9819d28964a114bf849fb9f765087d4d32019a5fccc1062ea217a68ae8475708179e926d60f60df70a39973d09e6e387807f287dbf2d02db7a45be47f428330d2d2900a531b716ea53f90e9109c3aa061c1291b484eacb3f574372bb&quot;
  deposit_data_root: &quot;0x1d605f33e04dd29303dafd86bd3dd88e3fa4fe9f8a690c596af384d1515e4d23&quot;
  eth1_data:
    deposit_root: &quot;0x3f9a271478e34f229dbde7880720bb764f94cc3008ad30fc40b822fa46551e7c&quot;
    deposit_count: &quot;442&quot;
    block_hash: &quot;0x1306dfc166e3c7fdfe93ce194349c64b49f57eb0ab103fc426be4cc1ef7256f1&quot;
  block_height: 443
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0xbe065ffe4f04afdfe075ddd6d51b69a8b470abe91f51e18845e3dd959b272134&quot;
      - &quot;0xb009f607491090689f616596852977e7f2617f96388353655e0b01bb9e3c5477&quot;
      - &quot;0xacc05a3daa1af57565781fd828122e22e64a429030d2e8b20702611e6f49bd47&quot;
    deposit_root: &quot;0x3f9a271478e34f229dbde7880720bb764f94cc3008ad30fc40b822fa46551e7c&quot;
    deposit_count: 442
    execution_block_hash: &quot;0x1306dfc166e3c7fdfe93ce194349c64b49f57eb0ab103fc426be4cc1ef7256f1&quot;
    execution_block_height: 443
- deposit_data:
    pubkey: &quot;0xaa93eab6f16b0bee0a2eaf3d548d354a716e1bfa4047ffae14af55bb49bb994310265e10c7ab47ffa33d1c3eceadbb4b&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa4d489afd3c027948032978b0384fed21b6013e19108ebd8f2937e3b32854c91ea80dcf183670be34574a05634eb06b4109970b34b0e998f9d09615a7b8ec277c2d62b43daacc9d346733060dd7f08208164c57cc54dee78de08c4d42774e51b&quot;
  deposit_data_root: &quot;0xc91ecd7959d5713b9f528f6fdfdf456416f0c19514640347fd465d24352e35d5&quot;
  eth1_data:
    deposit_root: &quot;0x7bc70f5b38014ee13c40977439be4afa105e103bf24aff9c687c1d52def0d90c&quot;
    deposit_count: &quot;443&quot;
    block_hash: &quot;0xb6fcd3780b78de4f093046724aba76445fff193f0aab33ee3e08099403f5d076&quot;
  block_height: 444
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0xbe065ffe4f04afdfe075ddd6d51b69a8b470abe91f51e18845e3dd959b272134&quot;
      - &quot;0xb009f607491090689f616596852977e7f2617f96388353655e0b01bb9e3c5477&quot;
      - &quot;0xacc05a3daa1af57565781fd828122e22e64a429030d2e8b20702611e6f49bd47&quot;
      - &quot;0xc91ecd7959d5713b9f528f6fdfdf456416f0c19514640347fd465d24352e35d5&quot;
    deposit_root: &quot;0x7bc70f5b38014ee13c40977439be4afa105e103bf24aff9c687c1d52def0d90c&quot;
    deposit_count: 443
    execution_block_hash: &quot;0xb6fcd3780b78de4f093046724aba76445fff193f0aab33ee3e08099403f5d076&quot;
    execution_block_height: 444
- deposit_data:
    pubkey: &quot;0xae363ffe8d6c6858d3c32967150ef670a2262ab9f46b3f2e3e4ae8910092bad1e7208ff9ba3f28b151dfab12f3474a19&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x803d1670174da10aa0eae9a24ef57151ce4fe2eb9f8c3144761f90fe483fd38d06aea4b7e6879afd43c5e1e3dfa223230edb7385dcd41d0d4eff69f94690ceab02bf9d5c35ecda1e30cc929403f64b0a08e9de644cbba5efcc5814ffbfc51322&quot;
  deposit_data_root: &quot;0x1ec544baffa893fc7cc179cccb186cae5d98da2920f837e49b6cd683abcb8fb6&quot;
  eth1_data:
    deposit_root: &quot;0xb81e9256ace4aee3308b567f7fb37713dff69385afb6b57a436070f318c2bd7b&quot;
    deposit_count: &quot;444&quot;
    block_hash: &quot;0x3c24b3a1983001debec5a13e73083d0bb99ab232cc3b26985f78dae529564581&quot;
  block_height: 445
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0xbe065ffe4f04afdfe075ddd6d51b69a8b470abe91f51e18845e3dd959b272134&quot;
      - &quot;0xb009f607491090689f616596852977e7f2617f96388353655e0b01bb9e3c5477&quot;
      - &quot;0xa1b8c431a46186490644ac091a8a657e248fdf1dbabd59a9e6c69007dce25c3b&quot;
    deposit_root: &quot;0xb81e9256ace4aee3308b567f7fb37713dff69385afb6b57a436070f318c2bd7b&quot;
    deposit_count: 444
    execution_block_hash: &quot;0x3c24b3a1983001debec5a13e73083d0bb99ab232cc3b26985f78dae529564581&quot;
    execution_block_height: 445
- deposit_data:
    pubkey: &quot;0x83ae23912c04f49176c912a5d728224c3bbfac588e2203e37c6ca7520b01c6225b2830b0d37c8eb641d9abb44a648e28&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8b5366124d214e3f88667a97297b75e2feaf3f54e09047b6e1d805499c961c76685f4dd16c8d169cff4fc17c401747ac0b6685693e80ab3324e4c77fcde51afb210799489d32a8251d6c25623abd5eb4930ab097b4d6d6daa38ad752cff3b435&quot;
  deposit_data_root: &quot;0xe76b1cfd301efe07f3af9878e54067b811f1872abd8cb7a02442fdf7cadd6d54&quot;
  eth1_data:
    deposit_root: &quot;0x99b58fdf354bd79892edced1978af6264777847c433d692efbfedff57526c7bd&quot;
    deposit_count: &quot;445&quot;
    block_hash: &quot;0x7480cf6cd450d4e3d9a461c222e8e0fd3a4416ac6c66a18d95bd870ed0294806&quot;
  block_height: 446
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0xbe065ffe4f04afdfe075ddd6d51b69a8b470abe91f51e18845e3dd959b272134&quot;
      - &quot;0xb009f607491090689f616596852977e7f2617f96388353655e0b01bb9e3c5477&quot;
      - &quot;0xa1b8c431a46186490644ac091a8a657e248fdf1dbabd59a9e6c69007dce25c3b&quot;
      - &quot;0xe76b1cfd301efe07f3af9878e54067b811f1872abd8cb7a02442fdf7cadd6d54&quot;
    deposit_root: &quot;0x99b58fdf354bd79892edced1978af6264777847c433d692efbfedff57526c7bd&quot;
    deposit_count: 445
    execution_block_hash: &quot;0x7480cf6cd450d4e3d9a461c222e8e0fd3a4416ac6c66a18d95bd870ed0294806&quot;
    execution_block_height: 446
- deposit_data:
    pubkey: &quot;0x86d99bd43392d34879ff4409aaa44f1a42b34471a59136ff2fc2c5d0f3bee905108958f4a0de383597476b6f8fa380eb&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8560371d260fcc434e0da634b18e1216ca8d63ea40486020c9568fbd959ed350f8b8b3fc1f6f88a48b7517d927c08c04190dc945da272ece929599becb29c8ed939ccb31cc4f316bf2c7341e2373f44ff8515858606fab8165e4ac6356f037bc&quot;
  deposit_data_root: &quot;0x28f2965716ad7616ab299ba34a56b5da43142e03867076aa477efc5774f7aa12&quot;
  eth1_data:
    deposit_root: &quot;0x440365613909570f9c374a476876624deed2636114a1dece1e7051d565d687f9&quot;
    deposit_count: &quot;446&quot;
    block_hash: &quot;0x452bf66254b503662848f580173b6b13a10efdf20d2016683b67c4d0beafbad4&quot;
  block_height: 447
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0xbe065ffe4f04afdfe075ddd6d51b69a8b470abe91f51e18845e3dd959b272134&quot;
      - &quot;0xb009f607491090689f616596852977e7f2617f96388353655e0b01bb9e3c5477&quot;
      - &quot;0xa1b8c431a46186490644ac091a8a657e248fdf1dbabd59a9e6c69007dce25c3b&quot;
      - &quot;0x22ee861ca07aca649f7d8b981e6c3bf4615ac3944a6acefbfbc843fe66b2d14f&quot;
    deposit_root: &quot;0x440365613909570f9c374a476876624deed2636114a1dece1e7051d565d687f9&quot;
    deposit_count: 446
    execution_block_hash: &quot;0x452bf66254b503662848f580173b6b13a10efdf20d2016683b67c4d0beafbad4&quot;
    execution_block_height: 447
- deposit_data:
    pubkey: &quot;0xae47eed8ebfbd33bf1e92f52fc40d16f4b2b5e0cf4f54f2463af76f83cf0fef26475dff6c5b9d78f81925ca7d51190ed&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x80f785a5c57201068c993fde0c2efb2004cfe05a03a65bae1562b9663fd62aa6a27fc529c69966838b3d2e41014eacdc1211d67c7ecfafb32d92e34a1bfdbd4df20f3051b7398715b95f34046e1e157186f2502725000322f66b6684ac7a5679&quot;
  deposit_data_root: &quot;0x4c4ee3b1458b7a43155652b0c8e734776ed957d7f0baadb41e9c69615240a8fb&quot;
  eth1_data:
    deposit_root: &quot;0x024dc727a35948ddc2d5c8def41df75d4ab5f9c638d8420fc130ce350d4ebf5c&quot;
    deposit_count: &quot;447&quot;
    block_hash: &quot;0x5d0fc230f957aec298b3a4f35bd4dbbdd2a71de4696668501310240d0c3c36ff&quot;
  block_height: 448
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0x2586924062b8d4cce4bda9de914e2a85d8352e0ea9d1512a816b099cbcb65c05&quot;
      - &quot;0xbe065ffe4f04afdfe075ddd6d51b69a8b470abe91f51e18845e3dd959b272134&quot;
      - &quot;0xb009f607491090689f616596852977e7f2617f96388353655e0b01bb9e3c5477&quot;
      - &quot;0xa1b8c431a46186490644ac091a8a657e248fdf1dbabd59a9e6c69007dce25c3b&quot;
      - &quot;0x22ee861ca07aca649f7d8b981e6c3bf4615ac3944a6acefbfbc843fe66b2d14f&quot;
      - &quot;0x4c4ee3b1458b7a43155652b0c8e734776ed957d7f0baadb41e9c69615240a8fb&quot;
    deposit_root: &quot;0x024dc727a35948ddc2d5c8def41df75d4ab5f9c638d8420fc130ce350d4ebf5c&quot;
    deposit_count: 447
    execution_block_hash: &quot;0x5d0fc230f957aec298b3a4f35bd4dbbdd2a71de4696668501310240d0c3c36ff&quot;
    execution_block_height: 448
- deposit_data:
    pubkey: &quot;0x9286bfc698dd8f807748245c4d13de02910fcd8bc9b375a308d8a2bc7c73a05c8254b73931e448fbb2cf2d24f8b42f56&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xaa4d210f5d05cc9475174d918b7f495c5a91291e08eb6e747a513265d3d7b52444df7213e1d476b8513f6ddcc90bf97c0e5ce888570f5537cc450b14ae716bc5bde3a8a251b9feb35129b63f52df8926494b921c0c2317548c680109503acff0&quot;
  deposit_data_root: &quot;0xffe2744a1f6606c4f333a1163e422c905af1da3faa8355a7c1d14b4d96cf3a12&quot;
  eth1_data:
    deposit_root: &quot;0x783f4af9f9ff701317e0a1fe3c9772aba6748d2c3278d5ab1bd30feb212dbccf&quot;
    deposit_count: &quot;448&quot;
    block_hash: &quot;0x3ca4825aa555d4e316dcf61ea7d127988b176af164b1705bab9831427b3a48c8&quot;
  block_height: 449
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
    deposit_root: &quot;0x783f4af9f9ff701317e0a1fe3c9772aba6748d2c3278d5ab1bd30feb212dbccf&quot;
    deposit_count: 448
    execution_block_hash: &quot;0x3ca4825aa555d4e316dcf61ea7d127988b176af164b1705bab9831427b3a48c8&quot;
    execution_block_height: 449
- deposit_data:
    pubkey: &quot;0x98857d698710dbc26a57f167d463de3fc8e15fa4221d8ef6d8853c7843b04d2119a865215075f52674340300e1ff58a7&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xad731a0a79a0d708d244ee8766bca38692a89fb89abca67ed6ed6bb672daf44ab77fa66ad298f0a158e72d3f7b3a55c719700c6173b8447d7cb46b07336fbae244fa124e3f98b825b7dc10c9429fc85dc4a5aa671006021aa0a72e5552b95ef3&quot;
  deposit_data_root: &quot;0x6af628d2a153eb81599f51910fd685f52bd32fb10ac3556bb0c608b35afc0c5e&quot;
  eth1_data:
    deposit_root: &quot;0x03cfe15696d6d04ec988563cf653ae99e72a85641c1de5499e287c0dbfc3fe86&quot;
    deposit_count: &quot;449&quot;
    block_hash: &quot;0x090750899e4923ca431e67389a655fe6080af94162863e81712b21111ffd5587&quot;
  block_height: 450
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x6af628d2a153eb81599f51910fd685f52bd32fb10ac3556bb0c608b35afc0c5e&quot;
    deposit_root: &quot;0x03cfe15696d6d04ec988563cf653ae99e72a85641c1de5499e287c0dbfc3fe86&quot;
    deposit_count: 449
    execution_block_hash: &quot;0x090750899e4923ca431e67389a655fe6080af94162863e81712b21111ffd5587&quot;
    execution_block_height: 450
- deposit_data:
    pubkey: &quot;0xabb8d751f2f97cd345688187accda8e00395503e500bd727b82b0be88484587776c225d64ca72703c186d6d0cb248e76&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x83ea0cdfe5f2641f06f69411ac348b2429f34544f17fba693e58a7c395b86afe7cb52ec681ee2b92865b38a2ef600f2708eb9746987cd9a4bd831a2d74953e17077c8eff72002d1e6dcfc63693c42e6c48801ed6960480cb8e88b36bdd67df5a&quot;
  deposit_data_root: &quot;0x966d2b44d3db4cd7fe7b890d54612f94f5e66aff6bb82f352e17ad42a35c7f60&quot;
  eth1_data:
    deposit_root: &quot;0x31cb5ea97e5cdb9ca3d10a4098e70b8fd784e6796603c63634eec24610665a1a&quot;
    deposit_count: &quot;450&quot;
    block_hash: &quot;0x1b42b2023d6aab58dcf21a8f96a4fd53a9980a99a92278d95bad77b79b3eb143&quot;
  block_height: 451
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x2ee848cde5b8b481d247e89b448dbd7e7fb077ce49a7a8777cb3d52d858452ef&quot;
    deposit_root: &quot;0x31cb5ea97e5cdb9ca3d10a4098e70b8fd784e6796603c63634eec24610665a1a&quot;
    deposit_count: 450
    execution_block_hash: &quot;0x1b42b2023d6aab58dcf21a8f96a4fd53a9980a99a92278d95bad77b79b3eb143&quot;
    execution_block_height: 451
- deposit_data:
    pubkey: &quot;0xb88f1156883e6edf6df2f4f94079d373992e2d236ddf7003cd8cf84d73e371d16d4397fc20163eb4d8b5ff134beb4b51&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8fcd914835883541cef44b08c1b3fc7c91b28f6fb491b9beff48554ac227dcb6ed535bb1a6cf8cd9be97f495420f358116c39749895d17784a6828bbfacc22c6bf3c42d17f8e4a8900ea17be43e6c5b27f4a83793ff68b26a9d9fcebc6a376e8&quot;
  deposit_data_root: &quot;0x88c1120bb5fa6ab67bf2b80803a27302619bdee14a10cf97df1e56ded1ed54d3&quot;
  eth1_data:
    deposit_root: &quot;0xe8b7f46dc7475278120b4752ae46cf7b4dc209ad1948739a5559bb8ad2c43846&quot;
    deposit_count: &quot;451&quot;
    block_hash: &quot;0x58a48bedd093c961425032a2b01bcc2789f04af84e1474c57d1739a0288553ce&quot;
  block_height: 452
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x2ee848cde5b8b481d247e89b448dbd7e7fb077ce49a7a8777cb3d52d858452ef&quot;
      - &quot;0x88c1120bb5fa6ab67bf2b80803a27302619bdee14a10cf97df1e56ded1ed54d3&quot;
    deposit_root: &quot;0xe8b7f46dc7475278120b4752ae46cf7b4dc209ad1948739a5559bb8ad2c43846&quot;
    deposit_count: 451
    execution_block_hash: &quot;0x58a48bedd093c961425032a2b01bcc2789f04af84e1474c57d1739a0288553ce&quot;
    execution_block_height: 452
- deposit_data:
    pubkey: &quot;0xb37a06d51bf2a06b938b2a1d84fc0e9a0d45e753401035d0c7557b01d200c302169a06c5276ed77b7b832a885376522e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb8152b87ca263de22dd75f0ef8197369bd750813ce33e8d49a67ee27ef560f384fe388f05a14aa0ac1a15cc43b7dcabe02bbd2035531e677009d17a552338e34e1bfdeedffecdc32982ed80ff2d863f39ee6b1e04136ea43a129edc137f60114&quot;
  deposit_data_root: &quot;0x719a442d020d219e23f2c202c972311f1eab73fd8bfe61a3518405c83c4df232&quot;
  eth1_data:
    deposit_root: &quot;0xb522e60c52c239b043e08c2f0cda07c615337f6067f9f76e794b1f71145727f4&quot;
    deposit_count: &quot;452&quot;
    block_hash: &quot;0xc276347716f8b77e58ce6840bae2e5fa0167bcc32590b414298060c7c70bc921&quot;
  block_height: 453
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x6cd34b4abd5cf459af14ab7b1b53f14c3f3c752241056a9b64349432d18e4f4e&quot;
    deposit_root: &quot;0xb522e60c52c239b043e08c2f0cda07c615337f6067f9f76e794b1f71145727f4&quot;
    deposit_count: 452
    execution_block_hash: &quot;0xc276347716f8b77e58ce6840bae2e5fa0167bcc32590b414298060c7c70bc921&quot;
    execution_block_height: 453
- deposit_data:
    pubkey: &quot;0xb960a785f7ea8fc1d9886ff43e3b736cf7fab383087b6f1d85727473d909a91215ec515fe72783d703e8d214cc72dbde&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xaa429b2d68b1a5e8493e942954a03d4cf7234280c5c48ece941bfaeb877351da8c9fc915141afb1e9f8ebca3eb4c1a7f006f4ba60b43df7951a87f9dcb7286b8bdcb8e34e3b1e73b53645425e35d68a7b95688b3557bcb30f7c45de075d3620d&quot;
  deposit_data_root: &quot;0x80b0dadc1f658351f89567fc40f0775d9a496f4e72380fc1187690de3223a11b&quot;
  eth1_data:
    deposit_root: &quot;0xc9f3220a5eef0065415e6ff59ca524424b32ad98e61d6a5fa58e3addf0c1d3b1&quot;
    deposit_count: &quot;453&quot;
    block_hash: &quot;0x99799c65563071761573abee510fc22423fd463f2f1ffc6c1185038e82171f51&quot;
  block_height: 454
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x6cd34b4abd5cf459af14ab7b1b53f14c3f3c752241056a9b64349432d18e4f4e&quot;
      - &quot;0x80b0dadc1f658351f89567fc40f0775d9a496f4e72380fc1187690de3223a11b&quot;
    deposit_root: &quot;0xc9f3220a5eef0065415e6ff59ca524424b32ad98e61d6a5fa58e3addf0c1d3b1&quot;
    deposit_count: 453
    execution_block_hash: &quot;0x99799c65563071761573abee510fc22423fd463f2f1ffc6c1185038e82171f51&quot;
    execution_block_height: 454
- deposit_data:
    pubkey: &quot;0xac748de8d5418285e99661d22ef888ee9b19fee4e3bb2db1fbd4404ac32fabf9ba2d41450c2f2ba42bd97cdf28a349b8&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x89cb911ffbffec15dfaec2c21298681348e4c02cf3e6dde9c7fc73093b94115cf433a485dea3561efcf7feb2cf9c2ede105004f477bad9be075e408dd73ef9c3be78862c8b6b3bf4122b28f887ae0a0120bc7a754e1f46dcc6b4b9606ddbc23b&quot;
  deposit_data_root: &quot;0xcd7377eac780c66d2dd90fbcda1563fbcc7f4cb53c0d2e2f4c22f88005755562&quot;
  eth1_data:
    deposit_root: &quot;0x20d947edb9a78bcf6b5a8ab78f2fc9d1b08a451d553977ae010d2cdc39566e59&quot;
    deposit_count: &quot;454&quot;
    block_hash: &quot;0x60bc4577621cbd0cbeb9238733a408f77bc2a1958775e864f8dbaf88e09be44c&quot;
  block_height: 455
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x6cd34b4abd5cf459af14ab7b1b53f14c3f3c752241056a9b64349432d18e4f4e&quot;
      - &quot;0xfa8b871b3d268957a0da1ff487492cb4e8ac619d397f80e1a36987ca54ef56f9&quot;
    deposit_root: &quot;0x20d947edb9a78bcf6b5a8ab78f2fc9d1b08a451d553977ae010d2cdc39566e59&quot;
    deposit_count: 454
    execution_block_hash: &quot;0x60bc4577621cbd0cbeb9238733a408f77bc2a1958775e864f8dbaf88e09be44c&quot;
    execution_block_height: 455
- deposit_data:
    pubkey: &quot;0xa89895024ffe3c247d5515a8f2cf3e5275dec9c1c3143d7a4dbabe1aa16761ca69225bd2921a4afee83e01cb4c83c25f&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x84d1d54c7b7afe591fd9be6342e92f4a1e0a0983a73cbf620c9653f602df0b9f1fd205e2b5e21edb3529cfb4fb200681012beaf6de044ee3198b256134c1a2b655df3fdeba942999f6f4e1642fa34b6185c5016d353e19441fcf55cebf6fd085&quot;
  deposit_data_root: &quot;0xd5166ba088a056939b9bd3f7fc516190e2dd84b2f2872c225236a97908cf5d60&quot;
  eth1_data:
    deposit_root: &quot;0xb9093524f50637874422a739e135b55224a74123bf8d04b993a02921a5401dae&quot;
    deposit_count: &quot;455&quot;
    block_hash: &quot;0x6a4fb53350211cabe2bc406b3da41c4fc959922aa4953a42326fa0c58b5db8b8&quot;
  block_height: 456
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x6cd34b4abd5cf459af14ab7b1b53f14c3f3c752241056a9b64349432d18e4f4e&quot;
      - &quot;0xfa8b871b3d268957a0da1ff487492cb4e8ac619d397f80e1a36987ca54ef56f9&quot;
      - &quot;0xd5166ba088a056939b9bd3f7fc516190e2dd84b2f2872c225236a97908cf5d60&quot;
    deposit_root: &quot;0xb9093524f50637874422a739e135b55224a74123bf8d04b993a02921a5401dae&quot;
    deposit_count: 455
    execution_block_hash: &quot;0x6a4fb53350211cabe2bc406b3da41c4fc959922aa4953a42326fa0c58b5db8b8&quot;
    execution_block_height: 456
- deposit_data:
    pubkey: &quot;0x8e0cd6b49327ba93279e394f62cb84375fc63bbac7c72eb4f90cd5d71e4cf34f1fe0d92b82ce51e60d9255a0fe99e021&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb16f03ea11ebd8f5f5c864bf87df767429229be5fad7b41bf26fa025bc4248af339ff07be292f5661d975344c4947d871368db8fd3ab8995c7ba358e4e73218b169fa32fbcc4839f9d1a1a9ef52b4169929d48d400783cc959ad4ca27a3432ad&quot;
  deposit_data_root: &quot;0x35d372da653d0c041ede27965e52876b47afacc14fc6ed6eaf37580bd5f85177&quot;
  eth1_data:
    deposit_root: &quot;0x88685588119ba1394dfd58c01b558e18fd9e1630431136f478f0099a37fad6f4&quot;
    deposit_count: &quot;456&quot;
    block_hash: &quot;0x16b9630f3d0113ff5a3688bd3ecff00d4958a1136f6e3e9c6155a35288c51cd6&quot;
  block_height: 457
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x53c1bf574da722d22635feb98ceae3cfa185fec248396946d571681fb60e9005&quot;
    deposit_root: &quot;0x88685588119ba1394dfd58c01b558e18fd9e1630431136f478f0099a37fad6f4&quot;
    deposit_count: 456
    execution_block_hash: &quot;0x16b9630f3d0113ff5a3688bd3ecff00d4958a1136f6e3e9c6155a35288c51cd6&quot;
    execution_block_height: 457
- deposit_data:
    pubkey: &quot;0xab195eaafc5a60c4c91722f53e19fce9c04ba9655f433a18f0472606ec826fbf77828d16f859297a9272d2b4fe50403b&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9297d77b34934381a63a39e25ae8ffd26a67bb1baaf6ce2d39ae53dde9e0ba2eb9ea5f6cd61d9f82a73e3c8f00220b5c14ded82f49ccc953a82a6f352a693d57ec256877122b2caf56c8405269a44ca255de858a1af5504388c4a04b71bdde1d&quot;
  deposit_data_root: &quot;0x69c7a9d2550955ae43c7a6790737017c37d9d2c353af01686d4736259ab45a77&quot;
  eth1_data:
    deposit_root: &quot;0xcff79088a43be898c147090a135293d6ac0b9a05370a36aa6403897e449b6d74&quot;
    deposit_count: &quot;457&quot;
    block_hash: &quot;0x66e0fcb1ac380fb70e9a3bf4771276b0a1bd23bf7cf6eb37fb3b919c7da07e98&quot;
  block_height: 458
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x53c1bf574da722d22635feb98ceae3cfa185fec248396946d571681fb60e9005&quot;
      - &quot;0x69c7a9d2550955ae43c7a6790737017c37d9d2c353af01686d4736259ab45a77&quot;
    deposit_root: &quot;0xcff79088a43be898c147090a135293d6ac0b9a05370a36aa6403897e449b6d74&quot;
    deposit_count: 457
    execution_block_hash: &quot;0x66e0fcb1ac380fb70e9a3bf4771276b0a1bd23bf7cf6eb37fb3b919c7da07e98&quot;
    execution_block_height: 458
- deposit_data:
    pubkey: &quot;0xaea50380eaca9b09e5baec21e5f522c964b0ac8d4aebb8e1a1a196a01fb5c2c87f524be56a57d2f80274d1a0d2ed7fa6&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x954643a0a8494712b0e1c45e089b17e84bfe57e4d901841e2e2381b303b724caf34741564ba450c8ef8469999f22a9a811c4b14c4599e2c3caa45f306264b7149402c643e4c82fafa3c966cd0bef954a214c06311ccf6a812b1ef43ea279a2b2&quot;
  deposit_data_root: &quot;0xb131ceaf7a69f35f76b5c8e6ccd346ccb2f10cf14a173d12758dd4a9fed3c0d7&quot;
  eth1_data:
    deposit_root: &quot;0x1ef3716bf7e7a51f7fc622319f07a89a2ea1c2bd4a6149e5ea6e069e63a5dc66&quot;
    deposit_count: &quot;458&quot;
    block_hash: &quot;0xbca1858a0a0f800b2b1921341c915c917e67ba447b530834ddab39c1b4b5dd59&quot;
  block_height: 459
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x53c1bf574da722d22635feb98ceae3cfa185fec248396946d571681fb60e9005&quot;
      - &quot;0x2f22c52f2268d8873a91866c36b0c38a75a64c6598e974ce14cf6b0b783fcf8a&quot;
    deposit_root: &quot;0x1ef3716bf7e7a51f7fc622319f07a89a2ea1c2bd4a6149e5ea6e069e63a5dc66&quot;
    deposit_count: 458
    execution_block_hash: &quot;0xbca1858a0a0f800b2b1921341c915c917e67ba447b530834ddab39c1b4b5dd59&quot;
    execution_block_height: 459
- deposit_data:
    pubkey: &quot;0xb68a35785d29094de3457406b8f974581ab72e2aea2c3ec1ffd21b0326297f09a838b669e3e1409e127a3bc3eaa8cb72&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xac9f75a49603af9cd321f521460eda36c3a1dd7eb88bff394e7692b8d4dc7e7c33868025c7cab4b365693a8743d514d5029c238b47357486bb3b4cf31f87c9ac07327ec39858fc89b580dee5ddcdf7d089acfb238cec502403de5bc2487ddb6f&quot;
  deposit_data_root: &quot;0xda57dcc5780f0fe914a0f88d1db9b36324b9e13a0fc44ad777ebec7a8ac154a4&quot;
  eth1_data:
    deposit_root: &quot;0x6262414f9280a354022ae8b80692ab01589f0f022775dbc08e7cbaabe1feb343&quot;
    deposit_count: &quot;459&quot;
    block_hash: &quot;0x88421a8eac3dd6665ad9040506148cbb90c37ff8278e3286d36eb41939177435&quot;
  block_height: 460
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x53c1bf574da722d22635feb98ceae3cfa185fec248396946d571681fb60e9005&quot;
      - &quot;0x2f22c52f2268d8873a91866c36b0c38a75a64c6598e974ce14cf6b0b783fcf8a&quot;
      - &quot;0xda57dcc5780f0fe914a0f88d1db9b36324b9e13a0fc44ad777ebec7a8ac154a4&quot;
    deposit_root: &quot;0x6262414f9280a354022ae8b80692ab01589f0f022775dbc08e7cbaabe1feb343&quot;
    deposit_count: 459
    execution_block_hash: &quot;0x88421a8eac3dd6665ad9040506148cbb90c37ff8278e3286d36eb41939177435&quot;
    execution_block_height: 460
- deposit_data:
    pubkey: &quot;0xb90a59e63d66d20d5e9a3b45be51fa7963da5ee137a126740036f432c50eecaade78c4a5bc92fe1908a153b15ad92a25&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8397c642292c99d42f208b26b2dd82f1e8d214dbb6829b70cf5a55c710a37572fb77e02beafb4c2208e7c6a965529009021b0d55dbf63c6eda839187158f5cb2141f25464da3802e2f411ec7bf5671225b231d2a4a48ed90c72ec8bfbabe30d9&quot;
  deposit_data_root: &quot;0x51c105f98c9892d6d1cead0485fe9058e733fbff334a4442e409140899cf445f&quot;
  eth1_data:
    deposit_root: &quot;0x34fd2a662b2220a66fc9b966be349b6c80781bf702a8702957ebd775a35e2e6c&quot;
    deposit_count: &quot;460&quot;
    block_hash: &quot;0x07fd13866775681d13fc3a2f7fd2ec38c86341a724a12140ed79d6c95bf1ad8b&quot;
  block_height: 461
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x53c1bf574da722d22635feb98ceae3cfa185fec248396946d571681fb60e9005&quot;
      - &quot;0x689f0a0b6d57f49f4654c506592ef965bcdab3336c358f30213e2d5d3630415a&quot;
    deposit_root: &quot;0x34fd2a662b2220a66fc9b966be349b6c80781bf702a8702957ebd775a35e2e6c&quot;
    deposit_count: 460
    execution_block_hash: &quot;0x07fd13866775681d13fc3a2f7fd2ec38c86341a724a12140ed79d6c95bf1ad8b&quot;
    execution_block_height: 461
- deposit_data:
    pubkey: &quot;0x9826a9986a35754dfdc31e69bb8b073eb7293aaa747b0990da43c2c04bc001c78257ab3a1a91d3c7f2bb9c8395ed9424&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa569d9ac3ef0d59e22d7776348817afbbe1c4213c2d827dd2c75cb4cc7992fafd838e5661b98a8f77712a82eb3a6e798106b7d3ff6b1376de96bebef0a915e648d08fee8478c5e39e8085693ad0af6ab4e5dfb0f22136e9d2f1a7d1b1a6d6482&quot;
  deposit_data_root: &quot;0xb50cfbee3651658b71f15612069c1ade31ca2a26449985ef20b99f3ffbd78353&quot;
  eth1_data:
    deposit_root: &quot;0x76934fb0b2c000d79600b534433d9ae771971013b7e6ff1b5459ff86f9fe09c7&quot;
    deposit_count: &quot;461&quot;
    block_hash: &quot;0x9ae6b3c353ce3cb09bfe114d6b4f3a02e3119baff9cd693a7215a3036299c7ea&quot;
  block_height: 462
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x53c1bf574da722d22635feb98ceae3cfa185fec248396946d571681fb60e9005&quot;
      - &quot;0x689f0a0b6d57f49f4654c506592ef965bcdab3336c358f30213e2d5d3630415a&quot;
      - &quot;0xb50cfbee3651658b71f15612069c1ade31ca2a26449985ef20b99f3ffbd78353&quot;
    deposit_root: &quot;0x76934fb0b2c000d79600b534433d9ae771971013b7e6ff1b5459ff86f9fe09c7&quot;
    deposit_count: 461
    execution_block_hash: &quot;0x9ae6b3c353ce3cb09bfe114d6b4f3a02e3119baff9cd693a7215a3036299c7ea&quot;
    execution_block_height: 462
- deposit_data:
    pubkey: &quot;0x854de57710b835c0253eef8a20d2e6f0ef8d260eb4443bbd5c38de0acd38035f0c1ad5d09994744588a497f8eb3b747e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa818e6ca068133ba1cb41c57f6b6b16db4ff64bdbe67d8207206989d8efc0021fb002976c3cff587687741db6d1ab6a200730acfe51121f49792c11865efde86e8d7ae4750f047eb18d544fcbe0aa03b73a38210a914cc1eb82012cfc9e0bb22&quot;
  deposit_data_root: &quot;0x48c0a3d3ca1ae0f20cd20838fac325cdc0b92253a3431bb9033a2b4144afb08f&quot;
  eth1_data:
    deposit_root: &quot;0xe74c79921d452c89e27a9414c76a65286982c0951d4ee0eb486361fc8208e5e2&quot;
    deposit_count: &quot;462&quot;
    block_hash: &quot;0xa11e6044fdd05aa46ecf17d49edb46d91545f750db221a4edbab2663880d2cee&quot;
  block_height: 463
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x53c1bf574da722d22635feb98ceae3cfa185fec248396946d571681fb60e9005&quot;
      - &quot;0x689f0a0b6d57f49f4654c506592ef965bcdab3336c358f30213e2d5d3630415a&quot;
      - &quot;0xc47891c2dae75dac43cad9c632bfbed1549eab22922ad0829e49fb45e3bfaa98&quot;
    deposit_root: &quot;0xe74c79921d452c89e27a9414c76a65286982c0951d4ee0eb486361fc8208e5e2&quot;
    deposit_count: 462
    execution_block_hash: &quot;0xa11e6044fdd05aa46ecf17d49edb46d91545f750db221a4edbab2663880d2cee&quot;
    execution_block_height: 463
- deposit_data:
    pubkey: &quot;0xadc1109ded58e828f3c992b3d367b8e8d9d5cbe102fb171b4f4dfa66a181ab040f13d15a38b10e50c8c87432904b6e1c&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb8799635089cb0c7b9703daf090358b53459304538f784eea9802a284bed2adb69c3c2e3b244da77b7ec5b420fbe2a4e1220c59059d904847b4750f7c188c92cc826ecdf1c6650f789856dcb49c7fbf380c76702169dfecd0c7d076ffecdfa1b&quot;
  deposit_data_root: &quot;0x8e7112b4f311f4c3a3a295185ba65739fc5f0a7bc06e2a561fd9f5ec1e3c56dd&quot;
  eth1_data:
    deposit_root: &quot;0x8dfaa386c19f0aa3bb523cdf7edae9a99a54ba5af875225e8ef106d89a9a7583&quot;
    deposit_count: &quot;463&quot;
    block_hash: &quot;0x66f1fe4d2e95c883b0a7698c48ad71aaaed1206a9ae8cce0d46c99a2d1834076&quot;
  block_height: 464
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x53c1bf574da722d22635feb98ceae3cfa185fec248396946d571681fb60e9005&quot;
      - &quot;0x689f0a0b6d57f49f4654c506592ef965bcdab3336c358f30213e2d5d3630415a&quot;
      - &quot;0xc47891c2dae75dac43cad9c632bfbed1549eab22922ad0829e49fb45e3bfaa98&quot;
      - &quot;0x8e7112b4f311f4c3a3a295185ba65739fc5f0a7bc06e2a561fd9f5ec1e3c56dd&quot;
    deposit_root: &quot;0x8dfaa386c19f0aa3bb523cdf7edae9a99a54ba5af875225e8ef106d89a9a7583&quot;
    deposit_count: 463
    execution_block_hash: &quot;0x66f1fe4d2e95c883b0a7698c48ad71aaaed1206a9ae8cce0d46c99a2d1834076&quot;
    execution_block_height: 464
- deposit_data:
    pubkey: &quot;0x87068fec51465d586d65ff531b32fe20d2e02535c08883721654338878b1aee8479fab486a19de804da1f301443f69d0&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8e8b77fbdab9f6a210e3d8dac73df968fec07362e42dbddfc5533b103715438897012d2d49b64ecb920ad8eee641cffe06706a2af60897c44a21bc6c6581e878235070c197d57f9f8882bccc88feeafb1d0203569be51063663f82027a3da08c&quot;
  deposit_data_root: &quot;0x14cab7fbbcb0c52a1c60cb65d05f7be70e33e4d4e6367ddc931482e6d839e76d&quot;
  eth1_data:
    deposit_root: &quot;0x42a835e727b7aaf06d891a55d8b7a067512cc87046e043dada051674d3d61438&quot;
    deposit_count: &quot;464&quot;
    block_hash: &quot;0xbdb7f8ea7927498e58540bc2b1d70b082c025dbe0d41fea325e7e65427d396dd&quot;
  block_height: 465
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x539c3abb99dc0d3652e3032b3abdd4f5d531d3783ac3c97c10e77108952d53fc&quot;
    deposit_root: &quot;0x42a835e727b7aaf06d891a55d8b7a067512cc87046e043dada051674d3d61438&quot;
    deposit_count: 464
    execution_block_hash: &quot;0xbdb7f8ea7927498e58540bc2b1d70b082c025dbe0d41fea325e7e65427d396dd&quot;
    execution_block_height: 465
- deposit_data:
    pubkey: &quot;0x95322a22f4abe8eb0a0f4cf8876c31abeb3684ed984f6b595b9f3b9527b60c5f730d03d4960f5094210a3f6383691348&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x921dc1028ad56faf90a0732ed439ca36f5f4fa643bcad13b95309a6afcab2ef45f535601289b18d3b68244a23b598e6a014d3b75ec07afa43a2718b9c1a670d8587d3fd8e6254204f6d2c3937ca09cd0c80de526b8bbe2150f4d3e05c218a747&quot;
  deposit_data_root: &quot;0xea4b7f1637589d380ebdd0b75914919c07ef2936943a96865acd55028cd7c065&quot;
  eth1_data:
    deposit_root: &quot;0xf289bbf81113da5f485fc53db8a774b6817e4648e8c1f5e7136c68ffe1688fb6&quot;
    deposit_count: &quot;465&quot;
    block_hash: &quot;0xf02d6940bc1291413166041a1c800d2d86203d07151c71ed39604d78e50800a1&quot;
  block_height: 466
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x539c3abb99dc0d3652e3032b3abdd4f5d531d3783ac3c97c10e77108952d53fc&quot;
      - &quot;0xea4b7f1637589d380ebdd0b75914919c07ef2936943a96865acd55028cd7c065&quot;
    deposit_root: &quot;0xf289bbf81113da5f485fc53db8a774b6817e4648e8c1f5e7136c68ffe1688fb6&quot;
    deposit_count: 465
    execution_block_hash: &quot;0xf02d6940bc1291413166041a1c800d2d86203d07151c71ed39604d78e50800a1&quot;
    execution_block_height: 466
- deposit_data:
    pubkey: &quot;0xb43fcdad30bb652a82ce6033d6cdd6b004f58eb102d54f4de5a59c17c774c66637e7ed8078b19afe55ed34ac2b969fc7&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x83444116edd61f30eb0ad94e86f36834a2b99db16ff37a19139349456b8afd64b7dd6c92e7fa8f6fe9bf13de87c39fa80d3dafdcf00f9285e2610a63da505c2f91bb01d55cb2f75f0aebdfa37ed10d8a8102165adf87d03b421e604231ed200d&quot;
  deposit_data_root: &quot;0xba13491453796254686b89b3a1d2589d271db8a73cf2420df2f1d7a232c69238&quot;
  eth1_data:
    deposit_root: &quot;0x566f2e0bf068a861f4bcbe154f442dd6ae9097bbf4270c7dbfb3221ae6957fde&quot;
    deposit_count: &quot;466&quot;
    block_hash: &quot;0x29affc9ff69377a80f0888246a6bc7c98e7b914e4d6ce935f33e017fbb119519&quot;
  block_height: 467
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x539c3abb99dc0d3652e3032b3abdd4f5d531d3783ac3c97c10e77108952d53fc&quot;
      - &quot;0x4f223a1f874097defdc9227f99dd60128d5695ed143768671db7ea87ff207409&quot;
    deposit_root: &quot;0x566f2e0bf068a861f4bcbe154f442dd6ae9097bbf4270c7dbfb3221ae6957fde&quot;
    deposit_count: 466
    execution_block_hash: &quot;0x29affc9ff69377a80f0888246a6bc7c98e7b914e4d6ce935f33e017fbb119519&quot;
    execution_block_height: 467
- deposit_data:
    pubkey: &quot;0x801125a4149f3b2ae29f7745ed91492ebd9de91da253f0a267f864302044310c1f9decede6b1b5a9e1719c36841aff5d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xaa4fd707ca74abc5be01c340ddad32ac490f164119e323928247e7ce5e846f31c7642270acd7cb26b220e1f957a2e1230e4073d742bfc38dc538ed5089e89d1765c8c459f2d0997357d548e797267db7066f91541415aa769fb3eaf964465861&quot;
  deposit_data_root: &quot;0x344061e3131a0fd07c4f8c46d4e68950c9e0226907b418e7485009a1efca42e3&quot;
  eth1_data:
    deposit_root: &quot;0xf92d82cd5cfaaba51447264da8eed8cd65da770562dcedd00ec05ff6da207892&quot;
    deposit_count: &quot;467&quot;
    block_hash: &quot;0xee7806737892c8ba330f1d4545aacbee5f0a4b25c44d596f5eecf419ca936039&quot;
  block_height: 468
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x539c3abb99dc0d3652e3032b3abdd4f5d531d3783ac3c97c10e77108952d53fc&quot;
      - &quot;0x4f223a1f874097defdc9227f99dd60128d5695ed143768671db7ea87ff207409&quot;
      - &quot;0x344061e3131a0fd07c4f8c46d4e68950c9e0226907b418e7485009a1efca42e3&quot;
    deposit_root: &quot;0xf92d82cd5cfaaba51447264da8eed8cd65da770562dcedd00ec05ff6da207892&quot;
    deposit_count: 467
    execution_block_hash: &quot;0xee7806737892c8ba330f1d4545aacbee5f0a4b25c44d596f5eecf419ca936039&quot;
    execution_block_height: 468
- deposit_data:
    pubkey: &quot;0xa7852f47c6391e4ea0854d59b4a69ac72be49f7f798c19146a787dcc25a48a183ac3902001d0225f242ced6cc09aa378&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa0a90f6758d780721ada83e733fbda997001304b093517bb175d9b50f903d366f16ca33f47d716197317f81326688aac0c99be675058e687c2391016f28451c82484faa49311ca5b5af7b73e68003ec0b6f10a03a5fb0d735e32a6319bcaee81&quot;
  deposit_data_root: &quot;0x9da6faf501a235e8957b782d919b8b63d469f9cf252b5786fd8ee778e291a127&quot;
  eth1_data:
    deposit_root: &quot;0xd7166c06e1e85afaa7ae992a6aba05a63e6017f6be9acc4bd43344807cbda528&quot;
    deposit_count: &quot;468&quot;
    block_hash: &quot;0x29e18f49fc40f155ff1bd424b6af69c1bb1146f5e5060fc5c9c6badabb52ec28&quot;
  block_height: 469
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x539c3abb99dc0d3652e3032b3abdd4f5d531d3783ac3c97c10e77108952d53fc&quot;
      - &quot;0xb6a8aae06157a95d5852c69b8815034853daddd3aea1c41b6082f625f64a6688&quot;
    deposit_root: &quot;0xd7166c06e1e85afaa7ae992a6aba05a63e6017f6be9acc4bd43344807cbda528&quot;
    deposit_count: 468
    execution_block_hash: &quot;0x29e18f49fc40f155ff1bd424b6af69c1bb1146f5e5060fc5c9c6badabb52ec28&quot;
    execution_block_height: 469
- deposit_data:
    pubkey: &quot;0xb0c1eb313f3894f5f19ddd7cb3472f015ccf51c24bf4316fae3e8502d3b65132a8d2ac58f7d17eec0a644ef31afda14d&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xaf2982541a4ee7cd7a39ce1f4dd094b64bbdf93763ae134a09c4abdb5dad4830b772b610dd54d8e7fb782de6f6e524fa0bd3dae3737afebb2a10478ba965d1619276a04a3782d3976957c60fa92cf552876ff66db974c8c4fd820a738b980040&quot;
  deposit_data_root: &quot;0x6bd3f89d5210692fea089c2d827b529bd2c9127d4dd27b152bd78da7bd466f29&quot;
  eth1_data:
    deposit_root: &quot;0x17128858a7687c2474b0cb4f79f498a32c46a922afd92d97723efcbc332b93e2&quot;
    deposit_count: &quot;469&quot;
    block_hash: &quot;0xc50e70d8f92b0410c880a034aca2ebff5f6b2bd917673b1b7cb095be4b7c033c&quot;
  block_height: 470
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x539c3abb99dc0d3652e3032b3abdd4f5d531d3783ac3c97c10e77108952d53fc&quot;
      - &quot;0xb6a8aae06157a95d5852c69b8815034853daddd3aea1c41b6082f625f64a6688&quot;
      - &quot;0x6bd3f89d5210692fea089c2d827b529bd2c9127d4dd27b152bd78da7bd466f29&quot;
    deposit_root: &quot;0x17128858a7687c2474b0cb4f79f498a32c46a922afd92d97723efcbc332b93e2&quot;
    deposit_count: 469
    execution_block_hash: &quot;0xc50e70d8f92b0410c880a034aca2ebff5f6b2bd917673b1b7cb095be4b7c033c&quot;
    execution_block_height: 470
- deposit_data:
    pubkey: &quot;0x8c6ccdc900d78ef20d5b22ad540e73864c858baf068349dafc397cd31c571708ec6ee6afef9e5711a587e3e97f1a50a0&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8d02c24dbaa0a13109feddc00dba3ecdbccf6f9f89ea859ce8293f131679c24786317f96ec390c847084f7e8ae5f56060b45fda9cbdfd4219e2806f0c2e340947fcb2860ab279860360e936b31e27fad05a4ffbbff514432e3f15f9ac7fbe5b7&quot;
  deposit_data_root: &quot;0x63bc1e79593a6bc90ad3e76e5cab85bbf3ebc0f95993633ee2070133bb805ee8&quot;
  eth1_data:
    deposit_root: &quot;0x0114581f1558b58a8fda8d0fd4d9c8d81e3a0a44e1ee0da77b688940dfcae870&quot;
    deposit_count: &quot;470&quot;
    block_hash: &quot;0xc72dde0d8a48244290c055cdcac8a82a10a5c83768430f4216a7f0db007f65bc&quot;
  block_height: 471
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x539c3abb99dc0d3652e3032b3abdd4f5d531d3783ac3c97c10e77108952d53fc&quot;
      - &quot;0xb6a8aae06157a95d5852c69b8815034853daddd3aea1c41b6082f625f64a6688&quot;
      - &quot;0x1b129cc8ae0d0bcf87188bb66ce17acc25350f28de10249e179c868a9f7a4a79&quot;
    deposit_root: &quot;0x0114581f1558b58a8fda8d0fd4d9c8d81e3a0a44e1ee0da77b688940dfcae870&quot;
    deposit_count: 470
    execution_block_hash: &quot;0xc72dde0d8a48244290c055cdcac8a82a10a5c83768430f4216a7f0db007f65bc&quot;
    execution_block_height: 471
- deposit_data:
    pubkey: &quot;0xa8aa5faaa4bbda5b5e7d610746f27c09bdee3a3f057550bca600ebe1c83749525a135829669a0162c3339ea40dc5525a&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x94fb954aed2ccc71dbeac75d03bab4f59bc09a2468b25a12ccda4d50efe9bf2ec3e4188ecbe50c1bee58ee2d90acb83b116085775618887034be7c1487e52e76d2aaa2fca8fc37ebbbf552d4a5996d086fc653b447337a89bcc0ff4e678b2e94&quot;
  deposit_data_root: &quot;0xc9ed8e05a9be23ad58521dfeda162c75bff62477ac3aea3f373e1c12c5fe5ce7&quot;
  eth1_data:
    deposit_root: &quot;0xc05d8b31462806679096a4b5e89c1f82e0c237f65cb53f9dbd7086517aef4321&quot;
    deposit_count: &quot;471&quot;
    block_hash: &quot;0x9923a0a46a2f622ff2ada864cb8ce46be4ad5ac7fd386ee8c1dc2df41279395a&quot;
  block_height: 472
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x539c3abb99dc0d3652e3032b3abdd4f5d531d3783ac3c97c10e77108952d53fc&quot;
      - &quot;0xb6a8aae06157a95d5852c69b8815034853daddd3aea1c41b6082f625f64a6688&quot;
      - &quot;0x1b129cc8ae0d0bcf87188bb66ce17acc25350f28de10249e179c868a9f7a4a79&quot;
      - &quot;0xc9ed8e05a9be23ad58521dfeda162c75bff62477ac3aea3f373e1c12c5fe5ce7&quot;
    deposit_root: &quot;0xc05d8b31462806679096a4b5e89c1f82e0c237f65cb53f9dbd7086517aef4321&quot;
    deposit_count: 471
    execution_block_hash: &quot;0x9923a0a46a2f622ff2ada864cb8ce46be4ad5ac7fd386ee8c1dc2df41279395a&quot;
    execution_block_height: 472
- deposit_data:
    pubkey: &quot;0xa7c107c72118446d1dc3c5c1c42f95ca2471dddd61c1461dd8ce028a1dae7656c98c3eca5f6dbeae8f9594e3e652a4d3&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8cec6a4e726448a24c2f9f4e1f82366bd723596c8d4a62be7a2c8a0e0a513518b9cd9cd00a13000a1d03a5bde2336c920752aa634d77143f890ab2718ecaaa5527fe7ef3b2489ff7548af90eefb857c03b9bf52dc9089989387c8be9141dea65&quot;
  deposit_data_root: &quot;0xd2602c538061473ff8ada72bccc5cb574ea9811b109867a442ec621a78184249&quot;
  eth1_data:
    deposit_root: &quot;0x71d80a6c13aaf2af9b142d5f75859f7f86cf33492301a62d42134810c1a43862&quot;
    deposit_count: &quot;472&quot;
    block_hash: &quot;0xd4b509039b3e7f5664ed77eed00addbc90392021394ae1c431c10f9236bf539c&quot;
  block_height: 473
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x539c3abb99dc0d3652e3032b3abdd4f5d531d3783ac3c97c10e77108952d53fc&quot;
      - &quot;0x399784c504476260102e50dbb4284f4f83d3acc78686434e89711b29ffb00b2b&quot;
    deposit_root: &quot;0x71d80a6c13aaf2af9b142d5f75859f7f86cf33492301a62d42134810c1a43862&quot;
    deposit_count: 472
    execution_block_hash: &quot;0xd4b509039b3e7f5664ed77eed00addbc90392021394ae1c431c10f9236bf539c&quot;
    execution_block_height: 473
- deposit_data:
    pubkey: &quot;0x899eaf183acd5beee0899a58c8ee5fff1dc76df143028d9871d231e8a3999d92098538d070fd1c9db5d9db60f23dfd4a&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x88a116fece26c6e4d209321a5c58a8e09e01fe165703b042cb577060a8bc3255a281bc960e65ce253e66d15560e38efc10fadf7f49224583d4d25b34258d46ffd6402356684954e33849e968ce77d484307dbcd7d02a6eaf75185c7512231add&quot;
  deposit_data_root: &quot;0x57f93038b3cac9f76cb61db2309f1a5853dee6b9f4b3e713c34c4cd2a18631dd&quot;
  eth1_data:
    deposit_root: &quot;0xdc3672b4162de2f668f5865ee0f8e00e755777968de8c44b3320c92592c8207a&quot;
    deposit_count: &quot;473&quot;
    block_hash: &quot;0x947b126441051344edc68b986f9b345352a4f0420b44dd06a6359204d5d0ac4f&quot;
  block_height: 474
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x539c3abb99dc0d3652e3032b3abdd4f5d531d3783ac3c97c10e77108952d53fc&quot;
      - &quot;0x399784c504476260102e50dbb4284f4f83d3acc78686434e89711b29ffb00b2b&quot;
      - &quot;0x57f93038b3cac9f76cb61db2309f1a5853dee6b9f4b3e713c34c4cd2a18631dd&quot;
    deposit_root: &quot;0xdc3672b4162de2f668f5865ee0f8e00e755777968de8c44b3320c92592c8207a&quot;
    deposit_count: 473
    execution_block_hash: &quot;0x947b126441051344edc68b986f9b345352a4f0420b44dd06a6359204d5d0ac4f&quot;
    execution_block_height: 474
- deposit_data:
    pubkey: &quot;0x8771579633474fb50075b4c801124f63c4a786e7a618bc50c00122f4fe8c18d1edc123ce9be8436b9bc8159c5d2061ec&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb208ae48bba24e07a4d4dd1465cd92f135487a71353e79657250e66e18e31c08477d6b3f94cd8836b18ac1d6d154fbb50bfc5fb9e261c5117b30a96dbb3ae0dbcfd912b465b1b0c694d0030c97ed3b40437c0559fe95bd2cfad07706345e302c&quot;
  deposit_data_root: &quot;0x70e6082f9f4c9f7cb7c0d946caac7dd325787fe08c2a6fde05ddc7ee71bc1978&quot;
  eth1_data:
    deposit_root: &quot;0x1e2891528f3695be75c16e6f8e948737a6be58ec77667c41f70309fe2d0a0c24&quot;
    deposit_count: &quot;474&quot;
    block_hash: &quot;0x05b249730f2706e2825a6c3beb0582bc9430679dae5fa24c864a246efcb97eee&quot;
  block_height: 475
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x539c3abb99dc0d3652e3032b3abdd4f5d531d3783ac3c97c10e77108952d53fc&quot;
      - &quot;0x399784c504476260102e50dbb4284f4f83d3acc78686434e89711b29ffb00b2b&quot;
      - &quot;0xff8e34dd64f1d9e20b42622f7dd59ce1f29ae93f52847609c7fbedd88e764275&quot;
    deposit_root: &quot;0x1e2891528f3695be75c16e6f8e948737a6be58ec77667c41f70309fe2d0a0c24&quot;
    deposit_count: 474
    execution_block_hash: &quot;0x05b249730f2706e2825a6c3beb0582bc9430679dae5fa24c864a246efcb97eee&quot;
    execution_block_height: 475
- deposit_data:
    pubkey: &quot;0x8416902c51bdb3933ff4e87558121d3fbab9f116f9a5b0ae9cc30c4d145c39dc988f5c0b754da3daeec71fa68144f9b3&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9402807f43da37ca29cede163b91633fde7614843314b423db475c86533e0006cf6b1e80a93dc04aedb919afdd9103b617e136915062a66211720207f6b1300da29a44c751251ed097a204b44780275514318e4cf73ad1971b10eebdb3a08aeb&quot;
  deposit_data_root: &quot;0x3ecd4d4c9a0d1810d3599f12fa62a3085f96dec792ed006f37bc2e2a20d5e90c&quot;
  eth1_data:
    deposit_root: &quot;0x04f3ebd098dd6485ad2ad107913118691ce85da75625af5e6fb730e536d298f9&quot;
    deposit_count: &quot;475&quot;
    block_hash: &quot;0xb63ee91d3c3edb9a298101f2c5c15a0dcc5fe27f0b564a620e944e7619845b1a&quot;
  block_height: 476
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x539c3abb99dc0d3652e3032b3abdd4f5d531d3783ac3c97c10e77108952d53fc&quot;
      - &quot;0x399784c504476260102e50dbb4284f4f83d3acc78686434e89711b29ffb00b2b&quot;
      - &quot;0xff8e34dd64f1d9e20b42622f7dd59ce1f29ae93f52847609c7fbedd88e764275&quot;
      - &quot;0x3ecd4d4c9a0d1810d3599f12fa62a3085f96dec792ed006f37bc2e2a20d5e90c&quot;
    deposit_root: &quot;0x04f3ebd098dd6485ad2ad107913118691ce85da75625af5e6fb730e536d298f9&quot;
    deposit_count: 475
    execution_block_hash: &quot;0xb63ee91d3c3edb9a298101f2c5c15a0dcc5fe27f0b564a620e944e7619845b1a&quot;
    execution_block_height: 476
- deposit_data:
    pubkey: &quot;0x83f8eb02f40f6369cb8836d521390b06ba91c72618056cd103ede2b6204069ff94c7364c2f24ca1db500ef627be3f1b2&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8d236cee7ae8ac4a4b3bc5d71e8f1ef916dac52c731bd0992c3fab191cf2aba1e56bd69b708278715248e63d8f8b8724174c05b8ec955faf684b353c7c29c0e2bbc8b045c62c2554c3d5679e932e7ea6415999140f48860c3977c7149d5565b5&quot;
  deposit_data_root: &quot;0xc157aa44092165b3935d971c9835801dc66b24f54c8d4c387afcc14e2b469204&quot;
  eth1_data:
    deposit_root: &quot;0xe7fcb3f12d9fd24d0ebd089fad35d0a4edd4dca4fad112f72a5a42bf313e54fb&quot;
    deposit_count: &quot;476&quot;
    block_hash: &quot;0x546c6d2e65b628e3015ee8c2d0494a9a20cc098ce586d738f6de069136472497&quot;
  block_height: 477
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x539c3abb99dc0d3652e3032b3abdd4f5d531d3783ac3c97c10e77108952d53fc&quot;
      - &quot;0x399784c504476260102e50dbb4284f4f83d3acc78686434e89711b29ffb00b2b&quot;
      - &quot;0xb99e45a812c5eaffd1f6ccb925e913d782b51cd8c371b11727ad48cc0de95d33&quot;
    deposit_root: &quot;0xe7fcb3f12d9fd24d0ebd089fad35d0a4edd4dca4fad112f72a5a42bf313e54fb&quot;
    deposit_count: 476
    execution_block_hash: &quot;0x546c6d2e65b628e3015ee8c2d0494a9a20cc098ce586d738f6de069136472497&quot;
    execution_block_height: 477
- deposit_data:
    pubkey: &quot;0xb08c6eef8be13656c3963726dc3be95a5087e363fd5e72301322ea73a8840520d51f142cd9d94d0da3b7a6f22d111fd4&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x974be67dd9641425535b8630a502c72298b86a579adb8f22d77474d3679ec0d3771190515ffea3cea288c5a401f275aa1951f6a3f226f9d0afd58a12520a51479a4ff168d782162ac242169580463e1e6968609fe0e911fdfe39192c816a3a03&quot;
  deposit_data_root: &quot;0xbafe7c7e5e984655b91e5c85b2a7064664c21483721e8d534bc04ce8c1849a1f&quot;
  eth1_data:
    deposit_root: &quot;0xf41c3d61184e6a446360ecb29eada4910b0694a5f26a281fcc7c07abb81f2f04&quot;
    deposit_count: &quot;477&quot;
    block_hash: &quot;0xbdb7e08ed1e7f61ee28337d7842866c1b545937e7c247d895e8ba87ac1b87cc2&quot;
  block_height: 478
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x539c3abb99dc0d3652e3032b3abdd4f5d531d3783ac3c97c10e77108952d53fc&quot;
      - &quot;0x399784c504476260102e50dbb4284f4f83d3acc78686434e89711b29ffb00b2b&quot;
      - &quot;0xb99e45a812c5eaffd1f6ccb925e913d782b51cd8c371b11727ad48cc0de95d33&quot;
      - &quot;0xbafe7c7e5e984655b91e5c85b2a7064664c21483721e8d534bc04ce8c1849a1f&quot;
    deposit_root: &quot;0xf41c3d61184e6a446360ecb29eada4910b0694a5f26a281fcc7c07abb81f2f04&quot;
    deposit_count: 477
    execution_block_hash: &quot;0xbdb7e08ed1e7f61ee28337d7842866c1b545937e7c247d895e8ba87ac1b87cc2&quot;
    execution_block_height: 478
- deposit_data:
    pubkey: &quot;0x8374c6a0d41b2da67f26a62120128838ab64f3928769a4280d0650ff18d6262b584e8f68a915bf8e4d1f6e18d72a6ecd&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb2d63f5fd222d3c4db2c0f7bf4875d7a98cbd9511a43cc448df75d682984ed16035d3a9ea512c8da123d78400a29751910aeb767cf9361e2af7d50f4680796c3fc7a499028508c1de8093f6c4a9faa2d2e8737e39e90efc7b7f6304c79e471a9&quot;
  deposit_data_root: &quot;0x646da1db4ebfa44f98a74e708b6834ef0b3547d3ed62f4aa5ea28922b9ceb10f&quot;
  eth1_data:
    deposit_root: &quot;0xbbae20cfeb909f6a6c3efb0bdbf43a91e0111ac12305726d7c6ff78f0337edeb&quot;
    deposit_count: &quot;478&quot;
    block_hash: &quot;0xdad4caa2c941c49d2f6f9f8dba86a411d4cad65a2a89c6a12d017f08ba5bd381&quot;
  block_height: 479
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x539c3abb99dc0d3652e3032b3abdd4f5d531d3783ac3c97c10e77108952d53fc&quot;
      - &quot;0x399784c504476260102e50dbb4284f4f83d3acc78686434e89711b29ffb00b2b&quot;
      - &quot;0xb99e45a812c5eaffd1f6ccb925e913d782b51cd8c371b11727ad48cc0de95d33&quot;
      - &quot;0xe4c5f8b27ed915c009a548dee4da3ba212b3c42979ac7fa6c80abfe02d1172dd&quot;
    deposit_root: &quot;0xbbae20cfeb909f6a6c3efb0bdbf43a91e0111ac12305726d7c6ff78f0337edeb&quot;
    deposit_count: 478
    execution_block_hash: &quot;0xdad4caa2c941c49d2f6f9f8dba86a411d4cad65a2a89c6a12d017f08ba5bd381&quot;
    execution_block_height: 479
- deposit_data:
    pubkey: &quot;0xb98aeef39fb7eecc46e6cff2632a543757a8bd80bebe409b5d0eafe2922583040749cee9f130cf12eebf85c1dfc0adb4&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x85fb8f084baed303cafc16887d1fd22b1ae16cf9a6978a9bdbea426975b183896a1ea8731b3ad9a61e0211519123cda50cbf3814f821938b9365ab4058228162aa1448881c64f410e15f09de147be4076ab418319748f97c09a57e18f3117370&quot;
  deposit_data_root: &quot;0xa196eee94becd475763319784c5f9a7ba0854e82893a0d9cf21d4952e08dddab&quot;
  eth1_data:
    deposit_root: &quot;0xb491c8ebe5be3cf6e59268e03ebc32a74e64efce2c805e1b328d3d2d8034af48&quot;
    deposit_count: &quot;479&quot;
    block_hash: &quot;0x56ca5f2c24ea7f40984bc5b6c97b289b23e33c6199d917b0dff9fa2e12607b60&quot;
  block_height: 480
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x539c3abb99dc0d3652e3032b3abdd4f5d531d3783ac3c97c10e77108952d53fc&quot;
      - &quot;0x399784c504476260102e50dbb4284f4f83d3acc78686434e89711b29ffb00b2b&quot;
      - &quot;0xb99e45a812c5eaffd1f6ccb925e913d782b51cd8c371b11727ad48cc0de95d33&quot;
      - &quot;0xe4c5f8b27ed915c009a548dee4da3ba212b3c42979ac7fa6c80abfe02d1172dd&quot;
      - &quot;0xa196eee94becd475763319784c5f9a7ba0854e82893a0d9cf21d4952e08dddab&quot;
    deposit_root: &quot;0xb491c8ebe5be3cf6e59268e03ebc32a74e64efce2c805e1b328d3d2d8034af48&quot;
    deposit_count: 479
    execution_block_hash: &quot;0x56ca5f2c24ea7f40984bc5b6c97b289b23e33c6199d917b0dff9fa2e12607b60&quot;
    execution_block_height: 480
- deposit_data:
    pubkey: &quot;0x8f9e00f60b9b830e72b7d0b45a3dab2cda1f678880db3b5dc5107e07850dc5146afe8b0999102d4a8bca5cbc27cd8a2c&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x967c3931f641a1b00bf1d2f1f05b0d39470d3a18009ac4069f5b69f8c3d90129c10d5b0cf81fde69ae27470a47834d3a0946c9d6edbfbb3386910d3e881a34dd9b58ee1c51b34bf3c60920c52d449adcd850fe9a3e662e449cf50e02ef80eeb0&quot;
  deposit_data_root: &quot;0x1d584d8969a792467db268a84b71823f5421782407a24814519c5480593bdf72&quot;
  eth1_data:
    deposit_root: &quot;0x134da8281281e224a0ffb96b845d7792e22fcedd065ef136210928ec2804fc8b&quot;
    deposit_count: &quot;480&quot;
    block_hash: &quot;0x0c9865641090c264e1d7cbc1b65b0faf1005121540dc51869caba029aec61f22&quot;
  block_height: 481
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
    deposit_root: &quot;0x134da8281281e224a0ffb96b845d7792e22fcedd065ef136210928ec2804fc8b&quot;
    deposit_count: 480
    execution_block_hash: &quot;0x0c9865641090c264e1d7cbc1b65b0faf1005121540dc51869caba029aec61f22&quot;
    execution_block_height: 481
- deposit_data:
    pubkey: &quot;0xb42800735102f10b3e09c11e9113e0f4955bd19d0c5174f587d446de44230b10c3e8b439fbfc2e47f9e82ac2ade917b3&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa26895838394e4ead46ee443e6e76d42af792263bdf42113c206e99cde1d5ec5784f2a072691e1bfa9e29664741c3944009fdad153287feb4c172dde4ac6b63825c4211f2c09c0ca619f8c83b2c82a618aadfc27058df67685c437033cb23e1b&quot;
  deposit_data_root: &quot;0xc2a1be8de10512de15ce813468cadd14fec5f4dcff841434ef8ac94b0d4a1e8c&quot;
  eth1_data:
    deposit_root: &quot;0xd45d33b559eb5e75ad5e92d049659ab27a2c036a7aa315ec40fbcf807a8b78a2&quot;
    deposit_count: &quot;481&quot;
    block_hash: &quot;0x8c9122b92253122ed84adea540862612634d94e7c00df5df311278d785176f1f&quot;
  block_height: 482
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0xc2a1be8de10512de15ce813468cadd14fec5f4dcff841434ef8ac94b0d4a1e8c&quot;
    deposit_root: &quot;0xd45d33b559eb5e75ad5e92d049659ab27a2c036a7aa315ec40fbcf807a8b78a2&quot;
    deposit_count: 481
    execution_block_hash: &quot;0x8c9122b92253122ed84adea540862612634d94e7c00df5df311278d785176f1f&quot;
    execution_block_height: 482
- deposit_data:
    pubkey: &quot;0x877968c73d43465feea583c7bde8270773fbcdcf9d1e3e4fe492a208e788bb56b329174b0d2539d96877e9d6f5bf1b41&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x83a31f50234740124160bb83287570c689c12df4415aa7d784fee273425568f566481089d6b910c6477cd982601d9b381333fa40c666da37750771f365a4998d6f2e1c5eb8412df44a7d4038b5528b3a624cc0af754e79e6e310e8669cef79f9&quot;
  deposit_data_root: &quot;0x5796c508baf67aa0316bd134dfd20381d7ccaa37735914bf83f122dd762e5ca2&quot;
  eth1_data:
    deposit_root: &quot;0x9d0ac2b2a873b08b17e722eb0893f30e4518ad523ee623d0567aa82dabc6dd32&quot;
    deposit_count: &quot;482&quot;
    block_hash: &quot;0xfde6c5dfbc17f3071be1020ace406b179a5e30640bc33c304b8e8264719aedd7&quot;
  block_height: 483
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0xdd4de29f488ddda22d81e4e7a3e890a1c2fa2f4602bf5612e8af70c852b459cc&quot;
    deposit_root: &quot;0x9d0ac2b2a873b08b17e722eb0893f30e4518ad523ee623d0567aa82dabc6dd32&quot;
    deposit_count: 482
    execution_block_hash: &quot;0xfde6c5dfbc17f3071be1020ace406b179a5e30640bc33c304b8e8264719aedd7&quot;
    execution_block_height: 483
- deposit_data:
    pubkey: &quot;0x915fdf1928be84527b07ceccbc4a278f1e9e010d6f716d8c3a4666bf649411744355ef25b22276c2ab51b3af29c67119&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa3624f6211be2fcca00aeacae32fbc4101e787724ccd33d7293053b35ac8364784da5202037343024f4c94c86ce0a0ba171efaa129810f463e6f1337e59bea4aee8da537b313ccf72d207859d51bc2bec6c585e2598747b0b7e9f824ffb9f75b&quot;
  deposit_data_root: &quot;0x823ace95fa80327a404d8bc47116e2f39db4807f1547044d2f855459a6910f88&quot;
  eth1_data:
    deposit_root: &quot;0x34065c8a5baf250ed894b10d34c0b32b892d3457967219896e660caab4900265&quot;
    deposit_count: &quot;483&quot;
    block_hash: &quot;0x15dafdb4863cb94e4f40272996afd55a2772e370e89b8a75114fbd6706099b96&quot;
  block_height: 484
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0xdd4de29f488ddda22d81e4e7a3e890a1c2fa2f4602bf5612e8af70c852b459cc&quot;
      - &quot;0x823ace95fa80327a404d8bc47116e2f39db4807f1547044d2f855459a6910f88&quot;
    deposit_root: &quot;0x34065c8a5baf250ed894b10d34c0b32b892d3457967219896e660caab4900265&quot;
    deposit_count: 483
    execution_block_hash: &quot;0x15dafdb4863cb94e4f40272996afd55a2772e370e89b8a75114fbd6706099b96&quot;
    execution_block_height: 484
- deposit_data:
    pubkey: &quot;0xa99b23673a9c02a8da9e44fda564aaacabc12fac43b600884e06ff21ca2ece8fb8ca28c593d3966ec6ff427f8f497c05&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa2e5bfd6972dc7e1224cd3a6cb8eb2120f88cb43912bbeac84e359e10ad2c707c6318c1a9edda7f10e0ec8a7c41af9e613fe59d07f50a3f5027e63c11b391ed425d1c6ab7ceea8681f310d34fe9b2c658c81472c30f89a6034d9f79ed5979b53&quot;
  deposit_data_root: &quot;0x726ba60cf4b669785203993565bb3b21592a22fdd92ed204db8774bd95854cf9&quot;
  eth1_data:
    deposit_root: &quot;0x5a94789da4c0fa8f904274e1a6be5fe01019d467234f560932302dc4480c9207&quot;
    deposit_count: &quot;484&quot;
    block_hash: &quot;0x5978eac6de2f57ef776f150ff7337be8d7323810da27f674804c0e2c34322109&quot;
  block_height: 485
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0xf8fc1b0c4abcf5d5c5214689c52a6c792ebb882fa93e6cdd79998c5bd752a4e1&quot;
    deposit_root: &quot;0x5a94789da4c0fa8f904274e1a6be5fe01019d467234f560932302dc4480c9207&quot;
    deposit_count: 484
    execution_block_hash: &quot;0x5978eac6de2f57ef776f150ff7337be8d7323810da27f674804c0e2c34322109&quot;
    execution_block_height: 485
- deposit_data:
    pubkey: &quot;0x8759613fcfec38cf67297fc0b956382eb403f1b9126d1de3a26e0ee7142346d5457f09c7765d82d49f51726293b3cf7e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9924c8222eea8672b5aa21d38fca95cdaecadda51e373cd60100f1084e96140d333d2b01f60308bc8ca3ece43f1f915311b478bdefe9302188d636d3321ab684530f32cd8fa62b2ca575e0d3ac6b163a1934dc5e702af08253dd68c61f039e4a&quot;
  deposit_data_root: &quot;0x9613b659ffe2c9842167aa76d78262e1b72c7815b2751f4e9abc40bdc833a793&quot;
  eth1_data:
    deposit_root: &quot;0x301a60c707ce54ecd68bf6ab842130f5687966e5e3d6802c98a93105b8fffa6c&quot;
    deposit_count: &quot;485&quot;
    block_hash: &quot;0x33d4c030649788458fa0fc39cb615cac9e8614791d012c471b8f2c45314a398b&quot;
  block_height: 486
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0xf8fc1b0c4abcf5d5c5214689c52a6c792ebb882fa93e6cdd79998c5bd752a4e1&quot;
      - &quot;0x9613b659ffe2c9842167aa76d78262e1b72c7815b2751f4e9abc40bdc833a793&quot;
    deposit_root: &quot;0x301a60c707ce54ecd68bf6ab842130f5687966e5e3d6802c98a93105b8fffa6c&quot;
    deposit_count: 485
    execution_block_hash: &quot;0x33d4c030649788458fa0fc39cb615cac9e8614791d012c471b8f2c45314a398b&quot;
    execution_block_height: 486
- deposit_data:
    pubkey: &quot;0xa0ab65230a0c9a2e2ec267918366deaa93d80068b14e691de2dff126c604e755b72d0865099078870d6a3d47a2f56d14&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x943d8cdce9bb776c6713cc436e6fe6dd9d3d6f015d79153945078cb204f725192e2bb9c95505b813782265e00532110b10c9c6d08012ead8d3d3ac825dee975cf68caa47a6a83697fec5f753de0480a2c81ec6799f3b9fcee7b561bdf1cd27e6&quot;
  deposit_data_root: &quot;0x02b77bbb8e3d988f7daa40bb4179390f620f74e3f370ca75e40087e188cfb290&quot;
  eth1_data:
    deposit_root: &quot;0xda801f823b9de4864cb8fbac530776a3faf03d59b3a2dbc736799f843ff769c4&quot;
    deposit_count: &quot;486&quot;
    block_hash: &quot;0xf40b8bd6aca0d2df5d30673cb93799ab391c73417d9fcd66c0f36061950258d7&quot;
  block_height: 487
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0xf8fc1b0c4abcf5d5c5214689c52a6c792ebb882fa93e6cdd79998c5bd752a4e1&quot;
      - &quot;0xc40108b2f8489c8b37335014f19abcb82e4493969e2c8ec160e771f38a2ac79b&quot;
    deposit_root: &quot;0xda801f823b9de4864cb8fbac530776a3faf03d59b3a2dbc736799f843ff769c4&quot;
    deposit_count: 486
    execution_block_hash: &quot;0xf40b8bd6aca0d2df5d30673cb93799ab391c73417d9fcd66c0f36061950258d7&quot;
    execution_block_height: 487
- deposit_data:
    pubkey: &quot;0xa76186ca2743b7149ab7b5ab83c843d2d724ed85ef13a9e0e23a697ba048cea17acc68d9dda73d1f4ef97b9747e491ec&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xae8ce2cf4550895297567df5bbe471d3c58caec5fdfb1b526f4f686c0d908b32e3c88e0905344ce7d6c5ccf7d24ac2820da54a60ef97d5ad62f3de61b3f3b5252294b280efb80f24c50c2c9b1e0775b8e263170b373b876051e34e2e8bb14a0d&quot;
  deposit_data_root: &quot;0x992ec5657a0236c36cdeb5c71669678c8d28314815f3f267ee7791968f93ee5a&quot;
  eth1_data:
    deposit_root: &quot;0x178c069965cd1da6422db237305cb7d972195a3320cb2e863a3e36aa0d7a29e6&quot;
    deposit_count: &quot;487&quot;
    block_hash: &quot;0xfbc23345cce8edc158f0ca53ecd03de7f09bc65f648cce073dff8588a7195f0a&quot;
  block_height: 488
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0xf8fc1b0c4abcf5d5c5214689c52a6c792ebb882fa93e6cdd79998c5bd752a4e1&quot;
      - &quot;0xc40108b2f8489c8b37335014f19abcb82e4493969e2c8ec160e771f38a2ac79b&quot;
      - &quot;0x992ec5657a0236c36cdeb5c71669678c8d28314815f3f267ee7791968f93ee5a&quot;
    deposit_root: &quot;0x178c069965cd1da6422db237305cb7d972195a3320cb2e863a3e36aa0d7a29e6&quot;
    deposit_count: 487
    execution_block_hash: &quot;0xfbc23345cce8edc158f0ca53ecd03de7f09bc65f648cce073dff8588a7195f0a&quot;
    execution_block_height: 488
- deposit_data:
    pubkey: &quot;0xa70362ba9834a49f9f1ffdccf221fc2eb1f7a5cb584bded1d79c44e7e7890ab28d787004c5cc6a45d0e941ae27f1fe39&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9840593dfd806431b6892e7c3026ea49084c25df871ba5dc8c9a28d5b2f8c9bd5379233c68d4af650f4409c6c5d814dd1337059655b61267c924f0f271eb7284702eff667a9ee4ac2994fef2a8c601d32a3ab39406f31c55976b824e5569f2c0&quot;
  deposit_data_root: &quot;0xd5b2e76b1095e39dc9cd525aab3f0ad77b8e3210c9950cffd3247cca2c2d93d9&quot;
  eth1_data:
    deposit_root: &quot;0xacc5e8c62a70a8b48ea72c2b7dcf7e81d33b98d0e7299f96830c4c9a87bc5b12&quot;
    deposit_count: &quot;488&quot;
    block_hash: &quot;0xe7952006db942a66abc5319d9ce249354eada481eee6cdaf97fe348f928dbd3e&quot;
  block_height: 489
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0x3875f467344ea7151aaeaf8d2f3c78cf2dacd91f8a81b6ab8ca1e02df2fff953&quot;
    deposit_root: &quot;0xacc5e8c62a70a8b48ea72c2b7dcf7e81d33b98d0e7299f96830c4c9a87bc5b12&quot;
    deposit_count: 488
    execution_block_hash: &quot;0xe7952006db942a66abc5319d9ce249354eada481eee6cdaf97fe348f928dbd3e&quot;
    execution_block_height: 489
- deposit_data:
    pubkey: &quot;0xac66effd5784f677ff6fa5cb96d9cf14552d5888a8cd78ff54581b9fb35d3980c9b34cab41f565288812d77e3a44cceb&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb7d4c0669a88e0f84cfc9c5d53bf41d7703bed37597ccc66902f8d8271e7a595b2f170c13072e25c9630384a5a9070cc18a783226667704a6858fff0e77ff24dba0df19aa8ad71056fd18598dce161e4d547c3f29190803204de160e859af69d&quot;
  deposit_data_root: &quot;0x952612c181f310ef8c2b53d2022d08549f4d21d9d0d603d44b2bd3809e5b333b&quot;
  eth1_data:
    deposit_root: &quot;0xaee05275977d88ab3de85c1ef629864f36fa9ad8bc59500eb34e56ebfb724130&quot;
    deposit_count: &quot;489&quot;
    block_hash: &quot;0xbb1f6f7c565f47fa6e524ee0901d2b8b7a402895f4ccb7ee210723d757715869&quot;
  block_height: 490
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0x3875f467344ea7151aaeaf8d2f3c78cf2dacd91f8a81b6ab8ca1e02df2fff953&quot;
      - &quot;0x952612c181f310ef8c2b53d2022d08549f4d21d9d0d603d44b2bd3809e5b333b&quot;
    deposit_root: &quot;0xaee05275977d88ab3de85c1ef629864f36fa9ad8bc59500eb34e56ebfb724130&quot;
    deposit_count: 489
    execution_block_hash: &quot;0xbb1f6f7c565f47fa6e524ee0901d2b8b7a402895f4ccb7ee210723d757715869&quot;
    execution_block_height: 490
- deposit_data:
    pubkey: &quot;0x933146088cae286d7d0c2759fab13c1f3e7cea13c05504c006e2ac25f322a779905fe4466f0db965620767d6270ac324&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa8a74b8afa78efaabefa3316ed4fb2715e2be3c0bc70b3df6b04c13f8d19ffe08df3558a083a1b34ceb06fb44c437cc9189378d8a785f2a3ac68606189d06f3787944c2b28f249bbd0755ffc2772f523a5cc2502a89f52be0d225c7330d9f478&quot;
  deposit_data_root: &quot;0xbc62013d7afb2e7f7c9c306c73449cef0f5b76e80568d3efe50744b3586c3c6a&quot;
  eth1_data:
    deposit_root: &quot;0x41dcb927c029b48451acb6f81bb177f21ec50556bce33f91939011f29fc834fd&quot;
    deposit_count: &quot;490&quot;
    block_hash: &quot;0x0af4b9127af4de48537331081e5d471983a3787901800be316b3060496e718dc&quot;
  block_height: 491
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0x3875f467344ea7151aaeaf8d2f3c78cf2dacd91f8a81b6ab8ca1e02df2fff953&quot;
      - &quot;0xc2117c26af280c0c49598e0448112e04588ab6a3ee01b2be0a1380ccd6ab884a&quot;
    deposit_root: &quot;0x41dcb927c029b48451acb6f81bb177f21ec50556bce33f91939011f29fc834fd&quot;
    deposit_count: 490
    execution_block_hash: &quot;0x0af4b9127af4de48537331081e5d471983a3787901800be316b3060496e718dc&quot;
    execution_block_height: 491
- deposit_data:
    pubkey: &quot;0xb31a6cb5ab165f4b7b66bee6fcab77e410a3c7d7049ca5a6a7bc64b30a1c49bef4a1ed72454b87c8b879c00c57212ac2&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8b9393ad8fe5132742cb3f2cfc722f9f80c98dfec7055a09fe4d9ee744c484d5ab234d1be89e8686ab6173096be867340b7d4c8ec2b76a4974a5e4f75664fcf6a82f95089fa8d284296a9e7608a88e8668974abfc58c0cc5552bdb0633449312&quot;
  deposit_data_root: &quot;0x38e2586880e59ae2b10e79b4bbea1bbf4fff9eb24c0e76e9eeff1117ecf7e326&quot;
  eth1_data:
    deposit_root: &quot;0xdc6d5c39bd67371b5a38d2baa1180139c09dd6e762ed5274586d6fae140aef33&quot;
    deposit_count: &quot;491&quot;
    block_hash: &quot;0x10a29b7a13bbba866147b26e86cb01908d83599a1dd6734fc5cbab0c8d5c2761&quot;
  block_height: 492
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0x3875f467344ea7151aaeaf8d2f3c78cf2dacd91f8a81b6ab8ca1e02df2fff953&quot;
      - &quot;0xc2117c26af280c0c49598e0448112e04588ab6a3ee01b2be0a1380ccd6ab884a&quot;
      - &quot;0x38e2586880e59ae2b10e79b4bbea1bbf4fff9eb24c0e76e9eeff1117ecf7e326&quot;
    deposit_root: &quot;0xdc6d5c39bd67371b5a38d2baa1180139c09dd6e762ed5274586d6fae140aef33&quot;
    deposit_count: 491
    execution_block_hash: &quot;0x10a29b7a13bbba866147b26e86cb01908d83599a1dd6734fc5cbab0c8d5c2761&quot;
    execution_block_height: 492
- deposit_data:
    pubkey: &quot;0x9570f6171cbc78d58dd8afd84cc2f803ab049dcc15566b4c16406f798b65346f3bb36c45aff846e4604ab79ddba8125f&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa93e273b50dbfbc9306d5dc86e49923e641166456f2930ebd3ca51ee1db9bc21bcfc27d90de43a76657c3f302456093b02adc0e553601ee8781f149c9c9e38021222db3614ac89f5789a9d0765bb94d03e0dc034b62a828317dd583d44a47efd&quot;
  deposit_data_root: &quot;0x52e9547d5df15475ad6635a94d60a382d8170a9e94db26e2948dfbc1838bba10&quot;
  eth1_data:
    deposit_root: &quot;0x22824f94535edf7e747a7ffe09ee5000d430a32a5eb63a223e6e888e558d6840&quot;
    deposit_count: &quot;492&quot;
    block_hash: &quot;0x24b8b1fb9de52367089b9098ba02dd01657c2da749dcefc4ff56f5c68c6852e7&quot;
  block_height: 493
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0x3875f467344ea7151aaeaf8d2f3c78cf2dacd91f8a81b6ab8ca1e02df2fff953&quot;
      - &quot;0x4f8311465fde082df60a4db44e53bcd965cf3a8f39d3166b2a769cf8a5cdc758&quot;
    deposit_root: &quot;0x22824f94535edf7e747a7ffe09ee5000d430a32a5eb63a223e6e888e558d6840&quot;
    deposit_count: 492
    execution_block_hash: &quot;0x24b8b1fb9de52367089b9098ba02dd01657c2da749dcefc4ff56f5c68c6852e7&quot;
    execution_block_height: 493
- deposit_data:
    pubkey: &quot;0x871e9ef179706974e0423fb0a6f17673dd3d91ac9625a5c034d2797c396698489dff3c53abea15b7b5604919fd36acf6&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x84eb083fb8262d0a9d6c1ba20a5ceeee8d8b4fa4643cca03b6fd7b8affe3245c57a60294732b27b05adf0ca549bf0187040b38828218e89fa3905975e37a6d0f7c3664b271bda3a996f698fb081f98606c079016017e45388f4abfed55d5acb6&quot;
  deposit_data_root: &quot;0x366bca78131fd8260d4223c1c7c2c4fed8d22a5f43647b8bb5692ede92d255bc&quot;
  eth1_data:
    deposit_root: &quot;0xe5cac4e82791679b4044bfa3435209aa4b6388af630191371a7851eaa79b3529&quot;
    deposit_count: &quot;493&quot;
    block_hash: &quot;0xe4511513af4b15a09c1f2e1fd8ca52c6425803ef329133541130331d5ea134ba&quot;
  block_height: 494
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0x3875f467344ea7151aaeaf8d2f3c78cf2dacd91f8a81b6ab8ca1e02df2fff953&quot;
      - &quot;0x4f8311465fde082df60a4db44e53bcd965cf3a8f39d3166b2a769cf8a5cdc758&quot;
      - &quot;0x366bca78131fd8260d4223c1c7c2c4fed8d22a5f43647b8bb5692ede92d255bc&quot;
    deposit_root: &quot;0xe5cac4e82791679b4044bfa3435209aa4b6388af630191371a7851eaa79b3529&quot;
    deposit_count: 493
    execution_block_hash: &quot;0xe4511513af4b15a09c1f2e1fd8ca52c6425803ef329133541130331d5ea134ba&quot;
    execution_block_height: 494
- deposit_data:
    pubkey: &quot;0x879391eff950beb2720f83aa628e43b313ec26e20cad9b75457bd8de5b1883fad8c5f28533ebebac4e377d82145d75da&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8a31291a8934809c33b88d68754d8abc0c6740474264c475d2e825f550b79cc4ba4d767f152afd628eb956ab0198014e18c365a66d4e9c6d5c92c8879791a41a9940304a419fabedb6d64d58706083e94afbca69c35718e6dbc8e97ead3ce50e&quot;
  deposit_data_root: &quot;0xa2d9df9463cd8a99c0caa53d39a2b5339149c329935288339b2dffda66babd34&quot;
  eth1_data:
    deposit_root: &quot;0x137fab1083cfe288afb0dc871b75b475b1cab3d6989cea5ec1ddc30588bcf9f3&quot;
    deposit_count: &quot;494&quot;
    block_hash: &quot;0xf5faca75aad4bc3195af3ce6e8cc953c804344697267f9621dc4d3d18d919ad4&quot;
  block_height: 495
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0x3875f467344ea7151aaeaf8d2f3c78cf2dacd91f8a81b6ab8ca1e02df2fff953&quot;
      - &quot;0x4f8311465fde082df60a4db44e53bcd965cf3a8f39d3166b2a769cf8a5cdc758&quot;
      - &quot;0xa3645b2bae71b310416e701a535d888cc14e78d867e2e88703a09b93af06de0d&quot;
    deposit_root: &quot;0x137fab1083cfe288afb0dc871b75b475b1cab3d6989cea5ec1ddc30588bcf9f3&quot;
    deposit_count: 494
    execution_block_hash: &quot;0xf5faca75aad4bc3195af3ce6e8cc953c804344697267f9621dc4d3d18d919ad4&quot;
    execution_block_height: 495
- deposit_data:
    pubkey: &quot;0xb03bdf830d2cf1c1d8f0bb100fb3d4d399b48ca2e67e8f8513809bdf49beeb4b710438d64bdd9f4d4aebc3cc844e9302&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb81d217f78655216903e2c617be8cc10455b5f58335f522a91c35329693d5af7e906e490edd919f63d74c27b142570bf1407f26517a16835c18f6032683939359fa721e3f9ed56b8a38aec6aa36d4fa344e80a0cf16f0c990bba0d4e1d9758bc&quot;
  deposit_data_root: &quot;0xd4872c8e2cd8f5fe969e07d8c702201df480500077039ef03baa524e4eecb5d5&quot;
  eth1_data:
    deposit_root: &quot;0x89ee072c31cf8d3c38c359eae18f99047dad53e040e404ce65f758d8973dd831&quot;
    deposit_count: &quot;495&quot;
    block_hash: &quot;0x2a4557f04eda1cfab40813fbfaa9d0cd3297311d4c35f56aa325e83b44667b4f&quot;
  block_height: 496
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0x3875f467344ea7151aaeaf8d2f3c78cf2dacd91f8a81b6ab8ca1e02df2fff953&quot;
      - &quot;0x4f8311465fde082df60a4db44e53bcd965cf3a8f39d3166b2a769cf8a5cdc758&quot;
      - &quot;0xa3645b2bae71b310416e701a535d888cc14e78d867e2e88703a09b93af06de0d&quot;
      - &quot;0xd4872c8e2cd8f5fe969e07d8c702201df480500077039ef03baa524e4eecb5d5&quot;
    deposit_root: &quot;0x89ee072c31cf8d3c38c359eae18f99047dad53e040e404ce65f758d8973dd831&quot;
    deposit_count: 495
    execution_block_hash: &quot;0x2a4557f04eda1cfab40813fbfaa9d0cd3297311d4c35f56aa325e83b44667b4f&quot;
    execution_block_height: 496
- deposit_data:
    pubkey: &quot;0xadf6fceba8b405cb2a0e853da1a8db38799eaf868a91294a297f0ba4601731a438f1f7a8b15c91cbc7b4f07734d74ac0&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9055a60776e60b558d5722e5f168b13f4ba31940ad146948423a771e4973081bc99b9247ad648af178b11d1331cadd83014504c0cc289afa2c399b983dca0a01c5a5c4b321fcd615b185f982e6663dbaadb0b9222681e841c452810421ce28c0&quot;
  deposit_data_root: &quot;0xb89408cff9700bea9c5070d4bcae6f0a4b5171f4232a341f5f6d259b15d51461&quot;
  eth1_data:
    deposit_root: &quot;0xed3c614ac36483433d060e8e8576cb18c7aaad8b5fa57c067869a892e83aff98&quot;
    deposit_count: &quot;496&quot;
    block_hash: &quot;0x15efa8aba9883de6c511364fc9949a2ce28fd1320914681c40cff4c7d03dd4e3&quot;
  block_height: 497
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0xbe91342b23cac4f3b516349701aa3357b170da8ebd6769691d1c633f0391b2be&quot;
    deposit_root: &quot;0xed3c614ac36483433d060e8e8576cb18c7aaad8b5fa57c067869a892e83aff98&quot;
    deposit_count: 496
    execution_block_hash: &quot;0x15efa8aba9883de6c511364fc9949a2ce28fd1320914681c40cff4c7d03dd4e3&quot;
    execution_block_height: 497
- deposit_data:
    pubkey: &quot;0xa931ae0ef4447284cad9e27b334924088b87f489d1c1eb49883cd2f35e4cd445dfac88e564605b32d471b56b4d98a4cb&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x927f3ded1db0e263965b5dc1433649056672f337df5a66e46e23be11287c60fb5fb83cc1878af02f020a41a52a5524730965f98460e4ec8faa34cfa7f82f84f7847e163a97bde7fd6326048787a0e65e71eb49225d2e00ef180a46eacb5821d9&quot;
  deposit_data_root: &quot;0x8526ea94647b0af12f3cda3d20987c8914451a827b81da295d625c6621de481c&quot;
  eth1_data:
    deposit_root: &quot;0x421728e94bc65613888da789ec8a68a70a9396a248416cf46a2ade5debdf71c7&quot;
    deposit_count: &quot;497&quot;
    block_hash: &quot;0x01e5154c23dc0820fddb99b9d1c36c7564750cb38a39c18cf3b1f2f6db3d036c&quot;
  block_height: 498
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0xbe91342b23cac4f3b516349701aa3357b170da8ebd6769691d1c633f0391b2be&quot;
      - &quot;0x8526ea94647b0af12f3cda3d20987c8914451a827b81da295d625c6621de481c&quot;
    deposit_root: &quot;0x421728e94bc65613888da789ec8a68a70a9396a248416cf46a2ade5debdf71c7&quot;
    deposit_count: 497
    execution_block_hash: &quot;0x01e5154c23dc0820fddb99b9d1c36c7564750cb38a39c18cf3b1f2f6db3d036c&quot;
    execution_block_height: 498
- deposit_data:
    pubkey: &quot;0xb304ff0820279e94ad069248706d39bddb36cb1ef69e1031f2f0683c69b4e8fe5bee35a64a7d160f8f207253bf6a1080&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xad022d059131eaf12492893f3b4d531ef72f713a18b5965e2f24a30d759e997809ae16fa808210f38cab0f7b3a244a0419913fb6805654a9b0e02e426e47b2aa363b8bddcaaf36569383559214a5a79d8190f9a268a30532c3e42866e02ca21f&quot;
  deposit_data_root: &quot;0x46c229cd0c3e568093841a1e7d92c9bfa369d9dc633067c83aee89f0cd754c3e&quot;
  eth1_data:
    deposit_root: &quot;0xdb3a62269b0ddfe5139f62b8b90c661c1f7e5e36821357e1b6e7e3288d9ec2ab&quot;
    deposit_count: &quot;498&quot;
    block_hash: &quot;0xcdd347d62aa299215a836ce87a9f671d2cb8dd4541325c26dfc66b5c87cf937e&quot;
  block_height: 499
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0xbe91342b23cac4f3b516349701aa3357b170da8ebd6769691d1c633f0391b2be&quot;
      - &quot;0xf2b54cd30ee3995c110c2028f35d5a400cb8a1ce9600757c8bae0e426db572c9&quot;
    deposit_root: &quot;0xdb3a62269b0ddfe5139f62b8b90c661c1f7e5e36821357e1b6e7e3288d9ec2ab&quot;
    deposit_count: 498
    execution_block_hash: &quot;0xcdd347d62aa299215a836ce87a9f671d2cb8dd4541325c26dfc66b5c87cf937e&quot;
    execution_block_height: 499
- deposit_data:
    pubkey: &quot;0xb51c0882970b04879282a60dcfda6577abd62328859c811ad190b4a77b824e4ef7dcfa544f7e76ad0d0c53372e9ba43f&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb67d9631d1380573c574fc1a57dfd7266a42318b253955bfc2fadb55af3eabdbb311950c219ae6ca5ea8e7a8967ba7a41519a96a7437c7fa24bdbe02ae13f7191308eacab1528639d0efd1b4d195006b63f862202175e8975fa5b7f86461f481&quot;
  deposit_data_root: &quot;0x5342789288be2a5531cb6f31633584200615948145d3542a266e2b8965edc64b&quot;
  eth1_data:
    deposit_root: &quot;0x54c8df95f9d2b54939012347e05c3214e517c55d8540807b1ad754619c5a971d&quot;
    deposit_count: &quot;499&quot;
    block_hash: &quot;0x0b9574a4021e274198282a737f25de33d496573581e0912393315b491ea15ef2&quot;
  block_height: 500
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0xbe91342b23cac4f3b516349701aa3357b170da8ebd6769691d1c633f0391b2be&quot;
      - &quot;0xf2b54cd30ee3995c110c2028f35d5a400cb8a1ce9600757c8bae0e426db572c9&quot;
      - &quot;0x5342789288be2a5531cb6f31633584200615948145d3542a266e2b8965edc64b&quot;
    deposit_root: &quot;0x54c8df95f9d2b54939012347e05c3214e517c55d8540807b1ad754619c5a971d&quot;
    deposit_count: 499
    execution_block_hash: &quot;0x0b9574a4021e274198282a737f25de33d496573581e0912393315b491ea15ef2&quot;
    execution_block_height: 500
- deposit_data:
    pubkey: &quot;0xa24dd1ce8d1d5af40401a2c2d47027de989313ead893a646456eb4ea9d6e38cf8cd37f75e2dfa631beed89970848a39c&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x91637e293d8b865c76aa80ccaa42e10dce7e1002647423cefa8e67c740f755a5b7b833a7b201e54a4d1a0a563963716412cb466eadd67b17d67c922d34f9f6e3c9ec1ad09434685cd0c7c3e1008ec84f4db02c3054023cea1d7716739129a3fe&quot;
  deposit_data_root: &quot;0x721297ec667e7bfec80ee3780c2a99c345a4a4de112c6c18acf2b2f7d9c01539&quot;
  eth1_data:
    deposit_root: &quot;0x695c65690f919bc3d1a81d29b03fbe3799754db34e73dd334d614198f58e7f78&quot;
    deposit_count: &quot;500&quot;
    block_hash: &quot;0x525ada6ebdc963f5b0cb396229e629557816abb142eb8e8161d5cfc5b7d2432d&quot;
  block_height: 501
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0xbe91342b23cac4f3b516349701aa3357b170da8ebd6769691d1c633f0391b2be&quot;
      - &quot;0xf71b0bf2bd3427f729de49cbe1f7cad35e2e80960e2f4a865c936f4197f74327&quot;
    deposit_root: &quot;0x695c65690f919bc3d1a81d29b03fbe3799754db34e73dd334d614198f58e7f78&quot;
    deposit_count: 500
    execution_block_hash: &quot;0x525ada6ebdc963f5b0cb396229e629557816abb142eb8e8161d5cfc5b7d2432d&quot;
    execution_block_height: 501
- deposit_data:
    pubkey: &quot;0x943c88ab60e1b649772ebefea93e27bdc89bae1901cb8f181fb813a753861bf7e3c460b909566f30be2ad7ecc7e345aa&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb6cbee3d623fcd4a2bdf4b372ac8a54bea60d3b9a3c1079336a2250f6584b0bb0f5ff6fe074211a733ba8c0bd52d102e0ead892d2c8c7258d80048f03717498493cba834a30c966fff67b205ad6ac3a1ede20f3c9ed50305f07d3f2ac89863af&quot;
  deposit_data_root: &quot;0x563286c1b77c9e1d183fb518d9f263071cb48a8069db366a6aeca6bd4ec35842&quot;
  eth1_data:
    deposit_root: &quot;0xb11904549318b9f97731d696ceaf2a039e35e5b779234026e50f7e8a678bbdb9&quot;
    deposit_count: &quot;501&quot;
    block_hash: &quot;0xa936f16a1d89a846f3001253b571b6ca0f0aba7e546382dee4a0dbcc7a63c63a&quot;
  block_height: 502
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0xbe91342b23cac4f3b516349701aa3357b170da8ebd6769691d1c633f0391b2be&quot;
      - &quot;0xf71b0bf2bd3427f729de49cbe1f7cad35e2e80960e2f4a865c936f4197f74327&quot;
      - &quot;0x563286c1b77c9e1d183fb518d9f263071cb48a8069db366a6aeca6bd4ec35842&quot;
    deposit_root: &quot;0xb11904549318b9f97731d696ceaf2a039e35e5b779234026e50f7e8a678bbdb9&quot;
    deposit_count: 501
    execution_block_hash: &quot;0xa936f16a1d89a846f3001253b571b6ca0f0aba7e546382dee4a0dbcc7a63c63a&quot;
    execution_block_height: 502
- deposit_data:
    pubkey: &quot;0xa2eea192ab4a2213efc58879ce008f8684c3b8da24d7a0124ed33c6ee9d3d12adcac702a938e2ccad79fde467fa413c4&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa25236c672bf2eb19b4a8a9da4564a35e2f3c8545f4190ce5916009f0957a28784622d6840a806f29df5a27e99d58057014595ab84d62f0d8edb67e4fa91504f68b906f9a975bb62da0714929fb0cb1262345bca6e2b71d0db4bc5d7f353397d&quot;
  deposit_data_root: &quot;0x3691a26d2ceb9f3a6417d2c53d9ed3fd5cc2fbcc1211d78ed5d2e21d7930ac17&quot;
  eth1_data:
    deposit_root: &quot;0x601b2c94d23ab5858f4eacb14fda5eeb7408d13582a6afdb24b8fc91f1ade8a1&quot;
    deposit_count: &quot;502&quot;
    block_hash: &quot;0x040c9bd5cc7316ee54b15126e380a8795a352165ba3eea6328e65389101541bb&quot;
  block_height: 503
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0xbe91342b23cac4f3b516349701aa3357b170da8ebd6769691d1c633f0391b2be&quot;
      - &quot;0xf71b0bf2bd3427f729de49cbe1f7cad35e2e80960e2f4a865c936f4197f74327&quot;
      - &quot;0xa3d1c3c7ccbc27ed4d1edd2579de324b7a53144a936ee798b133252cb1eb8466&quot;
    deposit_root: &quot;0x601b2c94d23ab5858f4eacb14fda5eeb7408d13582a6afdb24b8fc91f1ade8a1&quot;
    deposit_count: 502
    execution_block_hash: &quot;0x040c9bd5cc7316ee54b15126e380a8795a352165ba3eea6328e65389101541bb&quot;
    execution_block_height: 503
- deposit_data:
    pubkey: &quot;0xa1792fc5047546bc98391908b80fc9b4a790018b580836cfa593426624ab1785d11449a03c93759f34645d277e9f26ee&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xaa2521a398340e4fa390e4335a1cb3fe7e840ad6da4dec4c03332250ebd2d43fb6b7a968c6c06e50389fd654b08c338a143b1ccd26fb428a0b6df28d07d294d87cb214f7be07a59cf4f5326a17b801b9d1c37e8e44930420639784b5ee777cb8&quot;
  deposit_data_root: &quot;0x4bec8c542e2bfb99d7e4703013705c2c3192f21335f1ea00d5267e869640c31c&quot;
  eth1_data:
    deposit_root: &quot;0x3f0fbcbb62eb78578683087a8869a260b30b001bb6afdb53246538c61e686b6f&quot;
    deposit_count: &quot;503&quot;
    block_hash: &quot;0x5c8134c7e7bb2f1bc0781ddc9b331afd5be19587aaac6c911a617f8cdb9a6204&quot;
  block_height: 504
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0xbe91342b23cac4f3b516349701aa3357b170da8ebd6769691d1c633f0391b2be&quot;
      - &quot;0xf71b0bf2bd3427f729de49cbe1f7cad35e2e80960e2f4a865c936f4197f74327&quot;
      - &quot;0xa3d1c3c7ccbc27ed4d1edd2579de324b7a53144a936ee798b133252cb1eb8466&quot;
      - &quot;0x4bec8c542e2bfb99d7e4703013705c2c3192f21335f1ea00d5267e869640c31c&quot;
    deposit_root: &quot;0x3f0fbcbb62eb78578683087a8869a260b30b001bb6afdb53246538c61e686b6f&quot;
    deposit_count: 503
    execution_block_hash: &quot;0x5c8134c7e7bb2f1bc0781ddc9b331afd5be19587aaac6c911a617f8cdb9a6204&quot;
    execution_block_height: 504
- deposit_data:
    pubkey: &quot;0xb2f64f70753f79fc04398f220f2ee1a54d14c8bd31c1b27105aae559d5006434135e516e975f57c7a41241ac74ab6aaa&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa17e776cdecb5f4c33b2a84cd37b12bb2bba06fc0e95ec255a0722ef32b2b273d2dd47001574d9ac254c7451be09614702d2761cada37688adb3babade14bbaf03a480f771ce1bc52824f73518dc1dea9786d1dfd34407fa83974ad8c79c5849&quot;
  deposit_data_root: &quot;0xd4b6855d328858c320b36bbffda4a196e410d8ddf105c387c8ed7d3781853ab3&quot;
  eth1_data:
    deposit_root: &quot;0xd656f74b083d9e27e3d9a38247dc8ef3a48fa128173e054d6e8cc476a07a5dc0&quot;
    deposit_count: &quot;504&quot;
    block_hash: &quot;0xfd8f2f9a3cbc74fc6def66bcf7362ab06ffaa26414ec2be744954381e6e6c8e9&quot;
  block_height: 505
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0xbe91342b23cac4f3b516349701aa3357b170da8ebd6769691d1c633f0391b2be&quot;
      - &quot;0xe129a1eb08eea7dc270c6d43e68441450375894e2bb046328e0ce35a68faca31&quot;
    deposit_root: &quot;0xd656f74b083d9e27e3d9a38247dc8ef3a48fa128173e054d6e8cc476a07a5dc0&quot;
    deposit_count: 504
    execution_block_hash: &quot;0xfd8f2f9a3cbc74fc6def66bcf7362ab06ffaa26414ec2be744954381e6e6c8e9&quot;
    execution_block_height: 505
- deposit_data:
    pubkey: &quot;0x86195e4462e04f6e0f4c2545ecc9c0fa812f1ffd6cde31bef2f59c5806d839937d60bd8180c2362555f73aadf6591965&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x834363e5f9c86333ab75a6a75f31324e5789d3fa705a4cb13c86a8045c27b9a37e8648ce6b0bf3f1d1c57007e40b54d80a3cc975baff2463345a3c438668f70ba5fa4cf906f7a23687eddb0b2c46a2957ecc1d3867ff5c2462c7448112089311&quot;
  deposit_data_root: &quot;0xfa190fba4e1bf49150b7c76cfd7d07f269d46fe04f08995bb7473345b2bb4499&quot;
  eth1_data:
    deposit_root: &quot;0x723a02ae297d5787bbc4a3a1b30783fcd486c0ccd9428873c237d78d97ecdf2b&quot;
    deposit_count: &quot;505&quot;
    block_hash: &quot;0xd31b757dc9ab9e121243a12efd22177616a1a0327335121b63f0d91f175b3344&quot;
  block_height: 506
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0xbe91342b23cac4f3b516349701aa3357b170da8ebd6769691d1c633f0391b2be&quot;
      - &quot;0xe129a1eb08eea7dc270c6d43e68441450375894e2bb046328e0ce35a68faca31&quot;
      - &quot;0xfa190fba4e1bf49150b7c76cfd7d07f269d46fe04f08995bb7473345b2bb4499&quot;
    deposit_root: &quot;0x723a02ae297d5787bbc4a3a1b30783fcd486c0ccd9428873c237d78d97ecdf2b&quot;
    deposit_count: 505
    execution_block_hash: &quot;0xd31b757dc9ab9e121243a12efd22177616a1a0327335121b63f0d91f175b3344&quot;
    execution_block_height: 506
- deposit_data:
    pubkey: &quot;0x8a6d7746a13800bc06e455dc52786c35065e2b08054ab8e569e28391dbef3d2527eea72aa60e1b53a54dc477055bccf2&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x96725d9c529a3bec9780a7d693e589c2e1b8e2d328d21e52a9ade535810501c0f2f9e45022564b3e8c9c371d9cfada1e03098990f36a9a2e6defd299ce06e9ff8f90a683a2a4bc0083bb2c424a4e3311f95cbd030962305808dfafd5967eb1ba&quot;
  deposit_data_root: &quot;0x998a3d35a682a46fde29ea288109b96a4b24a246a7d4b24f7572bcff109d6ade&quot;
  eth1_data:
    deposit_root: &quot;0xc748ed0905ebcfec8085a8c67091ac467642915c73dd758f432b5e8658a90044&quot;
    deposit_count: &quot;506&quot;
    block_hash: &quot;0x28b47914e0960b493976bc8ee4cc861fa19f640d6a3369df08b413c550540df9&quot;
  block_height: 507
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0xbe91342b23cac4f3b516349701aa3357b170da8ebd6769691d1c633f0391b2be&quot;
      - &quot;0xe129a1eb08eea7dc270c6d43e68441450375894e2bb046328e0ce35a68faca31&quot;
      - &quot;0x9e659e07ef110f0141fdce5a789ae1a54952cadb33028e879430eb600ef4d58a&quot;
    deposit_root: &quot;0xc748ed0905ebcfec8085a8c67091ac467642915c73dd758f432b5e8658a90044&quot;
    deposit_count: 506
    execution_block_hash: &quot;0x28b47914e0960b493976bc8ee4cc861fa19f640d6a3369df08b413c550540df9&quot;
    execution_block_height: 507
- deposit_data:
    pubkey: &quot;0x961cc399896c8daecb0784f91943dd32077c9ad661f460f27f048ffc557010b4bd9a4a692306b6f70ff0f597fd31ecbe&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x9049a268bf99261658ce1087a0b7874a059b951c7a03bc56f46ab0474efefc1c245bbda655bd994d25576df5ce7ef3e30345a606af54bf4d171dc0dddcf6122f71ec286f57a543767b2869ff2f84df30e324a682011c250e52d2bda21eef798d&quot;
  deposit_data_root: &quot;0xc0107b388528dd8ec080388c8313dd88c9c6e6fc742a27081881a5209c084295&quot;
  eth1_data:
    deposit_root: &quot;0x0c016b6f117e5507d6e740412dda9f7e5cdd539650a8a424e7a06c836408078a&quot;
    deposit_count: &quot;507&quot;
    block_hash: &quot;0xf89a37f7162803e84f7ffbaf0f5ea73306993adfd524d7aa060d49316b96c607&quot;
  block_height: 508
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0xbe91342b23cac4f3b516349701aa3357b170da8ebd6769691d1c633f0391b2be&quot;
      - &quot;0xe129a1eb08eea7dc270c6d43e68441450375894e2bb046328e0ce35a68faca31&quot;
      - &quot;0x9e659e07ef110f0141fdce5a789ae1a54952cadb33028e879430eb600ef4d58a&quot;
      - &quot;0xc0107b388528dd8ec080388c8313dd88c9c6e6fc742a27081881a5209c084295&quot;
    deposit_root: &quot;0x0c016b6f117e5507d6e740412dda9f7e5cdd539650a8a424e7a06c836408078a&quot;
    deposit_count: 507
    execution_block_hash: &quot;0xf89a37f7162803e84f7ffbaf0f5ea73306993adfd524d7aa060d49316b96c607&quot;
    execution_block_height: 508
- deposit_data:
    pubkey: &quot;0x8edb799cc0407cf8db901082d7fcd613b7dd4ea03caef14073841e54531bdcdf3f661d551edae045b960b506e70b8dc8&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xa88cca9dc14b177d45e96da17be05c999f86f12db33ad5060b82e53f9a94949542bcec1ca0422d16de2439ee5fa1215615d16bd0e50ea1e3f9abcbe8096ca51837243a709a6fb02c9dfe443dc2e175af845465108d49132b0e94a3833e10080d&quot;
  deposit_data_root: &quot;0xdc384b4f094fc826477b19d9126ec7e2937fc95fb19397073f00e211e9dfc8b1&quot;
  eth1_data:
    deposit_root: &quot;0xf0ac44f68f2ebad7f114356cabeee522a8dfd5713da8a875d28630edbf2ba3d6&quot;
    deposit_count: &quot;508&quot;
    block_hash: &quot;0x14ce1569b047c9a4015e7ff6b15b90cf19bae216e88e578651af70927afc5425&quot;
  block_height: 509
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0xbe91342b23cac4f3b516349701aa3357b170da8ebd6769691d1c633f0391b2be&quot;
      - &quot;0xe129a1eb08eea7dc270c6d43e68441450375894e2bb046328e0ce35a68faca31&quot;
      - &quot;0x755680bc147f24f2b5988a005d2af577aaa2f9364a17d97436a7296698418aa3&quot;
    deposit_root: &quot;0xf0ac44f68f2ebad7f114356cabeee522a8dfd5713da8a875d28630edbf2ba3d6&quot;
    deposit_count: 508
    execution_block_hash: &quot;0x14ce1569b047c9a4015e7ff6b15b90cf19bae216e88e578651af70927afc5425&quot;
    execution_block_height: 509
- deposit_data:
    pubkey: &quot;0x8eab84a4394a69ff45dad4a17d4a8ce3bb04948c68bc70abbdebdd76c2156507a319d5bf9cfcaf750fe3b4d5c66723ee&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x921e0672eee586061a353cb40a0586354fbcf92c7c94be47a0e35f58c183bac72959dac50d83cc6e826ae29540ae4924048bfa5adc5b6be5fc4df54816a41fc265f514e2393796c454e822baff3ecedfcff8c36ca56731df32ca9f868219db1a&quot;
  deposit_data_root: &quot;0x9538b1a35a2401f1ae3146672fb986168c4872d6ce0ff63f9fd8fcc590b81a05&quot;
  eth1_data:
    deposit_root: &quot;0x2be7501704a28527b0cde140e090ae14b1951facdd019b1bbdb5a53165663b90&quot;
    deposit_count: &quot;509&quot;
    block_hash: &quot;0xc092fd8e7712ceb3e8b1db31d939638233c0768396159d836fd8fae04a020db3&quot;
  block_height: 510
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0xbe91342b23cac4f3b516349701aa3357b170da8ebd6769691d1c633f0391b2be&quot;
      - &quot;0xe129a1eb08eea7dc270c6d43e68441450375894e2bb046328e0ce35a68faca31&quot;
      - &quot;0x755680bc147f24f2b5988a005d2af577aaa2f9364a17d97436a7296698418aa3&quot;
      - &quot;0x9538b1a35a2401f1ae3146672fb986168c4872d6ce0ff63f9fd8fcc590b81a05&quot;
    deposit_root: &quot;0x2be7501704a28527b0cde140e090ae14b1951facdd019b1bbdb5a53165663b90&quot;
    deposit_count: 509
    execution_block_hash: &quot;0xc092fd8e7712ceb3e8b1db31d939638233c0768396159d836fd8fae04a020db3&quot;
    execution_block_height: 510
- deposit_data:
    pubkey: &quot;0xb4c37ed40d2d3d2ace8ba3e1d0bb1b0651d3d21c3dc5e8a4ef42513d649fc14d6dcd1ba7c8b893a2205f6afc870feb75&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x990065021cd5c4395a74ee4ef2bd3ae57e6a69afbb520c9af1793e2272ccf96252cb24cdc06f566d930939e709493e700610c5de71a888a01ae07f6e9eae7995e8c4a8e2ae2a0c9d19832ebd90dc3218857253a453f419681fe5974a56f5beee&quot;
  deposit_data_root: &quot;0x79922ab72714b5a5f07b6d4ad531260bdc3da6b2723f5a621a19f49d14f080d4&quot;
  eth1_data:
    deposit_root: &quot;0x904cf102790d85df5521caba1f278f99ed62a6b72fc1aa7a9c9731014b4b08c7&quot;
    deposit_count: &quot;510&quot;
    block_hash: &quot;0x59ecebf2c2f7d2de32d3de30320e7b278ca84c9ab21fecb0bc129a56eab60ef0&quot;
  block_height: 511
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0xbe91342b23cac4f3b516349701aa3357b170da8ebd6769691d1c633f0391b2be&quot;
      - &quot;0xe129a1eb08eea7dc270c6d43e68441450375894e2bb046328e0ce35a68faca31&quot;
      - &quot;0x755680bc147f24f2b5988a005d2af577aaa2f9364a17d97436a7296698418aa3&quot;
      - &quot;0x1ae3fbc472814f00a5434bbc76e084c37564a55fee67c206c9977c152b12c38e&quot;
    deposit_root: &quot;0x904cf102790d85df5521caba1f278f99ed62a6b72fc1aa7a9c9731014b4b08c7&quot;
    deposit_count: 510
    execution_block_hash: &quot;0x59ecebf2c2f7d2de32d3de30320e7b278ca84c9ab21fecb0bc129a56eab60ef0&quot;
    execution_block_height: 511
- deposit_data:
    pubkey: &quot;0xb02b650ec8c8a75cdb3c8cc64b612c5180aa31e0345ce16b1d9d8e5c7ce28d4feb8ed6bab0be68c13a5acd71f326fab8&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0x8eb8590912f2736f59f2fc221f167f9806159c922a041d94e1cb7dbd1703e84d7ea54623ffd01aeefab48ded3accac940610dacc940565a4bdadbd586bb7ea7e95cd8a6439363963618fb3332ae2eb1a33fdde5a20871550188a5a21657b141b&quot;
  deposit_data_root: &quot;0xaa58eeff0a6439e85c0062387253ed726b0dcb040f1ad6f9e2dd2ea9ef6b0d41&quot;
  eth1_data:
    deposit_root: &quot;0xdf4c6590595af97badd52a23a3d2da9e1171340d3e9d299ea462b482822e3680&quot;
    deposit_count: &quot;511&quot;
    block_hash: &quot;0xc5db6286114149aacff6eaae584d859fbbcbb914cb3f111447844e76e7623822&quot;
  block_height: 512
  snapshot:
    finalized:
      - &quot;0x1be35e1ed8992a8d55a57ee0a215ffa733e7e66282acfd151ad96e813963f4a1&quot;
      - &quot;0xce176f39f29e8b5f6cbd3d107bf8a2e6162266aef4ee4aa784e6c899474ca670&quot;
      - &quot;0xbfa916399e17a4550bfb5997c9b20433cc80c876ad0cf18df57493bce4dc8d29&quot;
      - &quot;0x61f220b3f77327db30183075bd0e691acebd9aa729ace9b85d6381f40bbabd15&quot;
      - &quot;0xbe91342b23cac4f3b516349701aa3357b170da8ebd6769691d1c633f0391b2be&quot;
      - &quot;0xe129a1eb08eea7dc270c6d43e68441450375894e2bb046328e0ce35a68faca31&quot;
      - &quot;0x755680bc147f24f2b5988a005d2af577aaa2f9364a17d97436a7296698418aa3&quot;
      - &quot;0x1ae3fbc472814f00a5434bbc76e084c37564a55fee67c206c9977c152b12c38e&quot;
      - &quot;0xaa58eeff0a6439e85c0062387253ed726b0dcb040f1ad6f9e2dd2ea9ef6b0d41&quot;
    deposit_root: &quot;0xdf4c6590595af97badd52a23a3d2da9e1171340d3e9d299ea462b482822e3680&quot;
    deposit_count: 511
    execution_block_hash: &quot;0xc5db6286114149aacff6eaae584d859fbbcbb914cb3f111447844e76e7623822&quot;
    execution_block_height: 512
- deposit_data:
    pubkey: &quot;0x890bbabc36dc93557dffada73af2e71bd15481fb5345d7b4755498ddb1bd8733f0140cc40007c76ccc8764ba42678d1e&quot;
    withdrawal_credentials: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;
    amount: &quot;32000000000&quot;
    signature: &quot;0xb2e4b4c3d177fbeacd0a4cfbb4eb8504e380b2354b5ffac72705ff61fbea065af6793ec133971dcc7da8cef0fe3ff61d06ea05be4f1e2b88c29be2d769008a9a1385c156861553587913c0a0fe74fc3a2efdc90111a0a1fbc96f7c16234c0909&quot;
  deposit_data_root: &quot;0xa26a328f61bac695e879575ad50b38d5e643ff8df03bfd1cd7f55da6e64e9228&quot;
  eth1_data:
    deposit_root: &quot;0x556a4bfa525440a9e36ac1758db883caf80a0226ea195e91445e01621a67f875&quot;
    deposit_count: &quot;512&quot;
    block_hash: &quot;0x5d025ae62b16de0ebfc98e502cc0aa0e583efa4537d6c68273634ebbcb648749&quot;
  block_height: 513
  snapshot:
    finalized:
      - &quot;0xff99e90235f5818855c9114be9ce29d0f028bcab5032cfbcf634609b211268b1&quot;
    deposit_root: &quot;0x556a4bfa525440a9e36ac1758db883caf80a0226ea195e91445e01621a67f875&quot;
    deposit_count: 512
    execution_block_hash: &quot;0x5d025ae62b16de0ebfc98e502cc0aa0e583efa4537d6c68273634ebbcb648749&quot;
    execution_block_height: 513

</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-4881/test_cases.yaml</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-4881/test_cases.yaml</guid>
      </item>
    
      <item>
        <title></title>
        <category>/</category>
        
        <description>@import &quot;minima&quot;;
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/main.css</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/main.css</guid>
      </item>
    
      <item>
        <title></title>
        <category>/</category>
        
        <description>Creative Commons Legal Code

CC0 1.0 Universal

    CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
    LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
    ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
    INFORMATION ON AN &quot;AS-IS&quot; BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
    REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
    PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
    THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
    HEREUNDER.

Statement of Purpose

The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an &quot;owner&quot;) of an original work of
authorship and/or a database (each, a &quot;Work&quot;).

Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works (&quot;Commons&quot;) that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.

For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the &quot;Affirmer&quot;), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.

1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights (&quot;Copyright and
Related Rights&quot;). Copyright and Related Rights include, but are not
limited to, the following:

  i. the right to reproduce, adapt, distribute, perform, display,
     communicate, and translate a Work;
 ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person&apos;s image or
     likeness depicted in a Work;
 iv. rights protecting against unfair competition in regards to a Work,
     subject to the limitations in paragraph 4(a), below;
  v. rights protecting the extraction, dissemination, use and reuse of data
     in a Work;
 vi. database rights (such as those arising under Directive 96/9/EC of the
     European Parliament and of the Council of 11 March 1996 on the legal
     protection of databases, and under any national implementation
     thereof, including any amended or successor version of such
     directive); and
vii. other similar, equivalent or corresponding rights throughout the
     world based on applicable law or treaty, and any national
     implementations thereof.

2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer&apos;s Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the &quot;Waiver&quot;). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer&apos;s heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer&apos;s express Statement of Purpose.

3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer&apos;s express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer&apos;s Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
&quot;License&quot;). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer&apos;s
express Statement of Purpose.

4. Limitations and Disclaimers.

 a. No trademark or patent rights held by Affirmer are waived, abandoned,
    surrendered, licensed or otherwise affected by this document.
 b. Affirmer offers the Work as-is and makes no representations or
    warranties of any kind concerning the Work, express, implied,
    statutory or otherwise, including without limitation warranties of
    title, merchantability, fitness for a particular purpose, non
    infringement, or the absence of latent or other defects, accuracy, or
    the present or absence of errors, whether or not discoverable, all to
    the greatest extent permissible under applicable law.
 c. Affirmer disclaims responsibility for clearing rights of other persons
    that may apply to the Work or any use thereof, including without
    limitation any person&apos;s Copyright and Related Rights in the Work.
    Further, Affirmer disclaims responsibility for obtaining any necessary
    consents, permissions or other rights required for any use of the
    Work.
 d. Affirmer understands and acknowledges that Creative Commons is not a
    party to this document and has no duty or obligation with respect to
    this CC0 or use of the Work.
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/LICENSE</link>
        <guid isPermaLink="true">https://eips.ethereum.org/LICENSE</guid>
      </item>
    
      <item>
        <title>Test Vectors for EIP-1057 - ProgPow</title>
        <category>/</category>
        
        <description># Test Vectors for EIP-1057 - ProgPow

Many of these vectors are derived from [chfast/ethash](https://github.com/chfast/ethash)

## fnv1a

|          `h` |          `d` |     _result_ |
| -----------: | -----------: | -----------: |
| `0X811C9DC5` | `0XDDD0A47B` | `0XD37EE61A` |
| `0XD37EE61A` | `0XEE304846` | `0XDEDC7AD4` |
| `0XDEDC7AD4` | `0X00000000` | `0XA9155BBC` |

## kiss99

For `z`=`362436069`, `w`=`521288629`, `jsr`=`123456789`, and `jcong`=`380116160` the result of each iterative call to `kiss99` is as follows:

| _iteration_ |     _result_ |kernel
| ----------: | -----------: |
|         `1` |  `769445856` |
|         `2` |  `742012328` |
|         `3` | `2121196314` |
|         `4` | `2805620942` |
|    `100000` |  `941074834` |

## fill_mix

For `hash_seed`=`0xEE304846DDD0A47B` and `lane_id`=`0` the values stored in the `mix` array will be

&gt; ```
&gt; 0x10C02F0D, 0x99891C9E, 0xC59649A0, 0x43F0394D,
&gt; 0x24D2BAE4, 0xC4E89D4C, 0x398AD25C, 0xF5C0E467,
&gt; 0x7A3302D6, 0xE6245C6C, 0x760726D3, 0x1F322EE7,
&gt; 0x85405811, 0xC2F1E765, 0xA0EB7045, 0xDA39E821,
&gt; 0x79FC6A48, 0x089E401F, 0x8488779F, 0xD79E414F,
&gt; 0x041A826B, 0x313C0D79, 0x10125A3C, 0x3F4BDFAC,
&gt; 0xA7352F36, 0x7E70CB54, 0x3B0BB37D, 0x74A3E24A,
&gt; 0xCC37236A, 0xA442B311, 0x955AB27A, 0x6D175B7E
&gt; ```

For the same hash and `lane_id`=`13` the value in the `mix` array will be

&gt; ```
&gt; 0x4E46D05D, 0x2E77E734, 0x2C479399, 0x70712177,
&gt; 0xA75D7FF5, 0xBEF18D17, 0x8D42252E, 0x35B4FA0E,
&gt; 0x462C850A, 0x2DD2B5D5, 0x5F32B5EC, 0xED5D9EED,
&gt; 0xF9E2685E, 0x1F29DC8E, 0xA78F098B, 0x86A8687B,
&gt; 0xEA7A10E7, 0xBE732B9D, 0x4EEBCB60, 0x94DD7D97,
&gt; 0x39A425E9, 0xC0E782BF, 0xBA7B870F, 0x4823FF60,
&gt; 0xF97A5A1C, 0xB00BCAF4, 0x02D0F8C4, 0x28399214,
&gt; 0xB4CCB32D, 0x83A09132, 0x27EA8279, 0x3837DDA3
&gt; ```

## keccak_f800_progpow

Test case 1:

|          |                                                                                                                   |
| -------- | ----------------------------------------------------------------------------------------------------------------- |
| header   | `0xCCDDEEFF`, `0x8899AABB`, `0x44556677`, `0x00112233`,&lt;br&gt;`0x33221100`, `0x77665544`, `0xBBAA9988`, `0xFFEEDDCC` |
| seed     | `0x123456789ABCDEF0`                                                                                              |
| digest   | `0x00000000`, `0x00000000`, `0x00000000`, `0x00000000`,&lt;br&gt;`0x00000000`, `0x00000000`, `0x00000000`, `0x00000000` |
| _result_ | `0x464830EE`, `0x7BA4D0DD`, `0x969E1798`, `0xCEC50EB6`,&lt;br&gt;`0x7872E2EA`, `0x597E3634`, `0xE380E73D`, `0x2F89D1E6` |

Test case 2:

|          |                                                                                                                   |
| -------- | ----------------------------------------------------------------------------------------------------------------- |
| header   | `0xCCDDEEFF`, `0x8899AABB`, `0x44556677`, `0x00112233`,&lt;br&gt;`0x33221100`, `0x77665544`, `0xBBAA9988`, `0xFFEEDDCC` |
| seed     | `0xEE304846DDD0A47B`                                                                                              |
| digest   | `0x0598F111`, `0x66B48AC5`, `0x719CFF10`, `0x5F0ACF9D`,&lt;br&gt;`0x162FFA18`, `0xEF8E7905`, `0x21470C77`, `0x7D767492` |
| _result_ | `0x47CD7C5B`, `0xD9FDBE2D`, `0xAC5C895B`, `0xFF67CE8E`,&lt;br&gt;`0x6B5AEB0D`, `0xE1C6ECD2`, `0x003D3862`, `0xCE8E72C3` |

## progPowInit

For ProgPow period 600 (block 30,000) the configurations should be

src array:

&gt; `0x1A`, `0x1E`, `0x01`, `0x13`, `0x0B`, `0x15`, `0x0F`, `0x12`,
&gt; `0x03`, `0x11`, `0x1F`, `0x10`, `0x1C`, `0x04`, `0x16`, `0x17`,
&gt; `0x02`, `0x0D`, `0x1D`, `0x18`, `0x0A`, `0x0C`, `0x05`, `0x14`,
&gt; `0x07`, `0x08`, `0x0E`, `0x1B`, `0x06`, `0x19`, `0x09`, `0x00`

dst array

&gt; `0x00`, `0x04`, `0x1B`, `0x1A`, `0x0D`, `0x0F`, `0x11`, `0x07`,
&gt; `0x0E`, `0x08`, `0x09`, `0x0C`, `0x03`, `0x0A`, `0x01`, `0x0B`,
&gt; `0x06`, `0x10`, `0x1C`, `0x1F`, `0x02`, `0x13`, `0x1E`, `0x16`,
&gt; `0x1D`, `0x05`, `0x18`, `0x12`, `0x19`, `0x17`, `0x15`, `0x14`

Kiss 99 state:
`z`=`0x6535921C` `w`=`0x29345B16`, `jsr`=`0xC0DD7F78`, `jcong`=`0x1165D7EB`

## merge

| `a`          | `b`          | `r`          | _result_     | _path exercised_ |
| ------------ | ------------ | ------------ | ------------ | ---------------- |
| `0x3B0BB37D` | `0xA0212004` | `0x9BD26AB0` | `0x3CA34321` | mul/add          |
| `0x10C02F0D` | `0x870FA227` | `0xD4F45515` | `0x91C1326A` | xor/mul          |
| `0x24D2BAE4` | `0x0FFB4C9B` | `0x7FDBC2F2` | `0x2EDDD94C` | rotl/xor         |
| `0xDA39E821` | `0x089C4008` | `0x8B6CD8C3` | `0x8A81E396` | rotr/xor         |

## math

| `a`          | `b`          | `r`          | _result_     | _operation exercised_   |
| ------------ | ------------ | ------------ | ------------ | ----------------------- |
| `0x8626BB1F` | `0xBBDFBC4E` | `0x883E5B49` | `0x4206776D` | add                     |
| `0x3F4BDFAC` | `0xD79E414F` | `0x36B71236` | `0x4C5CB214` | mul                     |
| `0x6D175B7E` | `0xC4E89D4C` | `0x944ECABB` | `0x53E9023F` | mul_hi32                |
| `0x2EDDD94C` | `0x7E70CB54` | `0x3F472A85` | `0x2EDDD94C` | min                     |
| `0x61AE0E62` | `0xe0596b32` | `0x3F472A85` | `0x61AE0E62` | min again (unsigned)    |
| `0x8A81E396` | `0x3F4BDFAC` | `0xCEC46E67` | `0x1E3968A8` | rotl32                  |
| `0x8A81E396` | `0x7E70CB54` | `0xDBE71FF7` | `0x1E3968A8` | rotr32                  |
| `0xA7352F36` | `0xA0EB7045` | `0x59E7B9D8` | `0xA0212004` | bitwise and             |
| `0xC89805AF` | `0x64291E2F` | `0x1BDC84A9` | `0xECB91FAF` | bitwise or              |
| `0x760726D3` | `0x79FC6A48` | `0xC675CAC5` | `0x0FFB4C9B` | bitwise xor             |
| `0x75551D43` | `0x3383BA34` | `0x2863AD31` | `0x00000003` | clz (leading zeros)     |
| `0xEA260841` | `0xE92C44B7` | `0xF83FFE7D` | `0x0000001B` | popcount (number of 1s) |

## progPowLoop

For the first loop iteration of block 30,000 the seed to use for `fill_mix`
would be `0xEE304846DDD0A47B`. A two dimensional `mix` array should be created
passing the rows into `fill_mix` with the column number as the loop argument.

The state of the mix array after the call to `progPowLoop` for block 30,000,
loop 1 are as follows.

`mix[0]` -

&gt; ```
&gt; 0x40E09E9C, 0x967A7DF0, 0x8626BB1F, 0x12C2392F,
&gt; 0xA21D8305, 0x44C2702E, 0x94C93945, 0x6B66B158,
&gt; 0x0CF00FAA, 0x26F5E6B5, 0x36EC0134, 0xC89805AF,
&gt; 0x58118540, 0x8617DC4D, 0xC759F486, 0x8A81E396,
&gt; 0x22443D4D, 0x64291E2F, 0x1998AB7F, 0x11C0FBBB,
&gt; 0xBEA9C139, 0x82D1E47E, 0x7ED3E850, 0x2F81531A,
&gt; 0xBBDFBC4E, 0xF58AEE4D, 0x3CA34321, 0x357BD48A,
&gt; 0x2F9C8B5D, 0x2319B193, 0x2856BB38, 0x2E3C33E6
&gt; ```

`mix[1]` -

&gt; ```
&gt; 0x4EB8A8F9, 0xD978BF17, 0x7D5074D4, 0x7A092D5D,
&gt; 0x8682D1BE, 0xC3D2941C, 0xF1A1A38B, 0x54BB6D34,
&gt; 0x2F0FB257, 0xB5464B50, 0x40927B67, 0xBB92A7E1,
&gt; 0x1305A517, 0xE06C6765, 0xA75FD647, 0x9F232D6E,
&gt; 0x0D9213ED, 0x8884671D, 0x54352B96, 0x6772E58E,
&gt; 0x1B8120C9, 0x179F3CFB, 0x116FFC82, 0x6D019BCE,
&gt; 0x1C26A750, 0x89716638, 0x02BEB948, 0x2E0AD5CE,
&gt; 0x7FA915B2, 0x93024F2F, 0x2F58032E, 0xF02E550C
&gt; ```

`mix[2]` -

&gt; ```
&gt; 0x008FF9BD, 0xC41F9802, 0x2E36FDC8, 0x9FBA2A91,
&gt; 0x0A921670, 0x231308E6, 0xEF09A56E, 0x9657A64A,
&gt; 0xF67723FE, 0x963DCD40, 0x354CBFDB, 0x57C07B9A,
&gt; 0x06AF5B40, 0xBA5DE5A6, 0xDA5AAE7B, 0x9F8A5E4B,
&gt; 0x7D6AFC9A, 0xE4783F78, 0x89B24946, 0x5EE94228,
&gt; 0xA209DAAA, 0xDCC27C64, 0x3366FBED, 0x0FEFB673,
&gt; 0x0FC205E3, 0xB61515B2, 0x70A45E9B, 0xBB225E5D,
&gt; 0xB8C38EA0, 0xE01DE9B4, 0x866FAA5B, 0x1A125220
&gt; ```

`mix[3]` -

&gt; ```
&gt; 0xE5F9C5CC, 0x6F75CFA2, 0xE0F50924, 0xE7B4F5EF,
&gt; 0x779B903D, 0x5F068253, 0x05FF68E5, 0x39348653,
&gt; 0x654B89E4, 0x0559769E, 0xA3D46B93, 0xD084454D,
&gt; 0xCFC5CF7D, 0x8C11D8E4, 0x795BDB59, 0xD9E03113,
&gt; 0xBAE8C355, 0x12B63814, 0x4046A018, 0xA269A32E,
&gt; 0x54A57C4B, 0x2ED1065B, 0xB69A2C76, 0x4AEF0950,
&gt; 0x6C2D187B, 0x8252FAE7, 0x3E9C0ED2, 0x26E47B15,
&gt; 0xFEFB48E3, 0xDA088C7F, 0xA82B0379, 0xA49C6D86
&gt; ```

`mix[4]` -

&gt; ```
&gt; 0xB926334C, 0x686A29AF, 0xD9E2EF15, 0x1C8A2D39,
&gt; 0x307ED4F4, 0x2ABB1DB6, 0xD6F95128, 0xDFCA05F8,
&gt; 0x904D9472, 0xEC09E200, 0x7143F47F, 0xEE488438,
&gt; 0xFCA48DA8, 0xA64C7DD4, 0xC4AE9A30, 0xEBA30BC9,
&gt; 0xB02630BF, 0xD1DF40CC, 0x4DFE8B7B, 0x205C97B3,
&gt; 0xE40376F8, 0x2491117E, 0x34984321, 0xA01546A7,
&gt; 0xB254F2F9, 0xC78A7C25, 0xFFC615E2, 0x5839FC88,
&gt; 0x2A04DF6C, 0xC02A9A8A, 0x39238EAD, 0x7139060C
&gt; ```

`mix[5]` -

&gt; ```
&gt; 0xC416E54B, 0x64AD1C57, 0xBF7CBA55, 0x176F714E,
&gt; 0xBE733426, 0x995C4132, 0x5F50F779, 0x0F76FDF3,
&gt; 0x526F7870, 0xE56A1A8A, 0xDCEB677E, 0xD471CC19,
&gt; 0xA9ED60E4, 0x145E807F, 0x8D652E92, 0x80E8116F,
&gt; 0xFF1A37EB, 0x1E0C49A1, 0x59D756DA, 0x39A8E761,
&gt; 0x2F0F646F, 0x43F41278, 0x88CC48DA, 0x8FDFF7A4,
&gt; 0x9AEACA2E, 0x59E7808C, 0x7F72E46B, 0xCA572333,
&gt; 0xC6029C88, 0x7736E592, 0xF1338231, 0x262B2C7F
&gt; ```

`mix[6]` -

&gt; ```
&gt; 0x3C554151, 0x70999423, 0x64BB49A8, 0xF9EBE9E9,
&gt; 0x7D9C28CF, 0x23EE7659, 0xD6504FCF, 0x1C58C2A1,
&gt; 0x62B9C627, 0x680AE248, 0xF196A153, 0x2A3C345A,
&gt; 0x860E6EB2, 0x266D2652, 0x3C9F2420, 0xF790A538,
&gt; 0x710A5523, 0xBEA2603A, 0x1C1CC272, 0xF91D482A,
&gt; 0x1CA19931, 0x7A80ED37, 0x9572513D, 0x376F1CFE,
&gt; 0xE57C1264, 0xE47BF931, 0xC7310E05, 0x7866CC9E,
&gt; 0xC676BBD5, 0x4C167FEB, 0x0FE03D2B, 0x46C6D26C
&gt; ```

`mix[7]` -

&gt; ```
&gt; 0x3395F65A, 0x7142A5B1, 0x97780661, 0xE5EE45B8,
&gt; 0xCD9FDC42, 0x25BF044C, 0x0350F81B, 0x55D50703,
&gt; 0xA8CB893E, 0xEE795201, 0xC2D6E598, 0xC2AC2D7A,
&gt; 0xD2E81716, 0xAD876790, 0x0F3339C7, 0xEEC31E01,
&gt; 0xA293ABF6, 0x28AE317D, 0x44A7AC05, 0xBEBA1C5E,
&gt; 0x325ED29E, 0x4344131E, 0x921CD8DD, 0x08AB9E0B,
&gt; 0xC18E66A6, 0x87E6BCA3, 0x24CE82AE, 0xC910B4F1,
&gt; 0x9E513EC0, 0xA1B8CB76, 0xF0455815, 0x36BC0DCF
&gt; ```

`mix[8]` -

&gt; ```
&gt; 0x0117C85F, 0xE018F2C6, 0x416C897D, 0x9D288A0F,
&gt; 0x2AA9EA93, 0x5A6D3CEA, 0xAA99B726, 0x0A42DAB7,
&gt; 0x72F6EA4A, 0x1DB074E6, 0x2E2A606C, 0xAC5D509B,
&gt; 0x53F13E85, 0x1D44B521, 0x24234C42, 0xAD5BAD70,
&gt; 0xAB2DA791, 0x6479546A, 0xD27B3771, 0xBB0A09DD,
&gt; 0x6D3C8056, 0x96572D4B, 0x52DB6535, 0x3D242BC1,
&gt; 0xF37D7C7A, 0xA60F7111, 0x59B59667, 0xF28635B0,
&gt; 0xC2A8F9F5, 0x7CFB9CCB, 0xDF8697AA, 0xA3260D94
&gt; ```

`mix[9]` -

&gt; ```
&gt; 0xA387FC4B, 0xC757D3A0, 0xA584E879, 0xB0A1EC29,
&gt; 0x82CB2EC3, 0x6BF33664, 0x41FECC42, 0xF60C2AC5,
&gt; 0xEA250BE5, 0x42BE9F33, 0x9227B0B3, 0x9080A6AB,
&gt; 0xAF193598, 0xC708BC8A, 0x020CDEDB, 0x7FA2F773,
&gt; 0x4338E670, 0x069E0242, 0x5AD87326, 0xD7A87124,
&gt; 0x220D5C46, 0x26D3400D, 0x4899D1EE, 0x90EAD2F6,
&gt; 0xFA3F1F74, 0x9C5A5D58, 0xAE20567C, 0x424B690D,
&gt; 0xC9A4057A, 0x9F2A5CD1, 0xAA33CD5F, 0x18F58C00
&gt; ```

`mix[10]` -

&gt; ```
&gt; 0xEAFE893C, 0x1ABB2971, 0x29803BB3, 0x5BC2F71F,
&gt; 0x619DAFAD, 0xD9CFEFB6, 0xB4FEFAB5, 0x5EB249EC,
&gt; 0x1A6E2B3A, 0xFB05DD28, 0xDCB33C2E, 0x630BB8AE,
&gt; 0x43463B39, 0x3BD2F552, 0xFB20C0A2, 0x3383BA34,
&gt; 0x2E9C1A99, 0x60A949B2, 0x861372AB, 0xC149D929,
&gt; 0xA77A0A93, 0xE0CEE0D9, 0x791E7E82, 0x66A8D75A,
&gt; 0x44D1845F, 0xE534DC4A, 0x2C7DD20C, 0xEEDAB329,
&gt; 0x3209FE2A, 0x0C0406BC, 0xD6D4BD2A, 0x5FDB13CC
&gt; ```

`mix[11]` -

&gt; ```
&gt; 0x2520ABB3, 0xCD942485, 0x9A2929BC, 0x0E10F18C,
&gt; 0xDFB1815E, 0x8BEF05A3, 0x531A8837, 0x668838E4,
&gt; 0xBACCE200, 0x003F85C2, 0x56226F05, 0xC2233173,
&gt; 0x2F39A0D9, 0xF4466D0D, 0x0B9E686C, 0x82C69BDA,
&gt; 0x0C8A8CD6, 0xA93F3001, 0x36A65EC1, 0x40CCFD7A,
&gt; 0x84484E23, 0xF0896D45, 0x06D9F760, 0x6559142C,
&gt; 0x9FFE2E88, 0x9593DC89, 0x89C9E3B9, 0x33285F41,
&gt; 0x16F636C8, 0xA08169C7, 0xA5E1C956, 0xC22CCF52
&gt; ```

`mix[12]` -

&gt; ```
&gt; 0xDC3B8CAA, 0xC6941197, 0x9969D596, 0x46453D3E,
&gt; 0x568EAFEA, 0x5B823345, 0xDE606E8E, 0x7523C86D,
&gt; 0x0EDAF441, 0x00C3D848, 0xAE5BAB99, 0xD705B9EE,
&gt; 0x54B49E3D, 0xF364A6A4, 0x42C55975, 0xFE41EED5,
&gt; 0xAD46170F, 0xAABE4868, 0x270379F9, 0xD33D0D7C,
&gt; 0xF39C476C, 0xA449118E, 0x71BCC1E4, 0x5E300E77,
&gt; 0x1CACD489, 0x4D82FABD, 0x090F9F80, 0xB2DB9626,
&gt; 0xE12A973B, 0x1B77460C, 0xD25F89F5, 0x5753612E
&gt; ```

`mix[13]` -

&gt; ```
&gt; 0x042D951C, 0x38833AA7, 0xBEA9894D, 0x7AE7F381,
&gt; 0x42DB6723, 0x1FB0294F, 0x41452A28, 0xA7A97B9C,
&gt; 0x228AA7EA, 0x781A7420, 0x4589736D, 0xB3C19349,
&gt; 0x685EF9E6, 0xB4987DF6, 0xC9C3B188, 0x2DCA6A03,
&gt; 0xE89A6D3D, 0x50EF7CF5, 0xF6274868, 0x8AA22824,
&gt; 0x980FFDE3, 0xD4A6CB4E, 0x06FF9E1A, 0xBADB6DF5,
&gt; 0xEDE3ADF3, 0xC9CF45F6, 0xFDFA194C, 0xAF076AA8,
&gt; 0x7B876CEA, 0xB0C89575, 0x35A72155, 0x6CFDFC06
&gt; ```

`mix[14]` -

&gt; ```
&gt; 0x0E3E28C8, 0xEC329DEC, 0x06D0A1D1, 0xF95ABEF8,
&gt; 0x168DCF28, 0xDD7714C1, 0x769C119E, 0xA5530A7D,
&gt; 0x1EEACB59, 0x30FD21BB, 0x082A3691, 0x1C4C9BCA,
&gt; 0x420F27DE, 0xA8FDA3AE, 0xE182142E, 0x5102F0FF,
&gt; 0x15B82277, 0x120C3217, 0x7BE714ED, 0xA251DCD5,
&gt; 0x6FB4F831, 0xB71D7B32, 0xD5F7A04A, 0x763E1A20,
&gt; 0x38E68B0C, 0xBB5A4121, 0x9340BF06, 0x948B03F8,
&gt; 0xE71BF17B, 0x1BB5F06B, 0x26F2A200, 0x5F28C415
&gt; ```

`mix[15]` -

&gt; ```
&gt; 0xC818CD64, 0xBC910343, 0xB18B7776, 0x7182DEBA,
&gt; 0x9DB319EE, 0x9AE7F32F, 0x3CA9F8B5, 0xC63F48ED,
&gt; 0x8321533A, 0x059C96B1, 0x8DCDA60A, 0x75B6C1D1,
&gt; 0xC3406B57, 0x3DFE9E9B, 0xC01E1FD7, 0xC4643218,
&gt; 0x6873F0BA, 0x8ABD36B9, 0xA74D0CBD, 0x8A637118,
&gt; 0x6916416C, 0xB6E3A8DD, 0xB68DD4FA, 0xFBD543EE,
&gt; 0x56F05592, 0x33D6DB82, 0x58D0A7DD, 0x18630C6E,
&gt; 0xB33749CA, 0x5D2E87F7, 0x0F3C39DB, 0x3CAE9895
&gt; ```

## progPowHash

### 0.9.2
[Machine-readable data](https://github.com/ethereum/EIPs/blob/ad4e73f239d53d72a21cfd8fdc89dc81eb9d2688/assets/eip-1057/test-vectors-0.9.3.json)

Block 30000:

- `prog_seed` - 600
- `nonce` - `123456789abcdef0`
- `header` - `ffeeddccbbaa9988776655443322110000112233445566778899aabbccddeeff`
- `mix_hash` - `11f19805c58ab46610ff9c719dcf0a5f18fa2f1605798eef770c47219274767d`
- `final_hash` - `5b7ccd472dbefdd95b895cac8ece67ff0deb5a6bd2ecc6e162383d00c3728ece`

Block 0:

- `prog_seed` - 0
- `nonce` - `0000000000000000`
- `header` - `0000000000000000000000000000000000000000000000000000000000000000`
- `mix_hash` - `faeb1be51075b03a4ff44b335067951ead07a3b078539ace76fd56fc410557a3`
- `final_hash` - `63155f732f2bf556967f906155b510c917e48e99685ead76ea83f4eca03ab12b`

Block 49:

- `prog_seed` - 0
- `nonce` - `0000000006ff2c47`
- `header` - `63155f732f2bf556967f906155b510c917e48e99685ead76ea83f4eca03ab12b`
- `mix_hash` - `c789c1180f890ec555ff42042913465481e8e6bc512cb981e1c1108dc3f2227d`
- `final_hash` - `9e7248f20914913a73d80a70174c331b1d34f260535ac3631d770e656b5dd922`

Block 50:

- `prog_seed` - 1
- `nonce` - `00000000076e482e`
- `header` - `9e7248f20914913a73d80a70174c331b1d34f260535ac3631d770e656b5dd922`
- `mix_hash` - `c7340542c2a06b3a7dc7222635f7cd402abf8b528ae971ddac6bbe2b0c7cb518`
- `final_hash` - `de37e1824c86d35d154cf65a88de6d9286aec4f7f10c3fc9f0fa1bcc2687188d`

Block 99:

- `prog_seed` - 1
- `nonce` - `000000003917afab`
- `header` - `de37e1824c86d35d154cf65a88de6d9286aec4f7f10c3fc9f0fa1bcc2687188d`
- `mix_hash` - `f5e60b2c5bfddd136167a30cbc3c8dbdbd15a512257dee7964e0bc6daa9f8ba7`
- `final_hash` - `ac7b55e801511b77e11d52e9599206101550144525b5679f2dab19386f23dcce`

Block 29,950:

- `prog_seed` - 599
- `nonce` - `005d409dbc23a62a`
- `header` - `ac7b55e801511b77e11d52e9599206101550144525b5679f2dab19386f23dcce`
- `mix_hash` - `07393d15805eb08ee6fc6cb3ad4ad1010533bd0ff92d6006850246829f18fd6e`
- `final_hash` - `e43d7e0bdc8a4a3f6e291a5ed790b9fa1a0948a2b9e33c844888690847de19f5`

Block 29,999:

- `prog_seed` - 599
- `nonce` - `005db5fa4c2a3d03`
- `header` - `e43d7e0bdc8a4a3f6e291a5ed790b9fa1a0948a2b9e33c844888690847de19f5`
- `mix_hash` - `7551bddf977491da2f6cfc1679299544b23483e8f8ee0931c4c16a796558a0b8`
- `final_hash` - `d34519f72c97cae8892c277776259db3320820cb5279a299d0ef1e155e5c6454`

Block 30,000:

- `prog_seed` - 600
- `nonce` - `005db8607994ff30`
- `header` - `d34519f72c97cae8892c277776259db3320820cb5279a299d0ef1e155e5c6454`
- `mix_hash` - `f1c2c7c32266af9635462e6ce1c98ebe4e7e3ecab7a38aaabfbf2e731e0fbff4`
- `final_hash` - `8b6ce5da0b06d18db7bd8492d9e5717f8b53e7e098d9fef7886d58a6e913ef64`

Block 30,049:

- `prog_seed` - 600
- `nonce` - `005e2e215a8ca2e7`
- `header` - `8b6ce5da0b06d18db7bd8492d9e5717f8b53e7e098d9fef7886d58a6e913ef64`
- `mix_hash` - `57fe6a9fbf920b4e91deeb66cb0efa971e08229d1a160330e08da54af0689add`
- `final_hash` - `c2c46173481b9ced61123d2e293b42ede5a1b323210eb2a684df0874ffe09047`

Block 30,050:

- `prog_seed` - 601
- `nonce` - `005e30899481055e`
- `header` - `c2c46173481b9ced61123d2e293b42ede5a1b323210eb2a684df0874ffe09047`
- `mix_hash` - `ba30c61cc5a2c74a5ecaf505965140a08f24a296d687e78720f0b48baf712f2d`
- `final_hash` - `ea42197eb2ba79c63cb5e655b8b1f612c5f08aae1a49ff236795a3516d87bc71`

Block 30,099:

- `prog_seed` - 601
- `nonce` - `005ea6aef136f88b`
- `header` - `ea42197eb2ba79c63cb5e655b8b1f612c5f08aae1a49ff236795a3516d87bc71`
- `mix_hash` - `cfd5e46048cd133d40f261fe8704e51d3f497fc14203ac6a9ef6a0841780b1cd`
- `final_hash` - `49e15ba4bf501ce8fe8876101c808e24c69a859be15de554bf85dbc095491bd6`

Block 59,950:

- `prog_seed` - 1,199
- `nonce` - `02ebe0503bd7b1da`
- `header` - `49e15ba4bf501ce8fe8876101c808e24c69a859be15de554bf85dbc095491bd6`
- `mix_hash` - `21511fbaa31fb9f5fc4998a754e97b3083a866f4de86fa7500a633346f56d773`
- `final_hash` - `f5c50ba5c0d6210ddb16250ec3efda178de857b2b1703d8d5403bd0f848e19cf`

Block 59,999:

- `prog_seed` - 1,199
- `nonce` - `02edb6275bd221e3`
- `header` - `f5c50ba5c0d6210ddb16250ec3efda178de857b2b1703d8d5403bd0f848e19cf`
- `mix_hash` - `653eda37d337e39d311d22be9bbd3458d3abee4e643bee4a7280a6d08106ef98`
- `final_hash` - `341562d10d4afb706ec2c8d5537cb0c810de02b4ebb0a0eea5ae335af6fb2e88`

Block 10,000,000:

- `prog_seed` - 200,000
- `nonce` - `005e30899481055e`
- `header` - `efda178de857b2b1703d8d5403bd0f848e19cff5c50ba5c0d6210ddb16250ec3`
- `mix_hash` - `b2403f56c426177856eaf0eedd707c86ae78a432b9169c3689a67058fcf2a848`
- `final_hash` - `206aee640c0fd21473d5cc3654d63c80442d9e2dfa676d2801d3ec1fbab38a6d`

Block 100,000,000:

- `prog_seed` - 2,000,000
- `nonce` - `02abe0589481055e`
- `header` - `49e15ba4bf501ce8fe88765403bd0f848e19cff5c50ba5c0d6210ddb16250ec3`
- `mix_hash` - `ac452084d6f4e6eacf4282ad58dbd4ce7ef2653fb5e6b5c877f56928c907432a`
- `final_hash` - `b879f84923e71b812ef5a42ece0b5b9366c31cab218f40afe65f8a2cae448a6f`

### 0.9.3
[Machine-readable data](https://github.com/ethereum/EIPs/blob/ad4e73f239d53d72a21cfd8fdc89dc81eb9d2688/assets/eip-1057/test-vectors-0.9.3.json)
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-1057/test-vectors</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-1057/test-vectors</guid>
      </item>
    
      <item>
        <title>Contributors</title>
        <category>/</category>
        
        <description>## Contributors

* Andrew Redden (@androolloyd)
* Patrick Gallagher (@pi0neerpat)
* Leo Alt (@leonardoalt)
* Santiago Palladino (@spalladino)
* William Entriken (@fulldecent)
* Gonçalo Sá (@GNSPS)
* Brian Burns (@Droopy78)
* Ramesh Nair(@hiddentao)
* Jules Goddard (@JulesGoddard)
* Micah Zoltu (@MicahZoltu)
* Sam Wilson (@SamWilsn)
* William Morriss (@wjmelements)
* Zachary (@Remscar)
* Patrick Collins (@PatrickAlphaC)
* Hadrien Croubois (@Amxx)
* (@farreldarian)
* Kelvin Schoofs (@SchoofsKelvin)
* (@0xpApaSmURf)
* Nathan Sala (@nataouze)
* Anders Torbjornsen (@anders-torbjornsen)
* (@Pandapip1)
* Xavier Iturralde (@xibot)
* Coder Dan (@cinnabarhorse)
* GldnXross (@gldnxross)
* Christian Reitwiessner (@chriseth)
* Timidan (@Timidan)
* cyotee doge (@cyotee)
* Glory Praise Emmanuel (@emmaglorypraise)
* Ed Zynda (@ezynda3)
* Arthur Nesbitt (@nesbitta)
* Cliff Hall (@cliffhall)
* Tyler Scott Ward (@tylerscottward)
* Troy Murray (@DannyDesert)
* Dan Finlay (@danfinlay)
* Theodore Georgas (@tgeorgas)
* Aditya Palepu (@apalepu23)
* Ronan Sandford (@wighawag)
* Markus Waas (@gorgos)
* Blessing Emah (@BlessingEmah)
* Andrew Edwards
* Ashwin Yardi (@ashwinYardi)
* Marco Castignoli (@marcocastignoli)
* Blaine Bublitz (@phated)
* Bearded
* Nick Barry (@ItsNickBarry)
* (@Vectorized)
* Rachit Srivastava (@rachit2501)
* Neeraj Kashyap (@zomglings)
* Zac Denham (@zdenham)
* JA (@ubinatus)
* Carter Carlson (@cartercarlson)
* James Sayer (@jamessayer98)
* Arpit Temani (@temaniarpit27)
* Parv Garg (@parv3213)
* Publius (@publiuss)
* Guy Hance (@guyhance)
* Payn (@Ayuilos)
* Luis Schliesske (@gitpusha)
* Hilmar Orth (@hilmarx)
* Matthieu Marie Joseph (@Gauddel)
* David Uzochukwu (@davidpius95)
* TJ VanSlooten (@tjvsx)
* 0xFluffyBeard (@0xFluffyBeard)
* Florian Pfeiffer (@FlorianPfeifferKanaloaNetwork)
* Mick de Graaf(@MickdeGraaf)
* Alessio Delmonti (@Alexintosh)
* Neirenoir (@Neirenoir)
* Evert Kors (@Evert0x)
* Patrick Kim (@pakim249CAL)
* Ersan YAKIT (@ersanyakit)
* Matias Arazi (@MatiArazi)
* Lucas Grasso Ramos (@LucasGrasso)
* Nikolay Angelov (@NikolayAngelov)
* John Reynolds (@gweiworld)
* Viraz Malhotra (@viraj124)
* Kemal Emre Ballı (@emrbli)
* Zack Peng (@zackpeng)
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-2535/Contributors</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-2535/Contributors</guid>
      </item>
    
      <item>
        <title>Set of test vectors to perform benchmarking of EIP-2537</title>
        <category>/</category>
        
        <description># Set of test vectors to perform benchmarking of EIP-2537

## Inlined vectors

Here one can find inputs (encoded with ABI from the main spec spec) that can be considered &quot;worst cases&quot; for &quot;double-and-add&quot; multiplication algorithm, and also some cases for pairing call. Those are purely for convenience of initial benchmarking of the full ABI without manual test generation. 

```
G1 addition example input = 
0000000000000000000000000000000012196c5a43d69224d8713389285f26b98f86ee910ab3dd668e413738282003cc5b7357af9a7af54bb713d62255e80f560000000000000000000000000000000006ba8102bfbeea4416b710c73e8cce3032c31c6269c44906f8ac4f7874ce99fb17559992486528963884ce429a992fee000000000000000000000000000000000001101098f5c39893765766af4512a0c74e1bb89bc7e6fdf14e3e7337d257cc0f94658179d83320b99f31ff94cd2bac0000000000000000000000000000000003e1a9f9f44ca2cdab4f43a1a3ee3470fdf90b2fc228eb3b709fcd72f014838ac82a6d797aeefed9a0804b22ed1ce8f7
G2 addition example input = 
0000000000000000000000000000000018c0ada6351b70661f053365deae56910798bd2ace6e2bf6ba4192d1a229967f6af6ca1c9a8a11ebc0a232344ee0f6d6000000000000000000000000000000000cc70a587f4652039d8117b6103858adcd9728f6aebe230578389a62da0042b7623b1c0436734f463cfdd187d20903240000000000000000000000000000000009f50bd7beedb23328818f9ffdafdb6da6a4dd80c5a9048ab8b154df3cad938ccede829f1156f769d9e149791e8e0cd900000000000000000000000000000000079ba50d2511631b20b6d6f3841e616e9d11b68ec3368cd60129d9d4787ab56c4e9145a38927e51c9cd6271d493d938800000000000000000000000000000000192fa5d8732ff9f38e0b1cf12eadfd2608f0c7a39aced7746837833ae253bb57ef9c0d98a4b69eeb2950901917e99d1e0000000000000000000000000000000009aeb10c372b5ef1010675c6a4762fda33636489c23b581c75220589afbc0cc46249f921eea02dd1b761e036ffdbae220000000000000000000000000000000002d225447600d49f932b9dd3ca1e6959697aa603e74d8666681a2dca8160c3857668ae074440366619eb8920256c4e4a00000000000000000000000000000000174882cdd3551e0ce6178861ff83e195fecbcffd53a67b6f10b4431e423e28a480327febe70276036f60bb9c99cf7633
G1 mul double and add worst case = 
0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
G2 mul double and add worst case = 
00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79beffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
Pairing case for 2 pairs = 
0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be
Pairing case for 4 pairs = 
0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be
Pairing case for 6 pairs = 
0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be
```
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-2537/bench_vectors</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-2537/bench_vectors</guid>
      </item>
    
      <item>
        <title>Fast subgroup checks used by EIP-2537</title>
        <category>/</category>
        
        <description># Fast subgroup checks used by EIP-2537

### Fields and Groups

Field Fp is defined as the finite field of size `p` with elements represented as integers between 0 and p-1 (both inclusive). 

Field Fp2 is defined as `Fp[X]/(X^2-nr2)` with elements  `el = c0 + c1 * v`, where `v` is the formal square root of `nr2` represented as integer pairs `(c0,c1)`.
 
Group G1 is defined as a set of Fp pairs (points) `(x,y)` such that either `(x,y)` is  `(0,0)` or `x,y` satisfy the curve Fp equation.

Group G2 is defined as a set of Fp2 pairs (points) `(x&apos;, y&apos;)` such that either `(x&apos;, y&apos;)` is `(0,0)` or `(x&apos;, y&apos;)` satisfy the curve Fp2 equation.


## Curve parameters

The set of parameters used by fast subgroup checks:

```
|x| (seed) = 15132376222941642752
x is negative = true
Cube root of unity modulo p - Beta = 793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350
r = 4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437 * v
s = 2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530 + 1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257 * v
```

## Helper function to compute the conjugate over Fp2 - `conjugate`

`conjugate(c0 + c1 * v) := c0 - c1 * v`

## G1 endomorphism - `phi`

The endomorphism `phi` transform the point from `(x,y)` to `(Beta*x,y)` where `Beta` is a precomputed cube root of unity modulo `p` given above in parameters sections:

`phi((x,y)) := (Beta*x,y)`

## G2 endomorphism - `psi`

`psi((x,y)) := (conjugate(x)*r,conjugate(y)*s)`

# The G1 case

Before accepting a point `P` as input that purports to be a member of G1 subject the input to the following endomorphism test: `phi(P) + x^2*P = 0`


# The G2 case

Before accepting a point `P` as input that purports to be a member of G2 subject the input to the following endomorphism test: `psi(P) + x*P = 0`

# Resources

* https://eprint.iacr.org/2021/1130.pdf, sec.4
* https://eprint.iacr.org/2022/352.pdf, sec. 4.2
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-2537/fast_subgroup_checks</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-2537/fast_subgroup_checks</guid>
      </item>
    
      <item>
        <title>Field element to curve point mapping used by EIP 2537</title>
        <category>/</category>
        
        <description># Field element to curve point mapping used by EIP 2537

For a BLS12-381 implemented by EIP-2537 a short Weierstrass curve equation y^2 = x^3 + A * x + B has a property that a product AB = 0, so to implement a mapping function two step algorithms is performed:
- Field element is mapped to a some other curve with AB != 0
- Isogeny is applied to one to one map a point of this other curve to a point on BLS12-381
- Cofactor is cleared for a point now on BLS12-381

Below we describe generic algorithms for mapping and isogeny application, and later on give concrete parameters for the algorithms

## Helper function to clear a cofactor

Later on we use a helper function to clear a cofactor of the curve point. It&apos;s implemented as

~~~
    clear_cofactor(P) := h_eff * P
~~~

where values of h_eff are given below in parameters sections

## Simplified SWU for AB != 0

The function map\_to\_curve\_simple\_swu(u) implements a simplification
of the Shallue-van de Woestijne-Ulas mapping described by Brier et
al., which they call the &quot;simplified SWU&quot; map. Wahby and Boneh generalize and optimize this mapping.

Preconditions: A Weierstrass curve y^2 = g(x) x^3 + A * x + B where A != 0 and B != 0.

Constants:

- A and B, the parameters of the Weierstrass curve.

- Z, an element of F meeting the below criteria.
  The criteria are:
  1. Z is non-square in F,
  2. Z != -1 in F,
  3. the polynomial g(x) - Z is irreducible over F, and
  4. g(B / (Z * A)) is square in F.

Sign of y: Inputs u and -u give the same x-coordinate.
Thus, we set sgn0(y) == sgn0(u).

Exceptions: The exceptional cases are values of u such that
Z^2 * u^4 + Z * u^2 == 0. This includes u == 0, and may include
other values depending on Z. Implementations must detect
this case and set x1 = B / (Z * A), which guarantees that g(x1)
is square by the condition on Z given above.

Operations:

~~~
1. tv1 = inv0(Z^2 * u^4 + Z * u^2)
2.  x1 = (-B / A) * (1 + tv1)
3.  If tv1 == 0, set x1 = B / (Z * A)
4. gx1 = x1^3 + A * x1 + B
5.  x2 = Z * u^2 * x1
6. gx2 = x2^3 + A * x2 + B
7.  If is_square(gx1), set x = x1 and y = sqrt(gx1)
8.  Else set x = x2 and y = sqrt(gx2)
9.  If sgn0(u) != sgn0(y), set y = -y
10. return (x, y)
~~~

## Simplified SWU for AB == 0

Wahby and Boneh show how to adapt the simplified SWU mapping to
Weierstrass curves having A == 0 or B == 0, which the mapping of
simple SWU does not support.

This method requires finding another elliptic curve E&apos; given by the equation

~~~
    y&apos;^2 = g&apos;(x&apos;) = x&apos;^3 + A&apos; * x&apos; + B&apos;
~~~

that is isogenous to E and has A&apos; != 0 and B&apos; != 0.
This isogeny defines a map iso\_map(x&apos;, y&apos;) given by a pair of rational functions.
iso\_map takes as input a point on E&apos; and produces as output a point on E.

Once E&apos; and iso\_map are identified, this mapping works as follows: on input
u, first apply the simplified SWU mapping to get a point on E&apos;, then apply
the isogeny map to that point to get a point on E.

Note that iso\_map is a group homomorphism, meaning that point addition
commutes with iso\_map.
Thus, when using this mapping in the hash\_to\_curve construction of {{roadmap}},
one can effect a small optimization by first mapping u0 and u1 to E&apos;, adding
the resulting points on E&apos;, and then applying iso\_map to the sum.
This gives the same result while requiring only one evaluation of iso\_map.

Preconditions: An elliptic curve E&apos; with A&apos; != 0 and B&apos; != 0 that is
isogenous to the target curve E with isogeny map iso\_map from
E&apos; to E.

So the full mapping algorithm looks as:

- map\_to\_curve\_simple\_swu is the simple SWU mapping to E&apos;
- iso\_map is the isogeny map from E&apos; to E

Sign of y: for this map, the sign is determined by map\_to\_curve\_simple\_swu.
No further sign adjustments are necessary.

Exceptions: map\_to\_curve\_simple\_swu handles its exceptional cases.
Exceptional cases of iso\_map are inputs that cause the denominator of
either rational function to evaluate to zero; such cases MUST return the
identity point on E.

## Full algorithm restated

~~~
1. (x&apos;, y&apos;) = map_to_curve_simple_swu(u)    # (x&apos;, y&apos;) is on E&apos;
2.   (x, y) = iso_map(x&apos;, y&apos;)               # (x, y) is on E
3. (x, y) = clear_cofactor((x, y))          # clears cofactor for point (x, y) on E
4. return (x, y)
~~~

## Parameters for EIP-2537

### Fp-to-G1 mapping


- Z: 11
- E&apos;: y&apos;^2 = x&apos;^3 + A&apos; * x&apos; + B&apos;, where
  - A&apos; = 0x144698a3b8e9433d693a02c96d4982b0ea985383ee66a8d8e8981aefd881ac98936f8da0e0f97f5cf428082d584c1d
  - B&apos; = 0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070a0b9c14fcef35ef55a23215a316ceaa5d1cc48e98e172be0
- h\_eff: 0xd201000000010001

The 11-isogeny map from (x&apos;, y&apos;) on E&apos; to (x, y) on E is given by the following rational functions:

- x = x\_num / x\_den, where
  - x\_num = k\_(1,11) * x&apos;^11 + k\_(1,10) * x&apos;^10 + k\_(1,9) * x&apos;^9 + ... + k\_(1,0)
  - x\_den = x&apos;^10 + k\_(2,9) * x&apos;^9 + k\_(2,8) * x&apos;^8 + ... + k\_(2,0)

- y = y&apos; * y\_num / y\_den, where
  - y\_num = k\_(3,15) * x&apos;^15 + k\_(3,14) * x&apos;^14 + k\_(3,13) * x&apos;^13 + ... + k\_(3,0)
  - y\_den = x&apos;^15 + k\_(4,14) * x&apos;^14 + k\_(4,13) * x&apos;^13 + ... + k\_(4,0)

The constants used to compute x\_num are as follows:

- k\_(1,0) = 0x11a05f2b1e833340b809101dd99815856b303e88a2d7005ff2627b56cdb4e2c85610c2d5f2e62d6eaeac1662734649b7
- k\_(1,1) = 0x17294ed3e943ab2f0588bab22147a81c7c17e75b2f6a8417f565e33c70d1e86b4838f2a6f318c356e834eef1b3cb83bb
- k\_(1,2) = 0xd54005db97678ec1d1048c5d10a9a1bce032473295983e56878e501ec68e25c958c3e3d2a09729fe0179f9dac9edcb0
- k\_(1,3) = 0x1778e7166fcc6db74e0609d307e55412d7f5e4656a8dbf25f1b33289f1b330835336e25ce3107193c5b388641d9b6861
- k\_(1,4) = 0xe99726a3199f4436642b4b3e4118e5499db995a1257fb3f086eeb65982fac18985a286f301e77c451154ce9ac8895d9
- k\_(1,5) = 0x1630c3250d7313ff01d1201bf7a74ab5db3cb17dd952799b9ed3ab9097e68f90a0870d2dcae73d19cd13c1c66f652983
- k\_(1,6) = 0xd6ed6553fe44d296a3726c38ae652bfb11586264f0f8ce19008e218f9c86b2a8da25128c1052ecaddd7f225a139ed84
- k\_(1,7) = 0x17b81e7701abdbe2e8743884d1117e53356de5ab275b4db1a682c62ef0f2753339b7c8f8c8f475af9ccb5618e3f0c88e
- k\_(1,8) = 0x80d3cf1f9a78fc47b90b33563be990dc43b756ce79f5574a2c596c928c5d1de4fa295f296b74e956d71986a8497e317
- k\_(1,9) = 0x169b1f8e1bcfa7c42e0c37515d138f22dd2ecb803a0c5c99676314baf4bb1b7fa3190b2edc0327797f241067be390c9e
- k\_(1,10) = 0x10321da079ce07e272d8ec09d2565b0dfa7dccdde6787f96d50af36003b14866f69b771f8c285decca67df3f1605fb7b
- k\_(1,11) = 0x6e08c248e260e70bd1e962381edee3d31d79d7e22c837bc23c0bf1bc24c6b68c24b1b80b64d391fa9c8ba2e8ba2d229

The constants used to compute x\_den are as follows:

- k\_(2,0) = 0x8ca8d548cff19ae18b2e62f4bd3fa6f01d5ef4ba35b48ba9c9588617fc8ac62b558d681be343df8993cf9fa40d21b1c
- k\_(2,1) = 0x12561a5deb559c4348b4711298e536367041e8ca0cf0800c0126c2588c48bf5713daa8846cb026e9e5c8276ec82b3bff
- k\_(2,2) = 0xb2962fe57a3225e8137e629bff2991f6f89416f5a718cd1fca64e00b11aceacd6a3d0967c94fedcfcc239ba5cb83e19
- k\_(2,3) = 0x3425581a58ae2fec83aafef7c40eb545b08243f16b1655154cca8abc28d6fd04976d5243eecf5c4130de8938dc62cd8
- k\_(2,4) = 0x13a8e162022914a80a6f1d5f43e7a07dffdfc759a12062bb8d6b44e833b306da9bd29ba81f35781d539d395b3532a21e
- k\_(2,5) = 0xe7355f8e4e667b955390f7f0506c6e9395735e9ce9cad4d0a43bcef24b8982f7400d24bc4228f11c02df9a29f6304a5
- k\_(2,6) = 0x772caacf16936190f3e0c63e0596721570f5799af53a1894e2e073062aede9cea73b3538f0de06cec2574496ee84a3a
- k\_(2,7) = 0x14a7ac2a9d64a8b230b3f5b074cf01996e7f63c21bca68a81996e1cdf9822c580fa5b9489d11e2d311f7d99bbdcc5a5e
- k\_(2,8) = 0xa10ecf6ada54f825e920b3dafc7a3cce07f8d1d7161366b74100da67f39883503826692abba43704776ec3a79a1d641
- k\_(2,9) = 0x95fc13ab9e92ad4476d6e3eb3a56680f682b4ee96f7d03776df533978f31c1593174e4b4b7865002d6384d168ecdd0a

The constants used to compute y\_num are as follows:

- k\_(3,0) = 0x90d97c81ba24ee0259d1f094980dcfa11ad138e48a869522b52af6c956543d3cd0c7aee9b3ba3c2be9845719707bb33
- k\_(3,1) = 0x134996a104ee5811d51036d776fb46831223e96c254f383d0f906343eb67ad34d6c56711962fa8bfe097e75a2e41c696
- k\_(3,2) = 0xcc786baa966e66f4a384c86a3b49942552e2d658a31ce2c344be4b91400da7d26d521628b00523b8dfe240c72de1f6
- k\_(3,3) = 0x1f86376e8981c217898751ad8746757d42aa7b90eeb791c09e4a3ec03251cf9de405aba9ec61deca6355c77b0e5f4cb
- k\_(3,4) = 0x8cc03fdefe0ff135caf4fe2a21529c4195536fbe3ce50b879833fd221351adc2ee7f8dc099040a841b6daecf2e8fedb
- k\_(3,5) = 0x16603fca40634b6a2211e11db8f0a6a074a7d0d4afadb7bd76505c3d3ad5544e203f6326c95a807299b23ab13633a5f0
- k\_(3,6) = 0x4ab0b9bcfac1bbcb2c977d027796b3ce75bb8ca2be184cb5231413c4d634f3747a87ac2460f415ec961f8855fe9d6f2
- k\_(3,7) = 0x987c8d5333ab86fde9926bd2ca6c674170a05bfe3bdd81ffd038da6c26c842642f64550fedfe935a15e4ca31870fb29
- k\_(3,8) = 0x9fc4018bd96684be88c9e221e4da1bb8f3abd16679dc26c1e8b6e6a1f20cabe69d65201c78607a360370e577bdba587
- k\_(3,9) = 0xe1bba7a1186bdb5223abde7ada14a23c42a0ca7915af6fe06985e7ed1e4d43b9b3f7055dd4eba6f2bafaaebca731c30
- k\_(3,10) = 0x19713e47937cd1be0dfd0b8f1d43fb93cd2fcbcb6caf493fd1183e416389e61031bf3a5cce3fbafce813711ad011c132
- k\_(3,11) = 0x18b46a908f36f6deb918c143fed2edcc523559b8aaf0c2462e6bfe7f911f643249d9cdf41b44d606ce07c8a4d0074d8e
- k\_(3,12) = 0xb182cac101b9399d155096004f53f447aa7b12a3426b08ec02710e807b4633f06c851c1919211f20d4c04f00b971ef8
- k\_(3,13) = 0x245a394ad1eca9b72fc00ae7be315dc757b3b080d4c158013e6632d3c40659cc6cf90ad1c232a6442d9d3f5db980133
- k\_(3,14) = 0x5c129645e44cf1102a159f748c4a3fc5e673d81d7e86568d9ab0f5d396a7ce46ba1049b6579afb7866b1e715475224b
- k\_(3,15) = 0x15e6be4e990f03ce4ea50b3b42df2eb5cb181d8f84965a3957add4fa95af01b2b665027efec01c7704b456be69c8b604

The constants used to compute y\_den are as follows:

- k\_(4,0) = 0x16112c4c3a9c98b252181140fad0eae9601a6de578980be6eec3232b5be72e7a07f3688ef60c206d01479253b03663c1
- k\_(4,1) = 0x1962d75c2381201e1a0cbd6c43c348b885c84ff731c4d59ca4a10356f453e01f78a4260763529e3532f6102c2e49a03d
- k\_(4,2) = 0x58df3306640da276faaae7d6e8eb15778c4855551ae7f310c35a5dd279cd2eca6757cd636f96f891e2538b53dbf67f2
- k\_(4,3) = 0x16b7d288798e5395f20d23bf89edb4d1d115c5dbddbcd30e123da489e726af41727364f2c28297ada8d26d98445f5416
- k\_(4,4) = 0xbe0e079545f43e4b00cc912f8228ddcc6d19c9f0f69bbb0542eda0fc9dec916a20b15dc0fd2ededda39142311a5001d
- k\_(4,5) = 0x8d9e5297186db2d9fb266eaac783182b70152c65550d881c5ecd87b6f0f5a6449f38db9dfa9cce202c6477faaf9b7ac
- k\_(4,6) = 0x166007c08a99db2fc3ba8734ace9824b5eecfdfa8d0cf8ef5dd365bc400a0051d5fa9c01a58b1fb93d1a1399126a775c
- k\_(4,7) = 0x16a3ef08be3ea7ea03bcddfabba6ff6ee5a4375efa1f4fd7feb34fd206357132b920f5b00801dee460ee415a15812ed9
- k\_(4,8) = 0x1866c8ed336c61231a1be54fd1d74cc4f9fb0ce4c6af5920abc5750c4bf39b4852cfe2f7bb9248836b233d9d55535d4a
- k\_(4,9) = 0x167a55cda70a6e1cea820597d94a84903216f763e13d87bb5308592e7ea7d4fbc7385ea3d529b35e346ef48bb8913f55
- k\_(4,10) = 0x4d2f259eea405bd48f010a01ad2911d9c6dd039bb61a6290e591b36e636a5c871a5c29f4f83060400f8b49cba8f6aa8
- k\_(4,11) = 0xaccbb67481d033ff5852c1e48c50c477f94ff8aefce42d28c0f9a88cea7913516f968986f7ebbea9684b529e2561092
- k\_(4,12) = 0xad6b9514c767fe3c3613144b45f1496543346d98adf02267d5ceef9a00d9b8693000763e3b90ac11e99b138573345cc
- k\_(4,13) = 0x2660400eb2e4f3b628bdd0d53cd76f2bf565b94e72927c1cb748df27942480e420517bd8714cc80d1fadc1326ed06f7
- k\_(4,14) = 0xe0fa1d816ddc03e6b24255e0d7819c171c40f65e273b853324efcd6356caa205ca2f570f13497804415473a1d634b8f

### Fp2-to-G2 mapping

Symbol `I` means a non-residue used to make an extension field Fp2

- Z: -(2 + I)
- E&apos;: y&apos;^2 = x&apos;^3 + A&apos; * x&apos; + B&apos;, where
  - A&apos; = 240 * I
  - B&apos; = 1012 * (1 + I)
- h\_eff: 0xbc69f08f2ee75b3584c6a0ea91b352888e2a8e9145ad7689986ff031508ffe1329c2f178731db956d82bf015d1212b02ec0ec69d7477c1ae954cbc06689f6a359894c0adebbf6b4e8020005aaa95551

The 3-isogeny map from (x&apos;, y&apos;) on E&apos; to (x, y) on E is given by the following rational functions:

- x = x\_num / x\_den, where
  - x\_num = k\_(1,3) * x&apos;^3 + k\_(1,2) * x&apos;^2 + k\_(1,1) * x&apos; + k\_(1,0)
  - x\_den = x&apos;^2 + k\_(2,1) * x&apos; + k\_(2,0)

- y = y&apos; * y\_num / y\_den, where
  - y\_num = k\_(3,3) * x&apos;^3 + k\_(3,2) * x&apos;^2 + k\_(3,1) * x&apos; + k\_(3,0)
  - y\_den = x&apos;^3 + k\_(4,2) * x&apos;^2 + k\_(4,1) * x&apos; + k\_(4,0)

The constants used to compute x\_num are as follows:

- k\_(1,0) = 0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6 + 0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97d6 * I
- k\_(1,1) = 0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71a * I
- k\_(1,2) = 0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71e + 0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38d * I
- k\_(1,3) = 0x171d6541fa38ccfaed6dea691f5fb614cb14b4e7f4e810aa22d6108f142b85757098e38d0f671c7188e2aaaaaaaa5ed1

The constants used to compute x\_den are as follows:

- k\_(2,0) = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa63 * I
- k\_(2,1) = 0xc + 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa9f * I

The constants used to compute y\_num are as follows:

- k\_(3,0) = 0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706 + 0x1530477c7ab4113b59a4c18b076d11930f7da5d4a07f649bf54439d87d27e500fc8c25ebf8c92f6812cfc71c71c6d706 * I
- k\_(3,1) = 0x5c759507e8e333ebb5b7a9a47d7ed8532c52d39fd3a042a88b58423c50ae15d5c2638e343d9c71c6238aaaaaaaa97be * I
- k\_(3,2) = 0x11560bf17baa99bc32126fced787c88f984f87adf7ae0c7f9a208c6b4f20a4181472aaa9cb8d555526a9ffffffffc71c + 0x8ab05f8bdd54cde190937e76bc3e447cc27c3d6fbd7063fcd104635a790520c0a395554e5c6aaaa9354ffffffffe38f * I
- k\_(3,3) = 0x124c9ad43b6cf79bfbf7043de3811ad0761b0f37a1e26286b0e977c69aa274524e79097a56dc4bd9e1b371c71c718b10

The constants used to compute y\_den are as follows:

- k\_(4,0) = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb + 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa8fb * I
- k\_(4,1) = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffa9d3 * I
- k\_(4,2) = 0x12 + 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaa99 * I</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-2537/field_to_curve</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-2537/field_to_curve</guid>
      </item>
    
      <item>
        <title>Test Vectors for EIP-2537 - Precompile for BLS12-381 curve operations</title>
        <category>/</category>
        
        <description># Test Vectors for EIP-2537 - Precompile for BLS12-381 curve operations

These test vectors are derived from [BLS 12-381 tests](https://github.com/ethereum/bls12-381-tests/tree/eip-2537)

Note: `BLS12_G1MUL` is executed by the `BLS12_G1MULTIEXP` precompile and `BLS12_G2MUL` is executed by the `BLS12_G2MULTIEXP` precompile.

- [`BLS12_G1ADD` Machine-readable data](/EIPs/assets/eip-2537/add_G1_bls.json)
- [`BLS12_G2ADD` Machine-readable data](/EIPs/assets/eip-2537/add_G2_bls.json)
- [`BLS12_G1MUL` Machine-readable data](/EIPs/assets/eip-2537/mul_G1_bls.json)
- [`BLS12_G2MUL` Machine-readable data](/EIPs/assets/eip-2537/mul_G2_bls.json)
- [`BLS12_G1MSM` Machine-readable data](/EIPs/assets/eip-2537/msm_G1_bls.json)
- [`BLS12_G2MSM` Machine-readable data](/EIPs/assets/eip-2537/msm_G2_bls.json)
- [`BLS12_PAIRING_CHECK` Machine-readable data](/EIPs/assets/eip-2537/pairing_check_bls.json)
- [`BLS12_MAP_FP_TO_G1` Machine-readable data](/EIPs/assets/eip-2537/map_fp_to_G1_bls.json)
- [`BLS12_MAP_FP2_TO_G2` Machine-readable data](/EIPs/assets/eip-2537/map_fp2_to_G2_bls.json)
- [Fail `BLS12_G1ADD` Machine-readable data](/EIPs/assets/eip-2537/fail-add_G1_bls.json)
- [Fail `BLS12_G2ADD` Machine-readable data](/EIPs/assets/eip-2537/fail-add_G2_bls.json)
- [Fail `BLS12_G1MUL` Machine-readable data](/EIPs/assets/eip-2537/fail-mul_G1_bls.json)
- [Fail `BLS12_G2MUL` Machine-readable data](/EIPs/assets/eip-2537/fail-mul_G2_bls.json)
- [Fail `BLS12_G1MSM` Machine-readable data](/EIPs/assets/eip-2537/fail-msm_G1_bls.json)
- [Fail `BLS12_G2MSM` Machine-readable data](/EIPs/assets/eip-2537/fail-msm_G2_bls.json)
- [Fail `BLS12_MAP_FP_TO_G1` Machine-readable data](/EIPs/assets/eip-2537/fail-map_fp_to_G1_bls.json)
- [Fail `BLS12_MAP_FP2_TO_G2` Machine-readable data](/EIPs/assets/eip-2537/fail-map_fp2_to_G2_bls.json)
- [Fail `BLS12_PAIRING_CHECK` Machine-readable data](/EIPs/assets/eip-2537/fail-pairing_check_bls.json)
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-2537/test-vectors</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-2537/test-vectors</guid>
      </item>
    
      <item>
        <title>Metadata standards</title>
        <category>/</category>
        
        <description># Metadata  standards 


This documentation consists of various JSON schemas (examples or standards) that can be referenced by the reader of this EIP for implementing EIP-3475 bonds storage.

## 1. Description metadata: 

```json 
[
    {
        &quot;title&quot;: &quot;defining the title information&quot;,
        &quot;_type&quot;: &quot;explaining the type of the title information added&quot;,
        &quot;description&quot;: &quot;little description about the information stored in  the bond&quot;,
    }
]
```

Example: adding details in bonds describing the local jurisdiction of the bonds where it&apos;s issued:

```json
{
&quot;title&quot;: &quot;localisation&quot;,
&quot;_type&quot;: &quot;string&quot;,
&quot;description&quot;: &quot;jurisdiction law codes compatibility&quot;
&quot;values&quot;: [&quot;fr &quot;, &quot;de&quot;, &quot;ch&quot;]
}
```
The &apos;values&apos; field defined above can also be ISO codes or other hex standard representation.
## 2. Nonce metadata:

- **Information defining the state of the bond** 

```json
[	
	{	
	&quot;title&quot;: &quot;maturity&quot;,
	&quot;_type&quot;: &quot;uint&quot;,
	&quot;description&quot;: &quot;Lorem ipsum...&quot;,
	&quot;values&quot;: [0, 0, 0]
	}
]
```


## 3. Class metadata:

```json
[ 
	{	
	&quot;title&quot;: &quot;symbol&quot;,
	&quot;_type&quot;: &quot;string&quot;,
	&quot;description&quot;: &quot;Lorem ipsum...&quot;,
	&quot;values&quot;: [&quot;Class symbol 1&quot;, &quot;Class symbol 2&quot;, &quot;Class symbol 3&quot;],
	},
	{	
	&quot;title&quot;: &quot;issuer&quot;,
	&quot;_type&quot;: &quot;string&quot;,
	&quot;description&quot;: &quot;Lorem ipsum...&quot;,
	&quot;values&quot;: [&quot;Issuer name 1&quot;, &quot;Issuer name 2&quot;, &quot;Issuer name 3&quot;],
	},

	{	
	&quot;title&quot;: &quot;issuer_address&quot;,
	&quot;_type&quot;: &quot;address&quot;,
	&quot;description&quot;: &quot;Lorem ipsum...&quot;,
	&quot;values&quot;:[&quot;Address 1.&quot;, &quot;Address 2&quot;, &quot;Address 3&quot;]
	},

	{	
	&quot;title&quot;: &quot;class_type&quot;,
	&quot;_type&quot;: &quot;string&quot;,
	&quot;description&quot;: &quot;Lorem ipsum...&quot;,
	&quot;values&quot;: [&quot;Class Type 1&quot;, &quot;Class Type 2&quot;, &quot;Class Type 3&quot;]
	},

	{	
	&quot;title&quot;: &quot;token_address&quot;,
	&quot;_type&quot;: &quot;address&quot;,
	&quot;description&quot;: &quot;Lorem ipsum...&quot;,
	&quot;values&quot;:[&quot;Address 1.&quot;, &quot;Address 2&quot;, &quot;Address 3&quot;]
	},

	{	
	&quot;title&quot;: &quot;period&quot;,
	&quot;_type&quot;: &quot;uint&quot;,
	&quot;description&quot;: &quot;Lorem ipsum...&quot;,
	&quot;values&quot;: [0, 0, 0]
	}
]
```
## Examples of other standards: 
    - ISO-20022 standard is the recently adopted standard by banks for communicating  financial operators (Banks, trading intermediaries, underwriters) that also include bond operations. 
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-3475/Metadata</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-3475/Metadata</guid>
      </item>
    
      <item>
        <title>Bundler Full Sequence Diagram</title>
        <category>/</category>
        
        <description># Bundler Full Sequence Diagram

```plantuml
title UserOperations mempool flow

actor Alice
actor Bob
participant &quot;Bundler RPC&quot;
participant &quot;Ethereum RPC&quot;
participant &quot;UserOp Mempool&quot;

group Alice Submits UserOp
note right of Alice: create UserOp
Alice-&gt;&quot;Bundler RPC&quot;: &quot;&quot;eth_sendUserOperation&quot;&quot;
&quot;Bundler RPC&quot;-&gt;&quot;Ethereum RPC&quot;: First Validation\ntrace view call to:\n&quot;&quot;handleOps([userOpA]&quot;&quot;)
&quot;Bundler RPC&quot;-&gt;&quot;UserOp Mempool&quot;: add &quot;&quot;UserOp&quot;&quot; to mempool
end
|||

group Bob Submits UserOp
note right of Bob: create UserOp
Bob-&gt;&quot;Bundler RPC&quot;: &quot;&quot;eth_sendUserOperation&quot;&quot;
&quot;Bundler RPC&quot;-&gt;&quot;Ethereum RPC&quot;: First Validation\ntrace view call to\n&quot;&quot;handleOps([userOpB]&quot;&quot;)
&quot;Bundler RPC&quot;-&gt;&quot;UserOp Mempool&quot;: add &quot;&quot;UserOp&quot;&quot; to mempool
end
|||

group Build Bundle
    &quot;Bundler RPC&quot;-&gt;&quot;UserOp Mempool&quot;: fetch pending &quot;&quot;UserOps&quot;&quot;
    return &quot;&quot;[UserOpA, UserOpB]&quot;&quot;
|||
    loop for each UserOp
        &quot;Bundler RPC&quot;-&gt;&quot;Ethereum RPC&quot;: Second Validation\ntrace view call to:\n&quot;&quot;handleOps([userOp])&quot;&quot;
|||
    end

note right of &quot;Bundler RPC&quot;: create bundle &quot;&quot;[UserOpA, UserOpB]&quot;&quot;
&quot;Bundler RPC&quot;-&gt;&quot;Ethereum RPC&quot;: Third Validation\ntrace view call to:\n&quot;&quot;handleOps([UserOpA, UserOpB])&quot;&quot;
|||
&quot;Bundler RPC&quot;-&gt;&quot;Ethereum RPC&quot;: submit transaction\n&quot;&quot;handleOps([UserOpA, UserOpB])&quot;&quot;
|||
end
```

# Bundle Sequence Diagram (Without factory)
```plantuml
@startuml
autonumber
participant &quot;EntryPoint&quot; as ep
participant &quot;Account A&quot; as account
participant &quot;Account B&quot; as account2
[-&gt;ep++ #gold: &quot;&quot;handleOps(userOps[])&quot;&quot;:
group Validations
|||
ep-&gt;account++ #blue: &lt;font color=blue&gt; &quot;&quot;validateUserOp&quot;&quot;
return &quot;&quot;deposit&quot;&quot;
|||
ep-&gt;ep: deduct &quot;&quot;Account_A&quot;&quot; deposit
|||
ep-&gt;account2++ #green: &lt;font color=green&gt; &quot;&quot;validateUserOp&quot;&quot;
return &quot;&quot;deposit&quot;&quot;
|||
ep-&gt;ep: deduct &quot;&quot;Account_B&quot;&quot; deposit
|||
end

group Executions
|||
ep-&gt;account++ #blue: &lt;font color=blue&gt; &quot;&quot;executeUserOp&quot;&quot;
deactivate account
ep-&gt;ep: refund &quot;&quot;Account_A&quot;&quot;
|||
ep-&gt;account2++ #green: &lt;font color=green&gt; &quot;&quot;executeUserOp&quot;&quot;
deactivate account2
ep-&gt;ep: refund &quot;&quot;Account_B&quot;&quot;
|||
end
ep--&gt;[: &quot;&quot;compensate(beneficiary)&quot;&quot;
hide footbox
```

# Bundle Sequence Diagram (with Paymaster)
```plantuml
@startuml
autonumber
participant &quot;EntryPoint&quot; as ep
participant &quot;Account&quot; as account
participant &quot;Paymaster&quot; as pm
[-&gt;ep++ #gold: &quot;&quot;handleOps(userOps[])&quot;&quot;:
group Validation
|||
ep-&gt;account++ #blue: &lt;font color=blue&gt; &quot;&quot;validateUserOp&quot;&quot;
deactivate account
ep-&gt;pm++ #gray: &quot;&quot;validatePaymasterUserOp&quot;&quot;
deactivate pm
ep-&gt;ep: deduct &quot;&quot;Paymaster&quot;&quot; deposit
|||
end
group Execution
|||
ep-&gt;account++ #blue: &lt;font color=blue&gt; &quot;&quot;executeUserOp&quot;&quot;
    deactivate account
ep-&gt;pm++ #gray: &quot;&quot;postOp&quot;&quot;
    deactivate pm
ep-&gt;ep: refund paymaster
|||
end
ep--&gt;[: &quot;&quot;compensate(beneficiary)&quot;&quot;
hide footbox
```

# Bundle Sequence Diagram (with Factory)
```plantuml
@startuml
autonumber
participant &quot;EntryPoint&quot; as ep
participant &quot;Factory&quot; as fact
participant &quot;Account&quot; as account
participant &quot;Account2&quot; as account2
[-&gt;ep++ #gold: handleOps(userOps[]):
group Validations
ep-&gt;fact++ #gray: create (initCode)
fact-&gt;o account: create
return account
ep-&gt;account++ #blue: &lt;font color=blue&gt; validateUserOp
return deposit
ep-&gt;ep: deduct account deposit
ep-&gt;account2++ #green: &lt;font color=green&gt; validateUserOp
return deposit
ep-&gt;ep: deduct account2 deposit
end
group Executions
ep-&gt;account++ #blue: &lt;font color=blue&gt; exec
deactivate account
ep-&gt;ep: refund account1
ep-&gt;account2++ #green: &lt;font color=green&gt; exec
deactivate account2
ep-&gt;ep: refund account2
end
ep--&gt;[: compensate(beneficiary)
hide footbox
```
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-4337/diagrams</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-4337/diagrams</guid>
      </item>
    
      <item>
        <title>SemVer Authors</title>
        <category>/</category>
        
        <description>SemVer Authors
==============

The following people have modified the Semantic Versioning 2.0.0 specification:

 - Tom Preston-Werner
 - Phil Haack
 - Haacked
 - isaacs
 - Thijs Schreijer
 - jeffhandley
 - Alexandr Tovmach
 - Adam Ralph
 - Eddie Garmon
 - Jeff Handley
 - Krzysztof Piasecki
 - Doug Beck
 - Gert de Pagter
 - Guillermo Calvo
 - Iulian Onofrei
 - Ivan Bessarabov
 - Jo Liss
 - Johanan Liebermann
 - Joseph Donahue
 - Konstantin
 - Kristian Glass
 - Mark Amery
 - OGINO Masanori
 - Oguz Bilgic
 - Slipp Douglas
 - Thomas Schraitle
 - Tim Vergenz
 - Todd Reed
 - Tristram Oaten
 - Wincent Colaiuta
 - alexandrtovmach
 - wolf99
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-5139/AUTHORS</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-5139/AUTHORS</guid>
      </item>
    
      <item>
        <title>Semantic Versioning 2.0.0</title>
        <category>/</category>
        
        <description>Semantic Versioning 2.0.0
==============================

Summary
-------

Given a version number MAJOR.MINOR.PATCH, increment the:

1. MAJOR version when you make incompatible API changes,
1. MINOR version when you add functionality in a backwards compatible
   manner, and
1. PATCH version when you make backwards compatible bug fixes.

Additional labels for pre-release and build metadata are available as extensions
to the MAJOR.MINOR.PATCH format.

Introduction
------------

In the world of software management there exists a dreaded place called
&quot;dependency hell.&quot; The bigger your system grows and the more packages you
integrate into your software, the more likely you are to find yourself, one
day, in this pit of despair.

In systems with many dependencies, releasing new package versions can quickly
become a nightmare. If the dependency specifications are too tight, you are in
danger of version lock (the inability to upgrade a package without having to
release new versions of every dependent package). If dependencies are
specified too loosely, you will inevitably be bitten by version promiscuity
(assuming compatibility with more future versions than is reasonable).
Dependency hell is where you are when version lock and/or version promiscuity
prevent you from easily and safely moving your project forward.

As a solution to this problem, we propose a simple set of rules and
requirements that dictate how version numbers are assigned and incremented.
These rules are based on but not necessarily limited to pre-existing
widespread common practices in use in both closed and open-source software.
For this system to work, you first need to declare a public API. This may
consist of documentation or be enforced by the code itself. Regardless, it is
important that this API be clear and precise. Once you identify your public
API, you communicate changes to it with specific increments to your version
number. Consider a version format of X.Y.Z (Major.Minor.Patch). Bug fixes not
affecting the API increment the patch version, backwards compatible API
additions/changes increment the minor version, and backwards incompatible API
changes increment the major version.

We call this system &quot;Semantic Versioning.&quot; Under this scheme, version numbers
and the way they change convey meaning about the underlying code and what has
been modified from one version to the next.

Semantic Versioning Specification (SemVer)
------------------------------------------

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;,
&quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be
interpreted as described in [RFC 2119](https://tools.ietf.org/html/rfc2119).

1. Software using Semantic Versioning MUST declare a public API. This API
could be declared in the code itself or exist strictly in documentation.
However it is done, it SHOULD be precise and comprehensive.

1. A normal version number MUST take the form X.Y.Z where X, Y, and Z are
non-negative integers, and MUST NOT contain leading zeroes. X is the
major version, Y is the minor version, and Z is the patch version.
Each element MUST increase numerically. For instance: 1.9.0 -&gt; 1.10.0 -&gt; 1.11.0.

1. Once a versioned package has been released, the contents of that version
MUST NOT be modified. Any modifications MUST be released as a new version.

1. Major version zero (0.y.z) is for initial development. Anything MAY change
at any time. The public API SHOULD NOT be considered stable.

1. Version 1.0.0 defines the public API. The way in which the version number
is incremented after this release is dependent on this public API and how it
changes.

1. Patch version Z (x.y.Z | x &gt; 0) MUST be incremented if only backwards
compatible bug fixes are introduced. A bug fix is defined as an internal
change that fixes incorrect behavior.

1. Minor version Y (x.Y.z | x &gt; 0) MUST be incremented if new, backwards
compatible functionality is introduced to the public API. It MUST be
incremented if any public API functionality is marked as deprecated. It MAY be
incremented if substantial new functionality or improvements are introduced
within the private code. It MAY include patch level changes. Patch version
MUST be reset to 0 when minor version is incremented.

1. Major version X (X.y.z | X &gt; 0) MUST be incremented if any backwards
incompatible changes are introduced to the public API. It MAY also include minor
and patch level changes. Patch and minor versions MUST be reset to 0 when major
version is incremented.

1. A pre-release version MAY be denoted by appending a hyphen and a
series of dot separated identifiers immediately following the patch
version. Identifiers MUST comprise only ASCII alphanumerics and hyphens
[0-9A-Za-z-]. Identifiers MUST NOT be empty. Numeric identifiers MUST
NOT include leading zeroes. Pre-release versions have a lower
precedence than the associated normal version. A pre-release version
indicates that the version is unstable and might not satisfy the
intended compatibility requirements as denoted by its associated
normal version. Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7,
1.0.0-x.7.z.92, 1.0.0-x-y-z.--.

1. Build metadata MAY be denoted by appending a plus sign and a series of dot
separated identifiers immediately following the patch or pre-release version.
Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-].
Identifiers MUST NOT be empty. Build metadata MUST be ignored when determining
version precedence. Thus two versions that differ only in the build metadata,
have the same precedence. Examples: 1.0.0-alpha+001, 1.0.0+20130313144700,
1.0.0-beta+exp.sha.5114f85, 1.0.0+21AF26D3----117B344092BD.

1. Precedence refers to how versions are compared to each other when ordered.

   1. Precedence MUST be calculated by separating the version into major,
      minor, patch and pre-release identifiers in that order (Build metadata
      does not figure into precedence).

   1. Precedence is determined by the first difference when comparing each of
      these identifiers from left to right as follows: Major, minor, and patch
      versions are always compared numerically.

      Example: 1.0.0 &lt; 2.0.0 &lt; 2.1.0 &lt; 2.1.1.

   1. When major, minor, and patch are equal, a pre-release version has lower
      precedence than a normal version:

      Example: 1.0.0-alpha &lt; 1.0.0.

   1. Precedence for two pre-release versions with the same major, minor, and
      patch version MUST be determined by comparing each dot separated identifier
      from left to right until a difference is found as follows:

      1. Identifiers consisting of only digits are compared numerically.

      1. Identifiers with letters or hyphens are compared lexically in ASCII
         sort order.

      1. Numeric identifiers always have lower precedence than non-numeric
         identifiers.

      1. A larger set of pre-release fields has a higher precedence than a
         smaller set, if all of the preceding identifiers are equal.

      Example: 1.0.0-alpha &lt; 1.0.0-alpha.1 &lt; 1.0.0-alpha.beta &lt; 1.0.0-beta &lt; 
      1.0.0-beta.2 &lt; 1.0.0-beta.11 &lt; 1.0.0-rc.1 &lt; 1.0.0.

Backus–Naur Form Grammar for Valid SemVer Versions
--------------------------------------------------
```
&lt;valid semver&gt; ::= &lt;version core&gt;
                 | &lt;version core&gt; &quot;-&quot; &lt;pre-release&gt;
                 | &lt;version core&gt; &quot;+&quot; &lt;build&gt;
                 | &lt;version core&gt; &quot;-&quot; &lt;pre-release&gt; &quot;+&quot; &lt;build&gt;

&lt;version core&gt; ::= &lt;major&gt; &quot;.&quot; &lt;minor&gt; &quot;.&quot; &lt;patch&gt;

&lt;major&gt; ::= &lt;numeric identifier&gt;

&lt;minor&gt; ::= &lt;numeric identifier&gt;

&lt;patch&gt; ::= &lt;numeric identifier&gt;

&lt;pre-release&gt; ::= &lt;dot-separated pre-release identifiers&gt;

&lt;dot-separated pre-release identifiers&gt; ::= &lt;pre-release identifier&gt;
                                          | &lt;pre-release identifier&gt; &quot;.&quot; &lt;dot-separated pre-release identifiers&gt;

&lt;build&gt; ::= &lt;dot-separated build identifiers&gt;

&lt;dot-separated build identifiers&gt; ::= &lt;build identifier&gt;
                                    | &lt;build identifier&gt; &quot;.&quot; &lt;dot-separated build identifiers&gt;

&lt;pre-release identifier&gt; ::= &lt;alphanumeric identifier&gt;
                           | &lt;numeric identifier&gt;

&lt;build identifier&gt; ::= &lt;alphanumeric identifier&gt;
                     | &lt;digits&gt;

&lt;alphanumeric identifier&gt; ::= &lt;non-digit&gt;
                            | &lt;non-digit&gt; &lt;identifier characters&gt;
                            | &lt;identifier characters&gt; &lt;non-digit&gt;
                            | &lt;identifier characters&gt; &lt;non-digit&gt; &lt;identifier characters&gt;

&lt;numeric identifier&gt; ::= &quot;0&quot;
                       | &lt;positive digit&gt;
                       | &lt;positive digit&gt; &lt;digits&gt;

&lt;identifier characters&gt; ::= &lt;identifier character&gt;
                          | &lt;identifier character&gt; &lt;identifier characters&gt;

&lt;identifier character&gt; ::= &lt;digit&gt;
                         | &lt;non-digit&gt;

&lt;non-digit&gt; ::= &lt;letter&gt;
              | &quot;-&quot;

&lt;digits&gt; ::= &lt;digit&gt;
           | &lt;digit&gt; &lt;digits&gt;

&lt;digit&gt; ::= &quot;0&quot;
          | &lt;positive digit&gt;

&lt;positive digit&gt; ::= &quot;1&quot; | &quot;2&quot; | &quot;3&quot; | &quot;4&quot; | &quot;5&quot; | &quot;6&quot; | &quot;7&quot; | &quot;8&quot; | &quot;9&quot;

&lt;letter&gt; ::= &quot;A&quot; | &quot;B&quot; | &quot;C&quot; | &quot;D&quot; | &quot;E&quot; | &quot;F&quot; | &quot;G&quot; | &quot;H&quot; | &quot;I&quot; | &quot;J&quot;
           | &quot;K&quot; | &quot;L&quot; | &quot;M&quot; | &quot;N&quot; | &quot;O&quot; | &quot;P&quot; | &quot;Q&quot; | &quot;R&quot; | &quot;S&quot; | &quot;T&quot;
           | &quot;U&quot; | &quot;V&quot; | &quot;W&quot; | &quot;X&quot; | &quot;Y&quot; | &quot;Z&quot; | &quot;a&quot; | &quot;b&quot; | &quot;c&quot; | &quot;d&quot;
           | &quot;e&quot; | &quot;f&quot; | &quot;g&quot; | &quot;h&quot; | &quot;i&quot; | &quot;j&quot; | &quot;k&quot; | &quot;l&quot; | &quot;m&quot; | &quot;n&quot;
           | &quot;o&quot; | &quot;p&quot; | &quot;q&quot; | &quot;r&quot; | &quot;s&quot; | &quot;t&quot; | &quot;u&quot; | &quot;v&quot; | &quot;w&quot; | &quot;x&quot;
           | &quot;y&quot; | &quot;z&quot;
```

Why Use Semantic Versioning?
----------------------------

This is not a new or revolutionary idea. In fact, you probably do something
close to this already. The problem is that &quot;close&quot; isn&apos;t good enough. Without
compliance to some sort of formal specification, version numbers are
essentially useless for dependency management. By giving a name and clear
definition to the above ideas, it becomes easy to communicate your intentions
to the users of your software. Once these intentions are clear, flexible (but
not too flexible) dependency specifications can finally be made.

A simple example will demonstrate how Semantic Versioning can make dependency
hell a thing of the past. Consider a library called &quot;Firetruck.&quot; It requires a
Semantically Versioned package named &quot;Ladder.&quot; At the time that Firetruck is
created, Ladder is at version 3.1.0. Since Firetruck uses some functionality
that was first introduced in 3.1.0, you can safely specify the Ladder
dependency as greater than or equal to 3.1.0 but less than 4.0.0. Now, when
Ladder version 3.1.1 and 3.2.0 become available, you can release them to your
package management system and know that they will be compatible with existing
dependent software.

As a responsible developer you will, of course, want to verify that any
package upgrades function as advertised. The real world is a messy place;
there&apos;s nothing we can do about that but be vigilant. What you can do is let
Semantic Versioning provide you with a sane way to release and upgrade
packages without having to roll new versions of dependent packages, saving you
time and hassle.

If all of this sounds desirable, all you need to do to start using Semantic
Versioning is to declare that you are doing so and then follow the rules. Link
to this website from your README so others know the rules and can benefit from
them.

FAQ
---

### How should I deal with revisions in the 0.y.z initial development phase?

The simplest thing to do is start your initial development release at 0.1.0
and then increment the minor version for each subsequent release.

### How do I know when to release 1.0.0?

If your software is being used in production, it should probably already be
1.0.0. If you have a stable API on which users have come to depend, you should
be 1.0.0. If you&apos;re worrying a lot about backwards compatibility, you should
probably already be 1.0.0.

### Doesn&apos;t this discourage rapid development and fast iteration?

Major version zero is all about rapid development. If you&apos;re changing the API
every day you should either still be in version 0.y.z or on a separate
development branch working on the next major version.

### If even the tiniest backwards incompatible changes to the public API require a major version bump, won&apos;t I end up at version 42.0.0 very rapidly?

This is a question of responsible development and foresight. Incompatible
changes should not be introduced lightly to software that has a lot of
dependent code. The cost that must be incurred to upgrade can be significant.
Having to bump major versions to release incompatible changes means you&apos;ll
think through the impact of your changes, and evaluate the cost/benefit ratio
involved.

### Documenting the entire public API is too much work!

It is your responsibility as a professional developer to properly document
software that is intended for use by others. Managing software complexity is a
hugely important part of keeping a project efficient, and that&apos;s hard to do if
nobody knows how to use your software, or what methods are safe to call. In
the long run, Semantic Versioning, and the insistence on a well defined public
API can keep everyone and everything running smoothly.

### What do I do if I accidentally release a backwards incompatible change as a minor version?

As soon as you realize that you&apos;ve broken the Semantic Versioning spec, fix
the problem and release a new minor version that corrects the problem and
restores backwards compatibility. Even under this circumstance, it is
unacceptable to modify versioned releases. If it&apos;s appropriate,
document the offending version and inform your users of the problem so that
they are aware of the offending version.

### What should I do if I update my own dependencies without changing the public API?

That would be considered compatible since it does not affect the public API.
Software that explicitly depends on the same dependencies as your package
should have their own dependency specifications and the author will notice any
conflicts. Determining whether the change is a patch level or minor level
modification depends on whether you updated your dependencies in order to fix
a bug or introduce new functionality. We would usually expect additional code
for the latter instance, in which case it&apos;s obviously a minor level increment.

### What if I inadvertently alter the public API in a way that is not compliant with the version number change (i.e. the code incorrectly introduces a major breaking change in a patch release)?

Use your best judgment. If you have a huge audience that will be drastically
impacted by changing the behavior back to what the public API intended, then
it may be best to perform a major version release, even though the fix could
strictly be considered a patch release. Remember, Semantic Versioning is all
about conveying meaning by how the version number changes. If these changes
are important to your users, use the version number to inform them.

### How should I handle deprecating functionality?

Deprecating existing functionality is a normal part of software development and
is often required to make forward progress. When you deprecate part of your
public API, you should do two things: (1) update your documentation to let
users know about the change, (2) issue a new minor release with the deprecation
in place. Before you completely remove the functionality in a new major release
there should be at least one minor release that contains the deprecation so
that users can smoothly transition to the new API.

### Does SemVer have a size limit on the version string?

No, but use good judgment. A 255 character version string is probably overkill,
for example. Also, specific systems may impose their own limits on the size of
the string.

### Is &quot;v1.2.3&quot; a semantic version?

No, &quot;v1.2.3&quot; is not a semantic version. However, prefixing a semantic version
with a &quot;v&quot; is a common way (in English) to indicate it is a version number.
Abbreviating &quot;version&quot; as &quot;v&quot; is often seen with version control. Example:
`git tag v1.2.3 -m &quot;Release version 1.2.3&quot;`, in which case &quot;v1.2.3&quot; is a tag
name and the semantic version is &quot;1.2.3&quot;.

### Is there a suggested regular expression (RegEx) to check a SemVer string?

There are two. One with named groups for those systems that support them
(PCRE [Perl Compatible Regular Expressions, i.e. Perl, PHP and R], Python
and Go).

See: &lt;https://regex101.com/r/Ly7O1x/3/&gt;

```
^(?P&lt;major&gt;0|[1-9]\d*)\.(?P&lt;minor&gt;0|[1-9]\d*)\.(?P&lt;patch&gt;0|[1-9]\d*)(?:-(?P&lt;prerelease&gt;(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P&lt;buildmetadata&gt;[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$
```

And one with numbered capture groups instead (so cg1 = major, cg2 = minor,
cg3 = patch, cg4 = prerelease and cg5 = buildmetadata) that is compatible
with ECMA Script (JavaScript), PCRE (Perl Compatible Regular Expressions,
i.e. Perl, PHP and R), Python and Go.

See: &lt;https://regex101.com/r/vkijKf/1/&gt;

```
^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$
```

About
-----

The Semantic Versioning specification was originally authored by [Tom
Preston-Werner](https://tom.preston-werner.com), inventor of Gravatar and
cofounder of GitHub.

If you&apos;d like to leave feedback, please [open an issue on
GitHub](https://github.com/semver/semver/issues).

License
-------

[Creative Commons ― CC BY 3.0](https://creativecommons.org/licenses/by/3.0/)
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-5139/semver</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-5139/semver</guid>
      </item>
    
      <item>
        <title></title>
        <category>/</category>
        
        <description>Here is a copy of the tl;dr section from an [extended analysis](https://hackmd.io/@adrninistrator1/SkHmz972n) of `pubkey2index` and `index2pubkey` cache usage provided by Navie Chan:

tl;dr: `index2Pubkey` is used in a lot more scenarios than `pubkey2Index`. The use cases for `index2Pubkey` do not require unfinalized information. `process_deposit()` is the only place in consensus spec that needs unfinalized information and it utilizes `pubkey2Index`.
In terms of the two-cache approach, `unfinalizedIndex2Pubkey` is not needed since there is not a place that utilizes it. `unfinalizedPubkey2Index`, however, is needed for `process_deposit()`.

|  | unfinalized pubkey2Index? | unfinalized index2Pubkey? |
|-|-|-|
| onBlock - state_transition - verify_block_signature | N/A | No |
| onBlock - state_transition - process_block - process_randao | N/A | No |
| onBlock - state_transition - process_block - process_operations - process_proposer_slashing | N/A | No |
| onBlock - state_transition - process_block - process_operations - process_attester_slashing - is_valid_indexed_attestation | N/A | No |
| onBlock - state_transition - process_block - process_operations - process_attestation - is_valid_indexed_attestation | N/A | No |
| onBlock - state_transition - process_block - process_operations - process_deposit - apply_deposit | Yes | N/A |
| onBlock - state_transition - process_block - process_operations - process_sync_aggregate - eth_fast_aggregate_verify | No | No |
| onBlock - state_transition - process_block - process_bls_to_execution_change | N/A | N/A |
| onBlock - state_transition - process_block - process_voluntary_exit | N/A | No |
| p2p - beacon_block ---- onBlock | N/A | No |
| p2p - beacon_aggregate_and_proof ---- onAttestation | N/A | No |
| p2p - voluntary_exit - process_voluntary_exit | N/A | No |
| p2p - proposer_slashing - process_proposer_slashing | N/A | No |
| p2p - attester_slashing - process_attester_slashing | N/A | No |
| p2p - beacon_attestation_{subnet_id} ---- onAttestation | N/A | No |
| p2p - sync_committee_contribution_and_proof | N/A | No |
| p2p - sync_committee_{subnet_id} | N/A | No |
| p2p - bls_to_execution_change - process_bls_to_execution_change | N/A | N/A |
| p2p - blob_sidecar_{subnet_id} - verify_blob_sidecar_signature | N/A | No |
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-6110/pubkey_to_index_cache_analysis</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-6110/pubkey_to_index_cache_analysis</guid>
      </item>
    
      <item>
        <title></title>
        <category>/</category>
        
        <description>[Modified version](/EIPs/assets/eip-6110/eth2_ws_calc.py) of a [script](https://gist.github.com/adiasg/3aceab409b36aa9a9d9156c1baa3c248) shows the following changes in the WS period computations with increase of a number of deposits per epoch (deviations are highlighted):

| Safety Decay | Avg. Val. Balance (ETH) | Val. Count | WS (Epochs), `16` deposits per slot | WS (Epochs), `1024` deposits per slot |
| ---- | ---- | ---- | ---- | ---- |
| 10 | 20 | 32768 | 272 | **256** |
| 10 | 20 | 65536 | 288 | **256** |
| 10 | 20 | 131072 | 320 | **257** |
| 10 | 20 | 262144 | 384 | **258** |
| 10 | 20 | 524288 | 512 | **260** |
| 10 | 20 | 1048576 | 768 | **264** |
| 10 | 24 | 32768 | 310 | 310 |
| 10 | 24 | 65536 | 365 | 365 |
| 10 | 24 | 131072 | 474 | 474 |
| 10 | 24 | 262144 | 692 | 692 |
| 10 | 24 | 524288 | 692 | 692 |
| 10 | 24 | 1048576 | 1041 | **504** |
| 10 | 28 | 32768 | 504 | 504 |
| 10 | 28 | 65536 | 752 | 752 |
| 10 | 28 | 131072 | 1248 | 1248 |
| 10 | 28 | 262144 | 2241 | 2241 |
| 10 | 28 | 524288 | 2241 | 2241 |
| 10 | 28 | 1048576 | 2241 | 2241 |
| 10 | 32 | 32768 | 665 | 665 |
| 10 | 32 | 65536 | 1075 | 1075 |
| 10 | 32 | 131072 | 1894 | 1894 |
| 10 | 32 | 262144 | 3532 | 3532 |
| 10 | 32 | 524288 | 3532 | 3532 |
| 10 | 32 | 1048576 | 3532 | 3532 |
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-6110/ws_period_analysis</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-6110/ws_period_analysis</guid>
      </item>
    
      <item>
        <title></title>
        <category>/</category>
        
        <description>MIT License

Copyright (c) 2023 Authentic Vision GmbH

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the &quot;Software&quot;), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-6956/LICENSE</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-6956/LICENSE</guid>
      </item>
    
      <item>
        <title>Withdrawal requests fee analysis</title>
        <category>/</category>
        
        <description># Withdrawal requests fee analysis

Analysis of the following parameters of the Withdrawal request smart contract:
* `MAX_WITHDRAWAL_REQUESTS_PER_BLOCK = 16`
* `TARGET_WITHDRAWAL_REQUESTS_PER_BLOCK = 2`

**TL; DR:** These parameters have reasonable values.

## Consensus layer with TARGET=2, MAX=16

Full withdrawal requests doesn&apos;t create additional data complexity on the CL side as the changes are applied to the list of validators.

Current exit churn size allows to initiate withdrawal for 256 ETH per epoch, if a number of request per epoch is at its level (`32 * MAX = 512` requests) then the average withdrawing amount should be no bigger than `0.5 ETH` to fit the churn. It is not unreasonable to assume that most of the time this limit will be satisfied.

Partial withdrawals has a separate list which processing depends on the exit churn. If there is enough churn then pending partial withdrawal request will be processed at least `MIN_VALIDATOR_WITHDRAWABILITY_DELAY = 256` epochs after it was queued on the CL. This delay sets a lower boundary on the number of pending withdrawals in the queue in a situation when each block has `MAX=16` requests, it is `256 * 32 * 16 = 131,072`, which is `3 MB` of data. In an extreme case scenario when e.g. ~10% of validators are exiting this number can grow up to `192 MB`.

With `TARGET=2` requests per each block the above numbers are reduced to `0.375 MB` and `24 MB` respectively. Average amount for a partial withdrawal increases up to `4.0 ETH`.

## Attack via prohibitive fee

Full withdrawal requests are a security mechanism and an attacker can potentially benefit from block this functionality by keep the request fee at a prohibitive level. This section explores such attack with more details.

The cost of attack includes two parts. First part is to raise the fee to a certain level (the base cost) and the second part is to keep the fee at that level (per block cost).

The fee is updated at the end of the block processing, so it remains the same regardless of a number of requests submitted within one block. The lowest fee is `1 Wei` which makes the base cost of this attack near to `0`. The cost per block is computed as `prohibitive_fee * TARGET`.

There are two ways to increase the cost:
* Raise fee upon each request -- affects mostly the base cost, has a slight effect on the cost per block
* Increase `TARGET` -- affects the cost per block

The cost of attack with the status quo and above improvements are provided in the table below. The second cost is the cost per hour of such attack, i.e. cost per block times `300` (number of slots per hour).

| Fee | TARGET=2 | TARGET=2 + fine-grained fee | TARGET=8 |
|-|-|-|-|
| 0.0001 ETH | 0.06 ETH | 0.07 ETH | 0.25 ETH |
| 0.01 ETH   | 6.25 ETH | 6.61 ETH | 25.00 ETH |
| 0.1 ETH    | 61.98 ETH | 65.56 ETH | 247.92 ETH |
| 0.5 ETH    | 303.39 ETH | 320.93 ETH | 1213.58 ETH |
| 1 ETH      | 614.59 ETH |  650.10 ETH | 2458.37 ETH |
| 2 ETH      | 1244.95 ETH | 1316.90 ETH | 4979.79 ETH |
| 4 ETH      | 2521.76 ETH | 2667.53 ETH | 10087.02 ETH |

To summarize:
* raising fee upon each requests increases the cost of an hour of attack by _~6%_, while `TARGET=8` makes the 4 times increase
* with the status quo the attack is not sustainable long term

## UX

Assuming `1 Gwei` to be a reasonable fee per request, it will take 2.75 hours for the fee to reach this level if someone submits 2,000 requests in one block (the max possible number to fit in 30M gas block).

From the UX standpoint it might seem quite long, but `TARGET=2`, comparing to e.g. `TARGET=8`, reduces the strain on the protocol by more efficiently rate limiting the growth of the EL and CL queues.
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7002/fee_analysis</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7002/fee_analysis</guid>
      </item>
    
      <item>
        <title>Appendix: Interoperability Analysis</title>
        <category>/</category>
        
        <description>
## Appendix: Interoperability Analysis

We provide a cherrypicked list of possible points of contact between ERC-7208 and other tokenization standards and proposals.

**ERC-1400 (Security Token Standard)**: This ERC provides a suite of standard interfaces for issuing/redeeming security tokens, managing their ownership and transfer restrictions, and providing transparency to token holders on how different subsets of their token balance behave with respect to transfer restrictions, rights and obligations. ERC-7208 can enhance ERC-1400 by offering a dynamic and flexible data management architecture. **Data Objects** enable the storage and modification of on-chain data for security tokens, such as compliance information or ownership details. Assets already issued under ERC-1400 can be wrapped into a **Vault Data Object** and exposed through any **Data Manager** interface (including **ERC-3643**). Additionally, ERC-7208 enablesthe fractionalization of ERC-1400 assets. If the asset is issued through an ERC-1400 **Data Manager** with native **Data Object** storage, the integration could lead to more versatile and transparent security token offerings, as a custom Identity Management logic can be embedded within the assets.

**EIP-2981 (Royalties)**: ERC-7208 can complement EIP-2981 as a **Data Manager** by providing a flexible way to handle royalties. **Data Objects** can store and manage the low-level storage of royalty information dynamically, independently from the interface used by the end user. This enables a complex royalty structure that can change over time or respond to predefined conditions, like embedding compliance checks and simultaneously exposing multiple interfaces for fractional ownership of the underlying asset. For instance, by leveraging ERC-7208, an individual royalty-based NFT can be traded in a compliant manner, concurrently under both an ERC-721 interface as well as an ERC-20 through the use of **Data Managers** that delegate their internal storage onto the **Data Object**.

**ERC-3643 (Security Tokens)**: ERC-3643 defines a *Security Token interface for Regulated Exchanges* based on ERC-20 token standard. The ERC-7208 can be used for wrapping many tokens (irrespective of their ERC) and adapting their logic to the ERC-3643. Additionally, a **Data Object** storing native ERC-3643 asset data can be used for improving the compliance logic and enabling the trading of underlying securities simultaneously through multiple interfaces that respond to different regulatory frameworks. Moreover, the separation of the storage enables the logic to implement functionalities that were not initially a part of the original ERC-3643, such as identity-based recovery of assets, role-based access control, the introduction of cross-chain support, etc.

**ERC-4337 (Account Abstraction)**: ERC-7208 can provide a standardized method to store and manage the complex data structures required by abstracted accounts. This can include user preferences, access control lists, recovery options, and other customizable account features. The mutable states of abstracted accounts can be efficiently handled using **Data Objects**. This, in turn, improves the adaptability and security of abstracted accounts. Additionally, an ERC-7208 implementation supporting meta-transactions and **Data Points** separated by chain-id can be developed to fully abstract account management across blockchains.

**EIP-4626 (Tokenized Vaults)**: Tokenized Vaults inherit from a single ERC-20 and ERC-2612 for approvals via EIP-712 secp256k1 signatures. ERC-7208 can enhance EIP-4626 by providing a more dynamic data layer for tokenized vaults. **Data Objects** store information about the assets in the vault, conditions for access, or other relevant data, enabling more nuanced interactions with tokenized vaults. Additionally, the **Data Point** can store more than a single ERC-20, greatly increasing the capabilities of Tokenized Vaults.

**ERC-4907 (Shared Ownership)**: The integration of ERC-4907 as a **Data Manager** with ERC-7208 **Data Point** storage can enhance the rental experience by allowing for additional rental-related data directly on-chain, such as rental terms, user permissions, and other customizable settings which would be self-contained within **Data Points** and therefore automatically updated as metadata. ERC-4907&apos;s rental mechanism complements ERC-7208&apos;s ability to manage mutable on-chain data. By combining these two, NFTs can not only be rented out for specific periods but also have their traits or states dynamically managed and updated during the rental period. This combination enhances security and compliance in NFT transactions, particularly for *Real World Asset Tokenization*. Rental agreements, regulatory compliance, intellectual property, and user rights can be embedded within Data Objects to ensure that the NFT usage adheres to predefined rules.

**ERC-7540 (Asynchronous ERC-4626 Tokenized Vaults)**: ERC-7540 vaults&apos;s are focused on asynchronous deposit and redemption. Integrating ERC-7540, either by Wrapping into a **Data Object** or by exposing an ERC-7208 **Data Manager**, will facilitate more complex financial products. DeFi products like undercollateralized loans, insurance products, or tokenized stocks often require operations to be handled in a non-instantaneous manner. However, the nature of these products requires adhering to regulatory compliance and identity management solutions. This can easily be achieved by implementing the use of on-chain adapters that enhance the logic while keeping the data secure.
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7208/erc-7208-compat</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7208/erc-7208-compat</guid>
      </item>
    
      <item>
        <title>Complexity analysis</title>
        <category>/</category>
        
        <description># Complexity analysis

## Network aggregates

Data complexity of the network aggregates does not increase as the new validity condition for the `beacon_aggregate_and_proof` gossipsub topic ensures that every network aggregate comprises a single committee.

## On chain aggregates

![image](/EIPs/assets/eip-7549/on_chain_aggregates.png)

The above plot shows potential optimisation effect of the proposed change. Namely, it is roughly 18KB to 4KB reduction in the size of a 64-committee aggregate for a 1 million validator set. Note that these numbers assume perfect aggregation.

### `MAX_ATTESTATIONS`

`MAX_ATTESTATIONS` parameter should be adjusted respectively to avoid increase of the block size.

![image](/EIPs/assets/eip-7549/max_attestations.png)

The above plot suggests `MAX_ATTESTATIONS = 8` as a reasonable limitation. Which means that assuming perfect aggregation the attestation capacity of the block increases from `128` committees to `8*64 = 512` committees, i.e. from `2` slots worth of attestations to `8`.

## Attester slashing

The plot below shows different variations of attester slashing data complexity. Numbers e.g. 64 vs 64 mean a number of committees which validator indices are represented by the corresponding `IndexedAttestation` structure. For instance, today every on chain aggregate comprises a single committee thus the worst case attester slashing produced from on chain aggregates will have two indexed attestations with `1_000_000 / 32 / 64 = 488` validator indices each, which is roughly `8 KB` of uncompressed data. With the proposed change an attester slashing obtained in the same way could require `488 KB` of uncompressed data because it could contain indices from up to 64 committees instead of just 1.

![image](/EIPs/assets/eip-7549/attester_slashing.png)

Note that in the case of attack entailing mass slashing the overall complexity of attester slashing data with the proposed change remains the same as it is with the status quo. However, the proposed changed increases the size of the beacon block as each slashing will contain up to 64 times more indices than with the status quo. The positive outcome here is that all slashable attestations can be processed during roughly one epoch (EIP-7549 makes this already possible).

The red line on the plot represents the case when one of the indexed attestations is obtained from an on chain aggregate and the other one from a network aggregate. Moreover, with the proposed change it is still possible to create a slashing from two network aggregates. Therefore, complexity of attester slashing data in case of a single slashing event depends on the _slasher database schema, i.e. whether or not a slasher has access to network aggregates_.

`MAX_ATTESTER_SLASHINGS = 1` is suggested to alleviate the increase of the attester slashing complexity.

### Compressed validator indices

Intuitively validator indices should compress well as there is just `20` bits of useful information per each validator index in the case of `1_000_000` validator set size. So `488 KB` of attester slashing data (the worst case) can be reduced to `153 KB` by employing a trivial compression algorithm.

_AttesterSlashing with 64x64 committees (1_000_000 validators) takes 320KB if compressed by Snappy (checked with PySpec SSZ test suite)._
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7549/complexity_analysis</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7549/complexity_analysis</guid>
      </item>
    
      <item>
        <title>Semantic Versioning 2.0.0</title>
        <category>/</category>
        
        <description>Semantic Versioning 2.0.0
==============================

Summary
-------

Given a version number MAJOR.MINOR.PATCH, increment the:

1. MAJOR version when you make incompatible API changes,
1. MINOR version when you add functionality in a backwards compatible
   manner, and
1. PATCH version when you make backwards compatible bug fixes.

Additional labels for pre-release and build metadata are available as extensions
to the MAJOR.MINOR.PATCH format.

Introduction
------------

In the world of software management there exists a dreaded place called
&quot;dependency hell.&quot; The bigger your system grows and the more packages you
integrate into your software, the more likely you are to find yourself, one
day, in this pit of despair.

In systems with many dependencies, releasing new package versions can quickly
become a nightmare. If the dependency specifications are too tight, you are in
danger of version lock (the inability to upgrade a package without having to
release new versions of every dependent package). If dependencies are
specified too loosely, you will inevitably be bitten by version promiscuity
(assuming compatibility with more future versions than is reasonable).
Dependency hell is where you are when version lock and/or version promiscuity
prevent you from easily and safely moving your project forward.

As a solution to this problem, we propose a simple set of rules and
requirements that dictate how version numbers are assigned and incremented.
These rules are based on but not necessarily limited to pre-existing
widespread common practices in use in both closed and open-source software.
For this system to work, you first need to declare a public API. This may
consist of documentation or be enforced by the code itself. Regardless, it is
important that this API be clear and precise. Once you identify your public
API, you communicate changes to it with specific increments to your version
number. Consider a version format of X.Y.Z (Major.Minor.Patch). Bug fixes not
affecting the API increment the patch version, backwards compatible API
additions/changes increment the minor version, and backwards incompatible API
changes increment the major version.

We call this system &quot;Semantic Versioning.&quot; Under this scheme, version numbers
and the way they change convey meaning about the underlying code and what has
been modified from one version to the next.

Semantic Versioning Specification (SemVer)
------------------------------------------

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;,
&quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be
interpreted as described in [RFC 2119](https://tools.ietf.org/html/rfc2119).

1. Software using Semantic Versioning MUST declare a public API. This API
could be declared in the code itself or exist strictly in documentation.
However it is done, it SHOULD be precise and comprehensive.

1. A normal version number MUST take the form X.Y.Z where X, Y, and Z are
non-negative integers, and MUST NOT contain leading zeroes. X is the
major version, Y is the minor version, and Z is the patch version.
Each element MUST increase numerically. For instance: 1.9.0 -&gt; 1.10.0 -&gt; 1.11.0.

1. Once a versioned package has been released, the contents of that version
MUST NOT be modified. Any modifications MUST be released as a new version.

1. Major version zero (0.y.z) is for initial development. Anything MAY change
at any time. The public API SHOULD NOT be considered stable.

1. Version 1.0.0 defines the public API. The way in which the version number
is incremented after this release is dependent on this public API and how it
changes.

1. Patch version Z (x.y.Z | x &gt; 0) MUST be incremented if only backwards
compatible bug fixes are introduced. A bug fix is defined as an internal
change that fixes incorrect behavior.

1. Minor version Y (x.Y.z | x &gt; 0) MUST be incremented if new, backwards
compatible functionality is introduced to the public API. It MUST be
incremented if any public API functionality is marked as deprecated. It MAY be
incremented if substantial new functionality or improvements are introduced
within the private code. It MAY include patch level changes. Patch version
MUST be reset to 0 when minor version is incremented.

1. Major version X (X.y.z | X &gt; 0) MUST be incremented if any backwards
incompatible changes are introduced to the public API. It MAY also include minor
and patch level changes. Patch and minor versions MUST be reset to 0 when major
version is incremented.

1. A pre-release version MAY be denoted by appending a hyphen and a
series of dot separated identifiers immediately following the patch
version. Identifiers MUST comprise only ASCII alphanumerics and hyphens
[0-9A-Za-z-]. Identifiers MUST NOT be empty. Numeric identifiers MUST
NOT include leading zeroes. Pre-release versions have a lower
precedence than the associated normal version. A pre-release version
indicates that the version is unstable and might not satisfy the
intended compatibility requirements as denoted by its associated
normal version. Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7,
1.0.0-x.7.z.92, 1.0.0-x-y-z.--.

1. Build metadata MAY be denoted by appending a plus sign and a series of dot
separated identifiers immediately following the patch or pre-release version.
Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-].
Identifiers MUST NOT be empty. Build metadata MUST be ignored when determining
version precedence. Thus two versions that differ only in the build metadata,
have the same precedence. Examples: 1.0.0-alpha+001, 1.0.0+20130313144700,
1.0.0-beta+exp.sha.5114f85, 1.0.0+21AF26D3----117B344092BD.

1. Precedence refers to how versions are compared to each other when ordered.

   1. Precedence MUST be calculated by separating the version into major,
      minor, patch and pre-release identifiers in that order (Build metadata
      does not figure into precedence).

   1. Precedence is determined by the first difference when comparing each of
      these identifiers from left to right as follows: Major, minor, and patch
      versions are always compared numerically.

      Example: 1.0.0 &lt; 2.0.0 &lt; 2.1.0 &lt; 2.1.1.

   1. When major, minor, and patch are equal, a pre-release version has lower
      precedence than a normal version:

      Example: 1.0.0-alpha &lt; 1.0.0.

   1. Precedence for two pre-release versions with the same major, minor, and
      patch version MUST be determined by comparing each dot separated identifier
      from left to right until a difference is found as follows:

      1. Identifiers consisting of only digits are compared numerically.

      1. Identifiers with letters or hyphens are compared lexically in ASCII
         sort order.

      1. Numeric identifiers always have lower precedence than non-numeric
         identifiers.

      1. A larger set of pre-release fields has a higher precedence than a
         smaller set, if all of the preceding identifiers are equal.

      Example: 1.0.0-alpha &lt; 1.0.0-alpha.1 &lt; 1.0.0-alpha.beta &lt; 1.0.0-beta &lt; 
      1.0.0-beta.2 &lt; 1.0.0-beta.11 &lt; 1.0.0-rc.1 &lt; 1.0.0.

Backus–Naur Form Grammar for Valid SemVer Versions
--------------------------------------------------
```
&lt;valid semver&gt; ::= &lt;version core&gt;
                 | &lt;version core&gt; &quot;-&quot; &lt;pre-release&gt;
                 | &lt;version core&gt; &quot;+&quot; &lt;build&gt;
                 | &lt;version core&gt; &quot;-&quot; &lt;pre-release&gt; &quot;+&quot; &lt;build&gt;

&lt;version core&gt; ::= &lt;major&gt; &quot;.&quot; &lt;minor&gt; &quot;.&quot; &lt;patch&gt;

&lt;major&gt; ::= &lt;numeric identifier&gt;

&lt;minor&gt; ::= &lt;numeric identifier&gt;

&lt;patch&gt; ::= &lt;numeric identifier&gt;

&lt;pre-release&gt; ::= &lt;dot-separated pre-release identifiers&gt;

&lt;dot-separated pre-release identifiers&gt; ::= &lt;pre-release identifier&gt;
                                          | &lt;pre-release identifier&gt; &quot;.&quot; &lt;dot-separated pre-release identifiers&gt;

&lt;build&gt; ::= &lt;dot-separated build identifiers&gt;

&lt;dot-separated build identifiers&gt; ::= &lt;build identifier&gt;
                                    | &lt;build identifier&gt; &quot;.&quot; &lt;dot-separated build identifiers&gt;

&lt;pre-release identifier&gt; ::= &lt;alphanumeric identifier&gt;
                           | &lt;numeric identifier&gt;

&lt;build identifier&gt; ::= &lt;alphanumeric identifier&gt;
                     | &lt;digits&gt;

&lt;alphanumeric identifier&gt; ::= &lt;non-digit&gt;
                            | &lt;non-digit&gt; &lt;identifier characters&gt;
                            | &lt;identifier characters&gt; &lt;non-digit&gt;
                            | &lt;identifier characters&gt; &lt;non-digit&gt; &lt;identifier characters&gt;

&lt;numeric identifier&gt; ::= &quot;0&quot;
                       | &lt;positive digit&gt;
                       | &lt;positive digit&gt; &lt;digits&gt;

&lt;identifier characters&gt; ::= &lt;identifier character&gt;
                          | &lt;identifier character&gt; &lt;identifier characters&gt;

&lt;identifier character&gt; ::= &lt;digit&gt;
                         | &lt;non-digit&gt;

&lt;non-digit&gt; ::= &lt;letter&gt;
              | &quot;-&quot;

&lt;digits&gt; ::= &lt;digit&gt;
           | &lt;digit&gt; &lt;digits&gt;

&lt;digit&gt; ::= &quot;0&quot;
          | &lt;positive digit&gt;

&lt;positive digit&gt; ::= &quot;1&quot; | &quot;2&quot; | &quot;3&quot; | &quot;4&quot; | &quot;5&quot; | &quot;6&quot; | &quot;7&quot; | &quot;8&quot; | &quot;9&quot;

&lt;letter&gt; ::= &quot;A&quot; | &quot;B&quot; | &quot;C&quot; | &quot;D&quot; | &quot;E&quot; | &quot;F&quot; | &quot;G&quot; | &quot;H&quot; | &quot;I&quot; | &quot;J&quot;
           | &quot;K&quot; | &quot;L&quot; | &quot;M&quot; | &quot;N&quot; | &quot;O&quot; | &quot;P&quot; | &quot;Q&quot; | &quot;R&quot; | &quot;S&quot; | &quot;T&quot;
           | &quot;U&quot; | &quot;V&quot; | &quot;W&quot; | &quot;X&quot; | &quot;Y&quot; | &quot;Z&quot; | &quot;a&quot; | &quot;b&quot; | &quot;c&quot; | &quot;d&quot;
           | &quot;e&quot; | &quot;f&quot; | &quot;g&quot; | &quot;h&quot; | &quot;i&quot; | &quot;j&quot; | &quot;k&quot; | &quot;l&quot; | &quot;m&quot; | &quot;n&quot;
           | &quot;o&quot; | &quot;p&quot; | &quot;q&quot; | &quot;r&quot; | &quot;s&quot; | &quot;t&quot; | &quot;u&quot; | &quot;v&quot; | &quot;w&quot; | &quot;x&quot;
           | &quot;y&quot; | &quot;z&quot;
```

Why Use Semantic Versioning?
----------------------------

This is not a new or revolutionary idea. In fact, you probably do something
close to this already. The problem is that &quot;close&quot; isn&apos;t good enough. Without
compliance to some sort of formal specification, version numbers are
essentially useless for dependency management. By giving a name and clear
definition to the above ideas, it becomes easy to communicate your intentions
to the users of your software. Once these intentions are clear, flexible (but
not too flexible) dependency specifications can finally be made.

A simple example will demonstrate how Semantic Versioning can make dependency
hell a thing of the past. Consider a library called &quot;Firetruck.&quot; It requires a
Semantically Versioned package named &quot;Ladder.&quot; At the time that Firetruck is
created, Ladder is at version 3.1.0. Since Firetruck uses some functionality
that was first introduced in 3.1.0, you can safely specify the Ladder
dependency as greater than or equal to 3.1.0 but less than 4.0.0. Now, when
Ladder version 3.1.1 and 3.2.0 become available, you can release them to your
package management system and know that they will be compatible with existing
dependent software.

As a responsible developer you will, of course, want to verify that any
package upgrades function as advertised. The real world is a messy place;
there&apos;s nothing we can do about that but be vigilant. What you can do is let
Semantic Versioning provide you with a sane way to release and upgrade
packages without having to roll new versions of dependent packages, saving you
time and hassle.

If all of this sounds desirable, all you need to do to start using Semantic
Versioning is to declare that you are doing so and then follow the rules. Link
to this website from your README so others know the rules and can benefit from
them.

FAQ
---

### How should I deal with revisions in the 0.y.z initial development phase?

The simplest thing to do is start your initial development release at 0.1.0
and then increment the minor version for each subsequent release.

### How do I know when to release 1.0.0?

If your software is being used in production, it should probably already be
1.0.0. If you have a stable API on which users have come to depend, you should
be 1.0.0. If you&apos;re worrying a lot about backwards compatibility, you should
probably already be 1.0.0.

### Doesn&apos;t this discourage rapid development and fast iteration?

Major version zero is all about rapid development. If you&apos;re changing the API
every day you should either still be in version 0.y.z or on a separate
development branch working on the next major version.

### If even the tiniest backwards incompatible changes to the public API require a major version bump, won&apos;t I end up at version 42.0.0 very rapidly?

This is a question of responsible development and foresight. Incompatible
changes should not be introduced lightly to software that has a lot of
dependent code. The cost that must be incurred to upgrade can be significant.
Having to bump major versions to release incompatible changes means you&apos;ll
think through the impact of your changes, and evaluate the cost/benefit ratio
involved.

### Documenting the entire public API is too much work!

It is your responsibility as a professional developer to properly document
software that is intended for use by others. Managing software complexity is a
hugely important part of keeping a project efficient, and that&apos;s hard to do if
nobody knows how to use your software, or what methods are safe to call. In
the long run, Semantic Versioning, and the insistence on a well defined public
API can keep everyone and everything running smoothly.

### What do I do if I accidentally release a backwards incompatible change as a minor version?

As soon as you realize that you&apos;ve broken the Semantic Versioning spec, fix
the problem and release a new minor version that corrects the problem and
restores backwards compatibility. Even under this circumstance, it is
unacceptable to modify versioned releases. If it&apos;s appropriate,
document the offending version and inform your users of the problem so that
they are aware of the offending version.

### What should I do if I update my own dependencies without changing the public API?

That would be considered compatible since it does not affect the public API.
Software that explicitly depends on the same dependencies as your package
should have their own dependency specifications and the author will notice any
conflicts. Determining whether the change is a patch level or minor level
modification depends on whether you updated your dependencies in order to fix
a bug or introduce new functionality. We would usually expect additional code
for the latter instance, in which case it&apos;s obviously a minor level increment.

### What if I inadvertently alter the public API in a way that is not compliant with the version number change (i.e. the code incorrectly introduces a major breaking change in a patch release)?

Use your best judgment. If you have a huge audience that will be drastically
impacted by changing the behavior back to what the public API intended, then
it may be best to perform a major version release, even though the fix could
strictly be considered a patch release. Remember, Semantic Versioning is all
about conveying meaning by how the version number changes. If these changes
are important to your users, use the version number to inform them.

### How should I handle deprecating functionality?

Deprecating existing functionality is a normal part of software development and
is often required to make forward progress. When you deprecate part of your
public API, you should do two things: (1) update your documentation to let
users know about the change, (2) issue a new minor release with the deprecation
in place. Before you completely remove the functionality in a new major release
there should be at least one minor release that contains the deprecation so
that users can smoothly transition to the new API.

### Does SemVer have a size limit on the version string?

No, but use good judgment. A 255 character version string is probably overkill,
for example. Also, specific systems may impose their own limits on the size of
the string.

### Is &quot;v1.2.3&quot; a semantic version?

No, &quot;v1.2.3&quot; is not a semantic version. However, prefixing a semantic version
with a &quot;v&quot; is a common way (in English) to indicate it is a version number.
Abbreviating &quot;version&quot; as &quot;v&quot; is often seen with version control. Example:
`git tag v1.2.3 -m &quot;Release version 1.2.3&quot;`, in which case &quot;v1.2.3&quot; is a tag
name and the semantic version is &quot;1.2.3&quot;.

### Is there a suggested regular expression (RegEx) to check a SemVer string?

There are two. One with named groups for those systems that support them
(PCRE [Perl Compatible Regular Expressions, i.e. Perl, PHP and R], Python
and Go).

See: &lt;https://regex101.com/r/Ly7O1x/3/&gt;

```
^(?P&lt;major&gt;0|[1-9]\d*)\.(?P&lt;minor&gt;0|[1-9]\d*)\.(?P&lt;patch&gt;0|[1-9]\d*)(?:-(?P&lt;prerelease&gt;(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P&lt;buildmetadata&gt;[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$
```

And one with numbered capture groups instead (so cg1 = major, cg2 = minor,
cg3 = patch, cg4 = prerelease and cg5 = buildmetadata) that is compatible
with ECMA Script (JavaScript), PCRE (Perl Compatible Regular Expressions,
i.e. Perl, PHP and R), Python and Go.

See: &lt;https://regex101.com/r/vkijKf/1/&gt;

```
^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$
```

About
-----

The Semantic Versioning specification was originally authored by [Tom
Preston-Werner](https://tom.preston-werner.com), inventor of Gravatar and
cofounder of GitHub.

If you&apos;d like to leave feedback, please [open an issue on
GitHub](https://github.com/semver/semver/issues).

License
-------

[Creative Commons ― CC BY 3.0](https://creativecommons.org/licenses/by/3.0/)
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7577/semver</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7577/semver</guid>
      </item>
    
      <item>
        <title>Set of test vectors to perform benchmarking of EIP-7619</title>
        <category>/</category>
        
        <description># Set of test vectors to perform benchmarking of EIP-7619

## Inlined vectors

Here is the list of well formatted and valid signature vectors to perform benchmarking. These vectors were based on [original falcon test vectors](https://falcon-sign.info/). Original vectors were encoded using abiEcodeWithSignature taking the message, public key, and signature as inputs. The method signature is `verify(bytes,bytes,bytes)`

```
[{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000002903933b3c07507e4201748494d832b6ee2a6c93bff9b0ee343b550d1f85a3d0de0d704c6d178429513090765843d1e460d17a527d2bca405bd55bbc7da09a8c620be0af4a767d9db96b80f55e466676751eaaba7b93b86d71132daa0eb376782b9eee37519ce10fdd33fe9f29312c31d8736206d165cf4c528aa3ddc017845e1f0dd5b0a44ff961c42d874a95533e5b438982f524ca954d87533bfbe42c63ff2abc77a34c79db55a99171bbcb72c842a6530af2f753f0c34ac632f9f1e7949f0bf6c67665b27722a8857d626b6ff1a136d923a39f4069b7477ff946e5247a6627791d49b59edc9e2525a860e6e9828d18f64a9f17222e8166a02453859bbda0b8186d8c9928bb571e4146401d7430e225904673ad21ccac54c146c248a1dd69ab6491e901d6d71b152155be97de057f3916a3f1b4273308c29b2f4d9697167b90681b1583ed930a71e990467dea368134beceebd597f9bec922e816f1b0570d728f4ae0464c1f797657f87a4e52dcdcaeb9272662ea66d7c6cd8781b31af555ad93f5f65e75816cb8dc306bb67e592b5261baca7c509629ea2af8abb80cba89ee535b76dfd9ccbbe3bf48f2bc8aa34b26e1103291053f5cb8de3a45afa5a76df8b2122ed2c82fbcf2259290d41a14f86b12f35f5d49762b34cff13ee7e42edec70201d7f37c33316288fa3078e36e58108865c3cfe263d563692043decc62f3426f86061285b7b1b336f56ff41bb65e9cd6d9b92fd90f864aa1c923cb8c755f5cde1770d862595427149d7721aaab5d194aea9acdeca15be43cba6a62b5a33909e9fc4da1c5814fbd7cd6a2fa572e318b42c6c319140b86e66392580a11a2b431f44c1f9270e4f7b2490f3b325a9977a71a575915636635b9969dbd6d220b24c3d99cebbbd834b88222bd08c3abe124e80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381096ba86cb658a8f445c9a5e4c28374bec879c8655f68526923240918074d0147c03162e4a49200648c652803c6fd7509ae9aa799d6310d0bd42724e0635920186207000767ca5a8546b1755308c304b84fc93b069e265985b398d6b834698287ff829aa820f17a7f4226ab21f601ebd7175226bab256d8888f009032566d6383d68457ea155a94301870d589c678ed304259e9d37b193bc2a7ccbcbec51d69158c44073aec9792630253318bc954dbf50d15028290dc2d309c7b7b02a6823744d463da17749595cb77e6d16d20d1b4c3aad89d320ebe5a672bb96d6cd5c1efec8b811200cbb062e473352540eddef8af9499f8cdd1dc7c6873f0c7a6bcb7097560271f946849b7f373640bb69ca9b518aa380a6eb0a7275ee84e9c221aed88f5bfbaf43a3ede8e6aa42558104faf800e018441930376c6f6e751569971f47adbca5ca00c801988f317a18722a29298925ea154dbc9024e120524a2d41dc0f18fd8d909f6c50977404e201767078ba9a1f9e40a8b2ba9c01b7da3a0b73a4c2a6b4f518bbee3455d0af2204ddc031c805c72ccb647940b1e6794d859aaebcea0deb581d61b9248bd9697b5cb974a8176e8f910469cae0ab4ed92d2aee9f7eb50296daf8057476305c1189d1d9840a0944f0447fb81e511420e67891b98fa6c257034d5a063437d379177ce8d3fa6eaf12e2dbb7eb8e498481612b1929617da5fb45e4cdf893927d8ba842aa861d9c50471c6d0c6df7e2bb26465a0eb6a3a709de792aafaaf922aa95dd5920b72b4b8856c6e632860b10f5cc08450003671af388961872b466400adb815ba81ea794945d19a100622a6ca0d41c4ea620c21dc125119e372418f04402d9fa7180f7bc89afa54f8082244a42f46e5b5abce87b50a7d6febe8d7bbbac92657cbda1db7c25572a4c1d0baea30447a865a2b1036b880037e2f4d26d453e9e913259779e9169b28a62eb809a5c744e04e260e1f2bbda874f1ac674839ddb47b3148c5946de0180148b7973d63c58193b17cd05d16e80cd7928c2a338363a23a81c0608c87505589b9da1c617e7b70786b6754fbb30a5816810b9e126cfcc5aa49326e9d842973874b6359b5db75610ba68a98c7b5e83f125a82522e13b83fb8f864e2a97b73b5d544a7415b6504a13939eab1595d64faf41fab25a864a574de524405e878339877886d2fc07fa0311508252413edfa1158466667aff78386daf7cb4c9b850992f96e20525330599ab601d454688e294c8c3e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021d81c4d8d734fcbfbeade3d3f8a039faa2a2c9957e835ad55b22e75bf57bb556ac800000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 0&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000002913908e25538484cd7f1613248fe6c9f6b4ec14be684c6defdd1e41333b6e9052ac4340e314eea2c99f7e62b31023eb236b557957f7174885220923a7763217d9fe59b5ba53157ced51cd4d9ab93b38c666d2047c4fa21aee43c95ea373f6d62f0e044bdb0be988685154ef7682617c7367b30d934b1d9c89229d281734a3005124b8d7c70b78e1634a3a20ccf9ab952c816dfad3d173567c139bdc624512f23f2a0c2f78c2be16d8f9b119d64ba6dec5e50ad104d8ba25edc9e53996f75d848caa0e4421167dd4d42d07d39c3e35d10924c1a8a9e098aa4d6112c67dbbf08c7a0888aeb657456c19e2259621edc3af8978de9c429b8167e679687a86cbb66403fbc6ee69f3f1344d07e845a865f22e5e94d9748cc12065fe1926d83cb288918c82d19fd5416de27576df8e45de1bd74351d996514748ae9018d27f57edb1de46975feba5e6d9bb1491c2a327bf158d03d2fbe0882ee0adc9b8121876dd9ef5c37f58d325af59b94df324cce5bc1216c8f4ecd0b4bb5728f83beeab09bfe3966cebdf4657ec6cfd773f0d5dba5bf28481dcb21aa1984e9c6d2168e350b4d6491d81967be0e354c869a8487f0f939f537a58df88abf2e4fadb55250897a54a8475d160d697a77da36bbb1438245b35dee2ac791920c9fad8025adc8dfa88b168716c5a45075a3f9536bce6238e1ad4d41995d675d3cb71ad4ce33d0326ec2a9f5b9c1dc6750ecaa6aeaad4c0edcc4a5015eb3f7503ba2210b16665f889e4d1cf3a9e298d61b23846593fd4d772c646dd024823371d531094cbb17902db113796852161f5d2a12608b3c1bcece960aad07952671e4cd6186b7ecfbc7710258b8b26cfa3f1cecc61121a49dd276e4b124e3573ac8231b60c778e03b74926e2bfbecd42f352bc325cf2204b3c0b5730e6188cfc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109baccc8d6c916c9ad12e3e49881f732b84870ce5976921d197a00d226ab8825430da78f19b0e7a12129ecb739d4a05c5ebb0019f0c610e14556a0b4c7a48e2e4cc851d2e8a57417e48f918b56dc605d25113451c3b10520f81c016a63c6f2d8826b90b04d8b0a792272607e39829adf4b09c0cafb11cf2f893c56b26420f84901ff072f9100013536822d512792643df4ede4b64200ae0bf82b7d46792eeae3571f501a9a814e69f21e84dc263457b913957886af9da2598003e853ac23b4d682971507b85bfeb146010b4b0cdd3f00af806cbd56a32987e38532ae3c7794058215c5db042026ac7dfa58ea5b17b8ae91e06a07db253e21eff361ec063412b227fe2cf9592c6b4888589f0a3a7fb9a300b131fc4ae755ce16a1554be6ce0f4e8301bb814e2d1903a209f0744687024949876ac94187fce08655c2131f2a448864cd6c77783ea2de6c1042c68e389f6d068eec2199dc9b6e92edd4469a923a683ab1c49557c19d9cc9a3822b628862a9e5df2b152f898172f3c5fda506c2b21e10ed39cc1cebf50b889c493e1b6614a53c30ee7be94abe59d83c270350ad490e2f9205e5607ae9328322c60aacacea9af2a12114626964b68af104aa3b34c1a9e0ae1885314891710b3ace65f54f40451abe425fd7af4218ffd067a2f61e32d851831aab032c0fa95bcc5504fcf8c180a9ea6d14cb23e35df931c40766468487612a172575d0ba6f20c225ab82a562f0eef6d20ed239da08287dde67701d2c29368dbe52acbbe0f219200535add286e6eb88e4f1643e922b2accbe8a3b52737a60a4344544966e66b7da65657b5bde6343b5987111c6863446c04415e0d985ab534e1d7eac615dc08e8f3d2a73d6057418368ad1dfa7001e647876cd50d589765695cf9715739e5d42fa684c51c9077a95e7eb31b87ba1808882b0cd9fa0f5d4f26d596af17f22dd09c18836106f5979203b01d10707840c80249f9b963080fd5221c250ae405f5a5d0c312b6ea8971a998324c542323808cc9a81a42aa9df3c9080bcb4cf5bd73dfe5c080ceaaa66e0fae05d88f23b76732ba4094c2d30fd16d26ac4247291fa2543b7751eff202113588b76a1646ecc6aa17861db54d5adbbfd3ae11423f3a78e8342deee705e98bf8bda82731a520374c69c6593c5d755c498f7b454c0185758c94b580d4257d66f71ead38205e2cc717032f1865649642472c5f34e1854040c63369c8317c1fc37518b16637840a86627113e3809a700cc1b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042225d5ce2ceac61930a07503fb59f7c2f936a3e075481da3ca299a80f8c5df9223a073e7b90e02ebf98ca2227eba38c1ab2568209e46dba961869c6f83983b17dcd49000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 1&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000002933987a6704b1dca3cda547250dbca1c94a4289c8d61e6a6caa946409782f9fc305cb1f5257f9bcc68036b80697cd9dd2cf98ac8da1cc94432e93180d313c447d023f3b657ab4cd49d1e5d776db772d8fa7479a24b121f818a110c92733d3bcf272f769059781c8f2a05f7e5297f96dd2aaf93371ce87b35571faf494ced71a1ba15c5001c29626ec399cd265ebcc5a8bb5279e7db529079e771918fd27964d5233636b435c2e6ea568cd90f6cbcbb9dd31c8912bf81c94eff353d44a11f9ee46191195136523ffde3947723660f0e73bbd56e5bb18c8430a9ef8f2997275eac4ce5554eea4b34718e5c68cf55838485415aaefa5d169dbdfa1c093a94a429f2838420eba43c80c592c63cd529dac89c8131c1c6518d49768322483c0153ea7962a74e4b33ff754c1f7e30b05d7567762c40d3e3c193330b6b958fdd941c4f9799f122c8f401e4de4d11745d1090263c2b29155191443545c736c6f0d13045560bc5b1fa0e635d18bbdaa34670d6766b29fe28e06a719c16b58cf5e9590770e5a7d67839d078a76e9b6905752b245688361aeada3e64106584892193fcf60ee4ef695d4f0eed0d4098c609726109dc125a591c67c5262256f749374490545bb71ca427d556ad0dbd5d3ed10abd68cbae5086ad505733a8360fd9f6539e62cd753d3a5829031832510ce8edd1dd1b3865e8d4430943449e3cbae7bd2fcd9c228ac428f871ab67bc836dde9cbf54cdec4b1069ee55c24faaafb0aff2229491152574d31e4dae9bfafba89f9abe28bc64fa7fdefb5c753a6c926c8084db42e834cb01a264322d2b85235aac65a60552f7c309db9bffb7a7327508a3c14c833f01674c761ac8a9f2a8bba7d974a23570b654edffdbfd06664290ce5adf35c560d0b986d3cb9df660ddffac20f2ba4c6773ccfe55918200000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109a26849868d082c87bdca6bb1e88d36216c5bd3220d55a6072a77aec88d6874e3508cd65fd93cc5170ec237197c895386e4bf7d9002e09279a51ccf68aa41b52a7944f3400fa7100cfe774a6fc69f0682e984527661c03ad6c405927c4a3be5db077b2c8e97e834489a8f4823c51059d77dbef762a6ce0c9968ad1b1be6fa927cd20bd1cc5b8b2ec699fcd7f62bca7066934f8b6f8606f6bf0a88bf5a20dbfbc769ab1663805906139ed205869acaafbcee4d28f8a995a9f8f5b94941125d2a5e0a2adf4facf5f29ac98337802607a5fb28ba13ac18a8e74953a3d81535ad5a99624464f79aeeda4ef663d25f01df8739bf62d261574ec2f8f9f59f56954a9e880f820a0d806028b181bb5251c2b5e19bf25faa9e42399e3643ed9d38d5927d9571b993fda7e34628ba61c22a151d1ea7d65b4e8541ed9d020f0a7610e867109ac17990fed9d757a3495bc6f860a081c384f4b1aa0f2ac647e44160bce0263a58ab59170133a162db70eb692d52eede0306941046cc4b572adfb8b835ed618616ac596ec2fa2b946f82103cf7b6abbd273e22b860ce523f6cf7546a0d432a085f01231ab8ad041ab8bc53dbb7d435f35c85a5b108cc19a792e41f9a7187856a0cb4f434f2206b1e724d789925df8b3c9862d5e7e57a626accb6b4aad29a586dfa1c06bd906adc74e9df379f56695a7465ad6d5127276d1e5904299aea6c0de978d29655ad2ff249268d939728c11d2c892b89826e1a6d9041974e3d641d0a3112dd38601c7187d1904862a55f4943276019565248f184796bcab4517cc8402656e96924d779917ed2185128a88e989c13fd2bc24fea58d4ff857105ecf648bdccd3a910e9ab0a1902a4a0f0c01963453edeb8dad9de230c29fa055e953b32fc959129d4858e9060c559ef8859ccb80a41041e3922ac6a8bde78586cd98bb8efec567dd1a77e19f2b1246ec44f816b6c753c262b0cc66cdebe282609847d8299b47098a1a6a90e463598f82aa43d2b81cae88ff45d8ac7a4941a3a90515fece50d340148a4ebb167be7556366b632a0eeb95e683587015bc07c209d1691ac832574bfb655874bb8553250eec6fc7ad15f15d611d10152429b8580d4429d784922c2ec2309c1802bae24a01dc6b0a8959b6b0dcdf0be67bc534e8c3609e825adb62314e52ba18f0473a9892b894cdc2c253ee8186d26a538e466920be4f440dc2c052ca09af439c82bb44d7ce370006c18546ac670ae38bf3c2820ce479959dcd780000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000632b8c4b0f29363eaee469a7e33524538aa066ae98980eaa19d1f10593203da2143b9e9e1973f7ff0e6c6aaa3c0b900e50d003412efe96deece3046d8c46bc7709228789775abdf56aed6416c90033780cb7a4984815da1b14660dcf34aa34bf82cebbcf0000000000000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 2&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028e394678201b357b0d2dade863a0a0a04d0c021febb0393e020f02c1139b6fd32461b3d7c621c39183ac0fb9ed693b4a36aad585641375a778dc6ea6fbb8e9c5437c52547468ac8498f5b684c932be7b6cd053fe8eddaeee554ae77cec6e53fa1eec85338b8eff9e4a2b453938ccfc98bc81ae4f5b8851c3931cb3670e39108341b4699cf43db9ec5cbcf6189c6ca9ba95e27848c45ffe4cdd08df65a14183ac9442ff589609f2294835448ca778865ac9ac91ce5738d3d254f3d2cdea10d0a3110b1f7a1751f66b294fae21fe57389a98939115c36fe118160e37c1d2ed89226aff6332eea5b6f08b43676eea1a4ce1e5a21f4196240dc625034b372da6b67386cc49d3223d985b2c4ea607f12cfbd09154b79e9e572e3eca7eb45a6d7a15e78bb96f75ae6e6d9a4d77d7250ebbdd56be91fdb790f15362280e1630eb398a177e5d2fb6c27274cd3c8906b8bb13bd8d465e47dcd983d571e59c9b0586757062d547832443278da72e23ebc0cfe54e026b516c997ed9855e1ff50589c4461b9997b761305b237b9c0ce201284997daeff8c7be3a7cff65b9b449a858ccf5c3e12161a69107c1f7fbd1ccd781d01b25f9dedb1e1ce39eaba01f9e714173a0dc1f83868a108aeef3b69c401d33b3af2bcb4e24ea2f18e1ce4a3a70b57d2cca28a4539c922997a9c751ba36f1f46e95efa0cd71877ade3d92f9a7f7c1f68cc196b70677a2c165253a85fad1b15236d9daa375da638a6db923c84314063185f6d235f738bb18d7e6399449eb2b7a35c9736df9cebc71617b9ed19a945fc7df40a574064eeee9f590141d62f1992879ce8e0a69f5bb33e93a5ceec014815c2f9c3484dbef569739d29ce8e43528a693590f3427de964ab4673a3d0659dcbed32b2686d0dc9a7f272a91a231858b007aeb100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381095a4cd8dbb5e94c93fe67a111582d99659b90e15b8a8cdd282af74e7f9576063a01d00e8c0a1f96cc8d944450f2e13e6978854cf645baed424c060040214bf90892ef584110e282d572164e51dc7e7e29b0de8daa7be034521f2cd46890fda0a8c5970a69bf96666fea57e9982ac20b93a78dfecbdd9e8a54bcfcf040ae7679e533a13d527816917762d2a2779225ae0345ebf0245a98a4c493b610dd8126e30ef4265ea112016c325d5d1c08f9e8610b1af0441cd0bd729209a4d900906a11852327e9ac6e504ba0eb1e343b9828094f4648248a03e00c0e944ad9496568d8d03cfec9149645d359066960b8e7a2092c5eb4bc9ab24abd196442872b612eeba910abe9945a24e14451c58de91660152cc72596347993ef8f39c953f2e26057aa0c5404c1a28445b0b0e8681f5ca714b3c4b48eaa4920fe47d1a7b304b4e2c4f29c10968c454a2448a24eccafbb6494e1a400cb909b8d6a205cd085a5c444bce049c098603b9fa8c9b7bf4763338a9461a32885220cf6b85bd4597d0a63e6d92e677151e329d3eb75a200dd78cc419044da6b72799ed847f2c8650215db04a8fc7bd3a48b7108703483e4556c78e8078b2eed0e5abb3a44052e9ce07e96cd095dab3979f8e886bcb9ea69b5d4d8a8a3726aa0b849f315217c877ca56b42da44a1b884c5be6d3d46c16bd01df24478cedd8dbd61fc36651adc42aa41e51c8a8b5a5514c08beceb6f820ba023d9867ddd2d1131c03c55ddd70a4bc60b16aaa380089da07baa1ce9d7c218b3b298e868ec5a492645cb7f5e6229edcf394493725699994044c63ac000c6b18802880d5083d1cf928203646da23f8faa6f5eec49d181ad166983e5c147b172ca8d48d210ae9bcaa5c5845a0d44c0afe6c31c956fb0e0d77387d56150a37982da6b7f8ec279189f1f09086040935b2eb756c47789537ebbfcb1f197d57f6f49a6893328279ef9be2b76c8ea4ae2b06233e057bcfd34d5c22cdc61700a7a1d926381d035fa468cf396ecbb29614b0b7e2c4bbb6624ac6a40eb24320ef3548a2115dbcd2b571cf795c7da111f80434802cb1d6a5a8764c9df861a026ea34b698d25321907452046b3aa6d5154d902065a7d618e5ad102613551ef6ee684100b45564110a2ce86563fe4efb1753b44c8ae0999524a51ba4df49aee8e3780e0e027f4d6376206187b8e3c17868b1e810c38455983aa4335c4e243d5201125ad99cb1408a7ae9ef51deb6816fd418bddeb988f78bd091eec230000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000842f7af5b52a046471efcd720c9384919be05a61cde8e8b01251c5ab885e820fd36ed9ff6fdf45783ec81a86728cbb74b426adff96123c08fac2bc6c58a9c0dd71761292262c65f20df47751f0831770a6bb7b3760bb7f5efffb6e11ac35f353a6f24400b80b287834e92c9cf0d3c949d6dca31b0b94e0e3312e8bd02174b170c2ca9355fe00000000000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 3&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028b397b89ab5bf11f5209ae360448d66b086e87ca103a6b5b007a95bcc5bf32f31ffbdab61f31ae1296831276d57c01ef83ffa0b0131da5cf7c545ac3fd9917eeb6edd2d7be330ed080a3d8536ee3f67dad1df0ff5a687893d7feb6a0ada0a153e8f0c55914cfbc529facead19930fef98ff18a8ca6abde1771c052f25c5806511bd4b7300cb6106fb3d36bde165e81f386b1da7a55c6f391f13ad98483db61a12c8996cd0d39a6bdb2d8c99a2f2b8d0e7c156b375f251b8798dd07b3273b99cace32513d8662c88c42e0b3e5bee8640f2f6752f4c8bb0a782666e745bfbf60d0bb1fa31b08ca927b34620ca3ed535c9fb62da94d11464922213458f74228e9a573697d066745deacedaee6466a20b428832364ebd0bbac1fa2d97ad1e9161a7d817b762238ed3ac9be96e4e0e7bf0b13de6297fbaa628dc5a45b3d0918d147d562846a5f0a87c15bd8b167bfb663511e0f7abf9cc3b3f94b0dbd4b7c310fa5c209869f28497ecb14b830505e24cce453a222a887ccf20e8318a5dc733cf835325baf13698bd3538adb62ef896442b4f5a7ecd231133aad4303ecf330dbbcc39d272cd037922f9a4e8cf3b8a5e54f5e0b7efaba938e555698abee35e86c5d59f2cc17681ace9b34ac2f0d4171ea4e02e1cbef7af36e992949b5a2dda8c8d3dbec1f15a959e08f6b3b47402ed9513748e1386bfdde46cc23eab472e3c6cbfa68316543c2a5e410d1937bf50cd3530769ca740eaa0a732edae2daecbb75db8d73ba7fa9df0d868c5a1f54f92853f1a6b49af37d8e04cf21734cc5d733c0663ade1a0e36632820fe58323e7ca08f591779235c4d8f15e9846d4c44ea3f1fa6b0febd2885909b6d5252a598ba9d27e917a6b6129c01ecaee889c76a0f3f4125914d42a6c12564ba599de7483a0c74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109ab4e1b27bb837071e86f45921a7cb6c2f0a95b65f86c5266ca4e91b2057efd23a1226f5c6e7ed0dfa5052411ee463a52129b6d3eeb31550d4e66abf8b05f4e774e37935204056f2d8a58005e0bb85deec4ec13ec280c577677949333bae642c04db049f8c20bdad79272e25208aa2c89847232927d134c6acde588cf68c66ed90549aa68f3a9b44177092d35533d21819b4d474c213b98a5295a91d29a78e70a45b8549af1750e52becd8c97f182c9afe8a9cb3ed67ca3c8210804cf566f687d1173461421c9d3507be3a6624e5444f3cc11232673babe5d8f7c71bc026b0a4e5b08c69705c9aa1ed2b214f295894c35d3f6d197b14f843768e12f8f1a258ff0361e84a959a67474ccdc3ac9ac5881c6c373e56e9749af6c5ac0a5a3b807a31bdd3e18ba0e2059a8f85547284e433c802351ded0b4411c0b3ce3e58191a450ef124c5b1ad0a06eebe50fd8309bd8c8398dadfec29360b6a6566096e3014bab2ab9c143881c5706703a9c62922f249c8af29f539389b59737a2ae69ac2be00605288e9ec311e14f932bf204fad695874cc9fc87b95cc6580652ea9da51cba61d317439c0ca6090d27ee6a7723b200420c27025132ae4923177fb3daa0a474dfb55a92d478f2e70ba14cd86a0d8c6bb865a71190e67386194261b1a61f19f6d8256e1c9782cdc412ba9b626f1d59c8b94dd347668d893cd074028ad9f7e06a3434b68de64028df5679b4e881949890b5ad4b7366072b39f0b63997b3a0b21570a8172fa852cb16965df4b73453d0f7dada09b59d288561c0110a19b710dacb94ba9b94125a42724037939221b14b220eb8cec3962e91da95038d38aa5573db97117e0cdc14d1eeea0da8c920fb59d5c09b4699545845112249206624195192c88a5a09060178a53831bf6fa43b269c783d509f1b4d377336965a6232a0b38798b262bc68eadc18be1b64cca2e9ab53478c8e823960948d6ee39a37ecff3929b7887e89a7936e3aa95a8c183a71d34bc39f176059cf659b1c6d79089474b501d02cb41ea2c78db533f8f2d4d3caf61aa04f1204829f7a589946f7d3acbeba6498bd2b9450b24d35c5125d8a6a065a8c4ee583fae7e6dc474322a9f1a1209ac38076c08020e9588791428662a0741776db03fb1b2242c64ec6534fd9864947eb3adb246a2029884e4cfc21844181d813289d4c4b6197d0938d6402967ec1cb4698d13784cd3d3aa03048754c321fd20f6af06d7e18bc7fd71d8a8c218e7fb0cf0e2e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a51cdf0ae1124780a8ff00318f779a3b86b3504d059ca7ab3fe4d6eae9fd46428d1dabb704c0735a8fe8708f409741017b723d9a304e54fdc5789a7b0748c2464b7308ac9665115644c569ae253d5205751342574c03346dddc1950a6273546616b96d0c5ece0a044af0edefbe445f9ae37da5afb8d22a56d9fd1801425a0a276f48431d7af039521e549551481391fe5f4ebfb7644d9f9782d83a95137e84ea3aeb3c2f8099000000000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 4&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028d392128952d1a2c9c635584ff941bc2363b2592c7f88ff0436c86dc22c39f80b43272e03082fc47c96699c58abae3ce93dce4b93739b0329a1f3ea59d58040d42a157bad2c58fc1158ea995d1523b98331f0894fe0e89c8b3fe9485a33adac5b2764d1c62180b348882e5a0bb1faf697d6270eb292789cf5d1d8ee61dcf88f1a67eeebf37d1b79066bfd8bfe6ae81d3ac3238ca7c12647f244f6406486358320f3ed148e789d20cde6c2f02f516490a7f4de042e71afca4a94dccf1729b4e5705e649a31c06c6fe9ff817933d872e3fff9e520116ca795e3fb4ca3fa8e555baedfb5cad72fed22739afd5add33dc6fb4f3ec0c69f3d873bc0840c1d9e224e3fac2eb312e33813790403c4df64163a4eb3098830f8a40241bdc0c8231180cc6b2fc8adfb9cd7d9fc0d5297cd29a6355a74675e35bcd2a2adefa6f9a5c7921d8ed3f49325aec76b69b5f32cf529b358363e944d096d39edd2205aa7e887a9c69f5c9238672a3c85ce9e3adc06cbd7713ebd4cdea898b7085b835dd69d994b02a8c5faf183daae29cce7f62b059ef669c8efb930583cffd9e49625336832502f46d3a64a6e8be308dabf79b5aa8d687c8a5f91999c59f20784d1601b26769ba9467399a28e3da8c9b062a6d71445a1572b3aad597e442cfc3803cf4464678c158b756f37a4c4a1717a56f7e504f2b99c3df53f5f74bed16a2ebb1bb2647da8a985fe79ed9c638ac0b21bf7d2cb6e78121772bd622ece3c70f223e6a6736ff7ce6e4c94c23ac3bdf5a69eeebcfa9ef2608e562ceb43775d8712ee1b9431df6319be764ef27d319e35ca5bc0dbe7495263082988c3f1e06d5205a681068f6d2136f54e6ba31e54470a857aeffed83fed25464c4c131efef4f8f9d3874ef6e9a8091eb9727eac7d7617a5ac23416b32500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003810917366093c4dde278681e494da28523a9dcb9c0a35537940baa6e272fb978586481520a4d78fc94e5d43b0bfdddd109c8889e9dc917b72725050923caf008d9a78972049b27251859df36694263880a8078c602c391a80241220b2b7c3084d2b48c035b3d1743b3e28866d970824d497e48c571902d6d1140ecc5e69908468a29933a51a0ca420e63ca16c8c220c51512c64405909a24920a8f2657808f6798ee050512a810869a0c92ec8f7122969a8585cda8f8413a7188fbc3b6c906043c74d962e9897cfeda160b047a595daf615b519792dd22999084991b6d4869f54d5db5d5d16a6fa7821728d16966479480fee91512c8a3023a05387a43a348e46b818f1367391e4c9225817c862dc90a014db8694cc550ce8da67274d992a69a436b7af4760d5947654ebccadb24477155681bc4df95b16029d4b51155bec4bb4771a18625796db2e115e575e6c177f09aae1ea6fb36e8cca5aa519f8576db037db6ff736f92cc3f3546973da73d50906336fd6b5b55615f0aa69e646f0a86c74e86329dd8eb4b6a5ded725d25698be16f9fb19d556512c3878c70935325fd954e8fa15c42425e1486688657e4a54000e6e86c8e94f5e4c40dc41e4d79d2a8262d8e84eeb7cb3756c4a32d2be8d15c567379631641010b93bc8792495c49095525222d8fb39b561622f0e123464cb294e09bb77f117136b499d43f8d7407856c6c31059a458ec6af8402e16bddaa911004f5716f0ee10a347129c9c6c55128a450119015b7081853410d647efdd5409892df41d5e199e4ca0693083f076c60449388dcf9874b8a136c64483be769b17468676a063c40944d5490824c0c3d4ca09cda50473ed9c98adae67996cb07ae220b2d842fc03a8d3556e0ebe7dea3d7b7a5161901e275be9a051bbd87890d8437e271231c35613bdb5414463a589e5bbc8b8988a0cf3bd1c82f536c677164480702ddbaebe4820400bae1872cd6e97f68b3c50369929f5ec072e7cafd188db57a80077e7eb8bae18fdcfea17c04d677a9b1383273a702c8669d58c5c1dbc1340f05d3e5de230b4274c1a9c9da89143d9e3492dc7d3aa177804626f8268d3bb91bc71038ca3dd2505db6711d8aa3b08facb594fdb01180ca7a95322335e0379826a16686de2964dd89f3cac461a0d692310380dc551572e3d8c1c392156c3476dd6d76fe3d61a89e9d5490eee3694cfe018859165ed4815416fea546220ba7cddcb39547cf5d0cfec0aaa23790dca6165ee1620000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c6dbe5b6c299b44f8d60fa972a336df789ef4534ec9ba90df92ad401d1907951eb6285eda8f134277ab0a1145001c34e392187122506aa2dbb8617d7943a129eb5c07df133d7ccde94a7cb7f1795c62493ed375353d1f044257da799f7d112c174fbc35687e2f87fefbe2d83d29d7314b30a749fe41b1b81095638f112bc4563420af235280e466ffbe7050c4937c60fc18d1a6025bcbd489f0c538e088e906abe8597e2c8ebb64f01d225c847aae4b77bae6eba9269962c4b94a9732ceaa2cb4093d442ffbcdd0000000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 5&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028c39047bc8feae6a114b23bbc1cb16e0d84a736aba26d079dd6523288a3df2d54d26de658bb00675a301c5c5e95118eae78fa4f66b7c775da8a0c8b9668527a5d56a094e6d97b85ad286b4c5c46cc9ba10cc57156b7f6254f1d33549dd759750f28f8d37256db6f6ea5da9e2d110d87fcf63e5dbee2b9cea4a7ca050bc8cf63cd8e7156e06a26b3ae4a0ad9f4287794be0b60188ab8c8bf7dd471e98022ca4b81a4d4dce211ccad07733cc6e648de7519affa2c2a431ea17f6051441e3755ce0987433778fa76a0483a5dd87420098b3cccff706e0a8b00b027ee654e34be27ff9f154ca56155aed2b19dae696382ccc410431ebdd926fb53dcb4238d8ef3abe7996e998922eb9566e97b03ebafe7d2601be75139c9641219075584e16dcef326e69ec579102c382669016c9acbe501ba5f3a2b2d35dfeb218ecf9951dce39eeaea6d04bf9fa803ccdec574f9d974b0df2e792363abcd616849e4823f5554e02f9285e117369d48f0fda6690f44d775662da3d4c1e731d4640eefdbbae8590572f76382b42af3b1476bd0bacf75a34571793499b88ec11994e5f868a88d9eea615fc13592f473639b93ae5957b4c473f5da390137318aeb27736a58446eb52685612570e5212af2c54e449d9e3f9a58c5b5276cf0ef4e953df367a04d373f22b2144e46250a0dd3715746b0f3557e1e70b827d152e2997a4940e2082cc95f9f66e3135e061305bea4a813f7e2edf1f5c68ee5f10ec9a2679cf445525c13dd7bb4e0635e28fc039f47ae9ad6d2ef912238a1a1742f0c4a617beec11227c70eb3400ad3b7967309ca419a72296f5c665920ce4e0a6e502044190c4269b1d225ab423eb9ea3d0d3241fed1340c90a6f89c7228f08b332de29ae3ab29065517add313a8d3f1c7ae39e9c40a2ad4cde00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381090c7a20d053023e475436eb8ccd644bde15fa9ce32e1cc8e95759acb851681944f0169a4d02417ba066870eedfd755ae0b94cb417d3eb4d2d58cee397191bc02a45d311fae5cc363acf76790d3db99920f8025ffb02d6d779a44bc85728b138f42a05537a540ac8e0b513a56b79bf5915a098e16a6091868aa0b3f45241236be9be376e048e367d3ab2012e67b6a1d209e204466c5418393d15060611a5a35283342f1182a7d72537518c087176195865f09d23d752e65b6daf915adbcc270182017bc310163245a3f6db8593d18833d04d606298dea7f01cc704def489ed144f685939e7fb5351232585212860a8997656d3e31f4457d0bb1ab1593d890849642126234c316788c203c9b5eeb703e587273270fc12421e59ad28c3b596047862c63196a8aecc6fa4b444289f95b534cb344eacea69aad1d72b8195912ce99a9c565d42f03f7587dbde100aaaca0aad7e254a6f12795f6d79299223465b7937165e1082c72dbf4d137bdb54c9a42d8df343231270d4d648382b8e17407cfa65d5e8148280250fe2b5077c0a457d82481748a494c61287111a4cfbbf2b0f9301414269683169d21280b5026db72209e763c01e2fb6606088221c7eadaf9211a682938233c2666d9c56fa08f1dd56546a949054935b6aa0191d30b5949345f657a09e88cbb3086b47abe3be7df4547468c59e8fea7ae6eec725802cb71a5f2747be79dc26fa9ac442da84b784c606690605eafbd6fb4e8ab5979be6c6a2f99ee4de1fde7418eab252a9bc7db50c232d2c506571a7f0dc0c37bd5ae1291526161556eb1bb2457c0ddcbca15d03f75816dfa2139fb757cea982d1ac4399b6c75bf141643e6da8911e14c5bd021d3753163d81c67c553cc1d594712d6018804899b13a07e5202160e6fb3b9b8feb50954843abdec215b254312c2839b90af2f0ddc2083ab8cc31e956668d14e6f7336bdf191032385e8b4f7da086d7ad6aa558b46470ca03be81fe6e8b430372742eb7f1d9423b7dfaf5077f41589b0aab756685e33cba2f94e3d61a5e4a476b546b7f83ec07865bc22b01c20f14cc99faa40e0ba99b4c361529d3836752dc6f41c1f237e1cc7f34d8d1f3c69e193a7897d386365ad292c6c8e587b5a5aad3a30052bf78e3a65da96054a4a8c3af06be2dbe3343b8c4fda41d50e4852cd7b1ee7c94fd8cdb35d62172ac94c0b4822934c5ddaf794d96dacd65ebaad4e334394e29adb80745c6ea0d3246452191c9eb3bb52bcaec94090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e70073bee97fc97c0fbc750d474aeb93189f061e1a5cf6600c04fb0464338ec7e85252f94fcbc7b2bd00e438480d9af3add92a92e3e2e8acb55077c3278fc7503988a76e9b6062996b20889aa55b343d5a003c8a8852d738f955799fa3426be5ccd3aa6b6eda04d4884941ffc0b69c5acf12b347a74d0580cc3335ba816200f87674a4c1d98097c70f2f27c74e94a661850610ecf4847ab5b58344f958c5719e06ba396225bbe21acb0fdc512b885d391e11b0c0ed5ce6b5dd8faff91f50025c69d43072f7706d80d9fd786e1104125d79a5f4b5fd838815d44fc8b1ab678078cc174dde970d448b00000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 6&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028a39203d65267bdcd045cc80ee0310080a6dba5b307b54fffc49b36ed2dbcd75e8823fdb888686e70feed4cac72f0b75e93b449f5364d068daf21da63e53d71507694cefa275fe88b474292103491682aef94c6134152fb117cb34884ebcbd5b30d0538f0410db94bb5ddca0a0cb1cdcd8da215386eff04d6b8fd29aa1592059cd8604f4ec9e09633f5f9b3979d77a05046eb41e0dc5c392c6dcbb485f9e99cdca601a8a9924a8a787a30504d35f1487018373ec1ec3f88bfafa066d4599a9f14936a1f7c16e2cbbd9b445e2c79b48f3e93ad62455a9740bcb21ff552b9c3b33a71018ad4117d3a81b3e5f37e5c3ac66783a3f946333e6c6fd7a66413524cdef9ebdd42068356e0090609aa74e153a5e1697c5b8bf248f745ecbe76162775d7977aa5cf2f9b487578edd4b63f558b4d2f71ddc313db4830d66a590cb34a9dbc7c86b74a40d5753e2f69a03f125c4b3790c57366889f35336372299266eeca7e9773d5f572e0d63c85366773ed2dc845da579192ee8e6552b6d1f1e2847779f4b2510f2468a2a0d5d4248110be5fa356d4c53366ecd5fa20cca2c7edfce04c09a780c7a20cffd313b7bad4d993437bd526ee9ad477ac5afd1364d7601b88a3078d981b0854f3189a9beb42f2640a33a2e93048dac3b47d5fee5d68a1af48679f54fcc49bce1223f5dd1314f11da9eaf3bbe4418c30ee077f08c936f9e9b40e191548ae37de1c494b84d1d6ce8435b3ee255464fdbd3a579abece298ace6652b494bb22dbf9d601e84cd37c8f1e74967672392a12ee6059e8c6145622f185a341eb9226734a45edb1e46be4a49dfab73c69e226c0922c83810e5b354a5ae5846e2f9549e5675b7e772498281bc84b853fdf7d82f776cfea51ea7c6a723d1456da7d996c9168b1d7fc09abfd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003810950167e03249f689c509512ae1741188e327986cd1b2df8f7d8c4eed217ceaa9440822c356256f4ae80dd91990c1281d55a54fec31b2fced6a2c08ca9a0051c403c1cc3afd366060929626e614813d05ea31a21ae5980a3c05461e99bd9e06afd0a63964a7c477f82e4586e21e760aa1732082af8aea89915062b2b3f070a5deeac5babc01b0b5c1be1c48ebe3f98f15b45c2d87c70166862e9db9cf191060718ec955c7f4b5dca457074be715725a77fc8c86300238548fa32206124e36549004a4699bd8521026a87286406f08de42c8131224d73e8cc5e573db4813ad6e721b2fc1564c55ce262b8b17b8bad225250c4796f0ff838408cb078aa5ea45dfe026e681054fe232b7cd32d97c51033c0932e4392a22464ee7868c8248b68a63ab16d92e745e2c01ad0a3326a5dbe788cd462c95be6b5f5bee1c199ca02bc34749454f07cadeb677cdccda6280f5aa11669250e8c107253062b74a8a1b86026a16afb09801b898a60c1b3fad69f184c240097aaf718e6ecfbf9a4589ce921279c209508019673b4a824120ad1fba22983b2f02d191847c20d5dc918238ea550c046f4456c963e882b6777027820cc5a1ac25e2663388a47c8d60b2fa406922c89274cfd9300f8e94ba812cd83a220de2629fc298ad2eb96d5e78b915325be1aa2f2e1036a74ad5540c24b2f60827839fa04bc56c05e104821bd8a0e0a217796491ca0a232352d5b9a551b2850a3e095500b043b0fed2d3c0c8b37512f67696b41434f139f0cd926df6eb042541fb934810e07aa7c90176b4b67cc51d1e1a96aab4e62d676253c065c31244e970044c4213af4aa4198c9f7a50616bf28d8d3b598564a1cba78e1e70492269944c878d8004ef1001bef09522d5d64980057e053c91b284666936b2893975680e3590da3c5724861527166d2826779a0314956d52dbb8a3ec553ac5c471ed0bd466fde3662810735f6e67c708009b91322d90c0a22a49c00c41f8112d249068750197c2b588a14352ebda05a4bd44a70d7f5d8a2544bf434fa2f43f677d54fa3572b718844cef0896b7380ce0374130f936df05ee53fce01047cc0c303154b834e4d38a6104e0429e0c2822e9b0320d2c395a79eb280c8d0858d412cc820c6b3ad78901ec12ad6562f886432bb3e0e7ea78100850852bfba018cf4680be5a46db7cb66156816554750a4ef5707c4b4257d68c905a94dd5e50dd4742d5583aadffd3de8d1e2d51f5d2bb5afa60c530a40f498320bcf82000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000108a1586245d81f96bd8ee81aa30f10c0adb343d74cf72c4dff71550c12873af89fa1874d4731c996243c3749af3f6188ffe9fa45430549045134eb29ef3cec37e72904aa082b1c6161e6b52361e49af4933a8d8c0734f21cafd7467b0c02876f43211d6122e3e735fe36064df7a0c91449237c2bc7c3a78ac7bb0f9567f2576f05802c872adf183a87aa3b8217188f2f3535f877724f35b29e545de4bcf258f13bbc7edd8c6587f733c9691f74b4151cf8c060c3ae9e8d49fe7c77bf477dc9f23fd0f0b67320275529034b84f94176730923c03aa50f9584d9c2d60b8dccf85a13f243f30a51abefbbf2cda602bf3d75e849eb92422b808416c7e56b046ce38e4677ad24d23d7237a9000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 7&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028d3967cbdd8cc69648592a8b3f0dd86f65f3e6de3a35de7607c57227259c7e2add449e6a5a8e0e92bd7c8139b404577d28ea1a294756130da3a2773e6ce1a573874d31b135a5332fa5f578765c7a3410cb2c1ccc6299d377a21c43a713e26a3ccbb7da64e0fba02a9ab1776d1e761d2bede6e58fb5da46b656a9c4f1a625cdb38b0863bae5210c7638cb42b12eb6c524e6215c6821294a91052a1968f6fa8a6779dd8926d51d61d94dee42dcdac360188a229f0ca71968e91986dc56245f4908ef6e4dce3907a846c94ac3832837ffff96a642b5f3e809e854647bd6b309224b90560fb74270ba6c9cf191cb23de0d699fdc4bf5cb229a665cdd10b3d7e1d12ce6ae70af27ea3ca1344792666d21bbc0598e8e8d5dcd41156ef981567abf4fac177d60a1216efaa49e1895cdd45653e3efd3cdc01a3893c5a896b4fa28f3bb90b2ac72d27caccb7957442bac92e4541b7cad9a81da77d79ebc3e10fe4cd878fc66679dc1aeab772b0b62299404cb7b35c7a5df8f8e96bfef6dea5efcbe4b7693e57a1df82d5ab8ae11da2609fb3653abf96ebcca1ac4f727663b3c2c25abd925ab6c5d942492eefa9c130d67c64363d8eced993e97fee28383264ab02e91de85f72afdd9f6664fa7610b9fd7d79a7be38a16497aaa22ecd71a98cb2b78c44494ac7f8a5e4dda78ee4f171a54e1f6684de3af6b7950e91fe7088cbbe8c425944b8643386fe75132b276197c423095692a68df1547845eab9426dce099efdeaaf887721c373053a86d7e1531a1a811140915409df90d6eb7049b6f22fb0a033e66fe820538417b10a39aff3d530a795a474c76d71a6cc5a9dc63d2699f51dae1d35ed87e2bd8d6a9fcbbc9dddf9927b9023945df671e5ba530e48623adb9ef0ce335427bae068962676c90d67d0b80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381091a886ad077a3206049169713e9552bede0e5c9ceb03e9c53b0c3ec6b0c8d87986a16a2a7dcd2882daa6ba6428ca74c906c50f2fe300188d7894e02d76b2e52a152b7057967e414922723be2de869aecd45e309ce8d7e2834160eafbdb673a2f5ebf98976bd89325eef697afca4714a4228345cf4b192e55058bf60f281018f9a3cd629604a69b9be4aed9531298a5f336c4f5d43546221eb53688a20e64b0e1b843e4e309576634e8938bbc234d353baf2b24add2bd9387d2b3a052c3a3e5987d42c204d5a5919310bdf6d03f9c0ead456d91f5dd9d72ddc253fb925daa856eb59b2fe99cc43cb7d11bbc01596ce135a066710189f77f894227654e89be8daea84e3c033c41452971e9864be90070c0e8eab762689450cc00fa2d49b7d8ae9861c15ca8f623b1805d80899e14c89b53c9be703073430c4e55c4c5819dd863891ed39afb85299791277b0599635741b6d36a9696bf5e2c238c8e1503baaeb7b0968293bda041c714f6a02c793b1ce1df1bb8b516f2970f54e0c00a029cb1255481f6ae5fc745e1a0c73eeb1a374dbf9847da42003a57b15782f077b192b685474168690d396d8ca786197802185b925828095bab8154b23d33d4022a2f4de98445015a1fbf5442a565cb056fad6bda886b9562153536a5271c0008efab78eef581ad823aa99a6248f6f8d20d8a476d86d0b8cc10348e89d8c2712382b71170ba2f8113ac4cd068222cc656a85e437501c78109e1397f0705bb3af7967c000a579df9c82e91d9034d8d74abda3a7a65cef0410431269e98a7154aad70fdf3face9df2a2480d3148e8e36eae98480b591a61745b8a95537e936c57a78a631c41eafe04efa130ac85e73245e04777a2014a78dfdf4ac5bd1938c92058f409eb5c9f735a188b83b00aec9c4435178dd34a60ecda575e67422af16753c04460649ab486b580eb6a8a5f7a2f2d2c6e404945fbd7797ba46c66459b9b99feed2b2441a6a570b026e00fb948a494831408cf6b448e895d2dbd719641983960398358f169df49c45849bc2799523c631068329fd0c95ff4dad2648e280454f0334f8289891ed56563af4d620c0fd706ecf269d44fe34fa66a4414d104b98418b251e8d54b88c983fe006bda5a730aaabfe957db47a94845d320eecfb4c0f8c84481644c9dad6ae5299b80cd0701c19831b2754e151e52240f8012503b19dba639263bb7ee1e34c417c5c1d958079433d42c069b94503695cc4f6b2fea165b3714a04d445850000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001299366ed7b3b623c411448b634446f1a3faabdd163a6cc1e2bcae4a98703cd8cee441405892fba051be2a586a6950a5ef73a255e5f86b0d7212e0c51c3bc79be4b88e76ed6f043fef3204faf044bfb1ed722d61eb5d0b74c66a257e8ac3a2206273c80d2ec2123a4dbb715d60118d99ed7322e38f1562f82379138da3ddb8baa7ce61ab729afc3748c0134633cf45a9973c05c75d04e82f631845427626b5799dc07ddf830ba01e8bc6236bb6d03b37d949dbb29eec7dfe60fbc17ea590956d251539792016e2a8b01e70476961bc9ada43cda682d0caa4fcc58810bba1a673ef8f6bc90baee701e8e4f7c04a346ca56c7b2862ff57756ce6cd1ee22d677bcdaa896eae96f87870e032c18b6c6a0c1a191fae2ed487ce55296cc4b6339eac9e8a742bd0a44c3525cc7500000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 8&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000290396a86471110abfb6da027c5f87ab1f27f8bb6b49f3f2e91e6b46be32d8e130dc7a2e741628cb2bc03d29cea8d83e37f52595f5ab7849bdbcb64005c2c76fddd9efbba3a6bcce3f2d9efb8ccac355457519b6662b90d108406f52b7c5023c7081856a91f899b5459216c688974048ebf30bf7238a5fc60466206422885cfcaaee349b65fe73b62f3b1b539e339cc0203b5899c7cf100f7f320196923344cbcd5441f1c897b35ef942dd49d57ca027d522dc445fc629718a189f635768623193b63d9d24dad34f906886a9c4d440885b3dedf09b0e362782cf4a500fad121c9f6a9a276d6ed43acc6886b313aa025583c3e890fb268648fbf0365b1c962342b9a508eab6e3503bf932788a362903d331556447ed92765ec261de9932ab65a29cf03127a6849423ea75d9d6daf11d9ab6895fd763e0b975a0a8749ed6f630b3d012a9ac1eb372b9c40d764aa58d304aea5f2ea4a051bc7b4fa563b55fceb8f57d0abce264d3ae78c2c2901d5ef4c095f1f12300d44abb0b72a49a136cee377da3facd36dd3e4f4e1e8e5bf3af62e9054d054e919ceef35c04237f901da625f5dda45a996bcf9445d02d73aed3e327745417108c66eb59b3079c7a79b11dea22a6542116567b7781ae338b8f4fe12cd56a1e5f0ad1b8f55e3c63288db3b19e994a391fc686d9a40875f7fd78ee6953b83179b1a9d6cd5a232b38d062814492f79096471b7869c8874ebf754f19aa53607b232ab9aedae6d15f8dc58f94a810751605eff4f72f4b6fb932d8d37ff5fd446b728212bdee94b4e1a0498308a816a97c377f9e8e220b36349eb77014dfcfb9692206bb0ca0e2558d712680311f374d3f8a6f3ed945675540d841d368b306a4258abb75663362f76fc44520adb75234da1a4f2a7e62972f1cc31175ade1ebc964000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109a9991eaa4ddb4e2504e9cb17d13033e85454c8d0cf4bf9b6995baa6c2e3dfac229555166ac0d0b4cc96ebb8ded61be1a9907d97cc8bb92f40c5467412069eb039682ebfcd9737bb970fb448428087c3ef26b95d496c60a09244c71b496ee98d9e30eb1c02d452ce16f78ad3566e7c0df62d0744a31611c61b48fd6570736212dbf67414b5e5ca80dc94a14887d846463126992b0598842fc58360ec4fe23e2d1131b42c413d48fb99efeffc35e82ab681020450a822551322eea3303f0bdb277a06662d8101dc15794a8e7274eb31539ebb551bcebc7a0a3248f4613193fa4863e601be1d4ef496c1676538a050ca951c3fab143b906ecd7882695f8648050c44087bda8104491594dc082b116594c9cc79f9ef4e313e62532dc9e730c9116aa1e319b7586aeae8afe2569c5bdbd05e9fbad14d901f9c8c1eb885b5a4524b70d0b7c015dcb79abe98656463811fe6852b74de215fb0e14374a23ca12e57cab4800645ba0f4008d05670a53762ffcd2c6cda47e6d3e665bf8438230915aba864cb35081d6d755c12f90647f6255951423ad9189e9e569ad58d9fa840bf10421abcbd2098867ac615bf1e0872e3a5b046e0142599e5753eb1dcb7a965e88ea675b64cce2e96d8d89592a12ab809930188c17d7ae8d9014c0ef26f0d1515882ca39f7aca326c174223d2b58bf1ad581a6588631a8a42900e90494fdebe4806b817eeadc78b6198a5e4c612581568b26dc24daa860d4406c83194d19a6a6b11dd433002f043a3aa0abcd42993958767e6008141042aaa92eb5ae521da36388bd79359ce02829c2b8245c57546f5d793d662749151207910a69982c11a67cf262e4ad5d251d5590a3da529cf6e071b74583050c5107588bf03f6022986bc25972b12eb602921b3e4a61659c2adebd0a3188cfed5fa6c914b416ce7598fe8d30cba81d29224478cec9c9759a82540060feb9a47c743c232bb4422958826f5c951885621f603974de96e07167b160d84092c3cdf349bda2e16167be0bf9dd39b447cf1e083f8663c4af2e3db210179b2926cc0dea0dd656b4bae4f8471e196950bb10b325f9116c43e6b392392b39f174c71c2819faa9b3f5eab7870d0838a940381876fb3247df1124d9e6016e0fc263ae6373381a198bc68afaadc18d9d9d89d0d201f655e4eba6f9870fbe950e36d710c8634d66d4e954361b56baa8d25e8f9d8240813007bca7c91278bcc837808a7d278e66ecbb014380a328081d58e420bb1cf900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014a0998114c84f84080e7eebb47d248980fac9d28f1abb6dbab3dd59a5cfd2c7cff7f308372874dd5447c7b02e30165501c0c673128e4c543a414222bdf47e7f4e8dca757b0f4a3281c0d10c4f02ab52aaf5b9a715e012607ba310947a60a5f62d6b8cfa96386d27cfa709189202421c078934aa2d955468e550ad4d0d4acdd98b168a9568e232192e92789830317fbc959087fffe353b6c168f3efbe7164444f1d6cba5246e31658c65440a841dba78257e78502843ec1a6e9710229c8eeb85d6cddc7d543285624aa1f756a5dd4f1a5d4fa52db8c5c34880ed448fbb6d254509fbeea0fa022f276b6a66bef7abfea6049ff74291babe781f718683397077b29fa9e2b46bc6b09251e587cc5b182195dd4060cc4a319bfbe251a5b660a739dfe5d0e5b93f3cb7e440194f1c8bda922cb1a3ee3d27edfd61c1d31a7f4534e84889ec83b51f164189276643400000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 9&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028d39279dbee6da8287c0d620ffada2de28eb0e9f41e2e79fdc92b43d4c6580e441d59a4129be0c21ddf0d74edd2ff767aeb8b182b7c252d9fb199db043b48b77fa53936b220cdcd8835a5904b65905d3129495d8f1c27858a462d140a0ef7f7de8b2350e82faba30dee6666f0d2cbb6f6c08d1cb0eb90a38af4b30ceceb2df459d1bed4ab5fa353fefc5b575e98bd326d9e9e718fade2913302833fd8798a2183fb452ea9233c35b01a59081b5fce34c6198460decfaadcda5b23e0c370359136aac704304f73b7bbd8c229851a011ec0a874e70e6f8badb8bca334e0d1ad49daa955a0c6dfad89935adba89d5a22f2287fe442275d6d0dc5e87a6e0d95c769003689026302761779850bfc488cec56129bf5e3876e1880cb76e58faee7d0d68e0a41bdd15030fde95c716369eb3eaa67832664a62486a990945a706a9609b8435e3636089052a0afbc2aab5457d2eabd7579a7121d6b3443d228a2258468e56a2c56d9cac228d05b613a994d1129eb21c8c0a131fd87b9338bcafdbd6bc7a557ea106621a5dc47abf2241dbccb896dda614c2c5c0c48d96bfee88779d3c2be69cb6a84432b6e0299a34551a5435697b6b118e5117ec0d6e739d79b531a63d3f840bcf3643119264bb7443bd974123954cbbc4ce5e5a75834750e173309dcc0d8d1945686ca3e9926d4889ddcd43e0391d98cb90078abedee3d1e218bc41e5d8b9daece41a3db4b5ce4f6c086bcf2174713e8c028700d3f8123d1d864b08ada0e9bfd6491942cda531b762f74c19a6a3a6ced10146997ba4444e1b1a8ff8b2ae8c7a925c12083fe605805c87e15188ff33999fc3aa380a5b83ae6b2f9a8d5d6fc9deaea7b2934b0ae2fda88f9e489a7b5b0ba230fb742eec340b7e87eed8a575b5cadfe7af2ead8b408cd49bc4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003810915cabcc9c2599f6b050af1f915f03e54213afd25fc1094041183e4dd483802f11d15a22dea54d61b4bc688d577b16fccb4350c20f8aa6f289bb51b7802de2b433646a85ca9fc1fb91bc4fc8f43354d7e50e2ca6e89de682b2be90879e05acb1844ed4a4d30245b2a9779c23365c01a92a3b4faa03d9ebbb94eafba28cb45be856f185317c84aa4a742139404a3ce7e570393d60c362d330c1b29234ed0ab5ea44c18e67e754fa4bf559c4fcaa86a758d8ae405ec0c9e4e757da1f349d302502812e7445b44444e57abaa2a69ba4789bf1fb96512e5812dedcd9b62635634539631146d603a1be880f1fdbb386407327633593f5d546fed4b0872a1700a5cb8a302d80625a698735cc4086bb09c38772fa083552b05f983402e01a874556a3c411293dbbcc95621a2d04023a24c7720e431c85d3b41f6da564b8c859b0502e14beb601aed0b0a7f5f315ad16ab5d240622fca43515a07707d1ca101872ce81f8caae565267f8d557ef4af8934434e7d8ab0eb85677c6622ebc08d261cb658e1d53d32483924ca03710d907a2067540e2fa6e07ba9d5e506e9324a1382c02b9c5d5947c7ab8211ad9b5e898c90099542e48fee8de131d1782d5c031c3ad75958e35aa86c964402168b7544a8460b3168eac09742a1cf56e227223c8a12136090f2f6dedd4c7468c5d9577467b5a284db5e6db70d8b476e4caa0d8ebce1e921e15378bcb5cf00767e4429d0a18c08268960074b6b7b219e45e41c6d3722d981395cd95162b15bb11ea5590118b4176fc4de525ac34403983695a22ae9fd63db9da24a40586806a80223d722dfbe64c55624b91c25545c1363a89195b29ecb9bb44c096ba5b5428acef3690a014717e5c17612ef69d9d3b815ee0ee91b2f5f06599c70ba879537b9c693364ebd837c7e82fc5fb5a13254b44b50bea7a1852552cb0350fc9d933627fd43711d21030514bc89c75b9d6b045094cc067012969d75d4d7a88854a6d276e78d990325391aa3c140771bb11bc99e9a533e818106425999a56ca8f35017694fb02974625de749965f2b4910da46c5ac2747695b44fcbbb8ae66c941f60ad60245df776012d2581ecab791f898bbc3b1a176ad55a0971353b212f6aa176234f5ac83eed78159c8c891f9d83a2ecac82085aab1b26c7119efcc7d10810961f946033489bae6c59cfd0e8e33891feffba1e0c47627118331854e39f866e40cf86c6747c144adc49cdbc745d34e9c52ab462006abcac558b7919000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016b4cca95cb9f254c2eaa7dcffef662ee03320d5fc626a6484304bf62fc20f341fbe26e1537d7bd20e95440f7cc95ee84e1297c807a0bc9006dfcd5c22a5c1fc0865f5d70e5d63ad677fffdea52bf85d1a4f159f7ed16a745b4d971b620048b5f518eb2dc672ca35022578059e1adad7c07fe910a5d566b8321d9a12f34c250be35ce964dddea23c90ea77c9c1bbe3532feefda3637157786ec7d37775ae5cb0bb92eab45a0fb1e833e8a6f3d06b85946e31a79b64a02b31fa640ed514a85882c89f693a06354dfddb0b5e23e7792134c69c1d3908882df3a7694a05b241b87fb2dbd1a4d9f26943b69f3cdf730301663089d1ebfc23299da21300f735cedf7b109f3e0bbe273776e6aafa7054a6cd9682b967eb7903de549e9558e62dcf3ac444dd7042fea362efb555bb97fb464ad7faeaba3197c14a6740477db50ce3fb8b762f48f880381d510fcc836e5880b48f08bd6333202e838ab73f2e106cfbfb218aab802da8a00f13f78ffb70c000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 10&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000291398934eed6bf931b3192b123259d3b9c3046d22e9a9f58faadcaff020fdb52f1948b12ba0d622ddab15183efd4940aa2b9a41d74dee79daf2a3898ac762024e94b63eb8547691b5ea454dd68129a64161a5fde9c43728b7d7ad61f148d0be857b7c5ae10d621de2f52a4badf2081be895c1d94799a98b43e550fd79ae81166fd58ae285216a7b94a5c6da92b28cd2f99aa05cf333225cdc5f66187b76577b413bf605a2aca2f0b9b10a377b25b0b1f0162b159a0aca8f279fe970b3c2b2b5e8ffca4f0136909e0c3e92acb2d8986152f8752ce9da490d6f1a961a55bbc5d767cd121ef860a1562b7a93124a4bc28bc0b1243925bef0413465eb53b926886c31377170b81de3e923b1215a3de6d4e9604c63057feb6c9848246f0f0aa331c3a5003499b6e465d1782a06c18d9a9292540810563f08476e42cd2cfd83e9d09a6ad3c75d4ea3d439881c5dd8494a4c29dd8d759afdd193be7489732a18fd39093d3e8bb35cb8ddd984bbd7bc565b549faa55a668f3b182921a96b6acc1c0f848e50b248d7ae1448b15862f0cd98df6c89938db53d5ee991f4b214c8fc61eb5a62283b037247090c118d41a19138173f855cb419accc297bc2c68c4b373c5e8b7be490312647dcaa2872892d9580313c38aba3ef631cf9124b73d31a770298f97198f71aba6a91e284080a33bde274be9a11868922085b0ca2d8641e5266aefff92cc23af03868cab5c566190c461a490d2bba2ac1eaf3e7987a43be98ddf7a9fbe7ca55dc2c5a4a613b829f63cda88e691a98fa6dd1fe635aee1419cb551feb1166ff6aad2235ade1083294294c21ae435c9a2606466673fe8bd60ca76ddea6273d7adfb74a2114528826d28bbcf9fb21ef2c818f5b8c6291604ebda40e7a85a746298a57be8a049c8ab17fdb0d4285dcacc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381095852d077c210623c929f4522646f8195e329366c814d7a09007f13e509120192d4eadf981643461022e15541ffe164ca927359ac2203df68901042db76d55d215a54c50dd702b05963db06e1cabbe5cd9aefad072f35f4fa4518d390e5358751843da082e689772b7f50dd7ba41cc86881bd5dd4262a8e18d23ed19d8ac3675d4776f7e46466225ac29d07784624f811a9a4cf26f8cd87b18a824d3156c5deee7370a5dea2dfc31258f6d8ca35857ea249962ad71893b27971f5182be714a946a111982949dcc93425a25b1082d71552aeb97ca9aa6a018e868c1860c9b66bba88ce19a355828d8c1c3be088eee935fcb0583e5c2f8684009a3b51fc5f2d69d38a54f03e613f15f8570a183cd4c0e1581c491e3db508d339a76a10987a93f505cce5e537e29671316105681ede3b42ed44c207e07ea105e8c3226a272c50c03d653e496686334c983e9a4118d4c5a81f401445f71cdc7176ac9f1b6dac1f6cc5aa4b361d37bf4c2d12cf1644385cc3f04461173f008122c764430589014a65c2b819b4f6d7a3dbdf807d21c2db8d4281105c85a0cb37237c353551a5a23789bbca14a0d974b83f9540ece712b9d856fd40328ababae82b20a54204de57f34a71a820ccc42065980d35bfc1ca97106d019cc0926f85ac55fbba2306d89b3ca3d07e8f2c58f02d96ed599f5795eb24620e575c5deb141d25cc41324e15b29eccbfd23694cea67e65793a07a5c869b636e5a870cd5d70644b28dd924a4001155759d9517188a9709ee275687a1c954f4de9651a0389c3e66d69c5688bbadf159ff880454dc3f5610453e6bd663889f5d8d1b12cef1ad97c39c7116d35844813b1a0c451fc679bdbe7391b39ee0b60cfd77326e6521e1a4ab8a556b759936c56814955064d266750c38781592275e0bfb74e9232202c46164226c1357eba92a961903f41ca3731a6d8442a5b98ca8fbb11b11e40bfc6064b16315ab8ca7735e578392e5a316cbda0066a6f93a841dc28f3dacb7a887a748aae6bbdae6869a142a671150871d79eab1ce431c891e5d526eaf2c58a1e445569280023a9e0012afbd774e7b1b6b22106615fc89cbca938d65f558545b31b24d67474421706c463877cfa95bb0c285cafe9f0e34390ad6c560a3a1212778dfdc3c9ba695a60e0bba43948a3b6b1b0810a0a218c8cd4e68b4ce9629ea5eb8d967b5a91b568162a7f2b25edb67ca95a332d70a5a686466f46e8d23fa51d0d1a59a7d845fd13e54e6999e16800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018c5c4b2e1a344da1418b0f4be3fd99505fc30f2a1e5b696e943bee2451d7b268f722e04f8e00fdd9e1a470f8c977a6d45a5f621b8815e352fa14f64977d1fa08082a48af495719ea6ac1c0b3d898603b4cf7ec88e68dd7190884382896d953d612cc21abecfb01a04a1bb1bbe8986d34625756396ccd84bd1a6b5454dda98824cd4844d98f356ab485eeb19f9196abb1c3088c0c3c5846c88760b696d91a232d6f4cffc85bff33de1a3433a27a209a461fcf37f2289f98bea7ccf183db1fc42a7edf958e7913f8711dc375e43f09be7c7a2c2b1318ae2a9cf5988fbc2ce0735a2cd9fb6c8496c34406c538c01bd494193240bff947fed47b7cce99a1747973f1faa5223ac564bba0ca8973d1310b5bfa1452cace9110bc22a8d4080a8baaa8adfa3cfb6685679b648484e3a43f9b1b2531949bbb8fae1846f6d45d9272fc2caa2913b5d9f8d322e9b18a685122d74634c60730c101578bef2480711feffe02123e76d6c846559e2ea99a98923ef095630102a5573ef027e0ab6e52555a9ede0d15a73c8b2fef87ca6fd9f903f00000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 11&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000029039a4dca0cc1dfeb7cbf5545b047972dbaa8660f41697ffed4141f67c1e542586a0b3e79852883a9eed24419accbd49d4b759e6780645fe8b3f6f2b839d2c30ebfeee18bdcb2c683687f0e68faa2348d26fd49ca9a8a5e4e2077ecb04b120eb0906672e9de392d0105ba628f3fab35eca4b8fff8bf29e6cb900561d98af1a3ea7685f2deebb64e292c395eadeb62ebb68e053fb6ab46d0a9ab20bc34fe4da60ec45655ae2426c5d94faa89d2ac73318c9621f9eb918a2b7127476faf7c2afbd0b3e092d267901c2df5b51e9a675ef6ed248fed3705af511691dd6fb08d7ab8877e5a379fee501ade965cf83c18ed3a28b5468cbba0ef5f3154f8c5d55b7999562d05eb48212fba201806826f83dbcd4ae8a6dde2331a5aa9c38b5f5217e36b60a7ada8417d8843d8a60e29d0dbf0d689afa9d1f5c2d95ece95706bb36f81d0b016899d524741d4a96c891642baf8a43f2146c85d1c82cabeb7d3f21488e13a0d35d6368cc5275d9875210c8a6228e73d6f5450b5a31b70d36d197439bbf43788574f78b49ef72e8f4b711eec715fcebc93e799fb9ca1e4bf031c604f6c190ce2411e146725ecf8aceb66d72ae5efa50ae275b48b3c5d7659c085336d316a3ded94be63f582733b554de9933852f31aeecf38b12aed7b34268e232162f0acbe7395847249eb148f133195925ee3daee1e22da91da652fbe71457a3c101756d11365d7b6c8d1d6a0edc72b0f56a6a7ad368513522dcdc4231fa299906d34a9934b57e44b80e4e8b63ef8f3349acaa3e2710672446b70e9aafdbee682b5dd6e56f12c4aa20250c5feb99256b1a618b22671949c1c45cc7cf86e0e4d95fd6f19d61c795ad6a57133c84c84e13dbae9e4324d39674a873a36c2f31298c73e4490cbc8092ef7b44429dd51f2d7cbc66ea5f15920000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003810975c13f126fc162648c39d4cf8b3ab76e15e9c8abf032d15511ffd1afb82491964c56dc295d28d0e39a4e2188ead42dd503a2ddb211f1e3088010b4a6058d78722d2c65758a4721d68314c5980f13ba07a796599f640cfa9651c77d93e092c6e0085073e9f61b54072a66adcf822d489a4cc9b9713d5e79098e9e241eeae432aab3e80316652506faabca6ac7a6a874852d9754061a15e1e5a7830db9653527dc2fb0ba77c93dd3b80d55dbc2056e3175f62d55be49f8852eadc78a879b36cece26cb6fb470d2e5611ea845371eb3262107ef281a6f2af40a616460a9a04eec5f24a10b83ded2d968f902d2b892e8a0f2c6528cc0d28650b31a049a71ab020e39126b8f29191db32997766f8ca08b386eb1372ac457b45a3c326abe7addcc32a8f6114b956506a1b0e2f18407eb5ce44ae86ea6e769a177d7978afb4ec614b624d84f5664a6531a28e67c74d3443ae4ce4cc44794009453348122d2a79c950505e3cba752ab8992e9f5498d65456ca270c56b244f64af532bd4b51b84bdc1891bcf563a0a266d24b994506de2d3584f7730de67e95f449d0d7f831ed8dc37d93309c84f9287fac823d40bbc3800cae3021a4c287dab322a02411962c5a6dc6c5dad95c9e64b0ee781051e7977e398795e58d2bd6b61754e5e33a4a6cca73e3ca3f0a6269ade483a858bfdae4e122639c0c60da8224220193a6c219c35b5045c15ba35fa824d28284d2c19042ae15c582f2601cbbca7a0788b60039d55f5bcb86989a74af58ed09b80c6618dcaa5ba6c5862f9635a37145fb62d6d47db9c6322386fd39bcafe213193b4dc08e43ba07c9ab2d2585d29067bcf0b61636c37e96621800bad62170a44286ed6bf80a8e00129ec2845ae8cae2f60f46a5819875c05fde3e5113429a5e77af66e351105f0423a57db21ec0e8211843271044c3365630a6e4cc0a8d9e1b47b7ddf172323ebb354a3292ac4c0a1add510019bc3b6dea65a98ce4a14eece2409828f9f45808033ebc17b92869163e9cf39613454d868915e224b20d94bf5348a0e15b5444e73e6ee02f3a8524198edabc7dd565452c9f645c1f97461c003e6a179515591972cdab44f5af6e783df8b88788be3698bed7335eae9a7085d43d5ef659edc0b07be5837a8a99e99cec0332140557ac43f26a119a5306210366d0f27a3da4bd7dc119a49de28f483919da06c87a8074c4201096bd5662ad5601d43294cd1d633419257ee947f8256744aa06fc820f48a936e23e70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ad49755a7b1a7cdc5c9bdf5149968061d3c95ee67bfbaf02750c45094303a9d9cd23a08f19b9c768adc63ffd1527186d09ca4e0356bb882e263bf015cbe3716c05b31a69dddb790ba82c341ac9b6be68a81b8bef8d882304baf0020d761a0db04412033dc369961a5213b04e81736a580f1162780599cc029e262d67f31b2773afb457a1adaaa292163144f17de384234f3303111fcd89bcb30333c6c6486f775ed099043c34e6c86450b650f1a02d03781b1d20691b767d166dadf1dcc4d8604d976efdc9168373a7316dda9b9fb02a4a321218d9f54e287b7167a08bc0153843bd6355aea1310824dd5d5ec458be694af176119d9e588a29c650ff5500293659ea478b39a62149f819cdb7e7cb32e1d7b1284f159e2ab1b1ea41af4d0ac94ff3111fc1ccd818f9b2cc7a259701405fdf6a51d2d3ef62789297bd16a659f14968ef902c4a23da409bf13a4913467b5c991854b2ca6cc006d3f4197a6aa58bd5dd95c36928da9583332c3fb134fa3890fe7e299f1c17205366c4f4230724c43e4803912e72b816658bbb1b63780865a1f66a2a49b96e93711b1be97b827d12173402828b1a065b94310d5bd6098d00000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 12&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000029039376d2e3be492dd739ec253bf85b5ac7a211f093a3e5cb1008b84836455ad88dc1dbe5ab2ba9ea44ecb9e42734c023b16604c73e1c0eaf6167fadb1d394a404a17b18e6630e94b6c678eb75a7ecd95c84c89a44613aa1af55c6f9a4d5b21ba2c0c9620fd291f7a8be8fea2c4a6a1e557a9f57d2a13389221b6923ae8d0b2f224453786a1d3f873f7f6dfb91b1faa526fea5ac8bb4e6be254ff233898a2afd5f2291d849c2a2b14d9cdcd950ae6dcb93252de2d537e9cf6574429b57c1b6cdd3410bc350ba4883aec4404714acc9618ffa20b626debcdcd7668fad9449a9c080ba0dab25fb81390d8e12c15874e5530eeb58b35515dca43a9db4da2eea4cdd9247fbccc48d6a20c9fea9289df5d04524eac5fb484b3289fa79530de7be3ca1304430c3b21325429b2eb046b0aaf7b271016ef39b0c0098323e3623c89c3d397553869a59f6d2899472fbe7bee8e5db34145ff296ecb230b335840128a858da460cf6f02bd52d035f7340999575196c24bb7abbe9305967c4b90dc466a63e2348d116ede4b2dd43f85dc812678274b8ed0bb142b6f38e110e70db5687dede4093955962475b8438b9d5f9e8e3a6447a5013e131d9bd8ade1b9f4052e785a9a97d37f7692c4e55124c3ee55e2760f1d7d27a76bcd62b28da2688af53e19f86705e66966d3c80684a262166824559ed35693888bf9cccc4f4c6542eaaa3bea234294097ebcbebb93c86843f2a5e666ab6f317708871bd6eea0c96f27b4ce779bc5d604a7bb50c1cab95ae46cf57f94b54626b75eafbb989d562b2c77ad9f7da10cb6938945b1f9b05e6e3494848fc423a94feda4dbf408fd7c51e9359fba93a4c7bf4092ec217d93910170d4ac018f85751de8504573b5381139a53fd14406788b935786cb5c5de55f3b413cd7b0704ab20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381090d16c993154b7c1e11bf24f8a4b8915979a4909aa50eb06bf229df670536b3e49f816eaa4845fb948e03393466f51b08a48a4c6fc8ea25080f04af906f462a0ce10051f289056fc56da4d45c8d6d86da462e11c9b9e1c1b5bed4059c644afbc60e7f5ece2b2ba80febb64ae4b846078b72d4b756330cd1b078786304691019c0a5879619b91d12b68aa88a6085dd2312aa41561730df41ab057607ea28f89e894ca0997bd300c52a6a2c56b13322ae7c04191b8468966e568ab6216dd73d5a6da35652ee95d206532304fa75dcd323d3e6cc262c8228bf54883442d09bdc5309420c3246a9e2ba65914dc6a1127e36f2db199d0ca12eb4d495a1ee606841c896f656a9887decd02f6c763d1c260907ab6c94ecd39be2a4767ff87a0403acd71fd4d137f8cd9d3a02646aea8193aeb01ee4b15e824509018aa3ecf1305460cba55244ae9da0469f21219c96e212a85c492f4ef93b6cd92ba54d1d4537082d5b3ae92ab36d0762a827d37140b06e62ca126ee918a69c1ca3c2ece11134974b6543e90ff5767b674ec48d162313b0ed788da8983032e389b871b826674c4f21be10b7194d590e2828ebbbdcdc905cd36a5a16b63b9cb3f452a1483fb60d33b9d46b199843a1c6630ca0be7a4bf5e9f5059ed73a4f63ae06728fb871c843b3caafaa3f52cabe41e50ae193ae1c3577a349eee190a06df2fa9ff59d32bab6dd2c088621621a61c23788012d95076df6108966d6a8a01e8010c808bb5ae356711ba306c0be1a58cfea3a25c91bcee47013000368def448d8d054071a6dc6d7d098be4ecde55385fb40052ab968d0e615d946736f511c04f98fe4ae47c54ac8bbd8661cf7383948b86804610c9092b8271dcd81f8ae99ecdb475f7ee582d8132607d6420019e46f40b5c7eade5fc577cde51058ac237cae7b0b13534a89ea2b786dec6f4e9191f69ec82fa9b0d39a4eeffe570cb1b4ba66281202ab9a93604b7c36a0085c08767995a914a55cac59ddf0732c2db19619d4d9702d800831c3e12ae607200634375aa296bbed1e45b20575791615505809baa7290399275861affaabbbbc165093b43823ca09134f22c497e2db2704a1409814af2f048eb9612ccd6d4a3c30866289be6328d341c9aaa689889286fd5cda0e195b448d139a7775ba921b65fea01c7cc7e6d3234f44af163c48a812b687b59e58cc0816e0f552187054a693da6b05f4532291384ddf1f403875c8410d69305dc7724c81716c7905643b0a630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ce439529df1864297e33956afee00a60099b658a67830a6a6abddc329e87831d9f9b647917fedf1ae182a40402143285516fcab83f447354c72fae81ac26e7005c2aa561763c152e66bd80f14565f47defa440dbb491e7994ab9fe35995d5fbb3800ca030b43df611141637a5246ab9d9cac02efe14af60736b6bdb2babb97cf21e831e5d04d41c00f090b154977900efadd3a9313389a3f84cb3ac38e8b57b70a43dd08a8243f8154013fd5cf29de5a8df0b197c12b17e0610fcfe3625cc94067e01e23d23a243ad1c1f805cc50e1447d1df93c25b8d76396bb7199e64129522462c5fc8b30c132d4ee9e0bf6f52961fce7ecf650647e7064aa5a6574649a323e144d7c5491de4c0a1a76d08f93f87a2fc7f6955fef86991e62e2cb42908e83b0c0a8bc180b7453ced293f1e20f300431ec1d395e8a537f0bc36a673d491f14381dea90d8f176d06031b0a7afb40ea8f76d37fa82e2572b9799a5fc7cf4c49bc20ad78efa8cd989a84d72ed680ac3c0f64155c56acbfd7c7d628b418a489f961357f77bd62204adb079dd3106485a37fee535c9cf82e832d8aadcbf686976b806b02ae733db46db0bf162e973931c3e338cc86db38c66262d1b2ebc7691b8281e0b20bf36305fba996d20ecfdc695000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 13&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028e393352b8693a74f57ade97a2ff8084240e6031a4c80ece2c8ec24338d723a615ff3255414d9b0bdc068c3a7bb68cf39c7ff5d25d92506858927b149b50770e1f1ed516a672d9f32da625bddcdd1d8d2ae9bae0d0403b9c9d3921c7aeaac6e1488aed22f1b4d929649fbb1ff920e32b7806410014f2835e45e3ed3407d4fc34b89a8e7f9fa8a6aa707fd631ca57735195070feab8330866318d6d6952d751b2bfa3ed533fba2ba88d29012b523537fe9db58a135ba2becf89b201832a975e24d7652be21fa7995d7af631ab0be87eb94488a13678fbeba188c147913d8eb336b17e449feb0681ece0896f1d679df0751e971d9aef8d7fa9645a60a855cd17e7e588fe3536359134030cdc62344b26251ecd378a875289aea9e7ecc8ba40e5e0bb105aa79e17b0a28d3d31595fdda771e0e67dcc9ed690572253d22c93a9adbe9e8107eb5be47060441558547e2cf51ddced2d035f5be78685dcd0bc7daa27dfd92ae04619f2a145e7e7302d0ea224d415e876d1a8852a50d86ca1198e329887fb8ae0c0f33d45d48cf23a8a660c8bda38864ce3b4aa74ee8d5128ce964d9eca33e42d21141cba077a73374402cca4f308b340430c5c45a168e5cf7edfa05514a9bece6ffb7cb26cae1ce045ec8b7eb160627247131dd1c356254902d46215a406d78f60ca261e7be99cff1cfcfa8b95ce1ce33457a47484dfc2f8d77078967b1ef840f7ee67f2d69e1b5d7c917780c3dc56ade992639909fe29c44f5a337cb5197c21b05a138ca695aa215423bf5a3b132cf324caedb1098aff25449a65074ada2a7363b8826310f8a7163fb861ba5dc4766523a3731879ad766efe4af7f33cf403113d45bdf09e46e70de095a0548bd3c8aea710299b148f60a71d884b40ce51200fb79615360c27763a49947c0c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003810951c93094c34b371a38ddf23a08d5094cebb9654ef04784fec75fce864bb98cbb3aead27eb64c58bf06611082a487ac9350b21c59657d8de96e9a97e24f17771c4aa7b56d628d77f8d133fa4f9b2deab3a4f21d2ca5308be23a8ded6de17996ae2b95ae3a01071e608bbae47a82ad1fe127455ab5f3d2f7a6cef3dacbdccc4deee247874831acb048cb6f4198ba9c3c48d4c1ea2db6e2d9a8c590a4546882050ed866b0b34bde86d003466005140f0a79d62417e3ac7a70156fd2e1c1842cc93b7af704a398e8a5f2cf8a7e6e2a0faab440798a7508e5536dfb40dd0211df62e392b18424b707d8577d47779325372b6e1183a60781645a2556eb55ec66aec335eaedc72d840c82830e1d1ea9c4424329284d44713a9ee91a3af6e1473814beb26a2b0ae9ebae38d2dccb0586c581c2aa518deb3b32d5c0049582d5380453e32f6a47b7eeb50450aa025c5ee9b3a0418b2b1122117f1d34b5ce25d6816ee4385dd577ff067b68255b43fa0c95421c3fe3112d9c461c4e137824b02648a8cb6383fc4f22dcfa03d4dba5da5c308da370b30a3d126c4ee430627274d100bab07c4b3200471692fa27d60a9926bcf112864104842c61ea45c2ab838d7d2c30e86bb43ed44531fb1a3004d25065b0961806f936f47e2dfa6e0eaa0228006222ad2a44776db37506d98ae3a365a1164a373f2eb76d901e9196596e1df1cbb6d60470848d7a144f57583da48628c29d1b2bb8ff87b905526a643af525db0f06f614c1106ba24165010b38204dadf86846d52406a306db06a5a39212faec23044d499b844349e0cf3b769dd016e8db42ab3ada291b80a56c1c27d902aa1c47bc20015ed478ad91dd0b2118ad698c77073286d53801ee95c7ef7d1c610082575a58a55e80065aa87c971169e096eb8c507907a5c0652207bc2a69fd0dfb38154475435b6fa1754bb6cbef7470c852d4decef5779d5b14b4955d87a8dfb23e8a4bab04d471cdc2b182d0f4b5e5828f9c697ddb445b628fad1842be2cf71cb24a90f4c01f45724a675d4dc13ea0f627468e7303c086065aa7a51f08f7e3d7208d541da44044a4f831364fb91b044132c0a12588a94f74509054821cee8125c112c94210167e30f6a517e507f04c0611638f2552b7944b80648c3429830ac26cae85b667b34ea305d48f7bac05158bce57401ce21b227842b88322c0256842498190b26b5961cb829690ba8cfca1aa61bd81cda008362b4944d5fe03e746c294866ae04c62c60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ef8cb18850e27d8416b88a9a71f4a66bdf447814db6c82098c371b53f61600ef5dfd88e4fb34200207c3f6f55166af4878d38fca7e2dc18fe662e3ea491b58a86246cae16090fb7ada53b9a67b3d0e3787d3323ea921274c60cffb19a889bcf0300fe10e242aae025f374dd83fbe9d007c8b9d9d75574c74146331ddec6f0e49c10dbaf15654897e33e2b4780dba484224aa6fac79015d5792faa2d532bb7d239b11d91420b98690b1fbde9632223927e0804bfb284368a426c414c3db8ea82f0d246413861475ed2dca9e80fb4f3c34fef7528069ae1975afc52ac5ad2cdbca1459e140f655556093210d7905a1a1e6ceeaef0194a0b2eab2c1ee853484e715d2a1db551fdc620d5331164c74ca4848b61d408d2f2a943fa09efeb63d524691c99dcc0b22cc61b98e6fb8039e5e0b2d7de2caaa900a44184bd56c9f02141a3ae8afc661e3e898ecd3004fdb0704272ba780cd5de35153b6fe223843024273642dcf8e4b58be2ab1f61668680084aa0b75a32e766c8ae5eb30d4e02a12e6798dea40f80d8ddfad2041a52922701c689f46f49f84cfc05eca6d7d4c356d50b6a0ba61966245d45134d6a1f5197540a1c39c36bb0b78831af3f5156e669fd9213b64e0cf1c5a31e88ae79ad61757ec67b551b9f0a760f646bf81f6b92403a62840cc29fa4f3949b3a9f0a9a4286ee7808a0000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 14&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000029439e0e18e05875803f1bc8344d6c6dbe9cc137cea265ba3bee061c86b468244d240a8dacc65104512d31771d7eb7cee332f4dc9431d33d548d15e6d5b16e11d6e12dfad966827c272fba0845db2d2124f239358555782f1851dfaa69c8ce011b09fc83b51ce3acd8bdbb4b08c32dc97efdad7a6602f9a6cf0930cc38b20deeabcf299c92563a7d8128d574306ca3f9b40e1a4caf8c3486913455344d79cf959b32e1ae76b7a8aa5d9dcac4b67b465cee26ca7cd22cbd99fd4cf072a764d999c4a1cb78b4250c11539ef6f89515135b4284a24af751f662d576a59a6d89c5a930b86f277085032a685f2cddb3e6c14aae190d54c77b4161226849cc465b875b16959cfd61be77fa48dcc2f89992a84ae0cdb00f3e1632dabdb679f9db3e246d165d50785365c32bf916098c55e77cc230a2401f7a9c1a36655f1dcee64d667654c5eaf9dc8ec21d8f36bfbd826af170e56554dbd64e0f9521332dda7738ae22ec9196437a4c4b9d637ce09a3ffa632b2930db4fd623bcdd9a8320ec0edd868ff187c25277928b9b7251fef9973b1a72a1a48cacd534e1a79cf34a2929c6e3d901ecc329479713553f5095251e49e8b93c1add51b2c3108395f453dc544a2b848918056918c5bd2e56c2deab8e0b5f0ab0bde66e62f6da342ab9247f7a29bd737285b127d5814511a667e8cc9c31dd9f20341ea73a479b91e42acdda0760de4e20efe745a2576496d637459d7636120ee5ee41e24ec4399eb52193b39efb717f13c7b18ad059b4c60b05027d36bb4625d543a843889f2af03bba3db7d367ad32025eb397e600d4fe27c788e34e068112664a0cd957522b6e3515d4d3359b8696387f60e8fb872ec11afdc3a70d8022cd0b316642134a425739956e770fdfb5e152f8f37e96bcbbc776ad0635e584e86c5306a947aa20000000000000000000000000000000000000000000000000000000000000000000000000000000000000381090668b7c31511f2b5a194415b57d459d43a7363d3a563165c849781f9be8a7c67ee415430edcdcad16ddc8dfc6048494a8b42ac0482f89052af16316000239c1c59c83b609bdc9a6191073362602dc0d3f7a49d9472c262713a87fe78682c1b155dc09786a4956006cc840a36e302962eabadee506ea417446ce07b0d203804e2ae5aa889072fe583068a63d9106e59cb9011a506b9330802c56cae015066296f89679c5d5488699303e282231e414203ca6552a5e7c6b5de5358770cbc741902f49bded7368a56c12defc6ae26ea722199bd54603bd88cccce0dee37322b2aad1c40acc9a1148223d87f6b7e80f17689289b2826092544a43791c5f99b60672beba1f24c3171070f0976698639d2fb9fe00bb07452431f92bb955c16fde3014694c3d05fe2ad49faa0364d052665028551fcc9d3a7d6f2d89e120656094ba4120a70a891fb5bb18ea55bde8231c898406c388a42245bb95d0486e9f908cb82a95d083e9f2c6626b35a51a5180c813f49ad11ff27f434bb4d2a42497afe333caab5400468d9f520c6a6447d7bed4432ab747605e5a79534125d25bbaf330a466355ae579318d2c1a77a94a8a98a21835210cfa9b0ef71f0df2327d9b0babc6e340e002ba42b8cab8df4b6aa35d42726ea5c11096a249f21ddea4904ad0a52a4d57c95495e14e65951517ea0a9b6d9c75935651823951d2bfc731e6cf32b49c03ce93ec69d2845979460f6bdea9296a1e445fb65f70be51b9b12156dba6dfe30351ebc5744b55a2c102427a0c5a88fd5473f4c77a552af471196f1d36922c4bfbc20478a20b05ca854629e294eb79098799505f6aa349907b310f0bb61ce2bc9e2a2864a3adaee15ad709409c75290cc0880a0a366df7f7566d0f3f6132212f47207bc45740cf20c25170aea74107495651b95414823a4c4cad7717560a8725018a49866347e83af90ac13d3322908050da28b118cc49fccd3d9494e58b6b6a7a7cc0e4f2da2ca96d304167c8532b0844b1b542132f8c988305d3a71136c06eb2e88cac01ac67d262a0b20886568ae5c1bf20d93507126b84685c781906283ca756d8b148ed8a688ab5821989e9838eb04215993500b83e785390a54979695819003709e607f68de2c30ee98f56a182ac42c9b0e3c2669b6d0e59d15a420560169956648f7cbd5d05e8b561fe5ced7185485ac16d2a745459d5f5812155b911d2ef76a190ebf049e3a75a41073604208aaeab1557853092429d39dce271a8165650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002109b64813c058f07a09a796fd764604eaf58ce144363702896df0ab5ff26d5de000d14bb8fd358ff5532d3b909ab62c18ac30f1900f84ebd3f4f18bd532d16c7b3470f0f8bdf72938c916db18bcf1429dc1635b1c152c5f89a9edb17116c11815a6c06273a889132923da908ff39f4940a840d3cb575dc4d637aafd37968ec61fc4ea04b4c320491a73ecfbdd8e10f1dfe902fccef93dd287ed872f67146bb8ca5a6adcf0350e8bba7f2f9762c4aa748fce19748eb17334146c152fd63fae3dfbb1a2c2b3c78960369551fdac5d54643beeaa59c1feb0c21dbbb19977d848cd82a7ae0005f45956e0fe4700f14fbaa0c12fb8c65a6aec95c5a5c8e79a6da9c4e446872575c06ae49a31b82245e1757c7ce84d6d5df3f642d3434b7e1a15a8b8a9db460826b6cdca69022dbf87595b582ddbb90a81e09a13c2ab1c125e4435ff30abc9c56a00edfa979f79d9c895e800d2dd6372fae5faacd83adf8a6d55279d52df547e9bab39d99076ad7d297371344d35bd584e0fb5932f92fd5183b9250cd180fc645bef6028c405b0ef35daf783428173f1f2482aa1363640f66af0fe8ecacc0dab84abd2a1fb53af44445698cf1ddf4c2ea214dd339be004e75bf76e95ca5c16981aba5540689c1c1f1daf4d0f89d62ccb3496340d61e7d5f5156fd3edd02edfec8fcdd0b231697b0e66f4a3aaf46117532f5ee2cb4d2b3b82b0beae0a45a482ce9a976cc99aa82beb0fe08cb68c400000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 15&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028f3984d5eb9e7735978788025d7179a00d6bf62ccab7899e3cc3e8771b36836021b66814e3c0eb5beb35de99e4b06a4e9d83e92aac1f466ad1340805dfd4aff852e282d02cf0063f36eaec9b14115aec20cf469b0fedcbc0d61c1629d0da6abe787578c138e7877cc1228c0c475041dccf3c83e5eece1834033ab0957a822751e78cfabf2d74dfac44c38d59a0105872d173468e3a6fa2eca271dbe600c1bbfb0df4c11e856ebbfb6926eea8cf6cd352432b6e914873906b07172eb1f05ca4bfa661869b5b205ad84273c582a17d194f37056fd7a7106653f5979c3936fa64855fa7ef27d8453e1349623e635936596d4ffa1d0d70dc55c76f037c3bf07812851afafdde994bcb9247f108d4ad002002258d43331f7e551172f4557edd87129cbbe04b66d0d69a42025124c6454eab4a20adb5d7a5195ab1ac9632d997cbeb9c08cb6b5b916b18062cbfe2d9a785286d972fbe8debb03217d37f0f70b7e9fa146222240e7fdd7cf21faf16dd08286922367e985ed10735cf222e536b89b658b8610b118cdda8957ce28f56d6e189bd0521f6d097ba6cffb70967deb9fddb15c5d3e2ea31aa16c09f589e1f817df2fed2febc049fbbbce77a9bffd069f6cf76ea78e67a5424f11f90b64ef6bb9bc2c0917e0e3426bc049e597ea8f00fde3a78a8a8350e037f2758a4540ace0607a993d5a64f54014adcb4473b14e64417bca1add943f1e624f8ed531bc2b9854352b9de3318baaaa91b30e91278af163d8820a4074f2b841ab64df6fe57a885ce3a51d8ea6a8199a9eb9a848d5939d605c20edf2d8bf4a0c81d0391cea9e9934399666dd4148e3501c1a3bd14d10381987e2ecd1da87221798faddae4997bfd69d91999786bf4f3e3c741e2ce8af52028862ca9dd29636f6e7765f11b7eb30c3495147a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381096711ba90b854e52c55c3b74ad10d9e7c84c4dae6da3ca84a7aa98c519c64975a5e642885f6415a0b2761ab65b49423e5ac45aceb68394e2f1d7c75070c813d6694634b475d6640b5e81721d9d1467944b52c5bda1e704db1bf98d976480dda68c4c5bcd2f1a84994f6836cb2c3eb2f7218c9c5fb398302548e01d7551b7b9e7138e72328c85dac7bb2a18dec0e8c0321844883093d51fb91d4c769709842aed6a994c9f1184a0ddc330804492dcc2f3a82dad417d5d88924bcc1f9eda5891931d1bf8d8dbde544e4949da113c97759ed654073baae3162caa447f80470130dacabfe8923aaed0e1ef8a82231a7bd8322677a80d0f20f9debf1e40c01a50cc05b01933390b593d84ed4f6a0300747e6133114b981587fe3b089a1071074c4f873fdde8977923072b1b5d75152e725d981246349f9364a602236a94a1f20205488221269190585b663ac809254b6b150147642052a0586e2abfc26305b427b13360a58dfc912a510bfe04e60a89ebe82ebb2d5671565e2f3b582242221ac77c387c2bb2a3e13496cdd030a014037cba99806442369e0dd586e6fb4485c41aba5baf8cda30b1f21e0f84d6b7e8dd0fae7f3a1de2ab582d12f63bd351db74008e261890e5df49c17016b9eb424dccbeabd207da09d0c5f1352da381c5e88a94935035681bc3fb9e4ebd50b879c1c0891bb58b5bb9229aa4952bc9a01669429618e366c9a28d40f3f79288fe27825013c32aa41ba870098fc3ca97280e8225e96637e24a884cdb8ea2e6d137705f874b902486ed5c884aa05bea4b8c8f1048fc99962c9a95dd2d431d4469b26efac541272d649165853e8c259a6ed5db168c7c090448a9f0624535e669eb77567a7ad5a9669c4c7f10790e29321aa5110105daf26d990396d7a27cad3102d68355c724f33fb86f41e1dd3d275a983511220b0cf0bdd301177ea12e79e12ce7153c16ed293924cb01065887b6893499418e748f1fce2f7879f1f489414d32d68471d8961b2564cbddd99bad1622c1922c28be4d6726a2c30e8599a0c7ece9d06419736bd3d07f99c63bdae5dd122be57199e109034ca15711d5daf5835150e428ecc537806c341f8896b4f65dc4b88fca66b68fcbbc170f6cecc038fc6c661be848b180665c448442f13c12690e72dad98a6fd2a24d4101375699296524811c67f31fbc2e7747925722dc27d11c24802d4ab4eb7d4af3433ac966e902892a1af040adaf810b6ef305688bcd909ad9aa23ab1d64d5139000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000231922320f7439e492f13c272a5738ff7122dd7a6b2832632e1f7a653fef3b8639bcb9e84f482f22a948ea17dde6958489593d2cb268bb52df8ed612f2317bd6847d1622cf0532cb499adc432233b93b6f7b1866b38975ac87859ac49f91e8d235846775f9e6e6d052339c741ef6178016edb3d0b1e3f3536667b3ea2d489f88d254b8582421a31461374f465d7ad62e896be0857134707a70477fabc09fe0a5cc3b3f32911f5ff3806b878205525af69007f50535df05c33af3b0d00e297ac7eaa012e1d863dd5dd5fa47fb09467dbad8bc42edbab42a9625bfdb9fe578343297506a3b71cdc8d5919955af4605fcb0c7164d96a187aff65d0f6210fef2d11ba08d90c4458542be72e084577be9e451b8b6f4909884bcc5d25316adccd0925664d4d91c2e56433c1b68c632b0ca56d856df1edd5e113d1f026b30dac4fd648a504f8f6809c701c97bcac2b99286cef5c1c923200b1bf6141ee1cfc51c5e14554bc02d7e058970254d2c02948360abc4dfb439e66946a8ad615147bd8a6cb0886211e8b15dff3c72b6f8908ce56bbc1b40e838103202e9f188d98e07555db61778f895f76fbd838b6d14209d28eb393668924ac0e61072cbd9f93b864904ff4302dcea131b2ca16bb04959acee096b1963ce07f59ab505fcc8d89fe08fc58751965f2f5ca753d76d58705652d3b1505e0f720ede3142de9776ffe4aa0c8a25e76c7a04843377c59f1002844e89189e22f621467b813a98bf07540a1649264f14a6844d65692617f7a4d93fa9a23829e256626000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 16&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000290390fa3bdb5ab3936b09d5fa7064fa73f30c04f03ade50f7d05abb06897bed29934392b4efdbb991b2f833835e58f6502654c5626b108f692a45cf3d4b30418c3b10b4e49f98be511e834ca557b4974644e41702edaada94aba338f7b06b3e731126f2ac7319a5b5b1db4ae3799bccd37106f467f4b3909e71e7d876e540e43b2a7f41e9b7215b5e442f6fdeae706c7c165a5f0570cd54beb3dfcb9ed53952810f127e88a978a204f8b9fce6cde4ddd5f53acf7f316881aab3d5550856ac848f05dd6218b4d5b09d2c73245ab7bae553d2040939a322df7e6c8d999266197666df4d8fafac20ded857940da19f7c5f19fb16b9d1ab716e7c5384457150a49a1b8f5cd816435a88a3e75d0959e544f08f7b23c191e4a5e538c0c19e886757a36089a485f253bd25ffde76fd612210ce3355abff95b83f97c7ae241099b8a2773cebac311922b36fd57e6b5e5e67dd73688d97cc9cfa8bd3b756a8bce891071d7338a7b185cf3066af991b911cdd3cb007b7388ac6770cdd861abf30ed9a66f8b3f95cb551b4294cfd627ddf7d3c485bb2eddbfed07205ae58c8c3ef51f9b8b63f64dfbfd7c4d92828bbf5a5547b1598460b6707e063d14867955090139f5205406709fb03a755636bad4ac2b21c1318c84f612e1336b86e3d2bbe378ec11de667ac946492a85f0ecd384db34e6c5624fd555b9e4e7218c8381adca4e12e3737dd8a92a9e7213f84895324030099bc31b6157d88ee9e0f62227ba42e07711754dd4f3b12d2f19c2c333f41cfbfb567fc9562537d3910b94250e58eb063515c61856913743f52c8b7e512811a52a08917b22282c64f66e5a9c55af739a60cbaf32a5a9ca34700bf6ca452521b15dd2d2c510dc5210a137b72976791d5352758cceee4316c6d43d73324cf9b53cfe3de9ab2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109814a8d123c2b1c797e1e03385037b41eeb476cd4f598b2779664e6097141e226a8215744799ea7c1e2cc1e82eb532c17838e68a33a2c80e212047ac5c78e916abdd57032d71571c43a8b772bba770ed61b6128d046bac0049b22259a9a2761a783e72668c4e0fed8d83284da499e5d5b06e16df91f66279d7efb35470cdb5d5065b397a9fd4b1e6df9388582ae0cfe11d5c27d4a4c0253fb5e9698955d993e4aa5a7647ee3c081067a90e8c9a4a1e3195115f57805d74dada882f8c5ff41201c901b2630855479b1811e1269c622f42468985992eea3538fd67bf8cab3e9cc6a4f16f7d7a52872bda46a56cf6a823d462521b5ed3c0bfd8ad08e251a77251ecaf240496355c087b64f198076b224f259ac1c6d2d788e975987ed9bdbda1a87672c4303a25c514c543f7182df111401fe8b6752083df179b7af611f8771b43936527d9996b058fcc16cb800a7159f47959d2a04d98545df3d209d763f189d38183d16a520bc793e00e51c565056e635c033ebb51e9149b7f25e9a4cd6d47534e55f4a617e5bd6c4b960d6a673590c6751b82f50759ea620c1d7b02da0d1b87ce8c4b55aeab4d4af69ad2afeac01fc68214e0686a51cc978c38f4dec5c52a9a925b598942a03a52b31d95c795de2ec550c56e042a37f613682a9652d5819ea41c1b81a83b232a9c34821ff22667634975ac04935623731950d389ce6243fab9879e44b82809759516dbf3bd5dedd52a4fada0e6291012e20d1abcc535bc88ff1212d3876f6d76b0d92a7af6163b39ed62c912a3fc76b9fd00c0a0db65c4d07b7d60f082496954cd8fefb7396e1b09049f1cb4c04906da422c7eb3733a2934162655a71328f215b4203bc10574bc9e3e133d2b5b3ef527b60f09839be40f00ea0fd2ad3282a52602bd092d1ba2c64b01181dc5221895794cfc4483ed1d9842964f39bba8e3285cc1202ade551061216a158be9501e184880cbef9bfc5aa91755cb2b72a27bcaed79a469fa41a1d52d5996d77a465d4935cc1981f0aa8a9875e4b458a2164615a9157a1e21a45d3a5439e35b41fe811649df5c2af99397076db1ac4c18f34822390d368199b9679f16922e3b67840189e5471bb5a67185529bda998c72b1769a14ef58bbadee644458968dbdc02fda2a9baaa3946f5a2e0303ab09316aa4abf51b64def04d81f4183287962f57ba578e0bba3d98a5333d6f3b1e061e2f79808162288d95e05c7a30acf2bd4e997770a0d97f116d687b87e61002bc7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000252576289d10ab03d5699eac322d349f55c547101e4424bfa43bbba3747b79f075ae1153a7a0ac8bb51d24fc46b7604e42efe4343fa34aa4eb16d918f25e8a4d67c860cca3f7480e1221ed3ae13a138f079fc252c6d7bebc55cb81b86e74f339614bebcf7e8f4440df8678b01a4a41b3afb1d112fe1c4c8d8c6bfe9d3ee2a335d477c60fbf43b2e5fffe1546f5172ef51cffb2a772e1575eac79b24d49fd77f0be351233e57ee6dcc7e2e29994873abd434d34ace83400c026e27e27888ea0bdd1bde5a3e55aa8b5f2feb57b8b0a96cd831906297c8169d04f15843a3249c50523cf56a4e19492ea16927dba8759b88a99e0d20820e51fc9b6a6863115cf05c5bc3f4c869eb5a87124df5db102d737f3899cfaa5fea4dd62dc4fedb1aaff67906adaf8968020efa5b10190f70e5f2c0f0457e4341bd449201d3a80aeb791254ec1c46ddcebc3896c6df702509ba62cd446d275806438eb4c03132b2e6bd01bd2f832d1d3c053c48c5a9db1c4a22b130c4c9e96a2bf4c2a8f7de0217a52d9aa5aeee5e6a49708237eab60b4019a51390c3ef10572a73d436875bb8d7d78543f96376e4bf3bcaabb92f89215e8d1093f3b287945708b5514bd7e62654d3bdf34b29009c64829a0cbf33c54d7ab0e81b81bdda93028b341ab1dff3d752dc4a1e5f9636a5c46e137ea35919d99e6571c5370c6e804bd2e2abf566f035d65cf8f97e3e8f2ecafa153bc6d8ec2831667a37fc96d1c2da40ba84d0fb041def32aadaef3f98cafa957f6552f79d28a36b8ba20a9452671de1be8af5d66714232507edb9ff657f3d7e5fa7320fc0359a5f99280d446283bc0000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 17&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028e3952eb4ec03f9f07230efbf1151a4b08fd1d81a28a474747aa04d61faafe7628f41e439b50eb7666cf9ea1e1ceb5fd66787455fa6ea614a8eeb53007e4822193835160c6f8391a0bfe7a2f3ac57f8d0179996e9ab8c14d93b2f81af5413188a7f173a1a0653613f56320eec9052af32f22fd5bde8e31794150bb5bbdcb7ef3644a71e89dd3186351d654f9532aff0a2bccc0a838e61e3cc41a17d13292e81167bf60e5344f3a1f4e641e3d56d90fe117b9db44c6f5920c547b9ae44a14cc02e26d625a0d4ff5ad76a7ff2a7dc7f768f3668b630fa9aa351bded638ebc7d009644b3ed661e0cca77b21ea831926613c64dbf60cefc126ce83362f290114d2b0ec7567650780e9cf751ba4a367f39484709335344b1c15e0d7af1418460add35fe6befeba2032f96a028aa33ea7d4c0312c7534f041ec0d5ee39977c4a728c312a0c04bb38e417d2dfb2aeab7f2027f9f711002ca9316e8a09696a99b7986a554b03a55bb23129c4737bb0f9ab971c39543c5b46b9006c68f95571232e6c894d86389dbabe567c5135cb6789e542becfd2df15d56b3048bedd23262cb333b34b3dfc2424ff57316d5f8684493e397597877c9332728820e06b19aaf771e6bc605f29c4bf5acba899c60d5a62b88c31452a1db397cee8ead93fa42ad986cfd99cd3bd20eb3abe6acb29876a1224ef437c563c0c7b9f3e6d9842fe99e634f2082ae55ae3b1d61c4bbec9a8510523b35b6010bc8a107a37f91472d93a87ff389a9a9e23f127fca118ba11fff6f2712102b3b79ce2a6c6edea70b43e59cd92c231841101226d4bedb0d3b9d8754e3dd7d7149c24e18112bce13ae5295d8cf18830f3e43f62e817641a6ac9e71e866e6eada26d326198e8d0864329067e8ce30935216618c74ddc8c92db316a12acd5fabb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381093c9c868a72e6545a12800b8c42cdbb344e18ef95da494a2e443c8c775946c5e0d11de95506b33019c5834611d093fda85980be3a7ad1e58b57c509d9fe0ff885b99b241ca8cf9bdd6e86ee6e9c123c3f55624d915e50c7e3a69b046542dad46a40b67bceb57b6ad86208be87072a2bca2614f8d45fd2e3252986d8f09ccf83649b95bd57f9141db3ba780ac89550a1b62b684a95b01410f0545d5ee17152b3870e9e415944b053d538204e170b15a03a058524574591bbed2084e01b1556d118e4d4411e08cdb5e22a86869002bd21b9114429340889f269e62084c472b655ba4802e744295e3908c45e29fd9b4a2e3a6be538438ea97ce7c85082de4ee9c2db3ae8551bee70c25d6bc59a50a4802c0dd46c4e1465cc5b9b4412116093973c593dfe93c654ce8d52c373edd8e52b5408f46205fc4dacd7582e483f7f5003668990a7829cdb39e72b6d86666d30fbe512aa628853cc688c4d49e8068590fd69f8bca49e95b8b2ce48c14e06b452d4c9125a1652322457a253df7079bc517700e5ec05e643f726527cad7642f9e25a670de67168b351094bd1cb4a92c7a97a4af9e41c1b0a7ea065227e2b11543a6166d995b028608d8aab09d8b449abf1eec62d52168bc3d54a6d18d6c6e4c8c4444c0282687dc32f49c6dccbfa820da145fda69c565366410ed6b7e96c747ed66a5a056f0ae07013a9ee1675a96d7a6a5a04adda38f8841fb578b1a7170b1d119012fa1b60636248ae6d2a066afebe6c17a237eced5dc85513a8d5a7a95dabb0b24daa47ee6e21bda17a7a460bcae0cdf7854a13792f9cde2ea27ae6412372495cf8a41de03d70cad168a88332696164c423d9b74095bcf2cc08518fb9f8c8a4490a8a8122908a4e0e12b5531ba18ec59c86cfda441b912f0a9a436b1a3c017219c8fdd60c89d5a68b0c4bfbb2edee56380ddc5aedefeb8da98e5e16d0027b63ab827826b0e9e2d61adc315b50280518a4f02524dbf0a4b08586ca137f665ed2eb3fddb2001c3556d5965921fc61b20d626a9b5a26aab2a866b27825b7ba45f60e96b8816fd228810dcb502f591b69dd93184dd0c91cc5205aae9db437d852c81e487047690792e303c2bb9a85b2829ae720c8f5263597167d64db2139c74c5948f8574a136b6bb0244007941e8a79b740ed17450af2b396324146a16a2e99471655049d14876958a6b8e52672440e675d0a9c7b6d42f56b8d79d7e1c7514c292e4a52db5084b6c4cb90e6b01cc60170da8ecc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000273021e9c06a2e4ef63d1a61958620c40016783879080d44311e04f2a446bcaee5a486d17ff0f356ba70ff1c2b55bf957a59202903ae349878cb822e04275e0afaabc0803bb6cde3741e0bf9fce0c5d5c814977474533dc63f9ed4f32ac3477a3ec9893ef55186728c85b03f4c2e61ca7733e1706766aeb8fea80e233e8761b57fd5a3cef700196674b34a3a55f68b3368b688fb1ddc976ff48ba6a98e2d66023f291a3c617a56ccbdb8732b8c34369ed11f4ccea8fc8f673ad9fa0fd8990bef70af44c617fdfa096695d0c94ea8e17554f4461dc776db2f416448b17680fe4d29b09e57603d8ebf55771af84d8d4b9097302901c25cb6d73932e67c323d12c8acb0e74cb89755f7eb3999d4eab5e1b775e6b5c29d9733697030a26f3b93b3f286db0f2dbda71e1f103878063e77919d8892eb6a34f821b603ed4a898a9f30d00feef20985fef1a7b7af70dd29c269e88687f005d551ef05eb0603fd38745aed4f5bf4c2fc09f0604c98ae3a89e46bbfe907b87a1672de547d651f035f392a8d4db5e7260f43953028e312b95b9f25fff2c0c579218390411d13d9a25f22de4c7aa05fd11781db08977160d48e02372c7d826f5cac37d1a9b4230be99a2d13cc2e9b2b17f0a1044eb9e0a2fba376d35cdd2bc05f57dce4bbc3bf07a09bcde369929e6250efdc61689466b040aea376b09453a2c16813bbb685b54a225c49008ba6811e8bb5b3627f8c281244fdf5533216d126ed0e64fdabec533424bff77fe722cc438ca7587c19d965f0bf085d8692c27c5c84a9dee53256d978948d89abdf9842e0b765be6a507d8630cbc5ca7fa0fbca1cecc78d2e536aa7b2b902c4379777ac0920d69c57cc4e6032252bde99e1a555e80d400000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 18&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028f3947542a164b1f13aa9c31864f6f58da0e3049167c445de882811ff4fc2348a200bc1474ea8c1d61c0d6ed109a01c0c83a3956b6d0b426051d31846370482673308e2cf1a2a475d13f754f2263c671a4d3359ca29d93472e2d49ab852e5253f5f764a0c51ad923f1a5f46b1c9883c0a408e33f17ec2dd7660ebd847f5ec56d763ffb48a26d854588132f87c2a2341df3b0b2109845d7070249363cae3ca192624fa1a175f7476da9dedb10e66960c560a773b4490ada76bb28742e78aafe564300ef43a55cf2c3072099ffc45682eee01f5f0e1f1ce4116c72d50973dab7d99cde54d4140fa3bbd29fc88703df11d223916b95b908d9ab78c70ac1f768e0c89f3ff19b6b3e2dbf5aacdb7d53eefa606411b9189f4167947804db84e76733acdb5506f976d21ce55bebadafe4f88b6a258f8968237b06ad004c7b2e9275379d4b2f930a1e17e3b88cad8cc0cde6a7f0c3f51162d0e6f31050f6c846d1bf841d9647ac5c7ba100dd7e34ef1f99abb6f99c1a759f711ac43fdced3a00fdcdc95ecabd52703c33635c217e634748e7e64dba87f7958b9c7f47c1ee779ed6d152d713e52379fe850f1145d708f7d69f37de501744836b8a2095c4a9b2e4d66cebe6453dc10821389b28eb4f95fbe612edd47513807173086282a9b4bfa65462308b16cd6fc2f1101b6ed4a10c58d42695f539d3c8275dec967a4fbd77107bfd636906b976202843c5f99fe732ba1c427a894d714b9c5a56648546211ddc291ee0d57ca52f21806f347a1f67d52a571cfcf1226469936b4eb6e7b876ab1c16ec8f2fdd364d81d52fb2d4ecebd0ec5707d3b32e658eb55691965cdcd8850dc9799ad6d2b3048545ed68252e24fcab353dbb750f419d79e67daa4ff22c6a848b6652b8a5aaca7a1ae53b5bc063f92572bdc180000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003810981e2d7709526d89bcddf707282e486092244ce95246cf446964b115d7a0819e828d98886001e98ffe0b646f518851dda8a5ef5ed498b599b3fc83c780c8f34696d2f0215ae0f751dd808b8c2852b9cbe976887bb6d442e64f7e6186612123261e3ad0d0150e9e4245982d9b0553bc8c68d38dbf3789b3a08822bd009d6e46a4db0d2bd24b6584c551748d8aba19052474591b90289db6760cf9f050d71851a92923b60bdf9d91cf98bc1623928577a8a990881a4474b285a26b2bd6a5a81391557a69ce2bbc4fb7658cdc84551a6c24764ec076017a4549dd789ad3a633498b79abc56a4502680731290f774830ebaf297b2e22e3272aa1953e5014bb88d78c38d2fe140eeb1c47765d580f1d89b28eb6c9ad5e66b7069ac3299dd967d60368fbef603d9053a6b203244ae0e9f2199e74a58d0854f2048f8694c1f5a6cb39a5b67760ef5dcdb3ad6260748cd54d71dd45a30d9dac7411f11a46f633f4e8319faa9070ae68901e11b2aca28c35c4e5640ce2c31b27a2ac7272c092a2a54e4d7645f3e5d1873f01a97549c0fd1f2aae11c008490dde9c2a6b13ab2ad4c5e23ddb507d4e9063122395406cfb9b71a11b113e236517634f9c25c65a06462e559dc04a88475230fd5999f54f8f924812895caa5c7f50cf603e164c609ad1a9e118f1b5bc7bf33e95c4808dcbd99de1ca8586907336699081565676f5c9924752e08274482723d06ceab0dfb3b996d086838af402588799f7191d5614013bb5613d663e2ebb2329294c846d07b78e2832d4889a08c9a63bb2023b4f572f0eba79c6f266236c3c7e647b81885e74e547990f47bae2845628aebaaf8d76e32e1d4b1c8e907ba4d8da1f643819146681ac394c532e819ea5f13f3085d859993cbc473c9ba16108db600a24176061f217e0174c0f89f131628b0b8db287a600c870a555d8aa91adf33f9e3031c19e2a95f2ab77a2a79613ddfe32342f64a9fdc935382c8523b9df854a67b572ccb8e26607e842545b816e060f78e97310e5a4409ee942302fedb17b8006cb01e72f33aa3925db28f1000220ab53d892bea6d4f71d8a5abf7d80837629f8a6f4204af362184a52c52a2787a1488a7ba510aa6cb56024612a84553ad9570b34517375da02c1e5c14d8ead2d9aa29d2418cc73b5ea95c146b80661bfdd329268bf9a042de33a6e37d7c4c8ed5d998268c601c2b960f22a9542e898b14198291d3136a4a5631fd34d4bbc4fb14a51b560de19ca25e74b952ef960000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002947bedafebabbbfb863ce496475f54e69a905afa45899c3d7c16cfc73e31597d2404ae7014612e4cbfa238efaf5b396b0b7435ada5de817e013188c280423c68924e1fa2a33ca56e6b85b7cca7f00d3a6151f0629c1b92a13573320e0025863bba7f3eeb987ee1b1a6230b10765dfc1feea498ae4b83521188e7503b506259103cefb370e3651b06dd4f08013ff3ab9e2430626b0bd584232948462d85c0f82da07b96fc65f62a43cd2f132d1a1d691c085980dad8796cce2fa0b268395eac3da2cc400f30f75be87316216980ce213b48651ddb9e294f8cdb2ca05d3f2a507e4a03e2849aa8062918afb5bce9e4c3abf2ffd4751dddcf08ab09e36a29b830f3bac6feebea084575472e6f4b239af89965a72954769a83e391de467934237b07d8884a6b14cad034fbf9bd7531d50d742e234e227e1a2daf77a2ffacc579525134b15186d81ae6e5538871024bd2897475d6ee5b11bc51edbb928d98475073785a75b331bf3d2297165ae6cf95c3a05f06df747498462054f58a5ac736f96014b1a8cdb319d030d06dad9cab2b913f35fc392e1fc4b027cdbe775d64b04f1076a7c8f44c360745f98e87b84c18ab76f84f373f635af4c8a87df08dd4507899bad892ff8cc1ee534d3277b5b82095628b84a7d5582149cf46c50aa963b56b4b91966b106b4b2eaa45d83a10993e8f933370ab29c6606b7ccfc41b21c6b99f2b9ac643e24300b350fa199ec10e64e4af19181f78e8c43b2fa796241dc42cc8992bdfcdc39e7bc41be68cdce4fbc47c996db42e8249eedc146c216b514430c705fc939b9eef677ad87f9cee3398551fa0daf774302324a410f4a4f4fc035cfbe960b38c390441e92d9e5624a8745976bc88fa538e398712361b77ad4ca5ff038d9f6ce157eb8a6137420d4e57018275dceebc4e480a5d000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 19&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000029039827d8071976add2d5b97da1ff39bbf92922198bfb2b0132277a92cd4a1fb04c581322ac40d803f9dd3dc7a4cb3832976ea9b96ad56c24230700193f3a2b985737cb970cd218519fd3296a360f1a52712c4f7b2fda90cc22df3eee9d242b91e68d34bbb3fdfa6cf32aebe419775765366c2888ee88d95533aeb6dcf3a6bab78a0f1194ba238c88bafb89fb714f0db5df3f10e353160a1f955b50a99c4343255fd3ee07f9b8737e1f9ef37a59191e5979712645f6e4fbf77e2a3697dea0271a61a87f9a6571972824c19d91e6de8d2b1e250bb65e5530bf6aa7313c54e293157b76f687ce3ccf35fc9369cee33883504d61ab8f8fae863f5939fb06eeffb70c6f16fcf6ac0d67da71f29d35fe5b22c3acafe8ffbf940cd54163c8c2649eb2cca35f06d5d257a42cc1387556558c5cda5fb69a877a98394f457ae0c6d1ad7e68356bcac8dc1dc67c7bfff7f6ed5be5629976757ad0b67da92706099ead1d8e97ab1693c0b5d8032145dfe6e9acbb111de7eb9af86445325eb2df0127fc55aaa778dc7555a8d2fa36eac66a1979a3d4f36979798bb4c765099e54d2a811ef946f2278b7b5468ae9735d2db6b459d29283bc2958039c4e6216f5498be44dcc432c54bcca325a60b3a25c469d5e290958743d0acef9579aaa59eb2c8203af8b991d4a8c9247a3eb7e934e84b9df7891f8fe3430f4a99b425d042e72a9bddfc2e52e8729503bc28734be651dd2126b3576e31999c5ea55acba1fe392f40a83ead26598962146c4a6ee5605abd151b54b8cbd6fbe599da4a896acaa2968366de611324092d9ab7682b368d67aa13c5a140ebc437acb208d170bce8ee7492f9afd02dc147caa74c8e89345cc64f2971a3a118af29adcf3433b907f14a591299ae0d59d24c88d98e58221e8f4c111260d9eb7ff600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109453a03fb02ec072875e542075b71863cfc95ad04719d6ddcd9b7c830b48485068515d40b41b191e2a613527ce6a5c0e6822aee7d925a1f5862dab5634b89fa74fd1eb582c7d1903d1bc00d8100393a18d33ac6c23acc60679d5743abee6c38ed629b0c75d3407fc6e9741a6ee87c924c2109863772ede806a15d60ff5d923181785befeadfbb1c2a1687db7272dad1b594456ba55637b1e095d4358c04901d4c9aa8a24b1251eafb0384c51ba4c30708fab323eddad026ad5ad668c332b6dedca32fd7573e8654925fdc8851ceb6976765340fa0d5b044285a4618d570d189cc1ac573497359db737dafd5ee447b8a9074e94ddaf016cc28a7dbd4faa0196cb76f08f743b0848b6588475da6b89861590a1bc2b449144e05443eb0da5a86ae587556f2cd0a5a3f3839d2718de39fd602125b69e241293bc9505668840e3c9372a53c4416b9559bd53e17a69e36968aec2a584ae5ee112739c0741a1b5d5a6cb47e67ab683e82dd6319bda37ab7baa60398a0bc5389cc49f41dd29b01e87812cd637f6ab34508e03eb8a20bea4d9b58a59801528da52871a165f726ad245c0e7a99e04e63696104db1859cb3a781dd58def272cb2c4da5cdc1514c85bf816024d1abeed462891d32b71ca6b5caaa5318c17b3e62cf84bdd0d17249a52acc8d4a84d451a72809ad62bc52703f0c4cb5667e67de898e6ae5028786955f9f4571f159e0d24ee235f9cd21622ed87c10c0af080278c575ca9d1d49401ad7b403fd1d264da8e64bf3b4cc4cb5ccec834c3e2e81db80867d1e6acb3b0521a160a7da17a62f54c8d152e153b35bd4c515d7af6f21ae02f955d4998fd24e2a755070a04a6321656cd3bd267cfa5049cd8e5c3ad84691b606255691c8d90f13c2ffa7a084cca39483967a0631307c4bf76848d86619151705c5452f549b43770eb744dc9055de40f61ad11f9730caed38bd6fe4e40391427178b53cdca51768541845519b854eef804ae30d31dab96add4ed2aaf2393a30efc8532877c75bd72b21c481d8ea2a70609949d02a511756143dd2958bbf0795b99539ed21b86964d2ba0d350c527f0a8f9c158c5196d513cb6b3619cad8ae21c182268cd7e1ab1e020619b0e6500f15ca23d19d1dd1b045fc939e908a9096e464ee41f4806eed53418b094a25a3f55fd8b2b4c288b3709585be693da5825312b662775058ef8daaaac14187d80ea3642b465d9e2c0e5a9c3aa7ee74ad900418e8a9062e815d78b4d1975196a5b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002b5a86ee95388df139f9c5a84108d1e63f7a7842909b818e9a0425c257649abf125386fb5286031e7e6d0eeb85c452e254da39bbda51f0d2167ec0a51992753ddfa76874aa80804e705cf8bbadf3b82b6d7fba3d1cad130abcc0b44d6d893356f3e94bf8e82ac532ef8c5e5f4200207bcf6b754f14e57a889ffb753f516ef8de2a647fad8e449264f0bbb4cf48bd01501736da49509c3426a3d4108b98e6a4aa6c4430e8ee76540051fbd1dfbfc01750e26547f8718ef7d897a0342bb000fb99aa63b781c9a4b831da798c014e58725e03d2f8b1a029c3337f4099239244aa320965b2cb5075052d901b6077a18c1ecfa5f272850a475b5f6bbc83f3c09a27072f80743b23ec6a9870913ee2805b4d296b2f81a9d733e5c8d5c0b477e51f9328af3af8abed960408afecd27fbdd08fef50f4b07959646e0a02104a69674294a79de0b25b65f4dbfa797e5fa56d66e8bc07d5e2e7c7d2e845699acea3bfac60b2c0b988cbab949a5b598d8e2f1aec66196e115ad7f237a1c7fcfb95a1bbd6939a250e7bb0f4a02c23cb1bd81090cb770e3a70cb081d121bd0bd5ed1dc06d61282b98bf2dd7b13d2c6cf833891c67951d7d0f429ebde3f1da943adb8ad285e6f13f798d6cd9a0a06bcd6125ebaa48f8f3bd5100a122f617817e3c42ebc3c3b154258fa26b9fd886ebfad42dedc6a2c4f9986bad88a2a79d7ee603554e9cfc5fe33a3a171cf7ba94fd43228019b2f6ff96a8abbc58d2098ad95a95442f6858eb69e131d7bcadad81b9bb69d7682a978279b631e22927decffbefbe8fb2e51d46a3fca66225d30451cef9953ef94f30b99f2b26ea75b84935ea4fb257dbe5734454b8087b3a4e115c6d31e72709303e9f0bb8c86fc6b11b93b53f9781bb92851a5cb5dc00d0b4e15683dbe4edbe986966fe1f711f24de9a0e1beaea8e835c70cddc589773d31191b74af780eb69867829abed6d3ffa94d5770000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 20&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028c393e5f8cf00dff51cd4f6deb3b7a65d7b1a3f3b59c9f3223168918f20b466011d71fa59d4e41514e2508cf50fa7ad579176974732dbb778a1c28ae5a472a39c71dc73b889fb289c9adb4592855972841c8e2b19d9c68e95f5f63559a716694096bddafa316fe6adac1b310b43f6986b1654fbd71ba420dd22c93dcac09cc0d21e0a4be9c3c23f6fffdf139564bbb2422cfa306c39bdf14270f8e77f1b7163cd9d1994fae59ee2d13ab3f7ff7b1262574e722af092a37bc0d66236e33674f80739958da090bc4b50269c0d16574d1254e5b9eb0e7a68795f6d5fba4462b1705404d63b882aa3c360990ca6d641478ffb250cd4b0c6c8c90638af31b5a5eb8f30a2f0fc9117b1d3b67f24e96129889d9216b074e933cd94911b22b8e4eb05414c2b7abe05e7ce4446fd11ea32ec4bd93ada657e4e241df58cdca11862ab334a9aca9fc1c4ffe2f7a8b45a0ee11088c9a1ec71f3900b36a8c2b90bbdb94d408aee9b1115f0eca50697431948d50d7c7f4d0c4ffe4b841582605b450a518595a51d6b2c860d3a5c7ded411ea46c8d2e8257a5c429accb7d19c6ed6295ed2c6c547b94c4ff1ae027e94c09bef55e397919c2c6c3f9e9787e6b1dd0bfe45624d537ba77ee5ede835ba3dc53d3ab548bfd45e6234ce181607b0f6cd89324e99ce20b0a2bd2560b2ef62f12ef9c15c23fdb9e440087ec7f58d8ca4faa989349e6a18db56fa47313309aef394c377f8b93733e2c7f7e80c3fecd8c562aeb654e3fa6a94f76534c21cab53bfae52d21f02a19bc0e8b87bb81ee203936ba0700793697fbcbf17940ff321cfc7606f23efd02e1e4573329041aff8f75630cce51a46918ae86fa5ed5d45acfa3d993c108620c44d8c7272844519c96e36ac14af1c956ad8b350b58c1e5a1a459247d3e5cf800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109805ddd41cbc874a784e9a38866287d09abe5a40014a8b184dbd8226269b8efb97c80be5efed2d18d2aeb5e848b0893d8c9abb6f6d4d994248db5d4d49386a3584c405a1020c9ab61a5e549241480c66f660bed4b700d424349c89d860da467e05cbe6a264a2756cd1932ad6ed812ea760ac980d75ed6590f1d8656291d7f1739be0538d7fb897690b0d0d28f09c4e80623a831519c8529eb229d1e51c5e7b74c8b24f68ac909e7152f394ff3a8d0c80421fad6d8e57c240d44339f2c695b118c3121a2272c268280e289a80ec43d561457b78b46df0582e41862f46c23ab02c737987348e44a8e99d50a31f05983892df3a7eb882714a1ff34d7e5ae62c291d070cb9b45bdba9480548c244284e357688319c69392b143b86200e7b6fcc0e6183da8d8b3df1e1c9000f49d964f6431b170f920170c9673c3468f3e03a88e5a64a9c46bf5c3e26c8e4b3eca9d8969c9a916feee001c95c21714bc72efcf978bed6607894403a32d571a6802b45a9e08b6201c876aca97714fdce56c02cfb37a4e2931de72a84a9165480486a966e9b27626dd81d68ece851e8b16458a8f43d0e99b3c2956966595376a210a6255e7a2831f66887a723a6dae749ec4a38b165d668811c082345b74093e1bd52aa91759781df4d223f6984ee572731ea1a1b6e138c025b709c2465aee176216d4a722e8934d16a973cb19cc1a83a994d070649c3a21a48a54d3985b6c3f2abe453565c5a8297dece0228d272412637880163e930f46942a1db5c09006e2836a1f90428ed0937ce011e4406e722ed8a1c55d169c54a3a3119adf511482f92c80001615bbcb200d6835cddaebfa1e7940886420c4202019b1adab78653188665253e362d0154822941d83cc66d8381187022a4e18b77b3ed0d05d0406c8bc2ec3b8d43c9895ad908dbebc290517e379c45f04bcd24e874a4b4168c73a2c66c2d616cb7ba184de461adf282e3ca3268c11dd993c8423fd0aa94acea536fc14dc243a24c8ff0dadb53526ebe34a157a51b455cdd4249a365fd8f156ca67f5c534ec06055709224a9b19a18edd395271c55faa96e9b82c41041d160985624f5d67ad9b0a18a492753a33335409671688f3da58c8c3aff9008a360826064617e2769ba3657ef2fb6d8b6fbe6e3ee1cfef591e6d2aeb2e9f3f2822f1d5dc26c6ac79cd0546a0760fa269557be9cc529d11e25e208d09da469a2f8b090f71fdf8f209fd19a2c6d39b5576543e5f2b2e6a3897e2c012d651a10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002d6f5abe373ce1f6fb14f2014f5bc0071b17ab2c84e8845fcbf4b15c79fbf2e5e06cffe6cad9a283014a975f81c9216b261cbc79edcd58d0e20c586d7c641e0ee97221befe54dbcc56a594df103ec24b52ddbb6052d1644972640f39deb98997fee7a252a65070798b7e46707fa440375b1ba705b3ecc7eac56d9c45297e585299c7d747b430f0d01e82081c70b4a87846f90267d5163181ded63e089a00afd33b0e2b3ace91182d8cc899223ce65a5d84b86bb3e8b34b13949bc800f2145468ba5411eacd6a6c331c340d4442d28efa0da959a2797c7181bd4bbe6e6dffd134cef373ecb0ec08590f06be0ce292d3718e2c0efc7cb40f1db26f5f38fdc82a72f81afbbc16591ee02dc818d63cae69ff0a28f942f7e07f6b0a741f3f0ebe3d0ea5859024aa408462d3d268c23f95d717c0a685a4ca73ad90ee923db57cd6cdd828b7ab0d4afa6a9ad7e32d407a44d7515c0a6af52a66ad72119ba1daec6514de3f8b462ec473072226aad61135b0f5ec646ba9a127c9894e51fdd1b2d38011a2a6d7497a55283133695d0af9b3ff7c5a8fd667231f9e511e3b8c4c3adc44d02de08c47b2382de67b32826754c6be5231ce0fc657341e20247cc6ce574f3d1a9376ac8237b49e5030e877a4e33cde25d838ead659eb1678706c759707fc66ce84cc968a8334c18f1632348824a6985a0331a93b59497b70c1a03a6848f18f5992972bc79f07f4222d2612797f495463836ae6cd3858d5b9bdf744a1cf361b5d454d41ac899a4fa61081b937cbabbf0ffec1b31c162224ea36ca2cd7fce54ec1a504932acc5bd0b17a156da7488f7017e4916a687fde7fcebb2901813b07964084ab0447a94dac3a0d3fda05b9f497cc1555a8c74838e29cb8ce89d304debe419d26ba7f3dc6e9526bd895495a5ff1d7ec83f70d045e306e7c2487a52cd7553f062d31888ef7fd27f667fcffa984afe0b9a4c4e85ca943812cdc157c5486b0b5ea6da05e4bb8697113190321a976d1806da129101e60a28b700000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 21&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000029039bc4207624a4d8110b9fcb7abe376d7e28aec5ea016f3e78bd146a337fe43f1fca1254b4d80de52d4fbd55966f8c33cb5d22affec72fbab4d56c7c230b068f4f457e5ebc7ea73398b734a7b3aeb1c90cef74ede174fac5c8a9c2fe928188745d1dbd73fedbe411764a7db72031479190317b94d184236e533a69be092eda15ec79e418a399b969971dabe5ab9cd0d74259595afc8bad15861ece82b1636c88af392832db3a7cc88e2465969db1635938464ec58189b9272f308cbe14fe2d239cc1f059e54d1f4398d43b48b94b521ace8c9238d1016c4cd1270298b43038a65a33c2ac6e2bc723a38b6eb05af57e4909aea70eea1e62497897d9f3edf2553f85956b2db520758dd2d7b28829a8e6ebd29568e54c56972ca6bb3b5c4ea2667f7c69b78f5cf9d7281de64c919d49bdfab39869ca94d21b4bf5e7706e950a8a91f2309db56d34e235bf0472c64e7cd9b6064b41f5c6a496feb363f7cce44a44bda7258d4d7481bb39f9b2e98168f6a2319f90e6a8aa7c9d729f9fd58e95b0d2e7780fb15a2dad2bfedfb19b0fbfaea9e748140f6c133659befb6401df677bb83d333f8ae6e82a70e26d50544e4a475973ea8cfd56cb23d1fd6b96babb1aab39cb1db70bf09fef36dae8c4e7e591499b45220ccb2fbbb747f512be314bf283ebb778252e23a664546c329b8d535958bf7be7b18a99fc5a57c267e28946e6eafc2ebd059fe37bc35bda020e69fef28f1c86b7399076cebfb976b89da44369eab3e559271dba93d5fa15c708c4368c09f91b1da3e4872a9c981eed5386162dc62f9c9f7c8c57de2eb4db13f2d58a4e8c86f179c99ae22fcca2160ca12c832cf8e58bcc346a375726522ab6edb40c892691157d506fd9b4459e9837129a4974cee84670f45873f6f2faf2e0bc336278da7c880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381099ebe7ef99dd75826b4e814e411fa8c8975952885f7817df068a40a08b3411c715a89637cad2936ab868588c4c7fbeac85c58c52374ca984908e52248db94504faddcb2024898960a8144d36df88215efd3c3996254512fab51cea17ac921432ca103be81e0d750065986b12744174124a79e73d7ebec8441340a12ffaaf3b1081f9a910b837912b8e848e9ef6e4db2d6462335b83a55143b515e2f7c5331b2e75a2afc7731d892012d52e99864cc7a9508b2741a637fb5cc3dc4a252e13fea97b5ade4cd3826ab5be3e4330705db85066e2ea4f54d971d0e7488209689758aff78810af5506fe7475ee5776cd7d50afe9d5b10833a4108ac91bbcc89ab7521f7ca15ec9630aaa613dc9d134007487d9163b17e277b0c2a6251c560b44eef2ebe7509903aad11991e31686e18b1673665901206ff838449e6386fe29d50d8f67e44b8a9ecbed8e25454a91d668173e04eb5a206d65e2fe4b216de507ea06fa7fd305bc24dd90c114b15cc6b639168e2b7422b02bcc56a046555f9abbe4390e12ac2543d6294a6190461c5d7d40d1cbe11b460b488450db04113caac6ef80bd9a41a0edc42331ca045a946bb46de4d19cc1a53b36c10c2dd95bd1df12f3876c742575c27a6108dd41109cb454f6b60b028f1c2a443ff24b0bb91ea591d2781f3cab7aeb5454e7db463ac7a1a1efc85bce87a81eecb9abb0ecd7edcc768a8021d5a5d7e33d0696693761f247994911ae16632466f88a9dea4c25da6a4a7886a79934cc15bfc5516ec1067326af8b8086e78a35d982afd935c28a19128f58459464e29f4ea8cb6b0a21184b353c723f16517a64d049c78db8b2d57cc68a14e6312e690b31ae6b1a82511437c520a021792894a23604de2ef8ee13d3424418b6b80ebd521a2ba3a4077f026655c7fe435b6a8080b1850b9b7eba4371400812985675587f8661838ed7b6d728b052b9c4f6e71f64a8e83c94e82f54b751546a9663702cc538b509ad8146b55e4be50908a961f3d041aaaf32d04cc38f29f92d284cf44901675d749dc5418af11f74241abbec827baeb48238965a5964f31019693f826047f2886da03cb62150cc03df3f6855c8f054a22de8f118ef45a80a720024fc06e8a3600a05f581fd1ca11bc70f12910436897b11a55e51b2f1b14cc207473402e89ac7c8ac99bff0db0414b3c97604bd903a505577503d541cb22afe09f755e0a9c5b2247c5a274ad4e44ad8097b7e08a290cf9d22b54d17abd8c8061a74bfc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002f74c4697a7d8195bc7d4b8f2fcf3a7e9419e8fc9ac6bafc5d658260511c697286bfe44e2ce98c21c98be42e5af0fceef8aa54c5770af287a81c7481fe3391a6111ae6243d545b2a651599b45931d7640579f8659a8bd6f77260f235f71476ed64714fddb70c549cbe089322130f7b0a21f530508970d55cba55baeacbedf684c7979078102ecffc2c3f182f710280cabc2decd3d3b5d3ce908cb2307b00fcc0c5412a12aecd041b5f70cc0149390312b9c81592bb0e2ece83d4495944e29aa798de67fd69e2bd0695dc573f78d8bb48e6b8679e1c50d1e6e58e218b77ee51597eb43ecf7301d86f457353d60e98cedc95b4a76844e889bf7e9d03503757569e40d55ab43d63293eddbb579fe981ffd4dab056f85006ffb5e759b9c16f5f6b235d7dd78458a73ef37118edf599aa504e9db9ab5dbc90b8e478f3dc1f35a7c4604a383bbbb410cfb2c5f746f83ef94bdb2f244d421818c26827d5b7d665b8a802181eb7a9ce95b6633e24d914feca7e969f64038acc3009b15168426edb67af2ccf4e859f5c616891d355f7910acfa599c396bbb2d2782cbf1432e6259faa77730b6b86fe0d67730152cd2ae0f9b0314048ccd25772c01fc9773ebf06618a8ce1e940f48663427775990cdc41c4dd3e9ac6eda1ea50e04f1d329e64c8532a7ae32238c131753d60a25810a5ffbeaa9007a6984ef69eed92b777e079ce0ff48c2aee9c18d1db9f49b5419ec6c0e2212ddd2e2fdeaf0fe9f2b84d9c50dde86a70fc28bbf8918a973cc67a36e97ce3027d73891e7aeb24baf4b12a9dc8aab5d6afa380bfac3703d2d32f1e40fbb532fd6d7d710dc0741dfc7eabfe55ba5c311a00e3be55c2ee74155e3a06685071a962d7532ac76d59fc187eff01f8d339f74323732168fa5d14f4b2a72c9164a04a6ef14bf5deb1833e4baa19a55ae590f542d4448e0eaff0e0afd2fb30fd671631b9325f4a0bac9a43dcd2840185a2f601117a625b0dad5503578537be2a535d2f556f371536bcf68c0e01c96301f08e1567dbf9d8504096a8fd89c086db695da191099fd1e8ea94035276d1d000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 22&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000029039f882dbf595cc444f0c636a526cbbe257530416afcc0c9943e964cc509c823bbdf4052f5a60aa07b94546d98eda4778f3360699fd372d8af0f3b268ae2247122928c74fdb1034c726d55dbd45d05ffd327ec32f4befbb050fcb25f1bbd6a880675fb787e90f4136a50ee370e1e1cc943b08877426a86a58e9a10a714923bbb5c6c881b1f8754569807a300e97bd68b3cc15632f4bcb333a8ababe6661589208a0c3d07708ef3670fe198a7a62496325ac9aa44fca604b10f8c25b17cd760d2daa0cc56273f7bace2350abc976d942578e291e0d8fed2e411b1ced6de7418e5ae7aa233c0b8eab476b963f7b146283134249812d3d555ee77130b16824f1e47568e37c27f0c25c9ce8f558543df64df4d1060dd6cb252aee1535fa48a759cac9e54996b9ba1cb9c76df5481575d91168b25021bbf7c57bb790ec2f0d5c57247a72959b2e85544a53e23d6e667670eff25c5fb28a137aa33046b0b83e85374766a026422f122778b5b1c39a5ba07a55658f1f940af67d5aeba5baa57d88a6a59b2ab0d064bd74aa6d851429e3aff8ed6139e80f6158f35f10869a590c4d2445952d7818468d126ebc97b68730550c6e2af1a2684e597088a0bb8decd88aafb8e4de7aa258127651003f7f8261e64beec53797074bfe1aaa3bb98260e4763b0501c175241c5cba5d5065af59f67e9fce94b51346e936d5e585c5694d28bd6dcbdddee2274437d31444c4650375ed9c9b3e3f57a37a67edd2188c691886be8febefc5b08ce7766b8824dc49ee452e993ad33c8322bbf673758fc6dcd6cb3c3a5b039d1dc262b334d628bd54b227c5dc409fa7321eb8758db792971d90e459432bf1c02bd4d58c86a9b175515330574c54c713dadb3a35ad92c903beadd55a5e6a30ac23a8665f81e5410a8cb1c1bb3a300400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109a9b5f0093eed754c40d5f7bb6b815d454a6ae292cf1c65a3a9506a2596d845717a489d41fdf4e229ad1647062ca385ec0c076d61bbd518429a5432f5ac994398f55aa1e550f5b468675320e6c3a54436cb5bc5c1180892ea8c1006b78d8339649f0121011b31884fa4869aafa51cd1da6d2a393988c5022b144f84d7c07290993b1a181e128d100380f3e6c56fd8f85006a5d72584c502fbc8f71a8903d2dee4fc3026caa0972c711c8226458b1c4a0cba4b16d1d13894718330a4680c42cc5f253aa2f25d58805b9cce0536a0abe98cdd2429ae8a0a1c0ef08822cd72740ab07a6621a5bc6e22606eafe3dccf3e853051900bda1eb3ad2f55782a8420d13a5401ecda6f4a0eea50a9979f16bfa57f0b0142e55d352585904ab0c511bed7e37255c9000e19498d5cef9182519c4e51847824572b9acdd558658df02dfa7677e72a635fa5ad60294fa872e9b9bbd7a67d64c580459d6cbda3d4df5a1fdb0e8ab89789b300ce25261a374d1a9b012a78ba26c1553e9ab7ea4fadbc75a4946936a58f785d4c34d808b821b1d056ce1a5a5a920345d068f795e975d2f79a7d9595b21360042148d60dd65b2e447cce4cc29e57448adab7973486a8b6acd0639cd77933c2c1545e0da4a34e06172b666f7879996a039c4865f1abb72623b444a9f9b3cf03cc160c379686d7ef8cb87b2017276e04a59475df821448f915f2e65b219162eefa6b188482f52c89cfecb1b51a0be44e6905a2245194fe0efc69962903621477be0223d25ddf883325b7aa0212ae7bf5f0928ed1aab98031b26ca92aa1e45482ee229b55515285bc955765e8ffa767c60e9e79dad386c29f205626641c09165a6e33552c15944e7d92fa9a289e5a02a346634b06a1707b866147db077191890a671729a1c16b8656e2557174e8729cc44a1c5a70356b3898c955d8a1a7359d8801184c556b857840338e830184e59153958d3254e046608f87a90970b4c3222c24b6e999461388a15d9ef64487639d26489532bb1d736d34ba3bd42c41a5dc2686cb15169d791d44ed81448e78f2569e10f2526e65bb21a2b9b77a2d30e28bde18d8ea84f36235338ee381806dc588f960eb57d2336fe9b00518c44943ec2769339d2b678ebc6b9b6a3c91b50981d7451604f2b7674484a16086dbb37fe17d974a15c44bc2cf693dbeaaf09a0191351fc28c5ea6060959245f45b64f725cc8784f5c942a3373dec77502996aa904e5af619e7e226c0e9fbabc42682fdb0600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000031872713ea55f1e5ccd5787f172657c6f6c74081de2d70816e8531497965df02dac04d91c4d09dcf8904cb152e2138f829386f4351015da253a5b5eb92d96e537dae3ce809443ea90332d9c754eb11f4de586a83b5dee7b1b9bd547ee7107530249b14279baa04683d74b69d7bfc8bbcd447fe7706593c01188fe6ad8d0e2572d49f83e93986b380d4169bdd94e3311941dd2b041dfabc5aea1297c65bb5c8352c99ff838d46b93b3e5f79e3cc5be5408fe5e59a10d488dd65a997b086fdd96cefb0247b2baf7b490317e34330a879d04e374c92ada33ee243d84da015fddec243b00bd7488aefe373e8ab1890273a7a2285988e9daf9c4e7c5a17f54ad6195ede2c79657e1bcced0641e20f7ee26eaf53dd8c82827f2d2783d44fb030c95791f41653e628062267a5cf534df00116c1ed1de9f360b97555c65cdd80724104fb1bd4da5785b5d9c24438557e48aee58d57a03e06d553b05b67e1c8d10085c2f153647f174f7922fb8d2210454f7014bddbc627756eb7cdef99b6e3a2779f82088e3f2da14c2dcb5b185aeb5d6acbfad43e286aae8f84a58e8df6abc64e4a8efd69fea18dbfa6808f25fd418de8ba923500b74e34dda3ca6ad8dc208102dc4a876d8b8cd2926aea4b3ae11a546f6235abea152dbdf43e0bcdfcdc83299207f294a707c8b4d1f56aa64a205c718aca69b862afe7489f11b324e7af6be68380d2ca6e0af0e2e20f890f2cf98907a9d43135c03e85e86c9ee417140efee9054b46c110a84f1841ae3cfafe5b4a95d6b2b606d8d0a70baea85c9412bc2d54146e9f866800e8e8615a0d64d1d595677e8c88699e3ca6097d47e9fe64050fb55033fad4d5f226da8eb5ddf99369acc7552927ed3ac7368b9efea2443926df26d1c172858fd8a5d4e1d7d39e7f7df047385d39131184087cdc45b299bd1f7048e918223da3f960608e853ee49ea667465dbbd889cbda20ffbb540c9ebba5c2cd16a22a57b561e01331d6ea6bdadbd6a5d2bd1441ef4e1d9dd11cc62a0fa5bbffcbed0d27b6acaf0889eaa5863dd9bb35920707b71a0805630d1769fea320516e71cb2b125ac274f16f7a6876f4b922c7c006f38ae1f7183ca768715d2af0000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 23&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000029139b0f6ae60978dc6f9af5e36443b544920c5729e68c4935b233adbdfae279752520c5a941b4a5a53788b429d746f12a9e06b99961cdaecca3d7a0b0ec937788c0840ba1685c9a63cbad9f4d4b167f2027d202c14e85c05b34567f126521969a2b4160ebf75036e4acab3c7c3841ba9317351f8aade47bfdda8364cfbd9ba10aebbc89947f4eb666922711d8c2a12f4934f668cd5befc1dbefcdab5ae06fad774829f6bab4b24b840e76a11cea8f8cc4b08ee9f18c8aff692efa3f4e0a35bedfddb7ee275ec4ab79ed54fb0cb22ce9e510fd631c4ef938a330241525658fc7f8eb91f360792653582b8ef1fa15183a498d7b325c5f953c9596df7c94df266d9172a545910b5a7d58e593f20059f5d1b52952732079b4b22d228231b342730b707368b2eeba43f2d72a8443fb1a4c51d38cb38e1265857bf87c33a2d910cc519575c84ebb1f9855e2908a0c297644141e3dedb140d5f474d1486310943b893368cfcb43086977fc2263316e67dd94d5509e3ba8bd134bae3ebac6cd0d4f9ba5172f14d5520b5a45c16b3f9348bb52ca1145a2a9fe9a3229ae31b8b4439b692f0df43ac91f299cba5699244f13a267571b7edd165327fa66c76d56726ebab44b63bb848d830792dd57230f7e9fc65b69cd5e06b7ec753efc2fab933140bad873b8a324747f4a5b0ec3dd78154acabb48c9bcede14464fa9099d3a93c50591da70126e2ec57d20e544e523d35aec9d11dd18ae9c1135d3ac4bf5ea459638d255c9bcf544b702c2b918eefd38dbb473c9d684e0f4731ca64084c14b4d71a862b4c54ec6f5c4a1688415ba99d49da3eff7e6d76fb8d4964a6fe01a4ab77d23d6a64ace07c542618de380e4eb96c66307c7c990f184a479cd8d160363e18ba52d1d64e62888780ab3cbd142fb743c1b315ac3be64000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109a630202b0e68891d4998ebec6b9fbabdd0c83803874aa0bb070c13106c321f74bcab20b5feb669cbdae69d22bd569c238e34ea5576b8d4b346e291b9a06e287a1a3175e1ce730fb11693fae3ae433226b3392a1c2810d55a5141ce31e092066b2b07172c84973cdd2a8108d94810a5f68189f2e040edf445610795d1102d66fcf9c9c7563b64ce6988b81f9013d244a59d8d8994657598c228f821951db5b0c55f32013715fe23dab7b29c82b9977f41be61468364dd3c84238b97c49e36fd305bd61b9a6705bdd19b2594ba6efbc41d91cf10e1edc97d52703c90ab1a1e903c4dc07603720d8a11a13a67319b0d7f9a93c8e0ea3eb545a865260fe06eb65154c0c53e84bdc7e7ae642025a8c812d246bc383899847017f65b9e7d81c14afe7a2cc5571706d154aea7a4b827ecbb8dbb527e5e3a9a690e646a657b35fc0061146eeaa3ad1f31fc95c2bc967101a1d8205bfc311050eb1d9ef45ff88c2ebfb7613568b00bf26065c9696e2d6b43ba1a44b1e90a689e460a31209f24699d234260e15aaa5bf2ff59b53bdebde3cb171862c6f8a43c272da55434a2399329571900405cd479ae32b9f47c0a4c2e5c36386f6b8a8b615085f2d4d0176085f9d88c5b3de027e3e2d067095e97f5e98ca8be9eb73784905c6a954a36e865827ef235f9de6b479dce36d7061afc23a55fd63d558f94ae5e067ece9633c26b0801242a77e0b9574025f5607969f6d1e953b07e6439c4ca725e1560122641a94b4cf4c08322810dc0ca2b589b253fa95ca148e315125a665819417c602540a4688f8f86a1e84b90a61e90e6dc4a2723aa7ad6f8803c9b98b8eef446a61777bf5d3dc49bddba64e96a77af81d89fa86c487e8af6173c96d39b658c0a2d42db08c0bb1260ba7a84d0756846528a97069388298bda1e6d840d9532f2ce84425cf525dabf4442b1bc8fca9da3a862a99369af147b6f41d9e85306a275b10935cedfb9576862536e19cb006219a1b595f305a1b0a1a74676304d91e1e5a0d45678cf1705dcf00179d8b849624923707915b60c663a3ae81901ca8f7492e377dba10687baf41bccaf19810d44d41fd2ab7ee5ef20b7d24c8998be5a59942039c112032f812a157d60827daa8f79b168f30a58e046e5ce3025e2239c149ae7ae2bccbeaea1c37f1268a2dc1642862010a674953782e79fb7ba25b360071d5d5d62c2a0aeb873689751eda1c13c79e30692ab4c53f9b3a9c414b70c69201637169d3e045a05cdd7f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000339209658cd1d801079ffe8e950bafd70a028cfcc35b9fb00d232c5603a1d51ba13e5de59e0277962c4474e9f3f60fcd99c9b79665b3839d5c037b921a4de8e144fa1d38182fbdeecda6934e814d9186591f01c5e23349b34f4439b4d402c4072cb4d702966ab473d2c39443f41fbdd0c48e566d33e076422ee72fb47b2ffd661f367e9efddc988bca02382ef93590d4fe3ece8b1d9d8b3a653219c7d131b43e2fde2851541f467c31129e6f9b9d124221cd52610b9f138eac1d01f193148fa0415b29f5c86d15067eb1e26c9d51f05655e8545f734f8f244854ad76c6b04c230898bea33efdceef100d79f8e3b894ba583466749b82007067806e3a7b3ba954f6fc5abff0e099a24d14d865f6f4538736124acc5ead4169ddf2144ad558da3c74cdabec147d2afa113edfd1e2280766b18792310fb6b4fe5d0d9f65906b1cc43655bb3d6178ef9093ac9c8f1a91bf49008179394eee79e1d8e3228f567770c1ba1e30ba4bce2465ab68f53ce21c0d8ab2f6e535828f211d4db957dc3af8b7e00dabd8f1f74c959b2aff45121c5b5abd3136c6f55d5f5ffdbcebc3cd7a430ff3813d23bcdc1254fe6949da4e7694028b7fcb876099e91b92c65d85c39d4be9325afe81703e5b18cbd7bd9eb59a9bb9408abd966ade9a60303807ad1b2c14c04cdf8fae6950a55b21c9ebb5e94713bf8c2890215c5da94b59cb31edc671093b15ff5014db4cd3ea8060260dc1612e9fd6e5ab40f0656121f689c8e94212269a7b24305c83bf0583418755ce690913cb081f2893fb42bc4750f2c053c48c1552430793cdde1a49ac9e21913210d727c4beb5640ab9b7505ea4e59af417a085394181784bf1bb0bc32bd71cc57ce77541581f14b8ba4b758500694796262b561a38c72893c77b548d779a3833eeb064cddba5471cbffbc769e139946155bf376a56415ab743de568cd21895ed6951b5bfe1b1629dd6510dcd4483f206954964e0517546dd96900a2540a51835818d1730b0c9123e7fd8b28e6843bffb659945a273cea944ff6e83c234b3e43db4630614e0b67778ea760ee341fe68c525e90475a1560821ae6b2a85015292c36eaa2e041ac04fb55922c48204525187c7e0476a9fed04efbba96f369d8ae709506620127fd399613a9796c4ff96d7e00000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 24&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028b39e9e77e97b2f3f36ebead3a05903d741b8cc201d39ef7edee1a5358c87b39e318d086c5bfe45096e3a06cc843288b4edc357dc2c1a88eef8fd16bc9a26846e12ff9f3e94db2f1e29ffaa083cedd2f7f7291a0f34bf43c9d134f47890b2227f9cc318e055ecd816b916787fb005ba659c85ba5302f70391c78d4b1b2e69b957da731daac9636294040f67206db17934551148dad55b378e74d933c089c6d4c93d22b5adc44c2c4cceb2e1d3f935b97da183291ad58a5ea93679eb93399a71dc3e1eff229f2833eb1e8a4a9b5a21df869dc5cd2dac11f7bbee7cdbc79256b327c82a3cc6bb3dcbcf2d299ed130c7b3579778ee92f457dc8459e4d27c91a47734f7b8a45db4c9c1e26d66ad76f7b73eb9ab293e62d87c9ba7ffd17baa8c0b1ef071dac7f5122db17c6b60441156bbab79c66135700d3d208a1fb18e562a9596117fe0a2da34fd2949b89832302b294eb9ad997710ba8d53cfed5361b28ddd18bc6cd4d2dd10ced70eb6061467d26a4a8d334d255e6c5475964d729d76c691452496d7f71298d4974fc7e4e6c1317dec8a02d9421f1e2ebba19de03973d92250884e5029a4ac53bc1ae5995adacb744d0e43bedb685f743eb3cce27bd0f08fb3d9a7433448e4360aad82350235ad9b059e54e454ed82d0923ef6b2adafddafbe97af8d98eae2a35f04b22d50d5c9b20b7cf1989a125dfb6bb24b1cae25b1438562ea36d65139d450b3989a2e7a8af2786199a9fbb3ffc1dede85c31c45d09680aba6fd06927904f340b2e676a713f9f156afd6d97db0181c1a7f87a744f3c44d0b803b2fdc524c23dc896c196dc2f8abeff3a91ba4208d124a35caba9a8bc9d52cbf2facc47a7d10d545997f1baac96e8e669b06b12422ccdb85d24a2b50bf0b2f8f901978369fe1933476780000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109257ca5894b5db45fd113984600c56195e331a2dec209ec1c10e3084c068ece17a013a8b0d66348991e9ebca922ab0590124d95c20b72e2a645ba61826227283a7622b8bd264f1d211e88c32c39b731d1477bc6403d4208e0809ad87cc1e4e6e1a2631a547af8a0a7872d74bd99575b6316da568bf316e785a5771a3e047a9331c01500dfbc1428b3fb875ec6737adedb884d9f96c13756fe53af6d000f149827ee354d8e60212e3a6a156fe6ff1f8f261cb3c3e81e205fc66653d5c78e63ad637badd0a359b1e7f84e0239bd760ba5e4aabb73f2e8d3e996368940ab2ac8140d4aa2d6a979a71b34dea2f2d78badac1de8e3b261a30f0d2d511b028e3de0a0a5ee69a166d80b25eb814c929a722271e7f1176e22a7bd8d1495657975ccc378a4e0f6e2738e7cb11cf81ba2a0d7ab96ddd13cacb88d7a637730cd68a1e51d6527692c10284cba6b5acd1fa54efa3491733c2081e5e250ae1e186e6092daf39094c7c54e47cdb34a23823e04af99c8ee52a2853b8786d96319986f04fc80f4ec5ac97ca85e3531623a27863c1be7919142ac094234af4e30446d81096293534dc8637a44c22f5078244e48203656d07b59156763ccaed571a3ed54d2c22181a2be23516ac025a640204d13b602e5d7b295b0e365ed7365404c651349c32672784a07d69e64ac5f0b69efe368b58c1a798d21849eff713dc7e544820c624e8ff247ba5283c85f75850c738ba2c3410d81a0b9ecedd051ac51c7b59e6c163539d55e6f41161e0bd86fa9d66771aaa9e9efd536395fdb4a6ec525cc56532690b973b8cb6259e087b1fa0c212849978ce0097801150e75d124d612d549557eb594a1282a47c18dfabda81a3015686a74df779ca1d9f1819cde465df3393fe30e1622c733a3d6034681da72d4ae5d69041455ccc0544294c9a86f4b5c442dcc448a87518e95fbf9be9df4ab765ef45212619670c763bfa6faaae032c42381ba2d6a50fbfc8cbd0e21546bf8194023651250d34a88bd9e9ec5220a6f9b0e48ea631202bd9a500a0ad3074800df410d89d8b10dcbb49cd036aa72f3237b877a1b51a59bae965a2b1450c1ff26b2a140be98e006ac981c1d1a408de3b3381ea8f2d36c3470db84f2a67a97845635bc433c402cc47a9152b0ade129b40d05bd7fc621e4028c0b033e0d184a261f29f98a99aa17b46ee5cb638fa77b76861b83daddfa2439bb207489952ed0b8bbf5510fb5d5b32812963f49b984435b4b151bb6337bd5cd9c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035a8f37a065dd696ad437ec82909261b842ec0a3e66f8ac574105a3c82ec8b4926f2466fa550f8ea1b6a9a142c00afa44be6512a85350930dffc99b95aa21012057051b68c48581ae439b9290a163aa4b6afcf80ffb91a3321c7b9abad56d5dc1be4e67e5576c9f3a7db96071859b94eb22a73dd96c66ae67ab11d1ab62a86d826c682dfb8cca3259dcb5b34be635421cd4206e7d92147f14c36424eaa407b441f58e5c187e58a26b2ae144888a3cc1387ac7d0a681eeddc3b7781ab282e8185ccf33fb27500cfd119e0415db1e45237520a868c8457c88a1d3ee97ec9451da35d7e74924f8902949e7eb14ba87c8ac672d7e4f3bec1b2814dfa67a8dd2e2d4ff4661d64bc4c6d6a78d4e489689b6063cdff5a3f1554501b424284a9f4b8fe777fe4e6afb83a85e36200a9ab40b9c18678454b2a3f50a4862ba1e36f0c57ad004ff90192b5619614e37dbb38a1b8a65ac613f7796c70772128377065b84f122540106d1b4f9123c4e009b4c0a85d59b35f72debddd154abec7f3fb25fd1fa04367386098de610b26fa3ecb031a6072d14607e92ffbe195abff71e586a984131af24e18ae94dbab0544fd2ad217960f337111bfbd4046809ea03c7c47b7177757a4a43e1fd0134859ba735a8fc17597e593bb58322136602954d3a21096b0d1dee5cf0ad17a5fcf561ffa21caa70d33998840e4cfa18ba481704a8b82d2cc1c110fc9a6704751365ae9f338afe4cf9c811697dddfa8635a2f3cd02dd1845251014bf2f2d6c02a907bd783207c4773a937048a07c500d7c424b5f65a2c376523740df9a0b60437cb8ae17d64dd51dd4e433af83b20c4b6b890b97976df09e3a86ac19006c229d59fc7a2923245b7b1f0acf7c42e486d41ca1ac1d7051aeef6003ce94182f97d099c74317f61eb47ae18c2bed6a3cb253c21ec835e435123e0a657ed926f880ce8e5de3155272328a467278f52ac50a1121ae818a3ea3a2e1f7401ce23aaf66a4ac289748a7e98a5124c586d8957bb4edd3f091492bb1a64d75efcd45ad51ca420f15da848b20dc6bb765e7b71359b3a9e95e121266ae4a40dc2e9a3d81ea1b1a643594b3d4e6abb7d1202201de92bdf0cc1ed977e2d5851822a01f48a6f23180822888ce345ac9be0cc69bc448d41ca20b79c35b1dad73e6c683e70c4439b404cbf07fcc39b0e5a1d33f3717a6bad28a6da4f091bc7a000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 25&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028e39d325086ed012aa552f85ff2dc29eb46260e7f56997816d109ec10b992cbb22c1663851dcc1c9e22db19e67e14edded864a56ec6f21dc34e4729c562af9bdeaf374866b5b178e16566211fdfbaf63a65956bc590a7de8b5becebf12ea4ec99e0e4b616373fc9fcc3e76d36a1d358be0b73571ab34a718d5c9b218f98d1e070012991a713161f9421edaa1fa040224cc216b6c1e687e7a16ffd7dea6803d9df51a1472e672466aedc88a410ec336802e71c6d2d8b02d58774fd725ad6572ee15120e7c2506e10b5239910bd2a96f55969e1648c5a28edefbd0dc61706e257949c4579f9414c44ecec36edce65693542c0c261d66e6b1c96f01aab13e9a56c9f88abef2cbddf9a4ddefd7474e024755ca3baf1d921d883424d5ae5ef620efce0a8db6a0e9d5d688c6451f9867d9ceef8a539fed890f492d41ccf6c18b9561895c313d749e34508a60a1a8d370c939e9022146639a698b8ed66656d8db6b2470f2ee391a6c6c830f0c17a65d73b6b688594f4fe58769ccd6ec5817a5d934c9d5952bc1a1e97a3f2e8ae4188f2eaa0123906e565e67ef6bec7bb57374ed5251e79b3bf2d5889cf0fc505acb0630dc5af7dea5da9fc35c7f067d0960b219a4e3311e4d226ddf75c5d7fef88a1a0fa82ede5e340234e8b5ecc22221b8aba445bff0df96578394e3ef50671e3db76d291d0c537ae956dce6611513ced78dece8e85a06ceb49c7590424de4e0ac98ce4e7d1fc031d0b3d677eeb5972f4d073959c9524b21c2cb49466dc5d1c84f751e8f01825cd60cebfd81e8d2b1d298ac6702d240f4f48e558b1f876b3b4c5c8246b6a51a794b4dfa26f0fae30464883291e643480cf7b8f3b67026b6c345c2417a9374f617234fdd22907e0a1ed212d921fd275f710becb934cd9a1660a1b0c481a4400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381094d55f0302f84e16ca4ede4b7ce7d10c91880774e4627a0c41977dad1173c5c9703dacc4926be81894c306ebc52e6a9a6638469f7a314a0409f409353ce5b2b6ec45fa5a2218f456570b5f162ec24698662d9af9d6ce27c548b5bd873560976934d835fb919abe46f182af92a4294d80a55bc3ea3b227f4bd193347380f5c930532c0f35acc6ab572944922be332282943a1be01fbc7977a8404012d55aba71e4fc2be1a384c25ead9ad035c130105b12b46cd217491d05b1ee028a0d237765c922676d4439c4ed55e7d70c8d99035bba2d931f263483d16ba53d020f5834d8126f41efcb6829d0aecec2b846e87e0cc5888b54848a0089b606ef669d7e52be55d441775c5c38bb5085315dd687c45d6e0ca43a3179941ed73e857bb4f84d6f1de96104e1a07cbe95c38b6e12323b405b021fc3c716d62c7a27cf1937bcff45a69e7e18bd8ee26d93be2b4228ea0bca906bc0e141dcdd7105e2b0c6185c3395e6955a88e4d828e568094a6e1f7c54796bbc088b264626561d49629b6e1ac5476cd402d5f480fb23429d8c67334e592784b9f2e44811b709cc623ab206d95cface03c0cba2b13c17a24b2dec7a807131e90198241dda9590cf4a569188522a4eba9804df61880f775f90ed9844cd2559666ac25edb747fba919686c7d717f133b35d99799450b29b3f01351290939723dd405ad08d6ae60f26419e9c9594991e320460b7f31062a908486b50e7c686f474b0755bab972ed2943dd39d5f0c85b870947b12498ba9d6c90e9865c14a0bc6173d39f886d8063271ac0afb7dcf688d129ec8aecb6f259a9594412bbab9393170d3ca6da14ce614d4524765c2c8b3b1e9ef162d73640e6adbb1b1309032ede646cebf9ac885c2bacdb65a7998a96dcdbad0b3920d4c665eb517c2a5794188d460d45f435699ebe7e25422edfe85b1a55c22da6f615b905a423c6b84279c0a9ea1297b9d1d7a9dbda245b569080f1d51618d1276051ea9564489e10ba6f943fd1ac14b0da56a5260f004b84602919897311d20a104486b5d22703344e26a4a78a5f58a5b686868de678545af649d16a03028df23b5ec21cfcfcd349ac08459d72448958b042957e624b637d200d9517f29ef6adaefa92824b5006d40d6152435909c46b7075a4a86a3095d9ea6d75ae841a29ec2af63fd2da2a922bacaddd02b42bd4b76e7cc87708612c68723c12c2821c99a97ad482024d7329956b5ea20153463055634cd416e4a2a6fb080c107e49f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037b30d61c6fbd64113fced8c5205026ebac0d9f3522182617cb00b6e70c8da62ecc1bbc8e1fdaf17cc61dd01ce85a9072cc1d9d34fdadba5b93e0aab4c9c4c9e26d3f7f145fcb23673b6e0b373c0fd1a58f52486b72624ef91a539519ee5305772a006e49521744912bcf3cdbad424f00428aa96ccc21d000efb09da5ce652e361a6fb649a060835e3b9dc9cbec660c7531620115ec905dca6ee2a1ce36554c0fc1d6dd6863b8f3843508ed5c214b6923e7f5c0304e9b0d5e5e433bd029116a33a60cb980737ac950577d0594bfe0ad2225cb8d3fa42f192b0ec05a49391632a32fa931c0fbd83a7b6ea24301ad0906e7911f9d900d19ae1247ababb1c0e9b9bd165185d9d7413ea068fe8824cce5b3ad51fe8e2bb2c4022c61b002c1df4852e4910f38613787ca12371038b6364d920e07b4b417401253451ddc25624b5d038b2dfe29b8494ec960f87803caa256a95c9868af819747e4bf26faaba6ddbaed93a7815c795ad5eb7fb4592df678ac1375388cc7ed3a6230cbe80abbb113c80b70c789cf0c66b943e67ce814f12d3d83f3b90a4320feb7fb81dc93b05d7fe2d36584399214d3d7c71aef322a5d04b5470703b3660bf86b0b17ba9ff23e45f7befec3758786d2111c81ba4d81b83feea35a0668e5eb3694963bb4db3acce4fcba6f3f6fed9627580dd2d2dc103ef7e52bb9745bd42a7fbdb459b5c8aaeba67686eb899e3177faf0897c61b008ace3304c41b4c79e2ef9c865e9958d8716bddb69154fb33187d927b5296c1589fb1ae3d553f116ff6cae56910ce6717c446b9947ab2a981a8f5999c1c6e517eb3fe584f5d10059910e22f40fbddb709c9f686f51abf7d7206a8bab4a346b51523c362d749238d7ef6671a89cd86a8540604f134d760267e91eb92fc0fc275cab69c776ef81dbad35027e5307f1d34ebf5d6e4df424d709666a1e649c044c4930098b2e6e3782a93976b55073c504563c7e052b6816c07f0fd54a759d2bc189fac3ff54549fc4de192efb58a9e301863a77380967735910f63d35ef5fdbd8751de4bc6bf2e3095628dc7f67c1f5571d17aa342593b2c7f953c3f0f22da1862122031bbeaf0d00a029c043304e3e2609c4fed8a7404fa10e2ec846a70eb0e37c5be61e698cf2296ec1fbe6fed75f6fe3113c23b29afb5a6d7e3a9e46e2d89d8c06450cea11492c1a97f7d6be8ff6c014930043022b264fd32593952bc606f779598631e48eed86ec2a013d8eb866f311a4000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 26&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000029139b5e6f6695f2c209a5bf45ef10f4a0aa6eae46204c5225b65ba72b7fe85b34f3b664eb4f709265a740665d03b48917610effe0494557b2b325503530cecae3a8643500b0451f56bbd5a87658c1a0468739aa687529ce734318ec1a52dfc2546674925d7d88ffeeccd708e9f49dd62a79d62bd0a2eb928546923b874ce32bb06a7b170883ecd3da99ac8fb0b9e43dd98b3729712b619fee5f638c9dd22b31f7c12835618ea16b290d21a471fd4b44fa288c64d866f8951d8bbd8e8f781814d61ec1b0334d065fd0df677f3cbe44125720ca1604b1069e35ba14432a9942d29222ac4bb082a1dbc7ce5264872f94a22b46eb7dd64b6f5f75132f816d5177af5ca0f6f98743d5a15e6a9995019f803dcfbc23402d16e40de8459f79aa071f6cdd85f5123115b6bb76d9e91b07ac72a73c2642c344874a6bf0397e22ce98dba77d2d16cb10cdf10fe29625bcbe2a52449d75331b0952d7275348a35792f7a110430c8abb979f38ca31fe332cfe058a2d300253033137c9eb8652d956621c9c455b97893c68b2266694f2ce27d1f15de805752f97449504b21165b3fb9e182af5bec294f8ab9f0fea611107c3e310335bc72e2148eae2e1deecca7f229db22e04c916caeef5d39f23d7a4dee52e26578a4b175aee8f8b877cb6518cbe620a521b4f8fced100f4e1cc9afeaefd666202231b76cdb86973ee7225d062f0d657611e3331f3fa40fd4c53d837471310a2ebf990e62a31402790e36d9d8f177f2dbe533fb6aea50d44954ea1710d349e0bab7e7066dcc530f9067fddd9c3c05a8da941c7246d2e0bfc987475e314b44b7e987d8f9940b8658cfda3648cfda0e46e78b1727bbd570127e2b329f6a63562b25336eb6f8e2a23d6666708fefb985822a921d550bb9f7d3b707be9e4cac393ab3bf0ad440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109ae552855225ee73d39be22e2102f2d95f428d12cb699eee3133ddec7b0d1efa42c9f402d840871a2ef6cb531072849e6720200ae8a36cb25bcbadf252c698cb9edc88104adc0901285118658f2c0000050aae42436c1fd34300065860ef234f81c7c5cf8cf13e063aa1152389a76820604a2cb864d2ec041ad5f8b6c871c3c664219a7855a3b1906e55bee55048d3fc7239b5924603caab326780e9e84f59c27ffa7ca0072eb63ac8d22e808b6405a477ad69356c3152dca8d933bc6389a689aa800c1d10440a94916024a1ef04d82d62a502f824879ab6ded4c5a4df948e2c32c64e9a328c8b36facc71b5429be4d1d99d06eeb56a86658802e9520038a150753e2ee009d3640a301dd1aa4e7449385fb1579bfe9809262457db455d31be7b77208c61da45a33789372fd029e9d5656b7bb6562aa8d8a964c0c529542b1b215d8f0b6288ed767c63a0544b5b6c4d820546ef70951a8401192ccb95041692c4c8b55f524adb341343b88d1c5bb60088ba80d26b77e16164963d805a10623d216a43ac2002621dc2c2154c6a1f556d145999bd894872cb120aab5b4dd1a655120a1dec12f26228be93de0431b3a7a93ac1e970df87a87a254e709184da1a8447d3b0928d17aec22b87ef5c2ce4a8cb529bfc4b4dfa800b830868cd902198c3d302b46aa29c487cb808e43323aa1d3ef00b98dadb9e0a692cc62bdc8505d4a310588377a8f6badb88a7d50bb991d500a331b12822e465685a5209de53604d0477f91d7bf4d1435e44d2a93b093f117dacc093914221a6f3505dc4b241da4021ca65b37681362666265b82f23ef1305faaa238a5496598230920c6b7035bd926d438666f10437502a655bf14857db9ef2b76e436b364b1cb362fb89b8051c1adc7796f8606b7985f92812afd40694b8d8aea57da5725c7155df8802525932d58bb3bc28db7b6a93606fdeacb0b242b6be2c16a5685a7c4509cb5229161b2e14d4228a1832318a39d3b2aa473219a7a7774e13a7293e984eaacb330a154a8fa845963c8090dcac8d37cea6b03bccdc903c0406ca2e646642dfb6e9ac941390bdb478171a0ef298ead5ce9cab149853519dd9b26d88e037dcf21adc3859f218435c25fddb3692c085705d9b11dadf8d965c8367938041657ac6d3911a50c5bee85ce39b811434227528e71859dc8527e3d474c97934e36089675cca4aa8999192a28c3b27adb114c005cba25df46dbe26c70b29c426bad33bcd2c80bf2e7ef3b99bbf00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000039cc83441b16b39bd7993766e7260d07751af2f19a41e70689b0eeed0c118d9ef109866aaef31b2d2962a25a3d1ca999214cdf0eb54598382eead64435b7122d275ea8879bd47b41eb64ea908867fd78ecfbe8e992a2636aa7477de5058179565d3a2ceb8ace5c0302018043c411d89975a64927b48cb622a13f1ed85cc1113897a68488161afa1e636ec786a0aa37b928ba88a50164a9ec372523aa9ec8885aa9c95b29f7ca1bbf0652bac195ba94e976d336b69a9f5346b4c7c81457f802dc9757c7a2435a617317340f764c1a2ae131a716318f00af0efa89d3b57d8f31e155598b3944d950d6a1d6485b509358efb3745b95edc30dcff02574f54dfb2d31b259d132d18897df868115679f06d41102cd4eed4ea290f711148b99b647b8555a4c0dca1d2d0871c59ab1382a2d6417e6236d71e2bfa1a75cda54f93e6c087d611878ac7670a04fd7d8cb0993f456e3bc1c3b5898076e22d2d9e0eebc7d7bb8d142bd2b5f6fa42b40bf676fb69c532d7520a4a105ef0c1337f53d6e9b4ba17f1e76af4cfdf08f794752d2bf71e8777e2a209f8891b1a53d7bf2a5786b00b9a0cd0fce79408f26befa2535be188a68201b1514074cd70660971f86e8d3e92790ae7ac591aa7a996149bcdf060c615209ffab82e6000f41b2a5606fdaf4cd08cab0c2f1103b2436b1fd7dec477c6233fbca3b07a0ca01bf3476bfe5334e32aaa2ed35d5747d673e7bb622e1aa7901c77f28a3ab2197c8b8253a1d28c969eee73d17ad71c7919e7f217ba2badbd1ebf986cfe981024fc347028c1109cd4204c7d53535a9b677e39a43193e054d0fd68104d88934dc7ba6cb3e942aec744b935cdcfeef4221784f96798e650ffb0febf2715d75339d0cb6c2e57c1e9d10f13e6786b7f041ab307b8cfa51a2f10b622995230fba54b70d94ae278ec224d9d0950ba97beba7eeb0e2fbc4093e548d9ec09ca1a08e5f0483024d7c1927ff8dc270900d42d31b81b13a29839bd746cbb3591bc33817741a31dea308f549a74f3a4e5478844183b8d7363ac1f4d4a5e907d9ed98afd08fb8baa84c324563495387a4f12c239fb63f0810447131311b2d2ca302c7da2da57c94c3b5e844f537886fb766ec0e977254dbca8fc84ad77430428f0692e55d8e2cab294b857ab51a2ce4a725433df28d9caba86c770743ad987bba58c0565bd18590931e283292889294b607a5f19d9e905aa3940836e2a74a2e94ff3062e85a5c6c978b5eb2b254bbcde128280e6cf02c11a0c2066f349e3c6c083965d5b8a9c000e15ff36c5bf3a6d4200000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 27&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000029339489320464ea8b179bd13b771054c23fc6c06602416c8b5dad336b62da10c42e1cc87d7210b94f88ab2c4d5262488974475f9e3c91832f4bfd9b49569e369253d69bc5417350308cb3429711ff077ecefaa35076a1eb8a42e3280b38ec2458c8ea59204a7874671e62f8b8772ff5ee2d2f46e1cc3bafe76cba1d0c2a6b9066acdda252d82fec52459a3df59b0d1b957a7e27b5a75d9aa94ff556deee722bc0b77260fca29299b6bba4539fc39c57999de4cb28a4d22e551d95b76af9373032ca8f9252328792fd4398c3eda8e97469dea9e38ed5ff7e1ad97efec33f902894eda15d3534584aeef5d19e798e6c84a7189be61f76c73c5159c2fe21e86c9c9005dbb56822e8557d8e91ef4c921446987214aebb65677264fecaf2b451292d4103670e4dd2d390afc61922704a228c9259d98f421c1825076d61f6983fec04f95e9564760472204e2b7aff6c4727509d5112aa510f91e33515bc698fcea819d8b4b64e9af3b98db44712540c2ad6f5e312069995caa07a4e3a61419fe5b81886cc8b1de279ac579af221bf6f92f7917da6bafb66c047edb1463130e07ad95aaa3eba0b2a4e9d4f9cfecdbef3324266afc6de9e31ad2b4aa4aa5b263e9c8b10dc79a21df495076e9a5da13e4c187f24a79cc524abffae72efeb6d28453f51819ca54dda776fdeee6c6c867a1c6dd5e2412b3dd593d39b7b16a71da56a48539afca8aba2c5167111b600b6d5b185ccdeeb549daa98d3bc773fa4f47398a092254f47ff1ed7b26e9787031e83b61c688585941ed4355d816923f883bd909340626eef02f28bc906431787c115575335dcb4c5959bed276d81ed6165bb448f0917c9e80c225c8b1886b16586b418c46b7a8c1fd8c3a0ba6858452d9ecbd938533f7237d6ece0b7db22bf3b78e0155d2ba0c232895c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003810946851f2593af933346e227da5b194c643bb1a19dbc41482229668309373c369518deb646b8a940d5d7f3a9653d941ca38a64c4f90bdbdd313a397ff6b4d7e856b61d5829dd7e1ab2db01c384e3a261f6a88858c1ad9e31f5ea535ebb52c059ca85bf73468222dcde6b9c5e7bd255d3c730b5d61aee277f27e5c8c59f65752f744ff21b12ad325638f41f4621a7259556d6824861384e3bb6401ca5358ca1d312680b0d2f80388bb26c00ab0008515738f6bf11c913f07e803b0615a4712cf8aa743acf6e073e12e23411ca6435eeb60614106d7a3ca308cda71dfc5639318fde671da47a57e3af049a4dc71826af379a2bf33ea8f44894c7a61f56549e5ec3e761e1bf4d44970270a9273bed3fa969c40b3470383754a3013af4add24f960956e837608f48e7066d1b34f9188b7191fda1abab78a81d5c2a6153df432c437253dff62d50e3b05e6bd00c6d34f5a1561a7d6d796aeb950f53803ee750d3a3882c5057749e1dab118dda3bd3743db9a305b1c01f0d953c008fd687a1f21c9be124d21d9de9134ea7d29da03f13f14075182a9d54434f00b44ee979311212840ef0f92059bd5c7949116961cd8962c71410977d48c28965da442a470604561ada652830aebae44528919265592068d03e5d19e516c3d9ab4c3623dda510ac8663c1d3af63535630f0624e7b38255d909fedb9b8ec3de1ed9235ac10c9d349dc6ca60d238ba9150e30cd5452c8cb4f59e49093740dde4a60973655a42604a2d064208ed97dd93f699e166066c0dce3339cfd5226dfea15e7c7443d08b5e5e45672653d89ea003b8b819a0537c11e8904f00b58e72029556d2b1dcffe67ca763879527e13ec960a8c23d216b90c36e96e623bccca7a20a7833ffd70d7dc50b038b89e7968606c5608e8062445ebb7a926e9c7ccbea432fb3623c8b4a7a675f05c833996b0d8b081902a99e281625798be81a290fac1011e56286893869f9b5fb40204645ce852787cba9a1ef89f026502ce2fa4b7aeba563b95cca136b5a05389ea4926690b7ecfa5b31204a4c124dd5f61eb63d7268246c651920bdf2455fd7d31950f278e163154291b79b6c93ad261efa0381ea980dd4efb5f8406d62c508a77d9be5b8799a598584cc9df588a598c4b97cfc63579967639f6d0c20b5866eb1d5b593d46ca363de17287498e3179ea16b43eab381d46f8b98575640215f4272158156e6bcd01c1dad878c809459510069e60dc817ae965609c06b1acbe15b2691d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003bd86d27c1fcdb8164f8909073f590d0a280e5ef193b0c42863ba518bc8a51e625658dbe2184c3353faeb674c991eed3f1b0fe3bbe50a21ec70e9f57b97c38d6e436d3dd577d7056b07a401ff0ebbbefaf8212b993a39281190e309ed0c50b269e4852dea85432a5941269fdf63766b21d25d8816de5e87ffa051009d232d6b258c5f43f45f2d48be09b2ccd8fc963fad81fb368502057afa7c865d62d932f652802a299295b29411439dcf832e8367a749b4d7adf7e8abde3ebfb844a9b1d32f77b2bf96b5d29fc15dae83ea80a990aef6590776ce1cb81587ada80b9a7b45aca3bbc54dbe67df090104fa196701280b97607a333a9b56a728710cc1cbb7569b79ff034572495181a92d2380a7ee5e9cd1b0f758c2bfbcc4e11464f1cc7d91f117319c30ccbf4c11e60b5dec724225b8d77b71aa58f5fbd498a3f49115687d58393be648805ba1737bb921a08d738243920c3834f8782a8256b7dd22ccd5f4ece86b8a0860bff21c5c8f0be987f2d510ed4df9cf94bf698680b7cfa22a575a3d1b5b431734b59a4b31913019c1f42dcb76a9ff32bfbc6e16d2fade26e3c17bae49cc415e4b370d1fb43ff652be62d18b0affdf286765f4f30fc8d6f2c4a58cd17b3bdfa013bb2daa075be5f522ef9bfc2e1506cc1c4d381b3342edc19c955a5fe48a712af5ace66a028d03fc859711c9d33231e48d41e58a2c2ad81da77529ad5e6b73e1ac96f0c8e53f153faea7903f917492a1d2b1203174a08551ff0f9f91e32bd0f31d606c80a505d5eb55265542db3653c2621e7eb3fd677f49534f261205f834eef1645af419ef6be5cfc16d54c7eeea12d2eb9458831f77fa558e4d5c7fe446ddaac3e1d502c941c95f572ad545ecc7cad21f0dd50845cbdedf589505fd34cd8c00d57243c3aa3615d84c39b0a72c28f40ac72da25ebc6987df5a7e390399463786e75d524ffb6c961bbc9301264bfe3c699101d18ada4a72d193971d54089e6fffa684cd3d77570ce0bb9179a156d3e2dcf266358499bfc158ac9a6913f622ca861c968ebba0a59a12674bfe39389a2125a02563b082259483e80c89a3763c0a9c3db485aebf22c844539edaa28a3fbc0053eec475679b741d9afc16b5fa109399fdd1fc3574df8a1292b8d7401aac1be452d38f97d531813369ee4c50f36736b95ae9c3e4f91ae85e2d664337daa40f75cced2f4a4d210bb4ee25a56dc217dd176db5aca43c002afd63ed8712d89e266674d9736fe4a9f202a81d177970411dccd289b25798272d2647ce6451906a4f7d46e87a46cf6cd048b6bdb62488a24f48d1ebd61ffa474321b929e0a7b6f9d0f6d777acc14815f343e1000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 28&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000029139b5ba7b60079daf1ba5a00cda43cd554b77ce43d9d4885b0b9e7561ca1741227d47ae62242d2b951a8e67b0714461be74139693b2adea9b6653fac921dc46ad1eeb5397e87ce1bce4fa36a907ed115d7274daa6616caf3f7d06c3f9ffe034f12abd9ac3f8e2321a4d5ab10e8558104d8ba781db11b41790422f344cae93cedce159d8ee3dc83b354803492faa68fe9e15f2d3d04c0d062067348859706b5803bd681e8a0a79db5117ed7add5bcb11f2dd86c41b49dd9fcd5ed6785d3943bcb949909bdf93957b48d162d471ff72892a8727882cd4ce14d1e48fbdd44d1a71b362505ed5610012f492019d9db4a7ea0b297bd5d688c20fcec21482a3ca4c3b8aa1ddd02e42bbaf4e1e41dd9728cf0c09cb49d06f12356cca37c63a144def14474d6cbbea9699aaef8397e213787280e538b97c7c591b952578276e449bf1de6e7aa47fb228efab148814231bca8e90387fa779f18149abe7235ebb469894191e925bb1e882c1a4d0dc22ed517676e39afa776dbaaa6906c69aac21506c7ba2b0c079c2b1efd36a09bc530f6b337345b3d91c3d9345ecb07c6a48e2d833234e5e57732c9f5698b82441f3d07e212ac4154925bed83519a014a8015d74dbb8dda9774ea3d58d951a46c93766a6930c2055c7775544e14409da5a847f367c09c6e15657382ce993c240db963ffd8c299ec7a34dcb658efe6d6a788a0e3e628a1a5b9205d953bc388f84208514fdc1d365dc5a091f25fe86d1464061630fe88c08dc5f508a94bda1acbff64f2f15f0c17d60b50edc4718ead7ba98f6f6423d178449913cf03cec708bac1563928e6d574c1ed9a36a94e3c1822b7f56ba63b5d7671489421d97663d4ec27f657869383b2c78d342fe64ca30ca5b58e59ec7638771ca8bc1d025af69077c2a3f73857eff691e680000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381094c22565a9ad9cfa0b93be14391a241559b03ff8bfb54b007484e5065638a4092d090e203815a51ab5d2614698cc8942ac693355a9aa8d34b37d42d57332a2320943676aa47b456c9ed35e5a68e1456edaa9a2422244a6c0a5490d0ac1dfc700feb870518772b449849196cfdc64a4bebbe6cbf0158e84abb513378248cae12c1976922ef0b6ac414d97d16825d0e02d4c14d625d9d0090d62e13508d18f21c1a9736982df0f266e3b4e465d3496569bec5e346f9c6a52b357e25f8df839f6e3af003a427a9a234a90dc3a084d2a0a828d65a44d6ebc209146d9de20f14df1fad5dcc94a6c50eed2ab022ba9899696528b626ac84f688952d84bccb1f106567e58dd468a9a1db62a2492650012aeb5b5c1267c20f2394da5a88a49580fb5da879846cf591dd0054855d617145916d207079195b620f38bd87da84060120c3b567ca925b488205c89d48b5849347fe0eec48326fc926d064bae1f96afc55bd84881020304a85096cee63cea82c79deedf823eb0327ae9707aad60a1ebd6d0b271bcfb109cfe57e968559499f2436079309aab1d7b69262bfede22bb7deac232cee72e406e472d29968f7cbef22c2c2ba759d359d393e56bfc6851d0284a5ef126a229639fb52168a0b18d906d6426a45d4ed269322be6b12e642b00ae6bd5df40ba394db03c414f17fc36a81eafdea089340b7cedb42a418b0bdc5c065cd2a5b832d41d9ad8bcd90313ad241283a9209bb7b3393b111ce8a40e7c4fb68d5591a802669ac895db467d25d8f0da7584b4dba9c8acc0b1d83cf665cf6b03c43a6697999701ccc327476320b1e49f16421f3c8896f2b225eef59af0707ad2692394b6125a828112a7704b4b2206ec8b524bd0b2081d04bd6c211b514a009cf0e34284a006bae44b98e68aa7646619d49b838b19d9aba21919bcf19c50e3cfde3dc12131a8e435198d7060b3e9ef4fc1a8b7ddd97ca77173a2de081db232b6f62218201af0b232ef90598ae99257709c4443bd5933cf8eac32285215014ae3502af68b52cccc4dda13830be2f20c26abaa8f97af22f53572c340181d403d5290abda684d48436d9c4b6d2922cabf2d8e684188d94b25539bbe6853a362ac890e9518b4ee6b46fe72c230eda281a8f285565d379b7c553ae214debef17da1a9660e8cc13b019eca87be154c813ae82b9eeee6982f1cf39f699bda514d333c8ef7d77c2e691e1065c2fd4eb82b6ed8d15b4851a642dc8be1e4e43ac64e50dd1564b7dab7c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003de56ed7708f98432fbc623424c2a3634780470a01784becff01bea5ba192d02c33675084263c4315420a009579ef80dd15eccbb812652421872a9577ef7d07896a727a64141bae7173426dd5a3925159bfa927ff1039e70f729847b48365b4d3551476206aa049ba5ae8f605847aa03965f058fcfd478961ebeed06530abe900042321059c297dacfe76cc12d52311b2ff8ee1231c77049e232d9fdb751fb27eb7eb6a373b4b1c06bd0ff46b1b208072c873e6f938e689839079e48c6d18f678769f5f28a903467f2ff2a8b02cb19df675a8fc7560a7d38a918ab8be083ec4e0ea148517ab90f38394833304f245bffc47f9eca771fb80b9c71ccd05fc3b0d66eb06d24b914b63d9f16ad2f2bc454b591d01ecfc527277ae71e3dc683161a53f129743f3428fb82a89dbd5d42f3eed237cd2f8d76de2e56a2143ac6b2ba811f745cc72132028eecd4412b76fdd87a2e396adce72dc69b8fe053042e798b220974587af96ba419da6888b13ffe217c9d01434347f4162fd554b760883e8eb1aee46c4c26b990c6ba10d2d939f513bf0eecade8b5deb8de2bc8c8894aca51e65aa696e390c11689f1c2cfbb70bc5f72c1872d99babe8de8fe2dbb446a8129af0ab8d9613f0cbf3cfa6ea3cc409f4a97581d5012707756994b6c8d4fe7f64e0f0b85a85d0a5fe23224dfd7abeba8e3fb2e97ad87fa8dd477adf48f64faf486d0df11ae9c3bd3a04abc962c5b02cda02d48f0b52d84d4920c116c22455df291a96e6adff91e3cd35cb8b5b4e70e3da8b87cdc969643a32b1f97131c5e0bae7f6dfbfac32218eaa596d444574ee85ef7c9998dc1088e5813d50a4377d29506817e4234f68b32ad68e00adbf6462f8d4e215f15a19dfde452f0a65360f7c1f20e11c42eec55565ccb23ce248bd62e9dbe8a7d6639028a92b422ab444c5688b5d191a4ba8956f358d131e2ff6dfc607accc5d31af9678f1a226530078ff9a73d681deb697670ddc3e9096ab0fedab664473dcffedf9be62a5c7c54fa2eb5059e9a1d38413b1a4fe6d531b799453bc7185abaf78cabcf65f365b00827cec5f29c4737047e3b2932a78757e9626a958486d1740ecf1ec17a01aae6adec5104eb934f432207ce31d7096acb3a0fe2f5dd7890c021892fe7d3f34596cf20b6b12fd55911acb46d7386f99a9e9ee067a45c6a1fbb463e63d69cb582da6ebd6330f4f80a1fa72f2ed24ce9bbcd967118cfc7e21f6bfb68a905f532bcf8b8befa03295d362b41d25cdccfc9b41767858f651bc56ab2bb4a8675513c5d6f1c943a20a27dd29f941ad141debaad219e056510bc984063fa0f389090d434157438bb1759690c453a2f55f72c033797a4b0c534ea2ea084b3b6f8966ac56b106fcc11ef08902f2ed0000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 29&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028d39e6cd3fa7e7e09b93000e06907c4ae1064148b82f3a467c01431a8d689cf7fd2760b85d27520e2b41d08423f3b27c70a993782b97eface24802f3448210ba2f865629d26608fb198e6275cbd89c29250503189f2e2e21861b355104e5b08ca4ea590086cb7a7d0d6493b526bfb3d63c494d84a65c945521d893644e57fe67553db48d3155c912213063fd5d3c7be362d4742f556ec6177f208145113e1bc348551bbf621a5be7e6a311097474f585d8c9b42461ed4c27861af281ee7d53a72535849f51008e4b4e9e8a3a68132c7cd73ec0348f4b5b4dd6e38d6cce6134819d6b869b2058ed9be8eae47cf219e20aa5f41c96490bebd628d9a701db97ee6317ed3ec8e432bbe30da6811a5fe20828f19922132eb1c3a1ebc5adbbd5d6b1c9e105facbeced43cecb52657a8c4aa33dc0be7cabde99c65c9b164d1b4bf88827ee6f0292dae893bc5c5c8c610631121b26c172bcd113623698eab59abddd10ffe0bcf88d125c6714362e6a630c2a6b0a43b37b572fb765f6dc7ff06f2c13e28a932722ccc63329c70f5982312d7f6f0ebdd2f3b75d1a272aeeeda36ca9e644bc79f4d39b47627e8c2ac9e75bdd9f3d1724af6c54d844cb34d95bfa5e3bd4e9b18b78e4d6e941b44be7673a0dae6d86b5a84ca1183f3b0590c97f3eea4a3e9545238ab20bccd32fc63afbccb9d318c5b114acb05026f2514840d7357ae4fb3383a9da9ed9620a53c7754fa8adc722453841515807534581c6a4ebbbeb3aecdbf4090f559070e0bb753ed6d47b63c5de7289de1953e6dd58db744af31ede53d8c88316344ebf7d1e62a37c754b6f3044f9487a46525896dbc904bef437adaf71d4b42b0c0eedc14bdcafc1eec9c7d627e2290397ec50b388f1b329975d28f24d74e6f4d2f03233d2c7105ba25babfc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381099b51c80124dfdc38dd3ba9db5f74653deab8598994a89d41228d2ebfa982cbc834a90283e96223528d7b585d77615c2c2dbac0fea0b945cb7f543b0340e85390714892c9d816a21185f09da28d2d0cc924e09b756be94ca73e8488aa79827b0e698037a067ab9096f7885838b5786ed792f23559ca563e963604f3ad29660d7d659a7f2b4b8605ff51ab589752f1be127fd50757d83fd5a00460bc1c99eb64cc141219ff0a821ad65c00ce199cdb24a7106c62c5c2463af1d8d6c5d49b47d697a22162c25e5483820a5ec3ba82e38abd8dfa69fcef9ab6c0d09125f197ee8682708546285d52c4759ea5f37c58a6098e67d5fdd36430727033e821eb8508e58601955fae4ac50a32ec7b1cd884d999a73137e2d16801e52a7ee88cb2a08facbd0d2e02fb6065647886c768695c7b11a169525b958b74ebe233943c9a2c61eb9503ffa4da46704fccdcab66adc40753e22b55e5848b154d4534d3bb5ce37fbb3c6d55690336a32869198a87d9236e9b54e4a09594b1a3f176214aa9b48d52b4d585b68d0a0b990011aeae9c73a950da77b25065b0c1915f5db4116e09be7e5c8774cfce821fc066960fc5fa57f8efe72cdfbf07bde8a6c62b7da0326c7372d1a080c041610b24216d4ad715eaca9708209321591a785fda386591dea20b3ebd15cc643db8d0666241c56f84c63de3fdad569d651aa88d550fb66a51c6670dae05220ca3c223b413e84509fd16fd8bb87d186d09ce701e2b416fa6cf9d6e369a1b6c0194fa059be0d989551072b561caed1db6978361016828ddb0e65e633664e6d097b58d837f49d7fb11c3cda52a35919410d167596b6609c8c303d95d08ef6ff98aaccbfa1dc22e5ff5d3037d8ce52a5e3bc91f64ff02f63c788627884a31fe1a3d2dbd662e64f59356ca6a60b1692a639294de1217e5ab5a79d6d3f84b084d797ee455ed0ed55f1485835e04bf89b4ed7bd8207d07fe0fa55b61a237da47f2a521618c1ce65a254f4e3a95a9021b8555683888c9461a432f55dd225f1d4e09e0ca3a288df88205b4232907d409589b326745525d0de8e596a973bea5479757d76c2926ad1b2499a25bc19fc94ba6d63ab4d5886e8e3b229604f3278c0e5c39983b9d212c40d6663010ece0969c8519e39334082636713d942fbd142e5a632d721e11fba3fd8ded20c269067adbdd8058976b76931d1a7ec84a9a063c9cc2e8846d8a9181d4d2f42a42575b88b0f8cc5bbb8a90b0674f22c3364d30094b8e530000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ffe42c006f144b0b4e188febc82d63d3d37096deec9d3dfc3b421635dddb73c76f6260ff1c53222a50d30b26e2de3d16e3aa64c78604e1191bbc0e2553117a441159b2a35fc8889499a2efbdd2f30b8b4c6cea38eb5b2575926e6f22ab96ddb4b0c5c6d78c3754a1b6deba49ffbcfa7477be9a0f74ec379d1c9aa59247c091611573af765ae698d78152187b291717a9f03fe767bcbb12f52311215579352e7ceaa8654b5403f18ce82e0a73bfd5fec1063b506f44eb1c9c5a03697d03dcb2ae15c5095f292b4bcb130b55c19ab728b3232ef77d1594611573cc6bdaa254f05934a329dc27cfa6cd8c02cb51c3c295c964c40502fe2b1a81a51c866f7c7380bfbe339b39c8f51f73722a05b5d1e9cb6313557b3656863803c9dc99bb1905d7f729b2db8da23d88200032f36ffd04da11ffdf6277acc69c5407289d00fdc3c56b32d54877f4a8dc70abd37ec532b8617d9f3c535b8e962fb389e976b4d1aa12de5c1c2ffacd50acfff65201104648e0c04cf7c1f880e8bda1d68404ba67c4bf64c9d2aceef81b35fabce58645e0f2f61eb4ccfefde7239be408710d349987d849d40b3ad294b9d815a91848f9ed53b69f78d9e955f6d1fd7e38ec291664d54c2bc359fba241ba6abcbf5fc2502d93760d9f6b1f7fb766040e98bdc23a6047134a35327fe128ae24b4c7d0cdcf1801947a1821ddd7424892df50e2dd5c1e2e6c5bfb4467524fb45c7d977604e7e0f1f98eb8c03eee1d9a5796c8a801f082678940f076bf44d3496730c9a640fefce385865899fc33b5dd34d036f2fd5d07fdc0a40fb725e84ce403b46de712b4b44ca8801a1ccf58233c5da06719769823b5945849ddabca56b0b4ef9327c8b5e5a445e6853e5b66b8d590759d6b2db722c22f8c741cf3c6325a76d93f4fde5872d5732fb19aaadeb7c18094727ed43b305b87ae2dbaad67f90feb86498cf65cc57ea635340f27ae5c5cd60ad3c763223af877e65a005c488aa4af9309e1aa02002b01df8865fd481ea254015796985969997a53b06df0355a6ab3c8219b652b09e1f86a6ca12d27c4bcb9e8d35e6889198c8fed71ad5642f5f9f7ce1df270d68aa05467ef9acd9a51347af1ee9ca7c4a5d78189042900c6d561f68d410a77e79726dc123b196c78829f02cae7d0623bfe9e7b0d8bf84033086295992b77acf027489d51bc7ff006a8d4ab8079d494413a565e7f687af40dd18b86aa4274edb8845df114c0146de3199cb55f773a87ffb126b3a4d00d38835cfd2d6652c07f572f39d0397fcd62acf6ed9f3e8951348ae7e52a669fa4e2bfcda548abb1989a1d74a27b73103770290e6ecac87029359354ee4c87a77bcb5ceb10162dd54499905ac8ed442c173cacde068bc546720d1284015acb90ca19147694b53899395dc663d6683908f3cba29ad37f15cd3903c4c7f4bd7300&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 30&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028f39edd2abd40b20f20393d7704593cf791ee9bca0b1246688d9b6211eb46c6c9e87e85b7cf7118e0c94c255bc37c95a0e7c7beafb52c6701b1316d4987416d2aaf491648067d407e682dc326a65f7bcdac5541965d3b4c73d358c7adadb37430ff5e3dd68c850d969e27e3f34445b648fcfd7c9dbfba90413624cf3c66102db52e65a28e204fdb0a646eb864410585523c08d99ec6f5eb43b767acadfc0459119fe2a07bfb3390779a86e2566510132f819ac55dd6b19f77168883f94dbe7d204d9788baa945c5d9dedbe424b0dfe76532af846e76d4b075339d71ac5bd838240199875a57d23b609bf310c7c7e5b5c1b28c46df55914092786c80ceb528d947e54eeb686baa7514ba921821581ddeb2d8eeb0feeabb1544501b4757125266dab57d27e3f12c900ccad3ab62de8c9278fbfde18a41994818bc2307f0f3d6af98963e87ad7fb5b556a4fba0286f9eceb7b2dc8c559b1d6ebc492e56aa04a20391096e7a6f8c6112a4b4b5c314a643d39f8445bc454f1d9866c8eaa75141e01c3d741fc4d91b0a1ad9507635a81127986b2361008675fc718eefaf8da45e8d5e41f56d6088ad430ab65565c97c2d98d41baab689cf71b12f135e815428130936faadd1e469b128dca1256375135dbdc8e0d3db7d9387364e30f413e728c8e799918bfe3176598baa2352c854ad1188d834eca3e3cd90a7b3887fee904a88716f4fca868beedd2379eaa743af4357ad98b8228d7346a5fb776a0d4d9ee6cb6c574c42089fe16a33264f31abc4e65a073940ae53c96a12a5501b1f424b87a2cb23ec454b3683c456ae1d350961c6a77ed4d08fb9d0af1aa2b7f98a36ba7d6ed62d38dd6b6db0b45e3711edd05733937afd24b09e7266b78559a2c5e24cdb32aa4010ab1329bbc8e895162d53f4bc3b61e2800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381092fc8155424abb0325dbd754ec57804c00f7af71f503cec4904e4818417b216f4dd6bcc4a9a9ba1b5c6f84a1912e6f06fd33ba229b792d5d5860e9cb23f657f80aa103871242c88991648dc93f1311a7f7688e4608f2013686859873e6d0210dad3904448aee3e3d40811012417f15ec800b672581aa023a526f4e4ddeace04faf63406ce6718c1af84bf87fca92cd23850daae5ea2a528aaeff240564d0197da3966e10ef390c36d624db4d81dd7f578c6a024ad1c5fb900f5e39d22cf8329c883231390337e3c59209b518294dd39d2a96ea77174a75897446f1d7a5783805bbb21c272a2ec5e39a51535351643474088b55820e701f9d9e01b26ed2cbd3622b9ef631a3de74980aeca0815588b23064433d69f75662e0f1a3ec33397065397c6c6a48f5f4012ae7cb6e6434926586cd9f688eba3aeafb2b4925d0ffe29b8915747b2214cf46ed5b079980279c609f41d99e4e8351b4486d5789936aee5b9520666e2d77a1a79cfbabb10daa5385ec0811f7653cc05513042b56959d3c570dce4ade1ab22718c19927945156393260680ccc516845c53190087fd80e21438cd57446bd671dd88c078553e4ab8d13aed4d5a648c4068b50460bc459ee81e02116361eedbfa16662634759ad5c2579774f1425a19197408d375912d346c4c9dbb746ebf06e15e45b7e9db5ff920245821fa4f213c61980a8e0ff973f46c57b08d09dc5a6c88d9bdb8328560541a047a3e5ad9946e0f76087bdcda3e1c6de131e681132c70db56ca9d5756a5ec70f5491d5471a807330831ad388cb51a48094aecac69bea30b4a5e8850ff87ea78c2781049e05925f81f3bac45280ab4988696cb4a3e3077e664eb9539c5dd71091e18169c8dd83d8d22970958e772d38d14c4ed314fc9ff03a647a36b23768e10df64e8d1bb0cba5bd0ada0016ad015331da96dbe34847b5cd84952622707e2cedc1b48ef16c3414e5a9e26e98c8c2d4c76d5243e26ff016e2b77b31f638f0c85c7cd6c1d847e37933dc01f8a79723aa9ab9b36484f15ad0a6d02a5c012a642cb1a14bee319c1df463a4562b08ce4909e1bc8ef991810ddd5549f971071d6c7c6cc60e8023c63559febdf5c4cf92b47d6d96615c8573382f3184c2ae6426366b4f1d088758e4e6a2ef39313c4638f5a3da0de2c0f612aa653fdc683a9512e1643c61c81da50a7196d1a4f8a78186f01fd3c861083f69b9f10142630d2c4ebb19216317b5dd9adda05ba671d77611a681085a0e70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004209c311ff20f574cd9b7bce1df705ae7dce6e7a621c935a6e57a59eb31fc443ab1e014ad332fa784583260aa6153c464565c4568108d60cc126f6e8ec3bc9120e5659c86cda8a31a7131936de7b3db39a4692808dc3d2bee8a99880ff9d1d5eff1e825a0f043d908d62a99779e013845ac0c21abe8e4df0ee901e4c6beb8bb36b30228b7756d617a8f30c16351d8ff91786f7406f75d9fb648830f88ea4537f42ead62e8790e9cf11f72c31d718221049c9aa35376ad8fb065f4809f4383a23c2b29425836c2dbce4680450896eeadee6b83539adfdf59aa4fce709d601640eb9a22dc3b41108a8ee1fccde9945ebb1d3f676ec8395255e125e62a32149c73451f597e1c32ad979e5be914ffc7c548d6ae92ed08501831e9007770a0233e5778f22adf7f1aaadf9c9a7c82d2f42989bf21627d3ef8bd0377a5be5c9f5a585a246a73de4340e6b43b36db775b34033962646c16f26a2b7179c40a721fea54805b9ec42177b42160b1a67341235b5af9f30b2703bff8cdeee5bd7ce506b0707a69f84225b6e5a92e80edfa235803dbe2cec47cfef0d9fac95c3379816a39f4550bdbfb45609c76d0351ddf8d61724bd5e8be94673b3013eebe172cace247d79925b12b5dba2f6fb72e797b2da849b79dee3db76775f5f1dd4595678671c7b18bb3749fbb0c6a7135d639f16b3864b5a251114de7e9f8cb02b4cc69902ec8d7d544d98e24a05f8accb182e2eb44bde868b077b1fac4726e8b01cdd0d024405665f7adb60a23fdbacf421246354e824cb74dfb35e57902794e459493905400d0a0bad51d8eb94efad55c67cd0c7cefe7a1b055f06371aec7f490fa685c611d553d8430992ee7b1855a9cb305b5ce53154345d7def6110ddbdb5cb59559eb664c6439e057dc022f8686f2aa0ca81552428437b0ceb5fbb5df254036bd2bae7290d947c963046771a39d2656312236569e775e7d2a041b7eeccec99c1b9d2757c7370e474012ae707ae00ac37b73ed9c8e1a2774e54baceb42e8b31bea734463cc15576bd4f7a33430b1987d62e47473391938312f2481838f286c4dfaf701ecbc6eab1a9f074c1f8d8963457dfaac9a9a8eea70c50ce70d1ba1006760ad3887605ec38861dc1a777d21e46ea169537057cdfe256cc08699d73b1ac4fbc62f863353581cad358b9c573d77585df6544e5d55048d66a352828cd1adf5f42310ffac022a25824430f741371027b2dc14717dc87342a74f0038674187e478d8eceffc16474a4aa8bda0c8d41962ef2a4b64a036c888ccf4ea628e1cb9ee0f9a918fb1b22b9367feeee0218c83cc7e27c5cb2ac64dc7e111e3c85ca0e6bd4f685e5ddd428e028d192142ccee3f0c8337bdf43ce4b62704aa53c703ec334fb56ffdfb81d7d4419535d17e5fcc0e6f558ad82149c591fe0357da15660f61544b4041128218b6de2b75d3801510669a3977e2983bcaf957ee2942e504c29890a81542ea208e1cec&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 31&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000002913986734218879d5a676e906d60725dd48becb9fb270dffe982b44c0e20bb46cdc8032a9c81c0e39cf4468a933824738f9185fababe4814112e3b3ca47bc1cdebdfb6b37c353d91701b4c921de7f598ae476ef50cb15dcc2c3bb7b7df9c9a4a70882c7ff30d528679fef4d85163c6a9712e5a179217fa516ca81841a687b2f1ae0ed8d591571309ae641dee6a026b70cd90f2cb14351f72c3559d1673bba036e8b64ccc790ce36aa2313226f0bfe11757f3dbdaf2edb4347e84be6cd3a09f11334dbd1ac6efaff0c9619265339ea04f7fb3ed0d031bc941060df534c8b31e79f74fcb3aa5b58588f8e4302db65690c14992a43e87ea44a6aee23ad63391e6fe6de8c2cbe9f6f8caac85d0aae47aacc1cdb2c305c66210530ecb16e5e78f48ed3cd2fa8f69bddce67d163bae5cced89a3283c18527983d5255896adfbe6d622c94b3b32a1c51538283a19cc9739b8419f663d0064d01d0dcd1c7651a29e5212ac672d9d77ea1c243501723afabadd1c8867fc91396c851c91a5ad0c04d7087e619624257fd3788ddd2a3e05eb80c27b3cba925bd3620c9bba9dc31dc39917f3b3c9ca23036a1b9d02ece4379548819a749037a27d37f1a706d23b9b69fb32757ceedfe854df2c218422a4de7be8b2e365aa8e8a1b799d5d95d40dc5ce1d3b10d8acd824a39e789e0f4f539a461045150e732dba2a44dd1ac83b04a2fbaaf23ec812ecd25b61d2b6b2ef8282f0c6df831fe0af19b77d4dba42d4886275b0be42f73cc8d9ba99c3bd76689ea372dfe6a5e30f3911f818cf5c2daae4e58073e5d8e83c559b9132ea74c64fcde4c70badc1c14d1eecfb75f06191dcf4abba5da00e3286abeea1aca746e0ac4b4f3e790c2ecd8694d24dcd5b48b8300a89db5c26c4f9082b4a9f374dc4a8c30c84d599668bde7080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381092c7504e654e94f1301733554cae3b351480ae99a556266091aa6a94538c28bebb58da27fc659f15e4eb9a756f986d08b186081c5e40769a82bec41517feceea8a06ee40fa1aa6604cfe55e025e68eea241994ec313fd83b56095f459e0bd2b8fd236b2ea50557550ff06fc5489248361b0edce30f762b0a0dd137b6f963aabddf69549992db0fad74b0e28a19f85c59be3266c76eefe9855ee54993c4ca06092185a4db5a57d29bf97b811e6b52e3c6bc5f1a5a906178c14caf632a6b5b4965a886a09b63051f9da2f49deaad93fb7c3d75f77725e049a95078e4c2c925f8d3765a9c009704704a9f27969e5c6635a081544f99884b345b5aae39975a834bc9743eec73eb5625a9e92648d96631569ac586852bcd8ca9c404365ef725594d77a8896600d46b40da2cce7951dc4008de7a0594b6090108ed5b9c79979f46f8ae6082aba5d2d347e229933c89883afd83f3589b03995d6a9931553189853c6b3200f8a2ac49cb93605e133d8b0510c1ae9a806bc09dc5fa291d2931b1ec2bb668ffe3a6c34a2ec89b34c46f3a1688aec80590308088e5653e9112b4364b16e2e4a06b9641d15f5d9c1e5a2999e9a245a3198d44a1483453f9be87eb148268821d9a760c1e7d9ed7f2fca655b16084949ec76629ad8e9015d7b56b25b32b86c0396c5da11bd6cd92adb55df8f0dd1a58cdbeb58320d71dca512994d83a138691e171ae0144324ce74029074dd1d0e8f5a3020ea0c00111c6b6ac3ae284d7a1ff1e25a7f243c4981174bc5027a3d582ea399adbdcaa879862f47452d1ae3c3dd6056475ac929eb5e5611e7600d75acc119f0d067cd476834b2859a959cc4211a312d4561d2b15529ab4894558d44f22768b05ee4164c62c70a36b1d4612eed6b8959a54bdddf868a6131955138ad29f932cbec17b74d3e779122501d541cc0418b0485da1307f2de748c582641faab6929394fc28d2d132b2a1fc54d4ce3a7ca1381e1c7942bdd4757b9a0f6165e26a9a9d4ec587e1ea40ce2e8b982ae6025afa147ddeb4619c507a9ec805074e4089d7203c5fcaf450e01a27bb21a3e8c8273a5caedd7435066c5b919df6766be779fc54712ec725107267a382545e08a0e6a079c6d11a50dec70b24c45d6503d6bc13947bd6a3239a6112b210a4994453cc501535c20a908c78f0b247139a92533e20f7cfeabcb0d13173fca1c7b7683f59762d8e08ec182b5a5ef40686e8774918cc0ffdf8a3d716111ec69cb2ce623774aaae70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004417ff38725f35312d75e58845fbc33e112dd95d5c1cf78119cb413ac839377c7051bf5f17add1484f5ee12f42b0587ab41df487ba5e4d8836777b614a9931a5fefdc4ac451662b342d675c940061c4ff01f747b69cff585fc5317636e2a830140c0007f73c76fcab96195c86db98e5e65c733825db0325407e5bb059490f2e9133f9b4aa328976256eaaed2fbc59d00288d4830d99731a3aef36e5bf5239f2899c500f942b80b00c3b33307450ff0c105bedb7df84231c5d24c3c3475ae2f46336582de93aadbfd385c824f21362c19b1c6a75f56b69297fb3084b6164204e2348cb1d7cd3ab494bfa7ec8fe346251c874085f803bd7f4dde1995f0d3d17033c461d06b49ecceee0d5312c3a435af5bec9808acc524599668aacd95ecea7ef07c4ca3fab1cf964fdba987c345046e6507ac3d372bf07d72cab816ba627c2bd452ab8dc3044a7f0a01d8c0ea47904a5dd66c6b7ef9130d628a4f2cea5a0d05aeab7daf2729c1041fbdb3c2d17bd66ae293c03e77a0837419471c29691edfb20cf69bc6260975089aa437628f140a44fa2e2967357ac1bf1345e4208c33cffede6cd634b371e7745143ff848f77e5130d1e0f51868585509f9cd3b906ee0a5072ca2e908d6765c74d9b5c35b6ba784a3ea59d808acbb1c24d6c088ca6c9e17bceb18337a4da0c1daeb5d51efb35712a475d6c5a2ea51e93fd79f7deb127f3418f354df06489e10b42bc1f20651660caea17f67f306f48e15db7e67a1b56578ba7be6c229fed9567e128d48551e6eefa17af5b95a716555571f44fbc41ab29208db7c1846e130866d5c9be6f73e601c55610dfd0f67d98933d252059daa1dec20ae0e5bed6568a6322322d8a40e6835fa66e317733e1b465434532eea8fa76886b600e06efc1da41f8dcec0a5e8ba8419f0b7879cc0a93bd14d99608b5bea931d8971da8d2d89053e1de40209e257e741bef48c17fa15467f1312a368d4a061bfc76c2b7bbd900b4a34da51b7cb5bd6e2fb08806a53c0d60273167d822fb6982785f2c3b0ec7d893b615724d0193928d0ea8ea2a1dec5abdcaa904c754cb7747449e87221b3d86bd5df26e11da753e768a8b481c306e485ec91074377dfc68be74a444906e420c2d8bccd84be13aa5ccd11115b669c89e9c0ce374bc4059c696e5f8344fee467ac8c8ade37daf614992914c763d971327b60946943847fb6b82672cc376b780953b6f4433df69ac61e110fbf1a35f6272561193d8652ebce3291333fdd4d84b9cfbc60a57e1f8b817e84ea15d440d4a4b4f7e19c08ddfc5949fe8cbddcd0296a62f12f53d48b1288b80e24c756fc38e2fae9c7a3315d1c6da42ae838afbbf5569f633a68289eb7073babcb210f4e08856fa65057bfabc70ad3b58c2c870dfb5e1b0d11b6fa6d5bbb68285d8f9c21bd89669781c9f4dc32eb1ef58b80b1d371334d36fa66a2b3dd4b3e4dedba7aa9fb7e0245f5fdbb66cda653c5232a131ec1f0c21db1c47b990a64a24dc8c4da951f419f57c03ff506e0147c22e9946100000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 32&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028c39d7986b401570e9f4bb9eec15430f66acef2c75e41dba700df6d2d192757696589b40df7939164d6f38fce5b3ac4af3b167691ead5efe7d53d0f5acebe4b5255069cbdb094a8841f890f7fb87fa80b7922be2bb9261ab0cbb9a4832adc2030221c7fdd1c1de61b47ecd2ae12ce354d06e14119b45eeeff5cf10593f52b108bc7a3e28c7495149665286d3d9ebb55111a24c49ec54ce3d09ae2cf35bac2733b2e5f3f0540b961e49b4cc4e928dae6ba0ae2ec944be7fb340d1561358c1331174e75f6e57a42bd48a255deedc2f6f34babc942e58a8230491242a92e7a4d82547be3a9b35559d9a4fbc9aa5ab73126c2986a6ecfc402252888e6f0f40813b7cd70dfe90f3ebbb55423ac1957d442464379fc9b576245fdf8bfc1a502c08c60674869df4c9fb82d76524db883a3672de91cb3f520bf2a1bf8ad8907306b2df7c100b7d30424f536558b4566b68f430e61b58430336d8a1694c5e0549b2c2b11ef83a19c053610d443976c34e649fb2424715fb628b95d7307bc38092a1f23590d8290d0abb8b2b76f9cee894de62d0df51e0bb53a599d7578be97f92a71b9928dad72e6ccaa37f48ab64baa971b93a6f341a4edb96f730e6b97c0e3220c9e1a5882742df32328d89c346107ac284cab77f6ed205e493cce399f9e3a0dbf84bc13d4689f6e668f051fdec8988926fa69ca4f1cbc3114e441119b4d3b7899aa1a5c429f91a168e25c569672956990ce441c9cacd47903c7b94c8e2370a76633cdf313d63e17c21cc948a22c4a1aa7a091f9145e5788b8b9cadf0aaa4ad64763cc4b9d040ac888b9ba6c1306fba7eb979e2689467d2bf23a987fa1ddecf2c934f8c6db7c9222d2b52a834d4680ad7f2c2669434b2a17573dba8576da649578b2c62c482248b3f1fa8485855d2c6800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109399153e3f95c2d61911e5918ca17977aaac8c51b0e03ee26c80466d0b1a021f425a281acea56322cdfda82cc0f8b31e20094fc0194ba09fe849dad90f5df94183c65f18e2758297a6d7481008892def78232057320c264d1475b4680002ab49b1c9d27de9164aa49fe9dc5ed67db62b8832a448a079450aa163ef495175a19d56fa5416f63a97992c85e215b38c5115585d2b27fd0a8f874ed000904e573dadd18a55e45f307c1b47a364522f4e19236759ae2ce2672741eeb11e49a6a2af119c098c707b89db786f729d23328eeb06fe24c754ad91459d9dbb844109aa8dc159eed5f22b16bafa53d906ac9a6676c61df402c09b0a6ceef27d028b2029a6a9062ddb05b45a6559909c260322ac96de0213fe26139190f92afed3663cd80470c6027f8b322efba6096fa25aaf46b4225998a470e548652db19e6b5a14e9555edd823761a24d055adf10d5dff930fd5a302d4e2d9cf2987056091e6ed0fc89d11bc688406a04d7c988386878509cac21338a9043d9122d7cd8c8688ca8f3b979a594eddf911860d552e01739619aa0b1795fa94f897e064224bf442d63ab17d6e1ab811bbb368c7fae6079930bdcbe62d2fc104b0c687fccbef3a9459776554a07f54b1372b82575a8e5710d8984bac0654250b544214fa37e8f5cefb6aacb276f08aad92ae08716198b725e2c9f62a834a7be6c0223009185c9001991061ada756f8c502c6361fc5daa1d34d158dedfd823b084f9fde329297ed0a61e5a58b852d1467628b37838949597e29c7468a1c5d889113d2257702c0ad1907e8d5b83446d3966313923552c36c496f0f8c2226de0c148bf02029e4cff0b29842f666cf14062a40997aa2f624b4574b006c284a56ede8876b5a123ec56385024db86d205335dec40a7456d39b9269b629cf9304a2c13146c119ff69318c2e7217f368192beab745e581f893c56170ca1f94228d2a00e401131edc89ca3bab5e1f198e768c0636b4164d38bbdecba120ce75c20aee452c8ff7cb82b89e0c07aafae327710584a61e6d7705d4e739aa444b029ea4aa17d3ba90b4e77aa60bbc73d1d286f61a93b260281af16bce4376b9e126e1b28d84e0d502420e6c5ef44a0d49239d8d7c56ec00bf3db5620613978752891b90b0ac786d74f5975964ab9745982496178164e65cc8989f7d5f853360c45a8f5a847f943314cc21700be8c543641031b278f5e91e01d49f05e2d29d9a5ece306d40e51e30a2b9ac22a1a0c538f76fa4ea000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000462789518ee21dc99cac94dd5298b2f3eb8f6ab8d0705d24d9aa3012f217464e7f203e08e5cea9e44f54a6f73e88d81592826e243b7f0b2a1b3a06e5afde23a2985183a0e430e01c3fa90e9f1db7e69dd8e7dc6fb802933e04a18834c091ecd46f0dd423f532668cee8a12a06bbc7e5ff3b9488b8f4a87a92bb8d6f313269ad95c574245e06563bb58bff6169b8f4c333033bc128b91cb81dd41b831df5103b295f744ede95fc3a0c72f1134a9321836afcfd563192c343040b943f69c0e98e8d740c06ccf840cbfc6bf777c9561065916f13d116d758a151e8ff4c355363aae8e4f49d2a2e062a2bb213aff25662d95549b4b025e70aa3363b50d25af84a3e5b0ffa598ce074733ad191c86c351592299c26c0a4933573ef436b73dfd0c4eacf93d361afe5f824b91bc178ee8381b9efd52302ab8cad6c08c7e090393b9b8abc78af374fac6e60bd104baaba524e68d75a759b94176105a9cff2e5b9c3984ff61c5afbf22b8e1b9e4f9bdffec0b19c2a5c8db3b8b2c02115d101805c1bd6652f738f02600e38998ca41ba8955094fad5bdc34133d4b523ede66cf483f1cd5acd9efaa69703807410939974d6dc033bc696541357da9881a4fd1385671b6e4bb889c68b544175c1e2ec1395dff4cc87e037087c615caf40804d5f44a2de301961a59818173730a45cf4c2df172614aff7199a40c9ffb9957242a89ff86b36a4f4d60f15db569c2fefaf677b35fe5f12ad5a323397714286e338ff6b9080fca50b657db477a52a93b243bf28ce2743794c361f443ad81ebaaeab2b237ebbc572d8586c3eab1f42baec1c985d28bc58b296a11d96a04b0e1f7f6790b92e450248804f3f62b5865941bfd444a910f31e1d6b79d8906e7e9828618f960ec14124fbeed28e1f58a8bc9d31773442fedc5a220f3912d0b41267d427c0c15bb76f9200c54b5f050307e13f1eb3de92b864c994a3df4cebd1bca634710fa342e23d7c8a5bac1b58aa321e215e4418428206f05232e2bcd1b5ee1bb7e34e7d4c93088991ee9dd643fd08b0185a2f0aeffb0ef0eea3acb4ce234bd5479a4f4296001305826f23083cc9dc99011864f250e77e42a0de26ab09ff6e3f32552f6f913256729b357cbf5dfc825e91bb5d3fac1f729803d431d339955960ead69b1e54536cfd774341cdfde1d1f527da4e738b2e292bdc884687d1016dc193edf34a37d284d026d33698295e864196e0bf16fa83a35f65ff2b38b7030e9e63eaaf594f272e07941313d538546bc84671739af822391ca4dbe6a579a81f45ff51fa5b7ef49beee7beba4ae07452c13366668f02752923ea3653043b26c883799fe6352f95144283d946ca87143b74c8a009c024d073baab9bc4da6c87d35fffd753e1eec7f01944639e566fe17a6f715f4197d1cba58d3d153bda37d7d2d5e19620ff0842527d109333fa2ba8bfc491689f4551bee6c9d13bb9e69ee4f44b782bb05d1e48d293bc15b9fc706d52b021c7159ff7df80e55627dd7555795f1fc616830a4ba2c02fe1a19dabe088e460bf3c5a88313c443179c593458467faa468791ca74e9b1e759847b6939f000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 33&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000291397d9d0f927817bec6bc25f3b047328080413df9bd8c2e1e4c6fad97f7a8e4e4e12f51ffcbb5449615d0c4bc714d0291b6a7276d51fd54c89b85199abaef153f62dc493b04561ca05c7212f656cf30c546ce8bf1a32a6ae9bd9eba3dbe74bbfcec5c60cc339e4e5504c511a835682c55be64728da143a4b5d7c7563ce1bb779847d5981af5291b77dac7a59471baaa350a5493a8d6e62f51266912449160c6e2649f2abe6d166c1a14cf816387aff2b4052e2012dc7b696fc7c831143351ebc6f85d5d32493d515a998d51cf9d51d5ee6d035da199e51e73c927eecb17e2cb1aca95dd23a2966acab882e170ec8709a48d45cfaea9a9b04119be742fbc7250d913f9021511b35908dce1eb69910c354fa4b6a136bd4fd13e76f6500d5e74ad1ff8cea52412b7e7f0a36ad04e0258f2482baa54c3135560947d519b49ef0b3cb78f417bd9a47a04d1c517e8db15b4d77cd2fae5f10c1d7c920b4f6d23ca12f30b9e50272f873bc8736408d6249b99230dad2d386449428ee908dc645addb60d37f04eb6c57a77bd607af1f157399c39de93e570ad0c03376ee34eb29cad333105864ece4c5e8b2447fa52f667046650af0cd9dac46505569487113f2e5209a8514e34c1c137752cc383e8d6e81957a541d3789ba52ce91b692b4081bf8ab4652351758ade2f1a90aca6f3595f3777a66aaf0f8256222f7c23c4d128c829863ce83dd5b67fe93b0e732311d566d3adb33e844497af2214b37db584ab22cef321119cead700639cda866501d431083a3f1848cdf9bb4a1ecf06289f3bd4b924086e306d240624868ea5e0cd25298421689a29b168bcc29fbcb5ef5194cb193d7ce00cae659587c19b0d0dbad5414ce4395449b121c69c9658278d036edace54dc7188df236a3dcbcd0443b0b2d9f5ff464d10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109a84d8d076d428ab2e474b3a057fe55827fa9e56c0402a6656a184cd8253ad8e07449f37eb6f8a3ad240079faf0c16346c2a66556f44aa6216d6548b12710199a1cccd446995671c1fa6271e61b9138d50a849e347d6e5cb2b69c09026e6bf1beaa5eb374db774e89cbb6ce5a62479f676775257658e19f6e765115965f71a059b6115c26384a0e7164bd18dd0e099c52c8aaf9547d4bb4b7c8f0225c3fd558ac00bfa4ed5623499629dade1281a392268caf7911cd0d93fe36675062292389c1c0fdcc6cbd54cca799190235e23957e9cae462f9e161b1a9a45c95930ba91417bad64db236c71b0e6c5d3993aa893af9e1a94b211db6a6a8c39edf1a10f45317e767fc423ee9094c812661711c2a3e9370817c99f644ca4b0ed2e36a6c235a968cd9abb6ac7186d60fc674a47b1429b6682957ec0d3dc1f8b6423e4986fe29c45e2505edf9949189cd63ac7943bfc13d0925947b2457752714c8747f253e6dbe9cd4630c5095e6a9e2a7072b376c0f65705dcb74d56bdb9c64b150e26923c0035da2c996879e2b5e7dee2ee381da452890642bd7ef914cf8a6744a5b551f56d37212d3291e2a66c7471fce1fbdceb4e3538f067c3806bad5de04f801f206257b01f02eba2b9962205da334d2934749b595b29454500870a4804c17965601c1f9f6d77e02645b0138c1782646b988b3cffd2fa2a7b3c261500b71999a912d52b02052b81e0d419ef6abdaee273f8fd2fef41149906fead6814994408572bebbc3e26a06de011a5611dab53606362729925cf25c803a22d5317ab667f56d684aa01511bbe2e7a43cf2f2ca443f7298a3236d9e485a3cca21aacad5378504f671d78a57b1f1d112a39521984c89298d569379f9b829ca193f6e8859e6e10459566854f0699c23c5e8d2f04f5f59e40d0949585a3e82f2291f83392809eae2594244b4185ad1c0a5947db11960aa57503c34e0da565a9f2bea8613454f8133352f651ba1bf7748a741601bc76739c522e6607fa869b73bd2cc93a911b702a6e21fba80c1f07b059624613d98e24b330ba9afea718f9fa2564079679620b744af23a0e13739641eb884a0fe4909defb712b731d14cb64624967bac9c5429566099c5d0376f8d1a0307a3524c5a1a960b4877549e8ba1a21374242c0b7ae81720280d262729ccdf15eac7f499209a197cf97b4a082918c1a9180ec1b52a7a57738088118d10b9b6cc6e1288bccc166f110851e6a138658d3f3ce88cba001f931f4817f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000483a4117808d9d05b702483924e99623e778e7a3b7623739ab7ac488ed93e711ebddec383bfb7e06086fd0c374f4668ab744ad99b8af1c75309b60f55dc03ff7be6f23187ffd5cb224068568ce2d06abe441557b04a5a0c2858c416f6f7aa89a96adfc2afc54e0f31416ceed005b7b140b342652dac7bf401fed4d94d475784936fceb4b4f334bb14ba55b1ea9a36e2b0591287eaf4aced997162691a96e7f59853e609eca9a225f615a49a12763d80b5dfe6f8638923c39bd652936b19b944d5116f790e866a61947eb60cd1f3a1f319710d0f40e487efbef51fb4d00f5dbb94810128215f72b1aedd74a1b1d237088de3098417714eeb67d6a3e6bb647b6b0ac6d0ba3089d4cf6252b69c414e2bd6614429b6fceabeba50a4b53c7394652acf7dd9403ae14436ed5fd4d1c9e238a8399a763806fef5c3742c55b7159ebf5a13b271428f91229c191d617808a26af9190f9d445bfd3b273702bc3e7f610854c8e86066be7757960a880cb6727cef19dc7b464c464a7dac9ae85b799747b8488a4123b6bc7f0f7c2a8e53fd4f8687075b4e25660f5107acf22ca688057dae0496ff15a3eb9379a9f6e22fa43c932f137e389478c05db86060686afeafbcb9ed79ae194c4146a48ce5e07eaf585279313851cb864a50075ae46c1aab3b3cb920dee2652f5afa0138051c7c980946e8d5e18c16789cd184dc5598f65875ef43418dd56e11defb5a4a6afbce041bb292e0e2ec563296ba4ea6cbfdcca32a18c8aa395515a83d0fb7819413e5ae056ff0ec2f63f1d52a8be0b334a628d00995bec7e46a34bcd2dca0e9c5a88e0fc8c43843d6ae074c699276293fd8db2be48885155688428c2f5a6c6c91bd4a03cde2126205f9ebafe319d1b4f80277fe99211a09628ad840046eb9aa568ec71252ce9f69827b677d9c0d99546df5a48a8d253ac0036ddaf4d045a70f94ec54bf5f06296b2c2617f2b0ec0b8374dd28de269faf739b1e55ae1846f548fb6c0403c5ecee3cf9d1927e317f0d07e11aeba01c240fe17c6660f7cb32305af1eb6de4312fdea6990da4e9135dbc0b88ad0ae0847e1576f3c2711b785b846c7a4b823688e4218596caed583a90dc46bb9b27e00e4c1110b65f77e602f043a8441563667691c07162e52a53cd76e2d74dcaaa2983bf2e8f02cc30b05bd4f9ac731931c59f9ebc038fafb09fbc886f4c4191352206bb49adaef9d74bd08a5b780ff0fa301343f5ea81d36912eccb0ff24bbf0be6a8283ebdeca79cfb22639da38c9c639c4bd66fe5a75f0414fcc1455702856e6fc58344bf02998e17e967183ae920b7e04f58aa09145d6da79b65efcd18ec55bb9cfd53914f80d73c2b08bb754ac63e4c82d44b72376a544d97394b7c99678758b15cb94e71f9fccf674b29ed5afdce452959be5af510d57f9e5395a576eaa1fa7ba9aa4122a779727071fa485c005b447760410dee20b7c2299b4a0d5d9e5e4e038a19c87806c3fb875ea5bd7f47d034d7d5fec4bf132b04e47574172d392ea7b371516190ab81c67b45fef6332848a51b6c7dba90c410a44e9a88ac082fe296a7435e7d2ddfc645d5aebbc29620525757dad1b0222159d658c7225d02374ee6af479fcf1aa28cd91b0000000000000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 34&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028e39a00fa134c1932aba2186fb7876bdac185b05223194b816efa21c281a18f17111008bb6d0789fd29ac3e423d9f6f9d9c5e82d739a7e74c723870330b8e618a479bba073708956346cf788af05305377afcedf5084aa3dadfc6114674c691ad5aa335ca6a156be1b5649295128d1f6352fa44e95e7b204866c861e3b06455a9fa6a654c9add67b2e39f0f8416eda9d538ffad2305ca506a4e0a328c57d8b8ddda55528ab936890355e1526fbb624a43eebb158f1a80d51d486a6f52673a4ca43b4099cddb58b23bdff17077be248d3747125288c8134884589dc15da229004d787f868a6975d2de3235fc3298f88cf7ca05cea7220cab3185ef6d1414091ebb68dc9498a9d9bdd7cb3938aa253ead21f851a8acbcee1f298ee1fb9abe2335e66df631c6ab5b764378fc14034dac8ad76a321b61256b60db4e1f8a3c3064b574ab171cc9af7738146bbfb3a997619093e320c5b5de6f1f9a7d116249386ea5d1a209f876fa7e7ec69b19aba120ccab424c708a7eb37575abfe141328d7d36532adbe0dee83516a27118772a3d8d9969c81394c5189807cd985ab4c4584c63e3ff4ef4e47acfba6046eb6ebdd3169836314c3ddd617061d6fe3d4094bbd8ea1773dfff679cf4edaa87432659fd175d2d77fdad9b56f9dbdb1d1abddb83e06513697309c5dece0e4ee69ec6a6468b4be0f38f1b21af5bf94d821c656dc45765ad7ba459c45d4a9a6419cc82037a83e18c14b5547e2c2409694f2b8a9fea5e67f9e87878ad3a1c6eaccd6df9f0d61cadd5e9b0422d7fd4d33809e1b3b3c4dcfabb7138c937fa1ab61d985f2c8d6dbf295f20434a6a761ade2eb8bb6dd4f8898d138d0b679d74a08277d9f76d7b7d4f5e82519c99956619bd9042ae9216291b785bdfc16f75891429f553db9650a713e80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381099ad9c55170eb9d1e9c0ee9af0c43955dabc117a797689e9d9a09dc200ca154e27d02afaf1982141dd69b1d467f0a4967f554215b2316826a4c59b193dd1098bf8089bba50084aa76011378af261a51f551ce4f0413ec7002d2efdda834f811cdaa8f6a1c9a04c4a31d30942cb5c965404162e22970d33d4d810e536febf89fcdbf1bf19a5c1a0a7ddb0bc060117a014830e8cf51197ba7dbee84628a030a4e51b91c94f1d1a60b625be9114547887e3b31a693b326e66a48a594f5411b7912e7db86a2992d959765ed2ffa04b463d207d9bb4a8a03f9e41ee868cc78c1e0daeb4f0e4de700525368e0f1f70c55e3124efd59579326124c7d018765fe31fd91043ee26f619cd4a78a49a11620bdaa2e93eb17b1395a559715a0468eb7e04afa76d44eb9d20cf982e4c8975cad6b960aa48597db69035a39b8e45e848b0091a0a75f89282da160d7888a3dded852a912c4892e5fa4511303120538a31f53bfa76e7cf4552f35b6b8c8079f4d17611dbe205aed729b0510042596fb3f3df250f0e48e98a9e6b330d5652fded709804b3e5a2ab21501912ba4e6a695cb9c3d81121615eca9aa0f8465b2af1b167c909a540a1778b704baf685efa42d7574a91c22f9b36408739f0f430b491f3a27d1545fc6c861ddd973aeb2c9b97740a8169ec7a91f4bbd35ec0ddaacd0f19465d366888a5b88a51bd6e64e3049ca37e93e2b480986a6156d14e3093ec4670edb9ab932d0534e1327017855639eeef5ae2468a6481d8d29801ce7ee22968375bc29409e0b3778bfc14ed3717f8df3f6ec0c00153e0fdb6e884611819ffa8ea68a9a9cb0fa23c74dbefdbf48f441f120442b3b5721a512c476e2871e65926d82f6346aa2727ade2b746386a0d86a376482d7a3e4de202e6a423e6d1d9a12060e4515875568c2ea8e31e82557cf2257de42492f89c2870a3d49c36f0b926d6c72d51f5d3bf23f867c468d6a08750a942a8b95f9ac745ea8265bd158555c8ad345e51afa3aa0ea10ce716535c312594efb83eb6ba4af59771024645d74c90906281bf0626a52db14c6b3b42215f0c884e79280aae4a640e21c7264b591e4a78dc49bab130ea64c9d82d3e7d68940527b30032d05b51df0ebec18f1aea517eb32dd0e3e9698a7eb57565cbce72669582c4768cd6544dd7da876ec9998e0609fd1c65bdc0dd0a9717f719754cf4dfabf71b399a5ab8c99f48da50f1230bb547fe830abde7634f789590a74239bcacefa11fd7258ca5c5c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004a4e82f5acc7c1a326d430475357629d568ea3d0dbe131114781d5bf8daa32fde9f3cecd288acd14445678c5ea6d3afafce48ea3957a6af8d8f23f78d84130fb6419f706eadd430cc85aff48283f15602265059abb075e011e3941834ebe70787cdd55f1e604c6b86f761d94c4f5e525791333df6d43869d6f36b212a8f35583d38a21d0947cbe26fbe6a36e189c73137f2f2d89f48566d04d2dd9125d2ea4e0b2a7e5c1e9d2ea036cfadcf7bb28f6df3b7d6395230c9d39d1e7558ea25340252708be23ec6c0c9a0946c5c5af0fe037c254d1a5b2b70b8f916cf37945bef76bdfdfb19a0daac5a83a6357e986b3155cff31024121634c3700ca99e5ecef1f2e411c6621fed6092c1ab59860271ac7f431e568075d59f71aa18096195f30bbeb1a6bac20e034f83c72be0536315879f1d1b7f31d38c12dd8e97819b4803d02becd436b61d1296ceb78ebf857e34087ec8ae8395269b5b0770b3423b39638910d2a3ddfec8502389fd8b5b09ffd10caad1a5c86e7e39629ab09a4abcdd00fbb9821f92e7dd24dda83d1d9762f52a89bed6c20648ea04fbad4233e5920ae83ffec28fdb5e432929a41db782b2cea8feb40cad0b27903050b650477e5d9443a536ecdfdac673952810596f1985427359d9e4797cabccd2fa0c0a2394d853b4e6f8e150b3e3ab5136cf476605ff5ffa9067c0fe58a143b50b18b09256657cf091132d449a6e7ee79aa870e9dbe46bf840edcb983f585ec2856c059808e72b8c901a25d6afd5372f168d533052a6d26418e035d87d0bf818adea19915047c8d824a425a8c7915756673e0f5fccb1b4fe7c1fdfce505f7e18f023fdd32a605906ec48e0fa755b6d87e47711e158d672c5fb4cd3b8d1d13fe9eece58453987cfcdd87b621b870f3aa27e73b6fb7fc0a6757893b978c63b7723c49d1005a1e5b1a4d60c4a2fef392df7ef97f149b499164455633fa485bdf92f804a47c8703d124522d73887a2b032f10f45343993ffb009d69e80fb54b6999a5bdb2760f8bcca648f3c52bfa1d887ae49862db4cbccc7213acbfdc48a57c3da1f1ebbea828182432aa1c593c3e5591c825e5706a5f9503311e91ec3d8f4a9554c3df915b5fbe0516a7a5597ecf8862a8df286ada96c90c9f2783f7f947a18ebbc64c1baf24b29f77521a9ebe09becffdb902efcd024046fd3e6182bf0c84bd3a0a5410eedbabfc60114e5db28b0943d79f58f766e2edb16759850d4cc3a9a57ae073cf6f3b24d36a4365e2bc64674259170b6d11dff63d0deed085b6321c45f218e09351aa0d4155189cc98de5627a03396a067ab3fea2c133062e3823fb1cafa5d592070c8e82abe812979dbdcb6d2e595f33830ad0e8e2f9e6cdc4d9c74b8026ead1815de36772769c4e00806f79950a40c979c14a4bdbfdb79df1de01fdfcaaebc93ddbad62ba166843a121d2b144559064e9de9e310dfc93d624c1061bad3195d6c9f46db64c65a31e90371f9b644e2a15e01c262395269a9ae83f50776f852903f86e5518bd008cf1b35e78f910d48c0b7bbaaad5dff2375c55d56b8f65b922229d5f494edccd2d676361619fedfe6bf0bfd7e4c77fc459f181120c4430c409ba89d2e5a8c36cc6200497611d9d705da6ae1aca4e16b389d632a982e017e1dad95dffbc7a7d7191e7b8fa1c0ed00000000000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 35&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028d39b2b6104233bc4d6d8242f22e0af819b55d9a43f65f4cc9d1f84b23372792c8de51494f7d6e3230fb9c955aab192e0ccd57606b888a2def33ea8ecb10e1d55aca9a05b9f2b26c2aef9f2949df9e8df6d77d6664cf9772da6bec91687f7d9bdf4bb92e4f1d69dc61d2f2aadfcacb94a2a1aa305158cd1d5dced6dd6edec628d3f5bd5478132bb25325f4d6a4d4f26c8a0b5df798ab920c4e6a584c2102a5af405a8830f8f8234c4f3e887ce8ec7c5fd8e16cde4f53366f239b848ad2405285a37998a9e97096a59ea98fba610861a3729d3d3b859dd86d20aed7de1df6dbc52af712c911359182924e6ba9271a3d3e8d2b054327739abe9bb75ac5cc49e3a571b99837384e7e29ff52929a1f0f1a84b914cd83e726927a38c9b25bcee3c37d7f2eeb48cdf296363d9c60a52869eec732aa17f696f6d5d1b2c11be8f69916524eea72cc77ae4a71cbb76eed0dada9dc36b71942843a15280f0f68844f94fc6a629ce1e5730a596773220c7e498d94e57618ef6773516281f8e41016019e68668632283374586ed6023a6ba40855b0486f0af3a5ab286c81a28e18659cfbfc1165011d3797b92cc114cb4d6283d7e3618451b1247c99e10e7d2eeefc2707a497bf78132b8cba4ddbdcc14f31cd9271b4c1fdb4b315e8826f9b1c56ecc5c5a30e6ce90bdae15c07f77360404d7c11df219d315b41e6f87474dcb60e26390ef97417afe7367b239d697ced464b0c4f0baf6d3828f087056d2cec0f5599a0eea10af46acd0e4a97c74969691239ad6e732d6529f7f43a84ca9103ad8f2e38b40cd4911893094d9de38d4a32bbe5e86b7ea0cd25c72fdf05e3211a7adf8a3a81d8fff2e42a5bb639b03f83e90582aa782687f2c8ea73155932dffd27f3918d15a7a50cdd3f760dbac55a8962969c5d660000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003810918219f6b58dfa21c609e50305ed12f58581acd6dfe57f4287669474b435cfa9012a7fc19c9bfd73dd8909c1c91858095e39fb6c9a7f0e96c743a6f856e292d1e95e4168656ba23216f47cd450e28717c0754ab57735493b9cf867287a47efb6a166d8330e5f762104469552c30c01a8593fa6563596fad566945c465a11b7dc279f362159c758a76566b17fd491c10a137ea5689d58ef39927cb85424dd8bd0c16a0b9b53b5bde864c6910495c53950f8178e0320bf2543d41b57b478c9ee8d83971c61120b8f3035cea799726d02a9d560808e6cba855e3014141a41512a8382ad07ef7e96b596cd65578a41dd0a57c96b8de5c321a04c1a6931880512dcea2e2c5e22222c1a3385d2f00e9288800584a912dcfc967c31a6bb61631810d4c05c173a4a9d4ee78ed58c687c1e653b0cec03e2fb05942ace0c1a24a8026c7d9226adb430da2738f85e51ae23eb776d818a646ac11742d3d47f1bc5bb5c0d74ba8c357ad03d5b16845584fd7e53e340387558c1654717491fa5c591024939484d837a7929c5994d78e797523f515a888138c07aaab6e920c7e4e0750cde4559d9cf51e57154d92e30761d7859179f957610ac8643439e45f137ab66dbe995f868c4f45742696a8ad3974ba5254a8dba2ccee71cbe664441c02b6511c3f85241d2870874e69313365dcc91724d5a455d2d78828bcf690e8cb4d0ae53b0088df642a59197687c38a57a654b567df80015ee6f7b5aaa627fc0543f22f8b10ce262635ecc24f7967b641ee8a4d9140b89716548a5977f1e48f461730bc931f9ad661806888e599d68778ba59871d09538275bb112aeebf9dc48ae3857f579272245dccef3c3533eab5e67db9e96a119c9c063d992acb8f49581c44c41ad702b356229c8bc6c0531f3abb81fa888e20327a0266947ab870c195db2c097a4234946c630984245845c80f6c6d5238b83aad14b6314776e149bf7c9221d2a7d0b5966c4f920ad3d355547bc3d54e2b09dc78867fcf55afa9d5910eafc77315494697065a679c9137f38db72cc0f2f4d14ded8926cd952fd65654f24ce0899abf3eb1f851d6c9c04fa4265bcf2e260845782a939f951c7c5ad99340204499fb2622cd003570545853572599c6fe11ed83c20e8ab48690ae072a76d7c89b475940d5720b8923e836b93d647bc7f38735862bc7ac3b9bc42054d46ca3a8302583ebcd3e029299f90f42bcae7559247285dc8051d3cb70ef3729505760361c751e5a40a167e3750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c5743e5d96b9b4c1469e7ad2b3703f711faf60ca335358ff3efc8fcff02cd020a443243b4169f9123351b6c36762b85be5e5eddf8d4b43d82caa615788406a31cdf4f7087d42db21ae48a069aa23a8f6d20a1c0762f973e526f011dec737e986cc324724bc5336d0362525757410e21046a12ac54f2237e68da036a5c1389e46a53ed8c21774906948d4c9e14f40519c54dbd02b7a4acaabd24ffd7f6ca4d6d582ef48940296d2893415e811fe7ef0801b35f1c594e6fea2c293869bbd45618b6f04fc26b55d55a0ae99445aea12f851b7e58a49cc6a0044f28e3eb838cfa6bac5df53b0db78be2ca2bea1bf2deffebd673a783c91a6c9ee710b12042ec2863a9b52eada5b0d32101bba8338f7c75cdae7b7fd6797b25f96abd53a24a7647a1c91610306ffc72a8da4d46b1778146a98bd59cea3173d41d5a53f9a7f9e282b5fda1afb062d8afb63cb19b0e76df782feb9f7fd50902133529cfdd7c51af297895ef6e1871afd4c3de93defa8fcf1fe67bd27b7eeb0cf37a6a8e09af1203922bd9b62672d4756519cd09dd9271ecd0285f92030a9fc81c09bf2fae86f5f50596c628e0be673571cbc2fd76c563e113004529b234fb50e9e3d6d1f814cb8e5b5cc3ea365d0bc7602b146cc0361397d9bee9246fba3a724c462e177d27836093ec009741abfa28379aebcf5ef09bbce00ce449fec3a3302fb9ad0f010ca338363539da545f159fbcd3d6a0482454023587a324f5132fb6f4ca602fab2cf6cd59104427264cc9ede8d10cd9dd7fa6133e65693dbf744443ae920994226e21d98634bc7f0710dbc37c18203efa5adb467b523322e21e4e686b6b85b00cb501ed84153baecd4d6cac9d1183e38b510f7b1dbbe5995bcb717529b83fbbe969dfd8de21183762fcded692b16502834fe8e7a7c46f84acdcd2c9975098cf0cde8ac0efafa449dc26840180dcd9353a2f1b06962677c808b07345e8abe95b8d24f21d751a4edcfa0e02ff077de64e6b992e8c8822682dcc7f03ca7582fe7c74e0a9822a02d888fdde1fc9e73c2ededdf32001e918771e5f511ef8f88ac19b76fac0c812f56938f814d712d99269d7802e47634e541b54e00f9eaf78a421506a88b4bf7332dfc7d79e8c41835031fb449507d19d5a8a512a5c527c95b6f21ee3e41fa43591dd9bd2e4293701bdafb624e0ea290da4b7a173003867c4cc3fd814e117b4eee283c58f5fb33d653e410f68c8962155b8c4fbc13bb750a0343737d1fab36ebc618a6a7c8e6f93855cb24937b01c438fa713d334df335d0745582f680627d8b94cbc25f0d12e3b1c27a3ed72e2558b800c19dc6b719b961e0fee43bfc34e999027ca1969aba4c45fdab9af01b955e948de951f5a1088beda43ac930fe99d8cbb3473475c444f43e928e1a44966265b38fadf9b1183700a95a81f85ea43e5c61dd9b2d67701c95583e8e3f15083717e1722d764b6e624505347c30e5e70163ed9a046c504ff534956e911294d2b9097bbeef8740377ef0d6c4cc8086422902bf63556ce6da8e33e68fcfb42707c00693a995d17680b76293194db217eb5a928303dcf1814e4a881b057baf2553ac4faac8e4bf23fd4074154cd4ae189ff7e204eedb8edd594cdc21b5b7d73a712b511d068f4d217c0f91f9d84c524d973d67aa741eb13fe922afabf79cd2396181143783030fd2d0cfefc877934d8037a4c32ae8e15b50a6fa4269000000000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 36&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028c3942cd9f37e96c32f0209a80ad3ff7bac01256d63c1e3b37bb8977ed51d0a1e68911771b6f1a95bfc9117f79373a64cfd2ce447184388b49edaa01c7abe811284a45aec212e44f71435210270eb8c24070bcc4d2e71069f3f4d8828d6bf5b148e43a0e9bc82171d36c50b122f2c61f598258f3fe091e36bed0c7f2688a299b681c7e2e6ef7dbf5d0b9993714b7fcb0a52613ada668b3d2d9ac723330ed586c1402e59c330cdf09a4849802390238cc3ed9137d443edeb19f3c645145cfac27a1eac2e118022aefc9e09e4207d0fe3313157779ba54fd9aa8b7a4f9ef570f1a52cb968c876948546a94a68df7687892132fc4d5455a3c8b25bd6d3d1afc7d7be54274dd050088d31345254d71757bc2f9f341365e7ad37c2036eb83d9c729290406b98763a88c8644e4987d02cd5e99bbbc6c26cce95db6e7f2fd137322efe74160cef6b05e94cd268aa98936d13a5ea00a1aa97833fdcfd726ce94a7b40a441a1ec1b6356be2a7b6e2299e853f4902c4c15966d322e1d427cbf133d3a9a44d2d9a691a1dccfaf58044bf3b1803eb4daf3db1992a3adda81053f5c9e5edb313e3cd90f07c2d5f785d410244e12ca1bb729d891ca3c67d3cf3edb64530ad584425f69b7eb905c2f320a4473f3cce8f879a33bdb4a5894447779a7d35530c337bd7d29ba88ea51f78e158c504d72ab26d347b3cddfd215fdcca482c544d66e7e10b25073d93455906c70ad738487e890c71b70eb36b4f22130b1118165f4c1885334e6436defe77f3f4d460b41fa889039ef8506d4a93f3ac39f1eea563cb3ac294091a12c5cff83d4afdab670e85c7149b7db12d24ce6264e67c6a4a7f7a82c231338dd5d57c42bd54475fb7a698ccf8fd8fb73d9b884460680cb750e34f13c7552c6924f2d6ddb5b417defe1a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381092cfabf566f8a956c0c7a080fdb186faab74a1654a537684bc23c86349afceaa31da9b3650c3d30e9a83059fd578a13d1ea15e5a27ba2276bab065d68fc8ea67bba7cb6255ca098c5bfc1806b043f1e68579cead41efa3732758a1e480dae94aa2d2424f58b89e3848aafb1bd1b510bf94aeec48787273db94dfdb655495a209898204ed7cc03b64ac5372617aec633fa0308615eb5abf31a4d750f38f7693de3f41d545ca116afb532320af6a69c84bc8d8ee4f89b3984565e7b1f0e661358829324a5559a3448268f297e0d40bf253c57ed7164581277617f8d54a6e63193cf598a90fb841348b1a439812fde084a4839576212f3444601f9b046b8bd9a3e69fb055c97b51021cc42f651c00a5369d93240cc25c34451b6a739f426778e89635e5876109d2d3ec2794071eb910e1062c030ae864544f4640de7d843a046d29bea0dbd1575d8bf43ad15ccd6c2b8cced02d64f96d5c4fb07deff2424829985fd6f12181031b475447438cb161b0c3fd034ae7e35e5c6b9f828577ce6b9ab13d27b2e6c8f6783e69b443275770b52fc416aa140956056942ce48b38d82025705c024ad24d43a209866b253f71c87f828a93bc0840ced05a479424d5ce84da043727e451c25168ea97b8a76826af5252116bea2a623448323025a19915785c8126d5eb4460f12a7b44022816394e643483c874bae2918356bc8b65b7b40e95d43745bb73a0e0b522a6ffb8a321913ec42c67884d7b3994b673e78a11b86885542d9d4f93f1235219ab2c4cea0e54825c8e49de36a2c7ddb9989678b45058f9590c5cd20ccc7079856692f0ea377d743a93efde53036d40a9702d3a9926eb927e986084602185ea001493f08259f309701fe49014c59f977c3c8533ce1ec61b54153af302a510a18bb5f3041841b03522bccfe991403111505c89a574405449cdd3976ed0c5bb177539f40594851510493003bbbd94099040464a13a3ebaf40d6036e199d427185f2ad19fb642df23155ada17d8684d69ade145ea226c02100fc928db572f628698d4a0063c917170dee3afa2dd9d437c18d22e050d8bc759707581165a1c85f1657aa180b54c9176de0222096d4d4585faf2704df61e36c599b1160aa6943f9a6dd08f9635f3f96e48ed39b1a87aa641d8484e0622e4ca0036b47495181fdea69abd60250d21a04e7897a2902a3705bde5fb5fbf1879d1b5230a8350c6a585ed67b38db2c268fb9a0ab3a6b9d199431429a2bf18a76e9f50187c50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004e63382e87ba70ea986a044b0cba2eafc3316c1ac95a5f16f6368c210dbeadfae6cf2382ddf5078ad594cde3bd1a837c517b1a20a2099d938df6aa02b6c0e62fe6147c904bcf3ede51ddda60de7887dfeb2866db402d23e5934a74c9ce4852d4b2f53cc9bcdda312964a548f6f7c8320af1d1bdba7fd32ec6c86bc3fcb4205ed3db092fdcad9ac4d2b8575883e13f69d8c16cb18d1b9284b31823ece917c905c5c8b9d180c1bd87975871014f773fb57d402b8fe16ee312692665824cf0bce4509326a31957319364cd421e9b21bbc1dff663ed850858a2450c2ffe64b65e009a3999ce4504ba5313ba0ee4a8843349c30fa6e59fd3aceca130a37c04f9b64722608768973996112684b64d0c87bf95e5dd60661935831a6a1a9575ebcb2f64a15296be788c775d80523d6bb4267d91b0c71ba5f90ddf1933de898e79fc7e39d0a3d146f185214468da50aeb47402ab542e52ceb768a70cb1f749e4164cf20e549b674ce965ffbb98d874d34b5b7851e575e6c1e4de9c170a10dab84940af055a951260b0119f5acba320b55cdce4f16346905a2073cd9fefba95734e4f4dfdb7a33f292d45698831f1d3e9fbf56d9692c14a8f9887265cbb4441ab331d977e3a68a1bc9f406ae0fb1c6e91205670641b9868e2a987baceee2364fdb089a63b53976d600bd7a8ae88a02872e46927269d281cefa385c98ccdfa6609394943fac32237368c6203aafabde072054ab5a14a91391d5a943f4ed4a4407f275ccfd15fd28f1ae0eb6edcc6612e3436572919e4dfb57c049bd77b344d8e04152863efd4fae8fe3a7230aeaaaf82870820085f4b3eb5215111b6b8952cf2ff468b3d10f3af849f16e190e9560f40b05e6e2204591b58a850e2710f7043aee2a44a6d4a108ceedeb2d216e51102dd08751925de6a7f67bca1980f0789b34e2f86729621f2285c5d3a036cd87c76102e9d607c37ccdac8062ceb961053f3195b5abd88bc64fc65f8be34166841683f1eed291938f75dfdb3af4fd2aa98ce95382acfb5d5dfe6ef243c8a0b19b80584fc0cd533e38bd485d1c52e0eb5bff90c0a947d9b9095ac1c0ce9754eabfc860990206b981235c7b612db61c9fdefc0f14dbf68a8a0ea4986cdc4aabad6c218559e11cceecd804eb98446fb33eae47c0388bd8972ddac02ce807b707d6d188cb31a1d76d44323e93dac4f8ecf77e7896c052ef16009ce4d1147df84fd5785d95d77310783f9aeff1dda693f4bed26457ed82a1cea19d9c4919257e3050b25a7d1ce7561740ddac3fd93a607c79875e050e40498bfbcca95bdb3d0fe639dc7cea80e3dab3ad73a4265f012451c1bcc2fda1e1aebb7fb18407f31e7496e2a18d2c686b47120688240a2fb134a3c314d4cb422811e850524684ec485e061f7365494a6403af170da461a3bc32ffaf9143d5e9b17b2285c56977aecaf880cdd34f26120dac4c950198233a50654efaca6ea97333d2bbc024a5e668821d20333df0b712510100aecab6b484ccb7814178f851a3e6ba0b76f16c4685d5ac8ba48558d382abecbdcf0b919c1acae46ebeb5011dd0b3c22b539810720cfbe4cbadb111e100c09c811e724a67c66a1b89eed1e7218861f55a4dc55e236c6e3521dcb374437a14e8000dbebf0f7f9bf409af952888675c11326d9e3e8a8828bf50caecff96075cf29446cada373529d310660cbd60c042c143e1736fe7afaf6fbe42791a8db01ec0475145257fe2df766d4ea972b14ae5110b8f8f42d659383e9bd760000000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 37&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028e398b05bdca0340fcae2a7281b0b9fde32a8081ff17bdbf172ca0431446e6d41affd805bc6b89af09ccd5aed8cd227ba62e9ebc7d57a2d6ec31b4f3cdfb491fd5979a90787a6ec1c7c0b5c715c843d40ddeb7dfe3b65fcc45d9d03296596af19aaa4095cdf5a5f3b3fe14323f39fcd2c96aa2d5ef1c5f33b51533283f8d61cb227d26b89e37741429e8f6ad85db6fc04e27287c1f0820df296cc587a1a3759d670d159bc520a4d22f5a239a75832f574e54bc0202e1d52a061c59e7fde916c94e86e01216d981828a8c84a557dc551163536c9c6e4ae0459cc8140991900be33bd74ba56ca48b02a0abf9073d84c127236bc93ebb6183fc662b38ff7f32548091de818667334cce59c4c020d3bd458b0ce9efa5c582218a7099553161ceb5452dce917a524ae509f6e64aa2b8370ba7068a49a4ee3c21428d2d2e3d14a979174e76ebc16876bb09c629c8ce50f7877be8465517b2dcf79def6ab74d963815cd2a19ebee64d07d5da3a152f9fb6bd7556a4ec5527346c229f4b84f9c12414e409e0674525d9e83131869e27a1bd2152894ef342b95e2769db169e2418cd639d6dea1a966d819ff25af5da02db2ff62f863e4b1047937cb5db28e9ee350dbe61503d9f0dbec6d4adacc89e664f70ebed2988a8c3684e4cc93a5b9166baffb6a75330442bbd24ffb42d3abd7fc93214b9bd90cea4a733cc202b9c17a86a799757a1236bb177ba4c9ea7b1e8fdf9e7df56e7bf688f365b26b81d174a6c5d99a6b9cbe0998a9ddf392af732da94a4a5faf508698ef5efa13b282bbd006d57ea1f93609cf3efd249d9bd5125ad02ad408ab4fc04918130b9fa3da5e78388eb948f2337e59aa36565548a0c8d67f8ad97c916c6d1f464cc130bc3955cc9c9305d1c688c912fbbc8131e6f599fcba25ba74a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109192d8df5c0202b46f9e839f684272fa51746f3106192755395cc1bfb7c5d384a3843cf71b27af4b12b5363b1cfb3e05c1704d524740f68c2812e9d9077d9a73addc7f4215fe2bef85256f0ad6ca1fe8d092e0b10bb61a153e02aed61769d49546a0c5c2c43b3bc58c7499d7342c0e9415c5ac7f6d12a8816fcaad3d453f7878c6f9b1b45579a9ca3e73f156fa50ac6b91450466659a5c6da070e7be05c5a4c29221375d4d26cc4d95858869bb6639c8ad00dc7b5031a433981ea8d42a33eeda9cbd6afb845b9284b79ae384cdc500585a9667e75e990ed21ec23990ac8d6ad14372d7ee5e0542f4dbcd4507febcf04062c7791db265e117b513247ba004c364b358dd5665936e4cec0fc0149ce524448c0bf08d88080eaac55521f7b1c541e91ecfea8e1cf1c57bc6267bbe438a03d0f691557d66bf92ecae1953c4e022d7aea08854ff8f9e348d405905c37a9f107cbb0700d55a55b0c71a1140675cc61771eacb8bc6046131dbe428110d5175451797ad50517912c89ab17e66e60bd384497939b896fdbad012a87dd94009b21b802b6ba6a2fc8662eacdda945cf48739e46f1859868b17a121068cf9f4b442447a5ac8712e8c8e6da6ef27a894fc21b2c999a99b70610edc294c8e7b44f8f6b6369b33932d2fd963aad2229e58f85657359a3039560512fb9a7c21f309a9f165da730b2485496cbc624915200c8cd2d4c58d509f2c6a0139cea6141fce21fab4cfe03e748c963c6ff8137093c4cf6ebd6fc91d454acd209d5938f8dd1978552e08e8b0a45c903424d795ab2819e410563397ac9a12c19761c7501ba0f537fa5a01bc7920893821558d15c100632e3bba9826898dc3f1b0e1d043e70a4176bc5fd461424f12ce124661ab084c0404d33a1969117454a140e5c48426ec60232e3e3cd66ec45b62b533a145d0e668f98274fc60cc12a23cf8b287d3aaf55638a356e06b266291d7b96085463364f5d97b69f5a7f1af662b22f22fc8aab716918351f0403a3c89b1a4cc7d4513df25a7769ed9ff68905bbe57d0f8cf2b0635c1a10518900cb1e8f17b4d539e894991c156b60af9a635454ee413992cf3b7924216297e301eda6444607ce32063794e18d2a8e9514578543939a15f3e5a46db9610a679850e51f3ff524666eeb396a4d7f81ddcbf366e86ca9da67aa2362dad5ad8a8352294610754e0d81462272f75bdeaa60e4bab1d2320d76ea01d31db40d18d8f41b94e2abccc6b24644fbb2b098849343cb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050767109894c579974373ca0054ed5f7c373b7aeb810721c3d9cefa02eb244ef6b17507300370adb24ae0173c6d114c51e05f822a770318033c082b6502f70012283eda2a9dc0a1381f145470e5d3729d201773d2aa63c18885a92c962bcd3628835391d70dc36273dfaa4966f65ad40eb51fb4b416a8d0b1ddf39cb932ec4503bea23e3d9d3b4501db426c6ad99c28d415fb565f62eb5c22bb043c8cafc42ebd1c7190dd32a5b14b571644471453740c081f3e3305f9ae70a5bd505874382ec0f6e2188563e763bb8d1bb8b16587ae25a6252f51e4ad02d0483c4a6e8aa2849c44629cf4b7c6dd6a5fecdab0f9b2f0b35e306c7532b64bd5a3ce67a0247d97024aafe5cbc13e375aa69b8287bba9ddc9aaac2bcf41a71e373ee36b13df9f829bbee8f48802dd9e03be42a5e290251bb130e0e2abcc4e096dd0f264e5d29f8c2388a0c3010e78f2a03f5ba1be13aa5e50f2ba67a031ce3f787754b8276ea1af62bc5fb4dd9a9b9bb84217a37eb9fc7aafb517337b30454200d6aae491e50d5007eac2150f60f640a5c4624ce6d8112119413731322bad9762bcf72349ee38e2a41102bc5461d72033072a90e82d105e6fcdaed9c223a4142cd55920196d7b1b9278c84b67a2e35bde3c9ceebb8e9007ba8758bd35c875dd5fa0a8fdaaaa9a09629b9df69afaab456e105dabf2ac5834b8d223b0a406e0d1295c876c447e8e09c93fb09ed1b3ef6e1f3b7fcb029f576a45a12620567e05f218bc3753109dd29ae0ade1370c0f871ab5ad8a9dbaa277fb869ee552e8733e73886d6dfeace6b35e481f37a516ebe191daa6f83e4ff453cf9cc9ddea8ee507af0e62ef3cb8c22949cb828e21c6aaf3fa9ac301e2257b0a054ff0a237f527d53eb757820af637ffc9f983a2b5aff0b4cc493e610314432c9c2f0ff73c4240d520d1d73721b429ce41807b7424b14f5eb1cd23d5562263fe1d58cb1d52e5175414800cb090242e240c3a7acad4c84dbd8abc2731fa2b1d9820da60fdb6baa7ea849b6a146e07af7fc201b3a98e5194bb5826945faca3690209e5726f070a71ee07ae76adb7e6199fccc81c8af7a463633a58873b4f7e65f522fda409979de41cf54f659e66cd5950a3a3e01570526c46417a00ec2e8821dc380abfa21384d141d259cbb9722f267e46272adc5cc4bce382b554226996f4a6a1605287276c18a48c8ff1a92ecd2815ca5452fd6157fc27532680022993535549bf9ab064052e6db4e9f83b5d0d885b94a90f59e67b9df0c321eb0f95ac07007e4ee33ba89aabeeeea01fd1172eca4e31fb02c507ffe43cd0d6c8570769a180e68a70bd344b4c992e7d3a6bfb96ac4d69c2d4f5efaca1d348dc1988de44b30da76babc307a88124f96f26737a85fe6047e7e485c7e4b6b99b575faedc9baca3e080e2b074cffce1f716c6a1d08234c45706d2883c6e5a001d02596cfe5b260de6134c75df3ac8bcf1919759e15576ca147cebe041d04e369bde70cc64157aeda311c8da520eae907c33e30dd89013e24b7b02e66c9f285bf7d5c3fd65bae24ab20d40addb451ab4bc4b9772d0b9039461bca8d3d2a4d71a2e6bfbe7f02325fd571fcae1fb47f855612f382188a5fa3d61c3e8e59ef016db0149c52e1c7dc84030e6c93c4f32da6ce5f3b8196affde834d2adc26cfa05940055401891519386bcd33d85584d74b2f16d8e19556c272aee8397a1741effc283dbad317740c1b67f8f4b7d2d1edd68d6615eac3f8e3cd26ac4f8058667fb388b19c654711b5b2eda75a9ab55174157cbe08c186a3d0963bb3011a9567bd499ad2a800000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 38&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028d39e1ca3e4dc881a5c1dd961672a5717a071606b2fe7d9b3039a9c09939881ef3a0b9697f9658cdc84786692967bc9e395b9463b813570b1177d49542e07088124fff7d66e856c3ae703a9ad7f546834d9de38bc556ef24fbb29cc10ee413e4d35cb40c0b0f5bc640e251978742785fcc61c225f04cea98b21f0a771160350927bdb3d926c44da84588662e0f53a2572d127419de643a36e80ac7bc665e632bddcd8f3ce5e4c0a3394c3d43a6eb4ff07871b88c5abd08ec4ba8f566d07bd2e5c351adf1a8a7151ee93e5eae6d07cbf3243acb5e6f84d3c752c3bfbf94273ad6d64f34e95036ba3740fee5b0b5773defc22b96e630612175c62e786a9bf8ee49492f8f8e0bf4f6ee4b7f174995580d29c69fc05dee9ed1d5c73450647cad2edcf9b41b5d5062ea54d8ad72a91d9c10b4f7365665da4fc692fd67ebb05317194d7523f7885aff5cf410e7b5d59022ae8d45078acb212cdd2aa35249c8f972d06218c952823371fc56ad943c5873b39ae291a977e10122fd8ad914db7460e934164ada467304f1f3ca582a260d4ebd3b480e20cbaebe99335af1d9a158cf9e5582e2403d788ccb6db44f65dc4d9cf68b3cb3c7cd66d3c11c50098e95d4debb5ac96a0490ff4a423908e6a38eaf6e0751ca185244cacb2e974e641d37b0fee591ffb5136f0759924dbe3f7901a6e7f0d06bd90f988e1bc8a6b24691948a7fd826b20dfcec54901cffd9e871be060590a2c56d7ce66236621935ba4bba88ccd5e0cb2a8ffb7b0cc9929fb250da56363a761dc98561ab54eaa159f8d649af7322796a2a676e0c52b8d7780e5e4ae1aa927fa46d36211f3b326ece21115971dee95850db4c68d752ad71560131edc66b18e3cbaf71f0d8fc353a3b53fe39fb7fdeb4e95f196d7270efe558528ca130a8ec000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381090eb6de01349bd88188fea4990cf05d39683af2cc47a28e5e85b5c36e47689d2ae60d686f01396ba958d729a2b7ab3f1408bc36ec98bf0455b86d0fb7d6d6ec8269c73011d1a25e65c1350d9924761d1cdb8683656d5151525f54cab04e0c87a0d6da945aafa025c72d336c80e1b62d85050ef7b43d2121746ecda8e086ee395484353da360a086d950c9a93b5f96c5535fcf9cb4be86655b486e0bc6cfd120942a703cb070c2ace1b9b6dec65d58197e7a38320e09beaf45f2103a1c053212f5b22fa25050aa8721a22a8635a8f8c74e6875357ebbdbcda19764a963cad92f0ba30a2570d0476239f5b6f2aeea5d6142c9a2d24d9393f16829bc50a65f7e68392e1efc2e942735f44cfb94354b219ac23f9d2463734c5d3e64fe46bb9a8eaeadfae698b4c49009766180ce49e76099f31964132b1ca59d70fdc6e102ac71fa692ca731ceb8d8335983674113083cedc9127ab5936dcb2db2ba05057b2ca4b9bac3847f5988164cfce5eb89a78174b07710ce506a521c16f4a0d94469f6102193a5407a72576aa4533f36a9458594a76908c2565e4ff72bc5deea7394057d0d35b0ea86cc5ccc26931fa3aabb615307740f65a1893381de1fc23d0d8b057de4d097a881833c85ab018c77565fd50c12cc350749266650acff866dedc72b3cbd071e9255a8c0ef680c4cf408f0ec497cec877ce52749aba8dc3ee021f86312ed8b200ac2d2651c0ca5a9aa5a4f4d7351a7c0b75f8620de2fd3c89ea38a918c694d10273e283122dde875631134963f172a498dd3675a40f38045ef276f8547b96131293fef0da650c9cb8fe433405a59048919770f9572b05917163c00859a9b2266bdc0e7399c8453a0698a752491e1bfe542f33dd7726b72d37787074e55197410b98cba51a0ff704ee672841011c74dc62d3616df438858994ddd1125e2a2383d26612195aa8ebf52371718c60408547a267690445519674a70e4e96a811195b096be278a13d36aa7cb2d5cd026eddb900ca1c87104e6d44544bf37614562210038ba3590cebfc13a75cd46d755ca7222221ba376d6ca863fc8b496fec1a992a242868104693f43ad425108a47a144406658b546c68916ae9e29321436b34528276b684552881b4c3f9c53864122d4a03ef1d34ae7c187aa29f92382de3aa59dc72b800355326b4133cdf332205718dfc3117632a1e1bbc128b6bab7b0e7ee1f5be5fed5631dc4331ac629b15faf7d2a4ac2198d6f1894c4d0c095ab8a54f8f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000528061934748c6758ecdeddf3a2df78574a470621496ce3f12e5e4555febccc1a46a772fcbadeba8b2eb5231b5b15deda5a38076c737e5d091a8ca8482f84ec4a20a51ddda391088f2c3926f8e1d8b77dd0abd606e9ac25a17a86a5c75adc215c5030355c4a1b307c1cc80a3bc4a7d4b4044fd35d173a2c7c081318f707828a3438dabe0836c2d6c14e1643f05ef8405531d5594411ae4dac6f3992279cae379d7c1762b122037301d3ffe8efd1beb4e027e055527d485d0871f2013e7b25cc26531c2ca6ddb98b31f0ac2c3bdf400a0bae942c9d4c4003f9952b67af67e85f572edc3345a84b6dc3cebbaadb7e3c876ab2da16ed0eacf4858033bf5a4f739f9e083a345c2bb5d8611dae90d25ac45d8b3d39b4de584cbeaccc6f5b6e61524349b50e818bb6b03c7e5b86795d49324ce6b1603791f20b3500a1b8ade82359263470d777b35dba38276096445842ba5d5e960fb2ab58730f970a15aa42d9737c33be700127a7ce7cade024d3abca59ca49f9a7edf44db62ccc07a595016868aa97a140178dc92530eff864c24954464ba886db7d74be7b540baaf807f1aebd014680ff4a51e16e1391e32069ee823f3d23db72244d657233578cb7d29a33e6ec31df1fdd43b51742cc30efc54be83149177e7bcde4450dcd142eb2cb745f8865dfd99dc84ab92750f1cfb0f3944e4e4eaa41261a1e8c58d9b230add792dce20d2612823c0ff9f82e04b61e48dbb83f1a6dd5cc7f92bcd0a37ab3053803d1188029aa1fed9ba04f4c961588c9ad2ba7ef1cfbc50fa69b799898eb0dfe9668260ca5680f91a10d2bef8f108ab28fcab693ecdb942070d2b9b8bbb22609c8395c23d7482c31b69b0f555b7c079d3defaa5fb302ed92619c058adf334e845eb1c6edd903c0de2aedd3d9830943f8bcc5954b65df37c901a17ef13fa75b0f2c8c1d2e38681874aebfe90b463f2cc7831958fdc0de0446991eb3c3612cc00188dfc1078fe458d2e5b80efa7bfce800c6b4ca0e570fa5858859633551da28f36f1ff418a9b7ad18aa89b4612f9d676d5fd98bce6f144cd7458ca9f2bc732a36a4d186ea290a009a870da3c1f60617d56ea7554062367121f3e5e569503aa573b172c6278dde5aa4ccda79d9d8faf41c6c9040c1d1d3cb78b41ffa8a0180395439f0d1b72e42471a9100973ab3bc7aec559d94d2d6402374ba5a584de168395a156324e1e4149abd35c72ae0f79863cb59ee6ba22145e36e0d85d3caf8a427d38c96ce489cd0aea20d7960608c074ce3cd0494b6d6d5ec8895f0f03ce78982ad8fd6784bcf16825286c51325662f34726ba66d3a91eeb598124d6755da090ef863fa31ccd5b08909a3279a35cfdce24d2ba16f42ad280b029a0e27137a671c862b0e6f73ff4a1de320c4daffb5cd4ac3522ef1c10e8a918005535f355ce6366b43a757938594366831dbf7ee72f311be4953edd1ea1c598960745d3dbb7f1e2d882cc063bc0791d18c6376a8497f2f91389a13aa96dab78feca081d761479848a5b4cc2e3d015f343b9000583e95e785a45a06842d7c6c0fe9ac4d70f085503d7ac954516953c497635ac8b7698bb784f73fe6e7f9d0ab9473e828168df4ec142cc1fe18fa067525915adf0764e44292a0316ef3c0a443683c92c4661409589eabd7b4dbd43f54317ae0e3d1c69c35a7868991fa0bc2f83430d89821b91a08ddc2d314a717f5bc6f3d89daf163af73e10c61630139e3feda723feb2edffe6c7f364fba22e6aab75e267065b5e7575946c56265743816b2cf12a106ae21921e3e92bfb7ff80e105468f8409d6698e8660b5b05f3f4bb19a0bd4be3569d24f51795752be74c429aeca5be737de8c01000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 39&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028d3915174a6765df00cf3e10440556af5fe6c07fd18c63f8a54276c42d431cb302040191fc1f4af55098d7b7b68961986fb4f90fb43e91434ff9e8519b43ceefaf0c9451187e3fcd63e5328474e13198a6a633239d41e74aa42760dea1efa9b5663198342583d04f8efe696ed0ef3eef2d592b67bb5195af0d7f22b46676b3a04ab22b713be82a8ed246e5677979f7aa59342a2db735cbeeacf048f38de585323c565564f6799524b2d2cbcf871e7a96735f6c4bb159abe1f0b3e5ef687ffc8c021c508f861af384d97b30bedd5cd5a09d79f5dc3b3a63058311dc2dad44e2c3e3ad36739544b6d60c964a694ad3c22c33584261de82a633e39cdd60be3a12916f74942abc50c6a2e6d67e9c66e6a8b08ee2e56d66e5a466c813530f7493e7ce38a2ac8a625385681ab5f242b6cce26db166446043a499e92a2a6e0a9757d1db721bd98425e15960a8bd79bbe185697cff36afe5bd59ef451524568f75a0bb1b3bc4420fc4f567aa662fc28025eff6b326e8aa7962a9ebd890ce991996541825a9f1ff294fbb97d0d2f11b9eac2f0456f60c4b638491f67afa8426cc56538a5a1c773be6ca5e64cc5ce4672277cc7b275c9ed6958635a74dfd6d82ae927b22b0191b36a4b003df65c4754ebd73eb79607bbffafc7e593760b34b99b69c25daa98fa12262abf86a7db64acb335eed9c0f23209652abde777289b7f073de9ea0f1bbc44b0aea77687329eae6e140d18e12d248b2f8ce0b1834659edf154e2b913885877fb4c830f6f422d44e14588a2927a4599f09dde700620667397466b4fb5b835aaed4291b2bc674dae853cbf98e320c363a31ea9f2caab6e136fb792694a6da08eff4a8ae71d8f2e7a632a31a42148c9b0f8362cf1211814a7a32783149245415b603942ab22a0ce15086c56000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109ab9ddef4bf16229baa4fb1f211bd6bbec7cb0a580199a0449a79203eb7662d18ee0ac9b894faa9c9eae51cedf4f21cd80049ac1c057327a43d6117a3d3a5915d358263ced2959e72271929612617b186203f16fdac31ba915f06579f3db73a5fd1e061811ad07bdf921f251e2bb266fd2cbaac8336af0b4514bc99730110b46e2ca36ced6b04a8c67bc9edfd15c159c30d6760277eee50e3459307799434eb29ae8cc07270d327648ee2deb759ac8061880091ebda7c659cb8338de93b107e5a48378bfeadad6463d817c944d0a8d9e5997e914054a2b64292061611b376cb9a97c133ab90c9cba231356327dbc83c195d7886c77260c499e041d0432e214b70356c37568221fa5f978e1631f7a44f0fe013a64ff2999d9593a45626526425059e7a7801660765ca9f8b8468903d05e02a498266bb250da5c26a4a20e9289433cf3a94e2e37b5a16644b1d50d584ed3c08397d769ec679b388ca1a5280c4a27629f4ec4f593f465db9bc48ba801600b8f95ce2704a4284ea61858701bf06eeda1bb565b3963705a3a71cb7e60d1a5017adc811c55c2983dda3e17ecb362aa24c14df83fcb7cd6b92a89f986b7645955d84f6b97a4c5834a6983472e11a3d92419de46ed2c8687f42f6e9f3a968df0da66b15e954cf9afaf0b92f88471f96f0cbccca5f23c03391b506a771c53f08f52168143d83a499c85016727ba99a6bb8277da82707d67e110dd2a4469e4764a85fc4cdac5d62e67e5102e459412a3700256f2b8424a0217ad7739521e9461f947708f579632e63b244b5e4713592971f5112257cace73a4d840bfdad3d7feab62811601a00e9e3c32768237d7176553ea2003070707b67e762935e8c8605d7ff29d07f96669d4d969d3e18c21a9f3bcac8ca9b261f7bb8f1846d268708aa512bfbd011628a01088c000eb79da9e12c611c5b85d741aee6da44c03977318fa095e9f0408add8455e6b0d1c25e33321527085b867846967998dc0f65b93a15a7d1eb923bb57d1af805260afcd1491a47786a859eb6289c120b8c5cd6051ff18e2201b6fbe89490c296824fae6eb3c52792d82b1408918799cc44331a71b4db01867abd28f82ad1e1718c9d575be51ef192019e65c798316eedcad88329dcb5f96c6796eff1b4b880924c04996485a11a9a94cb9d4804c5acdccb1770a5c6c39f95b1d13dd76a083996721301fbda0142215ec44e2c3157ba51d88f2a2a496556388a8b02a3ed4d77da8cf240a92f8761d9da000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000549ae2638d944822298959f47b2173de7d1e58aaa622296ad4a4cb67ec7ead8220ac2f171605ba2d08af3d6ff5849566eaf96209e9e00cc28eb9a517cf5061545aad24cce143a2ee1ab7cfa259ad9c01860b33b0036f2cb3a5086861212f408c5f055d226ccc77cc884452b2670d89548ec1c6e98fb311df03979cabf725e78956af185447287bca2517f554e9f25e19d93790318efc5d2602fabf262e5c7fc307e5a991e0122e332a803ac4a91b318b30d79394248521190d2be326037a89fe918d139f763dc8daa2c3bbce53f04809f0d97303f2f1b88b572b3086acaf38eef36b4c0791b4918204b0e1e923bce9e3bb1e7baa07135b176e266af174d5df26c44842ceac4ae4c1cff05557da3db8651261be78d766699b1891cb825fa9a418c45bb9f7f2d347f3f92f9529ca6db94e2ffcc69337fb3690f556c5a44cbbd9d79f60aff063de68b14bd2f4b7e8cdf94f6c2f40219d27f71e8ab3d4d6872a5d4b82eaf8e3943a6d425ed04fbc5c7596ae929ad680b245e3d6a7c5ccd7fdfa1d14ef0f72b9baaef05b7b84adc02913ddbc76d5fe80de30527ffad1825ccba34f8587c5b0291471d6957ad99c5fbcf3669b4ae5930c8af68305c2d3e84e714cb9049a9560a3c94aeb95a252f69b68f755dc0e0aab52dd054b670a275bd2bad7ff8ec0cde6224e9a0eb537e95dab992c382d6b03fa045da402ce7c5b55138fb400d9e86afe30923afee82c4528d1b38ce16d33beb47a96c18428d919ba98c9782806d6f4a40b52f7f0989337c724be24e9a5430cfea470d02ea36ca479faead94a74049898d1f1be53d5ab8cc0cdd5438a7c55827131de264aecd18e5f5f2f9fd60e8d2d6f55beb27eb77aeeac2a15432a5f1467483be6073243d0165a6c242fe1bd7b7aa701a0827f286ecb51e4c2626dcbe95466bc94a7e2a09ab334fee3959ca31974b6286e2a2051653341623cf3aca65637df657280b6025db0c0377ec09e6e32010f0f59711a30496695d23728319dfd0ab5f3aa69025276e68808130659d912a53693584188e310b1cacc41af4b19fad8da95d4b35e2569053f553a9dfcbb8fdee1455dfa0e4f5e94324c86a24288ae27f3576ae15fbc8bed49bfd8521d77a61fb523badf0e3cee53799016c6ee4e1e5defc19c7717a5c41ed8fa6bf0e5811baea76676de03767a607735c2a48bede511012eaf1f79e4d2c3566042ff2c63bb82fbb399ce20e1f268d3844bb473ad7366ef86d064c5ba080fc0c01bdd2ad343c5367d80d2a058cf40725268cd34123c219d9109780335611b008ee3f8848ea9d174d7b96bd2fd9a04fa2b550dcf0b301d64c0764299d317dcd0ca05718a1ac008d86fea330095e81567e83bde31a0d635098d7b86176ce6cc4025e8628c73b394d9a45b09b64bfd3a424162b16e1adaa1ab60006847c6d5ca5733237a330147cfe6b9170d7b88834bb79f1fddefcc0ebb1d4fef326e28c41c919607bf12ad112807bf8582933ddb096f1f3e2bcd6bcbd844da317cea2a7688a5fbba14d84c537814ec2b171ade28acf83ea481631b968c26f8d2bf2c5af7d61a93378e1e23fc756e2f0ee79199475ab4ba1fbc55d9adc2b05888b2910049bca98defefe96cdcb67ca9d4aa5bbfc6ca0ecbb78bf29035d158de2a1708d98beb85c70ad1c64b39b387516073e2fe85bd9efa25cb048c224e0ef76547dca67fd66485a97eb5e56c06c78ffa08ec1c9c6f2380912a2585cbcba2cd702cd2b51022f63ec920412989bd743a8a8beb07241e3e8eb38ca14cd400c83dbfa6fc8e04f58529007a1477e9613291af877692e4ca9ae118a1902ae7b4ae7dc2e992a6495cd19df32ce64131a8d8c41969a8bae1d870dd5f1360ba9278d5b76e746faf99d526199e87a4b1d3a5c48a33989f103cfb20000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 40&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000002913920f9a581bc978196ed0306712a1b468354c88066e29a7314e6c4d9412076f753fd3f36466b43be8f1bb3c354218b69f28aec52dedd47e3c9eb7ab19f03db4c95f55a23c8d84c7c472167891f5fa2e2c0988457368620f666098ebae80ebaf2e299befddf61ff2589197be74db308f7011b6cd0f40ea6813a35aa742bb169645aaeadd60c9c16ac2e121b915cac6562e7cb72e1cb96afd393cfbd3ddf343214f9e91d2703f32c81b202b4c826b7bc1baba154d3c53a558f485aed1f8bb18375f4c5090c68a311156270a95bcd85151f5775cea414d0df955d8cd28873579b121260452bfdf2aa51dea9a3ef827cafcaaf1d6c5f607c0ae3ba4c6af6ae24524703f2420d3761c0c311f5eb535dd6125c1f5f192d72d024c60db3cd33f1f5c7603bd6cb8e776b1cc17df0ef356fa0739b026309d14bac0f6c9e4b1df36768ad7e759acccaee7c164dbbcda4d0f5cba9ed7cc65da595146337d194dc74b2135a62a8662d122358e539d4e1f3ab3879445f32c62332b72a726c928deaab519908571e038d26ad523f0f3c4638a35a2e9744c735666d9988d546c8294753df8fec22163dbb0683c2d9620277a0966e2b39765a356ce78d01816b934a2e930ddcbc9e63ff8fc4c6d38322478a1e3fd3b652e01ef8a60cb1460ad6c956a5faac0577d6b86221cac97c5622b1a70d9d1646acbbaad7e77e6d29e720eb536b2feea35c7615257d78beb5ed43450baef14b8e49d2d87b33866c2db06d659dbb30640918e0c9f66656291f78b6ac9253eca3a767a7fca211684b54cc372f290fb237ddd7a6911450a4d89b37b612dd105eb34460793b924681d8995b23653a519daaac5aecd97222c996fe52d2b56bae5d9c39c641ec9418b2cfa2a8a5f3aca36b925cf530856c971892653e525f2623f5c1c64210780000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381095f8e5716b16bc4b346c9a3338107659c35d3aed0e104a1a878f0cd557909ea669190e21e922d11c685b486253ea8b4c8595d0adfe3e2884570c6f2172d8dba1c0c51769f81f9bffebc9ae5e7a43f3dbf8a72af261e090546035b5f5b48d068c5ef0d49de5a499e54a1a9922b7bead05379a45d454f8e9176e649e9c1849c92ed0ae6bbe4afb1794f5ad25d419420673a90055801945c3b928f85675806c9b189e4924e1dc307dc0936a88a6be025fd320d5c2383db1f3c98e5e3a6aecdb091a3d8725d446f89cfc354c1193ba887ab60aa4b6dc05aa4aba6fdaf35e6d6c164cd4790ef3ab592bb05990604a386a861623c17d092ed5dea97b419cea7a6e5f37979d2466a38a1577bd3e5b5bda1e0d61f3b5ca429c90e1e4daeb4a58b4b670da4d93e82a6c49aabace33b881fd900bc516ba1802f97d2c29497429589f43d78ffecb7ba152c53406c7f560ef534c1a5e73d615230d759039c401615d4a22a5f9590163fd7d7bb7c67cb5e157344f6fd9a8ec18536597c9a20a4d0172a593b92dd9778c81cd96c64db1cf2dd4bd5d087abd8b7abb56e2971b88e824bcf5d096dfe86552c26b216fed93e1e8b469ab368d9809597496758c751531d9eaaba0999ba94dd9820c2257d6bfd57276117303245bb965a860b5f94687295e0f822c9e3b8111d086c18d511f49f812f7d4b39849f7c4332f34957edda91d28ae9b50a051730ed627ac4223f94f594ff59d22e20a923dadb0db0158c7b87ed24a9a9c77b59835c1a3527e073803f6a496aea3aaebf670681e3594082afe65b793225630894e7c0d58d0c42344e4ad149d3902c8c5b7e501ca1591939b580ef604dfb2b650dee05fedd65ddcadebde40379239be34c8ef4aacb4aee95e0da2416dcbe190c0480a22c5296068df3ff5ded59466409bc4a79b12855e30f1910665549a7ea591f91525002ca584359b88ee9a913c953493437aa23035509108a2c5b36412163eb5e620dabd0f987ab8ab45ec0e759d7ade876c92900f7e367968c87fb1e63874e8a358580280452eda6f67f6ca36554a010d4254a4f3a4fa2c6951373b190858e63f797b460204b01123a724f58a2958468b94047c607215e3e21ea626fe423765d49be6a581bb239871cc43f8b58f906b2cdb21484fd5619e82900f9b5633ccddab86201d1dc568e78c1d5e6fa6772bfd0d7c126aef00cfe60d44d6dd849ea9e860e674774a9b9ea54e7ec443ef3db785cb2a4861a81aed1f544b2d734996bd500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000056a9d84e1dd28c513987d5587a4427853762b7d7af668ff9ec2e90211d6cf5c0de6c7e54b298c1a6c67ea9a693cedc4fca1a6adc2c6dd0e5bbcee7266b9c6ac8fa8af5e50078a6151f938161f1feacde4d8079b5a9d563423258cf3ae9e47d8e75740314f2ffa63865a8b30743f773a53e1aedeac45caae01993b75c8116fb0b431631ac001aa8bd02e5b83de627af0ccb3a3d86f66a7e5fb658f9226df31095780a6e8262a247d70f4e7c971d108567ffbd7fed0e16b7ffddd93f5764c3e02a61998c32146564d46589538b2e071af86a26321a3523354f4f0c396b863fc8e9e2e3a173901d0d178a9d2828d0e0974b72cedfb17937d6054f185a81d4f853787e6c3681a74fe25faa6c256a9f9e9a9253f98b9ae4b8fa0068dc28bc7e8d5785cfad20f7ddd643dae6a2ddb02713c9cafc2eb2fd18efdeced05cc24913061bdc38e932db5e8181fc0d3de26a94e2138800b3c01e07e83b3b0be187edc75da576af1cc7b7122367effd6ebf05f4c2eeb0ab6e9f91201a4237910a87de9fef777981d48fba28ab8d64d76380911f2a6621335dfa96b331ae8b3242ea1f2a260260244196b0b9596c411218a17d0a58d3b5735b9ad7b6259655cf6e2d0fe5b37d0a0b02e67951f5d3fb277b6e1ec87528b08229ab0ebd895cba2d075a47cc8100e9dd17de7d951bf0a68d710aac21c8226d8ca95ac49fcbe9d493a8d3c7f93fa61685be57ff422fad036304f317a3dbcfee7a4610c8c1ddaa79e37c19d6414f47230e01ef1cd5c7c2ffc319a29ae6a9c95b06c603f2cfc1d1fc914b036cda6cf9a876946983b06123c2e5c7d09bc190647cdc0512f35db9e214c77d3d7d0234c3f2590941236a367700f9c04d3afb949dca2067571bf28e78ed35fc026bd801c4afee9bf31c97580953950d2e81ee6426e78d6f8134ed19707473f0874367c86c9be170be63405a9bf7c46a420724b6ccff9c21b015e21bb02c5a7aeabca873b46571530de56e47288c3424da398517abb6502a9a6a65d4983d97e479941c44cf0136d225991226f70837e2a7d1e9cb1226f40bf59d52c66549bf8e360096954f5875c466160a0c75a252e5fe6b8f1841fe210bf08520ce74d77b69692086ef50bb64732f19d1a49e5800f077700553290635d418168a6b9e3ae980112afb9d58a18b94f972845c309e86fec7e456191d8760a1c2106036e44c5c9a5f2cfbc67d741e8e937e99ed7820ab0787e39c385356ef0f05cd3e31c44115a8892224197b1d1f554d5098b72058fad49c665f716a266cb4db6204666e1dc07b6cfde0ea00345661e0f94a5025d2ec98483cf482058d2eddb018cec11d91eb46b63971ab29367db46137cd7690d5782e3a3ddc8cabd545fc1aad8a9a0a39542aec55cc3d58a5bb5e4a559db1fcd2932eff6e81c8b8e5ad5b4e0424a444bc55d96df63c8971a5890310fe19dff8acba72d96fd3f32d67d41a2f3d0b343489c7fdee7556012c2d88e2ba9d512b71e7d04f92e6be3a9386565271d755bed752c853e4539f95c3287a275004f76b9a93837c6efc6760be4a39b8aa92c7605ac369472fb29e11acad98fc91b1b9bb3505638d4d46a3ae3c10c8dc115c35725f06649bfb00ba1ef214b9f2fe98be2da99ab23e7b9f014f5c5d0248a9e0e088ac175c8048c6beb5108da59dc234e9edfbe603ba912bea22505c2a9eaae766ff55aac8392aea5c722df25bc6c9fcf9b0275df71206a4e5290fc5e71d79928e357400dcb04efd7cc9bd0b86e04bfed9bdbce5787e40fcd6041adda615b5ecf03c30ab9b2809e3514e9ac87226c55f259c5f157945b0073431715e1740dcb319edddd1b5f2763f0439cc0d6ed5867d9d98c227ca3008f30d1b2aea40dc73ff8289e4a21586eff519520f888e7e2f6d29a269c12607d13d398f437cd7f0a07c94ee1e1e3d8518d0c97be1e250d79c5ae1709ad8a638f5500000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 41&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000290391715ba0f6ad0c69307ca003c8e19efbc02970725861c69a39a86562c22fbe2483303b09f8a6a9f9c71257159c663cde2114749d8541708e5831765c44a044a478beb14299af5c5b9c8a0d922d3cb1cd46905411fcff7fbbd0047bfdf89c3eec5bf742b8c1d57d8c31036d13712b44148323ded33728e44defb7e698a94d550660cc732af26429f1d7c8d07e2d57386d3b3e619d58370b48daf95f7af2b77a567b1e9936fbd2aecee99f35b39293a2cf65328acd717c7dacaf96f1e14d995ea44ae7e6654d4274cde749f1deef262f3202731c646a08e7627b1ea862072a300b6cef078a6ddae28bf1f9c6a169ee96ccd66fbb5ad431a5e0279af54c59e5fdcd3db0c96bd0aad217669544922e272f1950ebaf105651597d22edec059c47a0f26f2309065df87b6a3addbf721d178af4a0c1e74b841f64acac8bf4369fbc4ccbe4a2806cd06d775299891ae8119d645af9b2cda17c24fd2e14588d1717d4abfc26fce6cfb3678e91b5510a4aa4d2d46082992cac7959c81b68ff6087921812c4fea691021d562c30fc6a29ce773a2c6464ff44dbbe225f72aab6f0d4aa00cd665bbc3b4bb1fd6430b7ac0ce0eb51abeb7f0ca405c614829a99036f08a934bdbb6580bd1a8450b9d359d916bb6ed69ac413c51fae291714b70bd8ac4cb7c665063accf3695eb495bdd1816bb669ec00e577e0ee516499412549939cf1c6177fd46da0f5feeffb8d05a5a089ad1ebeedb334b28ca482c90524aa2110710ca2690246519d8eb51427d7e8feb933e3e3b8184cfbd2a5de9b53ee9ca129966dcf6097a933dc77e6efe1c957df4ba39a8b9e790e56ed12d4c4e918cb57633ce9e95cd445bc434afe893f6688d94c71e64c995c6ef611b273216118e713835b41e526094d6b94cd4655aeebc6caac572aa96fa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381098b44fdf4fbc81d1bfeb82a898f536031c675a266a950caff647b241a9eca4ac2e0eacd86444ba25986483b9ccdc11a43462dd204a8bc6fef376022e7b3270b5cb17724964fbf69cd20e06a000e52182da92c497a5254dedbbaaecb65f8da30619e4a9c747812b2c26aa090a594765ac11892607217073127025ec1a249ac7851dcab16881aa4347b918b6c0a5f40be129b28ff0d5888654b5d99aba9f013bd5511a8367b408263d319f2d6d85bd6613e8001baf24b9d3646cae6f09555014a01b811cd27ae86ffbba4cb20bfcebb8983d81386b81b2a0bcd8595a5d3a8ad9506b3de8bca5d44132b58a1853dab4290020052671387ab14de3b480d0709a68bd7e0108aa3c0a30327aa8f898c0452014aa12f2abe45dcd90e02842340936b938614b5d8eb01be448a427132518212580010f4da71b8ddbc9779acbf45f0b3b03b279eba01c1755d9926b08162b62e849f68d41803c998c9463aef9959036ea1f0bb509a901c3d28feaad2215d0b311176eca14b7cae6d34d20e3186c020f9865e3aa1fd0872d086d776e2a5a38ad0c291e0ee5b2d5b3c8e76a30943d8e220688c68e8db56618cff6b25636c761669a0acd6354f81f466fde0d66efa146315c9d7b710d7caab863835a47dd5a358d891fdee1456c7ed35a57070a3855f3b1d3b63f15bc0a078369ab8dfec3fa2f8014f14dcbde0d69886a304433cf9c6a4a358a752a606aa6d325ba67c880dafdd1eacd782d5278c0ea5c5b59412925fad811961a7bf169cb9d99b58a3332da6d9fb86e58eee1835cfcff753d892d6722c28b66192d9355fae09a146934f53d0536e44670edf6507b91af38fea713f78436a05e25109d4322bb5c4a101a2e7263e41767cfea0e39adec3460dee885346529871c6eb7987c88664d7d6ea6dad0eb4d5005bac169ba56d85bfc00eb23ae6334dc1b2a35419e2ed8277751a45302c94b09e9953935f4a2f8a2e7b302f9c98844ec3d4d312a7006d8561d7acf5af2c9850b164146c10a540bdc33a34b252a376142f0766890ba9d2552929ed03a7484997483326ac8cdb3b81c2e46f239aac99a7c17155432e66d2a44c25719aa46eb082dd2e83d6659679174f8d7059b1be6e9468b5ce1b511c0d9119a0981195ca9a46c354bc2027578eaea75195b892667e3370e30649109df40ad020a8505d5ba4866f9962c76ab8a49a58e059f6842d2c78419a4bc7808691bafccbd122a03290771285c0530582d247c00a7a0dde5f59d7230100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000058baf2860129c08a1a9c7a7bb3120b3e40afa1a4a09050c8483e7511fabf3285544d4ce3f41401dab8c17da547f6777a72519f6eeaac83016fa0e0fb0b33329dd02ab8eb1f291758074ebb5b7c4c102b75ba422821e6755b37b914d689d84808a89cf88f69a446f489a260ba03ca52a4aa14e8bcf4bfe5134dd2918a88d67329b9badc6ada4a3071fd21cfc45235fa0a1b82d91c5877f10ae087464251c8899732aa7fc8f6c0a5beaf4fa41e64ca97932925a06e218272500249577705804c6dd9f0f61dee6aae096be0ae5e67923137933fe4d61e9a88dfd5b3bd75aeeaf5018a5153985e2837ad1aad5eed91620d935eb9982dd2364b5413f490bf251fc783503fa146300e6adae0682e0597c3839c645dbe855919bb1cb80c3dc6e233909017bb31f5adaee05ce442eef594fc15fec3a2b4b81ecaad1340b0677f27009290ab3ab8788556389047f63c2ce9390658e151ca85baae45ed2fe12b6667967f6b772ee683ac2e7347c7b0efa332b3354b5043cb86200f8e4249f68030844d00a86faa7b79a4129ad676d1e9d58828a1af4c6bd68c29cc23002e0a0313500ba717b8756d4a18e41e381df8d7a999a153876db876ca4a508486a4f331cac9cb3e7c416c6329713cab76e1c8b63a8cad46f8eb1e65116f89a3b4eb8faa14a73097ca71aea3220be7fb7fe64919893930445d962c309e23332e4b3ed8ca768ef0ed46eaab199827ad628a1bc20ccd9f61bef67f7fcb017300ebc7493a7ccdaedbfca5f91e80b80decbfd9ead9bf22fe16b563512c7383d34801c504202d7a0e19821ec8495016362edac165904d2bbac484de1d4112c3a3e6ea56a78785b7caf2a44b5bc8becbc50bf4b521c1d086086feb009c06acb8fa0f53e7654fb02ad7898e35e5f3a7dcfc50124ba1f30178c707f4d36e4e7758c4cf82747753cc30a836311794a6a9017f53abd17a1c9647ab38ba56aac83c1812dee8a5a75c5cc958780a3e9c3c1f39729bd365948f7fcd8104cf09660060fbad2be9b8d8e5bdd22286eb0bfd4010681ae7928d0fc008e21c8f877d97b5b9c7a06c02530fbc6a9d6fcedfedf68a9682177757cdddffa6cb9086b8330e61851e2761d84da37635ea8441e3b23fd165ccea562b0a3616b30ee5fae00f76d6801b22f2215d80829e01db2c0743e3074cf26c96b0eddf97d79fb9c7ffe9b5cdb891f9e61fefe7e1cbd28fe25b7858921c8c99c45a84b50a8233037dacc20beeebb9b22089ddaf2ebf0698498da694f75ed2463d09ba2c757a986b8ca556cdf46cbcdf288c078041d497242f66411f47f35a21918855f105f24686076fa21bc1283f17245a7122a848b4bc10d996b2c5161fce0336b2ec747a4a07fa9851ac5423d1efc4b524e795b2e4bffd1c5cd21f5fec954824dcc53bc3883a7f571a9323dfdd2682c4a4c54e8862f347c9a8897779170b257ad26d90121dde722a3f214a44cf6c5a5ddb2452a2471ebe7fc8d0ef7f1edc7920cb42a71e4db49a0168d51843f47d17bade50dcb340e5f7b7e5b6a6c3afe0fb26b5ea172a4011eee838e5634e521483c6edbe9994b0658406ed8f4998c7b4e869845cd16cc4368da3bc1b025a6ffafbf540133c372d452dd831dcad39d61cced0a0ad193fa9886eac749001e3bead5a7962275fc62298a1bd054f4bd97acab2bbfdc355c73509d98b6de5b4cd774bdcaf1398532bb3db56524cc047abde6880c3b282fce0fb2ad7e4c5f7bc138b48d194e8c8036df4b9f3949e912afe5d2734662f27583193d0fba2b73c1a0d012db853bbbe4383f6c391f3220e1b5761c337a054fc9fdf09c01864b87324a90c776efbf5d34a68dee38ebaaccbb61b4c79a58cc848184f605d43cf9d40be90c1fbcf6735270132b59a636b16ed28111246270af32ea2cb7a42a084005aebb6161002e65b37217361bc269f5ed12f7d50613c82934a6d1d98d1308ac82827b7504f3fd351e0aca1c62843c9219023fd092692ba4b83be198ea000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 42&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000291398eee9a1420f891ac25675966e448e6ad97c0c4e55ef0a40af3e2f918395d86215e944bbd2e270f016fc1a08e2a3df1e2743d9659064666dec62f6f7509386e2509561ce024d04433126572ad44bd10a2b7e8e37126e233ae7ebce7bd5bbdbdaeb36aa23685b3aed81ff899c2c68d85652aacfd34f6a470894804a524261bca3d61ec629152ece0a288f7d1aee1bf8aa2ad668165bdf02614a15561b32eca86b5ff857a87ea4a17ae9f395032ab075eca60d8434b89a53c2691cb48b6f4eff60642aecf6994ce07d9679f2eb3a42b791b867a24534ce3968721790d241d1a52192787698440e72638ffc5d9d66548b9d7fd28a54ebd9a42f0caae11d3a4715536c8d0913c822929338a0645e5622b9a75945ad1eeac93c71fff75d8a612af3f7731d5da5b96ffac1a132483a55c5872c79c34508302704a6318527dfca409bd249972bcc5376f135cbe761a7523be7cf6bc39bac9af6525b93f9a0937db609edc96fcb8287f0ae33691ae16ac83622ee6525fb589e8d61953d6dd54bd7036dca6f1b1723fdfe568e4ea308fd41fa4f73b2b4b3996504834e5cb130cfd9b5fd159ad2c3987444b9e77e088ced314ca2e75087985bdbc18ae230cc0d7734d6c6f59bbb5f564d298fc07134ac32e4d21606310f41f4fb7cfe37b5acd37522d262497873a82fad531d987e78659a39022612463b2d1afcecf96a5b40ec4da6b85297997a9a3fbb5fad8b533d530f41f38392e6334c88312bbce57c6559a85ad1c477592f8f1e8179669d1dc5c2510a78d44cf54db497dc38edc511926a16d256a9c15346d0e4bc96fa5c55b58d67a60f5f56c70a395fc5f380d0aba909526b88b39ebc11f2e85d50466749d6140751bea2fbc81379ab2f695db0c3a2fe56936894333807d729b2fa78a473bc0a2f4fc54442000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003810998dd712976999b3e0e5798c093e04c7ad7a0a125f303e56470adafa26248bec73faa6283518c606305560ca2ea8b46691b7f1e2e9aff01dd660a63c8bfc27078a2f9b089eca92a52855a076c2e51f2daf2988cb65b22ae11720afb02d6f2e70a248607b11c324f1d9471381c01349e330ea4dbdbcbe6a4243e288821da75bc5ee094d70593297ec3d7ac6ed5524dc9a83c563e4ec5f02225e7ac5a74a41b76ca9c69d474d8e70c9444ba8c85f0a8d444ece795e4599b27da58507857c60a25fc58900796045531527ba92e280e5915e48dd78b8c0fa678db12432256911da24f150c060a40260452ad317bb8a2c3908ef067a1e63b8f14849219a2a7a57a356871ec1b53cc01b610e340274c920712409e435417807a08642faa891b51618b256efacab2c70624417a50786ab0ae4c58f88814463728c7787a544891e46b741268e85dddc8080d9e76a9e17c1bbd02cf4f3522faaf23ffa902bdc5b00ff72f22e64376895e128a2f466aa5a97d648834a7af7fb94ad8a721a867bc4ce465b68f890d250a0442a44417b88cea40c90a4464b1bb6b4d1359c102b87a8a5a61210950bb69fe24b2df2b7c6b8054722ff5ef91f5126049a901a45f670e86a431914139d9dbb9b0d47927c5f28ba48f457fbe83a330edf8a7c65a050a57ec900814757eee81b570b181671d9f4e3c38fb96e88ba9e902a02328d68872d346b49e2d55698417229c0195adbf4a558f42a7480e4abe20c68d309e7b7de56b8bf8943907413e0925e7703bc65a7c00b669c6690d7a48c6307fa0525e7aebc70c5d4b9fb1259adb1c0d0d21ed28418ad3801826c6b60a8a597c14f718c44b6f351db615dde738926aa58b896b9950432b9344d48f09c54786011836f915fa46d6a896fda3b553579144c6f5d67e01b2984d34f2f5e31009ce6291d42cc73dd2a3770d2b5b5de10d25246abcaf309c38ef461ba17096352b600c1479fc7129e857ab91d86b6494ddb07c1c0b3f497273985a22ff11bc69f13ac4048e19479869740b9be67cc4681645d84e1fec140424d398929aded092d557020002f1646f91af42c743e9d8ad09829b34732c5409dd03fac8953fbf2460284c9d8e753afe99ee2040025548894b55614de4585725ec8c2ab6f7528c9ec64fe00af65aad051b8a18ea5b09174291a1552a8da10d24b524eacab5166d49c4d314e14039b4553ba22f2400333a74667a8aa0215b301db0a975d69745949c0ed9c3268fcf523c2ce318f958e40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005aceca4505d43235f274d902464f4e763312bd11060f908621a063409eb42faa6bb5e20facd87b8ff41767c20f69b1f7e05d5f3a957f48dea57dcc91824fa48da6ddbde7e3327a0a8d46a47606eda01e67cea1f29bdc5fba446de60541dbed6f73d1fc5f49bd77d45285d3d8ca93f6df25aeef9324bedb40e800acb49794ab05e6d0aeb11a5994fba36dabb9559cd93cf522174061c116cf31874a18c46689fb8c075079dfaf73ea0ea7faadd47ad8ef68c06af9738b41be771020fedb79ca3d0165427b58e547105fcf82a12b67579d1d3aab29968817068732cdbc5a2e9e8d55d17468d03f38d564f5ac6efe1538e4a680e9e15e35ab54d07b6b58ec9ea7815ccf29f4f880cbf1946f39556bdc2bbc78a5134fa7a086ddc146ad9d503a4ca837e0823bf0728453f6b053788c69eff8d11acdf5f07282a75cbd17f2aed58e39d862ff056df17178625234ca7e03d22aaafc4c07e3fb08f4297b511b10579934d2761fbb600c9454ac05fff80cfb93de3b9e0ddd0ab1e494de477da2b5635e48d5bed5ce359e66a3ac845826be2b4bbfa6d825373bb2a4e93aa417648d1cea755aa4978784d6d9489f6738b4da03faedc659408d9395c934af774749a498b1406522351f86838865f53cb0157247484fd37ea59ba72ff3226aff1eee353abd34ddd63fcc89387b947027e04a6f4ecca1ee5f6bd1ca758aa4f796fe839338164b58d8e5d71e6d5cdeef6b279ef15a7bad873b12f7c5b3e2817c37bf00802d2534d425d52d0bd5935bf8658e5bd39b5268cc45d0f27cee5a57300f497e77af5268970782030e6928281379cb14bb56d2acd963d189c078c7a60e98a782f9483ece7b4871a061277186a01e878087381704bd72c63c32cbf2470a561c22a5dd3a1988b7ed0d274182e1b075af277920b362d612dc7ed82057ebfe51a3ca5a9a9a45de015c460be6a48cf67c820813048a1cea0fc3d7307f802b4fb7e523e7c8555fa56dcf66237f176d3d973c47f55af93fc4bc92b98b7de89829b1471dff53b649cb03b719db58daf824daa2de570df6314dcaf5b705557f9d783559277a754f3cd5b783d5a577ebe4a065d320284b01f71540f1986bcd443cf4fd480dbe06ef7710387cb5185deacb5c2a612bca275950b8988f247c4b773d8983d87f47d60f5bf80e6e7baedeb14b5ffbc46893a81c63f99f511d3e24fa8f7b1ba66a7db0c1d9acc6b5010ad725bdc2282d8a24018c975c8b12ed3326f48194d4ff93ebf051204cd224ea39f27d63fe07cfd0162358b412dbfd4715ad049ee5a31638d3111af2db7952f3a973646612712a607ea35826249d14cbde4380d8bc986067b1cc27503449fb128767986a406585c3d40daca75c27bd36117d2487bae82cf639ed1fa016add279d109b8cdae59eb31e1f006cb7af000a267e8582e55375cf6f06d1a47be9bfa21c8428045b9df96808ad74d054820a4d0873257eb318a3dc9b6d9585d973e26d435345b4d699a952c3092eeddd975fb59474212080d03ec489c695f19cba4d1cab1ae8d2e2c730b06e657d33722d24222ff7b613b6e8608e8a6003e11c80239ff431b5d8fa52b84b867a581798833590524c7b84eaf6cda9ca94c5ab8ef55a1262eec5c37467807c89ff7d075606a3902e7247e9c6646839c18493584d33db65d6dfc0f23e68c9d13fd57faf4836c28926693dc3ee372de27a9d3e4ab4229425ef48cc410f1792a51c9f6fa5316a1d9a7c99979884ef350b4882f6045921ca88d4e44b435c69c1aac11660971c2a3f6480c79e6e146c0b5cd2371bf5e7486ad7d0be88d62a2ae8f0d73c17cbac86ff6bda55a880b182a5237498e9cb343a9cd82d7784b72473d222e688d13cb81b2908bba854b9624a11dbe8cee9c3825c1bfba476b4d23d0b0c325f1c498a65a3589ea8e8df8dd9030b279ede30443cf80367ceea4a122dc8329e5ad42491cf57ef47ae2b15f9c54120966b95acd727a4a2b686b00626bc808f43d82d20deebca79b074a7bff38d2531ab2f726ac7087236eb3fb4bec8a2d4207dc84c0000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 43&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028e39ff96836b9dde5e1f7467b4ed990dbe9b1ae647cd9330fcb9861989e0606021ecb0a0e81966905669d59ae2298a03c92b53a68d62942ddb3238cd5e1727bd8278d3481b0ffea6ac8952873471d41914e191e69d234dc5b0b3b666225be79b9e681d10d64e5b9e259abfbf63ce72d1f7477234c7d9574051e26557242c6b2d883598b5534702b2dc3e9c0ae2099d1d1e6c1f4096580dd3a7ef881eee9e3169c37469f32204d5b228c7130cc52bad7e773910f633064ba2428c4433752b824274aaaf7f31ced827f286a28ba5a0b176540c9cc09edfcb7be74076bc56e8cba79b0abfb10ccf78e356272d2a5defcc889cb7b3bb1751d017d66e942dfddde53615d5727c9aa61934b8b608df2ef8daecb6335d2be970a5ea46dc4294a3415357bc6a05bb217bcf7b7c051fc5df317d1aeaf531597e136f250a42efa730257b61be63fdadaa42ea2eba4dd731393af5321d92d09c756f43a6c0d57ffcdb2acbcef365f0c43c4b59df560533a87e3e9cde312a3f728cbf978b99c72edab3cfceb4ea854500d1c30f46f11a868a69de4995ec2c0aa346da98d9d2e0864971d21a544328d04fb6158eda9f7882e59a1af9c743eeb87f943b77f6cae27e78b4e21cd29bbd9c995b644c2b7349cce895430fe1d8b47e0551b8e7208a937a7eb49d58d7d12b78e2324670afd4e03d1e23b3b9caa91a6cefcdb42aea5241018926fa869757b853fa0de58945de67acbe2a97c35c81f546817a9da608c48452f11673f39bc5a8b02b2306d2dbd36755d8c969953c71c55fdea63f73cdc1b7de3450dca1e69aab9b3b568d752e40de66252efa187ff611b45a7528462cfa696249f84fb9f45f160c6df934b6afc45a4b7a23d2d426a8bc1ffb66850f81dedfba314d4a41377be7116e343cc86fe279c9d34747200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381096a2243b6c6e3444b6eff96c0ceee038da453e7dcac5c157333b4ef8ba8559b346352813e542f49c060fb5fa509ab4fc84c3858b94b6bcda4a45d5fa2b05b3557d66c938688a1928a02abc8ccaa452ae5391349e0bd613f58b148b25c10ede53b2a8ba83de951d66ecb3dd52019506b2d5f3524e73e2b7a11c17507aac168af34dbd1a38618a8f9fe62068410662950778d222db4bd12e1091df50caa4997b1c8714c19e2d92c55a0514a7aa7b20abf3515f038fde4bb1e2cc4a18d51361729b3222825d7606682bbc6ddd96a4488d983a4445750771043d719854189219adc0955960b4ba0eb7e3b715ad63a41fe1c40d888f5995247b681585ae3b3256e4fa7b32b499a4e6334ae42527ae8b365e1044c8b75549a3d54f64a5ceceb82c928703278b602dffb7a50f1505bcb4897350aa58a91c7789ddde26d84f3315eae83b293cf13e81f8b5f56af3384e502169077b16548e526067c967a3fb779a7988f553526d948ab0fcee86813c7549f3d381742d15317eccfc7dd541d333619aadd44e57fc055039716d3a5ae6287d563a23a5e41e64f06a5b3d2e625d11dfc8c10782a9d8c404a8082f55a27336785de94850f6423ceeb8305434c16506ed4fbcdbe32b93168e263c92d51fada5b0e812deac4f74a898c52c239848e51146fec4d528cd76d0bfaa124c88b1530e535d7e76dbf7be068b060ecde661c8902a4d47a033d834332955e963047c08629b680f46c6bc4669e40724354e5410905994b3375edaf719464f71dc7aa464c25e8c7512a0dd5de27faa5ef410d8775384f21b7ce23b7f2aa793f352561c4ec6d1730e447876c30b769ca63a168fb5e0ed6a0e5d9a8be48fe756ba9ea09a61a711945a2096ecb821adb1892359dc1b0e10d7708ebc2d4d715619d2c75445ec378758138f9d88e5d1a18221594973c91a436594a339a3266d864601b471c6810256ed61694dab7082fecac7cde7418ea18966634cbe4dfafa6fe25a5762deca60e7447a706b95ffe0e35c8e4d84a068767696f440932dfb894e7911eb1f44837dc8a29ee48767d1a6ba816b7f2e303ca1e5803aa6da4f5bec4569533dbcc80d82fb7350dcc829de8039d8cc372c4f6b81e48dd52f92211efd76d583521ca14e015479a7ac93641e7507d585365211b24f41a04008b267a5c5cbbeae13029889d001c95c4b4fcd1f4bb85ea7de2df5aacd1a33a6a5a66a7c57e860a1891b4d78e77c017aa7090572d09d4d7741f086e34db80f76f670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005cd96e2865a0e602ea4e3c5657a7f761a6f771007989ff885261f5638c14c1bf80aade34cb956d2b5fa1ce38fde831423201d3692e8e6f40e68a68c085dbe3c4cd8e35394f74072f44de98a74e42c9176a86ac06bed8c0ca937db4c3bf92371106b7a68ea8fde1d1e082ccf522a397401ad0f8da6c82bf76eab8afe101c7ff023a0fcf015b40ada0073363e7cb25260c18662d651222a4ccf1b290ee6f7b111b9a963211d67d7674b499449f760352feeb9fb7265a5f2f7f20c0174802c7f48226d92620d3e009e85b104230c21ba2fb0012dac4bdf9fd184e09cb3e593eb1f3eeb418a8bf3173e6cb91fd8080c7e80dbe6730833a4a9f22c52716731c7cea4f70cde0f81d2d9aafb6b60820598a7f6aa1b963b7686528e6e7885ae085c3d26c4acbf9fc15080d972ca841175b343e59fed79ae3cb4dbb4f0d7d463bd3e0c4b2090139145b8d7db5db10abfa51dc909c5cf7809030d72a5090cdc765eecade2b365f719127548ca601ae0d21e402e18050acaed30ee13cddadacc9373a87a218787b585319a7e66fbb13851f7ad0d2bbc1efe6efe4f7ed248d844f58b6a5a21fa9295e0044982af6286de296550f72b5e416373f1dac006687ded1e7d40961e5177c207579f25e77be808a6ba33dce8a2a6f88e97ae98ecfbee5296d4a170e3574d9ba592a384cb0545bcfc32b3831c0b736ab77440722299f192dcad519523995f71f2983ba87aad2261e6e01c19dccae00f8d6914501d1ac3d4aff0c12fa125ecdca34dcdd8407f0045f8e8be0763e19eb007ed4dae36e30afb07f8daa7431b72f4a0a8017b3fde27123ac3e8ee575f8be310f68f81b696db1fe63ccb8d32b899b209b2205956d209bd6e48166bbb4372a607e83c47698db5ac8f9b40d05f38efc4a4a1309d999d5ce1e1a5828d56eda4666995897c8e6362d0b5054f04bccf79d03852d1003c80ccd55e9f4578d8bb2c8e220a4d7a4e2190024c85c718654ccf174ac96c1bc50ea49f961ee7697c88e6bb718679f1d1f1118376b31a4b8c0471f6d7aefc5ab426515d1b2cf0eae66246b3c4132a63c63d7e33eb9df8d8807215d58f46ee832ad3ec893d74e00c73510b9625f62d4eb5b500eecdbc7d088d3d318077a4a0f7d64adb13220232c08da75d23ca7b20cb109c972b7c159863991c32508339558b9383ddfe7e7dda740e5bed0ebd14ed300c634db01f359f81a7133669183eb187c17a2c8ab855bfce73e34a1f59adb0ec39ec0c7573ad3620a819333ee79d5e09cb8449f91923ef4c5e21549eb7f56075c014e1c3ad2805e682f07ba8aa265745cb600a460069678745fb9638f6709d62d2dad8defdd5a4d0c2ae7401292bd1da5f40d4cf5d59a403932ffb677237ad74691cae29fa31b955172efc5e83c225f2dc0430ab0c909a97bfb468ae182ecf91e9026de819f3440fbe69b9de26f812ff3f3ce8037f124ab368b1153c1cc127d140f754c525d4799e1a19d93b90460e6518f0b6936dc6310b7e9e6534b595e00225978214ee5aeb12a6f45b5c73fe86771818843ff7a6b88379c37165d9dad48affd6fbabd11b1fb90aa5a78918b317c5f9b2ced6b9647f130da9f91e1b1ceb84f6e1618248f06d654e159f71033072f1517064bd96a5c138402771abe7f39f53a798c2423b748eb7f310485d6376722e204fa33b9740e7fa68364289a677c5c78a19a7707d2549bf9329334478c64351fea1634388acd4be57e4abe9374a0e999b770cd81b1bf4a8ff300c297b116ceda1a4a1c1bd5a2275581a0589a46142139fc596a1406d16293076527cdf9aea2d0919f9678423b7d95b153dd1d9d62b72a12f6491a36604d19e7bb83c476d232769425557d3480623d40b7ac27c0f67d4ed5ca4d487be915a68352dcb03a3929a4bb795248ebe2fbe0612833d9305a0a31d195718bac193fc59b880042a7f61358104a919c7e7c210f02a856b8b1057dd8527fd4ae1ea81f9e1bf7c614ed8a312c95154873f86632cbd60c65176f13cac695bb4c23675331058397d6e96e4f9deeb859e3937553d94bede3c2b9a5ebf00964a49ab294bccee09e5a97381d2375941aa775a47f726e900000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 44&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028e39bd6e6021669a6e817c52541844ba27f615830e801f444f6e9485576c4d11cccb744c0c620a6259562862d3b97fca9198551f09fe5d3cd8c3a4b5f6d1d37030ed7545a4ad15847e61507298e6ab4c717074834357a5becfcd591cf0c070796b84e39bdd60c47d8b3d587c66ef6b1679e135f7137f62522a19ff977eaf506bca79b2f8885aceb965e0a91bb1e6c31d231b92225b520ca4b3eb67eba2d722c5149efbb9c907b50c91be4e0b7f8278d1ee426379f110b521b4c0212f648e971c51bd7448d0da3bc84561e1d7d6640de772c1075c5cc862d0cd1f5766bea9dca984f6952141abfd1ab762a129d1c091e628cc7325a686c107a0a5ac1f5a328c8e4d6372949bbb64c1be8eb8f0adb4f0e6f49cd8bec64f78c61e5a42e7f1c8268f02e47db3ec3f421daf458778d7645ef8ff7778c6c9a5af119b4c4cfae552ea3b3c2e1214fcd1bab78995fd3b7b7a99a24f8e21ea4e1d164a317aa7f68b05562c0fde7ac0af609663738480b4f26b5117a0f3f0b1259f21046aea70988cde09816b8c1e8fe365ed98ba57b564e0092a7cd96abe940824f1698925be6e761a4fdd8b6092ceecc064e250886dcb3ae1cbce9bd358a108e67e33318ee26a4474b34e9013cae2b2f245239dd58f6a0bf49d84460bfbc481cc13f53d99fe5613ceec21e2fe41ceffebbac86f3f122215aa3258117d45b6f91b409af438b896c3ded0d3dac639b1a8eef8927f4a1354836411368a1acbfbd08eb5d34bc86c271b018afdcf3b0fa6abb38ecaf774364fd2878f4c89cf3667b7e4b1a9bbc9dea131cb9e996487a55854ed2aefce9475b68af7407bc64d8565d86684bb6de96e02332ed8ded61e774f28fe1136848f14ce363b5374e4119dee5b0860b72ffd2adef3c2b34681b64ad9b31344ee5a554428c72ec40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381094cb918f77b628e3cc1a793fe55a97f7a5053a0ea6348c814982960cb69dc57cbafa358b2aaf4696e94d4612de259576f715c81e909310528640c27b2a95a934c8e2fc04b822e3ca2a433844acc6c1602510ec9ac13f1ad1423a31e6df1d7b5209b0aab607667951e6d1b30e665146bf4b1c619f7f30293bc6ea9717403dc3272eef3e95e4b824cfbf909cd10b5da1771c48c6c0db44b46e55ee11f356c466b1445951209a730026d23e8506a325d219578ff8b73833e4acc5ef82ad971b63145b2f6e2ffbb199e3a8f0c204f5224645d4b077cbeb79a3426f51e55a24ac197258f4e9fc31d520c1da2b2628adb49982060bbb8169d36d650f8ce84c930f97728a6e001103cc1d919ec2a064ac1631ccd0560c547306156c6befd95485bcc2bbd8de2978fee34806a4c71b1c5dcb7086be0162182363c55fb052181b778cdc2b621ffba7efff60291d44566fb120e621969627816a4e27a6164ade4a9921217955ab7dd0bde673d84b9bbe33fa7d86534ba6244584e5af9bd6da16f301aa67babb70be24e271727f9bfc04f716b92a6526ecd03a61c883f26c2a4d9d71c375a88a496e49e46f9bcc0f1425b94e84dc401d938766974b17c0ac0616c8d9aee1b6820d2453a6161314b316f611997fcba96fe999a979d4610db67cd534f0335ffc3db478542fa0e6b8698ef0e89af722a802ca3f28d96b94eac1fb927bb008bf39855d410b809c7693e44d9a55ec96426cea789286ba6e9de742e9eab5d29e447c2167c8dad21d1bf420c3b80750be94c593c80d8f1824fe134e1efd1af1b73646dbac281458f67bc8ab3a0cd36ac3d2e4a0006746c9d7d9a7b20421db5c1c2b756839472c7800d21d69d065de002ca6b26fdf4f046c2086056edeb9e17d195986d56d4d962a6468665c551f97e4cbb41c5dd48b1648e87ef434726e951db642e2f934a85f659a81d01b8d071249f78bd660ab3a00a677b58ccf820e8027f748d88dd596d0e9a2381ff473135c61042e7c8012eca88b042a5c09128f284c2c64d7d5ae909c0dff16ae4521243259918e96da50a592dada95fb9fe562899a6c01bb752ec44a4cff27801842ada26e2ca8e3838c27c93a744056f551010ef863d5b025db704cd8201e5db2a4fef0eafbe2e8aa80ed28780635b54c8715d4897e106443a8d386c51728583235273e7556eb69d3208047a95c629cae192be9e68813ae01a7462bc7382bbab775a65053911e95acec8b8a8c98861214c4caddb96be43f10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005ee047e2d484d798b3829ca6037d6c1588a2349de09c5ddfbec987652cfda01454ed791dbffa3d9da13a35230adbe1b39b042e3c70589658a03f75447c1cf3970dc10fe5a4a9e980f2a33b642b42e5e66e9ac4e7a56888fcd72913a79489b5b163bd37b8c3c8d242ffeb37d0c1ece21034be9e3685798c2ebc6b809defc02c6f0c2a3ad70ec0bad12d57add63ec3584ca98e680267fa514b34de4147c9d901b59914d49ce9e0f885855ed0ce7973f3307b675408f90b51c6a4d38a414d970eec989cc7900d7723e19acc4ef743f6d39eb1b563b8c13d42c0056b6c49732854925b606467f7bc662d17b924fc65e9c3cdc2ae73ff73040011a152b05ed7f96b2ff4cc39a22484af72812ef02b08ef4dcb64c8936e74549afdd5d876027fe2b431e61e52e8793888473f4c1e5c1bed2c4aef8e5e300a735b302474fc6f54869984f1a62dae29c7c9a0ccdecaa55fe137ba14b5c5c121e0c5eb33b035e01f3415529e0826b27498d7a71b0c086bacd140c02a5948aa54799d0dd0ffd384c7e68578247fa28d205b18adac94f7d3c8acb7daf71aee347b577d97ee8e7e865cf4fc1c16640ad1e9d0192aa13ae81a71118408e145b6121abb75b4bffd1d403057d4ad5cc730452475a7f067690bb81e81e17ba8dbc31059969b20d387ba59ca8ce499e59a65c8583f29cd539f4f75ddcc68c7bbbc43c849802d8347143e2fe78c1ab6d7ab6ba9917301c88386b294aac995c24ad680a8c3bdd7aebef21e84f5a1909a2d83a8dfe46a75f4b2b47614cd39bf3ca3460de9bb5c37eb7349a17ab32214d031ce927806fa394470f407673b0cdc3d9a7e3749f09ca895d464a4269682ce6ddcb8fa0ec2f05372c73dc3d06fa6f58090efbbc6d619a7a565d4efe441ad7e018a7f5e1384b88eb4506fc54e0ab0a8b9ee3641760ffc08f6bda78c12396473d1243baaf6ae10316213115441c0b65c7e475b4e1578d066a47d9c6e92fa32d0f2c365fd15f5a2e88a81691f039dc642ecedb6652d08acbe64625b46083ce758fa96c142eb34477e065aea04a45ff4fcc3e3d146acd7041f5f7e4c6b26c8205be7b66db46da55556ce02b48af55a4710bb28b8ce102cb15c1a4af59d9a17a2dda6e2d1e96987f6aa9f4216d8d5e5cbff7e2cb775e83a776063a4aaf937bf0ec84149ec1a7ee21f735d21625e85831b80dc11ebf04f30b13e3a7e4d4784c5f8c61c679e0b6863958f42ed31deaffb4c272a3731c1407445ca7673d225eb6509469dc6c1f0af43eb00f18b3a210aa57d51169f2a9fc251bb338ed4e9ddb19282dce871211d26482e13a8d533dee00d36ff5cea98dea72d9f0b32dc398a3d5537a3373058faaa3926c127a1ec739faf3d57cc1a05d578074a3a72c3f2b1692c2ba1f1ffed943e7bfcbf1e664c4f52f7bf8d86174ca8910c290c06804a7748db21008ac43e653d7fd7e0c982eda9356f68ddec26473956dff281f7b767010c57f4ad09a05063a6b3ce078dd32f3de1f40526c06a2d60e36e2c70502d5bebfd2f3bfcacf8720cde1657b9892406baa3df01e59313eb655b6a545331eba01bcdb9c99e4ad7fef7438ae8715fbe589a2f99cb9ca34b9610b3ce5be38fcf979240698174348417420aab069b8ad5f646f82958a136dc9f2f81e601056bb4ab5e10f4ebc4a00e18924c51d0fd104078471c6805c49d92c78c832ec3f10d8966e19add3d3b4516e12daf4f63fe6bbd228062db743d1f867800854f7bb7ffc2caa0d01a0bb683e368673a8e664bbaa17a8c0c04bcff05246f9c4f3020510a992ef26fd0933bbfde9d042862dffd33a6465f590a2287d8154777a89724fc3df9f2f1b1ed8765e7c7b761ca4781006822065703ade07a6e874e70928e1aba29ee490690d24f6e73d96b85fb53abfd1c1fde439279e08fa232043b2344b267cfe5901c60e7ca14b0c85edcfa2ab90f341821d2b4e25fe23129f2432db932f23b5957706a433b308fb918d1c8d81eeb399babe95e7229ad41f30460cf28671a4508b0bd1c61f48cdc23587bb9bdc6f565e76c86547cb71396661bec8c7fc2223751f765c91c45c674c36b49aedef3df2537f888904b507edcd89155d40cb81dda74376bc9cdcaff8a368f1086c99ede25526bc53f95f4017000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 45&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000291392b81249b15bec856423c0f967ef642c3b27d6e06574442411a793873e948c283614f9f568319d4098a7524ed5945668cd5b0f4ff1b18da4f1597af0d2fb979f829ce067f79237ce2ee1ba0d938cc4d092e28759bcbaa8fb0e61bae8f41cff73de088a1b12f2b48634eb6d7bfcb89d3fedbafdc1d92e3313f8cbf6e95b6a44712043cb9acdb058ba515cbea60491956a9672b244e367b4db666331a62d883036d947375fe4482db51487dcc92db90428852c339d162ad4604e43ccdce053155b5785271849d6004b76ae95d90964952f34299c2ed5ac8f3584a412c91f5f87d79a2591f4520750ecca9b821d23294d0320c3371dbcf33e421f893b13ab70ad688b3090c8a526cda47634ccde1aae8e22eff726978e3034bf4ddf36402fed1ea99a9a4f532bc48a0135e3755e19830e5490634567214c452686ead3f3b166944f7be60ebb01d77891cb0d7cdfee4e5dbe0a499fe7e23e9da3ea5d96b89c10cf4c507da111ff749282f71c7a7c3bd98322049cc2ca92d44b5945f51af65e1dac0eb6c2f6d034d7d65c926f8b94e4babd4214f13a1c8c574cc9cbbcd4e31715461116fb19d26c939e440b1d9469e0ea36a22ccf9f030b07ad6aa4fe1c9437fd9fc68afeb98ae6b078ae1a150b9554297214b38ef166ea2faa378992353c64b302843c9814c7d31a1a6ced63fe40db98e3c2951c5b83537815cc929fc48db80d7b949835102959cbd2d676c4a264c29e09d06a2ebe38ac3f28dfa6de44fa62bbce88f2610f0db5baa1d25489bfaedc6d9f7c6fddc4ccc9d3390f7e472143fce582c46077a997bb459261629974e505de441c0c21e7e3c15b1f3d2fb8d390fe9e84d6a5b024cd07615f4a57facf10f459a3f3ad7644c23b912ffbf9edf921cc8c5f00ade0570c73168f27b2f971b040e1bf2800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381098d692bdaec68cf339ab00a0d6e93b8d1c691abd5948f947f2be50b617a44de55e6a2b22d0844722e87ee82153ae963c96114e4ce59639cd450ed7f4a59e2bd09c0d1f20c4b463f6caa976884323a395ee6330148587cfd11d347e73aa4f244bf03fc98d501339cc8da7c444b349150e94069dee067e73d23de7382276ce91761fb0313406ba3d578f06bdf0105c8b715de951dbe4881674d1bfe19f1e12463c6d0aa10d3c9d98c005e12bd71da4a23936d6f06eedc9b2ec1d7508a8d56a301ffe37ee0c5b3a188f78253f10d1a6201c3993f2c40697aa9afdc09d2d905b8ef8423f50197801cdd5a9edf7b2f983a27b1621a98244e204017046f4c5c24963179b2ea6a036427b5a642d7285aef08deab061ede7d4415da452bd244229c2602524406c375c0bd5dd47a6095a533396163c40399deb38a075991901680048faa3491ac1694552855aa67440678f082e168942cc490cae17471b9c8904fe77d5622b9b8c3ebb0b6be8b2b1a580516ee08b54ce84318856fdb365e1374c5cc42401efa822285cb8c138112e261954d01d5938a57e365821d1fac020ba98ec714659b680a0c292d8c5392dc448192cd1ff9ed09467c50e6fa72a72f51a41fc43886014a0c4677939b9657bcc3081361058156043b7f8155046564121245093a618c827a566d41a5ed219e42700f2d0a876709a776605e882aa00558c6e7ea2bdcfa72f0fef47b2d3ab4803473a0ed8f3770a7999b22294d1067314e81147e3c20d966e768a75522a69c095e6a269f6620cda21a8efa43acdd4d65d98b219b4d49903a1850d5877b6bfc8373c85b538ccd037530c1a8794e8bbb440d640a9d44e925465311c0286a95eda5222d20f0a6ad631414c4290ddcc3174121a0c8088f2c26b4969e5e4f7cd65568d4d3946796e5d78628fd28968d5217184c7d7cabfbc5507d5818eee203ce8140f26ffa8e121c83ba4fd604edda4a8643939966220b606742b4193377ea847af11e889ada33474f11b4105815f693ccd1a6dd140767c4e61cd9a0f38fa3594d79e4129a9ed19c9eb900c18f172a7ef05b5b8380b028faa9bad43726ea2567e9087d09b6a27aa261a86d94ab4423a273563402a355cfae50a880b2b48a5fa924b4028a443d1b75f6d14961f5b4923dc41a26917210acc949df5730557f19b36485a4c16856e7e78b7fd9a8687dc8c49a4ca688efd9b4a78ccac139942137399fca42dabf769acd198322269666e17363cf5aaf9a931803270e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060f6a58aa820275a2f43d0f05dd0ee484af42b665ffb8f21db322abd256a5c753bc8ff6a2c71467922e09726655f1a7218e736752065c871221c0b9dee6a9d56b78a1c3b7357774396f6980226dca1f91ba828e06bbf324d5cce8d584d9d298261c7149899fc9f74d501e920f22aa34706a79213e35914dbf57b9642a42ef0d8226e31adf89d18c5f3163adecc79172c95650d764e3729edaa08c207d930c26df8ee1291c1cf889283b70af00c0489175f799273c837b281a5d1284e4447ed72598efae23b523274644da19bc0359ba59e5be9e5828ff587c335e136c1d789257864d2648ef9c03d1c4b9809dd07ceabd865254d3d8d597587d71e374fc2dde89c22c2330e8904f6b53f637348434a21aceab9892d5df8ff84cc58229782bed739bfb13448896f7b1064b499087f7547cfc0a49272c2a670a9431b1b5a07284b6749ef834510a3ec0c61a43d5d0eb48c8f487947c4fccefcc49deccb6111d617407c76a1b4a849c9a190310711b102f142f9e9cbb29f46447265e2c8ddb9174b780eb4a51003fb68483a265f2475d5bf6ece18af0cf31bf24cdd56583e777c4340086917b78068dfd380466f43d020e285ceed97a467db96bfaec22d80b4a6ec0dbb98cfc44436a41cadc85a90b214f00990d7b7010bbe4ac94809a0450c9abee5aa4037a44b0b4debd264120e762086b8d6f17afd37086c93a8a368be97e0f7546af16d731c21878063e38df3dcf3ade6dd2daa43c198f49b5d9ff5362333f29ec2f13cbb90dbe4e703edae9a4f7334a1c5ac60d5972c4af2ba61b63c93bf719854e615d16ba4f704c55260a8838679815fa59be08c4243cacc1a584cc1b4e777fcdc6e5a167c4cc9093749ace4836ae058be89cca3221a3f63f07089006e4c44e40653bf262945a640d8c2a24e7cc3529e4be76286c86ca2089cb8d4684508d1fab81eae7d8c731b65a22700bf9009a3190f5ed837ec22f9112383422027aed838f16a7740cf79ec101865d320e380d4aba745acc8eed376dc5b3aabe58debc35f8e983c92906aa2e3d8fbbe237325302e2a23cb1312ea7f532d64e79b9815996d28e0183eb728a37e19cb219987576c142f4b2f66ac6c7c77028ed59a8df27f78acd3910ddfceb88888b4a604e5d07ae1b53ea6df6ec2163ddc4bab422d2438ffa543b22441e50e4087fde4bee6d79d90a2f72548ddc41c5ae07dcc87666ea3c4b89a0b14afe03b585e7ca507e5f29997f2368b0c68c6ab6e344c082bd06ae922cd8089634918d9132df9cbd665a4149c59bf76b0e94f66481766fd79054aa80c02e0ae04a6e2be090582171b2a9af455cd9fc302ca9d1ec837ee26e0e4d0ac8f0692cb9abac979b58ca92e5194ebe46b520125bd0b3ed1ac2bd817d3510e33cfd17058f865dbc64e9b99352b6caf10f0a5a47449bf927a8eba06d34c80d77a0b00b88b25a4c8747aadbb11ba15adf9c959b05c4371cd8439fe5028e004a2e1d2f21190466fc7fd56e9ba0599a0eedd98246aeb4b85994787b7604cb52f5515b42c2fbd4b5e9e372a36cc4e66483dd884dfe42aaa5ee7fab200d8ec6e3556dde0f9e9c7346f9967f8f3cebe1e4d1cd8e6046e5e94bbc74ad3d51db0dc704f4a4025383f0391b9da37bca8ec59e807593a4f040fbb186607280967e5048cab92215dc783d9045f7a0922008628c771778661e97e9f88ea84bdaa8ba61126f71d193a2a564e3acde7adf2c0b3d5b022eb6e0c629782b0025c9079d4545d88aa2ba27d10c5dcbcfb7cf648939155066518878cc54a4f611aac21bd3a1ec628d3352f049915fca55234b9146ece5f78fbe7cffb35695363202edb9ec3501a93b4b6fc81b3dfdb5245feec8aa54195262c2467e15506b7d42a7ff61d75998722d0208bbfea05ce7d2e66900a9b34f44c2a21257c220c03f9d6d7f0312a36f5c12da20fb5290d5cfbc1dec7d05c44820885c479063ca88783c5aa128829417ec4dd41cf83a1d991df2efdfefe375e93f0371695e353ef737f4a75106211a5f70c82b4f360abcd078c9e829c82a6b7a36d22b8d1f6e3101ba009c759fc83999d52e29b387a8dc1658a43ec4c4d9330a4ed2138e035ebeae6343a76a82849e37141fce34e9a41eb5ef88bbb9257017ad8696c3847fd77ae103a082ed1a05de9420984c147aff927e1950244912079bdbe5cc070000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 46&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028d396061e4a48be98df42f5f01e108a9720881ba2ab7af5bbb39f4d02bac7395c2dee65656b1f16cf74085cd094229b613d4837f857b7ebde23d5dc1106232f250f315b79ce2f1623854e1f6ba37dc660983d34694e5c127d3224f951d409dd66291b8cddb8acac3aeb69b49b8b27597c91c7691c16acb661c61261dfd630350eca2d06450ccb71bc88d6ac918525c65bdabdf72fbf0aeeec6db6baa7ee5784a555fd3b3b39bf63f79054bb379d7b88fe8fa494b42811739576e2f3fbf32b11cb6c932a9926c1586dac45e48d8ce23bd141c49d9783c6e13bb48187e4924787c93d5fd606a759476c7244272b954b191f2888db548420f746f5125e3e91fbfd9ba7ce004034798e5271c9dab13ebce5c1a85c1d48badb55442fb5fc26c955dbcf48e7f4d8e58d225bc550a89a9bb6c8d2b6129beab54d8ab4334b03c12af64b2b544c474dfb8ab4f31fcf2972a1599ac39fdf10286121c0c795e8b14f52583e6be59d8dad382e1a6cd6e651c34f966672307ab155ac6edc9667355c12ffdc5dd55051979d26d92b9292e850b6b3dd3535887b65e7b2bddb372c4c753c922fb9e5d74a845a707b55918f9a1b4dc12988ff241db6317abbd4ffcbd34e59e5abc406cf50d06c330654c8eeb5224440e9a9d9be8448acbfee9c1f27f8ec097b6a7dc6aac527a4cb27170ccfa608c5c8aef999de9ec4e72854a8f7395c350a7562df07ab2509c736391e6c30ed0902e2405acb6de90c27cc589ac8db0a0cf3d1b19ddf1c2839a7887c3cd4cd3962ba7fbbf098eb5b439fd8e5b061c6461464f875f8f6fa679d1d90b43ca681245725ba4414e3f9996967d1c54f4c1e37de8766875a735ba0a46470cca8178ebf52cb37c5edd9faae9bd18c182c454fff074a731059ba42d5b8890a968b86dac75ffc6d500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109446ad5694387a212483239e56738b2a6aed03610b2202ce1537a8cd0390964121765a395f95d33f461a788944b3b4fadff5de938f0519485259e31f0942c846e9a52db839279168a94e3149fb810fe4f3b16c104aa4d3ca93f4f973b8596115a09bd0ecd9d0a4403103aaa91867667fd6de8dd51cc0a44200e59ca19505408807a0616ceabbecd7fd6e91b84bbcdbcb4fb5de35920908b6f521117e05a715895340a341b89450e03569a73f2f9287853c004e66227fb715c0509b8543ca9954b378988ef432914536b2296a0542414c8a0f019a4abd820e1e3a4b48ed05e1645901a92844414ce9c5130928222b615c6b400491e9189ee0eda4d195e36c1e21bfca54c98e08870bad09e61f1f959ba0371682aed6510587248d5e735de423444a05601689e99bb704687e71ca88ab4fa34ff604bbdc8f3fb24981d99a4578a8b9269a6a2002a3b60358e686616c291cc7c7ed7b9d51abe7fcee3a1e9d4dc6456f0eb789687b5c1eecbb062ed6592156431d6d624dc1cd3a6a40f71f4c7e34119397bd1d87b6e099ab57e67070c5372b5869429be572a8c506882a19eb4b580d6b769aadc84f928eb5ca82fbabea9d3d562bc0560ec442c2eae72e030b0479b62243a3e166edfaa5d62cea96497248d94d9c51a9a409d21490297147cac6647e1c4aeff6bed714127eb14bee9aa7368cc3214f4f9378eec043af42799ecc707bc2523b591aac3b61c72d2b898781b883815631e58b1b0d0b8b64e7127a1c8e13e090d58f406ba379de422468753fe9daa12201c7a0d41a017903fbafb551609a072411801fd1c16a6054c0b9d579213b23554a06d310d288712cbaca98c683890ab566c22e71f88c7b72eab964f9cceb1e4c1a4fd4ea454e5c9485d9e680e25dfb21e5b39270a20b45894da8d00a61a956ab91585a3d834d504bbcac39b9aa7f44801451af998df1ac850a87b5007bdd2f8c1b9e3e522a66868a7a19e6e468982dfd5734c46dd213527096d48f316f6a5290aad13f725a4b278749fb7070aa89b960d485cd729a7ee2d4af3a2144619cc04736a199c01f4d4ccce36729c1f5712878f093d43133300260d61b284d585344c5d44f761e0133c45db07f386701684fd984783550e8e84f473e47ca7896a020dd2a526012c149526e350adb4d838477704688fe0ff51076158f9d4e6ec1698b43d19b1c4abacbd62f92d1d6ab4f25cc12cd9c3926e65c5570a136bdd50f292024ba51070b5c2559a94681a38c21a5e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000630139ba17ed7b476dbb1cdfe3c42b3a57af5bbcb3be19ed04d6c3072fdfe917ecb9272d59ee89ef83522531d83aff8b9934a8423315c350d1481a4b02980dc29e1cb83b76623869649ac40ef297b153b679c327bb251c6e6bc169c48aba2a439f9ea24ef94656a415c3e86d7bcb43cb3717d54d773f1937dc8b0e02d4e6abbb1c83fe73f1b221c9a359e454c19de5e71ea4cb8c560eabf1da133ff20d81785d2ecd935b99f24840761446c324df81484c5c05045c0949df8d0f10f942e1b5b79074b358c25b6ec2b0b42df65d998b666cf1bc568e7d737f22ff541807be95ed85a9980e940e24d2c506bb0f9bee32effd85a2017de694f61bcc2b292595c97ff4c2145e48af8f0f3d71763b4db433ed7bdb8dbf8643475fb2b9155f0cc6a0048c5546900792bc01eba4b06c83a0c447ea0cf05410de55acb8e5521829c89bfbc084cd86e7ca3d701283b70f78e1ce9c3888ad2689e0ef5593d656285066f319e155f86c0a71256484f42a0c40e7cf13af0cf77c6d1cc7231a48538e9060a7863b774c9cc65e321e45aacc002c0170eddd18cc1424159d46bf99d08a28d2dea8917d28d91a1d6c409d945a5eea19413a1adca40de9458fa6bdf1e5308ef9e67e1e90e9d92bf19b5351fc49dff0a31e035038aaec651c0f20f276e4ef0ee35c14bb625eb34205516d95abeaa06a7a3bb3af2f12236406689bfab11e65fc63ebc5b944818dd1d53c0e7b88ce7aebae581d995ae7d8423778dfe20d6cea7ac0b1b4efe2b9d571de77bd8f71e89d9f6a2dc89103b73625887ab376bd12ce89a65e6280515a44a80d6c32799669260167da0a214ad0fb803930ab1952d93360b54433ce8220b29339dcf2702581e88952a5a1549dba11f4ccdb6fefd6d24522f3207796c8d5ba9d1582f888f2500964f2b975aed5d5af83409ff9720edcf5ce3fe9b6b586b08de21956e7970d8dc28f6208a80f5378ecbc506333a1d98c58eb0e2eb0cdece0f5d16a069ffd742d1e589f546c4f2ea3da0a56f984cfd93f5f2912fb1d068f2bd7c1b5e979abcc62e3a0164445398f5c0208e82b99aed1200d36289b1fdbbf03e43995341aed3ad712cc7c7530c751b40b765073ee4e4cdd411ae543ad5e2793f294320e9791ab35ae1697f23ebfa0280b8041859909b0089c101d7cc429408fabd2e073fca7f2c2886031e9f6a32f2b596a799967ba8a47e87dcc8854d45ddb6de39160600eb4235f4e3424d75ddc8ccf041aa05b25b5a3811540ea5b77cd8d7d611a63bef5c26d57475b28e961645aee0b9c8d47954faf634017787a21a671493e7c5f1a4c553e0a68ddd726db1ded4321dc735332fefdf2a84c22097ab3552f878e304598ec40eb349e1c1ae416f94112a2cf8e8702a4c3bde2f58245166550fc238e153d10f90652518b1d84ccd3ed836f150f1ff103976e743137da5a97a61276dfb0c11d071b240069582265a9cae4987b6c6b017dcd1594024d7b1336ff141e59936ec4ce5410e1b73ba6fb42d35f8999225cb1a135260967f4f6ef2172d53fa6ab6d1a2e3174b46c24bc103baf69c2128f093aeceebe8753eb352e2804ee64ae5140df1acdacd8f225b3c9a61264245b8e5cf759cddd75e25e2d790ffae8421515e0cd6f279d0080a3f80bb2e0729c0d2626b6ace31ce20bcda490c7660d04d1d82e6403000578926c52d8f9a4be7103d64e0f03e8f148bb2236781ec30f6d8bc827c107fcc40f26ddad485e6135bdc3bb331be139a07891717b692e23312d0e5b1c41f30c3b4b4700effb481a835ab54340269fff365ff87f58245621acfd83b7fcc6ff108132d8966f9836544354f7e216fbbb851f390dce8a72362f0454730b90d35ab3859763aee35668310fd501c7501f4599563006aaee9b636b676f3dbb6787317885b0f4a64171bf19cbf2ea7a625e1563032c196e1292d82c7484817dbf78d8e9e478fdc4c92cbef48d4cb4f0e6dcdca6682dc0a56c3e45ea0350d9ff88073748305fd7df3a3be8c055cb1c55167560d5c99345ba80c21ce791c4a511e384a02833b78e8aa02b1b877a9b8d806978519d716c611df54ae8ea2691540e87c6e79eb006569e02745021bdc7852e1fa4177e2c3ec89257618b38719cb07b0ba68f600236167f019694959c2ab6fb39d5890cb176f6acc3b9656e495c07027e3d4de781f48c1f1a8aa1b41449689e191e495ff3f263ddaaa8de0df6f1a4aa3ef1f5edfe437bb74ba00000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 47&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028f39c6bcdeb030f76fbcd57a6303782c61559358f482d89d73daf9b08fbc1894bfd92892ccfad8e2c974cf99c10f142df3acf91b6685c0776c8b19c05890f9f4cdb4934dd55d66b2b127e24df0336a6da3c0f272bb57fe46c58b7ba0db3852026c508a54f63f117ff5996a154e2bf149ceaa3fa3462886b7fa7364ac4c16d98d4ccede86ac998459789c23145c5599e1eccd38e8727ae5eb1d09c47083366bee138fa478975e43ba23c29d90def19095d9efb0e132bdb92271b7cb9a9a208b5bc95296887626678fa0eca950d369b38ad02231c47e39bd11e985df22b6f1f86aa764c34cec362e9adca59f91c1630c7c35598511349d267cf4c235ef96c4595f3614916f5367b16c405ac2a751ca99b5e7c687247b5c415a6556d621dec023782da707cb2d9e9856d900306144a539087a7089e67bbfd4ba74ebf2dd7cff41f315683be4b09ebce91232153806ada8bbac5fbd8f852e8972fadca987b9bc7ce7b908150d8923cb5bcfe6f9373233b3c6dbe8918f5a05e7713287627d0a7c3aa8c16aa6b60cc6e5b177e9d795a7c3ad478c2a5557c1344c2d9078b79d9ea0c44b441d39e322267464644d2a65e56b52ba69db95e2f24a6c5d7822995206ee557fd0f47a31d0861f5abeeb7b90656866fdbca61036ab192d679658138ff9f66c7a05db2fc556d7f882398a9adaef2cf6a5247a354bf715ba5a91c759469b223a8a0b9311ce6f53660eff7293b8089f955556305649ac9594bac56f9a59556ff5f9d7d123393fccfea0fc65ccb3f154461be6d57a441ed898c6e7752d2ac3b1e15af5cccbf134e14152f2e6423d36dd569bf144c576ba3ae43570c9992b8ef32697641e76188ee1eeb71ef26954a8112d869c82abbc8aa9995838fc337158824b67151e65ab10e0eba4eb940081a5323824000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003810939594078da8aa803a89085c18fbb275a1cf553c67e80cea6f2d5dac8b0aea9c7824083050899dbe8a625b1a27455f5e6316ead08a80925024d5e60a22a85f2284268988647d0b4b1d655c75221ad9407c2f16a84401e6d0be150e9189e63000c441b1bfec9590d9b26a8e207c43ba22a902ae192505dc033a063699b9c0870125dd9e8e0e690d434553e1f8526f52c6b869aea2ccd01b4a421453a221277178032b96dd640b0dc0b882ee772b0883f803628f173de559ae65c822027679a5efbb2cd8dcd0f6c4119d567249a8dfc2765c7869fae92447f26bcabee1b133541d12e2cab21269fa309e515a3b2eafd3c80c255008ed022bc6ee96d64420a183ee2669edb04500138208c23010c4933045194bd8590f11e005112bc765a145d812a2d6482afa042b2058b823fac6e92812e2696e594b96c12e074806e7ad58da71ad3cf4fc49360a592b270262364d3db4d1b660e220a03f944e8a599e4676da2b53c7b682113258e2962b5446badd1bcfbcd2ef1b4f8165178c859a98ed5806b484b18a90653026d4851c1493b7cd8835be9512558859085322f40210b73b95ef98b645c3e97304692cc66d50f2e28a2dfceda2d3a1cebc7a3bf5391f751672b75b7fc1d16caa1895072896746e3dd0ad16bc0fd2911488d51293dd38241650e50f554149a944320d4938fbaf51070b29f70a6498e02bc51130ad58550ff46f24be8f4d49a89cf6e2d9e1bbbe65e0ef9f1e08c4c117d81512a0a27603f31fb913a57475f0d44c3d55b6a8fd6cd8bb7a43cb4d2cec7e3af9b8dddb2bbe6cf87a8b885218ec62c4f821824a352004d0e938aceaffe178d6884990f3081fd45b99501514778a641ba283b32d5230b6a1e5e09dcd2aae64e5f3d623da2afad1a81ec1bba02dfaf6ed0bbc12465933d82c4d9508867abfed2e614ea733582d3a39f6f9f919d59c7780d10423eaf898cc19f34c00e868bdbe965a684551397ff4e80995675e2bf06c5ac48af09e5be28c9e8a3e1d736509700b1422b49a98106af252b0ed26d13eec2d701056fc64e963e2eec9aa8e75e583844bff3ab1ae559c1c8332444404c5dd7cb63598732f2c7d3f3e214b05e18e1cbd4ed2489b27b248facbd74d3564564e33a2248f7b6a0273e85556a6bc93489d6d4d24687b4508978c84a57a792f153318192fa35916881d589d93f5236db1827b10ce1f988522a81292dcbb77a93f4756012732924de0dca1eb7935db98d267735c26f8f651c9caadca4bb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000651edd4da833528b0511534f77857ffd16eafb1a2ac87e6844612dbb104b9f32025b7f54e993d65ce85a061b6ac6d70a15bb42bbbbb6e2e21aea55bb8a556120eb15ef35fd9774fc7b5c2894b747d3e4965b77dd8d5b26f38d413662783dcd332765b4de534d08d6514ca9dc6ed7f2bdb4b5c437178710b04491708836cf2cca08f28582107d27ac305ede6030b1f8aadc4a1d29ad16cb4d739d8f813d47da715cad6b5cde24ea95dff4415b527dd900442d9ed1ca712c58b206d6e79f8aefb882013358bc578638225be79b58fb677277f072aebcf8ccd6ab61a9d98a3b260e60aa625d78058fae6028e4c5562a0f3473c3ad530bc4471228f27502a8f8fe2d1f72022103c3a2dea363e68248ed8693b3b066b495561cf4468e8ebf32b454e54df1766468ad3831d56ef7eb9c231e999c4cc3a6b0ebbf2c4f22820e256f67497427f53ad22d42c9293dc8682d0be3517b63c6e871910adbb3406b6b3b1cad980aae47bf9686e80b6e5df2daccceaf9506b4667271779d00b4c1065951e21f2acf6cf3cccb8a633d1114ce9d531d94420e4ae496086638f031c0baab5722a41a66788d3885efc7fe1c3db54bc69e35b7489a0237a37afe5194b5f424f792cc1d696098bcf327d87ebc50429a95ed82105c4328d0095a9775589fdb6c262fa51ffee4d99c6d1a68fa661d1b6a0a2e0693d73b39218a6895bd83fc1d54831b7df146fe7bd2a91b979018787b9904285a35922e22a7f1761bea541eaf21d74e3a2f3c6f2247b042379ca4c553fd9256dd0c63e4c9dea60912d02fbe4ce7762069a86cde02a4e1e311b2afde435da0816aca659bd8c0650c1f118c0ea3622d72a5e96132f8b0ff8458c757648bd46e58195faa0fc4ff8fa44238e35a25c9807b6229000ee560d8e085f27375c2f659baa5fde302b9529bf4699505c28de33ab5dc2b8c02967947cd24c6a599acb5c2d1e7d6bf3bccea0253fbe11d8043fed532aafc9ee1151243bb80b92be239bc4fd1d1caff502951205f2e6393b704e67141e1218963f664fe0759c15e6c0a1b40602a73990f040502867a9eddbd4db0e554aea4bb9597949d5fb32c2e3af92cf7816bedad5ede1b769c823cabdefca1d1b85213c79eb03e065146b58e3bfbe80b4d4683b65ad1e0611372729b99a0b93934d52dde40c19fed5a2b3dc3030e0b5f26b66474a5cca6d741ab294bbba6be516105c08bdbabc97bdec2141d035bf6c3a71553d6f6350229ca2626b8b0b56a24f2d6eece436ecb77a70d747b6a6f830578b4792de533879b174353424e7d0eadf6bd5a74b36a4e6ea7e39a4215559557bce7a00faaf0d1f81016f913a10f3c9f406c7cb53282ca8fd5fe4f5fabb96f891583e0507912ba02709764694296a5248c340a1b9ec3db0f926f438ca96fecd40c4ad8daed9b8a29691601835fe14283762236ef2135443307e5f0082d1c2180ae96ed0dd99a6e9172088e8b94aa2952ba5e128b202b2cbc1966e69b6e6384820d9ab624bc71788ea84b4adfcfaa2efa1ddaa8855d1db3f58eef2d54fe11a8a5d78ed46b58460e6f2fba6cb70640700a4520aa1a2a9b336aefb17cde8ac78d67f194662642a0107ce38b74d731380a72ad4a0a068f09e0878e521f15ce8134780c3fd0cab2dc2473448654f88bf1fe2020901b90c0ed670866b1bc337881292fba885fe2bfef6fe74765ca12372c8cbd698ac41a4c337374587db15affb511d8c224f1743498d7173897ff5b8d070b89592bebe053d5c10dce67ca8542781ae749f3a42fad7e4a2004a565f81d5faecf11115c270155fb8af6aeda138b9c71458d6d2ff63441130ee9107c39260469521e020d2b42cb5a51098027f23890dae8b28bf722af9aba6224e02feb47e40112ccb164e8cf174bc9ac4c11af9b482df9c9f7f5f1b826428c21be395eb1f07de511e8258c84f5f035f4787ace18c190808efe99fcb455a54d366dde2e230b575ed5a4a75d57c9a38dde3d91d0d1a1c4de7f277caf23e0c5dd8e3b693dbc66b6bf1679b0af74a2b9065b64cf0978115cc456af685b22d85135727a8aad96338611dc109b36c85a92e4a0180aadd1d25c5b3d4c681a44bacb953e50f994fcf5281366cdec0cc50976074d91840b5079180cf643184adcf9e4ccb44328e7bb9eb2bd06dbb7a757c35ec3dcf795a5e05ed250159ec453a1692426f624cc0737f691e475804f155e44293151e42d3c0f115ecee53c6eeef69788f7e8e5c422bb102237499f2638244c0c080b3639a49ffc1730ebb0cfd8a46000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 48&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000293396cb65026c66350e40abc7bb71360f69efc0fb9d63fb5c9bd887ab9f204863bbaa83eea260e934a591663777aecdbfd1275fdefee36a102d69b27b361d3df3b3c36eee1fea635283420929cd924484150e23a822c84399a80e15d8afc8d414ba11c4be4b764cd688d0a29cb1639734b10ba49d13c6ab5a868cf44aaebcda0b2f65dd3ed08c2257c032bfe69dd0fff1a833748ae6fceafa908c19e95f9bcdadeb6eee65d8045145e709330c1227e57f200bf755ca5f16545c722ecb496deeb0073fcee0b04b191f670ea3fe4ab1efb467096190c5b744522f5fce7293983e1868e02b5960c688d6f5f37025e65d46bc213b876af13a886133d5165e12752d15bad3b89ebcddb344cc6cfbbacca14b279cab62d4caa9abedc991c1a584d5eab6ccfc8e446d81a9367402647bd125d98f5bf53797b1fad2f1a88d1c9ac9ee8711e4b749abbbbd79e88231996dac8c65b58fa80a323a83300f4a9159d44cdd9dc7f8947662516b934ed638e60ccbab698a148ccbab22209145b7f5d68e1b3743528cda5aa17e90d8110331365a65c3729e4e4bfc363ab7f5697308f66d76f57eaff8d45924a83635477520c0e6ebb6ed59c451d20ea6f3a6e0494c5e63337acf3abb8f0efd038b4b66ea6c1495f7a0495d1545c7f163363a37f72b3c42183c9aa188539858f364b0ce8ac61b785bb6f029543b0b904248e4adb96d1255caab193a269deacd5e7c69c5f9608bd18b564d7ec431fc6d5a3062597d2e7de43bfad16260ed1ae68bcebef6a12dadede8300857c59cdb3eb85a398590befbb3b6c931b933111c531157961694972e4d553a6ec675c28cc0d6ad22572241ac55aa51f49d28cd5c9a638e89429993fa58d43dc6c324dcc60dc465e261bc96060bb6ec27dc7f7c6690d099a322736bdf14348d90825070080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381096a818b273407c01c8249213a0b565b80b5c49366c618c81ed9dd96ab610919a99e036536eca7f5a44901349af1f20f285c014cd2fa9de06217be1da30a2352a5aa34b5f5a80c3796901871611888219c13e9522f15057eeb490844098a1492bd5d739361bee34c93f85bb581204dc922b1897c869b688eb40d78447fe9d46db16744558c220111c68397e78f36ecb3739fd79d450587d7098cce7c659fc158cdb2524d044716847f99ad9ff0e29ac16116fcfadc5dca3ce5a1a666a4097a055f2a796ad912209360f64f92b6d50470734fed6c3df3663de81f2336d9d6c917ae4f461e25dfaec16f68a81450661243f478547c298293017480f5662362e91d797baaa184c548bb522141372199c4df9e78527c1dd0fce7369f1a3169829a7715ba6ec5d2dfd23cfcc8fa6e87e26cf9c076b5132b5a5522062557d8274a97b9746c618640d1f283262a58c6a11200e61c918e5366f1de9b68c4e478f156904698b4c7c249286a34446bbe0de69a0deaf9d860a03b0803f79dd954b0e9e9bb34952e054650138d6bd8478e4a7941cbe5641acab52b62605cfd2b000c911078154fb96346242769aa33c7835414d61d3047566d2d59df694c286103bec352eee1f99bf5b9c2438ec2a73ccc120fc6b70756a4419e69f2b8ad27064587fb3ccace7975096556e05a27ce9f421262accb88cfc4820688550341f59a922499cf04fd582c98668067d75871be44b1c556347a49371e91655b2afc206dc393a35e8625218d1f2fd8134027880895ae8cb3b55663b1de466b196fec76700980a51d3d19d20b91ced725740c6b15685bb70162ba042a4d090c806bd171176f68b222a845881a21521d85e98776baa0b94707ead62d3177482f063884560b336e017e893a328891ea99a9664d57bb8b2f965978a43b27eb5e757c79460708176dbcb65ea71221e906aa71ef1597408ff4875dd846dd23a18e5ae3b4995435806fb08ab5e049b6253b1c18cf0b8026894ea9636a73641c4ed98ef0c2462f3e9e8db088dda9a77524a3d39b26b418045b195e3ea4b58d81d310209c297941068a23b1c11a77198b4c8154b7868c1a8b25c4d5186fd346337e58caa02329a278e00a25a1211c250fc9b72a5a01224172a10230ad910b9111404b4fd515f2a5c603afa98cb91c2ef42b629647eee3950f28bbd036696d4d8eb788842cec3f7abd78b04df561ae78a5ef681a2916bee22d09652151d672ff5c4b5832f35ae41afaba2d8bebc35c11000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000672d868ec985f946f3c31b6cfe4811ba530eacd0ed061ec383c203b2481ac697b8b88bc0f72b635027e443ab1f54478440de16e596d30a0f1252e0af54c0f382bbf5655bea8c6b9a2f6382d003cc7e4d4f223f8e35ec87cc543ead52e0e1ed956cfb32e8075715c07ca4817c4b8dace68c8b0da459271746be41d6102b3fa5e49aee8d443e78ad3246d0b9bccf6ab7cb7cf72b8a847ca16b435f0618594400037179441f3bf524231f747d920e86506e84c61d4d038d42e82d52d97abff896c1db1c646807156324f7b68db620ee435c7b8c9ac8b193b7c892565c3631e297495bd3b59293f9a9cea5e29e23a242b81dd05c8dc9dd669424573298c85870b109c7b593bf864b56895d81386466ca5cb6071005781fb214f1eae9672d0d16351a627a3faac49be4e13d552340328323cdcb4703bbe07c2a39d75d7737d5c1bd04355b8694432dfb7cb4f1901550c7d6f41080c0f6a2cc49d63a69243d137a78260c06e7a53aaf4f4b086e0220ebc5361a6a78c9b2ec09c2ea4ec45a41065b4b2daa866d9babd71c8e6cb378595f068edb258b2ad1f420b304e5924ebe273ad6d00684f75b6a31dc5290a37d0f9a848b1fc4a67dd9a4fb1f9b4c6cd45e87fab4a09129c9ab95c44703b75b54c9ef9e825928aca56527d79b338c5ac639d0265010f3c085d2b09aef0e4f55d080fb5ff79f13e8e4e8db020f4c095140d46a93f2e4811bfbc1393ec24f6b7ef31f13623df0360b1e335fc42098ca1efcd0306c5fecce942f6e299ac9ed81054fe452d3f63991da42d5680eef749c02fcba78db5f4f7c734c6b4d99af79711a0bab723c24364ac85700242878cca93465f286d5f7adad7f68f1d38cd6c6e0575a36f1e5521e420d348d947e745c2355fb5fb0f12dc6fb5e9435cf8e552c174a617151af8d5e7d469ad5cd741e16eb88ea6d7c5806b08571697d22a525c2e30dff608c921b955d2a990d9466829385de0a81875be564942ae740d15ac0af46a876426ebbe481738be19be06f174d975ae8dfb52a94af9a77e56267c0bb62169165ace155041406caf507146a02fb760629cc4c0e7d29108cb7c779455a3ef359bb6198ac75e16148998c16c9410dff2dae5f3c79da61d371992d4a151ba91dae8814c81eea4f78d23871326bafaa349c8eb57231b590f1ac13f599df5b39df36455f05e53cdc4d025410e8f8f8bb74854fefe0c4f790f58434309d36c1e7f3935d4f896368c91af95ec2df292ae3166b83976abd95089b05b461d4e9171cbb4747f3cd9bab04e5a3b98095754021229b4b820ebde63e463f2ee479fbfd83cacc61878773b129cd4b3e9afbaedb27c7fedec2f2d405b99933fe2c203d9949c567a7752aef8a7788d2375900e70315823daccd4f2a674196835c35ef813826b310346abb16b0145cd70fd0a04611ed5ad0b8ddfca6eba6b93445038c3dd23d3d15e8899f9c889af417e5662d538e466447e514a8897c21fe0be2ef18948b66eb04051c0bc961fa485422a66d649dfa86d4b3dd504a89919a9928ef96fd467713dccc1f19ee69ce3935f0416d9c5752b7dcf9272d2db86c3eb6f4897d94ddbef7c483fcc66232e535a8b0a5aa4bd443493fe539a32d433d9e89f7758db5b0606a96455b39f92aa788fbbe43cec8f1d36fea3adfd0353ea5532b49a7286381d985e018e6534005f605bf67ab4aaafdcc499ac0882fcd9d90bd88053cfdadaf466e536f2ffa7f18b3dc254e42fffc777e0339181473e2b7fc844b687eccc0eb543a54211084b1ec06b0d9eb0a0c96b88d6585f414873c13ef7002af2d47d5859a23d12a7d401ffd4bcf642db96c70fdad0cb03a6098437795bc9c7c6c804a26225eaa53f52747f01db4e62471a21dbc1ded9c4de2508812ab11f61f6364fcfeed445ffba549e45e641a80fb4b58ee20677c7d6cf0526dbf4e26d9e5afac5429b4474dffe709d09d766542d65e668d59c836bdfd0f78b846bc412f29da00291871d94bb5e6557d833c8db3d9beb37888c3a70684adc6b063fec3d847c42e0ce20e05482db165ffac5d1f2c661b9db6d19fb3e8909587351b25f2c225cb26bb137bc52d04ad8157f7d634f29a3623b4eb53b4ef9a78945280bca8c5e1882fae373eac69ea366e2f13a9fea75a6b7eb5cd4d9eb14f68a231bac780f84200146ce7795282952382e2393f0c2a99de830d3aa517dac4ac97f2aad3f7f8e3b49b22b078e3708c9cdd1b2a2a129656066c0030d747edd646384611d4eccc5b0b9df4852af7bfa94f6dd7584f6285ca2ea7ed3f8decb534e6d31d7165c609fd9ad235f5af8e4e8e58fd3d248d822c2020000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 49&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000290392e522b9ecf8f50f6ecdf24a6f8767a4176e0789d261de37daa719f688d4a36e71892a36426c2bdc6d7d9c32d6b55db6e410d3fd75844a52bf98ffccab5048f1f77609fdab4bd018693ab288e28fe7cc7d23ce6a1233191d8dbb2079654dff6e65ecfbe75ba6e34b07ea52daa5952563d153cd1719bfc480c137c4613c489c1613bdf6f57ed5c8bcec8366d059f6ff0d49a79cac3a03ce7d84567b337c19cecebd5951dfc58aebcecdafdaf38b622390bc27256cfecb618566355d23aaa5f72729eb51d96dbef13e983e2a9214701de760959945118b3354ec595c76e808b677f1efabe3107e7eef9b088ab7741afcfe9e96645438497f749b025cd1e6e3d201dcf2cbcdac95342fac56f256ef7fe1109369ebb4e81df503559b549ff762a6f5a244dac869d68da39cb69552af89ca484465e06163275d531b97c2f2b866217c29a6ba4048caea3cf3c0789c3c591e22acc26f4792e5a7a87977bfaaff4f9a2c99e412c73231fac98abcfffd06c8a09dd6869a9e91b217a2ece6a1ce3e4db5731b1a7e1256c312f993f3f0bba2516667104df46df483677c76780bfceaa066f4bb09bc1b7fcbf7a1f91ad72d3633691e0ba6fe389aaadd155f865b21f0d375005ed7ed4d75d7a744cd06bf18b791e89c29d18edca9bf491cf716e66be7a6fa4978c50ca52e77bbd9477536d385fa41acef2220b7225ae5eedd1f53a44c3a2390e29e5bb77a823966db91fd932e08dce8e4b7af2becd0347ca413cacd3f128c62c1114db9bc56efb9af7dc93150b9f3726bf794a8a373ce327286b1ed74652b459c4697d3c5a241332cba40627739dd536bd06f7778b79bcec6eaaac9355c425a3ae2ef58dcc0b1ee7d9f632d9ea9df1686b9bacebe94997a35ac504ac423a090b0a47190def26acadf09fe4319bc6a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109b3aea920d9adb9b9169b68eed40229adb7045ba67f403cb8f1e24842ab2c493177db5f893634e0081a5e8db24143f102107588bebad4521237b449a3a8547a935a029a7010c132edd7141c1dec97c905864d09f47d3cf3685a15631b84bb1b24c58f226e6142d29c425e7ac32193a0521080ea83f8df9186a120507969fb7a9dda6bb52c7870f4f14b82ddcb2bbc9fa7abcbeb6839366aa01f4cae7ef321682a912e5e3124a1952e7c88bb958f594705ba4ca5fda37c0f9e802405a171788935169fc7665a748209978830a63869175d0d36af40b508d64d3eab79e227d2a4082d6ddff6c785803a327e763501539f09d8c083dcd613bd71709900173a7686f598122d78f09c118c1c5ea7a50bc9e8989765f00cab0093eb28bef90553ac5e707d9bb0b78d32847129f02944aa54593e2b7050be865d6002cbd8913c040c441e13c327ac2ff746407f36898931358783602a0f302584060f70ea07d996bc5c260ae2e1aa55722857e013d853a22d31f249014607a58657dee5af2229d7953f9fe10a409722f9555f0c31b4a25428fd1709c3c9229dc02886a27378ccdeaca40f676faea48091043783603d224a91436a69be87fef39bfbaa5209de4eb09c910e2a4c19f3509b0c4addad1664580e0bc45506d961042c82da79825d9e82dc4d19a4ce5e34be581571a45c717477ebe669882c75cad47126a23362255167de619f66ca5675d87105e48500da661c5ba44c1512c82868f0df47b0ca0d9a9ace28dd0e2b2589882a60dd11486e5e50a6047b2f05d8388760b61bb52888cc89653e823a2aab80f248d2ef2018c91b04681e3a989c08a449767aa31b8a51c83490b389be2591b7076c18bf9d3852dbd46c6956ad8d11e8ab6c54f00980db27c867d84dd2d4cfa7589c3b300459febd54acb95b13c9338047e9845c7a4fd958c979ae6dab38db551ddc3d2e60d3e984a92197c0f61b275f6b93da0db55385739e303946c5250c4872fd683badc2783811d647a7095caa5e8498e0772611c2a7fd83a6bff867e0114c4abb5aa73adea9427d76c1f12952070bde43b4aa43762c9541e295d62e2af251d9d425f35788ac13d32665bd809c493911aeaf11b079532b66aff6b89a7549e16a216e86b06fb75a81e64a57d68903783f8879a2512a1a9400e0818d8aa662e05d2d306b5927e1cf2ae14fb9d8c70155c98901a29152a99d86eaca27d8049d67a5c7c63325e3794935599f87409ce91291f9c177b19e4852588e970000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006934beaf8cc3a7c393932cd37a2cd8ed790f05e4038adf1287e2acdcc0bed9bdbf92ce44aae95caf4eb142b858e1421610eafc47de566182835bdacd4c836f19bd686d53c3834efd928487a2ab3402c2e3ab3af97aa802b05223ca6927722c3bd1fe3f8c20f93c3951f907314896cd21cb99306fd7e5b6176945c2898b10c1df62fbb2680752cabc8980b5a0430be39d34bb7de9544bcccbfabab709c11bfff5c958c8763d8d5830235b49ead26c834e63c3f3f2d6ba944fd2688f6350ec99daf4cccc42c6be1cb19dd46514d71cb6e887dba80edb580b27f1142a20ea0d497e0336d55f1ffd4bb3d4b3521f0a01c7bb09258971d1ed4a98ec052b24776623d7b9a83c818795e3989eaeba8c9142a97afce855cc6ac0aba15f0546684ab5c2f48b23bb72a88b6af2ba9c73881103cb6fa99e3b03119eab03bc3b9bc365efcd7b9f49a8bab6a34a00aa8f2c88d7bebba808bd97111ebb192d82ad244e18bca732fe6f72fde5bd533e4bccd3f50332dad3a4169ea85c324d165413f10888ac3b21b91de09fcbb9b636ed00faaa669abf6429b78c3c04f239722f31fb0b1a20cb1a6b553908070ac13521df66772a6036e6695cf66b9a90e2111e499bcbf5dcd19744f43deb943445248a5e84f168e7bfea2dc4e1d0a87fb4140eb7c72d2dfcc27923206054cec870888a79938dacbaacf1f122b22ab5c9701d777bcf9809cebc9b7aac52468134fc4a92c2baa9b8c0f6249130a50337f460a42cb5364a5e7408caef8d12ba6934ab645de9832818f9db71f5eb0b158de6a76619e75245b56020e1664d8faf1c1782de4a688d4055e07d842410600e9454e28676d44357853ffa7740200c91eafa16bca21d0006f47fe8159a733e0e91549df434ef316e1df9bb97da6a2c2e2f20a65b3c00041a903270cbb55ae2432aee25c71ce73bc2322ccb8e5bd0e24820616a890b0851d825d79411c14948dcdf48776d72565422056fe75765e50736c82f71270bbcf229a7b7a45dc88aadf4f84238c896dab889e16c17db7be551ab24873fda82f102d0fcfc139c9febe9fa99819cef0e2684dfc5c843a6d496d8a595d33c51e1fde9a84059c7bc596d32d53e2fe046f23fefa51d13f9c28e227f5e24429b851addbf578922aeb0c5a61bbb666d11d127ba45c9e6378c70d75643de776483582e034e81fae0a3f029c47fb192cfa018ce1f68261d77cfc9e05ef19438e47f3de9a68c8dc09d07b1bdc6ced69592623750f72ec2fb8c5ca981dfb84b4bf0734377ee9dd8ef5ddcd96f438d30ab78f402ebff2163d43345ee8ca119f3208e21aa3a2185de967b475b9abfbc86465275f9a634fc22015e94a298e9c204e9786cb1ff14a5e99f942d42ab5df51ad09654083df0259aa1c26a760ccfdf4a276600c5fd3a54f210b20731941eb48a79435f1f86c45f8181d9758a1835721b87d36c725878375febcb8d48ed2ce8892db50965753a98f4e7110281db40ed64dd8eb51ab9ce41042589152d8cd5876ff30536f8955172a7a8f5c3f5ffd22c9954903136f781f0574f45f909bdf1657fc1cdcb9c4689f41e462c8d39108b10d78b6892c8775fdeb139258f8130bd1d2a1c72b5026506409f9862aa8729b35c652074494feb84a553cefbeed19d6ee94758e800f5fcbcaec19b6a00f33eb237aaa6fc0b3a08c1d8829c180bf95e7d05f919a929933b7a032cd20ace82aa5a45e5b2fb09812f36974b5eda1b387feb13bd49ac374f821341282c8fe2fb0cc5c075356833ff8cc6b648729a4298ecd73bd0ec73957077ac65722d0be23c1536b8db7b0506dae47c0070564e7d7f9444f47b22c679eb8aca4826f974a42043863e498e5301ea162c4e96684acc5ca26ccd083541bc4c1d2fd690e51f07fb08337450a204b0f4f2c17785e037424fd6e78746764584d5f19255496df1e524bff0aac31bde9254429565278a39ece4627c023edf18bc21bb523d44efc259742dee9ff7159d5f700d957ccbb505a88c2037629402c2a322d17647e430777b184ff7b4e8d6b94724abc36a5ccfac08e2479e8310bcb7a617a25fac6efd10d0a07248f7d4597f14309b8064fe3bc4a4479f905e832210d49363d1e5d58176dec9abcc0c5132fd6eccead2b05b56c96ecbbeb0b803e43db2f982ad9efe1e2a49649ed8e42707970c93615d54a3e673559b996e48a3b73143ba0884e918888156ca78f793dff990fd721de0c0b7916a5ced736e31292c5af062d7ccd83fe653294fac8c50cf6ba37b37d5a9bfd1e3b92d1825c1be0795f9b257cdab91ce99c0c51bdfcd6c0ab5a3bc6e30f884ecb4f1f61a3259cd279205b2c21cddb196360061758e67b1c3724f5cb6311eb4fb92e6c0d71e6d1ea4500000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 50&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028c391eaa6ab73fb23784957316b60078b5923b9c4575f6a88c5f5d0a79ae5566575f10008a55146ed70e8cd946a805ce788fe00d7a52ec6a77aeb35af66a886f860a40d87f7c319e5f21c59ae547cc2530c13bf17f1cb2f281a2308c262f14b5d99c9bedebf19fbf5a65466ca8ffeac92258e1509a496faed086575e9c1abbb0bca5cfe510827cb54802f3a648d1ce7b2eb84fddba2c6189cb7dad1439b357f663637c49b62e0db8b63a78245e4aae62d99d158627ac456c09d686930f8d4890935aa521bdff3ce8a7a7cdafca8ee8f53151bad4a112ae9b57e38dfd60884ac8e8d309799d6e607282c44854243486615bb44236ba57e37ac75bc179538a4a2f4cdbdc2bd72e06c9009bfe0f0e1973e32094082a9c8462699662b33762ec4e1c53b578721dc5e55fef79a0189dcc132669cdcc152490468953774db57f21ac120cda4195fd62d2e05030c4bd3e660d2b273380eb22d82cbd7255347aa45ca9f2db748bdee6af7732e2c87c5b6734b2351868f1333ab87b7dca8bf968d0d7653f8070745295a14e5012c65b955169dc7abd8b3720df15ae8b049950c439404f26a9cc5904dbd3b542cd501127f2b39543281d5816b1012117879234ea7d7e19bbfe70b5a83a8f748d3ea0a0db3b3d0517a1fb543f0cc0ed7e21dbf2cf56f3cb9d03a9c0c44715a24942254c26d52c6199c8bdadbf33866e615ed9e7787c8127cd0b6ccf05af8f18f95278b1e0594b064ab9915fa1fef5ead1fa22f1751b3c42f04ed1deefaae9da03c0aba8b8176f5b4e8f453e6dfb53c9cc92e677259bd37257f925bafd1d4f0e327d73d4ca2a0f7d872ac4c5fa9959852acad3df65d2af0ad6705e79bc6f60b5e0e898bb31313afe86ba74b3f261bd1387f06a73cc0d52016245f0d0cf592628a8c3eda2c6400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109a00147a46301ebba0c09ab93070a7fe19ca2e20a96bd2e0e32292074066d4af47d8ec32b78d7d66c98d859960507181dcd468136078f0a2c9154c876a751f1953a3c047e2f0185689f54979ced5dd0c15a795602486e11913446d14c59eca257466db48c46638f1ba0491a0194dbdb8e578c54002ba26b8ff6c5828f6a382bf86e52dec9da1106e41143db9922b002eab88b5229700b0a43c85ea0c8915431c5e54d4d7d540a6ad27cfd1e8143485b2ebce3c34ead1d4f2e23cb371d2a81e6b5baca94c51f89f613d0460c819c18c4d7df026a549f130a5adb04d93cf636263d2d1c0b335752fa6ee09488d481dc959478781089d384e46ad74b8a6773b257e10ad56b0d35bc0bf007d3648c481a6257de2a35c535e12fea795ed0e4e883fa89444d9a4ed8382b390b65179ea4bc285987e70f6549d27ed242d0c3237e1365b85f882f7c2cd9c68c6f49da8ee56d5e2d5e5ddabb8b50e08e198807ae0f229fbe1868a180075cae9dcb3c93b25886b9d096a3658e3c21a846e04a7a189ea0e28d1c0f2e4507d8e8301d9cd564e69a61b18aeef1c402e7634a1165c5a7b65315207ad707e61d8517146ca7b72cf8bea8440996b4f2399a6b28556e347c3304680c2a8ef890f768275be1aae589da642389e089c51a54477a36f3f6c8b746685872ae58c445a4d08a372e696b70a8f9c94ae146ccad63378f0a3f9d6e4963648123a130dbc6063d4581e55b9104979f6a25f215a27b871ab6a5ab68fb1cd58b23a35789151ce25a394c980af28f96271422320c9577130b3b527a75e72d950aafec351b9f8b8933f6b211c260fb71301754e699541cec6dd80d2b95425ec2b475e9744bf173c7de8554beedba06886c5217806025198a8273021f9be6959025cd60299720e6a0a6caf5e6d3e439fa0a912604f8512084e6b0e5d4340cffdb6340e28dda847be097a33dca1e9048055a5820fd36976c595f64c8a437a40660982f493b53943180acb487c9896d54d71be6433b6f584513e3208879bdb44bfa58524d9e402283096f109a0bc9ef5ce65d0e1bf5ba20e5a6b41dab444a02b8ca41725da8d19d348f612a89a828c1a2881bd66613a1c3f20fef591285db6486c2791adcfbd0584d2175217734c38bb6824d1a220e66a934d950500a01ef0a313d9bc0edf5ad2d68a2ee0b967d0a25812586e27646b4743bd7ee778652321acad1099c2c203456517ceaef339cc52508d63cb9fbc552629c0f1b80525621750913e51e4a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006b40bf9a7c0f63cdcf3f850ed7c5db6191eeefe29e498a19f9d89be4698821abd72edc34317b4f8ec2736dc83c24ac195bd55aff00e797a83dffadc7970fe53304f16f5dd92e6ec362b9e283e41ebf121fb2fa2a3f60124ef3ebf836ae51fdd55ca9f59b085ddd660724c072b86041b50a3a446cdb20a45ba65380adf007e005df2d9aa16a9d22b11dcf6f0b1964f04f45441a923691a15d80dc85003b9ae281f2b5983dd1a04d80a4d9c4372d9820bbfae3af7735e7c71e9f085c0a6e4bc107d9e4ba222b38fb236b2cc3a19dd6067beac460383ff2bcc771a7f1aaf092fc72c292fc1d5c6fc6b9715f1e1272eb22f8e0b33a2830e31bd6c531677902f6a95cabc3e9c1ae36f77037a785fea355137a581fc14e6bd5f1f7ad1a5dd19dedd448b47b558c22dd0fcbf296a812a726e7d1b57f4688d3f577104cfb15fc63c27f7b6051c7aed7d645186fca63ad9c2d68bff442466eff76bcf0e398d2bf54c2ca4cc614839e9bca48ab2cc53865803710a98d313aff1ddd06a65680eb83c640052db807eb2f38ed0cc211128044d331fec3e6b0b2f3b675c631fdade62c16d1719278413ea3f8e54ba34ede7e73f3d94802d2f9cb9794d257c46679a3f00015945903190b97071f8fb55f8696253aa3f39b3fad344fb88224f5313b43889b768171895f7aabeff25e21e525ea01a996c764a3acf12bffed08f3f751f5cc094b50b325f8b62c7a5b3256964d48543690538e634e5730354358534b65eddd44a526bb4b15e2042b6210f503eee06d00d615ccad10d73cdcbf5264b526674d85c0ed31ba5ee584f21fe6d13f883ace4b094768865e43099e54671240e8e2af8a7d7d22335b3974ce860e7238a7c1ca8a009eb51c8636f0659189ac8ef01c871e9008957cece0a367b63bd2852bde8690bd74c6d956435d0ab82f94a90cd00fc840dfc7036b84d51f1ff5076ca0974db6cf25af42ef7dc8c30c2b04ceb2510e86ffc510bf4c931639478fd1520ad571fa17958ccf8e37f5f6360030300ede3a33871e9582808bda2233996c5005fd0c23d99261f570ad9027767f6fc96d18ba98e8ddfc2b79ac12cda5f2367b4bb6b99a3e07b59882e49a92aece85339bbb18ab9644d20a3b2a795240492ce4eaf09d9ef728fb82b1de7b64b5d391251ffb0699335ced8c7ce642ff1a79f04c3ea0dc37ea101188361afad236eb218cfbd1d0ebd784ce27dcba0266ddeb87b59b66a4f75bb44665643fa358dd3d0b69b49f45a752b5c410e2299a62be4b57b32b0924a069a8e8c15d754cc34debb0d967e70693a6ffa58cf7099c2c2458b437c7b205cc7e815f6cb494080f9eaf3017e5ff918558dde415ff72e954ebc2ed4c20c8ece38cc916060d22e582d54f74c6c181c2601400110a683f4a365e45ff1387bce4e152a740136bb762b03a99fb68f6ab42620b2e3c00fa8d150944230a6330409b27e4aad1693e2c3dd12216c4e2ddbc5e9cba68b8b5417a7b2edae7eb67d25f4edecbb087f93dc9c927c33076b1c71a2b83b33870d602562ed378805a690dd2a427d86c2c46ba4741f3defeb91a05eace975c836e52868cffe52ca92f97de94768161a3e953bab6a28016782909ec53c02f35184aa9ccbd5b793b525204b72deb63e104376893b9452c3f2c492f423cbef1ec87c85788cf3073ffbbcd67ff79bd038672943ae4bc68da131dba8d7b41c83b4e9cfb6931987b270c74919bbd40612f823114e4bb148671f1aa62bd2bdfcc8b0b24010ec112e883aec9746d0f5de467addaf51f8c070a359108b1f91643071438f098233ad9a94d0faa665a39291a98d14a861905ecde4755d00e690429c57580dcb6d51bb6186ce72ebb1fa8413892cafb8713e89775013e546fda30aeb8af9f7155c08b25810c80ccaa5e700c124cff59fa32e0293adadbcc7b1a99f67e66b28da614c5a4ccd706afd05388c65ebce07a543d3dc1e5a5d1f307f675728d4c629a04e9e455b4da35236c677f26edc622c1fbf29568d509ea0690af4cb5dbb4e418b6162888e43b458774a31324bfd5ee8d2152e4ad43a3007d7d4af5fda172c2779837ad3a09e135de953ce966727a7183bf77adfc76430666b526692991d3c9db5bb377552a7801c548aa63f6931d3ee91b875cdbcbb7441a4ff81f86762332d7192fbc2f7b69a58db6ccd3558047f1940a1cacd6fa28a000b9795a2860394bf05f0120e6d85f96b1fe9de14e3ed66a31d747924b6ff2620778e0714aeb34b79a5d935a0306e55c36506a292c5dc568403551907e49a43a6263d2915108916f1e27cf3529d1b7bd1544af83a7cbe58547f192a93ce5c5bc6d652405ffcb95345f522b2d34e8ee0960bb85537a46121bd9a408d283a125eaa745bbab04e2231c19ae95e13901c69e5c9c4d70b104478f4a70d64f81269a8000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 51&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000029139d84e7223256efe74e873db962173e30471dc8af2ae4716d552a4e1040de365200f150c8a5244d05fa9d72329d4b58a225071306b4b5da50c469a42b1bb876514d41e08ceed24cdb973bcbdce1a21ffd620e63f732a5bdd59070aa84c520736e07c15ddecb7c038303b8a21847771aef94bffb9293cec4bcda2aac1b8fae23e8aeb90475e6665bb7d557a6bfe53c84a41b728d7ecd4d992d0c59c0fe2472c8eeeac249eb6eda1f4e58fe193bbcda3ccde94f178db428d13f2eb7f708ae2e4dffd39e886facdb0881e4ba4b1c0c8a21b263b4123cf18e21fbe2bb05a52688df7f67afd143e877fde54300bfc6f06e5e3719956b1b872fbf1fb7ed615c45670f86ceb0020b6c67ad3945cf398e3f12e4bb54c1a4b01515af34a4e2a3e225e16f801955715899b2bacf22eff74d9843b690d94be1ead658e7c84da7008fccd1f9c53a74cbc04af5e1455a7ea2088b736b13ef43d643721f8cfe1220c1c3869aac9791092e60894c48340880aaf9e124db2d5fbd6abbe0e91e833ca631fb147c6edd19a6cd8c59b6d4ce8ad2d94cecafc1999cf3f9d6ac820d2735fa1b11b149313a14854b5a9f6c839eb7c3bab0c671d9c1448cec3f58d1292655889da045a635084a08a9aa6ef53a342dae6b74e85f6b4f5df08c3b6f569fe461c40b32272fa6132587a9c153e319ddc2b9ec74ce3b1db94cd2b69d65cb447b3d952f70219bfebb29883b4e65371d961557fac151ad76fb3cbda1c37e70272d9c7174065df688b0fd1485c5515e341b2ccb7ba9d664ee13f9cdfe0617ef3fe6739a1ed042dc677a22d9b9cdd755ddd9924dfdcb1957bec922622b7dcae5899a4591f39ddeb347e67d3fda89761235b79c237b290c3a087121491e764ef84d59f9f41f30d0e6579c3b0d68f7b9b67c0ed1215e68705420c12000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109bc3573c92d98a180e9a943468c0090049c6b7d0f1c3dcdf9a560a5e1790573c8b18ceb929a2c95045ebe243c19b2d30d385294f96a5d9559bf06ae727f5a8b2f164a59e324cab93c4966f3471d9f403b04914baf0e5e26d3d79e1481d298189d4f8d8579aad6b35ecba1a4f4dae35388bdd44f85e6c37a5678035197e01634554ff03f57fc27da6977d89dcd37fe00512327352ac95a22ea2ccb7b4116428ae820a2899fc1b41ea58dee9a3b28a70f9559e1d37761642c2a0ad83d42ab89f920a6b6c58678b1ddeb3b62d084e0ec000c8af94404637a6a502b5ccca89ae308e28f3e7af1cb2be41002269b442e0326d8d7412846869f51d9a247c91196dcfaf2835bbabadd02c6bea7185f6e9ba7f6dc50bf79e350f3047f5b96ae64099c8c8d6c90946faaa73eb86759f8c07216714a872dc65ba190b8985feff71d89a53b005129560a650806ec0304f171ebaf8de49deabb982ed6da0d101837b8a67faaeabc6391493332fd50020246cc41125336750e043b662c771f675f1b3db378a34fb779e1e359be856713142e16e3aad7404c01948c9db51a3e97031298b65b0c7119386058003c1280b70670927c73730320b813521d49e965635c46562b7045f67581215abf17a4585957c0966c66402a7668b35d54a255ce04fd8dd29a56ce462f523698e8f093fecd7731dc75ead22e4f24bc43b7ebd584111e368bd066c77775d9676281cdbf5a1164ceeb8f127408970dd90634198c4ae965d3057ecbd73ae69a4c000d4511097c74818669802a0e7371b58012c6f25564c8a7b61df094a01b288756a1438908e21a672da20a9271231b9f553133935b4bdb1119a09b4d6f8104261ba0a1912f611e48f36766b4aad15b8385a9d0ad6ab463f3632b0808f1d43591f0461ed683145f500914748192dfc87da65e95684d9f89062029cc9de8a8ec37d54c80c77daa0985ef553058c21636b9afe89069bc317885689bcd0fe51384463c0cf0e5852e5c6adac53905506b7d2598ab2f990c2f21f7f573abaa6e2d0c61d5eb8d70adaff02be0140441b090b4db9677c0ea2bd392d318a5b0a1b39b1f08026e415d5e0e09556c2a50d1cb9046891423d4a7599a0e98a0ae3a952a9df557c3c658e999c77517e8ac6e6b8b71596a2db8da6446d8808f50dbeb1419319f748d1afed3b3652133dace8613b675beb5685db82765a3a27b6f5c0bd53388ae625b923196a229dd17aba86122c446e600296a6a10ab1908a66df5e628e30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006d5dbfc582ae98d8fd326fae96a1849efe729a1173339d90c48c3a2b867135f1dff5b497d05fd55130694b5f9c62d136647d767ae682a0f05c670ceecc03475ffd39e0bd4e45b720d9d7e8dd04e69c969627682ad83f48609f6e66d0be99064988e4654e3913b7caf1475622e211bc247b98e5baba1b804e2bf651713197d8a610cc111ba5fd98a053408ad155dcb756d28a283bf3b20e6f3785dd5f105f8d7d9f2956064860b097c675630edee1f17e2eb0b26b6c20e260f9a5915d63f1be2c74fb0b37013244481a2d0c581c4ee12516e0fd4701e9835c8526a490cb39e99fae07c40236808f9605a63a5106c19517c3711ca4b9e8eddc77b242575d904dbe64223cf14a8e39feeda9d6c5f9cd0d0719a7eb5efa71453636f78cab8262636ff1e136c787e38a43faf02699c1f260ec45b068edbeebbb8a0e08ce282bf47d27a33216856f0c59e743deb13397656ff17fc4b3c694b189c35e516be719cda6542260d1301df93a5d93ee118f7cb0ac94d0364c9ea66718a4bc7f3d7acffa60afb7100f7d97e98dffe167d1d8e46c912d41ea057362c13b078cb1d9c443c1a57ac18c4566f5f5388f47a40ca49cdaaf34bd4c9a597ffbf7ab20d7ce88dd76a639e09ada323c588b08140e9350268c1ff76079093a05ccf5e1613a70e6e37cd257875049a767332e5f7420f319f9ac78f97c0c4fa40b1eef8c8b48045c78f73584590fe41f9f274dea838de75dade66d04e9d9308cb0a9948320d28d9ca8f1f51e39ff3de20fd5a2a267d127c317acd51fb779e597a8dc7359d920548b8bcad761c6b8012304e12628a2652d12a8161e538c20d582bf567e9c2b46b4cfe2d2da31120c6df50df45c80513aa9eee9f2613a221aa1d23f861c7f26aac7813b7ed7278eb420a5c44f2a5879a2f1f9f11e14602762e3389b152c014ea9ddc9ddde9ed1d6f74e7526f690ef37e71d448342c012e032c00e480a699ade617434c12da0e69139d0d9036743b9e2b9134b5086fcb96b193330ace8e4f77148ad0f532e72e1792795080b54d7172fb9af1972d00ae24d0b3d86528675b3bc8c7b80598d855b95a77667ad0f671f00039c08cc99f5644bb006ba9356b9c02bc935212c43490c741b0845cd7b4247592374aeaa1b589e670ac62777293870963b5132dcc27088f5da5b831fa570766fa81c2a07b88bbd45b81992edfd2a7fe934219b1f648dd8a414fa03eafcd39e72bdf7d4f6b9c1f31a0a67df03f6709f2be0e7d1b1690c92ce7b8c6b1054270d796b16d6e445d24cb11229cb0f92dd81190a37838951ad28be2aeee6c5f63da60a911ae0a24b1d05ef2f814fb30aae8ca3bd9f01d4fabe5b279142af948b0e6bbccf7560107c161c816a0d8e61dd908445079baafb78c14f68b8b2bb241fb03c237a4cb250911142d0b460acc75e6b0f58bf28546a4779ea7342238826f636a510cc9cffee8bb0292a58a07694c05672b560b26158a8566d01d0eea0773e81f3f84376b29ce375fc56a0689a7ca5ce94b91814b62cbb61ea2efca0ce6712a941d612b0f700c56b46d464c2aaab3f64a89caa8561a1dab2869d79da1720274d031946c4c7715fb9c243dc95cca7aecff55eba4044467eb922e93f57e3e39b93876a03936dffdd2af48d055c6c188f2f229812ec94f3fbdf7d7db62e4274dc91718710eec2ce034aef266207c5ccba21552d6fb8ddbee8e931067010594a9e0cb37250f67281c0a369965367424d454cdd05d3c8f35a15f76b4c8c3fee42f4c9cad68849837ded3be58730b94ae3a5f9146f90e03b4c0836381b3f9ccb5de6bd2455d241be9132eb6d4937ff27663f4cadaa9cda193919f4cb0d0f727f6c7b26e831c3ac8decc234d79d1b3bd28305e3012a3733ad718fdab7dd1a6400bc47f47d20f627d2449dbff10e37a62299e22e408a28a806d403cbee19aff6fa9b1814b35b9573adc86f829a08893cfae4a0212293447d3086e21bba28049f3ed383519917b169e8a1b7dd64cefe0da643a97950a205cbff6bd9334180556e84199f0b60738715cd69aad7c882430578f6fba4579d908f863ca54d0b9862eea6abed31301d183cf465b1a256cbd597a629307a8a890f11c23dbff895b932e9cd2f5f06a4183d6f2d61117126fcd2ce2b86bb44a9a5b402e3eedbe4ed1df11716e91a2302cb72d8f0dae132e16311c80dca041694af1ef63f659959fcaa133d9e5668f94d0489311af3bad379de17793bb3ee8a284529a72cdec474b3a82d92c6cb21c63017f262e0d7dd47aa5c58f5e23f8a37f00d5438717f05bb974f18a5d3e1ca054ea053c30b34fbfaee88bc0195f061ac32f5b71b2a8a3ed4b8bc4edab40a6396c052dce72e10768526c00610e96df38aa70938cf844cf445d8e2bf73c4f32a742812d8c1db53afc6b6c0a4bc67c3cf7579702312d6c89bf14e9585d2c624d07feb4b5b57f8e4c5cfda69a5e922cc1e90000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 52&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028d39f66d8816092be48b7b5671164c056c8fc2a63ae8a966842adf7f2e8094730b258024ad78f144b0a72def33c4848746351b892fdb11ca57bb5ee817cd3dcd448a340bf0490ec4a79db1a820a64e85ac70373ebf945c85dfe058780a42dc4b66fb220bb6e83b78af7a3eb2cd6246cd8c532c8c760ff96023f2942b26e8f264483a4d079ecbdec587adf8e2d02988dc3a3a1a09ed02526e4f6d2a56891b373770804cd2862e2eca899b6dbf8af460ea012bb4c3706f5b894e66b535f7cbb5c178365bda9b3feedb4aab886dbf55e4a4281feb1d154933362f74b642e060d6874a7cc4169b2ce71790826ffd6ff6c1428bc3e97d52d170ec4e1eae8246a258f6dcfd7d4e02886f39781195dca15015e200acf5d74c86aa8d866161b272bdc4257b06cb3540a2a64d15eb49f975e18cdb9c92aad8445114341a640141e4397b6ddefc655c4f8e9879d4e62bfd8de1aa77c2d5dcb1db1905714e6f1d1905a0d05cd27736693b28fcbb677762b1449f442d134b99b8c9103e3c067b3cc7b7e8ce848c621d4d3b098f26f4a6948c7614a779d6696658b51d0947bfc3bae4587ece4ab578e950ee7575f6fe7c673066dbd06745a359a9402d5a8d9e98c0b239260e330b7fa02c99584e08761f55b771a4126234b757e36fec04a97ff61ae3b7729e772a123afe80a46a3677c9e99ae0e3e312c424757076d898ddf56972edda3f209631dff8cba56d48c9d9f38e990acbe0b8ca49f1f3cb2932362f09334850fc160f03dfa42968ffa58e8e427da43861b5e606379dc1466d733bec159c5fbff694521ddec52db515df4724c9671b169b4dad5ffa1f62bab8fe69f3194f96cdef505d42e050e9f2432ab2938a921e39112a01ab4a769847e66fa6e27a95783993d47ca934e303899c2466dd32aacd50f40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003810953597755ef4befa2567ed3892f3d0ee9779bc99a0363d1bc75ea58f54dced2a5ab23434f38b0d3ab8af596320cca7c579415aac3f4eda19a05527667db503ca552cb88f39f972aa4f57b2890c06a7ebc65e5dcff5ee2fd43136c6a0a7ae6a3bdc3c709243107f869741539e90981c5857daddaa56228c250d461c2d3d3f38241f94ab9afcf4d22be48d1efc38bf1936441104ca6c4d5a8db17f11ff8d90ae2eaef37f202499fadeb9f8d60ca42c70095c674d2f4c7d2484e8b12790d944812a97317eef72b1a2880055f5419b68b89524e941378b614cb5d2b882d740a9c0337a2018ec61622903eb6ca6445eed971d9be2b61ddbc7fe629f27c94eaadaeb763e68c5c034ec7f11895a382ba788302ec1866d519a511933b023a3c9b5e0c999a91659a288b7d3e91efb5649fcc61f2e88b3106804e1e5a2abf96c96c75093b24d0207c0169fad4a4c07bba34407d15f5541631f28e8f4f59b6a5e8e392e021ac27e01363eea2641e07c54ed62c0cb51530287710c88669db9b487ff22e59a7df8d7fe10a572c853143812393da4832378ab0228768204125f20380868b22915e725027200c5dc540ab150b3ab68e3a43444054b4b18b54c8c529e6be1aff1e589c929e495193a9bb4238c8de0a0675558e21cc152198d8bb781e62257e61427b878a62752e28e56ba34d0cb9b82488a763379d3015faa4f2a3340806a345ba913efd5374c6620b7dccb9e4116dadb844c3b74f42141cc4f50d26b69f622d0297d7b71f28451ad42ac63f6ef3973ea457176e9e303c95ef09e976522727f26b90d030815ba387c6c35860074b4ab1c644741cde49166458db1e165de9eb338f228610e2b8312b121163c2d380a705b06f4474d00029fe888169c9fedab5932899fa3e846546d618f149caada2598f23e0125c92680e602dee4c694132e53ba2af0e041e344f9a933a82ef18845cdb424ad3b816c1b08ab639a1690ed453c69c8a6e87d73e4519d07a049aaa7c2d02494438bc51f54ab09aca3cfef9a12d4b9c54c140486a048933f43737f5522b5062915a324ec9516698e486192d4920e1f58d4fdc9a30fde3779b88b601826801ab02affea199c19e7f28b084b8f4286b30a01b8ac62cc2b9e23913e1116427a85a15a0d888a6568be315a44d8c30d9389d67ff6d68a2073268488f720e684e56527275a8453a9f0886503eb7ab17c38a80a38a3d930267c11f80e70670806dc3609e9ebbb50477755c65f983e29cf084dd1c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006f66103e5b22f934203b5ca87337095c9a19267afb9695d309beb8a557bb7cc90332c4a03e1d416d397b945b607268f545928104cffd71b02864e010b666cfcb68b762fa5ec839b5aefd0407419441b38e6d881bd5218df73c675df101bf2c53d90ff86d4a3c7db19ec9cac044e0467a36337aaeec32217faf86cbd7bc2b663421754cff1200a8a66e18f812868bc8d1c8ca495e6462da4b8b96d4167f040f04927a7c27ad35cf174d42684ed55ac80d14cbe4cc2570642ddec4f44880d967e9af77ee27d0d3dbaec9067fb6fc957ac4a136c1d564e17f59ac4938d43fb9050d810989907125c47fcea6c162c723e79f68339cd1b3bf596988bd6e215271385cd50616868c6bf40fdc34bd30e5a00773e2c039723f2ac3a3fa45f4ce870841762d7435bd6ccc5fd3d58fe059ee455a806fde89155c84797fbb73691a1fc6921859e99066a3239e31f28d1a46100db1917621d9e61473cf1e71f9850b584b459d5690941e676a7dd56796313ed9abdbe03dc75afc1430dba27fe0f8df48ef7c339f462af1a6d30a5f8b480dfbbe860c4c0bc136393c8fa0875af454273c3cfdba7eea44eef1a4060136948cd98b9d2c19aea4934f3455f31dd15be6545134f17a195b6bc409159c0975e592a15e86ca4943ccacf4b46719a072db8c629b67768f1956f8158f179a0b645320489dee404c8d0c4e786cff39b324053f102c118e7d51173cec0fdd017f213b2b07ac6b2c7dec04172dd5396a020edfb74ed86fc31952d241a7c3d139def543d90976aa70599792e73cf73ad0bd4a359bf60dfb2ce96a784d8de5e23a95e831ca6ffba6b187bc5f29a7757185ec06ac882572ec6283a1875b54fe4f295e1970bf311dbabaf9f894d3364d68f529c4ef9030ab934bcb09459d5aac61919946fd28df1ac85876f979e8b8528e9bbe69f03deef136eea6a8fc86f31bd64285c8c9f49adf53a8baa7867ce52e72dc4a63929df3ba2662dc77d71f88d8af42b8d67ad54884ee11f5a6b3b794f7d5610909b0b740937587cf475da903159994a262b6f32a3d1723fdaae65e636b71cb0ef0a744f359bf08ac8231ed2970ce8c451266f703da3b57f85aceed4c1c174c50d9c226f028e972ac124faa6f60518699cb4c499220ea51a538f9ede67d0e98e1bf8fb4b24b1d8ef50a28a93e20076f8fb812cdab04871d331ff434ba66dd4577b18dc3f471b3e96a174b58a7ac2470eb8463a71ffcba2d064470fd2d4e15f9491db09df3e3ba376a3ddcc437312be5848db3b9079f2ae046798473bb970d725e1d7c6fdf405ae387dd7cc1735a7fc27d1a476592a514b87c9017e1e5d37e338f37916f3c72c5f2af75185b88694d4e8e0a93fbf20ce81a7a0c10d55737b6473fbd92bbb39febc6167336beb9c235997796b9c0dc18c353e80305175bb412acc29e647813d0003f727ed0577a7c14bcf67173da569320e887bdc8f5ad27fd8864261e802a6753c6f9bac844b5900ed0d4274c0e6ede42367079188b10bed5999501164fa4c5a818ed6ee229c3e0e0f7804b19eaf5d1132be1d7fc18be834c842b21f8ddb11f8cfaac10d2e124981ed698ee7caca211c5624f09c62e1d451429048b55ed0f8a714bb77a0d4b40f0a446eddfb27602b7bf894805c4aad9252658f6b21a05dc0cf6a3acdc227fa867a4e5b1db63a14de26a79aacf1900a7b7d867c15cfd1daa712f2a1e2a6c7b31b121465539cd0164e3ccf79a978b543ae9602996448c6f68069d044fc958911ef40b0b9afc78ed014d94571f6771ea5e2306a7cac32c135fec0bbf1dca3cb0b57daa239c01671718017c907048e0d19515cbf430d4b3b4ff4fc9a391d15a38b39c4e528fac04ebd3dc69144c98afa75102d21ff961bad2e1f25562af92554814405c4ec08dae4a0cd28be592c9c9bf997cc0fe31502dd541000d4640d59654d26ca2a17ba4cab0518ee097c05b2984ffc56e8182368e216768e0d07e17fb64003e95194d04c6e00e08386084febb6cbc841e8f3fe2a069c45554bc502c27591ca3c1dc9e6b1694ba2c1bc0713c1cf738db22ffeeb7443d72d5bdb975d192976a58ab33db58f5dae497a0b24011e15e3256ff124dd99af6fc300d1fecdcee18dd4fbf25e901125d4e80efa8e2a211701b74fd992e63376996994e054cc00e7e1de7db8e7d2898a735ec4920dbefaaea66b456cf6a12324c5d56762313a627b3523ab1e2c1c82e4fbab136ae4395fcf2672a58011d96bbdcf2a7478305756d66b30a4ac44e48b18a5964aa89f14187ea114084d52b4ba77755ba04c34777409bdb782b7b645e93b4db284525e2f9c9c38d73b475dde2251277a2e6c3183d5dea78414e22cc8fb4b2c7efa797cd4a87ac81d3242ec8d2c2efd6bcfd69c39f14b0b365f3151a96f75454a3a1400c76a4390fe9f2e7a22a0cfa687a5bef1c905d3a893b0dfd35bda184f25e62fddc2a52b6a67e76f550abe4cc8d1d63cc8631e4cc315e46d3015c3b8636b92b8d07075d401c654fb4a00000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 53&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028e397521de03da845cc38800822d3290ab28ef5e12dcc184eedd6250f4d0cd9675b225661e403ea8dd4f0792da0ad5d3c1b311b2c3c985a9ed9c1a10dd9a058e3e62cbdf7ac596dd3fa55dcf84caa1288331b180200eaea908445bca2fb7573a51708190c3162b54023b536af818559a593bf06ce9aa04dabed11367f33b02f560d34edab9438a47ee656a2303502c3833377e5acd12c12acc42ff76a5befdcd5b2c10c26cb85e39b2c512af5d855c7cd2a725cf632d3c034b0a37571f26fbc12d82a9b19e4993ba6cebd0bdad713abc57b0a44e6f52d9e5ae48eaa54342dab1856c8c5791115a18430b066acc367dd990506168e31f9ebc892c5c9b20ca099efda15f8d06231c8998efd247a1d3cf1356c61178a8c520ba7cece502a0613708f98516b6e5637550ee467f80c5236830c6d2dc4e1f40a2d692cf7e0b9eb223f84ddb2744febf92c67c8e400426c47b7756475a26f9c7a04740cab47caf3babad838d9e27ada4822c1bc1923f356aac82c091a0e9290edc54b41951f4abf3ef39c9a4d681b57bc9065605e56275f3de7aa5d2e0c1bf1a2905ad3d8294bb14b4818d1a274788ea96c4d9c863730b741993e5186ca6ed55c929868cdfc71015cbc5fc689b24d67f2bc5cdd09e0721d4af2a798faf0f9440db82c1ea42f51a981c748bb5b891acaceaedbfa3eb72d32fcd24aba6e165b32e963a70daaafecf20c61535f947cc31b4ca24058c8e1af8536db64450a91c8eb7621852208a1f483b7ca91ecd063f39e63148f13745a088f6fc49da8e03008c634f04222f0aaccc23e7335f0498cb76ddd55b94a7212c8f22076123481a0f7cb4605d4601a9e044667406d48fda770e0cd3bf47e596dfa35893c5ed1004af1987f224fc79161143dbdc331cc5de40ffd64b8db2c4db79bc70a8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109501d44c55351056f56e6cb5356251c7a2a17ec22d3753d94a7e70ff71bdae0e88c237f1a7405f312abf7b8cc3e335c6b471d4548944c1dc2a0b6120084a7957749414a430077422e6c259b80b54d51d8f62fab3e56cad24b8947ba4e4e2680cd871f58aaf4a463ef6b52f90e3b7fc50e576a93a94f44b101ed88ab0a980e86f4b3e3cdebf1931c2ad76289ba817e59a3d1a29a3592db572d8b6763010df92ba11451faf15b2592532e581ffa6f0597783079300fe6b64ed0e2115dc5e2785434b1188f3557c1add755919a65fa8fdae35a271ed1dad8fba0db260d36e7dca5396d8cf43155cb102dc623e836020b61f5cc8a41472170aecd62b854566eddca71d8d3d6a200b7cbbd844754a864f80544591ab475ea91862f9dc635f82e902f286effd41f18a86f1c9f38c1c846b2e4f2133f5f379ca9304808e67a134d9e0386af3a957c79806a9643925036204d9f5c2eecb070dfad3c6dbd845205e401bcb290a6eadca59bad3fd0f222ddb68405a02455f5485ab18089ef2534061d87efe360078de7b1595bdc29f24b64ce5dff680e4708fa4b328440da1a236cb9469132fb1da8754fba67c767ac2070aa2f666a8918297d66d41f53be2270c3b0baad4e37609869bcd92e3b566f76d45bb62078277985565f93396647a74b5f9a69559482059fa9a95b85dfd24c5e208f15900236b052bfc665cd7dbabc5c40f78908abc181886710128314df5b1cddc87a514d4684a1c710644d53cccb577a02a67936cbdb0b2c1879e3eedc25117ad59fe8f19c7cf8f5d999005229944a29ee349ae8e6bb85131910c4a3857b4111945110e7a298b15b599f6a8e9c31310aea43b6927b1455ac52259f259cca2e8205a219bfe16f9107284954b28cbbac4f1620c6a473bf8f084e124bb219cb42731e0403562f5027c9765572e06828bd95a1c45afbbe957afa7e2a11304eb6992e8ce7bef196328698b722c45bc3b6ece3180930a56b21f970b2af9acc9cc5425a83c1c184aa9364a4a5cf0ff83d3200ebbc183e1f4ea2e29bd9bf1ca4a3706b2a0d461ad357861097625c8f1b7ba13d4dc05ed021d4e3326dab07bf99778c2e0b49bc8b2e865869665e93b94fadfa673c8b1aabe5485435acd7507aa4e81263eda382c52213894e9c923f74b625d6a424817963a1029cee2888df1fd175868ff7821a4526f957c7f55a8d32c599b7b32d56a62489141c69c372bd44c2af290a9dd9f869bd1951ab112e7619e141598e4ff849ab880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007173eac87b3d642ceaa3dc904ac3c4245cb2a260e4b74d0394d33d4b71024144180a727f80b092305f31b2526998edf6f98e46933fdaf0e8709e98d54f13c2701c58bbe35292fd3334c5e03d345a9a2ea1e01b2c4573567ff1ff3ba7406a16f5a5805edd760ac78a3ab8602e415f67c7cea5b36421c79f83cbb14fa775448a832a4b28851ce215c11dcbaee652cdd7342b6b1204727479e6208fb556cf08bf7ee230f32659e829ce4fbce0955d01d36624bbac18c1d25a3e187722f8f74c88b56e518cf0e78b3b0eac56d8f13c4afc4da3613a41ccc2b0b0e2ebbfe5799e479f81335360d483596e9ae926751ec9b956555f271c2ccd85f0f6c1bbb2c326c29b5ddf6b5c4c11f8eed15c0143993feb626543e92ce4d66c0bd28c79ed1ecb793a3091d6b9ab510b0d41aa42d70c2d8f26ea0b826c8c375e1dd89b3e2a48fe5d88a462deac33bac35aa32ebc010af7e47b77ad23653d747760914e0ca12864cd401787efd96f30d82d8907dc68578067703dd19b2377df319eb540e8ae78b2be86bee1c915ff3b2f4b25c0ac22ccf89bd85371961944d8a4e6d20e2d3e9df3a07d3bf6986898786f0667545275fac3eb0f069b457d8ebbe5f60125f94756db04ea203451a0de160cbce2a34650d92f200448b097691a61361ac487fbc3c82b2bd7c1acca02031311971c3cf69ba459a0b640a702db4467973713a6f2466560ffac0592d64ff1d4a935220826eb559cfe0144ea4b8e54eaf67ddf91988dd4b3749c865008c0c1cf98bbf76d929b85c8c426c15fa56706984e0f2e90658fa3cc33ec9fc700976870c94035ecf9a0534b18d07f55923663835416e40235cc2550bd9822f0912cf101f86039830ad9102aa4a3b6777edec5ebe621082fcf81a1c6a528f0324ec9d39fa80b6e87d6366e7edaa0e14337d6708f7c3d2fb1978f4f5cd594fd35b267f9cd09370d3366dce286ccb9647a1944f8d8be63e5ef8f6108cc5e9afe9127da84e1913439ec35a4e17f7782df042dc2f7c5cad8a659db282e61763539b56c2afa0f2b507d549ec8c9e76c7db306380cd7b46c9699b6db8be06cca15e8e83763137b06bff02de2738a46c61b70edf4f394d54d0453dabf689fb6ba41616bc589cb9847224e74f919b6e03672ec6a52584fe81456d6e648dd6f0f9b068eb72241f067bf6b891a498a9a59356c735e10efb37b3ecf47cc5620a35442dd81e25d2c6db0e9e871301add193d628b30e3b4345751bc17e0b5b05af758a653de7bed3763303ffe1af05e407f296c736ca6f4c348b25718c7a814bd0730affc057842af3d9b9adb12fccd740add16218aa57e43835821a2bcd70f1027f3042d4a92f10d0a1fb8323e87869bfa8da24da75f8743fa3038c24fedc0c987065421bf4b300be3ed3f6d6d590968d3ee32a8f5e20ea6168756aa18bb78b6aa48c299c36d0e78b6f84cacab5946c69179e461f4c2dd201d8032a29ec6c52942ac37d9c76ab4a401c9aff96284e1e9e39bff6d912ca33b6118067605ea65d7f611dd963f4f75f97346fffd1df84c79ccba06804b3017775d8c0bf614fcf4d824709557937b22e1805a0a961ecf226f26e3706362bf6d8d1dd30be7eeda481a64961641dc57b9f0211f8ee43578e4c2b6507114dfff3c3f884586bfd1278d117f7c6014fd5980cdf1e2fd1f34ccad170842b9e819c22fab9890ae265c3bb6946fccfe218544d00a6ba5bef5224eae24002b6e83e0b35e98c2322be2eb3d8234be8b048c54e40782c9a24d7a8b461ec05f38a94aaef3da3b46d0d85b0d949cf1089408189ff97c56c7dee50a004aead82c15c7c0d0965f3c65a9a715a65d29cd3614954ebd91eeb4e74f862fbc944c56f2edec4d344f92e8154708ad0f5575880503ef0f107a9a9db99bae82357c16578f3e6cbdf9b427da88dc322d11c6ab2a6ae6f5179c94454e09df5caa6a519a4c1903c8f2925639e12af793695f256bf0e55e0d45b73880358f09719ed89a4a1a07868bfbf16095a20035d5d4f99fda19ddae3e21cb98308f4508b5cee706c27898f03a2bf14f29acbf055e4ab0713a7b6fc1a7853efd36e1290e69587fec15d492a66b9a4fea6e2bcde61e02fe18e06f59a2f4e06f177b14ce4c1cf1a8d1f49c554a8a4c68b9937b4c230320c80753d4b071bab2deda89c9181820336f1e766e447ea1c44e15cbb7c002c1813d2c1726db0e4de289466077da9610e5f3aa313b1b01dd79a4056a8bbe9d843ce5b0439325ffdfe91fdaddec6cb86d5cebb68d8f9c0ed237a4648c412780acff48fd9ce817ea70d950dcb989ea6b11fd87ea4f30347a27488c5c15be7fd6d1280fea3a7c022f8d9881fac93176db2025b4c7914a51099893a791bf5be851f325347484ca6ed51b2ba71548a6046ea7ec85b31a9967e7d119d2ca3a51c1e14d5a3eef0d41bdd615da01d45979007a1997de281bc340c3203d5bc0075b1aa38873a9dbb9d18e6e26971e70b54e41e2c8c91d2e60fbf85435c1ebc4893c45a201b1d2391549f52a1ca3e0440adfb746fbbf0d9933f9fa0220b3e04ebebb29d2a9ac1000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 54&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000029239aa49697d2c3cd7f903ed28a71d847768b9dceb9db330b3fb18409ce609bb965c35874e6ac169f6a90d9b7550b9b61304c82354b734bd1a14c473717c7533211f242d013ca3f622af135bd7917495ae0b58ad93c40649e3f77fba8e7ae15ccdba103844c21b9ee8eaa40cda999f63b0ba223980277af4ffab74b77355f2c6e91a4a16ee30d73b08c1f3911229344063cb76177c8bd04a452354926cec14e4f6e77b72a553fedd6219cac927ac6a02ceb25ab5a26efaa10c4f6d4a692e15a3a6fceba069150d8dcbdfb4a4096bc027bd99654ba48e3302a2f365b06acd6ac0f747498dcb9a8fd2d1ceacfb489719e4b5be5979edcc79d7ec9c467d47e0e0d2feafa1e73c4ce1d81fda1c70d1bff0a6b6c0be65b13fdb7b2d7f935b70a41b32a069c8f3793bac28b7f4c235d34ac649cacde6ef89830ebf7696095d6bc3d584ee9f1fc648e542524fbc5ec51bd3acd3d5f9e859a1dfb6cfc95ec9ba3e58de3abf1ba6eb284ceb8cd47e5185f167861eb5bbbaa9ee2b0f436a435ff6b7fd5b78a789f5c36f32e91286d48f328b9969cd4750283328a4747326688ba6f801cada4972305c7a85ecd2337502e1d69652bb84ab26da3247207d9d0a9366b774ad84aa12ce776d0692274737cde53ababc419d41d72c2cf8cb277c247ce1c72e9b86184090084b3dc08649a30e5134d1afa2133c4b4a7388522dc98fe58e6854678c85f31d51c9b6402ed228a511eb9faa9106da951a4fd25292b11deb545b828399490bd2cbc965697d720880ee9d39dd93b125e87877d7cf1fd36b4d741529f377dae238ecb5d7bb6f7e1b5170e629bf1f84212c489936f54972b350dbae090a38a5211091bbe91cc9819d3bad87be82fb25066f9331891339be5f3f138720dab868c62b0c2625bfc7c457a695e2408e9cf9d34000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381095c457eb82586534ec04bfb92022b08f4fe099e6da408e1b394dd8cfa2e0dad1b405c01513e9e07604ed6808c765951e0745cc09810d5ed6c984816545c43032721ddb89e9335213e3d60f845594ec64403e8ab3f381c15503a469f9e508c46b841228aa67eebf924e6b1783567fa5acf70d0f949d5e9c567954d14d2e4ab5ddd53d430518e877699c8d427e9a592526bee62cc4b822082d406759a026d1471ec36068eedd83ec33779ce6d9a8adb0b98a1d84979dced4accbea0b5200f61a45e5bc65dc403894f9589c1be5e36a6c9a78abb2accfb3bebede132380e78bfeee929253b78fb922b5289b163dc179089b9084bff2e9d1ae0cd56aaa9ed1249be1b332ddb2c26512ba7d4abb2e0321b370680b69957e58c67bba6d81466c998d4a368ec071e1c43b0eab029d14cf98ddd0833b86e2393b27445e8611f150a3681e022822df88e1a26ccbd52817316cded7c308c435b8d6459910565fbc8c3d01b784b8ad12f6f0e219f1a57d1839bacc8133248396ce9f104eacd3f32c538f82eaef752ce50a04a1bbaa0e6c531f023d95dce8360199ad417d518a3eb2e521f41ee9af31c9c84953f2164a08492591365f4c0737c49d4b849503e5f897ad512a8ccb282792657e3125146c6971a68752e9e0232e398a8866ade57508c03884cccb611070f0baa4644acc82c821d78331b05911d01ac581f661f65f6f1823c2fe912313f7830da4186d012834ac6854355289465d24991dd3232e5cf8c4c70b408fb9bc006160d38de09d16b7080ea7d407f9a147c2744a3e79bd22ef9fe9e7863784f19b959da90469c54584c7cace41473ccd6b03fc2d172e21632a6568ddac1dff212625814daea609e5500badb177c8cb0c24118eb7f3b96164626ddd1a4e9bfa9471e1a92f86cc37644115856aee33d192074d90084f840fc6744e818235ff785e08ad40924fc6491a166a057c05f86cb856adfec7c42242aa6d2797a797e01470b0c645d60949fe98bb07d81fa18268c3de610bbc6d6827b2193bb16295755d069b75f6fb41f9409c8cb96383891b9e5f6e98484a8a7134a8893a43a64c7ce243793d1efda9b8d0399f10da6b787e5142d0f45eeaf530449929067d2b0ae5d6f9bff5d1393411720ceec394092a8b87f8acc3d6dc216bd211d41397599341cb885c034aa264bb8ab88e1974a29bfb1066a59eb131c435a6aa4655b273c988b254ce053797d71b8d70edb71de40499e17939a906d146869841501b7092b6354000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000738baa4a41e4b68fe333ffa5ee97fd3de18f0eece8eb83e46a8e3505e2ef8aea2c4040ba3809a764b681ec7449f41a2463651a8cc6def0e4a058eb843ef016e5cba8d55f925e66524be55cb98fc3169082e52e0d6cc3600c4e8a560b6d448a72ccc95620101323f98b43e28d6357414185ecb0263c7bb94e7f86146661fc897844cf52873114d39123260893def13516f982783b927864b61b56d3a8e5b4705da3a95f6d12a6637c9ced02f07b4aa0b08b4924103036c2a93b31c91ebb6c5b77de090ebf60a04191eb6ce9cc9b550f5b0c9104b74d15358854181c0c5640fc74caee14fed6577fd75eeca14070b6d02a9a421247a5bb262d6e62b04649e75bbd3ed8e72752289fa7c1a68096dd96a4bac8a2dc27c44881dd2416387d74a005680a3d229d562d3daaf8dc37b4c87cc86a8c991e9327cdd43ba930cdd8d1e44aefb084b51111965c5dfb0ee2f09112b070cbfc545119aba823eb3f65f26bcc025b39f79be42c0396c5fc9fc924ef1b7ee9ddb71b6e69b579c0a64c5b020206cd3515b8d5f4ff29378b9580d282f7e5eceeb5ce9c09a7b334e62151100cd658dfffa66f4091231bea6c9de8129ec4f5fbe8be0ff4bc93367dc69d9e38c177b23afba5c27fee3e2b73c0037dd7c419c854df7c2412349bab43869469e80527c3ad3a7103152f9e0b03353a596002ff54aba8b14ac393ee52eb5564d63bc2738d571fa3c255abd20102bb299441b00eb988f3a5cfb238ef8c49963b4ae8877e6b317e208821510bf446ce6b06c33717c91c460924248382159198f09d0f5a25c1611b2d39cc6d2ed149fdf0e09a0b0b2bb77067182e386f5f6a55b68808dad98e5ceb0fdfae6a0315845acc7b9c172b0e82190a5eb7c58de4f86d883292a883045c62d6a1b3c886c345aa6158276efa6b93ab2188e47abdd25d332146e980e1b1e043cf63ee35a5aa01ab6cc62f77699dca16fa30e3632dc5ccd3253d01e547746c78021ac307f0ef1a0119ad11504803edad933150981c4d9fd181835c507651dc92a86737e3afd0eb4ddef6182872fbd31bfc6d8427c2f4d3a39bcbe6b5120b8cf2af5dc59949c92d10b1c6a96810564dd335e0755f9de25ec26c102355688c38250df8f96e105136855c8de4bdcd86df03f92977da16908caeeb4056f4a5f751a57ba057ac0309f1c107e594cf3c31544e4f1d93fb9ae7e1a2451e7082cf0c850990ee71ade0498f6a3852dc4fc128bfdb8abdda3d759c8d4f83fed8509cde5eed38410fb9f0a5f30ea45c9270ba2395df645aaee03f56158685a0ba65de3d2c5209a7ef4bdd4bbe0cdc966dd1bdf1fe0be06c7115f7ccd80f8012e5d17955ae0c9e4220076882f30dc5e391295994b9f809c09dbed8ccdfc89669f40492944ff20948080a4ed66ad8166b613ab2f4414762ae493ea6661950e8e56b3758a77cdbcfbf24fbbbf20eacd5cbf8815899a1c3fd20b1d04920025885388012d9c58ea842db9530b7ada901ab9ce46a12700687bde07fb99bf66d0c775218b8454c936f03558b899b59361a0c664081ce8a7858ddbc5e7c5480280411c9acf4d1ec45035d97524e9e44f963532ca5067609540c1bcb5627f99d5c61cb9a6d400f0ba0a74e45ddab5a4e8a765dcf2f3684e3a2661a78ac069fa38163ad9f9713eb45c841c6617697cf8a72c54b550dbe9c22b04d579b09aab0ef4ee8b70ca563f81ef9700c07761c944926f9a76a8c3eee1cf7e7524d65908c47c35b0453dc10db5b75123a5b26b9612c0ae18816a71f34638798dfca21f5073ce771500034f9a71feb8b621356c430b4d47cb1b59ad4677b5c679188d8861beaf52558165f691f65a692e8cb8d24abb74b8885edebbe52fb13dac16e3a8ebc4ef192fd10d71898e93547c7a09f8642aa3b4faae23e48bfa809c5989d3462aa50fd4e5c4095542c45e5600926c2decb4d18bb43b7274239a8dfa3d9de1bb9ca099dfe56dedfc9e120867efcda10b48f7e630506aa606d76e4537036127fa05fffb8b8703cdc8de70a78d014872111a431f393345d74e8866d9a9a633923072e93dbf47c54c4b205c60e67d5155b76f51ab49acc7435525605dd43a10c88a03e08e257c68937bf2984be63d40f8a60589d909f8f09688a77da15dc7b4853339f235b1bd60aa845b4db6b699325885c49df9c40781cc56fabea6201e2f8a9352c28ce321b9441422807e9c81c8f1ec85d240c9f1c8ecc4ff06d6e3682dea3e6cf92f2b74c2165af247ce0f5ab84460693254b523498a57e7442977f51f1c2f649bdf756e7f43ae543f5d8e692820f8a06322667a7fa9c1a5b10199a69ccea22c74e172fed43e550c68c337ecc5e6aad9f7eb997a7e619d47df73cb917a705c3cde5ff344f6fbcfaecce6b734e09a385fe54b224a880704d774581074c59eb0a3b42c59b8ba4518e764c5a532f6655dd839862af716903a118433ce0809376a88e88fa847b4d1c63ee393267b15c1e42a91dc6107cde990ec9ecc7c1066e9480e90a22907c51af47da837438a90cc07de8121691bd73802d5d09d18a2d8b38a28948735110891d1b559a73445838f359a6fb90a3cab887486cc9d95cba35b55693c890830d20000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 55&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000029039bb718041514c93427af2616d8c8bb9cddcdaebeb8b5721e90f1bd307c8d7d04c04f9f2ae8dfb9a247347ab9b167e91bb33aed7aa08daae7e3de2a0ece0d01efcb746b23705749c3497dd334f38b1ffabd946e7d880b10e22c1365aed7a3329f9756cacac435ef0cf35edda0e9cb55b735c5da20aebc95dade31a6531ded1a1fa090eb989e355505451b0b068768d274779d1eea76c4e9a479945a050f5f6b17bab3608368b86eec0e4e48e819e234feb40d3434aa9d8c5b83c7ad2281396da5f65d2c5373bb8eed29fa7a8401619121c35086cc13d9abe843d6690a732d751e7e3da654a3a1ea6a78cb5219d103f62b4efea61066692cf4d5cb877c73183792f51678f0fdce3fe782c9b594c3d8375496616ae575aa18360f31cef8d7b31a38a62e489874cb5b9963583acedba4995872f1b96190b1a9771854f6289767390953eaad0c314dba2778cc8e412a9f0e96c62cf87cd8bcf6af7124f5c43a91fc7d4380a35e98eb7e4fad4ec9e672db062057b0e4e20b375c7a86c707864bc5ad70ee5a947c725b3842e107f90621e5bb21d3701c334b94902c6630f7291b2432cf6a4f3b2be04af278542d9e3afe1e866dd13ab0edf43b767d669e4e8c4972e35642ded616529087c3dbfe6e1a35f66fb74961cc129431036c5b6cb2badc1014f5cfcb172637609ddf1aa949bcf9add9721b143f315a67ba514d82b98b9ef8e123bccada435253dc7d1fb5e4d3193168378c8bdea1274a24963c70a9390f7229b159e3e6a5486f5be42526f8fa332c9c7fff0b69e62881568ca9f3eed24d32b8771f468dd6bebd07b102f64f1c3cf9be92b1f1fb5c6daa80dd6b29957e0935f7cc15b8122db83986a3f304944ad0fdeced8aa5d2f1f1fbd9234e33db89c93531fa1923211878930a56af7f52843c3ac40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381095b7d96b723a6615a0a01c546919200bc38bbcd26734e799fa46423ba8dd979793da6694fc6a283aac71927baa5f88d69223afecb8bbf07f43a7164479e2fe522f6a321778ebfa6052438a064f7529e02c0160ef08ac629f83ae21125d296f722dde35c2895f9181ea0748863c254e0045d9168dbbc545132c4bd4b1cdb05b9ad64fb385d2b36b1437030497a921a40c87585ef6b1c83a253d1694710aa2a6d8c1b22b9b643de4341050d785155d21eb1e07771335e9b10f8bc108aaf5d8f9ac4b26816c90c285c4057cdf4a5b282235b1c9f616a34776940af6daad8789209fa306d98a6928cbea294a2956411c910387b082cab795b25bb27658714b96dfaf5b31bf103cdfa8b25661043ca91894b40ec08868dc4191e4d377ca39ae199af2738bea6ee0f76acb518922dda1c0d50e389a4913c75a05b86a7a90f802104a6121247265ae3c6c6e0a1b83e57f7874be6b13eed69b0e3c20a6c04b8f52520234db294eaaf01abee95d3a0dca766b5e32afb4cc23bc2b501b3c1ef57ea3632ea04ea530c5baa9c0ab6a3ecb6c22bd4887fe51b5202598da5e53ff17fc3a8a72d095bc25e233f7aedc7988e1f696826f2eb19710e3d1077914dc7b5c927292063202c02d594a4221999da892837ce6d917657f4a85ed17001c770fa40c7251ada372e988469c0d2322e4c6a98c6a1838f93ff641947940b57721a8ef9896e4b4964eed884568f4671f501a104ce890d29905a4ee4de482187d225805c966c148b5587350c88cc019c8b55136ab2e5a1ee8d4b1821e38e8b227ff8efd10ddc8b2606ae902743bdbbba13c56e0cc6747adc1895997d9bc9516a7f416868421dd62dde0d2a90b5c9bf9db247243fdba4db3ba84458d38fe8e4bb3642d2e9ae3d2181203350ad296af0f5846d27b2b7be1531a6e20704701034d5489f911c3498c8524da3a4dad29edef7b7265b68a287f84b745f58ec4d9b0e6486c47d5a08b22d8d600ad3aeac24f64af918223f3cb298b70b8eb482441174c72c3ef405f6a55debb202042014de0c8bc972d1bfafe808545618b1d099739ac546fc87f55611ecf4f580d516a5a2c8a06675ab3e08da0392dc2d4eb4179ed74f1f988aabbe944261e6dbc90223899bccdde54356099daa4e6b738e2b8e2dd27b83867ba5c818e54c6dfe70f4563a5d5c987c2846ab3613703311b4505c1e7b1912bd96cc1eaa49157b05828f7d5902de0152545a567dca20258a3fbc001b8b549c10a095a29452d6310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007590707ea05515798829f42a4cbddb4a95c5750879e0a584ab503f778015f83bebf6d63c3b48a4f478ef01091403ddc5a9662e39707dbc8502acf50f3e06ed0199cc647ea155feef503be045bea4035c07c4cceda306b8187185bd06c14220f2b7401229969c1cff8c36d499d5a725fa1ce7b44d71e6c0e4e750766183883d838dae4f00b140e0afccb0e72f935018a6314232dc632c5ad3c26919d1a7925bf0f665ca0223439518143486ce92650dd145fdb2e97e0d5bc9d6806f442fe90c9c1f52992e670db2603ad885fa42b3d8bea4e470b7f76a367aaa506e931890b6e4607f59e87a7a5fbf3991eeaee47cfbbfe3cbe028e67bb645d37a7be5e7cba6d7955cd62d1d8db0d9772ea0185c25bc1ad40a09d3e7e9caba72bdc3a6ef3c40c7ed6208854157914a80b5c66a6dec2317fb5a529421c03cca6fc0a3b3d51556e8dee7c1ebfba924fe2ebce8a46be96e761aa6749c0a9a2b2fc49b42ca47663ea3395df22de20947db14fc1fad03805955d67f8473baefe2c1e22bdcc7bb988db0dde4e83e26a16f10b93bd9cfdba77b9302edba0c9afba7369a023ef763c55484f7425f842111cae27e07a511a725f25d422d933f2ec201bffe3291411ac3cd6e91018c95074c18fc780a73945b148154987854cfa1cf1199bcd03519c8f34774453df90b71fea6734dea7191ee2a5735f7a191f527642d53c844b087e9346b07edd0b78c36f83445825e60a13c424f72530e05f75da8d33957faff004deb549985790956a0e7d9b256298d56bc6206f1e4e1e958fe298641a277a2c8b6b9b7660dbf689ad7e1a19cbd965cbeaa4a0d30741586290576996ae668ecbab4f06f2a1d542e32c5d3f042e7e29a41bf86bae29e7029d997876cfb23b10986a45ca029739b2446a29c55561aee8ffb187961e6e7401d726af6d8a5c816b2ceaa9a1c9b780ddcc4f0e4003542b193ae26ec687f8c51451d2d5387d9c3b9eb95981df2de069fe741cd5c15f6d1b12c5b9b94230aba33bf46dce8ac7e26896edcb4f87272c32d19e72c313738855c02c6f46f1162be0a3ed2e76704b16169689bf532ead7ae7f2b26f4d9b22712662beea1f46748fa4c27d1d825d3fe493b5b3b513617c81d21a0912d329c5a4e3a90ef5a29a4e3137d1ce3eee99c42d034e61593a4076ef124bd6bcf8fc911fc9f6077d82c2980c2adb955939441bc9e81bdf9d6996ce578114c01f9ba096d6ea40f4e0fbb18b3e3d25e7f6d6cb670ad26f604368acb6190667b7b7ed3c1a1da04e42ae0087852834b91aa072ad51c0193e5299481221bc9083118f7b5503559f1e2d9e22a8d57932cd0b59509e7d7f459e20ebf4c1d0df71472340e64992c0485d593714d6b469547616dfeafc95089689931e79944204a6d0a47a565dc325f3be19fd44bb6cd4bf2b1d4a78c883154d70705e121b833a4a7e7e80fcdca03f52c1f831ab0d989ac5dbb5cd83babcb3ee74b69681818dc05e33234775123f552cfc7c7bb0b98c937957a2c4e86e3d775468a7cb8d33756ed7489d04dbe52eaa2737efbc4c4d0f55b5a841e1453763e611bac358fad0b5778c6015d97cc42ca9fecc66cf844dfe55587c200da5250b3a419791f57d3a4f672551be885dfe2aa8637d6c890ee8e1063e782fd7e2cb356bf47b6eb93a155d8d64c9f6cca3971c5a7facc3c052a2aa9fb286750f76933261aff5ce408bda8382af8535145f432f78b3b25a768b5da2a211d1d07ab557cabc7a139f66edbb744aa76e0fbf22092e31c92cafc624ee1dc6732f27e8e7632c6eee2d1f5c85b52d712c884b36c91da383f0de9e06e5ef63d7b7a692e5e91ba1a1d9298e26694faad9ef262f117df8115e2e877197a8069a96210ce65d45e6aa7011654acfafda810cccc20c1985d54483dae12b29d7ecf66376968b52fbd727cbae7c9e3dbfee7391d985228aca9eb8ef98fae32bd24552a6b34baa581dbb03676a3a4546e10efcef269b18e1172f560fa0f0344149543551e079c1745bc0425b5233b7d7dc32f751d321638edb1cee56df0359eb6d9863cf3e341a56060c8ef8486014f956c39b751ae239a493a017b2fa5210d374ba83df5d799b7cd92987febb0b2cdb3ee42a61381304c5eae2add4777011c3279bbcd1edd6f91ff72b3c353ac35da8fa843dc5561d3cdb507730e8bef20cf09b0ddc36d47f4c10d82652dc2937d889f83b1ddc30e52b244250d19eea9cf7a3b5d931e2e25b64a0a81b2c4fe933a17beac2e10fd888d07f994e4f2583d204da126533f5e36b62486a00ccc317c4381a8fe11d36c43e71be108e22a98f53729f05a5e0aa38d512423db4bc1d6bfae9117383acf94ae2a737f6b8070858beaf08e365ca84925f8bebaeef5af77eb73a9d3648aaa6493cebddb95149f0dafacf129fc321e558084a44cca4b429d664d90dd90f2a04818b48d135952746ceca76f99b947a33a3bf7c535b187c1971af4fcb1eac841be7e96f429dd38127b52facc2dd6512d8d019e0080cadbf7078fc67e9af170a2a00f70f407b0a7ff469e2f6ea165f8b43eef1779a115089de9abe6b78c93e4b8e3b018686d16ce8ebc88cbc1d571372a3996c9e5967c035f9da6e200e7ecfd1cf7158563f36a3aac3cd8acf52a4eee29dceb03fa3272a671cfc9b00000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 56&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028f39d597b8c8c67250501a6fa51165c4b013e7129db802e07a1682ec24302b089fb379a140e619445cc2f7c4f232f8b2e1b38f304e04cae15b83b6c6e21cabd11d4d87b214d0202e5df5b86121b6780192f3162ed10d30caae9d58b3e7db04bd66f9529b44fe5117eb519a76ad3b50fae6c8e92bf57e0c585995d91e7aba8f0aae1dede55c54b9521ca2fa20a9220f0c40f005436d50ba2571879ef25c1864ae29cbbc4c5c795cab8895987a43c2cda9b8c37f98c443389f3a2991d9a256cb54c92a34af2a14dab0883b2955b4a3e61b2700481b44c109bb2144e0e34f78d26649189befdd32d998bd34ad07728a86738f770f81e232ed447d8792371bb76b948636cdec5bfec8aed272a4c4d7abfb0a576247d74e7d0a8772db4267db0a3400ca176eb109eca44d3dcb5b853a93e5e243c77bb908698d96e774c6f26b9ebc77227dc51e2569422452360708619be92702d7b41e46d23fa34a3191fe4da2b1d4f0acf78cf64db7c39968af8f8585c75835c655de7baaae9911bcbdb4a9a59bd542f16cf479543ea99461d57761923cb87a972c7eedd253c0e08a14932ca86d5bcf1e29949e73f75ffc3b55d9582a96879b38d34848f3215f4ebb4e1ee5acb5a2586a7208e6482f7e5964d30fa75962280651034734c501097628cd1ee7d1a2d625b384793eaa0b519652f749744f8a9aa106d4c01999dab89822eecb16a122d0879d296a773de8e7a23572f0551cab5c930fd04688c0e44621a8a58f9aa9ad28b6370ed47e77ffb47309d0acc439e45653a2a13c92147eef1de1174c6e40b3408cd32b27d3517527ef4a1eee2ef68f354a572d11713ca85979e8b1b29238b954b8b0c368bd7a55ba9336ad31ed82454facca8ac39f4ea59c467962c01244c24b97971474c7757f69235b4f4e04675bd400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381096401f6482f6e138a905296dad8f087d90ea59ce83e70e22380cfa89b87f9a2f75ed3b021e696446988b47f7a20ca9c667daaa27f86995d1c5b48b3f20ea9a1328967803942c57a304b5290e47800cd71b40cc8959d9229e9c3132128c013ca231c124b6554b0ee47402eca7d66188e611869c788aede544d6e05fa0097cca771b1170b19b87425e0761b162e518edce08c02c43642b50acfee82b7f6ef1531ebcd23fc94f8119d3368704e47cd4bde46de0302016e43a22acc77370df62a813b39cc1ea8808593006c2f67870028aaa2e81929e0c00280e8e0997077f1791c6225091141e0114b0f0e22c2875e6312711952e194026c2423449a99ad1cf5303162d5ba02d0abbacf13c02dd83730e1ea727802e0ab6e64e37e86d20a43df0e30c862336f864d1e556993669ffda3608223e2d1686212a2c133c3bba1090570759d488ff8c91b98270d7f0e43c5ff8616431c7778f8899ea21cdf531a0c056c6dae318415fa38a5780ba2086332fe00820f2fd0b1ce2bc542c33fab45c6e4b38c79403d5a192e663e31b8a735db979e10316f222443cd950627fb840f56bb24c75076d2eeaf72cb8887c1e1525901875dc4fe8920b873fb1558a1ea56c03299128a8ec031d52454774daf29eb1b4c94dc31d5056f7c343603eb158123760271508c96cb509956779d2a801fb2084768e73412b09d4028a58f423c3d758a13369ef6223462927f5495d84a4cab2399f8280384525012ccc76b18132c628230d70eadd6b8f423b79885248dee06f0fa05cf5c49fc4ac2cf253d0900d495ecc1a00efb2452547082f503994388672471ecb9572afaab48f24299d91d847a7b115ed9a35f9e04e0d19dc16aed9c90bc5622aa3ee762dd5ece293a923330dd0e8e04709091597b39949476b9153c71d89a2be8547a3416089aff4bde4059557566c0be62bc0e2b9903a0523d63b67eaab8803c685a074d5a091d6b24e3a8fa8ee877b348df5d53a91b98a7d9d0b14067c94b4cf51e25e9263fd9cd380949a987420a917d96608cc2b61cfda356db9adc719c84c27adc0173d08a3b8f8b83bae6b5168bacd3662026422391c66f4d18e8d3d72614bea6b63c56b37d085812b29f7f23404b07df425939ecaeab9e48f55f6238941e5a159372bf478ad0e06348edf1b4182715aaec93691426969082fb4b23070cf266f8f2ef90613e4a00b508a223e85b5c001fd45428f240a4a29937b4dca7e6e07d7e90def6d659bc6d4834d44c5bfc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077af3ea695264936d537d86e545e132131442c2973d19b37f8c911e3ecef4a13a8b1edf5e5968a6198d26205ffe6b76cb14e353b5e2c9de1bd44ab9bd55862ba1a479833335725ef52601810c778da4a32c497ccfa43f91c72a1499e8d295ae7cdb43f1ca05f0d4a31b30d9a69cab8288640f3f9e081e2c98cc8351c7eb9954d428da4bb374b346a83eff5aa3f455f2bb3fc922f901bbe5695e3ab9892a93beef90fc150b3bb47f6965c229f7dcc3100a4101840417a0e2547f9d42ab27216254a2898368bfc60e7d407271c213233b6913c8e48df10967757bfaf5b5e2a284b8f67c70537c97583786b5185b45e2e36bd8b5443e98601f772829176c4d66f44a81aae7c13f539490640bfc40b83e1c75305b06be60e18a0ab568859435b715e15ba1ee4de73e04e1b09dd15350ae423c131706f057255e9fa8fa3f9e3ade7435a6451f7a2aad0c0fe0f444c4a247dcbaa49e7c926dd52a33d3737b4439c1d40f861720e37bd25366eb5f34bf4b552160f3eb80ca8fb19304e1e4143090f8e965daeff17551a3931905b5cd991c6bc5af5be808073893a47fbfeec0940ef5e7d2f2ee199847e1a4bea447bec40f86f6fdaebece6ff0f66e04193355c9576dd4aab2d796cfee5d432b1d32e13b8903a06ffd3aecb00c169a3af8389848cec724f647c6ba8dc3134ca18586db3e4138601a16df8873a490f23c4d27fd9c3d4fabf2bdcba4af3f0793e7b591198100ec97602d9ba572409ea49d7c8edc646335fd4494577720ea7cdf3b4266fc201de4bc204c0d35cfb55010bfac68ca0df3ac936c9fd2a9c532b8e3461d25362efa37da159b64670060cab833eca799fcf1342c7ee1b80bde05abad08b9ee8908d50cd0d433dda0b120d1980f690acad9c072502ab537ef71b691917a76d3098c27fdc6fad1f1b29e307e17c87d9fa6a06cf8cef6568d9e4e005feefcb5f41a46d91e31b41268367d636c4478921e690d5d57e99da3448773d51b673109cfd3a58cc50c127f34f4963fced6c216e60ea0952317fbfe88807bff4223624f6126104cb46c8d39ee228bb4fc0002287e346e5ace43e2caec07a22203fe3c4aa9008a94f7075f6e449fb89905bb955fa0023608c494f7b73d2aa4e2b0a8a7e3caa889b6b6a6640f7222ef969d46ff6794bd97c5363921461bacda17f2781e14419436e37610e52e3b7b7bf9c1a4b1d80876030f9a8981daa4f06a432dba739db988bed5de7f38378ec1f7d8a46b305896ca0caa5d8ad74002863c6ff91ef25ae96450936509efa93f94718e895a82b4616a965af004038e0897a6563dbc91eb5a6172adba052250d06d210bcf5a250246fc3482e57fcd9901104c5ad58eeffac2860a4da9d2c308552efbda2d4275f3f3651e9935a0e42869b9263fc7ea71079e604a4ec6dc61cef6ac6cc06194def432c1f7cd9edfb0c4b448dae3c2a685bc818b2a90e17a4c1caaa5fc2632f720e764e2b8da314224498119a0d94cf5dce24176421c2736575672b361119ec7c766265768cd9ff1957a17779c11244c1cc82d72d4e3c87107885f71c56da2bc41008b0bc1375c12b3b2a80071ec03e377a93bfb227bd560edd5e5d88f46f7ff9831f05bf262f01f62278d3dc13f4f0ceca0509091c25d20666d8d3527975ca3495f6843b46b5d5b6f5c650e981defb3943963e14f00a0f78ce785a21634c46b531b4f2ac5ad0f03d92372c334ce963e514a1891716eb5d5bb1b67834994eda492719032e2a4f961ddd6d2002d8f52798c45a9da8145bfd191e97d1fba1b395858b0fc7d5f5a54e69fb3780635f70a763e44075075580778676e6b9705b40f40210e597b5aa1aa77bcc3be5005159a4b68cbdc6ad8674495e0df65a6decabafb993cc49c082d358db1e5b3a8af2fcb0049a15bf521986ad84148135cdb185fddca6802c2ade9ea2e82047725d73f51e072ccd799d696d7530f61b16e9b4727c58cb0f552b188f9b451be543bd809b63d66bcdbaeb7aa917be6aef05df559b3aeaf65d5ea12e852d1370efd6197f970f52292f27923a10d01aeb652a9a44573c137257b49d130f1da48e532b3e33d4854b995534380b4549511b39a99145af5abe0ccd3a9dbaf673efc115cb75a9a5a806679907bb525a2bd4507977329eb4c985b3575de6533fc5d62358c21af3dbdd20deefd7c417c77d37dc2a098a8fa48f7944b7ec6f929387ba11e3516c9ea681238650416ffb97ea343d5f227badfdd509b94c1451c54f85e4539a8f70dbb5efbb10b2d82a16fd0c997c603b8983ceb840a7c3b61918d8a97766bb8442c3b9ef2d324e28dc19748417d32f642874a8927688c74bf4f6f6724015c4dd50eb83b85f613fa20938f5c895f88830a40c9799c212b2dfb453ba0bc534f75cedaf7a016f6744cb4f5269fbf0284eb90cf1023918078024c3b125cd9c7501224050b4d20b585472b42a0f494513ed131bcd8f75e223317f56b37ca48780750de0bc81c74a3388c94d93a65719122e9d533274811b76965265d7b2f91ebe3c5924ed2d4dd5e327a6e7546aa2605e4c78d0208db7a7f678caadfb32e6bcf8c77fc7810f7d1d5d50e26d1a0da03b8afcf99904b2b3198670462451925381f0bc404c51f2f18fa7e2c1e8b0c6cf97a9a65e575373996c3e9da15a18d15c93548377677dd713c9828dc4e4ee823a241377c65a2948bd29447bfbe000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 57&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028f39190b213f635d834b16b526f9931c594b1a1c823622469ad90132c901ecfce0f332e9ca7db8ce32ddb825560d7b3d0319654274cfe85f998ea383eeeb64d53f72b9a57228fd8d7c8682c24a50c8d1de57ae26753d4b1af739268e192ae5fdb6e47d65e88d36ded52154cdb333f44065110def96357957d4b5752d5b58048734c636de890a5461a0141d3be432adc7dd30d8cb923db72cc930e444a1b4576ffbc318e50b6b8562110776f5a34dcc8745f87fe1f835b623ca95633894d5772b7aa37b457febb4c3a12b0727d9c36ecf47d3db49fdd3ddfe55c54ecd31e1a1a7a6b233e3336131298b43864a92cd6295d5f5c3b289f5e5aa3e4d9e1652b7b20559b6939842952e96bcbc05fb444103d0d9ed49449939b47abf3c8cfae782f63c157435f3a1d42954e6a7191d62d0e2cb96c822ce3481859b39f206a6a91538694661248bb1d294094d892e8b4ab78bb34e8d4fd9b7e85e6a52dff4e95a26f3ece616511c44fa713e4164d4e22fb72373a9cd8663584bd6dbce1d49f4abce24dd2f62a473662a8f34ec432148e65d97c8e8134e0bf64430c460eef676c8d94d867ae8e9660f1e5f546da7fa81c2538ba6fdf0957ea1c98735d1565489914e50db0dfe3f255dbeede674671908539a659360b6c9e79b25f1096128594c28b8fcf683ca9beef738987a0e6e5ae46202519324c305f316ff2b810d9ef622ac0a824451ad2f6320663298a3ef05c32f1829a3e9a7b970cf67719623698d1fd9915b5a0d2e8d0432c8f469afd3cacd32c3119d51d7d4d627a9475b2e76ba6796eb5ae2f01bb539f8e248f0645d9845d1ad7dbce5bdccb3f487c008d23381fd489190b66a75085ede27586c714c39290e949ad99342ff6b4ff1abf7a26c3e460ccbe96a448f1d60a3c6bbec4402c74f35f9d99c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109a894b5435417d96a04c205180b923b31b0a16107e55f3ea911fdac24a55e3f5772ac946501dbb38f691a8acde1a52cc66a9fe129f23e0c674a5514f7ee0f66a040f9fad65ef98b30b511131d5759366cd85e2ea4a75c70a2a326020ba90809ca4a552ca60c0a14a2fcb4fc8d1924922e61fa3c2b395d0b483ca544df18865d147a0066d6984a4d0efacf97b954b1d0d3fb6892b1bda0a2b152db4d56e1e86d604878e1282b29838f7948ba49fdc38873e55a92000743b758dde182c021196ef131788f897790a9686182b44f38a1ba01490da4b5a015f38401b94c390be14162a194d913845bb6b1cd30a16cdc4d7a3d1425362eea97715b8049a0ed54992b78aae2fc6b1e70f7926ac42424bd99e527b42a787b10734986b0cd01e6384ba3ba19c6c1f443e9773e32307bc658303ee8288792e45bd5052ac2c4f80fa6b0d774ab2e354ef9803289fb8fc66098a19ec89c045b00edc2e96f80ad235704e00551ef04339d7810760136fbea8d62328ae4316bbfb0bdfa974461934e0e5e699ad67206905d94255f6263b8094b34d05193fde092448ce350d9808221cd656e454fd13a450c86f0ba76585773a515f9e118cc0d368d18f8a992b934ed026330022a808aa2946d4f719b25bc11cf61a2828968e14d9a6d1c259875161ba3af9aecd232df5f7946d9f7e46ec837942b5482e08c7ac82d597b9ac211e577412710b6913cede923efb9b132228bbda4bb9ee6b38073c2d065c013472d1a74a52450d757ac894ef26ba235e2f143b0e1617e28e08e2eb1e3ba2147454a375b7c5645167a835012d8660f349c29d4d2878872ada4f9efbd95ca92047399d2867819e3f04a541a719b150049dfbc014a122187a991de82d87c6d7b743221979cdd1b4eb086e2bbea5a41b033e5478e7f4750498167ef782e41f6abed8fb40ccdab43cb62834366235a1a27695d75085924e6777d02eeb8c9c3c31b14bd451d2de10c500d012bab16063934b350216e526aa6fb280043a29dab219ac0b39242b6f548812a228cb0b6e9d415878e6829a86df00696a801cbc1034d200e7020c5fea6887ff21f65d627de4a3444ed3a35229fca6569e637755e98d51a34a9a80636b81a510b38cc4724eb1dabec6cf066908005bddf38ce22dc12f82c37bd92daa1b43bd26b12da890858e827617e88a94f1938a8312a7c8042ecca6c994279d6c4e18f0dd104f8ca67b65ea92f1083623543ad5359111d7615424adbc640e247aa18594e92f200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000079b437e0f77bd0e14d704be86135119f39a0a65650c762852e2694ad9bf2ea45c7ee59df915f5aac128309847e944127294566ffb193d0361dd7111d32b06dba60a12e053f424ddd70674e902e409bc6f5891cb9a76108322cdec1491d3d89a74cedd855bb0791dd6da371a75ae979593b5159fbe9ddacf88506e6a184547e2a7395a46fbaaaf286eb7780b789fed86f257e5036a3555e777b909243695ce89957df492c80050457afd84aad9f8918099ab00fd7ad3528a3d0afe5b52300053575b839572d4d7ce43c255bbf5f16948d40bcc2e63714487afd3638601adf47a324482ecc99fb88574538809227f8c0a5fa7f20a0b2fefda38e6a665550e44b8d5630290a4815621a5dd74a2108ca946241c48661eb087240788808bf676b145442b2de4c35e1a6b8cb1e97e54cb729202d8827a0d4994c6d7f3f406ed273b00b6590006af069d69173b5ea8237b87705f362288ac3a50bbe7e70eb15df6ed820d66290f57a87e51b2c5777c9c95c2a76ecf2e296a7c295bfe029bbe681b32a6d9f16d11c7ca2750e2f8877af5ddb616d8a820de998b0b2af5b0c2c5641f498c99971932327ec2c73c0ef4058d9f33683f60553ad2962370afc6725743c86e591d7d7c20944479daca5e92d66a33ca0c862dc60dfeb5ec3c6e7de356f6e43f06b1431358285398f8885176d60cba218217dc7afe4ad876d0890648052a56812bc3f8a9e6c49f9d70b0a032924b891a9410bbe2f214c842bbf0511ef9017744a0dbdbd500a4189b471930e25216d2588cf8ba39aae7623966cc62d6c4ecc8b00b0613d912e60adf613c8f55b778efb93a513a776c64e8dc943e6272c0eab4004b4b05ce9bce9ce2f2b86fd8429e9a72cb16ec3ded285339edfcd122150f4e7310f669b1dd4cd7e76d282d10314e8abf61d53bf343f3ebf9968e1be8f3785581f675bfc28c893729cf67345d0f7c11d6e7d6da0bff255bf706c986704a3b9c6fa0602c6dc108a59cca70f624b08e4f5393e597459bea4aaaa463a3b08de147e10de6b75a0d87bb79ba9a71e7f5999c8972ba992228b60912aa2d7a32703ba8bc02f774430a2b590911d48d3866396f1d71f19ca90ebd5277743a984e2156cb57de88ebe91bcc09ccb5c687cbcd4e48e4ee110f4075a21f9a051700b0c2698fcd6a5a73372ca366a230a9abd153e4dcab7a33a8226f8458c5892098bc0a95619880156548f300c40bdef81e8c1d8bd03031c690b7c3c000ce99675adb4b94752ea22bc9e0278d0a53a2a19363a9388bb8d6c24a45b5dedd8f7482e9c29603ff182f25856fbeee2b41b88b352f99db5f33d8eab1a1a1fede60ea6cfb7478db7540d3a286e88117503c4d0a2c13d32afe3f1a31d1af9ee60eab8fe06248cfffc7bb438b77d94b5644805cc276f19268dd1ffefbab3c796923288638da1c15e014723a84f8c2dd9f55f7adc2adc13fa7cdc29baf48ca438c882da5f7caa792b7cd984bb11ec4b681b332edfd4ab4c132b08bfb688f81baa3fec5a079e2182c282a3ebe2ad5e4c59090bbb989e6a07d85d604f5ffde0587add29a5175ce65d29fb9fde3e8b49eda1d88ee8dd64fa1498d33ebaf4a847ee9fedd3376af46c1552a150014c11ddfc5047929e2415d3f9d81186a685a1caf2f004de777760f0567e880866320a7b42e61cc994719ddc81e28525e50195ffe4e0467d9a9182b75ef57dfee926d7744485a55e07d1bcd1c9b9b12a60460bff016e9834848665f132e2ff87805e00154c7d9853dbca43d005bb197eeda3d2d9249a621efc4177415bb103893c82eeb0aeea056b40e98b5fe65527432ff33ce3e09fe1288a6e2641011721279253800abc4b73f65b15b434bd34a573e77a94729a78c92f0e791570a416a0876db39a8fda8696fb12e7fa3bb11e7838054e4195164b9676dd03327810ccff9586217aa3d50e7d3ebdb1ae1bf6889df316047cbb278ce8c9741798452a38e48a7138e1fba286b497fdb8b1e7bf6145c5f29ecf6d5430f8e550314db3cf48f27897f312c6d9d6357a880b721e5148da7f789238ce411f952695f4a878756bde311bb4e62f10c2f9939b8530ef70d3fb431655aeca2ad36bb5df0582a07f53f1df8e0325e635d5a5e795c130106502a081f2fc52a9d97c5daaf174f13d2de1ea0f8860f08f4fd5b571e1ab1e84437f3c82bf19b96e46513c316bdcf994bc26fb8461f90594e08e6d4a032c1da38481a1ad7bfb7d5270255bff23ce035535cf478216e6d2e62e147ad93357d62636b1ae42c4e8433bb94ca91d0f8ec265f2793514543aa86b786d9760be5c77aad5a8449a7dbe92391eaafc305c1267a68e6acf0f044fc144d82c917992748b9232dec4e33ec97534f2bf60b56edbff675f0343c9c78e8a8d0529a78e2eed9f998b360360352009f01905c1a4815a36b111cad8e5b34688b99216171d4f57283cd669dc05995bb8d94ecbd3e7b662c4a603bd85251f2ba35fb6ca492c2b3e996fe66a1eb904ccd61b0900e7dedcf136f50e4c3ad5fc312a2de4b3e51f355d01763692c0722c700a544e681a316a1d261fad727e557398e500f15df33883abe9d1ba645936891f5a91ff6c8a7b9b6fe5062718542df4fc4ba50d7f513945482381adc42d5a9d444ca211232615306d7241fc49f08912bacbafbb056c018ad4d6021d99fd720ed6548a5a29daefdce868d71a1ba72d9f998a3f89fcfe526493582c4c8af5c1be065ea29f6155428dbc955b745df0000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 58&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028f396e28a7922c055aabbc3bf90dc9ddb33b8faf144a2574d28ee73a65b2cd8b030769e76f9e74a1f3ae6349772b4c9bf97ca76da21c6866bbd95069dc7a7a9b30a8ea346ca1934bb29a2d330dac83dca43fe42d88ab526534ac9c019b30fdc8da63056508746d1971866d1046d335b5cab15ce8742bc509204e10bd6c04d3af4feaa51c287ddda8c7a0cd7c9f3f1fd573f7890c35c88a6196a159da6efbf944ed03b3f0c943aea9cf36536ced41db761d146a3beebdeda5399c3e89c8243a3d01cf20abcecca0caf33b7a146ba69145bcbbf4da4afc76a894e34278e8e408ac4eec5ada2c2cf2c69d19a9a3fcb02cd9b762b5d092306002ad43cc335dfe5b0d0d755a56936f44e1234f54ea074cae9f1a8b3b65256a2b570d81d80de12830eccfccf642a3bcd99b0a923198df7cf223b7d3253c2f81b3ea77fd58ad7c41839146727ce27500b35eb029890e9b6e4b1da18f29aaf35822a28ca55f6197378505431a4cd3a7473187827ffd5b7df4d4f2636c44ba4940e17528872b93f5d4d19f7f2defdd1685a0fc4a4b5869f0af5ea046df065990622a518e1dc2bb20f561906b84915953341f6cf536dd1d96fc2d8e846245c3b9f491b396e68769e099f8f78cc2776f96439158045ca6d71bda3b1cfda51806465504d8f7daf832b9a23c697ca3e8cbbe13e43d0f22b983aeaf396776a12b3444ae818737d039128434c73699417bd835cbc6bb2c3328c6fad7434893e8823c657ed27c912c73f87677a3fb7a275c4e7750e1137634a1254ffc413edf9944abf53165eb0e6470cfaf6cbb7bd5dcb21afa0a93fb9d6decdc64be1b9d87adc46b2f958a3a3ca53d8976a8e4d9904eb239ff2e3713eac872e0ee322246e4f4d75904665e26726fa7b267a6ecbc4dafdd24398c54753eaa4ea6f9073c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003810966d4f49b45697aa47cb2fa6005127acd5f0339522243e10ca96a1e0c1786cd6ab36ebab9d535e2be9290999160c95fe9e99681d751e71cff4e8adab0ab023609fd20c2a4084579508fa7f380c980f95c077e075821fef171a59bc305853a27465e166ee943cb0e2f5f341e7be9cb2c9881818de0762c460401de85d24758103024da1bea9318b4d58b5c6fc6082e13820ee86489914d9bbb038d57fc45c3a803e69d5ccedb64cd35460da556e1104b2998f79a0180bfa87010a4c74e39453801968f29e022740d7943af5bb1c63ddabfc97ab2b655f70906ca2681fa909a4f5f682d16f48512473e4cd3832566e9037540b15fc6e6b1e9c605dd611e067487600aeda22a1a05c736ef5c1d75701b5a2ab343dc65224a18a01a10771a9a0db7b432830acd442015e8cb180becfd6dc0d7e29d04028692bc19fac1f15c16f18161c35f756a81f780565579a1b8d06a8de1be5a4431c0e5f36995008701aa996b8815d887e73f89ca4eb4d2e3275d64358b19520158d171a3969dcd44918da6c5c57b30baf0725095cbbedc1a25efa58712b6800a92821f11563ec7a0e836710e7b65889a4fb55c52fb23992f1dcc756bb61e078691f7e6c3a011aa20133a03208b6f254b5967db704200ac30d7a5f880b2f15b2fecee94c662e8c11e68b2bce2327c4d859bd24718fd41214865b72056812a09964c539e89f6b2d0e0e303285a07d8bb616ddb5d9a2894f6b2ac7f687da7e7e06dd288c5d8c5d188cf4f700cb8b288ee4bf07abb34caf05c268d17e9c2429099e824766054b4d44ae4db23202f64ece96218565ce0a2c00359cea8a50fc023673b3bb486d756849807c948e81851eb77b0f481a10382b759b4167c0a3d69c40c39cccc7d7c205017e64d7c366efc33be587d570e55b99382535c46dbf625a92aa9e0b8c73ad97e7b5153207122bfa460d058c580cea2516a9aeb47a703b9a470ba8dff7baaefd331234072541b48f627064048ce8b97cca42d0981040baf0a8ef09e45d9c1343a9e1044859e5b01fdfc7269a40697feb8401580a59bc51715841e9c5f345d29e28348bb5550e881c7a026b95f220252d3921d10c690ec8c515445117fda9122b0cc238dcf2b80626ad3ea290fa591e7d078a74e69c575c58e57d29ed0600012438d49f20402192d53a106fff0026e2f1f44ca884e15ff5898defab6114d5a9a894573ef6f0304e8815a547a524eb1a6b257102a2c45290c625b5b9dcf80d58f241a31b40a5058ca0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007bce4e3edcd70c4bbed033f402ceedc2c265dca10b2de0db00d454c3ae1a0d00c97e1dc8c6804b1777ed21ddf5145b9f9348a931c128a8fb03827f653c37cd95859868dde356ace682f627fb69fcd97757bbe8bd5a260a293d2acf0bfa2c0a3548fe25a2ba1a21f95123d592b40c20a927fdb615e69878e8d7c98d261dc01958a088599d3f9bb5e14002192fc7de417b1074b3f7b52cd2a699091fd9dc3c5929e51cc0259d2255caf0e444ec11257b759978bd4a7c8e2ce8473325b7498681102de6ffe9764334d862e379d9f2ebf9b312fa75d7a50e08b94bd43eef78722d423928fb8e26fda85a345eeed0326a5d694e4729154a9997b269407b7d03818025eeb2ba96580626dfdb3bfbfce100c508170d8150e4980d5d386761f4e8311339b47852acc2a0a01dad90d3978de6536547d4f203ceffaa652e4f2f28639bc3ff83c485c28edc0bbe21d17b8ecaf3794d64c36ffe7f07e8a906cab8e7fc9067ca4bf9b074c7fb01ef99a05d7c0f35d889a63afe5ff18023bf77f8a3da0c3cecea0e538a6dab5c54f3a0d83151595ad3ec4c45132ec2f22f652ea5dd930e692a7c0d7c23de84314caa7c017ad50d430fef42de557073ddba6caa4a787c92e6e28368943cad0974edaeb7addf991cce20bf51c5a898cf0a2104abb810bd4937d23e5d43490a3194b8a109b745e0a365efa59199b43835682e996794f16c5cb874c88d9697b189ac54a1ba1f459623c1563cba7689ebb32dc4fa0bf30e064d119d40c36301a653a4f959c97873003cff7e8e030a137bafe0a60ad08e4f692dc107e68ab40edd0c384875b8525aa0a5ec3aceafe557ec76db5283672f9751afe1166d53542d216186a3def4dfa94e57bffbebd6f4afec3c0f3f40f651a1251a9ab39c262d42313e9f22879645589ea54fe894ac005115a43dd806b2c8be6222dd9f02189d4221a9dde99ecb8c3ef4171776268c12adc37e4ca92eef09d2d1803db1fe917521662ba7ec0c07292c7e2130eca4eeffe53ee0ceaaaff6f4ccfd42186611afee79bc651b1adbad08458592d69fbeec708c7537925658babbe7e9867915c6a728eaf41b0af2effe55207c01652891c373f7a14409d05fe9e26c2e72d688047de9a0954516b85ed6a3230b6b0ea9c5f086720c26efbf8b7f5c5d14651d54c4ea181a707c562239cfc08b2e09a2941d04d587b90134d8f670f734578534138cd9cb7ec04437a768fe65fc5b3fbe818db423a2208e485669082b422ab1257c2529cbf7ba4cb30fa27b7f702418c2ef9c3bf7cde53661df716449c6337c54542eadc5209a0e030ad6577deeacc6be1813db24bec035cee6aee93749d524222535a0277600f8e4f4beb473093c5a00b6666cb319dff131ae4f004eeb1bf71e5d274e3dfbfa246dada9d6f548907091045fccf79b363e695ad54c2f791861ce04874ee8c3375612de820cede04e4472bc3dc19abbb91c42a1c3d7b467837570e7d20a2ca6405deccff1aec03e0558076e988619cb0cda9cc87a12367bd486b676a4f71d40b88ab4e7fa750350dadd1a8f12b70864792d3cc1804be8b7cb9dda532182c32582015c1788b43054b7010229f46bd39000440e7f5d22e4d52eed85b204b344680426aef51f0ce0551feb9672dbf391a9ad363ed090837cac1e721878e65af9ba92a0ee7c7979925fba9f4e452eb4fe3af03b9eff0526ff0a331ac0b8cd27a0c49e5019b7025c3c9870c900a7fb31ff834e04b87db77c4d6dae4c3fee741e923704ee5f294d8f881833e9137158d1ee0fbfcb4637acb814a2a5346607bbcd6bc916235f7875334f2b75a7ea7b8b8ddcdf46c0b8007c9b3a014ec6e634d4173cafb1dd09cb9ed4a123151f4f2631d4bee1520c10c15afeb17198009c2b254c1ff0becafbf69be8c7dbbfc7e8f3f1ef05ff6a7945ff79ed6c317609b9238670dea26d56d481f87ca171ccfd726cc0728c965d9bc38d376d707e6979908b19fdf7e74ecd2d0671ec338fd54ad6cc5f789e96018521882588f888d7d715104d65954dba8907c0b7ce3f2acb802ed49ddf1416c29e8d685c5ad879464819e1d53fdac741f71e31ac0c17b6c8932a4a00e7164cf8bbfec36ebbd30392145b292d355fb304a88a638f991f6f89a398b09f1de4f0b29866029bee75a12d724a52736f2b9f49937f0e51b0f2e1bd2c1bc9325bbd1061e0f7685aca02da735d8fc39646e0b2453bb9690ed1c4853a757ea9dc2f4eb4b5adbcfcbfb0cd2587f61a24b77ca0d6cfcff47a98c7098b986d4fbd0e46ef0d1f9df842f4473c43912ab49f4117c8214a42f3083936c7e8a38b294ba081296a393dcaaddcd0d340ac62511e47da6591836553eedb466da6285359ee831a952e6c7ae3b943636124e43224d527b7d394511cf31c50ec1d3e7a20e49850905d504f1aae477830e3bda50430ebd47fdbb0bf537d8d479cb799b0429c3f6591328299a09f45cf9c6d30d5c1c9203b9521d807875d7fb2c2cfaa688414497122161b1b4f159b66c0834e111da4f82d5252367fd2dbfdc079333fc51ab0d34ecebbe786f984852a596be620ec6cf84ed596425b90316a13b39e5ebfa19b319bf0fd1d6c812f29970fb1ffe948bc0d2e057b1dea15445d71b5f728c72dd0c69e277c58f031f90932994ac5a177926dcc1c570ac1b4b099ed66abf7dde5a5d77d08ef1ad7c6ffe018f56efb07c737f33038846247eeee147e4a5995bdc3352b73f15fce5140410aae3f0af1764e5ad996d01608c5e6c6c96a20274ea7781b41fc532b01b52134fee28f501efd9cf00000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 59&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028e39fda37915556784b6dd3def74c1cbb9ca04763fa7b19c83ea40afdd274ffd1f48089005f95503cb14f91ff698ce258d32e38b4012358f7de25cd86b4b0bffe99ecbad4dbc7bf3f465db0677d2f5ad8d55eb4ade3571e873d143a8c099faa60ed7cb9825a6960c917a6bd639f0b34c0a67e9b5e1b88f5609a4ddaef2df2e8113d5a9355d7671297b761d5bee8cbe469c6f14d2cbba9a58d9f5cf1889b91b74b3671e43222ba1733e6ac694b2281a433fb1d55c300d04522249d2e4095ac8b5f7b9374e37004b653b9c9f228ca36c28ec6e0cc2b8f86f5b548aa64c9257e6749206e7550c7678b16b05d7798c4ff97bed1c038556bc5affe994fb0811984fbaf7197acbfce786355ab93ce146fc29678d025362fbd6b396852084ca78d3ad78c27c3b2e6ad98762399b0fdb89a02dce6f38a52012b93a6c6c56a84ca1367c6ead62991eca36d5d81a2376ee6eb1250982419878ec25a6965311bc2ecad685391b267dc6b5f2e9b51a2c9d9df725e3bc9cd7ad92aa14f10899d7bd47e11f83c88a017992390f96056610168042c9f2d9b4b12890af7ed7bed96df8bb151aecb9a008bb0bf473a43c5d5278229b1729224770986350903db18c321c90708e4232670556935eb9e9d187329be9d1c3cf6e8e196d893c6b832bd97cf776e84ebb71e8e0f87565e698f77462a51d3a6e282fb419f386f17553fca128321f2c1b5c8de3cd9b509db4ca3af5a549df4a3ed6837cc4ad326f3c8ff3f3516513ef034a3547aa2adaccaf391b341e2a8b1c776b05da461914d1d97bb29f285c1b6c53395d0686f5e6ecf053141f9bd2651889e31288fd3d46beafc5d29ae8ba19a2d8ce268d7eca6726758c54dd718c30546b1d75898350baa648f84c45d3c4cec118d65eb584b3e3a2de7bc71b50e46f1a392400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003810997885500831afca4b61ce58e26ca0cb664619e48429431b41292250449d8e5ebf1c2c7b224c4a3e35b949951a8a3934a5b8764929541942b52ce6fd33ea3f29f14729804114321c9a9fba8dc4c9704e19525c4515b81ec40104dc7a294ee80a9da6b0df412072faf5c048acf9804883b7bfa9275456cccb06e101813d6ca69006f42c312ec576dd3247045ef04d23b006f03fb2a744aebeb6ff12a0e828676e33d79c4be89ecd71441c88a348c244a44a0e4e34910095912daaa9063d358011d5499a44d66da24422d4129ab8a64866d82a506f27cf06dd64d523afa42fd613e7c6a45683351650dd83193de92b9be1e426493973070425be9c4005b15b5c7ab3c9d9706cac192d059bc2a4285690c6a8ab920d7b8cb4f0a36bc7db52caebe9e80cfa4ebcf13a98ee9f9f004de212a5f84ec4b273e71193081cbb40b8a24819f125d39f62a91b32c9f26f949b3ac22167a4e65c864a1eb2a0ef0c5bd51f8acae5263d2879a9cccff90c0581509c4ce052729049da60e47bd0d4ab374e25a43a835a8822cb7cc8e76072a8cf8c80971171ca576a0e76d992e4722f926ac5cf16f529194c94fe10e012bd9f6652904985f9d62192ac3d99bc25b0a05cf90024b493fd203c21a06336f28c2c4e0aefe28ee5160408fc5359c3c3b540efc439272bb5ee5c3390c0527f7e2970f5e3210ac554682a8ee41e3aba04ce65e69280afd5095acc5800bc6473d4c56509cd6a54a4fa4f083bfb63897a3860eac8718c7c650af490ed880c1c0196851e63f0bd7de2a94b0a0e553d809a994d10b44efbd40e2f46379af099d4a4235c76a70184ee4c0079611b35535b5be9dfc8985b08ad4eadd3f0e0a354fed47297d7ac004dc1b0a8653f5699f913d0881150ea1299d541032f9872e12c857a91a12134ca180334d89b3b2b645d3d7ebe7117e4d143258b40ffa5ca404637532b9ed32bc83bf5fec7a4921cb3f2a6471b18ce85d6dfdc4a49cdebd895e4f6257ccac42954940d71266acb48da755c8777a1185c7d65a83953d43ca3ce0d3bfaa151498c6355b64df59ce401a1e856bd383ce08725ef063d5066a9696cb1a1e8e6126fda1ca1e4f4c91ed57ea08e95c344651e5e81aa13b55dd13b24fa37be643247783d4289d1c97daa6784b82715285548b1811c8b1915182570955a967d77e6ad5d4303717ab1528af6bcacf37beb6e5039c1110b5c6413a452f48a161967456521c25c281dbabab272664ebda4b63a22f3e4ef6980bd10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007dd84c603d1b5549c46964ff2987a1f533b4ced94e67d576a3b0bf1c8bd87a74ac7db640fc9f7ade44ff79b820846eb83367153f5ddddf9dfb7848a13d59436916efabb82dd61291447491d2ca04166fa8680e8e0e0dc98e79344534ca1cbddb531797a61c291606200107002091adfa927a763cf98cbbd631cfe890b0ed257afd34ac0c5280aa7c70bd0c945d78e6fda284cbb7b3ab636bdf17342f2ba28d707147f14d15173d9bc0b6d65fd1663c86971be1fa59da8325e1f3773bacc5b8d4158ef525fde6e96631c51ad142250252a8e5786cd621210df3e24cc0b4b60ac2f013d76db0c73df40efaa05a65383a8892276b3d69dd511937d55d914c3222a2386d1bec0a268e683716af4ab709d2d225b86229095e87fe70d69e6a34bb214529ca3f082c0f2709e77b86b00b4a04bccd343c862333b7c9163857b77e30551710ccc3a803323f5cd4eb5317cd2e6a24bfb77727e1c64d0ac47beea1cb35e5f2ff6024c06f2f391fee76f2e69537673fc0124e48e4e2242e84d8affee6803ce6edf3a954d2c54562b8b76a4edd91e24a8640afe67255605849053b60f558b43ddb9f8a04e987d15f6292962d10ad8f7b47188d12d1c9090c0fe8710dc3937c6939496884bde0bea979839837c61be4df5662c724610c7fcb4631a0a2083417be6a20f4eed094e2145bc72a83a6e147a655c481dcc906e63adc0244d95b6085fc096fbcce81eeb0497f48bb5ef827c0893e331795e3b301dc9f3a91dba9fbc838e044e2ad9859f1dc67e9bcc375442b4eb59714b5ebba87ac9a79c99ce74f8bc75740ddcce46c4b408b91dd7d4ad26b0fb1a4ab874f5504c40e7363838d22aec45c10d3cc2e233124a5cd8344249edf388e37ba43598f2c2cf56d444bcee04a335b154dfa3ca694db481cbaa59514098ce6e0e4138c0a543efafeda4aecc022c824259a06c3d57a70ea15a5dfc822449a27f58f9ef842dcbb636ce293684e1b331cd821594a12634e5594410b6c5e2306dc8bbe62c8b0f49f2f699a59efb14d3cad399f74ed893e1eb43fd770fd61e0c58e5d8cbc9435f4ad0892681a30df4885927130432186ad4be41f6fb7cfe660e23c5e55f60789b3e97c3b622599938b36bd1c0bcf6fdb7e4ee44c92b6a86ca2470bcdb8bab8df6079382ca314bf3a8b3c4286518c356018fd6f6fcdd9be9ad9c228f29135544e723a898f483e9d9ee843e75acb3feac447973d12461fee3d984f3b4f31645faea56852d356c96cd73a6f185e8cd56731e83fea145a2bf0c15adc634dd9e2ffc799b59a0712eb4d2618680c7493f50a9bbf3f7bde1025cd44afdaf4a8c42c9254b1b34aa8559e1cee9bde7b4da0fb3cb2289418110620e505b793b91f422fcf53adda8f7c96d55e26244e075d9a70004642712eac377ce18f88f2c8581694b8f621707dab6d292179b2a95aec5ad6e409d78253dcc05eccdb45683dfffb9c629afcfb0654725d650e4a283fd98e47f37aa9309e2933cc0393625dd81d4a02f9d5082644de02b6472d5d3aae110747e4f756973fdfce8ea5f997e30b11ebd50b45f6889d227d87d9184cbc6ed40e96def8b9236763c9999e21bfc1a74457ffe5e0dc2b16876fe04c2e0f0f47012a767a7ac18d71a7fd65f8647a7e1ae2d4d255492a18aa81d17d390e381b1722bc3c38bccea9d5e73231d0c6e1a96ccb47079e36c994e94af9a318d67b6408bb602a91d8e9ec6499deed0b51a9ae31d9774a1bef4c1de0e7a324545b2af9870cd733c2195c5ecde386d298c33d492937497ea5f0e05c377a4d755dea9d96c61fe82cf6299eb34b857217a2c6733fed64f5dac5f95a0ef2294eca844b96ceb5163363a31c58c88428152663ab0a2b310b1a9e9027ca8cc0db6dff528f9a421fa826a86acb4fd1d79c1ae6123c9e685ba66f5ff109fdff2497b1a50c2e4e7b4662fa11fbaa305a960ca70ff98e5290a8c3a27b4a3cf1705c6df4290fa64f3259fdede7a81cfde4214230dfb9efb20049e905833b5d48923c8ce2f8a104946fb3356154519d950998677c56c8b2c80471a6117b142e26c0345cdf0634e356d80c3be12f4ab89eb41dddcf98188ead2ff420eed3fd9287322f24c62b21f430d5f9b8592ce1cdc946616111c91c667006e47992fe2d5a2aad82f8dd1af3c1b8ba5326220645885cc94e8b2b76cbff7e161e994c0cb9e489b8a5662e9d420913af34433f5bab10ac72c5eeb9249f3c102e1762e862c13cc882d20be16834e54dcc323ea89a133f451b70087a8dcdc5b518eef087a571b570a7966f1c49bfcdc70ac05034d1dcc56edc2c0f57d1aaf16718c67d162ba330aa61a2875f90e2935752bff1ec28a79ead1ac18e70a833946ca6a15d8765e1a62aef46bed232eae89dbec278297b396cf611448c5fd4b36b95cdc54e3394c63b9b0969d6488ff1c700b390e7226f99a945306c6504958cd43cd3d63910a4324bb662a0e5db1622d90ce00e50ce7112193872aab5cee0b8d6fd42f26c2fb87fdf99062169c0be75c85109d4e209dc8a640fed3ec71ef3de8878b3d1729ff118f50f8a33361c6f707f6011454c5d744989ec1beb644fcf99cb2e7c3cd20e6f1656e07c3566c4de68593bcba0ee9f7bd2e272c3d47a3e03985456f18cafbebbc1de74964becabdf3e9bbb9a10b29bf3b458fd50f19d63a6231cb51cde3df46e4bb6318e81e10ad1674a053c8cfe1e72853fd60e6e642642cb825644d6734afb00329839f22ced734fa1421c4334e20f2ecc8bbc2652004203b3b639fbdcf5fda1423f08c3a1100655e4763b8d8356a151d702124d30fdd87b34ec4d34bbb3639464e44a693690e193329000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 60&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028f39268464f3ef41911707137b6a6e6c0935361f3f0278924d7fcf5237a3bf73317bebee688b1965f2be1a451aea8d77994f28597f577543f2abd08e469b12f2ff1b22d66bf6b46ebe1f89bfc62c0b77bc91403678ec26591579948cd108f5f33fed346e6ab7db6a1a0be3a2c138092ed2f9d745fb137ebe7edf074963482489247bb96cbc451d41eb6a4843df4e073a735be04f25d15fea5ba357a92a65ededb92132b22dfef1cb870108635be8afdd876512def40daac22b6afc79bac02f8f6a979d5a9a2736fa22c896ab5bc675a10e793128a8d10d805538cc4c757e61cd62394685b5bcfc5e35511aec1d2b50e7407975f40c9934acc58bf18ad79036f08c3cad5f266a900fa96c39f0c6abbd9e51db431bb7d01ca28083338962bbbca5bf6e44c9e47c1ac98c21cc167a529fcdcb7a649561ed8b4011550dc2854d17c539b51858bb3262f0e8bbf091c18859a9caa5dec4b4e7ef2276231388f211ba5b429063bb5a847912615bcee592b1602ef6f8729cab22e8435855dcffce776fb85574dfe6565c9733fc699d16af31b745539cc4dd6363d35a228743fba2f91d75469939d3ab91754f3da7e0a4bbe8c6becfb8367d8491fa8e22a647ff6ecbb78f3651a69864494385b5d9b3093cc340db29cee7d75f6e5fa9c8b257ea92ebff446d0edfa8b1f6f5d2ab79589c377797796cd9b732f7d9613acd235888e8681ab71e4c78932903ccd1cadfdf222aa240690f45ec8026fb0470d6262f098e4825f57e19956e4e7e86094e5afa77a80204a77f986d3b89e595044b4906888e5f6fbecdc551183324c6cbf253bd55ab61a242bb93743aa97cf26c529fcbf8775eb5b2209bb7f869fcac86258ac9e9597f8b7430fd6a26185d9c50e85936c8a3bc75723f9ec9946e38b666db949bad69156ee90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109171dea4088cc125d52873108c5d838be0c879489fa148d8f2bec9f902a847512ed142213191e7be1164b744d43e07b2bfd6d964707b503935961688517abd956aa8685db2e4b769676787fad3c65f011949056b441d4d3b69b9ec927f1992602a5af10c5ad545f6b96331a01fa3b97ad9918c085ccdbc1766c7fa7892a5e8bcaa018e6aa5269ed3ada41de6a50506ef06481eb4605a429e59cb385fec7840b2cba691630e3208108b2696d98c29f78218a7a0533093d8a4477323856721b882a711fe32092896d389ee5041af89410ffafa90e744772c50585bbd61b01150650924e1a4a6fe5dd8cc637f6ca93f5aad6cf42cfe1ca127e12a0a6414796ae99f2e5a8ac7ab205476313528422d769091e3f237cfc192d1eb2767dffc00f8761357c502a18c08b87266885e3a7ed18a6eb068b0b5f9791ff32a703da047585b164cdd586e8ac5ad96f97036560076ba88343e010593e19ab0aac9aba7f172644b960d6751a9db4e2ae5750987f0110aeaa2ed059b23ea68306a04518a1439a0f13f5905ca6b03dcfe37bf5db80645d47742105848d545da961d750995b3c7d708a449de71067dc6f5932a7ac55504266f5505363117164b4831d2c923215ce11858e25adc6fa87e658de459061565e36f43989f6abce8778a74195690e6ca4c6877ac8aaa56608c36960941399ba76e3e420845c46cb10810c97829b75144af1b5c06c32e22fb2774d0e4980a2f172f2f33526870c3f2559f49dd3b8067a4cd47247ee7541363347a6ed0f4c99fa0c8d4692fe9e9b85245e1d283b979a00cbb76cbc0b504fb221ba9b95b9439e2d9c28d9e8edde4dd8e7d74651a965c5adea8fdefa1ca830fa5b24493e0dfb081f23af6a943b0bfb4b458d21f091fd984c73e4630797e8c7bea18faa83e58d73409a61ffc013999858e6cdd43a601af6ab1edad4b09d4f1a3fafa3452c0855bac0c84f1228dba9e11bbc8a7cb69beb57b30188394361222aaa61d55f8c182ec60db2cf85de5ff8d95082229f2e72cf009b2a4b6131725048aaa357fe186ba5c623a18536956ae75564e0b9b74263d06065a86950aa056b49dc93f40eda54c8770509213298d00b92e45cdc34945b90e6ae7d0a5430267865cf13d93c3af117ed8fbce293f19a0ea999b75b672720437effc7856910654e00caa06b5649023ca5469aa5621e8e62b8da9d6fed23f91fa6273275559b756a6a2bda7d830c401c45e88c041e23af642c8950089db56e827db65f9b9b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007fe92d5feef68737ece61c6e0078d77fbae97b0b9235f40b97099c114b1586e107b5ed1308a8a2d20be41af129da2e0b38eaf02faef733c7a1d1a387bc55ef008530abc22697d0465aa3eb71f41ee72add236cea9a25995f3689c5a451e2f03915d96abea10d356d549d68048977587326523ccd71c05fd57bfb3c7a853f535beddeadfb84118f6548860f6ba536277ddd7ab42123e93381a385fa3e6cc023c1458a9f94822d93248f36c48fddc972b5d6494b26658440ffbc23b57363f3d82cce69fee4747a889e85343288d55d30fc54d2d0744744dba9977720e8edd2c0aca1fc51b0c6a3c68bb9bb8da0385db1ca4e9ce660cf7eb2382e5e95d2ae19def904a8651dfae53a4d0dc4d057ab1a506c3bd7e1d1ea3fc4623e7d7b410dcb312f037b7a5fde5e0e604fc33270faf1ffb6ecb3125ddfa5c49f25bbc98238c8ab1b903537cd67238995e81b814280a4ced61513d69a2178086d505f8dd1df7e11ce66ae33d4c982f94231957031a258e0ec745672a57a5ce76d1170111b8882a9eb5388094ebbd53ee9ea1fce4a275f9d7060c8da79018487b452817280c63b01b05efbf897387592e2bb3bb486fae0ab09f46d9f2e176de96c59992c10a14ec16eac36102b1d15541607075e67c842a888c87b268e9809148a323c423220dc31566b62f45cce1e2bc1b3bf43b87c998f00023890bce517271bec16efaa33f11611fde87f197852bc2e7a2b44f8c72a6f79b22f73be0611b81efe09253931545d2453939c46b6797cc5dc5a8f1aa3bd8456eeeb84ee76dbf2ebf32598750ed10670df422c7d7993acc55f657e6e1b3dfa1bd6c1cd55fae97e69d2f8f5af368f7da0a63b4065eb6d8f02b19a34600252fdffdf4ed8de2ea9cd2e74d63a6cef29bf02f92d346ecb9a61081ee5ac811f33aa5792f6a1af570a8b0846f3e6ef38452346dd637b19eca37bd1a6c42b20a5bede9a5de3c9f169d04d8c6cf5376d3404f0c21dead53da6c169f390eed7b5b54dbe47cce0b2ad1179ea8fc80fddc7281bd4fe31b9a26a00444af0b4d40a1b72be37501308906149dc6fc5cf02b6f60aff82b975fc8f146961ebccb4d126add524a9b33bb16f6a83c6f3727a72efa2bac116e493e07b2ca718a63fcac8e9d52a1b61479b4ee52a5ed30fabcea4d01a792a92676721286814f3b0f4e15e23ce0c5d59a0c3eb8573c0a2f66c25f2eb2fcff787324721004979be5eac505dfd39f5538e2c1b2cc12d20c1c5cd87299766361aeddbfff743693081842378744879e6e6371b3ffa9ddf34966fbf8dee91b7edf6eec3e4e2f410cb5351f847646c22ab594046ded63347d04a008fbf6ee9696c638ece73b39a269db239df36443868ad44d26a5c40fc92dffb008e436e5c18907f5b18b5e6c5900b41a9801db070d2db651187a4da7e2647ed3e9b6e9781627eb576bee8334374468760dd3b32985d42945d953d434bfd80d7f7ba537265ffcf27db0da1abdae89bbe94d98bc9ca197e41c0839728f964fe4ce30b8cc43cbdcdd9ccbe06fe99debc6f4024f3f00d43febcd62a1822a6d507337ee79d4517aa486870602d4f1c5368b0eaa1ff6c011a9a953aae58c75bbd3dc78d263a578c75cdb1ab324d71b9a065a9af3dab854189585c68d499ae8db887745e20ad9738705b9d2f5d429f12d6462e5e2ef9ffba53ce2f4e75449d2a7dbc3c818e61dc546175a6e0c10ae631df6b1eae6d134c08466ebf6eb5f8257aa10ef8c6f27f4295f7ebfd450629f3eb4e0f4be247ad7f5e80703b1247a4fc277311d69e5d62e0b0201a805cc4f1f807de99420d563a703493ad35a56b2b2dc237112f5ec21c70bf139a9ead8f7e921f086e001b4c449e42a0e3afcd5bc757040a2865d0e5adaf98e37e6f8a501ff39cef0bc364eecdffd03069b81f5e1978c397862fd56362835c059fcbe4d8e2a957fadd7d05bb195e21ad67b429621e1d6872de2d8bfdc91544f9e6ae8c164a23255ad0e00bcb21456f8fa6ae018f49605736c81a5ac0945e2d965f1493ed5befce512ae93ad91daf6f5a151d6c9856dfddd1f877945d932261ded67ac8231dc3ccd0b04dc1b02079c897601e363ffb9a3bcbbbdb0b0a375e69ee4a7135c094abdc237faa2e5f82d2556290adcf82adba8402c4fc9d0724f15bb87cd7a75a1a7bf826896d8ef63c7a2a3c371756af638706270652c376100ec42fa55196df332820d377760448d3e7adc42e9f5d8a7074bd0fa97433b0e2c501252de6939ab948552663a17dd7ff05430fa76e29f0519d650b86fbb19fbed097143fc242573e3e6fa4bd4a2ef6d9ce6932a066b4f9ff935ba9bc26fc2e5031c20ae30a52970a2df3504576108d5f26517f8577be61e6aa9d192ed62cf36aa641da0d274b1ed5ee864b549154eb4115658e6c60219cc5b2e22c49ce3ba76a85efb549117e1207f6df081d0761421262e352182239f1e34edbea4bcd8fa0027543824dd58a20324fd4cfe943aae5e361c367b22f587e2f9bee841e11875b026f12b9571512f72985f98f6d0c212df36a60975429173e317f6acf72e621f30654a6deaef9e9e455524bf07ffdf44642a1826f734d69f3eef4d52f26c06376c8f71dfb65a24a4c57d74b5976950af3a57b4248909524bec47d858c69041eed34e0ed3b111bbc117ab112bbf947d646ab3b7172f5fb726dbc53ae37956e29f5b6b1e3c90baf4e4fa544ff63815fdf4ac9a2a80ca0e8722383437b9a02f3ac538feda7a6d6c1635d3624a385d846e79e956dce483b89c346c1287a1a7293168d8a885feb6569ebdf3f47f8bbb50aa43941eb20001959af1b9b358aba13fd9bbc596ea42a9774a120af091d544e79c50686c26b4fea396bf1e4c25b8ee4929d75569a5fac521c77b0000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 61&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000002903934f21077fefcc47670112fa772fb9e8ec38c35963586db92a0c8e837ce2729321e538d22a1e514490263d226ad50c18f078e55b755530cc12ec3171fa47ddc4ce27a1c528510a99dfe1bd893c9db07cf7de341b0bfc6e6344f73a66b1bebbbe6d8c5f7f1385e1dee0d4074b36c2abecea58c8db14071244465b484d137903ceb31825d27d00f3649083fb9d8f10e851c13f78ad8b98c9c0efa6f09779b3374820b06196e33dec20ba48489cd6716cd1e4811c5378d829b73d3b22b6f86ff90f9fe6279face066ab1fd5e3614bc233f6c5a679a329618964da169e35527422691d246dc944a37f5a5cce1cba0fa9fa78997ad4a63b08590c6f5976812a04a32fd3b0c734cca7b69f5b89e1cfb134b5eedfd8b2286accb5a250c71d332592a9e271079b92582f76cc2a72b9e188cc655f4f35db583635692abddd4c06bac26289cde73d49f16f248b6ba1469e9f4621d4f56760f7a8ea0912439f2c231e8e5e616bec18fa651b5acfe28f32d1c5b0fb098b4ee168b78cd5794e8f3724aa255f8db7993324c9ca63b848e3c59accb0ad8eba81b39ea96f4a27d656f749346b92a534581f74a890c11bff32aad3a3db71a460d446c0e4bc68ceb35391645295e11edda8538618c829cd8aa5843530b4195173a7fea46166c3ae29c2eb025a5926e79898369084e1926b24f1c458de3b4db48a6febd1bdfb7c3e0752ed37297ff123525a568b4c6ace8f0ede8d6b19ed7a5b70ae264947db9b5dc376b87d8fefbb65d7253c6f453622394411a9c0ce331f54d92ec1c38b4b0dc16ad45f1e92c137ed5a18ed9d45606227a8b3e8e07adf0ab95fed43f2c88a7b85ea578856dd688d5ca2990e03824b0e84ffc2701c892624da9357578ea323584807613b41208d4127a1cac9635784e135cc520e79da3bec0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381090d084688c21b232d552107be6cce12f609c4dfc3182f4155e480cbff882e6a8bf350eb73a474da862f1e8294b69067ca803288f557b895471186453a11cadd0f4224fbee4cb150a869804617866f75f2217de3e1bba1d90be5c17e637957b1199f0a99c0f134e56d3c09c17e625e0ab924ca9fb278cbe46dc0203bc7df0037504ed3ea0c9f19440d8a9c48fb5b606ed3b0cbf789acab23ee12f6962964181599ba142077f7b6cba20cb0747459d3bb651a86542c13b1858e20587dd5256f0c4445af985fac995f38d99ca89be2cdaaba4b2a1234ee452a1885681cb498bb65013606d139b40921a8fa6955eb02e92c10de989a55a4b9f1f6aaa184f120f476339a288d8029c2e39ee4b7569a9379358d3c2e5a64e75ae32e590413ab392549a7d93985b7dd8e091094c679a628b359cb6928539ba91dc370819c316c4e81a6c38cfcacc24821898c488fa808b5baea865a550b79fedc4457015d4833844b1c4a215375d0f44d6c30e45cee9b3350fddb9711972fde4eaa69c64c3e3e135b3c2574af5a0d4669475b63c29a97dbaa35057e55207ca5309e80f676f1d98118e651e56a407826dd69966e45ca0c192e79b1151e6c882943ab4c6a7f04437b3c9c6532ba3e978da86d0ef16079a883849dd5db26d0a90e20802cf528e90e4b7526b4d31ea27b01763808912303009bc7336d0121109c780da16079ea2ea20592cf67b12a1382a131a36ec68b05d06c88081fb44e662c01ccf4e659c6c1620c8fe78c4dab2f508088ecc9ad8761373382ee14693ebee1752ccf2a1ef471148a989ca8bfc7425e254c809d040d128b878a43772bd32a723c2f1651667869040bfb5a0e76202e74f716c1234695ffb983a285aa85a1826ee3147fd4c5c1880896a7aecb5bea88a29908c17bd52b4787e86d37f40fbc0f7495d9a1c29e6b417671e289ed7a74e28124066c0b65571a101688410055281a2f0d2c8c0cc28318676c4e64a24146e64720b59216246b91b89bf52be50fb3e488b4f8665fbf86c60a76ee1868019c43a6d5a2241641b39aea4f7ae90649ec2e0448e4e6e69ed67a9f74f37ab69cea91969c28cb1d776d6d2b552c049705824e43294248919dac36b5db3e73503b09361c730bd528605c6f3875c26ca36b64853b3179130ea5f421914378939709b89af835d7e05bbe54e50a8048ea638d76a244d32fb67535d37b83eb103573a1652508b7cc759672608b28fa4e96c62976bc8e28496c611706287a0bcc555c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081f7f704cef1c510bc2cae9b70fd248c656226bd5686d366528f0d0befc0a8761ec640cd2da7979de5eebdf6127f29abb8607f8a3d3be05be25aace7fef3063df28e22a522fff0b6ff6a0c61f79b02a408e8e1c775ab80be6841e9f8a9d030ae5518e3ea8a4e31e416e087d47919593598fd58122a9e601a57ef02de183d56921811ae2253628125c24f93c84361c5ec99e7b16962bd96ca190c68f3aa9dd60ce3aa7610589813b4fb77a4688308d9bc72cbe918583e298e03ab95fc500209c14abeb3a43baa92dcb11cb523c4d17eb9c6697b56c8b61eda05bf5789166f839291cfe2997b7dd462eda69b0615f2ad82aac0a32f4b30fe8725849c144a9c07799d6ce9d293c25d8302161757b8c8c8d07032d914ea7dac275919a1dfa0d3348ec07fdc70266975722763ef85ec4af9e14288c9659907526566bb3f2dd5dafc0d422568ca3ae52486d3f2c18b667e5622ba7e52c56bf00f82af2108cb4949a09179544f30758b7fb98c49ea160720991b14e2858d648f0585ad1bb1d08294f029bfe936154e9d328df2e054004fc5c29070df9ee50dcd0981d2bfb3aa7d6f637c4ce457c0c66d27e2670107a2b85d1f026bd970ef3fb7e32c60218d5e43a06d9cd26289a937b4fbad2a831425728f3d0d30c6c602af4b14411e9b3c7cf0b4d630614a9e03ac30ba2b024d496da984d08854f1366012c2400a5c8268c2b126dea5aeba0de7c92be0af08ca22e02604a753702bdcd642bbfa0cc91bd8375657a957306a76b6f139621481b6f15cb57bee128954d30f552661f906d8ab42cf260f30f88993bb40c9679385f5c4639888973361216df3c60c57d9b250f64b7634c94dda3fd122713fd2405a7b71f476c263a781dce271e7d0665e45dcb27f7293de57312396c58c40e268f57ed856f536c8feb4b0060488de3c25949d2b7e64207576641b34920d04b46766aa2978d9352c2769d49f8599f3d0439c928532e0ee428a3773fa4d68e6052335c6d93368e321d750d296799faf87b82c640a6e995d18dda002887f141db8ece2584da2fddf848d38357d585cd619b1625a70a5d333561d6de856ed9908d1e377ef7be03b326594808be58f7fb3939e939b73f11dab3e572dba41d43a046b8d2bb521728222d5a77dc886ac6f328d9a531118156d791d64f5df8ff8be8dca32eabc3cb259b0f72b021ceb4db36a6cd2fd149437b251f81f7588ae921456bef1a79fe83447d80caddbf20895667ca0e493a4731eec901e03f66de284400a5558922ad53d4e0ff7bc6c61640ade0274c63d94e96bf6c642b790823109f53c3c27130a1ee38d448239187f5009373be328af866a9b8dd1bb735e8002296043c6ff641a432709148c707b900ecf46555d77644565d5998c096756f79b6f0e20850b8bf0528e78bf5fb4859bd655227873d289cce47feda8414d09ed7e8d380fc4d580c7f44b01521e829e7b0cb2d2f345c517b65e2d476687ec9a4c160a3ac0b01cbaa588644d799b125910812790f06c1ecb1f1e64d5ccf92ae5e8147c98b0cfad5626bab5115844198e8c2ac1df9a208fcd2d2891f4a29009f5b36d8e31383811a9493cf8e143b5ac8a14d48119cc16d2c6bf6826fc47d4b782ffc76b64401b8249777e32c1298606553dacf386a22809b599924a635796a1aec3cd8568064852e54c95ad887d7afe837f6ff676f69ee6288879f6d96193ad94a0418bbba2eed5355876f2c3497448a5f8f3f83b136703d9a38fbb62784cc233df448a5e88eb5f81a0be97a16fd4caba1d87a4bfb08e002eba548f662d496a1478bb7c26c69ca4c100aa6872a4945d703ca812bdba53ac86010aa1d2c53f29e46ad095936ff50db8805df4b08c9580aeece3a6ddd828e7b5d4dabcaf112a6e35ab3c28a6ddc4d98ad1063c2ed72caa50086e6b72090cc1f2afebec6751f27ef51dd8557e53d928535d82a220f62ba0645e3c2618f3424ea1a339a138c9b8e26b14bc32d1736a4193c0c72cc402c3eab58817335c1424bd6f38cfe16338611118b4100e4038d07dca041c72e485c5290f0dde601565dae9cdf657a4c7839d3ade72986af396e767430125786e219bc5736f16fef66b4014e5961cfb4cfec4cb2a32205a92dbf1399e2710395ba1240d48277c120526cd9e2352f7d04d89cc2754379ce80a2cd1ac765718b8ba61ebb8bc6d0d407022e7ac672065fc8503bf5bc4138520cae233ea997463d7c9e00bbd852f12ec17c6f1db1914446aa21e156d210094b699b4117b31eae6386dc0de1f55ccec09aa1eb38cde4602598d452732c5ef8b07c477e3e2dd470737eaa7357e2e8b74c31a117b519bdcef79b6b044148a10468e38b5a6b7b10d74c6130a60a268ed73dc9a25ed68af354758fa3f57ed3558da654caca7150a8e4449d0ef640184a7a33d00ba765b01c442e88d9b4257b93904ace04375679bfd8271a03073e34c4a1c0437c4009a9590cb98d0b5581dc83407f04a22c9b0246de38e1a13f9b1191493818783950548be562f940240cdecd4a50c94e406b1bae04b50a3a19e7923183e3fd356238c45ae6559193e0e846df0fc6878be6c963aa8c3508dc31f766a4b29c78d749c89985ab8f580dbdf7993a2261cc4bbe489c3bbb38c46739bd2516d3c64a93f10cf559db6a0ea3bafee8b43f696a5288c66509a57c642bbeafb40f4cd0649b4ce25b6fb2ef5529b73556051213bb39cc4f1dc8004b1588c8de836699c66ced567998523ad3ac303d9e13617ce6c1d2fc4c35b22a24504c51f64155f24d91d0e8785b40912b3dcedede71a6933b36bb514fdd1d3d843aaacf2c1e79a5216622c20036c9c999dac3a5a2d43fac3b23119927806f497b4048f561a2276fda0302423147d35579dd4411416f0f59273429ac0464ac49b230e29dc124115d18a045663d228bfdac9f57b0c5b400&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 62&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028e39fb3e2df8e48162d954f40843cbab77a9d440f9ccf5d6f021f843235af3ad784fb17c01604304f167d2ff5b695155bb9f0aba3e35d8663cad7ca7e215fdc9fee4a93fb90e6dec449661ac3c9d6e2a6dbeeda57bad44ccd7f363582a02acfc306d040a199bea9802d9121aa8fa6ed6fea7afef3916d1f55ebb4d13cd76ad481beb37aa7b232f52b7fa2dbcef6d729a6e2d96050441d939ee844bcb5ca2d38fe3ae458d39da1f0b15b689eac9da300a978aad4b1b54a8f8d15d7c6a18d32999a6bd37b14a8ad3e994bab4bc1ec62d88732c916d8299776c778762899d8a51ba59e6930c8222e82318762e99bf27cb28fd1b9a1cb2b0f5e9222d03a1a0f050eeb78674d9448f47f766bfdbe5a8b1b21e073e55095931f3379e74883028d34ce250d59b44c0818e5bebe4dcfd3633a6f37461ec701c1b93ba641c7a2a3bca5adbaecbc71c59fb937892f3a9b7ec3e1868dc244a5bb651986bfd6d2a15a9b921f58758dd665d7fe7424f02ca63b5140d7b6dda60d3ff1f6386b97b3a952b00473189c55341bf655987e0af3e22d0fda8334e82e4a155da85350dafef891fb71f89e9bf440d07a655d57a5afc8788c6a75129de5d507bd6c7b7d087b3e7430747b749984f853d90a89e55472aa6b7b5edd40661419d6dbfb8659e7d6186b50e0b31d089d0376b647aef11d6def3ac9d308ffe5a73c126e83f7561ecade395189ce3c173dda2bd664da865df0984420ee2dba11393e136690e247514256512316af59a165b9ae26d8f24d22e5cf7cb6219296d114202bdc03e9d192e4a22c67ef1500bf4ecc1b06eb369c2420d571db531f04287f640560e09e022180323b48889ab9a7bd231226a642ab3df887c711e8bd28a50b20ace84e00ee257e8926e3d3547a8afeae10c9d44e2bf7f244a9774800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381098850f5eaa1d4b11b710f884094c99d79f361a0c7e75792023b51015766681f46a6c1949cd99fa59d195e4fa262a436e65ca4727f031aa2d521554866d26a019bcd0b956fd2e178361a7712e7b082d1ef43200b87582af7b4a9ad26ba80cb9403d0085f9ee1f17520064b6dc805a7e87767b21956339ef62db90915bf0fe4534eaeead1cf5ea5e988c5a9adf07dc5b7ca1226f2acb834965baaf577c4aac203c03748f6202045217681046c3b01a17c31b5ef413ad7653e31a285e55682365cd0731383c9bd01b2e97e695f89268d823b60076d98adeb1c55439efd31e64ae7814bb97238172a53a0bd1737fc0d0e7fb02c202d8db91f19e543ad61cf2414eb761c63d156b449633022300ee910db7ca3d173703fb472017896a8f0637d0d9d2432437b9ac7a08ada634389cbb8344509f6000f9110a04982d5543f092ed088a5a4a60f9853b2eae3825e4ab886ada68086aa0067bda34f27f6802081cff26f663be1ad69c3669d0482e4e2a206a25ab06fd78763dc6bf72e99671ee2d119f82ca73a9265838bae4960800e617a1d558328cca93cd0590d51d60117a6ca807d44037d8e6529083b17e78c4901ead9a7c0898510ac5a75b3e269910586d896176aac84157b00dc255bca81cbd30ca1081626a61dedffa12ccf0b2d24fd33f663372314c1955026465fa066234a87263213acbc95e2832b4dc1737d153b7047db15453958dc6c0b0205f721ccd11d5e68036ab387748b7ed0830a4dcbab826a25856b99b398de6487432b2cca6ee6f7a5244d29296617467f57d845477605e410560d52436a465e4ac6a57d10c953653ceb93250c9a614d35a80e287d201cc6c185bb65fe2f103745a88b6098509711da50889ae2318c45ae56c9b15d28d05e7dbfcb00c9d585a54a8bfde50965ae466261511a4a7e9a26410271a27009ca06df3d5c88adb50c1d1f7609c90846a8c887cc8202892ba7040a05a45c1dc474005b9187495c7e693e226da6f354c8a9dabda397796598c51a606d78dac5e7545504878ac3fb8a9aec9041e8c73299b86571b2dad6ef43b6c2f49493e718a1b28f475897977dc00c187eae86968af69b45464545e4133719ef9c6b327ab6ec97042e40058274a9ab8f1ed5d9ee6d3b97b20727386241121ecc9705987a3bf04339e0ac5bac4e9de5d3d7f21c541a59c5cea01cae06a29ce80480b517858903cfaee93a4333a9ca3edeeaa97fc6c85a04a81a39475c09bcbef74a02dd3451ac8bb28aca0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008402e086fa0c4582e0c6ccb020f86a6107475985160bed201760d6489cb05b8d21452c81bd5d317f8857703daba24e968f3164c82a4a9751dd88742b72141734dc0b4a77cbe2ae1c287a396a2f5804519456cf1eae273a5c6361f52c35edce5ed7388d61d01ac040676522c9fd7b02a7deafdcb4169867efb69792210a7069287c5dc958d0953c36f84d9a26989dd3b726be8b94b41dcba1b5374123f55a6dbd6360698551c27d16baafbb0ecbe116b44f11425da45d7fe8aba91697d83b6896a06a7888c97a91406b81b3a5bc8b68a984750893114b4011b9c8beba6f5c2d7d9f2c7a27030555633a0f90e30753a04b1958141af7c1b95ba208da36f729673d20da0a83f913bec8049f8cd032d9f9dd94b2086c61643ab2cffddb2b9be0af996d642b7a0a31ce0eec8c61b343aba980fcdace9ced7be4c9048b356d41002eee0433428846ba4220efb7f493ff57b0c706282eee448cf7da9b17b32d0eb0016983175469aa5bba53489ec56ba3a92a70fda2390e3a5d8c038f496e7c3180c6971a39491eac10d828d44b3de2be64569b907005783e62710b9ad8eb8c9af4b04993d40d1ebf165efdec748fe9f6b334da6a30c568bcbad095998a47242ca16803fe1720fcab85233ad76ebde102a5d93ab98460494bc886bb04c05ae89e157967747f8c050b33cca52ed5e59050965523ec5c4eaf94cf2f2ee80c35aeedd14e65d937c92855d03fc76abaad57a21a42420819ebb9aeb65f031f9c4ba0ac2ea27289e941db89669a0620797091aea3ebfc2ac354e94d27894f444ff9e604c8bdf7d6c00df0e7fe9827171010445e737d0a5867636e3488eaacccfcbac1030c0dfab639ab45c5ac5435e2c5b8244e58c3a6bac81eea408020bfec66ef55fddc618083ed737f4dd3bb65474487caddf3aa2720a6931fc69533b6491dfc7e6e5fabf8103d05f870bfefddefa20822a68a710b517065bd2478ce080e5dea09effba3a136c1bc9d7d8088f736c363b30e2af2a6f2395ea8161cb64079340fa642c7763e3bf0623c968a16263cdfdf1b8334e427955e20c1ebce8c8cb136da8d002d8a9e5da3b1f56668c1c59e20dc3be026a43f40910d3a2b601d9d3ea2bf6d2c2781f976ba840fc986c8af0df84b8b0fb291d1310039d6914f8f7cc6b26cc33af94150253e8eb410344a64344a5a0c06e0f3aa23c68617c6f4659df79285782c89bea3091083a069ef8f048371cfa054de45e32c19a44db5d435bc8fef5570b68d80d5bf5dc06da13c36e3aea341ca9fe20047ac30683aa9d862306534ec93e79eff79fe22e3ba15e2ba3f59f7b8b9314dce31095d3015710c2927b54ba6f46d3981975229eed16c9b17813801c7d3cb3604de9b7a4f18c2f91b2b50c1f43e87198afbac718935db9cb96d9fe048d969635cb9f4dca659ab1612a698ce45336b8d9ff5468301bf05d04b3558d66e88de88427fe87e65d36d3c29fa3fb126f1f294e9bb391ee427001c34126c6622905514ce153682754d7fb1c985ae4da600aada1593a0a214332b310620b1b4e95bcbfd6eb8a241cbe848bab37462224994e0d2f3f4b521dca4a9a5ab10bee741c5919907afd2552d4aa300addf67cec2862420c8d1d8dfff60fdbe2d4a8d03c92e23bdb3400f5390ee4b141c5843b1e2c07c9afdbc70e3fc08e2840ebf3b0e5296e1ee44d12e68240fdf063c07bebf01c08586e8153068c1adc744a7b54f53b0fec3c752da9f6f989a1afea4adf1ad6ae926cabe4e0cb2cd864412daee377de559a38047f31e834a6ce56d4041ba709945f07e514f96d783f32b0efcc8b889faf2b6d217246ba7c07b687e028f23d2409bbc12d6ec0d94ad9697bab6395b7070b6feb2e907a119209c9b7d86af953ba7d2ea63982bcd794a5bac69407bb7cec5e027833b17420f146ae08f4b753bef6ca0922f3294cd2a670127f9d2a2ca78a30f62056a425cbb7074c9a55135bd06ce677abdf33b420f66cfdbe9461bfdf385a97439b3431cd29decd9b5e59ec3adaae879a4e8d5e28ca13e73fcdba51c828de271207a5deab373b1b6677a29acb87cbb01f10cd2c090ee66d472e8db61615a5ecb84a7ff0988dd0df9831bf43d732a12ec8cd50a86add12a5a2ea765744b05f73725ab8704eccb08bd74517f21054e58903481e7a724f7ff24c43d6cd23de84cd69c9e464e67003903c3858a6724247eb929716e170e2d2739aae10b88bc3fb8ffa849e385b4113e78c24de1673fc7e7285e6e3744f3843ac7be7ec16bf74215694ce467a2e859dd4facab86250fece28e0a6a31dd529d08566a6389b85c310c28a8dabbcca9cd6a631ef0473abfd6846d8326561cc9cb8181c1593d0f15efb8129af9e838af518477ce361640169d9731fc139881d452773f21a3e79e514ddaa513d7b9f3399c0c57d21eaa00d44a7f031b79cac9fc304e936e75a0cf8d204a6cc3c0fa7d037dd8acc3a33cf5718061fcd57ebd06a607fe0bb0204e687b2a17b1ff47da357b51a753076cb89422098d4f880f831842957e648c54adbfcc0e488a95581e709b5a5a129da7ec5b00ac9b18b80533f2dd1bd0f475a61db18fc0c4ea655f602b207b572234230c831b26cecb7bc3284797c4bed5a977c3bfbeafea3dbfc4257d4c2c5bb8689830ee157f3b5aa1eac09cfce0555880a074aeb86062a8ace19acdc1a25f8d0e454f50f119d12e707d103f3c1a502d4e358d563e53554395b5d386ad49363978afbca2f8b673a693acef70d1db4ceaa8fa580160924d4f18119be46c71e09fdee45efb14a74db1c688e99e24cb6025e73a3e7f0f7ea9c485274d2b6cf9784cbe39e388f9ccf1e2e8dbfa6db43355391a369def645f815424253abd0b6de9c0a0af156d9a4eb7474a2e5937f008134debc9fc7e54812967fcf5bce28fb5cd43f1aa240ba2e9cedd6f350d556db1658868091e6034d7e1ee5c6645d0a345d46c42e23c6821c360f5acd13f589&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 63&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000292399478b7d63dcfe5827b8d651a992f550fcd6324914930c213cbaae64993f85fab338a8a0547427802fbfdde9e65e585e7c7f2cd9169b2d5a65dfe14deb7df7297fa20c828fd256344b55d7414c51a192ddba45566ee032650f7cbdbdfb09262d1d5c54c7608ebf7884bccbb9e505859ae0decc3af5c693254f430e8391f71e407e59442cb664b41b892f99417d9b547ca03a030983e2e9b3a800a32959b99b1a427006a9178ceed24c797566092cb2857c3d50de392b4a96585d8af1a04871cc8609ebb9c91a7f848558542cee96d235df42cbe40a410851a12888d439eb17cf3265b4c89d9ee3afc8739a3b7b8b2fa6cd793a39fbb0a793e8b492f3e7db091d513fcce10552d9b0d36850261106f23136f78e9cc4ac4f4bb6c8105b3f83036fa06a86649c483ed0e803488b10c8d9eeddf9f59ebf5266b75695973483c371cca64b8f4a6459d395c0927b6f115f6c70f693651aa2aaa937299d111e6955886bf3053f15312fdf546c9eb8bad337b4b576de152924ec40e011685cc16e5c5c69c7c20e0f333cc2e186dea073b346ef47f96ad769edfbb3605373fa993a27d767e2071920661aa21918283f2dd68f3e8f3e8db37c3a1f8b4439b3c3e176baacacda2487e30f4415ae80c0df0a675a29829f4649d8ea23d8a754d09866d0ac69646aeec8a56c11554e9bd1438dce566836740a3bbd8b33a6ece137352ba6789c29717f86ee1089d6492a7faf8e8cfc43b2c96491b5afffc46568af5cbf545356ba4a22a7f514e577b08afd164940a618b8b36f68fc22ba9bb64d06b6b67c360ce431ed2b5f3d1d5d350e066499e4aa695aa2b6ec82d9382b35c6b22cc8b446ab66ed6d21c469b14074aa1a33fadfcb26a9ccee91414ba5aab6e85b9f86b9787ee69813e7ceb4d3501817d991bfe9a73919c8400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381092b603bea9708542df92344b19916864adc580951495cc4ede75e2f89058ee2138f9843bbde7a2baa436318918c609620c822c87d6361c5177234e00acf847e6854b5957482bb09f4dcb147d5c640f1a2a54fa6e5a5d85b780f50bf9af5f8d94b55553846d68498e4e2a2acf3a2340d8f9e8652c248a06003da365a871be39085d922a1ef0866fc4c0431ad7b306e1a3adc14c475857b259344754efd0bf9cee6eb27cdd7185f22feb2c1db8242afada2ba72bb7fab3a43d6a673790d02a8517085c806e94b4221d070a32170dadbc7336f8bb3b8da0167642779e59b8684ce323686a8c8955dfdad7617b11180159e86e3919cdc5bb71d73911285759172a1e0998ad638f084c488a90a3955ca30b5eaf87bf2c6ba6d43ac46b257a829cf0eb0556954e38ae4bc6671647d13e47efe62c917a5de1f5a82e4eb66352b01b3754608d17e8a323485ebb4834518abe4ad91a4cc4fe6e88b843e7ef1214085f6babef7983edc23855d55d2dbc5ef381dacaacf8334b6fade578c26b933b946f0f706997c5e1a42ef69123f49f1cad3d1d66399525520ea338e6a03c67f4aacb2dc879446a3d44fc9b59113923f139d9b2be5e8d6717a6c72de54c85bba7b5066d7a183c9f500fc6b3d32a811f70791cdb6e5cef3584e9f792a5da33220b30f58fa9b9714d4894c14d6ec06c4b0c21cf8d95bd33ef537c2c1dd158a32533859903953e4ae1690afa5049e00e528a6af4d65da371c4c6d2794d4a3be636b9c16b073ab273c256e6d137d123902280b27378fdb02840d8039845a09dcc8f71260763a9400c4b2a73149a63346e58a4c6691770979e2a7a5e5d44893017283f517e52515a4b396fd0932cde86d34100b7e8a6c235c17c5029733aa162e777e8e6b589068b103a03230a964ea7e906b99b8ea596c527853805738a1885002c4ce4353ec588eadf77056aec91d097b7bae97ccb4240cf2d9480fba451da2334e34b9a5f10ab6e17ebc493c67b5a36069229fc94c68373c018945d1a68ba3167bb4e422055db574c7644346b09e31467a1941b3dabd41b4de22431eab905043f97cd9675a0714b702fc90d6fce5dbab755c3a4b5cd04b41c66924e49f3b9dd6b716e5e20939979a3064f90648fa68f19275bced0573691638980811d37de2bd007a1a8b0ec96c75dee5a034992d7c819822b0c6d452f9f2f880ce564700d89be5d1a2a04863869e183e5815f07a46021db118db65beeec3bdb47bcb87ee0ba2e96e692717dc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008615180b7de9a84f651da10d334009b3d65582f3912d329fbad4ae39a9eec78943338c29db4f49ef41e3c50dabbb530e99113440383f20d5a3a8ae279a6201a0c84b003f6717c709c21ae893b6e412d87f8e0cee5a89e60a14ce975a4d42e4f43f4710fc9fa29e9b2afa93441ef5570123aa88aff009e2507a3e60a79cda25652e3ac3ac0c10a816bc04739b6fc758ff9ac467879bb67f270e4eab43f10a633e5932b8d6dcf23814de8643407b17b5e2a91b340f7bf6882db694de4dee4c480ce037b9f9a220acdce84b03746f307a6026531d712c0630e7de3add3a8516ba602d2463e3478008b3252b658fea54de41265b5c81e4e913ea0e2a63309497abf961ec40ac374adc0ff3c6fae9bfac5cc2df475885b0bc636702828489183cde1a2934f2d63828ad1f2b8cfaffa53151b0ffae6224df54c2ac47cc8844b76222c2a3b6e132071150049b6e46aa75dea28c13477980315fb64ce500bf0c6f633ae621d65b331ba96cfac162dd7897b8505257e228cb621bba9176a7afb3a2cc20d7804ddb3aae4b87ffafd3c8dc541d05624db02bd62491067ec1cdf73147014febcfa5b561756d5e7a13b88d1e7b2c0375e1d0de71ed20ca9cc4e6dacdc579f1ab024aae2a0bec9004e5dd81c046f00a2a4cb767c4eb240d205278cb863d1a61def16635c6a84c2406288410fa4b73b21077d8f7a4075a1ddca3d0d334725151e434bda80d3e73593338b07958d27337e32cde0010dfe5e58b99eb27a97dbd1c5e6f9a552a02726aad5a4aa63edc336d83e5870dbd514193367af2274804628b4eedfda3b2a155694e89f5a6798c5d6e036159c1f00d8dfb03d41940e775974b11c3fe4456e07b127ccb44e6fd6b2918f57a6523d7f77f32478d9f1bb539846793d4284e2907830e5ea76054802a266c85b122a389eaf4700629036716e2869c0fc9440856d562711e903a1853bc68582a95344b612e5cbc7c5b2aee23cce4161a75829b2048742fbd65abfe2397cc7d66023de34df4f2df8540cce9781ed6482d29ca4e906716c8cc9596b158eb51bab8c2e00253d6589a99b3d20fb494834b42bbffb80e7b0441e356b541f83877736985f6330ea459c007ce8bf18d84e78e36482d581dc7df97528ce15f68e604b4de62422b3aa76f3e7e5b33a49cba9d89fcf50deb65ee45173795393a50fd4c60cf6becba7e733513537d13f89fcf1c4d6437de0eae608fb11d68b9adc0c3a19a3565f6d62ba81a326ec334b239b212b87320c03a75c58dc8f828c4195ed9d7acddce493123e235d098e9dc60f5d3a625e1ff66f245e9977f9630a40d26e3afb6676f5122a88ce5507bd825757d9ccd53fe574fd0e6e728da355403ad664ffdeaaf636256fadc3283d6f15b297f79216833cf2c745c4c5e17d03260a69178f2216168bf8f00c9889e1e35540254f150c587a884cdfc9e5f7d379be474356c06943e416eb0697a1ae989ab4872d0bdf436d9ffaafec1631c9939fcecb84db2846f12ca395f506687b4a5638085bc6ef58fe8e2abe9f8d51f272ee855e2db84a89d348dd66950b8f43939db897c519fa302594fd1fbd6b6e94ca8ff63a7949432dc2d35c60803a570b1dac95ee0a60c62fd18b3319601ad29a156400d392dc9a14ff50af6752c1f6edc2acb7ecca71097b6e82227de429f1a29c5e38abea1c74de06e6788cb1790ae9f0e8ab35afe60b001f45971d42949263aa62519b0d630281a4c5788d5591b1ef5a003c58987e8665701e5b1c6063f93533094e96820f918c354903775ceb6675c4ce9cf940c4beb8845b4f5e1f642bf505821e5a23122e2d1adb82a63ad18cd1e4775a96ca9ef9493d75ff784a2d4a99f54dc3f87828bdff4b3a3d98fa5a29b62a85caaffbace4592a81bfaa5b8bae6606ad25a92a43140690a6003aa2d617fc707a53ec9d868e33596e098773942d798263f58fe5a1b23046cfa136ea35203b90bea2c5f0aaeb5ea8c24b8b8cba14cdee28f45d0278f193228484bcc7e08a75d0064d605d674aca9019a0a9aaecd6ac672cb8410fee4192e6dca7855fbb1c584cf288bacb40707d7e6f8ba2956f6d099f52bc7b0ad72b5a3ffc03c7b47086330244ea5d393c6b9f256fd82d5cb9436a469acc3f8fc237146895be148749f82d39b7ba4ce47715bb393a96ab471665529ab9e9958b12396c1ba7529dbf289184ff0f635c2ba9df301036c869d52d993463222b70ba778e81c8dc668de41c0356eef5c39f1bd42398bff30f959e115c6b386e73f0fe28a2665bd463c781da1c46d6d4ea284b152c8c12426dc9cc467809bfda6fbfbc0bb4793babbf6ad564d57ae9f5e2b7f651d6ed980f8b1174a126cc58b23c32ba73f5031b3fcabfe7bc360aae412d799cc14d8b252d9f9ec9005b7fca04a88cc8ae9f7aefca94137003d5764faa3c7c45670585c84f74c4ebd1f5ad1f97ea093595592fb90e3cab01f98f06e114f13de67cdc36f3ffb01c3d51ea643c25a3f6aa2c57690e42b98583d925ac7b06a349782a1d33c06bd05a82a7aa3dd679326d948d74a1861926b45db78d36070d3087aa9c5f4f42ca57ee9ce7035bd88a85ce1107c8e07e5ba3a62ecf012bc75fbf97c4c72331b55ab9a6effd78869f1cd3f330526f262f7dfcfa2b084b61e90772d5fce8f038c0f72554467192cc8a27f1f53c8714da1864815974b00991f466648478c5f9bf036dc4083d72e8d144ab10fd32408da7677729347febc79e48e7b87388d9b59aefc84b5b3b589fd91863811a6436ed76b43e657f7ee03eb796285a4d93be9aaad1e1a1e81687e42ec83f3dd059b78bb7f8ec70e6c831db5e90c6b3aa511f36507dbc8e7a77df0f5b9ef03bfefe9471de7c7fbe67b9922260d3703d95a5bfcbcb62d830e20c23c6cfddc210e47cb575957d8c3514a2ed4561c738928f210057896eaeb1499d4ddc70f44e30661e780aaf5c0a20c8553f40d7d3ff6d120511c1073510d04f2de544121ab851e98f666906367c21302eefb1aaa723f6a531c454eea0be7d5000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 64&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000029339aa1244c317140a7a3a357d70c0767bfa6bf97cb1d540814beed3798e9280bd4c2a44ae8b4b32b22e28c4793939136e746846f5fc235d3801edcc28ed3202acfa91fdcab927c1aeaeeeb72edc2b4af68f367473e6c0e6310e3645516ad1c62866936f272270d8d7bd347d35e3f12ca4c632e32e61581214729b26df29fa49db5c6dde68763288538d0e33eddd20bfee3d0f4c259dd658737368a199b7a51f0b3387819eec986e5699398fca76d05362b8552c269f47a20424399b27a9104db2efbb379c9f2fab860f6cfc29a8e72cd3e3b8283cdc92ee8e4d89013c35979a45a39e76793bc71d2e86374997ab2c8e0c80dc0bb122c9a968d37ffeba50e73a79891c10f4bf6ef2540f3c995fcce3239c485ba4f16348c42da97d3705a920d03e65eb16c468279379526c572c5555611642f8dad296768bc660b8dc4b56319122c90ba5848743a587a3a5449e3553463f7072f6a41d3b59e8166d628147b428735c0ee656b6a83c18bc48f22a0a8b257b4552868cac986674443b79472c8c53faf8d46d3c8e1a7a9c5ac1d1af46206b6bb495223cc24569c679558ab69f4696614d532753ff7168387a5ff23ff5492e558d5327632d8e6391a7661b74f77513252aae2d404478f943d66a85e362b57d93dd94d9cee019f47854f03462d322a31778e45270ab18a642c136e69a863792ad62db66a36854d85e1fa7b9c1f9229806a588e74ad0531de3ed35ffc4466bcbc32bf15d366b8fa92d3618544f2773fda065b66f903c3805f610769cb622382c7204a6458f3b5a466d88ba22a57af492c868674ecd1675089fbb1a6b61495912c53f1b7797ec48e10a3cbe75f1483364efd7e79a56281f53045733912ec8d24923ac2644f65111e12ae9ebf05766f7059bc5b23559db9bfb9c9e7e9b6332cc23d3d8dbb5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381090b88f6231b993c7368ba543ada749a90b4a85dd4a24a5668999d289385f612c873932b42d5e574e6ec20755ce24690d91f6f3ec3357554170e60938a01e70c333c812b58487b59010143df1fc0bb7d2ca6b252f755a831f970976b06c1ffa0e1dea176641544b9d32f2e5c7063d0249e86c1eca77108d41a0ca9851c609d05286c218d04c5adb010f186627bbf264745cd8f4e22aa2e927100a57829e440bc2fb886cec3f411171714ec62e6c69ad0079cf1547aede44e6086cb876fd9897068d2221f601d6925a9d91a1bafe8d990ba638f96094d2455947b1e81a9a72f6205a78d13fab240197665e2722ba1bd2ac029e74f8f693b50c29812a99ea2aab2b956975288998f14e1e9863eb89cf7730f111d28a724a1ca81203215fae2d6053d259fa74ed61d79451f53f81a57314291f2de6ed2b7309c4429d0b46281006b7ca115a30a6c71238a5faf31f18097c3e01200e27be7a5e23316f0b13e269c3ac5b8a733a36aadb5e6e67e184023c602c7391f6cba8a56d52a10b7ac28aefbe2df06486105a578180999dea555eb6ca39db2d6d62402893c029cc717aa663250c6eb6d27e86b78dda22f5f6a346dfc67154e5da0c1e1fb3c6238694ccc0131c1584b554f02f0888d54a1167b0c5322ace27b66d50f82b47ed2b94727a9a26413491b97bf0a4d5884329d31819004c75048f44760502093c9d533c29e15a08a69552803e1a48b9f8956d8bb55ae818eec6d94ed660b16f83f21e09b5e6f55a3e9999536a0947547a26bd4720e7d751e20ca57b12738a44fbc3bbe1d342f5387b45159c6f5af6a52a12cf71487bd28597edb06c19c9d395efbce8582411434060a424a6615c5ea6b00e650dd3b7026dfd2811a5d17204eb30b202046638918516846755217c19a122f78c35a1ca26aea45eed8ef1b400aa94a9ee2311c678bbde21198f84cca12c629498400a2ed93ad676027936e1afc04a2b5497a2a94941c80294362b389a518d7da23de665e23f475409b63d02de6e1ae3faaaea1b37e4fba9b6a042324431b9485750bac6e5573da9db12aae8c5df9ee96f82fcb71e4697ad9d1d77f0626596b49e02890c12b444c387fc63cb156ce075f8052d9bfeb315f282360022c5107f644547a88944c32f294b0142e1491ac8af7e3c9707c26d792efab3f211a698052d8b35d9ff31c6b310e86e55491620607b10b48a654768774d2b7d380805de67e474a69c1aafebda6ad8d12327acdfab98c750278d49b7c903600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000088299b5b6fecdb52897a1958c5c3d1fc2f20b7d045f551856ea3cb441bad9089c64cb9489db6b63e0655afc4c2fa73c7417ff1b80b9c7a1d659687d2c415b3a909ca30e96849d4bcec6a9a6a4311204936ba972086b2394d86e840770d01550caa6ad85adc0ec851d2b3808e4a0e9830b99a70f6204ed4dbcb6759f6228126039607ad7ed8eafeea28d1c3e25a46bc18af7e01f55fad8244f15de36f890416aa09548554338972c5f88fd9357792819e51a63d0b872b0a4d21ea3597405b52793d50c6cd70b52841d53484bcd3ead004cef0a6bc16ce74cb8ad0848000d8c5158dc16625112d1d85d17a3c1c8bbdaea42c3a43e9930724655592116c4c6d0b8b223337ee4e754541a09d898f7fed71c3785b7f8721653986c525bc00f15590616437d11f9722824dfde7e9615f1fb8488e5327e4d8baf5f79d1ff5e808d154951ad87638910607b03faac3a61fe9916ba65ffd16986deb4169bd24a72b1c8168fe569f3c81f93f3ebdd21d4e806f79fb28550912e9afffb52e97860c4dc0d042c56e1bb71c28b68e416874ec7043306a29bd1f4b9a3e612a6778315e2c2b850d6eab9ff1905030fada250caf308735393c191134f3c493d00b5695775d82adb9f2abdad17fc41fbd7a1defe337c2f8adf69154cc0862fbd43035295b1a9c80b88fa8cf75b36ca08868f881966b41fb3e239eb1db9cb51606a0a9ebcd552b2f4e819e2c30abdeccdde88d2d2f82f3585b5143943c929591d20cef559cd2baf2dc7fe03c9e4e084e8890fce64a4aa9f13d5eb945ad7e3cc53e01fcdc192b97adc1f98d9e773a0177e8d97405808ebf48bf17b689bfc15f4c515e38a855a9266230c9085adc9a6ddaed93d80c3f38bc516695d202b4e89da5b4ebc43788c848f8c4a72f79f37f857edc105f13e4ececfd09302711bc1993f5308b8f32ab96fb8ec3f5ea0531dafd0ab3451f81f47e62c593c8d3e3beee79db06909576bf876145856f5f716caa436c98eab28c5b85bc2e4d7e1653ecbb8bb6b5bd6981dc72d7f63ba06cac8197eccdc72c1481db44724a3c21f7fc60661f11fdde8122da5d0b1d72a29952618b373423a892875e6ad24d0916109ed8e9a9a8d9a68acec4bb5eeb0d00eaea72d8d5a76c2a42f18cbdb3d336b71c70ac73d39d7eb04533453779a1f210bb4fc056b4728afdfcf46675c6ac76f750626d642e3ab117e5d6740154759a46c27d51306587650e1039054b876849882e7dfd807bd03e69021e337dd69d9b097722c6d2aeb517d773d2f7d84d69dabe1a1d6422ea1766c0fe7b8dd4d7283f2985d96d91a132b8ba03ad85f7d56095773222d0afdc5a192d29f3bb0c2539a1c99db4e711b6ace3febd58e45e99c9f5a04cecbb309d50397f28c48bb9cc9f9cf75a52253b634ec47216a1fd6358af26501821864569879be1736b0ad242ab5b8ed16a7ea0989ed4cae3567afe1f8209a028db46db0270b3bc06668a9bf5e1bc1061babba00ec4ec37280379139d19bc6072cc6b7d260a816cb82f9bc90897be3025475af12191690f9f400a914789a860155efd2d606a15895378c827f2a4ff700303962fd96db2dcd2d213eebb2460f0b753bc6902da81d44c983dd027f1171d40a2039997241e09ae5b6165b4d55a8e4c79671a8b8bdefef2c21f81c541a5719deb939f866b61be250af371cea7b7525094c904698d412737f7781bd779365f122ee627d9cd4a68da9d5be1b0431998aacf824cdd864c7365c01cd5a5f480b6ac1e5fead8ffe40d87c1f9fce81867157242285c5e76cf9667919c29a67ca0c0a61d7819d9ee6b792250a358f5691ccd80578f15288f3d5d6d7dd6dfa351fcf8df0223f7d1da1b76711fbe0e7fabd30377660ace7b23acf03abc1d973248cdd0897773fb74e20481ebd3e52657c9296b980905ad29271ec128513284f1b78f38634bf84cb80791a0c5649177791cdab87769d57b626f78a03435c758a207f52bd2a1f31e34b6a122b8701cd9fe478c57cf3535b6d51eb46caf794bd69363d5a56adde6945e9788f1e1dfd045bfbd0a68834b13d6b9ec4ea9c860eea0e9ac19c2de14ffbd6b57e5992b08943ea0283813f3f15e4f928b8d0f13de6863990f5c77f130c97d8be12571edcec7deec4b6ef4835f136da45da70a11f9192478fd8b4846c507410fd11668365b05252e68cb2c972acf50156e369b83bb85e62e4bd4d84c2e9ff41a5844d5d88aaae7ded852daa0ae5c14a5dce64c7e236e9b7b60f5b5ad4d953a2d842a52929491be3555ab8df534cad56dbbb86b28a8a86b7bd9ad1c58c87b8a089324e00fde32f8186b2b74523a22904c18ade02c3e965f94624f8df57e750ea6335e3eba705294b76cd6ada33d90fec1f48de7ba9dc7d8d60a53d2563964188874810c45736c57efbc3a3ceee7238aee5281882a554f2143bdf89ed4bd819c08239c187c12a8b6e763434b92c26fdd658b350f51775c60cbab7a2cb120db8ce8ae9aaf6af559f8cade84c4820209cbd27cc09230b22f013a0e4cf8041e4a789a5d20be9914a624ab957318848addb39c9748c8922c54327048a2e46523bfb22487538363459035ba49858f85a469957df1f4831bb7ffa0564c53233b99b596f5356089949306dedd6b904433d25c4854a80590b964df6b0703b4f9628d6b9a4d3f0a4096e9a0b46d6b32f66d563baf688add18de001da62e33c503a4387ce0920ba5d1e8b69c38e3745b19f8d8b6ca5e1ac6de90edb25fc32df04f0849d769fbed3f8169ea1d2252619a2304e055370b4443cd23e56d4934f9f3fc92f1c1eec626657e6a89c1394e56061af8ece3e2a17fbaaa4d579a99a7998632a6ae2683ddffffd27a27c8815511855f09adff7bc627a7a5c95fe57fa3ef81f494fa7ea6e6ca2d14775a25beaf1b5a3e35ecd4a306545d597e4e44301c3d1648f0a7d841f2f76fe59c6eafa3f5b58907fc4e642ecd28d16a71ee3d295f1de12de1485b9cebeb2cc6c9ac051d3d42b6a1a068533a7680a98d015b09c5b819ffc61688d441c1b7fd71180c4423e64ee940917c7dfaa19f3f51cb5b38d1b2b7c81d10e7c000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 65&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028d39041591f322083c778ddbce9e920ebdc68bd3d6305cf16f3e9e06c63d28989a4c72e2272253d8da9617e5ddb56a944df5c7272856b70953871163379de04275d91c15c2fd345eebbf295a31d5652adca4e3231cbae2ec75889659325e66ded6f7ed36ab2c34945144821eccee70d27afbb208e1bf47da02dd8aeb6c556e5ec0d6f57437fd419d4bceef7a815577d12844ea62a752961ac4c72a6f8476933028189bcecf4a89aa6e5d20952a9c9f4b08efa9a8b9a6332efd5327a1e82028ad751890aa9f1437ab0660a7b8869faf40c25749e737daaccac99354ace5d67c8a0e4e05624c8cb7b1e6224bfb8ce3e1917394dee4cc79e7609456960ebe6912c5bd888236d08f479eab9956750f4e91f994e0e91d8a5127e9fd5a0481f2887367f9b8b2cd95a92dabfd7a3a40f230b14bec4524c6d2a2d3a0a776a3bd536e5574ab17248c7d35488c2bf5ae832dff084113411af9219d20b21906cb2b9d707b50070d4f8bd8e37d451fae88e80baccf68d833fa0d82fb474c6b07d642c8d4ba98045cecbf51e680be36ea35d673d7606829793b3ed2c91c6e928c35cb028b889fe2e08e0f7f2deba1642d4c4468cea38afbf5476043954e6e507382fc2e7c149ca3f315b57894e7202a6c90c6fa6e5961a5ee7a542c2a7f34ed59bb8a178e769c41480508f46962c3ad804e9f86bf4ae8c7b244323847787469b28e9f6127e9154ca328f98a75b93bcd18184b0bfd74f93236115dcd7fa25e3437f3a9e9ab6ea4368fa7dab6161d026b85836a8cda79f7fb61508ce1c9437048e6be9bc788f7a0ea72c9b5e4344d6b3d972308ce446715588b1dc44fa17875923614dc9599e1e17dabdbef4be4bce85ebe5d33cc444656e5ed5ba07bb6c89c47f5f5b9c6d3dcbd327ab7cab1845161cddbc38d55a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003810931cd6e79526ff01b72efa4b1c1aa7bce3c83215925112143ca6722505ec8d4b90eacd29fae5e21e8c52591184d38179ba553d02cda4807d4383253cb3760e5467158b2e5afc3168e5f94ee55551df1865b5d6d2b364218c38dea5001b8b0836c9dfe8b097729f3e078417ca1a4c751b69f24da95ee153d97817846bf27730cfa9555a49fcd36e02845a109607d54550a2ce29795c154a15dca3c101a32b7c0422b50e5907560a3191905e661e2c6eb5232d3f234c2789fb2d6621328f04a00cb2b6ad8ee31f23ed7df948f5e9905e1ad1bfa53e919088313039edeb6c26753a2810e944462632cbc6d0401dc81311ae1b9441768820739ec3a26a26e89f8a5759e08f8b5b5f8f6bba95ea542fa3942601b83ddec860b8787734adb21bc02968a6e385822c5ef7bde67f27ddc7a1599a15740e2c6056610a0aa800b349e1e52a9d8e197c41c2405227e25319fdb619005bca59be7f494091279ce80d22f23480ad584fcc11818a0570a15cb487f086971f848799a19a929ce156e928624bb8650c53e003f078591744652718a09957317a6dfa90899cf3eb980f049a34da889d669338728b4ac22e4b6c82141bc2584cd8ebf0f4a08165edc0d40d84f934166706b6d6574845a4f56d0834224e5b94a24a4f1cc51054ef503884254fd4eb0b21314661f71e0c8a0e89edd81663f274551066f5a1e652f2795848207d08d28eb5d86c6f1fd4a68a1fdcd2a179dfab5515fe2ea2fdc198e7a20bd2f990f4e80d22b6d483cc2dba01bd85b53e90931469a92381e4a364a0755726c81408206b891da9e65ba5c9d2e28dc0928db12380a68c2f221a52bf41e58781730817c1758e8d8388a56484b0b41907b566e16cbca72068a5db15cc3302925e374b450de5255e7d503e781a37e783110cb59285288e635e4e4022e506452920ea7b11d83c0a7f7b79a472a9a42c0a0911f1779d15335beab8193cdfaa72a66da3ac6c218a00fc70485f481469aa22cd389042532864f600668343faa1011608c4df8321b43340f0647a5708aca55a12c67c19d9c509c44186d8d946f86717a1b692639f110763611b657d93d85218ba86c90b07b280fa3b9eee5222c15fc46e6e71a3243a7200d5a97e24944202d3ce7119eab7335368841a3b493f9e3fa8bc0be10a18834bed2a9458c0ffbb8490125f59c255387d475e646360755f47d4cc1d5c041e39216ebc1cd534b656510f4e62c5e666441f8e285983402f6ca9c57fb311275205f063b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008a3e3b57b208352a820f622a694b7c3f6f297239ef0a069615dc664c02f1822bba48e11e37bd9749c98facefffb0fe1792a386be10ca7b98cc874c68c36f5096d3718dc93e0734d6d6f913e3b958dc1fd1424818c9437b0fd59728ed46a79fb52c737a1d1d26f04ebac279a7ff6a971e2b69576b712d9224ea18fb9bf4e613a8935f3b36a073b01f37bdc0b77981c8f2804e93c395419352b85c8a32dd77d41da9bf3ecb914173e80dd1fc06e8ff5bf0e4f7424849a15eb7faf7de77456ebb64d10dc10fec6254070c7df387397137372ea3a53dfda7da13414af2df16c1e38c5c70a5f5f44f725d622049256bb15dc04a8d846a1a0dae7e765a7f00c498f1d0b2893b8405be4a43fb7e97881069a49134a2a847184b82eb5a690d87baf2f579619ee19a3d7a7c7eea72d6e3fccf0a8092bb8d3c6b551f27e63e762a30b4a4df2dbc4d119139ae1b135d06ff827846901577700935e0011b65461c2ef9a7b71eea33c8ca4519c7bcfb557c5e1d42d9243f2dc34057f5e0ccb9a457fc34dcb10d9b47f6ec3b9550d3ae4fd593dfa3e28c6cca1ff1ebc9d98da8db869f8c80bdbf8ad4684acb6a779ca9d0a106f26da17043773862681c5dd2deb1bca2ca48d4fbb4bb7c1f765dca3a1d991d890b9a8751ceaff543997fae5b128ab2ef22b3be94499dfd9d8e78fb4c82ca8d296b0415e84ca8b5f2024455b5decc8b4ccdc7bc4ee06b4f0c66e6748fbd07e3a3bc5b4b6889c40dc4a97ae3eb43c3914def976efe3bfd84a093bd69102d7b37c89b458a55b98a1974a13a7685d26e9d816c79585bcfc1042c2af88534a9fe8b0a6c8c44355a6d606f902db40d5490264bf0f352c27355633cb095268d5b8bec985a62d84b2323fe814053f05dedc22029d2998bd0bcb255c162c4bc03f60e3580ac3ae86c37850110e9a1bcbd75f64a0dd60b941e2f57da9d72498b3ea8324eea53da3895585ed2942b9140f260895dc6a1131a4c3ad2b64028bb8c0fd67e1be4c07f808b47daef306fd9578025f9c639660075837b2c95473f7f860d6ea2c53f4ba677a2345cf212c7757bb94f1a4f76d4e96625f6fe051b8246d1b7611bf6fe325ffff8514d2f9a3453f0e77ae8b958ab5b567e541f156c6f4d315b4c3c547d59bbd0d7403e2e6a49b9e7d3fdba338ada41875ceb03830a846a1fb266c0f1228aad2b76a2e3404278dbe482907206fa66487ad2c999867f870c8cb7a70b83437e14b9e893bf6b391dad75e84588e882246d161799adea63adf1ad706c0a3b76bae595d84b21ae9da30bbc0856987f2c2c543d977747b8cbd5a613b92804ecc5284ed23650e9dafb4b76d63f069710897334f18ea6b0cbf99cd590a78e3b050e1bb24c86d6323a17106f0cae3f30b01e4eb3db1b5f3a4771a880c8ac06bcd5a82d4103d0452fd7b54834c1cf8595dd77f82d4ad9ebc1cfd0c9a8cc787e10aa4d1688474208b69ff7ad4da6986e5f62a34ac3093e0fb1efe8ae3a96f6aae09b0e8f6e7a2b65c7387999cecca43cc33f026dc19bbfd867c48127cff579d1d71aff0c4a0e20f9fdfd599a6169df1b85f6051e02290df6f5ede4f29bb6f0c8f806d6850c6534ecddccd75bb8e4a097c70445585740f822e5cebb0e19eac82bb78ebde2ca60a810ac6c54119fd6427da8a0155ef48653515a919b299a306fd3c62b505a6911db2b56ca2f296e487ba02c546eca2783ade8e46a8c78eb1f3d7c04bb24548f92383e475ce6e572d8de1bfa9b3e35d9bd6c79547b592c95693750010a3d22cbb31aa5a4abe94897831b1ed9287631f006a735c36bc84a8c87497eea4873801a733f35b328c7d2ccbe4a41c193d22f972571ba7630b33080793498cc85e6eea1c412914459da175a6db8658d0bd7a823fab286edc20c785c40bfd539924a24af4e3d37bd781353677c76d4672098f5bdd17017012571d9afda05a40ab56998e40f5e359c43dfe32ca10a45bf08f67d128c24b1acc03cbac46ba6ca5a532c105e91e0c77ed59fb534aeecd68735a4978177bb5a656b9f83b202bb604d61a24574c16656e512c0a4cc6f597b3268573e10539d1ba775ed83bb680bb9115011c6ad43fbb66fb37c467249060a1586df27b2cefa65265ccb9051e468000ccae24f08ba941a8180a64bb624f146c8ec562363b32c369f62997c4b1375dd7de64725a598529244273caf8398913c6fc01522683cf1f9f965c491abe7a554f0019514ed98d75eb8bb8565f77c195f629f98163494b4aa2674f92a41dcb67edd1d818a5b98993d0b1198bb6bedabbb486bc6fde039433e842bac568a5b4eacc028cc2544b57d8883848dddee2e967ea85a6102bd0abdda41c3d78447bee1d4949449abaa9b3377e8cedcf04a500fd1a6916e26983e64b5e96fef87b32a060444d374409262453cb1376c349a8b5d1767b1e2991a1a6044e0f58831bd11f12159675d215d7eaa74807c995fe22017e30482db8a4b09ca7800822c75c92ff649fc0728f5a1d44efe7d0ff147274152d5f2f60342c8f5f951d8c95f83c1d54613a182d9dca68f54fd55047f1f90cfecc04d733dfa82cff2618f29a4db4f7e1e59dead58ca65d07cc90c25f804a895d6a82f9375451cc55506d276fbf783f7d4d53b9bfb83dbe4a8771afe21ac543983d68034badc980f9434527f9edaa2e228646fdf75b44899e749cf4c9e5b345222385a4424382603ad6efc24c56e769028f4394f2f6220a9b390d395e412498e57a08bad927b8bd5d76e18e8feb457fcbd3248d218236b07783e57fbfa03c292a9f5719e6aef2eea3fab2caeed5442e89bffb236cb13db2cf9c35a38c338c377c475daf45f8ea822f9aaac13425fbd43d3dd9229367f0b3687d7e82ac5ec2fc7cdb69c99a4eb1b8e45465c6a53f16ac0c4e0c970b8c732af515c09eaf25596f64a04ae4621037b8841fd2b1bbcb310ea23e122b0b9ab96d8f7702952d0e96e4cf79c2a30df0091acda91479ee2979b0054997c48f6a0e909bc52a943459af25553969eb31ce7685369a7fb014561b4697b8bce220983136e5eb2303cca4eadd4c6cc74ea2fe69d448ae6ed953a80363dded5591b27a1ea956df081ce99aa59dfc789d9d8fae952b0737099d467d0000000000000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 66&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000029039b7d84b8c06665933c5ccc14eae33f8f3504f1ad5e313bd60f374f24df54016872db24b61dba7f9042923942220dcf60f83a317c6693fd50364f7663d936565c7cba158975f5b098d8d4ce45710e40fc48bb06c76eb43c743070387bcc9c2c5f7e7b54077b56cc9d14f1e863a6d183c9b5eeb7f43c7220e1d5d29b05db79ac40b81bda955c995bfed529012bf9fa28db6a922f7487d0224a2d078acdbaf17d41a99f20112b0419a7515128ea665996a66f750f55a67be3238b60a474e659f47ddc0fec25a39f3bf03b9cad9885c2df49df156b7a69e66ae14557e2d4d29b485d6306eca8b058d9761174b3d2190825a603ddf3be1bc9bbb898e13f0dd27b7166cda7bdaa92f5266e8461b22f9e08d71ca0bbcc55bfcf8b27a9bd92b8df3409ddb36a8a57e74849b559aa6c8c1e7683cbb0a975da8b9f437473d2a28256f39d933f6b9b37b1244e5df476310792e47270841ebee1a3164cf30691ea8bb6e91a5b71b7a9acb909c5198e9cff096df643da556d82998fb20b5acaba3e88e1937924464fe2b8ea18567de6ccb288de348532fac16280addd06788a68f633b4932079e751df23433a99b3af441a4c7166d4249323a2b8f7fe74169fa4712ec8e0e94c93674f243aee9604d510bd5664488d6a7ad0ead49b2feb50aea25eb6b90aa548c93a2c8a7ba578e215df322ca6209e4d28dd2762c35c4cff7f3f15eac76e94d428cd4af72831e2bea896b410f842f20b1ecbb1a474d338c64c608cc216a6bc989c1f7eda984fb1895cc61531522d71d8bf9d0cde24ee3551169a1215089e7a7533e4163b4474a7aa749ee99636ec74fd004430aaf4630c271be3abdc49290d34746bbff74821f4a0dc695e6cd98d22d3659bb17f187372843b148643af99b55054374b638c69d7158bbbc7a49afbc40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381099060dee2ce47aa52323d87f2264f4f9ee780d3cd457e9d5df090e6c79bde3e8669135417ac15a931aade417ca058176dd0a1b4ddf5ea08633c3560f4d707cf1d9cb0a781988443a040635f1e9628393bb66ca2fab1f6680a6016244918dde03167f536387ff2849237acdc4d884146f73d7cc03896e4b41aaaa6f7ad029646f67c6180814a78ac95f3506e7100f6dd9735e6f715302a71d5401f35e0cf634f473da621cb9999e2ba6386bb80ff4c1313eec6305819c48f2e50f8040eef8d2dcf033d5f6a4d2e87a2816639bed223f26b818c00d1fcea1acfa48f403fd35ce19077520e673a6ceb957ea09615d18a3e89d1b13a845c07edbdc2bd45dfb05da73654ce0e65ee1609b255119280723af1616e8b5d91957f209bafa1407303c775729610712ba12c0aa1f088be6913b81464bba9c257732c9340049d36088d29da3ac37565250ada2c260b89117e569602ae83da7330764e7a45bcdbf423600683fec5dba5cb05a711a6c07386729f7d47182c242549f07035249062194c1e9beb10470f255f250f568461c166c49902da97986d0130c0cc00e9aa3b8408cf79daad1257eb9c049e71243b615659727e72584219962a5024436a8793aa37194599d1167acce2e50388898ccd91d18122278d4cd834958d6a1d757bbb5cb9a9edb852d989dca994b2694c20591d9dd19bc3267a393457825827285208151056a0d7bc76ca611e1306753931bb2215d67755ab81e512191372858590a6b244491fe4968f9e0efd4e06b89f626831a7d85e536e61151a7367423ba3e0c979c3003d277e3ae8fc94e3b7e4001ad989ecbc6059291c837aacd8d042ed42012626b387f08c0c0cf189c2ce58805c32c34a7e95887fd66867e4057d41e972d07f840d420a4da593848e9dde45791024cf05365047118291496db9a75f8ef0b6e900e387ce97be7e2a96f09c0e4871d02b189734b311bd6bbb0666168525d03a6d403d0e051a9559660889e211db4e3c36aa12068dcd9f7fad519520de367aa8e96084d9fc5fe8b1e1e0905251a413f2bdd1760d364d3a7b975b37f8ac87b6ab88a94137d891043ab2a18ed24f17b36cecf3573ca21f8dd674d625057f6311ade33bd5fbaf6cbf1a08dbdc96f8f64b92a7bf677c163143a9091b5678e11281c85f79fb083a970ca1dd1e34a1920766bc20c325519c8f0432750f4ba4b09a7262925faf79fa595a08dc0d69e13000d329a234b9e739d659c294990b37dc1e0e008ee468a787390000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008c489d960d04a3df6984276a3d17d59af9e72b25418c8797170fa701a672c5835ceaa22dc35470d038c6acc5082d2ae329f36697c91cbb1f9e42da59a654462bf19e04352192778cb050db6f4a656f6ab0bd9641ca8ce6c1ef8b020a3d9fd9dff772f38926458bda6e6072456e506ae464785399ad7b498afd4c211f09d0c722fbd9e20890cddc8c6eb9ee75390e6d76d0672fa64d8b97c65cca46dd1f542b6d6014f035d2817c4b9430ac8dc318cf8642ab34f4c8d71fc0e3b1fc961e94b6a84622876250fdc21987777360784d9a58f35e1c9b71f30561ed6854ee9b112e7b20ce064272213bd1a46d0d19e5efafaac7addf4d7b7a519d689398eaf1e67e64ace8e5e89756377e1fe458d04e3df7f6680f8b69815680276acdbee6c8e1aa909ec56994f3ef3b65fbefdbc29aeb0ea906274e838cac36a0607716fbc2b8da6150a4ef39e1cd9cca72915007723c5d2442f7133258234d18a257da2c13e53b47dc6abc2d607b98e351fcecee8ba8886821985bb3a7bd02429ecdc5a27eb04d01dadce88a324ae44f567593fbf730c284414056fa33ce90a6d6f146dbb1635bd26b4f883d4948da47216c70d2aa58ceb3979523c6a4f2f7ea455a97c7adb6c43685d63bd4c51d7ddcb81a06b9bac31a7b255b94052d686128d234bcb63ce713028451b18b981b83da1246281fc3bd2b06c741cf71979daefdfa0fd06fba3722ff7bcb2821fba964fbe9f6467fe583c06d3889a40360a7aa03358175ee75eb8fd1d3368c30b5691776c163764db924fba2362cc9572f642cdd2b11b40fa2683a529ec2100dededeaa70a1e639a71d6a96ad31f70a00fb63875d0fd5c21e56ae57b6e74eecd2ef34bb3e20be5a1f9f1f54955a18b4e4e4b9119973deb76a2a603fb6410a350667ece5c1c147dd00b07a88a7d0e86aa2d747a867ad90ba6660c7a0432e20849ef642a20cf5a20af7e34d139b39dd65c65b36750f17f0b9f1db06cc6e16f10eb289f567b647454a581604f381d66371238ab785585a4da2d00810ef6851a6009025fcadfb77ff7996ba6b091fe4130733466b29fed46554febc2ad291dd966bef4d79a9e04014d3003c95696e8bc39892ad32db6d6ad22d33e931bc87f78114bbbd97b334bcea676f9e9db23c0485ec06d8f37f070c143117b1bea49f06e1a2423d98c12883d32d29103f7699646e7091d393b21a260703e17380a1bd85452702c3af7df73ae7856a1c066013014de62c3c817dd74c44aa436a71490e7bdc6b8b74bf61711fdcc541ad7dc49cf4c3ec154879e048ff30df25065b5641367cbd3bba19606a9a27a64055d5d3b538fc88eda66ff9f26e619dcba696866de54a8dc8580b5b28144f952ffc6dc543e98cc9fd7f4538135c0f4deb4bf892266dcc48a4d1ddcf407be4fdf2a5afe4a0105a20ce2b3d9f48d608de2315240875f1fed696c49cd8d4a78ad26f51b3c804949c536ce35c3963dc1d238516b3f2d297f5c9939a946a0170e185c75087f37acf907f9e3f87a2b15cf81c7ecbf2165f0f3962d11e9c6a7845ecef432ce9e1fbe74c77ea1057d79cb595d47a8ddc1d911c6b97af76d91f3515081b95ced16275decdedced9ac790d73739e35973834503133510dbe39201f9b5c618231184b9dbafaa7ed6623e8bc492170812444db62d4f01925dc4f821c0896a746b4453e93ee51844b311b0a0a51601477bff651eb5ee331227a2e9e49f593eb2988e449e750e990a8a89906efab00e0955c81b6aeb160313007b481c40908130597626935389e47afcb0a20146f0c7b29b567e95d59ced7fa8023a2d69c89443a11e7150a03d09ee6b0f74358141d48e9bcaa3ee081c7d8f8c223f4d48efb3df8a4e287fc5b90b4fd251cb616687ed09ab1a06c42eb9d6a578d72e99d499882d216ddb3f35b0a33d9f2d3d4a700161a5c3b5a6729f197479e78009794aa1be3c25e0b9142613ad2ea508acaef5eee33dacf60cb7a16ab38d9f3cafd2150081b63a3a6ca0163a25fe81206a37a0874fd55fa3068b4c1b25e6325fa56646ee5f3431d33d0bc691c134ab306b0bd2d1087f4d898a529dae08b97683fe2eb8abc9095d67b79cff0e77404c1f7ff316c3cecbab77c710fbf961008047af22805d77eff79f815b21d142f517da2199f6627ad9fd85aa24e9b7f40c7796207a82901c7b5a3a42369a9bcebc24ece13a3ed064e4e748bee2890bb21b8e4845362be9aee46e25418f7ca38ed087e46e24f12012a1312bc623aaba6ed227cef116a3c2130b4b837ac77d86f8ca3553ba0cf5ad45e9b4e4e55059f1d4675291581d7cc9e5839212afcfa897e90cb601cb33a4d2241a5ed5925f6416be5a43d4767fa04f701076ad5ed5ece2d09b8daf11b00fedd2aa2e748cbcbe365031394ef823951ebc52b3e4c79d79234c16575910c29a35eb67c624f7504eeca3921f461d7f95eee39638c402481df7b59310c4554450789dfb28ed1e485c0018512eb05f14dc7a3db5c0606f9e28420d76b8f8534d2ae31aa01e90a20e248a7fb3b72ea859031c67f7b2b043d38f7183165a42ab28c6308608c530a9ca98f82c133bbc313fddd2109838e970dc9989ec14df781a518f6cb56dbedfc1e381250c64f95d0be5f37515437673425374d44811f4406ee2b5130334ba555839e61ae623d283c77247d2ef8b22ed138a526f7e41dfd41fc69a2839b77b51c6fd96d97d3ef8359e8725ba1afa80278fb3ba9c697f7e2bbcc5d3f0f2e61bfcf542d3160ede02cd6295fcc55865e7890342572499347df80ec073a91e00193baf804b884e9cf5c43269824d4caf7eef49fabd8bdc5496d190263c96dbcd287681c19b90c34635ffbdfeafe0601bbb7514fd84896a22895e9b21faeea372696e350f13959fc23533f3e8c34b17b595f3c935e37220aaf644f3a565114c34c7b85f1a3e465470166a62b13adb00a2bcd5a9a3ecd59fb772f09dd6a6e2ad12fd54ec62cface0022f2ffe3eb62db0f4d0f0f9d1fd6f3f11d76da868d2c1c4124915de19eacffcdb31f7ca018b6976260ca1bb2c4fcd6b9958f096313b608e208d875ea5a1fa89916d0367edc4f8890e93f1e660aff16ea79d1e583007e693bf06c172105b3dc24117dd921fb60d3ac0d2e5c89fef17087d885a0794e496e3cbea333cf72a507788efe00000000000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 67&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028c390fbb8189bba539d0f71d846cb47d234fbf86c5237298bb2728f4d99f9df7e650fdade79cbac773872ec934b123bba5f53aea4e21da4071b2d78b1e9518baebfe65ea95881aa7ad49d2f9df1cd23bbca6bd1d583819ae7cbfe68449f8a567a1649d21d22624d1449831cde3e771b10f56f33a99e638199e6e690324f39f6ee9d5fab43ffd0e31c06892d8a3cf5194cd9e9bb5eb7bf69b40cd27ba5b9bb39b3a04dd088b30e6132441dfbd4bca85d815d8ad0c99ba7fd7bad89bebd49ea6b86f3e7bd4eed883f8ae7f292b63e032df077ae0d9eb642a2759b7e6b31e9de221fcf0d59af76fcd1ed5ad35743628a06be37865f92e5fa50c31a88246d9cb8e2e33ef583fb5395c4384a1d1c8abd9bf3c2a9ba3b9a2e3d82bce921505efca3ad2851497dc4ac1ece5a3296a9dc4fab9f5885c1a5ae25db3f24f2b812ff36c1e53ceaff14cde797d9031398bae3d72a33d54395e61f355a2d8a6c13d1deb5b6231681e35c92426aabd0b542775bb75c893635fb58948ca18451c85459a24011a3c95d9e20f46e773d9182b7b8e995ff084ca2cf9c12316c513788b10b8e4aa3ea8d6aeed7cdd97ddf2bf8a22b5d6d6d65837cdf86735ee81f8b255bb142865791c9caf9b485a95a5640b63184d4c9ccd0925a921b1b9d269d24b73aa98eea4afecf8c363feec8393d5ae6ecfcb990454d34cc1eb3ee68d0ae4425d4d31328b53a9724e860f45c8d422669114c2613293891652a4830a6583d7e4fd65a5fb2917c7596bd639cfeb22f2e398d4f75478a752ceb4463f04a64c3124167a92b44f3cbdbbacf8d98caf066f69eac15674a0e8304876f60590b66cd75bde2dd5fd61fdbf7f7ae9995553c6ca818e4109858625a634fae6672a90cc54967d9ca092e413748cbc4df616a98aebd99142148000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381091a367c9936cc9ba4ae8f2bf71ca11255b9b1b3ec425dd2deb5e50e0e33e90b91ff6f9906e61bb42123659b2ab3d5a09e066915bd6a50de23997052f592d321adb26aa39fdf6d37b25437b441e82254b610b412cd8a303247fe8f816db98dd74defcd00298081a54a7ba135da6080581779e10ff809ed454bc488570326e8a356c2b215a43ab1c442444e5c3400f08499ff0b310f6df904ce0c41a8b8de46e4569127a03274bc6f141e5c988404509bb41e03f20253411982e290d3e3fcbdc8e435ee8c68216032401d2b666f2830e935aed601504eb2b59a13209a4a2602579eb2c553b5d18e8a4f5ae8d4ba19755868ab05f5835b25ea836b9a99bd3aee57d4782274092acda983a6be32dd7436f22429ab951e23b1c32c7f26782026ce8e8a346d17b82c3ab720c260f0dff6671254e5b21f7b6f696363e8085a38d1704b88190bb69cc010005b223a81ec041353bb25840c7810583d94244c07c9a97e8a8130d4e963a98c01dbcabb9f3b63f016db1b4a119cfc7681d3422a7c9252a70c53494312eee9b7df52504c8d7aeaa8496b5c5a7b25d35dbdd545c0b3d650396eb7c825e94976652d745ca26c7d8d64187023476d208e445550703b295479bc909116a0f5c719a64c8dea3db409e23f8f60465390adc03a491be6d4177020ba01d412d7b565bd63559e13bc98494eb7e45fdb7432064a8a50980771832ab39a27b29476b85e55031c568820bd2a9cb900df63f290cc1d043e31bc817067cd42d350db7123d542c0061c0f802a044a050a0277b5119881e121a94dab052b49f28c4576abf5653f17c0a5d45ed18d87795604bea1cf5c2999f2b29c414c3153c43c2d8c4bf216504fcdb9838e5e77a9dae22d79fc79ec4aa974fc80436743a74de1aa20c526fc477477046b50fb9745afd2f0e58a4df528a7d70953afde5146cd241ca15d58566f40f419709e54671ee098484f72cfaf8873616bc17ad64f073d776bdd2d6a8f3e5721ad2b7d82909a354cc5cbb0f49de6a5e08a22bd93441955874d5edb1b2ee30409603269f15a65ad349ae63d96fa8b502aaa74c43c84452a839cd32994bd7cfaf0af0c807de2f02d11af773888a27a88d3b3ad3b645212fd338e9ea7061fd11ef2e5d8ff5b7654fc4bc743251127597cb7ea123a03855b93fa41df289ce61093c8623da5d922a986721cc0fb32a71d3b8915803465e8fc69cd093b7f19d0240e4b5bce5ffa62ad4c410d66f2af8210f2fe85b21a1d5183e849c90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008e58337940ee74590eb25e52e78e8563a09cd2d45f650f48775e3e61f9e3509cc8eb7e983310d0185359f66bd80e0da1e45a6beb53acebb9030e310e81a576d0f80c64fce1d1fd77dca27b7c6e02b0cc26edbf496ad2e3ce8484e988e56bb28153587d7ecb02fd8882545e7bf79cc9966a7fede93f7e9451bc48fdbb481673d1c4135f95d68f40f4b4f847345a320fb4d736bf5f9fd347435462dd3a238e4c799e7cee081107e11682c7b558b19177522427f1d269fad81b565be538e8ff2d7193579aee51e50974bdc0b66331b59bf496c87e4f6e143754076db516c9c538410fb38a930cb5ba1e6610441126d01c8eb5f34e2e58424b8b218d9e68c5d8b4f5258eef07ee0aa5475a72ccf363d47d825fa524c16c7b7587c44864da9e4b267f738b87f7e5701147f550cd38774b17de48e6969a0dedf334fa67470419059c4d1607880cb12fa9c0ed23032c7e0f325169eace7daccdd4c2e5097fbba859970d7eac4522c1fea043c9278c1c89fcce95203033b4cea4f9f24b55ba6b79ef88f275310c6e48189efc1eeedab66b56b6bb028726bc463d93d742492841e85d5c837948978d0fadd1c172f8859c802c6be8394a05dada7546ee1cc5bb909d3189088f4fa6d07c573ed7263c081720e701d5d4b027ae54be175536f3bd5e91993cc040311a7d352aa26414cae30d10408ddb44e8c9513f4619e99edc894f963489876b24bb0b91bdc3ee5b78ac0d4046b2e864789c0c779e5af97f8f84f09a26ff74b8bcde66c007970830b70c2a1122dc9845905c3aa7810b40641e8bbb398a23bbef52bedabec7bb54823e64177a73786992dd67d5c007d770938402efbcb3a60281c5706920a9eee4c26c0b251c32b9e1936fdec2928110959e99255508250fd5ba84b4fb314187124072d30fbf2163d36f1480ecc08f7fb8093bfaa72f1914c63533ebb3a57420dc38dc93dd6ae4d197fab790c1efc1b7a2234522e0b408d0648c7ae782f2f08cb70b96cd76b5089af1ef4ba3a4c2faac363a4dc1c6c421f6ae1e9b67461eb02f36c25e763f1a2b73ceed4dceddce619cb313d124ce6f7ac986d6bc344e630f22cb654c1286fbc0ee01c968dadd1edad744c8bc828cf5f316336a5883166ed000ff98d6ce2ceae7d3e40bbc5714f71ba9e25e1506d644fb2de2fe190d327accca79d9b6d9db505cf1853e98f30e9ba5e568ed83e2567c936a64420c5d8f07ac4f65f38c28e88dd7b5209a600aeb81a6d2afa4faaefdafd9b7fd3ad7f49462cd577204184f9d44a45e2a909373ced24ec0ee56bf2e6675c506eda67b1e6dab75cbf1822e20e7a8a81a7729b42a6d67a1dd457fcd19b62f048ab97b3d694254e5c051fd2daf3d12ad627ec37c22117bdee9eaa290d11d56baff0de1037eba908fa03e2f869fa2b27936669306e8e70a0a4910a123f202797bf1c8fe47178bb1e8e8d7ab1c01f30f5e779b2bc99902df15185fed4c865997ab72254162d00858e0908ea95a9acd0fce72e571c7a381cc33e06a27fe6a5922775ee82c973cc3ca8a05717608f8703946c9a89854d627744da475defc1390dc44fcc3a23c47aa8af17240eb1a1a00a062d258d471f31333d0356243dc1cecfc559378b4395f01a970ea4074d5666b44d49ef291ed15930dada66765b165cb8331cfe549c38cd0672f534be60f4d9b4c125ffe747670513b5744676899b256b992e15106b99b794db3950582816612144649210751f3d0dfd5b25cd393e724f7fdef00756d0c8540e8891e592507599b06edfa6ebfe543084ac81858f5eb02d8f5eb8a72184851e8589a3ac6dfe1cdcf286723fc4c1202765fa4f783ee58c627ed494c7149bca6a4ddb420827cdca82dc42515beaf46ce9d9ed524bd00ebd3094f770b1e1dd09fc431e4c244d2305619dae208e65ef385ea92f5a79f12b99afdaea79c9d8d319944ac6cbbe3f1290ec6b87d97785e059e6871fdf239bc404021cb52064b88eb4cb3fb6a871b0f76c12d7b8c5e8fe0a65024ab5b25f4c67b6d15c22b0005b754cf7cbec898b49f4326f1ae4034e5f5a446a96ce08083d48525a3661e10c996dd22dc34fe570a4c8817d10d750fc5c2ed0c24c7cbcba5cd1b2680dbaa3315fbf2ba7457abeedc96b5d111110d4678ea5c7851d25f258926b0b028365799e940a6e17bb03cb332fbc6d713dea7108fc6268c8d33e7a578c94ff75be808c15ff7884f092c0e309f1af99b1a7314fa0f32c8d8e32b3e9d92c9c8ff6b8fbb99111529c4be3a2a4f62884373d0903180b4deabe613de5cf19415dfba7f9a46297ae2f21d7ea420b41f628fd8deba55207606539d11791623cb325f1e18c98aac27283bfab2408f4fd6cc58ec9e306643ba1c0c77d84b3930263e5a76a1ce94f3d7721f0098d54e6c990c3aff69b6a0d82c853ea2af2d3d2b3e96dad59ff873171b55d16ca9a7c68dad2e918174d264919ddcb4b9d01ce622d56c599bf60711c74315c918a7bb97b9513937afb6a652da68b6b0b34e316d7be9f5c282a5e8773c892782eff220667a6a54069c37b88eb1ce676aaecf2015e59fb7af4d30c4625dd8de4805f505e83c877cd61d2a0ba65b32b0dbdfbacfc88ca43e4ddf7a1a4517dce83b7b8acf8dcaad28284039747935865daf8dcfca29fb676ce2eba2c509cd75588fa5e58cefd0694626c9bb31c3afc372ed313c9bb3adc398e89dbdb108dda63f9380ebf9da17b378451634682f9823e209bf10e39f884ed270413152025cdbf4875c121b1e83e12c044453ffda6d8ca2c240ad522577c6898ab6f2abe1fe77f860939408cd193e605f87ff2248fa163ac2fc0f39bfc38503b23f5441e0e364caaab890073266b3b51217661f5df41c0ba925bb425ab3dd7b6a3675b7d60d0290131ead53a4eab0c66baa83f2fb77e74c3c123aba7731a3f62fab8eab2a96e8bbc911e501cd23a088e7887a469284e0b5c27b5cbc1de2b6938cf1af58a47fe78141306cb76e8f2b73620bc4549db6826d2d72873885f6c5311eb5b9462bb4631d314dfb9c836c6f4d9eec6818940c04689cc4d8d11ed9869355617861340e722b2be78197746e2759aaa8d68d1965888e89b6b0f5bf51f94e586b2cb8708f4cdb520bf31ddccfb7cb69e29a7ae8aab12c11f431de40fb9e82eb5f2b6ba1f9757f1487b63255fa69a755601c2fe17cd1892d5a6799c35d05098dc133bdd71318667d47c4671000000000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 68&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000029139e5ac2e02798e7b5741532eba7097878cd7ad2369ad29bfc8c1e7b99e17988b4718fbdc5053815c2a3db3a11a86b8cb0862cb886f615a249dd4e717c6099a6658733463f95856218c7fbbf869ad5699a8cd24ccb1a12228431b3da3ea24d81484786124ce8892ca8c667f250c7d52c8265716b3ca33dd15915c999a67a28aaa2b2fd6863ca34bda4c1508c4a97bac8f0a815b8693f98c510c73d28cb10398c4228df4f4884676f537ee6cad2948319fa44ff835f7e34afae848aa1b2449c9fd592a86c2e979d616b9bfa030e676099b316a120e7c8b8ddd9599970b053bcea4f912054dd28db7b5e691c7c6f060c5ef6a65e003a6bdc2b64cb2572d7e3d9ffc34fd25dee2ac6eab5973da718ee1bb882e0a94f48d65308905b3729cd3e83edb374b892226f86ede69c88f8cddbe251cc0faa0aae774f73c8c49f48fa4059fad2940751db946bea5adb5c92b9c2e99a3cc1143afc2fc605d847135917f2cd11c1aab17c798553db834f4ef4764f7a1a82938fd350d39005b2870243a0f5025daf60dae82f289d63e01a09aabfa14413beefa923b6aae9e18cdf0a6bd73553651d2b7cd077e5d2956a1051133c36ca165d6e330803e061981cc3395bcc20e34e5931b9a759d0a9ac14543ccabd6dcde26646bd4d220d6c63724582eb1e11f45dab63f53f5698d6daf138a42dbc7d9c625b398825cbfe1302cc494761bccb6de69943bfdc81ff27ca4bbdfdbbca100d2bcb434cadb2247f61fbd711e402e5eee0c5f3d2c69ab8c223abacaef09b6c7dac4f596bcd277513768e9bd68ac796aec253fffb35a4fdff71e9cdc3db106fb7d547d612973a4ca2d086bfa2232c9c10c6410325b092c7f685263a573da3d04116fe264486214ebd96356c8314b8d1d368ea93bad4987caf86826c8197c823034556d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109a79d8040e9e26066655962f0e74f3134bb32b063444a346c05b542e7aa950b77819b44646233f0bd0765616a7c47b1870d221e55a30346f92b347f353e525497f49bf5066df87efdd5a3782ac657fd1209515c3396a185675f4738077004d945efaebd210c50924d574dd0f8fa44ce3bb88ab1d1f021a65d1068b6c1e0f99e6504e935962c437c3f938666de1ec863172409bf4090bed8e90646602587b5f5461370cd4727a09a429850d9528412041f40c161ba43b5097d00c34501bb21728cd398d0aa08e5ead01a13a790dc091768947752e16529bd6a058c26a065549fe0ab915b023c06f412e8431849e1e7348ddc1585e03b55b50fa1888da4a5a59e367300ec7e4dbb609fa1b0424298530ba8ba480a45b5e95828013cac88239a989bc26992666142259d6e77e249467cec547592909c36061410f415ab230a33e623881a609d7733e7ed7bbe9d4fcaab864fa0a1cbb6eb63d91174c3463aefa2522906e6b75914077d3e344f89e28128f51a6f1ba1945232d33ad7c277dc35277aee95acd06600ee029229d5a7b0f3cf7ba04a17c1fc679985582a6372e2f59e52e6d235ec185f0db232a92a3da6c876328c4d6e06faaaba0a02d213e916e73f59db6df40cd1a09aa29981d7a0e760bf5e6939b7a42c7b72d27aa1eedd2972f2ad47c80ec667bae45386e07b48b94536c8d2523972e83473d8127085daebde1042166537f8bd08543bb6bd00a0af7d7a64f662b510996f78f84675e49f1466ef922b56eb18653296a24dff30aedb23e82a88a55cd478fa2425781e7b81cc5ac045aeb525e485117cd0143618529d259a8c725c1ed4202d20921125117a6836f9b80912559208975525eebfaa0a25a008827b259dc8b1104d45f922265dc0c551495c91d41ff8a09dde9463c3906f7461353c85af68ae9f8222c9c53e55ad234625bc9c5e48205d4c944191b6a9b48fe1bc0e5d50254c41b7a1ca52b7c57f0a1865602d1b30b8e2235b80a3f3811931c956e77c742c60a4c520633615b215da86d6006286e854018f7bd4b33a31c5d32a1081b02c993babc0075a6e8387bd02ca40d4aa068e8e9cc9ea8540200d25b9cda542a5f8a88779d9091bf27e579d5192b18edcc341531b24e840f830018e51de8272d0681ca3e8aa5787a7da1f70fa3b10db168a8dc6d4ef68212e010aeb7c54e1aafee6a79c9fc561ac6edb316fd34510f57aa6a5ec0ea238099225c71f4d0d61a85fc371ec13856ea74b9f68dd468d687d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090662215248e1f3afb19849f758d742f8afab595040c4dc520d603c9a80fa9cf2e97e4f4bd7350551fb667d606bdc31a45d88836cd376785c01f9007d47df95c1f4d1e30a927a13525409d91c9f5145c0b86d3b44e933ca81e4ed9559ac17940c61eb85b2d26d2c47924ab80acbaa3d9b1c8855c13ee45f5c8047c161aaa5321839a01783b21a5ee90cf91b8285c4779465b7a89de3d74d482080f68eb2d8b47429d5475356c50a92b3acbdea5786f4d6c2a304ab500490f84fd1d0f21acbea325d62d2657f3889b6f591a7f63d8633c061cb14b8266a7fe17642dedf1d08d9ffe369126cd780d9f99fc6262b5befcfef35d33498cb2cffe55f2f8d567ea8687dfc6e7d49a61fdbfe768c1d11bf5b3b18ca52225b096490c97cb9a0b3b2ca0762dcc36b60f7d26fcaa4e38b1f3a6279d889323010d9cb0a97fc488e09b06237e6eb0166465c2cbc2b9cd06f155759b6c93ca0cd3178845e0f3a2d20a68757aaf3c4e74545494462ccf28f6f51ec0fdff4f1e6d98fc5b63bff068fa7be1764bcf14497e71e424c9389c5dcf8c5ce1dcd40b82f1d75c3c3970da433a92a04de958766ac5eb3645f4d21882f7071383af8dffd6cdd91b549f143dcf59fed6674441eeb03d5013e90adccbd7e3da115535ac855dbaab7f51d70630dc00009e726a16deadb12047d85906cff315c73ee7d4e24c9067e3b772f3dcc44c25c7cb8622fdd7b8ecf5e9c877838d71d500f864a662619b1478f8ab4db2dd09a111acc99abe737ddbca06e88926c4e73b5f5d21eafc4b11938feeea5f8d5a4c616a342b54c9ce371817aa2409a55a3237be85a50f05b33d35aa86a62e85a01cf34ee7dc840a26fa1b8c6b307817c062d9a2e7163a3b036874d2abf6531a772d4031fdcd59ca79fbf442cb9155f90148dc3b723778e699c6985634185c3ffdb966adb80a3d1308150b12964142498466506bc0742783c27bd3472a5cb45021de066c28143ffbc82b5742be51e93bcfde1a61e661b730d8760e108b80c859e4b3a07d483a6a8967e5f01b03ec8b63a20c6a03755c75f419558878a5eb8bb0b2120f183e4becd4a104eb4db62cacf5f9964583815334a25bdb75724e549211699ac3bc9b2b5f58f1fb33429905df81c9422f8b84e95a7c36dec6ae9b48d4f502d8ab59b69e9d112693578d143a3f111ef00844303950f65ddeea6e30f1286de16546f90c4364a5c09755af3fecb13983c418b2fe4ac17bdda57e4d597e8bdccbfbe4082c446fc920e5145bbafc67fadd9799cd8c7714510da579516ed39b3e22de319977fc77a9ca61ae8252795d11724aaa866c1ffdbcbc1ff91af1b8713248864a4e8b9c59dd12863245f5048110dede7fe31ff9836715886c37e9642dbd6c668ba7ab8c2b706cdd58586eb7227b5768c3509c1f66493468859e275700ea38ba69064179f6036d7b50bd232b61c9b9659492894c0057dbfb80329a76cdc57b2a89bbb910483301ca0bf6aec7d5ddf86644ff52f48ff6c7cd00406cacbc09aa251708baf3276a52be2c7b42fb6a9036c318529ca98940769a67dcd532c0000afb5fc63ad2303e94e09d2cb40ccbe47faa1dd22ecf528179ad40fd4bfd43717864149243d61ca255344c52743200ed8385a7ca6cca24cf967d23d07dc2a3f9ad5f3240f4f022a6c6cd281b6c492e8d144a2f4641957ecc65b32c9f74bb468524ff58f0f3da2f5a56742896cc8f99088574264f857dc67cf04c4b63c6a08fc534229ca8ba616cd504f969ea6e3c98a517355f98a9e884062805b77623239074206e01ad2f3fc9fe9ff8254a5d3525c3b2f0a692803500c967a2e18511ef5b8845dc4b0dee9338c38c4b1b8b84ee63923250eb6f9e9c272617c7895bd538a6f34d3557812bbbfab2b8fa6eb5e95b9bce33ad3185cd90dd536a68639022c079b5ca7748864d37d45fa6780a45aa991f28bc0d3bf371ee2ff0c913cea6db38e4a278a4840ea1f255f8e83b6b6c5e260a49d727aa42095a88cb8120b51dafd764e690102f7fa07cea2eb86ac613e7be2f498f5767b622d04e8a6f272976fb058c3334cf8caad1d180e3456c210763c974e431cbc3e25ead8b9ff9243628d5b08d92cbf1d5df29a85b1a04d2999b3c669227b33610121d543cf4a978f8d9365c0ff8affa92b07fc8c8604a0f357f3c669445685b6a29898301a5afbe10ace8d64a47009c8741d7ce82e9900643900a3b92a26fe5f24886c06ae0918c3f2523c320699c799cbf72f0ddb08a0f1f63d6dc2f021c78a9d44503209190ee4be654663679cfd292292d71fc4ba6233a196ef9e95cb965852773404b2622b565bd91fca6747aaf7f4eaded7bd3bb53645381b687ae04b8d8a9bef1095eeb39a0beb4ea89badb4655a1afc7eecb7da0d670c192297cce0b31bbefebfe94c84603ba8c0b7cc73159ff59c01a037cf2c866dc40d88432cd6c2f1989351a4e41343cacf7bf2c2b395c863709d6ec1dbab2af514cc771df14df095dea8284be2b65097d8e6f72ef3936595384afc0026956e819f1657c901b92644e9d6d32d0d95549729b2cb3d5efac9c42a5f284abc3bf5cca5b08161b09d9a48ffb2996c3d4383d65b8d1f7fc3248cbe84b9c05464f4a76efa005fec342edd56959cd26cb0dae1b61b0493a4b68eb3d6335bbc280508f09d84e0c5f4ef520d92cd34d69e5bab76df5d2b72cb41a298d370ebeefcd6c1904b956458bda581efa6b3654be402ac3a971603f23f2b543c5beeda5f018543b72c146cf04680bcea31b4a238460329e2bc12f14c804fda3494c15452223d2477c9c8a497d04eaae7de09d7d7a879d3a5dba565ae1a38f15e69c18838c487c0fbad44a068c42efb7d3f5ef488f91c42f25ac564751f0efe0ece7d98bb1b3d0fc42c9756f4b8f9daf1fd0d414391155285c8daeaaf380bd07e43570f14e9a47a87bc733f1e676233f17bfb71aae464aed68487392d339ae064ae27bd57f8695f493ae56ca96c0615bda8da37133dd13c2b21da189a7329773fd8d51381bc118645440b28fa4f402ef84c4091d3a0bc4d206bdcf9007f5de9aa1e6cf7f6058ac6b69fbc703e908c4221f9065147766e48f54be4b076406e2f9ed19c1be982e636fd02dc26267c3ed989e6ad1cce62e7b988fa7c1831e5126111a4c3c29c38a1f96ccb3a04132175fa46f73c634ac6ec741b135645abf1dcea18571cf9a539f5cc935bc6d32beb1c7b8b3b5a141146ebc12dbbcc17bb4900cf0b95ebfaa52190afc6d8933cafc90000000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 69&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000029039ec14011a2e55345b10861679d7746cbfbb1c12583e3303bfbdbba2feaf805c123a3b19c23f5d9f10306cd3139c8d32bc85b9ef839ff76f90c244f23b68a19cc277dc9b95668ed6163fbafb839e618f3f0b69e675e2ed2fc1abebe061c9cde33896675e5c16c1df5bb393586f2e68d154b1743b812620ec2f3ea38283a08bd36b095a3338f4910acfb559089d96eee4e0777d75173fe7b6c42f8b72968a623ca8aa652f6e91edf4bd226094b45ea97f3f4f413d5a3ac4ed0f8e4470f7eb7a98e6268c3e49debe29969dd649f45b240d8ce7c15ae8d064827cdaab8829854a2b779d21fccd555e8502c91c93a1f95765344244d0edd3982c20a54748eb69ab4ae5280e75dedd784a8b22bcee3ef644a2ebb6794d6697172e520b142e1a8debf146923ec3c74ff555d9bce748646cdfc70eb635fdd41a6c4200ef4393f823693b3b4929879b2ed0d55714761054bc99785c8c0d3c8e70f30b74d8b0d2702ad6947d7f32135256fd135290a9a72c1471bf6ae2a3a30a419a74458f675bb2a6cf8b0fafa2a2a9ec3e9590962a6beeb8b5483138d84a628621ac267dcba0cc39686391056a487bf8c4d54a5e65bd8832f3c561002432d2664e3b12b443e5becf14d235ef7d18785c3f28d9fdd665d74d8395a3fe97aa73a9e1e54f6fd74a6f76f5867ab18525dc9f2525c1883b892afd9ed8d1b1261dbbbe8f0c2202d7cc6de830ccc00cf64d6a9c2dc8b244699af46e186616192e25ed9b2eb124dbd3c36c72510766046b7f70ee0eeab7304e6ef4faf9959624f7e3490e75d2373e3e8769a286b5e1b77c7c3a77526ca3c54804abcd5c8f4ee4b2cfeb1c824332140b822194e8b1df993b8098d2d11a37335fc76e54ec841dd13151d4b2b97141eb3b0df7af6c4d709addfa3348a8b9f28eedaf6ce7ef500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003810961caff0b7a0e20b8deb09b7ce1c626c89d7689d5a910bdb791865a7d11455584ace6fa4c7415d79f467c674dea7846a73559d8decb49aa897da5186264d4e235a629a1792b5e07556be013ca214551c5763680153c6e9ff71225a747d9b5f0676b2a32d1526afc6f21197ccf003359040882ea8202ad28630d39918621a278a151d05d65de8bb0e78552d82357e08934510c43554d2da85944e02d6a6813a1d7b605a53e496f1ec03cfa0ee20ae567bc4862486fe4864b98aa33fede4da4a2a747381427abf57b9a56214d5ed5fba4ef47654969e9635acc96adea4834bb5162af29d6784e8d173c6ebdd54268619b22436800ab1637b5fa41134e2052a1eda601a251962068c9b4191e2c0000833981702745fd58682168537153a2d0a0789d99ee3891ec0a45e2b179f54250992a3441b411871a0287b0daa4858b66b52712191678fa23d98665bb5c9512b28a1c3c96f6966089227db7e96e0bdf8abf6ae06d98d60e9f4901f53a36518046bc5485bb9700b3515ad35995f149bdc873ffc781a4caa7659aa582bc565c9ba8c1f9403cf727e255219854a8ab0d69ff239c8f609960ff6e58ed152863c580a08b6b8969f0012443416382274162b821b8caa5a24567e441207a1ee6c0a166ae377a60dd972e827b2b40379891a656938e5fc4abec5e8c69f719a44d243002e09b8cecb7290ee976aaa2200fb256f12eeddd7e0415eb365e613e240eb4660df067910d9b0d536e415ede269b200f4c1ea0ca170db83cc9af01f15eafb0b986f4ad195706edf6a07e51a0ab306b178725b7be392556e804180b72bb3ae987295e15be511614db45a006f785d06159684a53f854b6026c04c1ea55b5672181c3b106a94cca67b88185cfb76cdae407261a5dc862c0adacf5618efb221618af1c8c8d459d89a87b72602b71a42757bc25da112eb79ffae8365b41c4249d75aa138fce33201e8720a72f680e08d872a5609a3d4598d711aa6a1824097f9be821408653ba88393b064ef45be48f568933e0b10f66986a2530d48707b875162a0f9d954562804b2aebf87890cb61f68d9e3b515c29c26d8ab3ec21882a638b32508d46641b2a87224c620b0ce353560c12ef95837c74a0d3b8141e0f8a3f198b5a58859d19a2384f9ab459bc4bb50626b502b008a1807d110a8ceaa4ec63510df592bfec149c38b1e4a295799e38a070e387da5a8c4229b84f446f04ead911dd7538edeaa85220c27ee12899d7eb085c6ea450408b4a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000927954511394b9d10e1ba162861802a717e24ee42a346c9ed280c88e267a41ec09d6d73b6076e7e30257bf265b71a0b6e0cf408f02ba9078811be94d0f38559e9985463fc9671d182286cc4f18cabcaee1a3e5abdbc384fb27911168b54a387171c0524489fdf512e4d8d2f65050cfe7405d8df63a79c6e42a76f4538907eff4dc5870095241523f56fe8e389ebf1a1cc47ddb9f0188513d5259be257bda5be7381f22392cdc2406e0f2448a80f3824f2670f61920c667499de899f0f6b397381a2de66255e061ab92cd864de75c9db7cbab9fe76ac38e0ab3389530b4004055268b289b40d79b32e5ebcc74353510bd1627e2d5dd0be7d3dfd04138f6e3ee7526133dc70490612eaa5024be6fbefab24e1e83d8941a113d8b871f3dbc3011869174888cb7a265d7de9ab99b999c19af9b442ebdc904fedab52cf40b787aab35626417c5291f2eb892f43e698a8c65cbb6442a4832f33920fb2dbfc50b8e996fb227f2ff294c385a330957d2fada9f86839235ea79ecde6d9d94fbe7c79a38d40b9a8f241f53b921107ff1c72624c9600ec04dfa1160f1fa9e5d986a5a363e9ce8627276da73f5db47e4b90328884cfe93194cffa6fa680f77886e4a7a0fdaf13a7ddff6984b8855e1f58235babfd5106338fe2b075d4f10a9fb3d3c5f829b7c61b02b34e9bde6e62cbcc3ac9f467a6ca170eb43e632ebdbf6847f781e2469b4740fdb83da34ce34a286e3b363a72cbb13eb66ce1de35d8fd77dbedbf45c44dcd16e6b58a1699694d9006947c8c20810e85e3ebf8fb2c68b967743642d86556ab6958e545ab83ec24b96f2b4bb99cc8890c3c1e0fecce26ce09b6d99000694f870af9f642374ff0bbf61efc7cd5aaf5667fc3fe5745dfaf7f13fed70fe070ea4c09cb1a92d8b7f0dfd4b4a4b7dcf4ca6a97043bcef6346f1570f37b0eb48db8d15c8a82ed69b0c7833d6c830414c111c987471e84d2ceb5bd973dca34acd3a65d7b1a502368941935435b78b8f2b74c2bef127d96651247bdbe68eb7e466b9ea2a64a13c375103d7c8f7d30a13cbe184bd1ebb19f3274e645f5c7b82efdf09233d8ad146dc0715266963fd3cce6f8cdec20743bf1b7f57c101ac24c64d568923203e1a6af03a700f5a401ec4572bba528e284c151f1d108f7563858011fab32b3776cf2b910d7b21180dbe75742032791018258f4d1407c9a213755c5c91205352df919b6f14be056243df6ac2909e52c9a79f6917440667719185f1c5f1aaf40d873ba22956fa0bbad9c35360853333a10a0841d9d2e758a0b1bc187f6bbd31c41b74f9eeef1f7a28bdb7ac3d52fdc6fcb3ef0383a06a61188548963e552716d2bfbd6c2dcde496d06615e86a5cdb76a03bca2822aba85ec6807ebb6918ad2948d193ccf74f4bdaf7090cd4294c1785dcedb6b55886a848284a6a4a88a496800053e84a9f2dbf6b334aace11a5a540626716302e259a64c6316ed543806b3bbfe37563897e83bbefa570312df908c1786df0fcf55069edc336501a5ae9d4bf212d56a9cee811038656912238ae284575ef8de1285b763ae54adf44f91b6dd9e309b7a7a0ab71ec2e4611831b3ce1c9dc85cf907b52df7406b06367e7a43dece72dccc57d268820ea021c27056e3c6b50e7ba7a59b53539a6b7b06b35051e3151c23f3bd3c889b25d0ece1fd0df1aedf657fbb096ca1c861acb0158501ea1aefbf6dad11bdc325ac1ced3739a40b7a83458ef4f3453c0f6eabc1a48037809a90480df9dc4ff07daddc58df2733d49a4fa53c2a41e55a4a0167c6d33ba6e752aed3a125dfd6a0322cd235254505d7b3ced7a0dee7eb662acfd30f8b79d1a872998cbcf15cd86e26809e0d2da0324ddc90fd12caf9d8e4eda437fe4e658d47d67c95927c4b5dee965b940ce93e6743917296e10820a7101f8f633c93069e8b569f4625afd4ec61bfe4549fdd06c2290a91ac0fb40cb1f55dc8bc1fe695c73af603840ac0351f5256e00555c984e79a09e58c566d1a117b7e569beb5850fb491fd9b982442b55bdf53832aa65180dcddc2f768b1a1361994de8c25f3608ec853d5982e0afd1f9fa70170fc3589ddaf958dd840b4b502f8e2697d01ad7ac2233f6a16d540ef8d232887d2b4fa727ae2f038a69af3dae69eda8ef6bf1e0b67d811160b75231543ec5a4d0778b7b42fc1dd6732385aa4400450b3caeefdffcf147635cfa4aaa53de4ee3035bc40ce8670016384bb877a86a15b59f3df0c5d624d3d2b23ec46913618c745330a96c715c6f0bd096487e89b917384cc30b3d20a332f1b4056462227e98af9874ff1d18df2a6bf84ae822ee737f9e34ee8c69f23eeb9bf38ed056f499545f405759355c104284a6d08a9efad8fe28288b2084336a6479a6d42404f3e6ff3ad1dfc63c8aae971af11f2699f32f57ad29188492ce07bc1a271035b4d13a686efde5572353283a0f3138f6dc05cc35e5e5057c5c8b9e12b0164c0915adedf40a6e23848fa59adc0e65bdd2120486942f232315fc94b4676751a35aaed2828889864c4cb7dd95a662a475733c2ca8f6997a9c822c6c8b9dc95a8b4c367e613e97d3ec6d6ddc2f81022ec21b3a93244e3bc8c2737a7724a3cbd480b26819eeb2676fd383601d79fa266ed3f9bac2a98ff0109ad7e43e33e108d88c09ba82afcccfe98f50f789109d99dcd0a2c61947544f3666edc621b5d5ecb7088b2430a611bea52be7f5edfc6e2649f5e81f6df72fa9a748bff06af766a60d2b751b23a8aa95cbf733359f7c0cd19b1482a6e6572d1570349c688d78cf8b8c7dd37576dc47a193a2c2797d0af7504dee303823a8b77204ae7b6e91d431979798a7edf435056251d0e3f26b2ca16bfe3422cea0398d30f0a0dc06dc8a93d27d13650e5bfb6ba04c93faf0d7d06f99fe4f1f52a059fbe808179515fda48eca714f0947fe9a98f02d66fb0d80952411cdfceaef6aba16d92b8f1b82db151d7dcd7fb7781ec55f4a86c86011fbb9c5570ee76897e7803036e2fe3cdc2d5ea7a613897f3c69a6ea734e3811bfd15e90d7256a0c0c88ceb54ec6aac151b435cd2a870e4a02087c2b847c75b00b44bb3ca6d4404c3052bd308b8d5f595277592d26f6d5a2193cd4d650bf931fefb9deee61032b29ec0412f38e1cbe025b2891c59574c1450d9e3d8ef27940ef712143f06f38ddb86341a7fc781e0fa8971dad13aa7e93f1858c70a71a40164211ea9f6a41ae90d19032c2ea52c23375ce3c4e59599ecd6855213aea83f8dfc5cc70f58a62e4dca17c09705c0c099b29056592986c03cf5d67074735f2bea00000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 70&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028e39fc01f3f7988ec8690f097a68e3fcf37caaeeeb35686bc258d98bf475e64b4caaa8fe2aae0ff6c828045be9862a0ff05a1039646dae4550e5eb6fa0a8ccebc94b4c4f5283d9248155307ad7397cb76d7278d54929e373e6fe74ee4ec23509671e34a7edd142f38719acafef4d287671ec7bb94dda64b63d04fb1abccc161abb4684a65a5272e2d1917685a4600f56d303f4e623080a0b39cbcdb30d4e79ad86c90d0c030994b55ef5486f01e4b7ca3518ce1364bfc6b0d4f89bd49d2b78153206da3533d20cc42a8f02ef63cff4ed269eb53b83f73c19d5f58e1424790425f0cf82609fb0d99f6a26b2a06dafb102dfa02614ce7c65c59ace445418b27ed25d21dade092fa8dd22292e0a4dac9f4ef471d7ada1ba60fc8e020b54342e746cb4fb8db2b7c0dba41d6aa25917cf2e234368a4711904f93d6a4953d893912c3a43e483c0345d764d1dd8a48ef49c78e634b52639abf0aebd9f455519739b841e111db672056a35148522d29c947e730b85a272dd6528c2fa5406605429af7e00de994eae639db695f9d8fc7c39810f2c1fe1aae5547c72d6e38bbd2416ce2d8e29ede9bee852aa80b1062fc848fad2583afb1661ada6f5a221aaa3f1f28b306cf60af5d3d093b4ef9693914167e6a0f608a88c9f2d6bd13deca52c711a8e6814bf25874e8959675a3c442ef954d24c930b1ccbb126ff454b4125753b9173e096669764e24ee35aba4a3cc38f5ae7bc3b32eef4bbf9321d33f1b1a65eaa599c04cddccddab4d94827058f5a35bb9a7297c24ae6b33ad781562b50e382889984138d27ca9b28c25b8242974c6616a88eee3888b795d8f15ae126af7c4de34bbaa35c4b63385cb1dded43228c8ce8982097ab163bcf6080b91b3dd43d3c64f833e4dec1caa6e75d12d45735ac836ee540000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109ae9aef7425cc0395ec49206f4fccbbfaab89d24ab6b796bb906e43db6446b5db4aad6621f2c2b588d28613c9c7b0a9a85e5065e7f988dc48133a6e5027cf74974c421aa38e74946c1f6b0dde8696056119340d6a6cd19b42d9cccd89ea9eb500ef2b9536bbf78382cf7cb10ad34120281c8cf39917489b26be83b5770f3a0095b98aeb8cc2b87ee9f9a820479688c1708bee4a47c98ca00beb75b29823146e42b91926e9db7e2eb41df239aa04de4fbea9f64491aedc53c1a3941b4222bf1ea13619483d637d9c610c135cba3c1f86aaec146b85c9b5255d84b595cb3bcd65366aead7531463918d2608c2fa410393f6ebc21ce92c100db108dd80c34d36d8e934e45105be9b84b214c70ff00d88df8e98b898c366c1685f92f9ac29af603d1f3d13b3074b748c8d4247e9e868b42af52b4269da4b510df9fd66b83fc4ac713fab1897411c15a30dd6ab361dc44d16254849f420996c5986ce0644e70120acedaff77b2fd29aa2857730c62e9a3494e001a4b38b0e89fac0dea54615fe4613da7b104879a4a74e807daa851b01231c86014070918c2834800094de93866a69ac98761586bb90d05b0f6aec39f092433853c2363275851e8f221d2e2de0f794694c1545ab6f49aaa4f838104fdda0b8942ea5051ab89de8b4c24412e74d1923a40bcf4870b9ea94f8aa5d9c94122a88894643b65008988ef18b485dd341a0c48f6c5809e6485c12defed3c31b7e1f11e55261ed3ebf280c965e52fe59c5c0b0b701ac63c67a2379dad855d58c31c8cbaf9ee603425341f5387913854a0d440194bd743b5bcc43ea97e4b29def3df46485a168f26dec703378e82498e00c468c24c51ded2cf5a0666d59a9a0b3482573ac1828aa1b644d2fb800bbef838e385a65cb4955f5a44a19e650c3ca5ae9ee76b8c45746c82403fca210938a8918f7947d4eb198c9ca8a549c8142c7efc300416583801049d12e1a67c7a0afd96ebc7f806dd82d193c23f73862f231f2e8508905afbb504196668e2ba09c9b76b2904f264d0301118adc57ec7a79a2ec81374c3888c6c5514f9d53e32fae4a34b1d46052965e5890148043a2abbd265278945ca72816f7eb66840f7e026d0b53ec4039b9bc57356af474e9bf89ca0fe26a45e7459deb2045818d7601d7861866a225ed58e97f40f76446cecb85fd5a670a4b780445fcf64b8cc037a23da037eacd5dc485f2d9e1663f7272550401d6141836b0d0d83c5c253cab06152b8484abdbde837f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000948326a4fe723be9363acfc000705a10b6cd8a7b25e99a34b4a354cbd6f50550bed30f6c4208490b4194ab79b24b093fbe132c299df924f2ffcc2cdc6c2c9019eedf4b72d7f0817825bd787135927102e1da041e9a78b501b42dce777a79ace604e57df11775d7b87e75e5b00adac90d1add78cc5ad348c7472eec6e6e06f737e77115a9509a6ae6570f738dc2f21314a7ccb9d44add6e1434cdfe3614bc73a6b468f6691b60f4f2db103289a90c4fb2bf5aaf87826d2beb0880fa64e07e9bd30d4eda00d6bda01d1eb22bcf14ee797a859c9a0d9034e8c5316201af91388c47e1ddf061c9f45e067a5f60b355c98f8734559b8f1b82f47bd9cee0224a1d67d40706333523c34f3582b6c8cb47bf7d0e4fbc7d7cf3dbf21077e664fd59998338f4dd4a423c3a145ee1e994aacc1a48f81a7e9fe106008db93a6626b8c8505043ab864d93ae3972675e69c3825304086aa3419216ccae7f7d5117739e99d8f4a0b658148de33fdaaeb9967ef56677d2028c3b584c5cc1c096f4da16799408b2ee2fc3482ad2f49293cf4097a78492470099bdb90bcb4fe3b245ac8b3c53e05d7609e34770adcc147033a8fade81359ff63c3fb90c5a498c98b7a0e5ee9cf4d287759acda4bfa3965ca85e1d1c1019e7fe6d82e5e66a717f94890277e6db1eaa6f3291fe1bcd7d437094749ff5574b8728e0dc21a143a14e382937efb7ec1b0fb3f6f9c0f547f470e3b436dfc7986f923beaa89583d8978c433e0cb0c4e98516af1ac797c778662455a57fef45ba2c7865c1df5c502edb01c8cc729468091bb96be9da9c298528187867eee9a06141daa15f60cf719de2bd15010550b92a41f12d8f38b54692589aff51a9d5e6047a0d9b707369992251df31341a45b01b05ffed8adee5810824f903ea59f14fd500aedae797f8baeb470c0b14c4eda5c687e4848a85b30a8e8f59c45d4c9f0c65fccb15f4d4209a55722c29b6cb09aecb4e53fa3aa602c56ee3ba6900cc12889e7b87d5ef283af1586764519a30cf60833c82f0ed15e39a8bcad5c6aee9999e63d399c5cea10ae1f53b04858ef7896aa29fa541451fdb685734c39470250545193caf26c9891f7f965904ae10e8566bff9b2f465bbe13d6ea4a79586e68844b9fa68b2f992565c8b0ef5ffdeb5878cc12a0571ca3aea50add29dd06e13741a1ab215bf487be7735d1634332f47e037253054a21e0ad8d8f011334cb5951f833d4d344d632bcab7c373cb7dafe8f3d79e7e13bdb1c6cffa474a9fbb46f5736d55f3466534596ebd22b29107a8fa50c1d0e62f0533e343fee038fc0c3040a6df2d318bbc8420019b1b148d6d1dd2fe428c2fd617ca73f224ef9af9bf6f83cf1006616235471b69dd4eaf9f32529ef3e1dfe6765e61e246b519c702351c9cd66c57065ec78993d793b082e3685eb06f2530b07862277d339a52813c99ebe16c06c4c8f547d9705850e770982e8fa0275a52f430ff2422a115ece46a9202caa0195789532b1444f1507aab2e4303464e499989f21c7d881328f18dbc77d4b9b467cae244a93053c0321dfbf815da28b6ebf483eafbe634e9947bb5383fee3a31bc03a63fcdda5e3e46d5d3184718c348a83975728714351df43baf91787caca346dbb819602f18a4c4fe90c4ce307984bcded89cd2e4aeb66318c10d95afa5be53393feb981c21bb1411bb9c58818bcc141223d66ed5f35f90c05fd4848617220dd72f5e892292ce20aa9a0f9ad54022cbe94d2c86daf3fc66949ac35d8e122b02e2d155e73f4ce24d7e85a5c301dcc173ca8ec090af9dc7f443c983280dda27ed4b9bc71f86e84f7aee39e6a7e9bf5e43920aac858f0f49a06216d9d3984cd2e3575c0fa6ce8a5e28b0f481ccbaab450fabce8a1084ef458dbe257cf09d8116136c2cf1edfa6cce31aed0f1f8278c1c8d9c79846886d48e3fd311c015bf2373f7caa71aa26b011d0df5a843ab53d7e7f0466ccf49c5d4de872ca87b8895101ee0147a3dbd391beed75fc16f65814d56cb29273a5f4e5400fcabf85040505c31d001df0023726e9c1f7c29a37039fdda73b9b99acec3a029f7c0dd61ade7d5e835e1cd605aa8e583bf8dc99285e86cf91f4b4827a0e8956efde2b495a86f85e78b954341cf3afebe8db71c26b9b1ba27b47284aa84e55b1c2afee733ac596a10186d9ab504f33e34a06ca931d7633462b04b9b2b0d4751b0343503bcb2a1893d944fbdb4be63de167348a1588e6551fd9cf2101b0b4cb61422655fbeb50d64cb9e87a23007a39821ec3aba391485347624efc3dfda4a133c537d7cd8c3a549bb6bef9a52d2edf0a8892c6fc3eec3efc3c18741c85bf24cd3b36ca04ee77f654ed5595a0e4b9316ccfe4d2aa6b4a66b06f309337e363c9e39829c8838729f19811093dfbe962246473b7a19faedfdb0193f63eb85ef308cd3be5831f35ced36d9448d0ea8306044f78946079210cf89ff78104bcb2964ce2af9954d53885d7914e4ffa4ac7e9b3d103922fd1ad68c0a4592f885c5fee51d52214e17035e8681086203b79b5eb176679eb3263b44ea7287262dd84bb98f6639b9657ac04e397d69c634a0c1181eca485e467d62631ad2d9afd5ac5b86ed4005fdbb7404b65bbb826f1a2334a481b9cd46e0ce9c414a162e84368089f24149d7d05ea6adf40b25a708357aaa5a28801ff100f69252810188cfc6087507bb5bde1cd43bf72b1b3207ce4f7e65a18e5276613d4beddaf21af7b964ff69965c47cb03846f7ceddd2c5133080fc632a4f0b3495b2d2751727cf7681f28675552df2a0994e425a922bbfcf84189b8c9f43058d691db3166c596f6bc480efde06bdae7b9c2985a1f2f6441520620e193d7b94ab46dba2a1ade44e2b006734e6770f34b0e2122dd7f4eaf045164dea8c2fece7758630384c00a6b528a6ecf07045b2dc0281c936a540904733149bc65b0f57acd9a5e41c2adf83fd6a760b169beebf04644db1314270adf86d01cc2cd580c609e78bbcd9d2694a89f9cb6dd36b9aa2aa5581ff561b5417be2b52f3ef2581e461cb0690782f33862c52590643bece0a6141dc805d8f56c4f64c1bbc49a3ecf1e8827926796e5f9335df47da6d3e4c14795b547116fd1f3351fc55c28b543183fead8df7da4dfbcc38e224901ff7bd83b16631064cac4a37fa632f53f004374aa19861fdca515af91e66186ef804366d5a1b3b4faaa60a0c4b36b972a9579548b4cdace7eb85f1f68a4e4255fd994c1786975e7f6f0ba87d0295de72876bce37146a09edebc0164b9c4911ce41ef4d48130a27651bd0dc315fd622cb6d03759d35756806332658b5b33e768860c1946569aa45130486ad49b000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 71&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028d39be9b5af60dfa7ab0c6db2abbc5e2cdb5c27ff330b9039f6d8dcfc936e3491b3deb00466c5672e96293298ff43b16698c36bae260b0936eac6880c9f2edf5210b9250f105699568b65536ea66ec39d5992c49432a50a15e7794658d3dc54897af833cfff99266460566e52b7f4f841d07beb3ccde37ceff5de388de512c64db665b5284e93319072997204b24265cd57a1512ba5d13e43bcdf18d3ac901248c3f95b61125c91a295d9ef16dc227525691ec63a2c6311e757ceb3bf8b13f33032734556b28ce810dd3a6990a86e1249643507e6e9dc7ec6aebf0ba5d9e639fe508820f23739cdadb65ce88094f6390d7cf5ebf35ddcdd8a0d6693c238340b86a7d4d19aae1b4287997b03e6a1fd23ce66e3f3bab8349708131bbc303781194baaccf62137d464172fc575f99218dbf5865f609bad59a45944583d3c3b14b5b03edf5c6618ae1df8674e6fb24fe12e02c5d7ef4aa28964f572b8e24a26f4e172f25c7aa2b7106dad8a2c566782d6467193433ec71bed82c9c3ab70a3126af48566c1c2b1ce56b20aeda68aca7abceb7412047e1eaebde85df2ca976e6533be5e258e43cf6ae983ada3df0bffa747fa4db3fa590cd726c5761db5be64cb3f98f949cb6605773ca216b2a93e63e8f2bdb4c7c5b255d8e80d8f70652d99fdb3b6edbfd7de8905201843033a23d1a8750169e767fa2a7f4ff0bb4f1b76d760e857d2345cecd6de2821d2441c0aa6c8a54b33f858d22c6358e28c80929c647e1ff0e3c410f4153fa46b2795b524bf73d13abfff1e90239d78c2546550840443ca1e090d3f4f5c453b2a5704c76374f4e291fce1294833359da2caae625c4b9d10d8ed2a1b47779ba8adfd9ec94a6ec28a1d56c301ad7fd4a6cf8fb8bb49e5cd8a95faca199ec916c339198eaf12cbf48000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381093e9e3148ef94ec01aa6347e5e3441e62ec57c3634a1ba081212b27872740d1f61dd7424d3e356349d8439785dbe8fa11da6d61fb49aa52e54f0d88e99be86a69dedc256c11d617a9d91719e98759a07911180c333a3287fb52eaa3862986d6659e155a9a08329168b73cd02c96f98876a95a03643eddc75ff299a99d95ed2739cd0a980a3c1b7ec3cbcc8b6b82882a9aa9c63e5acc93b465d70e939c0171b045273f0c7a54709d1327141d352b2f76b9494276bb5bd79f2664eba7ebb974d5a858a108e457ca32322d0d5d5a154b49a18e7ea9b21ea34a2478b2142d04a9642a146285b56796d597a04c418b2d8ebb1c06c514a2a54b3a2e39c4e9878d1d9ad17ded801e80afba65e80a227196945c135504649d057d042e886c0c029713ed503da057d6a8aebd29566a51ab4f7de666f96f8a8d0d4aba313feb9846f13481e9567eaa41d050b465f781690f695a456050b47507a7deb7117e97595d812e7284851615a323247954d3714b83652098180b4aeeae01d055a7e83b542456190d950557898a59f444bd86f91db1f855c4a21cf86241090d62b9bf28e743a6aade85f484c3b464e6e90b43d6e75b30c6c3b74994498d40a683db05218ca6d1ae681d346d2045062d2098a444a16506c1a18274c9c3d82a6738d9e02551f37fa60be5c3aad620d862605e401f66161cfae08a61b22a1ad57c9b040879b0c580cce574a6f420d356275f368f867dd7d9a7e54f3428233a11ea3b37df205ea7ed636ac5c7cc7fb500d98683f37d7afee580654d9654cf51d6956fb4119e2642a5a2a94c6218eba6b4139cdb9a64eb2425d8bff3039cb9a4ce3029d8ad7a641a42a6651df498b0400aed0ea5895d0eb6e002559bc23280f00e864118f534368d22ad7abd369f9678b044eb4156432346fabed328e5c5aad06a792c4b8b5b85256b24dee75e19c160d197e8a9a99723eb638eb18e12309664ec189030b7f99fee34a000d454a5bca16e07908842e5091e4790d14aba30e9be3a57c22204ed0f67f95f7a6bbe9375c920dc28a112aa7e0e4e955937ab1655307f014d07cdd7c3a8fdd9b5622ddb9ead17131f9ca46bfa35b4802fab25d1de65fe476736fc0b1908898b35260cf598a8748b85f2237f85dc0cc86c14c45abf9be826e6541e8e5916b4d5375c870a6e1cb807a857bb62abe429ced65acd099a76d7c38d7cfeeb19aae095f00006608e942c6ed5912a691d685a13d6625fad387aa6d5f852c4856c973a40859f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000969efc63dd588a7230ce08efcfeea534f5a0eb005480ad1d169c386e476715238526e936fea7136e2d8aed60de31cc91dae4e764ce5f93624fa7f72b87562fb6ad8996b5e41fd478af0af8338a7fd9aa250efd2f2d20364e8a88a8642e8e38f38583abf8d3be97f14c3ede66ebf8ebc84385cae646cded8c5ce8f06910ba7fec05d828446d558d6fed766fba347da2e84da247c34266aa31c328804f4e3aaf6acbb0ad50feeccec00d20b3610785b9f1ba06a0badfb42a8f43de3f7bac36057ee0b4d2a15db040a8903f767f7352995c8fc3e06ed1b1322587eee5b31806192e04b09a7b433d08cb2a340942cb75c51e0f8409f907f69c5f8dc316a227942edf7a458974fda76c255ff4f1a85a352cd2cd2a21507e0f37451060d31d0847528b3ed5da3e7168cbd0302f1b03842e63b3dec6fb37357e37fc3cc26721f290726a47ab3d4dd8fd1778fe5133726c240e7b3e398f3d809c6c469680b9efd25dbe890d6936b76a52f97aef3f93872b76506a95685eecdcbce203400d182252471b99b7f4c6ced4cac8faca7682d0df07bc5904aae042479855098cbc41534f0ef17f38f1bc8c272cf72c1ac4a5564dd132130ee676e7d7ec3cabb4e85ac81945c87de08ec60ced3fa0ab3e83c18ae493a851434bfa2c4968b42acccf3609539c62a4e01f8bc159362e15ee91d8aa399d8bd8d67ba1e8fd646eebb4583812293406b05ba5be2b1df9620e6fe3daf8cebd9652bb04494b899f407c7d9ed1c4e77ffade24abe56ad597bd438928e05b0363d6d2685d34d6b51d71012844415c46f13181b146a3af25ae4e8853cc7c7ef6387306c45180a6ef9e97abe1e7d5e10115752c3071b6a213367e8b1a3d1c3703cc1840735315623901d772c61d55ef8c47db10f0eb7582d7a043018dc1363e93f315dd984b8002ea7bf5bed38d3f273276ca577cf99a635cb6ed9d6525520793405be27c86e6effeabb1e5f84a0076bd151cafc59853424de4b3460c673b0820d76e15ee47b6505d2d5c179db92a44042f3631c646d350ea9721b8984660a76018dca5c6bb1223cd03cc844dc9371d32549d9d645f75d2683fdad1df6434bbe43200e506ed2a815fab511172c70f99a85fa3970433e8955b2f9389f23c10141b5779a23b8671eae8b91991b78f635fbe8e627d3e79d91fd1e6e90699640ba3ae8d7e4cf5145f1259cc76ae50b1fa150d8338a9450a5b6b90eec9c94318bc78c9c7715a3eb215aee6443540d211a0556813529023e5a581623cd6d19bef0705a5f69aad4833a57c308144e92899ac5683147cdbd279d5c3a55bbc5e8f8e26a158a3e42f8c5b858909b024b4ba4069e26de66460ff4a7dc92bd54ac244007b6ac6ce07a31a2af3323cb55f07b8f480d279308fe10f2ddb001da6c4aa132b988ad03fb63e0eb06544571f5505cf377a81153d6fbd4fa2b7562074cfaf587ccf28dac84afa58809c0b296e0d2594d3582c28596f5af7500e143be7b49c63d04f49bbfbdf60b024daba5533f945ba90659758e06984921efeef79604059eb808c9fe1bf9bc5351a406fbba7f5d8fc9f891488e537db14b216a0535c9ff7bf8d5c68a2453a8a48e58fa7bf6eb76448d6d0bd05bd4628c4b852a236a11bec0f67118f1267ca42647f6f2303509094c9a7f3a07b2724abd2d9b56b71fa7ac6cdde456ec209be76c419855a5151ec9ebf0e0cf1b86f4e8e81b8173960f8d1c8affed1ac7b818af8e3bc092e2b209d693e80b11ec7da39ca93223e1b47c6127e8ad40a78bdb0ecbfa1f39c84cb9ecdf960abb39884627bc4105c53ee7bca4802b92af60241420cbb36c407f46cc2e953d7e3503cc82287a8d68d0e673e212173d80a12257add5256652188c00590dadcfb7dbb6b35507b853ea5fad4f52e02230cb3d3bbdfc43eb74780583e8dbb851e0257117f4a39a6676586216220c1ca21de16cdfe6e1cc99ea7c989916ad2fed4a8373cfcff02207529bffcb7b7601317450bf430bac9ce111b0fba8d7de6627f863078d8e6286b2d34856426ea90ffd58705444d0dc12d4feead0ffe543811e1ef306f40939922563832d06e6dea7109087ac051a361ea9e755856fd4e51388bc7c40c63e0953c8413ab0cbff70c466e15de5b089d095e8ee8a64e929d26ca3b71ef0b2360aecdfa89284cce08c666f4e0146362f0bb84b87a49fcf2324ebb96dd941f00e2586f7246436eb66b1e04af84482d8ecd2bc8ef9955cbec62afdd754a7f235c7f3c41cd0b36a9024d426b7388d3c33a5a6e858846c0fb0d88ba5798c923f9b43d14a6661c65092d5c5ec0f97d84784fa336ae6ef57c7a5d04804b96d19849ff9074724a5faca538e32c6efaa5209317543159272ce50454fe1e7d068c8f5ff3797a66d5f87758627ab5d40ebe1fb7ce9d69287ae7a5f349a5daabd8a8e7778baa26da0eb237034a3366448280237a165cbb303be6b33c0f11c1e56c50a84384a0f6878f2a99b14cd3b6820abd27d2011e0c37f8439bede65747038a5ff7f00daeda094331523cdb7e10f1063b64a584d3e9f0655268f89dbef3ea3fa4c6e54feebf8f0046c6c811f0767cf6fcc9b3497db05582774047a8dcff6a0c1b5188076e64a9d5693195075f2a05e507a5a523eee4537079f9e5e79210e4af056d6624d45a0eba553ca9bc92171451970102cab57dcd89acebbd7025008325c61145264f42e4d14a76e5c2f1c129d4c054da00501081617d1a27012a6e160750dba73becb5dc05105bfde1f1d0cdc837355844b291b09015fd610628513c1c86ead373730b99fcd4a552fba07163ce9cf6a3d3ac0525593f0648256e8b33fbcf92af58ce26d0f036e11230879dbb789507bceefd2960ea320236a224ea74dd2aaac541664fa3ea9430d4fb09c878169a8af1e7fd4be5e7926cb0b6a352b25f452454474107286edaa145c0a0573361522eacb618dd9c8b32bd1a8a5923f4c698cca0139dc640c1d5d557ce889bb69ce32d85853dfbb0f34da2cf18cc79472906b67f6bacbf287f31de0b9e7a01a356ec9b64653cb922501ea1eda940089ba0f293b667f482e92438805cd6851776cea0920cdefc4062c9b4e51f5aa1d7ff909cc2608b6f28ccf28d574bf67ce80d4ddcce28f2ade0162cb66894b5b2da0eb975cd95ee7fe72fda2736616c8b571fac94bf8c64acd1642d9431118f08a62328d99b2b9d90bbc915db764c4935951a59c369c72060cd9f4273bdca0c295294008c0ac3a149e8ca5e8bf21042f5f21c067147f3bb52b13975026a9df7246afb1d053670982ab316509f2850342913e1322758ed89da02dd79126726b1c5566c1831ccb1d62b3e271875e62cde0df0715d404f95f580b63923f362d416f83fe5ad98eed584717fbc2cb7d1b00101200f4eb4ca50000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 72&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028e39f0c7a03f3be72e73dbaeab0a54ade85140fe7754943a2721f0202a0c278cb34174408aadd077a2ab3289f1a6081a4dd54bd906490059740e03a35154103702a2851ba52a24d888bf01c2e3e2733a481ab6d2eb644c191d776db6ae1d4789a0c3bbb94b360585d5fb7ace6cea2e83bd5afb37a35abd4e20c2b2cd216a5eb1d3395f6cbadaccab732fe1365189ccd531caa3d00eaa053487c2e76e7984c8c9bed32cd3e4c56a1daac5c738d4bfbc8dde60dae08a3bf0f4775abafa8f9681a8adf84ab444752520c6c9e650bdb46cfc8d8e9234bedc25907e63c4d2749c67a272ab64c65d8a87dacd879587377d6f5ce20fd63049c672244ece2da79a2fb257f36f87821cc4b160d2af9b2265ebc6aacfba8cb74e2ca9bb61b95094f9a68d8785dfaf4aa373e59078b8eef9ad369d1d0611f88aed228cd38cfb6712060f5682aaef8eae5bceb8f2e2dc6d0cc63f039f4d3730753f75a29e33e6be5093a71952105622731629b8ef66a3dfff16151d2c9fe72578321bd779c38ab29c5620c7a01ecd2cbdc77f6afc163a47eee2ea53aa274c93b7bd3f8a2ca8ad6e0b76fb9b3995766a56eb10080b099fd2b5a4274b2e90d6226bd28f3e59e179a4e7eab3f2737a040d8afaa1ae1b274b313d236fd7a5247d28169d146524aac66e2f7cd12970932cc1189cba22a26e4fe171f55198067f2a53a37a3e7e41926d32bce5de688679fd8cd33f36fcc69b92048f589ffb929b8892cf33f17fcbccb4c39d86d9a09d496c6db19a3d99f189c5b93f1a5d43183b91f207210bdb6c53ad4f9c3f3ee0a7bc0f4cda658aa24cd9aaf6a5297a910d4e3e1461292a24ba6d0fd4b9949a23931d89ff7677d4ffa107ecdaa32fc4164990a821bc19e91857712a1a0721827d92343d9c751458738a9d90247671b7400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381091fdd8432929a5f83b2858bd46cc94d8ea52aac9f23a12424b532ed32b33ac0fb45588f37f8a49368628ba816214917e9f041d40c241598aa04e44282134ab31f890189fc5139b712de4795aca4a8d1ffd63ccbcfb9e230e597ec27b4a88cc05b00588f00a500db56db39d02e7bb8127760b0abe609147c67fed026e1cc142ee20f3696ed7b802d5be9058d8b207caa82e70b958026ead7eb965109f0e5871307ff0bcc8817d68f5b34c90359cf23805bc63ff309418535e9ac95eacf4023ae66316ed8eb4815dfe6bae3ed4074b3f84690a5be5c2e953961496df457f610a7dc6ab9e6985117198a4a8f18a5518865952474d2c6d16a64f14ba3d88f5bc954b85700911ce6eae341469e46eef7aa0a1f2948f169f756efc30819584a3b0390a6ca9f28f109b06adc37a42b2fba964ea67947215bbca5f31197443f4d74bc189089c076408bd46587938f611269156ab864815369dc56363cd68b51bdac396bed286a412880185163718fdae1bf393647dd16ab970910f5ef96ce583e94a88154ff3a5053170721316165b9f4a04bdc61a6a6896597d915dc10a70d81e827fe94771adfb7bd3e2aca6fe35c4969fff19a6f7197bdd69bf6c328a5fc1e12664f14b43dd813cc6c07bc8a892a9e24d32cbafa018dacf386849612dad8b61fac9aeb4d1e596430b3e8df930cba927e32cdc0ea9d467ae598d9d42be9062b6c54974d4acb55424df99309a250dcac7d5804ec12f927a059853b05f8d0bd07cdbfe777c8d34e8429d945410e9d3a4239e29bfb6a8978f062da07b9102b15546dd1470074b0fe4defad45360443220855050a10a556a42e0812648c4ed718351c53c30e336ba8535ba0950aae2a24e7ca9c5a456a62b1a3e0668a8dd792fdd5a52032bab6fa102f0c1aa234159803a2447fa81a5ba917d6d6f343049a8026df5986c58c975eaf297857b53646e246d99cd127b192f97501fb5d948217fcd96d3b1200c951e3d677811bc5ac04acabf4a0a821e9616f21c479802ae52978adc56c44f59f35369b5dd5e01002e0a9cbcb4b6fe80b7993690ebe50ada4921c3543ed7ec46b12488894abaaab1f655a8ee3134212ad5012a62a88870784f84e436141771fa10b77d2911b13257a04faea6b4e6897c968e89a90f48e786012ae85a56e0afa4f0457642db3c5dab5b74acbc3056d8cb9e1aae62d201b47ec86531d02e13db5c224895af18b0982783c6b7c73f2fc0274eb14b195bb24cac1bf93f5e014aa980100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000098aacb414eb55ae5e49107bd0ac5975544f83104f7264495ae0bf0a6d9594c422c16b99469eccdfe8b8000875b469309891ea42586a615d146de64fe59277a61631b2c7f7379cd52fab3871bade120ee9558d1479a91925634578cf14d35df3b5672f8b5f9f956fa9f7489d6e37e207fe556017736f6b147a8cf664d0e0521d94737e18188a1b7c30296ccc9067e7b55d6e0f2fbd875f42fefecac49510e324968b07372deb10a31c585457e0c48879ce44bc78898ecefac7bcee90d0f8925df2b52d5ac81692e0160f8fd5808645498428260f592e29bb90fcb07d0424ec79fb081840cb827caa4a9d562183d10ee41d281e26ce3ec0069c83e1e446ef82e2e30debe3f409e0a9e6d1550e224db15dbdda44341e4ed6f8b8984716ca87233197528547d090058607ca141424a13145f1e896555288c5e2877ab3b51c7f9248d2d56a8521975bc4eae3d009988cbd73c66931bada0725fb8a3448d43e0c7364e9494fc4e295a700e79972e1ffd626d1cbe0199917851638b192ef9f5c03223f2bbd67eb59a5e8baec3db40616938274201dea1ae640f6ee7e047cc4c13f80dc65e3fcb5c62386015f4ef1bfec561e121f9bfa9b2075bc1c4730503fdd5debce8a535eca01b9d5b021c290854b5f3d49effb263dda34c4e96aeae9e71a686c009b205994b46cfdf1f76727ca67d415b9d21d54312cdc6a8ed0aeab96b580d0b419e2058e5d843c17c96d156549962f81c266233ed2b795fac40b1992b626457f211f08106ad86f5702b9deb9323a0970ad86125eca836e0a3d6ccbc380d474049bd96ea246b8bd9542793a66e15b319aece6bee17adbba7db337d25f8f642774030a2ff969cb5671f59901cb109e661e55fd5e75eb2a96dc37fec76a82eb89d020b4916271cfb0cb3342494fdb62ea0d253fb8ff2e91357b33d96d41530b8b5e9550fe9b3f9f34fd5a2a1a6a8beb93ccc322622f3b5e8487de19af57cbd1481ace02779ad928b17a9b05cbeb722c783b088b5912c2d67ce5073f1801c23170deb1eb6ddffc4c33dd25f94f4fbe59d704e478fb49dd2142801c37ed8f539ec1782ebd2f3253bbe19c5a048b9ef41824a811119f3a6ad2a0d4b77338e001358c61a9794572b0c46eb1e0e575d4da141a415829ba8712b791b625b1b0ea840ee745d9ffe1e99efd782ba25859351f443654995102cbefad7e59d03c9a502ed7b77144d0566e4bfac086a7dea356cb9e5ac02dbf7e81d6ceed4a33da8d801d61bab5c01f259ee3a99ff7f6d7bf8f2160c4bc3f890736074b000c4c58fa4615880f93fad43d5657c76045d7c414e6b85f63aac91f04a616184e04ff9aad513ba767215fb0331a369d36c0ae9b1ec1268f1d0b43c42b786db23dd66465b3af17ffc68c67964c2fc9e41eabc45db68cd2c3d95b8bec787d994bb8e9cf1dd7d4c563fca5d80b3f1fe8e3c7bfb7d171f5b9023bfbcc0cf4371b63c856edbda154b4313c47983f4027f9e61e86da1e8cd787e3e6b50e1dfc9201b9ab92059f8b6d1bf7856cd55c5b1d6c4e6ebf818d481c56f66c79444f5a6544a64a7d78ead33eb805a6ac4310cd46a2331e707b9b0950ca12092402d68c1cc5c3f269dfdb13ab34b97eab50b0745be72bb0fd2d73bea5dd37802393b635e42a0def8544a96e7f40a8d9d06b64e38dc406bd59ac5c4e218591d20b8dba2125978096517ec5c03f9bc6f96cb255e216ef82d7c7c873029f9e1d98ebc0d8e1312b84b8d02e8d680aa56a506c8668b5b9c56d04cf68e37c7cb1b9377c867240cd42fc7fbde0ac44e3dccfd3f877c9923ae9cece0cbdab00ca530f434a33f1c939fb88adef4d12acbd8b2b5a139a3fb776d8223a9846465c0372b8c3233fb5280e936bbe9fd49058961463a4419d939f4f1fea705eb63114f0a3533638dc4d3efd620147770ad877e2354299cec6e5c18924e78dd661697adf89a77c7365522d3e8fc0855187139f7e43e9a0629ee321b2cbd9f007b05c22eff56fe48045686b36c5bac2267f37a2e3d4e03e19b1e422acea31c2e9f3e7541976d4e2fa03119df9c4cc2d5418f0fc7a467cd98e290695b9530b91d5df8c626c7236a5c0fba73578b9a47491ca0ad26a144b0f23ec23d2c5b2daa03bf40130f14b9a427cdff1f232c9cf02426228c570cf1fa7c00a773bc0d70858588542bbf8f581540870897bfac8387cbba3416a846cf9f4f5d3f9dcedd080cc0de9f71b93828b835430898e82896cd3f30fe2af8349db294fb2a8ffc0848692a0b9e8a66ebbfc0f896f8d03e3c6a0c27e0f2177b85a2f6fe31e8aaf14ea5c1fdc54e80cde47ae27a161264680107023cffa961e913c4e6af96c0be37ad859c334cdb8bbeecb5443662739d027ef1b9535a5a46e2169933e419454025623fd6779f54c622ef81ab9289b50758ea34f868ec85aee589b08962b85cf537bc733f62aafa95fd81a60d5c2e38d6ea0df7d1390bc5050e2463e3e2e3a769de2a94abdedfa0ed67cc0ffafc5a05a3b0fd37bbe6967bed8debf02a42cdc80bdc62158e184fdb6672f7947505e2c0a6c7762b1145c4baf30e3d32434d22707044dc99d2cf2d38f15c43abc8632382bbbc9e0f106565906f7d4948d30fb19edcc3748100397f71e1548e58a5a01876d0a12dcc80000224221c4abd98a5022506d24bf4d9b9108991ad3421d4ab9cc393dcb8d744f97822f95cbb2640e73e401f044fe20253acb8b32a75feda640e190454bab695a23b14ae3ef60b00491ab22f622daa89b6b2e6d18e735672fe0eb2de269e4e386c926e23b865e1ba22dda688293de144102f7030fde6df653e4106c08c2467ad7c54d1df0dc5981004876c6baa8720f70942700a154a376c8d45dae1be74910148ee3f2733e591e1965fe763b58c8b28af25e9b3c633abd83f1c0a4f68da2e0b85083bf97d4e919340c0437a604416c4f629b33039bbf2a1f561548321780411d2e8ac0edae76fc3a19f3c84c3be902a1e84fdf69b11a12dc8b78ef257b5fbb5d923ffd548451a52c6a3af31c70266ae8a957b2bd72a51a034a2921b8e19321108ac303b0d2e269d032c3db13f21d558c82ba4158962f2210e1c5fdd96c98d6639aa844f34e40c1b9c909cc6af1e97a8dc83b78c72b30b7ae400f44ca60af37770b3d9147f7d6f5a327f34df7cb8891e71d41d723cb18e0dd324e5cd22ae0d9f2b1d2bfced0288b7aa73af4fe0a8181ba1aa7eae966d0a240e10fe5735d98326a106d16dc49f3fdb19d3a8449c56a74153655600e4c9e38d302c6d4080017d93c628388df94860329baa289efa4587f079c6f03fa03c54540a0ab4b067ee46a5a346f2fbbff6570ed0166a55c258eabd62ad90f060fade84e8fac799f7928285f58557a72e055b535d00bd9a4880d10c05c07cfe7a6feadfcded880521803e339f6eae3ff28a0a471a003358f952320f41a0aef9d2800000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 73&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000029039784915427e145c07decbb355b862fd531a06b7cf66c8330f6b1b2d7e356799595d5dc2f38b854f26c5228b724878ddb5470f1b4a24831b23c09d13a59ddbd68e210e9a4799a4434b23c66388bb7b8a214e616863e3fd78af225db9b0d14b14efa29fe7bd1b4fdc40cc6bbd6cf25fdafeed14b6d7632bb6796a42afd1d91a9258eeb52abc6d68614ac23ced29399b1d1aa55abf41cbe2b0488aee8d0878fb323725d4abf5b5d1ac59124df1b173af84638d1e610577d13d532e719ef8244d12208cc67de43274df8d313fc3ed8c3967a8fd4a036a6becc823e9c46158661934dcafaf7fb70db127882e9e4480b64c824b8d20b1874bacf1aff44453ddad89257c850730b8408c230265e1e86c1a917a70d4ed16594d6e21ac21b885a0c7c52a85642bb6e3225225e6cc6a90766b851c771307c245d76139ec4f4ae3ad944befe80a7506771963ce543648268e3bdbde34bb65e3ab91a44c37cb2f810d85198c4bcad15ca526871bcba462b407a38ba6d7c223b508b1589bf8922aa50e43d9c1cfef6d8be4e46d0d03758a496f698d164d109cb08831189b2a390cd485c6e65d1567717490b659271fcdf5af450c8936c93eb9b46e5110ed2491d98ec92762c8709d6f1e8a0dcc99e560f8ac3ea1d8a1201936ca22e4b23632e30bbf4af39b32b7675fe6652ff7225f30bf4c9a730dee124ab5e1b317c555a24adceb420ad1cff1fbd3e73d5bb852ade331934571e70e10e732827c7ad6378f0ca9d4102876b5043fb979523b415063589633654a751dd8a37cdd6ff4354abef773e4705cbf2e790fb959f8644799287be11e45a5587f5eff23e6fd5bb3592d9b97b3e0d32d6de7672895633baaf9cd78c979b74399fcc29245a1066b3bae21f7feac39d29eb6f6ec2a2dfcae7421d504eef9ce6d166800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109ac5d0bd6dfc9f64249f32ac8a4f542287f851cd4849d461ffa85cd4022181627b6892b38ee41c27da98e096d5c34b6adab76a9f5c9806ed38c583ca6e1ac160350f1c7d085e51729c6357ce8869612847891eb6759ed2c38b90afe0d70654ab853b11941c242609b54b9b439714d09c70b70c314cec4d755f2cc9b4713908f0543e44659545a7192a1ec48659b910b86f65a76b3805b2b0cc8800dd49951d9292d2e0514e6ea56502ea5bfa1aa43d4b771e800e6db3e08f53dd0a6e43f6b500ba5ed540d9ddda0369a41656201bfb97f64731608ed86f991cf70fa111002437b9caafac79fca9eac3d170b32d95d72169369f4ea6948d55ff015ec0870469f2724ddd42b7a32f78b8f5db0f2ed8357d6a530ca021a83ace3a7606f4b22118832a959d2876c7b413d0d92e9085c07661e15e72822a27203f97fc0db80fe18100ad15fa1ad0ff43f40635348adeb94d7139256f24ab951e14b75ee096520ff66226095b9a02e11f2ca3337016ba2bc3a13226d56263c08c6eddfcd78642e2899490a64f092db3ecd5104a0e9f4c74c6800de5625c71bfb30b11295e583ea956ad5693b9d046a21b3c16449f68928eb109a93296add45d0b1627a4478834a160c865eb46672d3ef0d4425ae17e00a38169dfc931c266605c68ec0068cd0437959e787a5ea861853ea9b8cb41b9203d1fe9bec562518b9769fb222e2a1695650c8816e71d6cb2a23aa39e860ae61888eb8e12a32c4cb2859933851a324b10d1dab9467c520ea43e9d781e06b7a8d07dde6ca2e3967ab58576f80617ec0680398a3d96ffaff14edbab64210a8ab936d5e423b74e8da482102b33a58c291b68ac94325db663ea132e40f5f674ead74ef4a9104d8c7925d8053a6aa095858238b1f49857a6225596aa523f3f001906530a3d022ceb307cac6c965cb2c1e8d786a71cf88398af1a6c6c0986c0c26b0066b6738b4bab37569625c3d7ea178aba774667ee35a1f9f8e7e66d882d0a3b8c1737bf08840a68135b1d58ecba13dd554d0d2908f9c9e3912245789416378af256c9879ffa3cc1eb6bf49c30a2ce519467517a2cf9cc77c74a6a05210fa9160ea1a7eddd51759fc866e28a043d97c00d482683ddd3ec1a7e53ab4ed4b6a2264f716068d75c554dd9c7e7272819602b5d886456ed0e63e19b15a0c86f2168232b87297462b692b59c10063b64a62b2fa5d542c687a855c9588b864bd903e81534ea5257707d1764aae8023545a1a6b0470395d46430000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009ab5f7522ce6bd0ce6321c27b9eaa6f572616201f283c5ec171d0ba47662c2320897805e1551ed438f3fcbdaf9de6f3a19dc16fe9c167a65b6e52bcf512c919561b548496a4a80af7ce25458a62eae92ebf677872482d8647c30c12bb1f080c6b9a56560d64fab73db17487bbb007c66661ea9dda14601ab27a100ef4cf4b7447e51418651c03211f8fb884be91f3980fe13e00ea4ecfe6d54882059a436c90bcad80e4101cc6c0754417545f2d167629f80a3c5ffe45c00ab2baf0494d6c065872b03a987a5ee818b3ef11e47fe1747f49e2db6a14410f0b1f9610a2d6114395ef6ebb231fdf71d595cc1171db9c89d6cf202e42d4fb968ab8105fddb2aacb15fab8014b534cf468d77ecde2072623b7002620b7ac3e78b62ad673feef9f8e97e91acdab171fd415b2d15605dde00d074a770e36f2218f7130f13e91fa4c88deea7e854bcaa01b8458d40625a33e982f0955b83080a926ec240e31f0d9bf477ee3a016e146a3909683410d4d09ecdf32eaef580402f0d416dfc082cf1362e8b79158bd57739aee56dc41a549e534c7ccf3620c7d7d95b92994a747d5efb8ec43cfa8189baa9b75fd54694e512fca388b71a5b9ea591ae9cfa34183de59d284ab16b2effa4b26a24a0e615b38b83088a9827eeb5c29b419bc061b033e0e3fc809afdd3de948412677e0bb5136854532639f3ccb176d54ea1961b5c527ef66f4b3286a583e86208aeeb8ed07d9e6bf1beb33995f76ca480039a6130775895f19e3cd4873abe3bf2fa9de81bf0cb04575dd6ae282720b152cf0ec6a4a04016db0f3543d8272ae56b1152b02eaf22131420cb194021f97060d5ce52eb21b57cc93964dd21344786e3888617152d2abd829799ce47d20158aa93f7da85ca6146c5bb94b512da053c35bfa8840ca43f6509a1477603fd50f5e4f9a7cf8d2369156989ad638d35d345bdc859c52688211bf7ef3f4ad4944657289406bf01dcbb49d560a11840ef35dbc0c7f9c96dbea76300cf61997a87d70f5ff8c51aeca2cf0680b6fe8c4025e1e25b62103d248cdee335f4fcd67597103362003206c507970ea6d78cff4b68b44244019152dbf812675cf667e5e13c8596eb6fea3903bfb25ed08f902722a37f8e460e37a03a2d6adbdf79da20052de658390484b83bbab28d039a303d7376bf555181680b7966c798a1c6cb215257e37739de7b9706cd1cf3ab031f68c82d6ecfa507c104115040744d74a40c49245215639d0cf4a5a7a10098e9ce3564ac3c44f0683ae9d3094784d354db1af439bddf63d5cca668d8180264efeceeac0be1b8e1c6418e45f9ed6c779ecf169143b034cd9f332989d445c83a8786398c507b9171b4d95728575539cbb29c5b804268d88f2b39af1f9572b8daa9feeef69c4a77dc64bf2dbb5e57f8b33ab151769b2d00010d67a2d6f188d6d5b35e5e1873fe2b327e42afb8885a842d26c246f7c18e6bcdd6fa49b300c65a3822121e95004928104017cbce2ab95acadb9802bf4bb049b8e96468353d649654c6f69d774380a5a387d6414dc3000540bab6eccbaa088c1068ccef20036e5c8342fd512f55e6794bf85fe15721d99a1bfeedc218617a940c8c25d4dfafec677d2a719b2cddcd302294b7fa41aeab5606f859cc0d638ac94b99ac3ea48c687d278eebeb396dc5bf2d2e89e880f76b533fa54efd30d8ee38b34dc5f8ae62c637e9a7e85d99e011f62d261ab4d3dceb98a8972d3482cf817eff476b873ac56963bd60183b359713385ba82f6e24be2d6cfea6dbb4ad2e1b5b790ee54d23f64e740502e887629b346fc8fccc3338d0f2921131b84590b32c7cb82cba8bb3b81ef7bc5cb12f0aa0b3c6a5b2878dc4f868057c68460c71d40d4263ac5c8b8317d2d0b63403c7549439a9ef227268372ec3a54cf8ee97714bc4b55007f92b1a32238659ec1ee27d6f2987ab06fee84c3afdfa73240963f076a955bf3c19410e1da6a19b3ea3ae2dd8766082d3295d35436597783dafdadb905465d05fc21fa8ac2737a52fa8aaefbd2ed83f12545c1fa3198ff225d37070694c9392738e89467edb2da3cd1734ce398e32bcb1fea2e4fe1260a2d9f9edc3607a8ac8a51d5da36e99b31903025e0cb157fd2ff5b51c9191cc16a9ccb870b4060cfb0fd900aef62738a58c5726f5164417f084ef14fc0953e3c6036b818c21ca3476b8cc5f8ebaace257a0315031a03e64e7f749b9df99bb56ceebbaa4333bc7270edee90fa2715bddc38d44898a41998b2374b6ee3b8524d3a385c03868ee9479355092c4d20ec32deb51497f4ff34ae7e7ea4828c288f46e5148de28a8c660ee132e5b5489833dc66205ec968b60dab96c2a4452a7019bba9fe3d19d5829129e2a9c75c39416ac8695145f2b62eb9468198cbd48d7670ddc6af2f99f77e7acd01a34ea8e0e974206fbc22656867d09807b980563e06a559b0c3a7e6f43cf8db75b18c0f90c12ff3bd43abce7df75d17e631c08c974322010648fe2e2bc940e6510fb8835df8384eff3fe6a264687256c6bc0a5f9d2ddf208171db55c4446b03cf27796bc77e3c68d8f1252be21877d7c53747404420302ca5ae1ab57e43b158be8b707360a2f59d6a473f98b816fde2ccedd92385202c419278e8b840dba4c05e9bb65f68ae2a635a29110329e8c0c02f6fb5eee41ed225051ee975f92da52f93eb1fd7c0a098f6d1421701537298651313514ad31cb333e9c5da719bba95e73878ba41f9e2512862a80602aa2de1e1d086576531330cc7bb8f0cec38050b3cfae5c8b1d6cb849a579f2294f8ce80fde5405bfa3e6ecb01d5117203a4523591ac4030397de9ff81d5cc91af3002590f5854e852b88667638b2d052f2a7852425c8ec026e48d9ef5e73d1993d7f3fd7f704760562c36d2278c9ce131ec6aa444d7b2eaca3ee888d9b2ae122688dcb35455e7de31562ba618f1183308b30d07a5c34020546218101ad42ac5054d4703587ff60e860a60375fab12734912058d5b0b06430fabbfe0c0b43c22814f56dae9e2713325a31c682c13f008b9a3d4ffa8a454f0f64a9213ff2d557a4cbc64ec6e4eca0a976cd9f27497ba544dbaa3e2eca0f54c2634c719b9c3a2ce37bcc8158a880baa72780f8b1d3494f589e2af3044b4fdd86f4db2df0843ebd9f3518870f55488f41e234ce94e907a69d28bd83347702750db1ae2eb1454cdca37a8b5fc90091f548babf489e57c8919646e977274fc972088a522fff9f9306d2f0ed6c01ff92cae8440d7f3526b8c186d5b96942cb08032886051da2a9fe77e38beb18f4fb25f1152edf9d61347a00a844929976a327be46ffd3e2ee0b6ab1014294ec5d40cf7071c36b11127ff90720596c1b3065e7de8010aea469bb4f4ac5a6efd20591cefb7b94b2006d85ca475fee556f24cc41237c631b75eb594f8342deb4f976d73aa46563c1aa6d0b605a16152315626ba08807daa6025cf62b29176f3a85e4bca483effea7e5939000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 74&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000291398cfca6a83d89ce8414fef3d5473ed5eecde46df0db3b546eceb15847b861e058143f399a7f77f05dd240142bc99f48a21237269dad4698f1c7af491e0e7e89fce6ebe9f11244af7351c1002171871b63f94716e9b1c05d297218da5beb98b0c81609c8375ed496bea3ceeceaa4806720d8dae706109c3504704d78dbb1e3af10e3591dc0ccdc5f2366a1b368a2eb8ccd50a8597ebef0996bb95d79cccb9e5090fabc09763bbfad3edf23d3312411a2a089ac1511cdad6842275f339e2dce473841d8cb12858a7c65cf1250da9ecf264b88be1584f09275adf8666b1cc03ad7298a7a47190523a1aa671df1d34bf8b5e34ad536dbc405aee1a1b1867dba4fbeb0353aa51aa5fdd2d8932a4f77e4d89be716871a0d045e306348501a9ed7266b8fa8ae5c1b422e63a026d3655376fc5f69426b83a93791191cf5c8c93259e88200696e68dd8ed9ff411f68e28553928d1e622a3307cf00f9cdd5b792b6ba6ca8537a0a0e86ca16ddbc5d8279d8735949c67e7d8ebccc864836f849c25d86a78fe173a434546b1d773c8653a34cea1d00a813982a932010eaa72f6b81771cb5d511fac8b0d6d4f1ba6a1c2d37b0dd4fef9991058991fcd3497f9feff97dcd49f74625c86f263b8aa3a15062a14318c6bcc7d26c379a5648420d27c92261086c09306708990822a91506126b37cf6c4b90d9c5b625e7f99e608ce3a79f45f71068e395fdf0d52cbcba3c07a7b0dc7adad571f7d5226fc7e6e1354b6d6d77af188557e97aa124409ed7eff4c71246ab86fbee74a697059c73170af45a529469948d0492a1d3e023f9da5ebb81886922a826b53e9ce812433dcc5d104cdef93a5258d6696e819e6f2f1882c615ec877aa3062632487497087a512f5fcd276521148e6f5b435e4909ac20a631595c2b8fc96ba000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003810981b9188444af3c52cc8143c950d18d68aadb4649db8a6505595160e358392d06da0b5fae09d902fdddf63829c746980fe15f84b45bf1476d582ab2ab30a047a52ce418576c7e3bac8cb2c45c1985a2e3a817866182262e10ff5202b4fdf40b91dc7fa6900ad88705a57ea1c1cbcb44e762687811185de09309ccb606c3a84b9065170b64934e54d5e580c5892638ef534454c750cef7a5829d693a1e62349bd4f1a1466ae0a40c91796daa31220cb82f745e413dcf37663acc10e1461b31a4e3211deb3ba9c401d62318e137adab583edd5cbc0e45d9fb635ab21a05662e5a356a8525854a68db7ef291e30196004ca00793cb96771ada7de9eeeaea7bc409a2f40d9e7b11f7a1da1c9797a4ad804e12a28dee2d357a5d9f6ae86eaa2f99974156dc55408fd28ed06e91ecd01997d1c417c0a361b41080ba8a16eb857d1893ec0df59c418975006e2a774ad90b87628c2cc673b50e49708438a831b5dd0e160d2381b264e6a03ed4d3d5266db96a7edb6609da54c402c3155e84b8d0c52ba3cacd789e0fa404e71aa4acb4387b180028084ba2d3cb341a2ae6825facf242ba5a928a5fba2688a2a2b94d2c7bf01e4b03942c88a93f54cb6cf34aadb4250f91c481f558807ce922717c77399ec5e259b85559829f58403140979c835d8139adebe32e46acdd754a56c59732acdc6ad0ae8b190a516122c04564b02162df580224f567d03798436195d2925a2d4faf7a6c12f5db0ab5a9fa406a28b81cdc4a22faac7482494ac0ecc22b35c055e84c9618a19d4ee9ad0a6c0c51ca984acc2539be8ef60225fdbf749f88dd19b8426e22153d967e05bcd4116a6b7f125ef7350614d8728e7f086316d949916ee80462d349728bd7e0a988335d8a101c0cc5132edcd4a0e3752d4e373b2de52178b24d081b27bf98da3f81124785407177b5060a045d62ba9b9ca2335ee61ff0bfcee2152c5de08a06872829c64868d6e02911a3aabf0b7f46b55e46a02ac8200186d218ce708e9243c8a9da3748988d6814ecc9aba88797ac508d41392909c947e0254983d99d0051907ae90731cca13224faf9cd2d9d4c5245127b6988174ab89491e97d5d8a3fba29de0c230503c76e292915d016f5cf577384c9963340a0b89ecd94327e52be32a44bb4d2232939ddd67bbeedca012cc5226e07fc31ee8898884f5e14fd5962e8ea9413da56943016cf00190595d05126832c0caac116d82856d4a92f95da2b86da92e5db986e56459654af240000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009cc9ffa507328b2129c9f05a22b81a597fd1b8c27d554b36fd3eb150bc5fa0c6ed967ec5be6f1e52d3bed1508dc3c841360020cfc2ca1b0713076251f2935efa8500573cb4634c78a1d0f87d994e8e2b0bd265a877023b54d9a33282c12397dc74caab07ac2efd140df907651bcd1b37cab2d03f77cc28872291f1cb28fd4bbb5331c2a18e02120bfd2d9ec0c8938a6d43681dc03527fc2bf59703b5160d8e25d08534eb5aa5cc9c10572257d9e4db29235683bfe1776a2d9edacfba1adaf66587bc451d32c524c7934556f94776f91cdda96d2e5caf91a39503d3a742dc5a0efef7c1a13666e200c5e3fd7652d200adef51fc5136281570b7832e0c6e7552972e43291f202e6f916c916dc3fa48858f3d92b1b7efd42de140d43648aedd7c7379d7a4b71751a3348b6bba3b0db71b4c99c41e085e5536a3f0d2bddaa88069249e21e2d9906191bbb5c8b45353de72e00270431847aeb4ff6230cebd1969a0fb68d6e302b78da39adf6c0e681117c8432e24820b9ebf38838545e95cf7aefcf1e9436cf48e87b6c5181cb418132c7bc050b9498720d7d534792e0585f05da2735b7e68fe35dec358da1bf1681f7f62329bedfea3d12bfb26ad9403f3ac1db96d828050f39dce4017b45c5dae4d7de9e9f687a9d7fad1ae0e7197184142f6818a63d5617be9d8d82334a12e68f2eef88a0da3a915de63629550d8a64df591eecdbd1b89eb40ae9f9d65815271693c85f2ca41bf45e4fa16ef8b17d945ec61e757c6c609d8afaee32b3ca628842db255b619f6562e656f6125fb27195ec82fbeb9c14330dab649cdb74f523f5a98244194581503356b5b7ec51e2b35ae889452d3457ead713c0715aa7382dcc510b16e771b3a5a91949faf5e29223c8f1f861bc3b4e77e095bb61aba00eb29c065d6f9da9b4413d61b2202547fb6e34671930ebcdce4c541b3e2dc90073867a47197e08c96f74ed81de5f10c37c062e8d82364d67eb185cd098cac1bc3c522e4fabdf2fbefb66b9ec6e848f732a737fa7b935ef2848c29b1fb94044996eef006e251bceb5be356f286f0fc85e5cba627b67398cbfd6c0f520c6f896353fe75ba323d8ecd9d3ed2997580e7e1e49eecd91982c5da650d6b128068b8d3d72c1ec4bf1fbf121ba96e1cf5f247f9fda7018cb609329b1c95e59e112c393c45ef7138905902227cd21a39ce30397ff017495bc98a968fb497e03de5843e64923683f2e402da63cc25ad0ba13b85e3e379b08deb39542c06a268bbf44990447190a1f8adf0d3ed9ed9917886210864cad84e7c4d1282c4d3bff9dc23e4fa68ef6b0480e76459d1b5e0a7cc0cfc17f59531c4c1cb1d416b7d009ab50173f706289dbb68201c305e39fefad87929ef933006598ce0f0242a2c60955ae487115b4c367a7e49488491a6f044fa8b7afd81f6da09d29d4befe1b3c9eafda4f17d22eaae0b2d1646906d1cee65614640b53479e23831c56ebe12b92997d5fea725d78ca75f4509eebd3df4f741d6b2770521be2ae63ca365fe1518cfdcd5088d58cdfb8d3dba76731f74760a47c9d619a31b7e318e957194ac5acc6867cf8c9c235043d5c09240f346fea840ae0bb16094883fc801da0befac64a021f6f871413249e9c7f5cca92f4eab5713b0f2cd6c950f34ba6fb1cfaad541bd5faea45ea5fb37258301a49d7bc4657e3e986d707213c0f836b030c21593f11518eae3a8a95a2efc8b9839e79cd8cb0e6de59d5a43ff8f81fd35392f0c0659b7679542136782d559897fbcc0129c22f43a30cfb27e899a8ca52453f5459a281d0cc21f902403a596c7f69cbf9a64d97b935ab384fbea5851d831e8420066826d7e11e34047d18cf08283be8f29a8a79b0f477c27bc41b8ea4aa010ecf8ece0d37389ff13e235a4526070f96f415d41af2e053fd4440ddffd69799456e7335cc6d9f4370008803f7babb6c58b6996dc5a52649e25463b5267c188e2dc39b3258636ed8689e5c02e00574988b3af881d30e9eb38ac51c1e00e1c0a411ecf37e314276221d7d8713f7a449e38371854ea26520addb58082287faa1f77fc04095499a3c3a331a38852a287b24040c1ccc054086964fb1ee2b328f3de21a986507cd20b4de4898dfd15045324b93fdf85e5392de0f32c3badd04784012e97cb9ba19472b0c20eb0a71c89149ebb601abaa4a853f2c75dd2622235ac30d97b9d7b1216089b9cc8e879660e40ebcd15203404a8decadc42114715f4d8a6a10511bacc4ddc23520445a95fa3945bc95878bff18728e64de8b7767cfbbaa21f3ef2d92f3d7dfda792bbe4e5b3381077658bfbef8db95b64f9f2a44917b38df6f9391118978544369c882b218e7a7a31afc3eb9a75a28095c4478dc81f9cfa127bb749cc53898409365170823d65a0b46bcfba0e47cc0c5f6ecbee09131f134edd254f4f58b50c486dada13195b1a35739420a45be6558401f64c3b6ac94b73397925c20545621c7ecdc7da9f71a755f84d27f2c6d8415d37f2bf1966a76845216e41764ab96dc2e14c12df3684f7683fdaf5ec771db7050f81a4b3e516c7d5c955201a18f436962476c1284531764a9397e0edbffa8c3699929daeaf968b4524bd98ee62f9a0db9cbf99fda80cc6c57a5ee1099b1eb29799a5b5bf5593cda26ce2c66dea3d40545465c1d21f5b9373556b9ed0ae30e90b836003ca83f78e29bd8d49550286dc2de6407860e9a9cc5eaf3e1b1c73fc2d248b81b1cc8f59dabfb5daade6f2a0b38e76d9e6d0125955d08de7f334a56a8f362cc5d883d56bf7babae6d9e425376d34a05ab863a0d9adf7c6fda574fa8dc60965e021532c25ed4d568412d4143fbf2c4ec2f230d08337a4e546e01f7c1bff4c97f2f27af400caa57bcf398aa5bffe155b0f29a085d5053dfbedc3423818de8fc597eeab2c1663d8c81c71cb876f73ac854286063a2e8bd8614d06b80f3bf56381179342143f4c89b8cefe9168b6a96f416dc617b9f544f9df65ca6f4f7a84a327909666b70cffe889c86aca706a0a1365e248d6b341a004a27d4ee344f03ce6e85d3573e272d48210df7c3178efb7bfbef7765d24754673c9eec14c7513fd8de6386b0829ef0980b826ec9c77c81d1e3b8caa65992db9c2f8dd691c520fa6f233afaaedbf287a57a9a66d2330f4636f02ea3148c4bcd2c8b114d48a1027fb3bd5008d732c427adedec9969aead451e166954fdc207c1a4ec409cac60e42383385187af44f136f91a8461e62eafe6fcadd1e491162e46cfbbadddb72e5b54b7c655cb9489e7f4f7e55c93d3ad50cf84e1f47a706fedf818a5246bc755d6d18ef18702f5a90ce51812a67227c5e5a051133576e9ebc18afa18c1b05c854d343727b25bb10e3b9a3645d789287858fa43734d66ad831e8646fe604286544238dc99acfe3c8285230fc784bb73360f72ed34795b1c46edbe32a346bfa7f534b500c6c9d3ec26ad7ed20d1500e3dedf141df3c2f92e981472f0010a48f25429329ae92cbbb918246f5a53212703c75dfa15d014801a830deb75baa360000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 75&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e00000000000000000000000000000000000000000000000000000000000000290391b69c34c690b4af9f91f8c289b2a8bbe511df8eae492902aa4f7cf9b3e4cfbd80450d32a51affc2928a6bc50e68f49b3b277b5e5b251778de9a51fb61fab15413169be00d1b45a5ae2c8713c17668f30d1be514729cbace5557414b396f7b100c611f661ca347549f5af24d8b0e8b1b6d0c41035f5ec76dfce1f07e10b259cdd6d71cd8879a09054a0c871aff30cb561a5e8960c0a58265c5f7226b3f53890df376cce28c99b91271c45df4b51dbde39ca9761089cd1a3bff2cf69da6b49034055a3df75c2353a276c59091a34ca56806eda38b2fcab2e0d9e05d5c156e0ccf2aaf1d43c3389cc0f2e60e1d338e66bcae0422b195852222fcb8790d14bf5cdb53d8ee7c05228335df08ef90952c144eee093ed3c0eb5973b18389f1229e7294ea17b7a7be628a2e1055fd8f3c297a80d9fcc8e89f42cefdf9b5c11de776808a23ec2953e8a1f40c3342237ec55f48d2ebaeb2ce9ad4a7f81673ab8699f96b373ae41a63564a7ae6475919d73bf57c2747c0a0a13bda0c9a21ba43ccdf8343c4cbd718fc99ffc81b11ef6948c372d8fec8a5ee38f192751d1f4defd2743d20ad343c09e487d36679152a4b33d73671d3ec32cc24995a50cb6a132d62198e5f4183fcac682b1b7e692e5bdd898947d02c4119c82668a52a68e6fb540fc46912d532fbcad3130c7ef15f045946e2f0c7e4fd6be6117c53a325596b524e67e60ec68809b38d0d031714fe77b74d7d6b7194f22831bf0ccc7375e8ce99f5d0455cfaf23facbc44db122c3fd22af63975deb0fea40df6d9f64daed8acfa6813811596dad1e4df9b70fa6451c2ee79a2468e3d1be12c2ad573698c6ed2a3795f127bb38b8115a646af5293f12070f6e8b274eed9242e34d9ad938a89464172551cc9c899c9f2ead501c79863bb5a872986b8a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109ac1838684410af24692bb615d64f14fc804996812183ec4e994800ea987521260109f8ae5d8bdbf046765be00bfb4ba537a2c1248741c7e611e259b325209172eef8795025922775451b0580d06e25b878a5ceb738916328836c5f9d8a5e41fb18c68b20cc68f6573656f68e507c402e3b1977b947094375a450095e8a6d2f948faa13009b3015ff93a19d0726941798b489743342a28471dc06789860272f403c33e4b4caef89a5459c1f41f904d983f54b78d6d44b3044daa215d4c0a042ee0142105fb7e8d8548da380ace6aab1d49c173c047f647bc89eab36035264d4541b248808bde682a6553b1b5f228f8e04b4e6f21a1b84c4f6c1d2954f33d964a2941fcc5420ed834301d2733268ca16c1c50c4d8c1663237328600e21e047861bd08ae9a4245e8dccda5726cf66be76df86cd425a6e9a32852da10d300c2829dbedc11820710889226ab9beb20103825f310ebef38586c41f20ae33b2d6f69f109bb133e864340c8a13b01990720e51409325cc0df265e1b39a377822b9779da4f2212801465ad27a3940b06acf8c4f96e9a351184629b7b45fc0ef03573f3e0cf9566771a65c6ddbc6c3048d0858c60dd058a3bca7cb6742ba3386c6f5a7a4f40d4d9daade27408429c9c5be46606560f5436c9f4770dd1d61fe8163128dbf535b2e753a9520f20e231ab169a17221980fbbf6bba53bc5c845007351e0689464d428fb40dea26e3805f3c7e30aa86608100d47538de175f9dfaa124b4264c1ce1437519dfe312198184ef8ccb7251a1aab66910475e0aa567ea06387826c70fdeee7f9cfe9b41decfb2397690d4de16bfad7cc390af1a99542cca8a89f880723131ddc67f733a0a35a5e40f6248df14a3abcd679c9ca204413e475142b9810dd099a21c5527c95c3d54aeb365559e6e61a503b300ae36f0f7fbcd1c9d95bcbb77c6d7859c707c26b521a0b78c2e440715c065a0dd52029869b89418797a0ac0b2c13ce04e1ff60ed23e253fddb53a1240ca97444a70b67598080202a6ac3386f766a2973d36798b18c6b81e7203f0ccda7924f36a8f03bd48da7c9a7819df14a0eb65e6117b3ca15c23ee8aec48fe3dc17e97c2bf8c7e63191ca923d049d055812f7b6c15504e1b545cf2fe8801a729998039d45801b3649e04b10c28804f56e0d790542f0e04bedb71ddc5a6a571c901a59c6249c6c0f7da308ec0a0e54912245b89d095b9858637e4b718ae0da7774023fbc08cebad816fdbb02ee2bcbacbf0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009ede7e845902e852b331ef9923416e492c1641236e4e72408d800fd70774ba32b6b4be04b6e82237a247d26f9a33afc4745c16ce0554774c68b33cfc6e67ae34e42038fc6c324972642338daea75982c71720f1ec9542df94b38434da34a2003fabd9daea1950b7751da6c81aff7d03390f5d63455d417f5d12a510337a16197ebaf921b6a7a9a9a58f9696418eced6b27cb8efc8ecbd9b68714f721561af8553a0d84e30e009a8985d011cb994eeaaf88c76f7f3261b47fc174155c138db2eadb09a06073b211fc0d27113e8fea0da56e181cf532ba8207f5d80d6a30d8bacba540d49a81a0763a0467dba7883766ed6358e809261aa3d8b757c839b532f272c5767671a3a8bf3391b14f5e97bf2668a4e98847f1abfa21e2370870ddf24504f89b3db71e210c46d66ea7296d65c926e2c955d899ac830cd9d06808a68e9b3722b86e878cf21a5e5d41d7f3cd95d23a6344c259859735ae1a953ade13ca103692b33af90ed0345c7b038d938f8f494d90cbd3933b2a80fedc2be57960db23ad018bac63017a04fcc510553226cd86c74ab90e13c72a1be12e4d751dc670a98ec4f81e9f8954a693fc7175ba7e50d340ff7f15d568d0abded0bb1fc557b1e55971b4c4ce8cc1b4d9e239c73b1133c9e1672dee36a2d9527f315c21764648643d866b0e2ab6d2dee61d838bc5dac183fc511c4501b6e535ecc54f3edad6e8edbf0de7cb70bee861b2bff0d41bb87ffc0ebcaee9a6dfb98d31d35cfb6dc0442fc285ad0879e7b218b6e66453fe04207fe814c5f72e49406b48fcb1db145753dc2a2d3e9793594f7ef1a1a6339619e1040cde605648234a51b2f6774b31c7f9a77c2ce3b98819132bb725d288c65901f7001e05fe5326b6f701c337d41c8cf8748ff9c276ecd398c725c36c11857605f58c0b154dd9f3c1b4649ae677533eb0338b7475254e273b786c2fe7db4c13468caf0aa2aecd55dc1a5f868c8edffd8be8deec20a9faa621c4680f3eef4dfe4a79794fcbc5f8c56eedcc3e1963569a36525d4f6a5bdbba5d12966fd8a0fcc70783fd9f61613842f80d000c9281cbdf28c01c6f6aeac10df1ddcd0322e00c4e3cc801ef091d9c1b01e84dce725d57c800d38990251aa1d1206ad93a7dda40f27726d6a03d973150f7a88703724e314c0953d56da6eac442a70c2a08bc66bfa2b0ee11e185131e352d10dd714dde502097af0ad155aeeec2a6b93b149b75dbb898b2b3a7c5fef2f48d9b12a580f54c4eef3ff83a4f13f2f194af551d4800ae86aad6efc82ce460d325cbcfee3400ae939431ab4070d7a7cc005f270896051e32b1051e58941530e250f05af19ff416e65ce40655fda31d2e7a6158e07da08fa61afd5319b682de44afae146129a8b769c1708a5d3479b6c910b2ff0fc872a4a41aa8bf3ee16f80011d163b599d18501335a2be10cf117dda094fe01596c404c14580a7075d04ceef68bd8f813d7de6599f478f3de9ce60b294cb7ce5284a61e078939d08f3d4fd998add3b92532aa54e0c31087cf14bf4ec964ebaad53bd15d04e37948e94917dde181ee3bb2346335ffb403b000f5669019c5281d88a0e771176e49dd0ba22e719c0b731ec2aae9c898e74b2967bcbdce0d7d73057e004bd62269f4e7f3823dcc18cd6c551104b9b896b0ad138dde7c3d761138641bd3eff3df1552659fd97bdadfc59a05cbc622a4492a1b22cff72ac197d61a4c5a949aa9ac09d4c1112f4c1b1cae353c70278a21663e11f27e9ec66ecd4ad56f2179a3fcec37ac3a3f4b33c06bbbd4c8ce8e74825bbda3e58a2e2d928c2c6e6d886274bc0e2175ab03d8721c664fbd6455db2960e3aef0bb25afd3cb0bafb71a2bd18a89adaee00aadbc7e4ae70ed4b534aeeab88559194755f9656b43bc83e3952000d9e2295bf3391904218a015c786de0144868ee4aed203b261fe743b7168788a0680f7484792a3f64782b2b1ed9217b09ae9845dd71ed363f18e8aaecd51a4f5913aab33fea3fc5f1e37e0cd6333d2a8347cf45eb7c4ad967fe6fcfff3565743435ef09a646e75c7e968ecf4202a9b2c23aa8118a1683219b1155c2cabc95c696704f5b270c6d213332649363ae13ec811e9a1090d1603eff745e2fa83379dfc6da5efeced556e46a8a5ff1f2a5c0d911b95c20ec2465ad0c96ae7e16fc36143762bbc0734cf4d6134dcb0d739f7822470e0abf66a0ab15ce0d6096d3abba2ca4c81c1c68bdc252a8a4ba609b7c05ccd913ea56126f418fc0b06de8f76ef651f8085604c16e5910f3b8651ab78296b56b78326e41ac15774e442017fe5b291e5227ef5a4b78ccfa96d6921c8542a8a984bc87e2678903869c52c2568fee4e23ef3cc466ce270614e6472244a4294b31f9438f7e43437fc9c9c5f3efb0f4f0af2110a613661dc24a1c7f7a7f8cd14a943821f16f94bd874f1a32e305db4776cdf6633446724ccbb2488b1b06f0177819d53885127e6eb717c0d6718366a8b8a089aa6ab17cb2581a75ec748123b7d0383f3900efcff77d2e022e90aa41491117758221a0b149c8ebc23cc01c17b9fd39118dad413a391cfa0a5c614208060a61646c7cf1dfad4abc3a9cc5cd566db2ac8faf392c9d8e7da0f84b941d792a8493fbebad30d0daa0d683dcc1583f0c9019622eb6c92fbc475babc8b626319be2264ed873ac063f84b7f83688ac99d732a1e3fc12281bfb1e1e63d48bfbfca619bf4b95f899c50ad0f5fe4673347df2bbf2ca21bef49c7f8440d95a83299960f1e42b457addccce236946de80fd4862baf36387e041deaac3c9751ae345512bb1f423a3b4ca8d3a5e3796d289641d3424ff22670a46552ec68d7d095e8636441d777dbe2e9dbf6b5fede5318516c3886b943f6adf17d8b7cd40b20a48233c9fd981145b45a5cb8f6a88eaa36c270e93e1d876d7781bb92a1fd99727d8e0ae34c73398ab8781bb342f5aacf4081459ea5ec20c30cbb6122344c457f92b20448f78e1a2a291202003781ebda1747061c6ce1f8bf882fea4fb50bfe638685cd638eec15bc24252567025fc5c16ed1f5d98dd90c76e720ef7b4e25a20d262e339c5e5bb5a9cf051bf5fd1f63e93452a179277b57956821cdd901f1c01e634ae18485708a6ed8f592ae2ef3a9d54c9734ffbadc6f0b86d0398aece9374f9acafef38d4b97be9b932b9852f97aeec435311a67ae344ac1985738c72f52b3d8b71f64a916240477fddc5faf02f8224eb35d310fea03fd2c5933047355a438676d92eadf70df662d97c2f5e00cb293053699d51d302b78145c77ab03f34eaf170eda5215436faf0238a4b0d41d29f36052a5278c7d8af9a6ffc6e2b6ffc4c5d524f7640a7170957f3de2451ac75589ce328b61ea7179fd990da1698f5c73bb8639a4da2ad67d364db04771ca118c4055c25f1120a0643158c07cd22b375d5c1dfa26ffcda44921f41d4a504b2279dff03421cad19960f87c6b6dd8c29981cb66c9731f931e43b0d97c6ac9862e2cf711df0ded8e4d06f3957fff9085a95d9fcc95610fde22856b229a3121d8b81ee83dee4a6a9fa3fe8c75351574cb000bf7f3746ca1cc5414aeb23a200000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 76&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000002913939216cc1160bb3d6ab3146a0bc9445007cc90026d8d8e182c4dc7215ad06bb97ddc10672b373461d9e3b7e36c9244bf71be734c2b02675a0e34b4af9f8ffc2987209b62eaf671106f01ec4e5c297d24f876edd47db666bbd07c20862dca4f8d2453926e08a88c7df34dad87ffb527fa3a57fa7dd88d92a8da2b124fc869447e2e7fd5530a2c3582044c763e4a2dc0b3d7a3bc1f633ae3e676cb0f39b1cffbbecb563f412dca2352d5f3aed4b73b67f200853635029b7b71f198faf3aa57c992f306626031d3efcfe492f257bdc5c4cedc54ac4134830baa8a2b5834af993696c2bcecda36dc639ecb433f4888746f754e655c51f23f326cdfeca1b876ad1a4571984221a88daaf0d6f1bb6e2db41c7a464793faf941e0e4f02c85ea12a2eae27865193b39700321ca955f16175695529ec9545e7d12698aa3b52e36ef1c581918424cf6a293ee7c0718b13bec2e5d21ad9ff8ce1d5f84119db6ab1c9577e577af0afac3c45097b25efa2f8964b93dfd43dac4ffa926df6a18920c915878b68b721ca626745b16e53e6b0c2e1c89d2a2e89741e8cc70ab43146e348ce40d41e62e68c384db6c786f1a6864b4da854dd120871933a19c5d37c50e42d04670dc9bec2476108cdb938d94dd38c2cf4d14c5de9723fed394295e38ae0ca0ed7bbc9e64a5cbc92cfafdb51942be630a9680d4b61ed97b3b83471b93b28d3f0e1e64eaa168035080a577fc5116e9e2fe9804d58b69995c2650f440f87b36172db3d3c969cdd3d13c9ac6eba99bd8ca147e8d6f04da68c4b2f444925a8ffa6715cd5cb9330a5448a8e7e1071a5b824fab1e04309552568c3880b978aa95ec424e2ed24c12831575c4c336ff2973dda63498c9f41ce62a93da4277e978637557917db9a856c82a2499f6d61fb2be6b2aad43028c400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003810907e4d3ca27edc2a4f0eeb655e6c693b52b361f1dfe0e1e3b98bd61052d9a3880f411580a3cc99b078dfa01b51e356cab0f5f904c52ba131d192ee30210e0f079097cb35365ad95f4b04696a6e52a1e09656347b0555d31455c870aa302ac4866c4520f615d60d767ec2c66e201a2ae29311607e3b3c480a0404b887fd15197490deb3757691b62c6987bd51d8f69f2b198e52a73f4677005ac3e9b89b0c94c498198f85e65e0694005c68ce81d5b9f753df97b6b6d870a09b386182ac95966c827379e379e1a98d1d9e54433f1baf169596c2774e80b9b600e7131c78641899cbd7986f4d313acab39a4f390e3b49308f60876ecbe08acbb97485a5309d8f6b868d7ef512683f95a8898431cf163a0d2dc63e53fe2f7cc0c4942db082a8c3cb62ae7045fa3600f846ccbbdd8ba153ec892cd86ea4f5e4bb8e024fa80629739925022b43c18e150ccf9be9aa6f4696550b7e0d1a1389b1e08ee42993feead9e00e6d0df676049c91666a7d1292c18b82590192f6f25efa0552e4eb9282935360198356dc828dde37e62e4afabcd655db38cd313036cb3b8f5fc54965025027652f16c10c5bfc57670374311637ce91595ee23382086c35a514b40328f30b42fd55b9d2c1a102246bee241a7d380f84f28f365f605c84a5e6be36802ab0d82cc48426d055a2a6695675194b98901c7b2a052618a2b32e32b9b9c6977b46518912afe4e336d4b6098b55e8480c94a393e9505c8492e16781a3ba8e31618cecd02e000476cd61df5ce5d52404152e8d0d8bb5790f457be427442522ff32b4db27ebaab98321d64b0a84b708d9169a8726a3ad32ee72e84daf50a9cd900e0569a630027261a5e4bdfc08b800a9d418807215fdcdc540c570c5531b490959e526701ed9445c601a7ecc6138f1922b7ad2691c04c943176d62a25629d837e19d8594de21c8cc9279126e80abd3861906d0065c465d9b69f723f44e031e7125a7cc823d182082b5eb4b7155b117780c5168945131867aa26f71a6af1a1353348d3aa85b62284484152977625d658d21939be2aa2365298a935de5a34859f912bd6cf06065a6a52ed3a648268cc0aa260a7358a9f798aeaa153ca1aa30eff30b811c31bbcb8a4bf918a18f88cbb566aca6ad543c93d69d88085a805a114f18b1513155fc31faf1caf9a0e40f7090c60f0c09835229eacd0076fb40eadf63431596e4d209be649ee973d859d237e84101d98fc07b0418d83de83570f88575075170b66eb20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0e34fcf4626248b979a7a8d306cb9ed69c4ccb5cc3729d2692e0ba679d5c2feaac54a4e06d4efcedf78e19357dae263e1b5d107fb09618a9c34f54f19a738a66b95e6f88e20e01f879f53e8f4c371b571e1438ff70e0a8cd00d608976e24501b2ddd323efe6c1302a318cad821c6ffe641672bb80ac62286c69fcffd93422911c46d43dc9a1f00a73e19ebe6cc09a9801f2a1da708f0f1f98e7f1a18529010823230279f487911cef1e784a229d9e311bce5e2d368e6d613f791ddd617d0f37f604b786ca2bab754e8bc4bd3da37e66a54df1d3b268a5a80379a30a52b1532e8cfabe24168d83cbfd61e2346f901c361f771e0be3e03dae8cc30614c10fb8dccdcaa5b9a25ddd8d61e61f60f22308e12adc137d3d8c53cf7b31984cb813758baa19ac178f2f0cd2155ed674a7509a3cfa7ff66d2d9b1e60be50fe7fb79591c500f66bb1d35edb80263f4b696a3dda0b9b2911d01e76e9070d99db93d1d0c3874cffa776ba24424a6b453526f7c44eafabe13c0750f9df33e82105930139e70b5cf1b09dc3913d6bf4a4859f67fe814ff038f0fdab93522a35e7f81002a395989d68b8b7e4235a09837cc6402a5338da08e7c73dc63c43bac42054c694f4931b80140d6b104edec995cebcc5629f85d09ded8257626f9fa4079adef81d044c18bf2277daaa41931b62a6028f89f95f06d8a8fdeb95eb2eb1e90c0d8523e0b476b158e3040f212390ab2503021e8d6fc0733b963cc6188fb2532829925b59c8255d89f10b657053d0fa1d8e76c84826a4609284503d3a101ebfe7af93edc423ef5303cd946c8b570511e38eb04bee0060e678d03e4134f84f279a570aad0332417fb2099e3f1f279ce7d6ddb080c5d83064d107bb560b21183ae165cbb54cc75313de72d40d1cf5173455aa55c5c356d7c40a2a7023dd95d3f89b515d7598f800dcb7bf68b707978ecaf55b794a17559bd1e913f4472b1830783bbbab5f23a760c78c46157fd1b429c445494cdf92fec8bf9fc217d3ce2697bb6c671baa793cd0c1c84f579f0daec400beada799a9f417fe4744145f21c6f8559afa7a514a0e951f03e5e68c17a8e5816f3fcf41774d26be2edc11fc3a42cfcf00f817c3d0fbf474fd7f30c9c3c6be7f74fcc79fa6ab07cab037eea7d83866673a74c087b5f7542804071d53ce348d2e836749e35af0fb884d5d53abb195ae1ee6e9ae35dc91be359bcd510a7801fc243c07dee92373918aa4f8a89eda3895a52456f7244d1ff007cc7b1a52cbef4c1ade1c2c0ac189ab24b3f260475e1d08e7c5bfa30a1cdd71de5ace80d5fbd1d0f17198b79c8eea0365d139f2ae73cab6fbc9a79786896de0ce7fc747d68fa4abab662a09e0e409f7e652153352bb92f5da1836b0e92b0b644c821b2dd2bd0af193ac0f8cf5b8d88432f0248dab09b46fbef2ef1899b5981e9b33de4e9927ae50890fefc35f681e075d8b0169a2e16feda6392ab9858db87ed18acba25575afd1feda9fb3fd01ecac13c245df6972f65087513f505187c4e8ea54b6433fa092b6cd3af13f4718693904435c55d273060fbb5fda76074691269493e86f287922d074e54eff04209b2fdd3417d8436d1395e638d57db75d68f4f819141b6daf4d13a9a18629cf5f84b0cd02e7a397715dde5476bdc467218d11aacd6ce399d9d54645bb27ca43076b7e4e57fb4f7c4f4b8d0aa949719d731c3a927fdef1533d773cf1bb562d5ea43817a5acefe9eb7e51029dea143e8a1d5f76f9bfd74a26c6d38f54194319a1aaabc4daf45efbae770b9e9d834c09fe45c15d4bbc0251d3df2f2f23387dcabce6ca7a59625e18fd997770d164c338d0692af97c749fb746c0d3944ca4b2da6d3ad7b8c3aa922fc029cf9ac5580cfeaff50cb2e9044211ea522bb5769beb7a7bba0743f345feea9aa9da6ec5f0579cf7a5aa4dedc832fe3f65185a31fd49c0d259e3b7f8fa96e110d130f588cdec30d0fd4860ca6673c46d961fc68a4020fb03ae24b1ae12967ec1ed19abec0808a7ef89521152033f70f406a7005819d28dfc556c79de18584088f40be40a555eaefa78e3fa3d9360a7cebd963555cf208dc408a07ccc1369f98bd840f5c940721064e6c7cb241ed0697af0facf36f05632a504870abf90134a01af00d340f7a5d548a8078c2049600ee454d15eb8ce58c26b3c8185cf9dfcdca7d4b6dcdeb82230f993d51e701d8387b06bd45b4b61dc9da6d3b4356f50c1d4ad2b467d36ac092442fa90d1deb014475ac7ce90c974063459dc951decfa30d2de4c70fba39a8b6931217d0924ffa783c8c3daf048908e4aaeaaa3b7c98846278afdd1753252f39caed7d334d8575ce3ecfb2edec31afeb2bbe67fa929a267376293c2b2f295cd8dbd66106e1d9518be1798949f3315e0454d018c2b706fe836fb37ab908d9d698af495bd285a74e4cfc7612d42121f43fdaa7dcf44da82897b820514d66b92983a3ec819d2ce208d688b6f0aacadc0cdd619d815cd231ad8dd9b6dbad9c47e16fac098d0f4279ab52055d2ff765af6e3618c4509fae6ab00fa23980efb19a26e0a6ea4c9a7dc699121388748449c429b28ad2779f5642f05ff58b68ba3e289f90eb27ce06392616c080d659338caf274d46a90d58f2bfed25e8d4a8c62030a5e89f6b1a5f6112a38661e2f2b5a37bcbf050812dcdce9c0a939adf929c921e7da0c30815da318eb2f350f286441cc92060c970077623eee68b8c6fec9fffe780a6fc85fd7af90172951337af57339e98049132a4cf58874a7418fb7aba0628b6192bb2c43102ee6b1d7e824725d9c75d34a8b69df4a6bcb1f96b57767046c99ec6352751e2fe1075bb4092672379b3518ddc884fead5bd062b0336ea88bcbe0d22e066566347feb617a322bec561e9aa9d2177eef0dfeeaf6231ad56d0cd9e300709c9317b3d334d8d2ac97f96cf2f45b8582c4128d95da8ca207ae34d3daaccdb128c11694eee6d3e8e6ab767b6886b1f7235d85a4d9c7c831c5db8ad8323f63927a638e19497cfb308285a03ca2c1fe2ac4d919ad11511ecc6f28e7d0e0a614fe21b57bccdf83535c7e2c40840ba0014247190c580378454751eb3f2361d7193e160b9516f7ee1d683b336b873c8ba22e97480a61f002a73844c78309c0a3b31be30a192a62bdcc3d33a7a5ba1f6ae0404a8558740cae46e5fd15971b41c0bc39665a9b92eeb3328c328b073ed5b3720d37a1c097af8a6fddc3b2b067680e6caa760368b0e1c052e804e9f80f26b52596202ff2e0af7215999eaf7d3ee3e8916744e40aa1154322dd068aa15960dc38671a4f5889fbe709ce1deccfa80b9d33ad2fd963fe0581a2ed7718a27ca62819d05baa3212ec7cc1c5472bcf579ad52d5e1b2bee637d9827851c419a4cb91db57b2a6cb4433c1bd209648f1fe170abb964b272bcf0a263ce28cfa3a9d1449cffdf643e37ad97182f0031cb334a1eead23d63a5c2d0a675d0ed000f37fd2153e1afc4ac01692701014927601203ed2b8a477ccec45c1f43190e4fbaf2295e32a9383fc7915aa76950a301abe47bffaa9c294292126934ccfc173115a6ca96f3945fd5f924a5017125ad5aac705106eb852ef3190a24420196ecd37f7c67b57162cbeb97dfa000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 77&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028d397737f3bf5b0fda52f5dfb8934f4f39718163f472f9f145a59a06aa9a4fa988eea8a465c559b8ed5194c632d4038372509c27517e86ea22722732eb19fcb7dd4582b932793d07b3e75476adfcb7e302da777f5a4655b7c2c862bd6fa182e5bb99fa8f1f0319bcb142cf045fa4c67e918d85b368a4824469238b0e0cbfb58a20b7c5c655a0b2b846cd09bcc273507d7b168361943209d2140fbe59b2dadb7475a73545f42242f8d5f391c91fd9c0d061bf04234c4f315b8e6e1505f2b8549803c5f393517e7d8dab5dfab0241b892a3d8ad1665f0d473b149cc5a0983268c59cdce39561cc26f3fa7328d435990352c736e9eb3a8731179c5b518327d294f5e360ef7b4411aee6b05384f72ccb4bb54b8df1985a7e59dd7e548ac71dab2d022e4b1048971ebeb1184318505feadb15a9af5277937979175cbaa52f5d782e8ff6d4cba228ec632eb4b839b4bb11c24655ac254626fab8f5ee440b5916b4c9889518c54b62c9c62a4f40939654760b78e2346e1a08f26d598470e9c68f0453a297c99e167a6ad32d88d3b1d442c7c3b6d974b85a458bf98935e8727cc8a2fa4c544392be5eb0e98eae1a6da739abefed369332043b9d329bbec6224421f0c5cf1b7640acacd327b4e6e91a1be672c7854d64155ba5c731e5503f968674cbb39a259598f86df71568d12bdb432c985633a6da624bb2587874b22879ce84c1b81a78f3e6efe420bf324d3da646b111b64a2c515cd860be1fe54eb4b47dcaeaf39672d0ed6c5daa91ca329474cf3264fc989d74218f45204c7c193c6e0ca3a9846f4482373c7719b977021242d0ff1f4bd9f4d0c61234a2568140e794894eae03d321729cfcf76d41a3bd53539f0bbf9c49e764e3ae6813529b50bb66e1408421a61f9a7767063a1be6e0c93a98794a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109bd769a14ef6060b89635f60d858c4e20b65b0f0fe99cc4f3a9596448a6f9e826e7e7ae8841f6e5de605aaa12e573e16f5138f03f14204dc722b161e2bec4681651bf8aa622030d365437dec0ba3d40e1279ac5589fbebe81cac2f519d023299460744d5e74184843a7bc4d10a590cc31410143c902c12ea361418548ef712dc8748764953a23e278e5ea0140742d1a210f9c8a3f48c806a8109860cc7c82fce33f57cd7e0018d2d0245e6f2ba71c353522fd22278cf7a03682075110fa92d4c39b7c9a99b12d1f262b1b2e52407d42479d585eb08883b9e80242be600ba265a301da4ab35ce1ca678e4340169a2db0201a23a36fde9bad56f85627023cf2f9d08caf7ea99503720f8e212caa5c8385d5e03a5d62a5a0c0aa152c35116010d08f15dcc25893557294b0e22140bb88f0a74975c1be5a14e3bab2981b68e53f49ef602424e244c893899cb27a3d02cdd567a5faac17dc55a96e21bfe3285c700298b2f66a5eae7d604633b888435c0e9170c1617b3e2a7254c419dcbe7e6a9b90ca2822f5c9c0d72ffa3b04c2a971811f1bba52b9ca4fbb2bc2a09b74d710a6f0db49fcd92a1d5ac62512d6b68cd637d608c9295fe6e2f3be564a5140b146494281ba5dad07bedb7190c4c0e3fc5658ab7e91664de19d5876a823ac44f84abd9cba0d65e9167676026ead1e073dc8c98b2a9724f82ea6ebcc3154c477b16d6ee486da86d61b2586a73cb1366b83168500577b78ee78067184398d9533a15c8c408eaa7fb0fa7b74bc460d15e5c44211d32d26aa7cf812206796d14e24418338b23dba29882fb946798c02869317678195398be26309beeb06c3660f63b6f9909ca9f502f0643027edfb0e96c2a939d4b9b0e4ae7a7b1ba03e485a3b23d75a98f947e0a4c1c89911e4c61a29e2aef582c8714a6503504242a8887cbd304f48cf60167e19601ac5252a6500a944934f972665d599059fe92d9ad5494ee2612c21aaf08b23668180d49937cf4385c4ee87149ab05fdd3cc2ce68306ff151399a46ce7f6c54fa23642a3d494e18f284b20d5de6a281cb637c462413496c6f821d4cf829a421509d50138f8b659999b982ba2f5160a85048f0cbb97ad06d453522304d06dc193583d96a219dc79a2e352d296f072998282f34a5057158fd53a8ca751b67e76d487e4242d293b39190e15bcfc565b546aabacebe7be5e6616c0cc7b6b5b968f1c31169ca9fb2a5cb11368408b7a79bfc5ded3855ab61eb5ada7d37e1ad70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a2f96ad5faef409b8a4c21acb1acb596badf387d26656be3eb17987af59737e324b7bf8412a306b0e706aef73d79af753d9b0064ba9ced8dcea966543fe748e2611709ecd1ce6e4dd8fa812d485e91809a225936675369574b0d104a258e3353ee0e021683615ca5c7c531fb29a5025cc7f7323860443dc19c9858f741eb9d24a9f6f04fc839b67153214116e8b7fa982f338445830f915f7c85c88c23ba2a3ce8e2020a9d8dd7b18efe95563e3924d2a341826af51a8584cd026b1c433ef0221145ba8bdc8f73a467b33a9eb3e8cd2a4d671c17d7c28aaa539d1c5bf2f4138639afb89ce791daf0ef0281d52598f4c13d210974cfa1f099a0fc70b1dc120e5c00c33a2bd360bed57cce069060d6380be2204852d8bcfff4918ba0b70b0bd1e1d55dc1d68db1d20ae713b0093eaefa1e33d40d9bd95cff17568393e9bbf5cc1287325d2668f65dfcf44ace2f6c6cebb62f1433e69cd19e6c6532ea93682b22c4c4a62c6abcfaed08ee64f32723e56205222e4ae0831ab8fca8c265fea0cfc66aab1e367201752aec11f752b963792c071e42a8a1ab80658a0c6960147ed740cd07f307cf6a644a98e1d2e56c625acf458d0bdf6216a4f1b9c78ec3f14850c803a4207c894e61a8aa88840a27f2b439fa7cbaabbc789102a95323e06e2c324859db92c6ceaefdca389f677082180fe3d6202ff60dab9f87e3b84841c0a4eb5974d893333f7f1513e54ea4ae0731ec409f69b77089fafb121300042880ea59b7927e9435eabfdcc1019a96e145d5d157998d620e7bc6945dbd6cd78e94c2d89589f8dc8a01cf1b295a26b091847f034937f764adfd811f52b3aa187f3f49273eae5949ff34b64bc86ff11eefe378825d526509483e7191b33333e5465ffb025b269f898ce1f83ea549f1864b556c729f510118921b69594f67b8c229236ad3aee55bd7082e027b5d342c976a549e01618288944de0b2c77473a25201b61034b334968178afab7f8cd1feb6a25cf8dce3586ffaaa861471e2ee7f0c22538fb3c95d2145965c4673e6489764ae24b4f048ded77fe3487ae175f6d4898f69f9fff276470a93daf986a75f685919d98c9c609c795d4785ae941c782b551ef382f47209aadea19066ae5d3eba7bbd99e91943f1e62754a42ffc8048f7b87f128ccf6c96bd760b45f07f740e94491874b06cc3450aaf55bc664b407c57369cabd2708a9c478dff64d292d96ab71eb997f8b71cdd6ba02f52c5035ec26e8111ebf8268cb00df9ecd63bc0d557e2d2e77a6363b00daf25237e77dad03f929e5e9b39447a70d4e5f4b90958f312c80d594e1b1f3d0d23f2b0d9753bf3544061cf0c0f841c440319e74f9b9d15b91eba1e680ed6aab7d63a97b48c0a4aaf314e8e77e2ea6be9dcfc7b5557fec1b996a37c86cf6941325ec356ee75671726bced7d2157be8d4c62cf4bd0420baf2c4223597c0ef75f7a7c9533d14be0d21c37f06faa53ed5ee0ddb025862417f98d2f188895395cf2fe72185acbea952f55cad7ec2d684a5ab94b1257d7abb565b8c07b88c6335ffb9d2fc6f6779cc24fc3cdf92bb3b12ec54360a7cf3579632a2a65c518e57015df1c616c857f83f5f1aaff693acff210dd1e95ce04cca9a0bf385ed6ea2aed894e79d5133799393469b666209371e708d4d279e1ac5ace28985d0db2765d547c2902b715baed5a4fa3e7aa42645f3bbe1e9f3cdb87b1dd8dbb5aab08626591921cb49e552f8ebafcbcf428470719ae40b9ca847f31848f39e4d42049c5d40b0bff036e5409a6a12e7924148e60b64bb83386079b54486ffc8187302893b8bf826578d9ca03a1291983f21de7f6e65458f8942dc1b135c6c8c1fef4f3863a58db17112419590ae57b9425592ff22e596191e5ba7c513ec315ec3476c95a149f6a5ec1cf24870400fdf46217a23f42e0b61157c3cee23e7916b4475a94b96b917c171b1a34db13ad98833e457343f94a76ee226fa5b9f3066c2fd69f14d3aaed1b31f5114780442ebbc88d0de5f689cd910e7464d73423b9d4e03718c5c51871250d11e27e28df1268166e3af328a80d9d335f2d27d2e91dc61cddc7f733e345d56c11b6130875d93d527f93542fb352407185e7ac07051af7f642e34fa06b1376ba15a35d837c1bfe090ba67a89fc1e307dff3f02a988ecd48fd229733f641f2609ec8db14b1a5ac170b104f03c2509d2ee6844c716766d06a6a25d957530fd68a8de6f1753f83ec19ea2deb1a4f9c7986f20ff60a7508ded6547a85baba70577062e8144ba0496777a5218595e021937febad4bfdecac29e3fff2efe7d598fcb86f93a734e4c573e1496a6282a3b40e817dd3c9d631939aab350adc703899ee3bcb1b5eaf6ea8420dd6eb2d4f64a1818aafa97b73c75610b6005f1edc1ec7d8f8db1e5d3e9666c1292515105037d26f2c8d83fee1f4ef5deeb287cd7c1e11960218c1b8bb50453488bab019435065aedfecd8d218bd1e751fe736442e8d09ce7176a71c06415a30b070693a68bdaa5cdf62351ae665f37fefda9481e62ec181ed24f0d0649ad01c89ac422f1b7e27895e55dcc2fd817346d361fa559094b37894c0b478c68a1d7564d089d9d4417d5c7372a33ba475a81fc129f3259c5407bc7435825b415782cc84d85e69d9b44b32d78fa255a895cfd55319dae677ff89d93a3884ce9401775563ff1788cf3ac11cf96daa199e7f4579a0264378a323fda64fad2349c09465fb23ba09069c7fbc79e7288a82f9165268f6842e0aff0e250c21bbaeefb4347d4ef1cd51161dfd29bfaffbedf71dec93f4157a5c18995379ade8d15db59ec4a8b308c2eade1b7ddab55ce2220f3b3ae8cba7c8211cccb3846a225b438f4b37df54363a987c5c4e6b9d20ec3c0096317d11f982184b75d8effd168b7b41317d40f903a23a2649999db36caae31ba5d91998a684d30aaadbd3b1ec154bb6c92513bfc0c47c673254f42b1fa36b995cb737668cbdc2a0d1ba838e74e0e50b22fc22dd048f48b6d1e89e1ccce5a226f63ac7b8e6e9e8ce27050bf3dcd7d0f35f47bbec1caabd4d619cd77302ab4ff6f56dfbe9f5821aff2d72ee6a628daaae4440edcc070473bdaa54ccd775331ac2812fc5b9884915da582eb36f85c7923f06d961594753802efc5883ca484fc64face42de6c3105e23cb90663a3b381d0c6a7265b740bff0a1a017058f06e39a74bb07b63f883cf914fe675e7e5ad5ad44c9f90ddbe23a125d9be02264edc13972ff22ba48ece8890a223ec13addbe055a8b4e03882677fc0d94c9053da6ced34e132fd83810a793350446d60ae5dd0d174b534a3b6f5bc1b497f9406b5cdd414401b6dd881ceabab12cc51425e88a81bd9e14bda18273583cce0849aa48dba1cfc49cdf29242c73c99c87f063b8b739aa787570459c098405dccef78d6d97c21545f2959df9cd62f9c38ad9a849507c23a51714565642dd76c9103154327985f7dcc701b795a7af8625f06367adc11a7fd7b6abbda5b2ff6a825dd43b64a48ede4eff8603a82159a6011f9e626171e4593c0e963595a6e068ad05feb12378c71ae515a82c293eb7d2b01b333cbc7991b44685aa7513b3a58342ba5d094b773e6a27f8582f3dabf54def59974cb8a2499369b5b64c7ac08d32d75fe37371c578073dc83b82a828dfc325976ff282d3f60000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 78&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028f3972ad80221232c0d1b6aaf6d4b3edfd3e6f95aceafc3774782236ffe0638c345f226baca98c304e57bf93a8ff873d0ea1e57bad4c9f3bd634764c6468f0f0d94826a70c866cbd899cc0909e78e7ee687b62b46128213b0619bb8dfddb5edcd95989c911440e1cd23a061dddd030ef752f973daaf6e3e5414586f895bca5a660f0ebf9903832db6c5ec9cb369270b1798dd9bf2ea85ef905cb25783ddc00ea316a65273b996991c7658d81d365a80d6488cfc87e2fed2095773238e8a103419b4731f351f147156daa661526198bc494152b879443f30fa330cf97560f5332142c411173533887b300caacd6ab16522426e8cc244971da280aa947e967db7c7b5d07cdcaaeb1880e577062f8fea96260e623bd3395aeb9eff3f63e26a5adc3188c0eb257c98e3f8bb7bdd4d2daa51594015a40dd1e3c622f69da2934c6cf75b97eec5ecba23ccf5d12e29795440c25872c9591fedcc96f8230a69341df508a9b14bc60b6e63b532f799d1b21889b2a48f324b7e46493db133397c1233b1c03e7ef95953bb463db52461bf7d67e9748e2905945fe8753985f787cee9de20ece5af0729869c93798b664c9356fef749c7d235f7a3a219c6d98da31ad5d3cace9ea0ec509d258f7b9eb4ee5f0b23a4eca76d73f64d34d44387b2362abb1391b12e5ddd63e4bcdb2e8e7322ad79d3b5422cb792f92a9a5c4e81d9d8a871fc9a42d847990a7c84e49d4eb9893fa5bf810a61d3730a1e6fd3e70facfd75b58a9c379b04e97119aaa1ea51a7e92d0eadb2299f7b767f3751b434bcc48e2debb1d66e74c2236f9a440607d38d8e75731eaffd73a66856919fd7fb5a2d1206d63ed5b4533b187de9f01e8261484ae2291fad5448580560c36721a559c48badd4423fee399094448fcd11434d2bdb5d1b2923e5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381091eb994c3555d3e2e0d75ba34989704114c15f3d72b1391926aa1ec70a34c0177c4a2b927113d98bf87916ec9adf3194f0276d299a3e6ce6e7cae3299882f6d6418746ae643275d71b8d0ea04645c4a36652b21e413614d986c073980be01caedad03bcd568f6df56b377b104a58a9e998f79794879c62179ed5b2769dbf56716ad29b9c5e07e842215cca95eb7b6208b3f2d7e521437fbb39811905e62e947d1db8b460b593740271d603a0317cc1a255a35541ea7418542097b7b4c3c9a8e38ea0c4f58b7a89fa984a9a763810398dd2906450e6f5990661c10ee22952dcfee01c9c1f7b8eaaf1a78babb745748b3be8418659b1796d1b657fc6779011e00fbd028552332d63382888e9c422e1027aecb37d66930e752ad774491573051716f42f1b1ccec6c9efd8c434e9cfb0c283114ec8adaa5984e60daab409a528084c4cf277cec9fa0f8cace5fc591907c264aa5229714e68c2303a608245a89a31df8bbc3adc1a15bf568e50c813823c02efb1ec3591b963ecb7b20a0ba3d60c52a66e299aec21bf905f35df5142410a34d4f0959d54925bf4fc19e53e423e379d55888329676b6d290ba7c56f55f116b02ece3d6a2c26fb080171da810585495a557afad0467db19479b0861d7785a4d570d37474387d47039fc8a464d086f464233d360ee5062465135a6eb66ccb81a5ee7669190dde9fb02522b78fca5166e723890f651b462f36c6c9d578dd9c44fb1872123c06075ed61857612c7723d98dbec631f16b9c0e5b55183a2e24da1194a6a93de05d3ab9eed94d9dc89cba1e111914576876bcb3215936adb4abc8a4466a3864e861d4e739b8b6c4256202a793222b316c06048c652369e0e4c36e762ab8b3efa80ee1fa41b15a8e27284926d7cebc141a3118eed73d0ce46b87348f9d11d5e2a8135d1f7afa25d35dd0e818c8a3fa3ded2b6d19de44a8ebfe62508d41464efdbfcabdca700a91500e00a77400305f75b10767d1edb485b9b6b8455e2a3035e27227a9a038a934dd0b9478c0af5aae05e4120932ab60abe84365d338b892ea0d5014132f20577fd2f05983844990958c6b8ce2042612e30358d555117e6c18a9086ba47d5151df161959312a384817f95df6dcb7199a7d6b10da7ba4daf19c981a6983efc8bf9255133bd4e72d0606c24ee07c52901658c19199912c5419b095f71eaad268268cbaba8aba42794a6e11226fb0f1a2b165bd4ee8112c92a2210a20fc11f0a104f36613c1b2980538c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a502447d338bf1a375b66b77fb96cbe7742508b57dff4d33a368ebb8451c2c67b980d3576e6588d8678b285ef288a8b5c9c2726c4a550e764e47fffa2a128533a7653e480288447509e10013ae1944fffafbd9e2baca0b3c7069c07a4186c056fd3857caddadd5f891512daeeb26865f5c89ffa63a64c85a08e41ebe7bd8786a8add571a4267d5a9e426840a0b988e197a09f3770b5b0d80d65515cd4d8390af40e6150062dc4b8661a8238f232692c152c97b8cd5bfe7b5ad863dc92d99744d769087b3edd81d2e475f5cf0224b10cde6fae8dfc3519efdbe66805ad4468d84d3dd93430363677360da8f56cb58a6b775ff6417c1f324380b15c9ba668eb0f25fc2a690b483e856f3327b2d79fa6259e30d7f76199cfd21152b7c6ffc3fc113f70d3930c08b3c1eb1bf25c100c5a930eec2c52664f092b89614943d9d85ed86a2ef666a94f9826c3d116a2bbe49443e2c11748c977716381d9463da8d09612b80a6760e5a6fc5f59425eaaad6c8342c1ea4beedd5d73151ce213c0b155286ff22cd28e3bb88e0cee39cb859900d1e0fc19f6a7237bda8e51476f4844a316752fb347492a928eeb07aa39abdcc0164d1921b61352ed4ac94b82c410a56505633bad53a3e649acaf64c43c1acfcd4715fc594af6fb9e85b0b7ddd6e8621bd12a2bee48223a97ec8502c16b550b03087b6e87c1a860d36322064f8febc52f2b7c31dae7430870259bdaa5889852e3ae6f61013f5ad0d38727cf9d90c67bd7bb3b82d303c6c35383ed86fd5b7ddec824ea198ef780be830a1f2679d24ea6e2feefb979563f511d188f409f0cfd0050fd418414d01e46db3d23b3a90b24f4e96edd4f863bfb333d6a826d29eed167738bbe22c516c59fdf81b032bb55473a5ea2a1defe71c95a1eeb5c028435ad0379896cbbc76877501b054cf1fd2f6d7a9deccd70d0c07111147ef568dce514de96eed61600029c8d103b31c8b344a700de630276ba2c5633419c59e66577659538a6381e45584c7e1d6ed978ab0af89067ac83bb70deb6f2c58e339a5a66176a54d985da6e02002948c62be6f12314240fe18b09aacbce82ea462586b8316c3e0aea00f9998922f8d956120e53b4178223f4d2934a20976fd5a72027c8f4cb33e9bbcc0abd15395151266b6cd5b4a9e2fc1725d8e9ab2cbda47b507bb25ac995edd51ebda5fd19caf68fad8eac57cb5ef0c6fc861a73e64648ee3255db4c3394438f49377cc4ac2fce1b6bc812e5d282f122678713c6c6d452a33c632c0aa47686588752d72b0586fe5ec2464a6db40662fd2106a19f67dccc45692fca03685251d512642b0cee436c78d94c6f5f25bbcb41fc7e5b1aecd52b846a0b70eac93579603e9870f942ad4c1cfc9d49b1132777c6f1c184c1537178e5029067257a2da2827a2ec44d323d13dc6e4e1b9edf5949d4324228687fd54f02ccc3c4dda635fa546a5a6783959b1c48aa9d9c9f6381ebccd979253460857d3cb1c70893ee6f04709e35923883ee3c71c7f33b8cc28b9136b3ebe5f52b9a76817f2f74fdc2f12b459dff32d5a295be374b3fe507a0995bcacf1e7b24f4501b29f1e8b4f2a8cb394b3e459a4296f6439ba59ec88305ab045ff40b1dab4f672f878de1f9e46b9326cb3e2f3457b83ead8dec28dd079af0e984a69ed882e1cf21036578485dfc2debc9cfe82fce0383b4039d147c4c7e31e315fb57b9093daa811f4ee4568e32e5625abe76c5a1ae42a03441dbe766d0ef4df607406f7d489275e8c5d4470866f9049a4ad5c428b843dec3702e86e177e4b60181d2b5f099bebcb25f04c93d087c72436e87a9b3afce78fa31e2b892400b5c1071f8ae0f78ef6f7d71859a97c17ec0912d5ea27afeace739fcf66f489ec6355a3318f79649881cd6c7e96a881ecc4ff6934c3d10d99f1dfd00592cb037749b025bd4bc2832e206c1407e600fc2170c0bb57e5c7af0756830c2a6913e2b9c60575cd4a394f2a65c50e40a43cf5ebca6a8a32335707ddf4633bac7375dd53e24df20af30203b514d3793392e38fa8429b050f58b28cad0146f385809cc7faeff8b71b2bc93d2c6f72e31ae2d07cbb3cb7f43540894e01654edc71ccf4f361a847ec5b1d23c2d4680e29f0e1f992eda3ac41ecfe614fc010a2eed1bad87a7d17468d6fa5356edb25e9008a9bb328225f85202246816e1a542e1dd746a5fd3e064faa1248579d31cd3d65f8fff36f782622402db328c7850d82d8d8a52b897353a2f8b95624d2d958fc1c3ae6466eacca2a6a5e6add4a582d27e07633ccf697fa02e243a4fbb3dc727b718b5ac0fa6aab217e241627e69ca46f05ed6b496a739a29edaeef76992a507130715be555c68a7eead6e8ff3a378d8f4b7bafdee3edb9ec094440e31bba717a9c82a117d05edca2370003dfabfb2efb29510466f74e76ceccfc41709fac4cd8eaa998357170a7a293209eb0bb83dfe5e2f6d73c28d5409c55e95068d647bec42db8098f0089ef8a5fc5976bac421c37dda6c4227bc1ae5ae229f067515cea3d794c8d85564af208ae0fcf836b6c0af41477f99c8773d9dd1923c5c07e1fd508c7436ea93383797f372ef3103546a5278a4f59614a5d182344f0431d065c35620d63d4d001d7f626993241362e67d1bf41419858eecc2626537d44e2e23619381e96cfa91b3d8054681d298509d9b99e7aa99cf8742e37637b24136f8e1b487e9571e4c24ae5df307e4c7c62e55c47132ae404b33e5367c6f24d6680be32d20bc58370145486fd5eacbcf98eb7e7fb6293044067af11879e91444025fe52e24617269be192bb71bd9f95356edbed9df352ab56a854f9f531889a88689d3f161fe6155c6c1e8011d60a46f59c7d08c477fa652b559a80567076b4eac29a85d54c66b35d6960dff75a696cdb17ec9a7b74dc6c3652dae866e8758170d055c4bf60fa1238448cc9e29160df50160c4b0dfb36bca40af0bc5f7d490e7dbca49535742eecb90098a0a0fbbbbc7af25c0ca9bc039dfb555dd8431af188f7c1d0ff786d627c058a0b9a15f26b58aa2a5992bc8fc5aa14025ff95f294203b45ea081e28f094d0d4ad671c885e67b2e9e800f10048158698d56648f67bfa8cc73dd5afa15c1e48936b2596dee34459b484336c20cd77e58bf682479f9aef2fcda86e4f3a2fed7046e5a3828a9b3c0dbffc25fe699f25629a2045a51242e310cb369b730a5e81167758d7fe843261a598e4541b02d0db4bf5616ba07a440665f7fea6213114b6b1b38bc033d70e845445dcd18e23d34d3d6f4a52f5f904ac5d8feca5af1123658d09613209ee19954174a1ac7a8c7f9ea288bbe5a0705f3ce38f30ed5ee69cf5208d461efad51c456507c3729eb338ce15c4c253be21e81f082b0847c6871ca0fc8b3e80115fe2bb8cd8afae69a3c1429d21f149b7446888bb4dcb639819efee665b6d6f69e61452b9328b4887a7c04e9949390980a2609a667267035b11bf862c1131533ddafa518221627e0ee7e4009cd48e4aa9d0753a9ae82aa0257b69d569b4c53f05a75a521b327322c60398db0947d205d2a33ae51cf2cea8c9162dd604f8edbe91f5199d19efbf9896a46389e7bcba54b4aa57cba0d4f9da117f288133ad01a9a9b2a824d54f74d4172be2b1e5f0d3de60c13aa5b668ee6a45397c2e39573ebfabaaba48d1ddb2ab6453fbbac8dcc05349404889c7de23a16eafac8d5e541457c32cdce80cbc00000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 79&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028c3929f2430e44097fa6b3688339cb53168afbd1cc53e93bc9c0b086f663271686b79d1dd8212bc309abb1e2a95207ea2b9695eb32f744793a7d66cb3c7368ce6f45d244b5b53f92014ba55a3b93744cde710bdac90fa0447449c684ac599e289e3da47c116565b4e3df3df46c52035c97457468b26a80ab8dbf09f5e7cdb1a8aad1d13568b37991b1a89c7e6d05c2200d7a2c8e6d1d24c5abdfacda79374bd5de25779486b423ed6f8730be6fbdbd4fb9ee8e32db9df1d54cca074211a1436158b44b219fcd2a8a5e56daa0d09056f70eddb519187b185ebf489b50e5bc547a6ec4e255a585931944857b3390629e7332ecbe15fe877bf5bc0e6661d4c3f3665209220c5d90ed8a34e14e1e055ca76808a3775ea1b7b4eac40e61a3842d7d3db3492bc8695b818430767cf18b1cfcde27af4eac2d39273fd6ae46f21baaecad45966ea98bfd6b592683e17a320ccc4f7d5f55929666ece29946d64795302c975248c4daeaea51503b371c8c10929a2376caa8acda7ff783a58ae7e2f945f5693ccc86c3ad1fd12374b88a2b99d0e7338f2b3e88750a5e0eba47e3d43c79067461f30cfa5462d1e8232d107434482a1b7ef56c3fc41a91863256cde8b85cfe7dac9c94ebd3c801908f21bf1ce3086366cfdeb20f31eb5057cdd3995295fefe498fce2eb02eb03729cd6b38d6a45df4c49ea6bf27d4b8f04fbe0dbc46a52ba4131ffea99057e28767a6981f2fe91be5e7cd5ce1c16ce7705d638dfcd722d17233a85ea3af6d9c87205013c1dc83a4a8b93a4bfa4c1795aa87ccb99e8dcadfabde93d822ff45692d1cb907853cabc9b2f23a826f8aa028702cc6b184f3fffa44628484cb3c126ec1f96c08ac0c934e89b64480e613dc66d195fec8de7c919d503bfc2238379ae48b78da4109d2790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109b3a59cdabdadd5be753d87fe41f35b2efcdac24a9f34ad87dbbc817e91e8c9fbf00239b7a890614f8ccc3a9ea4691b02631d2c6a708388dd05c94635230f906f5dc285d5662da786de4960eacc7d56f0c5a3d434bad03b14c0c38f6ab0ca39d8a0c713be6c2607298f474563424087ff43f241252f9cbe1401af4727691e0bb056740a98d46cf94f57c250f347f8005adf632fa0d19cd6026c364769f1e68aa05964409e81ada1f308d67ad748a87b4a8d2b139d44952a7d7477b8ab88b0155922751ba060f0421b69abc6b3f6d3d3cf25dcb61cd682f6693a4979d57b409da0ad21f29605ad74a2647d5b3b9a764230472b399928946a73f9844ad03136f692401285474652004e8090791e5dd5fac65e0e9408a3ed6d8d1a4851e50345573ab2c6b3639ead5ea418aa6f003f910cdadb158a772e18fa653ea70f9fd442454c65d72c59976838287a6dfc329bf2c6deac72af07bd5edc584c56c0f307ac9b30d6598395f26ef94e4281581d009dcc1215667827128de1d828ba4e66e0c165ea111824d842dc42b72c6abdf4018e649a5e02d6286cc131853b4ad0da10bc621997475d893b91dd757501c0b2d8b68a3ded054dbce7d06d1d27a88a21f5c08e66141c1935c5814909f4c46a6726c54dfab35ab516fc4f7664977d298b506e9480eea95f5e4656bbb08d4f62f220d46fa929a5fefa3104117a88da8ed0b008958f2032d29d2437267d8ae45c566d13a16ed532d49ba396fd1190a5e23a1047f1f1012dbdbea54227133624eefe8af00a0780f518da511d8fb95c3f1051cfbd50be3679cfe58e07bea649fb5539239eee97c4dc947c9078c0432d2e4f2c95b7922af3a5a17b85c667aa19ae37e4e19e864e3292f69969f504b6eb22feddf8988c8e68c482f70a40132534ab3c611d6424d2e2df9b1ced75e8e5fcb8867390766917226694a4b5114c47620503e4c1cf9e1446308b0cf04786c216ba0c282e426b596f171667b2169308a17c70f15e7b4d96a45d6ec8f441dca43560d53036a93158c69ab2fbede3a58acf2b3fd196792697725eef348949366bcb8d80108c3ab2f4c9314f96f4b073088334a26df44e614c019dc5fbe523d1b3845f8b92523c17dc3de1c91f0d23c54254952f02bffa422b80d1444be2e4a0c42c5bbf1dbcaaa001f199c4ef157ad15179edffa359e916bd26fa6bc297a09ee04be062d97e1e0809d1d2d0df9e12105b32238aa886f36587dfdaa61590076ed77b892a9abb6485af000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a71aafa792bff719a3b794b2f8198ebd1556889c8c61ee6a51470ac9b274cb162af44a26e2ba5ea7663c4c78b4b66b322ecaca8f2ebb6a610b51d7c4399f4a64a870c038797cac80f709ca5c3c9faff7d797963e60983b584130c1b99328aadb2d261217cb95a535b8518a78a6d2f6cb8400c2aaa2daf451391f7b8ab0277a3af88e1ce6f1d3dbc386cbaff15308f073d29838692e645f566d4b3db4186c259bc84606855ea88938cec4f7211bc9b461e39dfbb9e44cbc273e02d4314a037e0a26d60985ef5a35f069d8b51f86e9b6801ca067ab75565d73581ebbbbd98ecb5af47509c8729d82ea0b35f0a376ebe6d90108cd61fbd0cec966c17264f6a87864457f41162ff7210049e6ce2b5354f8f19161e0866d6bc3935815d9267c600dc529521fd092b126ec440d49b8e3a166587657b52ae9e2923644f72876ee94a61d2db0ef4dab33abec0c47a6a725d4cdabd06d4f6a30bd7c90db3778c17b7d8ce82a5123b798d8b47c7f3e968c9e9f82a6eb3c2bdd8fc06d282f5cbf3050f6ff71e2edf7a109f23ab47f427bd75163162c37722bf70a6bbebebe8fd9c39152afeb78c37d718014f739f20baad1597b1f9c4e0b59fd82b834d83daffc935de4a3272d7c2454508c07502943e90fdb56128d6e6009ed09ce80a9b60d51aa2e4e162f7f0c362f6886bbcabe29ef6c7f38b742000b9d152ff709082fafe809c5dc9bcbc6f300b0a7840d0d36f39567d14d8227e7145f7ca670efe917e0f18b0570da3e05dde56883ff12bc0c76c2a1e9feffbb728d991769b7d0b0d34853c76fc0655ae200501c28755f57934bb9f46a3c6ab1dd8e0161c698133f4f2d7caf3392576b4bd2b6f8735d80bcf60656e132442bb7fcfdae160a2dfe3f3fb8209b5c933201785a7e8206096b84a222a68e62501846273f6a9145820f87f450d12c64ff79a843e897c8394ad54aaf4f3b886fb00a6c37b2efd0f6d4dd639c9989e7ca30e4f12eef440946b61d7a28904e1d74009b6d1aedf2fda8b5991cb37795a8ee51bbdaaea34a4c7040944761b9b4b4c12f455c536992a0852f7f07a9aeda8e522591cb4831b0c79fa977ab6bc49c9730186855986035d2c6e5a6d93da43e8825753721978aaeb433ce2f2a7d67c1ffebfea6f6059474d3022817a7329d9dd0e4a292302e4a57174b9c5346e4b6d75d65882ca7339a48c6e7af776a8515014a20e4390f6b4f4a19990fa725f5a69b9c3bd4e8bbaeae49979ac19600a3cec6de154985e236c3d0684269974bfc82301ac7196675f618182d7cf15ee5ce3b7abee0deea5c72f54cafef203d556b31327089a0c0de94f74458cfecb481adfe3cbb5da422bd3626b00c4572b4c2bd7584acd9129a76c616aae51f944becc4682aacafb8e3bb1a42a6a8e5fe7bdeb43305a34a98308ef2d49ede4f41361446a9ae4dfc1ee13d12821be0b01e55b865b563633e5a19dfb6425cb60159c147b18a6419f5085c5d0882656ed533eedf97674d0babb6cf32f696dec0f9921cb3dc9e6021fa198d554b1d83c42a0bf214fe4c0431547384f45aed9190cbcf98ed8278e8a03d551fa284c8a26218f0b0b58d99879db98449cc99b6b399dddad9924e6a7eb20a0f1fdad2f8138bdc7b445bc01503c509066b1603cda76fe41727ab5e027dcb15032e8f66bfa84544d22c501aa6f62b02c0f8764387163ccadbf1ed7238e7f16c80e6c37afec2e10ffb95ab0a39784f9fccd8ae263758abe392727e9ad442a44738d77cb61a6b1540ade751130489015ae5917c927232eed27bbf88481f3ca0c5ed2c31dfa943b2ead4a8c80b4946e3c138a61baf43a72c7a25e16874cbae254d3f14c154f7c60ccf665b566799a01e0f769b60f73c17c840e0018c6fbc10eeda3e35a77586b3a5936b363b2d5cb25c78a3e3aabbb84f1e64df47f97ae1645650fe1751a724ea9bf80744d0f33da6f313a3cc17d8f261585b62a75c167126d899219a26210dc55ab6db2b94e6993849b4986f988efb07478d6621cbf4b8ed772e61b0246a5582242fa20339b2d6cb89ba1b9210a318eb4697fd21efcfd230de9680514a442a13b29d8cb2627a6970bb97bf09c79c6ed7a27247662b25f39c8d675b0747f1a6d9ebbf7cfa7bc51a7ea3a7307ea4fa2a463bf53a645fe701fbf26628731cbc18636567ae633a49e59f6f049447803fa3d4f1f79f38026de9b07d8610c9f01befb7054aa46e523e001c1ec3a4e7084de0cce596dc63d9c1f1dc03f35f9b1918e62acb2640102e1d520e900969d53e83d2dbddc80d1dc54bee99531faa5a8d2dbf8346c7ed123587353dd63823453de350545c176446845bb3522a862f5d675419da901cf7d2d1f7050abfa3237d42753203be251b0364379232d2d9d8642d52a60f6f4cb09ef29fa1e6069f97a1175f8447fe98a813cc182e33ffd8b8cad93bf32a60f1a9e63a79a7f7fb9162783b89bb57f3e73155ced1d0084d5ba967f76c89c61c1a3e944f3b6f78d6cd3d1139a315c5276493481f3fff9b6a6b40c920eeed9efc74108c6bba5a15da736680a23db5672c5a32abda24b49f2011f44fa8ff9c73609ec195025f0456d753c848dc6296920fc32dde2174d37bfbcb86cf618aa0d486ee46c5e1ea14a3bae4952af5d4837f9b8122a19d1e59b909aceba6c849c8b452cd6cef877a65fd83e6d0c6ee35886688f1d877612cb8e671d83216a1f76693d6a4d6a2ec13eb6ca2005328b3c91f51b352a707ef8180f320d6e1685c1ef4d87e3cb77fa549bc12727e59c11bdf8a9631cc272998253028cecee8a2914182b90f586d80e7ece370979bde683f37123090012ab9243a4c145d6349c2791dc44e54956c5e9b59fad017d3ea27d85b48a896671a0ac14a73b5ab9145d8ba6aebf9ea25ac2e8e2c4d16c5009a83d0e84ceb80e95df2cec4cbefc7f5b90a84d408e8c4855f9aa2987d9fc9d8a451f32b367bb1de5271ed35ea153b5d400a6d8050ee82f519bd930245a96c9727fd24d8b94dc53d4b4f00d03172cd6b7f2be163b6d16fd6247b01988a6ee6ce7bfeaff78e983b8ddfba4242730e52b57876e3719d1f9f6cbcc81620f848d23c31e3fff7ebf2afe5011e6466b1889e7ef6281faf8b18a012ceb96796fca9b28e78335dfcb85bbeafaebb0fa75ee2d0d391ca97e05f0fe43475135b13613206a0d88438f17ec8e604b007afdcb9fa1378b7cb96675e0b19dc6fb02508e05a7fdaaf09297a3884aa051b6389a52f921f8ff31970fb082df554226c2613b80cc1adff770024d6bf011c0f028a012597ae56f36eb6b3e864d79639810b8ba7258b18192b5caa80dea4b140d3c6f1d707acd2256d676ae90980ba80e10b44109211aba830ee96e1bbd248315c804d391a86ab7d4b3a4a37fed90d9867da4b93fc32e79403e5d78ae99af1cd2acce65d4f3384d9ceab71b1e93b99704c64caf17b999234361e378b9362d14be3fd9e6c268013cb1fa2ea8361749d635c0429f796eb15a685e31dfe7a76ae870eba120331ac830f8c486f6c0c4f07b658ebb9274a463e0eea101481dd6b58835a303ace802ae79ebef51add98a67b7ff7968815acf4504b9d360f7c0120a00aba1fc558e6cbd8324ec35e0985294563a8d7eccccd9e3d1557a09885770836eccc7aee0f18b81e30f85d695440b5bce29945cbf60ff402b281942d38ea33a4b03e9fcbbbefaac2c455e8a03ff3f35154132c538ea16f0605efb788c3ca8435f6d595f776433585094abc75ba581ec59af701f66dd6091623e4676d167000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 80&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028f3917abd3d4a5cdfae84674c788e7c11967feb08e6d1da8507b63d90eec9c018650ddd7c23cd1804da9b1c3292493edb6788f821bd24224a8cef50fcd7562fbd3dc285e9a252b235fb944f1712615c3be915cc69583378a3940de99bf863969dcf81d6e6f86819626b103e5cd257b7c959cae312b33512cf6dfb8914e3a7ceeb58c45d2685759651f75a97c37ed1107336b37e789218120676212e166490d6992c747bad396ce54ee7923f094a79f0e489d33f547c9e09269fa9f2b201125936a828a75115f57ec2fd5ba8b4656a18bae6567bf64f72afe224b0ba7649b56f4835b4e0ee5f5fcbd6fdc0d0753434fbce4e2a2bbb9cb66ef58b3f3bfbdad5769a81a44b896a4aa11d2673558cee2d5bdf66aee68b18cd72cad4246533d0401d9bad31afd56ce8309f5b67d93c4843b0c1e3b1afd9df4eb64f712535da16a2488bbd8863a9c7e16826c8463f06ff46ba5355832ca3c4dd0adfbb13e5e76159d6d8d524ac8e93f7029086a9c8a054d8b6928700ed10c9c57090b38803c2d340cd2d2a77de84a6bc8fb6316d43ba13de8dd6ffb6e4421fda641ca4a8c86417db1fd877e38a21a9f214cd04d244688ec768877110e354aaa8ea5a6d26ee252c7b2992e04fd0891d8f6440a2cc4493d3799672de461d0422dfaa539643a69af42f3cef6e58ac476f1ec6e7595cd4bb4ba3af76d76e9120264c33339f87e6a22ec310c751a5b46a3f3d1d96920b927f5866eaad22012a4b220e752ee52aa5628536da8ba7b43a3d499d3350377723866885ddcb755ede5dea76c633ebb57349a99b6bf043133fd2cf14ff5719b36c9574f65548424f260937a5af164f35376e8b9276ab12c53d6e13b3b285a4021cf256b9517c834190b95aff18b93213686084fcaa2250efbc3ad3e06254d8f12774e39e940000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003810922aa6c4a882cdf3244f1b78bee7408d03ce840d6463cc5b37b4d0b92a199caf9efe7d3833980b4e2605f3acab79b8b1dbb6cf09479ed4a4bbb7c4b480eafff2b35b2c6f1518c3e46a2c1f1cb73822d5657916c300a1e67abe44d205e4023f089aff032b65ee0ed913385d2e94a500fd26d0a2a612320f732115d329d598d651007b9fc162857ea60303718b2b3e86d3744417ca1c8574123aab34ad629092e8f894b0692dbe59596b069416506a4cc2b6a0498b1d5de698c2ac4b683c89b902857d68d378110c3c41ac795965823884159507c669d21c0a7143a2a83e87a2280ae7c3248a1c908716cf6845c0a66ad562aa9e1e9ae84c5ea081e945157563cc4516c0cb988aa653ae5efab4e21188498903296a6d8212ffd27d82001eae8577ab022c49eef6fa64dc5d43f677aa1781892c650cd7e4813f82f6a5144c094dba4818072a8d36205cbeb9fdecc30c7001f8efe93b1b004e424766ec775d1f66a08db66340e2e6ca105283fee6039ce9a394b9c826f59dd162dd15a3144c986f460fc0db8c736bf2c03b67ab61115c4fa422057576511fb88fdced24b99d0371496300a918e57f4e298dc2fac7e2a320adc5ba37132073b531bdc44e0fd58682d4784c6c6b3dbacf9849d5bca1e210d949d7942949d71997156e1221a5b4926fd024b0f27247122616f9a405f903e654e4b69b3a480207b16130be1f1a1932e5b8332d49101d811b11def809ac05c5ecad9c4681411bcee94097aa399985a92c3409e5d4deab90376c8a509715f9308c6d55a34deda61ef6b14bcfff6b9df73156d3df1a6000a8021a7e3668da017bdafcb16229f20b93f472dc32e32288e8b86e6cba8c28041a0ae136221d947835bd7a9344d728a2817ae4ab0977d5d96b90249d088d9629000c774626ae124a13e3b7eed820084daf31caddd725e43317b03284b55a35a94562d3c7400691ceec018acc327a454d750a53da0162c423a55038bac96832c1974355f60118596fc86e91a542ba8a227fa1e644014ba05ac21db9ad9c53882c31357719b5a5cda5b08f280cb1a8c0a4b5c970956870202f87d109bd4788b013ac5f75ab780b25a633396f5aaa12003ac1e090a2c8b753642d5af55697bd9c1af7160c01009915e9ee926ea6bda4a68ba5930d82fe79f013ab33395f40f641274a5015283962c359f2673a922e8b3fa8b9303e5806258627d793ce06b15991b384e2707bb5e1d52e5394ba1c27867e4b280f526f65912c4b1b12ba3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a9263ec08b711ddf5c66036a13f574bb7be76445a1d1f83c7732b9f4c25fb9e799d4afa55817bcb39b974af92f3730767ce7d863b6a3406450dcbc5e0145d10b7d532da6e80196157c38d1b6d3c173f74d67ad8df24ecad4d9b59921418863a38270b982c4392225edd1845aed2199e2c38b36c7e0e5d2f3cc7f6803926d977c59ecdac67ca290658e72bad633358fcdde2a4b9c40169a0c7cccfdd93e4da3c3838e9308533bd468a9128c5a141c4842840e45bc8e4610a7c5e7535834c5ec73312a50197c76ae984b3521883f549be04e27d97580e6d85d0ee84cd0b8c65bfb1aa005c607de82da70021f8f90b7912c67dc5657e1882cfa6da3de1ba4ed823789c052649debc9085c74528162243133a6ae5c1c6bca3f730525b167d816485e40c208affa8706e3d74631eb4413032730a7647548b77579323eb03d36c2ec37d2389d4a17305f607c78f3073a2f4b4395bbc94af163acbe3c990306ba3f89af9affe785c3f6d102fb2bd55f0c1044034d6a871293b31a1b38e383cb926baf3ab4b5f79a47e9fa7b77bcd58aa35a7f16ddd11ff642069a8a327dfa800049babaab4afbeec9fa98adb9796fbee925bb70ee9e96540436e1473e3ae4c56d7099d8dbdde755a7e101bcceb596b9415f52374c8a3a73ec66b229dfd8cd7ee7d2cf1c5e7f490c7d9381d9321b15f84f640017851eced1dc80d32da3a0a57adc3ef37e021031866e278c7d51ff5ca8e9ecea1082423b41d772c5adc61a8c71c3d4caaaa3433928d7931ee715875bde2bfacaa0a7f799b45241c21bd2ece4a5944fb6890bf24908de58dd3c76173373254a36b0b2ac7d67926948cc0136dd9a5079d776c297fb6a585c290d5dae1c45e91153299eedb731e527f0f62e83c1e93c75fc74f9c7e63311562b0a55459a0d41e034c3af637eb29bc789e5920daadf265f42f2707dd1ad490b5f8a8d24a9968bff11a0c364a779ec385a9a33edb9cfc7dbc672ba60ce5f421b40634270b982d619f8e7960d32e1b8a76cecd13a3b0214dd34214cb5bb7fd530058d5de1fb9e4e88adca05926ce1f5597100f55dcbf64d47fc177ff87c4bd9f6ed7670fa7b7d339edcce6fc1eae069e0c303138689ddfd23396c145b79afcf68125989c8477bfc318cdbd69d1aa6d3ee41f4b1f9be4be9fa58a072412078cb9196556ee56fb7b2a2761dd04120fcd9ae9736f599c8b96bf8f964b305530a6df1f94874f36f07962f87acc0b285eda64d2e4857e26bed40e9a5dc0327f1d91259292c608d6c6d59804dc23a34d1f9f1b69331d68771e41542fc5d669cbc3cd7f8310f87e8fe8f6201e57b475de2318ea6ef9f7d32a728a44334cc9df28df77038c37cba62ea8cc5ee80e571879ad111f35b6a154fdf8d40fc93360d547d02f0743a37ebc4af178c6ce36c92ce6b80b6350202d2978621684a19afe1474155bb962014587b1f5a477092f42bc446d7811c0eb439a6829e538077abbbf03f515f1e6ac018efb05af79069c2569d2cd7140c4b1b47886064dac695d59fde2d8fddb35318d33edad94ad4fd988095b1156fd59551f0658ee666186369bfa84e30672e4659bfbf7963c377f0039e08de2c2d9803fc12d97b5e67ce9536af12daeb3b9903d8d95f336ff53286284bfe8d7ad13ec21c2a9ba93c9a97bd7f6148de7c8cb41ca75a9ecc8f9cc68d888faf6b3e75376b5b16f41e7e6b76a686eb365365e2074fb1d7efb1b285a2357b020fd3e47b89943fbc1596f3fa8289ad844386a691f33daed4b7a6a6729526160f2d32ba7f68ae6678564fca05bd811f208a8fa62f6731f23d46027008246fd4bf3c454a39ee225245e74da5910e7937b36661548a55a2270a9d27114ddc94dd9b9d4122289df0a5700222a977f15fd8e36afa1c4870bd3ce9b658e2d83882aac5f3db814346240ff8c8fba3f36e52ac9b441c76b6f104a0931bc45e202addcaccfb93a486a7734a6d82b9f6ca911448f988626846d413d987c5ac860fcc0d5f734269aef88d41a055794dce832babb7e306f622e5eaefdbe1cf195e320a1aceb4834b3e70061ec2d624c12eb35b16e5aae73053a3290d4bb1f51ffdf48c1a7218d365db7fec15bf0f710954cdec54917600014bde3a901dab1dec0844d7ff148eded9788cc85c0cff26e5895d91c56ba6950c0ba8fc6c773ab4a6091a5de3ac335ddc2110eb0144fd89b3d815ef4a26f718c1acb5723af1da5515442a03cfb9d90623fb21d78daf441000e285e9e7c235c0f31e258e6b3feac048db652b83e07848d2e9357649372b1a55975b2ec7fcfed19d0b6613bfdbb4b5b01a9aa3128ae137bdc1d8ffc3a38b597578042cf183ba8383c289c3d92f6b70aa9b3364e9fc5d43f3cd3f310d229912e91d5806c2a11e0bdd208a2af438be77b43680e2de67918fd414338a763910e1316965bf96bbf7df639266d075e90ee9c073011f6783750764fbe4906ecdd94ee9fb7e4aedb23ee88ebfb018c44fc8bafc66e6b454a3d0e332c7a6b34c2e8d1d26416ff43d768cc36ca9d3168355f1a281a6b2eaaeac7b64aabbad2156a1d781a78a896248c56f3491a5dda8c22c231aa7ae14bd558f66e6280fa65f20b246d815bff1d3c6cee6df9b4aa7f750307a7bf73850e6bcd22ca0ad74b4afc13cd4aa2fb7e7b588adb3a46a23ec88a34f13214b261a283ae8fbce8007c6ef6be255c33218aebecd3ec27edafd252994b70bd67407620d26e8567f4c7f6d636803b6a27eacc3b853706a8d57adbf7f7e142ff149c35119a6172d5884ede7c71e6c34d1b485a684dd56c9d670576b75cacb870a68ea7ff2bb461d9e2fdbf500b2f200110265a3cf24370a3f480da66f98fb5327b4cd796eaf0e559a5519f3c643b59e3b89d05d2a9f9da6732cdc2996408b7fab5a734310fcd73fa3fa5cacaf31ab04ec0b9734407c6dc575350212239ac9092da5812137bfc40f7735bfdf9827f768fc0363fc8c5739c7df828075ea2bbe6321d5a8ea2eb7e397c3d58a953c7f0baa69a96ac8110b125ee2e9701f43eeb87fdf58a6e6266be1136437599e26e8e6e853dbb6ed9df3931c5f402fd09b7e203ab36eaa6eeae72e908bd2b9cfd379bc9b407f0c882807bbd2e91f920eb24137002a48f1aaa0cbdf89fde5c51079f1d8cf7a014207f1b40773321ad952d77ce18ec7b48f2ca054e65420c1132ab67c832ee22ffd8672803cce3de7e9fd0690e55fa1af5f11611e3e2c71ced55e3e347f4cbeb9c93bec2b98e48495585392471af0ae589257ed8d01792112c798bca5107030f207ce567594b8433490d8ff1811f21b03a42ad0678927183321355e3d6908dc1125cdce038cd0469d72458b6cc5e67eb0d78c20819c6f3c4518b15cc63754ff8679915e329dd46feaefda5249ed7e754e7bd55c75cb764b6cc36bc06267b2479cafbb3f0bae32a93558190b65c85dcdc080cd56d51d4105c5b0717691d4db1893ef8ad550f55855b4123a38d18fd67b588a3a4c2a6604e874d721359352b235c17ab1da2758712af8179ff433211b93078735f909f985f557d0de52cb9203ddc67bf9dc8632acd8d4f90196af6bd2e79834371c5e9fdf5992adb04aea186af36f56271f763acffbf94df4b0512ca6b7ca8ff486504e565bda367e044fcd0f25fbc2a6c720867f95bfd92109780d2e6dd60ce90a4ca8eeb8c4cab289dcf99e687b017b37695c3b99b4fe97d7e5d52bb9813c04d03c9ad71770fe0986c7f3a3ffd3a261ac771de88c7acdef253e5ce2b50bc5c576d132b68ccc694ba883770b80f5ed7d527cee816527f69ca2c101747a0088879c3663037db5b0000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 81&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028d39066b7fd6af8283a781ccb32fb3658b268680044ad7b15a87f759d02fefb8bd5a089f529637702c7de12db83e877280dfa07c12890c262976d350483fbef8e65deb6d1cb4ca8599b5625a2a9524a9e61cf217c956a9dbcb9f562697c28884fe0d91d81b9bc20fb33fb6b86f46914212f9099ed3cf2a91fe37a167c35b8fe4e5a4ef2fef656bf4f21d26e14e57f2f8aae7b1b4d7da60b2ad9628645c99f6f3e4f449519bd1a264e0c43d4f4bf7b41eff53fc884258cc4b0cb7b5cefd0dc6ec6eb3394a97e6efa099d28bbb0f8341e7493d0fbbccb1f14b31a6c395128a88e9bd5ace41488fc85d7bdcdb97c28bb256921ace630c7fde8b82bd20acfb9cd67249feb0e44df04de63b0db94df2881c3453631d135dd44bd060dbfc75d1ffe26bf1c09f187c7cb052d854146e5fe52d06da94771ba8a131edf2fd5a8aa7109aa54af29ffc24b9d3749169bc2bca76427324c55982aaaa338b3f27727af34b8ec1a2497434b5e8bbe927009146a0581e5c86f71994c168657e00fa45b7d69cd53ec38faeba4d51d4f150f07a644a819dda79d4651ccc393af9612edccb592466b787dd5f785ca51bf71743782cc9276836d49408db28441120ddc06a59d71ba68b66e08404d0bee302e8e8d2a24d0bceb3455316f1a77fedb62133f47c33dbf8b9da64d3cf2f1eef2a44ae1a38e1cc8f7397be2e1bbb38d4f9e0bddd0a853090b9d3b8c6323f752fea6cfa30574d4b873cf7929b121d8b55a6756aa9378e3227eb733d79d8c428ffc3f225bf0c8f612908a65cfb3069ce88ad7f2c770e6d7d0f47e4e4313da82239658586956eb51a0c622ef767b63e320d2de697be8ccb0f4575a4174514c7638805da90d971d92e07d69d35f962736bed376bc179529f6d69578b78b55e6f66148755542da13b80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381092d51566b5bad4d881d17934a9a620cae4471c2eb5daeb1b556bad7bfa426376634e3c1ae86c889774b46a33a10ba176a5eb3e618240d5f4c04290af9742a652815a6a454afe282f43fca33007d1f8c87894b6860ae1c05c4d090171a6212f3976e7b96a2efa1c0e604b6a9328bbdc9478ef1ac890beefe777681c04999a47681fb7999435e3c4c0ff0044aad3ea22ae669d8c1acf4077a73d2d19a404b63772821af0c3119720f278c2434b8daad3f5d5e6224edc7849750306a2e9e1db2588c91dde676b489e5ea8f9f069506bdb2074a5a96d6dd423f1bf09daeb383f29ecb215a3dd3542273568de29a87980700914b10ed04bc22cdeb1911945889cd0823b9aa2825a6895b240d56a20e9b7b81c7c051cd88fa0e0c9d69515dd66184538eb06352a39dc17ce8f597db6a3c5855accbeca39369159f228d2dbd696537f6110eb302924851a85ea767f0a7e9e540b74c45f2f9c4dadd8594fca87e1a1d9a047a87a39655535a0bc568a9c476290d65c3c3b89e45a643ac64d5ab2a4388b89bacbb16276b8e6b7c7821cce2f21dfa68b830c5d8e9c19f3a96608e6d3590b2915a78ae513b888cb41e287042e12de2312d3b5356b156a2166943858d400b2ea07b485113579c4f81d2c8e51e9acb94b678739d83c24391ff545a6cb6282a2cb4f96a36a90c94d11f0c75707872918a2bd054407ce4c1cf0bafa89099ced89f2b20c89588af7667469709d7de374f80a1a7a9a23939e1e1c92fe28593b1d8386e532d9a04f29bd086fb058cd5b2db93ce810572c3e9d820b030fc27d4a66d6ca5fac7394bc39bec95aa39a4cd85859ef1b7897f27c9b14246694c039e2e0989af8278d19b02485df2843a510353d6ca652a3c102280b7451d19c0a39e42be89ee296b4acb7004ccb9a6650e99466e58225847b5a8e13842432306515287564ea787d2d72bfa23824a3192142782cf4bb148379ce6cb0fc01089e8256927b28887a16fc72632190b52e3c410a4b3906b6234bebaebc17ce0a395d452e01825968f6cba44e2ca4832c2d01357434fa45535e31cd6f8be0d812a44a68d11ee8c374a8a8227c2b950ae553445e655266194a48ed6d1c9ec8b7263e474bba192695df0541a4e0821bc30c90b13eab23924155b045c6372661ca39aa944a8141b58d5980d519c5088d4295779e5fca8be0312bad6961ba285ce5b1189bb86e44552d0a627efc01f1ee96821d9a26047b4863526ebbe91e9b29a2edba898b01ae21e05ce000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ab37785a08a3892c97d5ebfe52475298ba444674086d63e17e1faec96f6b10723447fc1b8cc758d1724a33e26518798183a4b3c99a7da54038b86473dfab8e626eb3bf54de5581e04450b2821f5020c466505990b173db9f030cfcfa505aa04b37cf0a063876843a042f17aeb1728787187428f8d1010d532c94c7ab2e1193994bff0cb56415fcd2a96be7f7fc2c57c8313e795367a22b6a17ce3b803083a74fdbcf030d91c957128099d6199686f2bea618cee111aa9d55a6f9e8966c102d849ade596a1b576924de0e92dd91fbb01cd93e24aa71eef219a78430d84965672fe6af091d46dcfa9ab906f6240913c1286ee0a152666ecfe2c154cd3fb14dc0f9c173e30fc9958a75aa6dd74822af7acad243fdfb743e47e48280990c2870904ef1c902261d0bd6bcfda91412bdee9a28c628f218e7648aa0027d918b48ef30a9b18390331805c6739bf6a2cb69a0de8766a7b3a448910d181f6449565a363430ba1c0fa8b11e1a151f6cefa3870c3b1d8cd800983ebd41b48c5624269efb440df23ff9bcb31a4b02f6505dc862b2103f76137fc6560f893577bc3fce92ada27f291305f2345ac82a846854f172131b042735d4b76c6ab2dcfd32bb6258b23ac790af2af7624451172fa7a29e0c5fdb3dc3b719b274b2838ff7a8b25f272ac8ea90fa3c8010ac7f65633eb43ff7a0a95ce99717f35d3c416b0e0da30470b5aa20eb9e2b66315b9407a4753df8bf505b8066c5d57ec4ccdd2236b9c58bd7337925191ed7b75b92c9cee626f13eaddecb07173c8160540fb9f6a4d43a1e9ab263b300c08966c247514647dfab3b420202529e963a51f8d23bd0f689bbc4d67d5a603b876e8cd3ec0770f0d9694dfc30083991cf3989db1812b4ac5452358075534190f012f7c0e47734c3ba748e04910783c0b845484461dcea67a1ec731354b902557486b484f67183fc711d10f906c68cd01f46481d040f084271dd784e5b958ae05b65bf5d207efbb5fdeb25366d6ff4161ca3a1cb71b2b9f90f86a315d800935ac0086d85d907a036c4333ea347000a0755550b68fe3dd7686e416483781b563680146697d6fae8333c24adc8a2436852ddadf6061e2b16fd3829c0b55c2e9c2c89f64cb8da02a6706498cf0330742083e9ac4593a1762d32dc4e6cc2d9f4310014fb15debbea324ebc2ea1e1660782559b9b39fbcf34c85fda9ad350d195ad7587aab621ef7ffb63277ce35ab43b01977c9f8dd6c2ae7b34fa7b35d5fa37d8b3719e736f18734cb3a2468be9ca0832dde0b958925a377fe6751c4eb8ff1ad295355302f0a5ed4e8f8c33fd5162542b8ed7cd985dbe3c84401830f6a7eb9d955ec74c7f98b02388b4e1353317cdb5eadaac9025038cc01f8655c7fb9aee940fc4b282748b39d277a7fef462038833a9a8eb50a8719f68b3e858825911f294a80faede9d4c1815844c2632dd20387950003dab80b1a58e541a5e6658af7d4cdd91fd1c08735b584f5c69c5ca94f6b7f97a4761b127db394ac72e902db9eb4b3e0b884c448ff2763ff9add530753263688cf92bb746181c17294bffc2a0b3969a7bba429a481c425b24745cead66286f5df04f1e4421c56acaa668e87ba58e3b07a062d1da60cc6b411667bde6f466b72c9169965bc7781da78a818f779a9b3d7a577f71a1df49aac865a0d6f2668cfd2c77cfa8d306a14dbbde4d3a3818b07dc89d5f51e117f7bfd007d60f32bb1b6bb01e76862398371fb91e0a3d4b39fd9146c47f627a066618cf83c32e5c82592b418bd2f5dcd8d42234625974f988a6f729c60ba5eaf18c77b611dfb187a581e3a10268a965f650fe242ce2fe08aa71515b59a6edfc9cbdae22df3aeb22e773cc2eb373619e9cda23c236ca3f7845c2136e93849d9f6aa1477f4513358cd8cb4e21444c9e5709818801eadfca23f2c23ddfd5b4ebb6089daedd14a21ebf3f7a8c1c80bbf7d37973bd156ac5c4462d29dccb7eeffa22a8b6ce433b600532f33999adc39196f01230614767285089fb262d8469dc66d24ae0b77fd05c3ec02fbc5ee328319409b8e2d7b0ac6801c1c8ba86f793c2037c71e2a25f114e9ee0edb3b83076eabfdafedefa0548dae91e62cb7c29c03413235b8c6eb9f46be29de8f5d30e8d97db6f45687dc4719b1024e48b7dffd0d2b474b2032b4e69b6382e603d4777f3450e2e467c6d9ab2782c0ae266c320d36bf67bd6b86ea9721b22741684d9c0ccc774335430071a5410c1e34b4bc1a823a93a38f5ab4781cc593b13a593867fb634c0c705107cd278c6ccee6d842748bfbd2ffd205c6bdfb3ac87f693c25c832c86d96b00bba0af88dcfbc8ca4328765de27fbf1389c4ede28317bd0ee447f030990e957d223a5ec66ced9d16400af6da8663c4e4111b4584f8f0066cdf8258d90c5d7b439503e3ab3fcc55fdf933e06d704416187aaf86e6c39695dea8b8189ec1299670be03b6a636889cb7f10f04ccd67278e77886cf3f6e2a05ba8d25ab8664ea817642acf5db4d9b3ef80e169463edb6bfdf67172e88d233609b091bbd085b970db8ae0daa5048ca42d6a54042f42445bab03f9bf1accef341b7349109ba0073d3715a9073ad9bed258268aee9dd5202e0edfa5720a317ea5cb41706c0d235465becdc8e3ff0d628ee5eea6aaf1bbd3e18fe9217516893df115e979c4cffec494988b6f9b86026610898c44ab1547c5f8ed5cbf3c3a837ddb6a444bd3e803e1824e6ab931310fe86b36587f1b34b0b48d358f4b97e9774213de7d92571380be2199e703119c5b9836dadfc826b71d588250ac37de0ec05c5823573c102bce44c9f044507671c4e1723950a3c0e14968cbabbfeeb049eb723db9b23cdf0273525c29cc5165530a1f1cf830d3551dd6bded53954947d5c334dc9c71907cdbfa109ebc52d6305477c14159257af8c51c6f09d76fc0085c3d969ec60fb09145e66a8a7489611db3fdefc35202b8aae82d3cdf666034beff49fe49a45c5ec438f4118f338545532ced916de78e3bf82b4e55907474386b9c172f393efe895334f7323cbb2aa7ce7718bef5e7a23af734bd4963fbc7889aa5c50f3955b904b5e577d71b21a293d766865e3f8c212de5ea084a9d22748a8009a7d1858328a1bdf7ba0f4e3b83be9707629252b3339cef796696855a574b4a4896ca68c3d6a6824e3f593069ec0a571e61282f8a29beb8bd788f7b351a8939cdad9e257587a77804f2704f49db3305514b85b449aee56ee40cb2a75d51690194284aacd0855b02893f8dcd3091629dc548705a1085e5cc33de7726a0f521c149003df380abdae96bcda55c44bf9bfa1103150f049563e848a8750625dcfdd9bfe02e1e57489b5b3aa28beaa80f4daa562deabb4bb6a27125369415885020d237a92ccc3a23593fe2183225bfa2ff39b0bef9cb0425375e256bcd572175483f713bd38f937f2b3d4c1f686c5af60061e0b05cc3ebaab0ae8ba21e47a8318bee4a01516046363d152936a1344e17a65e08030522ec667233145a56001b8d065dc2fed0d2a9f02c981a8962f984916314805dab644a5112caa1564895121d8b1fd046f547be282cf979752883ec79af70cf59a88d960f3336f0ae61357877aaaa34699a876144b65ca5b77a684d850d09b3d42cdbfc4539ea103f8377cfe5f9e5432403fab416662c4c83226191eeb7f82b01e0819c081fc40e7b978669c7856067e8b582832dd0b92588103c2616ba2c7774c46840318ca2b1a3798ff7ed9fec087f01798ea2445b92e67e2446126a7406e82ff8d3711311be16e9171531a95c966e6befea34938e6f5fa660f7c7cb533a119377f1d26ae6ae51d805ab96a64c8b80d6ee137f634b384c2e37700000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 82&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000002913961a0df9912c789f1d81d818b9433400db74f95782903e954db5dedb5c5150caeca3a16b4229be97bab66159c96451e439717de0f4b976b5c7aaf5dbc5f9cc53689a564d3c3eda073cffb88dd3a3d9ddb2a5ee0b8ca7ab65d7248c51e2f2e3044009554a58b1535ea47d0c5474950b14e73491e271eee100a2e332aa3cf63d9c6be0bc94cc8df237d82f45962d6fdbdd729efbaed57b589c8418a1157d269c4da9e55ffcf115c7eb332767ef938421b980d5fd6454d4a89b8b1529d36a93d4690d7f9b265275fa66a44fce5bbbc99b1b63f50342d91fdf1654ea69e1ee6b32c30fbc77c9e1a0afdd9ca4e67097fbbe9c9205921e33a648780dacd346f7661d4287455c1684511c3651a932c09a541e0c5618e274a03b523ce1e8fb5075c1578fb8a69a574f22ccff334b11842c17695f35ab15ed4bd24daff77c6a12430fbffcb8a5c874b987a735c45b5489bd8b7b6c8d9fc582db1640c916e1d6ca63bcadfa7175699cdc4d8516993abaef14dcd43b658f718f29922732de846de5d27bd47fff6756e2cee3413d9ff4e168be13eee1e4a11b0275075d3bd1a6fad4cdd1ce2762879d30d8db4df398863e99469cf47405864272e34abbea5cb28d8bc5830d8dcbcd86c5575f87661f60bb542f28eb4d23e0cff7dfdd799d8138ad0455b39c63e79c080c01564461f167557f80f16ac48042b1911e2a9ba5adb1ebce7b7d444a19946880b574eafca18ec2a49e4c354ace5891ca4fef1d042f51f90167399d08650754ab468da7bb30e2e8bd2c3c6ab58e45cc12cb84400e9984e855774f1429307fa72da70bc5129b356cd28ea01aa47a27e6b7b9b9895537fd0b419164429a35b8a8011e6c50a41c9adf9228fba6ecc9e3dbce99132589d89b133ddd05dffda02cc2add663160589aec1ffdb38924d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381091f7e16f467227515e29af3d1a17f2d1e5c3ae2c8896a4806e96acd393ef413c5922c605ffe2242f604c9657cc384d82a9b72594810d52bf83ecdcd34405e6760f98050b2d14fb996479219172d82823a9a36404d84246576b885fd4f86f6005891994be0f64a2f2c1f36b9d6ea305d8a8c065c43065ef4129aeec5b96eeb2054b7714868233cd23e88dfcb8b68d5d26bd8db4f07922210d2cc86b2e5b8539f12178621b2e4bb24bc16f6d30215d7e15e1a2c29362ef828a0325b35a895ac05b34b37ed80509c7929ba9153b28cb2f67ba619045556f5111ba711eca6f0949dfc358d38e27a06771082052b42e700be423de31dc4be60b2a15acaafae378ed8b5c093fb6d39e82b2f15ea8be9e03052a07226c51a497d0be255c93fd29b59289b9a61686d97eb6c752a897564045b081ce55f8cae01a82c0a32916975d89ce5fd96a8903603c7494c5737228f9927aa282d18c666ed660d460c4ff582268e9ce42b5586aa6b67b4eb1b53c50f1f95694a188ad8223ef33214d0763dd893b9e1023579b51d157e9ea965c1e60a22ce7db379ff1849c42f037ef860254dfc4cac3af575432689dcc5248186820806a63311a4ada396e0f1dc8d7965e46a238c2f549640a708ba1d15be4c9bb1a7d2bd93a8b620736ace01b0881716215b240614e821483a6144d0bacae67958cebc792b9e7e596efa01750db625de7a45f6a2f7415cf0b486597c1eb65b24fb1e1aa529795a2f039363a58fb2e22111a5cd2e4931646b2184779380d2200b4411756b4232766c1fb1395a2840e892c6ceaca714a28f1a73ed363e650fea9d4200854201126f2f11403474d5f8a6306b8cf425a21b9a0cb8c03af61b99630102b92d93d7bc721623f6d18845de62a7d3070f27fa5983604e3070b08741d91f7a8f0eb0e6d9da30674dc16bde179e557e8a46d26eed903a9ceb839f264c765c4661aa97a8b550535c85fe905ef395252e05b69950d940606da9724c74234fcb23b2ee231d827e384923b0da6146957090c39def8d2af5a08281d1a3751af861f523c81881b2f0274aa21452f35827e31d02e0896b9b4d512dd0b89654436316709f98e0ad0ab5a444e9d0985c9f19a7c5618f261204b3b4711a397185cbca45996841668165a3d2f567885bf4fa8eb4a3b4d14852c65f8be1c6b18994bb07a8ee315a2bf50f504057ab95904a06cbcb438c5c53b0fd97db6a499a3138a5db0a126bf42368a14c5043f204a680d5396b952a80a826b2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ad4ae3dde9e33719040345df8ea7e4c0b5e2cbc5cb80b34fddb959e2da1d67d74d2fbe5aab07c6357a9f3e5f6ef5379b4c75008e9077a1eb025f9023fe32fcd9076c8d2b291d0becf2dc624f9e752b1eea2cf0755fc9d4b2e4320dfd042c68577d58e61dad075bc1c3931aba78b473c0726ed495150d6a11a81dbbd1c840f5f1faacd54e3470e0d994deaca7e6e324a9fb4e581ab447a4ea026da3dc3c7e6ad55e88cb841e069eca63404cace0e3d4c8b9cec33bff6aa6341aa1eb69ad799c6cce358ca94555287d01b0192b1b49eb6f705e54fbc86465c4ba70134afc9a53c1c3a732e21b010002b49b7cc6f5237b794bc1d1f1e30a7f1eb95d195d5f26b46a704f77f80b092117ede1c340622ff32302dca7e7e43c2a4d8852cb508403b1aa8aca27a86936350264811550dfef05d72542c74d6243ab9d259202295a63f54c836cbf610e40eb85e9704041a51bf68578b10f7985c752dc35788e7b7754358082afec9e4b271d36974eb90a46f7d703b0cce941c3cd072a88f931a4ffd098634be0921d089e46637f88f9625b7df900a276b4bb75fc75921c8a8b6668df9946290e11fce4565a76d39d8fa55f324253ffbbf81536581621dee664a9e9e4f4fcd3a9765706b8ea833125a825b1cb30314b7c6c78b301638ead4311932fd4611d78572180ee441648f8bfab869874611c153feeff88a45f7a98206d0b2d97cb7ec2144f045225af5a9925ae7fd3db017e37259b7a2ff6c66820ddaac5651b2ec2e5767ddbbe18256b1d0d0f96cf5ee04266b8adb29b0ac5d55b73e1eca8fe724ee174b76ea1c0a54896e2bb565075f1669d3cca171657b66f343a634f4250287f853b52182b9be50df29021673db1841aca45e7263dce653f0dd84338e49ff5c6e3bb42f1a3c7164704a2a000149114d36bb9231606eda06c712a904c1e323c4aa3eee0bce6062a9cb956e004407014adb58eeabf486b38570955c30f2b5c28179f86cd5ffd603cd441a1fb06519368886bff9c2c127abd079346d762e51c311f196d5f825b45eddd4a48c7c2123e10a3d369d772750987edb96968c59441fb2f47f8e33fa4ced3006766c06bb6b339ed94b8fe57b20d96f1a27a61966289d8ff5072fd11d7ee53defe0014a11667d0a6c988bd16629fb53f269130b22a13aaba2e9f70dcc93d3bf6e611efb006ba585fb8e8720357e25df69c6df388fac792f87cce801fa49a8cbead1698c11b82c4f85fdb4d52a2a808483dca7334295bb3b2658aac18857878730831622124f5a254a464de459f3528c5194220e5bb1779c8f5e3866b0d60931a1a47502d99e2b186785658def57aba676626f9ccaaaf449609b07af7b57c78fa5bd06b2ad2927ab491ee461a94ac37a079d9bfa02203b09f7ef180c1c1c430518ff2d3f2a3582eaeb6668060a2b544e973e8a2b88733a902a0a80f8e4f30ac5d0223c1076482eb2ca5ae67039597514a4866061d5fbdd99694a060d0d0ee43a1b7290ffd7d796a9f1a2142db6e0f154aba8720396b6de939e668447c81cc828ff9d2a014fe001ca718c1d6acf4c08bc7796d344a29fd8913e4ce71e986c46bb66c2610fa797c9e1639df423c338d7192638f621d83a6802e72e38bee3aab064fb606962329997fe908597e7407cef098d4591e5e6011caca701994e4acf572f7c91057d3da06058a7dffd3248ee3333208bff27473e6f1ea3914c5b2056aecd7aee07f8dd26b3c2b8b9656ea4260d38e8d5f23c925a4476754240d0702c5859aec2329e1cc3e426bd7665b2a4ee2e75b41b561fce79690f64d1068dd35a294a8e8cb43a6aaa901109f0e09d985b6e323c30a017e75bf01d0aaa739102c1a6667ed48e60dd4499eab862851558dfd17229878f5bef0cc29fd19f59835579f3cdd4f85684e0d46d9618a205de3b29b0bfa5fbb36745b989211e2ba711527d32cbb5e35830df4549fea652377ebbac6d52787f9ebc3cb687ebb641bf51d3e22e98fca48f99584fb1f3bed3f97f33ebf656c5795055268f49985cea00819a07b8f4b0ecd7beda95eaf11e3498fa7aa414c54c38a08a841b012ae91763be911daef803e2ca385c9d4cdc642a0b343db6534c10d9e1755b7b2de543afe1d3c90981a7bd907e9cb14367243d9fdcaa8776aee5f65ed6dc02f633bcf9f57dae39e8e8261dc10029df7b7124beb67dd753b36892481ea7cc54ddc3a60ef8d4dcec4d5796dde0e7453bbf0fd93fcace97ce5048d75ed1f34b69a392e1734e262b2b2a1e246331a373b5cf1fee7bb46096c76349b0f19be63fe539dcd33a8450be894c2dc21beff0de6a841a533f4c9949289037d161bb97dce31cdff4c1e0ae36b4192594dec3b021e8f3d5b500c244cb122974f8cadf125de0cf832a920dec3a6f7150585d0209651b0faae0f74a36fc8779115b96136805ddd4f6f3a69c06af472f369f481359ff834a0fd2f9ae899ea36b9b061b63d07c1d4ed7a373acc40ead808564b05fb0c6e656a80fa3865aabe483848d14d1dfd66d7ab1f353642ee3417869da21622f6af551659d07e6c827c18ea36e2c5e806a9571a7b05bbc1ba283a8984bfabc555aacaeab2453573f782a4087f0f903af34596e83282a2e54773ac33543bd353a3f855bc46810930c3635a9b70ba7ffbeea95a129ccf9e9538eb11e119a072f806130d831af7e57d332ac889d7d9e6bbd1c65d64e089722f6954f126e64ea939d98084d434ee74b55c549bed21d11264f8b5e023277db52b03d7b8a8e75b12b11d62052e474e435707272d72d00d92288ceddcd1abf8e63a8a9963a48b54f492487b309f69cd90c9ff54b9c5a55cd2bad4a2e0a6b00b188fd6c527a8184bb63670bf626a995815810cc0f280131f5f652ec20609c7d3b910e4168fe273626bf0e2cbf05bc9ccd178ad91bc25cdf178b387dff0b6b40a46fdb6c975349b6cd8ad103cdc5dab8d09d9a5b55622e74564c1e789c5c185cac04fa0ed6065b9ccadb1d5dc80e90ab244ce1aac516b346adaebaf7a030d66fb90fd070ed062a41e0b70bee3b07f1c03887de5f79d70f9955b25b8c8201602784ef8a60147260d1bde8e152e8d3f992cb8255adace9d5dd2e9c856c47537742094190aa867459d20989db11841ae44824979c0a2093d7edcaa13c9de25e6eecbc5124055f17466467e123e39034502ba966cea873997ee25e52de2dbba874dc9ac222b49967b7bedb5c81be09827cab782f458795b2903d72ab16f4423964f82dc69c138eefa3273bc10376939e544964150d9df09e14be08cfca06c10bb2c315b1b676c40762f8209c0ef13cfe5fad76cfc17fe462d8330f78bab072c5465f7a26d047fec4bd3b918c9c761b91b02d820ed7ef345e79a66fba61ae13d3050a27488cbdbe693b800f1e76c188ebd8118c9432eb9e7124d35a1a038d237918f1db83304d10ab5dedf58c6951a92aab1a1a40e180254e730eb43b566a83cc71fb6b9749bfcd3a90b964966cae90fad7406a8a89b1e48c885bfe2db41c1996f20dc9a8dfcba1a6f2f307ef8fba5eeae9631c2d6328d90f17679dd9e8e9660d6bd4c8a1d79c47a5fd46bd2accaca2d5c6407b0f7f31d093ceef0342c67dde3f1ba5067ed1500dc45161b8636255924bf007c4c870990c5dce098c5a26386ad84d0f0ce4860349a147a4e7ab80151fa63882590b91c6ad3e70a68e6fec1a2cf65881a6dc38048fc14de71c702c934c5d3c4cf4c474f906c3400364bc400a7da087f94f1accb68439a9a6ffa8c6439b2cc5c0b17a7d649033798429f211d9de12b24d117583e1c425c2c0348c625cc44e9b976d319e72d4e09d5d6f36ee243f5fbcb190e84de56eb680dec8566f5a2c7d5f595116c628ca09401d561bd78356c634419225fb01cb637c46a627f6026d39ec1c62e9a3e85fae000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 83&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028e394870f89aa188a6e9e051e289d3bfd3328374fee68f6a87551fffc636ef26efd271adb17503ae02feab84e6d863990387b42fe1ea6276d0e9f376d3dad2f79d7ac0dd6adcfddbd5d5d1bbbac26d153eaf6167338dfbd561cfd618b3fd886afbd1b981113990eebc2c8c70b8096eb295a17a299a2a573d1d8e0a4419a9c6bd7afcb524e3a3a8e66edc425c9601ab6f363f2c6357a5d1e2e5a867074ea1580c0a12db334fc213a1cdcf7ae974bb6c767dff7a7f8beb19a4387c021cdfb3dc0b8b0310376ee383fe8fe9f9eb07a23865a28f638c8d2b1fedb6499143b468ad917cb463640e1b930c89dab6e8721102cb36b1855c6de0e9e748d4af8d833cf0d42eb1935ee3f0dd78567263d086c5141702b3f3dc316d621996323fd519a35c9c92f79fb393c568fc429cd4e68cdbc2bf46d92fdf0a066b1a5f6128b4a62a24f14c00b6d3141d28dbe6d1883947a86ff66fdb18c6ff5d88aab9b539de7b95f4c26aee96f8b50201cf2433d1b0e2c6100d21d9fdc2e32a22f8788da73dc18742195d7122c30d4a814de9fe215c3255bbf440a3f25efc4b8e9cc5a17eb56ba05948ed2ea101edc6fd4853076aa2c22aaf5342cf19449f2ed62d8caef994cc2298654e392884dc173bde847f3dcc8c12bf4a56d42f5307d88ffb93ea02f71542a0bd76bf1321e275e27bdea690e123ed4f2e07e6c0b08c130d8d7d34f383f8a4c455ca4dd53d6014e7264905f02c5c9b9f11164e581428a5cea3824bfefcc7786a917acd4fe8e88af5c280595bcb826e5f7f3cf72497f0bd456b3a8720f0cbdc465895b59c12da8cbdd7c813f916ed5fa2d53f838cea5f58ff62cca3a54c505e2b7658a1fb263e7e55aea35b84d3741fbf1faf5455f82fbc2fbbced6ba8ba4058de052ec39759b40b735c49fafa5bb5ca0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109a3e69b9aec1a1b4d7d50d861e0e1a2210420d047e1314932b7fdaa933bd000f524e2d8731ae13a8396bc54586706d189eb1659808853a37f1aadaf14c41e0e2f196851470db25656f0c754a3565cd44d12ca1617113c3b9703c9dc6a5cc494f091317ca20713855a2760b6b986086ce782341a51c8cf1a17f04b784d4fb62e95e4331957bf766cc378450a78876544873e20d68cb12d956b96e97985f8a177e1a627d5ef599ed5eca7243b53d2591a19fa92bba4de2ba53d8586e044c93306b6709367819b39a37046e9ca8d0e0fd9196daa01f45618ef91fb14a485951de27d711d03d3c4963d599a5a22dc10d79ec8dcd7fed9bfbc3a49eb36621c3e9c60d01f5d162de065db1c68bda2603ac3f0a57f86aa18d45a64c8bea0b6b64acc3b1e01bb22d9a712ab7090913505b49b91eee02567f81ae199f7dd55b7af3def3009d9413080e431e888946d25f6a55892ecb3a44d5b37c3f25cfe9feb0c27336b504ff7760a294a6ec8cbb9dab21d60771467af5997de0b79ca8a9c2ca5998bcd895e5509827226a7144b0c18513619554535856b5360460d742143e996da59b2fd20398b13934c7a48135f2f6539cb03a64035b581fb752b4d0d86ad18d2f14c84b4800ca5acdd487fda2b71001edbb2d579e2b5e0cf45f1b3d1f9aebb5da255108b8b0e3f9ae8717d42b06a0ec8135a9fed5e8633a52325af2cf073d894249f65798e13e5abd38b297e57471084bd5575930c474c95e4e6b31229406cae5d091828d6422834a8a5a08c4ece0cf530ef2a696282c1d44dce3f0acca569273401c92191f15347980d6543d75a60be8e217be8603637e6d2588299095d71e11b2cd1bf7a3929c599a15780f9bcaa41ca4a490abc2bb65e4ebe5084399ba4804a4d036629d72b5795b141c28e9c9eba2e5b0748d309bcf0a1c9cf0455c97535c9c99a3e5113b363022b1decc0006746b814a5c2011996aabee1ee734e4ef5534cdb9aa0afd828e6f14b6f52ea57acf955eba034b52ef7019b426d58097ed44c276391752f98b7877ca88942e33056ca52c9d8c291918e86588b40a8220711fe4d289018643491dd641f47503d6817da0dae35647e2ad7ea292c2a0e6ee77d923854392f71a5e5617501b4081ddf6c80c8f91097a1ac0b66fb80c3c7a352850dc59c254b8620dcfad94deb73e524c76bab305d3eaf638b6c3f85141e0bbdc5ed8a4c288a81ebb722dcdf084951e346ea317084821e459ec959a595cd2945b26098512f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000af5a7e941d3c14e2ddb4f971c9955868aca753a73e8ec6845ed6e9d3b444c826480f03ac771f92e94380bca7e50303fb79cba608e351a1a67bf217b9816e2af9f89be8a79f661470ca16bfb2c99efde97859ad1d217848289eaf543005f5c231599ff74299ec2a7c737ff94b7465de11f80e17d4fda264de568d8767ce822b3ab9642d95bc89533ce05fb331b86e3c5a296e4ea4c637ea458bced1f89355c0270d083d4920e72112ca1ed486191748b4f730ed52f9803d05a0f2f065be03b2603d6cdb154dd7765847d656b919b08969e41b23f9d376135bd5d924529410392aceb004849550e6cf2903181c9a395fd469b7de2c5060ed22922aa4d7c782a33330714a0af206b29b4fcbe0f12c18948f6634ffd7f2710138020e273cb0dfa735bdcde9bd6cec898c5e564ec71aa7880d97cc711412f28603de293cd5e904e9156d4f6bfe2be15347b9ff7848eb51cd0785d6a649ea3514e02695c7e3c4f021a9992d67bea1d68e5b17db2e0dc061ccb5ababa49d110055467f9dee61aba8f3e5c713e94a8a96c3a8afb698887c1fa4abc5157ced33a834dbf0f5af9eecbb5f2ad7b63b4c2ca94a117c2b92f3d51900926e26b101fbe6207ab0884cbfcb15f9f98f95b0d08e29390977f4d3dc710eea3ae7433d5ea87a5f710f1fceab26d516fc19fd272f6b0f01ee167f06e6c33273481f280ca64fda0549c8db884fdd467b93998360766d4cac4c8de783752fb6c6d7b1e47df23ceeca572f2ad3e2b628e31984b9054448ed1d90658bc658a9caec0485512ce084a535e7c8196b8bbca5d26c105c41e083f8d56f1530a8c1b36a7f3e41fccbac7f342b2d026064b304444192d4873fc57978e44151896ea6c0f13d017f683b203ba1de677ed00f2b737c4c69e53ecf16ab918939e120e9fe14b2243eff0116b24c6654be09c582f1e62e75efd8593e62e45ac36f717815b854b47a4ddcfc91fc533fa85bcecb6e560cf11e46d2f334b396d68b275e7404a70f2a805a64cd458a8e5f114a89124ba1866f917749ff32e59ee71948bd97f2d4128beab8bb0b6b06d84c6d466bfa30fd8100e48d951d0b3e787ef9611a56ffd64d970dbacfb1b4df064b1cb5da9918f5c58a10f0903b64286b1c1ae5cbd00eb8b363bdd7a7aaf2111c0c6e86e15abf6c1e761fbf027425968cdc19522b44ff3f56335c59760fae6d9028e76b284330f7510f2b55b6f46adf90311cc785d35c2bb49272be514cfbbd7a2b7b2e8c0b6dc28cb683d3d581f547f83bbd3b8c7b76925e44e6da89d5eef17ab0bf4213ef9c05b7b473901d483c647f416b98478c7100919c28515b617a27321841baa174c1a2d3494395294cebd48eea14bc3106ca9c69d9f6485d6abf1c2b1111a8bc602454685ca61ab4ee4db9f413caf8f0f204f04d40cd36fa5dab629cb53876db3e16372e626b6bc892c63c6b6c503c9d22efe113927395206bdaa4b83d4fef4feb42fa7a71f7ce2197fe282a02d0fe50f96b1f917a67e50eb79cd3ffef064542f7beb51ab05b56afd7aea5f4164cc9ba37d8fdb35a3deacf0cfb555161e7e41eb798160798be9d01e3de0c4288e0bab19ae398e94353adbe9a43524ace35830b82fcfd4b1dc2800ca4c38a56b7cd28bc3e2f69a0ac4655cd79b5789a2b72eaf93b018d4d6f4c983d08932b22c85af6fb07df0a786d98820e1b06bc17f62d6e39739790a13049252f1b9102dc692ceb20c270ffe9b902ab7ec5a4eaaf47f7e2d31b2195f5f48ad18d099c33384141da14e151ba57f6b1bb97901457202cdb83b5c713bd8a13f6e3e276c7d6c130ae287ca8931d9eece06ab7cca124d6d02d497d55ea9151a95e8a4dccda72d3f51a7db3f2879918753683b01ba1b154da83e6d84ddc9492f2dd8c128a30c75174ed1a6b8d93d08645270bde247782e882418ea158b2a2153b2d8f75c09932f324ec199d26e9f3c4c4cecd807367e3981e137858b98bd1268d2c894541ec99bbbad19a6856ea16a1e56b7b193baf79ab89d4e76327405658c4ecb5a8626302b3a4618aeac7e11a1199c4bb08c60ad78fea4827b59cc883b2ca7038d7845106de9174b2b8c17267273d23418af560265000543ed9886884912b4160fbd372fcdf706ef642cf1829493884b6cfe946ecf6140106dcbe11b3746e33fbd4b5852b732230b9047004f4fafa0d4bd7043c7d6595accd1b2771aaa76fe05a0c80b7b221dbef79950fc69147816cad0e52c05e72ceccf55fb4dabd81ecdb476417dbfdaf3b555cc90573cbed9474266c89fc55ff0bcc55602a51a1b5f91e425a1a58dcd4abd09bbc63933fb4279b9e21298f9fe0cf1a93c4a19695240e8978d604047abc7239f5053ea650d781307c50dec4d5e2360adeb9aa02c0f6fec5784784a271169ce456e1c32bf984c3323656ccc588c97e0ece5a40fc7b4ddbdddb764edc512de63270f07891bd160f78b8ecd3a4d11ec4c68ea0a0fbd0f23af9ab261a110f431f926c4995b05462e0dabf29d9660abbc660c9a675628270cea7ec5ae9b6f298b17b2392263700b8ead9c845ad29ccf109a2ed66ed5baf9c935754aaa1b84be2b5339f9bf3cf5e80af16967863fa8dca64f5fe873da4a6d33e39a592749b721fec203c0cac527ca96de7a96ce9a540f5da1902c97f960a05ebf0c32934f9b81244c945a60fd3f176dd8c261690d8ec98d19607129a50edd51135ffbaebc04a0961acc5a32fd058ffdf2c6866bf90a3e177787e7061bd2011ec08ec118ef0451cad010b53c68d0bddc701d10920d697ea3439b1a0f96e6256b7712f59c746d1c74c20b17d461c3df635eec83e3b8e098034f119b9d9a79ada735158eac3f434e805444d5ea2ec85cc8ed8f5bccab7dbb6ecfc2e385781579af1263d9fd32bee32e01db94703b5c756b894def19783b12bce2a1a8d29d96f329cb0791d697be7e0f05dd5c9dada52e1b8c1e5f75a0fc90ed8c05bdff86644b1ee61989caaa271061d4222818c894ae9eca2da7326e5c24ca1eeebe3720d2127ba997b0c572ae30615f8bc4278057f4762d46a39b934ddb2a0903fe1568c1bcc6c37e1f7c145eb7cb20a6a4b3466a7aba58b48be94f7e14cd20c87b2768358d06e3f607fe5e9dd1aaa8477975660f1e379b9ea26cc00cea8cfd6420f2fdc7ee6393aa17cef88645b821f8f42fc7dd97b0e16c04631f86ecf1cb76a6502fd1c13917ceb26a83596b117d5336387ddbea56162e8a5bf2fa35e697245bc7210cec13bfa694ae884582924168bf8ee2f61a734e37876f363225e5ae19b7c65ca6afc31c8b37bccb308a9c27f3e9902de365e288e6cc46e329e78be914b85eb980c0bad932c164671ed395d5d8317c133e2e000a10e0d20d0f408019b33d9a87ed7725ea4c5abad67e0cafbff31dd236e59defab7ff2cb40f479b56b261a32656f016deca5302a336ca15d10e0afcd168a4b922b79c11cb21881220374492d64df21453b41346a85174a0a4a3c1e973845c856ca70d6d25bb854d0c6bd3c75cd73998c7f64e35a58dcf593c85c2440a6aba4e470f87e6f9b4abe127b30f8992d8aad0be38f008d9d937582eb3aafc68f516d5aaf2503acc96e59a151d2d4b072ab6b38c54928d6656441c709f1c1b770ce6efcece11f8b3602eab63e0c629bbd8a79a96be4cdb072780f3d287b091fc94ff2c0d347fe280bbac308644bdb15a3c653863edd945af0ae725507507b82c283dc9909ccacbcf357d7a19703401b6e4474b94a6cbae575b942501a281b8166fdc70e6b4b60c2f57a4d66fe1197d301d0e0c7bec12cedf9496bca2183d04632711a79c8374b6de35c2eecb0239391c2019c720894bc7a635df18fceeb9aae16b3ce92717e2c56903d20d0712ef80131b8c48635163e97efb1fabd1500d061c93ad935be9a65a45a92e4a4e885268e712efbe5337214701baad4c73e81e73bff19af131f0aba105baabe849f0000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 84&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028e39af7a5eb57cd14f7f59b24bd95a0dce770e68bcfde7a0ddb7a1b21e2a244c80487b46242b5541914c112255ac0334c1f16e2490935f2126d18fd248671c766ec080baeb3a1d1b7139d9f29cb4ef492f0f509242652a5f57786b751981aede670a7b2b1e42d0e56bc49fa3e75129cd6ceb5c9d8f360185e85e15a40730d2411279d2a0d76ae6674b18f0c9e353e16df4c71854e90a5b283bc2f2e9a6d7adba5a8915c88bf30ce3f14a3f8d63fed755b52f65914a6d2bded608a366fe6c1653b10a14895d9e4320f8f63e7492c0d66384a9ac66736e02529b086b1bcf60fdb92410d9b66da4ad63cb68304671576750bdd368812ce490ea318c28ae230505c7d9d7dbfdd940cb6d9add228d9625093b1735f36fd95f6fa299d5806d351b19d2d5c627b6dcdc648bc1c62081d03af954ef1e3d5cb736e6a9fc7972df558646a1237479612f6962f34e329737181d5c9951cceab4afef8355c89eed6c105b1bdadaa86dbec7b14d87a0625f309024cda68a414a77545dcb62707b730dbac2a368db7629c65010952a7d8d874627d236495273ddda9373e1b9df19e5dff78966eeb1ef63496ff23cfe790f3607a24a10d5ebc9b8666f8c734161bdc2b81193b70f5edd863d1b256c1f4d03aabd3dbb1b234b57908d92f9954836ef072fffca87e7c4ed007560a8dd03664719b240b8421c866602a1ede47cfb6cc6230cfc23c8b71b5e657a329d5a772b465197a506c274ae7dd411b84d71c9fadeda24d879ae64faee5b2304d86112912622ca7cb4ece4607d36a6aec9b2598b3a05d3c4a26c939d09681f6b27d624f37731793904a073915e47ef9eab397429b31b699021844ec4e4bd743f647c66945d440a298e51636dd38db6c171b50f2cba27d3776198368d2ba5eb2819e57f8f832069b5639d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109b1f124fb0a62681a8c9e93fc123f0aedf3e751224b42b4db79c95ff086acc89803d2be1079eea9030dacb22a24d9c6ab374401e3906dcc2962e5ac96448ed227d01d361c475892052e83a0e0611d9e213825ef3556b501b29821658a14ad2b2e8e2885a85f78236ce157dcb0940965412d8173c48668d714dc61f43096659230bf82d70c6c3879b210688d4a180674407b604b728a8c4b50eb555bd0c6e404ef193c0130c7cbcb0a48359e8658e6996985525761989fba5983476dc0759d554da8c20953164acb136f27225f80382659115a4c04ffc4e597a13d7075d4365c32b1204b28a051f0746d84571e00fe8a240735c661e2ab56d8daf047706c223ebb63aeceb53909c2b0dd3158f0ae7af746576bf5fec2364ecaabe9ac93412e1d5dd28117ef0b156302cff0ed6dcc78a9d76bc9476f3875a54303a0047cb6fd643c67c22631345b88601535f2927a2a496842b693620689f904ad2b393fa65a71f1124b78400441e9eeb5d55f4559b5941990cd88272657414c230d965a01c309416576c8a7a3b247bfac848ae7656b19537020a9ae53c461319ac05ece0b6da8b789b12ac076e9c340b0d3ae1af65773181d47bc9991e4a3981a75094959d223ab9c86e93069549f4cd92240af4ac9b09d8856ddedf76319150513ecbb13a9764ac699063a1d321450a0864824e3a61bc036be9cc458cbc5cc86fed26ba8836261b93747552bc9801ca31b3c15592e801e2a3f093a950e83618325959bc8b4162943588a1224f36dc737ad5a00da06d5461362d5e197548c60866fd5d2299eaf6eef7354e6816bb4c2c16357492e3e7d389597b5735122a966d3937326bc324d53ee3e8161086484761426149402403a70c1e5cbb1067043c5531a295d42a3e99ca9ad60ffb5308cc6fb9dca59dd38388769300ffa1873d3450b37ea80c8c5d9e9a7a6ae38cd827dba510a31c8c3264c5ce155d11452ac41c432b85e6ca794c5d4e665843e5dbd5468d1f9be913908530087893e8cd51bef577d20d37863eccd5f2c96b8d413a557085e206801cb72469a632f62e65b58dcd35ce1a614a668a33f664920cd8698b5daad6ee840eab095f67c6df3146a1c3b36cd62d38adabe9ce88bf672513fbbd51685ee97785d32724809a5548b823227c9476540cdd927ad96d71f20dd88d5de356826762a262fa635a4f2d4bc04e51e559707f7c3fe114e56d804868c79de08d45a289e4d2c96652cc7bc824dd3c910ea625b786871c32d6d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b16e43eebe157e43d9f54130c668a153907d65bb19856a1b7c2fd5e2c770fd6bacb13baef951eb758485c128ece4f3e9377a58a45eba1c3a9ca5c94b50714088700d6fda933ece3a6989ee77a824a9e99674748a90b7f227b589250c9e156a8e50b74a7f49de036fced86ca0d4c02e217eefcaef7234f651ce4380b86389d7331c7657ac283f58c781f904405acbb68661310ec6921c1fb7483e74116378086d4a0c9a52af9847bb3ce0fe97f5a7c2cf588db3b6fd725ca83391656cb38fcb6d79531e56f5d42fc0cc20d04ad7bbf57001bf2f8e6b335cc57ca2db23c247ef9b75bbba3159030975d65b9aa7c10e0fa4f615f77126d5271129d8839a3f8da30c79174373c4ba643e4c4f0cb26bd5b8b9f7ea56de459eda15037d8772478fd9f7f7e06f3b422df0b425dbf1e91d3893ce20f78cdf1910c5d4674efadf122f41d6c7d6290df59fa029bd82e792e758ad4388f9d352e9d2fbe3e58810c380d1cc5768865d24bdd92145dbd1ee0d4724c769ef5cee12db2ae2708b4c8c7865e70ca31386388d991d46c4dc4dafc5ce66cb24d455bee01488a7c764a308c7054572fca0cc74a01a2b1f191c54146fb1aaf55b834f998b50909f3d003271e6504985dc836b5c44655b938769639799f2575bcfa92f13d32b283a5bda11177ce1f66d6b30788415bef598773e87b4c8c41f0ce6633b6c945a3b4c46b74f30945efd99cf3709fdafaeb4bd4c6bf605f89c7a9b4eea1a6599f0a32ce3f2c58587ea8bb3fe6495d92f2feec52bea3de2047f5eea7ea1453c762201ff1291afa87923107f7ff586e00d07824ee021649abd2d6e9ef11a1d31726ea9277134341ec57d790949590a963d25d6fadfa9ca21e43acb7e5ed4cb6e8bb36377c2618997943cd100a927d395376871acb9619bde9b1ffd5e48e271952613875fa3acd3e1f2e872f1d672aae6e2a575a4fdc4fae2dc6a7196e7eba94ae5b49be41e7295433adf49a6d2d945f43699d444a726423cd9164b9e28b0aa4485b0c767a9398df5dc5f23d27889c14b1abe98880e7bd5df9ab3d1321d5493a0a8b91ea4827627a9b59308cb0104cd8da7d9def2d47b27074ba007401415e900df03f251c8aa425f0fa59d74c41ba7a9288c8e280141caaf6c6932ddc4184f81f5c33f0fda005bf3fb6a0a9169a709875ae475302d57ce96d3db332188202597ff29d1f9ebad2b0ffa27c14ce9cca58c923283ba10e9fa1689d6c2b8804225d706e09ff97ae9cedc27d256e8736daa54382040648f2f6bfbecd6c3a9bfaf5d1ed23ead00eab351f1e0bb4c719ae6a1f5d12e7f09ecea62a2f554b18397fe1400da1eb6694635d7c9c626e0fc82cf8df6aa4ca88b69f78cd065c53f929baa58507fd3e3d8124c4bf287d452af47af9f4d926dfdb529a8abb8bb57c5c7611a97053a0cb0b01c754cb479c6cd3a3e867bac33e45ea0bb6bf77e0b2ec2f136dac0e259fa309fb5f6d8e7005e1696ce203c5d054e5927a87a1b4e81e73f22fafe61d7d64cbfbe519d39e716bdcbb37657e71b9390ff04b3c01c6f6842684115cd7f5aac208eea48906890248e58d1615634cc1263cd3adc14b67f1a1a8ed2626e7237af5488f5d269973f11458e3e4fc2ee35a4bf49c2f5f2361939fa243fa8f33b54eeeba9b0453701e367a7bf4d698c62da64732652c68c20a956522826f8e29a764ba93dbc98fcc87e59a1423886694057e131333c5dcdff3be7a1f0d344a2debb90051721e0226178deed353a136f69481f83651be3281c562d6127914cd24c38ffb327786086b08ebe89d03a33bf7b5dccf90de9c4d907d308e08a616c5343c116a098786383009dc70787aafb4529cd27cf85f946b8b238ad2f00df109fc84cdb48bb52b73e1de066636176e8c6c76216105486c553511df1f0664ec1e04ee0b0bd74a08070207486b7f326c3ee73188ab5bb7f8f5643093916491d62f0db18675ba4ce90b2ab310bba4705b65a581fbc5e76842a99d4926ae5bf7b8eabce5fa30cb98c1bcf0e0708da970096234d47bfe23a4f9ade29be5a8b6bbb748ea1c13d00388ac90b65ee10be6a9ac422ebddaf5482422aece19e702f6d26ed954d4e489cc48b2e39a6f168e98e11c1dfcb4a843354f1afd447962e5090ccf51ddf6643ce0afafcf3e4363187e69c31ab796132eeb04f2d4976a576b9bc8d9b1d491b74613c1af32e3d2def408abebcc27e4a915c983e10b6090fb2de6ff9e60c96cf4f940b09aec048e7a174711798fd76db15dcae0e570be3ac147e2f8777a522555b0898bcd7b04abbf060fa72b04604c9a583fefd02b2af9fa035f97de4daa4ee777f9d6985149db6c2f0a33ee1a1436b38dfdff87f831e83399c6a884273e612433ee3958f37c99a748df151e3ea011f4df5f0050597685e0230da1b1c7095e1203ea7099ba5c43e58ab0eda60af65291c3cc9a07257d71ca6c9eab93cef41294853a67a5b11f9192c96a36c701f142dc36b046218bebad9904fb765550598f8e2f49f5f0ad2608117196751e7e4c5cc4c3ef425a921c1ee15f37a1f80df1e24163ca145edb0fc4d988b8c7167acf9cd94f919ac96e5469859fdaec54e1970007eb9699342a9aa044a8ee478a3ecf8b59b0109ea7640c218ecc1e8cbc5e2fb61a1748b7c038efdadc2d096bc29d95b1be770d097afd8b0fe02173a1b3d7110f80d6c849f1afd1b01a60894b16140f9b34d96071a753545159c4ffa4dbaa938bdec287c6b83751c5e699724ab355d1fa0e081db286ec83343877c520e856c4adc65322aeb39cd87b7d8e4ff9222e085ed84c58b7ff513ad77f8a9eff2760a03f69ae5dd14dd92dd3f2d3d98e97b1987086b3eef2f2e822c851b7add83903786c050f30c4a4f4ba9361e49acad503e2a07ea119752e12d4fa09dc83f7a48ee3dcc1f09475960b6839ca736e498a128f78e58279063d839aba88ac9e5bc24bc07bbd2de1cf2e1ccc5987e63f83780d0ecf07eae21c8c752529735b37c980eb320dc949468c69b17da8ad612825a84d0529eb97ff8c4cd225fdfd1563bb6c5360abdcb3339434a298ddcf5f36188f3ab501e505828e8d2fd6dda062ad415c56414fd7557170f0f57bc5a401fa648699f3c7f7fd8f1f058849b817fadddc24726df851d3644414f55cade30a5764914675d574ead4d4db8725866a6c51bf0eb23b12fba1e101a6f3bdb98a2884d0f2b8deb3f279e9c38ebd0209dd05c0fcc6ea715257355d0d6be2c8bc7835187cdaea43a8ef9c59e88af6aa667a697a3df8bde250eaf4341a835b5ef93cff97656133b49e13213949a3f368d985e0d6c793319f4284dfada383137dc5b000b7fdd85f27865dc633562949bbe4fbff75417ab109f03015bd0f67728969435efae791ac72c6aef99a385a3e8b4c35f58380149c653fd78391a7c3b26a3550d37f9639164979288beee99e36ac6f44d0fcbaf0d210839d563a6249059a30ce6f047f5d541fc8a90a18610a8befb9493c5ac804d34d40881ca82e673788870705bcd585044b11f1d9bbd6b17d8b82b7ccc0554d1e3aa7f2762fe01385571c9fa7a103d07c1a209504876189de4b3c5910c26c5f33ea725a7d57cc30a6ec8f3eecf2409f1234a094556c0f7941cfb30fe86f208feb73c8e8ea8623640afbdb1cc589768a714cf945731debf4519b70870fb3a50f1fb368ada3fb217704a5d46d879ceff9bb72667acc673cb196afaa0db1160cc2cd7b260deb791a94d0988ed54b7e45f33e7cdba0fa105f3af3cb1521ea382b1266df304c900bf53e195ced03871a22c50da166bb9441cec83607083195d6cfa17297b678abb5e03950160130b47e25713b0829f64d2552efcf404f65798a86d5899b72150a91ba00f7dfbffe82531497b60c31c28992377a2dfd5fac8a9c16c835ce4dc24d0389277e6355c655c8a33c89bd48f55c13ede24b9bb348dec89612f0905719743c95c0e8b5653855676ce171f812eca405b6f96f2212d1a5369a11379282ac0c5ac41d00000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 85&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000029039574295fc2e0cc7f3b1479988d668f76998c35850f48906c303f71b687f83910923643968f21e458767e2b53ecbb434b8b130be3cc5baa96ef268a27b67966199d202ccb7b2187220f865fc36af8729b572bd72266eea98326cf631486fd6853f985c553aa31f19c3b659450e6b395b60b29f6c8fded43c79341676b147501257bc48e17a320666205c3c8ca14d4239b96e82be9d5a507243635ce1c5cb1b0fd511fe03d48e91b469488124496f564793d39eb4589a22927d1115551007e54dfdd22c8f1e81407ad5ca8a0450229e19fef06ca527a9e07bb7ed5ce129d53105a309de6b4cb1e4e6b4be1731f39b6d55a4bfb44059dfb6d223049acf73991ff64dcbcf7fd3e4a237474eab30267d11270759a362c3489a5649a90f7427cc4357af639b36551eeb4a7a8903a2801b9587759469a32c6e4199cc4aa089f63a8441085dce83e3fd25f1ff1fb706f64bfe0d4efd49dc6be46bdb28c51ddb4d7a63da4bd4ad9b51ca6449d9ab43696b6c0c6d487bbdb144a56c6a62cc89ce12ad879ceda27aad99676dfc838b567d7b58bae4544ab237e8e1dffaf4b1d4140be4b9fa19fe8f76ef243f4bc59e7ac97b7538b362c9df99ba9474c45c744782e706e826bf8a0128a13fb2db7ccf2286b66419896ef47ebe0f7282f66ee5f0637328c33eb2d926ddb82a7e1c14c19638a946114d635f6a559e13f7f15ff1e8c07a3cbe3d6e67bf784a157bdcda2cc14fb36b1230c79e0c9218a6d7b8efbab2deb3388a2e61be5e9781185e22f22592c580644807450ed3196b9cefa6966752cf7421b6e3b8ad3782c4a6c310056d356304261b749e293b984d6cfd6d90d73bf97447fd49a485dc50c826aca4dc595de25344acd40b67e4faa582f9cde26b74bcae425442a0fc3d7c557b8a51b8b6285700e460e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381093b0a2e2a51cc164119b7147853c200d1bcfb2f03f3bedc78ebad09db145064589682c691a865e31263bb77a9c2a1e3d20660019530bb1c4a08e68e7994d37f1ef25e73cb4cc574e01831b5ad64689da2faa419f78dfca7c374c1e7353c962510cf468f7a9b23440781aba6271ba919d1772dcb3abf2cd5447de6d8b5646a25309ef0ab639a105d771bd0e1d7baf9f8a30a4343b012d04b6301d4903dd11117ca0244289346ec4d095c058c631f291d5d1284fab7ad4e66b20cd1715b15539ecff272c199b44ad12b3b44501e60e980edc75544ba3b3301cc0e384989b37708015e9ca6c97f0f88b4c649b7ac9f4e6c4d8bf99fc7f751a68cb11f9fe90cbe7c55f9cb342a149d97c9d03d62b4c429dc632c077d52fa4b50e41c5c2f18cec36892d992d84320de6efa39d31317d1438dc9255946823b9d494055c2f67242eb4463d5eb4344d6e48e17ac35e1cfe2d3149d706dafd9fa250a94b587f6e32a9d540447059a9bac16b8d986ff08b47509f1ea5069b281dca9686082e86dd86a906e4dbeb5785161ca17c312140c94d8e84717c4b3e471599d8d5dd5418c4c184a3081f5ea0a0d5c744258e44b2c8b9c76c547dc5992928bf3ee21919b581a478c462d50f23773398e9fa05e1fa1ed94d64dbae9107057bd238ae1b40bdf582209a5f4955b9e94e27a366b1112801e71764ec75862f434467b8d2b95c5f8f9d7d307795d9a692ce39f043e0ef0dc1bfd8f457f2a70aec27f76a355cfc7e71ffc15f9412cb3b4be4d76a6569e25e92299dd58ef8df17302908d0b2352d11bcfe41ca25e19b9f124b688ee64a317ec8e35366782fba29da7099010eb8fe715f44b961e686f5fd6737b5b248036320b93b26f7f2564ee57601f3a9884975214a9587a7cd6263e98ee6185234606892a04baa64300e7bc9d3017faca06837156c759de95193fd454191bdab609907dc0e10d53a14d4039c71fbf0e1984672ae00936aaf7bb01c6f568b80db0cba9480a2eb4e793df8f1ea426d27e45558d68bd38bcd676ac4255e9366747165a9ab0c802701ea85a837c6b3b36513a760144da34040f96136a59575d7b6900c9244a2ea73ac34871926d368023a72f95c5ed89912e161e282a98d9afa21ea0d4d68ce688a865ad12bc6c0f2fc230c9dbdafd7210b1e572ea8073ece4464a1840886a76c103626217c26df87dcfaf846d6f97916d2a5e38b27b050a6c4c98babae1943b162d2e0bb7017198da78853ed5c02ebe6fd5a6de72000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b37c07185e0343df2a4201649ad5de4cffa20baf5dd43f5e4a6c81cd5143fe72865a7c036a2dfd617d96626995c12efad019ff44e0edd7028f29e3657ee3c0d02e9ce83ef0a648fd7cf183a7bf7c15095e0f9278b14fdf6c983cdcf2987dd0cc085400906dcd0d14aba60124f4b7494adbbae3a8d6052122575f99792f7240eb17864dc6d231721140e43f1110e73eb2e3c05049783b33aac4e4ca0a248775baf81fdb03d114508928bec3169a810296b5a4dac27e7c7f8d01cf5943cf4d8cf6ee6f9042bb300e50eea3224d35c9628e38c368ec3b42393fc820371db6557216a2c2d5a230fe3a7c6bcbdd89a2be5cdbe7f783ba379b6a4237db051e6256dce14dcf641190a956e8e85eb2638736b899ed045636ddb7a351f5a4f4108d9d6e0413f92b9d392495299128a5f4acce8c7747c675efe05ed7182db51c515b345029440ab61a904d2a390122680c951ed4575515144c5ca80d6f14d1cfdbb5373b78e09d04d0544151cfa1240790cd31165048d1484dc4d11d05057071db3433df071b367e00fd38c386dab689e4dff6fb421b2a95ff54dc29375c9d1c18a76c79acae3d3f35d4cfc385199a4ccaf6c9f0421bcf58d296ec7e0d1b95a6c4bcbac1271f94e438360a71a6440275591e41389b30caf2626a865b9e59552cb198a1d4453eba6d0f6fc491a8a7783b4a8baeb81e54f9189ce493efc1c5d830a4f637f2bf43cd86b91637611415c95685fe79966174312fdfbf33a646625f97521b5cb1f008135b824f1d6d8373006c7158e62b1f794ae34548a0c6dac8b60c559d81580ac0d84034a501516ee36cb4082732918365a5ab787face591ab02be6957ae4bb96b58e2b173da019d3e0cabebeba0af775779f14bfba8f595697731522df3c80cbdec16f6acc32659cf5daf193178307887ef1be1b48b5806d0fa9868a7fb853708b26873857786b974709c687d6597bcf6c7e476c1e47cafdbf30b6311ed434c0f998c4065399c59073c1f2bab1d46104e74ea6c976d416e58bdfd24ccd957cb431870de5da8763992ef68bb18075926b0e4e826095eb3b8cae086fb1759c94b873a1f4df477e0ee9eed8dfd7c77508b3f0c67f69be04355aba9344960639f6dd6b3a956dcd66370338617a365579c5993986b4f748cb7c990344b209785e22a40fdcf8f83061d37c9f1351b4473d6c74abe6b3eb2a7d62ca0f0c88a0aa8a46973f781df0126e8d55d3e9c41c2e3884f84fb0a06c484cfa0c9a0dfb8cfd573749c711c7c236b0f2f144e1ba4db2525c093deed29434fe43cb3040c5a374cfef33214fdd2d660398e91bf070a4f5f9746c2f08c41256fd5e955891146ffd38b155987e6a0fc47ac2a5950509b9e2c86b9dd9929378f43ef3935f1562672498c5640a22315be15b001d4b01418df8eb41dfe5c570e850582d8916c2e7fc2b728048e24bb9d1e8283615e039c16a2fc61011631bbd8f2beb24adf9552cf5797ce05d9d1a7e7f3f5455017b127d9bacd32bad0cdbd3991bbcaea5fc988ee7aec0b1003732f25489edb0a1f9897247cbc40e60f1dd276259ce19deccb90067f7293a68b683fb5232acd2217b8929859109d6852a43892098630a67d72b1cf4bd5d58e20c5c18b85d69df74ee8cc69baac7da48eb71a160f03b68c6be87a4919736f14363f004ea3f41dd37fd8e621bf433bca71e17565e060f3c0f889515d0a8c17fe0d6d734ff756256b0a62058b95422257780de000557df289f47910cc272a14bec737c0715f204c49f03150082dc904a5d170f7383f04f1e355f50f80d5461cba53490bb2e9484806d369d61fd00ed1ee5be518d04a24503b1c4c08c7ca084902a3942c04143807203287a985eb3fcae3c5309410cd9b9a548f54ded44321ce8c2a04679841daef7fbb6aa11091d240afbb467d9969c31c1cbf6b24f8cbfa20cb4cfa404b1310400271664763e9c1cd1b6fe5ff2a0fae22ab14efc016ccbb19c5dd5d047750db4addea3e7a193128a5f4d7bb6358f21b39a44259695904de3440bb28cf9466b562065c387189eac2f7522c9385dc2a607f6f9335ff8add47c7ba932659aff69b1f26ec8655bee4f97fbc846e48111cbe25524873d1db2f2282d0472a2aaa3cf491c26ddc5e1be77866a3b692e417e6717a4f4454c56f97f063b9e598865b6f71136d65ddb0f3cdec57decd5a57366ba96e4315a88b4ea3479321468ffff508d23b0701a62ce0cbc0fa37c91cff5c5a0433fd61ae11a922575f5baa714de46a58d6efc79bdb10c9af7e9950a61d44b3e17e3b5298501146485b562b1570ff5798b47641d67091cdf90902b2d762e3efe94c540de4a28269cc416edbddd4d43ac2fa82d638dd9bf11f3bf22fd81cc4bd4759d7d864eea0e8e8ab71796254b278cf9b650d1fef38b8437362b2d69ed84c54498331c6899e20c596fee7cad9ed8d83d86774afa6e56a4ed34b0b0842b21ccb67035406dedff0cecb0cd089929ed5ffa0ce210822444808bad99af603082bfe5c98ee4653349f8a43db64cf90190c96b0446cc9cd23e0d75b47f54a731e8bcb0a4c67401dee87876011033d2a526067fb73786fbc1ce696130fce5d5379cdac6788875d27c04783b1e2ef41063d57e3d6560d1ff48882c39131c95bae5a9c9392dab6cd17eefbcf61c464a4dbc08447443cbbf3fa80481f3bc1a5806042c07f7a7ad435875ddb1001565eb6b7b872cc6c853f771c1dd5d9c16bc27aceb3c7690125c1907c7ce904852108cafe76351269a3d3ea8812fae4fae35f0daec8e8b186f760005524998bb5de475e4df85209da915bdc972218ae7db7e2efa05a7d752ae61cf2f3dc26ca2d282c8e32b4838524be460971e077348290fa0043fb7616d821a71dda3a5fb76bfce0dc84aaea432df32b05133a26b46165297ebc45024777a868b8b1b0dd6f97658be799bd366cfdf99861e916f7cf06c034e4f79594f1bb6ecd9b7347911488928e1e473c4b8c73297f7ed845b9ec59020373eda57a436c1c9d1459c6114bb6258543d8f4f97b10aaef5a2e082ea173ee69702d83711fee6aee8f6b260d03ab74c3b5d8fddb81b208e16458511270dd1da295f25cde7e44a8349b60bf0c59d4b425c1fba60d2bcba47b906d2830d8d5c091dba756e61620d78b2dff28407fdc9da9113cbe82219bb2cc05e11c70d040bde821aa17b3e981558961ca571e5d5041f7de047a1727d9c904deebe561dc6dbd8876bc77c27322f512d6171bc03871eb0fdece70f119bacb41d1852220cff26110eb0eb78e39aa1b2a4c2e78679f53683520c5a57fea71a8e96e0aed33118dc4bdd035fd88f535b011d9c7deb6f406a072ae6c091016ed10a5a4ee9827882ee27c535262d1d745aa5231736f2deec8a6017bf0da36b416c98ab71c6824a6eeff3564665007c9e850fd02a1f5e201b534627b92d21a493df293db9f24de70c7b49a6e07acf2db6c90b448681666dcda318c08aad08d3e257af7e774c75debe3b3c07af683735e87f205b0fde07351849c5afd07d5722c6aa17b6ac2cc3551c305e6ac31e3601a236961f6618cd3a0f7dcf6f65b8ec82e27e44c8518cdc16ecf79374f796a3daabe2d5005b25576b35b021497c5a8f9b98da68d80e56a1cc1044c04dfb11d36cb147eabfdaafba0a93fced8675d7d6a9f999785c0e7346f4c68eb17c0a2409e2f5bd4ac5551ff66a9857c66f642f2a385131377b6372884c417e01bfbbe1ca748ac8969bf2c0bd8944767746d1d57d862795e8ecf9e8a5ca122d0259ffba822588c5eccd14cc6ff4b7354cb572f5bd695ed9d85de131fdd97dd5d6ce7844ddf9f3d112028b5125ae7a77a4aeb2ebb554682a26f457c43fe96d67c90be7e49ff443478e82d3a48680d737d1260b8210bbe962efae6505e496b1b6d4f1042a7b971605e2dc50be3bdfecc3010b9f5618d3a1b2c1f48888b859e4d6b63ca9d29990b6d502fc22b738b203a83d597b48d73c41860e4e99c57181f5b02f108ca193451025f3b368cf2741244f42b27cb9e57260d2e127ca166b32e0b9c927b247b31619b1d4000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 86&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028b391790c21c0d8d10efc63e6aaacad12df1592971e1845675f8fe28359ae6b7c030d99ddc6fa287f7f0dcec7c88e36d0ac760e5db970bae44b0cee69b9cdfc6606e3f868f3da257aa0b1c9928448789aa61a652fd352367ecc0af35ed149b18d8e363326b3e5708fcacde79e284ca2aad23c4caa5ad02c4d5d729b610fbc217790b3cdf53f4d9c9d665289d6403ef1f686cdb4ab40483f06ac469c8c358258cc190524f7b7f0227ea9b62674cc27768feddb0486a3abc362bf6260ac9bbeaac04becab0f851998039f818c0e52f915b5a3a234d2e636daa2a0ee2989b64b15cdfafa31ca792b8d62547615cc84b026a6b4bfc9b5d51c610932f0866f6a826e3735ed4e520f94816ee1e80bf8aca467497387a9f88c15939f52b057ed79b76b59252b7c7c89b0df5ecb854336f1e19d6adaff7496de3935245a4e90d3d9dfe21991678d293bff27b5c3f5a7cb71e9f75e9a14ceccea1d58c1e49f5d4be5e30c89c0536c32b6f7d32e4d86910280e6d0d4f9cbe265e79a56390871f5a97a2582f9f9f2d17638e666bbbffc6d26189c1f4a4620c9248c3c7774b22c705b93d501d6eb7e0e88f81d78c9aa476f6ba509befcc9d4afd2535844bb78c96f76ab19f4435944328da69be476b24d8e5f37b2aef00c33049c488e776dd468c9e4bfcb6492434c5665479850de3543e5699014b8d2693acda4f8193a1ce5add99623b2aa6518e2cda38769391459e6de3f4187101affc30766ac28d78ac3e0bfe68b19172ed82be41992dc59e64c0fee04dba029a438bbeda8c97b8d1a5f5c0dfaad06a569dae431348ed5ce0b9cec629e2d859a089261c63adaf26b1e541a2110fbc0e1750a04322d3078f15f18b0a24fdbb6cf5da73528466f2f904260b61eb26486a3d37ae37ed37c2f36a251edc81000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109718a494087ac0a08560ea63b2e04b9b6a766e45ada7e26f0a5b5e745adcc9286bfd7467f91245432ef0e180a5a56fb9a9d7f6a69248ba470a4b671d649148e7add35698ad60f27915a7315ab4832b060e7f648ed5b852fe280dcf3517914da0f5ec0117e11fa8086666ad97e3885aac8203999026fdc2d5ba9fbe243efa503c4aa99ec637d13ae05c406d9d16972641a5f9aaa551050376b89e62afa20076a832514421274b6265f543cffb4034594bb02bc28179ff15aad3d845180ae0e7059d9008360320aeb57139ea3a22530d844932d205d40382622e0b605fd57e688cb53c57a415fa0e14c466f47f2aa52ad54ded0804fed6e6a92431e0cb54b64ba70ca2b12a91aaae6a027200a8c697ae6677c028054187446172372aaf609924a4d95ece5f34927a2469d3182cac3acf591c98e945803d0cdf936894e231653512a82653328e621f9ec5e5b8e7a9a4e11073d42c61472db6879e03a348141ab24907c81eb5f44074d68425e55ef2332164383838f1245d89025df5c6ad186958c45029d3078652613a37a3521e8051bd11afa06f4928ee847ae155ac1882709260fa12656e9426212056ae36495a6af4a178a259870b3b2d35bf812594b823b9d8a245872e7a30df01372e34b6d4cbfaf71eed92440b4142940d8192e57a4aa36fbf318b28b8dfbb72dda085672bba0c76eb9a72e33b939596d9cb9a1157b922fa52e1dd78bc80ba6b44224e2a4d968323c80944252264d0591f79db4ac2222d8a05233bd4a193a31d45723d40640a24f4a3dd58ab65356eb81625271e7d2b6a229e9508157f7aa50582a0eee5d20755119f10edb5604d65269ef006792dc3596032a8fd088f023856295c2fd25a9991616c0ff620e0b17a782b42698e1f4a6da4865548ff8072aaf976a2e8530644767bf6ac422219e9bdd2721b1e4be021e5a283ac01641fc836e2f2473f6a3a6e852bae3514291feb408c71689ac118c02b7e9cf9caf7be227c77eddeb37451cf5b21a2a7b0856c40dc2ecac15f3aa34c99c93ddd3aa1f45315d60cf108e48f95c5e2a3b11e36b12fd99297e8a30a13236d320d02da2b944d025dda11b490ea3066ed83c3895dbd7251d693005e7b0189327c4966659cec73c9860f63f61d81082c258558664991d38d8652d0a84d95c27bda7e777d6c3493e926b228a0bb82a95fbadc90259af0dc2053626605a89ad8e1939d83692c784268b6091455b8be63c448a62303a60ff6b954b73bf507b76526868000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b58836254422c7d13f1120012fb9cc7cdaa1d8b72f6fa3943aa7de75263d3df814bbf2e80c3a204bc0f9ae33e4fa82ce893d35c57e41c7147602be12455b00b7949a3195264a3281cecc3fde34802b28c6e1f2b505ab6087d453bd6aa067b2370124840bcac4605ee4f14edfc4b4ff19a4d7a828e60156b49b4027ac18dccd20294f89ccf03d0cf47bb2f22d3749eee69ee17ab5d8e4dfccf36824d23e3f95e959d0494ffbc712ce3975e3a661b3f9e149a0234f691c2d820000de97cc016c43efe958da469f740610fd22b64d4bd2e30075e22bcfd4ab41d952d2394fc629f016ee1cd61aab4581f62a7b8648f8f8cf02462c81023cbe2755c91195a5917fe5a8b5058ecb8daff91dd3f73fe38665666dbf79cf6f203faf94a5ca3f3affaa2c2bd5f5dbc011daf46fd7ceb74b5875e4b5d80b6edb9817106b91865267e78731662218c8ede73e588256fb1ad57232aa5533d25bfc54452612f0c2aecae6de19355e1d508b888d18ff9f6d7d68199755cf5c210172f65342269ed96c77d80af8a244b43a99deb49b97a6f358aadfcff6aff72ab39540d375165185f31e0f1a6f97722ee365620bc5d642f8cdc59f7e84fd8615f4a336ed340be6ed8451997d87b7904c1b9a3a0bd1f8a01afd6a2d9f5b995e3fd0d44df8fbc8389b6cbb5537816c91f0efc3d2349f15eee747b254c5bbf9418bb979294423dd6de4d13484408362582a86d082350cc79ebcdcc05b70110a038736034ce4f3dc1d17e5d11c9c7620d40730b61437906933193d1272f7c89c701d495ed682f1335b7e1c42c994e090a67d932a8e825f4b9eda8f2a94b9a1f11f10e91396908a9d436dd01bae1d1de2c6acf458c0880e3f81adc2240a99e6083c9c188982713db243028ab07df407218ca6b3c4c93989ac96d92375834b915b724f2a105d6240e52b9d7003c67ff76f7a325d84abbc229266bb40d1dc8784ce1a4a6bd17972cdb26c274b06337d525f61b5bf952d23fa13757460b7b8a3b99eb023831f4fbef72d62931348622041ffd12634947579bc6e16bd1eaa8e8b2dfd54d74efced79ef4ff31ad42036debd0fda3b7f3f8e7a3f45955f82936a67122cd42e38af646cf565e294f422fac1e7d274185896f58e9d0fa1fcd3f4d379ecf5b566586246216556939bdf86d6a417c3bf77c64f95d7de8197ee25b44eef00209d33159710df001372c3e3d09f24b9b08b8938c522690674a7588933e1ca37d2c14df50777806ef6fd2285771a44f6de90475c6cc314df140c3962dd9d70c54e58cc5fa3302d69c80c6511d9d42a51b7cb7fd7fea8d8bd65a66fdb2ac80d945fb7ec72e138f5566ceb570968d84b60068df20c6cda2ad48372dc97424793fea8d2136923070c25f47c3d10839d1747b613b93530968d5e97a3fc0f563bffcde7b42c839efe66c3a8655d0ceb5af7a37d23dbbb52d05cf6fcbffa7c7491703349819ad94ce218912557d6c87937b2e7b0473856ec78713c29a02cf7b2b38e0dfe16804af6c2ba8607026892138011e06b4af179d63dbd97cb917b6507b798e58d74f485d3f063c044211e428fbffd5af2d7941900299602d3b15d5d600b435d9a21948b8d87a35205a3af9aa9ba491d56573a93c35af6683655e04a7a17f1b9709ed83e70d82a3df59a2fb7c051abe508601f322ffec089c49dc666ba04366c038ad59d397022f0f6344255f4d98bbb17120441cc75107005a74db35459c63770547a4afe59f2703894deb67612448ba7c4f6feadc1717f6ace410c6be62ac319cd33af285d17d55f500e364a0abe71d357ae0802af464b6d2732f3fb94bdb3baa497f2e44727bdcca5a4b65ae9df189ff1ac640940ff4d479a8072d34ecc523dc8fc7c87fc89a540485ae7bb3f29b041446ca427c0b48ca7515a1e31788e8b53e1122d372b6557f8d2a97cde893b20e60283954e2934af340a358a4376dd0cfcbfe305a2ce7b72dcfe2de105cf44833f548d1bce88d34b60bd29b69309dd87f4b91de10ebdd7d7f87d6231307d0ac784e0496db725ab97656c34e60b34b230f37e30fe326296c4e1bb88c0bac261df0e5f45e6e126103eed6b1ca146d58140a8893d847e92d9f3a0a883e8bf830147cedbdc7dd42c1a58a826a8a827f9ab26eccf64f68e9ca6b68261260b659b47e0dedbf5b077982b24ed9b36e8466dcb21ee69b5e2bccc49a163b4860ec2ccbd65032776dae601e18ecdab8e35c2760d5758592f6cc074298a97fc5e82e7da84036fd10e0725a0e4e58cc4db30499abec0c7d95d88bac2c58eb093312779bc1b8619ff2762fd1ff009273456d829394664c31ff6d7848b27174b36e59fb65d6bef6d974d5038a28f49ad465b28857cc12baaffabf3652c2e22b46b040e579fb040a0fb4b1daf0c157d35407c0b78e305ceeb232e7b7426c95639b1cf7b079e80521faa538e51e69255576650c3a16e143d0f815d2cc89eb00aa13af20394aa23cc6aa99a9f297d886ab9af2655d53816e066a02cf21c277daddef3d7d0825d094fd8fbd5386139757efd0b7f8501829725a4b70ff1dabf2958e07ed21db76266a88483ee7c51a7d215e1b41d2464911abbb1dc71f9613ed5446e4b0c97bdd47f22b372fb7662956fdcf3b108e0107f74301a054fb004925b041af354c04c20fd370ce1a014ebebd8311f3265a2f78b48124521a4aae240d3ba9f94fd33ca4a92d24a029e0754831869b58f670435a44dcdd7bf75ed9ff06dba52980dce49c1c26ba0965de3623f459e36127ac6afad4d5598fc45a95173d039cbbe2cdc7dab2865fb6bc0fa8dfd33c4a826cfc77bb7f45cb5aa73377a27271ae41630dd3d4e2722581537fcfb233e5af8f04ca824012b5c429ea498f4ad44afc249de2229fd7266fe84173a5ce44632b3650d6e1f278625d564b374c10c1afa3f17432cbe4b65327c6b6e0cd2f99b68ab043c5c6c99d7fe7fcf940f4887d309d7bc0ffaa5dc4b90c79266514f46ca2d5477f2b84b04e30dcafd0224170fa6d4ba9ad2a6dfa8ed73dff9d5d40d43f02610032719a7c5646ccd453cef409b4325f3fb6d9b9201fb115e4dfaa0b4d29959a44518774e94b2d4d6d06c7f065973becd203f5cf6cb59f869340ec6baf0121049db3e1146234cee4657c1b821af817da27bd4c9b1103c81f5b5161e6a9329d83d6e4dae1f3299858cd201222d34a85e2991bdcf32e9771f3e701897f647d62729c9805cbf118c9fa727b056a7271a23181b92f033de1ef113a856a884ad527b8deb92085af3db509fdb0265fba3376b31bf753dfa477dd5e247d939109f31cd430a692bcec4d9fc7c5b4630cab90c64b75496bc7ca54d5621fe3315ad03ebf1afd6d436bd2dbcbe707b35f916cfc147bbb5b8ad2e80abd692834e42e0724c8b901f5924212c4129f7451b9dd860a85855d1ac59f0b6b87a66b6a395dd81990aa3debf64c91cea6862b5793bafff81677fa2928e950d94a6333b0e77a15ae461e710be70afcb9fe6e0c21c5ad188e439a6e5138a2c5ad17126e759d48491e3f3f93f81eeb77b7b3a6add96917cf0beea202eea5adb3d5593a3dc9ff1f8f05dbf5a2707edbb6640eff5b65a0003cced2eb480942a13c1f1ccdf9994f1d11dbef0d3ba7c3801aa508c17bcf287a928b635f475195d88adf9f4c1ca7d3d1462dfd0f6939b89e5ed95f177bbb12253391876492bc01aff1c1daaf0a1c7821c2a4e33f52badf51987e010b391fc984328e020206ee98e9c8e6763120055f99725e48356fd800e11ce973d00c800c353a5df8b028e1e42f817c7433084c440e47532fc639172533df35f0ff43257841c3e4ec7dd7f601eaa81e9886fa3253844c195a62f89fa5d292536be8cacd80c94bbcd1a83c985936353c9233e512431a8863d7d8340e89307547bd10b16bf2c7e0bb01ab8093c70e4f4c8fd30608fa14ff072d81048391c07ddd82475a280d4edf81f739ad1a13bc6483c3c37bf52ed52ce8d568aa81864acabe225bc6467c79fbf43781f29b0c508e6825d4e56d25e45a8c0c6298765069fdcc66b2c5492fddfff69d6f5975fcd81041f30ffd7813ba3219b3139583eb588ddc57851e581fbd5e20127ebd0000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 87&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028d399ca20d4e3909bd093e8ca453a92cd33e6b85df13c9b5c4e8f2f98a6dd4f8f787e81ff4b8b38e1d8e23bfad106445a521900cc3ad7bd733c8aa8a81455a4a77865ad9a1f759bac389786649da39b7dcd75e4c0f876af1a9a53d533c2e238ff2edad1a852e3596c82ab885f3f24c29c8d27b7c56da263e83cc36d2456e51b5c6a2589bcb5ffd5d3bf9c33d7384c3190630882a8a0c1482edf611c65902c9a31ce475036ab335cf7f0bd77a95c7b60b4f4dfc4a73f06aac5d306873f586b78e9363ab53ad41274777ed4c38bf71105703fb5b49a515ddaaa30039e639292789f4d494480eece5f123366cb1efd4ab18188be9c9831b5ae27c83dabbcda71f0e4a0c29549368de3fc6575f934accf42e6f1ed7cd0860f97ae0dbcc6e6646e9c0ccdfc9fe87ff1d92229037ce83407dedcc258fb8503ed8d548ab52bb08550b668a789824df2080f4520804248f7f9e31a9832db49cc6723ac35b35a48911aec8ceed64ee6b3ef52bc2a6f3ce1a4f691ee3671998854ec150bebff534c50b73595ad38163926ce2ba17b75f884f55fd618a4da6d70cd4d58d676ff0ed53f2a0a1ef2b3cd5624b8d65e04cb4e4f99b56d9fd6d52f09741f19656074892f2e428051906e5b9777c4a25a65ffaa26f7690e250f51b4d044d7c442b2681f256b7b27b955b343136653357602d550a4162b0689a1e4479c1fdde55347fc35aa45e0ba5d6caa855f7100fa72d8af057183c832baabc9068caa3a66c27d69d7bf11c4fc5d7cade4dd9b90b412868ab577f236717bb3fc95d8df9b2b58f0308c9c8d6cf847614ea23c79e4e8045ffde016589b5f366b5c6ca38f0554c6b364f648d77c2513deb9e7dedf0f7ef524e023cdc56b3052d71ae246f5b4bac265a9c5a37d96830d983e99432f88e7757e892d0a4c8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381092570afd8692d941916614a94c3939f06e619580011938062f40e957617ed0f60776400b256f6a8c4eeb70722c83af4ebd79ba6d4c13b1af06cb48536ad6a669b110569c545087f2c6ed21447740844c1b28ea3b40efe97f8f81d0571c00e825b0fd8583d9a441da7f841da85890a982a28b55f08d8caea58682a96f25647ba1a95e01847d31149a9817bdd9e650a307584c3d075add148fec91643deb59300d3d0b0a42f50b70c946802175a9f6d4892144304682a555f6eb372cb1b6a81d46d79001800a4fc54749f2f13a976eef54e29e87d5d34c69dc423602ef1552f0647ad945cb7790aac565cf590bb5a45af1a0e23aed48c9accf6b31349186fc8f907d196426c517ce599149e1474bce81adba513c062a891daba2261ba1aed9cc8a362414a131bc2ba84a8f0319ee628b69b725d278d5d74b19b9fef94a15521783b58e079ce55d67a4c655da0a5d86b0287883970b87144fe15e80a685613370845e8b535ac1a29240657a294cfabf65a12649a6256aa1837d84b041addcff4b2564dacd435e84d17949af6865578c69a866ca675bbdf0081bdadc45c5d4c572dc6ea4600077be4469316c4d5abe4b7e4b1630719d4b51adad73a7d5ed39563d4e13feec954f4cd3faa699261100c800eb83620abc3642c7aebb1e126c1bc783b9633a0d2993d03d57f2eaaa141ca3008d3065f34fab18e297b398edc92d9eed69b71f169abc9189ad80bc6fa01e8ac2c3ce5119d28723ae81ade66a21d743e038c4b90143aaa4b79c68041a99cd51faea2381282b8115fae919812f6ae4a41be3ca6472513c3abbe66468320aa53a60f92f12fb6b47af1f5d7469c46066081dfdb1a0ef4b785931bf0763c4057f943c6ab16add81ccd0060340b80d453d81ec259b1d15f8d59d6f16013a74faab103580a239b59e93ad364ce1f1b91f9aa488afab4c0ff68dbebf24de143a17f970b21127dc4f083c0b12ce3b02680357510f1d9075f0e2addf4f58eab2d05008e3321acf554b129c9490c904f7a7e178518087b5dbde3f4239504febd6918287b6f968396220a6d9dfce7815e033183d8a5e42194ec2e15e377c55f69107e620136146746920383d5cb7a3a55edaa8a5f61ab7ee8b801186c09ed87a03e840d15888bdad6df9778795dca03232089265c1bfb433a75b1bed599ee43a9308af83147871c5572611fcbb1b30aee20b8cc5813c1c5045c6719957cbdf73b67354da5ee760c4fe802ad681b07210f9aecc0500d6e86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b79bd2b4058218a15c008a4bbba29592079583f684fead3e6b3f09abff0dbca23670ae4496077d47945e5f1ac3cd4add5763581285d80dfb43bba9c0730858293ff6a15915ab203fbe65c118b87ea37dfa1e06cbc0f24eba3f43a8be17ff1daf4277cda2cae8aa924e852c9d60524b98306927746c4eb26dc9475e8a0d0f920f33e1aff9d07ea5561e70865b2d8161b86fdd7638e7a72345dd72ee95bae1ebd2c24d2a5510abe3fc2ced397a067d215f6088d63fa63f2247427917e5c4fba14f0a22a04fd0ac1d948507751f3523be2b0a0cf2f96dc61f8187adf646d6914667759d49a6df9a327830effc9470cec6c82ea127a8b0c6510203879faac4323145931e146d962846bb1a6e84cb2c31bc686e388c853413ea7d3ebf7c752c6aec774637ee01f2817a5af133928af35f23fc3541fe7fa749a863a048efed2f8cc2ba86520b97fde0324c68d1ddde1e430c30ded0b25664ea676aac6b1f22925a40b319caa37dd5dedb99de4d963630a6fb0e8b00ad8f2a2b9bcc497a00099a70a9dc190a2ab2a058930e63fd6df342a625e9a095ee79137caeb8885117c7a9fb8df7a35d5a300d6f7eee40578a7507edc38a0d6522474e672f156fede7e1690c3bbdff40342f1f3ad3c34325bcdbff0a68249858c777551683a9f3af225163c9323a4ad5e666e0a9f44c6496269038aac5dc2767966c1560c5a09207406f3c47157d2fe5909346d8acbfddf3e3d19fe48b7c60e1c8cfb2eaab19e736b2595d33a0aa034726cb6146a01ebf5cc72eb1182b9a4bcef90a1aaf74079862cd775f8f773bcc490f6015b4d5469ee0bd95c1a32a1fbf283fce1fbf6f8cdcfc1884f4d2a899f3e7a95414de419d56462f502ee703cdba007c3bb78f20243c35b882c90cb7de3cae3f0468079c546645977347bc183fb0a6cd24481391cbdf9372e2d6765b6caf8eb0145bb269a47a1b4e2cdf9901d6aa284d919ba57163ab9929e715341bacd81f35bdbff36d59a1edabff3cad2c122386a6335348a3170337b94e4336b2b74e791981656cb5234a6f84db4142d3f323000fa98be61527f7548dab6e83928e9dd2e461f08a5bb52f241bb42254e5746fcce0f3620abc69a6e275b5e06a333360f9b809562ed116aa6cc2334694aaa4169310ed6af695678de22d3e551daf61c0a6c5f6c0f36fd3469a3b977f6d295e75abb804a43e1e7ac4708208a94e8368dca40856f1d43c9865d98f69f1c0ba9c8b33ac9ccd18d400d2559b1cdd82a0c875b5e136b97c02126c81a81eb5d1e421221564100450531dbd97bda77c1b0186527ecf526ce6bcd0add5668382d984af9277a21d40c06eb4bbbb0ccd6f64e90272fd632d47a388d301377ee745fbc9cb4c02e1f096ddf303bca4e1fb4b6df867676080cdfa6a29cedd15003ee636db8c74e7e293a087b1a5f62334585369d12d9876ed0f334c6711146643fd598f0d69bb3475d219d1f89066644897a9cc5630bc84c0cb5844087216038c8fb6750d0968d3d3e2d29d93639486c76dc045900ae1a13529e74beceb3338684402bbc3eb36870e0b37584e9f309bfb0dd9b966f0be1298dfe55d1a94a6767cae5eb3120133b7d7b71c9f2a538a97f8548fb176b0e8923b14af28ae26306214f1d392ae63c3736b9f9374ca10ebe93370c11bebeb45d066477f374866c8a7208ce6dcec404194bb1f833de0aa4700ca29681fa0f72d98679dc3e1e142852347b01daa08e5cbbfd242f7223600804e066fb5c98c8358370f5d390898fa44023a30f824f1c6a95b8e23308b4be474d03e34cf72be65f90d698dfe0d2828a797bbf8397ec87ab9ee00c76a1c7b3ced0100d3a1030136cab9a69f05cbe58a4a56a9c700bc591b87783de59369f2e62d5b885da09f25835a6dc06f954c19b347724244fda69e3356a4ef60f6a41cff3bb7cb22ecb128415cd1b89a9aec12b66f1ec23b14e7d7fd601ef7b000a0c96f386216f75710eb2c12817daba1d1295e7535331cb90a9b0d8f7542e73de2d93fe554063f57274df27bfb39bc4b78b72a88473408086d8df531e53b5be018e076032d1f8ef86d7afb8e8867b9d7728a25acfb6856d83592cada4494977678a9f4d134f49a8598a8e0f23d3b7a09b5308243410ca6f47e0bf8c43871600817460bdeb74e7d32c2ff7c40ea4bf924e795516ff7c7bc8e5fd5d64cc489f1894c6bcf0e9c312b1ee7e2bc68739372e7402e6aa2ecdca39c18d7441f0ff373946559c475e37d4ada64b98283e5a64be7bc2d1a1c148d2cdb4eda35f591d3a7e7ce15162f50ff1b025f87cbb82289fbe7f9c32db8f23012cccb87aca7d758d42019b9a8c15f508cac9284928f46f0dc1c1b6c6b4da030db9286ff8d3762ea4a83d096ae04f98e9416d3dac59e04f9e4e4359ad76926bbd9570a3d5811f69a1c4345b646bd946d0168ed62a7a431d920d707d8cc7e840bb9cf13d8abae8196d9177e8c28ce0dd9ef647eaaf0d3c97e52cb31b560ea7067b45aefb5ec2b7c7bdfa3996d1c7e467636bfa1bbe11d1ccf86b64ade9faf9287a23502e9ff711ca97d6cc09de814a67ba6123a8e4e67cf6e8cb6f7b36621bc6192ecee94d61860703ac8411b16e19644a6ab01813402629af52301c9d76a94cee22b1dca49f13b130028991c8ab383c8461433383da92ab34f1ebb4124b24c6c391ea44ee6e736bbc7a2d4660a878a600ae39b7dccaa51adbe90bd705ea51ad13c05e611749d43de336d396352cb0673abce7473decb0fc708ef28dcbe18c85ee0068fef64685acc3a7d0da9a21dd0afb10b95d81f6ae437022218b6094ce35d01248ea85a9ec6fb56a7a2a8453eb03e6ccbea0f2eadb015d8be3d09739eac07ad9e3f17d13e5f71cadfa220ecae90ea50bea87b19ca6fc5df31874d51723becc80c8845c9ea718454d2817ef8afd99b63090cba6c8089afa78770222fadee3b3b829cf36a8153efaf2cf28dc4651ff37a8921e402ef81a0f457fc1802ab06a759bf4071f082bfdc100ab612a4584b5ae19354854101ab0173d7d6a5a0637ccb58ae58978a8befd5a2c51d3d53150c336c0c0c2a27b442e2bce120c4ccf8d97ea4584434a6f48c0245b63b2255bc52adad4eda9279412d70be457f7dcac492fe53c06edeed766b46ebc3419e6da2a2847251f75c62a5fe7ae74f0dd5af50a447da6356dcc828c5f1a2c0c873e57041eb1158296c038b91f2e13d3d4b2887b284384a9ecb8bb378bb311f4abb19e1b90eb3a399c03bfb4ccb29aad80c55c1636559fc79a6c894b5bad8d529bf680631541a45eb0e57ba5b458a05f456c60fbb593dae90ae549416af96642a486f10843482afc3989bbd1e8e4ddf0791204f4b720abd2d8995c87c8a388ecb14860cf83b7a4406fb6c8c9393475082d24e516c5f1af91ceba444d8e460d0695746be057ea8d76f8c0c80358f3db2ae5b996272737516ef5e4ef5a1fe5967304cb6d00090c9623d29f0d4bce8ca3cbd54a30f9597e01e5845c1cdd8777e18c5d5d86492fdd0606f623d11a28dd9f02032e3a378c71b757b52021dce6ceec63792cea24d6dd7150ac8fcfca6554f7b08a5529d59628d0f35122504dd1542f6291bedbee09f81aa744a0f6c6dfca6207fbfab6b9e17e8a4040741f6508471e72d227d0fdc50c13f444310245ad17bf819ffbbc4e0485fa68cf1f0a4423f251538f25da989abcd008c803d368f626438432569f12d1612370e4c6c971079371081b37d8df7ee709198aaa2fcbd443b96732aaa4e6924a461b60ca4f4cb13e88d539aad709a3db84d2d6d26671a9f3877125b7a358389bbeea846a32e949db9a7853dbc7d5add92729ce1b5c00680974f3ddc6a8235c7319b6cd1ce5e0b66fe7c2f1115206c42b4c02990d79efa8be94927543c19ee93d0ec8811f9330693696c878cfadaa2d56e877d42a3680ab2f6a576fda7bf7957f781655cc664a0a4a0d16ce34d04d7c98a9e0c93d2e6d42870fe66864660b564ed4f881693d466bd68b6470af03a5a6e703dbb40515af5dca7142c4c8d79f5be4bb01a1b56be9d0936396a7eed9a84da86a4f00dcf676b4942d5df6e1378ea26d9118a54e17fc623b83aadb417ec82f9afcaceabbdcfe2f0b6ad4bc1601b4e24f547d61d1c1737adbcb46d98287372c00000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 88&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028d390993bada2925f8dcb73399575c058e13a00188fafcc94b4a93df3a33f50e4737ccb6ddb493a6056f45da2bbebe9b679c42795c4d9bd4ee5471f065b2bbc1c7236d6be4ff5abb2a5bfae8cdbb330ece62852eb0daa13b4ab5234f070ea4bb798bf1c8575a6b1c884ae0b6f7e4453cac428d177bb0a85f90f0deb276e415eebb5a39fb86753794fc196fb57f6aa712adfb8e75d6e9061e6420fad29b4898cf5e2d8de13454603d3e0b6adeb6315cd17456b64a3d49b490706eb708e642bd28fe4dcfbc7b2da4e0ffe33b839f1ea6a01d34cca4ba702d9a5886f40c3927e77f22ed529cc1d0da8b8172f2664e522938e3b0f234caa8cc714d7ec9abc19d8450ccaf0751795aa7d199bb379df0f06f31b7c1d0d83db71dcd1121621699d9aab299750e0a818fa40c97d39a0819b2fedfd0e6f98dade2b959df539dd3d974cdbffdab8333b5ed625b63f8e9dadbf6d6528768f55dd4dad9e788561c28b69a7bc02e487bbb4993c7191d74f56d97cef29382671e669c892ccb3623dba7772cff502a5b298471558f25bb0a45767322e123ea74dda4b4c1a54817ba450b95e9893bb7539d4aa935e90ea9cc9f1837921711d588d9e2849a0f299c8235a6523b3e69ebce3affff973988130352726e7fdcd200be648b84857131ad589f4ad5e3cea2c93c1163b3d56e6cc954555cd97b69e55f91d0c89c4d0270795b5885c7ffe8640b6b62cab1918cc6734ffd63d3a8dad6f1556b391388882508520723d2704c222519709fefced74c92bd98a3551fcc677d699be17581b0c4d7929aa4442729ec7353c3694348a35a8378a467558e36478f9d58719aa4af55ba50e84f8e35d1e00d62bf11aa69b7d4e6948915e8bc1648f065d67d371591c308b1b485dad50df3dd4d6ef388ba1e9533a46cf4cec80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003810912a19c5afcd12328c576d6a38d0366c455b7db2c6350e99577ad9bc8a729ddbb688ade4fb257eb7f6827b8eda7e6aec2898c995a844125c865e0c8996ee8362030d720772bf892caa7c2345e76967ec8c5118bb5a5115f0b345ab96f71288bbc46a70ba01ff274ded137ba74d02d69da72d5d46316e74991b5fcf85206002fa299540c66362a9dd434bc9851555d66c72295515b51c1598b836e9d66ea8af08c8f3774f01768d453764cb815c4573f8d894621461e5228097dd9aed269b015e235035e95963d33c7b323ef63f903d327060e0e682767cf05159a4c9cd05b286f64eea64ab5e16587817456ac01d81382614722c2d563deaf228081fb41de3c667f20d6772a8cd829e988a5c86071271e2879c1ac5b022cf8332d2ab608034ebcc2de8735019f28f1a1992cd22d33da30757342c28fdafb686ea882a1b24760d3d2395b30e603400d8c038d57c6d6a9ac0f294694780ce006a62737f71f968c463bc1eb17d7a2b230264086a261f5a4644bde1f9f90f1912be8dc514962f11381f42dc6254883042248c63129f8cc68b6ae11eb381a702e7e1018c206f215c25c14841a3ba1aa0283242db22b7e149a8b19357165b82788866228ae8e3083c92416406dc3dd9eac11a23d97fa2f94a7200d687d4bb202205cf5fd00ec17c432640ee2e76bb84ec512afeb643d59a3c7c63f02f93cd11483634f9c28a871c79539cd54409feff711c14b689d8a206f515637b89fe4194218933bd6fa02ade32203ea15a2b9029812650dadb583668def8fab09e4745c8d87084e5bf18c9da11160bd1567966048a50e495bc7197fd57e0440e7652d78414a74aa8f1d010d1237ce488861f455bceaa42971c49ac008debce2d0677a8bfe70d54f672f03f346e8b8f59c2c0d49c144762be90164d57f76eba31e436143958d0061a9b29e85c744698f2a5e200cace7a881e727d6d764bea6e16ba043566f3419f37d5817981d88316717cd62b092092add7a4e41dcb7d5c3b3229ceb3389c08a41459647c8c737ac58dde821eda81c1e80c955d4df7cde5cc714e85142f2dd6ac56af2bf08b60791eb4818445fa7ca5de4523c84e7c4e5cda5604d3254127d4f864d953edc388549c4a2e7ea9e0080eaf3b7934e321ec24087c37ea729aaf8b6205e733c8d09262f2b4041ea882b1da173c6e599f0cfd32facbb1af32851288d3337c9022c94968fa5926ac5999441b3a160311486fa743721fc64d915e556a5f609c56543408d7c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b9a4d83349dd620dc2cc0e9ada524b9be9b195973a839a042f4342d69e6b38918507a9747fcdd8b751d7c75abce2b482b3313d4c74ea4e7a4a91f2e08a059536b651508307b7f4c3aff5cf1579f90f32ba1e847778673e3956713c14661afa2d11ccf61fd8f9bc914d4b6e6d09c52aff7fefae325c180147153c9ae1924c9a2b8de4900bfbbc6797558b000c5adb9a8dc4cafb458ad328f19a2c55d5434bbfa7be5057e56511529709992bd6527e913b46abe38dbff90d4ab3c024a66fc0f8fb34afb96e22535a0ea8f313a087aa65355d7d5989c486e103fd526a7a6d812c0e4d8c081bcce4dcfbc64b68436739451be0c4b67bfca71be955ba9f9a23c223c7d0ffb1b2196c9c9845b6af341a363951e2008bdc4f3296dd0e1e3f480f2e4b0ec77a002eccfdabcc58d24cb0baa26eace96decaa0f6bf1cde0175afa65ad5c23c5e71b50df778208edbe426aa6e876c12440d7c4fccb42d039a14509092784baad37d9b8edf186cd4fcb3d9f8b0397e951777d602b8af613060fdab6b358302b3fd28437a06694f36ce12a035f09d677e48d077cefd1676d8fe51541bc19e3a6d6a5d879c4f9eb4713b7c0f3a652f3a05d74dabff79a302fdaf147531fdd57924f49e52b298219b03d6df166b481f232fc85c7cf52838969ced2dcfc18dd8c95891c498fb49289d1a982922a0fc02c849ac3bb7fa92cf43a64464d5bd919f75ada287fe657bf61dc07b3808c0fd0d71ea24de5353268b2c17c989c29465ba49111cc479f51a8cc623cfb6ff68149e52c77a7d85b5ecce66c05900ab9957bc7ed39e03649a103b5b6bfeeb168b7c1f30dca84aea509fec2b215dd95558a2708839396552f517a8fda28c3ed61f84e1b2e0dcdfa708de50d44bfc65bd4e70260c437c8b5b7158ec7e2301d9c7aaa68e0adef89fdb601711ad2998379145b29ce3681b513dc3ba9b2eb668c1b53697833670466e21e767361c0a4362e5b8ddc38ee6a9c4dc5205eb808b93c72ffafb635b4254e4f4496bacc753c8ed0bcaa88db683ce77c8165e8ddde665392cccd57bc07573d83cb3aa10648281efb08f92aacd8ab6f9b5d7fc66d29526bd57e421220ffe375b26c61a0ddbd9807022eb3b4b681a43e7719f5ec255c1e19ae6c542d6deef3b94b6960c18d0d7c8110b88f995826073b874042faf97f1ff034b8257418ca269f5ca588223393b0179f9817e08e7212d0d410ea259ea66bc4a00e7fb1190a732bfdbf7adea0e4550be90c3e37bf33baf436955742a2632aede259235702ea2e079d99a22c9755ed34c1e3ccbe746e728a932b1852f692b103112b303033ad3ce1172aa066860df570d21ebba51fab72d5afc4ae8995f532ae384cccc3c4a295af76a803fe076ccc920a80d82a9b614760ec43208579ef5dee164356d62ea33953e55195eee9b2e2018e6fd9d19a9f49258702dbaf6edbfd093919917b1b6734f012e2beb4f758dd481fb8a8d7796e755c6647501e28862b9f5b16ffa1c5d80dcb07141806fc348881a5a8891bb632a4ae4292a102d71504d0fc12c79d15bcd0799d30c7b9e72625a7df7dbc7ecf9eacc627ca9ae5d71e264f2f2a9d5db8593f3a90f3915ce480adf800c99fc2c8692f2b57b492bf9d84171f8c29af8d5549f82d3730927096ca18ff0b0c0c0b8b800508c44d5749b92d7d48f7fbd5c86e408ece0eae639af475073df5ca2cd5083bc4ff8852ddf5c399946a6b21b0841d137f583e0dda3a6046f082872b783eca3e14b21a2af61bb150847026f2371812b1a2be72024226f4613da860ac2ffc578dcb171dc27b896eefe49f885f9be4cc8766f37038e01cf20dbb661f507b2ecf2b023203a6259b0a018fc00b2ca9b3107b605f04388d5493ae7cc4bdd093ce761a92847c2a167739e0750b427b2aceb3abc5ff751a5f32d36b589787d4da509c85ead751353ab2c68a9c14b8b2c8166aeb6f27c7f101221c306aac74aab6b4e795525fe12038725d7af3d2a6d60e1ea85f2b94ea24f1b72fed9ddad4c8e5da484e80a2150de22e6adef41153d7b4331e8f011a3cd48dab02876b067312d0dc736e465f99ac3c9c56321507e79accf652e3857c749ad92dad15350a6b4b67229a3905db18ab2053e2d4f92f156a1d76d0aa891364002c991e632b53fa217aac1709f37f3402f43b0753361eb2f595f9fae3d7d96ff050dca0b9657f4c3ab49ebdbfe8816051c4e0aff32c5137749d53b062cb61f7201171b5dd716e9ccb38d00e50955596845dff602200b30d375a854ca4e9a7276ca1a1d9ee92a04bcd78854be251f7080aba6d8325d40b37054596ad80211a50afcc1dbc177600a70e648d8beb4fcb8919214894cddaa6d63b6f6c445469a6866721d4bf1117f25dff9d65fc8fbe5b0acc8b9039c7f94b2a5cc6068a0489e2e13a731dbe1094fa8558a601addb9e4dab04fa744cd5b95a9d57c52c8124ad950a5944dee2c55e5c8540dbee5823daa624f57fd5be994bab3ad4e74ea9443f8b6024bd6b49adf3972442d88e61e04fe8478ff28916584ccb65fb15686991d5781cb7eda067745258ea671e0a2665f94fea1b5490669d1ee8711518bb911094957586c8075e3bbedc47be059053a7658adfa0aceabdd46e0dd9647b34eba32e56b6305653ed386c50e79e15084f00f003b1d12504fdd8e47d03d9f7572276047bd22b82b8e81f87c86e6f20d2a756b16f291179a97b010f993c0f839c9a1238cfc9bde8074405cf1b35df423c7566ce965681f21c969e4f3f8fdca72a18d5daa80287f53b5f8429fea81612cf63ccf1b7a13512db4d1dd2678fe1189398032eaeb4368332972c728ad726b7290302c3c5acab6e73432e825b9046f846adca9d93780a36095aa5c51e354cc6e9a910cabbe59130e98f4acb3cb6d4efda9e2f78748ed58465937fc81c548ad038fdc32aec46b078cc5a7207658a9706f1c9653359de6c4457dbfa71d300f98f9bc5daa14dbdd5ef20dcede7e9d3f7da5c932ac3338ba40e46b17d89fe38f725129991983d4a81321b394f2d7b20d66e3deaaeb6fefc8cff0b68a766e27ccfba66deddb1f541deb3c1892ed2ad5d073162f0dd06b82e8878477bc96e03101c9b5d9d0ada10ec060b45e144b31e6b4de283fd43538b47178398fdd15b01ed421ee2c65847f7a4e9aece2f1d13971ffc0157040782ad4b591dea0906370820dde1000490ab1c27c03d02a0f4b4bfab0e56d7257288441cea63175cd6bd11382e6c873154332e627ce82e37c63889efbd8537ac35c21ad7a09c986cfebf13b19d5677c1104b373f3b55198d075aac608145ff9d0c4c12c83bb41036ab32227629eeb4922f172281a66c23c35b8a3e92de0a10d5e8c18b9a54d6c30230f3a8263986ac535b6bf63eddaf6a02c9100b712ec4bd49851a22af0e647f259c2e19b9acaeb6147c476c90745a353f6252ade8212a9f7c215c0b3053bf2b4e0ad225e8b344ec14c1b839877349c3743e8337d9c1eb128b06939c5a08f60a46fa700723eb6652fc26440d9bda3c99c10ad0742c2f039be6b66749b77e14f8223509365053e87ed870fe3906a16da6c62945dd2112c96a23942b1e14431aeca7dfce3fd4d6633e0b661fb34b0bf05c4d21e689cac9b6abd9f507f08e4aab94bbef1c629c0e1cf344e66d3a3e100b615bf762dff0cefc5e4cce0dd908f46c94e7411a151e713fe0c18ed33c4c03e55e12c0ac366da5c757c7090e0f94e2c34d93ea3b226adb2979d23e071f18c2eff33bcf41baaf52f4b44e38675dddec89c7bfe858bfd1ae70d96d0487972d70f8d8681982656ff734bb6323aa91ea14c6330c71783d235d9f094cb111abc4990319bbf163891535aa5f870164da65fff395db68b390084d4f2448b98cd56103e49caaeb6cd040c3aba8290284e9b2bc423117f4104d89b1b1607c6d34ac30aa9e79d8753b97cae90ecada6cafc6100d3d6d91e20393e0dc95b981fe0edbcf88e046f74184a96705ac226fd26089468e432d525643293bda781b64bacbdfd6c7301ac42aed7dbbce7abb9d67af315bcc3509cf03523fc887e27edcbd7c74dadfd0f126cdb49e28ecad38080f18a775e6d824c18359935d921744ea72fe293f299b530d9dc9285ef174ee60e2ddffccffe89960baba90d955cd2c96672513c758142d29a1ad79ca9291bc6782b64717f11a71e6d65a1a71d000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 89&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028b39701ba570358b5a80994bd86f960109ba7db348be3aa5fdee6d034434e30a2973d072bfc44fd0e375c475a93219530ded97cc216b716ece9648da51b188caa133dc4ba10c4e75697cbb251264f60afe9aa14fa64d6b91e335100903c0eb69f90ab6efc706815d797fe5cb314b91f3fd9cfc013d88eb2144efaae82cf0fed365a5633b9f3ecc852c882d2eb51531258e262e1924606ce99ac396c168a24cb78210bb9a6671f6a9e97c5d962710b16abd369ba19fb1dd7aba8591fec1bed14ffcbe3843209eb966498dccaa5ef508d7b83fdab47f034f27cce430ab4b6870f6050ed01865810db0a034192d27519d410e5e04ea2e8873c199a266be2cbc923302e9367ca8cbf5654c239e4fbfa6d288b7e4392e414aa4d1b0488431cc670576eb4961f9a8043284f4af93fd6cbe0067337057acddd36a764a2573338c4404df08c7889caea1ed42ae8dea3c9e92b378c9e3a868d615896a73de64b0ce751ced1e5f3f0588f8553f840d9371f828350bb6916b341446a583b453b6a4fa822502d2b7a2ba496a78bb2474d7bd29533cf0facb25322dcfc5566fd68b776dcb17154284a185f513a2fce23573647e619ace22cfbf8e6ad65e6dc75f55b57a68532cc6b2050b9476ac794d4ddb72daf6b70a47a29a4c1e661350dfdc922b1a9696c9f85864507a67b82a8ba76663f8d2a7f205956d0c9e60f9997439f1565124f1288d7299aa8c78c9b97a0d8b891acd328951f957ad530c0a29a9c022c33628aa8e4faeb8b3a6adb3f9249a79647a6490230c21d59ad6336e47b71082396fa67e93b185e48f6b0ff089a5d0bb1f6d863476fa4e4f7c7e9f4f3b3f72b8c8b4ce023f1b71a57ec9ab60c5dbaa1a6c41aea761f8cdc74f84fbef5406c3c5983779fc465dc3f6ab681cefae5e22ecf200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003810949680898e96b8fb7ed90c119dfb3402d2108740e002906293327462b7818b404f7e46cbb6d502741ce023000720aa4dde4b486e4e3ea5329329d9608bc46d446e817e2f54753561d95fa99d564a8cd2fb82acc659c2d2ac2695c740124595062539399498273a8a25a91fd58611844e7b7b801e42c65a32d7e015a6765ec3f556456f2df2b45054b2af862c409b06919f96c17a08064fa8047c23abd1401ca476d90d0438b7f9bf923cd4ea3b36960656ace0adf5ec9b70618a41fdade658873719b0d3a1d358bc7e1d12f816a928ae5a4671b5ea3a57e90442091a7f8aa442b0230bdc4b34f5a8c0941a88140291056b5616fccd884c249c75a250108c6a636bece5f334ab9e4e81cf699882cd5808da2068dbc8325032469bd9ca3a386f15a4d33ea22478223eca5830fa066242a1d7aeae045011e2000efdc791be97231e9c9ee416a8b3526e648bfbca279fd8ff605e08420ca1011b78a0fe2f68b98623a7eb8fc4d8b95288f955c09f643527f078dc9712d9d2a21780937377494ca47afeb4d6c232070c5b91199ea23315fea0f093f668a413ca79c7c9806cc120615743a2557d123d01d8ac7aefcbd769ef777056150544530b586f588819038df2c2703393ce905a41a362177b7cf1b321acd73ba528a1225ecd8cbe72a56a9adea9821063c64f06671878fff18840817ec46e17d1498777a275c350c9436c6095151bc0e064b6b2c558a36f6c311007048d9542f54ac6c78c962cece25174802b321810b5dd9f2b93bca521a2d991626635b0a7adb25b5874a7be68763298e477e9d16c63dd21b70b459313f577d1058d504fc66beb012cd56c4ef4391f457523751135a480ce45454b579a88092fdd32c7a92d633938ef730d1c1b91152e4777896f420c14519dc3dc6f9eb4e685e27478e479ea006255ae61ef79214b7b07283d8764454c58929c59a362d58dd65b85589f508d525308ecead712d4a206819e506569a401e2caff85593e3a23e62642a189a7f222aca0ade2099981a05331e4b0c5ae219c91f805c8abac20f97d0a2a6b34976ca2b3eec14d273897aa9d40c84ce40b619fd3695ccd7b92c00890a32e6f9752598196b0898654926e7dc4ff78c4d12402bd9f4736cda21d826da29587980458b2a41c4d9a92195c48bb94ca3ad01111030ced20c019f9d190fc84611673b3977f90f2e182dee9d630f2fd39f150e5342ebcb9116e18baed9acb4087282451bc13905b3080063365d4a97444b2506000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bbbe0f434dfa04ec225ff6b6db802a047e221bc064e5be89a5fc13937ae9d3f22b4439bb1c1bba01547a64ab3e810bbb09706d01959e2e906a69ffddf0c56726bdb58fb039d66ac5d77c7f0e9a8617b0c69176770da328d38171f39b5220279186250139922c0dd0f7c3f96d48615fc66db7568810931d257b230258ffe9cb35f87859e08139ebf7432e948ee3f962bb9015cacb8499bc69597abae4b841b606657e2e3c51ff5a8961ad42177a9e73950e3fa150439e2063b6555624a6d8e3af4fd5710fbe722b8c6267ba5df56846a085c56444573d692d5412cb70e443761751e58c41953bb9faa3ce1f4564c825a02f0e1339cd659ab1480804dd2e90e3086aaa292db39c6e2aaf1b001b47a21cc721c0c502c46ef0479bb7d8cbdf8e9c136397febc2d83c0fdbb3ed4fa6868068477206a26d2b7e0d20507aecb2756b888fcf5b446217de14ee6a20cf7e7b732fab22ca3abbe81b2be18463acaa3132773acd7476460536111cdcac98b1cc9b2c36aeb3fb318340f7397b4b4ad6aa87eac94ab7d98cc12ea5606162877465fa2cad276cbb5d36c40a0b014c53d2d3a96825e237342dfefaa6b9456b5ff1dca859c5976f77c3d3cbc9df355237ee9b4b4c90a9dd941294431db76dbb539dc48669e7aad21808332c8a4fe98b8f043fb756b526890452fa3c3527fcd584cd33e38ff9ff783538d39a184b7b3eb649e1c04c289fb65998f6cf5d5bbb0609fc3403d85c6df269017032cd24ac540e1b294bdd3c3a0c7117cab02b1a0063a174ff26fcda687433a667322320c0dec1ea3963f3b14375882b3478aed43c2c74debfe3a734f8b1a5cf92007f8fb627cc3aad5c6ae4c31846b72e7573041270ff40e762c0f8dbceb7512d44dc260a97d5ca7d60699981ed8476d8651c35c8ed498fc2961d1e38af46f3653630773209a63838a9222b813c23db0cf4196d6654126ba2b1840a7180e653b3d6e10c4c7ac3cee93b0399d918a52e59f0215b09a119e634e6e8a9886c877f157bf7b7dd827adedbaf03c718ae037c0b262588171839e952721de72180f8eed00b01f53e098b82165199c53129576036fc753a3d33aec92060dd19aa078a496a2b214b1bfbb747a1ec64071b0a078d74d0212e6203c9698c7449326a42bcbbe8d9501db916c64307d5f1083bcc36c0ffa18c0e4410b0b17d443481c3673d17bbd7a366a5fd1c3c5b3391a02eda7596b4f869a91a32b5a02a05611371231be035edc716f534724b5225e1a72a2b2cd357f4c326f1dee963fab680721d40dd70b750a019e70885515f43946a0dd3dd042969139f61eca0e9ee3107d3d28ac606ad53f236303e1fe986c38825318b7c4597b14e1a83b81295fef49fd0f2c1e14a0b146540d853db9706cd224b376343317bf7330b0c2721a409b856304fffe60c24c441d5e2797d4696c0fe046d305aee93cc6a2d89a81eb19643636a8b424b310034612105df16516ce9607cc0a2bac5835642c6ff9572191bc45e44d9b40da36b607f570ae8c39d490342786f31ce6764f3f7a764665b6cb93e54922c6d89db566f494e0ee069811ac82e8132f2f388d68490cb1c2172d2979fce3659d7076b4f457232eb839172963f8c342e2cd18969f086f451d33bb774f3d00e6fa2be02292f2e5cad3adf5dec28932bd784801e69364962bf39e25455303e1f289052d2f0cd4964e0ffcde29e7c074e5d57e43739dfa42aad636c352d363e3a23bdd134baabc7cd1621ca638ded7db7051f0456641ca872ecdb4d3c2603ddbbce16637010e782c4bd5230992e2ee7dd904f8a83ebaa7b4c3cee15b10794ace894118304bcda9e9b1376331d2248b802557aabcf913e95f783715bb5e90a4436e4bde7d651397a70a24257c39e0516bb1f548da36c1f1f92a416dc1114107cd863f3bfcb360286e774b21296259756ea6040cb61738eefe29a67895ac69797c640e03f0e9e731647c2da93373920341fdfbd50eb6b737bb0d9fda8ec8784920407d4f41486d8fc616430768d6431ccd789deff332b239ffd1900800cedd9661a55d6d96089007e9089a117f03d7858eb4c3fe2d07e91d8cab88d2ba5421846069fa6d4e5c9161a140cc3a288100bfbe61c3b0f0e820ab12d8fc54b054a0f4c777052495b45a7d1a883e67663dcf50c2230ca5319ab31cd76435dae41ce1ee25ecd3fa0c7e83b0168852b2cab674127cd7bc9ddf9dd4b57eb40128988c7c8994dc6a5fc939ff957f06c70a4056e63331f9aad254ebf2b8fccd580285bea486d91a0c2dbd5823ac8f6846ddabcde25a2252f8da1aeb32e6969276bd2a7f94cd7dd3143f3181489272b1589fd385ba844f90e35982b53141daeaed413054cdb935f3412e31d99c1147079cb487feee85e3906daed18106b8c407bbcb7716ef9d4d34e2ff04709c7457997ad6fadc55a8fa70bc907815805578a11a012c521a1325754cae2e3f7c9e1fffdbd4be31dc534961c318d1a894838e0c33806735dd11e408e500995b86b6ecd20d325347f792a3381d2a45587d9b6ae0aa27533732a6c421ca621aac42335848d9c0dd89f14eadf2f92ec532756cd5697ad752b6260c598ec9f0e9976a950b22daea8b74fcc87f28b5e9ed83c0339e566259ecf06e5ce209065de87feee5d1e9c466004b34583d6ae89b590ead6a96cd2951705ac764f329e28c996ad6db05f6c69ad2a39d3ee230f6501f1760aa41ffd936c9dbf20de3996917322d32b946062a3c27d8bf35ecda22403ab684cdc680dd166562d018d943369caefb9133a4bc4515cd5f9c08e7c22d153f0a7733eb4eb2cd8a74a4c85e40dadef6858c5927b6eeb2b01e9b7ab02f7048c8869991068b00fc19b9545ab42181dd5cb5488222a402e827f60a8d87b09ecc88350032f998e3c10a88d4733227334812ec97c5e5fa85faee1a1e28a58641531b139aa58bef49780dceaa408986cf3c40e226c60531945a20f91e5dc31ec86c9f9a0545e5fcb79a13b9afe9b133867ba7a38152abc6d9f8ee10090bb71e6adc6a6c2513b066f2565138bada60b0bd339f9be1aaddfc90dd272b4146d0f5830c6a53e295c849c15d001176e7774fcd7619d6ef1a30ba93cfe278ab4806bbf25ce4a4e94163f614e81dff7efcb015997f5138e22b80b2b00ad7579cd84db5d1c7fb16e9e8c5d9a5ba0ad0e0a7de79c18839d673632f3d2c7da2062eae844faccaf23590b2fbf1861405ac347eb9d723ecbde54cc96bc4d8ee2178f353310e5d69230c5db2841d2a06a3a4e03e054d99defc6004a6e405fa89b198a901ea1ae9f3112a29f3aec5698a42794e04d74d761e4aa5ad23de271969baf124450f4796da1eb1c01480436ab0f5d0b1b2e6717dd87eebf137420961f978896077e40b2d2ebb5664fd8ad89bb9333fdf46c33ef3bed21bcb5b4697451bdacf364f85462f5cb9f546657b4744edf757daaa4d3a9a2a6f281184c3576b1db0b540f3b36310020bc6ac0c6454a7cc8ec1182422b17bda202729c270194cd6044210d2b98731565812339edfe5a0dad79ba826d8c566c7d25dea9bff0badf1e4e5da2b884966e03fadc51c6d9bcfe877511157201dab48aed1ab038999e5cc3fe58ccd37d40050dee92e0bd5332413a7f0118724084ee5545fb51942df1ef399f734fb9592555b5f32290c53d7e5017efa2b61e29fdce90cc3e7c1b0e545425b1d3e1acb9089daa786cb0122db3ff27ea0367751a5462230f0f248147ebccba2e16d214e9a0baebe989bba020f95b623cb14acaf2be6f157dfdb1e32627133f0d26c7b65a189f39955ee31d9b507b43126b06b9e4524732c8621d2274438db7ecaf736ab7257ced950eb68bb868581649232793ec83379a16f40781e76f5cc57c48c3f5c2989bea803e1b63768436d39ad19bb77db46aae6e8473ed5dfec983f49e4b8e7ca6bf476ab2f0272c0c2dbef1bcb064d7400bfe1b9ecce13578a20b1d5b48133a74c5c59cae0115bc3b50574580bfa99d58bcad336ee2cca5b7994c784bb90cc8f1b9a0e21b39d5eba464de34d46ac0bbe436c2f419d60d8ab13786f9a841b52710d1b49bec290de317b66b6855abe156c07619a4b998cc582e3f54a7f457f1d2839bc3ebac937ad3ebc6a9e6e845379cf1d66d7c59000e3f6cf6823b005728a95bfb0acd044eb35d5adbe8933a3637887cf91ee74bb910fdcbe797b0c6b1b056500542bd39781bdf13ebfbfe949d7ba0b7f31102e63bfc6e22693f970000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 90&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028e393ec8e0a20aef7617b3cb99a5d6df2796d2438777eedf5c760f233b75e844fd465ce3845447d1afc38870a96fcb5cc757e5391b25a3999e628916e6951bd0dd4a938376a3c0e1ab0c563eeb3a8e891fe3c2a0dc4dc762044e937631de80b1d52e4975b06150c2b0ea92c15c8529f1cfaa00a6471006aeeb32395d8b1b89a8b9da4fbba69cc58efcbfb8c0a49befbcd9b371323a8e2c397eefd8f71fe917613f8469e53a953b7484606c9accccd4fd4aa0a4352f8dc48862616e85e1fb32a4408641cb1b36c82764b9518f2bb13fc3e2a1ef9af553ff182e391b74b1c8425fcc343d01a1c7114b8c6af3bac0f45bf891322a2dfba9025598a49040d67e6cead1a8caae126608cde1d3b5070b0c49963682b31581b51bf9fdbf652475942d14c8fd14663a3d04369bf934e64992e176790bb6e0728edb5f6f36d282143a084d8133b1fee42cf27e66161d8b8bb2bf5fa3ecc3242d514a37863296b1a37a5d4d165187337586aa0dad9faeb8153f0259cd4433d79ee95b2b8ff373c081cafe0bb5a67aaa51c4c914b4f6ba8bdaffac7c97386eba6065fac432c929d208c66638f9efd21c0efb4e8547181753affbdbcf649d6677693884fca0956d011764907d0bdd672a77b8c65f1094b0ebdb3be86750a61279006166eba609186460ab492a4c3bd1c1bd46f05047e88065d7188e4f277eed7295bec9b6eed33276dc4e0cdb43a1ea578ab9162886550120dec2f56bbf511358e51d827269cfcb172a934986ddbc8d52cacba526b32e448d98313d292445e0b663524af3b2c8641d752f409af7d11993f754c32c5884cac8c02b7f99de84ff7e70c8cfab1b5dacb3d88523bca7ec2073887bc5585728308cba5193cd31cd34b54aa9e6f5b1c841194896a8938048c865efd6fcf3acb12382659908000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038109a8f58b45f528577b9632006357b119e82d9a2362b04e8dd9e098054935f1af0b6899de9a367ccb5964d7a23eee6421a6b320d83efa67671488a48fc92427cb2fce93a774e169963e2cb44e866b1f6a72da131de81480d972df80d79d42413068acac0e5d92cbe0a6fc84010454b4c7a500153923c669dd962c72a44f472f37292c029ecb621e9dadfbabdc2c48125fd59321770fb6386a7dd43129e14cd234c17f46f04997c154d367b881468366bd7f8c5c06461c5140f5ae17a6a572a09e65f42c5c6657a8b42a8b27ec9ff637da768a07414c138728ce6f3f59e7117409a91d66c88717423a73b2f93004af749f56594353d6036836284b35595980e976ba9520a97fe07e61265231b110a2ba6506f030186b8454e2264af29e3508093e9fc6cf34a5032477b248808c6b2e29709ad575cfc16dd61893eeacf21660eae9102c99b9aa3210588cf0b3f010a91e591902d61b6a1a225376d2efd95fe5891184a3d5249db0ae8c82aa5b5ccd4e8585c1191ec37baecf2b2e98fe228234203a59ba1be8c53b399821ad992b14489e7509f4baba27ea61382451fb7b8beb43e122341aa4af073dde72ccd12a4005e17457dba1b2c19620ee936ea9dde0aafb9dcf553d5312425a87203263d68ae7a6ad916283f2901e3fa4190bc41643bb7aa98b5084bb0c5dbec3b9e7c90c150b21a7afdd89b0b2d944845c56f01061ad5189a9161df2784417918c0fd5e6acfb910e47377ec9bc0ae4c1958515e18990ad488bead5266ee8e3a46bf770148736b58c483cc454c62f4c728b026f7545d34f53f5c83121a8a99c796e01756ccc0c9a13172aa791ad795b020eea4c754a11a40dea9000e1958932639c280428e0835b007db8044010495e0a0111c1170fef4cea5476cb931e74ba516557236d8452c3e5f55efc77d440e08205e494fe2837b128934f34553127199f006c9a751de9f67a6cfe7578c0dbaa78f0310f8fe207f5ab1034cb1c443c6e65f25c1870b0dce898db8eb3027fca2c503043be9fa625883f804174403417a6877105a86bd6c7921a8f5399070260980a270bedaa0fe2e902e516a687202dd45358475729bac9895e60b5b1239a17922a5e2e4630d000614db8a6505f434c3a995395f2694bafca3314b6d8d3793225a36b519b1c1cd0a6cde5c82df9fa81700dda8ec14c642dac238c4e0066872a976fb9c3573e655e22aabab6614b1e5a956ef453a1ff501ee635b4a0171df0fee5972045167d6996795309000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bdc2601a39b6d7d91de539ef11c3b67ae3eb1607716f587bad5f60d311a9f4fe7f04350ca085eda6d41c4bb6c6e13e376bf8a314ddf791ae18be2ec0544afd3cc27bdf270c4550e9e78d497b92349ac07755bf9167b2958bde919123439d6f49c3408e8d88021e668a0a5fb6799330188e35ec5939b77097e3737c4f664d01d85faad0f583b3e95ede125587e2a79991750d5cf804325c72dc8ddf3471ee8fde02519d2d0ca7edd651eee30b3be335ccf7fb02059bc3a47ee3c056d4929ead4fcd82c8cf49625d5da460daa299718556bf0f77cc5cbadb99b64c8ead4474601fd5c79309d4e63aac392853072619efd7b958f0ebde5cbd40acd57df269a8810776d6dff2e637ea57adbfaa08df8d2581c38cb262dbb4d1f3c65a4fa068539d2056e08dcf03baff006edc688023a20728b227a99fed3b8f2bcbed2e3e6ecd8b8665a2e4d233b78d7c33f6e3bd9d0a24d13c8eacccb53a21dda9e7a34f9a0f031091e65f749c9ebccf3ddc4097a121d8c68eb7883405ee34f6a8b0208ea8d5a3fab53fe2cad1110bfa6e094f78d5314880bb67bfdfbc2df8aa250f1d7200ff9a3247c4976dbd1bbe99df02a3f246e5d466f85ed2f68e0b2de06b0f2448a7b98fbcbf5872bcae71bf0db4e70105b020ff130141e8de86dbe05b7d2a234ce2ea83a38e23a262e46ffbc837e8a71f657e443052e9a49dea4e344d497dd2de2afb4009d681f232bff4feeb173546cbcc4c80c9f85b1ce125be678e5ec62ef04433d55d4b8829b01ac165a440fcd6594f2c0cb456c8a47444ab05a0f0717b8185930d9738e885d24dab98e11ecff7d7a48a4527f94fc4c9d1b9d71f5e6bb39cf92b1a6d0509fffd42e77ac9ad6f50f8fc649b96b8ac08673f78ae8d0ba2b7243452b33aac44b06a2b9be1ad6a12583d3590a3f9af0e0dc35da88a257170d315f32f3a889601d6729433b7ade0f719386723eb2a008634749f5253cb7d9b2fc99a1ae1bbbe7f00a536cd38f8a7237d3992c3897df412f5b1d45e1ef5b5dc974d49cf8dbf785160bc527543458fd9378b3d4d3124214ae5676185794209ad0ee73b063cbd5b7830d00f817ca0d5cbb597c44d28e4885d935b7bf426c1339c500daf4f2033fa6a27a4196f233256650472f205d2c5e00e7087fb73027b0c6c9ac5c1d928ccd190b8a6bb33f512ca8e2369dae6111156de47a24469683f4721a25652ff87474dfd92a028b3ec5bcfc244ce442752a7da1da6c33fc22573bf0b13e371ca9fcc86c76fcf7a1654eef4442e47399835a06336e62952770c6e61c573cfd07b3ab631b8831fe3f5dd2c6df68ebf2f8e02ec9f6b90a371ed5e62c8463780ac453ab6f72d38c8f5212c8b650f63b98e3c0886b6a85ae8e7256c1efb30969532cdbf72184aecbde2a17b9811dd4222d080049c5d36c532cc0e910779d64af93d750ee96bda87562ebd3830fead07a3960cd6de7146603199563693392d3cce1332df35c2c8a2c251911d38e95815ce5a4ce5596e2d77711d87cdd54d22e8f0ab431bf8b24ce9c7bd6d077e436543c70b02f338841af0fb86b5ea4b6a47e27c1d83e1ab06801044f546adada437f3ce7d788a1c92a74ba540664658e70d4f2711979153ff1589792859c3bf122628479c7c35eee951dab8cdb0d4d150c2da338346988d34f8c5e589b231b5e00849611ba09711bd3a0516fd515e6c4ae1e8a3657c282c8120c97aa7a2e3baa22b6eabb8d8212a9a48e7759a9daaa51b538f662a05fb897067b7cf9d2ceb47a1897214ccfc225ce47cd60e86f7dea49e220f7ddd6894b30b66460decbbcb2e42b31f4adf0aacdde544b9124ea5ecb04b03c448b17e8094d489f516d23164d2317d3a1332e0500f1423136c8535d69065e880af34cf7e36db5ff2c18122e41880585b4d188411e86b370a024bd6e28143ea2eae52eb46be334a21a02e21c6755c0182b9a055a7d4c7b056e4930ce63edc79c9fb4e2fbffc58f776086f3487f02f8d1e7c8519c7f452e75ce5686a037b3642b95d7526acd4a81a47112cf96a8da7548016a22e9359198e871dbcc5852fbe14eecf3ccc5eb2fb5ec31d10474df7d63482a03e11f4aaa2eaedb714786e21d03af1cd644d06bb05ff7b3959601580bf50e5f7f82ff42e9cf2ffca0c67ffc52cedc53c7a5c9efb6c21092dda374d1cccbc78bbd9f5ee0fdf6da6ac60c95f7c2e96f17e3c379a52d5dbd1a92dd76d1f5dfa19ea0408e0e7f7867445445cfa60bcefc016e68872fbac9098fd6a8e84731c285570b1beacca6f4728958e7924f7a7b7730b9bdc9aaebd9e045f464071843c650d06c96d487cf8397286f81d93d0cc2008a62ee32421e5231998140909474f6d98541d899ea53714aefe652a3d792e4c72533332c3133707a49293e3b2e06ae18f2f81d601aaddaf2fd09ec59350e0979a5ae2b721771682a1bfb5748d000f9736031ca971288f34993df10fc06a16a6dbeed8cdaaa8127f3b71432e723558f0281459820a0f4a75a3b2716f976bdeb88be9c73f31623050d7c1a96c84988b01d847309e1b6d7b815883f83c9bdb7fcdaefa8ba69e25b824812b7d54530a3ecc96611897661158dae1b4aac112e9ac13d07fdc03dc7d5af23c08c5e4bbff737238fd3f1c06f94215bf2351dce9cae14b4dd4745ac0cd626054469c6a5286ff821ba192706d47ccebc443dd67fddb76797a8b78dd0daf850cb5d181c82298616e1d3a92f7fc82fd256857915773c7ad97cbb9710373299ae8516b8a1d647a13c7be848e0269ed6c8a91dc50d0cad21430a3bc9e718a13d1966a0182d9a24fff7ecbc7876c868af2baf2d8b782172c6719cf140e8cb877fe6d78779e1bb31c70c6c9a6a77529c51cf78a5e4fbd7ff6153b5195817f80603e5c5810c38cf43ca812eca52f73f045e33df4e3d04ec8c5f8b4a7399f6cbbf0d39dc951c476b9bcc002720ce89f09c3885673bba9c90d20dccca4a82ce5beb38bcd60afe2ba65fcfb01c8793b7ecc0f0b17a9da74f2e0fef4c90b5132fd6baf8c010fcb5e8e7faead7f2e0db29bfdd1811072623cee274ef2efb0f7d4191f332aaf20cf36ff89a2edf15f7b284cabbbef46901271d8c1b180f736125c8a44fe164ac7e687e9a58c3b1775238bf1a11f99bcb583d0e3c44bf4f76dcf9496a06f80ca52e24d55b54ab849d3040b4798bf5292b0574672e9f844016a52a4d4e4dad2053207bc97215bcc1bb93271c03c9ad2dfc7485ee2ed399236aa06cf9a12972e21afdc587a6334cd1d71a7539362d714ba26214664e3b4bc39cdb1db847583db8e002a2aab451b4e5bd6fe200730bfb2745d03c82b640f4ccf58701708f724effdf98cb04c78df36b7a866cfd596bf5ea18445eea0e34ed514d0dc2625039049a0cc82711dbbedce339c77f9fa1dc60eddd8d58c8f144b0f3d00227afd8710bdc66d29809728d7fbe85f08aa38aebe5605da29a09cc0526fee84691eaa54dc3744bf5a95275037fa2f600b1f91e502d5d81af48f8ec4c1834fe625fcdf2364067048727559047e07062b4d8a7d3851853bf28be9d2c511451e5fdd9459270328a2612dbff42e1dd34005a3da1226a023162f454923c0337e6c74b44bb27a3b1ac82dfd68b0a6daf93473d97a9e4591ec01a51cb6b47e2c7a85c1ffa73c35e5ce3003bc4534a2d9b16ebf9fed6464cb1e0cc665a451616a62b6a8481e4506a73883198c144a06331224d358196c815c811b103959edca35b26bcf86f41d9c7638547496787885ee62b14af431cab2ad4e0224d33476c58b8b0833bf13b50be2b1d682ca7dd194b793ad2c6e4ee25aaf95459302f0b4daed907a317bcc6a5f8d76ca9aa0d799f8ea39f330d6244bfb9f35e6223a0f665a65f55eab9bcbab446d7fcd424dce87f234864d2c27ee84600ed9193afefb6e7681bc94f514fe0748eb32d32262cab880d79cd4fe5cc963a4f688d448f2db2dcc5b0ca87ac26dd8506512c100273b8d4d902fc054d48d8bf9ee818ad9619f68a8904b613256db78c881cea3373f0cbbac336a78cd91ad9d60126e05cb8c16e9aa8482cf1b806b2f9c57bc8d63bf008ab2e49ede8e788bf96b9f1db2918dc5063f3f1d5b9b1c0327141acc0b4b248ffdcb8bcc127050d27c805e154a4825dee6be9c8d4e42b1f5efc1eecc6a45dbc119afb15ccad19789eaafa8b1715111ae32e2aced2278803b60e2fd63a43317498244a7cf7342342b60462510e19d83240dff5d58e762c093df326ea503fd347d2a92a5a4680d5e13b305671c729179fa21be83b0d83144e6300000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 91&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000029039c8179bde0ef14fe505c12577519ca2a4ecda5e4b243b06e526c8ba9280d0aef4565042157eb0777852accf08654731f249954a64be4d5280acbfad09bec64dfa1aaf1ad50f44483cf09b49d0da2f122c35b5282af18459de070f397cd7ead3e7d7f393da5badb3a0c5c80d4a652eab90f65d2d77bb646203adc09f287bcc834cd4d3d32f8c4ea7af39d0203e48f08cec5036b6392067fab01e1a46b021af96419024f38c738ba11cd82ef7ced432b79931a2a0c8a2b72caa82b6a89f3f3d00cae822c916e602b5e46aee06fa28de76e01bcc4abc9e145e8b29edaedc5e5452e6b86f59bbfbe1a93f6dbbaf15a94bcfa7dca1c69b731cb2395086d92fe114513061e7994fd131252bce24ff267b0be4650518a1e888aa7e93b93e571c65991d402d919c7620824498cbe4dbd994dfe7963a7dc3fd7e4f8d3a67e495c35d1dad27ad8378182dd20734cc292d9a0329be6bef50556d23bd631c4b3db5aa91e7613886d73358d2a3d33544cf262b6218482fac7bbe28ca529bc66258fa3c0b524c8e873925a11bce92fd208a382c3f5b79f7a27b708c522f1d29541434897b1228bf428f41dfe9915c6145753b4d06546cf1c63191ce26897f4f9112230e02f7aee93391e70a1ac8431dcd664dbe326d5e3c8555781e2badc662e39814bd8465a51ab425ad92b1133c7bf781bcf3ed1f49b34277e3ee9561f4d98d0ac5ed3d47764b8e68532c554edee77658f3ebc69c7adc76b31d5b9417ea2e5f1ea3bf98f333318f98793c44e1ab595af5f9247cdf5bdebf606db6aedfffa2156cc3bfd8416a6c3a39828291b4c0fd35d8516284d7a8b9b95d8f4b863b766254474d67461f4697a56bba7f9f823c77d5536dc2dcc0b6705624b9ebdec8b11d6c1023190beac83b128d4cc1cf71a26f1f4f7f5a3369ec0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003810972ce78a30f8e2772d4bc51bb09a3984580423a4768a291227109965932d458b4231ee5441d45517cdd8d5c4023d93e95a01d9e45702b070b8a0950f08844508c3a2f24a90e8576ac90d2d95df557849b99be8aacbeb6e9c56101c2b1663530ae97086b4de2967068011ce55725e1d28ba80ecaa5bf9b664df67a27355fabc0013e06885155657d49538aa9ee4c483ce6595bdd09b1fd10bea889b5952aa44048c2aba203b75b57ce20cd0123589084390cdf078d5d43450ee71125dfa84856f3488ed5b7a0ac28269e47335b18115adb0a2a62b5c16a0422ec427ee2302358e035c48380c113975e645841ae88c25b922f8a09d06c15b630e2dccc642c6e94d7f5978f45a01bf724067fbe507b86a2e732a2e09635d7598fb4105b628a0da51408db55aa11dc56de950b46235a55b581124aea1f2b2a15a1259867ae5023d1b86ca27cd213f389c22755e0b4410eaf9626e4b515f8ebb7288d1eb87a87687294fd424d6e4c97380d805b6044b3ce5e1b4516b32f0cc3e9c0e3d6159e0de81ec7c35f096400f407415076ddebc60e9a231844614bd1cf8aca0473f92f138ebaa3595a8e18378a4dd2a78bb616727654094e2861a9b5f00c0ba2616d65a3f5dc96a8fc5e40f698e27462025a43023d50cd0dab50dbf0425613db2ed7416d3923b780e51216192e85416e9029fc68f85566ee47a8fbf45a1a2e478ce5377c6c0885060a578ac7de3940b37897ac41afb0d657b56bc898316bc4819cc7b43daf2b93c6fca488bcc94d09363cb95a5a338d606b32ee548be8da084cb7f0baab300e384f196693a5ad290176d008560c1ef4d0289958315e45d805c29b6ab255a73fcf699735180445d4767c263fe38dd492363514613e160c71018ca5b84ad57159ec267b4fc179893d815e0cac8381e49636a285535e9e50a284999fe806b1e3e2c61b88bca6789d56b3211946b7d3405c015f321e8e23332e52bbe7d8616a840eb61ea4941af9ac8a11e9a18b1430aa3feab7aa1155e7fcc651b0dada235c5b378cc1a7e8e9d9b12ecaec95e3d49849ac12ba05e2054d01d0a4fc66b2666e748980d7e1089d8a9792d3f92b4e6ec262e5c9129a2e20f21c42a745f616950b1b80fa2b89a6a98e031cd8e0d09b0901718f041b8957b982b9b235dae46b30390434a32a45f2f7e6209dcc7986eb4211102e08168c3898961daf2833b84653fe5cbeccea3dd7b10ec2b3c60ec2485f90d6998ae07f66c6707995eb7585d239a226d467000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bfd9163116c86e64d90d35cb216fed71bdbe6a0797a48cb915f5a40fc8d31ad340767058b28cff0c240720327e12e653c1f98b5755d8000bc01324db2820781b94c4434fda76223845e0613e2526a95f28fb4a768b1487aa34dadb28cbe8df4fdb510dffe672ff004f37c7ac32072a24c0f12a050bb396ad56346f4e0ba75c0efac162288a7ee8a63255dba5cf451a0932fd56b05e40edd491293e045a6081f6586bdca10b41a6970d8f9a7b3b6b58aa772eefa9ed22c9a24a384d6947770862be4fe45c5e0e56fa4d116b79699ace41e5d9f2e4c245059cd798dd986a3763f527e0c9d5a88a09c4d76d447348509fa7d9bfbf3dea59ea57711a3b1a9352123d4a74df273fa24a89bcab42a6d455b5fe3c503f1ff638280f87c740b9e4c5ff20133cbdfb8d08caeb7de9f26811d437e6ec8c3143c0419c2f5135d25c7f40c7908c03f295fd26f1a03fbc7285196be40adc6fbdddc912b3bc94b0bce08dbc2185ee3cb766325068db55c31ffebe4b1f6848ad4fc201a5fd056916a397abe6a66ff9bb03b037b50ac509e46ca441ed45812e3334fd7036d190a7991e55cb817ec2a63cd800f293277e7d15f086618b55ad395c614d168fcedfb274fdf4fcd50cb976f68a266c5365e02a1ed0221ba4e13e70304824f94251249ca23c089b4d54e02ea03fb7c9841dd30404428aab2519d68cf564d75d18530c7d062496c120a8f5305aab23ae52255ec919eb0cd875422b144bf47f7472349558e746b0eb5493f1fc40abdadd2ed84a8b31221a485052369fd0b552972c9faeb1a78e826ba4dfb9e91e301db589e9d7c256e7051692c48534c6a5e2bf0f45b78aca66d5f53e549827e15d64e2f294f93d43b9f36bedce6cebc05e56ced3f846635ae3c384c3fd55b969ca31e8c625103c2b24e7ee45e92984ca23a331c5b14281b20116069c619d82d6080c6fe35c3a3fb2e73b695cad9c5d3300814fd65738dcc3eafcefcd24361aad13a25b3570d2d509fa449612bdb5b49e0605d7eb78449d1db40660af0f3d8bcd4869b6f175cd28ad72fe2668c3dfc1d4963d0eab309dd50b74b9d2947f86fbe9864ae5d0dc69b55b182ac1d914b11f631193f5f1f897ce52cee97d7ae95631fc2f2a1ae9b672165432eb2e5633b55185afa5e883268d8503aec10774d25d39c800b74405414fb06c55b8c48835577884d6b4f2f128246563066f8f34d76213e0720e899fc1f11a3b0a591885d82c688e40d6b44b54d6c7c6973156e2dd50c40a28d2ebba60f5117d64646caef72974f4b8362e4820ec04f2f373da8d883af27518567688146f16bf4e10969e70be8ace5d2ff6a135db1dd738907ea355fb6d243904f6427d11592672060da14443b55a9089167fc9d5efb2c64b0069795c341f90daff684e566611ea87bc40a4c45f22c23ab6888a754b89e4c95bb54629ce74ec999889c82714b5aec703de7bc080b0d2e622ed53b645688ce164ecdff4ed66c86049b2f9077f2a94cd685294f8ea9cbc1de29a48d39f6b308288dfdb47731e39644b576a298646752f5c53d7943a5d0f7dbbc9604902b61b8edefeb5ab7e5bfdbc1e6723e6047894547e440e918038cc13b47424ccfe1a207e08a40524b553c750683f5f6c960f05836fb9b28c59e1b471fd5331f1811ddf3eaff73798b7ffd6c9714978988c440ca906b4782a410372d70ee65a0a803061708003688f576e2d3a22580b706149a24b93a162be9f1b546680a1db2a8e54a576c28b4772c50a55161b2994514369c2192b2c90017cc8282f41d28099f38b2f1f0d2c0e46b444417a2078755591f00f01df0ce72b1d1bd255a14d2bf67ab3e630f95a5da9bd9e10f08efbf6fe722cf000c32460fa3271f18b39eaa4487c1ddf828b6bedf4523837bb3425ba1c1606e8d5d1e6182aa6a74f068f3e90b42641347ca755779216afbc99603391fcef4e8e5aa202bdca24b83ff42f4f01232d3f2831cda2db76fb93a4cf6e9efb71b5438a4b74c3190a8901d73566c50727559ba9bf6317d116e8f5536bacf064d3f86282e0f88dd40b63e75519c6a8e5664af8e1029fae87930f523e4dc7c2dd6dc3296a42a59f178d438866d929a70951bed05533eb1d818b7c7c595971c26b1d436d26897d6a6eb036a13511ac4a3bd724f2ca57fef07d2c0730800d35683d745125f4237add64b538b7dab0d0f258daf7de1a74f74a2fd010cdee810f514fcf6045f0cc84e2054b5f4ec2772718ffb4cca9c9be77f8f007333860180d60ee4dd8ce976e63ff49aa11dd42fe6946515e59da3e602b1861bd3f63c89362bcfe8438bc71959a617d8d63331a3d903bc5734b777fb14f7a2b063d79ea8637ac52c758ef88df217b95fa8fdf1009ab28d8a4f318f78772568cc7aa9e3b3e001c0111b1751b698ef1b66383d6b3ca942fe4f66fc97613cfbbc03eec9d0b7e08f80939d9a2ea1f72bda7b0d655ac3a94b4c699d3eb1bbd6076e63ef5c1fe9ce258b55d21164ca7ee03bb53d8ba4306f695e648093542d769da95a35ff3a2c071dd8abd5a82e217d82317065d50a87b689ae3a2ec7887957bb243373cf986490961220ea61ebe12ac0287b185070e124fc518c300620b4b6d4f29402b18c2462a7985c00e2a87691053b1fdecb7aa264f33e27c6b201ca6065ef79e5266513aea92e8d3e646453c089b5eba66d14bc45844d0240d2e7737c16668fd53e38a93d6003146019777c03644c300d06927ef6994ac794914efc5be0ca81680ca8c9752908fbd2d56d7fd1fc1c76eed755408f1d7802f0d3d0f347d82b162ee6f0a2a890e083c20b822fa6c4ad627f4ab5d1526d83d897c244d6ed4a427b23b4a0c19f4e8889257c1373764ab7063b5db8ed9c2443cb012381a2b3365eb568649d7ccd52271f25fd22fdc397e4c9c536ebb452cd2cd10dc5010bf433f88cb58d2b9edf2bcbfa83b782ffd4388f1bce3f8f9af5ae6be590bdcecb1bfea846d2f0199eccdb0c7e4d419f69b6a428eaeb462b67aa40340417bdfebb6039aab8242e39f6c11ec136d73fb315cf71414a2a1203af08fdee34ed0072c27462395815f7779012a41ec526be53da954e1f7a7ebbb68feb15cbaea8add6cd0f2fe3d3615991ab54f4c7884e8a80a9535f13be2ed944b3bb315de8af2a70439294cd53f041f41d3562be840c78efcb08661b1731feec46a9091ecede3a9fbc2dae42c72ebdd84308e95644373595db62157dba7dbf124bb45de6c2837b0066673bfd215ff915a8d41637eeb029c345e444251ecbbcdf79e246a80aa4591976a00da06c759c6160ed1986f8e15a562417da55109174628e7b11d49586882851205755b4f99a875ab3599fdcc094e4a2164e1764d24de805fd7b20efef2a8e23fea4e206dfa1fd9c31d90c1fecf745d3eb886190827d952703aa6a99b5000d8ee9d51de94a82dd053b6aa89cd7e94e92d4aa93a9224d3f688b5c834a53f2993638166a3de78aba7cb930cc5845f9915e6523683715a187e940fa2a978b5ca4c3b80db62e96a600f1864bf0b1aac23b1330b13eadd3a2f07ce7181d0a9497c455d228278e5cc3e4c00a2ea3eb8e5b9ce2799256302b0f8f1f829d3a3ae8aa7cc4ea229c5af476c01b8d48a9f6987df57c3469b6ef6dfcb488a3d5b91fe17b5798fe154ab8399a2e75f0d15b2a6aa91302056266b22a38a604edc374e2d2155abca119c11dc6827a47e3cee7032f6e0f59708dface221e47041cffc59ce0334d9b7c5e91c2c320a70ec2f32906624128363c893909f47bd970df652d5e6c2324033f32b1653a039f8c051d9dc8f839c50f5696e9e08f7f1cdac4750b429af03176ff6e643eca1d8fc710c6cdb0d26074d85316f4c9084d5f453f6d36c1cea0e389f3462e1478e2503c1db99fc46f3f0627f173672c21f3cc3b483998192e81efa689819d0007762adbd141a058587e030a3568e412d25662c40acdafc3c6ee30c10cc23e3ddedb6c73085c90c89b1218d67a328f06c3637a786d4715cb9f9d8b0b22d920b68b0557cc80a56fce0b6e2d6627de576e308757a8f37821898e96785ae323e413d3572205b0a5710143a2621c258c76c7c3ff7100a2fcae99c84d1ab1cecf7fc5b1e4698bfa3ba2a0856a65f2d4f291a4a164c0381d70d1213f7e40fc4ba42c43ea8e70043e27c5ab0827559b7cf7f2587d0d2f93c6382cf54e92764d815280d68c554e5b6fbb351bd18635786299dde39fcaf3efa708a3f18701eda1579bfb0bee4fa1f1ed6e09d450d427e4b91f4552f87f31f06f109e74af4bf301481452aafa2146f6375da467ea008bafc3c8408aadd61b07c28c55249ec0c8bfdb00ea000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 92&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000029039d6cdbdc149ef08d3931d78c780142b6d0c153cfa7cdec7b035faea8dbfdd876e45498fd64648dd85387234a179cfb3caa4fadfd641ef4f327849f42ffb271e812a31bf2f74a0d1e031c4bfb7ed572a7286bc55a2b16a3223ad642810956191ae4b795e7c973969e2afbe692be65554fe5d36b778c7415b9d1a69f385a22a92aad7a8fd4a54db30632af075c1c031e68fede0b86a6b10cdfc7a5c5c25069465acbe6cfe297782328c89639fa4b88a0d74d1a06f837e94604df6fd7eb45c22ea93ab96c2b0cc4ba13369d2379ab1e62fa6d77f1553907227da39e3acf630eb9c714edd269cb9bd9b826d10f7ea132237740966f230b44fdcc6ad7e8629cf2bef6659a5158c4faea3ca74b076783aab234877a9e165b29d0256d72833e956cb8fda33b136e941a662905b2ced926f5bf8a13e74e66528809a0ed677bd42cebad3f9d3668eb678030090c212ecfb4bcc7f6d7daa347b7ed3348110894b989f1e32cb83ecca74ea25975c4b900d310c4cb45b36b0de2d125525d1adc4938d0e5771b4eecdc42d3f96fc686495ad6e21ad1c8b87e4c5629013df4d96231c97d895e7869e7ebd6b926c09ac4ba865d2a1113d33463f37feae3d90379108fdb14d63a727bc2afe7547facdb1fdaf891f809909fc5e69e8eba7e7e59e41d6c29d7ab8f9778be71ea0afdb1cfc9afb08ade29ac44ab1042056999e0bd6dcc48d5b566eb5068e357a2c79e78d0c530ea0e926fc8444a0107d3b26d3fd38ef751d0059b9e8d34e6beb5fa49a5b0362984a8c1d5da35622daf4c565543faa3e9a8f1a9bf597826c93fbfcb8735aae90d607e9a7acc5b0eaea372e80c9f0f0efc4474e819109ec422f41c3aab07b4e124d6074192f9b4753ba93a61872d71ab358308e2f32811583d1676ce7daa78aca231294b1d740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381096df5b9021e118f52be5677b7ce9f06ccd112102faa88f4332a1029b32a892e6856200f9f05e45265ef3d76ba43e5c944d97e4637f3e8628517cabfc65ec94c34b56e443091011bc156d8a4df85572ac137941978b7e2755598e6450be95e5077a1ce8fb21ba087cda3494826c353d3007481be24ee43647e9cb8a9728a87b3a9bf08d3d991ab0cabf3838e2e7a989069012a39198059b8c55fa140edeb9a8e0b64b55e4eebc16d262f7e22243f5727abe22fa2a863706348ceebffdd0d9b426d519796a27ecadff2eaa3f7bb95c8b4255ee73484b54b02deba4886dba0eb45277438a085ed501a723c954169afd656e692b38f2f35bff9056066d16e4f21aa3589151001ec8239b817969e26ef8999c10045a0e886f9201b0ba422b6664c12966d229a298df28fdd27c0211e8a2c419da3d1910a51bed9d4dec5d796e1238526626d1add9c3ad35a0032e4ab490bd4db3976f58a6d568c5a1cb4b038e22b95de0d720dafaa831472249b0a043b8ecab63119aa3b01660973a65842b8b436e118a6927e7380a520543e41c951d203fda81e3109d04248b381d9fb78edc37689b426f5ad788c3eeb69b5107b58a545fbfb91d508640e4a7a974775d09e464b81cf20a17f5a3b82ed55a23590e8459049749580ff6f973028e3f2e84fd56b24e8046a422b738e88698ecb212ba805d83b69e5145070b17700a8953d4319580716484e47e1848814721d68205dedc3891c3307890425b0328543f39f568f1afb05fb6cb7167d553b6ed027b3d66ec6329d54023147315a05b669a44d76a91fd493fa68b53f561631b488e55398311c368d0b5d5e118c11e65427641487524f91e5d6776c929f54769bc773aaa09591934c80f1267a7d0e0c75429083a75befa7c8de83dc0d026e820620696107543efa1363239d89a5b794245a266f889e51c868f7608d1a29594c8030e69d32ce1fec2e0eb60450554eb7582b90c8c982b6ce73806366b7547627c5b9dbae231922f57d9a1044181b59dc29ea2b6c75e66cc59451d8ccd7774d640d927591afc8497afc0c22c307f22f1ecf75445003ad52f198425f9ca7ce007439926e892246c54f9b0275aca9a9fa283d57f8c5513306050df272c76599259359a798a215d622263119d92d7b461ea2185d216335128d50ac98fc6b11b4a219ea007e9d53849568157bb66e66a145fe0c862c2708d27a46260b102fe9cb7be8f826d4868f6ac050951d905495551d9768873061fae796d36586000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1e02c7c4451da90503c43fded1ccb3dee468a6a8d9e56670cd8f6a58e7941f1bc5efa6e2afdc0141a2f7e8f781d79e70b4813263a9dbc8d8a67f89371cfbd90977ec96461b28bee4c644f2c91e96257b1909b84ecb25cf438a3fd6b835e20d5cda56a1fb7995fcaa0ee1b5327fb1288e3c57cbef0554ca5ad6fcd1f1865c6aec6cbdb24495700ab5aaf078d8516ca4fa3a231a97c77bd150b127cdbfb42c03702c9027b2a5f6594b022ef55b63bf3eec27eb0e9529eccdc82bc6ad1f011f167d602ef1f175da5db4028bf08a053af2c728ade93b37edc2a75b7b6c6cf38cd1c07f359c73b131b13df76139dee6795f1d85b47f29ae97d0e40cf5dbb67360044f78940a1e80d9d99fd5ab0185210d8769911bc471650df0fcb9c3af038f7882f677790e146e612fcdd6fb89f90b7e5e46cd648f4bf8f736d69f8a91e4806346b4366fd48d1481c0b47add82003310b0a99b779d63ede1771f50221651b2d8af40f48b92ee1327c85a1d2ef2d86378076beb58556fcaec6029649a0ea5fde517a85d87704210e071fcb6f63317aeac3eb3e9746018e1028c50c790a45b1beda6eea2d646dce401ad5d7850a5f69cd85301920de77ab0d01b1361efa3e70ac05881bc02190720acc75a691d6064f9d24c79dc72476309e58cddf5fb2a253d857a79c8e898ab6adc300eaaf208820cb02f5f2cd317f4052d40de28e52c55a0349dd855d64e8da8296d4f572281e221a3d27ef76fee67fbe5484e6460c99950763b801fce828e93d2a633a1ca5d7ec582d7c463da5a9aa8056bb2173306f3820bd0a3273742789b61af89ccc42b81cc68745800d2a59231d5d28e832f443a871de5b6b10b58a8aa7cc9816014d7f3545ddf1f481b7f0c9dd41b4d96e5db767b74776c2253fa230df65f3e0b944b95ecd4138e2847418b084d9f9e0798cb5247238ec12b88c10a5c0c645e1d09d09059c72e33c28a472fdd8b88eaa93c63be7d980a12195c2ec3105df2bb81cc9c3009f7771b6b813cd12303e3a9961d6731af55ecfe5127bac68d06f835dd5f2d584fc0e648c3a4256e2a3d4b81966010964657f33d1fe0400724c488d5aacf9f2c0b802cd812c8452e5b8e2b17ff4a1289d33fc405f5db4ecab4a73fca3634756dfbf9012c413b6f64788fd0f68f8ab7620477acd3c14009377f3dd54b9eaf2784433d63341323f54d113fd63d7456afef885f13c13172a37a5dc82336b9515f8f7f4903ef6dbe9cb34930743b6ed11265cf94aaf406dea9802d17bcb369ad0d9964792f74d338dafe47ee88b3b74eba8e70774edc1f16fa876fd62b0bff880ce252ee4435b1debf36f0a06a4fb406f01d618c135e6103e2a39f4c9cf41ec93702ba76ba753ab49b5836c20f67d05943edddf47ab8c5b81f4bc22d773305076f7e5b697a7b25b016190072f756f19f397884e0521595326ca591672684a3be17c9f5cc8e8f4848f7136762178fbdcc7bc6a6c6a31345fee687b0505f72bf1ab7eb87bfe5f896cfd42dd67a239c70648b39bc0c84da33ca17838fb4213c38b68f22914fec3dc50194e883720719e9b5f8d037debb726dbd899abd97853c54b0bc347a322bfaf961c6cd6209c98aa81b8e2595fc151b1375bf4fca2dff49df40a3d1c694edff6e9687e73ef62dd42ad7a05195a7f206f097196aa0e4d68f8132d4a00ceded940c4f6ae02e6d3763073462c7a4bb11778290e744471ec554a05917e52c5263ff02c07bee055234eee10b79175dc164ab2051b03598df1d4311e87acf4aec45c55b1a58b0f05ebdabe248a27c0187643cb8f9529d31fe0ac4a28d780196da00dacff5f2dd64fb04e7c159dbbcdd3343bcb7ae188de15d923d2ac0af232c5389dc9c949fce554f7a0425d4f9b28df2ee4b81740c2b5a5b93f0f7ab75ebd360cbc78b11c28608b5bafc970cf3d4455a20a198392d876edcf89e2639b50cd84ae21bd50fb077050ebffb210be711d8ea807ca66493650e909911fd3cad99ab94b2ab2edff192d9d75257818272e147a9c54e06c53210fc091bf4175f2f44423669716fd9a6c4f96a0c4be17839769a806453e55d7357fbfb3d7a458e70957d524c0e896398e135bfa68a0cc136fb93ee7d30ad463e32e152fc32cb8e7f0b05a30eb13c0df98bc187ec0a54856d2efcda10a82b89dc8cd21c67d9b6df3d7005ef3b2bc9dcd5d55b64db40b74fd322cdf9d9911a00b5a02e1ad5ca9bf65d90db709fc1e5fc84be97574b09c83b49963a51228a667bbd84bfd8e0d90ec161fe5ca73bcb8d95fd7afd982ab7ebab51bd2b24cd6d356eb850d2c65593313d8ebb97e7dfa450ae982918582f86a356f538eb05afd460566d79f040d36c93d3c645b636560007d51b121de3fafb3ed70b475aff9617da4b52937c628678b109c3b76bc15bd02b766a394893d8ec966dfd8033d12a8d98ac5be201134325e32cb6786f4faecd7dcd05aef5f3739122b817824a672e71deb312cb7dd6a77116b30715076384297b1962efdfee6d6d2b2ed2ea4dd802f4784872d825db828557d4d927b7232682ad91cec3e508854f529853a8797b7bf7bff8e3c180980ddf4081e96a12a495acde0c73282ac78617c68a55a94573e5a37b859858d1e19adc82821b316b9d346ecfc6dbffb3779f692a62d20d1bc4e730fde2aee826e76638ade3dfaa11057b0bc8a80e8905b15e41d9a4105109f18e7e1362149ae9c568d1d642d65b94253be2b13e7230f8bcf34dc87241d1de72a65bba111c111cbf5bd618cd02e0a06e37f60b3736631073a6be004c1ad5f0091a82c87b276f7c5aaf6938c886a6039df23482e2064f6af05636b4c6ba6b24a29aaf2174af4bd959177203ae9b160f81ca6764948afcdacf6bec0b987c6dbe178dcf47c137c64809483019c5f2072d0301c19c500c60b5ca913c24a8f28f50e1578d806ff9f9b810ca14bf5f2268fa18dec67d973eb1d975aaf871abc980d06222493d900cebd8811fa20d5db8f8036430f8bd7f9554f7cb47f9ebf389f66c3ccf9f42db57affee074ffee4eb3e11612fd8a8fe02cc4e9d2f8bb36c505cece9dc87512aeb5d8ebe33328c5217ccaf2e1af1e38bfa84c0035decd8d8c250fb4d964e8f0ae448aab740d9ee9d794390686fe9a95183f0d5166d479c51014f1f29d8fec616e1a4e7a9c86e2af790bc7bd7bb6f746a2266332e04affbe6b9512e6620681c3317dc846e4fd7974e8ae87e370ecf9dfed574e339cd7e8a663ecd1a7bf5842391913d98686f7f2145bbc420f2f58b89131d5f3be41c85752e13504bcc549a8f690cd2b0e1e29e4dfa3cc76bd398bbf28f33a00c3915dd719f7cb985e9a0a7cc8190bffc8bf47310c71418d7a6c629c491eb8e455148bd4438ba6b7014608b0ce6a1bc5b035bc174c9bffd966d8305fe9e5619bca3fe4b39e6732dc652531819ac828f86ea11360678e786eaa741382d713ae26a608d582a3e4583d45744acedd32670b5ad4a1310301b28a174dc9858a55f0c1b7486cd66cb0635083b0c63016e40dfc533ab80c9cfaf1378d00769dcbad56b09da3a4e6cdbfd8f3fcb951680020dca58647665462e42f42dc14e7b20f262d3ceb0b1a2ba807b98d66232ad7d3839c298564bc36a134cc2447b1b9fe69271960459c0a6f897c1878140690da7d41fd8aaa05a679fdc3037eb2885ad3c82374f4bb991745351292dfd8e54f565e0093776b7ea65ddcd500beb4d15af6029f2630a0062f2d4fb331b47b6a5e139d385016e1fa490eaa209636b1383b7d7dc1148f07ed2cc2c03fa7fee09305f34c57b3ce899c18462b4f1ef88c1ac5259440aab48c5849652aad9d3cf3d31f36c7f64f918868182d36345ba5bb7a4ee088d8b081eb78fe977f5a5295177aa427215bb26d1de33ad4b2d610a47f8c672eeda703a04d0fae4c5961f13ad6fca81863d8a394135565d8b27904a511fd0621a532f84a47ccf4fcc2114d4c369b7a76822959f8caa25a6495081ca9ec3ac3348a981618592c090b6439cda2fbc932c8697b3709323e3388af8efa1b9cdbd65a65c8f0c302330ddbd10e0235f8030562452ede447ee5a5a9a636af6f615b1210aa7cbe69572b3467b643bc5f5ec3f9ad15b3ad918993355e209acbd0f1393076da3b0950803295b6571e476acaa04d48a4627367cb7faa83796c4178ca9071dccb8d3ea70381b61f0c56d515e0a765e266dacb13056317ad8737a1ad541aaccea1641946e331229f19bb54c20bd51e63d63bffa13110a552fd0a95ab984ef53bd639efa0568c6875b2798e3a0578c940c0c4197d3587bcb1cc45a99f5d37b1612dc1a4178a3e288fbd79ddacd049159d6a5416f9ef3f38c74449bfb2e6a894566c5c17b4555e154f29a932414636900000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 93&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028b39c001faaf11986fec8e02863bd822eb154bd4cafb7d6bf8650e55ea739e3e84c3ceab48ecd409327b8ccdba787c32089410e5990fb646e5d9af651e0f3ccacb064380ebe1be77ce270f5336e7e89fb913d53a604b01df4e3546196ed1c238a535a118b4677d556f767ca446394296b211a8d0a9237a567e330245c50b77946ef752626de96c7c7dc6752283fabb8846f700a57b90394c8ddd9a2adffeaa17e79163ee7f1c8099bd3f35610f9bd57fd498a31bdb66bc0f1b67739af2248c22dd0fb2d67d7148e91c6aab2fac5b3da6cc4d3c650a6c87ca7afd4e5a2da238d24a7b3a707f3455062358606297f5f9e9aac50f8675d75f51c515c23a5aafae39c8e520680257eabd6be244166cdd5d99a77fddcb3579442a12da2531dcc7571712649393e86c6b54c3d5adf4a8dfbea7a536c3f851633915e4922303fb9dd7bb6f061ea72f7dee8e7b4e95952b95418b74c5075dac4354b7a6cb85974226e6e60698c0ef7d883a8fbebb626c5a764b5528c848684891a4857f62294358e6114b9c6ad7dfcebb5f365beff09db0fabcf164d976f0c44f53dbe7f10c6c2a212233106221a8e649a0b4a62300fc988c02a48cbd1e646acd7bc0fdb091c954959accbf490109919a5579ab5091b612f3c125045b9681954ededa32d8e16748c92a4ef9101ef39dd6c1635a2c460d033fad52da60d955608cd0d8a98673e924d9c5295c647aeba32ac570eed6b51bac3a5a4ddeee03b53e4798e412e4842ad39df5da433d8d732fee01a57de9c90da6372a4a7a59ace518553e37694db53ec56b5b5dfb1f9c23f3e6757037b718721d7b79ff14688f0216afe9aaf22093f67039baf211667ab6d97cc69abb81322af4f9a34df047994d579a7943e74320541b87d3b16f6535d683d9e3de6454f4b900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003810965fd19040ce0158ecca79117d1bd47441fd23991007f2de0fa108d94524e9471ff1bcb9d8a4740c55101a1ae2eba4f09e39fc6da6521d75e24a40b78180aed214a816b65466b854934abfa4de103e045f49c14b9a234ed569647dbba742a18350d2d8dd6fb387a077116e528b96e0b8061a6647bdb8106bde40519aa51f664fe1a92249c043fcad4aaebd1dcb9f553c9e153fb3b38c4436b118c1858e9c120ae32153048619e01a9b6ba94c28ac67244c527b971ee384da8f9736fcc911bb842a96c92ff754c0e76f10a6b9520d9a89509a9708ca39ac39d9eafd4f53a6de053390c56fbda9ec94458f940b368ae0e5854203a15e12d482a065e97f82beacf3adce7177ea97d85f8ef26a23c8161066eb76d45464b101862471977409422a9718ca8e47c546a48eaba34da9afc2aaa1487b88b0b8269fac90454c1b6319d07b445557699cc98854c6488a8930be75c885e02eac1334ae2a4b1d5b4a7260e506213793f6942885af246c24341811141e063a30566782f394d26fc2258e03019545b6359bc965d26e7aeb1f4c0ff63318291be1953602d4c6e3998dac1121e26fc49cf57870bc562e16b666f6755ca18cad51454a252771a2b929956f288ed16caba1d1a42b59ef18bd224f72f135e0430e39bd3079caadce8c59ec9fc9b29b6c09ec1e98bfca72b334506890ccf101d25d99b0e24f87a534f3116c7e9f3a6f54c293c46fde4376679b35ac8a17001d456a862278095d01ab134581821b64252a64d2d32a165b17a5b8c3c8d84160b1ead6368ab31756d50a0343a7848512601ca2b55d3234eb58ae4889526da8c342ba93cda489292a3f1b7156d30c0ba624126342c2aa7c09e024b9b11eef2ab5b0c67d518b731d6d21a125b060e528e71fe755300911e0be8976a19a72a2494e047ed90b95169bef8540b308330644bfaebc877b8ba4ac9d2ff7e244100e6593425b42653a2cbcea5bcb872c79ba20021a7b9fe5ca49f04086911686d2615010ac80d66148efe629b63d6864ad5159f9e5123f191ead89dd76c559f45ef646f6dc18692da14a76abef3f84b620bb47a8a430d579a73d4c891b15bae5d027f5317411406f90d9000ddcb42f9d52a321bc55826a6ba1b936b6a2ea78876131b0b9ed266b71d9ba7f23359be2aa87629ec7873674dbd6ed80542247b06dc3be69a6cea6922a6539f88eb10c22aaa6e4dc62e00cc2aff2ef5483df4315d57a2393561261567041478ff727e18a651e1c4d3910920000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c3fe13692e3cc06ebe8ff9a292d890f0a34dfe9a4f968f196b475ac4df553a30e2fd5df008df4d7508302aaf6389b6a5a9135e9bc8a5accd2bd2df98ff662b763101d31e24e8f182fa50840be27f76ba5ed645bb4d3f7f2f6ce25179a47fd7b6441a9b3a28783ceedb425b2912734a75d7d03811172188253bd8f0f52eaee84a9fb025f95ea1b566c53297a6a090f7fd8b21639523e073adaa750d63da61631f933fedffb2819e0eb3074e9e11e10b102ac88e2c8d6cf408fd241ad301f9b8e18a88b74cb4b0dac76347635dfbb3eecfdf84229babcc003c6e4efb7394e25667dd7fa47d36e027559f53e98789e6e732e6aa23a71607677fb975c2852367c5ba5e3d10b3017ad26f9a38ce803929d08a43646ffbc3980b359d8bc2e9615636d4e5de8de6fb2465a983eb1696e98dd33faeb7af8c2d30506b22390d7f9fc21c7a016fdf22d21ed2ea4175fe9f5f44598ec26452700dc9a495675431e1236865f2f4aa5bc9c9a10eee9e29b1fc4fefcf8f24bf94342fc7e19aa6534c3b771d910aa419ea2bf70e2c1915891cc630a3397551e4f34bd2192b70eb210ea67cf152a35a3f5d0878e153579b42afafe5068b2be2b48127ffb54553b7a9b6f845e7d72c43938ae42bc03e33b836ab212909510aae7dbe8ee6d0eb8ad84d60832f3151273a1e09c514c3aa4cacd15564643f4255f36059022b91ba4137ecd97b34be3308d40ef06bcf4f45ec625b54c7347f52a21815508199c8b7a6212779cd171894da9fc3de2a6ef5d76bfe03b8199ed1dc92b2a403e4da009cbc0fb597c5952be32579eb8e781eb12d935848c051029c528cbb68cbc1de0102b42561e21f48e72e028c2cd8816a9027914571b49d2f94c9189e1a7f18d7d3d0a09b3a36edb8a084ace5fccc77e3e42eda0fbab8c81eaf170103ca757981839c9448362bcaaaa3f20c8dc653aef36953559f3597e1915f02a8d33d0e46201fc794ee055e6d9955b91fc7aba1f136c280367404725cb355fc2f129413581401f98236d2a6f8bed7fdd7ea99060dabe3f0e8ce20b0e98ea80994d1673e8ccc6a0ba4a9d544f3d31bd95c9d3847527a978c1f155efd84b6a7becfb749628ce82e80285fc7272ea05f953404e437ad557f38fd9bbf77a69b81e4441605b23f2aaedb00c7519d8e9cb4cae5f8c3fa74faabf6c12595ba045f647aba7168c65c8a6006733d1341435495c7088c3361b50c43787ec24c24f57323466b5c088e8097b44666453010da38ad65b426e72140af78a5448b2f93df3820f013fb9dcac49604c86f2b2e4ea565463917285f148e8bfa9e11943ad3b86b14ed59a190cae097db26daf8fd2a642676a37dd90c23b52c82ce028b80a805d9ba05457f7b6cbaecba4094822e16c14d6e2291b731d581b12fb16802653360aaa6a7989d61c80debfcce81a36d9ecc84039c4f086a5579d36ff5d0cbe61292e4fc3d14277af380a9c1dbf36c2d61f59cfc0d62524e042710bff5ba719e56ba367ffe849d660b9f7f3b638e113bf2e1a4db1b8f65a0fd680bb2a168a4fd5b4e0edf3208ad47f1ff4afbaa726e38763cb5c84c03da3d1e32cba873b9a0c750922cd3d0a10a4877eafef602f5c875fbf0ee2f4f0af7f308ef934f7e8e74fda62a860bb594fd061d1b2bb32ba613339042fd90e749acef450d204072acf58b18c365e4f4b815f1e837453c4255d53bb68d50f3677e7173fcc23d2b592149a9f3dd615868af91f705387547862d34553fd45b8df643f596dfdb7aba47bd5d91445826c86fd4d30365a2f9a3cc0913de19707d072f27a09eab906304008875b5be3526210d6b8bc8663975a1f78eab9cd7f7305cdd4c00d6277622e50606e1cadd639730101d088bc2bab295ad86ba8e26f5ebcb3e9c7c543e533a7b3c20f0f89001775f714825dc8547bab06f5b99c5305ef18372a184569323fe269d45b669b9a222c9defbb0b2c84f42a57ef343a5c12f5712eec33985df8f0c566d471a9403fc103a3eeed42829d8e3e5c517bde29447841ce96c8ac587df3e4b6227fab386140db0112ed0d2846355c4a45e94f3a0718ceec13fd3caaeefdf0b7f89f502aacf8c9d96d01b5549157b7df2be65bc30c889e69971700286c561df91c8cb923001e5f0e21d2c7a3dfe8d1af07fece1eda20c031b29a4389f265d2c7be64ec37b2884849ef30fc8a82d2f766ace68c72f0a4b72f3b50884749814387893db2370a3410f794c64cd24bf0d13e44ad500ba9816f9baed72f7593f758592c2e974d1207a664b869130baa1fa71dbc55875134e7cfa276e36568f79483886099a1070c14c6e4eb87523e04c0154a2250624261211723453cfad185298de06d08cc25fa18bc58b34ecdf5d9dbb02541bab4a2af110ae09130e12439f1cecc34f9ab5d7be36c827a6f2f6708b543d4ad2e424805e2a74895742b0a5da30cabe4ab45f40cbfccbeebdab9b8eb8f78781168b5bc79e04effe1757ab0547b9bd0d2625673ce528d2b4874d46df0e09c24fc413ef9ab4c3d2e803c1e316d77ff5de3368bb925b2b1f6ffc340525663931f5595c8aaaf9fb0dccdfa4793519a66d4fde38bd2044c60fd1de15d60ba878fda570e7aef6db69d2527a1f1481a9d05ff2f6f621238939acf5d2c37b2bc3a194a9e65e7441764a5ee37b1fef3b8c9c425be1b5ff0d05bcb6a3b91876ec04ed89a31749fd443c2b85f8f388e7070d77dee37e2b666628cc9a961236dd24af2769c1f613b4e77f8e82d1f410ed59f63f1df19bc53a448106de4f8efb8cc37e40144b0f658a4135e25a3cf36d8692def2677e4bea3a9770f19e44d55080625421d5badebef3b39be71c08650b5718a9b2fcefc4becb26c4b63c43f6557dd66517d103907f82f9c2b965b7c5e36059d2159183f5acb8b5ff5e6b92e94d53ab25ae955424e80edec4650be293e836da6148392c500ff4b7672932e90e068569b81ae335b2e5013ccc95f571948d58127eb1269a08d6e897d2d9b60f3e49847c05d0b3ac230a67eb6d38ffdbd4b8d82d7b9ec803429c701f080be86faa165c0111131712db4957fd84a8936ab55558c69d33d5890cadd08d7f0d4962cf9e2f69c7517e79db14b76e6e188f5ed95169a2a7e4c0ebc2175ec2dd44abcf239ceb3e22f955ed25da41768ca5fd9a9ae15faaafeb431958a679249ab8bf879185e8fbf9986b96a92972153b4cd0d1be001e5afae3ad1f0b1191f1483738e728d4ad240538e5ef7bc9ba4d5903929d74cb64241306fdbaaae17b1c3134aed2cc394d3ef9653cc62a29c4b0b9be04e95e072ec98f7a80a7b575ded4a1993aa884c1edffe056ec475d934b4eb0ebf418975728c6e9cb3919b2b67d2c71228a4df1fe2c8388e3a2bdd75549417fe795f1947f857b1c0c9ca021515fd4d79e691493b988080943c394bf29e4190082a94f224afde5853323ea51c06b41547eec0da5cc202a048d77c7b91e794c51e72b02ea7c14578c11d9df48e099465783e496029ebb6d42d9caa52902a4694355db01dd7f5d7c113ae06e3f712fa577e937cd4fb817659f93964e194fe7d509a81c258c69c3415a8f11d35b414339fd1cc1d4f50665d9111592d1c3a3d69fcf6a971c285a94f5ffbfe8d2fd2746dceb3b218d970d670d10135126e479d92000d41eabdeea4c04d1748a4908dd39c60a52aa5fe29c8aced50dc1295b5c2c4a98e3c62ee4f370f4d3e500fe27b66f65bae604fd558d66b7f09ce36c36c8b5b4fed193ef56d1d8df0fe6fe0031466a1c633203966fe83d6bff843657dc0af176aa8d5cb7312cb4e072bcff24d5f3828e29b2037e8d1fb63537c70c27011e9a97e3f04895f4e84ac69c55d450b46d5792a5d790557be64f765fa243afa98527b976783e7acdf76a7e1dcbda72431fc30d7b05197478d8d74077626ff7409f95b24a1f1bb6b803b9f1b9ad5b06883fae6c4b587c309a63f3b2fc9619032157b98c1da9608107e87f4fee0dae995ab86ac9869446cde92441f0b9f8240e6f7f7aa9189d92b7faa3280fa749ba8c7729f8974049c5cbcb8c6650cf1c16b8194c7ae1a82b40b8b04488fcc69e674362fe4821d4c1846cd9bc49234bcc464013f5f9a082fb83d63098c331d4b1c9129f52259ccaf4a9237f8ec5bccf06f230c08ddaf1d0c21c5930f55d3d5f60cbfc447e7fcbc75cd199733f8d17bd043b67b0c138cb0c9c8f2e477728f27dee573796f71b013689b537aead4991e67f2f5eb94bfad9509d7c235c9e55f68f26b9ce8aa90834d170f8b700a40ae9a817d5d17b1644d25bcf1172a5cf0c755a6ec04fafc39db06aaa05f5988e187b9e110eedea9c84b99ad29a4b31950f2c870a1f91daa6a5817faeae516fa42660fcf56000f7365d8c6cc11d4784c6fc02e4d0c727806e9d43b957bba124c980c31f81facc6d46f6c38d227eef8f000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 94&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028e39fe541a112f6b646c7b9d87f696377919a4819129ba47c7a9a7001764923e30568927555e13ca43113e8545141f2670ed07ef19a9dcba48436f1628f242edb03d99f94e95cb540d6f024597ffd6601f58c37846d8c4cca1fd8cda753895a6e83c40f6a20dbcfb81f6fab29895a50da2cd1c79e20d5d4faeb5b9aa933619c6feb7e89dccd2276f4c468976f91ac2c7891fd61cbde50556d4c73af6685af19fcc5fb178b4fc9ab5e4eae39f91983a7c4f268cb279622717d63f2f6d3bcb8affdda1783c1bf10c4417590411886e7183d50c238cf62d9f5220f12667fc8d3e1736ab248ae66ba6972c600c657353f52989ff09885d7572a3b1b8f0f39a2ad4610792441e997363878b7abe955473f9175291e883abded3f6f5d91f6509c110d7c15d39588e549f079a609787b22de08e2acc16206126bda6c1e4beb535c446ddafa74dfa2d0b2d05352d63004e67e62fc6666030550230c5f2a184752acc991e8c6245f49424322547a4a6255dc90268bc3e04be93189d42cdc477a123f522dfd85d9f7fbf4b72179aca570c39239d3991309869856b71ffcfbc69cc0655364151d45922536088af1b945fd99468cd1a461167dd24649f0641e632796a13b61e77dbdf96f036104419b88396aa541ce84eafe832589171a0b4099ce18ad1c14e2b38b45122a26706aac4589fa62fde88d8225ae7c9d68850445f4b3711f6c31cec72189b5d2669ac63399caa6a41e194e21c08ecaaa8e047195655f6b3bd770a54b3e30648d09828dd434f959edab0eb2f11cd83650426d9b77a9af32ee9cc7cfe672acfa2ebb5fcd1ac0428d743aab267b23d9c5da5544dfaf977e0eabdcfe66f5adc3c1c4880a7f9e18459e5f169eeb5b4d19b9cb26c94082a3dd9fb45f6d44df15840eb4671cb434d263fbe847d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003810983552540e488840bb2d239ba2bed9030c510c2a48ca381e4568d441790f4e625892ef02714020aea5528344de0608c52260c75de3156e33f1fc8cca0c1c774adce995a9beeaa7ca2ac853487c105e4c86b71486a9faad57406a1d2133e9132cc5cfdb17d35041514361971d326144b2f8acc5680d7c6259ce8ba67addae26e626922268f089481dc082491211be91bb701eb47af32682862d5084450a3209d43135e0ee51970cb38010ebbdbc3e4c262615fd76d98ae8a3ec6921b6f0fa39d42142296384ee14cf5ad0de83fccb79ab6430c1f61bd577c8ab50adc1a861c11ca013e8f418566e45e8d20c5f3c0f1887e4169af5171b78849d96ddee73cf9072425a8e25ad4b80305001c316d44eab64a87bbb18e6516db7a6752581b01e9bb8ecddd92a8288461cc0ae1ce17cb2672b7e4ad9914989e6502b56a5b0fc6aa7b444c6fbad5ab6a65d76493522e4130943628665be8c1066f78896958d06e9886c2abd34394756450762700aa946f563a8469294dad2d12082002b04754e1c830a4df3f62f423a883e82fd6f8b5a02ef56a4c7cf546aea5b5f97819b860665afebb47841ae669ba4bfa3b19f068fc70c831476806b81aaaba63f4903188e96b532771da01b2a32bdd3a70db1713c8d3b318dec9f79f0381ec5d383b1e589d8c1fe72480427490bd7827d7298a3e8e282050e2a3786ec26b993e72e09c8b7e0a265110a97154c38a0b98aad50c059f8bfd73637a06f86bc4ffdbf600ce5208094ae41d05229c96e3d560f95e98f464194e319fc96e59e3dd4b70e09f3bb59a007222e7959bc3764bb9017849dc4eb4bce34b46c8aba8eeb3934fc8d224e89df71c4384b7c281d5610985b63d1698b22791bc96ed00216d2b2b40ffcb2c16f0b919ea8082a0130a014b8b1702d1b248806432c4f80149629032c6c8668900e616e76560fa2ca955a60b19a404c1658cac2a652db9bf102430fa2824ed96dd147c3d9a9146652dd1e3b45117b3769189636e990d415d04fba60ffc224c12b9c4916b6faa0a62bde48e91e8609a31c3713fbaefdbdcd91fa9f65b45700bee9f14b2b3d1970c8dd42d40e44d7189d17a3be0c884676d4df7955f576662b68b768cdf2588c489e41cd3ab30c3eba990f8036ace875fccbf39aacb62b6900e6934b157ddeb25106d249b470b0e1386b1d1289caeab4a7125645529887a34fb0a11149fa0f0807d2e2c8148a3b10b07d633b4e5507a800f1fea0b211b0b89622638453dcbca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c601f7ab96e8c14d1a5094672d7034fa8f81703a2cc18983c972cc66736cd98b031ac8a479ced21a1f634938df85f3e83161646db81b9ac3ea22f80980b8e2eba4e9975714e5a98985817f426c41f3968349686b69af917564a2648401b8fa127fc3200dc16a9e663d1d345ea83131e21229dd39e70d7270de7577a7e9635602fd2c30efaf204a9234f0a73d21375658b0b0b04927e67f3f5534614edf5137badfed914a49aa301000092da93b3fa4a0ff592cc3a53f4a75b54fee775efa421eefcd6e0d32fb5cdc096886076da940b26c6e07f12f6e08fa7b3e2dc42055308e5607a2732717ae592a6909c6e084252a5b08685fe8c6c1da387b0aa9800b67cdb3ee2fb21b9be5e6b79ab545563068441c0c9c1e68cef6028a5cedf27d3ca47d95094c9e1e68b8449758be3ff8fde148abc420295dc76e3eba8e11433217fdc3136551a5a41c1c7e7d6ef43601946897fda54842d8f73faa7eb7ed0de544fef2a95c6fecb13c8c0f14b5b22493f54374184b73d5bd47383bbc5dd7bc1beac0cb8e66d2f413a9dceb7e1d0ee2d63b9eb28db232c33a95b792ae67d2591f5af59ddc45771a0e7195c4d25e7f4079359597678b0c0a87df3d66a686a9215dd566d4722c212ad05a23e1377e37e18a6ab3ab8bf5cd47bf1baf06eb05e4c150ca67d7e52bd297a08cfc97b575752e686b83575f425f3a450bb0f596a60e41f7183f463007fd019ee255bdef1d98b7a0a12ec33b3e2bc9bf0cc8f4860debcfbbd5e40b2adc2cd10ec35a341be7a49f8d204fdae86921b7de5ba700a61e2b041a8ea7040acee844892e5cf025ffec5322ff6d765bff1107c967a12eccb0489f64f8c13bd7057df76485446641aa7a560c7e73008c46572628e1a225a8d3f6d68ddc9759a952fc07cd43de4434bd3391089e900275e9ebc92563ac1403bb7dfdd182092130e3e6aeb7b666f4ba66c38bbe1f726f40a07df6c42079a6054399519e26d765ca065f4ddfd27a29cba292699cd826fa9d3e7ee31b0d76813879db5ec5c7f454095dc3bd27323dabd2dff949ac760d6137334507816330fa67d886021661adc69aebd882a07e01b4b6e5492399ecdea99222ee785c810b30409dfaf2a3ce5a05d699c2368249c9588d86feaa778b4860d6dd442088a21d2d9d0b49b15ec579776812af8ad582f1c44bb6432d7472300b5440a382ed87ab64b20373a0abdbce391d0bffc9c543ec686449fca9d04b7141836a416720bdff250a06d7651a1f98eabe4b340b2303591d0847aed6ffe423b6dd8c0c03459c381db506f531343f82c116323899df1e5d8db8997bec12eb70103f0bf2b3d53c4d4694052606ee32be4f5b35450358d7d85062dcf7f0bdb51364700baf92cd6ace4e2c10e6cd9a332716f5f4bf7598466a99238357798a499c9b8be77690635c57e7d87a904b3f2278c0b1b23e5860b0532f152e1626c86fd855f656b5d070bc81ce4634a87c8ea6d6a433c02dd2e6d6561b25968b149a6f3bba40b749f188b84314b5778a000cae91a53d59860ee6f7df38ca0935cd64c08a34bf19981c17951b9c39a847d0637441452e38ce5e1d9b99bed51b86705cebb8d3244c40bb8d70f846936a2be29c21604a7e6bd3e655022b929954f6c9a5743f5fc2127b49956d80128dd582ceaa06fc174813e5f5e6a0a4d7d26756fb28a6588e9410722591cce2a6c6ed0976b98e1fb0c642d5df8f08e96bae1fe10375fa1d7c70806101570fef1ebc8f58664281e2b61df2081b655013aef54616308504f5f4a1e8f156680163489d3fe7bb0a514f1d2d57ee6302853d7d03c767c7bdfb79e2b8c80403f26f6edbdd6a890a0a0b9b76d334e0f729ff9c47bfe960a1c3faf77e81b9ac156367423dbb4d766a1f3b1e67595effd76287f22bc37da4f0204633e804002eb7c1ad0836fa4d01e2fcdeab8457dfc3d8b7f1151bef3574f8f4653aa3780003787b8891901abc8250a974c15f2dddf9e1be6798647eed710d06cc3fb4c276bffa585680fc632d8efd1614745bc3c72b82c53feae935ea5014e2b321f69badf570fad878c9590fd20fb7bf1b31e373da93d1a8c63ea45e698ce060fe70aba0fa84f37e836f2ad2998f07101d3fc7ca2b08b1398e1687ed5a8ce860ef9b4889ff436b74d13281d1f6a7edf1dbe8989bfaeefe6a475e65217643e757006871e664099f5b3846553603cd9eef8fc195807361fbfdeb8dee6a0b79f009c10df397ffb865f4ebd0473d458d553358029c6b5a95d6ffee9b645311d10a8f479b7e5249aa87e3ded08311b4ddf3a458fe61ae294a22643861826acbbc9b0ea8b73157ce15d1ff35098ae67159b07ca7499398c26776dd9884b5d3786c87d48e864d8bbe2b73e2890f217e135bfdfc4dc5e805d9cefef5268e33db611aba6a5d57ec82b7246a63dcf3eaf3a51cf503d65c206d2362421de774158aeaffee45a6b5ad5cc0b1de0e2ea74e97913729a69e9c00a309ddceb7738baf4757ea9cc96e055bbdf692b12d8b01b92ce5ecf3d52187402cb7fd961a2672dc1875b6ea22ad7f5f42b1b52ba2d780f2e6c5b25fc7e30b1b663e3a09c8ff0b5c302e0e7f984ddcc62dda65fd996e17da72f02a16c354bbdad44c5b5044759bd53789b98bc58cc25fcdf10a9cbbf0fd6abd58a4cedd92c5d85ef22b3c5ee5d9440ce42995517d2f7352ce997f51a36b9fa5703b4c6491ad01f406fd1b5bf85321026d28b51354dadedf057b37743499a986469f908a01f3c1b74def5d8e2f57ed25a80720b540333109a0a65e7984b557f65429f3d3bd7ec3732a10d7af36dd5d2414a09949a0f57f37bd9021d2c482e61437cc15e9dfdd92d4c212c4fc6c22c54591e5afd48210fdc88040135e433f50e45874e0d5ee2bbc857f2c80e2fa4fc7acfec8eec0cab351f677c790787c715945c21bf923edc0a58878ae09acf5fb5a003c9c0b6e30a450ce6dad4b626108b88e89f1e6a7bb3843e1ec8aee35af69e81773cff71190f819ccf24142d60ac51b80b61019ec7ed2efb6c5f18b499fc9727bed2e3324f8b94a522092e0a98241e29f8f14c6561df3fea0824f9cb0fe10bb497e427ee62085e7aabb2900fa47bf27c1638bd116c5555c076deefe9754e8ed333d72ce9423e27ef640fd5199c0cafbcf2da1c5c34121a69e7e0deb3c268fe60c6797056383da43e6f472d225116f63124498271d3d43aadcc5871f2349ce040be068d72eb57b7827a7d9aa01405ba0ab07e684b91ef05418948f6713aef1f4948399e0e6130740cae3e481a6366295422be3ee2e892aa9fee86a6e23e2ebcbe654989fd93d1c4e7d62910e1223bd66b7c54f8dd7d373986e5d4141bf0bde98dd13aab7d598d698660f11fa4bfb0ad09d5c27b65386c8673e6c4ae9e8e30f8dd1a5a3fe557a3c29dcf99a7c376200ab595c49445e740e3daec07bc047fd6ea4fc6cfdc23d7449f9d1170fe635ca36d3de5b57f1cfb182de240cd4c1e480600c449d1a8596d8315906a53954201929e7665dd2e27d590d481dd394cf2e8ae19217f1ff0cb511def7460dc9e49c21607247857ba744b1384344b4c2d8ce987512376f66f1a279509281242a7a2a58ed500395418138abdb9c5572a258d157f4d3e88ed216bbe9cee3bd054fe61f94c59a4ad19aa62e456b86cade61622a6fea877575eeaea20c76ae8a89e7b44396bae0eeeab1c23f221a3df2b2cc683256a4e5c8207eda0b235562ad3b510f9d3fbe0b51cd8f238a0abd2ec182681606c8fd111d8ce1ec1cda6db4572303ddeb925ac1fffd75e321468266790dee6bc0e85070cee749d9e46795936324dd1388e1b11aa617500534b8daf2de12b035f73111b770f5f56f5c6a4152c45ce0e112e650faa9f3c7e59e3410745c29fa59cae5cc37fe4c6594990e50df1576b69b2b292afc58a804743f49dd7c98c1768fd19ab4213ae4fb197492af5bf7fbc6c8b507673539d8515dd527fafdd8ca3eff629caa720aa11e65922678447ad4ddf5ff943873df5203afea4130ca5f633e104ab083ec690cf092d208a98006e91bc7e33731d18e592869e564e6d3ff8bbbbb9837ffc1f1b92de0f5dd4a029c51e3f64592cac3de1b4ca5414f894b7b0b7d73d6bf1da4b908aceab47771da56a8b0536301fc5fd270caa55ce171332f7db2eb4619c4b2c1971ebc0ab8b0b11fd54c24285da8428ab9e0150d8897216b133ed554de8cee532024df8b8d9314d7c9a3ec60464f9c7bca8c3d4fba23a7b543ac111aba8c8f1bd54a243d565dc062f84cccedb0a03375fdfbcef8ad8cafc440d3e6f988dc607ecb947673dec4ad48724c91a6be22a0027e42af6d94d26d188d0b7b3a5af012880fc0105dd2f11171742321dd41a0401415c58ad4dc445642a2cbb466788f54d270bd8df25602b298b62b6d0fa3ada97008a99b73a807092f8957f17eead9d53b1128fbef1defcbc607ea92afbd353e95f52d33ab7c1ebe2&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 95&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028d397a652746f9b248cdf13b9b20063d43b63c20b9b70f2f25818941e8bee0f44b9699ce7ed29e3f510d5037156dfe04da53faa45557c92c5cedfa9fb16bd35d5ed668de4f519c8920c6ab83bb8151add739cf5745708e378d2a85b5206b2938928a7fc89ae4561d8ecf69dd45d14e313a4071e8423f834fb72c966e03de23b71e16c9d5d5dde05b04f919fc241728617f451eff8bcabcd33449610bd1a2ca657514b27550e707d152def7d18875428998eae4077a9e95bb8d3328e8d5368e8dcb61cf541a65b33e8fc0e16e74617418932c83a3cb16a4be4608c25d78d84017182ee3e6f09054d925348c0f3529349096277fc289a5a10265f80cc96089d53f1a88b09f40a18753170ab8ec1a54cda1a9d8e2a61cdbc3b66506731ce171604b8121362886cfeb23a74561f228cacb0ce03e7c664a115eab73f6b08a7d863b9f8ce97769364885369534d679b4e1cae00eac9b658f8e9e2aa5217177fa52bbcdff5ca19893130d2b64aa74d364cfe7dfc89b1969c2b1a036319b3a4ba453194bd21cf6b35043e372814c5d5dbf15459c699e0f53e7ad80e7d0c4e39b1da0b9824242b5ac626c2be939e6539456ff1151fdf31e23c8da3aaa4affa18ecad8978156aca54454f7adf6dac24133f479b0f4ab2e667cdbeda0b3e7a50f67ac087b30d1a677ffa573ef943124560c6625cfbebdf7bc593b0df55d854c64328d352d87f8daf48aad5566e8693f706e7e6d8a1a04c9b91f1b771d61ae6d74f795c325e5ca385c3b1c5a1edd623f5f7cdeb985e26a1dff046bb789c9d16650392cd6a95ae0ab2e7efec39748552dba304bca56aba76bf9c42a57ed6467ed4c549b32f48a2f4b8d4b26cbfac9f94292b757ca4e9367111bf300e9f9a41ebe53e029945ee2366a12ae66424b0ee17ae0dae636000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381092bec1fb3f54c2ba48103554fddd784ed3542935c555741740b7b5b3f14817d46c6940003947a599ede19587d5ac461545c9fd26e1045c6b375294b93dad72e6aeeff93c88cee0d358cc4b520643d39a9fbe1866c81222081d8e9a58f30761385c27f04008a8af3ce0a1416273621dbb5b284409587e9184e34798374c7f60361ed8474a192a6a92ee23551bb207e0cf06b85107d15858b6a8d2bb09c8a0ba7cdca4e9a1e61cba8119b526aabe8658b417273e68c9a93b3717d206b61cc82ecdbb82019bd27f96e3168247f82b0e06afc2c3d4e2c37283d86c18cb58ad156232211b4543a6c4fbc48ed20cbb9289cab66593be4088b005266dbd8586a5c846ef7f822811b3cdd5303d3ea41f60bfa2a5cd3b13c478ba0d90c9849bad36c4b42a9c1bdb3260bf8627c06054929263bc0a36a602a5e9aa8af79b06a481a5943c43eccd5b8251e91a4d59d02613a1b29d824bea8093378888760d5a3d523e8da7edd35b551ee83ba285dd6fed9e13e4dc9a046964329590dc323c7b6aee5a7ba2e2891415922d66b0cf328f9f8815b4718bacd7a26368d9d598ab4fab2e902320534d40c50c0beaaa7015b57baa11df2891a5a1093c6fbd4b14d08117c67d5d36a57a0745f40c7ded2632eccf749850c94625c6162c5e1656d32a061920d9c9ddf58b36ac71b29b9ea970b68627948f93808d6b9dae8b3c79fda25a865175d1c8fae2c693be41fcc1e5ca346c26193601132c8986c10650d6ca48dac3b1ce50302ad682998780305d0815688caa3644b849d4a5a32703413698a1db0d29fc3a39b15e3b1090b295524aa26d7564f5b9027e7be8f20ad1110f0a5d12e4e720e1b13969f2b8c9f899aa7f943d1cc14f26d0d22d2ab9a3929800bfcdd365543ffadca9947e98edf53397019672fbe1b62747551cd290b8ceb0864c44b3da27f7b7edfd49e001a1bcb0ee982d0035828ccb538525213c5a07b62b1e3265c283495e5478567dd5e0e6a19377824c33592e136a0c0b93e346511982415b971b1faec6b5622f5fec9f86c403d3666db734e519cece928044087ba75c0c27208a460a858344c26a7801881491b80df264972a46a108abdca9598cbc12a0315ee207cedd2058af4a2d811c34e7c67ba66587e7fed3623c09eb658e9500abf1a7a6dc24116606c3d3d6519e8b26e7e0d06eea1692f9659c09bb8814f0b3f2473c3ddc7a7383e8f689300c803f613a23c893a7ec270f26d648123723215cf5ee1650405ba53cc4b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c81de897f02ae7292abafa6a0cad52929113410f2ba972b4184e894c4d31081420751560956f49ce2b772635625afc3ca6698fbfde4d0a05ef243df190ba1ce780eb572590e01e6e283e1963f2b0722b0ceb365552f65bd405f1a284ddbed07ba61c4453d30cc28c83e41590e09d7bb6932d231285205d61332fa9263b8a2d3d7f7fa20f521ca4b49f249896780e08c2dc41669bf0777278f87bb1f72cddf4b998062b1642791f81ad474d6d8f963dcb4458ce11108544c41cdf19145b77038c7e8adcd6501508c53b25be6e787313018620d1ba647cca4a5a8399e11815eaecec6ae66dbc576699bb0ab44de111ab6f252256389efdc0546e641de87fd6a3a724716257a9174f39542539a593864441eb79d499fcdf2f1d053cebb3a1fcc09419d2c553c2265b3dc3943e0341bb49130e9981ec59945fa0b23e9dbdbf352aba0d925c4333f2ee1f2c83c847efa78bb13263b893d7cae029bf08cea2a5d1b5b997e403a489c6d9a124fb8386fe58c2476894e7754b8e5a162102a119482b5e59f8d89c8b1dea70b6c80641c77bfd12d45c5b3ce0021ee500a1665abcf740794e0d3e7e8cb5804a1e0d0c81a107dee80bf63bff8ce2ee2dd602df279de39c579b417a758356d2b48b41e83495dee9adfe4506e03f19dd096e81405264d408b2fbcdbf41db5ced6fbdc2645dbefe5bd038382993970c7686dba3fedc24e1f91ba4b6cf70b2e832b97be24b6393273a519db0b4446e98d77e86ccacfbeccb18939013c66f7a29b10de2e88fcfaef656b858b7dfacc4f21ef5f328c0ef604fedd993510ba40530b79525fe8d336def0e5c303539e664a9360edad7268f70df4de199ab3f70eb2ba65e2752bf5fdb1e853e6f4efcafbb31d8cc23155413be31082da958b01682894a9057cab66d4d64a6f3b1d81c5b75815a3e0caf6486b17339174276a84e11c117b060302dc2ee06a03c0e15395c0dd32661638f059a385578c1b792349a41c511d12ac7185b060a831ee296e6626459c2750faf3afb579f6f6836d566c00c979b5130e8e50431e914834cbb3d26f6e5ba50bcf05d50f699faf10767aa2831c3557a53af14bfd9f23c00f76c2680c7dbf4a9b2a425e34c943228c3ebe55a0960acc757d7878f7943e2e8a1cbc8c0d2139a6a6459d3492a1a7757f71e90a58a78e0ff9b04d059c5d131f6e3c30742fde5506ae7860045a4c903de96dc43ac6a69273bf8edab7e7fafbaad9efa8fa609961502efaccde63a6d98d8d017075487c608ff701a7e3381d7a2acb134b198950ecc6970a75af5625faa4eaf968cce48ffb673f4f365802a984c609c33ba312140a60a6f0924e945d11baacfcd643c874d352a90367ea4c59b63665364832b1a9a9a01eda92c64f393c357158973fa7c6047b8b5e27eedb28e26359402b63032f8b230f5aa968272819ca486a8bafd3d66799ae951cabf04ea81e1e7e4632b915d4e8387c7d1f4fafe1c1fc8666fe0318403ea0027487e947d844a7fa28c0523a64ebd95d2a8abf6a71fefb5bc059b2cbeecd4375f3a3f109dead98539244ddcfee9e42db3abdaf943c445712ebf19508a1ffa6133c5078c1da69a32cbe729a8876c4c73cb232024a87d87fd5f9456d3d4a936cb4ce2e00ef415406d66d344000a4a95cc9651425a16021336c4beff310210324c754bbe13cd0066c507413671c80cf492b4655d898a18a2f4db5a393400c6ad821580b0712d6c919c62e87fe212260eaef6876c409fca1047a67b223e0766144f3f676f051fbe912c4ce4a9f7b85459da031ec47c621f6ef06cd1621421fa52b047b51c944dfa94807083b4ed40d533b19813477193d1e4e96c8d76a5af3100fa44a985a6513060b08a7f3848159b3cc551d43370b223037753b824a099a7c7df59305be09e2e79618c83818bd542f39380126a927190ea5536dfa63b664aa7601c6d82cddf4ce4006e1af2601ec453971828cd09c29d2f3ea6392b58d38bcf40bf6b6497f6b848cb853b187610cd23880cb09787c76087356c66565c0399be746a81753442e4aaa54e84f1d8c2ccb2d00a551e960203d61e71a72e131ed1967dd06e72c99264ef2ee5bd156fc869b5031ba23a6d354d7cec58f339f6bc2dd1c547f07aa733994860197dce5bce6024a74668ed89a2c9cafe1f78b31638c3225d96009c260fbd28c1f0423e75c9c01a0f9e62b7f265fa3817f441f56ae79ba54a0c107fd7946a2ddda60d0eae428715fe2b4ff93bef83cd10e5e17760fe028f1aac8084a43edcc12bfd3265d13fa94d9704809a50881d48f0080a976c5bf31b353b9043c0f0b69ae6f2b8badd056752f2fc9e90c4b35850c2d45b9f354b41ed7826b976528875547a0c389b83725e26c006cc8240e380e3eb554dbf2133a131743539b1d174cca6b135c59f81d499631bda4cf90ded836e8c24c074a0bcd83271309ffef320791c9030fc2b1f53fd2de870e54eba20ce9930c279b48b39cb481737f012f65933650374ba39e2222191b0e3c7db9632ce9cb077322cef97ed832ddd8aaee53c52c03d2aaf8eb5597d8d6467a406bf428e2f16462e0c0d486a1c1c7348cbbf92633ec4ffa75945025a3c92095317e32290d4cbaa6ca40f3f201975f3fc8b733d1467c094e075e8415352e3ae51a6c5169a4aa430bcd66ff39b184f5b7174042dfcc6840eef60ccdcac12d012ae4f24f7184a038d8d9964ab405366740600b98cfe2e4737c8d846fd4e9b22b5047110d85b37bdb9e7e3baf5298bbdc1050aa20f14e34dec283830f5fa9c570c22ca659c1276be8ffbc0ac3551db8488855ae7ec21e239e88a0f68227d17dd87ffa3b3d0535f9e57807755de56a65c0de9f4a79f8746b20908bf9416a86f62ee2c2545bca2d55cd4d45dcdf06dc879e1b6270a80778d0274aa658395d800eaef367df4f4d838eee0a66093e0f419b9edc5f003e31cf0eb7e1cee9accda7a2dfc920a4b5222389dbf12ad17392850c434a9b3c260159b0f52e78e7a66d28dd5b3c77662cfed2cb3dd5bc3cc26a34293ebf1fb3a9bc59bb0c104c5a9387f3893a65d145d424ce741a375f9c65e733a024e78fe274b29ff4b0eb6f21fafc31453eaf7e48fabec5711d3898b876f59952c73123281a8e85148cef5a166bf45df36053d57ae6f29d3e334bb2395fa236d4daa8a4fdf99d80a9bcdbed36154bf4fa3d463d51974032d7b88b2504317e14165b1c3fe3d8fe366fc8284321d80f9cf512f418c63f73b7c29c07870332387bbd1a870ac39485f64086006cfd68c8299347615a423736c01faef2da56cfb6fc966948649324e22d4551b9f50654ee505547f7d0b8481adf6aac3977f49d7e6ae5c4248df7b43bda7f082aacfcdcf1c1bc04f2d45f5e028498ecbca47ec4d1ddeb03a2ab27be9e4b80585145676f8ae7a5017bc5efa317a576ed6e423d5a0495b8dc619712a2c3e6162b04b9bbc7de4be6532f6c1c019e702c014c60189a2612594bcb18317804c630264d07b7396db562777bc305b885e00706ff6d0208737bd229bc7aeeff5fb770a4c057b347601f1f6c16f60d4a53a0b32631ad2d41fa307f6630228e1807d22475d5e331a50a680896dc606f3941ac08f8ba46de5a49f5ed6a94965334fdfd69c4a6c7973d9615b3fe576b15aacb9b98d9e498d2a3a89b4f8eee715ed5f29f13dde7629bb386f7cc800f16f3b5ba8bd0e14cd8d9bb0f0aa615be9d7557f6efd00f7bbef9989e7f463279408e6ad77e100ae4457d57424f2b1caef43052c5b25c896baa1c2fe67d1d6f669311f17d39460f0b176a7727f53257a36faacbf3dfe623d8f882f8ee41ba1ce387e1d1860f4babe26ed678395b9979d84dea5c7b38905d4c7fd867ed7722d066bff3a833d3282bb40d1cd310dc8dac9270a49b65b5181eb30f166caf0832a8dc56b9d135550b506d98d036be7876836aae669507990de6d03e78a38139cf64f65fb410f192e30b045c93fe259c10e0c5b56a2b5f0605da0851104c4beeb4e3b30135cae5a6c68403c63121b0993832834a3b5ebdd345c41b26dd219560b624024b8b945a10d385b3ce4e0bd54e10a64aca59d283302028a9592120d142cceb1cc30e1f96ad041f1e17bcdc3c68c2ea2e0d65d6ba3696166cb365cc461abc4d67d504e8290eb452ecb77f6d5faa5053d01317646242384c5c510bd43c5780bbd01ebc3af33d29d8a09ef39ac85e70398d2a64dffa72b3efd8d6d57aa2f9dac0cc6eeab27b69fdf2403a5fede0bfaf441619be03fde44c49ff0a34e9c37d2b9aeb726d56eb646a67bf349323f397db056d71de72a2597d780942554c8f8273e307dba6bd02e944e0559509e1f28b511bd709d03ea2451ef234df6f077e06aa01e2806d5bdf89df29f1b3d8c6d8014496ad83857f7465f1072e88709d0194733e1fc8c9f092df5b9802fd2ddda8b142217b9532d8604e2f32d06f6400025930da2be9b25529788e6bf4eb7f84c272df455ce2ada291cfdb5fe815129e4aed59625c879e99b3e3c1b6c5d700000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 96&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028e39079c54f29e38d69a12a0c91d3279ae0530cc982c40e032e08e6a56434d8908bf777b792070db13a23418f8bfb34e754cf143199f85067fccd5458ff68b2b7c8a20525879a341b4984d0f031d6ab47be0057aa395c9945993698f4a08f635a75bb5f727b4d9d3d1726f935164fcc42216e851967e1e1533593ceaf7adc08131d8c4ff03a1d4707813fd5f498baffb3d4516daf219c10a47f3505efe09e964dedb2988bf27b3b9ccd241fbb7c3cdcb43e6af57f4c4c56689298c392edd425a3a3a24883b08b0de372aacff839d9995bf3a18c2e4dd36188f6e89ae652e7971e8266b165ff797981d70d866b2fc84a5b083d3e6f19dbc0a3c4a692d5b09497fa3d12ed21c439f1405971ecb4d8a1ac2210993c1f64fabcddd2626cb4c7228bc1f1443b52d498a5d6c0eb7d9acddf45f7afd0be4e7a86d2eb8b1fddd14a3173d88f258c47a495d81206c6b13919b4a16ede7737cde39fabcfb31bce8aec81bc2e45cfe1dd4874484421c8c8c5e848ea7b5092678d3b5fc4d6aa0e2c411967a6931a16671f68c7cdac6c6b9c23c628924c3369dc88e0f860f3b4927fadccfcf88a5e918b846522feeac8844e88e4e6c8e85f72d9520990625604613ed1a42a358d48660ead358ebb5338b75c5195bf229d437abe5dd13457e1addb97fdd6cf608161f399098956d245bbc8208d6b2b70a31525c62c0dde06b78edddaf1795f1b36cf7d5ea4618dbf5b9692a84f7aac58902a8f11d2e8d0a41e780977db214619d2fc753708fc4d1b3009ad55e8d64b518d75be86a0287baa767253ea62c8aa588069b91a93bb43d41fa98dafb984db882cbb61ee9d9486099c96bf3c0b76736d16c58ab15f9fdf780ffa43d7adc8d457526f85d3dc9ed483d32f89b39cdde0c1a6be2d8618e2b2034cbf327cac65f2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003810970c17dd329e1ed13269d3b0b1288afe581639e4c4d6481928a7c156222d05cc63f2dbc0b96024766adc665be9feb0cad85832918aaf76d0a4d2ae0ebbb037c2e156b26f72349aefd386a15a0806950adb162db9b1b32e7d85000d67cbaf8a97ae0413d5af748cd0de34562e1f86963e049820521754bce74b89f41d25b57169849095490c81a041fb49ca05e4265db87f7885744320a37c7a0377e552245a1c9bf9501dcf85559f89c7cce5b0ac7b69aae25b040d7cb3ae400c7bf254c665c9b40bb0ec81106b822c495c39b680136dc1fe10f8127329e2e23260834c8e5e7a516f49c92820bb0714cc5b482dc4c9ecd00b192a23e8f04f101326291861c9b049a68ed661cb932570d9091c85273eeeb3a6ec1750abcccaf96e69de0aa2a722a3590a197c3618ef8a7fbba0e8d7aeae2250dc3ed8aee0199d416b8653534c7600b4d7c6c7cd93e48d9289eefa63fdcd009eae2702898c010f2c193e4064e848265a667572f43d83d1181c9550c9d9a823892ef7bb0bba3e94852a6e107593211a585ac4aabcb870189c954ca058716963a8e22d6cd463928fc8b682d378dc90ac2a3c31267d8528b886dba668ac7aaea07ea202965723e5573be16497831255e6d7c3183d4944689f2b74583ede04bc48b32bea47050565a070f0e7a2545b331b95c7e35804894f62c7737b241316fe7e57e963c640a05cb2bc9f2f8f88008bcd9a3a9df46db1a95a460f04b1a4b0508b327de679739ee72f30c218dfedb8a0da2bc8419889750a8f977e44a89026cf37c405237c0975d0f612bf5846d892979b0320da9e8158a181b9f264705bd26101c5b97409210c53e4a49ad70fbdae2d1a32429607b290c7843f91e57eb8da522404b17a9cbee19eea111520464b2ece37a1ce364622584a371ca1f8b0c94b1fc66cb8d49007ad1c03e26e5adc4d0d436342c8d830203ec94e58a23e7c5eab37014371fcd9875eddf530de56ebf90f6717fdd6f05368c3894c175945a16f5e616b6a92911e8bf061a0fd983e3b26cd36c717a524e436b64d0188a462c0824be39c14d606d45440ab310d93422468d09a5565e3b5a3106d562c674b4dc08cace283a1ed107f599365e79a37632a589ae5e16179f40036008b3824daad3504effc9f6e7eb50ca9c79a99fc65da804f11b57004e8025b8e06e163c2c42f599c5f664b46f9764633f8b345e285d5da3424df6aad5c3be6398feb1444eb88024d071a9c9be9cb80baa5aabf42ede6c75f51fce000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ca2525e8b98c55864849ffc71ebc953f7a0eca6298f6aa15a83bf6923bd5921b1c86dbbfc544a39c364ef6d9281481e946c994f96829d6639727a5345560d8641e9a510f913f7fe5592c2a40cb278f5afd8d4504b5387c20945654f08168247a98f56a43a5020955f882d2d93781f4a83676b08f50341e953a5d1b67de7f6d1be3d78d5d060aa85b5ee4271763c437ccd595890dbc8fcfaf2754ae9349ba2fdf89847a15188716c0ec672887a4b9a15176ae0c5138819ca232d012be1dcffd29f677442083087c127cbd80b0d9cc0962bc8318e734910d1e2653bbf700c84bb0919e12df331ccdc7128b41f0666f6419afbadaf673be16c9177d3cf113c6488504de088149bfb83eacbbc400309b7ad753f7b2f5aa89f070c9d14c084c32df91c5f7cb6a7d869d64f4a05af80a98be7517ed784c17b0d7df96b9987b7ea7a398ce018ae6e13e1c0f7aa040ac3ffd273bb9687ad6fefdb211061a6228967e9dfef69bcc1c5d02ee56d49a93c8aad46d08322a2ca246ae8c3edc071d063ad605a97b8ae94d58e897a4a6310bcbf55b0cae1aa81769d30b46f883eaf29d4b5fea32f2dbde49360cb6235754bdc305abb5e5395360097378656e2bace675448889b0149d6086c51e9c3af07a76563164864f131cf9c0cd475cd4a58726ad237cfb76aca68032351fb24711da635871386b4bfc94b0db6d35f07d0196f75cedb92efbe7d653e0ff9326a596f9166ff6cab73125dad27f361d6122ca531d86910187e75f849edb52db26c96fdf05925dcca232480d3f979eab07cca68fc9069965d12bb666a180989ad1fbee3fe65e746c5a8f64dab2e370f0487d001121edd0d0d760531af46da65c75de11688ebf31dd2ac95c188bcfa07ea798609f3ea8e6364a43742a2825144fafc05abd17476480812eb2483734b13d075b3ee3ad510b67cf7057014351b2ce5357e3f12f43ba74ced614be3a9ac0e26763e9ac596f87ae98f72abe0de213a81a9a03e2b82f2312c1a186dfcfc3db346feb132931c793ecf837f57d8e326101f59705b77a3083e712ce347c2c29c23468b0c5857efa410197833987c61ecbc2a855ef78b3d7b1b697ab9844aad07c4b8ef666bd80daba5fcac900c5d358a11676ffc89dff4f36f29f14d9f9b854dced41ffc4b36381449d22801c19bf8e8ba1f07a1b38ffb527a34d009c4064a1e606ff2ab90ab2e05c156150ec14d7dc792578a16f46650d0abb61175d1817e2c38f109ebc01a3abb358673561691185da32eeef566c1ba1c72c1f08cd1b427b552425501b8783116f2eb0cff73c5d2def18d291c106980135821a77428fab20a935ac8b6dd8edd1a936225344eb103de0d5879cca09359b5b882291c0fb1fccf167c30dbecfc324ac315713cd10f35b72f0d4871a7cbaa2b4cc2bc2598f23da607c94a063c9e2013b0eda5f3bd5aadb2c429177a4bfd7b6181ed5f9a55c1f043da8155c9e7bebda7ea07dea49938fe07743df2295c220eb53348310842b1000b7a02ac025c3a94fa82d46ed7e2712de71b149742731ebe62e225d21a7f29d5f3a8a62b71fe16258570da412c07cecf82b2064ab5d98761c69fc5e899a8e174875b3179deaa0bf4a0261da9bf39148440dcbeb0c887e41fdf751505de79aa1f8593f45482b659f5b5f4cc3e7bfee59def49458db195a1a692b8af4aa44ccfb00b753ac761181b8aab39db82385ae776cfc585f7873613b62de55bb10a6b2f27e631ce41436c3fe390163e6f4ebd6b501519c96c06fadcac8f75920fe1435542fdf535ead6c0e3f41345996063b95a208defb6f110cc861580979bf4422ed395ca218cfc3b22c0ba8b31cb9eeeb51c3df35fece92795cafb8440f522b44e21b3a18d5cdbc296b887a4b927f36715e4ac2cab043d8b69a8704d6be24c725b0c2e814bca7b040c27fe8f4c14911051039af13f44e0485eb767f5404cfb6fd19da24d82fe24b53033c83dd8634e2e28aa330a81f14bac1c57dead7ffe39994d9d094383e14322e146a3df27a776e2f09a11ec9014c809f8e543594d6b4814918a129b36fd25015a044e04d3f081d4d201df86a0fcafbbfc695088170b8246776b6a28e59449c646d1e706cea96b12683cd3a7c60459d42989ca46694b0089cf88e9aec5e110f69fe0e3fe20d18309d1ba72a83a34813b771484505b08548fe5d376aaa0c414260ea4bce5eb81f6545cd5203026264938905be1e252574f4b4e71c6e12f99f6efd35effd64183cd0665fe89d6a357b1908e083511dce2cdf792a608044c31418c433f86719e156af3ff98d0f54ebeb9f9fbf24588a5557d310ef9d7cf5dd8a68512d8cb15114773c69d7b40c927858afc049f7c6a89841020e1c313c5c38b988ef505ebe6c15fc1d6ccd8b472f90ed64da895d06ac01bb99f455a195a670d22dbd5e3f03ac84a08831e9842a566e9785a0fd4c460c5cac154d705dce1e7fd1c45baeb23976af881cf5628f3cd92ab19bae8d45a03a859518e4a1e558fac2b48a432e46cf274e6496b63874ca4e4571132568aa43eec3d2a3948f40d327976a6d28cd816cfbeaf8fe126913384061d219f51179f679081503371ea0b6bd7e9524b0ece2573304ecb4a16eb471ca0817c0c6ede751f283aceec5a60c2796c6261ffc6226e4813241619f465dce67b38e1d5a647b079503144907307c7d6eb6e6ec1936b5c94fcc08a882b4555b19b33a9bf22384db38473a313966d157daf8aad41ef67d3a5fe723559096ab1768ff69773eb9d5c88d6f35f00dfa4473df71c7e9e35393638ded05d05c105cbf37711d38e3eee35e8cc0029b3761241fd1e56969e09e949690d4fe25735d774e777a2ca17fe058e14ae6806f611fb1e9fcd516e20499a704b67990716703a4287b50ab45d155d40edc0aaf97f5b87551c236cebe9cadd562b27957ead251f79caac6433f228b50167fb1a753306fff08b53a8a3cecc226857a321700ebe23ab4d6c35415ca79b682d6cfef6b1341e7ce00cb9870f432b63a2d9a9a43c87d28a95c514582812da37738bda6cc76142e08f69ebaa5acd0403100c2343e2fa088441e9a55c720bb509bc3600c27c1d39157e049650d1749751efe55a72349e2a5b714556ce2188ce972287be2152c7e58d3fcad43a214a4095de55cae9f627d8b9018daa01547842fa1ad14d67327cd47eb9b90cd94afdf5244de57e527f17894a410fb4210e06632e88a398400b0aa48cb3feb9a90acc668615d193d5a98158092fbb59ad2d6d4ffee433a2a6a971a228685ae5bbafb3ab28242c630af4656c5071c545618a0a765fce41b19970c2152d44c349d0cdfb29673d1a42ffec139d1c9958b0962f7b57f80cb8fe6331553b0df93da9bfc722b1c001f48ff9c0fef032610a1118ac9ebaf9202dffea605272a50a90768f031c72d570c0aa5b0d4fee4ad568895274388104c0bf88d03fadc3159d6cf28ac6a7e3e5cf6fe5c6658128cbf81456db8c29a76f9c75230f3837f1a94cb83c3aaabdf4b29c9045b45ab9552bbb6c0844bf2926267c0d74d3337249d5c9610e0f6ffd0278f12f39c48650c048d61a3fdb8e1a2e08ccca68803a55b39bd39160b0420cbeac7d8a55f571f490f694a7aa8b725ba84238ee1e711864aa1f74aff252c088e36b79b09c80278dd442eaea8c7d5833cd1baa18bdd866689e663eadd0eaa6e0c78a3e09dffe5f6f1f4003de24336586b25dc5ee45d56f31d8bb2de31b24e87172f3f1b26d400b08d50ff624e456183f269cbf06b3707260383174fda152e4d0c528a90c54114c4f278d0fb35b74dd3ecda14ee89d38e3227a7e18b068f134b22154348867a61719c926ea3320d1be0b9ed78466b2ded728ca04c15ac144185fb2f5084511a38cfd765659351ac1ac3e5f327d9f3de9b2b003758da78dfd08faef3625cedd87c8a55a3cd0257aa71b3788fd2449efd1f48948cb304468e3ca07ea7044fa185a2b91f9761c6532b9273db74c66b2de95ab19e5102cb90c719ec85671e2829b182bb6d09323248d6584f0ca67d422bcda65a0146d8df27ab4ae651706d5fa33b5bb88adc2a1a95105d55cca8439a5060d110760dee8b855d0839053be595278eae66542736d25c93d8544c6e55ed51ad6e7029c2e6d32cfa8844bc14972809e31754af84bb479c504ee77cb65ceddb6bda613feaa2ae6598d1f4975d0fcf9d9dc787eeb5c03f8b0bf438e83c38e2195ef1d35d40f5a14e194bc1bcc64d02ca722e7da28334e91fb6654d708c5b07946cdf58747086eb3ca59d095eb27f1b7e6806d3a35335b2265031a1120f28eed8b4c5d9af268502727c5d23152149c98e6970d4dcc4b9d0fecfa6a79fef82cb233e71fc8aa999df66ebf5a1db2ed1583c65803fa8958f49890d13bc05c6a991f26c31766bdef9bac601a47c8c3c5e395fd8f47e56f04439e9bc8e9b1901a529395f2d57495d70d0712881d298a60e3e013326cd56bf9f1319ea8d6a6511eeff373f081478a51e14f0aa4a33c6c5ea7816380c8984f7a5da45b0c4b6b550644e65a5b2df059ed050936fe6f073b4e8056accd3eb65a0b000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 97&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028d394e72095eb17bb89b37805a1a3f472fc37e69a0ba427a32f2386f52c9dcaad351be308a739c1c7a9dbd87d8f94936a385c7b24130b8369b7f6bd9400e8fd37b31965d883d53e2af36885b80b1d76feb8a0136a7129c7f85062d0407e6c0eef27b85ff65a1d16632354bee9345e7dafa13e91887c4bc29bcf099207fe20097969b67fdb4eb74b5199814e8d34292bc4a7197868d1fc1ca586891211d540bbc9fbabbd1ed52e396a268d15cfe35101016e126af6a92e5c1c05b111a249a23609b6e239b744d8ef96ffbb0755e21ffd4d210733ce6643b11328abc24b0edec14b215b79d1025f64bb6aacaf5efba920612b139b6d05857e67effe9f458b5aebe63942a7765947fe56455507a9bf9676954afe2523897713f4b611c06b24b0924ccaeca743adfb592ff2b7e7b27b2717d801cbd33990b9abecee5d0c1e6efc9ef9f6c3b99f3a711b5cb4e94ad1484a14cfebcb5e5561c41f2a2326485e8899de892d2d4ba27fb2d60abda75957299b240e5126c7c9630b8d34f122b70ae9b09550653536fb14641b652264c84e25642d0e7a34eb1374ddd8af675a847de1588dada7079b3074e4348a68a5b8c1ffa9ec2c35fc6627cec6e326c2348335ab421cd9cf7d1efc4f57c8967ce5915f5b36adef74de89e34446a904f64f9856a366ddef882034548e4d1e74240b2eee58c95d59540dc3af1948920c90c7d0f70ef579ac9ee662572aa2ab8e464d27d1d6d035a7dac3a3b22788fe46f59e06fdc9398d632d97f5378d0957466d316ac613230f29d31a96233c8c6730bd89deba496fc2a40cb62658a155cbcc89f14075f66318adb79acd2f5f508dd73f497745fdc437783480ce64cca97fce946437e744b562d8cd9cd9d22932295989249cd951207dda684a49b1b270703415b5bcf9656000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381093fb566559429d7b2ee3ca293583b0332090685a0f270752237922a326f8d1995d162b779fd150bb454762f76c80aee6dfe728de44782846f3a0a33e0155a1504066316794de8bee576a69c1d3d6d508a2bb88bdf0c5eb4f5da1c5d1aad04e34ceedd8bad0f306b483a004889a56c4aa1536c57e4e28148986133ba65a7658c82a2b09fe1851c3e7c0a960838120ee9666fa2f810b00f124705680cd8e2413b8edf1ddc9285d31274b616c8344fab11a1ddf18298d2b0b7b20814d25aa66c207a9b0dc6934b696e980e2b8d47f90818b59b9397fc41697365ff6856f555f898434982015474dc435cd44961928b0c2e011d9a5fec1d1774adc5146ce0121852b8536ad64d591876b58b824e1945d27d02c035d4d2cb302ed453e6954810a95e95b86da3ea4338a68018d6c3887ca0243429dd1eb04a153c626dadd26c4eff16f88f8f67dac0a32a476a22aa5494a215d8996db8a7325f087c9ebd614a5c4a602c6684921f0267446d26fd0f6a2919b075ab8ef184add4d63e69a6196d505753ad4794d8fe829112a1061565536a8e812594d095fc677d71d0b478c807ce77fe37c3621b1fa5c64ba45b829bb7b2545b75d8576a8981638693a6a9729be6c05a57669d22e871d54e53b6f694da6e0219cd8ca8e30a2a84600702e41a6289a414a327a4874d71dd068809f94b8181b72eaeb681a9c235cd9a9a1aa58d875fcf0273b97dd18ba54e6045ecb2c70df88b3a0cba1942dc0be2993a040fe968ea7c17db058c558dbbb4a2eff03c496746dd608cb446fed6dae00b811da881c261695fe95f80d352f7190114a0aa439b2dacc36792a8d8a0acf82bce5d784d507b13c148e646e8d5762ba02b1342bb0abda08a50b1a787ab281997414e4a79213019cd428857217b56665b8408e4fca791bbc6b308cbbd18c6fae797af2f814b01f7c040696e4fdbeb033137bafdfbad90e61b3e8cb84164e1a2de34b9d1a5403712f1d49dc9ff78dc73968180ce1859bc103be76a6421fbbaa6814550e113da61a7da4de44b60b2006020401b95d3e5d39554bd92de075391ecc0e00cae8574f519974f8818936de1e000c0d68cf0bea5f9da43b50d07147889809bc9125bf2e4678d715f46e45d68bcbc44338d490a9c6430465d8e58bd68aac8ffae968aa01dd69faee579d0e4b65e8ebd84fcaf0b0b6d3143cacac5650ea67279bc4aaf19c2abfe11598ca32764e66333e0111e037ae8eabb0174b5fdb1b630a1a3743a9d8bb02dc4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cc300769683fe7bfd74b3acd21af3898b74ca73dd126c8315538937cac4ef0ad4588765a26dcce1c90c559ce691e7eb3e0a497d357e1ab583c761439c0a66d1164518f01b6894067925753cc2866a91552fcd0ef029c2284c620caf364de6c56eb41ee0e4431d9be22b76451d132a3f9ad91a53449be820a7acf56f6adbc7107c7c729ec8a64fff6a24b4cf83ff4e945def336dbfea6067fccbd1cd6b5698adb1ad6df03fd0a553457b8e9feb4a1243feefc2df7f66ae3eca5bf169f7891adaea8d5c59012c7aa00a5a86b0a33d0006f8ad5a01c60abbda6d249d3fac7ebfb85103a3a747a45d0adb7def52ed3a5f1a620ee383a9c0cce1900e413fc74a7a97646111d54783928b15bca783d01efc67f49ce6f781e82d25d3f30561f507e3831cb4ea5b4a08d5489830017270b63d8298beebf48eb56bda5685d5e1e06404eb9a6c3790e9b29c99168b10badf8fdb03f3c568672773eec96428149ca272ea5a8083f8208bdce361e7d40bc4da75029d4a18b0b6ad615dbf849935d4755cffd270a52fa290811cd55bdca38ed89f0066adb9ba7f58366379ffe1caf3a9127e147c3af3dc27279391e0c09537e81e20e7b9fe4fe3da970fe50bfc96555233cc9e61d3c356aaa8eed5a8aea2327d7036ee03e7ee40aa35e9da4544b121514c261ec1cb0b2d75b1d5ce129e47f89825f69ba8254163179fc1331a917ae9c5a18556a10c5f983871b1258cb6fc8ad207f97a220c5598860b6c56f1eff09de6000241e901a89e107feec15833d34d6eb12db6b188faa0b858a5b9e32f84f783b43b6f8a3b2e4b044cff8902e1eb0c527bb4e29c92acc9dc7e0d9ac6b3a021415768b21dd9695983ee89c871c0eade0bce4fb72e682dfb5a2bb7498bf4d2c01240f67d1b62baa4e587069c16e3032114b14a1c4288febaebb4c75c3c05924a358c4bb7df95ecf81d67147fae3f605ede61b7ba164eba1ab36ece97db0ecb32a673e899b24557d8987af3adc57a9da609914c9b2d6d8ac58e5954e0db5aa9e75b444700b8f704e15a6a7bba81809fa8801c6ceb5747a44ceb8f99cfe6d8a2a03c03451e5f3d392725207f3dd28b2c00004425b7ae05fa3769183ab60857b27ab08bcc4321d293c93d1d850d4e7a81b14564d7b15ac0e3bc1bfe0561622c6aa06923eefe163629ede8ba1732dbfcad52d3baa6e11e569ea790b36a8472b2ca37bd5c0edd37d8f164b874952d00d592fb705c6b3110a12b03829c157191d33c579593e7828cda5c24a284ba2f5a42f0bfa601a8f6d3db1ca6d703ecbd261629c9f96ebc0458737b9951219e5b1f86192e2a85b47d80610a0acc8b1a70db2916f89cdb2c7f8943471ddbabd2a3536c5dc8a73cdeddeaaedc86fa148d2ee479f8465558852fcbea0dd8017f1b976281a5014319c2c3caccbf571d9550215b24134f6daef32716802e7945cb3f97afc1ab1da17d0c41b545a750ef345a6f88ad5ff52d512afa6558335b5eb8979d8e6dc1da562bb997e7d152d9fa3eaa09119c3474e11218230d8a56c19ad87fde483fbd6ddde9acba813bebc8505a323c601e5b5251650dae9334562e3dcc38a28bd7ded6942d0cc2014235c1b66cf4a57ba3010b83cc7050309f57a27207512d195d070db3d10ffcbacdb47e4231142bae588f92c5b0a71abd67ca9390c2e05fd2cf7a1fabb14c5a7ae3773c66db1f055214479e388b5e6abf0df8fd1b0e4f90828acc397643cbc274143fb4331262a20634877be4c7489c1ae9eaf90bb2a177a6b5ac15cbda27da0616e5f87461554f5686a7bd6d047ad0b98c8cdea3db78dd2970c78fb861f2a92ddc277876791c4a30f525659557831f4377065d19acb384cc68340152a6de6d84cdb58f433923d1fb8cc6b10bacd95b9ab1b45563998620d192032269fa8301c09a29c4b5b20ca0a3d63a4f5984b7db0f5b17417dc7b939b9b177bf423e2f3d57dff296e6e4ff0fb1744b13731206ead54ef0aa1da09bea8b0ac0ef71b73d009d30531de9fde90d86bf5f20d8e5a9e324e657a98f8c0031adac4385157ba4e28b48aed957a5b36c3b49057f8eca7f56808f794014dad170601070607010e004f42d01cc63b2a1761126ba045f1165e25fdd05901fac6b76e777faaaee6f5ed94302e2da28046b4bc60228e1b9e194f364e377f84681b3011583554b76fbf8d7456dbdea665adad6aa0556c8cc714f217a518a98615c4c1cfc8adbbd4d12c5bc23ad7a0f849e32fe2005334b55d7bcb43d1c95d4793e7c3882740cde8dd24b367294496a3e2f3251a66cdaece9e0a73d853f8d4e3a4637836ded68cb28ba4fcab02d61fb5cfa581792e636217f3238d78912ea0863816ffb2f388823174b19433c2b14bab69e12c3b791fe683744d4519455a52555af0d7e12749f6094afdba00fc6a609c7578c531fc4c3c3065ebf78414f112014726ec2230f9bcd9c15e36283144ccbe0d1785b65cf49ba8fefe92eb6907c0330bc98ac172ea9e8dd4df8974dd6b6772bbc6ca8e8562c5ec0b6592de7440ac915c35e0ac8087f22eba110ca3037b469b1d5bc92636d81881e38d8bbed01a29b3ebcf0c19eb95bf999eb848022592aeaab649ce19824ed9d3a32d75fba556ee07606a306d1fcec2e24b38274c361b7bc96ce37b7f4fe434eba17ac2a097051a92e4ec32e4c678f7762e8b96ebfd2600c0f224b04b2cd7e9f4ad327d53603828015e9cf45969800f02fa5e0ba26b8c844ba1fdffde44303ad0389c1b31d582877ca6bfad4973ba35fbb90ecdd95f430078bc39aa89434130a5fb8321e51f9624090d0277a9f112ee8ff65d3dba999c7c08727d0f08dcf00ce22f62c955d6a822f247c8065ab94ac442e1cb5f31254816794cc2556891a523b8aef09d3b9e07aa8b67b3b87567adebdbdfb93ba9a082f72052572c97e73af16cfc42d2a51a3683f84748a338aab56264753ba4083d356a27c71f47221ed8340c50afd46cd207c4f9634ab5a44888a4234770c46232c35eff83fa950b0a6879137dce209d5a1f26809b411f046f51ff084f15bfe03292ee845d3044235adbc299925235462e67f803daa1426f0e116b93f4532dd2784f7f87ae360281ce21f70d230c242e1a98de8fe1d6147ad71edec89e24a5980c45fd91e23516758af71df8e0dd96929d4da61a3baeabb96c9378986deb4c9101175e3af1e102b52a8da27d916ee4a28263ca485cfe87ee5436249c1a2f933669f6e3274e9bd93092f4a798ae85d6592ebb54dc65c28ba08582e275972b0a12c22a7792ccfd4a398e504c6fb2cf5ef1f9c268540b4fd7d07d59c49a559d86a56a009c4c18a3fceca109fc7a45c6e842abc22053e84878c4805d96ac96ba00fa40fc3b50407141105845055447ca94bd27f234183c2b8bf37f5cd249ed0705afaeae59c8be8f6b38069d67fb23f74284e8185c176b58b482900a3e09774383c7ecacf4fe5e580df99db102ad4018db73c73a635d3fcdc833b000c948d846aacc92ed54ffb3acae1bfe205d6b2312658f15decfa085d13bc3757c754c5704d8089563e0ccf52b04a49df293cafbbc2fed5d9551b5a3897ec7beaa56a4034bedceb4840a9bdfbb8bf47d66dd3a4e3eb1666372c6b2c39a48d52761bd36403cb130a087685e2eabb8711c11005ea09f90ac49665415c56cab6fd2719c45b6800df914f8ff327eed29d9b9a5bbd6b80b8bb31ad1522803b2c8d89166d5c6b2ed47bc5bbbc4abe6709d46b856ab81ddf15f098a9ab76a8257e7e5c2e7dae53fbd691736f0d6bafe0bb939172614e99c7d7e37754af6c3c637d076a43dbd70e5eae910c8170cecff1621e382d2977635b67f4fac555419f8a0bb76ccaeaef4c7385d293c9595ae10e5201c4a31b4c3ecb9f3b304efb1886f9c58a4ef04e73341b95d9bdb85d706b2a8d3fdd153743a8bb7b3289d0fe79f6a3b9e0fe160dd6700fd64fc87d9ac96858a6d395fef6f3d2193ebae7c3a92e18746a7f12b244fbc5b1df0086cc7045036519d9d7bf8e92b850ea0d3d1e775dea362362462dea2d3501d39203e2879070d1f7ac92fa1576f6d12886d5b979e3c788c09a769ef4ee45e14cd8e7553ebeefcd31ff3d43d4988db08f6630ba8ae8c7250ac42a3d78edb967d59310a4a224567d8797c42370cbd2302a3f49abeaf85fad9455f98b61ef2b5e34a5c552583872145e191bbffcaa526f5e38e497a1a1e1220a0f283a935ecd366a9069d5a2a80baba3a22fa85a2557db72d7e29eb4e33e8ed8bb4ec2ec7c2e9cedef46ea955834acf8c9ab23b78052446fd73c9d61683d7fa0088db97d07cc350af0b6b2ad7e66a493af814c11f8c0f2fdf0df40aafd0d218c00319c367e98d7f10c74ea06d31276f3f216e1cb2f12033915008cc83b00ac60fc9c2fb7f97d6e8cd79650d0f9d82bfd9cafef668021d3d165f3fe84221998bc8c29aea0b5b7e0f1f25a0d7447e806cc3fc39e6038be3df9ac01f46222d3a609f8a026744ab4f58a734e3782bec301ea91f2d8e2242d04a11e82474002143223f29656b1a7675aa5ad181004c4f1381df6a0f95a0186e82c04b4de881209e9ccca3ee5b1def0b02353738d92a07314403a1a2721c256121fba8b8ce9b4600000000000000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 98&quot;,&quot;NoBenchmark&quot;:false},{&quot;Input&quot;:&quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0000000000000000000000000000000000000000000000000000000000000028e392b32f0bc77e652f9f228bab513cf843b6e23c8580cb88d267d0cec21aab444099ed53080f08e7dcf5956e43b29ba14c19952b10659d924abe10674e8298f3d04799537af8f8afab10d1a5832b3180ed31ec02c9b181a3918b5271017e58431f406aeae5fa5919ab68641b2a1f16de913da932a9335a369d74a6db865555af860ff3eaa1519a3fde69e3b0cfd8c59061929c627e98dd67b4bb3b0d6e4c3d71c8c347ea2b48fd031fec89b33a4397b2c5bb95c31d43eb5a1d3e04a747e373b10bbd988daa8bb4219365c68366cfeace24dac4500f9467b15bcbe6ef171d6fe073b2f2be0cde0ea7f85ab83ca2912acae619355178adbdffc9a20e88b76c8c828ed57a06ea18bf94135af6cb999b2fbda45312c8ae42e3b2adc18cab15306b36888f56cd1e57f871aba60548e2bdd8249dc9fede613eec2471831cc645bb7d45fe2433d50706c2e4c40cb3d4f3c24b3d2f8872568987b8e7d5246f6f41c38d3d9ee76d96846c129e858625d8ff7be03196620844745a3e555bc7364bad29adfd836f354d72dd315365edc34298ce248b8ef31140c3eebe38c9b42608d1c7e6bba68f64e669ecac9c4e34e8ebfb3ed97145da35e84bb10d4532d9ac6b31a941d24dd2249de34ac4da8c50d70ea5b394372cb3652f4a4c9a82b290523a7d621cc3024b2289baecfa3ff2fa624ad7c2914cad596b675acf0e76b74d4b829b8a71bf3e563d3f64890eae6de0430b9f4a9bdf3dca0a43bb912f6876863bdf793f9e3fa4190d607f717da21e67a3ff6a737d85cba12f8a12635238223f7ccc3cfcc2957dc7b6eb1244443370c4f932623231a30882ec7d5cf648cef61ceb737abcd8a7f4e7169e4c2b7389faa68faa486d624ad1b3be28b36c3fbb84eec3165d206b1db1338fe86b104eeba7b96477bdc400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000381094f35170312acd574ca38a21c294a729efb2810e32446a55272fc097078c0a7c343480f90c16609e7acb350a86d5142c4234c0d0d76bd09d94fa10d37f1daf3107c1d003816c91f167328d29bf474eae365c783f8b53a2017b6646ab19903eb6d685917e462d325c82a872e4861ac0ba07d743c68622be0410058bb62562464b5649baac4e999c28e2058d616bfb243a685a9ae4ec9a30093817a2a9d64f814a17b16522ef00507c212c53ea18b9cb59a5a6c30ce521b99bc73d7e81376928465e9d0c9170d14d024204deb5b9ae2616c67857669d936eb259ab819ccbab95b688a088564d84012050a7379d5276473600cd43918e34f5287cadecf3c0a6830682c09e45c5a9327ae031f17e1d5a59c2e455699c8a31a9c9607eef9c69c2adabe1aa5eb2feb23825e3318824eb7327107aa7c155044ec30932222b1af387f4729d85005c8a07963eb31920cd50af78f4bbc65c5871a5fd513aa74a604033a71420236de100080b64006c55b7387cd0a61e758bcb255780424010522602f599de13a78116006bfd3a5ac319f907b422c74f8d491780084658403b3d8554f9104e36ab845565b74b569b59ef91f6dcf914384222051117681214e092119404e2f46b9bc96b4058a511bcdf8e33d07db2dbec2c5eae321b21d49968e0b3e55080967ddcb3e784ef687659b9751ce0294fb41e99584e35112c7727671e1556592eebeee39c9c81eec4f38d499a34b4a033e575b7e4e7052192d74a6e9742c01d627b12d36b450b8e620175031b9d23280913624deb7e8d40362b4e54a2b0723ee03b55c02dbc08942a269b88e42193b59c6232845651705b561c155347c31dd75ac6c4db2c6a6224301d3a3f5d514a54224547e6adb0495268c0cf9a84697422a40dd9b3f03aa67e4f2e2d5659e8a0a72f86727695ae53470589615a00a3a523d6f3d1059d32b2f15c11bd0b849c4157f56c536f32ec4665aaa7d23a00662b6368e47bc651a2a565050ed1fdf373c834409952bb8de2d4987a8b3633e89540cecd02ef5cf00ffe5dd442e3e1821039ca4751558c893528ca4a4e0a202f66bb4ee7b5f683f0272b7e9a0dd683769f6a616c6ce4da4b5c1ee8ec86e644b94a6e31b6b56df02dd2aba44ad8d48bb9a2ea64177246e20611558f408916131b7fa233b7d424c4715b4f4da27b9657af046a5995a9d054b04bb4bee96363fe4cbd26b3b8250a2d92fa95e159204a32b3eb1ee7d9054da54648e5a4436e6e1bf6018a35dd86a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ce4d21a6bb3a2356805e678673c45fb055fc5266e3f692af9935aea307f14a5c41b979966a5dfe42ebfed1487e4822b74ab5af28995e085ec8007eca4977c63ee5299fec63dccbc42eeacab488e574249e9d856146750ad97c8a443485ec1c5820beb0964640010f6407140791e74684dbb91052e2d8bef7bdcd78b2ec03c97a53295d683bdbe32a70dc19a2f75b8613aea9616ae0e280179492820f73fb7fa4121e673fb5c328f41b67ff8ffa7aee6564adaba046d6e1d6aa13fb24965390f829246dfa8763851405075f76cf94c66ffc3308214df0960c649aaedc22926ce9357d3875f8b71d68d75999aa3663c30a9edf07228bf7dff49ec1e6c7a33d2053597003b82392e826ebd701b4c981aaac9951c79e08f592c2c0637c8e5a7f9dcda599e859c317d4888b4098992e0e2d979e41c703686d577e5ba6001ec4f587140711293d664963632f87ea0461e0e0c5e9d8d292fb409f9f9ab172ee17fc8afabad06e42b437ce22924eb5dbd3a80a06962f3b37946259f9c75a233cb2b4abdc5cd1b648faeb1be8630db40d151b8fba693df2c5bdcaa14dc4783f450b6bc407515ceebc5c9a47bd1a141384f0b596cab1135c075651cba989c190f3171dc1d72330edaa01656813c4b7811715060b023fc426745c301b2a91e0d08ed3bded438c4ce6799c35f3981c882a0bde4a2feeb1a52cafa47b0c48558fc43f98fe08f03a71128362bb6fb9da6a22249f4d4352ae7d3dae85de497e2411eadcfe5bf1a3c075c45811e0097ecea255fe15bd8321fe8b546a8cacfb899eecf5419db363c7567c2fe7360b36de14674f500a31d3eec71451a7c0d5576a8939c0f6d4d9f2f03f3c516ce25ce73abb35c73aa94f6aefae6ad87052d6b195fa43586817f5bb974aae7f1b8608922411aa5b0d7d574016cbd3ded13395623470a108fa0e1d3f9faa7e1e5031843f2a23dbce8b196315290dea5795e4115d53dc570a444064cfa3c9457dbf3ee323b1966ecd2270c32910f8f430522471258a1f1955a6e1dd8c84ed9a566499bf85628615351abe84b401421da2cfaf575e2644c9304c075ecfc374066cec713fa4c0d89043689fbc59ff54b8f97ee0a3b0989bc5e4ef83cc9833e75bc8b67bb5ee3c06ea156611cda95a6702416807530ea206ed89835d20805ea988b1958569cdf7f809996214dadab4e20bd44917e3410ec6beac98fea07f764e85b66aed5e17cf675d2ed8e63db728fe75158cb31779e31379648b43d68ccff3780854cf03535c57122019456e73cf06769bf1fbf558542241ce665bd10f921828553585e0cf664cdc6160f9c47fa5330591b74194f4716056ca83993efec4a52db9a1fbd3b2f504ac19667325167407375b6d7de739f07947b511c8d475744e5c29d6e286a37f1ff8317bd0178f0e306a38fa6e75f4a80427feb2c91235d3e7f20d8101cfc03bb73f44ef59af3526e9afc580027a1dade37654238b8ec7af0105248fe30784a88b72e11fc1bd807e47a349bd29075befbb29730ef8e85e3abd5105559bacee74aa27d90d360a8d629dbec95eb34c7f7ca20096ff7b521e40d3944a975436896f372eeab6b8615eb91697965bbf955779dd3047f7e3bf029e3509a5780247445d6223d085afb4291d976efadc41e42dc2c0728d18f6155654a332fec72eb6aef8b92c1d177e3dc28c31971bcaff76ddebfd9588bc244b116d409e58dc5ada1648663d603c47faeb814aaa7eb9b6264356f926c18b9357bf426b89ddc8eb9177eceb5c6cdc64dd8feb7b326bc1ba89bd9035235da0e644ef959c58dd97b88d5c749b36931ac2694c67151db0894652e99254222d37cefe9e27b3dd663a152dbe29a3639afe42f4578937076180563aad6ad739255ea012a17d2a56627d84c44fbab261d392a966cfe19278799cf1634d42384323c496190d4b9fb662694e3887ea66ab9e8b195488c8dca47c8bc0424247759137cfbf86dedc3641904cb6facbb30a9fa84acf69a67b4afdf4c2aa420fc0d90cefa0dfbbcd3072d9f772fd6058e2bf0e251be93b00dc43765b53db51b22f12d3ed0cc5655e4aebd9d923f99a43e4461dcf5992030e66a1cdc3a65558d9bb3a39788d92328387d144850dd3706fd7a079e3d2398f542f91a8aaabf0c5068dbaf1fcc5160398abecf74884beb04f3a3ea38bbb80d798f5981b3f2db6c7b33f867b7dc06a4417e30f94cdb4f523aeea0be12bd75aaed57520db0d4b4f013be3a1dc7ae5c58fd1de9637f7d82f697b7e92da427a78feec6a5c0255eb57a43dea6cebc8805bc04e04fe789e222b1e2642d26edc14fb36ecc6092b3060e45eed6c5b35de8741f72933930ecbd7338cf39474122357365700cb50c5eb176fb92814fa7f4032570ccee6b859236ad5da5f1730129edc7be218ba9874620f6f0ebc45e0bd622f8fd1ae6974994af95c6519ec1c46650c073d194fa6ebc62f405f63a3416782a47872c7d77d648d0a1c802ffdfde5fdc112c94cfc68f401889efc522fe488fdb5384c0d93147ab6587659d936f98ecfbcdcfbf8b352d605f18c855e2559743ed97991c5d50df44a7b929303835654a3955abc5bee6327400a7ccce460b318d8b5ece5b12f606adb3d7b5ed59563b8e675e78029aabc234442c2463256fe02b04f556da35c4615d14a9f4eff17db0db81de4bdd894f6628a120be2d4cf3e1f46d53817899657035a76137e23c0b0e8ddd29465d7f15628fd435e6caaca4194fdbf85fdcc31d5dafcb52568b7c0cfbe713bc85fa424ba3abe149e4035fc86807a8b876d2163b447cad5ec0e6ef38a1d591afb46267f9dbf142cab1cac1f73beba212992fc6d4647ec17848d1adbb1901277a5078dd72d9c9184e893c0806e9b4aff0a824670d438620f2a7e8d2965b619d291e5824c014fc888a36fbbe17356431f0039038f9b497902aed969f9c488390b7087763638e976801127baf1f53803c4dc9649f0ee85d67b239e2bdafb2bd75f1d1da22a56fb3af10a9dde7ad306c4af8681029316c0e1949228e6bf5adf942f1c0ef92b2bcbc0c70d49e5808851444240a78b14d21b54f66271482f49b85f5180b268050327368496cfa8b54ecb97ee6d28eb74a3742f68583da046809002c22f7b31fbc0566969f9a15cdca892c4beb101a2ac3526c76e9d30982c9b4893450fdec4001d2431828d24d8b1a67df80e2e10ed2ea8d723227055c48006665f7da8e032efdc70bc7eeb2b369b551fac542ad6df1a23107e2b3c0e3ccacc25f26404c085cbf56e52d35d7948db9fda6dfc24709994719d8ced41a2cc9b3c4b2bef0967cb71861cf0e6aea9bec9395726aa0e2f1a7247ed0f6038e3df4bf566786073590dcf97f8f0a99658d8f630a2d130c46cf4d26c669360d0f70b75f904c9f923ab285d5db129f6c25ad21f9e26ac844d07a8eed86c4e224ebfc5b3f720d6f94b0a01b1433c46b40cf84e80f7a6afa7bb8f9acf818ad3cab2ddd6904c067bea4f1fe79b83cb0aa8fc75b6b096bad6fe94abfd48f8efc0f2b9a02ebda8fdbdbe1c77f1854edba18aae7f31ced9cd34c1b355108df18a8953932f7554af05b203a96a9bb93e0eff51d7f93b56e351562cf85a2d35eae2c2427b89a8662a1c723d4f14e6eafdbd636c2bb7ade29c1a6bc8a463734c808bec68b1e9a31af6e29b412f1cb8c90a9911ac5c3ea71e46113d2d7b1ae2d8802b06a770fd0e9e4652895e42181ad09bb541e9493f258711bb7bedd3e7ca8b8ce875669cf80a6880eca3f13800de7011ea67f443e505c4fb455608ae586f922b3c83fd33b306bdedb86223c33e3aa65edc93cbcf3a03adaf9f328997951d59a9200c0ba2618e3596af176b43122cedc52b1e006ea6d12dc236a6fcd7cc46825f2ef7ed71683a731d746fff2fe54e0b392a8cbfa38873196bb2b835dca7cb7c3ed9a004c7a329b9734a111744bdacdb669e69e9df1e52f07c513e3752a0ccd81d7ddc4a64868b7bb2bbbd2095373480522be10615248a179dcb61dac90f7fa5fa9b84f190a9c62b5ff9cd473a940f03e7107157d7eb60af1e3e384ffe8a67dcb2389b3b0fab7c789cf100ca95cd6a85442cb9a2c243fb9d454b20bae5762d72b8fe79b4df81163d61de4578cf976992d8b9989fc68089f811f53db1e1092b60220552876b818bea981571898cd6ab7b5f13c46b0a076526e3241d65014f855efd7bde08ad91f259dcb64e94ec3dad97811eb024ee1d341521dc92ae5e93c73422088976f2d27d64e1d193b955e6736ad2bccf3c1a53d590576434acbc0b687f27f255fef354e68aca47160efa7126f908e08e4548c11546d9c412d685fa84d2eb4dcb2bdfc48e2fa8023548198ebb072a48044f4391143e3bef4ff9066a4b0d03adc826819d67588ba84f99da27424103652acc039ddd3b567851cd78e4117a8b93afe01fc8eebdaa1acb8ba9d095789e76b9d5ab9ee177a15d666ef171fe1d4bdccfe2e58ce669b561f63028c6ce26db5c8182fe048680b175c7ab407215ff3a7801c950d509867ab1b0bef89b3e38a387915225ede76f91aad15a85d8c46efd588bb3baacbc52c036211512473420f3f061f5f53e9353de0780425745a76439b3811511c86ca503251f24113384e1a24a9367536e796ce08b896f572489a2339e82a856c00000000000000000000000000000000000000000000000000000000&quot;,&quot;Expected&quot;:&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,&quot;Gas&quot;:1,&quot;Name&quot;:&quot;Vector 99&quot;,&quot;NoBenchmark&quot;:false}]
```
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7619/bench_vectors</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7619/bench_vectors</guid>
      </item>
    
      <item>
        <title>5 seconds benchmark results</title>
        <category>/</category>
        
        <description>## 5 seconds benchmark results

```
goos: linux
goarch: amd64
pkg: github.com/ethereum/go-ethereum/core/vm
cpu: Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz
BenchmarkPrecompiledEcrecover/-Gas=3000-12         	   61453	     91486 ns/op	      3000 gas/op	        32.79 mgas/s	     800 B/op	       7 allocs/op
BenchmarkPrecompiledFalcon512/Vector_0-Gas=2101-12 	  100734	     56717 ns/op	      2101 gas/op	        37.04 mgas/s	    2520 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_1-Gas=2106-12 	  101684	     56510 ns/op	      2106 gas/op	        37.26 mgas/s	    2520 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_2-Gas=2111-12 	  101174	     56683 ns/op	      2111 gas/op	        37.24 mgas/s	    2520 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_3-Gas=2116-12 	   99828	     57143 ns/op	      2116 gas/op	        37.02 mgas/s	    2520 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_4-Gas=2121-12 	  101956	     56744 ns/op	      2121 gas/op	        37.37 mgas/s	    2520 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_5-Gas=2126-12 	  102994	     58001 ns/op	      2126 gas/op	        36.65 mgas/s	    2520 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_6-Gas=2131-12 	  102300	     56824 ns/op	      2131 gas/op	        37.50 mgas/s	    2776 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_7-Gas=2136-12 	   99993	     57946 ns/op	      2136 gas/op	        36.86 mgas/s	    2776 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_8-Gas=2141-12 	   98952	     57536 ns/op	      2141 gas/op	        37.21 mgas/s	    2776 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_9-Gas=2146-12 	   97986	     58009 ns/op	      2146 gas/op	        36.99 mgas/s	    2776 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_10-Gas=2151-12         	   99571	     57636 ns/op	      2151 gas/op	        37.32 mgas/s	    2776 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_11-Gas=2156-12         	   98488	     58712 ns/op	      2156 gas/op	        36.72 mgas/s	    2776 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_12-Gas=2161-12         	   99486	     57854 ns/op	      2161 gas/op	        37.35 mgas/s	    2776 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_13-Gas=2166-12         	   99860	     58472 ns/op	      2166 gas/op	        37.04 mgas/s	    2776 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_14-Gas=2171-12         	  100924	     58179 ns/op	      2171 gas/op	        37.31 mgas/s	    3160 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_15-Gas=2176-12         	   96562	     59211 ns/op	      2176 gas/op	        36.74 mgas/s	    3160 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_16-Gas=2181-12         	   96573	     58758 ns/op	      2181 gas/op	        37.11 mgas/s	    3160 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_17-Gas=2186-12         	   95428	     58460 ns/op	      2186 gas/op	        37.39 mgas/s	    3160 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_18-Gas=2191-12         	   98922	     58564 ns/op	      2191 gas/op	        37.41 mgas/s	    3160 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_19-Gas=2196-12         	   98349	     58908 ns/op	      2196 gas/op	        37.27 mgas/s	    3160 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_20-Gas=2201-12         	   98071	     58697 ns/op	      2201 gas/op	        37.49 mgas/s	    3160 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_21-Gas=2206-12         	   99408	     59406 ns/op	      2206 gas/op	        37.13 mgas/s	    3160 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_22-Gas=2211-12         	   99640	     59059 ns/op	      2211 gas/op	        37.43 mgas/s	    3160 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_23-Gas=2216-12         	   99399	     59409 ns/op	      2216 gas/op	        37.29 mgas/s	    3160 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_24-Gas=2221-12         	   95290	     59013 ns/op	      2221 gas/op	        37.63 mgas/s	    3160 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_25-Gas=2226-12         	   99997	     59205 ns/op	      2226 gas/op	        37.59 mgas/s	    3160 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_26-Gas=2231-12         	   92920	     58687 ns/op	      2231 gas/op	        38.01 mgas/s	    3544 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_27-Gas=2236-12         	   97474	     59255 ns/op	      2236 gas/op	        37.73 mgas/s	    3544 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_28-Gas=2241-12         	   98890	     59309 ns/op	      2241 gas/op	        37.78 mgas/s	    3544 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_29-Gas=2246-12         	   97158	     59470 ns/op	      2246 gas/op	        37.76 mgas/s	    3544 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_30-Gas=2251-12         	   96217	     59625 ns/op	      2251 gas/op	        37.75 mgas/s	    3544 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_31-Gas=2256-12         	   91668	     62747 ns/op	      2256 gas/op	        35.95 mgas/s	    3544 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_32-Gas=2266-12         	   93902	     59204 ns/op	      2266 gas/op	        38.27 mgas/s	    3544 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_33-Gas=2271-12         	   97846	     59762 ns/op	      2271 gas/op	        38.00 mgas/s	    3544 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_34-Gas=2276-12         	   95500	     60260 ns/op	      2276 gas/op	        37.76 mgas/s	    3544 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_35-Gas=2281-12         	   92139	     61466 ns/op	      2281 gas/op	        37.10 mgas/s	    3544 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_36-Gas=2286-12         	   95546	     60238 ns/op	      2286 gas/op	        37.94 mgas/s	    3544 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_37-Gas=2291-12         	   94633	     60190 ns/op	      2291 gas/op	        38.06 mgas/s	    3672 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_38-Gas=2296-12         	   95407	     61661 ns/op	      2296 gas/op	        37.23 mgas/s	    3672 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_39-Gas=2301-12         	   93936	     61283 ns/op	      2301 gas/op	        37.54 mgas/s	    3672 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_40-Gas=2306-12         	   94119	     59677 ns/op	      2306 gas/op	        38.64 mgas/s	    3672 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_41-Gas=2311-12         	   92101	     61007 ns/op	      2311 gas/op	        37.88 mgas/s	    3928 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_42-Gas=2316-12         	   93086	     60859 ns/op	      2316 gas/op	        38.05 mgas/s	    3928 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_43-Gas=2321-12         	   93742	     61208 ns/op	      2321 gas/op	        37.91 mgas/s	    3928 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_44-Gas=2326-12         	   94639	     62377 ns/op	      2326 gas/op	        37.28 mgas/s	    3928 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_45-Gas=2331-12         	   92235	     61630 ns/op	      2331 gas/op	        37.82 mgas/s	    3928 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_46-Gas=2336-12         	   93420	     61803 ns/op	      2336 gas/op	        37.79 mgas/s	    3928 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_47-Gas=2341-12         	   92262	     61451 ns/op	      2341 gas/op	        38.09 mgas/s	    3928 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_48-Gas=2346-12         	   92217	     62103 ns/op	      2346 gas/op	        37.77 mgas/s	    3928 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_49-Gas=2351-12         	   92612	     61988 ns/op	      2351 gas/op	        37.92 mgas/s	    4568 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_50-Gas=2356-12         	   93085	     62125 ns/op	      2356 gas/op	        37.92 mgas/s	    4568 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_51-Gas=2361-12         	   91515	     62135 ns/op	      2361 gas/op	        37.99 mgas/s	    4568 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_52-Gas=2366-12         	   94096	     62662 ns/op	      2366 gas/op	        37.75 mgas/s	    4568 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_53-Gas=2371-12         	   93184	     66734 ns/op	      2371 gas/op	        35.52 mgas/s	    4568 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_54-Gas=2376-12         	   87160	     73950 ns/op	      2376 gas/op	        32.12 mgas/s	    4568 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_55-Gas=2381-12         	   71065	     70963 ns/op	      2381 gas/op	        33.55 mgas/s	    4568 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_56-Gas=2386-12         	   76144	     70699 ns/op	      2386 gas/op	        33.74 mgas/s	    4568 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_57-Gas=2391-12         	   76360	     75385 ns/op	      2391 gas/op	        31.71 mgas/s	    4568 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_58-Gas=2396-12         	   82645	     71328 ns/op	      2396 gas/op	        33.59 mgas/s	    4568 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_59-Gas=2401-12         	   72736	     71673 ns/op	      2401 gas/op	        33.49 mgas/s	    4568 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_60-Gas=2406-12         	   84778	     68452 ns/op	      2406 gas/op	        35.14 mgas/s	    4568 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_61-Gas=2411-12         	   91416	     63326 ns/op	      2411 gas/op	        38.07 mgas/s	    4568 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_62-Gas=2416-12         	   91442	     63048 ns/op	      2416 gas/op	        38.31 mgas/s	    4568 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_63-Gas=2421-12         	   90864	     63330 ns/op	      2421 gas/op	        38.22 mgas/s	    4568 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_64-Gas=2431-12         	   89984	     63484 ns/op	      2431 gas/op	        38.29 mgas/s	    4568 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_65-Gas=2436-12         	   91274	     66384 ns/op	      2436 gas/op	        36.69 mgas/s	    4568 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_66-Gas=2441-12         	   86680	     68861 ns/op	      2441 gas/op	        35.44 mgas/s	    4568 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_67-Gas=2446-12         	   82628	     74306 ns/op	      2446 gas/op	        32.91 mgas/s	    4568 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_68-Gas=2451-12         	   79260	     70996 ns/op	      2451 gas/op	        34.52 mgas/s	    5336 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_69-Gas=2456-12         	   76460	     75526 ns/op	      2456 gas/op	        32.51 mgas/s	    5336 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_70-Gas=2461-12         	   86166	     74883 ns/op	      2461 gas/op	        32.86 mgas/s	    5336 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_71-Gas=2466-12         	   83335	     70610 ns/op	      2466 gas/op	        34.92 mgas/s	    5336 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_72-Gas=2471-12         	   81807	     78670 ns/op	      2471 gas/op	        31.40 mgas/s	    5336 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_73-Gas=2476-12         	   80444	     82829 ns/op	      2476 gas/op	        29.89 mgas/s	    5336 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_74-Gas=2481-12         	   76786	     79519 ns/op	      2481 gas/op	        31.19 mgas/s	    5336 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_75-Gas=2486-12         	   81050	     70981 ns/op	      2486 gas/op	        35.02 mgas/s	    5336 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_76-Gas=2491-12         	   86422	     68954 ns/op	      2491 gas/op	        36.12 mgas/s	    5336 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_77-Gas=2496-12         	   83240	     66162 ns/op	      2496 gas/op	        37.72 mgas/s	    5336 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_78-Gas=2501-12         	   88854	     65845 ns/op	      2501 gas/op	        37.98 mgas/s	    5336 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_79-Gas=2506-12         	   89886	     72613 ns/op	      2506 gas/op	        34.51 mgas/s	    5336 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_80-Gas=2511-12         	   79981	     67357 ns/op	      2511 gas/op	        37.27 mgas/s	    5336 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_81-Gas=2516-12         	   87176	     66094 ns/op	      2516 gas/op	        38.06 mgas/s	    5336 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_82-Gas=2521-12         	   88449	     65996 ns/op	      2521 gas/op	        38.19 mgas/s	    5336 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_83-Gas=2526-12         	   88611	     66354 ns/op	      2526 gas/op	        38.06 mgas/s	    5336 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_84-Gas=2531-12         	   87794	     66999 ns/op	      2531 gas/op	        37.77 mgas/s	    5336 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_85-Gas=2536-12         	   86299	     67295 ns/op	      2536 gas/op	        37.68 mgas/s	    5336 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_86-Gas=2541-12         	   89646	     66234 ns/op	      2541 gas/op	        38.36 mgas/s	    5336 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_87-Gas=2546-12         	   89415	     72866 ns/op	      2546 gas/op	        34.94 mgas/s	    5336 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_88-Gas=2551-12         	   73672	     77453 ns/op	      2551 gas/op	        32.93 mgas/s	    5336 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_89-Gas=2556-12         	   74731	     71803 ns/op	      2556 gas/op	        35.59 mgas/s	    5336 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_90-Gas=2561-12         	   77031	     76380 ns/op	      2561 gas/op	        33.52 mgas/s	    5336 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_91-Gas=2566-12         	   75326	     71679 ns/op	      2566 gas/op	        35.79 mgas/s	    5336 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_92-Gas=2571-12         	   71496	     76141 ns/op	      2571 gas/op	        33.76 mgas/s	    5848 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_93-Gas=2576-12         	   76779	     69734 ns/op	      2576 gas/op	        36.93 mgas/s	    5848 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_94-Gas=2581-12         	   78199	     69682 ns/op	      2581 gas/op	        37.03 mgas/s	    5848 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_95-Gas=2586-12         	   77578	     69543 ns/op	      2586 gas/op	        37.18 mgas/s	    5848 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_96-Gas=2596-12         	   77648	     74972 ns/op	      2596 gas/op	        34.62 mgas/s	    5848 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_97-Gas=2601-12         	   75147	     76185 ns/op	      2601 gas/op	        34.14 mgas/s	    5848 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_98-Gas=2606-12         	   68714	     73209 ns/op	      2606 gas/op	        35.59 mgas/s	    5848 B/op	      11 allocs/op
BenchmarkPrecompiledFalcon512/Vector_99-Gas=2611-12         	   77630	     72218 ns/op	      2611 gas/op	        36.15 mgas/s	    5848 B/op	      11 allocs/op
```
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7619/benchmark_results</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7619/benchmark_results</guid>
      </item>
    
      <item>
        <title>Set of test vectors to perform benchmarking of EIP-7619</title>
        <category>/</category>
        
        <description># Set of test vectors to perform benchmarking of EIP-7619

## Inlined vectors

Here is the list of vectors to perform benchmarking.

```
[
    {
		Input:    &quot;de8f50a1&quot;,
		Expected: &quot;0000000000000000000000000000000000000000000000000000000000000001&quot;,
		Name:     &quot;vector 0: No data after method signature&quot;,
	},
	{
		Input:    &quot;de8f50a1abc&quot;,
		Expected: &quot;0000000000000000000000000000000000000000000000000000000000000001&quot;,
		Name:     &quot;vector 1: No enough data after method signature&quot;,
	},
	{
		Input:    &quot;de8f50a100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000e0&quot;,
		Expected: &quot;0000000000000000000000000000000000000000000000000000000000000001&quot;,
		Name:     &quot;vector 2: Signature offset is zero&quot;,
	},
	{
		Input:    &quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0&quot;,
		Expected: &quot;0000000000000000000000000000000000000000000000000000000000000001&quot;,
		Name:     &quot;vector 3: Public key offset is zero&quot;,
	},
	{
		Input:    &quot;de8f50a1000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000&quot;,
		Expected: &quot;0000000000000000000000000000000000000000000000000000000000000001&quot;,
		Name:     &quot;vector 4: data offset is zero&quot;,
	},

	{
		Input:    &quot;de8f50a1000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0&quot;,
		Expected: &quot;0000000000000000000000000000000000000000000000000000000000000001&quot;,
		Name:     &quot;vector 5: signature length not present in input&quot;,
	},
	{
		Input:    &quot;de8f50a1000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000000&quot;,
		Expected: &quot;0000000000000000000000000000000000000000000000000000000000000001&quot;,
		Name:     &quot;vector 6: signature length is present but its value is zero&quot;,
	},
	{
		Input:    &quot;de8f50a1000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000600000000&quot;,
		Expected: &quot;0000000000000000000000000000000000000000000000000000000000000001&quot;,
		Name:     &quot;vector 7: Signature indicated length is too long&quot;,
	},

	{
		Input:    &quot;de8f50a1000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000201111111111111111111111111111111111111111111111111111111111111111&quot;,
		Expected: &quot;0000000000000000000000000000000000000000000000000000000000000001&quot;,
		Name:     &quot;vector 8: public key length not present in input&quot;,
	},
	{
		Input:    &quot;de8f50a1000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000020111111111111111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000000&quot;,
		Expected: &quot;0000000000000000000000000000000000000000000000000000000000000001&quot;,
		Name:     &quot;vector 9: public key length is present but its value is zero&quot;,
	},
	{
		Input:    &quot;de8f50a1000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000020111111111111111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000800000000000000&quot;,
		Expected: &quot;0000000000000000000000000000000000000000000000000000000000000001&quot;,
		Name:     &quot;vector 10: Public Key indicated length is too long&quot;,
	},

	{
		Input:    &quot;de8f50a1000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000020111111111111111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000202222222222222222222222222222222222222222222222222222222222222222&quot;,
		Expected: &quot;0000000000000000000000000000000000000000000000000000000000000001&quot;,
		Name:     &quot;vector 11: data length not present in input&quot;,
	},
	{
		Input:    &quot;de8f50a1000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000201111111111111111111111111111111111111111111111111111111111111111000000000000000000000000000000000000000000000000000000000000002022222222222222222222222222222222222222222222222222222222222222220000000000000000000000000000000000000000000000000000000000000000&quot;,
		Expected: &quot;0000000000000000000000000000000000000000000000000000000000000001&quot;,
		Name:     &quot;vector 12: data length is present but its value is zero&quot;,
	},
	{
		Input:    &quot;de8f50a1000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000002011111111111111111111111111111111111111111111111111111111111111110000000000000000000000000000000000000000000000000000000000000020222222222222222222222222222222222222222222222222222222222222222200000000000000000000000000000000000000000000000050000000000000000&quot;,
		Expected: &quot;0000000000000000000000000000000000000000000000000000000000000001&quot;,
		Name:     &quot;vector 13: Data indicated length is too long&quot;,
	},
	{
		Input:    &quot;de8f50a10000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000031200000000000000000000000000000000000000000000000000000000000006b30000000000000000000000000000000000000000000000000000000000000292390191ef48486eb9d9a6823d8e6ff0d7f4df8bed13af7fa55a7e8dfa0d19725842a5451bcf4c061982d021c63a7d666c2024fe57033b1a1bda8c2179c518c94d434947eacc109efe792857ff6450cc853e8bb9d5d951b3ddb1397fadc2210762b479e386e660a68eb2ad034a58a3d0cce2370edf257ff4f81fe97c9bb10c1a96ee87d2414fdf4ea39f9f7c0604d1a3aebe5d73a6a1f7221a99eb2389b905da94766cd27a9a89f13d56b97cdd346689cfc5b3bdbbdc5102d3b5f93a2a95be40afcaac416d831391474c2298da0a359bc958a5f227de991a338944d6ebe4963f1a4ba5bb3d5c672526992329c84c5770c03a5e43504a28fa86f3b9bd72354c0b1921d1b568e5212856d8436f79a8c409e631082a4e28b7cb99d89c2a9ab3c196c56a77e6d05718196b316d8e9bedcfc214e2a33c02f0afd821dbfcb966c8bb8dde01c812a2045b6bc8de767f97b739dc8ed262f43dfc092e49f34c7728839895e4620620e4a193e94dbf2a9d439e249e6ec3377ed6734030acd43d138b982c36df814a4257f971a53aa5d92a7670915469013e68124edae3fc11b4ca470938ee2f218bc0e11468a6092f233de914790c972f77d95f968ac5f6e0968e0efa8d628825f3fbad2254e04e9ba34defc698b2e19e9629290f4e5682270595035b07404b091f5325293ed4021c619d7f0914ac47219b9e5df6fda5acbb398adb5c8540dc3390a548d82be42fac8f6ef9963546bcf278e63fdd49d0abbe62208e3956468771df4a50dd7a3aa197d81f58c14425ee166d29aef3eb2c171ff9b24f575e0ae9a65227d1e57ab6c5df11a369645dac717ab671a4c10aef72824134d0e68676bb138ca20eb5e08a0d1f90ee48af1cce1f21c72394ac427f382ced545183689cdb72cec8ea30c77389a16204356259e4b1142d000000000000000000000000000000000000000000000000000000000000038109b7107f987f937ea7566bca38e1578b8d0b59294e68bd208bfa90133101f5efd8755e9f1fd20564762585baa5a4f165ebec6df80ab5248a22bba940a7754abe5329b5c60345f395ad2a33ac106e65f14b91d0dca308ae4cc6db5fe69eee9fe4a392ff64f52865070eb5587e7f83ab6c187cc0584b3552920a3d4b50ab0a4a1e8d9dea3d4b5eb015a2f4ab59ae3d0ad2c081d8d2428a83806de7973ec65975ff8fd7287c642b6a83250255b61838cb4d68c52600b8c5330fce48aaeb806d4fb99a9add5e56577454a5a5ad5699711dd04854bf11484713dea5d9abd17f9214c33c4f4d47a6600bc241011f52e29d9820ac85ab70dfccb1d08c003b489c0826bf28ccee71945637b7161e6a99584451bf8351a43a0b0755ce3044f0840b7ad0489e6572c896666463e2cfc8ebe1258e3a963ab1433b173865705c15f044bcfde1b780d29e422604a9081d2349f6d6b40671b7c6ae77f44c16a22412e9e32cb116363d99ca4d2c3ace6730fd45fc6612d389edcd1c9b2201ba32a4705fac61005e184b89a4c90983acd7afee694ac9d904473eb512ec2d4875c1c954b791506f02c9e65f5d04976ea4e81d22d4884eb1c47eeb1a7ee109e12e61ce0ee4dfa88fdacb78ed61b0a327c2069d8cd33d184e68a60c22f6804faceca968cf5c1c276c7d16386f38bb82d5ea1e11d801f5ef33d3a3b0171dc870741ce8373c779ae8935211348c436285703681f1e6b0adc05c35c56196c246731ee2a4a998ef918a165023a76d324c58419cd9e76ebca0e13823d90b2ebc641717b404e2ee2937d48b38441e88f1086c15c95de8a48632bee5fb56f99f07ac31037323000317c291e2eace7865ece23548e804679241f1366748b1656cd58c28b86d5e08e269d0e3a668a834f4178a188dd63384042773fac10b3d96f533ecabe3a8a27e091d5846d6ead8ac9241437240ad4f7d274b78403402210ad042ddf73d59e02abf657aa41e101455df638d44c181e4ca219f2c6679088ff11af439115d8ef38f3614b957e1ebb9cc2e6bee0c0664da7ba3f1268404a5bac8ed45854881972382908861cc7f14f5d03b112273917854617590aad70eeedf398cb206ff5c7f7a9c5390dfa27e14b1148518833b3375cdfaf5a73680cdd7d0ea5f664672fe91ae6700032a3ee21aeb3ab7b6a0f66b0f65597a7fb6f5c1a9b1459d48885db3734abec9918c0f3a8135bbb2279984a054115e9c12a8f10ca25b93be8a3acfb94dc6a90d4da0e0a7ada80000000000000000000000000000000000000000000000000000000000000064486c8e99de7f81a3b0f4610bb555be687d67e079f5b03ee9d18c21d766fe3d2d36ea378a89294f839dc9bcd9a8251f92cfd39aacc1e228f44442e95b3c59ef904613ece9d312028b07a3cb26b3c9844dcdb2699299d7d47fd63f7889d6c5ce34626b583b&quot;,
		Expected: &quot;0000000000000000000000000000000000000000000000000000000000000001&quot;,
		Name:     &quot;vector 14: Correct format but invalid Signature&quot;,
	},
]
```
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7619/invalid_signature_test_vectors</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7619/invalid_signature_test_vectors</guid>
      </item>
    
      <item>
        <title></title>
        <category>/</category>
        
        <description>```plantuml
title EIP-7701 Complete Transaction Flow

actor &quot;User&quot;
skinparam participantFontColor automatic
participant &quot;Ethereum&quot; #darkgreen
participant &quot;AA_ENTRY_POINT&quot; #darkgreen
participant &quot;Deployer Contract&quot; as DC #darkslateblue
participant &quot;Sender Contract&quot; as SC #darkorchid
participant &quot;Paymaster Contract&quot; as PC #olivedrab
participant &quot;Target Contract&quot; as TC #darkred

&quot;User&quot; -&gt; &quot;Ethereum&quot;: Submit AA transaction
note right of &quot;Ethereum&quot;: execute\nAA transaction\nstate transition
&quot;Ethereum&quot; -&gt; &quot;AA_ENTRY_POINT&quot;: 
|||

group Validation Phase
|||
opt Sender Deployment
&quot;AA_ENTRY_POINT&quot;-&gt;DC: Deploy AA Transaction Sender\n&quot;&quot;deployerData&quot;&quot;
note over DC: &quot;&quot;ACCEPTROLE 0xA0&quot;&quot;
DC -&gt; SC: Deploy Sender Contract\n&quot;&quot;CREATE2&quot;&quot;
DC--&gt;&quot;AA_ENTRY_POINT&quot;:deployed: true
|||
end
|||
&quot;AA_ENTRY_POINT&quot;-&gt;SC: Validate AA Transaction\n&quot;&quot;senderValidationData&quot;&quot;
note over SC: &quot;&quot;ACCEPTROLE 0xA1&quot;&quot;
return valid: true
|||

opt Gas Abstraction
&quot;AA_ENTRY_POINT&quot;-&gt;PC: Validate AA Transaction\n&quot;&quot;paymasterData&quot;&quot;
note over PC: &quot;&quot;ACCEPTROLE 0xA2&quot;&quot;
return valid: true
|||
end
|||
end
group Execution Phase
|||
&quot;AA_ENTRY_POINT&quot;-&gt;SC: Execute AA Transaction\n&quot;&quot;senderExecutionData&quot;&quot;
note over SC: &quot;&quot;ACCEPTROLE 0xA3&quot;&quot;
|||
SC-&gt;TC: AA Transaction\nExecution Body
|||
opt PostOp 
&quot;AA_ENTRY_POINT&quot;-&gt;PC: Paymaster PostOp Call
note over PC: &quot;&quot;ACCEPTROLE 0xA4&quot;&quot;
|||
end
|||
end
```
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7701/complete_flow</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7701/complete_flow</guid>
      </item>
    
      <item>
        <title></title>
        <category>/</category>
        
        <description>```plantuml
title EIP-7701 Simple Transaction Flow

actor &quot;User&quot;
skinparam participantFontColor automatic
participant &quot;Ethereum&quot; #darkgreen
participant &quot;AA_ENTRY_POINT&quot; #darkgreen
participant &quot;Sender Contract&quot; #darkorchid
participant &quot;Target Contract&quot; #darkred

&quot;User&quot; -&gt; &quot;Ethereum&quot;: Submit AA transaction
note right of &quot;Ethereum&quot;: execute\nAA transaction\nstate transition
&quot;Ethereum&quot; -&gt; &quot;AA_ENTRY_POINT&quot;:
|||
group Validation Phase
|||
&quot;AA_ENTRY_POINT&quot;-&gt;&quot;Sender Contract&quot;: Validate AA Transaction\n&quot;&quot;senderValidationData&quot;&quot;
note over &quot;Sender Contract&quot;: &quot;&quot;ACCEPTROLE 0xA1&quot;&quot;
return valid: true
|||
end
|||
group Execution Phase
&quot;AA_ENTRY_POINT&quot;-&gt;&quot;Sender Contract&quot;: Execute AA Transaction\n&quot;&quot;senderExecutionData&quot;&quot;
note over &quot;Sender Contract&quot;: &quot;&quot;ACCEPTROLE 0xA3&quot;&quot;
|||
&quot;Sender Contract&quot;-&gt;&quot;Target Contract&quot;: AA Transaction\nExecution Body
|||
end
|||
```
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7701/simple_flow</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7701/simple_flow</guid>
      </item>
    
      <item>
        <title></title>
        <category>/</category>
        
        <description>```mermaid
flowchart LR
    redeemer([&quot;redeemer&quot;]) --&quot;redeemDelegations&quot;--&gt; Delegation_Manager([&quot;Delegation Manager&quot;])
    Delegation_Manager -.-&gt;|validate delegation w/ Action| Delegation_Manager
    Delegation_Manager --&quot;execute delegated action&quot;--&gt; Delegator([&quot;Delegator&quot;])
    Delegator --&quot;executes CALL using Action&quot;--&gt; Target([&quot;Target&quot;])
    classDef action stroke:#333,stroke-width:2px,stroke-dasharray: 5, 5;
    classDef entity fill:#af,stroke:#333,stroke-width:2px;
    class redeemer,Delegator,Delegation_Manager,Target entity;
```
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7710/mermaid</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7710/mermaid</guid>
      </item>
    
      <item>
        <title>ERC-7738 Script Registry Contracts, deployment and test harness scripts</title>
        <category>/</category>
        
        <description># ERC-7738 Script Registry Contracts, deployment and test harness scripts

This folder contains sample (and actual deployed) ERC-7738 registry contracts and tapp scripts

## Test suite

- Init hardhat in this directory
```bash
npm install --save-dev hardhat
```

- Run the test harness
```bash
npx hardhat test
```

# Test a script on the registry

## Deploy Example Token

Deploy a test token, let&apos;s use a simple ERC-721 with a custom mint function:

```Solidity
// SPDX-License-Identifier: MIT
// Compatible with OpenZeppelin Contracts ^5.0.0
pragma solidity ^0.8.20;

import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;
import &quot;@openzeppelin/contracts/access/Ownable.sol&quot;;

contract MyToken is ERC721, Ownable {
    uint256 private _tokenId;
    constructor()
        ERC721(&quot;MyToken&quot;, &quot;MTK&quot;)
        Ownable(msg.sender)
    {
        _tokenId = 1;
    }

    function mint() public {
        _safeMint(msg.sender, _tokenId);
        _tokenId++;
    }
}
```
Deploy this NFT using eg Remix and make a note of the contract address.

## Create Simple TokenScript, emulate and Deploy

First install the TokenScript CLI tool

1. Install the TokenScript build tool (see [TokenScript Quickstart](https://launchpad-doc.vercel.app/quick-start/tokenscript-cli/quick-start-tokenscript-cli))
```bash
npm install -g @tokenscript/cli
```

Here is a minimal example minting tokenscript object file: [Basic NFT TokenScript](/EIPs/assets/eip-7738/tokenscript/examples/tokenscript.xml). 

2. Copy or clone this code to a directory, ensure it is called tokenscript.xml.
3. Locate the following line in the TokenScript:
```xml
&lt;ts:address network=&quot;ChainId&quot;&gt;CONTRACT_ADDRESS&lt;/ts:address&gt;
```
Replace the ChainId and CONTRACT_ADDRESS with the contract you deployed in the previous step.
4. Use Emulation to test (in the same directory as you put the examples/tokenscript.xml file):
```bash
tokenscript emulate
```
This will let you test the TokenScript functionality before deploying on the registry. The generated page will allow you to mint new tokens.

5. Upload the TokenScript to an FTP or IPFS and make a note of the URL or IPFS hash.

## Add script to the registry

1. Open the registry page:
[Holesky Registry Page](https://viewer-staging.tokenscript.org/?chain=17000&amp;contract=0x0077380bCDb2717C9640e892B9d5Ee02Bb5e0682&amp;scriptId=7738_2)
[Sepolia Registry Page](https://viewer-staging.tokenscript.org/?chain=11155111&amp;contract=0x0077380bCDb2717C9640e892B9d5Ee02Bb5e0682&amp;scriptId=7738_1)
[Base Sepolia Registry Page](https://viewer-staging.tokenscript.org/?chain=84532&amp;contract=0x0077380bCDb2717C9640e892B9d5Ee02Bb5e0682&amp;scriptId=7738_2)

Click on the onboarding button &quot;Set ScriptURI&quot;. Set the contract address and scriptURI in the card.

2. Test onboarding. Switch wallets, go to the token page of your token (eg for Holesky):

`https://viewer-staging.tokenscript.org/?chain=17000&amp;contract=&lt;YOUR CONTRACT ADDRESS&gt;`

This will open the TokenScript for your deployed contract. Click on the Mint onboarding button to generate new Tokens.


## Deploy your own registry on a testnet
For this test we will use Holesky, but you can also use Sepolia, or any testnet on which the ENS contracts has been deployed.

Add some test eth on 2 wallets (0.1 -&gt; 0.5 depending on gas price on the testnet)
Create a .env file which contains the following three keys:
```
PRIVATE_KEY_DEPLOY = &quot;0x&lt;PRIVATE KEY 1&gt;&quot;
PRIVATE_KEY_2DEPLOY = &quot;0x&lt;PRIVATE KEY 2&gt;&quot;
PRIVATE_KEY_ENS = &quot;0x&lt;PRIVATE KEY ENS&gt;&quot;
```

Create an ENS domain on Holesky using the PRIVATE_KEY_ENS wallet. Obtain a `.eth` domain, not `.box` or any other. Go to the ENS app https://app.ens.domains/ and obtain a new ENS using your Holesky.
Using the app, unwrap the domain. Click on &quot;More&quot; then &quot;Unwrap&quot;.

Now, use the script to transfer ownership of the ENS to where the ENSAssigner contract will be written:

1. Add the ENS name to your .env file (don&apos;t add the .eth suffix).
```
ENS_NAME=&quot;&lt;YOUR ENS&gt;&quot;
```

eg, if the domain you picked was &quot;kilkennycat.eth&quot;:
```
ENS_NAME=&quot;kilkennycat&quot;
```

2. Run the script (note this script changes ownership of the domain to the ENSAssigner contract that will soon be deployed)

```bash
npx hardhat run ./scripts/changeENSOwner.ts --network holesky
```

Now, ensure the change ownership transaction is written (check the console log of first deployment), and run the deploy script:

```bash
npx hardhat run ./scripts/deploy.ts --network holesky
```

Congrats your registry is deployed. Now to issue a bootstrap script for the registry.

## Generate TokenScript and upload to IPFS

1. Open the `./tokenscript` folder in your favourite editor, and find the `tokenscript.xml` file.
2. Locate the Origin contract definition line: 
```xml
&lt;ts:contract interface=&quot;erc721&quot; name=&quot;RegistryContract&quot;&gt;
```
3. Edit the contract network and address on the line below this.
4. Build the TokenScript object file (use commandline from the ./)
```bash
tokenscript build
```
5. Upload the `tokenscript.tsml` file in the `./tokenscript/out` directory to IPFS, or your publicly accessible FTP.

## Set the TokenScript entry on the Script Registry

Set the tokenscript for your registry via a script entry on the registry contract itself, using the script itself. This is akin to &apos;bootstrapping&apos; your registry. You could just as easily accomplish this by using an `ethers.js` script or verifying the contract on `https://etherscan.io` and then using etherscan&apos;s write menu.

use the tokenscript CLI `emulate` feature:
```bash
tokenscript emulate
```
This will automatically open an emulator browser page. Connect your Ethereum wallet which is holding the key you used to deploy the registry contract.
Now use the &apos;Onboarding card&apos; which is defined in the TokenScript xml - click the `Set ScriptURI` button.

This will open the card defined in `./onboard.html`. This card invites you to set the contract address - which in this case is your registry contract - and the URI of the Tokenscript TSML you uploaded in step 5. (eg `ipfs://QmRaVBN4NBevk1j4HHfCLrMjjLrYNnsnJS2caJs9smYAtq`).

Once you click on the `Set Script URI` button your wallet will ask permission to call the `setScriptURI(address contractAddress, string[] uri)` function.

## Test your registry

1. switch to a new directory and clone the tokenscript viewer repo:
```bash
git clone https://github.com/SmartTokenLabs/tokenscript-engine.git
```
```bash
cd ./tokenscript-engine/javascript/tokenscript-viewer
```
2. update the registry contract address: open `javascript/engine-js/src/repo/sources/RegistryScriptURI.ts` and change `const REGISTRY_7738` to your deployed registry address.
3. Add your Infura API key to the .env (you will have to create the .env file):
```
INFURA_API_KEY=1234567890ABCDEF1234567890ABCDEF
```
4. Install dependencies and run
```bash
npm i
```
```bash
npm run start
```
4. On the opened webpage, open your deployed registry script:
`http://localhost:3333/?chain=17000&amp;contract=&lt;YOUR DEPLOYED REGISTRY CONTRACT ADDRESS&gt;`
5. Set the ScriptURI for the NFT contract you deployed in the first step, by clicking the &quot;Set ScriptURI&quot; button from your deployed tokenscript. Set the NFT contract address and URI path you uploaded to.
6. (Optional) Set a name and icon for the registry script, by clicking on the &apos;Set Name&apos; and &apos;Set Icon&apos; buttons on the token that is now displayed.
7. Use the script served from your new registry:
`http://localhost:3333/?chain=17000&amp;contract=&lt;YOUR NFT Contract address&gt;`</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7738/tests</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7738/tests</guid>
      </item>
    
      <item>
        <title>EIP-7745 log index proof format</title>
        <category>/</category>
        
        <description>## EIP-7745 log index proof format

A log index proof is a Merkle multiproof that fully or partially proves the contents of certain filter map rows and index entries. The proof format specified here can be used to prove the results of log queries, transaction and block hash lookups, and also to initialize the log index state. The root hash of any proof can be calculated and validated against the expected log index root regardless of its contents but the required contents (the proven subset of filter rows and index entries) depend on the use case. These use cases and their conditions for proof validity are detailed in separate documents.

The general format of a log index proof is defined as follows:

```
class LogIndexProof(Container):
    filter_rows: FilterRows
    index_entries: IndexEntries
    next_index: uint64
    proof_nodes: List[Bytes32]
```

The filter map and index entry data included in the proof uses a more compact encoding than the binary Merkle tree leaves but their contents can be translated into a known set of tree leaves. The `proof_nodes` list provides additional tree node contents required to calculate the log index root and validate it against the one found in the relevant block header.

Note that the position and order of the proof nodes is not specified in the proof but can be determined based on the set of known leaves. Also note that the `next_index` pointer of the log index is always supplied with the proof and its leaf node is always considered known.

### Filter map row encoding

The `FilterRows` container contains all filter map row data included in the proof. For storage efficiency two different encodings are used: a general purpose one that supports long rows and partial storage of row data, and a compact one capable of fully storing limited size filter rows belonging to the same row index in a continuous range of adjacent filter maps.

Note that the efficiency gain achieved by using the compact encoding wherever possible is very significant; with the current filter map parameters the global average of filter row lengths is 1 entry (3 bytes) and for these less populated rows it is a typical scenario that the proof encodes all rows of the same row index in an entire epoch (1024 maps). In a typical use case these rows might account for the major part of the log index proof data. EIP-7745 generally tries to achieve a reasonable balance between efficiency and complexity, and in this case optimizing the encoding of the most frequently occurring scenario with a relatively simple extra encoding format is justified.
```
class FilterRows(Container):
    short_rows: List[ShortRows]
    long_rows: List[FilterRow]
```

#### General row encoding

```
class FilterRow(Container):
    map_index: uint32
    row_index, row_length: uint16
    stored_row_data: List[StoredRowSection]

class StoredRowSection(Container):
    start_index: uint16
    row_data: ByteList
```

In the general case, each filter map row is encoded in its own container. The row length is always stored while the stored column indices are represented as a list of continuous sections, with `row_data` encoded in a compact form (3 bytes per list entry, little endian byte order).

Note that in the consensus tree format list entries are hashed as 4 byte _uint32_ values in 32 byte data chunks stored in _ProgressiveList_ tree leaves. Therefore each stored section has to start and end on a chunk boundary (units of 8 list entries), except for the last chunk which can be shorter. Since the row length does determine the number of _ProgressiveList_ tree levels, all leaves of all used tree levels (including the unused zero leaves at the end of the last tree level) are considered as known leaves. Also the `PROG_LIST_NEXT_TREE` branch of the last tree level is known to be a zero leaf. If all list entries are stored then all leaves of the _ProgressiveList_ container tree are considered as known and no extra proof nodes are added in that subtree.

#### Short row encoding

```
class ShortRows(Container):
    first_map_index: uint32 
    row_index: uint16
    row_lengths, row_data: ByteList
```

The `ShortRows` container fully encodes a continuous range of rows if none of them is longer than 255 entries. The length of each row is encoded in the `row_lengths` byte list, while the length of this list determines the number of adjacent map rows encoded. The `row_data` is encoded in compact form (3 bytes per list entry, little endian), with the entries of all encoded rows stored in a single byte list.

### Index entry encoding

```
class IndexEntries(Container):
    empty_entries: List[uint64]
    matching_logs: List[MatchingLogEntry]
    false_logs: List[FalsePositiveLogEntry]
    tx_entries: List[TxEntry]
    block_entries: List[BlockEntry]
```

#### Log entry (true match)

```
class MatchingLogEntry(Container):
    entry_index: uint64
    log: Log
    meta: LogMeta

class Log(Container):
    address: ExecutionAddress
    topics: List[Bytes32, 4]
    data: ProgressiveByteList

class LogMeta(Container):
    block_number: uint64
    transaction_hash: Root
    transaction_index: uint64
    log_in_tx_index: uint64
```

In this case the index entry is fully specified, all leaves of the index entry subtree are known, not proof nodes will be added in the index entry container subtree, only at the siblings of the Merkle path leading to the entry in the `index_entries` tree.

#### Log entry (false positive)

```
class FalsePositiveLogEntry(Container):
    entry_index: uint64
    address: ExecutionAddress
    topics: List[Bytes32, 4]
```

In this case only the `address` and `topics` are specified because they are supposed to prove that the potential match indicated by the filter maps is not really a match as the actual address and topics do not match the specified filter criteria. The root of the `data` byte list and the `meta` container are considered unknown and are added as proof nodes.

#### Transaction entry

```
class TransactionEntry(Container):
    entry_index: uint64
    meta: TransactionMeta

class TransactionMeta(Container):
    block_number: uint64
    transaction_hash: Root
    transaction_index: uint64
    receipt_hash: Root
```

In this case the `Log` container is not initialized and its root is considered to be known as a zero leaf, which distinguishes `TransactionEntry` from log entries.

#### Block entry

```
class BlockEntry(Container):
    entry_index: uint64
    meta: BlockMeta

class BlockMeta(Container):
    block_number: uint64
    block_hash: Root
    timestamp: uint64
```
Similarly to `TransactionEntry`, the `Log` container root is known zero. Note that the last unused (zero) leaf of `BlockMeta` is also considered known and ensures that a `BlockMeta` is always distinguishable from a `TransactionMeta` which has `receipt_hash` in the same position that cannot be zero.

### Proof nodes

Proof nodes are tree nodes that are not known and also have no known descendants. They are added to the `proof_nodes` list in the order of a depth-first (left to right) traversal of the log index tree and can also be processed in the same order during the recursive reconstruction of the log index root, as shown on the figure below:

```
        14  *15
          \ /
*4   5 6   7
  \ /   \ /
   2     3
    \   /
     \ /
      1

*: known nodes
proof nodes: [5, 6, 14]
```


</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7745/log_index_proof_format</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7745/log_index_proof_format</guid>
      </item>
    
      <item>
        <title>EIP-7745 wire protocol extension</title>
        <category>/</category>
        
        <description>## EIP-7745 wire protocol extension

This document specifies the extensions to the [Ethereum Wire Protocol](https://github.com/ethereum/devp2p/blob/master/caps/eth.md) required to initialize the log index.

### Proposed new messages

#### GetLogIndexProof (0x12)

`[request-id: P, referenceBlockHash: B_32, proofType: P, proofSubset: P]`

Require peer to return a __LogIndexProof__ message containing a log index proof that proves the specified subset of the specified type of initialization data from the log index tree belonging to the specified _reference block_.

Note that all clients are expected to be able to serve log index proofs using either the current finalized block or the previous one as _reference block_. Also note that the initialization data served by this protocol are split into a limited number of pre-defined subsets so that proofs can be pre-generated for each potential _reference block_. This, together with the limited size of each individual response, makes it easy to ensure that serving this data will not be an excessive burden on the clients.

#### LogIndexProof (0x13)

`[request-id: P, log_index_proof]`

This is the response to __GetLogIndexProof__, providing the RLP encoded log index proof of the requested partial initialization data. See the [log index proof format](/EIPs/assets/eip-7745/log_index_proof_format) specification.

### Allowed proof types

#### EpochBoundaryProof (proofType = 0x01)

This proof allows the client to initialize log index rendering at epoch boundaries. It does not prove any filter row data, only index entries, typically of __BlockEntry__ type. Epoch boundary `i` is defined as the boundary between epochs `i` and `i+1` and allows the client to start rendering the index from epoch `i+1`. Epoch boundaries `0 &lt;= i &lt; epoch_count` can be proven, where `epoch_count = next_index // (MAPS_PER_EPOCH * VALUES_PER_MAP)` is the number of completed epochs. Note that every proof proves `next_index` and thereby also `epoch_count`. 

The range of proven boundaries is determined by the `proofSubset` parameter; boundaries `proofSubset * 128` to `min((proofSubset+1) * 128, epoch_count) - 1` are proven by the returned log index proof. Except for some corner cases listed below, each boundary `i` is proven by two adjacent __BlockEntry__ entries: the last one whose `map_entry_index &lt; i * MAPS_PER_EPOCH * VALUES_PER_MAP` and the first one whose `map_entry_index &gt;= i * MAPS_PER_EPOCH * VALUES_PER_MAP`. This proves the `map_entry_index` position of the last block boundary in the previous epoch, which allows the client to start processing the next block, skip the appropriate number of _map values_ and _index entries_ until the epoch boundary, then start rendering the next epoch.

Note that rendering from an epoch boundary is one option to initialize the log index and also makes it possible to generate the index for older epochs later.

##### Corner cases

The typical scenario described above assumes that there is at least one __BlockEntry__ both before and after the boundary. This assumption can be false in three valid corner cases:

- there is no __BlockEntry__ before the boundary and the block number of the one after the boundary is `firstIndexedBlock`. In this case rendering should start from the first epoch.
- there is no __BlockEntry__ after the boundary and the block number of the one before the boundary is `referenceBlock - 1`. In this case rendering from the boundary is possible.
- there are no __BlockEntry__ entries anywhere in the index and `firstIndexedBlock == referenceBlock`. In this case rendering should start from the first epoch.

In any other case the proof should be considered invalid.

Note that rendering an epoch as a part of a log index Merkle tree requires the sibling of the rendered epoch&apos;s root node to be known. This is automatically true if a `BlockEntry` in the rendered epoch (the one after the boundary) is proven. Otherwise it is not always guaranteed, therefore if there is no __BlockEntry__ in the next epoch after a proven boundary then the first index entry of that epoch should be proven, either as an __empty entry__, a __FalsePositiveLogEntry__ or a __TxEntry__. 

#### CurrentMapProof (proofType = 0x02)

This proof allows the client to initialize log index rendering at the _reference block_. It proves all rows of the current filter map and the index entry at `next_index`. This dataset is split into a fixed number of subsets (`0 &lt;= proofSubset &lt;= 63`). The proven map index is calculated as `mapIndex = next_index // VALUES_PER_MAP`.

Each proof proves 1024 rows between row index `proofSubset * 1024` and `proofSubset * 1024 + 1023`. Additionally, if `proofSubset == 0` then the index entry at `next_index` is also proven as an __empty entry__. This type of proof always uses the general row encoding format and the __FilterRow__ container type (`long_rows` is 1024 items long and `short_rows` is empty). Note that short row encoding has significant benefits when encoding a long section of rows of adjacent maps which is not the case here; in this case the majority of proof data is the sibling proof nodes of the Merkle path leading to each individual row of the same map index.
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7745/wire_protocol_extension</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7745/wire_protocol_extension</guid>
      </item>
    
      <item>
        <title>EIP-7825 Empirical Report</title>
        <category>/</category>
        
        <description># EIP-7825 Empirical Report

*The following represents a summary with empirical findings from analyzing a `2**24` transaction gas limit cap.*
*Date: July, 2025*

## Dataset
- **Period**: 6 months of Ethereum mainnet data (Q1 25)
- **Blocks analyzed**: 1,296,000
- **Total transactions**: 251,922,669

## Impact Metrics

### Transaction Impact

| Metric | Value |
|--------|-------|
| Affected transactions | 96,564 |
| Impact rate | 0.0383% |
| Unique affected addresses | 4,601 |
| Avg transactions per affected address | 21.0 |

### Gas Analysis (of Affected)

| Metric | Value |
|--------|-------|
| Average gas limit (affected txs) | 24,734,127 |
| Average gas used | 17,668,721 |
| Gas efficiency | 71.4% |
| Min gas used | 21,000 |
| Max gas used | 35,888,566 |
| Transactions with unnecessary high limits | 18,490 (19.15%) |

### Economic Impact

| Metric | Value |
|--------|-------|
| Total additional gas cost | 2,095,905,000 gas units |
| Avg additional gas per address | 455,532 gas units |
| Avg additional gas per transaction | 21,705 gas units |
| Avg cost per address | 0.0004873 ETH |

## Distribution Analysis

### Concentration

| Metric | Value |
|--------|-------|
| Gini coefficient | 0.870 |
| Top 10% addresses impact | 79.7% of affected transactions |
| Top 50 addresses impact | 37.6% of affected transactions |
| Addresses with 1 transaction | 1,848 (40.2%) |
| Addresses with &gt;100 transactions | 197 (4.3%) |

## Cumulative Distribution Function

### Sample
- **Total transactions analyzed**: 244,628,466
- **Blocks**: 1,317,600 (183 days)

### Distribution

| Gas Limit | Cumulative % | Transaction Count |
|-----------|--------------|-------------------|
| ≤21,000 | 26.02% | 63,660,952 |
| ≤50,000 | 36.85% | 90,137,805 |
| ≤100,000 | 60.31% | 147,541,155 |
| ≤200,000 | 69.50% | 170,005,321 |
| ≤500,000 | 92.81% | 227,033,454 |
| ≤1,000,000 | 96.65% | 236,444,479 |
| ≤2,000,000 | 98.39% | 240,708,106 |
| ≤5,000,000 | 99.29% | 242,903,913 |
| ≤10,000,000 | 99.76% | 243,975,982 |
| ≤16,777,216 | 99.96% | 244,535,902 |
| &gt;16,777,216 | 0.04% | 92,564 |

## Address Analysis

### Top 10 From Addresses

| Rank | Address | Transactions | Avg Gas Limit | Max Gas Limit |
|------|---------|--------------|---------------|---------------|
| 1 | 0x22dcb...e1 | 2,555 | 19,940,819 | 20,025,269 |
| 2 | 0xc87a8...85 | 2,205 | 22,766,999 | 30,000,000 |
| 3 | 0x78ec5...fe | 1,712 | 25,950,213 | 36,000,000 |
| 4 | 0x2a8b4...1c | 1,559 | 34,411,392 | 35,947,097 |
| 5 | 0xcde69...ff | 1,543 | 23,456,520 | 32,400,000 |
| 6 | 0x61fbb...6f | 1,345 | 19,439,482 | 32,400,000 |
| 7 | 0x4abf0...32 | 1,287 | 20,403,859 | 25,267,151 |
| 8 | 0xd6aaa...77 | 1,189 | 24,467,657 | 25,416,303 |
| 9 | 0x7340d...78 | 1,100 | 20,093,929 | 20,094,357 |
| 10 | 0xb5b3f...d9 | 1,089 | 19,461,632 | 34,508,005 |

### Top 10 To Addresses

| Rank | Address | Transactions | % of Total |
|------|---------|--------------|------------|
| 1 | 0x06450...f6 | 9,443 | 9.8% |
| 2 | 0x00000...0b | 6,645 | 6.9% |
| 3 | 0x3c7cb...97 | 3,017 | 3.1% |
| 4 | 0xca2b1...44 | 2,907 | 3.0% |
| 5 | 0x0a252...59 | 2,817 | 2.9% |
| 6 | 0x5b12a...d9 | 2,728 | 2.8% |
| 7 | 0xd6da1...29 | 2,651 | 2.7% |
| 8 | 0x00000...00 | 2,607 | 2.7% |
| 9 | 0xb0cd7...a3 | 2,413 | 2.5% |
| 10 | 0x22e4a...ad | 2,369 | 2.5% |

### Concentration Ratios

| Metric | Value |
|--------|-------|
| Unique from addresses | 4,601 |
| Unique to addresses | 3,834 |
| Concentration ratio | 0.83 |
| Top 10 to addresses share | 38.8% |
| Top 50 to addresses share | 71.5% |
| Top 100 to addresses share | 82.0% |

## Migration Analysis

### Transaction Splitting Requirements

| Splits Required | Address Count | Percentage |
|-----------------|---------------|------------|
| 2 | 4,502 | 97.8% |
| 3 | 99 | 2.2% |

### Gas Cost Distribution

| Percentile | Additional Gas per Transaction | ETH Cost (Historical) |
|------------|-------------------------------|----------------------|
| Min | 21,000 | 0.00000636 |
| 25th | 21,000 | 0.00000843 |
| 50th | 21,000 | 0.00000966 |
| 75th | 21,000 | 0.00001175 |
| 95th | 42,000 | 0.00002306 |
| Max | 84,000 | 0.00003670 |

## Summary Statistics

### 6-Month Period
- **Affected transactions**: 96,564 (0.0383%)
- **Affected addresses**: 4,601
- **Total ETH impact**: 2.2419 ETH
- **Average splits required**: 2.02

### CDF Analysis (183 days)
- **Transactions ≤16,777,216 gas**: 99.96%
- **Transactions &gt;16,777,216 gas**: 0.04%
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7825/analysis</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7825/analysis</guid>
      </item>
    
      <item>
        <title>EIP-7883 ModExp Analysis Report</title>
        <category>/</category>
        
        <description># EIP-7883 ModExp Analysis Report

*Generated on 2025-07-21 13:34:56*

## Executive Summary

This report provides an analysis of EIP-7883&apos;s impact on ModExp operations based on 304,301 historical Ethereum mainnet calls using the pricing formula from the latest EIP-7883 specification.

### Key Metrics

**Overall Impact:**
- **Total ModExp calls analyzed**: 304,301
- **Unique transactions**: 75,134
- **Calls with cost increases**: 304301 (100.0%)
- **Total additional gas required**: 542947771 gas
- **Average cost increase**: 1,784.25 gas per call
- **Maximum single call increase**: 64027 gas

**Economic Impact:**
- **Network congestion**: Average 0.006% of block gas limit
- **Cost predictability**: 100% of calls affected with 2.81x average increase

## Updated Pricing Formula

The EIP-7883 specification introduces three key changes:

1. **Minimum gas cost**: Increased from 200 to 500
2. **General multiplier**: Removed division by 3 (effectively 3x increase)
3. **Large exponent multiplier**: Doubled from 8 to 16 for exponents &gt; 32 bytes
4. **Base multiplication complexity**: Minimum of 16, doubles for sizes &gt; 32 bytes

## Parameter Analysis

### Input Size Distributions

**Statistical Summary:**

| Parameter | Min | Max | Mean | Median | Std Dev |
|-----------|-----|-----|------|--------|---------|
| Bsize | 32 | 385 | 32.0 | 32.0 | 2.7 |
| Esize | 1 | 32 | 32.0 | 32.0 | 0.4 |
| Msize | 32 | 384 | 32.0 | 32.0 | 2.7 |

**Common Size Combinations:**

| Base Size | Exponent Size | Modulus Size | Count | Percentage |
|-----------|---------------|--------------|-------|------------|
| 32 | 32 | 32 | 304,225 | 100.0% |
| 256 | 3 | 256 | 31 | 0.0% |
| 128 | 1 | 128 | 27 | 0.0% |
| 128 | 32 | 128 | 10 | 0.0% |
| 128 | 3 | 128 | 6 | 0.0% |
| 385 | 3 | 384 | 2 | 0.0% |

### Exponent Analysis

**Fermat Prime Usage**: 1,351 calls (0.4%)

**Most Common Exponent Values:**

| Rank | Exponent | Count | Percentage |
|------|----------|-------|------------|
| 1 | 0x30644e72... | 66,115 | 21.73% |
| 2 | 0xffffffff... | 54,656 | 17.96% |
| 3 | 0x1000000 | 50,599 | 16.63% |
| 4 | 0xffffff | 43,887 | 14.42% |
| 5 | 0xffffffff... | 28,955 | 9.52% |
| 6 | 0xc19139cb... | 20,644 | 6.78% |
| 7 | 0x3fffffff... | 15,463 | 5.08% |
| 8 | 0x1000002 | 6,703 | 2.20% |
| 9 | 0xa59c34 | 6,352 | 2.09% |
| 10 | 0x2000000 | 1,699 | 0.56% |

## Gas Cost Analysis

### Cost Distribution

| Cost Increase Range | Call Count | Percentage |
|-------------------|------------|------------|
| &lt;500 gas | 116,974 | 38.4% |
| 500-1K gas | 0 | 0.0% |
| 1K-5K gas | 187,278 | 61.5% |
| 5K-10K gas | 16 | 0.0% |
| 10K-50K gas | 31 | 0.0% |
| &gt;50K gas | 2 | 0.0% |

### Cost Increase Percentiles

| Percentile | Gas Increase |
|------------|--------------|
| 10th | 300 |
| 25th | 300 |
| 50th | 2,699 |
| 75th | 2,720 |
| 90th | 2,720 |
| 95th | 2,720 |
| 99th | 2,720 |

## Entity Analysis

### Most Impacted Senders

| Rank | Address | Total Increase (gas) | Avg Increase | Call Count | Current Cost | New Cost |
|------|---------|---------------------|--------------|------------|--------------|----------|
| 1 | [0x00000062...](https://etherscan.io/address/0x000000629fbcf27a347d1aeba658435230d74a5f) | 14,062,311 | 1,499.50 | 9,378 | 7,263,261 | 21,325,572 |
| 2 | [0x7202932b...](https://etherscan.io/address/0x7202932b3be70edf0657d5bada261d610e0d7db9) | 8,315,040 | 2,720 | 3,057 | 4,157,520 | 12,472,560 |
| 3 | [0xaaf7b278...](https://etherscan.io/address/0xaaf7b278bac078aa4f9bdc8e0a93cde604aa67d9) | 7,219,891 | 902.37 | 8,001 | 3,908,541 | 11,128,432 |
| 4 | [0x454ef2f6...](https://etherscan.io/address/0x454ef2f69f91527856e06659f92a66f464c1ca4e) | 7,190,430 | 2,678 | 2,685 | 3,592,530 | 10,782,960 |
| 5 | [0x54ab716d...](https://etherscan.io/address/0x54ab716d465be3d5eeca64e63ac0048d7a81659a) | 6,794,898 | 913.29 | 7,440 | 3,673,398 | 10,468,296 |
| 6 | [0xfcb73f64...](https://etherscan.io/address/0xfcb73f6405f6b9be91013d9477d81833a69c9c0d) | 6,216,927 | 1,499.50 | 4,146 | 3,211,077 | 9,428,004 |
| 7 | [0xf3b07f67...](https://etherscan.io/address/0xf3b07f6744e06cd5074b7d15ed2c33760837ce1f) | 3,045,348 | 912.33 | 3,338 | 1,646,548 | 4,691,896 |
| 8 | [0x4337001f...](https://etherscan.io/address/0x4337001fff419768e088ce247456c1b892888084) | 2,777,120 | 2,720 | 1,021 | 1,388,560 | 4,165,680 |
| 9 | [0x4337003f...](https://etherscan.io/address/0x4337003fcd2f56de3977ccb806383e9161628d0e) | 2,717,280 | 2,720 | 999 | 1,358,640 | 4,075,920 |
| 10 | [0x4337002c...](https://etherscan.io/address/0x4337002c5702ce424cb62a56ca038e31e1d4a93d) | 2,652,000 | 2,720 | 975 | 1,326,000 | 3,978,000 |
| 11 | [0x4337005d...](https://etherscan.io/address/0x4337005db25dbad41da5692ba1188751ee5d98b6) | 2,589,440 | 2,720 | 952 | 1,294,720 | 3,884,160 |
| 12 | [0x4337004e...](https://etherscan.io/address/0x4337004ec9c1417f1c7a26ebd4b4fbed6acf9e5d) | 2,586,720 | 2,720 | 951 | 1,293,360 | 3,880,080 |
| 13 | [0x58d14960...](https://etherscan.io/address/0x58d14960e0a2be353edde61ad719196a2b816522) | 1,476,481 | 939.84 | 1,571 | 795,631 | 2,272,112 |
| 14 | [0x6f9d816c...](https://etherscan.io/address/0x6f9d816c4ec365fe8fc6898c785be0e2d51bec2c) | 1,416,975 | 2,699 | 525 | 708,225 | 2,125,200 |
| 15 | [0xc2adcfcc...](https://etherscan.io/address/0xc2adcfccee33a417064d1a45d3b202de6d9fa474) | 1,232,589 | 1,499.50 | 822 | 636,639 | 1,869,228 |

### Most Impacted Contracts

| Rank | Contract | Total Increase (gas) | Avg per Call | Calls | Unique Users | Current Cost | New Cost |
|------|----------|---------------------|--------------|-------|--------------|--------------|----------|
| 1 | [0x5ff137d4...](https://etherscan.io/address/0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789) | 30,654,400 | 2,720 | 11,270 | 73 | 15,327,200 | 45,981,600 |
| 2 | [0x68d30f47...](https://etherscan.io/address/0x68d30f47f19c07bccef4ac7fae2dc12fca3e0dc9) | 14,062,311 | 1,499.50 | 9,378 | 1 | 7,263,261 | 21,325,572 |
| 3 | [0x8c0bfc04...](https://etherscan.io/address/0x8c0bfc04ada21fd496c55b8c50331f904306f564) | 13,028,282 | 951.25 | 13,696 | 17 | 7,011,182 | 20,039,464 |
| 4 | [0x5d8ba173...](https://etherscan.io/address/0x5d8ba173dc6c3c90c8f7c04c9288bef5fdbad06e) | 9,141,460 | 899.75 | 10,160 | 9 | 4,950,460 | 14,091,920 |
| 5 | [0x870679e1...](https://etherscan.io/address/0x870679e138bcdf293b7ff14dd44b70fc97e12fc0) | 7,190,430 | 2,678 | 2,685 | 1 | 3,592,530 | 10,782,960 |
| 6 | [0x3b4d794a...](https://etherscan.io/address/0x3b4d794a66304f130a4db8f2551b0070dfcf5ca7) | 6,216,927 | 1,499.50 | 4,146 | 1 | 3,211,077 | 9,428,004 |
| 7 | [0xa13baf47...](https://etherscan.io/address/0xa13baf47339d63b743e7da8741db5456dac1e556) | 1,416,975 | 2,699 | 525 | 1 | 708,225 | 2,125,200 |
| 8 | [0xd7f86b4b...](https://etherscan.io/address/0xd7f86b4b8cae7d942340ff628f82735b7a20893a) | 1,260,433 | 2,699 | 467 | 3 | 629,983 | 1,890,416 |
| 9 | [0x02993cdc...](https://etherscan.io/address/0x02993cdc11213985b9b13224f3af289f03bf298d) | 1,232,589 | 1,499.50 | 822 | 1 | 636,639 | 1,869,228 |
| 10 | [0xece9cf6a...](https://etherscan.io/address/0xece9cf6a8f2768a3b8b65060925b646afeaa5167) | 1,130,574 | 1,752.83 | 645 | 1 | 577,746 | 1,708,320 |
| 11 | [0x7cf3876f...](https://etherscan.io/address/0x7cf3876f681dbb6eda8f6ffc45d66b996df08fae) | 1,124,625 | 1,499.50 | 750 | 1 | 580,875 | 1,705,500 |
| 12 | [0x150fe8db...](https://etherscan.io/address/0x150fe8dbb943c372f3e8c31d9c89f1e6a13cbbfd) | 792,688 | 2,678 | 296 | 1 | 396,048 | 1,188,736 |
| 13 | [0x00000000...](https://etherscan.io/address/0x0000000071727de22e5e9d8baf0edac6f37da032) | 685,440 | 2,720 | 252 | 7 | 342,720 | 1,028,160 |
| 14 | [0xd19d4b5d...](https://etherscan.io/address/0xd19d4b5d358258f05d7b411e21a1460d11b0876f) | 575,808 | 1,499.50 | 384 | 1 | 297,408 | 873,216 |
| 15 | [0x92ef6af4...](https://etherscan.io/address/0x92ef6af472b39f1b363da45e35530c24619245a4) | 477,723 | 2,699 | 177 | 1 | 238,773 | 716,496 |

## Key Findings and Recommendations

### Impact Summary

1. **Universal Impact**: 100% of ModExp calls will see cost increases under the updated EIP-7883
2. **Significant Increases**: Average 2.8x cost increase across all operations
3. **Predictable Changes**: Cost increases follow clear patterns based on input sizes

### Recommendations by Stakeholder

**For Affected Users:**
- Review and update gas limits for all ModExp operations
- Budget for an average 1,784.25 gas increase per call
- Consider optimizing input sizes where possible

**For Infrastructure Providers:**
- Update gas estimation algorithms immediately
- Prepare for universal cost increases across all ModExp calls

---

*Report generated from historical Ethereum mainnet data. All gas calculations verified against the latest EIP-7883 specification.*
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7883/call_analysis</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7883/call_analysis</guid>
      </item>
    
      <item>
        <title>EIP-7883 Entity Impact Analysis</title>
        <category>/</category>
        
        <description># EIP-7883 Entity Impact Analysis

*Generated on 2025-07-21 13:36:39*

## Executive Summary

This report provides entity-level analysis of EIP-7883&apos;s impact using the updated pricing formula, focusing on the most affected addresses and their usage patterns.

### Key Statistics

- **Total unique senders analyzed**: 143
- **Senders with cost increases**: 143 (100%)
- **Total unique contracts**: 42
- **Contracts with increased costs**: 42 (100%)

### Entity Categories

| Category | Entity Count | Total Gas Increase | Total Calls | Avg Increase per Entity |
|----------|--------------|-------------------|-------------|-------------------------|
| Frequent User - High Impact | 8 | 31070669 | 18035 | 3.88M |
| Heavy User - High Impact | 3 | 28077100 | 24819 | 9.36M |
| Occasional User - High Impact | 42 | 7468316 | 2779 | 177.8K |
| Occasional User - Medium Impact | 24 | 1040342 | 490 | 43.3K |
| Rare User - Low Impact | 30 | 139499 | 71 | 4.6K |
| Rare User - Medium Impact | 9 | 346226 | 58 | 38.5K |
| Regular User - High Impact | 27 | 22169730 | 10067 | 821.1K |

## Top 50 Most Affected Entities

### By Total Gas Increase

| Rank | Address | Category | Total Increase | Avg per Call | Total Calls | Unique Contracts | % Increase | Current Cost | New Cost |
|------|---------|----------|----------------|--------------|-------------|------------------|------------|--------------|----------|
| 1 | [0x00000062...](https://etherscan.io/address/0x000000629fbcf27a347d1aeba658435230d74a5f) | Heavy User - High Impact | 14.06M | 1.5K | 9.4K | 1 | 193.6% | 7.26M | 21.33M |
| 2 | [0x7202932b...](https://etherscan.io/address/0x7202932b3be70edf0657d5bada261d610e0d7db9) | Frequent User - High Impact | 8.32M | 2.7K | 3.1K | 1 | 200.0% | 4.16M | 12.47M |
| 3 | [0xaaf7b278...](https://etherscan.io/address/0xaaf7b278bac078aa4f9bdc8e0a93cde604aa67d9) | Heavy User - High Impact | 7.22M | 902.37 | 8.0K | 2 | 184.7% | 3.91M | 11.13M |
| 4 | [0x454ef2f6...](https://etherscan.io/address/0x454ef2f69f91527856e06659f92a66f464c1ca4e) | Frequent User - High Impact | 7.19M | 2.7K | 2.7K | 1 | 200.1% | 3.59M | 10.78M |
| 5 | [0x54ab716d...](https://etherscan.io/address/0x54ab716d465be3d5eeca64e63ac0048d7a81659a) | Heavy User - High Impact | 6.79M | 913.29 | 7.4K | 2 | 185.0% | 3.67M | 10.47M |
| 6 | [0xfcb73f64...](https://etherscan.io/address/0xfcb73f6405f6b9be91013d9477d81833a69c9c0d) | Frequent User - High Impact | 6.22M | 1.5K | 4.1K | 1 | 193.6% | 3.21M | 9.43M |
| 7 | [0xf3b07f67...](https://etherscan.io/address/0xf3b07f6744e06cd5074b7d15ed2c33760837ce1f) | Frequent User - High Impact | 3.05M | 912.33 | 3.3K | 2 | 185.0% | 1.65M | 4.69M |
| 8 | [0x4337001f...](https://etherscan.io/address/0x4337001fff419768e088ce247456c1b892888084) | Frequent User - High Impact | 2.78M | 2.7K | 1.0K | 2 | 200.0% | 1.39M | 4.17M |
| 9 | [0x4337003f...](https://etherscan.io/address/0x4337003fcd2f56de3977ccb806383e9161628d0e) | Regular User - High Impact | 2.72M | 2.7K | 999 | 2 | 200.0% | 1.36M | 4.08M |
| 10 | [0x4337002c...](https://etherscan.io/address/0x4337002c5702ce424cb62a56ca038e31e1d4a93d) | Regular User - High Impact | 2.65M | 2.7K | 975 | 2 | 200.0% | 1.33M | 3.98M |
| 11 | [0x4337005d...](https://etherscan.io/address/0x4337005db25dbad41da5692ba1188751ee5d98b6) | Regular User - High Impact | 2.59M | 2.7K | 952 | 2 | 200.0% | 1.29M | 3.88M |
| 12 | [0x4337004e...](https://etherscan.io/address/0x4337004ec9c1417f1c7a26ebd4b4fbed6acf9e5d) | Regular User - High Impact | 2.59M | 2.7K | 951 | 2 | 200.0% | 1.29M | 3.88M |
| 13 | [0x58d14960...](https://etherscan.io/address/0x58d14960e0a2be353edde61ad719196a2b816522) | Frequent User - High Impact | 1.48M | 939.84 | 1.6K | 2 | 185.6% | 795.6K | 2.27M |
| 14 | [0x6f9d816c...](https://etherscan.io/address/0x6f9d816c4ec365fe8fc6898c785be0e2d51bec2c) | Regular User - High Impact | 1.42M | 2.7K | 525 | 1 | 200.1% | 708.2K | 2.13M |
| 15 | [0xc2adcfcc...](https://etherscan.io/address/0xc2adcfccee33a417064d1a45d3b202de6d9fa474) | Regular User - High Impact | 1.23M | 1.5K | 822 | 1 | 193.6% | 636.6K | 1.87M |
| 16 | [0x94a365ca...](https://etherscan.io/address/0x94a365ca808029af8db18257ecd296c16c61ac05) | Regular User - High Impact | 1.13M | 1.8K | 645 | 1 | 195.7% | 577.7K | 1.71M |
| 17 | [0x9c0b0dbb...](https://etherscan.io/address/0x9c0b0dbbae8a976ceea8c2a96f6d00c53839afdc) | Regular User - High Impact | 1.12M | 1.5K | 750 | 1 | 193.6% | 580.9K | 1.71M |
| 18 | [0x35274399...](https://etherscan.io/address/0x3527439923a63f8c13cf72b8fe80a77f6e572092) | Frequent User - High Impact | 1.06M | 948.79 | 1.1K | 1 | 185.8% | 568.4K | 1.62M |
| 19 | [0x2b711ee0...](https://etherscan.io/address/0x2b711ee00b50d67667c4439c28aeaf7b75cb6e0d) | Frequent User - High Impact | 993.3K | 899.75 | 1.1K | 2 | 184.7% | 537.9K | 1.53M |
| 20 | [0xa58428fd...](https://etherscan.io/address/0xa58428fd982447bdef7c8b6db6e9beb964b56147) | Regular User - High Impact | 839.4K | 2.7K | 311 | 1 | 200.1% | 419.5K | 1.26M |
| 21 | [0x3f261ad6...](https://etherscan.io/address/0x3f261ad6666d6fea319939a3373776632e252778) | Regular User - High Impact | 792.7K | 2.7K | 296 | 1 | 200.1% | 396.0K | 1.19M |
| 22 | [0x52ff08f3...](https://etherscan.io/address/0x52ff08f313a00a54e3beffb5c4a7f7446efb6754) | Regular User - High Impact | 575.8K | 1.5K | 384 | 1 | 193.6% | 297.4K | 873.2K |
| 23 | [0xe8c20ea8...](https://etherscan.io/address/0xe8c20ea8ef100d7aa3846616e5d07a5abb067c65) | Regular User - High Impact | 477.7K | 2.7K | 177 | 1 | 200.1% | 238.8K | 716.5K |
| 24 | [0x1a8312fa...](https://etherscan.io/address/0x1a8312fad1d803660d5d5dee8cddfc35b3bec33d) | Regular User - High Impact | 440.6K | 2.7K | 162 | 1 | 200.0% | 220.3K | 661.0K |
| 25 | [0xc1c0104f...](https://etherscan.io/address/0xc1c0104f8ec7cf4b2fc4f86781aa6cbd0e8a2400) | Regular User - High Impact | 415.6K | 2.7K | 154 | 1 | 200.1% | 207.7K | 623.4K |
| 26 | [0xf70da978...](https://etherscan.io/address/0xf70da97812cb96acdf810712aa562db8dfa3dbef) | Regular User - High Impact | 359.0K | 2.7K | 132 | 1 | 200.0% | 179.5K | 538.6K |
| 27 | [0xc8564726...](https://etherscan.io/address/0xc8564726aaa50cf006ea28c5ef2dadd85a26b723) | Regular User - High Impact | 326.4K | 2.7K | 120 | 1 | 200.0% | 163.2K | 489.6K |
| 28 | [0xad0a80a0...](https://etherscan.io/address/0xad0a80a085095eca46de3053c345516f1c722d2a) | Regular User - High Impact | 315.8K | 1.0K | 309 | 1 | 187.2% | 168.7K | 484.5K |
| 29 | [0x415ed64d...](https://etherscan.io/address/0x415ed64d42bc0c37aeaaef79aa767d963ef38807) | Regular User - High Impact | 304.4K | 1.7K | 175 | 1 | 195.6% | 155.6K | 460.0K |
| 30 | [0x7c088b4c...](https://etherscan.io/address/0x7c088b4c6dceae8889e1fcc8c52de8cb930f89a0) | Regular User - High Impact | 285.6K | 2.7K | 105 | 1 | 200.0% | 142.8K | 428.4K |
| 31 | [0x01b27db5...](https://etherscan.io/address/0x01b27db5a9a57c7bd411676413980f0c5ac2fd4f) | Regular User - High Impact | 285.6K | 2.7K | 105 | 1 | 200.0% | 142.8K | 428.4K |
| 32 | [0xf79a32b8...](https://etherscan.io/address/0xf79a32b893b793ff4964134273b9c0ab8e9b4005) | Regular User - High Impact | 285.6K | 2.7K | 105 | 1 | 200.0% | 142.8K | 428.4K |
| 33 | [0x0e902b2d...](https://etherscan.io/address/0x0e902b2d0408754271c9e97d81fd2ede279cade6) | Occasional User - High Impact | 269.3K | 2.7K | 99 | 1 | 200.0% | 134.6K | 403.9K |
| 34 | [0xf279dfcd...](https://etherscan.io/address/0xf279dfcdd57e1571c95e2c5b7e2ee453cbcdf77f) | Occasional User - High Impact | 261.1K | 2.7K | 96 | 1 | 200.0% | 130.6K | 391.7K |
| 35 | [0x8e86251c...](https://etherscan.io/address/0x8e86251c88e5b3ef134a37bcab2cd63beb627c4c) | Occasional User - High Impact | 261.1K | 2.7K | 96 | 1 | 200.0% | 130.6K | 391.7K |
| 36 | [0xe1963570...](https://etherscan.io/address/0xe19635704ae3b77bc993358ff515d10cceae0ce1) | Occasional User - High Impact | 261.1K | 2.7K | 96 | 1 | 200.0% | 130.6K | 391.7K |
| 37 | [0x8f47a238...](https://etherscan.io/address/0x8f47a238c7701247ee8469ddc37ac1df121cfcce) | Occasional User - High Impact | 253.0K | 2.7K | 93 | 1 | 200.0% | 126.5K | 379.4K |
| 38 | [0xcd0b5a01...](https://etherscan.io/address/0xcd0b5a01abe9c14f6efbc610c02ecf0fb69855da) | Regular User - High Impact | 252.2K | 1.7K | 145 | 1 | 195.6% | 129.0K | 381.2K |
| 39 | [0x3749dd5d...](https://etherscan.io/address/0x3749dd5d2820dc16f8128c81b14a3eba5826e04f) | Occasional User - High Impact | 236.6K | 2.7K | 87 | 1 | 200.0% | 118.3K | 355.0K |
| 40 | [0x554b30ef...](https://etherscan.io/address/0x554b30efcc7bf683b6e97170c1201ebfc69de4c8) | Occasional User - High Impact | 228.5K | 2.7K | 84 | 1 | 200.0% | 114.2K | 342.7K |
| 41 | [0x7b5cb95e...](https://etherscan.io/address/0x7b5cb95e372246b074e5e17d58e98bef46897b9a) | Occasional User - High Impact | 212.2K | 2.7K | 78 | 1 | 200.0% | 106.1K | 318.2K |
| 42 | [0x1d539601...](https://etherscan.io/address/0x1d53960165188ee0c74a5705ee6307fea517c613) | Occasional User - High Impact | 212.2K | 2.7K | 78 | 1 | 200.0% | 106.1K | 318.2K |
| 43 | [0x6a6fb757...](https://etherscan.io/address/0x6a6fb757b09178de160a39e1d82c9626ebd2be41) | Occasional User - High Impact | 212.2K | 2.7K | 78 | 1 | 200.0% | 106.1K | 318.2K |
| 44 | [0xcfdee1e8...](https://etherscan.io/address/0xcfdee1e80f67d45761f321f3c9ecb28aae769810) | Occasional User - High Impact | 204.0K | 2.7K | 75 | 1 | 200.0% | 102.0K | 306.0K |
| 45 | [0x30066439...](https://etherscan.io/address/0x30066439887c0a509cb38e45c9262e6924a29bbd) | Regular User - High Impact | 200.0K | 1.7K | 115 | 1 | 195.6% | 102.3K | 302.3K |
| 46 | [0x9b1a331b...](https://etherscan.io/address/0x9b1a331b4ac667fd97674ceedd861008488a3e40) | Occasional User - High Impact | 195.8K | 2.7K | 72 | 1 | 200.0% | 97.9K | 293.8K |
| 47 | [0xb5b25e9b...](https://etherscan.io/address/0xb5b25e9b8c5c2d4e03ca0a79e42aa226cdec3ff2) | Occasional User - High Impact | 195.8K | 2.7K | 72 | 1 | 200.0% | 97.9K | 293.8K |
| 48 | [0xce54f65a...](https://etherscan.io/address/0xce54f65abb8b61b83c14cbe97de97fce75bbf556) | Occasional User - High Impact | 195.8K | 2.7K | 72 | 1 | 200.0% | 97.9K | 293.8K |
| 49 | [0x2891d2f9...](https://etherscan.io/address/0x2891d2f99bc447a591f06d896f5f72647aa1bc4c) | Occasional User - High Impact | 195.8K | 2.7K | 72 | 1 | 200.0% | 97.9K | 293.8K |
| 50 | [0x0392b4cc...](https://etherscan.io/address/0x0392b4cc79fbb0f38d8942866c0302ae01c2b194) | Occasional User - High Impact | 187.7K | 2.7K | 69 | 1 | 200.0% | 93.8K | 281.5K |

## Top 50 Most Affected Contracts

| Rank | Contract Address | Total Increase | Avg per Call | Total Calls | Unique Users | User Concentration | % Increase | Current Cost | New Cost |
|------|------------------|----------------|--------------|-------------|--------------|-------------------|------------|--------------|----------|
| 1 | [0x5ff137d4...](https://etherscan.io/address/0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789) | 30.65M | 2.7K | 11.3K | 73.0 | 0.99 | 200.0% | 15.33M | 45.98M |
| 2 | [0x68d30f47...](https://etherscan.io/address/0x68d30f47f19c07bccef4ac7fae2dc12fca3e0dc9) | 14.06M | 1.5K | 9.4K | 1.0 | 1.00 | 193.6% | 7.26M | 21.33M |
| 3 | [0x8c0bfc04...](https://etherscan.io/address/0x8c0bfc04ada21fd496c55b8c50331f904306f564) | 13.03M | 951.25 | 13.7K | 17.0 | 1.00 | 185.8% | 7.01M | 20.04M |
| 4 | [0x5d8ba173...](https://etherscan.io/address/0x5d8ba173dc6c3c90c8f7c04c9288bef5fdbad06e) | 9.14M | 899.75 | 10.2K | 9.0 | 1.00 | 184.7% | 4.95M | 14.09M |
| 5 | [0x870679e1...](https://etherscan.io/address/0x870679e138bcdf293b7ff14dd44b70fc97e12fc0) | 7.19M | 2.7K | 2.7K | 1.0 | 1.00 | 200.1% | 3.59M | 10.78M |
| 6 | [0x3b4d794a...](https://etherscan.io/address/0x3b4d794a66304f130a4db8f2551b0070dfcf5ca7) | 6.22M | 1.5K | 4.1K | 1.0 | 1.00 | 193.6% | 3.21M | 9.43M |
| 7 | [0xa13baf47...](https://etherscan.io/address/0xa13baf47339d63b743e7da8741db5456dac1e556) | 1.42M | 2.7K | 525 | 1.0 | 1.00 | 200.1% | 708.2K | 2.13M |
| 8 | [0xd7f86b4b...](https://etherscan.io/address/0xd7f86b4b8cae7d942340ff628f82735b7a20893a) | 1.26M | 2.7K | 467 | 3.0 | 1.00 | 200.1% | 630.0K | 1.89M |
| 9 | [0x02993cdc...](https://etherscan.io/address/0x02993cdc11213985b9b13224f3af289f03bf298d) | 1.23M | 1.5K | 822 | 1.0 | 1.00 | 193.6% | 636.6K | 1.87M |
| 10 | [0xece9cf6a...](https://etherscan.io/address/0xece9cf6a8f2768a3b8b65060925b646afeaa5167) | 1.13M | 1.8K | 645 | 1.0 | 1.00 | 195.7% | 577.7K | 1.71M |
| 11 | [0x7cf3876f...](https://etherscan.io/address/0x7cf3876f681dbb6eda8f6ffc45d66b996df08fae) | 1.12M | 1.5K | 750 | 1.0 | 1.00 | 193.6% | 580.9K | 1.71M |
| 12 | [0x150fe8db...](https://etherscan.io/address/0x150fe8dbb943c372f3e8c31d9c89f1e6a13cbbfd) | 792.7K | 2.7K | 296 | 1.0 | 1.00 | 200.1% | 396.0K | 1.19M |
| 13 | [0x00000000...](https://etherscan.io/address/0x0000000071727de22e5e9d8baf0edac6f37da032) | 685.4K | 2.7K | 252 | 7.0 | 0.98 | 200.0% | 342.7K | 1.03M |
| 14 | [0xd19d4b5d...](https://etherscan.io/address/0xd19d4b5d358258f05d7b411e21a1460d11b0876f) | 575.8K | 1.5K | 384 | 1.0 | 1.00 | 193.6% | 297.4K | 873.2K |
| 15 | [0x92ef6af4...](https://etherscan.io/address/0x92ef6af472b39f1b363da45e35530c24619245a4) | 477.7K | 2.7K | 177 | 1.0 | 1.00 | 200.1% | 238.8K | 716.5K |
| 16 | [0xb90ed4c1...](https://etherscan.io/address/0xb90ed4c123843cbfd66b11411ee7694ef37e6e72) | 359.0K | 2.7K | 132 | 1.0 | 1.00 | 200.0% | 179.5K | 538.6K |
| 17 | [0xb32cb567...](https://etherscan.io/address/0xb32cb5677a7c971689228ec835800432b339ba2b) | 177.5K | 22.2K | 8 | 2.0 | 0.88 | 500.0% | 35.5K | 213.0K |
| 18 | [0xef2a435e...](https://etherscan.io/address/0xef2a435e5ee44b2041100ef8cbc8ae035166606c) | 171.4K | 2.7K | 64 | 1.0 | 1.00 | 200.1% | 85.6K | 257.0K |
| 19 | [0xabea9132...](https://etherscan.io/address/0xabea9132b05a70803a4e85094fd0e1800777fbef) | 159.9K | 779.80 | 205 | 1.0 | 1.00 | 181.4% | 88.1K | 248.0K |
| 20 | [0xb4544083...](https://etherscan.io/address/0xb45440830bd8d288bb2b5b01be303ae60fc855d8) | 108.0K | 1.5K | 72 | 1.0 | 1.00 | 193.6% | 55.8K | 163.7K |
| 21 | [0x95ca91ce...](https://etherscan.io/address/0x95ca91cea73239b15e5d2e5a74d02d6b5e0ae458) | 59.4K | 2.7K | 22 | 1.0 | 1.00 | 200.1% | 29.7K | 89.1K |
| 22 | [0xd1ce9000...](https://etherscan.io/address/0xd1ce90003a10e6dab877890ab1fd96511555e4b3) | 54.6K | 6.8K | 8 | 1.0 | 1.00 | 500.1% | 10.9K | 65.5K |
| 23 | [0x3d18ad73...](https://etherscan.io/address/0x3d18ad735f949febd59bbfcb5864ee0157607616) | 40.2K | 2.7K | 15 | 1.0 | 1.00 | 200.1% | 20.1K | 60.2K |
| 24 | [0x5968ada2...](https://etherscan.io/address/0x5968ada261a84e19a6c85830e655647752585ed4) | 29.9K | 2.7K | 11 | 1.0 | 1.00 | 200.0% | 15.0K | 44.9K |
| 25 | [0x2f3c2056...](https://etherscan.io/address/0x2f3c205613d9451f88e19e011ed23775afe00c41) | 27.0K | 1.5K | 18 | 1.0 | 1.00 | 193.6% | 13.9K | 40.9K |
| 26 | [0x271682de...](https://etherscan.io/address/0x271682deb8c4e0901d1a1550ad2e64d568e69909) | 21.6K | 2.7K | 8 | 3.0 | 0.75 | 200.1% | 10.8K | 32.4K |
| 27 | [0x38de07d2...](https://etherscan.io/address/0x38de07d2526ae929f1903e5f109b70c50e12a8e0) | 18.0K | 1.5K | 12 | 1.0 | 1.00 | 193.6% | 9.3K | 27.3K |
| 28 | [0x30efaaa9...](https://etherscan.io/address/0x30efaaa99f8efe310d9fdc83072e2a04c093d400) | 14.1K | 300 | 47 | 1.0 | 1.00 | 150.0% | 9.4K | 23.5K |
| 29 | [0x2d5805a4...](https://etherscan.io/address/0x2d5805a423d6ce771f06972ad4499f120902631a) | 10.9K | 2.7K | 4 | 2.0 | 0.75 | 200.0% | 5.4K | 16.3K |
| 30 | [0x5b5a0580...](https://etherscan.io/address/0x5b5a0580bcfd3673820bb249514234afad33e209) | 8.2K | 2.7K | 3 | 1.0 | 1.00 | 200.0% | 4.1K | 12.2K |
| 31 | [0xb3445d54...](https://etherscan.io/address/0xb3445d5413abf63df1112a4a517de2602f249785) | 8.2K | 2.7K | 3 | 1.0 | 1.00 | 200.0% | 4.1K | 12.2K |
| 32 | [0x9569fe8c...](https://etherscan.io/address/0x9569fe8cd0050069328e3707cffb61c77ddeb9d0) | 8.1K | 2.7K | 3 | 1.0 | 1.00 | 200.1% | 4.0K | 12.1K |
| 33 | [0x1fa7cb49...](https://etherscan.io/address/0x1fa7cb4925086128f3bb9e26761c9c75dbac3cd1) | 8.1K | 2.7K | 3 | 2.0 | 0.67 | 200.1% | 4.0K | 12.1K |
| 34 | [0x0baac79a...](https://etherscan.io/address/0x0baac79acd45a023e19345c352d8a7a83c4e5656) | 8.0K | 2.7K | 3 | 1.0 | 1.00 | 200.1% | 4.0K | 12.0K |
| 35 | [0xbadc0ffe...](https://etherscan.io/address/0xbadc0ffee00baa564f3fea62e9d37843284c1e6a) | 5.4K | 2.7K | 2 | 1.0 | 1.00 | 200.0% | 2.7K | 8.2K |
| 36 | [0xad3b67bc...](https://etherscan.io/address/0xad3b67bca8935cb510c8d18bd45f0b94f54a968f) | 5.4K | 2.7K | 2 | 1.0 | 1.00 | 200.0% | 2.7K | 8.2K |
| 37 | [0x8ddbbcc0...](https://etherscan.io/address/0x8ddbbcc0999f396237b6534ac600ebb0d8618c99) | 5.4K | 2.7K | 2 | 1.0 | 1.00 | 200.0% | 2.7K | 8.2K |
| 38 | [0xf0d54349...](https://etherscan.io/address/0xf0d54349addcf704f77ae15b96510dea15cb7952) | 5.4K | 2.7K | 2 | 1.0 | 1.00 | 200.1% | 2.7K | 8.1K |
| 39 | [0xfeda03b9...](https://etherscan.io/address/0xfeda03b91514d31b435d4e1519fd9e699c29bbfc) | 3.3K | 300 | 11 | 4.0 | 0.73 | 150.0% | 2.2K | 5.5K |
| 40 | [0x159f3668...](https://etherscan.io/address/0x159f3668c72bbecdf1fb31beed606ec9649654eb) | 2.7K | 2.7K | 1 | 1.0 | 1.00 | 200.1% | 1.3K | 4.0K |
| 41 | [0xd18d1779...](https://etherscan.io/address/0xd18d17791f2071bf3c855ba770420a9edea0728d) | 1.2K | 312 | 4 | 4.0 | 0.25 | 156.0% | 800 | 2.0K |
| 42 | [0x2eb474cf...](https://etherscan.io/address/0x2eb474cffabca358d9fd3f1d43ad2b2dfb809b0e) | 312 | 312 | 1 | 1.0 | 1.00 | 156.0% | 200 | 512 |

### Most Active Entities

| Rank | Address | Total Calls | Active Blocks | Calls/1K Blocks | First Block | Last Block | Activity Span |
|------|---------|-------------|---------------|-----------------|-------------|------------|---------------|
| 1 | [0x00000062...](https://etherscan.io/address/0x000000629fbcf27a347d1aeba658435230d74a5f) | 9.4K | 1.6K | 19.1 | 22.09M | 22.58M | 491.2K blocks |
| 2 | [0xaaf7b278...](https://etherscan.io/address/0xaaf7b278bac078aa4f9bdc8e0a93cde604aa67d9) | 8.0K | 292 | 18.4 | 22.09M | 22.52M | 434.3K blocks |
| 3 | [0x54ab716d...](https://etherscan.io/address/0x54ab716d465be3d5eeca64e63ac0048d7a81659a) | 7.4K | 688 | 17.1 | 22.09M | 22.52M | 434.4K blocks |
| 4 | [0xfcb73f64...](https://etherscan.io/address/0xfcb73f6405f6b9be91013d9477d81833a69c9c0d) | 4.1K | 691 | 8.4 | 22.09M | 22.58M | 491.2K blocks |
| 5 | [0xf3b07f67...](https://etherscan.io/address/0xf3b07f6744e06cd5074b7d15ed2c33760837ce1f) | 3.3K | 335 | 7.7 | 22.09M | 22.52M | 434.4K blocks |
| 6 | [0x7202932b...](https://etherscan.io/address/0x7202932b3be70edf0657d5bada261d610e0d7db9) | 3.1K | 967 | 30.6 | 22.09M | 22.19M | 99.9K blocks |
| 7 | [0x454ef2f6...](https://etherscan.io/address/0x454ef2f69f91527856e06659f92a66f464c1ca4e) | 2.7K | 1.3K | 5.5 | 22.09M | 22.58M | 491.4K blocks |
| 8 | [0x58d14960...](https://etherscan.io/address/0x58d14960e0a2be353edde61ad719196a2b816522) | 1.6K | 192 | 3.2 | 22.09M | 22.58M | 490.9K blocks |
| 9 | [0x35274399...](https://etherscan.io/address/0x3527439923a63f8c13cf72b8fe80a77f6e572092) | 1.1K | 144 | 3.1 | 22.09M | 22.45M | 359.7K blocks |
| 10 | [0x2b711ee0...](https://etherscan.io/address/0x2b711ee00b50d67667c4439c28aeaf7b75cb6e0d) | 1.1K | 138 | 2.3 | 22.09M | 22.58M | 486.1K blocks |
| 11 | [0x4337001f...](https://etherscan.io/address/0x4337001fff419768e088ce247456c1b892888084) | 1.0K | 502 | 2.1 | 22.09M | 22.58M | 491.2K blocks |
| 12 | [0x4337003f...](https://etherscan.io/address/0x4337003fcd2f56de3977ccb806383e9161628d0e) | 999 | 490 | 2.0 | 22.09M | 22.58M | 491.3K blocks |
| 13 | [0x4337002c...](https://etherscan.io/address/0x4337002c5702ce424cb62a56ca038e31e1d4a93d) | 975 | 482 | 2.0 | 22.09M | 22.58M | 491.4K blocks |
| 14 | [0x4337005d...](https://etherscan.io/address/0x4337005db25dbad41da5692ba1188751ee5d98b6) | 952 | 469 | 1.9 | 22.09M | 22.58M | 491.1K blocks |
| 15 | [0x4337004e...](https://etherscan.io/address/0x4337004ec9c1417f1c7a26ebd4b4fbed6acf9e5d) | 951 | 468 | 1.9 | 22.09M | 22.58M | 491.2K blocks |
| 16 | [0xc2adcfcc...](https://etherscan.io/address/0xc2adcfccee33a417064d1a45d3b202de6d9fa474) | 822 | 137 | 1.7 | 22.09M | 22.58M | 490.8K blocks |
| 17 | [0x9c0b0dbb...](https://etherscan.io/address/0x9c0b0dbbae8a976ceea8c2a96f6d00c53839afdc) | 750 | 125 | 1.5 | 22.09M | 22.58M | 491.0K blocks |
| 18 | [0x94a365ca...](https://etherscan.io/address/0x94a365ca808029af8db18257ecd296c16c61ac05) | 645 | 101 | 1.6 | 22.09M | 22.50M | 411.5K blocks |
| 19 | [0x6f9d816c...](https://etherscan.io/address/0x6f9d816c4ec365fe8fc6898c785be0e2d51bec2c) | 525 | 175 | 1.1 | 22.09M | 22.58M | 491.0K blocks |
| 20 | [0x52ff08f3...](https://etherscan.io/address/0x52ff08f313a00a54e3beffb5c4a7f7446efb6754) | 384 | 64 | 0.8 | 22.09M | 22.58M | 489.8K blocks |

### Highest Average Impact per Call

| Rank | Address | Avg Increase/Call | Total Calls | Total Increase | Category |
|------|---------|-------------------|-------------|----------------|----------|
| 1 | [0x01b27db5...](https://etherscan.io/address/0x01b27db5a9a57c7bd411676413980f0c5ac2fd4f) | 2.7K | 105 | 285.6K | Regular User - High Impact |
| 2 | [0x0e902b2d...](https://etherscan.io/address/0x0e902b2d0408754271c9e97d81fd2ede279cade6) | 2.7K | 99 | 269.3K | Occasional User - High Impact |
| 3 | [0x0a0256a9...](https://etherscan.io/address/0x0a0256a9166041101c90be87bbebb8242a3ba015) | 2.7K | 45 | 122.4K | Occasional User - High Impact |
| 4 | [0x0392b4cc...](https://etherscan.io/address/0x0392b4cc79fbb0f38d8942866c0302ae01c2b194) | 2.7K | 69 | 187.7K | Occasional User - High Impact |
| 5 | [0x1a8312fa...](https://etherscan.io/address/0x1a8312fad1d803660d5d5dee8cddfc35b3bec33d) | 2.7K | 162 | 440.6K | Regular User - High Impact |
| 6 | [0x17a9aa3f...](https://etherscan.io/address/0x17a9aa3f7945fb00c2eb16857baa4adb63da59db) | 2.7K | 15 | 40.8K | Occasional User - Medium Impact |
| 7 | [0x106b67c3...](https://etherscan.io/address/0x106b67c3f6d4fff429668b0496d2e4cda55e805b) | 2.7K | 48 | 130.6K | Occasional User - High Impact |
| 8 | [0x10314ac2...](https://etherscan.io/address/0x10314ac278aa9d431701f49e70273bd6e40c93f7) | 2.7K | 48 | 130.6K | Occasional User - High Impact |
| 9 | [0x4337004e...](https://etherscan.io/address/0x4337004ec9c1417f1c7a26ebd4b4fbed6acf9e5d) | 2.7K | 951 | 2.59M | Regular User - High Impact |
| 10 | [0x4337005d...](https://etherscan.io/address/0x4337005db25dbad41da5692ba1188751ee5d98b6) | 2.7K | 952 | 2.59M | Regular User - High Impact |
| 11 | [0x435b3539...](https://etherscan.io/address/0x435b3539f68283dd44f03a4bfe8666c0f6187033) | 2.7K | 54 | 146.9K | Occasional User - High Impact |
| 12 | [0x43d2cf58...](https://etherscan.io/address/0x43d2cf587f2dd7853a60d6a53032b1217e6ad8a4) | 2.7K | 51 | 138.7K | Occasional User - High Impact |
| 13 | [0x1d539601...](https://etherscan.io/address/0x1d53960165188ee0c74a5705ee6307fea517c613) | 2.7K | 78 | 212.2K | Occasional User - High Impact |
| 14 | [0x1f55ce12...](https://etherscan.io/address/0x1f55ce1234aa67f28b00c493535a230d8f1d16c7) | 2.7K | 15 | 40.8K | Occasional User - Medium Impact |
| 15 | [0x211d9824...](https://etherscan.io/address/0x211d98242e4c58e9eb17e3cc135a165bd59dd172) | 2.7K | 45 | 122.4K | Occasional User - High Impact |
| 16 | [0x23b32bae...](https://etherscan.io/address/0x23b32bae4708bc9af3962b81d6d8ca5327e9dffc) | 2.7K | 54 | 146.9K | Occasional User - High Impact |
| 17 | [0x2915637a...](https://etherscan.io/address/0x2915637a5f4b83b4097fc0b2eae2fe3c1c761465) | 2.7K | 33 | 89.8K | Occasional User - Medium Impact |
| 18 | [0x256b3cc1...](https://etherscan.io/address/0x256b3cc1e516d124b3027ecd083aa5a940d1328e) | 2.7K | 54 | 146.9K | Occasional User - High Impact |
| 19 | [0x2791a02d...](https://etherscan.io/address/0x2791a02da92175eb44d267cdcc954debf64ca31f) | 2.7K | 63 | 171.4K | Occasional User - High Impact |
| 20 | [0x2891d2f9...](https://etherscan.io/address/0x2891d2f99bc447a591f06d896f5f72647aa1bc4c) | 2.7K | 72 | 195.8K | Occasional User - High Impact |

## Entity Relationships

### Multi-Contract Users

Entities using multiple contracts (top 20 by total impact):

| Rank | Entity Address | Contracts Used | Total Calls | Total Increase | Primary Contract |
|------|----------------|----------------|-------------|----------------|------------------|
| 1 | [0xaaf7b278...](https://etherscan.io/address/0xaaf7b278bac078aa4f9bdc8e0a93cde604aa67d9) | 2 | 8.0K | 7.22M | [0x5d8ba173...](https://etherscan.io/address/0x5d8ba173dc6c3c90c8f7c04c9288bef5fdbad06e) |
| 2 | [0x54ab716d...](https://etherscan.io/address/0x54ab716d465be3d5eeca64e63ac0048d7a81659a) | 2 | 7.4K | 6.79M | [0x8c0bfc04...](https://etherscan.io/address/0x8c0bfc04ada21fd496c55b8c50331f904306f564) |
| 3 | [0xf3b07f67...](https://etherscan.io/address/0xf3b07f6744e06cd5074b7d15ed2c33760837ce1f) | 2 | 3.3K | 3.05M | [0x8c0bfc04...](https://etherscan.io/address/0x8c0bfc04ada21fd496c55b8c50331f904306f564) |
| 4 | [0x4337001f...](https://etherscan.io/address/0x4337001fff419768e088ce247456c1b892888084) | 2 | 1.0K | 2.78M | [0x5ff137d4...](https://etherscan.io/address/0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789) |
| 5 | [0x4337003f...](https://etherscan.io/address/0x4337003fcd2f56de3977ccb806383e9161628d0e) | 2 | 999 | 2.72M | [0x5ff137d4...](https://etherscan.io/address/0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789) |
| 6 | [0x4337002c...](https://etherscan.io/address/0x4337002c5702ce424cb62a56ca038e31e1d4a93d) | 2 | 975 | 2.65M | [0x5ff137d4...](https://etherscan.io/address/0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789) |
| 7 | [0x4337005d...](https://etherscan.io/address/0x4337005db25dbad41da5692ba1188751ee5d98b6) | 2 | 952 | 2.59M | [0x5ff137d4...](https://etherscan.io/address/0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789) |
| 8 | [0x4337004e...](https://etherscan.io/address/0x4337004ec9c1417f1c7a26ebd4b4fbed6acf9e5d) | 2 | 951 | 2.59M | [0x5ff137d4...](https://etherscan.io/address/0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789) |
| 9 | [0x58d14960...](https://etherscan.io/address/0x58d14960e0a2be353edde61ad719196a2b816522) | 2 | 1.6K | 1.48M | [0x8c0bfc04...](https://etherscan.io/address/0x8c0bfc04ada21fd496c55b8c50331f904306f564) |
| 10 | [0x2b711ee0...](https://etherscan.io/address/0x2b711ee00b50d67667c4439c28aeaf7b75cb6e0d) | 2 | 1.1K | 993.3K | [0x8c0bfc04...](https://etherscan.io/address/0x8c0bfc04ada21fd496c55b8c50331f904306f564) |
| 11 | [0x2572835e...](https://etherscan.io/address/0x2572835e02b59078711aa0800490e80975e4169d) | 2 | 168 | 151.2K | [0x8c0bfc04...](https://etherscan.io/address/0x8c0bfc04ada21fd496c55b8c50331f904306f564) |
| 12 | [0x59b84b24...](https://etherscan.io/address/0x59b84b24e307682df830b32ddc826fbbe003c210) | 2 | 144 | 129.6K | [0x8c0bfc04...](https://etherscan.io/address/0x8c0bfc04ada21fd496c55b8c50331f904306f564) |
| 13 | [0x0f9b807d...](https://etherscan.io/address/0x0f9b807d5b0ce12450059b425dc35c727d65cb2f) | 2 | 136 | 122.4K | [0x8c0bfc04...](https://etherscan.io/address/0x8c0bfc04ada21fd496c55b8c50331f904306f564) |
| 14 | [0x5ccc2130...](https://etherscan.io/address/0x5ccc2130e77ae3a3211740c2e897bfbb5d70aa54) | 2 | 2 | 5.4K | [0x1fa7cb49...](https://etherscan.io/address/0x1fa7cb4925086128f3bb9e26761c9c75dbac3cd1) |

## Power User Analysis

Entities in the top 1% by call volume (≥7.8K calls):

| Rank | Address | Total Calls | Total Increase | % of All Calls | % of All Increase | Category |
|------|---------|-------------|----------------|----------------|-------------------|----------|
| 1 | [0x00000062...](https://etherscan.io/address/0x000000629fbcf27a347d1aeba658435230d74a5f) | 9.4K | 14.06M | 3.08% | 2.59% | Heavy User - High Impact |
| 2 | [0xaaf7b278...](https://etherscan.io/address/0xaaf7b278bac078aa4f9bdc8e0a93cde604aa67d9) | 8.0K | 7.22M | 2.63% | 1.33% | Heavy User - High Impact |

## Summary Statistics

### Entity Distribution

- **Heavy Users (≥5,000 calls)**: 3 entities
- **Frequent Users (1,000-4,999 calls)**: 8 entities
- **Regular Users (100-999 calls)**: 27 entities
- **Occasional Users (10-99 calls)**: 66 entities
- **Rare Users (&lt;10 calls)**: 39 entities

### Impact Distribution

- **High Impact (≥100K gas increase)**: 80 entities
- **Medium Impact (10K-99K gas)**: 33 entities
- **Low Impact (&lt;10K gas)**: 30 entities

### Concentration Metrics

- **Top 10 entities**: 11.2% of total gas increase
- **Top 50 entities**: 15.5% of total gas increase
- **Top 100 entities**: 16.6% of total gas increase

## Key Insights

1. **Universal Impact**: All entities using the precompile are affected by the updated EIP-7883 pricing
2. **Significant Increases**: Average cost increase of ~3x across all operations
3. **Usage Patterns**: Heavy users will face the largest absolute cost increases
4. **Contract Concentration**: Some contracts serve many users and will see major cumulative impacts

## Methodology

- **Data source**: Ethereum mainnet ModExp precompile calls
- **Entity identification**: Based on transaction &apos;from&apos; addresses
- **Impact calculation**: Sum of all gas cost increases under updated EIP-7883
- **Categorization**: Based on usage patterns and impact levels
- **Concentration score**: Measures how concentrated contract usage is (0=distributed, 1=single user)

---

*This entity-focused analysis provides detailed insights into how the updated EIP-7883 impacts different users of the ModExp precompile.*
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7883/entity_analysis</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7883/entity_analysis</guid>
      </item>
    
      <item>
        <title>Compute operations to reprice in EIP-7904</title>
        <category>/</category>
        
        <description># Compute operations to reprice in EIP-7904

#### Maria Silva, January 2026

In this report, we present which operations should have a cost increase with EIP-7904 and describe the methodology to pick them. The analysis can be reproduced in the [0.5-gasbench_data_eda](https://github.com/misilva73/evm-gas-repricings/blob/185f37f5e0a5636161d5da4983d87a4e420b227a/notebooks/0.5-gasbench_data_eda.ipynb) notebook.

### Methodology

#### Data

The raw benchmark data was generated by running the [EEST benchmark suite](https://github.com/ethereum/execution-spec-tests/tree/main/tests/benchmark) with the [Nethermind benchmarking tooling](https://github.com/NethermindEth/gas-benchmarks). The database is hosted on a PostgreSQL server managed by the Nethermind team.

Each test was run multiple times to isolate random variations in runtime and outliers. The data was collected between 2026-01-05 and 2026-01-22.

The test are still using the Prague fork. A similar analysis is still needed for the Osaka fork.

All benchmarks were run on the performance branches of each client using the following hardware specification:

| Specification | Value |
|--------------|-------|
| spec_processor_type | x86_64 |
| spec_system_os | Linux |
| spec_kernel_release | 6.8.0-53-generic |
| spec_kernel_version | #55-Ubuntu SMP PREEMPT_DYNAMIC |
| spec_machine_arch | x86_64 |
| spec_processor_arch | 64bit |
| spec_cpu_model | AMD EPYC 7713 64-Core Processor |
| spec_num_cpus | 32 |

#### Data processing

The raw benchmark data was processed as follows:

1. **Parsing test metadata**: Each test title was parsed to extract the test file, test name, test parameters, fork version, and the target opcode or precompile being tested.

2. **Filtering invalid data**: Tests with execution time of 0ms were excluded. The ethrex client was also excluded from the analysis as it is still in early development.

3. **Removing outliers**: For each (client, test, opcode) combination, outliers were identified using the interquartile range (IQR) method:
   - Lower threshold: Q1 - 1.5 × IQR
   - Upper threshold: Q3 + 1.5 × IQR
   - Data points outside these thresholds were flagged as outliers and excluded from the worst-case analysis.

4. **Computing worst-case performance**: For each (client, test, opcode) combination, the minimum non-outlier MGas/s value was selected to represent the worst-case execution performance.

5. **Aggregating by opcode**: For each opcode, the worst-performing test across all clients was identified, along with the second-worst client&apos;s performance on that same test.

#### Selecting candidates

Operations were selected as candidates for repricing based on the following criteria:

1. **Performance threshold**: The worst-case MGas/s must be below 60 MGas/s. By increase the costs of these operations, we will be able to increase our base throughput 3x from our current 20Mgas/s.

2. **Multi-client validation**: To avoid penalizing all clients for a single client&apos;s implementation inefficiency, the second-worst client&apos;s performance is also considered. If the second-worst client achieves significantly better performance (&gt;20% above the threshold), the operation is flagged for client optimization rather than repricing.

3. **Excluding very slow tests**: Tests with worst-case MGas/s below 20 MGas/s were analyzed separately to understand if the slowness is due to specific test parameters or possible errors in data. After Osaka, we are running at 20Mgas/s, so we should not observe test with values lower than this.

### Performance results

#### Run times distribution by client

The benchmark data covers 237,733 test runs across 5 clients (Besu, Erigon, Geth, Nethermind, and Reth) on the Prague fork. The overall distribution of MGas/s shows significant variation across tests and clients.

![mgas_distribution_by_client](/EIPs/assets/eip-7904/figures/mgas_distribution_by_client.png)

The boxplot above shows that different clients have different performance characteristics:

- **Nethermind** and **Reth** the highest median performance
- **Besu** shows a wider distribution with a majority of tests at lower MGas/s values
- **Erigon** and **Geth** have intermediate performance, with still some slower tests, but a higher median performance than Besu.

#### Worst vs. second-worst client

An important consideration for repricing is whether poor performance is isolated to a single client or affects multiple implementations. This is important for distinguishing between:

- Operations that genuinely need repricing (multiple clients struggle)
- Operations where a specific client needs optimization (only one client struggles)

The chart shows the number of tests in which each client was the worst performer. We can see that **Besu** is the worst performer in the majority of tests, followed by Erigon.

![worst_client_count](/EIPs/assets/eip-7904/figures/worst_client_count.png)

The next plot shows the distribution of the performance ratio between the worst client and second-worst client. Each boxplot shows this distribution by the client (i.e., when each client is the worst performer).

![worst_second_worst_gap](/EIPs/assets/eip-7904/figures/worst_second_worst_gap.png)

For a majority of tests, the gap between worst and second-worst is small (&lt;20%), suggesting that the worst client is not significantly underperforming on relation to the other clients. However, we do see some tests with the gas is much wider. These test are more frequent for when Besu is the worst client.

#### Underpriced operations at 60 MGas/s

The following table shows operations with worst-case performance below 60 MGas/s:

| Operation | Type | Worst MGas/s | Worst Client | Second Worst MGas/s |
|-----------|------|-------------|--------------|---------------------|
| MULMOD | opcode | 20.60 | besu | 57.02 |
| MODEXP | precompile | 21.63 | geth | 25.06 |
| EQ | opcode | 22.80 | besu | 122.96 |
| SDIV | opcode | 23.14 | besu | 85.18 |
| REVERT | opcode | 23.38 | besu | 110.41 |
| SMOD | opcode | 24.99 | besu | 67.98 |
| MOD | opcode | 25.27 | besu | 70.98 |
| SAR | opcode | 27.15 | besu | 134.36 |
| MUL | opcode | 27.60 | besu | 147.87 |
| SUB | opcode | 28.80 | besu | 122.66 |
| DIV | opcode | 29.94 | besu | 88.54 |
| SHIFT | opcode | 30.47 | besu | 124.32 |
| point evaluation | precompile | 31.75 | erigon | 31.85 |
| RETURN | opcode | 32.95 | besu | 103.85 |
| ADDMOD | opcode | 32.98 | besu | 91.12 |
| CALLCODE | opcode | 34.78 | besu | 112.96 |
| CALLDATALOAD | opcode | 35.52 | besu | 77.65 |
| CALL | opcode | 35.60 | besu | 98.94 |
| DELEGATECALL | opcode | 36.30 | besu | 127.70 |
| SELFDESTRUCT | opcode | 36.65 | besu | 628.81 |
| STATICCALL | opcode | 37.60 | besu | 105.77 |
| CALLDATACOPY | opcode | 38.08 | besu | 193.12 |
| KECCAK | opcode | 38.49 | besu | 70.90 |
| SHL | opcode | 39.64 | besu | 136.58 |
| SHR | opcode | 41.84 | besu | 134.38 |
| BLS12_G1ADD | precompile | 41.97 | besu | 73.64 |
| XOR | opcode | 47.34 | besu | 122.21 |
| blake2f | precompile | 47.48 | reth | 50.07 |
| ecAdd | precompile | 47.89 | besu | 63.51 |
| BLS12_G2ADD | precompile | 49.01 | besu | 69.11 |
| SHA2-256 | precompile | 52.29 | besu | 235.32 |
| AND | opcode | 54.66 | besu | 122.87 |
| identity | precompile | 54.74 | besu | 178.01 |
| OR | opcode | 54.91 | besu | 126.59 |
| ecRecover | precompile | 55.04 | besu | 58.41 |
| TLOAD | opcode | 55.90 | erigon | 789.42 |
| CALLDATASIZE | opcode | 56.91 | besu | 134.27 |
| MSTORE | opcode | 57.07 | besu | 145.72 |
| ecPairing | precompile | 57.34 | nethermind | 67.85 |
| ecMul | precompile | 58.66 | reth | 90.32 |

This table is then split into two categories below: **Candidates for repricing** (where multiple clients struggle) and **Operations requiring client optimization** (where only one client struggles).

As expected, there are a significant number of operations where Besu is performing bellow 60Mgas/s, but the rest of the clients have a significantly higher performance. These are the likely cases where a single client optimization is needed.

MODEXP is still performing at 21.63 Mgas/s, however we expect this value to change in the Osaka branch as this operation was already repriced there. We need to run this again on the newest fork.

#### Slow tests

We also observed test performing at less than 20Mgas/s. Since there are likely issues in the data, we exclude them from the underpriced operations. However, we need to confirm whether this is actually issues in the test and not a new bottleneck. The test in question are the following:

- `test_extcode_ops` in Geth and Erigon
- `test_xcall` in Geth
- `test_arithmetic` in Besu (only `opcode_ADD`)
- `test_selfbalance` in Besu (only `contract_balance_0`)
- `test_call_frame_context_ops` in Besu (`opcode_ORIGIN`)

### Final list

#### Candidates for repricing

The following operations are candidates for repricing under EIP-7904. These are operations where:

- The worst-case MGas/s is below 60 MGas/s, AND
- The second-worst client also performs below 72 MGas/s (60 × 1.2), indicating the poor performance is not isolated to a single client

| Operation | Type | Worst MGas/s | Worst Client | Second Worst MGas/s | Second Worst / Worst |
|-----------|------|-------------|--------------|---------------------|----------------------|
| MULMOD | opcode | 20.60 | besu | 57.02 | 2.77× |
| MODEXP | precompile | 21.63 | geth | 25.06 | 1.16× |
| SMOD | opcode | 24.99 | besu | 67.98 | 2.72× |
| MOD | opcode | 25.27 | besu | 70.98 | 2.81× |
| point evaluation | precompile | 31.75 | erigon | 31.85 | 1.00× |
| KECCAK | opcode | 38.49 | besu | 70.90 | 1.84× |
| BLS12_G1ADD | precompile | 41.97 | besu | 73.64 | 1.75× |
| blake2f | precompile | 47.48 | reth | 50.07 | 1.05× |
| ecAdd | precompile | 47.89 | besu | 63.51 | 1.33× |
| BLS12_G2ADD | precompile | 49.01 | besu | 69.11 | 1.41× |
| ecRecover | precompile | 55.04 | besu | 58.41 | 1.06× |
| ecPairing | precompile | 57.34 | nethermind | 67.85 | 1.18× |

#### Operations requiring client optimization

The following operations have poor performance on a single client but acceptable performance on others. These should be addressed through client optimization rather than protocol-level repricing:

| Operation | Type | Worst MGas/s | Worst Client | Second Worst MGas/s | Gap |
|-----------|------|-------------|--------------|---------------------|-----|
| EQ | opcode | 22.80 | besu | 122.96 | 5.4× |
| SDIV | opcode | 23.14 | besu | 85.18 | 3.7× |
| REVERT | opcode | 23.38 | besu | 110.41 | 4.7× |
| SAR | opcode | 27.15 | besu | 134.36 | 4.9× |
| MUL | opcode | 27.60 | besu | 147.87 | 5.4× |
| SUB | opcode | 28.80 | besu | 122.66 | 4.3× |
| DIV | opcode | 29.94 | besu | 88.54 | 3.0× |
| SHIFT | opcode | 30.47 | besu | 124.32 | 4.1× |
| RETURN | opcode | 32.95 | besu | 103.85 | 3.2× |
| ADDMOD | opcode | 32.98 | besu | 91.12 | 2.8× |
| CALLCODE | opcode | 34.78 | besu | 112.96 | 3.2× |
| CALLDATALOAD | opcode | 35.52 | besu | 77.65 | 2.2× |
| CALL | opcode | 35.60 | besu | 98.94 | 2.8× |
| DELEGATECALL | opcode | 36.30 | besu | 127.70 | 3.5× |
| SELFDESTRUCT | opcode | 36.65 | besu | 628.81 | 17.2× |
| STATICCALL | opcode | 37.60 | besu | 105.77 | 2.8× |
| CALLDATACOPY | opcode | 38.08 | besu | 193.12 | 5.1× |
| SHL | opcode | 39.64 | besu | 136.58 | 3.4× |
| SHR | opcode | 41.84 | besu | 134.38 | 3.2× |
| XOR | opcode | 47.34 | besu | 122.21 | 2.6× |
| SHA2-256 | precompile | 52.29 | besu | 235.32 | 4.5× |
| AND | opcode | 54.66 | besu | 122.87 | 2.2× |
| identity | precompile | 54.74 | besu | 178.01 | 3.3× |
| OR | opcode | 54.91 | besu | 126.59 | 2.3× |
| TLOAD | opcode | 55.90 | erigon | 789.42 | 14.1× |
| CALLDATASIZE | opcode | 56.91 | besu | 134.27 | 2.4× |
| MSTORE | opcode | 57.07 | besu | 145.72 | 2.6× |
| ecMul | precompile | 58.66 | reth | 90.32 | 1.5× |

The next step is to reach out to the individual clients and assess the reason for the slow performance and whether it can be improved by Glamsterdam.

#### Client feedback

The Besu team provided the following feedback:

- They are not yet able to reproduce the numbers for `EQ`, so more analysis here is needed.
- They are already working on optimizing arithmetic operations (e.g. `MOD`, `SMOD`, `ADDMOD`, `MULMOD`, `DIV`, `SDIV`, `MUL` and `SUB`). They expect the performance to improve with new `Uint256` implementation.
- They proposed to add to the repricing table all the `DIV` related opcodes as they are more complex than simple arithmetic like `ADD` and based on the same algorithm. The list of these operations is `MOD`, `SMOD`, `ADDMOD`, `MULMOD`, `DIV`, and `SDIV`.
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7904/included_operations</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7904/included_operations</guid>
      </item>
    
      <item>
        <title>New gas cost proposal for EIP-7904</title>
        <category>/</category>
        
        <description>
New gas cost proposal for EIP-7904
==================================



This is an automated report generated from the script `./src/estimate_7904_repricings.py`. 
The script uses the runtime estimation output generated by this script. 
The report with the runtime estimation results can be found in 
`./reports/eip-7904/2026-01-15_2026-01-29/runtime_estimation_autogenerated_report.md`.

## Methodology



New gas costs are calculated using an anchor rate of **60 million gas per second**,
which represents a target execution rate for EVM operations. The formula used is:

```
new_gas = (anchor_rate * runtime_ms) / 1000
```

Where `runtime_ms` is the estimated runtime in milliseconds from the regression models.

## Understanding the results



The table below shows the **worst-case** gas costs across all tested clients (taking the maximum
estimated cost per operation). This conservative approach ensures that the new gas costs account
for the slowest implementation among the major Ethereum clients.

The **Change** column shows the relative change as a decimal (e.g., 1.0 = 100% increase, 0.5 = 50% increase,
-0.25 = 25% decrease). Operations with `inf` indicate costs going from 0 to a positive value.

Only operations and parameters with good model fits (R² &gt; 0.5 and p-value &lt; 0.05) are included
in the gas cost proposals. Operations with poor model fits are listed separately in the
&quot;Errors and caveats&quot; section.

## New gas proposal


The following table shows the new gas cost for all operations and parameters with a good model fit.


|Opcode|Parameter|Current Gas|New Gas (Rounded)|Change|
| :---: | :---: | :---: | :---: | :---: |
|ADDMOD|constant|8|8|0.0|
|BLAKE2F|constant|0|170|inf|
|BLAKE2F|num_rounds|1|2|1.0|
|BLS12_G1ADD|constant|375|643|0.71|
|BLS12_G2ADD|constant|600|765|0.27|
|DIV|constant|5|15|2.0|
|ECADD|constant|150|314|1.09|
|ECPAIRING|constant|45000|34710|-0.23|
|ECPAIRING|num_pairs|34000|34103|0.0|
|ECRECOVER|constant|3000|2904|-0.03|
|KECCAK256|constant|30|45|0.5|
|KECCAK256|msg_size|6|1|-0.83|
|MOD|constant|5|12|1.4|
|MULMOD|constant|8|11|0.38|
|POINT_EVALUATION|constant|50000|89363|0.79|
|SDIV|constant|5|20|3.0|
|SMOD|constant|5|3|-0.4|

## Gas costs by client


The following plot shows the new gas costs (rounded) for each operation parameter across different clients, with error bars representing the confidence intervals.


![Gas costs by client](/EIPs/assets/eip-7904/runtime_estimation/2026-01-15_2026-01-29/figs/gas_costs_by_client.png)
## Errors and caveats


All parameters had a good model fit.



The following operations have no estimation for the following clients:


- BLAKE2F: erigon

- BLS12_G1ADD: erigon

- BLS12_G2ADD: erigon

- ECADD: erigon

- ECPAIRING: erigon

- ECRECOVER: erigon

- POINT_EVALUATION: erigon
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7904/runtime_estimation/2026-01-15_2026-01-29/new_gas_proposal</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7904/runtime_estimation/2026-01-15_2026-01-29/new_gas_proposal</guid>
      </item>
    
      <item>
        <title>Operation run times estimation results - EIP-7904</title>
        <category>/</category>
        
        <description>
Operation run times estimation results - EIP-7904
=================================================

Table of contents
=================

* [MULMOD](#mulmod)
* [ADDMOD](#addmod)
* [SMOD](#smod)
* [MOD](#mod)
* [SMOD](#smod)
* [DIV](#div)
* [SDIV](#sdiv)
* [POINT_EVALUATION](#point_evaluation)
* [BLS12_G1ADD](#bls12_g1add)
* [BLS12_G2ADD](#bls12_g2add)
* [ECADD](#ecadd)
* [ECRECOVER](#ecrecover)
* [KECCAK256](#keccak256)
* [BLAKE2F](#blake2f)
* [ECPAIRING](#ecpairing)

# Introduction



This is an automated report generated from the opcode run times
estimation script `./src/estimate_7904_repricings.py`. The script
uses data generated by running the
[EEST benchmark suite](https://github.com/ethereum/execution-spec-tests/tree/main/tests/benchmark)
with the [Nethermind benchmarking tooling](https://github.com/NethermindEth/gas-benchmarks).

The data includes all the tests for operations repriced in EIP-7904 run
between 2026-01-15 and 2026-01-29.

For each operation and client, an NNLS linear regression model is fitted to estimate the
operation run time as a function of the operation count and other operation-specific parameters
(e.g., number of rounds for BLAKE2F, message size for KECCAK256, number of pairs for ECPAIRING).
The results are presented below.

# How to Interpret the Results

## Model Used



**Non-Negative Least Squares (NNLS) Linear Regression** is used to estimate operation runtimes.
This model ensures all coefficients are non-negative, which is physically meaningful since
execution time cannot be negative. The model estimates runtime as a linear combination of:

- **Constant term (intercept)**: Base overhead for executing the test, which includes setup and teardown time
- **Operation count (slope)**: Number of times the operation is executed in the test. This paramater 
is the one that allows us to estimate the per-operation runtime.
- **Operation-specific parameters**: Variables like number of rounds, message size, or number of pairs

For simple operations, the model estimates: `runtime = intercept + slope × operation_count`

For variable operations, the model estimates: `runtime = intercept + slope × operation_count +
 param1_coef × operation_count × param1 + param2_coef × operation_count × param2 + ...`

## Model Quality Metrics



Each model reports two key metrics to assess the quality of the fit:

**R² (R-squared / Coefficient of Determination)**
- Ranges from 0 to 1 (or can be negative for very poor fits)
- Measures how well the model explains the variance in the data
- **Interpretation**:
  - R² &gt; 0.9: Excellent fit - the model explains &gt;90% of the variance
  - R² &gt; 0.7: Good fit - the model captures most of the relationship
  - R² &gt; 0.5: Acceptable fit - the model has predictive power but notable variance remains
  - R² &lt; 0.5: Poor fit - the model may not be reliable

**p-value**
- Tests the statistical significance of each coefficient, based on a bootstrap sample estimation
- **Interpretation**:
  - p &lt; 0.05: Statistically significant - the parameter has a real effect on runtime
  - p ≥ 0.05: Not significant - the parameter&apos;s effect cannot be distinguished from random noise

We also plot some diagnostic graphs for each operation and client combination to visually assess the model fit.

# MULMOD

## reth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.989
Model:                  NNLS                    Adj. R-squared:          0.989
No. Observations:       320                               RMSE:          36.73
Df Residuals:           318                                MAE:          24.25
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     31.4231      2.9149       0.000     25.5657     37.3067
       opcount      0.0000      0.0000       0.000      0.0000      0.0000
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/MULMOD_reth_regression.png&quot; alt=&quot;MULMOD_reth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/MULMOD_reth_diagnostics.png&quot; alt=&quot;MULMOD_reth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/MULMOD_reth_bootstrap.png&quot; alt=&quot;MULMOD_reth_bootstrap&quot; width=&quot;600&quot;/&gt;


## nethermind


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.986
Model:                  NNLS                    Adj. R-squared:          0.986
No. Observations:       430                               RMSE:          66.34
Df Residuals:           428                                MAE:          42.28
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     28.6369      4.5129       0.000     20.2732     37.8599
       opcount      0.0001      0.0000       0.000      0.0001      0.0001
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/MULMOD_nethermind_regression.png&quot; alt=&quot;MULMOD_nethermind_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/MULMOD_nethermind_diagnostics.png&quot; alt=&quot;MULMOD_nethermind_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/MULMOD_nethermind_bootstrap.png&quot; alt=&quot;MULMOD_nethermind_bootstrap&quot; width=&quot;600&quot;/&gt;


## geth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.990
Model:                  NNLS                    Adj. R-squared:          0.990
No. Observations:       430                               RMSE:          59.81
Df Residuals:           428                                MAE:          38.26
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     31.0378      3.9965       0.000     23.1553     38.7857
       opcount      0.0001      0.0000       0.000      0.0001      0.0001
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/MULMOD_geth_regression.png&quot; alt=&quot;MULMOD_geth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/MULMOD_geth_diagnostics.png&quot; alt=&quot;MULMOD_geth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/MULMOD_geth_bootstrap.png&quot; alt=&quot;MULMOD_geth_bootstrap&quot; width=&quot;600&quot;/&gt;


## besu


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.980
Model:                  NNLS                    Adj. R-squared:          0.980
No. Observations:       430                               RMSE:         217.33
Df Residuals:           428                                MAE:         156.62
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     40.8901     15.5092       0.005     13.5016     72.9058
       opcount      0.0002      0.0000       0.000      0.0002      0.0002
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/MULMOD_besu_regression.png&quot; alt=&quot;MULMOD_besu_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/MULMOD_besu_diagnostics.png&quot; alt=&quot;MULMOD_besu_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/MULMOD_besu_bootstrap.png&quot; alt=&quot;MULMOD_besu_bootstrap&quot; width=&quot;600&quot;/&gt;


## erigon


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          1.000
Model:                  NNLS                    Adj. R-squared:          1.000
No. Observations:       30                                RMSE:          11.20
Df Residuals:           28                                 MAE:           7.82
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     27.7081      3.5287       0.000     20.3352     34.1970
       opcount      0.0001      0.0000       0.000      0.0001      0.0001
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/MULMOD_erigon_regression.png&quot; alt=&quot;MULMOD_erigon_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/MULMOD_erigon_diagnostics.png&quot; alt=&quot;MULMOD_erigon_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/MULMOD_erigon_bootstrap.png&quot; alt=&quot;MULMOD_erigon_bootstrap&quot; width=&quot;600&quot;/&gt;


# ADDMOD

## reth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.991
Model:                  NNLS                    Adj. R-squared:          0.991
No. Observations:       320                               RMSE:          26.74
Df Residuals:           318                                MAE:          17.69
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     32.2943      2.0437       0.000     28.3926     36.4658
       opcount      0.0000      0.0000       0.000      0.0000      0.0000
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/ADDMOD_reth_regression.png&quot; alt=&quot;ADDMOD_reth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ADDMOD_reth_diagnostics.png&quot; alt=&quot;ADDMOD_reth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ADDMOD_reth_bootstrap.png&quot; alt=&quot;ADDMOD_reth_bootstrap&quot; width=&quot;600&quot;/&gt;


## nethermind


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.986
Model:                  NNLS                    Adj. R-squared:          0.986
No. Observations:       430                               RMSE:          40.36
Df Residuals:           428                                MAE:          22.15
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     26.2244      3.2736       0.000     19.5882     32.3655
       opcount      0.0000      0.0000       0.000      0.0000      0.0000
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/ADDMOD_nethermind_regression.png&quot; alt=&quot;ADDMOD_nethermind_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ADDMOD_nethermind_diagnostics.png&quot; alt=&quot;ADDMOD_nethermind_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ADDMOD_nethermind_bootstrap.png&quot; alt=&quot;ADDMOD_nethermind_bootstrap&quot; width=&quot;600&quot;/&gt;


## geth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.989
Model:                  NNLS                    Adj. R-squared:          0.989
No. Observations:       430                               RMSE:          57.35
Df Residuals:           428                                MAE:          36.68
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     32.5766      3.9405       0.000     25.0283     40.1535
       opcount      0.0001      0.0000       0.000      0.0001      0.0001
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/ADDMOD_geth_regression.png&quot; alt=&quot;ADDMOD_geth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ADDMOD_geth_diagnostics.png&quot; alt=&quot;ADDMOD_geth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ADDMOD_geth_bootstrap.png&quot; alt=&quot;ADDMOD_geth_bootstrap&quot; width=&quot;600&quot;/&gt;


## besu


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.980
Model:                  NNLS                    Adj. R-squared:          0.979
No. Observations:       430                               RMSE:         181.34
Df Residuals:           428                                MAE:         130.22
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     35.6849     13.0733       0.006      8.6600     60.3857
       opcount      0.0001      0.0000       0.000      0.0001      0.0001
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/ADDMOD_besu_regression.png&quot; alt=&quot;ADDMOD_besu_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ADDMOD_besu_diagnostics.png&quot; alt=&quot;ADDMOD_besu_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ADDMOD_besu_bootstrap.png&quot; alt=&quot;ADDMOD_besu_bootstrap&quot; width=&quot;600&quot;/&gt;


## erigon


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          1.000
Model:                  NNLS                    Adj. R-squared:          0.999
No. Observations:       30                                RMSE:          13.39
Df Residuals:           28                                 MAE:          11.06
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     29.4920      3.4449       0.000     22.3475     35.8904
       opcount      0.0001      0.0000       0.000      0.0001      0.0001
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/ADDMOD_erigon_regression.png&quot; alt=&quot;ADDMOD_erigon_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ADDMOD_erigon_diagnostics.png&quot; alt=&quot;ADDMOD_erigon_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ADDMOD_erigon_bootstrap.png&quot; alt=&quot;ADDMOD_erigon_bootstrap&quot; width=&quot;600&quot;/&gt;


# SMOD

## reth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.986
Model:                  NNLS                    Adj. R-squared:          0.986
No. Observations:       320                               RMSE:          13.38
Df Residuals:           318                                MAE:           9.28
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     31.8194      1.2095       0.000     29.4033     34.1328
       opcount      0.0000      0.0000       0.000      0.0000      0.0000
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/SMOD_reth_regression.png&quot; alt=&quot;SMOD_reth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SMOD_reth_diagnostics.png&quot; alt=&quot;SMOD_reth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SMOD_reth_bootstrap.png&quot; alt=&quot;SMOD_reth_bootstrap&quot; width=&quot;600&quot;/&gt;


## nethermind


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.985
Model:                  NNLS                    Adj. R-squared:          0.985
No. Observations:       430                               RMSE:          16.88
Df Residuals:           428                                MAE:          11.30
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     30.3208      1.1754       0.000     28.1543     32.6954
       opcount      0.0000      0.0000       0.000      0.0000      0.0000
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/SMOD_nethermind_regression.png&quot; alt=&quot;SMOD_nethermind_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SMOD_nethermind_diagnostics.png&quot; alt=&quot;SMOD_nethermind_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SMOD_nethermind_bootstrap.png&quot; alt=&quot;SMOD_nethermind_bootstrap&quot; width=&quot;600&quot;/&gt;


## geth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.958
Model:                  NNLS                    Adj. R-squared:          0.958
No. Observations:       430                               RMSE:          54.31
Df Residuals:           428                                MAE:          26.24
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     33.3730      3.1894       0.000     27.0449     39.4705
       opcount      0.0000      0.0000       0.000      0.0000      0.0000
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/SMOD_geth_regression.png&quot; alt=&quot;SMOD_geth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SMOD_geth_diagnostics.png&quot; alt=&quot;SMOD_geth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SMOD_geth_bootstrap.png&quot; alt=&quot;SMOD_geth_bootstrap&quot; width=&quot;600&quot;/&gt;


## besu


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.984
Model:                  NNLS                    Adj. R-squared:          0.984
No. Observations:       430                               RMSE:          44.74
Df Residuals:           428                                MAE:          31.00
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     30.3917      3.3060       0.000     23.9998     36.2517
       opcount      0.0000      0.0000       0.000      0.0000      0.0000
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/SMOD_besu_regression.png&quot; alt=&quot;SMOD_besu_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SMOD_besu_diagnostics.png&quot; alt=&quot;SMOD_besu_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SMOD_besu_bootstrap.png&quot; alt=&quot;SMOD_besu_bootstrap&quot; width=&quot;600&quot;/&gt;


## erigon


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.993
Model:                  NNLS                    Adj. R-squared:          0.992
No. Observations:       30                                RMSE:          24.50
Df Residuals:           28                                 MAE:          11.61
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     22.2938      6.5115       0.011      5.7869     31.2411
       opcount      0.0000      0.0000       0.000      0.0000      0.0000
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/SMOD_erigon_regression.png&quot; alt=&quot;SMOD_erigon_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SMOD_erigon_diagnostics.png&quot; alt=&quot;SMOD_erigon_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SMOD_erigon_bootstrap.png&quot; alt=&quot;SMOD_erigon_bootstrap&quot; width=&quot;600&quot;/&gt;


# MOD

## reth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.991
Model:                  NNLS                    Adj. R-squared:          0.991
No. Observations:       320                               RMSE:          31.06
Df Residuals:           318                                MAE:          20.79
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     34.6663      2.5633       0.000     29.9558     39.6959
       opcount      0.0000      0.0000       0.000      0.0000      0.0000
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/MOD_reth_regression.png&quot; alt=&quot;MOD_reth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/MOD_reth_diagnostics.png&quot; alt=&quot;MOD_reth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/MOD_reth_bootstrap.png&quot; alt=&quot;MOD_reth_bootstrap&quot; width=&quot;600&quot;/&gt;


## nethermind


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.990
Model:                  NNLS                    Adj. R-squared:          0.990
No. Observations:       430                               RMSE:          40.16
Df Residuals:           428                                MAE:          24.83
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     30.1414      2.7993       0.000     24.6640     35.4751
       opcount      0.0000      0.0000       0.000      0.0000      0.0000
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/MOD_nethermind_regression.png&quot; alt=&quot;MOD_nethermind_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/MOD_nethermind_diagnostics.png&quot; alt=&quot;MOD_nethermind_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/MOD_nethermind_bootstrap.png&quot; alt=&quot;MOD_nethermind_bootstrap&quot; width=&quot;600&quot;/&gt;


## geth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.985
Model:                  NNLS                    Adj. R-squared:          0.985
No. Observations:       430                               RMSE:          56.92
Df Residuals:           428                                MAE:          33.00
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     33.6655      3.9946       0.000     26.0844     42.2995
       opcount      0.0001      0.0000       0.000      0.0001      0.0001
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/MOD_geth_regression.png&quot; alt=&quot;MOD_geth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/MOD_geth_diagnostics.png&quot; alt=&quot;MOD_geth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/MOD_geth_bootstrap.png&quot; alt=&quot;MOD_geth_bootstrap&quot; width=&quot;600&quot;/&gt;


## besu


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.977
Model:                  NNLS                    Adj. R-squared:          0.977
No. Observations:       430                               RMSE:         257.81
Df Residuals:           428                                MAE:         180.30
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     42.7935     18.3770       0.013      4.6972     78.3645
       opcount      0.0002      0.0000       0.000      0.0002      0.0002
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/MOD_besu_regression.png&quot; alt=&quot;MOD_besu_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/MOD_besu_diagnostics.png&quot; alt=&quot;MOD_besu_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/MOD_besu_bootstrap.png&quot; alt=&quot;MOD_besu_bootstrap&quot; width=&quot;600&quot;/&gt;


## erigon


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.996
Model:                  NNLS                    Adj. R-squared:          0.996
No. Observations:       30                                RMSE:          30.18
Df Residuals:           28                                 MAE:          21.90
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     39.0732      8.3577       0.000     22.2512     55.7676
       opcount      0.0001      0.0000       0.000      0.0001      0.0001
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/MOD_erigon_regression.png&quot; alt=&quot;MOD_erigon_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/MOD_erigon_diagnostics.png&quot; alt=&quot;MOD_erigon_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/MOD_erigon_bootstrap.png&quot; alt=&quot;MOD_erigon_bootstrap&quot; width=&quot;600&quot;/&gt;


# SMOD

## reth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.986
Model:                  NNLS                    Adj. R-squared:          0.986
No. Observations:       320                               RMSE:          13.38
Df Residuals:           318                                MAE:           9.28
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     31.8194      1.2095       0.000     29.4033     34.1328
       opcount      0.0000      0.0000       0.000      0.0000      0.0000
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/SMOD_reth_regression.png&quot; alt=&quot;SMOD_reth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SMOD_reth_diagnostics.png&quot; alt=&quot;SMOD_reth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SMOD_reth_bootstrap.png&quot; alt=&quot;SMOD_reth_bootstrap&quot; width=&quot;600&quot;/&gt;


## nethermind


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.985
Model:                  NNLS                    Adj. R-squared:          0.985
No. Observations:       430                               RMSE:          16.88
Df Residuals:           428                                MAE:          11.30
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     30.3208      1.1754       0.000     28.1543     32.6954
       opcount      0.0000      0.0000       0.000      0.0000      0.0000
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/SMOD_nethermind_regression.png&quot; alt=&quot;SMOD_nethermind_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SMOD_nethermind_diagnostics.png&quot; alt=&quot;SMOD_nethermind_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SMOD_nethermind_bootstrap.png&quot; alt=&quot;SMOD_nethermind_bootstrap&quot; width=&quot;600&quot;/&gt;


## geth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.958
Model:                  NNLS                    Adj. R-squared:          0.958
No. Observations:       430                               RMSE:          54.31
Df Residuals:           428                                MAE:          26.24
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     33.3730      3.1894       0.000     27.0449     39.4705
       opcount      0.0000      0.0000       0.000      0.0000      0.0000
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/SMOD_geth_regression.png&quot; alt=&quot;SMOD_geth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SMOD_geth_diagnostics.png&quot; alt=&quot;SMOD_geth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SMOD_geth_bootstrap.png&quot; alt=&quot;SMOD_geth_bootstrap&quot; width=&quot;600&quot;/&gt;


## besu


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.984
Model:                  NNLS                    Adj. R-squared:          0.984
No. Observations:       430                               RMSE:          44.74
Df Residuals:           428                                MAE:          31.00
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     30.3917      3.3060       0.000     23.9998     36.2517
       opcount      0.0000      0.0000       0.000      0.0000      0.0000
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/SMOD_besu_regression.png&quot; alt=&quot;SMOD_besu_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SMOD_besu_diagnostics.png&quot; alt=&quot;SMOD_besu_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SMOD_besu_bootstrap.png&quot; alt=&quot;SMOD_besu_bootstrap&quot; width=&quot;600&quot;/&gt;


## erigon


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.993
Model:                  NNLS                    Adj. R-squared:          0.992
No. Observations:       30                                RMSE:          24.50
Df Residuals:           28                                 MAE:          11.61
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     22.2938      6.5115       0.011      5.7869     31.2411
       opcount      0.0000      0.0000       0.000      0.0000      0.0000
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/SMOD_erigon_regression.png&quot; alt=&quot;SMOD_erigon_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SMOD_erigon_diagnostics.png&quot; alt=&quot;SMOD_erigon_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SMOD_erigon_bootstrap.png&quot; alt=&quot;SMOD_erigon_bootstrap&quot; width=&quot;600&quot;/&gt;


# DIV

## reth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.991
Model:                  NNLS                    Adj. R-squared:          0.991
No. Observations:       320                               RMSE:          43.95
Df Residuals:           318                                MAE:          27.80
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     33.6486      3.4720       0.000     26.8360     40.5650
       opcount      0.0001      0.0000       0.000      0.0001      0.0001
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/DIV_reth_regression.png&quot; alt=&quot;DIV_reth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/DIV_reth_diagnostics.png&quot; alt=&quot;DIV_reth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/DIV_reth_bootstrap.png&quot; alt=&quot;DIV_reth_bootstrap&quot; width=&quot;600&quot;/&gt;


## nethermind


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.986
Model:                  NNLS                    Adj. R-squared:          0.986
No. Observations:       430                               RMSE:          64.73
Df Residuals:           428                                MAE:          39.87
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     30.8596      4.4705       0.000     22.2831     39.8098
       opcount      0.0001      0.0000       0.000      0.0001      0.0001
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/DIV_nethermind_regression.png&quot; alt=&quot;DIV_nethermind_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/DIV_nethermind_diagnostics.png&quot; alt=&quot;DIV_nethermind_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/DIV_nethermind_bootstrap.png&quot; alt=&quot;DIV_nethermind_bootstrap&quot; width=&quot;600&quot;/&gt;


## geth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.986
Model:                  NNLS                    Adj. R-squared:          0.986
No. Observations:       430                               RMSE:          70.49
Df Residuals:           428                                MAE:          44.11
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     31.4015      5.1975       0.000     21.3700     41.5393
       opcount      0.0001      0.0000       0.000      0.0001      0.0001
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/DIV_geth_regression.png&quot; alt=&quot;DIV_geth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/DIV_geth_diagnostics.png&quot; alt=&quot;DIV_geth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/DIV_geth_bootstrap.png&quot; alt=&quot;DIV_geth_bootstrap&quot; width=&quot;600&quot;/&gt;


## besu


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.969
Model:                  NNLS                    Adj. R-squared:          0.969
No. Observations:       430                               RMSE:         377.34
Df Residuals:           428                                MAE:         276.74
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     41.3458     25.1943       0.060      0.0000     93.7752
       opcount      0.0002      0.0000       0.000      0.0002      0.0002
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/DIV_besu_regression.png&quot; alt=&quot;DIV_besu_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/DIV_besu_diagnostics.png&quot; alt=&quot;DIV_besu_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/DIV_besu_bootstrap.png&quot; alt=&quot;DIV_besu_bootstrap&quot; width=&quot;600&quot;/&gt;


## erigon


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          1.000
Model:                  NNLS                    Adj. R-squared:          1.000
No. Observations:       30                                RMSE:           9.48
Df Residuals:           28                                 MAE:           7.18
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     33.7244      3.4691       0.000     26.9306     40.5072
       opcount      0.0001      0.0000       0.000      0.0001      0.0001
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/DIV_erigon_regression.png&quot; alt=&quot;DIV_erigon_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/DIV_erigon_diagnostics.png&quot; alt=&quot;DIV_erigon_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/DIV_erigon_bootstrap.png&quot; alt=&quot;DIV_erigon_bootstrap&quot; width=&quot;600&quot;/&gt;


# SDIV

## reth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.990
Model:                  NNLS                    Adj. R-squared:          0.990
No. Observations:       320                               RMSE:          57.16
Df Residuals:           318                                MAE:          37.61
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     31.4257      4.5085       0.000     23.0489     41.0961
       opcount      0.0001      0.0000       0.000      0.0001      0.0001
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/SDIV_reth_regression.png&quot; alt=&quot;SDIV_reth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SDIV_reth_diagnostics.png&quot; alt=&quot;SDIV_reth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SDIV_reth_bootstrap.png&quot; alt=&quot;SDIV_reth_bootstrap&quot; width=&quot;600&quot;/&gt;


## nethermind


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.977
Model:                  NNLS                    Adj. R-squared:          0.977
No. Observations:       430                               RMSE:         108.13
Df Residuals:           428                                MAE:          70.48
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     28.3499      7.6774       0.000     11.8263     42.8811
       opcount      0.0001      0.0000       0.000      0.0001      0.0001
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/SDIV_nethermind_regression.png&quot; alt=&quot;SDIV_nethermind_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SDIV_nethermind_diagnostics.png&quot; alt=&quot;SDIV_nethermind_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SDIV_nethermind_bootstrap.png&quot; alt=&quot;SDIV_nethermind_bootstrap&quot; width=&quot;600&quot;/&gt;


## geth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.988
Model:                  NNLS                    Adj. R-squared:          0.988
No. Observations:       430                               RMSE:          68.54
Df Residuals:           428                                MAE:          42.44
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     28.0247      5.5172       0.000     17.2510     38.4472
       opcount      0.0001      0.0000       0.000      0.0001      0.0001
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/SDIV_geth_regression.png&quot; alt=&quot;SDIV_geth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SDIV_geth_diagnostics.png&quot; alt=&quot;SDIV_geth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SDIV_geth_bootstrap.png&quot; alt=&quot;SDIV_geth_bootstrap&quot; width=&quot;600&quot;/&gt;


## besu


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.971
Model:                  NNLS                    Adj. R-squared:          0.971
No. Observations:       430                               RMSE:         483.08
Df Residuals:           428                                MAE:         335.85
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     26.4209     27.4641       0.233      0.0000     90.8952
       opcount      0.0003      0.0000       0.000      0.0003      0.0003
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/SDIV_besu_regression.png&quot; alt=&quot;SDIV_besu_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SDIV_besu_diagnostics.png&quot; alt=&quot;SDIV_besu_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SDIV_besu_bootstrap.png&quot; alt=&quot;SDIV_besu_bootstrap&quot; width=&quot;600&quot;/&gt;


## erigon


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.999
Model:                  NNLS                    Adj. R-squared:          0.999
No. Observations:       30                                RMSE:          17.05
Df Residuals:           28                                 MAE:          12.01
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     32.0771      5.4484       0.000     23.3307     44.2564
       opcount      0.0001      0.0000       0.000      0.0001      0.0001
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/SDIV_erigon_regression.png&quot; alt=&quot;SDIV_erigon_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SDIV_erigon_diagnostics.png&quot; alt=&quot;SDIV_erigon_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/SDIV_erigon_bootstrap.png&quot; alt=&quot;SDIV_erigon_bootstrap&quot; width=&quot;600&quot;/&gt;


# POINT_EVALUATION

## reth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.993
Model:                  NNLS                    Adj. R-squared:          0.993
No. Observations:       320                               RMSE:         364.33
Df Residuals:           318                                MAE:         250.88
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     33.9425     27.3986       0.126      0.0000     92.9463
       opcount      1.4861      0.0074       0.000      1.4701      1.4985
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/POINT_EVALUATION_reth_regression.png&quot; alt=&quot;POINT_EVALUATION_reth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/POINT_EVALUATION_reth_diagnostics.png&quot; alt=&quot;POINT_EVALUATION_reth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/POINT_EVALUATION_reth_bootstrap.png&quot; alt=&quot;POINT_EVALUATION_reth_bootstrap&quot; width=&quot;600&quot;/&gt;


## nethermind


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.992
Model:                  NNLS                    Adj. R-squared:          0.992
No. Observations:       430                               RMSE:         391.02
Df Residuals:           428                                MAE:         255.69
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     13.1322     19.5270       0.327      0.0000     65.9079
       opcount      1.4894      0.0059       0.000      1.4750      1.4982
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/POINT_EVALUATION_nethermind_regression.png&quot; alt=&quot;POINT_EVALUATION_nethermind_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/POINT_EVALUATION_nethermind_diagnostics.png&quot; alt=&quot;POINT_EVALUATION_nethermind_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/POINT_EVALUATION_nethermind_bootstrap.png&quot; alt=&quot;POINT_EVALUATION_nethermind_bootstrap&quot; width=&quot;600&quot;/&gt;


## geth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.992
Model:                  NNLS                    Adj. R-squared:          0.992
No. Observations:       430                               RMSE:         388.20
Df Residuals:           428                                MAE:         243.56
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     40.4320     26.1932       0.060      0.0000     99.7871
       opcount      1.4835      0.0071       0.000      1.4683      1.4962
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/POINT_EVALUATION_geth_regression.png&quot; alt=&quot;POINT_EVALUATION_geth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/POINT_EVALUATION_geth_diagnostics.png&quot; alt=&quot;POINT_EVALUATION_geth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/POINT_EVALUATION_geth_bootstrap.png&quot; alt=&quot;POINT_EVALUATION_geth_bootstrap&quot; width=&quot;600&quot;/&gt;


## besu


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.991
Model:                  NNLS                    Adj. R-squared:          0.991
No. Observations:       430                               RMSE:         411.40
Df Residuals:           428                                MAE:         305.87
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     28.5453     24.1757       0.177      0.0000     79.9144
       opcount      1.4843      0.0066       0.000      1.4710      1.4964
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/POINT_EVALUATION_besu_regression.png&quot; alt=&quot;POINT_EVALUATION_besu_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/POINT_EVALUATION_besu_diagnostics.png&quot; alt=&quot;POINT_EVALUATION_besu_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/POINT_EVALUATION_besu_bootstrap.png&quot; alt=&quot;POINT_EVALUATION_besu_bootstrap&quot; width=&quot;600&quot;/&gt;


## erigon

NNLS model did not run... Error: No valid data remaining after dropping NaN values

# BLS12_G1ADD

## reth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.990
Model:                  NNLS                    Adj. R-squared:          0.990
No. Observations:       320                               RMSE:          73.12
Df Residuals:           318                                MAE:          50.37
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     32.8474      6.6176       0.000     19.9333     45.6873
       opcount      0.0051      0.0000       0.000      0.0051      0.0052
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/BLS12_G1ADD_reth_regression.png&quot; alt=&quot;BLS12_G1ADD_reth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/BLS12_G1ADD_reth_diagnostics.png&quot; alt=&quot;BLS12_G1ADD_reth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/BLS12_G1ADD_reth_bootstrap.png&quot; alt=&quot;BLS12_G1ADD_reth_bootstrap&quot; width=&quot;600&quot;/&gt;


## nethermind


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.986
Model:                  NNLS                    Adj. R-squared:          0.986
No. Observations:       430                               RMSE:         100.40
Df Residuals:           428                                MAE:          63.21
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     13.5899      8.7007       0.067      0.0000     31.3154
       opcount      0.0059      0.0000       0.000      0.0058      0.0060
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/BLS12_G1ADD_nethermind_regression.png&quot; alt=&quot;BLS12_G1ADD_nethermind_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/BLS12_G1ADD_nethermind_diagnostics.png&quot; alt=&quot;BLS12_G1ADD_nethermind_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/BLS12_G1ADD_nethermind_bootstrap.png&quot; alt=&quot;BLS12_G1ADD_nethermind_bootstrap&quot; width=&quot;600&quot;/&gt;


## geth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.992
Model:                  NNLS                    Adj. R-squared:          0.992
No. Observations:       430                               RMSE:          66.89
Df Residuals:           428                                MAE:          45.46
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     33.3366      4.9335       0.000     23.4914     42.7542
       opcount      0.0051      0.0000       0.000      0.0051      0.0052
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/BLS12_G1ADD_geth_regression.png&quot; alt=&quot;BLS12_G1ADD_geth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/BLS12_G1ADD_geth_diagnostics.png&quot; alt=&quot;BLS12_G1ADD_geth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/BLS12_G1ADD_geth_bootstrap.png&quot; alt=&quot;BLS12_G1ADD_geth_bootstrap&quot; width=&quot;600&quot;/&gt;


## besu


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.943
Model:                  NNLS                    Adj. R-squared:          0.943
No. Observations:       430                               RMSE:         376.50
Df Residuals:           428                                MAE:         282.35
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const      4.7707     17.4892       0.398      0.0000     58.1477
       opcount      0.0107      0.0001       0.000      0.0104      0.0109
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/BLS12_G1ADD_besu_regression.png&quot; alt=&quot;BLS12_G1ADD_besu_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/BLS12_G1ADD_besu_diagnostics.png&quot; alt=&quot;BLS12_G1ADD_besu_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/BLS12_G1ADD_besu_bootstrap.png&quot; alt=&quot;BLS12_G1ADD_besu_bootstrap&quot; width=&quot;600&quot;/&gt;


## erigon

NNLS model did not run... Error: No valid data remaining after dropping NaN values

# BLS12_G2ADD

## reth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.991
Model:                  NNLS                    Adj. R-squared:          0.991
No. Observations:       320                               RMSE:          60.02
Df Residuals:           318                                MAE:          41.12
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     34.2802      4.9762       0.000     24.8162     44.7806
       opcount      0.0074      0.0000       0.000      0.0073      0.0075
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/BLS12_G2ADD_reth_regression.png&quot; alt=&quot;BLS12_G2ADD_reth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/BLS12_G2ADD_reth_diagnostics.png&quot; alt=&quot;BLS12_G2ADD_reth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/BLS12_G2ADD_reth_bootstrap.png&quot; alt=&quot;BLS12_G2ADD_reth_bootstrap&quot; width=&quot;600&quot;/&gt;


## nethermind


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.990
Model:                  NNLS                    Adj. R-squared:          0.990
No. Observations:       430                               RMSE:          79.95
Df Residuals:           428                                MAE:          52.21
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const      0.0000      2.1068       1.000      0.0000      7.6520
       opcount      0.0092      0.0000       0.000      0.0091      0.0093
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/BLS12_G2ADD_nethermind_regression.png&quot; alt=&quot;BLS12_G2ADD_nethermind_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/BLS12_G2ADD_nethermind_diagnostics.png&quot; alt=&quot;BLS12_G2ADD_nethermind_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/BLS12_G2ADD_nethermind_bootstrap.png&quot; alt=&quot;BLS12_G2ADD_nethermind_bootstrap&quot; width=&quot;600&quot;/&gt;


## geth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.992
Model:                  NNLS                    Adj. R-squared:          0.992
No. Observations:       430                               RMSE:          52.54
Df Residuals:           428                                MAE:          35.01
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     29.6103      3.8388       0.000     22.2773     37.6501
       opcount      0.0070      0.0000       0.000      0.0069      0.0071
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/BLS12_G2ADD_geth_regression.png&quot; alt=&quot;BLS12_G2ADD_geth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/BLS12_G2ADD_geth_diagnostics.png&quot; alt=&quot;BLS12_G2ADD_geth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/BLS12_G2ADD_geth_bootstrap.png&quot; alt=&quot;BLS12_G2ADD_geth_bootstrap&quot; width=&quot;600&quot;/&gt;


## besu


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.958
Model:                  NNLS                    Adj. R-squared:          0.958
No. Observations:       430                               RMSE:         229.33
Df Residuals:           428                                MAE:         173.41
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const      1.9380     11.0376       0.482      0.0000     37.3520
       opcount      0.0127      0.0001       0.000      0.0125      0.0129
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/BLS12_G2ADD_besu_regression.png&quot; alt=&quot;BLS12_G2ADD_besu_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/BLS12_G2ADD_besu_diagnostics.png&quot; alt=&quot;BLS12_G2ADD_besu_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/BLS12_G2ADD_besu_bootstrap.png&quot; alt=&quot;BLS12_G2ADD_besu_bootstrap&quot; width=&quot;600&quot;/&gt;


## erigon

NNLS model did not run... Error: No valid data remaining after dropping NaN values

# ECADD

## reth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.991
Model:                  NNLS                    Adj. R-squared:          0.991
No. Observations:       320                               RMSE:         104.34
Df Residuals:           318                                MAE:          76.32
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     29.7112      8.6267       0.001     13.3779     46.9809
       opcount      0.0038      0.0000       0.000      0.0037      0.0038
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/ECADD_reth_regression.png&quot; alt=&quot;ECADD_reth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ECADD_reth_diagnostics.png&quot; alt=&quot;ECADD_reth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ECADD_reth_bootstrap.png&quot; alt=&quot;ECADD_reth_bootstrap&quot; width=&quot;600&quot;/&gt;


## nethermind


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.986
Model:                  NNLS                    Adj. R-squared:          0.985
No. Observations:       430                               RMSE:          84.76
Df Residuals:           428                                MAE:          55.88
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     14.8697      5.7797       0.005      3.2806     26.1806
       opcount      0.0024      0.0000       0.000      0.0024      0.0025
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/ECADD_nethermind_regression.png&quot; alt=&quot;ECADD_nethermind_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ECADD_nethermind_diagnostics.png&quot; alt=&quot;ECADD_nethermind_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ECADD_nethermind_bootstrap.png&quot; alt=&quot;ECADD_nethermind_bootstrap&quot; width=&quot;600&quot;/&gt;


## geth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.989
Model:                  NNLS                    Adj. R-squared:          0.989
No. Observations:       430                               RMSE:          86.48
Df Residuals:           428                                MAE:          59.62
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     21.6074      6.2813       0.000     10.0396     34.1265
       opcount      0.0029      0.0000       0.000      0.0029      0.0029
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/ECADD_geth_regression.png&quot; alt=&quot;ECADD_geth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ECADD_geth_diagnostics.png&quot; alt=&quot;ECADD_geth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ECADD_geth_bootstrap.png&quot; alt=&quot;ECADD_geth_bootstrap&quot; width=&quot;600&quot;/&gt;


## besu


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.982
Model:                  NNLS                    Adj. R-squared:          0.982
No. Observations:       430                               RMSE:         204.25
Df Residuals:           428                                MAE:         144.53
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     25.9624     13.9894       0.034      0.0000     53.1046
       opcount      0.0052      0.0000       0.000      0.0052      0.0053
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/ECADD_besu_regression.png&quot; alt=&quot;ECADD_besu_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ECADD_besu_diagnostics.png&quot; alt=&quot;ECADD_besu_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ECADD_besu_bootstrap.png&quot; alt=&quot;ECADD_besu_bootstrap&quot; width=&quot;600&quot;/&gt;


## erigon

NNLS model did not run... Error: No valid data remaining after dropping NaN values

# ECRECOVER

## reth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.990
Model:                  NNLS                    Adj. R-squared:          0.990
No. Observations:       320                               RMSE:         106.43
Df Residuals:           318                                MAE:          69.10
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     40.5342      9.2076       0.000     23.0866     59.6352
       opcount      0.0469      0.0003       0.000      0.0463      0.0475
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/ECRECOVER_reth_regression.png&quot; alt=&quot;ECRECOVER_reth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ECRECOVER_reth_diagnostics.png&quot; alt=&quot;ECRECOVER_reth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ECRECOVER_reth_bootstrap.png&quot; alt=&quot;ECRECOVER_reth_bootstrap&quot; width=&quot;600&quot;/&gt;


## nethermind


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.991
Model:                  NNLS                    Adj. R-squared:          0.991
No. Observations:       430                               RMSE:          98.35
Df Residuals:           428                                MAE:          63.25
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     30.1650      6.9901       0.000     16.7049     44.6032
       opcount      0.0446      0.0002       0.000      0.0441      0.0450
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/ECRECOVER_nethermind_regression.png&quot; alt=&quot;ECRECOVER_nethermind_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ECRECOVER_nethermind_diagnostics.png&quot; alt=&quot;ECRECOVER_nethermind_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ECRECOVER_nethermind_bootstrap.png&quot; alt=&quot;ECRECOVER_nethermind_bootstrap&quot; width=&quot;600&quot;/&gt;


## geth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.993
Model:                  NNLS                    Adj. R-squared:          0.993
No. Observations:       430                               RMSE:          94.49
Df Residuals:           428                                MAE:          63.08
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     36.6028      6.4618       0.000     24.6673     49.6262
       opcount      0.0480      0.0002       0.000      0.0477      0.0484
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/ECRECOVER_geth_regression.png&quot; alt=&quot;ECRECOVER_geth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ECRECOVER_geth_diagnostics.png&quot; alt=&quot;ECRECOVER_geth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ECRECOVER_geth_bootstrap.png&quot; alt=&quot;ECRECOVER_geth_bootstrap&quot; width=&quot;600&quot;/&gt;


## besu


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.985
Model:                  NNLS                    Adj. R-squared:          0.985
No. Observations:       430                               RMSE:         135.74
Df Residuals:           428                                MAE:          91.87
Df Model:               1      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     29.7974      9.8595       0.001     11.3764     49.1138
       opcount      0.0484      0.0003       0.000      0.0478      0.0490
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/ECRECOVER_besu_regression.png&quot; alt=&quot;ECRECOVER_besu_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ECRECOVER_besu_diagnostics.png&quot; alt=&quot;ECRECOVER_besu_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ECRECOVER_besu_bootstrap.png&quot; alt=&quot;ECRECOVER_besu_bootstrap&quot; width=&quot;600&quot;/&gt;


## erigon

NNLS model did not run... Error: No valid data remaining after dropping NaN values

# KECCAK256

## reth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.993
Model:                  NNLS                    Adj. R-squared:          0.993
No. Observations:       5120                              RMSE:          59.67
Df Residuals:           5117                               MAE:          39.23
Df Model:               2      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     30.8731      1.1967       0.000     28.6487     33.2196
       opcount      0.0000      0.0000       0.000      0.0000      0.0000
      msg_size      0.0000      0.0000       0.000      0.0000      0.0000
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/KECCAK256_reth_regression.png&quot; alt=&quot;KECCAK256_reth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/KECCAK256_reth_diagnostics.png&quot; alt=&quot;KECCAK256_reth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/KECCAK256_reth_bootstrap.png&quot; alt=&quot;KECCAK256_reth_bootstrap&quot; width=&quot;600&quot;/&gt;


## nethermind


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.985
Model:                  NNLS                    Adj. R-squared:          0.985
No. Observations:       6880                              RMSE:          98.77
Df Residuals:           6877                               MAE:          77.41
Df Model:               2      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     27.1124      1.7795       0.000     23.5517     30.5938
       opcount      0.0000      0.0000       0.000      0.0000      0.0000
      msg_size      0.0000      0.0000       0.000      0.0000      0.0000
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/KECCAK256_nethermind_regression.png&quot; alt=&quot;KECCAK256_nethermind_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/KECCAK256_nethermind_diagnostics.png&quot; alt=&quot;KECCAK256_nethermind_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/KECCAK256_nethermind_bootstrap.png&quot; alt=&quot;KECCAK256_nethermind_bootstrap&quot; width=&quot;600&quot;/&gt;


## geth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.925
Model:                  NNLS                    Adj. R-squared:          0.925
No. Observations:       6880                              RMSE:         239.33
Df Residuals:           6877                               MAE:         168.50
Df Model:               2      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const      7.8135      4.3612       0.044      0.0000     16.3268
       opcount      0.0005      0.0000       0.000      0.0005      0.0005
      msg_size      0.0000      0.0000       0.000      0.0000      0.0000
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/KECCAK256_geth_regression.png&quot; alt=&quot;KECCAK256_geth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/KECCAK256_geth_diagnostics.png&quot; alt=&quot;KECCAK256_geth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/KECCAK256_geth_bootstrap.png&quot; alt=&quot;KECCAK256_geth_bootstrap&quot; width=&quot;600&quot;/&gt;


## besu


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.955
Model:                  NNLS                    Adj. R-squared:          0.955
No. Observations:       6880                              RMSE:         263.59
Df Residuals:           6877                               MAE:         198.95
Df Model:               2      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const      5.8207      4.2703       0.096      0.0000     14.6842
       opcount      0.0007      0.0000       0.000      0.0007      0.0007
      msg_size      0.0000      0.0000       0.000      0.0000      0.0000
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/KECCAK256_besu_regression.png&quot; alt=&quot;KECCAK256_besu_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/KECCAK256_besu_diagnostics.png&quot; alt=&quot;KECCAK256_besu_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/KECCAK256_besu_bootstrap.png&quot; alt=&quot;KECCAK256_besu_bootstrap&quot; width=&quot;600&quot;/&gt;


## erigon


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.947
Model:                  NNLS                    Adj. R-squared:          0.947
No. Observations:       480                               RMSE:         189.92
Df Residuals:           477                                MAE:         154.33
Df Model:               2      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     11.2532     10.4939       0.175      0.0000     35.1932
       opcount      0.0004      0.0000       0.000      0.0004      0.0005
      msg_size      0.0000      0.0000       0.000      0.0000      0.0000
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/KECCAK256_erigon_regression.png&quot; alt=&quot;KECCAK256_erigon_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/KECCAK256_erigon_diagnostics.png&quot; alt=&quot;KECCAK256_erigon_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/KECCAK256_erigon_bootstrap.png&quot; alt=&quot;KECCAK256_erigon_bootstrap&quot; width=&quot;600&quot;/&gt;


# BLAKE2F

## reth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.952
Model:                  NNLS                    Adj. R-squared:          0.952
No. Observations:       1280                              RMSE:         115.39
Df Residuals:           1277                               MAE:          92.63
Df Model:               2      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     14.8301      4.6685       0.001      5.5662     24.3891
       opcount      0.0006      0.0000       0.000      0.0006      0.0006
    num_rounds      0.0000      0.0000       0.000      0.0000      0.0000
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/BLAKE2F_reth_regression.png&quot; alt=&quot;BLAKE2F_reth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/BLAKE2F_reth_diagnostics.png&quot; alt=&quot;BLAKE2F_reth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/BLAKE2F_reth_bootstrap.png&quot; alt=&quot;BLAKE2F_reth_bootstrap&quot; width=&quot;600&quot;/&gt;


## nethermind


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.977
Model:                  NNLS                    Adj. R-squared:          0.977
No. Observations:       1720                              RMSE:          77.08
Df Residuals:           1717                               MAE:          54.97
Df Model:               2      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const      0.0000      0.0000       1.000      0.0000      0.0000
       opcount      0.0007      0.0000       0.000      0.0007      0.0007
    num_rounds      0.0000      0.0000       0.000      0.0000      0.0000
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/BLAKE2F_nethermind_regression.png&quot; alt=&quot;BLAKE2F_nethermind_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/BLAKE2F_nethermind_diagnostics.png&quot; alt=&quot;BLAKE2F_nethermind_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/BLAKE2F_nethermind_bootstrap.png&quot; alt=&quot;BLAKE2F_nethermind_bootstrap&quot; width=&quot;600&quot;/&gt;


## geth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.988
Model:                  NNLS                    Adj. R-squared:          0.988
No. Observations:       1720                              RMSE:          56.02
Df Residuals:           1717                               MAE:          41.08
Df Model:               2      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     17.6718      1.9910       0.000     13.6075     21.6085
       opcount      0.0007      0.0000       0.000      0.0007      0.0007
    num_rounds      0.0000      0.0000       0.000      0.0000      0.0000
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/BLAKE2F_geth_regression.png&quot; alt=&quot;BLAKE2F_geth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/BLAKE2F_geth_diagnostics.png&quot; alt=&quot;BLAKE2F_geth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/BLAKE2F_geth_bootstrap.png&quot; alt=&quot;BLAKE2F_geth_bootstrap&quot; width=&quot;600&quot;/&gt;


## besu


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.975
Model:                  NNLS                    Adj. R-squared:          0.975
No. Observations:       1720                              RMSE:         277.67
Df Residuals:           1717                               MAE:         196.53
Df Model:               2      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     62.5567     10.3996       0.000     42.2762     82.6965
       opcount      0.0028      0.0000       0.000      0.0028      0.0028
    num_rounds      0.0000      0.0000       0.000      0.0000      0.0000
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/BLAKE2F_besu_regression.png&quot; alt=&quot;BLAKE2F_besu_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/BLAKE2F_besu_diagnostics.png&quot; alt=&quot;BLAKE2F_besu_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/BLAKE2F_besu_bootstrap.png&quot; alt=&quot;BLAKE2F_besu_bootstrap&quot; width=&quot;600&quot;/&gt;


## erigon

NNLS model did not run... Error: No valid data remaining after dropping NaN values

# ECPAIRING

## reth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.988
Model:                  NNLS                    Adj. R-squared:          0.988
No. Observations:       1432                              RMSE:          93.51
Df Residuals:           1429                               MAE:          50.85
Df Model:               2      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     34.1944      3.4072       0.000     27.9524     41.3956
       opcount      0.5785      0.0055       0.000      0.5678      0.5895
     num_pairs      0.4691      0.0016       0.000      0.4658      0.4721
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/ECPAIRING_reth_regression.png&quot; alt=&quot;ECPAIRING_reth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ECPAIRING_reth_diagnostics.png&quot; alt=&quot;ECPAIRING_reth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ECPAIRING_reth_bootstrap.png&quot; alt=&quot;ECPAIRING_reth_bootstrap&quot; width=&quot;600&quot;/&gt;


## nethermind


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.990
Model:                  NNLS                    Adj. R-squared:          0.990
No. Observations:       1982                              RMSE:          96.86
Df Residuals:           1979                               MAE:          56.12
Df Model:               2      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     33.2452      3.2925       0.000     26.9497     39.7779
       opcount      0.3005      0.0043       0.000      0.2925      0.3093
     num_pairs      0.5684      0.0016       0.000      0.5651      0.5714
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/ECPAIRING_nethermind_regression.png&quot; alt=&quot;ECPAIRING_nethermind_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ECPAIRING_nethermind_diagnostics.png&quot; alt=&quot;ECPAIRING_nethermind_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ECPAIRING_nethermind_bootstrap.png&quot; alt=&quot;ECPAIRING_nethermind_bootstrap&quot; width=&quot;600&quot;/&gt;


## geth


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.989
Model:                  NNLS                    Adj. R-squared:          0.989
No. Observations:       1982                              RMSE:          41.44
Df Residuals:           1979                               MAE:          21.09
Df Model:               2      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     35.2135      1.3674       0.000     32.7371     38.0138
       opcount      0.3013      0.0022       0.000      0.2973      0.3058
     num_pairs      0.2147      0.0006       0.000      0.2135      0.2159
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/ECPAIRING_geth_regression.png&quot; alt=&quot;ECPAIRING_geth_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ECPAIRING_geth_diagnostics.png&quot; alt=&quot;ECPAIRING_geth_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ECPAIRING_geth_bootstrap.png&quot; alt=&quot;ECPAIRING_geth_bootstrap&quot; width=&quot;600&quot;/&gt;


## besu


```python
==============================================================================
                           NNLS Regression Results                            
==============================================================================
Dep. Variable:          run_duration_ms              R-squared:          0.986
Model:                  NNLS                    Adj. R-squared:          0.986
No. Observations:       1982                              RMSE:          46.00
Df Residuals:           1979                               MAE:          27.86
Df Model:               2      
==============================================================================
                      coef     std err     P-value      [0.025      0.975]
------------------------------------------------------------------------------
         const     31.3547      1.5207       0.000     28.2816     34.4007
       opcount      0.3031      0.0024       0.000      0.2986      0.3077
     num_pairs      0.2107      0.0007       0.000      0.2093      0.2121
==============================================================================
Notes: Non-negative least squares with bootstrap inference (1000 iterations)
==============================================================================
```

&lt;img src=&quot;./figs/ECPAIRING_besu_regression.png&quot; alt=&quot;ECPAIRING_besu_regression&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ECPAIRING_besu_diagnostics.png&quot; alt=&quot;ECPAIRING_besu_diagnostics&quot; width=&quot;600&quot;/&gt;

&lt;img src=&quot;./figs/ECPAIRING_besu_bootstrap.png&quot; alt=&quot;ECPAIRING_besu_bootstrap&quot; width=&quot;600&quot;/&gt;


## erigon

NNLS model did not run... Error: No valid data remaining after dropping NaN values
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7904/runtime_estimation/2026-01-15_2026-01-29/runtime_estimation_autogenerated_report</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7904/runtime_estimation/2026-01-15_2026-01-29/runtime_estimation_autogenerated_report</guid>
      </item>
    
      <item>
        <title>Block Access List (BAL) Size Analysis</title>
        <category>/</category>
        
        <description># Block Access List (BAL) Size Analysis

&gt; Analysis done with the BAL version https://github.com/ethereum/EIPs/blob/5cff3c4c11d2e06a269ade5b9ca005bb674f6b5f/EIPS/eip-7928.md

## Executive Summary

This report presents an empirical analysis of Block Access List (BAL) sizes across 100 historical Ethereum blocks. The analysis examines BAL encoding efficiency using SSZ format and compares configurations with and without storage read tracking.

## Methodology

- **Sample Size**: 100 blocks from the Ethereum mainnet
- **Block Range**: Blocks 22615032 to 22616022 (sampled every 10 blocks)
- **Encoding Format**: SSZ
- **Compression**: Snappy compression
- **Configurations**: Analysis performed both with and without storage read tracking

## Key Findings

### 1. Overall BAL Sizes

#### Configuration: With Storage Reads
- **Raw Size**: 91.3 KB average (25.1 - 164.8 KB range)
- **Compressed Size**: 42.7 KB average (11.7 - 78.7 KB range)
- **Compression Ratio**: 2.1x

#### Configuration: Without Storage Reads  
- **Raw Size**: 63.6 KB average (17.4 - 117.3 KB range)
- **Compressed Size**: 29.3 KB average (7.9 - 56.2 KB range)
- **Compression Ratio**: 2.2x

#### Impact of Storage Reads
- **Size Increase**: 45.6% when including storage reads
- **Absolute Difference**: 13.4 KB average increase

### 2. Component Breakdown

Average compressed sizes by component type (with storage reads):

- **Storage Writes**: 23.0 KB (54.0% of total)
- **Storage Reads**: 13.4 KB (31.3% of total)
- **Balance Changes**: 5.8 KB (13.6% of total)
- **Code Deployments**: 0.5 KB (1.1% of total)
- **Nonce Updates**: 0.0 KB (0.0% of total)

### 3. Block Activity Metrics

Average per block:
- **Transactions**: 183.4 (min: 54, max: 365)
- **Unique Accounts**: 407.0
- **Storage Writes**: 583.2
- **Storage Reads**: 818.2

### 4. Size Distribution

Compressed BAL size percentiles (with reads):
- **P10**: 21.7 KB
- **P25**: 28.9 KB  
- **P50**: 42.6 KB (median)
- **P75**: 54.6 KB
- **P90**: 64.7 KB
- **P95**: 73.7 KB
- **P99**: 78.7 KB

### 5. Correlation Analysis

- **Size vs Transactions**: Pearson correlation = 0.876
- **Size vs Storage Writes**: Pearson correlation = 0.973
- **Size vs Unique Accounts**: Pearson correlation = 0.956

## Technical Details

### BAL Structure

The Block Access List uses an account-centric design with hierarchical organization:

```
BlockAccessList
└── AccountChanges[]
    ├── address: Address (20 bytes)
    ├── storage_changes: SlotChanges[]
    │   ├── slot: StorageKey (32 bytes)
    │   └── changes: StorageChange[]
    │       ├── tx_index: uint16
    │       └── new_value: StorageValue (32 bytes)
    ├── storage_reads: SlotRead[]
    │   └── slot: StorageKey (32 bytes)
    ├── balance_changes: BalanceChange[]
    │   ├── tx_index: uint16
    │   └── post_balance: Balance (12 bytes)
    ├── nonce_changes: NonceChange[]
    │   ├── tx_index: uint16
    │   └── new_nonce: uint64
    └── code_changes: CodeChange[]
        ├── tx_index: uint16
        └── new_code: CodeData (variable)
```

### Encoding Efficiency Features

1. **Address Deduplication**: Each address appears only once, regardless of how many changes it has
2. **Slot Deduplication**: Each storage slot appears only once per account
3. **Transaction Indexing**: Uses uint16 (2 bytes) instead of full transaction hashes
4. **Optimized Field Sizes**: 
   - Balance: 12 bytes (sufficient for total ETH supply)
   - Transaction index: 2 bytes (supports up to 65,535 transactions)
   - Address: 20 bytes (standard Ethereum address)

## Key Insights

1. **Storage Operations Dominate**: Storage changes and reads account for 85.3% of the total BAL size, making storage optimization critical.

2. **Read Tracking Cost**: Including storage reads adds approximately 13.4 KB per block on average, a 45.6% increase.

3. **Scalability**: The median block (178 transactions) produces a 42.6 KB compressed BAL, while the 95th percentile block (286 transactions) produces 73.7 KB.

4. **Network Impact**: At current block production rates (12 seconds), BALs would add approximately 300.2 MB/day to node bandwidth requirements.

## Conclusions

The SSZ-encoded Block Access List provides an efficient method for recording state access patterns:

- **Typical blocks** (25th-75th percentile) generate compressed BALs of 28.9-54.6 KB
- **Large blocks** (95th percentile) remain under 73.7 KB compressed
- **Compression effectiveness** of 2.1x makes network transmission practical
- **Read tracking overhead** of 45.6% is still considered acceptable for the benefits provided, but might be removed in the future.
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7928/bal_size_analysis</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7928/bal_size_analysis</guid>
      </item>
    
      <item>
        <title>EIP-7928 Component Size &amp;amp; Compression Analysis - 1000 Blocks</title>
        <category>/</category>
        
        <description># EIP-7928 Component Size &amp; Compression Analysis - 1000 Blocks

## Dataset
- **Blocks Analyzed**: 1000 blocks (23,991,474 to 23,992,473)
- **Encoding**: RLP format
- **Compression**: Snappy algorithm

## Per-Block Component Statistics (KiB)

| Component | Avg Raw | Median Raw | Avg Compressed | Median Compressed | Avg Ratio | Median Ratio |
|-----------|---------|------------|----------------|-------------------|-----------|--------------
| Storage Writes | 52.6 | 49.6 | 29.2 | 28.0 | 1.79x | 1.78x |
| Storage Reads | 31.7 | 29.7 | 18.7 | 17.5 | 1.71x | 1.71x |
| Balance Changes | 6.8 | 6.6 | 6.7 | 6.5 | 1.02x | 1.00x |
| Nonce Changes | 1.1 | 1.0 | 1.1 | 1.0 | 0.99x | 1.00x |
| Code Changes | 2.1 | 0.2 | 1.2 | 0.2 | 1.37x | 1.16x |
| Account Addresses (w/ Changes) | 8.1 | 8.0 | 7.7 | 7.6 | 1.05x | 1.05x |
| Touched-Only Addresses | 3.6 | 3.6 | 3.5 | 3.4 | 1.03x | 1.06x |
| RLP Encoding Overhead | 4.6 | 4.5 | 4.4 | 4.3 | 1.05x | 1.05x |
| **Full BAL** | **110.8** | **106.0** | **72.4** | **70.5** | **1.52x** | **1.52x** |

## Component Size Distribution (KiB)

| Component | Min Raw | Max Raw | Std Dev Raw | Min Compressed | Max Compressed | Std Dev Compressed |
|-----------|---------|---------|-------------|----------------|----------------|-------------------|
| Storage Writes | 4.5 | 197.0 | 23.7 | 2.8 | 113.8 | 12.8 |
| Storage Reads | 1.2 | 105.7 | 15.0 | 0.9 | 88.9 | 9.2 |
| Balance Changes | 0.7 | 22.4 | 2.8 | 0.7 | 22.4 | 2.7 |
| Nonce Changes | 0.1 | 4.4 | 0.5 | 0.1 | 4.5 | 0.5 |
| Code Changes | 0.0 | 72.6 | 5.6 | 0.0 | 25.3 | 2.9 |
| Account Addresses (w/ Changes) | 1.9 | 29.5 | 3.2 | 1.8 | 28.1 | 3.0 |
| Touched-Only Addresses | 0.8 | 12.6 | 1.4 | 0.8 | 12.2 | 1.3 |
| RLP Encoding Overhead | 1.2 | 16.8 | 2.1 | 1.1 | 16.2 | 2.0 |
| **Full BAL** | **10.9** | **301.9** | **45.5** | **8.6** | **191.4** | **28.8** |

## Compression Ratio Distribution

| Component | Min Ratio | Max Ratio | Std Dev | 25th Percentile | 75th Percentile |
|-----------|-----------|-----------|---------|-----------------|-----------------
| Storage Writes | 1.54x | 2.86x | 0.12x | 1.74x | 1.83x |
| Storage Reads | 1.07x | 2.33x | 0.16x | 1.61x | 1.81x |
| Balance Changes | 1.00x | 1.50x | 0.04x | 1.00x | 1.03x |
| Nonce Changes | 0.97x | 1.07x | 0.00x | 0.99x | 1.00x |
| Code Changes | 0.93x | 8.67x | 0.65x | 0.99x | 1.56x |
| Account Addresses (w/ Changes) | 1.02x | 1.08x | 0.02x | 1.04x | 1.06x |
| Touched-Only Addresses | 1.00x | 1.10x | 0.03x | 1.02x | 1.05x |
| RLP Encoding Overhead | 1.02x | 1.12x | 0.03x | 1.03x | 1.07x |
| **Full BAL** | **1.19x** | **1.98x** | **0.09x** | **1.47x** | **1.56x** |

## Block Activity Metrics (per block)

| Metric | Average | Median | Min | Max |
|--------|---------|--------|-----|-----|
| Total Accounts | 603 | 600 | 98 | 1474 |
| Storage Writes Count | 700 | 667 | 65 | 2521 |
| Storage Reads Count | 982 | 922 | 36 | 3279 |
| Balance Changes Count | 612 | 598 | 62 | 1812 |
| Nonce Changes Count | 229 | 224 | 18 | 770 |

## Component Percentage of Full BAL

| Component | % of Raw Size | % of Compressed Size |
|-----------|---------------|---------------------|
| Storage Writes | 47.5% | 40.3% |
| Storage Reads | 28.6% | 25.8% |
| Balance Changes | 6.2% | 9.2% |
| Nonce Changes | 1.0% | 1.5% |
| Code Changes | 1.9% | 1.6% |
| Account Addresses (w/ Changes) | 7.3% | 10.7% |
| Touched-Only Addresses | 3.3% | 4.8% |
| RLP Encoding Overhead | 4.1% | 6.1% |

## BAL vs Block Size Comparison

Comparison using compressed block average of **71.71 KiB**:

| Metric | BAL Size (KiB) | Block Size (KiB) | Ratio (BAL/Block) | Size Difference |
|--------|---------------|------------------|-------------------|------------------|
| **Full BAL (with reads)** | 72.4 | 71.7 | 1.01x | +0.7 KiB |
| **BAL without reads** | 49.4 | 71.7 | 0.69x | -22.3 KiB |

- Full BAL **with reads** is 1.01x the size of a compressed block
- BAL **without reads** is 0.69x the size of a compressed block
- Storage reads add **23.0 KiB** (46.6%) to BAL size
- BAL overhead vs blocks: **+1.0%** (with reads), **-31.1%** (without reads)

## Storage Reads Impact Analysis

- **WITH reads** (Full BAL): 72.4 KiB compressed
- **WITHOUT reads**: 49.4 KiB compressed
- **Storage reads overhead**: 23.0 KiB (46.6%)

## Summary

1. **Component dominance**: Storage writes are 47.5% of raw BAL size
2. **Account addressing**: Accounts with changes (10.7%) vs touched-only (4.8%)
3. **Pure RLP overhead**: Encoding structure accounts for 6.1% of compressed size
4. **Compression efficiency**: Overall 1.52x compression ratio
5. **Size variability**: BAL sizes vary from 8.6 to 191.4 KiB compressed
6. **Block size ratio**: Full BALs are 1.01x compressed block size
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7928/bal_size_analysis_60m</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7928/bal_size_analysis_60m</guid>
      </item>
    
      <item>
        <title>EIP-7976 Empirical Report (64/64 Pricing at the Floor)</title>
        <category>/</category>
        
        <description># EIP-7976 Empirical Report (64/64 Pricing at the Floor)

*The following represents a summary with empirical findings from analyzing EIP-7976&apos;s impact on transactions.*
*Date: January, 2026*

## Dataset

- **Period**: 150 days of Ethereum mainnet data (August 2025 - January 2026)
- **Blocks analyzed**: 1,080,000 blocks
- **Total transactions**: 245,624,335

## Overall Impact Metrics

### Transaction Impact Summary

| Metric | Value |
|--------|-------|
| Total unaffected transactions | 240,588,721 (97.95%) |
| Total affected transactions | 5,035,614 (2.05%) |
| Transactions already affected by EIP-7623 | 2,093,004 (0.85%) |
| New transactions affected by EIP-7976 only | 2,942,610 (1.20%) |
| EIP-7623 overlap percentage | 41.6% |

### Address Distribution

| Metric | Value |
|--------|-------|
| Unique affected senders | 636,577 |
| Unique affected recipients | 521,874 |
| Avg transactions per affected sender | 7.91 |
| Avg transactions per affected recipient | 9.65 |

## Gas Usage Analysis (Affected Transactions)

### Basic Gas Metrics

| Metric | Value |
|--------|-------|
| Mean gas used | 140,959 |
| Median gas used | 38,031 |
| Average calldata bytes | 3,460 |
| Average zero bytes | 1,883 |
| Average non-zero bytes | 1,577 |

## Most Affected Senders

### Top 30 Senders by Additional Cost Impact

| Rank | Address | Transactions | Total Cost Increase (gas) | Avg Cost/Tx | Etherscan Link |
|------|---------|--------------|---------------------------|-------------|----------------|
| 1 | 0x54b839d988c9e712cd36cbf7c95dedc2b9f9ae6c | 44,296 | 100,215,386,242 | 2,262,402 | [View](https://etherscan.io/address/0x54b839d988c9e712cd36cbf7c95dedc2b9f9ae6c) |
| 2 | 0xcbe6fbf5e3c427013688e04d0fde56705890c4be | 27,031 | 93,199,568,422 | 3,447,877 | [View](https://etherscan.io/address/0xcbe6fbf5e3c427013688e04d0fde56705890c4be) |
| 3 | 0xe08cdadd44440e32ef153956a7ec40804a32dd74 | 3,360 | 24,782,661,408 | 7,375,792 | [View](https://etherscan.io/address/0xe08cdadd44440e32ef153956a7ec40804a32dd74) |
| 4 | 0xc17ea94008d5a8ee86f120e092cd35a679166416 | 59,548 | 12,647,040,432 | 212,383 | [View](https://etherscan.io/address/0xc17ea94008d5a8ee86f120e092cd35a679166416) |
| 5 | 0x148ee7daf16574cd020afa34cc658f8f3fbd2800 | 4,409 | 11,475,576,948 | 2,602,761 | [View](https://etherscan.io/address/0x148ee7daf16574cd020afa34cc658f8f3fbd2800) |
| 6 | 0x16f09b37b20bfbb07130bba8226299926e39b488 | 14,598 | 9,858,634,629 | 675,341 | [View](https://etherscan.io/address/0x16f09b37b20bfbb07130bba8226299926e39b488) |
| 7 | 0x6860c4ee678d847ae67771f2e5eea96ccb7fdf8d | 81,588 | 8,129,909,932 | 99,645 | [View](https://etherscan.io/address/0x6860c4ee678d847ae67771f2e5eea96ccb7fdf8d) |
| 8 | 0xf4ceb19b2467ef784b5e83b863418c50997b1646 | 18,119 | 7,588,481,162 | 418,813 | [View](https://etherscan.io/address/0xf4ceb19b2467ef784b5e83b863418c50997b1646) |
| 9 | 0x646c4fbdf82b5766c5eaf1fab9a8927fb5992d38 | 118,451 | 7,384,356,334 | 62,341 | [View](https://etherscan.io/address/0x646c4fbdf82b5766c5eaf1fab9a8927fb5992d38) |
| 10 | 0x0373b1ed3b9e601bb8b17afde70b0ccab76a981d | 158,514 | 7,277,663,018 | 45,911 | [View](https://etherscan.io/address/0x0373b1ed3b9e601bb8b17afde70b0ccab76a981d) |
| 11 | 0xe2da046340e00264c4f0443243a0565007ae08ac | 3,944 | 5,940,541,350 | 1,506,222 | [View](https://etherscan.io/address/0xe2da046340e00264c4f0443243a0565007ae08ac) |
| 12 | 0xa7ec2be4ed79ef315b4301aeca424a2dfdeaf09a | 65,856 | 5,616,659,491 | 85,286 | [View](https://etherscan.io/address/0xa7ec2be4ed79ef315b4301aeca424a2dfdeaf09a) |
| 13 | 0x7835fb36a8143a014a2c381363cd1a4dee586d2a | 2,887 | 5,601,056,603 | 1,940,095 | [View](https://etherscan.io/address/0x7835fb36a8143a014a2c381363cd1a4dee586d2a) |
| 14 | 0xf2099c4783921f44ac988b67e743daefd4a00efd | 1,436 | 4,201,896,151 | 2,926,111 | [View](https://etherscan.io/address/0xf2099c4783921f44ac988b67e743daefd4a00efd) |
| 15 | 0x7804405f18e134c3c47d71ae02eb454d25722d88 | 678 | 4,153,379,856 | 6,125,928 | [View](https://etherscan.io/address/0x7804405f18e134c3c47d71ae02eb454d25722d88) |
| 16 | 0xfe9dcec48761d2826e3e3d95597462dfb281db79 | 48,221 | 4,047,228,659 | 83,930 | [View](https://etherscan.io/address/0xfe9dcec48761d2826e3e3d95597462dfb281db79) |
| 17 | 0x1346d9c6315f6c23fe280b49ef215aebd49338b2 | 6,211 | 3,673,122,501 | 591,389 | [View](https://etherscan.io/address/0x1346d9c6315f6c23fe280b49ef215aebd49338b2) |
| 18 | 0x5f62d006c10c009ff50c878cd6157ac861c99990 | 7,952 | 3,655,219,300 | 459,660 | [View](https://etherscan.io/address/0x5f62d006c10c009ff50c878cd6157ac861c99990) |
| 19 | 0x3f773dc3ccc70b3d2a549713ac8d556af949d4e8 | 1,323 | 3,653,595,781 | 2,761,599 | [View](https://etherscan.io/address/0x3f773dc3ccc70b3d2a549713ac8d556af949d4e8) |
| 20 | 0xc8a5849a02ad01b572a0108aebf5a0d27777a552 | 63,707 | 3,484,943,560 | 54,702 | [View](https://etherscan.io/address/0xc8a5849a02ad01b572a0108aebf5a0d27777a552) |
| 21 | 0x30c2f77eaa93aace5e56ea4dcba5f21f794b58be | 687 | 3,326,641,119 | 4,842,272 | [View](https://etherscan.io/address/0x30c2f77eaa93aace5e56ea4dcba5f21f794b58be) |
| 22 | 0xcbeb5d484b54498d3893a0c3eb790331962e9e9d | 7,602 | 2,716,498,081 | 357,339 | [View](https://etherscan.io/address/0xcbeb5d484b54498d3893a0c3eb790331962e9e9d) |
| 23 | 0xd312535f0104a45ebd16cd29756fe9e6f8fe633c | 42,892 | 2,461,082,112 | 57,378 | [View](https://etherscan.io/address/0xd312535f0104a45ebd16cd29756fe9e6f8fe633c) |
| 24 | 0xb947d63b578fb48233de4076407dd0498dcf36ab | 584 | 2,431,099,134 | 4,162,840 | [View](https://etherscan.io/address/0xb947d63b578fb48233de4076407dd0498dcf36ab) |
| 25 | 0x1c9a7a489f62a75e276d3790ba92aaf12af13469 | 6,923 | 2,145,392,271 | 309,893 | [View](https://etherscan.io/address/0x1c9a7a489f62a75e276d3790ba92aaf12af13469) |
| 26 | 0xf3d021d51a725f5dbdce253248e826a8644be3c1 | 3,693 | 2,063,909,478 | 558,870 | [View](https://etherscan.io/address/0xf3d021d51a725f5dbdce253248e826a8644be3c1) |
| 27 | 0x2b4820042fe6a5b8ab01b29ede19203181d625fa | 18,285 | 1,880,349,910 | 102,835 | [View](https://etherscan.io/address/0x2b4820042fe6a5b8ab01b29ede19203181d625fa) |
| 28 | 0xf6309d5a91fa559cbf8f6ff3c5ec8fb67fe38577 | 628 | 1,830,917,976 | 2,915,474 | [View](https://etherscan.io/address/0xf6309d5a91fa559cbf8f6ff3c5ec8fb67fe38577) |
| 29 | 0x000cb000e880a92a8f383d69da2142a969b93de7 | 5,223 | 1,787,396,594 | 342,216 | [View](https://etherscan.io/address/0x000cb000e880a92a8f383d69da2142a969b93de7) |
| 30 | 0x785cd82bb016c740d41ca9e0b1bacc3a2439dc0d | 23,798 | 1,666,264,939 | 70,017 | [View](https://etherscan.io/address/0x785cd82bb016c740d41ca9e0b1bacc3a2439dc0d) |

### Key Observations

- **Top single address** (0x54b839d988c9e712cd36cbf7c95dedc2b9f9ae6c) accounts for 19.6% of all additional costs with 44,296 transactions
- **Highest volume address** (0x0373b1ed3b9e601bb8b17afde70b0ccab76a981d) has 158,514 affected transactions but only 45,911 gas average increase per transaction
- **Highest per-transaction impact** (0xe08cdadd44440e32ef153956a7ec40804a32dd74) shows 7.4M gas average increase per transaction

### Cost Impact

| Metric | Value |
|--------|-------|
| Mean cost increase per transaction | 101,489.08 gas units |
| Median cost increase per transaction | 11,444 gas units |

## Address Concentration Analysis

### Transaction Distribution

| Address Group | Count | Percentage |
|---------------|-------|------------|
| 1 affected transaction | 388,216 | 60.98% |
| ≤10 affected transactions | 611,619 | 96.08% |
| ≤50 affected transactions | 632,916 | 99.43% |
| ≤100 affected transactions | 634,730 | 99.71% |
| ≤200 affected transactions | 635,491 | 99.83% |
| ≤400 affected transactions | 635,926 | 99.90% |

### Transaction Volume Concentration

| Top Addresses | % of Affected Transactions |
|---------------|---------------------------|
| Top 10 | 26.79% |
| Top 20 | 33.47% |
| Top 30 | 37.17% |
| Top 40 | 39.70% |
| Top 50 | 41.76% |

### Transaction Volume by Percentiles

| Address Percentile | % of Affected Transactions |
|-------------------|---------------------------|
| Top 10% | 47.70% |
| Top 20% | 54.00% |
| Top 30% | 56.74% |
| Top 40% | 58.57% |
| Top 50% | 59.92% |

### Cost Impact Concentration

| Top Addresses | % of Additional Costs |
|---------------|----------------------|
| Top 10 | 55.28% |
| Top 20 | 63.90% |
| Top 30 | 68.26% |
| Top 40 | 71.15% |
| Top 50 | 73.64% |

### Cost Impact by Percentiles

| Address Percentile | % of Additional Costs |
|-------------------|----------------------|
| Top 1% | 91.44% |
| Top 10% | 97.31% |
| Top 20% | 98.75% |
| Top 30% | 99.40% |
| Top 40% | 99.72% |
| Top 50% | 99.87% |

## Method Analysis

### Top 20 Affected Function Selectors

| Rank | Function Selector | Transactions | Total Cost Increase | Avg Cost/Tx | Method Name |
|------|------------------|--------------|---------------------|-------------|-------------|
| 1 | 0x5578ceae | 28,355 | 94,835,044,230 | 3,343,786 | registerContinuousMemoryPage(...) |
| 2 | 0x538f9406 | 27,826 | 93,972,171,674 | 3,377,149 | updateState(uint256[],uint256[]) |
| 3 | 0x87201b41 | 70,794 | 26,600,051,568 | 375,772 | fulfillAvailableAdvancedOrders(...) |
| 4 | 0x5e10b3f0 | 379,355 | 22,244,424,770 | 58,646 | workMyDirefulOwner(uint256,uint256) |
| 5 | 0xfd9f1e10 | 191,576 | 18,205,559,712 | 95,012 | cancel(...) |
| 6 | 0xf074ba62 | 3,827 | 9,634,717,355 | 2,517,565 | verifyCheckpointProofs(...) |
| 7 | 0x09c5eabe | 42,105 | 8,765,393,130 | 208,186 | execute(bytes) |
| 8 | 0x6fadcf72 | 72,208 | 5,516,170,528 | 76,366 | forward(address,bytes) |
| 9 | 0xe85a6a28 | 16,654 | 4,985,983,858 | 299,377 | verifyFRI(...) |
| 10 | 0x415e2848 | 74,876 | 3,076,701,516 | 41,091 | swap_6269342730() |
| 11 | 0x3fe317a6 | 7,137 | 2,743,013,450 | 384,350 | verifyMerkle(...) |
| 12 | 0x55944a42 | 35,064 | 2,610,534,480 | 74,445 | matchAdvancedOrders(...) |
| 13 | 0x82ad56cb | 19,638 | 2,582,341,458 | 131,491 | aggregate3((address,bool,bytes)[]) |
| 14 | 0xe7acab24 | 25,484 | 2,080,247,964 | 81,621 | fulfillAdvancedOrder(...) |
| 15 | 0x13d79a0b | 21,713 | 1,555,462,876 | 71,652 | settleOrders(bytes) |
| 16 | 0xbb2f45e1 | 4,214 | 1,061,775,096 | 251,964 | submitV1(...) |
| 17 | 0x64971c46 | 13,972 | 1,002,671,000 | 71,750 | swap(...) |
| 18 | 0x4c2c47bd | 630 | 931,755,480 | 1,478,976 | bulkRegisterValidator(...) |

### Key Methods by Category

#### Zero-Knowledge Proof Systems

- **registerContinuousMemoryPage**: 28,355 txs, avg 3,343,786 gas increase
- **updateState**: 27,826 txs, avg 3,377,149 gas increase
- **verifyCheckpointProofs**: 3,827 txs, avg 2,517,565 gas increase
- **verifyFRI**: 16,654 txs, avg 299,377 gas increase
- **verifyMerkle**: 7,137 txs, avg 384,350 gas increase

#### NFT Marketplace Operations

- **fulfillAvailableAdvancedOrders**: 70,794 txs, avg 375,772 gas increase
- **matchAdvancedOrders**: 35,064 txs, avg 74,445 gas increase
- **fulfillAdvancedOrder**: 25,484 txs, avg 81,621 gas increase
- **cancel**: 191,576 txs, avg 95,012 gas increase

#### Multi-signature/Proxy Operations

- **forward**: 72,208 txs, avg 76,366 gas increase
- **execute**: 42,105 txs, avg 208,186 gas increase
- **aggregate3**: 19,638 txs, avg 131,491 gas increase

## EIP-7623 Interaction Analysis

### Linear Cost Increase

The analysis reveals that **41.6% of transactions affected by EIP-7976 are already impacted by EIP-7623**. This means:

- **2,093,004 transactions** (0.85% of all transactions) will experience **linear cost increases** as calldata pricing moves from EIP-7623 rates to EIP-7976 rates
- **2,942,610 transactions** (1.20% of all transactions) represent new impact from EIP-7976

### Pricing Structure Comparison

| Byte Type | Current | EIP-7623 | EIP-7976 | 7623→7976 Increase |
|-----------|---------|----------|----------|-------------------|
| Zero bytes | 4 gas | 10 gas | 64 gas | +54 gas (540%) |
| Non-zero bytes | 16 gas | 40 gas | 64 gas | +24 gas (60%) |


### Key Findings

1. **High Concentration**: Cost impact is extremely concentrated with top 1% of addresses responsible for 91.44% of additional costs

2. **EIP-7623 Linear Escalation**: A significant portion of affected transactions (41.6%) will see linear cost increases from existing EIP-7623 pricing

3. **Address Distribution**: 60.98% of affected addresses have only 1 affected transaction, indicating diverse but minimal user impact

4. **Methods**: Impact is dominated by zero-knowledge proof operations and NFT marketplace operations, with additional impact from multi-signature/proxy operations

5. **Cost Variance**: Median increase (11,444 gas) vs mean increase (101,489.08 gas) shows high variance in impact severity

6. **Broader Impact**: With 64/64 pricing, 2.05% of transactions are affected (vs 1.48% with 15/60 pricing), representing a 38.5% increase in affected transaction count</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7976/eip7976_empirical_analysis</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7976/eip7976_empirical_analysis</guid>
      </item>
    
      <item>
        <title>Compute and memory operations</title>
        <category>/</category>
        
        <description># Compute and memory operations

```python
# Keccak Op
KECCAK = 0x20

# Environmental Ops
CALLDATACOPY = 0x37
CODECOPY = 0x39
RETURNDATACOPY = 0x3E

# Memory Operations
MLOAD = 0x51
MSTORE = 0x52
MSTORE8 = 0x53
MCOPY = 0x5E

# System Operations
RETURN = 0xF3
REVERT = 0xFD
```
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-8011/compute_mem_ops</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-8011/compute_mem_ops</guid>
      </item>
    
      <item>
        <title>Pure compute operations</title>
        <category>/</category>
        
        <description># Pure compute operations

```python
# Arithmetic Ops
ADD = 0x01
MUL = 0x02
SUB = 0x03
DIV = 0x04
SDIV = 0x05
MOD = 0x06
SMOD = 0x07
ADDMOD = 0x08
MULMOD = 0x09
EXP = 0x0A
SIGNEXTEND = 0x0B

# Comparison Ops
LT = 0x10
GT = 0x11
SLT = 0x12
SGT = 0x13
EQ = 0x14
ISZERO = 0x15

# Bitwise Ops
AND = 0x16
OR = 0x17
XOR = 0x18
NOT = 0x19
BYTE = 0x1A
SHL = 0x1B
SHR = 0x1C
SAR = 0x1D

# Environmental Ops
ADDRESS = 0x30
ORIGIN = 0x32
CALLER = 0x33
CALLVALUE = 0x34
CALLDATALOAD = 0x35
CALLDATASIZE = 0x36
CODESIZE = 0x38
GASPRICE = 0x3A
RETURNDATASIZE = 0x3D

# Block Ops
BLOCKHASH = 0x40
COINBASE = 0x41
TIMESTAMP = 0x42
NUMBER = 0x43
PREVRANDAO = 0x44
GASLIMIT = 0x45
CHAINID = 0x46
SELFBALANCE = 0x47
BASEFEE = 0x48
BLOBHASH = 0x49
BLOBBASEFEE = 0x4A

# Control Flow Ops
STOP = 0x00
JUMP = 0x56
JUMPI = 0x57
PC = 0x58
GAS = 0x5A
JUMPDEST = 0x5B

# Storage Ops
TLOAD = 0x5C
TSTORE = 0x5D

# Pop Operation
POP = 0x50

# Push Operations
PUSH0 = 0x5F
PUSH1 = 0x60
PUSH2 = 0x61
PUSH3 = 0x62
PUSH4 = 0x63
PUSH5 = 0x64
PUSH6 = 0x65
PUSH7 = 0x66
PUSH8 = 0x67
PUSH9 = 0x68
PUSH10 = 0x69
PUSH11 = 0x6A
PUSH12 = 0x6B
PUSH13 = 0x6C
PUSH14 = 0x6D
PUSH15 = 0x6E
PUSH16 = 0x6F
PUSH17 = 0x70
PUSH18 = 0x71
PUSH19 = 0x72
PUSH20 = 0x73
PUSH21 = 0x74
PUSH22 = 0x75
PUSH23 = 0x76
PUSH24 = 0x77
PUSH25 = 0x78
PUSH26 = 0x79
PUSH27 = 0x7A
PUSH28 = 0x7B
PUSH29 = 0x7C
PUSH30 = 0x7D
PUSH31 = 0x7E
PUSH32 = 0x7F

# Dup operations
DUP1 = 0x80
DUP2 = 0x81
DUP3 = 0x82
DUP4 = 0x83
DUP5 = 0x84
DUP6 = 0x85
DUP7 = 0x86
DUP8 = 0x87
DUP9 = 0x88
DUP10 = 0x89
DUP11 = 0x8A
DUP12 = 0x8B
DUP13 = 0x8C
DUP14 = 0x8D
DUP15 = 0x8E
DUP16 = 0x8F

# Swap operations
SWAP1 = 0x90
SWAP2 = 0x91
SWAP3 = 0x92
SWAP4 = 0x93
SWAP5 = 0x94
SWAP6 = 0x95
SWAP7 = 0x96
SWAP8 = 0x97
SWAP9 = 0x98
SWAP10 = 0x99
SWAP11 = 0x9A
SWAP12 = 0x9B
SWAP13 = 0x9C
SWAP14 = 0x9D
SWAP15 = 0x9E
SWAP16 = 0x9F

# Memory Operations
MSIZE = 0x59
```
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-8011/compute_ops</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-8011/compute_ops</guid>
      </item>
    
      <item>
        <title>LOG operations</title>
        <category>/</category>
        
        <description># LOG operations

```python
# Log Operations
LOG0 = 0xA0
LOG1 = 0xA1
LOG2 = 0xA2
LOG3 = 0xA3
LOG4 = 0xA4
```</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-8011/log_ops</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-8011/log_ops</guid>
      </item>
    
      <item>
        <title>Going multidimensional - an empirical analysis on gas metering in the EVM</title>
        <category>/</category>
        
        <description># Going multidimensional - an empirical analysis on gas metering in the EVM

**This document is a copy-paste from [this ethresearch post](https://ethresear.ch/t/going-multidimensional-an-empirical-analysis-on-gas-metering-in-the-evm/22621)**

This post summarizes the key takeaways from an empirical analysis focused on understanding how different EVM gas metering schemes impact network throughput and block utilization. Concretely, we were focused on multidimensional schemes, where the usage of different resources is metered separately.

For conciseness, I am jumping over many technical details. Please refer to the [project documentation](https://hackmd.io/@nightingale/evm-gas-meter) for more details.

I would like to thank @dcrapis for the valuable review, comments, and discussion, [Shouqiao Wang](https://x.com/qiaoqiao2001?lang=en) for the early discussions and for sharing his initial analysis, and the ethPandaOps team for access to their amazing data. This project was supported by the grant [ROP-15: EVM Gas Metering](https://blog.ethereum.org/2025/05/08/allocation-q1-25) provided by the [Robust Incentives Group](https://rig.ethereum.org/).

## Gas metering and block utilization

Gas is the unit that quantifies the computational work needed to perform operations on the Ethereum network. Every transaction on Ethereum consumes resources, and to prevent spam and endless loops, users must pay for these resources.

An essential component of this process is the gas metering scheme, i.e., the function responsible for measuring how full a block is and how many resources remain available. All decentralized networks have limited resources, and thus, protocols must have a way to meter usage and decide when a block is reaching those limits.

In Ethereum, the current metering scheme attributes a cost to each operation (measured in units of gas) and adds the gas of each transaction. Then, it compares this sum against a fixed limit of 36 million gas units. Once a block reaches 36 million gas units, it is considered completely full. In addition to this limit, the protocol also compares the gas utilized by the block against a target of 18 million, which is used to set the base fee all transactions must pay.

This scheme has the advantage of being simple and, thus, easy to interface with. However, it has the drawback of overestimating how close a block is to being at the limits of the network resources. 

To illustrate this point, let us start with a simple example. In this example, we have two blocks, $B_1$ and $B_2$, and a network that only cares about two resources, $x$ and $y$, which with a limit of 1. $B_1$ has a usage by resource of $(x=1, y=0)$ and $B_2$ has a usage by resource of $(x=0.5, y=0.5)$. According to the current scheme, both blocks have the same usage of 1 unit. However, we can see that neither block is reaching the limits of the available resources. $B_1$ is at the limit of resource $x$, but it does not use resource $y$. On the other hand, $B_2$ is only using half of both resources.

This lack of expressivity in the current scheme led to the idea of replacing it with a scheme in which the usage and limits of different resources are considered separately. These are commonly referred to as &quot;multidimensional schemes&quot;.

A possible approach is a scheme similar to the one [described by Vitalik](https://vitalik.eth.limo/general/2024/05/09/multidim.html). In this approach, we separate the resources into groups (in our previous example, resource $x$ would be one group, and resource $y$ would be the other). Then, for each block, we add the gas units for each group ($g_x$ and $g_y$) and define the block resource utilization as the maximum of the groups ( $\text{utilization}=\max(c_x*r_x+c_y*r_y, c&apos;_x*r_x, g_y)$). Note however that Vitalik&apos;s approach is at transaction-level, instead of at block-level. We can see that in our previous example, this metering scheme would allow us to fill both blocks with more transactions: $B_1$ can additionally include 0.5 units of each resource, while block $B_2$ can include 1 unit of resource $y$ without reaching the block limit.

This example highlights a potential advantage of multidimensional metering. By allowing for a more efficient account of resource utilization, we can increase network throughput (i.e., process more transactions in a block) without significantly impacting the risk of resource overuse. However, there are two key questions to consider here:

1. What are the actual throughput gains we should expect from going multidimensional?
2. What is the design space for multidimensional schemes? And what are the next steps to decide on the best design?

We will try to address each of these questions in the following sections.

## Going multidimensional. Why?

### Historical gas usage by resource

To understand the potential throughput gains of multidimensional metering, we first need to examine how much gas is being used by each resource. To this end, we designed a data pipeline that collects raw transaction data from [Xatu’s dataset](https://ethpandaops.io/data/xatu/) and the [debug traces](https://github.com/akegaviar/Erigon-Geth-debug_traceTransaction-guide/) from an Erigon node, processes and aggregates this data to compute individual gas cost components (intrinsic costs, input data, opcodes, and refunds) by transaction and maps these costs to specific EVM resources (compute, memory, state, history, access, and bloom topics).

The mapping between operations and resources is a major assumption underlying this analysis; different mappings will have a significant impact on the final resource breakdown. Our mapping is based on the knowledge of the underlying operations (e.g., we know that some opcodes only use compute resources) and a partial breakdown of the [cost of some opcodes by resource](https://docs.google.com/spreadsheets/d/1IBf9qD0VUQErsw-oPtaEFa2P3L5w-K46cGPB_n8j0jU/edit?usp=sharing) made when the gas model was first designed.

We should further note that this analysis overlooks the costs and resource utilization associated with blobs. Although this is a parallel free market at the moment, it will nevertheless impose constraints on bandwidth limits and, thus, should be considered when designing a new gas metering model.

The plot below shows the contribution of each resource to the total gas consumption observed between blocks 22000000 and 22005000 (which were processed on March 8th). For improved visibility, we aggregate costs across groups of 10 consecutive blocks. Since each bar is a sum over 10 blocks, the maximum gas that can be used per bar is 360 million units, while the target gas is 180 million units. We plot the target line of 180 million units.

![plot_1](/EIPs/assets/eip-8011/plot_1.png)

In our data, state represents a significant portion of the gas used in Ethereum blocks, accounting for 30.2% of all gas consumed between blocks 22000000 and 22005000. The second resource with the most gas used is compute (26.8%), followed by access (21.9%). History, bandwidth, and bloom topics have less relevant contributions, accounting for 9.9%, 6.9%, and 1.6% of all the gas used, respectively.

This means that state, compute, and access are the bottleneck resources, as they cover a significant portion of the available block space. Thus, we expect that metering models that separate these resources will show the biggest gains.

When considering resource constraints and the impact of a multidimensional metering scheme on network scalability, looking into the times of congestion or &quot;high load&quot; is also relevant. Using the same data as before, we filtered the blocks with a high utilization rate (more than 95%) and plotted the distribution of block utilization rate by resource and the block count by top resource. These blocks constitute 9.7% of the consecutive blocks dataset.

|   |   |
|---|---|
|![plot_2](/EIPs/assets/eip-8011/plot_2.png)| ![plot_3](/EIPs/assets/eip-8011/plot_3.png)|

Interestingly, state dominates in these blocks (with some contribution from compute and access), which is a significant change when compared with the average block. This indicates that, during periods of high demand, the types of operations more commonly used differ from those used in the average block. Thus, for the current usage of the EVM, state is likely the most important resource to consider when designing multidimensional schemes.

### Block building simulation and metering schemes

By now, we know that state, compute, and access are the most likely resources to achieve throughput gains. However, we still have not answered what the actual gains might be. To accomplish this, we built a simulation based on the [Monte-Carlo method](https://en.wikipedia.org/wiki/Monte_Carlo_method) that uses repeated random sampling to estimate the throughput observed under different metering schemes and transaction demand levels.

We model transaction demand through scenarios. They control the number of transactions and which transactions arrive at the mempool at each 12-second slot. For each slot, we refresh the mempool with the transactions generated by the demand scenario. Then, we build a block for the slot. First, we order the mempool transactions by their transaction fees (the highest are first). Second, we iteratively add transactions to the block until it is full according to the metering scheme being tested. Of course, once we add a transaction to block, we remove it from the mempool so that it cannot be selected again. This mempool refresh and block-building cycle is repeated for a pre-defined number of blocks.

The first scenario we want to discuss aims to mimic an infinite demand for historical transactions. In other words, it tries to estimate the maximum gains we could achieve under different metering schemes, assuming that there are always more transactions available to fill a block up to the 36 million gas units limit. This scenario samples transactions from the same historical blocks processed on March 8th until the block is full.

The following table displays the average gains in transaction throughput (i.e., the number of transactions included in a block) and total gas used (i.e., the total number of gas units included in a block) for various metering schemes. The averages are computed over 100,000 Monte Carlo iterations of a single block built under this scenario.

| **Metering scheme** | **Average gain in throughput** | **Average gain in gas used** |
|:---:|:---:|:---:|
| Compute vs. Others | 60.1% | 44.0% |
| State vs. Others | 58.9% | 52.5% |
| Access vs. Others | 49.6% | 34.1% |
| Bandwidth vs. Others | 26.2% | 11.7% |
| State vs. Compute vs. Others | 145.2% | 133.8% |
| State vs. Compute vs. Access vs. Others | 241.3% | 219.1% |

Between the two-dimensional schemes, Compute vs. Others and State vs. Others show the largest gain in throughput compared to the current one-dimensional scheme. Access vs. Others also shows a significant gain, although slightly lower than the other two schemes. Additionally, both the three-dimensional and the four-dimensional schemes result in even larger gains over the current scheme, which highlights that compute, state and access have relevant gas usage in historical transactions and, as such, metering these resources separately can have a significant impact in throughput in a case with infinite demand of these transactions.

This trend is also observed in the total gas units included in the block. Although, the gains for the gas used are slightly lower than those observed in transaction throughput.

Now that we estimated the maximum gains one could observe in the various metering schemes, it is natural to question how much additional demand would be required in each metering scheme to fill Ethereum blocks and achieve the throughput previously observed. To this end, we designed a set of scenarios where we sample historical transactions from March 8th with varying demand levels.

The demand is modeled by the empirical distribution observed on March 8th, with a multiplier to increase the average demand. For example, a multiplier of 2x will result in an average demand that is double the demand observed on March 8th. The plot below shows the transaction arrival count distributions for the four demand multipliers tested.

![plot_4](/EIPs/assets/eip-8011/plot_4.png)

The next plot shows the median block utilization and the inter-quartile range (IQR) by metering scheme and demand level. Recall that the block utilization represents how full a block is and is defined as the metered gas of a block divided by the 36 million gas units limit.

![plot_5](/EIPs/assets/eip-8011/plot_5.png)

In line with previous results, the base demand (multiplier = 1x) is insufficient to achieve high utilization rates across all metering schemes. As demand levels increase, median utilization rates also rise. In the two-dimensional schemes, a demand level of 3x is needed to achieve full blocks for the median case. The three-dimensional scheme requires a demand of 5x. Regarding the four-dimensional model, all demand levels tested result in partially filled blocks in the median case.

## Going multidimensional. What do?

Based on our empirical analysis, there is a significant gain in L1 scalability in moving to a multidimensional metering scheme. However, are there any downsides? The key tradeoff is complexity.

There are two levels on which multidimensional metering increases complexity. The first level is implementation complexity. We need to be able to track the amount of gas each EVM operation consumes per resource, and this requires a hard fork on the execution clients to add the new resource dimensions. In addition, we need to encode the mapping between each operation and each resource. This mapping is crucial to ensuring the network continues to function properly; therefore, it is essential to conduct in-depth benchmarks on the resource usage of each operation. This could be an analysis akin to [gas-cost-estimator](https://github.com/imapp-pl/gas-cost-estimator/tree/master) but for all the relevant EVM resources. Finally, we are introducing a new variable that is only used to track block utilization. At the same time, we continue to use the total gas to compute transaction fees, which can be confusing.

The second level of complexity relates to block building. Even though the experience for users remains the same - transactions cost the same, and users continue to submit a single gas limit and maximum fee - block builders now have a more complicated optimization problem. Not only do they need to consider the MEV and transaction fees, but also how to efficiently pack blocks into the various resources.
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-8011/multidim_empirical_analysis</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-8011/multidim_empirical_analysis</guid>
      </item>
    
      <item>
        <title>State operations</title>
        <category>/</category>
        
        <description># State operations

```python
# Environmental Ops
BALANCE = 0x31
EXTCODESIZE = 0x3B
EXTCODECOPY = 0x3C
EXTCODEHASH = 0x3F

# Storage Ops
SLOAD = 0x54
SSTORE = 0x55

# System Operations
CREATE = 0xF0
CALL = 0xF1
CALLCODE = 0xF2
DELEGATECALL = 0xF4
CREATE2 = 0xF5
STATICCALL = 0xFA
SELFDESTRUCT = 0xFF
```
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-8011/state_ops</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-8011/state_ops</guid>
      </item>
    
      <item>
        <title></title>
        <category>/</category>
        
        <description>| Variable           | Symbol       | Value         | Unit          | Source |
| -------------------|--------------|---------------|---------------|--------|
| Network Hashrate   |H&lt;sub&gt;N&lt;/sub&gt; | 296000        | GH/s          | https://etherscan.io/chart/hashrate |
| GPU Hashrate       |H&lt;sub&gt;M&lt;/sub&gt; | 31.2          | MH/s          | https://www.legitreviews.com/geforce-gtx-1070-ethereum-mining-small-tweaks-great-hashrate-low-power_195451 |
| GPU Power          |P&lt;sub&gt;M&lt;/sub&gt; | 110.6         | W             | https://www.reddit.com/r/ethereum/comments/7vewys/10000_tons_co2_per_day_and_climbing_eip_858/dtrswyz/ |


## Network Power Consumption (P&lt;sub&gt;N&lt;/sub&gt;)

A baseline value for network power consumption can be found by multiplying the total network hashrate with a &quot;best case&quot; value for the power/hashrate ratio that a miner can achieve.

&gt; P&lt;sub&gt;N&lt;/sub&gt; = H&lt;sub&gt;N&lt;/sub&gt; x P&lt;sub&gt;M&lt;/sub&gt; / H&lt;sub&gt;M&lt;/sub&gt;
&gt;
&gt; P&lt;sub&gt;N&lt;/sub&gt; = 296000 (GH/s) x 110.6 (W) x 1000 (MH/GH) / ( 31.2 (MH/s) x 10^6 (W/MW) )
&gt;
&gt; P&lt;sub&gt;N&lt;/sub&gt; = 1049 MW

As a side note, people often confuse power (W) and energy (power x time, eg. Wh). For instance, assuming an average daily P&lt;sub&gt;Nd&lt;/sub&gt; of 1049 MW we can calculate that days Energy consumption by multiplying by the number of hours in a day.

&gt; E&lt;sub&gt;Nd&lt;/sub&gt; = P&lt;sub&gt;Nd&lt;/sub&gt; x T&lt;sub&gt;d&lt;/sub&gt;
&gt;
&gt; E&lt;sub&gt;Nd&lt;/sub&gt; = 1049 (MW) x 24 (h/d) / 1000 (GW/MW)
&gt;
&gt; E&lt;sub&gt;Nd&lt;/sub&gt; = 19.7 GWh
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-858/calculations</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-858/calculations</guid>
      </item>
    
      <item>
        <title></title>
        <category>/</category>
        
        <description>This directory contains contract sources for EIP 3267 draft.

The audit of the contracts was paid for, now it is in progress.
(There are some FIXME/TODO comments for the auditors.)

The contracts are to be compiled with Solidity 0.7.6.

Dependencies (Node.js packages):

- @openzeppelin/contracts 3.3.0
- abdk-libraries-solidity 2.4.0

The contracts to be deployed are:
- SalaryWithDAO
- DefaultDAOInterface

The sources:
- [ERC1155/ERC1155.sol](/EIPs/assets/eip-3267/contracts/ERC1155/ERC1155.sol)
- [ERC1155/ERC1155TokenReceiver.sol](/EIPs/assets/eip-3267/contracts/ERC1155/ERC1155TokenReceiver.sol)
- [ERC1155/ERC1155WithTotals.sol](/EIPs/assets/eip-3267/contracts/ERC1155/ERC1155WithTotals.sol)
- [ERC1155/IERC1155.sol](/EIPs/assets/eip-3267/contracts/ERC1155/IERC1155.sol)
- [ERC1155/IERC1155TokenReceiver.sol](/EIPs/assets/eip-3267/contracts/ERC1155/IERC1155TokenReceiver.sol)
- [BaseBidOnAddresses.sol](/EIPs/assets/eip-3267/contracts/BaseBidOnAddresses.sol)
- [BaseLock.sol](/EIPs/assets/eip-3267/contracts/BaseLock.sol)
- [BaseRestorableSalary.sol](/EIPs/assets/eip-3267/contracts/BaseRestorableSalary.sol)
- [BaseSalary.sol](/EIPs/assets/eip-3267/contracts/BaseSalary.sol)
- [BidOnAddresses.sol](/EIPs/assets/eip-3267/contracts/BidOnAddresses.sol)
- [DAOInterface.sol](/EIPs/assets/eip-3267/contracts/DAOInterface.sol)
- [DefaultDAOInterface.sol](/EIPs/assets/eip-3267/contracts/DefaultDAOInterface.sol)
- [Salary.sol](/EIPs/assets/eip-3267/contracts/Salary.sol)
- [SalaryWithDAO.sol](/EIPs/assets/eip-3267/contracts/SalaryWithDAO.sol)
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-3267/contracts/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-3267/contracts/</guid>
      </item>
    
      <item>
        <title>EIP-3525</title>
        <category>/</category>
        
        <description># EIP-3525

## Demonstration only

The code included in this directory is ONLY for the purpose of demonstrating how to implement this proposal, it is not a full-featured implementation ready for production.

So please DO NOT use the code here for purposes other than study.
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-3525/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-3525/</guid>
      </item>
    
      <item>
        <title></title>
        <category>/</category>
        
        <description>&lt;div align=&quot;center&quot;&gt;

# ERC721 Consumable Extension

[![License: CC0-1.0](https://img.shields.io/badge/License-CC0-yellow.svg)](https://creativecommons.org/publicdomain/zero/1.0/)

&lt;/div&gt;

This project provides a reference implementation of the proposed `ERC721Consumer` OPTIONAL extension.

## Install

In order to install the required dependencies you need to execute:
```shell
npm install
```

## Compile

In order to compile the solidity contracts you need to execute:
```shell
npx hardhat compile
```

## Tests

```shell
npx hardhat test
```</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-4400/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-4400/</guid>
      </item>
    
      <item>
        <title></title>
        <category>/</category>
        
        <description>#EIP4519 Proof of Concept - Firmware
This firmware is designed for a device using an ESP32 as a smart asset associated with an EIP4519 SmartNFT. The device has two operation modes: registration mode and application mode.
##Registration mode 
In this mode, the device generates 51 bytes  with the TRNG of the ESP32 core. Those bytes are used for the initial values of a CTR-DRBG PRNG to generate the private key of the Ethereum account. Only the address of this account is shared. The UART port is needed for communications with this device.
The commands in this mode are:
&gt;‘0’ – Check if the device is ready.
&gt;‘1’ – Share the address of the account.
&gt;‘2’ – Save the initial values of CTR-DRBG PRNG in an EEPROM and changes the operation mode.
##Application Mode
The device reads the EEPROM to obtain the initial values of the CTR-DRBG PRNG and recover the Ethereum account. The device connects to a WiFi station. With Infura, the device checks the state of its associated SmartNFT registered on an EIP4519 Smart Contract and also checks if the device must be engaged with the owner or the user. The UART port is needed for communications with this device.
The commands in this mode are:
&gt;&apos;Z&apos;+OWNER/USER_ADDRESS – The device checks if the address must be authenticated and generates a nonce.
&gt;&apos;Y&apos;+SIGN_D+&apos;#&apos;+NONCE_D – The device checks the signature, signs NONCE_D, and sends the signature.
&gt;&apos;Y&apos;+SIGNED_PK+&apos;#&apos;+PK – The device checks the signature, generates the shared key, and sends the transaction to the EIP4519 Smart Contract.
&gt;&apos;C&apos; – The EEPROM is cleared, only for debug process.
&gt;&apos;R&apos; – The device is restarted to refresh the SmartNFT state, only for debug process.
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-4519/ESP32_Firmware/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-4519/ESP32_Firmware/</guid>
      </item>
    
      <item>
        <title>Proof of concept of an implementation of an Smart Non Fungible Token</title>
        <category>/</category>
        
        <description># Proof of concept of an implementation of an Smart Non Fungible Token
This proof of concept is launch in the Ethereum Kovan Testnet with the address 0x7eB5A03E7ED70ABf70fee48965D0411d37F335aC.
Use the proposal Non Fungible Token binding assets with SmartNFT and define the user management of the assets.
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-4519/PoC_SmartNFT/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-4519/PoC_SmartNFT/</guid>
      </item>
    
      <item>
        <title>Multi-Fractional Non-Fungible Token</title>
        <category>/</category>
        
        <description># Multi-Fractional Non-Fungible Token
Solidity Implementation of Multi-Fractional Non-Fungible Token.

## Problem Trying to solve
Before, ERC20 Token contract should be deployed every time when fractionalizing a specific NFT.

To solve this problem, this standard proposes a token standard to cover multiple fractionalized nft in a contract without having to deploy each time.

Issue : https://github.com/ethereum/EIPs/issues/4674

PR : https://github.com/ethereum/EIPs/pull/4675

## How to use
```
contracts/
        helper/
        interface/
        math/
        MFNFT.sol
        NFT.sol
        ERC20Token.sol
```

### Contracts
``MFNFT.sol`` : Multi-Fractional Non-Fungible Token Contract

``NFT.sol`` : Non-Fungible Token Contract

``ERC20Token.sol`` : Sample ERC-20 Token Contract

``helper/Verifier.sol`` : Contract that verifies the ownership of NFT before fractionalization

``math/SafeMath.sol`` : Openzeppelin SafeMath Library

``interface/IERC20.sol`` : ERC-20 Token Interface

``interface/IERC721.sol`` : ERC-721 Token Interface

``interface/IMFNFT`` : MFNFT Token Interface

### Install &amp; Test

Installation
```
npm install
```

Test
```
npx hardhat test
```

Coverage
```
npx hardhat coverage
```
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-4675/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-4675/</guid>
      </item>
    
      <item>
        <title>EIP-4907</title>
        <category>/</category>
        
        <description># EIP-4907
EIP-4907 is an extension of ERC-721. It proposes an additional role **user** and a valid duration indicator **expires**. It allows users and developers manage the use right more simple and efficient.

### Tools
* [Visual Studio Code](https://code.visualstudio.com/)
* [Solidity](https://marketplace.visualstudio.com/items?itemName=JuanBlanco.solidity) - Solidity support for Visual Studio code
* [Truffle](https://truffleframework.com/) - the most popular development framework for Ethereum

### Install
```
npm install
```

### Test
```
truffle test
```

### Additional Resources
* [Official Truffle Documentation](http://truffleframework.com/docs/) for complete and detailed guides, tips, and sample code.</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-4907/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-4907/</guid>
      </item>
    
      <item>
        <title>EIP-5007</title>
        <category>/</category>
        
        <description># EIP-5007
This standard is an extension of [ERC-721](/EIPs/EIPS/eip-721). It proposes some additional functions (`startTime`, `endTime`) to help with on-chain time management.

## Tools
* [Truffle](https://truffleframework.com/) - a development framework for Ethereum

## Install
```
npm install truffle -g
npm install
```

## Test
```
truffle test
```
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-5007/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-5007/</guid>
      </item>
    
      <item>
        <title>EIP-5218 Reference Implementations</title>
        <category>/</category>
        
        <description># EIP-5218 Reference Implementations

This is the source code for a reference implementation of EIP-5218.

## Build and Test

The repo expects a Foundry build system, optionally using visual studio code for editing. You can run the test suite with:

```bash
forge test -vvvvv
```

</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-5218/contracts/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-5218/contracts/</guid>
      </item>
    
      <item>
        <title>EIP 5252 implementation</title>
        <category>/</category>
        
        <description># EIP 5252 implementation

This project is a reference implementation of EIP-5252.

Try running some of the following tasks:

```shell
npx hardhat help
npx hardhat test
GAS_REPORT=true npx hardhat test
npx hardhat node
npx hardhat run scripts/deploy.ts
```
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-5252/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-5252/</guid>
      </item>
    
      <item>
        <title>EIP-5725: Transferrable Vesting NFT - Reference Implementation</title>
        <category>/</category>
        
        <description># EIP-5725: Transferrable Vesting NFT - Reference Implementation

This repository serves as a reference implementation for **EIP-5725 Transferrable Vesting NFT Standard**. A Non-Fungible Token (NFT) standard used to vest ERC-20 tokens over a vesting release curve.

## Contents

- [EIP-5725 Specification](/EIPs/assets/eip-5725/contracts/IERC5725.sol): Interface and definitions for the EIP-5725 specification.
- [ERC-5725 Implementation (abstract)](/EIPs/assets/eip-5725/contracts/ERC5725.sol): ERC-5725 contract which can be extended to implement the specification.
- [VestingNFT Implementation](/EIPs/assets/eip-5725/contracts/reference/LinearVestingNFT.sol): Full ERC-5725 implementation using cliff vesting curve.
- [LinearVestingNFT Implementation](/EIPs/assets/eip-5725/contracts/reference/VestingNFT.sol): Full ERC-5725 implementation using linear vesting curve.
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-5725/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-5725/</guid>
      </item>
    
      <item>
        <title>SDC Solidity implementation</title>
        <category>/</category>
        
        <description># SDC Solidity implementation

## Description

The reference SDC implementation can be unit tested with Hardhat to understand the trade process logic.

### Compile and run tests with Hardhat

We provide the essential steps to compile the contracts and run the provided unit tests.

### Provided Contracts and Tests

#### Interfaces

- `contracts/ISDC.sol` - Interface contract (aggregation of `ISDCTrade`, `ISDCSettlement`, `IAsyncTransferCallback`)
- `contracts/ISDCTrade.sol` - Interface related to trade incept/confirm/terminate
- `contracts/ISDCSettlement.sol` - Interface related to settlement initiate/perform/after
- `contracts/IAsyncTransferCallback.sol` - Interface related to transfer.

- `contracts/IAsyncTransfer.sol` - Interface (extending the ERC-20) for settlement tokens used in `SDCPledgedBalance`.

#### Implementations

- `contracts/SDCSingleTrade.sol` - SDC abstract contract for an OTC Derivative (single trade case only)
- `contracts/SDCSingleTradePledgedBalance.sol` - SDC full implementation for an OTC Derivative (single trade case only)
- `contracts/ERC20Settlement.sol` - Mintable settlement token contract implementing `IERC20Settlement` for unit tests

#### Tests

- `test/SDCTests.js` - Unit tests for the life-cycle of the sdc implementation

### Compile and run tests with Hardhat

Install dependencies:
```shell
npm i
```

Compile:
```shell
npx hardhat compile
```

Run all tests:
```shell
npx hardhat test
```

### Configuration files

- `package.js` - Javascript package definition.
- `hardhat.config.js` - Hardhat config.

### Used javascript-based testing libraries for solidity

- `ethereum-waffle`: Waffle is a Solidity testing library. It allows you to write tests for your contracts with JavaScript.
- `chai`: Chai is an assertion library and provides functions like expect.
- `ethers`: This is a popular Ethereum client library. It allows you to interface with blockchains that implement the Ethereum API.
- `solidity-coverage`: This library gives you coverage reports on unit tests with the help of Istanbul.

## Version history / release notes

### 0.8.0

- Re-introduced the method `afterSettlement` that can be used to check pre-conditions of the next settlement cycle, e.g., triggered by a time-oracle.
- Added the event `SettlementAwaitingInitiation` which should be issued when the trade goes active and when `afterSettlement` veryfied that the trade is ready for the next settlement.
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-6123/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-6123/</guid>
      </item>
    
      <item>
        <title>Example implementation of EIP-6358</title>
        <category>/</category>
        
        <description># Example implementation of EIP-6358

## Prerequisites
- truffle &gt;= v5.7.9
- node &gt;= v18.12.1
- npm &gt;= 8.19.2
- npx &gt;= 8.19.2

## Installation
```
npm install
```

Add the configuration file `truffle-config.js` into the directory `./`. The file `truffle-config.js` can be generated by executing the command in an $empty directory$:
```
npx truffle init
```

**Note that:**  

- type `N` when asked `Overwrite contracts?`
- type `N` when asked `Overwrite migrations?`
- type `N` when asked `Overwrite test?`

After `truffle-config.js` is generated, then:  

- Uncommnet the content of `development`, like this:

```
development: {
     host: &quot;127.0.0.1&quot;,     // Localhost (default: none)
     port: 8545,            // Standard Ethereum port (default: none)
     network_id: &quot;*&quot;,       // Any network (default: none)
    },
```

## Compilation
```
touch .secret
npx truffle compile
```

## Unit test
### Launch local testnet
```
npx ganache -s 0
```

### Test
Open another terminate

```
npx truffle test
```</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-6358/src/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-6358/src/</guid>
      </item>
    
      <item>
        <title>ERC-6604</title>
        <category>/</category>
        
        <description>ERC-6604
========

 * [`AbstractERC20.sol`](/EIPs/assets/eip-6604/contracts/AbstractERC20.sol)
 * [`AbstractToken.sol`](/EIPs/assets/eip-6604/contracts/AbstractToken.sol)
 * [`GenericEIP712.sol`](/EIPs/assets/eip-6604/contracts/GenericEIP712.sol)
 * [`IAbstractToken.sol`](/EIPs/assets/eip-6604/contracts/IAbstractToken.sol)
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-6604/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-6604/</guid>
      </item>
    
      <item>
        <title></title>
        <category>/</category>
        
        <description>&lt;div align=&quot;center&quot;&gt;

# ERC6786 Royalty Debt Registry

&lt;/div&gt;

This project provides a reference implementation of the proposed `ERC-6786 Royalty Debt Registry`.

## Install

In order to install the required dependencies you need to execute:
```shell
npm install
```

## Compile

In order to compile the solidity contracts you need to execute:
```shell
npx hardhat compile
```

## Tests

```shell
npx hardhat test
```</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-6786/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-6786/</guid>
      </item>
    
      <item>
        <title>EIP-6808 implementation</title>
        <category>/</category>
        
        <description># EIP-6808 implementation

This project is a reference implementation of EIP-6808.

Try running some of the following tasks:

```shell
npm i
truffle compile
truffle test
```
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-6808/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-6808/</guid>
      </item>
    
      <item>
        <title>EIP 6809 implementation</title>
        <category>/</category>
        
        <description># EIP 6809 implementation

This project is a reference implementation of EIP-6809.

Try running some of the following tasks:

```shell
npm i
truffle compile
truffle test
```
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-6809/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-6809/</guid>
      </item>
    
      <item>
        <title>ERCxxxx Reference implementation</title>
        <category>/</category>
        
        <description># ERCxxxx Reference implementation
This reference implementation is [MIT](/EIPs/assets/eip-6956/LICENSE) licensed and can therefore be freely used in any project.

## Getting started
From this directory, run 

```
npm install &amp;&amp; npx hardhat test
```



</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-6956/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-6956/</guid>
      </item>
    
      <item>
        <title>EIP 6982 implementation</title>
        <category>/</category>
        
        <description># EIP 6982 implementation

As a reference implementation of EIP-6982 we use the Nduja Labs ERC721Lockable contract.

To run the tests, run the following commands:

```shell
npm i -g pnpm
pnpm i
pnpm test
```
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-6982/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-6982/</guid>
      </item>
    
      <item>
        <title>ERC-7007 Reference Implementation</title>
        <category>/</category>
        
        <description># ERC-7007 Reference Implementation

This is a WIP implementation of ERC-7007 based on the discussions in the [EIP-7007 issue thread](https://github.com/ethereum/EIPs/issues/7007).

## Setup
Run `npm install` in the root directory.

## Testing
Try running some of the following tasks:

```shell
npx hardhat help
npx hardhat test
REPORT_GAS=true npx hardhat test
```

## Metadata Standard

```json
{
    &quot;title&quot;: &quot;AIGC Metadata&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;name&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Identifies the asset to which this NFT represents&quot;
        },
        &quot;description&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Describes the asset to which this NFT represents&quot;
        },
        &quot;image&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive.&quot;
        },

        &quot;prompt&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Identifies the prompt from which this AIGC NFT generated&quot;
        },
        &quot;seed&quot;: {
            &quot;type&quot;: &quot;uint256&quot;,
            &quot;description&quot;: &quot;Identifies the seed from which this AIGC NFT generated&quot;
        },
        &quot;aigc_type&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;image/video/audio...&quot;
        },
        &quot;aigc_data&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;A URI pointing to a resource with mime type image/* representing the asset to which this AIGC NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive.&quot;
        }
    }
}
```</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7007/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7007/</guid>
      </item>
    
      <item>
        <title>Reference implementation of ERC-7208 and usage examples</title>
        <category>/</category>
        
        <description># Reference implementation of ERC-7208 and usage examples
## List of contracts
### Interfaces
- [IDataIndex](/EIPs/assets/eip-7208/contracts/interfaces/IDataIndex.sol) - Interface of **DataIndex**
- [IDataObject](/EIPs/assets/eip-7208/contracts/interfaces/IDataObject.sol) - Interface of **DataObject**
- [IDataPointRegistry](/EIPs/assets/eip-7208/contracts/interfaces/IDataPointRegistry.sol) - Interface of Data Point Registry
- [IIDManager](/EIPs/assets/eip-7208/contracts/interfaces/IIDManager.sol) - Interface for building and querying Data Index user identifiers

### Implementation
- [DataIndex](/EIPs/assets/eip-7208/contracts/DataIndex.sol) - Data Index (implements `IDataIndex` and `IIDManager`)
- [DataPointRegistry](/EIPs/assets/eip-7208/contracts/DataPointRegistry.sol) - Data Point Registry (implements `IDataPointRegistry`)
- [DataPoints](/EIPs/assets/eip-7208/contracts/utils/DataPoints.sol) - Library implementing DataPoint type and its encode/decode functions
- [ChainidTools](/EIPs/assets/eip-7208/contracts/utils/ChainidTools.sol) - Library implementing utility functions to work with chain ids

### Usage examples
- [IFractionTransferEventEmitter](/EIPs/assets/eip-7208/contracts/interfaces/IFractionTransferEventEmitter.sol) - Interface used for **DataManagers** communication to emit ERC20 Transfer events
- [IFungibleFractionsOperations](/EIPs/assets/eip-7208/contracts/interfaces/IFungibleFractionsOperations.sol) - Interface defines **DataObject** operations, which can be called by **DataManager**
- [MinimalisticFungibleFractionsDO](/EIPs/assets/eip-7208/contracts/dataobjects/MinimalisticFungibleFractionsDO.sol) - **DataObject** implements data storage and related logic for token  with Fungible Fractions (like ERC1155)
- [MinimalisticERC1155WithERC20FractionsDataManager](/EIPs/assets/eip-7208/contracts/datamanagers/MinimalisticERC1155WithERC20FractionsDataManager.sol) - **DataManager** implements token with fungible fractions with ERC1155 interface, linked to a DataManager which implements ERC20 interface for same token
- [MinimalisticERC20FractionDataManager](/EIPs/assets/eip-7208/contracts/datamanagers/MinimalisticERC20FractionDataManager.sol) - implements token with ERC20 interface, linked to a **DataManager** which implements ERC1155 interface for same token
- [MinimalisticERC20FractionDataManagerFactory](/EIPs/assets/eip-7208/contracts/datamanagers/MinimalisticERC20FractionDataManagerFactory.sol) - factory of **DataManagers** implementing ERC20 interface for token with fungible fractions

---

An audited implementation can be found [here](https://github.com/Nexera-Foundation/Minimalistic-ERC-7208/).</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7208/contracts/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7208/contracts/</guid>
      </item>
    
      <item>
        <title>PBM Solidity implementation</title>
        <category>/</category>
        
        <description># PBM Solidity implementation

## Description

We provide a list of sample PBM implementation for reference.

### Provided Contracts and Tests

&lt;!-- TBD: Explain the folder structure --&gt;

- `contracts/preloaded-pbm/XXXX.sol` - PBMRC1 implementation contract to demonstrate preloaded PBMs
- `contracts/non-preloaded-pbm/XXXX.sol` - Interface contract
&lt;!-- - `contracts/attest-unlock-pbm/XXXX.sol` - contract to demonstrate a 3rd party attestation to allow unwrap of a PBM --&gt;
- `contracts/XXXX.sol` - Interface contract
- `contracts/ERC20.sol` - ERC20 token contract for unit tests
- `test/XXXXX.js` - Unit tests for livecycle of the PBM implementation

### Used javascript based testing libraries for solidity

&lt;!-- TBD: Fill this up with libraries used --&gt;

- `hardhat`: hardhat allows for testing of contracts with JavaScript via Mocha as the test runner
- `chai`: Chai is an assertion library and provides functions like expect.
- `ethers`: This is a popular Ethereum client library. It allows you to interface with blockchains that implement the Ethereum API.

### Compile and run tests with hardhat

&lt;!-- TBD: Improve this with nix file --&gt;

We provide the essential steps to compile the contracts and run provided unit tests
Check that you have the latest version of npm and node via `npm -version` and `node -v` (should be a LTS version for hardhat support)

1. Check out project
2. Go to folder and initialise a new npm project: `npm init -y`. A basic `package.json` file should occur
3. Install Hardhat as local solidity dev environment: `npx hardhat`
4. Select following option: Create an empty hardhat.config.js
5. Install Hardhat as a development dependency: `npm install --save-dev hardhat`
6. Install further testing dependencies:
   `npm install --save-dev @nomiclabs/hardhat-waffle @nomiclabs/hardhat-ethers ethereum-waffle chai  ethers solidity-coverage`
7. Install open zeppelin contracts: `npm install @openzeppelin/contracts`
8. add plugins to hardhat.config.ts:

```
require(&quot;@nomiclabs/hardhat-waffle&quot;);
require(&apos;solidity-coverage&apos;);
```

9. Adding commands to `package.json`:

```
&quot;scripts&quot;: {
    &quot;build&quot;: &quot;hardhat compile&quot;,
    &quot;test:light&quot;: &quot;hardhat test&quot;,
    &quot;test&quot;: &quot;hardhat coverage&quot;
  },
```

9. run `npm run build`
10. run `npm run test`
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7291/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7291/</guid>
      </item>
    
      <item>
        <title>Ethereum Entity Component System</title>
        <category>/</category>
        
        <description># Ethereum Entity Component System

World contracts are containers for entities, component contracts, and system contracts. Its core principle is to establish the relationship between entities and component contracts, and different entities will attach different components. And use the system contract to dynamically change the data of the entity in the component.
Usual workflow when building ECS-based programs

1. Implement the `IWorld` interface to create a world contract.
2. Call `createEntity()` of the world contract to create an entity.
3. Implement the `IComponent` interface to create a Component contract.
4. Call `registerComponent()` of the world contract to register the component contract.
5. Call `addComponent()` of the world contract to attach the component to the entity.
6. Create a system contract, which is a contract without interface restrictions, and you can define any function in the system contract.
7. Call `registerSystem()` of the world contract to register the system contract.
8. Run the system.

- [`System.sol`](/EIPs/assets/eip-7509/System.sol)
- [`Types.sol`](/EIPs/assets/eip-7509/Types.sol)
- [`World.sol`](/EIPs/assets/eip-7509/World.sol)
- [`Component.sol`](/EIPs/assets/eip-7509/Component.sol)</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7509/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7509/</guid>
      </item>
    
      <item>
        <title>DvP Solidity implementation</title>
        <category>/</category>
        
        <description># DvP Solidity implementation

## Description

The interfaces in this proposal model a functional transaction scheme to establish a secure *delivery-versus-payment*
across two blockchains, where a) no intermediary is required and b) one of the two chains
can securely interact with a stateless &quot;decryption oracle&quot;. Here, *delivery-versus-payment* refers to the exchange of,
e.g., an asset against a payment; however, the concept is generic to make a transfer of one token on one
chain (e.g., the payment) conditional to the successful transfer of another token on another chain (e.g., the asset).

The scheme is realized by two smart contracts, one on each chain.
One smart contract implements the `ILockingContract` interface on one chain (e.g. the &quot;asset chain&quot;), and another smart contract implements the `IDecryptionContract` interface on the other chain (e.g., the &quot;payment chain&quot;).
The smart contract implementing `ILockingContract` locks a token (e.g., the asset) on its chain until a key is presented to encrypt to one of two given values.
The smart contract implementing `IDecryptionContract`, decrypts one of two keys (via the decryption oracle) conditional to the success or failure of the token transfer (e.g., the payment). A stateless decryption oracle is attached to the chain running `IDecryptionContract` for the decryption.

### Provided Contracts

#### DvP

- `contracts/ILockingContract.sol` - Contract locking transfer with given encrypted keys or hashes.
- `contracts/IDecryptionContract.sol` - Contract performing conditional upon transfer decryption (possibly based on an external oracle).

#### Decryption Oracle

- `contracts/IKeyDecryptionOracle.sol` - Interface implemented by a decryption oracle proxy contract.
- `contracts/IKeyDecryptionOracleCallback.sol` - Interface to be implemented by a callback receiving the decrypted key.

### Documentation

- `doc/DvP-Seq-Diag.png` - Sequence diagram of the DvP
- `doc/multi-party-dvp.svg` - Sequence diagram of a multi-party-dvp.

</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7573/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7573/</guid>
      </item>
    
      <item>
        <title>ERC7641: Intrinsic RevShare Token</title>
        <category>/</category>
        
        <description># ERC7641: Intrinsic RevShare Token

An ERC-20 extension that integrates a revenue-sharing mechanism, ensuring tokens intrinsically represent a share of a communal revenue pool
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7641/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7641/</guid>
      </item>
    
      <item>
        <title>EIP-7701: Native Account Abstraction explained</title>
        <category>/</category>
        
        <description># EIP-7701: Native Account Abstraction explained

The purpose of this document is to provide more details about the design of EIP-7701,
while keeping the [Specification](/EIPs/EIPS/eip-7701#specification) section of the core document concise.

## Definitions for terms used in EIP-7701

* **Smart Contract Account**: an Ethereum smart contract that serves as the user&apos;s account and on-chain identity.
  It is responsible for holding user&apos;s assets, verifying user requests, and executing actions on the user&apos;s behalf.
* **Sender**: the Smart Contract Account sending the current AA transaction.
* **Paymaster**: a smart contract that is requested to pay gas fees for the current AA transaction on behalf of the
  `Sender` contract.
* **Deployer**: a smart contract that performs a deployment for a new `Sender` contract if necessary in the context of
  the current AA transaction.
* **Entity**: a common term for any of the smart contracts mentioned above in the context of an EIP-7701 Transaction.
* **Transaction Validity**:
  A property of an Ethereum transaction that describes whether this transaction can be included in a block without a
  violation of the ethereum execution and consensus rules.
  This property depends on both the inputs of the transaction and the current state of the Ethereum blockchain and can
  change over time.
* **EIP-7701 Transaction**: the entire transaction initiated by the `Sender` Smart Contract Account and represented with
  an [EIP-2718](../../EIPS/eip-2718) compatible Transaction Envelope object.
* **Call Frame**: The context and state for a specific function call during contract execution, including input
  parameters, local variables, and the execution environment.
* **Top-Level Call Frame**: The initial execution context of a transaction accessing the contract, the &quot;entry point&quot; to
  the EVM code.
* **EIP-7701 Call Frame**:
  A single atomic element of EVM code execution,
  represented by a single top-level call to a specific address with a given data.\
  An EIP-7701 call frame may contain inner call frames as well, but they are not referred to as &quot;EIP-7701 call frames&quot;.\
  An EIP-7701 call frame may either succeed or revert.
* **Frame&apos;s Role**:
  An identifier of an action that the invoked contract is asked to make during the current call frame.
  An Entity may have one or more roles as part of the EIP-7701 Transaction flow.
* **EIP-7701 Transaction Phase**:
  A set of EIP-7701 Call Frames that form a single step in an EIP-7701 Transaction flow.
  There are two phases in an EIP-7701 Transaction: *validation* and *execution*
* **Validation phase**:
  A set of EIP-7701 Call Frames that define the current EIP-7701 Transaction&apos;s **Validity** by executing the
  **validation** EVM code.
* **Execution phase**:
  A set of EIP-7701 Call Frames that perform the actions according to the `Sender` and the `Paymaster` contracts&apos;
  interpretation of the user input.
  These frames do not define the **Validity** of the transaction.

## A frame context `current_context_role` variable

During the execution of the `Sender`, `Paymaster` or a `Deployer` code as defined by the `AA_TX_TYPE` transaction,
the frame context `current_context_role` variable is set to the corresponding role.

The `current_context_role` remains set only for the top-level frame, as well as for inner frames made in the context of the entity, through an uninterrupted chain of `DELEGATECALL` calls.

By default, the value for `current_context_role` is set to `ROLE_SENDER_EXECUTION`.
Call frames initiated with any opcodes other than `DELEGATECALL` run with the `ROLE_SENDER_EXECUTION` role.

If by the end of the execution of the `Sender`, `Paymaster` or a `Deployer` code
`current_context_role` is not explicitly accepted by using the `ACCEPT_ROLE` opcode,
the EIP-7701 Call Frame reverts.

An EIP-7701 transaction is valid if and only if the following conditions are met for each of
`role_sender_deployment`, `role_sender_validation`, `role_paymaster_validation`:

* The top-level call frame did not revert.
* `ACCEPT_ROLE` was called at least once with the role input parameter equal to `current_context_role` in a frame that did not revert.

### New `TXPARAMLOAD`, `TXPARAMSIZE`, and `TXPARAMCOPY` opcodes

Accessing transaction details within call frames is performed using the new `TXPARAM*` opcode family.
The instructions accept the parameter identifier value that we call `txparam_id`.

The `TXPARAMDLOAD`, `TXPARAMSIZE`, `TXPARAMCOPY` follow the pattern of `CALLDATA*` / `RETURNDATA*` opcode
families.

### Limitations on `TXPARAM*` opcodes

The `TXPARAM*` opcodes are only functional in the top level frames for all roles.
Calling these opcodes in another context returns zero values and zero lengths.

Requesting `execution_status` and `execution_gas_used` parameters outside the `role_paymaster_post_op` role&apos;s frame returns zero values.

Contracts may use `CURRENT_ROLE` (`current_context_role`) to determine the current frame role.

## Paymaster post-operation frame (optional)

This step is performed with the `role_paymaster_post_op` role.

It is intended to provide the Paymaster contract with an opportunity to finalize any calculations after the
results of the Sender Execution are known.

The `execution_status` and `execution_gas_cost` values are runtime introspection parameters only accessible during this frame via the `TXPARAMLOAD` opcode.

The post-operation frame is considered an integral part of the transaction execution phase.
It means that if the post-operation frame reverts its execution, the Sender Execution state changes are also reverted.

## Transaction Execution Flow

All legacy transaction types only have an implicit validation phase where balance, nonce, and signature are checked,
and an implicit execution phase with a single top-level execution frame.

For all legacy transaction types, during the single top-level execution frame,
the `ORIGIN` (`0x32`, `tx.origin`) and `CALLER` (`0x33`, `msg.sender`)
are both equal to the address that is determined by the transaction&apos;s ECDSA signature (`yParity`, `r`, `s`).

When processing an EIP-7701 transaction, however, multiple execution frames will be created.
The full list of possible frames and their corresponding role definitions is as follows:

1. **Validation Phase**
    * `sender` deployment frame (once per account) - `role_sender_deployment`
    * `sender` validation frame (required) - `role_sender_validation`
    * `paymaster` validation frame (optional) - `role_paymaster_validation`
2. **Execution Phase**
    * `sender` execution frame (required) - `role_sender_execution`
    * `paymaster` post-operation frame (optional) - `role_paymaster_post_op`

All execution frames in the **Validation Phase** must be completed successfully without reverting
in order for the transaction to be considered valid for a given position in a block.

## Transaction execution context

Note that some behaviours in the EVM depend on the transaction context. These behaviours include:

1. Costs of the `SSTORE (0x55)` opcode per [EIP-2200](../../EIPS/eip-2200)
2. Costs of accessing cold addresses and slots per [EIP-2929](../../EIPS/eip-2929)
3. Values available within the transient storage per [EIP-1153](../../EIPS/eip-1153)
4. Maximum amount of gas refund assigned after the execution per [EIP-3529](../../EIPS/eip-3529)

These features are not affected by the separation of the transaction into multiple frames.
Meaning, for example, that a value set with `TSTORE (0x5D)` in one frame will remain available in the next one.

### Flow diagrams

#### Simple AA Transaction flow

![Simple AA transaction flow diagram](/EIPs/assets/eip-7701/simple_flow.svg)

#### Complete AA transaction flow

![Simple AA transaction flow diagram](/EIPs/assets/eip-7701/complete_flow.svg)

## Rationale

### Introduction of the `TXPARAM*` opcode family

The validation calls of a Smart Contract Account code need to have full access to the majority of transaction
details in order to be able to make an informed decision about either accepting or rejecting the transaction.

A small subset of this data is available with the existing opcodes, like `CALLER (0x33)` or `GASPRICE  (0x3A)`.
However, creating an opcode for every transaction parameter is not feasible or desirable.

The `TXPARAM*` opcode family provides the Account Abstraction contracts with access to this data.

These values are not made accessible to the transactions&apos; execution or to legacy transaction types.
This limitation prevents the `TXPARAM*` opcode family from becoming a new source of a globally observable state,
which could create backwards compatibility issues in the future.

### Reverting execution on `postOp` frame revert

The `postOp` frame is part of the execution phase and is a way for Paymasters to manage their bookkeeping,
refund the user, and enforce post-execution conditions to make sure the Sender did what the Paymaster expected it to.
It is not a part of transaction validation, meaning that if it reverts, the Paymaster still pays for the transaction.

If the `postOp` frame reverts it indicates that these post-execution conditions, defined by the paymaster, were not met.
This could occur if, for example:

* A user failed to perform the specific action the Paymaster intended to pay for
* A user provided false information during validation that was found to be false when checked in the `postOp` frame.
* An &quot;intent&quot; was not correctly fulfilled by a solver as verified in the `postOp` frame.

By reverting the main execution frame when the `postOp` frame reverts:

* The user receives no value from the transaction, as their intended operation is undone. This removes an important potential incentive for users to exploit the paymaster.
* The paymaster is protected from sponsoring unintended or abusive operations. While the paymaster still incurs the gas costs for the transaction, they prevent non-compliant operation from successfully completing.
* The paymaster is able to identify the offending Sender account and take action, such as refusing future transactions.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7701/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7701/</guid>
      </item>
    
      <item>
        <title>References for ERC-7746</title>
        <category>/</category>
        
        <description># References for ERC-7746

In this directory you can find a reference implementation of the ILayer interface and a sample MockERC20 contract.

In this test, a [Protected.sol](/EIPs/assets/eip-7746/test/Protected.sol) contract is protected by a [RateLimitLayer.sol](/EIPs/assets/eip-7746/test/RateLimitLayer.sol) layer. The RateLimitLayer implements the ILayer interface and enforces a rate which client has configured.
The Drainer simulates a vulnerable contract that acts in a malicious way. In the `test.ts` The Drainer contract is trying to drain the funds from the Protected contract. It is assumed that Protected contract has bug that allows partial unauthorized access to the state.
The RateLimitLayer is configured to allow only 10 transactions per block from same sender. The test checks that the Drainer contract is not able to drain the funds from the Protected contract.</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7746/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7746/</guid>
      </item>
    
      <item>
        <title>ERC-7818</title>
        <category>/</category>
        
        <description># ERC-7818

This is reference implementation of ERC-7818

## Implementation Describe

#### Sliding Window Algorithm to look for expiration balance

This contract creates an abstract implementation that adopts the `Sliding Window Algorithm` to maintain a window over a period of time (block height). This efficient approach allows for the look back and calculation of `usable balances` for each account within that window period. With this approach, the contract does not require a variable acting as a `counter` or a `state` to keep updating the latest state, nor does it need any interaction calls to keep updating the current period, which is an effortful and costly design.

&lt;p align=&quot;center&quot;&gt;
    &lt;img src=&quot;implementation.svg&quot; alt=&quot;Sliding Window Maintain Balance is Epoch&quot;&gt;
&lt;/p&gt;

#### `epoch` and `list` for storing data in vertical and horizontal way

```solidity
    // skipping

    struct Epoch {
        uint256 totalBalance;
        mapping(uint256 =&gt; uint256) blockBalances;
        SortedList.List list;
    }

    // skipping

    // O(n→) fot traversal each epoch.
    // O(n↓) for traversal each element in list.
    mapping(uint256 =&gt; mapping(address =&gt; Epoch))) private _balances;
    mapping(uint256 =&gt; uint256) private _worldStateBalance;
```

With `epoch` it provides an abstract loop in a horizontal way more efficient for calculating the usable balance of the account because it provides `totalBalance` which acts as suffix balance, so you don&apos;t need to get to iterate or traversal over the `list` in vertical to calculate the entire balance if the `epoch` can presume not to expire.
The `_worldStateBalance` mapping tracks the total token balance across all accounts that minted tokens within a particular block. This structure allows the contract to trace expired balances easily. By consolidating balance data for each block.

#### Buffering 1 `epoch` rule for ensuring safety

In this design, the buffering slot is the critical element that requires careful calculation to ensure accurate handling of balances nearing expiration. By incorporating this buffer, the contract guarantees that any expiring balance is correctly accounted for within the sliding window mechanism, ensuring reliability and preventing premature expiration or missed balances.

#### First-In-First-Out (FIFO) priority to enforce token expiration rules

Enforcing `FIFO` priority ensures that tokens nearing expiration are processed before newer ones, aligning with the token lifecycle and expiration rules. This method eliminates the need for additional `off-chain` computation and ensures that all token processing occurs efficiently `on-chain`, fully compliant with the ERC20 interface.
A **sorted** list is integral to this approach. Each `epoch` maintains its own list, sorted by token creation which is can be `block.timestamp` or `blocknumber`, preventing any overlap with other `epoch`. This separation ensures that tokens in one `epoch` do not interfere with the balance handling in another. The contract can then independently manage token expirations within each `epoch`, minimizing computation while maintaining accuracy and predictability in processing balances.

---

#### Token Receipt and Transaction Likelihood across various blocktime

Assuming each year contains 4 `epoch`, which aligns with familiar time-based divisions like a year being divided into four quarters, the following table presents various scenarios based on block time and token receipt intervals. It illustrates the potential transaction frequency and likelihood of receiving tokens within a given period.

| Block Time (ms) | Receive Token Every (ms) | Index/Epoch | Frequency           | Likelihood    |
| --------------- | ------------------------ | ----------- | ------------------- | ------------- |
| 100             | 100                      | 78,892,315  | 864,000 _times/day_ | Very Unlikely |
| 500             | 500                      | 15,778,463  | 172,800 _times/day_ | Very Unlikely |
| 1000            | 1000                     | 7,889,231   | 86,400 _times/day_  | Very Unlikely |
| 1000            | 28,800,000               | 273         | 3 _times/day_       | Unlikely      |
| 1000            | 86,400,000               | 91          | 1 _times/day_       | Possible      |
| 5000            | 86,400,000               | 18          | 1 _times/month_     | Very Likely   |
| 10000           | 86,400,000               | 9           | 3 _times/month_     | Very Likely   |

&gt; [!IMPORTANT]  
&gt; - Transactions per day are assumed based on loyalty point earnings.
&gt; - Likelihood varies depending on the use case; for instance, gaming use cases may have higher transaction volumes than the given estimates.

## Security Considerations in The Reference Implementation

- Solidity Division Rounding Down This implementation contract may encounter scenarios where the calculated expiration block is shorter than the actual expiration block. However, contract mitigates this risk by enforcing valid block times within the defined limits of `MINIMUM_BLOCK_TIME` and `MAXIMUM_BLOCK_TIME`.

## Usage

#### Install Dependencies
```bash
yarn install
```

#### Compile the Contract
Compile the reference implementation
```bash
yarn compile
```

#### Run Tests
Execute the provided test suite to verify the contract&apos;s functionality and integrity
```bash
yarn test
```

### Cleaning Build Artifacts
To clean up compiled files and artifacts generated during testing or deployment
```bash
yarn clean
```</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7818/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7818/</guid>
      </item>
    
      <item>
        <title>ERC-7858</title>
        <category>/</category>
        
        <description># ERC-7858

This is reference implementation of ERC-7858

## Implementation Describe

### Per-Token Expiry

Default `ERC7858` is each token has its own independent start and end date, stored using `block.timestamp` or `block.number`. This provides flexibility, allowing tokens to expire at different dates/blocks.

### Epoch-based Expiry

`ERC7858Epoch` similar to ERC-7818, this method enforces a shared lifetime duration for all tokens, ensuring they expire simultaneously. This can be useful for fixed-term subscriptions or time-based access control.

## Usage

#### Install Dependencies
```bash
yarn install
```

#### Compile the Contract
Compile the reference implementation
```bash
yarn compile
```

#### Run Tests
Execute the provided test suite to verify the contract&apos;s functionality and integrity
```bash
yarn test
```

### Cleaning Build Artifacts
To clean up compiled files and artifacts generated during testing or deployment
```bash
yarn clean
```
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7858/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7858/</guid>
      </item>
    
      <item>
        <title>NTT-EIP as a building block for FALCON, DILITHIUM and STARK verifiers</title>
        <category>/</category>
        
        <description># NTT-EIP as a building block for FALCON, DILITHIUM and STARK verifiers

This repository contains the EIP for NTT transform, along with a python reference code, and a solidity implementation.

## Context 

### The threat
With the release of Willow cheap, the concern for quantum threat against Ethereum seems to accelerate. Post by [Asanso](https://ethresear.ch/t/so-you-wanna-post-quantum-ethereum-transaction-signature/21291) and [PMiller](https://ethresear.ch/t/tidbits-of-post-quantum-eth/21296) summarize those stakes and possible solutions. Those solutions include use of lattice based signatures such as Dillithium or FALCON (the latter being more optimized for onchain constraints), STARKs and FHE. There is a consensus in the cryptographic research community around lattices as the future of asymetric protocols, and STARKs won the race for ZKEVMs implementation (as used by Scroll, Starknet and ZKsync).

Those protocols have in common to require fast polynomial multiplication over prime fields, and use NTT (a special [FFT](https://vitalik.eth.limo/general/2019/05/12/fft.html) adapted to prime fields). While in the past Montgomery multipliers over elliptic curve fields were the critical target of optimizations (both hardware and software), NTT optimization is the key to a performant PQ implementation.

### Discussion

In the past Ethereum chose specificity by picking secp256k1 as its sole candidate for signature. Later, after dedicated hardware and proving systems working on other hardwares were realeased, a zoo of EIP flourished to propose alternative curves. There where attempt to have higher level EIPs to enable all of those at once, such as EWASM, SIMD, EVMMAX,  or RIP7696 (by decreasing order of genericity and complexity).

Picking NTT as EIP instead of a given scheme would provide massive gas cost reduction for all schemes relying on it.
- **pros** : massive reduction to all cited protocols, more agility for evolutions.
- **cons**:  requires to be wrapped into  implementations, not optimal for a given target compared to dedicated EIP, not stateless.

## Overview

The NTT operates on sequences of numbers (often coefficients of polynomials) in a modular arithmetic system. It maps these sequences into a different domain where convolution operations (e.g., polynomial multiplication) become simpler and faster, akin to how FFT simplifies signal convolution. Compared to FFT which uses root of unity in complex plane, NTT uses roots of unity in a finite field or ring. 

The NTT is based on the Discrete Fourier Transform (DFT), defined as:
$$
X[k] = \sum_{j=0}^{N-1} x[j] \cdot \omega^{j \cdot k} \mod q$$

Where:
- $x[j]$: Input sequence of length N.
- $X[k]$: Transformed sequence,
- $q$: A prime modulus,
- $\omega$: A primitive N-th root of unity modulo $q$, with
$\omega^N \equiv 1 \mod q \quad \text{and} \quad \omega^k \not\equiv 1 \mod q \; \forall \; 0 &lt; k &lt; N$

NTT computation uses the a similar approach as Cooley-Tukey algorithm to provide a O(N log N) complexity. The NTT algorithm transforms a sequence $(x[j])$ to $(X[k])$ using modular arithmetic. It is invertible, allowing reconstruction of the original sequence via the Inverse NTT (INTT). The inverse process is similar but requires dividing by \(N\) (mod \(q\)) and using $(\omega^{-1}$) (the modular inverse of $\omega$). The following algorithm is extracted from 
[[LN16]](https://eprint.iacr.org/2016/504.pdf), and describe how to compute the NTT when $R_q= \mathbb{Z}_q[X]/X^n+1$ (Negative Wrap Convolution).

![alt text](/EIPs/assets/eip-7885/image.png)

The Inverse NTT is computed through the following algorithm:

![alt text](/EIPs/assets/eip-7885/image-1.png)

## Benchmarks

### Python

| Field | $n$ | Recursive NTT (Tetration) | Iterative NTT (ZKNox) | Iterative InvNTT (ZKNox)|
|-|-|-|-|-|
|Falcon   | 512  | 761 μs  | 528 μs  | 561 μs  |
|Falcon   | 1024 | 1642 μs | 1076 μs | 1199 μs |
|Dilithium| 128  | 165 μs  | 114 μs  | 113 μs  |
|Dilithium| 256  | 371 μs  | 258 μs  | 260 μs  |
|BabyBear | 256  | 531 μs  | 389 μs  | 404 μs  |

The recursive inverse NTT is very costly because of the required inversions. For Falcon, the field is small enough so that field inversions can be precomputed, but the cost is still higher than the iterative inverse NTT.
The field arithmetic has not been optimized. In the case of BabyBear, this becomes significant and so the comparison is not really significant.

### Solidity


| Function                   | Description               | gas cost | Tests Status |
|------------------------|---------------------|---------------------|---------------------|
| NTT recursive       | original gas cost from [falcon-solidity](https://github.com/Tetration-Lab/falcon-solidity/blob/main/src/Falcon.sol)         | 6.9M | OK|
| InvNTT recursive          | original gas cost from [falcon-solidity](https://github.com/Tetration-Lab/falcon-solidity/blob/main/src/Falcon.sol)  | 7.8M | OK|
| Full Falcon verification         | original gas cost from [falcon-solidity](https://github.com/Tetration-Lab/falcon-solidity/blob/main/src/Falcon.sol)  | 24 M| OK|
| NTT iterative      | ZKNOX  |  4M | OK|
|  InvNTT iterative       | ZKNOX | 4.2M | OK|
| Full Falcon verification          | ZKNOX  | 8.5 M| OK|


### Yul


Further optimizations are reached by using Yul for critical sections and using the CODECOPY and EXTCODECOPY trick detailed in of [[RD23]](https://eprint.iacr.org/2023/939.pdf) (section 3.3, &quot;Hacking EVM memory access cost&quot;). 


| Function                   | Description               | gas cost | Tests Status |
|------------------------|---------------------|---------------------|---------------------|
| ntt.NTTFW       | ZKNOX_NTTFW, iterative yuled    | 1.9M | OK|
| falcon.verify_opt       | Full falcon verification with precomputated pubkey         | 3.6M | OK|

### Go Ethereum (WIP)

ZKNOX is planning a client implementation for node of the considered EIP.

## Conclusion

We provided an optimized version of FALCON, using an optimized version of NTT. This code can be used to speed up Stark verification as well as other lattices primitives (Dilithium, Kyber, etc.). While it seems achievable to use FALCON as a progressive precompile, the cost remains very high. Using a client implementation with NTT-EIP (in a Geth fork for example), ETHEREUM could become from a PQ-Friendly and ZK-Friendly chain. This work is supported by the Ethereum Foundation.


## References

- [[LN16]](https://eprint.iacr.org/2016/504.pdf) Speeding up the Number Theoretic Transform for Faster Ideal Lattice-Based Cryptography. Patrick Longa, Michael Naehrig.
- [[EIP616]](https://eips.ethereum.org/EIPS/eip-616) EIP-616: SIMD Operations for the EVM. Greg Colvin.
- [[RD23]](https://eprint.iacr.org/2023/939.pdf) Speeding up elliptic computations for Ethereum Account Abstraction. Renaud Dubois.
- [[DILITHIUM]](https://eprint.iacr.org/2017/633.pdf) CRYSTALS-Dilithium: A Lattice-Based Digital Signature Scheme. Léo Ducas, Eike Kiltz, Tancrède Lepoint, Vadim Lyubashevsky, Peter Schwabe, Gregor Seiler and Damien Stehlé.</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7885/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7885/</guid>
      </item>
    
      <item>
        <title>Optimism-geth with NTT Precompiles (liboqs Implementation)</title>
        <category>/</category>
        
        <description># Optimism-geth with NTT Precompiles (liboqs Implementation)

Fork of `op-geth` with precompiled contracts for Number Theoretic Transform (NTT) operations using open-quantum-safe liboqs via CGO bindings, enabling efficient on-chain post-quantum cryptographic operations.

## Precompiled Contracts

| Address | Name      | Description                                                            |
| ------- | --------- | ---------------------------------------------------------------------- |
| `0x12`  | NTT_FW    | Forward NTT using liboqs (Falcon-512/1024, ML-DSA)                     |
| `0x13`  | NTT_INV   | Inverse NTT using liboqs (same schemes as NTT_FW)                      |
| `0x14`  | VECMULMOD | Element-wise modular multiplication: `result[i] = (a[i] * b[i]) mod q` |
| `0x15`  | VECADDMOD | Element-wise modular addition: `result[i] = (a[i] + b[i]) mod q`       |

### Supported Schemes

| Scheme      | Ring Degree | Modulus | Element Size     |
| ----------- | ----------- | ------- | ---------------- |
| Falcon-512  | 512         | 12289   | uint16 (2 bytes) |
| Falcon-1024 | 1024        | 12289   | uint16 (2 bytes) |
| ML-DSA      | 256         | 8380417 | int32 (4 bytes)  |

## Installation

### 1. Install liboqs with NTT CGO Bindings

```bash
# Clone and install dependencies
git clone -b feature/ntt-cgo-bindings https://github.com/yhl125/liboqs.git
sudo apt install astyle cmake gcc ninja-build libssl-dev python3-pytest python3-pytest-xdist unzip xsltproc doxygen graphviz python3-yaml valgrind pkg-config

# Build liboqs and Go bindings
cd liboqs/bindings/go
make all
```

### 2. Configure Environment

```bash
# Set paths (adjust to your installation directory)
export PKG_CONFIG_PATH=/path/to/liboqs/bindings/go/.config:$PKG_CONFIG_PATH
export DYLD_LIBRARY_PATH=/path/to/liboqs/build/lib:$DYLD_LIBRARY_PATH  # macOS
export LD_LIBRARY_PATH=/path/to/liboqs/build/lib:$LD_LIBRARY_PATH      # Linux
```

### 3. Build op-geth

```bash
make geth
```

## API Reference

### NTT_FW (0x12) - Forward Transform

Transforms coefficients into NTT domain using liboqs.

**Input:**

```
[0:4]   ring_degree (uint32, big-endian)
[4:12]  modulus (uint64, big-endian)
[12:*]  coefficients (Falcon: uint16×N, ML-DSA: int32×N, big-endian)
```

**Output:** NTT-transformed coefficients (same format as input)

**Gas Cost:**

- Falcon-512: 500 gas (~9.4μs, 53 mgas/s)
- Falcon-1024: 1,080 gas (~20.4μs, 53 mgas/s)
- ML-DSA: 256 gas (~4.8μs, 53 mgas/s)

### NTT_INV (0x13) - Inverse Transform

Transforms NTT domain coefficients back to standard representation.

**Input:** Same as NTT_FW (coefficients in NTT domain)

**Output:** Coefficients in standard representation

**Gas Cost:**

- Falcon-512: 500 gas (~9.4μs, 53 mgas/s)
- Falcon-1024: 1,080 gas (~20.3μs, 53 mgas/s)
- ML-DSA: 340 gas (~6.4μs, 53 mgas/s)

### VECMULMOD (0x14) - Vector Multiplication

Element-wise modular multiplication in NTT domain.

**Input:**

```
[0:4]   ring_degree (uint32, big-endian)
[4:12]  modulus (uint64, big-endian)
[12:12+n*size] vector_a
[12+n*size:*]  vector_b
```

**Output:** Element-wise product `(a[i] * b[i]) mod q`

**Gas Cost:** `ceil(0.32 × n)`

- Falcon-512: 164 gas (~2.9μs, 56 mgas/s)
- Falcon-1024: 328 gas (~6.0μs, 55 mgas/s)
- ML-DSA: 82 gas (~2.0μs, 42 mgas/s)

### VECADDMOD (0x15) - Vector Addition

Element-wise modular addition.

**Input:** Same as VECMULMOD

**Output:** Element-wise sum `(a[i] + b[i]) mod q`

**Gas Cost:** `ceil(0.3 × n)`

- Falcon-512: 154 gas (~2.8μs, 55 mgas/s)
- Falcon-1024: 308 gas (~5.8μs, 53 mgas/s)
- ML-DSA: 77 gas (~1.6μs, 47 mgas/s)

## Testing

```bash
cd core/vm

# All NTT tests
go test -v -run TestPrecompiled.*NTT

# Specific tests
go test -v -run TestPrecompiledNTT_FW
go test -v -run TestPrecompiledNTT_VECMULMOD

# Benchmarks
go test -bench=BenchmarkPrecompiledNTT -benchtime=5s
```

**Test Coverage:**

- Scheme detection (Falcon-512/1024, ML-DSA)
- Input validation (malformed inputs, invalid parameters)
- Round-trip verification (`INTT(NTT(x)) = x`)
- Cross-scheme isolation
- Performance benchmarks with crypto standards

### Benchmark Results

Benchmarks were run on an Intel(R) Xeon(R) CPU @ 2.20GHz. For detailed results, please see the files below:

- [Ecrecover Benchmark Test Results](/EIPs/assets/eip-7885/op-geth/cgo/benchmark_results/BenchmarkPrecompiledEcrecover)
- [NTT &amp; NTT Vector Operations Benchmark Test Results](/EIPs/assets/eip-7885/op-geth/cgo/benchmark_results/BenchmarkPrecompiledNTT)
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7885/op-geth/cgo/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7885/op-geth/cgo/</guid>
      </item>
    
      <item>
        <title>Optimism-geth with Pure Go NTT Precompiles</title>
        <category>/</category>
        
        <description># Optimism-geth with Pure Go NTT Precompiles

Fork of `op-geth` with precompiled contracts for Number Theoretic Transform (NTT) operations implemented in pure Go, enabling efficient on-chain post-quantum cryptographic operations without external dependencies.

## Precompiled Contracts

| Address | Name      | Description                                                            |
| ------- | --------- | ---------------------------------------------------------------------- |
| `0x12`  | NTT_FW    | Forward NTT (Falcon-512/1024, ML-DSA)                                  |
| `0x13`  | NTT_INV   | Inverse NTT (Falcon-512/1024, ML-DSA)                                  |
| `0x14`  | VECMULMOD | Element-wise modular multiplication: `result[i] = (a[i] * b[i]) mod q` |
| `0x15`  | VECADDMOD | Element-wise modular addition: `result[i] = (a[i] + b[i]) mod q`       |

### Supported Schemes

| Scheme      | Ring Degree | Modulus | Element Size     |
| ----------- | ----------- | ------- | ---------------- |
| Falcon-512  | 512         | 12289   | uint16 (2 bytes) |
| Falcon-1024 | 1024        | 12289   | uint16 (2 bytes) |
| ML-DSA      | 256         | 8380417 | int32 (4 bytes)  |

## Implementation Details

This implementation uses **pure Go** for all NTT operations, located in `crypto/ntt/`:

- `falcon.go`: Falcon NTT with Montgomery arithmetic
- `falcon_tables.go`: Pre-computed twiddle factors for Falcon
- `dilithium.go`: ML-DSA/Dilithium NTT implementation
- `dilithium_tables.go`: Pre-computed zetas for ML-DSA

## API Reference

### NTT_FW (0x12) - Forward Transform

Transforms coefficients into NTT domain.

**Input:**

```
[0:4]   ring_degree (uint32, big-endian)
[4:12]  modulus (uint64, big-endian)
[12:*]  coefficients (Falcon: uint16×N, ML-DSA: int32×N, big-endian)
```

**Output:** NTT-transformed coefficients (same format as input)

**Gas Cost:**

- Falcon-512: 790 gas
- Falcon-1024: 1,750 gas
- ML-DSA: 220 gas

### NTT_INV (0x13) - Inverse Transform

Transforms NTT domain coefficients back to standard representation.

**Input:** Same as NTT_FW (coefficients in NTT domain)

**Output:** Coefficients in standard representation

**Gas Cost:**

- Falcon-512: 790 gas
- Falcon-1024: 1,750 gas
- ML-DSA: 270 gas

### VECMULMOD (0x14) - Vector Multiplication

Element-wise modular multiplication in NTT domain.

**Input:**

```
[0:4]   ring_degree (uint32, big-endian)
[4:12]  modulus (uint64, big-endian)
[12:12+n*size] vector_a
[12+n*size:*]  vector_b
```

**Output:** Element-wise product `(a[i] * b[i]) mod q`

**Gas Cost:** `ceil(0.32 × n)`

- Falcon-512: 164 gas
- Falcon-1024: 328 gas
- ML-DSA: 82 gas

### VECADDMOD (0x15) - Vector Addition

Element-wise modular addition.

**Input:** Same as VECMULMOD

**Output:** Element-wise sum `(a[i] + b[i]) mod q`

**Gas Cost:** `ceil(0.3 × n)`

- Falcon-512: 154 gas
- Falcon-1024: 308 gas
- ML-DSA: 77 gas

## Testing

```bash
cd core/vm

# All NTT tests
go test -v -run TestPrecompiled.*NTT
go test -v -run TestPrecompiledVectorOp

# Benchmarks
go test -bench=BenchmarkPrecompiledNTT
```

**Test Coverage:**

- Scheme detection (Falcon-512/1024, ML-DSA)
- Input validation (malformed inputs, invalid parameters)
- Round-trip verification (`INTT(NTT(x)) = x`)
- Cross-scheme isolation
- Performance benchmarks

### Benchmark Results

Benchmarks were run on an Intel(R) Xeon(R) CPU @ 2.20GHz. For detailed results, please see:

- [Ecrecover Benchmark Test Results](/EIPs/assets/eip-7885/op-geth/nocgo/benchmark_results/BenchmarkPrecompiledEcrecover)
- [NTT &amp; NTT Vector Operations Benchmark Test Results](/EIPs/assets/eip-7885/op-geth/nocgo/benchmark_results/BenchmarkPrecompiledNTT)
</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7885/op-geth/nocgo/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7885/op-geth/nocgo/</guid>
      </item>
    
      <item>
        <title>NTT</title>
        <category>/</category>
        
        <description># NTT
Generic implementation of the Number Theoretic Transform in the context of cryptography applications.

We provide tests for various NTT-friendly rings, including Falcon&apos;s ring with `q = 12*1024+1` and the defining polynomial `x¹⁰²⁴+1`.

The implementation requires the file `ntt_constants.py`, generated using `python generate_constants.py`.

## Install
```
make install
```

## Tests
For running all tests:
```
make test
```
For running a specific test, use:
```
make test TEST=test_ntt_recursive.TestNTTRecursive.test_ntt_intt
```

## Benchmarks
For running the benchmarks:
```
make bench
```
Note that the field arithmetic is not optimized. For example, Montgomery multiplication is not implemented here.</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7885/pythonref/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7885/pythonref/</guid>
      </item>
    
      <item>
        <title>ERC-7943 uRWA Minimal Package</title>
        <category>/</category>
        
        <description># ERC-7943 uRWA Minimal Package

## Install dependencies
```bash
forge install OpenZeppelin/openzeppelin-contracts
forge install foundry-rs/forge-std
```

## Build
```bash
forge build
```

## Test
```bash
forge test -vv
```

## Gas report
```bash
forge test --gas-report
```

## Coverage
```bash
forge coverage
```</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-7943/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-7943/</guid>
      </item>
    
      <item>
        <title>KAT vectors</title>
        <category>/</category>
        
        <description># KAT vectors
We provide two files containing Known Answer Test vectors:
- [mldsa_nist.rsp](/EIPs/assets/eip-8051/mldsa_nist.rsp) containing the NIST submission KAT file for security level II,
- [mldsa_evm.rsp](/EIPs/assets/eip-8051/mldsa_evm.rsp) containing test vectors for the EVM-friendly version with the same format as NIST.

</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-8051/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-8051/</guid>
      </item>
    
      <item>
        <title></title>
        <category>/</category>
        
        <description>Groups reference implementation assets

- After creating the Ethereum Magicians discussion, update `discussions-to` in `ERCS/erc-8063.md` with the live URL.
- Contracts:
  - `IERC8063.sol`: interface
  - `ERC8063.sol`: minimal implementation
  - `ERC8063ERC20.sol`: optional ERC-20 compatibility implementation (decimals=0)


</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/assets/eip-8063/</link>
        <guid isPermaLink="true">https://eips.ethereum.org/assets/eip-8063/</guid>
      </item>
    
      <item>
        <title></title>
        <category>/</category>
        
        <description>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;{% if page.xsl %}&lt;?xml-stylesheet type=&quot;text/xml&quot; href=&quot;{{ &apos;/feed.xslt.xml&apos; | absolute_url }}&quot;?&gt;{% endif %}&lt;feed xmlns=&quot;http://www.w3.org/2005/Atom&quot; {% if site.lang %}xml:lang=&quot;{{ site.lang }}&quot;{% endif %}&gt;&lt;generator uri=&quot;https://jekyllrb.com/&quot; version=&quot;{{ jekyll.version }}&quot;&gt;Jekyll&lt;/generator&gt;&lt;link href=&quot;{{ page.url | absolute_url }}&quot; rel=&quot;self&quot; type=&quot;application/atom+xml&quot; /&gt;&lt;link href=&quot;{{ &apos;/&apos; | absolute_url }}&quot; rel=&quot;alternate&quot; type=&quot;text/html&quot; {% if site.lang %}hreflang=&quot;{{ site.lang }}&quot; {% endif %}/&gt;&lt;updated&gt;{{ site.time | date_to_xmlschema }}&lt;/updated&gt;&lt;id&gt;{{ page.url | absolute_url | xml_escape }}&lt;/id&gt;{% assign title = site.title | default: site.name %}{% if page.collection != &quot;posts&quot; %}{% assign collection = page.collection | capitalize %}{% assign title = title | append: &quot; | &quot; | append: collection %}{% endif %}{% if page.category %}{% assign category = page.category | capitalize %}{% assign title = title | append: &quot; | &quot; | append: category %}{% endif %}{% if title %}&lt;title type=&quot;html&quot;&gt;{{ title | smartify | xml_escape }}&lt;/title&gt;{% endif %}{% if site.description %}&lt;subtitle&gt;{{ site.description | xml_escape }}&lt;/subtitle&gt;{% endif %}{% if site.author %}&lt;author&gt;&lt;name&gt;{{ site.author.name | default: site.author | xml_escape }}&lt;/name&gt;{% if site.author.email %}&lt;email&gt;{{ site.author.email | xml_escape }}&lt;/email&gt;{% endif %}{% if site.author.uri %}&lt;uri&gt;{{ site.author.uri | xml_escape }}&lt;/uri&gt;{% endif %}&lt;/author&gt;{% endif %}{% if page.tags %}{% assign posts = site.tags[page.tags] %}{% else %}{% assign posts = site[page.collection] %}{% endif %}{% if page.category %}{% assign posts = posts | where: &quot;category&quot;, page.category %}{% endif %}{% unless site.show_drafts %}{% assign posts = posts | where_exp: &quot;post&quot;, &quot;post.draft != true&quot; %}{% endunless %}{% assign posts = posts | sort: &quot;date&quot; | reverse %}{% assign posts_limit = site.feed.posts_limit | default: 10 %}{% for post in posts limit: posts_limit %}&lt;entry{% if post.lang %}{{&quot; &quot;}}xml:lang=&quot;{{ post.lang }}&quot;{% endif %}&gt;{% assign post_title = post.title | smartify | strip_html | normalize_whitespace | xml_escape %}&lt;title type=&quot;html&quot;&gt;{{ post_title }}&lt;/title&gt;&lt;link href=&quot;{{ post.url | absolute_url }}&quot; rel=&quot;alternate&quot; type=&quot;text/html&quot; title=&quot;{{ post_title }}&quot; /&gt;&lt;published&gt;{{ post.date | date_to_xmlschema }}&lt;/published&gt;&lt;updated&gt;{{ post.last_modified_at | default: post.date | date_to_xmlschema }}&lt;/updated&gt;&lt;id&gt;{{ post.id | absolute_url | xml_escape }}&lt;/id&gt;{% assign excerpt_only = post.feed.excerpt_only | default: site.feed.excerpt_only %}{% unless excerpt_only %}&lt;content type=&quot;html&quot; xml:base=&quot;{{ post.url | absolute_url | xml_escape }}&quot;&gt;{{ post.content | strip | xml_escape }}&lt;/content&gt;{% endunless %}{% assign post_author = post.author | default: post.authors[0] | default: site.author %}{% assign post_author = site.data.authors[post_author] | default: post_author %}{% assign post_author_email = post_author.email | default: nil %}{% assign post_author_uri = post_author.uri | default: nil %}{% assign post_author_name = post_author.name | default: post_author %}&lt;author&gt;&lt;name&gt;{{ post_author_name | default: &quot;&quot; | xml_escape }}&lt;/name&gt;{% if post_author_email %}&lt;email&gt;{{ post_author_email | xml_escape }}&lt;/email&gt;{% endif %}{% if post_author_uri %}&lt;uri&gt;{{ post_author_uri | xml_escape }}&lt;/uri&gt;{% endif %}&lt;/author&gt;{% if post.category %}&lt;category term=&quot;{{ post.category | xml_escape }}&quot; /&gt;{% elsif post.categories %}{% for category in post.categories %}&lt;category term=&quot;{{ category | xml_escape }}&quot; /&gt;{% endfor %}{% endif %}{% for tag in post.tags %}&lt;category term=&quot;{{ tag | xml_escape }}&quot; /&gt;{% endfor %}{% if post.excerpt and post.excerpt != empty %}&lt;summary type=&quot;html&quot;&gt;{{ post.excerpt | strip_html | normalize_whitespace | xml_escape }}&lt;/summary&gt;{% endif %}{% assign post_image = post.image.path | default: post.image %}{% if post_image %}{% unless post_image contains &quot;://&quot; %}{% assign post_image = post_image | absolute_url %}{% endunless %}&lt;media:thumbnail xmlns:media=&quot;http://search.yahoo.com/mrss/&quot; url=&quot;{{ post_image | xml_escape }}&quot; /&gt;&lt;media:content medium=&quot;image&quot; url=&quot;{{ post_image | xml_escape }}&quot; xmlns:media=&quot;http://search.yahoo.com/mrss/&quot; /&gt;{% endif %}&lt;/entry&gt;{% endfor %}&lt;/feed&gt;</description>
        <pubDate></pubDate>
        <link>https://eips.ethereum.org/feed.xml</link>
        <guid isPermaLink="true">https://eips.ethereum.org/feed.xml</guid>
      </item>
    
      <item>
        <title>EIP Purpose and Guidelines</title>
        <category>Meta/</category>
        
        <description>## What is an EIP?

EIP stands for Ethereum Improvement Proposal. An EIP is a design document providing information to the Ethereum community, or describing a new feature for Ethereum or its processes or environment. The EIP should provide a concise technical specification of the feature and a rationale for the feature. The EIP author is responsible for building consensus within the community and documenting dissenting opinions.

## EIP Rationale

We intend EIPs to be the primary mechanisms for proposing new features, for collecting community technical input on an issue, and for documenting the design decisions that have gone into Ethereum. Because the EIPs are maintained as text files in a versioned repository, their revision history is the historical record of the feature proposal.

For Ethereum implementers, EIPs are a convenient way to track the progress of their implementation. Ideally, each implementation maintainer would list the EIPs that they have implemented. This will give end users a convenient way to know the current status of a given implementation or library.

## EIP Types

There are three types of EIP:

- A **Standards Track EIP** describes any change that affects most or all Ethereum implementations, such as: a change to the network protocol, a change in block or transaction validity rules, proposed application standards/conventions, or any change or addition that affects the interoperability of applications using Ethereum. Standards Track EIPs consist of three parts—a design document, an implementation, and (if warranted) an update to the [formal specification](https://github.com/ethereum/yellowpaper). Furthermore, Standards Track EIPs can be broken down into the following categories:
  - **Core**: improvements requiring a consensus fork (e.g. [EIP-5](/EIPs/EIPS/eip-5), [EIP-101](/EIPs/EIPS/eip-101)), as well as changes that are not necessarily consensus critical but may be relevant to [“core dev” discussions](https://github.com/ethereum/pm) (for example, [EIP-90], and the miner/node strategy changes 2, 3, and 4 of [EIP-86](/EIPs/EIPS/eip-86)).
  - **Networking**: includes improvements around [devp2p](https://github.com/ethereum/devp2p/blob/readme-spec-links/rlpx.md) ([EIP-8](/EIPs/EIPS/eip-8)) and [Light Ethereum Subprotocol](https://ethereum.org/en/developers/docs/nodes-and-clients/#light-node), as well as proposed improvements to network protocol specifications of [whisper](https://github.com/ethereum/go-ethereum/issues/16013#issuecomment-364639309) and [swarm](https://github.com/ethereum/go-ethereum/pull/2959).
  - **Interface**: includes improvements around language-level standards like method names ([EIP-6](/EIPs/EIPS/eip-6)) and [contract ABIs](https://docs.soliditylang.org/en/develop/abi-spec.html).
  - **ERC**: application-level standards and conventions, including contract standards such as token standards ([ERC-20](/EIPs/EIPS/eip-20)), name registries ([ERC-137](/EIPs/EIPS/eip-137)), URI schemes, library/package formats, and wallet formats.

- A **Meta EIP** describes a process surrounding Ethereum or proposes a change to (or an event in) a process. Process EIPs are like Standards Track EIPs but apply to areas other than the Ethereum protocol itself. They may propose an implementation, but not to Ethereum&apos;s codebase; they often require community consensus; unlike Informational EIPs, they are more than recommendations, and users are typically not free to ignore them. Examples include procedures, guidelines, changes to the decision-making process, and changes to the tools or environment used in Ethereum development. Any meta-EIP is also considered a Process EIP.

- An **Informational EIP** describes an Ethereum design issue, or provides general guidelines or information to the Ethereum community, but does not propose a new feature. Informational EIPs do not necessarily represent Ethereum community consensus or a recommendation, so users and implementers are free to ignore Informational EIPs or follow their advice.

It is highly recommended that a single EIP contain a single key proposal or new idea. The more focused the EIP, the more successful it tends to be. A change to one client doesn&apos;t require an EIP; a change that affects multiple clients, or defines a standard for multiple apps to use, does.

An EIP must meet certain minimum criteria. It must be a clear and complete description of the proposed enhancement. The enhancement must represent a net improvement. The proposed implementation, if applicable, must be solid and must not complicate the protocol unduly.

### Special requirements for Core EIPs

If a **Core** EIP mentions or proposes changes to the EVM (Ethereum Virtual Machine), it should refer to the instructions by their mnemonics and define the opcodes of those mnemonics at least once. A preferred way is the following:

```
REVERT (0xfe)
```

## EIP Work Flow

### Shepherding an EIP

Parties involved in the process are you, the champion or *EIP author*, the [*EIP editors*](#eip-editors), and the [*Ethereum Core Developers*](https://github.com/ethereum/pm).

Before you begin writing a formal EIP, you should vet your idea. Ask the Ethereum community first if an idea is original to avoid wasting time on something that will be rejected based on prior research. It is thus recommended to open a discussion thread on [the Ethereum Magicians forum](https://ethereum-magicians.org/) to do this.

Once the idea has been vetted, your next responsibility will be to present (by means of an EIP) the idea to the reviewers and all interested parties, invite editors, developers, and the community to give feedback on the aforementioned channels. You should try and gauge whether the interest in your EIP is commensurate with both the work involved in implementing it and how many parties will have to conform to it. For example, the work required for implementing a Core EIP will be much greater than for an ERC and the EIP will need sufficient interest from the Ethereum client teams. Negative community feedback will be taken into consideration and may prevent your EIP from moving past the Draft stage.

### Core EIPs

For Core EIPs, given that they require client implementations to be considered **Final** (see &quot;EIPs Process&quot; below), you will need to either provide an implementation for clients or convince clients to implement your EIP.

The best way to get client implementers to review your EIP is to present it on an AllCoreDevs call. You can request to do so by posting a comment linking your EIP on an [AllCoreDevs agenda GitHub Issue](https://github.com/ethereum/pm/issues).  

The AllCoreDevs call serves as a way for client implementers to do three things. First, to discuss the technical merits of EIPs. Second, to gauge what other clients will be implementing. Third, to coordinate EIP implementation for network upgrades.

These calls generally result in a &quot;rough consensus&quot; around what EIPs should be implemented. This &quot;rough consensus&quot; rests on the assumptions that EIPs are not contentious enough to cause a network split and that they are technically sound.

:warning: The EIPs process and AllCoreDevs call were not designed to address contentious non-technical issues, but, due to the lack of other ways to address these, often end up entangled in them. This puts the burden on client implementers to try and gauge community sentiment, which hinders the technical coordination function of EIPs and AllCoreDevs calls. If you are shepherding an EIP, you can make the process of building community consensus easier by making sure that [the Ethereum Magicians forum](https://ethereum-magicians.org/) thread for your EIP includes or links to as much of the community discussion as possible and that various stakeholders are well-represented.

*In short, your role as the champion is to write the EIP using the style and format described below, shepherd the discussions in the appropriate forums, and build community consensus around the idea.*

### EIP Process

The following is the standardization process for all EIPs in all tracks:

![EIP Status Diagram](/EIPs/assets/eip-1/EIP-process-update.jpg)

**Idea** - An idea that is pre-draft. This is not tracked within the EIP Repository.

**Draft** - The first formally tracked stage of an EIP in development. An EIP is merged by an EIP Editor into the EIP repository when properly formatted.

**Review** - An EIP Author marks an EIP as ready for and requesting Peer Review.

**Last Call** - This is the final review window for an EIP before it is moved to `Final`. An EIP enters `Last Call` when the specification is stable and the author opens a PR with a review end date (`last-call-deadline`), typically 14 days later. 

If this period results in necessary normative changes it will revert the EIP to `Review`.

**Final** - This EIP represents the final standard. A Final EIP exists in a state of finality and should only be updated to correct errata and add non-normative clarifications.

A PR moving an EIP from Last Call to Final SHOULD contain no changes other than the status update. Any content or editorial proposed change SHOULD be separate from this status-updating PR and committed prior to it.

**Stagnant** - Any EIP in `Draft` or `Review` or `Last Call` if inactive for a period of 6 months or greater is moved to `Stagnant`. An EIP may be resurrected from this state by Authors or EIP Editors through moving it back to `Draft` or its earlier status. If not resurrected, a proposal may stay forever in this status.

&gt;*EIP Authors are notified of any algorithmic change to the status of their EIP*

**Withdrawn** - The EIP Author(s) have withdrawn the proposed EIP. This state has finality and can no longer be resurrected using this EIP number. If the idea is pursued at a later date, it is considered a new proposal.

**Living** - A special status for EIPs that are designed to be continually updated and not reach a state of finality. This includes most notably EIP-1.

## What belongs in a successful EIP?

Each EIP should have the following parts:

- Preamble - RFC 822 style headers containing metadata about the EIP, including the EIP number, a short descriptive title (limited to a maximum of 44 characters), a description (limited to a maximum of 140 characters), and the author details. Irrespective of the category, the title and description should not include EIP number. See [below](/EIPs/EIPS/eip-1#eip-header-preamble) for details.
- Abstract - Abstract is a multi-sentence (short paragraph) technical summary. This should be a very terse and human-readable version of the specification section. Someone should be able to read only the abstract to get the gist of what this specification does.
- Motivation *(optional)* - A motivation section is critical for EIPs that want to change the Ethereum protocol. It should clearly explain why the existing protocol specification is inadequate to address the problem that the EIP solves. This section may be omitted if the motivation is evident.
- Specification - The technical specification should describe the syntax and semantics of any new feature. The specification should be detailed enough to allow competing, interoperable implementations for any of the current Ethereum platforms (besu, erigon, ethereumjs, go-ethereum, nethermind, or others).
- Rationale - The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages. The rationale should discuss important objections or concerns raised during discussion around the EIP.
- Backwards Compatibility *(optional)* - All EIPs that introduce backwards incompatibilities must include a section describing these incompatibilities and their consequences. The EIP must explain how the author proposes to deal with these incompatibilities. This section may be omitted if the proposal does not introduce any backward incompatibilities, but this section must be included if backward incompatibilities exist.
- Test Cases *(optional)* - Test cases for an implementation are mandatory for EIPs that are affecting consensus changes. Tests should either be inlined in the EIP as data (such as input/expected output pairs) or included in `../assets/eip-###/&lt;filename&gt;`. This section may be omitted for non-Core proposals.
- Reference Implementation *(optional)* - An optional section that contains a reference/example implementation that people can use to assist in understanding or implementing this specification. This section may be omitted for all EIPs.
- Security Considerations - All EIPs must contain a section that discusses the security implications/considerations relevant to the proposed change. Include information that might be important for security discussions, surfaces risks and can be used throughout the life-cycle of the proposal. E.g., include security-relevant design decisions, concerns, important discussions, implementation-specific guidance and pitfalls, an outline of threats and risks and how they are being addressed. EIP submissions missing the &quot;Security Considerations&quot; section will be rejected. An EIP cannot proceed to status &quot;Final&quot; without a Security Considerations discussion deemed sufficient by the reviewers.
- Copyright Waiver - All EIPs must be in the public domain. The copyright waiver MUST link to the license file and use the following wording: `Copyright and related rights waived via [CC0](/EIPs/LICENSE).`

## EIP Formats and Templates

EIPs should be written in [markdown](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) format. There is a [template](https://github.com/ethereum/EIPs/blob/master/eip-template.md) and [contributor](https://github.com/ethereum/EIPs/blob/master/CONTRIBUTING.md) guidelines to follow.

## EIP Header Preamble

Each EIP must begin with an [RFC 822](https://www.ietf.org/rfc/rfc822.txt) style header preamble, preceded and followed by three hyphens (`---`). This header is also termed [&quot;front matter&quot; by Jekyll](https://jekyllrb.com/docs/front-matter/). The headers must appear in the following order.

`eip`: *EIP number*

`title`: *The EIP title is a few words, not a complete sentence*

`description`: *Description is one full (short) sentence*

`author`: *The list of the author&apos;s or authors&apos; name(s) and/or username(s), or name(s) and email(s). Details are below.*

`discussions-to`: *The url pointing to the official discussion thread*

`status`: *Draft, Review, Last Call, Final, Stagnant, Withdrawn, Living*

`last-call-deadline`: *The date last call period ends on* (Optional field, only needed when status is `Last Call`)

`type`: *One of `Standards Track`, `Meta`, or `Informational`*

`category`: *One of `Core`, `Networking`, `Interface`, or `ERC`* (Optional field, only needed for `Standards Track` EIPs)

`created`: *Date the EIP was created on*

`requires`: *EIP number(s)* (Optional field)

`withdrawal-reason`: *A sentence explaining why the EIP was withdrawn.* (Optional field, only needed when status is `Withdrawn`)

Headers that permit lists must separate elements with commas.

Headers requiring dates will always do so in the format of ISO 8601 (yyyy-mm-dd).

### `author` header

The `author` header lists the names, email addresses or usernames of the authors/owners of the EIP. Those who prefer anonymity may use a username only, or a first name and a username. The format of the `author` header value must be:

&gt; Random J. User &amp;lt;address@dom.ain&amp;gt;

or

&gt; Random J. User (@username)

or

&gt; Random J. User (@username) &amp;lt;address@dom.ain&amp;gt;

if the email address and/or GitHub username is included, and

&gt; Random J. User

if neither the email address nor the GitHub username are given.

At least one author must use a GitHub username, in order to get notified on change requests and have the capability to approve or reject them.

### `discussions-to` header

While an EIP is a draft, a `discussions-to` header will indicate the URL where the EIP is being discussed.

The preferred discussion URL is a topic on [Ethereum Magicians](https://ethereum-magicians.org/). The URL cannot point to Github pull requests, any URL which is ephemeral, and any URL which can get locked over time (i.e. Reddit topics).

### `type` header

The `type` header specifies the type of EIP: Standards Track, Meta, or Informational. If the track is Standards please include the subcategory (core, networking, interface, or ERC).

### `category` header

The `category` header specifies the EIP&apos;s category. This is required for standards-track EIPs only.

### `created` header

The `created` header records the date that the EIP was assigned a number. Both headers should be in yyyy-mm-dd format, e.g. 2001-08-14.

### `requires` header

EIPs may have a `requires` header, indicating the EIP numbers that this EIP depends on. If such a dependency exists, this field is required.

A `requires` dependency is created when the current EIP cannot be understood or implemented without a concept or technical element from another EIP. Merely mentioning another EIP does not necessarily create such a dependency.

## Linking to External Resources

Other than the specific exceptions listed below, links to external resources **SHOULD NOT** be included. External resources may disappear, move, or change unexpectedly.

The process governing permitted external resources is described in [EIP-5757](/EIPs/EIPS/eip-5757).

### Execution Client Specifications

Links to the Ethereum Execution Client Specifications may be included using normal markdown syntax, such as:

```markdown
[Ethereum Execution Client Specifications](https://github.com/ethereum/execution-specs/blob/9a1f22311f517401fed6c939a159b55600c454af/README.md)
```

Which renders to:

[Ethereum Execution Client Specifications](https://github.com/ethereum/execution-specs/blob/9a1f22311f517401fed6c939a159b55600c454af/README.md)

Permitted Execution Client Specifications URLs must anchor to a specific commit, and so must match this regular expression:

```regex
^(https://github.com/ethereum/execution-specs/(blob|commit)/[0-9a-f]{40}/.*|https://github.com/ethereum/execution-specs/tree/[0-9a-f]{40}/.*)$
```

### Execution Specification Tests

Links to the Ethereum Execution Specification Tests (EEST) may be included using normal markdown syntax, such as:

```markdown
[Ethereum Execution Specification Tests](https://github.com/ethereum/execution-spec-tests/blob/c9b9307ff320c9bb0ecb9a951aeab0da4d9d1684/README.md)
```

Which renders to:

[Ethereum Execution Specification Tests](https://github.com/ethereum/execution-spec-tests/blob/c9b9307ff320c9bb0ecb9a951aeab0da4d9d1684/README.md)

Permitted Execution Specification Tests URLs must anchor to a specific commit, and so must match one of these regular expressions:

```regex
^https://(www\.)?github\.com/ethereum/execution-spec-tests/(blob|tree)/[a-f0-9]{40}/.+$
```

```regex
^https://(www\.)?github\.com/ethereum/execution-spec-tests/commit/[a-f0-9]{40}$
```

### Consensus Layer Specifications

Links to specific commits of files within the Ethereum Consensus Layer Specifications may be included using normal markdown syntax, such as:

```markdown
[Beacon Chain](https://github.com/ethereum/consensus-specs/blob/26695a9fdb747ecbe4f0bb9812fedbc402e5e18c/specs/sharding/beacon-chain.md)
```

Which renders to:

[Beacon Chain](https://github.com/ethereum/consensus-specs/blob/26695a9fdb747ecbe4f0bb9812fedbc402e5e18c/specs/sharding/beacon-chain.md)

Permitted Consensus Layer Specifications URLs must anchor to a specific commit, and so must match this regular expression:

```regex
^https://github.com/ethereum/consensus-specs/(blob|commit)/[0-9a-f]{40}/.*$
```

### Networking Specifications

Links to specific commits of files within the Ethereum Networking Specifications may be included using normal markdown syntax, such as:

```markdown
[Ethereum Wire Protocol](https://github.com/ethereum/devp2p/blob/40ab248bf7e017e83cc9812a4e048446709623e8/caps/eth.md)
```

Which renders as:

[Ethereum Wire Protocol](https://github.com/ethereum/devp2p/blob/40ab248bf7e017e83cc9812a4e048446709623e8/caps/eth.md)

Permitted Networking Specifications URLs must anchor to a specific commit, and so must match this regular expression:

```regex
^https://github.com/ethereum/devp2p/(blob|commit)/[0-9a-f]{40}/.*$
```

### Portal Specifications

Links to specific commits of files within the Ethereum Portal Specifications may be included using normal markdown syntax, such as:

```markdown
[Portal Wire Protocol](https://github.com/ethereum/portal-network-specs/blob/5e321567b67bded7527355be714993c24371de1a/portal-wire-protocol.md)
```

Which renders as:

[Portal Wire Protocol](https://github.com/ethereum/portal-network-specs/blob/5e321567b67bded7527355be714993c24371de1a/portal-wire-protocol.md)

Permitted Networking Specifications URLs must anchor to a specific commit, and so must match this regular expression:

```regex
^https://github.com/ethereum/portal-network-specs/(blob|commit)/[0-9a-f]{40}/.*$
```

### World Wide Web Consortium (W3C)

Links to a W3C &quot;Recommendation&quot; status specification may be included using normal markdown syntax. For example, the following link would be allowed:

```markdown
[Secure Contexts](https://www.w3.org/TR/2021/CRD-secure-contexts-20210918/)
```

Which renders as:

[Secure Contexts](https://www.w3.org/TR/2021/CRD-secure-contexts-20210918/)

Permitted W3C recommendation URLs MUST anchor to a specification in the technical reports namespace with a date, and so MUST match this regular expression:

```regex
^https://www\.w3\.org/TR/[0-9][0-9][0-9][0-9]/.*$
```

### Web Hypertext Application Technology Working Group (WHATWG)

Links to WHATWG specifications may be included using normal markdown syntax, such as:

```markdown
[HTML](https://html.spec.whatwg.org/commit-snapshots/578def68a9735a1e36610a6789245ddfc13d24e0/)
```

Which renders as:

[HTML](https://html.spec.whatwg.org/commit-snapshots/578def68a9735a1e36610a6789245ddfc13d24e0/)

Permitted WHATWG specification URLs must anchor to a specification defined in the `spec` subdomain (idea specifications are not allowed) and to a commit snapshot, and so must match this regular expression:

```regex
^https:\/\/[a-z]*\.spec\.whatwg\.org/commit-snapshots/[0-9a-f]{40}/$
```

Although not recommended by WHATWG, EIPs must anchor to a particular commit so that future readers can refer to the exact version of the living standard that existed at the time the EIP was finalized. This gives readers sufficient information to maintain compatibility, if they so choose, with the version referenced by the EIP and the current living standard.

### Internet Engineering Task Force (IETF)

Links to an IETF Request For Comment (RFC) specification may be included using normal markdown syntax, such as:

```markdown
[RFC 8446](https://www.rfc-editor.org/rfc/rfc8446)
```

Which renders as:

[RFC 8446](https://www.rfc-editor.org/rfc/rfc8446)

Permitted IETF specification URLs MUST anchor to a specification with an assigned RFC number (meaning cannot reference internet drafts), and so MUST match this regular expression:

```regex
^https:\/\/www.rfc-editor.org\/rfc\/.*$
```

### Bitcoin Improvement Proposal

Links to Bitcoin Improvement Proposals may be included using normal markdown syntax, such as:

```markdown
[BIP 38](https://github.com/bitcoin/bips/blob/3db736243cd01389a4dfd98738204df1856dc5b9/bip-0038.mediawiki)
```

Which renders to:

[BIP 38](https://github.com/bitcoin/bips/blob/3db736243cd01389a4dfd98738204df1856dc5b9/bip-0038.mediawiki)

Permitted Bitcoin Improvement Proposal URLs must anchor to a specific commit, and so must match this regular expression:

```regex
^(https://github.com/bitcoin/bips/blob/[0-9a-f]{40}/bip-[0-9]+\.mediawiki)$
```

### National Vulnerability Database (NVD)

Links to the Common Vulnerabilities and Exposures (CVE) system as published by the National Institute of Standards and Technology (NIST) may be included, provided they are qualified by the date of the most recent change, using the following syntax:

```markdown
[CVE-2023-29638 (2023-10-17T10:14:15)](https://nvd.nist.gov/vuln/detail/CVE-2023-29638)
```

Which renders to:

[CVE-2023-29638 (2023-10-17T10:14:15)](https://nvd.nist.gov/vuln/detail/CVE-2023-29638)

### Chain Agnostic Improvement Proposals (CAIPs)

Links to a Chain Agnostic Improvement Proposals (CAIPs) specification may be included using normal markdown syntax, such as:

```markdown
[CAIP 10](https://github.com/ChainAgnostic/CAIPs/blob/5dd3a2f541d399a82bb32590b52ca4340b09f08b/CAIPs/caip-10.md)
```

Which renders to:

[CAIP 10](https://github.com/ChainAgnostic/CAIPs/blob/5dd3a2f541d399a82bb32590b52ca4340b09f08b/CAIPs/caip-10.md)

Permitted Chain Agnostic URLs must anchor to a specific commit, and so must match this regular expression:

```regex
^(https://github.com/ChainAgnostic/CAIPs/blob/[0-9a-f]{40}/CAIPs/caip-[0-9]+\.md)$
```

### Ethereum Yellow Paper

Links to the Ethereum Yellow Paper may be included using normal markdown syntax, such as:

```markdown
[Ethereum Yellow Paper](https://github.com/ethereum/yellowpaper/blob/9c601d6a58c44928d4f2b837c0350cec9d9259ed/paper.pdf)
```

Which renders to:

[Ethereum Yellow Paper](https://github.com/ethereum/yellowpaper/blob/9c601d6a58c44928d4f2b837c0350cec9d9259ed/paper.pdf)

Permitted Yellow Paper URLs must anchor to a specific commit, and so must match this regular expression:

```regex
^(https://github\.com/ethereum/yellowpaper/blob/[0-9a-f]{40}/paper\.pdf)$
```

### Execution Client Specification Tests

Links to the Ethereum Execution Client Specification Tests may be included using normal markdown syntax, such as:

```markdown
[Ethereum Execution Client Specification Tests](https://github.com/ethereum/execution-spec-tests/blob/d5a3188f122912e137aa2e21ed2a1403e806e424/README.md)
```

Which renders to:

[Ethereum Execution Client Specification Tests](https://github.com/ethereum/execution-spec-tests/blob/d5a3188f122912e137aa2e21ed2a1403e806e424/README.md)

Permitted Execution Client Specification Tests URLs must anchor to a specific commit, and so must match this regular expression:

```regex
^(https://github.com/ethereum/execution-spec-tests/(blob|commit)/[0-9a-f]{40}/.*|https://github.com/ethereum/execution-spec-tests/tree/[0-9a-f]{40}/.*)$
```

### Digital Object Identifier System

Links qualified with a Digital Object Identifier (DOI) may be included using the following syntax:

````markdown
This is a sentence with a footnote.[^1]

[^1]:
    ```csl-json
    {
      &quot;type&quot;: &quot;article&quot;,
      &quot;id&quot;: 1,
      &quot;author&quot;: [
        {
          &quot;family&quot;: &quot;Jameson&quot;,
          &quot;given&quot;: &quot;Hudson&quot;
        }
      ],
      &quot;DOI&quot;: &quot;00.0000/a00000-000-0000-y&quot;,
      &quot;title&quot;: &quot;An Interesting Article&quot;,
      &quot;original-date&quot;: {
        &quot;date-parts&quot;: [
          [2022, 12, 31]
        ]
      },
      &quot;URL&quot;: &quot;https://sly-hub.invalid/00.0000/a00000-000-0000-y&quot;,
      &quot;custom&quot;: {
        &quot;additional-urls&quot;: [
          &quot;https://example.com/an-interesting-article.pdf&quot;
        ]
      }
    }
    ```
````

Which renders to:

&lt;!-- markdownlint-capture --&gt;
&lt;!-- markdownlint-disable code-block-style --&gt;

This is a sentence with a footnote.[^1]

[^1]:
    ```csl-json
    {
      &quot;type&quot;: &quot;article&quot;,
      &quot;id&quot;: 1,
      &quot;author&quot;: [
        {
          &quot;family&quot;: &quot;Jameson&quot;,
          &quot;given&quot;: &quot;Hudson&quot;
        }
      ],
      &quot;DOI&quot;: &quot;00.0000/a00000-000-0000-y&quot;,
      &quot;title&quot;: &quot;An Interesting Article&quot;,
      &quot;original-date&quot;: {
        &quot;date-parts&quot;: [
          [2022, 12, 31]
        ]
      },
      &quot;URL&quot;: &quot;https://sly-hub.invalid/00.0000/a00000-000-0000-y&quot;,
      &quot;custom&quot;: {
        &quot;additional-urls&quot;: [
          &quot;https://example.com/an-interesting-article.pdf&quot;
        ]
      }
    }
    ```

&lt;!-- markdownlint-restore --&gt;

See the [Citation Style Language Schema](https://resource.citationstyles.org/schema/v1.0/input/json/csl-data.json) for the supported fields. In addition to passing validation against that schema, references must include a DOI and at least one URL.

The top-level URL field must resolve to a copy of the referenced document which can be viewed at zero cost. Values under `additional-urls` must also resolve to a copy of the referenced document, but may charge a fee.

### Execution API Specification

Links to the Ethereum Execution API Specification may be included using normal markdown syntax, such as:

```markdown
[Ethereum Execution API Specification](https://github.com/ethereum/execution-apis/blob/dd00287101e368752ba264950585dde4b61cdc17/README.md)
```

Which renders to:

[Ethereum Execution API Specification](https://github.com/ethereum/execution-apis/blob/dd00287101e368752ba264950585dde4b61cdc17/README.md)

Permitted Execution API Specification URLs must anchor to a specific commit, and so must match this regular expression:

```regex
^(https://github.com/ethereum/execution-apis/(blob|commit)/[0-9a-f]{40}/.*|https://github.com/ethereum/execution-apis/tree/[0-9a-f]{40}/.*)$
```

## Linking to other EIPs

References to other EIPs should follow the format `EIP-N` where `N` is the EIP number you are referring to.  Each EIP that is referenced in an EIP **MUST** be accompanied by a relative markdown link the first time it is referenced, and **MAY** be accompanied by a link on subsequent references.  The link **MUST** always be done via relative paths so that the links work in this GitHub repository, forks of this repository, the main EIPs site, mirrors of the main EIP site, etc.  For example, you would link to this EIP as `./eip-1.md`.

## Auxiliary Files

Images, diagrams and auxiliary files should be included in a subdirectory of the `assets` folder for that EIP as follows: `assets/eip-N` (where **N** is to be replaced with the EIP number). When linking to an image in the EIP, use relative links such as `../assets/eip-1/image.png`. Prefer SVG diagrams, then PNG, and finally everything else.

## Transferring EIP Ownership

It occasionally becomes necessary to transfer ownership of EIPs to a new champion. In general, we&apos;d like to retain the original author as a co-author of the transferred EIP, but that&apos;s really up to the original author. A good reason to transfer ownership is because the original author no longer has the time or interest in updating it or following through with the EIP process, or has fallen off the face of the &apos;net (i.e. is unreachable or isn&apos;t responding to email). A bad reason to transfer ownership is because you don&apos;t agree with the direction of the EIP. We try to build consensus around an EIP, but if that&apos;s not possible, you can always submit a competing EIP.

If you are interested in assuming ownership of an EIP, send a message asking to take over, addressed to both the original author and the EIP editor. If the original author doesn&apos;t respond to the email in a timely manner, the EIP editor will make a unilateral decision (it&apos;s not like such decisions can&apos;t be reversed :)).

## EIP Editors

The current EIP editors are

- Matt Garnett (@lightclient)
- Sam Wilson (@SamWilsn)
- Zainan Victor Zhou (@xinbenlv)
- Gajinder Singh (@g11tech)
- Jochem Brouwer (@jochem-brouwer)

Emeritus EIP editors are

- Alex Beregszaszi (@axic)
- Casey Detrio (@cdetrio)
- Gavin John (@Pandapip1)
- Greg Colvin (@gcolvin)
- Hudson Jameson (@Souptacular)
- Martin Becze (@wanderer)
- Micah Zoltu (@MicahZoltu)
- Nick Johnson (@arachnid)
- Nick Savers (@nicksavers)
- Vitalik Buterin (@vbuterin)

If you would like to become an EIP editor, please check [EIP-5069](/EIPs/EIPS/eip-5069).

## EIP Editor Responsibilities

For each new EIP that comes in, an editor does the following:

- Read the EIP to check if it is ready: sound and complete. The ideas must make technical sense, even if they don&apos;t seem likely to get to final status.
- The title should accurately describe the content.
- Check the EIP for language (spelling, grammar, sentence structure, etc.), markup (GitHub flavored Markdown), code style

If the EIP isn&apos;t ready, the editor will send it back to the author for revision, with specific instructions.

Once the EIP is ready for the repository, the EIP editor will:

- Assign an EIP number (generally incremental; editors can reassign if number sniping is suspected)
- Merge the corresponding [pull request](https://github.com/ethereum/EIPs/pulls)
- Send a message back to the EIP author with the next step.

Many EIPs are written and maintained by developers with write access to the Ethereum codebase. The EIP editors monitor EIP changes, and correct any structure, grammar, spelling, or markup mistakes we see.

The editors don&apos;t pass judgment on EIPs. We merely do the administrative &amp; editorial part.

## Style Guide

### Titles

The `title` field in the preamble:

- Should be in title case.
- Should not include the word &quot;standard&quot; or any variation thereof; and
- Should not include the EIP&apos;s number.

### Descriptions

The `description` field in the preamble:

- Should be in sentence case.
- Should not include the word &quot;standard&quot; or any variation thereof; and
- Should not include the EIP&apos;s number.

### EIP numbers

When referring to an EIP with a `category` of `ERC`, it must be written in the hyphenated form `ERC-X` where `X` is that EIP&apos;s assigned number. When referring to EIPs with any other `category`, it must be written in the hyphenated form `EIP-X` where `X` is that EIP&apos;s assigned number.

### RFC 2119 and RFC 8174

EIPs are encouraged to follow [RFC 2119](https://www.ietf.org/rfc/rfc2119.html) and [RFC 8174](https://www.ietf.org/rfc/rfc8174.html) for terminology and to insert the following at the beginning of the Specification section:

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

Don&apos;t use RFC 2119 keywords (all-caps SHOULD/MUST/etc.) outside of the specification section.

## History

This document was derived heavily from [Bitcoin&apos;s BIP-0001](https://github.com/bitcoin/bips) written by Amir Taaki which in turn was derived from [Python&apos;s PEP-0001](https://peps.python.org/). In many places text was simply copied and modified. Although the PEP-0001 text was written by Barry Warsaw, Jeremy Hylton, and David Goodger, they are not responsible for its use in the Ethereum Improvement Process, and should not be bothered with technical questions specific to Ethereum or the EIP. Please direct all comments to the EIP editors.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 27 Oct 2015 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1</guid>
      </item>
    
      <item>
        <title>Homestead Hard-fork Changes</title>
        <category>Standards Track/Core</category>
        
        <description>### Meta reference

[Homestead](/EIPs/EIPS/eip-606).

### Parameters

|   FORK_BLKNUM   | CHAIN_NAME  |
|-----------------|-------------|
|    1,150,000    | Main net    |
|   494,000       | Morden      |
|    0            | Future testnets    |

# Specification

If `block.number &gt;= HOMESTEAD_FORK_BLKNUM`, do the following:

1. The gas cost *for creating contracts via a transaction* is increased from 21,000 to 53,000, i.e. if you send a transaction and the to address is the empty string, the initial gas subtracted is 53,000 plus the gas cost of the tx data, rather than 21,000 as is currently the case. Contract creation from a contract using the `CREATE` opcode is unaffected.
2. All transaction signatures whose s-value is greater than `secp256k1n/2` are now considered invalid. The ECDSA recover precompiled contract remains unchanged and will keep accepting high s-values; this is useful e.g. if a contract recovers old Bitcoin signatures.
3. If contract creation does not have enough gas to pay for the final gas fee for adding the contract code to the state, the contract creation fails (i.e. goes out-of-gas) rather than leaving an empty contract.
4. Change the difficulty adjustment algorithm from the current formula: `block_diff = parent_diff + parent_diff // 2048 * (1 if block_timestamp - parent_timestamp &lt; 13 else -1) + int(2**((block.number // 100000) - 2))` (where the `int(2**((block.number // 100000) - 2))` represents the exponential difficulty adjustment component) to `block_diff = parent_diff + parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99) + int(2**((block.number // 100000) - 2))`, where `//` is the integer division operator, eg. `6 // 2 = 3`, `7 // 2 = 3`, `8 // 2 = 4`. The `minDifficulty` still defines the minimum difficulty allowed and no adjustment may take it below this.

# Rationale

Currently, there is an excess incentive to create contracts via transactions, where the cost is 21,000, rather than contracts, where the cost is 32,000. Additionally, with the help of suicide refunds, it is currently possible to make a simple ether value transfer using only 11,664 gas; the code for doing this is as follows:

```python
from ethereum import tester as t
&gt; from ethereum import utils
&gt; s = t.state()
&gt; c = s.abi_contract(&apos;def init():\n suicide(0x47e25df8822538a8596b28c637896b4d143c351e)&apos;, endowment=10**15)
&gt; s.block.get_receipts()[-1].gas_used
11664
&gt; s.block.get_balance(utils.normalize_address(0x47e25df8822538a8596b28c637896b4d143c351e))
1000000000000000
```
This is not a particularly serious problem, but it is nevertheless arguably a bug.

Allowing transactions with any s value with `0 &lt; s &lt; secp256k1n`, as is currently the case, opens a transaction malleability concern, as one can take any transaction, flip the s value from `s` to `secp256k1n - s`, flip the v value (`27 -&gt; 28`, `28 -&gt; 27`), and the resulting signature would still be valid. This is not a serious security flaw, especially since Ethereum uses addresses and not transaction hashes as the input to an ether value transfer or other transaction, but it nevertheless creates a UI inconvenience as an attacker can cause the transaction that gets confirmed in a block to have a different hash from the transaction that any user sends, interfering with user interfaces that use transaction hashes as tracking IDs. Preventing high s values removes this problem.

Making contract creation go out-of-gas if there is not enough gas to pay for the final gas fee has the benefits that:
- (i) it creates a more intuitive &quot;success or fail&quot; distinction in the result of a contract creation process, rather than the current &quot;success, fail, or empty contract&quot; trichotomy;
- (ii) makes failures more easily detectable, as unless contract creation fully succeeds then no contract account will be created at all; and
- (iii) makes contract creation safer in the case where there is an endowment, as there is a guarantee that either the entire initiation process happens or the transaction fails and the endowment is refunded.

The difficulty adjustment change conclusively solves a problem that the Ethereum protocol saw two months ago where an excessive number of miners were mining blocks that contain a timestamp equal to `parent_timestamp + 1`; this skewed the block time distribution, and so the current block time algorithm, which targets a *median* of 13 seconds, continued to target the same median but the mean started increasing. If 51% of miners had started mining blocks in this way, the mean would have increased to infinity. The proposed new formula is roughly based on targeting the mean; one can prove that with the formula in use, an average block time longer than 24 seconds is mathematically impossible in the long term.

The use of `(block_timestamp - parent_timestamp) // 10` as the main input variable rather than the time difference directly serves to maintain the coarse-grained nature of the algorithm, preventing an excessive incentive to set the timestamp difference to exactly 1 in order to create a block that has slightly higher difficulty and that will thus be guaranteed to beat out any possible forks. The cap of -99 simply serves to ensure that the difficulty does not fall extremely far if two blocks happen to be very far apart in time due to a client security bug or other black-swan issue.

# Implementation

This is implemented in Python here:

1. https://github.com/ethereum/pyethereum/blob/d117c8f3fd93359fc641fd850fa799436f7c43b5/ethereum/processblock.py#L130
2. https://github.com/ethereum/pyethereum/blob/d117c8f3fd93359fc641fd850fa799436f7c43b5/ethereum/processblock.py#L129
3. https://github.com/ethereum/pyethereum/blob/d117c8f3fd93359fc641fd850fa799436f7c43b5/ethereum/processblock.py#L304
4. https://github.com/ethereum/pyethereum/blob/d117c8f3fd93359fc641fd850fa799436f7c43b5/ethereum/blocks.py#L42
</description>
        <pubDate>Sun, 15 Nov 2015 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2</guid>
      </item>
    
      <item>
        <title>Addition of CALLDEPTH opcode</title>
        <category>Standards Track/Core</category>
        
        <description># Abstract

This is a proposal to add a new opcode, `CALLDEPTH`. The `CALLDEPTH` opcode would return the remaining available call stack depth.

# Motivation

There is a limit specifying how deep contracts can call other contracts; the call stack. The limit is currently `256`. If a contract invokes another contract (either via `CALL` or `CALLCODE`), the operation will fail if the call stack depth limit has been reached.

This behaviour makes it possible to subject a contract to a &quot;call stack attack&quot; [1]. In such an attack, an attacker first creates a suitable depth of the stack, e.g. by recursive calls. After this step, the attacker invokes the targeted contract. If the targeted calls another contract, that call will fail. If the return value is not properly checked to see if the call was successful, the consequences could be damaging.

Example:

1. Contract `A` wants to be invoked regularly, and pays Ether to the invoker in every block.
2. When contract `A` is invoked, it calls contracts `B` and `C`, which consumes a lot of gas. After invocation, contract `A` pays Ether to the caller.
3. Malicious user `X` ensures that the stack depth is shallow before invoking A. Both calls to `B` and `C` fail, but `X` can still collect the reward.

It is possible to defend against this in two ways:

1. Check return value after invocation.
2. Check call stack depth experimentally. A library [2] by Piper Merriam exists for this purpose. This method is quite costly in gas.


[1] a.k.a &quot;shallow stack attack&quot; and &quot;stack attack&quot;. However, to be precise, the word &apos;&apos;stack&apos;&apos; has a different meaning within the EVM, and is not to be confused with the &apos;&apos;call stack&apos;&apos;.

[2] https://github.com/pipermerriam/ethereum-stack-depth-lib

# Specification

The opcode `CALLDEPTH` should return the remaining call stack depth. A value of `0` means that the call stack is exhausted, and no further calls can be made.

# Rationale

The actual call stack depth, as well as the call stack depth limit, are present in the EVM during execution, but just not available within the EVM. The implementation should be fairly simple and would provide a cheap and way to protect against call stack attacks.

# Implementation

Not implemented.
</description>
        <pubDate>Thu, 19 Nov 2015 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3</guid>
      </item>
    
      <item>
        <title>EIP Classification</title>
        <category>Meta/</category>
        
        <description># Abstract

This document describes a classification scheme for EIPs, adapted from [BIP 123](https://github.com/bitcoin/bips/blob/master/bip-0123.mediawiki).

EIPs are classified by system layers with lower numbered layers involving more intricate interoperability requirements.

The specification defines the layers and sets forth specific criteria for deciding to which layer a particular standards EIP belongs.

# Motivation

Ethereum is a system involving a number of different standards. Some standards are absolute requirements for interoperability while others can be considered optional, giving implementers a choice of whether to support them.

In order to have a EIP process which more closely reflects the interoperability requirements, it is necessary to categorize EIPs accordingly. Lower layers present considerably greater challenges in getting standards accepted and deployed.

# Specification

Standards EIPs are placed in one of four layers:

1. Consensus
2. Networking
3. API/RPC
4. Applications

# 1. Consensus Layer

The consensus layer defines cryptographic commitment structures. Its purpose is ensuring that anyone can locally evaluate whether a particular state and history is valid, providing settlement guarantees, and assuring eventual convergence.

The consensus layer is not concerned with how messages are propagated on a network.

Disagreements over the consensus layer can result in network partitioning, or forks, where different nodes might end up accepting different incompatible histories. We further subdivide consensus layer changes into soft forks and hard forks.

## Soft Forks

In a soft fork, some structures that were valid under the old rules are no longer valid under the new rules. Structures that were invalid under the old rules continue to be invalid under the new rules.

## Hard Forks

In a hard fork, structures that were invalid under the old rules become valid under the new rules.

# 2. Networking Layer

The networking layer specifies the Ethereum wire protocol (eth) and the Light Ethereum Subprotocol (les). RLPx is excluded and tracked in the [devp2p repository](https://github.com/ethereum/devp2p).

Only a subset of subprotocols are required for basic node interoperability. Nodes can support further optional extensions.

It is always possible to add new subprotocols without breaking compatibility with existing protocols, then gradually deprecate older protocols. In this manner, the entire network can be upgraded without serious risks of service disruption.


# 3. API/RPC Layer

The API/RPC layer specifies higher level calls accessible to applications. Support for these EIPs is not required for basic network interoperability but might be expected by some client applications.

There&apos;s room at this layer to allow for competing standards without breaking basic network interoperability.

# 4. Applications Layer

The applications layer specifies high level structures, abstractions, and conventions that allow different applications to support similar features and share data.
</description>
        <pubDate>Tue, 17 Nov 2015 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4</guid>
      </item>
    
      <item>
        <title>Gas Usage for `RETURN` and `CALL*`</title>
        <category>Standards Track/Core</category>
        
        <description>### Abstract

This EIP makes it possible to call functions that return strings and other dynamically-sized arrays.
Currently, when another contract / function is called from inside the Ethereum Virtual Machine,
the size of the output has to be specified in advance. It is of course possible to give a larger
size, but gas also has to be paid for memory that is not written to, which makes returning
dynamically-sized data both costly and inflexible to the extent that it is actually unusable.

The solution proposed in this EIP is to charge gas only for memory that is actually written to at
the time the `CALL` returns.

### Specification

The gas and memory semantics for `CALL`, `CALLCODE` and `DELEGATECALL` (called later as `CALL*`)
are changed in the following way (`CREATE` does not write to memory and is thus unaffected):

Suppose the arguments to `CALL*` are `gas, address, value, input_start, input_size, output_start, output_size`,
then, at the beginning of the opcode, gas for growing memory is only charged for `input_start + input_size`, but not
for `output_start + output_size`.

If the called contract returns data of size `n`, the memory of the calling contract is grown to
`output_start + min(output_size, n)` (and the calling contract is charged gas for that) and the
output is written to the area `[output_start, output_start + min(n, output_size))`.

The calling contract can run out of gas both at the beginning of the opcode and at the end
of the opcode.

After the call, the `MSIZE` opcode should return the size the memory was actually grown to.

### Motivation

In general, it is good practice to reserve a certain memory area for the output of a call,
because letting a subroutine write to arbitrary areas in memory might be dangerous. On the
other hand, it is often hard to know the output size of a call prior to performing the call:
The data could be in the storage of another contract which is generally inaccessible and
determining its size would require another call to that contract.

Furthermore, charging gas for areas of memory that are not actually written to is unnecessary.

This proposal tries to solve both problems: A caller can choose to provide a gigantic area of
memory at the end of their memory area. The callee can &quot;write&quot; to it by returning and the
caller is only charged for the memory area that is actually written.

This makes it possible to return dynamic data like strings and dynamically-sized arrays
in a very flexible way. It is even possible to determine the size of the returned data:
If the caller uses `output_start = MSIZE` and `output_size = 2**256-1`, the area of
memory that was actually written to is `(output_start, MSIZE)` (here, `MSIZE` as evaluated
after the call). This is important because it allows &quot;proxy&quot; contracts
which call other contracts whose interface they do not know and just return their output,
i.e. they both forward the input and the output. For this, it is important that the caller
(1) does not need to know the size of the output in advance and (2) can determine the
size of the output after the call.


### Rationale

This way of dealing with the problem requires a minimal change to the Ethereum Virtual Machine.
Other means of achieving a similar goal would have changed the opcodes themselves or
the number of their arguments. Another possibility would have been to only change the
gas mechanics if `output_size` is equal to `2**256-1`. Since the main difficulty in the
implementation is that memory has to be enlarged at two points in the code around `CALL`,
this would not have been a simplification.

At an earlier stage, it was proposed to also add the size of the returned data on the stack,
but the `MSIZE` mechanism described above should be sufficient and is much better
backwards compatible.

Some comments are available at https://github.com/ethereum/EIPs/issues/8

### Backwards Compatibility

This proposal changes the semantics of contracts because contracts can access the gas counter
and the size of memory.

On the other hand, it is unlikely that existing contracts will suffer from this change due to
the following reasons:

Gas:

The VM will not charge more gas than before. Usually, contracts are written in a way such
that their semantics do not change if they use up less gas. If more gas were used, contracts
might go out-of-gas if they perform a tight estimation for gas needed by sub-calls. Here,
contracts might only return more gas to their callers.

Memory size:

The `MSIZE` opcode is typically used to allocate memory at a previously unused spot.
The change in semantics affects existing contracts in two ways:

1. Overlaps in allocated memory. By using `CALL`, a contract might have wanted to allocate
   a certain slice of memory, even if that is not written to by the called contract.
   Subsequent uses of `MSIZE` to allocate memory might overlap with this slice that is
   now smaller than before the change. It is, though, unlikely that such contracts exist.

2. Memory addresses change. Rather general, if memory is allocated using `MSIZE`, the
   addresses of objects in memory will be different after the change. Contracts should
   all be written in a way, though, such that objects in memory are _relocatable_,
   i.e. their absolute position in memory and their relative position to other
   objects does not matter. This is of course not the case for arrays, but they
   are allocated in a single allocation and not with an intermediate `CALL`.


### Implementation

VM implementers should take care not to grow the memory until the end of the call and after a check that sufficient
gas is still available. Typical uses of the EIP include &quot;reserving&quot; `2**256-1` bytes of memory for the output.

Python implementation:

  old: http://vitalik.ca/files/old.py
  new: http://vitalik.ca/files/new.py
</description>
        <pubDate>Sun, 22 Nov 2015 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5</guid>
      </item>
    
      <item>
        <title>Renaming SUICIDE opcode</title>
        <category>Standards Track/Interface</category>
        
        <description>### Abstract
The solution proposed in this EIP is to change the name of the `SUICIDE` opcode in Ethereum programming languages with `SELFDESTRUCT`.

### Motivation
Mental health is a very real issue for many people and small notions can make a difference. Those dealing with loss or depression would benefit from not seeing the word suicide in our programming languages. By some estimates, 350 million people worldwide suffer from depression. The semantics of Ethereum&apos;s programming languages need to be reviewed often if we wish to grow our ecosystem to all types of developers.

An Ethereum security audit commissioned by DEVolution, GmbH and [performed by Least Authority](https://github.com/LeastAuthority/ethereum-analyses/blob/master/README.md) recommended the following:
&gt; Replace the instruction name &quot;suicide&quot; with a less connotative word like &quot;self-destruct&quot;, &quot;destroy&quot;, &quot;terminate&quot;, or &quot;close&quot;, especially since that is a term describing the natural conclusion of a contract.

The primary reason for us to change the term suicide is to show that people matter more than code and Ethereum is a mature enough of a project to recognize the need for a change. Suicide is a heavy subject and we should make every effort possible to not affect those in our development community who suffer from depression or who have recently lost someone to suicide. Ethereum is a young platform and it will cause less headaches if we implement this change early on in its life.

### Implementation
`SELFDESTRUCT` is added as an alias of `SUICIDE` opcode (rather than replacing it).
https://github.com/ethereum/solidity/commit/a8736b7b271dac117f15164cf4d2dfabcdd2c6fd
https://github.com/ethereum/serpent/commit/1106c3bdc8f1bd9ded58a452681788ff2e03ee7c
</description>
        <pubDate>Sun, 22 Nov 2015 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6</guid>
      </item>
    
      <item>
        <title>DELEGATECALL</title>
        <category>Standards Track/Core</category>
        
        <description>### Hard Fork
[Homestead](/EIPs/EIPS/eip-606)

### Parameters
- Activation:
  - Block &gt;= 1,150,000 on Mainnet
  - Block &gt;= 494,000 on Morden
  - Block &gt;= 0 on future testnets

### Overview

Add a new opcode, `DELEGATECALL` at `0xf4`, which is similar in idea to `CALLCODE`, except that it propagates the sender and value from the parent scope to the child scope, i.e. the call created has the same sender and value as the original call.

### Specification

`DELEGATECALL`: `0xf4`, takes 6 operands:
- `gas`: the amount of gas the code may use in order to execute;
- `to`: the destination address whose code is to be executed;
- `in_offset`: the offset into memory of the input;
- `in_size`: the size of the input in bytes;
- `out_offset`: the offset into memory of the output;
- `out_size`: the size of the scratch pad for the output.

#### Notes on gas
- The basic stipend is not given; `gas` is the total amount the callee receives.
- Like `CALLCODE`, account creation never happens, so the upfront gas cost is always `schedule.callGas` + `gas`.
- Unused gas is refunded as normal.

#### Notes on sender
- `CALLER` and `VALUE` behave exactly in the callee&apos;s environment as they do in the caller&apos;s environment.

#### Other notes
- The depth limit of 1024 is still preserved as normal.

### Rationale

Propagating the sender and value from the parent scope to the child scope makes it much easier for a contract to store another address as a mutable source of code and &apos;&apos;pass through&apos;&apos; calls to it, as the child code would execute in essentially the same environment (except for reduced gas and increased callstack depth) as the parent.

Use case 1: split code to get around 3m gas barrier

```python
~calldatacopy(0, 0, ~calldatasize())
if ~calldataload(0) &lt; 2**253:
    ~delegate_call(msg.gas - 10000, $ADDR1, 0, ~calldatasize(), ~calldatasize(), 10000)
    ~return(~calldatasize(), 10000)
elif ~calldataload(0) &lt; 2**253 * 2:
    ~delegate_call(msg.gas - 10000, $ADDR2, 0, ~calldatasize(), ~calldatasize(), 10000)
    ~return(~calldatasize(), 10000)
...
```

Use case 2: mutable address for storing the code of a contract:

```python
if ~calldataload(0) / 2**224 == 0x12345678 and self.owner == msg.sender:
    self.delegate = ~calldataload(4)
else:
    ~delegate_call(msg.gas - 10000, self.delegate, 0, ~calldatasize(), ~calldatasize(), 10000)
    ~return(~calldatasize(), 10000)
```
The child functions called by these methods can now freely reference `msg.sender` and `msg.value`.

### Possible arguments against

* You can replicate this functionality by just sticking the sender into the first twenty bytes of the call data. However, this would mean that code would need to be specially compiled for delegated contracts, and would not be usable in delegated and raw contexts at the same time.
</description>
        <pubDate>Sun, 15 Nov 2015 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7</guid>
      </item>
    
      <item>
        <title>devp2p Forward Compatibility Requirements for Homestead</title>
        <category>Standards Track/Networking</category>
        
        <description>### Abstract

This EIP introduces new forward-compatibility requirements for implementations of the
devp2p Wire Protocol, the RLPx Discovery Protocol and the RLPx TCP Transport Protocol.
Clients which implement EIP-8 behave according to Postel&apos;s Law:

&gt; Be conservative in what you do, be liberal in what you accept from others.

### Specification

Implementations of **the devp2p Wire Protocol** should ignore the version number of hello
packets. When sending the hello packet, the version element should be set to the highest
devp2p version supported. Implementations should also ignore any additional list elements
at the end of the hello packet.

Similarly, implementations of **the RLPx Discovery Protocol** should not validate the
version number of the ping packet, ignore any additional list elements in any packet, and
ignore any data after the first RLP value in any packet. Discovery packets with unknown
packet type should be discarded silently. The maximum size of any discovery packet is
still 1280 bytes.

Finally, implementations of **the RLPx TCP Transport protocol** should accept a new
encoding for the encrypted key establishment handshake packets. If an EIP-8 style RLPx
`auth-packet` is received, the corresponding `ack-packet` should be sent using the rules
below.

Decoding the RLP data in `auth-body` and `ack-body` should ignore mismatches of `auth-vsn`
and `ack-vsn`, any additional list elements and any trailing data after the list. During
the transitioning period (i.e. until the old format has been retired), implementations
should pad `auth-body` with at least 100 bytes of junk data. Adding a random amount in
range [100, 300] is recommended to vary the size of the packet.

```text
auth-vsn         = 4
auth-size        = size of enc-auth-body, encoded as a big-endian 16-bit integer
auth-body        = rlp.list(sig, initiator-pubk, initiator-nonce, auth-vsn)
enc-auth-body    = ecies.encrypt(recipient-pubk, auth-body, auth-size)
auth-packet      = auth-size || enc-auth-body

ack-vsn          = 4
ack-size         = size of enc-ack-body, encoded as a big-endian 16-bit integer
ack-body         = rlp.list(recipient-ephemeral-pubk, recipient-nonce, ack-vsn)
enc-ack-body     = ecies.encrypt(initiator-pubk, ack-body, ack-size)
ack-packet       = ack-size || enc-ack-body

where

X || Y
    denotes concatenation of X and Y.
X[:N]
    denotes an N-byte prefix of X.
rlp.list(X, Y, Z, ...)
    denotes recursive encoding of [X, Y, Z, ...] as an RLP list.
sha3(MESSAGE)
    is the Keccak256 hash function as used by Ethereum.
ecies.encrypt(PUBKEY, MESSAGE, AUTHDATA)
    is the asymmetric authenticated encryption function as used by RLPx.
    AUTHDATA is authenticated data which is not part of the resulting ciphertext,
    but written to HMAC-256 before generating the message tag.
```

### Motivation

Changes to the devp2p protocols are hard to deploy because clients running an older
version will refuse communication if the version number or structure of the hello
(discovery ping, RLPx handshake) packet does not match local expectations.

Introducing forward-compatibility requirements as part of the Homestead consensus upgrade
will ensure that all client software in use on the Ethereum network can cope with future
network protocol upgrades (as long as backwards-compatibility is maintained).

### Rationale

The proposed changes address forward compatibility by applying Postel&apos;s Law (also known as
the Robustness Principle) throughout the protocol stack. The merit and applicability of
this approach has been studied repeatedly since its original application in RFC 761. For a
recent perspective, see
[&quot;The Robustness Principle Reconsidered&quot; (Eric Allman, 2011)](https://queue.acm.org/detail.cfm?id=1999945).

#### Changes to the devp2p Wire Protocol

All clients currently contain statements such as the following:

```python
# pydevp2p/p2p_protocol.py
if data[&apos;version&apos;] != proto.version:
    log.debug(&apos;incompatible network protocols&apos;, peer=proto.peer,
        expected=proto.version, received=data[&apos;version&apos;])
    return proto.send_disconnect(reason=reasons.incompatible_p2p_version)
```

These checks make it impossible to change the version or structure of the hello packet.
Dropping them enables switching to a newer protocol version: Clients implementing a newer
version simply send a packet with higher version and possibly additional list elements.

* If such a packet is received by a node with lower version, it will blindly assume that
  the remote end is backwards-compatible and respond with the old handshake.
* If the packet is received by a node with equal version, new features of the protocol can
  be used.
* If the packet is received by a node with higher version, it can enable
  backwards-compatibility logic or drop the connection.

#### Changes to the RLPx Discovery Protocol

The relaxation of discovery packet decoding rules largely codifies current practice. Most
existing implementations do not care about the number of list elements (an exception being
go-ethereum) and do not reject nodes with mismatching version. This behaviour is not
guaranteed by the spec, though.

If adopted, the change makes it possible to deploy protocol changes in a similar manner to
the devp2p hello change: simply bump the version and send additional information. Older
clients will ignore the additional elements and can continue to operate even when the
majority of the network has moved on to a newer protocol.

#### Changes to the RLPx TCP Handshake

Discussions of the RLPx v5 changes (chunked packets, change to key derivation) have
faltered in part because the v4 handshake encoding provides only one in-band way to add a
version number: shortening the random portion of the nonce. Even if the RLPx v5 handshake
proposal were accepted, future upgrades are hard because the handshake packet is a fixed
size ECIES ciphertext with known layout.

I propose the following changes to the handshake packets:

* Adding the length of the ciphertext as a plaintext header.
* Encoding the body of the handshake as RLP.
* Adding a version number to both packets in place of the token flag (unused).
* Removing the hash of the ephemeral public key (it is redundant).

These changes make it possible to upgrade the RLPx TCP transport protocol in the same
manner as described for the other protocols, i.e. by adding list elements and bumping the
version. Since this is the first change to the RLPx handshake packet, we can seize the
opportunity to remove all currently unused fields.

Additional data is permitted (and in fact required) after the RLP list because the
handshake packet needs to grow in order to be distinguishable from the old format.
Clients can employ logic such as the following pseudocode to handle both formats
simultaneously.

```go
packet = read(307, connection)
if decrypt(packet) {
    // process as old format
} else {
    size = unpack_16bit_big_endian(packet)
    packet += read(size - 307 + 2, connection)
    if !decrypt(packet) {
        // error
    }
    // process as new format
}
```

The plain text size prefix is perhaps the most controversial aspect of this document. It
has been argued that the prefix aids adversaries that seek to filter and identify RLPx
connections on the network level.

This is largely a question of how much effort the adversary is willing to expense. If the
recommendation to randomise the lengths is followed, pure pattern-based packet
recognition is unlikely to succeed.

* For typical firewall operators, blocking all connections whose first two bytes form an
  integer in range [300,600] is probably too invasive. Port-based blocking would be
  a more effective measure to filter most RLPx traffic.
* For an attacker who can afford to correlate many criteria, the size prefix would ease
  recognition because it adds to the indicator set. However, such an attacker could also
  be expected to read or participate in RLPx Discovery traffic, which would be sufficient
  to enable blocking of RLPx TCP connections whatever their format is.

### Backwards Compatibility

This EIP is backwards-compatible, all valid version 4 packets are still accepted.

### Implementation

[go-ethereum](https://github.com/ethereum/go-ethereum/pull/2091)
[libweb3core](https://github.com/ethereum/libweb3core/pull/46)
[pydevp2p](https://github.com/ethereum/pydevp2p/pull/32)

### Test Vectors

#### devp2p Base Protocol

devp2p hello packet advertising version 22 and containing a few additional list elements:

```text
f87137916b6e6574682f76302e39312f706c616e39cdc5836574683dc6846d6f726b1682270fb840
fda1cff674c90c9a197539fe3dfb53086ace64f83ed7c6eabec741f7f381cc803e52ab2cd55d5569
bce4347107a310dfd5f88a010cd2ffd1005ca406f1842877c883666f6f836261720304
```

#### RLPx Discovery Protocol

Implementations should accept the following encoded discovery packets as valid.
The packets are signed using the secp256k1 node key

```text
b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291
```

ping packet with version 4, additional list elements:

```text
e9614ccfd9fc3e74360018522d30e1419a143407ffcce748de3e22116b7e8dc92ff74788c0b6663a
aa3d67d641936511c8f8d6ad8698b820a7cf9e1be7155e9a241f556658c55428ec0563514365799a
4be2be5a685a80971ddcfa80cb422cdd0101ec04cb847f000001820cfa8215a8d790000000000000
000000000000000000018208ae820d058443b9a3550102
```

ping packet with version 555, additional list elements and additional random data:

```text
577be4349c4dd26768081f58de4c6f375a7a22f3f7adda654d1428637412c3d7fe917cadc56d4e5e
7ffae1dbe3efffb9849feb71b262de37977e7c7a44e677295680e9e38ab26bee2fcbae207fba3ff3
d74069a50b902a82c9903ed37cc993c50001f83e82022bd79020010db83c4d001500000000abcdef
12820cfa8215a8d79020010db885a308d313198a2e037073488208ae82823a8443b9a355c5010203
040531b9019afde696e582a78fa8d95ea13ce3297d4afb8ba6433e4154caa5ac6431af1b80ba7602
3fa4090c408f6b4bc3701562c031041d4702971d102c9ab7fa5eed4cd6bab8f7af956f7d565ee191
7084a95398b6a21eac920fe3dd1345ec0a7ef39367ee69ddf092cbfe5b93e5e568ebc491983c09c7
6d922dc3
```

pong packet with additional list elements and additional random data:

```text
09b2428d83348d27cdf7064ad9024f526cebc19e4958f0fdad87c15eb598dd61d08423e0bf66b206
9869e1724125f820d851c136684082774f870e614d95a2855d000f05d1648b2d5945470bc187c2d2
216fbe870f43ed0909009882e176a46b0102f846d79020010db885a308d313198a2e037073488208
ae82823aa0fbc914b16819237dcd8801d7e53f69e9719adecb3cc0e790c57e91ca4461c9548443b9
a355c6010203c2040506a0c969a58f6f9095004c0177a6b47f451530cab38966a25cca5cb58f0555
42124e
```

findnode packet with additional list elements and additional random data:

```text
c7c44041b9f7c7e41934417ebac9a8e1a4c6298f74553f2fcfdcae6ed6fe53163eb3d2b52e39fe91
831b8a927bf4fc222c3902202027e5e9eb812195f95d20061ef5cd31d502e47ecb61183f74a504fe
04c51e73df81f25c4d506b26db4517490103f84eb840ca634cae0d49acb401d8a4c6b6fe8c55b70d
115bf400769cc1400f3258cd31387574077f301b421bc84df7266c44e9e6d569fc56be0081290476
7bf5ccd1fc7f8443b9a35582999983999999280dc62cc8255c73471e0a61da0c89acdc0e035e260a
dd7fc0c04ad9ebf3919644c91cb247affc82b69bd2ca235c71eab8e49737c937a2c396
```

neighbours packet with additional list elements and additional random data:

```text
c679fc8fe0b8b12f06577f2e802d34f6fa257e6137a995f6f4cbfc9ee50ed3710faf6e66f932c4c8
d81d64343f429651328758b47d3dbc02c4042f0fff6946a50f4a49037a72bb550f3a7872363a83e1
b9ee6469856c24eb4ef80b7535bcf99c0004f9015bf90150f84d846321163782115c82115db84031
55e1427f85f10a5c9a7755877748041af1bcd8d474ec065eb33df57a97babf54bfd2103575fa8291
15d224c523596b401065a97f74010610fce76382c0bf32f84984010203040101b840312c55512422
cf9b8a4097e9a6ad79402e87a15ae909a4bfefa22398f03d20951933beea1e4dfa6f968212385e82
9f04c2d314fc2d4e255e0d3bc08792b069dbf8599020010db83c4d001500000000abcdef12820d05
820d05b84038643200b172dcfef857492156971f0e6aa2c538d8b74010f8e140811d53b98c765dd2
d96126051913f44582e8c199ad7c6d6819e9a56483f637feaac9448aacf8599020010db885a308d3
13198a2e037073488203e78203e8b8408dcab8618c3253b558d459da53bd8fa68935a719aff8b811
197101a4b2b47dd2d47295286fc00cc081bb542d760717d1bdd6bec2c37cd72eca367d6dd3b9df73
8443b9a355010203b525a138aa34383fec3d2719a0
```

#### RLPx Handshake

In these test vectors, node A initiates a connection with node B.
The values contained in all packets are given below:

```text
Static Key A:    49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee
Static Key B:    b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291
Ephemeral Key A: 869d6ecf5211f1cc60418a13b9d870b22959d0c16f02bec714c960dd2298a32d
Ephemeral Key B: e238eb8e04fee6511ab04c6dd3c89ce097b11f25d584863ac2b6d5b35b1847e4
Nonce A:         7e968bba13b6c50e2c4cd7f241cc0d64d1ac25c7f5952df231ac6a2bda8ee5d6
Nonce B:         559aead08264d5795d3909718cdd05abd49572e84fe55590eef31a88a08fdffd
```

(Auth₁)  RLPx v4 format (sent from A to B):
```text
048ca79ad18e4b0659fab4853fe5bc58eb83992980f4c9cc147d2aa31532efd29a3d3dc6a3d89eaf
913150cfc777ce0ce4af2758bf4810235f6e6ceccfee1acc6b22c005e9e3a49d6448610a58e98744
ba3ac0399e82692d67c1f58849050b3024e21a52c9d3b01d871ff5f210817912773e610443a9ef14
2e91cdba0bd77b5fdf0769b05671fc35f83d83e4d3b0b000c6b2a1b1bba89e0fc51bf4e460df3105
c444f14be226458940d6061c296350937ffd5e3acaceeaaefd3c6f74be8e23e0f45163cc7ebd7622
0f0128410fd05250273156d548a414444ae2f7dea4dfca2d43c057adb701a715bf59f6fb66b2d1d2
0f2c703f851cbf5ac47396d9ca65b6260bd141ac4d53e2de585a73d1750780db4c9ee4cd4d225173
a4592ee77e2bd94d0be3691f3b406f9bba9b591fc63facc016bfa8
```

(Auth₂) EIP-8 format with version 4 and no additional list elements (sent from A to B):
```text
01b304ab7578555167be8154d5cc456f567d5ba302662433674222360f08d5f1534499d3678b513b
0fca474f3a514b18e75683032eb63fccb16c156dc6eb2c0b1593f0d84ac74f6e475f1b8d56116b84
9634a8c458705bf83a626ea0384d4d7341aae591fae42ce6bd5c850bfe0b999a694a49bbbaf3ef6c
da61110601d3b4c02ab6c30437257a6e0117792631a4b47c1d52fc0f8f89caadeb7d02770bf999cc
147d2df3b62e1ffb2c9d8c125a3984865356266bca11ce7d3a688663a51d82defaa8aad69da39ab6
d5470e81ec5f2a7a47fb865ff7cca21516f9299a07b1bc63ba56c7a1a892112841ca44b6e0034dee
70c9adabc15d76a54f443593fafdc3b27af8059703f88928e199cb122362a4b35f62386da7caad09
c001edaeb5f8a06d2b26fb6cb93c52a9fca51853b68193916982358fe1e5369e249875bb8d0d0ec3
6f917bc5e1eafd5896d46bd61ff23f1a863a8a8dcd54c7b109b771c8e61ec9c8908c733c0263440e
2aa067241aaa433f0bb053c7b31a838504b148f570c0ad62837129e547678c5190341e4f1693956c
3bf7678318e2d5b5340c9e488eefea198576344afbdf66db5f51204a6961a63ce072c8926c
```

(Auth₃) EIP-8 format with version 56 and 3 additional list elements (sent from A to B):
```text
01b8044c6c312173685d1edd268aa95e1d495474c6959bcdd10067ba4c9013df9e40ff45f5bfd6f7
2471f93a91b493f8e00abc4b80f682973de715d77ba3a005a242eb859f9a211d93a347fa64b597bf
280a6b88e26299cf263b01b8dfdb712278464fd1c25840b995e84d367d743f66c0e54a586725b7bb
f12acca27170ae3283c1073adda4b6d79f27656993aefccf16e0d0409fe07db2dc398a1b7e8ee93b
cd181485fd332f381d6a050fba4c7641a5112ac1b0b61168d20f01b479e19adf7fdbfa0905f63352
bfc7e23cf3357657455119d879c78d3cf8c8c06375f3f7d4861aa02a122467e069acaf513025ff19
6641f6d2810ce493f51bee9c966b15c5043505350392b57645385a18c78f14669cc4d960446c1757
1b7c5d725021babbcd786957f3d17089c084907bda22c2b2675b4378b114c601d858802a55345a15
116bc61da4193996187ed70d16730e9ae6b3bb8787ebcaea1871d850997ddc08b4f4ea668fbf3740
7ac044b55be0908ecb94d4ed172ece66fd31bfdadf2b97a8bc690163ee11f5b575a4b44e36e2bfb2
f0fce91676fd64c7773bac6a003f481fddd0bae0a1f31aa27504e2a533af4cef3b623f4791b2cca6
d490
```

(Ack₁) RLPx v4 format (sent from B to A):
```text
049f8abcfa9c0dc65b982e98af921bc0ba6e4243169348a236abe9df5f93aa69d99cadddaa387662
b0ff2c08e9006d5a11a278b1b3331e5aaabf0a32f01281b6f4ede0e09a2d5f585b26513cb794d963
5a57563921c04a9090b4f14ee42be1a5461049af4ea7a7f49bf4c97a352d39c8d02ee4acc416388c
1c66cec761d2bc1c72da6ba143477f049c9d2dde846c252c111b904f630ac98e51609b3b1f58168d
dca6505b7196532e5f85b259a20c45e1979491683fee108e9660edbf38f3add489ae73e3dda2c71b
d1497113d5c755e942d1
```

(Ack₂) EIP-8 format with version 4 and no additional list elements (sent from B to A):
```text
01ea0451958701280a56482929d3b0757da8f7fbe5286784beead59d95089c217c9b917788989470
b0e330cc6e4fb383c0340ed85fab836ec9fb8a49672712aeabbdfd1e837c1ff4cace34311cd7f4de
05d59279e3524ab26ef753a0095637ac88f2b499b9914b5f64e143eae548a1066e14cd2f4bd7f814
c4652f11b254f8a2d0191e2f5546fae6055694aed14d906df79ad3b407d94692694e259191cde171
ad542fc588fa2b7333313d82a9f887332f1dfc36cea03f831cb9a23fea05b33deb999e85489e645f
6aab1872475d488d7bd6c7c120caf28dbfc5d6833888155ed69d34dbdc39c1f299be1057810f34fb
e754d021bfca14dc989753d61c413d261934e1a9c67ee060a25eefb54e81a4d14baff922180c395d
3f998d70f46f6b58306f969627ae364497e73fc27f6d17ae45a413d322cb8814276be6ddd13b885b
201b943213656cde498fa0e9ddc8e0b8f8a53824fbd82254f3e2c17e8eaea009c38b4aa0a3f306e8
797db43c25d68e86f262e564086f59a2fc60511c42abfb3057c247a8a8fe4fb3ccbadde17514b7ac
8000cdb6a912778426260c47f38919a91f25f4b5ffb455d6aaaf150f7e5529c100ce62d6d92826a7
1778d809bdf60232ae21ce8a437eca8223f45ac37f6487452ce626f549b3b5fdee26afd2072e4bc7
5833c2464c805246155289f4
```

(Ack₃) EIP-8 format with version 57 and 3 additional list elements (sent from B to A):
```text
01f004076e58aae772bb101ab1a8e64e01ee96e64857ce82b1113817c6cdd52c09d26f7b90981cd7
ae835aeac72e1573b8a0225dd56d157a010846d888dac7464baf53f2ad4e3d584531fa203658fab0
3a06c9fd5e35737e417bc28c1cbf5e5dfc666de7090f69c3b29754725f84f75382891c561040ea1d
dc0d8f381ed1b9d0d4ad2a0ec021421d847820d6fa0ba66eaf58175f1b235e851c7e2124069fbc20
2888ddb3ac4d56bcbd1b9b7eab59e78f2e2d400905050f4a92dec1c4bdf797b3fc9b2f8e84a482f3
d800386186712dae00d5c386ec9387a5e9c9a1aca5a573ca91082c7d68421f388e79127a5177d4f8
590237364fd348c9611fa39f78dcdceee3f390f07991b7b47e1daa3ebcb6ccc9607811cb17ce51f1
c8c2c5098dbdd28fca547b3f58c01a424ac05f869f49c6a34672ea2cbbc558428aa1fe48bbfd6115
8b1b735a65d99f21e70dbc020bfdface9f724a0d1fb5895db971cc81aa7608baa0920abb0a565c9c
436e2fd13323428296c86385f2384e408a31e104670df0791d93e743a3a5194ee6b076fb6323ca59
3011b7348c16cf58f66b9633906ba54a2ee803187344b394f75dd2e663a57b956cb830dd7a908d4f
39a2336a61ef9fda549180d4ccde21514d117b6c6fd07a9102b5efe710a32af4eeacae2cb3b1dec0
35b9593b48b9d3ca4c13d245d5f04169b0b1
```

Node B derives the connection secrets for (Auth₂, Ack₂) as follows:

```text
aes-secret = 80e8632c05fed6fc2a13b0f8d31a3cf645366239170ea067065aba8e28bac487
mac-secret = 2ea74ec5dae199227dff1af715362700e989d889d7a493cb0639691efb8e5f98
```

Running B&apos;s `ingress-mac` keccak state on the string &quot;foo&quot; yields the hash

```text
ingress-mac(&quot;foo&quot;) = 0c7ec6340062cc46f5e9f1e3cf86f8c8c403c5a0964f5df0ebd34a75ddc86db5
```

### Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 18 Dec 2015 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8</guid>
      </item>
    
      <item>
        <title>Token Standard</title>
        <category>Standards Track/ERC</category>
        
        <description>## Simple Summary

A standard interface for tokens.


## Abstract

The following standard allows for the implementation of a standard API for tokens within smart contracts.
This standard provides basic functionality to transfer tokens, as well as allow tokens to be approved so they can be spent by another on-chain third party.


## Motivation

A standard interface allows any tokens on Ethereum to be re-used by other applications: from wallets to decentralized exchanges.


## Specification

## Token
### Methods

**NOTES**:
 - The following specifications use syntax from Solidity `0.4.17` (or above)
 - Callers MUST handle `false` from `returns (bool success)`.  Callers MUST NOT assume that `false` is never returned!


#### name

Returns the name of the token - e.g. `&quot;MyToken&quot;`.

OPTIONAL - This method can be used to improve usability,
but interfaces and other contracts MUST NOT expect these values to be present.


``` js
function name() public view returns (string)
```


#### symbol

Returns the symbol of the token. E.g. &quot;HIX&quot;.

OPTIONAL - This method can be used to improve usability,
but interfaces and other contracts MUST NOT expect these values to be present.

``` js
function symbol() public view returns (string)
```



#### decimals

Returns the number of decimals the token uses - e.g. `8`, means to divide the token amount by `100000000` to get its user representation.

OPTIONAL - This method can be used to improve usability,
but interfaces and other contracts MUST NOT expect these values to be present.

``` js
function decimals() public view returns (uint8)
```


#### totalSupply

Returns the total token supply.

``` js
function totalSupply() public view returns (uint256)
```



#### balanceOf

Returns the account balance of another account with address `_owner`.

``` js
function balanceOf(address _owner) public view returns (uint256 balance)
```



#### transfer

Transfers `_value` amount of tokens to address `_to`, and MUST fire the `Transfer` event.
The function SHOULD `throw` if the message caller&apos;s account balance does not have enough tokens to spend.

*Note* Transfers of 0 values MUST be treated as normal transfers and fire the `Transfer` event.

``` js
function transfer(address _to, uint256 _value) public returns (bool success)
```



#### transferFrom

Transfers `_value` amount of tokens from address `_from` to address `_to`, and MUST fire the `Transfer` event.

The `transferFrom` method is used for a withdraw workflow, allowing contracts to transfer tokens on your behalf.
This can be used for example to allow a contract to transfer tokens on your behalf and/or to charge fees in sub-currencies.
The function SHOULD `throw` unless the `_from` account has deliberately authorized the sender of the message via some mechanism.

*Note* Transfers of 0 values MUST be treated as normal transfers and fire the `Transfer` event.

``` js
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)
```



#### approve

Allows `_spender` to withdraw from your account multiple times, up to the `_value` amount. If this function is called again it overwrites the current allowance with `_value`.

**NOTE**: To prevent attack vectors like the one [described here](https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/) and discussed [here](https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729),
clients SHOULD make sure to create user interfaces in such a way that they set the allowance first to `0` before setting it to another value for the same spender.
THOUGH The contract itself shouldn&apos;t enforce it, to allow backwards compatibility with contracts deployed before

``` js
function approve(address _spender, uint256 _value) public returns (bool success)
```


#### allowance

Returns the amount which `_spender` is still allowed to withdraw from `_owner`.

``` js
function allowance(address _owner, address _spender) public view returns (uint256 remaining)
```



### Events


#### Transfer

MUST trigger when tokens are transferred, including zero value transfers.

A token contract which creates new tokens SHOULD trigger a Transfer event with the `_from` address set to `0x0` when tokens are created.

``` js
event Transfer(address indexed _from, address indexed _to, uint256 _value)
```



#### Approval

MUST trigger on any successful call to `approve(address _spender, uint256 _value)`.

``` js
event Approval(address indexed _owner, address indexed _spender, uint256 _value)
```



## Implementation

There are already plenty of ERC20-compliant tokens deployed on the Ethereum network.
Different implementations have been written by various teams that have different trade-offs: from gas saving to improved security.

#### Example implementations are available at
- [OpenZeppelin implementation](/EIPs/assets/eip-20/OpenZeppelin-ERC20.sol)
- [ConsenSys implementation](/EIPs/assets/eip-20/Consensys-EIP20.sol)


## History

Historical links related to this standard:

- Original proposal from Vitalik Buterin: https://github.com/ethereum/wiki/wiki/Standardized_Contract_APIs/499c882f3ec123537fc2fccd57eaa29e6032fe4a
- Reddit discussion: https://www.reddit.com/r/ethereum/comments/3n8fkn/lets_talk_about_the_coin_standard/
- Original Issue #20: https://github.com/ethereum/EIPs/issues/20



## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 19 Nov 2015 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-20</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-20</guid>
      </item>
    
      <item>
        <title>Mixed-case checksum address encoding</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/eips/issues/55</comments>
        
        <description># Specification

Code:

``` python
import eth_utils


def checksum_encode(addr): # Takes a 20-byte binary address as input
    hex_addr = addr.hex()
    checksummed_buffer = &quot;&quot;

    # Treat the hex address as ascii/utf-8 for keccak256 hashing
    hashed_address = eth_utils.keccak(text=hex_addr).hex()

    # Iterate over each character in the hex address
    for nibble_index, character in enumerate(hex_addr):

        if character in &quot;0123456789&quot;:
            # We can&apos;t upper-case the decimal digits
            checksummed_buffer += character
        elif character in &quot;abcdef&quot;:
            # Check if the corresponding hex digit (nibble) in the hash is 8 or higher
            hashed_address_nibble = int(hashed_address[nibble_index], 16)
            if hashed_address_nibble &gt; 7:
                checksummed_buffer += character.upper()
            else:
                checksummed_buffer += character
        else:
            raise eth_utils.ValidationError(
                f&quot;Unrecognized hex character {character!r} at position {nibble_index}&quot;
            )

    return &quot;0x&quot; + checksummed_buffer


def test(addr_str):
    addr_bytes = eth_utils.to_bytes(hexstr=addr_str)
    checksum_encoded = checksum_encode(addr_bytes)
    assert checksum_encoded == addr_str, f&quot;{checksum_encoded} != expected {addr_str}&quot;


test(&quot;0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed&quot;)
test(&quot;0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359&quot;)
test(&quot;0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB&quot;)
test(&quot;0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb&quot;)

```

In English, convert the address to hex, but if the `i`th digit is a letter (ie. it&apos;s one of `abcdef`) print it in uppercase if the `4*i`th bit of the hash of the lowercase hexadecimal address is 1 otherwise print it in lowercase.

# Rationale

Benefits:
- Backwards compatible with many hex parsers that accept mixed case, allowing it to be easily introduced over time
- Keeps the length at 40 characters
- On average there will be 15 check bits per address, and the net probability that a randomly generated address if mistyped will accidentally pass a check is 0.0247%. This is a ~50x improvement over ICAP, but not as good as a 4-byte check code.

# Implementation

In javascript:

```js
const createKeccakHash = require(&apos;keccak&apos;)

function toChecksumAddress (address) {
  address = address.toLowerCase().replace(&apos;0x&apos;, &apos;&apos;)
  var hash = createKeccakHash(&apos;keccak256&apos;).update(address).digest(&apos;hex&apos;)
  var ret = &apos;0x&apos;

  for (var i = 0; i &lt; address.length; i++) {
    if (parseInt(hash[i], 16) &gt;= 8) {
      ret += address[i].toUpperCase()
    } else {
      ret += address[i]
    }
  }

  return ret
}
```

```
&gt; toChecksumAddress(&apos;0xfb6916095ca1df60bb79ce92ce3ea74c37c5d359&apos;)
&apos;0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359&apos;
```

Note that the input to the Keccak256 hash is the lowercase hexadecimal string (i.e. the hex address encoded as ASCII):

```
    var hash = createKeccakHash(&apos;keccak256&apos;).update(Buffer.from(address.toLowerCase(), &apos;ascii&apos;)).digest()
```

# Test Cases

```
# All caps
0x52908400098527886E0F7030069857D2E4169EE7
0x8617E340B3D01FA5F11F306F4090FD50E238070D
# All Lower
0xde709f2102306220921060314715629080e2fb77
0x27b1fdb04752bbc536007a920d24acb045561c26
# Normal
0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed
0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359
0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB
0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb
```
</description>
        <pubDate>Thu, 14 Jan 2016 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-55</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-55</guid>
      </item>
    
      <item>
        <title>URI Scheme with Metadata, Value and Bytecode</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/67</comments>
        
        <description>## Abstract

This proposal (inspired by BIP 21) defines a format for encoding a transaction into a URI, including a recipient, number of ethers (possibly zero), and optional bytecode.

## Motivation

Imagine these scenarios:

    * An exchange or a instant converter like ShapeShift wants to create a single Ethereum address for payments that will be converted into credit in their internal system or output bitcoin to an address.
    * A store wants to show a QR code to a client that will pop up a payment for exactly 12.34 ethers, which contains metadata on the product being bought.
    * A betting site wants to provide a link that the user can click on his site and it will open a default Ethereum wallet and execute a specific contract with given parameters.
    * A dapp in Mist wants to simply ask the user to sign a transaction with a specific ABI in a single call.


In all these scenarios, the provider wants to internally set up a transaction, with a recipient, an associated number of ethers (or none) and optional bytecode, all without requiring any fuss from the end user that is expected simply to choose a sender and authorise the transaction.

Currently implementations for this are wonky: ShapeShift creates tons of temporary addresses and uses an internal system to check which one correspond to which metadata, there isn&apos;t any standard way for stores that want payment in ether to put specific metadata about price on the call and any app implementing contracts will have to use different solutions depending on the client they are targeting.

The proposal goes beyond address, and also includes optional bytecode and value. Of course this would make the link longer, but it should not be something visible to the user. Instead it should be shown as a visual code (QR or otherwise), a link, or some other way to pass the information.

If properly implemented in all wallets, this should make execution of contracts directly from wallets much simpler as the wallet client only needs to put the bytecode obtained by reading the QR code.

## Specification

If we follow the bitcoin standard, the result would be:

```
 ethereum:&lt;address&gt;[?value=&lt;value&gt;][?gas=&lt;suggestedGas&gt;][?data=&lt;bytecode&gt;]
```

Other data could be added, but ideally the client should take them from elsewhere in the blockchain, so instead of having a `label` or a `message` to be displayed to the users, these should be read from an identity system or metadata on the transaction itself.

### Example 1

Clicking this link would open a transaction that would try to send _5 unicorns_ to address _deadbeef_. The user would then simply approve, based on each wallet UI.

```
 ethereum:0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7?gas=100000&amp;data=0xa9059cbb00000000000000000000000000000000000000000000000000000000deadbeef0000000000000000000000000000000000000000000000000000000000000005
```

#### Without Bytecode

Alternatively, the bytecode could be generated by the client and the request would be in plain text:

```
 ethereum:&lt;address&gt;[?value=&lt;value&gt;][?gas=&lt;suggestedGas&gt;][?function=nameOfFunction(param)]
```

### Example 2

This is the same function as above, to send 5 unicorns from he sender to _deadbeef_, but now with a more readable function, which the client converts to bytecode.

```
 ethereum:0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7?gas=100000&amp;function=transfer(address 0xdeadbeef, uint 5)
```

## Rationale

TODO

## Security Considerations

TODO

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 17 Feb 2016 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-67</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-67</guid>
      </item>
    
      <item>
        <title>Abstraction of transaction origin and signature</title>
        <category>Standards Track/Core</category>
        
        <description># Summary

Implements a set of changes that serve the combined purpose of &quot;abstracting out&quot; signature verification and nonce checking, allowing users to create &quot;account contracts&quot; that perform any desired signature/nonce checks instead of using the mechanism that is currently hard-coded into transaction processing.

# Parameters

* METROPOLIS_FORK_BLKNUM: TBD
* CHAIN_ID: same as used for EIP 155 (ie. 1 for mainnet, 3 for testnet)
* NULL_SENDER: 2**160 - 1

# Specification

If `block.number &gt;= METROPOLIS_FORK_BLKNUM`, then:
1. If the signature of a transaction is `(CHAIN_ID, 0, 0)` (ie. `r = s = 0`, `v = CHAIN_ID`), then treat it as valid and set the sender address to `NULL_SENDER`
2. Transactions of this form MUST have gasprice = 0, nonce = 0, value = 0, and do NOT increment the nonce of account NULL_SENDER.
3. Create a new opcode at `0xfb`, `CREATE2`, with 4 stack arguments (value, salt, mem_start, mem_size) which sets the creation address to `sha3(sender + salt + sha3(init code)) % 2**160`, where `salt` is always represented as a 32-byte value.
4. Add to _all_ contract creation operations, including transactions and opcodes, the rule that if a contract at that address already exists and has non-empty code OR non-empty nonce, the operation fails and returns 0 as if the init code had run out of gas. If an account has empty code and nonce but nonempty balance, the creation operation may still succeed.

# Rationale

The goal of these changes is to set the stage for abstraction of account security. Instead of having an in-protocol mechanism where ECDSA and the default nonce scheme are enshrined as the only &quot;standard&quot; way to secure an account, we take initial steps toward a model where in the long term all accounts are contracts, contracts can pay for gas, and users are free to define their own security model.

Under EIP 86, we can expect users to store their ether in contracts, whose code might look like the following (example in Serpent):

```python
# Get signature from tx data
sig_v = ~calldataload(0)
sig_r = ~calldataload(32)
sig_s = ~calldataload(64)
# Get tx arguments
tx_nonce = ~calldataload(96)
tx_to = ~calldataload(128)
tx_value = ~calldataload(160)
tx_gasprice = ~calldataload(192)
tx_data = string(~calldatasize() - 224)
~calldataload(tx_data, 224, ~calldatasize())
# Get signing hash
signing_data = string(~calldatasize() - 64)
~mstore(signing_data, tx.startgas)
~calldataload(signing_data + 32, 96, ~calldatasize() - 96)
signing_hash = sha3(signing_data:str)
# Perform usual checks
prev_nonce = ~sload(-1)
assert tx_nonce == prev_nonce + 1
assert self.balance &gt;= tx_value + tx_gasprice * tx.startgas
assert ~ecrecover(signing_hash, sig_v, sig_r, sig_s) == &lt;pubkey hash here&gt;
# Update nonce
~sstore(-1, prev_nonce + 1)
# Pay for gas
~send(MINER_CONTRACT, tx_gasprice * tx.startgas)
# Make the main call
~call(msg.gas - 50000, tx_to, tx_value, tx_data, len(tx_data), 0, 0)
# Get remaining gas payments back
~call(20000, MINER_CONTRACT, 0, [msg.gas], 32, 0, 0)
```

This can be thought of as a &quot;forwarding contract&quot;. It accepts data from the &quot;entry point&quot; address 2**160 - 1 (an account that anyone can send transactions from), expecting that data to be in the format `[sig, nonce, to, value, gasprice, data]`. The forwarding contract verifies the signature, and if the signature is correct it sets up a payment to the miner and then sends a call to the desired address with the provided value and data.

The benefits that this provides lie in the most interesting cases:

- **Multisig wallets**: currently, sending from a multisig wallet requires each operation to be ratified by the participants, and each ratification is a transaction. This could be simplified by having one ratification transaction include signatures from the other participants, but even still it introduces complexity because the participants&apos; accounts all need to be stocked up with ETH. With this EIP, it will be possible to just have the contract store the ETH, send a transaction containing all signatures to the contract directly, and the contract can pay the fees.
- **Ring signature mixers**: the way that ring signature mixers work is that N individuals send 1 coin into a contract, and then use a linkable ring signature to withdraw 1 coin later on. The linkable ring signature ensures that the withdrawal transaction cannot be linked to the deposit, but if someone attempts to withdraw twice then those two signatures can be linked and the second one prevented. However, currently there is a privacy risk: to withdraw, you need to have coins to pay for gas, and if these coins are not properly mixed then you risk compromising your privacy. With this EIP, you can pay for gas straight our of your withdrawn coins.
- **Custom cryptography**: users can upgrade to ed25519 signatures, Lamport hash ladder signatures or whatever other scheme they want on their own terms; they do not need to stick with ECDSA.
- **Non-cryptographic modifications**: users can require transactions to have expiry times (this being standard would allow old empty/dust accounts to be flushed from the state securely), use k-parallelizable nonces (a scheme that allows transactions to be confirmed slightly out-of-order, reducing inter-transaction dependence), or make other modifications.

(2) and (3) introduce a feature similar to bitcoin&apos;s P2SH, allowing users to send funds to addresses that provably map to only one particular piece of code. Something like this is crucial in the long term because, in a world where all accounts are contracts, we need to preserve the ability to send to an account before that account exists on-chain, as that&apos;s a basic functionality that exists in all blockchain protocols today.

# Miner and transaction replaying strategy

Note that miners would need to have a strategy for accepting these transactions. This strategy would need to be very discriminating, because otherwise they run the risk of accepting transactions that do not pay them any fees, and possibly even transactions that have no effect (eg. because the transaction was already included and so the nonce is no longer current).

One simple strategy is to have a set of regexps that the to address of an account would be checked against, each regexp corresponding to a &quot;standard account type&quot; which is known to be &quot;safe&quot; (in the sense that if an account has that code, and a particular check involving the account balances, account storage and transaction data passes, then if the transaction is included in a block the miner will get paid), and mine and relay transactions that pass these checks.

One example would be to check as follows:

1. Check that the to address has code which is the compiled version of the Serpent code above, with `&lt;pubkey hash here&gt;` replaced with any public key hash.
2. Check that the signature in the transaction data verifies with that key hash.
3. Check that the gasprice in the transaction data is sufficiently high
4. Check that the nonce in the state matches the nonce in the transaction data
5. Check that there is enough ether in the account to pay for the fee

If all five checks pass, relay and/or mine the transaction.

A looser but still effective strategy would be to accept any code that fits the same general format as the above, consuming only a limited amount of gas to perform nonce and signature checks and having a guarantee that transaction fees will be paid to the miner. Another strategy is to, alongside other approaches, try to process any transaction that asks for less than 250,000 gas, and include it only if the miner&apos;s balance is appropriately higher after executing the transaction than before it.

# Copyright

Copyright and related rights waived via CC0.
</description>
        <pubDate>Fri, 10 Feb 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-86</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-86</guid>
      </item>
    
      <item>
        <title>Change difficulty adjustment to target mean block time including uncles</title>
        <category>Standards Track/Core</category>
        
        <description>### Specification

Currently, the formula to compute the difficulty of a block includes the following logic:

``` python
adj_factor = max(1 - ((timestamp - parent.timestamp) // 10), -99)
child_diff = int(max(parent.difficulty + (parent.difficulty // BLOCK_DIFF_FACTOR) * adj_factor, min(parent.difficulty, MIN_DIFF)))
...
```

If `block.number &gt;= BYZANTIUM_FORK_BLKNUM`, we change the first line to the following:

``` python
adj_factor = max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99)
```
### Rationale

This new formula ensures that the difficulty adjustment algorithm targets a constant average rate of blocks produced including uncles, and so ensures a highly predictable issuance rate that cannot be manipulated upward by manipulating the uncle rate. A formula that accounts for the exact number of included uncles:
``` python
adj_factor = max(1 + len(parent.uncles) - ((timestamp - parent.timestamp) // 9), -99)
```
can be fairly easily seen to be (to within a tolerance of ~3/4194304) mathematically equivalent to assuming that a block with `k` uncles is equivalent to a sequence of `k+1` blocks that all appear with the exact same timestamp, and this is likely the simplest possible way to accomplish the desired effect. But since the exact formula depends on the full block and not just the header, we are instead using an approximate formula that accomplishes almost the same effect but has the benefit that it depends only on the block header (as you can check the uncle hash against the blank hash).

Changing the denominator from 10 to 9 ensures that the block time remains roughly the same (in fact, it should decrease by ~3% given the current uncle rate of 7%).

### References

1. EIP 100 issue and discussion: https://github.com/ethereum/EIPs/issues/100
2. https://bitslog.wordpress.com/2016/04/28/uncle-mining-an-ethereum-consensus-protocol-flaw/
</description>
        <pubDate>Thu, 28 Apr 2016 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-100</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-100</guid>
      </item>
    
      <item>
        <title>Serenity Currency and Crypto Abstraction</title>
        <category>Standards Track/Core</category>
        
        <description>### Specification

1.  Accounts now have only two fields in their RLP encoding: **code** and **storage**.
2.  Ether is no longer stored in account objects directly; instead, at address `0`, we premine a contract which contains all ether holdings. The `eth.getBalance` command in web3 is remapped appropriately.
3.  `msg.value` no longer exists as an opcode.
4.  A transaction now only has four fields: **to**, **startgas**, **data** and **code**.
5.  Aside from an RLP validity check, and checking that the **to** field is twenty bytes long, the **startgas** is an integer, and **code** is either empty or hashes to the **to** address, there are no other validity constraints; anything goes. However, the block gas limit remains, so miners are disincentivized from including junk.
6.  Gas is charged for bytes in **code** at the same rate as **data**.
7.  When a transaction is sent, if the receiving account does not yet exist, the account is created, and its code is set to the code provided in the transaction; otherwise the code is ignored.
8.  A `tx.gas` opcode is added alongside the existing `msg.gas` at index `0x5c`; this new opcode allows the transaction to access the original amount of gas allotted for the transaction

Note that `ECRECOVER`, sequence number/nonce incrementing and ether are now nowhere in the bottom-level spec (NOTE: ether is going to continue to have a privileged role in Casper PoS). To replicate existing functionality under the new model, we do the following.

Simple user accounts can have the following default standardized code:

```python
# We assume that data takes the following schema:
# bytes 0-31: v (ECDSA sig)
# bytes 32-63: r (ECDSA sig)
# bytes 64-95: s (ECDSA sig)
# bytes 96-127: sequence number (formerly called &quot;nonce&quot;)
# bytes 128-159: gasprice
# bytes 172-191: to
# bytes 192+: data

# Get the hash for transaction signing
~mstore(0, msg.gas)
~calldatacopy(32, 96, ~calldatasize() - 96)
h = sha3(96, ~calldatasize() - 96)
# Call ECRECOVER contract to get the sender
~call(5000, 3, [h, ~calldataload(0), ~calldataload(32), ~calldataload(64)], 128, ref(addr), 32)
# Check sender correctness
assert addr == 0x82a978b3f5962a5b0957d9ee9eef472ee55b42f1
# Check sequence number correctness
assert ~calldataload(96) == self.storage[-1]
# Increment sequence number
self.storage[-1] += 1
# Make the sub-call and discard output
~call(msg.gas - 50000, ~calldataload(160), 192, ~calldatasize() - 192, 0, 0)
# Pay for gas
~call(40000, 0, [SEND, block.coinbase, ~calldataload(128) * (tx.gas - msg.gas + 50000)], 96, 0, 0)
```

This essentially implements signature and nonce checking, and if both checks pass then it uses all remaining gas minus 50000 to send the actual desired call, and then finally pays for gas.

Miners can follow the following algorithm upon receiving transactions:

1.  Run the code for a maximum of 50000 gas, stopping if they see an operation or call that threatens to go over this limit
2.  Upon seeing that operation, make sure that it leaves at least 50000 gas to spare (either by checking that the static gas consumption is small enough or by checking that it is a call with `msg.gas - 50000` as its gas limit parameter)
3.  Pattern-match to make sure that gas payment code at the end is *exactly* the same as in the code above.

This process ensures that miners *waste* at most 50000 gas before knowing whether or not it will be worth their while to include the transaction, and is also highly general so users can experiment with new cryptography (eg. ed25519, Lamport), ring signatures, quasi-native multisig, etc. Theoretically, one can even create an account for which the *valid signature* type is a valid Merkle branch of a receipt, creating a quasi-native alarm clock.

If someone wants to send a transaction with nonzero value, instead of the current `msg.sender` approach, we compile into a three step process:

1.  In the outer scope just before calling, call the ether contract to create a cheque for the desired amount
2.  In the inner scope, if a contract uses the `msg.value` opcode anywhere in the function that is being called, then we have the contract cash out the cheque at the start of the function call and store the amount cashed out in a standardized address in memory
3.  In the outer scope just after calling, send a message to the ether contract to disable the cheque if it has not yet been cashed

### Rationale

This allows for a large increase in generality, particularly in a few
areas:

1.  Cryptographic algorithms used to secure accounts (we could reasonably say that Ethereum is quantum-safe, as one is perfectly free to secure one&apos;s account with Lamport signatures). The nonce-incrementing approach is now also open to revision on the part of account holders, allowing for experimentation in k-parallelizable nonce techniques, UTXO schemes, etc.
2.  Moving ether up a level of abstraction, with the particular benefit of allowing ether and sub-tokens to be treated similarly by contracts
3.  Reducing the level of indirection required for custom-policy accounts such as multisigs

It also substantially simplifies and *purifies* the underlying Ethereum protocol, reducing the minimal consensus implementation complexity.

### Implementation

Coming soon.
</description>
        <pubDate>Sun, 15 Nov 2015 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-101</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-101</guid>
      </item>
    
      <item>
        <title>safe &quot;eth_sendTransaction&quot; authorization via html popup</title>
        <category>Standards Track/Interface</category>
        
        <description>## Abstract

This draft EIP describes the details of an authorization method that if provided by rpc enabled ethereum nodes would allow regular websites to send transactions (via ```eth_sendTransaction```) without the need to enable CORS. Instead, user would be asked to confirm the transaction via an html popup.

Every read only rpc call the dapp wants to perform is redirected to an invisible iframe from the node&apos;s domain and for every transaction that the dapp wish to execute, an html popup is presented to the user to allow him/her to cancel or confirm the transaction. This allows the dapp to connect to the node&apos;s rpc api without being  granted any kind of privileges. This allows users to safely interact with dapps running in their everyday web browser while their accounts are unlocked. In case the account is not unlocked, and the node has allowed the &quot;personal&quot; api via rpc,the html page also allow the user to enter their password to unlock the account for the scope of the transaction.

## Motivation

Currently, if a user navigates to a dapp running on a website using her/his everyday browser, the dapp will by default have no access to the rpc api for security reasons. The user will have to enable CORS for the website&apos;s domain in order for the dapp to work. Unfortunately if the user does so, the dapp will be able to send transactions from any unlocked account without the need for any user consent. In other words, not only does the user need to change the node&apos;s default setting, but the user is also forced to trust the dapp in order to use it. This is of course not acceptable and forces existing dapps to rely on the use of workarounds like:
- if the transaction is a plain ether transfer, the user is asked to enter it in a dedicated trusted wallet like &quot;Mist&quot;
- For more complex case, the user is asked to enter the transaction manually via the node command line interface.


This proposal aims to provide a safe and user friendly alternative.

Here are some screenshots of the provided implementation of that html popup:

### Account unlocked

When the account is already unlocked, the user is presented with the following popup for every transaction that the dapp attempts to make:

![](/EIPs/assets/eip-107/authorization.png)

### Account locked and no &quot;personal&quot; api exposed via rpc:

When the account is locked, and the node does not provide access to account unlocking via its rpc interface, the following popup will be presented. This is not ideal since this requires the user to know how to unlock an account:

![](/EIPs/assets/eip-107/authorization-locked.png)

### Account locked but node exposing the &quot;personal&quot; api via rpc :

A better option is to ask the user for their password, but this is only possible if the node allows access to the &quot;personal&quot; api via rpc. In such case, the following dialog will be presented to the user so he/she can accept the transaction by providing the password required to unlock the account:

![](/EIPs/assets/eip-107/authorization-password.png)


## Specification

In order for the mechanism to work, the node needs to serve an html file via http at the url \&lt;node url\&gt;/authorization.html

This file will then be used by the dapp in 2 different modes (invisible iframe and popup window).

The invisible iframe will be embedded in the dapp to allow the dapp to send its read-only rpc call without having to enable CORS for the dapp&apos;s website domain. This is done by sending message to the iframe (via javascript ```window.postMessage```) which in turn execute the rpc call. This works since the iframe and the node share the same domain/port.

In the iframe mode, the html file&apos;s javascript code will ensure that no call requiring an unlocked key can be made. This is to prevent dapps from embedding the invisible iframe and tricking the user into clicking the confirm button.
If the dapp requires an ```eth_sendTransaction``` call, the dapp will instead open a new window using the same url.

In this popup window mode, the html file&apos;s javascript code will allow ```eth_sendTransaction``` (but not  ```eth_sign```, as there is no way to display to the user the meaningful content of the transaction to sign in a safe way) to be called. But instead of sending the call to the node directly, a confirmation dialog will be presented showing the sender and recipient addresses, as well as the amount being transferred along with the potential gas cost. Upon the user approving, the request will be sent and the result returned to the dapp. An error will be returned in case the user cancel the request.

The html page also checks for the availability of the &quot;personal&quot; api and if so, will ask the user to unlock the account if necessary. The unlocking is temporary (3s) so the password will be asked again if a transaction is attempted before the end of this short time.

In both iframe mode and window mode, the communication with the dapp is achieved using ```window.postMessage```.
The first message the iframe/window sends is a message containing the string &quot;ready&quot; to let the dapp know that it now accepts messages. Then the dapp can start performing rpc call by sending message using the following object :
```
{
  id:&lt;an id&gt;, //so responses can be match as there is no guarantee of the order of the response
  payload:&lt;json rpc object&gt; //this is the exact object that usually send to the node
}
```

For ```eth_sendTransaction``` the &quot;gas&quot;, &quot;gasPrice&quot; and &quot;from&quot; field need to be set in the rpc parameter so that the window can display the correct value. If not all of these are passed in, the window will return an error.

Upon receiving such message, the iframe will perform the actual rpc call to the node but only if such a call is a read only call (not requiring an unlocked key). If it is not it will return a error. The window on the other will only accept ```eth_sendTransaction``` calls but will display a dialog so the user can accept or cancel the request.

In all the cases, the iframe/window will send a message back to the dapp using the following object:
```
{
  id:&lt;id matching the request&gt;,
  result:&lt;rpc result as is&gt;,
  error:&lt;error object&gt;
}
```

the error object cannot be a javascript Error object due to postMessage limitation. Instead it is
```
{
  message:&lt;a string describing the error&gt;,
  type:&lt;a string defining the type of error&gt; //type=&quot;cancel&quot; means the user cancel the transaction
}
```


## Rationale

The design for that proposal was chosen for its simplicity and security. A previous idea was to use an oauth-like protocol in order for the user to accept or deny a transaction request. It would have required deeper code change in the node and some geth contributors argues that such change did not fit into geth code base as it would have required dapp aware code.
The current design, instead has a very simple implementation (self contained html file that can be shared across node&apos;s implementation) and its safeness is guaranteed by browsers&apos; cross domain policies.

The use of iframe/ window was required to have both security and user friendliness. The invisible iframe allows the dapp to execute read only calls without the need for user input, and the window ensures user approval before making a call. While we could have made it without the window mode by making the iframe confirmation use the native browser ```window.confirm``` dialog, this would have prevented the use of a more elegant confirmation popup that the current design allows. It also happens to be that the ```window.confirm``` is not safe in some browsers, as it gives focus to the accept option and can be triggered automatically (https://bugs.chromium.org/p/chromium/issues/detail?id=260653).


## Implementations

In order to implement this design, the following html file or an equivalent one needs to be served at the url \&lt;node url\&gt;/authorization.html

That&apos;s it.


```html
&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;Ethereum Authorization&lt;/title&gt;
  &lt;/head&gt;
  &lt;script&gt;
    //https://github.com/alexvandesande/blockies
    !function(){function r(r){for(var t=0;t&lt;l.length;t++)l[t]=0;for(var t=0;t&lt;r.length;t++)l[t%4]=(l[t%4]&lt;&lt;5)-l[t%4]+r.charCodeAt(t)}function t(){var r=l[0]^l[0]&lt;&lt;11;return l[0]=l[1],l[1]=l[2],l[2]=l[3],l[3]=l[3]^l[3]&gt;&gt;19^r^r&gt;&gt;8,(l[3]&gt;&gt;&gt;0)/(1&lt;&lt;31&gt;&gt;&gt;0)}function e(){var r=Math.floor(360*t()),e=60*t()+40+&quot;%&quot;,o=25*(t()+t()+t()+t())+&quot;%&quot;,n=&quot;hsl(&quot;+r+&quot;,&quot;+e+&quot;,&quot;+o+&quot;)&quot;;return n}function o(r){for(var e=r,o=r,n=Math.ceil(e/2),a=e-n,l=[],c=0;o&gt;c;c++){for(var f=[],h=0;n&gt;h;h++)f[h]=Math.floor(2.3*t());var i=f.slice(0,a);i.reverse(),f=f.concat(i);for(var v=0;v&lt;f.length;v++)l.push(f[v])}return l}function n(r,t,e,o,n){var a=document.createElement(&quot;canvas&quot;),l=Math.sqrt(r.length);a.width=a.height=l*e;var c=a.getContext(&quot;2d&quot;);c.fillStyle=o,c.fillRect(0,0,a.width,a.height),c.fillStyle=t;for(var f=0;f&lt;r.length;f++){var h=Math.floor(f/l),i=f%l;c.fillStyle=1==r[f]?t:n,r[f]&amp;&amp;c.fillRect(i*e,h*e,e,e)}return a}function a(t){t=t||{};var a=t.size||8,l=t.scale||4,c=t.seed||Math.floor(Math.random()*Math.pow(10,16)).toString(16);r(c);var f=t.color||e(),h=t.bgcolor||e(),i=t.spotcolor||e(),v=o(a),u=n(v,f,l,h,i);return u}var l=new Array(4);window.blockies={create:a}}();

    /* bignumber.js v2.3.0 https://github.com/MikeMcl/bignumber.js/LICENCE */
    !function(e){&quot;use strict&quot;;function n(e){function E(e,n){var t,r,i,o,u,s,f=this;if(!(f instanceof E))return j&amp;&amp;L(26,&quot;constructor call without new&quot;,e),new E(e,n);if(null!=n&amp;&amp;H(n,2,64,M,&quot;base&quot;)){if(n=0|n,s=e+&quot;&quot;,10==n)return f=new E(e instanceof E?e:s),U(f,P+f.e+1,k);if((o=&quot;number&quot;==typeof e)&amp;&amp;0*e!=0||!new RegExp(&quot;^-?&quot;+(t=&quot;[&quot;+N.slice(0,n)+&quot;]+&quot;)+&quot;(?:\\.&quot;+t+&quot;)?$&quot;,37&gt;n?&quot;i&quot;:&quot;&quot;).test(s))return h(f,s,o,n);o?(f.s=0&gt;1/e?(s=s.slice(1),-1):1,j&amp;&amp;s.replace(/^0\.0*|\./,&quot;&quot;).length&gt;15&amp;&amp;L(M,v,e),o=!1):f.s=45===s.charCodeAt(0)?(s=s.slice(1),-1):1,s=D(s,10,n,f.s)}else{if(e instanceof E)return f.s=e.s,f.e=e.e,f.c=(e=e.c)?e.slice():e,void(M=0);if((o=&quot;number&quot;==typeof e)&amp;&amp;0*e==0){if(f.s=0&gt;1/e?(e=-e,-1):1,e===~~e){for(r=0,i=e;i&gt;=10;i/=10,r++);return f.e=r,f.c=[e],void(M=0)}s=e+&quot;&quot;}else{if(!g.test(s=e+&quot;&quot;))return h(f,s,o);f.s=45===s.charCodeAt(0)?(s=s.slice(1),-1):1}}for((r=s.indexOf(&quot;.&quot;))&gt;-1&amp;&amp;(s=s.replace(&quot;.&quot;,&quot;&quot;)),(i=s.search(/e/i))&gt;0?(0&gt;r&amp;&amp;(r=i),r+=+s.slice(i+1),s=s.substring(0,i)):0&gt;r&amp;&amp;(r=s.length),i=0;48===s.charCodeAt(i);i++);for(u=s.length;48===s.charCodeAt(--u););if(s=s.slice(i,u+1))if(u=s.length,o&amp;&amp;j&amp;&amp;u&gt;15&amp;&amp;(e&gt;y||e!==d(e))&amp;&amp;L(M,v,f.s*e),r=r-i-1,r&gt;z)f.c=f.e=null;else if(G&gt;r)f.c=[f.e=0];else{if(f.e=r,f.c=[],i=(r+1)%O,0&gt;r&amp;&amp;(i+=O),u&gt;i){for(i&amp;&amp;f.c.push(+s.slice(0,i)),u-=O;u&gt;i;)f.c.push(+s.slice(i,i+=O));s=s.slice(i),i=O-s.length}else i-=u;for(;i--;s+=&quot;0&quot;);f.c.push(+s)}else f.c=[f.e=0];M=0}function D(e,n,t,i){var o,u,f,c,a,h,g,p=e.indexOf(&quot;.&quot;),d=P,m=k;for(37&gt;t&amp;&amp;(e=e.toLowerCase()),p&gt;=0&amp;&amp;(f=J,J=0,e=e.replace(&quot;.&quot;,&quot;&quot;),g=new E(t),a=g.pow(e.length-p),J=f,g.c=s(l(r(a.c),a.e),10,n),g.e=g.c.length),h=s(e,t,n),u=f=h.length;0==h[--f];h.pop());if(!h[0])return&quot;0&quot;;if(0&gt;p?--u:(a.c=h,a.e=u,a.s=i,a=C(a,g,d,m,n),h=a.c,c=a.r,u=a.e),o=u+d+1,p=h[o],f=n/2,c=c||0&gt;o||null!=h[o+1],c=4&gt;m?(null!=p||c)&amp;&amp;(0==m||m==(a.s&lt;0?3:2)):p&gt;f||p==f&amp;&amp;(4==m||c||6==m&amp;&amp;1&amp;h[o-1]||m==(a.s&lt;0?8:7)),1&gt;o||!h[0])e=c?l(&quot;1&quot;,-d):&quot;0&quot;;else{if(h.length=o,c)for(--n;++h[--o]&gt;n;)h[o]=0,o||(++u,h.unshift(1));for(f=h.length;!h[--f];);for(p=0,e=&quot;&quot;;f&gt;=p;e+=N.charAt(h[p++]));e=l(e,u)}return e}function F(e,n,t,i){var o,u,s,c,a;if(t=null!=t&amp;&amp;H(t,0,8,i,w)?0|t:k,!e.c)return e.toString();if(o=e.c[0],s=e.e,null==n)a=r(e.c),a=19==i||24==i&amp;&amp;B&gt;=s?f(a,s):l(a,s);else if(e=U(new E(e),n,t),u=e.e,a=r(e.c),c=a.length,19==i||24==i&amp;&amp;(u&gt;=n||B&gt;=u)){for(;n&gt;c;a+=&quot;0&quot;,c++);a=f(a,u)}else if(n-=s,a=l(a,u),u+1&gt;c){if(--n&gt;0)for(a+=&quot;.&quot;;n--;a+=&quot;0&quot;);}else if(n+=u-c,n&gt;0)for(u+1==c&amp;&amp;(a+=&quot;.&quot;);n--;a+=&quot;0&quot;);return e.s&lt;0&amp;&amp;o?&quot;-&quot;+a:a}function _(e,n){var t,r,i=0;for(u(e[0])&amp;&amp;(e=e[0]),t=new E(e[0]);++i&lt;e.length;){if(r=new E(e[i]),!r.s){t=r;break}n.call(t,r)&amp;&amp;(t=r)}return t}function x(e,n,t,r,i){return(n&gt;e||e&gt;t||e!=c(e))&amp;&amp;L(r,(i||&quot;decimal places&quot;)+(n&gt;e||e&gt;t?&quot; out of range&quot;:&quot; not an integer&quot;),e),!0}function I(e,n,t){for(var r=1,i=n.length;!n[--i];n.pop());for(i=n[0];i&gt;=10;i/=10,r++);return(t=r+t*O-1)&gt;z?e.c=e.e=null:G&gt;t?e.c=[e.e=0]:(e.e=t,e.c=n),e}function L(e,n,t){var r=new Error([&quot;new BigNumber&quot;,&quot;cmp&quot;,&quot;config&quot;,&quot;div&quot;,&quot;divToInt&quot;,&quot;eq&quot;,&quot;gt&quot;,&quot;gte&quot;,&quot;lt&quot;,&quot;lte&quot;,&quot;minus&quot;,&quot;mod&quot;,&quot;plus&quot;,&quot;precision&quot;,&quot;random&quot;,&quot;round&quot;,&quot;shift&quot;,&quot;times&quot;,&quot;toDigits&quot;,&quot;toExponential&quot;,&quot;toFixed&quot;,&quot;toFormat&quot;,&quot;toFraction&quot;,&quot;pow&quot;,&quot;toPrecision&quot;,&quot;toString&quot;,&quot;BigNumber&quot;][e]+&quot;() &quot;+n+&quot;: &quot;+t);throw r.name=&quot;BigNumber Error&quot;,M=0,r}function U(e,n,t,r){var i,o,u,s,f,l,c,a=e.c,h=S;if(a){e:{for(i=1,s=a[0];s&gt;=10;s/=10,i++);if(o=n-i,0&gt;o)o+=O,u=n,f=a[l=0],c=f/h[i-u-1]%10|0;else if(l=p((o+1)/O),l&gt;=a.length){if(!r)break e;for(;a.length&lt;=l;a.push(0));f=c=0,i=1,o%=O,u=o-O+1}else{for(f=s=a[l],i=1;s&gt;=10;s/=10,i++);o%=O,u=o-O+i,c=0&gt;u?0:f/h[i-u-1]%10|0}if(r=r||0&gt;n||null!=a[l+1]||(0&gt;u?f:f%h[i-u-1]),r=4&gt;t?(c||r)&amp;&amp;(0==t||t==(e.s&lt;0?3:2)):c&gt;5||5==c&amp;&amp;(4==t||r||6==t&amp;&amp;(o&gt;0?u&gt;0?f/h[i-u]:0:a[l-1])%10&amp;1||t==(e.s&lt;0?8:7)),1&gt;n||!a[0])return a.length=0,r?(n-=e.e+1,a[0]=h[(O-n%O)%O],e.e=-n||0):a[0]=e.e=0,e;if(0==o?(a.length=l,s=1,l--):(a.length=l+1,s=h[O-o],a[l]=u&gt;0?d(f/h[i-u]%h[u])*s:0),r)for(;;){if(0==l){for(o=1,u=a[0];u&gt;=10;u/=10,o++);for(u=a[0]+=s,s=1;u&gt;=10;u/=10,s++);o!=s&amp;&amp;(e.e++,a[0]==b&amp;&amp;(a[0]=1));break}if(a[l]+=s,a[l]!=b)break;a[l--]=0,s=1}for(o=a.length;0===a[--o];a.pop());}e.e&gt;z?e.c=e.e=null:e.e&lt;G&amp;&amp;(e.c=[e.e=0])}return e}var C,M=0,T=E.prototype,q=new E(1),P=20,k=4,B=-7,$=21,G=-1e7,z=1e7,j=!0,H=x,V=!1,W=1,J=100,X={decimalSeparator:&quot;.&quot;,groupSeparator:&quot;,&quot;,groupSize:3,secondaryGroupSize:0,fractionGroupSeparator:&quot; &quot;,fractionGroupSize:0};return E.another=n,E.ROUND_UP=0,E.ROUND_DOWN=1,E.ROUND_CEIL=2,E.ROUND_FLOOR=3,E.ROUND_HALF_UP=4,E.ROUND_HALF_DOWN=5,E.ROUND_HALF_EVEN=6,E.ROUND_HALF_CEIL=7,E.ROUND_HALF_FLOOR=8,E.EUCLID=9,E.config=function(){var e,n,t=0,r={},i=arguments,s=i[0],f=s&amp;&amp;&quot;object&quot;==typeof s?function(){return s.hasOwnProperty(n)?null!=(e=s[n]):void 0}:function(){return i.length&gt;t?null!=(e=i[t++]):void 0};return f(n=&quot;DECIMAL_PLACES&quot;)&amp;&amp;H(e,0,A,2,n)&amp;&amp;(P=0|e),r[n]=P,f(n=&quot;ROUNDING_MODE&quot;)&amp;&amp;H(e,0,8,2,n)&amp;&amp;(k=0|e),r[n]=k,f(n=&quot;EXPONENTIAL_AT&quot;)&amp;&amp;(u(e)?H(e[0],-A,0,2,n)&amp;&amp;H(e[1],0,A,2,n)&amp;&amp;(B=0|e[0],$=0|e[1]):H(e,-A,A,2,n)&amp;&amp;(B=-($=0|(0&gt;e?-e:e)))),r[n]=[B,$],f(n=&quot;RANGE&quot;)&amp;&amp;(u(e)?H(e[0],-A,-1,2,n)&amp;&amp;H(e[1],1,A,2,n)&amp;&amp;(G=0|e[0],z=0|e[1]):H(e,-A,A,2,n)&amp;&amp;(0|e?G=-(z=0|(0&gt;e?-e:e)):j&amp;&amp;L(2,n+&quot; cannot be zero&quot;,e))),r[n]=[G,z],f(n=&quot;ERRORS&quot;)&amp;&amp;(e===!!e||1===e||0===e?(M=0,H=(j=!!e)?x:o):j&amp;&amp;L(2,n+m,e)),r[n]=j,f(n=&quot;CRYPTO&quot;)&amp;&amp;(e===!!e||1===e||0===e?(V=!(!e||!a),e&amp;&amp;!V&amp;&amp;j&amp;&amp;L(2,&quot;crypto unavailable&quot;,a)):j&amp;&amp;L(2,n+m,e)),r[n]=V,f(n=&quot;MODULO_MODE&quot;)&amp;&amp;H(e,0,9,2,n)&amp;&amp;(W=0|e),r[n]=W,f(n=&quot;POW_PRECISION&quot;)&amp;&amp;H(e,0,A,2,n)&amp;&amp;(J=0|e),r[n]=J,f(n=&quot;FORMAT&quot;)&amp;&amp;(&quot;object&quot;==typeof e?X=e:j&amp;&amp;L(2,n+&quot; not an object&quot;,e)),r[n]=X,r},E.max=function(){return _(arguments,T.lt)},E.min=function(){return _(arguments,T.gt)},E.random=function(){var e=9007199254740992,n=Math.random()*e&amp;2097151?function(){return d(Math.random()*e)}:function(){return 8388608*(1073741824*Math.random()|0)+(8388608*Math.random()|0)};return function(e){var t,r,i,o,u,s=0,f=[],l=new E(q);if(e=null!=e&amp;&amp;H(e,0,A,14)?0|e:P,o=p(e/O),V)if(a&amp;&amp;a.getRandomValues){for(t=a.getRandomValues(new Uint32Array(o*=2));o&gt;s;)u=131072*t[s]+(t[s+1]&gt;&gt;&gt;11),u&gt;=9e15?(r=a.getRandomValues(new Uint32Array(2)),t[s]=r[0],t[s+1]=r[1]):(f.push(u%1e14),s+=2);s=o/2}else if(a&amp;&amp;a.randomBytes){for(t=a.randomBytes(o*=7);o&gt;s;)u=281474976710656*(31&amp;t[s])+1099511627776*t[s+1]+4294967296*t[s+2]+16777216*t[s+3]+(t[s+4]&lt;&lt;16)+(t[s+5]&lt;&lt;8)+t[s+6],u&gt;=9e15?a.randomBytes(7).copy(t,s):(f.push(u%1e14),s+=7);s=o/7}else j&amp;&amp;L(14,&quot;crypto unavailable&quot;,a);if(!s)for(;o&gt;s;)u=n(),9e15&gt;u&amp;&amp;(f[s++]=u%1e14);for(o=f[--s],e%=O,o&amp;&amp;e&amp;&amp;(u=S[O-e],f[s]=d(o/u)*u);0===f[s];f.pop(),s--);if(0&gt;s)f=[i=0];else{for(i=-1;0===f[0];f.shift(),i-=O);for(s=1,u=f[0];u&gt;=10;u/=10,s++);O&gt;s&amp;&amp;(i-=O-s)}return l.e=i,l.c=f,l}}(),C=function(){function e(e,n,t){var r,i,o,u,s=0,f=e.length,l=n%R,c=n/R|0;for(e=e.slice();f--;)o=e[f]%R,u=e[f]/R|0,r=c*o+u*l,i=l*o+r%R*R+s,s=(i/t|0)+(r/R|0)+c*u,e[f]=i%t;return s&amp;&amp;e.unshift(s),e}function n(e,n,t,r){var i,o;if(t!=r)o=t&gt;r?1:-1;else for(i=o=0;t&gt;i;i++)if(e[i]!=n[i]){o=e[i]&gt;n[i]?1:-1;break}return o}function r(e,n,t,r){for(var i=0;t--;)e[t]-=i,i=e[t]&lt;n[t]?1:0,e[t]=i*r+e[t]-n[t];for(;!e[0]&amp;&amp;e.length&gt;1;e.shift());}return function(i,o,u,s,f){var l,c,a,h,g,p,m,w,v,N,y,S,R,A,D,F,_,x=i.s==o.s?1:-1,I=i.c,L=o.c;if(!(I&amp;&amp;I[0]&amp;&amp;L&amp;&amp;L[0]))return new E(i.s&amp;&amp;o.s&amp;&amp;(I?!L||I[0]!=L[0]:L)?I&amp;&amp;0==I[0]||!L?0*x:x/0:NaN);for(w=new E(x),v=w.c=[],c=i.e-o.e,x=u+c+1,f||(f=b,c=t(i.e/O)-t(o.e/O),x=x/O|0),a=0;L[a]==(I[a]||0);a++);if(L[a]&gt;(I[a]||0)&amp;&amp;c--,0&gt;x)v.push(1),h=!0;else{for(A=I.length,F=L.length,a=0,x+=2,g=d(f/(L[0]+1)),g&gt;1&amp;&amp;(L=e(L,g,f),I=e(I,g,f),F=L.length,A=I.length),R=F,N=I.slice(0,F),y=N.length;F&gt;y;N[y++]=0);_=L.slice(),_.unshift(0),D=L[0],L[1]&gt;=f/2&amp;&amp;D++;do{if(g=0,l=n(L,N,F,y),0&gt;l){if(S=N[0],F!=y&amp;&amp;(S=S*f+(N[1]||0)),g=d(S/D),g&gt;1)for(g&gt;=f&amp;&amp;(g=f-1),p=e(L,g,f),m=p.length,y=N.length;1==n(p,N,m,y);)g--,r(p,m&gt;F?_:L,m,f),m=p.length,l=1;else 0==g&amp;&amp;(l=g=1),p=L.slice(),m=p.length;if(y&gt;m&amp;&amp;p.unshift(0),r(N,p,y,f),y=N.length,-1==l)for(;n(L,N,F,y)&lt;1;)g++,r(N,y&gt;F?_:L,y,f),y=N.length}else 0===l&amp;&amp;(g++,N=[0]);v[a++]=g,N[0]?N[y++]=I[R]||0:(N=[I[R]],y=1)}while((R++&lt;A||null!=N[0])&amp;&amp;x--);h=null!=N[0],v[0]||v.shift()}if(f==b){for(a=1,x=v[0];x&gt;=10;x/=10,a++);U(w,u+(w.e=a+c*O-1)+1,s,h)}else w.e=c,w.r=+h;return w}}(),h=function(){var e=/^(-?)0([xbo])(?=\w[\w.]*$)/i,n=/^([^.]+)\.$/,t=/^\.([^.]+)$/,r=/^-?(Infinity|NaN)$/,i=/^\s*\+(?=[\w.])|^\s+|\s+$/g;return function(o,u,s,f){var l,c=s?u:u.replace(i,&quot;&quot;);if(r.test(c))o.s=isNaN(c)?null:0&gt;c?-1:1;else{if(!s&amp;&amp;(c=c.replace(e,function(e,n,t){return l=&quot;x&quot;==(t=t.toLowerCase())?16:&quot;b&quot;==t?2:8,f&amp;&amp;f!=l?e:n}),f&amp;&amp;(l=f,c=c.replace(n,&quot;$1&quot;).replace(t,&quot;0.$1&quot;)),u!=c))return new E(c,l);j&amp;&amp;L(M,&quot;not a&quot;+(f?&quot; base &quot;+f:&quot;&quot;)+&quot; number&quot;,u),o.s=null}o.c=o.e=null,M=0}}(),T.absoluteValue=T.abs=function(){var e=new E(this);return e.s&lt;0&amp;&amp;(e.s=1),e},T.ceil=function(){return U(new E(this),this.e+1,2)},T.comparedTo=T.cmp=function(e,n){return M=1,i(this,new E(e,n))},T.decimalPlaces=T.dp=function(){var e,n,r=this.c;if(!r)return null;if(e=((n=r.length-1)-t(this.e/O))*O,n=r[n])for(;n%10==0;n/=10,e--);return 0&gt;e&amp;&amp;(e=0),e},T.dividedBy=T.div=function(e,n){return M=3,C(this,new E(e,n),P,k)},T.dividedToIntegerBy=T.divToInt=function(e,n){return M=4,C(this,new E(e,n),0,1)},T.equals=T.eq=function(e,n){return M=5,0===i(this,new E(e,n))},T.floor=function(){return U(new E(this),this.e+1,3)},T.greaterThan=T.gt=function(e,n){return M=6,i(this,new E(e,n))&gt;0},T.greaterThanOrEqualTo=T.gte=function(e,n){return M=7,1===(n=i(this,new E(e,n)))||0===n},T.isFinite=function(){return!!this.c},T.isInteger=T.isInt=function(){return!!this.c&amp;&amp;t(this.e/O)&gt;this.c.length-2},T.isNaN=function(){return!this.s},T.isNegative=T.isNeg=function(){return this.s&lt;0},T.isZero=function(){return!!this.c&amp;&amp;0==this.c[0]},T.lessThan=T.lt=function(e,n){return M=8,i(this,new E(e,n))&lt;0},T.lessThanOrEqualTo=T.lte=function(e,n){return M=9,-1===(n=i(this,new E(e,n)))||0===n},T.minus=T.sub=function(e,n){var r,i,o,u,s=this,f=s.s;if(M=10,e=new E(e,n),n=e.s,!f||!n)return new E(NaN);if(f!=n)return e.s=-n,s.plus(e);var l=s.e/O,c=e.e/O,a=s.c,h=e.c;if(!l||!c){if(!a||!h)return a?(e.s=-n,e):new E(h?s:NaN);if(!a[0]||!h[0])return h[0]?(e.s=-n,e):new E(a[0]?s:3==k?-0:0)}if(l=t(l),c=t(c),a=a.slice(),f=l-c){for((u=0&gt;f)?(f=-f,o=a):(c=l,o=h),o.reverse(),n=f;n--;o.push(0));o.reverse()}else for(i=(u=(f=a.length)&lt;(n=h.length))?f:n,f=n=0;i&gt;n;n++)if(a[n]!=h[n]){u=a[n]&lt;h[n];break}if(u&amp;&amp;(o=a,a=h,h=o,e.s=-e.s),n=(i=h.length)-(r=a.length),n&gt;0)for(;n--;a[r++]=0);for(n=b-1;i&gt;f;){if(a[--i]&lt;h[i]){for(r=i;r&amp;&amp;!a[--r];a[r]=n);--a[r],a[i]+=b}a[i]-=h[i]}for(;0==a[0];a.shift(),--c);return a[0]?I(e,a,c):(e.s=3==k?-1:1,e.c=[e.e=0],e)},T.modulo=T.mod=function(e,n){var t,r,i=this;return M=11,e=new E(e,n),!i.c||!e.s||e.c&amp;&amp;!e.c[0]?new E(NaN):!e.c||i.c&amp;&amp;!i.c[0]?new E(i):(9==W?(r=e.s,e.s=1,t=C(i,e,0,3),e.s=r,t.s*=r):t=C(i,e,0,W),i.minus(t.times(e)))},T.negated=T.neg=function(){var e=new E(this);return e.s=-e.s||null,e},T.plus=T.add=function(e,n){var r,i=this,o=i.s;if(M=12,e=new E(e,n),n=e.s,!o||!n)return new E(NaN);if(o!=n)return e.s=-n,i.minus(e);var u=i.e/O,s=e.e/O,f=i.c,l=e.c;if(!u||!s){if(!f||!l)return new E(o/0);if(!f[0]||!l[0])return l[0]?e:new E(f[0]?i:0*o)}if(u=t(u),s=t(s),f=f.slice(),o=u-s){for(o&gt;0?(s=u,r=l):(o=-o,r=f),r.reverse();o--;r.push(0));r.reverse()}for(o=f.length,n=l.length,0&gt;o-n&amp;&amp;(r=l,l=f,f=r,n=o),o=0;n;)o=(f[--n]=f[n]+l[n]+o)/b|0,f[n]%=b;return o&amp;&amp;(f.unshift(o),++s),I(e,f,s)},T.precision=T.sd=function(e){var n,t,r=this,i=r.c;if(null!=e&amp;&amp;e!==!!e&amp;&amp;1!==e&amp;&amp;0!==e&amp;&amp;(j&amp;&amp;L(13,&quot;argument&quot;+m,e),e!=!!e&amp;&amp;(e=null)),!i)return null;if(t=i.length-1,n=t*O+1,t=i[t]){for(;t%10==0;t/=10,n--);for(t=i[0];t&gt;=10;t/=10,n++);}return e&amp;&amp;r.e+1&gt;n&amp;&amp;(n=r.e+1),n},T.round=function(e,n){var t=new E(this);return(null==e||H(e,0,A,15))&amp;&amp;U(t,~~e+this.e+1,null!=n&amp;&amp;H(n,0,8,15,w)?0|n:k),t},T.shift=function(e){var n=this;return H(e,-y,y,16,&quot;argument&quot;)?n.times(&quot;1e&quot;+c(e)):new E(n.c&amp;&amp;n.c[0]&amp;&amp;(-y&gt;e||e&gt;y)?n.s*(0&gt;e?0:1/0):n)},T.squareRoot=T.sqrt=function(){var e,n,i,o,u,s=this,f=s.c,l=s.s,c=s.e,a=P+4,h=new E(&quot;0.5&quot;);if(1!==l||!f||!f[0])return new E(!l||0&gt;l&amp;&amp;(!f||f[0])?NaN:f?s:1/0);if(l=Math.sqrt(+s),0==l||l==1/0?(n=r(f),(n.length+c)%2==0&amp;&amp;(n+=&quot;0&quot;),l=Math.sqrt(n),c=t((c+1)/2)-(0&gt;c||c%2),l==1/0?n=&quot;1e&quot;+c:(n=l.toExponential(),n=n.slice(0,n.indexOf(&quot;e&quot;)+1)+c),i=new E(n)):i=new E(l+&quot;&quot;),i.c[0])for(c=i.e,l=c+a,3&gt;l&amp;&amp;(l=0);;)if(u=i,i=h.times(u.plus(C(s,u,a,1))),r(u.c).slice(0,l)===(n=r(i.c)).slice(0,l)){if(i.e&lt;c&amp;&amp;--l,n=n.slice(l-3,l+1),&quot;9999&quot;!=n&amp;&amp;(o||&quot;4999&quot;!=n)){(!+n||!+n.slice(1)&amp;&amp;&quot;5&quot;==n.charAt(0))&amp;&amp;(U(i,i.e+P+2,1),e=!i.times(i).eq(s));break}if(!o&amp;&amp;(U(u,u.e+P+2,0),u.times(u).eq(s))){i=u;break}a+=4,l+=4,o=1}return U(i,i.e+P+1,k,e)},T.times=T.mul=function(e,n){var r,i,o,u,s,f,l,c,a,h,g,p,d,m,w,v=this,N=v.c,y=(M=17,e=new E(e,n)).c;if(!(N&amp;&amp;y&amp;&amp;N[0]&amp;&amp;y[0]))return!v.s||!e.s||N&amp;&amp;!N[0]&amp;&amp;!y||y&amp;&amp;!y[0]&amp;&amp;!N?e.c=e.e=e.s=null:(e.s*=v.s,N&amp;&amp;y?(e.c=[0],e.e=0):e.c=e.e=null),e;for(i=t(v.e/O)+t(e.e/O),e.s*=v.s,l=N.length,h=y.length,h&gt;l&amp;&amp;(d=N,N=y,y=d,o=l,l=h,h=o),o=l+h,d=[];o--;d.push(0));for(m=b,w=R,o=h;--o&gt;=0;){for(r=0,g=y[o]%w,p=y[o]/w|0,s=l,u=o+s;u&gt;o;)c=N[--s]%w,a=N[s]/w|0,f=p*c+a*g,c=g*c+f%w*w+d[u]+r,r=(c/m|0)+(f/w|0)+p*a,d[u--]=c%m;d[u]=r}return r?++i:d.shift(),I(e,d,i)},T.toDigits=function(e,n){var t=new E(this);return e=null!=e&amp;&amp;H(e,1,A,18,&quot;precision&quot;)?0|e:null,n=null!=n&amp;&amp;H(n,0,8,18,w)?0|n:k,e?U(t,e,n):t},T.toExponential=function(e,n){return F(this,null!=e&amp;&amp;H(e,0,A,19)?~~e+1:null,n,19)},T.toFixed=function(e,n){return F(this,null!=e&amp;&amp;H(e,0,A,20)?~~e+this.e+1:null,n,20)},T.toFormat=function(e,n){var t=F(this,null!=e&amp;&amp;H(e,0,A,21)?~~e+this.e+1:null,n,21);if(this.c){var r,i=t.split(&quot;.&quot;),o=+X.groupSize,u=+X.secondaryGroupSize,s=X.groupSeparator,f=i[0],l=i[1],c=this.s&lt;0,a=c?f.slice(1):f,h=a.length;if(u&amp;&amp;(r=o,o=u,u=r,h-=r),o&gt;0&amp;&amp;h&gt;0){for(r=h%o||o,f=a.substr(0,r);h&gt;r;r+=o)f+=s+a.substr(r,o);u&gt;0&amp;&amp;(f+=s+a.slice(r)),c&amp;&amp;(f=&quot;-&quot;+f)}t=l?f+X.decimalSeparator+((u=+X.fractionGroupSize)?l.replace(new RegExp(&quot;\\d{&quot;+u+&quot;}\\B&quot;,&quot;g&quot;),&quot;$&amp;&quot;+X.fractionGroupSeparator):l):f}return t},T.toFraction=function(e){var n,t,i,o,u,s,f,l,c,a=j,h=this,g=h.c,p=new E(q),d=t=new E(q),m=f=new E(q);if(null!=e&amp;&amp;(j=!1,s=new E(e),j=a,(!(a=s.isInt())||s.lt(q))&amp;&amp;(j&amp;&amp;L(22,&quot;max denominator &quot;+(a?&quot;out of range&quot;:&quot;not an integer&quot;),e),e=!a&amp;&amp;s.c&amp;&amp;U(s,s.e+1,1).gte(q)?s:null)),!g)return h.toString();for(c=r(g),o=p.e=c.length-h.e-1,p.c[0]=S[(u=o%O)&lt;0?O+u:u],e=!e||s.cmp(p)&gt;0?o&gt;0?p:d:s,u=z,z=1/0,s=new E(c),f.c[0]=0;l=C(s,p,0,1),i=t.plus(l.times(m)),1!=i.cmp(e);)t=m,m=i,d=f.plus(l.times(i=d)),f=i,p=s.minus(l.times(i=p)),s=i;return i=C(e.minus(t),m,0,1),f=f.plus(i.times(d)),t=t.plus(i.times(m)),f.s=d.s=h.s,o*=2,n=C(d,m,o,k).minus(h).abs().cmp(C(f,t,o,k).minus(h).abs())&lt;1?[d.toString(),m.toString()]:[f.toString(),t.toString()],z=u,n},T.toNumber=function(){return+this},T.toPower=T.pow=function(e,n){var t,r,i,o=d(0&gt;e?-e:+e),u=this;if(null!=n&amp;&amp;(M=23,n=new E(n)),!H(e,-y,y,23,&quot;exponent&quot;)&amp;&amp;(!isFinite(e)||o&gt;y&amp;&amp;(e/=0)||parseFloat(e)!=e&amp;&amp;!(e=NaN))||0==e)return t=Math.pow(+u,e),new E(n?t%n:t);for(n?e&gt;1&amp;&amp;u.gt(q)&amp;&amp;u.isInt()&amp;&amp;n.gt(q)&amp;&amp;n.isInt()?u=u.mod(n):(i=n,n=null):J&amp;&amp;(t=p(J/O+2)),r=new E(q);;){if(o%2){if(r=r.times(u),!r.c)break;t?r.c.length&gt;t&amp;&amp;(r.c.length=t):n&amp;&amp;(r=r.mod(n))}if(o=d(o/2),!o)break;u=u.times(u),t?u.c&amp;&amp;u.c.length&gt;t&amp;&amp;(u.c.length=t):n&amp;&amp;(u=u.mod(n))}return n?r:(0&gt;e&amp;&amp;(r=q.div(r)),i?r.mod(i):t?U(r,J,k):r)},T.toPrecision=function(e,n){return F(this,null!=e&amp;&amp;H(e,1,A,24,&quot;precision&quot;)?0|e:null,n,24)},T.toString=function(e){var n,t=this,i=t.s,o=t.e;return null===o?i?(n=&quot;Infinity&quot;,0&gt;i&amp;&amp;(n=&quot;-&quot;+n)):n=&quot;NaN&quot;:(n=r(t.c),n=null!=e&amp;&amp;H(e,2,64,25,&quot;base&quot;)?D(l(n,o),0|e,10,i):B&gt;=o||o&gt;=$?f(n,o):l(n,o),0&gt;i&amp;&amp;t.c[0]&amp;&amp;(n=&quot;-&quot;+n)),n},T.truncated=T.trunc=function(){return U(new E(this),this.e+1,1)},T.valueOf=T.toJSON=function(){var e,n=this,t=n.e;return null===t?n.toString():(e=r(n.c),e=B&gt;=t||t&gt;=$?f(e,t):l(e,t),n.s&lt;0?&quot;-&quot;+e:e)},null!=e&amp;&amp;E.config(e),E}function t(e){var n=0|e;return e&gt;0||e===n?n:n-1}function r(e){for(var n,t,r=1,i=e.length,o=e[0]+&quot;&quot;;i&gt;r;){for(n=e[r++]+&quot;&quot;,t=O-n.length;t--;n=&quot;0&quot;+n);o+=n}for(i=o.length;48===o.charCodeAt(--i););return o.slice(0,i+1||1)}function i(e,n){var t,r,i=e.c,o=n.c,u=e.s,s=n.s,f=e.e,l=n.e;if(!u||!s)return null;if(t=i&amp;&amp;!i[0],r=o&amp;&amp;!o[0],t||r)return t?r?0:-s:u;if(u!=s)return u;if(t=0&gt;u,r=f==l,!i||!o)return r?0:!i^t?1:-1;if(!r)return f&gt;l^t?1:-1;for(s=(f=i.length)&lt;(l=o.length)?f:l,u=0;s&gt;u;u++)if(i[u]!=o[u])return i[u]&gt;o[u]^t?1:-1;return f==l?0:f&gt;l^t?1:-1}function o(e,n,t){return(e=c(e))&gt;=n&amp;&amp;t&gt;=e}function u(e){return&quot;[object Array]&quot;==Object.prototype.toString.call(e)}function s(e,n,t){for(var r,i,o=[0],u=0,s=e.length;s&gt;u;){for(i=o.length;i--;o[i]*=n);for(o[r=0]+=N.indexOf(e.charAt(u++));r&lt;o.length;r++)o[r]&gt;t-1&amp;&amp;(null==o[r+1]&amp;&amp;(o[r+1]=0),o[r+1]+=o[r]/t|0,o[r]%=t)}return o.reverse()}function f(e,n){return(e.length&gt;1?e.charAt(0)+&quot;.&quot;+e.slice(1):e)+(0&gt;n?&quot;e&quot;:&quot;e+&quot;)+n}function l(e,n){var t,r;if(0&gt;n){for(r=&quot;0.&quot;;++n;r+=&quot;0&quot;);e=r+e}else if(t=e.length,++n&gt;t){for(r=&quot;0&quot;,n-=t;--n;r+=&quot;0&quot;);e+=r}else t&gt;n&amp;&amp;(e=e.slice(0,n)+&quot;.&quot;+e.slice(n));return e}function c(e){return e=parseFloat(e),0&gt;e?p(e):d(e)}var a,h,g=/^-?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,p=Math.ceil,d=Math.floor,m=&quot; not a boolean or binary digit&quot;,w=&quot;rounding mode&quot;,v=&quot;number type has more than 15 significant digits&quot;,N=&quot;0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_&quot;,b=1e14,O=14,y=9007199254740991,S=[1,10,100,1e3,1e4,1e5,1e6,1e7,1e8,1e9,1e10,1e11,1e12,1e13],R=1e7,A=1e9;if(&quot;undefined&quot;!=typeof crypto&amp;&amp;(a=crypto),&quot;function&quot;==typeof define&amp;&amp;define.amd)define(function(){return n()});else if(&quot;undefined&quot;!=typeof module&amp;&amp;module.exports){if(module.exports=n(),!a)try{a=require(&quot;crypto&quot;)}catch(E){}}else e||(e=&quot;undefined&quot;!=typeof self?self:Function(&quot;return this&quot;)()),e.BigNumber=n()}(this);
  &lt;/script&gt;

  &lt;style&gt;
    body{
      font-family: &apos;HelveticaNeue-Light&apos;, &apos;Helvetica Neue Light&apos;, &apos;Helvetica Neue&apos;, &apos;Helvetica&apos;, &apos;Arial&apos;, &apos;Lucida Grande&apos;, sans-serif;
      background: #E2E2E2;
    }
    *, *:after, *:before {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }

    #pleasewait{
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      padding: 0;
      margin: 0;
    }
    #infomessage {
      text-align: center;
      font-size: 1rem;
      margin: 0 2rem 4.5rem;
    }

    .wrapper{
      background: #E2E2E2;
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      padding: 0;
      margin: 0;
      display:none;
      text-align: center;
    }
    .title {
      text-align: center;
      font-size: 1.2rem;
      margin: 1rem 0rem;
    }
    .message {
      text-align: center;
      font-size: 1rem;
      /*margin: 0 2rem 4.5rem;*/
    }

    #passwordField {
      text-align: center;
      font-size: 1rem;
      margin: 1rem 0rem;
      /*margin: 0 2rem 4.5rem;*/
    }

    .wrapper button {
      background: transparent;
      border: none;
      color: #1678E5;
      height: 3rem;
      font-size: 1rem;
      width: 50%;
      position: absolute;
      bottom: 0;
      cursor: pointer;
    }
    #cancel-button {
      border-top: 1px solid #B4B4B4;
      border-right: 1px solid #B4B4B4;
      left: 0;
      border-radius: 0 0 0 10px;
    }
    #confirm-button {
      border-top: 1px solid #B4B4B4;
      right: 0;
      border-radius: 0 0 10px 0;
    }
    .wrapper button:focus,
    .wrapper button:hover {
      font-weight: bold;
      background: #EFEFEF;
    }
    .wrapper button:active {
      background: #D6D6D6;
    }

    .button {
      margin: 1rem 0rem;
      display: inline-block;
      padding: 9px 15px;
      background-color: #3898EC;
      color: white;
      border: 0;
      line-height: inherit;
      text-decoration: none;
      cursor: pointer;
      border-radius: 0;
    }

    input.button {
      -webkit-appearance: button;
    }
  &lt;/style&gt;

  &lt;body&gt;

    &lt;div id=&quot;pleasewait&quot;&gt;
      &lt;br/&gt;
      &lt;p id=&quot;infomessage&quot;&gt;Please wait...&lt;/p&gt;
    &lt;/div&gt;

    &lt;form id=&quot;form&quot; class=&quot;wrapper&quot;&gt;
      &lt;br/&gt;
      &lt;p id=&quot;message&quot; class=&quot;message&quot;&gt;&lt;/p&gt;
      &lt;p id=&quot;passwordField&quot;&gt;&lt;label&gt;Password Required:&lt;/label&gt;&lt;input id=&quot;password&quot; type=&quot;password&quot; /&gt;&lt;/p&gt;
      &lt;button id=&quot;cancel-button&quot; type=&quot;button&quot; autofocus&gt;Cancel&lt;/button&gt;
      &lt;button id=&quot;confirm-button&quot; type=&quot;button&quot; &gt;Confirm&lt;/button&gt;
    &lt;/form&gt;

    &lt;div id=&quot;modal-dialog&quot; class=&quot;wrapper&quot;&gt;
      &lt;h3 id=&quot;modal-dialog-title&quot; class=&quot;title&quot;&gt;Title&lt;/h3&gt;
      &lt;p id=&quot;modal-dialog-message&quot; class=&quot;message&quot;&gt;Message&lt;/p&gt;
      &lt;span id=&quot;modal-dialog-button&quot; class=&quot;button&quot;&gt;Ok&lt;/span&gt;
    &lt;/div&gt;

    &lt;script&gt;
    var noMessageReceivedYet = true;
    var closedByCode = false;
    var pleaseWait = document.getElementById(&quot;pleasewait&quot;);
    var form = document.getElementById(&quot;form&quot;);
    var cancelButton = document.getElementById(&quot;cancel-button&quot;);
    var confirmButton = document.getElementById(&quot;confirm-button&quot;);
    var message = document.getElementById(&quot;message&quot;);
    var infoMessage = document.getElementById(&quot;infomessage&quot;);
    var password = document.getElementById(&quot;password&quot;);
    var passwordField = document.getElementById(&quot;passwordField&quot;);
    var modalDialog = document.getElementById(&quot;modal-dialog&quot;);
    var modalDialogButton = document.getElementById(&quot;modal-dialog-button&quot;);
    var modalDialogTitle = document.getElementById(&quot;modal-dialog-title&quot;);
    var modalDialogMessage = document.getElementById(&quot;modal-dialog-message&quot;);

    var firstUrl = null;

    var inIframe = true;
    var source = null;
    if(window.opener){
      inIframe = false;
      source = window.opener;
    }else if(window.parent != window){
      source = window.parent;
    }else{
      console.log(&quot;closing&quot;);
      window.close();
    }

    function closeWindow(){
      closedByCode = true;
      window.close();
    }

    function showWaiting(text){
      if(!text){
        text = &quot;Please wait...&quot;
      }
      infoMessage.innerHTML = text;
      pleaseWait.style.display = &quot;block&quot;;
      form.style.display = &quot;none&quot;;
    }

    function hideWaiting(){
      pleaseWait.style.display = &quot;none&quot;;
      form.style.display = &quot;block&quot;;

      window.onbeforeunload = null;
    }

    function showMessage(title, message, callback, buttonText){
      modalDialog.style.display = &quot;block&quot;;
      modalDialogTitle.innerHTML = title;
      modalDialogMessage.innerHTML = &quot;&quot;;
      if((typeof message) == &quot;string&quot;){
        modalDialogMessage.innerHTML += message;
      }else{
        modalDialogMessage.appendChild(message);
      }
      modalDialogMessage.appendChild(document.createElement(&apos;br&apos;));

      if(!buttonText){
        buttonText = &quot;Ok&quot;;
      }
      modalDialogButton.innerHTML = buttonText;
      modalDialogButton.onclick = function(){
        modalDialogButton.onclick = null;
        modalDialog.style.display = &quot;none&quot;;
        if(callback){
          callback();
        }
      }
    }

    function hideMessage(){
      modalDialog.style.display = &quot;none&quot;;
      modalDialogButton.onclick = null;
    }

    function sendAsync(url,payload, callback) {
      var request = new XMLHttpRequest();
      request.open(&apos;POST&apos;, url, true);
      request.setRequestHeader(&apos;Content-Type&apos;,&apos;application/json&apos;);

      request.onreadystatechange = function() {
        if (request.readyState === 4) {
          var result = request.responseText;
          var error = null;
          try {
            result = JSON.parse(result);
          } catch(e) {
            var message = !!result &amp;&amp; !!result.error &amp;&amp; !!result.error.message ? result.error.message : &apos;Invalid JSON RPC response: &apos; + JSON.stringify(result);
            error = {message:message,type:&quot;JsonParse&quot;};
          }
          callback(error, result);
        }
      };

      try {
        request.send(JSON.stringify(payload));
      } catch(e) {
        callback({message:&apos;CONNECTION ERROR: Couldn\&apos;t connect to node &apos;+ url +&apos;.&apos;,type:&quot;noConnection&quot;});
      }
    }

    function addBlocky(message, address){
      var icon = blockies.create({
        seed: address,
        size: 8,
        scale: 6
      });
      message.appendChild(icon);
    }

    function askAuthorization(transactionInfo, data, requireUnlock, sourceWindow){


      var value = transactionInfo[&quot;value&quot;] ? transactionInfo.value : &quot;0&quot;;
      var gasProvided = transactionInfo.gas;
      var gasPriceProvided = transactionInfo.gasPrice;
      var gasPrice = new BigNumber(gasPriceProvided,16);
      var gas = new BigNumber(gasProvided,16);
      var weiValue = new BigNumber(value,16);
      var gasWeiValue = gas.times(gasPrice);
      var etherValue = weiValue.dividedBy(new BigNumber(&quot;1000000000000000000&quot;));
      var gasEtherValue = gasWeiValue.dividedBy(new BigNumber(&quot;1000000000000000000&quot;));

      hideWaiting();

      message.innerHTML = &quot;&quot;;

      addBlocky(message,transactionInfo.from);

      var span = document.createElement(&apos;span&apos;);
      span.style=&quot;font-size:3em;&quot;;
      span.innerHTML = &quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot; + &quot;&amp;#x2192;&quot; + &quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;;
      message.appendChild(span);

      addBlocky(message,transactionInfo.to);

      message.appendChild(document.createElement(&apos;br&apos;));
      var textSpan = document.createElement(&quot;span&quot;);
      message.appendChild(textSpan);
      textSpan.innerHTML = etherValue.toFormat() + &quot; ether &lt;br/&gt;  + gas cost (&quot; + gasEtherValue.toFormat() + &quot; ether )&quot;

      if(requireUnlock){
        passwordField.style.display = &quot;block&quot;;
      }else{
        passwordField.style.display = &quot;none&quot;;
      }

      cancelButton.onclick = function(){
        sourceWindow.postMessage({id:data.id,result:null,error:{message:&quot;Not Authorized&quot;},type:&quot;cancel&quot;},firstUrl);
        closeWindow();
      }

      var submitFunc = function(){
        window.onbeforeunload = function (event) {
          if(!closedByCode){
            return &quot;do not close now as a transaction is progress, this cannot be canceled and we wait for an answer&quot;;
          }
        };
        if(requireUnlock){
          if(password.value == &quot;&quot;){
            password.style.border = &quot;2px solid red&quot;;
            return false;
          }
          password.style.border = &quot;none&quot;;
          var params = [transactionInfo.from,password.value,3];
          showWaiting(&quot;Please wait...&lt;br/&gt;Do not close the window.&quot;);
          sendAsync(data.url,{id:999992,method:&quot;personal_unlockAccount&quot;,params:params},function(error,result){
            if(error || result.error){
              showMessage(&quot;Error unlocking account&quot;, &quot;Please retry.&quot;, hideWaiting);
            }else{
              sendAsync(data.url,data.payload,function(error,result){
                sourceWindow.postMessage({id:data.id,result:result,error:error},firstUrl);
                closeWindow();
              });
            }
          });
        }else{
          sendAsync(data.url,data.payload,function(error,result){
            if(result &amp;&amp; result.error){
              processMessage(data,sourceWindow);
            }else{
              sourceWindow.postMessage({id:data.id,result:result,error:error},firstUrl);
              closeWindow();
            }
          });
          showWaiting();
        }
        return false;
      }

      form.onsubmit = submitFunc;
      confirmButton.onclick = submitFunc;
    }

    function needToAndCanUnlockAccount(address,url,callback){
      sendAsync(url,{id:9999990,method:&quot;eth_sign&quot;,params:[address,&quot;0xc6888fa8d57087278718986382264244252f8d57087278718986382264244252f&quot;]},function(error,result){
        if(error || result.error){
          sendAsync(url,{id:9999991,method:&quot;personal_listAccounts&quot;,params:[]},function(error,result){
            if(error || result.error){
              callback(true,false);
            }else{
              callback(true,true);
            }
          });
        }else{
          callback(false);
        }
      });
    }

    function receiveMessage(event){
      if(event.source != source){
        return;
      }
      if(firstUrl){
        if(firstUrl != event.origin){
          return;
        }
      }else{
        firstUrl = event.origin;
      }
      hideMessage();
      noMessageReceivedYet = false;
      var data = event.data;
      try{
        processMessage(data,event.source);
      }catch(e){
        event.source.postMessage({id:data.id,result:null,error:{message:&quot;Could not process message data&quot;},type:&quot;notValid&quot;},firstUrl);
        showMessage(&quot;Error&quot;,&quot;The application has sent invalid data&quot;, function(){
          closeWindow();
        });
      }

    }

    var allowedMethods = [
       &quot;web3_clientVersion&quot;
      ,&quot;web3_sha3&quot;
      ,&quot;net_version&quot;
      ,&quot;net_peerCount&quot;
      ,&quot;net_listening&quot;
      ,&quot;eth_protocolVersion&quot;
      ,&quot;eth_syncing&quot;
      ,&quot;eth_coinbase&quot;
      ,&quot;eth_mining&quot;
      ,&quot;eth_hashrate&quot;
      ,&quot;eth_gasPrice&quot;
      ,&quot;eth_accounts&quot;
      ,&quot;eth_blockNumber&quot;
      ,&quot;eth_getBalance&quot;
      ,&quot;eth_getStorageAt&quot;
      ,&quot;eth_getTransactionCount&quot;
      ,&quot;eth_getBlockTransactionCountByHash&quot;
      ,&quot;eth_getBlockTransactionCountByNumber&quot;
      ,&quot;eth_getUncleCountByBlockHash&quot;
      ,&quot;eth_getUncleCountByBlockNumber&quot;
      ,&quot;eth_getCode&quot;
      ,&quot;eth_sendRawTransaction&quot;
      ,&quot;eth_call&quot;
      ,&quot;eth_estimateGas&quot;
      ,&quot;eth_getBlockByHash&quot;
      ,&quot;eth_getBlockByNumber&quot;
      ,&quot;eth_getTransactionByHash&quot;
      ,&quot;eth_getTransactionByBlockHashAndIndex&quot;
      ,&quot;eth_getTransactionByBlockNumberAndIndex&quot;
      ,&quot;eth_getTransactionReceipt&quot;
      ,&quot;eth_getUncleByBlockHashAndIndex&quot;
      ,&quot;eth_getUncleByBlockNumberAndIndex&quot;
      ,&quot;eth_getCompilers&quot;
      ,&quot;eth_compileLLL&quot;
      ,&quot;eth_compileSolidity&quot;
      ,&quot;eth_compileSerpent&quot;
      ,&quot;eth_newFilter&quot;
      ,&quot;eth_newBlockFilter&quot;
      ,&quot;eth_newPendingTransactionFilter&quot;
      ,&quot;eth_uninstallFilter&quot;
      ,&quot;eth_getFilterChanges&quot;
      ,&quot;eth_getFilterLogs&quot;
      ,&quot;eth_getLogs&quot;
      ,&quot;eth_getWork&quot;
      ,&quot;eth_submitWork&quot;
      ,&quot;eth_submitHashrate&quot;
      // ,&quot;shh_post&quot;
      // ,&quot;shh_version&quot;
      // ,&quot;shh_newIdentity&quot;
      // ,&quot;shh_hasIdentity&quot;
      // ,&quot;shh_newGroup&quot;
      // ,&quot;shh_addToGroup&quot;
      // ,&quot;shh_newFilter&quot;
      // ,&quot;shh_uninstallFilter&quot;
      // ,&quot;shh_getFilterChanges&quot;
      // ,&quot;shh_getMessages&quot;
    ];

    function isMethodAllowed(method){
      return allowedMethods.indexOf(method) != -1;
    }

    function processMessage(data, sourceWindow){

      if(inIframe){
        if(isMethodAllowed(data.payload.method)){
          sendAsync(data.url,data.payload,function(error,result){
            sourceWindow.postMessage({id:data.id,result:result,error:error},firstUrl);
          });
        }else{
          sourceWindow.postMessage({id:data.id,result:null,error:{message:&quot;method (&quot; + data.payload.method + &quot;) not allowed in iframe&quot;},type:&quot;notAllowed&quot;},firstUrl);
        }
      }else if(data.payload.method == &quot;eth_sendTransaction&quot;){
        var transactionInfo = null;
        if(data.payload.params.length &gt; 0){
          if(data.payload.params[0][&quot;gas&quot;] &amp;&amp; data.payload.params[0][&quot;gasPrice&quot;] &amp;&amp; data.payload.params[0][&quot;to&quot;] &amp;&amp; data.payload.params[0][&quot;from&quot;]){
            transactionInfo = data.payload.params[0];
          }
        }
        if(transactionInfo != null){
          needToAndCanUnlockAccount(transactionInfo.from,data.url,function(requireUnlock,canUnlock){
            if(requireUnlock &amp;&amp; canUnlock){
              askAuthorization(transactionInfo,data,true, sourceWindow);
            }else if(!requireUnlock){
              askAuthorization(transactionInfo,data,false,sourceWindow);
            }else if(requireUnlock &amp;&amp; !canUnlock){
              var messageHtml = document.createElement(&apos;span&apos;);
              addBlocky(messageHtml,transactionInfo.from);
              messageHtml.appendChild(document.createElement(&apos;br&apos;));
              var span = document.createElement(&apos;span&apos;);
              span.innerHTML = &quot;You need to unlock your account first : &lt;br/&gt;&quot; + transactionInfo.from;
              messageHtml.appendChild(span);

              showMessage(&quot;Account Locked&quot;,messageHtml,function(){
                processMessage(data,sourceWindow);
              }, &quot;Done&quot;);
            }

          });
        }else{
          sourceWindow.postMessage({id:data.id,result:null,error:{message:&quot;Need to specify from , to, gas and gasPrice&quot;},type:&quot;notValid&quot;},firstUrl);
          closeWindow();
        }
      }else{
        sourceWindow.postMessage({id:data.id,result:null,error:{message:&quot;method (&quot; + data.payload.method + &quot;) not allowed in popup&quot;},type:&quot;notAllowed&quot;},firstUrl);
      }     
    }

    function checkMessageNotReceived(){
      if(noMessageReceivedYet){
        showMessage(&quot;Error&quot;,&quot;No transaction received. Please make sure popup are not blocked.&quot;, function(){
          closeWindow();
        });
      }
    }
    setTimeout(checkMessageNotReceived,1000);

    window.addEventListener(&quot;message&quot;, receiveMessage);
    if(source){
      source.postMessage(&quot;ready&quot;,&quot;*&quot;);
    }

    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;
```

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 05 Jun 2016 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-107</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-107</guid>
      </item>
    
      <item>
        <title>Ethereum Domain Name Service - Specification</title>
        <category>Standards Track/ERC</category>
        
        <description># Abstract

This draft EIP describes the details of the Ethereum Name Service, a proposed protocol and ABI definition that provides flexible resolution of short, human-readable names to service and resource identifiers. This permits users and developers to refer to human-readable and easy to remember names, and permits those names to be updated as necessary when the underlying resource (contract, content-addressed data, etc) changes.

The goal of domain names is to provide stable, human-readable identifiers that can be used to specify network resources. In this way, users can enter a memorable string, such as &apos;vitalik.wallet&apos; or &apos;www.mysite.swarm&apos;, and be directed to the appropriate resource. The mapping between names and resources may change over time, so a user may change wallets, a website may change hosts, or a swarm document may be updated to a new version, without the domain name changing. Further, a domain need not specify a single resource; different record types allow the same domain to reference different resources. For instance, a browser may resolve &apos;mysite.swarm&apos; to the IP address of its server by fetching its A (address) record, while a mail client may resolve the same address to a mail server by fetching its MX (mail exchanger) record.
# Motivation

Existing [specifications](https://github.com/ethereum/wiki/wiki/Registrar-ABI) and [implementations](https://ethereum.gitbooks.io/frontier-guide/content/registrar_services.html) for name resolution in Ethereum provide basic functionality, but suffer several shortcomings that will significantly limit their long-term usefulness:
- A single global namespace for all names with a single &apos;centralised&apos; resolver.
- Limited or no support for delegation and sub-names/sub-domains.
- Only one record type, and no support for associating multiple copies of a record with a domain.
- Due to a single global implementation, no support for multiple different name allocation systems.
- Conflation of responsibilities: Name resolution, registration, and whois information.

Use-cases that these features would permit include:
- Support for subnames/sub-domains - eg, live.mysite.tld and forum.mysite.tld.
- Multiple services under a single name, such as a DApp hosted in Swarm, a Whisper address, and a mail server.
- Support for DNS record types, allowing blockchain hosting of &apos;legacy&apos; names. This would permit an Ethereum client such as Mist to resolve the address of a traditional website, or the mail server for an email address, from a blockchain name.
- DNS gateways, exposing ENS domains via the Domain Name Service, providing easier means for legacy clients to resolve and connect to blockchain services.

The first two use-cases, in particular, can be observed everywhere on the present-day internet under DNS, and we believe them to be fundamental features of a name service that will continue to be useful as the Ethereum platform develops and matures.

The normative parts of this document does not specify an implementation of the proposed system; its purpose is to document a protocol that different resolver implementations can adhere to in order to facilitate consistent name resolution. An appendix provides sample implementations of resolver contracts and libraries, which should be treated as illustrative examples only.

Likewise, this document does not attempt to specify how domains should be registered or updated, or how systems can find the owner responsible for a given domain. Registration is the responsibility of registrars, and is a governance matter that will necessarily vary between top-level domains.

Updating of domain records can also be handled separately from resolution. Some systems, such as swarm, may require a well defined interface for updating domains, in which event we anticipate the development of a standard for this.
# Specification
## Overview

The ENS system comprises three main parts:
- The ENS registry
- Resolvers
- Registrars

The registry is a single contract that provides a mapping from any registered name to the resolver responsible for it, and permits the owner of a name to set the resolver address, and to create subdomains, potentially with different owners to the parent domain.

Resolvers are responsible for performing resource lookups for a name - for instance, returning a contract address, a content hash, or IP address(es) as appropriate. The resolver specification, defined here and extended in other EIPs, defines what methods a resolver may implement to support resolving different types of records.

Registrars are responsible for allocating domain names to users of the system, and are the only entities capable of updating the ENS; the owner of a node in the ENS registry is its registrar. Registrars may be contracts or externally owned accounts, though it is expected that the root and top-level registrars, at a minimum, will be implemented as contracts.

Resolving a name in ENS is a two-step process. First, the ENS registry is called with the name to resolve, after hashing it using the procedure described below. If the record exists, the registry returns the address of its resolver. Then, the resolver is called, using the method appropriate to the resource being requested. The resolver then returns the desired result.

For example, suppose you wish to find the address of the token contract associated with &apos;beercoin.eth&apos;. First, get the resolver:

```javascript
var node = namehash(&quot;beercoin.eth&quot;);
var resolver = ens.resolver(node);
```

Then, ask the resolver for the address for the contract:

```javascript
var address = resolver.addr(node);
```

Because the `namehash` procedure depends only on the name itself, this can be precomputed and inserted into a contract, removing the need for string manipulation, and permitting O(1) lookup of ENS records regardless of the number of components in the raw name.
## Name Syntax

ENS names must conform to the following syntax:

&lt;pre&gt;&amp;lt;domain&gt; ::= &amp;lt;label&gt; | &amp;lt;domain&gt; &quot;.&quot; &amp;lt;label&gt;
&amp;lt;label&gt; ::= any valid string label per [UTS46](https://unicode.org/reports/tr46/)
&lt;/pre&gt;

In short, names consist of a series of dot-separated labels. Each label must be a valid normalised label as described in [UTS46](https://unicode.org/reports/tr46/) with the options `transitional=false` and `useSTD3AsciiRules=true`. For Javascript implementations, a [library](https://www.npmjs.com/package/idna-uts46) is available that normalises and checks names.

Note that while upper and lower case letters are allowed in names, the UTS46 normalisation process case-folds labels before hashing them, so two names with different case but identical spelling will produce the same namehash.

Labels and domains may be of any length, but for compatibility with legacy DNS, it is recommended that labels be restricted to no more than 64 characters each, and complete ENS names to no more than 255 characters. For the same reason, it is recommended that labels do not start or end with hyphens, or start with digits.

## namehash algorithm

Before being used in ENS, names are hashed using the &apos;namehash&apos; algorithm. This algorithm recursively hashes components of the name, producing a unique, fixed-length string for any valid input domain. The output of namehash is referred to as a &apos;node&apos;.

Pseudocode for the namehash algorithm is as follows:

```
def namehash(name):
  if name == &apos;&apos;:
    return &apos;\0&apos; * 32
  else:
    label, _, remainder = name.partition(&apos;.&apos;)
    return sha3(namehash(remainder) + sha3(label))
```

Informally, the name is split into labels, each label is hashed. Then, starting with the last component, the previous output is concatenated with the label hash and hashed again. The first component is concatenated with 32 &apos;0&apos; bytes. Thus, &apos;mysite.swarm&apos; is processed as follows:

```
node = &apos;\0&apos; * 32
node = sha3(node + sha3(&apos;swarm&apos;))
node = sha3(node + sha3(&apos;mysite&apos;))
```

Implementations should conform to the following test vectors for namehash:

    namehash(&apos;&apos;) = 0x0000000000000000000000000000000000000000000000000000000000000000
    namehash(&apos;eth&apos;) = 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae
    namehash(&apos;foo.eth&apos;) = 0xde9b09fd7c5f901e23a3f19fecc54828e9c848539801e86591bd9801b019f84f

## Registry specification

The ENS registry contract exposes the following functions:

```solidity
function owner(bytes32 node) constant returns (address);
```

Returns the owner (registrar) of the specified node.

```solidity
function resolver(bytes32 node) constant returns (address);
```

Returns the resolver for the specified node.

```solidity
function ttl(bytes32 node) constant returns (uint64);
```

Returns the time-to-live (TTL) of the node; that is, the maximum duration for which a node&apos;s information may be cached.

```solidity
function setOwner(bytes32 node, address owner);
```

Transfers ownership of a node to another registrar. This function may only be called by the current owner of `node`. A successful call to this function logs the event `Transfer(bytes32 indexed, address)`.

```solidity
function setSubnodeOwner(bytes32 node, bytes32 label, address owner);
```

Creates a new node, `sha3(node, label)` and sets its owner to `owner`, or updates the node with a new owner if it already exists. This function may only be called by the current owner of `node`. A successful call to this function logs the event `NewOwner(bytes32 indexed, bytes32 indexed, address)`.

```solidity
function setResolver(bytes32 node, address resolver);
```

Sets the resolver address for `node`. This function may only be called by the owner of `node`. A successful call to this function logs the event `NewResolver(bytes32 indexed, address)`.

```solidity
function setTTL(bytes32 node, uint64 ttl);
```

Sets the TTL for a node. A node&apos;s TTL applies to the &apos;owner&apos; and &apos;resolver&apos; records in the registry, as well as to any information returned by the associated resolver.
## Resolver specification

Resolvers may implement any subset of the record types specified here. Where a record types specification requires a resolver to provide multiple functions, the resolver MUST implement either all or none of them. Resolvers MUST specify a fallback function that throws.

Resolvers have one mandatory function:

```solidity
function supportsInterface(bytes4 interfaceID) constant returns (bool)
```

The `supportsInterface` function is documented in [EIP-165](/EIPs/EIPS/eip-165), and returns true if the resolver implements the interface specified by the provided 4 byte identifier. An interface identifier consists of the XOR of the function signature hashes of the functions provided by that interface; in the degenerate case of single-function interfaces, it is simply equal to the signature hash of that function. If a resolver returns `true` for `supportsInterface()`, it must implement the functions specified in that interface.

`supportsInterface` must always return true for `0x01ffc9a7`, which is the interface ID of `supportsInterface` itself.

 Currently standardised resolver interfaces are specified in the table below.

The following interfaces are defined:

| Interface name | Interface hash | Specification |
| --- | --- | --- |
| `addr` | 0x3b3b57de | [Contract address](#addr) |
| `name`      | 0x691f3431   | #181    |
| `ABI`       | 0x2203ab56   | #205    |
| `pubkey`    | 0xc8690233   | #619    |

EIPs may define new interfaces to be added to this registry.

### &lt;a name=&quot;addr&quot;&gt;&lt;/a&gt;Contract Address Interface

Resolvers wishing to support contract address resources must provide the following function:

```solidity
function addr(bytes32 node) constant returns (address);
```

If the resolver supports `addr` lookups but the requested node does not have an addr record, the resolver MUST return the zero address.

Clients resolving the `addr` record MUST check for a zero return value, and treat this in the same manner as a name that does not have a resolver specified - that is, refuse to send funds to or interact with the address. Failure to do this can result in users accidentally sending funds to the 0 address.

Changes to an address MUST trigger the following event:

```solidity
event AddrChanged(bytes32 indexed node, address a);
```
# Appendix A: Registry Implementation

```solidity
contract ENS {
    struct Record {
        address owner;
        address resolver;
        uint64 ttl;
    }

    mapping(bytes32=&gt;Record) records;

    event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);
    event Transfer(bytes32 indexed node, address owner);
    event NewResolver(bytes32 indexed node, address resolver);

    modifier only_owner(bytes32 node) {
        if(records[node].owner != msg.sender) throw;
        _
    }

    function ENS(address owner) {
        records[0].owner = owner;
    }

    function owner(bytes32 node) constant returns (address) {
        return records[node].owner;
    }

    function resolver(bytes32 node) constant returns (address) {
        return records[node].resolver;
    }

    function ttl(bytes32 node) constant returns (uint64) {
        return records[node].ttl;
    }

    function setOwner(bytes32 node, address owner) only_owner(node) {
        Transfer(node, owner);
        records[node].owner = owner;
    }

    function setSubnodeOwner(bytes32 node, bytes32 label, address owner) only_owner(node) {
        var subnode = sha3(node, label);
        NewOwner(node, label, owner);
        records[subnode].owner = owner;
    }

    function setResolver(bytes32 node, address resolver) only_owner(node) {
        NewResolver(node, resolver);
        records[node].resolver = resolver;
    }

    function setTTL(bytes32 node, uint64 ttl) only_owner(node) {
        NewTTL(node, ttl);
        records[node].ttl = ttl;
    }
}
```
# Appendix B: Sample Resolver Implementations
### Built-in resolver

The simplest possible resolver is a contract that acts as its own name resolver by implementing the contract address resource profile:

```solidity
contract DoSomethingUseful {
    // Other code

    function addr(bytes32 node) constant returns (address) {
        return this;
    }

    function supportsInterface(bytes4 interfaceID) constant returns (bool) {
        return interfaceID == 0x3b3b57de || interfaceID == 0x01ffc9a7;
    }

    function() {
        throw;
    }
}
```

Such a contract can be inserted directly into the ENS registry, eliminating the need for a separate resolver contract in simple use-cases. However, the requirement to &apos;throw&apos; on unknown function calls may interfere with normal operation of some types of contract.

### Standalone resolver

A basic resolver that implements the contract address profile, and allows only its owner to update records:

```solidity
contract Resolver {
    event AddrChanged(bytes32 indexed node, address a);

    address owner;
    mapping(bytes32=&gt;address) addresses;

    modifier only_owner() {
        if(msg.sender != owner) throw;
        _
    }

    function Resolver() {
        owner = msg.sender;
    }

    function addr(bytes32 node) constant returns(address) {
        return addresses[node];    
    }

    function setAddr(bytes32 node, address addr) only_owner {
        addresses[node] = addr;
        AddrChanged(node, addr);
    }

    function supportsInterface(bytes4 interfaceID) constant returns (bool) {
        return interfaceID == 0x3b3b57de || interfaceID == 0x01ffc9a7;
    }

    function() {
        throw;
    }
}
```

After deploying this contract, use it by updating the ENS registry to reference this contract for a name, then calling `setAddr()` with the same node to set the contract address it will resolve to.
### Public resolver

Similar to the resolver above, this contract only supports the contract address profile, but uses the ENS registry to determine who should be allowed to update entries:

```solidity
contract PublicResolver {
    event AddrChanged(bytes32 indexed node, address a);
    event ContentChanged(bytes32 indexed node, bytes32 hash);

    ENS ens;
    mapping(bytes32=&gt;address) addresses;

    modifier only_owner(bytes32 node) {
        if(ens.owner(node) != msg.sender) throw;
        _
    }

    function PublicResolver(address ensAddr) {
        ens = ENS(ensAddr);
    }

    function addr(bytes32 node) constant returns (address ret) {
        ret = addresses[node];
    }

    function setAddr(bytes32 node, address addr) only_owner(node) {
        addresses[node] = addr;
        AddrChanged(node, addr);
    }

    function supportsInterface(bytes4 interfaceID) constant returns (bool) {
        return interfaceID == 0x3b3b57de || interfaceID == 0x01ffc9a7;
    }

    function() {
        throw;
    }
}
```
# Appendix C: Sample Registrar Implementation

This registrar allows users to register names at no cost if they are the first to request them.

```solidity
contract FIFSRegistrar {
    ENS ens;
    bytes32 rootNode;

    function FIFSRegistrar(address ensAddr, bytes32 node) {
        ens = ENS(ensAddr);
        rootNode = node;
    }

    function register(bytes32 subnode, address owner) {
        var node = sha3(rootNode, subnode);
        var currentOwner = ens.owner(node);
        if(currentOwner != 0 &amp;&amp; currentOwner != msg.sender)
            throw;

        ens.setSubnodeOwner(rootNode, subnode, owner);
    }
}
```
</description>
        <pubDate>Mon, 04 Apr 2016 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-137</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-137</guid>
      </item>
    
      <item>
        <title>REVERT instruction</title>
        <category>Standards Track/Core</category>
        
        <description>## Simple Summary

The `REVERT` instruction provides a way to stop execution and revert state changes, without consuming all provided gas and with the ability to return a reason.

## Abstract

The `REVERT` instruction will stop execution, roll back all state changes done so far and provide a pointer to a memory section, which can be interpreted as an error code or message. While doing so, it will not consume all the remaining gas.

## Motivation

Currently this is not possible. There are two practical ways to revert a transaction from within a contract: running out of gas or executing an invalid instruction. Both of these options will consume all remaining gas. Additionally, reverting an EVM execution means that all changes, including LOGs, are lost and there is no way to convey a reason for aborting an EVM execution.

## Specification

On blocks with `block.number &gt;= BYZANTIUM_FORK_BLKNUM`, the `REVERT` instruction is introduced at `0xfd`. It expects two stack items, the top item is the `memory_offset` followed by `memory_length`. It does not produce any stack elements because it stops execution.

The semantics of `REVERT` with respect to memory and memory cost are identical to those of `RETURN`. The sequence of bytes given by `memory_offset` and `memory_length` is called &quot;error message&quot; in the following.

The effect of `REVERT` is that execution is aborted, considered as failed, and state changes are rolled back. The error message will be available to the caller in the returndata buffer and will also be copied to the output area, i.e. it is handled in the same way as the regular return data is handled.

The cost of the `REVERT` instruction equals to that of the `RETURN` instruction, i.e. the rollback itself does not consume all gas, the contract only has to pay for memory.

In case there is not enough gas left to cover the cost of `REVERT` or there is a stack underflow, the effect of the `REVERT` instruction will equal to that of a regular out of gas exception, i.e. it will consume all gas.

In the same way as all other failures, the calling opcode returns `0` on the stack following a `REVERT` opcode in the callee.

In case `REVERT` is used in the context of a `CREATE` or `CREATE2` call, no code is deployed, `0` is put on the stack and the error message is available in the returndata buffer.

The content of the optionally provided memory section is not defined by this EIP, but is a candidate for another Informational EIP.

## Backwards Compatibility

This change has no effect on contracts created in the past unless they contain `0xfd` as an instruction.

## Test Cases

```
6c726576657274656420646174616000557f726576657274206d657373616765000000000000000000000000000000000000600052600e6000fd
```

should:
- return `0x726576657274206d657373616765` as `REVERT` data,
- the storage at key `0x0` should be left as unset and
- use 20024 gas in total.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 06 Feb 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-140</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-140</guid>
      </item>
    
      <item>
        <title>Designated invalid EVM instruction</title>
        <category>Standards Track/Core</category>
        
        <description>## Abstract

An instruction is designated to remain as an invalid instruction.

## Motivation

The invalid instruction can be used as a distinct reason to abort execution.

## Specification

The opcode `0xfe` is the `INVALID` instruction. It can be used to abort the execution (i.e. duplicates as an `ABORT` instruction).

## Backwards Compatibility

This instruction was never used and therefore has no effect on past contracts.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 09 Feb 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-141</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-141</guid>
      </item>
    
      <item>
        <title>Bitwise shifting instructions in EVM</title>
        <category>Standards Track/Core</category>
        
        <description>## Abstract

Native bitwise shifting instructions are introduced, which are more efficient processing wise on the host and are cheaper to use by a contract.

## Motivation

EVM is lacking bitwise shifting operators, but supports other logical and arithmetic operators. Shift operations can be implemented via arithmetic operators, but that has a higher cost and requires more processing time from the host. Implementing `SHL` and `SHR` using arithmetic cost each 35 gas, while the proposed instructions take 3 gas.

## Specification

The following instructions are introduced:

### `0x1b`: `SHL` (shift left)

The `SHL` instruction (shift left) pops 2 values from the stack, first `arg1` and then `arg2`, and pushes on the stack `arg2` shifted to the left by `arg1` number of bits. The result is equal to

```
(arg2 * 2^arg1) mod 2^256
```

Notes:

- The value (`arg2`) is interpreted as an unsigned number.
- The shift amount (`arg1`) is interpreted as an unsigned number.
- If the shift amount (`arg1`) is greater or equal 256 the result is 0.
- This is equivalent to `PUSH1 2 EXP MUL`.

### `0x1c`: `SHR` (logical shift right)

The `SHR` instruction (logical shift right) pops 2 values from the stack, first `arg1` and then `arg2`, and pushes on the stack `arg2` shifted to the right by `arg1` number of bits with zero fill. The result is equal to

```
floor(arg2 / 2^arg1)
```

Notes:

- The value (`arg2`) is interpreted as an unsigned number.
- The shift amount (`arg1`) is interpreted as an unsigned number.
- If the shift amount (`arg1`) is greater or equal 256 the result is 0.
- This is equivalent to `PUSH1 2 EXP DIV`.

### `0x1d`: `SAR` (arithmetic shift right)

The `SAR` instruction (arithmetic shift right) pops 2 values from the stack, first `arg1` and then `arg2`, and pushes on the stack `arg2` shifted to the right by `arg1` number of bits with sign extension. The result is equal to

```
floor(arg2 / 2^arg1)
```

Notes:

- The value (`arg2`) is interpreted as a signed number.
- The shift amount (`arg1`) is interpreted as an unsigned number.
- If the shift amount (`arg1`) is greater or equal 256 the result is 0 if `arg2` is non-negative or -1 if `arg2` is negative.
- This is **not** equivalent to `PUSH1 2 EXP SDIV`, since it rounds differently. See `SDIV(-1, 2) == 0`, while `SAR(-1, 1) == -1`.

The cost of the shift instructions is set at `verylow` tier (3 gas).

## Rationale

Instruction operands were chosen to fit the more natural use case of shifting a value already on the stack. This means the operand order is swapped compared to most arithmetic instructions.

## Backwards Compatibility

The newly introduced instructions have no effect on bytecode created in the past.

## Test Cases

### `SHL` (shift left)

1. ```
   PUSH 0x0000000000000000000000000000000000000000000000000000000000000001
   PUSH 0x00
   SHL
   ---
   0x0000000000000000000000000000000000000000000000000000000000000001
   ```
   
2. ```
   PUSH 0x0000000000000000000000000000000000000000000000000000000000000001
   PUSH 0x01
   SHL
   ---
   0x0000000000000000000000000000000000000000000000000000000000000002
   ```
   
3. ```
   PUSH 0x0000000000000000000000000000000000000000000000000000000000000001
   PUSH 0xff
   SHL
   ---
   0x8000000000000000000000000000000000000000000000000000000000000000
   ```
   
4. ```
   PUSH 0x0000000000000000000000000000000000000000000000000000000000000001
   PUSH 0x0100
   SHL
   ---
   0x0000000000000000000000000000000000000000000000000000000000000000
   ```
   
5. ```
   PUSH 0x0000000000000000000000000000000000000000000000000000000000000001
   PUSH 0x0101
   SHL
   ---
   0x0000000000000000000000000000000000000000000000000000000000000000
   ```
   
6. ```
   PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
   PUSH 0x00
   SHL
   ---
   0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
   ```
   
7. ```
   PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
   PUSH 0x01
   SHL
   ---
   0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
   ```
   
8. ```
   PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
   PUSH 0xff
   SHL
   ---
   0x8000000000000000000000000000000000000000000000000000000000000000
   ```
   
9. ```
   PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
   PUSH 0x0100
   SHL
   ---
   0x0000000000000000000000000000000000000000000000000000000000000000
   ```
   
10. ```
    PUSH 0x0000000000000000000000000000000000000000000000000000000000000000
    PUSH 0x01
    SHL
    ---
    0x0000000000000000000000000000000000000000000000000000000000000000
    ```
    
11. ```
    PUSH 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
    PUSH 0x01
    SHL
    ---
    0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
    ```

### `SHR` (logical shift right)

1. ```
   PUSH 0x0000000000000000000000000000000000000000000000000000000000000001
   PUSH 0x00
   SHR
   ---
   0x0000000000000000000000000000000000000000000000000000000000000001
   ```
   
2. ```
   PUSH 0x0000000000000000000000000000000000000000000000000000000000000001
   PUSH 0x01
   SHR
   ---
   0x0000000000000000000000000000000000000000000000000000000000000000
   ```
   
3. ```
   PUSH 0x8000000000000000000000000000000000000000000000000000000000000000
   PUSH 0x01
   SHR
   ---
   0x4000000000000000000000000000000000000000000000000000000000000000
   ```
   
4. ```
   PUSH 0x8000000000000000000000000000000000000000000000000000000000000000
   PUSH 0xff
   SHR
   ---
   0x0000000000000000000000000000000000000000000000000000000000000001
   ```
   
5. ```
   PUSH 0x8000000000000000000000000000000000000000000000000000000000000000
   PUSH 0x0100
   SHR
   ---
   0x0000000000000000000000000000000000000000000000000000000000000000
   ```
   
6. ```
   PUSH 0x8000000000000000000000000000000000000000000000000000000000000000
   PUSH 0x0101
   SHR
   ---
   0x0000000000000000000000000000000000000000000000000000000000000000
   ```
   
7. ```
   PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
   PUSH 0x00
   SHR
   ---
   0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
   ```
   
8. ```
   PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
   PUSH 0x01
   SHR
   ---
   0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
   ```
   
9. ```
   PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
   PUSH 0xff
   SHR
   ---
   0x0000000000000000000000000000000000000000000000000000000000000001
   ```
   
10. ```
    PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
    PUSH 0x0100
    SHR
    ---
    0x0000000000000000000000000000000000000000000000000000000000000000
    ```
    
11. ```
    PUSH 0x0000000000000000000000000000000000000000000000000000000000000000
    PUSH 0x01
    SHR
    ---
    0x0000000000000000000000000000000000000000000000000000000000000000
    ```

### `SAR` (arithmetic shift right)

1. ```
   PUSH 0x0000000000000000000000000000000000000000000000000000000000000001
   PUSH 0x00
   SAR
   ---
   0x0000000000000000000000000000000000000000000000000000000000000001
   ```
   
2. ```
   PUSH 0x0000000000000000000000000000000000000000000000000000000000000001
   PUSH 0x01
   SAR
   ---
   0x0000000000000000000000000000000000000000000000000000000000000000
   ```
   
3. ```
   PUSH 0x8000000000000000000000000000000000000000000000000000000000000000
   PUSH 0x01
   SAR
   ---
   0xc000000000000000000000000000000000000000000000000000000000000000
   ```
   
4. ```
   PUSH 0x8000000000000000000000000000000000000000000000000000000000000000
   PUSH 0xff
   SAR
   ---
   0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
   ```
   
5. ```
   PUSH 0x8000000000000000000000000000000000000000000000000000000000000000
   PUSH 0x0100
   SAR
   ---
   0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
   ```
   
6. ```
   PUSH 0x8000000000000000000000000000000000000000000000000000000000000000
   PUSH 0x0101
   SAR
   ---
   0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
   ```
   
7. ```
   PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
   PUSH 0x00
   SAR
   ---
   0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
   ```
   
8. ```
   PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
   PUSH 0x01
   SAR
   ---
   0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
   ```
   
9. ```
   PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
   PUSH 0xff
   SAR
   ---
   0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
   ```
   
10. ```
    PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
    PUSH 0x0100
    SAR
    ---
    0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
    ```
    
11. ```
    PUSH 0x0000000000000000000000000000000000000000000000000000000000000000
    PUSH 0x01
    SAR
    ---
    0x0000000000000000000000000000000000000000000000000000000000000000
    ```
    
12. ```
    PUSH 0x4000000000000000000000000000000000000000000000000000000000000000
    PUSH 0xfe
    SAR
    ---
    0x0000000000000000000000000000000000000000000000000000000000000001
    ```
    
13. ```
    PUSH 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
    PUSH 0xf8
    SAR
    ---
    0x000000000000000000000000000000000000000000000000000000000000007f
    ```
    
14. ```
    PUSH 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
    PUSH 0xfe
    SAR
    ---
    0x0000000000000000000000000000000000000000000000000000000000000001
    ```
    
15. ```
    PUSH 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
    PUSH 0xff
    SAR
    ---
    0x0000000000000000000000000000000000000000000000000000000000000000
    ```
    
16. ```
    PUSH 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
    PUSH 0x0100
    SAR
    ---
    0x0000000000000000000000000000000000000000000000000000000000000000
    ```
    
### Implementation

Client support:

- cpp-ethereum: https://github.com/ethereum/cpp-ethereum/pull/4054

Compiler support:

- Solidity/LLL: https://github.com/ethereum/solidity/pull/2541

### Tests

Sources:

- https://github.com/ethereum/tests/tree/develop/src/GeneralStateTestsFiller/stShift

Filled Tests:

- https://github.com/ethereum/tests/tree/develop/GeneralStateTests/stShift
- https://github.com/ethereum/tests/tree/develop/BlockchainTests/GeneralStateTests/stShift

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 13 Feb 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-145</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-145</guid>
      </item>
    
      <item>
        <title>Gas cost changes for IO-heavy operations</title>
        <category>Standards Track/Core</category>
        
        <description>### Meta reference

[Tangerine Whistle](/EIPs/EIPS/eip-608).

### Parameters

|   FORK_BLKNUM   |  CHAIN_ID  | CHAIN_NAME  |
|-----------------|------------|-------------|
|    2,463,000    |     1      | Main net    |

### Specification

If `block.number &gt;= FORK_BLKNUM`, then:
- Increase the gas cost of EXTCODESIZE to 700 (from 20).
- Increase the base gas cost of EXTCODECOPY to 700 (from 20).
- Increase the gas cost of BALANCE to 400 (from 20).
- Increase the gas cost of SLOAD to 200 (from 50).
- Increase the gas cost of CALL, DELEGATECALL, CALLCODE to 700 (from 40).
- Increase the gas cost of SELFDESTRUCT to 5000 (from 0).
- If SELFDESTRUCT hits a newly created account, it triggers an additional gas cost of 25000 (similar to CALLs).
- Increase the recommended gas limit target to 5.5 million.
- Define &quot;all but one 64th&quot; of `N` as `N - floor(N / 64)`.
- If a call asks for more gas than the maximum allowed amount (i.e. the total amount of gas remaining in the parent after subtracting the gas cost of the call and memory expansion), do not return an OOG error; instead, if a call asks for more gas than all but one 64th of the maximum allowed amount, call with all but one 64th of the maximum allowed amount of gas (this is equivalent to a version of EIP-90&lt;sup&gt;[1](https://github.com/ethereum/EIPs/issues/90)&lt;/sup&gt; plus EIP-114&lt;sup&gt;[2](https://github.com/ethereum/EIPs/issues/114)&lt;/sup&gt;). CREATE only provides all but one 64th of the parent gas to the child call.

That is, substitute:

```
        extra_gas = (not ext.account_exists(to)) * opcodes.GCALLNEWACCOUNT + \
            (value &gt; 0) * opcodes.GCALLVALUETRANSFER
        if compustate.gas &lt; gas + extra_gas:
            return vm_exception(&apos;OUT OF GAS&apos;, needed=gas+extra_gas)
        submsg_gas = gas + opcodes.GSTIPEND * (value &gt; 0)
```

With:

```
        def max_call_gas(gas):
          return gas - (gas // 64)

        extra_gas = (not ext.account_exists(to)) * opcodes.GCALLNEWACCOUNT + \
            (value &gt; 0) * opcodes.GCALLVALUETRANSFER
        if compustate.gas &lt; extra_gas:
            return vm_exception(&apos;OUT OF GAS&apos;, needed=extra_gas)
        if compustate.gas &lt; gas + extra_gas:
            gas = min(gas, max_call_gas(compustate.gas - extra_gas))
        submsg_gas = gas + opcodes.GSTIPEND * (value &gt; 0)
```

### Rationale

Recent denial-of-service attacks have shown that opcodes that read the state tree are under-priced relative to other opcodes. There are software changes that have been made, are being made and can be made in order to mitigate the situation; however, the fact will remain that such opcodes will be by a substantial margin the easiest known mechanism to degrade network performance via transaction spam. The concern arises because it takes a long time to read from disk, and is additionally a risk to future sharding proposals as the &quot;attack transactions&quot; that have so far been most successful in degrading network performance would also require tens of megabytes to provide Merkle proofs for. This EIP increases the cost of storage reading opcodes to address this concern. The costs have been derived from an updated version of the calculation table used to generate the 1.0 gas costs: https://docs.google.com/spreadsheets/d/15wghZr-Z6sRSMdmRmhls9dVXTOpxKy8Y64oy9MvDZEQ/edit#gid=0; the rules attempt to target a limit of 8 MB of data that needs to be read in order to process a block, and include an estimate of 500 bytes for a Merkle proof for SLOAD and 1000 for an account.

This EIP aims to be simple, and adds a flat penalty of 300 gas on top of the costs calculated in this table to account for the cost of loading the code (~17–21 kb in the worst case).

The EIP 90 gas mechanic is introduced because without it, all current contracts that make calls would stop working as they use an expression like `msg.gas - 40` to determine how much gas to make a call with, relying on the gas cost of calls being 40. Additionally, EIP 114 is introduced because, given that we are making the cost of a call higher and less predictable, we have an opportunity to do it at no extra cost to currently available guarantees, and so we also achieve the benefit of replacing the call stack depth limit with a &quot;softer&quot; gas-based restriction, thereby eliminating call stack depth attacks as a class of attack that contract developers have to worry about and hence increasing contract programming safety. Note that with the given parameters, the de-facto maximum call stack depth is limited to ~340 (down from ~1024), mitigating the harm caused by any further potential quadratic-complexity DoS attacks that rely on calls.

The gas limit increase is recommended so as to preserve the de-facto transactions-per-second processing capability of the system for average contracts.

## References

1. EIP-90, https://github.com/ethereum/EIPs/issues/90
2. EIP-114, https://github.com/ethereum/EIPs/issues/114
</description>
        <pubDate>Sat, 24 Sep 2016 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-150</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-150</guid>
      </item>
    
      <item>
        <title>Add BLAKE2 compression function `F` precompile</title>
        <category>Standards Track/Core</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/152</comments>
        
        <description>## Simple Summary

This EIP will enable the BLAKE2b hash function and other higher-round 64-bit BLAKE2 variants to run cheaply on the EVM, allowing easier interoperability between Ethereum and Zcash as well as other Equihash-based PoW coins.

## Abstract

This EIP introduces a new precompiled contract which implements the compression function `F` used in the BLAKE2 cryptographic hashing algorithm, for the purpose of allowing interoperability between the EVM and Zcash, as well as introducing more flexible cryptographic hash primitives to the EVM.

## Motivation

Besides being a useful cryptographic hash function and SHA3 finalist, BLAKE2 allows for efficient verification of the Equihash PoW used in Zcash, making a BTC Relay - style SPV client possible on Ethereum. A single verification of an Equihash PoW verification requires 512 iterations of the hash function, making verification of Zcash block headers prohibitively expensive if a Solidity implementation of BLAKE2 is used.

BLAKE2b, the common 64-bit BLAKE2 variant, is highly optimized and faster than MD5 on modern processors.

Interoperability with Zcash could enable contracts like trustless atomic swaps between the chains, which could provide a much needed aspect of privacy to the very public Ethereum blockchain.

## Specification

We propose adding a precompiled contract at address `0x09` wrapping the [BLAKE2 `F` compression function](https://tools.ietf.org/html/rfc7693#section-3.2).

The precompile requires 6 inputs tightly encoded, taking exactly 213 bytes, as explained below. The encoded inputs are corresponding to the ones specified in the [BLAKE2 RFC Section 3.2](https://tools.ietf.org/html/rfc7693#section-3.2):

- `rounds` - the number of rounds - 32-bit unsigned big-endian word
- `h` - the state vector - 8 unsigned 64-bit little-endian words
- `m` - the message block vector - 16 unsigned 64-bit little-endian words
- `t_0, t_1` - offset counters - 2 unsigned 64-bit little-endian words
- `f` - the final block indicator flag - 8-bit word

```
[4 bytes for rounds][64 bytes for h][128 bytes for m][8 bytes for t_0][8 bytes for t_1][1 byte for f]
```

The boolean `f` parameter is considered as `true` if set to `1`.
The boolean `f` parameter is considered as `false` if set to `0`.
All other values yield an invalid encoding of `f` error.

The precompile should compute the `F` function as [specified in the RFC](https://tools.ietf.org/html/rfc7693#section-3.2) and return the updated state vector `h` with unchanged encoding (little-endian).

### Example Usage in Solidity

The precompile can be wrapped easily in Solidity to provide a more development-friendly interface to `F`.

```solidity
function F(uint32 rounds, bytes32[2] memory h, bytes32[4] memory m, bytes8[2] memory t, bool f) public view returns (bytes32[2] memory) {
  bytes32[2] memory output;

  bytes memory args = abi.encodePacked(rounds, h[0], h[1], m[0], m[1], m[2], m[3], t[0], t[1], f);

  assembly {
    if iszero(staticcall(not(0), 0x09, add(args, 32), 0xd5, output, 0x40)) {
      revert(0, 0)
    }
  }

  return output;
}

function callF() public view returns (bytes32[2] memory) {
  uint32 rounds = 12;

  bytes32[2] memory h;
  h[0] = hex&quot;48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5&quot;;
  h[1] = hex&quot;d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b&quot;;

  bytes32[4] memory m;
  m[0] = hex&quot;6162630000000000000000000000000000000000000000000000000000000000&quot;;
  m[1] = hex&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;;
  m[2] = hex&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;;
  m[3] = hex&quot;0000000000000000000000000000000000000000000000000000000000000000&quot;;

  bytes8[2] memory t;
  t[0] = hex&quot;0300000000000000&quot;;
  t[1] = hex&quot;0000000000000000&quot;;

  bool f = true;

  // Expected output:
  // ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d1
  // 7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923
  return F(rounds, h, m, t, f);
}
```

### Gas costs and benchmarks

Each operation will cost `GFROUND * rounds` gas, where `GFROUND = 1`. Detailed benchmarks are presented in the benchmarks appendix section.

## Rationale

BLAKE2 is an excellent candidate for precompilation. BLAKE2 is heavily optimized for modern 64-bit CPUs, specifically utilizing 24 and 63-bit rotations to allow parallelism through SIMD instructions and little-endian arithmetic. These characteristics provide exceptional speed on native CPUs: 3.08 cycles per byte, or 1 gibibyte per second on an Intel i5.

In contrast, the big-endian 32 byte semantics of the EVM are not conducive to efficient implementation of BLAKE2, and thus the gas cost associated with computing the hash on the EVM is disproportionate to the true cost of computing the function natively.

An obvious implementation would be a direct BLAKE2b hash function precompile. At first glance, a BLAKE2b precompile satisfies most hashing and interoperability requirements on the EVM. Once we started digging in, however, it became clear that any BLAKE2b implementation would need specific features and internal modifications based on different projects&apos; requirements and libraries.

A [thread with the Zcash team](https://github.com/ethereum/EIPs/issues/152#issuecomment-499240310) makes the issue clear.

&gt; The minimal thing that is necessary for a working ZEC-ETH relay is an implementation of BLAKE2b Compression F in a precompile.

&gt; A BLAKE2b Compression Function F precompile would also suffice for the Filecoin and Handshake interop goals.

&gt; A full BLAKE2b precompile would suffice for a ZEC-ETH relay, provided that the implementation provided the parts of the BLAKE2 API that we need (personalization, maybe something else—I&apos;m not sure).

&gt; I&apos;m not 100% certain if a full BLAKE2b precompile would also suffice for the Filecoin and Handshake goals. It almost certainly could, provided that it supports all the API that they need.

&gt; BLAKE2s — whether the Compression Function F or the full hash — is only a nice-to-have for the purposes of a ZEC-ETH relay.

From this and other conversations with teams in the space, we believe we should focus first on the `F` precompile as a strictly necessary piece for interoperability projects. A BLAKE2b precompile is a nice-to-have, and we support any efforts to add one-- but it&apos;s unclear whether complete requirements and a flexible API can be found in time for Istanbul.

Implementation of only the core F compression function also allows substantial flexibility and extensibility while keeping changes at the protocol level to a minimum. This will allow functions like tree hashing, incremental hashing, and keyed, salted, and personalized hashing as well as variable length digests, none of which are currently available on the EVM.

## Backwards Compatibility

There is very little risk of breaking backwards-compatibility with this EIP, the sole issue being if someone were to build a contract relying on the address at `0x09` being empty. The likelihood of this is low, and should specific instances arise, the address could be chosen to be any arbitrary value with negligible risk of collision.

## Test Cases

#### Test vector 0
* input: (empty)
* output: error &quot;input length for BLAKE2 F precompile should be exactly 213 bytes&quot;

#### Test vector 1
* input:
`00000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001`
* output: error &quot;input length for BLAKE2 F precompile should be exactly 213 bytes&quot;

#### Test vector 2
* input:
`000000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001`
* output: error &quot;input length for BLAKE2 F precompile should be exactly 213 bytes&quot;

#### Test vector 3
* input:
`0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000002`
* output: error &quot;incorrect final block indicator flag&quot;

#### Test vector 4
* input:
`0000000048c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001`
* output:
`08c9bcf367e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d282e6ad7f520e511f6c3e2b8c68059b9442be0454267ce079217e1319cde05b`

#### Test vector 5
* input:
`0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001`
* output: `ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923`

#### Test vector 6
* input:
`0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000`
* output:
`75ab69d3190a562c51aef8d88f1c2775876944407270c42c9844252c26d2875298743e7f6d5ea2f2d3e8d226039cd31b4e426ac4f2d3d666a610c2116fde4735`

#### Test vector 7
* input:
`0000000148c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001`
* output:
`b63a380cb2897d521994a85234ee2c181b5f844d2c624c002677e9703449d2fba551b3a8333bcdf5f2f7e08993d53923de3d64fcc68c034e717b9293fed7a421`

#### Test vector 8
* input:
`ffffffff48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001`
* output:
`fc59093aafa9ab43daae0e914c57635c5402d8e3d2130eb9b3cc181de7f0ecf9b22bf99a7815ce16419e200e01846e6b5df8cc7703041bbceb571de6631d2615`

## Implementation

An initial implementation of the `F` function in Go, adapted from the standard library, can be found in our [Golang BLAKE2 library fork](https://github.com/keep-network/blake2-f). There&apos;s also an implementation of the precompile in our fork of [go-ethereum](https://github.com/keep-network/go-ethereum/pull/4).

## References

For reference, further discussion on this EIP also occurred in the following PRs and issues

 * [Original Issue](https://github.com/ethereum/EIPs/issues/152)
 * [Ethereum Magicians](https://ethereum-magicians.org/t/blake2b-f-precompile/3157)
 * [PR 2129](https://github.com/ethereum/EIPs/pull/2129)

## Appendix - benchmarks

Assuming ecRecover precompile is perfectly priced, we executed a set of benchmarks comparing Blake2b F compression function precompile with ecRecover precompile. For benchmarks, we used 3.1 GHz Intel Core i7 64-bit machine.

```sh
$ sysctl -n machdep.cpu.brand_string
Intel(R) Core(TM) i7-7920HQ CPU @ 3.10GHz
```

### 12 rounds

An average gas price of F precompile call with 12 rounds compared to ecRecover should have been `6.74153` and it gives `0.5618` gas per round.

```
Name                                         Gascost         Time (ns)     MGas/S    Gasprice for 10MGas/S    Gasprice for ECDSA eq
-----------------------------------------  ---------  ----------------  ---------  -----------------------  -----------------------
PrecompiledEcrecover/                           3000  152636              19.6546                 1526.36               3000
PrecompiledBlake2F/testVectors2bX_0               12     338              35.503                     3.38                  6.64326
PrecompiledBlake2F/testVectors2bX_3               12     336              35.7143                    3.36                  6.60395
PrecompiledBlake2F/testVectors2bX_70              12     362              33.1492                    3.62                  7.11497
PrecompiledBlake2F/testVectors2bX_140             12     339              35.3982                    3.39                  6.66291
PrecompiledBlake2F/testVectors2bX_230             12     339              35.3982                    3.39                  6.66291
PrecompiledBlake2F/testVectors2bX_300             12     343              34.9854                    3.43                  6.74153
PrecompiledBlake2F/testVectors2bX_370             12     336              35.7143                    3.36                  6.60395
PrecompiledBlake2F/testVectors2bX_440             12     337              35.6083                    3.37                  6.6236
PrecompiledBlake2F/testVectors2bX_510             12     345              34.7826                    3.45                  6.78084
PrecompiledBlake2F/testVectors2bX_580             12     355              33.8028                    3.55                  6.97738
```

Columns

* `MGas/S` - Shows what MGas per second was measured on that machine at that time
* `Gasprice for 10MGas/S` shows what the gasprice should have been, in order to reach 10 MGas/second
* `Gasprice for ECDSA eq` shows what the gasprice should have been, in order to have the same cost/cycle as ecRecover

### 1200 rounds

An average gas price of F precompile call with 1200 rounds compared to ecRecover should have been `436.1288` and it gives `0.3634` gas per round.

```
Name                                         Gascost         Time (ns)     MGas/S    Gasprice for 10MGas/S    Gasprice for ECDSA eq
-----------------------------------------  ---------  ----------------  ---------  -----------------------  -----------------------
PrecompiledEcrecover/                           3000  156152              19.212                  1561.52               3000
PrecompiledBlake2F/testVectors2bX_0             1200   22642              52.9989                  226.42                434.999
PrecompiledBlake2F/testVectors2bX_3             1200   22885              52.4361                  228.85                439.668
PrecompiledBlake2F/testVectors2bX_70            1200   22737              52.7774                  227.37                436.824
PrecompiledBlake2F/testVectors2bX_140           1200   22602              53.0926                  226.02                434.231
PrecompiledBlake2F/testVectors2bX_230           1200   22501              53.331                   225.01                432.29
PrecompiledBlake2F/testVectors2bX_300           1200   22435              53.4879                  224.35                431.022
PrecompiledBlake2F/testVectors2bX_370           1200   22901              52.3995                  229.01                439.975
PrecompiledBlake2F/testVectors2bX_440           1200   23134              51.8717                  231.34                444.452
PrecompiledBlake2F/testVectors2bX_510           1200   22608              53.0786                  226.08                434.346
PrecompiledBlake2F/testVectors2bX_580           1200   22563              53.1844                  225.63                433.481
```

### 1 round

An average gas price of F precompile call with 1 round compared to ecRecover should have been `2.431701`. However, in this scenario the call cost would totally overshadow the dynamic cost anyway.

```
Name                                         Gascost         Time (ns)      MGas/S    Gasprice for 10MGas/S    Gasprice for ECDSA eq
-----------------------------------------  ---------  ----------------  ----------  -----------------------  -----------------------
PrecompiledEcrecover/                           3000  157544              19.0423                  1575.44               3000
PrecompiledBlake2F/testVectors2bX_0                1     126               7.93651                    1.26                  2.39933
PrecompiledBlake2F/testVectors2bX_3                1     127               7.87402                    1.27                  2.41837
PrecompiledBlake2F/testVectors2bX_70               1     128               7.8125                     1.28                  2.43741
PrecompiledBlake2F/testVectors2bX_140              1     125               8                          1.25                  2.38029
PrecompiledBlake2F/testVectors2bX_230              1     128               7.8125                     1.28                  2.43741
PrecompiledBlake2F/testVectors2bX_300              1     127               7.87402                    1.27                  2.41837
PrecompiledBlake2F/testVectors2bX_370              1     131               7.63359                    1.31                  2.49454
PrecompiledBlake2F/testVectors2bX_440              1     129               7.75194                    1.29                  2.45646
PrecompiledBlake2F/testVectors2bX_510              1     125               8                          1.25                  2.38029
PrecompiledBlake2F/testVectors2bX_580              1     131               7.63359                    1.31                  2.49454
```


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 04 Oct 2016 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-152</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-152</guid>
      </item>
    
      <item>
        <title>Simple replay attack protection</title>
        <category>Standards Track/Core</category>
        
        <description>### Hard fork
[Spurious Dragon](/EIPs/EIPS/eip-607)

### Parameters
- `FORK_BLKNUM`: 2,675,000
- `CHAIN_ID`: 1 (main net)

### Specification

If `block.number &gt;= FORK_BLKNUM` and `CHAIN_ID` is available, then when computing the hash of a transaction for the purposes of signing, instead of hashing only six rlp encoded elements `(nonce, gasprice, startgas, to, value, data)`, you **SHOULD** hash nine rlp encoded elements `(nonce, gasprice, startgas, to, value, data, chainid, 0, 0)`.  If you do, then the `v` of the signature **MUST** be set to `{0,1} + CHAIN_ID * 2 + 35` where `{0,1}` is the parity of the `y` value of the curve point for which `r` is the x-value in the secp256k1 signing process.  If you choose to only hash 6 values, then `v` continues to be set to `{0,1} + 27` as previously.

If `block.number &gt;= FORK_BLKNUM` and `v = CHAIN_ID * 2 + 35` or `v = CHAIN_ID * 2 + 36`, then when computing the hash of a transaction for purposes of recovering, instead of hashing six rlp encoded elements `(nonce, gasprice, startgas, to, value, data)`, hash nine rlp encoded elements `(nonce, gasprice, startgas, to, value, data, chainid, 0, 0)`. The currently existing signature scheme using `v = 27` and `v = 28` remains valid and continues to operate under the same rules as it did previously.

### Example

Consider a transaction with `nonce = 9`, `gasprice = 20 * 10**9`, `startgas = 21000`, `to = 0x3535353535353535353535353535353535353535`, `value = 10**18`, `data=&apos;&apos;` (empty).

The &quot;signing data&quot; becomes:

```
0xec098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a764000080018080
```

The &quot;signing hash&quot; becomes:

```
0xdaf5a779ae972f972197303d7b574746c7ef83eadac0f2791ad23db92e4c8e53
```

If the transaction is signed with the private key `0x4646464646464646464646464646464646464646464646464646464646464646`, then the v,r,s values become:

```
(37, 18515461264373351373200002665853028612451056578545711640558177340181847433846, 46948507304638947509940763649030358759909902576025900602547168820602576006531)
```

Notice the use of 37 instead of 27. The signed tx would become:

```
0xf86c098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83
```

### Rationale

This would provide a way to send transactions that work on Ethereum without working on ETC or the Morden testnet. ETC is encouraged to adopt this EIP but replacing `CHAIN_ID` with a different value, and all future testnets, consortium chains and alt-etherea are encouraged to adopt this EIP replacing `CHAIN_ID` with a unique value.


### List of Chain ID&apos;s:

| `CHAIN_ID`     | Chain(s)                                   |
| ---------------| -------------------------------------------|
| 1              | Ethereum mainnet                           |
| 2              | Morden (disused), Expanse mainnet          |
| 3              | Ropsten                                    |
| 4              | Rinkeby                                    |
| 5              | Goerli                                     |
| 42             | Kovan                                      |
| 1337           | Geth private chains (default)              |


Find more chain ID&apos;s on [chainid.network](https://chainid.network) and contribute to [ethereum-lists/chains](https://github.com/ethereum-lists/chains).
</description>
        <pubDate>Fri, 14 Oct 2016 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-155</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-155</guid>
      </item>
    
      <item>
        <title>State clearing</title>
        <category>Standards Track/Core</category>
        
        <description># Specification

For all blocks where `block.number &gt;= FORK_BLKNUM` (TBA):
1. In all cases where a state change is made to an account, and this state change results in the account state being saved with nonce = 0, balance = 0, code empty, storage empty (hereinafter &quot;empty account&quot;), the account is instead deleted.
2. If an address is &quot;touched&quot; and that address contains an empty account, then it is deleted. A &quot;touch&quot; is defined as any situation where if the account at the given address were nonexistent it would be created.
3. Whenever the EVM checks if an account exists, emptiness is treated as equivalent to nonexistence. Particularly, note that this implies that, once this change is enabled, there is no longer a meaningful difference between emptiness and nonexistence from the point of view of EVM execution.
4. Zero-value calls and zero-value suicides no longer consume the 25000 account creation gas cost in any circumstance

The cases where a &quot;touch&quot; takes place can be enumerated as follows:
- Zero-value-bearing CALLs
- CREATEs (if the code that is ultimately saved is empty and there is no ether remaining in the account when it is saved)
- Zero-value-bearing SUICIDEs
- Transaction recipients
- Contracts created in contract creation transactions
- Miners receiving transaction fees (note the case where the gasprice is zero, and the account does not yet exist because it only receives the block/uncle/nephew rewards _after_ processing every transaction)
### Specification (1b)

When the EVM checks for emptiness (for the purpose of possibly applying the 25000 gas cost), emptiness is defined by `is_empty(acct): return get_balance(acct) == 0 and get_code(acct) == &quot;&quot; and get_nonce(acct) == 0`; emptiness of storage does not matter. This simplifies client implementation because there is no need to add extra complexity to make caches enumerable in the correct way and does not significantly affect the intended result, as the cases where balance/code/nonce are empty but storage is nonempty where this change would lead to an extra 25000 gas being paid are pathological and have no real use value.
### Specification (1c)

Do not implement point 2 above (ie. no new empty accounts can be created, but existing ones are not automatically destroyed unless their state is actually _changed_). Instead, during each block starting from (and including) N and ending when there are no null accounts left, select the 1000 null accounts that are left-most in order of sha3(address), and delete them (ordering by hash is necessary so as to allow the accounts to be easily found by iterating the tree).
# Rationale

This removes a large number of empty accounts that have been put in the state at very low cost due to flaws in earlier versions of the Ethereum protocol, thereby greatly reducing state size and hence both reducing the hard disk load of a full client and reducing the time for a fast sync. Additionally, it simplifies the protocol in the long term, as once all &quot;empty&quot; objects are cleared out there is no longer any meaningful distinction between an account being empty and being nonexistent, and indeed one can simply view nonexistence as a compact representation of emptiness.

Note that this proposal does introduce a **temporary** breaking of existing guarantees, in that by repeatedly zero-value-calling already existing empty accounts one can create a state change at a cost of 700 gas per account instead of the usual 5000 per gas minimum (with SUICIDE refunds this goes down further to 350 gas per account). Allowing such a large number of state writes per block will lead to heightened block processing times and increase uncle rates in the short term while the existing empty accounts are being cleared, and eventually once all empty accounts are cleared this issue will no longer exist.

# References

1. EIP-158 issue and discussion: https://github.com/ethereum/EIPs/issues/158
2. EIP-161 issue and discussion: https://github.com/ethereum/EIPs/issues/161
</description>
        <pubDate>Sun, 16 Oct 2016 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-158</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-158</guid>
      </item>
    
      <item>
        <title>EXP cost increase</title>
        <category>Standards Track/Core</category>
        
        <description>### Hard fork
[Spurious Dragon](/EIPs/EIPS/eip-607)

### Parameters
- `FORK_BLKNUM`: 2,675,000
- `CHAIN_ID`: 1

### Specification

If `block.number &gt;= FORK_BLKNUM`, increase the gas cost of EXP from 10 + 10 per byte in the exponent to 10 + 50 per byte in the exponent.

### Rationale

Benchmarks suggest that EXP is currently underpriced by a factor of about 4–8.

### References

1. EIP-160 issue and discussion: https://github.com/ethereum/EIPs/issues/160
</description>
        <pubDate>Thu, 20 Oct 2016 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-160</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-160</guid>
      </item>
    
      <item>
        <title>State trie clearing (invariant-preserving alternative)</title>
        <category>Standards Track/Core</category>
        
        <description>### Hard fork
[Spurious Dragon](/EIPs/EIPS/eip-607)

### Parameters
- `FORK_BLKNUM`: 2,675,000
- `CHAIN_ID`: 1 (Mainnet)

### Specification

a. Account creation transactions and the `CREATE` operation SHALL, prior to the execution of the initialisation code, **increment** the **nonce** over and above its normal starting value by **one** (for normal networks, this will be simply 1, however test-nets with non-zero default starting nonces will be different).

b. Whereas `CALL` and `SUICIDE` would charge 25,000 gas when the destination is non-existent, now the charge SHALL **only** be levied if the operation transfers **more than zero value** and the destination account is _dead_.

c. No account may _change state_ from non-existent to existent-but-_empty_. If an operation would do this, the account SHALL instead remain non-existent.

d. _At the end of the transaction_, any account _touched_ by the execution of that transaction which is now _empty_ SHALL instead become non-existent (i.e. **deleted**).

Where:

An account is considered to be _touched_ when it is involved in any potentially _state-changing_ operation. This includes, but is not limited to, being the recipient of a **transfer of zero value**.

An account is considered _empty_ when it has **no code** and **zero nonce** and **zero balance**.

An account is considered _dead_ when either it is non-existent or it is _empty_.

_At the end of the transaction_ is immediately following the execution of the suicide list, prior to the determination of the state trie root for receipt population.

An account _changes state_ when:
- it is the target or refund of a `SUICIDE` operation for **zero or more** value;
- it is the source or destination of a `CALL` operation or message-call transaction transferring **zero or more** value;
- it is the source or creation of a `CREATE` operation or contract-creation transaction endowing **zero or more** value;
- as the block author (&quot;miner&quot;) it is the recipient of block-rewards or transaction-fees of **zero or more** value.

#### Notes

In the present Ethereum protocol, it should be noted that very few state changes can ultimately result in accounts that are empty following the execution of the transaction. In fact there are only four contexts that current implementations need track:
- an empty account has zero value transferred to it through `CALL`;
- an empty account has zero value transferred to it through `SUICIDE`;
- an empty account has zero value transferred to it through a message-call transaction;
- an empty account has zero value transferred to it through a zero-gas-price fees transfer.

### Rationale

Same as #158 except that several edge cases are avoided since we do not break invariants:
- ~~that an account can go from having code and storage to not having code or storage mid-way through the execution of a transaction;~~ [corrected]
- that a newly created account cannot be deleted prior to being deployed.

`CREATE` avoids zero in the nonce to avoid any suggestion of the oddity of `CREATE`d accounts being reaped half-way through their creation.

### Addendum (2017-08-15)

On 2016-11-24, a consensus bug occurred due to two implementations having different behavior in the case of state reverts.[3] The specification was amended to clarify that empty account deletions are reverted when the state is reverted.

### References

1. EIP-158 issue and discussion: https://github.com/ethereum/EIPs/issues/158
2. EIP-161 issue and discussion: https://github.com/ethereum/EIPs/issues/161
3. https://blog.ethereum.org/2016/11/25/security-alert-11242016-consensus-bug-geth-v1-4-19-v1-5-2/
&gt; Details: Geth was failing to revert empty account deletions when the transaction causing the deletions of empty accounts ended with an out-of-gas exception. An additional issue was found in Parity, where the Parity client incorrectly failed to revert empty account deletions in a more limited set of contexts involving out-of-gas calls to precompiled contracts; the new Geth behavior matches Parity’s, and empty accounts will cease to be a source of concern in general in about one week once the state clearing process finishes.
</description>
        <pubDate>Mon, 24 Oct 2016 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-161</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-161</guid>
      </item>
    
      <item>
        <title>Initial ENS Hash Registrar</title>
        <category>Standards Track/ERC</category>
        
        <description>## Contents
- Abstract
- Motivations
- Specification
  - Initial restrictions
  - Name format for hash registration
  - Auctioning names
  - Deeds
  - Deployment and Upgrade process
  - Registrar Interface
- Rationale
  - Not committing to a permanent registrar at the outset
  - Valid names &gt;= 7 characters
  - Restricting TLD to `.eth`
  - Holding ether as collateral
- Prior work

&lt;!-- /MarkdownTOC --&gt;

## Abstract

This ERC describes the implementation, as deployed to the main ethereum network on 2017-05-04, of a registrar contract to govern the allocation of names in the Ethereum Name Service (ENS). The corresponding source code is [here](https://github.com/ethereum/ens/blob/mainnet/contracts/HashRegistrarSimplified.sol).

For more background, refer to [EIP-137](/EIPs/EIPS/eip-137).

&gt; Registrars are responsible for allocating domain names to users of the system, and are the only entities capable of updating the ENS; the owner of a node in the ENS registry is its registrar. Registrars may be contracts or externally owned accounts, though it is expected that the root and top-level registrars, at a minimum, will be implemented as contracts.
&gt;
&gt; \- EIP 137

A well designed and governed registrar is essential to the success of the ENS described in EIP 137, but is described separately in this document as it is external to the core ENS protocol.

In order to maximize utility and adoption of a new namespace, the registrar should mitigate speculation and &quot;name squatting&quot;, however the best approach for mitigation is unclear. Thus an &quot;initial&quot; registrar is proposed, which implements a simple approach to name allocation. During the initial period, the available namespace will be significantly restricted to the `.eth` top level domain, and subdomain shorter than 7 characters in length disallowed. This specification largely describes @alexvandesande and @arachnid&apos;s [hash registrar implementation](https://github.com/ethereum/ens/blob/mainnet/contracts/HashRegistrarSimplified.sol) in order to facilitate discussion.

The intent is to replace the Initial Registrar contract with a permanent registrar contract. The Permanent Registrar will increase the available namespace, and incorporate lessons learned from the performance of the Initial Registrar. This upgrade is expected to take place within approximately 2 years of initial deployment.

## Motivations

The following factors should be considered in order to optimize for adoption of the ENS, and good governance of the Initial Registrar&apos;s namespace.

**Upgradability:** The Initial Registrar should be safely upgradeable, so that knowledge gained during its deployment can be used to replace it with an improved and permanent registrar.

**Effective allocation:** Newly released namespaces often create a land grab situation, resulting in many potentially valuable names being purchased but unused, with the hope of re-selling at a profit. This reduces the availability of the most useful names, in turn decreasing the utility of the name service to end users.

Achieving an effective allocation may or may not require human intervention for dispute resolution and other forms of curation. The Initial Registrar should not aim to create to most effective possible allocation, but instead limit the cost of misallocation in the long term.

**Security:** The registrar will hold a balance of ether without an explicit limit. It must be designed securely.

**Simplicity:** The ENS specification itself emphasizes a separation of concerns, allowing the most essential element, the registry to be as simple as possible. The interim registrar in turn should be as simple as possible while still meeting its other design goals.

**Adoption:** Successful standards become more successful due to network effects. The registrar should consider what strategies will encourage the adoption of the ENS in general, and the namespace it controls in particular.

## Specification

### Initial restrictions

The Initial Registrar is expected to be in service for approximately two years, prior to upgrading. This should be sufficient time to learn, observe, and design an updated system.

During the initial two year period, the available name space will be restricted to the `.eth` TLD.

This restriction is enforced by the owner of the ENS root node who should not assign any nodes other than `.eth` to the Initial Registrar. The ENS&apos;s root node should be controlled by multiple parties using a multisig contract.

The Initial Registrar will also prohibit registration of names 6 characters or less in length.

### Name format for hash registration

Names submitted to the initial registrar must be hashed using Ethereum&apos;s sha3 function. Note that the hashes submitted to the registrar are the hash of the subdomain label being registered, not the namehash as defined in EIP 137.

For example, in order to register `abcdefg.eth`, one should submit `sha3(&apos;abcdefg&apos;)`, not `sha3(sha3(0, &apos;eth&apos;), &apos;abcdefg&apos;)`.

### Auctioning names

The registrar will allocate the available names through a Vickrey auction:

&gt; A Vickrey auction is a type of sealed-bid auction. Bidders submit written bids without knowing the bid of the other people in the auction. The highest bidder wins but the price paid is the second-highest bid. This type of auction... gives bidders an incentive to bid their true value.
&gt;
&gt; \- [Vickrey Auction, Wikipedia](https://en.wikipedia.org/wiki/Vickrey_auction)

The auction lifecycle of a name has 5 possible states, or Modes.

1. **Not-yet-available:** The majority of names will be initially unavailable for auction, and will become available some time during the 8 weeks after launch.
2. **Open:** The earliest availability for a name is determined by the most significant byte of its sha3 hash. `0x00` would become available immediately, `0xFF` would become available after 8 weeks, and the availability of other names is distributed accordingly. Once a name is available, it is possible to start an auction on it.
3. **Auction:** Once the auction for a name has begun, there is a 72 hour bidding period. Bidders must submit a payment of ether, along with sealed bids as a hash of `sha3(bytes32 hash, address owner, uint value, bytes32 salt)`. The bidder may obfuscate the true bid value by sending a greater amount of ether.
4. **Reveal:** After the bidding period, a 48 hour reveal period commences. During this time, bidders must reveal the true parameters of their sealed bid. As bids are revealed, ether payments are returned according to the schedule of &quot;refund ratios&quot; outlined in the table below. If no bids are revealed, the name will return to the Open state.
5. **Owned:** After the reveal period has finished, the winning bidder must submit a transaction to finalize the auction, which then calls the ENS&apos;s `setSubnodeOwner` function, recording the winning bidder&apos;s address as the owner of the hash of the name.

The following table outlines important parameters which define the Registrar&apos;s auction mechanism.

#### Registrar Parameters

|        Name        |                                            Description                                             |   Value    |
|--------------------|----------------------------------------------------------------------------------------------------|------------|
| totalAuctionLength | The full time period from start of auction to end of the reveal period.                            | 5 days     |
| revealPeriod       | The length of the time period during which bidding is no longer allowed, and bids must be revealed. | 48 hours   |
| launchLength       | The time period during which all names will become available for auction.                          | 8 weeks    |
| minPrice           | The minimum amount of ether which must be locked up in exchange for ownership of a name.           | 0.01 ether |

### Deeds

The Initial Registrar contract does not hold a balance itself. All ether sent to the Registrar will be held in a separate `Deed` contracts. A deed contract is first created and funded when a sealed bid is submitted. After an auction is completed and a hash is registered, the deed for the winning bid is held in exchange for ownership of the hash. Non-winning bids are refunded.

A deed for an owned name may be transferred to another account by its owner, thus transferring ownership and control of the name.

After 1 year of registration, the owner of a hash may choose to relinquish ownership and have the value of the deed returned to them.

Deeds for non-winning bids can be closed by various methods, at which time any ether held will either be returned to the bidder, burnt, or sent to someone else as a reward for actions which help the registrar.

The following table outlines what portion of the balance held in a deed contract will be returned upon closure, and to whom. The remaining balance will be burnt.

#### Refund schedule

| Reason for Deed closure | Refund Recipient | Refund Percentage |
| --- | --- | --- |
| A valid non-winning bid is revealed. | Bidder | 99.5% |
| A bid submitted after the auction period is revealed. | Bidder | 99.5% |
| An otherwise valid bid is revealed on an owned name. &lt;sup&gt;1&lt;/sup&gt; | Bidder | 0.5% |
| An expired sealed bid is cancelled. &lt;sup&gt;2&lt;/sup&gt; | Canceler | 0.5% |
| A registered hash is reported as invalid. &lt;sup&gt;3&lt;/sup&gt; | Reporter | 50% |
| A registered hash is reported as invalid. &lt;sup&gt;3&lt;/sup&gt; | Owner | 50% |

##### Notes:

1. This incentivizes all bids to be revealed in time. If bids could be revealed late, an extortion attack on the current highest bidder could be made by threatening to reveal a new second highest bid.
2. A bid which remains sealed after more than 2 weeks and 5 days may be cancelled by anyone to collect a small reward.
2. Since names are hashed before auctioning and registration, the Initial Registrar is unable to enforce character length restrictions independently. A reward is therefore provided for reporting invalid names.

### Deployment and Upgrade process

The Initial Registrar requires the ENS&apos;s address as a constructor, and should be deployed after the ENS. The multisig account owning the root node in the ENS should then set the Initial Registrar&apos;s address as owner of the `eth` node.

The Initial Registrar is expected to be replaced by a Permanent Registrar approximately 2 years after deployment. The following process should be used for the upgrade:
1. The Permanent Registrar contract will be deployed.
2. The multisig account owning the root node in the ENS will assign ownership of the `.eth` node to the Permanent Registrar.
3. Owners of hashes in the Initial Registrar will be responsible for registering their deeds to the Permanent Registrar. A couple options are considered here:
   1. Require owners to transfer their ownership prior to a cutoff date in order to maintain ownership and/or continue name resolution services.
   2. Have the Permanent Registrar query the Initial Registrar for ownership if it is lacking an entry.

### Planned deactivation

In order to limit dependence on the Initial Registrar, new auctions will stop after 4 years, and all ether held in deeds after 8 years will become unreachable.

### Registrar Interface

`function state(bytes32 _hash) constant returns (Mode)`
- Implements a state machine returning the current state of a name

`function entries(bytes32 _hash) constant returns (Mode, address, uint, uint, uint)`
- Returns the following information regarding a registered name:
  * state
  * deed address
  * registration date
  * balance of the deed
  * highest value bid at auction

`function getAllowedTime(bytes32 _hash) constant returns (uint timestamp)`
- Returns the time at which the hash will no longer be in the initial `not-yet-available` state.

`function isAllowed(bytes32 _hash, uint _timestamp) constant returns (bool allowed)`
- Takes a hash and a time, returns true if and only if it has passed the initial `not-yet-available` state.

`function startAuction(bytes32 _hash);`
- Moves the state of a hash from Open to Auction. Throws if state is not Open.

`function startAuctions(bytes32[] _hashes);`
- Starts multiple auctions on an array of hashes. This enables someone to open up an auction for a number of dummy hashes when they are only really interested in bidding for one. This will increase the cost for an attacker to simply bid blindly on all new auctions. Dummy auctions that are open but not bid on are closed after a week.

`function shaBid(bytes32 hash, address owner, uint value, bytes32 salt) constant returns (bytes32 sealedBid);`
- Takes the parameters of a bid, and returns the sealedBid hash value required to participate in the bidding for an auction. This obfuscates the parameters in order to mimic the mechanics of placing a bid in an envelope.

`function newBid(bytes32 sealedBid);`
- Bids are sent by sending a message to the main contract with a sealedBid hash and an amount of ether. The hash contains information about the bid, including the bidded name hash, the bid value, and a random salt. Bids are not tied to any one auction until they are revealed. The value of the bid itself can be masqueraded by sending more than the value of your actual bid. This is followed by a 48h reveal period. Bids revealed after this period will be burned and the ether unrecoverable. Since this is an auction, it is expected that most public hashes, like known domains and common dictionary  words, will have multiple bidders pushing the price up.

`function startAuctionsAndBid(bytes32[] hashes, bytes32 sealedBid)`
- A utility function allowing a call to `startAuctions` followed by `newBid` in a single transaction.


`function unsealBid(bytes32 _hash, address _owner, uint _value, bytes32 _salt);`
- Once the bidding period is completed, there is a reveal period during with the properties of a bid are submitted to reveal them. The registrar hashes these properties using the `shaBid()` function above to verify that they match a pre-existing sealed bid. If the unsealedBid is the new best bid, the old best bid is returned to its bidder.

`function cancelBid(bytes32 seal);`
- Cancels an unrevealed bid according to the rules described in the notes on the refund schedule above.

`function finalizeAuction(bytes32 _hash);`

After the registration date has passed, this function can be called to finalize the auction, which then calls the ENS function `setSubnodeOwner()`  updating the ENS record to set the winning bidder as owner of the node.

`function transfer(bytes32 _hash, address newOwner);`
- Update the owner of the ENS node corresponding to the submitted hash to a new owner. This function must be callable only by the current owner.

`function releaseDeed(bytes32 _hash);`
- After some time, the owner can release the property and get their ether back.

`function invalidateName(string unhashedName);`
- Since registration is done on the hash of a name, the registrar itself cannot validate names. This function can be used to report a name which is 6 characters long or less. If it has been registered, the submitter will earn 10% of the deed value. We are purposefully handicapping the simplified registrar as a way to force it into being restructured in a few years.

`function eraseNode(bytes32[] labels)`
- Allows anyone to delete the owner and resolver records for a subdomain of a name that is not currently owned in the registrar. For instance, to zero `foo.bar.eth` on a registrar that owns `.eth`, pass an array containing `[sha3(&apos;foo&apos;), sha3(&apos;bar&apos;)]`.

`function transferRegistrars(bytes32 _hash) onlyOwner(_hash);`
- Used during the upgrade process to a permanent registrar. If this registrar is no longer the owner of the its root node in the ENS, this function will transfers the deed to the current owner, which should be a new registrar. This function throws if this registrar still owns its root node.

## Rationale

### Starting with a temporary registrar

Anticipating and designing for all the potential issues of name allocation names is unlikely to succeed. This approach chooses not to be concerned with getting it perfect, but allows us to observe and learn with training wheels on, and implement improvements before expanding the available namespace to shorter names or another TLD.

### Valid names &gt;= 7 characters

Preserving the shortest, and often most valuable, domain names for the upgraded registrar provides the opportunity to implement processes for dispute resolution (assuming they are found to be necessary).

### Delayed release of names

A slower release allows for extra time to identify, and address any issues which may arise after launch.

### Restricting TLD to `.eth`

Choosing a single TLD helps to maximize network effects by focusing on one namespace.

A three letter TLD is a pattern made familiar by it&apos;s common usage in internet domain names. This familiarity significantly increases the potential of the ENS to be integrated into pre-existing DNS systems, and reserved as a [special-use domain name](https://www.iana.org/assignments/special-use-domain-names/special-use-domain-names.xhtml#special-use-domain).  A recent precedent for this is the [reservation of the `.onion` domain](https://tools.ietf.org/html/rfc7686).

### Holding ether as collateral

This approach is simpler than the familiar model of requiring owners to make recurring payments to retain ownership of a domain name. It also makes the initial registrar a revenue neutral service.

## Prior work

This document borrows heavily from several sources:
- [EIP-137](/EIPs/EIPS/eip-137) outlines the initial implementation of the Registry Contract (ENS.sol) and associated Resolver contracts.
- [ERC-26](https://github.com/ethereum/EIPs/issues/26) was the first ERC to propose a name service at the contract layer
- @alexvandesande&apos;s current implementation of the [HashRegistrar](https://github.com/ethereum/ens/blob/mainnet/contracts/HashRegistrarSimplified.sol)

### Edits:
- 2016-10-26 Added link Alex&apos;s design in abstract
- 2016-11-01 change &apos;Planned deactivation&apos; to h3&apos;
- 2017-03-13 Update timelines for bidding and reveal periods

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 25 Oct 2016 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-162</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-162</guid>
      </item>
    
      <item>
        <title>Standard Interface Detection</title>
        <category>Standards Track/ERC</category>
        
        <description>## Simple Summary

Creates a standard method to publish and detect what interfaces a smart contract implements.

## Abstract

Herein, we standardize the following:

1. How interfaces are identified
2. How a contract will publish the interfaces it implements
3. How to detect if a contract implements ERC-165
4. How to detect if a contract implements any given interface

## Motivation

For some &quot;standard interfaces&quot; like [the ERC-20 token interface](/EIPs/EIPS/eip-20), it is sometimes useful to query whether a contract supports the interface and if yes, which version of the interface, in order to adapt the way in which the contract is to be interacted with. Specifically for ERC-20, a version identifier has already been proposed. This proposal standardizes the concept of interfaces and standardizes the identification (naming) of interfaces.

## Specification

### How Interfaces are Identified

For this standard, an *interface* is a set of [function selectors as defined by the Ethereum ABI](https://solidity.readthedocs.io/en/develop/abi-spec.html#function-selector). This a subset of [Solidity&apos;s concept of interfaces](https://solidity.readthedocs.io/en/develop/abi-spec.html) and the  `interface` keyword definition which also defines return types, mutability and events.

We define the interface identifier as the XOR of all function selectors in the interface. This code example shows how to calculate an interface identifier:

```solidity
pragma solidity ^0.4.20;

interface Solidity101 {
    function hello() external pure;
    function world(int) external pure;
}

contract Selector {
    function calculateSelector() public pure returns (bytes4) {
        Solidity101 i;
        return i.hello.selector ^ i.world.selector;
    }
}
```

Note: interfaces do not permit optional functions, therefore, the interface identity will not include them.

### How a Contract will Publish the Interfaces it Implements

A contract that is compliant with ERC-165 shall implement the following interface (referred as `ERC165.sol`):

```solidity
pragma solidity ^0.4.20;

interface ERC165 {
    /// @notice Query if a contract implements an interface
    /// @param interfaceID The interface identifier, as specified in ERC-165
    /// @dev Interface identification is specified in ERC-165. This function
    ///  uses less than 30,000 gas.
    /// @return `true` if the contract implements `interfaceID` and
    ///  `interfaceID` is not 0xffffffff, `false` otherwise
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
```

The interface identifier for this interface is `0x01ffc9a7`. You can calculate this by running `bytes4(keccak256(&apos;supportsInterface(bytes4)&apos;));` or using the `Selector` contract above.

Therefore the implementing contract will have a `supportsInterface` function that returns:

- `true` when `interfaceID` is `0x01ffc9a7` (EIP165 interface)
- `false` when `interfaceID` is `0xffffffff`
- `true` for any other `interfaceID` this contract implements
- `false` for any other `interfaceID`

This function must return a bool and use at most 30,000 gas.

Implementation note, there are several logical ways to implement this function. Please see the example implementations and the discussion on gas usage.

### How to Detect if a Contract Implements ERC-165

1. The source contract makes a `STATICCALL` to the destination address with input data: `0x01ffc9a701ffc9a700000000000000000000000000000000000000000000000000000000` and gas 30,000. This corresponds to `contract.supportsInterface(0x01ffc9a7)`.
2. If the call fails or return false, the destination contract does not implement ERC-165.
3. If the call returns true, a second call is made with input data `0x01ffc9a7ffffffff00000000000000000000000000000000000000000000000000000000`.
4. If the second call fails or returns true, the destination contract does not implement ERC-165.
5. Otherwise it implements ERC-165.

### How to Detect if a Contract Implements any Given Interface

1. If you are not sure if the contract implements ERC-165, use the above procedure to confirm.
2. If it does not implement ERC-165, then you will have to see what methods it uses the old-fashioned way.
3. If it implements ERC-165 then just call `supportsInterface(interfaceID)` to determine if it implements an interface you can use.

## Rationale

We tried to keep this specification as simple as possible. This implementation is also compatible with the current Solidity version.

## Backwards Compatibility

The mechanism described above (with `0xffffffff`) should work with most of the contracts previous to this standard to determine that they do not implement ERC-165.

Also [the ENS](/EIPs/EIPS/eip-137) already implements this EIP.

## Test Cases

Following is a contract that detects which interfaces other contracts implement. From @fulldecent and @jbaylina.

```solidity
pragma solidity ^0.4.20;

contract ERC165Query {
    bytes4 constant InvalidID = 0xffffffff;
    bytes4 constant ERC165ID = 0x01ffc9a7;

    function doesContractImplementInterface(address _contract, bytes4 _interfaceId) external view returns (bool) {
        uint256 success;
        uint256 result;

        (success, result) = noThrowCall(_contract, ERC165ID);
        if ((success==0)||(result==0)) {
            return false;
        }

        (success, result) = noThrowCall(_contract, InvalidID);
        if ((success==0)||(result!=0)) {
            return false;
        }

        (success, result) = noThrowCall(_contract, _interfaceId);
        if ((success==1)&amp;&amp;(result==1)) {
            return true;
        }
        return false;
    }

    function noThrowCall(address _contract, bytes4 _interfaceId) constant internal returns (uint256 success, uint256 result) {
        bytes4 erc165ID = ERC165ID;

        assembly {
                let x := mload(0x40)               // Find empty storage location using &quot;free memory pointer&quot;
                mstore(x, erc165ID)                // Place signature at beginning of empty storage
                mstore(add(x, 0x04), _interfaceId) // Place first argument directly next to signature

                success := staticcall(
                                    30000,         // 30k gas
                                    _contract,     // To addr
                                    x,             // Inputs are stored at location x
                                    0x24,          // Inputs are 36 bytes long
                                    x,             // Store output over input (saves space)
                                    0x20)          // Outputs are 32 bytes long

                result := mload(x)                 // Load the result
        }
    }
}
```

## Implementation

This approach uses a `view` function implementation of `supportsInterface`. The execution cost is 586 gas for any input. But contract initialization requires storing each interface (`SSTORE` is 20,000 gas). The `ERC165MappingImplementation` contract is generic and reusable.

```solidity
pragma solidity ^0.4.20;

import &quot;./ERC165.sol&quot;;

contract ERC165MappingImplementation is ERC165 {
    /// @dev You must not set element 0xffffffff to true
    mapping(bytes4 =&gt; bool) internal supportedInterfaces;

    function ERC165MappingImplementation() internal {
        supportedInterfaces[this.supportsInterface.selector] = true;
    }

    function supportsInterface(bytes4 interfaceID) external view returns (bool) {
        return supportedInterfaces[interfaceID];
    }
}

interface Simpson {
    function is2D() external returns (bool);
    function skinColor() external returns (string);
}

contract Lisa is ERC165MappingImplementation, Simpson {
    function Lisa() public {
        supportedInterfaces[this.is2D.selector ^ this.skinColor.selector] = true;
    }

    function is2D() external returns (bool){}
    function skinColor() external returns (string){}
}
```

Following is a `pure` function implementation of `supportsInterface`. The worst-case execution cost is 236 gas, but increases linearly with a higher number of supported interfaces.

```solidity
pragma solidity ^0.4.20;

import &quot;./ERC165.sol&quot;;

interface Simpson {
    function is2D() external returns (bool);
    function skinColor() external returns (string);
}

contract Homer is ERC165, Simpson {
    function supportsInterface(bytes4 interfaceID) external view returns (bool) {
        return
          interfaceID == this.supportsInterface.selector || // ERC165
          interfaceID == this.is2D.selector
                         ^ this.skinColor.selector; // Simpson
    }

    function is2D() external returns (bool){}
    function skinColor() external returns (string){}
}
```

With three or more supported interfaces (including ERC165 itself as a required supported interface), the mapping approach (in every case) costs less gas than the pure approach (at worst case).

## Version history
* PR 1640, finalized 2019-01-23 -- This corrects the noThrowCall test case to use 36 bytes rather than the previous 32 bytes. The previous code was an error that still silently worked in Solidity 0.4.x but which was broken by new behavior introduced in Solidity 0.5.0. This change was discussed at [#1640](https://github.com/ethereum/EIPs/pull/1640).

* EIP 165, finalized 2018-04-20 -- Original published version.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 23 Jan 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-165</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-165</guid>
      </item>
    
      <item>
        <title>Contract code size limit</title>
        <category>Standards Track/Core</category>
        
        <description>### Hard fork
[Spurious Dragon](/EIPs/EIPS/eip-607)

### Parameters
- `MAX_CODE_SIZE`: `0x6000` (`2**14 + 2**13`)
- `FORK_BLKNUM`: 2,675,000
- `CHAIN_ID`: 1 (Mainnet)

### Specification

If `block.number &gt;= FORK_BLKNUM`, then if contract creation initialization returns data with length of **more than** `MAX_CODE_SIZE` bytes, contract creation fails with an out of gas error.

### Rationale

Currently, there remains one slight quadratic vulnerability in Ethereum: when a contract is called, even though the call takes a constant amount of gas, the call can trigger O(n) cost in terms of reading the code from disk, preprocessing the code for VM execution, and also adding O(n) data to the Merkle proof for the block&apos;s proof-of-validity. At current gas levels, this is acceptable even if suboptimal. At the higher gas levels that could be triggered in the future, possibly very soon due to dynamic gas limit rules, this would become a greater concern—not nearly as serious as recent denial of service attacks, but still inconvenient especially for future light clients verifying proofs of validity or invalidity. The solution is to put a hard cap on the size of an object that can be saved to the blockchain, and do so non-disruptively by setting the cap at a value slightly higher than what is feasible with current gas limits.

### References

1. EIP-170 issue and discussion: https://github.com/ethereum/EIPs/issues/170
2. pyethereum implementation: https://github.com/ethereum/pyethereum/blob/5217294871283d8dc4fb3ca9d8a78c7d416490e8/ethereum/messages.py#L397
</description>
        <pubDate>Fri, 04 Nov 2016 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-170</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-170</guid>
      </item>
    
      <item>
        <title>Contract Ownership Standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/173</comments>
        
        <description>## Abstract

This specification defines standard functions for owning or controlling a contract. 

An implementation allows reading the current owner (`owner() returns (address)`) and transferring ownership (`transferOwnership(address newOwner)`) along with a standardized event for when ownership is changed (`OwnershipTransferred(address indexed previousOwner, address indexed newOwner)`).

## Motivation

Many smart contracts require that they be owned or controlled in some way. For example to withdraw funds or perform administrative actions. It is so common that the contract interface used to handle contract ownership should be standardized to allow compatibility with user interfaces and contracts that manage contracts.

Here are some examples of kinds of contracts and applications that can benefit from this standard:
1. Exchanges that buy/sell/auction ethereum contracts. This is only widely possible if there is a standard for getting the owner of a contract and transferring ownership.
2. Contract wallets that hold the ownership of contracts and that can transfer the ownership of contracts.
3. Contract registries. It makes sense for some registries to only allow the owners of contracts to add/remove their contracts. A standard must exist for these contract registries to verify that a contract is being submitted by the owner of it before accepting it.
4. User interfaces that show and transfer ownership of contracts.

## Specification

Every ERC-173 compliant contract must implement the `ERC173` interface. Contracts should also implement `ERC165` for the ERC-173 interface.

```solidity

/// @title ERC-173 Contract Ownership Standard
///  Note: the ERC-165 identifier for this interface is 0x7f5828d0
interface ERC173 /* is ERC165 */ {
    /// @dev This emits when ownership of a contract changes.    
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /// @notice Get the address of the owner    
    /// @return The address of the owner.
    function owner() view external returns(address);
	
    /// @notice Set the address of the new owner of the contract
    /// @dev Set _newOwner to address(0) to renounce any ownership.
    /// @param _newOwner The address of the new owner of the contract    
    function transferOwnership(address _newOwner) external;	
}

interface ERC165 {
    /// @notice Query if a contract implements an interface
    /// @param interfaceID The interface identifier, as specified in ERC-165
    /// @dev Interface identification is specified in ERC-165. 
    /// @return `true` if the contract implements `interfaceID` and
    ///  `interfaceID` is not 0xffffffff, `false` otherwise
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
```

The `owner()` function may be implemented as `pure` or `view`.

The `transferOwnership(address _newOwner)` function may be implemented as `public` or `external`.

To renounce any ownership of a contract set `_newOwner` to the zero address: `transferOwnership(address(0))`. If this is done then a contract is no longer owned by anybody.

The OwnershipTransferred event should be emitted when a contract is created.

## Rationale

Key factors influencing the standard: 
- Keeping the number of functions in the interface to a minimum to prevent contract bloat.
- Backwards compatibility with existing contracts.
- Simplicity
- Gas efficient

Several ownership schemes were considered. The scheme chosen in this standard was chosen because of its simplicity, low gas cost and backwards compatibility with existing contracts.

Here are other schemes that were considered:
1. **Associating an Ethereum Name Service (ENS) domain name with a contract.** A contract&apos;s `owner()` function could look up the owner address of a particular ENS name and use that as the owning address of the contract. Using this scheme a contract could be transferred by transferring the ownership of the ENS domain name to a different address. Short comings to this approach are that it is not backwards compatible with existing contracts and requires gas to make external calls to ENS related contracts to get the owner address.
2. **Associating an ERC721-based non-fungible token (NFT) with a contract.** Ownership of a contract could be tied to the ownership of an NFT. The benefit of this approach is that the existing ERC721-based infrastructure could be used to sell/buy/auction contracts. Short comings to this approach are additional complexity and infrastructure required. A contract could be associated with a particular NFT but the NFT would not track that it had ownership of a contract unless it was programmed to track contracts. In addition handling ownership of contracts this way is not backwards compatible.

This standard does not exclude the above ownership schemes or other schemes from also being implemented in the same contract. For example a contract could implement this standard and also implement the other schemes so that ownership could be managed and transferred in multiple ways. This standard does provide a simple ownership scheme that is backwards compatible, is light-weight and simple to implement, and can be widely adopted and depended on.

This standard can be (and has been) extended by other standards to add additional ownership functionality. 

## Security Considerations

If the address returned by `owner()` is an externally owned account then its private key must not be lost or compromised.

## Backwards Compatibility

Many existing contracts already implement this standard.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 07 Jun 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-173</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-173</guid>
      </item>
    
      <item>
        <title>ENS support for reverse resolution of Ethereum addresses</title>
        <category>Standards Track/ERC</category>
        
        <description># Abstract
This EIP specifies a TLD, registrar, and resolver interface for reverse resolution of Ethereum addresses using ENS. This permits associating a human-readable name with any Ethereum blockchain address. Resolvers can be certain that the reverse record was published by the owner of the Ethereum address in question.

# Motivation
While name services are mostly used for forward resolution - going from human-readable identifiers to machine-readable ones - there are many use-cases in which reverse resolution is useful as well:

 - Applications that allow users to monitor accounts benefit from showing the name of an account instead of its address, even if it was originally added by address.
 - Attaching metadata such as descriptive information to an address allows retrieving this information regardless of how the address was originally discovered.
 - Anyone can configure a name to resolve to an address, regardless of ownership of that address. Reverse records allow the owner of an address to claim a name as authoritative for that address.

# Specification
Reverse ENS records are stored in the ENS hierarchy in the same fashion as regular records, under a reserved domain, `addr.reverse`. To generate the ENS name for a given account&apos;s reverse records, convert the account to hexadecimal representation in lower-case, and append `addr.reverse`. For instance, the ENS registry&apos;s address at `0x112234455c3a32fd11230c42e7bccd4a84e02010` has any reverse records stored at `112234455c3a32fd11230c42e7bccd4a84e02010.addr.reverse`.

Note that this means that contracts wanting to do dynamic reverse resolution of addresses will need to perform hex encoding in the contract.

## Registrar
The owner of the `addr.reverse` domain will be a registrar that permits the caller to take ownership of 
the reverse record for their own address. It provides the following methods:

### function claim(address owner) returns (bytes32 node)

When called by account `x`, instructs the ENS registry to transfer ownership of the name `hex(x) + &apos;.addr.reverse&apos;` to the provided address, and return the namehash of the ENS record thus transferred.

Allowing the caller to specify an owner other than themselves for the relevant node facilitates contracts that need accurate reverse ENS entries delegating this to their creators with a minimum of code inside their constructor:

    reverseRegistrar.claim(msg.sender)

### function claimWithResolver(address owner, address resolver) returns (bytes32 node)

When called by account `x`, instructs the ENS registry to set the resolver of the name `hex(x) + &apos;.addr.reverse&apos;` to the specified resolver, then transfer ownership of the name to the provided address, and return the namehash of the ENS record thus transferred. This method facilitates setting up a custom resolver and owner in fewer transactions than would be required if calling `claim`.

### function setName(string name) returns (bytes32 node)

When called by account `x`, sets the resolver for the name `hex(x) + &apos;.addr.reverse&apos;` to a default resolver, and sets the name record on that name to the specified name. This method facilitates setting up simple reverse records for users in a single transaction.

## Resolver interface
A new resolver interface is defined, consisting of the following method:

    function name(bytes32 node) constant returns (string);

Resolvers that implement this interface must return a valid ENS name for the requested node, or the empty string if no name is defined for the requested node.

The interface ID of this interface is 0x691f3431.

Future EIPs may specify more record types appropriate to reverse ENS records.

# Appendix 1: Registrar implementation

This registrar, written in Solidity, implements the specifications outlined above.

    pragma solidity ^0.4.10;

    import &quot;./AbstractENS.sol&quot;;

    contract Resolver {
        function setName(bytes32 node, string name) public;
    }

    /**
     * @dev Provides a default implementation of a resolver for reverse records,
     * which permits only the owner to update it.
     */
    contract DefaultReverseResolver is Resolver {
        AbstractENS public ens;
        mapping(bytes32=&gt;string) public name;

        /**
         * @dev Constructor
         * @param ensAddr The address of the ENS registry.
         */
        function DefaultReverseResolver(AbstractENS ensAddr) {
            ens = ensAddr;
        }

        /**
         * @dev Only permits calls by the reverse registrar.
         * @param node The node permission is required for.
         */
        modifier owner_only(bytes32 node) {
            require(msg.sender == ens.owner(node));
            _;
        }

        /**
         * @dev Sets the name for a node.
         * @param node The node to update.
         * @param _name The name to set.
         */
        function setName(bytes32 node, string _name) public owner_only(node) {
            name[node] = _name;
        }
    }

    contract ReverseRegistrar {
        // namehash(&apos;addr.reverse&apos;)
        bytes32 constant ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2;

        AbstractENS public ens;
        Resolver public defaultResolver;

        /**
         * @dev Constructor
         * @param ensAddr The address of the ENS registry.
         * @param resolverAddr The address of the default reverse resolver.
         */
        function ReverseRegistrar(AbstractENS ensAddr, Resolver resolverAddr) {
            ens = ensAddr;
            defaultResolver = resolverAddr;
        }

        /**
         * @dev Transfers ownership of the reverse ENS record associated with the
         *      calling account.
         * @param owner The address to set as the owner of the reverse record in ENS.
         * @return The ENS node hash of the reverse record.
         */
        function claim(address owner) returns (bytes32 node) {
            return claimWithResolver(owner, 0);
        }

        /**
         * @dev Transfers ownership of the reverse ENS record associated with the
         *      calling account.
         * @param owner The address to set as the owner of the reverse record in ENS.
         * @param resolver The address of the resolver to set; 0 to leave unchanged.
         * @return The ENS node hash of the reverse record.
         */
        function claimWithResolver(address owner, address resolver) returns (bytes32 node) {
            var label = sha3HexAddress(msg.sender);
            node = sha3(ADDR_REVERSE_NODE, label);
            var currentOwner = ens.owner(node);

            // Update the resolver if required
            if(resolver != 0 &amp;&amp; resolver != ens.resolver(node)) {
                // Transfer the name to us first if it&apos;s not already
                if(currentOwner != address(this)) {
                    ens.setSubnodeOwner(ADDR_REVERSE_NODE, label, this);
                    currentOwner = address(this);
                }
                ens.setResolver(node, resolver);
            }

            // Update the owner if required
            if(currentOwner != owner) {
                ens.setSubnodeOwner(ADDR_REVERSE_NODE, label, owner);
            }

            return node;
        }

        /**
         * @dev Sets the `name()` record for the reverse ENS record associated with
         * the calling account. First updates the resolver to the default reverse
         * resolver if necessary.
         * @param name The name to set for this address.
         * @return The ENS node hash of the reverse record.
         */
        function setName(string name) returns (bytes32 node) {
            node = claimWithResolver(this, defaultResolver);
            defaultResolver.setName(node, name);
            return node;
        }

        /**
         * @dev Returns the node hash for a given account&apos;s reverse records.
         * @param addr The address to hash
         * @return The ENS node hash.
         */
        function node(address addr) constant returns (bytes32 ret) {
            return sha3(ADDR_REVERSE_NODE, sha3HexAddress(addr));
        }

        /**
         * @dev An optimised function to compute the sha3 of the lower-case
         *      hexadecimal representation of an Ethereum address.
         * @param addr The address to hash
         * @return The SHA3 hash of the lower-case hexadecimal encoding of the
         *         input address.
         */
        function sha3HexAddress(address addr) private returns (bytes32 ret) {
            addr; ret; // Stop warning us about unused variables
            assembly {
                let lookup := 0x3031323334353637383961626364656600000000000000000000000000000000
                let i := 40
            loop:
                i := sub(i, 1)
                mstore8(i, byte(and(addr, 0xf), lookup))
                addr := div(addr, 0x10)
                i := sub(i, 1)
                mstore8(i, byte(and(addr, 0xf), lookup))
                addr := div(addr, 0x10)
                jumpi(loop, i)
                ret := sha3(0, 40)
            }
        }
    }

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 01 Dec 2016 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-181</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-181</guid>
      </item>
    
      <item>
        <title>Ethereum Smart Contract Packaging Standard</title>
        <category>Standards Track/ERC</category>
        
        <description># Abstract

This ERC proposes a specification for Ethereum smart contract packages.  

The specification was collaboratively developed by the following Ethereum development framework maintainers.

* Tim Coulter (Truffle)
* Denis Erfurt (Dapple)
* Piper Merriam (Populus)
* RJ Catalano (Eris PM)
* Iuri Matias (Embark)

# Motivation

Packaging is a core piece of modern software development which is missing from the Ethereum ecosystem.  The lack of packaging limits the ability for developers to reuse code which negatively affects productivity and security.

A key example of this is the ERC20 standard.  There are a few well audited reusable token contracts available but most developers end up writing their own because of the difficulty in finding and reusing existing code.

A packaging standard should have the following positive effects on the ecosystem:

* Greater overall productivity caused by the ability to reuse existing code.
* Increased security caused by the ability to reuse existing well audited implementations of common patterns (ERC20, crowdfunding, etc).

Smart contract packaging should also have a direct positive effect on the end user.  Wallet software will be able to consume a released package and generate an interface for interacting with any deployed contracts included within that package.  With the advent of [ENS](/EIPs/EIPS/eip-137) all of the pieces will be in place for a wallet to take a human readable name and present the user with an interface for interacting with the underlying application.


# Specification

The full specification for this standard is maintained separately in the repository [epm/epm-spec](https://github.com/ethpm/epm-spec).

This EIP refers to the `1.0.0` version of the specification: [https://github.com/ethpm/epm-spec/tree/v1.0.0](https://github.com/ethpm/epm-spec/tree/v1.0.0)

The specification contains details for a single document referred to as a *&quot;Release Lockfile&quot;*.  

* Release Lockfile Specification: [https://github.com/ethpm/epm-spec/blob/v1.0.0/release-lockfile.spec.md](https://github.com/ethpm/epm-spec/blob/v1.0.0/release-lockfile.spec.md).
* JSON Schema for Release Lockfile: [https://github.com/ethpm/epm-spec/blob/v1.0.0/spec/release-lockfile.spec.json](https://github.com/ethpm/epm-spec/blob/v1.0.0/spec/release-lockfile.spec.json)

&gt; These documents have not been inlined into this ERC to ensure that there is a single source of truth for the specification.


# Use Cases

This specification covers the following types of smart contract packages.

1. Packages with contracts intended to be used as base contract such as the common `owned` pattern.
2. Packages with contracts that are ready to use as-is such as an ERC20 token contract.
3. Packages with deployed contracts such as libraries or services.

Full explanations and examples of these use cases can be found in the [`README.md`](https://github.com/ethpm/epm-spec/blob/v1.0.0/README.md#use-cases) from the `epm/epm-spec` repository.


# Package Managers

The *Release Lockfile* is intended for consumption by package management software.  Specific care was made to ensure that all of the following functionality can be implemented by package managers.


## Deterministic builds

Ensures that a package will always resolve to the same set of dependencies and source files.  Both source files and dependencies are content addressed to ensure that the referenced resources cannot change.


## Bytecode verification

Contains the appropriate information for a package manager to inspect a deployed contract and verify that its bytecode matches the bytecode that results from compilation and linking of the package source code.


## Multi-chain deploys

Supports deployments across multiple chains, allowing a package to define addresses on both the public mainnet and testnet.


## Trusted packages

Allows for packages which exclude source code or other elements which would be needed for verification of the contract bytecode.  This allows for minimalistic packages to be created for special situations where the package manager will not be performing verification.


# Framework support and integration

Support for ERC190 is either implemented or in progress for the following:

* [Truffle](https://truffleframework.com/)
* [Populus](https://populus.readthedocs.io/en/latest/)
* [Dapple](https://dapple.readthedocs.io/en/master/)
* [Eris PM](https://github.com/eris-ltd/eris-cli)
* [Embark](https://github.com/iurimatias/embark-framework)
* [Browser Solidity](https://github.com/ethereum/remix-ide/issues/386)
</description>
        <pubDate>Tue, 10 Jan 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-190</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-190</guid>
      </item>
    
      <item>
        <title>Signed Data Standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/191</comments>
        
        <description># Abstract

This ERC proposes a specification about how to handle signed data in Ethereum contracts.

# Motivation

Several multisignature wallet implementations have been created which accepts `presigned` transactions. A `presigned` transaction is a chunk of binary `signed_data`, along with signature (`r`, `s` and `v`). The interpretation of the `signed_data` has not been specified, leading to several problems:

* Standard Ethereum transactions can be submitted as `signed_data`. An Ethereum transaction can be unpacked, into the following components: `RLP&lt;nonce, gasPrice, startGas, to, value, data&gt;` (hereby called `RLPdata`), `r`, `s` and `v`. If there are no syntactical constraints on `signed_data`, this means that `RLPdata` can be used as a syntactically valid `presigned` transaction.
* Multisignature wallets have also had the problem that a `presigned` transaction has not been tied to a particular `validator`, i.e a specific wallet. Example:
    1. Users `A`, `B` and `C` have the `2/3`-wallet `X`
    2. Users `A`, `B` and `D` have the `2/3`-wallet `Y`
    3. User `A` and `B` submit `presigned` transactions to `X`.
    4. Attacker can now reuse their presigned transactions to `X`, and submit to `Y`.

## Specification

We propose the following format for `signed_data`

```
0x19 &lt;1 byte version&gt; &lt;version specific data&gt; &lt;data to sign&gt;.
```

The initial `0x19` byte is intended to ensure that the `signed_data` is not valid RLP.

&gt; For a single byte whose value is in the [0x00, 0x7f] range, that byte is its own RLP encoding.

That means that any `signed_data` cannot be one RLP-structure, but a 1-byte `RLP` payload followed by something else. Thus, any EIP-191 `signed_data` can never be an Ethereum transaction.

Additionally, `0x19` has been chosen because since ethereum/go-ethereum#2940 , the following is prepended before hashing in personal_sign:

```
&quot;\x19Ethereum Signed Message:\n&quot; + len(message).
```

Using `0x19` thus makes it possible to extend the scheme by defining a version `0x45` (`E`) to handle these kinds of signatures.

### Registry of version bytes

| Version byte | EIP            | Description
| ------------ | -------------- | -----------
|    `0x00`    | [191][eip-191] | Data with intended validator
|    `0x01`    | [712][eip-712] | Structured data
|    `0x45`    | [191][eip-191] | `personal_sign` messages

#### Version `0x00`

```
0x19 &lt;0x00&gt; &lt;intended validator address&gt; &lt;data to sign&gt;
```

The version `0x00` has `&lt;intended validator address&gt;` for the version specific data. In the case of a Multisig wallet that perform an execution based on a passed signature, the validator address is the address of the Multisig itself. The data to sign could be any arbitrary data.

#### Version `0x01`

The version `0x01` is for structured data as defined in [EIP-712]

#### Version `0x45` (E)

```
0x19 &lt;0x45 (E)&gt; &lt;thereum Signed Message:\n&quot; + len(message)&gt; &lt;data to sign&gt;
```

The version `0x45` (E) has `&lt;thereum Signed Message:\n&quot; + len(message)&gt;` for the version-specific data. The data to sign can be any arbitrary data.

&gt; NB: The `E` in `Ethereum Signed Message` refers to the version byte 0x45. The character `E` is `0x45` in hexadecimal which makes the remainder, `thereum Signed Message:\n + len(message)`, the version-specific data.

[EIP-191]: /EIPs/EIPS/eip-191

[EIP-712]: /EIPs/EIPS/eip-712

### Example

The following snippets has been written in Solidity 0.8.0.

#### Version `0x00`

```solidity
function signatureBasedExecution(address target, uint256 nonce, bytes memory payload, uint8 v, bytes32 r, bytes32 s) public payable {
        
    // Arguments when calculating hash to validate
    // 1: byte(0x19) - the initial 0x19 byte
    // 2: byte(0) - the version byte
    // 3: address(this) - the validator address
    // 4-6 : Application specific data

    bytes32 hash = keccak256(abi.encodePacked(byte(0x19), byte(0), address(this), msg.value, nonce, payload));

    // recovering the signer from the hash and the signature
    addressRecovered = ecrecover(hash, v, r, s);
   
    // logic of the wallet
    // if (addressRecovered == owner) executeOnTarget(target, payload);
}
```
## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 20 Jan 2016 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-191</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-191</guid>
      </item>
    
      <item>
        <title>Precompiled contracts for addition and scalar multiplication on the elliptic curve alt_bn128</title>
        <category>Standards Track/Core</category>
        
        <description>## Simple Summary

Precompiled contracts for elliptic curve operations are required in order to perform zkSNARK verification within the block gas limit.

## Abstract

This EIP suggests to add precompiled contracts for addition and scalar multiplication on a specific pairing-friendly elliptic curve. This can in turn be combined with [EIP-197](/EIPs/EIPS/eip-197) to verify zkSNARKs in Ethereum smart contracts. The general benefit of zkSNARKs for Ethereum is that it will increase the privacy for users (because of the Zero-Knowledge property) and might also be a scalability solution (because of the succinctness and efficient verifiability property).

## Motivation

Current smart contract executions on Ethereum are fully transparent, which makes them unsuitable for several use-cases that involve private information like the location, identity or history of past transactions. The technology of zkSNARKs could be a solution to this problem. While the Ethereum Virtual Machine can make use of zkSNARKs in theory, they are currently too expensive
to fit the block gas limit. Because of that, this EIP proposes to specify certain parameters for some elementary primitives that enable zkSNARKs so that they can be implemented more efficiently and the gas cost be reduced.

Note that while fixing these parameters might look like limiting the use-cases for zkSNARKs, the primitives are so basic that they can be combined in ways that are flexible enough so that it should even be possible to allow future advances in zkSNARK research without the need for a further hard fork.

## Specification

If `block.number &gt;= BYZANTIUM_FORK_BLKNUM`, add precompiled contracts for point addition (ADD)  and scalar multiplication (MUL) on the elliptic curve &quot;alt_bn128&quot;.

Address of ADD: 0x6
Address for MUL: 0x7

The curve is defined by:
```
Y^2 = X^3 + 3
over the field F_p with
p = 21888242871839275222246405745257275088696311157297823662689037894645226208583
```

### Encoding

Field elements and scalars are encoded as 32 byte big-endian numbers. Curve points are encoded as two field elements `(x, y)`, where the point at infinity is encoded as `(0, 0)`.

Tuples of objects are encoded as their concatenation.

For both precompiled contracts, if the input is shorter than expected, it is assumed to be virtually padded with zeros at the end (i.e. compatible with the semantics of the `CALLDATALOAD` opcode). If the input is longer than expected, surplus bytes at the end are ignored.

The length of the returned data is always as specified (i.e. it is not &quot;unpadded&quot;).

### Exact semantics

Invalid input: For both contracts, if any input point does not lie on the curve or any of the field elements (point coordinates) is equal or larger than the field modulus p, the contract fails. The scalar can be any number between `0` and `2**256-1`.

#### ADD
Input: two curve points `(x, y)`.
Output: curve point `x + y`, where `+` is point addition on the elliptic curve `alt_bn128` specified above.
Fails on invalid input and consumes all gas provided.

#### MUL
Input: curve point and scalar `(x, s)`.
Output: curve point `s * x`, where `*` is the scalar multiplication on the elliptic curve `alt_bn128` specified above.
Fails on invalid input and consumes all gas.

### Gas costs

 - Gas cost for ``ECADD``: 500
 - Gas cost for ``ECMUL``: 40000

## Rationale

The specific curve `alt_bn128` was chosen because it is particularly well-suited for zkSNARKs, or, more specifically their verification building block of pairing functions. Furthermore, by choosing this curve, we can use synergy effects with ZCash and re-use some of their components and artifacts.

The feature of adding curve and field parameters to the inputs was considered but ultimately rejected since it complicates the specification: The gas costs are much harder to determine and it would be possible to call the contracts on something which is not an actual elliptic curve.

A non-compact point encoding was chosen since it still allows to perform some operations in the smart contract itself (inclusion of the full y coordinate) and two encoded points can be compared for equality (no third projective coordinate).

## Backwards Compatibility

As with the introduction of any precompiled contract, contracts that already use the given addresses will change their semantics. Because of that, the addresses are taken from the &quot;reserved range&quot; below 256.

## Test Cases

Inputs to test:

 - Curve points which would be valid if the numbers were taken mod p (should fail).
 - Both contracts should succeed on empty input.
 - Truncated input that results in a valid curve point.
 - Points not on curve (but valid otherwise).
 - Multiply point with scalar that lies between the order of the group and the field (should succeed).
 - Multiply point with scalar that is larger than the field order (should succeed).

## Implementation

Implementation of these primitives are available here:

 - [libff](https://github.com/scipr-lab/libff/blob/master/libff/algebra/curves/alt_bn128/alt_bn128_g1.cpp) (C++)
 - [bn](https://github.com/zcash/bn/blob/master/src/groups/mod.rs) (Rust)

In both codebases, a specific group on the curve alt_bn128 is used and is called G1.

 - [Python](https://github.com/ethereum/py_pairing/blob/master/py_ecc/bn128/bn128_curve.py) - probably most self-contained and best readable.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 02 Feb 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-196</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-196</guid>
      </item>
    
      <item>
        <title>Precompiled contracts for optimal ate pairing check on the elliptic curve alt_bn128</title>
        <category>Standards Track/Core</category>
        
        <description>## Simple Summary

Precompiled contracts for elliptic curve pairing operations are required in order to perform zkSNARK verification within the block gas limit.

## Abstract

This EIP suggests to add precompiled contracts for a pairing function on a specific pairing-friendly elliptic curve. This can in turn be combined with [EIP-196](/EIPs/EIPS/eip-196) to verify zkSNARKs in Ethereum smart contracts. The general benefit of zkSNARKs for Ethereum is that it will increase the privacy for users (because of the Zero-Knowledge property) and might also be a scalability solution (because of the succinctness and efficient verifiability property).

## Motivation

Current smart contract executions on Ethereum are fully transparent, which makes them unsuitable for several use-cases that involve private information like the location, identity or history of past transactions. The technology of zkSNARKs could be a solution to this problem. While the Ethereum Virtual Machine can make use of zkSNARKs in theory, they are currently too expensive
to fit the block gas limit. Because of that, this EIP proposes to specify certain parameters for some elementary primitives that enable zkSNARKs so that they can be implemented more efficiently and the gas cost be reduced.

Note that fixing these parameters will in no way limit the use-cases for zkSNARKs, it will even allow for incorporating some advances in zkSNARK research without the need for a further hard fork.

Pairing functions can be used to perform a limited form of multiplicatively homomorphic operations, which are necessary for current zkSNARKs. This precompile can be used to run such computations within the block gas limit. This precompiled contract only specifies a certain check, and not an evaluation of a pairing function. The reason is that the codomain of a pairing function is a rather complex field which could provide encoding problems and all known uses of pairing function in zkSNARKs only require the specified check.

## Specification

For blocks where `block.number &gt;= BYZANTIUM_FORK_BLKNUM`, add a precompiled contracts for a bilinear function on groups on the elliptic curve &quot;alt_bn128&quot;. We will define the precompiled contract in terms of a discrete logarithm. The discrete logarithm is of course assumed to be hard to compute, but we will give an equivalent specification that makes use of elliptic curve pairing functions which can be efficiently computed below.

Address: 0x8

For a cyclic group `G` (written additively) of prime order `q` let `log_P: G -&gt; F_q` be the discrete logarithm on this group with respect to a generator `P`, i.e. `log_P(x)` is the smallest non-negative integer `n` such that `n * P = x`.

The precompiled contract is defined as follows, where the two groups `G_1` and `G_2` are defined by their generators `P_1` and `P_2` below. Both generators have the same prime order `q`.

```
Input: (a1, b1, a2, b2, ..., ak, bk) from (G_1 x G_2)^k
Output: If the length of the input is incorrect or any of the inputs are not elements of
        the respective group or are not encoded correctly, the call fails.
        Otherwise, return one if
        log_P1(a1) * log_P2(b1) + ... + log_P1(ak) * log_P2(bk) = 0
        (in F_q) and zero else.
```

Note that `k` is determined from the length of the input. Following the section on the encoding below,
`k` is the length of the input divided by `192`. If the input length is not a multiple of `192`,
the call fails. Empty input is valid and results in returning one.

In order to check that an input is an element of `G_1`, verifying the encoding of the coordinates and checking that they satisfy the curve equation (or is the encoding of infinity) is sufficient. For `G_2`, in addition to that, the order of the element has to be checked to be equal to the group order `q = 21888242871839275222246405745257275088548364400416034343698204186575808495617`.

### Definition of the groups

The groups `G_1` and `G_2` are cyclic groups of prime order `q = 21888242871839275222246405745257275088548364400416034343698204186575808495617`.

The group `G_1` is defined on the curve `Y^2 = X^3 + 3` over the field `F_p` with `p = 21888242871839275222246405745257275088696311157297823662689037894645226208583` with generator `P1 = (1, 2)`.

The group `G_2` is defined on the curve `Y^2 = X^3 + 3/(i+9)` over a different field `F_p^2 = F_p[i] / (i^2 + 1)` (p is the same as above) with generator
```
P2 = (
  11559732032986387107991004021392285783925812861821192530917403151452391805634 * i +
  10857046999023057135944570762232829481370756359578518086990519993285655852781,
  4082367875863433681332203403145435568316851327593401208105741076214120093531 * i +
  8495653923123431417604973247489272438418190587263600148770280649306958101930
)
```

Note that `G_2` is the only group of order `q` of that elliptic curve over the field `F_p^2`. Any other generator of order `q` instead of `P2` would define the same `G_2`. However, the concrete value of `P2` is useful for skeptical readers who doubt the existence of a group of order `q`. They can be instructed to compare the concrete values of `q * P2` and `P2`.


### Encoding

Elements of `F_p` are encoded as 32 byte big-endian numbers. An encoding value of `p` or larger is invalid.

Elements `a * i + b` of `F_p^2` are encoded as two elements of `F_p`, `(a, b)`.

Elliptic curve points are encoded as a Jacobian pair `(X, Y)` where the point at infinity is encoded as `(0, 0)`.

Note that the number `k` is derived from the input length.

The length of the returned data is always exactly 32 bytes and encoded as a 32 byte big-endian number.

### Gas costs

The gas costs of the precompiled contract are `80 000 * k + 100 000`, where `k` is the number of
points or, equivalently, the length of the input divided by 192.

## Rationale

The specific curve `alt_bn128` was chosen because it is particularly well-suited for zkSNARKs, or, more specifically their verification building block of pairing functions. Furthermore, by choosing this curve, we can use synergy effects with ZCash and re-use some of their components and artifacts.

The feature of adding curve and field parameters to the inputs was considered but ultimately rejected since it complicates the specification; the gas costs are much harder to determine and it would be possible to call the contracts on something which is not an actual elliptic curve or does not admit an efficient pairing implementation.

A non-compact point encoding was chosen since it still allows to perform some operations in the smart contract itself (inclusion of the full y coordinate) and two encoded points can be compared for equality (no third projective coordinate).

The encoding of field elements in `F_p^2` was chosen in this order to be in line with the big endian encoding of the elements themselves.

## Backwards Compatibility

As with the introduction of any precompiled contract, contracts that already use the given addresses will change their semantics. Because of that, the addresses are taken from the &quot;reserved range&quot; below 256.

## Test Cases

To be written.

## Implementation

The precompiled contract can be implemented using elliptic curve pairing functions, more specifically, an optimal ate pairing on the alt_bn128 curve, which can be implemented efficiently. In order to see that, first note that a pairing function `e: G_1 x G_2 -&gt; G_T` fulfills the following properties (`G_1` and `G_2` are written additively, `G_T` is written multiplicatively):

(1) `e(m * P1, n * P2) = e(P1, P2)^(m * n)`
(2) `e` is non-degenerate

Now observe that
```
log_P1(a1) * log_P2(b1) + ... + log_P1(ak) * log_P2(bk) = 0 (in F_q)
```
if and only if
```
e(P1, P2)^(log_P1(a1) * log_P2(b1) + ... + log_P1(ak) * log_P2(bk)) = 1 (in G_T)
```

Furthermore, the left hand side of this equation is equal to
```
e(log_P1(a1) * P1, log_P2(b1) * P2) * ... * e(log_P1(ak) * P1, log_P2(bk) * P2)
= e(a1, b1) * ... * e(ak, bk)
```

And thus, the precompiled contract can be implemented by verifying that
`e(a1, b1) * ... * e(ak, bk) = 1`

Implementations are available here:

 - [libff](https://github.com/scipr-lab/libff/blob/master/libff/algebra/curves/alt_bn128/alt_bn128_g1.hpp) (C++)
 - [bn](https://github.com/zcash/bn/blob/master/src/groups/mod.rs) (Rust)
 - [Python](https://github.com/ethereum/py_pairing/blob/master/py_ecc/bn128/bn128_pairing.py)

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 06 Feb 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-197</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-197</guid>
      </item>
    
      <item>
        <title>Big integer modular exponentiation</title>
        <category>Standards Track/Core</category>
        
        <description># Parameters

* `GQUADDIVISOR: 20`

# Specification

At address 0x00......05, add a precompile that expects input in the following format:

    &lt;length_of_BASE&gt; &lt;length_of_EXPONENT&gt; &lt;length_of_MODULUS&gt; &lt;BASE&gt; &lt;EXPONENT&gt; &lt;MODULUS&gt;
    
Where every length is a 32-byte left-padded integer representing the number of bytes to be taken up by the next value. Call data is assumed to be infinitely right-padded with zero bytes, and excess data is ignored. Consumes `floor(mult_complexity(max(length_of_MODULUS, length_of_BASE)) * max(ADJUSTED_EXPONENT_LENGTH, 1) / GQUADDIVISOR)` gas, and if there is enough gas, returns an output `(BASE**EXPONENT) % MODULUS` as a byte array with the same length as the modulus.

`ADJUSTED_EXPONENT_LENGTH` is defined as follows.

* If `length_of_EXPONENT &lt;= 32`, and all bits in `EXPONENT` are 0, return 0
* If `length_of_EXPONENT &lt;= 32`, then return the index of the highest bit in `EXPONENT` (eg. 1 -&gt; 0, 2 -&gt; 1, 3 -&gt; 1, 255 -&gt; 7, 256 -&gt; 8).
* If `length_of_EXPONENT &gt; 32`, then return `8 * (length_of_EXPONENT - 32)` plus the index of the highest bit in the first 32 bytes of `EXPONENT` (eg. if `EXPONENT = \x00\x00\x01\x00.....\x00`, with one hundred bytes, then the result is 8 * (100 - 32) + 253 = 797). If all of the first 32 bytes of `EXPONENT` are zero, return exactly `8 * (length_of_EXPONENT - 32)`.

`mult_complexity` is a function intended to approximate the difficulty of Karatsuba multiplication (used in all major bigint libraries) and is defined as follows.

```
def mult_complexity(x):
    if x &lt;= 64: return x ** 2
    elif x &lt;= 1024: return x ** 2 // 4 + 96 * x - 3072
    else: return x ** 2 // 16 + 480 * x - 199680
```

For example, the input data:

    0000000000000000000000000000000000000000000000000000000000000001
    0000000000000000000000000000000000000000000000000000000000000020
    0000000000000000000000000000000000000000000000000000000000000020
    03
    fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e
    fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
    
Represents the exponent `3**(2**256 - 2**32 - 978) % (2**256 - 2**32 - 977)`. By Fermat&apos;s little theorem, this equals 1, so the result is:

    0000000000000000000000000000000000000000000000000000000000000001
    
Returned as 32 bytes because the modulus length was 32 bytes. The `ADJUSTED_EXPONENT_LENGTH` would be 255, and the gas cost would be `mult_complexity(32) * 255 / 20 = 13056` gas (note that this is ~8 times the cost of using the EXP opcode to compute a 32-byte exponent). A 4096-bit RSA exponentiation would cost `mult_complexity(512) * 4095 / 100 = 22853376` gas in the worst case, though RSA verification in practice usually uses an exponent of 3 or 65537, which would reduce the gas consumption to 5580 or 89292, respectively.

This input data:

    0000000000000000000000000000000000000000000000000000000000000000
    0000000000000000000000000000000000000000000000000000000000000020
    0000000000000000000000000000000000000000000000000000000000000020
    fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e
    fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
    
Would be parsed as a base of 0, exponent of `2**256 - 2**32 - 978` and modulus of `2**256 - 2**32 - 977`, and so would return 0. Notice how if the length_of_BASE is 0, then it does not interpret _any_ data as the base, instead immediately interpreting the next 32 bytes as EXPONENT.

This input data:

    0000000000000000000000000000000000000000000000000000000000000000
    0000000000000000000000000000000000000000000000000000000000000020
    ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
    fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
    fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd
    
Would parse a base length of 0, an exponent length of 32, and a modulus length of `2**256 - 1`, where the base is empty, the exponent is `2**256 - 2` and the modulus is `(2**256 - 3) * 256**(2**256 - 33)` (yes, that&apos;s a really big number). It would then immediately fail, as it&apos;s not possible to provide enough gas to make that computation.

This input data:

    0000000000000000000000000000000000000000000000000000000000000001
    0000000000000000000000000000000000000000000000000000000000000002
    0000000000000000000000000000000000000000000000000000000000000020
    03
    ffff
    8000000000000000000000000000000000000000000000000000000000000000
    07

Would parse as a base of 3, an exponent of 65535, and a modulus of `2**255`, and it would ignore the remaining 0x07 byte.

This input data:

    0000000000000000000000000000000000000000000000000000000000000001
    0000000000000000000000000000000000000000000000000000000000000002
    0000000000000000000000000000000000000000000000000000000000000020
    03
    ffff
    80
    
Would also parse as a base of 3, an exponent of 65535 and a modulus of `2**255`, as it attempts to grab 32 bytes for the modulus starting from 0x80 - but there is no further data, so it right-pads it with 31 zero bytes.

# Rationale

This allows for efficient RSA verification inside of the EVM, as well as other forms of number theory-based cryptography. Note that adding precompiles for addition and subtraction is not required, as the in-EVM algorithm is efficient enough, and multiplication can be done through this precompile via `a * b = ((a + b)**2 - (a - b)**2) / 4`.

The bit-based exponent calculation is done specifically to fairly charge for the often-used exponents of 2 (for multiplication) and 3 and 65537 (for RSA verification).

# Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 30 Jan 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-198</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-198</guid>
      </item>
    
      <item>
        <title>ENS support for contract ABIs</title>
        <category>Standards Track/ERC</category>
        
        <description>## Simple Summary
This EIP proposes a mechanism for storing ABI definitions in ENS, for easy lookup of contract interfaces by callers.

## Abstract
ABIs are important metadata required for interacting with most contracts. At present, they are typically supplied out-of-band, which adds an additional burden to interacting with contracts, particularly on a one-off basis or where the ABI may be updated over time. The small size of ABIs permits an alternative solution, storing them in ENS, permitting name lookup and ABI discovery via the same process.

ABIs are typically quite compact; the largest in-use ABI we could find, that for the DAO, is 9450 bytes uncompressed JSON, 6920 bytes uncompressed CBOR, and 1128 bytes when the JSON form is compressed with zlib. Further gains on CBOR encoding are possible using a CBOR extension that permits eliminating repeated strings, which feature extensively in ABIs. Most ABIs, however, are far shorter than this, consisting of only a few hundred bytes of uncompressed JSON.

This EIP defines a resolver profile for retrieving contract ABIs, as well as encoding standards for storing ABIs for different applications, allowing the user to select between different representations based on their need for compactness and other considerations such as onchain access.

## Specification
### ABI encodings
In order to allow for different tradeoffs between onchain size and accessibility, several ABI encodings are defined. Each ABI encoding is defined by a unique constant with only a single bit set, allowing for the specification of 256 unique encodings in a single uint.

The currently recognised encodings are:

| ID | Description          |
|----|----------------------|
| 1  | JSON                 |
| 2  | zlib-compressed JSON |
| 4  | CBOR                 |
| 8  | URI                  |

This table may be extended in future through the EIP process.

Encoding type 1 specifies plaintext JSON, uncompressed; this is the standard format in which ABIs are typically encoded, but also the bulkiest, and is not easily parseable onchain.

Encoding type 2 specifies zlib-compressed JSON. This is significantly smaller than uncompressed JSON, and is straightforward to decode offchain. However, it is impracticalfor onchain consumers to use.

Encoding type 4 is [CBOR](https://cbor.io/). CBOR is a binary encoding format that is a superset of JSON, and is both more compact and easier to parse in limited environments such as the EVM. Consumers that support CBOR are strongly encouraged to also support the [stringref extension](http://cbor.schmorp.de/stringref) to CBOR, which provides significant additional reduction in encoded size.

Encoding type 8 indicates that the ABI can be found elsewhere, at the specified URI. This is typically the most compact of the supported forms, but also adds external dependencies for implementers. The specified URI may use any schema, but HTTP, IPFS, and Swarm are expected to be the most common.

### Resolver profile
A new resolver interface is defined, consisting of the following method:

    function ABI(bytes32 node, uint256 contentType) constant returns (uint256, bytes);

The interface ID of this interface is 0x2203ab56.

contentType is a bitfield, and is the bitwise OR of all the encoding types the caller will accept. Resolvers that implement this interface must return an ABI encoded using one of the requested formats, or `(0, &quot;&quot;)` if they do not have an ABI for this function, or do not support any of the requested formats.

The `abi` resolver profile is valid on both forward and reverse records.

### ABI lookup process

When attempting to fetch an ABI based on an ENS name, implementers should first attempt an ABI lookup on the name itself. If that lookup returns no results, they should attempt a reverse lookup on the Ethereum address the name resolves to.

Implementers should support as many of the ABI encoding formats as practical.

## Rationale

Storing ABIs onchain avoids the need to introduce additional dependencies for applications wishing to fetch them, such as swarm or HTTP access. Given the typical compactness of ABIs, we believe this is a worthwhile tradeoff in many cases.

The two-step resolution process permits different names to provide different ABIs for the same contract, such as in the case where it&apos;s useful to provide a minimal ABI to some callers, as well as specifying ABIs for contracts that did not specify one of their own. The fallback to looking up an ABI on the reverse record permits contracts to specify their own canonical ABI, and prevents the need for duplication when multiple names reference the same contract without the need for different ABIs.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 06 Feb 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-205</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-205</guid>
      </item>
    
      <item>
        <title>Blockhash refactoring</title>
        <category>Standards Track/Core</category>
        
        <description>### Summary

Stores blockhashes in the state, reducing the protocol complexity and the need for client implementation complexity in order to process the BLOCKHASH opcode. Also extends the range of how far back blockhash checking can go, with the side effect of creating direct links between blocks with very distant block numbers, facilitating much more efficient initial light client syncing.

### Parameters

* `CONSTANTINOPLE_FORK_BLKNUM`: TBD
* `SUPER_USER`: 2**160 - 2
* `BLOCKHASH_CONTRACT_ADDR`: 0xf0 (ie. 240)
* `BLOCKHASH_CONTRACT_CODE`: see below

### Specification

If `block.number == CONSTANTINOPLE_FORK_BLKNUM`, then when processing the block, before processing any transactions set the code of BLOCKHASH_CONTRACT_ADDR to BLOCKHASH_CONTRACT_CODE.

If `block.number &gt;= CONSTANTINOPLE_FORK_BLKNUM`, then when processing a block, before processing any transactions execute a call with the parameters:

* `SENDER`: SUPER_USER
* `GAS`: 1000000
* `TO`: BLOCKHASH_CONTRACT_ADDR
* `VALUE`: 0
* `DATA`: &amp;lt;32 bytes corresponding to the block&apos;s prevhash&amp;gt;

If `block.number &gt;= CONSTANTINOPLE_FORK_BLKNUM + 256`, then the BLOCKHASH opcode instead returns the result of executing a call (NOT a transaction) with the parameters:

* `SENDER`: &amp;lt;account from which the opcode was called&amp;gt;
* `GAS`: 1000000
* `TO`: BLOCKHASH_CONTRACT_ADDR
* `VALUE`: 0
* `DATA`: 32 byte zero-byte-leftpadded integer representing the stack argument with which the opcode was called

Also, for blocks where `block.number &gt;= CONSTANTINOPLE_FORK_BLKNUM`, the gas cost is increased from 20 to 800 to reflect the higher costs of processing the algorithm in the contract code.

### BLOCKHASH_CONTRACT_CODE

The Serpent source code is:

```python
with offset = 0:
    if msg.sender == 0xfffffffffffffffffffffffffffffffffffffffe:
        with bn = block.number - 1:
            while bn:
                ~sstore(offset + ~mod(bn, 256), ~calldataload(0))
                if ~mod(bn, 256):
                    ~stop()
                bn = ~div(bn, 256)
                offset += 256
    elif ~calldataload(0) &gt;= 0 and ~calldataload(0) &lt; block.number:
        with tbn = ~calldataload(0):
            with dist_minus_one = block.number - tbn - 1:
                while dist_minus_one &gt;= 256 &amp;&amp; ~mod(tbn, 256) == 0:
                    offset += 256
                    tbn = ~div(tbn, 256) 
                    dist_minus_one = ~div(dist_minus_one, 256)
                if dist_minus_one &gt;= 256:
                    return(0)
                return(~sload(offset + ~mod(tbn, 256)))
    else:
        return(0)
```

The EVM init code is:

```
0x6100f58061000e60003961010356600073fffffffffffffffffffffffffffffffffffffffe33141561005857600143035b801561005257600035610100820683015561010081061561003f57005b6101008104905061010082019150610022565b506100f3565b600060003512151561006e574360003512610071565b60005b156100e7576000356001814303035b6101008112151561009857600061010083061461009b565b60005b156100ba57610100830192506101008204915061010081049050610080565b610100811215156100d057600060a052602060a0f35b610100820683015460c052602060c0f350506100f2565b600060e052602060e0f35b5b505b6000f3
```

The EVM bytecode that the contract code should be set to is:

```
0x600073fffffffffffffffffffffffffffffffffffffffe33141561005857600143035b801561005257600035610100820683015561010081061561003f57005b6101008104905061010082019150610022565b506100f3565b600060003512151561006e574360003512610071565b60005b156100e7576000356001814303035b6101008112151561009857600061010083061461009b565b60005b156100ba57610100830192506101008204915061010081049050610080565b610100811215156100d057600060a052602060a0f35b610100820683015460c052602060c0f350506100f2565b600060e052602060e0f35b5b50
```

### Rationale

This removes the need for implementations to have an explicit way to look into historical block hashes, simplifying the protocol definition and removing a large component of the &quot;implied state&quot; (information that is technically state but is not part of the state tree) and thereby making the protocol more &quot;pure&quot;. Additionally, it allows blocks to directly point to blocks far behind them, which enables extremely efficient and secure light client protocols.
</description>
        <pubDate>Fri, 10 Feb 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-210</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-210</guid>
      </item>
    
      <item>
        <title>New opcodes: RETURNDATASIZE and RETURNDATACOPY</title>
        <category>Standards Track/Core</category>
        
        <description>## Simple Summary

A mechanism to allow returning arbitrary-length data inside the EVM has been requested for quite a while now. Existing proposals always had very intricate problems associated with charging gas. This proposal solves the same problem while at the same time, it has a very simple gas charging mechanism and requires minimal changes to the call opcodes. Its workings are very similar to the way calldata is handled already; after a call, return data is kept inside a virtual buffer from which the caller can copy it (or parts thereof) into memory. At the next call, the buffer is overwritten. This mechanism is 100% backwards compatible.

## Abstract

Please see summary.

## Motivation

In some situations, it is vital for a function to be able to return data whose length cannot be anticipated before the call. In principle, this can be solved without alterations to the EVM, for example by splitting the call into two calls where the first is used to compute only the size. All of these mechanisms, though, are very expensive in at least some situations. A very useful example of such a worst-case situation is a generic forwarding contract; a contract that takes call data, potentially makes some checks and then forwards it as is to another contract. The return data should of course be transferred in a similar way to the original caller. Since the contract is generic and does not know about the contract it calls, there is no way to determine the size of the output without adapting the called contract accordingly or trying a logarithmic number of calls.

Compiler implementors are advised to reserve a zero-length area for return data if the size of the return data is unknown before the call and then use `RETURNDATACOPY` in conjunction with `RETURNDATASIZE` to actually retrieve the data.

Note that this proposal also makes the EIP that proposes to allow to return data in case of an intentional state reversion ([EIP-140](/EIPs/EIPS/eip-140)) much more useful. Since the size of the failure data might be larger than the regular return data (or even unknown), it is possible to retrieve the failure data after the CALL opcode has signalled a failure, even if the regular output area is not large enough to hold the data.

## Specification

If `block.number &gt;= BYZANTIUM_FORK_BLKNUM`, add two new opcodes and amend the semantics of any opcode that creates a new call frame (like `CALL`, `CREATE`, `DELEGATECALL`, ...) called call-like opcodes in the following. It is assumed that the EVM (to be more specific: an EVM call frame) has a new internal buffer of variable size, called the return data buffer. This buffer is created empty for each new call frame. Upon executing any call-like opcode, the buffer is cleared (its size is set to zero). After executing a call-like opcode, the complete return data (or failure data, see [EIP-140](/EIPs/EIPS/eip-140)) of the call is stored in the return data buffer (of the caller), and its size changed accordingly. As an exception, `CREATE` and `CREATE2` are considered to return the empty buffer in the success case and the failure data in the failure case. If the call-like opcode is executed but does not really instantiate a call frame (for example due to insufficient funds for a value transfer or if the called contract does not exist), the return data buffer is empty.

As an optimization, it is possible to share the return data buffer across call frames because at most one will be non-empty at any time.

`RETURNDATASIZE`: `0x3d`

Pushes the size of the return data buffer onto the stack.
Gas costs: 2 (same as `CALLDATASIZE`)

`RETURNDATACOPY`: `0x3e`

This opcode has similar semantics to `CALLDATACOPY`, but instead of copying data from the call data, it copies data from the return data buffer. Furthermore, accessing the return data buffer beyond its size results in a failure; i.e. if `start + length` overflows or results in a value larger than `RETURNDATASIZE`, the current call stops in an out-of-gas condition. In particular, reading 0 bytes from the end of the buffer will read 0 bytes; reading 0 bytes from one-byte out of the buffer causes an exception.

Gas costs: `3 + 3 * ceil(amount / 32)` (same as `CALLDATACOPY`)

## Rationale

Other solutions that would allow returning dynamic data were considered, but they all had to deduct the gas from the call opcode and thus were both complicated to implement and specify ([5/8](https://github.com/ethereum/EIPs/issues/8)). Since this proposal is very similar to the way calldata is handled, it fits nicely into the concept. Furthermore, the eWASM architecture already handles return data in exactly the same way.

Note that the EVM implementation needs to keep the return data until the next call or the return from the current call. Since this resource was already paid for as part of the memory of the callee, it should not be a problem. Implementations may either choose to keep the full memory of the callee alive until the next call or copy only the return data to a special memory area.

Keeping the memory of the callee until the next call-like opcode does not increase the peak memory usage in the following sense; any memory allocation in the caller&apos;s frame that happens after the return from the call can be moved before the call without a change in gas costs, but will add this allocation to the peak allocation.

The number values of the opcodes were allocated in the same nibble block that also contains `CALLDATASIZE` and `CALLDATACOPY`.

## Backwards Compatibility

This proposal introduces two new opcodes and stays fully backwards compatible apart from that.

## Test Cases

## Implementation

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 13 Feb 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-211</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-211</guid>
      </item>
    
      <item>
        <title>New opcode STATICCALL</title>
        <category>Standards Track/Core</category>
        
        <description>## Simple Summary

To increase smart contract security, this proposal adds a new opcode that can be used to call another contract (or itself) while disallowing any modifications to the state during the call (and its subcalls, if present).

## Abstract

This proposal adds a new opcode that can be used to call another contract (or itself) while disallowing any modifications to the state during the call (and its subcalls, if present). Any opcode that attempts to perform such a modification (see below for details) will result in an exception instead of performing the modification.

## Motivation

Currently, there is no restriction about what a called contract can do, as long as the computation can be performed with the amount of gas provided. This poses certain difficulties about smart contract engineers; after a regular call, unless you know the called contract, you cannot make any assumptions about the state of the contracts. Furthermore, because you cannot know the order of transactions before they are confirmed by miners, not even an outside observer can be sure about that in all cases.

This EIP adds a way to call other contracts and restrict what they can do in the simplest way. It can be safely assumed that the state of all accounts is the same before and after a static call.

## Specification

Introduce a new `STATIC` flag to the virtual machine. This flag is set to `false` initially. Its value is always copied to sub-calls with an exception for the new opcode below.

Opcode: `0xfa`.

`STATICCALL` functions equivalently to a `CALL`, except it takes only 6 arguments (the &quot;value&quot; argument is not included and taken to be zero), and calls the child with the `STATIC` flag set to `true` for the execution of the child. Once this call returns, the flag is reset to its value before the call.

Any attempts to make state-changing operations inside an execution instance with `STATIC` set to `true` will instead throw an exception. These operations include `CREATE`, `CREATE2`, `LOG0`, `LOG1`, `LOG2`, `LOG3`, `LOG4`, `SSTORE`, and `SELFDESTRUCT`. They also include `CALL` with a non-zero value. As an exception, `CALLCODE` is not considered state-changing, even with a non-zero value.

## Rationale

This allows contracts to make calls that are clearly non-state-changing, reassuring developers and reviewers that re-entrancy bugs or other problems cannot possibly arise from that particular call; it is a pure function that returns an output and does nothing else. This may also make purely functional HLLs easier to implement.

## Backwards Compatibility

This proposal adds a new opcode but does not modify the behaviour of other opcodes and thus is backwards compatible for old contracts that do not use the new opcode and are not called via the new opcode.

## Test Cases

To be written.

## Implementation

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 13 Feb 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-214</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-214</guid>
      </item>
    
      <item>
        <title>Token with transaction handling model</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-223-token-standard/12894</comments>
        
        <description>## Abstract

The following describes an interface and logic for fungible tokens that supports a `tokenReceived` callback to notify contract recipients when tokens are received. This makes tokens behave identical to ether.

## Motivation

This token introduces a communication model for contracts that can be utilized to straighten the behavior of contracts that interact with such tokens. Specifically, this proposal:

1. Informs receiving contracts of incoming token transfers, as opposed to [ERC-20](/EIPs/EIPS/eip-20) where the recipient of a token transfer gets no notification.
2. Is more gas-efficient when depositing tokens to contracts.
3. Allows for `_data` recording for financial transfers.

## Specification

Contracts intending to receive these tokens MUST implement `tokenReceived`.

Token transfers to contracts not implementing `tokenReceived` as described below MUST revert.

### Token contract

#### Token Methods

##### `totalSupply`

```solidity
function totalSupply() view returns (uint256)
```

Returns the total supply of the token. The functionality of this method is identical to that of ERC-20.

##### `name`

```solidity
function name() view returns (string memory)
```

Returns the name of the token.  The functionality of this method is identical to that of ERC-20.

OPTIONAL - This method can be used to improve usability, but interfaces and other contracts MUST NOT expect these values to be present.

##### `symbol`

```solidity
function symbol() view returns (string memory)
```

Returns the symbol of the token. The functionality of this method is identical to that of ERC-20.

OPTIONAL - This method can be used to improve usability, but interfaces and other contracts MUST NOT expect these values to be present.

##### `decimals`

```solidity
function decimals() view returns (uint8)
```

Returns the number of decimals of the token. The functionality of this method is identical to that of ERC-20.

OPTIONAL - This method can be used to improve usability, but interfaces and other contracts MUST NOT expect these values to be present. 

##### `balanceOf`

```solidity
function balanceOf(address _owner) view returns (uint256)
```

Returns the account balance of another account with address `_owner`. The functionality of this method is identical to that of ERC-20.

##### `transfer(address, uint)`

```solidity
function transfer(address _to, uint _value) returns (bool)
```

This function must transfer tokens, and if `_to` is a contract, it must call the `tokenReceived(address, uint256, bytes calldata)` function of `_to`. If the `tokenReceived` function is not implemented in `_to` (recipient contract), then the transaction must fail and the transfer of tokens must be reverted.
If `_to` is an externally owned address, then the transaction must be sent without executing `tokenReceived` in `_to`.
 `_data` can be attached to this token transaction, but it requires more gas. `_data` can be empty.
 
The `tokenReceived` function of `_to` MUST be called after all other operations to avoid re-entrancy attacks.
 
NOTE: If `transfer` function is `payable` and ether was deposited then the amount of deposited ether MUST be delivered to `_to` address alongside tokens. If ether was sent alongside tokens in this way then ether MUST be delivered first, then token balances must be updated, then `tokenReceived` function MUST be called in `_to` if it is a contract.

##### `transfer(address, uint, bytes)`

```solidity
function transfer(address _to, uint _value, bytes calldata _data) returns (bool)
```

This function must transfer tokens and invoke the function `tokenReceived (address, uint256, bytes)` in `_to`, if `_to` is a contract. If the `tokenReceived` function is not implemented in `_to` (recipient contract), then the transaction must fail and the transfer of tokens must not occur. 
If `_to` is an externally owned address (determined by the code size being zero), then the transaction must be sent without executing `tokenReceived` in `_to`.
 `_data` can be attached to this token transaction, but it requires more gas. `_data` can be empty.

NOTE: A possible way to check whether the `_to` is a contract or an address is to assemble the code of `_to`. If there is no code in `_to`, then this is an externally owned address, otherwise it&apos;s a contract. If `transfer` function is `payable` and ether was deposited then the amount of deposited ether MUST be delivered to `_to` address alongside tokens.

The `tokenReceived` function of `_to` MUST be called after all other operations to avoid re-entrancy attacks.

#### Events

##### `Transfer`

```solidity
event Transfer(address indexed _from, address indexed _to, uint256 _value, bytes _data)
```

Triggered when tokens are transferred. Compatible with and similar to the ERC-20 `Transfer` event.

### [ERC-223](/EIPs/EIPS/eip-223) Token Receiver

#### Receiver Methods

```solidity
function tokenReceived(address _from, uint _value, bytes calldata _data) returns (bytes4)
```

A function for handling token transfers, which is called from the token contract, when a token holder sends tokens. `_from` is the address of the sender of the token, `_value` is the amount of incoming tokens, and `_data` is attached data similar to `msg.data` of ether transactions. It works by analogy with the fallback function of Ether transactions and returns nothing.

NOTE: `msg.sender` will be a token-contract inside the `tokenReceived` function. It may be important to filter which tokens were sent (by token-contract address). The token sender (the person who initiated the token transaction) will be `_from` inside the `tokenReceived` function. The `tokenReceived` function must return `0x8943ec02` after handling an incoming token transfer. The `tokenReceived` function call can be handled by the fallback function of the recipient contact (and in this case it may not return the magic value 0x8943ec02).

IMPORTANT: This function must be named `tokenReceived` and take parameters `address`, `uint256`, `bytes` to match the function signature `0x8943ec02`. This function can be manually called by a EOA.

## Rationale

This standard introduces a communication model by enforcing the `transfer` to execute a handler function in the destination address. This is an important security consideration as it is required that the receiver explicitly implements the token handling function. In cases where the receiver does not implements such function the transfer MUST be reverted.

This standard sticks to the push transaction model where the transfer of assets is initiated on the senders side and handled on the receivers side. As the result, ERC-223 transfers are more gas-efficient while dealing with depositing to contracts as ERC-223 tokens can be deposited with just one transaction while ERC-20 tokens require at least two calls (one for `approve` and the second that will invoke `transferFrom`).

- [ERC-20](/EIPs/EIPS/eip-20) deposit: `approve` ~46 gas, `transferFrom` ~75K gas

- ERC-223 deposit: `transfer` and handling on the receivers side ~54K gas

This standard introduces the ability to correct user errors by allowing to handle ANY transactions on the recipients side and reject incorrect or improper transfers. This tokens utilize ONE transferring method for both types of interactions with contracts and externally owned addresses which can simplify the user experience and allow to avoid possible user mistakes.

One downside of the commonly used [ERC-20](/EIPs/EIPS/eip-20) standard that ERC-223 is intended to solve is that [ERC-20](/EIPs/EIPS/eip-20) implements two methods of token transferring: (1) `transfer` function and (2) `approve + transferFrom` pattern. Transfer function of [ERC-20](/EIPs/EIPS/eip-20) standard does not notify the receiver and therefore if any tokens are sent to a contract with the `transfer` function then the receiver will not recognize this transfer and the tokens can become stuck in the receivers address without any possibility of recovering them. [ERC-20](/EIPs/EIPS/eip-20) standard places the burden of determining the transferring method on the user and if the incorrect method is chosen the user can lose the transferred tokens. ERC-223 automatically determines the transferring method, preventing the user from losing tokens due to choosing wrong method.

ERC-223 is intended to simplify the interaction with contracts that are intended to work with tokens. ERC-223 utilizes a &quot;deposit&quot; pattern, similar to that of plain Ether. An ERC-223 deposit to a contract is a simple call of the `transfer` function. This is one transaction as opposed to two step process of `approve + transferFrom` depositing.

This standard allows payloads to be attached to transactions using the `bytes calldata _data` parameter, which can encode a second function call in the destination address, similar to how `msg.data` does in an ether transaction, or allow for public logging on chain should it be necessary for financial transactions.

## Backwards Compatibility

The interface of this token is similar to that of ERC-20 and most functions serve the same purpose as their analogues in ERC-20. 
`transfer(address, uint256, bytes calldata)` function is not backwards compatible with ERC-20 interface.

ERC-20 tokens can be delivered to a non-contract address with `transfer` function. ERC-20 tokens can be deposited to a contract address with `approve` + `transferFrom` pattern. Depositing ERC-20 tokens to the contract address with `transfer` function will always result in token deposit not being recognized by the recipient contract.

Here is an example of the contract code that handles ERC-20 token deposit. The following contract can accepts `tokenA` deposits. It is impossible to prevent deposits of non-tokenA to this contract. If tokenA is deposited with `transfer` function then it will result in a loss of tokens for the depositor because the balance of the user will be decreased in the contract of tokenA but the value of `deposits` variable in the `ERC20Receiver` will not be increased i.e. the deposit will not be credited. As of 5/9/2023 **$201M worth of 50 examined ERC-20 tokens are already lost** in this way on Ethereum mainnet.

```solidity
contract ERC20Receiver
{
    address tokenA;
    mapping (address =&gt; uint256) deposits;
    function deposit(uint _value, address _token) public
    {
        require(_token == tokenA);
        IERC20(_token).transferFrom(msg.sender, address(this), _value);
        deposits[msg.sender] += _value;
    }
}
```

ERC-223 tokens must be delivered to non-contract address or contract address in the same way with `transfer` function.

Here is an example of the contract code that handles ERC-223 token deposit. The following contract can filter tokens and only accepts `tokenA`. Other ERC-223 tokens would be rejected.

```solidity
contract ERC223Receiver
{
    address tokenA;
    mapping (address =&gt; uint256) deposits;
    function tokenReceived(address _from, uint _value, bytes memory _data) public returns (bytes4)
    {
        require(msg.sender == tokenA);
        deposits[_from] += _value;
        return 0x8943ec02;
    }
}
```

## Security Considerations

This token utilizes the model similar to plain ether behavior. Therefore replay issues must be taken into account.

### Reference Implementation

```solidity
pragma solidity ^0.8.19;

library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * This test is non-exhaustive, and there may be false-negatives: during the
     * execution of a contract&apos;s constructor, its address will be reported as
     * not containing a contract.
     *
     * &gt; It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies in extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size &gt; 0;
    }
}

abstract contract IERC223Recipient {
/**
 * @dev Standard ERC-223 receiving function that will handle incoming token transfers.
 *
 * @param _from  Token sender address.
 * @param _value Amount of tokens.
 * @param _data  Transaction metadata.
 */
    function tokenReceived(address _from, uint _value, bytes memory _data) public virtual returns (bytes4);
}

/**
 * @title Reference implementation of the ERC223 standard token.
 */
contract ERC223Token {

     /**
     * @dev Event that is fired on successful transfer.
     */
    event Transfer(address indexed from, address indexed to, uint value, bytes data);

    string  private _name;
    string  private _symbol;
    uint8   private _decimals;
    uint256 private _totalSupply;
    
    mapping(address =&gt; uint256) private balances; // List of user balances.

    /**
     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with
     * a default value of 18.
     *
     * To select a different value for {decimals}, use {_setupDecimals}.
     *
     * All three of these values are immutable: they can only be set once during
     * construction.
     */
     
    constructor(string memory new_name, string memory new_symbol, uint8 new_decimals)
    {
        _name     = new_name;
        _symbol   = new_symbol;
        _decimals = new_decimals;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view returns (string memory)
    {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view returns (string memory)
    {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5,05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC223} uses, unless {_setupDecimals} is
     * called.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC223-balanceOf} and {IERC223-transfer}.
     */
    function decimals() public view returns (uint8)
    {
        return _decimals;
    }

    /**
     * @dev See {IERC223-totalSupply}.
     */
    function totalSupply() public view returns (uint256)
    {
        return _totalSupply;
    }

    /**
     * @dev See {IERC223-standard}.
     */
    function standard() public view returns (string memory)
    {
        return &quot;223&quot;;
    }

    
    /**
     * @dev Returns balance of the `_owner`.
     *
     * @param _owner   The address whose balance will be returned.
     * @return balance Balance of the `_owner`.
     */
    function balanceOf(address _owner) public view returns (uint256)
    {
        return balances[_owner];
    }
    
    /**
     * @dev Transfer the specified amount of tokens to the specified address.
     *      Invokes the `tokenFallback` function if the recipient is a contract.
     *      The token transfer fails if the recipient is a contract
     *      but does not implement the `tokenFallback` function
     *      or the fallback function to receive funds.
     *
     * @param _to    Receiver address.
     * @param _value Amount of tokens that will be transferred.
     * @param _data  Transaction metadata.
     */
    function transfer(address _to, uint _value, bytes calldata _data) public returns (bool success)
    {
        // Standard function transfer similar to ERC20 transfer with no _data .
        // Added due to backwards compatibility reasons .
        balances[msg.sender] = balances[msg.sender] - _value;
        balances[_to] = balances[_to] + _value;
        if(Address.isContract(_to)) {
            IERC223Recipient(_to).tokenReceived(msg.sender, _value, _data);
        }
        emit Transfer(msg.sender, _to, _value, _data);
        return true;
    }
    
    /**
     * @dev Transfer the specified amount of tokens to the specified address.
     *      This function works the same with the previous one
     *      but doesn&apos;t contain `_data` param.
     *      Added due to backwards compatibility reasons.
     *
     * @param _to    Receiver address.
     * @param _value Amount of tokens that will be transferred.
     */
    function transfer(address _to, uint _value) public returns (bool success)
    {
        bytes memory _empty = hex&quot;00000000&quot;;
        balances[msg.sender] = balances[msg.sender] - _value;
        balances[_to] = balances[_to] + _value;
        if(Address.isContract(_to)) {
            IERC223Recipient(_to).tokenReceived(msg.sender, _value, _empty);
        }
        emit Transfer(msg.sender, _to, _value, _empty);
        return true;
    }
}
```

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 03 May 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-223</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-223</guid>
      </item>
    
      <item>
        <title>Clique proof-of-authority consensus protocol</title>
        <category>Standards Track/Core</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/225</comments>
        
        <description>## Abstract

Clique is a proof-of-authority consensus protocol. It shadows the design of Ethereum mainnet, so it can be added to any client with minimal effort.

## Motivation

Ethereum&apos;s first official testnet was Morden. It ran from July 2015 to about November 2016, when due to the accumulated junk and some testnet consensus issues between Geth and Parity, it was finally laid to rest in favor of a testnet reboot.

Ropsten was thus born, clearing out all the junk and starting with a clean slate. This ran well until the end of February 2017, when malicious actors decided to abuse the low PoW and gradually inflate the block gas limits to 9 billion (from the normal 4.7 million), at which point sending in gigantic transactions crippling the entire network. Even before that, attackers attempted multiple extremely long reorgs, causing network splits between different clients, and even different versions.

The root cause of these attacks is that a PoW network is only as secure as the computing capacity placed behind it. Restarting a new testnet from zero wouldn&apos;t solve anything, since the attacker can mount the same attack over and over again. The Parity team decided to go with an emergency solution of rolling back a significant number of blocks, and enacting a soft-fork rule that disallows gas limits above a certain threshold.

While this solution may work in the short term:

* It&apos;s not elegant: Ethereum supposed to have dynamic block limits
* It&apos;s not portable: other clients need to implement new fork logic themselves
* It&apos;s not compatible with sync modes: fast and light clients are both out of luck
* It&apos;s just prolonging the attacks: junk can still be steadily pushed in ad infinitum

Parity&apos;s solution although not perfect, is nonetheless workable. I&apos;d like to propose a longer term alternative solution, which is more involved, yet should be simple enough to allow rolling out in a reasonable amount of time.

### Standardized proof-of-authority

As reasoned above, proof-of-work cannot work securely in a network with no value. Ethereum has its long term goal of proof-of-stake based on Casper, but that is heavy research so we cannot rely on that any time soon to fix today&apos;s problems. One solution however is easy enough to implement, yet effective enough to fix the testnet properly, namely a proof-of-authority scheme.

The main design goals of the PoA protocol described here is that it should be very simple to implement and embed into any existing Ethereum client, while at the same time allow using existing sync technologies (fast, light, warp) without needing client developers to add custom logic to critical software.

## Design constraints

There are two approaches to syncing a blockchain in general:

 * The classical approach is to take the genesis block and crunch through all the transactions one by one. This is tried and proven, but in Ethereum complexity networks quickly turns out to be very costly computationally.
 * The other is to only download the chain of block headers and verify their validity, after which point an arbitrary recent state may be downloaded from the network and checked against recent headers.

A PoA scheme is based on the idea that blocks may only be minted by trusted signers. As such, every block (or header) that a client sees can be matched against the list of trusted signers. The challenge here is how to maintain a list of authorized signers that can change in time? The obvious answer (store it in an Ethereum contract) is also the wrong answer: fast, light and warp sync don&apos;t have access to the state during syncing.

**The protocol of maintaining the list of authorized signers must be fully contained in the block headers.**

The next obvious idea would be to change the structure of the block headers so it drops the notions of PoW, and introduces new fields to cater for voting mechanisms. This is also the wrong answer: changing such a core data structure in multiple implementations would be a nightmare development, maintenance and security wise.

**The protocol of maintaining the list of authorized signers must fit fully into the current data models.**

So, according to the above, we can&apos;t use the EVM for voting, rather have to resort to headers. And we can&apos;t change header fields, rather have to resort to the currently available ones. Not much wiggle room.

### Repurposing header fields for signing and voting

The most obvious field that currently is used solely as *fun metadata* is the 32 byte **extra-data** section in block headers. Miners usually place their client and version in there, but some fill it with alternative &quot;messages&quot;. The protocol would extend this field ~~to~~ with 65 bytes with the purpose of a secp256k1 miner signature. This would allow anyone obtaining a block to verify it against a list of authorized signers. It also makes the **miner** section in block headers obsolete (since the address can be derived from the signature).

*Note, changing the length of a header field is a non invasive operation as all code (such as RLP encoding, hashing) is agnostic to that, so clients wouldn&apos;t need custom logic.*

The above is enough to validate a chain, but how can we update a dynamic list of signers. The answer is that we can repurpose the newly obsoleted **miner** field and the PoA obsoleted **nonce** field to create a voting protocol:

 * During regular blocks, both of these fields would be set to zero.
 * If a signer wishes to enact a change to the list of authorized signers, it will:
   * Set the **miner** to the signer it wishes to vote about
   * Set the **nonce** to `0` or `0xff...f` to vote in favor of adding or kicking out

Any clients syncing the chain can &quot;tally&quot; up the votes during block processing, and maintain a dynamically changing list of authorized signers by popular vote.

To avoid having an infinite window to tally up votes in, and also to allow periodically flushing stale proposals, we can reuse the concept of an epoch from ethash, where every epoch transition flushes all pending votes. Furthermore, these epoch transitions can also act as stateless checkpoints containing the list of current authorized signers within the header extra-data. This permits clients to sync up based only on a checkpoint hash without having to replay all the voting that was done on the chain up to that point. It also allows the genesis header to fully define the chain, containing the list of initial signers.

### Attack vector: Malicious signer

It may happen that a malicious user gets added to the list of signers, or that a signer key/machine is compromised. In such a scenario the protocol needs to be able to defend itself against reorganizations and spamming. The proposed solution is that given a list of N authorized signers, any signer may only mint 1 block out of every K. This ensures that damage is limited, and the remainder of the miners can vote out the malicious user.

### Attack vector: Censoring signer

Another interesting attack vector is if a signer (or group of signers) attempts to censor out blocks that vote on removing them from the authorization list. To work around this, we restrict the allowed minting frequency of signers to 1 out of N/2. This ensures that malicious signers need to control at least 51% of signing accounts, at which case it&apos;s game over anyway.

### Attack vector: Spamming signer

A final small attack vector is that of malicious signers injecting new vote proposals inside every block they mint. Since nodes need to tally up all votes to create the actual list of authorized signers, they need to track all votes through time. Without placing a limit on the vote window, this could grow slowly, yet unbounded. The solution is to place a ~~moving~~ window of W blocks after which votes are considered stale. ~~A sane window might be 1-2 epochs.~~ We&apos;ll call this an epoch.

### Attack vector: Concurrent blocks

If the number of authorized signers are N, and we allow each signer to mint 1 block out of K, then at any point in time N-K+1 miners are allowed to mint. To avoid these racing for blocks, every signer would add a small random &quot;offset&quot; to the time it releases a new block. This ensures that small forks are rare, but occasionally still happen (as on the main net). If a signer is caught abusing it&apos;s authority and causing chaos, it can be voted out.

## Specification

We define the following constants:

 * **`EPOCH_LENGTH`**: Number of blocks after which to checkpoint and reset the pending votes.
   * Suggested `30000` for the testnet to remain analogous to the mainnet `ethash` epoch.
 * **`BLOCK_PERIOD`**: Minimum difference between two consecutive block&apos;s timestamps.
   * Suggested `15s` for the testnet to remain analogous to the mainnet `ethash` target.
 * **`EXTRA_VANITY`**: Fixed number of extra-data prefix bytes reserved for signer *vanity*.
   * Suggested `32 bytes` to retain the current extra-data allowance and/or use.
 * **`EXTRA_SEAL`**: Fixed number of extra-data suffix bytes reserved for signer seal.
   * `65 bytes` fixed as signatures are based on the standard `secp256k1` curve.
   * Filled with zeros on genesis block.
 * **`NONCE_AUTH`**: Magic nonce number `0xffffffffffffffff` to vote on adding a new signer.
 * **`NONCE_DROP`**: Magic nonce number `0x0000000000000000` to vote on removing a signer.
 * **`UNCLE_HASH`**: Always `Keccak256(RLP([]))` as uncles are meaningless outside of PoW.
 * **`DIFF_NOTURN`**: Block score (difficulty) for blocks containing out-of-turn signatures.
   * Suggested `1` since it just needs to be an arbitrary baseline constant.
 * **`DIFF_INTURN`**: Block score (difficulty) for blocks containing in-turn signatures.
   * Suggested `2` to show a slight preference over out-of-turn signatures.

We also define the following per-block constants:

 * **`BLOCK_NUMBER`**: Block height in the chain, where the height of the genesis is block `0`.
 * **`SIGNER_COUNT`**: Number of authorized signers valid at a particular instance in the chain.
 * **`SIGNER_INDEX`**: Zero-based index of the block signer in the sorted list of current authorized signers.
 * **`SIGNER_LIMIT`**: Number of consecutive blocks out of which a signer may only sign one.
   * Must be `floor(SIGNER_COUNT / 2) + 1` to enforce majority consensus on a chain.

We repurpose the `ethash` header fields as follows:

 * **`beneficiary`** / **`miner`**: Address to propose modifying the list of authorized signers with.
   * Should be filled with zeroes normally, modified only while voting.
   * Arbitrary values are permitted nonetheless (even meaningless ones such as voting out non signers) to avoid extra complexity in implementations around voting mechanics.
   * **Must** be filled with zeroes on checkpoint (i.e. epoch transition) blocks.
   * Transaction execution **must** use the actual block signer (see `extraData`) for the `COINBASE` opcode and transaction fees **must** be attributed to the signer account.
 * **`nonce`**: Signer proposal regarding the account defined by the `beneficiary` field.
   * Should be **`NONCE_DROP`** to propose deauthorizing `beneficiary` as an existing signer.
   * Should be **`NONCE_AUTH`** to propose authorizing `beneficiary` as a new signer.
   * **Must** be filled with zeroes on checkpoint (i.e. epoch transition) blocks.
   * **Must** not take up any other value apart from the two above (for now).
 * **`extraData`**: Combined field for signer vanity, checkpointing and signer signatures.
   * First **`EXTRA_VANITY`** bytes (fixed) may contain arbitrary signer vanity data.
   * Last **`EXTRA_SEAL`** bytes (fixed) is the signer&apos;s signature sealing the header.
   * Checkpoint blocks **must** contain a list of signers (`N*20 bytes`) in between, **omitted** otherwise.
   * The list of signers in checkpoint block extra-data sections **must** be sorted in ascending byte order.
 * **`mixHash`**: Reserved for fork protection logic, similar to the extra-data during the DAO.
   * **Must** be filled with zeroes during normal operation.
 * **`ommersHash`**: **Must** be **`UNCLE_HASH`** as uncles are meaningless outside of PoW.
 * **`timestamp`**: **Must** be at least the parent timestamp + **`BLOCK_PERIOD`**.
 * **`difficulty`**: Contains the standalone score of the block to derive the quality of a chain.
   * **Must** be **`DIFF_NOTURN`** if `BLOCK_NUMBER % SIGNER_COUNT != SIGNER_INDEX`
   * **Must** be **`DIFF_INTURN`** if `BLOCK_NUMBER % SIGNER_COUNT == SIGNER_INDEX`

### Authorizing a block

To authorize a block for the network, the signer needs to sign the block&apos;s sighash containing **everything except the signature itself**. This means that this hash contains every field of the header (`nonce` and `mixDigest` included), and also the  `extraData` with the exception of the 65 byte signature suffix. The fields are hashed in the order of their definition in the yellow paper. Note that this sighash differs from the final block hash which also includes the signature.

The sighash is signed using the standard `secp256k1` curve, and the resulting 65 byte signature (`R`, `S`, `V`, where `V` is `0` or `1`) is embedded into the `extraData` as the trailing 65 byte suffix.

To ensure malicious signers (loss of signing key) cannot wreck havoc in the network, each signer is allowed to sign **maximum one** out of **`SIGNER_LIMIT`** consecutive blocks. The order is not fixed, but in-turn signing weighs more (**`DIFF_INTURN`**) than out of turn one (**`DIFF_NOTURN`**).

#### Authorization strategies

As long as signers conform to the above specs, they can authorize and distribute blocks as they see fit. The following suggested strategy will however reduce network traffic and small forks, so it&apos;s a suggested feature:

 * If a signer is allowed to sign a block (is on the authorized list and didn&apos;t sign recently).
   * Calculate the optimal signing time of the next block (parent + **`BLOCK_PERIOD`**).
   * If the signer is in-turn, wait for the exact time to arrive, sign and broadcast immediately.
   * If the signer is out-of-turn, delay signing by `rand(SIGNER_COUNT * 500ms)`.

This small strategy will ensure that the in-turn signer (who&apos;s block weighs more) has a slight advantage to sign and propagate versus the out-of-turn signers. Also the scheme allows a bit of scale with the increase of the number of signers.

### Voting on signers

Every epoch transition (genesis block included) acts as a stateless checkpoint, from which capable clients should be able to sync without requiring any previous state. This means epoch headers **must not** contain votes, all non settled votes are discarded, and tallying starts from scratch.

For all non-epoch transition blocks:

 * Signers may cast one vote per own block to propose a change to the authorization list.
 * Only the latest proposal per target beneficiary is kept from a single signer.
 * Votes are tallied live as the chain progresses (concurrent proposals allowed).
 * Proposals reaching majority consensus **`SIGNER_LIMIT`** come into effect immediately.
 * Invalid proposals are **not** to be penalized for client implementation simplicity.

**A proposal coming into effect entails discarding all pending votes for that proposal (both for and against) and starting with a clean slate.**

#### Cascading votes

A complex corner case may arise during signer deauthorization. When a previously authorized signer is dropped, the number of signers required to approve a proposal might decrease by one. This might cause one or more pending proposals to reach majority consensus, the execution of which might further cascade into new proposals passing.

Handling this scenario is non obvious when multiple conflicting proposals pass simultaneously (e.g. add a new signer vs. drop an existing one), where the evaluation order might drastically change the outcome of the final authorization list. Since signers may invert their own votes in every block they mint, it&apos;s not so obvious which proposal would be &quot;first&quot;.

To avoid the pitfalls cascading executions would entail, the Clique proposal explicitly forbids cascading effects. In other words: **Only the `beneficiary` of the current header/vote may be added to/dropped from the authorization list. If that causes other proposals to reach consensus, those will be executed when their respective beneficiaries are &quot;touched&quot; again (given that majority consensus still holds at that point).**

#### Voting strategies

Since the blockchain can have small reorgs, a naive voting mechanism of &quot;cast-and-forget&quot; may not be optimal, since a block containing a singleton vote may not end up on the final chain.

A simplistic but working strategy is to allow users to configure &quot;proposals&quot; on the signers (e.g. &quot;add 0x...&quot;, &quot;drop 0x...&quot;). The signing code can then pick a random proposal for every block it signs and inject it. This ensures that multiple concurrent proposals as well as reorgs get eventually noted on the chain.

This list may be expired after a certain number of blocks / epochs, but it&apos;s important to realize that &quot;seeing&quot; a proposal pass doesn&apos;t mean it won&apos;t get reorged, so it should not be immediately dropped when the proposal passes.

## Test Cases

```go
// block represents a single block signed by a particular account, where
// the account may or may not have cast a Clique vote.
type block struct {
  signer     string   // Account that signed this particular block
  voted      string   // Optional value if the signer voted on adding/removing someone
  auth       bool     // Whether the vote was to authorize (or deauthorize)
  checkpoint []string // List of authorized signers if this is an epoch block
}

// Define the various voting scenarios to test
tests := []struct {
  epoch   uint64   // Number of blocks in an epoch (unset = 30000)
  signers []string // Initial list of authorized signers in the genesis
  blocks  []block  // Chain of signed blocks, potentially influencing auths
  results []string // Final list of authorized signers after all blocks
  failure error    // Failure if some block is invalid according to the rules
}{
  {
    // Single signer, no votes cast
    signers: []string{&quot;A&quot;},
    blocks:  []block{
      {signer: &quot;A&quot;}
    },
    results: []string{&quot;A&quot;},
  }, {
    // Single signer, voting to add two others (only accept first, second needs 2 votes)
    signers: []string{&quot;A&quot;},
    blocks:  []block{
      {signer: &quot;A&quot;, voted: &quot;B&quot;, auth: true},
      {signer: &quot;B&quot;},
      {signer: &quot;A&quot;, voted: &quot;C&quot;, auth: true},
    },
    results: []string{&quot;A&quot;, &quot;B&quot;},
  }, {
    // Two signers, voting to add three others (only accept first two, third needs 3 votes already)
    signers: []string{&quot;A&quot;, &quot;B&quot;},
    blocks:  []block{
      {signer: &quot;A&quot;, voted: &quot;C&quot;, auth: true},
      {signer: &quot;B&quot;, voted: &quot;C&quot;, auth: true},
      {signer: &quot;A&quot;, voted: &quot;D&quot;, auth: true},
      {signer: &quot;B&quot;, voted: &quot;D&quot;, auth: true},
      {signer: &quot;C&quot;},
      {signer: &quot;A&quot;, voted: &quot;E&quot;, auth: true},
      {signer: &quot;B&quot;, voted: &quot;E&quot;, auth: true},
    },
    results: []string{&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;D&quot;},
  }, {
    // Single signer, dropping itself (weird, but one less cornercase by explicitly allowing this)
    signers: []string{&quot;A&quot;},
    blocks:  []block{
      {signer: &quot;A&quot;, voted: &quot;A&quot;, auth: false},
    },
    results: []string{},
  }, {
    // Two signers, actually needing mutual consent to drop either of them (not fulfilled)
    signers: []string{&quot;A&quot;, &quot;B&quot;},
    blocks:  []block{
      {signer: &quot;A&quot;, voted: &quot;B&quot;, auth: false},
    },
    results: []string{&quot;A&quot;, &quot;B&quot;},
  }, {
    // Two signers, actually needing mutual consent to drop either of them (fulfilled)
    signers: []string{&quot;A&quot;, &quot;B&quot;},
    blocks:  []block{
      {signer: &quot;A&quot;, voted: &quot;B&quot;, auth: false},
      {signer: &quot;B&quot;, voted: &quot;B&quot;, auth: false},
    },
    results: []string{&quot;A&quot;},
  }, {
    // Three signers, two of them deciding to drop the third
    signers: []string{&quot;A&quot;, &quot;B&quot;, &quot;C&quot;},
    blocks:  []block{
      {signer: &quot;A&quot;, voted: &quot;C&quot;, auth: false},
      {signer: &quot;B&quot;, voted: &quot;C&quot;, auth: false},
    },
    results: []string{&quot;A&quot;, &quot;B&quot;},
  }, {
    // Four signers, consensus of two not being enough to drop anyone
    signers: []string{&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;D&quot;},
    blocks:  []block{
      {signer: &quot;A&quot;, voted: &quot;C&quot;, auth: false},
      {signer: &quot;B&quot;, voted: &quot;C&quot;, auth: false},
    },
    results: []string{&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;D&quot;},
  }, {
    // Four signers, consensus of three already being enough to drop someone
    signers: []string{&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;D&quot;},
    blocks:  []block{
      {signer: &quot;A&quot;, voted: &quot;D&quot;, auth: false},
      {signer: &quot;B&quot;, voted: &quot;D&quot;, auth: false},
      {signer: &quot;C&quot;, voted: &quot;D&quot;, auth: false},
    },
    results: []string{&quot;A&quot;, &quot;B&quot;, &quot;C&quot;},
  }, {
    // Authorizations are counted once per signer per target
    signers: []string{&quot;A&quot;, &quot;B&quot;},
    blocks:  []block{
      {signer: &quot;A&quot;, voted: &quot;C&quot;, auth: true},
      {signer: &quot;B&quot;},
      {signer: &quot;A&quot;, voted: &quot;C&quot;, auth: true},
      {signer: &quot;B&quot;},
      {signer: &quot;A&quot;, voted: &quot;C&quot;, auth: true},
    },
    results: []string{&quot;A&quot;, &quot;B&quot;},
  }, {
    // Authorizing multiple accounts concurrently is permitted
    signers: []string{&quot;A&quot;, &quot;B&quot;},
    blocks:  []block{
      {signer: &quot;A&quot;, voted: &quot;C&quot;, auth: true},
      {signer: &quot;B&quot;},
      {signer: &quot;A&quot;, voted: &quot;D&quot;, auth: true},
      {signer: &quot;B&quot;},
      {signer: &quot;A&quot;},
      {signer: &quot;B&quot;, voted: &quot;D&quot;, auth: true},
      {signer: &quot;A&quot;},
      {signer: &quot;B&quot;, voted: &quot;C&quot;, auth: true},
    },
    results: []string{&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;D&quot;},
  }, {
    // Deauthorizations are counted once per signer per target
    signers: []string{&quot;A&quot;, &quot;B&quot;},
    blocks:  []block{
      {signer: &quot;A&quot;, voted: &quot;B&quot;, auth: false},
      {signer: &quot;B&quot;},
      {signer: &quot;A&quot;, voted: &quot;B&quot;, auth: false},
      {signer: &quot;B&quot;},
      {signer: &quot;A&quot;, voted: &quot;B&quot;, auth: false},
    },
    results: []string{&quot;A&quot;, &quot;B&quot;},
  }, {
    // Deauthorizing multiple accounts concurrently is permitted
    signers: []string{&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;D&quot;},
    blocks:  []block{
      {signer: &quot;A&quot;, voted: &quot;C&quot;, auth: false},
      {signer: &quot;B&quot;},
      {signer: &quot;C&quot;},
      {signer: &quot;A&quot;, voted: &quot;D&quot;, auth: false},
      {signer: &quot;B&quot;},
      {signer: &quot;C&quot;},
      {signer: &quot;A&quot;},
      {signer: &quot;B&quot;, voted: &quot;D&quot;, auth: false},
      {signer: &quot;C&quot;, voted: &quot;D&quot;, auth: false},
      {signer: &quot;A&quot;},
      {signer: &quot;B&quot;, voted: &quot;C&quot;, auth: false},
    },
    results: []string{&quot;A&quot;, &quot;B&quot;},
  }, {
    // Votes from deauthorized signers are discarded immediately (deauth votes)
    signers: []string{&quot;A&quot;, &quot;B&quot;, &quot;C&quot;},
    blocks:  []block{
      {signer: &quot;C&quot;, voted: &quot;B&quot;, auth: false},
      {signer: &quot;A&quot;, voted: &quot;C&quot;, auth: false},
      {signer: &quot;B&quot;, voted: &quot;C&quot;, auth: false},
      {signer: &quot;A&quot;, voted: &quot;B&quot;, auth: false},
    },
    results: []string{&quot;A&quot;, &quot;B&quot;},
  }, {
    // Votes from deauthorized signers are discarded immediately (auth votes)
    signers: []string{&quot;A&quot;, &quot;B&quot;, &quot;C&quot;},
    blocks:  []block{
      {signer: &quot;C&quot;, voted: &quot;D&quot;, auth: true},
      {signer: &quot;A&quot;, voted: &quot;C&quot;, auth: false},
      {signer: &quot;B&quot;, voted: &quot;C&quot;, auth: false},
      {signer: &quot;A&quot;, voted: &quot;D&quot;, auth: true},
    },
    results: []string{&quot;A&quot;, &quot;B&quot;},
  }, {
    // Cascading changes are not allowed, only the account being voted on may change
    signers: []string{&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;D&quot;},
    blocks:  []block{
      {signer: &quot;A&quot;, voted: &quot;C&quot;, auth: false},
      {signer: &quot;B&quot;},
      {signer: &quot;C&quot;},
      {signer: &quot;A&quot;, voted: &quot;D&quot;, auth: false},
      {signer: &quot;B&quot;, voted: &quot;C&quot;, auth: false},
      {signer: &quot;C&quot;},
      {signer: &quot;A&quot;},
      {signer: &quot;B&quot;, voted: &quot;D&quot;, auth: false},
      {signer: &quot;C&quot;, voted: &quot;D&quot;, auth: false},
    },
    results: []string{&quot;A&quot;, &quot;B&quot;, &quot;C&quot;},
  }, {
    // Changes reaching consensus out of bounds (via a deauth) execute on touch
    signers: []string{&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;D&quot;},
    blocks:  []block{
      {signer: &quot;A&quot;, voted: &quot;C&quot;, auth: false},
      {signer: &quot;B&quot;},
      {signer: &quot;C&quot;},
      {signer: &quot;A&quot;, voted: &quot;D&quot;, auth: false},
      {signer: &quot;B&quot;, voted: &quot;C&quot;, auth: false},
      {signer: &quot;C&quot;},
      {signer: &quot;A&quot;},
      {signer: &quot;B&quot;, voted: &quot;D&quot;, auth: false},
      {signer: &quot;C&quot;, voted: &quot;D&quot;, auth: false},
      {signer: &quot;A&quot;},
      {signer: &quot;C&quot;, voted: &quot;C&quot;, auth: true},
    },
    results: []string{&quot;A&quot;, &quot;B&quot;},
  }, {
    // Changes reaching consensus out of bounds (via a deauth) may go out of consensus on first touch
    signers: []string{&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;D&quot;},
    blocks:  []block{
      {signer: &quot;A&quot;, voted: &quot;C&quot;, auth: false},
      {signer: &quot;B&quot;},
      {signer: &quot;C&quot;},
      {signer: &quot;A&quot;, voted: &quot;D&quot;, auth: false},
      {signer: &quot;B&quot;, voted: &quot;C&quot;, auth: false},
      {signer: &quot;C&quot;},
      {signer: &quot;A&quot;},
      {signer: &quot;B&quot;, voted: &quot;D&quot;, auth: false},
      {signer: &quot;C&quot;, voted: &quot;D&quot;, auth: false},
      {signer: &quot;A&quot;},
      {signer: &quot;B&quot;, voted: &quot;C&quot;, auth: true},
    },
    results: []string{&quot;A&quot;, &quot;B&quot;, &quot;C&quot;},
  }, {
    // Ensure that pending votes don&apos;t survive authorization status changes. This
    // corner case can only appear if a signer is quickly added, removed and then
    // readded (or the inverse), while one of the original voters dropped. If a
    // past vote is left cached in the system somewhere, this will interfere with
    // the final signer outcome.
    signers: []string{&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;D&quot;, &quot;E&quot;},
    blocks:  []block{
      {signer: &quot;A&quot;, voted: &quot;F&quot;, auth: true}, // Authorize F, 3 votes needed
      {signer: &quot;B&quot;, voted: &quot;F&quot;, auth: true},
      {signer: &quot;C&quot;, voted: &quot;F&quot;, auth: true},
      {signer: &quot;D&quot;, voted: &quot;F&quot;, auth: false}, // Deauthorize F, 4 votes needed (leave A&apos;s previous vote &quot;unchanged&quot;)
      {signer: &quot;E&quot;, voted: &quot;F&quot;, auth: false},
      {signer: &quot;B&quot;, voted: &quot;F&quot;, auth: false},
      {signer: &quot;C&quot;, voted: &quot;F&quot;, auth: false},
      {signer: &quot;D&quot;, voted: &quot;F&quot;, auth: true}, // Almost authorize F, 2/3 votes needed
      {signer: &quot;E&quot;, voted: &quot;F&quot;, auth: true},
      {signer: &quot;B&quot;, voted: &quot;A&quot;, auth: false}, // Deauthorize A, 3 votes needed
      {signer: &quot;C&quot;, voted: &quot;A&quot;, auth: false},
      {signer: &quot;D&quot;, voted: &quot;A&quot;, auth: false},
      {signer: &quot;B&quot;, voted: &quot;F&quot;, auth: true}, // Finish authorizing F, 3/3 votes needed
    },
    results: []string{&quot;B&quot;, &quot;C&quot;, &quot;D&quot;, &quot;E&quot;, &quot;F&quot;},
  }, {
    // Epoch transitions reset all votes to allow chain checkpointing
    epoch:   3,
    signers: []string{&quot;A&quot;, &quot;B&quot;},
    blocks:  []block{
      {signer: &quot;A&quot;, voted: &quot;C&quot;, auth: true},
      {signer: &quot;B&quot;},
      {signer: &quot;A&quot;, checkpoint: []string{&quot;A&quot;, &quot;B&quot;}},
      {signer: &quot;B&quot;, voted: &quot;C&quot;, auth: true},
    },
    results: []string{&quot;A&quot;, &quot;B&quot;},
  }, {
    // An unauthorized signer should not be able to sign blocks
    signers: []string{&quot;A&quot;},
    blocks:  []block{
      {signer: &quot;B&quot;},
    },
    failure: errUnauthorizedSigner,
  }, {
    // An authorized signer that signed recently should not be able to sign again
    signers: []string{&quot;A&quot;, &quot;B&quot;},
    blocks: []block{
      {signer: &quot;A&quot;},
      {signer: &quot;A&quot;},
    },
    failure: errRecentlySigned,
  }, {
    // Recent signatures should not reset on checkpoint blocks imported in a batch
    epoch:   3,
    signers: []string{&quot;A&quot;, &quot;B&quot;, &quot;C&quot;},
    blocks:  []block{
      {signer: &quot;A&quot;},
      {signer: &quot;B&quot;},
      {signer: &quot;A&quot;, checkpoint: []string{&quot;A&quot;, &quot;B&quot;, &quot;C&quot;}},
      {signer: &quot;A&quot;},
    },
    failure: errRecentlySigned,
  },
}
```

## Implementation

A reference implementation is part of [go-ethereum](https://github.com/ethereum/go-ethereum/tree/master/consensus/clique) and has been functioning as the consensus engine behind the [Rinkeby](https://www.rinkeby.io) testnet since April, 2017.
## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 06 Mar 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-225</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-225</guid>
      </item>
    
      <item>
        <title>Formal process of hard forks</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-233-formal-process-of-hard-forks/1387</comments>
        
        <description>## Abstract

To describe the formal process of preparing and activating hard forks.

## Motivation

Today discussions about hard forks happen at various forums and sometimes in ad-hoc ways.

## Specification

A Meta EIP should be created and merged as a *Draft* as soon as a new hard fork is planned.

This EIP should contain:
- the desired codename of the hard fork,
- activation block number once decided
- a timeline section
- an EIPs to include section
- the **Requires** header should point to the previous hard fork meta EIP.

The draft shall be updated with summaries of the decisions around the hard fork.

### Timeline

Once a timeline with key dates is agreed upon for other crucial dates. The basic outline of a hardfork timeline should include:
* Hard deadline to accept proposals for this hard fork
* Soft deadline for major client implementations
* Projected date for testnet network upgrade
* Projected date for mainnet upgrade (the activation block number / projected date for this block)

### EIP Inclusion Process

Anyone that wishes to propose a Core EIP for the hard fork should make a PR against the Meta EIP representing the hard fork. The EIP must be published as at least `Draft`. It enters the _Proposed EIPs_ section, along with at least one person who is a point of contact for wanting to include the EIP.

EIPs can move states by discussion done on the &quot;[All Core Devs Meetings](https://github.com/ethereum/pm/)&quot;:
- If accepted for a hard fork, the EIP should be moved to the _Accepted EIPs_ section. If the EIP has major client implementations and no security issues by the timeline date, it is scheduled for inclusion.
- If rejected from a hard fork, the EIP should be moved to the _Rejected EIPs_ section.
- Once the EIPs in the _Accepted EIPs_ section have successfully launched on a testnet roll out, they are moved to the _Included EIPs_ section.

---

The Meta EIP representing the hard fork should move in to the `Accepted` state once the changes are frozen (i.e. all referenced EIPs are in the `Accepted` state) and in to the `Final` state once the hard fork has been activated.

## Template

A template for the [Istanbul Hardfork Meta 1679](/EIPs/EIPS/eip-1679) is included below ([source file on GitHub](/EIPs/EIPS/eip-1679)):

```
{% raw %}
---
eip: 1679
title: &quot;Hardfork Meta: Istanbul&quot;
author: Alex Beregszaszi (@axic), Afri Schoedon (@5chdn)
type: Meta
status: Draft
created: 2019-01-04
requires: 1716
---

## Abstract

This meta-EIP specifies the changes included in the Ethereum hardfork named Istanbul.

## Specification

- Codename: Istanbul
- Activation: TBD

### Included EIPs

- TBD

### Accepted EIPs

- TBD

### Rejected EIPs

- TBD

### Proposed EIPs

- TBD

## Timeline

* 2019-05-17 (Fri) hard deadline to accept proposals for &quot;Istanbul&quot;
* 2019-07-19 (Fri) soft deadline for major client implementations
* 2019-08-14 (Wed) projected date for testnet network upgrade (Ropsten, Görli, or ad-hoc testnet)
* 2019-10-16 (Wed) projected date for mainnet upgrade (&quot;Istanbul&quot;)

## References

- TBD (e.g. link to Core Dev notes or other references)

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

{% endraw %}
```

## Rationale

A meta EIP for coordinating the hard fork should help in visibility and traceability of the scope of changes as well as provide a simple name and/or number for referring to the proposed fork.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 23 Mar 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-233</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-233</guid>
      </item>
    
      <item>
        <title>Add `blockHash` to JSON-RPC filter options.</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/234</comments>
        
        <description>## Simple Summary

Add an option to JSON-RPC filter options (used by `eth_newFilter` and `eth_getLogs`) that allows specifying the block hash that should be included in the results.  This option would be an alternative to `fromBlock`/`toBlock` options.

## Abstract

This addition would allow clients to fetch logs for specific blocks, whether those blocks were in the current main chain or not.  This resolves some issues that make it difficult/expensive to author robust clients due to the nature of chain reorgs, unreliable network connections and the result set not containing enough details in the empty case.

## Specification

The filter options used by `eth_newFilter` would have an additional optional parameter named `blockHash` whose value is a single block hash.  The Ethereum node responding to the request would either send back an error if the block hash was not found or it would return the results matching the filter (per normal operation) constrained to the block provided.  Internally, this would function (presumably) similar to the `fromBlock` and `toBlock` filter options.

## Rationale

A client (dApp) who needs reliable notification of both log additions (on new blocks) and log removals (on chain reorgs) cannot achieve this while relying solely on subscriptions and filters.  This is because a combination of a network or remote node failure during a reorg can result in the client getting out of sync with reality.  An example of where this can happen with Websockets is when the client opens a web socket connection, sets up a log filter subscription, gets notified of some new logs, then loses the web socket connection, then (while disconnected) a re-org occurs, then the client connects back and establishes a new log filter.  In this scenario they will not receive notification of the log removals from the node because they were disconnected when the removals were broadcast and the loss of their connection resulted in the node forgetting about their existence.  A similar scenario can be concocted for HTTP clients where between polls for updates, the node goes down and comes back (resulting in loss of filter state) and a re-org also occurs between the same two polls.

In order to deal with this while still providing a robust mechanism for internal block/log additional/removal, the client can maintain a blockchain internally (last `n` blocks) and only subscribe/poll for new blocks.  When a new block is received, the client can reconcile their internal model with the new block, potentially back-filling parents or rolling back/removing blocks from their internal model to get in sync with the node.  This can account for any type of disconnect/reorg/outage scenario and also allows the client (as an added benefit) to talk to a cluster of Ethereum nodes (e.g., via round-robin) rather than being tightly coupled to a single node.

Once the user has a reliable stream of blocks, they can then look at the bloom filter for the new block and if the block *may* have logs of interest they can fetch the filtered logs for that block from the node.  The problem that arises is that a re-org may occur between when the client receives the block and when the client fetches the logs for that block.  Given the current set of filter options, the client can only ask for logs by block number.  In this scenario, the logs they get back will be for a block that *isn&apos;t* the block they want the logs for and is instead for a block that was re-orged in (and may not be fully reconciled with the internal client state).  This can be partially worked around by looking at the resulting logs themselves and identifying whether or not they are for the block hash requested.  However, if the result set is an empty array (no logs fetched) then the client is in a situation where they don&apos;t know what block the results are for.  The results could have been legitimately empty (bloom filter can yield false positives) for the block in question, or they could be receiving empty logs for a block that they don&apos;t know about.  At this point, there is no decision the client can make that allows them a guarantee of recovery.  They can assume the empty logs were for the correct block, but if they weren&apos;t then they will never try to fetch again.  This creates a problem if the block was only transiently re-orged out because it may come back before the next block poll so the client will never witness the reorg.  They can assume the empty logs were for the wrong block, and refetch them, but they may continue to get empty results putting them right back into the same situation.

By adding the ability to fetch logs by hash, the client can be guaranteed that if they get a result set, it is for the block in question.  If they get an error, then they can take appropriate action (e.g., rollback that block client-side and re-fetch latest).

## Backwards Compatibility

The only potential issue here is the `fromBlock` and `toBlock` fields.  It wouldn&apos;t make sense to include both the hash and the number so it seems like `fromBlock`/`toBlock` should be mutually exclusive with `blockHash`.

## Test Cases

`{ &quot;jsonrpc&quot;: &quot;2.0&quot;, &quot;id&quot;: 1, &quot;method&quot;: &quot;eth_getLogs&quot;, params: [{&quot;blockHash&quot;: &quot;0xbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0c&quot;}] }` should return all of the logs for the block with hash `0xbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0c`.  If a `topics` field is added to the filter options then a filtered set of logs for that block should be returned.  If no block exists with that hash then an error should be returned with a `code` of `-32000`, a `message` of `&quot;Block not found.&quot;` and a `data` of `&quot;0xbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0c&quot;`.

## Implementation

- [x] [Geth](https://github.com/ethereum/go-ethereum/pull/16734)

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 24 Mar 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-234</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-234</guid>
      </item>
    
      <item>
        <title>Ethereum purpose allocation for Deterministic Wallets</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-erc-app-keys-application-specific-wallet-accounts/2742</comments>
        
        <description>## Abstract
This EIP defines a logical hierarchy for deterministic wallets based on [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki), the purpose scheme defined in [BIP43](https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki) and [this proposed change to BIP43](https://github.com/bitcoin/bips/pull/523).

This EIP is a particular application of BIP43.

## Motivation
Because Ethereum is based on account balances rather than UTXO, the hierarchy defined by BIP44 is poorly suited. As a result, several competing derivation path strategies have sprung up for deterministic wallets, resulting in inter-client incompatibility. This BIP seeks to provide a path to standardise this in a fashion better suited to Ethereum&apos;s unique requirements.

## Specification
We define the following 2 levels in BIP32 path:

&lt;pre&gt;
m / purpose&apos; / subpurpose&apos; / EIP&apos;
&lt;/pre&gt;

Apostrophe in the path indicates that BIP32 hardened derivation is used.

Each level has a special meaning, described in the chapters below.

### Purpose

Purpose is set to 43, as documented in [this proposed change to BIP43](https://github.com/bitcoin/bips/pull/523).

The purpose field indicates that this path is for a non-bitcoin cryptocurrency.

Hardened derivation is used at this level.

### Subpurpose
Subpurpose is set to 60, the SLIP-44 code for Ethereum.

Hardened derivation is used at this level.

### EIP
EIP is set to the EIP number specifying the remainder of the BIP32 derivation path. This permits new Ethereum-focused applications of deterministic wallets without needing to interface with the BIP process.

Hardened derivation is used at this level.

## Rationale
The existing convention is to use the &apos;Ethereum&apos; coin type, leading to paths starting with `m/44&apos;/60&apos;/*`. Because this still assumes a UTXO-based coin, we contend that this is a poor fit, resulting in standardisation, usability, and security compromises. As a result, we are making the above proposal to define an entirely new hierarchy for Ethereum-based chains.

## Backwards Compatibility
The introduction of another derivation path requires existing software to add support for this scheme in addition to any existing schemes. Given the already confused nature of wallet derivation paths in Ethereum, we anticipate this will cause relatively little additional disruption, and has the potential to improve matters significantly in the long run.

## Test Cases
TBD

## Implementation
None yet.

## References
[This discussion on derivation paths](https://github.com/ethereum/EIPs/issues/84)

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 13 Apr 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-600</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-600</guid>
      </item>
    
      <item>
        <title>Ethereum hierarchy for deterministic wallets</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-erc-app-keys-application-specific-wallet-accounts/2742</comments>
        
        <description>## Abstract
This EIP defines a logical hierarchy for deterministic wallets based on [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki), the purpose scheme defined in [BIP43](https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki) and eip-draft-ethereum-purpose.

This EIP is a particular application of eip-draft-ethereum-purpose.

## Motivation
At present, different Ethereum clients and wallets use different derivation paths; a summary of them can be found [here](https://github.com/ethereum/EIPs/issues/84#issuecomment-292324521). Some of these paths violate BIP44, the standard defining derivation paths starting with `m/44&apos;/`. This creates confusion and incompatibility between wallet implementations, in some cases making funds from one wallet inaccessible on another, and in others requiring prompting users manually for a derivation path, which hinders usability.

Further, BIP44 was designed with UTXO-based blockchains in mind, and is a poor fit for Ethereum, which uses an accounts abstraction instead.

As an alternative, we propose a deterministic wallet hierarchy better tailored to Ethereum&apos;s unique requirements.

## Specification
We define the following 4 levels in BIP32 path:

&lt;pre&gt;
m / purpose&apos; / subpurpose&apos; / EIP&apos; / wallet&apos;
&lt;/pre&gt;

Apostrophe in the path indicates that BIP32 hardened derivation is used.

Each level has a special meaning, described in the chapters below.

### Purpose

Purpose is a constant set to 43, indicating the key derivation is for a non-bitcoin cryptocurrency.

Hardened derivation is used at this level.

### Subpurpose
Subpurpose is set to 60, the SLIP-44 code for Ethereum.

Hardened derivation is used at this level.

### EIP
EIP is set to the EIP number specifying the remainder of the BIP32 derivation path. For paths following this EIP specification, the number assigned to this EIP is used.

Hardened derivation is used at this level.

### Wallet
This component of the path splits the wallet into different user identities, allowing a single wallet to have multiple public identities.

Accounts are numbered from index 0 in sequentially increasing manner. This number is used as child index in BIP32 derivation.

Hardened derivation is used at this level.

Software should prevent a creation of an account if a previous account does not have a transaction history (meaning its address has not been used before).

Software needs to discover all used accounts after importing the seed from an external source.

## Rationale
The existing convention is to use the &apos;Ethereum&apos; coin type, leading to paths starting with `m/44&apos;/60&apos;/*`. Because this still assumes a UTXO-based coin, we contend that this is a poor fit, resulting in standardisation, usability, and security compromises. As a result, we are making the above proposal to define an entirely new hierarchy for Ethereum-based chains.

## Backwards Compatibility
The introduction of another derivation path requires existing software to add support for this scheme in addition to any existing schemes. Given the already confused nature of wallet derivation paths in Ethereum, we anticipate this will cause relatively little additional disruption, and has the potential to improve matters significantly in the long run.

For applications that utilise mnemonics, the authors expect to submit another EIP draft that describes a method for avoiding backwards compatibility concerns when transitioning to this new derivation path.

## Test Cases
TBD

## Implementation
None yet.

## References
[This discussion on derivation paths](https://github.com/ethereum/EIPs/issues/84)

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 13 Apr 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-601</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-601</guid>
      </item>
    
      <item>
        <title>Hardfork Meta: Homestead</title>
        <category>Meta/</category>
        
        <description>## Abstract

This specifies the changes included in the hard fork named Homestead.

## Specification

- Codename: Homestead
- Activation:
  - Block &gt;= 1,150,000 on Mainnet
  - Block &gt;= 494,000 on Morden
  - Block &gt;= 0 on future testnets
- Included EIPs:
  - [EIP-2](/EIPs/EIPS/eip-2) (Homestead Hard-fork Changes)
  - [EIP-7](/EIPs/EIPS/eip-7) (DELEGATECALL)
  - [EIP-8](/EIPs/EIPS/eip-8) (Networking layer: devp2p Forward Compatibility Requirements for Homestead)

## References

1. https://blog.ethereum.org/2016/02/29/homestead-release/

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 23 Apr 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-606</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-606</guid>
      </item>
    
      <item>
        <title>Hardfork Meta: Spurious Dragon</title>
        <category>Meta/</category>
        
        <description>## Abstract

This specifies the changes included in the hard fork named Spurious Dragon.

## Specification

- Codename: Spurious Dragon
- Aliases: State-clearing
- Activation:
  - Block &gt;= 2,675,000 on Mainnet
  - Block &gt;= 1,885,000 on Morden
- Included EIPs:
  - [EIP-155](/EIPs/EIPS/eip-155) (Simple replay attack protection)
  - [EIP-160](/EIPs/EIPS/eip-160) (EXP cost increase)
  - [EIP-161](/EIPs/EIPS/eip-161) (State trie clearing)
  - [EIP-170](/EIPs/EIPS/eip-170) (Contract code size limit)

## References

1. https://blog.ethereum.org/2016/11/18/hard-fork-no-4-spurious-dragon/

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 23 Apr 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-607</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-607</guid>
      </item>
    
      <item>
        <title>Hardfork Meta: Tangerine Whistle</title>
        <category>Meta/</category>
        
        <description>## Abstract

This specifies the changes included in the hard fork named Tangerine Whistle (EIP 150).

## Specification

- Codename: Tangerine Whistle
- Aliases: EIP 150, Anti-DoS
- Activation:
  - Block &gt;= 2,463,000 on Mainnet
- Included EIPs:
  - [EIP-150](/EIPs/EIPS/eip-150) (Gas cost changes for IO-heavy operations)

## References

1. https://blog.ethereum.org/2016/10/13/announcement-imminent-hard-fork-eip150-gas-cost-changes/
2. https://blog.ethereum.org/2016/10/18/faq-upcoming-ethereum-hard-fork/

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 23 Apr 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-608</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-608</guid>
      </item>
    
      <item>
        <title>Hardfork Meta: Byzantium</title>
        <category>Meta/</category>
        
        <description>## Abstract

This specifies the changes included in the hard fork named Byzantium.

## Specification

- Codename: Byzantium
- Aliases: Metropolis/Byzantium, Metropolis part 1
- Activation:
  - Block &gt;= 4,370,000 on Mainnet
  - Block &gt;= 1,700,000 on Ropsten testnet
- Included EIPs:
  - [EIP-100](/EIPs/EIPS/eip-100) (Change difficulty adjustment to target mean block time including uncles)
  - [EIP-140](/EIPs/EIPS/eip-140) (REVERT instruction in the Ethereum Virtual Machine)
  - [EIP-196](/EIPs/EIPS/eip-196) (Precompiled contracts for addition and scalar multiplication on the elliptic curve alt_bn128)
  - [EIP-197](/EIPs/EIPS/eip-197) (Precompiled contracts for optimal ate pairing check on the elliptic curve alt_bn128)
  - [EIP-198](/EIPs/EIPS/eip-198) (Precompiled contract for bigint modular exponentiation)
  - [EIP-211](/EIPs/EIPS/eip-211) (New opcodes: RETURNDATASIZE and RETURNDATACOPY)
  - [EIP-214](/EIPs/EIPS/eip-214) (New opcode STATICCALL)
  - [EIP-649](/EIPs/EIPS/eip-649) (Difficulty Bomb Delay and Block Reward Reduction)
  - [EIP-658](/EIPs/EIPS/eip-658) (Embedding transaction status code in receipts)

## References

1. https://blog.ethereum.org/2017/10/12/byzantium-hf-announcement/

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 23 Apr 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-609</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-609</guid>
      </item>
    
      <item>
        <title>Subroutines and Static Jumps for the EVM</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-615-subroutines-and-static-jumps-for-the-evm-last-call/3472</comments>
        
        <description>## Simple Summary

In the 21st century, on a blockchain circulating billions of ETH, formal specification and verification are an essential tool against loss. Yet the design of the EVM makes this unnecessarily difficult. Further, the design of the EVM makes near-linear-time compilation to machine code difficult. We propose to move forward with proposals to resolve these problems by tightening EVM security guarantees and reducing barriers to performance.

## Abstract

EVM code is currently difficult to statically analyze, hobbling critical tools for preventing the many expensive bugs our blockchain has experienced. Further, none of the current implementations of the Ethereum Virtual Machine—including the compilers—are sufficiently performant to reduce the need for precompiles and otherwise meet the network&apos;s long-term demands.  This proposal identifies dynamic jumps as a major reason for these issues, and proposes changes to the EVM specification to address the problem, making further efforts towards a safer and more performant the EVM possible.

We also propose to validate—in near-linear time—that EVM contracts correctly use subroutines, avoid misuse of the stack, and meet other safety conditions _before_ placing them on the blockchain.  Validated code precludes most runtime exceptions and the need to test for them.  And well-behaved control flow and use of the stack makes life easier for interpreters, compilers, formal analysis, and other tools.

## Motivation

Currently the EVM supports only dynamic jumps, where the address to jump to is an argument on the stack.  Worse, the EVM fails to provide ordinary, alternative control flow facilities like subroutines and switches provided by Wasm and most CPUs.  So dynamic jumps cannot be avoided, yet they obscure the structure of the code and thus mostly inhibit control- and data-flow analysis.  This puts the quality and speed of optimized compilation fundamentally at odds.  Further, since many jumps can potentially be to any jump destination in the code, the number of possible paths through the code can go up as the product of the number of jumps by the number of destinations, as does the time complexity of static analysis.  Many of these cases are undecidable at deployment time, further inhibiting static and formal analyses.

However, given Ethereum&apos;s security requirements, **near-linear** **`n log n`** **time complexity** is essential.  Otherwise, Contracts can be crafted or discovered with quadratic complexity to use as denial of service attack vectors against validations and optimizations.

But absent dynamic jumps code can be statically analyzed in linear time.  That allows for _linear time validation_.  It also allows for code generation and such optimizations as can be done in `log n` time to comprise an _`n log n`_ _time compiler_.

And absent dynamic jumps, and with proper subroutines the EVM is a better target for code generation from other languages, including
* Solidity
* Vyper
* LLVM IR
  * front ends include C, C++, Common Lisp, D, Fortran, Haskell, Java, Javascript, Kotlin, Lua, Objective-C, Pony, Pure, Python, Ruby, Rust, Scala, Scheme, and Swift

The result is that all of the following validations and optimizations can be done at deployment time with near-linear `(n log n)` time complexity.
* The absence of most exceptional halting states can be validated.
* The maximum use of resources can be sometimes be calculated.
* Bytecode can be compiled to machine code in near-linear time.
* Compilation can more effectively optimize use of smaller registers.
* Compilation can more effectively optimize injection of gas metering.

## Specification

### Dependencies

&gt; **[EIP-1702](/EIPs/EIPS/eip-1702). Generalized Account Versioning Scheme.** This proposal needs a versioning scheme to allow for its bytecode (and eventually eWasm bytecode) to be deployed with existing bytecode on the same blockchain.

### Proposal

We propose to deprecate two existing instructions—`JUMP` and `JUMPI`—and propose new instructions to support their legitimate uses.  In particular, it must remain possible to compile Solidity and Vyper code to EVM bytecode, with no significant loss of performance or increase in gas price.

Especially important is efficient translation to and from [eWasm](https://github.com/ewasm/design) and to machine code.  To that end we maintain a close correspondence between [Wasm](https://webassembly.github.io/spec/core/_download/WebAssembly.pdf), [x86](https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf), [ARM](https://static.docs.arm.com/100076/0100/arm_instruction_set_reference_guide_100076_0100_00_en.pdf) and proposed EVM instructions.

| EIP-615   | Wasm          | x86  | ARM
| --------- | ------------- | ---- | ---- |
| JUMPTO    | br            | JMP  | B    |
| JUMPIF    | br_if         | JE   | BEQ  |
| JUMPV     | br_table      | JMP  | TBH  |
| JUMPSUB   | call          | CALL | BL   |
| JUMPSUBV  | call_indirect | CALL | BL   |
| RETURN    | return        | RET  | RET  |
| GETLOCAL  | local.get     | POP  | POP  |
| PUTLOCAL  | local.put     | PUSH | PUSH |
| BEGINSUB  | func          |      |      |
| BEGINDATA | tables        |      |      |

#### Preliminaries

These forms
&gt; *`INSTRUCTION`*
&gt;
&gt; *`INSTRUCTION x`*
&gt;
&gt; *`INSTRUCTION x, y`*

name an *`INSTRUCTION`* with no, one and two arguments, respectively. An instruction is represented in the bytecode as a single-byte opcode. Any arguments are laid out as immediate data bytes following the opcode inline, interpreted as fixed length, MSB-first, two&apos;s-complement, two-byte positive integers. (Negative values are reserved for extensions.)

#### Branches and Subroutines

The two most important uses of `JUMP` and `JUMPI` are static jumps and return jumps. Conditional and unconditional static jumps are the mainstay of control flow.  Return jumps are implemented as a dynamic jump to a return address pushed on the stack.  With the combination of a static jump and a dynamic return jump you can—and Solidity does—implement subroutines.  The problem is that static analysis cannot tell the one place the return jump is going, so it must analyze every possibility (a heavy analysis).

Static jumps are provided by
&gt; `JUMPTO jump_target`
&gt;
&gt; `JUMPIF jump_target`
&gt;
&gt; which are the same as `JUMP` and `JUMPI` except that they jump to an immediate `jump_target` rather than an address on the stack.

To support subroutines, `BEGINSUB`, `JUMPSUB`, and `RETURNSUB` are provided.  Brief descriptions follow, and full semantics are given below.

&gt; `BEGINSUB n_args, n_results`
&gt;
&gt; marks the **single** entry to a subroutine.  `n_args` items are taken off of the stack at entry to, and `n_results` items are placed on the stack at return from the subroutine.   The subroutine ends at the next `BEGINSUB` instruction (or `BEGINDATA`, below) or at the end of the bytecode.

&gt; `JUMPSUB jump_target`
&gt;
&gt; jumps to an immediate subroutine address.

&gt; `RETURNSUB`
&gt;
&gt;returns from the current subroutine to the instruction following the JUMPSUB that entered it.

#### Switches, Callbacks, and Virtual Functions

Dynamic jumps are also used for `O(1)` indirection: an address to jump to is selected to push on the stack and be jumped to.  So we also propose two more instructions to provide for constrained indirection.  We support these with vectors of `JUMPDEST` or `BEGINSUB` offsets stored inline, which can be selected with an index on the stack.  That constrains validation to a specified subset of all possible destinations.  The danger of quadratic blow up is avoided because it takes as much space to store the jump vectors as it does to code the worst case exploit.

Dynamic jumps to a `JUMPDEST` are used to implement `O(1)` jumptables, which are useful for dense switch statements.  Wasm and most CPUs provide similar instructions.

&gt; `JUMPV n, jump_targets`
&gt;
&gt; jumps to one of a vector of `n` `JUMPDEST` offsets via a zero-based index on the stack.  The vector is stored inline at the `jump_targets` offset after the BEGINDATA bytecode as MSB-first, two&apos;s-complement, two-byte positive integers.  If the index is greater than or equal to `n - 1` the last (default) offset is used.

Dynamic jumps to a `BEGINSUB` are used to implement `O(1)` virtual functions and callbacks, which take at most two pointer dereferences on most CPUs.   Wasm provides a similar instruction.

&gt; `JUMPSUBV n, jump_targets`
&gt;
&gt;jumps to one of a vector of `n` `BEGINSUB` offsets via a zero-based index on the stack.  The vector is stored inline at the `jump_targets` offset after the DATA bytecode, as MSB-first, two&apos;s-complement, two-byte positive integers.  If the index is greater than or equal to `n - 1` the last (default) offset is used.

#### Variable Access

These operations provide convenient access to subroutine parameters and local variables at fixed stack offsets within a subroutine.  Otherwise only sixteen variables can be directly addressed.

&gt; `PUTLOCAL n`
&gt;
&gt; Pops the stack to the local variable `n`.

&gt; `GETLOCAL n`
&gt;
&gt; Pushes the local variable `n` onto the stack.

Local variable `n` is the nth stack item below the frame pointer, `FP[-n]`, as defined below.

#### Data

There needs to be a way to place unreachable data into the bytecode that will be skipped over and not validated.  Indirect jump vectors will not be valid code.  Initialization code must create runtime code from data that might not be valid code.  And unreachable data might prove useful to programs for other purposes.

&gt; `BEGINDATA`
&gt;
&gt; specifies that all of the following bytes to the end of the bytecode are data, and not reachable code.

#### Structure

Valid EIP-615 EVM bytecode begins with a valid header.  This is the magic number  ‘\0evm’ followed by the semantic versioning number &apos;\1\5\0&apos;.  (For Wasm the header is &apos;\0asm\1&apos;).

Following the header is the BEGINSUB opcode for the _main_ routine.  It takes no arguments and returns no values.  Other subroutines may follow the _main_ routine, and an optional BEGINDATA opcode may mark the start of a data section.

### Semantics

Jumps to and returns from subroutines are described here in terms of
* The EVM data stack, (as defined in the [Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf)) usually just called “the stack.”
* A return stack of `JUMPSUB` and `JUMPSUBV` offsets.
* A frame stack of frame pointers.

We will adopt the following conventions to describe the machine state:
* The _program counter_ `PC` is (as usual) the byte offset of the currently executing instruction.
* The _stack pointer_ `SP` corresponds to the [Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf)&apos;s substate `s` of the machine state.
  * `SP[0]` is where a new item is can be pushed on the stack.
  * `SP[1]` is the first item on the stack, which can be popped off the stack.
  * The stack grows towards lower addresses.
* The _frame pointer_ `FP` is set to `SP + n_args` at entry to the currently executing subroutine.
  * The _stack items_ between the frame pointer and the current stack pointer are called the _frame_.
  * The current number of items in the frame, `FP - SP`, is the _frame size_.

&gt; **Note**: Defining the frame pointer so as to include the arguments is unconventional, but better fits our stack semantics and simplifies the remainder of the proposal.

The frame pointer and return stacks are internal to the subroutine mechanism, and not directly accessible to the program.  This is necessary to prevent the program from modifying its own state in ways that could be invalid.

Execution of EVM bytecode begins with the _main_ routine with no arguments, `SP` and `FP` set to 0, and with one value on the return stack—`code_size - 1`. (Executing the virtual byte of 0 after this offset causes an EVM to stop.  Thus executing a `RETURNSUB` with no prior `JUMPSUB` or `JUMBSUBV`—that is, in the _main_ routine—executes a `STOP`.)

Execution of a subroutine begins with `JUMPSUB` or `JUMPSUBV`, which

* pushes `PC` on the return stack,
* pushes `FP` on the frame stack
  * thus suspending execution of the current subroutine,
* sets `FP` to `SP + n_args`, and
* sets `PC` to the specified `BEGINSUB` address
  * thus beginning execution of the new subroutine.

Execution of a subroutine is suspended during and resumed after execution of nested subroutines, and ends upon encountering a `RETURNSUB`, which

* sets `FP` to the top of the virtual frame stack and pops the stack,
* sets `SP` to `FP + n_results`,
* sets `PC` to top of the return stack and pops the stack, and
* advances `PC` to the next instruction

thus resuming execution of the enclosing subroutine or _main_ routine.  A `STOP` or `RETURN` also ends the execution of a subroutine.

For example, starting from this stack,
```
_________________
      | locals      20 &lt;- FP
frame |             21
______|___________  22
                       &lt;- SP
```
and after pushing two arguments and branching with `JUMPSUB` to a `BEGINSUB 2, 3`
```
PUSH 10
PUSH 11
JUMPSUB beginsub
```
and initializing three local variables
```
PUSH 99
PUSH 98
PUSH 97
```
the stack looks like this
```
                    20
                    21
__________________  22
      | arguments   10 &lt;- FP
frame |___________  11
      | locals      99
      |             98
______|___________  97
                       &lt;- SP
```
After some amount of computation the stack could look like this
```
                    20
                    21
__________________  22
      | returns     44 &lt;- FP
      |             43
frame |___________  42
      | locals      13
______|___________  14
                       &lt;- SP
```
and after `RETURNSUB` would look like this
```
_________________
      | locals      20 &lt;- FP
      |             21
frame |___________  22
      | returns     44
      |             43
______|___________  42
                       &lt;- SP
```

### Validity

We would like to consider EVM code valid iff no execution of the program can lead to an exceptional halting state, but we must validate code in linear time. So our validation does not consider the code’s data and computations, only its control flow and stack use.  This means we will reject programs with invalid code paths, even if those paths are not reachable.  Most conditions can be validated, and will not need to be checked at runtime; the exceptions are sufficient gas and sufficient stack.  As such, static analysis may yield false negatives belonging to well-understood classes of code requiring runtime checks.  Aside from those cases, we can validate large classes at validation time and with linear complexity.

_Execution_ is as defined in the [Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf)—a sequence of changes in the EVM state.  The conditions on valid code are preserved by state changes.  At runtime, if execution of an instruction would violate a condition the execution is in an exceptional halting state.  The Yellow Paper defines five such states.
&gt;**1**  Insufficient gas

&gt;**2**  More than 1024 stack items

&gt;**3**  Insufficient stack items

&gt;**4**  Invalid jump destination

&gt;**5**  Invalid instruction

We propose to expand and extend the Yellow Paper conditions to handle the new instructions we propose.

To handle the return stack we expand the conditions on stack size:
&gt;**2a**  The size of the data stack does not exceed 1024.

&gt;**2b**  The size of the return stack does not exceed 1024.

Given our more detailed description of the data stack we restate condition 3—stack underflow—as
&gt;**3**  `SP` must be less than or equal to `FP`

Since the various `DUP` and `SWAP` operations—as well as `PUTLOCAL` and `GETLOCAL`—are defined as taking items off the stack and putting them back on, this prevents them from accessing data below the frame pointer, since taking too many items off of the stack would mean that `SP` is less than `FP`.

To handle the new jump instructions and subroutine boundaries, we expand the conditions on jumps and jump destinations.
&gt;**4a**  `JUMPTO`, `JUMPIF`, and `JUMPV` address only `JUMPDEST` instructions.

&gt;**4b**  `JUMPSUB` and `JUMPSUBV` address only `BEGINSUB` instructions.

&gt;**4c**  `JUMP` instructions do not address instructions outside of the subroutine they occur in.

We have two new conditions on execution to ensure consistent use of the stack by subroutines:
&gt;**6**  For `JUMPSUB` and `JUMPSUBV` the frame size is at least the `n_args` of the `BEGINSUB`(s) to jump to.

&gt;**7**  For `RETURNSUB` the frame size is equal to the `n_results` of the enclosing `BEGINSUB`.

Finally, we have one condition that prevents pathological uses of the stack:
&gt;**8**  For every instruction in the code the frame size is constant.

In practice, we must test at runtime for conditions 1 and 2—sufficient gas and sufficient stack.  We don’t know how much gas there will be, we don’t know how deep a recursion may go, and analysis of stack depth even for non-recursive programs is nontrivial.

All of the remaining conditions we validate statically.


#### Costs &amp; Codes

All of the instructions are `O(1)` with a small constant, requiring just a few machine operations each, whereas a `JUMP` or `JUMPI` typically does an `O(log n)` binary search of an array of `JUMPDEST` offsets before every jump. With the cost of `JUMPI` being _high_ and the cost of `JUMP` being _mid_, we suggest the cost of `JUMPV` and `JUMPSUBV` should be _mid_, `JUMPSUB` and `JUMPIF` should be _low_, and`JUMPTO` and the rest should be _verylow_.  Measurement will tell.

We suggest the following opcodes:
```
0xb0 JUMPTO
0xb1 JUMPIF
0xb2 JUMPV
0xb3 JUMPSUB
0xb4 JUMPSUBV
0xb5 BEGINSUB
0xb6 BEGINDATA
0xb7 RETURNSUB
0xb8 PUTLOCAL
0xb9 GETLOCAL
```

## Backwards Compatibility

These changes would need to be implemented in phases at decent intervals:
&gt;**1.**  If this EIP is accepted, invalid code should be deprecated. Tools should stop generating invalid code, users should stop writing it, and clients should warn about loading it.

&gt;**2.**  A later hard fork would require clients to place only valid code on the block chain.  Note that despite the fork old EVM code will still need to be supported indefinitely; older contracts will continue to run, and to create new contracts.

If desired, the period of deprecation can be extended indefinitely by continuing to accept code not versioned as new—but without validation.  That is, by delaying or canceling phase 2.

Regardless, we will need a versioning scheme like [EIP-1702](/EIPs/EIPS/eip-1702) to allow current code and EIP-615 code to coexist on the same blockchain.

## Rationale

This design was highly constrained by the existing EVM semantics, the requirement for eWasm compatibility, and the security demands of the Ethereum environment.  It was also informed by the lead author&apos;s previous work implementing Java and Scheme interpreters.  As such there was very little room for alternative designs.

As described above, the approach was simply to deprecate the problematic dynamic jumps, then ask what opcodes were necessary to provide for the features they supported.  These needed to include those provided by eWasm, which themselves were modeled after typical hardware.  The only real innovation was to move the frame pointer and the return pointer to their own stacks, so as to prevent any possibility of overwriting them. (Although Forth also uses a return stack.)  This allowed for treating subroutine arguments as local variables, and facilitated the return of multiple values.

## Implementation

Implementation of this proposal need not be difficult.  At the least, interpreters can simply be extended with the new opcodes and run unchanged otherwise.  The new opcodes require only stacks for the frame pointers and return offsets and the few pushes, pops, and assignments described above. The bulk of the effort is the validator, which in most languages can almost be transcribed from the pseudocode above.

A lightly tested C++ reference implementation is available in [Greg Colvin&apos;s Aleth fork.](https://github.com/gcolvin/aleth/tree/master/libaleth-interpreter)  This version required circa 110 lines of new interpreter code and a well-commented, 178-line validator.

## Appendix A
### Validation

Validation comprises two tasks:
* Check that jump destinations are correct and instructions valid.
* Check that subroutines satisfy the conditions on control flow and stack use.

We sketch out these two validation functions in pseudo-C below.  To simplify the presentation only the five primitives are handled (`JUMPV` and `JUMPSUBV` would just add more complexity to loop over their vectors), we assume helper functions for extracting instruction arguments from immediate data and managing the stack pointer and program counter, and some optimizations are forgone.

#### Validating Jumps

Validating that jumps are to valid addresses takes two sequential passes over the bytecode—one to build sets of jump destinations and subroutine entry points, another to check that addresses jumped to are in the appropriate sets.
```
    bytecode[code_size]   // contains EVM bytecode to validate
    is_sub[code_size]     // is there a BEGINSUB at PC?
    is_dest[code_size]    // is there a JUMPDEST at PC?
    sub_for_pc[code_size] // which BEGINSUB is PC in?

    bool validate_jumps(PC)
    {
        current_sub = PC

        // build sets of BEGINSUBs and JUMPDESTs
        for (PC = 0; instruction = bytecode[PC]; PC = advance_pc(PC))
        {
            if instruction is invalid
                return false
            if instruction is BEGINDATA
                break;
            if instruction is BEGINSUB
                is_sub[PC] = true
                current_sub = PC
                sub_for_pc[PC] = current_sub
            if instruction is JUMPDEST
                is_dest[PC] = true
            sub_for_pc[PC] = current_sub
        }

        // check that targets are in subroutine
        for (PC = 0; instruction = bytecode[PC]; PC = advance_pc(PC))
        {
            if instruction is BEGINDATA
                break;
            if instruction is BEGINSUB
                current_sub = PC
            if instruction is JUMPSUB
                if is_sub[jump_target(PC)] is false
                    return false
            if instruction is JUMPTO or JUMPIF
                if is_dest[jump_target(PC)] is false
                    return false
            if sub_for_pc[PC] is not current_sub
                return false
       }
       return true
    }
```
Note that code like this is already run by EVMs to check dynamic jumps, including building the jump destination set every time a contract is run, and doing a lookup in the jump destination set before every jump.

#### Subroutine Validation

This function can be seen as a symbolic execution of a subroutine in the EVM code, where only the effect of the instructions on the state being validated is computed.  Thus the structure of this function is very similar to an EVM interpreter.  This function can also be seen as an acyclic traversal of the directed graph formed by taking instructions as vertices and sequential and branching connections as edges, checking conditions along the way.  The traversal is accomplished via recursion, and cycles are broken by returning when a vertex which has already been visited is reached.  The time complexity of this traversal is `O(|E|+|V|)`: The sum of the number of edges and number of vertices in the graph.

The basic approach is to call `validate_subroutine(i, 0, 0)`, for `i` equal to the first instruction in the EVM code through each `BEGINDATA` offset.  `validate_subroutine()` traverses instructions sequentially, recursing when `JUMP` and `JUMPI` instructions are encountered.  When a destination is reached that has been visited before it returns, thus breaking cycles.  It returns true if the subroutine is valid, false otherwise.

```
    bytecode[code_size]     // contains EVM bytecode to validate
    frame_size[code_size ]  // is filled with -1

    // we validate each subroutine individually, as if at top level
    // * PC is the offset in the code to start validating at
    // * return_pc is the top PC on return stack that RETURNSUB returns to
    // * at top level FP = SP = 0 is both the frame size and the stack size
    // * as items are pushed SP get more negative, so the stack size is -SP
    validate_subroutine(PC, return_pc, SP)
    {
        // traverse code sequentially, recurse for jumps
        while true
        {
            instruction = bytecode[PC]

            // if frame size set we have been here before
            if frame_size[PC] &gt;= 0
            {
                // check for constant frame size
                if instruction is JUMPDEST
                    if -SP != frame_size[PC]
                        return false

                // return to break cycle
                return true
            }
            frame_size[PC] = -SP

            // effect of instruction on stack
            n_removed = removed_items(instructions)
            n_added = added_items(instruction)

            // check for stack underflow
            if -SP &lt; n_removed
                return false

            // net effect of removing and adding stack items
            SP += n_removed
            SP -= n_added

            // check for stack overflow
            if -SP &gt; 1024
                return false

            if instruction is STOP, RETURN, or SUICIDE
                return true

            // violates single entry
            if instruction is BEGINSUB
                 return false

            // return to top or from recursion to JUMPSUB
            if instruction is RETURNSUB
                return true;;

            if instruction is JUMPSUB
            {
                // check for enough arguments
                sub_pc = jump_target(PC)
                if -SP &lt; n_args(sub_pc)
                    return false
                return true
            }

            // reset PC to destination of jump
            if instruction is JUMPTO
            {
                PC = jump_target(PC)
                continue
            }

            // recurse to jump to code to validate
            if instruction is JUMPIF
            {
                if not validate_subroutine(jump_target(PC), return_pc, SP)
                    return false
            }

            // advance PC according to instruction
            PC = advance_pc(PC)
        }

        // check for right number of results
        if (-SP != n_results(return_pc)
            return false
        return true
    }
```
## Appendix B
### EVM Analysis

There is a large and growing ecosystem of researchers, authors, teachers, auditors, and analytic tools--providing software and services focused on the correctness and security of EVM code.  A small sample is given here.

#### Some Tools

* [Contract Library](https://contract-library.com/)
* [EthereumJ](https://github.com/ethereum/ethereumj)
* [Exthereum](https://github.com/exthereum/blockchain)
* [Harmony](https://github.com/ether-camp/ethereum-harmony)
* [JEB](https://www.pnfsoftware.com/blog/ethereum-smart-contract-decompiler/)
* [Mythril](https://github.com/ConsenSys/mythril)
* [Securify](https://github.com/eth-sri/securify)
* [Skale](https://www.skalelabs.com/)
* [Status](https://status.im/)

#### Some Papers

* [A Formal Verification Tool for Ethereum VM Bytecode](https://www.google.com/url?q=http://fsl.cs.illinois.edu/FSL/papers/2018/park-zhang-saxena-daian-rosu-2018-fse/park-zhang-saxena-daian-rosu-2018-fse-public.pdf)
* [A Lem formalization of EVM and some Isabelle/HOL proofs](https://github.com/pirapira/eth-isabelle)
* [A survey of attacks on Ethereum smart contracts](https://eprint.iacr.org/2016/1007.pdf)
* [Defining the Ethereum Virtual Machine for Interactive Theorem Provers](https://www.google.com/url?q=http://fc17.ifca.ai/wtsc/Defining%2520the%2520Ethereum%2520Virtual%2520Machine%2520for%2520Interactive%2520Theorem%2520Provers.pdf)
* [Ethereum 2.0 Specifications](https://github.com/ethereum/eth2.0-specs)
* [Formal Verification of Smart Contracts](https://www.cs.umd.edu/~aseem/solidetherplas.pdf)
* [JelloPaper: Human Readable Semantics of EVM in K](https://jellopaper.org/)
* [KEVM: A Complete Semantics of the Ethereum Virtual Machine.](https://www.ideals.illinois.edu/items/102260)
* [Making Smart Contracts Smarter](https://eprint.iacr.org/2016/633.pdf)
* [Securify: Practical Security Analysis of Smart Contracts](https://arxiv.org/pdf/1806.01143.pdf)
* [The Thunder Protocol](https://docs.thundercore.com/thunder-whitepaper.pdf)
* [Towards Verifying Ethereum Smart Contract Bytecode in Isabelle/HOL](https://trustworthy.systems/publications/full_text/Amani_BBS_18.pdf)
*[A Lem formalization of EVM 1.5](https://github.com/seed/eth-isabelle/tree/evm15)


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 10 Dec 2016 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-615</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-615</guid>
      </item>
    
      <item>
        <title>SIMD Operations for the EVM</title>
        <category>Standards Track/Core</category>
        
        <description>## ABSTRACT

A proposal to provide Single Instruction Multiple Data types and operations for the Ethereum Virtual Machine, making full use of the 256-bit wide EVM stack items, and offering substantial performance gains for both vector and scalar operations.

## MOTIVATION

Most all modern CPUs include SIMD hardware that operates on wide registers of data, applying a Single Instruction to Multiple Data lanes in parallel, where lanes divide a register into a vector of scalar elements of equal size.  This model is an excellent fit for the wide stack items of the EVM, offering substantial performance boosts for operations that can be expressed as parallel operations on vectors of scalars.  For some examples, a brief literature search finds SIMD speedups of
* up to 7X for [SHA-512](http://keccak.noekeon.org/sw_performance.html)
* 4X for [elliptic curve scalar multiplication](https://link.springer.com/chapter/10.1007/3-540-45439-X_16)
* 3X to 4X for [BLAKE2b](https://github.com/minio/blake2b-simd)
* up to 3X for [OpenSSL](https://software.intel.com/en-us/articles/improving-openssl-performance)
* 2X to 3X for [elliptic curve modular multiplication](http://ieee-hpec.org/2013/index_htm_files/24-Simd-acceleration-Pabbuleti-2886999.pdf)
* 1.7X to 1.9X for [SHA-256](https://github.com/minio/sha256-simd)
* 1.3X for [RSA encryption](https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.738.1218&amp;rep=rep1&amp;type=pdf)

## SPECIFICATION

### Encoding

We propose a simple encoding of SIMD operations as extended two-byte codes.  The first byte is the opcode, and the second byte is the SIMD type: scalar type, lane width, and number of elements.

 N bits | Field
-|-
8 | opcode
1 | scalar type: 0 = unsigned integer, 1 = IEEE float
1 | reserved: 0
2 | lane width: log base 2 of the number of bytes, as an MSB first integer
1 | reserved: 0
3 | element count: log base 2 of the number of lanes, as an MSB first integer

Thus we can specify SIMD types with unsigned integer lanes from 8 to 64 bits in vectors of 32 to 2 lanes, respectively.  Floating point lanes however support only 32- and 64-bit IEEE floating point.  And a type of _0x7F_ represents a normal 256-bit EVM integer.

_Note that when the element count is one the operation is on one scalar, so this specification also provides for native operations on single scalars of native sizes._

_Note that floating point operations are **not** proposed for inclusion in the initial release, but we considered it important to reserve code space for possible future expansion._

### Semantics

We define the following extended versions of the EVM&apos;s arithmetic, logic, and comparison operations.  As with the normal versions, they consume their arguments from the stack and place their results on the stack, except that their arguments are vectors rather than scalars.

lo\hi |	B             | C
-|-|-
0|                     | XLT
1| XADD           | XGT
2| XMUL          | XSLT
3| XSUB           | XSGT
4| XDIV            | XEQ
5| XSDIV          | XISZERO
6| XMOD          | XAND
7| XSMOD        | XOR
8|                      | XXOR
9|                       | XNOT
A|                       | XINDEX
B|                       | XSHL
C|                       | XSHR
D|                       | XSAR
E| XCAST           | XROL
F| XSHUFFLE      | XROR

Except for XSHUFFLE, XCAST, and XINDEX all the extended operations on unsigned integer values have the same semantics as the corresponding operations for codes 01 through 1F, except that the modulus varies by scalar type and the operations are applied pair-wise to the elements of the source operands to compute the destination elements.  _The source operands must have the same element type and number of elements._  E.g.
```
PUSH uint8[1, 2, 3]
PUSH uint8[4, 5, 6]
XADD
```
leaves
```
uint8[5, 7, 9]
```
on the stack.

XSHUFFLE takes two vectors on the stack: a vector to permute and a permutation mask.  E.g.
```
PUSH uint64[4, 5, 6, 0]
PUSH uint8[2, 0, 1, 3]
SHUFFLE
```
leaves
```
uint64[6, 4, 5 , 0]
```
on the stack. The mask must have integral type, and the same number of elements as the source vector.

The second byte of the XCAST opcode is applied to the item on the stack to create a new vector of the specified type.  Elements are converted according to the usual C conventions, missing elements are set to zero, and extra elements are discarded.  If the stack item is not a vector it is converted to a vector by taking its bits least-significant-bit first and copying them into the corresponding bits of each element, least-significant-element first.  Again, excess data is truncated and missing data is 0-filled.  Vectors are converted to 256-bit EVM integers via the reverse process., with elements that are floating point NANs normalized to all bits on.

_Note that MLOAD and MSTORE are valid only on 256-bit EVM integers.  For SIMD vectors an XCAST is needed after a load and before a store to convert vectors to and from 256-bit integers._

XINDEX has the same semantics as BYTE, except that individual elements of the vector are indexed.

Floating point values follow IEEE 754 semantics.  Since those are not defined for shifting and rotating those operations are defined here as having no effect.

Extended operations other than XSHUFFLE and XCAST are only valid on vectors of the same SIMD type.  This can be validated at contract creation time, or else checked at runtime.

### Subroutines

If [EIP-187](https://github.com/ethereum/EIPs/pull/187) is accepted a type-safe syntax for declaring subroutines taking vector arguments will be needed.

* `BEGINSUBX n_args, arg_types... n_results, result_types...`
marks the **single** entry to a subroutine.  `n_args` items are taken off of the stack at entry to, and `n_results` items are placed on the stack at return from the subroutine. `n_args` and `n_results` are given as one immediate byte each.  The `arg_types` and `result_types` are given in the same encoding as second byte of the SIMD opcodes, and must match the values on the stack.  The bytecode for a subroutine ends at the next `BEGINSUB`, `BEGINSUBX` or `BEGINDATA` instruction or at the end of the bytecode.

## RATIONALE

Currently, the lowest common denominator for SIMD hardware (e.g. Intel SSE2 and ARM Neon) is 16-byte registers supporting integer lanes of 1, 2, 4, and 8 bytes, and floating point lanes of 4 and 8 bytes.  More recent SIMD hardware (e.g. Intel AVX) supports 32-byte registers, and EVM stack items are also 32 bytes wide.  The limits above derive from these numbers, assuring that EVM code is within the bounds of available hardware - and the reserved bits provide room for growth.

For most modern languages (including Rust, Python, Go, Java, and C++) compilers can do a good job of generating SIMD code for parallelizable loops, and/or there are intrinsics or libraries available for explicit access to SIMD hardware.  So a portable software implementation will likely provide good use of the hardware on most platforms, and intrinsics or libraries can be used as available and needed.  Thus we can expect these operations to take about the same (or for 256-bit vectors on 128-bit hardware up to twice) the time to execute regardless of element size or number of elements.

### Gas

One motivation for these operations, besides taking full advantage of the hardware, is assigning lower gas costs for operations on smaller scalars.

On a machine with 64-bit registers the standard algorithms from Knuth&apos;s [Art of Computer Programming](https://library.aceondo.net/ebooks/Computer_Science/algorithm-the_art_of_computer_programming-knuth.pdf) require 32-bit digits, using the upper half of a register for overflows, so for 256-bit values N=8 digits are needed, and for 64-bit values N=2 digits are needed.  The cycle counts for these algorithms are:

operation | cycles | N = 2 | N = 4 | N = 8
-|-|-|-|-
add | 10 _N_ + 6 | 26 | 46 | 86
subtract | 12 _N_ + 3 |27 | 51 | 99
multiply | 28 _N_**2 + 11 _N_ + 3 | 137 | 495 |1883
divide | 15 _N_**2 + 119 _N_ + 111 | 409 | 827 | 2023

The remaining operations are of about the same complexity as addition and subtraction, or less. Given that JUMPDEST is a no-op, and is assigned a gas price of 1, this can be taken as the overhead of the interpreter.  All of the arithmetic operations are assigned the same gas price of 5, for a remaining runtime of 4.  The interpreter loop itself takes about 6 to 8 C instructions, so ADD and SUB are reasonably priced, but MUL is some 5 to 21 times slower than ADD or SUB, and DIV is some 15 to 23 times slower, so they are clearly mispriced.

By comparison, on most [Intel](https://software.intel.com/sites/landingpage/IntrinsicsGuide) and [ARM](https://developer.arm.com/docs/100166/latest/programmers-model/instruction-set-summary/table-of-processor-instructions) SIMD units instructions take approximately the following cycle counts, independent of register width.

operation | Intel cycles | ARM cycles | gas
-|-|-|-
add | .5 | 1 | 1
subtract | .5 | 1 | 1
multiply | 2 | 1 | 1
divide | 10 | 12 | 2

Since all but the divide operation take fewer cycles than the interpreter overhead they are assigned the minimal cost of 1.  Division takes slightly more, and is assigned a cost of 2.
</description>
        <pubDate>Tue, 25 Apr 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-616</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-616</guid>
      </item>
    
      <item>
        <title>Whisper Specification</title>
        <category>Standards Track/Networking</category>
        
        <description>## Abstract

This EIP describes the format of Whisper messages within the ÐΞVp2p Wire Protocol.
This EIP should substitute the [existing specification](https://github.com/ethereum/wiki/wiki/Whisper-Wire-Protocol).
More detailed documentation on Whisper could be found [here](https://github.com/ethereum/go-ethereum/wiki/Whisper).

## Motivation

It is necessary to specify the standard for Whisper messages in order to ensure forward compatibility of different Whisper clients.

## Specification

All Whisper messages sent as ÐΞVp2p Wire Protocol packets should be RLP-encoded arrays of data containing two objects: integer packet code followed by another object (whose type depends on the packet code). 

If Whisper node does not support a particular packet code, it should just ignore the packet without generating any error.

### Packet Codes

The message codes reserved for Whisper protocol: 0 - 127.
Messages with unknown codes must be ignored, for forward compatibility of future versions.

The Whisper sub-protocol should support the following packet codes:

| EIP   | Name                       | Int Value |
|-------|----------------------------|-----------|
|       | Status                     |     0     |
|       | Messages                   |     1     |
|       | PoW Requirement            |     2     |
|       | Bloom Filter               |     3     |
|-------|----------------------------|-----------|


The following message codes are optional, but they are reserved for specific purpose.

| EIP   | Name                       | Int Value |
|-------|----------------------------|-----------|
|       | P2P Request                |    126    |
|       | P2P Message                |    127    |
|-------|----------------------------|-----------|

### Packet Format and Usage

**Status** [`0`]

This packet contains two objects: integer message code (0x00) followed by a list of values: integer version, float PoW requirement, and bloom filter, in this order. The bloom filter parameter is optional; if it is missing or nil, the node is considered to be full node (i.e. accepts all messages). The format of PoW and bloom filter please see below (message codes 2 and 3).

Status message should be sent after the initial handshake and prior to any other messages.

**Messages** [`1`, `whisper_envelopes`]

This packet contains two objects: integer message code (0x01) followed by a list (possibly empty) of Whisper Envelopes.

This packet is used for sending the standard Whisper envelopes.

**PoW Requirement** [`2`, `PoW`]

This packet contains two objects: integer message code (0x02) followed by a single floating point value of PoW. This value is the IEEE 754 binary representation of 64-bit floating point number. Values of qNAN, sNAN, INF and -INF are not allowed. Negative values are also not allowed.

This packet is used by Whisper nodes for dynamic adjustment of their individual PoW requirements. Recipient of this message should no longer deliver the sender messages with PoW lower than specified in this message.

PoW is defined as average number of iterations, required to find the current BestBit (the number of leading zero bits in the hash), divided by message size and TTL:

	PoW = (2**BestBit) / (size * TTL)

PoW calculation:

	fn short_rlp(envelope) = rlp of envelope, excluding env_nonce field.
	fn pow_hash(envelope, env_nonce) = sha3(short_rlp(envelope) ++ env_nonce)
	fn pow(pow_hash, size, ttl) = 2**leading_zeros(pow_hash) / (size * ttl)

where size is the size of the full RLP-encoded envelope.

**Bloom Filter** [`3`, `bytes`]

This packet contains two objects: integer message code (0x03) followed by a byte array of arbitrary size.

This packet is used by Whisper nodes for sharing their interest in messages with specific topics.

The Bloom filter is used to identify a number of topics to a peer without compromising (too much) privacy over precisely what topics are of interest. Precise control over the information content (and thus efficiency of the filter) may be maintained through the addition of bits.

Blooms are formed by the bitwise OR operation on a number of bloomed topics. The bloom function takes the topic and projects them onto a 512-bit slice. At most, three bits are marked for each bloomed topic.

The projection function is defined as a mapping from a 4-byte slice S to a 512-bit slice D; for ease of explanation, S will dereference to bytes, whereas D will dereference to bits.

	LET D[*] = 0
	FOREACH i IN { 0, 1, 2 } DO
	LET n = S[i]
	IF S[3] &amp; (2 ** i) THEN n += 256
	D[n] = 1
	END FOR


OPTIONAL

**P2P Request** [`126`, `whisper_envelope`]

This packet contains two objects: integer message code (0x7E) followed by a single Whisper Envelope.

This packet is used for sending Dapp-level peer-to-peer requests, e.g. Whisper Mail Client requesting old messages from the Whisper Mail Server.

**P2P Message** [`127`, `whisper_envelope`]

This packet contains two objects: integer message code (0x7F) followed by a single Whisper Envelope.

This packet is used for sending the peer-to-peer messages, which are not supposed to be forwarded any further. E.g. it might be used by the Whisper Mail Server for delivery of old (expired) messages, which is otherwise not allowed.


### Whisper Envelope

Envelopes are RLP-encoded structures of the following format:

	[ Expiry, TTL, Topic, Data, Nonce ]
	
`Expiry`: 4 bytes (UNIX time in seconds).

`TTL`: 4 bytes (time-to-live in seconds).

`Topic`: 4 bytes of arbitrary data.

`Data`: byte array of arbitrary size (contains encrypted message).

`Nonce`: 8 bytes of arbitrary data (used for PoW calculation).

### Contents of Data Field of the Message (Optional)

This section outlines the optional description of Data Field to set up an example. Later it may be moved to a separate EIP.

It is only relevant if you want to decrypt the incoming message, but if you only want to send a message, any other format would be perfectly valid and must be forwarded to the peers.

Data field contains encrypted message of the Envelope. In case of symmetric encryption, it also contains appended Salt (a.k.a. AES Nonce, 12 bytes). Plaintext (unencrypted) payload consists of the following concatenated fields: flags, auxiliary field, payload, padding and signature (in this sequence).

	flags: 1 byte; first two bits contain the size of auxiliary field, third bit indicates whether the signature is present.
	
	auxiliary field: up to 4 bytes; contains the size of payload.

	payload: byte array of arbitrary size (may be zero).

	padding: byte array of arbitrary size (may be zero).

	signature: 65 bytes, if present.

	salt: 12 bytes, if present (in case of symmetric encryption).

Those unable to decrypt the message data are also unable to access the signature. The signature, if provided, is the ECDSA signature of the Keccak-256 hash of the unencrypted data using the secret key of the originator identity. The signature is serialised as the concatenation of the `R`, `S` and `V` parameters of the SECP-256k1 ECDSA signature, in that order. `R` and `S` are both big-endian encoded, fixed-width 256-bit unsigned. `V` is an 8-bit big-endian encoded, non-normalised and should be either 27 or 28.

The padding field was introduced in order to align the message size, since message size alone might reveal important metainformation. Padding can be arbitrary size. However, it is recommended that the size of Data Field (excluding the Salt) before encryption (i.e. plain text) should be factor of 256 bytes.

### Payload Encryption

Asymmetric encryption uses the standard Elliptic Curve Integrated Encryption Scheme with SECP-256k1 public key.

Symmetric encryption uses AES GCM algorithm with random 96-bit nonce.

## Rationale

Packet codes 0x00 and 0x01 are already used in all Whisper versions.

Packet code 0x02 will be necessary for the future development of Whisper. It will provide possibility to adjust the PoW requirement in real time. It is better to allow the network to govern itself, rather than hardcode any specific value for minimal PoW requirement.

Packet code 0x03 will be necessary for scalability of the network. In case of too much traffic, the nodes will be able to request and receive only the messages they are interested in.

Packet codes 0x7E and 0x7F may be used to implement Whisper Mail Server and Client. Without P2P messages it would be impossible to deliver the old messages, since they will be recognized as expired, and the peer will be disconnected for violating the Whisper protocol. They might be useful for other purposes when it is not possible to spend time on PoW, e.g. if a stock exchange will want to provide live feed about the latest trades.

## Backwards Compatibility

This EIP is compatible with Whisper version 6. Any client which does not implement certain packet codes should gracefully ignore the packets with those codes. This will ensure the forward compatibility. 

## Implementation

The golang implementation of Whisper (v.6) already uses packet codes 0x00 - 0x03. Parity&apos;s implementation of v.6 will also use codes 0x00 - 0x03. Codes 0x7E and 0x7F are reserved, but still unused and left for custom implementation of Whisper Mail Server.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 05 May 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-627</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-627</guid>
      </item>
    
      <item>
        <title>Storage of text records in ENS</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2439</comments>
        
        <description>## Abstract
This EIP defines a resolver profile for ENS that permits the lookup of arbitrary key-value
text data. This allows ENS name holders to associate e-mail addresses, URLs and other
informational data with a ENS name.


## Motivation
There is often a desire for human-readable metadata to be associated with otherwise
machine-driven data; used for debugging, maintenance, reporting and general information.

In this EIP we define a simple resolver profile for ENS that permits ENS names to
associate arbitrary key-value text.


## Specification

### Resolver Profile

A new resolver interface is defined, consisting of the following method:

```solidity
interface IERC634 {
  /// @notice Returns the text data associated with a key for an ENS name
  /// @param node A nodehash for an ENS name
  /// @param key A key to lookup text data for
  /// @return The text data
  function text(bytes32 node, string key) view returns (string text);
}
```

The [EIP-165](/EIPs/EIPS/eip-165) interface ID of this interface is `0x59d1d43c`.

The `text` data may be any arbitrary UTF-8 string. If the key is not present, the empty string
must be returned.


### Global Keys

Global Keys must be made up of lowercase letters, numbers and
the hyphen (-).

- **avatar** - a URL to an image used as an avatar or logo
- **description** - A description of the name
- **display** - a canonical display name for the ENS name; this MUST match the ENS name when its case is folded, and clients should ignore this value if it does not (e.g. `&quot;ricmoo.eth&quot;` could set this to `&quot;RicMoo.eth&quot;`)
- **email** - an e-mail address
- **keywords** - A list of comma-separated keywords, ordered by most significant first; clients that interpresent this field may choose a threshold beyond which to ignore
- **mail** - A physical mailing address
- **notice** - A notice regarding this name
- **location** - A generic location (e.g. `&quot;Toronto, Canada&quot;`)
- **phone** - A phone number as an E.164 string
- **url** - a website URL

### Service Keys

Service Keys must be made up of a *reverse dot notation* for
a namespace which the service owns, for example, DNS names
(e.g. `.com`, `.io`, etc) or ENS name (i.e. `.eth`). Service
Keys must contain at least one dot.

This allows new services to start using their own keys without
worrying about colliding with existing services and also means
new services do not need to update this document.

The following services are common, which is why recommendations are
provided here, but ideally a service would declare its own key.

- **com.github** - a GitHub username
- **com.peepeth** - a Peepeth username
- **com.linkedin** - a LinkedIn username
- **com.twitter** - a Twitter username
- **io.keybase** - a Keybase username
- **org.telegram** - a Telegram username

This technique also allows for a service owner to specify a hierarchy
for their keys, such as:

- **com.example.users**
- **com.example.groups**
- **com.example.groups.public**
- **com.example.groups.private**


### Legacy Keys

The following keys were specified in earlier versions of this EIP,
which is still in draft.

Their use is not likely very wide, but applications attempting
maximal compatibility may wish to query these keys as a fallback
if the above replacement keys fail.

- **vnd.github** - a GitHub username (renamed to `com.github`)
- **vnd.peepeth** - a peepeth username (renamced to `com.peepeth`)
- **vnd.twitter** - a twitter username (renamed to `com.twitter`)


## Rationale

### Application-specific vs general-purpose record types

Rather than define a large number of specific record types (each for generally human-readable
data) such as `url` and `email`, we follow an adapted model of DNS&apos;s `TXT` records, which allow
for a general keys and values, allowing future extension without adjusting the resolver, while
allowing applications to use custom keys for their own purposes.


## Backwards Compatibility
Not applicable.


## Security Considerations
None.


## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 17 May 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-634</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-634</guid>
      </item>
    
      <item>
        <title>Metropolis Difficulty Bomb Delay and Block Reward Reduction</title>
        <category>Standards Track/Core</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/649</comments>
        
        <description>## Simple Summary
The average block times are increasing due to the difficulty bomb (also known as the &quot;_ice age_&quot;) slowly accelerating. This EIP proposes to delay the difficulty bomb for approximately one and a half year and to reduce the block rewards with the Byzantium fork, the first part of the Metropolis fork.

## Abstract
Starting with `BYZANTIUM_FORK_BLKNUM` the client will calculate the difficulty based on a fake block number suggesting the client that the difficulty bomb is adjusting around 3 million blocks later than previously specified with the Homestead fork. Furthermore, block rewards will be adjusted to a base of 3 ETH, uncle and nephew rewards will be adjusted accordingly.

## Motivation
The Casper development and switch to proof-of-stake is delayed, the Ethash proof-of-work should be feasible for miners and allow sealing new blocks every 15 seconds on average for another one and a half years. With the delay of the ice age, there is a desire to not suddenly also increase miner rewards. The difficulty bomb has been known about for a long time and now it&apos;s going to stop from happening. In order to maintain stability of the system, a block reward reduction that offsets the ice age delay would leave the system in the same general state as before. Reducing the reward also decreases the likelihood of a miner driven chain split as Ethereum approaches proof-of-stake.

## Specification
#### Relax Difficulty with Fake Block Number
For the purposes of `calc_difficulty`, simply replace the use of `block.number`, as used in the exponential ice age component, with the formula:

    fake_block_number = max(0, block.number - 3_000_000) if block.number &gt;= BYZANTIUM_FORK_BLKNUM else block.number

#### Adjust Block, Uncle, and Nephew rewards
To ensure a constant Ether issuance, adjust the block reward to `new_block_reward`, where

    new_block_reward = 3_000_000_000_000_000_000 if block.number &gt;= BYZANTIUM_FORK_BLKNUM else block.reward

(3E18 wei, or 3,000,000,000,000,000,000 wei, or 3 ETH).

Analogue, if an uncle is included in a block for `block.number &gt;= BYZANTIUM_FORK_BLKNUM` such that `block.number - uncle.number = k`, the uncle reward is

    new_uncle_reward = (8 - k) * new_block_reward / 8

This is the existing pre-Metropolis formula for uncle rewards, simply adjusted with `new_block_reward`.

The nephew reward for `block.number &gt;= BYZANTIUM_FORK_BLKNUM` is

    new_nephew_reward = new_block_reward / 32

This is the existing pre-Metropolis formula for nephew rewards, simply adjusted with `new_block_reward`.

## Rationale
This will delay the ice age by 42 million seconds (approximately 1.4 years), so the chain would be back at 30 second block times at the end of 2018. An alternate proposal was to add special rules to the difficulty calculation to effectively _pause_ the difficulty between different blocks. This would lead to similar results.

This was previously discussed at All Core Devs Meeting [#09](https://github.com/ethereum/pm/blob/master/AllCoreDevs-EL-Meetings/Meeting%209.md#metropolis-timing-and-roadmap-discussion), [#12](https://github.com/ethereum/pm/blob/master/AllCoreDevs-EL-Meetings/Meeting%2012.md#5-metropolis-update), [#13](https://github.com/ethereum/pm/blob/master/AllCoreDevs-EL-Meetings/Meeting%2013.md#3-eip-186-reduce-eth-issuance-before-proof-of-stake-hudson), and [#14](https://github.com/ethereum/pm/blob/master/AllCoreDevs-EL-Meetings/Meeting%2014.md#1-eip-186-reduce-eth-issuance-before-proof-of-stake-core-devs). Consensus on the specification was achieved in All Core Devs Meeting [#19](https://github.com/ethereum/pm/blob/master/AllCoreDevs-EL-Meetings/Meeting%2019.md) and specification drafted in EIP issue [#649](https://github.com/ethereum/EIPs/issues/649). It was decided to replace EIP [#186](https://github.com/ethereum/EIPs/issues/186) and include the block reward reduction along with the difficulty bomb delay in All Core Devs Meeting [#20](https://github.com/ethereum/pm/blob/master/AllCoreDevs-EL-Meetings/Meeting%2020.md) and [#21](https://github.com/ethereum/pm/blob/master/AllCoreDevs-EL-Meetings/Meeting%2021.md); accepted in [#22](https://github.com/ethereum/pm/blob/master/AllCoreDevs-EL-Meetings/Meeting%2022.md).

## Backwards Compatibility
This EIP is not forward compatible and introduces backwards incompatibilities in the difficulty calculation, as well as the block, uncle and nephew reward structure. Therefore, it should be included in a scheduled hardfork at a certain block number. It&apos;s suggested to include this EIP in the first of the two Metropolis hard-forks, the _Byzantium_ fork.

## Test Cases
Test cases exist in ethereum/tests [#269](https://github.com/ethereum/tests/pull/269).

## Implementation
The following clients implemented EIP-649:

- Geth [#15028](https://github.com/ethereum/go-ethereum/pull/15028)
- Parity [#5855](https://github.com/paritytech/parity/pull/5855)
- EthereumJ [#927](https://github.com/ethereum/ethereumj/pull/927)
- Cpp-Ethereum [#4050](https://github.com/ethereum/cpp-ethereum/issues/4050)
- PyEthereum [#383](https://github.com/ethereum/pyethereum/pull/383)

The Yellow Paper implements EIP-649 in [#333](https://github.com/ethereum/yellowpaper/pull/333).

Other notable implementations:

- Eth-Isabelle [#459](https://github.com/pirapira/eth-isabelle/issues/459)
- Py-EVM [#123](https://github.com/ethereum/py-evm/pull/123)

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 21 Jun 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-649</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-649</guid>
      </item>
    
      <item>
        <title>Embedding transaction status code in receipts</title>
        <category>Standards Track/Core</category>
        
        <description>## Abstract
This EIP replaces the intermediate state root field of the receipt with a status code indicating if the top-level call succeeded or failed.

## Motivation
With the introduction of the REVERT opcode in EIP140, it is no longer possible for users to assume that a transaction failed iff it consumed all gas. As a result, there is no clear mechanism for callers to determine whether a transaction succeeded and the state changes contained in it were applied.

Full nodes can provide RPCs to get a transaction return status and value by replaying the transaction, but fast nodes can only do this for nodes after their pivot point, and light nodes cannot do this at all, making a non-consensus solution impractical.

Instead, we propose to replace the intermediate state root, already obsoleted by EIP98, with the return status (1 for success, 0 for failure). This both allows callers to determine success status, and remedies the previous omission of return data from the receipt.

## Specification
For blocks where block.number &gt;= BYZANTIUM_FORK_BLKNUM, the intermediate state root is replaced by a status code, 0 indicating failure (due to any operation that can cause the transaction or top-level call to revert) and 1 indicating success.

## Rationale
This constitutes a minimal possible change that permits fetching the success/failure state of transactions, preserving existing capabilities with minimum disruption or additional work for Metropolis.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 30 Jun 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-658</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-658</guid>
      </item>
    
      <item>
        <title>SWAPN, DUPN and EXCHANGE instructions</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-663-unlimited-swap-and-dup-instructions/3346</comments>
        
        <description>## Abstract

Currently, `SWAP*` and `DUP*` instructions are limited to a stack depth of 16. Introduce three new instructions, `SWAPN`, `DUPN` and `EXCHANGE` which lift this limitation and allow accessing the stack at higher depths.

## Motivation

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 &quot;stack to memory elevation&quot; in a compiler. This can result in complex and inefficient code.

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.

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.

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.

Introducing `SWAPN`, `DUPN` and `EXCHANGE` will provide an option to compilers to simplify accessing deep stack items.

## Specification

We introduce three new instructions:

1. `DUPN` (`0xe6`)
2. `SWAPN` (`0xe7`)
3. `EXCHANGE` (`0xe8`)

If the code is legacy bytecode, any of these instructions result in an *exceptional halt*. (*Note: This means no change to behaviour.*)

If the code is valid EOF1, the following rules apply:

1. The instructions are followed by an 8-bit immediate value, which we call `imm`, and can have a value of 0 to 255.
   1. In the case of `DUPN` and `SWAPN`, we introduce the variable `n` which equals to `imm + 1`.
   2. In the case of `EXCHANGE`, we introduce the variable `n` which is equal to `(imm &gt;&gt; 4) + 1`, and the variable `m` which is equal to `(imm &amp; 0x0F) + 1` (i.e., the first and second nibbles of `imm`, converted to one-indexing).
2. Code validation is extended to check that no relative jump instruction (`RJUMP`/`RJUMPI`/`RJUMPV`) targets immediate values of `DUPN`, `SWAPN` or `EXCHANGE`.
3. The stack validation algorithm of [EIP-5450](/EIPs/EIPS/eip-5450) is extended:
   1. Before `DUPN` if the current stack height is less than `n`, code is invalid. After `DUPN`, the stack height is incremented.
   2. Before `SWAPN` if the current stack height is less than `n + 1`, code is invalid. After `SWAPN`, the stack height is unchanged.
   3. Before `EXCHANGE` if the current stack height is less than `n + m + 1`, code is invalid. After `EXCHANGE`, the stack height is unchanged.
4. Execution rules:
   1. `DUPN`: the `n`&apos;th stack item is duplicated at the top of the stack. (*Note: We use 1-based indexing here.*)
   2. `SWAPN`: the `n + 1`&apos;th stack item is swapped with the top of the stack.
   3. `EXCHANGE`: the `n + 1`&apos;th stack item is swapped with the `n + m + 1`&apos;th stack item.

The gas cost for all three instructions is set at 3.

## Rationale

### Use of an immediate argument

Allowing dynamic selection of the arguments to swap, dup, or exchange 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 argument that is not dynamic in nature. 

### EOF-only

Since this instruction depends on an immediate argument encoding, it can only be enabled within EOF. In legacy bytecode that encoding could contradict jumpdest-analysis.

### Size of immediate argument

For `DUPN` and `SWAPN` a 16-bit size was considered to accommodate the full stack space of 1024 items, however:

1. that would require an additional restriction/check (`n &lt; 1024`)
2. the 256 depth is a large improvement over the current 16 and the overhead of an extra byte would make it less useful

Similarly for `EXCHANGE`, the proposed scheme allows addressing of 32 items.

### Gas cost

The gas cost for these operations is the same as for existing `DUP*` and `SWAP*` instructions, because they are just implemented as pointer swaps.

### `EXCHANGE` vs `SWAPN`

As mentioned before, `EXCHANGE` 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, `SWAP2 SWAP3 SWAP2`. 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.

## Backwards Compatibility

This has no effect on backwards compatibility because the opcodes were not previously allocated and the feature is only enabled in EOF.

## Test Cases

Given `stack[]` is a 0-based data structure, and `n`, `m` and `imm` are defined as according to the spec:

- `DUPN imm` to fail validation if `stack_height &lt; n`.
- `SWAPN imm` to fail validation if `stack_height &lt; n + 1`.
- `EXCHANGE imm` to fail validation if `stack_height &lt; n + m + 1`.
- `DUPN imm` to increment maximum stack height of a function. Validation fails if maximum stack height exceeds limit of 1023.
- `DUPN imm`, `SWAPN imm`, and `EXCHANGE imm` to fail at run-time if gas available is less than 3.
- `DUPN imm` should duplicate the `stack[n - 1]` item and push it to the stack
- `SWAPN imm` should swap `stack[n]` with `stack[stack.top()]`
- `EXCHANGE imm` should swap `stack[n]` with `stack[n + m]`.

## Security Considerations

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.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 03 Jul 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-663</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-663</guid>
      </item>
    
      <item>
        <title>Add precompiled contract for Ed25519 signature verification</title>
        <category>Standards Track/Core</category>
        
        <description>## Simple Summary

Support performant and cheap verification of Ed25519 cryptographic signatures in smart contracts in general by adding a precompiled contract for Ed25519 signature verification to the EVM.

## Abstract

Verification of Ed25519 cryptographic signatures is obviously possible in EVM bytecode. However, the gas cost will be very high, and computationally expensive, as such tight, wide word operations intensive code as required for Ed25519 is not a good fit for the EVM bytecode model.

The addition of a native compiled function, in a precompiled contract, to the EVM solves both cost and performance problems.

## Motivation

Ed25519 and Ed448 (that is, EdDSA using Curve25519 or Curve448) are IETF recommendations ([RFC7748](https://tools.ietf.org/html/rfc7748)) with some attractive properties:

* Ed25519 is intended to operate at around the 128-bit security level and Ed448 at around the 224-bit security level
* EdDSA uses small public keys (32 or 57 octets) and signatures (64 or 114 octets) for Ed25519 and Ed448, respectively
* Ed25519/Ed448 are designed so that fast, constant-time (timing attack resistant) and generally side-channel resistant  implementations are easier to produce

Despite being around only for some years, post-Snowden, these curves [have gained wide use](https://ianix.com/pub/ed25519-deployment.html) quickly in various protocols and systems:

* TLS / ECDH(E) (session keys)
* TLS / x.509 (client and server certificates)
* DNSSEC (zone signing)
* OpenSSH (user keys)
* GNUPG/OpenPGP (user keys)
* OpenBSD Signify (software signing)

One motivation for Ed25519 signature verification in smart contracts is to **associate** existing off-chain systems, records or accounts that use Ed25519 (like above) with blockchain addresses or **delegate** by allowing to sign data with Ed25519 (only), and then submit this Ed25519-signed data anonymously (via any Eth sender address) to the blockchain, having the contract check the Ed25519 signature of the transaction.

Another motivation is the processing of external, Ed25519 proof-of-stake based blockchains within Ethereum smart contracts.

When a transactions contains data that comes with an Ed25519 signature, that proves that the sender of the Ethereum transaction was also in control of the private key (and the data), and this allows the contract to establish an association between the blockchain and the external system or account, and the external system establish the reverse relation.

For example, a contract might check a Ed25519 signed piece of data submitted to the Ethereum transaction like the current block number. That proves to the contract, that the sender is in possession of both the Ethereum private key and the Ed25519 private key, and hence the contract will accept an association between both. This again can be the root anchor for various powerful applications, as now a potentially crypto holding key owner has proven to be in control of some external off-chain system or account, like e.g. a DNS server, a DNS domain, a cluster node and so on.

## Specification

If `block.number &gt;= CONSTANTINOPLE_FORK_BLKNUM`, add a precompiled contract for Ed25519 signature verification (`ED25519VFY`).

The proposal adds a new precompiled function `ED25519VFY` with the following input and output.

`ED25519VFY` takes as **input 128 octets**:

1. **message**: the 32-octet message that was signed
2. **public key**: the 32-octet Ed25519 public key of the signer
3. **signature**: the 64-octet Ed25519 signature

`ED25519VFY` returns as **output 4 octets**:

* `0x00000000` if signature is valid
* any non-zero value indicates a signature verification failure

### Address

The address of `ED25519VFY` is **`0x9`.**

### Gas costs

Gas cost for `ED25519VFY` is **2000**.

## Rationale

The proposed `ED25519VFY` function takes the signer public key as a call parameter, as with Ed25519, I don&apos;t believe it is possible to derive the signers public key from the signature and message alone.

The proposed `ED25519VFY` function uses a zero return value to indicate success, since this allows for different errors to be distinguished by return value, as all non-zero return values signal a verification failure.

`ECRECOVER` has a gas cost of 3000. Since Ed25519 is computationally cheaper, the gas price should be less.

## Backwards Compatibility

As the proposed precompiled contract is deployed at a reserved (&lt;255) and previously unused address, an implementation of the proposal should not introduce any backward compatibility issues.

## Test Cases

Test vectors for Ed25519 can be found in this IETF ID https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-6.

More test vectors can be found in the regression tests of NaCl (see references).

## Implementation

### libsodium

libsodium is a mature, high-quality C implementation of Ed25519, with bindings for many languages.

Further, libsodium is (to my knowledge, and as of today 2018/04) the only Ed25519 implementation that has gone through a [Security Assessment](https://www.privateinternetaccess.com/blog/2017/08/libsodium-v1-0-12-and-v1-0-13-security-assessment/).

To minimize consensus failure risks, the proposal recommends to use libsodium for adding the precompile in all Ethereum client implementations.

&gt; Note: as an alternative to libsodium, I looked into HACL, an implementation of Ed25519 in F* (a ML dialect) that can be transpiled to C, and that was formally verified for functional correctness and memory safety of the resulting C code. However, this is new and compared to libsodium which is a &quot;know thing&quot; seems risky nevertheless.

### libsodium bindings

Here is an overview of the language bindings to libsodium for four Ethereum clients this proposal recommends:


| Client       | Language | libsodium binding  |
---------------|----------|--------------------|
| Geth         | Go       | use cgo with C [libsodium](https://github.com/jedisct1/libsodium)|
| Parity       | Rust     | [sodiumoxide](https://github.com/dnaq/sodiumoxide)|
| PyEthereum   | Python   | [PyNaCl](https://github.com/pyca/pynacl)|
| cpp-ethereum | C++      | [libsodium](https://github.com/jedisct1/libsodium)|
----------------------------------------------------------------------------

### PRs

Implementations of this proposal are here:

1. [go-ethereum PR #16453](https://github.com/ethereum/go-ethereum/pull/16453)
2. [pyethereum PR #862](https://github.com/ethereum/pyethereum/pull/862)
3. [parity PR #8330](https://github.com/paritytech/parity/pull/8330)
4. [cpp-ethereum PR #4945](https://github.com/ethereum/cpp-ethereum/pull/4945)

## References

* RFC7748 - Elliptic Curves for Security https://tools.ietf.org/html/rfc7748
* Definition of Ed25519: https://ed25519.cr.yp.to/ed25519-20110926.pdf
* Ed25519 - high-speed high-security signatures: https://ed25519.cr.yp.to/
* NaCl - Networking and Cryptography library: https://nacl.cr.yp.to/sign.html
* NaCl Crypto Libraries (which contains Ed25519): https://ianix.com/pub/ed25519-deployment.html
* Test vectors for Ed25519: https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-03#section-6
* NaCl regression tests: https://ed25519.cr.yp.to/python/sign.py and https://ed25519.cr.yp.to/python/sign.input
* On the recoverability of public keys from signature+message (alone): https://crypto.stackexchange.com/questions/9936/what-signature-schemes-allow-recovering-the-public-key-from-a-signature
* Bernstein, D., &quot;Curve25519: new Diffie-Hellman speed records&quot;, DOI 10.1007/11745853_14, February 2006, https://cr.yp.to/ecdh.html
* Hamburg, M., &quot;Ed448-Goldilocks, a new elliptic curve&quot;, June 2015, https://eprint.iacr.org/2015/625&gt;
* RFC8080: Edwards-Curve Digital Security Algorithm (EdDSA) for DNSSEC (https://datatracker.ietf.org/doc/html/rfc8080)

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 25 Mar 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-665</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-665</guid>
      </item>
    
      <item>
        <title>URL Format for Transaction Requests</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-681-representing-various-transactions-as-urls</comments>
        
        <description>## Simple Summary
A standard way of representing various transactions, especially payment requests in ether and [ERC-20](/EIPs/EIPS/eip-20) tokens as URLs.

## Abstract
URLs embedded in QR-codes, hyperlinks in web-pages, emails or chat messages provide for robust cross-application signaling between very loosely coupled applications. A standardized URL format for payment requests allows for instant invocation of the user&apos;s preferred wallet application (even if it is a webapp or a swarm đapp), with the correct parameterization of the payment transaction only to be confirmed by the (authenticated) user.

## Motivation
The convenience of representing payment requests by standard URLs has been a major factor in the wide adoption of Bitcoin. Bringing a similarly convenient mechanism to Ethereum would speed up its acceptance as a payment platform among end-users. In particular, URLs embedded in broadcast Intents are the preferred way of launching applications on the Android operating system and work across practically all applications. Desktop web browsers have a standardized way of defining protocol handlers for URLs with specific protocol specifications. Other desktop applications typically launch the web browser upon encountering a URL. Thus, payment request URLs could be delivered through a very broad, ever growing selection of channels.

This specification supersedes the defunct ERC-67, which is a URL format for representing arbitrary transactions in a low-level fashion. This ERC focuses specifically on the important special case of payment requests, while allowing for other, ABI-specified transactions.

## Specification

### Syntax
Payment request URLs contain &quot;ethereum&quot; in their schema (protocol) part and are constructed as follows:

    request                 = schema_prefix target_address [ &quot;@&quot; chain_id ] [ &quot;/&quot; function_name ] [ &quot;?&quot; parameters ]
    schema_prefix           = &quot;ethereum&quot; &quot;:&quot; [ &quot;pay-&quot; ]
    target_address          = ethereum_address
    chain_id                = 1*DIGIT
    function_name           = STRING
    ethereum_address        = ( &quot;0x&quot; 40*HEXDIG ) / ENS_NAME
    parameters              = parameter *( &quot;&amp;&quot; parameter )
    parameter               = key &quot;=&quot; value
    key                     = &quot;value&quot; / &quot;gas&quot; / &quot;gasLimit&quot; / &quot;gasPrice&quot; / TYPE
    value                   = number / ethereum_address / STRING
    number                  = [ &quot;-&quot; / &quot;+&quot; ] *DIGIT [ &quot;.&quot; 1*DIGIT ] [ ( &quot;e&quot; / &quot;E&quot; ) [ 1*DIGIT ] ]


Where `TYPE` is a standard ABI type name, as defined in [Ethereum Contract ABI specification](https://solidity.readthedocs.io/en/develop/abi-spec.html). `STRING` is a URL-encoded unicode string of arbitrary length, where delimiters and the
percentage symbol (`%`) are mandatorily hex-encoded with a `%` prefix.

Note that a `number` can be expressed in *scientific notation*, with a multiplier of a power of 10. Only integer numbers are allowed, so the exponent MUST be greater or equal to the number of decimals after the point.

If *key* in the parameter list is `value`, `gasLimit`, `gasPrice` or `gas` then *value* MUST be a `number`. Otherwise, it must correspond to the `TYPE` string used as *key*.

For the syntax of ENS_NAME, please consult [ERC-137](/EIPs/EIPS/eip-137) defining Ethereum Name Service.

### Semantics

`target_address` is mandatory and denotes either the beneficiary of native token payment (see below) or the contract address with which the user is asked to interact.

`chain_id` is optional and contains the decimal chain ID, such that transactions on various test- and private networks can be requested. If no `chain_id` is present, the client&apos;s current network setting remains effective.

If `function_name` is missing, then the URL is requesting payment in the native token of the blockchain, which is ether in our case. The amount is specified in `value` parameter, in the atomic unit (i.e. wei). The use of scientific notation is strongly encouraged. For example, requesting 2.014 ETH to address `0xfb6916095ca1df60bb79Ce92ce3ea74c37c5d359` would look as follows:
[ethereum:0xfb6916095ca1df60bb79Ce92ce3ea74c37c5d359?value=2.014e18](ethereum:0xfb6916095ca1df60bb79Ce92ce3ea74c37c5d359?value=2.014e18)

Requesting payments in [ERC-20](/EIPs/EIPS/eip-20) tokens involves a request to call the `transfer` function of the token contract with an `address` and a `uint256` typed parameter, containing the *beneficiary address* and the *amount in atomic units*, respectively. For example,
requesting a Unicorn to address `0x8e23ee67d1332ad560396262c48ffbb01f93d052` looks as follows:
[ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7/transfer?address=0x8e23ee67d1332ad560396262c48ffbb01f93d052&amp;uint256=1](ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7/transfer?address=0x8e23ee67d1332ad560396262c48ffbb01f93d052&amp;uint256=1)

If using ENS names instead of hexadecimal addresses, the resolution is up to the payer, at any time between receiving the URL and sending the transaction. Hexadecimal addresses always take precedence over ENS names, i. e. even if there exists a matching ENS name consisting of `0x` followed by 40 hexadecimal digits, it should never be resolved. Instead, the hexadecimal address should be used directly.

Note that the indicated amount is only a suggestion (as are all the supplied arguments) which the user is free to change. With no indicated amount, the user should be prompted to enter the amount to be paid.

Similarly `gasLimit` and `gasPrice` are suggested user-editable values for *gas limit* and *gas price*, respectively, for the requested transaction. It is acceptable to abbreviate `gasLimit` as `gas`, the two are treated synonymously.

## Rationale
The proposed format is chosen to resemble `bitcoin:` URLs as closely as possible, as both users and application programmers are already familiar with that format. In particular, this motivated the omission of the unit, which is often used in Ethereum ecosystem. Handling different orders of magnitude is facilitated by the exponent so that amount values can be expressed in their nominal units, just like in the case of `bitcoin:`. The use of scientific notation is strongly encouraged when expressing monetary value in ether or [ERC-20](/EIPs/EIPS/eip-20) tokens. For better human readability, the exponent should be the decimal value of the nominal unit: 18 for ether or the value returned by `decimals()` of the token contract for [ERC-20](/EIPs/EIPS/eip-20) tokens. Additional parameters may be added, if popular use cases requiring them emerge in practice.

The `0x` prefix before ethereum addresses specified as hexadecimal numbers is following established practice and also unambiguously distinguishes hexadecimal addresses from ENS names consisting of 40 alphanumeric characters.

Future upgrades that are partially or fully incompatible with this proposal must use a prefix other than `pay-` that is separated by a dash (`-`) character from whatever follows it.

## Backwards Compatibility

In the fairly common case of only indicating the recipient address in a request for payment in ether, this specification is compatible with the superseded ERC-67.

## Security Considerations

Since irreversible transactions can be initiated with parameters from such URLs, the integrity and authenticity of these URLs are of great importance.
In particular, changing either the recipient address or the amount transferred can be a profitable attack. Users should only use URLs received from authenticated sources with adequate integrity protection.

To prevent malicious redirection of payments using ENS, hexadecimal interpretation of Ethereum addresses must have precedence over ENS lookups. Client software may alert the user if an ENS address is visually similar to a hexadecimal address or even outright reject such addresses as likely phishing attacks.

In order to make sure that the amount transacted is the same as the amount intended, the amount communicated to the human user should be easily verifiable by inspection, including the order of magnitude. In case of [ERC-20](/EIPs/EIPS/eip-20) token payments, if the payer client has access to the blockchain or some other trusted source of information about the token contract, the interface should display the amount in the units specified in the token contract. Otherwise, it should be displayed as expressed in the URL, possibly alerting the user to the uncertainty of the nominal unit. To facilitate human inspection of the amount, the use of scientific notation with an exponent corresponding to the nominal unit of the transacted token (e.g. 18 in case of ether) is advisable.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 01 Aug 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-681</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-681</guid>
      </item>
    
      <item>
        <title>Revert creation in case of collision</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-revert-on-address-collision/13442</comments>
        
        <description>## Abstract

This EIP causes contract creation to throw an error when attempted at an address with pre-existing code. This prevents an attack consisting of deploying contract code and later changing the code arbitrarily by &quot;creating&quot; an account at that existing address.

## Specification

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

If a contract creation is attempted due to a creation transaction, the `CREATE` opcode, the `CREATE2` opcode, or any other reason, and the destination address already has either a nonzero nonce, or a nonzero code length, 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.

## Rationale

One of the core tenets of smart contracts is that their code will not change. However with sufficient computing power an attacker can change the code stored in an address to any other code, steal funds or execute other malicious activity.

## Backwards Compatibility

This is an execution layer upgrade, and so it requires a hard fork.

## Test Cases

Given a genesis allocation of

```
Address : 0xd0bBEc6D2c628b7e2E6D5556daA14a5181b604C5,
Balance : 1000000000000000000, // 1 ether
Nonce   : 0,
code    : &quot;&quot;,

Address : 0x7658771dc6Af74a3d2F8499D349FF9c1a0DF8826,
Balance : 0,
Nonce   : 1,
Code    : &quot;0xB0B0FACE&quot;,
```

A contract created in the first transaction from EOA `0xd0bBEc6...` (`227bcc6959669226360814723ed739f1214201584b6a27409dfb8228b8be5f59`), with no salt, should revert.

## Security Considerations

This EIP is a security upgrade: it enforces the immutability of deployed code.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 20 Mar 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-684</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-684</guid>
      </item>
    
      <item>
        <title>Address Collision of Contract Address Causes Exceptional Halt</title>
        <category>Standards Track/Core</category>
        
        <description>## Simple Summary

This EIP proposes to make contract creation fail on an account with nonempty code or non-zero nonce.

## Abstract

Some test cases in the consensus test suite try to deploy a contract at an address already with nonempty code. Although such cases can virtually never happen on the main network before the Constantinople fork block, the test cases detected discrepancies in clients&apos; behavior.  Currently, the Yellow Paper says that the contract creation starts with the empty code and the initial nonce even in the case of address collisions. To simplify the semantics, this EIP proposes that address collisions cause failures of contract creation.

## Motivation

This EIP has no practical relevance to the main net history, but simplifies testing and reasoning.

This EIP has no effects after Constantinople fork because [EIP-86](/EIPs/EIPS/eip-86) contains the changes proposed in this EIP. Even before the Constantinople fork, this EIP has no practical relevance because the change is visible only in case of a hash collision of keccak256.

Regarding testing, this EIP relieves clients from supporting reversion of code overwriting.

Regarding reasoning, this EIP establishes an invariant that non-empty code is never modified.

## Specification

If `block.number &gt;= 0`, when a contract creation is on an account with non-zero nonce or non-empty code, the creation fails as if init code execution resulted in an exceptional halt.  This applies to contract creation triggered by a contract creation transaction and by CREATE instruction.

## Rationale

It seems impractical to implement never-used features just for passing tests.  Client implementations will be simpler with this EIP.

## Backwards Compatibility

This EIP is backwards compatible on the main network.

## Test Cases

At least the BlockchainTest called `createJS\_ExampleContract\_d0g0v0\_EIP158` will distinguish clients that implement this EIP.

## Implementation

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 15 Aug 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-689</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-689</guid>
      </item>
    
      <item>
        <title>Create `eth_chainId` method for JSON-RPC</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-695-create-eth-chainid-method-for-json-rpc/1845</comments>
        
        <description>## Simple Summary

Include `eth_chainId` method in `eth_`-namespaced JSON-RPC methods.

## Abstract

The `eth_chainId` method should return a single STRING result
for an integer value in hexadecimal format, describing the
currently configured `CHAIN_ID` value used for signing replay-protected transactions,
introduced by [EIP-155](/EIPs/EIPS/eip-155).

## Motivation

Currently although we can use `net_version` RPC call to get the
current network ID, there&apos;s no RPC for querying the chain ID. This
makes it impossible to determine the current actual blockchain using
the RPC.

## Specification

### `eth_chainId`

Returns the currently configured chain ID, a value used in replay-protected transaction
signing as introduced by [EIP-155](/EIPs/EIPS/eip-155).

The chain ID returned should always correspond to the information in the current known
head block. This ensures that caller of this RPC method can always use the retrieved
information to sign transactions built on top of the head.

If the current known head block does not specify a chain ID, the client should treat any
calls to `eth_chainId` as though the method were not supported, and return a suitable
error.

#### Parameters

None.

#### Returns

`QUANTITY` - integer of the current chain ID.

#### Example

```js
curl -X POST --data &apos;{&quot;jsonrpc&quot;:&quot;2.0&quot;,&quot;method&quot;:&quot;eth_chainId&quot;,&quot;params&quot;:[],&quot;id&quot;:83}&apos;

// Result
{
  &quot;id&quot;: 83,
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;result&quot;: &quot;0x3d&quot; // 61
}
```

## Rationale

An ETH/ETC client can accidentally connect to an ETC/ETH RPC
endpoint without knowing it unless it tries to sign a transaction or
it fetches a transaction that is known to have signed with a chain
ID. This has since caused trouble for application developers, such as
MetaMask, to add multi-chain support.

## Backwards Compatibility

Not relevant.

## Security Considerations

Consumers should prefer `eth_chainId` over `net_version`, so that they can reliably identify chain they are communicating with.

Implementers should take care to implement `eth_chainId` correctly and promote its use, since the chain ID is critical in replay attack prevention as described in [EIP-155](/EIPs/EIPS/eip-155), and consumers will rely on it to identify the chain they are communicating with.

## Implementation

- [Parity PR](https://github.com/paritytech/parity/pull/6329)
- [Geth PR](https://github.com/ethereum/go-ethereum/pull/17617)
- [Geth Classic PR](https://github.com/ethereumproject/go-ethereum/pull/336)

## Reference

Return value `QUANTITY` adheres to standard JSON RPC hex value encoding, as documented in the [Ethereum.org documentation](https://ethereum.org/en/developers/docs/apis/json-rpc/#hex-encoding).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 21 Aug 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-695</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-695</guid>
      </item>
    
      <item>
        <title>OPCODE 0x46 BLOCKREWARD</title>
        <category>Standards Track/Core</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/698</comments>
        
        <description>## Simple Summary

This EIP adds an additional opcode to the EVM which will return a finalized blocks reward value. 

## Abstract

In the EVM, the 0x40 opcodes are reserved for `Block Information`. Currently reserved opcodes are:
* `0X40 BLOCKHASH`
* `0X41 COINBASE`
* `0X42 TIMESTAMP`
* `0X43 NUMBER`
* `0X44 DIFFICULTY`
* `0X45 GASLIMIT`

This EIP would add an additional opcode, `0x46 BLOCKREWARD`, which would return the block reward for any finalized block. The finalized block reward would include the base reward, uncle payments, and gas.   

## Motivation


Per EIP-649 ( #669 ) periodic block reward reductions/variance are now planned in the roadmap, however, this EIP is consensus system agnostic and is most useful in decentralized pool operations and for any contract that benefits from knowing a block reward payout(i.e. Merge mined tokens) 

## Specification

After block `n` all clients should process opcode `0x46` as follows:  

* Value: `0x46`
* Mnemonic: `BLOCKREWARD`
* δ:` 0` nothing removed from stack
* α:`1` block reward added to stack
* Description: `Get the block&apos;s reward emission` 
* GasCost: `G&lt;sub&gt;base&lt;/sub&gt;`

Where:`µ&apos;&lt;sub&gt;s&lt;/sub&gt;[0] ≡ I&lt;sub&gt;HR&lt;/sub&gt;`


## Rationale

### Contract Mining Pools

For distributed consensus systems(staking pools and mining pools) ad hoc groups combine resources in order to reduce variance in payouts. Broadly, pool operations function by allowing a collective of  miners / stakers  to verify their contribution to solving PoW or staking share by periodically submitting solutions which are representative of the miners probability of finding a true block. 

In all these schemes `B` stands for a block reward minus pool fee and `p` is a probability of finding a block in a share attempt ( `p=1/D`, where `D` is current block difficulty).

Some common methods of mining pool payout are pay-per-share, `R = B * p`, proportional [`R = B * (n/N)` where `n` is amount of a miners shares, and `N` is amount of all shares in this round.], and pay-per-last-N-shares [`R = B * (n/N)` where miner&apos;s reward is calculated on a basis of `N` last shares, instead of all shares for the last round]. All of these methods are predicated on knowing the block reward paid for a given block. In order to provide a trust minimized solution, `0x46` can be used to call a blocks reward for computing payouts.     

### Merge mined tokens

Contracts could create tokens which could be variably ‘minted’ as a function of block reward by calling `0x46`  

## Backwards Compatibility


### Currently deployed contracts

No impact

### Current clients

This EIP would be incompatible with currently deployed clients that are not able to handle `0x46` and would process all transactions and block containing the opcode as invalid. 

Implementation should occur as part of a coordinated hardfork.

## Implementation


## Further reading

[Mining Pools](https://en.wikipedia.org/wiki/Mining_pool)

The Yellow Paper Appendix H. Virtual Machine Specification section H.2

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 28 Aug 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-698</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-698</guid>
      </item>
    
      <item>
        <title>DEVp2p snappy compression</title>
        <category>Standards Track/Networking</category>
        
        <description>## Abstract
The base networking protocol (DEVp2p) used by Ethereum currently does not employ any form of compression. This results in a massive amount of bandwidth wasted in the entire network, making both initial sync as well as normal operation slower and laggier.

This EIP proposes a tiny extension to the DEVp2p protocol to enable [Snappy compression](https://en.wikipedia.org/wiki/Snappy_(compression)) on all message payloads after the initial handshake. After extensive benchmarks, results show that data traffic is decreased by 60-80% for initial sync. You can find exact numbers below.

## Motivation
Synchronizing the Ethereum main network (block 4,248,000) in Geth using fast sync currently consumes 1.01GB upload and 33.59GB download bandwidth. On the Rinkeby test network (block 852,000) it&apos;s 55.89MB upload and 2.51GB download.

However, most of this data (blocks, transactions) are heavily compressible. By enabling compression at the message payload level, we can reduce the previous numbers to 1.01GB upload / 13.46GB download on the main network, and 46.21MB upload / 463.65MB download on the test network.

The motivation behind doing this at the DEVp2p level (opposed to eth for example) is that it would enable compression for all sub-protocols (eth, les, bzz) seamlessly, reducing any complexity those protocols might incur in trying to individually optimize for data traffic.

## Specification
Bump the advertised DEVp2p version number from `4` to `5`. If during handshake, the remote side advertises support only for version `4`, run the exact same protocol as until now.

If the remote side advertises a DEVp2p version `&gt;= 5`, inject a Snappy compression step right before encrypting the DEVp2p message during sending:

 * A message consists of `{Code, Size, Payload}`
  * Compress the original payload with Snappy and store it in the same field.
  * Update the message size to the length of the compressed payload.
  * Encrypt and send the message as before, oblivious to compression.

Similarly to message sending, when receiving a DEVp2p v5 message from a remote node, insert a Snappy decompression step right after decrypting the DEVp2p message:

* A message consists of `{Code, Size, Payload}`
 * Decrypt the message payload as before, oblivious to compression.
 * Decompress the payload with Snappy and store it in the same field.
 * Update the message size to the length of the decompressed payload.

Important caveats:

 * The handshake message is **never** compressed, since it is needed to negotiate the common version.
 * Snappy framing is **not** used, since the DEVp2p protocol already message oriented.

*Note: Snappy supports uncompressed binary literals (up to 4GB) too, leaving room for fine-tuned future optimisations for already compressed or encrypted data that would have no gain of compression (Snappy usually detects this case automatically).*

### Avoiding DOS attacks

Currently a DEVp2p message length is limited to 24 bits, amounting to a maximum size of 16MB. With the introduction of Snappy compression, care must be taken not to blindly decompress messages, since they may get significantly larger than 16MB.

However, Snappy is capable of calculating the decompressed size of an input message without inflating it in memory (*[the stream starts with the uncompressed length up to a maximum of `2^32 - 1` stored as a little-endian varint](https://github.com/google/snappy/blob/master/format_description.txt#L20)*). This can be used to discard any messages which decompress above some threshold. **The proposal is to use the same limit (16MB) as the threshold for decompressed messages.** This retains the same guarantees that the current DEVp2p protocol does, so there won&apos;t be surprises in application level protocols.

## Alternatives (discarded)

**Alternative solutions to data compression that have been brought up and discarded are:**

Extend protocol `xyz` to support compressed messages versus doing it at DEVp2p level:

 * **Pro**: Can be better optimized when to compress and when not to.
 * **Con**: Mixes in transport layer encoding into application layer logic.
 * **Con**: Makes the individual message specs more convoluted with compression details.
 * **Con**: Requires cross client coordination on every single protocol, making the effort much harder and repeated (eth, les, shh, bzz).

Introduce seamless variations of protocol such as `xyz` expanded with `xyz-compressed`:

 * **Pro**: Can be done (hacked in) without cross client coordination.
 * **Con**: Litters the network with client specific protocol announces.
 * **Con**: Needs to be specced in an EIP for cross interoperability anyway.

**Other ideas that have been discussed and discarded:**

Don&apos;t explicitly limit the decompressed message size, only the compressed one:

 * **Pro**: Allows larger messages to traverse through DEVp2p.
 * **Con**: Upper layer protocols need to check and discard large messages.
 * **Con**: Needs lazy decompression to allow size limitations without DOS.

## Backwards Compatibility
This proposal is fully backward compatible. Clients upgrading to the proposed DEVp2p protocol version `5` should still support skipping the compression step for connections that only advertise version `4` of the DEVp2p protocol.

## Implementation
You can find a reference implementation of this EIP in https://github.com/ethereum/go-ethereum/pull/15106.

## Test vectors

There is more than one valid encoding of any given input, and there is more than one good internal compression algorithm within Snappy when trading off throughput for output size. As such, different implementations might produce slight variations in the compressed form, but all should be cross compatible between each other.

As an example, take hex encoded RLP of block #272621 from the Rinkeby test network: [block.rlp (~3MB)](https://gist.githubusercontent.com/karalabe/72a1a6c4c1dbe6d4996879e415697f06/raw/195bf0c0050ee9805fcd5db4b5b650c58879a55f/block.rlp).

 * Encoding the raw RLP via [Go&apos;s Snappy library](https://github.com/golang/snappy) yields: [block.go.snappy (~70KB)](https://gist.githubusercontent.com/karalabe/72a1a6c4c1dbe6d4996879e415697f06/raw/195bf0c0050ee9805fcd5db4b5b650c58879a55f/block.go.snappy).
 * Encoding the raw RLP via [Python&apos;s Snappy library](https://github.com/andrix/python-snappy) yields: [block.py.snappy (~70KB)](https://gist.githubusercontent.com/karalabe/72a1a6c4c1dbe6d4996879e415697f06/raw/195bf0c0050ee9805fcd5db4b5b650c58879a55f/block.py.snappy).

You can verify that an encoded binary can be decoded into the proper plaintext using the following snippets:

### Go

```sh
$ go get https://github.com/golang/snappy
```

```go
package main

import (
	&quot;bytes&quot;
	&quot;encoding/hex&quot;
	&quot;fmt&quot;
	&quot;io/ioutil&quot;
	&quot;log&quot;
	&quot;os&quot;

	&quot;github.com/golang/snappy&quot;
)

func main() {
	// Read and decode the decompressed file
	plainhex, err := ioutil.ReadFile(os.Args[1])
	if err != nil {
		log.Fatalf(&quot;Failed to read decompressed file %s: %v&quot;, os.Args[1], err)
	}
	plain, err := hex.DecodeString(string(plainhex))
	if err != nil {
		log.Fatalf(&quot;Failed to decode decompressed file: %v&quot;, err)
	}
	// Read and decode the compressed file
	comphex, err := ioutil.ReadFile(os.Args[2])
	if err != nil {
		log.Fatalf(&quot;Failed to read compressed file %s: %v&quot;, os.Args[2], err)
	}
	comp, err := hex.DecodeString(string(comphex))
	if err != nil {
		log.Fatalf(&quot;Failed to decode compressed file: %v&quot;, err)
	}
	// Make sure they match
	decomp, err := snappy.Decode(nil, comp)
	if err != nil {
		log.Fatalf(&quot;Failed to decompress compressed file: %v&quot;, err)
	}
	if !bytes.Equal(plain, decomp) {
		fmt.Println(&quot;Booo, decompressed file does not match provided plain text!&quot;)
		return
	}
	fmt.Println(&quot;Yay, decompressed data matched provided plain text!&quot;)
}
```

```sh
$ go run main.go block.rlp block.go.snappy
Yay, decompressed data matched provided plain text!

$ go run main.go block.rlp block.py.snappy
Yay, decompressed data matched provided plain text!
```

### Python

```bash
$ pip install python-snappy
```

```py
import snappy
import sys

# Read and decode the decompressed file
with open(sys.argv[1], &apos;rb&apos;) as file:
    plainhex = file.read()

plain = plainhex.decode(&quot;hex&quot;)

# Read and decode the compressed file
with open(sys.argv[2], &apos;rb&apos;) as file:
    comphex = file.read()

comp = comphex.decode(&quot;hex&quot;)

# Make sure they match
decomp = snappy.uncompress(comp)
if plain != decomp:
    print &quot;Booo, decompressed file does not match provided plain text!&quot;
else:
    print &quot;Yay, decompressed data matched provided plain text!&quot;
```

```sh
$ python main.py block.rlp block.go.snappy
Yay, decompressed data matched provided plain text!

$ python main.py block.rlp block.py.snappy
Yay, decompressed data matched provided plain text!
```

## References

 * Snappy website: https://google.github.io/snappy/
 * Snappy specification: https://github.com/google/snappy/blob/master/format_description.txt

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 07 Sep 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-706</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-706</guid>
      </item>
    
      <item>
        <title>Typed structured data hashing and signing</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-712-eth-signtypeddata-as-a-standard-for-machine-verifiable-and-human-readable-typed-data-signing/397</comments>
        
        <description>## Abstract

This is a standard for hashing and signing of typed structured data as opposed to just bytestrings. It includes a

* theoretical framework for correctness of encoding functions,
* specification of structured data similar to and compatible with Solidity structs,
* safe hashing algorithm for instances of those structures,
* safe inclusion of those instances in the set of signable messages,
* an extensible mechanism for domain separation,
* new RPC call `eth_signTypedData`, and
* an optimized implementation of the hashing algorithm in EVM.

It does not include replay protection.

## Motivation

Signing data is a solved problem if all we care about are bytestrings. Unfortunately in the real world we care about complex meaningful messages. Hashing structured data is non-trivial and errors result in loss of the security properties of the system.

As such, the adage &quot;don&apos;t roll your own crypto&quot; applies. Instead, a peer-reviewed well-tested standard method needs to be used. This EIP aims to be that standard.

This EIP aims to improve the usability of off-chain message signing for use on-chain. We are seeing growing adoption of off-chain message signing as it saves gas and reduces the number of transactions on the blockchain. Currently signed messages are an opaque hex string displayed to the user with little context about the items that make up the message.

![eth_sign screenshot](/EIPs/assets/eip-712/eth_sign.png)

Here we outline a scheme to encode data along with its structure which allows it to be displayed to the user for verification when signing. Below is an example of what a user could be shown when signing a message according to the present proposal.

![eth_signTypedData screenshot](/EIPs/assets/eip-712/eth_signTypedData.png)

## Specification

The set of signable messages is extended from transactions and bytestrings `𝕋 ∪ 𝔹⁸ⁿ` to also include structured data `𝕊`. The new set of signable messages is thus `𝕋 ∪ 𝔹⁸ⁿ ∪ 𝕊`. They are encoded to bytestrings suitable for hashing and signing as follows:

* `encode(transaction : 𝕋) = RLP_encode(transaction)`
* `encode(message : 𝔹⁸ⁿ) = &quot;\x19Ethereum Signed Message:\n&quot; ‖ len(message) ‖ message` where `len(message)` is the _non-zero-padded_ ascii-decimal encoding of the number of bytes in `message`.
* `encode(domainSeparator : 𝔹²⁵⁶, message : 𝕊) = &quot;\x19\x01&quot; ‖ domainSeparator ‖ hashStruct(message)` where `domainSeparator` and `hashStruct(message)` are defined below.

This encoding is deterministic because the individual components are. The encoding is injective because the three cases always differ in first byte. (`RLP_encode(transaction)` does not start with `\x19`.)

The encoding is compliant with [ERC-191][ERC-191]. The &apos;version byte&apos; is fixed to `0x01`, the &apos;version specific data&apos; is the 32-byte domain separator `domainSeparator` and the &apos;data to sign&apos; is the 32-byte `hashStruct(message)`.

[ERC-191]: /EIPs/EIPS/eip-191

### Definition of typed structured data `𝕊`

To define the set of all structured data, we start with defining acceptable types. Like ABIv2 these are closely related to Solidity types. It is illustrative to adopt Solidity notation to explain the definitions. The standard is specific to the Ethereum Virtual Machine, but aims to be agnostic to higher level languages. Example:

```Solidity
struct Mail {
    address from;
    address to;
    string contents;
}
```

**Definition**: A _struct type_ has valid identifier as name and contains zero or more member variables. Member variables have a member type and a name.

**Definition**: A _member type_ can be either an atomic type, a dynamic type or a reference type.

**Definition**: The _atomic types_ are `bytes1` to `bytes32`, `uint8` to `uint256`, `int8` to `int256`, `bool` and `address`. These correspond to their definition in Solidity. Note that there are no aliases `uint` and `int`. Note that contract addresses are always plain `address`. Fixed point numbers are not supported by the standard. Future versions of this standard may add new atomic types.

**Definition**: The _dynamic types_ are `bytes` and `string`. These are like the atomic types for the purpose of type declaration, but their treatment in encoding is different.

**Definition**: The _reference types_ are arrays and structs. Arrays are either fixed size or dynamic and denoted by `Type[n]` or `Type[]` respectively. Structs are references to other structs by their name. The standard supports recursive struct types.

**Definition**: The set of structured typed data `𝕊` contains all the instances of all the struct types.

### Definition of `hashStruct`

The `hashStruct` function is defined as

* `hashStruct(s : 𝕊) = keccak256(typeHash ‖ encodeData(s))` where `typeHash = keccak256(encodeType(typeOf(s)))`

**Note**: The `typeHash` is a constant for a given struct type and does not need to be runtime computed.

### Definition of `encodeType`

The type of a struct is encoded as `name ‖ &quot;(&quot; ‖ member₁ ‖ &quot;,&quot; ‖ member₂ ‖ &quot;,&quot; ‖ … ‖ memberₙ &quot;)&quot;` where each member is written as `type ‖ &quot; &quot; ‖ name`. For example, the above `Mail` struct is encoded as `Mail(address from,address to,string contents)`.

If the struct type references other struct types (and these in turn reference even more struct types), then the set of referenced struct types is collected, sorted by name and appended to the encoding. An example encoding is `Transaction(Person from,Person to,Asset tx)Asset(address token,uint256 amount)Person(address wallet,string name)`.

### Definition of `encodeData`

The encoding of a struct instance is `enc(value₁) ‖ enc(value₂) ‖ … ‖ enc(valueₙ)`, i.e. the concatenation of the encoded member values in the order that they appear in the type. Each encoded member value is exactly 32-byte long.

The atomic values are encoded as follows: Boolean `false` and `true` are encoded as `uint256` values `0` and `1` respectively. Addresses are encoded as `uint160`. Integer values are sign-extended to 256-bit and encoded in big endian order. `bytes1` to `bytes31` are arrays with a beginning (index `0`) and an end (index `length - 1`), they are zero-padded at the end to `bytes32` and encoded in beginning to end order. This corresponds to their encoding in ABI v1 and v2.

The dynamic values `bytes` and `string` are encoded as a `keccak256` hash of their contents.

The array values are encoded as the `keccak256` hash of the concatenated `encodeData` of their contents (i.e. the encoding of `SomeType[5]` is identical to that of a struct containing five members of type `SomeType`).

The struct values are encoded recursively as `hashStruct(value)`. This is undefined for cyclical data.

### Definition of `domainSeparator`


```Solidity
domainSeparator = hashStruct(eip712Domain)
```

where the type of `eip712Domain` is a struct named `EIP712Domain` with one or more of the below fields. Protocol designers only need to include the fields that make sense for their signing domain. Unused fields are left out of the struct type.

* `string name` the user readable name of signing domain, i.e. the name of the DApp or the protocol.
* `string version` the current major version of the signing domain. Signatures from different versions are not compatible.
* `uint256 chainId` the [EIP-155][EIP-155] chain id. The user-agent _should_ refuse signing if it does not match the currently active chain.
* `address verifyingContract` the address of the contract that will verify the signature. The user-agent _may_ do contract specific phishing prevention.
* `bytes32 salt` a disambiguating salt for the protocol. This can be used as a domain separator of last resort.

[EIP-155]: /EIPs/EIPS/eip-155

Future extensions to this standard can add new fields with new user-agent behaviour constraints. User-agents are free to use the provided information to inform/warn users or refuse signing. Dapp implementers should not add private fields, new fields should be proposed through the EIP process.

The `EIP712Domain` fields should be the order as above, skipping any absent fields. Future field additions must be in alphabetical order and come after the above fields. User-agents should accept fields in any order as specified by the `EIP712Domain` type.

### Specification of the `eth_signTypedData` JSON RPC

The method `eth_signTypedData` is added to the Ethereum JSON-RPC. The method parallels `eth_sign`.

#### eth_signTypedData

The sign method calculates an Ethereum specific signature with: `sign(keccak256(&quot;\x19\x01&quot; ‖ domainSeparator ‖ hashStruct(message)))`, as defined above.

**Note**: the address to sign with must be unlocked. 

##### Parameters

1. `Address` - 20 Bytes - Address of the account that will sign the messages.
2. `TypedData` - Typed structured data to be signed.

Typed data is a JSON object containing type information, domain separator parameters and the message object. Below is the json-schema definition for `TypedData` param.

```JavaScript
{
  type: &apos;object&apos;,
  properties: {
    types: {
      type: &apos;object&apos;,
      properties: {
        EIP712Domain: {type: &apos;array&apos;},
      },
      additionalProperties: {
        type: &apos;array&apos;,
        items: {
          type: &apos;object&apos;,
          properties: {
            name: {type: &apos;string&apos;},
            type: {type: &apos;string&apos;}
          },
          required: [&apos;name&apos;, &apos;type&apos;]
        }
      },
      required: [&apos;EIP712Domain&apos;]
    },
    primaryType: {type: &apos;string&apos;},
    domain: {type: &apos;object&apos;},
    message: {type: &apos;object&apos;}
  },
  required: [&apos;types&apos;, &apos;primaryType&apos;, &apos;domain&apos;, &apos;message&apos;]
}
```

##### Returns

`DATA`: Signature. As in `eth_sign` it is a hex encoded 65 byte array starting with `0x`. It encodes the `r`, `s` and `v` parameters from appendix F of the yellow paper in big-endian format. Bytes 0...32 contain the `r` parameter, bytes 32...64 the `s` parameter and the last byte the `v` parameter. Note that the `v` parameter includes the chain id as specified in [EIP-155][eip-155].

##### Example

Request:

```shell
curl -X POST --data &apos;{&quot;jsonrpc&quot;:&quot;2.0&quot;,&quot;method&quot;:&quot;eth_signTypedData&quot;,&quot;params&quot;:[&quot;0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826&quot;, {&quot;types&quot;:{&quot;EIP712Domain&quot;:[{&quot;name&quot;:&quot;name&quot;,&quot;type&quot;:&quot;string&quot;},{&quot;name&quot;:&quot;version&quot;,&quot;type&quot;:&quot;string&quot;},{&quot;name&quot;:&quot;chainId&quot;,&quot;type&quot;:&quot;uint256&quot;},{&quot;name&quot;:&quot;verifyingContract&quot;,&quot;type&quot;:&quot;address&quot;}],&quot;Person&quot;:[{&quot;name&quot;:&quot;name&quot;,&quot;type&quot;:&quot;string&quot;},{&quot;name&quot;:&quot;wallet&quot;,&quot;type&quot;:&quot;address&quot;}],&quot;Mail&quot;:[{&quot;name&quot;:&quot;from&quot;,&quot;type&quot;:&quot;Person&quot;},{&quot;name&quot;:&quot;to&quot;,&quot;type&quot;:&quot;Person&quot;},{&quot;name&quot;:&quot;contents&quot;,&quot;type&quot;:&quot;string&quot;}]},&quot;primaryType&quot;:&quot;Mail&quot;,&quot;domain&quot;:{&quot;name&quot;:&quot;Ether Mail&quot;,&quot;version&quot;:&quot;1&quot;,&quot;chainId&quot;:1,&quot;verifyingContract&quot;:&quot;0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC&quot;},&quot;message&quot;:{&quot;from&quot;:{&quot;name&quot;:&quot;Cow&quot;,&quot;wallet&quot;:&quot;0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826&quot;},&quot;to&quot;:{&quot;name&quot;:&quot;Bob&quot;,&quot;wallet&quot;:&quot;0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB&quot;},&quot;contents&quot;:&quot;Hello, Bob!&quot;}}],&quot;id&quot;:1}&apos;
```

Result:

```JavaScript
{
  &quot;id&quot;:1,
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;result&quot;: &quot;0x4355c47d63924e8a72e509b65029052eb6c299d53a04e167c5775fd466751c9d07299936d304c153f6443dfa05f40ff007d72911b6f72307f996231605b915621c&quot;
}
```

An example how to use Solidity ecrecover to verify the signature calculated with `eth_signTypedData` can be found in the [Example.js][example-js]. The contract is deployed on the testnet Ropsten and Rinkeby.

[example-js]: /EIPs/assets/eip-712/Example.js

#### personal_signTypedData

There also should be a corresponding `personal_signTypedData` method which accepts the password for an account as the last argument.

### Specification of the Web3 API

Two methods are added to Web3.js version 1 that parallel the `web3.eth.sign` and `web3.eth.personal.sign` methods.

#### web3.eth.signTypedData

```JavaScript
web3.eth.signTypedData(typedData, address [, callback])
```

Signs typed data using a specific account. This account needs to be unlocked.

##### Parameters

1. ``Object`` - Domain separator and typed data to sign. Structured according to the JSON-Schema specified above in the `eth_signTypedData` JSON RPC call. 
2. ``String|Number`` - Address to sign data with. Or an address or index of a local wallet in :ref:`web3.eth.accounts.wallet &lt;eth_accounts_wallet&gt;`.
3. ``Function`` - (optional) Optional callback, returns an error object as first parameter and the result as second.

**Note**: The 2. ``address`` parameter can also be an address or index from the `web3.eth.accounts.wallet &lt;eth_accounts_wallet&gt;`. It will then sign locally using the private key of this account.

##### Returns

``Promise`` returns ``String`` - The signature as returned by `eth_signTypedData`.

##### Example

See the `eth_signTypedData` JSON-API example above for the value of `typedData`.

```JavaScript
web3.eth.signTypedData(typedData, &quot;0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826&quot;)
.then(console.log);
&gt; &quot;0x4355c47d63924e8a72e509b65029052eb6c299d53a04e167c5775fd466751c9d07299936d304c153f6443dfa05f40ff007d72911b6f72307f996231605b915621c&quot;
```

#### web3.eth.personal.signTypedData

```JavaScript
web3.eth.personal.signTypedData(typedData, address, password [, callback])
```

Identical to `web3.eth.signTypedData` except for an additional `password` parameter analogous to `web3.eth.personal.sign`.

## Rationale

The `encode` function is extended with a new case for the new types. The first byte of the encoding distinguishes the cases. For the same reason it is not safe to start immediately with the domain separator or a `typeHash`. While hard, it may be possible to construct a `typeHash` that also happens to be a prefix of a valid RLP encoded transaction.

The domain separator prevents collision of otherwise identical structures. It is possible that two DApps come up with an identical structure like `Transfer(address from,address to,uint256 amount)` that should not be compatible. By introducing a domain separator the DApp developers are guaranteed that there can be no signature collision.

The domain separator also allows for multiple distinct signatures use-cases on the same struct instance within a given DApp. In the previous example, perhaps signatures from both `from` and `to` are required. By providing two distinct domain separators these signatures can be distinguished from each other.

**Alternative 1**: Use the target contract address as domain separator. This solves the first problem, contracts coming up with identical types, but does not address the second use-case. The standard does suggest implementors to use the target contract address where this is appropriate.

The function `hashStruct` starts with a `typeHash` to separate types. By giving different types a different prefix the `encodeData` function only has to be injective within a given type. It is okay for `encodeData(a)` to equal `encodeData(b)` as long as `typeOf(a)` is not `typeOf(b)`.

### Rationale for `typeHash`

The `typeHash` is designed to turn into a compile time constant in Solidity. For example:

```Solidity
bytes32 constant MAIL_TYPEHASH = keccak256(
  &quot;Mail(address from,address to,string contents)&quot;);
```

For the type hash several alternatives were considered and rejected for the reasons:

**Alternative 2**: Use ABIv2 function signatures. `bytes4` is not enough to be collision resistant. Unlike function signatures, there is negligible runtime cost incurred by using longer hashes.

**Alternative 3**: ABIv2 function signatures modified to be 256-bit. While this captures type info, it does not capture any of the semantics other than the function. This is already causing a practical collision between [ERC-20]&apos;s and [ERC-721]&apos;s `transfer(address,uint256)`, where in the former the `uint256` refers to an amount and the latter to a unique id. In general ABIv2 favors compatibility where a hashing standard should prefer incompatibility.

[ERC-20]: /EIPs/EIPS/eip-20

[ERC-721]: /EIPs/EIPS/eip-721

**Alternative 4**: 256-bit ABIv2 signatures extended with parameter names and struct names. The `Mail` example from above would be encoded as `Mail(Person(string name,address wallet) from,Person(string name,address wallet) to,string contents)`. This is longer than the proposed solution. And indeed, the length of the string can grow exponentially in the length of the input (consider `struct A{B a;B b;}; struct B {C a;C b;}; …`). It also does not allow a recursive struct type (consider `struct List {uint256 value; List next;}`).

**Alternative 5**: Include natspec documentation. This would include even more semantic information in the schemaHash and further reduces chances of collision. It makes extending and amending documentation a breaking changes, which contradicts common assumptions. It also makes the schemaHash mechanism very verbose.

### Rationale for `encodeData`

The `encodeData` is designed to allow easy implementation of `hashStruct` in Solidity:

```Solidity
function hashStruct(Mail memory mail) pure returns (bytes32 hash) {
    return keccak256(abi.encode(
        MAIL_TYPEHASH,
        mail.from,
        mail.to,
        keccak256(mail.contents)
    ));
}
```

it also allows for an efficient in-place implementation in EVM

```Solidity
function hashStruct(Mail memory mail) pure returns (bytes32 hash) {

    // Compute sub-hashes
    bytes32 typeHash = MAIL_TYPEHASH;
    bytes32 contentsHash = keccak256(mail.contents);

    assembly {
        // Back up select memory
        let temp1 := mload(sub(mail, 32))
        let temp2 := mload(add(mail, 128))

        // Write typeHash and sub-hashes
        mstore(sub(mail, 32), typeHash)
        mstore(add(mail, 64), contentsHash)

        // Compute hash
        hash := keccak256(sub(mail, 32), 128)

        // Restore memory
        mstore(sub(mail, 32), temp1)
        mstore(add(mail, 64), temp2)
    }
}
```

The in-place implementation makes strong but reasonable assumptions on the memory layout of structs in memory. Specifically it assumes structs are not allocated below address 32, that members are stored in order, that all values are padded to 32-byte boundaries, and that dynamic and reference types are stored as a 32-byte pointers.

**Alternative 6**: Tight packing. This is the default behaviour in Solidity when calling `keccak256` with multiple arguments. It minimizes the number of bytes to be hashed but requires complicated packing instructions in EVM to do so. It does not allow in-place computation.

**Alternative 7**: ABIv2 encoding. Especially with the upcoming `abi.encode` it should be easy to use `abi.encode` as the `encodeData` function. The ABIv2 standard by itself fails the determinism security criteria. There are several valid ABIv2 encodings of the same data. ABIv2 does not allow in-place computation.

**Alternative 8**: Leave `typeHash` out of `hashStruct` and instead combine it with the domain separator. This is more efficient, but then the semantics of the Solidity `keccak256` hash function are not injective.

**Alternative 9**: Support cyclical data structures. The current standard is optimized for tree-like data structures and undefined for cyclical data structures. To support cyclical data a stack containing the path to the current node needs to be maintained and a stack offset substituted when a cycle is detected. This is prohibitively more complex to specify and implement. It also breaks composability where the hashes of the member values are used to construct the hash of the struct (the hash of the member values would depend on the path). It is possible to extend the standard in a compatible way to define hashes of cyclical data.

Similarly, a straightforward implementation is sub-optimal for directed acyclic graphs. A simple recursion through the members can visit the same node twice. Memoization can optimize this.

### Rationale for `domainSeparator`

Since different domains have different needs, an extensible scheme is used where the DApp specifies a `EIP712Domain` struct type and an instance `eip712Domain` which it passes to the user-agent. The user-agent can then apply different verification measures depending on the fields that are there.

## Backwards Compatibility

The RPC calls, web3 methods and `SomeStruct.typeHash` parameter are currently undefined. Defining them should not affect the behaviour of existing DApps.

The Solidity expression `keccak256(someInstance)` for an instance `someInstance` of a struct type `SomeStruct` is valid syntax. It currently evaluates to the `keccak256` hash of the memory address of the instance. This behaviour should be considered dangerous. In some scenarios it will appear to work correctly but in others it will fail determinism and/or injectiveness. DApps that depend on the current behaviour should be considered dangerously broken.

## Test Cases

An example contract can be found in [Example.sol][ex-sol] and an example implementation of signing in JavaScript in [Example.js][ex-js]

[ex-sol]: /EIPs/assets/eip-712/Example.sol

[ex-js]: /EIPs/assets/eip-712/Example.js

## Security Considerations

### Replay attacks

This standard is only about signing messages and verifying signatures. In many practical applications, signed messages are used to authorize an action, for example an exchange of tokens. It is _very important_ that implementers make sure the application behaves correctly when it sees the same signed message twice. For example, the repeated message should be rejected or the authorized action should be idempotent. How this is implemented is specific to the application and out of scope for this standard.

### Frontrunning attacks

The mechanism for reliably broadcasting a signature is application-specific and out of scope for this standard. When the signature is broadcast to a blockchain for use in a contract, the application has to be secure against frontrunning attacks. In this kind of attack, an attacker intercepts the signature and submits it to the contract before the original intended use takes place. The application should behave correctly when the signature is submitted first by an attacker, for example by rejecting it or simply producing exactly the same effect as intended by the signer.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 12 Sep 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-712</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-712</guid>
      </item>
    
      <item>
        <title>Non-Fungible Token Standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/eips/issues/721</comments>
        
        <description>## Simple Summary

A standard interface for non-fungible tokens, also known as deeds.

## Abstract

The following standard allows for the implementation of a standard API for NFTs within smart contracts. This standard provides basic functionality to track and transfer NFTs.

We considered use cases of NFTs being owned and transacted by individuals as well as consignment to third party brokers/wallets/auctioneers (&quot;operators&quot;). NFTs can represent ownership over digital or physical assets. We considered a diverse universe of assets, and we know you will dream up many more:

- Physical property — houses, unique artwork
- Virtual collectibles — unique pictures of kittens, collectible cards
- &quot;Negative value&quot; assets — loans, burdens and other responsibilities

In general, all houses are distinct and no two kittens are alike. NFTs are *distinguishable* and you must track the ownership of each one separately.

## Motivation

A standard interface allows wallet/broker/auction applications to work with any NFT on Ethereum. We provide for simple ERC-721 smart contracts as well as contracts that track an *arbitrarily large* number of NFTs. Additional applications are discussed below.

This standard is inspired by the ERC-20 token standard and builds on two years of experience since EIP-20 was created. EIP-20 is insufficient for tracking NFTs because each asset is distinct (non-fungible) whereas each of a quantity of tokens is identical (fungible).

Differences between this standard and EIP-20 are examined below.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

**Every ERC-721 compliant contract must implement the `ERC721` and `ERC165` interfaces** (subject to &quot;caveats&quot; below):

```solidity
pragma solidity ^0.4.20;

/// @title ERC-721 Non-Fungible Token Standard
/// @dev See https://eips.ethereum.org/EIPS/eip-721
///  Note: the ERC-165 identifier for this interface is 0x80ac58cd.
interface ERC721 /* is ERC165 */ {
    /// @dev This emits when ownership of any NFT changes by any mechanism.
    ///  This event emits when NFTs are created (`from` == 0) and destroyed
    ///  (`to` == 0). Exception: during contract creation, any number of NFTs
    ///  may be created and assigned without emitting Transfer. At the time of
    ///  any transfer, the approved address for that NFT (if any) is reset to none.
    event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);

    /// @dev This emits when the approved address for an NFT is changed or
    ///  reaffirmed. The zero address indicates there is no approved address.
    ///  When a Transfer event emits, this also indicates that the approved
    ///  address for that NFT (if any) is reset to none.
    event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);

    /// @dev This emits when an operator is enabled or disabled for an owner.
    ///  The operator can manage all NFTs of the owner.
    event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);

    /// @notice Count all NFTs assigned to an owner
    /// @dev NFTs assigned to the zero address are considered invalid, and this
    ///  function throws for queries about the zero address.
    /// @param _owner An address for whom to query the balance
    /// @return The number of NFTs owned by `_owner`, possibly zero
    function balanceOf(address _owner) external view returns (uint256);

    /// @notice Find the owner of an NFT
    /// @dev NFTs assigned to zero address are considered invalid, and queries
    ///  about them do throw.
    /// @param _tokenId The identifier for an NFT
    /// @return The address of the owner of the NFT
    function ownerOf(uint256 _tokenId) external view returns (address);

    /// @notice Transfers the ownership of an NFT from one address to another address
    /// @dev Throws unless `msg.sender` is the current owner, an authorized
    ///  operator, or the approved address for this NFT. Throws if `_from` is
    ///  not the current owner. Throws if `_to` is the zero address. Throws if
    ///  `_tokenId` is not a valid NFT. When transfer is complete, this function
    ///  checks if `_to` is a smart contract (code size &gt; 0). If so, it calls
    ///  `onERC721Received` on `_to` and throws if the return value is not
    ///  `bytes4(keccak256(&quot;onERC721Received(address,address,uint256,bytes)&quot;))`.
    /// @param _from The current owner of the NFT
    /// @param _to The new owner
    /// @param _tokenId The NFT to transfer
    /// @param data Additional data with no specified format, sent in call to `_to`
    function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;

    /// @notice Transfers the ownership of an NFT from one address to another address
    /// @dev This works identically to the other function with an extra data parameter,
    ///  except this function just sets data to &quot;&quot;.
    /// @param _from The current owner of the NFT
    /// @param _to The new owner
    /// @param _tokenId The NFT to transfer
    function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;

    /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
    ///  TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE
    ///  THEY MAY BE PERMANENTLY LOST
    /// @dev Throws unless `msg.sender` is the current owner, an authorized
    ///  operator, or the approved address for this NFT. Throws if `_from` is
    ///  not the current owner. Throws if `_to` is the zero address. Throws if
    ///  `_tokenId` is not a valid NFT.
    /// @param _from The current owner of the NFT
    /// @param _to The new owner
    /// @param _tokenId The NFT to transfer
    function transferFrom(address _from, address _to, uint256 _tokenId) external payable;

    /// @notice Change or reaffirm the approved address for an NFT
    /// @dev The zero address indicates there is no approved address.
    ///  Throws unless `msg.sender` is the current NFT owner, or an authorized
    ///  operator of the current owner.
    /// @param _approved The new approved NFT controller
    /// @param _tokenId The NFT to approve
    function approve(address _approved, uint256 _tokenId) external payable;

    /// @notice Enable or disable approval for a third party (&quot;operator&quot;) to manage
    ///  all of `msg.sender`&apos;s assets
    /// @dev Emits the ApprovalForAll event. The contract MUST allow
    ///  multiple operators per owner.
    /// @param _operator Address to add to the set of authorized operators
    /// @param _approved True if the operator is approved, false to revoke approval
    function setApprovalForAll(address _operator, bool _approved) external;

    /// @notice Get the approved address for a single NFT
    /// @dev Throws if `_tokenId` is not a valid NFT.
    /// @param _tokenId The NFT to find the approved address for
    /// @return The approved address for this NFT, or the zero address if there is none
    function getApproved(uint256 _tokenId) external view returns (address);

    /// @notice Query if an address is an authorized operator for another address
    /// @param _owner The address that owns the NFTs
    /// @param _operator The address that acts on behalf of the owner
    /// @return True if `_operator` is an approved operator for `_owner`, false otherwise
    function isApprovedForAll(address _owner, address _operator) external view returns (bool);
}

interface ERC165 {
    /// @notice Query if a contract implements an interface
    /// @param interfaceID The interface identifier, as specified in ERC-165
    /// @dev Interface identification is specified in ERC-165. This function
    ///  uses less than 30,000 gas.
    /// @return `true` if the contract implements `interfaceID` and
    ///  `interfaceID` is not 0xffffffff, `false` otherwise
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
```

A wallet/broker/auction application MUST implement the **wallet interface** if it will accept safe transfers.

```solidity
/// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02.
interface ERC721TokenReceiver {
    /// @notice Handle the receipt of an NFT
    /// @dev The ERC721 smart contract calls this function on the recipient
    ///  after a `transfer`. This function MAY throw to revert and reject the
    ///  transfer. Return of other than the magic value MUST result in the
    ///  transaction being reverted.
    ///  Note: the contract address is always the message sender.
    /// @param _operator The address which called `safeTransferFrom` function
    /// @param _from The address which previously owned the token
    /// @param _tokenId The NFT identifier which is being transferred
    /// @param _data Additional data with no specified format
    /// @return `bytes4(keccak256(&quot;onERC721Received(address,address,uint256,bytes)&quot;))`
    ///  unless throwing
    function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes _data) external returns(bytes4);
}
```

The **metadata extension** is OPTIONAL for ERC-721 smart contracts (see &quot;caveats&quot;, below). This allows your smart contract to be interrogated for its name and for details about the assets which your NFTs represent.

```solidity
/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
/// @dev See https://eips.ethereum.org/EIPS/eip-721
///  Note: the ERC-165 identifier for this interface is 0x5b5e139f.
interface ERC721Metadata /* is ERC721 */ {
    /// @notice A descriptive name for a collection of NFTs in this contract
    function name() external view returns (string _name);

    /// @notice An abbreviated name for NFTs in this contract
    function symbol() external view returns (string _symbol);

    /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
    /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC
    ///  3986. The URI may point to a JSON file that conforms to the &quot;ERC721
    ///  Metadata JSON Schema&quot;.
    function tokenURI(uint256 _tokenId) external view returns (string);
}
```

This is the &quot;ERC721 Metadata JSON Schema&quot; referenced above.

```json
{
    &quot;title&quot;: &quot;Asset Metadata&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;name&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Identifies the asset to which this NFT represents&quot;
        },
        &quot;description&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Describes the asset to which this NFT represents&quot;
        },
        &quot;image&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive.&quot;
        }
    }
}
```

The **enumeration extension** is OPTIONAL for ERC-721 smart contracts (see &quot;caveats&quot;, below). This allows your contract to publish its full list of NFTs and make them discoverable.

```solidity
/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
/// @dev See https://eips.ethereum.org/EIPS/eip-721
///  Note: the ERC-165 identifier for this interface is 0x780e9d63.
interface ERC721Enumerable /* is ERC721 */ {
    /// @notice Count NFTs tracked by this contract
    /// @return A count of valid NFTs tracked by this contract, where each one of
    ///  them has an assigned and queryable owner not equal to the zero address
    function totalSupply() external view returns (uint256);

    /// @notice Enumerate valid NFTs
    /// @dev Throws if `_index` &gt;= `totalSupply()`.
    /// @param _index A counter less than `totalSupply()`
    /// @return The token identifier for the `_index`th NFT,
    ///  (sort order not specified)
    function tokenByIndex(uint256 _index) external view returns (uint256);

    /// @notice Enumerate NFTs assigned to an owner
    /// @dev Throws if `_index` &gt;= `balanceOf(_owner)` or if
    ///  `_owner` is the zero address, representing invalid NFTs.
    /// @param _owner An address where we are interested in NFTs owned by them
    /// @param _index A counter less than `balanceOf(_owner)`
    /// @return The token identifier for the `_index`th NFT assigned to `_owner`,
    ///   (sort order not specified)
    function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);
}
```

### Caveats

The 0.4.20 Solidity interface grammar is not expressive enough to document the ERC-721 standard. A contract which complies with ERC-721 MUST also abide by the following:

- Solidity issue #3412: The above interfaces include explicit mutability guarantees for each function. Mutability guarantees are, in order weak to strong: `payable`, implicit nonpayable, `view`, and `pure`. Your implementation MUST meet the mutability guarantee in this interface and you MAY meet a stronger guarantee. For example, a `payable` function in this interface may be implemented as nonpayable (no state mutability specified) in your contract. We expect a later Solidity release will allow your stricter contract to inherit from this interface, but a workaround for version 0.4.20 is that you can edit this interface to add stricter mutability before inheriting from your contract.
- Solidity issue #3419: A contract that implements `ERC721Metadata` or `ERC721Enumerable` SHALL also implement `ERC721`. ERC-721 implements the requirements of interface ERC-165.
- Solidity issue #2330: If a function is shown in this specification as `external` then a contract will be compliant if it uses `public` visibility. As a workaround for version 0.4.20, you can edit this interface to switch to `public` before inheriting from your contract.
- Solidity issues #3494, #3544: Use of `this.*.selector` is marked as a warning by Solidity, a future version of Solidity will not mark this as an error.

*If a newer version of Solidity allows the caveats to be expressed in code, then this EIP MAY be updated and the caveats removed, such will be equivalent to the original specification.*

## Rationale

There are many proposed uses of Ethereum smart contracts that depend on tracking distinguishable assets. Examples of existing or planned NFTs are LAND in Decentraland, the eponymous punks in CryptoPunks, and in-game items using systems like DMarket or EnjinCoin. Future uses include tracking real-world assets, like real-estate (as envisioned by companies like Ubitquity or Propy). It is critical in each of these cases that these items are not &quot;lumped together&quot; as numbers in a ledger, but instead each asset must have its ownership individually and atomically tracked. Regardless of the nature of these assets, the ecosystem will be stronger if we have a standardized interface that allows for cross-functional asset management and sales platforms.

**&quot;NFT&quot; Word Choice**

&quot;NFT&quot; was satisfactory to nearly everyone surveyed and is widely applicable to a broad universe of distinguishable digital assets. We recognize that &quot;deed&quot; is very descriptive for certain applications of this standard (notably, physical property).

*Alternatives considered: distinguishable asset, title, token, asset, equity, ticket*

**NFT Identifiers**

Every NFT is identified by a unique `uint256` ID inside the ERC-721 smart contract. This identifying number SHALL NOT change for the life of the contract. The pair `(contract address, uint256 tokenId)` will then be a globally unique and fully-qualified identifier for a specific asset on an Ethereum chain. While some ERC-721 smart contracts may find it convenient to start with ID 0 and simply increment by one for each new NFT, callers SHALL NOT assume that ID numbers have any specific pattern to them, and MUST treat the ID as a &quot;black box&quot;. Also note that NFTs MAY become invalid (be destroyed). Please see the enumeration functions for a supported enumeration interface.

The choice of `uint256` allows a wide variety of applications because UUIDs and sha3 hashes are directly convertible to `uint256`.

**Transfer Mechanism**

ERC-721 standardizes a safe transfer function `safeTransferFrom` (overloaded with and without a `bytes` parameter) and an unsafe function `transferFrom`. Transfers may be initiated by:

- The owner of an NFT
- The approved address of an NFT
- An authorized operator of the current owner of an NFT

Additionally, an authorized operator may set the approved address for an NFT. This provides a powerful set of tools for wallet, broker and auction applications to quickly use a *large* number of NFTs.

The transfer and accept functions&apos; documentation only specify conditions when the transaction MUST throw. Your implementation MAY also throw in other situations. This allows implementations to achieve interesting results:

- **Disallow transfers if the contract is paused** — prior art, CryptoKitties deployed contract, line 611
- **Blocklist certain address from receiving NFTs** — prior art, CryptoKitties deployed contract, lines 565, 566
- **Disallow unsafe transfers** — `transferFrom` throws unless `_to` equals `msg.sender` or `countOf(_to)` is non-zero or was non-zero previously (because such cases are safe)
- **Charge a fee to both parties of a transaction** — require payment when calling `approve` with a non-zero `_approved` if it was previously the zero address, refund payment if calling `approve` with the zero address if it was previously a non-zero address, require payment when calling any transfer function, require transfer parameter `_to` to equal `msg.sender`, require transfer parameter `_to` to be the approved address for the NFT
- **Read only NFT registry** — always throw from `safeTransferFrom`, `transferFrom`, `approve` and `setApprovalForAll`

Failed transactions will throw, a best practice identified in ERC-223, ERC-677, ERC-827 and OpenZeppelin&apos;s implementation of SafeERC20.sol. ERC-20 defined an `allowance` feature, this caused a problem when called and then later modified to a different amount, as on OpenZeppelin issue \#438. In ERC-721, there is no allowance because every NFT is unique, the quantity is none or one. Therefore we receive the benefits of ERC-20&apos;s original design without problems that have been later discovered.

Creation of NFTs (&quot;minting&quot;) and destruction of NFTs (&quot;burning&quot;) is not included in the specification. Your contract may implement these by other means. Please see the `event` documentation for your responsibilities when creating or destroying NFTs.

We questioned if the `operator` parameter on `onERC721Received` was necessary. In all cases we could imagine, if the operator was important then that operator could transfer the token to themself and then send it -- then they would be the `from` address. This seems contrived because we consider the operator to be a temporary owner of the token (and transferring to themself is redundant). When the operator sends the token, it is the operator acting on their own accord, NOT the operator acting on behalf of the token holder. This is why the operator and the previous token owner are both significant to the token recipient.

*Alternatives considered: only allow two-step ERC-20 style transaction, require that transfer functions never throw, require all functions to return a boolean indicating the success of the operation.*

**ERC-165 Interface**

We chose Standard Interface Detection (ERC-165) to expose the interfaces that a ERC-721 smart contract supports.

A future EIP may create a global registry of interfaces for contracts. We strongly support such an EIP and it would allow your ERC-721 implementation to implement `ERC721Enumerable`, `ERC721Metadata`, or other interfaces by delegating to a separate contract.

**Gas and Complexity** (regarding the enumeration extension)

This specification contemplates implementations that manage a few and *arbitrarily large* numbers of NFTs. If your application is able to grow then avoid using for/while loops in your code (see CryptoKitties bounty issue \#4). These indicate your contract may be unable to scale and gas costs will rise over time without bound.

We have deployed a contract, XXXXERC721, to Testnet which instantiates and tracks 340282366920938463463374607431768211456 different deeds (2^128). That&apos;s enough to assign every IPV6 address to an Ethereum account owner, or to track ownership of nanobots a few micron in size and in aggregate totalling half the size of Earth. You can query it from the blockchain. And every function takes less gas than querying the ENS.

This illustration makes clear: the ERC-721 standard scales.

*Alternatives considered: remove the asset enumeration function if it requires a for-loop, return a Solidity array type from enumeration functions.*

**Privacy**

Wallets/brokers/auctioneers identified in the motivation section have a strong need to identify which NFTs an owner owns.

It may be interesting to consider a use case where NFTs are not enumerable, such as a private registry of property ownership, or a partially-private registry. However, privacy cannot be attained because an attacker can simply (!) call `ownerOf` for every possible `tokenId`.

**Metadata Choices** (metadata extension)

We have required `name` and `symbol` functions in the metadata extension. Every token EIP and draft we reviewed (ERC-20, ERC-223, ERC-677, ERC-777, ERC-827) included these functions.

We remind implementation authors that the empty string is a valid response to `name` and `symbol` if you protest to the usage of this mechanism. We also remind everyone that any smart contract can use the same name and symbol as *your* contract. How a client may determine which ERC-721 smart contracts are well-known (canonical) is outside the scope of this standard.

A mechanism is provided to associate NFTs with URIs. We expect that many implementations will take advantage of this to provide metadata for each NFT. The image size recommendation is taken from Instagram, they probably know much about image usability. The URI MAY be mutable (i.e. it changes from time to time). We considered an NFT representing ownership of a house, in this case metadata about the house (image, occupants, etc.) can naturally change.

Metadata is returned as a string value. Currently this is only usable as calling from `web3`, not from other contracts. This is acceptable because we have not considered a use case where an on-blockchain application would query such information.

*Alternatives considered: put all metadata for each asset on the blockchain (too expensive), use URL templates to query metadata parts (URL templates do not work with all URL schemes, especially P2P URLs), multiaddr network address (not mature enough)*

**Community Consensus**

A significant amount of discussion occurred on the original ERC-721 issue, additionally we held a first live meeting on Gitter that had good representation and well advertised (on Reddit, in the Gitter #ERC channel, and the original ERC-721 issue). Thank you to the participants:

- [@ImAllInNow](https://github.com/imallinnow) Rob from DEC Gaming / Presenting Michigan Ethereum Meetup Feb 7
- [@Arachnid](https://github.com/arachnid) Nick Johnson
- [@jadhavajay](https://github.com/jadhavajay) Ajay Jadhav from AyanWorks
- [@superphly](https://github.com/superphly) Cody Marx Bailey - XRAM Capital / Sharing at hackathon Jan 20 / UN Future of Finance Hackathon.
- [@fulldecent](https://github.com/fulldecent) William Entriken

A second event was held at ETHDenver 2018 to discuss distinguishable asset standards (notes to be published).

We have been very inclusive in this process and invite anyone with questions or contributions into our discussion. However, this standard is written only to support the identified use cases which are listed herein.

## Backwards Compatibility

We have adopted `balanceOf`, `totalSupply`, `name` and `symbol` semantics from the ERC-20 specification. An implementation may also include a function `decimals` that returns `uint8(0)` if its goal is to be more compatible with ERC-20 while supporting this standard. However, we find it contrived to require all ERC-721 implementations to support the `decimals` function.

Example NFT implementations as of February 2018:

- CryptoKitties -- Compatible with an earlier version of this standard.
- CryptoPunks -- Partially ERC-20 compatible, but not easily generalizable because it includes auction functionality directly in the contract and uses function names that explicitly refer to the assets as &quot;punks&quot;.
- Auctionhouse Asset Interface -- The author needed a generic interface for the Auctionhouse ÐApp (currently ice-boxed). His &quot;Asset&quot; contract is very simple, but is missing ERC-20 compatibility, `approve()` functionality, and metadata. This effort is referenced in the discussion for EIP-173.

Note: &quot;Limited edition, collectible tokens&quot; like Curio Cards and Rare Pepe are *not* distinguishable assets. They&apos;re actually a collection of individual fungible tokens, each of which is tracked by its own smart contract with its own total supply (which may be `1` in extreme cases).

The `onERC721Received` function specifically works around old deployed contracts which may inadvertently return 1 (`true`) in certain circumstances even if they don&apos;t implement a function (see Solidity DelegateCallReturnValue bug). By returning and checking for a magic value, we are able to distinguish actual affirmative responses versus these vacuous `true`s.

## Test Cases

0xcert ERC-721 Token includes test cases written using Truffle.

## Implementations

0xcert ERC721 -- a reference implementation

- MIT licensed, so you can freely use it for your projects
- Includes test cases
- Active bug bounty, you will be paid if you find errors

Su Squares -- an advertising platform where you can rent space and place images

- Complete the Su Squares Bug Bounty Program to seek problems with this standard or its implementation
- Implements the complete standard and all optional interfaces

ERC721ExampleDeed -- an example implementation

- Implements using the OpenZeppelin project format

XXXXERC721, by William Entriken -- a scalable example implementation

- Deployed on testnet with 1 billion assets and supporting all lookups with the metadata extension. This demonstrates that scaling is NOT a problem.

## References

**Standards**

1. [ERC-20](/EIPs/EIPS/eip-20) Token Standard.
1. [ERC-165](/EIPs/EIPS/eip-165) Standard Interface Detection.
1. [ERC-173](/EIPs/EIPS/eip-173) Owned Standard.
1. [ERC-223](https://github.com/ethereum/EIPs/issues/223) Token Standard.
1. [ERC-677](https://github.com/ethereum/EIPs/issues/677) `transferAndCall` Token Standard.
1. [ERC-827](https://github.com/ethereum/EIPs/issues/827) Token Standard.
1. Ethereum Name Service (ENS). https://ens.domains
1. Instagram -- What&apos;s the Image Resolution? https://help.instagram.com/1631821640426723
1. JSON Schema. https://json-schema.org/
1. Multiaddr. https://github.com/multiformats/multiaddr
1. RFC 2119 Key words for use in RFCs to Indicate Requirement Levels. https://www.ietf.org/rfc/rfc2119.txt

**Issues**

1. The Original ERC-721 Issue. https://github.com/ethereum/eips/issues/721
1. Solidity Issue \#2330 -- Interface Functions are External. https://github.com/ethereum/solidity/issues/2330
1. Solidity Issue \#3412 -- Implement Interface: Allow Stricter Mutability. https://github.com/ethereum/solidity/issues/3412
1. Solidity Issue \#3419 -- Interfaces Can&apos;t Inherit. https://github.com/ethereum/solidity/issues/3419
1. Solidity Issue \#3494 -- Compiler Incorrectly Reasons About the `selector` Function. https://github.com/ethereum/solidity/issues/3494
1. Solidity Issue \#3544 -- Cannot Calculate Selector of Function Named `transfer`. https://github.com/ethereum/solidity/issues/3544
1. CryptoKitties Bounty Issue \#4 -- Listing all Kitties Owned by a User is `O(n^2)`. https://github.com/axiomzen/cryptokitties-bounty/issues/4
1. OpenZeppelin Issue \#438 -- Implementation of `approve` method violates ERC20 standard. https://github.com/OpenZeppelin/zeppelin-solidity/issues/438
1. Solidity DelegateCallReturnValue Bug. https://solidity.readthedocs.io/en/develop/bugs.html#DelegateCallReturnValue

**Discussions**

1. Reddit (announcement of first live discussion). https://www.reddit.com/r/ethereum/comments/7r2ena/friday_119_live_discussion_on_erc_nonfungible/
1. Gitter #EIPs (announcement of first live discussion). https://gitter.im/ethereum/EIPs?at=5a5f823fb48e8c3566f0a5e7
1. ERC-721 (announcement of first live discussion). https://github.com/ethereum/eips/issues/721#issuecomment-358369377
1. ETHDenver 2018. https://ethdenver.com

**NFT Implementations and Other Projects**

1. CryptoKitties. https://www.cryptokitties.co
1. 0xcert ERC-721 Token. https://github.com/0xcert/ethereum-erc721
1. Su Squares. https://tenthousandsu.com
1. Decentraland. https://decentraland.org
1. CryptoPunks. https://www.larvalabs.com/cryptopunks
1. DMarket. https://www.dmarket.io
1. Enjin Coin. https://enjincoin.io
1. Ubitquity. https://www.ubitquity.io
1. Propy. https://tokensale.propy.com
1. CryptoKitties Deployed Contract. https://etherscan.io/address/0x06012c8cf97bead5deae237070f9587f8e7a266d#code
1. Su Squares Bug Bounty Program. https://github.com/fulldecent/su-squares-bounty
1. XXXXERC721. https://github.com/fulldecent/erc721-example
1. ERC721ExampleDeed. https://github.com/nastassiasachs/ERC721ExampleDeed
1. Curio Cards. https://mycuriocards.com
1. Rare Pepe. https://rarepepewallet.com
1. Auctionhouse Asset Interface. https://github.com/dob/auctionhouse/blob/master/contracts/Asset.sol
1. [OpenZeppelin `SafeERC20.sol` Implementation](/EIPs/assets/eip-721/SafeERC20.sol).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 24 Jan 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-721</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-721</guid>
      </item>
    
      <item>
        <title>General data key/value store and execution</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/discussion-for-eip725/12158</comments>
        
        <description>## Abstract

The following describes two standards that allow for a generic data storage in a smart contract and a generic execution through a smart contract. These can be used separately or in conjunction and can serve as building blocks for smart contract accounts, upgradable metadata, and other means.

## Motivation

The initial motivation came out of the need to create a smart contract account system that&apos;s flexible enough to be viable long-term but also defined enough to be standardized. They are a generic set of two standardized building blocks to be used in all forms of smart contracts.

This standard consists of two sub-standards, a generic data key/value store (`ERC725Y`) and a generic execute function (`ERC725X`). Both of these in combination allow for a very flexible and long-lasting account system. The account version of `ERC725` is standardized under `LSP0-ERC725Account`.

These standards (`ERC725` X and Y) can also be used separately as `ERC725Y` can be used to enhance NFTs and Token metadata or other types of smart contracts. `ERC725X` allows for a generic execution through a smart contract, functioning as an account or actor.

## Specification

### Ownership

This contract is controlled by a single owner. The owner can be a smart contract or an external account.
This standard requires [ERC-173](/EIPs/EIPS/eip-173) and SHOULD implement the functions:

- `owner() view`
- `transferOwnership(address newOwner)`

And the event:

- `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)`

---

### `ERC725X`

**`ERC725X`** interface id according to [ERC-165](/EIPs/EIPS/eip-165): `0x7545acac`.

Smart contracts implementing the `ERC725X` standard MUST implement the [ERC-165](/EIPs/EIPS/eip-165) `supportsInterface(..)` function and MUST support the `ERC165` and `ERC725X` interface ids.

### `ERC725X` Methods

Smart contracts implementing the `ERC725X` standard SHOULD implement all of the functions listed below:

#### execute

```solidity
function execute(uint256 operationType, address target, uint256 value, bytes memory data) external payable returns(bytes memory)
```

Function Selector: `0x44c028fe`

Executes a call on any other smart contracts or address, transfers the blockchains native token, or deploys a new smart contract.


_Parameters:_

- `operationType`: the operation type used to execute.
- `target`: the smart contract or address to call. `target` will be unused if a contract is created (operation types 1 and 2).
- `value`: the amount of native tokens to transfer (in Wei).
- `data`: the call data, or the creation bytecode of the contract to deploy.


_Requirements:_

- MUST only be called by the current owner of the contract.
- MUST revert when the execution or the contract creation fails.
- `target` SHOULD be address(0) in case of contract creation with `CREATE` and `CREATE2` (operation types 1 and 2).
- `value` SHOULD be zero in case of `STATICCALL` or `DELEGATECALL` (operation types 3 and 4).


_Returns:_ `bytes` , the returned data of the called function, or the address of the contract deployed (operation types 1 and 2).

**Triggers Event:** [ContractCreated](#contractcreated), [Executed](#executed)

The following `operationType` COULD exist:

- `0` for `CALL`
- `1` for `CREATE`
- `2` for `CREATE2`
- `3` for `STATICCALL`
- `4` for `DELEGATECALL` - **NOTE** This is a potentially dangerous operation type

Others may be added in the future.

#### data parameter

- For operationType, `CALL`, `STATICCALL` and `DELEGATECALL` the data field can be random bytes or an abi-encoded function call.

- For operationType, `CREATE` the `data` field is the creation bytecode of the contract to deploy appended with the constructor argument(s) abi-encoded.

- For operationType, `CREATE2` the `data` field is the creation bytecode of the contract to deploy appended with:
  1. the constructor argument(s) abi-encoded
  2. a `bytes32` salt.

```
data = &lt;contract-creation-code&gt; + &lt;abi-encoded-constructor-arguments&gt; + &lt;bytes32-salt&gt;
```

&gt; See [EIP-1014: Skinny CREATE2](/EIPs/EIPS/eip-1014) for more information.

#### executeBatch

```solidity
function executeBatch(uint256[] memory operationsType, address[] memory targets, uint256[] memory values, bytes[] memory datas) external payable returns(bytes[] memory)
```

Function Selector: `0x31858452`

Executes a batch of calls on any other smart contracts, transfers the blockchain native token, or deploys a new smart contract.

_Parameters:_

- `operationsType`: the list of operations type used to execute.
- `targets`: the list of addresses to call. `targets` will be unused if a contract is created (operation types 1 and 2).
- `values`: the list of native token amounts to transfer (in Wei).
- `datas`: the list of call data, or the creation bytecode of the contract to deploy.

_Requirements:_

- Parameters array MUST have the same length.
- MUST only be called by the current owner of the contract.
- MUST revert when the execution or the contract creation fails.
- `target` SHOULD be address(0) in case of contract creation with `CREATE` and `CREATE2` (operation types 1 and 2).
- `value` SHOULD be zero in case of `STATICCALL` or `DELEGATECALL` (operation types 3 and 4).

_Returns:_ `bytes[]` , array list of returned data of the called function, or the address(es) of the contract deployed (operation types 1 and 2).

**Triggers Event:** [ContractCreated](#contractcreated), [Executed](#executed) on each call iteration

### `ERC725X` Events

#### Executed

```solidity
event Executed(uint256 indexed operationType, address indexed target, uint256 indexed value, bytes4 data);
```

MUST be triggered when `execute` creates a new call using the `operationType` `0`, `3`, `4`.

#### ContractCreated

```solidity
event ContractCreated(uint256 indexed operationType, address indexed contractAddress, uint256 indexed value, bytes32 salt);
```

MUST be triggered when `execute` creates a new contract using the `operationType` `1`, `2`.

---

### `ERC725Y`

**`ERC725Y`** interface id according to [ERC-165](/EIPs/EIPS/eip-165): `0x629aa694`.

Smart contracts implementing the `ERC725Y` standard MUST implement the [ERC-165](/EIPs/EIPS/eip-165) `supportsInterface(..)` function and MUST support the `ERC165` and `ERC725Y` interface ids.

### `ERC725Y` Methods

Smart contracts implementing the `ERC725Y` standard MUST implement all of the functions listed below:

#### getData

```solidity
function getData(bytes32 dataKey) external view returns(bytes memory)
```

Function Selector: `0x54f6127f`

Gets the data set for the given data key.

_Parameters:_

- `dataKey`: the data key which value to retrieve.

_Returns:_ `bytes` , The data for the requested data key.

#### getDataBatch

```solidity
function getDataBatch(bytes32[] memory dataKeys) external view returns(bytes[] memory)
```

Function Selector: `0xdedff9c6`

Gets array of data at multiple given data keys.

_Parameters:_

- `dataKeys`: the data keys which values to retrieve.

_Returns:_ `bytes[]` , array of data values for the requested data keys.

#### setData

```solidity
function setData(bytes32 dataKey, bytes memory dataValue) external
```

Function Selector: `0x7f23690c`

Sets data as bytes in the storage for a single data key. 

_Parameters:_

- `dataKey`: the data key which value to set.
- `dataValue`: the data to store.

_Requirements:_

- MUST only be called by the current owner of the contract.

**Triggers Event:** [DataChanged](#datachanged)

#### setDataBatch

```solidity
function setDataBatch(bytes32[] memory dataKeys, bytes[] memory dataValues) external
```

Function Selector: `0x97902421`

Sets array of data at multiple data keys. MUST only be called by the current owner of the contract.

_Parameters:_

- `dataKeys`: the data keys which values to set.
- `dataValues`: the array of bytes to set.

_Requirements:_

- Array parameters MUST have the same length.
- MUST only be called by the current owner of the contract.

**Triggers Event:** [DataChanged](#datachanged)

### `ERC725Y` Events

#### DataChanged

```solidity
event DataChanged(bytes32 indexed dataKey, bytes dataValue)
```

MUST be triggered when a data key was successfully set.

### `ERC725Y` Data keys

Data keys, are the way to retrieve values via `getData()`. These `bytes32` values can be freely chosen, or defined by a standard.
A common way to define data keys is the hash of a word, e.g. `keccak256(&apos;ERCXXXMyNewKeyType&apos;)` which results in: `0x6935a24ea384927f250ee0b954ed498cd9203fc5d2bf95c735e52e6ca675e047`

The `LSP2-ERC725JSONSchema` standard is a more explicit `ERC725Y` data key standard, that defines key types and value types, and their encoding and decoding.

## Rationale

The generic way of storing data keys with values was chosen to allow upgradability over time. Stored data values can be changed over time. Other smart contract protocols can then interpret this data in new ways and react to interactions from a `ERC725` smart contract differently.

The data stored in an `ERC725Y` smart contract is not only readable/writable by off-chain applications, but also by other smart contracts. Function overloading was used to allow for the retrievable of single and multiple keys, to keep gas costs minimal for both use cases.

## Backwards Compatibility

All contracts since `ERC725v2` from 2018/19 should be compatible with the current version of the standard. Mainly interface ID and Event parameters have changed, while `getData(bytes32[])` and `setData(bytes32[], bytes[])` was added as an efficient way to set/get multiple keys at once. The same applies to execution, as `execute(..[])` was added as an efficient way to batch calls.

From 2023 onward, overloading was removed from `ERC-725` (including `ERC725-X` and `ERC725-Y`). This is because, while overloading is accommodated in Solidity, it isn&apos;t broadly supported across most blockchain languages. In order to make the standard language-independent, it was decided to shift from overloading to simply attach the term &quot;Batch&quot; to the functions that accept an array as parameters.

## Reference Implementation

Reference implementations can be found in [`ERC725.sol`](/EIPs/assets/eip-725/ERC725.sol).

## Security Considerations

This contract allows generic executions, therefore special care needs to be taken to prevent re-entrancy attacks and other forms of call chain attacks.

When using the operation type `4` for `delegatecall`, it is important to consider that the called contracts can alter the state of the calling contract and also change owner variables and `ERC725Y` data storage entries at will. Additionally calls to `selfdestruct` are possible and other harmful state-changing operations.

### Solidity Interfaces

```solidity
// SPDX-License-Identifier: CC0-1.0

pragma solidity &gt;=0.5.0 &lt;0.7.0;

// ERC165 identifier: `0x7545acac`
interface IERC725X  /* is ERC165, ERC173 */ {

    event Executed(uint256 indexed operationType, address indexed target, uint256 indexed  value, bytes4 data);
    event ContractCreated(uint256 indexed operationType, address indexed contractAddress, uint256 indexed value, bytes32 salt);


    function execute(uint256 operationType, address target, uint256 value, bytes memory data) external payable returns(bytes memory);

    function executeBatch(uint256[] memory operationsType, address[] memory targets, uint256[] memory values, bytes memory datas) external payable returns(bytes[] memory);
}

// ERC165 identifier: `0x629aa694`
interface IERC725Y /* is ERC165, ERC173 */ {
    
    event DataChanged(bytes32 indexed dataKey, bytes dataValue);

    function getData(bytes32 dataKey) external view returns(bytes memory);
    function getDataBatch(bytes32[] memory dataKeys) external view returns(bytes[] memory);

    function setData(bytes32 dataKey, bytes memory dataValue) external;
    function setDataBatch(bytes32[] memory dataKeys, bytes[] memory dataValues) external;
}
interface IERC725 /* is IERC725X, IERC725Y */ {
}
```

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 02 Oct 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-725</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-725</guid>
      </item>
    
      <item>
        <title>wallet_watchAsset RPC Method</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-747-eth-watchtoken/1048</comments>
        
        <description>## Abstract

This EIP standardizes a new wallet-scoped RPC method, `wallet_watchAsset`, to allow a client to suggest a token for the user&apos;s wallet to track.

## Motivation

Today, one of the major uses of Ethereum wallets is to track users&apos; assets.
Without this EIP, each wallet either needs to pre-load a list of approved assets, or users must manually add assets to their wallet.
In the first case, wallets are burdened with both the security of managing this list, as well as the bandwidth of mass polling for known assets on their wallet.
In the second case, the user experience is terrible.

## Specification

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

A new RPC method, `wallet_watchAsset` is added. `wallet_watchAsset` requests that a specified asset be listed to the user&apos;s wallet. It MUST immediately (i.e. before prompting the user) return `true` if the request was valid, or error if it was not. The meaning of &quot;listed to the user&apos;s wallet&quot; is dependent on the wallet implementation. A successful call to `wallet_watchAsset` MUST indicate that the wallet recognized the request and that it contained no issues, but doesn&apos;t indicate whether the user was prompted or whether the asset was actually added to the wallet.

### `wallet_watchAsset` Parameters

The `wallet_watchAsset` method takes a single parameter, a `WatchAssetParameters` object, which is defined as follows:
 
```typescript
interface WatchAssetParameters {
  type: string; // The asset&apos;s interface, e.g. &apos;ERC1046&apos;
  options: any;
}
```

The `type` string SHOULD be the commonly accepted name of the interface implemented by the asset&apos;s contract, e.g. `ERC1046`. Defining the global identifiers for different asset types is beyond the scope of this EIP.

This interface SHOULD be extended or modified depending on the asset `type`. These changes MUST be specified in separate EIPs.

### `wallet_watchAsset` Returns

`wallet_watchAsset` immediately (i.e. without waiting for user interaction) returns the boolean value `true` to indicate that the request was recognized (regardless of whether the user was prompted), or errors if the request is invalid. An error might occur in the following circumstances (not comprehensive):

- The asset type is unrecognized/unsupported
- The asset was blocked due to an allowlist or denylist (this makes the request &apos;invalid&apos; since the root cause requires developer action)
- Downloading the image failed to load
  - The wallet didn&apos;t load some of the metadata required to display the asset, in order to protect against a potential SSRF attack

### `ERC1046` type

The format of the options field is:

```typescript
interface ERC1046WatchAssetOptions {
{
    address: string; // The hexadecimal address of the token contract
    chainId?: number; // The chain ID of the asset. If empty, defaults to the current chain ID.
  };
}
```

`address` is required, and the other fields are optional. `address` MUST be the `0x`-prefixed checksummed hexadecimal address of the token contract. `chainId` MUST be the chain ID to which the asset belongs.

If the checksum fails, the request MUST be considered invalid.

If the wallet does not recognize the `chainId`, or the `chainId` is blank and the wallet does not have a concept of &quot;active&quot; chain, the call MUST fail.

`wallet_watchAsset` MUST fetch the [ERC-1046](/EIPs/EIPS/eip-1046) `tokenURI` and check the `interop` field to determine the type of the token. If the parsing fails, or the type is unknown, the RPC call MUST error.

`wallet_watchAsset` SHOULD check the `name` and `symbol` fields, and the contract `address` and `chainId` against a list of well-known tokens. If the name and/or symbol are similar to ones on the list but the `chainId`/`address` don&apos;t match, a warning SHOULD be presented to the user.

The wallet SHOULD whitelist and/or blacklist specific ports and schemes to avoid SSRF attacks.

### Legacy `ERC20` type

The format of the options field is:

```typescript
interface ERC20WatchAssetOptions {
{
    address: string; // The hexadecimal address of the token contract
    chainId?: number; // The chain ID of the asset. If empty, defaults to the current chain ID.
  };
}
```

`address` is required, and the other fields are optional. `address` MUST be the `0x`-prefixed checksummed hexadecimal address of the token contract. `chainId` MUST be the chain ID to which the asset belongs.

If the checksum fails, the request MUST be considered invalid.

If the wallet does not recognize the `chainId`, or the `chainId` is blank and the wallet does not have a concept of &quot;active&quot; chain, the call MUST fail.

`wallet_watchAsset` SHOULD check the `name` and `symbol` fields, and the contract `address` and `chainId` against a list of well-known tokens. If the name and/or symbol are similar to ones on the list but the `chainId`/`address` don&apos;t match, a warning SHOULD be presented to the user.

If possible, it is RECOMMENDED to instead use the `ERC1046` type, which supports images and custom metadata.

## Rationale

Displaying a user&apos;s assets is a basic feature that every modern DApp user expects. Most wallets currently either manage their own asset lists, which they store client-side, or they query a centralized API for balances, which reduces decentralization and allows correlating account holders with IP addresses. Additionally, refreshing/polling an asset list from the network can be costly, especially on bandwidth-constrained devices. Also, maintaining an asset list becomes a political act, provoking harassment and inducing pressure to list obscure assets.

Automatically listing assets makes assets into a sort of spam mail: Users suddenly see new assets that they don&apos;t care about in their wallet. This can be used to send unsolicited information, or even to conduct phishing scams. This phenomenon is already common with airdropped tokens, a major cause of network congestion, because spamming people with new tokens has, so far, been rewarded with increased user attention.

When a user is manually adding an asset, they had likely previously learned about it from a website. At that moment, there was a natural alignment of interests, where both parties wanted the user to track the token. This is a natural point to introduce an API to easily allow these parties to collaborate.

## Security Considerations

### Server-Side Request Forgery

Wallets should be careful about making arbitrary requests to URLs. As such, it is recommended for wallets to sanitize the URI by whitelisting specific schemes and ports. A vulnerable wallet could be tricked into, for example, modifying data on a locally-hosted redis database.

### Validation

Wallets should warn users if the symbol or name matches or is similar to another token, to avoid phishing scams.

### Fingerprinting

To avoid fingerprinting based on wallet behavior and/or listed assets, the RPC call must return as soon as the user is prompted or an error occurs, without waiting for the user to accept or deny the prompt.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 13 Aug 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-747</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-747</guid>
      </item>
    
      <item>
        <title>Subscriptions and filters for completed transactions</title>
        <category>Standards Track/Interface</category>
        
        <description>## Simple Summary
Provide a way for external callers to be notified of completed transactions, and access the return data of functions executed when a transaction is mined.

## Abstract
When a new transaction is submitted successfully to an Ethereum node, the node responds with the transaction&apos;s hash.  If the transaction involved the execution of a contract function that returns data, the data is discarded.  If the return data is state-dependent, which is common, there is no straightforward way for the caller to access or compute the return data.  This EIP proposes that callers should be able to subscribe to (or poll for) completed transactions.  The Ethereum node sends the return data to the caller when the transactions are sealed.

## Motivation
External callers presently have no way of accessing return data from Ethereum, if the function was executed via `eth_sendTransaction` or `eth_sendRawTransaction` RPC request.  Access to function return data is in many cases a desirable feature.  Making return data available to external callers also addresses the inconsistency between internal callers, which have access to return data within the context of the transaction, and external callers, which do not.  Presently, a common workaround is to log the return data, which is bad for several reasons: it contributes to chain bloat, imposes additional gas costs on the caller, and can result in unused logs being written if the externally called function involves other (internal) function calls that log their return data.  While implementing the original version of this EIP, it was decided to expand this functionality slightly to allow for external callers to be notified of their completed transactions even in the case where there is *no* return data.  This could be either because the method called doesn&apos;t return a value, or because the transaction is a simple transfer of value.

## Specification

### Subscription
A caller who wants to be notified when transactions of theirs complete sends an `eth_subscribe` RPC request with the first parameter `&quot;completedTransaction&quot;`:

```json
{&quot;jsonrpc&quot;: &quot;2.0&quot;, &quot;id&quot;: 1, &quot;method&quot;: &quot;eth_subscribe&quot;, &quot;params&quot;: [&quot;completedTransaction&quot;, filter]}
```

The `filter` parameter is a dictionary containing 3 optional named arguments:  `from`, `to`, and `hasReturnData`.  `from` and `to` can each either be single addresses, or a list of addresses.  They are used to filter out any transactions not sent from an address in the `from` list and sent to an address in the to list.  `hasReturnData` is a boolean--if it is specified and `true`, then notifications will be received only for completed transactions containing returnData.

For example, to restrict results to contract creations originating from either of two addresses (0x3f7d39bDBf1f5cE649c194571aEd3D2BbB2F85ce or 0x7097f41F1C1847D52407C629d0E0ae0fDD24fd58):

```json
filter = { &quot;from&quot; : [&quot;0x3f7d39bDBf1f5cE649c194571aEd3D2BbB2F85ce&quot;,
                      &quot;0x7097f41F1C1847D52407C629d0E0ae0fDD24fd58&quot;],
           &quot;to&quot; : &quot;0x0&quot; 
         }
```

To restrict results to method calls on contract address 0xD9Cb531aB97A652c8fC60dcF6D263fcA2F5764e9:
```json
filter = { &quot;to&quot; : &quot;0xD9Cb531aB97A652c8fC60dcF6D263fcA2F5764e9&quot;, &quot;hasReturnData&quot; : true }
```
Or to be notified of any transactions submitted by this rpc client when they complete, with no further restrictions:
```json
filter = {}
```

After the request is received, the Ethereum node responds with a subscription ID:

```json
{&quot;jsonrpc&quot;: &quot;2.0&quot;, &quot;id&quot;: 1, &quot;result&quot;: &quot;0x00000000000000000000000000000b0b&quot;}
```

Suppose the caller then submits a transaction via `eth_sendTransaction` or `eth_sendRawTransaction` RPC request which has the transaction hash `&quot;0x00000000000000000000000000000000000000000000000000000000deadbeef&quot;`.  When the transaction is sealed (mined), the Ethereum node pushes a notification to the caller.  If the transaction is a method call on a contract, this will include the return value (eg. `&quot;0x000000000000000000000000000000000000000000000000000000000000002a&quot;`) of the called function:

```json
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;method&quot;: &quot;eth_subscription&quot;,
  &quot;params&quot;: {
    &quot;result&quot;: {
      &quot;transactionHash&quot;: &quot;0x00000000000000000000000000000000000000000000000000000000deadbeef&quot;,
      &quot;returnData&quot;: &quot;0x000000000000000000000000000000000000000000000000000000000000002a&quot;
    },
    &quot;subscription&quot;: &quot;0x00000000000000000000000000000b0b&quot;
  }
}
```

The caller receives notifications about their transactions in two cases: first when a transaction is sealed, and again (with an extra `&quot;removed&quot;: true` field) if a transaction is affected by a chain reorganization.  Notifications are sent to the client for all transactions submitted from the client that are sealed _after_ subscribing.  If `from`, `to`, or `hasReturnData` is specified, then only those matching the filter criteria will generate notifications.  As with other subscriptions, the caller can send an `eth_unsubscribe` RPC request to stop receiving push notifications:

```json
{&quot;jsonrpc&quot;: &quot;2.0&quot;, &quot;id&quot;: 2, &quot;method&quot;: &quot;eth_unsubscribe&quot;, &quot;params&quot;: [&quot;0x00000000000000000000000000000b0b&quot;]}
```

### Polling
Push notifications require full duplex connections (i.e., websocket or IPC).  Instead of subscribing, callers using HTTP send an `eth_newCompletedTransactionFilter` request:

```json
{&quot;jsonrpc&quot;: &quot;2.0&quot;, &quot;id&quot;: 1, &quot;method&quot;: &quot;eth_newCompletedTransactionFilter&quot;, &quot;params&quot;: [filter] }
```

The Ethereum node responds with a filter ID:

```json
{&quot;jsonrpc&quot;: &quot;2.0&quot;, &quot;id&quot;: 1, &quot;result&quot;: &quot;0x1&quot;}
```

When a transaction is submitted, the Ethereum node pushes the transaction notification, including return value, into a queue which is emptied when the caller polls using `eth_getFilterChanges`:

```json
{&quot;jsonrpc&quot;: &quot;2.0&quot;, &quot;id&quot;: 2, &quot;method&quot;: &quot;eth_getFilterChanges&quot;, &quot;params&quot;: [&quot;0x1&quot;]}
```

The node responds with an array of transaction hashes and their corresponding return data, in the order they were computed:

```json
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 2,
  &quot;result&quot;: [{
    &quot;transactionHash&quot;: &quot;0x00000000000000000000000000000000000000000000000000000000deadbeef&quot;,
    &quot;returnData&quot;: &quot;0x000000000000000000000000000000000000000000000000000000000000002a&quot;
  }]
}
```

All transactions that were sealed _after_ the initial `eth_newCompletedTransactionFilter` request are included in this array.  Again, if the `filter` param is a non-empty dictionary (contains either `from`, `to`, or `hasReturnData`) then only transactions matching the filter criteria generate notifications.  Note that in the polling case, there is no way for the Ethereum node to be sure that an RPC client which submits a transaction was the same as the one who created the filter, so there is no restriction based on where the transaction was submitted.


## Rationale
[EIP-658](/EIPs/EIPS/eip-658) originally proposed adding return data to transaction receipts.  However, return data is not charged for (as it is not stored on the blockchain), so adding it to transaction receipts could result in DoS and spam opportunities.  Instead, a simple Boolean `status` field was added to transaction receipts.  This modified version of EIP 658 was included in the Byzantium hard fork.  While the `status` field is useful, applications often need the return data as well.

The primary advantage of using the strategy outlined here is efficiency: no extra data needs to be stored on the blockchain, and minimal extra computational load is imposed on nodes.  Although after-the-fact lookups of the return value would not be supported, this is consistent with the conventional use of return data, which are only accessible to the caller when the function returns, and are not stored for later use.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 09 Nov 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-758</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-758</guid>
      </item>
    
      <item>
        <title>Token Standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/777</comments>
        
        <description>## Simple Summary

This EIP defines standard interfaces and behaviors for token contracts.

## Abstract

This standard defines a new way to interact with a token contract while remaining backward compatible with [ERC-20].

It defines advanced features to interact with tokens.
Namely, *operators* to send tokens on behalf of another address&amp;mdash;contract or regular account&amp;mdash;and
send/receive *hooks* to offer token holders more control over their tokens.

It takes advantage of [ERC-1820] to find out whether and where to notify contracts and regular addresses
when they receive tokens as well as to allow compatibility with already-deployed contracts.

## Motivation

This standard tries to improve upon the widely used [ERC-20] token standard.
The main advantages of this standard are:

1. Uses the same philosophy as Ether in that tokens are sent with `send(dest, value, data)`.

2. Both contracts and regular addresses can control and reject which token they send
   by registering a `tokensToSend` hook.
   (Rejection is done by `revert`ing in the hook function.)

3. Both contracts and regular addresses can control and reject which token they receive
   by registering a `tokensReceived` hook.
   (Rejection is done by `revert`ing in the hook function.)

4. The `tokensReceived` hook allows to send tokens to a contract and notify it in a single transaction,
   unlike [ERC-20] which requires a double call (`approve`/`transferFrom`) to achieve this.

5. The holder can &quot;authorize&quot; and &quot;revoke&quot; operators which can send tokens on their behalf.
   These operators are intended to be verified contracts
   such as an exchange, a cheque processor or an automatic charging system.

6. Every token transaction contains `data` and `operatorData` bytes fields
   to be used freely to pass data from the holder and the operator, respectively.

7. It is backward compatible with wallets that do not contain the `tokensReceived` hook function
   by deploying a proxy contract implementing the `tokensReceived` hook for the wallet.

## Specification

### ERC777Token (Token Contract)

``` solidity
interface ERC777Token {
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function totalSupply() external view returns (uint256);
    function balanceOf(address holder) external view returns (uint256);
    function granularity() external view returns (uint256);

    function defaultOperators() external view returns (address[] memory);
    function isOperatorFor(
        address operator,
        address holder
    ) external view returns (bool);
    function authorizeOperator(address operator) external;
    function revokeOperator(address operator) external;

    function send(address to, uint256 amount, bytes calldata data) external;
    function operatorSend(
        address from,
        address to,
        uint256 amount,
        bytes calldata data,
        bytes calldata operatorData
    ) external;

    function burn(uint256 amount, bytes calldata data) external;
    function operatorBurn(
        address from,
        uint256 amount,
        bytes calldata data,
        bytes calldata operatorData
    ) external;

    event Sent(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256 amount,
        bytes data,
        bytes operatorData
    );
    event Minted(
        address indexed operator,
        address indexed to,
        uint256 amount,
        bytes data,
        bytes operatorData
    );
    event Burned(
        address indexed operator,
        address indexed from,
        uint256 amount,
        bytes data,
        bytes operatorData
    );
    event AuthorizedOperator(
        address indexed operator,
        address indexed holder
    );
    event RevokedOperator(address indexed operator, address indexed holder);
}
```

The token contract MUST implement the above interface.
The implementation MUST follow the specifications described below.

The token contract MUST register the `ERC777Token` interface with its own address via [ERC-1820].

&gt; This is done by calling the `setInterfaceImplementer` function on the [ERC-1820] registry
&gt; with the token contract address as both the address and the implementer
&gt; and the `keccak256` hash of `ERC777Token` (`0xac7fbab5f54a3ca8194167523c6753bfeb96a445279294b6125b68cce2177054`)
&gt; as the interface hash.

If the contract has a switch to enable or disable ERC-777 functions, every time the switch is triggered,
the token MUST register or unregister the `ERC777Token` interface for its own address accordingly via ERC1820.
Unregistering implies calling the `setInterfaceImplementer` with the token contract address as the address,
the `keccak256` hash of `ERC777Token` as the interface hash and `0x0` as the implementer.
(See [Set An Interface For An Address][erc1820-set] in [ERC-1820] for more details.)

When interacting with the token contract, all amounts and balances MUST be unsigned integers.
I.e. internally, all values are stored as a denomination of 1E-18 of a token.
The display denomination&amp;mdash;to display any amount to the end user&amp;mdash;MUST
be 10&lt;sup&gt;18&lt;/sup&gt; of the internal denomination.

In other words, the internal denomination is similar to a wei
and the display denomination is similar to an ether.
It is equivalent to an [ERC-20]&apos;s `decimals` function returning `18`.
E.g. if a token contract returns a balance of `500,000,000,000,000,000` (0.5&amp;times;10&lt;sup&gt;18&lt;/sup&gt;) for a user,
the user interface MUST show `0.5` tokens to the user.
If the user wishes to send `0.3` tokens,
the contract MUST be called with an amount of `300,000,000,000,000,000` (0.3&amp;times;10&lt;sup&gt;18&lt;/sup&gt;).

User Interfaces which are generated programmatically from the ABI of the token contract
MAY use and display the internal denomination.
But this MUST be made clear, for example by displaying the `uint256` type.

#### **View Functions**

The `view` functions detailed below MUST be implemented.

**`name` function**

``` solidity
function name() external view returns (string memory)
```

Get the name of the token, e.g., `&quot;MyToken&quot;`.

&gt; &lt;small&gt;**identifier:** `06fdde03`&lt;/small&gt;  
&gt; &lt;small&gt;**returns:** Name of the token.&lt;/small&gt;

**`symbol` function**

``` solidity
function symbol() external view returns (string memory)
```

Get the symbol of the token, e.g., `&quot;MYT&quot;`.

&gt; &lt;small&gt;**identifier:** `95d89b41`&lt;/small&gt;  
&gt; &lt;small&gt;**returns:** Symbol of the token.&lt;/small&gt;

**`totalSupply` function**

``` solidity
function totalSupply() external view returns (uint256)
```

Get the total number of minted tokens.

*NOTE*: The total supply MUST be equal to the sum of the balances of all addresses&amp;mdash;as
returned by the `balanceOf` function.

*NOTE*: The total supply MUST be equal to the sum of all the minted tokens
as defined in all the `Minted` events minus the sum of all the burned tokens as defined in all the `Burned` events.

&gt; &lt;small&gt;**identifier:** `18160ddd`&lt;/small&gt;  
&gt; &lt;small&gt;**returns:** Total supply of tokens currently in circulation.&lt;/small&gt;

**`balanceOf` function**

``` solidity
function balanceOf(address holder) external view returns (uint256)
```

Get the balance of the account with address `holder`.

The balance MUST be zero (`0`) or higher.

&gt; &lt;small&gt;**identifier:** `70a08231`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`holder`: Address for which the balance is returned.&lt;/small&gt;
&gt;
&gt; &lt;small&gt;**returns:** Amount of tokens held by `holder` in the token contract.&lt;/small&gt;

**`granularity` function**

``` solidity
function granularity() external view returns (uint256)
```

Get the smallest part of the token that&apos;s not divisible.

In other words, the granularity is the smallest amount of tokens (in the internal denomination)
which MAY be minted, sent or burned at any time.

The following rules MUST be applied regarding the *granularity*:

- The *granularity* value MUST be set at creation time.

- The *granularity* value MUST NOT be changed, ever.

- The *granularity* value MUST be greater than or equal to `1`.

- All balances MUST be a multiple of the granularity.

- Any amount of tokens (in the internal denomination) minted, sent or burned
  MUST be a multiple of the *granularity* value.

- Any operation that would result in a balance that&apos;s not a multiple of the *granularity* value
  MUST be considered invalid, and the transaction MUST `revert`.

*NOTE*: Most tokens SHOULD be fully partition-able.
I.e., this function SHOULD return `1` unless there is a good reason for not allowing any fraction of the token.

&gt; &lt;small&gt;**identifier:** `556f0dc7`&lt;/small&gt;  
&gt; &lt;small&gt;**returns:** The smallest non-divisible part of the token.&lt;/small&gt;

*NOTE*: [`defaultOperators`][defaultOperators] and [`isOperatorFor`][isOperatorFor] are also `view` functions,
defined under the [operators] for consistency.

*[ERC-20] compatibility requirement*:  
The decimals of the token MUST always be `18`.
For a *pure* ERC-777 token the [ERC-20] `decimals` function is OPTIONAL,
and its existence SHALL NOT be relied upon when interacting with the token contract.
(The decimal value of `18` is implied.)
For an [ERC-20] compatible token, the `decimals` function is REQUIRED and MUST return `18`.
(In [ERC-20], the `decimals` function is OPTIONAL.
If the function is not present, the `decimals` value is not clearly defined and may be assumed to be `0`.
Hence for compatibility reasons, `decimals` MUST be implemented for [ERC-20] compatible tokens.)

#### **Operators**

An `operator` is an address which is allowed to send and burn tokens on behalf of some *holder*.

When an address becomes an *operator* for a *holder*, an `AuthorizedOperator` event MUST be emitted.
The `AuthorizedOperator`&apos;s `operator` (topic 1) and `holder` (topic 2)
MUST be the addresses of the *operator* and the *holder* respectively.

When a *holder* revokes an *operator*, a `RevokedOperator` event MUST be emitted.
The `RevokedOperator`&apos;s `operator` (topic 1) and `holder` (topic 2)
MUST be the addresses of the *operator* and the *holder* respectively.

*NOTE*: A *holder* MAY have multiple *operators* at the same time.

The token MAY define *default operators*.
A *default operator* is an implicitly authorized *operator* for all *holders*.
`AuthorizedOperator` events MUST NOT be emitted when defining the *default operators*.
The rules below apply to *default operators*:

- The token contract MUST define *default operators* at creation time.

- The *default operators* MUST be invariants. I.e., the token contract MUST NOT add or remove *default operators* ever.

- `AuthorizedOperator` events MUST NOT be emitted when defining *default operators*.

- A *holder* MUST be allowed to revoke a *default operator*
  (unless the *holder* is the *default operator* in question).

- A *holder* MUST be allowed to re-authorize a previously revoked *default operator*.

- When a *default operator* is explicitly authorized or revoked for a specific *holder*,
  an `AuthorizedOperator` or `RevokedOperator` event (respectively) MUST be emitted.

The following rules apply to any *operator*:

- An address MUST always be an *operator* for itself. Hence an address MUST NOT ever be revoked as its own *operator*.

- If an address is an *operator* for a *holder*, `isOperatorFor` MUST return `true`.

- If an address is not an *operator* for a *holder*, `isOperatorFor` MUST return `false`.

- The token contract MUST emit an `AuthorizedOperator` event with the correct values
  when a *holder* authorizes an address as its *operator* as defined in the
  [`AuthorizedOperator` Event][authorizedoperator].

- The token contract MUST emit a `RevokedOperator` event with the correct values
  when a *holder* revokes an address as its *operator* as defined in the
  [`RevokedOperator` Event][revokedoperator].

*NOTE*: A *holder* MAY authorize an already authorized *operator*.
An `AuthorizedOperator` MUST be emitted each time.

*NOTE*: A *holder* MAY revoke an already revoked *operator*.
A `RevokedOperator` MUST be emitted each time.

**`AuthorizedOperator` event** &lt;a id=&quot;authorizedoperator&quot;&gt;&lt;/a&gt;

``` solidity
event AuthorizedOperator(address indexed operator, address indexed holder)
```

Indicates the authorization of `operator` as an *operator* for `holder`.

*NOTE*: This event MUST NOT be emitted outside of an *operator* authorization process.

&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`operator`: Address which became an *operator* of `holder`.&lt;/small&gt;  
&gt; &lt;small&gt;`holder`: Address of a *holder* which authorized the `operator` address as an *operator*.&lt;/small&gt;

**`RevokedOperator` event** &lt;a id=&quot;revokedoperator&quot;&gt;&lt;/a&gt;

``` solidity
event RevokedOperator(address indexed operator, address indexed holder)
```

Indicates the revocation of `operator` as an *operator* for `holder`.

*NOTE*: This event MUST NOT be emitted outside of an *operator* revocation process.

&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`operator`: Address which was revoked as an *operator* of `holder`.&lt;/small&gt;  
&gt; &lt;small&gt;`holder`: Address of a *holder* which revoked the `operator` address as an *operator*.&lt;/small&gt;

The `defaultOperators`, `authorizeOperator`, `revokeOperator` and `isOperatorFor` functions described below
MUST be implemented to manage *operators*.
Token contracts MAY implement other functions to manage *operators*.

**`defaultOperators` function** &lt;a id=&quot;defaultOperators&quot;&gt;&lt;/a&gt;

``` solidity
function defaultOperators() external view returns (address[] memory)
```

Get the list of *default operators* as defined by the token contract.

*NOTE*: If the token contract does not have any *default operators*, this function MUST return an empty list.

&gt; &lt;small&gt;**identifier:** `06e48538`&lt;/small&gt;  
&gt; &lt;small&gt;**returns:** List of addresses of all the *default operators*.&lt;/small&gt;

**`authorizeOperator` function**

``` solidity
function authorizeOperator(address operator) external
```

Set a third party `operator` address as an *operator* of `msg.sender` to send and burn tokens on its behalf.

*NOTE*: The *holder* (`msg.sender`) is always an *operator* for itself.
This right SHALL NOT be revoked.
Hence this function MUST `revert` if it is called to authorize the holder (`msg.sender`)
as an *operator* for itself (i.e. if `operator` is equal to `msg.sender`).

&gt; &lt;small&gt;**identifier:** `959b8c3f`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`operator`: Address to set as an *operator* for `msg.sender`.&lt;/small&gt;

**`revokeOperator` function**

``` solidity
function revokeOperator(address operator) external
```

Remove the right of the `operator` address to be an *operator* for `msg.sender`
and to send and burn tokens on its behalf.

*NOTE*: The *holder* (`msg.sender`) is always an *operator* for itself.
This right SHALL NOT be revoked.
Hence this function MUST `revert` if it is called to revoke the holder (`msg.sender`)
as an *operator* for itself (i.e., if `operator` is equal to `msg.sender`).

&gt; &lt;small&gt;**identifier:** `fad8b32a`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`operator`: Address to rescind as an *operator* for `msg.sender`.&lt;/small&gt;

**`isOperatorFor` function** &lt;a id=&quot;isOperatorFor&quot;&gt;&lt;/a&gt;

``` solidity
function isOperatorFor(
    address operator,
    address holder
) external view returns (bool)
```

Indicate whether the `operator` address is an *operator* of the `holder` address.

&gt; &lt;small&gt;**identifier:** `d95b6371`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`operator`: Address which may be an *operator* of `holder`.&lt;/small&gt;  
&gt; &lt;small&gt;`holder`: Address of a *holder* which may have the `operator` address as an *operator*.&lt;/small&gt;
&gt;
&gt; &lt;small&gt;**returns:** `true` if `operator` is an *operator* of `holder` and `false` otherwise.&lt;/small&gt;

*NOTE*: To know which addresses are *operators* for a given *holder*,
one MUST call `isOperatorFor` with the *holder* for each *default operator*
and parse the `AuthorizedOperator`, and `RevokedOperator` events for the *holder* in question.

#### **Sending Tokens**

When an *operator* sends an `amount` of tokens from a *holder* to a *recipient*
with the associated `data` and `operatorData`, the token contract MUST apply the following rules:

- Any authorized *operator* MAY send tokens to any *recipient* (except to `0x0`).

- The balance of the *holder* MUST be decreased by the `amount`.

- The balance of the *recipient* MUST be increased by the `amount`.

- The balance of the *holder* MUST be greater or equal to the `amount`&amp;mdash;such
  that its resulting balance is greater or equal to zero (`0`) after the send.

- The token contract MUST emit a `Sent` event with the correct values as defined in the [`Sent` Event][sent].

- The *operator* MAY include information in the `operatorData`.

- The token contract MUST call the `tokensToSend` hook of the *holder*
  if the *holder* registers an `ERC777TokensSender` implementation via [ERC-1820].

- The token contract MUST call the `tokensReceived` hook of the *recipient*
  if the *recipient* registers an `ERC777TokensRecipient` implementation via [ERC-1820].

- The `data` and `operatorData` MUST be immutable during the entire send process&amp;mdash;hence
  the same `data` and `operatorData` MUST be used to call both hooks and emit the `Sent` event.

The token contract MUST `revert` when sending in any of the following cases:

- The *operator* address is not an authorized operator for the *holder*.

- The resulting *holder* balance or *recipient* balance after the send
  is not a multiple of the *granularity* defined by the token contract.

- The *recipient* is a contract, and it does not implement the `ERC777TokensRecipient` interface via [ERC-1820].

- The address of the *holder* or the *recipient* is `0x0`.

- Any of the resulting balances becomes negative, i.e. becomes less than zero (`0`).

- The `tokensToSend` hook of the *holder* `revert`s.

- The `tokensReceived` hook of the *recipient* `revert`s.

The token contract MAY send tokens from many *holders*, to many *recipients*, or both. In this case:

- The previous send rules MUST apply to all the *holders* and all the *recipients*.
- The sum of all the balances incremented MUST be equal to the total sent `amount`.
- The sum of all the balances decremented MUST be equal to the total sent `amount`.
- A `Sent` event MUST be emitted for every *holder* and *recipient* pair with the corresponding amount for each pair.
- The sum of all the amounts from the `Sent` event MUST be equal to the total sent `amount`.

*NOTE*: Mechanisms such as applying a fee on a send is considered as a send to multiple *recipients*:
the intended *recipient* and the fee *recipient*.

*NOTE*: Movements of tokens MAY be chained.
For example, if a contract upon receiving tokens sends them further to another address.
In this case, the previous send rules apply to each send, in order.

*NOTE*: Sending an amount of zero (`0`) tokens is valid and MUST be treated as a regular send.

*Implementation Requirement*:  
- The token contract MUST call the `tokensToSend` hook *before* updating the state.
- The token contract MUST call the `tokensReceived` hook *after* updating the state.  
I.e., `tokensToSend` MUST be called first,
then the balances MUST be updated to reflect the send,
and finally `tokensReceived` MUST be called *afterward*.
Thus a `balanceOf` call within `tokensToSend` returns the balance of the address *before* the send
and a `balanceOf` call within `tokensReceived` returns the balance of the address *after* the send.

*NOTE*: The `data` field contains information provided by the *holder*&amp;mdash;similar
to the data field in a regular ether send transaction.
The `tokensToSend()` hook, the `tokensReceived()`, or both
MAY use the information to decide if they wish to reject the transaction.

*NOTE*: The `operatorData` field is analogous to the `data` field except it SHALL be provided by the *operator*.

The `operatorData` MUST only be provided by the *operator*.
It is intended more for logging purposes and particular cases.
(Examples include payment references, cheque numbers, countersignatures and more.)
In most of the cases the recipient would ignore the `operatorData`, or at most, it would log the `operatorData`.

**`Sent` event** &lt;a id=&quot;sent&quot;&gt;&lt;/a&gt;

``` solidity
event Sent(
    address indexed operator,
    address indexed from,
    address indexed to,
    uint256 amount,
    bytes data,
    bytes operatorData
)
```

Indicate a send of `amount` of tokens from the `from` address to the `to` address by the `operator` address.

*NOTE*: This event MUST NOT be emitted outside of a send or an [ERC-20] transfer process.

&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`operator`: Address which triggered the send.&lt;/small&gt;  
&gt; &lt;small&gt;`from`: *Holder* whose tokens were sent.&lt;/small&gt;  
&gt; &lt;small&gt;`to`: Recipient of the tokens.&lt;/small&gt;  
&gt; &lt;small&gt;`amount`: Number of tokens sent.&lt;/small&gt;  
&gt; &lt;small&gt;`data`: Information provided by the *holder*.&lt;/small&gt;  
&gt; &lt;small&gt;`operatorData`: Information provided by the *operator*.&lt;/small&gt;

The `send` and `operatorSend` functions described below MUST be implemented to send tokens.
Token contracts MAY implement other functions to send tokens.

**`send` function**

``` solidity
function send(address to, uint256 amount, bytes calldata data) external
```

Send the `amount` of tokens from the address `msg.sender` to the address `to`.

The *operator* and the *holder* MUST both be the `msg.sender`.

&gt; &lt;small&gt;**identifier:** `9bd9bbc6`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`to`: Recipient of the tokens.&lt;/small&gt;  
&gt; &lt;small&gt;`amount`: Number of tokens to send.&lt;/small&gt;  
&gt; &lt;small&gt;`data`: Information provided by the *holder*.&lt;/small&gt;

**`operatorSend` function**

``` solidity
function operatorSend(
    address from,
    address to,
    uint256 amount,
    bytes calldata data,
    bytes calldata operatorData
) external
```

Send the `amount` of tokens on behalf of the address `from` to the address `to`.

*Reminder*: If the *operator* address is not an authorized operator of the `from` address,
then the send process MUST `revert`.

*NOTE*: `from` and `msg.sender` MAY be the same address.
I.e., an address MAY call `operatorSend` for itself.
This call MUST be equivalent to `send` with the addition
that the *operator* MAY specify an explicit value for `operatorData`
(which cannot be done with the `send` function).

&gt; &lt;small&gt;**identifier:** `62ad1b83`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`from`: *Holder* whose tokens are being sent.&lt;/small&gt;  
&gt; &lt;small&gt;`to`: Recipient of the tokens.&lt;/small&gt;  
&gt; &lt;small&gt;`amount`: Number of tokens to send.&lt;/small&gt;  
&gt; &lt;small&gt;`data`: Information provided by the *holder*.&lt;/small&gt;  
&gt; &lt;small&gt;`operatorData`: Information provided by the *operator*.&lt;/small&gt;

#### **Minting Tokens**

Minting tokens is the act of producing new tokens.
[ERC-777] intentionally does not define specific functions to mint tokens.
This intent comes from the wish not to limit the use of the [ERC-777] standard
as the minting process is generally specific for every token.

Nonetheless, the rules below MUST be respected when minting for a *recipient*:

- Tokens MAY be minted for any *recipient* address (except `0x0`).

- The total supply MUST be increased by the amount of tokens minted.

- The balance of `0x0` MUST NOT be decreased.

- The balance of the *recipient* MUST be increased by the amount of tokens minted.

- The token contract MUST emit a `Minted` event with the correct values as defined in the [`Minted` Event][minted].

- The token contract MUST call the `tokensReceived` hook of the *recipient*
  if the *recipient* registers an `ERC777TokensRecipient` implementation via [ERC-1820].

- The `data` and `operatorData` MUST be immutable during the entire mint process&amp;mdash;hence
  the same `data` and `operatorData` MUST be used to call the `tokensReceived` hook and emit the `Minted` event.

The token contract MUST `revert` when minting in any of the following cases:

- The resulting *recipient* balance after the mint is not a multiple of the *granularity* defined by the token contract.
- The *recipient* is a contract, and it does not implement the `ERC777TokensRecipient` interface via [ERC-1820].
- The address of the *recipient* is `0x0`.
- The `tokensReceived` hook of the *recipient* `revert`s.

*NOTE*: The initial token supply at the creation of the token contract MUST be considered as minting
for the amount of the initial supply to the address(es) receiving the initial supply.
This means one or more `Minted` events must be emitted
and the `tokensReceived` hook of the recipient(s) MUST be called.

*[ERC-20] compatibility requirement*:  
While a `Sent` event MUST NOT be emitted when minting,
if the token contract is [ERC-20] backward compatible,
a `Transfer` event with the `from` parameter set to `0x0` SHOULD be emitted as defined in the [ERC-20] standard.

The token contract MAY mint tokens for multiple *recipients* at once. In this case:

- The previous mint rules MUST apply to all the *recipients*.
- The sum of all the balances incremented MUST be equal to the total minted amount.
- A `Minted` event MUST be emitted for every *recipient* with the corresponding amount for each *recipient*.
- The sum of all the amounts from the `Minted` event MUST be equal to the total minted `amount`.

*NOTE*: Minting an amount of zero (`0`) tokens is valid and MUST be treated as a regular mint.

*NOTE*: While during a send or a burn, the data is provided by the *holder*, it is inapplicable for a mint.
In this case the data MAY be provided by the token contract or the *operator*,
for example to ensure a successful minting to a *holder* expecting specific data.

*NOTE*: The `operatorData` field contains information provided by the *operator*&amp;mdash;similar
to the data field in a regular ether send transaction.
The `tokensReceived()` hooks MAY use the information to decide if it wish to reject the transaction.

**`Minted` event** &lt;a id=&quot;minted&quot;&gt;&lt;/a&gt;

``` solidity
event Minted(
    address indexed operator,
    address indexed to,
    uint256 amount,
    bytes data,
    bytes operatorData
)
```

Indicate the minting of `amount` of tokens to the `to` address by the `operator` address.

*NOTE*: This event MUST NOT be emitted outside of a mint process.

&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`operator`: Address which triggered the mint.&lt;/small&gt;  
&gt; &lt;small&gt;`to`: Recipient of the tokens.&lt;/small&gt;  
&gt; &lt;small&gt;`amount`: Number of tokens minted.&lt;/small&gt;  
&gt; &lt;small&gt;`data`: Information provided for the *recipient*.&lt;/small&gt;  
&gt; &lt;small&gt;`operatorData`: Information provided by the *operator*.&lt;/small&gt;

#### **Burning Tokens**

Burning tokens is the act of destroying existing tokens.
[ERC-777] explicitly defines two functions to burn tokens (`burn` and `operatorBurn`).
These functions facilitate the integration of the burning process in wallets and dapps.
However, the token contract MAY prevent some or all *holders* from burning tokens for any reason.
The token contract MAY also define other functions to burn tokens.

The rules below MUST be respected when burning the tokens of a *holder*:

- Tokens MAY be burned from any *holder* address (except `0x0`).

- The total supply MUST be decreased by the amount of tokens burned.

- The balance of `0x0` MUST NOT be increased.

- The balance of the *holder* MUST be decreased by amount of tokens burned.

- The token contract MUST emit a `Burned` event with the correct values as defined in the [`Burned` Event][burned].

- The token contract MUST call the `tokensToSend` hook of the *holder*
  if the *holder* registers an `ERC777TokensSender` implementation via [ERC-1820].

- The `operatorData` MUST be immutable during the entire burn process&amp;mdash;hence
  the same `operatorData` MUST be used to call the `tokensToSend` hook and emit the `Burned` event.

The token contract MUST `revert` when burning in any of the following cases:

- The *operator* address is not an authorized operator for the *holder*.

- The resulting *holder* balance after the burn is not a multiple of the *granularity*
  defined by the token contract.

- The balance of *holder* is inferior to the amount of tokens to burn
  (i.e., resulting in a negative balance for the *holder*).

- The address of the *holder* is `0x0`.

- The `tokensToSend` hook of the *holder* `revert`s.

*[ERC-20] compatibility requirement*:  
While a `Sent` event MUST NOT be emitted when burning;
if the token contract is [ERC-20] enabled, a `Transfer` event with the `to` parameter set to `0x0` SHOULD be emitted.
The [ERC-20] standard does not define the concept of burning tokens, but this is a commonly accepted practice.

The token contract MAY burn tokens for multiple *holders* at once. In this case:

- The previous burn rules MUST apply to each *holders*.
- The sum of all the balances decremented MUST be equal to the total burned amount.
- A `Burned` event MUST be emitted for every *holder* with the corresponding amount for each *holder*.
- The sum of all the amounts from the `Burned` event MUST be equal to the total burned `amount`.

*NOTE*: Burning an amount of zero (`0`) tokens is valid and MUST be treated as a regular burn.

*NOTE*: The `data` field contains information provided by the holder&amp;mdash;similar
to the data field in a regular ether send transaction.
The `tokensToSend()` hook, the `tokensReceived()`, or both
MAY use the information to decide if they wish to reject the transaction.

*NOTE*: The `operatorData` field is analogous to the `data` field except it SHALL be provided by the *operator*.

**`Burned` event** &lt;a id=&quot;burned&quot;&gt;&lt;/a&gt;

``` solidity
event Burned(
    address indexed operator,
    address indexed from,
    uint256 amount,
    bytes data,
    bytes operatorData
);
```

Indicate the burning of `amount` of tokens from the `from` address by the `operator` address.

*NOTE*: This event MUST NOT be emitted outside of a burn process.

&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`operator`: Address which triggered the burn.&lt;/small&gt;  
&gt; &lt;small&gt;`from`: *Holder* whose tokens were burned.&lt;/small&gt;  
&gt; &lt;small&gt;`amount`: Number of tokens burned.&lt;/small&gt;  
&gt; &lt;small&gt;`data`: Information provided by the *holder*.&lt;/small&gt;  
&gt; &lt;small&gt;`operatorData`: Information provided by the *operator*.&lt;/small&gt;

The `burn` and `operatorBurn` functions described below MUST be implemented to burn tokens.
Token contracts MAY implement other functions to burn tokens.

**`burn` function**

``` solidity
function burn(uint256 amount, bytes calldata data) external
```

Burn the `amount` of tokens from the address `msg.sender`.

The *operator* and the *holder* MUST both be the `msg.sender`.

&gt; &lt;small&gt;**identifier:** `fe9d9303`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`amount`: Number of tokens to burn.&lt;/small&gt;  
&gt; &lt;small&gt;`data`: Information provided by the *holder*.&lt;/small&gt;

**`operatorBurn` function**

``` solidity
function operatorBurn(
    address from,
    uint256 amount,
    bytes calldata data,
    bytes calldata operatorData
) external
```

Burn the `amount` of tokens on behalf of the address `from`.

*Reminder*: If the *operator* address is not an authorized operator of the `from` address,
then the burn process MUST `revert`.

&gt; &lt;small&gt;**identifier:** `fc673c4f`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`from`: *Holder* whose tokens will be burned.&lt;/small&gt;  
&gt; &lt;small&gt;`amount`: Number of tokens to burn.&lt;/small&gt;  
&gt; &lt;small&gt;`data`: Information provided by the *holder*.&lt;/small&gt;  
&gt; &lt;small&gt;`operatorData`: Information provided by the *operator*.&lt;/small&gt;

*NOTE*: The *operator* MAY pass any information via `operatorData`.
The `operatorData` MUST only be provided by the *operator*.

*NOTE*: `from` and `msg.sender` MAY be the same address.
I.e., an address MAY call `operatorBurn` for itself.
This call MUST be equivalent to `burn`
with the addition that the *operator* MAY specify an explicit value for `operatorData`
(which cannot be done with the `burn` function).

#### **`ERC777TokensSender` And The `tokensToSend` Hook**

The `tokensToSend` hook notifies of any request to decrement the balance (send and burn) for a given *holder*.
Any address (regular or contract) wishing to be notified of token debits from their address
MAY register the address of a contract implementing the `ERC777TokensSender` interface described below via [ERC-1820].

&gt; This is done by calling the `setInterfaceImplementer` function on the [ERC-1820] registry
&gt; with the *holder* address as the address,
&gt; the `keccak256` hash of `ERC777TokensSender`
&gt; (`0x29ddb589b1fb5fc7cf394961c1adf5f8c6454761adf795e67fe149f658abe895`) as the interface hash,
&gt; and the address of the contract implementing the `ERC777TokensSender` as the implementer.

``` solidity
interface ERC777TokensSender {
    function tokensToSend(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes calldata userData,
        bytes calldata operatorData
    ) external;
}
```

*NOTE*: A regular address MAY register a different address&amp;mdash;the address of a contract&amp;mdash;implementing
the interface on its behalf.
A contract MAY register either its address or the address of another contract
but said address MUST implement the interface on its behalf.

**`tokensToSend`**

``` solidity
function tokensToSend(
    address operator,
    address from,
    address to,
    uint256 amount,
    bytes calldata userData,
    bytes calldata operatorData
) external
```

Notify a request to send or burn (if `to` is `0x0`) an `amount` tokens from the `from` address to the `to` address
by the `operator` address.

*NOTE*: This function MUST NOT be called outside of a burn, send or [ERC-20] transfer process.

&gt; &lt;small&gt;**identifier:** `75ab9782`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`operator`: Address which triggered the balance decrease (through sending or burning).&lt;/small&gt;  
&gt; &lt;small&gt;`from`: *Holder* whose tokens were sent.&lt;/small&gt;  
&gt; &lt;small&gt;`to`: Recipient of the tokens for a send (or `0x0` for a burn).&lt;/small&gt;  
&gt; &lt;small&gt;`amount`: Number of tokens the *holder* balance is decreased by.&lt;/small&gt;  
&gt; &lt;small&gt;`data`: Information provided by the *holder*.&lt;/small&gt;  
&gt; &lt;small&gt;`operatorData`: Information provided by the *operator*.&lt;/small&gt;

The following rules apply when calling the `tokensToSend` hook:

- The `tokensToSend` hook MUST be called for every send and burn processes.

- The `tokensToSend` hook MUST be called *before* the state is updated&amp;mdash;i.e. *before* the balance is decremented.

- `operator` MUST be the address which triggered the send or burn process.

- `from` MUST be the address of the *holder* whose tokens are sent or burned.

- `to` MUST be the address of the *recipient* which receives the tokens for a send.

- `to` MUST be `0x0` for a burn.

- `amount` MUST be the number of tokens the *holder* sent or burned.

- `data` MUST contain the extra information (if any) provided to the send or the burn process.

- `operatorData` MUST contain the extra information provided by the address
  which triggered the decrease of the balance (if any).

- The *holder* MAY block a send or burn process by `revert`ing.
  (I.e., reject the withdrawal of tokens from its account.)

*NOTE*: Multiple *holders* MAY use the same implementation of `ERC777TokensSender`.

*NOTE*: An address can register at most one implementation at any given time for all [ERC-777] tokens.
Hence the `ERC777TokensSender` MUST expect to be called by different token contracts.
The `msg.sender` of the `tokensToSend` call is expected to be the address of the token contract.

*[ERC-20] compatibility requirement*:  
This hook takes precedence over [ERC-20] and MUST be called (if registered)
when calling [ERC-20]&apos;s `transfer` and `transferFrom` event.
When called from a `transfer`, `operator` MUST be the same value as the `from`.
When called from a `transferFrom`, `operator` MUST be the address which issued the `transferFrom` call.

#### **`ERC777TokensRecipient` And The `tokensReceived` Hook**

The `tokensReceived` hook notifies of any increment of the balance (send and mint) for a given *recipient*.
Any address (regular or contract) wishing to be notified of token credits to their address
MAY register the address of a contract implementing the `ERC777TokensRecipient` interface described below via [ERC-1820].

&gt; This is done by calling the `setInterfaceImplementer` function on the [ERC-1820] registry
&gt; with the *recipient* address as the address,
&gt; the `keccak256` hash of `ERC777TokensRecipient`
&gt; (`0xb281fc8c12954d22544db45de3159a39272895b169a852b314f9cc762e44c53b`) as the interface hash,
&gt; and the address of the contract implementing the `ERC777TokensRecipient` as the implementer.

``` solidity
interface ERC777TokensRecipient {
    function tokensReceived(
        address operator,
        address from,
        address to,
        uint256 amount,
        bytes calldata data,
        bytes calldata operatorData
    ) external;
}
```

If the *recipient* is a contract, which has not registered an `ERC777TokensRecipient` implementation;
then the token contract:

- MUST `revert` if the `tokensReceived` hook is called from a mint or send call.

- SHOULD continue processing the transaction
  if the `tokensReceived` hook is called from an ERC-20 `transfer` or `transferFrom` call.

*NOTE*: A regular address MAY register a different address&amp;mdash;the address of a contract&amp;mdash;implementing
the interface on its behalf.
A contract MUST register either its address or the address of another contract
but said address MUST implement the interface on its behalf.

**`tokensReceived`**

``` solidity
function tokensReceived(
    address operator,
    address from,
    address to,
    uint256 amount,
    bytes calldata data,
    bytes calldata operatorData
) external
```

Notify a send or mint (if `from` is `0x0`) of `amount` tokens from the `from` address to the `to` address
by the `operator` address.

*NOTE*: This function MUST NOT be called outside of a mint, send or [ERC-20] transfer process.

&gt; &lt;small&gt;**identifier:** `0023de29`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`operator`: Address which triggered the balance increase (through sending or minting).&lt;/small&gt;  
&gt; &lt;small&gt;`from`: *Holder* whose tokens were sent (or `0x0` for a mint).&lt;/small&gt;  
&gt; &lt;small&gt;`to`: Recipient of the tokens.&lt;/small&gt;  
&gt; &lt;small&gt;`amount`: Number of tokens the *recipient* balance is increased by.&lt;/small&gt;  
&gt; &lt;small&gt;`data`: Information provided by the *holder*.&lt;/small&gt;  
&gt; &lt;small&gt;`operatorData`: Information provided by the *operator*.&lt;/small&gt;

The following rules apply when calling the `tokensReceived` hook:

- The `tokensReceived` hook MUST be called for every send and mint processes.

- The `tokensReceived` hook MUST be called *after* the state is updated&amp;mdash;i.e. *after* the balance is incremented.

- `operator` MUST be the address which triggered the send or mint process.

- `from` MUST be the address of the *holder* whose tokens are sent for a send.

- `from` MUST be `0x0` for a mint.

- `to` MUST be the address of the *recipient* which receives the tokens.

- `amount` MUST be the number of tokens the *recipient* sent or minted.

- `data` MUST contain the extra information (if any) provided to the send or the mint process.

- `operatorData` MUST contain the extra information provided by the address
  which triggered the increase of the balance (if any).

- The *holder* MAY block a send or mint process by `revert`ing.
  (I.e., reject the reception of tokens.)

*NOTE*: Multiple *holders* MAY use the same implementation of `ERC777TokensRecipient`.

*NOTE*: An address can register at most one implementation at any given time for all [ERC-777] tokens.
Hence the `ERC777TokensRecipient` MUST expect to be called by different token contracts.
The `msg.sender` of the `tokensReceived` call is expected to be the address of the token contract.

*[ERC-20] compatibility requirement*:  
This hook takes precedence over [ERC-20] and MUST be called (if registered)
when calling [ERC-20]&apos;s `transfer` and `transferFrom` event.
When called from a `transfer`, `operator` MUST be the same value as the `from`.
When called from a `transferFrom`, `operator` MUST be the address which issued the `transferFrom` call.

#### **Note On Gas Consumption**

Dapps and wallets SHOULD first estimate the gas required when sending, minting, or burning tokens&amp;mdash;using
[`eth_estimateGas`][eth_estimateGas]&amp;mdash;to avoid running out of gas during the transaction.

### Logo

| **Image** | ![beige logo] | ![white logo] | ![light grey logo] | ![dark grey logo] | ![black logo] |
|----------:|:-------------:|:-------------:|:------------------:|:-----------------:|:-------------:|
| **Color** | beige         | white         | light grey         | dark grey         | black         |
| **Hex**   | `#C99D66`     | `#FFFFFF`     | `#EBEFF0`          | `#3C3C3D`         | `#000000`     |

The logo MAY be used, modified and adapted to promote valid [ERC-777] token implementations
and [ERC-777] compliant technologies such as wallets and dapps.

[ERC-777] token contract authors MAY create a specific logo for their token based on this logo.

The logo MUST NOT be used to advertise, promote or associate in any way technology&amp;mdash;such
as tokens&amp;mdash;which is not [ERC-777] compliant.

The logo for the standard can be found in the [`/assets/eip-777/logo`][logos] folder in `SVG` and `PNG` formats.
The `PNG` version of the logo offers a few sizes in pixels.
If needed, other sizes MAY be created by converting from `SVG` into `PNG`.

## Rationale

The principal intent for this standard is
to solve some of the shortcomings of [ERC-20] while maintaining backward compatibility with [ERC-20],
and avoiding the problems and vulnerabilities of [EIP-223].

Below are the rationales for the decisions regarding the main aspects of the standards.

*NOTE*: Jacques Dafflon ([0xjac]), one of the authors of the standard,
conjointly wrote his [master thesis] on the standard,
which goes in more details than could reasonably fit directly within the standard,
and can provide further clarifications regarding certain aspects or decisions.

### Lifecycle

More than just sending tokens, [ERC-777] defines the entire lifecycle of a token,
starting with the minting process, followed by the sending process and terminating with the burn process.

Having a lifecycle clearly defined is important for consistency and accuracy,
especially when value is derived from scarcity.
In contrast when looking at some [ERC-20] tokens, a discrepancy can be observed
between the value returned by the `totalSupply` and the actual circulating supply,
as the standard does not clearly define a process to create and destroy tokens.

### Data

The mint, send and burn processes can all make use of a `data` and `operatorData` fields
which are passed to any movement (mint, send or burn).
Those fields may be empty for simple use cases,
or they may contain valuable information related to the movement of tokens,
similar to information attached to a bank transfer by the sender or the bank itself.

The use of a `data` field is equally present in other standard proposals such as [EIP-223],
and was requested by multiple members of the community who reviewed this standard.

### Hooks

In most cases, [ERC-20] requires two calls to safely transfer tokens to a contract without locking them.
A call from the sender, using the `approve` function
and a call from the recipient using `transferFrom`.
Furthermore, this requires extra communication between the parties which is not clearly defined.
Finally, holders can get confused between `transfer` and `approve`/`transferFrom`.
Using the former to transfer tokens to a contract will most likely result in locked tokens.

Hooks allow streamlining of the sending process and offer a single way to send tokens to any recipient.
Thanks to the `tokensReceived` hook, contracts are able to react and prevent locking tokens upon reception.

#### **Greater Control For Holders**

The `tokensReceived` hook also allows holders to reject the reception of some tokens.
This gives greater control to holders who can accept or reject incoming tokens based on some parameters,
for example located in the `data` or `operatorData` fields.

Following the same intentions and based on suggestions from the community,
the `tokensToSend` hook was added to give control over and prevent the movement of outgoing tokens.

#### **[ERC-1820] Registry**

The [ERC-1820] Registry allows holders to register their hooks.
Other alternatives were examined beforehand to link hooks and holders.

The first was for hooks to be defined at the sender&apos;s or recipient&apos;s address.
This approach is similar to [EIP-223] which proposes a `tokenFallback` function on recipient contracts
to be called when receiving tokens,
but improves on it by relying on [ERC-165] for interface detection.
While straightforward to implement, this approach imposes several limitations.
In particular, the sender and recipient must be contracts in order to provide their implementation of the hooks.
Preventing externally owned addresses to benefit from hooks.
Existing contracts have a strong probability not to be compatible,
as they undoubtedly were unaware and do not define the new hooks.
Consequently existing smart contract infrastructure such as multisig wallets
which potentially hold large amounts of ether and tokens would need to be migrated to new updated contracts.

The second approach considered was to use [ERC-672] which offered pseudo-introspection for addresses using reverse-ENS.
However, this approach relied heavily on ENS, on top of which reverse lookup would need to be implemented.
Analysis of this approach promptly revealed a certain degree of complexity and security concerns
which would transcend the benefits of approach.

The third solution&amp;mdash;used in this standard&amp;mdash;is to rely on a unique registry
where any address can register the addresses of contracts implementing the hooks on its behalf.
This approach has the advantage that externally owned accounts and contracts can benefit from hooks,
including existing contracts which can rely on hooks deployed on proxy contracts.

The decision was made to keep this registry in a separate EIP,
as to not over complicate this standard.
More importantly, the registry is designed in a flexible fashion,
such that other EIPs and smart contract infrastructures can benefit from it
for their own use cases, outside the realm of [ERC-777] and tokens.
The first proposal for this registry was [ERC-820].
Unfortunately, issues emanating from upgrades in the Solidity language to versions 0.5 and above
resulted in a bug in a separated part of the registry, which required changes.
This was discovered right after the last call period.
Attempts made to avoid creating a separate EIP, such as [ERC-820a], were rejected.
Hence the standard for the registry used for [ERC-777] became [ERC-1820].
[ERC-1820] and [ERC-820] are functionally equivalent. [ERC-1820] simply contains the fix for newer versions of Solidity.

### Operators

The standard defines the concept of operators as any address which moves tokens.
While intuitively every address moves its own tokens,
separating the concepts of holder and operator allows for greater flexibility.
Primarily, this originates from the fact that the standard defines a mechanism for holders
to let other addresses become their operators.
Moreover, unlike the approve calls in [ERC-20] where the role of an approved address is not clearly defined,
[ERC-777] details the intent of and interactions with operators,
including an obligation for operators to be approved,
and an irrevocable right for any holder to revoke operators.

#### **Default Operators**

Default operators were added based on community demand for pre-approved operators.
That is operators which are approved for all holders by default.
For obvious security reasons, the list of default operators is defined at the token contract creation time,
and cannot be changed.
Any holder still has the right to revoke default operators.
One of the obvious advantages of default operators is to allow ether-less movements of tokens.
Default operators offer other usability advantages,
such as allowing token providers to offer functionality in a modular way,
and to reduce the complexity for holders to use features provided through operators.

## Backward Compatibility

This EIP does not introduce backward incompatibilities and is backward compatible with the older [ERC-20] token standard.

This EIP does not use `transfer` and `transferFrom` and uses `send` and `operatorSend`
to avoid confusion and mistakes when deciphering which token standard is being used.

This standard allows the implementation of [ERC-20] functions `transfer`, `transferFrom`, `approve` and `allowance`
alongside to make a token fully compatible with [ERC-20].

The token MAY implement `decimals()` for backward compatibility with [ERC-20].
If implemented, it MUST always return `18`.

Therefore a token contract MAY implement both [ERC-20] and [ERC-777] in parallel.
The specification of the `view` functions (such as `name`, `symbol`, `balanceOf`, `totalSupply`) and internal data
(such as the mapping of balances) overlap without problems.
Note however that the following functions are mandatory in [ERC-777] and MUST be implemented:
`name`, `symbol` `balanceOf` and `totalSupply`
(`decimals` is not part of the [ERC-777] standard).

The state-modifying functions from both standards are decoupled and can operate independently from each other.
Note that [ERC-20] functions SHOULD be limited to only being called from old contracts.

If the token implements [ERC-20],
it MUST register the `ERC20Token` interface with its own address via [ERC-1820].
This is done by calling the `setInterfaceImplementer` function on the ERC-1820 registry
with the token contract address as both the address and the implementer
and the `keccak256` hash of `ERC20Token` (`0xaea199e31a596269b42cdafd93407f14436db6e4cad65417994c2eb37381e05a`)
as the interface hash.

If the contract has a switch to enable or disable ERC-20 functions, every time the switch is triggered,
the token MUST register or unregister the `ERC20Token` interface for its own address accordingly via ERC1820.
Unregistering implies calling the `setInterfaceImplementer` with the token contract address as the address,
the `keccak256` hash of `ERC20Token` as the interface hash and `0x0` as the implementer.
(See [Set An Interface For An Address][erc1820-set] in [ERC-1820] for more details.)

The difference for new contracts implementing [ERC-20] is that
`tokensToSend` and `tokensReceived` hooks take precedence over [ERC-20].
Even with an [ERC-20] `transfer` and `transferFrom` call, the token contract MUST check via [ERC-1820]
if the `from` and the `to` address implement `tokensToSend` and `tokensReceived` hook respectively.
If any hook is implemented, it MUST be called.
Note that when calling [ERC-20] `transfer` on a contract, if the contract does not implement `tokensReceived`,
the `transfer` call SHOULD still be accepted even if this means the tokens will probably be locked.

The table below summarizes the different actions the token contract MUST take
when sending, minting and transferring token via [ERC-777] and [ERC-20]:

&lt;table&gt;
  &lt;tr&gt;
    &lt;th align=&quot;right&quot;&gt;ERC1820&lt;/th&gt;
    &lt;th&gt;&lt;code&gt;to&lt;/code&gt; address&lt;/th&gt;
    &lt;th align=&quot;center&quot;&gt;ERC777 Sending And Minting&lt;/th&gt;
    &lt;th align=&quot;center&quot;&gt;ERC20 &lt;code&gt;transfer&lt;/code&gt;/&lt;code&gt;transferFrom&lt;/code&gt;&lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td rowspan=&quot;2&quot; align=&quot;right&quot;&gt;
      &lt;code&gt;ERC777TokensRecipient&lt;/code&gt;&lt;br/&gt;registered
    &lt;/td&gt;
    &lt;td&gt;regular address&lt;/td&gt;
    &lt;td colspan=&quot;2&quot; rowspan=&quot;2&quot; align=&quot;center&quot;&gt;
      MUST call &lt;code&gt;tokensReceived&lt;/code&gt;
    &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;contract&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td rowspan=&quot;2&quot; align=&quot;right&quot;&gt;
      &lt;code&gt;ERC777TokensRecipient&lt;/code&gt;&lt;br/&gt;not registered
    &lt;/td&gt;
    &lt;td&gt;regular address&lt;/td&gt;
    &lt;td colspan=&quot;2&quot; align=&quot;center&quot;&gt;continue&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;contract&lt;/td&gt;
    &lt;td align=&quot;center&quot;&gt;MUST &lt;code&gt;revert&lt;/code&gt;&lt;/td&gt;
    &lt;td align=&quot;center&quot;&gt;SHOULD continue&lt;sup&gt;&lt;a id=&quot;continue-footnote-backlink&quot; href=&quot;#continue-footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;

&gt; &lt;a href=&quot;#continue-footnote-backlink&quot;&gt;&lt;small id=&quot;continue-footnote&quot;&gt;1.&lt;/small&gt;&lt;/a&gt;
&gt; &lt;small&gt;The transaction SHOULD continue for clarity as ERC20 is not aware of hooks.&lt;/small&gt;  
&gt; &lt;small&gt;However, this can result in accidentally locked tokens.&lt;/small&gt;
&gt; &lt;small&gt;If avoiding accidentally locked tokens is paramount, the transaction MAY &lt;code&gt;revert&lt;/code&gt;.&lt;/small&gt;


There is no particular action to take if `tokensToSend` is not implemented.
The movement MUST proceed and only be canceled if another condition is not respected
such as lack of funds or a `revert` in `tokensReceived` (if present).

During a send, mint and burn, the respective `Sent`, `Minted` and `Burned` events MUST be emitted.
Furthermore, if the token contract declares that it implements `ERC20Token` via [ERC-1820],
the token contract SHOULD emit a `Transfer` event for minting and burning
and MUST emit a `Transfer` event for sending (as specified in the [ERC-20] standard).
During an [ERC-20]&apos;s `transfer` or `transferFrom` functions, a valid `Sent` event MUST be emitted.

Hence for any movement of tokens, two events MAY be emitted:
an [ERC-20] `Transfer` and an [ERC-777] `Sent`, `Minted` or `Burned` (depending on the type of movement).
Third-party developers MUST be careful not to consider both events as separate movements.
As a general rule, if an application considers the token as an ERC20 token,
then only the `Transfer` event MUST be taken into account.
If the application considers the token as an ERC777 token,
then only the `Sent`, `Minted` and `Burned` events MUST be considered.

## Test Cases

The [repository with the reference implementation][0xjac/ERC777] contains all the [tests][ref tests].

## Implementation

The GitHub repository [0xjac/ERC777] contains the [reference implementation].
The reference implementation is also available via [npm][npm/erc777] and can be installed with `npm install erc777`.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[operators]: #operators

[ERC-20]: /EIPs/EIPS/eip-20

[ERC-165]: /EIPs/EIPS/eip-165
[ERC-672]: https://github.com/ethereum/EIPs/issues/672

[ERC-777]: /EIPs/EIPS/eip-777

[ERC-820]: /EIPs/EIPS/eip-820
[ERC-820a]: https://github.com/ethereum/EIPs/pull/1758

[ERC-1820]: /EIPs/EIPS/eip-1820

[erc1820-set]: /EIPs/EIPS/eip-1820#set-an-interface-for-an-address
[0xjac]: https://github.com/0xjac
[0xjac/ERC777]: https://github.com/0xjac/ERC777
[master thesis]: https://github.com/0xjac/master-thesis
[npm/erc777]: https://www.npmjs.com/package/erc777
[ref tests]: https://github.com/0xjac/ERC777/blob/master/test/ReferenceToken.test.js
[reference implementation]: https://github.com/0xjac/ERC777/blob/master/contracts/examples/ReferenceToken.sol
[EIP-223]: https://github.com/ethereum/EIPs/issues/223
[eth_estimateGas]: https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_estimategas

[authorizedoperator]: #authorizedoperator
[revokedoperator]: #revokedoperator
[isOperatorFor]: #isOperatorFor
[defaultOperators]: #defaultOperators
[sent]: #sent
[minted]: #minted
[burned]: #burned

[logos]: https://github.com/ethereum/EIPs/tree/master/assets/eip-777/logo

[beige logo]: /EIPs/assets/eip-777/logo/png/ERC-777-logo-beige-48px.png

[white logo]: /EIPs/assets/eip-777/logo/png/ERC-777-logo-white-48px.png

[light grey logo]: /EIPs/assets/eip-777/logo/png/ERC-777-logo-light_grey-48px.png

[dark grey logo]: /EIPs/assets/eip-777/logo/png/ERC-777-logo-dark_grey-48px.png

[black logo]: /EIPs/assets/eip-777/logo/png/ERC-777-logo-black-48px.png
</description>
        <pubDate>Mon, 20 Nov 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-777</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-777</guid>
      </item>
    
      <item>
        <title>Ethereum Node Records (ENR)</title>
        <category>Standards Track/Networking</category>
        
          <comments>https://github.com/ethereum/devp2p/issues/43</comments>
        
        <description># Abstract

This EIP defines Ethereum Node Records, an open format for p2p connectivity information.

# Motivation

Ethereum nodes discover each other through the node discovery protocol. The purpose of
that protocol is relaying node identity public keys (on the secp256k1 curve), their IP
address and two port numbers. No other information can be relayed.

This specification seeks to lift the restrictions of the discovery v4 protocol by defining
a flexible format, the *node record*, for connectivity-related information. Node records
can be relayed through a future version of the node discovery protocol. They can also be
relayed through arbitrary other mechanisms such as DNS, ENS, a devp2p subprotocol, etc.

Node records improve cryptographic agility and handling of protocol upgrades. A record can
contain information about arbitrary transport protocols and public key material associated
with them.

Another goal of the new format is to provide authoritative updates of connectivity
information. If a node changes its endpoint and publishes a new record, other nodes should
be able to determine which record is newer.

# Specification

The components of a node record are:

- `signature`: cryptographic signature of record contents
- `seq`: The sequence number, a 64-bit unsigned integer. Nodes should increase the number
   whenever the record changes and republish the record.
-  The remainder of the record consists of arbitrary key/value pairs

A record&apos;s signature is made and validated according to an *identity scheme*. The identity
scheme is also responsible for deriving a node&apos;s address in the DHT.

The key/value pairs must be sorted by key and must be unique, i.e. any key may be present
only once. The keys can technically be any byte sequence, but ASCII text is preferred. Key
names in the table below have pre-defined meaning.

| Key         | Value                                      |
|:------------|:-------------------------------------------|
| `id`        | name of identity scheme, e.g. &quot;v4&quot;         |
| `secp256k1` | compressed secp256k1 public key, 33 bytes  |
| `ip`        | IPv4 address, 4 bytes                      |
| `tcp`       | TCP port, big endian integer               |
| `udp`       | UDP port, big endian integer               |
| `ip6`       | IPv6 address, 16 bytes                     |
| `tcp6`      | IPv6-specific TCP port, big endian integer |
| `udp6`      | IPv6-specific UDP port, big endian integer |

All keys except `id` are optional, including IP addresses and ports. A record without
endpoint information is still valid as long as its signature is valid. If no `tcp6` /
`udp6` port is provided, the `tcp` / `udp` port applies to both IP addresses. Declaring
the same port number in both `tcp`, `tcp6` or `udp`, `udp6` should be avoided but doesn&apos;t
render the record invalid.

### RLP Encoding

The canonical encoding of a node record is an RLP list of `[signature, seq, k, v, ...]`.
The maximum encoded size of a node record is 300 bytes. Implementations should reject
records larger than this size.

Records are signed and encoded as follows:

    content   = [seq, k, v, ...]
    signature = sign(content)
    record    = [signature, seq, k, v, ...]

### Text Encoding

The textual form of a node record is the base64 encoding of its RLP representation,
prefixed by `enr:`. Implementations should use the [URL-safe base64 alphabet][base64url]
and omit padding characters.

### &quot;v4&quot; Identity Scheme

This specification defines a single identity scheme to be used as the default until other
schemes are defined by further EIPs. The &quot;v4&quot; scheme is backwards-compatible with the
cryptosystem used by Node Discovery v4.

- To sign record `content` with this scheme, apply the keccak256 hash function (as used by
  the EVM) to `content`, then create a signature of the hash. The resulting 64-byte
  signature is encoded as the concatenation of the `r` and `s` signature values (the
  recovery ID `v` is omitted).
- To verify a record, check that the signature was made by the public key in the
  &quot;secp256k1&quot; key/value pair of the record.
- To derive a node address, take the keccak256 hash of the uncompressed public key.

# Rationale

The format is meant to suit future needs in two ways:

- Adding new key/value pairs: This is always possible and doesn&apos;t require implementation
  consensus. Existing clients will accept any key/value pairs regardless of whether they
  can interpret their content.
- Adding identity schemes: these need implementation consensus because the network won&apos;t
  accept the signature otherwise. To introduce a new identity scheme, propose an EIP and
  get it implemented. The scheme can be used as soon as most clients accept it.

The size of a record is limited because records are relayed frequently and may be included
in size-constrained protocols such as DNS. A record containing a IPv4 address, when signed
using the &quot;v4&quot; scheme occupies roughly 120 bytes, leaving plenty of room for additional
metadata.

You might wonder about the need for so many pre-defined keys related to IP addresses and
ports. This need arises because residential and mobile network setups often put IPv4
behind NAT while IPv6 traffic—if supported—is directly routed to the same host. Declaring
both address types ensures a node is reachable from IPv4-only locations and those
supporting both protocols.

# Test Vectors

This is an example record containing the IPv4 address `127.0.0.1` and UDP port `30303`.
The node ID is `a448f24c6d18e575453db13171562b71999873db5b286df957af199ec94617f7`.

```text
enr:-IS4QHCYrYZbAKWCBRlAy5zzaDZXJBGkcnh4MHcBFZntXNFrdvJjX04jRzjzCBOonrkTfj499SZuOh8R33Ls8RRcy5wBgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQPKY0yuDUmstAHYpMa2_oxVtw0RW_QAdpzBQA8yWM0xOIN1ZHCCdl8
```

The record is signed using the &quot;v4&quot; identity scheme using sequence number `1` and this
private key:

```text
b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291
```

The RLP structure of the record is:

```text
[
  7098ad865b00a582051940cb9cf36836572411a47278783077011599ed5cd16b76f2635f4e234738f30813a89eb9137e3e3df5266e3a1f11df72ecf1145ccb9c,
  01,
  &quot;id&quot;,
  &quot;v4&quot;,
  &quot;ip&quot;,
  7f000001,
  &quot;secp256k1&quot;,
  03ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd3138,
  &quot;udp&quot;,
  765f,
]
```

# Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[base64url]: https://tools.ietf.org/html/rfc4648#section-5
</description>
        <pubDate>Thu, 23 Nov 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-778</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-778</guid>
      </item>
    
      <item>
        <title>Hardfork Meta: DAO Fork</title>
        <category>Meta/</category>
        
        <description>## Abstract

This documents the changes included in the hard fork named &quot;DAO Fork&quot;. Unlike other hard forks, the DAO Fork did not change the protocol; all EVM opcodes, transaction format, block structure, and so on remained the same. Rather, the DAO Fork was an &quot;irregular state change&quot; that transferred ether balances from a list of accounts (&quot;child DAO&quot; contracts) into a specified account (the &quot;WithdrawDAO&quot; contract).

## Specification

- Codename: DAO Fork
- Activation:
  - Block == 1,920,000 on Mainnet

See references [1] and [2] for the original, full specification. It is summarized here for convenience.

At block 1880000, the following accounts are encoded into a list `L`:
* The DAO (`0xbb9bc244d798123fde783fcc1c72d3bb8c189413`)
* its extraBalance (`0x807640a13483f8ac783c557fcdf27be11ea4ac7a`)
* all children of the DAO creator (`0x4a574510c7014e4ae985403536074abe582adfc8`)
* and the extraBalance of each child

&lt;details&gt;
&lt;summary&gt;Reference list L&lt;/summary&gt;

```
0xd4fe7bc31cedb7bfb8a345f31e668033056b2728,
0xb3fb0e5aba0e20e5c49d252dfd30e102b171a425,
0x2c19c7f9ae8b751e37aeb2d93a699722395ae18f,
0xecd135fa4f61a655311e86238c92adcd779555d2,
0x1975bd06d486162d5dc297798dfc41edd5d160a7,
0xa3acf3a1e16b1d7c315e23510fdd7847b48234f6,
0x319f70bab6845585f412ec7724b744fec6095c85,
0x06706dd3f2c9abf0a21ddcc6941d9b86f0596936,
0x5c8536898fbb74fc7445814902fd08422eac56d0,
0x6966ab0d485353095148a2155858910e0965b6f9,
0x779543a0491a837ca36ce8c635d6154e3c4911a6,
0x2a5ed960395e2a49b1c758cef4aa15213cfd874c,
0x5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5,
0x9c50426be05db97f5d64fc54bf89eff947f0a321,
0x200450f06520bdd6c527622a273333384d870efb,
0xbe8539bfe837b67d1282b2b1d61c3f723966f049,
0x6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb,
0xf1385fb24aad0cd7432824085e42aff90886fef5,
0xd1ac8b1ef1b69ff51d1d401a476e7e612414f091,
0x8163e7fb499e90f8544ea62bbf80d21cd26d9efd,
0x51e0ddd9998364a2eb38588679f0d2c42653e4a6,
0x627a0a960c079c21c34f7612d5d230e01b4ad4c7,
0xf0b1aa0eb660754448a7937c022e30aa692fe0c5,
0x24c4d950dfd4dd1902bbed3508144a54542bba94,
0x9f27daea7aca0aa0446220b98d028715e3bc803d,
0xa5dc5acd6a7968a4554d89d65e59b7fd3bff0f90,
0xd9aef3a1e38a39c16b31d1ace71bca8ef58d315b,
0x63ed5a272de2f6d968408b4acb9024f4cc208ebf,
0x6f6704e5a10332af6672e50b3d9754dc460dfa4d,
0x77ca7b50b6cd7e2f3fa008e24ab793fd56cb15f6,
0x492ea3bb0f3315521c31f273e565b868fc090f17,
0x0ff30d6de14a8224aa97b78aea5388d1c51c1f00,
0x9ea779f907f0b315b364b0cfc39a0fde5b02a416,
0xceaeb481747ca6c540a000c1f3641f8cef161fa7,
0xcc34673c6c40e791051898567a1222daf90be287,
0x579a80d909f346fbfb1189493f521d7f48d52238,
0xe308bd1ac5fda103967359b2712dd89deffb7973,
0x4cb31628079fb14e4bc3cd5e30c2f7489b00960c,
0xac1ecab32727358dba8962a0f3b261731aad9723,
0x4fd6ace747f06ece9c49699c7cabc62d02211f75,
0x440c59b325d2997a134c2c7c60a8c61611212bad,
0x4486a3d68fac6967006d7a517b889fd3f98c102b,
0x9c15b54878ba618f494b38f0ae7443db6af648ba,
0x27b137a85656544b1ccb5a0f2e561a5703c6a68f,
0x21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241,
0x23b75c2f6791eef49c69684db4c6c1f93bf49a50,
0x1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b,
0xb9637156d330c0d605a791f1c31ba5890582fe1c,
0x6131c42fa982e56929107413a9d526fd99405560,
0x1591fc0f688c81fbeb17f5426a162a7024d430c2,
0x542a9515200d14b68e934e9830d91645a980dd7a,
0xc4bbd073882dd2add2424cf47d35213405b01324,
0x782495b7b3355efb2833d56ecb34dc22ad7dfcc4,
0x58b95c9a9d5d26825e70a82b6adb139d3fd829eb,
0x3ba4d81db016dc2890c81f3acec2454bff5aada5,
0xb52042c8ca3f8aa246fa79c3feaa3d959347c0ab,
0xe4ae1efdfc53b73893af49113d8694a057b9c0d1,
0x3c02a7bc0391e86d91b7d144e61c2c01a25a79c5,
0x0737a6b837f97f46ebade41b9bc3e1c509c85c53,
0x97f43a37f595ab5dd318fb46e7a155eae057317a,
0x52c5317c848ba20c7504cb2c8052abd1fde29d03,
0x4863226780fe7c0356454236d3b1c8792785748d,
0x5d2b2e6fcbe3b11d26b525e085ff818dae332479,
0x5f9f3392e9f62f63b8eac0beb55541fc8627f42c,
0x057b56736d32b86616a10f619859c6cd6f59092a,
0x9aa008f65de0b923a2a4f02012ad034a5e2e2192,
0x304a554a310c7e546dfe434669c62820b7d83490,
0x914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79,
0x4deb0033bb26bc534b197e61d19e0733e5679784,
0x07f5c1e1bc2c93e0402f23341973a0e043f7bf8a,
0x35a051a0010aba705c9008d7a7eff6fb88f6ea7b,
0x4fa802324e929786dbda3b8820dc7834e9134a2a,
0x9da397b9e80755301a3b32173283a91c0ef6c87e,
0x8d9edb3054ce5c5774a420ac37ebae0ac02343c6,
0x0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9,
0x5dc28b15dffed94048d73806ce4b7a4612a1d48f,
0xbcf899e6c7d9d5a215ab1e3444c86806fa854c76,
0x12e626b0eebfe86a56d633b9864e389b45dcb260,
0xa2f1ccba9395d7fcb155bba8bc92db9bafaeade7,
0xec8e57756626fdc07c63ad2eafbd28d08e7b0ca5,
0xd164b088bd9108b60d0ca3751da4bceb207b0782,
0x6231b6d0d5e77fe001c2a460bd9584fee60d409b,
0x1cba23d343a983e9b5cfd19496b9a9701ada385f,
0xa82f360a8d3455c5c41366975bde739c37bfeb8a,
0x9fcd2deaff372a39cc679d5c5e4de7bafb0b1339,
0x005f5cee7a43331d5a3d3eec71305925a62f34b6,
0x0e0da70933f4c7849fc0d203f5d1d43b9ae4532d,
0xd131637d5275fd1a68a3200f4ad25c71a2a9522e,
0xbc07118b9ac290e4622f5e77a0853539789effbe,
0x47e7aa56d6bdf3f36be34619660de61275420af8,
0xacd87e28b0c9d1254e868b81cba4cc20d9a32225,
0xadf80daec7ba8dcf15392f1ac611fff65d94f880,
0x5524c55fb03cf21f549444ccbecb664d0acad706,
0x40b803a9abce16f50f36a77ba41180eb90023925,
0xfe24cdd8648121a43a7c86d289be4dd2951ed49f,
0x17802f43a0137c506ba92291391a8a8f207f487d,
0x253488078a4edf4d6f42f113d1e62836a942cf1a,
0x86af3e9626fce1957c82e88cbf04ddf3a2ed7915,
0xb136707642a4ea12fb4bae820f03d2562ebff487,
0xdbe9b615a3ae8709af8b93336ce9b477e4ac0940,
0xf14c14075d6c4ed84b86798af0956deef67365b5,
0xca544e5c4687d109611d0f8f928b53a25af72448,
0xaeeb8ff27288bdabc0fa5ebb731b6f409507516c,
0xcbb9d3703e651b0d496cdefb8b92c25aeb2171f7,
0x6d87578288b6cb5549d5076a207456a1f6a63dc0,
0xb2c6f0dfbb716ac562e2d85d6cb2f8d5ee87603e,
0xaccc230e8a6e5be9160b8cdf2864dd2a001c28b6,
0x2b3455ec7fedf16e646268bf88846bd7a2319bb2,
0x4613f3bca5c44ea06337a9e439fbc6d42e501d0a,
0xd343b217de44030afaa275f54d31a9317c7f441e,
0x84ef4b2357079cd7a7c69fd7a37cd0609a679106,
0xda2fef9e4a3230988ff17df2165440f37e8b1708,
0xf4c64518ea10f995918a454158c6b61407ea345c,
0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97,
0xbb9bc244d798123fde783fcc1c72d3bb8c189413,
0x807640a13483f8ac783c557fcdf27be11ea4ac7a
```
&lt;/details&gt;

At the beginning of block 1920000, all ether throughout all accounts in `L` will be transferred to a contract deployed at `0xbf4ed7b27f1d666546e30d74d50d173d20bca754`. The contract was created from the following Solidity code (compiler version `v0.3.5-2016-07-01-48238c9`):

```solidity
// Deployed on mainnet at 0xbf4ed7b27f1d666546e30d74d50d173d20bca754

contract DAO {
    function balanceOf(address addr) returns (uint);
    function transferFrom(address from, address to, uint balance) returns (bool);
    uint public totalSupply;
}

contract WithdrawDAO {
    DAO constant public mainDAO = DAO(0xbb9bc244d798123fde783fcc1c72d3bb8c189413);
    address public trustee = 0xda4a4626d3e16e094de3225a751aab7128e96526;

    function withdraw(){
        uint balance = mainDAO.balanceOf(msg.sender);

        if (!mainDAO.transferFrom(msg.sender, this, balance) || !msg.sender.send(balance))
            throw;
    }

    function trusteeWithdraw() {
        trustee.send((this.balance + mainDAO.balanceOf(this)) - mainDAO.totalSupply());
    }
}
```

This contract is deployed on Mainnet in block 1883496 in transaction hash `0xfeae1ff3cf9b6927d607744e3883ea105fb16042d4639857d9cfce3eba644286`. The deployment code of the contract is:

```
0x606060405273da4a4626d3e16e094de3225a751aab7128e96526600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff02191690830217905550610462806100516000396000f360606040526000357c0100000000000000000000000000000000000000000000000000000000900480632e6e504a1461005a5780633ccfd60b14610069578063eedcf50a14610078578063fdf97cb2146100b157610058565b005b61006760048050506100ea565b005b6100766004805050610277565b005b6100856004805050610424565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100be600480505061043c565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073bb9bc244d798123fde783fcc1c72d3bb8c18941373ffffffffffffffffffffffffffffffffffffffff166318160ddd604051817c01000000000000000000000000000000000000000000000000000000000281526004018090506020604051808303816000876161da5a03f115610002575050506040518051906020015073bb9bc244d798123fde783fcc1c72d3bb8c18941373ffffffffffffffffffffffffffffffffffffffff166370a0823130604051827c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1681526020019150506020604051808303816000876161da5a03f11561000257505050604051805190602001503073ffffffffffffffffffffffffffffffffffffffff16310103604051809050600060405180830381858888f19350505050505b565b600073bb9bc244d798123fde783fcc1c72d3bb8c18941373ffffffffffffffffffffffffffffffffffffffff166370a0823133604051827c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1681526020019150506020604051808303816000876161da5a03f1156100025750505060405180519060200150905073bb9bc244d798123fde783fcc1c72d3bb8c18941373ffffffffffffffffffffffffffffffffffffffff166323b872dd333084604051847c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200193505050506020604051808303816000876161da5a03f1156100025750505060405180519060200150158061041657503373ffffffffffffffffffffffffffffffffffffffff16600082604051809050600060405180830381858888f19350505050155b1561042057610002565b5b50565b73bb9bc244d798123fde783fcc1c72d3bb8c18941381565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168156
```

This deployment results in the runtime bytecode: 

```
0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900480632e6e504a1461005a5780633ccfd60b14610069578063eedcf50a14610078578063fdf97cb2146100b157610058565b005b61006760048050506100ea565b005b6100766004805050610277565b005b6100856004805050610424565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100be600480505061043c565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073bb9bc244d798123fde783fcc1c72d3bb8c18941373ffffffffffffffffffffffffffffffffffffffff166318160ddd604051817c01000000000000000000000000000000000000000000000000000000000281526004018090506020604051808303816000876161da5a03f115610002575050506040518051906020015073bb9bc244d798123fde783fcc1c72d3bb8c18941373ffffffffffffffffffffffffffffffffffffffff166370a0823130604051827c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1681526020019150506020604051808303816000876161da5a03f11561000257505050604051805190602001503073ffffffffffffffffffffffffffffffffffffffff16310103604051809050600060405180830381858888f19350505050505b565b600073bb9bc244d798123fde783fcc1c72d3bb8c18941373ffffffffffffffffffffffffffffffffffffffff166370a0823133604051827c0100000000000000000000000000000000000000000000000000000000028152600401808273ffffffffffffffffffffffffffffffffffffffff1681526020019150506020604051808303816000876161da5a03f1156100025750505060405180519060200150905073bb9bc244d798123fde783fcc1c72d3bb8c18941373ffffffffffffffffffffffffffffffffffffffff166323b872dd333084604051847c0100000000000000000000000000000000000000000000000000000000028152600401808473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200193505050506020604051808303816000876161da5a03f1156100025750505060405180519060200150158061041657503373ffffffffffffffffffffffffffffffffffffffff16600082604051809050600060405180830381858888f19350505050155b1561042057610002565b5b50565b73bb9bc244d798123fde783fcc1c72d3bb8c18941381565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168156
```

Blocks with block numbers in the range [1_920_000, 1_920_009] **MUST** have `0x64616f2d686172642d666f726b` (hex encoded ASCII string `dao-hard-fork`) in the `extraData` field of the block.

## References

1. https://blog.slock.it/hard-fork-specification-24b889e70703
2. https://blog.ethereum.org/2016/07/15/to-fork-or-not-to-fork/

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 26 Nov 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-779</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-779</guid>
      </item>
    
      <item>
        <title>Canary Standard</title>
        <category>Standards Track/ERC</category>
        
        <description>## Simple Summary

A standard interface for canary contracts.

## Abstract

The following standard allows the implementation of canaries within contracts.
This standard provides basic functionality to check if a canary is alive, keeping the canary alive and optionally manage feeders.

## Motivation

The canary can e.g. be used as a [warrant canary](https://en.wikipedia.org/wiki/Warrant_canary).
A standard interface allows other applications to easily interface with canaries on Ethereum - e.g. for visualizing the state, automated alarms, applications to feed the canary or contracts (e.g. insurance) that use the state.

## Specification

### Methods

#### isAlive()

Returns if the canary was fed properly to signal e.g. that no warrant was received.

``` js
function isAlive() constant returns (bool alive)
```

#### getBlockOfDeath()

Returns the block the canary died.
Throws if the canary is alive.

``` js
function getBlockOfDeath() constant returns (uint256 block)
```

#### getType()

Returns the type of the canary:

* `1` = Simple (just the pure interface as defined in this ERC)
* `2` = Single feeder (as defined in ERC-TBD)
* `3` = Single feeder with bad food (as defined in ERC-TBD)
* `4` = Multiple feeders (as defined in ERC-TBD)
* `5` = Multiple mandatory feeders (as defined in ERC-TBD)
* `6` = IOT (as defined in ERC-TBD)

`1` might also be used for a special purpose contract that does not need a special type but still wants to expose the functions and provide events as defined in this ERC.

``` js
function getType() constant returns (uint8 type)
```

### Events

#### RIP

MUST trigger when the contract is called the first time after the canary died.

``` js
event RIP()
```

## Implementation

TODO

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 16 Dec 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-801</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-801</guid>
      </item>
    
      <item>
        <title>Pseudo-introspection Registry Contract</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/820</comments>
        
        <description>&gt; :information_source: **[ERC-1820] has superseded [ERC-820].** :information_source:  
&gt; [ERC-1820] fixes the incompatibility in the [ERC-165] logic which was introduced by the Solidty 0.5 update.  
&gt; Have a look at the [official announcement][erc1820-annoucement], and the comments about the [bug][erc820-bug] and the [fix][erc820-fix].  
&gt; Apart from this fix, [ERC-1820] is functionally equivalent to [ERC-820].
&gt;
&gt; :warning: [ERC-1820] MUST be used in lieu of [ERC-820]. :warning:


## Simple Summary

This standard defines a universal registry smart contract where any address (contract or regular account) can register which interface it supports and which smart contract is responsible for its implementation.

This standard keeps backward compatibility with [ERC-165].

## Abstract

This standard defines a registry where smart contracts and regular accounts can publish which functionalities they implement---either directly or through a proxy contract.

Anyone can query this registry to ask if a specific address implements a given interface and which smart contract handles its implementation.

This registry MAY be deployed on any chain and shares the same address on all chains.

Interfaces with zeroes (`0`) as the last 28 bytes are considered [ERC-165] interfaces, and this registry SHALL forward the call to the contract to see if it implements the interface.

This contract also acts as an [ERC-165] cache to reduce gas consumption.

## Motivation

There have been different approaches to define pseudo-introspection in Ethereum. The first is [ERC-165] which has the limitation that it cannot be used by regular accounts. The second attempt is [ERC-672] which uses reverse [ENS]. Using reverse [ENS] has two issues. First, it is unnecessarily complicated, and second, [ENS] is still a centralized contract controlled by a multisig. This multisig theoretically would be able to modify the system.

This standard is much simpler than [ERC-672], and it is *fully* decentralized.

This standard also provides a *unique* address for all chains. Thus solving the problem of resolving the correct registry address for different chains.

## Specification

### [ERC-820] Registry Smart Contract

&gt; This is an exact copy of the code of the [ERC820 registry smart contract].

``` solidity
/* ERC820 Pseudo-introspection Registry Contract
 * This standard defines a universal registry smart contract where any address
 * (contract or regular account) can register which interface it supports and
 * which smart contract is responsible for its implementation.
 *
 * Written in 2018 by Jordi Baylina and Jacques Dafflon
 *
 * To the extent possible under law, the author(s) have dedicated all copyright
 * and related and neighboring rights to this software to the public domain
 * worldwide. This software is distributed without any warranty.
 *
 * You should have received a copy of the CC0 Public Domain Dedication along
 * with this software. If not, see
 * &lt;https://creativecommons.org/publicdomain/zero/1.0/&gt;.
 *
 *    ███████╗██████╗  ██████╗ █████╗ ██████╗  ██████╗
 *    ██╔════╝██╔══██╗██╔════╝██╔══██╗╚════██╗██╔═████╗
 *    █████╗  ██████╔╝██║     ╚█████╔╝ █████╔╝██║██╔██║
 *    ██╔══╝  ██╔══██╗██║     ██╔══██╗██╔═══╝ ████╔╝██║
 *    ███████╗██║  ██║╚██████╗╚█████╔╝███████╗╚██████╔╝
 *    ╚══════╝╚═╝  ╚═╝ ╚═════╝ ╚════╝ ╚══════╝ ╚═════╝
 *
 *    ██████╗ ███████╗ ██████╗ ██╗███████╗████████╗██████╗ ██╗   ██╗
 *    ██╔══██╗██╔════╝██╔════╝ ██║██╔════╝╚══██╔══╝██╔══██╗╚██╗ ██╔╝
 *    ██████╔╝█████╗  ██║  ███╗██║███████╗   ██║   ██████╔╝ ╚████╔╝
 *    ██╔══██╗██╔══╝  ██║   ██║██║╚════██║   ██║   ██╔══██╗  ╚██╔╝
 *    ██║  ██║███████╗╚██████╔╝██║███████║   ██║   ██║  ██║   ██║
 *    ╚═╝  ╚═╝╚══════╝ ╚═════╝ ╚═╝╚══════╝   ╚═╝   ╚═╝  ╚═╝   ╚═╝
 *
 */
pragma solidity 0.4.24;
// IV is value needed to have a vanity address starting with `0x820`.
// IV: 9513

/// @dev The interface a contract MUST implement if it is the implementer of
/// some (other) interface for any address other than itself.
interface ERC820ImplementerInterface {
    /// @notice Indicates whether the contract implements the interface `interfaceHash` for the address `addr` or not.
    /// @param interfaceHash keccak256 hash of the name of the interface
    /// @param addr Address for which the contract will implement the interface
    /// @return ERC820_ACCEPT_MAGIC only if the contract implements `interfaceHash` for the address `addr`.
    function canImplementInterfaceForAddress(bytes32 interfaceHash, address addr) external view returns(bytes32);
}


/// @title ERC820 Pseudo-introspection Registry Contract
/// @author Jordi Baylina and Jacques Dafflon
/// @notice This contract is the official implementation of the ERC820 Registry.
/// @notice For more details, see https://eips.ethereum.org/EIPS/eip-820
contract ERC820Registry {
    /// @notice ERC165 Invalid ID.
    bytes4 constant INVALID_ID = 0xffffffff;
    /// @notice Method ID for the ERC165 supportsInterface method (= `bytes4(keccak256(&apos;supportsInterface(bytes4)&apos;))`).
    bytes4 constant ERC165ID = 0x01ffc9a7;
    /// @notice Magic value which is returned if a contract implements an interface on behalf of some other address.
    bytes32 constant ERC820_ACCEPT_MAGIC = keccak256(abi.encodePacked(&quot;ERC820_ACCEPT_MAGIC&quot;));

    mapping (address =&gt; mapping(bytes32 =&gt; address)) interfaces;
    mapping (address =&gt; address) managers;
    mapping (address =&gt; mapping(bytes4 =&gt; bool)) erc165Cached;

    /// @notice Indicates a contract is the `implementer` of `interfaceHash` for `addr`.
    event InterfaceImplementerSet(address indexed addr, bytes32 indexed interfaceHash, address indexed implementer);
    /// @notice Indicates `newManager` is the address of the new manager for `addr`.
    event ManagerChanged(address indexed addr, address indexed newManager);

    /// @notice Query if an address implements an interface and through which contract.
    /// @param _addr Address being queried for the implementer of an interface.
    /// (If `_addr == 0` then `msg.sender` is assumed.)
    /// @param _interfaceHash keccak256 hash of the name of the interface as a string.
    /// E.g., `web3.utils.keccak256(&apos;ERC777Token&apos;)`.
    /// @return The address of the contract which implements the interface `_interfaceHash` for `_addr`
    /// or `0x0` if `_addr` did not register an implementer for this interface.
    function getInterfaceImplementer(address _addr, bytes32 _interfaceHash) external view returns (address) {
        address addr = _addr == 0 ? msg.sender : _addr;
        if (isERC165Interface(_interfaceHash)) {
            bytes4 erc165InterfaceHash = bytes4(_interfaceHash);
            return implementsERC165Interface(addr, erc165InterfaceHash) ? addr : 0;
        }
        return interfaces[addr][_interfaceHash];
    }

    /// @notice Sets the contract which implements a specific interface for an address.
    /// Only the manager defined for that address can set it.
    /// (Each address is the manager for itself until it sets a new manager.)
    /// @param _addr Address to define the interface for. (If `_addr == 0` then `msg.sender` is assumed.)
    /// @param _interfaceHash keccak256 hash of the name of the interface as a string.
    /// For example, `web3.utils.keccak256(&apos;ERC777TokensRecipient&apos;)` for the `ERC777TokensRecipient` interface.
    /// @param _implementer Contract address implementing _interfaceHash for _addr.
    function setInterfaceImplementer(address _addr, bytes32 _interfaceHash, address _implementer) external {
        address addr = _addr == 0 ? msg.sender : _addr;
        require(getManager(addr) == msg.sender, &quot;Not the manager&quot;);

        require(!isERC165Interface(_interfaceHash), &quot;Must not be a ERC165 hash&quot;);
        if (_implementer != 0 &amp;&amp; _implementer != msg.sender) {
            require(
                ERC820ImplementerInterface(_implementer)
                    .canImplementInterfaceForAddress(_interfaceHash, addr) == ERC820_ACCEPT_MAGIC,
                &quot;Does not implement the interface&quot;
            );
        }
        interfaces[addr][_interfaceHash] = _implementer;
        emit InterfaceImplementerSet(addr, _interfaceHash, _implementer);
    }

    /// @notice Sets the `_newManager` as manager for the `_addr` address.
    /// The new manager will be able to call `setInterfaceImplementer` for `_addr`.
    /// @param _addr Address for which to set the new manager.
    /// @param _newManager Address of the new manager for `addr`.
    function setManager(address _addr, address _newManager) external {
        require(getManager(_addr) == msg.sender, &quot;Not the manager&quot;);
        managers[_addr] = _newManager == _addr ? 0 : _newManager;
        emit ManagerChanged(_addr, _newManager);
    }

    /// @notice Get the manager of an address.
    /// @param _addr Address for which to return the manager.
    /// @return Address of the manager for a given address.
    function getManager(address _addr) public view returns(address) {
        // By default the manager of an address is the same address
        if (managers[_addr] == 0) {
            return _addr;
        } else {
            return managers[_addr];
        }
    }

    /// @notice Compute the keccak256 hash of an interface given its name.
    /// @param _interfaceName Name of the interface.
    /// @return The keccak256 hash of an interface name.
    function interfaceHash(string _interfaceName) external pure returns(bytes32) {
        return keccak256(abi.encodePacked(_interfaceName));
    }

    /* --- ERC165 Related Functions --- */
    /* --- Developed in collaboration with William Entriken. --- */

    /// @notice Updates the cache with whether the contract implements an ERC165 interface or not.
    /// @param _contract Address of the contract for which to update the cache.
    /// @param _interfaceId ERC165 interface for which to update the cache.
    function updateERC165Cache(address _contract, bytes4 _interfaceId) external {
        interfaces[_contract][_interfaceId] = implementsERC165InterfaceNoCache(_contract, _interfaceId) ? _contract : 0;
        erc165Cached[_contract][_interfaceId] = true;
    }

    /// @notice Checks whether a contract implements an ERC165 interface or not.
    /// The result may be cached, if not a direct lookup is performed.
    /// @param _contract Address of the contract to check.
    /// @param _interfaceId ERC165 interface to check.
    /// @return `true` if `_contract` implements `_interfaceId`, false otherwise.
    function implementsERC165Interface(address _contract, bytes4 _interfaceId) public view returns (bool) {
        if (!erc165Cached[_contract][_interfaceId]) {
            return implementsERC165InterfaceNoCache(_contract, _interfaceId);
        }
        return interfaces[_contract][_interfaceId] == _contract;
    }

    /// @notice Checks whether a contract implements an ERC165 interface or not without using nor updating the cache.
    /// @param _contract Address of the contract to check.
    /// @param _interfaceId ERC165 interface to check.
    /// @return `true` if `_contract` implements `_interfaceId`, false otherwise.
    function implementsERC165InterfaceNoCache(address _contract, bytes4 _interfaceId) public view returns (bool) {
        uint256 success;
        uint256 result;

        (success, result) = noThrowCall(_contract, ERC165ID);
        if (success == 0 || result == 0) {
            return false;
        }

        (success, result) = noThrowCall(_contract, INVALID_ID);
        if (success == 0 || result != 0) {
            return false;
        }

        (success, result) = noThrowCall(_contract, _interfaceId);
        if (success == 1 &amp;&amp; result == 1) {
            return true;
        }
        return false;
    }

    /// @notice Checks whether the hash is a ERC165 interface (ending with 28 zeroes) or not.
    /// @param _interfaceHash The hash to check.
    /// @return `true` if the hash is a ERC165 interface (ending with 28 zeroes), `false` otherwise.
    function isERC165Interface(bytes32 _interfaceHash) internal pure returns (bool) {
        return _interfaceHash &amp; 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0;
    }

    /// @dev Make a call on a contract without throwing if the function does not exist.
    function noThrowCall(address _contract, bytes4 _interfaceId)
        internal view returns (uint256 success, uint256 result)
    {
        bytes4 erc165ID = ERC165ID;

        assembly {
                let x := mload(0x40)               // Find empty storage location using &quot;free memory pointer&quot;
                mstore(x, erc165ID)                // Place signature at beginning of empty storage
                mstore(add(x, 0x04), _interfaceId) // Place first argument directly next to signature

                success := staticcall(
                    30000,                         // 30k gas
                    _contract,                     // To addr
                    x,                             // Inputs are stored at location x
                    0x08,                          // Inputs are 8 bytes long
                    x,                             // Store output over input (saves space)
                    0x20                           // Outputs are 32 bytes long
                )

                result := mload(x)                 // Load the result
        }
    }
}

```

### Deployment Transaction

Below is the raw transaction which MUST be used to deploy the smart contract on any chain.

```
0xf90a2a8085174876e800830c35008080b909d7608060405234801561001057600080fd5b506109b7806100206000396000f30060806040526004361061008d5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166329965a1d81146100925780633d584063146100bf5780635df8122f146100fc57806365ba36c114610123578063a41e7d5114610155578063aabbb8ca14610183578063b7056765146101a7578063f712f3e8146101e9575b600080fd5b34801561009e57600080fd5b506100bd600160a060020a036004358116906024359060443516610217565b005b3480156100cb57600080fd5b506100e0600160a060020a0360043516610512565b60408051600160a060020a039092168252519081900360200190f35b34801561010857600080fd5b506100bd600160a060020a036004358116906024351661055e565b34801561012f57600080fd5b506101436004803560248101910135610655565b60408051918252519081900360200190f35b34801561016157600080fd5b506100bd600160a060020a0360043516600160e060020a0319602435166106e3565b34801561018f57600080fd5b506100e0600160a060020a036004351660243561076d565b3480156101b357600080fd5b506101d5600160a060020a0360043516600160e060020a0319602435166107e7565b604080519115158252519081900360200190f35b3480156101f557600080fd5b506101d5600160a060020a0360043516600160e060020a03196024351661089c565b6000600160a060020a0384161561022e5783610230565b335b90503361023c82610512565b600160a060020a03161461029a576040805160e560020a62461bcd02815260206004820152600f60248201527f4e6f7420746865206d616e616765720000000000000000000000000000000000604482015290519081900360640190fd5b6102a38361091c565b156102f8576040805160e560020a62461bcd02815260206004820152601960248201527f4d757374206e6f74206265206120455243313635206861736800000000000000604482015290519081900360640190fd5b600160a060020a038216158015906103195750600160a060020a0382163314155b156104a15760405160200180807f4552433832305f4143434550545f4d414749430000000000000000000000000081525060130190506040516020818303038152906040526040518082805190602001908083835b6020831061038d5780518252601f19909201916020918201910161036e565b51815160209384036101000a6000190180199092169116179052604080519290940182900382207f249cb3fa000000000000000000000000000000000000000000000000000000008352600483018a9052600160a060020a0388811660248501529451909650938816945063249cb3fa936044808401945091929091908290030181600087803b15801561042057600080fd5b505af1158015610434573d6000803e3d6000fd5b505050506040513d602081101561044a57600080fd5b5051146104a1576040805160e560020a62461bcd02815260206004820181905260248201527f446f6573206e6f7420696d706c656d656e742074686520696e74657266616365604482015290519081900360640190fd5b600160a060020a03818116600081815260208181526040808320888452909152808220805473ffffffffffffffffffffffffffffffffffffffff19169487169485179055518692917f93baa6efbd2244243bfee6ce4cfdd1d04fc4c0e9a786abd3a41313bd352db15391a450505050565b600160a060020a03808216600090815260016020526040812054909116151561053c575080610559565b50600160a060020a03808216600090815260016020526040902054165b919050565b3361056883610512565b600160a060020a0316146105c6576040805160e560020a62461bcd02815260206004820152600f60248201527f4e6f7420746865206d616e616765720000000000000000000000000000000000604482015290519081900360640190fd5b81600160a060020a031681600160a060020a0316146105e557806105e8565b60005b600160a060020a03838116600081815260016020526040808220805473ffffffffffffffffffffffffffffffffffffffff19169585169590951790945592519184169290917f605c2dbf762e5f7d60a546d42e7205dcb1b011ebc62a61736a57c9089d3a43509190a35050565b60008282604051602001808383808284378201915050925050506040516020818303038152906040526040518082805190602001908083835b602083106106ad5780518252601f19909201916020918201910161068e565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902090505b92915050565b6106ed82826107e7565b6106f85760006106fa565b815b600160a060020a03928316600081815260208181526040808320600160e060020a031996909616808452958252808320805473ffffffffffffffffffffffffffffffffffffffff19169590971694909417909555908152600284528181209281529190925220805460ff19166001179055565b60008080600160a060020a038516156107865784610788565b335b91506107938461091c565b156107b85750826107a4828261089c565b6107af5760006107b1565b815b92506107df565b600160a060020a038083166000908152602081815260408083208884529091529020541692505b505092915050565b60008080610815857f01ffc9a70000000000000000000000000000000000000000000000000000000061093e565b9092509050811580610825575080155b1561083357600092506107df565b61084585600160e060020a031961093e565b909250905081158061085657508015155b1561086457600092506107df565b61086e858561093e565b90925090506001821480156108835750806001145b1561089157600192506107df565b506000949350505050565b600160a060020a0382166000908152600260209081526040808320600160e060020a03198516845290915281205460ff1615156108e4576108dd83836107e7565b90506106dd565b50600160a060020a03808316600081815260208181526040808320600160e060020a0319871684529091529020549091161492915050565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff161590565b6040517f01ffc9a7000000000000000000000000000000000000000000000000000000008082526004820183905260009182919060208160088189617530fa9051909690955093505050505600a165627a7a723058204fc4461c9d5a247b0eafe0f9c508057bc0ad72bc24668cb2a35ea65850e10d3100291ba08208208208208208208208208208208208208208208208208208208208208200a00820820820820820820820820820820820820820820820820820820820820820
```

The strings of `820`&apos;s at the end of the transaction are the `r` and `s` of the signature. From this deterministic pattern (generated by a human), anyone can deduce that no one knows the private key for the deployment account.

### Deployment Method

This contract is going to be deployed using the keyless deployment method---also known as [Nick]&apos;s method---which relies on a single-use address. (See [Nick&apos;s article] for more details). This method works as follows:

1. Generate a transaction which deploys the contract from a new random account.
  - This transaction MUST NOT use [EIP-155] in order to work on any chain.
  - This transaction MUST have a relatively high gas price to be deployed on any chain. In this case, it is going to be 100 Gwei.

2. Set the `v`, `r`, `s` of the transaction signature to the following values:

   ```
   v: 27
   r: 0x8208208208208208208208208208208208208208208208208208208208208200
   s: 0x0820820820820820820820820820820820820820820820820820820820820820
   ```

   Those `r` and `s` values---made of a repeating pattern of `820`&apos;s---are predictable &quot;random numbers&quot; generated deterministically by a human.

   &gt; The values of `r` and `s` must be 32 bytes long each---or 64 characters in hexadecimal. Since `820` is 3 characters long and 3 is not a divisor of 64, but it is a divisor of 63, the `r` and `s` values are padded with one extra character.  
   &gt; The `s` value is prefixed with a single zero (`0`). The `0` prefix also guarantees that `s &lt; secp256k1n ÷ 2 + 1`.  
   &gt; The `r` value, cannot be prefixed with a zero, as the transaction becomes invalid. Instead it is suffixed with a zero (`0`) which still respects the condition `s &lt; secp256k1n`.

3. We recover the sender of this transaction, i.e., the single-use deployment account.

    &gt; Thus we obtain an account that can broadcast that transaction, but we also have the warranty that nobody knows the private key of that account.

4. Send exactly 0.08 ethers to this single-use deployment account.

5. Broadcast the deployment transaction.

This operation can be done on any chain, guaranteeing that the contract address is always the same and nobody can use that address with a different contract.


### Single-use Registry Deployment Account

```
0xE6C244a1C10Aa0085b0cf92f04cdaD947C2988b8
```

This account is generated by reverse engineering it from its signature for the transaction. This way no one knows the private key, but it is known that it is the valid signer of the deployment transaction.

&gt; To deploy the registry, 0.08 ethers MUST be sent to this account *first*.

### Registry Contract Address

```
0x820b586C8C28125366C998641B09DCbE7d4cBF06
```

The contract has the address above for every chain on which it is deployed.

&lt;details&gt;
&lt;summary&gt;Raw metadata of &lt;code&gt;./contracts/ERC820Registry.sol&lt;/code&gt;&lt;/summary&gt;

```json
{
  &quot;compiler&quot;: {
    &quot;version&quot;: &quot;0.4.24+commit.e67f0147&quot;
  },
  &quot;language&quot;: &quot;Solidity&quot;,
  &quot;output&quot;: {
    &quot;abi&quot;: [
      {
        &quot;constant&quot;: false,
        &quot;inputs&quot;: [
          {
            &quot;name&quot;: &quot;_addr&quot;,
            &quot;type&quot;: &quot;address&quot;
          },
          {
            &quot;name&quot;: &quot;_interfaceHash&quot;,
            &quot;type&quot;: &quot;bytes32&quot;
          },
          {
            &quot;name&quot;: &quot;_implementer&quot;,
            &quot;type&quot;: &quot;address&quot;
          }
        ],
        &quot;name&quot;: &quot;setInterfaceImplementer&quot;,
        &quot;outputs&quot;: [],
        &quot;payable&quot;: false,
        &quot;stateMutability&quot;: &quot;nonpayable&quot;,
        &quot;type&quot;: &quot;function&quot;
      },
      {
        &quot;constant&quot;: true,
        &quot;inputs&quot;: [
          {
            &quot;name&quot;: &quot;_addr&quot;,
            &quot;type&quot;: &quot;address&quot;
          }
        ],
        &quot;name&quot;: &quot;getManager&quot;,
        &quot;outputs&quot;: [
          {
            &quot;name&quot;: &quot;&quot;,
            &quot;type&quot;: &quot;address&quot;
          }
        ],
        &quot;payable&quot;: false,
        &quot;stateMutability&quot;: &quot;view&quot;,
        &quot;type&quot;: &quot;function&quot;
      },
      {
        &quot;constant&quot;: false,
        &quot;inputs&quot;: [
          {
            &quot;name&quot;: &quot;_addr&quot;,
            &quot;type&quot;: &quot;address&quot;
          },
          {
            &quot;name&quot;: &quot;_newManager&quot;,
            &quot;type&quot;: &quot;address&quot;
          }
        ],
        &quot;name&quot;: &quot;setManager&quot;,
        &quot;outputs&quot;: [],
        &quot;payable&quot;: false,
        &quot;stateMutability&quot;: &quot;nonpayable&quot;,
        &quot;type&quot;: &quot;function&quot;
      },
      {
        &quot;constant&quot;: true,
        &quot;inputs&quot;: [
          {
            &quot;name&quot;: &quot;_interfaceName&quot;,
            &quot;type&quot;: &quot;string&quot;
          }
        ],
        &quot;name&quot;: &quot;interfaceHash&quot;,
        &quot;outputs&quot;: [
          {
            &quot;name&quot;: &quot;&quot;,
            &quot;type&quot;: &quot;bytes32&quot;
          }
        ],
        &quot;payable&quot;: false,
        &quot;stateMutability&quot;: &quot;pure&quot;,
        &quot;type&quot;: &quot;function&quot;
      },
      {
        &quot;constant&quot;: false,
        &quot;inputs&quot;: [
          {
            &quot;name&quot;: &quot;_contract&quot;,
            &quot;type&quot;: &quot;address&quot;
          },
          {
            &quot;name&quot;: &quot;_interfaceId&quot;,
            &quot;type&quot;: &quot;bytes4&quot;
          }
        ],
        &quot;name&quot;: &quot;updateERC165Cache&quot;,
        &quot;outputs&quot;: [],
        &quot;payable&quot;: false,
        &quot;stateMutability&quot;: &quot;nonpayable&quot;,
        &quot;type&quot;: &quot;function&quot;
      },
      {
        &quot;constant&quot;: true,
        &quot;inputs&quot;: [
          {
            &quot;name&quot;: &quot;_addr&quot;,
            &quot;type&quot;: &quot;address&quot;
          },
          {
            &quot;name&quot;: &quot;_interfaceHash&quot;,
            &quot;type&quot;: &quot;bytes32&quot;
          }
        ],
        &quot;name&quot;: &quot;getInterfaceImplementer&quot;,
        &quot;outputs&quot;: [
          {
            &quot;name&quot;: &quot;&quot;,
            &quot;type&quot;: &quot;address&quot;
          }
        ],
        &quot;payable&quot;: false,
        &quot;stateMutability&quot;: &quot;view&quot;,
        &quot;type&quot;: &quot;function&quot;
      },
      {
        &quot;constant&quot;: true,
        &quot;inputs&quot;: [
          {
            &quot;name&quot;: &quot;_contract&quot;,
            &quot;type&quot;: &quot;address&quot;
          },
          {
            &quot;name&quot;: &quot;_interfaceId&quot;,
            &quot;type&quot;: &quot;bytes4&quot;
          }
        ],
        &quot;name&quot;: &quot;implementsERC165InterfaceNoCache&quot;,
        &quot;outputs&quot;: [
          {
            &quot;name&quot;: &quot;&quot;,
            &quot;type&quot;: &quot;bool&quot;
          }
        ],
        &quot;payable&quot;: false,
        &quot;stateMutability&quot;: &quot;view&quot;,
        &quot;type&quot;: &quot;function&quot;
      },
      {
        &quot;constant&quot;: true,
        &quot;inputs&quot;: [
          {
            &quot;name&quot;: &quot;_contract&quot;,
            &quot;type&quot;: &quot;address&quot;
          },
          {
            &quot;name&quot;: &quot;_interfaceId&quot;,
            &quot;type&quot;: &quot;bytes4&quot;
          }
        ],
        &quot;name&quot;: &quot;implementsERC165Interface&quot;,
        &quot;outputs&quot;: [
          {
            &quot;name&quot;: &quot;&quot;,
            &quot;type&quot;: &quot;bool&quot;
          }
        ],
        &quot;payable&quot;: false,
        &quot;stateMutability&quot;: &quot;view&quot;,
        &quot;type&quot;: &quot;function&quot;
      },
      {
        &quot;anonymous&quot;: false,
        &quot;inputs&quot;: [
          {
            &quot;indexed&quot;: true,
            &quot;name&quot;: &quot;addr&quot;,
            &quot;type&quot;: &quot;address&quot;
          },
          {
            &quot;indexed&quot;: true,
            &quot;name&quot;: &quot;interfaceHash&quot;,
            &quot;type&quot;: &quot;bytes32&quot;
          },
          {
            &quot;indexed&quot;: true,
            &quot;name&quot;: &quot;implementer&quot;,
            &quot;type&quot;: &quot;address&quot;
          }
        ],
        &quot;name&quot;: &quot;InterfaceImplementerSet&quot;,
        &quot;type&quot;: &quot;event&quot;
      },
      {
        &quot;anonymous&quot;: false,
        &quot;inputs&quot;: [
          {
            &quot;indexed&quot;: true,
            &quot;name&quot;: &quot;addr&quot;,
            &quot;type&quot;: &quot;address&quot;
          },
          {
            &quot;indexed&quot;: true,
            &quot;name&quot;: &quot;newManager&quot;,
            &quot;type&quot;: &quot;address&quot;
          }
        ],
        &quot;name&quot;: &quot;ManagerChanged&quot;,
        &quot;type&quot;: &quot;event&quot;
      }
    ],
    &quot;devdoc&quot;: {
      &quot;author&quot;: &quot;Jordi Baylina and Jacques Dafflon&quot;,
      &quot;methods&quot;: {
        &quot;getInterfaceImplementer(address,bytes32)&quot;: {
          &quot;params&quot;: {
            &quot;_addr&quot;: &quot;Address being queried for the implementer of an interface. (If `_addr == 0` then `msg.sender` is assumed.)&quot;,
            &quot;_interfaceHash&quot;: &quot;keccak256 hash of the name of the interface as a string. E.g., `web3.utils.keccak256(&apos;ERC777Token&apos;)`.&quot;
          },
          &quot;return&quot;: &quot;The address of the contract which implements the interface `_interfaceHash` for `_addr` or `0x0` if `_addr` did not register an implementer for this interface.&quot;
        },
        &quot;getManager(address)&quot;: {
          &quot;params&quot;: {
            &quot;_addr&quot;: &quot;Address for which to return the manager.&quot;
          },
          &quot;return&quot;: &quot;Address of the manager for a given address.&quot;
        },
        &quot;implementsERC165Interface(address,bytes4)&quot;: {
          &quot;params&quot;: {
            &quot;_contract&quot;: &quot;Address of the contract to check.&quot;,
            &quot;_interfaceId&quot;: &quot;ERC165 interface to check.&quot;
          },
          &quot;return&quot;: &quot;`true` if `_contract` implements `_interfaceId`, false otherwise.&quot;
        },
        &quot;implementsERC165InterfaceNoCache(address,bytes4)&quot;: {
          &quot;params&quot;: {
            &quot;_contract&quot;: &quot;Address of the contract to check.&quot;,
            &quot;_interfaceId&quot;: &quot;ERC165 interface to check.&quot;
          },
          &quot;return&quot;: &quot;`true` if `_contract` implements `_interfaceId`, false otherwise.&quot;
        },
        &quot;interfaceHash(string)&quot;: {
          &quot;params&quot;: {
            &quot;_interfaceName&quot;: &quot;Name of the interface.&quot;
          },
          &quot;return&quot;: &quot;The keccak256 hash of an interface name.&quot;
        },
        &quot;setInterfaceImplementer(address,bytes32,address)&quot;: {
          &quot;params&quot;: {
            &quot;_addr&quot;: &quot;Address to define the interface for. (If `_addr == 0` then `msg.sender` is assumed.)&quot;,
            &quot;_implementer&quot;: &quot;Contract address implementing _interfaceHash for _addr.&quot;,
            &quot;_interfaceHash&quot;: &quot;keccak256 hash of the name of the interface as a string. For example, `web3.utils.keccak256(&apos;ERC777TokensRecipient&apos;)` for the `ERC777TokensRecipient` interface.&quot;
          }
        },
        &quot;setManager(address,address)&quot;: {
          &quot;params&quot;: {
            &quot;_addr&quot;: &quot;Address for which to set the new manager.&quot;,
            &quot;_newManager&quot;: &quot;Address of the new manager for `addr`.&quot;
          }
        },
        &quot;updateERC165Cache(address,bytes4)&quot;: {
          &quot;params&quot;: {
            &quot;_contract&quot;: &quot;Address of the contract for which to update the cache.&quot;,
            &quot;_interfaceId&quot;: &quot;ERC165 interface for which to update the cache.&quot;
          }
        }
      },
      &quot;title&quot;: &quot;ERC820 Pseudo-introspection Registry Contract&quot;
    },
    &quot;userdoc&quot;: {
      &quot;methods&quot;: {
        &quot;getInterfaceImplementer(address,bytes32)&quot;: {
          &quot;notice&quot;: &quot;Query if an address implements an interface and through which contract.&quot;
        },
        &quot;getManager(address)&quot;: {
          &quot;notice&quot;: &quot;Get the manager of an address.&quot;
        },
        &quot;implementsERC165Interface(address,bytes4)&quot;: {
          &quot;notice&quot;: &quot;Checks whether a contract implements an ERC165 interface or not. The result may be cached, if not a direct lookup is performed.&quot;
        },
        &quot;implementsERC165InterfaceNoCache(address,bytes4)&quot;: {
          &quot;notice&quot;: &quot;Checks whether a contract implements an ERC165 interface or not without using nor updating the cache.&quot;
        },
        &quot;interfaceHash(string)&quot;: {
          &quot;notice&quot;: &quot;Compute the keccak256 hash of an interface given its name.&quot;
        },
        &quot;setInterfaceImplementer(address,bytes32,address)&quot;: {
          &quot;notice&quot;: &quot;Sets the contract which implements a specific interface for an address. Only the manager defined for that address can set it. (Each address is the manager for itself until it sets a new manager.)&quot;
        },
        &quot;setManager(address,address)&quot;: {
          &quot;notice&quot;: &quot;Sets the `_newManager` as manager for the `_addr` address. The new manager will be able to call `setInterfaceImplementer` for `_addr`.&quot;
        },
        &quot;updateERC165Cache(address,bytes4)&quot;: {
          &quot;notice&quot;: &quot;Updates the cache with whether the contract implements an ERC165 interface or not.&quot;
        }
      }
    }
  },
  &quot;settings&quot;: {
    &quot;compilationTarget&quot;: {
      &quot;./contracts/ERC820Registry.sol&quot;: &quot;ERC820Registry&quot;
    },
    &quot;evmVersion&quot;: &quot;byzantium&quot;,
    &quot;libraries&quot;: {},
    &quot;optimizer&quot;: {
      &quot;enabled&quot;: true,
      &quot;runs&quot;: 200
    },
    &quot;remappings&quot;: []
  },
  &quot;sources&quot;: {
    &quot;./contracts/ERC820Registry.sol&quot;: {
      &quot;content&quot;: &quot;/* ERC820 Pseudo-introspection Registry Contract\n * This standard defines a universal registry smart contract where any address\n * (contract or regular account) can register which interface it supports and\n * which smart contract is responsible for its implementation.\n *\n * Written in 2018 by Jordi Baylina and Jacques Dafflon\n *\n * To the extent possible under law, the author(s) have dedicated all copyright\n * and related and neighboring rights to this software to the public domain\n * worldwide. This software is distributed without any warranty.\n *\n * You should have received a copy of the CC0 Public Domain Dedication along\n * with this software. If not, see\n * &lt;https://creativecommons.org/publicdomain/zero/1.0/&gt;.\n *\n *    ███████╗██████╗  ██████╗ █████╗ ██████╗  ██████╗\n *    ██╔════╝██╔══██╗██╔════╝██╔══██╗╚════██╗██╔═████╗\n *    █████╗  ██████╔╝██║     ╚█████╔╝ █████╔╝██║██╔██║\n *    ██╔══╝  ██╔══██╗██║     ██╔══██╗██╔═══╝ ████╔╝██║\n *    ███████╗██║  ██║╚██████╗╚█████╔╝███████╗╚██████╔╝\n *    ╚══════╝╚═╝  ╚═╝ ╚═════╝ ╚════╝ ╚══════╝ ╚═════╝\n *\n *    ██████╗ ███████╗ ██████╗ ██╗███████╗████████╗██████╗ ██╗   ██╗\n *    ██╔══██╗██╔════╝██╔════╝ ██║██╔════╝╚══██╔══╝██╔══██╗╚██╗ ██╔╝\n *    ██████╔╝█████╗  ██║  ███╗██║███████╗   ██║   ██████╔╝ ╚████╔╝\n *    ██╔══██╗██╔══╝  ██║   ██║██║╚════██║   ██║   ██╔══██╗  ╚██╔╝\n *    ██║  ██║███████╗╚██████╔╝██║███████║   ██║   ██║  ██║   ██║\n *    ╚═╝  ╚═╝╚══════╝ ╚═════╝ ╚═╝╚══════╝   ╚═╝   ╚═╝  ╚═╝   ╚═╝\n *\n */\npragma solidity 0.4.24;\n// IV is value needed to have a vanity address starting with `0x820`.\n// IV: 9513\n\n/// @dev The interface a contract MUST implement if it is the implementer of\n/// some (other) interface for any address other than itself.\ninterface ERC820ImplementerInterface {\n    /// @notice Indicates whether the contract implements the interface `interfaceHash` for the address `addr` or not.\n    /// @param interfaceHash keccak256 hash of the name of the interface\n    /// @param addr Address for which the contract will implement the interface\n    /// @return ERC820_ACCEPT_MAGIC only if the contract implements `interfaceHash` for the address `addr`.\n    function canImplementInterfaceForAddress(bytes32 interfaceHash, address addr) external view returns(bytes32);\n}\n\n\n/// @title ERC820 Pseudo-introspection Registry Contract\n/// @author Jordi Baylina and Jacques Dafflon\n/// @notice This contract is the official implementation of the ERC820 Registry.\n/// @notice For more details, see https://eips.ethereum.org/EIPS/eip-820\ncontract ERC820Registry {\n    /// @notice ERC165 Invalid ID.\n    bytes4 constant INVALID_ID = 0xffffffff;\n    /// @notice Method ID for the ERC165 supportsInterface method (= `bytes4(keccak256(&apos;supportsInterface(bytes4)&apos;))`).\n    bytes4 constant ERC165ID = 0x01ffc9a7;\n    /// @notice Magic value which is returned if a contract implements an interface on behalf of some other address.\n    bytes32 constant ERC820_ACCEPT_MAGIC = keccak256(abi.encodePacked(\&quot;ERC820_ACCEPT_MAGIC\&quot;));\n\n    mapping (address =&gt; mapping(bytes32 =&gt; address)) interfaces;\n    mapping (address =&gt; address) managers;\n    mapping (address =&gt; mapping(bytes4 =&gt; bool)) erc165Cached;\n\n    /// @notice Indicates a contract is the `implementer` of `interfaceHash` for `addr`.\n    event InterfaceImplementerSet(address indexed addr, bytes32 indexed interfaceHash, address indexed implementer);\n    /// @notice Indicates `newManager` is the address of the new manager for `addr`.\n    event ManagerChanged(address indexed addr, address indexed newManager);\n\n    /// @notice Query if an address implements an interface and through which contract.\n    /// @param _addr Address being queried for the implementer of an interface.\n    /// (If `_addr == 0` then `msg.sender` is assumed.)\n    /// @param _interfaceHash keccak256 hash of the name of the interface as a string.\n    /// E.g., `web3.utils.keccak256(&apos;ERC777Token&apos;)`.\n    /// @return The address of the contract which implements the interface `_interfaceHash` for `_addr`\n    /// or `0x0` if `_addr` did not register an implementer for this interface.\n    function getInterfaceImplementer(address _addr, bytes32 _interfaceHash) external view returns (address) {\n        address addr = _addr == 0 ? msg.sender : _addr;\n        if (isERC165Interface(_interfaceHash)) {\n            bytes4 erc165InterfaceHash = bytes4(_interfaceHash);\n            return implementsERC165Interface(addr, erc165InterfaceHash) ? addr : 0;\n        }\n        return interfaces[addr][_interfaceHash];\n    }\n\n    /// @notice Sets the contract which implements a specific interface for an address.\n    /// Only the manager defined for that address can set it.\n    /// (Each address is the manager for itself until it sets a new manager.)\n    /// @param _addr Address to define the interface for. (If `_addr == 0` then `msg.sender` is assumed.)\n    /// @param _interfaceHash keccak256 hash of the name of the interface as a string.\n    /// For example, `web3.utils.keccak256(&apos;ERC777TokensRecipient&apos;)` for the `ERC777TokensRecipient` interface.\n    /// @param _implementer Contract address implementing _interfaceHash for _addr.\n    function setInterfaceImplementer(address _addr, bytes32 _interfaceHash, address _implementer) external {\n        address addr = _addr == 0 ? msg.sender : _addr;\n        require(getManager(addr) == msg.sender, \&quot;Not the manager\&quot;);\n\n        require(!isERC165Interface(_interfaceHash), \&quot;Must not be a ERC165 hash\&quot;);\n        if (_implementer != 0 &amp;&amp; _implementer != msg.sender) {\n            require(\n                ERC820ImplementerInterface(_implementer)\n                    .canImplementInterfaceForAddress(_interfaceHash, addr) == ERC820_ACCEPT_MAGIC,\n                \&quot;Does not implement the interface\&quot;\n            );\n        }\n        interfaces[addr][_interfaceHash] = _implementer;\n        emit InterfaceImplementerSet(addr, _interfaceHash, _implementer);\n    }\n\n    /// @notice Sets the `_newManager` as manager for the `_addr` address.\n    /// The new manager will be able to call `setInterfaceImplementer` for `_addr`.\n    /// @param _addr Address for which to set the new manager.\n    /// @param _newManager Address of the new manager for `addr`.\n    function setManager(address _addr, address _newManager) external {\n        require(getManager(_addr) == msg.sender, \&quot;Not the manager\&quot;);\n        managers[_addr] = _newManager == _addr ? 0 : _newManager;\n        emit ManagerChanged(_addr, _newManager);\n    }\n\n    /// @notice Get the manager of an address.\n    /// @param _addr Address for which to return the manager.\n    /// @return Address of the manager for a given address.\n    function getManager(address _addr) public view returns(address) {\n        // By default the manager of an address is the same address\n        if (managers[_addr] == 0) {\n            return _addr;\n        } else {\n            return managers[_addr];\n        }\n    }\n\n    /// @notice Compute the keccak256 hash of an interface given its name.\n    /// @param _interfaceName Name of the interface.\n    /// @return The keccak256 hash of an interface name.\n    function interfaceHash(string _interfaceName) external pure returns(bytes32) {\n        return keccak256(abi.encodePacked(_interfaceName));\n    }\n\n    /* --- ERC165 Related Functions --- */\n    /* --- Developed in collaboration with William Entriken. --- */\n\n    /// @notice Updates the cache with whether the contract implements an ERC165 interface or not.\n    /// @param _contract Address of the contract for which to update the cache.\n    /// @param _interfaceId ERC165 interface for which to update the cache.\n    function updateERC165Cache(address _contract, bytes4 _interfaceId) external {\n        interfaces[_contract][_interfaceId] = implementsERC165InterfaceNoCache(_contract, _interfaceId) ? _contract : 0;\n        erc165Cached[_contract][_interfaceId] = true;\n    }\n\n    /// @notice Checks whether a contract implements an ERC165 interface or not.\n    /// The result may be cached, if not a direct lookup is performed.\n    /// @param _contract Address of the contract to check.\n    /// @param _interfaceId ERC165 interface to check.\n    /// @return `true` if `_contract` implements `_interfaceId`, false otherwise.\n    function implementsERC165Interface(address _contract, bytes4 _interfaceId) public view returns (bool) {\n        if (!erc165Cached[_contract][_interfaceId]) {\n            return implementsERC165InterfaceNoCache(_contract, _interfaceId);\n        }\n        return interfaces[_contract][_interfaceId] == _contract;\n    }\n\n    /// @notice Checks whether a contract implements an ERC165 interface or not without using nor updating the cache.\n    /// @param _contract Address of the contract to check.\n    /// @param _interfaceId ERC165 interface to check.\n    /// @return `true` if `_contract` implements `_interfaceId`, false otherwise.\n    function implementsERC165InterfaceNoCache(address _contract, bytes4 _interfaceId) public view returns (bool) {\n        uint256 success;\n        uint256 result;\n\n        (success, result) = noThrowCall(_contract, ERC165ID);\n        if (success == 0 || result == 0) {\n            return false;\n        }\n\n        (success, result) = noThrowCall(_contract, INVALID_ID);\n        if (success == 0 || result != 0) {\n            return false;\n        }\n\n        (success, result) = noThrowCall(_contract, _interfaceId);\n        if (success == 1 &amp;&amp; result == 1) {\n            return true;\n        }\n        return false;\n    }\n\n    /// @notice Checks whether the hash is a ERC165 interface (ending with 28 zeroes) or not.\n    /// @param _interfaceHash The hash to check.\n    /// @return `true` if the hash is a ERC165 interface (ending with 28 zeroes), `false` otherwise.\n    function isERC165Interface(bytes32 _interfaceHash) internal pure returns (bool) {\n        return _interfaceHash &amp; 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0;\n    }\n\n    /// @dev Make a call on a contract without throwing if the function does not exist.\n    function noThrowCall(address _contract, bytes4 _interfaceId)\n        internal view returns (uint256 success, uint256 result)\n    {\n        bytes4 erc165ID = ERC165ID;\n\n        assembly {\n                let x := mload(0x40)               // Find empty storage location using \&quot;free memory pointer\&quot;\n                mstore(x, erc165ID)                // Place signature at beginning of empty storage\n                mstore(add(x, 0x04), _interfaceId) // Place first argument directly next to signature\n\n                success := staticcall(\n                    30000,                         // 30k gas\n                    _contract,                     // To addr\n                    x,                             // Inputs are stored at location x\n                    0x08,                          // Inputs are 8 bytes long\n                    x,                             // Store output over input (saves space)\n                    0x20                           // Outputs are 32 bytes long\n                )\n\n                result := mload(x)                 // Load the result\n        }\n    }\n}\n&quot;,
      &quot;keccak256&quot;: &quot;0x8eecce3912a15087b3f5845d5a74af7712c93d0a8fcd6f2d40f07ed5032022ab&quot;
    }
  },
  &quot;version&quot;: 1
}
```

&lt;/details&gt;

### Interface Name

Any interface name is hashed using `keccak256` and sent to `getInterfaceImplementer()`.

If the interface is part of a standard, it is best practice to explicitly state the interface name and link to this published [ERC-820] such that other people don&apos;t have to come here to look up these rules.

For convenience, the registry provides a function to compute the hash on-chain:

``` solidity
function interfaceHash(string _interfaceName) public pure returns(bytes32)
```

Compute the keccak256 hash of an interface given its name.

&gt; &lt;small&gt;**identifier:** `65ba36c1`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`_interfaceName`: Name of the interface.&lt;/small&gt;  
&gt; &lt;small&gt;**returns:** The `keccak256` hash of an interface name.&lt;/small&gt;

#### **Approved ERCs**

If the interface is part of an approved ERC, it MUST be named `ERC###XXXXX` where `###` is the number of the ERC and XXXXX should be the name of the interface in CamelCase. The meaning of this interface SHOULD be defined in the specified ERC.

Examples:

- `keccak256(&quot;ERC20Token&quot;)`
- `keccak256(&quot;ERC777Token&quot;)`
- `keccak256(&quot;ERC777TokensSender&quot;)`
- `keccak256(&quot;ERC777TokensRecipient&quot;)`

#### **[ERC-165] Compatible Interfaces**

&gt; The compatibility with [ERC-165], including the [ERC165 Cache], has been designed and developed with [William Entriken].

Any interface where the last 28 bytes are zeroes (`0`) SHALL be considered an [ERC-165] interface.

**[ERC-165] Lookup**

Anyone can explicitly check if a contract implements an [ERC-165] interface using the registry by calling one of the two functions below:

``` solidity
function implementsERC165Interface(address _contract, bytes4 _interfaceId) public view returns (bool)
```

Checks whether a contract implements an [ERC-165] interface or not.

*NOTE*: The result is cached. If the cache is out of date, it MUST be updated by calling `updateERC165Cache`. (See [ERC165 Cache] for more details.)

&gt; &lt;small&gt;**identifier:** `f712f3e8`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`_contract`: Address of the contract to check.&lt;/small&gt;  
&gt; &lt;small&gt;`_interfaceId`: [ERC-165] interface to check.&lt;/small&gt;  
&gt; &lt;small&gt;**returns:** `true` if `_contract` implements `_interfaceId`, false otherwise.&lt;/small&gt;

``` solidity
function implementsERC165InterfaceNoCache(address _contract, bytes4 _interfaceId) public view returns (bool)
```

Checks whether a contract implements an [ERC-165] interface or not without using nor updating the cache.

&gt; &lt;small&gt;**identifier:** `b7056765`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`_contract`: Address of the contract to check.&lt;/small&gt;  
&gt; &lt;small&gt;`_interfaceId`: [ERC-165] interface to check.&lt;/small&gt;  
&gt; &lt;small&gt;**returns:** `true` if `_contract` implements `_interfaceId`, false otherwise.&lt;/small&gt;

**[ERC-165] Cache** &lt;a id=&quot;erc165-cache&quot;&gt;&lt;/a&gt;

Whether a contract implements an [ERC-165] interface or not can be cached manually to save gas.

If a contract dynamically changes its interface and relies on the [ERC-165] cache of the [ERC-820] registry, the cache MUST be updated manually---there is no automatic cache invalidation or cache update. Ideally the contract SHOULD automatically update the cache when changing its interface. However anyone MAY update the cache on the contract&apos;s behalf.

The cache update MUST be done using the `updateERC165Cache` function:

``` solidity
function updateERC165Cache(address _contract, bytes4 _interfaceId) public
```

&gt; &lt;small&gt;**identifier:** `a41e7d51`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`_contract`: Address of the contract for which to update the cache.&lt;/small&gt;  
&gt; &lt;small&gt;`_interfaceId`: [ERC-165] interface for which to update the cache.&lt;/small&gt;

#### **Private User-defined Interfaces**

This scheme is extensible. You MAY make up your own interface name and raise awareness to get other people to implement it and then check for those implementations. Have fun but please, you MUST not conflict with the reserved designations above.

### Set An Interface For An Address

For any address to set a contract as the interface implementation, it must call the following function of the [ERC-820] registry:

``` solidity
function setInterfaceImplementer(address _addr, bytes32 _interfaceHash, address _implementer) public
```

Sets the contract which implements a specific interface for an address.

Only the `manager` defined for that address can set it. (Each address is the manager for itself, see the [manager] section for more details.)

*NOTE*: If  `_addr` and `_implementer` are two different addresses, then:

- The `_implementer` MUST implement the `ERC820ImplementerInterface` (detailed below).
- Calling `canImplementInterfaceForAddress` on `_implementer` with the given `_addr` and  `_interfaceHash` MUST return the `ERC820_ACCEPT_MAGIC` value.

*NOTE*: The `_interfaceHash` MUST NOT be an [ERC-165] interface---it MUST NOT end with 28 zeroes (`0`).

*NOTE*: The `_addr` MAY be `0`, then `msg.sender` is assumed. This default value simplifies interactions via multisigs where the data of the transaction to sign is constant regardless of the address of the multisig instance.

&gt; &lt;small&gt;**identifier:** `29965a1d`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`_addr`: Address to define the interface for (if `_addr == 0` them `msg.sender`: is assumed)&lt;/small&gt;  
&gt; &lt;small&gt;`_interfaceHash`: `keccak256` hash of the name of the interface as a string, for example `web3.utils.keccak256(&apos;ERC777TokensRecipient&apos;)` for the ERC777TokensRecipient interface.&lt;/small&gt;  
&gt; &lt;small&gt;`_implementer`: Contract implementing `_interfaceHash` for `_addr`.&lt;/small&gt;

### Get An Implementation Of An Interface For An Address

Anyone MAY query the [ERC-820] Registry to obtain the address of a contract implementing an interface on behalf of some address using the `getInterfaceImplementer` function.

``` solidity
function getInterfaceImplementer(address _addr, bytes32 _interfaceHash) public view returns (address)
```

Query if an address implements an interface and through which contract.

*NOTE*: If the last 28 bytes of the `_interfaceHash` are zeroes (`0`), then the first 4 bytes are considered an [ERC-165] interface and the registry SHALL forward the call to the contract at `_addr` to see if it implements the [ERC-165] interface (the first 4 bytes of `_interfaceHash`). The registry SHALL also cache [ERC-165] queries to reduce gas consumption. Anyone MAY call the `erc165UpdateCache` function to update whether a contract implements an interface or not.

*NOTE*: The `_addr` MAY be `0`, then `msg.sender` is assumed. This default value is consistent with the behavior of the `setInterfaceImplementer` function and simplifies interactions via multisigs where the data of the transaction to sign is constant regardless of the address of the multisig instance.

&gt; &lt;small&gt;**identifier:** `aabbb8ca`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`_addr`: Address being queried for the implementer of an interface. (If `_addr == 0` them `msg.sender` is assumed.)&lt;/small&gt;  
&gt; &lt;small&gt;`_interfaceHash`: keccak256 hash of the name of the interface as a string. E.g. `web3.utils.keccak256(&apos;ERC777Token&apos;)`&lt;/small&gt;  
&gt; &lt;small&gt;**returns:** The address of the contract which implements the interface `_interfaceHash` for `_addr` or `0x0` if `_addr` did not register an implementer for this interface.&lt;/small&gt;


### Interface Implementation (`ERC820ImplementerInterface`)

``` solidity
interface ERC820ImplementerInterface {
    /// @notice Indicates whether the contract implements the interface `interfaceHash` for the address `addr`.
    /// @param addr Address for which the contract will implement the interface
    /// @param interfaceHash keccak256 hash of the name of the interface
    /// @return ERC820_ACCEPT_MAGIC only if the contract implements `ìnterfaceHash` for the address `addr`.
    function canImplementInterfaceForAddress(bytes32 interfaceHash, address addr) public view returns(bytes32);
}
```

Any contract being registered as the implementation of an interface for a given address MUST implement said interface. In addition if it implements an interface on behalf of a different address, the contract MUST implement the `ERC820ImplementerInterface` shown above.

``` solidity
function canImplementInterfaceForAddress(bytes32 interfaceHash, address addr) view public returns(bytes32);
```

Indicates whether a contract implements an interface (`interfaceHash`) for a given address (`addr`).

If a contract implements the interface (`interfaceHash`) for a given address (`addr`), it MUST return `ERC820_ACCEPT_MAGIC` when called with the `addr` and the `interfaceHash`. If it does not implement the `interfaceHash` for a given address (`addr`), it MUST NOT return `ERC820_ACCEPT_MAGIC`.

&gt; &lt;small&gt;**identifier:** `f0083250`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`interfaceHash`: Hash of the interface which is implemented&lt;/small&gt;  
&gt; &lt;small&gt;`addr`: Address for which the interface is implemented&lt;/small&gt;  
&gt; &lt;small&gt;**returns:** `ERC820_ACCEPT_MAGIC` only if the contract implements `ìnterfaceHash` for the address `addr`.&lt;/small&gt;

The special value `ERC820_ACCEPT_MAGIC` is defined as the `keccka256` hash of the string `&quot;ERC820_ACCEPT_MAGIC&quot;`.

``` solidity
bytes32 constant ERC820_ACCEPT_MAGIC = keccak256(&quot;ERC820_ACCEPT_MAGIC&quot;);
```

&gt; The reason to return `ERC820_ACCEPT_MAGIC` instead of a boolean is to prevent cases where a contract fails to implement the `canImplementInterfaceForAddress` but implements a fallback function which does not throw. In this case, since `canImplementInterfaceForAddress` does not exist, the fallback function is called instead, executed without throwing and returns `1`. Thus making it appear as if `canImplementInterfaceForAddress` returned `true`.

### Manager

The manager of an address (regular account or a contract) is the only entity allowed to register implementations of interfaces for the address. By default, any address is its own manager.

The manager can transfer its role to another address by calling `setManager` on the registry contract with the address for which to transfer the manager and the address of the new manager.

**`setManager` Function**

``` solidity
function setManager(address _addr, address _newManager) public
```

Sets the `_newManager` as manager for the `_addr` address.

The new manager will be able to call `setInterfaceImplementer` for `_addr`.

If `_newManager` is `0x0`, the manager is reset to `_addr` itself as the manager.

&gt; &lt;small&gt;**identifier:** `5df8122f`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`_addr`: Address for which to set the new manager.&lt;/small&gt;  
&gt; &lt;small&gt;`_newManager`: The address of the new manager for `_addr`. (Pass `0x0` to reset the manager to `_addr`.)&lt;/small&gt;

**`getManager` Function**

``` solidity
function getManager(address _addr) public view returns(address)
```

Get the manager of an address.

&gt; &lt;small&gt;**identifier:** `3d584063`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`_addr`: Address for which to return the manager.&lt;/small&gt;  
&gt; &lt;small&gt;**returns:** Address of the manager for a given address.&lt;/small&gt;

## Rationale

This standards offers a way for any type of address (externally owned and contracts) to implement an interface and potentially delegate the implementation of the interface to a proxy contract. This delegation to a proxy contract is necessary for externally owned accounts and useful to avoid redeploying existing contracts such as multisigs and DAOs.

The registry can also act as a [ERC-165] cache in order to save gas when looking up if a contract implements a specific [ERC-165] interface. This cache is intentionally kept simple, without automatic cache update or invalidation. Anyone can easily and safely update the cache for any interface and any contract by calling the `updateERC165Cache` function.

The registry is deployed using a keyless deployment method relying on a single-use deployment address to ensure no one controls the registry, thereby ensuring trust.

## Backward Compatibility

This standard is backward compatible with [ERC-165], as both methods MAY be implemented without conflicting with each other.

## Test Cases

Please check the [jbaylina/ERC820] repository for the full test suite.

## Implementation

The implementation is available in the repo: [jbaylina/ERC820].

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[EIP-155]: /EIPs/EIPS/eip-155

[ERC-165]: /EIPs/EIPS/eip-165
[ERC-672]: https://github.com/ethereum/EIPs/issues/672

[ERC-820]: /EIPs/EIPS/eip-820
[ERC820 registry smart contract]: https://github.com/jbaylina/ERC820/blob/master/contracts/ERC820Registry.sol
[manager]: #manager
[lookup]: #get-an-implementation-of-an-interface-for-an-address
[ERC165 Cache]: #erc165-cache
[Nick&apos;s article]: https://medium.com/@weka/how-to-send-ether-to-11-440-people-187e332566b7
[jbaylina/ERC820]: https://github.com/jbaylina/ERC820
[Nick]: https://github.com/Arachnid/
[William Entriken]: https://github.com/fulldecent
[ENS]: https://ens.domains/

[ERC-1820]: /EIPs/EIPS/eip-1820
[erc1820-annoucement]: https://github.com/ethereum/EIPs/issues/820#issuecomment-464109166
[erc820-bug]: https://github.com/ethereum/EIPs/issues/820#issuecomment-452465748
[erc820-fix]: https://github.com/ethereum/EIPs/issues/820#issuecomment-454021564
</description>
        <pubDate>Fri, 05 Jan 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-820</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-820</guid>
      </item>
    
      <item>
        <title>Token Exchange Standard</title>
        <category>Standards Track/ERC</category>
        
        <description>## Simple Summary
A standard for token contracts, providing token exchange services thereby facilitating cross token payments.

## Abstract
The following standard provides functionally to make payments in the form of any other registered tokens, as well as allow token contracts to store any other tokens in an existing token contract. This standard allows ERC20 token holders to exchange their token with another ERC20 token and use the exchanged tokens to make payments. After a successful payment, the former specified ERC20 tokens, will be stored within the ERC20 token contract they are exchanged with. This proposal uses the term target contract which is used to denote the contract to the token with whom we want to exchange our tokens.

## Motivation
Existing token standards do not provide functionality to exchange tokens. Existing token converters reduce the total supply of an existing token, which in the sense destroys the currency. Token converters do not solve this problem and hence discourages creation of new tokens. This solution does not destroy the existing token but in essence preserve them in the token contract that they are exchanged with, which in turn increases the market value of the latter.

## Specification
### Sender Interface
This interface must be inherited by a ERC20 token contract that wants to exchange its tokens with another token.

#### Storage Variables
##### exchnagedWith
This mapping stores the number of tokens exchanged with another token, along with the latter’s address. Every time more tokens are exchanged the integer value is incremented consequently. This mapping acts as a record to denote which target contract holds our tokens.

```solidity
mapping ( address =&gt; uint ) private exchangedWith;
```
##### exchangedBy
This mapping stores the address of the person who initiated the exchange and the amount of tokens exchanged.

```solidity
mapping ( address =&gt; uint ) private exhangedBy;
```

#### Methods

NOTE: Callers MUST handle false from returns (bool success). Callers MUST NOT assume that false is never returned!

##### exchangeToken
This function calls the intermediate exchange service contract that handles the exchanges. This function takes the address of the target contract and the amount we want to exchange as parameters and returns boolean `success` and `creditedAmount`.

```solidity
function exchangeToken(address _targetContract, uint _amount) public returns(bool success, uint creditedAmount)
```

##### exchangeAndSpend
This function calls an intermediate exchange service contract that handles exchange and expenditure. This function takes the address of the target contract, the amount we want to spend in terms of target contract tokens and address of the receiver as parameters and returns boolean `success`.

```solidity
function exchangeAndSpend(address _targetContract, uint _amount,address _to) public returns(bool success)
```

##### __exchangerCallback
This function is called by the exchange service contract to our token contract to deduct calculated amount from our balance. It takes the address of the targert contract , the address of the person who exchanged the tokens and amount to be deducted from exchangers account as parameters and returns boolean `success`.

NOTE: It is required that only the exchange service contract has the authority to call this function.

```solidity
function __exchangerCallback(address _targetContract,address _exchanger, uint _amount) public returns(bool success)
```

#### Events

##### Exchange
This event logs any new exchanges that have taken place.

```solidity
event Exchange(address _from, address _ targetContract, uint _amount)
```

##### ExchangeSpent
This event logs any new exchange that have taken place and have been spent immediately.

```solidity
event ExchangeSpent(address _from, address _targetContract, address _to, uint _amount)
```

### Receiver Interface
This interface must be inherited by a ERC20 token contract that wants to receive exchanged tokens.

#### Storage Variables
##### exchangesRecieved
This mapping stores the number of tokens received in terms of another token, along with its address. Every time more tokens are exchanged the integer value is incremented consequently. This mapping acts as a record to denote which tokens do this contract holds apart from its own.

```solidity
mapping ( address =&gt; uint ) private exchnagesReceived;
```
#### Methods

NOTE: Callers MUST handle false from returns (bool success). Callers MUST NOT assume that false is never returned!

##### __targetExchangeCallback
This function is called by the intermediate exchange service contract. This function should add `_amount` tokens of the target contract to the exchangers address for exchange to be completed successfully.

NOTE: It is required that only the exchange service contract has the authority to call this function.

```solidity
function __targetExchangeCallback (uint _to, uint _amount) public returns(bool success)
```

##### __targetExchangeAndSpendCallback
This function is called by the intermediate exchange service contract. This function should add `_amount` tokens of the target contract to the exchangers address and transfer it to the `_to` address for the exchange and expenditure to be completed successfully.

NOTE: It is required that only the exchange service contract has the authority to call this function.

```solidity
function __targetExchangeAndSpendCallback (address _from, address _to, uint _amount) public returns(bool success)
```

#### Events
##### Exchange
This event logs any new exchanges that have taken place.

```solidity
event Exchange(address _from, address _with, uint _amount)
```

##### ExchangeSpent
This event logs any new exchange that have taken place and have been spent immediately.
```solidity
event ExchangeSpent(address _from, address _ targetContract, address _to, uint _amount)
```

### Exchange Service Contract

This is an intermediate contract that provides a gateway for exchanges and expenditure. This contract uses oracles to get the authenticated exchange rates.

#### Storage Variables

##### registeredTokens

This array stores all the tokens that are registered for exchange. Only register tokens can participate in exchanges.

```solidity
address[] private registeredTokens;
```

#### Methods

##### registerToken

This function is called by the owner of the token contract to get it’s tokens registered. It takes the address of the token as the parameter and return boolean `success`.

NOTE: Before any exchange it must be ensured that the token is registered.

```solidity
function registerToken(address _token) public returns(bool success)
```

##### exchangeToken

This function is called by the token holder who wants to exchange his token with the `_targetContract` tokens. This function queries the exchange rate, calculates the converted amount, calls `__exchangerCallback` and calls the `__targetExchangeCallback`. It takes address of the target contract and amount to exchange as parameter and returns boolean `success` and amount credited.

```solidity
function exchangeToken(address _targetContract, uint _amount, address _from) public returns(bool success, uint creditedAmount)
```

##### exchangeAndSpend

This function is called by the token holder who wants to exchange his token with the `_targetContract` tokens. This function queries the exchange rate, calculates the converted amount, calls `__exchangerCallback` and calls the `__targetExchangeAndSpendCallback`. It takes address of the target contract and amount to exchange as parameter and returns boolean `success` and amount credited.

```solidity
function exchangeAndSpend(address _targetContract, uint _amount, address _from, address _to) public returns(bool success)
```

#### Events

##### Exchanges

This event logs any new exchanges that have taken place.

```solidity
event Exchange( address _from, address _by, uint _value ,address _target )
```
##### ExchangeAndSpent

This event logs any new exchange that have taken place and have been spent immediately.

```solidity
event ExchangeAndSpent ( address _from, address _by, uint _value ,address _target ,address _to)
```

### Diagramatic Explanation

#### Exchanging Tokens
![token-exchange-standard-visual-representation-1](/EIPs/assets/eip-823/eip-823-token-exchange-standard-visual-representation-1.png)

NOTE: After the successful exchange the contract on right owns some tokens of the contract on the left.

#### Exchanging And Spending Tokens

![token-exchange-standard-visual-representation-2](/EIPs/assets/eip-823/eip-823-token-exchange-standard-visual-representation-2.png)

NOTE: After the successful exchange the contract on right owns some tokens of the contract on the left.

## Rationale

Such a design provides a consistent exchange standard 
applicable to all ERC20 tokens that follow it.
The primary advantage for of this strategy is that the exchanged tokens will not be lost. They can either be spent or preserved.
Token convert face a major drawback of destroying tokens after conversion. This mechanism treats tokens like conventional currency where tokens are not destroyed but are stored.

## Backward Compatibility

This proposal is fully backward compatible. Tokens extended by this proposal should also be following ERC20 standard. The functionality of ERC20 standard should not be affected by this proposal but will provide additional functionality to it.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Sat, 06 Jan 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-823</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-823</guid>
      </item>
    
      <item>
        <title>URI Format for Ethereum</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-831-uri-format-for-ethereum/10105</comments>
        
        <description>## Abstract

URIs embedded in QR-codes, hyperlinks in web-pages, emails or chat messages provide for robust cross-application signaling between very loosely coupled applications. A standardized URI format allows for instant invocation of the user&apos;s preferred wallet application.

## Specification

### Syntax

Ethereum URIs contain &quot;ethereum&quot; or &quot;eth&quot; in their schema (protocol) part and are constructed as follows:

    request                 = &quot;eth&quot; [ &quot;ereum&quot; ] &quot;:&quot; [ prefix &quot;-&quot; ] payload
    prefix                  = STRING
    payload                 = STRING

### Semantics

`prefix` is optional and defines the use-case for this URI. If no prefix is given: &quot;pay-&quot; is assumed to be concise and ensure backward compatibility to [EIP-67](/EIPs/EIPS/eip-67). When the prefix is omitted, the payload must start with `0x`. Also prefixes must not start with `0x`. So starting with `0x` can be used as a clear signal that there is no prefix.

`payload` is mandatory and the content depends on the prefix. Structuring of the content is defined in the ERC for the specific use-case and not in the scope of this document. One example is [EIP-681](./eip-681) for the pay- prefix.

## Rationale

The need for this ERC emerged when refining EIP-681. We need a container that does not carry the weight of the use-cases. EIP-67 was the first attempt on defining Ethereum-URIs. This ERC tries to keep backward compatibility and not break existing things. This means EIP-67 URIs should still be valid and readable. Only if the prefix feature is used, EIP-67 parsers might break. No way was seen to avoid this and innovate on the same time. This is also the reason this open prefix approach was chosen to being able to adopt to future use-cases and not block the whole &quot;ethereum:&quot; scheme for a limited set of use-cases that existed at the time of writing this.

## Security Considerations

There are no known security considerations at this time.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 15 Jan 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-831</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-831</guid>
      </item>
    
      <item>
        <title>ABI specification for REVERT reason string</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-838-what-is-the-current-status/14671</comments>
        
        <description>## Abstract

This proposal specifies how to encode potential error conditions in the JSON ABI of a smart contract. A high-level language could then provide a syntax for declaring and throwing these errors. The compiler will encode these errors in the reason parameter of the REVERT opcode in a way that can be easily reconstructed by libraries such as web3.


## Motivation

It&apos;s important to provide clear feedback to users (and developers) about what went wrong with their Ethereum transactions. The REVERT opcode is a step in the right direction, as it allows smart contract developers to encode a message describing the failure in the reason parameter. There is an implementation under review in Solidity that accepts a string, thus providing a low-level interface to this parameter. However, standardizing a method for passing errors from this parameter back to clients will bring many benefits to both users and developers.

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

## Specification

To conform to this specification, compilers producing JSON ABIs SHOULD include error declarations alongside functions and events. Each error object MUST contain the keys name (string) and arguments (same types as the function’s inputs list). The value of type MUST be &quot;error&quot;.

Example:

```
{ &quot;type&quot;: &quot;error&quot;, &quot;name&quot;: &quot;InsufficientBalance&quot;, &quot;arguments&quot;: [ { &quot;name&quot;: &quot;amount&quot;, &quot;type&quot;: &quot;uint256&quot; } ] }
```

A selector for this error can be computed from its signature (InsufficientBalance() for the example above) in the same way that it&apos;s currently done for public functions and events. This selector MUST be included in the reason string so that clients can perform a lookup. Any arguments for the error are RLP encoded in the same way as return values from functions. The exact format in which both the selector and the arguments are encoded is to be defined. The Solidity implementation mentioned above leaves room for expansion by prefixing the free-form string with uint256(0).

A high-level language like Solidity can then implement a syntax like this:

```
contract MyToken {
  error InsufficientFunds(uint256 amount);

  function transfer(address _to, uint256 _amount) {
    if (balances[msg.sender] &lt;= _amount)
       throw InsufficientFunds(_amount);
    ...
  }
  ...
}
```

### Possible extensions


1. A NatSpec comment above the error declaration can be used to provide a default error message. Arguments to the error can be interpolated in the message string with familiar NatSpec syntax.

```
/// @notice You don&apos;t have enough funds to transfer `amount`.
error InsufficientFunds(uint256 amount);
```

2. A function may declare to its callers which errors it can throw. A list of these errors must be included in the JSON ABI item for that function, under the `errors` key. Example:

```
function transfer(address _to, uint256 _amount) throws(InsufficientFunds);
```

Special consideration should be given to error overloading if we want to support a similar syntax in the future, as errors with same name but different arguments will produce a different selector.

## Rationale

Needs discussion. &lt;!-- TODO --&gt;

## Backwards Compatibility

Apps and tools that have not implemented this spec can ignore the encoded reason string when it&apos;s not prefixed by zero.

## Security Considerations

Needs discussion. &lt;!-- TODO --&gt;

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 20 Aug 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-838</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-838</guid>
      </item>
    
      <item>
        <title>Reduce block reward and delay difficulty bomb</title>
        <category>Standards Track/Core</category>
        
        <description>## Simple Summary
Reduce the block reward to 1 ETH and delay the difficulty bomb.

## Abstract
The current public Ethereum network has a hashrate that corresponds to a tremendous level of energy consumption. As this energy consumption has a correlated environmental cost the network participants have an ethical obligation to ensure this cost is not higher than necessary. At this time, the most direct way to reduce this cost is to lower the block reward in order to limit the appeal of ETH mining. Unchecked growth in hashrate is also counterproductive from a security standpoint.
Recent research developments also now time the switch to POS as sometime in 2019 and as a result there is need to further delay the difficulty bomb so the network doesn&apos;t grind to a halt.


## Motivation
The current public Ethereum network has a hashrate of 296 TH/s. This hashrate corresponds to a power usage of roughly [1 TW](/EIPs/assets/eip-858/calculations) and yearly energy consumption of 8.8 TWh (roughly 0.04% of [total](https://en.wikipedia.org/wiki/List_of_countries_by_electricity_consumption) global electricity consumption). A future switch to full Proof of Stake will solve this issue entirely. Yet that switch remains enough in the future that action should be taken in the interim to limit excess harmful side affects of the present network.

## Specification

Delay difficulty bomb by 2,000,000 blocks
Adjust block, uncle, and nephew rewards to reflect a new block reward of 1 ETH.

## Rationale
This will delay the difficulty bomb by roughly a year. The difficulty bomb remains a community supported mechanism to aid a future transition to POS.

The network hashrate provides security by reducing the likelihood that an adversary could mount a 51% attack. A static block reward means that factors (price) may be such that participation in mining grows unchecked. This growth may be counterproductive and work to also grow and potential pool of adversaries. The means we have to arrest this growth is to reduce the appeal of mining and the most direct way to do that is to reduce the block reward.

## Backwards Compatibility
This EIP is consensus incompatible with the current public Ethereum chain and would cause a hard fork when enacted. The resulting fork would allow users to chose between two chains: a chain with a block reward of 1 ETH/block and another with a block reward of 3 ETH/block. This is a good choice to allow users to make. In addition, the difficulty bomb would be delayed - ensuring the network would not grind to a halt.

## Test Cases
Tests have, as yet, not been completed.

## Implementation
No implementation including both block reward and difficulty adjustment is currently available.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 29 Jan 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-858</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-858</guid>
      </item>
    
      <item>
        <title>Standardized Ethereum Recovery Proposals</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-867-standardized-ethereum-recovery-proposals-erps/139</comments>
        
        <description>## Simple Summary
Provide a standardized format for Ethereum Recovery Proposals (ERPs), which relate to recovery of certain classes of lost funds.  Individual ERPs will follow the same process as any EIP, but will be formatted and evaluated in a standard way to ensure consistency and transparency. 

**This EIP does not advocate for or against the acceptance of any particular recovery proposals, nor would its acceptance alone result in any state changes to the blockchain.**  

## Abstract
This proposal identifies a common solution method that can be used to address certain classes of lost funds on the Ethereum blockchain.  In particular, it is intended to address cases where there is no disagreement about the right outcome between directly affected parties, enabling timely and low-risk solutions to many issues that have already occurred or are likely to occur again as Ethereum grows.  

The solution method is divided into three parts:

1. Standards that will need to be met by any follow-on ERP in order to be considered for approval. 
2. Recommendations for a common format for ERPs to use to specify a set of corrective actions that can be interpreted by clients. 
3. Guidelines for client teams to implement code that can read, interpret, and apply the corrective actions at a specific block.  The set of possible corrective actions is intentionally limited to minimize risk associated with any ERP. 


## Motivation
The issue of fund recovery on the Ethereum blockchain is often controversial. Frozen fund recovery proposals are almost never successful due to the relatively ad-hoc nature of such requests and the subjectivity that is often required to evaluate the merits. This EIP attempts to remove these barriers by providing both a standardized format for fund recovery EIPs and an objective standard by which to measure future proposals.

## Specification
This EIP describes a common format to be used for a subclass of EIPs, referred to as ethereum recovery proposals (ERPs), that propose an irregular state change required to address a fund recovery scenario that cannot be addressed using the standard protocol.  Each ERP will reference this EIP will follow the guidelines set out here.  

The purpose of each ERP is (a) to clearly describe the issue to be corrected, (b) to describe why an irregular state change is both necessary and justified, and (c) to demonstrate that the proposed actions will achieve the ERP&apos;s objectives.  

Each ERP will be required to use a standard format to represent the set of proposed state changes and must include a verification script that can reliably generate those changes.  ERPs that do not meet (at least) these requirements will not be considered for approval.

Each ERP should contain the following items:

- **Preamble**: EIP (RFC 822) header containing metadata about the ERP, including the EIP number, a short title (44 character maximum), and the real names (and optional contact information) for each author.
- **Simple Summary**: A simplified and layman-accessible explanation of the ERP.
- **Detailed description**: A human-readable description of the proposed corrective actions and the criteria used to determine the proposed actions.  
- **Justification**: A concise description of why the corrective actions are both reasonable and unlikely to be challenged by any directly affected party.   
- **Verification script**: A machine-readable script that outputs one State Change Object. The script should clearly implement the selection and action generating logic outlined in the description such that reviewers can independently re-generate an identical State Change Object.  
- **State Change Object**: The output of the verification script and the input to the ethereum clients.  Primarily, it specifies the complete set of proposed state change actions. 
- **Appendix (optional)**: with supporting evidence. Attachments in the appendix may include documents verifying details specified as part of the recovery proposal description. 

 The following sections give more detailed descriptions of the expectations for the Justification, Verification Script, and the format of the State Change Object.

### Justification
A concise description of why this action is both reasonable (cannot be accomplished without an irregular state change) and unlikely to be challenged by a *directly* affected party. 

**Considerable example** (concise, includes supporting evidence, no negative impact): 
*A crowdsale run by XYZ incorrectly published the testnet address of their crowdsale contract to their public website at the start of their crowdsale on Jan 19, 2018.  501 ETH was sent by 328 users on the mainnet to the incorrect address between block 4,235,987 and 4,236,050.  See here for the testnet contract, and see here for the transactions to the same address on the mainnet.  See here for a statement made by XYZ on their website.  Because there is a contract at this address on the testnet and the corresponding nonce for the creator address has already been used on the mainnet, it is considered effectively impossible that anyone coincidentally holds the private key. We have verified that all transactions came from addresses with no associated code, so there should be no issue returning eth to the senders.*  

**Insufficient example** (not enough detail, no supporting evidence): 
*We accidentally put the wrong contract address up on our website.  Can you please refund any eth sent to 0x1234 back to the senders.  Thanks.*

**Unacceptable example** (not objective, one person’s word against another):
*I sent tokens to X for services and he did a lousy job.  I want my money back, but he won’t refund me.  Please help!!*

### Verification Script
A machine-readable script that outputs a single State Change Object. This script should be implemented so that it is easily audited by a reviewer. Verification scripts should be javascript files that may use the [web3.js](https://github.com/ethereum/web3.js/) library. 

There are a few guidelines for verification scripts:

- Scripts should always be written to be as concise as reasonably possible, and anyone executing the verification script should review it first to verify that it does not contain any unsafe operations. 
- No verification script should ever require an unlocked ethereum wallet 
- The script should hardcode the highest block included during execution (otherwise the results may differ between runs).

The purpose of the ERP Verification script is to unambiguously specify (through code) the criteria used to compute the set of State Change Actions.  The script’s output, as described above, will be the input used by all Ethereum clients.  Client teams should avoid manually pre-processing the artifact or using the artifact to simply guide changes in the code.  Instead, the artifact should be bundled with the client and processed directly by the client at the specified block. This will minimize the amount of client effort required for each ERP and help to ensure compatibility between clients. We anticipate that some ERP Verification scripts may be trivial, but we recommend their inclusion for consistency. 

### State Change Object
The State Change Object is a standard format that will be interpretable by all Ethereum clients.

It is a single JSON object containing the following fields:
- **erpId**: A string identifier for this ERP (likely the associated EIP number, e.g. “EIP-1234”).  This will be converted from ascii to a hex string, then added as extra data on the target block.
- **targetBlock**: The block at which the stateChange should be applied.  Clients would use this to determine when a set of state changes should occur
- **actions**: An array of State Change Actions.
- **metadata**
  - **sourceBlock**: The highest block considered by the script when it was run.
  - **version**: The version of the verification script when it was run.  

### State Change Actions
A State Change action is a JSON object that includes a “type” field and a set of “data” fields, where the contents of the data fields are dependent on the type and must follow the schema defined for that type.  This allows clients to support a limited set of operations initially and add more based on a subsequent EIP if needed.  Support for the following action types should be implemented by clients upon adoption of this EIP:  

#### weiTransfer
The `weiTransfer` action transfers ETH from one address to another.

*Data fields*

- **type** (*string*): `weiTransfer`
- **fromAddress** (*hex string*): The address from which ETH should be transferred
- **toAddress** (*hex string*): The address to which ETH should be sent
- **value** (*decimal string*): The amount of ETH to be transferred, in units of wei. The value must be a whole number greater than zero.


#### storeCode
The `storeCode` action stores the given code at the given address.

*Data fields*

- **type** (*string*): `storeCode`
- **toAddress** (*hex string*): The address to which the contract should be restored.  
- **expectedCodeHash** (*hex string*): the expected hash of the code already at the toAddress.The empty string should be used if no code is expected at the toAddress.  In all other cases, the “0x” prefix is optional.
- **code** (*hex string*): the new bytecode associated with the contract

### Appendix (Optional)
The appendix can include additional supporting evidence or attachments that will help reviewers understand or verify the claims made in the ERP.  

For the storeCode operation, it should include the proposed contract source (e.g. Solidity) as well as the other details required such that a reviewer can compile the source and generate the same bytecode.  It should also include the source that was originally stored at that address, if possible/applicable.  If the two contracts are not identical, changes should be noted. If they are identical, the author should indicate why no changes are necessary (this is unlikely). Additionally, any relevant reviews, audits, and test cases should be included to the extent that they address the issues encountered with the original contract.  

If accepted, an ERP could easily compile the block at while the changes are to take place, and the source of the actions (which would be the output of the script, in a standardized object output). These can be bundled with the client for seamless execution.


## ERP Approval Process
ERPs are a subclass of EIPs and will, therefore, follow the same approval process.    

### Testing
*The ERP authors are currently seeking feedback from client teams about the proper testing procedures* 

## Ethereum Client Implementation 
Clients that choose to adopt the proposal outlined in this EIP will implement a module that scans a designated directory for SCO files (each time the client process launches) to construct a mapping between target blocks and SCO file names.  When starting work on a new block, clients should first consult the set of SCO target blocks discovered and determine if there are any recovery actions required for the current block.  

E.g. in this example, `erpsByTargetBlock` is the mapping between the target block number associated with each ERP&apos;s State Change Object and a reference (i.e. file name) to the resource with the actual data.

```
if (erpsByTargetBlock.get(currentBlock) != null) {
    try {
        applyRecoveryActions(erpsByTargetBlock.get(currentBlock));
     }
     catch (e) {
        // recovery actions should be treated as a batch.  
        // If one fails, they all fail.
     }
}


// continue with normal block processing...
```

The `applyRecoveryActions` method must apply the recovery actions in the same order as they are stored in the SCO file.  Clients are responsible for ensuring that no State Change Action will result in an account transferring an amount that is greater than its current balance.  The `toAddress` for both `weiTransfer` and `storeCode` should always be a valid address (i.e. never `0x0`).

Additionally, each block affected by an ERP should include extra data to indicate that the state change occurred.  The extra data included in the block should be the erpId found in the SCO file, converted to hex (i.e. `hexStringToBytes(asciiToHex(erpId))`).  Clients should also validate that the expected header appears in the target block if the block is received from a peer.

The ERP should link to pull requests for each client repository, and these pull requests should link back to the ERP and also contain its EIP preamble and summary. 

Each PR associated with an ERP should consist of a single file (the SCO file) added to the client’s designated SCO directory.  No additional client code should be required.

### Limitations of this EIP

This EIP is focused on standardizing how recovery proposals can be formatted, to optimize readability and eliminate or minimize as much as possible the potential for mistakes or intentional abuses. 

The following are considered out of scope from this EIP:
- Which fund recovery proposals, if any, should be accepted for implementation. 
- How common classes of recovery proposal plaintiff may organize ERPs representing a collective group of individual parties 
 

## Rationale
The primary consideration for the approach described above was to minimize the amount of risk associated with recovery actions that would otherwise not have a viable solution.  A secondary consideration was to standardize the format used in the proposals for recovery actions.

First, including a verification script guarantees that the way in which the recovery actions were determined is unambiguous.  This does not mean that the recovery actions are necessarily correct, only that the logic used to determine them is fully specified and auditable.

Second, requiring that the output of the verification script is directly interpretable by client programs minimizes the work necessary for each client to adopt a particular ERP.  It also reduces the risk that two clients will make different decisions about the implementation of a particular ERP.

Third, action types are intentionally limited and inflexible, which reduces the likelihood of unintended consequences or maliciously constructed files affecting the blockchain state.  The format is easily extensible with new actions types if needed but that would require a separate EIP.


## Implementation
A reference implementation has been written for the EthereumJ platform. See the pull request [here](https://github.com/ethereum/ethereumj/pull/1004#commits-pushed-1105610).


## ERP Examples

This section will include examples and SCO resource files, as well as a brief tutorial on how to test using a private testnet. 


## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 02 Feb 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-867</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-867</guid>
      </item>
    
      <item>
        <title>Node Discovery v4 ENR Extension</title>
        <category>Standards Track/Networking</category>
        
          <comments>https://github.com/ethereum/devp2p/issues/44</comments>
        
        <description># Abstract

This EIP defines an extension to Node Discovery Protocol v4 to enable authoritative
resolution of [Ethereum Node Records (ENR)](/EIPs/EIPS/eip-778).

# Motivation

To bridge current and future discovery networks and to aid the implementation of other
relay mechanisms for ENR such as DNS, we need a way to request the most up-to-date version
of a node record. This EIP provides a way to request it using the existing discovery
protocol.

# Specification

Implementations of Node Discovery Protocol v4 should support two new packet types, a
request and reply of the node record. The existing ping and pong packets are extended with
a new field containing the sequence number of the ENR.

### Ping Packet (0x01)

```text
packet-data = [version, from, to, expiration, enr-seq]
```

`enr-seq` is the current sequence number of the sending node&apos;s record. All other fields
retain their existing meaning.

### Pong Packet (0x02)

```text
packet-data = [to, ping-hash, expiration, enr-seq]
```

`enr-seq` is the current sequence number of the sending node&apos;s record. All other fields
retain their existing meaning.

### ENRRequest Packet (0x05)

```text
packet-data = [ expiration ]
```

When a packet of this type is received, the node should reply with an ENRResponse packet
containing the current version of its record.

To guard against amplification attacks, the sender of ENRRequest should have replied to a
ping packet recently (just like for FindNode). The `expiration` field, a UNIX timestamp,
should be handled as for all other existing packets i.e. no reply should be sent if it
refers to a time in the past.

### ENRResponse Packet (0x06)

```text
packet-data = [ request-hash, ENR ]
```

This packet is the response to ENRRequest.

- `request-hash` is the hash of the entire ENRRequest packet being replied to.
- `ENR` is the node record.

The recipient of the packet should verify that the node record is signed by node who sent
ENRResponse.

## Resolving Records

To resolve the current record of a node public key, perform a recursive Kademlia lookup
using the FindNode, Neighbors packets. When the node is found, send ENRRequest to it and
return the record from the response.

# Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 02 Feb 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-868</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-868</guid>
      </item>
    
      <item>
        <title>Simpler NFT standard with batching and native atomic swaps</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/875</comments>
        
        <description>## Summary
A simple non fungible token standard that allows batching tokens into lots and settling p2p atomic transfers in one transaction. You can test out an example implementation on rinkeby here: https://rinkeby.etherscan.io/address/0xffab5ce7c012bc942f5ca0cd42c3c2e1ae5f0005 and view the repo here: https://github.com/alpha-wallet/ERC-Example

## Purpose
While other standards allow the user to transfer a non-fungible token, they require one transaction per token, this is heavy on gas and partially responsible for clogging the ethereum network. There are also few definitions for how to do a simple atomic swap.

## Rinkeby example
This standard has been implemented in an example contract on rinkeby: https://rinkeby.etherscan.io/address/0xffab5ce7c012bc942f5ca0cd42c3c2e1ae5f0005

## Specification

### function name() constant returns (string name)

returns the name of the contract e.g. CarLotContract

### function symbol() constant returns (string symbol)

Returns a short string of the symbol of the in-fungible token, this should be short and generic as each token is non-fungible.

### function balanceOf(address _owner) public view returns (uint256[] balance)

Returns an array of the users balance.

### function transfer(address _to, uint256[] _tokens) public;

Transfer your unique tokens to an address by adding an array of the token indices. This compares favourable to ERC721 as you can transfer a bulk of tokens in one go rather than one at a time. This has a big gas saving as well as being more convenient.

### function transferFrom(address _from, address _to, uint256[] _tokens) public;

Transfer a variable amount of tokens from one user to another. This can be done from an authorised party with a specified key e.g. contract owner.

## Optional functions

### function totalSupply() constant returns (uint256 totalSupply);

Returns the total amount of tokens in the given contract, this should be optional as assets might be allocated and issued on the fly. This means that supply is not always fixed.

### function ownerOf(uint256 _tokenId) public view returns (address _owner);

Returns the owner of a particular token, I think this should be optional as not every token contract will need to track the owner of a unique token and it costs gas to loop and map the token id owners each time the balances change.

### function trade(uint256 expiryTimeStamp, uint256[] tokenIndices, uint8 v, bytes32 r, bytes32 s) public payable

A function which allows a user to sell a batch of non-fungible tokens without paying for the gas fee (only the buyer has to) in a p2p atomic swap. This is achieved by signing an attestation containing the amount of tokens to sell, the contract address, an expiry timestamp, the price and a prefix containing the ERC spec name and chain id. A buyer can then pay for the deal in one transaction by attaching the appropriate ether to satisfy the deal.

This design is also more efficient as it allows orders to be done offline until settlement as opposed to creating orders in a smart contract and updating them. The expiry timestamp protects the seller against people using old orders.

This opens up the gates for a p2p atomic swap but should be optional to this standard as some may not have use for it.

Some protections need to be added to the message such as encoding the chain id, contract address and the ERC spec name to prevent replays and spoofing people into signing message that allow a trade.

## Interface

```solidity
contract ERC165 
{
            /// @notice Query if a contract implements an interface
            /// @param interfaceID The interface identifier, as specified in ERC-165
            /// @dev Interface identification is specified in ERC-165. This function
            ///  uses less than 30,000 gas.
            /// @return `true` if the contract implements `interfaceID` and
            ///  `interfaceID` is not 0xffffffff, `false` otherwise
            function supportsInterface(bytes4 interfaceID) external view returns (bool);
}

interface ERC875 /* is ERC165 */
{
  event Transfer(address indexed _from, address indexed _to, uint256[] tokenIndices);

  function name() constant public returns (string name);
  function symbol() constant public returns (string symbol);
  function balanceOf(address _owner) public view returns (uint256[] _balances);
  function transfer(address _to, uint256[] _tokens) public;
  function transferFrom(address _from, address _to, uint256[] _tokens) public;
}

//If you want the standard functions with atomic swap trading added
interface ERC875WithAtomicSwapTrading is ERC875 {
    function trade(
        uint256 expiryTimeStamp, 
        uint256[] tokenIndices,
        uint8 v, 
        bytes32 r, 
        bytes32 s
    ) public payable;
}
```

## Example implementation

Please visit this [repo](https://github.com/alpha-wallet/ERC875) to see an example implementation  

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 08 Feb 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-875</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-875</guid>
      </item>
    
      <item>
        <title>DGCL Token</title>
        <category>Standards Track/ERC</category>
        
        <description># Delaware General Corporations Law (DGCL) compatible share token

Ref: [proposing-an-eip-for-DGCL-tokens](https://forum.ethereum.org/discussion/17200/proposing-an-eip-for-regulation-a-Tokens)

## Simple Summary

An `ERC-20` compatible token that conforms to [Delaware State Senate, 149th General Assembly, Senate Bill No. 69: An act to Amend Title 8 of the Delaware Code Relating to the General Corporation Law](https://legis.delaware.gov/json/BillDetail/GenerateHtmlDocument?legislationId=25730&amp;legislationTypeId=1&amp;docTypeId=2&amp;legislationName=SB69), henceforth referred to as &apos;The Act&apos;.

## Abstract

The recently amended &apos;Title 8 of the Delaware Code Relating to the General Corporation Law&apos; now explicitly allows for the use of blockchains to maintain corporate share registries. This means it is now possible to create a tradable `ERC-20` token where each token represents a share issued by a Delaware corporation. Such a token must conform to the following principles over and above the `ERC-20` standard.

1. Token owners must have their identity verified.
2. The token contract must provide the following three functions of a `Corporations Stock ledger` (Ref: Section 224 of The Act):

    1. Reporting:

        It must enable the corporation to prepare the list of shareholders specified in Sections 219 and 220 of The Act.

    2. It must record the information specified in Sections 156, 159, 217(a) and 218 of The Act:

        - Partly paid shares
        - Total amount paid
        - Total amount to be paid

    3. Transfers of shares as per section 159 of The Act:

        It must record transfers of shares as governed by Article 8 of subtitle I of Title 6.

3. Each token MUST correspond to a single share, each of which would be paid for in full, so there is no need to record information concerning partly paid shares, and there are no partial tokens.

4. There must be a mechanism to allow a shareholder who has lost their private key, or otherwise lost access to their tokens to have their address `cancelled` and the tokens re-issued to a new address.

## Motivation

1. Delaware General Corporation Law requires that shares issued by a Delaware corporation be recorded in a share registry.
2. The share registry can be represented by an `ERC-20` token contract that is compliant with Delaware General Corporation Law.
3. This standard can cover equity issued by any Delaware corporation, whether private or public.

By using a `DGCL` compatible token, a firm may be able to raise funds via IPO, conforming to Delaware Corporations Law, but bypassing the need for involvement of a traditional Stock Exchange.

There are currently no token standards that conform to the `DGCL` rules. `ERC-20` tokens do not support KYC/AML rules required by the General Corporation Law, and do not provide facilities for the exporting of lists of shareholders.

### What about ERC-721?

The proposed standard could easily be used to enhance `ERC-721`, adding features for associating tokens with assets such as share certificates.

While the `ERC-721` token proposal allows for some association of metadata with an Ethereum address, its uses are _not completely aligned_ with The Act, and it is not, in its current form, fully `ERC-20` compatible.

## Specification

The `ERC-20` token provides the following basic features:

    contract ERC20 {
      function totalSupply() public view returns (uint256);
      function balanceOf(address who) public view returns (uint256);
      function transfer(address to, uint256 value) public returns (bool);
      function allowance(address owner, address spender) public view returns (uint256);
      function transferFrom(address from, address to, uint256 value) public returns (bool);
      function approve(address spender, uint256 value) public returns (bool);
      event Approval(address indexed owner, address indexed spender, uint256 value);
      event Transfer(address indexed from, address indexed to, uint256 value);
    }

This will be extended as follows:

    /**
     *  An `ERC20` compatible token that conforms to Delaware State Senate,
     *  149th General Assembly, Senate Bill No. 69: An act to Amend Title 8
     *  of the Delaware Code Relating to the General Corporation Law.
     *
     *  Implementation Details.
     *
     *  An implementation of this token standard SHOULD provide the following:
     *
     *  `name` - for use by wallets and exchanges.
     *  `symbol` - for use by wallets and exchanges.
     *
     *  The implementation MUST take care not to allow unauthorised access to
     *  share-transfer functions.
     *
     *  In addition to the above the following optional `ERC20` function MUST be defined.
     *
     *  `decimals` — MUST return `0` as each token represents a single share and shares are non-divisible.
     *
     *  @dev Ref https://github.com/ethereum/EIPs/pull/884
     */
    contract ERC884 is ERC20 {

        /**
         *  This event is emitted when a verified address and associated identity hash are
         *  added to the contract.
         *  @param addr The address that was added.
         *  @param hash The identity hash associated with the address.
         *  @param sender The address that caused the address to be added.
         */
        event VerifiedAddressAdded(
            address indexed addr,
            bytes32 hash,
            address indexed sender
        );

        /**
         *  This event is emitted when a verified address and associated identity hash are
         *  removed from the contract.
         *  @param addr The address that was removed.
         *  @param sender The address that caused the address to be removed.
         */
        event VerifiedAddressRemoved(address indexed addr, address indexed sender);

        /**
         *  This event is emitted when the identity hash associated with a verified address is updated.
         *  @param addr The address whose hash was updated.
         *  @param oldHash The identity hash that was associated with the address.
         *  @param hash The hash now associated with the address.
         *  @param sender The address that caused the hash to be updated.
         */
        event VerifiedAddressUpdated(
            address indexed addr,
            bytes32 oldHash,
            bytes32 hash,
            address indexed sender
        );

        /**
         *  This event is emitted when an address is cancelled and replaced with
         *  a new address.  This happens in the case where a shareholder has
         *  lost access to their original address and needs to have their share
         *  reissued to a new address.  This is the equivalent of issuing replacement
         *  share certificates.
         *  @param original The address being superseded.
         *  @param replacement The new address.
         *  @param sender The address that caused the address to be superseded.
         */
        event VerifiedAddressSuperseded(
            address indexed original,
            address indexed replacement,
            address indexed sender
        );

        /**
         *  Add a verified address, along with an associated verification hash to the contract.
         *  Upon successful addition of a verified address, the contract must emit
         *  `VerifiedAddressAdded(addr, hash, msg.sender)`.
         *  It MUST throw if the supplied address or hash are zero, or if the address has already been supplied.
         *  @param addr The address of the person represented by the supplied hash.
         *  @param hash A cryptographic hash of the address holder&apos;s verified information.
         */
        function addVerified(address addr, bytes32 hash) public;

        /**
         *  Remove a verified address, and the associated verification hash. If the address is
         *  unknown to the contract then this does nothing. If the address is successfully removed, this
         *  function must emit `VerifiedAddressRemoved(addr, msg.sender)`.
         *  It MUST throw if an attempt is made to remove a verifiedAddress that owns tokens.
         *  @param addr The verified address to be removed.
         */
        function removeVerified(address addr) public;

        /**
         *  Update the hash for a verified address known to the contract.
         *  Upon successful update of a verified address the contract must emit
         *  `VerifiedAddressUpdated(addr, oldHash, hash, msg.sender)`.
         *  If the hash is the same as the value already stored then
         *  no `VerifiedAddressUpdated` event is to be emitted.
         *  It MUST throw if the hash is zero, or if the address is unverified.
         *  @param addr The verified address of the person represented by the supplied hash.
         *  @param hash A new cryptographic hash of the address holder&apos;s updated verified information.
         */
        function updateVerified(address addr, bytes32 hash) public;

        /**
         *  Cancel the original address and reissue the tokens to the replacement address.
         *  Access to this function MUST be strictly controlled.
         *  The `original` address MUST be removed from the set of verified addresses.
         *  Throw if the `original` address supplied is not a shareholder.
         *  Throw if the `replacement` address is not a verified address.
         *  Throw if the `replacement` address already holds tokens.
         *  This function MUST emit the `VerifiedAddressSuperseded` event.
         *  @param original The address to be superseded. This address MUST NOT be reused.
         */
        function cancelAndReissue(address original, address replacement) public;

        /**
         *  The `transfer` function MUST NOT allow transfers to addresses that
         *  have not been verified and added to the contract.
         *  If the `to` address is not currently a shareholder then it MUST become one.
         *  If the transfer will reduce `msg.sender`&apos;s balance to 0 then that address
         *  MUST be removed from the list of shareholders.
         */
        function transfer(address to, uint256 value) public returns (bool);

        /**
         *  The `transferFrom` function MUST NOT allow transfers to addresses that
         *  have not been verified and added to the contract.
         *  If the `to` address is not currently a shareholder then it MUST become one.
         *  If the transfer will reduce `from`&apos;s balance to 0 then that address
         *  MUST be removed from the list of shareholders.
         */
        function transferFrom(address from, address to, uint256 value) public returns (bool);

        /**
         *  Tests that the supplied address is known to the contract.
         *  @param addr The address to test.
         *  @return true if the address is known to the contract.
         */
        function isVerified(address addr) public view returns (bool);

        /**
         *  Checks to see if the supplied address is a shareholder.
         *  @param addr The address to check.
         *  @return true if the supplied address owns a token.
         */
        function isHolder(address addr) public view returns (bool);

        /**
         *  Checks that the supplied hash is associated with the given address.
         *  @param addr The address to test.
         *  @param hash The hash to test.
         *  @return true if the hash matches the one supplied with the address in `addVerified`, or `updateVerified`.
         */
        function hasHash(address addr, bytes32 hash) public view returns (bool);

        /**
         *  The number of addresses that hold tokens.
         *  @return the number of unique addresses that hold tokens.
         */
        function holderCount() public view returns (uint);

        /**
         *  By counting the number of token holders using `holderCount`
         *  you can retrieve the complete list of token holders, one at a time.
         *  It MUST throw if `index &gt;= holderCount()`.
         *  @param index The zero-based index of the holder.
         *  @return the address of the token holder with the given index.
         */
        function holderAt(uint256 index) public view returns (address);

        /**
         *  Checks to see if the supplied address was superseded.
         *  @param addr The address to check.
         *  @return true if the supplied address was superseded by another address.
         */
        function isSuperseded(address addr) public view returns (bool);

        /**
         *  Gets the most recent address, given a superseded one.
         *  Addresses may be superseded multiple times, so this function needs to
         *  follow the chain of addresses until it reaches the final, verified address.
         *  @param addr The superseded address.
         *  @return the verified address that ultimately holds the share.
         */
        function getCurrentFor(address addr) public view returns (address);
    }

### Securities Exchange Commission Requirements

The Securities Exchange Commission (SEC) has additional requirements as to how a crowdsale ought to be run and what information must be made available to the general public. This information is however out of scope from this standard, though the standard does support the requirements.

For example: The SEC requires a crowdsale&apos;s website display the amount of money raised in US Dollars. To support this a crowdsale contract minting these tokens must maintain a USD to ETH conversion rate (via Oracle or some other mechanism) and must record the conversion rate used at time of minting.

Also, depending on the type of raise, the SEC (or other statutory body) can apply limits to the number of shareholders allowed. To support this the standard provides the `holderCount` and `isHolder` functions which a crowdsale can invoke to check that limits have not been exceeded.

### Use of the Identity `hash` value

Implementers of a crowdsale, in order to comply with The Act, must be able to produce an up-to-date list of the names and addresses of all shareholders. It is not desirable to include those details in a public blockchain, both for reasons of privacy, and also for reasons of economy. Storing arbitrary string data on the blockchain is strongly discouraged.

Implementers should maintain an off-chain private database that records the owner&apos;s name, residential address, and Ethereum address. The implementer must then be able to extract the name and address for any address, and hash the name + address data and compare that hash to the hash recorded in the contract using the `hasHash` function. The specific details of this system are left to the implementer.

It is also desirable that the implementers offer a REST API endpoint along the lines of

    GET https://&lt;host&gt;/&lt;pathPrefix&gt;/:ethereumAddress -&gt; [true|false]

to enable third party auditors to verify that a given Ethereum address is known to the implementers as a verified address.

How the implementers verify a person&apos;s identity is up to them and beyond the scope of this standard.

### Handling users who have lost access to their addresses

A traditional share register is typically managed by a Transfer Agent who is authorised to maintain the register accurately, and to handle shareholder enquiries. A common request is for share certificates to be reissued in the case where the shareholder has lost or destroyed their original.

Token implementers can handle that via the `cancelAndReissue` function, which must perform the various changes to ensure that the old address now points to the new one, and that cancelled addresses are not then reused.

### Permissions management

It is not desirable that anyone can add, remove, update, or supersede verified addresses. How access to these functions is controlled is outside of the scope of this standard.

## Rationale

The proposed standard offers as minimal an extension as possible over the existing `ERC-20` standard in order to conform to the requirements of The Act. Rather than return a `bool` for successful or unsuccessful completion of state-changing functions such as `addVerified`, `removeVerified`, and `updateVerified`, we have opted to require that implementations `throw` (preferably by using the [forthcoming `require(condition, &apos;fail message&apos;)` syntax](https://github.com/ethereum/solidity/issues/1686#issuecomment-328181514)).

## Backwards Compatibility

The proposed standard is designed to maintain compatibility with `ERC-20` tokens with the following provisos:

1. The `decimals` function MUST return `0` as the tokens MUST NOT be divisible,
2. The `transfer` and `transferFrom` functions MUST NOT allow transfers to non-verified addresses, and MUST maintain a list of shareholders.
3. Shareholders who transfer away their remaining tokens must be pruned from the list of shareholders.

Proviso 1 will not break compatibility with modern wallets or exchanges as they all appear to use that information if available.

Proviso 2 will cause transfers to fail if an attempt is made to transfer tokens to a non-verified address. This is implicit in the design and implementers are encouraged to make this abundantly clear to market participants. We appreciate that this will make the standard unpalatable to some exchanges, but it is an SEC requirement that shareholders of a corporation provide verified names and addresses.

Proviso 3 is an implementation detail.

## Test Cases and Reference Implementation

Test cases and a reference implementation are available at [github.com/davesag/ERC884-reference-implementation](https://github.com/davesag/ERC884-reference-implementation).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 14 Feb 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-884</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-884</guid>
      </item>
    
      <item>
        <title>DelegateProxy</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/pull/897</comments>
        
        <description>## Simple Summary
Proxy contracts are being increasingly used as both as an upgradeability mechanism
and a way to save gas when deploying many instances of a particular contract. This
standard proposes a set of interfaces for proxies to signal how they work and what
their main implementation is.

## Abstract
Using proxies that delegate their own logic to another contract is becoming an
increasingly popular technique for both smart contract upgradeability and creating
cheap clone contracts.

We don&apos;t believe there is value in standardizing any particular implementation
of a DelegateProxy, given its simplicity, but we believe there is a lot of value
in agreeing on an interface all proxies use that allows for a standard way to
operate with proxies.

## Implementations

- **aragonOS**: [AppProxyUpgradeable](https://github.com/aragon/aragonOS/blob/master/contracts/apps/AppProxyUpgradeable.sol), [AppProxyPinned](https://github.com/aragon/aragonOS/blob/master/contracts/apps/AppProxyPinned.sol) and [KernelProxy](https://github.com/aragon/aragonOS/blob/master/contracts/kernel/KernelProxy.sol)

- **zeppelinOS**: [Proxy](https://github.com/zeppelinos/labs/blob/2da9e859db81a61f2449d188e7193788ca721c65/upgradeability_ownership/contracts/Proxy.sol)

## Standardized interface

```solidity
interface ERCProxy {
  function proxyType() public pure returns (uint256 proxyTypeId);
  function implementation() public view returns (address codeAddr);
}
```

### Code address (`implementation()`)
The returned code address is the address the proxy would delegate calls to at that
moment in time, for that message.

### Proxy Type (`proxyType()`)

Checking the proxy type is the way to check whether a contract is a proxy at all.
When a contract fails to return to this method or it returns 0, it can be assumed
that the contract is not a proxy.

It also allows for communicating a bit more of information about how the proxy
operates. It is a pure function, therefore making it effectively constant as
it cannot return a different value depending on state changes.

- **Forwarding proxy** (`id = 1`): The proxy will always forward to the same code
address. The following invariant should always be true: once the proxy returns
a non-zero code address, that code address should never change.

- **Upgradeable proxy** (`id = 2`): The proxy code address can be changed depending
on some arbitrary logic implemented either at the proxy level or in its forwarded
logic.

## Benefits

- **Source code verification**: right now when checking the code of a proxy in explorers
like Etherscan, it just shows the code in the proxy itself but not the actual
code of the contract. By standardizing this construct, they will be able to show
both the actual ABI and code for the contract.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 21 Feb 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-897</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-897</guid>
      </item>
    
      <item>
        <title>Simple Staking Interface</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/900</comments>
        
        <description>## Abstract

The following standard describes a common staking interface allowing for easy to use staking systems. The interface is kept simple allowing for various use cases to be implemented. This standard describes the common functionality for staking as well as providing information on stakes.

## Motivation

As we move to more token models, having a common staking interface which is familiar to users can be useful. The common interface can be used by a variety of applications, this common interface could be beneficial especially to things like Token curated registries which have recently gained popularity.

## Specification

```solidity
interface Staking {

    event Staked(address indexed user, uint256 amount, uint256 total, bytes data);
    event Unstaked(address indexed user, uint256 amount, uint256 total, bytes data);

    function stake(uint256 amount, bytes data) public;
    function stakeFor(address user, uint256 amount, bytes data) public;
    function unstake(uint256 amount, bytes data) public;
    function totalStakedFor(address addr) public view returns (uint256);
    function totalStaked() public view returns (uint256);
    function token() public view returns (address);
    function supportsHistory() public pure returns (bool);

    // optional
    function lastStakedFor(address addr) public view returns (uint256);
    function totalStakedForAt(address addr, uint256 blockNumber) public view returns (uint256);
    function totalStakedAt(uint256 blockNumber) public view returns (uint256);
}
```

### stake

Stakes a certain amount of tokens, this MUST transfer the given amount from the user.

*The data field can be used to add signalling information in more complex staking applications*

MUST trigger ```Staked``` event.

### stakeFor

Stakes a certain amount of tokens, this MUST transfer the given amount from the caller.

*The data field can be used to add signalling information in more complex staking applications*

MUST trigger ```Staked``` event.

### unstake

Unstakes a certain amount of tokens, this SHOULD return the given amount of tokens to the user, if unstaking is currently not possible the function MUST revert.

*The data field can be used to remove signalling information in more complex staking applications*

MUST trigger ```Unstaked``` event.

### totalStakedFor

Returns the current total of tokens staked for an address.

### totalStaked

Returns the current total of tokens staked.

### token

Address of the token being used by the staking interface.

### supportsHistory

MUST return true if the optional history functions are implemented, otherwise false.

### lastStakedFor

***OPTIONAL:** As not all staking systems require a complete history, this function is optional.*

Returns last block address staked at.

### totalStakedForAt

***OPTIONAL:** As not all staking systems require a complete history, this function is optional.*

Returns total amount of tokens staked at block for address.

### totalStakedAt

***OPTIONAL:** As not all staking systems require a complete history, this function is optional.*

Returns the total tokens staked at block.

## Implementation

- [Stakebank](https://github.com/HarbourProject/stakebank)
- [Aragon](https://github.com/aragon/aragon-apps/pull/101)
- [PoS Staking](https://github.com/maticnetwork/contracts/blob/master/contracts/StakeManager.sol)
- [BasicStakeContract](https://github.com/codex-protocol/contract.erc-900)

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 22 Feb 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-900</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-900</guid>
      </item>
    
      <item>
        <title>Token Validation</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/update-on-erc902-validated-token/1639</comments>
        
        <description># Simple Summary
A protocol for services providing token ownership and transfer validation.

# Abstract
This standard provides a registry contract method for authorizing token transfers. By nature, this covers both initially issuing tokens to users (ie: transfer from contract to owner), transferring tokens between users, and token spends.

# Motivation
The tokenization of assets has wide application, not least of which is financial instruments such as securities and security tokens. Most jurisdictions have placed legal constraints on what may be traded, and who can hold such tokens which are regarded as securities. Broadly this includes KYC and AML validation, but may also include time-based spend limits, total volume of transactions, and so on.

Regulators and sanctioned third-party compliance agencies need some way to link off-chain compliance information such as identity and residency to an on-chain service. The application of this design is broader than legal regulation, encompassing all manner of business logic permissions for the creation, management, and trading of tokens.

Rather than each token maintaining its own whitelist (or other mechanism), it is preferable to share on-chain resources, rules, lists, and so on. There is also a desire to aggregate data and rules spread across multiple validators, or to apply complex behaviours (ex. switching logic, gates, state machines) to apply distributed data to an application.

# Specification

## `TokenValidator`

```solidity
interface TokenValidator {
    function check(
        address _token,
        address _subject
    ) public returns(byte statusCode)

    function check(
        address _token,
        address _from,
        address _to,
        uint256 _amount
    ) public returns (byte statusCode)
}
```

### Methods

#### `check`/2

`function check(address _token, address _subject) public returns (byte _resultCode)`

&gt; parameters
&gt; * `_token`: the token under review
&gt; * `_subject`: the user or contract to check
&gt;
&gt; *returns* an ERC1066 status code

#### `check`/4

`function check(address token, address from, address to, uint256 amount) public returns (byte resultCode)`

&gt; parameters
&gt; * `_token`: the token under review
&gt; * `_from`: in the case of a transfer, who is relinquishing token ownership
&gt; * `_to`: in the case of a transfer, who is accepting token ownership
&gt; * `_amount`: The number of tokens being transferred
&gt;
&gt; *returns* an ERC1066 status code

## `ValidatedToken`

```solidity
interface ValidatedToken {
    event Validation(
        address indexed subject,
        byte   indexed result
    )

    event Validation(
        address indexed from,
        address indexed to,
        uint256 value,
        byte   indexed statusCode
    )
}
```

### Events

#### `Validation`/2

`event Validation(address indexed subject, byte indexed resultCode)`

This event MUST be fired on return from a call to a `TokenValidator.check/2`.

&gt; parameters
&gt; * `subject`: the user or contract that was checked
&gt; * `statusCode`: an ERC1066 status code


#### `Validation`/4

```solidity
event Validation(
    address indexed from,
    address indexed to,
    uint256 amount,
    byte   indexed statusCode
)
```

This event MUST be fired on return from a call to a `TokenValidator.check/4`.

&gt; parameters
&gt; * `from`: in the case of a transfer, who is relinquishing token ownership
&gt; * `to`: in the case of a transfer, who is accepting token ownership
&gt; * `amount`: The number of tokens being transferred
&gt; * `statusCode`: an ERC1066 status code

# Rationale

This proposal includes a financial permissions system on top of any financial token. This design is not a general roles/permission system. In any system, the more you know about the context where a function will be called, the more powerful your function can be. By restricting ourselves to token transfers (ex. ERC20 or EIP-777), we can make assumptions about the use cases our validators will need to handle, and can make the API both small, useful, and extensible.

The events are fired by the calling token. Since `Validator`s may aggregate or delegate to other `Validator`s, it would generate a lot of useless events were it the
`Validator`&apos;s responsibility. This is also the reason why we include the `token` in the `call/4` arguments: a `Validator` cannot rely on `msg.sender` to determine the token that the call is concerning.

We have also seen a similar design from [R-Token](https://github.com/harborhq/r-token) that uses an additional field: `spender`. While there are potential use cases for this, it&apos;s not widely used enough to justify passing a dummy value along with every call. Instead, such a call would look more like this:

```solidity
function approve(address spender, uint amount) public returns (bool success) {
    if (validator.check(this, msg.sender, spender, amount) == okStatusCode) {
        allowed[msg.sender][spender] = amount;
        Approval(msg.sender, spender, amount);
        return true;
    } else {
        return false;
    }
}
```

A second `check/2` function is also required, that is more general-purpose, and does not specify a transfer amount or recipient. This is intended for general checks, such as checking roles (admin, owner, &amp;c), or if a user is on a simple whitelist.

We have left the decision to make associated `Validator` addresses public, private, or hardcoded up to the implementer. The proposed design does not include a centralized registry. It also does not include an interface for a `Validated` contract. A token may require one or many `Validator`s for different purposes, requiring different validations for different, or just a single `Validator`. The potential use cases are too varied to provide a single unified set of methods. We have provided a set of example contracts [here](https://github.com/Finhaven/ValidatedToken/) that may be inherited from for common use cases.

The status codes in the `byte` returns are unspecified. Any status code scheme may be used, though a general status code proposal is fortcoming.

By only defining the validation check, this standard is widely compatible with ERC-20, EIP-721, EIP-777, future token standards, centralized and decentralized exchanges, and so on.

# Implementation
[Reference implementation](https://github.com/expede/validated-token/)

# Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 14 Feb 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-902</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-902</guid>
      </item>
    
      <item>
        <title>Reward clients for a sustainable network</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-908-reward-full-nodes-and-clients/241</comments>
        
        <description>## A reward for running a full node is deprecated, but the proposal for a reward for clients remains

While Casper validators are incentivized to validate transactions, there are still no incentives for relaying blocks and storing data (which includes state). This paper is more a high-level analysis and discussion rather than attempting to provide a concrete solution. [Pocket Network](https://www.pokt.network/) is a separate blockchain being designed as of Sept 2018 that incentivises relaying transactions, that is intended to be compatible with other blockchains. Note also that [Rocket Pool](https://github.com/rocket-pool/rocketpool) is under development and is planned to be a pool for Casper, which will help to incentivise running a full node. Another alternative is [VIPnode](https://github.com/vipnode/vipnode.org) which charges fees to light clients for full nodes that serve them. In light of these solutions being developed, perhaps a more appropriate approach to generally rewarding clients would be to incentivize bandwidth (relaying and downloading), storage and I/O (while computation is already incentivized with gas for miners and will be for proposers under sharding and Casper). Note also that notaries will be incentivized to download collations under sharding. Outdated (Casper FFG will be implemented with Ethereum 2.0 with sharding: [shasper](https://notes.ethereum.org/SCIg8AH5SA-O4C1G1LYZHQ#)): given that it looks like Casper FFG will be implemented soon, to minimize undue complexity to the protocol, incentivizing validation in the mean time may be considered not worthwhile. For a previous version of the proposal containing a proposal for rewarding a full node, refer to [here](https://github.com/ethereum/EIPs/commit/97e235d0ba4a88b4ce29834aa2b94107b8d91e12#diff-9a43a8739b5a9e1dec427324cb264921).

## Simple Summary
When each transaction is validated, give a reward to clients for developing the client.

## Abstract
The tragedy of the commons is a phenomenon that is well known in many sectors, most notably in regard to sustainability. It involves the over-utilization of shared finite resources, which detriments all participants and stakeholders involved (which in the case of a global public good can be everyone, including future generations). Without proper management of public resources, a tragedy of the commons can occur. Internalizing externalities (where externalities can be broadly defined as effects that are not accounted for in the intrinsic price of a good, service or resource) is one way of incentivizing the proper management of resources, although other methods that actually properly manage them are necessary. This EIP proposes to make a change to the protocol to provide a reward to clients for providing the software that enables Ethereum to function, where the reward can include a proportion of transaction fees (reducing the full proportion that the miner currently receives), and some newly minted ETH. Thus, clients are incentivized to maintain and improve the security and health of the Ethereum protocol and ecosystem. To summarize the mechanism in the proposal, a user agent is attached to a transaction, where this user agent contains a vector with the index of a client address in an access list. The client address could be inserted by the client and verified that it is the same as a read-only constant in the client&apos;s storage. 

Reward mechanisms that are external to being built in to the protocol are beyond the scope of this EIP. Such extra-protocol reward methods include state channel payments for extra services such as light client servers providing faster information such as receipts; state channel payments for buying state reads from full nodes; archival services (which is only applicable to future proposed versions of Ethereum with stateless clients); and tokens for the client and running full nodes.

## Motivation
Currently there is a lack of incentives for anyone to run a full node, while joining a mining pool is not really economical if one has to purchase a mining rig (several GPUs) now, since there is unlikely to be a return on investment by the time that Ethereum transitions to hybrid Proof-of-Work/Proof-of-Stake with [Casper FFG](/EIPs/EIPS/eip-1011), then full PoS with [CBC Casper](https://github.com/ethereum/research/blob/master/papers/CasperTFG/CasperTFG.pdf).

Additionally, providing a reward for clients gives a revenue stream that is independent of state channels or other layer 2 mechanisms, which are less secure, although this insecurity can be offset by mechanisms such as insurance, bonded payments and time locks. Rationalising that investors may invest in a client because it is an enabler for the Ethereum ecosystem (and thus opening up investment opportunities) may not scale very well, and it seems that it is more sustainable to monetize the client as part of the service(s) that it provides. 

While it may be argued that the funds raised by the Ethereum pre-mine (the pre-ICO and the ICO) can be used to fund client development, that argument is questionable, since Parity is VC-funded, and other clients such as Prysmatic Labs [1](https://medium.com/@XYOracleNetwork?source=search_post), [2](https://twitter.com/prylabs/status/996391036753666050), [3](https://medium.com/prysmatic-labs/biweekly-development-update-2-d29d0c91e7d0) and [exthereum](https://medium.com/compound-finance/introducing-exthereum-the-newest-ethereum-client-7a5e30d4d6aa) have received funding from other parties, whereas perhaps they would not have needed to do so if there was sufficient funding from the Ethereum pre-mine funds. [Drops of Diamond](https://github.com/Drops-of-Diamond/diamond_drops) is yet to receive any funding.

Incentivizing client development would more directly incentivize resource provision in the protocol, preventing a tragedy of the commons, where there is an extreme lack of supply and excess demand, leading to the protocol being unusable. 

See [here](https://eprint.iacr.org/2014/452.pdf#subsection.2.1) for an analysis in the context of Bitcoin, PoW, and a hybrid PoW/PoS protocol. While Ethereum has a gas limit, the section points out that this is not enough as the market cap increases and the incentive to attack the network increases, while the ratio of security costs to transaction fees does not, while PoS will further alleviate the problem. However, the section points out that PoS is not enough, since the costs of propagating, verifying and storing transactions are not incentivised. Note that the &quot;Proof of Activity: Extending Bitcoin’s Proof of Work via Proof of Stake&quot; paper also contains a scheme for incentivizing a target participation level.

&gt; The word “activity” in the phrase Proof of  Activity emphasizes the point that only active stakeholders who maintain a full online node get rewarded, in exchange for the vital services that they provide for the network.  This stands in contrast to earlier Proof  of  Stake schemes in which offline stake can accumulate weight over time, and may ultimately be utilized in double-spending attacks.

We can also incentivize full nodes to propagate transactions and to store transactions or state, in addition to verifying them. While these first two incentivizations are outside the scope of this EIP, there are proposals [here](https://ethresear.ch/t/incentivizing-a-robust-p2p-network-relay-layer/1438) and [here](https://ethresear.ch/t/incentivizing-full-state-nodes/1640), respectively.

Implementing this as a layer 2 solution may not ensure the sustainability of the protocol, since not everyone would use it; if the protocol doesn&apos;t have any cost for full nodes to validate transactions, then people will take advantage of that and not use the layer 2 solution. It seems that you should at least have the part where the reward is provided in protocol, but then that and the user agent signature doesn&apos;t really add anything else to the protocol, so doing some part in-protocol and some part e.g. the verification or a verification-game off-protocol could be done, but it&apos;s already done in protocol. Note also that some computationally expensive tasks are too challenging to feasibly do in protocol, e.g. due to not fitting in the gas limit, could be done with Truebit, where verifiers have an incentive. 

Not providing incentives for clients is an issue now as there is less incentive to build a client that aligns with the needs of users, funds need to be raised externally to the protocol to fund client development, which is not as decentralized. If only a smaller subset is able to fund client development, such as VCs, angel investors and institutional investors, that may not align well with the interests of all current and potential stakeholders of Ethereum (which includes future stakeholders). Ostensibly, one of the goals of Ethereum is to decentralize everything, including wealth, or in other words, to improve wealth equality. Not providing incentives for full nodes validating transactions may not seem like as much of an issue now, but not doing so could hinder the growth of the protocol. Of course, incentives aren&apos;t enough, it also needs to be technically decentralized so that it is ideally possible for a low-end mainstream computer or perhaps even a mobile or embedded IoT device to be a verifying full node, or at least to be able to help with securing the network if it is deemed impractical for them to be a full node.

Note that with a supply cap (as in [EIP-960](https://github.com/ethereum/EIPs/issues/960), the issuance can be prevented from increasing indefinitely. Alternatively, it could at least be reduced (still potentially but not necessarily to zero, or to the same rate at which Ether is burnt when slashing participants, such as validators under a Casper PoS scheme or notaries under a sharding scheme), e.g. by hard forks, or as per [EIP-1015](/EIPs/EIPS/eip-1015), an on-chain contract governed by a decision assembly that gets signalling from other contracts that represent some set of stakeholders.

## Specification
Add a new field to each block called `PrevBlockVerifications`, which is an arbitrary, unlimited size byte array. When a client verifies that a previous block is [valid](https://ethereum.github.io/yellowpaper/paper.pdf#subsubsection.4.3.2), the client appends a user agent to PrevBlockVerifications via an opcode in a transaction, PREV_BLOCK_VERIF. The user agent is a vector with the  immutable fields: the blockhash of the block that is validated, and the index of a client address in an access list (details are below). A miner validates a transaction before including it in a block, however they are not able to change these fields of the vector because they&apos;re immutable.

Send 0.15 ETH to the client (see the rationale below), when the block is processed. The amounts could include a proportion of transaction fees (while the miner would then receive less), which would reduce newly issued ETH. These amounts are specified in new `ClientReward` fields in the block.

In order to only incentivize verifying recent blocks, assert that the block number corresponding to a blockhash is less than 400 blocks ago.

### Attacks and added specifications to prevent them

A miner could create a client and fill their block with transactions that only contain the PREV_BLOCK_VERIF opcode (or alternatively, arbitrarily complex transactions, still with the opcode), with previous blockhashes that they have validated and the address of their client. To prevent this, state would have to store a list containing lists, with each sublist listing the blockhashes up to 400 blocks ago that correspond to a miner, then a miner (or a proposer under Casper CBC) could have to put down a deposit, and be slashed if the proposer inserts such a transaction (that contains a blockhash which they have already proposed, not just in a block but at any time previously). Updating the state to remove blockhashes more than 400 blocks ago would add additional overhead, although you could add an extra window for older blocks, say 120,000 blocks (roughly every 3 weeks), still ignore blocks that are older than 400 blocks ago, and remove these older 120,000 blocks every 120,000 blocks. An attacker could bribe a miner/proposer to include transactions like above that contain an address of a client in the access list which they own. However, the above slashing condition should disincentivize this.

### More details on the access list

The access list prevents anyone inserting any address to the first element of the vector, where there may be a way to prevent censorship and centralization of authority of who decides to register new addresses in the list, e.g. on-chain governance with signalling (possibly similar to [EIP-1015](/EIPs/EIPS/eip-1015), which also specifies an alternative way of sending funds) or a layer 2 proof of authority network where new addresses can be added via a smart contract. Note that there may be serious drawbacks to implementing either of these listed examples. There is a refutation of [on-chain governance](https://medium.com/@Vlad_Zamfir/against-on-chain-governance-a4ceacd040ca) as well as of [plutocracy](https://vitalik.ca/general/2018/03/28/plutocracy.html). [Proof of Authority](https://en.wikipedia.org/wiki/Proof-of-authority) isn&apos;t suitable for a public network since it doesn&apos;t distribute trust well. However, using signalling in layer 2 contracts is more acceptable, but Vlad Zamfir argues that using that to influence outcomes in the protocol can disenfranchise miners from being necessary participants in the governance process. Thus, in light of these counterpoints, having an access list may not be suitable until a decentralized, trustless way of maintaining it is implemented and ideally accepted by the majority of a random sample that represents the population of Ethereum users.

However, another alternative to managing the access list would be to have decentralized verification that the address produced from querying an index in the access list does correspond to that of a &quot;legitimate&quot; client. Part of this verification would involve checking that there is a client that claims that this address is owned by them, that they are happy to receive funds in this manner and agree or arranged to putting the address in the access list, and that the client passes all tests in the [Ethereum test suite](https://github.com/ethereum/tests). However, this last proviso would then preclude new clients being funded from the start of development, although such would-be clients would not be able to receive funds in-protocol until they implement the client anyway (as an aside, they could raise funds in various ways—a DAII, pronounced die-yee, is recommended, while a platform for DAIIs is under development by [Dogezer](https://dogezer.com/)). All of this could be done off-chain, and if anyone found that some address in the access list was not legitimate, then they could challenge that address with a proof of illegitimacy, and the participant that submitted the address to the access list could be slashed (while they must hold a deposit in order to register and keep an address in the access list).

Additionally, it should help with being only able to read the client&apos;s address from the client, and the whole transaction could revert if the address is not in the access list. You could provide the index of the address in the access list, and then you could `assert` that the address found at that index matches that which can be read by the client (where the latter would be a read-only address).

## Rationale

### A rough qualitative analysis of fees 

As of May 4 2018, there are [16428 nodes](https://web.archive.org/web/20180504051128/https://ethernodes.org/network/1). Assume that an annual cost for an average client developer organisation is $1 million per annum. Projecting forward (and noting that the number of nodes should increase substantially if this EIP was implemented, thus aiding Ethereum&apos;s goal of decentralizing everything) assume that there are 10 clients. Thus let us assume that the number of nodes doubles to 30000 nodes within 5 years (this assumption is probably conservative, even if it is forward looking). Assume for simplicity that the costs of a client are entirely covered by this block reward.

Average cost per client = number of nodes * Block reward per client / number of clients

Block reward per client (worse case for ETH price) = Average revenue per client * number of clients / (ETH exchange rate * number of nodes)

= $2,000,000 * 10 / (500 * 30,000)

= 1.333333333 ETH

Block reward per client (better case) = $1,000,000 * 10 / (2000 * 30,000) = 0.166666667 ETH

Suppose that we use a block reward of 0.15 ETH for clients.

&lt;!--There are more than 5552465 blocks and counting. With a reward of 0.001 ETH for each block, a full state node that verified every block would receive 5552.465 ETH. However, the difficulty of verifying blocks increases over time, so--&gt;

### More rationale (outdated by above)

The amount of computation to validate a transaction will be the same as a miner, since the transaction will need to be executed. Thus, if there would be transaction fees for validating full nodes and clients, and transactions need to be executed by validators just like miners have to, it makes sense to have them calculated in the same way as gas fees for miners. This would controversially increase the amount of transaction fees a lot, since there can be many validators for a transaction. In other words, it is controversial whether to provide the same amount of transaction fee for a full node validator as for a miner (which in one respect is fair, since the validator has to do the same amount of computation), or prevent transaction fees from rising much higher, and have a transaction fee for a full node as, say, the transaction fee for a miner, divided by the average number of full nodes validating a transaction. The latter option seems even more controversial (but is still better than the status quo), since while there would be more of an incentive to run a full node than there is now with no incentive, validators would be paid less for performing the same amount of computation.

And as for the absolute amounts, this will require data analysis, but clearly a full node should receive much less than a miner for processing a transaction in a block, since there are many transactions in a block, and there are many confirmations of a block. Data analysis could involve calculating the average number of full nodes verifying transactions in a block. Macroeconomic analysis could entail the economic security benefit that full nodes provide to the network.

Now, as to the ratio of rewards to the client vs the full node, as an initial guess I would suggest something like 99:1. Why such a big difference? Well, I would guess that clients spend roughly 99 times more time on developing and maintaining the client than a full node user spends running and maintaining a full node. During a week there might be several full-time people working on the client, but a full node might only spend half an hour (or less) initially setting it up, plus running it, plus electricity and internet costs. Full node operators probably don&apos;t need to upgrade their computer (and buying a mining rig isn&apos;t worth it with Casper PoS planning on being implemented soon).

However, on further analysis, clients would also get the benefit of a large volume of rewards from every full node running the client, so to incentivise full node operation further, the ratio could change to say, 4:1, or even 1:1, and of course could be adjusted with even further actual data analysis, rather than speculation.

Providing rewards to full node validators and to clients would increase the issuance. In order to maintain the issuance at current levels, this EIP could also reduce the mining reward (despite being reduced previously with the Byzantium release in October 2017 from 5 ETH to 3 ETH), but that would generate more controversy and discussion.

Another potential point of controversy with rewarding clients and full nodes is that the work previously done by them has not been paid for until now (except of course by the Ethereum Foundation or Parity VCs funding the work), so existing clients may say that this EIP gives an advantage to new entrants. However, this doesn&apos;t hold up well, because existing clients have the first mover advantage, with much development to create useful and well-used products.

There is a tradeoff. Higher fees means you may cut out poor people and people who just don&apos;t want to pay fees. But if a laptop can run a full node and get paid for it then that would offset the fees through usage. Full nodes do provide a security benefit, so the total fees given could at least be some fraction of this benefit. Fees that go towards client development incentivise a higher quality client. To me, I think it makes more sense to internalize costs as much as possible: for computation, storage, bandwidth, I/O, client development, running full nodes, mining/validating, etc. You avoid a tragedy of the commons through externalizing costs. The more you internalize costs, the more sustainable it is, and the less you rely on rich people being generous, etc. (Although, getting philosophical, ultimately you can&apos;t force rich people to be generous, they have to do so out of the kindness of their hearts.)

Regarding rewards for full nodes, in the [draft phase 1 sharding spec](https://ethresear.ch/t/sharding-phase-1-spec/1407) proposers acting as full nodes have rewards for proposing blobs (without execution) or later in phase 3 transactions (with execution) to be included into collations/blocks. So that would help. However, full nodes that do not act as proposers and just verify transactions, or [full state nodes](https://ethresear.ch/t/incentivizing-full-state-nodes/1640), are still not incentivized.

Note that while further quantitative analysis to specify fees should be done, some level of experimentation after implementing this method on-chain may be necessary.

### Security
All of the below struck out information should be prevented via using an access list and verifying that the read-only address provided by the client matches with an address in the access list, as well as using a layer 2 solution such as a PoA network for censorship resistance and minimization of centralization in the access list.

Further discussion is at https://ethresear.ch/t/incentives-for-running-full-ethereum-nodes/1239.

## Backwards Compatibility

Introducing in-protocol fees is a backwards-incompatible change, so would be introduced in a hard-fork.

## Test Cases
TODO

## Implementation
TODO

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 01 Mar 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-908</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-908</guid>
      </item>
    
      <item>
        <title>Mineable Token Standard</title>
        <category>Standards Track/ERC</category>
        
        <description>### Simple Summary

A specification for a standardized Mineable Token that uses a Proof of Work algorithm for distribution. 

### Abstract

This specification describes a method for initially locking tokens within a token contract and slowly dispensing them with a mint() function which acts like a faucet. This mint() function uses a Proof of Work algorithm in order to minimize gas fees and control the distribution rate. Additionally, standardization of mineable tokens will give rise to standardized CPU and GPU token mining software, token mining pools and other external tools in the token mining ecosystem.

### Motivation

Token distribution via the ICO model and its derivatives is susceptible to illicit behavior by human actors. Furthermore, new token projects are centralized because a single entity must handle and control all of the initial coins and all of the raised ICO money.  By distributing tokens via an &apos;Initial Mining Offering&apos; (or IMO), the ownership of the token contract no longer belongs with the deployer at all and the deployer is &apos;just another user.&apos; As a result, investor risk exposure utilizing a mined token distribution model is significantly diminished. This standard is intended to be standalone, allowing maximum interoperability with ERC20, ERC721, and others.

### Specification

#### Interface
The general behavioral specification includes a primary function that defines the token minting operation, an optional merged minting operation for issuing multiple tokens, getters for challenge number, mining difficulty, mining target and current reward, and finally a Mint event, to be emitted upon successful solution validation and token issuance. At a minimum, contracts must adhere to this interface (save the optional merge operation). It is recommended that contracts interface with the more behaviorally defined Abstract Contract described below, in order to leverage a more defined construct, allowing for easier external implementations via overridden phased functions. (see &apos;Abstract Contract&apos; below)

``` solidity
interface ERC918  {
   
   function mint(uint256 nonce) public returns (bool success);

   function getAdjustmentInterval() public view returns (uint);

   function getChallengeNumber() public view returns (bytes32);

   function getMiningDifficulty() public view returns (uint);

   function getMiningTarget() public view returns (uint);

   function getMiningReward() public view returns (uint);
   
   function decimals() public view returns (uint8);

   event Mint(address indexed from, uint rewardAmount, uint epochCount, bytes32 newChallengeNumber);
}
```

#### Abstract Contract (Optional)

The Abstract Contract adheres to the EIP918 Interface and extends behavioral definition through the introduction of 4 internal phases of token mining and minting: hash, reward, epoch and adjust difficulty, all called during the mint() operation. This construct provides a balance between being too general for use while providing ample room for multiple mined implementation types.

### Fields

#### adjustmentInterval
The amount of time between difficulty adjustments in seconds.

``` solidity
bytes32 public adjustmentInterval;
```

#### challengeNumber
The current challenge number. It is expected that a new challenge number is generated after a new reward is minted.

``` solidity
bytes32 public challengeNumber;
```

#### difficulty
The current mining difficulty which should be adjusted via the \_adjustDifficulty minting phase

``` solidity
uint public difficulty;
```

#### tokensMinted
Cumulative counter of the total minted tokens, usually modified during the \_reward phase

``` solidity
uint public tokensMinted;
```

#### epochCount
Number of &apos;blocks&apos; mined

``` solidity
uint public epochCount;
```

### Mining Operations

#### mint

Returns a flag indicating a successful hash digest verification, and reward allocation to msg.sender. In order to prevent MiTM attacks, it is recommended that the digest include a recent Ethereum block hash and msg.sender&apos;s address. Once verified, the mint function calculates and delivers a mining reward to the sender and performs internal accounting operations on the contract&apos;s supply.

The mint operation exists as a public function that invokes 4 separate phases, represented as functions hash, \_reward, \_newEpoch, and \_adjustDifficulty. In order to create the most flexible implementation while adhering to a necessary contract protocol, it is recommended that token implementors override the internal methods, allowing the base contract to handle their execution via mint.

This externally facing function is called by miners to validate challenge digests, calculate reward,
populate statistics, mutate epoch variables and adjust the solution difficulty as required. Once complete,
a Mint event is emitted before returning a boolean success flag.

``` solidity
contract AbstractERC918 is EIP918Interface {

    // the amount of time between difficulty adjustments
    uint public adjustmentInterval;
     
    // generate a new challenge number after a new reward is minted
    bytes32 public challengeNumber;
    
    // the current mining target
    uint public miningTarget;

    // cumulative counter of the total minted tokens
    uint public tokensMinted;

    // number of blocks per difficulty readjustment
    uint public blocksPerReadjustment;

    //number of &apos;blocks&apos; mined
    uint public epochCount;
   
    /*
     * Externally facing mint function that is called by miners to validate challenge digests, calculate reward,
     * populate statistics, mutate epoch variables and adjust the solution difficulty as required. Once complete,
     * a Mint event is emitted before returning a success indicator.
     **/
    function mint(uint256 nonce) public returns (bool success) {
        require(msg.sender != address(0));

        // perform the hash function validation
        hash(nonce);
        
        // calculate the current reward
        uint rewardAmount = _reward();
        
        // increment the minted tokens amount
        tokensMinted += rewardAmount;
        
        epochCount = _epoch();

        //every so often, readjust difficulty. Don&apos;t readjust when deploying
        if(epochCount % blocksPerReadjustment == 0){
            _adjustDifficulty();
        }
       
        // send Mint event indicating a successful implementation
        emit Mint(msg.sender, rewardAmount, epochCount, challengeNumber);
        
        return true;
    }
}
```

##### *Mint Event*

Upon successful verification and reward the mint method dispatches a Mint Event indicating the reward address, the reward amount, the epoch count and newest challenge number.

``` solidity
event Mint(address indexed from, uint reward_amount, uint epochCount, bytes32 newChallengeNumber);
```

#### hash

Public interface function hash, meant to be overridden in implementation to define hashing algorithm and validation. Returns the validated digest

``` solidity
function hash(uint256 nonce) public returns (bytes32 digest);
```

#### \_reward

Internal interface function \_reward, meant to be overridden in implementation to calculate and allocate the reward amount. The reward amount must be returned by this method.

``` solidity
function _reward() internal returns (uint);
```

#### \_newEpoch

Internal interface function \_newEpoch, meant to be overridden in implementation to define a cutpoint for mutating mining variables in preparation for the next phase of mine.

``` solidity
function _newEpoch(uint256 nonce) internal returns (uint);
```
 
#### \_adjustDifficulty
 
Internal interface function \_adjustDifficulty, meant to be overridden in implementation to adjust the difficulty (via field difficulty) of the mining as required

``` solidity
function _adjustDifficulty() internal returns (uint);
```

#### getAdjustmentInterval

The amount of time, in seconds, between difficulty adjustment operations.

``` solidity
function getAdjustmentInterval() public view returns (uint);
```

#### getChallengeNumber

Recent ethereum block hash, used to prevent pre-mining future blocks.

``` solidity
function getChallengeNumber() public view returns (bytes32);
```

#### getMiningDifficulty

The number of digits that the digest of the PoW solution requires which typically auto adjusts during reward generation.

``` solidity
function getMiningDifficulty() public view returns (uint)
```

#### getMiningReward

Return the current reward amount. Depending on the algorithm, typically rewards are divided every reward era as tokens are mined to provide scarcity.

``` solidity
function getMiningReward() public view returns (uint)
```

### Example mining function
A general mining function written in python for finding a valid nonce for keccak256 mined token, is as follows: 
``` python
def generate_nonce():
  myhex =  b&apos;%064x&apos; % getrandbits(32*8)
  return codecs.decode(myhex, &apos;hex_codec&apos;)
  
def mine(challenge, public_address, difficulty):
  while True:
    nonce = generate_nonce()
    hash1 = int(sha3.keccak_256(challenge+public_address+nonce).hexdigest(), 16)
    if hash1 &lt; difficulty:
      return nonce, hash1
```

Once the nonce and hash1 are found, these are used to call the mint() function of the smart contract to receive a reward of tokens.

### Merged Mining Extension (Optional)
In order to provide support for merge mining multiple tokens, an optional merged mining extension can be implemented as part of the ERC918 standard. It is important to note that the following function will only properly work if the base contracts use tx.origin instead of msg.sender when applying rewards. If not the rewarded tokens will be sent to the calling contract and not the end user.

``` solidity
/**
 * @title ERC-918 Mineable Token Standard, optional merged mining functionality
 * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-918.md
 * 
 */
contract ERC918Merged is AbstractERC918 {
    /*
     * @notice Externally facing merge function that is called by miners to validate challenge digests, calculate reward,
     * populate statistics, mutate state variables and adjust the solution difficulty as required. Additionally, the
     * merge function takes an array of target token addresses to be used in merged rewards. Once complete,
     * a Mint event is emitted before returning a success indicator.
     *
     * @param _nonce the solution nonce
     **/
    function merge(uint256 _nonce, address[] _mineTokens) public returns (bool) {
      for (uint i = 0; i &lt; _mineTokens.length; i++) {
        address tokenAddress = _mineTokens[i];
        ERC918Interface(tokenAddress).mint(_nonce);
      }
    }

    /*
     * @notice Externally facing merge function kept for backwards compatibility with previous definition
     *
     * @param _nonce the solution nonce
     * @param _challenge_digest the keccak256 encoded challenge number + message sender + solution nonce
     **/
     function merge(uint256 _nonce, bytes32 _challenge_digest, address[] _mineTokens) public returns (bool) {
       //the challenge digest must match the expected
       bytes32 digest = keccak256( abi.encodePacked(challengeNumber, msg.sender, _nonce) );
       require(digest == _challenge_digest, &quot;Challenge digest does not match expected digest on token contract [ ERC918Merged.mint() ]&quot;);
       return merge(_nonce, _mineTokens);
     }
}
```

### Delegated Minting Extension (Optional)
In order to facilitate a third party minting submission paradigm, such as the case of miners submitting solutions to a pool operator and/or system, a delegated minting extension can be used to allow pool accounts submit solutions on the behalf of a user, so the miner can avoid directly paying Ethereum transaction costs. This is performed by an off chain mining account packaging and signing a standardized mint solution packet and sending it to a pool or 3rd party to be submitted.

The ERC918 Mineable Mint Packet Metadata should be prepared using following schema:
``` solidity
{
    &quot;title&quot;: &quot;Mineable Mint Packet Metadata&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;nonce&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Identifies the target solution nonce&quot;,
        },
        &quot;origin&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Identifies the original user that mined the solution nonce&quot;,
        },
        &quot;signature&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;The signed hash of tightly packed variables sha3(&apos;delegatedMintHashing(uint256,address)&apos;)+nonce+origin_account&quot;,
        }
    }
}
```
The preparation of a mineable mint packet on a JavaScript client would appear as follows:

``` solidity
function prepareDelegatedMintTxn(nonce, account) {
  var functionSig = web3.utils.sha3(&quot;delegatedMintHashing(uint256,address)&quot;).substring(0,10)
  var data = web3.utils.soliditySha3( functionSig, nonce, account.address )
  var sig = web3.eth.accounts.sign(web3.utils.toHex(data), account.privateKey )
  // prepare the mint packet
  var packet = {}
  packet.nonce = nonce
  packet.origin = account.address
  packet.signature = sig.signature
  // deliver resulting JSON packet to pool or third party
  var mineableMintPacket = JSON.stringify(packet, null, 4)
  /* todo: send mineableMintPacket to submitter */
  ...
}
```
Once the packet is prepared and formatted it can then be routed to a third party that will submit the transaction to the contract&apos;s delegatedMint() function, thereby paying for the transaction gas and receiving the resulting tokens. The pool/third party must then manually payback the minted tokens minus fees to the original minter.

The following code sample exemplifies third party packet relaying:
``` solidity
//received by minter
var mineableMintPacket = ...
var packet = JSON.parse(mineableMintPacket)
erc918MineableToken.delegatedMint(packet.nonce, packet.origin, packet.signature)
```
The Delegated Mint Extension expands upon ERC918 realized as a sub-contract:
``` js
import &apos;openzeppelin-solidity/contracts/contracts/cryptography/ECDSA.sol&apos;;

contract ERC918DelegatedMint is AbstractERC918, ECDSA {
   /**
     * @notice Hash (keccak256) of the payload used by delegatedMint
     * @param _nonce the golden nonce
     * @param _origin the original minter
     * @param _signature the original minter&apos;s elliptical curve signature
     */
    function delegatedMint(uint256 _nonce, address _origin, bytes _signature) public returns (bool success) {
        bytes32 hashedTx = delegatedMintHashing(_nonce, _origin);
        address minter = recover(hashedTx, _signature);
        require(minter == _origin, &quot;Origin minter address does not match recovered signature address [ AbstractERC918.delegatedMint() ]&quot;);
        require(minter != address(0), &quot;Invalid minter address recovered from signature [ ERC918DelegatedMint.delegatedMint() ]&quot;);
        success = mintInternal(_nonce, minter);
    }

    /**
     * @notice Hash (keccak256) of the payload used by delegatedMint
     * @param _nonce the golden nonce
     * @param _origin the original minter
     */
    function delegatedMintHashing(uint256 _nonce, address _origin) public pure returns (bytes32) {
        /* &quot;0x7b36737a&quot;: delegatedMintHashing(uint256,address) */
        return toEthSignedMessageHash(keccak256(abi.encodePacked( bytes4(0x7b36737a), _nonce, _origin)));
    }
}
```

### Mineable Token Metadata (Optional)
In order to provide for richer and potentially mutable metadata for a particular Mineable Token, it is more viable to offer an off-chain reference to said data. This requires the implementation of a single interface method &apos;metadataURI()&apos; that returns a JSON string encoded with the string fields symbol, name, description, website, image, and type.

Solidity interface for Mineable Token Metadata:
``` solidity
/**
 * @title ERC-918 Mineable Token Standard, optional metadata extension
 * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-918.md
 * 
 */
interface ERC918Metadata is AbstractERC918 {
    /**
     * @notice A distinct Uniform Resource Identifier (URI) for a mineable asset.
     */
    function metadataURI() external view returns (string);
}
```

Mineable Token Metadata JSON schema definition:
``` solidity
{
    &quot;title&quot;: &quot;Mineable Token Metadata&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;symbol&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Identifies the Mineable Token&apos;s symbol&quot;,
        },
        &quot;name&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Identifies the Mineable Token&apos;s name&quot;,
        },
        &quot;description&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Identifies the Mineable Token&apos;s long description&quot;,
        },
        &quot;website&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Identifies the Mineable Token&apos;s homepage URI&quot;,
        },
        &quot;image&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Identifies the Mineable Token&apos;s image URI&quot;,
        },
        &quot;type&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Identifies the Mineable Token&apos;s hash algorithm ( ie.keccak256 ) used to encode the solution&quot;,
        }
    }
}
```

### Rationale

The solidity keccak256 algorithm does not have to be used, but it is recommended since it is a cost effective one-way algorithm to perform in the EVM and simple to perform in solidity. The nonce is the solution that miners try to find and so it is part of the hashing algorithm. A challengeNumber is also part of the hash so that future blocks cannot be mined since it acts like a random piece of data that is not revealed until a mining round starts. The msg.sender address is part of the hash so that a nonce solution is valid only for a particular Ethereum account and so the solution is not susceptible to man-in-the-middle attacks. This also allows pools to operate without being easily cheated by the miners since pools can force miners to mine using the pool&apos;s address in the hash algorithm.  

The economics of transferring electricity and hardware into mined token assets offers a flourishing community of decentralized miners the option to be involved in the Ethereum token economy directly. By voting with hash power, an economically pegged asset to real-world resources, miners are incentivized to participate in early token trade to revamp initial costs, providing a bootstrapped stimulus mechanism between miners and early investors.

One community concern for mined tokens has been around energy use without a function for securing a network.  Although token mining does not secure a network, it serves the function of securing a community from corruption as it offers an alternative to centralized ICOs. Furthermore, an initial mining offering may last as little as a week, a day, or an hour at which point all of the tokens would have been minted.


### Backwards Compatibility
Earlier versions of this standard incorporated a redundant &apos;challenge_digest&apos; parameter on the mint() function that hash-encoded the packed variables challengeNumber, msg.sender and nonce. It was decided that this could be removed from the standard to help minimize processing and thereby gas usage during mint operations. However, in the name of interoperability with existing mining programs and pool software the following contract can be added to the inheritance tree:

``` solidity
/**
 * @title ERC-918 Mineable Token Standard, optional backwards compatibility function
 * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-918.md
 * 
 */
contract ERC918BackwardsCompatible is AbstractERC918 {

    /*
     * @notice Externally facing mint function kept for backwards compatibility with previous mint() definition
     * @param _nonce the solution nonce
     * @param _challenge_digest the keccak256 encoded challenge number + message sender + solution nonce
     **/
    function mint(uint256 _nonce, bytes32 _challenge_digest) public returns (bool success) {
        //the challenge digest must match the expected
        bytes32 digest = keccak256( abi.encodePacked(challengeNumber, msg.sender, _nonce) );
        require(digest == _challenge_digest, &quot;Challenge digest does not match expected digest on token contract [ AbstractERC918.mint() ]&quot;);
        success = mint(_nonce);
    }
}
```

### Test Cases
(Test cases for an implementation are mandatory for EIPs that are affecting consensus changes. Other EIPs can choose to include links to test cases if applicable.)


### Implementation

Simple Example:
https://github.com/0xbitcoin/EIP918-Mineable-Token/blob/master/contracts/SimpleERC918.sol

Complex Examples:

https://github.com/0xbitcoin/EIP918-Mineable-Token/blob/master/contracts/0xdogeExample.sol
https://github.com/0xbitcoin/EIP918-Mineable-Token/blob/master/contracts/0xdogeExample2.sol
https://github.com/0xbitcoin/EIP918-Mineable-Token/blob/master/contracts/0xBitcoinBase.sol

0xBitcoin Token Contract: 
https://etherscan.io/address/0xb6ed7644c69416d67b522e20bc294a9a9b405b31

MVI OpenCL Token Miner 
https://github.com/mining-visualizer/MVis-tokenminer/releases

PoWAdv Token Contract:
https://etherscan.io/address/0x1a136ae98b49b92841562b6574d1f3f5b0044e4c


### Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Wed, 07 Mar 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-918</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-918</guid>
      </item>
    
      <item>
        <title>Address metadata registry</title>
        <category>Standards Track/ERC</category>
        
        <description>## Abstract
This EIP specifies a registry for address metadata, permitting both contracts and external accounts to supply metadata about themselves to onchain and offchain callers. This permits use-cases such as generalised authorisations, providing token acceptance settings, and claims registries.

## Motivation
An increasing set of use cases require storage of metadata associated with an address; see for instance EIP 777 and EIP 780, and the ENS reverse registry in EIP 181. Presently each use-case defines its own specialised registry. To prevent a proliferation of special-purpose registry contracts, we instead propose a single standardised registry using an extendable architecture that allows future standards to implement their own metadata standards.

## Specification
The metadata registry has the following interface:
```solidity
interface AddressMetadataRegistry {
  function provider(address target) view returns(address);
  function setProvider(address _provider);
}
```

`setProvider` specifies the metadata registry to be associated with the caller&apos;s address, while `provider` returns the address of the metadata registry for the supplied address.

The metadata registry will be compiled with an agreed-upon version of Solidity and deployed using the trustless deployment mechanism to a fixed address that can be replicated across all chains.

## Provider specification

Providers may implement any subset of the metadata record types specified here. Where a record types specification requires a provider to provide multiple functions, the provider MUST implement either all or none of them. Providers MUST throw if called with an unsupported function ID.

Providers have one mandatory function:

```solidity
function supportsInterface(bytes4 interfaceID) constant returns (bool)
```

The `supportsInterface` function is documented in [EIP-165](/EIPs/EIPS/eip-165), and returns true if the provider implements the interface specified by the provided 4 byte identifier. An interface identifier consists of the XOR of the function signature hashes of the functions provided by that interface; in the degenerate case of single-function interfaces, it is simply equal to the signature hash of that function. If a provider returns `true` for `supportsInterface()`, it must implement the functions specified in that interface.

`supportsInterface` must always return true for `0x01ffc9a7`, which is the interface ID of `supportsInterface` itself.

The first argument to all provider functions MUST be the address being queried; this facilitates the creation of multi-user provider contracts.

Currently standardised provider interfaces are specified in the table below.

| Interface name | Interface hash | Specification |
| --- | --- | --- |

EIPs may define new interfaces to be added to this registry.

## Rationale
There are two obvious approaches for a generic metadata registry: the indirection approach employed here, or a generalised key/value store. While indirection incurs the cost of an additional contract call, and requires providers to change over time, it also provides for significantly enhanced flexibility over a key/value store; for that reason we selected this approach.

## Backwards Compatibility
There are no backwards compatibility concerns.

## Implementation
The canonical implementation of the metadata registry is as follows:
```solidity
contract AddressMetadataRegistry {
  mapping(address=&gt;address) public provider;
  
  function setProvider(address _provider) {
    provider[msg.sender] = _provider;
  }
}
```

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 12 Mar 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-926</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-926</guid>
      </item>
    
      <item>
        <title>Generalised authorisations</title>
        <category>Standards Track/ERC</category>
        
        <description>## Abstract
This EIP specifies a generic authorisation mechanism, which can be used to implement a variety of authorisation patterns, replacing approvals in ERC20, operators in ERC777, and bespoke authorisation patterns in a variety of other types of contract.

## Motivation
Smart contracts commonly need to provide an interface that allows a third-party caller to perform actions on behalf of a user. The most common example of this is token authorisations/operators, but other similar situations exist throughout the ecosystem, including for instance authorising operations on ENS domains. Typically each standard reinvents this system for themselves, leading to a large number of incompatible implementations of the same basic pattern. Here, we propose a generic method usable by all such contracts.

The pattern implemented here is inspired by [ds-auth](https://github.com/dapphub/ds-auth) and by OAuth.

## Specification
The generalised authorisation interface is implemented as a metadata provider, as specified in EIP 926. The following mandatory function is implemented:

```solidity
function canCall(address owner, address caller, address callee, bytes4 func) view returns(bool);
```

Where:
 - `owner` is the owner of the resource. If approved the function call is treated as being made by this address.
 - `caller` is the address making the present call.
 - `callee` is the address of the contract being called.
 - `func` is the 4-byte signature of the function being called.

For example, suppose Alice authorises Bob to transfer tokens on her behalf. When Bob does so, Alice is the `owner`, Bob is the `caller`, the token contract is the `callee`, and the function signature for the transfer function is `func`.

As this standard uses EIP 926, the authorisation flow is as follows:

 1. The callee contract fetches the provider for the `owner` address from the metadata registry contract, which resides at a well-known address.
 2. The callee contract calls `canCall()` with the parameters described above. If the function returns false, the callee reverts execution.

Commonly, providers will wish to supply a standardised interface for users to set and unset their own authorisations. They SHOULD implement the following interface:

```solidity
function authoriseCaller(address owner, address caller, address callee, bytes4 func);
function revokeCaller(address owner, address caller, address callee, bytes4 func);
```

Arguments have the same meaning as in `canCall`. Implementing contracts MUST ensure that `msg.sender` is authorised to call `authoriseCaller` or `revokeCaller` on behalf of `owner`; this MUST always be true if `owner == msg.sender`. Implementing contracts SHOULD use the standard specified here to determine if other callers may provide authorisations as well.

Implementing contracts SHOULD treat a `func` of 0 as authorising calls to all functions on `callee`. If `authorised` is `false` and `func` is 0, contracts need only clear any blanket authorisation; individual authorisations may remain in effect.

## Backwards Compatibility
There are no backwards compatibility concerns.

## Implementation
Example implementation TBD.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 12 Mar 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-927</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-927</guid>
      </item>
    
      <item>
        <title>Modifications to ethash to invalidate existing dedicated hardware implementations</title>
        <category>Standards Track/Core</category>
        
        <description>## Simple Summary

This EIP modifies ethash in order to break ASIC miners specialized for the current ethash
mining algorithm.


## Abstract

There are companies who currently have dedicated hardware based ethereum miners in
production, and may be actively mining.  This EIP aims to &quot;poison
the well&quot; by modifying the block mining algorithm in a low risk manner that
may *&quot;break&quot;* these miners if they are in-fact built as traditional ASICs.


## Motivation

ASIC-based miners will have lower operational costs than GPU-based miners, which
will result in GPU-based mining quickly becoming unprofitable.  Given that
production of ASIC-based miners has a high barrier to entry and few market players,
this will cause a trend towards centralization of mining power.

Risks include market dominance by a single manufacturer that may utilize production
stock to mine themselves, introduce backdoors in their hardware, or facilitate a 51%
attack that would otherwise be infeasible.

This trend towards centralization has a negative effect on network security,
putting significant control of the network in the hands of only a few entities.

Ethash remains ASIC-resistant, however ASIC manufacturer technology is advancing
and ethash may require further changes in order to remain resistant to unforeseen
design techniques. This EIP seeks explicitly to buy time during which newly-developed
ASIC technology will face a barrier while more long-term mechanisms to ensure
continued ASIC resistance can be explored.

## Specification

If `block.number &gt;= ASIC_MITIGATION_FORK_BLKNUM`, require that the ethash solution
sealing the block has been mined using `ethashV2`.

## EthashV2

`ethashV2` will be identical in specification to the current `ethash`(v1) algorithm, with
the exception of the implementation of `fnv`.

The new algorithm replaces the 5 current uses of `fnv` inside `hashimoto` with 5
separate instances defined as `fnvA`, `fnvB`, `fnvC`, `fnvD`, and `fnvE`, utilizing

``` c
FNV_PRIME_A=0x10001a7
FNV_PRIME_B=0x10001ab
FNV_PRIME_C=0x10001cf
FNV_PRIME_D=0x10001e3
FNV_PRIME_E=0x10001f9
```

`fnvA` replaces `fnv` in the DAG item selection step;
`fnvB` replaces `fnv` in the DAG item mix step;
`fnvC(fnvD(fnvE` replaces `fnv(fnv(fnv(` in the compress mix step.

`fnv` as utilized in DAG-item creation should remain unchanged.

## Agent Changes (Optional Variant)
 
The JSON-RPC `eth_GetWork` call may optionally return the proposed blocks algorithm.
While a miner or pool may infer the requirement for `ethashV2` based on the computed
epoch of the provided seedHash, it is beneficial to explicitly provide this
field so a miner does not require special configuration when mining on a chain
that chooses not to implement the `ASIC_Mitigation` hardfork.

Due to compatibility concerns with implementations that already add additional
parameters to `GetWork`, it is desired to add `BlockNumber` as an explicit 4th parameter
as suggested in https://github.com/ethereum/go-ethereum/issues/2333. Algorithm
should then be returned as either `&quot;ethash&quot;` or `&quot;ethashV2&quot;` according to the
`block.number &gt;= ASIC_MITIGATION_FORK_BLKNUM` criteria.
  
## Rationale

This EIP is aimed at breaking existing ASIC-based miners via small changes to the
existing ethash algorithm.  We hope to accomplish the following:

1. Break existing ASIC-based miners.
2. Demonstrate a willingness to fork in the event of future ASIC miner production.

Goal #1 is something that we can only do probabilistically without detailed
knowledge of existing ASIC miner design. The known released miner is available for
purchase [here](https://shop.bitmain.com/product/detail?pid=00020180403174908564M8dMJKtz06B7),
with delivery slated for mid-summer 2018.

Our approach should balance the inherent security risks involved with changing
the mining algorithm with the risk that the change we make does not break existing
ASIC miners.  This EIP leans towards minimizing the security risks by making minimal
changes to the algorithm, accepting the risk that the change may not break dedicated
hardware miners that utilize partially- or fully-configurable logic.

Furthermore, we do not wish to introduce significant algorithm changes that
may alter the power utilization or performance profile of existing GPU hardware.

The change of FNV constant is a minimal change that can be quickly
implemented across the various network node and miner implementations.

It is proposed that `ASIC_MITIGATION_FORK_BLKNUM` be no more than 5550000 (epoch 185), giving
around 30 days of notice to node and miner developers and a sufficient window
for formal analysis of the changes by experts. We must weigh this window against
the risk introduced by allowing ASICs that may exist to continue to propagate
on the network, as well as the risk of providing too much advanced warning to
ASIC developers.

It is further understood that this change will not prevent redesign of existing
dedicated hardware with new ASIC chips. The intention of this change is only
to disable currently active or mid-production hardware and provide time for
POS development as well as larger algorithm changes to be well analyzed by
experts.

The choice of FNV constants is made based on the formal specification at
https://tools.ietf.org/html/draft-eastlake-fnv-14#section-2.1

@goobur provided the following python code to output primes matching this criteria:

``` python
candidates = [2**24 + 2**8 + _ for _ in xrange(256)]
candidates = [_ for _ in candidates if is_prime(_)]
[&quot;0x%x&quot; % _ for _ in candidates if _ % (2**40 - 2**24 - 1) &gt; (2**24 + 2**8 + 2**7)]
```

The minimal prime constraint was relaxed, as has already been the case in `ethashV1`.

Typical ASIC synthesis tools would optimize multiplication of a constant
in the FNV algorithm, while reducing the area needed for the multiplier according
to the hamming weight of the constant. To reduce the chance of ASIC adaptation
through minor mask changes, we propose choosing new constants with a larger
hamming weight, however care should be taken not to choose constants with too
large of a weight.

The current FNV prime, `0x1000193`, has a hamming weight of 6.

``` c
HammingWeight(0x10001a7) = 7;
HammingWeight(0x10001ab) = 7;
HammingWeight(0x10001cf) = 8;
HammingWeight(0x10001e3) = 7;
HammingWeight(0x10001ef) = 9; // Not chosen
HammingWeight(0x10001f9) = 8;
HammingWeight(0x10001fb) = 9; // Not chosen
```

An analysis can be done regarding the dispersion of these constants as compared to
`0x01000193`, using the following snippet.

``` c
// https://eips.ethereum.org/EIPS/eip-969

#include &lt;stdlib.h&gt;
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;

int main() {
    u_int32_t candidate = 0;
    u_int32_t dups = 0;
    u_int32_t fnv_candidate = 0x10001a7; // MODIFY!
    u_int8_t *counts = malloc(0xFFFFFFFF);

    memset(counts, &apos;\0&apos;, 0xFFFFFFFF);

    for (candidate = 0; candidate &lt; 0xFFFFFFFF; candidate++) {
        u_int32_t result = (u_int32_t)(candidate * fnv_candidate);
        u_int8_t oldCount = counts[result];

        counts[result] = counts[result]+1;
        if (oldCount != 0) {
            dups++;
        }

        //// progress display: remove comment to speed down
        //if ((candidate &amp; 0xFFFFF) == 0xFFFFF) printf(&quot;0x%08x\n&quot;, candidate);
    }
    printf(&quot;\nFNV candidate 0x%08x : %i dups\n&quot;, fnv_candidate, dups);

    return 0;
}
```

It can be empirically confirmed that no more than 1 duplicate occurs in the
32-bit word space with these constants.

It is worth noting that FNV is not a cryptographic hash, and it is not used as
such in ethash. That said, a more invasive hash algorithm change could be considered.

One suggestion has been [MurmurHash3](https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp).

[Other suggestions have been made](https://twitter.com/el33th4xor/status/981292363627810818):
[Argon2](https://github.com/P-H-C/phc-winner-argon2),
[Equihash](https://blog.z.cash/why-equihash/) of Zcash fame, and
[Balloon Hashing](https://crypto.stanford.edu/balloon/).

Another possible candidate is [Cuckoo Cycle](https://github.com/tromp/cuckoo),
although there are some concerns regarding unaddressed optimization
vulnerabilities. One review can be found
[here](https://da-data.blogspot.com/2014/03/a-public-review-of-cuckoo-cycle.html).

This may be considered once the exact mechanism of the released ASICs is known and 
their effectiveness against its optimisations can be fully evaluated.


## Backwards Compatibility

This change implements a backwards incompatible change to proof of work based
block mining.  All existing miners will be required to update to clients which
implement this new algorithm, and all nodes will require updates to accept
solutions from the new proof of work algorithm.

## Test Cases

TODO: will need to generate test cases for `ethereum/tests` repository corresponding to the consensus
changes.

## Implementation

TODO

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 03 Apr 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-969</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-969</guid>
      </item>
    
      <item>
        <title>Composable Non-Fungible Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-998-composable-non-fungible-tokens-cnfts/387</comments>
        
        <description>## Abstract

An extension of the [ERC-721 standard](/EIPs/EIPS/eip-721) to enable ERC-721 tokens to own other ERC-721 tokens and [ERC-20](/EIPs/EIPS/eip-20) tokens.

An extension of the [ERC-20](/EIPs/EIPS/eip-20) and `ERC-223 https://github.com/ethereum/EIPs/issues/223` standards to enable ERC-20 and `ERC-223` tokens to be owned by ERC-721 tokens.

This specification covers four different kinds of composable tokens:

1. [`ERC998ERC721` top-down composable tokens that receive, hold and transfer ERC-721 tokens](#erc-721-top-down-composable)
2. [`ERC998ERC20` top-down composable tokens that receive, hold and transfer ERC-20 tokens](#erc-20-top-down-composable)
3. [`ERC998ERC721` bottom-up composable tokens that attach themselves to other ERC-721 tokens.](#erc-721-bottom-up-composable)
4. [`ERC998ERC20` bottom-up composable tokens that attach themselves to ERC-721 tokens.](#erc-20-bottom-up-composable)

which map to

1. An `ERC998ERC721` top-down composable is an ERC-721 token with additional functionality for owning other ERC-721 tokens. 
2. An `ERC998ERC20` top-down composable is an ERC-721 token with additional functionality for owning ERC-20 tokens. 
3. An `ERC998ERC721` bottom-up composable is an ERC-721 token with additional functionality for being owned by an ERC-721 token.
4. An `ERC998ERC20` bottom-up composable is an ERC-20 token with additional functionality for being owned by an ERC-721 token.

A top-down composable contract stores and keeps track of child tokens for each of its tokens.

A bottom-up composable contract stores and keeps track of a parent token for each its tokens.

With composable tokens it is possible to compose lists or trees of ERC-721 and ERC-20 tokens connected by ownership. Any such structure will have a single owner address at the root of the structure that is the owner of the entire composition. The entire composition can be transferred with one transaction by changing the root owner.

Different composables, top-down and bottom-up, have their advantages and disadvantages which are explained in the [Rational section](#rationale). It is possible for a token to be one or more kinds of composable token.

A non-fungible token is compliant and Composable of this EIP if it implements one or more of the following interfaces:

* `ERC998ERC721TopDown`
* `ERC998ERC20TopDown`
* `ERC998ERC721BottomUp`
* `ERC998ERC20BottomUp`

## Specification

### ERC-721

`ERC998ERC721` top-down, `ERC998ERC20` top-down, and `ERC998ERC721` bottom-up composable contracts must implement the [ERC-721 interface](/EIPs/EIPS/eip-721).

### ERC-20

`ERC998ERC20` bottom-up composable contracts must implement the [ERC-20 interface](/EIPs/EIPS/eip-20).

### [ERC-165](/EIPs/EIPS/eip-165)

The [ERC-165 standard](/EIPs/EIPS/eip-165) must be applied to each [ERC-998](/EIPs/EIPS/eip-998) interface that is used.

### Authentication

Authenticating whether a user or contract can execute some action works the same for both `ERC998ERC721` top-down and `ERC998ERC721` bottom-up composables.

A `rootOwner` refers to the owner address at the top of a tree of composables and ERC-721 tokens. 

Authentication within any composable is done by finding the rootOwner and comparing it to `msg.sender`, the return result of `getApproved(tokenId)` and the return result of `isApprovedForAll(rootOwner, msg.sender)`. If a match is found then authentication passes, otherwise authentication fails and the contract throws.

Here is an example of authentication code:

```solidity
address rootOwner = address(rootOwnerOf(_tokenId));
require(rootOwner == msg.sender || 
  isApprovedForAll(rootOwner,msg.sender) ||
  getApproved(tokenId) == msg.sender;
```

The `approve(address _approved, uint256 _tokenId)` and `getApproved(uint256 _tokenId)` ERC-721 functions are implemented specifically for the rootOwner. This enables a tree of composables to be transferred to a new rootOwner without worrying about which addresses have been approved in child composables, because any prior approves can only be used by the prior rootOwner.

Here are example implementations:

```solidity
function approve(address _approved, uint256 _tokenId) external {
  address rootOwner = address(rootOwnerOf(_tokenId));	
  require(rootOwner == msg.sender || isApprovedForAll(rootOwner,msg.sender));

  rootOwnerAndTokenIdToApprovedAddress[rootOwner][_tokenId] = _approved;
  emit Approval(rootOwner, _approved, _tokenId);
}

function getApproved(uint256 _tokenId) public view returns (address)  {
  address rootOwner = address(rootOwnerOf(_tokenId));
  return rootOwnerAndTokenIdToApprovedAddress[rootOwner][_tokenId];
}
```

### Traversal

The rootOwner of a composable is gotten by calling `rootOwnerOf(uint256 _tokenId)` or `rootOwnerOfChild(address _childContract, uint256 _childTokenId)`. These functions are used by top-down and bottom-up composables to traverse up the tree of composables and ERC-721 tokens to find the rootOwner.

`ERC998ERC721` top-down and bottom-up composables are interoperable with each other. It is possible for a top-down composable to own a bottom-up composable or for a top-down composable to own an ERC-721 token that owns a bottom-up token. In any configuration calling `rootOwnerOf(uint256 _tokenID)` on a composable will return the root owner address at the top of the ownership tree.

It is important to get the traversal logic of `rootOwnerOf` right. The logic for `rootOwnerOf` is the same whether or not a composable is bottom-up or top-down or both.
Here is the logic:

```
Logic for rootOwnerOf(uint256 _tokenId)

If the token is a bottom-up composable and has a parent token then call rootOwnerOf for the parent token.
    If the call was successful then the returned address is the rootOwner.
    Otherwise call rootOwnerOfChild for the parent token.
        If the call was successful then the returned address is the rootOwner.
        Otherwise get the owner address of the token and that is the rootOwner.
Otherwise call rootOwnerOfChild for the token
    If the call was successful then the returned address is the rootOwner.
    Otherwise get the owner address of the token and that is the rootOwner.
```

Calling `rootOwnerOfChild` for a token means the following logic:

```solidity
// Logic for calling rootOwnerOfChild for a tokenId
address tokenOwner = ownerOf(tokenId);
address childContract = address(this);
bytes32 rootOwner = ERC998ERC721(tokenOwner).rootOwnerOfChild(childContract, tokenId);
```

But understand that the real call to `rootOwnerOfChild` should be made with assembly so that the code can check if the call failed and so that the `staticcall` opcode is used to ensure that no state is modified.

Tokens/contracts that implement the above authentication and traversal functionality are &quot;composable aware&quot;.

### Composable Transfer Function Parameter Format

Composable functions that make transfers follow the same parameter format: **from:to:what**.

For example the `getChild(address _from, uint256 _tokenId, address _childContract, uint256 _childTokenId)` composable function transfers an ERC-721 token from an address to a top-down composable. The `_from` parameter is the **from**, the `_tokenId` parameter is the **to** and the `address _childContract, uint256 _childTokenId` parameters are the **what**.

Another example is the `safeTransferChild(uint256 _fromTokenId, address _to, address _childContract, uint256 _childTokenId)` function. The `_fromTokenId` is the **from**, the `_to` is the **to** and the `address _childContract, address _childTokenId` parameters are the **what**.

### transferFrom/safeTransferFrom Functions Do Not Transfer Tokens Owned By Tokens

In bottom-up and top-down composable contracts the `transferFrom` and `safeTransferFrom` functions must throw if they are called directly to transfer a token that is owned by another token.

The reason for this is that these functions do not explicitly specify which token owns a token to be transferred. [See the rational section for more information about this.](#explicit-transfer-parameters)

`transferFrom/safeTransferFrom` functions must be used to transfer tokens that are owned by an address.


### ERC-721 Top-Down Composable

ERC-721 top-down composables act as containers for ERC-721 tokens. 

ERC-721 top-down composables are ERC-721 tokens that can receive, hold and transfer ERC-721 tokens.

There are two ways to transfer a ERC-721 token to a top-down composable:

1. Use the `function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data)` function. The `_to` argument is the top-down composable contract address. The `bytes data` argument holds the integer value of the top-down composable tokenId that the ERC-721 token is transferred to.
2. Call `approve` in the ERC-721 token contract for the top-down composable contract. Then call `getChild` in the composable contract.

The first ways is for ERC-721 contracts that have a `safeTransferFrom` function. The second way is for contracts that do not have this function such as cryptokitties.

Here is an example of transferring ERC-721 token 3 from an address to top-down composable token 6:

```solidity
uint256 tokenId = 6;
bytes memory tokenIdBytes = new bytes(32);
assembly { mstore(add(tokenIdBytes, 32), tokenId) }
ERC721(contractAddress).safeTransferFrom(userAddress, composableAddress, 3, tokenIdBytes);
```

Every ERC-721 top-down composable compliant contract must implement the `ERC998ERC721TopDown` interface.

The `ERC998ERC721TopDownEnumerable` and `ERC998ERC20TopDownEnumerable` interfaces are optional.

```solidity
pragma solidity ^0.4.24;

/// @title `ERC998ERC721` Top-Down Composable Non-Fungible Token
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-998.md
///  Note: the ERC-165 identifier for this interface is 0xcde244d9
interface ERC998ERC721TopDown {

  /// @dev This emits when a token receives a child token.
  /// @param _from The prior owner of the token.
  /// @param _toTokenId The token that receives the child token.
  event ReceivedChild(
    address indexed _from, 
    uint256 indexed _toTokenId, 
    address indexed _childContract, 
    uint256 _childTokenId
  );
  
  /// @dev This emits when a child token is transferred from a token to an address.
  /// @param _fromTokenId The parent token that the child token is being transferred from.
  /// @param _to The new owner address of the child token.
  event TransferChild(
    uint256 indexed _fromTokenId, 
    address indexed _to, 
    address indexed _childContract, 
    uint256 _childTokenId
  );

  /// @notice Get the root owner of tokenId.
  /// @param _tokenId The token to query for a root owner address
  /// @return rootOwner The root owner at the top of tree of tokens and ERC-998 magic value.
  function rootOwnerOf(uint256 _tokenId) public view returns (bytes32 rootOwner);
  
  /// @notice Get the root owner of a child token.
  /// @param _childContract The contract address of the child token.
  /// @param _childTokenId The tokenId of the child.
  /// @return rootOwner The root owner at the top of tree of tokens and ERC-998 magic value.
  function rootOwnerOfChild(
    address _childContract, 
    uint256 _childTokenId
  ) 
    public 
    view
    returns (bytes32 rootOwner);
  
  /// @notice Get the parent tokenId of a child token.
  /// @param _childContract The contract address of the child token.
  /// @param _childTokenId The tokenId of the child.
  /// @return parentTokenOwner The parent address of the parent token and ERC-998 magic value
  /// @return parentTokenId The parent tokenId of _tokenId
  function ownerOfChild(
    address _childContract, 
    uint256 _childTokenId
  ) 
    external 
    view 
    returns (
      bytes32 parentTokenOwner, 
      uint256 parentTokenId
    );
  
  /// @notice A token receives a child token
  /// @param _operator The address that caused the transfer.
  /// @param _from The owner of the child token.
  /// @param _childTokenId The token that is being transferred to the parent.
  /// @param _data Up to the first 32 bytes contains an integer which is the receiving parent tokenId.  
  function onERC721Received(
    address _operator, 
    address _from, 
    uint256 _childTokenId, 
    bytes _data
  ) 
    external 
    returns(bytes4);
    
  /// @notice Transfer child token from top-down composable to address.
  /// @param _fromTokenId The owning token to transfer from.
  /// @param _to The address that receives the child token
  /// @param _childContract The ERC-721 contract of the child token.
  /// @param _childTokenId The tokenId of the token that is being transferred.
  function transferChild(
    uint256 _fromTokenId,
    address _to, 
    address _childContract, 
    uint256 _childTokenId
  ) 
    external;
  
  /// @notice Transfer child token from top-down composable to address.
  /// @param _fromTokenId The owning token to transfer from.
  /// @param _to The address that receives the child token
  /// @param _childContract The ERC-721 contract of the child token.
  /// @param _childTokenId The tokenId of the token that is being transferred.
  function safeTransferChild(
    uint256 _fromTokenId,
    address _to, 
    address _childContract, 
    uint256 _childTokenId
  ) 
    external;
  
  /// @notice Transfer child token from top-down composable to address.
  /// @param _fromTokenId The owning token to transfer from.
  /// @param _to The address that receives the child token
  /// @param _childContract The ERC-721 contract of the child token.
  /// @param _childTokenId The tokenId of the token that is being transferred.
  /// @param _data Additional data with no specified format
  function safeTransferChild(
    uint256 _fromTokenId,
    address _to, 
    address _childContract, 
    uint256 _childTokenId, 
    bytes _data
  ) 
    external;
  
  /// @notice Transfer bottom-up composable child token from top-down composable to other ERC-721 token.
  /// @param _fromTokenId The owning token to transfer from.
  /// @param _toContract The ERC-721 contract of the receiving token
  /// @param _toTokenId The receiving token  
  /// @param _childContract The bottom-up composable contract of the child token.
  /// @param _childTokenId The token that is being transferred.
  /// @param _data Additional data with no specified format
  function transferChildToParent(
    uint256 _fromTokenId, 
    address _toContract, 
    uint256 _toTokenId, 
    address _childContract, 
    uint256 _childTokenId, 
    bytes _data
  ) 
    external;
  
  /// @notice Get a child token from an ERC-721 contract.
  /// @param _from The address that owns the child token.
  /// @param _tokenId The token that becomes the parent owner
  /// @param _childContract The ERC-721 contract of the child token
  /// @param _childTokenId The tokenId of the child token
  function getChild(
    address _from, 
    uint256 _tokenId, 
    address _childContract, 
    uint256 _childTokenId
  ) 
    external;
}
```

#### `rootOwnerOf` 1

```solidity
/// @notice Get the root owner of tokenId.
/// @param _tokenId The token to query for a root owner address
/// @return rootOwner The root owner at the top of tree of tokens and ERC-998 magic value.
function rootOwnerOf(uint256 _tokenId) public view returns (bytes32 rootOwner);
```

This function traverses token owners until the root owner address of `_tokenId` is found.

The first 4 bytes of rootOwner contain the ERC-998 magic value `0xcd740db5`. The last 20 bytes contain the root owner address.

The magic value is returned because this function may be called on contracts when it is unknown if the contracts have a `rootOwnerOf` function. The magic value is used in such calls to ensure a valid return value is received.

If it is unknown whether a contract has the `rootOwnerOf` function then the first four bytes of the `rootOwner` return value must be compared to `0xcd740db5`. 

`0xcd740db5` is equal to:

```solidity
this.rootOwnerOf.selector ^ this.rootOwnerOfChild.selector ^ 
this.tokenOwnerOf.selector ^ this.ownerOfChild.selector;
```

Here is an example of a value returned by `rootOwnerOf`.
`0xcd740db50000000000000000e5240103e1ff986a2c8ae6b6728ffe0d9a395c59`

#### rootOwnerOfChild

```solidity
/// @notice Get the root owner of a child token.
/// @param _childContract The contract address of the child token.
/// @param _childTokenId The tokenId of the child.
/// @return rootOwner The root owner at the top of tree of tokens and ERC-998 magic value.
function rootOwnerOfChild(
  address _childContract, 
  uint256 _childTokenId
) 
  public 
  view 
  returns (bytes32 rootOwner);
```

This function traverses token owners until the root owner address of the supplied child token is found.

The first 4 bytes of rootOwner contain the ERC-998 magic value `0xcd740db5`. The last 20 bytes contain the root owner address.

The magic value is returned because this function may be called on contracts when it is unknown if the contracts have a `rootOwnerOf` function. The magic value is used in such calls to ensure a valid return value is received.

If it is unknown whether a contract has the `rootOwnerOfChild` function then the first four bytes of the `rootOwner` return value must be compared to `0xcd740db5`. 

#### ownerOfChild

```solidity
/// @notice Get the parent tokenId of a child token.
/// @param _childContract The contract address of the child token.
/// @param _childTokenId The tokenId of the child.
/// @return parentTokenOwner The parent address of the parent token and ERC-998 magic value
/// @return parentTokenId The parent tokenId of _tokenId
function ownerOfChild(
  address _childContract, 
  uint256 _childTokenId
) 
  external 
  view 
  returns (
    address parentTokenOwner, 
    uint256 parentTokenId
  );
```

This function is used to get the parent tokenId of a child token and get the owner address of the parent token.

The first 4 bytes of parentTokenOwner contain the ERC-998 magic value `0xcd740db5`. The last 20 bytes contain the parent token owner address.

The magic value is returned because this function may be called on contracts when it is unknown if the contracts have a `ownerOfChild` function. The magic value is used in such calls to ensure a valid return value is received.

If it is unknown whether a contract has the `ownerOfChild` function then the first four bytes of the `parentTokenOwner` return value must be compared to `0xcd740db5`. 

#### `onERC721Received`

```solidity
/// @notice A token receives a child token
/// @param _operator The address that caused the transfer.
/// @param _from The prior owner of the child token.
/// @param _childTokenId The token that is being transferred to the parent.
/// @param _data Up to the first 32 bytes contains an integer which is the receiving parent tokenId.  
function onERC721Received(
  address _operator, 
  address _from, 
  uint256 _childTokenId, 
  bytes _data
) 
  external 
  returns(bytes4);
```

This is a function defined in the ERC-721 standard. This function is called in an ERC-721 contract when `safeTransferFrom` is called. The `bytes _data` argument contains an integer value from 1 to 32 bytes long that is the parent tokenId that an ERC-721 token is transferred to. 

The `onERC721Received` function is how a top-down composable contract is notified that an ERC-721 token has been transferred to it and what tokenId in the top-down composable is the parent tokenId.

The return value for `onERC721Received` is the magic value `0x150b7a02` which is equal to `bytes4(keccak256(abi.encodePacked(&quot;onERC721Received(address,address,uint256,bytes)&quot;)))`.

#### transferChild

```solidity
/// @notice Transfer child token from top-down composable to address.
/// @param _fromTokenId The owning token to transfer from.
/// @param _to The address that receives the child token
/// @param _childContract The ERC-721 contract of the child token.
/// @param _childTokenId The tokenId of the token that is being transferred.
function transferChild(
  uint256 _fromTokenId,
  address _to, 
  address _childContract, 
  uint256 _childTokenId
) 
  external;
```

This function authenticates `msg.sender` and transfers a child token from a top-down composable to a different address. 

This function makes this call within it:

```solidity
ERC721(_childContract).transferFrom(this, _to, _childTokenId);
```

#### safeTransferChild 1

```solidity
/// @notice Transfer child token from top-down composable to address.
/// @param _fromTokenId The owning token to transfer from.
/// @param _to The address that receives the child token
/// @param _childContract The ERC-721 contract of the child token.
/// @param _childTokenId The tokenId of the token that is being transferred.
function safeTransferChild(
  uint256 _fromTokenId,
  address _to, 
  address _childContract, 
  uint256 _childTokenId
) 
  external;
```

This function authenticates `msg.sender` and transfers a child token from a top-down composable to a different address. 

This function makes this call within it:

```solidity
ERC721(_childContract).safeTransferFrom(this, _to, _childTokenId);
```

#### safeTransferChild 2

```solidity
/// @notice Transfer child token from top-down composable to address or other top-down composable.
/// @param _fromTokenId The owning token to transfer from.
/// @param _to The address that receives the child token
/// @param _childContract The ERC721 contract of the child token.
/// @param _childTokenId The tokenId of the token that is being transferred.
/// @param _data Additional data with no specified format, can be used to specify tokenId to transfer to
function safeTransferChild(
  uint256 _fromTokenId,
  address _to, 
  address _childContract, 
  uint256 _childTokenId, 
  bytes _data
) 
  external;
```

This function authenticates `msg.sender` and transfers a child token from a top-down composable to a different address or to a different top-down composable.

A child token is transferred to a different top-down composable if the `_to` address is a top-down composable contract and `bytes _data` is supplied an integer representing the parent tokenId.

This function makes this call within it: 

```solidity
ERC721(_childContract).safeTransferFrom(this, _to, _childTokenId, _data);
```

#### transferChildToParent

```solidity
/// @notice Transfer bottom-up composable child token from top-down composable to other ERC-721 token.
/// @param _fromTokenId The owning token to transfer from.
/// @param _toContract The ERC-721 contract of the receiving token
/// @param _toToken The receiving token  
/// @param _childContract The bottom-up composable contract of the child token.
/// @param _childTokenId The token that is being transferred.
/// @param _data Additional data with no specified format
function transferChildToParent(
  uint256 _fromTokenId, 
  address _toContract, 
  uint256 _toTokenId, 
  address _childContract, 
  uint256 _childTokenId, 
  bytes _data
) 
  external
```

This function authenticates `msg.sender` and transfers a child bottom-up composable token from a top-down composable to a different ERC-721 token. This function can only be used when the child token is a bottom-up composable token. It is designed to transfer a bottom-up composable token from a top-down composable to an ERC-721 token (bottom-up style) in one transaction.

This function makes this call within it:

```solidity
ERC998ERC721BottomUp(_childContract).transferToParent(
  address(this), 
  _toContract, 
  _toTokenId, 
  _childTokenId, 
  _data
);
```

#### getChild 

```solidity
/// @notice Get a child token from an ERC-721 contract.
/// @param _from The address that owns the child token.
/// @param _tokenId The token that becomes the parent owner
/// @param _childContract The ERC-721 contract of the child token
/// @param _childTokenId The tokenId of the child token
function getChild(
  address _from, 
  uint256 _tokenId, 
  address _childContract, 
  uint256 _childTokenId
) 
  external;
```

This function is used to transfer an ERC-721 token when its contract does not have a `safeTransferChild(uint256 _fromTokenId, address _to, address _childContract, uint256 _childTokenId, bytes _data)` function.

A transfer with this function is done in two steps:

1. The owner of the ERC-721 token calls `approve` or `setApprovalForAll` in the ERC-721 contract for the top-down composable contract.
2. The owner of the ERC-721 token calls `getChild` in the top-down composable contract for the ERC-721 token.

The `getChild` function must authenticate that `msg.sender` is the owner of the ERC-721 token in the ERC-721 contract or is approved or an operator of the ERC-721 token in the ERC-721 contract.

#### ERC-721 Top-Down Composable Enumeration

Optional interface for top-down composable enumeration:

```solidity
///  @dev The ERC-165 identifier for this interface is 0xa344afe4
interface ERC998ERC721TopDownEnumerable {

  /// @notice Get the total number of child contracts with tokens that are owned by tokenId.
  /// @param _tokenId The parent token of child tokens in child contracts
  /// @return uint256 The total number of child contracts with tokens owned by tokenId.
  function totalChildContracts(uint256 _tokenId) external view returns(uint256);
  
  /// @notice Get child contract by tokenId and index
  /// @param _tokenId The parent token of child tokens in child contract
  /// @param _index The index position of the child contract
  /// @return childContract The contract found at the tokenId and index.
  function childContractByIndex(
    uint256 _tokenId, 
    uint256 _index
  ) 
    external 
    view 
    returns (address childContract);
  
  /// @notice Get the total number of child tokens owned by tokenId that exist in a child contract.
  /// @param _tokenId The parent token of child tokens
  /// @param _childContract The child contract containing the child tokens
  /// @return uint256 The total number of child tokens found in child contract that are owned by tokenId.
  function totalChildTokens(
    uint256 _tokenId, 
    address _childContract
  ) 
    external 
    view 
    returns(uint256);
  
  /// @notice Get child token owned by tokenId, in child contract, at index position
  /// @param _tokenId The parent token of the child token
  /// @param _childContract The child contract of the child token
  /// @param _index The index position of the child token.
  /// @return childTokenId The child tokenId for the parent token, child token and index
  function childTokenByIndex(
    uint256 _tokenId, 
    address _childContract, 
    uint256 _index
  )
    external 
    view 
    returns (uint256 childTokenId);
}
```

### ERC-20 Top-Down Composable

ERC-20 top-down composables act as containers for ERC-20 tokens.
  
ERC-20 top-down composables are ERC-721 tokens that can receive, hold and transfer ERC-20 tokens.

There are two ways to transfer ERC-20 tokens to an ERC-20 Top-Down Composable:

1. Use the `transfer(address _to, uint256 _value, bytes _data);` function from the `ERC-223` contract. The `_to` argument is the ERC-20 top-down composable contract address. The `_value` argument is how many ERC-20 tokens to transfer. The `bytes` argument holds the integer value of the top-down composable tokenId that receives the ERC-20 tokens.
2. Call `approve` in the ERC-20 contract for the ERC-20 top-down composable contract. Then call `getERC20(address _from, uint256 _tokenId, address _erc20Contract, uint256 _value)` from the ERC-20 top-down composable contract.

The first way is for ERC-20 contracts that support the `ERC-223` standard. The second way is for contracts that do not.

ERC-20 top-down composables implement the following interface:
  
```solidity
/// @title `ERC998ERC20` Top-Down Composable Non-Fungible Token
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-998.md
///  Note: the ERC-165 identifier for this interface is 0x7294ffed
interface ERC998ERC20TopDown {

  /// @dev This emits when a token receives ERC-20 tokens.
  /// @param _from The prior owner of the token.
  /// @param _toTokenId The token that receives the ERC-20 tokens.
  /// @param _erc20Contract The ERC-20 contract.
  /// @param _value The number of ERC-20 tokens received.
  event ReceivedERC20(
    address indexed _from, 
    uint256 indexed _toTokenId, 
    address indexed _erc20Contract, 
    uint256 _value
  );
  
  /// @dev This emits when a token transfers ERC-20 tokens.
  /// @param _tokenId The token that owned the ERC-20 tokens.
  /// @param _to The address that receives the ERC-20 tokens.
  /// @param _erc20Contract The ERC-20 contract.
  /// @param _value The number of ERC-20 tokens transferred.
  event TransferERC20(
    uint256 indexed _fromTokenId, 
    address indexed _to, 
    address indexed _erc20Contract, 
    uint256 _value
  );

  /// @notice A token receives ERC-20 tokens
  /// @param _from The prior owner of the ERC-20 tokens
  /// @param _value The number of ERC-20 tokens received
  /// @param _data Up to the first 32 bytes contains an integer which is the receiving tokenId.  
  function tokenFallback(address _from, uint256 _value, bytes _data) external;
  
  /// @notice Look up the balance of ERC-20 tokens for a specific token and ERC-20 contract
  /// @param _tokenId The token that owns the ERC-20 tokens
  /// @param _erc20Contract The ERC-20 contract
  /// @return The number of ERC-20 tokens owned by a token from an ERC-20 contract
  function balanceOfERC20(
    uint256 _tokenId, 
    address _erc20Contract
  ) 
    external 
    view 
    returns(uint256);
  
  /// @notice Transfer ERC-20 tokens to address
  /// @param _tokenId The token to transfer from
  /// @param _value The address to send the ERC-20 tokens to
  /// @param _erc20Contract The ERC-20 contract
  /// @param _value The number of ERC-20 tokens to transfer
  function transferERC20(
    uint256 _tokenId, 
    address _to, 
    address _erc20Contract, 
    uint256 _value
  ) 
    external;
  
  /// @notice Transfer ERC-20 tokens to address or ERC-20 top-down composable
  /// @param _tokenId The token to transfer from
  /// @param _value The address to send the ERC-20 tokens to
  /// @param _erc223Contract The `ERC-223` token contract
  /// @param _value The number of ERC-20 tokens to transfer
  /// @param _data Additional data with no specified format, can be used to specify tokenId to transfer to
  function transferERC223(
    uint256 _tokenId, 
    address _to, 
    address _erc223Contract, 
    uint256 _value, 
    bytes _data
  )
    external;
  
  /// @notice Get ERC-20 tokens from ERC-20 contract.
  /// @param _from The current owner address of the ERC-20 tokens that are being transferred.
  /// @param _tokenId The token to transfer the ERC-20 tokens to.
  /// @param _erc20Contract The ERC-20 token contract
  /// @param _value The number of ERC-20 tokens to transfer  
  function getERC20(
    address _from, 
    uint256 _tokenId, 
    address _erc20Contract, 
    uint256 _value
  ) 
    external;
}
```

#### tokenFallback

```solidity
/// @notice A token receives ERC-20 tokens
/// @param _from The prior owner of the ERC-20 tokens
/// @param _value The number of ERC-20 tokens received
/// @param _data Up to the first 32 bytes contains an integer which is the receiving tokenId.  
function tokenFallback(address _from, uint256 _value, bytes _data) external;  
```

This function comes from the `ERC-223` which is an extension of the ERC-20 standard. This function is called on the receiving contract from the sending contract when ERC-20 tokens are transferred. This function is how the ERC-20 top-down composable contract gets notified that one of its tokens received ERC-20 tokens. Which token received ERC-20 tokens is specified in the `_data` parameter.

#### `balanceOfERC20`

```solidity
/// @notice Look up the balance of ERC-20 tokens for a specific token and ERC-20 contract
/// @param _tokenId The token that owns the ERC-20 tokens
/// @param _erc20Contract The ERC-20 contract
/// @return The number of ERC-20 tokens owned by a token from an ERC-20 contract
function balanceOfERC20(
  uint256 _tokenId, 
  address _erc20Contract
) 
  external 
  view 
  returns(uint256);
```

Gets the balance of ERC-20 tokens owned by a token from a specific ERC-20 contract.

#### `transferERC20`

```solidity
/// @notice Transfer ERC-20 tokens to address
/// @param _tokenId The token to transfer from
/// @param _value The address to send the ERC-20 tokens to
/// @param _erc20Contract The ERC-20 contract
/// @param _value The number of ERC-20 tokens to transfer
function transferERC20(
  uint256 _tokenId, 
  address _to, 
  address _erc20Contract, 
  uint256 _value
)
  external;
```

This is used to transfer ERC-20 tokens from a token to an address. This function calls `ERC20(_erc20Contract).transfer(_to, _value)`;

This function must authenticate `msg.sender`.

#### `transferERC223`

```solidity
  /// @notice Transfer ERC-20 tokens to address or ERC-20 top-down composable
  /// @param _tokenId The token to transfer from
  /// @param _value The address to send the ERC-20 tokens to
  /// @param _erc223Contract The `ERC-223` token contract
  /// @param _value The number of ERC-20 tokens to transfer
  /// @param _data Additional data with no specified format, can be used to specify tokenId to transfer to
  function transferERC223(
    uint256 _tokenId, 
    address _to, 
    address _erc223Contract, 
    uint256 _value, 
    bytes _data
  )
    external;
```

This function is from the `ERC-223`. It is used to transfer ERC-20 tokens from a token to an address or to another token by putting an integer token value in the `_data` argument.

This function must authenticate `msg.sender`.

#### `getERC20`

```solidity
/// @notice Get ERC-20 tokens from ERC-20 contract.
/// @param _from The current owner address of the ERC-20 tokens that are being transferred.
/// @param _tokenId The token to transfer the ERC-20 tokens to.
/// @param _erc20Contract The ERC-20 token contract
/// @param _value The number of ERC-20 tokens to transfer  
function getERC20(
  address _from, 
  uint256 _tokenId, 
  address _erc20Contract, 
  uint256 _value
) 
  external;
```

This function is used to transfer ERC-20 tokens to an ERC-20 top-down composable when an ERC-20 contract does not have a `transferERC223(uint256 _tokenId, address _to, address _erc223Contract, uint256 _value, bytes _data)` function.

Before this function can be used the ERC-20 top-down composable contract address must be approved in the ERC-20 contract to transfer the ERC-20 tokens.

This function must authenticate that `msg.sender` equals `_from` or has been approved in the ERC-20 contract.

#### ERC-20 Top-Down Composable Enumeration

Optional interface for top-down composable enumeration:

```solidity
/// @dev The ERC-165 identifier for this interface is 0xc5fd96cd
interface ERC998ERC20TopDownEnumerable {
  
  /// @notice Get the number of ERC-20 contracts that token owns ERC-20 tokens from
  /// @param _tokenId The token that owns ERC-20 tokens.
  /// @return uint256 The number of ERC-20 contracts
  function totalERC20Contracts(uint256 _tokenId) external view returns(uint256);
  
  /// @notice Get an ERC-20 contract that token owns ERC-20 tokens from by index
  /// @param _tokenId The token that owns ERC-20 tokens.
  /// @param _index The index position of the ERC-20 contract.
  /// @return address The ERC-20 contract
  function erc20ContractByIndex(
    uint256 _tokenId, 
    uint256 _index
  ) 
    external 
    view 
    returns(address);
}
```

### ERC-721 Bottom-Up Composable

ERC-721 bottom-up composables are ERC-721 tokens that attach themselves to other ERC-721 tokens.

ERC-721 bottom-up composable contracts store the owning address of a token and the parent tokenId if any.

```solidity
/// @title `ERC998ERC721` Bottom-Up Composable Non-Fungible Token
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-998.md
///  Note: the ERC-165 identifier for this interface is 0xa1b23002
interface ERC998ERC721BottomUp {

  /// @dev This emits when a token is transferred to an ERC-721 token
  /// @param _toContract The contract the token is transferred to
  /// @param _toTokenId The token the token is transferred to
  /// @param _tokenId The token that is transferred  
  event TransferToParent(
    address indexed _toContract, 
    uint256 indexed _toTokenId, 
    uint256 _tokenId
  );
  
  /// @dev This emits when a token is transferred from an ERC-721 token
  /// @param _fromContract The contract the token is transferred from
  /// @param _fromTokenId The token the token is transferred from
  /// @param _tokenId The token that is transferred  
  event TransferFromParent(
    address indexed _fromContract, 
    uint256 indexed _fromTokenId, 
    uint256 _tokenId
  );
  
  /// @notice Get the root owner of tokenId.
  /// @param _tokenId The token to query for a root owner address
  /// @return rootOwner The root owner at the top of tree of tokens and ERC-998 magic value.
  function rootOwnerOf(uint256 _tokenId) external view returns (bytes32 rootOwner);

  /// @notice Get the owner address and parent token (if there is one) of a token
  /// @param _tokenId The tokenId to query.
  /// @return tokenOwner The owner address of the token
  /// @return parentTokenId The parent owner of the token and ERC-998 magic value
  /// @return isParent True if parentTokenId is a valid parent tokenId and false if there is no parent tokenId
  function tokenOwnerOf(
    uint256 _tokenId
  )
    external 
    view
    returns (
      bytes32 tokenOwner, 
      uint256 parentTokenId, 
      bool isParent
    );
 
  /// @notice Transfer token from owner address to a token
  /// @param _from The owner address
  /// @param _toContract The ERC-721 contract of the receiving token
  /// @param _toToken The receiving token
  /// @param _data Additional data with no specified format
  function transferToParent(
    address _from, 
    address _toContract, 
    uint256 _toTokenId, 
    uint256 _tokenId, 
    bytes _data
  )
    external;
   
  /// @notice Transfer token from a token to an address
  /// @param _fromContract The address of the owning contract
  /// @param _fromTokenId The owning token
  /// @param _to The address the token is transferred to.
  /// @param _tokenId The token that is transferred
  /// @param _data Additional data with no specified format
  function transferFromParent(
    address _fromContract, 
    uint256 _fromTokenId, 
    address _to, 
    uint256 _tokenId, 
    bytes _data
  )
    external;
  
  /// @notice Transfer a token from a token to another token
  /// @param _fromContract The address of the owning contract
  /// @param _fromTokenId The owning token
  /// @param _toContract The ERC-721 contract of the receiving token
  /// @param _toToken The receiving token
  /// @param _tokenId The token that is transferred
  /// @param _data Additional data with no specified format
  function transferAsChild(
    address _fromContract, 
    uint256 _fromTokenId, 
    address _toContract, 
    uint256 _toTokenId, 
    uint256 _tokenId, 
    bytes _data
  )
    external;
}
```

#### `rootOwnerOf`

```solidity
/// @notice Get the root owner of tokenId.
/// @param _tokenId The token to query for a root owner address
/// @return rootOwner The root owner at the top of tree of tokens and ERC-998 magic value.
function rootOwnerOf(uint256 _tokenId) public view returns (bytes32 rootOwner);
```

This function traverses token owners until the root owner address of `_tokenId` is found.

The first 4 bytes of rootOwner contain the ERC-998 magic value `0xcd740db5`. The last 20 bytes contain the root owner address.

The magic value is returned because this function may be called on contracts when it is unknown if the contracts have a `rootOwnerOf` function. The magic value is used in such calls to ensure a valid return value is received.

If it is unknown whether a contract has the `rootOwnerOf` function then the first four bytes of the `rootOwner` return value must be compared to `0xcd740db5`. 

`0xcd740db5` is equal to:

```solidity
this.rootOwnerOf.selector ^ this.rootOwnerOfChild.selector ^ 
this.tokenOwnerOf.selector ^ this.ownerOfChild.selector;
```

Here is an example of a value returned by `rootOwnerOf`.
`0xcd740db50000000000000000e5240103e1ff986a2c8ae6b6728ffe0d9a395c59`

#### tokenOwnerOf

```solidity
/// @notice Get the owner address and parent token (if there is one) of a token
/// @param _tokenId The tokenId to query.
/// @return tokenOwner The owner address of the token and ERC-998 magic value.
/// @return parentTokenId The parent owner of the token
/// @return isParent True if parentTokenId is a valid parent tokenId and false if there is no parent tokenId
function tokenOwnerOf(
  uint256 _tokenId
)
  external 
  view 
  returns (
    bytes32 tokenOwner, 
    uint256 parentTokenId, 
    bool isParent
  );
```

This function is used to get the owning address and parent tokenId of a token if there is one stored in the contract.

If `isParent` is true then `tokenOwner` is the owning ERC-721 contract address and `parentTokenId` is a valid parent tokenId. If `isParent` is false then `tokenOwner` is a user address and `parentTokenId` does not contain a valid parent tokenId and must be ignored.

The first 4 bytes of `tokenOwner` contain the ERC-998 magic value `0xcd740db5`. The last 20 bytes contain the token owner address.

The magic value is returned because this function may be called on contracts when it is unknown if the contracts have a `tokenOwnerOf` function. The magic value is used in such calls to ensure a valid return value is received.

If it is unknown whether a contract has the `rootOwnerOf` function then the first four bytes of the `tokenOwner` return value must be compared to `0xcd740db5`. 

#### transferToParent

```solidity
/// @notice Transfer token from owner address to a token
/// @param _from The owner address
/// @param _toContract The ERC-721 contract of the receiving token
/// @param _toToken The receiving token
/// @param _data Additional data with no specified format
function transferToParent(
  address _from, 
  address _toContract, 
  uint256 _toTokenId, 
  uint256 _tokenId, 
  bytes _data
)
  external;
```

This function is used to transfer a token from an address to a token. `msg.sender` must be authenticated.

This function must check that `_toToken` exists in `_toContract` and throw if not.

#### transferFromParent

```solidity
/// @notice Transfer token from a token to an address
/// @param _fromContract The address of the owning contract
/// @param _fromTokenId The owning token
/// @param _to The address the token is transferred to.
/// @param _tokenId The token that is transferred
/// @param _data Additional data with no specified format
function transferFromParent(
  address _fromContract, 
  uint256 _fromTokenId, 
  address _to, 
  uint256 _tokenId, 
  bytes _data
)
  external;
```

This function is used to transfer a token from a token to an address. `msg.sender` must be authenticated.

This function must check that `_fromContract` and `_fromTokenId` own `_tokenId` and throw not.

#### transferAsChild

```solidity
/// @notice Transfer a token from a token to another token
/// @param _fromContract The address of the owning contract
/// @param _fromTokenId The owning token
/// @param _toContract The ERC-721 contract of the receiving token
/// @param _toToken The receiving token
/// @param _tokenId The token that is transferred
/// @param _data Additional data with no specified format
function transferAsChild(
  address _fromContract, 
  uint256 _fromTokenId, 
  address _toContract, 
  uint256 _toTokenId, 
  uint256 _tokenId, 
  bytes _data
)
  external;
```

This function is used to transfer a token from a token to another token. `msg.sender` must be authenticated.

This function must check that `_toToken` exists in `_toContract` and throw if not.

This function must check that `_fromContract` and `_fromTokenId` own `_tokenId` and throw if not.

#### ERC-721 Bottom-Up Composable Enumeration

Optional interface for bottom-up composable enumeration:

```solidity
/// @dev The ERC-165 identifier for this interface is 0x8318b539
interface ERC998ERC721BottomUpEnumerable {
  
  /// @notice Get the number of ERC-721 tokens owned by parent token.
  /// @param _parentContract The contract the parent ERC-721 token is from.
  /// @param _parentTokenId The parent tokenId that owns tokens
  //  @return uint256 The number of ERC-721 tokens owned by parent token.
  function totalChildTokens(
    address _parentContract, 
    uint256 _parentTokenId
  ) 
    external 
    view 
    returns (uint256);
  
  /// @notice Get a child token by index
  /// @param _parentContract The contract the parent ERC-721 token is from.
  /// @param _parentTokenId The parent tokenId that owns the token
  /// @param _index The index position of the child token
  /// @return uint256 The child tokenId owned by the parent token
  function childTokenByIndex(
    address _parentContract, 
    uint256 _parentTokenId, 
    uint256 _index
  ) 
    external 
    view 
    returns (uint256);
}
```

### ERC-20 Bottom-Up Composable

ERC-20 bottom-up composables are ERC-20 tokens that attach themselves to ERC-721 tokens, or are owned by a user address like standard ERC-20 tokens.

When owned by an ERC-721 token, ERC-20 bottom-up composable contracts store the owning address of a token and the parent tokenId. ERC-20 bottom-up composables add several methods to the ERC-20 and `ERC-223` interfaces allowing for querying the balance of parent tokens, and transferring tokens to, from, and between parent tokens.

This functionality can be implemented by adding one additional mapping to track balances of tokens, in addition to the standard mapping for tracking user address balances.

```solidity
/// @dev This mapping tracks standard ERC20/`ERC-223` ownership, where an address owns
///  a particular amount of tokens.
mapping(address =&gt; uint) userBalances;

/// @dev This additional mapping tracks ERC-998 ownership, where an ERC-721 token owns
///  a particular amount of tokens. This tracks contractAddres =&gt; tokenId =&gt; balance
mapping(address =&gt; mapping(uint =&gt; uint)) nftBalances;
```

The complete interface is below.

```solidity
/// @title `ERC998ERC20` Bottom-Up Composable Fungible Token
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-998.md
/// Note: The ERC-165 identifier for this interface is 0xffafa991
interface ERC998ERC20BottomUp {
  
  /// @dev This emits when a token is transferred to an ERC-721 token
  /// @param _toContract The contract the token is transferred to
  /// @param _toTokenId The token the token is transferred to
  /// @param _amount The amount of tokens transferred
  event TransferToParent(
    address indexed _toContract, 
    uint256 indexed _toTokenId, 
    uint256 _amount
  );

  /// @dev This emits when a token is transferred from an ERC-721 token
  /// @param _fromContract The contract the token is transferred from
  /// @param _fromTokenId The token the token is transferred from
  /// @param _amount The amount of tokens transferred
  event TransferFromParent(
    address indexed _fromContract, 
    uint256 indexed _fromTokenId, 
    uint256 _amount
  );

  /// @notice Get the balance of a non-fungible parent token
  /// @param _tokenContract The contract tracking the parent token
  /// @param _tokenId The ID of the parent token
  /// @return amount The balance of the token
  function balanceOfToken(
    address _tokenContract, 
    uint256 _tokenId
  )
    external
    view
    returns (uint256 amount);

  /// @notice Transfer tokens from owner address to a token
  /// @param _from The owner address
  /// @param _toContract The ERC-721 contract of the receiving token
  /// @param _toToken The receiving token
  /// @param _amount The amount of tokens to transfer
  function transferToParent(
    address _from, 
    address _toContract, 
    uint256 _toTokenId, 
    uint256 _amount
  )
    external;

  /// @notice Transfer token from a token to an address
  /// @param _fromContract The address of the owning contract
  /// @param _fromTokenId The owning token
  /// @param _to The address the token is transferred to
  /// @param _amount The amount of tokens to transfer
  function transferFromParent(
    address _fromContract, 
    uint256 _fromTokenId, 
    address _to, 
    uint256 _amount
  )
    external;

  /// @notice Transfer token from a token to an address, using `ERC-223` semantics
  /// @param _fromContract The address of the owning contract
  /// @param _fromTokenId The owning token
  /// @param _to The address the token is transferred to
  /// @param _amount The amount of tokens to transfer
  /// @param _data Additional data with no specified format, can be used to specify the sender tokenId
  function transferFromParentERC223(
    address _fromContract, 
    uint256 _fromTokenId, 
    address _to, 
    uint256 _amount, 
    bytes _data
  )
    external;

  /// @notice Transfer a token from a token to another token
  /// @param _fromContract The address of the owning contract
  /// @param _fromTokenId The owning token
  /// @param _toContract The ERC-721 contract of the receiving token
  /// @param _toToken The receiving token
  /// @param _amount The amount tokens to transfer
  function transferAsChild(
    address _fromContract, 
    uint256 _fromTokenId, 
    address _toContract, 
    uint256 _toTokenId, 
    uint256 _amount
   )
    external;
}
```

#### balanceOfToken

```solidity
/// @notice Get the balance of a non-fungible parent token
/// @param _tokenContract The contract tracking the parent token
/// @param _tokenId The ID of the parent token
/// @return amount The balance of the token
function balanceOfToken(
  address _tokenContract, 
  uint256 _tokenId
)
  external
  view
  returns (uint256 amount);
```

This function returns the balance of a non-fungible token. It mirrors the standard ERC-20 method `balanceOf`, but accepts the address of the parent token&apos;s contract, and the parent token&apos;s ID. This method behaves identically to `balanceOf`, but checks for ownership by ERC-721 tokens rather than user addresses.

#### `transferToParent`

```solidity
/// @notice Transfer tokens from owner address to a token
/// @param _from The owner address
/// @param _toContract The ERC-721 contract of the receiving token
/// @param _toToken The receiving token
/// @param _amount The amount of tokens to transfer
function transferToParent(
  address _from, 
  address _toContract, 
  uint256 _toTokenId, 
  uint256 _amount
)
  external;
```

This function transfers an amount of tokens from a user address to an ERC-721 token. This function MUST ensure that the recipient contract implements ERC-721 using the ERC-165 `supportsInterface` function. This function SHOULD ensure that the recipient token actually exists, by calling `ownerOf` on the recipient token&apos;s contract, and ensuring it neither throws nor returns the zero address. This function MUST emit the `TransferToParent` event upon a successful transfer (in addition to the standard ERC-20 `Transfer` event!). This function MUST throw if the `_from` account balance does not have enough tokens to spend.

#### `transferFromParent`

```solidity
/// @notice Transfer token from a token to an address
/// @param _fromContract The address of the owning contract
/// @param _fromTokenId The owning token
/// @param _to The address the token is transferred to
/// @param _amount The amount of tokens to transfer
function transferFromParent(
  address _fromContract, 
  uint256 _fromTokenId, 
  address _to, 
  uint256 _amount
)
  external;
```

This function transfers an amount of tokens from an ERC-721 token to an address. This function MUST emit the `TransferFromParent` event upon a successful transfer (in addition to the standard ERC-20 `Transfer` event!). This function MUST throw if the balance of the sender ERC-721 token is less than the `_amount` specified. This function MUST verify that the `msg.sender` owns the sender ERC-721 token, and MUST throw otherwise.

#### `transferFromParentERC223`

```solidity
/// @notice Transfer token from a token to an address, using `ERC-223` semantics
/// @param _fromContract The address of the owning contract
/// @param _fromTokenId The owning token
/// @param _to The address the token is transferred to
/// @param _amount The amount of tokens to transfer
/// @param _data Additional data with no specified format, can be used to specify the sender tokenId
function transferFromParentERC223(
  address _fromContract, 
  uint256 _fromTokenId, 
  address _to, 
  uint256 _amount, 
  bytes _data
)
  external;
```

This function transfers an amount of tokens from an ERC-721 token to an address. This function has identical requirements to `transferFromParent`, except that it additionally MUST invoke `tokenFallback` on the recipient address, if the address is a contract, as specified by `ERC-223`.

#### transferAsChild 1

```solidity
/// @notice Transfer a token from a token to another token
/// @param _fromContract The address of the owning contract
/// @param _fromTokenId The owning token
/// @param _toContract The ERC-721 contract of the receiving token
/// @param _toToken The receiving token
/// @param _amount The amount tokens to transfer
function transferAsChild(
  address _fromContract, 
  uint256 _fromTokenId, 
  address _toContract, 
  uint256 _toTokenId, 
  uint256 _amount
)
  external;
```

This function transfers an amount of tokens from an ERC-721 token to another ERC-721 token. This function MUST emit BOTH the `TransferFromParent` and `TransferToParent` events (in addition to the standard ERC-20 `Transfer` event!). This function MUST throw if the balance of the sender ERC-721 token is less than the `_amount` specified. This function MUST verify that the `msg.sender` owns the sender ERC-721 token, and MUST throw otherwise. This function MUST ensure that the recipient contract implements ERC-721 using the ERC-165 `supportsInterface` function. This function SHOULD ensure that the recipient token actually exists, by calling `ownerOf` on the recipient token&apos;s contract, and ensuring it neither throws nor returns the zero address.

### Notes

For backwards-compatibility, implementations MUST emit the standard ERC-20 `Transfer` event when a transfer occurs, regardless of whether the sender and recipient are addresses or ERC-721 tokens. In the case that either sender or recipient are tokens, the corresponding parameter in the `Transfer` event SHOULD be the contract address of the token.

Implementations MUST implement all ERC-20 and `ERC-223` functions in addition to the functions specified in this interface.

## Rationale

Two different kinds of composable (top-down and bottom-up) exist to handle different use cases. A regular ERC-721 token cannot own a top-down composable, but it can own a bottom-up composable. A bottom-up composable cannot own a regular ERC-721 but a top-down composable can own a regular ERC-721 token. Having multiple kinds of composables enable different token ownership possibilities.

### Which Kind of Composable To Use?

If you want to transfer regular ERC-721 tokens to non-fungible tokens, then use top-down composables.

If you want to transfer non-fungible tokens to regular ERC-721 tokens then use bottom-up composables.

### Explicit Transfer Parameters

Every ERC-998 transfer function includes explicit parameters to specify the prior owner and the new owner of a token. Explicitly providing **from** and **to** is done intentionally to avoid situations where tokens are transferred in unintended ways.

Here is an example of what could occur if **from** was not explicitly provided in transfer functions:
&gt; An exchange contract is an approved operator in a specific composable contract for user A, user B and user C.
&gt;
&gt; User A transfers token 1 to user B. At the same time the exchange contract transfers token 1 to user C (with the implicit intention to transfer from user A). User B gets token 1 for a minute before it gets incorrectly transferred to user C. The second transfer should have failed but it didn&apos;t because no explicit **from** was provided to ensure that token 1 came from user A.

## Backwards Compatibility

Composables are designed to work with ERC-721, `ERC-223` and ERC-20 tokens.

Some older ERC-721 contracts do not have a `safeTransferFrom` function. The `getChild` function can still be used to transfer a token to an ERC-721 top-down composable.

If an ERC-20 contract does not have the `ERC-223` function `transfer(address _to, uint _value, bytes _data)` then the `getERC20` function can still be used to transfer ERC-20 tokens to an ERC-20 top-down composable.

## Reference Implementation

An implementation can be found here: `https://github.com/mattlockyer/composables-998`

## Security Considerations

Needs discussion.


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).



</description>
        <pubDate>Sat, 07 Jul 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-998</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-998</guid>
      </item>
    
      <item>
        <title>Restore Contract Code at 0x863DF6BFa4469f3ead0bE8f9F2AAE51c91A907b4</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-999-restore-contract-code-at-0x863df6bfa4/130</comments>
        
        <description>## Simple Summary
This document proposes to restore the contract code of the `WalletLibrary`
contract at `0x863DF6BFa4469f3ead0bE8f9F2AAE51c91A907b4` with a patched version.
The contract was accidentally self-destructed and renders a significant amount
of Ether inaccessible.

## Abstract
The `WalletLibrary` contract was used by the
[Parity Wallet](https://www.parity.io/) to reduce gas costs for users deploying
multi-signature wallets on the Ethereum blockchain. It contained basic
functionality such as confirming or revoking multi-signature transactions for
any wallet deployed that depends on this library. The
[accidental self-destruction](https://github.com/paritytech/parity/issues/6995)
of the library contract caused significant amounts of Ether and other assets
owned by many different parties to be inaccessible. This proposal suggests
restoring the `WalletLibrary` by a
[patched](https://github.com/parity-contracts/0x863df6bfa4) version to allow the
owners of the dependent multi-signature wallets regain access to their assets.

## Motivation
This proposal is necessary because the Ethereum protocol does not allow the
restoration of self-destructed contracts and there is no other simple way to
enable the affected users and companies regaining access to their tokens and
Ether. In opposite to previously discussed proposals, this will not change any
EVM semantics and tries to achieve the goal of unfreezing the funds by a single
state transition as specified in the next section.

## Specification
The self-destructed contract code at
[`0x863DF6BFa4469f3ead0bE8f9F2AAE51c91A907b4`](https://etherscan.io/address/0x863df6bfa4469f3ead0be8f9f2aae51c91a907b4#code)
shall be replaced with a patched version of the
[`walletLibrary.sol`](https://github.com/parity-contracts/0x863df6bfa4/blob/master/contracts/walletLibrary.sol)
as reviewed, tested, and approved in
[parity-contracts/0x863df6bfa4](https://github.com/parity-contracts/0x863df6bfa4):

```json
{
	&quot;object&quot;: &quot;606060405234156200000d57fe5b5b6000808054806001018281620000259190620002d9565b916000526020600020900160005b6000909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506200012081805480602002602001604051908101604052809291908181526020018280548015620000fd57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311620000b2575b505050505060016000620001286401000000000262001d46176401000000009004565b5b5062000330565b600060015411156200013a5760006000fd5b6200015981620001806401000000000262001d71176401000000009004565b620001798383620001c26401000000000262001d9c176401000000009004565b5b5b505050565b60006001541115620001925760006000fd5b80600281905550620001b7620002c16401000000000262001bcf176401000000009004565b6004819055505b5b50565b600060006001541115620001d65760006000fd5b600082111515620001e75760006000fd5b81835110151515620001f95760006000fd5b8251600181905550600090505b8251811015620002b35782818151811015156200021f57fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff16600582600101610100811015156200025357fe5b0160005b508190555080600101610105600085848151811015156200027457fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b80600101905062000206565b816000819055505b5b505050565b60006201518042811515620002d257fe5b0490505b90565b815481835581811511620003035781836000526020600020918201910162000302919062000308565b5b505050565b6200032d91905b80821115620003295760008160009055506001016200030f565b5090565b90565b611ebf80620003406000396000f300606060405236156100ef576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063173825d91461016d5780632f54bf6e146101a35780634123cb6b146101f157806352375093146102175780635c52c2f51461023d578063659010e71461024f5780637065cb4814610275578063746c9171146102ab578063797af627146102d1578063b20d30a91461030d578063b61d27f61461032d578063b75c7dc61461039c578063ba51a6df146103c0578063c2cf7326146103e0578063c41a360a1461043b578063f00d4b5d1461049b578063f1736d86146104f0575b61016b5b6000341115610168577fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c3334604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a15b5b565b005b341561017557fe5b6101a1600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610516565b005b34156101ab57fe5b6101d7600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610659565b604051808215151515815260200191505060405180910390f35b34156101f957fe5b610201610691565b6040518082815260200191505060405180910390f35b341561021f57fe5b610227610697565b6040518082815260200191505060405180910390f35b341561024557fe5b61024d61069d565b005b341561025757fe5b61025f6106d7565b6040518082815260200191505060405180910390f35b341561027d57fe5b6102a9600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506106dd565b005b34156102b357fe5b6102bb610829565b6040518082815260200191505060405180910390f35b34156102d957fe5b6102f360048080356000191690602001909190505061082f565b604051808215151515815260200191505060405180910390f35b341561031557fe5b61032b6004808035906020019091905050610dcc565b005b341561033557fe5b61037e600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919080359060200190820180359060200191909192905050610e06565b60405180826000191660001916815260200191505060405180910390f35b34156103a457fe5b6103be60048080356000191690602001909190505061127d565b005b34156103c857fe5b6103de6004808035906020019091905050611392565b005b34156103e857fe5b61042160048080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061141a565b604051808215151515815260200191505060405180910390f35b341561044357fe5b610459600480803590602001909190505061149c565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156104a357fe5b6104ee600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506114bf565b005b34156104f857fe5b610500611672565b6040518082815260200191505060405180910390f35b600060003660405180838380828437820191505092505050604051809103902061053f81611678565b156106535761010560008473ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549150600082141561057f57610652565b600160015403600054111561059357610652565b6000600583610100811015156105a557fe5b0160005b5081905550600061010560008573ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506105e6611890565b6105ee6119d0565b7f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da83604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a15b5b5b505050565b6000600061010560008473ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541190505b919050565b60015481565b60045481565b6000366040518083838082843782019150509250505060405180910390206106c481611678565b156106d35760006003819055505b5b5b50565b60035481565b60003660405180838380828437820191505092505050604051809103902061070481611678565b156108245761071282610659565b1561071c57610823565b610724611890565b60fa600154101515610739576107386119d0565b5b60fa60015410151561074a57610823565b6001600081548092919060010191905055508173ffffffffffffffffffffffffffffffffffffffff1660056001546101008110151561078557fe5b0160005b508190555060015461010560008473ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c382604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a15b5b5b5050565b60005481565b600060008261083d81611678565b15610dc45760006101086000866000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415806108c757506000610108600086600019166000191681526020019081526020016000206001015414155b80610906575060006101086000866000191660001916815260200190815260200160002060020180546001816001161561010002031660029004905014155b15610dc25760006101086000866000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610a5057610a496101086000866000191660001916815260200190815260200160002060010154610108600087600019166000191681526020019081526020016000206002018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a3f5780601f10610a1457610100808354040283529160200191610a3f565b820191906000526020600020905b815481529060010190602001808311610a2257829003601f168201915b5050505050611b37565b9150610b71565b6101086000856000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166101086000866000191660001916815260200190815260200160002060010154610108600087600019166000191681526020019081526020016000206002016040518082805460018160011615610100020316600290048015610b4a5780601f10610b1f57610100808354040283529160200191610b4a565b820191906000526020600020905b815481529060010190602001808311610b2d57829003601f168201915b505091505060006040518083038185876185025a03f1925050501515610b705760006000fd5b5b7fe3a3a4111a84df27d76b68dc721e65c7711605ea5eee4afd3a9c58195217365c338561010860008860001916600019168152602001908152602001600020600101546101086000896000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1661010860008a6000191660001916815260200190815260200160002060020187604051808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200186600019166000191681526020018581526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818154600181600116156101000203166002900481526020019150805460018160011615610100020316600290048015610d475780601f10610d1c57610100808354040283529160200191610d47565b820191906000526020600020905b815481529060010190602001808311610d2a57829003601f168201915b505097505050505050505060405180910390a16101086000856000191660001916815260200190815260200160002060006000820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001820160009055600282016000610db79190611be6565b505060019250610dc3565b5b5b5b5050919050565b600036604051808383808284378201915050925050506040518091039020610df381611678565b15610e0157816002819055505b5b5b5050565b60006000610e1333610659565b1561127357600084849050148015610e305750610e2f85611b51565b5b80610e3d57506001600054145b15610fed5760008673ffffffffffffffffffffffffffffffffffffffff161415610ea457610e9d8585858080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050611b37565b9050610ef3565b8573ffffffffffffffffffffffffffffffffffffffff168585856040518083838082843782019150509250505060006040518083038185876185025a03f1925050501515610ef25760006000fd5b5b7f9738cd1a8777c86b011f7b01d87d484217dc6ab5154a9d41eda5d14af8caf292338688878786604051808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281038252858582818152602001925080828437820191505097505050505050505060405180910390a1611271565b6000364360405180848480828437820191505082815260200193505050506040518091039020915060006101086000846000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16148015611099575060006101086000846000191660001916815260200190815260200160002060010154145b80156110d85750600061010860008460001916600019168152602001908152602001600020600201805460018160011615610100020316600290049050145b1561118f57856101086000846000191660001916815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550846101086000846000191660001916815260200190815260200160002060010181905550838361010860008560001916600019168152602001908152602001600020600201919061118d929190611c2e565b505b6111988261082f565b1515611270577f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328233878988886040518087600019166000191681526020018673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018581526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b5b5b5b5b50949350505050565b60006000600061010560003373ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054925060008314156112be5761138c565b8260020a9150610106600085600019166000191681526020019081526020016000209050600082826001015416111561138b5780600001600081548092919060010191905055508181600101600082825403925050819055507fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b3385604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182600019166000191681526020019250505060405180910390a15b5b50505050565b6000366040518083838082843782019150509250505060405180910390206113b981611678565b15611415576001548211156113cd57611414565b816000819055506113dc611890565b7facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da826040518082815260200191505060405180910390a15b5b5b5050565b600060006000600061010660008760001916600019168152602001908152602001600020925061010560008673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549150600082141561147f5760009350611493565b8160020a9050600081846001015416141593505b50505092915050565b6000600560018301610100811015156114b157fe5b0160005b505490505b919050565b60006000366040518083838082843782019150509250505060405180910390206114e881611678565b1561166b576114f683610659565b156115005761166a565b61010560008573ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549150600082141561153b5761166a565b611543611890565b8273ffffffffffffffffffffffffffffffffffffffff166005836101008110151561156a57fe5b0160005b5081905550600061010560008673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508161010560008573ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c8484604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a15b5b5b50505050565b60025481565b600060006000600061010560003373ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054925060008314156116bb57611888565b6101066000866000191660001916815260200190815260200160002091506000826000015414156117455760005482600001819055506000826001018190555061010780548091906001016117109190611cae565b826002018190555084610107836002015481548110151561172d57fe5b906000526020600020900160005b5081600019169055505b8260020a90506000818360010154161415611887577fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda3386604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182600019166000191681526020019250505060405180910390a16001826000015411151561185e57610107610106600087600019166000191681526020019081526020016000206002015481548110151561180a57fe5b906000526020600020900160005b5060009055610106600086600019166000191681526020019081526020016000206000600082016000905560018201600090556002820160009055505060019350611888565b8160000160008154809291906001900391905055508082600101600082825417925050819055505b5b5b505050919050565b60006000610107805490509150600090505b818110156119bc576101086000610107838154811015156118bf57fe5b906000526020600020900160005b50546000191660001916815260200190815260200160002060006000820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560018201600090556002820160006119269190611be6565b505060006001026101078281548110151561193d57fe5b906000526020600020900160005b5054600019161415156119b05761010660006101078381548110151561196d57fe5b906000526020600020900160005b505460001916600019168152602001908152602001600020600060008201600090556001820160009055600282016000905550505b5b8060010190506118a2565b61010760006119cb9190611cda565b5b5050565b6000600190505b600154811015611b33575b60015481108015611a095750600060058261010081101515611a0057fe5b0160005b505414155b15611a1b5780806001019150506119e2565b5b6001600154118015611a4557506000600560015461010081101515611a3d57fe5b0160005b5054145b15611a625760016000815480929190600190039190505550611a1c565b60015481108015611a8b57506000600560015461010081101515611a8257fe5b0160005b505414155b8015611aac5750600060058261010081101515611aa457fe5b0160005b5054145b15611b2e57600560015461010081101515611ac357fe5b0160005b505460058261010081101515611ad957fe5b0160005b508190555080610105600060058461010081101515611af857fe5b0160005b50548152602001908152602001600020819055506000600560015461010081101515611b2457fe5b0160005b50819055505b6119d7565b5b50565b600081516020830184f09050803b15610000575b92915050565b6000611b5c33610659565b15611bc957600454611b6c611bcf565b1115611b89576000600381905550611b82611bcf565b6004819055505b600354826003540110158015611ba55750600254826003540111155b15611bc3578160036000828254019250508190555060019050611bc8565b600090505b5b5b919050565b60006201518042811515611bdf57fe5b0490505b90565b50805460018160011615610100020316600290046000825580601f10611c0c5750611c2b565b601f016020900490600052602060002090810190611c2a9190611cfc565b5b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611c6f57803560ff1916838001178555611c9d565b82800160010185558215611c9d579182015b82811115611c9c578235825591602001919060010190611c81565b5b509050611caa9190611cfc565b5090565b815481835581811511611cd557818360005260206000209182019101611cd49190611d21565b5b505050565b5080546000825590600052602060002090810190611cf89190611d21565b5b50565b611d1e91905b80821115611d1a576000816000905550600101611d02565b5090565b90565b611d4391905b80821115611d3f576000816000905550600101611d27565b5090565b90565b60006001541115611d575760006000fd5b611d6081611d71565b611d6a8383611d9c565b5b5b505050565b60006001541115611d825760006000fd5b80600281905550611d91611bcf565b6004819055505b5b50565b600060006001541115611daf5760006000fd5b600082111515611dbf5760006000fd5b81835110151515611dd05760006000fd5b8251600181905550600090505b8251811015611e85578281815181101515611df457fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1660058260010161010081101515611e2757fe5b0160005b50819055508060010161010560008584815181101515611e4757fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b806001019050611ddd565b816000819055505b5b5050505600a165627a7a7230582016889f0740f073d397f9d00b0d19900fb050b957e3e2942f861085beb9baab180029&quot;,
	&quot;opcodes&quot;: &quot;PUSH1 0x60 PUSH1 0x40 MSTORE CALLVALUE ISZERO PUSH3 0xD JUMPI INVALID JUMPDEST JUMPDEST PUSH1 0x0 DUP1 DUP1 SLOAD DUP1 PUSH1 0x1 ADD DUP3 DUP2 PUSH3 0x25 SWAP2 SWAP1 PUSH3 0x2D9 JUMP JUMPDEST SWAP2 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 ADD PUSH1 0x0 JUMPDEST PUSH1 0x0 SWAP1 SWAP2 SWAP1 SWAP2 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF MUL NOT AND SWAP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND MUL OR SWAP1 SSTORE POP POP PUSH3 0x120 DUP2 DUP1 SLOAD DUP1 PUSH1 0x20 MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD DUP1 ISZERO PUSH3 0xFD JUMPI PUSH1 0x20 MUL DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 JUMPDEST DUP2 PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 PUSH1 0x1 ADD SWAP1 DUP1 DUP4 GT PUSH3 0xB2 JUMPI JUMPDEST POP POP POP POP POP PUSH1 0x1 PUSH1 0x0 PUSH3 0x128 PUSH5 0x100000000 MUL PUSH3 0x1D46 OR PUSH5 0x100000000 SWAP1 DIV JUMP JUMPDEST JUMPDEST POP PUSH3 0x330 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 SLOAD GT ISZERO PUSH3 0x13A JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST PUSH3 0x159 DUP2 PUSH3 0x180 PUSH5 0x100000000 MUL PUSH3 0x1D71 OR PUSH5 0x100000000 SWAP1 DIV JUMP JUMPDEST PUSH3 0x179 DUP4 DUP4 PUSH3 0x1C2 PUSH5 0x100000000 MUL PUSH3 0x1D9C OR PUSH5 0x100000000 SWAP1 DIV JUMP JUMPDEST JUMPDEST JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 SLOAD GT ISZERO PUSH3 0x192 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST DUP1 PUSH1 0x2 DUP2 SWAP1 SSTORE POP PUSH3 0x1B7 PUSH3 0x2C1 PUSH5 0x100000000 MUL PUSH3 0x1BCF OR PUSH5 0x100000000 SWAP1 DIV JUMP JUMPDEST PUSH1 0x4 DUP2 SWAP1 SSTORE POP JUMPDEST JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH1 0x1 SLOAD GT ISZERO PUSH3 0x1D6 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST PUSH1 0x0 DUP3 GT ISZERO ISZERO PUSH3 0x1E7 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST DUP2 DUP4 MLOAD LT ISZERO ISZERO ISZERO PUSH3 0x1F9 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST DUP3 MLOAD PUSH1 0x1 DUP2 SWAP1 SSTORE POP PUSH1 0x0 SWAP1 POP JUMPDEST DUP3 MLOAD DUP2 LT ISZERO PUSH3 0x2B3 JUMPI DUP3 DUP2 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH3 0x21F JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x5 DUP3 PUSH1 0x1 ADD PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH3 0x253 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP DUP2 SWAP1 SSTORE POP DUP1 PUSH1 0x1 ADD PUSH2 0x105 PUSH1 0x0 DUP6 DUP5 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH3 0x274 JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 DUP2 SWAP1 SSTORE POP JUMPDEST DUP1 PUSH1 0x1 ADD SWAP1 POP PUSH3 0x206 JUMP JUMPDEST DUP2 PUSH1 0x0 DUP2 SWAP1 SSTORE POP JUMPDEST JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH3 0x15180 TIMESTAMP DUP2 ISZERO ISZERO PUSH3 0x2D2 JUMPI INVALID JUMPDEST DIV SWAP1 POP JUMPDEST SWAP1 JUMP JUMPDEST DUP2 SLOAD DUP2 DUP4 SSTORE DUP2 DUP2 ISZERO GT PUSH3 0x303 JUMPI DUP2 DUP4 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP2 DUP3 ADD SWAP2 ADD PUSH3 0x302 SWAP2 SWAP1 PUSH3 0x308 JUMP JUMPDEST JUMPDEST POP POP POP JUMP JUMPDEST PUSH3 0x32D SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH3 0x329 JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH3 0x30F JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH2 0x1EBF DUP1 PUSH3 0x340 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x60 PUSH1 0x40 MSTORE CALLDATASIZE ISZERO PUSH2 0xEF JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV PUSH4 0xFFFFFFFF AND DUP1 PUSH4 0x173825D9 EQ PUSH2 0x16D JUMPI DUP1 PUSH4 0x2F54BF6E EQ PUSH2 0x1A3 JUMPI DUP1 PUSH4 0x4123CB6B EQ PUSH2 0x1F1 JUMPI DUP1 PUSH4 0x52375093 EQ PUSH2 0x217 JUMPI DUP1 PUSH4 0x5C52C2F5 EQ PUSH2 0x23D JUMPI DUP1 PUSH4 0x659010E7 EQ PUSH2 0x24F JUMPI DUP1 PUSH4 0x7065CB48 EQ PUSH2 0x275 JUMPI DUP1 PUSH4 0x746C9171 EQ PUSH2 0x2AB JUMPI DUP1 PUSH4 0x797AF627 EQ PUSH2 0x2D1 JUMPI DUP1 PUSH4 0xB20D30A9 EQ PUSH2 0x30D JUMPI DUP1 PUSH4 0xB61D27F6 EQ PUSH2 0x32D JUMPI DUP1 PUSH4 0xB75C7DC6 EQ PUSH2 0x39C JUMPI DUP1 PUSH4 0xBA51A6DF EQ PUSH2 0x3C0 JUMPI DUP1 PUSH4 0xC2CF7326 EQ PUSH2 0x3E0 JUMPI DUP1 PUSH4 0xC41A360A EQ PUSH2 0x43B JUMPI DUP1 PUSH4 0xF00D4B5D EQ PUSH2 0x49B JUMPI DUP1 PUSH4 0xF1736D86 EQ PUSH2 0x4F0 JUMPI JUMPDEST PUSH2 0x16B JUMPDEST PUSH1 0x0 CALLVALUE GT ISZERO PUSH2 0x168 JUMPI PUSH32 0xE1FFFCC4923D04B559F4D29A8BFC6CDA04EB5B0D3C460751C2402C5C5CC9109C CALLER CALLVALUE PUSH1 0x40 MLOAD DUP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 JUMPDEST JUMPDEST JUMP JUMPDEST STOP JUMPDEST CALLVALUE ISZERO PUSH2 0x175 JUMPI INVALID JUMPDEST PUSH2 0x1A1 PUSH1 0x4 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x516 JUMP JUMPDEST STOP JUMPDEST CALLVALUE ISZERO PUSH2 0x1AB JUMPI INVALID JUMPDEST PUSH2 0x1D7 PUSH1 0x4 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x659 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x1F9 JUMPI INVALID JUMPDEST PUSH2 0x201 PUSH2 0x691 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x21F JUMPI INVALID JUMPDEST PUSH2 0x227 PUSH2 0x697 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x245 JUMPI INVALID JUMPDEST PUSH2 0x24D PUSH2 0x69D JUMP JUMPDEST STOP JUMPDEST CALLVALUE ISZERO PUSH2 0x257 JUMPI INVALID JUMPDEST PUSH2 0x25F PUSH2 0x6D7 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x27D JUMPI INVALID JUMPDEST PUSH2 0x2A9 PUSH1 0x4 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x6DD JUMP JUMPDEST STOP JUMPDEST CALLVALUE ISZERO PUSH2 0x2B3 JUMPI INVALID JUMPDEST PUSH2 0x2BB PUSH2 0x829 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x2D9 JUMPI INVALID JUMPDEST PUSH2 0x2F3 PUSH1 0x4 DUP1 DUP1 CALLDATALOAD PUSH1 0x0 NOT AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x82F JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x315 JUMPI INVALID JUMPDEST PUSH2 0x32B PUSH1 0x4 DUP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0xDCC JUMP JUMPDEST STOP JUMPDEST CALLVALUE ISZERO PUSH2 0x335 JUMPI INVALID JUMPDEST PUSH2 0x37E PUSH1 0x4 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP3 ADD DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP2 SWAP1 SWAP2 SWAP3 SWAP1 POP POP PUSH2 0xE06 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x3A4 JUMPI INVALID JUMPDEST PUSH2 0x3BE PUSH1 0x4 DUP1 DUP1 CALLDATALOAD PUSH1 0x0 NOT AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x127D JUMP JUMPDEST STOP JUMPDEST CALLVALUE ISZERO PUSH2 0x3C8 JUMPI INVALID JUMPDEST PUSH2 0x3DE PUSH1 0x4 DUP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x1392 JUMP JUMPDEST STOP JUMPDEST CALLVALUE ISZERO PUSH2 0x3E8 JUMPI INVALID JUMPDEST PUSH2 0x421 PUSH1 0x4 DUP1 DUP1 CALLDATALOAD PUSH1 0x0 NOT AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x141A JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 ISZERO ISZERO ISZERO ISZERO DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x443 JUMPI INVALID JUMPDEST PUSH2 0x459 PUSH1 0x4 DUP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x149C JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST CALLVALUE ISZERO PUSH2 0x4A3 JUMPI INVALID JUMPDEST PUSH2 0x4EE PUSH1 0x4 DUP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 DUP1 CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 PUSH1 0x20 ADD SWAP1 SWAP2 SWAP1 POP POP PUSH2 0x14BF JUMP JUMPDEST STOP JUMPDEST CALLVALUE ISZERO PUSH2 0x4F8 JUMPI INVALID JUMPDEST PUSH2 0x500 PUSH2 0x1672 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x0 PUSH1 0x0 CALLDATASIZE PUSH1 0x40 MLOAD DUP1 DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 SHA3 PUSH2 0x53F DUP2 PUSH2 0x1678 JUMP JUMPDEST ISZERO PUSH2 0x653 JUMPI PUSH2 0x105 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SLOAD SWAP2 POP PUSH1 0x0 DUP3 EQ ISZERO PUSH2 0x57F JUMPI PUSH2 0x652 JUMP JUMPDEST PUSH1 0x1 PUSH1 0x1 SLOAD SUB PUSH1 0x0 SLOAD GT ISZERO PUSH2 0x593 JUMPI PUSH2 0x652 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 DUP4 PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x5A5 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP DUP2 SWAP1 SSTORE POP PUSH1 0x0 PUSH2 0x105 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 DUP2 SWAP1 SSTORE POP PUSH2 0x5E6 PUSH2 0x1890 JUMP JUMPDEST PUSH2 0x5EE PUSH2 0x19D0 JUMP JUMPDEST PUSH32 0x58619076ADF5BB0943D100EF88D52D7C3FD691B19D3A9071B555B651FBF418DA DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 JUMPDEST JUMPDEST JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH2 0x105 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SLOAD GT SWAP1 POP JUMPDEST SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x1 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x4 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 CALLDATASIZE PUSH1 0x40 MLOAD DUP1 DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 SHA3 PUSH2 0x6C4 DUP2 PUSH2 0x1678 JUMP JUMPDEST ISZERO PUSH2 0x6D3 JUMPI PUSH1 0x0 PUSH1 0x3 DUP2 SWAP1 SSTORE POP JUMPDEST JUMPDEST JUMPDEST POP JUMP JUMPDEST PUSH1 0x3 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 CALLDATASIZE PUSH1 0x40 MLOAD DUP1 DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 SHA3 PUSH2 0x704 DUP2 PUSH2 0x1678 JUMP JUMPDEST ISZERO PUSH2 0x824 JUMPI PUSH2 0x712 DUP3 PUSH2 0x659 JUMP JUMPDEST ISZERO PUSH2 0x71C JUMPI PUSH2 0x823 JUMP JUMPDEST PUSH2 0x724 PUSH2 0x1890 JUMP JUMPDEST PUSH1 0xFA PUSH1 0x1 SLOAD LT ISZERO ISZERO PUSH2 0x739 JUMPI PUSH2 0x738 PUSH2 0x19D0 JUMP JUMPDEST JUMPDEST PUSH1 0xFA PUSH1 0x1 SLOAD LT ISZERO ISZERO PUSH2 0x74A JUMPI PUSH2 0x823 JUMP JUMPDEST PUSH1 0x1 PUSH1 0x0 DUP2 SLOAD DUP1 SWAP3 SWAP2 SWAP1 PUSH1 0x1 ADD SWAP2 SWAP1 POP SSTORE POP DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x5 PUSH1 0x1 SLOAD PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x785 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP DUP2 SWAP1 SSTORE POP PUSH1 0x1 SLOAD PUSH2 0x105 PUSH1 0x0 DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 DUP2 SWAP1 SSTORE POP PUSH32 0x994A936646FE87FFE4F1E469D3D6AA417D6B855598397F323DE5B449F765F0C3 DUP3 PUSH1 0x40 MLOAD DUP1 DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 JUMPDEST JUMPDEST JUMPDEST POP POP JUMP JUMPDEST PUSH1 0x0 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 DUP3 PUSH2 0x83D DUP2 PUSH2 0x1678 JUMP JUMPDEST ISZERO PUSH2 0xDC4 JUMPI PUSH1 0x0 PUSH2 0x108 PUSH1 0x0 DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 ADD PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO DUP1 PUSH2 0x8C7 JUMPI POP PUSH1 0x0 PUSH2 0x108 PUSH1 0x0 DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x1 ADD SLOAD EQ ISZERO JUMPDEST DUP1 PUSH2 0x906 JUMPI POP PUSH1 0x0 PUSH2 0x108 PUSH1 0x0 DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x2 ADD DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 POP EQ ISZERO JUMPDEST ISZERO PUSH2 0xDC2 JUMPI PUSH1 0x0 PUSH2 0x108 PUSH1 0x0 DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 ADD PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xA50 JUMPI PUSH2 0xA49 PUSH2 0x108 PUSH1 0x0 DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x1 ADD SLOAD PUSH2 0x108 PUSH1 0x0 DUP8 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x2 ADD DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0xA3F JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xA14 JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xA3F JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xA22 JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP POP POP POP PUSH2 0x1B37 JUMP JUMPDEST SWAP2 POP PUSH2 0xB71 JUMP JUMPDEST PUSH2 0x108 PUSH1 0x0 DUP6 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 ADD PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH2 0x108 PUSH1 0x0 DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x1 ADD SLOAD PUSH2 0x108 PUSH1 0x0 DUP8 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x2 ADD PUSH1 0x40 MLOAD DUP1 DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0xB4A JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xB1F JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xB4A JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xB2D JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP SWAP2 POP POP PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP6 DUP8 PUSH2 0x8502 GAS SUB CALL SWAP3 POP POP POP ISZERO ISZERO PUSH2 0xB70 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST JUMPDEST PUSH32 0xE3A3A4111A84DF27D76B68DC721E65C7711605EA5EEE4AFD3A9C58195217365C CALLER DUP6 PUSH2 0x108 PUSH1 0x0 DUP9 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x1 ADD SLOAD PUSH2 0x108 PUSH1 0x0 DUP10 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 ADD PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH2 0x108 PUSH1 0x0 DUP11 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x2 ADD DUP8 PUSH1 0x40 MLOAD DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD DUP6 DUP2 MSTORE PUSH1 0x20 ADD DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH1 0x20 ADD DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP5 DUP2 DUP2 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV DUP1 ISZERO PUSH2 0xD47 JUMPI DUP1 PUSH1 0x1F LT PUSH2 0xD1C JUMPI PUSH2 0x100 DUP1 DUP4 SLOAD DIV MUL DUP4 MSTORE SWAP2 PUSH1 0x20 ADD SWAP2 PUSH2 0xD47 JUMP JUMPDEST DUP3 ADD SWAP2 SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 JUMPDEST DUP2 SLOAD DUP2 MSTORE SWAP1 PUSH1 0x1 ADD SWAP1 PUSH1 0x20 ADD DUP1 DUP4 GT PUSH2 0xD2A JUMPI DUP3 SWAP1 SUB PUSH1 0x1F AND DUP3 ADD SWAP2 JUMPDEST POP POP SWAP8 POP POP POP POP POP POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 PUSH2 0x108 PUSH1 0x0 DUP6 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 PUSH1 0x0 DUP3 ADD PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD SWAP1 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF MUL NOT AND SWAP1 SSTORE PUSH1 0x1 DUP3 ADD PUSH1 0x0 SWAP1 SSTORE PUSH1 0x2 DUP3 ADD PUSH1 0x0 PUSH2 0xDB7 SWAP2 SWAP1 PUSH2 0x1BE6 JUMP JUMPDEST POP POP PUSH1 0x1 SWAP3 POP PUSH2 0xDC3 JUMP JUMPDEST JUMPDEST JUMPDEST JUMPDEST POP POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 CALLDATASIZE PUSH1 0x40 MLOAD DUP1 DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 SHA3 PUSH2 0xDF3 DUP2 PUSH2 0x1678 JUMP JUMPDEST ISZERO PUSH2 0xE01 JUMPI DUP2 PUSH1 0x2 DUP2 SWAP1 SSTORE POP JUMPDEST JUMPDEST JUMPDEST POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH2 0xE13 CALLER PUSH2 0x659 JUMP JUMPDEST ISZERO PUSH2 0x1273 JUMPI PUSH1 0x0 DUP5 DUP5 SWAP1 POP EQ DUP1 ISZERO PUSH2 0xE30 JUMPI POP PUSH2 0xE2F DUP6 PUSH2 0x1B51 JUMP JUMPDEST JUMPDEST DUP1 PUSH2 0xE3D JUMPI POP PUSH1 0x1 PUSH1 0x0 SLOAD EQ JUMPDEST ISZERO PUSH2 0xFED JUMPI PUSH1 0x0 DUP7 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ ISZERO PUSH2 0xEA4 JUMPI PUSH2 0xE9D DUP6 DUP6 DUP6 DUP1 DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP4 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP POP POP POP POP PUSH2 0x1B37 JUMP JUMPDEST SWAP1 POP PUSH2 0xEF3 JUMP JUMPDEST DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP6 DUP6 DUP6 PUSH1 0x40 MLOAD DUP1 DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP3 POP POP POP PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP6 DUP8 PUSH2 0x8502 GAS SUB CALL SWAP3 POP POP POP ISZERO ISZERO PUSH2 0xEF2 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST JUMPDEST PUSH32 0x9738CD1A8777C86B011F7B01D87D484217DC6AB5154A9D41EDA5D14AF8CAF292 CALLER DUP7 DUP9 DUP8 DUP8 DUP7 PUSH1 0x40 MLOAD DUP1 DUP8 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP7 DUP2 MSTORE PUSH1 0x20 ADD DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH1 0x20 ADD DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP6 DUP6 DUP3 DUP2 DUP2 MSTORE PUSH1 0x20 ADD SWAP3 POP DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP8 POP POP POP POP POP POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 PUSH2 0x1271 JUMP JUMPDEST PUSH1 0x0 CALLDATASIZE NUMBER PUSH1 0x40 MLOAD DUP1 DUP5 DUP5 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP4 POP POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 SHA3 SWAP2 POP PUSH1 0x0 PUSH2 0x108 PUSH1 0x0 DUP5 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 ADD PUSH1 0x0 SWAP1 SLOAD SWAP1 PUSH2 0x100 EXP SWAP1 DIV PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND EQ DUP1 ISZERO PUSH2 0x1099 JUMPI POP PUSH1 0x0 PUSH2 0x108 PUSH1 0x0 DUP5 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x1 ADD SLOAD EQ JUMPDEST DUP1 ISZERO PUSH2 0x10D8 JUMPI POP PUSH1 0x0 PUSH2 0x108 PUSH1 0x0 DUP5 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x2 ADD DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 POP EQ JUMPDEST ISZERO PUSH2 0x118F JUMPI DUP6 PUSH2 0x108 PUSH1 0x0 DUP5 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 ADD PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD DUP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF MUL NOT AND SWAP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND MUL OR SWAP1 SSTORE POP DUP5 PUSH2 0x108 PUSH1 0x0 DUP5 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x1 ADD DUP2 SWAP1 SSTORE POP DUP4 DUP4 PUSH2 0x108 PUSH1 0x0 DUP6 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x2 ADD SWAP2 SWAP1 PUSH2 0x118D SWAP3 SWAP2 SWAP1 PUSH2 0x1C2E JUMP JUMPDEST POP JUMPDEST PUSH2 0x1198 DUP3 PUSH2 0x82F JUMP JUMPDEST ISZERO ISZERO PUSH2 0x1270 JUMPI PUSH32 0x1733CBB53659D713B79580F79F3F9FF215F78A7C7AA45890F3B89FC5CDDFBF32 DUP3 CALLER DUP8 DUP10 DUP9 DUP9 PUSH1 0x40 MLOAD DUP1 DUP8 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD DUP7 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP6 DUP2 MSTORE PUSH1 0x20 ADD DUP5 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP5 DUP5 DUP3 DUP2 DUP2 MSTORE PUSH1 0x20 ADD SWAP3 POP DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP8 POP POP POP POP POP POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 JUMPDEST JUMPDEST JUMPDEST JUMPDEST JUMPDEST POP SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 PUSH2 0x105 PUSH1 0x0 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SLOAD SWAP3 POP PUSH1 0x0 DUP4 EQ ISZERO PUSH2 0x12BE JUMPI PUSH2 0x138C JUMP JUMPDEST DUP3 PUSH1 0x2 EXP SWAP2 POP PUSH2 0x106 PUSH1 0x0 DUP6 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SWAP1 POP PUSH1 0x0 DUP3 DUP3 PUSH1 0x1 ADD SLOAD AND GT ISZERO PUSH2 0x138B JUMPI DUP1 PUSH1 0x0 ADD PUSH1 0x0 DUP2 SLOAD DUP1 SWAP3 SWAP2 SWAP1 PUSH1 0x1 ADD SWAP2 SWAP1 POP SSTORE POP DUP2 DUP2 PUSH1 0x1 ADD PUSH1 0x0 DUP3 DUP3 SLOAD SUB SWAP3 POP POP DUP2 SWAP1 SSTORE POP PUSH32 0xC7FB647E59B18047309AA15AAD418E5D7CA96D173AD704F1031A2C3D7591734B CALLER DUP6 PUSH1 0x40 MLOAD DUP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP3 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 JUMPDEST JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH1 0x0 CALLDATASIZE PUSH1 0x40 MLOAD DUP1 DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 SHA3 PUSH2 0x13B9 DUP2 PUSH2 0x1678 JUMP JUMPDEST ISZERO PUSH2 0x1415 JUMPI PUSH1 0x1 SLOAD DUP3 GT ISZERO PUSH2 0x13CD JUMPI PUSH2 0x1414 JUMP JUMPDEST DUP2 PUSH1 0x0 DUP2 SWAP1 SSTORE POP PUSH2 0x13DC PUSH2 0x1890 JUMP JUMPDEST PUSH32 0xACBDB084C721332AC59F9B8E392196C9EB0E4932862DA8EB9BEAF0DAD4F550DA DUP3 PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 JUMPDEST JUMPDEST JUMPDEST POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 PUSH2 0x106 PUSH1 0x0 DUP8 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SWAP3 POP PUSH2 0x105 PUSH1 0x0 DUP7 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SLOAD SWAP2 POP PUSH1 0x0 DUP3 EQ ISZERO PUSH2 0x147F JUMPI PUSH1 0x0 SWAP4 POP PUSH2 0x1493 JUMP JUMPDEST DUP2 PUSH1 0x2 EXP SWAP1 POP PUSH1 0x0 DUP2 DUP5 PUSH1 0x1 ADD SLOAD AND EQ ISZERO SWAP4 POP JUMPDEST POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x5 PUSH1 0x1 DUP4 ADD PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x14B1 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP SLOAD SWAP1 POP JUMPDEST SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 CALLDATASIZE PUSH1 0x40 MLOAD DUP1 DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 SHA3 PUSH2 0x14E8 DUP2 PUSH2 0x1678 JUMP JUMPDEST ISZERO PUSH2 0x166B JUMPI PUSH2 0x14F6 DUP4 PUSH2 0x659 JUMP JUMPDEST ISZERO PUSH2 0x1500 JUMPI PUSH2 0x166A JUMP JUMPDEST PUSH2 0x105 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SLOAD SWAP2 POP PUSH1 0x0 DUP3 EQ ISZERO PUSH2 0x153B JUMPI PUSH2 0x166A JUMP JUMPDEST PUSH2 0x1543 PUSH2 0x1890 JUMP JUMPDEST DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x5 DUP4 PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x156A JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP DUP2 SWAP1 SSTORE POP PUSH1 0x0 PUSH2 0x105 PUSH1 0x0 DUP7 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 DUP2 SWAP1 SSTORE POP DUP2 PUSH2 0x105 PUSH1 0x0 DUP6 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 DUP2 SWAP1 SSTORE POP PUSH32 0xB532073B38C83145E3E5135377A08BF9AAB55BC0FD7C1179CD4FB995D2A5159C DUP5 DUP5 PUSH1 0x40 MLOAD DUP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 JUMPDEST JUMPDEST JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH1 0x2 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 PUSH1 0x0 PUSH2 0x105 PUSH1 0x0 CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SLOAD SWAP3 POP PUSH1 0x0 DUP4 EQ ISZERO PUSH2 0x16BB JUMPI PUSH2 0x1888 JUMP JUMPDEST PUSH2 0x106 PUSH1 0x0 DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 SWAP2 POP PUSH1 0x0 DUP3 PUSH1 0x0 ADD SLOAD EQ ISZERO PUSH2 0x1745 JUMPI PUSH1 0x0 SLOAD DUP3 PUSH1 0x0 ADD DUP2 SWAP1 SSTORE POP PUSH1 0x0 DUP3 PUSH1 0x1 ADD DUP2 SWAP1 SSTORE POP PUSH2 0x107 DUP1 SLOAD DUP1 SWAP2 SWAP1 PUSH1 0x1 ADD PUSH2 0x1710 SWAP2 SWAP1 PUSH2 0x1CAE JUMP JUMPDEST DUP3 PUSH1 0x2 ADD DUP2 SWAP1 SSTORE POP DUP5 PUSH2 0x107 DUP4 PUSH1 0x2 ADD SLOAD DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x172D JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 ADD PUSH1 0x0 JUMPDEST POP DUP2 PUSH1 0x0 NOT AND SWAP1 SSTORE POP JUMPDEST DUP3 PUSH1 0x2 EXP SWAP1 POP PUSH1 0x0 DUP2 DUP4 PUSH1 0x1 ADD SLOAD AND EQ ISZERO PUSH2 0x1887 JUMPI PUSH32 0xE1C52DC63B719ADE82E8BEA94CC41A0D5D28E4AAF536ADB5E9CCCC9FF8C1AEDA CALLER DUP7 PUSH1 0x40 MLOAD DUP1 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD DUP3 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 PUSH1 0x1 DUP3 PUSH1 0x0 ADD SLOAD GT ISZERO ISZERO PUSH2 0x185E JUMPI PUSH2 0x107 PUSH2 0x106 PUSH1 0x0 DUP8 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x2 ADD SLOAD DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x180A JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 ADD PUSH1 0x0 JUMPDEST POP PUSH1 0x0 SWAP1 SSTORE PUSH2 0x106 PUSH1 0x0 DUP7 PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 PUSH1 0x0 DUP3 ADD PUSH1 0x0 SWAP1 SSTORE PUSH1 0x1 DUP3 ADD PUSH1 0x0 SWAP1 SSTORE PUSH1 0x2 DUP3 ADD PUSH1 0x0 SWAP1 SSTORE POP POP PUSH1 0x1 SWAP4 POP PUSH2 0x1888 JUMP JUMPDEST DUP2 PUSH1 0x0 ADD PUSH1 0x0 DUP2 SLOAD DUP1 SWAP3 SWAP2 SWAP1 PUSH1 0x1 SWAP1 SUB SWAP2 SWAP1 POP SSTORE POP DUP1 DUP3 PUSH1 0x1 ADD PUSH1 0x0 DUP3 DUP3 SLOAD OR SWAP3 POP POP DUP2 SWAP1 SSTORE POP JUMPDEST JUMPDEST JUMPDEST POP POP POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH2 0x107 DUP1 SLOAD SWAP1 POP SWAP2 POP PUSH1 0x0 SWAP1 POP JUMPDEST DUP2 DUP2 LT ISZERO PUSH2 0x19BC JUMPI PUSH2 0x108 PUSH1 0x0 PUSH2 0x107 DUP4 DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x18BF JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 ADD PUSH1 0x0 JUMPDEST POP SLOAD PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 PUSH1 0x0 DUP3 ADD PUSH1 0x0 PUSH2 0x100 EXP DUP2 SLOAD SWAP1 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF MUL NOT AND SWAP1 SSTORE PUSH1 0x1 DUP3 ADD PUSH1 0x0 SWAP1 SSTORE PUSH1 0x2 DUP3 ADD PUSH1 0x0 PUSH2 0x1926 SWAP2 SWAP1 PUSH2 0x1BE6 JUMP JUMPDEST POP POP PUSH1 0x0 PUSH1 0x1 MUL PUSH2 0x107 DUP3 DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x193D JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 ADD PUSH1 0x0 JUMPDEST POP SLOAD PUSH1 0x0 NOT AND EQ ISZERO ISZERO PUSH2 0x19B0 JUMPI PUSH2 0x106 PUSH1 0x0 PUSH2 0x107 DUP4 DUP2 SLOAD DUP2 LT ISZERO ISZERO PUSH2 0x196D JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 ADD PUSH1 0x0 JUMPDEST POP SLOAD PUSH1 0x0 NOT AND PUSH1 0x0 NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 PUSH1 0x0 PUSH1 0x0 DUP3 ADD PUSH1 0x0 SWAP1 SSTORE PUSH1 0x1 DUP3 ADD PUSH1 0x0 SWAP1 SSTORE PUSH1 0x2 DUP3 ADD PUSH1 0x0 SWAP1 SSTORE POP POP JUMPDEST JUMPDEST DUP1 PUSH1 0x1 ADD SWAP1 POP PUSH2 0x18A2 JUMP JUMPDEST PUSH2 0x107 PUSH1 0x0 PUSH2 0x19CB SWAP2 SWAP1 PUSH2 0x1CDA JUMP JUMPDEST JUMPDEST POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 SWAP1 POP JUMPDEST PUSH1 0x1 SLOAD DUP2 LT ISZERO PUSH2 0x1B33 JUMPI JUMPDEST PUSH1 0x1 SLOAD DUP2 LT DUP1 ISZERO PUSH2 0x1A09 JUMPI POP PUSH1 0x0 PUSH1 0x5 DUP3 PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1A00 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP SLOAD EQ ISZERO JUMPDEST ISZERO PUSH2 0x1A1B JUMPI DUP1 DUP1 PUSH1 0x1 ADD SWAP2 POP POP PUSH2 0x19E2 JUMP JUMPDEST JUMPDEST PUSH1 0x1 PUSH1 0x1 SLOAD GT DUP1 ISZERO PUSH2 0x1A45 JUMPI POP PUSH1 0x0 PUSH1 0x5 PUSH1 0x1 SLOAD PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1A3D JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP SLOAD EQ JUMPDEST ISZERO PUSH2 0x1A62 JUMPI PUSH1 0x1 PUSH1 0x0 DUP2 SLOAD DUP1 SWAP3 SWAP2 SWAP1 PUSH1 0x1 SWAP1 SUB SWAP2 SWAP1 POP SSTORE POP PUSH2 0x1A1C JUMP JUMPDEST PUSH1 0x1 SLOAD DUP2 LT DUP1 ISZERO PUSH2 0x1A8B JUMPI POP PUSH1 0x0 PUSH1 0x5 PUSH1 0x1 SLOAD PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1A82 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP SLOAD EQ ISZERO JUMPDEST DUP1 ISZERO PUSH2 0x1AAC JUMPI POP PUSH1 0x0 PUSH1 0x5 DUP3 PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1AA4 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP SLOAD EQ JUMPDEST ISZERO PUSH2 0x1B2E JUMPI PUSH1 0x5 PUSH1 0x1 SLOAD PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1AC3 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP SLOAD PUSH1 0x5 DUP3 PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1AD9 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP DUP2 SWAP1 SSTORE POP DUP1 PUSH2 0x105 PUSH1 0x0 PUSH1 0x5 DUP5 PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1AF8 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP SLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 DUP2 SWAP1 SSTORE POP PUSH1 0x0 PUSH1 0x5 PUSH1 0x1 SLOAD PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1B24 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP DUP2 SWAP1 SSTORE POP JUMPDEST PUSH2 0x19D7 JUMP JUMPDEST JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 DUP2 MLOAD PUSH1 0x20 DUP4 ADD DUP5 CREATE SWAP1 POP DUP1 EXTCODESIZE ISZERO PUSH2 0x0 JUMPI JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x1B5C CALLER PUSH2 0x659 JUMP JUMPDEST ISZERO PUSH2 0x1BC9 JUMPI PUSH1 0x4 SLOAD PUSH2 0x1B6C PUSH2 0x1BCF JUMP JUMPDEST GT ISZERO PUSH2 0x1B89 JUMPI PUSH1 0x0 PUSH1 0x3 DUP2 SWAP1 SSTORE POP PUSH2 0x1B82 PUSH2 0x1BCF JUMP JUMPDEST PUSH1 0x4 DUP2 SWAP1 SSTORE POP JUMPDEST PUSH1 0x3 SLOAD DUP3 PUSH1 0x3 SLOAD ADD LT ISZERO DUP1 ISZERO PUSH2 0x1BA5 JUMPI POP PUSH1 0x2 SLOAD DUP3 PUSH1 0x3 SLOAD ADD GT ISZERO JUMPDEST ISZERO PUSH2 0x1BC3 JUMPI DUP2 PUSH1 0x3 PUSH1 0x0 DUP3 DUP3 SLOAD ADD SWAP3 POP POP DUP2 SWAP1 SSTORE POP PUSH1 0x1 SWAP1 POP PUSH2 0x1BC8 JUMP JUMPDEST PUSH1 0x0 SWAP1 POP JUMPDEST JUMPDEST JUMPDEST SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH3 0x15180 TIMESTAMP DUP2 ISZERO ISZERO PUSH2 0x1BDF JUMPI INVALID JUMPDEST DIV SWAP1 POP JUMPDEST SWAP1 JUMP JUMPDEST POP DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV PUSH1 0x0 DUP3 SSTORE DUP1 PUSH1 0x1F LT PUSH2 0x1C0C JUMPI POP PUSH2 0x1C2B JUMP JUMPDEST PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 DUP2 ADD SWAP1 PUSH2 0x1C2A SWAP2 SWAP1 PUSH2 0x1CFC JUMP JUMPDEST JUMPDEST POP JUMP JUMPDEST DUP3 DUP1 SLOAD PUSH1 0x1 DUP2 PUSH1 0x1 AND ISZERO PUSH2 0x100 MUL SUB AND PUSH1 0x2 SWAP1 DIV SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 PUSH1 0x1F ADD PUSH1 0x20 SWAP1 DIV DUP2 ADD SWAP3 DUP3 PUSH1 0x1F LT PUSH2 0x1C6F JUMPI DUP1 CALLDATALOAD PUSH1 0xFF NOT AND DUP4 DUP1 ADD OR DUP6 SSTORE PUSH2 0x1C9D JUMP JUMPDEST DUP3 DUP1 ADD PUSH1 0x1 ADD DUP6 SSTORE DUP3 ISZERO PUSH2 0x1C9D JUMPI SWAP2 DUP3 ADD JUMPDEST DUP3 DUP2 GT ISZERO PUSH2 0x1C9C JUMPI DUP3 CALLDATALOAD DUP3 SSTORE SWAP2 PUSH1 0x20 ADD SWAP2 SWAP1 PUSH1 0x1 ADD SWAP1 PUSH2 0x1C81 JUMP JUMPDEST JUMPDEST POP SWAP1 POP PUSH2 0x1CAA SWAP2 SWAP1 PUSH2 0x1CFC JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST DUP2 SLOAD DUP2 DUP4 SSTORE DUP2 DUP2 ISZERO GT PUSH2 0x1CD5 JUMPI DUP2 DUP4 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP2 DUP3 ADD SWAP2 ADD PUSH2 0x1CD4 SWAP2 SWAP1 PUSH2 0x1D21 JUMP JUMPDEST JUMPDEST POP POP POP JUMP JUMPDEST POP DUP1 SLOAD PUSH1 0x0 DUP3 SSTORE SWAP1 PUSH1 0x0 MSTORE PUSH1 0x20 PUSH1 0x0 SHA3 SWAP1 DUP2 ADD SWAP1 PUSH2 0x1CF8 SWAP2 SWAP1 PUSH2 0x1D21 JUMP JUMPDEST JUMPDEST POP JUMP JUMPDEST PUSH2 0x1D1E SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH2 0x1D1A JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH2 0x1D02 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH2 0x1D43 SWAP2 SWAP1 JUMPDEST DUP1 DUP3 GT ISZERO PUSH2 0x1D3F JUMPI PUSH1 0x0 DUP2 PUSH1 0x0 SWAP1 SSTORE POP PUSH1 0x1 ADD PUSH2 0x1D27 JUMP JUMPDEST POP SWAP1 JUMP JUMPDEST SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 SLOAD GT ISZERO PUSH2 0x1D57 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST PUSH2 0x1D60 DUP2 PUSH2 0x1D71 JUMP JUMPDEST PUSH2 0x1D6A DUP4 DUP4 PUSH2 0x1D9C JUMP JUMPDEST JUMPDEST JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x1 SLOAD GT ISZERO PUSH2 0x1D82 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST DUP1 PUSH1 0x2 DUP2 SWAP1 SSTORE POP PUSH2 0x1D91 PUSH2 0x1BCF JUMP JUMPDEST PUSH1 0x4 DUP2 SWAP1 SSTORE POP JUMPDEST JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x0 PUSH1 0x1 SLOAD GT ISZERO PUSH2 0x1DAF JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST PUSH1 0x0 DUP3 GT ISZERO ISZERO PUSH2 0x1DBF JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST DUP2 DUP4 MLOAD LT ISZERO ISZERO ISZERO PUSH2 0x1DD0 JUMPI PUSH1 0x0 PUSH1 0x0 REVERT JUMPDEST DUP3 MLOAD PUSH1 0x1 DUP2 SWAP1 SSTORE POP PUSH1 0x0 SWAP1 POP JUMPDEST DUP3 MLOAD DUP2 LT ISZERO PUSH2 0x1E85 JUMPI DUP3 DUP2 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x1DF4 JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x5 DUP3 PUSH1 0x1 ADD PUSH2 0x100 DUP2 LT ISZERO ISZERO PUSH2 0x1E27 JUMPI INVALID JUMPDEST ADD PUSH1 0x0 JUMPDEST POP DUP2 SWAP1 SSTORE POP DUP1 PUSH1 0x1 ADD PUSH2 0x105 PUSH1 0x0 DUP6 DUP5 DUP2 MLOAD DUP2 LT ISZERO ISZERO PUSH2 0x1E47 JUMPI INVALID JUMPDEST SWAP1 PUSH1 0x20 ADD SWAP1 PUSH1 0x20 MUL ADD MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 SHA3 DUP2 SWAP1 SSTORE POP JUMPDEST DUP1 PUSH1 0x1 ADD SWAP1 POP PUSH2 0x1DDD JUMP JUMPDEST DUP2 PUSH1 0x0 DUP2 SWAP1 SSTORE POP JUMPDEST JUMPDEST POP POP POP JUMP STOP LOG1 PUSH6 0x627A7A723058 SHA3 AND DUP9 SWAP16 SMOD BLOCKHASH CREATE PUSH20 0xD397F9D00B0D19900FB050B957E3E2942F861085 0xbe 0xb9 0xba 0xab XOR STOP 0x29 &quot;,
	&quot;sourceMap&quot;: &quot;2715:10853:0:-;;;3523:112;;;;;;;3552:18;3574:8;:27;;;;;;;;;;;:::i;:::-;;;;;;;;;;;3596:3;3574:27;;;;;;;;;;;;;;;;;;;;;;;3605:26;3616:8;3605:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3626:1;3629;3605:10;;;;;:26;;;:::i;:::-;3523:112;;2715:10853;;7697:168;7585:1;7571:11;;:15;7567:26;;;7588:5;;;7567:26;7800:23;7813:9;7800:12;;;;;:23;;;:::i;:::-;7827:34;7842:7;7851:9;7827:14;;;;;:34;;;:::i;:::-;7595:1;7697:168;;;;:::o;6966:115::-;7585:1;7571:11;;:15;7567:26;;;7588:5;;;7567:26;7048:6;7033:12;:21;;;;7070:7;:5;;;;;:7;;;:::i;:::-;7058:9;:19;;;;7595:1;6966:115;;:::o;3977:349::-;4171:6;7585:1;7571:11;;:15;7567:26;;;7588:5;;;7567:26;4088:1;4076:9;:13;4068:22;;;;;;;;4120:9;4102:7;:14;:27;;4094:36;;;;;;;;4148:7;:14;4134:11;:28;;;;4180:1;4171:10;;4166:131;4187:7;:14;4183:1;:18;4166:131;;;4238:7;4246:1;4238:10;;;;;;;;;;;;;;;;;;4233:16;;4215:8;4228:1;4224;:5;4215:15;;;;;;;;;;;;:34;;;;;4291:1;4287;:5;4254:12;:30;4272:7;4280:1;4272:10;;;;;;;;;;;;;;;;;;4267:16;;4254:30;;;;;;;;;;;:38;;;;4166:131;4203:3;;;;;4166:131;;;4313:9;4300:10;:22;;;;7595:1;3977:349;;;;:::o;12529:73::-;12572:4;12593:6;12587:3;:12;;;;;;;;12580:19;;12529:73;;:::o;2715:10853::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;&quot;,
	&quot;linkReferences&quot;: {}
}
```

To verify the byte-code above, a patched version is deployed at
[`0x21C9E434c669c4d73f55215A6F2130A185E127AC`](https://etherscan.io/address/0x21C9E434c669c4d73f55215A6F2130A185E127AC#code)
to be reviewed. The compiler settings used can be extracted from the following
meta-data:

```json
{&quot;compiler&quot;:{&quot;version&quot;:&quot;0.4.10+commit.f0d539ae&quot;},&quot;language&quot;:&quot;Solidity&quot;,&quot;output&quot;:{&quot;abi&quot;:[{&quot;constant&quot;:false,&quot;inputs&quot;:[{&quot;name&quot;:&quot;_owner&quot;,&quot;type&quot;:&quot;address&quot;}],&quot;name&quot;:&quot;removeOwner&quot;,&quot;outputs&quot;:[],&quot;payable&quot;:false,&quot;type&quot;:&quot;function&quot;},{&quot;constant&quot;:true,&quot;inputs&quot;:[{&quot;name&quot;:&quot;_addr&quot;,&quot;type&quot;:&quot;address&quot;}],&quot;name&quot;:&quot;isOwner&quot;,&quot;outputs&quot;:[{&quot;name&quot;:&quot;&quot;,&quot;type&quot;:&quot;bool&quot;}],&quot;payable&quot;:false,&quot;type&quot;:&quot;function&quot;},{&quot;constant&quot;:true,&quot;inputs&quot;:[],&quot;name&quot;:&quot;m_numOwners&quot;,&quot;outputs&quot;:[{&quot;name&quot;:&quot;&quot;,&quot;type&quot;:&quot;uint256&quot;}],&quot;payable&quot;:false,&quot;type&quot;:&quot;function&quot;},{&quot;constant&quot;:true,&quot;inputs&quot;:[],&quot;name&quot;:&quot;m_lastDay&quot;,&quot;outputs&quot;:[{&quot;name&quot;:&quot;&quot;,&quot;type&quot;:&quot;uint256&quot;}],&quot;payable&quot;:false,&quot;type&quot;:&quot;function&quot;},{&quot;constant&quot;:false,&quot;inputs&quot;:[],&quot;name&quot;:&quot;resetSpentToday&quot;,&quot;outputs&quot;:[],&quot;payable&quot;:false,&quot;type&quot;:&quot;function&quot;},{&quot;constant&quot;:true,&quot;inputs&quot;:[],&quot;name&quot;:&quot;m_spentToday&quot;,&quot;outputs&quot;:[{&quot;name&quot;:&quot;&quot;,&quot;type&quot;:&quot;uint256&quot;}],&quot;payable&quot;:false,&quot;type&quot;:&quot;function&quot;},{&quot;constant&quot;:false,&quot;inputs&quot;:[{&quot;name&quot;:&quot;_owner&quot;,&quot;type&quot;:&quot;address&quot;}],&quot;name&quot;:&quot;addOwner&quot;,&quot;outputs&quot;:[],&quot;payable&quot;:false,&quot;type&quot;:&quot;function&quot;},{&quot;constant&quot;:true,&quot;inputs&quot;:[],&quot;name&quot;:&quot;m_required&quot;,&quot;outputs&quot;:[{&quot;name&quot;:&quot;&quot;,&quot;type&quot;:&quot;uint256&quot;}],&quot;payable&quot;:false,&quot;type&quot;:&quot;function&quot;},{&quot;constant&quot;:false,&quot;inputs&quot;:[{&quot;name&quot;:&quot;_h&quot;,&quot;type&quot;:&quot;bytes32&quot;}],&quot;name&quot;:&quot;confirm&quot;,&quot;outputs&quot;:[{&quot;name&quot;:&quot;o_success&quot;,&quot;type&quot;:&quot;bool&quot;}],&quot;payable&quot;:false,&quot;type&quot;:&quot;function&quot;},{&quot;constant&quot;:false,&quot;inputs&quot;:[{&quot;name&quot;:&quot;_newLimit&quot;,&quot;type&quot;:&quot;uint256&quot;}],&quot;name&quot;:&quot;setDailyLimit&quot;,&quot;outputs&quot;:[],&quot;payable&quot;:false,&quot;type&quot;:&quot;function&quot;},{&quot;constant&quot;:false,&quot;inputs&quot;:[{&quot;name&quot;:&quot;_to&quot;,&quot;type&quot;:&quot;address&quot;},{&quot;name&quot;:&quot;_value&quot;,&quot;type&quot;:&quot;uint256&quot;},{&quot;name&quot;:&quot;_data&quot;,&quot;type&quot;:&quot;bytes&quot;}],&quot;name&quot;:&quot;execute&quot;,&quot;outputs&quot;:[{&quot;name&quot;:&quot;o_hash&quot;,&quot;type&quot;:&quot;bytes32&quot;}],&quot;payable&quot;:false,&quot;type&quot;:&quot;function&quot;},{&quot;constant&quot;:false,&quot;inputs&quot;:[{&quot;name&quot;:&quot;_operation&quot;,&quot;type&quot;:&quot;bytes32&quot;}],&quot;name&quot;:&quot;revoke&quot;,&quot;outputs&quot;:[],&quot;payable&quot;:false,&quot;type&quot;:&quot;function&quot;},{&quot;constant&quot;:false,&quot;inputs&quot;:[{&quot;name&quot;:&quot;_newRequired&quot;,&quot;type&quot;:&quot;uint256&quot;}],&quot;name&quot;:&quot;changeRequirement&quot;,&quot;outputs&quot;:[],&quot;payable&quot;:false,&quot;type&quot;:&quot;function&quot;},{&quot;constant&quot;:true,&quot;inputs&quot;:[{&quot;name&quot;:&quot;_operation&quot;,&quot;type&quot;:&quot;bytes32&quot;},{&quot;name&quot;:&quot;_owner&quot;,&quot;type&quot;:&quot;address&quot;}],&quot;name&quot;:&quot;hasConfirmed&quot;,&quot;outputs&quot;:[{&quot;name&quot;:&quot;&quot;,&quot;type&quot;:&quot;bool&quot;}],&quot;payable&quot;:false,&quot;type&quot;:&quot;function&quot;},{&quot;constant&quot;:true,&quot;inputs&quot;:[{&quot;name&quot;:&quot;ownerIndex&quot;,&quot;type&quot;:&quot;uint256&quot;}],&quot;name&quot;:&quot;getOwner&quot;,&quot;outputs&quot;:[{&quot;name&quot;:&quot;&quot;,&quot;type&quot;:&quot;address&quot;}],&quot;payable&quot;:false,&quot;type&quot;:&quot;function&quot;},{&quot;constant&quot;:false,&quot;inputs&quot;:[{&quot;name&quot;:&quot;_from&quot;,&quot;type&quot;:&quot;address&quot;},{&quot;name&quot;:&quot;_to&quot;,&quot;type&quot;:&quot;address&quot;}],&quot;name&quot;:&quot;changeOwner&quot;,&quot;outputs&quot;:[],&quot;payable&quot;:false,&quot;type&quot;:&quot;function&quot;},{&quot;constant&quot;:true,&quot;inputs&quot;:[],&quot;name&quot;:&quot;m_dailyLimit&quot;,&quot;outputs&quot;:[{&quot;name&quot;:&quot;&quot;,&quot;type&quot;:&quot;uint256&quot;}],&quot;payable&quot;:false,&quot;type&quot;:&quot;function&quot;},{&quot;inputs&quot;:[],&quot;payable&quot;:false,&quot;type&quot;:&quot;constructor&quot;},{&quot;payable&quot;:true,&quot;type&quot;:&quot;fallback&quot;},{&quot;anonymous&quot;:false,&quot;inputs&quot;:[{&quot;indexed&quot;:false,&quot;name&quot;:&quot;owner&quot;,&quot;type&quot;:&quot;address&quot;},{&quot;indexed&quot;:false,&quot;name&quot;:&quot;operation&quot;,&quot;type&quot;:&quot;bytes32&quot;}],&quot;name&quot;:&quot;Confirmation&quot;,&quot;type&quot;:&quot;event&quot;},{&quot;anonymous&quot;:false,&quot;inputs&quot;:[{&quot;indexed&quot;:false,&quot;name&quot;:&quot;owner&quot;,&quot;type&quot;:&quot;address&quot;},{&quot;indexed&quot;:false,&quot;name&quot;:&quot;operation&quot;,&quot;type&quot;:&quot;bytes32&quot;}],&quot;name&quot;:&quot;Revoke&quot;,&quot;type&quot;:&quot;event&quot;},{&quot;anonymous&quot;:false,&quot;inputs&quot;:[{&quot;indexed&quot;:false,&quot;name&quot;:&quot;oldOwner&quot;,&quot;type&quot;:&quot;address&quot;},{&quot;indexed&quot;:false,&quot;name&quot;:&quot;newOwner&quot;,&quot;type&quot;:&quot;address&quot;}],&quot;name&quot;:&quot;OwnerChanged&quot;,&quot;type&quot;:&quot;event&quot;},{&quot;anonymous&quot;:false,&quot;inputs&quot;:[{&quot;indexed&quot;:false,&quot;name&quot;:&quot;newOwner&quot;,&quot;type&quot;:&quot;address&quot;}],&quot;name&quot;:&quot;OwnerAdded&quot;,&quot;type&quot;:&quot;event&quot;},{&quot;anonymous&quot;:false,&quot;inputs&quot;:[{&quot;indexed&quot;:false,&quot;name&quot;:&quot;oldOwner&quot;,&quot;type&quot;:&quot;address&quot;}],&quot;name&quot;:&quot;OwnerRemoved&quot;,&quot;type&quot;:&quot;event&quot;},{&quot;anonymous&quot;:false,&quot;inputs&quot;:[{&quot;indexed&quot;:false,&quot;name&quot;:&quot;newRequirement&quot;,&quot;type&quot;:&quot;uint256&quot;}],&quot;name&quot;:&quot;RequirementChanged&quot;,&quot;type&quot;:&quot;event&quot;},{&quot;anonymous&quot;:false,&quot;inputs&quot;:[{&quot;indexed&quot;:false,&quot;name&quot;:&quot;_from&quot;,&quot;type&quot;:&quot;address&quot;},{&quot;indexed&quot;:false,&quot;name&quot;:&quot;value&quot;,&quot;type&quot;:&quot;uint256&quot;}],&quot;name&quot;:&quot;Deposit&quot;,&quot;type&quot;:&quot;event&quot;},{&quot;anonymous&quot;:false,&quot;inputs&quot;:[{&quot;indexed&quot;:false,&quot;name&quot;:&quot;owner&quot;,&quot;type&quot;:&quot;address&quot;},{&quot;indexed&quot;:false,&quot;name&quot;:&quot;value&quot;,&quot;type&quot;:&quot;uint256&quot;},{&quot;indexed&quot;:false,&quot;name&quot;:&quot;to&quot;,&quot;type&quot;:&quot;address&quot;},{&quot;indexed&quot;:false,&quot;name&quot;:&quot;data&quot;,&quot;type&quot;:&quot;bytes&quot;},{&quot;indexed&quot;:false,&quot;name&quot;:&quot;created&quot;,&quot;type&quot;:&quot;address&quot;}],&quot;name&quot;:&quot;SingleTransact&quot;,&quot;type&quot;:&quot;event&quot;},{&quot;anonymous&quot;:false,&quot;inputs&quot;:[{&quot;indexed&quot;:false,&quot;name&quot;:&quot;owner&quot;,&quot;type&quot;:&quot;address&quot;},{&quot;indexed&quot;:false,&quot;name&quot;:&quot;operation&quot;,&quot;type&quot;:&quot;bytes32&quot;},{&quot;indexed&quot;:false,&quot;name&quot;:&quot;value&quot;,&quot;type&quot;:&quot;uint256&quot;},{&quot;indexed&quot;:false,&quot;name&quot;:&quot;to&quot;,&quot;type&quot;:&quot;address&quot;},{&quot;indexed&quot;:false,&quot;name&quot;:&quot;data&quot;,&quot;type&quot;:&quot;bytes&quot;},{&quot;indexed&quot;:false,&quot;name&quot;:&quot;created&quot;,&quot;type&quot;:&quot;address&quot;}],&quot;name&quot;:&quot;MultiTransact&quot;,&quot;type&quot;:&quot;event&quot;},{&quot;anonymous&quot;:false,&quot;inputs&quot;:[{&quot;indexed&quot;:false,&quot;name&quot;:&quot;operation&quot;,&quot;type&quot;:&quot;bytes32&quot;},{&quot;indexed&quot;:false,&quot;name&quot;:&quot;initiator&quot;,&quot;type&quot;:&quot;address&quot;},{&quot;indexed&quot;:false,&quot;name&quot;:&quot;value&quot;,&quot;type&quot;:&quot;uint256&quot;},{&quot;indexed&quot;:false,&quot;name&quot;:&quot;to&quot;,&quot;type&quot;:&quot;address&quot;},{&quot;indexed&quot;:false,&quot;name&quot;:&quot;data&quot;,&quot;type&quot;:&quot;bytes&quot;}],&quot;name&quot;:&quot;ConfirmationNeeded&quot;,&quot;type&quot;:&quot;event&quot;}],&quot;devdoc&quot;:{&quot;methods&quot;:{}},&quot;userdoc&quot;:{&quot;methods&quot;:{}}},&quot;settings&quot;:{&quot;compilationTarget&quot;:{&quot;browser/WalletLibrary.sol&quot;:&quot;WalletLibrary&quot;},&quot;libraries&quot;:{},&quot;optimizer&quot;:{&quot;enabled&quot;:false,&quot;runs&quot;:200},&quot;remappings&quot;:[]},&quot;sources&quot;:{&quot;browser/WalletLibrary.sol&quot;:{&quot;keccak256&quot;:&quot;0xf72fcdc85e15f93172878ca6a61fb81604d1052e9e724bc3896d65b3b4ab1bb0&quot;,&quot;urls&quot;:[&quot;bzzr://009bd59bd78f59804eaffb6111d341caea58888f8e5b5f75aebdf009fc6136c0&quot;]}},&quot;version&quot;:1}
```

The differences to the originally deployed contract code can be reviewed at:

* [parity-contracts/0x863df6bfa4#2](https://github.com/parity-contracts/0x863df6bfa4/pull/2):
Remove the `selfdestruct()`
* [parity-contracts/0x863df6bfa4#3](https://github.com/parity-contracts/0x863df6bfa4/pull/3):
Initialize the library owner to `0x0`

The following sections propose two equivalent specifications, 999a and 999b,
which technically achieve the same results. To implement this proposal only one
of them has to be applied.

### Direct State Transition via Bytecode (999a)
At `CNSTNTNPL_FORK_BLKNUM`, directly recreate the account
`0x863DF6BFa4469f3ead0bE8f9F2AAE51c91A907b4` with the following parameters:

* Nonce: `0x1`
* Code:

```
0x606060405236156100ef576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063173825d91461016d5780632f54bf6e146101a35780634123cb6b146101f157806352375093146102175780635c52c2f51461023d578063659010e71461024f5780637065cb4814610275578063746c9171146102ab578063797af627146102d1578063b20d30a91461030d578063b61d27f61461032d578063b75c7dc61461039c578063ba51a6df146103c0578063c2cf7326146103e0578063c41a360a1461043b578063f00d4b5d1461049b578063f1736d86146104f0575b61016b5b6000341115610168577fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c3334604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a15b5b565b005b341561017557fe5b6101a1600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610516565b005b34156101ab57fe5b6101d7600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610659565b604051808215151515815260200191505060405180910390f35b34156101f957fe5b610201610691565b6040518082815260200191505060405180910390f35b341561021f57fe5b610227610697565b6040518082815260200191505060405180910390f35b341561024557fe5b61024d61069d565b005b341561025757fe5b61025f6106d7565b6040518082815260200191505060405180910390f35b341561027d57fe5b6102a9600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506106dd565b005b34156102b357fe5b6102bb610829565b6040518082815260200191505060405180910390f35b34156102d957fe5b6102f360048080356000191690602001909190505061082f565b604051808215151515815260200191505060405180910390f35b341561031557fe5b61032b6004808035906020019091905050610dcc565b005b341561033557fe5b61037e600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919080359060200190820180359060200191909192905050610e06565b60405180826000191660001916815260200191505060405180910390f35b34156103a457fe5b6103be60048080356000191690602001909190505061127d565b005b34156103c857fe5b6103de6004808035906020019091905050611392565b005b34156103e857fe5b61042160048080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061141a565b604051808215151515815260200191505060405180910390f35b341561044357fe5b610459600480803590602001909190505061149c565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156104a357fe5b6104ee600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506114bf565b005b34156104f857fe5b610500611672565b6040518082815260200191505060405180910390f35b600060003660405180838380828437820191505092505050604051809103902061053f81611678565b156106535761010560008473ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549150600082141561057f57610652565b600160015403600054111561059357610652565b6000600583610100811015156105a557fe5b0160005b5081905550600061010560008573ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506105e6611890565b6105ee6119d0565b7f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da83604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a15b5b5b505050565b6000600061010560008473ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541190505b919050565b60015481565b60045481565b6000366040518083838082843782019150509250505060405180910390206106c481611678565b156106d35760006003819055505b5b5b50565b60035481565b60003660405180838380828437820191505092505050604051809103902061070481611678565b156108245761071282610659565b1561071c57610823565b610724611890565b60fa600154101515610739576107386119d0565b5b60fa60015410151561074a57610823565b6001600081548092919060010191905055508173ffffffffffffffffffffffffffffffffffffffff1660056001546101008110151561078557fe5b0160005b508190555060015461010560008473ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c382604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a15b5b5b5050565b60005481565b600060008261083d81611678565b15610dc45760006101086000866000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415806108c757506000610108600086600019166000191681526020019081526020016000206001015414155b80610906575060006101086000866000191660001916815260200190815260200160002060020180546001816001161561010002031660029004905014155b15610dc25760006101086000866000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610a5057610a496101086000866000191660001916815260200190815260200160002060010154610108600087600019166000191681526020019081526020016000206002018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a3f5780601f10610a1457610100808354040283529160200191610a3f565b820191906000526020600020905b815481529060010190602001808311610a2257829003601f168201915b5050505050611b37565b9150610b71565b6101086000856000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166101086000866000191660001916815260200190815260200160002060010154610108600087600019166000191681526020019081526020016000206002016040518082805460018160011615610100020316600290048015610b4a5780601f10610b1f57610100808354040283529160200191610b4a565b820191906000526020600020905b815481529060010190602001808311610b2d57829003601f168201915b505091505060006040518083038185876185025a03f1925050501515610b705760006000fd5b5b7fe3a3a4111a84df27d76b68dc721e65c7711605ea5eee4afd3a9c58195217365c338561010860008860001916600019168152602001908152602001600020600101546101086000896000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1661010860008a6000191660001916815260200190815260200160002060020187604051808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200186600019166000191681526020018581526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828103825284818154600181600116156101000203166002900481526020019150805460018160011615610100020316600290048015610d475780601f10610d1c57610100808354040283529160200191610d47565b820191906000526020600020905b815481529060010190602001808311610d2a57829003601f168201915b505097505050505050505060405180910390a16101086000856000191660001916815260200190815260200160002060006000820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001820160009055600282016000610db79190611be6565b505060019250610dc3565b5b5b5b5050919050565b600036604051808383808284378201915050925050506040518091039020610df381611678565b15610e0157816002819055505b5b5b5050565b60006000610e1333610659565b1561127357600084849050148015610e305750610e2f85611b51565b5b80610e3d57506001600054145b15610fed5760008673ffffffffffffffffffffffffffffffffffffffff161415610ea457610e9d8585858080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050611b37565b9050610ef3565b8573ffffffffffffffffffffffffffffffffffffffff168585856040518083838082843782019150509250505060006040518083038185876185025a03f1925050501515610ef25760006000fd5b5b7f9738cd1a8777c86b011f7b01d87d484217dc6ab5154a9d41eda5d14af8caf292338688878786604051808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001806020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281038252858582818152602001925080828437820191505097505050505050505060405180910390a1611271565b6000364360405180848480828437820191505082815260200193505050506040518091039020915060006101086000846000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16148015611099575060006101086000846000191660001916815260200190815260200160002060010154145b80156110d85750600061010860008460001916600019168152602001908152602001600020600201805460018160011615610100020316600290049050145b1561118f57856101086000846000191660001916815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550846101086000846000191660001916815260200190815260200160002060010181905550838361010860008560001916600019168152602001908152602001600020600201919061118d929190611c2e565b505b6111988261082f565b1515611270577f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf328233878988886040518087600019166000191681526020018673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018581526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001806020018281038252848482818152602001925080828437820191505097505050505050505060405180910390a15b5b5b5b5b50949350505050565b60006000600061010560003373ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054925060008314156112be5761138c565b8260020a9150610106600085600019166000191681526020019081526020016000209050600082826001015416111561138b5780600001600081548092919060010191905055508181600101600082825403925050819055507fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b3385604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182600019166000191681526020019250505060405180910390a15b5b50505050565b6000366040518083838082843782019150509250505060405180910390206113b981611678565b15611415576001548211156113cd57611414565b816000819055506113dc611890565b7facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da826040518082815260200191505060405180910390a15b5b5b5050565b600060006000600061010660008760001916600019168152602001908152602001600020925061010560008673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549150600082141561147f5760009350611493565b8160020a9050600081846001015416141593505b50505092915050565b6000600560018301610100811015156114b157fe5b0160005b505490505b919050565b60006000366040518083838082843782019150509250505060405180910390206114e881611678565b1561166b576114f683610659565b156115005761166a565b61010560008573ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549150600082141561153b5761166a565b611543611890565b8273ffffffffffffffffffffffffffffffffffffffff166005836101008110151561156a57fe5b0160005b5081905550600061010560008673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508161010560008573ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c8484604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a15b5b5b50505050565b60025481565b600060006000600061010560003373ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054925060008314156116bb57611888565b6101066000866000191660001916815260200190815260200160002091506000826000015414156117455760005482600001819055506000826001018190555061010780548091906001016117109190611cae565b826002018190555084610107836002015481548110151561172d57fe5b906000526020600020900160005b5081600019169055505b8260020a90506000818360010154161415611887577fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda3386604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182600019166000191681526020019250505060405180910390a16001826000015411151561185e57610107610106600087600019166000191681526020019081526020016000206002015481548110151561180a57fe5b906000526020600020900160005b5060009055610106600086600019166000191681526020019081526020016000206000600082016000905560018201600090556002820160009055505060019350611888565b8160000160008154809291906001900391905055508082600101600082825417925050819055505b5b5b505050919050565b60006000610107805490509150600090505b818110156119bc576101086000610107838154811015156118bf57fe5b906000526020600020900160005b50546000191660001916815260200190815260200160002060006000820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560018201600090556002820160006119269190611be6565b505060006001026101078281548110151561193d57fe5b906000526020600020900160005b5054600019161415156119b05761010660006101078381548110151561196d57fe5b906000526020600020900160005b505460001916600019168152602001908152602001600020600060008201600090556001820160009055600282016000905550505b5b8060010190506118a2565b61010760006119cb9190611cda565b5b5050565b6000600190505b600154811015611b33575b60015481108015611a095750600060058261010081101515611a0057fe5b0160005b505414155b15611a1b5780806001019150506119e2565b5b6001600154118015611a4557506000600560015461010081101515611a3d57fe5b0160005b5054145b15611a625760016000815480929190600190039190505550611a1c565b60015481108015611a8b57506000600560015461010081101515611a8257fe5b0160005b505414155b8015611aac5750600060058261010081101515611aa457fe5b0160005b5054145b15611b2e57600560015461010081101515611ac357fe5b0160005b505460058261010081101515611ad957fe5b0160005b508190555080610105600060058461010081101515611af857fe5b0160005b50548152602001908152602001600020819055506000600560015461010081101515611b2457fe5b0160005b50819055505b6119d7565b5b50565b600081516020830184f09050803b15610000575b92915050565b6000611b5c33610659565b15611bc957600454611b6c611bcf565b1115611b89576000600381905550611b82611bcf565b6004819055505b600354826003540110158015611ba55750600254826003540111155b15611bc3578160036000828254019250508190555060019050611bc8565b600090505b5b5b919050565b60006201518042811515611bdf57fe5b0490505b90565b50805460018160011615610100020316600290046000825580601f10611c0c5750611c2b565b601f016020900490600052602060002090810190611c2a9190611cfc565b5b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611c6f57803560ff1916838001178555611c9d565b82800160010185558215611c9d579182015b82811115611c9c578235825591602001919060010190611c81565b5b509050611caa9190611cfc565b5090565b815481835581811511611cd557818360005260206000209182019101611cd49190611d21565b5b505050565b5080546000825590600052602060002090810190611cf89190611d21565b5b50565b611d1e91905b80821115611d1a576000816000905550600101611d02565b5090565b90565b611d4391905b80821115611d3f576000816000905550600101611d27565b5090565b90565b60006001541115611d575760006000fd5b611d6081611d71565b611d6a8383611d9c565b5b5b505050565b60006001541115611d825760006000fd5b80600281905550611d91611bcf565b6004819055505b5b50565b600060006001541115611daf5760006000fd5b600082111515611dbf5760006000fd5b81835110151515611dd05760006000fd5b8251600181905550600090505b8251811015611e85578281815181101515611df457fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff1660058260010161010081101515611e2757fe5b0160005b50819055508060010161010560008584815181101515611e4757fe5b9060200190602002015173ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b806001019050611ddd565b816000819055505b5b5050505600a165627a7a7230582084feb3505964efa62a6ffa78d913a175fe7bc168dd50067d25b1d5ddb6d10a1e0029
```

* Storage:
	* `0x0000000000000000000000000000000000000000000000000000000000000000`:
`0x0000000000000000000000000000000000000000000000000000000000000001`
	* `0x0000000000000000000000000000000000000000000000000000000000000001`:
`0x0000000000000000000000000000000000000000000000000000000000000001`
	* `0x0000000000000000000000000000000000000000000000000000000000000004`:
`0x00000000000000000000000000000000000000000000000000000000000044e1`
	* `0xa5baec7d73105a3c7298203bb205bbc41b63fa384ae73a6016b890a7ca29ae2d`:
`0x0000000000000000000000000000000000000000000000000000000000000001`

The balance of the account shall be left unchanged.

### Alternate Specification via Codehash (999b)
At `CNSTNTNPL_FORK_BLKNUM`, directly recreate the account
`0x863DF6BFa4469f3ead0bE8f9F2AAE51c91A907b4` with the following parameters:

* Nonce: `0x1`
* Storage:
	* `0x0000000000000000000000000000000000000000000000000000000000000000`:
`0x0000000000000000000000000000000000000000000000000000000000000001`
	* `0x0000000000000000000000000000000000000000000000000000000000000001`:
`0x0000000000000000000000000000000000000000000000000000000000000001`
	* `0x0000000000000000000000000000000000000000000000000000000000000004`:
`0x00000000000000000000000000000000000000000000000000000000000044e1`
	* `0xa5baec7d73105a3c7298203bb205bbc41b63fa384ae73a6016b890a7ca29ae2d`:
`0x0000000000000000000000000000000000000000000000000000000000000001`

In addition, the codehash at that address shall be replaced by the codehash at
address `0x21C9E434c669c4d73f55215A6F2130A185E127AC`. The codehash is
`0x6209d55547da7b035d54ef8d73275e863d3072b91da6ace1614fa6381f4e2c09`. The
balance of the account shall be left unchanged.

## Rationale
The design decision to restore the `WalletLibrary` contract code in a single
state transition was made after lengthy discussions of
[alternate proposals](https://gist.github.com/5chdn/a9bb8617cc8523a030126a3d1c60baf3)
that explored different ways to improve the Ethereum protocol to allow contract
revivals by adding different built-in contracts. It was eventually concluded
that all of these proposals changing the EVM semantics around self-destructed
contracts were introducing unwanted side-effects and
[potential risks](https://medium.com/@weka/on-paritys-proposed-changes-to-selfdestruct-behaviour-c3f0e5bc0f49)
to the existing smart-contract ecosystem on the Ethereum platform.

The total supply of Ether is neither changed nor does this proposal require the
transfer of any tokens or assets including Ether. It is assumed that this change
is aligned with the interests both of (A) Parity Technologies that intended to
provide a smart-contracts library for multi-signature wallets to last forever
for its users and (B) the users of the multi-signature wallets that meant to
safely store their assets in a contract accessible any time they desire. Lastly,
the client-side implementation cost of this proposal is estimated to be low. A
sample implementation will be attached and linked in the following sections.

## Backwards Compatibility
This proposal introduces backwards incompatibilities in the state of the
contract at `0x863DF6BFa4469f3ead0bE8f9F2AAE51c91A907b4`. The Ethereum protocol
does not allow the restoration of self-destructed contracts. To implement this
on the Ethereum blockchain, it is recommended to add the necessary state
transition in a future hard-fork at a well-defined block number, e.g.,
`CNSTNTNPL_FORK_BLKNUM` for the Constantinople milestone which is supposed to be
the next scheduled hard-fork on the Ethereum road-map.

## Implementation
A proof-of-concept implementation is available for the Parity client on branch
[`a5-eip999-poc`](https://github.com/paritytech/parity/compare/a5-eip999-poc)
([#8406](https://github.com/paritytech/parity/pull/8406)). A sample chain
configuration for Parity can be found at the same branch in
[`multisig_test.json`](https://github.com/paritytech/parity/blob/891e633021eec78dd62104bf5a99af50f66b06c7/ethcore/res/ethereum/multisig_test.json#L38-L51)
describing the state change as specified above.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 04 Apr 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-999</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-999</guid>
      </item>
    
      <item>
        <title>Uniformity Between 0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B and 0x15E55EF43efA8348dDaeAa455F16C43B64917e3c</title>
        <category>Standards Track/Core</category>
        
          <comments>https://github.com/andywesley/EIPs/issues/1</comments>
        
        <description>## Simple Summary

This document proposes to improve the uniformity of ether distribution
between wallet address `0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B` and
wallet address `0x15E55EF43efA8348dDaeAa455F16C43B64917e3c` which are
currently experiencing a significant non-uniformity.

## Abstract

As of the date of this EIP, the difference in balance between
address `0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B` and address
`0x15E55EF43efA8348dDaeAa455F16C43B64917e3c` is far from equitable
or uniform, with the former having more than 365,000 ether
more than the latter. The distribution of ether between these two
addresses must be improved in order to protect the Ethereum economy
from centralized control. This will be accomplished by transferring
100,000 ether from the former address to the latter. This is a properly
motivated improvement in keeping with the core Ethereum philosophy of
decentralization.

## Motivation

This proposal is necessary because the Ethereum protocol does not allow
the owner of an address which does not own an equitable amount of ether
to claim their share of ether from an address which owns a dangerously
centralized quantity. Rather than proposing an overly complicated generic
mechanism for any user to claim ether to which they believe they are
equitably entitled, this proposal will take the simple route of a one-time
transfer of 100,000 ether from `0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B`
to `0x15E55EF43efA8348dDaeAa455F16C43B64917e3c`. This avoids duplicating
the effort of other proposals and provides a net improvement to the
Ethereum project and community.

## Specification

The balance of `0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B` will be decreased
by 100,000 ether. The balance of `0x15E55EF43efA8348dDaeAa455F16C43B64917e3c`
will be increased by 100,000 ether. No net change in the amount of extant
ether will occur unless at the time of implementation the former address does not
contain sufficient ether for such a deduction.

## Rationale

The value 100,000 was chosen after careful technically sound analysis of various economic theories
developed over the past century. In spite of the fact that it is a convenient round
number, it is actually the exact output of a complex statistical process iterated to
determine the optimal distribution of ether between these addresses.

## Backwards Compatibility

Clients that fail to implement this change will not be aware of the correct balances
for these addresses. This will create a hard fork. The implementation of this change
consistently among all clients as intended by the proposal process will be sufficient
to ensure that backwards compatibility is not a concern.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 18 Apr 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1010</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1010</guid>
      </item>
    
      <item>
        <title>Hybrid Casper FFG</title>
        <category>Standards Track/Core</category>
        
          <comments>https://github.com/djrtwo/EIPs/issues/5</comments>
        
        <description>## Simple Summary

Specification of the first step to transition Ethereum main net from Proof of Work (PoW) to Proof of Stake (PoS). The resulting consensus model is a PoW/PoS hybrid.

## Abstract

This EIP specifies a hybrid PoW/PoS consensus model for Ethereum main net. Existing PoW mechanics are used for new block creation, and a novel PoS mechanism called Casper the Friendly Finality Gadget (FFG) is layered on top using a smart contract.

Through the use of Ether deposits, slashing conditions, and a modified fork choice, FFG allows the underlying PoW blockchain to be finalized.  As network security is greatly shifted from PoW to PoS, PoW block rewards are reduced.

This EIP does not contain safety and liveness proofs or validator implementation details, but these can be found in the [Casper FFG paper](https://arxiv.org/abs/1710.09437) and [Validator Implementation Guide](https://github.com/ethereum/casper/blob/master/VALIDATOR_GUIDE.md) respectively.

## Glossary

* **epoch**: The span of blocks between checkpoints. Epochs are numbered starting at the hybrid casper fork, incrementing by one at the start of each epoch.
* **finality**: The point at which a block has been decided upon by a client to _never_ revert. Proof of Work does not have the concept of finality, only of further deep block confirmations.
* **checkpoint**: The block/hash under consideration for finality for a given epoch. This block is the _last_ block of the previous epoch. Rather than dealing with every block, Casper FFG only considers checkpoints for finalization. When a checkpoint is explicitly finalized, all ancestor blocks of the checkpoint are implicitly finalized.
* **validator**: A participant in the Casper FFG consensus that has deposited ether in the casper contract and has the responsibility to vote and finalize checkpoints.
* **validator set**: The set of validators in the casper contract at any given time.
* **dynasty**: The number of finalized checkpoints in the chain from root to the parent of a block. The dynasty is used to define when a validator starts and ends validating. The current dynasty only increments when a checkpoint is finalized as opposed to epoch numbers that increment regardless of finality.
* **slash**: The burning of some amount of a validator&apos;s deposit along with an immediate logout from the validator set. Slashing occurs when a validator signs two conflicting `vote` messages that violate a slashing condition. For an in-depth discussion of slashing conditions, see the [Casper FFG Paper](https://arxiv.org/abs/1710.09437).

## Motivation

Transitioning the Ethereum network from PoW to PoS has been on the roadmap and in the [Yellow Paper](https://github.com/ethereum/yellowpaper) since the launch of the protocol. Although effective in coming to a decentralized consensus, PoW consumes an incredible amount of energy, has no economic finality, and has no effective strategy in resisting cartels. Excessive energy consumption, issues with equal access to mining hardware, mining pool centralization, and an emerging market of ASICs each provide a distinct motivation to make the transition as soon as possible.

Until recently, the proper way to make this transition was still an open area of research. In October of 2017 [Casper the Friendly Finality Gadget](https://arxiv.org/abs/1710.09437) was published, solving open questions of economic finality through validator deposits and crypto-economic incentives. For a detailed discussion and proofs of &quot;accountable safety&quot; and &quot;plausible liveness&quot;, see the [Casper FFG](https://arxiv.org/abs/1710.09437) paper.

The Casper FFG contract can be layered on top of any block proposal mechanism, providing finality to the underlying chain. This EIP proposes layering FFG on top of the existing PoW block proposal mechanism as a conservative step-wise approach in the transition to full PoS. The new FFG staking mechanism requires minimal changes to the protocol, allowing the Ethereum network to fully test and evaluate Casper FFG on top of PoW before moving to a validator based block proposal mechanism.

## Parameters

* `HYBRID_CASPER_FORK_BLKNUM`: TBD
* `CASPER_ADDR`: TBD
* `CASPER_CODE`: see below
* `CASPER_BALANCE`: 1.25e24 wei (1,250,000 ETH)
* `MSG_HASHER_ADDR`: TBD
* `MSG_HASHER_CODE`: see below
* `PURITY_CHECKER_ADDR`: TBD
* `PURITY_CHECKER_CODE`: see below
* `NULL_SENDER`: `2**160 - 1`
* `NEW_BLOCK_REWARD`: 6e17 wei (0.6 ETH)
* `REWARD_STEPDOWN_BLOCK_COUNT`: 5.5e5 blocks (~3 months)
* `CASPER_INIT_DATA`: TBD
* `VOTE_BYTES`: `0xe9dc0614`
* `INITIALIZE_EPOCH_BYTES`: `0x5dcffc17`
* `NON_REVERT_MIN_DEPOSIT`: amount in wei configurable by client

### Casper Contract Parameters

* `EPOCH_LENGTH`: 50 blocks
* `WARM_UP_PERIOD`: 1.8e5 blocks (~1 month)
* `WITHDRAWAL_DELAY`: 1.5e4 epochs
* `DYNASTY_LOGOUT_DELAY`: 700 dynasties
* `BASE_INTEREST_FACTOR`: 7e-3
* `BASE_PENALTY_FACTOR`: 2e-7
* `MIN_DEPOSIT_SIZE`: 1.5e21 wei (1500 ETH)


## Specification

#### Deploying Casper Contract

If `block.number == HYBRID_CASPER_FORK_BLKNUM`, then when processing the block before processing any transactions:

* set the code of `MSG_HASHER_ADDR` to `MSG_HASHER_CODE`
* set the code of `PURITY_CHECKER_ADDR` to `PURITY_CHECKER_CODE`
* set the code of `CASPER_ADDR` to `CASPER_CODE`
* set balance of `CASPER_ADDR` to `CASPER_BALANCE`

Then execute a `CALL` with the following parameters before executing any normal block transactions:

* `SENDER`: `NULL_SENDER`
* `GAS`: 3141592
* `TO`: `CASPER_ADDR`
* `VALUE`: 0
* `NONCE`: 0
* `GASPRICE`: 0
* `DATA`: `CASPER_INIT_DATA`

This `CALL` utilizes no gas and does not increment the nonce of `NULL_SENDER`

#### Initialize Epochs

If `block.number &gt;= (HYBRID_CASPER_FORK_BLKNUM + WARM_UP_PERIOD)` and `block.number % EPOCH_LENGTH == 0`, execute a `CALL` with the following parameters before executing any normal block transactions:

* `SENDER`: `NULL_SENDER`
* `GAS`: 3141592
* `TO`: `CASPER_ADDR`
* `VALUE`: 0
* `NONCE`: 0
* `GASPRICE`: 0
* `DATA`: `INITIALIZE_EPOCH_BYTES` followed by the 32-byte encoding of `floor(block.number / EPOCH_LENGTH)`

This `CALL` utilizes no gas and does not increment the nonce of `NULL_SENDER`

#### Casper Votes

A `vote` transaction is defined as a transaction with the following parameters:

* `TO`: `CASPER_ADDR`
* `DATA`: Begins with `VOTE_BYTES`

If `block.number &gt;= HYBRID_CASPER_FORK_BLKNUM`, then:

* A valid `vote` transaction to `CASPER_ADDR` must satisfy each of the following:
  * Must have the following signature `(CHAIN_ID, 0, 0)` (ie. `r = s = 0, v = CHAIN_ID`)
  * Must have `value == nonce == gasprice == 0`
* When producing and validating a block, when handling `vote` transactions to `CASPER_ADDR`:
  * Only include &quot;valid&quot; `vote` transactions as defined above
  * Place all `vote` transactions at the end of the block
  * Track cumulative gas used by votes separately from cumulative gas used by normal transactions via `vote_gas_used`
  * Total `vote_gas_used` of `vote` transactions cannot exceed the `block_gas_limit`, independent of gas used by normal block transactions
* When applying `vote` transactions to `CASPER_ADDR` to vm state:
  * Set sender to `NULL_SENDER`
  * Count gas of `vote` toward `vote_gas_used`
  * Do not count gas of `vote` toward the normal `gas_used`. For all `vote` transaction receipts, cumulative gas used is equal to last non-`vote` transaction receipt
  * Do not increment the nonce of `NULL_SENDER`
* All unsuccessful `vote` transactions to `CASPER_ADDR` are invalid and must not be included in the block


#### Fork Choice and Finalization

If `block.number &gt;= HYBRID_CASPER_FORK_BLKNUM`, the fork choice rule is the logic represented by the following pseudocode. Note that options `--casper-fork-choice` and `--exclude` are discussed below in &quot;Client Settings&quot;.

```python
def handle_block(new_block):
    if not is_new_head(new_block):
        return

    set_head(new_block)
    if --casper-fork-choice is on:
        check_and_finalize_new_checkpoint(new_block)


def is_new_head(new_block):
    if --casper-fork-choice is off
        # old pure PoW chain scoring rule
        return new_block.total_difficuty &gt; current_head.total_difficulty

    if new_block is in --exclude list or one of its descendants
        return false

    # don&apos;t revert finalized blocks
    if db.last_finalized_block is not in new_block.ancestors:
        return false

    # new casper chain scoring rule
    return highest_justified_epoch(new_block) * 10**40 + new_block.total_difficuty &gt;
        highest_justified_epoch(current_head) * 10**40 + current_head.total_difficulty


def highest_justified_epoch(block):
    casper = block.post_state.casper_contract
    return casper.highest_justified_epoch(NON_REVERT_MIN_DEPOSITS)


def check_and_finalize_new_checkpoint(new_block):
    casper = new_block.post_state.casper_contract

    # If no finalized blocks, db.last_finalized_epoch initialized to -1

    finalized_epoch = casper.highest_finalized_epoch(NON_REVERT_MIN_DEPOSITS)
    if finalized_epoch &gt; db.last_finalized_epoch:
        finalized_hash = casper.checkpoint_hashes(finalized_epoch)

        # ensure not trivially finalized
        if finalized_hash == b&apos;\x00&apos; * 32:
            return

        db.last_finalized_epoch = finalized_epoch
        db.last_finalized_block = finalized_hash
```

The new chain scoring rule queries the casper contract to find the highest justified epoch that meets the client&apos;s minimum deposit requirement (`NON_REVERT_MIN_DEPOSITS`). The `10**40` multiplier ensures that the justified epoch takes precedence over block mining difficulty. `total_difficulty` only serves as a tie breaker if the two blocks in question have an equivalent `highest_justified_epoch`.

_Note_: If the client has no justified checkpoints, the contract returns `highest_justified_epoch` as `0` essentially reverting the fork choice rule to pure PoW.

When assessing a new block as the chain&apos;s head, clients must _never revert finalized blocks_ as seen by the code commented as &quot;don&apos;t revert finalized blocks&quot;.

When a new block is added as the chain&apos;s head, clients then check for a new finalized block. This is handled by the `check_and_finalized_new_checkpoint(new_block)` method above. If the highest finalized epoch in the casper contract is greater than the previous finalized epoch, then the client finalizes the block with the hash `casper.checkpoint_hashes(finalized_epoch)`, storing this block and the related epoch number in the client database as finalized.

Clients only consider checkpoints justified or finalized if deposits were greater than `NON_REVERT_MIN_DEPOSIT` _during the epoch in question_. This logic is encapsulated in `casper.highest_justified_epoch(NON_REVERT_MIN_DEPOSIT)` and `casper.highest_finalized_epoch(NON_REVERT_MIN_DEPOSIT)`, respectively.


#### Block Reward

If `block.number &gt;= HYBRID_CASPER_FORK_BLKNUM`, then `block_reward` is defined by the following logic and utilizes the same formulas for ommer rewards but with the updated `block_reward`.

```python
if block.number &lt; HYBRID_CASPER_FORK_BLKNUM + REWARD_STEPDOWN_BLOCK_COUNT:
    block_reward = 5 * NEW_BLOCK_REWARD
elif block.number &lt; HYBRID_CASPER_FORK_BLKNUM + 2*REWARD_STEPDOWN_BLOCK_COUNT:
    block_reward = 4 * NEW_BLOCK_REWARD
elif block.number &lt; HYBRID_CASPER_FORK_BLKNUM + 3*REWARD_STEPDOWN_BLOCK_COUNT:
    block_reward = 3 * NEW_BLOCK_REWARD
elif block.number &lt; HYBRID_CASPER_FORK_BLKNUM + 4*REWARD_STEPDOWN_BLOCK_COUNT:
    block_reward = 2 * NEW_BLOCK_REWARD
else:
    block_reward = NEW_BLOCK_REWARD
```


#### Validators

The mechanics and responsibilities of validators are not specified in this EIP because they rely upon network transactions to the contract at `CASPER_ADDR` rather than on protocol level implementation and changes.
See the [Validator Implementation Guide](https://github.com/ethereum/casper/blob/master/VALIDATOR_GUIDE.md) for validator details.

#### MSG_HASHER_CODE

The source code for `MSG_HASHER_CODE` is located [here](https://github.com/ethereum/casper/blob/master/casper/contracts/msg_hash.se.py).
The source is to be migrated to Vyper LLL before the bytecode is finalized for this EIP.

The EVM init code is:
```
TBD
```

The EVM bytecode that the contract should be set to is:
```
TBD
```

#### PURITY_CHECKER_CODE

The source code for `PURITY_CHECKER_CODE` is located [here](https://github.com/ethereum/research/blob/master/impurity/check_for_impurity.se).
The source is to be migrated to Vyper LLL before the bytecode is finalized for this EIP.

The EVM init code is:
```
TBD
```

The EVM bytecode that the contract should be set to is:
```
TBD
```

#### CASPER_CODE

The source code for `CASPER_CODE` is located at
[here](https://github.com/ethereum/casper/blob/master/casper/contracts/simple_casper.v.py).
The contract is to be formally verified and further tested before the bytecode is finalized for this EIP.

The EVM init code with the above specified params is:
```
TBD
```

The EVM bytecode that the contract should be set to is:
```
TBD
```

#### Client Settings
Clients should be implemented with the following configurable settings:

##### Enable Casper Fork Choice
The ability to enable/disable the Casper Fork Choice. A suggested implementation is `--casper-fork-choice`.

This setting should ship as default disabled in client versions during the initial casper fork. This setting should ship as default enabled in subsequent client versions.

##### NON_REVERT_MIN_DEPOSIT
The minimum size of total deposits that the client must observe in the FFG contract for the state of the contract to affect the client&apos;s fork choice. A suggested implementation is `--non-revert-min-deposit WEI_VALUE`.

The suggested default value that clients should ship with is at least 2e23 wei (200K ETH).

See &quot;Fork Choice&quot; more details.

##### Exclusion
The ability to exclude a specified blockhash and all of its descendants from a client&apos;s fork choice. A suggested implementation is `--exclude BLOCKHASHES`, where `BLOCK_HASHES` is a comma delimited list of blockhashes to exclude.

Note: this _can_ by design override a client&apos;s forkchoice and revert finalized blocks.

##### Join Fork
The ability to manually join a fork specified by a blockhash. A suggested implementation is `--join-fork BLOCKHASH` where the client automatically sets the head to the block defined by`BLOCKHASH` and locally finalizes it.

Note: this _can_ by design override a client&apos;s forkchoice and revert finalized blocks.

##### Monitor Votes
The ability to monitor incoming `vote` transactions for slashing conditions and submit proof to the casper contract for a finder&apos;s fee if found. A suggested implementation is `--monitor-votes`.

The setting should default to disabled.

The following pseudocode defines when two `vote` messages violate a slashing condition. A `vote` message is the singular argument included in a `vote` transaction.
```python
def decode_rlp_list(vote_msg):
    # [validator_index, target_hash, target_epoch, source_epoch, signature]
    return RLPList(vote_msg, [int, bytes, int, int, bytes])

def same_target_epoch(vote_msg_1, vote_msg_2):
    decoded_values_1 = decode_rlp_msg(vote_msg_1)
    target_epoch_1 = decoded_values_1[2]

    decoded_values_2 = decode_rlp_msg(vote_msg_2)
    target_epoch_2 = decoded_values_2[2]

    return target_epoch_1 == target_epoch_2

def surrounds(vote_msg_1, vote_msg_2):
    decoded_values_1 = decode_rlp_msg(vote_msg_1)
    target_epoch_1 = decoded_values_1[2]
    source_epoch_1 = decoded_values_1[3]

    decoded_values_2 = decode_rlp_msg(vote_msg_2)
    target_epoch_2 = decoded_values_2[2]
    source_epoch_1 = decoded_values_1[3]

    vote_1_surrounds_vote_2 = target_epoch_1 &gt; target_epoch_2 and source_epoch_1 &lt; source_epoch_2
    vote_2_surrounds_vote_1 = target_epoch_2 &gt; target_epoch_1 and source_epoch_2 &lt; source_epoch_1

    return vote_1_surrounds_vote_2 or vote_2_surrounds_vote_1

def violates_slashing_condition(vote_msg_1, vote_msg_2):
    return same_target_epoch(vote_msg_1, vote_msg_2) or surrounds(vote_msg_1, vote_msg_2)
```

The casper contract also provides a helper method `slashable(vote_msg_1, vote_msg_2)` to check if two votes violate a slashing condition. Clients should use the above pseudocode in combination with `casper.slashable()` as a final check when deciding whether to submit a `slash` to the contract.

The `--monitor-votes` setting is to be used for clients that wish to monitor vote transactions for slashing conditions. If a slashing condition is found, the client creates and sends a transaction to `slash` on the casper contract. The first transaction to include the slashing condition proof slashes the validator in question and sends a 4% finder&apos;s fee to the transaction sender.

## Rationale

Naive PoS specifications and implementations have existed since early blockchain days, but most are vulnerable to serious attacks and do not hold up under crypto-economic analysis. Casper FFG solves problems such as &quot;Nothing at Stake&quot; and &quot;Long Range Attacks&quot; through requiring validators to post slashable deposits and through defining economic finality.

#### Minimize Consensus Changes
The finality gadget is designed to minimize changes across clients. For this reason, FFG is implemented within the EVM, so that the contract byte code encapsulates most of the complexity of the fork.

Most other decisions were made to minimize changes across clients. For example, it would be possible to allow `CASPER_ADDR` to mint Ether each time it paid rewards (as compared to creating the contract with `CASPER_BALANCE`), but this would be more invasive and error-prone than relying on existing EVM mechanics.

#### Deploying Casper Contract
The `MSG_HASHER_CODE` and `PURITY_CHECKER_CODE` both do not require any initialization so the EVM bytecode can simply be placed at `MSG_HASHER_ADDR` and `PURITY_CHECKER_ADDR`. On the other hand, the casper contract _does_ require passing in parameters and initialization of state. This initialization would normally occur by the EVM init code interacting with the CREATE opcode. Due to the nature of this contract being deployed outside of normal block transactions and to a particular address, the EVM init code/CREATE method requires client specific &quot;hacks&quot; to make it work. For simplicity of specifying across clients, the EVM bytecode -- `CASPER_CODE` -- is placed at `CASPER_ADDR` followed by an explicit `CALL` to a one-time `init` method on the casper contract. `init` handles all of the logic that a constructor normally would, accepting contract parameters as arguments and setting initial variable values, and can only be run _once_.

`CASPER_INIT_DATA` is composed of the byte signature of the `init` method of the casper contract concatenated with the 32-byte encodings of the following variables in the following order:

  * `EPOCH_LENGTH`
  * `WITHDRAWAL_DELAY`
  * `DYNASTY_LOGOUT_DELAY`
  * `MSG_HASHER_ADDR`
  * `PURITY_CHECKER_ADDR`
  * `BASE_INTEREST_FACTOR`
  * `BASE_PENALTY_FACTOR`
  * `MIN_DEPOSIT_SIZE`

The entirety of this data is provided as a bytestring -- `CASPER_INIT_DATA` -- to reduce the chance of encoding errors across clients, especially regarding fixed decimal types which are new in vyper and not yet supported by all clients.

#### Casper Contract Params

`EPOCH_LENGTH` is set to 50 blocks as a balance between time to finality and message overhead.

`WARM_UP_PERIOD` is set to 1.8e5 blocks to provide validators with an approximate 1 month period to make initial deposits before full contract functionality and voting begin. This helps prevent degenerate cases such as having very few or even just one validator in the initial dynasty. This 1 month period also gives the network time to observe on the order of how many validators will initially be participating in consensus. If for some reason there is an unexpectedly low turnout, the community might choose to delay validation and consider design alternatives.

`WITHDRAWAL_DELAY` is set to 15000 epochs to freeze a validator&apos;s funds for approximately 4 months after logout. This allows for at least a 4 month window to identify and slash a validator for attempting to finalize two conflicting checkpoints. This also defines the window of time with which a client must log on to sync the network due to weak subjectivity.

`DYNASTY_LOGOUT_DELAY` is set to 700 dynasties to prevent immediate logout in the event of an attack from being a viable strategy.

`BASE_INTEREST_FACTOR` is set to 7e-3 such that if there are ~10M ETH in total deposits, then validators earn approximately 5% per year in ETH rewards under optimal FFG conditions.

`BASE_PENALTY_FACTOR` is set to 2e-7 such that if 50% of deposits go offline, then offline validators lose half of their deposits in approximately 3 weeks, at which the online portion of validators becomes a 2/3 majority and can begin finalizing checkpoints again.

`MIN_DEPOSIT_SIZE` is set to 1500 ETH to form a natural upper bound on the total number of validators, bounding the overhead due to `vote` messages. Using formulas found [here](https://medium.com/@VitalikButerin/parametrizing-casper-the-decentralization-finality-time-overhead-tradeoff-3f2011672735) under &quot;From validator count to minimum staking ETH&quot;, we estimate that with 1500 ETH minimum deposit at an assumed ~10M in total deposits there will be approximately 900 validators at any given time. `vote`s are only sent after the first quarter of an epoch so 900 votes have to fit into 37 blocks or ~24 `vote`s per block. We have experimented with more dynamic models for `MIN_DEPOSIT_SIZE`, but these tend to introduce significant complexities and without data from a live network seem to be premature optimizations.

#### Initialize Epochs
The call to the method at `INITIALIZE_EPOCH_BYTES` at `CASPER_ADDR` at the start of each epoch is a call to the `initialize_epoch` method in the casper contract. This method can only be called once per epoch and is guaranteed by the protocol to be called at the start block of each epoch by `NULL_SENDER`. This method performs a number of bookkeeping tasks around incrementing variables, updating rewards, etc.

Any call to this method fails prior to the end of the `WARM_UP_PERIOD`. Thus the protocol does not begin executing `initialize_epoch` calls until `block.number &gt;= HYBRID_CASPER_FORK_BLKNUM + WARM_UP_PERIOD`.

#### Issuance
A fixed amount of 1.25M ETH was chosen as `CASPER_BALANCE` to fund the casper contract. This gives the contract enough runway to operate for approximately 2 years (assuming ~10M ETH in validator deposits). Acting similarly to the &quot;difficulty bomb&quot;, this &quot;funding crunch&quot; forces the network to hardfork in the relative near future to further fund the contract. This future hardfork is an opportunity to upgrade the contract and transition to full PoS.

The PoW block reward is reduced from 3.0 to 0.6 ETH/block over the course of approximately one year because the security of the chain is greatly shifted from PoW difficulty to PoS finality and because rewards are now issued to both validators and miners. Rewards are stepped down by 0.6 ETH/block every 3 months (`REWARD_STEPDOWN_BLOCK_COUNT`) to provide for a conservative transition period from full PoW to hybrid PoS/PoW. This gives validators time to become familiar with the new technology and begin logging on and also provides the network with more leeway in case of any unforeseen issues. If any major issues do arise, the Ethereum network will still have substantial PoW security to rely upon while decisions are made and/or patches are deployed. See [here](https://gist.github.com/djrtwo/bc864c0d0a275170183803814b207b9a) for further analysis of the current PoW security and of the effect of PoW block reward reduction in the context of Hybrid Casper FFG.

In addition to block rewards, miners now receive an issuance reward for including successful `vote` transactions into the block on time. This reward is equal to 1/8th that of the reward the validator receives for a successful `vote` transaction. Under optimal FFG conditions after group validator reward adjustments are made, miners receive approximately 1/5th of the total ETH issued by the Casper contract.

Below is a table of deposit sizes with associated annual interest rate and approximate time until funding crunch:

| Deposit Size | Annual Validator Interest | Funding Crunch |
| -------- | -------- | -------- |
| 2.5M ETH | 10.12%   | ~4 years   |
| 10M ETH  | 5.00%    | ~2 years   |
| 20M ETH  | 3.52%    | ~1.4 years |
| 40M ETH  | 2.48%    | ~1 year    |

#### Gas Changes
Normal block transactions cannot affect casper `vote` validation results, but casper `vote` validation results can affect normal block transaction execution. Due to this asymmetrical relationship, `vote` transactions can be processed in parallel with normal block transactions if `vote` transactions are placed after all normal block transactions. Because `vote` transactions can be processed in parallel to normal block transactions, `vote` transactions cost 0 gas for validators, ensuring that validators can submit votes even in highly congested or high gas-price periods.

`vote_gas_used` is introduced to ensure that `vote` transactions do not put an undue burden on block processing. The additional overhead from `vote` transactions is capped at the same limit as normal block transactions so that, when run in parallel, neither sets of transactions exceed the overhead defined by the `block_gas_limit`.

The call to `initialize_epoch` at the beginning of each epoch requires 0 gas so that this protocol state transition does not take any gas allowance away from normal transactions.

#### NULL_SENDER and Account Abstraction
This EIP implements a limited version of account abstraction for validators&apos; `vote` transactions. The general design was borrowed from [EIP-86](/EIPs/EIPS/eip-86). Rather than relying upon native transaction signatures, each validator specifies a signature contract when sending their `deposit` to `CASPER_ADDR`. When casting a `vote`, the validator bundles and signs the parameters of their `vote` according to the requirements of their signature contract. The `vote` method of the casper contract checks the signature of the parameters against the validator&apos;s signature contract, exiting the transaction as unsuccessful if the signature is not successfully verified.

This allows validators to customize their own signing scheme for votes. Use cases include:
* quantum-secure signature schemes
* multisig wallets
* threshold schemes

For more details on validator account abstraction, see the [Validator Implementation Guide](https://github.com/ethereum/casper/blob/master/VALIDATOR_GUIDE.md).

#### Client Settings
##### Enable Casper Fork Choice
Releasing client versions with the casper fork choice as initially default disabled allows for a more conservative transition to hybrid Casper FFG. Under normal operating conditions there are no disparities between the PoW fork choice and the hybrid Casper FFG fork choice. The two fork choice rules can only diverge if either 51% of miners or 51% of validators are faulty.

Validators will begin to log on, vote, and finalize the FFG contract before the majority of the network begins explicitly relying upon the new finality mechanism. Once a significant number of validators have logged on and the finality mechanism has been tested on the live network, new client software versions that change the default to enabled will be released.

##### NON_REVERT_MIN_DEPOSIT
`NON_REVERT_MIN_DEPOSIT` is defined and configurable locally by each client. Clients are in charge of deciding upon the minimum deposits (security) at which they will accept the chain as finalized. In the general case, differing values in the choice of this local constant will not create any fork inconsistencies because clients with very strict finalization requirements will revert to follow the longest PoW chain.

Arguments have been made to hardcode a value into clients or the contract, but we cannot reasonably define security required for all clients especially in the context of massive fluctuations in the value of ETH.

##### Exclusion
This setting is useful in coordinating minority forks in cases of majority collusion.

##### Join Fork
This setting is to be used by new clients that are syncing the network for the first time. Due to weak subjectivity, a blockhash should be supplied to successfully sync the network when initially starting a node.

This setting is also useful for coordinating minority forks in cases of majority collusion.

##### Monitor Votes
Monitoring the network for slashing conditions is key to Casper FFG&apos;s &quot;accountable safety&quot; as submitting proof of nefarious activity burns a validator&apos;s deposit.

This setting is suggested default disabled because the block producer will almost certainly frontrun anyone else submitting a `slash` transaction. To prevent every client on the network from submitting a `slash` transaction in the event of a slashing condition, this setting should only be enabled by block producers and those clients who explicitly choose to monitor votes.

## Backwards Compatibility
This EIP is not forward compatible and introduces backwards incompatibilities in the state, fork choice rule, block reward, transaction validity, and gas calculations on certain transactions. Therefore, all changes should be included in a scheduled hardfork at `HYBRID_CASPER_FORK_BLKNUM`.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 20 Apr 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1011</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1011</guid>
      </item>
    
      <item>
        <title>Hardfork Meta: Constantinople</title>
        <category>Meta/</category>
        
        <description>## Abstract

This meta-EIP specifies the changes included in the Ethereum hardfork named Constantinople.

## Specification

- Codename: Constantinople
- Aliases: Metropolis/Constantinople, Metropolis part 2
- Activation:
  - `Block &gt;= 7_280_000` on the Ethereum Mainnet
  - `Block &gt;= 4,230,000` on the Ropsten testnet
  - `Block &gt;= 9_200_000` on the Kovan testnet
  - `Block &gt;= 3_660_663` on the Rinkeby testnet
- Included EIPs:
  - [EIP-145](/EIPs/EIPS/eip-145): Bitwise shifting instructions in EVM
  - [EIP-1014](/EIPs/EIPS/eip-1014): Skinny CREATE2
  - [EIP-1052](/EIPs/EIPS/eip-1052): EXTCODEHASH Opcode
  - [EIP-1234](/EIPs/EIPS/eip-1234): Delay difficulty bomb, adjust block reward
  - [EIP-1283](/EIPs/EIPS/eip-1283): Net gas metering for SSTORE without dirty maps

## References

1. The list above includes the EIPs discussed as candidates for Constantinople at the All Core Dev [Constantinople Session #1](https://github.com/ethereum/pm/issues/55). See also [Constantinople Progress Tracker](https://github.com/ethereum/pm/wiki/Constantinople-Progress-Tracker).
2. https://blog.ethereum.org/2019/02/22/ethereum-constantinople-st-petersburg-upgrade-announcement/

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 20 Apr 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1013</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1013</guid>
      </item>
    
      <item>
        <title>Skinny CREATE2</title>
        <category>Standards Track/Core</category>
        
        <description>### Specification

Adds a new opcode (`CREATE2`) at `0xf5`, which takes 4 stack arguments: endowment, memory_start, memory_length, salt. Behaves identically to `CREATE` (`0xf0`), except using `keccak256( 0xff ++ address ++ salt ++ keccak256(init_code))[12:]` instead of the usual sender-and-nonce-hash as the address where the contract is initialized at.

The `CREATE2` has the same `gas` schema as `CREATE`, but also an extra `hashcost` of `GSHA3WORD * ceil(len(init_code) / 32)`, to account for the hashing that must be performed. The `hashcost` is deducted at the same time as memory-expansion gas and `CreateGas` is deducted: _before_ evaluation of the resulting address and the execution of `init_code`.

- `0xff` is a single byte, 
- `address` is always `20` bytes, 
- `salt` is always `32` bytes (a stack item). 

The preimage for the final hashing round is thus always exactly `85` bytes long.

The coredev-call at 2018-08-10 decided to use the formula above. 


### Motivation

Allows interactions to (actually or counterfactually in channels) be made with addresses that do not exist yet on-chain but can be relied on to only possibly eventually contain code that has been created by a particular piece of init code. Important for state-channel use cases that involve counterfactual interactions with contracts.

### Rationale

#### Address formula

* Ensures that addresses created with this scheme cannot collide with addresses created using the traditional `keccak256(rlp([sender, nonce]))` formula, as `0xff` can only be a starting byte for RLP for data many petabytes long.
* Ensures that the hash preimage has a fixed size,

#### Gas cost

Since address calculation depends on hashing the `init_code`, it would leave clients open to DoS attacks if executions could repeatedly cause hashing of large pieces of `init_code`, since expansion of memory is paid for only once. This EIP uses the same cost-per-word as the `SHA3` opcode. 

### Clarifications

The `init_code` is the code that, when executed, produces the runtime bytecode that will be placed into the state, and which typically is used by high level languages to implement a &apos;constructor&apos;.

This EIP makes collisions possible. The behaviour at collisions is specified by [EIP-684](https://github.com/ethereum/EIPs/issues/684):

&gt; If a contract creation is attempted, due to either a creation transaction or the `CREATE` (or future `CREATE2`) opcode, and the destination address already has either nonzero nonce, or nonempty code, then the creation throws immediately, with exactly the same behavior as would arise if the first byte in the init code were an invalid opcode. This applies retroactively starting from genesis.

Specifically, if `nonce` or `code` is nonzero, then the create-operation fails. 

With [EIP-161](/EIPs/EIPS/eip-161) 

&gt; Account creation transactions and the `CREATE` operation SHALL, prior to the execution of the initialisation code, increment the nonce over and above its normal starting value by one

This means that if a contract is created in a transaction, the `nonce` is immediately non-zero, with the side-effect that a collision within the same transaction will always fail -- even if it&apos;s carried out from the `init_code` itself.

It should also be noted that `SELFDESTRUCT` (`0xff`) has no immediate effect on `nonce` or `code`, thus a contract cannot be destroyed and recreated within one transaction.

### Examples

Example 0
* address `0x0000000000000000000000000000000000000000`
* salt `0x0000000000000000000000000000000000000000000000000000000000000000`
* init_code `0x00`
* gas (assuming no mem expansion): `32006`
* result: `0x4D1A2e2bB4F88F0250f26Ffff098B0b30B26BF38`

Example 1
* address `0xdeadbeef00000000000000000000000000000000`
* salt `0x0000000000000000000000000000000000000000000000000000000000000000`
* init_code `0x00`
* gas (assuming no mem expansion): `32006`
* result: `0xB928f69Bb1D91Cd65274e3c79d8986362984fDA3`

Example 2
* address `0xdeadbeef00000000000000000000000000000000`
* salt `0x000000000000000000000000feed000000000000000000000000000000000000`
* init_code `0x00`
* gas (assuming no mem expansion): `32006`
* result: `0xD04116cDd17beBE565EB2422F2497E06cC1C9833`

Example 3
* address `0x0000000000000000000000000000000000000000`
* salt `0x0000000000000000000000000000000000000000000000000000000000000000`
* init_code `0xdeadbeef`
* gas (assuming no mem expansion): `32006`
* result: `0x70f2b2914A2a4b783FaEFb75f459A580616Fcb5e`

Example 4
* address `0x00000000000000000000000000000000deadbeef`
* salt `0x00000000000000000000000000000000000000000000000000000000cafebabe`
* init_code `0xdeadbeef`
* gas (assuming no mem expansion): `32006`
* result: `0x60f3f640a8508fC6a86d45DF051962668E1e8AC7`

Example 5
* address `0x00000000000000000000000000000000deadbeef`
* salt `0x00000000000000000000000000000000000000000000000000000000cafebabe`
* init_code `0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef`
* gas (assuming no mem expansion): `32012`
* result: `0x1d8bfDC5D46DC4f61D6b6115972536eBE6A8854C`

Example 6
* address `0x0000000000000000000000000000000000000000`
* salt `0x0000000000000000000000000000000000000000000000000000000000000000`
* init_code `0x`
* gas (assuming no mem expansion): `32000`
* result: `0xE33C0C7F7df4809055C3ebA6c09CFe4BaF1BD9e0`

</description>
        <pubDate>Fri, 20 Apr 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1014</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1014</guid>
      </item>
    
      <item>
        <title>Configurable On Chain Issuance</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-dynamic-block-rewards-with-governance-contract/204</comments>
        
        <description>## Simple Summary

This EIP changes the block reward step by instead of setting it to be hard coded on the clients and to be given to the miner/validator etherbase, it should instead go to an address decided by an on-chain contract, with hard limits on how it would be issued (six month lock-in; issuance can only decrease or be maintained, but not increase;). A decision method is suggested but not essential to the notion of this EIP. This would **not be a generic governance solution**, which is a much broader and harder topic, would **not** affect technical upgrade decisions or other hard forks, but seen as *a forum to attempt to prevent contentious hard forks* that can be solved with the issuance.

## Summary
### Thesis: many controversial issues boil down to resources
These are current EIPs that are being developed or debated. They might seem unrelated but they have something in common, that they can be resolved by proper channel of funds.

#### Casper and PoS

Moving to PoS has been on the roadmap since day 0 for ethereum, along with a reduction in issuance to a cost equivalent to the Validator&apos;s cost of security (considered to be more efficient than PoW). But the exact issuance necessary for PoS has yet to be determined and is currently being researched. Casper validation will be an on chain contract and therefore it will need to be funded. It&apos;s unlikely that a definitive final answer on how much issuance is needed for validation will be reached in the next years as new research will uncover new arguments, so it would make sense to allow some flexibility on this matter

#### Issuance Cap at 120 Million

[EIP-960](https://github.com/ethereum/EIPs/issues/960), Vitalik&apos;s not so jokey april&apos;s fool has been taken seriously. It proposes the issuance to be slowly reduced until it reaches 120 million ether. One of the main counterpoints by Vlad can be simplified by [we don&apos;t know enough to know what that ether can be used for](https://medium.com/@Vlad_Zamfir/against-vitaliks-fixed-supply-eip-eip-960-18e182a7e5bd) and Vitalik&apos;s counterpoint is that [reducing emissions can be a way to reduce future abuse of these funds by finding a schelling point at 0](https://medium.com/@VitalikButerin/to-be-clear-im-not-necessarily-wedded-to-a-finite-supply-cap-a7aa48ab880c). Issuance has already been reduced once, from 5 ether to the current 3 ether per block. The main point of a hard cap is that a lot of people consider *not issuing* as having a positive contribution, that can outweigh other actions. Burning ether is also a valid issuance decision.

#### Asics and advantages of PoW

[EIP-960](https://eips.ethereum.org/EIPS/eip-969) proposes a change in algorithm to avoid mining being dominated by ASICS. Counter arguments by Phil Daian argue among others than [resisting economies of scale is futile and there might be specific security advantages to specialized hardware](https://pdaian.com/blog/anti-asic-forks-considered-harmful/). One of the main arguments for PoW mining, even when it doesn&apos;t provide security, it is useful as a fair distribution mechanism, that **PoW allows any person with a computer, internet access and electricity to obtain currency without having to deal with government imposed currency controls**.

#### Recovery Forks

After the Parity Multisig library self destruction, three different strategies have been attempted to recover the funds: [a general protocol improvement to allow reviving self destructed contracts](https://gist.github.com/5chdn/a9bb8617cc8523a030126a3d1c60baf3) (which was considered dangerous), a [general process to recover funds](https://github.com/ethereum/EIPs/pull/867) and a [specific recovery of the multisig library](/EIPs/EIPS/eip-999). The latter two are finding a lot of resistance from the community, but it&apos;s unlikely that these issues are going away soon. The affected parties have a large incentive (fluctuating at almost half a billion dollars) to keep trying, and it&apos;s an issue that is likely to occur again in the future. If they get reimbursed, [there are many other special cases of ether provably burnt or stuck](https://github.com/ethereum/EIPs/issues/156) that might deserve the same treatment. If they get shut down, they have an incentive to move forward a fork implementation: even if they are a minority chain, it&apos;s likely they&apos;ll recover an amount larger than 0, which is what they would otherwise, and it means the main ethereum community might lose a valuable team of developers. 


#### Other Public Goods

There are many other types of public goods that could be funded by issuance. By *Public Good*, I&apos;m using a strict definition of something that brings value to everyone, both those who funded it and free-loaders, making it hard to fund it exclusively by traditional private incentives. They can be research, whole network security, [incentivize full clients and networking](/EIPs/EIPS/eip-908), fair distribution of tokens etc.

## Proposed Solution
### Issuance Contract

This EIP proposes a future hard fork where block reward is not issued to miners/validators etherbase, but instead to a single contract, that then will activate the default function (with a fixed amount of gas) and then it will forward the ether to other contracts which will finally distribute to their final destinations. 

#### Limits on the contract

##### It can only deal with issuance

It&apos;s not meant to be a general governance contract. The contract **should NOT be used** to decide software updates, to freeze funds, change contract balances or anything on the consensus layer other than the strict definition of *where block rewards go*. It should be seen as a platform to settle disputes to avoid the implementation of contentious hard forks, not as a mean to remove the power of users and developers to execute them.

##### It cannot only decrease issuance, and once decreased it cannot be increased again

In order to reduce future abuse and uncertainty, **once issuance is reduced, it cannot be increased**. To prevent a single action reducing it to 0, the reduction is limited up to a percentage per time, so if the **decision assembly** is aggressively to reduce issuance to zero, it would take a known number of years.

##### Results are locked for s

Whenever a new decision on either reducing the issuance or changing the target is made, the effects will have a six-month delay to it. Once a decision is made it is final, it will take place six months after that, but if it&apos;s shortly reversed, then that change will be short lived. The rationale behind is that it allows time to anyone disagreeing with the decision to:

* Sell their coins so that if a bad actor takes over they will have a reduced reward
* Attempt to revert the decision as soon as possible, to reduce the duration that the change will take place
* Organize to create counter measures against the decision 
* Implement a hard fork changing the decision contract or to remove the issuance contract altogether, as a last resort measure 

##### Interface

It would have the following interface:

`function targetContract() returns (address)`

There&apos;s a single target contract that should ether issued to. At each new block, that contract would have the default function called so it would forward to the intended addresses. 

`function decisionAssembly() returns (address)`

A contract that would represent the internal governance of decisions. More on this later.

`function reduceIssuance(uint)`

Can only be called by **decision assembly**. The contract is allowed to reduce or maintain the issuance per block. **Change is not executed immediately, effects only happen six months later, but once a decision is committed it is irrevocable**.

`function changeTargetContract(address)`

Can only be called by **decision assembly**. It changes the contract that will receive the funds in the future. Only one contract can be appointed, but if the community desires to split issuance or even burn a part of it (in a non-irrevocable manner) it can be done in that contract. Change is not executed immediately, **effects only happen six months later**, but once a decision is committed it is certain, even if it&apos;s later reverted: if a new target contract is changed after a few hours, then it still means that in six month&apos;s time, it would issue for that contract for a few hours.

`function executeDecision(uint)`

Can be called by anyone: it executes a change to issuance amount or target that had been scheduled six months prior.

##### Decision Assembly 

A contract that has the power to decide the changes to issuance, the core of the governance of these decisions. The exact format of this governance is open to debate, but what follows is a suggestion:

The decision would be made by multiple signalling contracts, each one implemented by separate groups and representing one aspect of the community or one sort of measurement. Each signaling process would have a `int` bound in which they could vote and they would have their own internal process to decide that. As new governance methods are tested and debated, new signalling contracts should be added and removed. Suggested signalling contracts:

* Futarchy and prediction markets based on multiple measures
* Votes weighted by ether balance (optionally with multipliers if the voters were committed to locking votes)
* Token votes, weighted by their own relative ether exchange rate
* Votes by individual humans if a good sybil resistance, coercion mechanism is developed 
* Block-signalling, as a way to measure validators/miners choices
* Some sort of signalling representing developers, exchanges or other stakeholders
* Any other proposed manner

Since adding and removing signalling contracts, as well as changing their total weight would be controlled by the contract itself, it would be crucial that the first signalling contracts were a diverse set of interests, and that they were open to adding more signals as new governance is experimented as well as removing signals that stop representing the community.

### Questions to be debated

A lot of things are suggested in this EIP, so I would like to propose these questions to be debated:

1. Do we want to have dynamically changing block rewards, instead of having them be hard coded in the protocol?
2. If the answer above is yes, then what would be the best governance process to decide it, and what sorts of limits would we want that governance contract to have?
3. If the answer is a multi-signalling contract, then what sorts of signals would we want, what sort of relative weight should they have and what would be the process to add and remove them?





## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 20 Apr 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1015</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1015</guid>
      </item>
    
      <item>
        <title>tokenURI Interoperability</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-1046-erc-20-metadata-extension/13036</comments>
        
        <description>## Abstract

[ERC-721](/EIPs/EIPS/eip-721) introduced a `tokenURI` function for non-fungible tokens to handle miscellaneous metadata such as:

- thumbnail image
- title
- description
- special asset properties
- etc.

This ERC adds a `tokenURI` function to [ERC-20](/EIPs/EIPS/eip-20), and extends [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155) to enable interoperability between all three types of token URI.

## Motivation

See the note about the metadata extension in [ERC-721](/EIPs/EIPS/eip-721#rationale). The same arguments apply to ERC-20.

Being able to use similar mechanisms to extract metadata for ERC-20, ERC-721, ERC-1155, and future standards is useful for determining:

- What type of token a contract is (if any);
- How to display a token to a user, either in an asset listing page or on a dedicated token page; and
- Determining the capabilities of the token

## Specification

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

### Interoperability Metadata

The following TypeScript interface is used in later sections:

```typescript
/**
 * Interoperability metadata.
 * This can be extended by other proposals.
 * 
 * All fields MUST be optional.
 * **Not every field has to be a boolean.** Any optional JSON-serializable object can be used by extensions.
 */
interface InteroperabilityMetadata {
    /**
     * This MUST be true if this is ERC-1046 Token Metadata, otherwise, this MUST be omitted.
     * Setting this to true indicates to wallets that the address should be treated as an ERC-20 token.
     **/
    erc1046?: boolean | undefined;

    /**
     * This MUST be true if this is ERC-721 Token Metadata, otherwise, this MUST be omitted.
     * Setting this to true indicates to wallets that the address should be treated as an ERC-721 token.
     **/
    erc721?: boolean | undefined;

    /**
     * This MUST be true if this is ERC-1155 Token Metadata, otherwise, this MUST be omitted.
     * Setting this to true indicates to wallets that the address should be treated as an ERC-1155 token.
     **/
    erc1155?: boolean | undefined;
}
```

### ERC-20 Extension

#### ERC-20 Interface Extension

Compliant contracts MUST implement the following Solidity interface:

```solidity
pragma solidity ^0.8.0;

/// @title  ERC-20 Metadata Extension
interface ERC20TokenMetadata /* is ERC20 */ {
    /// @notice     Gets an ERC-721-like token URI
    /// @dev        The resolved data MUST be in JSON format and support ERC-1046&apos;s ERC-20 Token Metadata Schema
    function tokenURI() external view returns (string);
}
```

#### ERC-20 Token Metadata Schema

The resolved JSON of the `tokenURI` described in the ERC-20 Interface Extension section MUST conform to the following TypeScript interface:

```typescript
/**
 * Asset Metadata
 */
interface ERC20TokenMetadata {
    /**
     * Interoperability, to differentiate between different types of tokens and their corresponding URIs.
     **/
    interop: InteroperabilityMetadata;
    
    /**
     * The name of the ERC-20 token. 
     * If the `name()` function is present in the ERC-20 token and returns a nonempty string, these MUST be the same value.
     */
    name?: string;
    
    /**
     * The symbol of the ERC-20 token. 
     * If the `symbol()` function is present in the ERC-20 token and returns a nonempty string, these MUST be the same value.
     */
    symbol?: string;
    
    /**
     * The decimals of the ERC-20 token. 
     * If the `decimals()` function is present in the ERC-20 token, these MUST be the same value.
     * Defaults to 18 if neither this parameter nor the ERC-20 `decimals()` function are present.
     */
    decimals?: number;
    
    /**
     * Provides a short one-paragraph description of the ERC-20 token, without any markup or newlines.
     */
    description?: string;
    
    /**
     * A URI pointing to a resource with mime type `image/*` that represents this token.
     * If the image is a bitmap, it SHOULD have a width between 320 and 1080 pixels
     * The image SHOULD have an aspect ratio between 1.91:1 and 4:5 inclusive.
     */
    image?: string;
    
    /**
     * One or more URIs each pointing to a resource with mime type `image/*` that represents this token.
     * If an image is a bitmap, it SHOULD have a width between 320 and 1080 pixels
     * Images SHOULD have an aspect ratio between 1.91:1 and 4:5 inclusive.
     */
    images?: string[];
    
    /**
     * One or more URIs each pointing to a resource with mime type `image/*` that represent an icon for this token.
     * If an image is a bitmap, it SHOULD have a width between 320 and 1080 pixels, and MUST have a height equal to its width
     * Images MUST have an aspect ratio of 1:1, and use a transparent background
     */
    icons?: string[];
}
```

### ERC-721 Extension

#### Extension to the ERC-721 Metadata Schema

Contracts that implement ERC-721 and use its token metadata URI SHOULD to use the following TypeScript extension to the metadata URI:

```typescript
interface ERC721TokenMetadataInterop extends ERC721TokenMetadata {
    /**
     * Interoperability, to avoid confusion between different token URIs
     **/
    interop: InteroperabilityMetadata;
}
```

### ERC-1155 Extension

#### ERC-1155 Interface Extension

[ERC-1155](/EIPs/EIPS/eip-1155)-compliant contracts using the metadata extension SHOULD implement the following Solidity interface:

```solidity
pragma solidity ^0.8.0;

/// @title  ERC-1155 Metadata URI Interoperability Extension
interface ERC1155TokenMetadataInterop /* is ERC1155 */ {
    /// @notice         Gets an ERC-1046-compliant ERC-1155 token URI
    /// @param  tokenId The token ID to get the URI of
    /// @dev            The resolved data MUST be in JSON format and support ERC-1046&apos;s Extension to the ERC-1155 Token Metadata Schema
    ///                 This MUST be the same URI as the `uri(tokenId)` function, if present.
    function tokenURI(uint256 tokenId) external view returns (string);
}
```

#### Extension to the ERC-1155 Metadata Schema

Contracts that implement ERC-1155 and use its token metadata URI are RECOMMENDED to use the following extension to the metadata URI. Contracts that implement the interface described in the ERC-1155 Interface Extension section MUST use the following TypeScript extension:

```typescript
interface ERC1155TokenMetadataInterop extends ERC1155TokenMetadata {
    /**
     * Interoperability, to avoid confusion between different token URIs
     **/
    interop: InteroperabilityMetadata;
}
```

### Miscellaneous Recommendations

To save gas, it is RECOMMENDED for compliant contracts not to implement the `name()`, `symbol()`, or `decimals()` functions, and instead to only include them in the metadata URI. Additionally, for ERC-20 tokens, if the decimals is `18`, then it is NOT RECOMMENDED to include the `decimals` field in the metadata.

## Rationale

This ERC makes adding metadata to ERC-20 tokens more straightforward for developers, with minimal to no disruption to the overall ecosystem. Using the same parameter name makes it easier to reuse code.

Additionally, the recommendations not to use ERC-20&apos;s `name`, `symbol`, and `decimals` functions save gas.

Built-in interoperability is useful as otherwise it might not be easy to differentiate the type of the token. Interoperability could be done using [ERC-165](/EIPs/EIPS/eip-165), but static calls are time-inefficient for wallets and websites, and is generally inflexible. Instead, including interoperability data in the token URI increases flexibility while also giving a performance increase.

## Backwards Compatibility

This EIP is fully backwards compatible as its implementation simply extends the functionality of ERC-20 tokens and is optional. Additionally, it makes backward compatible recommendations for ERC-721 and ERC-1155 tokens.

## Security Considerations

### Server-Side Request Forgery (SSRF)

Wallets should be careful about making arbitrary requests to URLs. As such, it is recommended for wallets to sanitize the URI by whitelisting specific schemes and ports. A vulnerable wallet could be tricked into, for example, modifying data on a locally-hosted redis database.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 13 Apr 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1046</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1046</guid>
      </item>
    
      <item>
        <title>Overflow checking for the EVM</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-arithmetic-overflow-detection-for-the-evm/261</comments>
        
        <description>## Abstract
This EIP adds overflow checking for EVM arithmetic operations, and two new opcodes that check and clear the overflow flags.

## Motivation
The correct functioning of many contracts today is dependent on detecting and preventing overflow of arithmetic operations. Since the EVM operates on mod 2^256 integers and provides no built-in overflow detection or prevention, this requires manual checks on every arithmetic operation.

In the interests of facilitating efficient and secure contracts, we propose new opcodes that permit efficient detection of overflows, which can be checked periodically rather than after each operation.

## Specification

Two new flags are added to the EVM state: overflow (`ovf`) and signed overflow (`sovf`).

The `ovf` flag is set in the following circumstances:

 - When an `ADD` (`0x01`) opcode, with both inputs treated as unsigned integers, produces an ideal output in excess of 2^256 - 1.
 - When a `SUB` (`0x03`) opcode, with both inputs treated as unsigned integers, produces an ideal output less than 0.
 - When a `MUL` (`0x02`) opcode, with both inputs treated as unsigned integers, produces an ideal output in excess of 2^256 - 1.

The `sovf` flag is set whenever the `ovf` flag is set, and additionally in the following circumstances:

 - When an `ADD` opcode with both inputs having the same MSB results in the output having a different MSB (eg, `(+a) + (+b) = (-c)` or `(-a) + (-b) = (+c)`).
 - When a `SUB` opcode occurs and the result has the same MSB as the subtracted (second argument) (eg, `(+a) - (-b) = (-c)` or `(-a) - (+b) = (+c)`).
 - When a `MUL` opcode with both inputs being positive has a negative output.
 - When a `MUL` opcode with both inputs being negative has a negative output.
 - When a `MUL` opcode with one negative input and one positive input has a positive output.

A new opcode, `OFV` is added, with number `0x0c`. This opcode takes 0 arguments from the stack. When executed, it pushes `1` if the `ovf` flag is set, and `0` otherwise. It then sets the `ovf` flag to false.

A new opcode, `SOVF` is added, with number `0x0d`. This opcode takes 0 arguments from the stack. When executed, it pushes `1` if the `sovf` flag is set, and `0` otherwise. It then sets the `sovf` flag to false.

## Rationale
Any change to implement overflow protection needs to preserve behaviour of existing contracts, which precludes many changes to the arithmetic operations themselves. One option would be to provide an opcode that enables overflow protection, causing a throw or revert if an overflow happens. However, this limits the manner in which overflows can be handled.

Instead, we replicate functionality from real world CPUs, which typically implement &apos;carry&apos; and &apos;overflow&apos; flags.

Separate flags for signed and unsigned overflow are necessary due to the fact that a signed overflow may not result in an unsigned overflow.

## Backwards Compatibility
This EIP introduces no backwards compatibility issues.

## Test Cases
TBD

## Implementation
TBD

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 02 May 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1051</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1051</guid>
      </item>
    
      <item>
        <title>EXTCODEHASH opcode</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/extcodehash-opcode/262</comments>
        
        <description>## Abstract
This EIP specifies a new opcode, which returns the keccak256 hash of a contract&apos;s code.

## Motivation
Many contracts need to perform checks on a contract&apos;s bytecode, but do not necessarily need the bytecode itself. For instance, a contract may want to check if another contract&apos;s bytecode is one of a set of permitted implementations, or it may perform analyses on code and whitelist any contract with matching bytecode if the analysis passes.

Contracts can presently do this using the `EXTCODECOPY` (`0x3c`) opcode, but this is expensive, especially for large contracts, in cases where only the hash is required. As a result, we propose a new opcode, `EXTCODEHASH`, which returns the keccak256 hash of a contract&apos;s bytecode.

## Specification

A new opcode, `EXTCODEHASH`, is introduced, with number `0x3f`. The `EXTCODEHASH` 
takes one argument from the stack, zeros the first 96 bits 
and pushes to the stack the keccak256 hash of the code of the account 
at the address being the remaining 160 bits. 

In case the account does not exist or is empty (as defined by [EIP-161](/EIPs/EIPS/eip-161)) `0` is pushed to the stack.

In case the account does not have code the keccak256 hash of empty data
(i.e. `c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470`)
is pushed to the stack.

The gas cost of the `EXTCODEHASH` is 400.


## Rationale

As described in the motivation section, this opcode is widely useful, and saves 
on wasted gas in many cases.

The gas cost is the same as the gas cost for the `BALANCE` opcode because the 
execution of the `EXTCODEHASH` requires the same account lookup as in `BALANCE`.

Only the 20 last bytes of the argument are significant (the first 12 bytes are 
ignored) similarly to the semantics of the `BALANCE` (`0x31`), `EXTCODESIZE` (`0x3b`) and 
`EXTCODECOPY` (`0x3c`).

The `EXTCODEHASH` distinguishes accounts without code and non-existing accounts.
This is consistent with the way accounts are represented in the state trie.
This also allows smart contracts to check whether an account exists.


## Backwards Compatibility

There are no backwards compatibility concerns.


## Test Cases

1. The `EXTCODEHASH` of the account without code is `c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470`
   what is the keccak256 hash of empty data.
2. The `EXTCODEHASH` of non-existent account is `0`.
3. The `EXTCODEHASH` of a precompiled contract is either `c5d246...` or `0`.
4. If `EXTCODEHASH` of `A` is `X`, then `EXTCODEHASH` of `A + 2**160` is `X`.
5. The `EXTCODEHASH` of an account that selfdestructed in the current transaction.
6. The `EXTCODEHASH` of an account that selfdestructed and later the selfdestruct has been reverted.
7. The `EXTCODEHASH` of an account created in the current transaction.
8. The `EXTCODEHASH` of an account that has been newly created and later the creation has been reverted.
9. The `EXTCODEHASH` of an account that firstly does not exist and later is empty.
10. The `EXTCODEHASH` of an empty account that is going to be cleared by the state clearing rule.


## Implementation
TBD

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 02 May 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1052</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1052</guid>
      </item>
    
      <item>
        <title>Ethereum Lightweight Identity</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1056</comments>
        
        <description>## Simple Summary

A registry for key and attribute management of lightweight blockchain identities.

## Abstract

This ERC describes a standard for creating and updating identities with a limited use of blockchain resources. An identity can have an unlimited number of `delegates` and `attributes` associated with it. Identity creation is as simple as creating a regular key pair ethereum account, which means that it&apos;s free (no gas costs) and all ethereum accounts are valid identities. Furthermore this ERC is fully [DID compliant](https://w3c-ccg.github.io/did-spec/).

## Motivation

As we have been developing identity systems for the last couple of years at uPort it has become apparent that the cost of identity creation is a large issue. The previous Identity proposal [ERC-725](/EIPs/EIPS/eip-725) faces this exact issue. Our requirements when creating this ERC is that identity creation should be free, and should be possible to do in an offline environment (e.g. refugee scenario). However it must also be possible to rotate keys without changing the primary identifier of the identity. The identity system should be fit to use off-chain as well as on-chain.

## Definitions

* `Identifier`: a piece of data that uniquely identifies the identity, an ethereum address

* `delegate`: an address that is delegated for a specific time to perform some sort of function on behalf of an identity

* `delegateType`: the type of a delegate, is determined by a protocol or application higher up
  Examples:
  
  * `did-jwt`
  * `raiden`

* `attribute`: a piece of data associated with the identity

## Specification

This ERC specifies a contract called `EthereumDIDRegistry` that is deployed once and can then be commonly used by everyone.

### Identity ownership

By default an identity is owned by itself, meaning whoever controls the ethereum account with that address. The owner can be updated to a new key pair account or to a multisig account etc.

#### identityOwner

Returns the owner of the given identity.

```js
function identityOwner(address identity) public view returns(address);
```

#### changeOwner

Sets the owner of the given identity to another ethereum account.

```js
function changeOwner(address identity, address newOwner) public;
```

#### changeOwnerSigned

Same as above but with raw signature.


```js
function changeOwnerSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, address newOwner) public;
```

### Delegate management

Delegates can be used both on- and off-chain. They all have a `delegateType` which can be used to specify the purpose of the delegate.

#### validDelegate

Returns true if the given `delegate` is a delegate with type `delegateType` of `identity`.

```js
function validDelegate(address identity, bytes32 delegateType, address delegate) public view returns(bool);
```

#### addDelegate

Adds a new delegate with the given type. `validity` indicates the number of seconds that the delegate will be valid for, after which it will no longer be a delegate of `identity`.

```js
function addDelegate(address identity, bytes32 delegateType, address delegate, uint validity) public;
```


#### addDelegateSigned

Same as above but with raw signature.


```js
function addDelegateSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 delegateType, address delegate, uint validity) public;
```


#### revokeDelegate

Revokes the given `delegate` for the given `identity`.


```js
function revokeDelegate(address identity, bytes32 delegateType, address delegate) public;
```


#### revokeDelegateSigned

Same as above but with raw signature.


```js
function revokeDelegateSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 delegateType, address delegate) public;
```


### Attribute management

Attributes contain simple data about the identity. They can be managed only by the owner of the identity.


#### setAttribute

Sets an attribute with the given `name` and `value`, valid for `validity` seconds.


```js
function setAttribute(address identity, bytes32 name, bytes value, uint validity) public;
```


#### setAttributeSigned

Same as above but with raw signature.


```js
function setAttributeSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 name, bytes value, uint validity) public;
```


#### revokeAttribute

Revokes an attribute.


```js
function revokeAttribute(address identity, bytes32 name, bytes value) public;
```


#### revokeAttributeSigned

Same as above but with raw signature.


```js
function revokeAttributeSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, bytes32 name, bytes value) public;
```


### Events

#### DIDOwnerChanged

MUST be triggered when `changeOwner` or `changeOwnerSigned` was successfully called.


```js
event DIDOwnerChanged(
  address indexed identity,
  address owner,
  uint previousChange
);
```


#### DIDDelegateChanged

MUST be triggered when a change to a delegate was successfully made.


```js
event DIDDelegateChanged(
  address indexed identity,
  bytes32 delegateType,
  address delegate,
  uint validTo,
  uint previousChange
);
```


#### DIDAttributeChanged

MUST be triggered when a change to an attribute was successfully made.


```js
event DIDAttributeChanged(
  address indexed identity,
  bytes32 name,
  bytes value,
  uint validTo,
  uint previousChange
);
```


### Efficient lookup of events through linked identity events

Contract Events are a useful feature for storing data from smart contracts exclusively for off-chain use.  Unfortunately current ethereum implementations provide a very inefficient lookup mechanism. By using linked events that always link to the previous block with a change for the identity, we can solve this problem with much improved performance. Each identity has its previously changed block stored in the `changed` mapping.



1. Lookup `previousChange` block for identity

2. Lookup all events for given identity address using web3, but only for the `previousChange` block

3. Do something with the event

4. Find `previousChange` from the event  and repeat



Example code:


```js
const history = []
previousChange = await didReg.changed(identity)
while (previousChange) {
  const filter = await didReg.allEvents({topics: [identity], fromBlock: previousChange, toBlock: previousChange})
  const events = await getLogs(filter)
  previousChange = undefined
  for (let event of events) {
    history.unshift(event)
    previousChange = event.args.previousChange
  }
}     
```


### Building a DID document for an identity

The primary owner key should be looked up using `identityOwner(identity)`.  This should be the first of the publicKeys listed. Iterate through the `DIDDelegateChanged` events to build a list of additional keys and authentication sections as needed. The list of delegateTypes to include is still to be determined. Iterate through `DIDAttributeChanged` events for service entries, encryption public keys and other public names. The attribute names are still to be determined.


## Rationale

For on-chain interactions Ethereum has a built in account abstraction that can be used regardless of whether the account is a smart contract or a key pair. Any transaction has a `msg.sender` as the verified send of the transaction.


Since each Ethereum transaction has to be funded, there is a growing trend of on-chain transactions that are authenticated via an externally created signature and not by the actual transaction originator. This allows 3rd party funding services or receiver pays without any fundamental changes to the underlying Ethereum architecture. These kinds of transactions have to be signed by an actual key pair and thus can not be used to represent smart contract based Ethereum accounts.


We propose a way of a Smart Contract or regular key pair delegating signing for various purposes to externally managed key pairs. This allows a smart contract to be represented both on-chain as well as off-chain or in payment channels through temporary or permanent delegates.


## Backwards Compatibility

All ethereum accounts are valid identities (and DID compatible) using this standard. This means that any wallet provider that uses key pair accounts already supports the bare minimum of this standard, and can implement `delegate` and `attribute` functionality by simply using the `ethr-did` referenced below. As the **DID Auth** standard solidifies it also means that all of these wallets will be compatible with the [DID decentralized login system](https://github.com/decentralized-identity).


## Implementation

[ethr-did-registry](https://github.com/uport-project/ethr-did-registry/blob/develop/contracts/EthereumDIDRegistry.sol) (`EthereumDIDRegistry` contract implementation)

[ethr-did-resolver](https://github.com/uport-project/ethr-did-resolver) (DID compatible resolver)

[ethr-did](https://github.com/uport-project/ethr-did) (javascript library for using the identity)


### Deployment

The address for the `EthereumDIDRegistry` is `0xdca7ef03e98e0dc2b855be647c39abe984fcf21b` on Mainnet, Ropsten, Rinkeby and Kovan.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Thu, 03 May 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1056</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1056</guid>
      </item>
    
      <item>
        <title>ProgPoW, a Programmatic Proof-of-Work</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-progpow-a-programmatic-proof-of-work/272</comments>
        
        <description>## Simple Summary

A new Proof-of-Work algorithm to replace Ethash that utilizes almost all parts of commodity GPUs.

## Abstract

ProgPoW is a proof-of-work algorithm designed to close the efficiency gap available to specialized ASICs. It utilizes almost all parts of commodity hardware (GPUs), and comes pre-tuned for the most common hardware utilized in the Ethereum network.

This document presents an overview of the algorithm and examines what it means to be “ASIC-resistant.” Next, we compare existing PoW designs by analyzing how each algorithm executes in hardware. Finally, we present the detailed implementation by walking through the code.

## Motivation

Ever since the first bitcoin mining ASIC was released, many new Proof of Work algorithms have been created with the intention of being “ASIC-resistant”. The goal of “ASIC-resistance” is to resist the centralization of PoW mining power such that these coins couldn’t be so easily manipulated by a few players.

Ethereum&apos;s approach is to incentivize a geographically-distributed community of miners with a low barrier to entry on commodity hardware.  As stated in the [Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf):

&gt; 11.5. Mining Proof-of-Work. The mining proof-ofwork (PoW) exists as a cryptographically secure nonce that proves beyond reasonable doubt that a particular amount of computation has been expended in the determination of some token value n. It is utilised to enforce the blockchain security by giving meaning and credence to the notion of difficulty (and, by extension, total difficulty). However, since mining new blocks comes with an attached reward, the proof-of-work not only functions as a method of securing confidence that the blockchain will remain canonical into the future, but also as a wealth distribution mechanism.

&gt; For both reasons, there are two important goals of the proof-of-work function; firstly, it should be as accessible as possible to as many people as possible. The requirement of, or reward from, specialised and uncommon hardware should be minimised. This makes the distribution model as open as possible, and, ideally, makes the act of mining a simple swap from electricity to Ether at roughly the same rate for anyone around the world.

&gt; Secondly, it should not be possible to make super-linear profits, and especially not so with a high initial barrier. Such a mechanism allows a well-funded adversary to gain a troublesome amount of the network’s total mining power and as such gives them a super-linear reward (thus skewing distribution in their favour) as well as reducing the network security...

&gt; ... While ASICs exist for a proof-of-work function, both goals are placed in jeopardy.  Because of this, a proof-of-work function that is ASIC-resistant (i.e. difficult or economically inefficient to implement in specialised compute hardware) has been identified as the proverbial silver bullet.

It is from these premises that Ethash was designed as an ASIC-resistant proof-of-work:

&gt; Two directions exist for ASIC resistance; firstly make it sequential memory-hard, i.e. engineer the function such that the determination of the nonce requires a lot of memory and bandwidth such that the memory cannot be used in parallel to discover multiple nonces simultaneously. The second is to make the type of computation it would need to do general-purpose; the meaning of “specialised hardware” for a general-purpose task set is, naturally, general purpose hardware and as such commodity desktop computers are likely to be pretty close to “specialised hardware” for the task. For Ethereum 1.0 we have chosen the first path.

5 years of experience with the Ethereum blockchain have demonstrated the success of our approach.  This success cannot be taken for granted.
* 11 years of experience with PoW Blockchains have shown a centralization in hardware development, resulting in a [few companies](https://www.asicminervalue.com/) controlling the lifecycle of new hardware with limited distribution.
* New ASICs for Ethash are providing higher efficiency than GPUs, such as the [Antminer E3](https://shop.bitmain.com/product/detail?pid=00020181031134626816gh0zYNKC06A3).
* As much as 40% of the Ethereum network may now be secured by ASICs.

ProgPow restores Ethash&apos; ASIC-resistance by extending Ethash with a GPU-specific approach to the second path — making the “specialised hardware” for the PoW task commodity hardware.

### ProgPoW Overview
The design goal of ProgPoW is to have the algorithm’s requirements match what is available on commodity GPUs:  If the algorithm were to be implemented on a custom ASIC there should be little opportunity for efficiency gains compared to a commodity GPU.

The main elements of the algorithm are:
* Changes keccak_f1600 (with 64-bit words) to keccak_f800 (with 32-bit words) to reduce impact on total power
* Increases mix state.
* Adds a random sequence of math in the main loop.
* Adds reads from a small, low-latency cache that supports random addresses.
* Increases the DRAM read from 128 bytes to 256 bytes.

The random sequence changes every `PROGPOW_PERIOD` (about 2 to 12 minutes depending on the configured value).  When mining source code is generated for the random sequence and compiled on the host CPU.  The GPU will execute the compiled code where what math to perform and what mix state to use are already resolved.

While a custom ASIC to implement this algorithm is still possible, the efficiency gains available are minimal.  The majority of a commodity GPU is required to support the above elements. The only optimizations available are:
* Remove the graphics pipeline (displays, geometry engines, texturing, etc)
* Remove floating point math
* A few ISA tweaks, like instructions that exactly match the merge() function

These would result in minimal, roughly 1.1-1.2x, efficiency gains.  This is much less than the 2x for Ethash or 50x for Cryptonight.

### Rationale for PoW on Commodity Hardware
With the growth of large mining pools, the control of hashing power has been delegated to the top few pools to provide a steadier economic return for small miners. While some have made the argument that large centralized pools defeats the purpose of “ASIC resistance,” it’s important to note that ASIC based coins are even more centralized for several reasons.

1. No natural distribution: There isn’t an economic purpose for ultra-specialized hardware outside of mining and thus no reason for most people to have it.
2. No reserve group: Thus, there’s no reserve pool of hardware or reserve pool of interested parties to jump in when coin price is volatile and attractive for manipulation.
3. High barrier to entry: Initial miners are those rich enough to invest capital and ecological resources on the unknown experiment a new coin may be. Thus, initial coin distribution through mining will be very limited causing centralized economic bias.
4. Delegated centralization vs implementation centralization: While pool centralization is delegated, hardware monoculture is not: only the limited buyers of this hardware can participate so there isn’t even the possibility of divesting control on short notice.
5. No obvious decentralization of control even with decentralized mining: Once large custom ASIC makers get into the game, designing back-doored hardware is trivial. ASIC makers have no incentive to be transparent or fair in market participation.

While the goal of “ASIC resistance” is valuable, the entire concept of “ASIC resistance” is a bit of a fallacy.  CPUs and GPUs are themselves ASICs.  Any algorithm that can run on a commodity ASIC (a CPU or GPU) by definition can have a customized ASIC created for it with slightly less functionality. Some algorithms are intentionally made to be  “ASIC friendly” - where an ASIC implementation is drastically more efficient than the same algorithm running on general purpose hardware. The protection that this offers when the coin is unknown also makes it an attractive target for a dedicated mining ASIC company as soon as it becomes useful.

Therefore, ASIC resistance is: the efficiency difference of specialized hardware versus hardware that has a wider adoption and applicability.  A smaller efficiency difference between custom vs general hardware mean higher resistance and a better algorithm. This efficiency difference is the proper metric to use when comparing the quality of PoW algorithms.  Efficiency could mean absolute performance, performance per watt, or performance per dollar - they are all highly correlated.  If a single entity creates and controls an ASIC that is drastically more efficient, they can gain 51% of the network hashrate and possibly stage an attack.

### Review of Existing PoW Algorithms

#### SHA256
* Potential ASIC efficiency gain ~ 1000X

The SHA algorithm is a sequence of simple math operations - additions, logical ops, and rotates.

To process a single op on a CPU or GPU requires fetching and decoding an instruction, reading data from a register file, executing the instruction, and then writing the result back to a register file.  This takes significant time and power.

A single op implemented in an ASIC takes a handful of transistors and wires.  This means every individual op takes negligible power, area, or time.  A hashing core is built by laying out the sequence of required ops.

The hashing core can execute the required sequence of ops in much less time, and using less power or area, than doing the same sequence on a CPU or GPU.  A bitcoin ASIC consists of a number of identical hashing cores and some minimal off-chip communication.

#### Scrypt and NeoScrypt
* Potential ASIC efficiency gain ~ 1000X

Scrypt and NeoScrypt are similar to SHA in the arithmetic and bitwise operations used. Unfortunately, popular coins such as Litecoin only use a scratchpad size between 32kb and 128kb for their PoW mining algorithm. This scratch pad is small enough to trivially fit on an ASIC next to the math core. The implementation of the math core would be very similar to SHA, with similar efficiency gains.

#### X11 and X16R
* Potential ASIC efficiency gain ~ 1000X

X11 (and similar X##) require an ASIC that has 11 unique hashing cores pipelined in a fixed sequence.  Each individual hashing core would have similar efficiency to an individual SHA core, so the overall design will have the same efficiency gains.

X16R requires the multiple hashing cores to interact through a simple sequencing state machine. Each individual core will have similar efficiency gains and the sequencing logic will take minimal power, area, or time.

The Baikal BK-X is an existing ASIC with multiple hashing cores and a programmable sequencer.  It has been upgraded to enable new algorithms that sequence the hashes in different orders.

#### Equihash
* Potential ASIC efficiency gain ~ 100X

The ~150mb of state is large but possible on an ASIC. The binning, sorting, and comparing of bit strings could be implemented on an ASIC at extremely high speed.

#### Cuckoo Cycle
* Potential ASIC efficiency gain ~ 100X

The amount of state required on-chip is not clear as there are Time/Memory Tradeoff attacks. A specialized graph traversal core would have similar efficiency gains to a SHA compute core.

#### CryptoNight
* Potential ASIC efficiency gain ~ 50X

Compared to Scrypt, CryptoNight does much less compute and requires a full 2mb of scratch pad (there is no known Time/Memory Tradeoff attack).  The large scratch pad will dominate the ASIC implementation and limit the number of hashing cores, limiting the absolute performance of the ASIC.  An ASIC will consist almost entirely of just on-die SRAM.

#### Ethash
* Potential ASIC efficiency gain ~ 2X

Ethash requires external memory due to the large size of the DAG.  However that is all that it requires - there is minimal compute that is done on the result loaded from memory.  As a result a custom ASIC could remove most of the complexity, and power, of a GPU and be just a memory interface connected to a small compute engine.

## Specification

ProgPoW can be tuned using the following parameters.  The proposed settings have been tuned for a range of existing, commodity GPUs:

* `PROGPOW_PERIOD`: Number of blocks before changing the random program
* `PROGPOW_LANES`: The number of parallel lanes that coordinate to calculate a single hash instance
* `PROGPOW_REGS`: The register file usage size
* `PROGPOW_DAG_LOADS`: Number of uint32 loads from the DAG per lane
* `PROGPOW_CACHE_BYTES`: The size of the cache
* `PROGPOW_CNT_DAG`: The number of DAG accesses, defined as the outer loop of the algorithm (64 is the same as Ethash)
* `PROGPOW_CNT_CACHE`: The number of cache accesses per loop
* `PROGPOW_CNT_MATH`: The number of math operations per loop

The values of these parameters have been tweaked between the original version and the version proposed here for Ethereum adoption.  See [this medium post](https://medium.com/@ifdefelse/progpow-progress-da5bb31a651b) for details.

| Parameter             | 0.9.2 | 0.9.3 |
|-----------------------|-------|-------|
| `PROGPOW_PERIOD`      | `50`  | `10`  |
| `PROGPOW_LANES`       | `16`  | `16`  |
| `PROGPOW_REGS`        | `32`  | `32`  |
| `PROGPOW_DAG_LOADS`   | `4`   | `4`   |
| `PROGPOW_CACHE_BYTES` | `16x1024` | `16x1024` |
| `PROGPOW_CNT_DAG`     | `64`  | `64`  | `64`  |
| `PROGPOW_CNT_CACHE`   | `12`  | `11`  | `11`  |
| `PROGPOW_CNT_MATH`    | `20`  | `18`  | `18`  |

| DAG Parameter            | 0.9.2 | 0.9.3 |
|--------------------------|-------|-------|
| `ETHASH_DATASET_PARENTS` | `256` | `256` |


The random program changes every `PROGPOW_PERIOD` blocks (default `10`, roughly 2 minutes) to ensure the hardware executing the algorithm is fully programmable.  If the program only changed every DAG epoch (roughly 5 days) certain miners could have time to develop hand-optimized versions of the random sequence, giving them an undue advantage.

Sample code is written in C++, this should be kept in mind when evaluating the code in the specification.
All numerics are computed using unsigned 32 bit integers.  Any overflows are trimmed off before proceeding to the next computation.  Languages that use numerics not fixed to bit lengths (such as Python and JavaScript) or that only use signed integers (such as Java) will need to keep their languages&apos; quirks in mind.  The extensive use of 32 bit data values aligns with modern GPUs internal data architectures.

ProgPoW uses a 32-bit variant of **FNV1a** for merging data. The existing Ethash uses a similar variant of FNV1 for merging, but FNV1a provides better distribution properties.

Test vectors can be found [in the test vectors file](/EIPs/assets/eip-1057/test-vectors#fnv1a).

```cpp
const uint32_t FNV_PRIME = 0x1000193;
const uint32_t FNV_OFFSET_BASIS = 0x811c9dc5;

uint32_t fnv1a(uint32_t h, uint32_t d)
{
    return (h ^ d) * FNV_PRIME;
}
```

ProgPow uses [KISS99](https://en.wikipedia.org/wiki/KISS_(algorithm)) for random number generation. This is the simplest (fewest instruction) random generator that passes the TestU01 statistical test suite.  A more complex random number generator like Mersenne Twister can be efficiently implemented on a specialized ASIC, providing an opportunity for efficiency gains.

Test vectors can be found [in the test vectors file](/EIPs/assets/eip-1057/test-vectors#kiss99).

```cpp
typedef struct {
    uint32_t z, w, jsr, jcong;
} kiss99_t;

// KISS99 is simple, fast, and passes the TestU01 suite
// https://en.wikipedia.org/wiki/KISS_(algorithm)
// http://www.cse.yorku.ca/~oz/marsaglia-rng.html
uint32_t kiss99(kiss99_t &amp;st)
{
    st.z = 36969 * (st.z &amp; 65535) + (st.z &gt;&gt; 16);
    st.w = 18000 * (st.w &amp; 65535) + (st.w &gt;&gt; 16);
    uint32_t MWC = ((st.z &lt;&lt; 16) + st.w);
    st.jsr ^= (st.jsr &lt;&lt; 17);
    st.jsr ^= (st.jsr &gt;&gt; 13);
    st.jsr ^= (st.jsr &lt;&lt; 5);
    st.jcong = 69069 * st.jcong + 1234567;
    return ((MWC^st.jcong) + st.jsr);
}
```

The `fill_mix` function populates an array of `int32` values used by each lane in the hash calculations.

Test vectors can be found [in the test vectors file](/EIPs/assets/eip-1057/test-vectors#fill_mix).

```cpp
void fill_mix(
    uint64_t seed,
    uint32_t lane_id,
    uint32_t mix[PROGPOW_REGS]
)
{
    // Use FNV to expand the per-warp seed to per-lane
    // Use KISS to expand the per-lane seed to fill mix
    uint32_t fnv_hash = FNV_OFFSET_BASIS;
    kiss99_t st;
    st.z = fnv1a(fnv_hash, seed);
    st.w = fnv1a(fnv_hash, seed &gt;&gt; 32);
    st.jsr = fnv1a(fnv_hash, lane_id);
    st.jcong = fnv1a(fnv_hash, lane_id);
    for (int i = 0; i &lt; PROGPOW_REGS; i++)
        mix[i] = kiss99(st);
}
```

Like Ethash Keccak is used to seed the sequence per-nonce and to produce the final result.  The keccak-f800 variant is used as the 32-bit word size matches the native word size of modern GPUs.  The implementation is a variant of SHAKE with width=800, bitrate=576, capacity=224, output=256, and no padding.  The result of keccak is treated as a 256-bit big-endian number - that is result byte 0 is the MSB of the value.

As with Ethash the input and output of the keccak function are fixed and relatively small.  This means only a single &quot;absorb&quot; and &quot;squeeze&quot; phase are required.  For a pseudo-code implementation of the `keccak_f800_round` function see the `Round[b](A,RC)` function in the &quot;Pseudo-code description of the permutations&quot; section of the [official Keccak specs](https://keccak.team/keccak_specs_summary.html).

```cpp
hash32_t keccak_f800_progpow(uint32_t* state)
{
    // keccak_f800 call for the single absorb pass
    for (int r = 0; r &lt; 22; r++)
        keccak_f800_round(st, r);

    // Squeeze phase for fixed 8 words of output
    hash32_t ret;
    for (int i=0; i&lt;8; i++)
        ret.uint32s[i] = st[i];

    return ret;
}
```

The inner loop uses FNV and KISS99 to generate a random sequence from the `prog_seed`.  This random sequence determines which mix state is accessed and what random math is performed.

Since the `prog_seed` changes only once per `PROGPOW_PERIOD` (10 blocks or about 2 minutes) it is expected that while mining `progPowLoop` will be evaluated on the CPU to generate source code for that period&apos;s sequence.  The source code will be compiled on the CPU before running on the GPU.  You can see an example sequence and generated source code in [kernel.cu](https://github.com/ifdefelse/ProgPOW/blob/824cd791634204c4cc7e31f84bb76c0c84895bd3/test/kernel.cu).

Test vectors can be found [in the test vectors file](/EIPs/assets/eip-1057/test-vectors#progpowinit).

```cpp
kiss99_t progPowInit(uint64_t prog_seed, int mix_seq_dst[PROGPOW_REGS], int mix_seq_src[PROGPOW_REGS])
{
    kiss99_t prog_rnd;
    prog_rnd.z = fnv1a(FNV_OFFSET_BASIS, prog_seed);
    prog_rnd.w = fnv1a(prog_rnd.z, prog_seed &gt;&gt; 32);
    prog_rnd.jsr = fnv1a(prog_rnd.w, prog_seed);
    prog_rnd.jcong = fnv1a(prog_rnd.jsr, prog_seed &gt;&gt; 32);
    // Create a random sequence of mix destinations for merge() and mix sources for cache reads
    // guarantees every destination merged once
    // guarantees no duplicate cache reads, which could be optimized away
    // Uses Fisher-Yates shuffle
    for (int i = 0; i &lt; PROGPOW_REGS; i++)
    {
        mix_seq_dst[i] = i;
        mix_seq_src[i] = i;
    }
    for (int i = PROGPOW_REGS - 1; i &gt; 0; i--)
    {
        int j;
        j = kiss99(prog_rnd) % (i + 1);
        swap(mix_seq_dst[i], mix_seq_dst[j]);
        j = kiss99(prog_rnd) % (i + 1);
        swap(mix_seq_src[i], mix_seq_src[j]);
    }
    return prog_rnd;
}
```

The math operations that merges values into the mix data are ones chosen to maintain entropy.

Test vectors can be found [in the test vectors file](/EIPs/assets/eip-1057/test-vectors#math).

```cpp
// Merge new data from b into the value in a
// Assuming A has high entropy only do ops that retain entropy
// even if B is low entropy
// (IE don&apos;t do A&amp;B)
uint32_t merge(uint32_t a, uint32_t b, uint32_t r)
{
    switch (r % 4)
    {
    case 0: return (a * 33) + b;
    case 1: return (a ^ b) * 33;
    // prevent rotate by 0 which is a NOP
    case 2: return ROTL32(a, ((r &gt;&gt; 16) % 31) + 1) ^ b;
    case 3: return ROTR32(a, ((r &gt;&gt; 16) % 31) + 1) ^ b;
    }
}
```

The math operations chosen for the random math are ones that are easy to implement in CUDA and OpenCL, the two main programming languages for commodity GPUs. The [mul_hi](https://www.khronos.org/registry/OpenCL/sdk/1.1/docs/man/xhtml/mul_hi.html), [min](https://www.khronos.org/registry/OpenCL/sdk/2.0/docs/man/xhtml/integerMax.html), [clz](https://www.khronos.org/registry/OpenCL/sdk/1.1/docs/man/xhtml/clz.html), and [popcount](https://www.khronos.org/registry/OpenCL/sdk/2.0/docs/man/xhtml/popcount.html) functions match the corresponding OpenCL functions.  ROTL32 matches the OpenCL [rotate](https://www.khronos.org/registry/OpenCL/sdk/1.0/docs/man/xhtml/rotate.html) function.  ROTR32 is rotate right, which is equivalent to `rotate(i, 32-v)`.

Test vectors can be found [in the test vectors file](/EIPs/assets/eip-1057/test-vectors#math).

```cpp
// Random math between two input values
uint32_t math(uint32_t a, uint32_t b, uint32_t r)
{
    switch (r % 11)
    {
    case 0: return a + b;
    case 1: return a * b;
    case 2: return mul_hi(a, b);
    case 3: return min(a, b);
    case 4: return ROTL32(a, b);
    case 5: return ROTR32(a, b);
    case 6: return a &amp; b;
    case 7: return a | b;
    case 8: return a ^ b;
    case 9: return clz(a) + clz(b);
    case 10: return popcount(a) + popcount(b);
    }
}
```

The flow of the inner loop is:
* Lane `(loop % LANES)` is chosen as the leader for that loop iteration
* The leader&apos;s `mix[0]` value modulo the number of 256-byte DAG entries is used to select where to read from the full DAG
* Each lane reads `DAG_LOADS` sequential words, using `(lane ^ loop) % LANES` as the starting offset within the entry.
* The random sequence of math and cache accesses is performed
* The DAG data read at the start of the loop is merged at the end of the loop

`prog_seed` and `loop` come from the outer loop, corresponding to the current program seed (which is block_number/PROGPOW_PERIOD) and the loop iteration number.  `mix` is the state array, initially filled by `fill_mix`. `dag` is the bytes of the Ethash DAG grouped into 32 bit unsigned ints in little-endian format.  On little-endian architectures this is just a normal int32 pointer to the existing DAG.

`DAG_BYTES` is set to the number of bytes in the current DAG, which is generated identically to the existing Ethash algorithm.  

Test vectors can be found [in the test vectors file](/EIPs/assets/eip-1057/test-vectors#progpowloop).

```cpp
void progPowLoop(
    const uint64_t prog_seed,
    const uint32_t loop,
    uint32_t mix[PROGPOW_LANES][PROGPOW_REGS],
    const uint32_t *dag)
{
    // dag_entry holds the 256 bytes of data loaded from the DAG
    uint32_t dag_entry[PROGPOW_LANES][PROGPOW_DAG_LOADS];
    // On each loop iteration rotate which lane is the source of the DAG address.
    // The source lane&apos;s mix[0] value is used to ensure the last loop&apos;s DAG data feeds into this loop&apos;s address.
    // dag_addr_base is which 256-byte entry within the DAG will be accessed
    uint32_t dag_addr_base = mix[loop%PROGPOW_LANES][0] %
        (DAG_BYTES / (PROGPOW_LANES*PROGPOW_DAG_LOADS*sizeof(uint32_t)));
    for (int l = 0; l &lt; PROGPOW_LANES; l++)
    {
        // Lanes access DAG_LOADS sequential words from the dag entry
        // Shuffle which portion of the entry each lane accesses each iteration by XORing lane and loop.
        // This prevents multi-chip ASICs from each storing just a portion of the DAG
        size_t dag_addr_lane = dag_addr_base * PROGPOW_LANES + (l ^ loop) % PROGPOW_LANES;
        for (int i = 0; i &lt; PROGPOW_DAG_LOADS; i++)
            dag_entry[l][i] = dag[dag_addr_lane * PROGPOW_DAG_LOADS + i];
    }

    // Initialize the program seed and sequences
    // When mining these are evaluated on the CPU and compiled away
    int mix_seq_dst[PROGPOW_REGS];
    int mix_seq_src[PROGPOW_REGS];
    int mix_seq_dst_cnt = 0;
    int mix_seq_src_cnt = 0;
    kiss99_t prog_rnd = progPowInit(prog_seed, mix_seq_dst, mix_seq_src);

    int max_i = max(PROGPOW_CNT_CACHE, PROGPOW_CNT_MATH);
    for (int i = 0; i &lt; max_i; i++)
    {
        if (i &lt; PROGPOW_CNT_CACHE)
        {
            // Cached memory access
            // lanes access random 32-bit locations within the first portion of the DAG
            int src = mix_seq_src[(mix_seq_src_cnt++)%PROGPOW_REGS];
            int dst = mix_seq_dst[(mix_seq_dst_cnt++)%PROGPOW_REGS];
            int sel = kiss99(prog_rnd);
            for (int l = 0; l &lt; PROGPOW_LANES; l++)
            {
                uint32_t offset = mix[l][src] % (PROGPOW_CACHE_BYTES/sizeof(uint32_t));
                mix[l][dst] = merge(mix[l][dst], dag[offset], sel);
            }
        }
        if (i &lt; PROGPOW_CNT_MATH)
        {
            // Random Math
            // Generate 2 unique sources
            int src_rnd = kiss99(prog_rnd) % (PROGPOW_REGS * (PROGPOW_REGS-1));
            int src1 = src_rnd % PROGPOW_REGS; // 0 &lt;= src1 &lt; PROGPOW_REGS
            int src2 = src_rnd / PROGPOW_REGS; // 0 &lt;= src2 &lt; PROGPOW_REGS - 1
            if (src2 &gt;= src1) ++src2; // src2 is now any reg other than src1
            int sel1 = kiss99(prog_rnd);
            int dst  = mix_seq_dst[(mix_seq_dst_cnt++)%PROGPOW_REGS];
            int sel2 = kiss99(prog_rnd);
            for (int l = 0; l &lt; PROGPOW_LANES; l++)
            {
                uint32_t data = math(mix[l][src1], mix[l][src2], sel1);
                mix[l][dst] = merge(mix[l][dst], data, sel2);
            }
        }
    }
    // Consume the global load data at the very end of the loop to allow full latency hiding
    // Always merge into mix[0] to feed the offset calculation
    for (int i = 0; i &lt; PROGPOW_DAG_LOADS; i++)
    {
        int dst = (i==0) ? 0 : mix_seq_dst[(mix_seq_dst_cnt++)%PROGPOW_REGS];
        int sel = kiss99(prog_rnd);
        for (int l = 0; l &lt; PROGPOW_LANES; l++)
            mix[l][dst] = merge(mix[l][dst], dag_entry[l][i], sel);
    }
}
```

The flow of the overall algorithm is:
* A keccak hash of the header + nonce to create a digest of 256 bits from keccak_f800 (padding is consistent with custom one in ethash)
* Use first two words of digest as seed to generate initial mix data
* Loop multiple times, each time hashing random loads and random math into the mix data
* Hash all the mix data into a single 256-bit value
* A final keccak hash using carry-over digest from initial data + mix_data final 256 bit value (padding is consistent with custom one in ethash)
* When mining this final value is compared against a `hash32_t` target

```cpp
hash32_t progPowHash(
    const uint64_t prog_seed,    // value is (block_number/PROGPOW_PERIOD)
    const uint64_t nonce,
    const hash32_t header,
    const uint32_t *dag          // gigabyte DAG located in framebuffer - the first portion gets cached
)
{
    hash32_t hash_init;
    hash32_t hash_final;

    uint32_t mix[PROGPOW_LANES][PROGPOW_REGS];

    /*  
        ========================================
        Absorb phase for initial keccak pass
        ========================================
    */

    {
        uint32_t state[25] = {0x0};
        // 1st fill with header data (8 words)
        for (int i = 0; i &lt; 8; i++)
            state[i] = header.uint32s[i];

        // 2nd fill with nonce (2 words)
        state[8] = nonce;
        state[9] = nonce &gt;&gt; 32;

        // 3rd apply padding
        state[10] = 0x00000001;
        state[18] = 0x80008081;

        // keccak(header..nonce)
        hash_init = keccak_f800_progpow(state);

        // get the seed to initialize mix
        seed = ((uint64_t)hash_init.uint32s[1] &lt;&lt; 32) | hash_init.uint32s[0]);
	}

    // initialize mix for all lanes
    for (int l = 0; l &lt; PROGPOW_LANES; l++)
        fill_mix(seed, l, mix[l]);

    // execute the randomly generated inner loop
    for (int i = 0; i &lt; PROGPOW_CNT_DAG; i++)
        progPowLoop(prog_seed, i, mix, dag);

    // Reduce mix data to a per-lane 32-bit digest
    uint32_t digest_lane[PROGPOW_LANES];
    for (int l = 0; l &lt; PROGPOW_LANES; l++)
    {
        digest_lane[l] = FNV_OFFSET_BASIS;
        for (int i = 0; i &lt; PROGPOW_REGS; i++)
            digest_lane[l] = fnv1a(digest_lane[l], mix[l][i]);
    }
    // Reduce all lanes to a single 256-bit digest
    for (int i = 0; i &lt; 8; i++)
        digest.uint32s[i] = FNV_OFFSET_BASIS;
    for (int l = 0; l &lt; PROGPOW_LANES; l++)
        digest.uint32s[l%8] = fnv1a(digest.uint32s[l%8], digest_lane[l]);

    /*  
        ========================================
        Absorb phase for final keccak pass
        ========================================
    */

    {
        uint32_t state[25] = {0x0};

        // 1st fill with hash_init (8 words)
        for (int i = 0; i &lt; 8; i++)
            state[i] = hash_init.uint32s[i];

        // 2nd fill with digest from main loop
        for (int i = 8; i &lt; 16; i++)
            state[i] = digest.uint32s[i - 8];

        // 3rd apply padding
        state[17] = 0x00000001;
        state[24] = 0x80008081;

        // keccak(header..nonce)
        hash_final = keccak_f800_progpow(state);
	}

    // Compare hash final to target
    [...]

}
```

## Security Considerations

This proposal has been software and hardware audited:
* [Least Authority — ProgPoW Software Audit PDF](https://leastauthority.com/static/publications/LeastAuthority-ProgPow-Algorithm-Final-Audit-Report.pdf)
* [Bob Rao - ProgPoW Hardware Audit PDF](https://github.com/ethereum-cat-herders/progpow-audit/raw/master/Bob%20Rao%20-%20ProgPOW%20Hardware%20Audit%20Report%20Final.pdf)

Least Authority in their findings suggest a change to DAG generation --  modification of `ETHASH_DATASET_PARENTS` from a value of 256 to the new value of 512 -- in order to mitigate vulnerability to a &quot;Light Evaluation&quot; attack. Due to this the DAG memory file used by ProgPoW is would no longer compatible with the one used by Ethash (epoch length and size increase ratio remain the same though).

We do not recommend implementing this fix at this time. Ethash will not be exploitable for years, and it&apos;s not clear ProgPoW will ever be exploitable.  It&apos;s better to deploy the audited code.

After the completion of the audits a clever finding by [Kik](https://github.com/kik/) disclosed a vulnerability to [bypassing ProgPoW memory hardness](https://github.com/kik/progpow-exploit).  The vulnerability is present in Ethash as well but is near-impossible to exploit.  In progPoW it is not possible to exploit -- it assumes the ability to create variants of the candidate block&apos;s header hash in a fashion similar to bitcoin, which is actually not possible in Ethereum.  An attacker would need modified block headers, would need customized nodes able to accept the modified block headers, and uses extraNonce/extraData as entropy -- which isn’t the standard.  And the required brute-force search would be difficult to accomplish in one blocktime.  And even if supported by a customized node the block propagation of such mined blocks would be immediately blocked by other peers as the header hash is invalid.

The authors have since found another vulnerability similar to Kik&apos;s, but it adds too much overhead to be ASIC-friendly.  See Lanfranchi&apos;s full explanation [here](https://github.com/ifdefelse/ProgPOW/issues/51#issuecomment-690155355).  To completely prevent such exploits we could change the condition modifying the input state of the last keccak pass from
* header (256 bits) +
* seed for mix initiator (64 bits) +
* mix from main loop (256 bits)
* no padding

to
* digest from initial keccak (256 bits) +
* mix from main loop (256 bits) +
* padding

thus widening the constraint to target in keccak [brute force keccak linear searches](https://github.com/kik/progpow-exploit) from 64 to 256 bits.

This fix is available as a PR to the reference implementation.  Again, we do not recommend implementing this fix at this time.  Kik&apos;s vulnerability and others like it cannot be exploited now and likely never will be.  It&apos;s better to deploy the audited code.

Note that these vulnerabilities cannot be exploited to deny service, double spend, or otherwise damage the network.  They could at worst give their deployer an efficiency advantage over other miners.

## Test Cases

The random sequence generated for block 30,000 (prog_seed 3,000) can been seen in [kernel.cu](https://github.com/ifdefelse/ProgPOW/blob/824cd791634204c4cc7e31f84bb76c0c84895bd3/test/kernel.cu).

The algorithm run on block 30,000 produces the following digest and result:
```
Header     : 0xffeeddccbbaa9988776655443322110000112233445566778899aabbccddeeff
Nonce      : 0x123456789abcdef0
Hash init  : 0xee304846ddd0a47b98179e96b60ec5ceeae2727834367e593de780e3e6d1892f
Mix seed   : 0x7ba4d0dd464830ee
Mix hash   : 0x493c13e9807440571511b561132834bbd558dddaa3b70c09515080a6a1aff6d0
Hash final : 0x46b72b75f238bea3fcfd227e0027dc173dceaa1fb71744bd3d5e030ed2fed053
```

Additional test vectors can be found [in the test vectors file](/EIPs/assets/eip-1057/test-vectors#progpowhash).

Machine-readable test vectors (T.B.D)


## Implementation

The reference ProgPoW mining implementation is located at [the @ifdefelse ProgPOW repository](https://github.com/ifdefelse/ProgPOW).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

The reference ProgPoW mining implementation located at [ProgPOW](https://github.com/ifdefelse/ProgPOW) is a derivative of ethminer so retains the GPL license.
</description>
        <pubDate>Wed, 02 May 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1057</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1057</guid>
      </item>
    
      <item>
        <title>Formalize IPFS hash into ENS(Ethereum Name Service) resolver</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-1062-formalize-ipfs-hash-into-ens-ethereum-name-service-resolver/281</comments>
        
        <description>## Simple Summary
To specify the mapping protocol between resources stored on IPFS and ENS(Ethereum Naming Service).

## Abstract
The following standard details the implementation of how to combine the IPFS cryptographic hash unique fingerprint with ENS public resolver. This standard provides a functionality to get and set IPFS online resources to ENS resolver.
  
We think that this implementation is not only aim to let more developers and communities to provide more use cases, but also leverage the human-readable features to gain more user adoption accessing decentralized resources. We considered the IPFS ENS resolver mapping standard a cornerstone for building future Web3.0 service.

## Motivation
To build a fully decentralized web service, it’s necessary to have a decentralized file storage system. Here comes the IPFS, for three following advantages :
- Address large amounts of data, and has unique cryptographic hash for every record.
- Since IPFS is also based on peer to peer network, it can be really helpful to deliver large amounts of data to users, in a safer way and lower the millions of cost for the bandwidth.
- IPFS stores files in high efficient way via tracking version history for every file, and removing the duplications across the network.
  
Those features makes perfect match for integrating into ENS, and these make users can easily access content through ENS, and show up in the normal browser.


## Specification
The condition now is that the IPFS file fingerprint using base58 and in the meantime, the Ethereum uses hex in API to encode the binary data. So that need a way to process the condition requires not only we need to transfer from IPFS to Ethereum, but also need to convert it back.
  
To solve these requirements, we can use binary buffer bridging that gap.  
When mapping the IPFS base58 string to ENS resolver, first we convert the Base58 to binary buffer, turn the buffer to hex encrypted format, and save to the contract. Once we want to get the IPFS resources address represented by the specific ENS, we can first find the mapping information stored as hex format before, extract the hex format to binary buffer, and finally turn that to IPFS Base58 address string.


## Rationale
To implement the specification, need two methods from ENS public resolver contract, when we want to store IPFS file fingerprint to contract, convert the Base58 string identifier to the hex format and invoke the `setMultihash` method below :
  
```solidity
function setMultihash(bytes32 node, bytes hash) public only_owner(node);
```
  
Whenever users need to visit the ENS content, we call the `multihash` method to get the IPFS hex data, transfer to the Base58 format, and return the IPFS resources to use.
  
```solidity
function multihash(bytes32 node) public view returns (bytes);
```

## Test Cases

To implement the way to transfer from base58 to hex format and the reverse one, using the ‘multihashes’ library to deal with the problem.  
The library link : [https://www.npmjs.com/package/multihashes](https://www.npmjs.com/package/multihashes)  
To implement the method transfer from IPFS(Base58) to hex format :
  
```javascript
import multihash from &apos;multihashes&apos;

export const toHex = function(ipfsHash) {
  let buf = multihash.fromB58String(ipfsHash);
  return &apos;0x&apos; + multihash.toHexString(buf);
}
```
  
To implement the method transfer from hex format to IPFS(Base58) :
  
```javascript
import multihash from &apos;multihashes&apos;

export const toBase58 = function(contentHash) {
  let hex = contentHash.substring(2)
  let buf = multihash.fromHexString(hex);
  return multihash.toB58String(buf);
}
```

## Implementation
The use case can be implemented as browser extension. Users can easily download the extension, and easily get decentralized resources by just typing the ENS just like we normally type the DNS to browser the website. Solve the current pain for normal people can not easily visit the total decentralized website.

The workable implementation repository : [https://github.com/PortalNetwork/portal-network-browser-extension](https://github.com/PortalNetwork/portal-network-browser-extension)

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).


</description>
        <pubDate>Wed, 02 May 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1062</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1062</guid>
      </item>
    
      <item>
        <title>Status Codes</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-1066-ethereum-status-codes-esc/</comments>
        
        <description>## Simple Summary

Broadly applicable status codes for smart contracts.

## Abstract

This standard outlines a common set of status codes in a similar vein to HTTP statuses. This provides a shared set of signals to allow smart contracts to react to situations autonomously, expose localized error messages to users, and so on.

The current state of the art is to either `revert` on anything other than a clear success (ie: require human intervention), or return a low-context `true` or `false`. Status codes are similar-but-orthogonal to `revert`ing with a reason, but aimed at automation, debugging, and end-user feedback (including translation). _They are fully compatible with both `revert` and `revert`-with-reason._

As is the case with HTTP, having a standard set of known codes has many benefits for developers. They remove friction from needing to develop your own schemes for every contract, makes inter-contract automation easier, and makes it easier to broadly understand which of the finite states your request produced. Importantly, it makes it much easier to distinguish between expected errors states, truly exceptional conditions that require halting execution, normal state transitions, and various success cases.

## Motivation

### Semantic Density

HTTP status codes are widely used for this purpose. BEAM languages use atoms and tagged tuples to signify much the same information. Both provide a lot of information both to the programmer (debugging for instance), and to the program that needs to decide what to do next.

Status codes convey a much richer set of information [than Booleans](https://existentialtype.wordpress.com/2011/03/15/boolean-blindness/), and are able to be reacted to autonomously unlike arbitrary strings.

### User Experience (UX)

_End users get little to no feedback, and there is no translation layer._

Since ERC1066 status codes are finite and known in advance, we can leverage [ERC-1444](/EIPs/EIPS/eip-1444) to provide global, human-readable sets of status messages. These may also be translated into any language, differing levels of technical detail, added as `revert` messages, natspecs, and so on.

Status codes convey a much richer set of information than Booleans, and are able to be reacted to autonomously unlike arbitrary strings.

### Developer Experience (DX)

_Developers currently have very little context exposed by their smart contracts._

At time of writing, other than stepping through EVM execution and inspecting memory dumps directly, it is very difficult to understand what is happening during smart contract execution. By returning more context, developers can write well-decomposed tests and assert certain codes are returned as an expression of where the smart contract got to. This includes status codes as bare values, `event`s, and `revert`s.

Having a fixed set of codes also makes it possible to write common helper functions to react in common ways to certain signals. This can live off- or on-chain library, lowering the overhead in building smart contracts, and helping raise code quality with trusted shared components.

We also see a desire for this [in transactions](/EIPs/EIPS/eip-658), and there&apos;s no reason that these status codes couldn&apos;t be used by the EVM itself.

### Smart Contract Autonomy

_Smart contracts don’t know much about the result of a request beyond pass/fail; they can be smarter with more context._

Smart contracts are largely intended to be autonomous. While each contract may define a specific interface, having a common set of semantic codes can help developers write code that can react appropriately to various situations.

While clearly related, status codes are complementary to `revert`-with-reason. Status codes are not limited to rolling back the transaction, and may represent known error states without halting execution. They may also represent off-chain conditions, supply a string to revert, signal time delays, and more.

All of this enables contracts to share a common vocabulary of state transitions, results, and internal changes, without having to deeply understand custom status enums or the internal business logic of collaborator contracts.

## Specification

### Format

Codes are returned either on their own, or as the first value of a multiple return.

```solidity
// Status only

function isInt(uint num) public pure returns (byte status) {
    return hex&quot;01&quot;;
}

// Status and value

uint8 private counter;

function safeIncrement(uint8 interval) public returns (byte status, uint8 newCounter) {
    uint8 updated = counter + interval;

    if (updated &gt;= counter) {
        counter = updated;
        return (hex&quot;01&quot;, updated);
    } else {
        return (hex&quot;00&quot;, counter);
    }
}
```

### Code Table

Codes break nicely into a 16x16 matrix, represented as a 2-digit hex number. The high nibble represents the code&apos;s kind or &quot;category&quot;, and the low nibble contains the state or &quot;reason&quot;. We present them below as separate tables per range for explanatory and layout reasons.

**NB: Unspecified codes are _not_ free for arbitrary use, but rather open for further specification.**

#### `0x0*` Generic

General codes. These double as bare &quot;reasons&quot;, since `0x01 == 1`.

| Code   | Description                             |
|--------|-----------------------------------------|
| `0x00` | Failure                                 |
| `0x01` | Success                                 |
| `0x02` | Awaiting Others                         |
| `0x03` | Accepted                                |
| `0x04` | Lower Limit or Insufficient             |
| `0x05` | Receiver Action Requested               |
| `0x06` | Upper Limit                             |
| `0x07` | [reserved]                              |
| `0x08` | Duplicate, Unnecessary, or Inapplicable |
| `0x09` | [reserved]                              |
| `0x0A` | [reserved]                              |
| `0x0B` | [reserved]                              |
| `0x0C` | [reserved]                              |
| `0x0D` | [reserved]                              |
| `0x0E` | [reserved]                              |
| `0x0F` | Informational or Metadata               |

#### `0x1*` Permission &amp; Control

Also used for common state machine actions (ex. &quot;stoplight&quot; actions).

| Code   | Description                                       |
|--------|---------------------------------------------------|
| `0x10` | Disallowed or Stop                                |
| `0x11` | Allowed or Go                                     |
| `0x12` | Awaiting Other&apos;s Permission                       |
| `0x13` | Permission Requested                              |
| `0x14` | Too Open / Insecure                               |
| `0x15` | Needs Your Permission or Request for Continuation |
| `0x16` | Revoked or Banned                                 |
| `0x17` | [reserved]                                        |
| `0x18` | Not Applicable to Current State                 |
| `0x19` | [reserved]                                        |
| `0x1A` | [reserved]                                        |
| `0x1B` | [reserved]                                        |
| `0x1C` | [reserved]                                        |
| `0x1D` | [reserved]                                        |
| `0x1E` | [reserved]                                        |
| `0x1F` | Permission Details or Control Conditions          |

#### `0x2*` Find, Inequalities &amp; Range

This range is broadly intended for finding and matching. Data lookups and order matching are two common use cases.

| Code   | Description                         |
|--------|-------------------------------------|
| `0x20` | Not Found, Unequal, or Out of Range |
| `0x21` | Found, Equal or In Range            |
| `0x22` | Awaiting Match                      |
| `0x23` | Match Request Sent                  |
| `0x24` | Below Range or Underflow            |
| `0x25` | Request for Match                   |
| `0x26` | Above Range or Overflow             |
| `0x27` | [reserved]                          |
| `0x28` | Duplicate, Conflict, or Collision   |
| `0x29` | [reserved]                          |
| `0x2A` | [reserved]                          |
| `0x2B` | [reserved]                          |
| `0x2C` | [reserved]                          |
| `0x2D` | [reserved]                          |
| `0x2E` | [reserved]                          |
| `0x2F` | Matching Meta or Info               |

#### `0x3*` Negotiation &amp; Governance

Negotiation, and very broadly the flow of such transactions. Note that &quot;other party&quot; may be more than one actor (not necessarily the sender).

| Code   | Description                             |
|--------|-----------------------------------------|
| `0x30` | Sender Disagrees or Nay                 |
| `0x31` | Sender Agrees or Yea                    |
| `0x32` | Awaiting Ratification                   |
| `0x33` | Offer Sent or Voted                     |
| `0x34` | Quorum Not Reached                      |
| `0x35` | Receiver&apos;s Ratification Requested       |
| `0x36` | Offer or Vote Limit Reached             |
| `0x37` | [reserved]                              |
| `0x38` | Already Voted                           |
| `0x39` | [reserved]                              |
| `0x3A` | [reserved]                              |
| `0x3B` | [reserved]                              |
| `0x3C` | [reserved]                              |
| `0x3D` | [reserved]                              |
| `0x3E` | [reserved]                              |
| `0x3F` | Negotiation Rules or Participation Info |

#### `0x4*` Availability &amp; Time

Service or action availability.

| Code   | Description                                          |
|--------|------------------------------------------------------|
| `0x40` | Unavailable                                          |
| `0x41` | Available                                            |
| `0x42` | Paused                                               |
| `0x43` | Queued                                               |
| `0x44` | Not Available Yet                                    |
| `0x45` | Awaiting Your Availability                           |
| `0x46` | Expired                                              |
| `0x47` | [reserved]                                           |
| `0x48` | Already Done                                         |
| `0x49` | [reserved]                                           |
| `0x4A` | [reserved]                                           |
| `0x4B` | [reserved]                                           |
| `0x4C` | [reserved]                                           |
| `0x4D` | [reserved]                                           |
| `0x4E` | [reserved]                                           |
| `0x4F` | Availability Rules or Info (ex. time since or until) |

#### `0x5*` Tokens, Funds &amp; Finance

Special token and financial concepts. Many related concepts are included in other ranges.

| Code   | Description                     |
|--------|---------------------------------|
| `0x50` | Transfer Failed                 |
| `0x51` | Transfer Successful             |
| `0x52` | Awaiting Payment From Others    |
| `0x53` | Hold or Escrow                  |
| `0x54` | Insufficient Funds              |
| `0x55` | Funds Requested                 |
| `0x56` | Transfer Volume Exceeded        |
| `0x57` | [reserved]                      |
| `0x58` | Funds Not Required              |
| `0x59` | [reserved]                      |
| `0x5A` | [reserved]                      |
| `0x5B` | [reserved]                      |
| `0x5C` | [reserved]                      |
| `0x5D` | [reserved]                      |
| `0x5E` | [reserved]                      |
| `0x5F` | Token or Financial Information |

#### `0x6*` TBD

Currently unspecified. (Full range reserved)

#### `0x7*` TBD

Currently unspecified. (Full range reserved)

#### `0x8*` TBD

Currently unspecified. (Full range reserved)

#### `0x9*` TBD

Currently unspecified. (Full range reserved)

#### `0xA*` Application-Specific Codes

Contracts may have special states that they need to signal. This proposal only outlines the broadest meanings, but implementers may have very specific meanings for each, as long as they are coherent with the broader definition.

| Code   | Description                            |
|--------|----------------------------------------|
| `0xA0` | App-Specific Failure                   |
| `0xA1` | App-Specific Success                   |
| `0xA2` | App-Specific Awaiting Others           |
| `0xA3` | App-Specific Acceptance                |
| `0xA4` | App-Specific Below Condition           |
| `0xA5` | App-Specific Receiver Action Requested |
| `0xA6` | App-Specific Expiry or Limit           |
| `0xA7` | [reserved]                             |
| `0xA8` | App-Specific Inapplicable Condition    |
| `0xA9` | [reserved]                             |
| `0xAA` | [reserved]                             |
| `0xAB` | [reserved]                             |
| `0xAC` | [reserved]                             |
| `0xAD` | [reserved]                             |
| `0xAE` | [reserved]                             |
| `0xAF` | App-Specific Meta or Info              |

#### `0xB*` TBD

Currently unspecified. (Full range reserved)

#### `0xC*` TBD

Currently unspecified. (Full range reserved)

#### `0xD*` TBD

Currently unspecified. (Full range reserved)

#### `0xE*` Encryption, Identity &amp; Proofs

Actions around signatures, cryptography, signing, and application-level authentication.

The meta code `0xEF` is often used to signal a payload describing the algorithm or process used.

| Code   | Description                         |
|--------|-------------------------------------|
| `0xE0` | Decrypt Failure                     |
| `0xE1` | Decrypt Success                     |
| `0xE2` | Awaiting Other Signatures or Keys   |
| `0xE3` | Signed                              |
| `0xE4` | Unsigned or Untrusted               |
| `0xE5` | Signature Required                  |
| `0xE6` | Known to be Compromised             |
| `0xE7` | [reserved]                          |
| `0xE8` | Already Signed or Not Encrypted     |
| `0xE9` | [reserved]                          |
| `0xEA` | [reserved]                          |
| `0xEB` | [reserved]                          |
| `0xEC` | [reserved]                          |
| `0xED` | [reserved]                          |
| `0xEE` | [reserved]                          |
| `0xEF` | Cryptography, ID, or Proof Metadata |

#### `0xF*` Off-Chain

For off-chain actions. Much like th `0x0*: Generic` range, `0xF*` is very general, and does little to modify the reason.

Among other things, the meta code `0xFF` may be used to describe what the off-chain process is.

| Code   | Description                       |
|--------|-----------------------------------|
| `0xF0` | Off-Chain Failure                 |
| `0xF1` | Off-Chain Success                 |
| `0xF2` | Awaiting Off-Chain Process        |
| `0xF3` | Off-Chain Process Started         |
| `0xF4` | Off-Chain Service Unreachable     |
| `0xF5` | Off-Chain Action Required         |
| `0xF6` | Off-Chain Expiry or Limit Reached |
| `0xF7` | [reserved]                        |
| `0xF8` | Duplicate Off-Chain Request       |
| `0xF9` | [reserved]                        |
| `0xFA` | [reserved]                        |
| `0xFB` | [reserved]                        |
| `0xFC` | [reserved]                        |
| `0xFD` | [reserved]                        |
| `0xFE` | [reserved]                        |
| `0xFF` | Off-Chain Info or Meta            |

### As a Grid

|        | `0x0*` General                                 | `0x1*` Permission &amp; Control                              | `0x2*` Find, Inequalities &amp; Range          | `0x3*` Negotiation &amp; Governance                | `0x4*` Availability &amp; Time                                  | `0x5*` Tokens, Funds &amp; Finance         | `0x6*` TBD        | `0x7*` TBD        | `0x8*` TBD        | `0x9*` TBD        | `0xA*` Application-Specific Codes             | `0xB*` TBD        | `0xC*` TBD        | `0xD*` TBD        | `0xE*` Encryption, Identity &amp; Proofs       | `0xF*` Off-Chain                         |
|--------|------------------------------------------------|----------------------------------------------------------|--------------------------------------------|------------------------------------------------|-------------------------------------------------------------|----------------------------------------|-------------------|-------------------|-------------------|-------------------|-----------------------------------------------|-------------------|-------------------|-------------------|--------------------------------------------|------------------------------------------|
| `0x*0` | `0x00` Failure                                 | `0x10` Disallowed or Stop                                | `0x20` Not Found, Unequal, or Out of Range | `0x30` Sender Disagrees or Nay                 | `0x40` Unavailable                                          | `0x50` Transfer Failed                 | `0x60` [reserved] | `0x70` [reserved] | `0x80` [reserved] | `0x90` [reserved] | `0xA0` App-Specific Failure                   | `0xB0` [reserved] | `0xC0` [reserved] | `0xD0` [reserved] | `0xE0` Decrypt Failure                     | `0xF0` Off-Chain Failure                 |
| `0x*1` | `0x01` Success                                 | `0x11` Allowed or Go                                     | `0x21` Found, Equal or In Range            | `0x31` Sender Agrees or Yea                    | `0x41` Available                                            | `0x51` Transfer Successful             | `0x61` [reserved] | `0x71` [reserved] | `0x81` [reserved] | `0x91` [reserved] | `0xA1` App-Specific Success                   | `0xB1` [reserved] | `0xC1` [reserved] | `0xD1` [reserved] | `0xE1` Decrypt Success                     | `0xF1` Off-Chain Success                 |
| `0x*2` | `0x02` Awaiting Others                         | `0x12` Awaiting Other&apos;s Permission                       | `0x22` Awaiting Match                      | `0x32` Awaiting Ratification                   | `0x42` Paused                                               | `0x52` Awaiting Payment From Others    | `0x62` [reserved] | `0x72` [reserved] | `0x82` [reserved] | `0x92` [reserved] | `0xA2` App-Specific Awaiting Others           | `0xB2` [reserved] | `0xC2` [reserved] | `0xD2` [reserved] | `0xE2` Awaiting Other Signatures or Keys   | `0xF2` Awaiting Off-Chain Process        |
| `0x*3` | `0x03` Accepted                                | `0x13` Permission Requested                              | `0x23` Match Request Sent                  | `0x33` Offer Sent or Voted                     | `0x43` Queued                                               | `0x53` Hold or Escrow                  | `0x63` [reserved] | `0x73` [reserved] | `0x83` [reserved] | `0x93` [reserved] | `0xA3` App-Specific Acceptance                | `0xB3` [reserved] | `0xC3` [reserved] | `0xD3` [reserved] | `0xE3` Signed                              | `0xF3` Off-Chain Process Started         |
| `0x*4` | `0x04` Lower Limit or Insufficient             | `0x14` Too Open / Insecure                               | `0x24` Below Range or Underflow            | `0x34` Quorum Not Reached                      | `0x44` Not Available Yet                                    | `0x54` Insufficient Funds              | `0x64` [reserved] | `0x74` [reserved] | `0x84` [reserved] | `0x94` [reserved] | `0xA4` App-Specific Below Condition           | `0xB4` [reserved] | `0xC4` [reserved] | `0xD4` [reserved] | `0xE4` Unsigned or Untrusted               | `0xF4` Off-Chain Service Unreachable     |
| `0x*5` | `0x05` Receiver Action Required                | `0x15` Needs Your Permission or Request for Continuation | `0x25` Request for Match                   | `0x35` Receiver&apos;s Ratification Requested       | `0x45` Awaiting Your Availability                           | `0x55` Funds Requested                 | `0x65` [reserved] | `0x75` [reserved] | `0x85` [reserved] | `0x95` [reserved] | `0xA5` App-Specific Receiver Action Requested | `0xB5` [reserved] | `0xC5` [reserved] | `0xD5` [reserved] | `0xE5` Signature Required                  | `0xF5` Off-Chain Action Required         |
| `0x*6` | `0x06` Upper Limit                             | `0x16` Revoked or Banned                                 | `0x26` Above Range or Overflow             | `0x36` Offer or Vote Limit Reached             | `0x46` Expired                                              | `0x56` Transfer Volume Exceeded        | `0x66` [reserved] | `0x76` [reserved] | `0x86` [reserved] | `0x96` [reserved] | `0xA6` App-Specific Expiry or Limit           | `0xB6` [reserved] | `0xC6` [reserved] | `0xD6` [reserved] | `0xE6` Known to be Compromised             | `0xF6` Off-Chain Expiry or Limit Reached |
| `0x*7` | `0x07` [reserved]                              | `0x17` [reserved]                                        | `0x27` [reserved]                          | `0x37` [reserved]                              | `0x47` [reserved]                                           | `0x57` [reserved]                      | `0x67` [reserved] | `0x77` [reserved] | `0x87` [reserved] | `0x97` [reserved] | `0xA7` [reserved]                             | `0xB7` [reserved] | `0xC7` [reserved] | `0xD7` [reserved] | `0xE7` [reserved]                          | `0xF7` [reserved]                        |
| `0x*8` | `0x08` Duplicate, Unnecessary, or Inapplicable | `0x18` Not Applicable to Current State                 | `0x28` Duplicate, Conflict, or Collision   | `0x38` Already Voted                           | `0x48` Already Done                                         | `0x58` Funds Not Required              | `0x68` [reserved] | `0x78` [reserved] | `0x88` [reserved] | `0x98` [reserved] | `0xA8` App-Specific Inapplicable Condition    | `0xB8` [reserved] | `0xC8` [reserved] | `0xD8` [reserved] | `0xE8` Already Signed or Not Encrypted     | `0xF8` Duplicate Off-Chain Request       |
| `0x*9` | `0x09` [reserved]                              | `0x19` [reserved]                                        | `0x29` [reserved]                          | `0x39` [reserved]                              | `0x49` [reserved]                                           | `0x59` [reserved]                      | `0x69` [reserved] | `0x79` [reserved] | `0x89` [reserved] | `0x99` [reserved] | `0xA9` [reserved]                             | `0xB9` [reserved] | `0xC9` [reserved] | `0xD9` [reserved] | `0xE9` [reserved]                          | `0xF9` [reserved]                        |
| `0x*A` | `0x0A` [reserved]                              | `0x1A` [reserved]                                        | `0x2A` [reserved]                          | `0x3A` [reserved]                              | `0x4A` [reserved]                                           | `0x5A` [reserved]                      | `0x6A` [reserved] | `0x7A` [reserved] | `0x8A` [reserved] | `0x9A` [reserved] | `0xAA` [reserved]                             | `0xBA` [reserved] | `0xCA` [reserved] | `0xDA` [reserved] | `0xEA` [reserved]                          | `0xFA` [reserved]                        |
| `0x*B` | `0x0B` [reserved]                              | `0x1B` [reserved]                                        | `0x2B` [reserved]                          | `0x3B` [reserved]                              | `0x4B` [reserved]                                           | `0x5B` [reserved]                      | `0x6B` [reserved] | `0x7B` [reserved] | `0x8B` [reserved] | `0x9B` [reserved] | `0xAB` [reserved]                             | `0xBB` [reserved] | `0xCB` [reserved] | `0xDB` [reserved] | `0xEB` [reserved]                          | `0xFB` [reserved]                        |
| `0x*C` | `0x0C` [reserved]                              | `0x1C` [reserved]                                        | `0x2C` [reserved]                          | `0x3C` [reserved]                              | `0x4C` [reserved]                                           | `0x5C` [reserved]                      | `0x6C` [reserved] | `0x7C` [reserved] | `0x8C` [reserved] | `0x9C` [reserved] | `0xAC` [reserved]                             | `0xBC` [reserved] | `0xCC` [reserved] | `0xDC` [reserved] | `0xEC` [reserved]                          | `0xFC` [reserved]                        |
| `0x*D` | `0x0D` [reserved]                              | `0x1D` [reserved]                                        | `0x2D` [reserved]                          | `0x3D` [reserved]                              | `0x4D` [reserved]                                           | `0x5D` [reserved]                      | `0x6D` [reserved] | `0x7D` [reserved] | `0x8D` [reserved] | `0x9D` [reserved] | `0xAD` [reserved]                             | `0xBD` [reserved] | `0xCD` [reserved] | `0xDD` [reserved] | `0xED` [reserved]                          | `0xFD` [reserved]                        |
| `0x*E` | `0x0E` [reserved]                              | `0x1E` [reserved]                                        | `0x2E` [reserved]                          | `0x3E` [reserved]                              | `0x4E` [reserved]                                           | `0x5E` [reserved]                      | `0x6E` [reserved] | `0x7E` [reserved] | `0x8E` [reserved] | `0x9E` [reserved] | `0xAE` [reserved]                             | `0xBE` [reserved] | `0xCE` [reserved] | `0xDE` [reserved] | `0xEE` [reserved]                          | `0xFE` [reserved]                        |
| `0x*F` | `0x0F` Informational or Metadata               | `0x1F` Permission Details or Control Conditions          | `0x2F` Matching Meta or Info               | `0x3F` Negotiation Rules or Participation Info | `0x4F` Availability Rules or Info (ex. time since or until) | `0x5F` Token or Financial Information  | `0x6F` [reserved] | `0x7F` [reserved] | `0x8F` [reserved] | `0x9F` [reserved] | `0xAF` App-Specific Meta or Info              | `0xBF` [reserved] | `0xCF` [reserved] | `0xDF` [reserved] | `0xEF` Cryptography, ID, or Proof Metadata | `0xFF` Off-Chain Info or Meta            |

### Example Function Change

```solidity
uint256 private startTime;
mapping(address =&gt; uint) private counters;

// Before
function increase() public returns (bool _available) {
    if (now &lt; startTime &amp;&amp; counters[msg.sender] == 0) {
        return false;
    };

    counters[msg.sender] += 1;
    return true;
}

// After
function increase() public returns (byte _status) {
    if (now &lt; start) { return hex&quot;44&quot;; } // Not yet available
    if (counters[msg.sender] == 0) { return hex&quot;10&quot;; } // Not authorized

    counters[msg.sender] += 1;
    return hex&quot;01&quot;; // Success
}
```

### Example Sequence Diagrams

```
0x03 = Waiting
0x31 = Other Party (ie: not you) Agreed
0x41 = Available
0x44 = Not Yet Available


                          Exchange


AwesomeCoin                 DEX                     TraderBot
     +                       +                          +
     |                       |       buy(AwesomeCoin)   |
     |                       | &lt;------------------------+
     |         buy()         |                          |
     | &lt;---------------------+                          |
     |                       |                          |
     |     Status [0x44]     |                          |
     +---------------------&gt; |       Status [0x44]      |
     |                       +------------------------&gt; |
     |                       |                          |
     |                       |        isDoneYet()       |
     |                       | &lt;------------------------+
     |                       |                          |
     |                       |       Status [0x44]      |
     |                       +------------------------&gt; |
     |                       |                          |
     |                       |                          |
     |     Status [0x41]     |                          |
     +---------------------&gt; |                          |
     |                       |                          |
     |       buy()           |                          |
     | &lt;---------------------+                          |
     |                       |                          |
     |                       |                          |
     |     Status [0x31]     |                          |
     +---------------------&gt; |      Status [0x31]       |
     |                       +------------------------&gt; |
     |                       |                          |
     |                       |                          |
     |                       |                          |
     |                       |                          |
     +                       +                          +
```



```
0x01 = Generic Success
0x10 = Disallowed
0x11 = Allowed

                                              Token Validation


           Buyer                  RegulatedToken           TokenValidator               IDChecker          SpendLimiter
             +                          +                         +                         +                   +
             |        buy()             |                         |                         |                   |
             +------------------------&gt; |          check()        |                         |                   |
             |                          +-----------------------&gt; |          check()        |                   |
             |                          |                         +-----------------------&gt; |                   |
             |                          |                         |                         |                   |
             |                          |                         |         Status [0x10]   |                   |
             |                          |       Status [0x10]     | &lt;-----------------------+                   |
             |        revert()          | &lt;-----------------------+                         |                   |
             | &lt;------------------------+                         |                         |                   |
             |                          |                         |                         |                   |
+---------------------------+           |                         |                         |                   |
|                           |           |                         |                         |                   |
| Updates ID with provider  |           |                         |                         |                   |
|                           |           |                         |                         |                   |
+---------------------------+           |                         |                         |                   |
             |                          |                         |                         |                   |
             |         buy()            |                         |                         |                   |
             +------------------------&gt; |        check()          |                         |                   |
             |                          +-----------------------&gt; |         check()         |                   |
             |                          |                         +-----------------------&gt; |                   |
             |                          |                         |                         |                   |
             |                          |                         |       Status [0x11]     |                   |
             |                          |                         | &lt;-----------------------+                   |
             |                          |                         |                         |                   |
             |                          |                         |                         |   check()         |
             |                          |                         +-------------------------------------------&gt; |
             |                          |                         |                         |                   |
             |                          |                         |                         |  Status [0x11]    |
             |                          |       Status [0x11]     | &lt;-------------------------------------------+
             |        Status [0x01]     | &lt;-----------------------+                         |                   |
             | &lt;------------------------+                         |                         |                   |
             |                          |                         |                         |                   |
             |                          |                         |                         |                   |
             |                          |                         |                         |                   |
             +                          +                         +                         +                   +
```

## Rationale

### Encoding

Status codes are encoded as a `byte`. Hex values break nicely into high and low nibbles: `category` and `reason`. For instance, `0x01` stands for general success (ie: `true`) and `0x00` for general failure (ie: `false`).

As a general approach, all even numbers are blocking conditions (where the receiver does not have control), and odd numbers are nonblocking (the receiver is free to continue as they wish). This aligns both a simple bit check with the common encoding of Booleans.

`bytes1` is very lightweight, portable, easily interoperable with `uint8`, cast from `enum`s, and so on.

#### Alternatives

Alternate schemes include `bytes32` and `uint8`. While these work reasonably well, they have drawbacks.

`uint8` feels even more similar to HTTP status codes, and enums don&apos;t require as much casting. However does not break as evenly as a square table (256 doesn&apos;t look as nice in base 10).

Packing multiple codes into a single `bytes32` is nice in theory, but poses additional challenges. Unused space may be interpreted as `0x00 Failure`, you can only efficiently pack four codes at once, and there is a challenge in ensuring that code combinations are sensible. Forcing four codes into a packed representation encourages multiple status codes to be returned, which is often more information than strictly necessarily. This can lead to paradoxical results (ex `0x00` and `0x01` together), or greater resources allocated to interpreting 256&lt;sup&gt;4&lt;/sup&gt; (4.3 billion) permutations.

### Multiple Returns

While there may be cases where packing a byte array of status codes may make sense, the simplest, most forwards-compatible method of transmission is as the first value of a multiple return.

Familiarity is also a motivating factor. A consistent position and encoding together follow the principle of least surprise. It is both viewable as a &quot;header&quot; in the HTTP analogy, or like the &quot;tag&quot; in BEAM tagged tuples.

### Human Readable

Developers should not be required to memorize 256 codes. However, they break nicely into a table. Cognitive load is lowered by organizing the table into categories and reasons. `0x10` and `0x11` belong to the same category, and `0x04` shares a reason with `0x24`

While this repository includes helper enums, we have found working directly in the hex values to be quite natural. Status code `0x10` is just as comfortable as HTTP 401, for example.

#### Localizations

One commonly requested application of this spec is human-readable translations of codes. This has been moved to its own proposal: [ERC-1444](/EIPs/EIPS/eip-1444), primarily due to a desire to keep both specs focused.

### Extensibility

The `0xA` category is reserved for application-specific statuses. In the case that 256 codes become insufficient, `bytes1` may be embedded in larger byte arrays.

### EVM Codes

The EVM also returns a status code in transactions; specifically `0x00` and `0x01`. This proposal both matches the meanings of those two codes, and could later be used at the EVM level.

### Empty Space

Much like how HTTP status codes have large unused ranges, there are totally empty sections in this proposal. The intent is to not impose a complete set of codes up front, and to allow users to suggest uses for these spaces as time progresses.

### Beyond Errors

This spec is intended to be much more than a set of common errors. One design goal is to enable easier contract-to-contract communication, protocols built on top of status codes, and flows that cross off-chain. Many of these cases include either expected kinds of exception state (as opposed to true errors), neutral states, time logic, and various successes.

Just like how HTTP 200 has a different meaning from HTTP 201, ERC-1066 status codes can relay information between contract beyond simply pass or fail. They can be thought of as the edges in a graph that has smart contracts as nodes.

### Fully `revert`able

_This spec is fully compatible with `revert`-with-reason and does not intend to supplant it in any way._ Both by reverting with a common code, the developer can determine what went wrong from a set of known error states.

Further, by leveraging ERC-1066 and a translation table (such as in ERC-1444) in conjunction, developers and end users alike can receive fully automated human-readable error messages in the language and phrasing of their choice.

### Nibble Order

Nibble order makes no difference to the machine, and is purely mnemonic. This design was originally in opposite order, but changed it for a few convenience factors. Since it&apos;s a different scheme from HTTP, it may feel strange initially, but becomes very natural after a couple hours of use.

#### Short Forms

Generic is `0x0*`, general codes are consistent with their integer representations

```solidity
hex&quot;1&quot; == hex&quot;01&quot; == 1 // with casting
```

#### Contract Categories

Many applications will always be part of the same category. For instance, validation will generally be in the `0x10` range.

```solidity
contract Whitelist {
    mapping(address =&gt; bool) private whitelist;
    uint256 private deadline;
    byte constant private prefix = hex&quot;10&quot;;

    check(address _, address _user) returns (byte _status) {
        if (now &gt;= deadline)  { return prefix | 5; }
        if (whitelist[_user]) { return prefix | 1; }
        return prefix;
    }
}
```

#### Helpers

This above also means that working with app-specific enums is slightly easier, and also saves gas (fewer operations required).

```solidity
enum Sleep {
    Awake,
    Asleep,
    BedOccupied,
    WindingDown
}

// From the helper library

function appCode(Sleep _state) returns (byte code) {
    return byte(160 + _state); // 160 = 0xA0
}

// Versus

function appCode(Sleep _state) returns (byte code) {
    return byte((16 * _state) + 10); // 10 = 0xA
}
```

## Implementation

Reference cases and helper libraries (Solidity and JS) can be found at:
* [Source Code](https://github.com/fission-suite/fission-codes/)
* [Package on npm](https://www.npmjs.com/package/fission-codes/)

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 05 May 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1066</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1066</guid>
      </item>
    
      <item>
        <title>Gas relay for contract calls</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc1077-and-1078-the-magic-of-executable-signed-messages-to-login-and-do-actions/351</comments>
        
        <description>## Simple Summary

A standard interface for gas abstraction in top of smart contracts. 

Allows users to offer [EIP-20] token for paying the gas used in a call. 

## Abstract

A main barrier for the adoption of DApps is the requirement of multiple tokens for executing in chain actions. Allowing users to sign messages to show intent of execution, but allowing a third party relayer to execute them can circumvent this problem, while ETH will always be required for ethereum transactions, it&apos;s possible for smart contract to take [EIP-191] signatures and forward a payment incentive to an untrusted party with ETH for executing the transaction. 

## Motivation

Standardizing a common format for them, as well as a way in which the user allows the transaction to be paid in tokens, gives app developers a lot of flexibility and can become the main way in which app users interact with the Blockchain.


## Specification 

### Methods

#### executeGasRelay

Executes `_execData` with current `lastNonce()` and pays `msg.sender` the gas used in specified `_gasToken`.

```solidity
function executeGasRelay(bytes calldata _execData, uint256 _gasPrice, uint256 _gasLimit, address _gasToken, address _gasRelayer, bytes calldata _signature) external;	
```

### executeGasRelayMsg

Returns the `executeGasRelay` message used for signing messages..

```solidity
function executeGasRelayMsg(uint256 _nonce, bytes memory _execData, uint256 _gasPrice, uint256 _gasLimit, address _gasToken, address _gasRelayer) public pure returns (bytes memory);
```

#### executeGasRelayERC191Msg

Returns the [EIP-191] of `executeGasRelayMsg` used for signing messages and for verifying the execution.

```solidity
function executeGasRelayERC191Msg(uint256 _nonce, bytes memory _execData, uint256 _gasPrice, uint256 _gasLimit, address _gasToken, address _gasRelayer) public view returns (bytes memory);
```

#### lastNonce

Returns the current nonce for the gas relayed messages.

```solidity
function lastNonce() public returns (uint nonce);
```

### Signed Message

The signed message require the following fields:

* Nonce: A nonce *or* a timestamp;
* Execute Data: the bytecode to be executed by the account contract;
* Gas Price: The gas price (paid in the selected token);
* Gas Limit: The gas reserved to the relayed execution;
* Gas Token: A token in which the gas will be paid (leave 0 for ether);
* Gas Relayer: the beneficiary of gas refund for this call (leave 0 for `block.coinbase`) .

#### Signing the message

The message **MUST** be signed as [EIP-191] standard, and the called contract **MUST** also implement [EIP-1271] which must validate the signed messages.

Messages **MUST** be signed by the owner of the account contract executing. If the owner is a contract, it must implement [EIP-1271] interface and forward validation to it. 

In order to be compliant, the transaction **MUST** request to sign a &quot;messageHash&quot; that is a concatenation of multiple fields.

The fields **MUST** be constructed as this method:

The first and second fields are to make it [EIP-191] compliant. Starting a transaction with `byte(0x19)` ensure the signed data from being a [valid ethereum transaction](https://github.com/ethereum/wiki/wiki/RLP). The second argument is a version control byte. The third being the validator address (the account contract address) according to version 0 of [EIP-191]. The remaining arguments being the application specific data for the gas relay: chainID as per [EIP-1344], execution nonce, execution data, agreed gas Price, gas limit of gas relayed call, gas token to pay back and gas relayer authorized to receive the reward.

The [EIP-191] message must be constructed as follows:
```solidity
keccak256(
	abi.encodePacked(
        byte(0x19), //ERC-191 - the initial 0x19 byte
        byte(0x0), //ERC-191 - the version byte
        address(this), //ERC-191 - version data (validator address)
        chainID,
        bytes4(
            keccak256(&quot;executeGasRelay(uint256,bytes,uint256,uint256,address,address)&quot;)
        ),
        _nonce, 
        _execData,
        _gasPrice,
        _gasLimit,
        _gasToken,
        _gasRelayer
    )
)
```

## Rationale

User pain points:

* users don&apos;t want to think about ether
* users don&apos;t want to think about backing up private keys or seed phrases
* users want to be able to pay for transactions using what they already have on the system, be apple pay, xbox points or even a credit card
* Users don’t want to sign a new transaction at every move
* Users don’t want to download apps/extensions (at least on the desktop) to connect to their apps

App developer pain points:
* Many apps use their own token and would prefer to use those as the main accounting
* Apps want to be able to have apps in multiple platforms without having to share private keys between devices or have to spend transaction costs moving funds between them
* Token developers want to be able for their users to be able to move funds and pay fees in the token
* While the system provides fees and incentives for miners, there are no inherent business model for wallet developers (or other apps that initiate many transactions)

Using signed messages, specially combined with an account contract that holds funds, and multiple disposable ether-less keys that can sign on its behalf, solves many of these pain points.

### Multiple signatures

More than one signed transaction with the same parameter can be executed by this function at the same time, by passing all signatures in the `messageSignatures` field. That field will split the signature in multiple 72 character individual signatures and evaluate each one. This is used for cases in which one action might require the approval of multiple parties, in a single transaction.

If multiple signatures are required, then all signatures should then be *ordered by account* and the account contract should implement signatures checks locally (`JUMP`) on [EIP-1271] interface which might forward (`STATIC_CALL`) the [EIP-1271] signature check to owner contract.

### Keep track of nonces:

Note that `executeGasRelay` function does not take a `_nonce` as parameter. The contract knows what is the current nonce, and can only execute the transactions in order, therefore there is no reason

Nonces work similarly to normal ethereum transactions: a transaction can only be executed if it matches the last nonce + 1, and once a transaction has occurred, the `lastNonce` will be updated to the current one. This prevents transactions to be executed out of order or more than once.

Contracts may accept transactions without nonce (nonce = 0). The contract then must keep the full hash of the transaction to prevent it from being replayed. This would allows contracts to have more flexibilities as you can sign a transaction that can be executed out of order or not at all, but it uses more memory for each transaction. It can be used, for instance, for transactions that the user wants to schedule in the future but cannot know its future nonce, or transactions that are made for state channel contracts that are not guaranteed to be executed or are only executed when there&apos;s some dispute.

### Execute transaction

After signature validation, the evaluation of `_execBytes` is up to the account contract implementation, it&apos;s role of the wallet to properly use the account contract and it&apos;s gas relay method. 
A common pattern is to expose an interface which can be only called by the contract itself. The `_execBytes` could entirely forward the call in this way, as example: `address(this).call.gas(_gasLimit)(_execData);`
Where `_execData` could call any method of the contract itself, for example:

- `call(address to, uint256 value, bytes data)`:  allow any type of ethereum call be performed; 
- `create(uint256 value, bytes deployData)`: allows create contract 
- `create2(uint256 value, bytes32 salt, bytes deployData)`: allows create contract with deterministic address 
- `approveAndCall(address token, address to, uint256 value, bytes data)`: allows safe approve and call of an ERC20 token.
- `delegatecall(address codeBase, bytes data)`: allows executing code stored on other contract
- `changeOwner(address newOwner)`: Some account contracts might allow change of owner
- `foo(bytes bar)`: Some account contracts might have custom methods of any format.

The standardization of account contracts is not scope of this ERC, and is presented here only for illustration on possible implementations. 
Using a self call to evaluate `_execBytes` is not mandatory, depending on the account contract logic, the evaluation could be done locally. 

### Gas accounting and refund

The implementing contract must keep track of the gas spent. One way to do it is to first call `gasLeft()` at the beginning of the function and then after executing the desired action and compare the difference.

The contract then will make a token transfer (or ether, if `tokenAddress` is nil) in the value of `gasSpent * gasPrice` to the `_gasRelayer`, that is the account that deployed the message.

If `_gasRelayer` is zero, then the funds **MUST** go to `block.coinbase`.

If there are not enough funds, or if the total surpasses `gasLimit` then the transaction **MUST** revert.

If the executed transaction fails internally, nonces should still be updated and gas needs to be paid.

Contracts are not obligated to support ether or any other token they don’t want and can be implemented to only accept refunds in a few tokens of their choice.

### Usage examples

This scheme opens up a great deal of possibilities on interaction as well as different experiments on business models:

* Apps can create individual identities contract for their users which holds the actual funds and then create a different private key for each device they log into. Other apps can use the same identity and just ask to add permissioned public keys to manage the device, so that if one individual key is lost, no ether is lost.
* An app can create its own token and only charge their users in its internal currency for any ethereum transaction. The currency units can be rounded so it looks more similar to actual amount of transactions: a standard transaction always costs 1 token, a very complex transaction costs exactly 2, etc. Since the app is the issuer of the transactions, they can do their own Sybil verifications and give a free amount of currency units to new users to get them started.
* A game company creates games with a traditional monthly subscription, either by credit card or platform-specific microtransactions. Private keys never leave the device and keep no ether and only the public accounts are sent to the company. The game then signs transactions on the device with gas price 0, sends them to the game company which checks who is an active subscriber and batches all transactions and pays the ether themselves. If the company goes bankrupt, the gamers themselves can set up similar subscription systems or just increase the gas price. End result is a **ethereum based game in which gamers can play by spending apple, google or xbox credits**.
* A standard token is created that doesn’t require its users to have ether, and instead allows tokens to be transferred by paying in tokens. A wallet is created that signs messages and send them via whisper to the network, where other nodes can compete to download the available transactions, check the current gas price, and select those who are paying enough tokens to cover the cost. **The result is a token that the end users never need to keep any ether and can pay fees in the token itself.**
* A DAO is created with a list of accounts of their employees. Employees never need to own ether, instead they sign messages, send them to whisper to a decentralized list of relayers which then deploy the transactions. The DAO contract then checks if the transaction is valid and sends ether to the deployers. Employees have an incentive not to use too many of the companies resources because they’re identifiable.  The result is that the users of the DAO don&apos;t need to keep ether, and **the contract ends up paying for it&apos;s own gas usage**.

## Backwards Compatibility

There is no issues with backwards compatibility, however for future upgrades, as `_execData` contains arbitrary data evaluated by the account contract, it&apos;s up to the contract to handle properly this data and therefore contracts can gas relay any behavior with the current interface.

## Test Cases

TBD

## Implementation

One initial implementation of such a contract can be found at [Status.im account-contracts repository](https://github.com/status-im/account-contracts/blob/develop/contracts/account/AccountGasAbstract.sol)

Other version is implemented as Gnosis Safe variant in: https://github.com/status-im/safe-contracts

### Similar implementations

The idea of using signed messages as executable intent has been around for a while and many other projects are taking similar approaches, which makes it a great candidate for a standard that guarantees interoperability:

* [EIP-877](https://github.com/ethereum/EIPs/pull/877) An attempt of doing the same but with a change in the protocol
* [Status](https://github.com/status-im/ideas/issues/73)
* [Aragon](https://github.com/aragonlabs/pay-protocol) (this might not be the best link to show their work in this area)
* [Token Standard Functions for Preauthorized Actions](https://github.com/ethereum/EIPs/issues/662)
* [Token Standard Extension 865](https://github.com/ethereum/EIPs/issues/865)
* [Iuri Matias: Transaction Relay](https://github.com/iurimatias/TransactionRelay)
* [uPort: Meta transactions](https://github.com/uport-project/uport-identity#send-a-meta-tx)
* [uPort: safe Identities](https://github.com/uport-project/uport-identity/blob/develop/docs/txRelay.md)
* [Gnosis safe contracts](https://github.com/gnosis/safe-contracts)

Swarm city uses a similar proposition for etherless transactions, called [Gas Station Service](https://github.com/swarmcity/SCLabs-gasstation-service), but it&apos;s a different approach. Instead of using signed messages, a traditional ethereum transaction is signed on an etherless account, the transaction is then sent to a service that immediately sends the exact amount of ether required and then publishes the transaction.

## Security Considerations

Deployers of transactions (relayers) should be able to call untrusted contracts, which provides no guarantees that the contract they are interacting with correctly implements the standard and they will be reimbursed for gas. To prevent being fooled by bad implementations, relayers must **estimate the outcome of a transaction**, and only include/sign transactions which have a desired outcome. 

Is also interest of relayers to maintaining a private reputation of contracts they interact with, as well as keep track of which tokens and for which `gasPrice` they’re willing to deploy transactions.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

## References

* [Universal Logins talk at UX Unconf, Toronto](https://www.youtube.com/watch?v=qF2lhJzngto)

[EIP-20]: /EIPs/EIPS/eip-20

[EIP-191]: /EIPs/EIPS/eip-191

[EIP-1271]: /EIPs/EIPS/eip-1271

[EIP-1344]: /EIPs/EIPS/eip-1344
</description>
        <pubDate>Fri, 04 May 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1077</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1077</guid>
      </item>
    
      <item>
        <title>Universal login / signup using ENS subdomains</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc1077-and-1078-the-magic-of-executable-signed-messages-to-login-and-do-actions/351</comments>
        
        <description>## Abstract

This presents a method to replace the usual signup/login design pattern with a minimal ethereum native scheme, that doesn’t require passwords, backing up private keys nor typing seed phrases. From the user&apos;s point of view it will be very similar to patterns they’re already used to with second factor authentication (without relying in a central server), but for dapp developers it requires a new way to think about ethereum transactions.


## Simple Summary

The unique identifier of the user is a contract that implements both Identity and the Executable Signed Messages ERCs. The user should not need to provide this address directly, only a ENS name pointing to it. These types of contracts are indirectly controlled by private keys that can sign messages indicating intents, which are then deployed to the contract by a third party (or a decentralized network of deployers).  

In this context, therefore, a device &quot;logging into&quot; an app using an identity, means that the device will generate a private key locally and then request an authorization to add that key as one of the signers of that identity, with a given set of permissions. Since that private key is only used for signing messages, it is not required to hold ether, tokens or assets, and if lost, it can be simply be replaced by a new one – the user&apos;s funds are kept on the identity contract.

In this context, ethereum accounts are used in a manner more similar to auth tokens, rather than unique keys.

The login process is as follows:

#### 1) Request a name from the user

The first step of the process is to request from the user the ENS name that points to their identity. If the user doesn’t have a login set up, the app should–if they have an integrated identity manager–provide an option to provide a subdomain or a name they own.

**UX Note:** there are many ways to provide this interface, the app can ask if they want to signup/login before hand or simply directly ask them to type the name. Note that since it’s trivial to verify if a username exists, your app should adapt to it gracefully and not require the user to type their name twice. If they ask to signup and provide a name that exists then ask them if they want to login using that name, or similarly if they ask to connect to an existing name but type a non-existent name show them a nice alert and ask them if they want to create that name now. Don’t force them to type the same name twice in two different fields.

#### 2.a) Create a new identity

If the user doesn’t have an identity, the app should provide the option to create one for them. Each app must have one or more domains they control which they can create immediate subdomains on demand. The app therefore will make these actions on the background:

1. Generate a private key which it will keep saved locally on the device or browser, the safest way possible.
2. Create (or set up) an identity contract which supports both ERC720 and ERC1077
3. Register the private key created on step 1 as the *only* admin key of the contract (the app must not add any app-controlled key, except as a recovery option - see 5)
4. Register the requested subdomain and transfer its ownership to the contract (while the app controls the main domain and may keep the option to reassign them at will, the ownership of the subdomain itself should belong to the identity, therefore allowing them to transfer it)
5. (Optionally) Register a recovery method on the contract, which allows the user to regain access to the contract in case the main key is lost.

All those steps can be designed to be set up in a single ethereum transaction. Since this step is not free, the app reserves the right to charge for registering users, or require the user to be verified in a sybil resistant manner of the app’s choosing (captcha, device ID registration, proof of work, etc)

The user shouldn’t be forced to wait for transaction confirmation times. Instead, have an indicator somewhere on the app that shows the progress and then allow the user to interact with your app normally. It’s unlikely that they’ll need the identity in the first few minutes and if something goes wrong (username gets registered at the same time), you can then ask the user for an action.

**Implementation note:** in order to save gas, some of these steps can be done in advance. The app can automatically deploy a small number of contracts when the gas price is low, and set up all their main variables to be 0xFFFFFF...FFFFF. These should be considered ‘vacant’ and when the user registers one, they will get a gas discount for freeing up space on the chain. This has the added benefit of allowing the user a choice in contract address/icon.

#### 2.b) Connect to an existing identity

If the user wants to connect with an existing identity, then the first thing the app needs to understand is what level of privilege it’s going to ask for:

**Manager** the higher level, allows the key to initiate or sign transactions that change the identity itself, like adding or removing keys. An app should only require this level if it integrates an identity manager. Depending on how the identity is set up, it might require signature from more keys before these transactions can be deployed.

**Action** this level allows the key to initiate or sign transactions on address other than itself. It can move funds, ether, assets etc. An app should only require this level of privilege if it’s a general purpose wallet or browser for sending ethereum transactions. Depending on how the identity is set up, it might require signature from more keys before these transactions can be deployed.

**Encryption** the lower level has no right to initiate any transactions, but it can be used to represent the user in specific instances or off-chain signed messages. It’s the ideal level of privilege for games, chat or social media apps, as they can be used to sign moves, send messages, etc. If a game requires actual funds (say, to start a game with funds in stake) then it should still use the encryption level, and then require the main wallet/browser of the user to sign messages using the ethereum URI standard.

Once the desired level is known, the app must take these steps:

1. **Generate a private key** which it will keep saved locally on the device or browser, the safest way possible.
2. **Query ens** to figure the existing address of the identity
3. **Generate the bytecode** for a transaction calling the function `addKey(PUBLICKEY,LEVEL)`.
4. **Broadcast a transaction request on a whisper channel** or some other decentralized network of peers. Details on this step require further discussions
1. **If web3 is available** then attempt calling web3.eth.sendTransaction. This can be automatic or prompted by user action.
1. **Attempt calling a URI** if the app supports [URL format for transaction requests EIP](/EIPs/EIPS/eip-681) then attempt calling this. This can be automatic or prompted by user action.
1. **Show a QR code**: with an EIP681 formatted URL. That QR code can be clickable to attempt to retry the other options, but it should be done last: if step 1 works, the user should receive a notification on their compatible device and won&apos;t need to use the QR code.

Here&apos;s an example of a EIP681 compatible address to add a public key generated locally in the app:

`ethereum:bob.example.eth?function=addKey(address=&apos;0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef&apos;,uint=1)`

If adding the new key requires multiple signatures, or if the app receiving that request exclusiveky deals with executable signed messages and has no ether on itself, then it should follow the steps in the next section on how to request transactions.

As before, the user shouldn’t be forced to wait for transaction confirmation times. Instead, have an indicator somewhere on the app the shows the progress and then allow the user to interact with your app normally.



#### 3) Request transactions

After step 2, the end result should be that your app should have the identity address of the user, their main ens name and a private key, whose public account is listed on the identity as one of their keys, with roles being either manager, action or encryption. Now it can start using that information to sign and execute transactions.

**Not all transactions need to be on chain**, actually most common uses of signed messages should be off chain. If you have a chat app, for instance, you can use the local key for signing messages and sending it to the other parties, and they can just query the identity contract to see if that key actually comes from the user. If you have a game with funds at stake, only the first transaction moving funds and setting up the initial game needs to be executed by the identity: at each turn the players can sign a hash of the current state of the board and at the end, the last two plays can be used to determine the winner. Notice that keys can be revoked at any time, so your app should take that in consideration, for instance saving all keys at the start of the game. Keys that only need this lower level of privilege, should be set at level 4 (encryption).

Once you decided you actually need an on-chain transaction, follow these steps:

1. **Figure out the TO, FROM, VALUE and DATA**. These are the basics of any ethereum transaction. `from` is the compatible contract you want the transaction to be deployed from.
2. **Check the privilege level you need:** if the `to` and `from` fields are the same contract, ie, if the transaction requires the identity to act upon itself (for instance, when adding or removing a key) then you need level 1 (management), otherwise it&apos;s 2 (action). Verify if the key your app owns correspond to the required level.
3. **Verify how many keys are required** by calling `requiredSignatures(uint level)` on the target contract
4. **Figure out gasLimit**: Estimate the gas cost of the desired transaction, and add a margin (recommended: add 100k gas)
5. **Figure out gasToken and gasPrice**:  Check the current gas price considering network congestions and the market price of the token the user is going to pay with. Leave gasToken as 0 for ether. Leave gasPrice as 0 if you are deploying it yourself and subsidizing the costs elsewhere.
6. **Sign an executable signed transaction** by following that standard.

After having all the signed executable message, we need to deploy it to the chain. If the transaction only requires a single signature, then the app provider can deploy it themselves. Send the transaction to the `from` address and attempt to call the function `executeSigned`, using the parameters and signature you just collected.

If the transaction need to collect more signatures or the app doesn&apos;t have a deployable server, the app should follow these steps:

1. **Broadcast the transaction on a whisper channel** or some other decentralized network of peers. Details on this step require further discussions
2. **If web3 is available** then attempt calling web3.eth.personal_sign. This can be automatic or prompted by user action.
3. **Show a QR code**: with the signed transaction and the new data to be signed. That QR code can be clickable to attempt to retry the other options, but it should be done last: if step 1 works, the user should receive a notification on their compatible device and won&apos;t need to use the QR code.

The goal is to keep broadcasting signatures via whisper until a node that is willing to deploy them is able to collect all messages.

Once you&apos;ve followed the above steps, watch the transaction pool to any transaction to that address and then take the user to your app. Once you seen the desired transaction, you can stop showing the  QR code and proceed with the app, while keeping some indication that the transaction is in progress. Subscribe to the event `ExecutedSigned` of the desired contract: once you see the transaction with the nonce, you can call it a success. If you see a different transaction with the same or higher nonce (or timestamp) then you consider the transaction permanently failed and restart the process.


### Implementation

No working examples of this implementation exists, but many developers have expressed interest in adopting it. This section will be edited in the future to reflect that.

### Conclusion and future improvements

This scheme would allow much more lighter apps, that don’t require holding ether, and can keep unlocked private keys on the device to be able to send messages and play games without requesting user prompt every time. More work is needed to standardize common decentralized messaging protocols as well as open source tools for deployment nodes, in order to create a decentralized and reliable layer for message deployment.

### References

* [Universal Logins talk at UX Unconf, Toronto](https://www.youtube.com/watch?v=qF2lhJzngto)

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 04 May 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1078</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1078</guid>
      </item>
    
      <item>
        <title>Recoverable Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-1080-recoverabletoken-standard/364</comments>
        
        <description>## Simple Summary

A standard interface for tokens that support chargebacks, theft prevention, and lost &amp; found resolutions.

## Abstract

The following standard allows for the implementation of a standard API for tokens extending ERC-20 or ERC-791. This standard provides basic functionality to recover stolen or lost accounts, as well as provide for the chargeback of tokens.

## Motivation

To mitigate the effects of reasonably provable token or asset loss or theft and to help resolve other conflicts. Ethereum&apos;s protocol should not be modified because of loss, theft, or conflicts, but it is possible to solve these problems in the smart contract layer.

## Specification

## RecoverableToken

### Methods

#### claimLost

Reports the `lostAccount` address as being lost. MUST trigger the `AccountClaimedLost` event.

After the time configured in `getLostAccountRecoveryTimeInMinutes` the implementer MUST provide a mechanism for determining the correct owner of the tokens held and moving the tokens to a new account.

Account recoveries must trigger the `AccountRecovered` event.

``` js
function claimLost(address lostAccount) returns (bool success)
```

#### cancelLostClaim

Reports the `msg.sender`&apos;s account as being not being lost. MUST trigger the `AccountClaimedLostCanceled` event.

MUST fail if an account recovery process has already begun.

Otherwise, this method MUST stop a dispute from being started to recover funds.

``` js
function claimLost() returns (bool success)
```

#### reportStolen

Reports the current address as being stolen. MUST trigger the `AccountFrozen` event.
Successful calls MUST result in the `msg.sender`&apos;s tokens being frozen.

The implementer MUST provide a mechanism for determining the correct owner of the tokens held and moving the tokens to a new account.

Account recoveries must trigger the `AccountRecovered` event.

``` js
function reportStolen() returns (bool success)
```

#### chargeback

Requests a reversal of transfer on behalf of `msg.sender`.

The implementer MUST provide a mechanism for determining the correct owner of the tokens disputed and moving the tokens to the correct account.

MUST comply with sender&apos;s chargeback window as value configured by `setPendingTransferTimeInMinutes`.

``` js
function chargeback(uint256 pendingTransferNumber) returns (bool success)
```

#### getPendingTransferTimeInMinutes

Get the time an account has to chargeback a transfer.

``` js
function getPendingTransferTime(address account) view returns (uint256 minutes)
```

#### setPendingTransferTimeInMinutes

Sets the time `msg.sender`&apos;s account has to chargeback a transfer.

MUST NOT change the time if the account has any pending transfers.

``` js
function setPendingTransferTime(uint256 minutes) returns (bool success)
```

#### getLostAccountRecoveryTimeInMinutes

Get the time account has to wait before a lost account dispute can start.

``` js
function getLostAccountRecoveryTimeInMinutes(address account) view returns (uint256 minutes)
```

#### setLostAccountRecoveryTimeInMinutes

Sets the time `msg.sender`&apos;s account has to sit before a lost account dispute can start.

MUST NOT change the time if the account has open disputes.

``` js
function setLostAccountRecoveryTimeInMinutes(uint256 minutes) returns (bool success)
```

### Events

#### AccountRecovered

The recovery of an account that was lost or stolen.

``` js
event AccountClaimedLost(address indexed account, address indexed newAccount)
```

#### AccountClaimedLostCanceled

An account claimed as being lost.

``` js
event AccountClaimedLost(address indexed account)
```

#### AccountClaimedLost

An account claimed as being lost.

``` js
event AccountClaimedLost(address indexed account)
```

#### PendingTransfer

A record of a transfer pending. 

``` js
event PendingTransfer(address indexed from, address indexed to, uint256 value, uint256 pendingTransferNumber)
```

#### ChargebackRequested

A record of a chargeback being requested.

``` js
event ChargebackRequested(address indexed from, address indexed to, uint256 value, uint256 pendingTransferNumber)
```

#### Chargeback

A record of a transfer being reversed.

``` js
event Chargeback(address indexed from, address indexed to, uint256 value, uint256 indexed pendingTransferNumber)
```

#### AccountFrozen

A record of an account being frozen. MUST trigger when an account is frozen.

``` js
event AccountFrozen(address indexed reported)
```

## Rationale

* A recoverable token standard can provide configurable safety for users or contracts who desire this safety.
* Implementations of this standard will give users the ability to select a dispute resolution process on an opt-in basis and benefit the community by decreasing the necessity of consideration of token recovery actions.


## Implementation

Pending.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 02 May 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1080</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1080</guid>
      </item>
    
      <item>
        <title>Standard Bounties</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://gitter.im/bounties-network/Lobby</comments>
        
        <description>## Simple Summary
A standard contract and interface for issuing bounties on Ethereum, usable for any type of task, paying in any ERC20 token or in ETH.

## Abstract
In order to encourage cross-platform interoperability of bounties on Ethereum, and for easier reputational tracking, StandardBounties can facilitate the administration of funds in exchange for deliverables corresponding to a completed task, in a publicly auditable and immutable fashion.

## Motivation
In the absence of a standard for bounties on Ethereum, it would be difficult for platforms to collaborate and share the bounties which users create (thereby recreating the walled gardens which currently exist on Web2.0 task outsourcing platforms). A standardization of these interactions across task types also makes it far easier to track various reputational metrics (such as how frequently you pay for completed submissions, or how frequently your work gets accepted).

## Specification
After studying bounties as they&apos;ve existed for thousands of years (and after implementing and processing over 300 of them on main-net in beta), we&apos;ve discovered that there are 3 core steps to every bounty:
- a bounty is **issued**: an `issuer` specifies the requirements for the task, describing the desired outcome, and how much they would be willing to pay for the completion of that task (denoted in one or several tokens).
- a bounty is **fulfilled**: a bounty `fulfiller` may see the bounty, complete the task, and produce a deliverable which is itself the desired outcome of the task, or simply a record that it was completed. Hashes of these deliverables should be stored immutably on-chain, to serve as proof after the fact.
- a fulfillment is **accepted**: a bounty `issuer` or `arbiter` may select one or more submissions to be accepted, thereby releasing payment to the bounty fulfiller(s), and transferring ownership over the given deliverable to the `issuer`.

To implement these steps, a number of functions are needed:
- `initializeBounty(address _issuer, address _arbiter, string _data, uint _deadline)`: This is used when deploying a new StandardBounty contract, and is particularly useful when applying the proxy design pattern, whereby bounties cannot be initialized in their constructors. Here, the data string should represent an IPFS hash, corresponding to a JSON object which conforms to the schema (described below).
- `fulfillBounty(address[] _fulfillers, uint[] _numerators, uint _denomenator, string _data)`: This is called to submit a fulfillment, submitting a string representing an IPFS hash which contains the deliverable for the bounty. Initially fulfillments could only be submitted by one individual at a time, however users consistently told us they desired to be able to collaborate on fulfillments, thereby allowing the credit for submissions to be shared by several parties. The lines along which eventual payouts are split are determined by the fractions of the submission credited to each fulfiller (using the array of numerators and single denominator). Here, a bounty platform may also include themselves as a collaborator to collect a small fee for matching the bounty with fulfillers.
- `acceptFulfillment(uint _fulfillmentId, StandardToken[] _payoutTokens, uint[] _tokenAmounts)`: This is called by the `issuer` or the `arbiter` to pay out a given fulfillment, using an array of tokens, and an array of amounts of each token to be split among the contributors. This allows for the bounty payout amount to move as it needs to be based on incoming contributions (which may be transferred directly to the contract address). It also allows for the easy splitting of a given bounty&apos;s balance among several fulfillments, if the need should arise.
   - `drainBounty(StandardToken[] _payoutTokens)`: This may be called by the `issuer` to drain a bounty of it&apos;s funds, if the need should arise.
- `changeBounty(address _issuer, address _arbiter, string _data, uint _deadline)`: This may be called by the `issuer` to change the `issuer`, `arbiter`, `data`, and `deadline` fields of their bounty.
- `changeIssuer(address _issuer)`: This may be called by the `issuer` to change to a new `issuer` if need be
- `changeArbiter(address _arbiter)`: This may be called by the `issuer` to change to a new `arbiter` if need be
- `changeData(string _data)`: This may be called by the `issuer` to change just the `data`
- `changeDeadline(uint _deadline)`: This may be called by the `issuer` to change just the `deadline`

Optional Functions:
- `acceptAndFulfill(address[] _fulfillers, uint[] _numerators, uint _denomenator, string _data, StandardToken[] _payoutTokens, uint[] _tokenAmounts)`: During the course of the development of this standard, we discovered the desire for fulfillers to avoid paying gas fees on their own, entrusting the bounty&apos;s `issuer` to make the submission for them, and at the same time accept it. This is useful since it still immutably stores the exchange of tokens for completed work, but avoids the need for new bounty fulfillers to have any ETH to pay for gas costs in advance of their earnings.
- `changeMasterCopy(StandardBounty _masterCopy)`: For `issuer`s to be able to change the masterCopy which their proxy contract relies on, if the proxy design pattern is being employed.
- `refundableContribute(uint[] _amounts, StandardToken[] _tokens)`: While non-refundable contributions may be sent to a bounty simply by transferring those tokens to the address where it resides, one may also desire to contribute to a bounty with the option to refund their contribution, should the bounty never receive a correct submission which is paid out.
`refundContribution(uint _contributionId)`: If a bounty hasn&apos;t yet paid out to any correct submissions and is past it&apos;s deadline, those individuals who employed the `refundableContribute` function may retrieve their funds from the contract.

**Schemas**
Persona Schema:
```
{
   name: // optional - A string representing the name of the persona
   email: // optional - A string representing the preferred contact email of the persona
   githubUsername: // optional - A string representing the github username of the persona
   address: // required - A string web3 address of the persona
}
```
Bounty issuance `data` Schema:
```
{
  payload: {
    title: // A string representing the title of the bounty
    description: // A string representing the description of the bounty, including all requirements
    issuer: {
       // persona for the issuer of the bounty
    },
    funders:[
       // array of personas of those who funded the issue.
    ],
    categories: // an array of strings, representing the categories of tasks which are being requested
    tags: // an array of tags, representing various attributes of the bounty
    created: // the timestamp in seconds when the bounty was created
    tokenSymbol: // the symbol for the token which the bounty pays out
    tokenAddress: // the address for the token which the bounty pays out (0x0 if ETH)

    // ------- add optional fields here -------
    sourceFileName: // A string representing the name of the file
    sourceFileHash: // The IPFS hash of the file associated with the bounty
    sourceDirectoryHash: // The IPFS hash of the directory which can be used to access the file
    webReferenceURL: // The link to a relevant web reference (ie github issue)
  },
  meta: {
    platform: // a string representing the original posting platform (ie &apos;gitcoin&apos;)
    schemaVersion: // a string representing the version number (ie &apos;0.1&apos;)
    schemaName: // a string representing the name of the schema (ie &apos;standardSchema&apos; or &apos;gitcoinSchema&apos;)
  }
}
```
Bounty `fulfillment` data Schema:

```
{
  payload: {
    description: // A string representing the description of the fulfillment, and any necessary links to works
    sourceFileName: // A string representing the name of the file being submitted
    sourceFileHash: // A string representing the IPFS hash of the file being submitted
    sourceDirectoryHash: // A string representing the IPFS hash of the directory which holds the file being submitted
    fulfillers: {
      // personas for the individuals whose work is being submitted
    }

    // ------- add optional fields here -------
  },
  meta: {
    platform: // a string representing the original posting platform (ie &apos;gitcoin&apos;)
    schemaVersion: // a string representing the version number (ie &apos;0.1&apos;)
    schemaName: // a string representing the name of the schema (ie &apos;standardSchema&apos; or &apos;gitcoinSchema&apos;)
  }
}
```
## Rationale
The development of this standard began a year ago, with the goal of encouraging interoperability among bounty implementations on Ethereum. The initial version had significantly more restrictions: a bounty&apos;s `data` could not be changed after issuance (it seemed unfair for bounty `issuer`s to change the requirements after work is underway), and the bounty payout could not be changed (all funds needed to be deposited in the bounty contract before it could accept submissions). 

The initial version was also far less extensible, and only allowed for fixed payments to a given set of fulfillments. This new version makes it possible for funds to be split among several correct submissions, for submissions to be shared among several contributors, and for payouts to not only be in a single token as before, but in as many tokens as the `issuer` of the bounty desires. These design decisions were made after the 8+ months which Gitcoin, the Bounties Network, and Status Open Bounty have been live and meaningfully facilitating bounties for repositories in the Web3.0 ecosystem.

## Test Cases
Tests for our implementation can be found here: https://github.com/Bounties-Network/StandardBounties/tree/develop/test

## Implementation
A reference implementation can be found here: https://github.com/Bounties-Network/StandardBounties/blob/develop/contracts/StandardBounty.sol
**Although this code has been tested, it has not yet been audited or bug-bountied, so we cannot make any assertions about it&apos;s correctness, nor can we presently encourage it&apos;s use to hold funds on the Ethereum mainnet.**

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 14 May 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1081</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1081</guid>
      </item>
    
      <item>
        <title>Net gas metering for SSTORE operations</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-net-storage-gas-metering-for-the-evm/383</comments>
        
        <description>## Abstract
This EIP proposes a change to how gas is charged for EVM `SSTORE` operations, in order to reduce excessive gas costs in situations where these are unwarranted, and to enable new use-cases for contract storage.

## Motivation
Presently, `SSTORE` (`0x55`) operations are charged as follows:

 - 20,000 gas to set a slot from 0 to non-0
 - 5,000 gas for any other change
 - A 10,000 gas refund when a slot is set from non-0 to 0. Refunds are applied at the end of the transaction.

In situations where a single update is made to a storage value in a transaction, these gas costs have been determined to fairly reflect the resources consumed by the operation. However, this results in excessive gas costs for sequences of operations that make multiple updates.

Some examples to illustrate the problem:

 - If a contract with empty storage sets slot 0 to 1, then back to 0, it will be charged `20000 + 5000 - 10000 = 15000` gas, despite this sequence of operations not requiring any disk writes.
 - A contract with empty storage that increments slot 0 5 times will be charged `20000 + 5 * 5000 = 45000` gas, despite this sequence of operations requiring no more disk activity than a single write, charged at 20000 gas.
 - A balance transfer from account A to account B followed by a transfer from B to C, with all accounts having nonzero starting and ending balances, will cost `5000 * 4 = 20000` gas.

Addressing this issue would also enable new use-cases that are currently cost-prohibitive, where a sequence of operations results in no net change to storage at the end of the transaction. For instance, mutexes to prevent reentrancy, or context information passed between multiple calls to the same contract. One such example is an `approveAndCall` operation, which would permit sending to and calling a contract in a single transaction, without that contract having to be updated for a new token standard.

## Specification
The following changes are made to the EVM:

 - A &apos;dirty map&apos; for each transaction is maintained, tracking all storage slots in all contracts that have been modified in the current transaction. The dirty map is scoped in the same manner as updates to storage, meaning that changes to the dirty map in a call that later reverts are not retained.
 - When a storage slot is written to with the value it already contains, 200 gas is deducted.
 - When a storage slot&apos;s value is changed for the first time, the slot is marked as dirty. If the slot was previously set to 0, 20000 gas is deducted; otherwise, 5000 gas is deducted.
 - When a storage slot that is already in the dirty map is written to, 200 gas is deducted.
 - At the end of the transaction, for each slot in the dirty map:
   - If the slot was 0 before the transaction and is 0 now, refund 19800 gas.
   - If the slot was nonzero before the transaction and its value has not changed, refund 4800 gas.
   - If the slot was nonzero before the transaction and is 0 now, refund 15000 gas.

After these changes, transactions that make only a single change to a storage slot will retain their existing costs. However, contracts that make multiple changes will see significantly reduced costs. Repeating the examples from the Motivation section:

 - If a contract with empty storage sets slot 0 to 1, then back to 0, it will be charged `20000 + 200 - 19800 = 400` gas, down from 15000.
 - A contract with empty storage that increments slot 0 5 times will be charged `20000 + 5 * 200 = 21000` gas, down from 45000.
 - A balance transfer from account A to account B followed by a transfer from B to C, with all accounts having nonzero starting and ending balances, will cost `5000 * 3 + 200 - 4800 = 10400` gas, down from 20000.

## Rationale
We believe the proposed mechanism represents the simplest way to reduce storage gas costs in situations where they do not reflect the actual costs borne by nodes. Several alternative designs were considered and dismissed:

 - Charging a flat 200 gas for `SSTORE` operations, and an additional 19800 / 4800 at the end of a transaction for new or modified values is simpler, and removes the need for a dirty map, but pushes a significant source of gas consumption out of the EVM stack and applies it at the end of the transaction, which is likely to complicate debugging and reduces contracts&apos; ability to limit the gas consumption of callees, as well as introducing a new mechanism to the EVM.
 - Keeping a separate refund counter for storage gas refunds would avoid the issue of refunds being limited to half the gas consumed (not necessary here), but would introduce additional complexity in tracking this value.
 - Refunding gas each time a storage slot is set back to its initial value would introduce a new mechanism (instant refunds) and complicate gas accounting for contracts calling other contracts; it would also permit the possibility of a contract call with negative execution cost.

## Backwards Compatibility
This EIP requires a hard fork to implement.

No contract should see an increase in gas cost for this change, and many will see decreased gas consumption, so no contract-layer backwards compatibility issues are anticipated.

## Test Cases

 - Writing x to a storage slot that contains 0, where x != 0 (20k gas, no refund)
 - Writing y to a storage slot that contained x, where x != y and x != 0 (5k gas, no refund)
 - Writing 0 to a storage slot that contains x, where x != 0 (5k gas, 10k refund)
 - Writing 0 to a storage slot that already contains zero (200 gas, no refund)
 - Writing x to a storage slot that already contains x, where x != 0 (200 gas, no refund)
 - Writing x, then y to a storage slot that contains 0, where x != y (20200 gas, no refund)
 - Writing x, then y to a storage slot that contains 0, where x != y != z and x != 0 (5200 gas, no refund)
 - Writing x, then 0 to a storage slot that contains 0, where x != 0 (20200 gas, 19800 refund)
 - Writing x, then y to a storage slot that contains y, where x != y != 0 (5200 gas, 4800 refund)
 - Writing x, then 0 to a storage slot that contains 0, then reverting the stack frame in which the writes occurred (20200 gas, no refund)
 - Writing x, then y to a storage slot that contains y, then reverting the stack frame in which the writes occurred (5200 gas, no refund)
 - In a nested frame, writing x to a storage slot that contains 0, then returning, and writing 0 to that slot (20200 gas, 19800 refund)

## Implementation
TBD

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 17 May 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1087</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1087</guid>
      </item>
    
      <item>
        <title>Opt-in account exposure</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-1102-opt-in-provider-access/414</comments>
        
        <description>## Simple summary

This proposal describes a communication protocol between dapps and Ethereum-enabled DOM environments that allows the Ethereum-enabled DOM environment to choose what information to supply the dapp with and when.

## Abstract

The previous generation of Ethereum-enabled DOM environments follows a pattern of injecting a provider populated with accounts without user consent. This puts users of such environments at risk because malicious websites can use these accounts to view detailed account information and to arbitrarily initiate unwanted transactions on a user&apos;s behalf.

This proposal outlines a protocol in which Ethereum-enabled DOM environments can choose to expose no accounts until the user approves account access.

## Specification

### Concepts

#### RFC-2119

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;,  &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC-2119](https://www.ietf.org/rfc/rfc2119.txt).

#### `eth_requestAccounts`

Providers exposed by Ethereum-enabled DOM environments define a new RPC method: `eth_requestAccounts`. Calling this method may trigger a user interface that allows the user to approve or reject account access for a given dapp. This method returns a `Promise` that is resolved with an `Array` of accounts or is rejected with an `Error` if accounts are not available.

```typescript
ethereum.send(&apos;eth_requestAccounts&apos;): Promise&lt;Array&lt;string&gt;&gt;
```

#### Provider#enable (DEPRECATED)

**Note: This method is deprecated in favor of the RPC method [`eth_requestAccounts`](#eth_requestaccounts).**

Providers exposed by Ethereum-enabled DOM environments define a new RPC method: `ethereum.enable()`. Calling this method triggers a user interface that allows the user to approve or reject account access for a given dapp. This method returns a `Promise` that is resolved with an `Array` of accounts if the user approves access or rejected with an `Error` if the user rejects access.

```typescript
ethereum.enable(): Promise&lt;any&gt;
```

### Protocol

#### Legacy dapp initialization

```
START dapp
IF web3 is defined
    CONTINUE dapp
IF web3 is undefined
    STOP dapp
```

#### Proposed dapp initialization

```
START dapp
IF provider is defined
    REQUEST[1] account access
    IF user approves
        RESOLVE[2] account access
        CONTINUE dapp
    IF user rejects
        REJECT[3] account access
        STOP dapp
IF provider is undefined
    STOP dapp
```

##### `[1] REQUEST`

Dapps **MUST** request accounts by calling the `eth_requestAccounts` RPC method on the provider exposed at `window.ethereum`. Calling this method **MAY** trigger a user interface that allows the user to approve or reject account access for a given dapp. This method **MUST** return a `Promise` that is resolved with an array of one or more user accounts or rejected if no accounts are available (e.g., the user rejected account access).

##### `[2] RESOLVE`

The `Promise` returned when calling the `eth_requestAccounts` RPC method **MUST** be resolved with an `Array` of user accounts.

##### `[3] REJECT`

The `Promise` returned when calling the `eth_requestAccounts` RPC method **MUST** be rejected with an informative `Error` if no accounts are available for any reason.

### Example initialization

```js
try {
    // Request account access if needed
    const accounts = await ethereum.send(&apos;eth_requestAccounts&apos;);
    // Accounts now exposed, use them
    ethereum.send(&apos;eth_sendTransaction&apos;, { from: accounts[0], /* ... */ })
} catch (error) {
    // User denied account access
}
```

### Constraints

* Browsers **MUST** expose a provider at `window.ethereum` .
* Browsers **MUST** define an `eth_requestAccounts` RPC method.
* Browsers **MAY** wait for a user interaction before resolving/rejecting the `eth_requestAccounts` promise.
* Browsers **MUST** include at least one account if the `eth_requestAccounts` promise is resolved.
* Browsers **MUST** reject the promise with an informative error if no accounts are available.

## Rationale

The pattern of automatic account exposure followed by the previous generation of Ethereum-enabled DOM environments fails to protect user privacy and fails to maintain safe user experience: untrusted websites can both view detailed account information and arbitrarily initiate transactions on a user&apos;s behalf. Even though most users may reject unsolicited transactions on untrusted websites, a protocol for account access should make such unsolicited requests impossible.

This proposal establishes a new pattern wherein dapps must request access to user accounts. This protocol directly strengthens user privacy by allowing the browser to hide user accounts and preventing unsolicited transaction requests on untrusted sites.

### Immediate value-add

* Users can reject account access on untrusted sites to hide accounts.
* Users can reject account access on untrusted sites to prevent unsolicited transactions.

### Long-term value-add

* Dapps could request specific account information based on user consent.
* Dapps could request specific user information based on user consent (uPort, DIDs).
* Dapps could request a specific network based on user consent.
* Dapps could request multiple instances of the above based on user consent.

## Backwards compatibility

This proposal impacts dapp developers and requires that they request access to user accounts following the protocol outlined above. Similarly, this proposal impacts dapp browser developers and requires that they only expose user accounts following the protocol defined above.

## Implementation

The MetaMask team [has implemented](https://github.com/MetaMask/metamask-extension/pull/4703) the strategy described above.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 04 May 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1102</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1102</guid>
      </item>
    
      <item>
        <title>Reduce alt_bn128 precompile gas costs</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-1108-reduce-alt-bn128-precompile-gas-costs/3206</comments>
        
        <description>## Simple Summary  

The elliptic curve arithmetic precompiles are currently overpriced. Re-pricing the precompiles would greatly assist a number of privacy solutions and scaling solutions on Ethereum. 

## Abstract

Changes in 2018 to the underlying library used by the official Go reference
implementation led to significant performance gains for the `ECADD`, `ECMUL`,
and pairing check precompiled contracts on the `alt_bn128` elliptic curve.

In the Parity client, field operations used by the precompile algorithms were optimized in 2018, 
and recent changes to the pairing algorithm used by the `bn` crate have brought considerable speedups.

Faster operations on Ethereum clients should be reflected in reduced gas costs.

## Motivation

Recently, the underlying library used by the [official Go reference
implementation](https://github.com/ethereum/go-ethereum) to implement the
`ECADD` (at address `0x06`), `ECMUL` (at address `0x07`), and pairing check (at
address `0x08`) precompiled contracts was shifted to [Cloudflare&apos;s bn256
library](https://github.com/cloudflare/bn256). Based on the [initial PR that
introduced this change](https://github.com/ethereum/go-ethereum/pull/16203),
and corroborated in [a later
note](https://github.com/ethereum/go-ethereum/pull/16301#issuecomment-372687543),
the computational cost of `ECADD`, `ECMUL`, and pairing checks (excepting the
constant) has dropped roughly an order of magnitude across the board.

Also, optimizations in the bn library [in 2018](https://github.com/paritytech/bn/pull/9) and [2019](https://github.com/paritytech/bn/pull/14)
used by the [Parity client](https://github.com/paritytech/parity-ethereum) led to a 
significant performance boost we 
[benchmarked](https://gist.github.com/zac-williamson/838410a3da179d47d31b25b586c15e53) 
and compared against the [previous 
results](https://gist.github.com/pdyraga/4649b74436940a01e8221d85e80bfeef).  


## Specification

Following is a table with the current gas cost and new gas cost:

| Contract      | Address   | Current Gas Cost               | Updated Gas Cost    |
| ------------- | --------- | -----------------------------  | ------------------- |
| `ECADD`       | `0x06`    | 500&lt;sup&gt;[1]&lt;/sup&gt;              | 150                 |
| `ECMUL`       | `0x07`    | 40 000&lt;sup&gt;[1]&lt;/sup&gt;           | 6 000               |
| Pairing check | `0x08`    | 80 000 * k + 100 000&lt;sup&gt;[2]&lt;/sup&gt;| 34 000 * k + 45 000    |

The gas costs for `ECADD` and `ECMUL` are updates to the costs listed in
EIP-196, while the gas costs for the pairing check are updates to the cost
listed in EIP-197. Updated gas costs have been adjusted to the less performant 
client which is Parity, according to benchmarks&lt;sup&gt;[3]&lt;/sup&gt;.

To come up with these updates gas costs, the performance of the `ecrecover` precompile
was measured at 116 microseconds per `ecrecover` invocation. Assuming the `ecrecover`
gas price is fair at 3,000 gas, we get a price of 25.86 gas per microsecond of a precompile
algorithm&apos;s runtime. With this in mind, the pairing precompile took 3,037 microseconds to
compute 1 pairing, and 14,663 microseconds to compute 10 pairings. From this, the pairing
algorithm has a fixed &apos;base&apos; run-time of 1,745 microseconds, plus 1,292 microseconds per
pairing. We can split the run-time into &apos;fixed cost&apos; and &apos;linear cost per pairing&apos;
components because of the structure of the algorithm.

Thus using a &apos;fair&apos; price of 25.86 gas per microsecond, we get a gas formula of
~`35,000 * k + 45,000` gas, where `k` is the number of pairings being computed. [4]

[1]- Per [EIP-196](/EIPs/EIPS/eip-196).

[2]- Per [EIP-197](/EIPs/EIPS/eip-197).

[3]- [Parity benchmarks.](https://gist.github.com/zac-williamson/838410a3da179d47d31b25b586c15e53)

[4]- [PR comment clarifying gas cost math](https://github.com/ethereum/EIPs/pull/1987#discussion_r280977066).

## Rationale  

### Existing protocols would benefit immensely from cheaper elliptic curve cryptography

Fast elliptic curve cryptography is a keystone of a growing number of protocols built on top of Ethereum. To list a few:  

* [The AZTEC protocol](https://github.com/AztecProtocol/AZTEC) utilizes the elliptic curve precompiles to construct private tokens, with zero-knowledge transaction logic, via the [ERC-1723](https://github.com/ethereum/EIPs/issues/1723) and [ERC-1724](https://github.com/ethereum/EIPs/issues/1724) standard.  
* [Matter Labs](https://github.com/matter-labs/matter-network) utilizes the precompiles to implement Ignis, a scaling solution with a throughput of 500txns per second  
* [Rollup](https://github.com/rollup/rollup) utilizes the precompiles to create L2 scaling solutions, where the correctness of transactions is guaranteed by main-net, without an additional consensus layer  
* ZEther[^1] uses precompiles `ECADD` and `ECMUL` to construct confidential transactions

[^1]:
    ```csl-json
    {
        &quot;publisher-place&quot;: &quot;Cham&quot;,
        &quot;URL&quot;: &quot;https://eprint.iacr.org/2019/191.pdf&quot;,
        &quot;custom&quot;: {
            &quot;additional-urls&quot;: [
                &quot;https://web.archive.org/web/20220819003610/https://crypto.stanford.edu/~buenz/papers/zether.pdf&quot;
            ]
        },
        &quot;DOI&quot;: &quot;10.1007/978-3-030-51280-4_23&quot;,
        &quot;abstract&quot;: &quot;Smart contract platforms such as Ethereum and Libra provide ways to seamlessly remove trust and add transparency to various distributed applications. Yet, these platforms lack mechanisms to guarantee user privacy, even at the level of simple payments, which are essential for most smart contracts.&quot;,
        &quot;author&quot;: [
          {
            &quot;given&quot;: &quot;Benedikt&quot;,
            &quot;family&quot;: &quot;Bünz&quot;
          },
          {
            &quot;given&quot;: &quot;Shashank&quot;,
            &quot;family&quot;: &quot;Agrawal&quot;
          },
          {
            &quot;given&quot;: &quot;Mahdi&quot;,
            &quot;family&quot;: &quot;Zamani&quot;
          },
          {
            &quot;given&quot;: &quot;Dan&quot;,
            &quot;family&quot;: &quot;Boneh&quot;
          }
        ],
        &quot;container-title&quot;: &quot;Financial Cryptography and Data Security&quot;,
        &quot;editor&quot;: [
          {
            &quot;given&quot;: &quot;Joseph&quot;,
            &quot;family&quot;: &quot;Bonneau&quot;
          },
          {
            &quot;given&quot;: &quot;Nadia&quot;,
            &quot;family&quot;: &quot;Heninger&quot;
          }
        ],
        &quot;type&quot;: &quot;paper-conference&quot;,
        &quot;id&quot;: &quot;10.1007/978-3-030-51280-4_23&quot;,
        &quot;citation-key&quot;: &quot;10.1007/978-3-030-51280-4_23&quot;,
        &quot;ISBN&quot;: &quot;978-3-030-51280-4&quot;,
        &quot;issued&quot;: {
          &quot;date-parts&quot;: [
            [
              2020
            ]
          ]
        },
        &quot;page&quot;: &quot;423-443&quot;,
        &quot;publisher&quot;: &quot;Springer International Publishing&quot;,
        &quot;title&quot;: &quot;Zether: Towards Privacy in a Smart Contract World&quot;
    }
    ```

These are all technologies that have been, or are in the process of being, deployed to main-net. These protocols would all benefit from reducing the gas cost of the precompiles.  

To give a concrete example, it currently costs `820,000` gas to validate the cryptography in a typical AZTEC confidential transaction. If the gas schedule for the precompiles correctly reflected their load on the Ethereum network, this cost would be `197,000` gas. This significantly increases the potential use cases for private assets on Ethereum. AZTEC is planning to deploy several cryptographic protocols Ethereum, but these are at the limits of what is practical given the current precompile costs:  

* Confidential weighted voting  
* Partial-order filling over encrypted orders, for private decentralized exchanges  
* Anonymous identity sharing proofs (e.g. proving you are on a whitelist, without revealing who you are)  
* Many-to-one payments and one-to-many confidential payments, as encrypted communication channels between main-net and L2 applications  

For zk-SNARK based protocols on Ethereum, EIP-1108 will not only reduce the gas costs of verifying zk-SNARKs substantially, but can also aid in [batching together multiple zk-SNARK proofs](https://github.com/matter-labs/Groth16BatchVerifier). This is also a technique that can be used to split up monolithic zk-SNARK circuits into a batch of zk-SNARKs with smaller individual circuit sizes, which makes zk-SNARKs both easier to construct and deploy.

ZEther transactions currently cost ~`6,000,000` gas. This EIP would reduce this to ~`1,000,000` gas, which makes the protocol more practical.  

To summarise, there are several protocols that currently exist on main-net, that would benefit immensely from this EIP. Elliptic curve cryptography can provide valuable solutions for Ethereum, such as scaling and privacy, and the scope and scale of these solutions can be increased if the gas costs for the `bn128` precompiles accurately reflects their computational load on the network.

### Cheaper elliptic curve cryptography can be used to trade storage for computation  

Solutions such as Rollup and Ignis can be used to batch groups of individual transactions into a zk-SNARK proof, with the on-chain state being represented by a small Merkle root, instead of multiple account balances.  

If zk-SNARK verification costs are decreased, these solutions can be deployed for a wider range of use cases and more Rollup-style transactions can be processed per block.

### Parity and Geth already have fast algorithms that justify reduced gas costs  

This EIP does not require Parity or Geth to deploy new cryptographic libraries, as fast bn128 algorithms have already been integrated into these clients. This goal of proposing this EIP for Istanbul, is to supplement [EIP-1829](/EIPs/EIPS/eip-1829) (arithmetic over generic elliptic curves), providing an immediate solution to the pressing problem of expensive cryptography, while more advanced solutions are developed, defined and deployed.


## Test Cases  

As no underlying algorithms are being changed, there are no additional test cases to specify.  

## Implementation  

Both the Parity and Geth clients have already implemented cryptographic libraries that are fast enough to justify reducing the precompile gas costs. As a reference, here are a list of elliptic curve libraries, in `C++`, `golang` and `rust`, that support the `bn128` curve, and have run-times that are equal to or faster than the Parity benchmarks.  

* [Parity bn crate (rust)](https://github.com/paritytech/bn)  
* [Geth bn256 library (golang)](https://github.com/ethereum/go-ethereum/tree/master/crypto/bn256/cloudflare)  
* [MCL, a portable C++ pairing library](https://github.com/herumi/mcl)  
* [Libff, a C++ pairing library used in many zk-SNARK libraries](https://github.com/scipr-lab/libff)

## Additional References

@vbuterin independently proposed a similar reduction after this EIP was originally created, with similar rationale, as [ethereum/EIPs#1187](https://github.com/ethereum/EIPs/issues/1187).

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 21 May 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1108</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1108</guid>
      </item>
    
      <item>
        <title>PRECOMPILEDCALL opcode (Remove CALL costs for precompiled contracts)</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-1109-remove-call-costs-for-precompiled-contracts/447</comments>
        
        <description>## Simple Summary

This EIP creates a specific opcode named `PRECOMPILEDCALL` to call Precompiled contracts without the costs of a normal `CALL`.

## Abstract

This EIP tries to resolve the problem of high gas consumption when calling precompiled contracts with a small gas cost. Using this opcode for calling precompiled contracts allows to define precompiled contracts whose effective cost it is less than 700.

## Motivation

Each precompiled contract has an already defined cost for calling it. It does not make sense to add the implicit extra gas cost of the CALL opcode.

As an example, SHA256 precompiled contract costs 60 and ECADD costs 500 (proposed to costs only 50 in [EIP-1108](/EIPs/EIPS/eip-1108) . When a precompiled contract is called, 700 gas is consumed just for the CALL opcode besides the costs of the precompiled contract.

This makes no sense, and right now it&apos;s impossible to define a precompiled contract whose effective cost for using it, is less than 700.

## Specification

If `block.number &gt;= XXXXX`, define a new opcode named `PRECOMPILEDCALL` with code value `0xfb`.

The gas cost of the OPCODE is 2 (Gbase) plus the Specific gas cost defined for each specific precompiled smart contract.

The OPCODE takes 5 words from the stack and returns 1 word to the stack.

The input stack values are:

mu_s[0] = The address of the precompiled smart contract that is called.
mu_s[1] = Pointer to memory for the input parameters.
mu_s[2] = Length of the input parameters in bytes.
mu_s[3] = Pointer to memory where the output is stored
mu_s[4] = Length of the output buffer.


The return will be 1 in case of success call and 0 in any of the next cases:

1.- mu_s[0] is an address of an undefined precompiled smart contract.
2.- The precompiled smart contract fails (as defined on each smart contract). Invalid input parameters for example.

Precompiled smart contracts, does not execute opcodes, so there is no need to pass a gas parameter as a normal `CALL` (`0xf1`).  If the available gas is less that 2 plus the required gas required for the specific precompiled smart contract, the context just STOPS executing with an &quot;Out of Gas&quot; error.

There is no stack check for this call.

The normal `CALL`s to the precompiled smart contracts continue to work with the exact same behavior.

A `PRECOMPILEDCALL` to a regular address or regular smart contract, is considered a call to an &quot;undefined smart contract&quot;, so the VM MUST not execute it and the opcode must return 0x0 .


## Rationale

There was a first proposal for removing the gast consts for the `CALL`, but it looks that it&apos;s easier to implement and test a new opcode just for that.

The code is just the next opcode available after the `STATICCALL` opcode.

## Backwards Compatibility

This EIP is backwards compatible.  Smart contracts that call precompiled contracts using this new opcode will cost less from now on.

Old contracts that call precompiled smart contracts with the `CALL` method, will continue working.

## Test Cases

- Normal call to a defined precompiled contract.
- Call to undefined precompiled contract.
- Call to a regular contract
- Call to a regular account
- Call to 0x0 smart contract (Does not exists).
- Call with large values for the offste pointers and lengths
- Call with the exact gas remaining needed to call smart contract.
- Call with the exact gas remaining minus one needed to call smart contract.

## Implementation

Not implemented yet.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 22 May 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1109</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1109</guid>
      </item>
    
      <item>
        <title>Revised Ethereum Smart Contract Packaging Standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1123</comments>
        
        <description>This ERC has been abandoned in favor of the EthPM V3 smart contract packaging standard defined in [ERC-2678](/EIPs/EIPS/eip-2678)

Simple Summary
==============

A data format describing a smart contract software package.


Abstract
==========

This EIP defines a data format for *package manifest* documents,
representing a package of one or more smart contracts, optionally
including source code and any/all deployed instances across multiple
networks. Package manifests are minified JSON objects, to be distributed
via content addressable storage networks, such as IPFS.

This document presents a natural language description of a formal
specification for version **2** of this format.


Motivation
==========

This standard aims to encourage the Ethereum development ecosystem
towards software best practices around code reuse. By defining an open,
community-driven package data format standard, this effort seeks to
provide support for package management tools development by offering a
general-purpose solution that has been designed with observed common
practices in mind.

As version 2 of this specification, this standard seeks to address a
number of areas of improvement found for the previous version (defined
in
[EIP-190](/EIPs/EIPS/eip-190)).
This version:

-   Generalizes storage URIs to represent any content addressable URI
    scheme, not only IPFS.

-   Renames *release lockfile* to *package manifest*.

-   Adds support for languages other than Solidity by generalizing the
    compiler information format.

-   Redefines link references to be more flexible, to represent
    arbitrary gaps in bytecode (besides only addresses), in a more
    straightforward way.

-   Forces format strictness, requiring that package manifests contain
    no extraneous whitespace, and sort object keys in alphabetical
    order, to prevent hash mismatches.


&lt;div id=&quot;package-specification&quot;&gt;&lt;/div&gt;

Specification
=============

This document defines the specification for an EthPM package manifest. A
package manifest provides metadata about a [Package](#term-package), and
in most cases should provide sufficient information about the packaged
contracts and its dependencies to do bytecode verification of its
contracts.

&gt; **Note**
&gt;
&gt; A [hosted
&gt; version](https://ethpm.github.io/ethpm-spec) of this
&gt; specification is available via GitHub Pages. This EIP and the hosted
&gt; HTML document were both autogenerated from the same documentation
&gt; source.


Guiding Principles
------------------

This specification makes the following assumptions about the document
lifecycle.

1.  Package manifests are intended to be generated programmatically by
    package management software as part of the release process.

2.  Package manifests will be consumed by package managers during tasks
    like installing package dependencies or building and deploying new
    releases.

3.  Package manifests will typically **not** be stored alongside the
    source, but rather by package registries *or* referenced by package
    registries and stored in something akin to IPFS.


Conventions
-----------


### RFC2119

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;https://www.ietf.org/rfc/rfc2119.txt&gt;


### Prefixed vs Unprefixed

A [prefixed](#term-prefixed) hexadecimal value begins with `0x`.
[Unprefixed](#term-unprefixed) values have no prefix. Unless otherwise
specified, all hexadecimal values **should** be represented with the
`0x` prefix.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Prefixed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;0xdeadbeef&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Unprefixed&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;deadbeef&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


Document Format
---------------

The canonical format is a single JSON object. Packages **must** conform
to the following serialization rules.

-   The document **must** be tightly packed, meaning no linebreaks or
    extra whitespace.

-   The keys in all objects must be sorted alphabetically.

-   Duplicate keys in the same object are invalid.

-   The document **must** use
    [UTF-8](https://en.wikipedia.org/wiki/UTF-8)
    encoding.

-   The document **must** not have a trailing newline.


Document Specification
----------------------

The following fields are defined for the package. Custom fields **may**
be included. Custom fields **should** be prefixed with `x-` to prevent
name collisions with future versions of the specification.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;See Also&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Formalized (&lt;a href=&quot;https://json-schema.org&quot;&gt;JSON-Schema&lt;/a&gt;) version of this specification: &lt;a href=&quot;https://github.com/ethpm/ethpm-spec/tree/v2.0.0/spec/package.spec.json&quot;&gt;package.spec.json&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Jump To&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a href=&quot;#definitions&quot;&gt;Definitions&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;div id=&quot;manifest-version&quot;&gt;&lt;/div&gt;

### EthPM Manifest Version: `manifest_version`

The `manifest_version` field defines the specification version that this
document conforms to. Packages **must** include this field.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Key&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;manifest_version&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;String&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Allowed Values&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;2&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;div id=&quot;package-names&quot;&gt;&lt;/div&gt;

### Package Name: `package_name`

The `package_name` field defines a human readable name for this package.
Packages **must** include this field. Package names **must** begin with
a lowercase letter and be comprised of only lowercase letters, numeric
characters, and the dash character `-`. Package names **must** not
exceed 214 characters in length.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Key&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;package_name&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;String&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Format&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;must&lt;/strong&gt; match the regular expression &lt;code&gt;^[a-zA-Z][a-zA-Z0-9_]{0,255}$&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


### Package Meta: `meta`

The `meta` field defines a location for metadata about the package which
is not integral in nature for package installation, but may be important
or convenient to have on-hand for other reasons. This field **should**
be included in all Packages.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Key&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;meta&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;a href=&quot;#package-meta-object&quot;&gt;Package Meta Object&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


### Version: `version`

The `version` field declares the version number of this release. This
value **must** be included in all Packages. This value **should**
conform to the [semver](https://semver.org/) version
numbering specification.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Key&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;version&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;String&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


### Sources: `sources`

The `sources` field defines a source tree that **should** comprise the
full source tree necessary to recompile the contracts contained in this
release. Sources are declared in a key/value mapping.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Key&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;sources&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Object (String: String)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Format&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;See Below.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


#### Format

Keys **must** be relative filesystem paths beginning with a `./`.

Paths **must** resolve to a path that is within the current working
directory.

Values **must** conform to *one of* the following formats.

-   Source string.

-   [Content Addressable URI](#term-content-addressable-uri).

When the value is a source string the key should be interpreted as a
file path.

-   If the resulting document is a directory the key should be
    interpreted as a directory path.

-   If the resulting document is a file the key should be interpreted as
    a file path.


### Contract Types: `contract_types`

The `contract_types` field holds the [Contract
Types](#term-contract-type) which have been included in this release.
[Packages](#term-package) **should** only include contract types that
can be found in the source files for this package. Packages **should
not** include contract types from dependencies. Packages **should not**
include abstract contracts in the contract types section of a release.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Key&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;contract_types&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Object (String: &lt;a href=&quot;#contract-type-object&quot;&gt;Contract Type Object&lt;/a&gt;)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Format&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Keys &lt;strong&gt;must&lt;/strong&gt; be valid &lt;a href=&quot;#term-contract-alias&quot;&gt;Contract Aliases&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Values &lt;strong&gt;must&lt;/strong&gt; conform to the &lt;a href=&quot;#contract-type-object&quot;&gt;Contract Type Object&lt;/a&gt; definition.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


### Deployments: `deployments`

The `deployments` field holds the information for the chains on which
this release has [Contract Instances](#term-contract-instance) as well
as the [Contract Types](#term-contract-type) and other deployment
details for those deployed contract instances. The set of chains defined
by the `*BIP122 URI &lt;#bip122-uris&gt;*` keys for this object **must** be
unique.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Key&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;deployments&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Object (String: Object(String: &lt;a href=&quot;#contract-instance-object&quot;&gt;Contract Instance Object&lt;/a&gt;))&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Format&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;See Below.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


#### Format

Keys **must** be a valid BIP122 URI chain definition.

Values **must** be objects which conform to the following format.

-   Keys **must** be valid [Contract Instance
    Names](#term-contract-instance-name).

-   Values **must** be a valid [Contract Instance
    Object](#contract-instance-object).


### Build Dependencies: `build_dependencies`

The `build_dependencies` field defines a key/value mapping of Ethereum
[Packages](#term-package) that this project depends on.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Key&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;build_dependencies&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Object (String: String)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Format&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Keys &lt;strong&gt;must&lt;/strong&gt; be valid &lt;a href=&quot;#package-names&quot;&gt;package names&lt;/a&gt; matching the regular expression &lt;code&gt;[a-z][-a-z0-9]{0,213}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Values &lt;strong&gt;must&lt;/strong&gt; be valid IPFS URIs which resolve to a valid package.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


Definitions
-----------

Definitions for different objects used within the Package. All objects
allow custom fields to be included. Custom fields **should** be prefixed
with `x-` to prevent name collisions with future versions of the
specification.


&lt;div id=&quot;link-reference-object&quot;&gt;&lt;/div&gt;

### The *Link Reference* Object

A [Link Reference](#term-link-reference) object has the following
key/value pairs. All link references are assumed to be associated with
some corresponding [Bytecode](#term-bytecode).


#### Offsets: `offsets`

The `offsets` field is an array of integers, corresponding to each of
the start positions where the link reference appears in the bytecode.
Locations are 0-indexed from the beginning of the bytes representation
of the corresponding bytecode. This field is invalid if it references a
position that is beyond the end of the bytecode.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Array&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


#### Length: `length`

The `length` field is an integer which defines the length in bytes of
the link reference. This field is invalid if the end of the defined link
reference exceeds the end of the bytecode.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Integer&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


#### Name: `name`

The `name` field is a string which **must** be a valid
[Identifier](#term-identifier). Any link references which **should** be
linked with the same link value **should** be given the same name.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;String&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Format&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;must&lt;/strong&gt; conform to the &lt;a href=&quot;#term-identifier&quot;&gt;Identifier&lt;/a&gt; format.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;div id=&quot;link-value-object&quot;&gt;&lt;/div&gt;

### The *Link Value* Object

Describes a single [Link Value](#term-link-value).

A **Link Value object** is defined to have the following key/value
pairs.


&lt;div id=&quot;offset-offset-1&quot;&gt;&lt;/div&gt;

#### Offsets: `offsets`

The `offsets` field defines the locations within the corresponding
bytecode where the `value` for this link value was written. These
locations are 0-indexed from the beginning of the bytes representation
of the corresponding bytecode.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Integer&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Format&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;See Below.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

**Format**

Array of integers, where each integer **must** conform to all of the
following.

-   greater than or equal to zero

-   strictly less than the length of the unprefixed hexadecimal
    representation of the corresponding bytecode.


#### Type: `type`

The `type` field defines the `value` type for determining what is
encoded when [linking](#term-linking) the corresponding bytecode.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;String&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Allowed Values&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;&amp;quot;literal&amp;quot;&lt;/code&gt; for bytecode literals&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;quot;reference&amp;quot;&lt;/code&gt; for named references to a particular &lt;a href=&quot;#term-contract-instance&quot;&gt;Contract Instance&lt;/a&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


#### Value: `value`

The `value` field defines the value which should be written when
[linking](#term-linking) the corresponding bytecode.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;String&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Format&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Determined based on &lt;code&gt;type&lt;/code&gt;, see below.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

**Format**

For static value *literals* (e.g. address), value **must** be a *byte
string*

To reference the address of a [Contract
Instance](#term-contract-instance) from the current package the value
should be the name of that contract instance.

-   This value **must** be a valid contract instance name.

-   The chain definition under which the contract instance that this
    link value belongs to must contain this value within its keys.

-   This value **may not** reference the same contract instance that
    this link value belongs to.

To reference a contract instance from a [Package](#term-package) from
somewhere within the dependency tree the value is constructed as
follows.

-   Let `[p1, p2, .. pn]` define a path down the dependency tree.

-   Each of `p1, p2, pn` **must** be valid package names.

-   `p1` **must** be present in keys of the `build_dependencies` for the
    current package.

-   For every `pn` where `n &gt; 1`, `pn` **must** be present in the keys
    of the `build_dependencies` of the package for `pn-1`.

-   The value is represented by the string
    `&lt;p1&gt;:&lt;p2&gt;:&lt;...&gt;:&lt;pn&gt;:&lt;contract-instance&gt;` where all of `&lt;p1&gt;`,
    `&lt;p2&gt;`, `&lt;pn&gt;` are valid package names and `&lt;contract-instance&gt;` is
    a valid [Contract Name](#term-contract-name).

-   The `&lt;contract-instance&gt;` value **must** be a valid [Contract
    Instance Name](#term-contract-instance-name).

-   Within the package of the dependency defined by `&lt;pn&gt;`, all of the
    following must be satisfiable:

    -   There **must** be *exactly* one chain defined under the
        `deployments` key which matches the chain definition that this
        link value is nested under.

    -   The `&lt;contract-instance&gt;` value **must** be present in the keys
        of the matching chain.


### The *Bytecode* Object

A bytecode object has the following key/value pairs.


#### Bytecode: `bytecode`

The `bytecode` field is a string containing the `0x` prefixed
hexadecimal representation of the bytecode.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;String&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Format&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;0x&lt;/code&gt; prefixed hexadecimal.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


#### Link References: `link_references`

The `link_references` field defines the locations in the corresponding
bytecode which require [linking](#term-linking).

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Array&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Format&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;All values &lt;strong&gt;must&lt;/strong&gt; be valid &lt;a href=&quot;#link-reference-object&quot;&gt;Link Reference objects&lt;/a&gt;. See also below.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

**Format**

This field is considered invalid if *any* of the [Link
References](#term-link-reference) are invalid when applied to the
corresponding `bytecode` field, *or* if any of the link references
intersect.

Intersection is defined as two link references which overlap.


#### Link Dependencies: `link_dependencies`

The `link_dependencies` defines the [Link Values](#term-link-value) that
have been used to link the corresponding bytecode.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Array&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Format&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;All values &lt;strong&gt;must&lt;/strong&gt; be valid &lt;a href=&quot;#link-value-object&quot;&gt;Link Value objects&lt;/a&gt;. See also below.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

**Format**

Validation of this field includes the following:

-   Two link value objects **must not** contain any of the same values
    for `offsets`.

-   Each [link value object](#link-value-object) **must** have a
    corresponding [link reference object](#link-reference-object) under
    the `link_references` field.

-   The length of the resolved `value` **must** be equal to the `length`
    of the corresponding [Link Reference](#term-link-reference).


&lt;div id=&quot;package-meta-object&quot;&gt;&lt;/div&gt;

### The *Package Meta* Object

The *Package Meta* object is defined to have the following key/value
pairs.


#### Authors: `authors`

The `authors` field defines a list of human readable names for the
authors of this package. Packages **may** include this field.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Key&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;authors&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Array (String)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


#### License: `license`

The `license` field declares the license under which this package is
released. This value **should** conform to the
[SPDX](https://en.wikipedia.org/wiki/Software_Package_Data_Exchange)
format. Packages **should** include this field.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Key&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;license&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;String&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


#### Description: `description`

The `description` field provides additional detail that may be relevant
for the package. Packages **may** include this field.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Key&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;description&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;String&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


#### Keywords: `keywords`

The `keywords` field provides relevant keywords related to this package.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Key&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;keywords&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;List of Strings&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


#### Links: `links`

The `links` field provides URIs to relevant resources associated with
this package. When possible, authors **should** use the following keys
for the following common resources.

-   `website`: Primary website for the package.

-   `documentation`: Package Documentation

-   `repository`: Location of the project source code.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Key&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;links&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Object (String: String)&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;div id=&quot;contract-type-object&quot;&gt;&lt;/div&gt;

### The *Contract Type* Object

A *Contract Type* object is defined to have the following key/value
pairs.


#### Contract Name: `contract_name`

The `contract_name` field defines the [Contract
Name](#term-contract-name) for this [Contract
Type](#term-contract-type).

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;If the &lt;a href=&quot;#term-contract-name&quot;&gt;Contract Name&lt;/a&gt; and &lt;a href=&quot;#term-contract-alias&quot;&gt;Contract Alias&lt;/a&gt; are not the same.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;String&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Format&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;must&lt;/strong&gt; be a valid &lt;a href=&quot;#term-contract-name&quot;&gt;Contract Name&lt;/a&gt;.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


#### Deployment Bytecode: `deployment_bytecode`

The `deployment_bytecode` field defines the bytecode for this [Contract
Type](#term-contract-type).

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Object&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Format&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;must&lt;/strong&gt; conform to &lt;a href=&quot;#the-bytecode-object&quot;&gt;the Bytecode Object&lt;/a&gt; format.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


#### Runtime Bytecode: `runtime_bytecode`

The `runtime_bytecode` field defines the unlinked `0x`-prefixed runtime
portion of [Bytecode](#term-bytecode) for this [Contract
Type](#term-contract-type).

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Object&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Format&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;must&lt;/strong&gt; conform to &lt;a href=&quot;#the-bytecode-object&quot;&gt;the Bytecode Object&lt;/a&gt; format.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


#### ABI: `abi`

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;List&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Format&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;must&lt;/strong&gt; conform to the &lt;a href=&quot;https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI#json&quot;&gt;Ethereum Contract ABI JSON format&lt;/a&gt;.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


#### Natspec: `natspec`

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Object&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Format&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;The union of the &lt;a href=&quot;https://github.com/ethereum/wiki/wiki/Ethereum-Natural-Specification-Format#user-documentation&quot;&gt;UserDoc&lt;/a&gt; and &lt;a href=&quot;https://github.com/ethereum/wiki/wiki/Ethereum-Natural-Specification-Format#developer-documentation&quot;&gt;DevDoc&lt;/a&gt; formats.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


#### Compiler: `compiler`

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Object&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Format&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;must&lt;/strong&gt; conform to &lt;a href=&quot;#the-compiler-information-object&quot;&gt;the Compiler Information object&lt;/a&gt; format.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;div id=&quot;contract-instance-object&quot;&gt;&lt;/div&gt;

### The *Contract Instance* Object

A **Contract Instance Object** represents a single deployed [Contract
Instance](#term-contract-instance) and is defined to have the following
key/value pairs.


#### Contract Type: `contract_type`

The `contract_type` field defines the [Contract
Type](#term-contract-type) for this [Contract
Instance](#term-contract-instance). This can reference any of the
contract types included in this [Package](#term-package) *or* any of the
contract types found in any of the package dependencies from the
`build_dependencies` section of the [Package
Manifest](#term-package-manifest).

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;String&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Format&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;See Below.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

**Format**

Values for this field **must** conform to *one of* the two formats
herein.

To reference a contract type from this Package, use the format
`&lt;contract-alias&gt;`.

-   The `&lt;contract-alias&gt;` value **must** be a valid [Contract
    Alias](#term-contract-alias).

-   The value **must** be present in the keys of the `contract_types`
    section of this Package.

To reference a contract type from a dependency, use the format
`&lt;package-name&gt;:&lt;contract-alias&gt;`.

-   The `&lt;package-name&gt;` value **must** be present in the keys of the
    `build_dependencies` of this Package.

-   The `&lt;contract-alias&gt;` value **must** be a valid [Contract
    Alias](#term-contract-alias).

-   The resolved package for `&lt;package-name&gt;` must contain the
    `&lt;contract-alias&gt;` value in the keys of the `contract_types`
    section.


#### Address: `address`

The `address` field defines the [Address](#term-address) of the
[Contract Instance](#term-contract-instance).

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;String&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Format&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Hex encoded &lt;code&gt;0x&lt;/code&gt; prefixed Ethereum address matching the regular expression &lt;code&gt;0x[0-9a-fA-F]{40}&lt;/code&gt;.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


#### Transaction: `transaction`

The `transaction` field defines the transaction hash in which this
[Contract Instance](#term-contract-instance) was created.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;String&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Format&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;0x&lt;/code&gt; prefixed hex encoded transaction hash.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


#### Block: `block`

The `block` field defines the block hash in which this the transaction
which created this *contract instance* was mined.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;String&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Format&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;0x&lt;/code&gt; prefixed hex encoded block hash.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;div id=&quot;runtime-bytecode-runtime-bytecode-1&quot;&gt;&lt;/div&gt;

#### Runtime Bytecode: `runtime_bytecode`

The `runtime_bytecode` field defines the runtime portion of bytecode for
this [Contract Instance](#term-contract-instance). When present, the
value from this field supersedes the `runtime_bytecode` from the
[Contract Type](#term-contract-type) for this [Contract
Instance](#term-contract-instance).

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Object&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Format&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;must&lt;/strong&gt; conform to &lt;a href=&quot;#the-bytecode-object&quot;&gt;the Bytecode Object&lt;/a&gt; format.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

Every entry in the `link_references` for this bytecode **must** have a
corresponding entry in the `link_dependencies` section.


#### Compiler: `compiler`

The `compiler` field defines the compiler information that was used
during compilation of this [Contract Instance](#term-contract-instance).
This field **should** be present in all [Contract
Types](#term-contract-type) which include `bytecode` or
`runtime_bytecode`.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Object&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Format&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;strong&gt;must&lt;/strong&gt; conform to the &lt;a href=&quot;#compiler-information-object&quot;&gt;Compiler Information Object&lt;/a&gt; format.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;div id=&quot;compiler-information-object&quot;&gt;&lt;/div&gt;

### The *Compiler Information* Object

The `compiler` field defines the compiler information that was used
during compilation of this [Contract Instance](#term-contract-instance).
This field **should** be present in all contract instances that locally
declare `runtime_bytecode`.

A *Compiler Information* object is defined to have the following
key/value pairs.


#### Name `name`

The `name` field defines which compiler was used in compilation.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Key&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;name&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;String&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


#### Version: `version`

The `version` field defines the version of the compiler. The field
**should** be OS agnostic (OS not included in the string) and take the
form of either the stable version in
[semver](https://semver.org/) format or if built on a
nightly should be denoted in the form of `&lt;semver&gt;-&lt;commit-hash&gt;` ex:
`0.4.8-commit.60cc1668`.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Yes&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Key&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;version&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;String&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


#### Settings: `settings`

The `settings` field defines any settings or configuration that was used
in compilation. For the `&quot;solc&quot;` compiler, this **should** conform to
the [Compiler Input and Output
Description](https://solidity.readthedocs.io/en/latest/using-the-compiler.html#compiler-input-and-output-json-description).

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Required&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;No&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Key&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;settings&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Type&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Object&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


### BIP122 URIs

BIP122 URIs are used to define a blockchain via a subset of the
[BIP-122](https://github.com/bitcoin/bips/blob/master/bip-0122.mediawiki)
spec.

    blockchain://&lt;genesis_hash&gt;/block/&lt;latest confirmed block hash&gt;

The `&lt;genesis hash&gt;` represents the blockhash of the first block on the
chain, and `&lt;latest confirmed block hash&gt;` represents the hash of the
latest block that’s been reliably confirmed (package managers should be
free to choose their desired level of confirmations).


Rationale
=========

The following use cases were considered during the creation of this
specification.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;owned&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;A package which contains contracts which are not meant to be used by themselves but rather as base contracts to provide functionality to other contracts through inheritance.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;transferable&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;A package which has a single dependency.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;standard-token&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;A package which contains a reusable contract.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;safe-math-lib&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;A package which contains deployed instance of one of the package contracts.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;piper-coin&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;A package which contains a deployed instance of a reusable contract from a dependency.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;escrow&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;A package which contains a deployed instance of a local contract which is linked against a deployed instance of a local library.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;wallet&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;A package with a deployed instance of a local contract which is linked against a deployed instance of a library from a dependency.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;wallet-with-send&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;A package with a deployed instance which links against a deep dependency.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

Each use case builds incrementally on the previous one.

A full listing of [Use
Cases](https://ethpm.github.io/ethpm-spec/use-cases.html)
can be found on the hosted version of this specification.


Glossary
==========


&lt;div id=&quot;term-abi&quot;&gt;&lt;/div&gt;

ABI
---

The JSON representation of the application binary interface. See the
official
[specification](https://solidity.readthedocs.io/en/develop/abi-spec.html)
for more information.


&lt;div id=&quot;term-address&quot;&gt;&lt;/div&gt;

Address
-------

A public identifier for an account on a particular chain


&lt;div id=&quot;term-bytecode&quot;&gt;&lt;/div&gt;

Bytecode
--------

The set of EVM instructions as produced by a compiler. Unless otherwise
specified this should be assumed to be hexadecimal encoded, representing
a whole number of bytes, and [prefixed](#term-prefixed) with `0x`.

Bytecode can either be linked or unlinked. (see
[Linking](#term-linking))

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Unlinked Bytecode&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;The hexadecimal representation of a contract’s EVM instructions that contains sections of code that requires &lt;a href=&quot;#term-linking&quot;&gt;linking&lt;/a&gt; for the contract to be functional.&lt;/p&gt;
&lt;p&gt;The sections of code which are unlinked &lt;strong&gt;must&lt;/strong&gt; be filled in with zero bytes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: &lt;code&gt;0x606060405260e06000730000000000000000000000000000000000000000634d536f&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;Linked Bytecode&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;The hexadecimal representation of a contract’s EVM instructions which has had all &lt;a href=&quot;#term-link-reference&quot;&gt;Link References&lt;/a&gt; replaced with the desired &lt;a href=&quot;#term-link-value&quot;&gt;Link Values&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: &lt;code&gt;0x606060405260e06000736fe36000604051602001526040518160e060020a634d536f&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;div id=&quot;term-chain-definition&quot;&gt;&lt;/div&gt;

Chain Definition
----------------

This definition originates from [BIP122
URI](https://github.com/bitcoin/bips/blob/master/bip-0122.mediawiki).

A URI in the format `blockchain://&lt;chain_id&gt;/block/&lt;block_hash&gt;`

-   `chain_id` is the unprefixed hexadecimal representation of the
    genesis hash for the chain.

-   `block_hash` is the unprefixed hexadecimal representation of the
    hash of a block on the chain.

A chain is considered to match a chain definition if the genesis
block hash matches the `chain_id` and the block defined by `block_hash`
can be found on that chain. It is possible for multiple chains to match
a single URI, in which case all chains are considered valid matches


&lt;div id=&quot;term-content-addressable-uri&quot;&gt;&lt;/div&gt;

Content Addressable URI
-----------------------

Any URI which contains a cryptographic hash which can be used to verify
the integrity of the content found at the URI.

The URI format is defined in RFC3986

It is **recommended** that tools support IPFS and Swarm.


&lt;div id=&quot;term-contract-alias&quot;&gt;&lt;/div&gt;

Contract Alias
--------------

This is a name used to reference a specific [Contract
Type](#term-contract-type). Contract aliases **must** be unique within a
single [Package](#term-package).

The contract alias **must** use *one of* the following naming schemes:

-   `&lt;contract-name&gt;`

-   `&lt;contract-name&gt;[&lt;identifier&gt;]`

The `&lt;contract-name&gt;` portion **must** be the same as the [Contract
Name](#term-contract-name) for this contract type.

The `[&lt;identifier&gt;]` portion **must** match the regular expression
`\[[-a-zA-Z0-9]{1,256}]`.


&lt;div id=&quot;term-contract-instance&quot;&gt;&lt;/div&gt;

Contract Instance
-----------------

A contract instance a specific deployed version of a [Contract
Type](#term-contract-type).

All contract instances have an [Address](#term-address) on some specific
chain.


&lt;div id=&quot;term-contract-instance-name&quot;&gt;&lt;/div&gt;

Contract Instance Name
----------------------

A name which refers to a specific [Contract
Instance](#term-contract-instance) on a specific chain from the
deployments of a single [Package](#term-package). This name **must** be
unique across all other contract instances for the given chain. The name
must conform to the regular expression `[a-zA-Z][a-zA-Z0-9_]{0,255}`

In cases where there is a single deployed instance of a given [Contract
Type](#term-contract-type), package managers **should** use the
[Contract Alias](#term-contract-alias) for that contract type for this
name.

In cases where there are multiple deployed instances of a given contract
type, package managers **should** use a name which provides some added
semantic information as to help differentiate the two deployed instances
in a meaningful way.


&lt;div id=&quot;term-contract-name&quot;&gt;&lt;/div&gt;

Contract Name
-------------

The name found in the source code that defines a specific [Contract
Type](#term-contract-type). These names **must** conform to the regular
expression `[a-zA-Z][-a-zA-Z0-9_]{0,255}`.

There can be multiple contracts with the same contract name in a
projects source files.


&lt;div id=&quot;term-contract-type&quot;&gt;&lt;/div&gt;

Contract Type
-------------

Refers to a specific contract in the package source. This term can be
used to refer to an abstract contract, a normal contract, or a library.
Two contracts are of the same contract type if they have the same
bytecode.

Example:

    contract Wallet {
        ...
    }

A deployed instance of the `Wallet` contract would be of type
`Wallet`.


&lt;div id=&quot;term-identifier&quot;&gt;&lt;/div&gt;

Identifier
----------

Refers generally to a named entity in the [Package](#term-package).

A string matching the regular expression `[a-zA-Z][-_a-zA-Z0-9]{0,255}`


&lt;div id=&quot;term-link-reference&quot;&gt;&lt;/div&gt;

Link Reference
--------------

A location within a contract’s bytecode which needs to be linked. A link
reference has the following properties.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;offset&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Defines the location within the bytecode where the link reference begins.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;length&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;Defines the length of the reference.&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;name&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;(optional.) A string to identify the reference&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;div id=&quot;term-link-value&quot;&gt;&lt;/div&gt;

Link Value
----------

A link value is the value which can be inserted in place of a [Link
Reference](#term-link-reference)


&lt;div id=&quot;term-linking&quot;&gt;&lt;/div&gt;

Linking
-------

The act of replacing [Link References](#term-link-reference) with [Link
Values](#term-link-value) within some [Bytecode](#term-bytecode).


&lt;div id=&quot;term-package&quot;&gt;&lt;/div&gt;

Package
-------

Distribution of an application’s source or compiled bytecode along with
metadata related to authorship, license, versioning, et al.

For brevity, the term **Package** is often used metonymously to mean
[Package Manifest](#term-package-manifest).


&lt;div id=&quot;term-package-manifest&quot;&gt;&lt;/div&gt;

Package Manifest
----------------

A machine-readable description of a package (See
[Specification](#package-specification) for information about the format
for package manifests.)


&lt;div id=&quot;term-prefixed&quot;&gt;&lt;/div&gt;

Prefixed
--------

[Bytecode](#term-bytecode) string with leading `0x`.

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Example&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;0xdeadbeef&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;div id=&quot;term-unprefixed&quot;&gt;&lt;/div&gt;

Unprefixed
----------

Not [Prefixed](#term-prefixed).

&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;col style=&quot;width: 50%&quot; /&gt;
&lt;/colgroup&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;p&gt;Example&lt;/p&gt;&lt;/td&gt;
&lt;td&gt;&lt;p&gt;&lt;code&gt;deadbeef&lt;/code&gt;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


Backwards Compatibility
=======================

This specification supports backwards compatibility by use of the
[manifest\_version](#manifest-version) property. This
specification corresponds to version `2` as the value for that field.


Implementations
===============

This submission aims to coincide with development efforts towards
widespread implementation in commonly-used development tools.

The following tools are known to have begun or are nearing completion of
a supporting implementation.

-   [Truffle](https://trufflesuite.com/)

-   [Populus](https://populus.readthedocs.io/en/latest/)

-   [Embark](https://embark.status.im/)

Full support in implementation **may** require [Further
Work](#further-work), specified below.


Further Work
============

This EIP addresses only the data format for package descriptions.
Excluded from the scope of this specification are:

-   Package registry interface definition

-   Tooling integration, or how packages are stored on disk.

These efforts **should** be considered separate, warranting future
dependent EIP submssions.


Acknowledgements
================

The authors of this document would like to thank the original authors of
[EIP-190](/EIPs/EIPS/eip-190),
[ETHPrize](http://ethprize.io/) for their funding
support, all community
[contributors](https://github.com/ethpm/ethpm-spec/graphs/contributors),
and the Ethereum community at large.


Copyright
=========

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 01 Jun 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1123</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1123</guid>
      </item>
    
      <item>
        <title>Standardised DAPP announcements</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-sda-standardised-dapp-announcements/508?u=thunderdeliverer</comments>
        
        <description>## Simple Summary
Standardisation of announcements in DAPPs and services on Ethereum network. This ERC provides proposed mechanics to increase the quality of service provided by DAPP developers and service providers, by setting a framework for announcements. Be it transitioning to a new smart contract or just freezing the service for some reason.

## Abstract
The proposed ERC defines format on how to post announcements about the service as well as how to remove them. It also defines mechanics on posting permissions and human friendly interface.

## Motivation
Currently there are no guidelines on how to notify the users of the service status in the DAPPs. This is especially obvious in ERC20 and it&apos;s derivates. If the service is impeded by any reason it is good practice to have some sort of guidelines on how to announce that to the user. The standardisation would also provide traceability of the service&apos;s status.

## Specification

### Structures

#### Announcer

Stores information about the announcement maker. The `allowedToPost` stores posting permissions and is used for modifiers limiting announcement posting only to authorised entities. The `name` is used for human friendly identifier of the author to be stored.

``` js
struct Announcer{
  bool allowedToPost;
  string name;
}
```


#### Announcement

Stores information about the individual announcement. The human friendly author identifier is stored in `author`. Ethereum address associated with the author is stored in `authorAddress`. The announcement itself is stored in `post`.

``` js
struct Announcement{
  string author;
  address authorAddress;
  string post;
}
```



### Methods
#### the number of announcements

Returns the number of announcements currently active.

OPTIONAL - this method can be used to provide quicker information for the UI, but could also be retrieved from `numberOfMessages` variable.

``` js
function theNumberOfAnnouncements() public constant returns(uint256 _numberOfAnnouncements)
```


#### read posts

Returns the specified announcement as well as human friendly poster identificator (name or nickname).

``` js
function readPosts(uint256 _postNumber) public constant returns(string _author, string _post)
```


#### give posting permission

Sets posting permissions of the address `_newAnnouncer` to `_postingPrivileges` and can also be used to revoke those permissions. The `_posterName` is human friendly author identificator used in the announcement data.

``` js
function givePostingPermission(address _newAnnouncer, bool _postingPrivileges, string _posterName) public onlyOwner returns(bool success)
```


#### can post

Checks if the entity that wants to post an announcement has the posting privilieges.

``` js
modifier canPost{
 require(posterData[msg.sender].allowedToPost);
 _;
}
```


#### post announcement

Lets user post announcements, but only if they have their posting privileges set to `true`. The announcement is sent in `_message` variable.

``` js
function postAnnouncement(string _message) public canPost
```


#### remove announcement

Removes an announcement with `_messageNumber` announcement identifier and rearranges the mapping so there are no empty slots. The `_removalReason` is used to update users if the issue that caused the announcement is resolved or what are the next steps from the service provider / DAPP development team.

``` js
function removeAnnouncement(uint256 _messageNumber, string _removalReason) public
```



### Events

#### New announcement

MUST trigger when new announcement is created.

Every time there is a new announcement it should be advertised in this event. It holds the information about author `author` and the announcement istelf `message`.

``` js
event NewAnnouncement(string author, string message)
```


#### Removed announcement

MUST trigger when an announcement is removed.

Every time an announcement is removed it should be advertised in this event. It holds the information about author `author`, the announcement itself `message`, the reason for removal or explanation of the solution `reason` and the address of the entity that removed the announcement `remover`.

``` js
event RemovedAnnouncement(string author, string message, string reason, address remover);
```

## Rationale
The proposed solution was designed with UX in mind . It provides mechanics that serve to present the announcements in the user friendly way. It is meant to be deployed as a Solidity smart contract on Ethereum network.

## Test Cases
The proposed version is deployed on Ropsten testnet all of the information can be found [here](https://ropsten.etherscan.io/address/0xb04f67172b9733837e59ebaf03d277279635c8e6#readContract).

## Implementation

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 31 May 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1129</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1129</guid>
      </item>
    
      <item>
        <title>Extending ERC20 with token locking capability</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1132</comments>
        
        <description>## Simple Summary

An extension to the ERC20 standard with methods for time-locking of tokens within a contract.

## Abstract

This proposal provides basic functionality to time-lock tokens within an ERC20 smart contract for multiple utilities without the need of transferring tokens to an external escrow smart contract.  It also allows fetching balance of locked and transferable tokens. 

Time-locking can also be achieved via staking (#900), but that requires transfer of tokens to an escrow contract / stake manager, resulting in the following six concerns: 

1. additional trust on escrow contract / stake manager 
2. additional approval process for token transfer
3. increased ops costs due to gas requirements in transfers
4. tough user experience as the user needs to claim the amount back from external escrows 
5. inability for the user to track their true token balance / token activity 
6. inability for the user to utilize their locked tokens within the token ecosystem.

## Motivation

dApps often require tokens to be time-locked against transfers for letting members 1) adhere to vesting schedules and 2) show skin in the game to comply with the underlying business process. I realized this need while building Nexus Mutual and GovBlocks. 

In [Nexus Mutual](https://nexusmutual.io), claim assessors are required to lock their tokens before passing a vote for claims assessment. This is important as it ensures assessors’ skin in the game. The need here was that once a claim assessor locks his tokens for ‘n’ days, he should be able to cast multiple votes during that period of ‘n’ days, which is not feasible with staking mechanism.  There are other scenarios like skills/identity verification or participation in gamified token curated registries where time-locked tokens are required as well. 

In [GovBlocks](https://govblocks.io), I wanted to allow dApps to lock member tokens for governance, while still allowing members to use those locked tokens for other activities within the dApp business. This is also the case with DGX governance model where they’ve proposed quarterly token locking for participation in governance activities of DGX. 

In addition to locking functionality, I have proposed a `Lock()` and `Unlock()` event, just like the `Transfer()` event , to track token lock and unlock status. From token holder’s perspective, it gets tough to manage token holdings if certain tokens are transferred to another account for locking, because whenever `balanceOf()` queries are triggered on token holder’s account – the result does not include locked tokens. A `totalBalanceOf()` function intends to solve this problem.  

The intention with this proposal is to enhance the ERC20 standard with token-locking capability so that dApps can time-lock tokens of the members without having to transfer tokens to an escrow / stake manager and at the same time allow members to use the locked tokens for multiple utilities.

## Specification

I’ve extended the ERC20 interface with the following enhancements:

### Locking of tokens
```solidity
/**
  * @dev Locks a specified amount of tokens against an address,
  *      for a specified reason and time
  * @param _reason The reason to lock tokens
  * @param _amount Number of tokens to be locked
  * @param _time Lock time in seconds
  */
function lock(bytes32 _reason, uint256 _amount, uint256 _time) public returns (bool)
```

### Fetching number of tokens locked under each utility
```solidity
/**
  * @dev Returns tokens locked for a specified address for a
  *      specified reason
  *
  * @param _of The address whose tokens are locked
  * @param _reason The reason to query the lock tokens for
  */
   tokensLocked(address _of, bytes32 _reason) view returns (uint256 amount)
```

### Fetching number of tokens locked under each utility at a future timestamp
```solidity
/**
  * @dev Returns tokens locked for a specified address for a
  *      specified reason at a specific time
  *
  * @param _of The address whose tokens are locked
  * @param _reason The reason to query the lock tokens for
  * @param _time The timestamp to query the lock tokens for
  */
  function tokensLockedAtTime(address _of, bytes32 _reason, uint256 _time) public view returns (uint256 amount)
```

### Fetching number of tokens held by an address
```solidity
/**
  * @dev @dev Returns total tokens held by an address (locked + transferable)
  * @param _of The address to query the total balance of
  */
function totalBalanceOf(address _of)  view returns (uint256 amount)
```

### Extending lock period
```solidity
/**
  * @dev Extends lock for a specified reason and time
  * @param _reason The reason to lock tokens
  * @param _time Lock extension time in seconds
  */
  function extendLock(bytes32 _reason, uint256 _time) public returns (bool)
```

### Increasing number of tokens locked
```solidity
/**
  * @dev Increase number of tokens locked for a specified reason
  * @param _reason The reason to lock tokens
  * @param _amount Number of tokens to be increased
  */
  function increaseLockAmount(bytes32 _reason, uint256 _amount) public returns (bool)
```
### Fetching number of unlockable tokens under each utility
```solidity
/**
  * @dev Returns unlockable tokens for a specified address for a specified reason
  * @param _of The address to query the unlockable token count of
  * @param _reason The reason to query the unlockable tokens for
  */
  function tokensUnlockable(address _of, bytes32 _reason) public view returns (uint256 amount)
 ```    
### Fetching number of unlockable tokens
```solidity
/**
  * @dev Gets the unlockable tokens of a specified address
  * @param _of The address to query the unlockable token count of
  */
  function getUnlockableTokens(address _of) public view returns (uint256 unlockableTokens)
```
### Unlocking tokens
```solidity
/**
  * @dev Unlocks the unlockable tokens of a specified address
  * @param _of Address of user, claiming back unlockable tokens
  */
  function unlock(address _of) public returns (uint256 unlockableTokens)
```

### Lock event recorded in the token contract
`event Locked(address indexed _of, uint256 indexed _reason, uint256 _amount, uint256 _validity)`

### Unlock event recorded in the token contract
`event Unlocked(address indexed _of, uint256 indexed _reason, uint256 _amount)`

## Test Cases

Test cases are available at [https://github.com/nitika-goel/lockable-token](https://github.com/nitika-goel/lockable-token).

## Implementation

- Complete implementation available at https://github.com/nitika-goel/lockable-token
- [GovBlocks](https://govblocks.io) Project specific implementation available at https://github.com/somish/govblocks-protocol/blob/Locking/contracts/GBTStandardToken.sol

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 03 Jun 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1132</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1132</guid>
      </item>
    
      <item>
        <title>Transient storage opcodes</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-transient-storage-opcodes/553</comments>
        
        <description>## Abstract

This proposal introduces transient storage opcodes, which manipulate state that behaves identically to storage, except that transient storage is discarded after every transaction, and `TSTORE` is not subject to the gas stipend check as defined in [EIP-2200](/EIPs/EIPS/eip-2200). In other words, the values of transient storage are never deserialized from storage or serialized to storage. Thus transient storage is cheaper since it never requires disk access. Transient storage is accessible to smart contracts via 2 new opcodes, `TLOAD` and `TSTORE`, where “T” stands for &quot;transient:&quot;

```
TLOAD  (0x5c)
TSTORE (0x5d)
```

## Motivation

Running a transaction in Ethereum can generate multiple nested frames of execution, each created by `CALL` (or similar) instructions. Contracts can be re-entered during the same transaction, in which case there are more than one frame belonging to one contract. Currently, these frames can communicate in two ways: via inputs/outputs passed via `CALL` instructions, and via storage updates. If there is an intermediate frame belonging to another untrusted contract, communication via inputs/outputs is not secure. Notable example is a reentrancy lock which cannot rely on the intermediate frame to pass through the state of the lock. Communication via storage (`SSTORE`/`SLOAD`) is costly. Transient storage is a dedicated and gas efficient solution to the problem of inter frame communication.

Storage refunds accumulated due to inter frame communication are also limited to 20% of gas spent by a transaction due to [EIP-3529](/EIPs/EIPS/eip-3529) (introduced in the London hard fork). This greatly reduces the refunds for transiently-set storage slots in otherwise low-cost transactions. For example, in order to receive the full refund of one re-entrancy lock, the transaction must spend ~80k gas on other operations.

Language support could be added in relatively easy way. For example, in Solidity, a qualifier `transient` can be introduced (similar to the existing qualifiers `memory` and `storage`, and Java&apos;s own `transient` keyword with a similar meaning). Since the addressing scheme of `TSTORE` and `TLOAD` is the same as for `SSTORE` and `SLOAD`, code generation routines that exist for storage variables, can be easily generalised to also support transient storage.

Potential use cases enabled or improved by this EIP include:

1. Reentrancy locks
2. On-chain computable CREATE2 addresses: constructor arguments are read from the factory contract instead of passed as part of init code hash
3. Single transaction [ERC-20](/EIPs/EIPS/eip-20) approvals, e.g. `#temporaryApprove(address spender, uint256 amount)`
4. Fee-on-transfer contracts: pay a fee to a token contract to unlock transfers for the duration of a transaction
5. &quot;Till&quot; pattern: allowing users to perform all actions as part of a callback, and checking the &quot;till&quot; is balanced at the end
6. Proxy call metadata: pass additional metadata to an implementation contract without using calldata, e.g. values of immutable proxy constructor arguments  

These opcodes are more efficient to execute than the `SSTORE` and `SLOAD` opcodes because the original value never needs to be loaded from storage (i.e. is always 0). The gas accounting rules are also simpler, since no refunds are required.

## Specification

Two new opcodes are added to EVM, `TLOAD` (`0x5c`) and `TSTORE` (`0x5d`). (Note that previous drafts of this EIP specified the values `0xb3` and `0xb4` for `TLOAD` and `TSTORE` respectively to avoid conflict with other EIPs. The conflict has since been removed.)

They use the same arguments on stack as `SLOAD` (`0x54`) and `SSTORE` (`0x55`).

`TLOAD` pops one 32-byte word from the top of the stack, treats this value as the address, fetches 32-byte word from the transient storage at that address, and pushes the value on top of the stack.

`TSTORE` pops two 32-byte words from the top of the stack. The word on the top is the address, and the next is the value. `TSTORE` saves the value at the given address in the transient storage.

Addressing is the same as `SLOAD` and `SSTORE`. i.e. each 32-byte address points to a unique 32-byte word.

Gas cost for `TSTORE` is the same as a warm `SSTORE` of a dirty slot (i.e. original value is not new value and is not current value, currently 100 gas), and gas cost of `TLOAD` is the same as a hot `SLOAD` (value has been read before, currently 100 gas). Gas cost cannot be on par with memory access due to transient storage&apos;s interactions with reverts.

All values in transient storage are discarded at the end of the transaction.

Transient storage is private to the contract that owns it, in the same way as persistent storage. Only owning contract frames may access their transient storage. And when they do, all the frames access the same transient store, in the same way as persistent storage, but unlike memory.

When transient storage is used in the context of `DELEGATECALL` or `CALLCODE`, then the owning contract of the transient storage is the contract that issued `DELEGATECALL` or `CALLCODE` instruction (the caller) as with persistent storage. When transient storage is used in the context of `CALL` or `STATICCALL`, then the owning contract of the transient storage is the contract that is the target of the `CALL` or `STATICCALL` instruction (the callee).

If a frame reverts, all writes to transient storage that took place between entry to the frame and the return are reverted, including those that took place in inner calls.  This mimics the behavior of persistent storage.

If the `TSTORE` opcode is called within the context of a `STATICCALL`, it will result in an exception instead of performing the modification. `TLOAD` is allowed within the context of a `STATICCALL`.

The behavior of the opcodes for transient storage differs from the opcodes for storage in that `TSTORE` does not require _gasleft_, as defined in [EIP-2200](/EIPs/EIPS/eip-2200), to be less than or equal to the gas stipend (currently 2,300).

## Rationale

Another option to solve the problem of inter-frame communication is repricing the `SSTORE` and `SLOAD` opcodes to be cheaper for the transient storage use case. This has already been done as of [EIP-2200](/EIPs/EIPS/eip-2200). However, [EIP-3529](/EIPs/EIPS/eip-3529) reduced the maximum refund to only 20% of the transaction gas cost, which means the use of transient storage is severely limited.

Another approach is to keep the refund counter for transient storage separate from the refund counter for other storage uses, and remove the refund cap for transient storage. However, that approach is more complex to implement and understand. For example, the 20% refund cap must be applied to the gas used _after_ subtracting the uncapped gas refund. Otherwise, the refund amount available subject to the 20% refund cap could be increased by executing transient storage writes. Thus it is preferable to have a separate mechanism that does not interact with the refund counter. Future hard forks can remove the complex refund behavior meant to support the transient storage use case, encouraging migration to contracts that are more efficient for the Ethereum clients to execute.

There is a known objection to the word-addressed storage-like interface of the `TSTORE` and `TLOAD` opcodes since transient storage is more akin to memory than storage in lifecycle. A byte-addressed memory-like interface is another option. The storage-like word-addressed interface is preferred due to the usefulness of mappings in combination with the transaction-scoped memory region. Often times, you will need to keep transient state with arbitrary keys, such as in the [ERC-20](/EIPs/EIPS/eip-20) temporary approval use case which uses a mapping of `(owner, spender)` to `allowance`. Mappings are difficult to implement using linear memory, and linear memory must also have dynamic gas costs. It is also more complicated to handle reverts with a linear memory. It is possible to have a memory-like interface while the underlying implementation uses a map to allow for storage in arbitrary offsets, but this would result in a third memory-storage hybrid interface that would require new code paths in compilers.

Some think that a unique transaction identifier may obviate the need for transient storage as described in this EIP. This is a misconception: a transaction identifier used in combination with regular storage has all the same issues that motivate this EIP. The two features are orthogonal.  

Relative cons of this transient storage EIP:

- Does not address transient usages of storage in existing contracts
- New code in the clients
- New concept for the yellow paper (more to update)

Relative pros of this transient storage EIP:

- Transient storage opcodes are considered separately in protocol upgrades and not inadvertently broken (e.g. [EIP-3529](/EIPs/EIPS/eip-3529))
- Clients do not need to load the original value
- No upfront gas cost to account for non-transient writes
- Does not change the semantics of the existing operations
- No need to clear storage slots after usage
- Simpler gas accounting rules
- Future storage designs (e.g. Verkle tree) do not need to account for transient storage refunds

## Backwards Compatibility

This EIP requires a hard fork to implement.

Since this EIP does not change behavior of any existing opcodes, it is backwards compatible with all existing smart contracts.

## Test Cases

A test suite for this EIP can be found [here](https://github.com/ethereum/execution-spec-tests/tree/1983444bbe1a471886ef7c0e82253ffe2a4053e1/tests/cancun/eip1153_tstore).

## Reference Implementation

Because the transient storage must behave almost identically to storage within the context of a single transaction with regards to revert behavior, it is necessary to be able to revert to a previous state of transient storage within a transaction. At the same time reverts are exceptional cases and loads, stores and returns should be cheap.

A map of current state plus a journal of all changes and a list of checkpoints is recommended. This has the following time complexities:

- On entry to a call frame, a call marker is added to the list - `O(1)`
- New values are written to the current state, and the previous value is written to the journal - `O(1)`
- When a call exits successfully, the marker to the journal index of when that call was entered is discarded - `O(1)`
- On revert all entries are reverted up to the last checkpoint, in reverse - `O(N)` where `N` = number of journal entries since last checkpoint

```typescript
interface JournalEntry {
    addr: string
    key: string
    prevValue: string
}

type Journal = JournalEntry[]

type Checkpoints = Journal[&apos;length&apos;][]

interface Current {
    [addr: string]: {
        [key: string]: string
    }
}

const EMPTY_VALUE = &apos;0x0000000000000000000000000000000000000000000000000000000000000000&apos;

class TransientStorage {
    /**
     * The current state of transient storage.
     */
    private current: Current = {}
    /**
     * All changes are written to the journal. On revert, we apply the changes in reverse to the last checkpoint.
     */
    private journal: Journal = []
    /**
     * The length of the journal at the time of each checkpoint
     */
    private checkpoints: Checkpoints = [0]

    /**
     * Returns the current value of the given contract address and key
     * @param addr The address of the contract
     * @param key The key of transient storage for the address
     */
    public get(addr: string, key: string): string {
        return this.current[addr]?.[key] ?? EMPTY_VALUE
    }

    /**
     * Set the current value in the map
     * @param addr the address of the contract for which the key is being set
     * @param key the slot to set for the address
     * @param value the new value of the slot to set
     */
    public put(addr: string, key: string, value: string) {
        this.journal.push({
            addr,
            key,
            prevValue: this.get(addr, key),
        })

        this.current[addr] = this.current[addr] ?? {}
        this.current[addr][key] = value;
    }

    /**
     * Commit all the changes since the last checkpoint
     */
    public commit(): void {
        if (this.checkpoints.length === 0) throw new Error(&apos;Nothing to commit&apos;)
        this.checkpoints.pop() // The last checkpoint is discarded.
    }

    /**
     * To be called whenever entering a new context. If revert is called after checkpoint, all changes made after the latest checkpoint are reverted.
     */
    public checkpoint(): void {
        this.checkpoints.push(this.journal.length)
    }

    /**
     * Revert transient storage to the state from the last call to checkpoint
     */
    public revert() {
        const lastCheckpoint = this.checkpoints.pop()
        if (typeof lastCheckpoint === &apos;undefined&apos;) throw new Error(&apos;Nothing to revert&apos;)

        for (let i = this.journal.length - 1; i &gt;= lastCheckpoint; i--) {
            const {addr, key, prevValue} = this.journal[i]
            // we can assume it exists, since it was written in the journal
            this.current[addr][key] = prevValue
        }
        this.journal.splice(lastCheckpoint, this.journal.length - lastCheckpoint)
    }
}
```

The worst case time complexity can be produced by writing the maximum number of keys that can fit in one block, and then reverting. In this case, the client is required to do twice as many writes to apply all the entries in the journal. However, the same case applies to the state journaling implementation of existing clients, and cannot be DOS&apos;d with the following code.

```solidity
pragma solidity =0.8.13;

contract TryDOS {
    uint256 slot;

    constructor() {
        slot = 1;
    }

    function tryDOS() external {
        uint256 i = 1;
        while (gasleft() &gt; 5000) {
            unchecked {
                slot = i++;
            }
        }
        revert();
    }
}
```

## Security Considerations

`TSTORE` presents a new way to allocate memory on a node with linear cost. In other words, each TSTORE allows the developer to store 32 bytes for 100 gas, excluding any other required operations to prepare the stack. Given 30 million gas, the maximum amount of memory that can be allocated using TSTORE is:

```
30M gas * 1 TSTORE / 100 gas * 32 bytes / 1 TSTORE * 1MB / 2^20 bytes ~= 9.15MB
```

Given the same amount of gas, the maximum amount of memory that can be allocated in a single context by `MSTORE` is ~3.75MB:

```
30M gas = 3x + x^2 / 512 =&gt; x = ~123,169 32-byte words
~123,169 words * 32 bytes/word * 1MB / 2^20 bytes = 3.75MB
```

However, if you only spend 1M gas allocating memory in each context, and make calls to reset the memory expansion cost, you can allocate ~700KB per million gas, for a total of ~20MB of memory allocated:

```
1M gas = 3x + x^2 / 512 =&gt; x = ~21,872 32-byte words
30M gas * ~21,872 words / 1M gas * 32 bytes/word * 1MB / 2^20 bytes = ~20MB
```

Smart contract developers should understand the lifetime of transient storage variables before use. Because transient storage is automatically cleared at the end of the transaction, smart contract developers may be tempted to avoid clearing slots as part of a call in order to save gas. However, this could prevent further interactions with the contract in the same transaction (e.g. in the case of re-entrancy locks) or cause other bugs, so smart contract developers should be careful to _only_ leave transient storage slots with nonzero values when those slots are intended to be used by future calls within the same transaction. Otherwise, these opcodes behave exactly the same as `SSTORE` and `SLOAD`, so all the usual security considerations apply especially in regard to reentrancy risk.

Smart contract developers may also be tempted to use transient storage as an alternative to in-memory mappings. They should be aware that transient storage is not discarded when a call returns or reverts, as is memory, and should prefer memory for these use cases so as not to create unexpected behavior on reentrancy in the same transaction. The necessarily high cost of transient storage over memory should already discourage this usage pattern. Most usages of in-memory mappings can be better implemented with key-sorted lists of entries, and in-memory mappings are rarely required in smart contracts (i.e. the author knows of no known use cases in production).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 15 Jun 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1153</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1153</guid>
      </item>
    
      <item>
        <title>Oracle Interface</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1161</comments>
        
        <description>## Simple Summary
A standard interface for oracles.

## Abstract
In order for ethereum smart contracts to interact with off-chain systems, oracles must be used. These oracles report values which are normally off-chain, allowing smart contracts to react to the state of off-chain systems. A distinction and a choice is made between push and pull based oracle systems. Furthermore, a standard interface for oracles is described here, allowing different oracle implementations to be interchangeable.

## Motivation
The Ethereum ecosystem currently has many different oracle implementations available, but they do not provide a unified interface. Smart contract systems would be locked into a single set of oracle implementations, or they would require developers to write adapters/ports specific to the oracle system chosen in a given project.

Beyond naming differences, there is also the issue of whether or not an oracle report-resolving transaction _pushes_ state changes by calling affected contracts, or changes the oracle state allowing dependent contracts to _pull_ the updated value from the oracle. These differing system semantics could introduce inefficiencies when adapting between them.

Ultimately, the value in different oracle systems comes from their underlying resolution mechanics, and points where these systems are virtually identical should be standardized.

These oracles may be used for answering questions about &quot;real-world events&quot;, where each ID can be correlated with a specification of a question and its answers (so most likely for prediction markets, basically).

Another use case could be for decision-making processes, where the results given by the oracle represent decisions made by the oracle (e.g. futarchies). DAOs may require their use in decision making processes.

Both the ID and the results are intentionally unstructured so that things like time series data (via splitting the ID) and different sorts of results (like one of a few, any subset of up to 256, or some value in a range with up to 256 bits of granularity) can be represented.

## Specification

&lt;dl&gt;
  &lt;dt&gt;Oracle&lt;/dt&gt;
  &lt;dd&gt;An entity which reports data to the blockchain.&lt;/dd&gt;

  &lt;dt&gt;Oracle consumer&lt;/dt&gt;
  &lt;dd&gt;A smart contract which receives data from an oracle.&lt;/dd&gt;

  &lt;dt&gt;ID&lt;/dt&gt;
  &lt;dd&gt;A way of indexing the data which an oracle reports. May be derived from or tied to a question for which the data provides the answer.&lt;/dd&gt;

  &lt;dt&gt;Result&lt;/dt&gt;
  &lt;dd&gt;Data associated with an id which is reported by an oracle. This data oftentimes will be the answer to a question tied to the id. Other equivalent terms that have been used include: answer, data, outcome.&lt;/dd&gt;

  &lt;dt&gt;Report&lt;/dt&gt;
  &lt;dd&gt;A pair (ID, result) which an oracle sends to an oracle consumer.&lt;/dd&gt;
&lt;/dl&gt;

```solidity
interface OracleConsumer {
    function receiveResult(bytes32 id, bytes result) external;
}
```

`receiveResult` MUST revert if the `msg.sender` is not an oracle authorized to provide the `result` for that `id`.

`receiveResult` MUST revert if `receiveResult` has been called with the same `id` before.

`receiveResult` MAY revert if the `id` or `result` cannot be handled by the consumer.

Consumers MUST coordinate with oracles to determine how to encode/decode results to and from `bytes`. For example, `abi.encode` and `abi.decode` may be used to implement a codec for results in Solidity. `receiveResult` SHOULD revert if the consumer receives a unexpected result format from the oracle.

The oracle can be any Ethereum account.

## Rationale
The specs are currently very similar to what is implemented by ChainLink (which can use any arbitrarily-named callback) and Oraclize (which uses `__callback`).

With this spec, the oracle _pushes_ state to the consumer, which must react accordingly to the updated state. An alternate _pull_-based interface can be prescribed, as follows:

### Alternate Pull-based Interface
Here are alternate specs loosely based on Gnosis prediction market contracts v1. Reality Check also exposes a similar endpoint (`getFinalAnswer`).

```solidity
interface Oracle {
    function resultFor(bytes32 id) external view returns (bytes result);
}
```

`resultFor` MUST revert if the result for an `id` is not available yet.

`resultFor` MUST return the same result for an `id` after that result is available.

### Push vs Pull
Note that push-based interfaces may be adapted into pull-based interfaces. Simply deploy an oracle consumer which stores the result received and implements `resultFor` accordingly.

Similarly, every pull-based system can be adapted into a push-based system: just add a method on the oracle smart contract which takes an oracle consumer address and calls `receiveResult` on that address.

In both cases, an additional transaction would have to be performed, so the choice to go with push or pull should be based on the dominant use case for these oracles.

In the simple case where a single account has the authority to decide the outcome of an oracle question, there is no need to deploy an oracle contract and store the outcome on that oracle contract. Similarly, in the case where the outcome comes down to a vote, existing multisignature wallets can be used as the authorized oracle.

#### Multiple Oracle Consumers
In the case that many oracle consumers depend on a single oracle result and all these consumers expect the result to be pushed to them, the push and pull adaptations mentioned before may be combined if the pushing oracle cannot be trusted to send the same result to every consumer (in a sense, this forwards the trust to the oracle adaptor implementation).

In a pull-based system, each of the consumers would have to be called to pull the result from the oracle contract, but in the proposed push-based system, the adapted oracle would have to be called to push the results to each of the consumers.

Transaction-wise, both systems are roughly equivalent in efficiency in this scenario, but in the push-based system, there&apos;s a need for the oracle consumers to store the results again, whereas in the pull-based system, the consumers may continue to refer to the oracle for the results. Although this may be somewhat less efficient, requiring the consumers to store the results can also provide security guarantees, especially with regards to result immutability.

#### Result Immutability
In both the proposed specification and the alternate specification, results are immutable once they are determined. This is due to the expectation that typical consumers will require results to be immutable in order to determine a resulting state consistently. With the proposed push-based system, the consumer enforces the result immutability requirement, whereas in the alternate pull-based system, either the oracle would have to be trusted to implement the spec correctly and enforce the immutability requirement, or the consumer would also have to handle result immutability.

For data which mutates over time, the `id` field may be structured to specify &quot;what&quot; and &quot;when&quot; for the data (using 128 bits to specify &quot;when&quot; is still safe for many millennia).

## Implementation

* [Tidbit](https://github.com/levelkdev/tidbit) tracks this EIP.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 13 Jun 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1154</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1154</guid>
      </item>
    
      <item>
        <title>Multi Token Standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1155</comments>
        
        <description>## Simple Summary

A standard interface for contracts that manage multiple token types. A single deployed contract may include any combination of fungible tokens, non-fungible tokens or other configurations (e.g. semi-fungible tokens).

## Abstract

This standard outlines a smart contract interface that can represent any number of fungible and non-fungible token types. Existing standards such as ERC-20 require deployment of separate contracts per token type. The ERC-721 standard&apos;s token ID is a single non-fungible index and the group of these non-fungibles is deployed as a single contract with settings for the entire collection. In contrast, the ERC-1155 Multi Token Standard allows for each token ID to represent a new configurable token type, which may have its own metadata, supply and other attributes.

The `_id` argument contained in each function&apos;s argument set indicates a specific token or token type in a transaction.

## Motivation

Tokens standards like ERC-20 and ERC-721 require a separate contract to be deployed for each token type or collection. This places a lot of redundant bytecode on the Ethereum blockchain and limits certain functionality by the nature of separating each token contract into its own permissioned address. With the rise of blockchain games and platforms like Enjin Coin, game developers may be creating thousands of token types, and a new type of token standard is needed to support them. However, ERC-1155 is not specific to games and many other applications can benefit from this flexibility.

New functionality is possible with this design such as transferring multiple token types at once, saving on transaction costs. Trading (escrow / atomic swaps) of multiple tokens can be built on top of this standard and it removes the need to &quot;approve&quot; individual token contracts separately. It is also easy to describe and mix multiple fungible or non-fungible token types in a single contract.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

**Smart contracts implementing the ERC-1155 standard MUST implement all of the functions in the `ERC1155` interface.**

**Smart contracts implementing the ERC-1155 standard MUST implement the ERC-165 `supportsInterface` function and MUST return the constant value `true` if `0xd9b67a26` is passed through the `interfaceID` argument.**

```solidity
pragma solidity ^0.5.9;

/**
    @title ERC-1155 Multi Token Standard
    @dev See https://eips.ethereum.org/EIPS/eip-1155
    Note: The ERC-165 identifier for this interface is 0xd9b67a26.
 */
interface ERC1155 /* is ERC165 */ {
    /**
        @dev Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see &quot;Safe Transfer Rules&quot; section of the standard).
        The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender).
        The `_from` argument MUST be the address of the holder whose balance is decreased.
        The `_to` argument MUST be the address of the recipient whose balance is increased.
        The `_id` argument MUST be the token type being transferred.
        The `_value` argument MUST be the number of tokens the holder balance is decreased by and match what the recipient balance is increased by.
        When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address).
        When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address).        
    */
    event TransferSingle(address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _value);

    /**
        @dev Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see &quot;Safe Transfer Rules&quot; section of the standard).      
        The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender).
        The `_from` argument MUST be the address of the holder whose balance is decreased.
        The `_to` argument MUST be the address of the recipient whose balance is increased.
        The `_ids` argument MUST be the list of tokens being transferred.
        The `_values` argument MUST be the list of number of tokens (matching the list and order of tokens specified in _ids) the holder balance is decreased by and match what the recipient balance is increased by.
        When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address).
        When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address).                
    */
    event TransferBatch(address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _values);

    /**
        @dev MUST emit when approval for a second party/operator address to manage all tokens for an owner address is enabled or disabled (absence of an event assumes disabled).        
    */
    event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);

    /**
        @dev MUST emit when the URI is updated for a token ID.
        URIs are defined in RFC 3986.
        The URI MUST point to a JSON file that conforms to the &quot;ERC-1155 Metadata URI JSON Schema&quot;.
    */
    event URI(string _value, uint256 indexed _id);

    /**
        @notice Transfers `_value` amount of an `_id` from the `_from` address to the `_to` address specified (with safety call).
        @dev Caller must be approved to manage the tokens being transferred out of the `_from` account (see &quot;Approval&quot; section of the standard).
        MUST revert if `_to` is the zero address.
        MUST revert if balance of holder for token `_id` is lower than the `_value` sent.
        MUST revert on any other error.
        MUST emit the `TransferSingle` event to reflect the balance change (see &quot;Safe Transfer Rules&quot; section of the standard).
        After the above conditions are met, this function MUST check if `_to` is a smart contract (e.g. code size &gt; 0). If so, it MUST call `onERC1155Received` on `_to` and act appropriately (see &quot;Safe Transfer Rules&quot; section of the standard).        
        @param _from    Source address
        @param _to      Target address
        @param _id      ID of the token type
        @param _value   Transfer amount
        @param _data    Additional data with no specified format, MUST be sent unaltered in call to `onERC1155Received` on `_to`
    */
    function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) external;

    /**
        @notice Transfers `_values` amount(s) of `_ids` from the `_from` address to the `_to` address specified (with safety call).
        @dev Caller must be approved to manage the tokens being transferred out of the `_from` account (see &quot;Approval&quot; section of the standard).
        MUST revert if `_to` is the zero address.
        MUST revert if length of `_ids` is not the same as length of `_values`.
        MUST revert if any of the balance(s) of the holder(s) for token(s) in `_ids` is lower than the respective amount(s) in `_values` sent to the recipient.
        MUST revert on any other error.        
        MUST emit `TransferSingle` or `TransferBatch` event(s) such that all the balance changes are reflected (see &quot;Safe Transfer Rules&quot; section of the standard).
        Balance changes and events MUST follow the ordering of the arrays (_ids[0]/_values[0] before _ids[1]/_values[1], etc).
        After the above conditions for the transfer(s) in the batch are met, this function MUST check if `_to` is a smart contract (e.g. code size &gt; 0). If so, it MUST call the relevant `ERC1155TokenReceiver` hook(s) on `_to` and act appropriately (see &quot;Safe Transfer Rules&quot; section of the standard).                      
        @param _from    Source address
        @param _to      Target address
        @param _ids     IDs of each token type (order and length must match _values array)
        @param _values  Transfer amounts per token type (order and length must match _ids array)
        @param _data    Additional data with no specified format, MUST be sent unaltered in call to the `ERC1155TokenReceiver` hook(s) on `_to`
    */
    function safeBatchTransferFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external;

    /**
        @notice Get the balance of an account&apos;s tokens.
        @param _owner  The address of the token holder
        @param _id     ID of the token
        @return        The _owner&apos;s balance of the token type requested
     */
    function balanceOf(address _owner, uint256 _id) external view returns (uint256);

    /**
        @notice Get the balance of multiple account/token pairs
        @param _owners The addresses of the token holders
        @param _ids    ID of the tokens
        @return        The _owner&apos;s balance of the token types requested (i.e. balance for each (owner, id) pair)
     */
    function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) external view returns (uint256[] memory);

    /**
        @notice Enable or disable approval for a third party (&quot;operator&quot;) to manage all of the caller&apos;s tokens.
        @dev MUST emit the ApprovalForAll event on success.
        @param _operator  Address to add to the set of authorized operators
        @param _approved  True if the operator is approved, false to revoke approval
    */
    function setApprovalForAll(address _operator, bool _approved) external;

    /**
        @notice Queries the approval status of an operator for a given owner.
        @param _owner     The owner of the tokens
        @param _operator  Address of authorized operator
        @return           True if the operator is approved, false if not
    */
    function isApprovedForAll(address _owner, address _operator) external view returns (bool);
}
```

### ERC-1155 Token Receiver

**Smart contracts MUST implement all of the functions in the `ERC1155TokenReceiver` interface to accept transfers. See &quot;Safe Transfer Rules&quot; for further detail.**

**Smart contracts MUST implement the ERC-165 `supportsInterface` function and signify support for the `ERC1155TokenReceiver` interface to accept transfers. See &quot;ERC1155TokenReceiver ERC-165 rules&quot; for further detail.**

```solidity
pragma solidity ^0.5.9;

/**
    Note: The ERC-165 identifier for this interface is 0x4e2312e0.
*/
interface ERC1155TokenReceiver {
    /**
        @notice Handle the receipt of a single ERC1155 token type.
        @dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeTransferFrom` after the balance has been updated.        
        This function MUST return `bytes4(keccak256(&quot;onERC1155Received(address,address,uint256,uint256,bytes)&quot;))` (i.e. 0xf23a6e61) if it accepts the transfer.
        This function MUST revert if it rejects the transfer.
        Return of any other value than the prescribed keccak256 generated value MUST result in the transaction being reverted by the caller.
        @param _operator  The address which initiated the transfer (i.e. msg.sender)
        @param _from      The address which previously owned the token
        @param _id        The ID of the token being transferred
        @param _value     The amount of tokens being transferred
        @param _data      Additional data with no specified format
        @return           `bytes4(keccak256(&quot;onERC1155Received(address,address,uint256,uint256,bytes)&quot;))`
    */
    function onERC1155Received(address _operator, address _from, uint256 _id, uint256 _value, bytes calldata _data) external returns(bytes4);

    /**
        @notice Handle the receipt of multiple ERC1155 token types.
        @dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeBatchTransferFrom` after the balances have been updated.        
        This function MUST return `bytes4(keccak256(&quot;onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)&quot;))` (i.e. 0xbc197c81) if it accepts the transfer(s).
        This function MUST revert if it rejects the transfer(s).
        Return of any other value than the prescribed keccak256 generated value MUST result in the transaction being reverted by the caller.
        @param _operator  The address which initiated the batch transfer (i.e. msg.sender)
        @param _from      The address which previously owned the token
        @param _ids       An array containing ids of each token being transferred (order and length must match _values array)
        @param _values    An array containing amounts of each token being transferred (order and length must match _ids array)
        @param _data      Additional data with no specified format
        @return           `bytes4(keccak256(&quot;onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)&quot;))`
    */
    function onERC1155BatchReceived(address _operator, address _from, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external returns(bytes4);       
}
```

### Safe Transfer Rules

To be more explicit about how the standard `safeTransferFrom` and `safeBatchTransferFrom` functions MUST operate with respect to the `ERC1155TokenReceiver` hook functions, a list of scenarios and rules follows.

#### Scenarios

**_Scenario#1 :_** The recipient is not a contract.
* `onERC1155Received` and `onERC1155BatchReceived` MUST NOT be called on an EOA (Externally Owned Account).

**_Scenario#2 :_** The transaction is not a mint/transfer of a token.
* `onERC1155Received` and `onERC1155BatchReceived` MUST NOT be called outside of a mint or transfer process.

**_Scenario#3 :_** The receiver does not implement the necessary `ERC1155TokenReceiver` interface function(s).
* The transfer MUST be reverted with the one caveat below.
    - If the token(s) being sent are part of a hybrid implementation of another standard, that particular standard&apos;s rules on sending to a contract MAY now be followed instead. See &quot;Backwards Compatibility&quot; section.

**_Scenario#4 :_** The receiver implements the necessary `ERC1155TokenReceiver` interface function(s) but returns an unknown value.
* The transfer MUST be reverted.

**_Scenario#5 :_** The receiver implements the necessary `ERC1155TokenReceiver` interface function(s) but throws an error.
* The transfer MUST be reverted.

**_Scenario#6 :_** The receiver implements the `ERC1155TokenReceiver` interface and is the recipient of one and only one balance change (e.g. `safeTransferFrom` called).
* The balances for the transfer MUST have been updated before the `ERC1155TokenReceiver` hook is called on a recipient contract.
* The transfer event MUST have been emitted to reflect the balance changes before the `ERC1155TokenReceiver` hook is called on the recipient contract.
* One of `onERC1155Received` or `onERC1155BatchReceived` MUST be called on the recipient contract.
* The `onERC1155Received` hook SHOULD be called on the recipient contract and its rules followed.
    - See &quot;onERC1155Received rules&quot; for further rules that MUST be followed.
* The `onERC1155BatchReceived` hook MAY be called on the recipient contract and its rules followed.
    - See &quot;onERC1155BatchReceived rules&quot; for further rules that MUST be followed.

**_Scenario#7 :_** The receiver implements the `ERC1155TokenReceiver` interface and is the recipient of more than one balance change (e.g. `safeBatchTransferFrom` called).
* All balance transfers that are referenced in a call to an `ERC1155TokenReceiver` hook MUST be updated before the `ERC1155TokenReceiver` hook is called on the recipient contract.
* All transfer events MUST have been emitted to reflect current balance changes before an `ERC1155TokenReceiver` hook is called on the recipient contract.
* `onERC1155Received` or `onERC1155BatchReceived` MUST be called on the recipient as many times as necessary such that every balance change for the recipient in the scenario is accounted for.
    - The return magic value for every hook call MUST be checked and acted upon as per &quot;onERC1155Received rules&quot; and &quot;onERC1155BatchReceived rules&quot;.
* The `onERC1155BatchReceived` hook SHOULD be called on the recipient contract and its rules followed.    
    - See &quot;onERC1155BatchReceived rules&quot; for further rules that MUST be followed.
* The `onERC1155Received` hook MAY be called on the recipient contract and its rules followed.    
    - See &quot;onERC1155Received rules&quot; for further rules that MUST be followed.
    
**_Scenario#8 :_** You are the creator of a contract that implements the `ERC1155TokenReceiver` interface and you forward the token(s) onto another address in one or both of `onERC1155Received` and `onERC1155BatchReceived`.
* Forwarding should be considered acceptance and then initiating a new `safeTransferFrom` or `safeBatchTransferFrom` in a new context.
    - The prescribed keccak256 acceptance value magic for the receiver hook being called MUST be returned after forwarding is successful.
* The `_data` argument MAY be re-purposed for the new context.
* If forwarding fails the transaction MAY be reverted.
    - If the contract logic wishes to keep the ownership of the token(s) itself in this case it MAY do so.
    
**_Scenario#9 :_** You are transferring tokens via a non-standard API call i.e. an implementation specific API and NOT `safeTransferFrom` or `safeBatchTransferFrom`.
* In this scenario all balance updates and events output rules are the same as if a standard transfer function had been called.
    - i.e. an external viewer MUST still be able to query the balance via a standard function and it MUST be identical to the balance as determined by `TransferSingle` and `TransferBatch` events alone.
* If the receiver is a contract the `ERC1155TokenReceiver` hooks still need to be called on it and the return values respected the same as if a standard transfer function had been called. 
    - However while the `safeTransferFrom` or `safeBatchTransferFrom` functions MUST revert if a receiving contract does not implement the `ERC1155TokenReceiver` interface, a non-standard function MAY proceed with the transfer.
    - See &quot;Implementation specific transfer API rules&quot;.


#### Rules

**_safeTransferFrom rules:_**
* Caller must be approved to manage the tokens being transferred out of the `_from` account (see &quot;Approval&quot; section).
* MUST revert if `_to` is the zero address.
* MUST revert if balance of holder for token `_id` is lower than the `_value` sent to the recipient.
* MUST revert on any other error.
* MUST emit the `TransferSingle` event to reflect the balance change (see &quot;TransferSingle and TransferBatch event rules&quot; section).
* After the above conditions are met, this function MUST check if `_to` is a smart contract (e.g. code size &gt; 0). If so, it MUST call `onERC1155Received` on `_to` and act appropriately (see &quot;onERC1155Received rules&quot; section).
    - The `_data` argument provided by the sender for the transfer MUST be passed with its contents unaltered to the `onERC1155Received` hook function via its `_data` argument.

**_safeBatchTransferFrom rules:_**
* Caller must be approved to manage all the tokens being transferred out of the `_from` account (see &quot;Approval&quot; section).
* MUST revert if `_to` is the zero address.
* MUST revert if length of `_ids` is not the same as length of `_values`.
* MUST revert if any of the balance(s) of the holder(s) for token(s) in `_ids` is lower than the respective amount(s) in `_values` sent to the recipient.
* MUST revert on any other error.
* MUST emit `TransferSingle` or `TransferBatch` event(s) such that all the balance changes are reflected (see &quot;TransferSingle and TransferBatch event rules&quot; section).
* The balance changes and events MUST occur in the array order they were submitted (_ids[0]/_values[0] before _ids[1]/_values[1], etc).
* After the above conditions are met, this function MUST check if `_to` is a smart contract (e.g. code size &gt; 0). If so, it MUST call `onERC1155Received` or `onERC1155BatchReceived` on `_to` and act appropriately (see &quot;onERC1155Received and onERC1155BatchReceived rules&quot; section).
    - The `_data` argument provided by the sender for the transfer MUST be passed with its contents unaltered to the `ERC1155TokenReceiver` hook function(s) via their `_data` argument.

**_TransferSingle and TransferBatch event rules:_**
* `TransferSingle` SHOULD be used to indicate a single balance transfer has occurred between a `_from` and `_to` pair.
    - It MAY be emitted multiple times to indicate multiple balance changes in the transaction, but note that `TransferBatch` is designed for this to reduce gas consumption.
    - The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender).
    - The `_from` argument MUST be the address of the holder whose balance is decreased.
    - The `_to` argument MUST be the address of the recipient whose balance is increased.
    - The `_id` argument MUST be the token type being transferred.
    - The `_value` argument MUST be the number of tokens the holder balance is decreased by and match what the recipient balance is increased by.
    - When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address). See &quot;Minting/creating and burning/destroying rules&quot;.
    - When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address). See &quot;Minting/creating and burning/destroying rules&quot;.
* `TransferBatch` SHOULD be used to indicate multiple balance transfers have occurred between a `_from` and `_to` pair.
    - It MAY be emitted with a single element in the list to indicate a singular balance change in the transaction, but note that `TransferSingle` is designed for this to reduce gas consumption.
    - The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender).
    - The `_from` argument MUST be the address of the holder whose balance is decreased for each entry pair in `_ids` and `_values`.
    - The `_to` argument MUST be the address of the recipient whose balance is increased for each entry pair in `_ids` and `_values`.
    - The `_ids` array argument MUST contain the ids of the tokens being transferred.
    - The `_values` array argument MUST contain the number of token to be transferred for each corresponding entry in `_ids`.
    - `_ids` and `_values` MUST have the same length.
    - When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address). See &quot;Minting/creating and burning/destroying rules&quot;.
    - When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address). See &quot;Minting/creating and burning/destroying rules&quot;.
* The total value transferred from address `0x0` minus the total value transferred to `0x0` observed via the `TransferSingle` and `TransferBatch` events MAY be used by clients and exchanges to determine the &quot;circulating supply&quot; for a given token ID.
* To broadcast the existence of a token ID with no initial balance, the contract SHOULD emit the `TransferSingle` event from `0x0` to `0x0`, with the token creator as `_operator`, and a `_value` of 0.
* All `TransferSingle` and `TransferBatch` events MUST be emitted to reflect all the balance changes that have occurred before any call(s) to `onERC1155Received` or `onERC1155BatchReceived`.
    - To make sure event order is correct in the case of valid re-entry (e.g. if a receiver contract forwards tokens on receipt) state balance and events balance MUST match before calling an external contract.

**_onERC1155Received rules:_**
- The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender).
* The `_from` argument MUST be the address of the holder whose balance is decreased.
    - `_from` MUST be 0x0 for a mint.
* The `_id` argument MUST be the token type being transferred.
* The `_value` argument MUST be the number of tokens the holder balance is decreased by and match what the recipient balance is increased by.
* The `_data` argument MUST contain the information provided by the sender for the transfer with its contents unaltered.
    - i.e. it MUST pass on the unaltered `_data` argument sent via the `safeTransferFrom` or `safeBatchTransferFrom` call for this transfer.
* The recipient contract MAY accept an increase of its balance by returning the acceptance magic value `bytes4(keccak256(&quot;onERC1155Received(address,address,uint256,uint256,bytes)&quot;))`
    - If the return value is `bytes4(keccak256(&quot;onERC1155Received(address,address,uint256,uint256,bytes)&quot;))` the transfer MUST be completed or MUST revert if any other conditions are not met for success.
* The recipient contract MAY reject an increase of its balance by calling revert.
    - If the recipient contract throws/reverts the transaction MUST be reverted.
* If the return value is anything other than `bytes4(keccak256(&quot;onERC1155Received(address,address,uint256,uint256,bytes)&quot;))` the transaction MUST be reverted.
* `onERC1155Received` (and/or `onERC1155BatchReceived`) MAY be called multiple times in a single transaction and the following requirements must be met:
    - All callbacks represent mutually exclusive balance changes.
    - The set of all calls to `onERC1155Received` and `onERC1155BatchReceived` describes all balance changes that occurred during the transaction in the order submitted.
* A contract MAY skip calling the `onERC1155Received` hook function if the transfer operation is transferring the token to itself.

**_onERC1155BatchReceived rules:_**
- The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender).
* The `_from` argument MUST be the address of the holder whose balance is decreased.
    - `_from` MUST be 0x0 for a mint.    
* The `_ids` argument MUST be the list of tokens being transferred.
* The `_values` argument MUST be the list of number of tokens (matching the list and order of tokens specified in `_ids`) the holder balance is decreased by and match what the recipient balance is increased by.
* The `_data` argument MUST contain the information provided by the sender for the transfer with its contents unaltered.
    - i.e. it MUST pass on the unaltered `_data` argument sent via the `safeBatchTransferFrom` call for this transfer.
* The recipient contract MAY accept an increase of its balance by returning the acceptance magic value `bytes4(keccak256(&quot;onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)&quot;))`
    - If the return value is `bytes4(keccak256(&quot;onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)&quot;))` the transfer MUST be completed or MUST revert if any other conditions are not met for success.
* The recipient contract MAY reject an increase of its balance by calling revert.
    - If the recipient contract throws/reverts the transaction MUST be reverted.
* If the return value is anything other than `bytes4(keccak256(&quot;onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)&quot;))` the transaction MUST be reverted.
* `onERC1155BatchReceived` (and/or `onERC1155Received`) MAY be called multiple times in a single transaction and the following requirements must be met:
    - All callbacks represent mutually exclusive balance changes.
    - The set of all calls to `onERC1155Received` and `onERC1155BatchReceived` describes all balance changes that occurred during the transaction in the order submitted.
* A contract MAY skip calling the `onERC1155BatchReceived` hook function if the transfer operation is transferring the token(s) to itself.
    
**_ERC1155TokenReceiver ERC-165 rules:_**
* The implementation of the ERC-165 `supportsInterface` function SHOULD be as follows:
    ```solidity
    function supportsInterface(bytes4 interfaceID) external view returns (bool) {
        return  interfaceID == 0x01ffc9a7 ||    // ERC-165 support (i.e. `bytes4(keccak256(&apos;supportsInterface(bytes4)&apos;))`).
                interfaceID == 0x4e2312e0;      // ERC-1155 `ERC1155TokenReceiver` support (i.e. `bytes4(keccak256(&quot;onERC1155Received(address,address,uint256,uint256,bytes)&quot;)) ^ bytes4(keccak256(&quot;onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)&quot;))`).
    }
    ```
* The implementation MAY differ from the above but:
  - It MUST return the constant value `true` if `0x01ffc9a7` is passed through the `interfaceID` argument. This signifies ERC-165 support.
  - It MUST return the constant value `true` if `0x4e2312e0` is passed through the `interfaceID` argument. This signifies ERC-1155 `ERC1155TokenReceiver` support.
  - It MUST NOT consume more than 10,000 gas.
    - This keeps it below the ERC-165 requirement of 30,000 gas, reduces the gas reserve needs and minimises possible side-effects of gas exhaustion during the call.

**_Implementation specific transfer API rules:_**
* If an implementation specific API function is used to transfer ERC-1155 token(s) to a contract, the `safeTransferFrom` or `safeBatchTransferFrom` (as appropriate) rules MUST still be followed if the receiver implements the `ERC1155TokenReceiver` interface. If it does not the non-standard implementation SHOULD revert but MAY proceed.    
* An example:
    1. An approved user calls a function such as `function myTransferFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values);`.
    2. `myTransferFrom` updates the balances for `_from` and `_to` addresses for all `_ids` and `_values`.
    3. `myTransferFrom` emits `TransferBatch` with the details of what was transferred from address `_from` to address `_to`.
    4. `myTransferFrom` checks if `_to` is a contract address and determines that it is so (if not, then the transfer can be considered successful).
    5. `myTransferFrom` calls `onERC1155BatchReceived` on `_to` and it reverts or returns an unknown value (if it had returned `bytes4(keccak256(&quot;onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)&quot;))` the transfer can be considered successful).    
    6. At this point `myTransferFrom` SHOULD revert the transaction immediately as receipt of the token(s) was not explicitly accepted by the `onERC1155BatchReceived` function.            
    7. If however `myTransferFrom` wishes to continue it MUST call `supportsInterface(0x4e2312e0)` on `_to` and if it returns the constant value `true` the transaction MUST be reverted, as it is now known to be a valid receiver and the previous acceptance step failed. 
        - NOTE: You could have called `supportsInterface(0x4e2312e0)` at a previous step if you wanted to gather and act upon that information earlier, such as in a hybrid standards scenario.
    8. If the above call to `supportsInterface(0x4e2312e0)` on `_to` reverts or returns a value other than the constant value `true` the `myTransferFrom` function MAY consider this transfer successful.
        - __NOTE__: this MAY result in unrecoverable tokens if sent to an address that does not expect to receive ERC-1155 tokens.
* The above example is not exhaustive but illustrates the major points (and shows that most are shared with `safeTransferFrom` and `safeBatchTransferFrom`):
    - Balances that are updated MUST have equivalent transfer events emitted.
    - A receiver address has to be checked if it is a contract and if so relevant `ERC1155TokenReceiver` hook function(s) have to be called on it. 
    - Balances (and events associated) that are referenced in a call to an `ERC1155TokenReceiver` hook MUST be updated (and emitted) before the `ERC1155TokenReceiver` hook is called.
    - The return values of the `ERC1155TokenReceiver` hook functions that are called MUST be respected if they are implemented.    
    - Only non-standard transfer functions MAY allow tokens to be sent to a recipient contract that does NOT implement the necessary `ERC1155TokenReceiver` hook functions. `safeTransferFrom` and `safeBatchTransferFrom` MUST revert in that case (unless it is a hybrid standards implementation see &quot;Backwards Compatibility&quot;).

**_Minting/creating and burning/destroying rules:_**
* A mint/create operation is essentially a specialized transfer and MUST follow these rules:
    - To broadcast the existence of a token ID with no initial balance, the contract SHOULD emit the `TransferSingle` event from `0x0` to `0x0`, with the token creator as `_operator`, and a `_value` of 0.
    - The &quot;TransferSingle and TransferBatch event rules&quot; MUST be followed as appropriate for the mint(s) (i.e. singles or batches) however the `_from` argument MUST be set to `0x0` (i.e. zero address) to flag the transfer as a mint to contract observers.
        - __NOTE:__ This includes tokens that are given an initial balance in the contract. The balance of the contract MUST also be able to be determined by events alone meaning initial contract balances (for eg. in construction) MUST emit events to reflect those balances too.            
* A burn/destroy operation is essentially a specialized transfer and MUST follow these rules:
    - The &quot;TransferSingle and TransferBatch event rules&quot; MUST be followed as appropriate for the burn(s) (i.e. singles or batches) however the `_to` argument MUST be set to `0x0` (i.e. zero address) to flag the transfer as a burn to contract observers.           
    - When burning/destroying you do not have to actually transfer to `0x0` (that is impl specific), only the `_to` argument in the event MUST be set to `0x0` as above.
* The total value transferred from address `0x0` minus the total value transferred to `0x0` observed via the `TransferSingle` and `TransferBatch` events MAY be used by clients and exchanges to determine the &quot;circulating supply&quot; for a given token ID.
* As mentioned above mint/create and burn/destroy operations are specialized transfers and so will likely be accomplished with custom transfer functions rather than `safeTransferFrom` or `safeBatchTransferFrom`. If so the &quot;Implementation specific transfer API rules&quot; section would be appropriate.   
    - Even in a non-safe API and/or hybrid standards case the above event rules MUST still be adhered to when minting/creating or burning/destroying.
* A contract MAY skip calling the `ERC1155TokenReceiver` hook function(s) if the mint operation is transferring the token(s) to itself. In all other cases the `ERC1155TokenReceiver` rules MUST be followed as appropriate for the implementation (i.e. safe, custom and/or hybrid). 


##### A solidity example of the keccak256 generated constants for the various magic values (these MAY be used by implementation):

```solidity
bytes4 constant public ERC1155_ERC165 = 0xd9b67a26; // ERC-165 identifier for the main token standard.
bytes4 constant public ERC1155_ERC165_TOKENRECEIVER = 0x4e2312e0; // ERC-165 identifier for the `ERC1155TokenReceiver` support (i.e. `bytes4(keccak256(&quot;onERC1155Received(address,address,uint256,uint256,bytes)&quot;)) ^ bytes4(keccak256(&quot;onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)&quot;))`).
bytes4 constant public ERC1155_ACCEPTED = 0xf23a6e61; // Return value from `onERC1155Received` call if a contract accepts receipt (i.e `bytes4(keccak256(&quot;onERC1155Received(address,address,uint256,uint256,bytes)&quot;))`).
bytes4 constant public ERC1155_BATCH_ACCEPTED = 0xbc197c81; // Return value from `onERC1155BatchReceived` call if a contract accepts receipt (i.e `bytes4(keccak256(&quot;onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)&quot;))`).
```

### Metadata

The URI value allows for ID substitution by clients. If the string `{id}` exists in any URI, clients MUST replace this with the actual token ID in hexadecimal form. This allows for a large number of tokens to use the same on-chain string by defining a URI once, for that large number of tokens.

* The string format of the substituted hexadecimal ID MUST be lowercase alphanumeric: `[0-9a-f]` with no 0x prefix.
* The string format of the substituted hexadecimal ID MUST be leading zero padded to 64 hex characters length if necessary.

Example of such a URI: `https://token-cdn-domain/{id}.json` would be replaced with `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json` if the client is referring to token ID 314592/0x4CCE0.

#### Metadata Extensions

The optional `ERC1155Metadata_URI` extension can be identified with the [ERC-165 Standard Interface Detection](/EIPs/EIPS/eip-165).

If the optional `ERC1155Metadata_URI` extension is included:
* The ERC-165 `supportsInterface` function MUST return the constant value `true` if `0x0e89341c` is passed through the `interfaceID` argument.
* _Changes_ to the URI MUST emit the `URI` event if the change can be expressed with an event (i.e. it isn&apos;t dynamic/programmatic).
    - An implementation MAY emit the `URI` event during a mint operation but it is NOT mandatory. An observer MAY fetch the metadata uri at mint time from the `uri` function if it was not emitted.    
* The `uri` function SHOULD be used to retrieve values if no event was emitted. 
* The `uri` function MUST return the same value as the latest event for an `_id` if it was emitted.
* The `uri` function MUST NOT be used to check for the existence of a token as it is possible for an implementation to return a valid string even if the token does not exist.

```solidity
pragma solidity ^0.5.9;

/**
    Note: The ERC-165 identifier for this interface is 0x0e89341c.
*/
interface ERC1155Metadata_URI {
    /**
        @notice A distinct Uniform Resource Identifier (URI) for a given token.
        @dev URIs are defined in RFC 3986.
        The URI MUST point to a JSON file that conforms to the &quot;ERC-1155 Metadata URI JSON Schema&quot;.        
        @return URI string
    */
    function uri(uint256 _id) external view returns (string memory);
}
```

#### ERC-1155 Metadata URI JSON Schema

This JSON schema is loosely based on the &quot;ERC721 Metadata JSON Schema&quot;, but includes optional formatting to allow for ID substitution by clients. If the string `{id}` exists in any JSON value, it MUST be replaced with the actual token ID, by all client software that follows this standard.

* The string format of the substituted hexadecimal ID MUST be lowercase alphanumeric: `[0-9a-f]` with no 0x prefix.
* The string format of the substituted hexadecimal ID MUST be leading zero padded to 64 hex characters length if necessary.

```json
{
    &quot;title&quot;: &quot;Token Metadata&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;name&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Identifies the asset to which this token represents&quot;
        },
        &quot;decimals&quot;: {
            &quot;type&quot;: &quot;integer&quot;,
            &quot;description&quot;: &quot;The number of decimal places that the token amount should display - e.g. 18, means to divide the token amount by 1000000000000000000 to get its user representation.&quot;
        },
        &quot;description&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Describes the asset to which this token represents&quot;
        },
        &quot;image&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;A URI pointing to a resource with mime type image/* representing the asset to which this token represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive.&quot;
        },
        &quot;properties&quot;: {
            &quot;type&quot;: &quot;object&quot;,
            &quot;description&quot;: &quot;Arbitrary properties. Values may be strings, numbers, object or arrays.&quot;
        }
    }
}
```

An example of an ERC-1155 Metadata JSON file follows. The properties array proposes some SUGGESTED formatting for token-specific display properties and metadata.

```json
{
	&quot;name&quot;: &quot;Asset Name&quot;,
	&quot;description&quot;: &quot;Lorem ipsum...&quot;,
	&quot;image&quot;: &quot;https:\/\/s3.amazonaws.com\/your-bucket\/images\/{id}.png&quot;,
	&quot;properties&quot;: {
		&quot;simple_property&quot;: &quot;example value&quot;,
		&quot;rich_property&quot;: {
			&quot;name&quot;: &quot;Name&quot;,
			&quot;value&quot;: &quot;123&quot;,
			&quot;display_value&quot;: &quot;123 Example Value&quot;,
			&quot;class&quot;: &quot;emphasis&quot;,
			&quot;css&quot;: {
				&quot;color&quot;: &quot;#ffffff&quot;,
				&quot;font-weight&quot;: &quot;bold&quot;,
				&quot;text-decoration&quot;: &quot;underline&quot;
			}
		},
		&quot;array_property&quot;: {
			&quot;name&quot;: &quot;Name&quot;,
			&quot;value&quot;: [1,2,3,4],
			&quot;class&quot;: &quot;emphasis&quot;
		}
	}
}
```

##### Localization

Metadata localization should be standardized to increase presentation uniformity across all languages. As such, a simple overlay method is proposed to enable localization. If the metadata JSON file contains a `localization` attribute, its content MAY be used to provide localized values for fields that need it. The `localization` attribute should be a sub-object with three attributes: `uri`, `default` and `locales`. If the string `{locale}` exists in any URI, it MUST be replaced with the chosen locale by all client software.

##### JSON Schema

```json
{
    &quot;title&quot;: &quot;Token Metadata&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;name&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Identifies the asset to which this token represents&quot;,
        },
        &quot;decimals&quot;: {
            &quot;type&quot;: &quot;integer&quot;,
            &quot;description&quot;: &quot;The number of decimal places that the token amount should display - e.g. 18, means to divide the token amount by 1000000000000000000 to get its user representation.&quot;
        },
        &quot;description&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Describes the asset to which this token represents&quot;
        },
        &quot;image&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;A URI pointing to a resource with mime type image/* representing the asset to which this token represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive.&quot;
        },
        &quot;properties&quot;: {
            &quot;type&quot;: &quot;object&quot;,
            &quot;description&quot;: &quot;Arbitrary properties. Values may be strings, numbers, object or arrays.&quot;,
        },
        &quot;localization&quot;: {
            &quot;type&quot;: &quot;object&quot;,
            &quot;required&quot;: [&quot;uri&quot;, &quot;default&quot;, &quot;locales&quot;],
            &quot;properties&quot;: {
                &quot;uri&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;The URI pattern to fetch localized data from. This URI should contain the substring `{locale}` which will be replaced with the appropriate locale value before sending the request.&quot;
                },
                &quot;default&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;The locale of the default data within the base JSON&quot;
                },
                &quot;locales&quot;: {
                    &quot;type&quot;: &quot;array&quot;,
                    &quot;description&quot;: &quot;The list of locales for which data is available. These locales should conform to those defined in the Unicode Common Locale Data Repository (http://cldr.unicode.org/).&quot;
                }
            }
        }
    }
}
```

##### Localized Sample

Base URI:
```json
{
  &quot;name&quot;: &quot;Advertising Space&quot;,
  &quot;description&quot;: &quot;Each token represents a unique Ad space in the city.&quot;,
  &quot;localization&quot;: {
    &quot;uri&quot;: &quot;ipfs://QmWS1VAdMD353A6SDk9wNyvkT14kyCiZrNDYAad4w1tKqT/{locale}.json&quot;,
    &quot;default&quot;: &quot;en&quot;,
    &quot;locales&quot;: [&quot;en&quot;, &quot;es&quot;, &quot;fr&quot;]
  }
}
```

es.json:
```json
{
  &quot;name&quot;: &quot;Espacio Publicitario&quot;,
  &quot;description&quot;: &quot;Cada token representa un espacio publicitario único en la ciudad.&quot;
}
```

fr.json:
```json
{
  &quot;name&quot;: &quot;Espace Publicitaire&quot;,
  &quot;description&quot;: &quot;Chaque jeton représente un espace publicitaire unique dans la ville.&quot;
}
```

### Approval

The function `setApprovalForAll` allows an operator to manage one&apos;s entire set of tokens on behalf of the approver. To permit approval of a subset of token IDs, an interface such as [ERC-1761 Scoped Approval Interface](/EIPs/EIPS/eip-1761) is suggested.
The counterpart `isApprovedForAll` provides introspection into any status set by `setApprovalForAll`.

An owner SHOULD be assumed to always be able to operate on their own tokens regardless of approval status, so should SHOULD NOT have to call `setApprovalForAll` to approve themselves as an operator before they can operate on them.  

## Rationale

### Metadata Choices

The `symbol` function (found in the ERC-20 and ERC-721 standards) was not included as we do not believe this is a globally useful piece of data to identify a generic virtual item / asset and are also prone to collisions. Short-hand symbols are used in tickers and currency trading, but they aren&apos;t as useful outside of that space.

The `name` function (for human-readable asset names, on-chain) was removed from the standard to allow the Metadata JSON to be the definitive asset name and reduce duplication of data. This also allows localization for names, which would otherwise be prohibitively expensive if each language string was stored on-chain, not to mention bloating the standard interface. While this decision may add a small burden on implementers to host a JSON file containing metadata, we believe any serious implementation of ERC-1155 will already utilize JSON Metadata.

### Upgrades

The requirement to emit `TransferSingle` or `TransferBatch` on balance change implies that a valid implementation of ERC-1155 redeploying to a new contract address MUST emit events from the new contract address to replicate the deprecated contract final state. It is valid to only emit a minimal number of events to reflect only the final balance and omit all the transactions that led to that state. The event emit requirement is to ensure that the current state of the contract can always be traced only through events. To alleviate the need to emit events when changing contract address, consider using the proxy pattern, such as described in [EIP-2535](/EIPs/EIPS/eip-2535). This will also have the added benefit of providing a stable contract address for users.

### Design decision: Supporting non-batch

The standard supports `safeTransferFrom` and `onERC1155Received` functions because they are significantly cheaper for single token-type transfers, which is arguably a common use case.

### Design decision: Safe transfers only

The standard only supports safe-style transfers, making it possible for receiver contracts to depend on `onERC1155Received` or `onERC1155BatchReceived` function to be always called at the end of a transfer.

### Guaranteed log trace

As the Ethereum ecosystem continues to grow, many dapps are relying on traditional databases and explorer API services to retrieve and categorize data. The ERC-1155 standard guarantees that event logs emitted by the smart contract will provide enough data to create an accurate record of all current token balances. A database or explorer may listen to events and be able to provide indexed and categorized searches of every ERC-1155 token in the contract.

### Approval

The function `setApprovalForAll` allows an operator to manage one&apos;s entire set of tokens on behalf of the approver. It enables frictionless interaction with exchange and trade contracts.

Restricting approval to a certain set of token IDs, quantities or other rules MAY be done with an additional interface or an external contract. The rationale is to keep the ERC-1155 standard as generic as possible for all use-cases without imposing a specific approval scheme on implementations that may not need it. Standard token approval interfaces can be used, such as the suggested [ERC-1761 Scoped Approval Interface](/EIPs/EIPS/eip-1761) which is compatible with ERC-1155.

## Backwards Compatibility

There have been requirements during the design discussions to have this standard be compatible with existing standards when sending to contract addresses, specifically ERC-721 at time of writing.
To cater for this scenario, there is some leeway with the revert logic should a contract not implement the `ERC1155TokenReceiver` as per &quot;Safe Transfer Rules&quot; section above, specifically &quot;Scenario#3 : The receiver does not implement the necessary `ERC1155TokenReceiver` interface function(s)&quot;.

Hence in a hybrid ERC-1155 contract implementation an extra call MUST be made on the recipient contract and checked before any hook calls to `onERC1155Received` or `onERC1155BatchReceived` are made.
Order of operation MUST therefore be:
1. The implementation MUST call the function `supportsInterface(0x4e2312e0)` on the recipient contract, providing at least 10,000 gas.
2. If the function call succeeds and the return value is the constant value `true` the implementation proceeds as a regular ERC-1155 implementation, with the call(s) to the `onERC1155Received` or `onERC1155BatchReceived` hooks and rules associated.
3. If the function call fails or the return value is NOT the constant value `true` the implementation can assume the recipient contract is not an `ERC1155TokenReceiver` and follow its other standard&apos;s rules for transfers. 
   
*__Note that a pure implementation of a single standard is recommended__* rather than a hybrid solution, but an example of a hybrid ERC-1155/ERC-721 contract is linked in the references section under implementations.

An important consideration is that even if the tokens are sent with another standard&apos;s rules the *__ERC-1155 transfer events MUST still be emitted.__* This is so the balances can still be determined via events alone as per ERC-1155 standard rules.

## Usage

This standard can be used to represent multiple token types for an entire domain. Both fungible and non-fungible tokens can be stored in the same smart-contract.

### Batch Transfers

The `safeBatchTransferFrom` function allows for batch transfers of multiple token IDs and values. The design of ERC-1155 makes batch transfers possible without the need for a wrapper contract, as with existing token standards. This reduces gas costs when more than one token type is included in a batch transfer, as compared to single transfers with multiple transactions.

Another advantage of standardized batch transfers is the ability for a smart contract to respond to the batch transfer in a single operation using `onERC1155BatchReceived`.

It is RECOMMENDED that clients and wallets sort the token IDs and associated values (in ascending order) when posting a batch transfer, as some ERC-1155 implementations offer significant gas cost savings when IDs are sorted. See [Horizon Games - Multi-Token Standard](https://github.com/horizon-games/multi-token-standard) &quot;packed balance&quot; implementation for an example of this.

### Batch Balance

The `balanceOfBatch` function allows clients to retrieve balances of multiple owners and token IDs with a single call.

### Enumerating from events

In order to keep storage requirements light for contracts implementing ERC-1155, enumeration (discovering the IDs and values of tokens) must be done using event logs. It is RECOMMENDED that clients such as exchanges and blockchain explorers maintain a local database containing the token ID, Supply, and URI at the minimum. This can be built from each TransferSingle, TransferBatch, and URI event, starting from the block the smart contract was deployed until the latest block.

ERC-1155 contracts must therefore carefully emit `TransferSingle` or `TransferBatch` events in any instance where tokens are created, minted, transferred or destroyed.

### Non-Fungible Tokens

The following strategies are examples of how you MAY mix fungible and non-fungible tokens together in the same contract. The standard does NOT mandate how an implementation must do this. 

##### Split ID bits

The top 128 bits of the uint256 `_id` parameter in any ERC-1155 function MAY represent the base token ID, while the bottom 128 bits MAY represent the index of the non-fungible to make it unique.

Non-fungible tokens can be interacted with using an index based accessor into the contract/token data set. Therefore to access a particular token set within a mixed data contract and a particular non-fungible within that set, `_id` could be passed as `&lt;uint128: base token id&gt;&lt;uint128: index of non-fungible&gt;`.

To identify a non-fungible set/category as a whole (or a fungible) you COULD just pass in the base id via the `_id` argument as `&lt;uint128: base token id&gt;&lt;uint128: zero&gt;`. If your implementation uses this technique this naturally means the index of a non-fungible SHOULD be 1-based.

Inside the contract code the two pieces of data needed to access the individual non-fungible can be extracted with uint128(~0) and the same mask shifted by 128.

```solidity
uint256 baseTokenNFT = 12345 &lt;&lt; 128;
uint128 indexNFT = 50;

uint256 baseTokenFT = 54321 &lt;&lt; 128;

balanceOf(msg.sender, baseTokenNFT); // Get balance of the base token for non-fungible set 12345 (this MAY be used to get balance of the user for all of this token set if the implementation wishes as a convenience).
balanceOf(msg.sender, baseTokenNFT + indexNFT); // Get balance of the token at index 50 for non-fungible set 12345 (should be 1 if user owns the individual non-fungible token or 0 if they do not).
balanceOf(msg.sender, baseTokenFT); // Get balance of the fungible base token 54321.
```

Note that 128 is an arbitrary number, an implementation MAY choose how they would like this split to occur as suitable for their use case. An observer of the contract would simply see events showing balance transfers and mints happening and MAY track the balances using that information alone.
For an observer to be able to determine type (non-fungible or fungible) from an ID alone they would have to know the split ID bits format on a implementation by implementation basis.

The [ERC-1155 Reference Implementation](https://github.com/enjin/erc-1155) is an example of the split ID bits strategy.

##### Natural Non-Fungible tokens

Another simple way to represent non-fungibles is to allow a maximum value of 1 for each non-fungible token. This would naturally mirror the real world, where unique items have a quantity of 1 and fungible items have a quantity greater than 1.

## References

**Standards**
- [ERC-721 Non-Fungible Token Standard](/EIPs/EIPS/eip-721)
- [ERC-165 Standard Interface Detection](/EIPs/EIPS/eip-165)
- [ERC-1538 Transparent Contract Standard](/EIPs/EIPS/eip-1538)
- [JSON Schema](https://json-schema.org/)
- [RFC 2119 Key words for use in RFCs to Indicate Requirement Levels](https://www.ietf.org/rfc/rfc2119.txt)

**Implementations**
- [ERC-1155 Reference Implementation](https://github.com/enjin/erc-1155)
- [Horizon Games - Multi-Token Standard](https://github.com/horizon-games/multi-token-standard)
- [Enjin Coin](https://enjincoin.io) ([GitHub](https://github.com/enjin))
- [The Sandbox - Dual ERC-1155/721 Contract](https://github.com/pixowl/thesandbox-contracts/tree/master/src/Asset)

**Articles &amp; Discussions**
- [GitHub - Original Discussion Thread](https://github.com/ethereum/EIPs/issues/1155)
- [ERC-1155 - The Crypto Item Standard](https://blog.enjincoin.io/erc-1155-the-crypto-item-standard-ac9cf1c5a226)
- [Here Be Dragons - Going Beyond ERC-20 and ERC-721 To Reduce Gas Cost by ~80%](https://medium.com/horizongames/going-beyond-erc20-and-erc721-9acebd4ff6ef)
- [Blockonomi - Ethereum ERC-1155 Token Perfect for Online Games, Possibly More](https://blockonomi.com/erc1155-gaming-token/)
- [Beyond Gaming - Exploring the Utility of ERC-1155 Token Standard!](https://blockgeeks.com/erc-1155-token/)
- [ERC-1155: A new standard for The Sandbox](https://medium.com/sandbox-game/erc-1155-a-new-standard-for-the-sandbox-c95ee1e45072)

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 17 Jun 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1155</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1155</guid>
      </item>
    
      <item>
        <title>Minimal Proxy Contract</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/optionality/clone-factory/issues/10</comments>
        
        <description>## Simple Summary
To simply and cheaply clone contract functionality in an immutable way, this standard specifies a minimal bytecode implementation that delegates all calls to a known, fixed address.  
## Abstract
By standardizing on a known minimal bytecode redirect implementation, this standard allows users and third party tools (e.g. Etherscan) to (a) simply discover that a contract will always redirect in a known manner and (b) depend on the behavior of the code at the destination contract as the behavior of the redirecting contract.  Specifically, tooling can interrogate the bytecode at a redirecting address to determine the location of the code that will run - and can depend on representations about that code (verified source, third-party audits, etc).  This implementation forwards all calls and 100% of the gas to the implementation contract and then relays the return value back to the caller.  In the case where the implementation reverts, the revert is passed back along with the payload data (for revert with message).

## Motivation
This standard supports use-cases wherein it is desirable to clone exact contract functionality with a minimum of side effects (e.g. memory slot stomping) and with low gas cost deployment of duplicate proxies.

## Specification
The exact bytecode of the standard clone contract is this: `363d3d373d3d3d363d73bebebebebebebebebebebebebebebebebebebebe5af43d82803e903d91602b57fd5bf3` wherein the bytes at indices 10 - 29 (inclusive) are replaced with the 20 byte address of the master functionality contract.  

A reference implementation of this can be found at the [optionality/clone-factory](https://github.com/optionality/clone-factory) github repo. 

## Rationale
The goals of this effort have been the following:
- inexpensive deployment (low gas to deploy clones)
- support clone initialization in creation transaction (through factory contract model)
- simple clone bytecode to encourage directly bytecode interrogation (see CloneProbe.sol in the clone-factory project)
- dependable, locked-down behavior - this is not designed to handle upgradability, nor should it as the representation we are seeking is stronger.
- small operational overhead - adds a single call cost to each call
- handles error return bubbling for revert messages

## Backwards Compatibility
There are no backwards compatibility issues.  There may be some systems that are using earlier versions of the proxy contract bytecode.  They will not be compliant with this standard.

## Test Cases
Test cases include:
- invocation with no arguments
- invocation with arguments
- invocation with fixed length return values
- invocation with variable length return values
- invocation with revert (confirming reverted payload is transferred)
  
Tests for these cases are included in the reference implementation project.

## Implementation
Deployment bytecode is not included in this specification.  One approach is defined in the proxy-contract reference implementation.

### Standard Proxy
The disassembly of the standard deployed proxy contract code (from r2 and edited to include stack visualization)

```
|           0x00000000      36             calldatasize          cds
|           0x00000001      3d             returndatasize        0 cds
|           0x00000002      3d             returndatasize        0 0 cds
|           0x00000003      37             calldatacopy          
|           0x00000004      3d             returndatasize        0
|           0x00000005      3d             returndatasize        0 0 
|           0x00000006      3d             returndatasize        0 0 0
|           0x00000007      36             calldatasize          cds 0 0 0
|           0x00000008      3d             returndatasize        0 cds 0 0 0
|           0x00000009      73bebebebebe.  push20 0xbebebebe     0xbebe 0 cds 0 0 0
|           0x0000001e      5a             gas                   gas 0xbebe 0 cds 0 0 0
|           0x0000001f      f4             delegatecall          suc 0
|           0x00000020      3d             returndatasize        rds suc 0
|           0x00000021      82             dup3                  0 rds suc 0
|           0x00000022      80             dup1                  0 0 rds suc 0
|           0x00000023      3e             returndatacopy        suc 0
|           0x00000024      90             swap1                 0 suc
|           0x00000025      3d             returndatasize        rds 0 suc
|           0x00000026      91             swap2                 suc 0 rds
|           0x00000027      602b           push1 0x2b            0x2b suc 0 rds
|       ,=&lt; 0x00000029      57             jumpi                 0 rds
|       |   0x0000002a      fd             revert
|       `-&gt; 0x0000002b      5b             jumpdest              0 rds
\           0x0000002c      f3             return

```

NOTE: as an effort to reduce gas costs as much as possible, the above bytecode depends on EIP-211 specification that `returndatasize` returns zero prior to any calls within the call-frame. `returndatasize` uses 1 less gas than `dup*`.

### Vanity Address Optimization
Proxy deployment can be further optimized by installing the master contract at a vanity contract deployment address with leading zero-bytes.  By generating a master contract vanity address that includes Z leading 0 bytes in its address, you can shorten the proxy bytecode by replacing the `push20` opcode with `pushN` (where N is 20 - Z) followed by the N non-zero address bytes.  The revert jump address is decremented by Z in this case.  Here is an example where Z = 4:
```
|           0x00000000      36             calldatasize          cds
|           0x00000001      3d             returndatasize        0 cds
|           0x00000002      3d             returndatasize        0 0 cds
|           0x00000003      37             calldatacopy          
|           0x00000004      3d             returndatasize        0
|           0x00000005      3d             returndatasize        0 0 
|           0x00000006      3d             returndatasize        0 0 0
|           0x00000007      36             calldatasize          cds 0 0 0
|           0x00000008      3d             returndatasize        0 cds 0 0 0
|           0x00000009      6fbebebebebe.  push16 0xbebebebe     0xbebe 0 cds 0 0 0
|           0x0000001a      5a             gas                   gas 0xbebe 0 cds 0 0 0
|           0x0000001b      f4             delegatecall          suc 0
|           0x0000001c      3d             returndatasize        rds suc 0
|           0x0000001d      82             dup3                  0 rds suc 0
|           0x0000001e      80             dup1                  0 0 rds suc 0
|           0x0000001f      3e             returndatacopy        suc 0
|           0x00000020      90             swap1                 0 suc
|           0x00000021      3d             returndatasize        rds 0 suc
|           0x00000022      91             swap2                 suc 0 rds
|           0x00000023      6027           push1 0x27            0x27 suc 0 rds
|       ,=&lt; 0x00000025      57             jumpi                 0 rds
|       |   0x00000026      fd             revert
|       `-&gt; 0x00000027      5b             jumpdest              0 rds
\           0x00000028      f3             return
```
This saves 4 bytes of proxy contract size (savings on each deployment) and has zero impact on runtime gas costs.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 22 Jun 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1167</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1167</guid>
      </item>
    
      <item>
        <title>Wallet &amp; shop standard for all tokens (erc20)</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1182</comments>
        
        <description># All tokens go to heaven
## Simple Summary
Make wallets and shops created from certified contracts make erc20 tokens easy to use for commerce.

![wallet](/EIPs/assets/eip-1175/wallet.png)

## Abstract
The mutual trust between the wallet and the shop created by the authenticated contract allows you to pay for and purchase items at a simple process.

## Motivation
New standards with improvements have been released, but the majority of tokens currently being developed are erc20 tokens. So I felt I needed a proposal to use old tokens in commerce.
 To use various erc20 tokens for trading, you need a custom contract. However, a single wallet with a variety of tokens, and a mutually trusted store, can make transactions that are simple and efficient. The erc20 token is traded through two calls, `approve (address _spender, uint256 _value)` and `transferFrom (address _from, address _to, uint256 _value)`, but when using the wallet contract, `paySafe (address _shop, uint256 _item)`will be traded only in one call.
And if you only reuse the store interface, you can also trade using `payUnsafe (address _shop, uint256 _item)`.

## Specification
![workflow](/EIPs/assets/eip-1175/workflow.png)
## WalletCenter
### Methods
#### createWallet
Create wallet contract and add to list. Returns the address of new wallet.

``` js
function createWallet() public returns (address _wallet)
```

#### isWallet
Returns true or false value for test this address is a created by createWallet.

``` js
function isWallet(address _wallet) public constant returns (bool)
```

#### createShop
Create Shop contract and add to list. Returns the address of new Shop with erc20 token address.

``` js
function createShop(address _erc20) public returns (address _shop)
```

#### isShop
Returns true or false value for test this address is a created by createWallet.

``` js
function isShop(address _shop) public constant returns (bool)
```

### Events
#### Wallet
Search for my wallet.
``` js
event Wallet(address indexed _owner, address indexed _wallet)
```

#### Shop
Search for my shop.
``` js
event Shop(address indexed _owner, address indexed _shop, address indexed _erc20)
```

## Wallet
Wallet must be created by wallet center.
### Methods
#### balanceOf
Returns the account balance of Wallet.
``` js
function balanceOf(address _erc20) public constant returns (uint256 balance)
```

#### withdrawal
withdrawal `_value` amount of `_erc20` token to `_owner`.
``` js
function withdrawal(address _erc20, uint256 _value) onlyOwner public returns (bool success)
```

#### paySafe
Pay for safe shop (created by contract) item with item index `_item`.
``` js
function paySafe(address _shop, uint256 _item) onlyOwner onlyShop(_shop) public payable returns (bool success)
```

#### payUnsafe
Pay for unsafe shop (did not created by contract) item with item index `_item`.
``` js
function payUnsafe(address _shop, uint256 _item) onlyOwner public payable returns (bool success)
```

#### payCancel
Cancel pay and refund. (only weekly model)
``` js
function payCancel(address _shop, uint256 _item) onlyOwner public returns (bool success)
```

#### refund
Refund from shop with item index `_item`.
``` js
function refund(uint256 _item, uint256 _value) public payable returns (bool success)
```

### Events
#### Pay
``` js
event Pay(address indexed _shop, uint256 indexed _item, uint256 indexed _value)
```

#### Refund
``` js
event Refund(address indexed _shop, uint256 indexed _item, uint256 indexed _value)
```

## Shop
Shop is created by wallet center or not. but Shop that created by wallet center is called safe shop.
### Methods
#### balanceOf
Returns the account balance of Shop.
``` js
function balanceOf(address _erc20) public constant returns (uint256 balance)
```

#### withdrawal
withdrawal `_value` amount of `_erc20` token to `_owner`.
``` js
function withdrawal(address _erc20, uint256 _value) onlyOwner public returns (bool success)
```

#### pay
Pay from buyer with item index `_item`.
``` js
function pay(uint256 _item) onlyWallet(msg.sender) public payable returns (bool success)
```

#### refund
refund token to `_to`.
``` js
function refund(address _buyer, uint256 _item, uint256 _value) onlyWallet(_buyer) onlyOwner public payable returns (bool success)
```

#### resister
Listing item for sell.
``` js
function resister(uint8 _category, uint256 _price, uint256 _stock) onlyOwner public returns (uint256 _itemId)
```

#### update
Update item state for sell. (change item `_price` or add item `_stock`)
``` js
function update(uint256 _item, uint256 _price, uint256 _stock) onlyOwner public
```

#### price
Get token address and price from buyer with item index `_item`.
``` js
function price(uint256 _item) public constant returns (address _erc20, uint256 _value)
```

#### canBuy
`_who` can Buy `_item`.
``` js
function canBuy(address _who, uint256 _item) public constant returns (bool _canBuy)
```

#### isBuyer
`_who` is buyer of `_item`.
``` js
function isBuyer(address _who, uint256 _item) public constant returns (bool _buyer)
```

#### info
Set shop information bytes.
``` js
function info(bytes _msgPack)
```

#### upVote
Up vote for this shop.
``` js
function upVote()
```

#### dnVote
Down vote for this shop.
``` js
function dnVote()
```

#### about
Get shop token, up vote and down vote.
``` js
function about() view returns (address _erc20, uint256 _up, uint256 _down)
```

#### infoItem
Set item information bytes.
``` js
function infoItem(uint256 _item, bytes _msgPack)
```

#### upVoteItem
Up vote for this item.
``` js
function upVoteItem(uint256 _item)
```

#### dnVoteItem
Down vote for this item.
``` js
function dnVoteItem(uint256 _item)
```

#### aboutItem
Get Item price, up vote and down vote.
``` js
function aboutItem(uint256 _item) view returns (uint256 _price, uint256 _up, uint256 _down)
```

### Events
#### Pay
``` js
event Pay(address indexed _buyer, uint256 indexed _item, uint256 indexed _value)
```

#### Refund
``` js
event Refund(address indexed _to, uint256 indexed _item, uint256 indexed _value)
```

#### Item
``` js
event Item(uint256 indexed _item, uint256 _price)
```

#### Info
``` js
event Info(bytes _msgPack)
```

#### InfoItem
``` js
event InfoItem(uint256 indexed _item, bytes _msgPack)
```

## Implementation
Sample token contract address is [0x393dd70ce2ae7b30501aec94727968c517f90d52](https://ropsten.etherscan.io/address/0x393dd70ce2ae7b30501aec94727968c517f90d52)

WalletCenter contract address is [0x1fe0862a4a8287d6c23904d61f02507b5044ea31](https://ropsten.etherscan.io/address/0x1fe0862a4a8287d6c23904d61f02507b5044ea31)

WalletCenter create shop contract address is [0x59117730D02Ca3796121b7975796d479A5Fe54B0](https://ropsten.etherscan.io/address/0x59117730D02Ca3796121b7975796d479A5Fe54B0)

WalletCenter create wallet contract address is [0x39da7111844df424e1d0a0226183533dd07bc5c6](https://ropsten.etherscan.io/address/0x39da7111844df424e1d0a0226183533dd07bc5c6)


## Appendix
``` js
pragma solidity ^0.4.24;

contract ERC20Interface {
    function totalSupply() public constant returns (uint);
    function balanceOf(address tokenOwner) public constant returns (uint balance);
    function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
    function transfer(address to, uint tokens) public returns (bool success);
    function approve(address spender, uint tokens) public returns (bool success);
    function transferFrom(address from, address to, uint tokens) public returns (bool success);

    event Transfer(address indexed from, address indexed to, uint tokens);
    event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}

contract SafeMath {
    function safeAdd(uint a, uint b) public pure returns (uint c) {
        c = a + b;
        require(c &gt;= a);
    }
    function safeSub(uint a, uint b) public pure returns (uint c) {
        require(b &lt;= a);
        c = a - b;
    }
    function safeMul(uint a, uint b) public pure returns (uint c) {
        c = a * b;
        require(a == 0 || c / a == b);
    }
    function safeDiv(uint a, uint b) public pure returns (uint c) {
        require(b &gt; 0);
        c = a / b;
    }
}

contract _Base {
    address internal owner;
    address internal walletCenter;
    
    modifier onlyOwner {
        require(owner == msg.sender);
        _;
    }
    modifier onlyWallet(address _addr) {
        require(WalletCenter(walletCenter).isWallet(_addr));
        _;
    }
    modifier onlyShop(address _addr) {
        require(WalletCenter(walletCenter).isShop(_addr));
        _;
    }

    function balanceOf(address _erc20) public constant returns (uint256 balance) {
        if(_erc20==address(0))
            return address(this).balance;
        return ERC20Interface(_erc20).balanceOf(this);
    }

    function transfer(address _to, address _erc20, uint256 _value) internal returns (bool success) {
        require((_erc20==address(0)?address(this).balance:ERC20Interface(_erc20).balanceOf(this))&gt;=_value);
        if(_erc20==address(0))
            _to.transfer(_value);
        else
            ERC20Interface(_erc20).approve(_to,_value);
        return true;
    }
    
    function withdrawal(address _erc20, uint256 _value) public returns (bool success);
    
    event Pay(address indexed _who, uint256 indexed _item, uint256 indexed _value);
    event Refund(address indexed _who, uint256 indexed _item, uint256 indexed _value);
    event Prize(address indexed _who, uint256 indexed _item, uint256 indexed _value);
}

contract _Wallet is _Base {
    constructor(address _who) public {
        owner           = _who;
        walletCenter    = msg.sender;
    }
    
    function pay(address _shop, uint256 _item) private {
        require(_Shop(_shop).canBuy(this,_item));

        address _erc20;
        uint256 _value;
        (_erc20,_value) = _Shop(_shop).price(_item);
        
        transfer(_shop,_erc20,_value);
        _Shop(_shop).pay(_item);
        emit Pay(_shop,_item,_value);
    }
    
    function paySafe(address _shop, uint256 _item) onlyOwner onlyShop(_shop) public payable returns (bool success) {
        pay(_shop,_item);
        return true;
    }
    function payUnsafe(address _shop, uint256 _item) onlyOwner public payable returns (bool success) {
        pay(_shop,_item);
        return true;
    }
    function payCancel(address _shop, uint256 _item) onlyOwner public returns (bool success) {
        _Shop(_shop).payCancel(_item);
        return true;
    }

    function refund(address _erc20, uint256 _item, uint256 _value) public payable returns (bool success) {
        require((_erc20==address(0)?msg.value:ERC20Interface(_erc20).allowance(msg.sender,this))==_value);
        if(_erc20!=address(0))
            ERC20Interface(_erc20).transferFrom(msg.sender,this,_value);
        emit Refund(msg.sender,_item,_value);
        return true;
    }
    function prize(address _erc20, uint256 _item, uint256 _value) public payable returns (bool success) {
        require((_erc20==address(0)?msg.value:ERC20Interface(_erc20).allowance(msg.sender,this))==_value);
        if(_erc20!=address(0))
            ERC20Interface(_erc20).transferFrom(msg.sender,this,_value);
        emit Prize(msg.sender,_item,_value);
        return true;
    }
    
    function withdrawal(address _erc20, uint256 _value) onlyOwner public returns (bool success) {
        require((_erc20==address(0)?address(this).balance:ERC20Interface(_erc20).balanceOf(this))&gt;=_value);
        if(_erc20==address(0))
            owner.transfer(_value);
        else
            ERC20Interface(_erc20).transfer(owner,_value);
        return true;
    }
}

contract _Shop is _Base, SafeMath{
    address erc20;
    constructor(address _who, address _erc20) public {
        owner           = _who;
        walletCenter    = msg.sender;
        erc20           = _erc20;
    }
    
    struct item {
        uint8                       category;   // 0 = disable, 1 = non Stock, non Expire, 2 = can Expire (after 1 week), 3 = stackable
        uint256                     price;
        uint256                     stockCount;

        mapping(address=&gt;uint256)   customer;
    }

    uint                    index;
    mapping(uint256=&gt;item)  items;
    
    function pay(uint256 _item) onlyWallet(msg.sender) public payable returns (bool success) {
        require(canBuy(msg.sender, _item));
        require((erc20==address(0)?msg.value:ERC20Interface(erc20).allowance(msg.sender,this))==items[_item].price);
        
        if(erc20!=address(0))
            ERC20Interface(erc20).transferFrom(msg.sender,this,items[_item].price);
        
        if(items[_item].category==1 || items[_item].category==2 &amp;&amp; now &gt; safeAdd(items[_item].customer[msg.sender], 1 weeks))
            items[_item].customer[msg.sender]   = now;
        else if(items[_item].category==2 &amp;&amp; now &lt; safeAdd(items[_item].customer[msg.sender], 1 weeks) )
            items[_item].customer[msg.sender]   = safeAdd(items[_item].customer[msg.sender], 1 weeks);
        else if(items[_item].category==3) {
            items[_item].customer[msg.sender]   = safeAdd(items[_item].customer[msg.sender],1);
            items[_item].stockCount             = safeSub(items[_item].stockCount,1);
        }

        emit Pay(msg.sender,_item,items[_item].customer[msg.sender]);
        return true;
    }
    
    function payCancel(uint256 _item) onlyWallet(msg.sender) public returns (bool success) {
        require (items[_item].category==2&amp;&amp;safeAdd(items[_item].customer[msg.sender],2 weeks)&gt;now&amp;&amp;balanceOf(erc20)&gt;=items[_item].price);

        items[_item].customer[msg.sender]  = safeSub(items[_item].customer[msg.sender],1 weeks);
        transfer(msg.sender, erc20, items[_item].price);
        _Wallet(msg.sender).refund(erc20,_item,items[_item].price);
        emit Refund(msg.sender,_item,items[_item].price);

        return true;
    }
    function refund(address _to, uint256 _item) onlyWallet(_to) onlyOwner public payable returns (bool success) {
        require(isBuyer(_to,_item)&amp;&amp;items[_item].category&gt;0&amp;&amp;(items[_item].customer[_to]&gt;0||(items[_item].category==2&amp;&amp;safeAdd(items[_item].customer[_to],2 weeks)&gt;now)));
        require((erc20==address(0)?address(this).balance:ERC20Interface(erc20).balanceOf(this))&gt;=items[_item].price);

        if(items[_item].category==1)
            items[_item].customer[_to]  = 0;
        else if(items[_item].category==2)
            items[_item].customer[_to]  = safeSub(items[_item].customer[_to],1 weeks);
        else
            items[_item].customer[_to]  = safeSub(items[_item].customer[_to],1);
            
        transfer(_to, erc20, items[_item].price);
        _Wallet(_to).refund(erc20,_item,items[_item].price);
        emit Refund(_to,_item,items[_item].price);

        return true;
    }
    
    event Item(uint256 indexed _item, uint256 _price);
    function resister(uint8 _category, uint256 _price, uint256 _stock) onlyOwner public returns (uint256 _itemId) {
        require(_category&gt;0&amp;&amp;_category&lt;4);
        require(_price&gt;0);
        items[index]    = item(_category,_price,_stock);
        index = safeAdd(index,1);
        emit Item(index,_price);
        return safeSub(index,1);
    }
    function update(uint256 _item, uint256 _price, uint256 _stock) onlyOwner public {
        require(items[_item].category&gt;0);
        require(_price&gt;0);
        uint256 temp = items[_item].price;
        items[_item].price      = _price;
        items[_item].stockCount = safeAdd(items[_item].stockCount,_stock);
        
        if(temp!=items[_item].price)
            emit Item(index,items[_item].price);
    }
    
    function price(uint256 _item) public constant returns (address _erc20, uint256 _value) {
        return (erc20,items[_item].price);
    }
    
    function canBuy(address _who, uint256 _item) public constant returns (bool _canBuy) {
        return  (items[_item].category&gt;0) &amp;&amp;
                !(items[_item].category==1&amp;&amp;items[_item].customer[_who]&gt;0) &amp;&amp;
                (items[_item].stockCount&gt;0);
    }
    
    function isBuyer(address _who, uint256 _item) public constant returns (bool _buyer) {
        return (items[_item].category==1&amp;&amp;items[_item].customer[_who]&gt;0)||(items[_item].category==2&amp;&amp;safeAdd(items[_item].customer[_who],1 weeks)&gt;now)||(items[_item].category==3&amp;&amp;items[_item].customer[_who]&gt;0);
    }
    
    uint lastWithdrawal;
    function withdrawal(address _erc20, uint256 _value) onlyOwner public returns (bool success) {
        require(safeAdd(lastWithdrawal,1 weeks)&lt;=now);
        require((_erc20==address(0)?address(this).balance:ERC20Interface(_erc20).balanceOf(this))&gt;=_value);
        if(_erc20==address(0))
            owner.transfer(_value);
        else
            ERC20Interface(_erc20).transfer(owner,_value);
        lastWithdrawal = now;
        return true;
    }
}

contract WalletCenter {
    mapping(address=&gt;bool) public     wallet;
    event Wallet(address indexed _owner, address indexed _wallet);
    function createWallet() public returns (address _wallet) {
        _wallet = new _Wallet(msg.sender);
        wallet[_wallet] = true;
        emit Wallet(msg.sender,_wallet);
        return _wallet;
    }
    function isWallet(address _wallet) public constant returns (bool) {
        return wallet[_wallet];
    }
    mapping(address=&gt;bool) public     shop;
    event Shop(address indexed _owner, address indexed _shop, address indexed _erc20);
    function createShop(address _erc20) public returns (address _shop) {
        _shop   = new _Shop(msg.sender,_erc20);
        shop[_shop] = true;
        emit Shop(msg.sender,_shop,_erc20);
        return _shop;
    }
    function isShop(address _shop) public constant returns (bool) {
        return shop[_shop];
    }
}
```
## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 21 Jun 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1175</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1175</guid>
      </item>
    
      <item>
        <title>Multi-class Token Standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1179</comments>
        
        <description>## Simple Summary
A standard interface for multi-class fungible tokens.
## Abstract
This standard allows for the implementation of a standard API for multi-class fungible tokens (henceforth referred to as &quot;MCFTs&quot;) within smart contracts. This standard provides basic functionality to track and transfer ownership of MCFTs.
## Motivation
Currently, there is no standard to support tokens that have multiple classes. In the real world, there are many situations in which defining distinct classes of the same token would be fitting (e.g. distinguishing between preferred/common/restricted shares of a company). Yet, such nuance cannot be supported in today&apos;s token standards. An ERC-20 token contract defines tokens that are all of one class while an ERC-721 token contract creates a class (defined by token_id) for each individual token. The ERC-1178 token standard proposes a new standard for creating multiple classes of tokens within one token contract.

&gt; Aside: In theory, while it is possible to implement tokens with classes using the properties of token structs in ERC-721 tokens, gas costs of implementing this in practice are prohibitive for any non-trivial application.

## Specification
### ERC-20 Compatibility (partial)
**name**

```solidity    
function name() constant returns (string name)
```

*OPTIONAL - It is recommended that this method is implemented for enhanced usability with wallets and exchanges, but interfaces and other contracts MUST NOT depend on the existence of this method.*

Returns the name of the aggregate collection of MCFTs managed by this contract. - e.g. `&quot;My Company Tokens&quot;`.

**class name**

```solidity    
function className(uint256 classId) constant returns (string name)
```

*OPTIONAL - It is recommended that this method is implemented for enhanced usability with wallets and exchanges, but interfaces and other contracts MUST NOT depend on the existence of this method.*

Returns the name of the class of MCFT managed by this contract. - e.g. `&quot;My Company Preferred Shares Token&quot;`.

**symbol**
```solidity    
function symbol() constant returns (string symbol)
```

*OPTIONAL - It is recommend that this method is implemented for enhanced usability with wallets and exchanges, but interfaces and other contracts MUST NOT depend on the existence of this method.*

Returns a short string symbol referencing the entire collection of MCFT managed in this contract. e.g. &quot;MUL&quot;. This symbol SHOULD be short (3-8 characters is recommended), with no whitespace characters or new-lines and SHOULD be limited to the uppercase latin alphabet (i.e. the 26 letters used in English).

**totalSupply**
```solidity    
function totalSupply() constant returns (uint256 totalSupply)
```
Returns the total number of all MCFTs currently tracked by this contract.

**individualSupply**
```solidity    
function individualSupply(uint256 _classId) constant returns (uint256 individualSupply)
```
Returns the total number of MCFTs of class `_classId` currently tracked by this contract.

**balanceOf**
```solidity
function balanceOf(address _owner, uint256 _classId) constant returns (uint256 balance)
```

Returns the number of MCFTs of token class `_classId` assigned to address `_owner`.

**classesOwned**
```solidity
function classesOwned(address _owner) constant returns (uint256[] classes)
```

Returns an array of `_classId`&apos;s of MCFTs that address `_owner` owns in the contract. 
&gt; NOTE: returning an array is supported by `pragma experimental ABIEncoderV2`

## Basic Ownership

**approve**
```solidity    
function approve(address _to, uint256 _classId, uint256 quantity)
```
Grants approval for address `_to` to take possession `quantity` amount of the MCFT with ID `_classId`. This method MUST `throw` if `balanceOf(msg.sender, _classId) &lt; quantity`, or if `_classId` does not represent an MCFT class currently tracked by this contract, or if `msg.sender == _to`.

Only one address can &quot;have approval&quot; at any given time for a given address and `_classId`. Calling `approve` with a new address and `_classId` revokes approval for the previous address and `_classId`. Calling this method with 0 as the `_to` argument clears approval for any address and the specified `_classId`.

Successful completion of this method MUST emit an `Approval` event (defined below) unless the caller is attempting to clear approval when there is no pending approval. In particular, an Approval event MUST be fired if the `_to` address is zero and there is some outstanding approval. Additionally, an Approval event MUST be fired if `_to` is already the currently approved address and this call otherwise has no effect. (i.e. An `approve()` call that &quot;reaffirms&quot; an existing approval MUST fire an event.)

&lt;!--
ActionPrior State_to addressNew StateEventClear unset approvalClear0ClearNoneSet new approvalClearXSet to XApproval(owner, X, _classId)Change approvalSet to XYSet to YApproval(owner, Y, _classId)Reaffirm approvalSet to XXSet to XApproval(owner, X, _classId)Clear approvalSet to X0ClearApproval(owner, 0, _classId)
Note: ANY change of ownership of an MCFT – whether directly through the `transfer` and `transferFrom` methods defined in this interface, or through any other mechanism defined in the conforming contract – MUST clear any and all approvals for the transferred MCFT. The implicit clearing of approval via ownership transfer MUST also fire the event `Approval(0, _classId)` if there was an outstanding approval. (i.e. All actions that transfer ownership must emit the same Approval event, if any, as would emitted by calling `approve(0, _classId)`.)--&gt;

**transfer**
```solidity
function transfer(address _to, uint256 _classId, uint256 quantity)
```
Assigns the ownership of `quantity` MCFT&apos;s with ID `_classId` to `_to` if and only if `quantity == balanceOf(msg.sender, _classId)`. A successful transfer MUST fire the `Transfer` event (defined below).

This method MUST transfer ownership to `_to` or `throw`, no other outcomes can be possible. Reasons for failure include (but are not limited to):

* `msg.sender` is not the owner of `quantity` amount of tokens of `_classId`&apos;s. 
* `_classId` does not represent an MCFT class currently tracked by this contract

A conforming contract MUST allow the current owner to &quot;transfer&quot; a token to themselves, as a way of affirming ownership in the event stream. (i.e. it is valid for `_to == msg.sender` if `balanceOf(msg.sender, _classId) &gt;= balance`.) This &quot;no-op transfer&quot; MUST be considered a successful transfer, and therefore MUST fire a `Transfer` event (with the same address for `_from` and `_to`).

## Advanced Ownership and Exchange
```solidity
function approveForToken(uint256 classIdHeld, uint256 quantityHeld, uint256 classIdWanted, uint256 quantityWanted)
```
Allows holder of one token to allow another individual (or the smart contract itself) to approve the exchange of their tokens of one class for tokens of another class at their specified exchange rate (see sample implementation for more details). This is equivalent to posting a bid in a marketplace. 

```solidity
function exchange(address to, uint256 classIdPosted, uint256 quantityPosted, uint256 classIdWanted, uint256 quantityWanted)
```
Allows an individual to fill an existing bid (see above function) and complete the exchange of their tokens of one class for another. In the sample implementation, this function call should fail unless the callee has already approved the contract to transfer their tokens. Of course, it is possible to create an implementation where calling this function implicitly assumes approval and the transfer is completed in one step. 

```solidity
transferFrom(address from, address to, uint256 classId)
```
Allows a third party to initiate a transfer of tokens from `from` to `to` assuming the approvals have been granted.

## Events
**Transfer**

This event MUST trigger when MCFT ownership is transferred via any mechanism.

Additionally, the creation of new MCFTs MUST trigger a Transfer event for each newly created MCFTs, with a `_from` address of 0 and a `_to` address matching the owner of the new MCFT (possibly the smart contract itself). The deletion (or burn) of any MCFT MUST trigger a Transfer event with a `_to` address of 0 and a `_from` address of the owner of the MCFT (now former owner!).

NOTE: A Transfer event with `_from == _to` is valid. See the `transfer()` documentation for details.

```solidity
event Transfer(address indexed _from, address indexed _to, uint256 _classId)
```
    
**Approval**
This event MUST trigger on any successful call to `approve(_to, _classId, quantity)` (unless the caller is attempting to clear approval when there is no pending approval).

```solidity
event Approval(address indexed _owner, address indexed _approved, uint256 _classId)
```
## Rationale
### Current Limitations
The design of this project was motivated when I tried to create different classes of fungible ERC-721 tokens (an oxymoron) but ran into gas limits from having to create each tokens individually and maintain them in an efficient data structure for access. Using the maximum gas amount one can send with a transaction on Metamask (a popular web wallet), I was only able to create around 46 ERC-721 tokens before exhausting all gas. This experience motivated the creation of the multi-class fungible token standard. 


## Backwards Compatibility
Adoption of the MCFT standard proposal would not pose backwards compatibility issues as it defines a new standard for token creation. This standard follows the semantics of ERC-721 as closely as possible, but can&apos;t be entirely compatible with it due to the fundamental differences between multi-class fungible and non-fungible tokens. For example, the `ownerOf`, `takeOwnership`, and `tokenOfOwnerByIndex` methods in the ERC-721 token standard cannot be implemented in this standard. Furthermore, the function arguments to `balanceOf`, `approve`, and `transfer` differ as well. 

## Implementation
A sample implementation can be found [here](https://github.com/achon22/ERC-1178/blob/master/erc1178-sample.sol)

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Fri, 22 Jun 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1178</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1178</guid>
      </item>
    
      <item>
        <title>Storage of DNS Records in ENS</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip1185-dns-resolver-profile-for-ens/1589</comments>
        
        <description>## Abstract

This EIP defines a resolver profile for ENS that provides features for storage and lookup of DNS records. This allows ENS to be used as a store of authoritative DNS information.

## Motivation

ENS is a highly desirable store for DNS information.  It provides the distributed authority of DNS without conflating ownership and authoritative serving of information.  With ENS, the owner of a domain has full control over their own DNS records.  Also, ENS has the ability (through smart contracts) for a domain&apos;s subdomains to be irrevocably assigned to another entity.

## Specification

The resolver profile to support DNS on ENS follows the resolver specification as defined in [ERC-137](/EIPs/EIPS/eip-137).

Traditionally, DNS is a zone-based system in that all of the records for a zone are kept together in the same file.  This has the benefit of simplicity and atomicity of zone updates, but when transposed to ENS can result in significant gas costs for simple changes.  As a result, the resolver works on the basis of record sets.  A record set is uniquely defined by the tuple `(domain, name, resource record type)`, for example the tuple `(example.com, www.example.com, A)` defines the record set of `A` records for the name `www.example.com` in the domain `example.com`.  A record set can contain 0 or more values, for example if `www.example.com` has `A` records `1.2.3.4` and `5.6.7.8` then the aforementioned tuple will have two values.

The choice to work at the level of record sets rather than zones means that this specification cannot completely support some features of DNS, such as zone transfers and DNSSEC.  It would be possible to build a different resolver profile that works at the zone level, however it would be very expensive to carry out updates and so is not considered further for this EIP.

The DNS resolver interface consists of two functions to set DNS information and two functions to query DNS information.

### setDNSRecords(bytes32 node, bytes data)

`setDNSRecords()` sets, updates or clears 1 or more DNS records for a given node.  It has function signature `0x0af179d7`.

The arguments for the function are as follows:

  - node: the namehash of the fully-qualified domain in ENS for which to set the records.  Namehashes are defined in [ERC-137](/EIPs/EIPS/eip-137)
  - data: 1 or more DNS records in DNS wire format.  Any record that is supplied without a value will be cleared.  Note that all records in the same RRset should be contiguous within the data; if not then the later RRsets will overwrite the earlier one(s)


### clearDNSZone(bytes32 node)

`clearDNSZone()` removes all DNS records for the domain.  It has function signature `0xad5780af`.

Although it is possible to clear records individually with `setDNSRecords()` as described above this requires the owner to know all of the records that have been set (as the resolver has no methods to iterate over the records for a given domain), and might require multiple transactions.  `clearDNSZone()` removes all zone information in a single operation.

The arguments for the function is as follows:

  - node: the namehash of the fully-qualified domain in ENS for which to clear the records.  Namehashes are defined in [ERC-137](/EIPs/EIPS/eip-137)

### dnsRecords(bytes32 node, bytes32 name, uint16 resource) view returns (bytes)

`dnsRecords()` obtains the DNS records for a given node, name and resource.  It has function signature `0x2461e851`.

The arguments for the function are as follows:

  - node: the namehash of the fully-qualified domain in ENS for which to set the records.  Namehashes are defined in [ERC-137](/EIPs/EIPS/eip-137)
  - name: the `keccak256()` hash of the name of the record in DNS wire format.
  - resource: the resource record ID.  Resource record IDs are defined in RFC1035 and subsequent RFCs.

The function returns all matching records in DNS wire format.  If there are no records present the function will return nothing.

### hasDNSRecords(bytes32 node, bytes32 name) view returns (bool)

`hasDNSRecords()` reports if there are any records for the provided name in the domain.  It has function signature `0x4cbf6ba4`.

This function is needed by DNS resolvers when working with wildcard resources as defined in RFC4592.

The arguments for the function are as follows:

  - node: the namehash of the fully-qualified domain in ENS for which to set the records.  Namehashes are defined in [ERC-137](/EIPs/EIPS/eip-137)
  - name: the `keccak256()` hash of the name of the record in DNS wire format.

The function returns `true` if there are any records for the provided node and name, otherwise `false`.

## Rationale

DNS is a federated system of naming, and the higher-level entities control availability of everything beneath them (_e.g._ `.org` controls the availability of `ethereum.org`).  A decentralized version of DNS would not have this constraint, and allow lookups directly for any domain with relevant records within ENS.

## Backwards Compatibility

Not applicable.

## Reference Implementation

The reference implementation of the DNS resolver is as follows:

```solidity
pragma solidity ^0.7.4;
import &quot;../ResolverBase.sol&quot;;
import &quot;@ensdomains/dnssec-oracle/contracts/RRUtils.sol&quot;;

abstract contract DNSResolver is ResolverBase {
    using RRUtils for *;
    using BytesUtils for bytes;

    bytes4 constant private DNS_RECORD_INTERFACE_ID = 0xa8fa5682;
    bytes4 constant private DNS_ZONE_INTERFACE_ID = 0x5c47637c;

    // DNSRecordChanged is emitted whenever a given node/name/resource&apos;s RRSET is updated.
    event DNSRecordChanged(bytes32 indexed node, bytes name, uint16 resource, bytes record);
    // DNSRecordDeleted is emitted whenever a given node/name/resource&apos;s RRSET is deleted.
    event DNSRecordDeleted(bytes32 indexed node, bytes name, uint16 resource);
    // DNSZoneCleared is emitted whenever a given node&apos;s zone information is cleared.
    event DNSZoneCleared(bytes32 indexed node);

    // DNSZonehashChanged is emitted whenever a given node&apos;s zone hash is updated.
    event DNSZonehashChanged(bytes32 indexed node, bytes lastzonehash, bytes zonehash);

    // Zone hashes for the domains.
    // A zone hash is an ERC-1577 content hash in binary format that should point to a
    // resource containing a single zonefile.
    // node =&gt; contenthash
    mapping(bytes32=&gt;bytes) private zonehashes;

    // Version the mapping for each zone.  This allows users who have lost
    // track of their entries to effectively delete an entire zone by bumping
    // the version number.
    // node =&gt; version
    mapping(bytes32=&gt;uint256) private versions;

    // The records themselves.  Stored as binary RRSETs
    // node =&gt; version =&gt; name =&gt; resource =&gt; data
    mapping(bytes32=&gt;mapping(uint256=&gt;mapping(bytes32=&gt;mapping(uint16=&gt;bytes)))) private records;

    // Count of number of entries for a given name.  Required for DNS resolvers
    // when resolving wildcards.
    // node =&gt; version =&gt; name =&gt; number of records
    mapping(bytes32=&gt;mapping(uint256=&gt;mapping(bytes32=&gt;uint16))) private nameEntriesCount;

    /**
     * Set one or more DNS records.  Records are supplied in wire-format.
     * Records with the same node/name/resource must be supplied one after the
     * other to ensure the data is updated correctly. For example, if the data
     * was supplied:
     *     a.example.com IN A 1.2.3.4
     *     a.example.com IN A 5.6.7.8
     *     www.example.com IN CNAME a.example.com.
     * then this would store the two A records for a.example.com correctly as a
     * single RRSET, however if the data was supplied:
     *     a.example.com IN A 1.2.3.4
     *     www.example.com IN CNAME a.example.com.
     *     a.example.com IN A 5.6.7.8
     * then this would store the first A record, the CNAME, then the second A
     * record which would overwrite the first.
     *
     * @param node the namehash of the node for which to set the records
     * @param data the DNS wire format records to set
     */
    function setDNSRecords(bytes32 node, bytes calldata data) external authorised(node) {
        uint16 resource = 0;
        uint256 offset = 0;
        bytes memory name;
        bytes memory value;
        bytes32 nameHash;
        // Iterate over the data to add the resource records
        for (RRUtils.RRIterator memory iter = data.iterateRRs(0); !iter.done(); iter.next()) {
            if (resource == 0) {
                resource = iter.dnstype;
                name = iter.name();
                nameHash = keccak256(abi.encodePacked(name));
                value = bytes(iter.rdata());
            } else {
                bytes memory newName = iter.name();
                if (resource != iter.dnstype || !name.equals(newName)) {
                    setDNSRRSet(node, name, resource, data, offset, iter.offset - offset, value.length == 0);
                    resource = iter.dnstype;
                    offset = iter.offset;
                    name = newName;
                    nameHash = keccak256(name);
                    value = bytes(iter.rdata());
                }
            }
        }
        if (name.length &gt; 0) {
            setDNSRRSet(node, name, resource, data, offset, data.length - offset, value.length == 0);
        }
    }

    /**
     * Obtain a DNS record.
     * @param node the namehash of the node for which to fetch the record
     * @param name the keccak-256 hash of the fully-qualified name for which to fetch the record
     * @param resource the ID of the resource as per https://en.wikipedia.org/wiki/List_of_DNS_record_types
     * @return the DNS record in wire format if present, otherwise empty
     */
    function dnsRecord(bytes32 node, bytes32 name, uint16 resource) public view returns (bytes memory) {
        return records[node][versions[node]][name][resource];
    }

    /**
     * Check if a given node has records.
     * @param node the namehash of the node for which to check the records
     * @param name the namehash of the node for which to check the records
     */
    function hasDNSRecords(bytes32 node, bytes32 name) public view returns (bool) {
        return (nameEntriesCount[node][versions[node]][name] != 0);
    }

    /**
     * Clear all information for a DNS zone.
     * @param node the namehash of the node for which to clear the zone
     */
    function clearDNSZone(bytes32 node) public authorised(node) {
        versions[node]++;
        emit DNSZoneCleared(node);
    }

    /**
     * setZonehash sets the hash for the zone.
     * May only be called by the owner of that node in the ENS registry.
     * @param node The node to update.
     * @param hash The zonehash to set
     */
    function setZonehash(bytes32 node, bytes calldata hash) external authorised(node) {
        bytes memory oldhash = zonehashes[node];
        zonehashes[node] = hash;
        emit DNSZonehashChanged(node, oldhash, hash);
    }

    /**
     * zonehash obtains the hash for the zone.
     * @param node The ENS node to query.
     * @return The associated contenthash.
     */
    function zonehash(bytes32 node) external view returns (bytes memory) {
        return zonehashes[node];
    }

    function supportsInterface(bytes4 interfaceID) virtual override public pure returns(bool) {
        return interfaceID == DNS_RECORD_INTERFACE_ID ||
               interfaceID == DNS_ZONE_INTERFACE_ID ||
               super.supportsInterface(interfaceID);
    }

    function setDNSRRSet(
        bytes32 node,
        bytes memory name,
        uint16 resource,
        bytes memory data,
        uint256 offset,
        uint256 size,
        bool deleteRecord) private
    {
        uint256 version = versions[node];
        bytes32 nameHash = keccak256(name);
        bytes memory rrData = data.substring(offset, size);
        if (deleteRecord) {
            if (records[node][version][nameHash][resource].length != 0) {
                nameEntriesCount[node][version][nameHash]--;
            }
            delete(records[node][version][nameHash][resource]);
            emit DNSRecordDeleted(node, name, resource);
        } else {
            if (records[node][version][nameHash][resource].length == 0) {
                nameEntriesCount[node][version][nameHash]++;
            }
            records[node][version][nameHash][resource] = rrData;
            emit DNSRecordChanged(node, name, resource, rrData);
        }
    }
}
```

## Security Considerations

Security of this solution would be dependent on security of the records within the ENS domain.  This degenenrates to the security of the key(s) which have authority over that domain.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 26 Jun 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1185</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1185</guid>
      </item>
    
      <item>
        <title>RPC-Method to get Merkle Proofs - eth_getProof</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1186</comments>
        
        <description>## Simple Summary

One of the great features of Ethereum is the fact, that you can verify all data of the state. But in order to allow verification of accounts outside the client, we need an additional function delivering us the required proof. These proofs are important to secure Layer2-Technologies.

## Abstract

Ethereum uses a [Merkle Tree](https://github.com/ethereum/eth-wiki/blob/master/fundamentals/patricia-tree.md) to store the state of accounts and their storage. This allows verification of each value by simply creating a Merkle Proof. But currently, the standard RPC-Interface does not give you access to these proofs. This EIP suggests an additional RPC-Method, which creates Merkle Proofs for Accounts and Storage Values. 

Combined with a stateRoot (from the blockheader) it enables offline verification of any account or storage-value. This allows especially IOT-Devices or even mobile apps which are not able to run a light client to verify responses from an untrusted source only given a trusted blockhash.

## Motivation

In order to create a MerkleProof access to the full state db is required. The current RPC-Methods allow an application to access single values (`eth_getBalance`,`eth_getTransactionCount`,`eth_getStorageAt`,`eth_getCode`), but it is impossible to read the data needed for a  MerkleProof through the standard RPC-Interface. (There are implementations using leveldb and accessing the data via filesystems, but this can not be used for production systems since it requires the client to be stopped first - See https://github.com/zmitton/eth-proof) 

Today MerkleProofs are already used internally. For example, the [Light Client Protocol](https://github.com/zsfelfoldi/go-ethereum/wiki/Light-Ethereum-Subprotocol-%28LES%29#on-demand-data-retrieval) supports a function creating MerkleProof, which is used in order to verify the requested account or storage-data.

Offering these already existing function through the RPC-Interface as well would enable Applications to store and send these proofs to devices which are not directly connected to the p2p-network and still are able to verify the data. This could be used to verify data in mobile applications or IOT-devices, which are currently only using a remote client.


## Specification

As Part of the eth-Module, an additional Method called `eth_getProof` should be defined as follows:

#### eth_getProof

Returns the account- and storage-values of the specified account including the Merkle-proof.  

##### Parameters

1. `DATA`, 20 Bytes - address of the account.
2. `ARRAY`, 32 Bytes - array of storage-keys which should be proofed and included. See [`eth_getStorageAt`](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getstorageat)  
3. `QUANTITY|TAG` - integer block number, or the string `&quot;latest&quot;` or `&quot;earliest&quot;`, see the [default block parameter](https://github.com/ethereum/wiki/wiki/JSON-RPC#the-default-block-parameter)

##### Returns

`Object` - A account object:

  - `balance`: `QUANTITY` - the balance of the account. See [`eth_getBalance`](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getbalance) 
  - `codeHash`: `DATA`, 32 Bytes - hash of the code of the account. For a simple Account without code it will return `&quot;0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470&quot;` 
  - `nonce`: `QUANTITY`, - nonce of the account. See [`eth_getTransactionCount`](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactioncount) 
  - `storageHash`: `DATA`, 32 Bytes - SHA3 of the StorageRoot. All storage will deliver a MerkleProof starting with this rootHash.
  - `accountProof`: `ARRAY` - Array of rlp-serialized MerkleTree-Nodes, starting with the stateRoot-Node, following the path of the SHA3 (address) as key. 
  - `storageProof`: `ARRAY` - Array of storage-entries as requested. Each entry is an object with these properties:
  
      - `key`: `QUANTITY` - the requested storage key
      - `value`: `QUANTITY` - the storage value
      - `proof`: `ARRAY` - Array of rlp-serialized MerkleTree-Nodes, starting with the storageHash-Node, following the path of the SHA3 (key) as path. 
      

##### Example


```json
{
  &quot;id&quot;: 1,
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;method&quot;: &quot;eth_getProof&quot;,
  &quot;params&quot;: [
    &quot;0x7F0d15C7FAae65896648C8273B6d7E43f58Fa842&quot;,
    [  &quot;0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421&quot; ],
    &quot;latest&quot;
  ]
}
```

The result will look like this:

```json
{
  &quot;id&quot;: 1,
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;result&quot;: {
    &quot;accountProof&quot;: [
      &quot;0xf90211a...0701bc80&quot;,
      &quot;0xf90211a...0d832380&quot;,
      &quot;0xf90211a...5fb20c80&quot;,
      &quot;0xf90211a...0675b80&quot;,
      &quot;0xf90151a0...ca08080&quot;
    ],
    &quot;balance&quot;: &quot;0x0&quot;,
    &quot;codeHash&quot;: &quot;0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470&quot;,
    &quot;nonce&quot;: &quot;0x0&quot;,
    &quot;storageHash&quot;: &quot;0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421&quot;,
    &quot;storageProof&quot;: [
      {
        &quot;key&quot;: &quot;0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421&quot;,
        &quot;proof&quot;: [
          &quot;0xf90211a...0701bc80&quot;,
          &quot;0xf90211a...0d832380&quot;
        ],
        &quot;value&quot;: &quot;0x1&quot;
      }
    ]
  }
}
```

## Rationale

This one Method actually returns 3 different important data points:

1. The 4 fields of an account-object as specified in the yellow paper `[nonce, balance, storageHash, codeHash ]`, which allows storing a hash of the account-object in order to keep track of changes.
2. The MerkleProof for the account starting with a stateRoot from the specified block.
3. The MerkleProof for each requested storage entry starting with a storageHash from the account.

Combining these in one Method allows the client to work very efficient since the required data are already fetched from the db.

### Proofs for non existent values

In case an address or storage-value does not exist, the proof needs to provide enough data to verify this fact. This means the client needs to follow the path from the root node and deliver until the last matching node. If the last matching node is a branch, the proof value in the node must be an empty one. In case of leaf-type, it must be pointing to a different relative-path in order to proof that the requested path does not exist.

### possible Changes to be discussed:

- instead of providing the blocknumber maybe the blockhash would be better since it would allow proofs of uncles-states.
- in order to reduce data, the account-object may only provide the `accountProof` and `storageProof`. The Fields `balance`, `nonce`, `storageHash` and `codeHash` could be taken from the last Node in the proof by deserializing it. 

## Backwards Compatibility

Since this only adds a new Method there are no issues with Backwards Compatibility.

## Test Cases

TODO: Tests still need to be implemented, but the core function creating the proof already exists inside the clients and are well tested.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 24 Jun 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1186</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1186</guid>
      </item>
    
      <item>
        <title>Add chain id to mixed-case checksum address encoding</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1121</comments>
        
        <description>## Simple Summary

This EIP extends [EIP-55](/EIPs/EIPS/eip-55) by optionally adding a chain id defined by [EIP-155](/EIPs/EIPS/eip-155) to the checksum calculation.

## Abstract

The [EIP-55](/EIPs/EIPS/eip-55) was created to prevent users from losing funds by sending them to invalid addresses. This EIP extends [EIP-55](/EIPs/EIPS/eip-55) 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.  

## Motivation

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 [EIP-55](/EIPs/EIPS/eip-55) checksum algorithm it is possible to achieve this objective.

## Specification

Convert the address using the same algorithm defined by [EIP-55](/EIPs/EIPS/eip-55) 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 `0x` separator before calculating the hash. Then convert the address to hexadecimal, but if the ith digit is a letter (ie. it&apos;s one of `abcdef`) print it in uppercase if the 4*ith bit of the calculated hash is 1 otherwise print it in lowercase.

## Rationale

 Benefits:
 
 - By means of a minimal code change on existing libraries, users are protected from losing funds by mixing addresses of different Ethereum based networks.

## Implementation

```python
#!/usr/bin/python3
from sha3 import keccak_256
import random
&quot;&quot;&quot;
   addr (str): Hexadecimal address, 40 characters long with 2 characters prefix
   chainid (int): chain id from EIP-155 &quot;&quot;&quot;
def eth_checksum_encode(addr, chainid=1):
    adopted_eip1191 = [30, 31]
    hash_input = str(chainid) + addr.lower() if chainid in adopted_eip1191 else addr[2:].lower()
    hash_output = keccak_256(hash_input.encode(&apos;utf8&apos;)).hexdigest()
    aggregate = zip(addr[2:].lower(),hash_output)
    out = addr[:2] + &apos;&apos;.join([c.upper() if int(a,16) &gt;= 8 else c for c,a in aggregate])
    return out
```

## Test Cases

```python
eth_mainnet = [
&quot;0x27b1fdb04752bbc536007a920d24acb045561c26&quot;,
&quot;0x3599689E6292b81B2d85451025146515070129Bb&quot;,
&quot;0x42712D45473476b98452f434e72461577D686318&quot;,
&quot;0x52908400098527886E0F7030069857D2E4169EE7&quot;,
&quot;0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed&quot;,
&quot;0x6549f4939460DE12611948b3f82b88C3C8975323&quot;,
&quot;0x66f9664f97F2b50F62D13eA064982f936dE76657&quot;,
&quot;0x8617E340B3D01FA5F11F306F4090FD50E238070D&quot;,
&quot;0x88021160C5C792225E4E5452585947470010289D&quot;,
&quot;0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb&quot;,
&quot;0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB&quot;,
&quot;0xde709f2102306220921060314715629080e2fb77&quot;,
&quot;0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359&quot;,
]
rsk_mainnet = [
&quot;0x27b1FdB04752BBc536007A920D24ACB045561c26&quot;,
&quot;0x3599689E6292B81B2D85451025146515070129Bb&quot;,
&quot;0x42712D45473476B98452f434E72461577d686318&quot;,
&quot;0x52908400098527886E0F7030069857D2E4169ee7&quot;,
&quot;0x5aaEB6053f3e94c9b9a09f33669435E7ef1bEAeD&quot;,
&quot;0x6549F4939460DE12611948B3F82B88C3C8975323&quot;,
&quot;0x66F9664f97f2B50F62d13EA064982F936de76657&quot;,
&quot;0x8617E340b3D01Fa5f11f306f4090fd50E238070D&quot;,
&quot;0x88021160c5C792225E4E5452585947470010289d&quot;,
&quot;0xD1220A0Cf47c7B9BE7a2e6ba89F429762E7B9adB&quot;,
&quot;0xDBF03B407c01E7CD3cBea99509D93F8Dddc8C6FB&quot;,
&quot;0xDe709F2102306220921060314715629080e2FB77&quot;,
&quot;0xFb6916095cA1Df60bb79ce92cE3EA74c37c5d359&quot;,
]
rsk_testnet = [
&quot;0x27B1FdB04752BbC536007a920D24acB045561C26&quot;,
&quot;0x3599689e6292b81b2D85451025146515070129Bb&quot;,
&quot;0x42712D45473476B98452F434E72461577D686318&quot;,
&quot;0x52908400098527886E0F7030069857D2e4169EE7&quot;,
&quot;0x5aAeb6053F3e94c9b9A09F33669435E7EF1BEaEd&quot;,
&quot;0x6549f4939460dE12611948b3f82b88C3c8975323&quot;,
&quot;0x66f9664F97F2b50f62d13eA064982F936DE76657&quot;,
&quot;0x8617e340b3D01fa5F11f306F4090Fd50e238070d&quot;,
&quot;0x88021160c5C792225E4E5452585947470010289d&quot;,
&quot;0xd1220a0CF47c7B9Be7A2E6Ba89f429762E7b9adB&quot;,
&quot;0xdbF03B407C01E7cd3cbEa99509D93f8dDDc8C6fB&quot;,
&quot;0xDE709F2102306220921060314715629080e2Fb77&quot;,
&quot;0xFb6916095CA1dF60bb79CE92ce3Ea74C37c5D359&quot;,
]
test_cases = {30 : rsk_mainnet, 31 : rsk_testnet, 1 : eth_mainnet}

for chainid, cases in test_cases.items():
    for addr in cases:
        assert ( addr == eth_checksum_encode(addr,chainid) )
```

## Usage

### Usage  Table

| Network      | Chain id | Supports this EIP |
|-|-|-|
| RSK Mainnet  | 30       | Yes               |
| RSK Testnet  | 31       | Yes               |

### Implementation Table

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

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</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>Ethereum Provider JavaScript API</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2319</comments>
        
        <description>## Summary

A JavaScript Ethereum Provider API for consistency across clients and applications.

## Abstract

A common convention in the Ethereum web application (&quot;dapp&quot;) ecosystem is for key management software (&quot;wallets&quot;) to expose their API via a JavaScript object in the web page.
This object is called &quot;the Provider&quot;.

Historically, Provider implementations have exhibited conflicting interfaces and behaviors between wallets.
This EIP formalizes an Ethereum Provider API to promote wallet interoperability.
The API is designed to be minimal, event-driven, and agnostic of transport and RPC protocols.
Its functionality is easily extended by defining new RPC methods and `message` event types.

Historically, Providers have been made available as `window.ethereum` in web browsers, but this convention is not part of the specification.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC-2119](https://www.ietf.org/rfc/rfc2119.txt).

&gt; Comments like this are non-normative.

### Definitions

_This section is non-normative._

- Provider
  - A JavaScript object made available to a consumer, that provides access to Ethereum by means of a Client.
- Client
  - An endpoint that receives Remote Procedure Call (RPC) requests from the Provider, and returns their results.
- Wallet
  - An end-user application that manages private keys, performs signing operations, and acts as a middleware between the Provider and the Client.
- Remote Procedure Call (RPC)
  - A Remote Procedure Call (RPC), is any request submitted to a Provider for some procedure that is to be processed by a Provider, its Wallet, or its Client.

### Connectivity

The Provider is said to be &quot;connected&quot; when it can service RPC requests to at least one chain.

The Provider is said to be &quot;disconnected&quot; when it cannot service RPC requests to any chain at all.

&gt; To service an RPC request, the Provider must successfully submit the request to the remote location, and receive a response.
&gt; In other words, if the Provider is unable to communicate with its Client, for example due to network issues, the Provider is disconnected.

### API

&gt; The Provider API is specified using TypeScript.
&gt; The authors encourage implementers to declare their own types and interfaces, using the ones in this section as a basis.
&gt;
&gt; For consumer-facing API documentation, see [Appendix I](#appendix-i-consumer-facing-api-documentation)

The Provider **MUST** implement and expose the API defined in this section.
All API entities **MUST** adhere to the types and interfaces defined in this section.

#### request

&gt; The `request` method is intended as a transport- and protocol-agnostic wrapper function for Remote Procedure Calls (RPCs).

```typescript
interface RequestArguments {
  readonly method: string;
  readonly params?: readonly unknown[] | object;
}

Provider.request(args: RequestArguments): Promise&lt;unknown&gt;;
```

The Provider **MUST** identify the requested RPC method by the value of `RequestArguments.method`.

If the requested RPC method takes any parameters, the Provider **MUST** accept them as the value of `RequestArguments.params`.

RPC requests **MUST** be handled such that the returned Promise either resolves with a value per the requested RPC method&apos;s specification, or rejects with an error.

If resolved, the Promise **MUST** resolve with a result per the RPC method&apos;s specification. The Promise **MUST NOT** resolve with any RPC protocol-specific response objects, unless the RPC method&apos;s return type is so defined.

If the returned Promise rejects, it **MUST** reject with a `ProviderRpcError` as specified in the [RPC Errors](#rpc-errors) section below.

The returned Promise **MUST** reject if any of the following conditions are met:

- An error is returned for the RPC request.
  - If the returned error is compatible with the `ProviderRpcError` interface, the Promise **MAY** reject with that error directly.
- The Provider encounters an error or fails to process the request for any reason.

&gt; If the Provider implements any kind of authorization logic, the authors recommend rejecting with a `4100` error in case of authorization failures.

The returned Promise **SHOULD** reject if any of the following conditions are met:

- The Provider is disconnected.
  - If rejecting for this reason, the Promise rejection error `code` **MUST** be `4900`.
- The RPC request is directed at a specific chain, and the Provider is not connected to that chain, but is connected to at least one other chain.
  - If rejecting for this reason, the Promise rejection error `code` **MUST** be `4901`.

See the section [Connectivity](#connectivity) for the definitions of &quot;connected&quot; and &quot;disconnected&quot;.

### Supported RPC Methods

A &quot;supported RPC method&quot; is any RPC method that may be called via the Provider.

All supported RPC methods **MUST** be identified by unique strings.

Providers **MAY** support whatever RPC methods required to fulfill their purpose, standardized or otherwise.

If an RPC method defined in a finalized EIP is not supported, it **SHOULD** be rejected with a `4200` error per the [Provider Errors](#provider-errors) section below, or an appropriate error per the RPC method&apos;s specification.

#### RPC Errors

```typescript
interface ProviderRpcError extends Error {
  code: number;
  data?: unknown;
}
```

- `message`
  - **MUST** be a human-readable string
  - **SHOULD** adhere to the specifications in the [Error Standards](#error-standards) section below
- `code`
  - **MUST** be an integer number
  - **SHOULD** adhere to the specifications in the [Error Standards](#error-standards) section below
- `data`
  - **SHOULD** contain any other useful information about the error

##### Error Standards

`ProviderRpcError` codes and messages **SHOULD** follow these conventions, in order of priority:

1. The errors in the [Provider Errors](#provider-errors) section below

2. Any errors mandated by the erroring RPC method&apos;s specification

3. The [`CloseEvent` status codes](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes)

#### Provider Errors

| Status code | Name                  | Description                                                              |
| ----------- | --------------------- | ------------------------------------------------------------------------ |
| 4001        | User Rejected Request | The user rejected the request.                                           |
| 4100        | Unauthorized          | The requested method and/or account has not been authorized by the user. |
| 4200        | Unsupported Method    | The Provider does not support the requested method.                      |
| 4900        | Disconnected          | The Provider is disconnected from all chains.                            |
| 4901        | Chain Disconnected    | The Provider is not connected to the requested chain.                    |

&gt; `4900` is intended to indicate that the Provider is disconnected from all chains, while `4901` is intended to indicate that the Provider is disconnected from a specific chain only.
&gt; In other words, `4901` implies that the Provider is connected to other chains, just not the requested one.

### Events

The Provider **MUST** implement the following event handling methods:

- `on`
- `removeListener`

These methods **MUST** be implemented per the Node.js [`EventEmitter` API](https://nodejs.org/api/events.html).

&gt; To satisfy these requirements, Provider implementers should consider simply extending the Node.js `EventEmitter` class and bundling it for the target environment.

#### message

&gt; The `message` event is intended for arbitrary notifications not covered by other events.

When emitted, the `message` event **MUST** be emitted with an object argument of the following form:

```typescript
interface ProviderMessage {
  readonly type: string;
  readonly data: unknown;
}
```

##### Subscriptions

If the Provider supports Ethereum RPC subscriptions, e.g. [`eth_subscribe`](https://geth.ethereum.org/docs/rpc/pubsub), the Provider **MUST** emit the `message` event when it receives a subscription notification.

If the Provider receives a subscription message from e.g. an `eth_subscribe` subscription, the Provider **MUST** emit a `message` event with a `ProviderMessage` object of the following form:

```typescript
interface EthSubscription extends ProviderMessage {
  readonly type: &apos;eth_subscription&apos;;
  readonly data: {
    readonly subscription: string;
    readonly result: unknown;
  };
}
```

#### connect

See the section [Connectivity](#connectivity) for the definition of &quot;connected&quot;.

If the Provider becomes connected, the Provider **MUST** emit the event named `connect`.

This includes when:

- The Provider first connects to a chain after initialization.
- The Provider connects to a chain after the `disconnect` event was emitted.

This event **MUST** be emitted with an object of the following form:

```typescript
interface ProviderConnectInfo {
  readonly chainId: string;
}
```

`chainId` **MUST** specify the integer ID of the connected chain as a hexadecimal string, per the [`eth_chainId`](/EIPs/EIPS/eip-695) Ethereum RPC method.

#### disconnect

See the section [Connectivity](#connectivity) for the definition of &quot;disconnected&quot;.

If the Provider becomes disconnected from all chains, the Provider **MUST** emit the event named `disconnect` with value `error: ProviderRpcError`, per the interfaced defined in the [RPC Errors](#rpc-errors) section. The value of the error&apos;s `code` property **MUST** follow the [status codes for `CloseEvent`](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes).

#### chainChanged

If the chain the Provider is connected to changes, the Provider **MUST** emit the event named `chainChanged` with value `chainId: string`, specifying the integer ID of the new chain as a hexadecimal string, per the [`eth_chainId`](/EIPs/EIPS/eip-695) Ethereum RPC method.

#### accountsChanged

If the accounts available to the Provider change, the Provider **MUST** emit the event named `accountsChanged` with value `accounts: string[]`, containing the account addresses per the `eth_accounts` Ethereum RPC method.

The &quot;accounts available to the Provider&quot; change when the return value of `eth_accounts` changes.

## Rationale

The purpose of a Provider is to _provide_ a consumer with access to Ethereum.
In general, a Provider must enable an Ethereum web application to do two things:

- Make Ethereum RPC requests
- Respond to state changes in the Provider&apos;s Ethereum chain, Client, and Wallet

The Provider API specification consists of a single method and five events.
The `request` method and the `message` event alone, are sufficient to implement a complete Provider.
They are designed to make arbitrary RPC requests and communicate arbitrary messages, respectively.

The remaining four events can be separated into two categories:

- Changes to the Provider&apos;s ability to make RPC requests
  - `connect`
  - `disconnect`
- Common Client and/or Wallet state changes that any non-trivial application must handle
  - `chainChanged`
  - `accountsChanged`

These events are included due to the widespread production usage of related patterns, at the time of writing.

## Backwards Compatibility

Many Providers adopted a draft version of this specification before it was finalized.
The current API is designed to be a strict superset of the legacy version, and this specification is in that sense fully backwards compatible.
See [Appendix III](#appendix-iii-legacy-provider-api) for the legacy API.

Providers that only implement this specification will not be compatible with Ethereum web applications that target the legacy API.

## Implementations

At the time of writing, the following projects have working implementations:

- [buidler.dev](https://github.com/nomiclabs/buidler/pull/608)
- [ethers.js](https://github.com/ethers-io/ethers.js/blob/56af4413b1dd1787db68985e0b612b63d86fdf7c/packages/providers/src.ts/web3-provider.ts)
- [eth-provider](https://www.npmjs.com/package/eth-provider)
- [MetaMask](https://github.com/MetaMask/inpage-provider)
- [WalletConnect](https://github.com/WalletConnect/walletconnect-monorepo/blob/d33fd2070d7a67f74de50fd10ca4217f4e2f22f3/packages/providers/web3-provider/README.md)
- [web3.js](https://web3js.readthedocs.io/)

## Security Considerations

The Provider is intended to pass messages between an Ethereum Client and an Ethereum application.
It is _not_ responsible for private key or account management; it merely processes RPC messages and emits events.
Consequently, account security and user privacy need to be implemented in middlewares between the Provider and its Ethereum Client.
In practice, we call these middleware applications &quot;Wallets,&quot; and they usually manage the user&apos;s private keys and accounts.
The Provider can be thought of as an extension of the Wallet, exposed in an untrusted environment, under the control of some third party (e.g. a website).

### Handling Adversarial Behavior

Since it is a JavaScript object, consumers can generally perform arbitrary operations on the Provider, and all its properties can be read or overwritten.
Therefore, it is best to treat the Provider object as though it is controlled by an adversary.
It is paramount that the Provider implementer protects the user, Wallet, and Client by ensuring that:

- The Provider does not contain any private user data.
- The Provider and Wallet programs are isolated from each other.
- The Wallet and/or Client rate-limit requests from the Provider.
- The Wallet and/or Client validate all data sent from the Provider.

### Chain Changes

Since all Ethereum operations are directed at a particular chain, it&apos;s important that the Provider accurately reflects the Client&apos;s configured chain, per the `eth_chainId` Ethereum RPC method (see [EIP-695](/EIPs/EIPS/eip-695)).

This includes ensuring that `eth_chainId` has the correct return value, and that the `chainChanged` event is emitted whenever that value changes.

### User Account Exposure and Account Changes

Many Ethereum write operations (e.g. `eth_sendTransaction`) require a user account to be specified.
Provider consumers access these accounts via the `eth_accounts` RPC method, and by listening for the `accountsChanged` event.

As with `eth_chainId`, it is critical that `eth_accounts` has the correct return value, and that the `accountsChanged` event is emitted whenever that value changes.

The return value of `eth_accounts` is ultimately controlled by the Wallet or Client.
In order to protect user privacy, the authors recommend not exposing any accounts by default.
Instead, Providers should support RPC methods for explicitly requesting account access, such as `eth_requestAccounts` (see [EIP-1102](/EIPs/EIPS/eip-1102)) or `wallet_requestPermissions` (see [EIP-2255](/EIPs/EIPS/eip-2255)).

## References

- [Initial discussion in `ethereum/interfaces`](https://github.com/ethereum/interfaces/issues/16)
- [Deprecated Ethereum Magicians thread](https://ethereum-magicians.org/t/eip-1193-ethereum-provider-javascript-api/640)
- [Continuing discussion](https://github.com/ethereum/EIPs/issues/2319)
- Related EIPs
  - [EIP-1102: Opt-in Account Exposure](/EIPs/EIPS/eip-1102)
  - [EIP-1474: Remote Procedure Call Specification](/EIPs/EIPS/eip-1474)
  - [EIP-1767: GraphQL Interface to Ethereum Node Data](/EIPs/EIPS/eip-1767)
  - [EIP-2255: Wallet Permissions](/EIPs/EIPS/eip-2255)

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

## Appendix I: Consumer-Facing API Documentation

### request

Makes an Ethereum RPC method call.

```typescript
interface RequestArguments {
  readonly method: string;
  readonly params?: readonly unknown[] | object;
}

Provider.request(args: RequestArguments): Promise&lt;unknown&gt;;
```

The returned Promise resolves with the method&apos;s result or rejects with a [`ProviderRpcError`](#errors). For example:

```javascript
Provider.request({ method: &apos;eth_accounts&apos; })
  .then((accounts) =&gt; console.log(accounts))
  .catch((error) =&gt; console.error(error));
```

Consult each Ethereum RPC method&apos;s documentation for its `params` and return type.
You can find a list of common methods [here](/EIPs/EIPS/eip-1474).

#### RPC Protocols

Multiple RPC protocols may be available. For examples, see:

- [EIP-1474](/EIPs/EIPS/eip-1474), the Ethereum JSON-RPC API
- [EIP-1767](/EIPs/EIPS/eip-1767), the Ethereum GraphQL schema

### Events

Events follow the conventions of the Node.js [`EventEmitter` API](https://nodejs.org/api/events.html).

#### connect

The Provider emits `connect` when it:

- first connects to a chain after being initialized.
- first connects to a chain, after the `disconnect` event was emitted.

```typescript
interface ProviderConnectInfo {
  readonly chainId: string;
}

Provider.on(&apos;connect&apos;, listener: (connectInfo: ProviderConnectInfo) =&gt; void): Provider;
```

The event emits an object with a hexadecimal string `chainId` per the `eth_chainId` Ethereum RPC method, and other properties as determined by the Provider.

#### disconnect

The Provider emits `disconnect` when it becomes disconnected from all chains.

```typescript
Provider.on(&apos;disconnect&apos;, listener: (error: ProviderRpcError) =&gt; void): Provider;
```

This event emits a [`ProviderRpcError`](#errors). The error `code` follows the table of [`CloseEvent` status codes](https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes).

#### chainChanged

The Provider emits `chainChanged` when connecting to a new chain.

```typescript
Provider.on(&apos;chainChanged&apos;, listener: (chainId: string) =&gt; void): Provider;
```

The event emits a hexadecimal string `chainId` per the `eth_chainId` Ethereum RPC method.

#### accountsChanged

The Provider emits `accountsChanged` if the accounts returned from the Provider (`eth_accounts`) change.

```typescript
Provider.on(&apos;accountsChanged&apos;, listener: (accounts: string[]) =&gt; void): Provider;
```

The event emits with `accounts`, an array of account addresses, per the `eth_accounts` Ethereum RPC method.

#### message

The Provider emits `message` to communicate arbitrary messages to the consumer.
Messages may include JSON-RPC notifications, GraphQL subscriptions, and/or any other event as defined by the Provider.

```typescript
interface ProviderMessage {
  readonly type: string;
  readonly data: unknown;
}

Provider.on(&apos;message&apos;, listener: (message: ProviderMessage) =&gt; void): Provider;
```

##### Subscriptions

[`eth_` subscription methods](https://geth.ethereum.org/docs/rpc/pubsub) and [`shh_` subscription methods](https://github.com/ethereum/go-ethereum/wiki/Whisper-v6-RPC-API#shh_subscribe) rely on this event to emit subscription updates.

For e.g. `eth_subscribe` subscription updates, `ProviderMessage.type` will equal the string `&apos;eth_subscription&apos;`, and the subscription data will be the value of `ProviderMessage.data`.

### Errors

```typescript
interface ProviderRpcError extends Error {
  message: string;
  code: number;
  data?: unknown;
}
```

## Appendix II: Examples

These examples assume a web browser environment.

```javascript
// Most Providers are available as window.ethereum on page load.
// This is only a convention, not a standard, and may not be the case in practice.
// Please consult the Provider implementation&apos;s documentation.
const ethereum = window.ethereum;

// Example 1: Log chainId
ethereum
  .request({ method: &apos;eth_chainId&apos; })
  .then((chainId) =&gt; {
    console.log(`hexadecimal string: ${chainId}`);
    console.log(`decimal number: ${parseInt(chainId, 16)}`);
  })
  .catch((error) =&gt; {
    console.error(`Error fetching chainId: ${error.code}: ${error.message}`);
  });

// Example 2: Log last block
ethereum
  .request({
    method: &apos;eth_getBlockByNumber&apos;,
    params: [&apos;latest&apos;, true],
  })
  .then((block) =&gt; {
    console.log(`Block ${block.number}:`, block);
  })
  .catch((error) =&gt; {
    console.error(
      `Error fetching last block: ${error.message}.
       Code: ${error.code}. Data: ${error.data}`
    );
  });

// Example 3: Log available accounts
ethereum
  .request({ method: &apos;eth_accounts&apos; })
  .then((accounts) =&gt; {
    console.log(`Accounts:\n${accounts.join(&apos;\n&apos;)}`);
  })
  .catch((error) =&gt; {
    console.error(
      `Error fetching accounts: ${error.message}.
       Code: ${error.code}. Data: ${error.data}`
    );
  });

// Example 4: Log new blocks
ethereum
  .request({
    method: &apos;eth_subscribe&apos;,
    params: [&apos;newHeads&apos;],
  })
  .then((subscriptionId) =&gt; {
    ethereum.on(&apos;message&apos;, (message) =&gt; {
      if (message.type === &apos;eth_subscription&apos;) {
        const { data } = message;
        if (data.subscription === subscriptionId) {
          if (&apos;result&apos; in data &amp;&amp; typeof data.result === &apos;object&apos;) {
            const block = data.result;
            console.log(`New block ${block.number}:`, block);
          } else {
            console.error(`Something went wrong: ${data.result}`);
          }
        }
      }
    });
  })
  .catch((error) =&gt; {
    console.error(
      `Error making newHeads subscription: ${error.message}.
       Code: ${error.code}. Data: ${error.data}`
    );
  });

// Example 5: Log when accounts change
const logAccounts = (accounts) =&gt; {
  console.log(`Accounts:\n${accounts.join(&apos;\n&apos;)}`);
};
ethereum.on(&apos;accountsChanged&apos;, logAccounts);
// to unsubscribe
ethereum.removeListener(&apos;accountsChanged&apos;, logAccounts);

// Example 6: Log if connection ends
ethereum.on(&apos;disconnect&apos;, (code, reason) =&gt; {
  console.log(`Ethereum Provider connection closed: ${reason}. Code: ${code}`);
});
```

## Appendix III: Legacy Provider API

This section documents the legacy Provider API, which is extensively used in production at the time of writing.
As it was never fully standardized, significant deviations occur in practice.
The authors recommend against implementing it except to support legacy Ethereum applications.

### sendAsync (DEPRECATED)

This method is superseded by [`request`](#request).

`sendAsync` is like `request`, but with JSON-RPC objects and a callback.

```typescript
Provider.sendAsync(request: Object, callback: Function): void;
```

Historically, the request and response object interfaces have followed the [Ethereum JSON-RPC specification](/EIPs/EIPS/eip-1474).

### send (DEPRECATED)

This method is superseded by [`request`](#request).

```typescript
Provider.send(...args: unknown[]): unknown;
```

### Legacy Events

#### close (DEPRECATED)

This event is superseded by [`disconnect`](#disconnect).

#### networkChanged (DEPRECATED)

The event `networkChanged` is superseded by [`chainChanged`](#chainchanged).

For details, see [EIP-155: Simple replay attack protection](/EIPs/EIPS/eip-155) and [EIP-695: Create eth_chainId method for JSON-RPC](/EIPs/EIPS/eip-695).

#### notification (DEPRECATED)

This event is superseded by [`message`](#message).

Historically, this event has been emitted with e.g. `eth_subscribe` subscription updates of the form `{ subscription: string, result: unknown }`.
</description>
        <pubDate>Sat, 30 Jun 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1193</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1193</guid>
      </item>
    
      <item>
        <title>Voting Interface</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-1202-voting-interface/11484</comments>
        
        <description>## Abstract

This EIP defines an API for implementing voting with smart contracts. This standard provides functionality for voting, viewing vote results, and setting voting status.

## Motivation

Voting is one of the earliest examples of EVM programming and is also a key part of DAO and organizational governance processes. We expect many DAOs will ultimately need to leverage voting as an important part of their governance. By creating a voting standard for smart contracts and tokens, we can have the following benefits:

### Benefits of having a standard

1. Allow general UIs and applications to be built on top of a standardized voting interface so that more users can participate, and encourage more dApps and DAOs to think about their governance.
2. Allow delegated voting, smart-contract voting, and automatic voting.
3. Allow voting results to be recorded on-chain in a standard way, and allow DAOs and dApps to honor the voting results programmatically.
4. Allow compatibility with token standards such as [ERC-20](/EIPs/EIPS/eip-20) and newer standards such as [ERC-777](/EIPs/EIPS/eip-777), as well as item standards such as [ERC-721](/EIPs/EIPS/eip-721).
5. Create massive potential for interoperability within Ethereum ecosystems and other systems.
6. Allow setting voting deadlines, determining single or multiple options, and requiring voting order. (The trade-off is interface complexity; we might need an [ERC-20](/EIPs/EIPS/eip-20)-style approach first and later an [ERC-777](/EIPs/EIPS/eip-777)-style approach for advanced voting.)
7. Record voting weights based on token amounts.
8. Possibly allow trustworthy, privacy-safe voting and anonymous voting (with the voter address not being associated with the vote they cast, given a list of randomized or obfuscated voting options).
9. Possibly allow rewards based on voting participation or voting results.

### Non-Goal / Out of Scope

1. **Delegation**: We intentionally leave delegation out of scope. A separate EIP could be proposed to address this particular use case.
2. **Eligibility or Weights**: Some implementations may want voting weights or voting eligibility to be configurable. For example, OpenZeppelin&apos;s implementation of GovernorBravo uses snapshots. Weight calculations such as quadratic voting are also outside the scope of this EIP. This EIP is intended to be flexible enough for current and future voting-weight calculations.
3. **Proposal**: We intentionally leave proposals out of scope. Proposals are identified by `proposalId`, but the information included in a proposal, whether it is on-chain or off-chain, and whether it is executable are all left out of this proposal. A separate EIP could be proposed to address this particular use case. See one such proposal: [ERC-5247](/EIPs/EIPS/eip-5247).
4. **Signature Aggregations / Endorsement**: When implementing contracts want to allow users to submit their vote or vote approval offline and have another account generate the transaction, signature aggregations or endorsements are outside the scope of this EIP. A separate EIP could be proposed to address this particular use case. See one such proposal here: [ERC-5453](/EIPs/EIPS/eip-5453).

### Use-cases

1. Decide on issuing a new token, issuing more tokens, or issuing a sub-token.
2. Decide on creating a new item under [ERC-721](/EIPs/EIPS/eip-721).
3. Decide on electing a certain person or smart contract to be the delegated leader for a project or subproject.
4. Decide on audit-result ownership that allows migration of a smart-contract proxy address.

## Specification

1. Compliant contracts MUST implement the `IERC1202Core` below

```solidity
interface IERC1202Core {
    event VoteCast(
        address indexed voter,
        uint256 indexed proposalId,
        uint8 support,
        uint256 weight,
        string reason,
        bytes extraParams
    );

    function castVote(
        uint256 proposalId,
        uint8 support,
        uint256 weight,
        string calldata reasonUri,
        bytes calldata extraParams
    ) external payable returns;

    function castVoteFrom(
        address from,
        uint256 proposalId,
        uint8 support,
        uint256 weight,
        string calldata reasonUri,
        bytes calldata extraParams
    ) external payable returns;

    function execute(uint256 proposalId, bytes memory extraParams) payable external;
}
```

2. Compliant contracts MAY implement the `IERC1202MultiVote` Interface. If the intention is for multi-options to be supported, e.g. for ranked-choices
or variant weights voting, Compliant contracts MUST implement `IERC1202MultiVote` Interface.

```solidity
interface IERC1202MultiVote {
    event MultiVoteCast(
        address indexed voter,
        uint256 indexed proposalId,
        uint8[] support,
        uint256[] weight,
        string reason,
        bytes extraParams
    );

    function castMultiVote(
        uint256 proposalId,
        uint8[] support,
        uint256[] weight,
        string calldata reasonUri,
        bytes calldata extraParams
    ) external payable;
}
```

3. The compliant contract SHOULD implement the [ERC-5269](/EIPs/EIPS/eip-5269) interface.


### Getting Info: Voting Period, Eligibility, Weight

```solidity
interface IERC1202Info {
    function votingPeriodFor(uint256 proposalId) external view returns (uint256 startPointOfTime, uint256 endPointOfTime);
    function eligibleVotingWeight(uint256 proposalId, address voter) external view returns (uint256);
}
```

## Rationale

We made the following design decisions, and here are the rationales.

### Granularity and Anonymity

We created a `view` function, `ballotOf`, primarily to make it easier for people to check the vote from a certain address. This has the following assumptions:

- It is possible to check someone&apos;s vote directly given an address. If implementers do not want to make this so easy, they can simply reject all calls to this function. We want to make sure that we support both anonymous and non-anonymous voting. However, since all calls to a smart contract are logged in block history, there is not much secrecy unless cryptographic techniques are used. I am not sufficiently cryptography-savvy to comment on that possibility. Please see &quot;Second Feedback Questions 2018&quot; for a related topic.

- It assumes that each individual address can vote for only one decision. Users can distribute their available voting power at a more granular level. If implementers want to allow this, they can ask the user to create another wallet address and grant that new address a certain amount of power. For example, in token-based voting where voting weight is determined by the amount of tokens held by a voter, a voter who wants to distribute their voting power across two different options (or option sets) can transfer some of the tokens to the new account and cast votes from both accounts.

### Weights

We assume votes have `weight`, which can be checked by calling `eligibleVotingWeight(proposalId, address voter)`, and that the weight distribution is either determined internally or set by the constructor.

## Backwards Compatibility

1. The `support` options are chosen to be `uint8` for the purpose of being backward-compatible with GovernorBravo. This can be increased in the future.

## Security Considerations

We expect the voting standard to be used in connection with other contracts such as token distributions, actions conducted by consensus or on behalf of an entity, multi-signature wallets, and similar systems.

The major security consideration is ensuring that the standard interface is used only for performing downstream actions or receiving upstream input (vote casting). We expect future audit tools to be based on standard interfaces.

It is also important to note, as discussed in this standard, that for the sake of simplicity this EIP is kept in a very basic form. It can be extended to support many different implementation variations. Such variations might contain different assumptions about the behavior and interpretation of actions. One example is: what does it mean if someone votes multiple times through `vote`?

- Would that mean the voter is increasing their weight?
- Would that mean they vote for multiple options in the meantime?
- Does the latter vote override the previous vote?

Because of the flexible nature of voting, we expect that many subsequent standards will need to be created as extensions of this EIP. We suggest that any extension or implementation of this standard be thoroughly audited before being included in large-scale or high-asset-volume applications.

The third consideration is non-triviality. Some voting applications assume **_anonymity_**, **_randomness_**, **_time-based deadline_**, **_ordering_**, etc. These requirements are known to be non-trivial to achieve on Ethereum. We suggest that any applications or organizations rely on audited and time-proven shared libraries when these requirements need to be enforced in their applications.

The fourth consideration is potential abuse. When voting is standardized and put on-chain, it is possible to write another contract that rewards a voter for voting in a certain way. This creates potential issues of bribery and conflict-of-interest abuse that were previously hard to implement.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 08 Jul 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1202</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1202</guid>
      </item>
    
      <item>
        <title>ERC-1203 Multi-Class Token Standard (ERC-20 Extension)</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1203</comments>
        
        <description>## Simple Summary

A standard interface for multi-class tokens (MCTs).

## Abstract

The following standard allows for the implementation of a standard API for MCTs within smart contracts. This standard provides basic functionality to track, transfer, and convert MCTs.

## Motivation

This standard is heavily inspired by ERC-20 Token Standard and ERC-721 Non-Fungible Token Standard. However, whereas these standards are chiefly concerned with representation of items/value in a single class, fungible or note, this proposed standard focus on that of a more complexed, multi-class system. It is fair to think of MCTs as a hybrid of fungible tokens (FT) and non-fungible tokens (NFTs), that is tokens are fungible within the same class but non-fungible with that from a different class. And conversions between classes may be optionally supported.

MCTs are useful in representing various structures with heterogeneous components, such as:

- **Abstract Concepts:** A company may have different classes of stocks (e.g. senior preferred, junior preferred, class A common, class B common) that together make up its outstanding equities. A shareholder&apos;s position of such company composites of zero or more shares in each class.

- **Virtual Items:** A sandbox computer game may have many types of resources (e.g. rock, wood, berries, cows, meat, knife, etc.) that together make up that virtual world. A player&apos;s inventory has any combination and quantity of these resources

- **Physical Items:** A supermarket may have many SKUs it has available for purchase (e.g. eggs, milk, beef jerky, beer, etc.). Things get added or removed from a shopper&apos;s cart as it moves down the aisle.

It&apos;s sometimes possible, especially with regard to abstract concepts or virtual items, to convert from one class to another, at a specified conversion ratio. When it comes to physical items, such conversion essentially is the implementation of bartering. Though it might generally be easier to introduce a common intermediary class, i.e. money.

## Specification

```solidity
contract ERC20 {
    function totalSupply() public view returns (uint256);
    function balanceOf(address _owner) public view returns (uint256);
    function transfer(address _to, uint256 _value) public returns (bool);
    function approve(address _spender, uint256 _value) public returns (bool);
    function allowance(address _owner, address _spender) public view returns (uint256);
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool);

    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}

contract ERC1203 is ERC20 {
    function totalSupply(uint256 _class) public view returns (uint256);
    function balanceOf(address _owner, uint256 _class) public view returns (uint256);
    function transfer(address _to, uint256 _class, uint256 _value) public returns (bool);
    function approve(address _spender, uint256 _class, uint256 _value) public returns (bool);
    function allowance(address _owner, address _spender, uint256 _class) public view returns (uint256);
    function transferFrom(address _from, address _to, uint256 _class, uint256 _value) public returns (bool);

    function fullyDilutedTotalSupply() public view returns (uint256);
    function fullyDilutedBalanceOf(address _owner) public view returns (uint256);
    function fullyDilutedAllowance(address _owner, address _spender) public view returns (uint256);
    function convert(uint256 _fromClass, uint256 _toClass, uint256 _value) public returns (bool);

    event Transfer(address indexed _from, address indexed _to, uint256 _class, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender, uint256 _class, uint256 _value);
    event Convert(uint256 indexed _fromClass, uint256 indexed _toClass, uint256 _value);
}
```

### ERC-20 Methods and Events (fully compatible)

Please see [ERC-20 Token Standard](/EIPs/EIPS/eip-20) for detailed specifications. Do note that these methods and events only work on the &quot;default&quot; class of an MCT.

```solidity
    function totalSupply() public view returns (uint256);
    function balanceOf(address _owner) public view returns (uint256);
    function transfer(address _to, uint256 _value) public returns (bool);
    function approve(address _spender, uint256 _value) public returns (bool);
    function allowance(address _owner, address _spender) public view returns (uint256);
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool);

    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
```

### Tracking and Transferring

**totalSupply**

Returns the total number of tokens in the specified `_class`

```solidity
    function totalSupply(uint256 _class) public view returns (uint256);
```

**balanceOf**

Returns the number of tokens of a specified `_class` that the `_owner` has

```solidity
    function balanceOf(address _owner, uint256 _class) public view returns (uint256);
```

**transfer**

Transfer `_value` tokens of `_class` to address specified by `_to`, return `true` if successful

```solidity
    function transfer(address _to, uint256 _class, uint256 _value) public returns (bool);
```

**approve**

Grant `_spender` the right to transfer `_value` tokens of `_class`, return `true` if successful

```solidity
    function approve(address _spender, uint256 _class, uint256 _value) public returns (bool);
```

**allowance**

Return the number of tokens of `_class` that `_spender` is authorized to transfer on the behalf of `_owner`

```solidity
    function allowance(address _owner, address _spender, uint256 _class) public view returns (uint256);
```

**transferFrom**

Transfer `_value` tokens of `_class` from address specified by `_from` to address specified by `_to` as previously approved, return `true` if successful

```solidity
    function transferFrom(address _from, address _to, uint256 _class, uint256 _value) public returns (bool);
```

**Transfer**

Triggered when tokens are transferred or created, including zero value transfers

```solidity
    event Transfer(address indexed _from, address indexed _to, uint256 _class, uint256 _value);
```

**Approval**

Triggered on successful `approve`

```solidity
    event Approval(address indexed _owner, address indexed _spender, uint256 _class, uint256 _value);
```

### Conversion and Dilution

**fullyDilutedTotalSupply**

Return the total token supply as if all converted to the lowest common denominator class

```solidity
    function fullyDilutedTotalSupply() public view returns (uint256);
```

**fullyDilutedBalanceOf**

Return the total token owned by `_owner` as if all converted to the lowest common denominator class

```solidity
    function fullyDilutedBalanceOf(address _owner) public view returns (uint256);
```

**fullyDilutedAllowance**

Return the total token `_spender` is authorized to transfer on behalf of `_owner` as if all converted to the lowest common denominator class

```solidity
    function fullyDilutedAllowance(address _owner, address _spender) public view returns (uint256);
```

**convert**

Convert `_value` of `_fromClass` to `_toClass`, return `true` if successful

```solidity
    function convert(uint256 _fromClass, uint256 _toClass, uint256 _value) public returns (bool);
```

**Conversion**

Triggered on successful `convert`

```solidity
    event Conversion(uint256 indexed _fromClass, uint256 indexed _toClass, uint256 _value);
```

## Rationale
This standard purposely extends ERC-20 Token Standard so that new MCTs following or existing ERC-20 tokens extending this standard are fully compatible with current wallets and exchanges. In addition, new methods and events are kept as closely to ERC-20 conventions as possible for ease of adoption.

We have considered alternative implementations to support the multi-class structure, as discussed below, and we found current token standards incapable or inefficient in deal with such structures.

**Using multiple ERC-20 tokens**

It is certainly possible to create an ERC-20 token for each class, and a separate contract to coordinate potential conversions, but the short coming in this approach is clearly evident. The rationale behind this standard is to have a single contract to manage multiple classes of tokens.

**Shoehorning ERC-721 token**

Treating each token as unique, the non-fungible token standard offers maximum representational flexibility arguably at the expense of convenience. The main challenge of using ERC-721 to represent multi-class token is that separate logic is required to keep track of which tokens belongs to which class, a hacky and unnecessary endeavor.

**Using ERC-1178 token**

We came across ERC-1178 as we were putting final touches on our own proposal. The two ERCs look very similar on the surface but we believe there&apos;re a few key advantages this one has over ERC-1178.

- ERC-1178 offers no backward compatibility whereas this proposal is an extension of ERC-20 and therefore fully compatible with all existing wallets and exchanges
- By the same token, existing ERC-20 contracts can extend themselves to adopt this standard and support additional classes without affecting their current behaviors
- This proposal introduces the concept of cross class conversion and dilution, making each token class integral part of a whole system rather than many silos

## Backwards Compatibility
This EIP is fully compatible with the mandatory methods of ERC20 Token Standard so long as the implementation includes a &quot;lowest common denominator&quot; class, which may be class B common/gold coin/money in the abstract/virtual/physical examples above respectively. Where it is not possible to implement such class, then the implementation should specify a default class for tracking or transferring unless otherwise specified, e.g. US dollar is transferred unless other currency is explicitly specified.

We find it contrived to require the optional methods of ERC20 Token Standard, `name()`, `symbol()`, and `decimals()`, but developers are certainly free to implement these as they wish.

## Test Cases
The repository at [jeffishjeff/ERC-1203](https://github.com/jeffishjeff/ERC-1203) contains the [sample test cases](https://github.com/jeffishjeff/ERC-1203/blob/master/token.test.js).

## Implementation
The repository at [jeffishjeff/ERC-1203](https://github.com/jeffishjeff/ERC-1203) contains the [sample implementation](https://github.com/jeffishjeff/ERC-1203/blob/master/token.sol).

## References
- ERC-20 Token Standard. ./eip-20.md
- ERC-721 Non-Fungible Token Standard. ./eip-721.md
- ERC-1178 Multi-class Token Standard. ./eip-1178.md

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 01 Jul 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1203</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1203</guid>
      </item>
    
      <item>
        <title>DAuth Access Delegation Standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1207</comments>
        
        <description>DAuth Access Delegation Standard
=====

## Simple Summary
DAuth is a standard interface for accessing authorization delegation between smart contracts and users.

## Abstract
The DAuth protocol defines a set of standard API allowing identity delegations between smart contracts without the user&apos;s private key.  Identity delegations include accessing and operating a user&apos;s data and assets contained in the delegated contracts.

## Motivation
The inspiration for designing DAuth comes from OAuth protocol that is extensively used in web applications. But unlike the centralized authorization of OAuth, DAuth works in a  distributed manner, thus providing much more reliability and generality.

## Specification
![Rationale](/EIPs/assets/eip-1207/rationale.png)

**Resource owner**: the authorizer

**Resource contract**: the contract providing data and operators

**API**: the resource contract APIs that the grantee contract can invoke

**Client contract**: the grantee contract using authorization to access and operate the data

**Grantee request**: the client contract calls the resource contract with the authorizer authorization


**AuthInfo**
``` js
struct AuthInfo {
    string[] funcNames;
    uint expireAt;
}
```
Required - The struct contains user authorization information
* `funcNames`: a list of function names callable by the granted contract
* `expireAt`: the authorization expire timestamp in seconds

**userAuth**
```  js
mapping(address =&gt; mapping(address =&gt; AuthInfo)) userAuth;
```
Required - userAuth maps (authorizer address, grantee contract address) pair to the user’s authorization AuthInfo object

**callableFuncNames**
```  js
string[] callableFuncNames;
```
Required - All methods that are allowed other contracts to call
* The callable function MUST verify the grantee’s authorization

**updateCallableFuncNames**
```  js
function updateCallableFuncNames(string _invokes) public returns (bool success);
```
Optional - Update the callable function list for the client contract by the resource contract&apos;s administrator
* `_invokes`: the invoke methods that the client contract can call
* return: Whether the callableFuncNames is updated or not
* This method MUST return success or throw, no other outcomes can be possible

**verify**
```  js
function verify(address _authorizer, string _invoke) internal returns (bool success);
```
Required - check the invoke method authority for the client contract
* `_authorizer`: the user address that the client contract agents
* `_invoke`: the invoke method that the client contract wants to call
* return: Whether the grantee request is authorized or not
* This method MUST return success or throw, no other outcomes can be possible

**grant**
```  js
function grant(address _grantee, string _invokes, uint _expireAt) public returns (bool success);
```
Required - delegate a client contract to access the user&apos;s resource
* `_grantee`: the client contract address
* `_invokes`: the callable methods that the client contract can access. It is a string which contains all function names split by spaces
* `_expireAt`: the authorization expire timestamp in seconds
* return: Whether the grant is successful or not
* This method MUST return success or throw, no other outcomes can be possible
* A successful grant MUST fire the Grant event(defined below)

**regrant**
```  js
function regrant(address _grantee, string _invokes, uint _expireAt) public returns (bool success);
```
Optional - alter a client contract&apos;s delegation

**revoke**
```  js
function revoke(address _grantee) public returns (bool success);
```
Required - delete a client contract&apos;s delegation
* `_grantee`: the client contract address
* return: Whether the revoke is successful or not
* A successful revoke MUST fire the Revoke event(defined below).

**Grant**
```  js
event Grant(address _authorizer, address _grantee, string _invokes, uint _expireAt);
```
* This event MUST trigger when the authorizer grant a new authorization when `grant` or `regrant` processes successfully

**Revoke**
```  js
event Revoke(address _authorizer, address _grantee);
```
* This event MUST trigger when the authorizer revoke a specific authorization successfully

**Callable Resource Contract Functions**

All public or external functions that are allowed the grantee to call MUST use overload to implement two functions: The First one is the standard method that the user invokes directly, the second one is the grantee methods of the same function name with one more authorizer address parameter.

Example:
```  js
function approve(address _spender, uint256 _value) public returns (bool success) {
    return _approve(msg.sender, _spender, _value);
}

function approve(address _spender, uint256 _value, address _authorizer) public returns (bool success) {
    verify(_authorizer, &quot;approve&quot;);

    return _approve(_authorizer, _spender, _value);
}

function _approve(address sender, address _spender, uint256 _value) internal returns (bool success) {
    allowed[sender][_spender] = _value;
    emit Approval(sender, _spender, _value);
    return true;
}
```

## Rationale

**Current Limitations**

The current design of many smart contracts only considers the user invokes the smart contract functions by themselves using the private key. However, in some case, the user wants to delegate other client smart contracts to access and operate their data or assets in the resource smart contract. There isn’t a common protocol to provide a standard delegation approach.

**Rationale**

On the Ethereum platform, all storage is transparent and the `msg.sender` is reliable. Therefore, the DAuth don&apos;t need an `access_token` like OAuth. DAuth just recodes the users&apos; authorization for the specific client smart contract&apos;s address. It is simple and reliable on the Ethereum platform.

## Backwards Compatibility
This EIP introduces no backward compatibility issues. In the future, the new version protocol has to keep these interfaces.

## Implementation
Following is the DAuth Interface implementation. Furthermore, the example implementations of EIP20 Interface and ERC-DAuth Interface are also provided. Developers can easily implement their own contracts with ERC-DAuth Interface and other EIP.

* ERC-DAuth Interface implementation is available at:

  https://github.com/DIA-Network/ERC-DAuth/blob/master/ERC-DAuth-Interface.sol

* Example implementation with EIP20 Interface and ERC-DAuth Interface is available at:

  https://github.com/DIA-Network/ERC-DAuth/blob/master/eip20-dauth-example/EIP20DAuth.sol


## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 10 Jul 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1207</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1207</guid>
      </item>
    
      <item>
        <title>Defuse Difficulty Bomb and Reset Block Reward</title>
        <category>Standards Track/Core</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1227</comments>
        
        <description>## Simple Summary
This EIP proposes to permanently disable the &quot;difficulty bomb&quot; and reset the block reward to pre-Byzantium levels.

## Abstract
Starting with `FORK_BLKNUM` the client will calculate the difficulty without the additional exponential component. Furthermore, block rewards will be adjusted to a base of 5 ETH, uncle and nephew rewards will be adjusted accordingly.

## Motivation
Due to the &quot;difficulty bomb&quot; (also known as the &quot;ice age&quot;), introduced in EIP [#2](/EIPs/EIPS/eip-2), an artificial exponential increase in difficulty until chain freeze, users may find it much more challenging to remain on the unforked chain after a hard-fork. This is a desirable effect of the ice age (in fact, its only stated purpose) in the case of a scheduled network upgrade, but is especially problematic when a hard-fork includes a controversial change.

This situation has already been observed: during the Byzantium hard-fork users were given the &quot;choice&quot; of following the upgraded side of the chain or remaining on the original chain, the latter already experiencing block times greater than 30 seconds. In reality one will find that organizing a disperse and decentralized set of individuals to keep the original, soon-to-be-dead chain alive under such conditions impossible. This is exacerbated when a controversial change, such as EIP [#649](/EIPs/EIPS/eip-649), is merged in so close to the hard-fork date, as users cannot be organized to take an educated stance for or against the change on such short notice.

Ultimately, the difficulty bomb serves but a single purpose: make it more difficult to keep the original chain alive after a hard-fork. This is unacceptable if the only way the community can make their voice heard is running/not running client software, and not through the EIP process, since they effectively have no choice and therefore no power. This EIP proposes to completely eliminate the difficulty bomb, returning some measure of power over Ethereum&apos;s governance process to the users, to the community.

Given the controversy surrounding the directly relevant EIP [#649](/EIPs/EIPS/eip-649), the issuance should also be reset to pre-Byzantium levels. It may be reduced again at a later time via a new hard-fork, only this time users would actually have a meaningful choice in accepting the change or not. Note: the issuance reduction is not the focus of this proposal, and is optional; the defusing of the difficulty bomb is of primary concern.

## Specification
#### Remove Exponential Component of Difficulty Adjustment
For the purposes of `calc_difficulty`, simply remove the exponential difficulty adjustment component, `epsilon`, i.e. the `int(2**((block.number // 100000) - 2))`.

#### Reset Block, Uncle, and Nephew rewards
To ensure a constant Ether issuance, adjust the block reward to `new_block_reward`, where

    new_block_reward = 5_000_000_000_000_000_000 if block.number &gt;= FORK_BLKNUM else block.reward

(5E18 wei, or 5,000,000,000,000,000,000 wei, or 5 ETH).

Analogue, if an uncle is included in a block for `block.number &gt;= FORK_BLKNUM` such that `block.number - uncle.number = k`, the uncle reward is

    new_uncle_reward = (8 - k) * new_block_reward / 8

This is the existing pre-Byzantium formula for uncle rewards, simply adjusted with `new_block_reward`.

The nephew reward for `block.number &gt;= FORK_BLKNUM` is

    new_nephew_reward = new_block_reward / 32

This is the existing pre-Byzantium formula for nephew rewards, simply adjusted with `new_block_reward`.

## Rationale
This will permanently, without further changes, disable the &quot;ice age.&quot; It will also reset the block reward to pre-Byzantium levels. Both of these changes are specified similarly to EIP [#649](/EIPs/EIPS/eip-649), so they should require only minimal changes from client developers.

## Backwards Compatibility
This EIP is not forward compatible and introduces backwards incompatibilities in the difficulty calculation, as well as the block, uncle and nephew reward structure. However, it may be controversial in nature among different sections of the userbase&amp;mdash;the very problem this EIP is made to address. Therefore, it should not be included in a scheduled hardfork at a certain block number. It is suggested to implement this EIP in an isolated hard-fork before the second of the two Metropolis hard-forks.

## Test Cases
Forthcoming.

## Implementation
Forthcoming.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 18 Jul 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1227</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1227</guid>
      </item>
    
      <item>
        <title>Constantinople Difficulty Bomb Delay and Block Reward Adjustment</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-1234-constantinople-difficulty-bomb-delay-and-block-reward-adjustment/833</comments>
        
        <description>## Simple Summary
The average block times are increasing due to the difficulty bomb (also known as the &quot;_ice age_&quot;) slowly accelerating. This EIP proposes to delay the difficulty bomb for approximately 12 months and to reduce the block rewards with the Constantinople fork, the second part of the Metropolis fork.

## Abstract
Starting with `CNSTNTNPL_FORK_BLKNUM` the client will calculate the difficulty based on a fake block number suggesting the client that the difficulty bomb is adjusting around 5 million blocks later than previously specified with the Homestead fork. Furthermore, block rewards will be adjusted to a base of 2 ETH, uncle and nephew rewards will be adjusted accordingly.

## Motivation
The Casper development and switch to proof-of-stake is delayed, the Ethash proof-of-work should be feasible for miners and allow sealing new blocks every 15 seconds on average for another 12 months. With the delay of the ice age, there is a desire to not suddenly also increase miner rewards. The difficulty bomb has been known about for a long time and now it&apos;s going to stop from happening. In order to maintain stability of the system, a block reward reduction that offsets the ice age delay would leave the system in the same general state as before. Reducing the reward also decreases the likelihood of a miner driven chain split as Ethereum approaches proof-of-stake.

## Specification
#### Relax Difficulty with Fake Block Number
For the purposes of `calc_difficulty`, simply replace the use of `block.number`, as used in the exponential ice age component, with the formula:

    fake_block_number = max(0, block.number - 5_000_000) if block.number &gt;= CNSTNTNPL_FORK_BLKNUM else block.number

#### Adjust Block, Uncle, and Nephew rewards
To ensure a constant Ether issuance, adjust the block reward to `new_block_reward`, where

    new_block_reward = 2_000_000_000_000_000_000 if block.number &gt;= CNSTNTNPL_FORK_BLKNUM else block.reward

(2E18 wei, or 2,000,000,000,000,000,000 wei, or 2 ETH).

Analogue, if an uncle is included in a block for `block.number &gt;= CNSTNTNPL_FORK_BLKNUM` such that `block.number - uncle.number = k`, the uncle reward is

    new_uncle_reward = (8 - k) * new_block_reward / 8

This is the existing pre-Constantinople formula for uncle rewards, simply adjusted with `new_block_reward`.

The nephew reward for `block.number &gt;= CNSTNTNPL_FORK_BLKNUM` is

    new_nephew_reward = new_block_reward / 32

This is the existing pre-Constantinople formula for nephew rewards, simply adjusted with `new_block_reward`.

## Rationale
This will delay the ice age by 29 million seconds (approximately 12 months), so the chain would be back at 30 second block times in winter 2019. An alternate proposal was to add special rules to the difficulty calculation to effectively _pause_ the difficulty between different blocks. This would lead to similar results.

This was previously discussed at All Core Devs Meeting [#42](https://github.com/ethereum/pm/blob/6dbd82303bfcb697eaf9a76de37f5fa570e6379d/AllCoreDevs-EL-Meetings/Meeting%2042.md) and subsequent meetings; and accepted in the Constantinople Session [#1](https://github.com/ethereum/pm/issues/55).

## Backwards Compatibility
This EIP is not forward compatible and introduces backwards incompatibilities in the difficulty calculation, as well as the block, uncle and nephew reward structure. Therefore, it should be included in a scheduled hardfork at a certain block number. It&apos;s suggested to include this EIP in the second Metropolis hard-fork, _Constantinople_.

## Test Cases
Test cases shall be created once the specification is to be accepted by the developers or implemented by the clients.

## Implementation
The implementation in it&apos;s logic does not differ from [EIP-649](/EIPs/EIPS/eip-649); an implementation for Parity-Ethereum is available in [parity-ethereum#9187](https://github.com/paritytech/parity-ethereum/pull/9187).

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 19 Jul 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1234</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1234</guid>
      </item>
    
      <item>
        <title>Remove Difficulty Bomb</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/difficulty-bomb-removal/832</comments>
        
        <description>## Simple Summary
The average block times are increasing due to the difficulty bomb (also known as the &quot;_ice age_&quot;) slowly accelerating. This EIP proposes to remove the difficulty increase over time and replace it with a fixed difficulty targeting 15 second blocks.

## Abstract
Starting with `FORK_BLOCK_NUMBER` the client will calculate the difficulty without considering the current block number.

## Motivation
The difficulty bomb operates under the assumption that miners decide what code economic participants are running, rather than economic participants deciding for themselves.  In reality, miners will mine whatever chain is most profitable and the most profitable chain is the one that economic participants use.  If 99% of miners mine a chain that no economic participants use then that chain will have no value and the miners will cease mining of it in favor of some other chain that does have economic participants.  Another way to put this is that miners will follow economic participants, not the other way around.

## Specification
#### Remove Difficulty
For the purposes of `calc_difficulty`, if `block.number &gt;= FORK_BLOCK_NUMBER` then change the epsilon component to `0` rather than having it be a function of block number.

## Rationale
With the difficulty bomb removed, when Casper is released it will be up to economic participants to decide whether they want the features that Casper enables or not.  If they do not want Casper, they are free to continue running unpatched clients and participating in the Ethereum network as it exists today.  This freedom of choice is the cornerstone of DLTs and making it hard for people to make that choice (by creating an artificial pressure) does not work towards that goal of freedom of choice.  If the development team is not confident that economic participants will want Casper, then they should re-evaluate their priorities rather than trying to force Casper onto users.

Author Personal Note: I think we will see almost all economic participants in Ethereum switch to PoS/Sharding without any extra pressure beyond client defaults.

## Backwards Compatibility
This EIP is not forward compatible and introduces backwards incompatibilities in the difficulty calculation. Therefore, it should be included in a scheduled hardfork at a certain block number.

## Test Cases
Test cases shall be created once the specification is to be accepted by the developers or implemented by the clients.

## Implementations
The yellow paper implements this change in https://github.com/ethereum/yellowpaper/pull/710

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 21 Jul 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1240</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1240</guid>
      </item>
    
      <item>
        <title>Membership Verification Token (MVT)</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1261</comments>
        
        <description>## Simple Summary

A standard interface for Membership Verification Token(MVT).

## Abstract

The following standard allows for the implementation of a standard API for Membership Verification Token within smart contracts(called entities). This standard provides basic functionality to track membership of individuals in certain on-chain ‘organizations’. This allows for several use cases like automated compliance, and several forms of governance and membership structures.

We considered use cases of MVTs being assigned to individuals which are non-transferable and revocable by the owner. MVTs can represent proof of recognition, proof of membership, proof of right-to-vote and several such otherwise abstract concepts on the blockchain. The following are some examples of those use cases, and it is possible to come up with several others:

- Voting: Voting is inherently supposed to be a permissioned activity. So far, onchain voting systems are only able to carry out voting with coin balance based polls. This can now change and take various shapes and forms.
- Passport issuance, social benefit distribution, Travel permit issuance, Drivers licence issuance are all applications which can be abstracted into membership, that is belonging of an individual to a small set, recognized by some authority as having certain entitlements, without needing any individual specific information(right to welfare, freedom of movement, authorization to operate vehicles, immigration)
- Investor permissioning: Making regulatory compliance a simple on chain process. Tokenization of securities, that are streamlined to flow only to accredited addresses, tracing and certifying on chain addresses for AML purposes.
- Software licencing: Software companies like game developers can use the protocol to authorize certain hardware units(consoles) to download and use specific software(games)

In general, an individual can have different memberships in their day to day life. The protocol allows for the creation of software that puts everything all at one place. Their identity can be verified instantly. Imagine a world where you don&apos;t need to carry a wallet full of identity cards (Passport, gym membership, SSN, Company ID etc) and organizations can easily keep track of all its members. Organizations can easily identify and disallow fake identities.

Attributes are a huge part of ERC-1261 which help to store identifiable information regarding its members. Polls can make use of attributes to calculate the voterbase.
E.g: Users should belong to USA entity and not belong to Washington state attribute to be a part of a poll.

There will exist a mapping table that maps attribute headers to an array of all possible attributes. This is done in order to subdivide entities into subgroups which are exclusive and exhaustive. For example,
header: blood group alphabet
Array: [ o, a, b, ab ]
header: blood group sign
Array: [ +, - ]

NOT an example of exclusive exhaustive:
Header: video subscription
Array: [ Netflix, HBO, Amazon ]
Because a person is not necessitated to have EXACTLY one of the elements. He or she may have none or more than one.

## Motivation

A standard interface allows any user, applications to work with any MVT on Ethereum. We provide for simple ERC-1261 smart contracts. Additional applications are discussed below.

This standard is inspired from the fact that voting on the blockchain is done with token balance weights. This has been greatly detrimental to the formation of flexible governance systems on the blockchain, despite the tremendous governance potential that blockchains offer. The idea was to create a permissioning system that allows organizations to vet people once into the organization on the blockchain, and then gain immense flexibility in the kind of governance that can be carried out.

We have also reviewed other Membership EIPs including EIP-725/735 Claim Registry. A significant difference between #735 claims and #1261 MVTs is information ownership. In #735 the Claim Holder owns any claims made about themselves. The problem with this is that there is no way for a Claim Issuer to revoke or alter a claim once it has been issued. While #735 does specify a removeClaim method, a malicious implementation could simply ignore that method call, because they own the claim.

Imagine that SafeEmploy™, a background checking company, issues a claim about Timmy. The claim states that Timmy has never been convicted of any felonies. Timmy makes some bad decisions, and now that claim is no longer true. SafeEmploy™ executes removeClaim, but Timmy&apos;s #735 contract just ignores it, because Timmy wants to stay employed (and is crypto-clever). #1261 MVTs do not have this problem. Ownership of a badge/claim is entirely determined by the contract issuing the badges, not the one receiving them. The issuer is free to remove or change those badges as they see fit.

**Trade-off between trustlessness and usability:**
To truly understand the value of the protocol, it is important to understand the trade-off we are treading on. The MVT contract allows the creator to revoke the token, and essentially confiscate the membership of the member in question. To some, this might seem like an unacceptable flaw, however this is a design choice, and not a flaw.
The choice may seem to place a great amount of trust in the individuals who are managing the entity contract(entity owners). If the interests of the entity owner conflict with the interests of the members, the owner may resort to addition of fake addresses(to dominate consensus) or evicting members(to censor unfavourable decisions). At first glance this appears to be a major shortcomings, because the blockchain space is used to absolute removal of authority in most cases. Even the official definition of a dapp requires the absence of any party that manages the services provided by the application. However, the trust in entity owners is not misplaced, if it can be ensured that the interests of entity owners are aligned with the interests of members.
Another criticism of such a system would be that the standard edge of blockchain intermediation - “you cannot bribe the system if you don’t know who to bribe” - no longer holds. It is possible to bribe an entity owner into submission, and get them to censor or fake votes. There are several ways to respond to this argument. First of all, all activities, such as addition of members, and removal of members can be tracked on the blockchain and traces of such activity cannot be removed. It is not difficult to build analytics tools to detect malicious activity(adding 100 fake members suddenly who vote in the direction/sudden removal of a number of members voting in a certain direction). Secondly, the entity owners’ power is limited to the addition and removal of members. This means that they cannot tamper any votes. They can only alter the counting system to include fake voters or remove real voters. Any sensible auditor can identify the malicious/victim addresses and create an open source audit tool to find out the correct results. The biggest loser in this attack will be the entity owner, who has a reputation to lose.
Finally, one must understand why we are taking a step away from trustlessness in this trade-off. The answer is usability. Introducing a permissioning system expands the scope of products and services that can be delivered through the blockchain, while leveraging other aspects of the blockchain(cheap, immutable, no red-tape, secure). Consider the example of the driver licence issuing agency using the ERC-1300 standard. This is a service that simply cannot be deployed in a completely trustless environment. The introduction of permissioned systems expanded the scope of services on the blockchain to cover this particular service. Sure, they have the power to revoke a person’s licence for no reason. But will they? Who stands to lose the most, if the agency acts erratically? The agency itself. Now consider the alternative, the way licences(not necessarily only drivers licence, but say shareholder certificates and so on) are issued, the amount of time consumed, the complete lack of transparency. One could argue that if the legacy systems providing these services really wanted to carry out corruption and nepotism in the execution of these services, the present systems make it much easier to do so. Also, they are not transparent, meaning that there is no way to even detect if they act maliciously.
All that being said, we are very excited to share our proposal with the community and open up to suggestions in this space.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

**Every ERC-1261 compliant contract must implement the `ERC1261`, `ERC173` and `ERC165` interfaces** (subject to &quot;caveats&quot; below):

```solidity
/// @title ERC-1261 MVT Standard
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1261.md
///  The constructor should define the attribute set for this MVT.
///  Note: the ERC-165 identifier for this interface is 0x1d8362cf.
interface IERC1261 {/* is ERC173, ERC165 */
    /// @dev This emits when a token is assigned to a member.
    event Assigned(address indexed _to, uint[] attributeIndexes);

    /// @dev This emits when a membership is revoked.
    event Revoked(address indexed _to);

    /// @dev This emits when a user forfeits his membership
    event Forfeited(address indexed _to);

    /// @dev This emits when a membership request is accepted
    event ApprovedMembership(address indexed _to, uint[] attributeIndexes);

    /// @dev This emits when a membership is requested by an user
    event RequestedMembership(address indexed _to);

    /// @dev This emits when data of a member is modified.
    ///  Doesn&apos;t emit when a new membership is created and data is assigned.
    event ModifiedAttributes(address indexed _to, uint attributeIndex, uint attributeValueIndex);

    /// @notice Adds a new attribute (key, value) pair to the set of pre-existing attributes.
    /// @dev Adds a new attribute at the end of the array of attributes and maps it to `values`.
    ///  Contract can set a max number of attributes and throw if limit is reached.
    /// @param _name Name of the attribute which is to be added.
    /// @param values List of values of the specified attribute.
    function addAttributeSet(bytes32 _name, bytes32[] calldata values) external;

    /// @notice Modifies the attribute value of a specific attribute for a given `_to` address.
    /// @dev Use appropriate checks for whether a user/admin can modify the data.
    ///  Best practice is to use onlyOwner modifier from ERC173.
    /// @param _to The address whose attribute is being modified.
    /// @param _attributeIndex The index of attribute which is being modified.
    /// @param _modifiedValueIndex The index of the new value which is being assigned to the user attribute.
    function modifyAttributeByIndex(address _to, uint _attributeIndex, uint _modifiedValueIndex) external;

    /// @notice Requests membership from any address.
    /// @dev Throws if the `msg.sender` already has the token.
    ///  The individual `msg.sender` can request for a membership if some existing criteria are satisfied.
    ///  When a membership is requested, this function emits the RequestedMembership event.
    ///  dev can store the membership request and use `approveRequest` to assign membership later
    ///  dev can also oraclize the request to assign membership later
    /// @param _attributeIndexes the attribute data associated with the member.
    ///  This is an array which contains indexes of attributes.
    function requestMembership(uint[] calldata _attributeIndexes) external payable;

    /// @notice User can forfeit his membership.
    /// @dev Throws if the `msg.sender` already doesn&apos;t have the token.
    ///  The individual `msg.sender` can revoke his/her membership.
    ///  When the token is revoked, this function emits the Revoked event.
    function forfeitMembership() external payable;

    /// @notice Owner approves membership from any address.
    /// @dev Throws if the `_user` doesn&apos;t have a pending request.
    ///  Throws if the `msg.sender` is not an owner.
    ///  Approves the pending request
    ///  Make oraclize callback call this function
    ///  When the token is assigned, this function emits the `ApprovedMembership` and `Assigned` events.
    /// @param _user the user whose membership request will be approved.
    function approveRequest(address _user) external;

    /// @notice Owner discards membership from any address.
    /// @dev Throws if the `_user` doesn&apos;t have a pending request.
    ///  Throws if the `msg.sender` is not an owner.
    ///  Discards the pending request
    ///  Make oraclize callback call this function if criteria are not satisfied
    /// @param _user the user whose membership request will be discarded.
    function discardRequest(address _user) external;

    /// @notice Assigns membership of an MVT from owner address to another address.
    /// @dev Throws if the member already has the token.
    ///  Throws if `_to` is the zero address.
    ///  Throws if the `msg.sender` is not an owner.
    ///  The entity assigns the membership to each individual.
    ///  When the token is assigned, this function emits the Assigned event.
    /// @param _to The address to which the token is assigned.
    /// @param _attributeIndexes The attribute data associated with the member.
    ///  This is an array which contains indexes of attributes.
    function assignTo(address _to, uint[] calldata _attributeIndexes) external;

    /// @notice Only Owner can revoke the membership.
    /// @dev This removes the membership of the user.
    ///  Throws if the `_from` is not an owner of the token.
    ///  Throws if the `msg.sender` is not an owner.
    ///  Throws if `_from` is the zero address.
    ///  When transaction is complete, this function emits the Revoked event.
    /// @param _from The current owner of the MVT.
    function revokeFrom(address _from) external;

    /// @notice Queries whether a member is a current member of the organization.
    /// @dev MVT&apos;s assigned to the zero address are considered invalid, and this
    ///  function throws for queries about the zero address.
    /// @param _to An address for whom to query the membership.
    /// @return Whether the member owns the token.
    function isCurrentMember(address _to) external view returns (bool);

     /// @notice Gets the value collection of an attribute.
    /// @dev Returns the values of attributes as a bytes32 array.
    /// @param _name Name of the attribute whose values are to be fetched
    /// @return The values of attributes.
    function getAttributeExhaustiveCollection(bytes32 _name) external view returns (bytes32[] memory);

    /// @notice Returns the list of all past and present members.
    /// @dev Use this function along with isCurrentMember to find wasMemberOf() in Js.
    ///  It can be calculated as present in getAllMembers() and !isCurrentMember().
    /// @return List of addresses who have owned the token and currently own the token.
    function getAllMembers() external view returns (address[]);

    /// @notice Returns the count of all current members.
    /// @dev Use this function in polls as denominator to get percentage of members voted.
    /// @return Count of current Members.
    function getCurrentMemberCount() external view returns (uint);

    /// @notice Returns the list of all attribute names.
    /// @dev Returns the names of attributes as a bytes32 array.
    ///  AttributeNames are stored in a bytes32 Array.
    ///  Possible values for each attributeName are stored in a mapping(attributeName =&gt; attributeValues).
    ///  AttributeName is bytes32 and attributeValues is bytes32[].
    ///  Attributes of a particular user are stored in bytes32[].
    ///  Which has a single attributeValue for each attributeName in an array.
    ///  Use web3.toAscii(data[0]).replace(/\u0000/g, &quot;&quot;) to convert to string in JS.
    /// @return The names of attributes.
    function getAttributeNames() external view returns (bytes32[] memory);

    /// @notice Returns the attributes of `_to` address.
    /// @dev Throws if `_to` is the zero address.
    ///  Use web3.toAscii(data[0]).replace(/\u0000/g, &quot;&quot;) to convert to string in JS.
    /// @param _to The address whose current attributes are to be returned.
    /// @return The attributes associated with `_to` address.
    function getAttributes(address _to) external view returns (bytes32[]);

    /// @notice Returns the `attribute` stored against `_to` address.
    /// @dev Finds the index of the `attribute`.
    ///  Throws if the attribute is not present in the predefined attributes.
    ///  Returns the attributeValue for the specified `attribute`.
    /// @param _to The address whose attribute is requested.
    /// @param _attributeIndex The attribute Index which is required.
    /// @return The attribute value at the specified name.
    function getAttributeByIndex(address _to, uint _attributeIndex) external view returns (bytes32);
}

interface ERC173 /* is ERC165 */ {
    /// @dev This emits when ownership of a contract changes.
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /// @notice Get the address of the owner
    /// @return The address of the owner.
    function owner() external view;

    /// @notice Set the address of the new owner of the contract
    /// @param _newOwner The address of the new owner of the contract
    function transferOwnership(address _newOwner) external;
}

interface ERC165 {
    /// @notice Query if a contract implements an interface
    /// @param interfaceID The interface identifier, as specified in ERC-165
    /// @dev Interface identification is specified in ERC-165. This function
    ///  uses less than 30,000 gas.
    /// @return `true` if the contract implements `interfaceID` and
    ///  `interfaceID` is not 0xffffffff, `false` otherwise
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
```

The **metadata extension** is OPTIONAL for ERC-1261 smart contracts (see &quot;caveats&quot;, below). This allows your smart contract to be interrogated for its name and for details about the organization which your MV tokens represent.

```solidity
/// @title ERC-1261 MVT Standard, optional metadata extension
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1261.md
interface ERC1261Metadata /* is ERC1261 */ {
    /// @notice A descriptive name for a collection of MVTs in this contract
    function name() external view returns (string _name);

    /// @notice An abbreviated name for MVTs in this contract
    function symbol() external view returns (string _symbol);
}
```

This is the &quot;ERC1261 Metadata JSON Schema&quot; referenced above.

```json
{
  &quot;title&quot;: &quot;Organization Metadata&quot;,
  &quot;type&quot;: &quot;object&quot;,
  &quot;properties&quot;: {
    &quot;name&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Identifies the organization to which this MVT represents&quot;
    },
    &quot;description&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Describes the organization to which this MVT represents&quot;
    }
  }
}
```

### Caveats

The 0.4.24 Solidity interface grammar is not expressive enough to document the ERC-1261 standard. A contract which complies with ERC-1261 MUST also abide by the following:

- Solidity issue #3412: The above interfaces include explicit mutability guarantees for each function. Mutability guarantees are, in order weak to strong: `payable`, implicit nonpayable, `view`, and `pure`. Your implementation MUST meet the mutability guarantee in this interface and you MAY meet a stronger guarantee. For example, a `payable` function in this interface may be implemented as nonpayble (no state mutability specified) in your contract. We expect a later Solidity release will allow your stricter contract to inherit from this interface, but a workaround for version 0.4.24 is that you can edit this interface to add stricter mutability before inheriting from your contract.
- Solidity issue #3419: A contract that implements `ERC1261Metadata` SHALL also implement `ERC1261`.
- Solidity issue #2330: If a function is shown in this specification as `external` then a contract will be compliant if it uses `public` visibility. As a workaround for version 0.4.24, you can edit this interface to switch to `public` before inheriting from your contract.
- Solidity issues #3494, #3544: Use of `this.*.selector` is marked as a warning by Solidity, a future version of Solidity will not mark this as an error.

_If a newer version of Solidity allows the caveats to be expressed in code, then this EIP MAY be updated and the caveats removed, such will be equivalent to the original specification._

## Rationale

There are many potential uses of Ethereum smart contracts that depend on tracking membership. Examples of existing or planned MVT systems are Vault, a DAICO platform, and Stream, a security token framework. Future uses include the implementation of direct democracy, in-game memberships and badges, licence and travel document issuance, electronic voting machine trails, software licencing and many more.

**MVT Word Choice:**

Since the tokens are non transferable and revocable, they function like membership cards. Hence the word membership verification token.

**Transfer Mechanism**

MVTs can&apos;t be transferred. This is a design choice, and one of the features that distinguishes this protocol.
Any member can always ask the issuer to revoke the token from an existing address and assign to a new address.
One can think of the set of MVTs as identifying a user, and you cannot split the user into parts and have it be the same user, but you can transfer a user to a new private key.

**Assign and Revoke mechanism**

The assign and revoke functions&apos; documentation only specify conditions when the transaction MUST throw. Your implementation MAY also throw in other situations. This allows implementations to achieve interesting results:

- **Disallow additional memberships after a condition is met** — Sample contract available on GitHub
- **Blacklist certain address from receiving MV tokens** — Sample contract available on GitHub
- **Disallow additional memberships after a certain time is reached** — Sample contract available on GitHub
- **Charge a fee to user of a transaction** — require payment when calling `assign` and `revoke` so that condition checks from external sources can be made

**ERC-173 Interface**

We chose Standard Interface for Ownership (ERC-173) to manage the ownership of a ERC-1261 contract.

A future EIP/ Zeppelin may create a multi-ownable implementation for ownership. We strongly support such an EIP and it would allow your ERC-1261 implementation to implement `ERC1261Metadata`, or other interfaces by delegating to a separate contract.

**ERC-165 Interface**

We chose Standard Interface Detection (ERC-165) to expose the interfaces that a ERC-1261 smart contract supports.

A future EIP may create a global registry of interfaces for contracts. We strongly support such an EIP and it would allow your ERC-1261 implementation to implement `ERC1261Metadata`, or other interfaces by delegating to a separate contract.

**Gas and Complexity** (regarding the enumeration extension)

This specification contemplates implementations that manage a few and _arbitrarily large_ numbers of MVTs. If your application is able to grow then avoid using for/while loops in your code. These indicate your contract may be unable to scale and gas costs will rise over time without bound

**Privacy**

Personal information: The protocol does not put any personal information on to the blockchain, so there is no compromise of privacy in that respect.
Membership privacy: The protocol by design, makes it public which addresses are/aren’t members. Without making that information public, it would not be possible to independently audit governance activity or track admin(entity owner) activity.

**Metadata Choices** (metadata extension)

We have required `name` and `symbol` functions in the metadata extension. Every token EIP and draft we reviewed (ERC-20, ERC-223, ERC-677, ERC-777, ERC-827) included these functions.

We remind implementation authors that the empty string is a valid response to `name` and `symbol` if you protest to the usage of this mechanism. We also remind everyone that any smart contract can use the same name and symbol as _your_ contract. How a client may determine which ERC-1261 smart contracts are well-known (canonical) is outside the scope of this standard.

A mechanism is provided to associate MVTs with URIs. We expect that many implementations will take advantage of this to provide metadata for each MVT system. The URI MAY be mutable (i.e. it changes from time to time). We considered an MVT representing membership of a place, in this case metadata about the organization can naturally change.

Metadata is returned as a string value. Currently this is only usable as calling from `web3`, not from other contracts. This is acceptable because we have not considered a use case where an on-blockchain application would query such information.

_Alternatives considered: put all metadata for each asset on the blockchain (too expensive), use URL templates to query metadata parts (URL templates do not work with all URL schemes, especially P2P URLs), multiaddr network address (not mature enough)_

**Community Consensus**

We have been very inclusive in this process and invite anyone with questions or contributions into our discussion. However, this standard is written only to support the identified use cases which are listed herein.

## Backwards Compatibility

We have adopted `name` and `symbol` semantics from the ERC-20 specification.

Example MVT implementations as of July 2018:

- Membership Verification Token(https://github.com/chaitanyapotti/MembershipVerificationToken)

## Test Cases

Membership Verification Token ERC-1261 Token includes test cases written using Truffle.

## Implementations

Membership Verification Token ERC1261 -- a reference implementation

- MIT licensed, so you can freely use it for your projects
- Includes test cases
- Also available as a npm package - npm i membershipverificationtoken

## References

**Standards**

1. ERC-20 Token Standard. ./eip-20.md
1. ERC-165 Standard Interface Detection. ./eip-165.md
1. ERC-725/735 Claim Registry ./eip-725.md
1. ERC-173 Owned Standard. ./eip-173.md
1. JSON Schema. https://json-schema.org/
1. Multiaddr. https://github.com/multiformats/multiaddr
1. RFC 2119 Key words for use in RFCs to Indicate Requirement Levels. https://www.ietf.org/rfc/rfc2119.txt

**Issues**

1. The Original ERC-1261 Issue. https://github.com/ethereum/eips/issues/1261
1. Solidity Issue \#2330 -- Interface Functions are Axternal. https://github.com/ethereum/solidity/issues/2330
1. Solidity Issue \#3412 -- Implement Interface: Allow Stricter Mutability. https://github.com/ethereum/solidity/issues/3412
1. Solidity Issue \#3419 -- Interfaces Can&apos;t Inherit. https://github.com/ethereum/solidity/issues/3419

**Discussions**

1. Gitter #EIPs (announcement of first live discussion). https://gitter.im/ethereum/EIPs?at=5b5a1733d2f0934551d37642
1. ERC-1261 (announcement of first live discussion). https://github.com/ethereum/eips/issues/1261

**MVT Implementations and Other Projects**

1. Membership Verification Token ERC-1261 Token. https://github.com/chaitanyapotti/MembershipVerificationToken

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 14 Jul 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1261</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1261</guid>
      </item>
    
      <item>
        <title>Standard Signature Validation Method for Contracts</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1271</comments>
        
        <description>## Abstract
Externally Owned Accounts (EOA) can sign messages with their associated private keys, but currently contracts cannot. We propose a standard way for any contracts to verify whether a signature on a behalf of a given contract is valid. This is possible via the implementation of a `isValidSignature(hash, signature)` function on the signing contract, which can be called to validate a signature.

## Motivation

There are and will be many contracts that want to utilize signed messages for validation of rights-to-move assets or other purposes. In order for these contracts to be able to support non Externally Owned Accounts (i.e., contract owners), we need a standard mechanism by which a contract can indicate whether a given signature is valid or not on its behalf.

One example of an application that requires signatures to be provided would be decentralized exchanges with off-chain orderbook, where buy/sell orders are signed messages. In these applications, EOAs sign orders, signaling their desire to buy/sell a given asset and giving explicit permissions to the exchange smart contracts to conclude a trade via a signature. When it comes to contracts however, regular signatures are not possible since contracts do not possess a private key, hence this proposal.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt).

```javascript
pragma solidity ^0.5.0;

contract ERC1271 {

  // bytes4(keccak256(&quot;isValidSignature(bytes32,bytes)&quot;)
  bytes4 constant internal MAGICVALUE = 0x1626ba7e;

  /**
   * @dev Should return whether the signature provided is valid for the provided hash
   * @param _hash      Hash of the data to be signed
   * @param _signature Signature byte array associated with _hash
   *
   * MUST return the bytes4 magic value 0x1626ba7e when function passes.
   * MUST NOT modify state (using STATICCALL for solc &lt; 0.5, view modifier for solc &gt; 0.5)
   * MUST allow external calls
   */ 
  function isValidSignature(
    bytes32 _hash, 
    bytes memory _signature)
    public
    view 
    returns (bytes4 magicValue);
}
```

`isValidSignature` can call arbitrary methods to validate a given signature, which could be context dependent (e.g. time based or state based), EOA dependent (e.g. signers authorization level within smart wallet), signature scheme Dependent (e.g. ECDSA, multisig, BLS), etc. 

This function should be implemented by contracts which desire to sign messages (e.g. smart contract wallets, DAOs, multisignature wallets, etc.) Applications wanting to support contract signatures should call this method if the signer is a contract.


## Rationale
We believe the name of the proposed function to be appropriate considering that an *authorized* signers providing proper signatures for a given data would see their signature as &quot;valid&quot; by the signing contract. Hence, a signed action message is only valid when the signer is authorized to perform a given action on the behalf of a smart wallet. 

Two arguments are provided for simplicity of separating the hash signed from the signature. A bytes32 hash is used instead of the unhashed message for simplicity, since contracts could expect a certain hashing function that is not standard, such as with [EIP-712](/EIPs/EIPS/eip-712). 

`isValidSignature()` should not be able to modify states in order to prevent `GasToken` minting or similar attack vectors. Again, this is to simplify the implementation surface of the function for better standardization and to allow off-chain contract queries.

The specific return value is expected to be returned instead of a boolean in order to have stricter and simpler verification of a signature. 

## Backwards Compatibility

This EIP is backward compatible with previous work on signature validation since this method is specific to contract based signatures and not EOA signatures. 

## Reference Implementation

Example implementation of a signing contract:

```solidity

  /**
   * @notice Verifies that the signer is the owner of the signing contract.
   */
  function isValidSignature(
    bytes32 _hash,
    bytes calldata _signature
  ) external override view returns (bytes4) {
    // Validate signatures
    if (recoverSigner(_hash, _signature) == owner) {
      return 0x1626ba7e;
    } else {
      return 0xffffffff;
    }
  }

 /**
   * @notice Recover the signer of hash, assuming it&apos;s an EOA account
   * @dev Only for EthSign signatures
   * @param _hash       Hash of message that was signed
   * @param _signature  Signature encoded as (bytes32 r, bytes32 s, uint8 v)
   */
  function recoverSigner(
    bytes32 _hash,
    bytes memory _signature
  ) internal pure returns (address signer) {
    require(_signature.length == 65, &quot;SignatureValidator#recoverSigner: invalid signature length&quot;);

    // Variables are not scoped in Solidity.
    uint8 v = uint8(_signature[64]);
    bytes32 r = _signature.readBytes32(0);
    bytes32 s = _signature.readBytes32(32);

    // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
    // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
    // the valid range for s in (281): 0 &lt; s &lt; secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most
    // signatures from current libraries generate a unique signature with an s-value in the lower half order.
    //
    // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
    // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
    // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
    // these malleable signatures as well.
    //
    // Source OpenZeppelin
    // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/cryptography/ECDSA.sol

    if (uint256(s) &gt; 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
      revert(&quot;SignatureValidator#recoverSigner: invalid signature &apos;s&apos; value&quot;);
    }

    if (v != 27 &amp;&amp; v != 28) {
      revert(&quot;SignatureValidator#recoverSigner: invalid signature &apos;v&apos; value&quot;);
    }

    // Recover ECDSA signer
    signer = ecrecover(_hash, v, r, s);
    
    // Prevent signer from being 0x0
    require(
      signer != address(0x0),
      &quot;SignatureValidator#recoverSigner: INVALID_SIGNER&quot;
    );

    return signer;
  }
```

Example implementation of a contract calling the isValidSignature() function on an external signing contract ; 

```solidity
  function callERC1271isValidSignature(
    address _addr,
    bytes32 _hash,
    bytes calldata _signature
  ) external view {
    bytes4 result = IERC1271Wallet(_addr).isValidSignature(_hash, _signature);
    require(result == 0x1626ba7e, &quot;INVALID_SIGNATURE&quot;);
  }
```

## Security Considerations
Since there are no gas-limit expected for calling the isValidSignature() function, it is possible that some implementation will consume a large amount of gas. It is therefore important to not hardcode an amount of gas sent when calling this method on an external contract as it could prevent the validation of certain signatures.

Note also that each contract implementing this method is responsible to ensure that the signature passed is indeed valid, otherwise catastrophic outcomes are to be expected.


## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 25 Jul 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1271</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1271</guid>
      </item>
    
      <item>
        <title>Eliminate Difficulty Bomb and Adjust Block Reward on Constantinople Shift</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-1276-eliminate-difficulty-bomb-and-adjust-block-reward-on-constantinople-shift/908</comments>
        
        <description>## Simple Summary
The average block times are increasing due to the factor of difficulty logic well known as difficulty bomb. This EIP proposes to eliminate the difficulty bomb forever and to reduce the block rewards with the Constantinople fork, the second part of the Metropolis fork.

## Abstract
Starting with `CNSTNTNPL_FORK_BLKNUM` the client will calculate the difficulty without considering the current block number. Furthermore, block rewards will be adjusted to a base of 2 ETH, uncle and nephew rewards will be adjusted accordingly.

## Motivation
Block time has been played a most important role on blockchain ecosystem, and it is being adjusted by the logic of mining difficulty calculation that is already implemented on the node client as a part of proof-of-work consensus. Last year, average block time rapidly increased due to the wrong design of difficulty logic that is meant to be changed on the part of Casper upgrade, however, implementation of casper has been delayed therefore it was inevitable to delay the difficulty bomb in order to prevent the significant delay of processing transactions on ethereum network.

Despite of the successful hardfork to delay the activation of difficulty bomb, activation of the difficulty bomb is expected to happen again on the upcoming period before implementing casper protocol on ethereum network. Therefore, completely removing the difficulty bomb is the most proper way to response the block time increase instead of delaying it again.

Also decreasing the block mining reward along with difficulty bomb removal is expected to help the growth of the stable ethereum ecosystem, right now ethereum dominates 92% of the total hashrate share of ethash based chains, and this corresponds to a tremendous level of energy consumption. As this energy consumption has a correlated environmental cost the network participants have an ethical obligation to ensure this cost is not higher than necessary. At this time, the most direct way to reduce this cost is to lower the block reward in order to limit the appeal of ETH mining. Unchecked growth in hashrate is also counterproductive from a security standpoint. Reducing the reward also decreases the likelihood of a miner driven chain split as Ethereum approaches proof-of-stake.

## Specification
#### Remove Exponential Component of Difficulty Adjustment
For the purposes of `calc_difficulty`, simply remove the exponential difficulty adjustment component, `epsilon`, i.e. the `int(2**((block.number // 100000) - 2))`.

#### Adjust Block, Uncle, and Nephew rewards
To ensure a constant Ether issuance, adjust the block reward to `new_block_reward`, where

    new_block_reward = 2_000_000_000_000_000_000 if block.number &gt;= CNSTNTNPL_FORK_BLKNUM else block.reward

(2E18 wei, or 2,000,000,000,000,000,000 wei, or 2 ETH).

Analogue, if an uncle is included in a block for `block.number &gt;= CNSTNTNPL_FORK_BLKNUM` such that `block.number - uncle.number = k`, the uncle reward is

    new_uncle_reward = (8 - k) * new_block_reward / 8

This is the existing pre-Constantinople formula for uncle rewards, simply adjusted with `new_block_reward`.

The nephew reward for `block.number &gt;= CNSTNTNPL_FORK_BLKNUM` is

    new_nephew_reward = new_block_reward / 32

This is the existing pre-Constantinople formula for nephew rewards, simply adjusted with `new_block_reward`.

## Rationale
This will completely remove the difficulty bomb on difficulty adjustment algorithm without delaying the difficulty bomb again, therefore it is possible to prevent network delay on the beginning of 2019.

This EIP-1276 opposes directly the intent of [EIP-1234](/EIPs/EIPS/eip-1234) which should be also considered in discussions.

## Backwards Compatibility
This EIP is not forward compatible and introduces backwards incompatibilities in the difficulty calculation, as well as the block, uncle and nephew reward structure. Therefore, it should be included in a scheduled hardfork at a certain block number. It&apos;s suggested to include this EIP in the second Metropolis hard-fork, _Constantinople_.

## Test Cases
Test cases shall be created once the specification is to be accepted by the developers or implemented by the clients.

## Implementation
The implementation shall be created once the specification is to be accepted by the developers or implemented by the clients.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 31 Jul 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1276</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1276</guid>
      </item>
    
      <item>
        <title>Net gas metering for SSTORE without dirty maps</title>
        <category>Standards Track/Core</category>
        
          <comments>https://github.com/sorpaas/EIPs/issues/1</comments>
        
        <description>## Abstract

This EIP proposes net gas metering changes for `SSTORE` opcode, enabling
new usages for contract storage, and reducing excessive gas costs
where it doesn&apos;t match how most implementations work.

This acts as an alternative for EIP-1087, where it tries to be
friendlier to implementations that use different optimization
strategies for storage change caches.

## Motivation

This EIP proposes a way for gas metering on SSTORE (as an alternative
for EIP-1087 and EIP-1153), using information that is more universally
available to most implementations, and requires as little change in
implementation structures as possible.

* *Storage slot&apos;s original value*.
* *Storage slot&apos;s current value*. 
* Refund counter.

Usages that benefits from this EIP&apos;s gas reduction scheme includes:

* Subsequent storage write operations within the same call frame. This
  includes reentry locks, same-contract multi-send, etc.
* Exchange storage information between sub call frame and parent call
  frame, where this information does not need to be persistent outside
  of a transaction. This includes sub-frame error codes and message
  passing, etc.

## Specification

Definitions of terms are as below:

* *Storage slot&apos;s original value*: This is the value of the storage if
  a reversion happens on the *current transaction*.
* *Storage slot&apos;s current value*: This is the value of the storage
  before SSTORE operation happens.
* *Storage slot&apos;s new value*: This is the value of the storage after
  SSTORE operation happens.

Replace `SSTORE` opcode gas cost calculation (including refunds) with
the following logic:

* If *current value* equals *new value* (this is a no-op), 200 gas is
  deducted.
* If *current value* does not equal *new value*
  * If *original value* equals *current value* (this storage slot has
    not been changed by the current execution context)
    * If *original value* is 0, 20000 gas is deducted.
    * Otherwise, 5000 gas is deducted. If *new value* is 0, add 15000
      gas to refund counter.
  * If *original value* does not equal *current value* (this storage
    slot is dirty), 200 gas is deducted. Apply both of the following
    clauses.
    * If *original value* is not 0
      * If *current value* is 0 (also means that *new value* is not
        0), remove 15000 gas from refund counter. We can prove that
        refund counter will never go below 0.
      * If *new value* is 0 (also means that *current value* is not
        0), add 15000 gas to refund counter.
    * If *original value* equals *new value* (this storage slot is
      reset)
      * If *original value* is 0, add 19800 gas to refund counter.
      * Otherwise, add 4800 gas to refund counter.

Refund counter works as before -- it is limited to half of the gas
consumed. On a transaction level, refund counter will never go below
zero. However, there are some important notes depending on the
implementation details:

* If an implementation uses &quot;transaction level&quot; refund counter (refund
  is checkpointed at each call frame), then the refund counter
  continues to be unsigned.
* If an implementation uses &quot;execution-frame level&quot; refund counter
  (a new refund counter is created at each call frame, and then merged
  back to parent when the call frame finishes), then the refund
  counter needs to be changed to signed -- at internal calls, a child
  refund can go below zero.

## Explanation

The new gas cost scheme for `SSTORE` is divided into three different
types:

* **No-op**: the virtual machine does not need to do anything. This is
  the case if *current value* equals *new value*.
* **Fresh**: this storage slot has not been changed, or has been reset
  to its original value. This is the case if *current value* does not
  equal *new value*, and *original value* equals *current value*.
* **Dirty**: this storage slot has already been changed. This is the
  case if *current value* does not equal *new value*, and *original
  value* does not equal *current value*.

We can see that the above three types cover all possible variations of
*original value*, *current value*, and *new value*.

**No-op** is a trivial operation. Below we only consider cases for
**Fresh** and **Dirty**.

All initial (not-**No-op**) `SSTORE` on a particular storage slot starts
with **Fresh**. After that, it will become **Dirty** if the value has
been changed. When going from **Fresh** to **Dirty**, we charge the
gas cost the same as current scheme. A **Dirty** storage slot can be
reset back to **Fresh** via a `SSTORE` opcode. This will trigger a
refund.

When a storage slot remains at **Dirty**, we charge 200 gas. In this
case, we would also need to keep track of `R_SCLEAR` refunds -- if we
already issued the refund but it no longer applies (*current value* is
0), then removes this refund from the refund counter. If we didn&apos;t
issue the refund but it applies now (*new value* is 0), then adds this
refund to the refund counter. It is not possible where a refund is not
issued but we remove the refund in the above case, because all storage
slot starts with **Fresh** state.

### State Transition

Below is a graph ([by
@Arachnid](https://github.com/ethereum/EIPs/pull/1283#issuecomment-410229053))
showing possible state transition of gas costs. We ignore **No-op**
state because that is trivial:

![State Transition](/EIPs/assets/eip-1283/state.png)

Below is table version of the above diagram. Vertical shows the *new
value* being set, and horizontal shows the state of *original value*
and *current value*.

When *original value* is 0:

|    | A (`current=orig=0`) | B (`current!=orig`)      |
|----|----------------------|--------------------------|
| ~0 | B; 20k gas           | B; 200 gas               |
| 0  | A; 200 gas           | A; 200 gas, 19.8k refund |

When *original value* is not 0:

|             | X (`current=orig!=0`) | Y (`current!=orig`)     | Z (`current=0`)           |
|-------------|-----------------------|-------------------------|---------------------------|
| `orig`      | X; 200 gas            | X; 200 gas, 4.8k refund | X; 200 gas, -10.2k refund |
| `~orig, ~0` | Y; 5k gas             | Y; 200 gas              | Y; 200 gas, -15k refund   |
| 0           | Z; 5k gas, 15k refund | Z; 200 gas, 15k refund  | Z; 200 gas                |

## Rationale

This EIP mostly achieves what a transient storage tries to do
(EIP-1087 and EIP-1153), but without the complexity of introducing the
concept of &quot;dirty maps&quot;, or an extra storage struct.

* We don&apos;t suffer from the optimization limitation of
  EIP-1087. EIP-1087 requires keeping a dirty map for storage changes,
  and implicitly makes the assumption that a transaction&apos;s storage
  changes are committed to the storage trie at the end of a
  transaction. This works well for some implementations, but not for
  others. After EIP-658, an efficient storage cache implementation
  would probably use an in-memory trie (without RLP encoding/decoding)
  or other immutable data structures to keep track of storage changes,
  and only commit changes at the end of a block. For them, it is
  possible to know a storage&apos;s original value and current value, but
  it is not possible to iterate over all storage changes without
  incurring additional memory or processing costs.
* It never costs more gas compared with the current scheme.
* It covers all usages for a transient storage. Clients that are easy
  to implement EIP-1087 will also be easy to implement this
  specification. Some other clients might require a little bit extra
  refactoring on this. Nonetheless, no extra memory or processing cost
  is needed on runtime.

Regarding `SSTORE` gas cost and refunds, see Appendix for proofs of
properties that this EIP satisfies.

* For *absolute gas used* (that is, actual *gas used* minus *refund*),
  this EIP is equivalent to EIP-1087 for all cases.
* For one particular case, where a storage slot is changed, reset to
  its original value, and then changed again, EIP-1283 would move more
  gases to refund counter compared with EIP-1087.

Examine examples provided in EIP-1087&apos;s Motivation:

* If a contract with empty storage sets slot 0 to 1, then back to 0,
  it will be charged `20000 + 200 - 19800 = 400` gas.
* A contract with empty storage that increments slot 0 5 times will be
  charged `20000 + 5 * 200 = 21000` gas.
* A balance transfer from account A to account B followed by a
  transfer from B to C, with all accounts having nonzero starting and
  ending balances, it will cost `5000 * 3 + 200 - 4800 = 10400` gas.

## Backwards Compatibility

This EIP requires a hard fork to implement. No gas cost increase is
anticipated, and many contracts will see gas reduction.

## Test Cases

Below we provide 17 test cases. 15 of them covering consecutive two
`SSTORE` operations are based on work [by
@chfast](https://github.com/ethereum/tests/issues/483). Two additional
cases with three `SSTORE` operations is used to test the case when a
slot is reset and then set again.

| Code                               | Used Gas | Refund | Original | 1st | 2nd | 3rd |
|------------------------------------|----------|--------|----------|-----|-----|-----|
| `0x60006000556000600055`           | 412      | 0      | 0        | 0   | 0   |     |
| `0x60006000556001600055`           | 20212    | 0      | 0        | 0   | 1   |     |
| `0x60016000556000600055`           | 20212    | 19800  | 0        | 1   | 0   |     |
| `0x60016000556002600055`           | 20212    | 0      | 0        | 1   | 2   |     |
| `0x60016000556001600055`           | 20212    | 0      | 0        | 1   | 1   |     |
| `0x60006000556000600055`           | 5212     | 15000  | 1        | 0   | 0   |     |
| `0x60006000556001600055`           | 5212     | 4800   | 1        | 0   | 1   |     |
| `0x60006000556002600055`           | 5212     | 0      | 1        | 0   | 2   |     |
| `0x60026000556000600055`           | 5212     | 15000  | 1        | 2   | 0   |     |
| `0x60026000556003600055`           | 5212     | 0      | 1        | 2   | 3   |     |
| `0x60026000556001600055`           | 5212     | 4800   | 1        | 2   | 1   |     |
| `0x60026000556002600055`           | 5212     | 0      | 1        | 2   | 2   |     |
| `0x60016000556000600055`           | 5212     | 15000  | 1        | 1   | 0   |     |
| `0x60016000556002600055`           | 5212     | 0      | 1        | 1   | 2   |     |
| `0x60016000556001600055`           | 412      | 0      | 1        | 1   | 1   |     |
| `0x600160005560006000556001600055` | 40218    | 19800  | 0        | 1   | 0   | 1   |
| `0x600060005560016000556000600055` | 10218    | 19800  | 1        | 0   | 1   | 0   |

## Appendix: Proof

Because the *storage slot&apos;s original value* is defined as the value
when a reversion happens on the *current transaction*, it&apos;s easy to
see that call frames won&apos;t interfere SSTORE gas calculation. So
although the below proof is discussed without call frames, it applies
to all situations with call frames. We will discuss the case
separately for *original value* being zero and not zero, and use
*induction* to prove some properties of SSTORE gas cost.

*Final value* is the value of a particular storage slot at the end of
a transaction. *Absolute gas used* is the absolute value of *gas used*
minus *refund*. We use `N` to represent the total number of SSTORE
operations on a storage slot. For states discussed below, refer to
*State Transition* in *Explanation* section.

### Original Value Being Zero

When *original value* is 0, we want to prove that:

* **Case I**: If the *final value* ends up still being 0, we want to charge `200 *
  N` gases, because no disk write is needed.
* **Case II**: If the *final value* ends up being a non-zero value, we want to
  charge `20000 + 200 * (N-1)` gas, because it requires writing this
  slot to disk.
  
#### Base Case

We always start at state A. The first SSTORE can:

* Go to state A: 200 gas is deducted. We satisfy *Case I* because
  `200 * N == 200 * 1`.
* Go to state B: 20000 gas is deducted. We satisfy *Case II* because
  `20000 + 200 * (N-1) == 20000 + 200 * 0`.
  
#### Inductive Step

* From A to A. The previous gas cost is `200 * (N-1)`. The current
  gas cost is `200 + 200 * (N-1)`. It satisfy *Case I*.
* From A to B. The previous gas cost is `200 * (N-1)`. The current
  gas cost is `20000 + 200 * (N-1)`. It satisfy *Case II*.
* From B to B. The previous gas cost is `20000 + 200 * (N-2)`. The
  current gas cost is `200 + 20000 + 200 * (N-2)`. It satisfy
  *Case II*.
* From B to A. The previous gas cost is `20000 + 200 * (N-2)`. The
  current gas cost is `200 - 19800 + 20000 + 200 * (N-2)`. It satisfy
  *Case I*.
  
### Original Value Not Being Zero

When *original value* is not 0, we want to prove that:

* **Case I**: If the *final value* ends up unchanged, we want to
  charge `200 * N` gases, because no disk write is needed.
* **Case II**: If the *final value* ends up being zero, we want to
  charge `5000 - 15000 + 200 * (N-1)` gas. Note that `15000` is the
  refund in actual definition.
* **Case III**: If the *final value* ends up being a changed non-zero
  value, we want to charge `5000 + 200 * (N-1)` gas.
  
#### Base Case

We always start at state X. The first SSTORE can:

* Go to state X: 200 gas is deducted. We satisfy *Case I* because
  `200 * N == 200 * 1`.
* Go to state Y: 5000 gas is deducted. We satisfy *Case III* because
  `5000 + 200 * (N-1) == 5000 + 200 * 0`.
* Go to state Z: The absolute gas used is `5000 - 15000` where 15000
  is the refund. We satisfy *Case II* because `5000 - 15000 + 200 *
  (N-1) == 5000 - 15000 + 200 * 0`.
  
#### Inductive Step

* From X to X. The previous gas cost is `200 * (N-1)`. The current gas
  cost is `200 + 200 * (N-1)`. It satisfy *Case I*.
* From X to Y. The previous gas cost is `200 * (N-1)`. The current gas
  cost is `5000 + 200 * (N-1)`. It satisfy *Case III*.
* From X to Z. The previous gas cost is `200 * (N-1)`. The current
  absolute gas cost is `5000 - 15000 + 200 * (N-1)`. It satisfy *Case
  II*.
* From Y to X. The previous gas cost is `5000 + 200 * (N-2)`. The
  absolute current gas cost is `200 - 4800 + 5000 + 200 * (N-2)`. It
  satisfy *Case I*.
* From Y to Y. The previous gas cost is `5000 + 200 * (N-2)`. The
  current gas cost is `200 + 5000 + 200 * (N-2)`. It satisfy *Case
  III*.
* From Y to Z. The previous gas cost is `5000 + 200 * (N-2)`. The
  current absolute gas cost is `200 - 15000 + 5000 + 200 * (N-2)`. It
  satisfy *Case II*.
* From Z to X. The previous gas cost is `5000 - 15000 + 200 *
  (N-2)`. The current absolute gas cost is `200 + 10200 + 5000 -
  15000 + 200 * (N-2)`. It satisfy *Case I*.
* From Z to Y. The previous gas cost is `5000 - 15000 + 200 *
  (N-2)`. The current absolute gas cost is `200 + 15000 + 5000 -
  15000 + 200 * (N-2)`. It satisfy *Case III*.
* From Z to Z. The previous gas cost is `5000 - 15000 + 200 *
  (N-2)`. The current absolute gas cost is `200 + 5000 - 15000 + 200 *
  (N-2)`. It satisfy *Case II*.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 01 Aug 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1283</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1283</guid>
      </item>
    
      <item>
        <title>Increase Gcallstipend gas in the CALL opcode</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-1285-increase-gcallstipend-gas-in-the-call-opcode/941</comments>
        
        <description>## Simple Summary
Increase the ``Gcallstipend`` fee parameter in the ``CALL`` opcode from ``2,300`` to ``3,500`` gas units.

## Abstract
Currently, the ``CALL`` opcode forwards a stipend of ``2,300`` gas units for a non zero value ``CALL`` operations where a contract is called. This stipend is given to the contract to allow execution of its ``fallback`` function. The stipend given is intentionally small in order to prevent the called contract from spending the call gas or performing an attack (like re-entrancy).
While the stipend is small it should still give the sufficient gas required for some cheap opcodes like ``LOG``, but it&apos;s not enough for some more complex and modern logics to be implemented.
This EIP proposes to increase the given stipend from ``2,300`` to ``3,500`` to increase the usability of  the ``fallback`` function.


## Motivation
The main motivation behind this EIP is to allow simple fallback functions to be implemented for contracts following the ``&quot;Proxy&quot;`` pattern. Simply explained, a ``&quot;Proxy Contract&quot;`` is a contract which use ``DELEGATECALL`` in its ``fallback`` function to behave according to the logic of another contract and serve as an independent instance for the logic of the contract it points to.
This pattern is very useful for saving gas per deployment (as Proxy contracts are very lean) and it opens the ability to experiment with upgradability of contracts.
On average, the ``DELEGATECALL`` functionality of a proxy contract costs about ``1,000`` gas units.
When a contract transfers ETH to a proxy contract, the proxy logic will consume about ``1,000`` gas units before the ``fallback`` function of the logic contract will be executed. This leaves merely about 1,300 gas units for the execution of the logic. This is a severe limitation as it is not enough for an average ``LOG`` operation (it might be enough for a ``LOG`` with one parameter).
By slightly increasing the gas units given in the stipend we allow proxy contracts have proper ``fallback`` logic without increasing the attack surface of the calling contract.

## Specification
Increase the ``Gcallstipend`` fee parameter in the ``CALL`` opcode from ``2,300`` to ``3,500`` gas unit.
The actual change to the Ethereum clients would be to change the ``CallStipend`` they store as a constant.
For an implementation example you can find a Geth client implementation linked [here](https://github.com/ben-kaufman/go-ethereum/tree/eip-1285). The actual change to the code can be found [here](https://github.com/ben-kaufman/go-ethereum/blob/eip-1285/params/protocol_params.go#L41).

## Rationale
The rational for increasing the ``Gcallstipend`` gas parameter by ``1,200`` gas units comes from the cost of performing ``DELEGATECALL`` and ``SLOAD`` with a small margin for some small additional operations. All while still keeping the stipend relatively small and insufficient for accessing the storage or changing the state.

## Backwards Compatibility
This EIP requires a backwards incompatible change for the ``Gcallstipend`` gas parameter in the ``CALL`` opcode.


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 01 Aug 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1285</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1285</guid>
      </item>
    
      <item>
        <title>Modify Ethereum PoW Incentive Structure and Delay Difficulty Bomb</title>
        <category>Standards Track/Core</category>
        
          <comments>https://github.com/atlanticcrypto/Discussion/issues/1</comments>
        
        <description>## Simple Summary
Network security and overall ecosystem maturity warrants the continued incentivization of Proof of Work participation but may allow for a reduction in ancillary ETH issuance and the delay of the Difficulty Bomb. This EIP proposes a reduction of Uncle and removal of Nephew rewards while delaying the Difficulty Bomb with the Constantinople hard fork.

## Abstract
Starting with CNSTNTNPL_FORK_BLKNUM the client will calculate the difficulty based on a fake block number suggesting the client that the difficulty bomb is adjusting around 6 million blocks later than previously specified with the Homestead fork. 

Furthermore, Uncle rewards will be adjusted and Nephew rewards will be removed to eliminate excess ancillary ETH issuance. The current ETH block reward of 3 ETH will remain constant.


## Motivation
Network scalability and security are at the forefront of risks to the Ethereum protocol. With great strides being made towards on and off chain scalability, the existence of an artificial throughput limiting device in the protocol is not warranted. Removing the risk of reducing throughput through the initialization of the Difficulty Bomb is &quot;low-hanging-fruit&quot; to ensure continued operation at a minimum of current throughput through the next major hard fork (scheduled for late 2019).

The security layer of the Ethereum network is and should remain robust. Incentives for continued operation of the security of the growing ecosystem are paramount. 

At the same time, the ancillary issuance benefits of the Ethereum protocol can be adjusted to reduce the overall issuance profile. Aggressively adjusting Uncle and removing Nephew rewards will reduce the inflationary aspect of ETH issuance, while keeping the current block reward constant at 3 ETH will ensure top line incentives stay in place.

## Specification
#### Relax Difficulty with Fake Block Number
For the purposes of `calc_difficulty`, simply replace the use of `block.number`, as used in the exponential ice age component, with the formula:

    fake_block_number = max(0, block.number - 6_000_000) if block.number &gt;= CNSTNTNPL_FORK_BLKNUM else block.number
    
#### Adjust Uncle and Nephew rewards
If an uncle is included in a block for `block.number &gt;= CNSTNTNPL_FORK_BLKNUM` such that `block.number - uncle.number = k`, the uncle reward is

    new_uncle_reward = (3 - k) * new_block_reward / 8

This is the existing pre-Constantinople formula for uncle rewards, adjusted to reward 2 levels of Uncles at a reduced rate.

The nephew reward for `block.number &gt;= CNSTNTNPL_FORK_BLKNUM` is

    new_nephew_reward = 0

This is a removal of all rewards for Nephew blocks.

## Rationale

The security layer of the Ethereum network is and should remain robust. Incentives for continued operation of the growing ecosystem’s security are paramount. 

At the same time, the ancillary issuance benefits of the Ethereum protocol can be adjusted to reduce the overall issuance profile. Aggressively adjusting Uncle and removing Nephew rewards will reduce the inflationary aspect of ETH issuance, while keeping the current block reward constant at 3 ETH will ensure top line incentives stay in place.

The Difficulty Bomb was instituted as a type of planned obsolescence to force the implementation of network upgrades with regular frequency. With the focus on scalability for the protocol, delaying a mechanism whereby the throughput of the network can be limited artificially, due to any circumstance, is a logical step to ensure continued minimum network operation at the current throughput level. We believe the existence of the Difficulty Bomb has allowed for the inclusion of protocol upgrades in forced hard-forks, and will continue to do so.

Through August 4th, the 2018 year to date reward issued to Uncle blocks totaled over 635,000 ETH. The average reward per Uncle totals 2.27 ETH. The year to date average Uncle rate is 22.49%. Using the year to date metrics, the ongoing average ETH paid as an Uncle reward per block is 0.51 ETH plus the Uncle inclusion reward of 0.021 ETH (0.09375 ETH * .2249), total Uncle related reward per block being over 0.53 ETH. With total year to date block rewards totaling approximately 3,730,000 ETH, the network has paid an additional 17pct in Uncle rewards. This is issuance that can be reduced while still maintaining the overall integrity and incentivization of network security.

Reducing the issuance of ETH in rewarding Uncle blocks (forked blocks caused by latency in propagation, a multi-faceted problem) should directly incentivize the investment in technologies and efficiencies to reduce block propagation latency which may lead to a reduction in Network wide Uncle rates, reducing ancillary issuance further.

Reducing the Uncle rewards from the current specification to the proposed will yield two levels of ancillary ETH issuance for Uncles:

Level 1 Uncle -&gt; 0.75 ETH

Level 2 Uncle -&gt; 0.375 ETH

These levels are sufficient to continue incentivizing decentralized participation, while also providing an immediate economic incentive for the upgrade of the Ethereum node network and its tangential infrastructure.

We believe that the ETH network has been subsidizing transaction inclusion through the robust Uncle Reward structure since inception. We also believe that a removal of the set subsidy will create a dynamic response mechanism whereby Miners and transaction senders will minimize total costs of transaction inclusion. This dynamic response structure may limit unnecessary layer 1 transaction throughput while providing incentives for layer 2 scaling solutions.

The Nephew reward structure should be entirely eliminated.

Due to current market conditions, and the likelihood of a further USD denominated price decline (50%), we believe that any top line reduction to security incentives will put the Ethereum network at undue risk. Unlike the time of the Byzantium hard fork, current USD denominated economics for securing the Ethereum network threaten the participation of the most decentralized Miner community (at home miners), which we believe make up the largest proportion of the overall network hashrate. We believe eliminating this portion of the community will increase centralization and the probability of an organized network attack. 

For a technology so new and with so much potential, we find it extremely irresponsible to increase the likelihood of a network attack by reducing ETH Issuance past this proposal’s level.

With a reduction to the Uncle and removal of the Nephew reward, ancillary ETH issuance should drop (under normal market conditions, i.e. 22.49% uncle rate) by over 75pct and total ETH issuance from the successful sealing and mining of valid blocks should drop over 10pct.

Paired with the diffusal of the Difficulty Bomb, this proposal strikes a balance between ensuring status quo network throughput, reducing overall ETH issuance, and continuing top line incentives for investment in infrastructure and efficiencies to continue operating the Ethereum network’s security layer.

## Backwards Compatibility
This EIP is not forward compatible and introduces backwards incompatibilities in the difficulty calculation, as well as the block, uncle and nephew reward structure. Therefore, it should be included in a scheduled hardfork at a certain block number. It&apos;s suggested to include this EIP in the second Metropolis hard-fork, Constantinople.

## Test Cases
Test cases shall be created once the specification is to be accepted by the developers or implemented by the clients.

## Implementation
Forthcoming.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 05 Aug 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1295</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1295</guid>
      </item>
    
      <item>
        <title>Smart Contract Package Registry Interface</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1319</comments>
        
        <description>## Simple Summary
A standard interface for smart contract package registries.

## Abstract
This EIP specifies an interface for publishing to and retrieving assets from smart contract package registries. It is a companion EIP to [1123](/EIPs/EIPS/eip-1123) which defines a standard for smart contract package manifests.

## Motivation
The goal is to establish a framework that allows smart contract publishers to design and deploy code registries with arbitrary business logic while exposing a set of common endpoints that tooling can use to retrieve assets for contract consumers.

A clear standard would help the existing EthPM Package Registry evolve from a centralized, single-project community resource into a decentralized multi-registry system whose constituents are bound together by the proposed interface. In turn, these registries could be ENS name-spaced, enabling installation conventions familiar to users of `npm` and other package managers.

**Examples**
```shell
$ ethpm install packages.zeppelin.eth/Ownership
```

```javascript
const SimpleToken = await web3.packaging
                              .registry(&apos;packages.ethpm.eth&apos;)
                              .getPackage(&apos;simple-token&apos;)
                              .getVersion(&apos;^1.1.5&apos;);
```

## Specification
The specification describes a small read/write API whose components are mandatory. It allows registries to manage versioned releases using the conventions of [semver](https://semver.org/) without imposing this as a requirement. It assumes registries will share the following structure and conventions:

+ a **registry** is a deployed contract which manages a collection of **packages**.
+ a **package** is a collection of **releases**
+ a **package** is identified by a unique string name and unique bytes32 **packageId** within a given **registry**
+ a **release** is identified by a `bytes32` **releaseId** which must be unique for a given package name and release version string pair.
+ a **releaseId** maps to a set of data that includes a **manifestURI** string which describes the location of an [EIP 1123 package manifest](/EIPs/EIPS/eip-1123). This manifest contains data about the release including the location of its component code assets.
+ a **manifestURI** is a URI as defined by [RFC3986](https://tools.ietf.org/html/rfc3986) which can be used to retrieve the contents of the package manifest. In addition to validation against RFC3986, each **manifestURI** must also contain a hash of the content as specified in the [EIP-1123](/EIPs/EIPS/eip-1123).

### Examples

**Package Names / Release Versions**

```shell
&quot;simple-token&quot; # package name
&quot;1.0.1&quot;        # version string
```

**Release IDs**

Implementations are free to choose any scheme for generating a **releaseId**. A common approach would be to hash the strings together as below:

```solidity
// Hashes package name and a release version string
function generateReleaseId(string packageName, string version)
  public
  view
  returns (bytes32 releaseId)
  {
    return keccak256(abi.encodePacked(packageName, version));
  }
```
Implementations **must** expose this id generation logic as part of their public `read` API so
tooling can easily map a string based release query to the registry&apos;s unique identifier for that release.

**Manifest URIs**

Any IPFS or Swarm URI meets the definition of **manifestURI**.

Another example is content on GitHub addressed by its SHA-1 hash. The Base64 encoded content at this hash can be obtained by running:
```shell
$ curl https://api.github.com/repos/:owner/:repo/git/blobs/:file_sha

# Example
$ curl https://api.github.com/repos/rstallman/hello/git/blobs/ce013625030ba8dba906f756967f9e9ca394464a
```

The string &quot;hello&quot; can have its GitHub SHA-1 hash independently verified by comparing it to the output of:
```shell
$ printf &quot;blob 6\000hello\n&quot; | sha1sum
&gt; ce013625030ba8dba906f756967f9e9ca394464a
```

### Write API Specification
The write API consists of a single method, `release`. It passes the registry the package name, a
version identifier for the release, and a URI specifying the location of a manifest which
details the contents of the release.
```solidity
function release(string packageName, string version, string manifestURI) public
  returns (bytes32 releaseId);
```

### Events

#### VersionRelease
MUST be triggered when `release` is successfully called.

```solidity
event VersionRelease(string packageName, string version, string manifestURI)
```

### Read API Specification

The read API consists of a set of methods that allows tooling to extract all consumable data from a registry.

```solidity
// Retrieves a slice of the list of all unique package identifiers in a registry.
// `offset` and `limit` enable paginated responses / retrieval of the complete set.  (See note below)
function getAllPackageIds(uint offset, uint limit) public view
  returns (
    bytes32[] packageIds,
    uint pointer
  );

// Retrieves the unique string `name` associated with a package&apos;s id.
function getPackageName(bytes32 packageId) public view returns (string packageName);

// Retrieves the registry&apos;s unique identifier for an existing release of a package.
function getReleaseId(string packageName, string version) public view returns (bytes32 releaseId);

// Retrieves a slice of the list of all release ids for a package.
// `offset` and `limit` enable paginated responses / retrieval of the complete set. (See note below)
function getAllReleaseIds(string packageName, uint offset, uint limit) public view
  returns (
    bytes32[] releaseIds,
    uint pointer
  );

// Retrieves package name, release version and URI location data for a release id.
function getReleaseData(bytes32 releaseId) public view
  returns (
    string packageName,
    string version,
    string manifestURI
  );

// Retrieves the release id a registry *would* generate for a package name and version pair
// when executing a release.
function generateReleaseId(string packageName, string version)
  public
  view
  returns (bytes32 releaseId);

// Returns the total number of unique packages in a registry.
function numPackageIds() public view returns (uint totalCount);

// Returns the total number of unique releases belonging to the given packageName in a registry.
function numReleaseIds(string packageName) public view returns (uint totalCount);
```
**Pagination**

`getAllPackageIds` and `getAllReleaseIds` support paginated requests because it&apos;s possible that the return values for these methods could become quite large. The methods should return a `pointer` that points to the next available item in a list of all items such that a caller can use it to pick up from where the previous request left off.  (See [here](https://mixmax.com/blog/api-paging-built-the-right-way) for a discussion of the merits and demerits of various pagination strategies.) The `limit` parameter defines the maximum number of items a registry should return per request.

## Rationale
The proposal hopes to accomplish the following:

+ Define the smallest set of inputs necessary to allow registries to map package names to a set of
release versions while allowing them to use any versioning schema they choose.
+ Provide the minimum set of getter methods needed to retrieve package data from a registry so that registry aggregators can read all of their data.
+ Define a standard query that synthesizes a release identifier from a package name and version pair so that tooling can resolve specific package version requests without needing to query a registry about all of a package&apos;s releases.

Registries may offer more complex `read` APIs that manage requests for packages within a semver range or at `latest` etc. This EIP is agnostic about how tooling or registries might implement these. It recommends that registries implement [EIP-165](/EIPs/EIPS/eip-165) and avail themselves of resources to publish more complex interfaces such as [EIP-926](/EIPs/EIPS/eip-926).

## Backwards Compatibility
No existing standard exists for package registries. The package registry currently deployed by EthPM would not comply with the standard since it implements only one of the method signatures described in the specification.

## Implementation
A reference implementation of this proposal is in active development at the EthPM organization on GitHub [here](https://github.com/ethpm/escape-truffle).

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 13 Aug 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1319</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1319</guid>
      </item>
    
      <item>
        <title>WalletConnect URI Format</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/wallet-connect-eip/850</comments>
        
        <description>## Abstract

This standard defines how the data to connect some application and a wallet can be encoded with a URI. This URI can then be shown either as a QR code or as a link.

## Specification

### Syntax

WalletConnect request URI with the following parameters:

    request       = &quot;wc&quot; &quot;:&quot; topic [ &quot;@&quot; version ][ &quot;?&quot; parameters ]
    topic         = STRING
    version       = 1*DIGIT
    parameters    = parameter *( &quot;&amp;&quot; parameter )
    parameter     = key &quot;=&quot; value
    key           = STRING
    value         = STRING

### Semantics

Required parameters are dependent on the WalletConnect protocol version:

For WalletConnect v1.0 protocol (`version`=`1`) the parameters are:

- `key` - symmetric key used for encryption
- `bridge` - url of the bridge server for relaying messages

For WalletConnect v2.0 protocol (`version`=`2`) the parameters are:

- `symKey` - symmetric key used for encrypting messages over relay
- `methods` - jsonrpc methods supported for pairing topic
- `relay-protocol` - transport protocol for relaying messages
- `relay-data` - (optional) transport data for relaying messages
- `expiryTimestamp` - (optional) unix epoch in seconds when pairing expires

### Example

```
# 1.0
wc:8a5e5bdc-a0e4-4702-ba63-8f1a5655744f@1?bridge=https%3A%2F%2Fbridge.walletconnect.org&amp;key=41791102999c339c844880b23950704cc43aa840f3739e365323cda4dfa89e7a

# 2.0
wc:7f6e504bfad60b485450578e05678ed3e8e8c4751d3c6160be17160d63ec90f9@2?relay-protocol=irn&amp;symKey=587d5484ce2a2a6ee3ba1962fdd7e8588e06200c46823bd18fbd67def96ad303&amp;methods=[wc_sessionPropose],[wc_authRequest,wc_authBatchRequest]&quot;&amp;expiryTimestamp=1705934757
```

## Rationale

This proposal moves away from the JSON format used in the alpha version of the WalletConnect protocol because it suffered from very inefficient parsing of the intent of the QR code, thereby making it easier to create better QR code parsers APIs for wallets to implement. Also by using a URI instead of JSON inside the QR-Code the Android Intent system can be leveraged.

## Backwards Compatibility

Versioning is required as part of the syntax for this URI specification to allow the WalletConnect protocol to evolve and allow backwards-compatibility whenever a new version is introduced.

## Security Considerations

URIs should be shared between user devices or applications and no sensitive data is shared within the URI that could compromise the communication or would allow control of the user&apos;s private keys.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 15 Aug 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1328</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1328</guid>
      </item>
    
      <item>
        <title>Subscriptions on the blockchain</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-1337-subscriptions-on-the-blockchain/4422</comments>
        
        <description>## Simple Summary
Monthly subscriptions are a key monetization channel for legacy web, and arguably they are the most healthy monetization channel for businesses on the legacy web (especially when compared to ad/surveillance) based models.  They are arguably more healthy than a token based economic system (depending upon the vesting model of the ICO) because

##### For a user:
 * you don&apos;t have to read a complex whitepaper to use a dapps utility (as opposed to utility tokens)
* you don&apos;t have to understand the founder&apos;s vesting schedules
* you can cancel anytime

##### For a Service Provider:
* since you know your subscriber numbers, churn numbers, conversion rate, you get consistent cash flow, and accurate projections
* you get to focus on making your customers happy 
* enables you to remove speculators from your ecosystem

For these reasons, we think it&apos;s imperative to create a standard way to do &apos;subscriptions&apos; on Ethereum.

## Abstract
To enable replay-able transactions users sign a concatenated bytes hash that is composed of the input data needed to execute the transaction. This data is stored off chain by the recipient of the payment and is transmitted to the customers smart contract for execution alongside a provided signature.

## Motivation
Recurring payments are the bedrock of SaSS and countless other businesses, a robust specification for defining this interaction will enable a broad spectrum of revenue generation and business models.

## Specification
#### Enum Contract

EIP-1337 Contracts should be compiled with a contract that references all the enumerations that are required for operation

```SOLIDITY
/// @title Enum - Collection of enums
/// Original concept from Richard Meissner - &lt;richard@gnosis.pm&gt; Gnosis safe contracts
contract Enum {
    enum Operation {
        Call,
        DelegateCall,
        Create,
        ERC20, 
        ERC20Approve
    }
    enum SubscriptionStatus {
        ACTIVE,
        PAUSED,
        CANCELLED,
        EXPIRED
    }
    
    enum Period {
        INIT,
        DAY,
        WEEK,
        MONTH
    }
}
```

#### EIP-165

EIP-1337 compliant contracts support EIP-165 announcing what interfaces they support 

```SOLIDITY
interface ERC165 {
  /**
   * @notice Query if a contract implements an interface
   * @param interfaceID The interface identifier, as specified in ERC-165
   * @dev Interface identification is specified in ERC-165. This function
   * uses less than 30,000 gas.
   * @return `true` if the contract implements `interfaceID` and
   * `interfaceID` is not 0xffffffff, `false` otherwise
   **/
  function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
```

#### Public View Functions

###### isValidSubscription
```SOLIDITY

/** @dev Checks if the subscription is valid.
  * @param bytes subscriptionHash is the identifier of the customer&apos;s subscription with its relevant details.
  * @return success is the result of whether the subscription is valid or not.
  **/

function isValidSubscription(
            uint256 subscriptionHash
        ) 
        public 
        view 
        returns (
            bool success
        )
```
###### getSubscriptionStatus
```SOLIDITY

/** @dev returns the value of the subscription
  * @param bytes subscriptionHash is the identifier of the customer&apos;s subscription with its relevant details.
  * @return status is the enumerated status of the current subscription, 0 expired, 1 active, 2 paused, 3 cancelled
  **/
function getSubscriptionStatus(
        uint256 subscriptionHash
    )
    public 
    view 
    returns (
        uint256 status, 
        uint256 nextWithdraw
    )
```

###### getSubscriptionHash

```SOLIDITY
/** @dev returns the hash of cocatenated inputs to the address of the contract holding the logic.,
  * the owner would sign this hash and then provide it to the party for execution at a later date,
  * this could be viewed like a cheque, with the exception that unless you specifically
  * capture the hash on chain a valid signature will be executable at a later date, capturing the hash lets you modify the status to cancel or expire it.
  * @param address recipient the address of the person who is getting the funds.
  * @param uint256 value the value of the transaction
  * @param bytes data the data the user is agreeing to
  * @param uint256 txGas the cost of executing one of these transactions in gas(probably safe to pad this)
  * @param uint256 dataGas the cost of executing the data portion of the transaction(delegate calls etc)
  * @param uint 256 gasPrice the agreed upon gas cost of Execution of this subscription(cost incurment is up to implementation, ie, sender or receiver)
  * @param address gasToken address of the token in which gas will be compensated by, address(0) is ETH, only works in the case of an enscrow implementation)
  * @param bytes meta dynamic bytes array with 4 slots, 2 required, 2 optional // address refundAddress / uint256 period / uint256 offChainID / uint256 expiration (uinx timestamp)
  * @return bytes32, return the hash input arguments concatenated to the address of the contract that holds the logic.
  **/
function getSubscriptionHash(
        address recipient,
        uint256 value,
        bytes data,
        Enum.Operation operation,
        uint256 txGas,
        uint256 dataGas,
        uint256 gasPrice,
        address gasToken,
        bytes meta
    )
    public
    view
    returns (
        bytes32 subscriptionHash
    )
```


###### getModifyStatusHash

```SOLIDITY
/** @dev returns the hash of concatenated inputs that the owners user would sign with their public keys
  * @param address recipient the address of the person who is getting the funds.
  * @param uint256 value the value of the transaction
  * @return bytes32 returns the hash of concatenated inputs with the address of the contract holding the subscription hash
  **/
function getModifyStatusHash(
        bytes32 subscriptionHash
        Enum.SubscriptionStatus status
    )
    public
    view
    returns (
        bytes32 modifyStatusHash
    )
```
#### Public Functions

###### modifyStatus
```SOLIDITY

/** @dev modifys the current subscription status
  * @param uint256 subscriptionHash is the identifier of the customer&apos;s subscription with its relevant details.
  * @param Enum.SubscriptionStatus status the new status of the subscription
  * @param bytes signatures of the requested method being called
  * @return success is the result of the subscription being paused
  **/
function modifyStatus(
        uint256 subscriptionHash, 
        Enum.SubscriptionStatus status, 
        bytes signatures
    ) 
    public 
    returns (
        bool success
    )
```

###### executeSubscription
```SOLIDITY

/** @dev returns the hash of cocatenated inputs to the address of the contract holding the logic.,
  * the owner would sign this hash and then provide it to the party for execution at a later date,
  * this could be viewed like a cheque, with the exception that unless you specifically
  * capture the hash on chain a valid signature will be executable at a later date, capturing the hash lets you modify the status to cancel or expire it.
  * @param address recipient the address of the person who is getting the funds.
  * @param uint256 value the value of the transaction
  * @param bytes data the data the user is agreeing to
  * @param uint256 txGas the cost of executing one of these transactions in gas(probably safe to pad this)
  * @param uint256 dataGas the cost of executing the data portion of the transaction(delegate calls etc)
  * @param uint 256 gasPrice the agreed upon gas cost of Execution of this subscription(cost incurment is up to implementation, ie, sender or receiver)
  * @param address gasToken address of the token in which gas will be compensated by, address(0) is ETH, only works in the case of an enscrow implementation)
  * @param bytes meta dynamic bytes array with 4 slots, 2 required, 2 optional // address refundAddress / uint256 period / uint256 offChainID / uint256 expiration (uinx timestamp)
  * @param bytes signatures signatures concatenated that have signed the inputs as proof of valid execution
  * @return bool success something to note that a failed execution will still pay the issuer of the transaction for their gas costs.
  **/
function executeSubscription(
        address to,
        uint256 value,
        bytes data,
        Enum.Operation operation,
        uint256 txGas,
        uint256 dataGas,
        uint256 gasPrice,
        address gasToken,
        bytes meta,
        bytes signatures
    )
    public 
    returns (
        bool success
    )
```

## Rationale
Merchants who accept credit-cards do so by storing a token that is retrieved from a third party processor(stripe, paypal, etc), this token is used to grant access to pull payment from the cx&apos;s credit card provider and move funds to the merchant account. 
Having users sign input data acts in a similliar fashion and enables that merchant to store the signature of the concatenated bytes hash and input data used to generate the hash and pass them off to the contract holding the subscription logic, thus enabling a workflow that is similliar to what exists in the present day legacy web.

## Backwards Compatibility
N/A

## Test Cases
TBD

## Implementation
TBD

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 01 Aug 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1337</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1337</guid>
      </item>
    
      <item>
        <title>ChainID opcode</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/add-chain-id-opcode-for-replay-protection-when-handling-signed-messages-in-contracts/1131</comments>
        
        <description>## Abstract
This EIP adds an opcode that returns the current chain&apos;s EIP-155 unique identifier.

## Motivation
[EIP-155](/EIPs/EIPS/eip-155) proposes to use the chain ID to prevent replay attacks between different chains. It would be a great benefit to have the same possibility inside smart contracts when handling signatures, especially for Layer 2 signature schemes using [EIP-712](/EIPs/EIPS/eip-712).

## Specification
Adds a new opcode `CHAINID` at 0x46, which uses 0 stack arguments. It pushes the current chain ID onto the stack. Chain ID is a 256-bit value. The operation costs `G_base` to execute.

The value of the current chain ID is obtained from the chain ID configuration, which should match the EIP-155 unique identifier a client will accept from incoming transactions. Please note that per EIP-155, it is not *required* that a transaction have an EIP-155 unique identifier, but in that scenario this opcode will still return the configured chain ID and not a default.

## Rationale
The current approach proposed by EIP-712 is to specify the chain ID at compile time. Using this approach will result in problems after a hardfork, as well as human error that may lead to loss of funds or replay attacks on signed messages.
By adding the proposed opcode it will be possible to access the current chain ID and validate signatures based on that.

Currently, there is no specification for how chain ID is set for a particular network, relying on choices made manually by the client implementers and the chain community. There is a potential scenario where, during a &quot;contentious split&quot; over a divisive issue, a community using a particular value of chain ID will make a decision to split into two such chains. When this scenario occurs, it will be unsafe to maintain chain ID to the same value on both chains, as chain ID is used for replay protection for in-protocol transactions (per EIP-155), as well as for L2 and &quot;meta-transaction&quot; use cases (per EIP-712 as enabled by this proposal). There are two potential resolutions in this scenario under the current process: 1) one chain decides to modify their value of chain ID (while the other keeps it), or 2) both chains decide to modify their value of chain ID.

In order to mitigate this situation, users of the proposed `CHAINID` opcode **must** ensure that their application can handle a potential update to the value of chain ID during their usage of their application in case this does occur, if required for the continued use of the application. A Trustless Oracle that logs the timestamp when a change is made to chain ID can be implemented either as an application-level feature inside the application contract system, or referenced as a globally standard contract. Failure to provide a mitigation for this scenario could lead to a sudden loss of legitimacy of previously signed off-chain messages, which could be an issue during settlement periods and other longer-term verification events for these types of messages. Not all applications of this opcode may need mitigations to handle this scenario, but developers should provide reasoning on a case-by-case basis.

One example of a scenario where it would not make sense to leverage a global oracle is with the Plasma L2 paradigm. In the Plasma paradigm, an operator or group of operators submit blocks from the L2 network to the base chain (in this case Ethereum) summarizing transactions that have occurred on that chain. The submission of these blocks may not perfectly align with major events on the mainchain, such as a split causing an update of chain ID, which may cause a significant insecurity in the protocol if chain ID is utilized in signing messages. If the operators are not allowed to control the update of chain ID they will not be able to perfectly synchronize the update with their block submissions, and certain past transactions may be rejected because they do not align with the update. This is one example of the unintended consequences of trying to specify too much of the behavior of chain ID during a contentious split, and why having a simple opcode for access is most optimal, versus a more complicated precompile or contract.

This proposed opcode would be the simplest possible way to implement this functionality, and allows developers the flexibility to implement their own global or local handling of chain ID changes, if required.

## Backwards Compatibility
This EIP is fully backwards compatible with all chains which implement EIP-155 chain ID domain separator for transaction signing.

## References
This was previously suggested as part of [EIP-901](https://github.com/ethereum/EIPs/issues/901).

## Test Cases
Test Cases added to [ethereum/tests](https://github.com/ethereum/tests/pull/627)

## Implementation
A reference implementation for the Trinity Python client is [here](https://github.com/ethereum/py-evm/pull/1803).

An example implementation of a trustless chain ID oracle was implemented [here](https://github.com/fubuloubu/chain-id-oracle/blob/master/ChainIdOracle.vy).

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 22 Aug 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1344</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1344</guid>
      </item>
    
      <item>
        <title>Specify restricted address range for precompiles/system contracts</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-1352-specify-restricted-address-range-for-precompiles-system-contracts/1151</comments>
        
        <description>## Simple Summary
Specify an Ethereum address range occupied by precompiles and future system contracts. Regular accounts and contracts cannot obtain such an address.

## Abstract
The address range between 0x0000000000000000000000000000000000000000 and 0x000000000000000000000000000000000000ffff is reserved for precompiles and system contracts.

## Motivation
This will simplify certain future features where unless this is implemented, several exceptions must be specified.

## Specification
The address range between 0x0000000000000000000000000000000000000000 and 0x000000000000000000000000000000000000ffff is reserved for precompiles and system contracts.

Due to the extremely low probability (and lack of adequate testing possibilities) no explicit checks should be added to ensure that external transaction signing or
the invoking of the `CREATE` instruction can result in a precompile address.

## Rationale
N/A

## Backwards Compatibility
No contracts on the main network have been created at the specified addresses. As a result it should pose no backwards compatibility problems.

## Test Cases
N/A

## Implementation
N/A

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 27 Jul 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1352</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1352</guid>
      </item>
    
      <item>
        <title>Ethash 1a</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-1355-ethash-1a/1167</comments>
        
        <description>## Motivation

Provide minimal set of changes to Ethash algorithm to hinder and delay the adoption of ASIC based mining.

## Specification

1. Define hash function `fnv1a()` as
   ```python
   def fnv1a(v1, v2):
       return ((v1 ^ v2) * FNV1A_PRIME) % 2**32
   ```
   where `FNV1A_PRIME` is 16777499 or 16777639.
2. Change the hash function that determines the DAG item index in Ethash algorithm from `fnv()` to new `fnv1a()`.
   In [Main Loop](https://github.com/ethereum/eth-wiki/blob/master/concepts/ethash/ethash.md#main-loop) change
   ```python
   p = fnv(i ^ s[0], mix[i % w]) % (n // mixhashes) * mixhashes
   ```
   to
   ```python
   p = fnv1a(i ^ s[0], mix[i % w]) % (n // mixhashes) * mixhashes
   ```

## Rationale

The usual argument for decentralization and network security.

Unless programmable, an ASIC is hardwired to perform sequential operations in a given order. fnv1a changes the order in which an exclusive-or and a multiply are applied, effectively disabling the current wave of ASICS. A second objective is minimize ethash changes to be the least disruptive, to facilitate rapid development, and to lower the analysis and test requirements. Minimizing changes to ethash reduces risk associated with updating all affected network components, and also reduces the risk of detuning existing GPUs. It&apos;s expected that this specific change would have no effect on existing GPU performance.

Changing fnv to fnv1a has no cryptographic implications. It is merely an efficient hash function with good dispersion characteristics used to scramble DAG indexing. We remain focused on risk mitigation by reducing the need for rigorous cryptographic analysis.


### FNV Primes

The 16777639 satisfies all requirements from [Wikipedia](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV_prime).

The 16777499 is preferred by FNV authors but not used in the reference FNV implementation because of historical reasons.
See [A few remarks on FNV primes](http://www.isthe.com/chongo/tech/comp/fnv/index.html#fnv-prime).

## Copyright

This work is licensed under a [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-nc-sa/4.0/).
</description>
        <pubDate>Sun, 26 Aug 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1355</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1355</guid>
      </item>
    
      <item>
        <title>Payable Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/eips/issues/1363</comments>
        
        <description>## Simple Summary
Defines a token interface for [ERC-20](/EIPs/EIPS/eip-20) tokens that supports executing recipient code after `transfer` or `transferFrom`, or spender code after `approve`.

## Abstract
Standard functions a token contract and contracts working with tokens can implement to make a token Payable.

`transferAndCall` and `transferFromAndCall` will call an `onTransferReceived` on a `ERC1363Receiver` contract.  

`approveAndCall` will call an `onApprovalReceived` on a `ERC1363Spender` contract.

## Motivation
There is no way to execute code after a [ERC-20](/EIPs/EIPS/eip-20) transfer or approval (i.e. making a payment), so to make an action it is required to send another transaction and pay GAS twice.

This proposal wants to make token payments easier and working without the use of any other listener. It allows to make a callback after a transfer or approval in a single transaction.

There are many proposed uses of Ethereum smart contracts that can accept [ERC-20](/EIPs/EIPS/eip-20) payments. 

Examples could be 
* to create a token payable crowdsale
* selling services for tokens 
* paying invoices
* making subscriptions

For these reasons it was named as **&quot;Payable Token&quot;**.

Anyway you can use it for specific utilities or for any other purposes who require the execution of a callback after a transfer or approval received.

This proposal has been inspired by the [ERC-721](/EIPs/EIPS/eip-721) `onERC721Received` and `ERC721TokenReceiver` behaviours. 

## Specification
Implementing contracts **MUST** implement the [ERC-1363](/EIPs/EIPS/eip-1363) interface as well as the [ERC-20](/EIPs/EIPS/eip-20) and [ERC-165](/EIPs/EIPS/eip-165) interfaces.

```solidity
pragma solidity ^0.8.0;

interface ERC1363 /* is ERC20, ERC165 */ {
  /*
   * Note: the ERC-165 identifier for this interface is 0xb0202a11.
   * 0xb0202a11 ===
   *   bytes4(keccak256(&apos;transferAndCall(address,uint256)&apos;)) ^
   *   bytes4(keccak256(&apos;transferAndCall(address,uint256,bytes)&apos;)) ^
   *   bytes4(keccak256(&apos;transferFromAndCall(address,address,uint256)&apos;)) ^
   *   bytes4(keccak256(&apos;transferFromAndCall(address,address,uint256,bytes)&apos;)) ^
   *   bytes4(keccak256(&apos;approveAndCall(address,uint256)&apos;)) ^
   *   bytes4(keccak256(&apos;approveAndCall(address,uint256,bytes)&apos;))
   */

  /**
   * @notice Transfer tokens from `msg.sender` to another address and then call `onTransferReceived` on receiver
   * @param to address The address which you want to transfer to
   * @param value uint256 The amount of tokens to be transferred
   * @return true unless throwing
   */
  function transferAndCall(address to, uint256 value) external returns (bool);

  /**
   * @notice Transfer tokens from `msg.sender` to another address and then call `onTransferReceived` on receiver
   * @param to address The address which you want to transfer to
   * @param value uint256 The amount of tokens to be transferred
   * @param data bytes Additional data with no specified format, sent in call to `to`
   * @return true unless throwing
   */
  function transferAndCall(address to, uint256 value, bytes memory data) external returns (bool);

  /**
   * @notice Transfer tokens from one address to another and then call `onTransferReceived` on receiver
   * @param from address The address which you want to send tokens from
   * @param to address The address which you want to transfer to
   * @param value uint256 The amount of tokens to be transferred
   * @return true unless throwing
   */
  function transferFromAndCall(address from, address to, uint256 value) external returns (bool);


  /**
   * @notice Transfer tokens from one address to another and then call `onTransferReceived` on receiver
   * @param from address The address which you want to send tokens from
   * @param to address The address which you want to transfer to
   * @param value uint256 The amount of tokens to be transferred
   * @param data bytes Additional data with no specified format, sent in call to `to`
   * @return true unless throwing
   */
  function transferFromAndCall(address from, address to, uint256 value, bytes memory data) external returns (bool);

  /**
   * @notice Approve the passed address to spend the specified amount of tokens on behalf of msg.sender
   * and then call `onApprovalReceived` on spender.
   * @param spender address The address which will spend the funds
   * @param value uint256 The amount of tokens to be spent
   * @return true unless throwing
   */
  function approveAndCall(address spender, uint256 value) external returns (bool);

  /**
   * @notice Approve the passed address to spend the specified amount of tokens on behalf of msg.sender
   * and then call `onApprovalReceived` on spender.
   * @param spender address The address which will spend the funds
   * @param value uint256 The amount of tokens to be spent
   * @param data bytes Additional data with no specified format, sent in call to `spender`
   * @return true unless throwing
   */
  function approveAndCall(address spender, uint256 value, bytes memory data) external returns (bool);
}

interface ERC20 {
  function totalSupply() external view returns (uint256);
  function balanceOf(address account) external view returns (uint256);
  function transfer(address recipient, uint256 amount) external returns (bool);
  function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
  function allowance(address owner, address spender) external view returns (uint256);
  function approve(address spender, uint256 amount) external returns (bool);
  event Transfer(address indexed from, address indexed to, uint256 value);
  event Approval(address indexed owner, address indexed spender, uint256 value);
}

interface ERC165 {
  function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
```

A contract that wants to accept token payments via `transferAndCall` or `transferFromAndCall` **MUST** implement the following interface:

```solidity
/**
 * @title ERC1363Receiver interface
 * @dev Interface for any contract that wants to support `transferAndCall` or `transferFromAndCall`
 *  from ERC1363 token contracts.
 */
interface ERC1363Receiver {
  /*
   * Note: the ERC-165 identifier for this interface is 0x88a7ca5c.
   * 0x88a7ca5c === bytes4(keccak256(&quot;onTransferReceived(address,address,uint256,bytes)&quot;))
   */

  /**
   * @notice Handle the receipt of ERC1363 tokens
   * @dev Any ERC1363 smart contract calls this function on the recipient
   * after a `transfer` or a `transferFrom`. This function MAY throw to revert and reject the
   * transfer. Return of other than the magic value MUST result in the
   * transaction being reverted.
   * Note: the token contract address is always the message sender.
   * @param operator address The address which called `transferAndCall` or `transferFromAndCall` function
   * @param from address The address which are token transferred from
   * @param value uint256 The amount of tokens transferred
   * @param data bytes Additional data with no specified format
   * @return `bytes4(keccak256(&quot;onTransferReceived(address,address,uint256,bytes)&quot;))`
   *  unless throwing
   */
  function onTransferReceived(address operator, address from, uint256 value, bytes memory data) external returns (bytes4);
}
``` 

A contract that wants to accept token payments via `approveAndCall` **MUST** implement the following interface:

```solidity
/**
 * @title ERC1363Spender interface
 * @dev Interface for any contract that wants to support `approveAndCall`
 *  from ERC1363 token contracts.
 */
interface ERC1363Spender {
  /*
   * Note: the ERC-165 identifier for this interface is 0x7b04a2d0.
   * 0x7b04a2d0 === bytes4(keccak256(&quot;onApprovalReceived(address,uint256,bytes)&quot;))
   */

  /**
   * @notice Handle the approval of ERC1363 tokens
   * @dev Any ERC1363 smart contract calls this function on the recipient
   * after an `approve`. This function MAY throw to revert and reject the
   * approval. Return of other than the magic value MUST result in the
   * transaction being reverted.
   * Note: the token contract address is always the message sender.
   * @param owner address The address which called `approveAndCall` function
   * @param value uint256 The amount of tokens to be spent
   * @param data bytes Additional data with no specified format
   * @return `bytes4(keccak256(&quot;onApprovalReceived(address,uint256,bytes)&quot;))`
   *  unless throwing
   */
  function onApprovalReceived(address owner, uint256 value, bytes memory data) external returns (bytes4);
}
``` 

## Rationale
The choice to use `transferAndCall`, `transferFromAndCall` and `approveAndCall` derives from the [ERC-20](/EIPs/EIPS/eip-20) naming. They want to highlight that they have the same behaviours of `transfer`, `transferFrom` and `approve` with the addition of a callback on receiver or spender.

## Backwards Compatibility
This proposal has been inspired also by [ERC-223](https://github.com/ethereum/EIPs/issues/223) and [ERC-677](https://github.com/ethereum/EIPs/issues/677) but it uses the [ERC-721](/EIPs/EIPS/eip-721) approach, so it doesn&apos;t override the [ERC-20](/EIPs/EIPS/eip-20) `transfer` and `transferFrom` methods and defines the interfaces IDs to be implemented maintaining the [ERC-20](/EIPs/EIPS/eip-20) backwards compatibility.  

## Security Considerations
The `approveAndCall` and `transferFromAndCall` methods can be affected by the same issue of the standard [ERC-20](/EIPs/EIPS/eip-20) `approve` and `transferFrom` method.
  
Changing an allowance with the `approveAndCall` methods brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering.

One possible solution to mitigate this race condition is to first reduce the spender&apos;s allowance to 0 and set the desired value afterwards ([EIP-20#issuecomment-263524729](https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729)).

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 30 Aug 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1363</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1363</guid>
      </item>
    
      <item>
        <title>Reduced gas cost for call to self</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-1380-reduced-gas-cost-for-call-to-self/1242</comments>
        
        <description>## Abstract

Reduce the gas cost for call instructions, when the goal is to run a new instance of the currently loaded contract.

## Motivation

The current gas cost of 700 for all call types (`CALL`, `DELEGATECALL`, `CALLCODE` and `STATICCALL`) does not take into account that a call to a contract itself
does not need to perform additional I/O operations, because the current contract code has already been loaded into memory.

Reducing the call-to-self gas cost would greatly benefit smart contract languages, such as Solidity and Vyper, who would then be able to utilise `CALL` instead
of `JUMP` opcodes for internal function calls. While languages can already utilise `CALL` for internal function calls, they are discouraged to do so due to the
gas costs associated with it.

Using `JUMP` comes at a considerable cost in complexity to the implementation of a smart contract language and/or compiler. The context (including stack and memory)
must be swapped in and out of the calling functions context. A desired feature is having *pure* functions, which do not modify the state of memory, and realising
them through `JUMP` requires a bigger effort from the compiler as opposed to being able to use `CALL`s.

Using call-to-self provides the guarantee that when making an internal call the function can rely on a clear reset state of memory or context, benefiting both
contract writers and contract consumers against potentially undetected edge cases were memory could poison the context of the internal function.

Because of the `JUMP` usage for internal functions a smart contract languages are also at risk of reaching the stack depth limit considerably faster, if nested
function calls with many in and/or outputs are required.

Reducing the gas cost, and thereby incentivising of using call-to-self instead of `JUMP`s for the internal function implementation will also benefit static
analyzers and tracers.

## Specification

If `block.number &gt;= FORK_BLKNUM`, then decrease the cost of `CALL`, `DELEGATECALL`, `CALLCODE` and `STATICCALL` from 700 to 40,
if and only if, the destination address of the call equals to the address of the caller.

## Rationale

EIP150 has increased the cost of these instructions from 40 to 700 to more fairly charge for loading new contracts from disk, e.g. to reflect the I/O charge more closely.
By assuming that 660 is the cost of loading a contract from disk, one can assume that the original 40 gas is a fair cost of creating a new VM instance of an already loaded contract code.

## Backwards Compatibility

This should pose no risk to backwards compatibility. Currently existing contracts should not notice the difference, just see cheaper execution.
With EIP150 contract (and language) developers had a lesson that relying on strict gas costs is not feasible as costs may change.
The impact of this EIP is even less that of EIP150 because the costs are changing downwards and not upwards.

## Test Cases

TBA

## Implementation

TBA

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 31 Aug 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1380</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1380</guid>
      </item>
    
      <item>
        <title>Attestation management contract</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1386</comments>
        
        <description>### Introduction

Very often, we will need to use Attestations like &quot;Alice lives in Australia&quot; on the blockchain; that is issued by a valid issuer off chain for privacy reasons and is revokable inside a smart contract.

An issuer can create a smart contract where he revokes multiple attestations in one go by building a bloom filter of all the hashes of the revoked attestations.

An issuer can also put the validation method in their smart contract that can be called by other smart contracts who need to validate attestations issued by them. This allows each attestor to update their attestation format separately.

### Purpose

This ERC provides an interface for attestation issuers to manage their attestation signing keys and the attestations that are issued off chain for actions such as revocation and validation.

In our draft implementation we include functions to hold cryptographic attestations, change the issuing contracts of attestations, revoke attestations and verify the authenticity of a cryptographic attestation.

### Example use cases

Let&apos;s say that our friend, Alice, wants to buy a bottle of wine to consume with her friends. She wants to do the order online and have it delivered to her home address whilst paying for it with Ether.

Alice has a cryptographic attestation from her local road and maritime services who attests to her age, date of birth, country of residence and ability to drive.

Alice is able to split up this attestation (see merkle tree attestations ERC [here](https://github.com/alpha-wallet/blockchain-attestation/blob/master/ethereum/lib/MerkleTreeAttestation.sol)) and provides only the leaf that states she is over the age of 21.

Alice goes to buy the wine through the wine vendors smart contract and feeds in the merkle tree attestation proving that she is above 21 and can thus buy the wine, whilst attaching the appropriate amount of ether to complete the purchase.

The issuer smart contract is able to validate her attestation, check that the issuer contract is valid and capable of performing such an attestation to her age. In this case it would have to be from someone like a driver&apos;s licence authority, as attestations to age from a school ID are not of a high enough capacity.

The wine vendors smart contract validates the attestation, checks the payment amount is correct and credits Alice with the wine tokens she needs to complete the sale and deliver the wine.

When the wine vendor shows up to her apartment with the wine, there is no need to prove her age again.

### Draft interface
```solidity
/* each attestation issuer should provide their own verify() for the
 * attestations they issued. There are two reasons for this. First, we
 * need to leave room for new attestation methods other than the
 * Merkle Tree format we are recommending. Second, the validity of the
 * attestation may depend on the context that only the attestor
 * knows. For example, a ticket as an attestation issued on a
 * successful redemption of an American Express credit */

contract Issuer {
  struct Attestation
    {
        bytes32[] merklePath;
        bool valid;
        uint8 v;
        bytes32 r;
        bytes32 s;
        address attestor;
        address recipient;
        bytes32 salt;
        bytes32 key;
        bytes32 val;
    }`
  /* Verify the authenticity of an attestation */
  function verify(Attestation attestation);
  function addattestorKey(address newAttestor, string capacity, uint expiry);

  /* this should call the revoke first */
  function replaceKey(address attestorToReplace, string capacity, uint expiry, address newAttestor);

  /* this revokes a single key */
  function removeKey(address attestor);

  /* if the key exists with such capacity and isn&apos;t revoked or expired */
  function validateKey(address attestor, string capacity) returns (bool);

  /* revoke an attestation by replace the bloom filter, this helps preserve privacy */
  function revokeAttestations(Bloomfilter b);

}
```

Please click [here](https://github.com/alpha-wallet/blockchain-attestation/blob/master/ethereum/example-james-squire/james-squire.sol) to see a draft implementation of this interface

### Related ERC&apos;s
#1388 #1387
</description>
        <pubDate>Sat, 08 Sep 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1386</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1386</guid>
      </item>
    
      <item>
        <title>Merkle Tree Attestations with Privacy enabled</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1387</comments>
        
        <description>### Introduction

It&apos;s often needed that an Ethereum smart contract must verify a claim (I live in Australia) attested by a valid attester.

For example, an ICO contract might require that the participant, Alice, lives in Australia before she participates. Alice&apos;s claim of residency could come from a local Justice of the Peace who could attest that &quot;Alice is a resident of Australia in NSW&quot;.

Unlike previous attempts, we assume that the attestation is signed and issued off the blockchain in a Merkle Tree format. Only a part of the Merkle tree is revealed by Alice at each use. Therefore we avoid the privacy problem often associated with issuing attestations on chain. We also assume that Alice has multiple signed Merkle Trees for the same factual claim to avoid her transactions being linkable.

## Purpose
This ERC provides an interface and reference implementation for smart contracts that need users to provide an attestation and validate it.

### Draft implementation
```solidity
contract MerkleTreeAttestationInterface {
    struct Attestation
    {
        bytes32[] merklePath;
        bool valid;
        uint8 v;
        bytes32 r;
        bytes32 s;
        address attester;
        address recipient;
        bytes32 salt;
        bytes32 key;
        bytes32 val;
    }

    function validate(Attestation attestation) public returns(bool);
}

```
### Relevant implementation examples
[Here](https://github.com/alpha-wallet/blockchain-attestation/blob/master/ethereum/lib/MerkleTreeAttestation.sol) is an example implementation of the MerkleTreeAttestationInterface
[Here](https://github.com/alpha-wallet/blockchain-attestation/blob/master/ethereum/example-james-squire/james-squire.sol) is an example service which would use such a merkle tree attestation

### Related ERC&apos;s
#1388 #1386
</description>
        <pubDate>Sat, 08 Sep 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1387</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1387</guid>
      </item>
    
      <item>
        <title>Attestation Issuers Management List</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1388</comments>
        
        <description>### Introduction

In smart contracts, we will need methods to handle cryptographic attestations to a users identifier or abilities. Let&apos;s say we have a real estate agent, KiwiRealtors, that provides an &quot;expression of interest&quot; function though a smart contract and requires the users to provide an attestation that they are a resident of New Zealand or Australia, as a legal requirement. This has actually happened in the New Zealand property market and it is the perfect example of a need to handle such attestations.

However, it is not practical for a smart contract to explicitly trust an attestation issuer. There are multiple issuers who can provide an attestation to a person&apos;s residency - a local Justice of the Peace, the land title office, local police, passport authority etc. We envision a model where the effort to manage the list of qualified issuers is practically outsourced to a list.

Anyone can publish a list of issuers. Only the most trusted and carefully maintained lists gets popular use.

### Purpose
This ERC provides a smart contract interface for anyone to manage a list of attestation issuers. A smart contract would explicitly trust a list, and therefore all attestations issued by the issuers on the list.

### Draft implementation
```solidity
    /* The purpose of this contract is to manage the list of attestation
     * issuer contracts and their capacity to fulfill requirements
     */
 contract ManagedListERC
    {
      /* a manager is the steward of a list. Only he/she/it can change the
       * list by removing/adding attestation issuers to the list.

       * An issuer in the list is represented by their contract
       * addresses, not by the attestation signing keys managed by such a
       * contract.
       */
      struct List
      {
	      string name;
	      string description; // short description of what the list entails
	      string capacity; // serves as a filter for the attestation signing keys
	  /* if a smart contract specifies a list, only attestation issued
	   * by issuers on that list is accepted. Furthermore, if that
	   * list has a non-empty capacity, only attestations signed by a
	   * signing key with that capacity is accepted. */

	    address[] issuerContracts; // all these addresses are contracts, no signing capacity
	    uint expiry;
      }

      // find which list the sender is managing, then add an issuer to it
      function addIssuer(address issuerContractAddress) public;

      //return false if the list identified by the sender doesn&apos;t have this issuer in the list
      function removeIssuer(address issuerContractAddress, List listToRemoveIssuerFrom) public returns(bool);

      /* called by services, e.g. Kiwi Properties or James Squire */
      /* loop through all issuer&apos;s contract and execute validateKey() on
       * every one of them in the hope of getting a hit, return the
       * contract address of the first hit. Note that there is an attack
       * method for one issuer to claim to own the key of another which
       * is mitigated by later design. */
       //loop through the issuers array, calling validate on the signingKeyOfAttestation
      function getIssuerCorrespondingToAttestationKey(bytes32 list_id, address signingKeyOfAttestation) public returns (address);

       /* for simplicity we use sender&apos;s address as the list ID,
	 * accepting these consequences: a) if one user wish to maintain
	 * several lists with different capacity, he or she must use a
	 * different sender address for each. b) if the user replaced the
	 * sender&apos;s key, either because he or she suspects the key is
	 * compromised or that it is lost and reset through special means,
	 * then the list is still identified by the first sender&apos;s
	 * address.
      */

      function createList(List list) public;

      /* replace list manager&apos;s key with the new key */
      function replaceListIndex(List list, address manager) public returns(bool);

    }
```

Click [here](https://github.com/alpha-wallet/blockchain-attestation/blob/master/ethereum/trustlist/ManagedList.sol) to see an example implementation of this ERC

### Related ERC&apos;s
#1387 #1386
</description>
        <pubDate>Sat, 08 Sep 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1388</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1388</guid>
      </item>
    
      <item>
        <title>Poll Standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1417</comments>
        
        <description>## Note to Readers

1. We have created a couple of implementations of polls for varied use cases.
   Please refer to them [here](https://github.com/chaitanyapotti/Voting)

## Simple Summary

A standard interface for Polls to be used with EIP-1261 (MVT).

## Abstract

The following standard allows for the implementation of a standard API for polls to be used with MVTs (refer [EIP-1261](/EIPs/EIPS/eip-1261)). The standard provides basic functionality to vote, unvote, tally votes, get voter turnout, and a lot more. The poll standard attempts to modularize blockchain voting by breaking down a poll into 4 crucial building blocks: voterbase qualification, vote weight calculation, vote consequences, and vote tallying. By creating a common interface for polls that have different kinds of building blocks, the poll standard makes it possible to make interactive front end applications which can seamlessly get data from a poll contract in order to bring transparency into consensus and decision making on the blockchain.

We considered the usage of polls with MVTs because MVTs serve as a permissioning mechanism. The manual permissioning of polls allows for vote weightage functions to take up several shapes and forms. Hence the voterbase function applies several logical checks on the vote sender to confirm that they are member(see EIP 1261) of a certain entity or combination of entities. For the specification of the nature of voting, we define the vote weight function. The vote weight function decides how much of vote share each voter will receive and this can be based on several criteria, some of which are listed below in this article. There are certain kinds of polls that enforce certain consequences on the voter, for example a poll may require a voter to lock in a certain amount of tokens, or require the voter to pay a small fee. These on-chain consequences can be coded into the consequence module of the poll standard. Finally, the last module is where the votes are added. A ballot for each candidate is updated whenever relevant, depending on the vote value, and the corresponding NoV count(number of voters). This module is common for most polls, and is the most straightforward. Polls may be time bound, ie. having a finish time, after which no votes are recorded, or be unbound, such that there is no finish time. The following are some examples of specific polls which leverage the flexibility of the poll standard, and it is possible to come up with several others:

- Plurality Voting: The simplest form of voting is when you want all eligible voters to have one vote per person. This is the simplest to code, as the vote weight is 1, and there is no vote consequence. The only relevant module here is the voterbase, which can be categorized by one or more MVT contracts.
- Token proportional voting: This kind of a poll is actually possible without the use of a voterbase function, because the vote weight function having token proportionality automatically rules out addresses which don&apos;t hold the appropriate ERC - 20/ ERC - 777 token. However the voterbase function may be leveraged to further permission the system and give voting rights only to a fixed subset of token holders.
- Capped Token Proportional Voting: This is a modified version of the previous example, where each voter is given proportional vote share only until a certain limit of token ownership. After exceeding that limit, holding more coins does not add more vote share. This format leverages the voterbase module effectively, disallowing people from spreading their coins across multiple addresses by allowing the admin to control which addresses can vote.
- Delegated Voting: Certain polls may allow voters to delegate their votes to other voters. This is known as delegated voting or liquid democracy. For such a poll, a complicated vote weight function is needed, and a data structure concerning the voterbase is also required. A consequence of voting here would be that a user cannot delegate, and a consequence of delegating is that a user cannot vote. Sample implementation of polls contains an example of this vote scheme.
- Karma Based Voting: A certain form of poll may be based on weightage from digital respect. This digital respect would be like a simple upvote from one member of voterbase to another. A mapping of mappings along with an appropriate vote weight function can serve this purpose. Sample implementation has an example.
- Quadratic voting: A system where each vote is associated with a fee, and the fee is proportional to the square of the vote weight that the voter wants. This can be designed by applying a vote weight based on the transaction message, and then charging a fee in the vote consequence module.

The poll standard is intended to be a smart contract standard that makes poll deployment flexible, transparent and accessible.

## Motivation

A standard interface allows any user or applications to work with any Poll contract on Ethereum. We provide for simple ERC-1417 smart contracts. Additional applications are discussed below.

This standard is inspired by the lack of governance tools in the blockchain space. Whenever there is a consensus collection exercise, someone goes ahead and deploys some kind of poll, and there is no standard software for accessing the data on the poll. For an end user who is not a developer, this is a real problem. The poll, which might be fully transparent, appears to be completely opaque to a common user who does not understand blockchain. In order for developers to build applications for interacting with and accessing poll data, and for poll deployers to have ready application level support, there must be a standardization of poll interfaces.

This realization happened while conducting market research on DAICOs. The first ever DAICO, Abyss, had far from optimal user experience, and abysmal transparency. Since then, we have been working on a poll standard. During the process, we came across EIP 1202, the voting standard, and found that the discussion there had already diverged from our thoughts to an extent that it made sense to publish a separate proposal altogether. Some of the benefits brought by the poll standard - EIP 1417 aims to offer some additional benefits.

1. Modularization: EIP 1417 modularizes the code present in the poll standard into 4 major building blocks based on functionality. These are: voterbase logic, vote weight calculation, vote consequence processing, and tallying module. This makes it easy for developers to change parts of a poll without disrupting other parts, and also helps people understand better, code written in the same format by other people.

2. Permissioning: Permissioning is an important aspect of polls, and is missing in most poll proposals so far, on the blockchain. For some reason, most blockchain based polls seem to consider token holding as the only way to permission a poll. However this hampers flexibility, and hence our poll standard is leveraging EIP 1261 in order to clear the permissioning hurdle. Not only does it allow for more creative poll structures in terms of vote weightage, but even improves the flexibility in permissioning by allowing developers to combine several entities and read attributes from entities.

3. Flexibility: The vote weight module of the poll standard can be used effectively to design various kinds of poll contracts which function differently and are suited to different environments. Some examples are quadratic voting, karma voting, delegated voting, token based voting, and one person one vote systems. These schemes are possible due to the separation of voterbase creation and vote weight calculation.

4. NoV Counts: Several weighted polls have struggled to provide proper transparency because they only show the final result without enough granularity. This is because they do not store the number of voters that have voted for each proposal, and only store the total accrued vote for each option. EIP 1417 solves this by additionally recording number of voters(NoV) in each proposal. This NoV count is redundant in the case of one person one vote, but elsewhere, it is helpful in figuring out concentration of power. This ensures that malicious parties can be traced to a larger extent.

5. Event Logging: The poll standard logs an event during a successful vote, unsuccessful vote, and a successful unvote. This is being done so that in the event of a malicious admin removing real members or adding fake members, communities can build tools in order to perform advanced audits and simulate results in the absence of the malicious attack. Such advanced features are completely absent in most polls, and hence, it is hard to investigate such polls.

6. Pollscan.io: The Electus foundation is working on a web based application for accessing and interacting with poll data on the blockchain, it will be deployed on the domain name www.pollscan.io in the coming months.

All that being said, we are very excited to share our proposal with the community and open up to suggestions in this space.

### Benefits

1. Building applications (pollscan.io) on top of a standardized voting interface enables transparency and encourage more DAO/DAICO&apos;s to act responsibly in terms of governance
2. Create Action contracts which take actions programmatically based on the result of a poll
3. Allow the compatibility with token standard such as [ERC-20](/EIPs/EIPS/eip-20) or (./eip-777.md)) and membership standard such as [EIP-1261](/EIPs/EIPS/eip-1261)
4. Flexibility allows for various voting schemes including but not limited to modern schemes such as PLCR Voting

### Use-cases:

Polls are useful in any context of collective decision making, which include but aren&apos;t limited to:

1. Governing public resources, like ponds, playgrounds, streets etc
2. Maintaining fiscal policy in a transparent consensus driven manner
3. Governing crowdfunded projects - refer DAICO, Vitalik Buterin
4. Implementation of Futarchy
5. Decision making in political parties, and municipal corporations
6. Governing expenditure of a cryptocurrency community

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

**Every ERC-1417 compliant contract must implement the `ERC1417` and `ERC165` interfaces** (subject to &quot;caveats&quot; below):

```solidity
/// @title ERC-1417 Poll Standard
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1417.md
///  Note: the ERC-165 identifier for this interface is 0x4fad898b.
interface IPoll {
    /// @dev This emits when a person tries to vote without permissions. Useful for auditing purposes.
    ///  E.g.: To prevent an admin to revoke permissions; calculate the result had they not been removed.
    /// @param _from User who tried to vote
    /// @param _to the index of the proposal he voted to
    /// @param voteWeight the weight of his vote
    event TriedToVote(address indexed _from, uint8 indexed _to, uint voteWeight);

    /// @dev This emits when a person votes successfully
    /// @param _from User who successfully voted
    /// @param _to the index of the proposal he voted to
    /// @param voteWeight the weight of his vote
    event CastVote(address indexed _from, uint8 indexed _to, uint voteWeight);

    /// @dev This emits when a person revokes his vote
    /// @param _from User who successfully unvoted
    /// @param _to the index of the proposal he unvoted
    /// @param voteWeight the weight of his vote
    event RevokedVote(address indexed _from, uint8 indexed _to, uint voteWeight);

    /// @notice Handles the vote logic
    /// @dev updates the appropriate data structures regarding the vote.
    ///  stores the proposalId against the user to allow for unvote
    /// @param _proposalId the index of the proposal in the proposals array
    function vote(uint8 _proposalId) external;

    /// @notice Handles the unvote logic
    /// @dev updates the appropriate data structures regarding the unvote
    function revokeVote() external;

    /// @notice gets the proposal names
    /// @dev limit the proposal count to 32 (for practical reasons), loop and generate the proposal list
    /// @return the list of names of proposals
    function getProposals() external view returns (bytes32[]);

    /// @notice returns a boolean specifying whether the user can vote
    /// @dev implement logic to enable checks to determine whether the user can vote
    ///  if using eip-1261, use protocol addresses and interface (IERC1261) to enable checking with attributes
    /// @param _to the person who can vote/not
    /// @return a boolean as to whether the user can vote
    function canVote(address _to) external view returns (bool);

    /// @notice gets the vote weight of the proposalId
    /// @dev returns the current cumulative vote weight of a proposal
    /// @param _proposalId the index of the proposal in the proposals array
    /// @return the cumulative vote weight of the specified proposal
    function getVoteTally(uint _proposalId) external view returns (uint);

    /// @notice gets the no. of voters who voted for the proposal
    /// @dev use a struct to keep a track of voteWeights and voterCount
    /// @param _proposalId the index of the proposal in the proposals array
    /// @return the voter count of the people who voted for the specified proposal
    function getVoterCount(uint _proposalId) external view returns (uint);

    /// @notice calculates the vote weight associated with the person `_to`
    /// @dev use appropriate logic to determine the vote weight of the individual
    ///  For sample implementations, refer to end of the eip
    /// @param _to the person whose vote weight is being calculated
    /// @return the vote weight of the individual
    function calculateVoteWeight(address _to) external view returns (uint);

    /// @notice gets the leading proposal at the current time
    /// @dev calculate the leading proposal at the current time
    ///  For practical reasons, limit proposal count to 32.
    /// @return the index of the proposal which is leading
    function winningProposal() external view returns (uint8);

    /// @notice gets the name of the poll e.g.: &quot;Admin Election for Autumn 2018&quot;
    /// @dev Set the name in the constructor of the poll
    /// @return the name of the poll
    function getName() external view returns (bytes32);

    /// @notice gets the type of the Poll e.g.: Token (XYZ) weighted poll
    /// @dev Set the poll type in the constructor of the poll
    /// @return the type of the poll
    function getPollType() external view returns (bytes32);

    /// @notice gets the logic to be used in a poll&apos;s `canVote` function
    ///  e.g.: &quot;XYZ Token | US &amp; China(attributes in erc-1261) | Developers(attributes in erc-1261)&quot;
    /// @dev Set the Voterbase logic in the constructor of the poll
    /// @return the voterbase logic
    function getVoterBaseLogic() external view returns (bytes32);

    /// @notice gets the start time for the poll
    /// @dev Set the start time in the constructor of the poll as Unix Standard Time
    /// @return start time as Unix Standard Time
    function getStartTime() external view returns (uint);

    /// @notice gets the end time for the poll
    /// @dev Set the end time in the constructor of the poll as Unix Time or specify duration in constructor
    /// @return end time as Unix Standard Time
    function getEndTime() external view returns (uint);

    /// @notice returns the list of entity addresses (eip-1261) used for perimissioning purposes.
    /// @dev addresses list can be used along with IERC1261 interface to define the logic inside `canVote()` function
    /// @return the list of addresses of entities
    function getProtocolAddresses() external view returns (address[]);

    /// @notice gets the vote weight against all proposals
    /// @dev limit the proposal count to 32 (for practical reasons), loop and generate the vote tally list
    /// @return the list of vote weights against all proposals
    function getVoteTallies() external view returns (uint[]);

    /// @notice gets the no. of people who voted against all proposals
    /// @dev limit the proposal count to 32 (for practical reasons), loop and generate the vote count list
    /// @return the list of voter count against all proposals
    function getVoterCounts() external view returns (uint[]);

    /// @notice For single proposal polls, returns the total voterbase count.
    ///  For multi proposal polls, returns the total vote weight against all proposals
    ///  this is used to calculate the percentages for each proposal
    /// @dev limit the proposal count to 32 (for practical reasons), loop and generate the voter base denominator
    /// @return an integer which specifies the above mentioned amount
    function getVoterBaseDenominator() external view returns (uint);
}
```

### Caveats

The 0.4.24 Solidity interface grammar is not expressive enough to document the ERC-1417 standard. A contract which complies with ERC-1417 MUST also abide by the following:

- Solidity issue #3412: The above interfaces include explicit mutability guarantees for each function. Mutability guarantees are, in order weak to strong: `payable`, implicit nonpayable, `view`, and `pure`. Your implementation MUST meet the mutability guarantee in this interface and you MAY meet a stronger guarantee. For example, a `payable` function in this interface may be implemented as nonpayble (no state mutability specified) in your contract. We expect a later Solidity release will allow your stricter contract to inherit from this interface, but a workaround for version 0.4.24 is that you can edit this interface to add stricter mutability before inheriting from your contract.
- Solidity issue #2330: If a function is shown in this specification as `external` then a contract will be compliant if it uses `public` visibility. As a workaround for version 0.4.24, you can edit this interface to switch to `public` before inheriting from your contract.

_If a newer version of Solidity allows the caveats to be expressed in code, then this EIP MAY be updated and the caveats removed, such will be equivalent to the original specification._

## Rationale

As the poll standard is built with the intention of creating a system that allows for more transparency and accessibility of governance data, the design choices in the poll standard are driven by this motivator. In this section we go over some of the major design choices, and why these choices were made:

1. Event logging: The logic behind maintaining event logs in the cases of:

   - Cast Vote
   - Unvote
   - Failed Vote
     is to ensure that in the event of a manipulated voterbase, simple off chain checks can be performed to audit the integrity of the poll result.

2. No poll finish trigger: There was a consideration of adding functions in the poll which execute after completion of the poll to carry out some pre-decided logic. However this was deemed to be unnecessary - because such an action can be deployed in a separate contract which simply reads the result of a given poll, and against the spirit of modularity, because no actions can be created after the poll has been deployed. Also, such functions would not be able to combine the results of polls, and definitely would not fit into polls that do not have an end time.

3. Allow for unbound polls: The poll standard, unlike other voting standard proposals, does not force polls to have an end time. This becomes relevant in some cases where the purpose of a poll is to have a live register of ongoing consensus. Some other use cases come into picture when you want to deploy a set of action contracts which read from the poll, and want to be able to execute the action contract whenever a poll reaches a certain threshold, rather than waiting for the end of the poll.

4. Modularization: There have been opinions in the Ethereum community that there cannot exist a voting standard, because voting contracts can be of various types, and have several shapes and forms. However we disagree, and make the case that modularization is the solution. While different polls may need different logic, they all need consistent end points. All polls need to give out results along with headcounts, all polls should have event logs, all polls should be examinable with frontend tools, and so on. The poll standard is not a statement saying “all polls should be token based” or any such specific system. However the poll standard is a statement saying that all polls should have a common access and modification protocol - this will enable more apps to include governance without having to go through the trouble of making customers start using command line.

Having explained our rationale, we are looking forward to hearing from the community some thoughts on how this can be made more useful or powerful.

**Gas and Complexity** (regarding the enumeration for proposal count)

This specification contemplates implementations that contain a sample of 32 proposals (max up to blockgaslimit). If your application is able to grow and needs more than 32 proposals, then avoid using for/while loops in your code. These indicate your contract may be unable to scale and gas costs will rise over time without bound

**Privacy**

Personal information: The standard does not put any personal information on to the blockchain, so there is no compromise of privacy in that respect.

**Community Consensus**

We have been very inclusive in this process and invite anyone with questions or contributions into our discussion. However, this standard is written only to support the identified use cases which are listed herein.

## Test Cases

Voting Standard includes test cases written using Truffle.

## Implementations

Voting Standard -- a reference implementation

- MIT licensed, so you can freely use it for your projects
- Includes test cases
- Also available as a npm package - npm i electusvoting

## References

**Standards**

- [EIP-20: ERC-20 Token Standard (a.k.a. ERC-20)](/EIPs/EIPS/eip-20)
- [EIP-165: Standard Interface Detection](/EIPs/EIPS/eip-165)
- [EIP-721: Non-Fungible Token Standard(a.k.a. ERC-721)](/EIPs/EIPS/eip-721)
- [ERC-1261 MV Token Standard](/EIPs/EIPS/eip-1261)
- [RFC 2119 Key words for use in RFCs to Indicate Requirement Levels](https://www.ietf.org/rfc/rfc2119.txt)

**Issues**

1. The Original ERC-1417 Issue. https://github.com/ethereum/eips/issues/1417
1. Solidity Issue \#2330 -- Interface Functions are Axternal. https://github.com/ethereum/solidity/issues/2330
1. Solidity Issue \#3412 -- Implement Interface: Allow Stricter Mutability. https://github.com/ethereum/solidity/issues/3412
1. Solidity Issue \#3419 -- Interfaces Can&apos;t Inherit. https://github.com/ethereum/solidity/issues/3419

**Discussions**

1. ERC-1417 (announcement of first live discussion). https://github.com/ethereum/eips/issues/1417

**Voting Implementations and Other Projects**

- [Voting Implementations](https://github.com/chaitanyapotti/Voting)

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 16 Sep 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1417</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1417</guid>
      </item>
    
      <item>
        <title>Blockchain Storage Rent Payment</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-1418-storage-rent/10737</comments>
        
        <description>## Abstract

At each block, deduct an amount of value (&quot;rent&quot;) from every account based on the quantity of storage used by that account.

## Motivation

Ethereum is a public utility and we are underpricing the long-term costs of storage. Storage cost can be approximately modeled as bytes × time.

## Specification

**Updated transaction type**

A new transaction type is introduced. Whereas [EIP-1559](/EIPs/EIPS/eip-1559) introduced warm access for contract state, this new type introduces warm access for contract code.

**New state variables (per account)**

* **σ[a]_rent** -- an amount of value, in Wei, this is a signed value
* **σ[a]_storageWords** -- number of words in storage

**New constants**

* **`RENT_WORD_COST`** -- The rent cost, in Wei, paid for each word-block
* **`RENT_ACCOUNT_COST`** -- The rent cost, in Wei, paid for each account-block
* **`FORK_BLOCK`** – When implementation starts

**New opcodes**

* **`RENTBALANCE(address)`** -- G_BALANCE -- Similar to `BALANCE`
  * This returns the logical `σ[a]_rent` value which is defined to reduce each block. It is possible for the implementation to calculate this value using the recommended implementation variables, rather than storing and updating  `σ[a]_rent` every block for every account.
* **`SENDRENT(address, amount)`** -- G_BASE -- Convert value to rent and send to account
  1. `σ[account]_rent` += amount
  2. `σ[msg.sender]_balance` -= amount

**Updated opcodes**

A new subroutine, paying for rent, is established as such:

```pseudocode
PAYRENT(account)
    blocks_to_pay = NUMBER - σ[account]_rentLastPaid
    cost_per_block = RENT_ACCOUNT_COST + RENT_WORD_COST * (⌈∥σ[account]_code∥ / 32⌉ + * σ[a]_storageWords)
    rent_to_pay = blocks_to_pay * cost_per_block
    σ[account]_rent -= rent_to_pay
    if σ[account]_rent &lt; 0
    		σ[account]_value += σ[account]_rent
    		σ[account]_rent = 0
    end
    if σ[account]_value &lt; 0
    		σ[account]_rent = σ[account]_value
    		σ[account]_value = 0
    end
    σ[account]_rentLastPaid = NUMBER
    σ[account]_rentEvictBlock = NUMBER + ⌊σ[account]_rent / cost_per_block⌋
END PAYRENT
```

* **`SSTORE(account, key, value)`**
  * Perform PAYRENT(account)
  * If `account` is evicted (i.e. `NUMBER` &gt; `σ[account]_rentEvictBlock`) then transaction fails unless using the new transaction type and sufficient proofs are included to validate the old storage root and calculate the new root.
  * Do normal SSTORE operation
  * If the old value was zero for this [account, key] and the new value is non-zero, then `σ[account]_storageWords++`
  * If the old value was non-zero for this [account, key] and the new value is zero, then `σ[account]_storageWords--`, and if the result is negative then set to zero
* **`SLOAD(account, key)`**
  * If `account` is evicted (i.e. `NUMBER` &gt; `σ[account]_rentEvictBlock`) then transaction fails unless using the new transaction type and sufficient proofs are included to validate the existing storage root and the existing storage value.
  * Do normal SLOAD operation.
* **`CALL (and derivatives)`**
  * If the target block is evicted (i.e. `NUMBER` &gt; `σ[account]_rentEvictBlock`) then transaction fails unless using the new transaction type and sufficient proof is included to validate the existing code.
  * Do normal CALL operation
* **`CREATE`**
  * Set σ[account]_rentLastPaid = NUMBER
  * Do normal CREATE operation
  * `σ[account]_storageWord = 0`
  * Note: it is possible there is a pre-existing rent balance here

**New built-in contract**

* `PAYRENT(address, amount)` -- Calls `PAYRENT` opcode
  * This is a convenience for humans to send Ether from their accounts and turn it into rent. Note that simple accounts (CODESIZE == 0) cannot call arbitrary opcodes, they can only call CREATE or CALL.
  * The gas cost of PAYRENT will be 10,000 or lower if possible.

**Calculating `σ[account]_storageWord` for existing accounts**

DRAFT...

It is not an acceptable upgrade if on the fork block it is necessary for only archive nodes to participate which know the full storage amount for each account.

An acceptable upgrade will be if the required `σ[account]_storageWord` can be calculated (or estimated) incrementally based on new transaction activity.

DRAFT: I think it is possible to make such an acceptable upgrade using an unbiased estimator

* add one bit of storage per `SSTORE` for legacy accounts on the first access of a given key
* add log(n) bits for each trie level
* assume that storage keys are a random variable

To think more about...

**No changes to current opcode gas costs.**

## Rationale 

**No call**

A contract will not know or react to the receipt of rent. This is okay. Workaround: if a contract really needed to know who provided rent payments then it could create a function in its ABI to attribute these payments. It is already possible to send payments to a contract without attribution by using `SELFDESTRUCT`. Other blockchains like TRON allow to transfer value to a contract without performing a call.

**Eviction responsibility / lazy evaluation**

The specification gives responsibility for eviction to the consensus clients. This is the most predictable behavior because it happens exactly when it should. Also there need not be any incentive mechanism (refund gas, bounty) for outside participants (off-chain) to monitor accounts and request removal.

It is possible that an arbitrary number of accounts will be evicted in one block. That doesn&apos;t matter. Client implementations do not need to track which accounts are evicted, consensus is achieved just by agreeing on the conditions under which an account would be evicted.

**No converting rent to value**

Ether converted to rent cannot be converted back. Anybody that works in accounting and knows about gifts cards should tell you this is a good idea. It makes reasoning about the system much easier.

**Accounts pay rent**

Yes, they pay rent. It costs resources to account for their balances so we charge them rent.

**Why do you need a separate rent account?**

Because anybody/everybody can contribute to the rent account. If you depend on a contract, you should contribute to its rent.

But the contract can spend all of its value.

By maintaining a separate rent and value balance, this allows people to contribute to the rent while being confident that this is allowing the contract to stay around.

NOTE: cloning. With this EIP, it may become feasible to allow storage cloning. Yes really. Because the new clone will be paying rent. See other EIP, I think made by Augur team.

### Economics &amp; constants

An `SSTORE` executed in 2015 cost 20,000 gas and has survived about 6 million blocks. The gas price has been around 1 ~ 50 Gwei. So basically 4,000 Wei per block per word so far. Maybe storing an account is 10 times more intensive than storing a word. But actually `G_transaction` is 21,000 and `G_sstore` is 20,000 so these are similar and they can both create new accounts / words.

How about:

* `RENT_WORD_COST` -- 4,000 Wei
* `RENT_ACCOUNT_COST` -- 4,000 Wei
* `FORK_BLOCK` – when implementation starts

The rent is priced in cold, hard Ether. It is not negotiated by clients, it is not dynamic.

A future EIP may change this pricing to be dynamic. For example to notarize a block, notaries may be required to prove they have the current storage dataset (excluding evictions). Additionally, they may also prove they have the dataset plus evictions to earn an additional fee. The relative storage of the evicted accounts, and the other accounts versus the value of the additional fee may be used as a feedback mechanism to set a market price for storage.

FYI, there are about 15B words in the Ethereum Mainnet dataset and about 100M total Ether mined. This means if all Ether was spent on storage at current proposed prices it would be 400 terabyte-years of storage. I&apos;m not sure if it is helpful to look at it that way.

## Backwards Compatibility

EIP-1559 already introduces a mechanism for nodes to participate without recording the full network state and for clients to warm cache with storage data in their type 2 transactions.

Users will need to be educated.

Many smart contracts allow anybody to use an arbitrary amount of storage in them. This can limit the usefulness of deploying this proposal on an existing chain.

**Recommended implementation variables (per account)**

* **σ[a]_rentLastPaid** -- a block number that is set when:
  * Value is transferred into an account (`CREATE`, `CALL`, `SELFDESTRUCT`)
  * Code is set for an account (`CREATE`)
  * An account&apos;s storage is updated (`SSTORE`)
  * This begins with a logical value of `FORK_BLOCK` for all accounts

* **σ[a]_rentEvictBlock** -- the block number when this account will be evicted

**Storage note**

For every account that is evicted, clients may choose to delete that storage from disk. A future EIP may make an incentive to keep this extra data for a fee. A future EIP may create a mechanism for clients to exchange information about these storage states.

## Security Considerations

Many smart contracts allow anybody to use an arbitrary amount of storage in them.

## Copyright

Copyright and related rights waived via CC0.

&lt;!--

 ## TODO

 To discuss:

 - Can/should an evicted account be allowed to be un-evicted when paying past due rent?
   --&gt;
</description>
        <pubDate>Sun, 16 Sep 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1418</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1418</guid>
      </item>
    
      <item>
        <title>dApp Components (avatar) &amp; Universal Wallet</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethresear.ch/t/avatar-system-and-universal-wallet-for-ethereum-address/3473</comments>
        
        <description>## Simple Summary
Contracts are open source based. And most developers use the public contracts at the start of the project to modify or simply include them. This is project-oriented centralized development and I think it is a waste of resources. Therefore, we propose to make dApp or contracts component-ready for use in other services.

## Abstract
There have been suggestions for modified tokens based on erc20, but since many tokens have already been built on erc20, it is necessary to increase the utilization of already developed erc20 tokens. Therefore, we propose a universal wallet that can use erc20 tokens universally. We also propose a component dApp that allows you to create and save your avatar (&amp; social badge system), and use it immediately in other services. All of the dApps suggested in this document are based on decentralized development and use that anyone can create and participate in.

## Motivation
While many projects are under development in an open source way, they are simply adding and deploy with open sources to their projects. This means that you are developing a centralized service that uses your own dApp-generated information on your own. In order to improve the block chain ecosystem, all resources created by dApp and placed in the public block chain must be reusable in another dApp. This means that you can enhance your service by exchanging the generated information with other dApp. Likewise, ERC20 Tokens require Universal Wallet standards to be easy to use for direct transactions.

### Seeds for improvement of the blockchain ecosystem.
- Synergy - With other dApps and resources.
- Enhanced interface - For ERC20 tokens.
- Easy &amp; Decentralized - Everyone should be able to add to their services easily, without censorship.


#### The following avatar store, badge system, and universal wallet are kind of examples about component dApp.
![intro](/EIPs/assets/eip-1438/intro.png)

## Specification
### 1. Avatar
#### 1.1. Avatar Shop
- The avatar store is created after ERC20 currency is set.
- You can customize asset category &amp; viewer script.

#### 1.2. Upload asset &amp; user data
The avatar&apos;s information &amp; assets are stored in the event log part of the block chain.
- Assets are SVG format. (compressed with gzip)
- avatar information data is json (compressed with msgpack)

![avatar](/EIPs/assets/eip-1438/avatar.png)
** The avatar assets from [Avataaars](https://github.com/fangpenlin/avataaars) developed by [Fang-Pen Lin](https://twitter.com/fangpenlin), the original avatar is designed by [Pablo Stanley](https://twitter.com/pablostanley).

### 2. Universal Wallet
![wallet](/EIPs/assets/eip-1438/wallet.png)
#### 2.1. ERC20 interface
``` js
contract ERC20Interface {
    function totalSupply() public constant returns (uint);
    function balanceOf(address tokenOwner) public constant returns (uint balance);
    function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
    function transfer(address to, uint tokens) public returns (bool success);
    function approve(address spender, uint tokens) public returns (bool success);
    function transferFrom(address from, address to, uint tokens) public returns (bool success);

    event Transfer(address indexed from, address indexed to, uint tokens);
    event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}
```

#### 2.2. Fixed ERC20 contract for receive approval and execute function in one call
``` js
function approveAndCall(address spender, uint tokens, bytes data) public returns (bool success) {
    allowed[msg.sender][spender] = tokens;
    emit Approval(msg.sender, spender, tokens);
    ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, this, data);
    return true;
}
```

#### 2.3. And ApproveAndCallFallBack contract for Fixed ERC20.
However, many ERC20 tokens are not prepared.
``` js
contract ApproveAndCallFallBack {
    function receiveApproval(address from, uint256 tokens, address token, bytes data) public;
}
```
#### 2.4. Universal Wallet
We propose a Universal Wallet to solve this problem.

``` js
contract UniversalWallet is _Base {

    constructor(bytes _msgPack) _Base(_msgPack) public {}
    function () public payable {}

    //-------------------------------------------------------
    // erc20 interface
    //-------------------------------------------------------
    function balanceOf(address _erc20) public constant returns (uint balance) {
        if(_erc20==address(0))
            return address(this).balance;
        return _ERC20Interface(_erc20).balanceOf(this);
    }
    function transfer(address _erc20, address _to, uint _tokens) onlyOwner public returns (bool success) {
        require(balanceOf(_erc20)&gt;=_tokens);
        if(_erc20==address(0))
            _to.transfer(_tokens);
        else
            return _ERC20Interface(_erc20).transfer(_to,_tokens);
        return true;
    }
    function approve(address _erc20, address _spender, uint _tokens) onlyOwner public returns (bool success) {
        require(_erc20 != address(0));
        return _ERC20Interface(_erc20).approve(_spender,_tokens);
    }

    //-------------------------------------------------------
    // pay interface
    //-------------------------------------------------------
    function pay(address _store, uint _tokens, uint256[] _options) onlyOwner public {
        address erc20   = _ApproveAndCallFallBack(_store).erc20();
        address spender = _ApproveAndCallFallBack(_store).spender();
        if(erc20 == address(0)) {
            transfer(erc20,spender,_tokens);
            _ApproveAndCallFallBack(_store).receiveApproval(_options);
        } else {
            _ERC20Interface(erc20).approve(spender,_tokens);
            _ApproveAndCallFallBack(_store).receiveApproval(_options);
        }
    }
    function pay(address _store, uint _tokens, bytes _msgPack) onlyOwner public {
        address erc20   = _ApproveAndCallFallBack(_store).erc20();
        address spender = _ApproveAndCallFallBack(_store).spender();
        if(erc20 == address(0)) {
            transfer(erc20,spender,_tokens);
            _ApproveAndCallFallBack(_store).receiveApproval(_msgPack);
        } else {
            _ERC20Interface(erc20).approve(spender,_tokens);
            _ApproveAndCallFallBack(_store).receiveApproval(_msgPack);
        }
    }
}
```

## Test Cases
- https://www.nitro888.com
- https://github.com/Nitro888/nitro888.github.io
- https://github.com/Nitro888/dApp-Alliance

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 21 Sep 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1438</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1438</guid>
      </item>
    
      <item>
        <title>Localized Messaging with Signal-to-Text</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-1444-localized-messaging-with-signal-to-text/</comments>
        
        <description>## Simple Summary

A method of converting machine codes to human-readable text in any language and phrasing.

## Abstract

An on-chain system for providing user feedback by converting machine-efficient codes into human-readable strings in any language or phrasing. The system does not impose a list of languages, but rather lets users create, share, and use the localizated text of their choice.

## Motivation

There are many cases where an end user needs feedback or instruction from a smart contract. Directly exposing numeric codes does not make for good UX or DX. If Ethereum is to be a truly global system usable by experts and lay persons alike, systems to provide feedback on what happened during a transaction are needed in as many languages as possible.

Returning a hard-coded string (typically in English) only serves a small segment of the global population. This standard proposes a method to allow users to create, register, share, and use a decentralized collection of translations, enabling richer messaging that is more culturally and linguistically diverse.

There are several machine efficient ways of representing intent, status, state transition, and other semantic signals including booleans, enums and [ERC-1066 codes](/EIPs/EIPS/eip-1066). By providing human-readable messages for these signals, the developer experience is enhanced by returning easier to consume information with more context (ex. `revert`). End user experience is enhanced by providing text that can be propagated up to the UI.

## Specification

### Contract Architecture

Two types of contract: `LocalizationPreferences`, and `Localization`s.

The `LocalizationPreferences` contract functions as a proxy for `tx.origin`.

```diagram
                                                                   +--------------+
                                                                   |              |
                                                          +------&gt; | Localization |
                                                          |        |              |
                                                          |        +--------------+
                                                          |
                                                          |
+-----------+          +-------------------------+        |        +--------------+
|           |          |                         | &lt;------+        |              |
| Requestor | &lt;------&gt; | LocalizationPreferences | &lt;-------------&gt; | Localization |
|           |          |                         | &lt;------+        |              |
+-----------+          +-------------------------+        |        +--------------+
                                                          |
                                                          |
                                                          |        +--------------+
                                                          |        |              |
                                                          +------&gt; | Localization |
                                                                   |              |
                                                                   +--------------+
```

### `Localization`

A contract that holds a simple mapping of codes to their text representations.

```solidity
interface Localization {
  function textFor(bytes32 _code) external view returns (string _text);
}
```

#### `textFor`

Fetches the localized text representation.

```solidity
function textFor(bytes32 _code) external view returns (string _text);
```

### `LocalizationPreferences`

A proxy contract that allows users to set their preferred `Localization`. Text lookup is delegated to the user&apos;s preferred contract.

A fallback `Localization` with all keys filled MUST be available. If the user-specified `Localization` has not explicitly set a loalization (ie. `textFor` returns `&quot;&quot;`), the `LocalizationPreferences` MUST redelegate to the fallback `Localization`.

```solidity
interface LocalizationPreferences {
  function set(Localization _localization) external returns (bool);
  function textFor(bytes32 _code) external view returns (bool _wasFound, string _text);
}
```

#### `set`

Registers a user&apos;s preferred `Localization`. The registering user SHOULD be considered `tx.origin`.

```solidity
function set(Localization _localization) external;
```

#### `textFor`

Retrieve text for a code found at the user&apos;s preferred `Localization` contract.

The first return value (`bool _wasFound`) represents if the text is available from that `Localization`, or if a fallback was used. If the fallback was used in this context, the `textFor`&apos;s first return value MUST be set to `false`, and is `true` otherwise.

```solidity
function textFor(bytes32 _code) external view returns (bool _wasFound, string _text);
```

### String Format

All strings MUST be encoded as [UTF-8](https://www.ietf.org/rfc/rfc3629.txt).

```solidity
&quot;Špeĉiäl chârãçtérs are permitted&quot;
&quot;As are non-Latin characters: アルミ缶の上にあるみかん。&quot;
&quot;Emoji are legal: 🙈🙉🙊🎉&quot;
&quot;Feel free to be creative: (ﾉ◕ヮ◕)ﾉ*:･ﾟ✧&quot;
```

### Templates

Template strings are allowed, and MUST follow the [ANSI C `printf`](https://pubs.opengroup.org/onlinepubs/009696799/utilities/printf.html) conventions.

```solidity
&quot;Satoshi&apos;s true identity is %s&quot;
```

Text with 2 or more arguments SHOULD use the POSIX parameter field extension.

```solidity
&quot;Knock knock. Who&apos;s there? %1$s. %1$s who? %2$s!&quot;
```

## Rationale

### `bytes32` Keys

`bytes32` is very efficient since it is the EVM&apos;s base word size. Given the enormous number of elements (card(A) &gt; 1.1579 × 10&lt;sup&gt;77&lt;/sup&gt;), it can embed nearly any practical signal, enum, or state. In cases where an application&apos;s key is longer than `bytes32`, hashing that long key can map that value into the correct width.

Designs that use datatypes with small widths than `bytes32` (such as `bytes1` in [ERC-1066](/EIPs/EIPS/eip-1066)) can be directly embedded into the larger width. This is a trivial one-to-one mapping of the smaller set into the larger one.

### Local vs Globals and Singletons

This spec has opted to not _force_ a single global registry, and rather allow any contract and use case deploy their own system. This allows for more flexibility, and does not restrict the community for opting to use singleton `LocalizationPreference` contracts for common use cases, share `Localization`s between different proxys, delegate translations between `Localization`s, and so on.

There are many practical uses of agreed upon singletons. For instance, translating codes that aim to be fairly universal and integrated directly into the broader ecosystem (wallets, frameworks, debuggers, and the like) will want to have a single `LocalizationPreference`.

Rather the dispersing several `LocalizationPreference`s for different use cases and codes, one could imagine a global &quot;registry of registries&quot;. While this approach allows for a unified lookups of all translations in all use cases, it is antithetical to the spirit of decentralization and freedom. Such a system also increases the lookup complexity, places an onus on getting the code right the first time (or adding the overhead of an upgradable contract), and need to account for use case conflicts with a &quot;unified&quot; or centralized numbering system. Further, lookups should be lightweight (especially in cases like looking up revert text).

For these reasons, this spec chooses the more decentralized, lightweight, free approach, at the cost of on-chain discoverability. A registry could still be compiled, but would be difficult to enforce, and is out of scope of this spec.

### Off Chain Storage

A very viable alternative is to store text off chain, with a pointer to the translations on-chain, and emit or return a `bytes32` code for another party to do the lookup. It is difficult to guarantee that off-chain resources will be available, and requires coordination from some other system like a web server to do the code-to-text matching. This is also not compatible with `revert` messages.

### ASCII vs UTF-8 vs UTF-16

UTF-8 is the most widely used encoding at time of writing. It contains a direct embedding of ASCII, while providing characters for most natural languages, emoji, and special characters.

Please see the [UTF-8 Everywhere Manifesto](https://utf8everywhere.org/) for more information.

### When No Text is Found

Returning a blank string to the requestor fully defeats the purpose of a localization system. The two options for handling missing text are:

1. A generic &quot;text not found&quot; message in the preferred language
2. The actual message, in a different language

#### Generic Option

This designed opted to not use generic fallback text. It does not provide any useful information to the user other than to potentially contact the `Localization` maintainer (if one even exists and updating is even possible).

#### Fallback Option

The design outlined in this proposal is to providing text in a commonly used language (ex. English or Mandarin). First, this is the language that will be routed to if the user has yet to set a preference. Second, there is a good chance that a user may have _some_ proficiency with the language, or at least be able to use an automated translation service.

Knowing that the text fell back via `textFor`s first return field boolean is _much_ simpler than attempting language detection after the fact. This information is useful for certain UI cases. for example where there may be a desire to explain why localization fell back.

### Decentralized Text Crowdsourcing

In order for Ethereum to gain mass adoption, users must be able to interact with it in the language, phrasing, and level of detail that they are most comfortable with. Rather than imposing a fixed set of translations as in a traditional, centralized application, this EIP provides a way for anyone to create, curate, and use translations. This empowers the crowd to supply culturally and linguistically diverse messaging, leading to broader and more distributed access to information.

### `printf`-style Format Strings

C-style `printf` templates have been the de facto standard for some time. They have wide compatibility across most languages (either in standard or third-party libraries). This makes it much easier for the consuming program to interpolate strings with low developer overhead.

#### Parameter Fields

The POSIX parameter field extension is important since languages do not share a common word order. Parameter fields enable the reuse and rearrangement of arguments in different localizations.

```solidity
(&quot;%1$s is an element with the atomic number %2$d!&quot;, &quot;Mercury&quot;, 80);
// =&gt; &quot;Mercury is an element with the atomic number 80!&quot;
```

#### Simplified Localizations

Localization text does not require use of all parameters, and may simply ignore values. This can be useful for not exposing more technical information to users that would otherwise find it confusing.

```ruby
#!/usr/bin/env ruby

sprintf(&quot;%1$s é um elemento&quot;, &quot;Mercurio&quot;, 80)
# =&gt; &quot;Mercurio é um elemento&quot;
```

```clojure
#!/usr/bin/env clojure

(format &quot;Element #%2$s&quot; &quot;Mercury&quot; 80)
;; =&gt; Element #80
```

### Interpolation Strategy

Please note that it is highly advisable to return the template string _as is_, with arguments as multiple return values or fields in an `event`, leaving the actual interpolation to be done off chain.


```solidity
event AtomMessage {
  bytes32 templateCode;
  bytes32 atomCode;
  uint256 atomicNumber;
}
```

```javascript
#!/usr/bin/env node

var printf = require(&apos;printf&apos;);

const { returnValues: { templateCode, atomCode, atomicNumber } } = eventResponse;

const template = await AppText.textFor(templateCode);
// =&gt; &quot;%1$s ist ein Element mit der Ordnungszahl %2$d!&quot;

const atomName = await PeriodicTableText.textFor(atomCode);
// =&gt; &quot;Merkur&quot;

printf(template, atomName, 80);
// =&gt; &quot;Merkur ist ein Element mit der Ordnungszahl 80!&quot;
```

### Unspecified Behaviour

This spec does not specify:

* Public or private access to the default `Localization`
* Who may set text
  * Deployer
  * `onlyOwner`
  * Anyone
  * Whitelisted users
  * and so on
* When text is set
  * `constructor`
  * Any time
  * Write to empty slots, but not overwrite existing text
  * and so on

These are intentionally left open. There are many cases for each of these, and restricting any is fully beyond the scope of this proposal.

## Implementation

```solidity
pragma solidity ^0.4.25;

contract Localization {
  mapping(bytes32 =&gt; string) private dictionary_;

  constructor() public {}

  // Currently overwrites anything
  function set(bytes32 _code, string _message) external {
    dictionary_[_code] = _message;
  }

  function textFor(bytes32 _code) external view returns (string _message) {
    return dictionary_[_code];
  }
}

contract LocalizationPreference {
  mapping(address =&gt; Localization) private registry_;
  Localization public defaultLocalization;

  bytes32 private empty_ = keccak256(abi.encodePacked(&quot;&quot;));

  constructor(Localization _defaultLocalization) public {
    defaultLocalization = _defaultLocalization;
  }

  function set(Localization _localization) external returns (bool) {
    registry_[tx.origin] = _localization;
    return true;
  }

  function get(bytes32 _code) external view returns (bool, string) {
    return get(_code, tx.origin);
  }

  // Primarily for testing
  function get(bytes32 _code, address _who) public view returns (bool, string) {
    string memory text = getLocalizationFor(_who).textFor(_code);

    if (keccak256(abi.encodePacked(text)) != empty_) {
      return (true, text);
    } else {
      return (false, defaultLocalization.textFor(_code));
    }
  }

  function getLocalizationFor(address _who) internal view returns (Localization) {
    if (Localization(registry_[_who]) == Localization(0)) {
      return Localization(defaultLocalization);
    } else {
      return Localization(registry_[tx.origin]);
    }
  }
}
```

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 23 Sep 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1444</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1444</guid>
      </item>
    
      <item>
        <title>ERC-1450 A compatible security token for issuing and trading SEC-compliant securities</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-proposal-ldgrtoken-a-compatible-security-token-for-issuing-and-trading-sec-compliant-securities/1468</comments>
        
        <description># ERC-1450 - A compatible security token for issuing and trading SEC-compliant securities

## Simple Summary
`ERC-1450` is an `ERC-20` compatible token that enables issuing tokens representing securities that are required to comply with one or more of the following [Securities Act Regulations: Regulation Crowdfunding, Regulation D, and Regulation A](https://www.sec.gov/smallbusiness/exemptofferings).

## Abstract
`ERC-1450` facilitates the recording of ownership and transfer of securities sold in compliance with the [Securities Act Regulations CF, D and A](https://www.sec.gov/smallbusiness/exemptofferings). The issuance and trading of securities is subject to the Securities Exchange Commission (SEC) and specific U.S. state blue sky laws and regulations.

`ERC-1450` manages securities ownership during issuance and trading. The Issuer is the only role that should create a `ERC-1450` and assign the RTA. The RTA is the only role that is allowed to execute `ERC-1450`’s `mint`, `burnFrom`, and `transferFrom` functions. No role is allowed to execute `ERC-1450`’s `transfer` function.

## Motivation
With the advent of the [JOBS Act](https://www.sec.gov/spotlight/jobs-act.shtml) in 2012 and the launch of Regulation Crowdfunding and the amendments to Regulation A and Regulation D in 2016, there has been an expansion in the exemptions available to Issuers and Investors to sell and purchase securities that have not been &quot;registered&quot; with the SEC under the Securities Act of 1933.

There are currently no token standards that expressly facilitate conformity to securities law and related regulations. ERC-20 tokens do not support the regulated roles of Funding Portal, Broker Dealer, RTA, and Investor and do not support the [Bank Secrecy Act/USA Patriot Act KYC and AML requirements](https://www.occ.treas.gov/topics/compliance-bsa/bsa/index-bsa.html). Other improvements (notably [EIP-1404 (Simple Restricted Token Standard)](https://github.com/ethereum/EIPs/issues/1404) have tried to tackle KYC and AML regulatory requirement. This approach is novel because the RTA is solely responsible for performing KYC and AML and should be solely responsible for `transferFrom`, `mint`, and `burnFrom`.

## Specification
`ERC-1450` extends `ERC-20`.

### `ERC-1450`
`ERC-1450` requires that only the Issuer can create a token representing the security that only the RTA manages. Instantiating the `ERC-1450` requires the `Owned` and `IssuerControlled` modifiers, and only the Issuer should execute the `ERC-1450` constructor for a compliant token. `ERC-1450` extends the general `Ownable` modifier to describe a specific subset of owners that automate and decentralize compliance through the contract modifiers `Owned` and `IssuerControlled` and the function modifiers `onlyOwner` and `onlyIssuerTransferAgent`. The `Owned` contract modifier instantiates the `onlyOwner` modifier for functions. The `IssuerControlled` modifier instantiates the `onlyIssuerTransferAgent` modifier for functions.

`ERC-1450` must prevent anyone from executing the `transfer`, `allowance`, and `approve` functions and/or implement these functions to always fail. `ERC-1450` updates the `transferFrom`, `mint`, and `burnFrom` functions. `transferFrom`, `mint`, and `burnFrom` may only be executed by the RTA and are restricted with the `onlyIssuerTransferAgent` modifier. Additionally, `ERC-1450` defines the functions `transferOwnership`, `setTransferAgent`, `setPhysicalAddressOfOperation`, and `isTransferAgent`.  Only the issuer may call the `transferOwnership`, `setTransferAgent`, and `setPhysicalAddressOfOperation` functions. Anyone may call the `isTransferAgent` function.

### Issuers and RTAs
For compliance reasons, the `ERC-1450` constructor must specify the issuer (the `owner`), the RTA (`transferAgent`), the security’s `name`, and the security’s `symbol`.

#### Issuer Owned
`ERC-1450` must specify the `owner` in its constructor, apply the `Owned` modifier, and instantiate the `onlyOwner` modifier to enable specific functions to permit only the Issuer’s `owner` address to execute them. `ERC-1450` also defines the function `transferOwnership` which transfers ownership of the Issuer to the new `owner`’s address and can only be called by the `owner`. `transferOwnership` triggers the `OwnershipTransferred` event.

#### Issuer Controlled
`IssuerControlled` maintains the Issuer’s ownership of their securities by owning the contract and enables the Issuer to set and update the RTA for the Issuer’s securities. `ERC-1450`‘s constructor must have an `IssuerControlled` modifier with the issuer specified in its `ERC-1450` constructor. `IssuerControlled` instantiates the `onlyIssuerTransferAgent` modifier for `ERC-1450` to enable specific functions (`setPhysicalAddressOfOperation` and `setTransferAgent`) to permit only the Issuer to execute these functions.

#### Register Transfer Agent Controlled
`ERC-1450` defines the `setTransferAgent` function (to change the RTA) and `setPhysicalAddressOfOperation` function (to change the Issuer’s address) and must restrict execution to the Issuer’s owner with the `onlyOwner` modifier. `setTransferAgent` must emit the `TransferAgentUpdated` event. `setPhysicalAddressOfOperation` must emit the `PhysicalAddressOfOperationUpdated` event.

`ERC-1450` must specify the `transferAgent` in its constructor and instantiate the `onlyIssuerTransferAgent` modifier to enable specific functions (`transferFrom`, `mint`, and `burnFrom`) to permit only the Issuer’s `transferAgent` address to execute them. `ERC-1450` also defines the public function `isTransferAgent` to lookup and identify the Issuer’s RTA.

#### Securities
`ERC-1450` updates the `transferFrom`, `mint`, and `burnFrom` functions by applying the `onlyIssuerTransferAgent` to enable the issuance, re-issuance, and trading of securities.

### ERC-20 Extension
`ERC-20` tokens provide the following functionality:

```solidity
contract ERC20 {
  function totalSupply() public view returns (uint256);
  function balanceOf(address who) public view returns (uint256);
  function transfer(address to, uint256 value) public returns (bool);
  function allowance(address owner, address spender) public view returns (uint256);
  function transferFrom(address from, address to, uint256 value) public returns (bool);
  function approve(address spender, uint256 value) public returns (bool);
  event Approval(address indexed owner, address indexed spender, uint256 value);
  event Transfer(address indexed from, address indexed to, uint256 value);
}
```

`ERC-20` is extended as follows:

```solidity
/**
 * ERC-1450 is an ERC-20 compatible token that facilitates compliance with one or more of Securities Act Regulations CF, D and A. 
 *
 * Implementations of the ERC-1450 standard must define the following optional ERC-20
 *     fields:
 * 
 * name - The name of the security
 * symbol - The symbol of the security
 * 
 * Implementations of the ERC-1450 standard must specify the following constructor
 *   arguments:
 * 
 * _owner - the address of the owner
 * _transferAgent - the address of the transfer agent
 * _name - the name of the security
 * _symbol - the symbol of the security
 *  
 *  Implementations of the ERC-1450 standard must implement the following contract
 *      modifiers:
 * 
 * Owned - Only the address of the security’s issuer is permitted to execute the
 *     token’s constructor. This modifier also sets up the onlyOwner function modifier.
 * IssuerControlled - This modifier sets up the onlyIssuerTransferAgent function modifier.
 * 
 * Implementations of the ERC-1450 standard must implement the following function
 *      modifiers:
 * 
 * onlyOwner - Only the address of the security’s issuer is permitted to execute the
 *     functions transferOwnership, setTransferAgent, and setPhysicalAddressOfOperation.
 * onlyIssuerTransferAgent - Only the address of the issuer’s Registered Transfer
 *     Agent is permitted to execute the functions transferFrom, mint, and burnFrom.
 * 
 * Implementations of the ERC-1450 standard must implement the following required ERC-20
 *     event to always fail:
 * 
 * Approval - Should never be called as the functions that emit this event must be
 *     implemented to always fail. 
 * 
 * Implementations of the ERC-1450 standard must implement the following required
 *     ERC-20 functions to always fail:
 * 
 * transfer - Not a legal, regulated call for transferring securities because
 *     the token holder initiates the token transfer. The function must be implemented to
 *     always fail.
 * allowance - Not a legal, regulated call for transferring securities because
 *     the token holder may not allow third parties to initiate token transfers. The
 *     function must be implemented to always fail.
 * approve - Not a legal, regulated call for transferring securities because
 *     the token holder may not allow third parties to initiate token transfers. The
 *     function must be implemented to always fail.
 * 
 * Implementations of the ERC-1450 standard must implement the following optional
 *     ERC-20 function:
 * decimals - Must return &apos;0&apos; because securities are indivisible entities.
 * 
 * Implementations of the ERC-1450 standard must implement the following functions:
 * 
 * mint - Only the address of the issuer&apos;s Registered Transfer Agent may create new
 *     securities.
 * burnFrom - Only the address of the issuer’s Registered Transfer Agent may burn or 
 *     destroy securities.
 */

Contract ERC-1450 is Owned, IssuerControlled {

  /**
   * The constructor must implement a modifier (Owned) that creates the onlyOwner modifier
   * to allow only the address of the issuer (the owner) to execute the transferOwnership,
   * setTransferAgent, and setPhysicalAddressOfOperation functions. The construct must also
   * implement a modifier (TransferAgentControlled) that creates the onlyIssuerTransferAgent
   * modifier to allow only the address of the issuer’s Registered Transfer Agent to execute
   * the functions transferFrom, mint, and burnFrom).
   */
    constructor(address _owner, address _transferAgent, string _name, string _symbol)
          Owned(_issuer) TransferAgentControlled(_transferAgent) public;

    /**
     * Specify that only the owner (issuer) may execute a function.
     *
     * onlyOwner requires the msg.sender to be the owner’s address.
     */
    modifier onlyOwner();

    /**
     * Specify that only the issuer’s transferAgent may execute a function.
     *
     * onlyIssuerTransferAgent requires the msg.sender to be the transferAgent’s address.
     */
    modifier onlyIssuerTransferAgent();

    /**
     * Transfer ownership of a security from one issuer to another issuer.
     *
     * transferOwnership must implement the onlyOwner modifier to only allow the
     *     address of the issuer’s owner to transfer ownership.
     * transferOwnership requires the _newOwner address to be the address of the new
     *     issuer.
     */
    function transferOwnership(address _newOwner) public onlyOwner;

    /**
     * Triggered after transferOwnership is executed.
     */
    event OwnershipTransferred()

    /**
     * Sets the transfer agent for the security.
     *
     * setTransferAgent must implement the onlyOwner modifier to only allow the
     *     address of the issuer’s specify the security’s transfer agent.
     * setTransferAgent requires the _newTransferAgent address to be the address of the
     *     new transfer agent.
     */
    function setTransferAgent(address _newTransferAgent) public onlyOwner;

    /**
     * Triggered after setTransferAgent is executed.
     */
    event TransferAgentUpdated(address indexed previousTransferAgent, address indexed
        newTransferAgent);

    /**
     * Sets the issuers physical address of operation.
     *
     * setPhysicalAddressOfOperation must implement the onlyOwner modifier to only allow
     *     the address of the issuer’s owner to transfer ownership.
     * setPhysicalAddressOfOperation requires the _newPhysicalAddressOfOperation address
     *     to be the new address of the issuer.
     */
    function setPhysicalAddressOfOperation(string _newPhysicalAddressOfOperation) public
        onlyOwner;

    /**
     * Triggered after setPhysicalAddressOfOperation is executed.
     */
    event PhysicalAddressOfOperationUpdated(string previousPhysicalAddressOfOperation,
        string newPhysicalAddressOfOperation);

    /**
     * Look up the security’s transfer agent.
     *
     * isTransferAgent is a public function.
     * isTransferAgent requires the _lookup address to determine if that address
     *   is the security’s transfer agent.
     */
    function isTransferAgent(address _lookup) public view returns (bool);

    /**
     * transfer is not a legal, regulated call and must be implemented to always fail.
     */
    transfer(address to, uint tokens) public returns (bool success);

    /**
     * Approval does not have to be implemented. This event should never be triggered as
     * the functions that emit this even are not legal, regulated calls.
     */
    event Approval(address indexed tokenOwner, address indexed spender, uint tokens);

    /**
     * allowance is not a legal, regulated call and must be implemented to always fail.
     */
    allowance(address tokenOwner, address spender) public constant returns (uint remaining);

    /**
     * approve is not a legal, regulated call and must be implemented to always fail.
     */
    approve(address spender, uint tokens) public returns (bool success);

    /**
     * Transfer securities.
     *
     * transferFrom must implement the onlyIssuerTransferAgent modifier to only allow the
     *     address of the issuer’s Registered Transfer Agent to transfer `ERC-1450`s.
     * transferFrom requires the _from address to have _value tokens.
     * transferFrom requires that the _to address must not be 0 because securities must
     *     not destroyed in this manner.
     */
    function transferFrom(address _from, address _to, uint256 _value) public
        onlyIssuerTransferAgent returns (bool);

    /**
     * Create new securities.
     *
     * mint must implement the onlyIssuerTransferAgent modifier to only allow the address
     *     of the issuer’s Registered Transfer Agent to mint `ERC-1450` tokens.
     * mint requires that the _to address must not be 0 because securities must
     *     not destroyed in this manner.
     * mint must add _value tokens to the _to address and increase the totalSupply by
     *     _value.
     * mint must emit the Transfer event.
     */
    function mint(address _to, uint256 _value) public onlyIssuerTransferAgent returns
        (bool);

    /**
     * Burn or destroy securities.
     *
     * burnFrom must implement the onlyIssuerTransferAgent modifier to only allow the
     *     address of the issuer’s Registered Transfer Agent to burn `ERC-1450`s.
     * burnFrom requires the _from address to have _value tokens.
     * burnFrom must subtract _value tokens from the _from address and decrease the
     *     totalSupply by _value.
     * burnFrom must emit the Transfer event.
     */
    function burnFrom(address _who, uint256 _value) public onlyIssuerTransferAgent returns
        (bool);
}
```

### Securities Exchange Commission Requirements
The SEC has very strict requirements as to the specific roles that are allowed to perform specific actions. Specifically, only the RTA may `mint` and `transferFrom` securities.

Implementers must maintain off-chain services and databases that record and track the Investor’s name, physical address, Ethereum address, and security ownership amount. The implementers and the SEC must be able to access the Investor’s private information on an as needed basis. Issuers and the RTA must be able to produce a current list of all Investors, including the names, addresses, and security ownership levels for every security at any given moment. Issuers and the RTA must be able to re-issue securities to Investors for a variety of regulated reasons.

Private Investor information must never be publicly exposed on a public blockchain. 

### Managing Investor Information
Special care and attention must be taken to ensure that the personally identifiable information of Investors is never exposed or revealed to the public.

### Issuers who lost access to their address or private keys
There is no recourse if the Issuer loses access to their address to an existing instance of their securities. Special care and efforts must be made by the Issuer to secure and safely store their address and associated private key. The Issuer can reassign ownership to another Issuer but not in the case where the Issuer loses their private key.

If the Issuer loses access, the Issuer’s securities must be rebuilt using off-chain services. The Issuer must create (and secure) a new address. The RTA can read the existing Issuer securities, and the RTA can `mint` Investor securities accordingly under a new `ERC-1450` smart contract.

### Registered Transfer Agents who lost access to their address or private keys
If the RTA loses access, the RTA can create a new Ethereum address, and the Issuer can execute the `setTransferAgent` function to reassign the RTA.

### Handling Investors (security owners) who lost access to their addresses or private keys
Investors may “lose” their credentials for a number of reasons: they simply “lost” their credentials, they were hacked or the victim of fraud, they committed securities-related fraud, or a life event (like death) occurred. Because the RTA manages the Issuer’s securities, the RTA may authorize ownership related changes of securities (as long as they are properly notarized and verified).

If an Investor (or, say, the Investor’s heir) loses their credentials, the Investor must go through a notarized process to notify the RTA of the situation and supply a new Investor address. From there, the RTA can `mint` the “lost” securities to the new Investor address and `burnFrom` the old Investor address (because the RTA knows all Investors’ addresses).

## Rationale
The are currently no token standards that facilitate compliance with SEC regulations. The closest token is [ERC-884 (Delaware General Corporations Law (DGCL) compatible share token)](/EIPs/EIPS/eip-884) which states that SEC requirements are out of scope. [EIP-1404 (Simple Restricted Token Standard)](https://github.com/ethereum/EIPs/issues/1404) does not go far enough to address SEC requirements around re-issuing securities to Investors.

## Backwards Compatibility
`ERC-1450` maintains compatibility with ERC-20 tokens with the following stipulations:
* `function allowance(address tokenOwner, address spender) public constant returns (uint remaining);`
  * Must be implemented to always fail because allowance is not a legal, regulated call for a security.
* `function transfer(address to, uint tokens) public returns (bool success);`
  * As the token holder initiates the transfer, must be implemented to always fail because transfer is not a legal, regulated call for a security.
* `function approve(address spender, uint tokens) public returns (bool success);`
  * Must be implemented to always fail because approve is not a legal, regulated call for a security
* `function transferFrom(address from, address to, uint tokens) public returns (bool success);`
  * Must be implemented so that only the Issuer’s RTA can perform this action
* `event Approval(address indexed tokenOwner, address indexed spender, uint tokens);`
  * Does not have to be implemented. Approval should never be called as the functions that emit this event must be implemented to always fail

## Test Cases
Test cases are available at [https://github.com/StartEngine/ldgr_smart_contracts/tree/master/test](https://github.com/StartEngine/ldgr_smart_contracts/tree/master/test).

## Implementations
A reference implementation is available at [https://github.com/StartEngine/ldgr_smart_contracts](https://github.com/StartEngine/ldgr_smart_contracts).

## Copyright Waiver
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 25 Sep 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1450</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1450</guid>
      </item>
    
      <item>
        <title>Node Discovery via DNS</title>
        <category>Standards Track/Networking</category>
        
          <comments>https://github.com/ethereum/devp2p/issues/50</comments>
        
        <description>## Abstract

This document describes a scheme for authenticated, updateable Ethereum node
lists retrievable via DNS.

## Motivation

Many Ethereum clients contain hard-coded bootstrap node lists. Updating those
lists requires a software update. The current lists are small, giving the client
little choice of initial entry point into the Ethereum network. We would like to
maintain larger node lists containing hundreds of nodes, and update them
regularly.

The scheme described here is a replacement for client bootstrap node lists with
equivalent security and many additional benefits. Large lists populated by
traversing the node discovery DHT can serve as a fallback option for nodes which
can&apos;t join the DHT due to restrictive network policy. DNS-based node lists may
also be useful to Ethereum peering providers because their customers can
configure the client to use the provider&apos;s list.

## Specification

A &apos;node list&apos; is a list of &apos;node records&apos; [as defined by EIP-778](/EIPs/EIPS/eip-778)
of arbitrary length. Lists
may refer to other lists using links. The entire list is signed using a
secp256k1 private key. The corresponding public key must be known to the client
in order to verify the list.

To refer to a DNS node list, clients use a URL with &apos;enrtree&apos; scheme. The URL
contains the DNS name on which the list can be found as well as the public key
that signed the list. The public key is contained in the username part of the
URL and is the base32 encoding (RFC-4648) of the compressed 32-byte binary public key.

Example:

    enrtree://AM5FCQLWIZX2QFPNJAP7VUERCCRNGRHWZG3YYHIUV7BVDQ5FDPRT2@nodes.example.org

This URL refers to a node list at the DNS name &apos;nodes.example.org&apos; and is signed
by the public key
`0x049f88229042fef9200246f49f94d9b77c4e954721442714e85850cb6d9e5daf2d880ea0e53cb3ac1a75f9923c2726a4f941f7d326781baa6380754a360de5c2b6`

### DNS Record Structure

The nodes in a list are encoded as a merkle tree for distribution via the DNS
protocol. Entries of the merkle tree are contained in DNS TXT records. The root
of the tree is a TXT record with the following content:

    enrtree-root:v1 e=&lt;enr-root&gt; l=&lt;link-root&gt; seq=&lt;sequence-number&gt; sig=&lt;signature&gt;

where

- `enr-root` and `link-root` refer to the root hashes of subtrees containing
  nodes and links subtrees.
- `sequence-number` is the tree&apos;s update sequence number, a decimal integer.
- `signature` is a 65-byte secp256k1 EC signature over the keccak256 hash of the
  record content, excluding the `sig=` part, encoded as URL-safe base64 (RFC-4648).

Further TXT records on subdomains map hashes to one of three entry types. The
subdomain name of any entry is the base32 encoding of the (abbreviated)
keccak256 hash of its text content.

- `enrtree-branch:&lt;h₁&gt;,&lt;h₂&gt;,...,&lt;hₙ&gt;` is an intermediate tree entry containing
  hashes of subtree entries.
- `enrtree://&lt;key&gt;@&lt;fqdn&gt;` is a leaf pointing to a different list located at
  another fully qualified domain name. Note that this format matches the URL
  encoding. This type of entry may only appear in the subtree pointed to by
  `link-root`.
- `enr:&lt;node-record&gt;` is a leaf containing a node record. The node record is
  encoded as a URL-safe base64 string. Note that this type of entry matches the
  canonical ENR text encoding. It may only appear in the `enr-root` subtree.

No particular ordering or structure is defined for the tree. Whenever the tree
is updated, its sequence number should increase. The content of any TXT record
should be small enough to fit into the 512 byte limit imposed on UDP DNS
packets. This limits the number of hashes that can be placed into an
`enrtree-branch` entry.

Example in zone file format:

    ; name                        ttl     class type  content
    @                             60      IN    TXT   enrtree-root:v1 e=JWXYDBPXYWG6FX3GMDIBFA6CJ4 l=C7HRFPF3BLGF3YR4DY5KX3SMBE seq=1 sig=o908WmNp7LibOfPsr4btQwatZJ5URBr2ZAuxvK4UWHlsB9sUOTJQaGAlLPVAhM__XJesCHxLISo94z5Z2a463gA
    C7HRFPF3BLGF3YR4DY5KX3SMBE    86900   IN    TXT   enrtree://AM5FCQLWIZX2QFPNJAP7VUERCCRNGRHWZG3YYHIUV7BVDQ5FDPRT2@morenodes.example.org
    JWXYDBPXYWG6FX3GMDIBFA6CJ4    86900   IN    TXT   enrtree-branch:2XS2367YHAXJFGLZHVAWLQD4ZY,H4FHT4B454P6UXFD7JCYQ5PWDY,MHTDO6TMUBRIA2XWG5LUDACK24
    2XS2367YHAXJFGLZHVAWLQD4ZY    86900   IN    TXT   enr:-HW4QOFzoVLaFJnNhbgMoDXPnOvcdVuj7pDpqRvh6BRDO68aVi5ZcjB3vzQRZH2IcLBGHzo8uUN3snqmgTiE56CH3AMBgmlkgnY0iXNlY3AyNTZrMaECC2_24YYkYHEgdzxlSNKQEnHhuNAbNlMlWJxrJxbAFvA
    H4FHT4B454P6UXFD7JCYQ5PWDY    86900   IN    TXT   enr:-HW4QAggRauloj2SDLtIHN1XBkvhFZ1vtf1raYQp9TBW2RD5EEawDzbtSmlXUfnaHcvwOizhVYLtr7e6vw7NAf6mTuoCgmlkgnY0iXNlY3AyNTZrMaECjrXI8TLNXU0f8cthpAMxEshUyQlK-AM0PW2wfrnacNI
    MHTDO6TMUBRIA2XWG5LUDACK24    86900   IN    TXT   enr:-HW4QLAYqmrwllBEnzWWs7I5Ev2IAs7x_dZlbYdRdMUx5EyKHDXp7AV5CkuPGUPdvbv1_Ms1CPfhcGCvSElSosZmyoqAgmlkgnY0iXNlY3AyNTZrMaECriawHKWdDRk2xeZkrOXBQ0dfMFLHY4eENZwdufn1S1o

### Client Protocol

To find nodes at a given DNS name, say &quot;mynodes.org&quot;:

1. Resolve the TXT record of the name and check whether it contains a valid
   &quot;enrtree-root=v1&quot; entry. Let&apos;s say the `enr-root` hash contained in the entry
   is &quot;CFZUWDU7JNQR4VTCZVOJZ5ROV4&quot;.
2. Verify the signature on the root against the known public key and check
   whether the sequence number is larger than or equal to any previous number
   seen for that name.
3. Resolve the TXT record of the hash subdomain, e.g.
   &quot;CFZUWDU7JNQR4VTCZVOJZ5ROV4.mynodes.org&quot; and verify whether the content
   matches the hash.
4. The next step depends on the entry type found:
   - for `enrtree-branch`: parse the list of hashes and continue resolving them (step 3).
   - for `enr`: decode, verify the node record and import it to local node storage.

During traversal, the client must track hashes and domains which are already
resolved to avoid going into an infinite loop. It&apos;s in the client&apos;s best
interest to traverse the tree in random order.

Client implementations should avoid downloading the entire tree at once during
normal operation. It&apos;s much better to request entries via DNS when-needed, i.e.
at the time when the client is looking for peers.

## Rationale

### Why DNS?

We have chosen DNS as the distribution medium because it is always available,
even under restrictive network conditions. The protocol provides low latency and
answers to DNS queries can be cached by intermediate resolvers. No custom server
software is needed. Node lists can be deployed to any DNS provider such as
CloudFlare DNS, dnsimple, Amazon Route 53 using their respective client
libraries.

### Why is this a merkle tree?

Being a merkle tree, any node list can be authenticated by a single signature on
the root. Hash subdomains protect the integrity of the list. At worst
intermediate resolvers can block access to the list or disallow updates to it,
but cannot corrupt its content. The sequence number prevents replacing the root
with an older version.

Synchronizing updates on the client side can be done incrementally, which
matters for large lists. Individual entries of the tree are small enough to fit
into a single UDP packet, ensuring compatibility with environments where only
basic UDP DNS is available. The tree format also works well with caching
resolvers: only the root of the tree needs a short TTL. Intermediate entries and
leaves can be cached for days.

### Why does the link subtree exist?

Links between lists enable federation and web-of-trust functionality. The
operator of a large list can delegate maintenance to other list providers. If
two node lists link to each other, users can use either list and get nodes from
both.

The link subtree is separate from the tree containing ENRs. This is done to
enable client implementations to sync these trees independently. A client
wanting to get as many nodes as possible will sync the link tree first and add
all linked names to the sync horizon.

## Security Considerations

Discovery via DNS is less secure than via DHT, because it relies on a trusted
party to publish the records regularly. The actor could easily eclipse
bootstrapping nodes by only publishing node records that it controls.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 26 Sep 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1459</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1459</guid>
      </item>
    
      <item>
        <title>Base Security Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-1462-base-security-token/1501</comments>
        
        <description>## Simple Summary

An extension to ERC-20 standard token that provides compliance with securities regulations and legal enforceability.

## Abstract

This EIP defines a minimal set of additions to the default token standard such as [ERC-20](/EIPs/EIPS/eip-20), that allows for compliance with domestic and international legal requirements. Such requirements include KYC (Know Your Customer) and AML (Anti Money Laundering) regulations, and the ability to lock tokens for an account, and restrict them from transfer due to a legal dispute. Also the ability to attach additional legal documentation, in order to set up a dual-binding relationship between the token and off-chain legal entities.

The scope of this standard is being kept as narrow as possible to avoid restricting potential use-cases of this base security token. Any additional functionality and limitations not defined in this standard may be enforced on per-project basis.

## Motivation

There are several security token standards that have been proposed recently. Examples include [ERC-1400](https://github.com/ethereum/EIPs/issues/1411), also [ERC-1450](https://eips.ethereum.org/EIPS/eip-1450). We have concerns about each of them, mostly because the scope of each of these EIPs contains many project-specific or market-specific details. Since many EIPs are coming from the respective backing companies, they capture many niche requirements that are excessive for a general case.

For instance, ERC-1411 uses dependency on [ERC-1410](https://github.com/ethereum/eips/issues/1410) but it falls out of the &quot;security tokens&quot; scope. Also its dependency on [ERC-777](/EIPs/EIPS/eip-777) will block the adoption for a quite period of time before ERC-777 is finalized, but the integration guidelines for existing ERC-20 workflows are not described in that EIP, yet. Another attempt to make a much simpler base standard [ERC-1404](https://github.com/ethereum/EIPs/issues/1404) is missing a few important points, specifically it doesn&apos;t provide enough granularity to distinguish between different ERC-20 transfer functions such as `transfer` and `transferFrom`. It also doesn&apos;t provide a way to bind legal documentation to the issued tokens.

What we propose in this EIP is a simple and very modular solution for creating a base security token for the widest possible scope of applications, so it can be used by other issuers to build upon. The issuers should be able to add more restrictions and policies to the token, using the functions and implementation proposed below, but they must not be limited in any way while using this ERC.

## Specification

The ERC-20 token provides the following basic features:

```solidity
contract ERC20 {
    function totalSupply() public view returns (uint256);
    function balanceOf(address who) public view returns (uint256);
    function transfer(address to, uint256 value) public returns (bool);
    function allowance(address owner, address spender) public view returns (uint256);
    function transferFrom(address from, address to, uint256 value) public returns (bool);
    function approve(address spender, uint256 value) public returns (bool);
    event Approval(address indexed owner, address indexed spender, uint256 value);
    event Transfer(address indexed from, address indexed to, uint256 value);
}
```

This will be extended as follows:

```solidity
interface BaseSecurityToken /* is ERC-20 */ {
    // Checking functions
    function checkTransferAllowed (address from, address to, uint256 value) public view returns (byte);
    function checkTransferFromAllowed (address from, address to, uint256 value) public view returns (byte);
    function checkMintAllowed (address to, uint256 value) public view returns (byte);
    function checkBurnAllowed (address from, uint256 value) public view returns (byte);

    // Documentation functions
    function attachDocument(bytes32 _name, string _uri, bytes32 _contentHash) external;
    function lookupDocument(bytes32 _name) external view returns (string, bytes32);
}
```

### Transfer Checking Functions

We introduce four new functions that should be used to check that the actions are allowed for the provided inputs. The implementation details of each function are left for the token issuer, it is the issuer&apos;s responsibility to add all necessary checks that will validate an operation in accordance with KYC/AML policies and legal requirements set for a specific token asset.

Each function must return a status code from the common set of Ethereum status codes (ESC), according to [ERC-1066](/EIPs/EIPS/eip-1066). Localization of these codes is out of the scope of this proposal and may be optionally solved by adopting [ERC-1444](/EIPs/EIPS/eip-1444) on the application level. If the operation is allowed by a checking function, the return status code must be `0x11` (Allowed) or an issuer-specific code with equivalent but more precise meaning. If the operation is not allowed by a checking function, the status must be `0x10` (Disallowed) or an issuer-specific code with equivalent but more precise meaning. Upon an internal error, the function must return the most relevant code from the general code table or an issuer-specific equivalent, example: `0xF0` (Off-Chain Failure).

**For [ERC-20](/EIPs/EIPS/eip-20) based tokens,**
* It is required that transfer function must be overridden with logic that checks the corresponding checkTransferAllowed return status code.
* It is required that `transferFrom` function must be overridden with logic that checks the corresponding `checkTransferFromAllowed` return status code.
* It is required that `approve` function must be overridden with logic that checks the corresponding `checkTransferFromAllowed` return status code.
* Other functions such as `mint` and `burn` must be overridden, if they exist in the token implementation, they should check `checkMintAllowed` and `checkBurnAllowed` status codes accordingly.

**For [ERC-777](/EIPs/EIPS/eip-777) based tokens,**
* It is required that `send` function must be overridden with logic that checks the corresponding return status codes:
    - `checkTransferAllowed` return status code, if transfer happens on behalf of the tokens owner;
    - `checkTransferFromAllowed` return status code, if transfer happens on behalf of an operator (i.e. delegated transfer).
* It is required that `burn` function must be overridden with logic that checks the corresponding `checkBurnAllowed` return status code.
* Other functions, such as `mint` must be overridden, if they exist in the token implementation, e.g. if the security token is mintable. `mint` function must call `checkMintAllowed` ad check it return status code.

For both cases,

* It is required for guaranteed compatibility with ERC-20 and ERC-777 wallets that each checking function returns `0x11` (Allowed) if not overridden with the issuer&apos;s custom logic.
* It is required that all overridden checking functions must revert if the action is not allowed or an error occurred, according to the returned status code.

Inside checker functions the logic is allowed to use any feature available on-chain: perform calls to registry contracts with whitelists/blacklists, use built-in checking logic that is defined on the same contract, or even run off-chain queries through an oracle.

### Documentation Functions

We also introduce two new functions that should be used for document management purposes. Function `attachDocument` adds a reference pointing to an off-chain document, with specified name, URI and contents hash. The hashing algorithm is not specified within this standard, but the resulting hash must not be longer than 32 bytes. Function `lookupDocument` gets the referenced document by its name.

* It is not required to use documentation functions, they are optional and provided as a part of a legal framework.
* It is required that if `attachDocument` function has been used, the document reference must have a unique name, overwriting the references under same name is not allowed. All implementations must check if the reference under the given name is already existing.

## Rationale

This EIP targets both ERC-20 and ERC-777 based tokens, although the most emphasis is given to ERC-20 due to its widespread adoption. However, this extension is designed to be compatible with the forthcoming ERC-777 standard, as well.

All checking functions are named with prefixes `check` since they return check status code, not booleans, because that is important to facilitate the debugging and tracing process. It is responsibility of the issuer to implement the logic that will handle the return codes appropriately. Some handlers will simply throw errors, other handlers would log information for future process mining. More rationale for status codes can be seen in [ERC-1066](/EIPs/EIPS/eip-1066).

We require two different transfer validation functions: `checkTransferAllowed` and `checkTransferFromAllowed` since the corresponding `transfer` and `transferFrom` are usually called in different contexts. Some token standards such as [ERC-1450](/EIPs/EIPS/eip-1450) explicitly disallow use of `transfer`, while allowing only `transferFrom`. There might be also different complex scenarios, where `transfer` and `transferFrom` should be treated differently. ERC-777 is relying on its own `send` for transferring tokens, so it is reasonable to switch between checker functions based on its call context. We decided to omit the `checkApprove` function since it would be used in exactly the same context as `checkTransferFromAllowed`. In many cases it is required not only regulate securities transfers, but also restrict burn and `mint` operations, and additional checker functions have been added for that.

The documentation functions that we propose here are a must-have tool to create dual-bindings with off-chain legal documents, a great example of this can be seen in [Neufund&apos;s Employee Incentive Options Plan](https://medium.com/@ZoeAdamovicz/37376fd0384a) legal framework that implements full legal enforceability: the smart contract refers to printed ESOP Terms &amp; Conditions Document, which itself refers back to smart contract. This is becoming a widely adopted practice even in cases where there are no legal requirements to reference the documents within the security token. However they&apos;re almost always required, and it&apos;s a good way to attach useful documentation of various types.

## Backwards Compatibility

This EIP is fully backwards compatible as its implementation extends the functionality of ERC-20 and ERC-777 tokens.

## Implementation

* https://github.com/AtlantPlatform/BaseSecurityToken

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 01 Oct 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1462</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1462</guid>
      </item>
    
      <item>
        <title>Smart Contract Weakness Classification (SWC)</title>
        <category>Informational/</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1469</comments>
        
        <description>## Simple Summary

This EIP proposes a classification scheme for security weaknesses in Ethereum smart contracts. 

## Abstract

The SWC is a smart contract specific software weakness classification scheme for developers, tool vendors and security practitioners. The SWC is loosely aligned to the terminologies and structure used in the [Common Weakness Enumeration - CWE](https://cwe.mitre.org) scheme while overlaying a wide range of weakness variants that are specific to smart contracts.

The goals of the SWC scheme are as follows:

- Provide a straightforward way to classify weaknesses in smart contract systems.
- Provide a straightforward way to identify the weakness(es) that lead to a vulnerability in a smart contract system. 
- Define a common language for describing weaknesses in smart contract systems&apos; architecture, design and code.
- Train and increase the performance of smart contract security analysis tools.


## Motivation

In the software security industry, it is a widely accepted practice to use a common terminology and to classify security related bugs and errors with a standardized scheme. While this has not stopped vulnerabilities from appearing in software, it has helped communities focusing on web applications, network protocols, IOT devices and various other fields to educate users and developers to understand the nature of security related issues in their software. It has also allowed the security community to quickly understand vulnerabilities that occur in production systems to perform root cause analysis or triage findings from various security analysis sources. In recent years various organizations and companies also published vulnerability data to find the most widespread security issues based on collected vulnerability data. Two examples that are widely used and referred to are the [SANS TOP 25 Most Dangerous Software Errors](https://www.sans.org/top25-software-errors) and the [OWASP TOP 10](https://www.owasp.org/index.php/Top_10-2017_Top_10). None of those publications would have been possible without a common classification scheme. 

At present no such weakness classification scheme exists for weaknesses specific to Ethereum Smart Contracts. Common language and awareness of security weaknesses is mostly derived from academic papers, best practice guides and published articles. Findings from audit reports and security tool analysis add to the wide range of terminologies that is used to describe the discovered weaknesses. It is often time consuming to understand the technical root cause and the risk associated to findings from different sources even for security experts. 

## Rationale 

While recognizing the current gap, the SWC does not aim to reinvent the wheel in regards to classification of security weaknesses. It rather proposes to build on top of what has worked well in other parts of the software security community -  specifically the Common Weakness Enumeration (CWE), a list of software vulnerability types that stands out in terms of adoption and breadth of coverage. While CWE does not describe any weaknesses specific to smart contracts, it does describe related weaknesses at higher abstraction layers. This EIP proposes to create smart contract specific variants while linking back to the larger spectrum of software errors and mistakes listed in the CWE that different platforms and technologies have in common. 

## Specification

Before discussing the SWC specification it is important to describe the terminology used:

- Weakness: A software error or mistake that in the right conditions can by itself or coupled with other weaknesses lead to a vulnerability. 
- Vulnerability: A weakness or multiple weaknesses which directly or indirectly lead to an undesirable state in a smart contract system. 
- Variant: A specific weakness that is described in a very low detail specific to Ethereum smart contracts. Each variant is assigned a unique SWC ID.
- Relationships: CWE has a wide range of _Base_ and _Class_ types that group weaknesses on higher abstraction layers. The CWE uses _Relationships_ to link SWC smart contract weakness variants to existing _Base_ or _Class_ CWE types. _Relationships_ are  used to provide context on how SWCs are linked to the wider group of software security weaknesses and to be able to generate useful visualisations and insights through issue data sets. In its current revision it is proposed to link a SWC to its closest parent in the CWE. 
- SWC ID: A numeric identifier linked to a variant (e.g. SWC-101).
- Test Case: A test case constitutes a micro-sample or real-world smart contract that demonstrates concrete instances of one or multiple SWC variants. Test cases serve as the basis for meaningful weakness classification and are useful to security analysis tool developers. 

The SWC in its most basic form links a numeric identifier to a weakness variant. For example the identifier _SWC-101_ is linked to the _Integer Overflow and Underflow_ variant. While a list with the weakness title and a unique id is useful by itself, it would also be ambiguous without further details. Therefore the SWC recommends to add a definition and test cases to any weakness variant.

**SWC definition**  

A SWC definition is formatted in markdown to allow good readability and tools to process them easily. It consists of the following attributes. 

- Title: A name for the weakness that points to the technical root cause.
- Relationships: Links a CWE _Base_ or _Class_ type to its CWE variant. The _Integer Overflow and Underflow_ variant for example is linked to [CWE-682 - Incorrect Calculation](https://cwe.mitre.org/data/definitions/682.html).
- Description: Describes the nature and potential impact of the weakness on the contract system. 
- Remediation: Describes ways on how to fix the weakness. 
- References: Links to external references that contain relevant additional information on the weakness.

**Test cases**

Test cases include crafted as well as real-world samples of vulnerable smart contracts. A single test case consists of three components:

1. Source code of a smart contract sample; e.g. Solidity, Vyper, etc.
2. Compiled asset from an EVM compiler in machine readable format; e.g. JSON or ethPM.
3. Test result configuration that describes which and how many instances of a weakness variant can be found in a given sample. The YAML schema for the proposed test case configuration is listed below.

```YAML
title: SWC config
type: object
required:
- description
- issues
properties:
  description:
    type: string
  issues:
    title: Issues
    type: array
    items:
      title: Issue
      type: object
      required:
      - id
      - count
      properties:
        id:
          type: string
        count:
          type: number
        locations:
          items:
            bytecode_offsets:
              type: object
            line_numbers:
              type: object
```

## Implementation

The Smart Contract Weakness Classification registry located in this [GitHub repository](https://github.com/SmartContractSecurity/SWC-registry) uses the SWC scheme proposed in this EIP. A GitHub Pages rendered version is also available [here](https://smartcontractsecurity.github.io/SWC-registry/).

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 18 Sep 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1470</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1470</guid>
      </item>
    
      <item>
        <title>Remote procedure call specification</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-remote-procedure-call-specification/1537</comments>
        
        <description>## Simple Summary

This proposal defines a standard set of remote procedure call methods that an Ethereum node should implement.

## Abstract

Nodes created by the current generation of Ethereum clients expose inconsistent and incompatible remote procedure call (RPC) methods because no formal Ethereum RPC specification exists. This proposal standardizes such a specification to provide developers with a predictable Ethereum RPC interface regardless of underlying node implementation.

## Specification

### Concepts

#### RFC-2119

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;,  &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC-2119](https://www.ietf.org/rfc/rfc2119.txt).

#### JSON-RPC

Communication with Ethereum nodes is accomplished using [JSON-RPC](https://www.jsonrpc.org/specification), a stateless, lightweight [remote procedure call](https://en.wikipedia.org/wiki/Remote_procedure_call) protocol that uses [JSON](http://www.json.org/) as its data format. Ethereum RPC methods **MUST** be called using [JSON-RPC request objects](https://www.jsonrpc.org/specification#request_object) and **MUST** respond with [JSON-RPC response objects](https://www.jsonrpc.org/specification#response_object).

#### Error codes

If an Ethereum RPC method encounters an error, the `error` member included on the response object **MUST** be an object containing a `code` member and descriptive `message` member. The following list contains all possible error codes and associated messages:

|Code|Message|Meaning|Category|
|-|-|-|-|
|-32700|Parse error|Invalid JSON|standard|
|-32600|Invalid request|JSON is not a valid request object|standard|
|-32601|Method not found|Method does not exist|standard|
|-32602|Invalid params|Invalid method parameters|standard|
|-32603|Internal error|Internal JSON-RPC error|standard|
|-32000|Invalid input|Missing or invalid parameters|non-standard|
|-32001|Resource not found|Requested resource not found|non-standard|
|-32002|Resource unavailable|Requested resource not available|non-standard|
|-32003|Transaction rejected|Transaction creation failed|non-standard|
|-32004|Method not supported|Method is not implemented|non-standard|
|-32005|Limit exceeded|Request exceeds defined limit|non-standard|
|-32006|JSON-RPC version not supported|Version of JSON-RPC protocol is not supported|non-standard|

Example error response:

```sh
{
    &quot;id&quot;: 1337
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;error&quot;: {
        &quot;code&quot;: -32003,
        &quot;message&quot;: &quot;Transaction rejected&quot;
    }
}
```

#### Value encoding

Specific types of values passed to and returned from Ethereum RPC methods require special encoding:

##### `Quantity`

- A `Quantity` value **MUST** be hex-encoded.
- A `Quantity` value **MUST** be &quot;0x&quot;-prefixed.
- A `Quantity` value **MUST** be expressed using the fewest possible hex digits per byte.
- A `Quantity` value **MUST** express zero as &quot;0x0&quot;.

Examples `Quantity` values:

|Value|Valid|Reason|
|-|-|-|
|0x|`invalid`|empty not a valid quantity|
|0x0|`valid`|interpreted as a quantity of zero|
|0x00|`invalid`|leading zeroes not allowed|
|0x41|`valid`|interpreted as a quantity of 65|
|0x400|`valid`|interpreted as a quantity of 1024|
|0x0400|`invalid`|leading zeroes not allowed|
|ff|`invalid`|values must be prefixed|

##### `Block Identifier`

The RPC methods below take a default block identifier as a parameter.
- `eth_getBalance`
- `eth_getStorageAt`
- `eth_getTransactionCount`
- `eth_getCode`
- `eth_call`
- `eth_getProof`

Since there is no way to clearly distinguish between a `Data` parameter and a `Quantity` parameter, [EIP-1898](/EIPs/EIPS/eip-1898) provides a format to specify a block either using the block hash or block number. The block identifier is a JSON `object` with the following fields:

|Property|Type|Description|
|-|-|-|
|`[blockNumber]`|{[`Quantity`](#quantity)}|The block in the canonical chain with this number|
|OR `[blockHash]`|{[`Data`](#data)}|The block uniquely identified by this hash. The `blockNumber` and `blockHash` properties are mutually exclusive; exactly one of them must be set.|
|`requireCanonical`|{`boolean`}|(optional) Whether or not to throw an error if the block is not in the canonical chain as described below. Only allowed in conjunction with the `blockHash` tag. Defaults to `false`.|

If the block is not found, the callee SHOULD raise a JSON-RPC error (the recommended error code is `-32001: Resource not found`. If the tag is `blockHash` and `requireCanonical` is `true`, the callee SHOULD additionally raise a JSON-RPC error if the block is not in the canonical chain (the recommended error code is `-32000: Invalid input` and in any case should be different than the error code for the block not found case so that the caller can distinguish the cases). The block-not-found check SHOULD take precedence over the block-is-canonical check, so that if the block is not found the callee raises block-not-found rather than block-not-canonical.

##### `Data`

- A `Data` value **MUST** be hex-encoded.
- A `Data` value **MUST** be &quot;0x&quot;-prefixed.
- A `Data` value **MUST** be expressed using two hex digits per byte.

Examples `Data` values:

|Value|Valid|Reason|
|-|-|-|
|0x|`valid`|interpreted as empty data|
|0x0|`invalid`|each byte must be represented using two hex digits|
|0x00|`valid`|interpreted as a single zero byte|
|0x41|`true`|interpreted as a data value of 65|
|0x004200|`true`|interpreted as a data value of 16896|
|0xf0f0f|`false`|bytes require two hex digits|
|004200|`false`|values must be prefixed|

##### Proposing changes

New Ethereum RPC methods and changes to existing methods **MUST** be proposed via the traditional EIP process. This allows for community consensus around new method implementations and proposed method modifications. RPC method proposals **MUST** reach &quot;draft&quot; status before being added to this proposal and the official Ethereum RPC specification defined herein.

### Methods

#### web3_clientVersion

##### Description

Returns the version of the current client

##### Parameters

_(none)_

##### Returns

{`string`} - client version

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;web3_clientVersion&quot;,
    &quot;params&quot;: [],
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;Mist/v0.9.3/darwin/go1.4.1&quot;
}
```
---

#### web3_sha3

##### Description

Hashes data using the Keccak-256 algorithm

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{[`Data`](#data)}|data to hash|

##### Returns

{[`Data`](#data)} - Keccak-256 hash of the given data

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;web3_sha3&quot;,
    &quot;params&quot;: [&quot;0x68656c6c6f20776f726c64&quot;]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;0xc94770007dda54cF92009BFF0dE90c06F603a09f&quot;
}
```
---

#### net_listening

##### Description

Determines if this client is listening for new network connections

##### Parameters

_(none)_

##### Returns

{`boolean`} - `true` if listening is active or `false` if listening is not active

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;net_listening&quot;,
    &quot;params&quot;: []
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: true
}
```
---

#### net_peerCount

##### Description

Returns the number of peers currently connected to this client

##### Parameters

_(none)_

##### Returns

{[`Quantity`](#quantity)} - number of connected peers

##### Example
```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;net_peerCount&quot;,
    &quot;params&quot;: []
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;0x2&quot;
}
```
---

#### net_version

##### Description

Returns the chain ID associated with the current network

##### Parameters

_(none)_

##### Returns

{`string`} - chain ID associated with the current network

Common chain IDs:

- `&quot;1&quot;` -  Ethereum mainnet
- `&quot;3&quot;` - Ropsten testnet
- `&quot;4&quot;` - Rinkeby testnet
- `&quot;42&quot;` - Kovan testnet

**Note:** See EIP-155 for a [complete list](/EIPs/EIPS/eip-155#list-of-chain-ids) of possible chain IDs.

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;net_version&quot;,
    &quot;params&quot;: []
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;3&quot;
}
```
---

#### eth_accounts

##### Description

Returns a list of addresses owned by this client

##### Parameters

_(none)_

##### Returns

{[`Data[]`](#data)} - array of addresses

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_accounts&quot;,
    &quot;params&quot;: []
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: [&quot;0xc94770007dda54cF92009BFF0dE90c06F603a09f&quot;]
}
```
---

#### eth_blockNumber

##### Description

Returns the number of the most recent block seen by this client

##### Parameters

_(none)_

##### Returns

{[`Quantity`](#quantity)} - number of the latest block

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_blockNumber&quot;,
    &quot;params&quot;: []
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;0xc94&quot;
}
```
---

#### eth_call

##### Description

Executes a new message call immediately without submitting a transaction to the network

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{`object`}|@property {[`Data`](#data)} `[from]` - transaction sender&lt;br/&gt;@property {[`Data`](#data)} `to` - transaction recipient or `null` if deploying a contract&lt;br/&gt;@property {[`Quantity`](#quantity)} `[gas]` - gas provided for transaction execution&lt;br/&gt;@property {[`Quantity`](#quantity)} `[gasPrice]` - price in wei of each gas used&lt;br/&gt;@property {[`Quantity`](#quantity)} `[value]` - value in wei sent with this transaction&lt;br/&gt;@property {[`Data`](#data)} `[data]` - contract code or a hashed method call with encoded args|
|2|{[`Quantity`](#quantity)\|`string`\|[`Block Identifier`](#block-identifier)}|block number, or one of `&quot;latest&quot;`, `&quot;earliest&quot;` or `&quot;pending&quot;`, or a block identifier as described in [`Block Identifier`](#block-identifier)|

##### Returns

{[`Data`](#data)} - return value of executed contract

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_call&quot;,
    &quot;params&quot;: [{
        &quot;data&quot;: &quot;0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675&quot;,
        &quot;from&quot;: &quot;0xb60e8dd61c5d32be8058bb8eb970870f07233155&quot;,
        &quot;gas&quot;: &quot;0x76c0&quot;,
        &quot;gasPrice&quot;: &quot;0x9184e72a000&quot;,
        &quot;to&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
        &quot;value&quot;: &quot;0x9184e72a&quot;
    }]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;0x&quot;
}
```
---

#### eth_coinbase

##### Description

Returns the coinbase address for this client

##### Parameters

_(none)_

##### Returns

{[`Data`](#data)} - coinbase address

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_coinbase&quot;,
    &quot;params&quot;: []
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;0xc94770007dda54cF92009BFF0dE90c06F603a09f&quot;
}
```
---

#### eth_estimateGas

##### Description

Estimates the gas necessary to complete a transaction without submitting it to the network

**Note:** The resulting gas estimation may be significantly more than the amount of gas actually used by the transaction. This is due to a variety of reasons including EVM mechanics and node performance.

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{`object`}|@property {[`Data`](#data)} `[from]` - transaction sender&lt;br/&gt;@property {[`Data`](#data)} `[to]` - transaction recipient&lt;br/&gt;@property {[`Quantity`](#quantity)} `[gas]` - gas provided for transaction execution&lt;br/&gt;@property {[`Quantity`](#quantity)} `[gasPrice]` - price in wei of each gas used&lt;br/&gt;@property {[`Quantity`](#quantity)} `[value]` - value in wei sent with this transaction&lt;br/&gt;@property {[`Data`](#data)} `[data]` - contract code or a hashed method call with encoded args|
|2|{[`Quantity`](#quantity)\|`string`}|block number, or one of `&quot;latest&quot;`, `&quot;earliest&quot;` or `&quot;pending&quot;`|

##### Returns

{[`Quantity`](#quantity)} - amount of gas required by transaction

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_estimateGas&quot;,
    &quot;params&quot;: [{
        &quot;data&quot;: &quot;0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675&quot;,
        &quot;from&quot;: &quot;0xb60e8dd61c5d32be8058bb8eb970870f07233155&quot;,
        &quot;gas&quot;: &quot;0x76c0&quot;,
        &quot;gasPrice&quot;: &quot;0x9184e72a000&quot;,
        &quot;to&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
        &quot;value&quot;: &quot;0x9184e72a&quot;
    }]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;0x5208&quot;
}
```
---

#### eth_gasPrice

##### Description

Returns the current price of gas expressed in wei

##### Parameters

_(none)_

##### Returns

{[`Quantity`](#quantity)} - current gas price in wei

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_gasPrice&quot;,
    &quot;params&quot;: []
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;0x09184e72a000&quot;
}
```
---

#### eth_getBalance

##### Description

Returns the balance of an address in wei

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{[`Data`](#data)}|address to query for balance|
|2|{[`Quantity`](#quantity)\|`string`\|[`Block Identifier`](#block-identifier)}|block number, or one of `&quot;latest&quot;`, `&quot;earliest&quot;` or `&quot;pending&quot;`, or a block identifier as described in [`Block Identifier`](#block-identifier)|

##### Returns

{[`Quantity`](#quantity)} - balance of the provided account in wei

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_getBalance&quot;,
    &quot;params&quot;: [&quot;0xc94770007dda54cF92009BFF0dE90c06F603a09f&quot;, &quot;latest&quot;]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;0x0234c8a3397aab58&quot;
}
```
---

#### eth_getBlockByHash

##### Description

Returns information about a block specified by hash

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{[`Data`](#data)}|hash of a block|
|2|{`boolean`}|`true` will pull full transaction objects, `false` will pull transaction hashes|

##### Returns

{`null|object`} - `null` if no block is found, otherwise a block object with the following members:

- {[`Data`](#data)} `extraData` - &quot;extra data&quot; field of this block
- {[`Data`](#data)} `hash` - block hash or `null` if pending
- {[`Data`](#data)} `logsBloom` - logs bloom filter or `null` if pending
- {[`Data`](#data)} `miner` - address that received this block&apos;s mining rewards
- {[`Data`](#data)} `nonce` - proof-of-work hash or `null` if pending
- {[`Data`](#data)} `parentHash` - parent block hash
- {[`Data`](#data)} `receiptsRoot` -root of this block&apos;s receipts trie
- {[`Data`](#data)} `sha3Uncles` - SHA3 of the uncles data in this block
- {[`Data`](#data)} `stateRoot` - root of this block&apos;s final state trie
- {[`Data`](#data)} `transactionsRoot` - root of this block&apos;s transaction trie
- {[`Quantity`](#quantity)} `difficulty` - difficulty for this block
- {[`Quantity`](#quantity)} `gasLimit` - maximum gas allowed in this block
- {[`Quantity`](#quantity)} `gasUsed` - total used gas by all transactions in this block
- {[`Quantity`](#quantity)} `number` - block number or `null` if pending
- {[`Quantity`](#quantity)} `size` - size of this block in bytes
- {[`Quantity`](#quantity)} `timestamp` - unix timestamp of when this block was collated
- {[`Quantity`](#quantity)} `totalDifficulty` - total difficulty of the chain until this block
- {`Array&lt;Transaction&gt;`} `transactions` - list of transaction objects or hashes
- {`Array&lt;Transaction&gt;`} `uncles` - list of uncle hashes

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_getBlockByHash&quot;,
    &quot;params&quot;:[&quot;0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;, true]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: {
        &quot;difficulty&quot;: &quot;0x027f07&quot;,
        &quot;extraData&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
        &quot;gasLimit&quot;: &quot;0x9f759&quot;,
        &quot;gasUsed&quot;: &quot;0x9f759&quot;,
        &quot;hash&quot;: &quot;0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;,
        &quot;logsBloom&quot;: &quot;0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;,
        &quot;miner&quot;: &quot;0x4e65fda2159562a496f9f3522f89122a3088497a&quot;,
        &quot;nonce&quot;: &quot;0xe04d296d2460cfb8472af2c5fd05b5a214109c25688d3704aed5484f9a7792f2&quot;,
        &quot;number&quot;: &quot;0x1b4&quot;,
        &quot;parentHash&quot;: &quot;0x9646252be9520f6e71339a8df9c55e4d7619deeb018d2a3f2d21fc165dde5eb5&quot;,
        &quot;sha3Uncles&quot;: &quot;0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347&quot;,
        &quot;size&quot;:  &quot;0x027f07&quot;,
        &quot;stateRoot&quot;: &quot;0xd5855eb08b3387c0af375e9cdb6acfc05eb8f519e419b874b6ff2ffda7ed1dff&quot;,
        &quot;timestamp&quot;: &quot;0x54e34e8e&quot;
        &quot;totalDifficulty&quot;:  &quot;0x027f07&quot;,
        &quot;transactions&quot;: []
        &quot;transactionsRoot&quot;: &quot;0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421&quot;,
        &quot;uncles&quot;: [&quot;0x1606e5...&quot;, &quot;0xd5145a9...&quot;]
    }
}
```
---

#### eth_getBlockByNumber

##### Description

Returns information about a block specified by number

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{[`Quantity`](#quantity)\|`string`}|block number, or one of `&quot;latest&quot;`, `&quot;earliest&quot;` or `&quot;pending&quot;`|
|2|{`boolean`}|`true` will pull full transaction objects, `false` will pull transaction hashes|

##### Returns

{`null|object`} - `null` if no block is found, otherwise a block object with the following members:

- {[`Data`](#data)} `extraData` - &quot;extra data&quot; field of this block
- {[`Data`](#data)} `hash` - block hash or `null` if pending
- {[`Data`](#data)} `logsBloom` - logs bloom filter or `null` if pending
- {[`Data`](#data)} `miner` - address that received this block&apos;s mining rewards
- {[`Data`](#data)} `nonce` - proof-of-work hash or `null` if pending
- {[`Data`](#data)} `parentHash` - parent block hash
- {[`Data`](#data)} `receiptsRoot` -root of this block&apos;s receipts trie
- {[`Data`](#data)} `sha3Uncles` - SHA3 of the uncles data in this block
- {[`Data`](#data)} `stateRoot` - root of this block&apos;s final state trie
- {[`Data`](#data)} `transactionsRoot` - root of this block&apos;s transaction trie
- {[`Quantity`](#quantity)} `difficulty` - difficulty for this block
- {[`Quantity`](#quantity)} `gasLimit` - maximum gas allowed in this block
- {[`Quantity`](#quantity)} `gasUsed` - total used gas by all transactions in this block
- {[`Quantity`](#quantity)} `number` - block number or `null` if pending
- {[`Quantity`](#quantity)} `size` - size of this block in bytes
- {[`Quantity`](#quantity)} `timestamp` - unix timestamp of when this block was collated
- {[`Quantity`](#quantity)} `totalDifficulty` - total difficulty of the chain until this block
- {`Array&lt;Transaction&gt;`} `transactions` - list of transaction objects or hashes
- {`Array&lt;Transaction&gt;`} `uncles` - list of uncle hashes

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_getBlockByNumber&quot;,
    &quot;params&quot;:[&quot;0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;, true]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: {
        &quot;difficulty&quot;: &quot;0x027f07&quot;,
        &quot;extraData&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
        &quot;gasLimit&quot;: &quot;0x9f759&quot;,
        &quot;gasUsed&quot;: &quot;0x9f759&quot;,
        &quot;hash&quot;: &quot;0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;,
        &quot;logsBloom&quot;: &quot;0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;,
        &quot;miner&quot;: &quot;0x4e65fda2159562a496f9f3522f89122a3088497a&quot;,
        &quot;nonce&quot;: &quot;0xe04d296d2460cfb8472af2c5fd05b5a214109c25688d3704aed5484f9a7792f2&quot;,
        &quot;number&quot;: &quot;0x1b4&quot;,
        &quot;parentHash&quot;: &quot;0x9646252be9520f6e71339a8df9c55e4d7619deeb018d2a3f2d21fc165dde5eb5&quot;,
        &quot;sha3Uncles&quot;: &quot;0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347&quot;,
        &quot;size&quot;:  &quot;0x027f07&quot;,
        &quot;stateRoot&quot;: &quot;0xd5855eb08b3387c0af375e9cdb6acfc05eb8f519e419b874b6ff2ffda7ed1dff&quot;,
        &quot;timestamp&quot;: &quot;0x54e34e8e&quot;
        &quot;totalDifficulty&quot;:  &quot;0x027f07&quot;,
        &quot;transactions&quot;: []
        &quot;transactionsRoot&quot;: &quot;0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421&quot;,
        &quot;uncles&quot;: [&quot;0x1606e5...&quot;, &quot;0xd5145a9...&quot;]
    }
}
```
---

#### eth_getBlockTransactionCountByHash

##### Description

Returns the number of transactions in a block specified by block hash

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{[`Data`](#data)}|hash of a block|

##### Returns

{[`Quantity`](#quantity)} - number of transactions in the specified block

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_getBlockTransactionCountByHash&quot;,
    &quot;params&quot;: [&quot;0xc94770007dda54cF92009BFF0dE90c06F603a09f&quot;]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;0xc&quot;
}
```
---

#### eth_getBlockTransactionCountByNumber

##### Description

Returns the number of transactions in a block specified by block number

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{[`Quantity`](#quantity)\|`string`}|block number, or one of `&quot;latest&quot;`, `&quot;earliest&quot;` or `&quot;pending&quot;`|

##### Returns

{[`Quantity`](#quantity)} - number of transactions in the specified block

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_getBlockTransactionCountByNumber&quot;,
    &quot;params&quot;: [&quot;0xe8&quot;]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;0xa&quot;
}
```
---

#### eth_getCode

##### Description

Returns the contract code stored at a given address

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{[`Data`](#data)}|address to query for code|
|2|{[`Quantity`](#quantity)\|`string`\|[`Block Identifier`](#block-identifier)}|block number, or one of `&quot;latest&quot;`, `&quot;earliest&quot;` or `&quot;pending&quot;`, or a block identifier as described in [`Block Identifier`](#block-identifier)|

##### Returns

{[`Data`](#data)} - code from the specified address

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_getCode&quot;,
    &quot;params&quot;: [&quot;0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b&quot;, &quot;0x2&quot;]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;0x600160008035811a818181146012578301005b601b6001356025565b8060005260206000f25b600060078202905091905056&quot;
}
```
---

#### eth_getFilterChanges

##### Description

Returns a list of all logs based on filter ID since the last log retrieval

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{[`Quantity`](#quantity)}|ID of the filter|

##### Returns

{`Array&lt;Log&gt;`} - array of log objects with the following members:

- {[`Data`](#data)} `address` - address from which this log originated
- {[`Data`](#data)} `blockHash` - hash of block containing this log or `null` if pending
- {[`Data`](#data)} `data` - contains the non-indexed arguments of the log
- {[`Data`](#data)} `transactionHash` - hash of the transaction that created this log or `null` if pending
- {[`Quantity`](#quantity)} `blockNumber` - number of block containing this log or `null` if pending
- {[`Quantity`](#quantity)} `logIndex` - index of this log within its block or `null` if pending
- {[`Quantity`](#quantity)} `transactionIndex` - index of the transaction that created this log or `null` if pending
- {[`Data[]`](#data)} `topics` - list of order-dependent topics
- {`boolean`} `removed` - `true` if this filter has been destroyed and is invalid

**Note:** The return value of `eth_getFilterChanges` when retrieving logs from `eth_newBlockFilter` and `eth_newPendingTransactionFilter` filters will be an array of hashes, not an array of Log objects.

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_getFilterChanges&quot;,
    &quot;params&quot;: [&quot;0x16&quot;]
}&apos; &lt;url&gt;

# Response
{
   &quot;id&quot;: 1337,
   &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: [{
        &quot;address&quot;: &quot;0x16c5785ac562ff41e2dcfdf829c5a142f1fccd7d&quot;,
        &quot;blockHash&quot;: &quot;0x8216c5785ac562ff41e2dcfdf5785ac562ff41e2dcfdf829c5a142f1fccd7d&quot;,
        &quot;blockNumber&quot;:&quot;0x1b4&quot;,
        &quot;data&quot;:&quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
        &quot;logIndex&quot;: &quot;0x1&quot;,
        &quot;topics&quot;: [],
        &quot;transactionHash&quot;:  &quot;0xdf829c5a142f1fccd7d8216c5785ac562ff41e2dcfdf5785ac562ff41e2dcf&quot;,
        &quot;transactionIndex&quot;: &quot;0x0&quot;
   }]
}
```
---

#### eth_getFilterLogs

##### Description

Returns a list of all logs based on filter ID

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{[`Quantity`](#quantity)}|ID of the filter|

##### Returns

{`Array&lt;Log&gt;`} - array of log objects with the following members:

- {[`Data`](#data)} address - address from which this log originated
- {[`Data`](#data)} blockHash - hash of block containing this log or `null` if pending
- {[`Data`](#data)} data - contains the non-indexed arguments of the log
- {[`Data`](#data)} transactionHash - hash of the transaction that created this log or `null` if pending
- {[`Quantity`](#quantity)} blockNumber - number of block containing this log or `null` if pending
- {[`Quantity`](#quantity)} logIndex - index of this log within its block or `null` if pending
- {[`Quantity`](#quantity)} transactionIndex - index of the transaction that created this log or `null` if pending
- {`Array&lt;Data&gt;`} topics - list of order-dependent topics
- {`boolean`} removed - `true` if this filter has been destroyed and is invalid

**Note:** The return value of `eth_getFilterLogs` when retrieving logs from `eth_newBlockFilter` and `eth_newPendingTransactionFilter` filters will be an array of hashes, not an array of Log objects.

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_getFilterLogs&quot;,
    &quot;params&quot;: [&quot;0x16&quot;]
}&apos; &lt;url&gt;

# Response
{
   &quot;id&quot;: 1337,
   &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: [{
        &quot;address&quot;: &quot;0x16c5785ac562ff41e2dcfdf829c5a142f1fccd7d&quot;,
        &quot;blockHash&quot;: &quot;0x8216c5785ac562ff41e2dcfdf5785ac562ff41e2dcfdf829c5a142f1fccd7d&quot;,
        &quot;blockNumber&quot;:&quot;0x1b4&quot;,
        &quot;data&quot;:&quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
        &quot;logIndex&quot;: &quot;0x1&quot;,
        &quot;topics&quot;: [],
        &quot;transactionHash&quot;:  &quot;0xdf829c5a142f1fccd7d8216c5785ac562ff41e2dcfdf5785ac562ff41e2dcf&quot;,
        &quot;transactionIndex&quot;: &quot;0x0&quot;
   }]
}
```
---

#### eth_getLogs

##### Description

Returns a list of all logs based on a filter object

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{`object`}|@property {[`Quantity`](#quantity)\|`string`} `[fromBlock]` - block number, or one of `&quot;latest&quot;`, `&quot;earliest&quot;` or `&quot;pending&quot;`&lt;br/&gt;@property {[`Quantity`](#quantity)\|`string`} `[toBlock]` - block number, or one of `&quot;latest&quot;`, `&quot;earliest&quot;` or `&quot;pending&quot;`&lt;br/&gt;@property {[`Data`](#data)\|[`Data[]`](#data)} `[address]` - contract address or a list of addresses from which logs should originate&lt;br/&gt;@property {[`Data[]`](#data)} `[topics]` - list of order-dependent topics&lt;br/&gt;@property {[`Data`](#data)} `[blockhash]` - restrict logs to a block by hash|

**Note:** If `blockhash` is passed, neither `fromBlock` nor `toBlock` are allowed or respected.

##### Returns

{`Array&lt;Log&gt;`} - array of log objects with the following members:

- {[`Data`](#data)} `address` - address from which this log originated
- {[`Data`](#data)} `blockHash` - hash of block containing this log or `null` if pending
- {[`Data`](#data)} `data` - contains the non-indexed arguments of the log
- {[`Data`](#data)} `transactionHash` - hash of the transaction that created this log or `null` if pending
- {[`Quantity`](#quantity)} `blockNumber` - number of block containing this log or `null` if pending
- {[`Quantity`](#quantity)} `logIndex` - index of this log within its block or `null` if pending
- {[`Quantity`](#quantity)} `transactionIndex` - index of the transaction that created this log or `null` if pending
- {[`Data`](#data)} `topics` - list of order-dependent topics
- {`boolean`} `removed` - `true` if this filter has been destroyed and is invalid

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_getLogs&quot;,
    &quot;params&quot;: [{
        &quot;topics&quot;:[&quot;0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b&quot;]
    }]
}&apos; &lt;url&gt;

# Response
{
   &quot;id&quot;: 1337,
   &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: [{
        &quot;address&quot;: &quot;0x16c5785ac562ff41e2dcfdf829c5a142f1fccd7d&quot;,
        &quot;blockHash&quot;: &quot;0x8216c5785ac562ff41e2dcfdf5785ac562ff41e2dcfdf829c5a142f1fccd7d&quot;,
        &quot;blockNumber&quot;:&quot;0x1b4&quot;,
        &quot;data&quot;:&quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
        &quot;logIndex&quot;: &quot;0x1&quot;,
        &quot;topics&quot;: [],
        &quot;transactionHash&quot;:  &quot;0xdf829c5a142f1fccd7d8216c5785ac562ff41e2dcfdf5785ac562ff41e2dcf&quot;,
        &quot;transactionIndex&quot;: &quot;0x0&quot;
   }]
}
```
---

#### eth_getStorageAt

##### Description

Returns the value from a storage position at an address

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{[`Data`](#data)}|address of stored data|
|2|{[`Quantity`](#quantity)}|index into stored data|
|3|{[`Quantity`](#quantity)\|`string`\|[`Block Identifier`](#block-identifier)}|block number, or one of `&quot;latest&quot;`, `&quot;earliest&quot;` or `&quot;pending&quot;`, or a block identifier as described in [`Block Identifier`](#block-identifier)|

##### Returns

{[`Data`](#data)} - value stored at the given address and data index

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_getStorageAt&quot;,
    &quot;params&quot;: [&quot;0x295a70b2de5e3953354a6a8344e616ed314d7251&quot;, &quot;0x0&quot;, &quot;latest&quot;]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;0x00000000000000000000000000000000000000000000000000000000000004d2&quot;
}
```
---

#### eth_getTransactionByBlockHashAndIndex

##### Description

Returns information about a transaction specified by block hash and transaction index

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{[`Data`](#data)}|hash of a block|
|2|{[`Quantity`](#quantity)}|index of a transaction in the specified block|

##### Returns

{`null|object`} - `null` if no transaction is found, otherwise a transaction object with the following members:

- {[`Data`](#data)} `r` - ECDSA signature r
- {[`Data`](#data)} `s` - ECDSA signature s
- {[`Data`](#data)} `blockHash` - hash of block containing this transaction or `null` if pending
- {[`Data`](#data)} `from` - transaction sender
- {[`Data`](#data)} `hash` - hash of this transaction
- {[`Data`](#data)} `input` - contract code or a hashed method call
- {[`Data`](#data)} `to` - transaction recipient or `null` if deploying a contract
- {[`Quantity`](#quantity)} `v` - ECDSA recovery ID
- {[`Quantity`](#quantity)} `blockNumber` - number of block containing this transaction or `null` if pending
- {[`Quantity`](#quantity)} `gas` - gas provided for transaction execution
- {[`Quantity`](#quantity)} `gasPrice` - price in wei of each gas used
- {[`Quantity`](#quantity)} `nonce` - unique number identifying this transaction
- {[`Quantity`](#quantity)} `transactionIndex` - index of this transaction in the block or `null` if pending
- {[`Quantity`](#quantity)} `value` - value in wei sent with this transaction

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_getTransactionByBlockHashAndIndex&quot;,
    &quot;params&quot;:[&quot;0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;, &quot;0x0&quot;]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: {
        &quot;blockHash&quot;: &quot;0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2&quot;,
        &quot;blockNumber&quot;: &quot;0x5daf3b&quot;,
        &quot;from&quot;: &quot;0xa7d9ddbe1f17865597fbd27ec712455208b6b76d&quot;,
        &quot;gas&quot;: &quot;0xc350&quot;,
        &quot;gasPrice&quot;: &quot;0x4a817c800&quot;,
        &quot;hash&quot;: &quot;0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b&quot;,
        &quot;input&quot;: &quot;0x68656c6c6f21&quot;,
        &quot;nonce&quot;: &quot;0x15&quot;,
        &quot;r&quot;: &quot;0x1b5e176d927f8e9ab405058b2d2457392da3e20f328b16ddabcebc33eaac5fea&quot;,
        &quot;s&quot;: &quot;0x4ba69724e8f69de52f0125ad8b3c5c2cef33019bac3249e2c0a2192766d1721c&quot;,
        &quot;to&quot;: &quot;0xf02c1c8e6114b1dbe8937a39260b5b0a374432bb&quot;,
        &quot;transactionIndex&quot;: &quot;0x41&quot;,
        &quot;v&quot;: &quot;0x25&quot;,
        &quot;value&quot;: &quot;0xf3dbb76162000&quot;
    }
}
```
---

#### eth_getTransactionByBlockNumberAndIndex

##### Description

Returns information about a transaction specified by block number and transaction index

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{[`Quantity`](#quantity)\|`string`}|block number, or one of `&quot;latest&quot;`, `&quot;earliest&quot;` or `&quot;pending&quot;`|
|2|{[`Quantity`](#quantity)}|index of a transaction in the specified block|

##### Returns

{`null|object`} - `null` if no transaction is found, otherwise a transaction object with the following members:

- {[`Data`](#data)} `r` - ECDSA signature r
- {[`Data`](#data)} `s` - ECDSA signature s
- {[`Data`](#data)} `blockHash` - hash of block containing this transaction or `null` if pending
- {[`Data`](#data)} `from` - transaction sender
- {[`Data`](#data)} `hash` - hash of this transaction
- {[`Data`](#data)} `input` - contract code or a hashed method call
- {[`Data`](#data)} `to` - transaction recipient or `null` if deploying a contract
- {[`Quantity`](#quantity)} `v` - ECDSA recovery ID
- {[`Quantity`](#quantity)} `blockNumber` - number of block containing this transaction or `null` if pending
- {[`Quantity`](#quantity)} `gas` - gas provided for transaction execution
- {[`Quantity`](#quantity)} `gasPrice` - price in wei of each gas used
- {[`Quantity`](#quantity)} `nonce` - unique number identifying this transaction
- {[`Quantity`](#quantity)} `transactionIndex` - index of this transaction in the block or `null` if pending
- {[`Quantity`](#quantity)} `value` - value in wei sent with this transaction

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_getTransactionByBlockNumberAndIndex&quot;,
    &quot;params&quot;:[&quot;0x29c&quot;, &quot;0x0&quot;]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: {
        &quot;blockHash&quot;: &quot;0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2&quot;,
        &quot;blockNumber&quot;: &quot;0x5daf3b&quot;,
        &quot;from&quot;: &quot;0xa7d9ddbe1f17865597fbd27ec712455208b6b76d&quot;,
        &quot;gas&quot;: &quot;0xc350&quot;,
        &quot;gasPrice&quot;: &quot;0x4a817c800&quot;,
        &quot;hash&quot;: &quot;0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b&quot;,
        &quot;input&quot;: &quot;0x68656c6c6f21&quot;,
        &quot;nonce&quot;: &quot;0x15&quot;,
        &quot;r&quot;: &quot;0x1b5e176d927f8e9ab405058b2d2457392da3e20f328b16ddabcebc33eaac5fea&quot;,
        &quot;s&quot;: &quot;0x4ba69724e8f69de52f0125ad8b3c5c2cef33019bac3249e2c0a2192766d1721c&quot;,
        &quot;to&quot;: &quot;0xf02c1c8e6114b1dbe8937a39260b5b0a374432bb&quot;,
        &quot;transactionIndex&quot;: &quot;0x41&quot;,
        &quot;v&quot;: &quot;0x25&quot;,
        &quot;value&quot;: &quot;0xf3dbb76162000&quot;
    }
}
```
---

#### eth_getTransactionByHash

##### Description

Returns information about a transaction specified by hash

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{[`Data`](#data)}|hash of a transaction|

##### Returns

{`null|object`} - `null` if no transaction is found, otherwise a transaction object with the following members:

- {[`Data`](#data)} `r` - ECDSA signature r
- {[`Data`](#data)} `s` - ECDSA signature s
- {[`Data`](#data)} `blockHash` - hash of block containing this transaction or `null` if pending
- {[`Data`](#data)} `from` - transaction sender
- {[`Data`](#data)} `hash` - hash of this transaction
- {[`Data`](#data)} `input` - contract code or a hashed method call
- {[`Data`](#data)} `to` - transaction recipient or `null` if deploying a contract
- {[`Quantity`](#quantity)} `v` - ECDSA recovery ID
- {[`Quantity`](#quantity)} `blockNumber` - number of block containing this transaction or `null` if pending
- {[`Quantity`](#quantity)} `gas` - gas provided for transaction execution
- {[`Quantity`](#quantity)} `gasPrice` - price in wei of each gas used
- {[`Quantity`](#quantity)} `nonce` - unique number identifying this transaction
- {[`Quantity`](#quantity)} `transactionIndex` - index of this transaction in the block or `null` if pending
- {[`Quantity`](#quantity)} `value` - value in wei sent with this transaction

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_getTransactionByHash&quot;,
    &quot;params&quot;: [&quot;0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b&quot;]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: {
        &quot;blockHash&quot;: &quot;0x1d59ff54b1eb26b013ce3cb5fc9dab3705b415a67127a003c3e61eb445bb8df2&quot;,
        &quot;blockNumber&quot;: &quot;0x5daf3b&quot;,
        &quot;from&quot;: &quot;0xa7d9ddbe1f17865597fbd27ec712455208b6b76d&quot;,
        &quot;gas&quot;: &quot;0xc350&quot;,
        &quot;gasPrice&quot;: &quot;0x4a817c800&quot;,
        &quot;hash&quot;: &quot;0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b&quot;,
        &quot;input&quot;: &quot;0x68656c6c6f21&quot;,
        &quot;nonce&quot;: &quot;0x15&quot;,
        &quot;r&quot;: &quot;0x1b5e176d927f8e9ab405058b2d2457392da3e20f328b16ddabcebc33eaac5fea&quot;,
        &quot;s&quot;: &quot;0x4ba69724e8f69de52f0125ad8b3c5c2cef33019bac3249e2c0a2192766d1721c&quot;,
        &quot;to&quot;: &quot;0xf02c1c8e6114b1dbe8937a39260b5b0a374432bb&quot;,
        &quot;transactionIndex&quot;: &quot;0x41&quot;,
        &quot;v&quot;: &quot;0x25&quot;,
        &quot;value&quot;: &quot;0xf3dbb76162000&quot;
    }
}
```
---

#### eth_getTransactionCount

##### Description

Returns the number of transactions sent from an address

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{[`Data`](#data)}|address to query for sent transactions|
|2|{[`Quantity`](#quantity)\|`string`\|[`Block Identifier`](#block-identifier)}|block number, or one of `&quot;latest&quot;`, `&quot;earliest&quot;` or `&quot;pending&quot;`, or a block identifier as described in [`Block Identifier`](#block-identifier)|

##### Returns

{[`Quantity`](#quantity)} - number of transactions sent from the specified address

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_getTransactionCount&quot;,
    &quot;params&quot;: [&quot;0xc94770007dda54cF92009BFF0dE90c06F603a09f&quot;, &quot;latest&quot;]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;0x1&quot;
}
```
---

#### eth_getTransactionReceipt

##### Description

Returns the receipt of a transaction specified by hash

**Note:** Transaction receipts are unavailable for pending transactions.

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{[`Data`](#data)}|hash of a transaction|

##### Returns

{`null|object`} - `null` if no transaction is found, otherwise a transaction receipt object with the following members:

- {[`Data`](#data)} `blockHash` - hash of block containing this transaction
- {[`Data`](#data)} `contractAddress` - address of new contract or `null` if no contract was created
- {[`Data`](#data)} `from` - transaction sender
- {[`Data`](#data)} `logsBloom` - logs bloom filter
- {[`Data`](#data)} `to` - transaction recipient or `null` if deploying a contract
- {[`Data`](#data)} `transactionHash` - hash of this transaction
- {[`Quantity`](#quantity)} `blockNumber` - number of block containing this transaction
- {[`Quantity`](#quantity)} `cumulativeGasUsed` - gas used by this and all preceding transactions in this block
- {[`Quantity`](#quantity)} `gasUsed` - gas used by this transaction
- {[`Quantity`](#quantity)} `status` - `1` if this transaction was successful or `0` if it failed
- {[`Quantity`](#quantity)} `transactionIndex` - index of this transaction in the block
- {`Array&lt;Log&gt;`} `logs` - list of log objects generated by this transaction

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_getTransactionReceipt&quot;,
    &quot;params&quot;: [&quot;0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238&quot;]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: {
        &quot;blockHash&quot;: &apos;0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b&apos;,
        &quot;blockNumber&quot;: &apos;0xb&apos;,
        &quot;contractAddress&quot;: &apos;0xb60e8dd61c5d32be8058bb8eb970870f07233155&apos;,
        &quot;cumulativeGasUsed&quot;: &apos;0x33bc&apos;,
        &quot;gasUsed&quot;: &apos;0x4dc&apos;,
        &quot;logs&quot;: [],
        &quot;logsBloom&quot;: &quot;0x00...0&quot;,
        &quot;status&quot;: &quot;0x1&quot;,
        &quot;transactionHash&quot;: &apos;0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238&apos;,
        &quot;transactionIndex&quot;:  &apos;0x1&apos;
    }
}
```
---

#### eth_getUncleByBlockHashAndIndex

##### Description

Returns information about an uncle specified by block hash and uncle index position

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{[`Data`](#data)}|hash of a block|
|2|{[`Quantity`](#quantity)}|index of uncle|

##### Returns

{`null|object`} - `null` if no block or uncle is found, otherwise an uncle object with the following members:

- {[`Data`](#data)} `extraData` - &quot;extra data&quot; field of this block
- {[`Data`](#data)} `hash` - block hash or `null` if pending
- {[`Data`](#data)} `logsBloom` - logs bloom filter or `null` if pending
- {[`Data`](#data)} `miner` - address that received this block&apos;s mining rewards
- {[`Data`](#data)} `nonce` - proof-of-work hash or `null` if pending
- {[`Data`](#data)} `parentHash` - parent block hash
- {[`Data`](#data)} `receiptsRoot` -root of this block&apos;s receipts trie
- {[`Data`](#data)} `sha3Uncles` - SHA3 of the uncles data in this block
- {[`Data`](#data)} `stateRoot` - root of this block&apos;s final state trie
- {[`Data`](#data)} `transactionsRoot` - root of this block&apos;s transaction trie
- {[`Quantity`](#quantity)} `difficulty` - difficulty for this block
- {[`Quantity`](#quantity)} `gasLimit` - maximum gas allowed in this block
- {[`Quantity`](#quantity)} `gasUsed` - total used gas by all transactions in this block
- {[`Quantity`](#quantity)} `number` - block number or `null` if pending
- {[`Quantity`](#quantity)} `size` - size of this block in bytes
- {[`Quantity`](#quantity)} `timestamp` - unix timestamp of when this block was collated
- {[`Quantity`](#quantity)} `totalDifficulty` - total difficulty of the chain until this block
- {`Array&lt;Transaction&gt;`} `uncles` - list of uncle hashes

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_getUncleByBlockHashAndIndex&quot;,
    &quot;params&quot;: [&quot;0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b&quot;, &quot;0x0&quot;]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: {
        &quot;difficulty&quot;: &quot;0x027f07&quot;,
        &quot;extraData&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
        &quot;gasLimit&quot;: &quot;0x9f759&quot;,
        &quot;gasUsed&quot;: &quot;0x9f759&quot;,
        &quot;hash&quot;: &quot;0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;,
        &quot;logsBloom&quot;: &quot;0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;,
        &quot;miner&quot;: &quot;0x4e65fda2159562a496f9f3522f89122a3088497a&quot;,
        &quot;nonce&quot;: &quot;0xe04d296d2460cfb8472af2c5fd05b5a214109c25688d3704aed5484f9a7792f2&quot;,
        &quot;number&quot;: &quot;0x1b4&quot;,
        &quot;parentHash&quot;: &quot;0x9646252be9520f6e71339a8df9c55e4d7619deeb018d2a3f2d21fc165dde5eb5&quot;,
        &quot;sha3Uncles&quot;: &quot;0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347&quot;,
        &quot;size&quot;:  &quot;0x027f07&quot;,
        &quot;stateRoot&quot;: &quot;0xd5855eb08b3387c0af375e9cdb6acfc05eb8f519e419b874b6ff2ffda7ed1dff&quot;,
        &quot;timestamp&quot;: &quot;0x54e34e8e&quot;
        &quot;totalDifficulty&quot;:  &quot;0x027f07&quot;,
        &quot;transactionsRoot&quot;: &quot;0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421&quot;,
        &quot;uncles&quot;: []
    }
}
```
---

#### eth_getUncleByBlockNumberAndIndex

##### Description

Returns information about an uncle specified by block number and uncle index position

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{[`Quantity`](#quantity)\|`string`}|block number, or one of `&quot;latest&quot;`, `&quot;earliest&quot;` or `&quot;pending&quot;`|
|2|{[`Quantity`](#quantity)}|index of uncle|

##### Returns

{`null|object`} - `null` if no block or uncle is found, otherwise an uncle object with the following members:

- {[`Data`](#data)} `extraData` - &quot;extra data&quot; field of this block
- {[`Data`](#data)} `hash` - block hash or `null` if pending
- {[`Data`](#data)} `logsBloom` - logs bloom filter or `null` if pending
- {[`Data`](#data)} `miner` - address that received this block&apos;s mining rewards
- {[`Data`](#data)} `nonce` - proof-of-work hash or `null` if pending
- {[`Data`](#data)} `parentHash` - parent block hash
- {[`Data`](#data)} `receiptsRoot` -root of this block&apos;s receipts trie
- {[`Data`](#data)} `sha3Uncles` - SHA3 of the uncles data in this block
- {[`Data`](#data)} `stateRoot` - root of this block&apos;s final state trie
- {[`Data`](#data)} `transactionsRoot` - root of this block&apos;s transaction trie
- {[`Quantity`](#quantity)} `difficulty` - difficulty for this block
- {[`Quantity`](#quantity)} `gasLimit` - maximum gas allowed in this block
- {[`Quantity`](#quantity)} `gasUsed` - total used gas by all transactions in this block
- {[`Quantity`](#quantity)} `number` - block number or `null` if pending
- {[`Quantity`](#quantity)} `size` - size of this block in bytes
- {[`Quantity`](#quantity)} `timestamp` - unix timestamp of when this block was collated
- {[`Quantity`](#quantity)} `totalDifficulty` - total difficulty of the chain until this block
- {`Array&lt;Transaction&gt;`} `uncles` - list of uncle hashes

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_getUncleByBlockNumberAndIndex&quot;,
    &quot;params&quot;: [&quot;0x29c&quot;, &quot;0x0&quot;]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: {
        &quot;difficulty&quot;: &quot;0x027f07&quot;,
        &quot;extraData&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
        &quot;gasLimit&quot;: &quot;0x9f759&quot;,
        &quot;gasUsed&quot;: &quot;0x9f759&quot;,
        &quot;hash&quot;: &quot;0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;,
        &quot;logsBloom&quot;: &quot;0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;,
        &quot;miner&quot;: &quot;0x4e65fda2159562a496f9f3522f89122a3088497a&quot;,
        &quot;nonce&quot;: &quot;0xe04d296d2460cfb8472af2c5fd05b5a214109c25688d3704aed5484f9a7792f2&quot;,
        &quot;number&quot;: &quot;0x1b4&quot;,
        &quot;parentHash&quot;: &quot;0x9646252be9520f6e71339a8df9c55e4d7619deeb018d2a3f2d21fc165dde5eb5&quot;,
        &quot;sha3Uncles&quot;: &quot;0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347&quot;,
        &quot;size&quot;:  &quot;0x027f07&quot;,
        &quot;stateRoot&quot;: &quot;0xd5855eb08b3387c0af375e9cdb6acfc05eb8f519e419b874b6ff2ffda7ed1dff&quot;,
        &quot;timestamp&quot;: &quot;0x54e34e8e&quot;
        &quot;totalDifficulty&quot;:  &quot;0x027f07&quot;,
        &quot;transactionsRoot&quot;: &quot;0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421&quot;,
        &quot;uncles&quot;: []
    }
}
```
---

#### eth_getUncleCountByBlockHash

##### Description

Returns the number of uncles in a block specified by block hash

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{[`Data`](#data)}|hash of a block|

##### Returns

{[`Quantity`](#quantity)} - number of uncles in the specified block

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_getUncleCountByBlockHash&quot;,
    &quot;params&quot;: [&quot;0xc94770007dda54cF92009BFF0dE90c06F603a09f&quot;]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;0xc&quot;
}
```
---

#### eth_getUncleCountByBlockNumber

##### Description

Returns the number of uncles in a block specified by block number

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{[`Quantity`](#quantity)\|`string`}|block number, or one of `&quot;latest&quot;`, `&quot;earliest&quot;` or `&quot;pending&quot;`|

##### Returns

{[`Quantity`](#quantity)} - number of uncles in the specified block

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_getUncleCountByBlockNumber&quot;,
    &quot;params&quot;: [&quot;0xe8&quot;]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;0x1&quot;
}
```
---

#### eth_getWork

##### Description

Returns a list containing relevant information for proof-of-work

##### Parameters

_none_

##### Returns

{[`Data[]`](#data)} - array with the following items:

1. {[`Data`](#data)} - current block header pow-hash
1. {[`Data`](#data)} - seed hash used for the DAG
1. {[`Data`](#data)} - boundary condition (&quot;target&quot;), 2^256 / difficulty

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_getWork&quot;,
    &quot;params&quot;: []
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: [
        &quot;0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef&quot;,
        &quot;0x5EED00000000000000000000000000005EED0000000000000000000000000000&quot;,
        &quot;0xd1ff1c01710000000000000000000000d1ff1c01710000000000000000000000&quot;
    ]
}
```
---

#### eth_hashrate

##### Description

Returns the number of hashes-per-second this node is mining at

##### Parameters

_(none)_

##### Returns

{[`Quantity`](#quantity)} - number of hashes-per-second

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_hashrate&quot;,
    &quot;params&quot;: []
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;0x38a&quot;
}
```
---

#### eth_mining

##### Description

Determines if this client is mining new blocks

##### Parameters

_(none)_

##### Returns

{`boolean`} - `true` if this client is mining or `false` if it is not mining

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_mining&quot;,
    &quot;params&quot;: []
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: true
}
```
---

#### eth_newBlockFilter

##### Description

Creates a filter to listen for new blocks that can be used with `eth_getFilterChanges`

##### Parameters

_none_

##### Returns

{[`Quantity`](#quantity)} - ID of the newly-created filter that can be used with `eth_getFilterChanges`

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_newBlockFilter&quot;,
    &quot;params&quot;: []
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;0x1&quot;
}
```
---

#### eth_newFilter

##### Description

Creates a filter to listen for specific state changes that can then be used with `eth_getFilterChanges`

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{`object`}|@property {[`Quantity`](#quantity)\|`string`} `[fromBlock]` - block number, or one of `&quot;latest&quot;`, `&quot;earliest&quot;` or `&quot;pending&quot;`&lt;br/&gt;@property {[`Quantity`](#quantity)\|`string`} `[toBlock]` - block number, or one of `&quot;latest&quot;`, `&quot;earliest&quot;` or `&quot;pending&quot;`&lt;br/&gt;@property {[`Data`](#data)\|[`Data[]`](#data)} `[address]` - contract address or a list of addresses from which logs should originate&lt;br/&gt;@property {[`Data[]`](#data)} `[topics]` - list of order-dependent topics|

**Note:** Topics are order-dependent. A transaction with a log with topics `[A, B]` will be matched by the following topic filters:
- `[]` - &quot;anything&quot;
- `[A]` - &quot;A in first position (and anything after)&quot;
- `[null, B]` - &quot;anything in first position AND B in second position (and anything after)&quot;
- `[A, B]` - &quot;A in first position AND B in second position (and anything after)&quot;
- `[[A, B], [A, B]]` - &quot;(A OR B) in first position AND (A OR B) in second position (and anything after)&quot;

##### Returns

{[`Quantity`](#quantity)} - ID of the newly-created filter that can be used with `eth_getFilterChanges`

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_newFilter&quot;,
    &quot;params&quot;: [{
        &quot;topics&quot;: [&quot;0x0000000000000000000000000000000000000000000000000000000012341234&quot;]
    }]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;0x1&quot;
}
```
---

#### eth_newPendingTransactionFilter

##### Description

Creates a filter to listen for new pending transactions that can be used with `eth_getFilterChanges`

##### Parameters

_none_

##### Returns

{[`Quantity`](#quantity)} - ID of the newly-created filter that can be used with `eth_getFilterChanges`

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_newPendingTransactionFilter&quot;,
    &quot;params&quot;: []
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;0x1&quot;
}
```
---

#### eth_protocolVersion

##### Description

Returns the current Ethereum protocol version

##### Parameters

_(none)_

##### Returns

{`string`} - current Ethereum protocol version

##### Example
```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_protocolVersion&quot;,
    &quot;params&quot;: []
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;54&quot;
}
```
---

#### eth_sendRawTransaction

##### Description

Sends and already-signed transaction to the network

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{[`Data`](#data)}|signed transaction data|

##### Returns

{[`Data`](#data)} - transaction hash, or the zero hash if the transaction is not yet available

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_sendRawTransaction&quot;,
    &quot;params&quot;: [&quot;0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675&quot;]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;
}
```
---

#### eth_sendTransaction

##### Description

Creates, signs, and sends a new transaction to the network

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{`object`}|@property {[`Data`](#data)} `from` - transaction sender&lt;br/&gt;@property {[`Data`](#data)} `[to]` - transaction recipient&lt;br/&gt;@property {[`Quantity`](#quantity)} `[gas=&quot;0x15f90&quot;]` - gas provided for transaction execution&lt;br/&gt;@property {[`Quantity`](#quantity)} `[gasPrice]` - price in wei of each gas used&lt;br/&gt;@property {[`Quantity`](#quantity)} `[value]` - value in wei sent with this transaction&lt;br/&gt;@property {[`Data`](#data)} `[data]` - contract code or a hashed method call with encoded args&lt;br/&gt;@property {[`Quantity`](#quantity)} `[nonce]` - unique number identifying this transaction|

##### Returns

{[`Data`](#data)} - transaction hash, or the zero hash if the transaction is not yet available

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_sendTransaction&quot;,
    &quot;params&quot;: [{
        &quot;data&quot;: &quot;0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675&quot;,
        &quot;from&quot;: &quot;0xb60e8dd61c5d32be8058bb8eb970870f07233155&quot;,
        &quot;gas&quot;: &quot;0x76c0&quot;,
        &quot;gasPrice&quot;: &quot;0x9184e72a000&quot;,
        &quot;to&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
        &quot;value&quot;: &quot;0x9184e72a&quot;
    }]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;
}
```
---

#### eth_sign

##### Description

Calculates an Ethereum-specific signature in the form of `keccak256(&quot;\x19Ethereum Signed Message:\n&quot; + len(message) + message))`

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{[`Data`](#data)}|address to use for signing|
|2|{[`Data`](#data)}|data to sign|

##### Returns

{[`Data`](#data)} - signature hash of the provided data

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_sign&quot;,
    &quot;params&quot;: [&quot;0x9b2055d370f73ec7d8a03e965129118dc8f5bf83&quot;, &quot;0xdeadbeaf&quot;]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b&quot;
}
```
---

#### eth_signTransaction

##### Description

Signs a transaction that can be submitted to the network at a later time using with `eth_sendRawTransaction`

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{`object`}|@property {[`Data`](#data)} `from` - transaction sender&lt;br/&gt;@property {[`Data`](#data)} `[to]` - transaction recipient&lt;br/&gt;@property {[`Quantity`](#quantity)} `[gas=&quot;0x15f90&quot;]` - gas provided for transaction execution&lt;br/&gt;@property {[`Quantity`](#quantity)} `[gasPrice]` - price in wei of each gas used&lt;br/&gt;@property {[`Quantity`](#quantity)} `[value]` - value in wei sent with this transaction&lt;br/&gt;@property {[`Data`](#data)} `[data]` - contract code or a hashed method call with encoded args&lt;br/&gt;@property {[`Quantity`](#quantity)} `[nonce]` - unique number identifying this transaction|

##### Returns

{[`Data`](#data)} - signature hash of the transaction object

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_signTransaction&quot;,
    &quot;params&quot;: [{
        &quot;data&quot;: &quot;0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675&quot;,
        &quot;from&quot;: &quot;0xb60e8dd61c5d32be8058bb8eb970870f07233155&quot;,
        &quot;gas&quot;: &quot;0x76c0&quot;,
        &quot;gasPrice&quot;: &quot;0x9184e72a000&quot;,
        &quot;to&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
        &quot;value&quot;: &quot;0x9184e72a&quot;
    }]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;0xa3f20717a250c2b0b729b7e5becbff67fdaef7e0699da4de7ca5895b02a170a12d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee1b&quot;
}
```
---

#### eth_signTypedData

##### Description

Calculates an Ethereum-specific signature in the form of `keccak256(&quot;\x19Ethereum Signed Message:\n&quot; + len(message) + message))`

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{[`Data`](#data)}|address to use for signing|
|2|{[`Data`](#data)}|message to sign containing type information, a domain separator, and data|

**Note:** Client developers should refer to EIP-712 for complete semantics around [encoding and signing data](/EIPs/EIPS/eip-712#specification). Dapp developers should refer to EIP-712 for the expected structure of [RPC method input parameters](/EIPs/EIPS/eip-712#parameters).

##### Returns

{[`Data`](#data)} - signature hash of the provided message

##### Example

```sh
# Request
curl -X POST --data &apos;{
	&quot;id&quot;: 1337
	&quot;jsonrpc&quot;: &quot;2.0&quot;,
	&quot;method&quot;: &quot;eth_signTypedData&quot;,
	&quot;params&quot;: [&quot;0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826&quot;, {
		&quot;types&quot;: {
			&quot;EIP712Domain&quot;: [{
				&quot;name&quot;: &quot;name&quot;,
				&quot;type&quot;: &quot;string&quot;
			}, {
				&quot;name&quot;: &quot;version&quot;,
				&quot;type&quot;: &quot;string&quot;
			}, {
				&quot;name&quot;: &quot;chainId&quot;,
				&quot;type&quot;: &quot;uint256&quot;
			}, {
				&quot;name&quot;: &quot;verifyingContract&quot;,
				&quot;type&quot;: &quot;address&quot;
			}],
			&quot;Person&quot;: [{
				&quot;name&quot;: &quot;name&quot;,
				&quot;type&quot;: &quot;string&quot;
			}, {
				&quot;name&quot;: &quot;wallet&quot;,
				&quot;type&quot;: &quot;address&quot;
			}],
			&quot;Mail&quot;: [{
				&quot;name&quot;: &quot;from&quot;,
				&quot;type&quot;: &quot;Person&quot;
			}, {
				&quot;name&quot;: &quot;to&quot;,
				&quot;type&quot;: &quot;Person&quot;
			}, {
				&quot;name&quot;: &quot;contents&quot;,
				&quot;type&quot;: &quot;string&quot;
			}]
		},
		&quot;primaryType&quot;: &quot;Mail&quot;,
		&quot;domain&quot;: {
			&quot;name&quot;: &quot;Ether Mail&quot;,
			&quot;version&quot;: &quot;1&quot;,
			&quot;chainId&quot;: 1,
			&quot;verifyingContract&quot;: &quot;0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC&quot;
		},
		&quot;message&quot;: {
			&quot;from&quot;: {
				&quot;name&quot;: &quot;Cow&quot;,
				&quot;wallet&quot;: &quot;0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826&quot;
			},
			&quot;to&quot;: {
				&quot;name&quot;: &quot;Bob&quot;,
				&quot;wallet&quot;: &quot;0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB&quot;
			},
			&quot;contents&quot;: &quot;Hello, Bob!&quot;
		}
	}]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: &quot;0x4355c47d63924e8a72e509b65029052eb6c299d53a04e167c5775fd466751c9d07299936d304c153f6443dfa05f40ff007d72911b6f72307f996231605b915621c&quot;
}
```
---

#### eth_submitHashrate

##### Description

Submit a mining hashrate

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{[`Data`](#data)}|hash rate|
|2|{[`Data`](#data)}|random ID identifying this node|

##### Returns

{`boolean`} - `true` if submitting went through successfully, `false` otherwise

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_submitHashrate&quot;,
    &quot;params&quot;: [
        &quot;0x0000000000000000000000000000000000000000000000000000000000500000&quot;,
        &quot;0x59daa26581d0acd1fce254fb7e85952f4c09d0915afd33d3886cd914bc7d283c&quot;
    ]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: true
}
```
---

#### eth_submitWork

##### Description

Submit a proof-of-work solution

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{[`Data`](#data)}|nonce found|
|2|{[`Data`](#data)}|header&apos;s pow-hash|
|3|{[`Data`](#data)}|mix digest|

##### Returns

{`boolean`} - `true` if the provided solution is valid, `false` otherwise

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_submitWork&quot;,
    &quot;params&quot;: [
        &quot;0x0000000000000001&quot;,
        &quot;0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef&quot;,
        &quot;0xD1GE5700000000000000000000000000D1GE5700000000000000000000000000&quot;
    ]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: true
}
```
---

#### eth_syncing

##### Description

Returns information about the status of this client&apos;s network synchronization

##### Parameters

_(none)_

##### Returns

{`boolean|object`} - `false` if this client is not syncing with the network, otherwise an object with the following members:

- {[`Quantity`](#quantity)} `currentBlock` - number of the most-recent block synced
- {[`Quantity`](#quantity)} `highestBlock` - number of latest block on the network
- {[`Quantity`](#quantity)} `startingBlock` - block number at which syncing started

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_syncing&quot;,
    &quot;params&quot;: []
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: {
        &quot;currentBlock&quot;: &apos;0x386&apos;,
        &quot;highestBlock&quot;: &apos;0x454&apos;,
        &quot;startingBlock&quot;: &apos;0x384&apos;
    }
}
```
---

#### eth_uninstallFilter

##### Description

Destroys a filter based on filter ID

**Note:** This should only be called if a filter and its notifications are no longer needed. This will also be called automatically on a filter if its notifications are not retrieved using `eth_getFilterChanges` for a period of time.

##### Parameters

|#|Type|Description|
|-|-|-|
|1|{[`Quantity`](#quantity)}|ID of the filter to destroy|

##### Returns

{`boolean`} - `true` if the filter is found and successfully destroyed or `false` if it is not

##### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_uninstallFilter&quot;,
    &quot;params&quot;: [&quot;0xb&quot;]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1337,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: true
}
```
---

## Rationale

Much of Ethereum&apos;s effectiveness as an enterprise-grade application platform depends on its ability to provide a reliable and predictable developer experience. Nodes created by the current generation of Ethereum clients expose RPC endpoints with differing method signatures; this forces applications to work around method inconsistencies to maintain compatibility with various Ethereum RPC implementations.

Both Ethereum client developers and downstream dapp developers lack a formal Ethereum RPC specification. This proposal standardizes such a specification in a way that&apos;s versionable and modifiable through the traditional EIP process.

## Backwards compatibility

This proposal impacts Ethereum client developers by requiring that any exposed RPC interface adheres to this specification. This proposal impacts dapp developers by requiring that any RPC calls currently used in applications are made according to this specification.

## Implementation

The current generation of Ethereum clients includes several implementations that attempt to expose this RPC specification:

|Client Name|Language|Homepage|
|-|-|-|
|Geth|Go|[geth.ethereum.org](https://geth.ethereum.org)|
|Parity|Rust|[parity.io/ethereum](https://parity.io/ethereum)|
|Aleth|C++|[cpp-ethereum.org](https://cpp-ethereum.org)|

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 02 Oct 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1474</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1474</guid>
      </item>
    
      <item>
        <title>Define a maximum block timestamp drift</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/define-a-maximum-block-timestamp-drift/1556</comments>
        
        <description>## Simple Summary

Include an explicit definition of the acceptable timestamp drift in the protocol specification.

## Abstract

On the basis that both Geth and Parity implement the same timestamp validation requirements, this should be written into the reference specification.

## Motivation

There is a lack of clarity about how accurate timestamps in the block header must be. The yellow paper describes the timestamp as 

&gt; A scalar value equal to the reasonable output of Unix’s time() at this block’s inception

This causes [confusion](https://ethereum.stackexchange.com/questions/5924/how-do-ethereum-mining-nodes-maintain-a-time-consistent-with-the-network/5926#5926) about the safe use of the `TIMESTAMP` opcode (solidity&apos;s `block.timestamp` or `now`) in smart contract development.

Differing interpretations of &apos;reasonable&apos; may create a risk of consenus failures.


## Specification

The yellow paper should define a timestamp as: 

&gt; A scalar value equal to the output of Unix’s time() at this block’s inception. For the purpose of block validation, it must be greater than the previous block&apos;s timestamp, and no more than 15 seconds greater than system time.


## Rationale

Both [Geth](https://github.com/ethereum/go-ethereum/blob/4e474c74dc2ac1d26b339c32064d0bac98775e77/consensus/ethash/consensus.go#L45) and [Parity](https://github.com/paritytech/parity-ethereum/blob/73db5dda8c0109bb6bc1392624875078f973be14/ethcore/src/verification/verification.rs#L296-L307) reject blocks with timestamp more than 15 seconds in the future. This establishes a defacto standard, which should be made explicit in the reference specification. 


## Backwards Compatibility

It may be necessary to relax this requirement for blocks which were mined early in the main chain&apos;s history, if they would be considered invalid.

## Test Cases

These would be important to have.




## Implementation
_The implementations must be completed before any EIP is given status &quot;Final&quot;, but it need not be completed before the EIP is accepted. While there is merit to the approach of reaching consensus on the specification and rationale before writing code, the principle of &quot;rough consensus and running code&quot; is still useful when it comes to resolving many discussions of API details.
_
## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 09 Oct 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1482</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1482</guid>
      </item>
    
      <item>
        <title>Digital Identity Aggregator</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1495</comments>
        
        <description>## Simple Summary
A protocol for aggregating digital identity information that&apos;s broadly interoperable with existing, proposed, and hypothetical future digital identity standards.

## Abstract
This EIP proposes an identity management and aggregation framework on the Ethereum blockchain. It allows entities to claim an `Identity` via a singular `Identity Registry` smart contract, associate it with Ethereum addresses in a variety of meaningful ways, and use it to interact with smart contracts. This enables arbitrarily complex identity-related functionality. Notably (among other features) ERC-1484 `Identities`: are self-sovereign, can natively support [ERC-725](/EIPs/EIPS/eip-725) and [ERC-1056](/EIPs/EIPS/eip-1056) identities, are [DID compliant](https://github.com/NoahZinsmeister/ERC-1484/blob/master/best-practices/DID-Method.md), and can be fully powered by [meta-transactions](https://github.com/NoahZinsmeister/ERC-1484/tree/master/contracts/examples/Providers/MetaTransactions).

## Motivation
Emerging identity standards and related frameworks proposed by the Ethereum community (including ERCs/EIPs [725](/EIPs/EIPS/eip-725), [735](https://github.com/ethereum/EIPs/issues/735), [780](https://github.com/ethereum/EIPs/issues/780), [1056](/EIPs/EIPS/eip-1056), etc.) define and instrumentalize digital identity in a variety of ways. As existing approaches mature, new standards emerge, and isolated, non-standard approaches to identity develop, coordinating on identity will become increasingly burdensome for blockchain users and developers, and involve the unnecessary duplication of work.

The proliferation of on-chain identity solutions can be traced back to the fact that each codifies a notion of identity and links it to specific aspects of Ethereum (claims protocols, per-identity smart contracts, signature verification schemes, etc.). This proposal eschews that approach, instead introducing a protocol layer in between the Ethereum network and individual identity applications. This solves identity management and interoperability challenges by enabling any identity-driven application to leverage an un-opinionated identity management protocol.

## Definitions
- `Identity Registry`: A single smart contract which is the hub for all `Identities`. The primary responsibility of the `Registry` is to define and enforce the rules of a global namespace for `Identities`, which are individually denominated by Ethereum Identification Numbers (EINs).

- `Identity`: A data structure containing all the core information relevant to an identity, namely: a `Recovery Address`, an `Associated Addresses` set, a `Providers` set, and a `Resolvers` set. `Identities` are denominated by EINs (incrementing `uint` identifiers starting at 1), which are unique but otherwise uninformative. Each `Identity` is a Solidity struct:

```solidity
struct Identity {
    address recoveryAddress;
    AddressSet.Set associatedAddresses;
    AddressSet.Set providers;
    AddressSet.Set resolvers;
}
```

- `Associated Address`: An Ethereum address publicly associated with an `Identity`. In order for an address to become an `Associated Address`, an `Identity` must either transact from or produce an appropriately signed message from the candidate address and an existing `Associated Address`, indicating intent to associate. An `Associated Address` can be removed from an `Identity` by transacting/producing a signature indicating intent to disassociate. A given address may only be an `Associated Address` for one `Identity` at any given time.

- `Provider`: An Ethereum address (typically but not by definition a smart contract) authorized to act on behalf of `Identities` who have authorized them to do so. This includes but is not limited to managing the `Associated Address`, `Provider`, and `Resolver` sets for an `Identity`. `Providers` exist to facilitate user adoption by making it easier to manage `Identities`.

- `Resolver`: A smart contract containing arbitrary information pertaining to `Identities`. A resolver may implement an identity standard, such as ERC-725, or may consist of a smart contract leveraging or declaring identifying information about `Identities`. These could be simple attestation structures or more sophisticated financial dApps, social media dApps, etc. Each `Resolver` added to an `Identity` makes the `Identity` more informative.

- `Recovery Address`: An Ethereum address (either an account or smart contract) that can be used to recover lost `Identities` as outlined in the [Recovery](#recovery) section.

- `Destruction`: In the event of irrecoverable loss of control of an `Identity`, `Destruction` is a contingency measure to permanently disable the `Identity`. It removes all `Associated Addresses`, `Providers`, and optionally `Resolvers` while preserving the `Identity`. Evidence of the existence of the `Identity` persists, while control over the `Identity` is nullified.

## Specification
A digital identity in this proposal can be viewed as an omnibus account, containing more information about an identity than any individual identity application could. This omnibus identity is resolvable to an unlimited number of sub-identities called `Resolvers`. This allows an atomic entity, the `Identity`, to be resolvable to abstract data structures, the `Resolvers`. `Resolvers` recognize `Identities` by any of their `Associated Addresses`, or by their `EIN`.

The protocol revolves around claiming an `Identity` and managing `Associated Addresses`, `Providers` and `Resolvers`. Identities can delegate much or all of this responsibility to one or more `Providers`, or perform it directly from an `Associated Address`. `Associated Addresses`/`Providers` may add and remove `Resolvers` and `Providers` indiscriminately. `Associated Addresses` may only be added or removed with the appropriate permission.

### Identity Registry
The `Identity Registry` contains functionality to create new `Identities` and for existing `Identities` to manage their `Associated Addresses`, `Providers`, and `Resolvers`. It is important to note that this registry fundamentally requires transactions for every aspect of building out an `Identity`. However, recognizing the importance of accessibility to dApps and identity applications, we empower `Providers` to build out `Identities` on the behalf of users, without requiring users to pay gas costs. An example of this pattern, often referred to as a meta transactions, can be [seen in the reference implementation](https://github.com/NoahZinsmeister/ERC-1484/tree/master/contracts/examples/Providers/MetaTransactions).

Due to the fact that multiple addresses can be associated with a given identity (though not the reverse), `Identities` are denominated by `EIN`. This `uint` identifier can be encoded in QR format or mapped to more user-friendly formats, such as a `string`, in registries at the `Provider` or `Resolver` level.

### Address Management
The address management function consists of trustlessly connecting multiple user-owned `Associated Addresses` to an `Identity`. It does not give special status to any particular `Associated Address`, rather leaving this (optional) specification to identity applications built on top of the protocol - for instance, `management`, `action`, `claim` and `encryption` keys denominated in the ERC-725 standard, or `identifiers` and `delegates` as denominated in ERC-1056. This allows a user to access common identity data from multiple wallets while still:

- retaining the ability to interact with contracts outside of their identity
- taking advantage of address-specific permissions established at the application layer of a user&apos;s identity.

Trustlessness in the address management function is achieved through a robust permissioning scheme. To add an `Associated Address` to an `Identity`, implicit permission from a transaction sender or explicit permission from a signature is required from 1) an address already within the registry and 2) an address to be claimed. Importantly, the transaction need not come from any particular address, as long as permission is established, which allows not only users but third parties (companies, governments, etc.) to bear the overhead of managing identities. To prevent a compromised `Associated Address` from unilaterally removing other `Associated Addresses`, it&apos;s only possible to remove an `Associated Address` by transacting or producing a signature from it.

All signatures required in ERC-1484 are designed per the [ERC-191](/EIPs/EIPS/eip-191) v0 specification. To avoid replay attacks, all signatures must include a timestamp within a rolling lagged window of the current `block.timestamp`. For more information, see this [best practices document](https://github.com/NoahZinsmeister/ERC-1484/blob/master/best-practices/VerifyingSignatures.md) in the reference implementation.

### Provider Management
While the protocol allows users to directly call identity management functions, it also aims to be more robust and future-proof by allowing `Providers`, typically smart contracts, to perform identity management functions on a user&apos;s behalf. A `Provider` set by an `Identity` can perform address management and resolver management functions by passing a user&apos;s `EIN` in function calls.

### Resolver Management
A `Resolver` is any smart contract that encodes information which resolves to an `Identity`. We remain agnostic about the specific information that can be encoded in a resolver and the functionality that this enables. The existence of `Resolvers` is primarily what makes this ERC an identity *protocol* rather than an identity *application*. `Resolvers` resolve abstract data in smart contracts to an atomic entity, the `Identity`.

### Recovery
If users lose control over an `Associated Address`, the `Recovery Address` provides a fallback mechanism. Upon `Identity` creation, a `Recovery Address` is passed as a parameter by the creator. Recovery functionality is triggered in three scenarios:

**1. Changing Recovery Address**: If a recovery key is lost, an `Associated Address`/`Provider` can [triggerRecoveryAddressChange](#triggerrecoveryaddresschange)/[triggerRecoveryAddressChangeFor](#triggerrecoveryaddresschangefor). To prevent malicious behavior from someone who has gained control of an `Associated Address` or `Provider` and is changing the `Recovery Address` to one under their control, this action triggers a 14 day challenge period during which the old `Recovery Address` may reject the change by [triggering recovery](#triggerrecovery). If the `Recovery Address` does not reject the change within 14 days, the `Recovery Address` is changed.

**2. Recovery**: Recovery occurs when a user recognizes that an `Associated Address` or the `Recovery Address` belonging to the user is lost or stolen. In this instance the `Recovery Address` must call [triggerRecovery](#triggerrecovery). This removes all `Associated Addresses` and `Providers` from the corresponding `Identity` and replaces them with an address passed in the function call. The `Identity` and associated `Resolvers` maintain integrity. The user is now responsible for adding the appropriate un-compromised addresses back to their `Identity`.

*Importantly, the `Recovery Address` can be a user-controlled wallet or another address, such as a multisig wallet or smart contract. This allows for arbitrarily sophisticated recovery logic! This includes the potential for recovery to be fully compliant with standards such as [DID](https://decentralized.id/).*

**3. Destruction**
The Recovery scheme offers considerable power to a `Recovery Address`; accordingly, `Destruction` is a nuclear option to combat malicious control over an `Identity` when a `Recovery Address` is compromised. If a malicious actor compromises a user&apos;s `Recovery Address` and triggers recovery, any address removed in the `Recovery` process can call [triggerDestruction](#triggerdestruction) within 14 days to permanently disable the `Identity`. The user would then need to create a new `Identity`, and would be responsible for engaging in recovery schemes for any identity applications built in the `Resolver` or `Provider` layers.

#### Alternative Recovery Considerations
We considered many possible alternatives when devising the Recovery process outlined above. We ultimately selected the scheme that was most un-opinionated, modular, and consistent with the philosophy behind the `Associated Address`, `Provider`, and `Resolver` components. Still, we feel that it is important to highlight some of the other recovery options we considered, to provide a rationale as to how we settled on what we did.

**High Level Concerns**
Fundamentally, a Recovery scheme needs to be resilient to a compromised address taking control of a user&apos;s `Identity`. A secondary concern is preventing a compromised address from maliciously destroying a user&apos;s identity due to off-chain utility, which is not an optimal scenario, but is strictly better than if they&apos;ve gained control.

**Alternative 1: Nuclear Option**
This approach would allow any `Associated Address` to destroy an `Identity` whenever another `Associated Address` is compromised. While this may seem severe, we strongly considered it because this ERC is an identity *protocol*, not an identity *application*. This means that though a user&apos;s compromised `Identity` is destroyed, they should still have recourse to whatever restoration mechanisms are available in each of their actual identities at the `Resolver` and/or `Provider` level. We ultimately dismissed this approach for two main reasons:

- It is not robust in cases where a user has only one `Associated Address`
- It would increase the frequency of recovery requests to identity applications due to its unforgiving nature.

**Alternative 2: Unilateral Address Removal via Providers**
This would allow `Associated Addresses`/`Providers` to remove `Associated Addresses` without a signature from said address. This implementation would allow `Providers` to include arbitrarily sophisticated schemes for removing a rogue address - for instance, multi-sig requirements, centralized off-chain verification, user controlled master addresses, deferral to a jurisdictional contract, and more. To prevent a compromised `Associated Address` from simply setting a malicious `Provider` to remove un-compromised addresses, it would have required a waiting period between when a `Provider` is set and when they would be able to remove an `Associated Address`. We dismissed this approach because we felt it placed too high of a burden on `Providers`. If a `Provider` offered a sophisticated range of functionality to a user, but post-deployment a threat was found in the Recovery logic of the provider, `Provider`-specific infrastructure would need to be rebuilt. We also considered including a flag that would allow a user to decide whether or not a `Provider` may remove `Associated Addresses` unilaterally. Ultimately, we concluded that only allowing removal of `Associated Addresses` via the `Recovery Address` enables equally sophisticated recovery logic while separating the functionality from `Providers`, leaving less room for users to relinquish control to potentially flawed implementations.

## Rationale
We find that at a protocol layer, identities should not rely on specific claim or attestation structures, but should instead be a part of a trustless framework upon which arbitrarily sophisticated claim and attestation structures may be built.

The main criticism of existing identity solutions is that they&apos;re overly restrictive. We aim to limit requirements, keep identities modular and future-proof, and remain un-opinionated regarding any functionality a particular identity component may have. This proposal gives users the option to interact on the blockchain using an robust `Identity` rather than just an address.

## Implementation
**The reference implementation for ERC-1484 may be found in [NoahZinsmeister/ERC-1484](https://github.com/NoahZinsmeister/ERC-1484).**

#### identityExists

Returns a `bool` indicating whether or not an `Identity` denominated by the passed `EIN` exists.

```solidity
function identityExists(uint ein) public view returns (bool);
```

#### hasIdentity

Returns a `bool` indicating whether or not the passed `_address` is associated with an `Identity`.

```solidity
function hasIdentity(address _address) public view returns (bool);
```

#### getEIN

Returns the `EIN` associated with the passed `_address`. Throws if the address is not associated with an `EIN`.

```solidity
function getEIN(address _address) public view returns (uint ein);
```

#### isAssociatedAddressFor

Returns a `bool` indicating whether or not the passed `_address` is associated with the passed `EIN`.

```solidity
function isAssociatedAddressFor(uint ein, address _address) public view returns (bool);
```

#### isProviderFor

Returns a `bool` indicating whether or not the passed `provider` has been set by the passed `EIN`.

```solidity
function isProviderFor(uint ein, address provider) public view returns (bool);
```

#### isResolverFor

Returns a `bool` indicating whether or not the passed `resolver` has been set by the passed `EIN`.

```solidity
function isResolverFor(uint ein, address resolver) public view returns (bool);
```

#### getIdentity

Returns the `recoveryAddress`, `associatedAddresses`, `providers` and `resolvers` of the passed `EIN`.

```solidity
function getIdentity(uint ein) public view
    returns (
        address recoveryAddress,
        address[] memory associatedAddresses, address[] memory providers, address[] memory resolvers
    );
```

#### createIdentity

Creates an `Identity`, setting the `msg.sender` as the sole `Associated Address`. Returns the `EIN` of the new `Identity`.

```solidity
function createIdentity(address recoveryAddress, address[] memory providers, address[] memory resolvers)
    public returns (uint ein);
```

Triggers event: [IdentityCreated](#identitycreated)

#### createIdentityDelegated

Performs the same logic as `createIdentity`, but can be called by any address. This function requires a signature from the `associatedAddress` to ensure their consent.

```solidity
function createIdentityDelegated(
    address recoveryAddress, address associatedAddress, address[] memory providers, address[] memory resolvers,
    uint8 v, bytes32 r, bytes32 s, uint timestamp
)
    public returns (uint ein);
```

Triggers event: [IdentityCreated](#identitycreated)

#### addAssociatedAddress

Adds the `addressToAdd` to the `EIN` of the `approvingAddress`. The `msg.sender` must be either of the `approvingAddress` or the `addressToAdd`, and the signature must be from the other one.

```solidity
function addAssociatedAddress(
    address approvingAddress, address addressToAdd, uint8 v, bytes32 r, bytes32 s, uint timestamp
)
    public
```

Triggers event: [AssociatedAddressAdded](#associatedaddressadded)

#### addAssociatedAddressDelegated

Adds the `addressToAdd` to the `EIN` of the `approvingAddress`. Requires signatures from both the `approvingAddress` and the `addressToAdd`.

```solidity
function addAssociatedAddressDelegated(
    address approvingAddress, address addressToAdd,
    uint8[2] memory v, bytes32[2] memory r, bytes32[2] memory s, uint[2] memory timestamp
)
    public
```

Triggers event: [AssociatedAddressAdded](#associatedaddressadded)

#### removeAssociatedAddress

Removes the `msg.sender` as an `Associated Address` from its `EIN`.

```solidity
function removeAssociatedAddress() public;
```

Triggers event: [AssociatedAddressRemoved](#associatedaddressremoved)


#### removeAssociatedAddressDelegated

Removes the `addressToRemove` from its associated `EIN`. Requires a signature from the `addressToRemove`.

```solidity
function removeAssociatedAddressDelegated(address addressToRemove, uint8 v, bytes32 r, bytes32 s, uint timestamp)
    public;
```

Triggers event: [AssociatedAddressRemoved](#associatedaddressremoved)

#### addProviders

Adds an array of `Providers` to the `Identity` of the `msg.sender`.

```solidity
function addProviders(address[] memory providers) public;
```

Triggers event: [ProviderAdded](#provideradded)

#### addProvidersFor

Performs the same logic as `addProviders`, but must be called by a `Provider`.

```solidity
function addProvidersFor(uint ein, address[] memory providers) public;
```

Triggers event: [ProviderAdded](#provideradded)

#### removeProviders

Removes an array of `Providers` from the `Identity` of the `msg.sender`.

```solidity
function removeProviders(address[] memory providers) public;
```

Triggers event: [ProviderRemoved](#providerremoved)


#### removeProvidersFor

Performs the same logic as `removeProviders`, but is called by a `Provider`.

```solidity
function removeProvidersFor(uint ein, address[] memory providers) public;
```

Triggers event: [ProviderRemoved](#providerremoved)


#### addResolvers

Adds an array of `Resolvers` to the `EIN` of the `msg.sender`.

```solidity
function addResolvers(address[] memory resolvers) public;
```

Triggers event: [ResolverAdded](#resolveradded)

#### addResolversFor

Performs the same logic as `addResolvers`, but must be called by a `Provider`.

```solidity
function addResolversFor(uint ein, address[] memory resolvers) public;
```

Triggers event: [ResolverAdded](#resolveradded)

#### removeResolvers

Removes an array of `Resolvers` from the `EIN` of the `msg.sender`.

```solidity
function removeResolvers(address[] memory resolvers) public;
```

Triggers event: [ResolverRemoved](#resolverremoved)

#### removeResolversFor

Performs the same logic as `removeResolvers`, but must be called by a `Provider`.

```solidity
function removeResolversFor(uint ein, address[] memory resolvers) public;
```

Triggers event: [ResolverRemoved](#resolverremoved)

#### triggerRecoveryAddressChange

Initiates a change in the current `recoveryAddress` for the `EIN` of the `msg.sender`.

```solidity
function triggerRecoveryAddressChange(address newRecoveryAddress) public;
```

Triggers event: [RecoveryAddressChangeTriggered](#recoveryaddresschangetriggered)

#### triggerRecoveryAddressChangeFor

Initiates a change in the current `recoveryAddress` for a given `EIN`.

```solidity
function triggerRecoveryAddressChangeFor(uint ein, address newRecoveryAddress) public;
```

Triggers event: [RecoveryAddressChangeTriggered](#recoveryaddresschangetriggered)

#### triggerRecovery

Triggers `EIN` recovery from the current `recoveryAddress`, or the old `recoveryAddress` if changed within the last 2 weeks.

```solidity
function triggerRecovery(uint ein, address newAssociatedAddress, uint8 v, bytes32 r, bytes32 s, uint timestamp) public;
```

Triggers event: [RecoveryTriggered](#recoverytriggered)

#### triggerDestruction

Triggers destruction of an `EIN`. This renders the `Identity` permanently unusable.

```solidity
function triggerDestruction(uint ein, address[] memory firstChunk, address[] memory lastChunk, bool clearResolvers)
  public;
```

Triggers event: [IdentityDestroyed](#identitydestroyed)

### Events

#### IdentityCreated

MUST be triggered when an `Identity` is created.

```solidity
event IdentityCreated(
    address indexed initiator, uint indexed ein,
    address recoveryAddress, address associatedAddress, address[] providers, address[] resolvers, bool delegated
);
```

#### AssociatedAddressAdded

MUST be triggered when an address is added to an `Identity`.

```solidity
event AssociatedAddressAdded(
    address indexed initiator, uint indexed ein, address approvingAddress, address addedAddress, bool delegated
);
```

#### AssociatedAddressRemoved

MUST be triggered when an address is removed from an `Identity`.

```solidity
event AssociatedAddressRemoved(address indexed initiator, uint indexed ein, address removedAddress, bool delegated);
```

#### ProviderAdded

MUST be triggered when a provider is added to an `Identity`.

```solidity
event ProviderAdded(address indexed initiator, uint indexed ein, address provider, bool delegated);
```

#### ProviderRemoved

MUST be triggered when a provider is removed.

```solidity
event ProviderRemoved(address indexed initiator, uint indexed ein, address provider, bool delegated);
```

#### ResolverAdded

MUST be triggered when a resolver is added.

```solidity
event ResolverAdded(address indexed initiator, uint indexed ein, address resolvers, bool delegated);
```

#### ResolverRemoved

MUST be triggered when a resolver is removed.

```solidity
event ResolverRemoved(address indexed initiator, uint indexed ein, address resolvers, bool delegated);
```

#### RecoveryAddressChangeTriggered

MUST be triggered when a recovery address change is triggered.

```solidity
event RecoveryAddressChangeTriggered(
    address indexed initiator, uint indexed ein,
    address oldRecoveryAddress, address newRecoveryAddress, bool delegated
);
```

#### RecoveryTriggered

MUST be triggered when recovery is triggered.

```solidity
event RecoveryTriggered(
    address indexed initiator, uint indexed ein, address[] oldAssociatedAddresses, address newAssociatedAddress
);
```

#### IdentityDestroyed

MUST be triggered when an `Identity` is destroyed.

```solidity
event IdentityDestroyed(address indexed initiator, uint indexed ein, address recoveryAddress, bool resolversReset);
```

### Solidity Interface
```solidity
interface IdentityRegistryInterface {
    function isSigned(address _address, bytes32 messageHash, uint8 v, bytes32 r, bytes32 s)
        external pure returns (bool);

    // Identity View Functions /////////////////////////////////////////////////////////////////////////////////////////
    function identityExists(uint ein) external view returns (bool);
    function hasIdentity(address _address) external view returns (bool);
    function getEIN(address _address) external view returns (uint ein);
    function isAssociatedAddressFor(uint ein, address _address) external view returns (bool);
    function isProviderFor(uint ein, address provider) external view returns (bool);
    function isResolverFor(uint ein, address resolver) external view returns (bool);
    function getIdentity(uint ein) external view returns (
        address recoveryAddress,
        address[] memory associatedAddresses, address[] memory providers, address[] memory resolvers
    );

    // Identity Management Functions ///////////////////////////////////////////////////////////////////////////////////
    function createIdentity(address recoveryAddress, address[] calldata providers, address[] calldata resolvers)
        external returns (uint ein);
    function createIdentityDelegated(
        address recoveryAddress, address associatedAddress, address[] calldata providers, address[] calldata resolvers,
        uint8 v, bytes32 r, bytes32 s, uint timestamp
    ) external returns (uint ein);
    function addAssociatedAddress(
        address approvingAddress, address addressToAdd, uint8 v, bytes32 r, bytes32 s, uint timestamp
    ) external;
    function addAssociatedAddressDelegated(
        address approvingAddress, address addressToAdd,
        uint8[2] calldata v, bytes32[2] calldata r, bytes32[2] calldata s, uint[2] calldata timestamp
    ) external;
    function removeAssociatedAddress() external;
    function removeAssociatedAddressDelegated(address addressToRemove, uint8 v, bytes32 r, bytes32 s, uint timestamp)
        external;
    function addProviders(address[] calldata providers) external;
    function addProvidersFor(uint ein, address[] calldata providers) external;
    function removeProviders(address[] calldata providers) external;
    function removeProvidersFor(uint ein, address[] calldata providers) external;
    function addResolvers(address[] calldata resolvers) external;
    function addResolversFor(uint ein, address[] calldata resolvers) external;
    function removeResolvers(address[] calldata resolvers) external;
    function removeResolversFor(uint ein, address[] calldata resolvers) external;

    // Recovery Management Functions ///////////////////////////////////////////////////////////////////////////////////
    function triggerRecoveryAddressChange(address newRecoveryAddress) external;
    function triggerRecoveryAddressChangeFor(uint ein, address newRecoveryAddress) external;
    function triggerRecovery(uint ein, address newAssociatedAddress, uint8 v, bytes32 r, bytes32 s, uint timestamp)
        external;
    function triggerDestruction(
        uint ein, address[] calldata firstChunk, address[] calldata lastChunk, bool resetResolvers
    ) external;

    // Events //////////////////////////////////////////////////////////////////////////////////////////////////////////
    event IdentityCreated(
        address indexed initiator, uint indexed ein,
        address recoveryAddress, address associatedAddress, address[] providers, address[] resolvers, bool delegated
    );
    event AssociatedAddressAdded(
        address indexed initiator, uint indexed ein, address approvingAddress, address addedAddress
    );
    event AssociatedAddressRemoved(address indexed initiator, uint indexed ein, address removedAddress);
    event ProviderAdded(address indexed initiator, uint indexed ein, address provider, bool delegated);
    event ProviderRemoved(address indexed initiator, uint indexed ein, address provider, bool delegated);
    event ResolverAdded(address indexed initiator, uint indexed ein, address resolvers);
    event ResolverRemoved(address indexed initiator, uint indexed ein, address resolvers);
    event RecoveryAddressChangeTriggered(
        address indexed initiator, uint indexed ein, address oldRecoveryAddress, address newRecoveryAddress
    );
    event RecoveryTriggered(
        address indexed initiator, uint indexed ein, address[] oldAssociatedAddresses, address newAssociatedAddress
    );
    event IdentityDestroyed(address indexed initiator, uint indexed ein, address recoveryAddress, bool resolversReset);
}
```

## Backwards Compatibility
`Identities` established under this standard consist of existing Ethereum addresses; accordingly, there are no backwards compatibility issues. Deployed, non-upgradeable smart contracts that wish to become `Resolvers` for `Identities` will need to write wrapper contracts that resolve addresses to `EIN`-denominated `Identities`.

## Additional References
- [ERC-1484 Reference Implementation](https://github.com/NoahZinsmeister/ERC-1484)
- [ERC-191 Signatures](/EIPs/EIPS/eip-191)
- [ERC-725 Identities](/EIPs/EIPS/eip-725)
- [ERC-1056 Identities](/EIPs/EIPS/eip-1056)

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 12 Oct 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1484</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1484</guid>
      </item>
    
      <item>
        <title>TEthashV1</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/anti-eth-asic-mining-eip-1488-pr/1807</comments>
        
        <description>## Simple Summary
This EIP modifies ethash in order to break ASIC miners specialized for the current ethash mining algorithm.

## Abstract
This EIP pursue &quot;obsolete current ASIC miners&quot; by modifying PoW algorithm in a very low risk manner and update to latest hash algorithm from deprecated FNV Hash algorithms.

Following TEthashV1 algorithm suggests safe transition of PoW algorithms and secure the FNV Algorithm in MIX Parts.

## Motivation
Provide original Ethash proof of work verification with minimal set of changes by updating FNV0 algorithm

## Specification

#### 1. Reference materials on ETHASH FNV0

#### Where FNV Applied on ETHASH

- In [ETHASH](https://web.archive.org/web/20200505215203/https://github.com/ethereum/wiki/wiki/Ethash), FNV Hash is used on
  * 1) On data aggregation function, MIX parts.
  
  * Ethash Algorithm 

  ```
    Header + Nonce
           |
        Keccak 
           |
      **[MIX 0]**  --&gt; **[DAG Page]**
           |               |
         Mixing         &lt;--|
          ...
           |
      **[Mix 63]**
           |
           |-----&gt; Mix64  [Process] ---&gt; Mix Digest [32B]
  ```
  
  * FNV used in DAG Generation 
    and Mixing for random access or DAG Page.

#### 2. Current applied Ethash FNV hash implementation is deprecated now.

[FNV-0_hash (deprecated)](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-0_hash_(deprecated))

  It is a simple way of hashing algorithm

  ```
   hash = 0
   for each byte_of_data to be hashed
   	hash = hash × FNV_prime
   	hash = hash XOR octet_of_data
   return hash
  ```

  When analysed FNV-0 , there&apos;s very weak [avalanche effect](https://simple.wikipedia.org/wiki/Avalanche_effect), when hash input changes on 1~2bits. refer [FNV-Analysis reference section](https://github.com/tao-foundation/FNV-Analysis#how-to-test-and-analysis-reference-test-code)
  
  We need to research and apply newer FNV hash or short message hash algorithm.

#### 3. FNV1A hash algorithm description

Previous proposed algorithm based on FNV1 [EIP-1355](/EIPs/EIPS/eip-1355)

There&apos;s an implementation that looks like &quot;Missing Offset Bias&quot; at **FNV1A**.

Quotation of [original algorithm FNV1A](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash)
```
use hash offset
FNV-1a hash
The FNV-1a hash differs from the FNV-1 hash by only the order in which the multiply and XOR is performed:[8][10]

   hash = FNV_offset_basis
   for each byte_of_data to be hashed
   	hash = hash XOR byte_of_data
   	hash = hash × FNV_prime
   return hash
```

FNV_offset_basis and computation order change of xor and multiplication Makes one more xor and multiply computation, but more secure hash effects than FNV0. 
and make dispersion boundary condition (0, even number, ..) by using of Prime Number.

#### 4. Real Implementation for FNV1A 

Consider real computation resources, in TEthashV1 uses hash byte_of_data to 4bytes aligned data.

In TETHashV1, Adapts fully follow the FNV1A implementation.

  - TETHASHV1 FNV1A implementation

Following are reference implementation of FNV1A adapted in TETHashV1.

```cpp
// Reference Pseudo c/cpp implementation

#define FNV_PRIME 0x01000193U
#define FNV_OFFSET_BASIS  0x811c9dc5U

#define fnv1a(x, y)         ((((FNV_OFFSET_BASIS^(x))*FNV_PRIME) ^ (y)) * FNV_PRIME)
#define fnv1a_reduce(a,b,c,d) (fnv1a(fnv1a(fnv1a(a, b), c), d))
```

Another Byte aligned implementation of FNV1A , call to FNV1c

```cpp
#define FNV_PRIME   0x01000193U
#define FNV_OFFSET_BASIS  0x811c9dc5U

#define fnv1i(x)           (  (( (( ((                                          \
                                ( ((FNV_OFFSET_BASIS)^( ((x)&gt;&gt;24)&amp;0x000000ff )) * FNV_PRIME) \
                            ^   (((x)&gt;&gt;16  )&amp;0x000000ff)) * FNV_PRIME) \
                            ^   (((x)&gt;&gt;8   )&amp;0x000000ff)) * FNV_PRIME) \
                            ^   (((x)      )&amp;0x000000ff)) * FNV_PRIME) \
                            )
#define fnv1c(x, y)            ((fnv1i(x) ^ (y)) * FNV_PRIME)
```

#### 5. [FNV-Analysis](https://github.com/tao-foundation/FNV-Analysis)
FNV Mix Algorithm Analysis for TEthashV1

#### How to test and analysis reference test code.

You can compile it with simple in terminal.
No additional library needs, 

```sh
gcc -o fnvtest fnvcltest.c
```

And You can execute it
```
fnvtest

F(00,00)::VEC(0, 0, ffffffff, 0)::      FNV  :00000000, DF=00000000(00) DS(00000000), FNV1 :00000000, DF=00000000(00) DS(00000000), FNV1a:117697cd, DF=117697cd(17) DS(117697cd), FNV1c:1210d00f, DF=127f8dbf(20) DS(11a1725f),         F___RC=efe1b9c4, DF:efe1b9c4(19) , F1__RC=deb68dfe, DF:deb68dfe(22) , F1A_RC=99bad28b, DF:99bad28b(17) , F1C_RC=e29fa497, DF:e29fa497(18)
F(00,01)::VEC(0, 1, ffffffff, 0)::      FNV  :00000001, DF=00000001(01) DS(00000001), FNV1 :01000193, DF=01000193(06) DS(01000193), FNV1a:1076963a, DF=010001f7(09) DS(01000193), FNV1c:1110ce7c, DF=03001e73(11) DS(01000193),         F___RC=fefffe6d, DF:111e47a9(14) , F1__RC=d9fd8597, DF:074b0869(12) , F1A_RC=72c287e0, DF:eb78556b(19) , F1C_RC=6b6991ef, DF:89f63578(17)
F(00,02)::VEC(0, 2, ffffffff, 0)::      FNV  :00000002, DF=00000003(02) DS(00000001), FNV1 :02000326, DF=030002b5(08) DS(01000193), FNV1a:0f7694a7, DF=1f00029d(11) DS(01000193), FNV1c:1410d335, DF=05001d49(09) DS(030004b9),         F___RC=d8fd8404, DF:26027a69(13) , F1__RC=9b16d24c, DF:42eb57db(19) , F1A_RC=c17f0ecb, DF:b3bd892b(18) , F1C_RC=a5be8e78, DF:ced71f97(21)
F(00,03)::VEC(0, 3, ffffffff, 0)::      FNV  :00000003, DF=00000001(01) DS(00000001), FNV1 :030004b9, DF=0100079f(10) DS(01000193), FNV1a:0e769314, DF=010007b3(09) DS(01000193), FNV1c:1310d1a2, DF=07000297(09) DS(01000193),         F___RC=b2fb099b, DF:6a068d9f(16) , F1__RC=5c301f01, DF:c726cd4d(17) , F1A_RC=94cf402e, DF:55b04ee5(16) , F1C_RC=aea1a025, DF:0b1f2e5d(17)
F(00,04)::VEC(0, 4, ffffffff, 0)::      FNV  :00000004, DF=00000007(03) DS(00000001), FNV1 :0400064c, DF=070002f5(10) DS(01000193), FNV1a:0d769181, DF=03000295(07) DS(01000193), FNV1c:0e10c9c3, DF=1d001861(09) DS(050007df),         F___RC=8cf88f32, DF:3e0386a9(14) , F1__RC=1d496bb6, DF:417974b7(17) , F1A_RC=89401d59, DF:1d8f5d77(20) , F1C_RC=e4e96c7c, DF:4a48cc59(13)
F(00,05)::VEC(0, 5, ffffffff, 0)::      FNV  :00000005, DF=00000001(01) DS(00000001), FNV1 :050007df, DF=01000193(06) DS(01000193), FNV1a:0c768fee, DF=01001e6f(11) DS(01000193), FNV1c:0d10c830, DF=030001f3(09) DS(01000193),         F___RC=66f614c9, DF:ea0e9bfb(20) , F1__RC=de62b86b, DF:c32bd3dd(19) , F1A_RC=346e222c, DF:bd2e3f75(21) , F1C_RC=502e5f82, DF:b4c733fe(20)
F(00,06)::VEC(0, 6, ffffffff, 0)::      FNV  :00000006, DF=00000003(02) DS(00000001), FNV1 :06000972, DF=03000ead(10) DS(01000193), FNV1a:0b768e5b, DF=070001b5(09) DS(01000193), FNV1c:1010cce9, DF=1d0004d9(10) DS(030004b9),         F___RC=40f39a60, DF:26058ea9(13) , F1__RC=9f7c0520, DF:411ebd4b(16) , F1A_RC=b376a527, DF:8718870b(13) , F1C_RC=1241a9a4, DF:426ff626(17)
F(00,07)::VEC(0, 7, ffffffff, 0)::      FNV  :00000007, DF=00000001(01) DS(00000001), FNV1 :07000b05, DF=01000277(08) DS(01000193), FNV1a:0a768cc8, DF=01000293(06) DS(01000193), FNV1c:0f10cb56, DF=1f0007bf(15) DS(01000193),         F___RC=1af11ff7, DF:5a028597(13) , F1__RC=609551d5, DF:ffe954f5(22) , F1A_RC=14293bea, DF:a75f9ecd(21) , F1C_RC=49d34bba, DF:5b92e21e(16)
F(00,08)::VEC(0, 8, ffffffff, 0)::      FNV  :00000008, DF=0000000f(04) DS(00000001), FNV1 :08000c98, DF=0f00079d(12) DS(01000193), FNV1a:09768b35, DF=030007fd(12) DS(01000193), FNV1c:1a10dca7, DF=150017f1(12) DS(0b001151),         F___RC=f4eea58e, DF:ee1fba79(21) , F1__RC=21ae9e8a, DF:413bcf5f(19) , F1A_RC=eeebb7a5, DF:fac28c4f(17) , F1C_RC=7da04f47, DF:347304fd(16)
F(00,09)::VEC(0, 9, ffffffff, 0)::      FNV  :00000009, DF=00000001(01) DS(00000001), FNV1 :09000e2b, DF=010002b3(07) DS(01000193), FNV1a:087689a2, DF=01000297(07) DS(01000193), FNV1c:1910db14, DF=030007b3(10) DS(01000193),         F___RC=ceec2b25, DF:3a028eab(14) , F1__RC=e2c7eb3f, DF:c36975b5(18) , F1A_RC=54e1aef8, DF:ba0a195d(15) , F1C_RC=d425e1af, DF:a985aee8(16)
F(00,0a)::VEC(0, a, ffffffff, 0)::      FNV  :0000000a, DF=00000003(02) DS(00000001), FNV1 :0a000fbe, DF=03000195(07) DS(01000193), FNV1a:0776880f, DF=0f0001ad(10) DS(01000193), FNV1c:1c10dfcd, DF=050004d9(08) DS(030004b9),         F___RC=a8e9b0bc, DF:66059b99(15) , F1__RC=a3e137f4, DF:4126dccb(15) , F1A_RC=213fcd63, DF:75de639b(20) , F1C_RC=7e1d2751, DF:aa38c6fe(18)
F(00,0b)::VEC(0, b, ffffffff, 0)::      FNV  :0000000b, DF=00000001(01) DS(00000001), FNV1 :0b001151, DF=01001eef(12) DS(01000193), FNV1a:0676867c, DF=01000e73(09) DS(01000193), FNV1c:1b10de3a, DF=070001f7(11) DS(01000193),         F___RC=82e73653, DF:2a0e86ef(16) , F1__RC=64fa84a9, DF:c71bb35d(19) , F1A_RC=5598ce46, DF:74a70325(14) , F1C_RC=6400c630, DF:1a1de161(14)
F(00,0c)::VEC(0, c, ffffffff, 0)::      FNV  :0000000c, DF=00000007(03) DS(00000001), FNV1 :0c0012e4, DF=070003b5(10) DS(01000193), FNV1a:057684e9, DF=03000295(07) DS(01000193), FNV1c:1610d65b, DF=0d000861(07) DS(050007df),         F___RC=5ce4bbea, DF:de038db9(17) , F1__RC=2613d15e, DF:42e955f7(18) , F1A_RC=6a220ff1, DF:3fbac1b7(20) , F1C_RC=6e781da4, DF:0a78db94(15)
F(00,0d)::VEC(0, d, ffffffff, 0)::      FNV  :0000000d, DF=00000001(01) DS(00000001), FNV1 :0d001477, DF=01000693(07) DS(01000193), FNV1a:04768356, DF=010007bf(11) DS(01000193), FNV1c:1510d4c8, DF=03000293(07) DS(01000193),         F___RC=36e24181, DF:6a06fa6b(17) , F1__RC=e72d1e13, DF:c13ecf4d(18) , F1A_RC=168d4944, DF:7caf46b5(19) , F1C_RC=65bbcfa1, DF:0bc3d205(13)
F(00,0e)::VEC(0, e, ffffffff, 0)::      FNV  :0000000e, DF=00000003(02) DS(00000001), FNV1 :0e00160a, DF=0300027d(09) DS(01000193), FNV1a:037681c3, DF=07000295(08) DS(01000193), FNV1c:1810d981, DF=0d000d49(09) DS(030004b9),         F___RC=10dfc718, DF:263d8699(15) , F1__RC=a8466ac8, DF:4f6b74db(20) , F1A_RC=93e667bf, DF:856b2efb(19) , F1C_RC=76f80ee3, DF:1343c142(11)
F(00,0f)::VEC(0, f, ffffffff, 0)::      FNV  :0000000f, DF=00000001(01) DS(00000001), FNV1 :0f00179d, DF=01000197(07) DS(01000193), FNV1a:02768030, DF=010001f3(08) DS(01000193), FNV1c:1710d7ee, DF=0f000e6f(13) DS(01000193),         F___RC=eadd4caf, DF:fa028bb7(17) , F1__RC=695fb77d, DF:c119ddb5(17) , F1A_RC=0f485682, DF:9cae313d(17) , F1C_RC=3667e8dc, DF:409fe63f(18)
F(00,10)::VEC(0, 10, ffffffff, 0)::     FNV  :00000010, DF=0000001f(05) DS(00000001), FNV1 :10001930, DF=1f000ead(13) DS(01000193), FNV1a:01767e9d, DF=0300fead(14) DS(01000193), FNV1c:0210b6df, DF=15006131(09) DS(1500210f),         F___RC=c4dad246, DF:2e079ee9(17) , F1__RC=2a790432, DF:4326b34f(16) , F1A_RC=d10adebd, DF:de42883f(16) , F1C_RC=1ce48e12, DF:2a8366ce(15)
```

`F(00,01)` : is input x,y 

`VEC(0, 1, ffffffff, 0)`  : is `fnv_reduce` input vector (a,b,c,d)

`FNV  :00000001, DF=00000001(01) DS(00000001)` : 
  * `FNV(00,01)` result is 00000001 , 
  * `DF` : is changed bitcounts, compared with previous outputs, in this case prev[00,00] current[00,01] input is 1bit changed, and output result 1bit changed.
  * `DS` : is distances of previous result and current result , ABS(prev_fnvresult,current_fnvresult).

** Basically, `DF` is higher is best on hash algorithm.

`F___RC=fefffe6d, DF:111e47a9(14)` : `fnv_reduce = fnv(fnv(fnv(a,b),c),d) ` result is fefffe6d , and Different Bits counts are `14` bits.

  
## Rationale

In case of ethash algorithm, it can&apos;t prevent ASIC forever.

And, current ethash algorithm&apos;s FNV function is deprecated.

So, It needs to be upgraded and it will make current ethash based ASICs obsolete.

And current TETHASHV1 FNV1A implementation is based on most of ethash , which is verified for a long time.

Another propose of big differencing the Ethash algorithm need to crypto analysis for a long times and need to GPU code optimization times.

**Verification and Optimization timeline Examples**

original ethminer (2015) -&gt; claymore optimized miner (2016) [1year]

genoil ethminer (2015) -&gt; ethereum-mining/ethminer (2017) [2year]

## Test Results::

Tethash miner has 2~3% of hashrate degrade on GPU, due to more core computation time.

## Copyright

This work is licensed under a [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-nc-sa/4.0/).
</description>
        <pubDate>Thu, 01 Nov 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1485</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1485</guid>
      </item>
    
      <item>
        <title>Human Cost Accounting Standard (Like Gas but for humans)</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/freeworkculture/kazini/issues/11</comments>
        
        <description>## Simple Summary
A standard interface for Human Capital Accounting tokens.

## Abstract
The following standard allows for the implementation of a standard API for HUCAP tokens within smart contracts. This standard provides basic functionality to discover, track and transfer the motivational hierarchy of human resources. While blockchain architecture has succeeded in the financialisation of integrity by way of transparency; correspondingly real world outcomes will be proportional to the degree of individualisation of capital by way of knowledge.

## Motivation
The Ethereum protocol architecture has a deterministic world-view bounded to the random reality of the human domain that supplies the intentions and logic. The yellow paper formally defines the EVM as a state machine with only deterministic parameters and state transition operators. Oracle requests to another on-chain contract, and/or off-chain HTTP lookups still make for multiple deterministic transactions.

A standard interface that allows the appraisal of individual capabilities concurrently with output and the overall knowledge-base will reduce market search costs and increase the autonomous insertion of mindful innovation into the blockchain ecosystem. We provide for simple smart contracts to define and track an arbitrarily large number of HUCAP assets. Additional applications are discussed below.

The Belief-Desire-Intention model is a plan-theoretic framework for establishing means-end coherence in agent based modelling system.
The blockchain&apos;s cryptographic security architecture reliably scales to a blockchain based PKI web-of-trust hierarchies.
ERC-20 token standard allows any tokens on Ethereum to be re-used by other applications: from wallets to decentralized exchanges.
ERC-721 token standard allows wallet/broker/auction applications to work with any NFT on Ethereum.
ERC-1155 Crypto Item standard allows a smart contract interface where one can represent any number of ERC-20 and ERC-721 assets in a single contract.

This standard is inspired by the belief–desire–intention (BDI) model of human practical reasoning developed by Michael Bratman as a way of explaining future-directed intention. A BDI agent is a particular type of bounded rational software agent, imbued with particular mental attitudes, viz: Beliefs, Desires and Intentions (BDI). The model identifies commitment as the distinguishing factor between desire and intention, and a noteworthy property that leads to (1) temporal persistence in plans and in the sense of explicit reference to time, (2) further plans being made on the basis of those to which it is already committed, (3) hierarchical nature of plans, since the overarching plan remains in effect while subsidiary plans are being executed.

The BDI software model is an attempt to solve a problem of plans and planning choice and the execution thereof. The complement of which tenders a sufficient metric for indicating means-end coherence and ascribing cost baselines to such outcomes.

## Specification

#### Main Interface
```solidity
pragma solidity ^0.4.25;
pragma experimental ABIEncoderV2;

/**
    @title ERC-**** Human Capital Accounting Standard
    @dev See https://github.com/freeworkculture/kazini/issues/11
    Note: the ERC-165 identifier for this interface is 0xf23a6e61.
 */

interface IERC_HUCAP {

    /**
        @notice Compute the index value of an Agents BDI in the ecosystem.
        @param _address Set the stance of an agent
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
    */
    function updateIndex() internal returns (bool);

    /**
        @notice Get the active/inactive and states of an Agent in the ecosystem.
        @param _address Set the stance of an agent
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
    */
    function iam() view public returns (bool iam_, IERC_HUCAP_TYPES.IS state_);

    /**
        @notice Fetch the bdi index value of an Agent in the ecosystem.
        @param _address Set the stance of an agent
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
    */
    function index() view public returns (uint8 index_);
    
    /**
        @notice Count of Public Keys in key ring of an Agent in the ecosystem.
        @param _address Set the stance of an agent
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
    */
    function ringLength() view public returns (uint ringlength_);

    /**
        @notice Get the PGP Public Key Id of an Agent in the ecosystem.
        @param &quot;&quot; Set the stance of an agent
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
    */  
    function keyId() view public returns (bytes32 KEYID_);

     /**
        @notice Get the merit data of an Agent in the ecosystem.
        @param &quot;&quot; Set the stance of an agent
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
    */   
    function merits() view public returns (
        uint experience_,
        bytes32 reputation_,
        bytes32 talent_,
        uint8 index_,
        bytes32 hash_);

    /**
        @notice Get the accreditation of an Agent in the ecosystem.
        @param &quot;&quot; Set the stance of an agent
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
    */
    function kbase() view public returns (IERC_HUCAP_TYPES.KBase kbase_);

    /**
        @notice Get the desire of an Agent in the ecosystem.
        @param _desire    Pro-attitude
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
        
    */
    function desire(bytes1 _desire) view external returns (bytes32);

    /**
        @notice Get the intention of an Agent in the ecosystem.
        @param _intention    Conduct-controlling pro-attitude
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
        
    */
    function intention(bool _intention) view external returns  (bytes32);
    
    /**
        @notice Cycle the intention of an Agent in the ecosystem.
        @param _intention    Conduct-controlling pro-attitude
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
    */
    function flipIntention() external returns  (bool);
    

    /**
        @notice Get the user data of an Agent in the ecosystem.
        @param &quot;&quot;    Conduct-controlling pro-attitude
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
    */
    function getDoer() view external returns  (
        bytes32 fPrint,
        bool iam_,
        bytes32 email,
        bytes32 fName,
        bytes32 lName,
        uint age,
        bytes32 data_);

    /**
        @notice Get the belief data of an Agent in the ecosystem.
        @param _kbase    Source address
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
        
    */
    function getBelief(IERC_HUCAP_TYPES.KBase _kbase) view external returns  (
        bytes32 country_,
        bytes32 cAuthority_,
        bytes32 score_);

    /**
        @notice Get the desire data of an Agent in the ecosystem.
        @param _desire    Pro-attitides
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
        
    */
    function getDesire(bytes1 _desire) view external returns  (bytes32,bool);

    /**
        @notice Get the intention of an Agent in the ecosystem.
        @param _intention    Conduct-controlling pro-attitude
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
        
    */
    function getIntention(bool _intention) view external returns  (IERC_HUCAP_TYPES.IS,bytes32,uint256);

    /**
        @notice Sign the Public Key of an Agent in the ecosystem.
        @param _address    Address of key to sign, must belong to an Agent 
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
        
    */
    function sign(address _address) public onlyOwner returns (uint, bool signed);

    /**
        @notice Sign the Public Key of an Agent in the ecosystem.
        @param &quot;&quot;    internal helper function to add key in keyring
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
    */
    function sign() external onlyDoer returns (uint, bool signed);

    /**
        @notice Revoke the Public Key of an Agent in the ecosystem.
        @param _address    Address of key to revoke, must belong to an Agent
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
        
    */
    function revoke(address _address) external onlyDoer returns (uint, bool revoked);

    /**
        @notice Revoke the Public Key of an Agent in the ecosystem.
        @param &quot;&quot;    internal helper function to remove key from keyring
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
    */
    function revoke() external onlyDoer returns (uint, bool revoked);

    /**
        @notice Set the trust level for a Public Key of an Agent in the ecosystem.
        @param _level    Degree of trust
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
        
    */
    function trust(Trust _level) returns (bool);

    /**
        @notice Increment the number of keys in the keyring of an Agent in the ecosystem.
        @param _keyd    Target key
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
        
    */
    function incSigns(bytes32 _keyd) external ProxyKey returns (uint);

    /**
        @notice Decrement the number of keys in the keyring of an Agent in the ecosystem.
        @param _keyd    Target key
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
        
    */
    function decSigns(bytes32 _keyd) external ProxyKey returns (uint);

    /**
        @notice Set the knowledge credentials of an Agent in the ecosystem.
        @param _kbase    Level of accreditation
        @param _country      Source country
        @param _cAuthority     Accreditation authority
        @param _score  Accreditation 
        @param _year Year of Accreditation
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
    */
    function setbdi(
        KBase _kbase,
        bytes32 _country,
        bytes32 _cAuthority,
        bytes32 _score,
        uint _year
        ) external ProxyBDI returns (bool qualification_);

    /**
        @notice Set the SNA metrics of an Agent in the ecosystem
        @param _refMSD    Minimum shortest distance
        @param _refRank      Rank of target key
        @param _refSigned     No of keys signed I have signed
        @param _refSigs  No. of keys that have signed my key
        @param _refTrust Degree of tructThrows on any error rather than return a false flag to minimize user errors
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
    */
    function setbdi(
        uint _refMSD,
        uint _refRank,
        uint _refSigned,
        uint _refSigs,
        bytes32 _refTrust
        ) external ProxyBDI returns (bool reputation_);

    /**
        @notice Set the talents of an Agent in the ecosystem
        @param _talent    Agent&apos;s talent
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
    */
    function setbdi(bytes32 _talent) external ProxyBDI returns (bool talent_);

    /**
        @notice Set the desires of an Agent in the ecosystem
        @param _desire    Pro-attitude
        @param _goal      A goal is an instatiated pro-attitude
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
    */
    function setbdi(bytes1 _desire, Desire _goal) public onlyDoer returns (bool);

    /**
        @notice Set the intention of an Agent in the ecosystem
        @param _service    Conducting-controlling pro-attitude
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors
    */
    function setbdi(Intention _service) public onlyDoer returns (bool);
    
    /**
        @notice Set the targeted intention of an Agent in the ecosystem.
        @param _intention    Conduct-controlling pro-attitude
        @param _state      Agent stance       
        @dev For the purpose of 
        Throws on any error rather than return a false flag to minimize user errors

    */
    function intention(bool _intention, IERC_HUCAP_TYPES.IS _state) external returns  (IERC_HUCAP_TYPES.IS);

/* End of interface IERC_HUCAP */
}


```
#### User Defined Types Extension Interface

```solidity

interface IERC_HUCAP_TYPES {

/* Enums*/

    // Weights	   1,		2,		 4,		    8,		   16,	    32,		64,	    128    256
    enum KBase {PRIMARY,SECONDARY,TERTIARY,CERTIFICATION,DIPLOMA,LICENSE,BACHELOR,MASTER,DOCTORATE}
    
    
    enum IS { CLOSED, CREATOR, CURATOR, ACTIVE, INACTIVE, RESERVED, PROVER }

/* Structus */

        struct Clearance {
        bytes32 Zero;
        bytes32 Unknown;
        bytes32 Generic;
        bytes32 Poor;
        bytes32 Casual;
        bytes32 Partial;
        bytes32 Complete;
        bytes32 Ultimate;
    }
/* End of interface IERC_HUCAP_TYPES */
}

```
#### Web-of-trust Extension Interface

```solidity
pragma solidity ^0.4.25;
pragma experimental ABIEncoderV2;

interface IERC_HUCAP_KEYSIGNING_EXTENSION {

    bytes32 constant public _InterfaceId_ERC165_        = &quot;CREATOR 0.0118 XOR OF ALL FUNCTIONS IN THE INTERFACE&quot;;   // Complies to ERC165

//  KEY MASKING TABLE
//  bytes32 constant public MASK 			   		    = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
//  bytes32 constant public KEYID                       = 0xffffffffffffffffffffffffffffffffff90EBAC34FC40EAC30FC9CB464A2E56; // EXAMPLE PGP PUBLIC KEY ID
//  bytes32 constant public KEY_CERTIFICATION 		    = 0x01ffffffffffffff &lt;&lt; 192; // “C”	Key Certification
//  bytes32 constant public SIGN_DATA   			    = 0x02ffffffffffffff &lt;&lt; 192; // “S”	Sign Data
//  bytes32 constant public ENCRYPT_COMMUNICATIONS 	    = 0x04ffffffffffffff &lt;&lt; 192; // “E”	Encrypt Communications
//  Clearance constant public Trust                     = 0x03ff &lt;&lt; 192; // Trust: Unknown
                                                        // BYTES32 Value with 
                                                        // Public Key Id, masking
                                                        // Key Certification masking
                                                        // Split Key masking
                                                        // Generic masking
                                                        // Ordinary masking
                                                        //  Trust.Unknown masking
                                                        //  bytes32 constant public DOER = 0x11ff10ff100f03ffff00ffffffffffffffff90EBAC34FC40EAC30FC9CB464A2E56;

    bytes32 constant public KEY_CERTIFICATION 		    = 0x01ffffffffffffff &lt;&lt; 192; // “C”	Key Certification
    bytes32 constant public SIGN_DATA   			    = 0x02ffffffffffffff &lt;&lt; 192; // “S”	Sign Data
    bytes32 constant public ENCRYPT_COMMUNICATIONS 	    = 0x04ffffffffffffff &lt;&lt; 192; // “E”	Encrypt Communications
    bytes32 constant public ENCRYPT_STORAGE  		    = 0x08ffffffffffffff &lt;&lt; 192; // “E”	Encrypt Storage
    bytes32 constant public SPLIT_KEY   			    = 0x10ffffffffffffff &lt;&lt; 192; // Split key
    bytes32 constant public AUTHENTICATION   		    = 0x20ffffffffffffff &lt;&lt; 192; // “A”	Authentication
    bytes32 constant public MULTI_SIGNATURE			    = 0x80ffffffffffffff &lt;&lt; 192; // Held by more than one person
    bytes32 constant public TRUST_AMOUNT                = 0xffffffffffff00ff &lt;&lt; 192;
    bytes32 constant public BINARY_DOCUMENT             = 0xffff00ffffffffff &lt;&lt; 192; // 0x00: Signature of a binary document.
    bytes32 constant public CANONICAL_DOCUMENT          = 0xffff01ffffffffff &lt;&lt; 192; // 0x01: Signature of a canonical text document.
    bytes32 constant public STANDALONE_SIGNATURE        = 0xffff02ffffffffff &lt;&lt; 192; // 0x02: Standalone signature.
    bytes32 constant public GENERIC                     = 0xffff10ffffffffff &lt;&lt; 192; // 0x10: Generic certification of a User ID and Public-Key packet.
    bytes32 constant public PERSONA                     = 0xffff11ffffffffff &lt;&lt; 192; // 0x11: Persona certification of a User ID and Public-Key packet.
    bytes32 constant public CASUAL                      = 0xffff12ffffffffff &lt;&lt; 192; // 0x12: Casual certification of a User ID and Public-Key packet.
    bytes32 constant public POSITIVE                    = 0xffff13ffffffffff &lt;&lt; 192; // 0x13: Positive certification of a User ID and Public-Key packet.
    bytes32 constant public SUBKEY_BINDING              = 0xffff18ffffffffff &lt;&lt; 192; // 0x18: Subkey Binding Signature
    bytes32 constant public PRIMARY_KEY_BINDING         = 0xffff19ffffffffff &lt;&lt; 192; // 0x19: Primary Key Binding Signature
    bytes32 constant public DIRECTLY_ON_KEY             = 0xffff1Fffffffffff &lt;&lt; 192; // 0x1F: Signature directly on a key
    bytes32 constant public KEY_REVOCATION              = 0xffff20ffffffffff &lt;&lt; 192; // 0x20: Key revocation signature
    bytes32 constant public SUBKEY_REVOCATION           = 0xffff28ffffffffff &lt;&lt; 192; // 0x28: Subkey revocation signature
    bytes32 constant public CERTIFICATION_REVOCATION    = 0xffff30ffffffffff &lt;&lt; 192; // 0x30: Certification revocation signature
    bytes32 constant public TIMESTAMP                   = 0xffff40ffffffffff &lt;&lt; 192; // 0x40: Timestamp signature.
    bytes32 constant public THIRD_PARTY_CONFIRMATION    = 0xffff50ffffffffff &lt;&lt; 192; // 0x50: Third-Party Confirmation signature.
    bytes32 constant public ORDINARY   				    = 0xffffffff100fffff &lt;&lt; 192;
    bytes32 constant public INTRODUCER 				    = 0xffffffff010fffff &lt;&lt; 192;
    bytes32 constant public ISSUER	   				    = 0xffffffff001fffff &lt;&lt; 192;

//  EDGES MASKING TABLE
    Clearance internal TRUST = Clearance({
        Zero:       0x01ff &lt;&lt; 192,
        Unknown:    0x03ff &lt;&lt; 192,
        Generic:    0x07ff &lt;&lt; 192,
        Poor:       0xF0ff &lt;&lt; 192,
        Casual:     0xF1ff &lt;&lt; 192,
        Partial:    0xF3ff &lt;&lt; 192,
        Complete:   0xF7ff &lt;&lt; 192,
        Ultimate:   0xFFff &lt;&lt; 192
        });

    /**
    /// @notice Cycle through state transition of an Agent in the ecosystem.
    /// @param _address toggle on/off a doer agent
    //  @dev `anybody` can retrieve the talent data in the contract
    */
    function flipTo(address _address) external onlyOwner returns (IS);

    /**
    /// @notice Turn Agent in the ecosystem to on/off.
    /// @param _address toggle on/off a doer agent
    //  @dev `anybody` can retrieve the talent data in the contract
    */
    function toggle(address _address) external onlyOwner returns (bool);

    /**
    /// @notice Set the trust level of an Agent in the ecosystem.
    /// @param _level toggle on/off a doer agent
    //  @dev `anybody` can retrieve the talent data in the contract
    */
    function trust(Trust _level) returns (bytes32 Trust);

    event LogCall(address indexed from, address indexed to, address indexed origin, bytes _data);

/* End of interface IERC_HUCAP_KEYSIGNING_EXTENSION */
}

```
#### Human Capital Accounting Extension Interface

```solidity
pragma solidity ^0.4.25;
pragma experimental ABIEncoderV2;

interface IERC_HUCAP_TRACKUSERS_EXTENSION {

    /// @notice Instantiate an Agent in the ecosystem with default data.
    /// @param _address initialise a doer agent
    //  @dev `anybody` can retrieve the talent data in the contract
    function initAgent(Doers _address) external onlyControlled returns (bool);

    /// @notice Get the data by uuid of an Agent in the ecosystem.
    /// @param _uuid Get the address of a unique uid
    //  @dev `anybody` can retrieve the talent data in the contract
    function getAgent(bytes32 _uuid) view external returns (address);

    /// @notice Get the data of all Talents in the ecosystem.
    /// @param _address Query if address belongs to an agent
    //  @dev `anybody` can retrieve the talent data in the contract
    function iam(address _address) view public returns (bool);

    /// @notice Get the data of all Talents in the ecosystem.
    /// @param _address Query if address belongs to a doer
    //  @dev `anybody` can retrieve the talent data in the contract
    function isDoer(address _address) view public returns (IS);

    /// @notice Get the number of doers that can be spawned by a Creators.
    /// The query condition of the contract
    //  @dev `anybody` can retrieve the count data in the contract
    function getAgent(address _address)
    view public returns (bytes32 keyid_, IS state_, bool active_, uint myDoers_);

    /// @notice Get the data of all Talents in the ecosystem.
    /// @param _talent The talent whose frequency is being queried
    //  @dev `anybody` can retrieve the talent data in the contract
    function getTalents(bytes32 _talent)
    view external returns  (uint talentK_, uint talentI_, uint talentR_, uint talentF_);

    /// @notice Increment a kind of talent in the ecosystem.
    /// @param The talent whose frequency is being queried
    //  @dev `anybody` can retrieve the talent data in the contract
    function incTalent() payable public onlyDoer returns (bool);

    /// @notice Decrement a kind of talent in the ecosystem..
    /// @param The talent whose frequency is being queried
    //  @dev `anybody` can retrieve the talent data in the contract
    function decTalent() payable public onlyDoer returns (bool);

    /// @notice Set the Public-Key Id of an Agent in the ecosystem.
    /// @param _address Set the Public-key Id of an agent
    //  @dev `anybody` can retrieve the talent data in the contract
    function setAgent(address _address, bytes32 _keyId) external onlyControlled returns (bytes32);

    /// @notice Transition the states of an Agent in the ecosystem.
    /// @param _address Set the stance of an agent
    //  @dev `anybody` can retrieve the talent data in the contract
    function setAgent(address _address, IS _state) external onlyControlled returns (IS);

    /// @notice Set the active status of an Agent in the ecosystem.
    /// @param _address Toggle the true/false status of an agent
    //  @dev `anybody` can retrieve the talent data in the contract
    function setAgent(address _address, bool _active) external onlyControlled returns (bool);

    /// @notice Set the data of all Intentions of Agents in the ecosystem.
    /// @param _serviceId Track number of offers available
    //  @dev `anybody` can retrieve the talent data in the contract
    function setAllPromises(bytes32 _serviceId) external onlyControlled;

/* End of interface IERC_HUCAP_TRACKUSERS_EXTENSION */
}


```
## Rationale
[WIP]

## Backwards Compatibility
[WIP]

## Test Cases
[WIP]

## Implementation
[WIP]

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 12 Oct 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1491</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1491</guid>
      </item>
    
      <item>
        <title>Upgradable Smart Contract</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1503</comments>
        
        <description>## Simple Summary

A standard interface/guideline that makes a smart contract upgradable. 

## Abstract

Ethereum smart contracts have suffered a number of security issues in the past few years. The cost of fixing such a bug in smart contract is significant; for example, the consequences of The DAO attack in June 2016 caused tremendous financial loss and the hard fork of Ethereum blockchain.

The following standard makes it possible to upgrade a standard API within smart contracts. This standard provides basic functionalities to upgrade the operations of the contract without data migration. To ensure the decentralization/community interests, it also contains a voting mechanism to control the upgrading process. 

## Motivation

Smart contract is immutable after deployment. If any security risk is identified or program bug is detected, developers always have to destruct the old contract, deploy a new one and potentially migrate the data (hard fork) to the new contract. In some cases, deploying a smart contract with bugs and potential security vulnerabilities can cause a significant amount of financial loss.  

We propose this upgradable contract to fix the current situation. With the upgradable contract, developers can deploy a new version of smart contract after previous deployment and retain the data at the same time. 

For example, after an ERC20-compliant token contract is deployed, the users exploit a vulnerability in the source code.  Without the support of upgradable contract, developers have to fix this issue by deploy a new, secured contract otherwise the attackers would take advantage of the security hole, which may cause a tremendous financial loss. A challenge is how to migrate data from the old contract to a new one. With the upgradable contract below, this will become relatively easy as developers only have to upgrade the Handler contract to fix bugs while the Data contract will remain the same.

## Specification

The upgradable contract consists of three parts:

- **Handler contract** (implements **Handler interface**) defines operations and provides services. This contract can be upgraded;
- **Data contract** keeps the resources (data) and is controlled by the Handler contract;
- **Upgrader contract (optional)** deals with the voting mechanism and upgrades the Handler contract. The voters are pre-defined by the contract owner. 

&gt; The following codes are exact copies of the [ERC-1504 Upgradable Smart Contract.](https://gist.github.com/swordghost/77c96a972106af6ec6ccea9c2d66e768)

### Handler contract and Handler interface

Functions of the Handler contract vary with requirements, so developers would better design interfaces for Handler contracts to limit them and make sure external applications are always supported.

Below is the specification of Handler interface. In the Handler interface we define the following actions:

- Initialize the Data contract;
- Register the Upgrader contract address;
- Destruct the Handler contract after upgrading is done;
- Verify the current Handler is the working one → it should always return true.

Developers have to define their business-related functions as well.


```solidity
/// Handler interface.
/// Handler defines business related functions.
/// Use the interface to ensure that your external services are always supported.
/// Because of function live(), we design IHandler as an abstract contract rather than a true interface.
contract IHandler {

    /// Initialize the data contarct.
    /// @param  _str    value of exmStr of Data contract.
    /// @param  _int    value of exmInt of Data contract.
    /// @param  _array  value of exmArray of Data contract.
    function initialize (string _str, uint256 _int, uint16 [] _array) public;

    /// Register Upgrader contract address.
    /// @param  _upgraderAddr   address of the Upgrader contract.
    function registerUpgrader (address _upgraderAddr) external;

    /// Upgrader contract calls this to check if it is registered.
    /// @return if the Upgrader contract is registered.
    function isUpgraderRegistered () external view returns(bool);

    /// Handler has been upgraded so the original one has to self-destruct.
    function done() external;

    /// Check if the Handler contract is a working Handler contract.
    /// It is used to prove the contract is a Handler contract.
    /// @return always true.
    function live() external pure returns(bool) {
        return true;
    }

    /** Functions - define functions here */

    /** Events - add events here */
}
```


The process of deploying a Handler contract:

1. Deploy Data contract;
2. Deploy a Handler contract at a given address specified in the Data contract;
3. Register the Handler contract address by calling setHandler() in the Data contract, or use an Upgrader contract to switch the Handler contract, which requires that Data contract is initialized;
4. Initialize Data contract if haven’t done it already.

### Data Contract

Below is the specification of Data contract. There are three parts in the Data contract:

- **Administrator Data**: owner’s address, Handler contract’s address and a boolean indicating whether the contract is initialized or not;
- **Upgrader Data**: Upgrader contract’s address, upgrade proposal’s submission timestamp and proposal’s time period;
- **Resource Data**: all other resources that the contract needs to keep and manage.


```solidity
/// Data Contract
contract DataContract {

    /** Management data */
    /// Owner and Handler contract
    address private owner;
    address private handlerAddr;

    /// Ready?
    bool private valid;

    /** Upgrader data */
    address private upgraderAddr;
    uint256 private proposalBlockNumber;
    uint256 private proposalPeriod;
    /// Upgrading status of the Handler contract
    enum UpgradingStatus {
        /// Can be upgraded
        Done,
        /// In upgrading
        InProgress,
        /// Another proposal is in progress
        Blocked,
        /// Expired
        Expired,
        /// Original Handler contract error
        Error
    }

    /** Data resources - define variables here */

    /** Modifiers */

    /// Check if msg.sender is the Handler contract. It is used for setters.
    /// If fail, throw PermissionException.
    modifier onlyHandler;

    /// Check if msg.sender is not permitted to call getters. It is used for getters (if necessary).
    /// If fail, throw GetterPermissionException.
    modifier allowedAddress;

    /// Check if the contract is working.
    /// It is used for all functions providing services after initialization.
    /// If fail, throw UninitializationException.
    modifier ready;

    /** Management functions */

    /// Initializer. Just the Handler contract can call it. 
    /// @param  _str    default value of this.exmStr.
    /// @param  _int    default value of this.exmInt.
    /// @param  _array  default value of this.exmArray.
    /// exception   PermissionException msg.sender is not the Handler contract.
    /// exception   ReInitializationException   contract has been initialized.
    /// @return if the initialization succeeds.
    function initialize (string _str, uint256 _int, uint16 [] _array) external onlyHandler returns(bool);

    /// Set Handler contract for the contract. Owner must set one to initialize the Data contract.
    /// Handler can be set by owner or Upgrader contract.
    /// @param  _handlerAddr    address of a deployed Handler contract.
    /// @param  _originalHandlerAddr    address of the original Handler contract, only used when an Upgrader contract want to set the Handler contract.
    /// exception   PermissionException msg.sender is not the owner nor a registered Upgrader contract.
    /// exception   UpgraderException   Upgrader contract does not provide a right address of the original Handler contract.
    /// @return if Handler contract is successfully set.
    function setHandler (address _handlerAddr, address _originalHandlerAddr) external returns(bool);

    /** Upgrader contract functions */

    /// Register an Upgrader contract in the contract.
    /// If a proposal has not been accepted until proposalBlockNumber + proposalPeriod, it can be replaced by a new one.
    /// @param  _upgraderAddr  address of a deployed Upgrader contract.
    /// exception   PermissionException msg.sender is not the owner.
    /// exception   UpgraderConflictException   Another Upgrader contract is working.
    /// @return if Upgrader contract is successfully registered.
    function startUpgrading (address _upgraderAddr) public returns(bool);

    /// Getter of proposalPeriod.
    /// exception   UninitializationException   uninitialized contract.
    /// exception   GetterPermissionException   msg.sender is not permitted to call the getter.
    /// @return this.proposalPeriod.
    function getProposalPeriod () public view isReady allowedAddress returns(uint256);

    /// Setter of proposalPeriod.
    /// @param  _proposalPeriod new value of this.proposalPeriod.
    /// exception   UninitializationException   uninitialized contract.
    /// exception   PermissionException msg.sender is not the owner.
    /// @return if this.proposalPeriod is successfully set.
    function setProposalPeriod (uint256 _proposalPeriod) public isReady returns(bool);

    /// Return upgrading status for Upgrader contracts.
    /// @param  _originalHandlerAddr    address of the original Handler contract.
    /// exception   UninitializationException   uninitialized contract.
    /// @return Handler contract&apos;s upgrading status.
    function canBeUpgraded (address _originalHandlerAddr) external view isReady returns(UpgradingStatus);

    /// Check if the contract has been initialized.
    /// @return if the contract has been initialized.
    function live () external view returns(bool);

    /** Getters and setters of data resources: define functions here */
}
```


### Upgrader Contract (Optional)

Handler contract can be upgraded by calling setHandler() of Data contract. If the owner wants to collect ideas from users, an Upgrader contract will help him/her manage voting and upgrading.

Below is the specification of Upgrader contract:

- The Upgrader contract has the ability to take votes from the registered voters.
  - The contract owner is able to add voters any time before the proposal expires;
  - Voter can check the current status of the proposal (succeed or expired).
- Developers are able to delete this Upgrader contract by calling done() any time after deployment.

The Upgrader contract works as follows:

1. Verify the Data contract, its corresponding Handler contract and the new Handler contract have all been deployed;
2. Deploy an Upgrader contract using Data contract address, previous Handler contract address and new Handler contract address;
3. Register upgrader address in the new Handler contract first, then the original handler and finally the Data contract;
4. Call startProposal() to start the voting process;
5. Call getResolution() before the expiration;
6. Upgrading succeed or proposal is expired.

Note:

- Function done() can be called at any time to let upgrader destruct itself.
- Function status() can be called at any time to show caller status of the upgrader.


```solidity
/// Handler upgrader
contract Upgrader {
    // Data contract
    DataContract public data;
    // Original Handler contract
    IHandler public originalHandler;
    // New Handler contract
    address public newHandlerAddr;

    /** Marker */
    enum UpgraderStatus {
        Preparing,
        Voting,
        Success,
        Expired,
        End
    }
    UpgraderStatus public status;

    /// Check if the proposal is expired.
    /// If so, contract would be marked as expired.
    /// exception   PreparingUpgraderException  proposal has not been started.
    /// exception   ReupgradingException    upgrading has been done.
    /// exception   ExpirationException proposal is expired.
    modifier notExpired {
        require(status != UpgraderStatus.Preparing, &quot;Invalid proposal!&quot;);
        require(status != UpgraderStatus.Success, &quot;Upgrading has been done!&quot;);
        require(status != UpgraderStatus.Expired, &quot;Proposal is expired!&quot;);
        if (data.canBeUpgraded(address(originalHandler)) != DataContract.UpgradingStatus.InProgress) {
            status = UpgraderStatus.Expired;
            require(false, &quot;Proposal is expired!&quot;);
        }
        _;
    }

    /// Start voting.
    /// Upgrader must do upgrading check, namely checking if Data contract and 2 Handler contracts are ok.
    /// exception   RestartingException proposal has been already started.
    /// exception   PermissionException msg.sender is not the owner.
    /// exception   UpgraderConflictException   another upgrader is working.
    /// exception   NoPreparationException  original or new Handler contract is not prepared.
    function startProposal () external;

    /// Anyone can try to get resolution.
    /// If voters get consensus, upgrade the Handler contract.
    /// If expired, self-destruct.
    /// Otherwise, do nothing.
    /// exception   PreparingUpgraderException  proposal has not been started.
    /// exception   ExpirationException proposal is expired.
    /// @return     status of proposal.
    function getResolution() external returns(UpgraderStatus);

    /// Destruct itself.
    /// exception   PermissionException msg.sender is not the owner.
    function done() external;

    /** Other voting mechanism related variables and functions */
}
```


### Caveats

Since the Upgrader contract in [ERC-1504](/EIPs/EIPS/eip-1504) has a simple voting mechanism, it is prone to all the limitations that the voting contract is facing:

- The administrator can only be the owner of data and Handler contracts. Furthermore, only the administrator has the power to add voters and start a proposal. 
- It requires voters to be constantly active, informative and attentive to make a upgrader succeed.
- The voting will only be valid in a given time period. If in a given time period the contract cannot collect enough “yes” to proceed, the proposal will be marked expired. 

## Rationale

### Data Contract and Handler Contract

A smart contract is actually a kind of software, which provides some kind of services. From the perspective of software engineering, a service consists of **resources** that abstract the data and **operations** that abstract the process logic on the data. The requirement of upgrading is mostly on the logic part. Therefore, in order to make a smart contract upgradable, we divide it into two parts:

1. Data contract keeps the resources;
2. Handler contract contains operations.

The Handler contract can be upgraded in the future while the Data contract is permanent. Handler contract can manipulate the variables in Data contract through the getter and setter functions provided by Data contract.

### Upgrader Contract and Voting Mechanism

In order to prevent centralization and protect the interests of the community and stakeholders, we also design a voting mechanism in the Upgrader contract. Upgrader contract contains addresses of Data contract and two Handler contracts, and collects votes from pre-defined voters to upgrade the Handler contract when the pre-set condition is fulfilled.

For simplicity, the upgradable contract comes with a very minimal version of the voting mechanism. If the contract owner wants to implement a more complex voting mechanism, he/she can modify the existing voting mechanism to incorporate upgradability. The expiration mechanism (see modifier notExpried in Upgrader contract and related functions in Data contract) and upgrading check (see function startProposal() in Upgrader contract) to the contract are mandatory.

### Gas and Complexity (regarding the enumeration extension)

Using an upgrader will cost some gas. If the Handler contract is upgraded by the owner, it just costs gas that a contract call will cost, which is usually significantly lower than creating and deploying a new contract.  

Although upgrading contract may take some efforts and gas, it is a much less painful than deprecating the insecure contract/creating a new contract or hard fork (e.g. DAO attack). Contract creation requires a significant amount of effort and gas. One of the advantages of upgradable contracts is that the contract owners don’t have to create new contracts; instead, they only need to upgrade parts of contract that cause issues, which is less expensive compared to data loss and blockchain inconsistency. In other words, upgradable contracts make Data contract more scalable and flexible. 

### Community Consensus

Thank you to those who helped on review and revise the proposal:

- [@lsankar4033](https://github.com/lsankar4033) from MIT
- more

The proposal is initiated and developed by the team Renaissance and the Research Group of Blockchain System @ Center for Operating System at Peking University.

We have been very inclusive in this process and invite anyone with questions or contributions into our discussion. However, this standard is written only to support the identified use cases which are listed herein.

## Implementations

1. [Renaissance](https://www.renaissance.app) - a protocol that connect creators and fans financially
2. [ERC-1504](/EIPs/EIPS/eip-1504) - a reference implementation


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 17 Oct 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1504</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1504</guid>
      </item>
    
      <item>
        <title>Standard for Insurance Policies as ERC-721 Non Fungible Tokens</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1523</comments>
        
        <description>## Simple Summary
A standard interface for insurance policies, based on ERC 721.

## Abstract
The following standard allows for the implementation of a standard API for insurance policies within smart contracts.
Insurance policies are financial assets which are unique in some aspects, as they are connected to a customer, a specific risk, or have other unique properties like premium, period, carrier, underwriter etc.
Nevertheless, there are many potential applications where insurance policies can be traded, transferred or otherwise treated as an asset.
The ERC 721 standard already provides the standard and technical means to handle policies as a specific class of non fungible tokens.
insurance In this proposal, we define a minimum metadata structure with properties which are common to the greatest possible class of policies.

## Motivation
For a decentralized insurance protocol, a standard for insurance policies is crucial for interoperability of the involved services and application.
It allows policies to be bundled, securitized, traded in a uniform and flexible way by many independent actors like syndicates, brokers, and insurance companies.

## Specification
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.

An ERC-1523 compliant insurance policy is a non-fungible token which **MUST adhere to the ERC-721 token standard** and **MUST implement theERC721Metadata and the ERC721Enumerable interface**:

```solidity
/// @title ERC-1523 Insurance Policy Standard
///  Note: the ERC-165 identifier for this interface is 0x5a04be32
interface ERC1523 /* is ERC721, ERC721Metadata, ERC721Enumerable */ {

}
```

The implementor MAY choose values for the ```name``` and ```symbol```.

The **policy metadata extension** is **RECOMMENDED** for ERC-1523 smart contracts. 
This allows your smart contract to be interrogated for policy metadata.

```solidity
/// @title ERC-1523 Insurance Policy Standard, optional policy metadata extension
/// @dev See ...
///  Note: the ERC-165 identifier for this interface is 0x5a04be32
interface ERC1523PolicyMetadata /* is ERC1523 */ {

    /// @notice Metadata string for a given property.
    /// Properties are identified via hash of their property path.
    /// e.g. the property &quot;name&quot; in the ERC721 Metadata JSON Schema has the path /properties/name
    /// and the property path hash is the keccak256() of this property path. 
    /// this allows for efficient addressing of arbitrary properties, as the set of properties is potentially unlimited.
    /// @dev Throws if `_propertyPathHash` is not a valid property path hash. 
    function policyMetadata(uint256 _tokenId, bytes32 _propertyPathHash) external view returns (string _property);

}
```

In analogy to the “ERC721 Metadata JSON Schema”, the tokenURI **MUST** point to a JSON file with the following properties:
```json
{
    &quot;title&quot;: &quot;Asset Metadata&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;name&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Identifies the asset to which this NFT represents&quot;,
        },
        &quot;description&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Describes the asset to which this NFT represents&quot;,
        },
        \[additional parameters according to the following table\]
    }
}
```

### Additional parameters for the metadata JSON Schema

| Parameter     | Type          | Mandatory | Description                                                                        |
| ------------- | ------------- | ----------| ---------------------------------------------------------------------------------- |  
| carrier       | string        | yes       | Describes the carrier which takes the primary risk                                 |
| risk          | string        | yes       | Describes the risk                                                                 |
| status        | string        | yes       | Describes the status of the policy, e.g. applied for, underwritten, expired        |
| parameters    | string        | no        | Describes further parameters characterizing the risk                               |
| terms         | string        | no        | Describes legal terms &amp; conditions which apply for this policy                     |
| premium       | string        | no        | A string representation of the premium, **MAY** contain currency denominator       |
| sum_insured   | string        | no        | A string representation of the sum insured, **MAY** contain currency denominator   |

Parameters which are mandatory **MUST** be included in the metadata JSON. Other parameters **MAY** be included. However, the proposed optional parameters **SHOULD** be used for the intended purpose, so e.g. if the premium amount would be included in the metadata, the parameter name **SHOULD** be &quot;premium&quot;.
All parameters **MAY** be plain text or **MAY** also be URIs pointing to resources which contain the respective information, and which **MAY** be protected by an authentication mechanism. 

## Rationale
Insurance policies form an important class of financial assets, and it is natural to express those assets as a class of non-fungible tokens which adhere to the established ERC-721 standard.
We propose a standard for the accompanying metadata structures which are needed to uniquely define an insurance policy. Standardization is key because we expect decentralized insurance to receive widespread adoption and it is crucial to establish a unified standard to enable composability and the creation of universal toolsets. 
We therefore propose a standardized naming scheme for the different parameters describing an insurance policy. We propose three mandatory parameters which need to be included in every NFT and further parameters which **MAY** be used, and for which we only standardize the naming conventions.
### Mandatory parameters
While policies can have a multitude of possible properties, it is common that policies are issued by some entity, which is basically the entity responsible for paying out claims.
Second, an insurance policy is typically related to a specific risk. Some risks are unique, but there are cases where many policies share the same risk
(e.g. all flight delay policies for the same flight).
In general, the relation of policies to risks is a many-to-one relation with the special case of a one-to-one relation.
Third, a policy has a lifecycle of different statuses. Therefore the NFT 
We believe that those four properties are necessary to describe a policy. For many applications, those properties may be even sufficient. 

### Optional parameters
Most policies need more parameters to characterize the risk and other features, like premium, period etc. The naming conventions are listed in the above table.
However, any implementation **MAY** chose to implement more properties.

### On-chain vs. off-chain metadata
For some applications it will be sufficient to store the metadata in an off-chain repository or database which can be addressed by the tokenURI resource locator.
For more advanced applications, it can be desirable to have metadata available on-chain. 
Therefore, we require that the ```tokenURI``` **MUST** point to a JSON with the above structure, while the implementation of the ```policyMetadata``` function is **OPTIONAL**.


## Backwards Compatibility

## Test Cases

## Implementation

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 10 Oct 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1523</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1523</guid>
      </item>
    
      <item>
        <title>Transparent Contract Standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1538</comments>
        
        <description>Replaced by [EIP-2535 Diamond Standard](/EIPs/EIPS/eip-2535).

## Simple Summary
This standard provides a contract architecture that makes upgradeable contracts flexible, unlimited in size, and transparent. 

A transparent contract publicly documents the full history of all changes made to it.

All changes to a transparent contract are reported in a standard format.

## Abstract
A transparent contract is a proxy contract design pattern that provides the following:

1. A way to add, replace and remove multiple functions of a contract atomically (at the same time).
1. Standard events to show what functions are added, replaced and removed from a contract, and why the changes are made.
2. A standard way to query a contract to discover and retrieve information about all functions exposed by it.
3. Solves the 24KB maximum contract size limitation, making the maximum contract size of a transparent contract practically unlimited. This standard makes the worry about contract size a thing of the past.
4. Enables an upgradeable contract to become immutable in the future if desired.

## Motivation
A fundamental benefit of Ethereum contracts is that their code is immutable, thereby acquiring trust by trustlessness. People do not have to trust others if it is not possible for a contract to be changed.

However, a fundamental problem with trustless contracts that cannot be changed is that they cannot be changed. 

#### Bugs

Bugs and security vulnerabilities are unwittingly written into immutable contracts that ruin them.

#### Improvements

Immutable, trustless contracts cannot be improved, resulting in increasingly inferior contracts over time.

Contract standards evolve, new ones come out. People, groups and organizations learn over time what people want and what is better and what should be built next. Contracts that cannot be improved not only hold back the authors that create them, but everybody who uses them.

#### Upgradeable Contracts vs. Centralized Private Database
Why have an upgradeable contract instead of a centralized, private, mutable database?
Here are some reasons:
1. Because of the openness of storage data and verified code, it is possible to show a provable history of trustworthiness.
2. Because of the openness, bad behavior can be spotted and reported when it happens.
3. Independent security and domain experts can review the change history of contracts and vouch for their history of trustworthiness.
4. It is possible for an upgradeable contract to become immutable and trustless.
5. An upgradeable contract can have parts of it that are not upgradeable and so are partially immutable and trustless.

#### Immutability

In some cases immutable, trustless contracts are the right fit. This is the case when a contract is only needed for a short time or it is known ahead of time that there will never be any reason to change or improve it.

### Middle Ground

Transparent contracts provide a middle ground between immutable trustless contracts that can&apos;t be improved and upgradeable contracts that can&apos;t be trusted.

### Purposes

1. Create upgradeable contracts that earn trust by showing a provable history of trustworthiness. 
2. Document the development of contracts so their development and change is provably public and can be understood.
3. Create upgradeable contracts that can become immutable in the future if desired.
4. Create contracts that are not limited by a max size.

### Benefits &amp; Use Cases
This standard is for use cases that benefit from the following:
1. The ability to add, replace or remove multiple functions of a contract atomically (at the same time).
2. Each time a function is added, replaced or removed, it is documented with events.
3. Build trust over time by showing all changes made to a contract.
4. Unlimited contract size.
5. The ability to query information about functions currently supported by the contract.
6. One contract address that provides all needed functionality and never needs to be replaced by another contract address.
7. The ability for a contract to be upgradeable for a time, and then become immutable.
8. Add trustless guarantees to a contract with &quot;unchangeable functions&quot;. 

### New Software Possibilities

This standard enables a form of contract version control software to be written.

Software and user interfaces can be written to filter the `FunctionUpdate` and `CommitMessage` events of a contract address. Such software can show the full history of changes of any contract that implements this standard. 

User interfaces and software can also use this standard to assist or automate changes of contracts.

## Specification

&gt; **Note:**
The solidity `delegatecall` opcode enables a contract to execute a function from another contract, but it is executed as if the function was from the calling contract. Essentially `delegatecall` enables a contract to &quot;borrow&quot; another contract&apos;s function. Functions executed with `delegatecall` affect the storage variables of the calling contract, not the contract where the functions are defined.

### General Summary

A transparent contract delegates or forwards function calls to it to other contracts using `delegatecode`. 

A transparent contract has an `updateContract` function that enables multiple functions to be added, replaced or removed.

An event is emitted for every function that is added, replaced or removed so that all changes to a contract can be tracked in a standard way.

A transparent contract is a contract that implements and complies with the design points below.

### Terms

1. In this standard a **delegate contract** is a contract that a transparent contract fallback function forwards function calls to using `delegatecall`.
2. In this standard an **unchangeable function** is a function that is defined directly in a transparent contract and so cannot be replaced or removed.

### Design Points

A contract is a transparent contract if it implements the following design points:

1. A transparent contract is a contract that contains a fallback function, a constructor, and zero or more unchangeable functions that are defined directly within it.
2. The constructor of a transparent contract associates the `updateContract` function with a contract that implements the ERC1538 interface. The `updateContract` function can be an &quot;unchangeable function&quot; that is defined directly in the transparent contract or it can be defined in a delegate contract. Other functions can also be associated with contracts in the constructor.
3. After a transparent contract is deployed functions are added, replaced and removed by calling the `updateContract` function.
4. The `updateContract` function associates functions with contracts that implement those functions, and emits the `CommitMessage` and `FunctionUpdate` events that document function changes.
5. The `FunctionUpdate` event is emitted for each function that is added, replaced or removed. The `CommitMessage` event is emitted one time for each time the `updateContract` function is called and is emitted after any `FunctionUpdate` events are emitted.
6. The `updateContract` function can take a list of multiple function signatures in its `_functionSignatures` parameter and so add/replace/remove multiple functions at the same time.
7. When a function is called on a transparent contract it executes immediately if it is an &quot;unchangeable function&quot;. Otherwise the fallback function is executed. The fallback function finds the delegate contract associated with the function and executes the function using `delegatecall`. If there is no delegate contract for the function then execution reverts.
8. The source code of a transparent contract and all delegate contracts used by it are publicly viewable and verified.

The transparent contract address is the address that users interact with. The transparent contract address never changes. Only delegate addresses can change by using the `updateContracts` function.

Typically some kind of authentication is needed for adding/replacing/removing functions from a transparent contract, **however the scheme for authentication or ownership is not part of this standard**.

### Example

Here is an example of an implementation of a transparent contract. Please note that the example below is an **example only.  It is not the standard**. A contract is a transparent contract when it implements and complies with the design points listed above.

```solidity
pragma solidity ^0.5.7;

contract ExampleTransparentContract {
  // owner of the contract
  address internal contractOwner;
  event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

  // maps functions to the delegate contracts that execute the functions
  // funcId =&gt; delegate contract
  mapping(bytes4 =&gt; address) internal delegates;

  // maps each function signature to its position in the funcSignatures array.
  // signature =&gt; index+1
  mapping(bytes =&gt; uint256) internal funcSignatureToIndex;
    
  event CommitMessage(string message);
  event FunctionUpdate(bytes4 indexed functionId, address indexed oldDelegate, address indexed newDelegate, string functionSignature);
  
  // this is an example of an &quot;unchangeable function&quot;.
  // return the delegate contract address for the supplied function signature
  function delegateAddress(string calldata _functionSignature) external view returns(address) {
    require(funcSignatureToIndex[bytes(_functionSignature)] != 0, &quot;Function signature not found.&quot;);
    return delegates[bytes4(keccak256(bytes(_functionSignature)))];
  }
  
  // add a function using the updateContract function
  // this is an internal helper function
  function addFunction(address _erc1538Delegate, address contractAddress, string memory _functionSignatures, string memory _commitMessage) internal {    
    // 0x03A9BCCF == bytes4(keccak256(&quot;updateContract(address,string,string)&quot;))
    bytes memory funcdata = abi.encodeWithSelector(0x03A9BCCF, contractAddress, _functionSignatures, _commitMessage);
    bool success;
    assembly {
      success := delegatecall(gas, _erc1538Delegate, add(funcdata, 0x20), mload(funcdata), funcdata, 0)
    }
    require(success, &quot;Adding a function failed&quot;);   
  }

  constructor(address _erc1538Delegate) public {
    contractOwner = msg.sender;
    emit OwnershipTransferred(address(0), msg.sender);

    // adding ERC1538 updateContract function
    bytes memory signature = &quot;updateContract(address,string,string)&quot;;
    bytes4 funcId = bytes4(keccak256(signature));
    delegates[funcId] = _erc1538Delegate;
    emit FunctionUpdate(funcId, address(0), _erc1538Delegate, string(signature));
    emit CommitMessage(&quot;Added ERC1538 updateContract function at contract creation&quot;);
	
    // associate &quot;unchangeable functions&quot; with this transparent contract address
    // prevents function selector clashes with delegate contract functions
    // uses the updateContract function
    string memory functions = &quot;delegateAddress(string)&quot;;
    addFunction(_erc1538Delegate, address(this), functions, &quot;Associating unchangeable functions&quot;);
	
    // adding ERC1538Query interface functions
    functions = &quot;functionByIndex(uint256)functionExists(string)delegateAddresses()delegateFunctionSignatures(address)functionById(bytes4)functionBySignature(string)functionSignatures()totalFunctions()&quot;;    
    // &quot;0x01234567891011121314&quot; is an example address of an ERC1538Query delegate contract
    addFunction(_erc1538Delegate, 0x01234567891011121314, functions, &quot;Adding ERC1538Query functions&quot;);
    
    // additional functions could be added at this point
  }

  // Making the fallback function payable makes it work for delegate contract functions 
  // that are payable and not payable.
  function() external payable {
    // Delegate every function call to a delegate contract
    address delegate = delegates[msg.sig];
    require(delegate != address(0), &quot;Function does not exist.&quot;);
    assembly {
      let ptr := mload(0x40)
      calldatacopy(ptr, 0, calldatasize)
      let result := delegatecall(gas, delegate, ptr, calldatasize, 0, 0)
      let size := returndatasize
      returndatacopy(ptr, 0, size)
      switch result
      case 0 {revert(ptr, size)}
      default {return (ptr, size)}
    }
  }
}
```
As can be seen in the above example, every function call is delegated to a delegate contract, unless the function is defined directly in the transparent contract (making it an unchangeable function).

The constructor function adds the `updateContract` function to the transparent contract, which is then used to add other functions to the transparent contract.

Each time a function is added to a transparent contract the events `CommitMessage` and `FunctionUpdate` are emitted to document exactly what functions where added or replaced and why.

The delegate contract that implements the `updateContract` function implements the following interface: 
### ERC1538 Interface

```solidity
pragma solidity ^0.5.7;

/// @title ERC1538 Transparent Contract Standard
/// @dev Required interface
///  Note: the ERC-165 identifier for this interface is 0x61455567
interface ERC1538 {
  /// @dev This emits when one or a set of functions are updated in a transparent contract.
  ///  The message string should give a short description of the change and why
  ///  the change was made.
  event CommitMessage(string message);
  
  /// @dev This emits for each function that is updated in a transparent contract.
  ///  functionId is the bytes4 of the keccak256 of the function signature.
  ///  oldDelegate is the delegate contract address of the old delegate contract if
  ///  the function is being replaced or removed.
  ///  oldDelegate is the zero value address(0) if a function is being added for the
  ///  first time.
  ///  newDelegate is the delegate contract address of the new delegate contract if 
  ///  the function is being added for the first time or if the function is being 
  ///  replaced.
  ///  newDelegate is the zero value address(0) if the function is being removed.
  event FunctionUpdate(
    bytes4 indexed functionId, 
    address indexed oldDelegate, 
    address indexed newDelegate, 
    string functionSignature
  );

  /// @notice Updates functions in a transparent contract.
  /// @dev If the value of _delegate is zero then the functions specified 
  ///  in _functionSignatures are removed.
  ///  If the value of _delegate is a delegate contract address then the functions 
  ///  specified in _functionSignatures will be delegated to that address.
  /// @param _delegate The address of a delegate contract to delegate to or zero
  ///        to remove functions.      
  /// @param _functionSignatures A list of function signatures listed one after the other
  /// @param _commitMessage A short description of the change and why it is made
  ///        This message is passed to the CommitMessage event.          
  function updateContract(address _delegate, string calldata _functionSignatures, string calldata _commitMessage) external;  
}
```
### Function Signatures String Format

The text format for the `_functionSignatures` parameter is simply a string of function signatures. For example: `&quot;myFirstFunction()mySecondFunction(string)&quot;` This format is easy to parse and is concise.

Here is an example of calling the `updateContract` function that adds the ERC721 standard functions to a transparent contract:
```javascript
functionSignatures = &quot;approve(address,uint256)balanceOf(address)getApproved(uint256)isApprovedForAll(address,address)ownerOf(uint256)safeTransferFrom(address,address,uint256)safeTransferFrom(address,address,uint256,bytes)setApprovalForAll(address,bool)transferFrom(address,address,uint256)&quot;
tx = await transparentContract.updateContract(erc721Delegate.address, functionSignatures, &quot;Adding ERC721 functions&quot;);
```

### Removing Functions

Functions are removed by passing `address(0)` as the first argument to the `updateContract` function. The list of functions that are passed in are removed.

### Source Code Verification

The transparent contract source code and the source code for the delegate contracts should be verified in a provable way by a third party source such as etherscan.io.
&lt;!--
A transparent contract must implement the [ERC-165 Standard Interface Detection standard](/EIPs/EIPS/eip-165) via a delegate contract by adding the `supportsInterface` function using the `updateContract` function. The interfaceID for the ERC1538 standard is `0x61455567`.
--&gt;

### Function Selector Clash
A function selector clash occurs when a function is added to a contract that hashes to the same four-byte hash as an existing function. This is unlikely to occur but should be prevented in the implementation of the `updateContract` function. See the [reference implementation of ERC1538](https://github.com/mudgen/transparent-contracts-erc1538) to see an example of how function clashes can be prevented.

### ERC1538Query

Optionally, the function signatures of a transparent contract can be stored in an array in the transparent contract and queried to get what functions the transparent contract supports and what their delegate contract addresses are.

The following is an optional interface for querying function information from a transparent contract:

```solidity
pragma solidity ^0.5.7;

interface ERC1538Query {
    
  /// @notice Gets the total number of functions the transparent contract has.
  /// @return The number of functions the transparent contract has,
  ///  not including the fallback function.
  function totalFunctions() external view returns(uint256);
	
  /// @notice Gets information about a specific function
  /// @dev Throws if `_index` &gt;= `totalFunctions()`
  /// @param _index The index position of a function signature that is stored in an array
  /// @return The function signature, the function selector and the delegate contract address
  function functionByIndex(uint256 _index) 
    external 
    view 
    returns(
      string memory functionSignature, 
      bytes4 functionId, 
      address delegate
    );
	
  /// @notice Checks to see if a function exists
  /// @param The function signature to check
  /// @return True if the function exists, false otherwise
  function functionExists(string calldata _functionSignature) external view returns(bool);
	
  /// @notice Gets all the function signatures of functions supported by the transparent contract
  /// @return A string containing a list of function signatures
  function functionSignatures() external view returns(string memory);
	
  /// @notice Gets all the function signatures supported by a specific delegate contract
  /// @param _delegate The delegate contract address
  /// @return A string containing a list of function signatures
  function delegateFunctionSignatures(address _delegate) external view returns(string memory);
	
  /// @notice Gets the delegate contract address that supports the given function signature
  /// @param The function signature
  /// @return The delegate contract address
  function delegateAddress(string calldata _functionSignature) external view returns(address);
	
  /// @notice Gets information about a function
  /// @dev Throws if no function is found
  /// @param _functionId The id of the function to get information about
  /// @return The function signature and the contract address
  function functionById(bytes4 _functionId) 
    external 
    view 
    returns(
      string memory signature, 
      address delegate
    );
	
  /// @notice Get all the delegate contract addresses used by the transparent contract
  /// @return An array of all delegate contract addresses
  function delegateAddresses() external view returns(address[] memory);
}
```

See the [reference implementation of ERC1538](https://github.com/mudgen/transparent-contracts-erc1538) to see how this is implemented.

The text format for the list of function signatures returned from the `delegateFunctionSignatures` and `functionSignatures` functions is simply a string of function signatures. Here is an example of such a string: `&quot;approve(address,uint256)balanceOf(address)getApproved(uint256)isApprovedForAll(address,address)ownerOf(uint256)safeTransferFrom(address,address,uint256)safeTransferFrom(address,address,uint256,bytes)setApprovalForAll(address,bool)transferFrom(address,address,uint256)&quot;`

### How To Deploy A Transparent Contract
1. Create and deploy to a blockchain a contract that implements the ERC1538 interface. You can skip this step if there is already such a contract deployed to the blockchain.
2. Create your transparent contract with a fallback function as given above. Your transparent contract also needs a constructor that adds the `updateContract` function.
3. Deploy your transparent contract to a blockchain. Pass in the address of the ERC1538 delegate contract to your constructor if it requires it.

See the [reference implementation](https://github.com/mudgen/transparent-contracts-erc1538) for examples of these contracts.

### Wrapper Contract for Delegate Contracts that Depend on Other Delegate Contracts
In some cases some delegate contracts may need to call external/public functions that reside in other delegate contracts. A convenient way to solve this problem is to create a contract that contains empty implementations of functions that are needed and import and extend this contract in delegate contracts that call functions from other delegate contracts. This enables delegate contracts to compile without having to provide implementations of the functions that are already given in other delegate contracts. This is a way to save gas, prevent reaching the max contract size limit, and prevent duplication of code. This strategy was given by @amiromayer. [See his comment for more information.](https://github.com/ethereum/EIPs/issues/1538#issuecomment-451985155) Another way to solve this problem is to use assembly to call functions provided by other delegate contracts.

### Decentralized Authority
It is possible to extend this standard to add consensus functionality such as an approval function that multiple different people call to approve changes before they are submitted with the `updateContract` function. Changes only go into effect when the changes are fully approved. The `CommitMessage` and ` FunctionUpdate` events should only be emitted when changes go into effect.

## Security
&gt; This standard refers to **owner(s)** as one or more individuals that have the power to add/replace/remove functions of an upgradeable contract.

### General

The owners(s) of an upgradeable contract have the ability to alter, add or remove data from the contract&apos;s data storage. Owner(s) of a contract can also execute any arbitrary code in the contract on behalf of any address. Owners(s) can do these things by adding a function to the contract that they call to execute arbitrary code. This is an issue for upgradeable contracts in general and is not specific to transparent contracts.

&gt;**Note:** The design and implementation of contract ownership is **not** part of this standard. The examples given in this standard and in the reference implementation are just **examples** of how it could be done.

### Unchangeable Functions

&quot;Unchangeable functions&quot; are functions defined in a transparent contract itself and not in a delegate contract. The owner(s) of a transparent contract are not able to replace these functions. The use of unchangeable functions is limited because in some cases they can still be manipulated if they read or write data to the storage of the transparent contract. Data read from the transparent contract&apos;s storage could have been altered by the owner(s) of the contract. Data written to the transparent contract&apos;s storage can be undone or altered by the owner(s) of the contract.

In some cases unchangeble functions add trustless guarantees to a transparent contract.

### Transparency

Contracts that implement this standard emit an event every time a function is added, replaced or removed. This enables people and software to monitor the changes to a contract. If any bad acting function is added to a contract then it can be seen. To comply with this standard all source code of a transparent contract and delegate contracts must be publicly available and verified. 

Security and domain experts can review the history of change of any transparent contract to detect any history of foul play.

## Rationale

### String of Function Signatures Instead of bytes4[] Array of Function Selectors

The `updateContract` function takes a `string` list of functions signatures as an argument instead of a `bytes4[]` array of function selectors for three reasons:

1. Passing in function signatures enables the implementation of `updateContract` to prevent selector clashes. 
2. A major part of this standard is to make upgradeable contracts more transparent by making it easier to see what has changed over time and why. When a function is added, replaced or removed its function signature is included in the FunctionUpdate event that is emitted. This makes it relatively easy to write software that filters the events of a contract to display to people what functions have been added/removed and changed over time without needing access to the source code or ABI of the contract. If only four-byte function selectors were provided this would not be possible.
3. By looking at the source code of a transparent contract it is not possible to see all the functions that it supports. This is why the ERC1538Query interface exists, so that people and software have a way to look up and examine or show all functions currently supported by a transparent contract. Function signatures are used so that ERC1538Query functions can show them.

### Gas Considerations

Delegating function calls does have some gas overhead. This is mitigated in two ways: 
1. Delegate contracts can be small, reducing gas costs. Because it costs more gas to call a function in a contract with many functions than a contract with few functions.
2. Because transparent contracts do not have a max size limitation it is possible to add gas optimizing functions for use cases. For example someone could use a transparent contract to implement the ERC721 standard and implement batch transfer functions from the [ERC1412 standard](https://github.com/ethereum/EIPs/issues/1412) to help reduce gas (and make batch transfers more convenient).

### Storage

The standard does not specify how data is stored or organized by a transparent contract. But here are some suggestions:

**Inherited Storage**

1. The storage variables of a transparent contract consist of the storage variables defined in the transparent contract source code and the source code of delegate contracts that have been added.

2. A delegate contract can use any storage variable that exists in a transparent contract as long as it defines within it all the storage variables that exist, in the order that they exist, up to and including the ones being used.

3. A delegate contract can create new storage variables as long as it has defined, in the same order, all storage variables that exist in the transparent contract.

Here is a simple way inherited storage could be implemented:

1. Create a storage contract that contains the storage variables that your transparent contract and delegate contracts will use.
2. Make your delegate contracts inherit the storage contract.
3. If you want to add a new delegate contract that adds new storage variables then create a new storage contract that adds the new storage variables and inherits from the old storage contract. Use your new storage contract with your new delegate contract.
4. Repeat steps 2 or 3 for every new delegate contract.


**Unstructured Storage**

Assembly is used to store and read data at specific storage locations. An advantage to this approach is that previously used storage locations don&apos;t have to be defined or mentioned in a delegate contract if they aren&apos;t used by it.

**Eternal Storage**

Data can be stored using a generic API based on the type of data. [See ERC930 for more information.](https://github.com/ethereum/EIPs/issues/930)

### Becoming Immutable
It is possible to make a transparent contract become immutable. This is done by calling the `updateContract` function to remove the `updateContract` function. With this gone it is no longer possible to add, replace and remove functions.

### Versions of Functions

Software or a user can verify what version of a function is called by getting the delegate contract address of the function. This can be done by calling the `delegateAddress` function from the ERC1538Query interface if it is implemented. This function takes a function signature as an argument and returns the delegate contract address where it is implemented.

### Best Practices, Tools and More Information

&gt; More information, tools, tutorials and best practices concerning transparent contracts need to be developed and published. 

Below is a growing list of articles concerning transparent contracts and their use.  If you have an article about transparent contracts you would like to share then please submit a comment to this issue about it to get it added.

[ERC1538: Future Proofing Smart Contracts and Tokens](https://coinjournal.net/erc1538-future-proofing-smart-contacts-and-tokens/)

[The ERC1538 improving towards the “transparent contract” standard](https://www.crypto-economy.net/en/ethereum-eth-erc1538-transparent-contract-standard/)

### Inspiration

This standard was inspired by ZeppelinOS&apos;s implementation of [Upgradeability with vtables](https://github.com/zeppelinos/labs/tree/master/upgradeability_with_vtable). 

This standard was also inspired by the design and implementation of the [Mokens contract](https://etherscan.io/address/0xc1eab49cf9d2e23e43bcf23b36b2be14fc2f8838#code) from the [Mokens project](https://github.com/Mokens/MIPs/blob/master/MIPS/mip-2-Goals-and-Objectives.md). The Mokens contract has been [upgraded to implement this standard](https://etherscan.io/address/0x0ac5637fe62ec14fd9e237a81a9679d4adef701f#code).


## Backwards Compatibility
This standard makes a contract compatible with future standards and functionality because new functions can be added and existing functions can be replaced or removed.

This standard future proofs a contract.

## Implementation
A reference implementation of this standard is given in the [transparent-contracts-erc1538](https://github.com/mudgen/transparent-contracts-erc1538) repository.


## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 31 Oct 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1538</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1538</guid>
      </item>
    
      <item>
        <title>Fee market change for ETH 1.0 chain</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-1559-fee-market-change-for-eth-1-0-chain/2783</comments>
        
        <description>## Simple Summary
A transaction pricing mechanism that includes fixed-per-block network fee that is burned and dynamically expands/contracts block sizes to deal with transient congestion. 

## Abstract
We introduce a new [EIP-2718](/EIPs/EIPS/eip-2718) transaction type, with the format `0x02 || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, amount, data, access_list, signature_y_parity, signature_r, signature_s])`.

There is a base fee per gas in protocol, which can move up or down each block according to a formula which is a function of gas used in parent block and gas target (block gas limit divided by elasticity multiplier) of parent block.
The algorithm results in the base fee per gas increasing when blocks are above the gas target, and decreasing when blocks are below the gas target.
The base fee per gas is burned.
Transactions specify the maximum fee per gas they are willing to give to miners to incentivize them to include their transaction (aka: priority fee).
Transactions also specify the maximum fee per gas they are willing to pay total (aka: max fee), which covers both the priority fee and the block&apos;s network fee per gas (aka: base fee).
Senders will always pay the base fee per gas of the block their transaction was included in, and they will pay the priority fee per gas set in the transaction, as long as the combined amount of the two fees doesn&apos;t exceed the transaction&apos;s maximum fee per gas.

## Motivation
Ethereum historically priced transaction fees using a simple auction mechanism, where users send transactions with bids (&quot;gasprices&quot;) and miners choose transactions with the highest bids, and transactions that get included pay the bid that they specify. This leads to several large sources of inefficiency:

* **Mismatch between volatility of transaction fee levels and social cost of transactions**: bids to include transactions on mature public blockchains, that have enough usage so that blocks are full, tend to be extremely volatile. It&apos;s absurd to suggest that the cost incurred by the network from accepting one more transaction into a block actually is 10x more when the cost per gas is 10 nanoeth compared to when the cost per gas is 1 nanoeth; in both cases, it&apos;s a difference between 8 million gas and 8.02 million gas.
* **Needless delays for users**: because of the hard per-block gas limit coupled with natural volatility in transaction volume, transactions often wait for several blocks before getting included, but this is socially unproductive; no one significantly gains from the fact that there is no &quot;slack&quot; mechanism that allows one block to be bigger and the next block to be smaller to meet block-by-block differences in demand.
* **Inefficiencies of first price auctions**: The current approach, where transaction senders publish a transaction with a bid a maximum fee, miners choose the highest-paying transactions, and everyone pays what they bid. This is well-known in mechanism design literature to be highly inefficient, and so complex fee estimation algorithms are required. But even these algorithms often end up not working very well, leading to frequent fee overpayment.
* **Instability of blockchains with no block reward**: In the long run, blockchains where there is no issuance (including Bitcoin and Zcash) at present intend to switch to rewarding miners entirely through transaction fees. However, there are known issues with this that likely leads to a lot of instability, incentivizing mining &quot;sister blocks&quot; that steal transaction fees, opening up much stronger selfish mining attack vectors, and more. There is at present no good mitigation for this.

The proposal in this EIP is to start with a base fee amount which is adjusted up and down by the protocol based on how congested the network is. When the network exceeds the target per-block gas usage, the base fee increases slightly and when capacity is below the target, it decreases slightly. Because these base fee changes are constrained, the maximum difference in base fee from block to block is predictable. This then allows wallets to auto-set the gas fees for users in a highly reliable fashion. It is expected that most users will not have to manually adjust gas fees, even in periods of high network activity. For most users the base fee will be estimated by their wallet and a small priority fee, which compensates miners taking on orphan risk (e.g. 1 nanoeth), will be automatically set. Users can also manually set the transaction max fee to bound their total costs.

An important aspect of this fee system is that miners only get to keep the priority fee. The base fee is always burned (i.e. it is destroyed by the protocol). This ensures that only ETH can ever be used to pay for transactions on Ethereum, cementing the economic value of ETH within the Ethereum platform and reducing risks associated with miner extractable value (MEV). Additionally, this burn counterbalances Ethereum inflation while still giving the block reward and priority fee to miners. Finally, ensuring the miner of a block does not receive the base fee is important because it removes miner incentive to manipulate the fee in order to extract more fees from users.

## Specification
Block validity is defined in the reference implementation below.
The `GASPRICE` (`0x3a`) opcode **MUST** return the `effective_gas_price` as defined in the reference implementation below.

As of `FORK_BLOCK_NUMBER`, a new [EIP-2718](/EIPs/EIPS/eip-2718) transaction is introduced with `TransactionType` 2.

The intrinsic cost of the new transaction is inherited from [EIP-2930](/EIPs/EIPS/eip-2930), specifically `21000 + 16 * non-zero calldata bytes + 4 * zero calldata bytes + 1900 * access list storage key count + 2400 * access list address count`.

The [EIP-2718](/EIPs/EIPS/eip-2718) `TransactionPayload` for this transaction is `rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, amount, data, access_list, signature_y_parity, signature_r, signature_s])`.

The `signature_y_parity, signature_r, signature_s` elements of this transaction represent a secp256k1 signature over `keccak256(0x02 || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, amount, data, access_list]))`.

The [EIP-2718](/EIPs/EIPS/eip-2718) `ReceiptPayload` for this transaction is `rlp([status, cumulative_transaction_gas_used, logs_bloom, logs])`.

*Note: `//` is integer division, round down.*
```python
from typing import Union, Dict, Sequence, List, Tuple, Literal
from dataclasses import dataclass, field
from abc import ABC, abstractmethod

@dataclass
class TransactionLegacy:
	signer_nonce: int = 0
	gas_price: int = 0
	gas_limit: int = 0
	destination: int = 0
	amount: int = 0
	payload: bytes = bytes()
	v: int = 0
	r: int = 0
	s: int = 0

@dataclass
class Transaction2930Payload:
	chain_id: int = 0
	signer_nonce: int = 0
	gas_price: int = 0
	gas_limit: int = 0
	destination: int = 0
	amount: int = 0
	payload: bytes = bytes()
	access_list: List[Tuple[int, List[int]]] = field(default_factory=list)
	signature_y_parity: bool = False
	signature_r: int = 0
	signature_s: int = 0

@dataclass
class Transaction2930Envelope:
	type: Literal[1] = 1
	payload: Transaction2930Payload = Transaction2930Payload()

@dataclass
class Transaction1559Payload:
	chain_id: int = 0
	signer_nonce: int = 0
	max_priority_fee_per_gas: int = 0
	max_fee_per_gas: int = 0
	gas_limit: int = 0
	destination: int = 0
	amount: int = 0
	payload: bytes = bytes()
	access_list: List[Tuple[int, List[int]]] = field(default_factory=list)
	signature_y_parity: bool = False
	signature_r: int = 0
	signature_s: int = 0

@dataclass
class Transaction1559Envelope:
	type: Literal[2] = 2
	payload: Transaction1559Payload = Transaction1559Payload()

Transaction2718 = Union[Transaction1559Envelope, Transaction2930Envelope]

Transaction = Union[TransactionLegacy, Transaction2718]

@dataclass
class NormalizedTransaction:
	signer_address: int = 0
	signer_nonce: int = 0
	max_priority_fee_per_gas: int = 0
	max_fee_per_gas: int = 0
	gas_limit: int = 0
	destination: int = 0
	amount: int = 0
	payload: bytes = bytes()
	access_list: List[Tuple[int, List[int]]] = field(default_factory=list)

@dataclass
class Block:
	parent_hash: int = 0
	uncle_hashes: Sequence[int] = field(default_factory=list)
	author: int = 0
	state_root: int = 0
	transaction_root: int = 0
	transaction_receipt_root: int = 0
	logs_bloom: int = 0
	difficulty: int = 0
	number: int = 0
	gas_limit: int = 0 # note the gas_limit is the gas_target * ELASTICITY_MULTIPLIER
	gas_used: int = 0
	timestamp: int = 0
	extra_data: bytes = bytes()
	proof_of_work: int = 0
	nonce: int = 0
	base_fee_per_gas: int = 0

@dataclass
class Account:
	address: int = 0
	nonce: int = 0
	balance: int = 0
	storage_root: int = 0
	code_hash: int = 0

INITIAL_BASE_FEE = 1000000000
INITIAL_FORK_BLOCK_NUMBER = 10 # TBD
BASE_FEE_MAX_CHANGE_DENOMINATOR = 8
ELASTICITY_MULTIPLIER = 2

class World(ABC):
	def validate_block(self, block: Block) -&gt; None:
		parent_gas_target = self.parent(block).gas_limit // ELASTICITY_MULTIPLIER
		parent_gas_limit = self.parent(block).gas_limit

		# on the fork block, don&apos;t account for the ELASTICITY_MULTIPLIER to avoid
		# unduly halving the gas target.
		if INITIAL_FORK_BLOCK_NUMBER == block.number:
			parent_gas_target = self.parent(block).gas_limit
			parent_gas_limit = self.parent(block).gas_limit * ELASTICITY_MULTIPLIER 

		parent_base_fee_per_gas = self.parent(block).base_fee_per_gas
		parent_gas_used = self.parent(block).gas_used
		transactions = self.transactions(block)

		# check if the block used too much gas
		assert block.gas_used &lt;= block.gas_limit, &apos;invalid block: too much gas used&apos;

		# check if the block changed the gas limit too much
		assert block.gas_limit &lt; parent_gas_limit + parent_gas_limit // 1024, &apos;invalid block: gas limit increased too much&apos;
		assert block.gas_limit &gt; parent_gas_limit - parent_gas_limit // 1024, &apos;invalid block: gas limit decreased too much&apos;

		# check if the gas limit is at least the minimum gas limit
		assert block.gas_limit &gt;= 5000

		# check if the base fee is correct
		if INITIAL_FORK_BLOCK_NUMBER == block.number:
			expected_base_fee_per_gas = INITIAL_BASE_FEE
		elif parent_gas_used == parent_gas_target:
			expected_base_fee_per_gas = parent_base_fee_per_gas
		elif parent_gas_used &gt; parent_gas_target:
			gas_used_delta = parent_gas_used - parent_gas_target
			base_fee_per_gas_delta = max(parent_base_fee_per_gas * gas_used_delta // parent_gas_target // BASE_FEE_MAX_CHANGE_DENOMINATOR, 1)
			expected_base_fee_per_gas = parent_base_fee_per_gas + base_fee_per_gas_delta
		else:
			gas_used_delta = parent_gas_target - parent_gas_used
			base_fee_per_gas_delta = parent_base_fee_per_gas * gas_used_delta // parent_gas_target // BASE_FEE_MAX_CHANGE_DENOMINATOR
			expected_base_fee_per_gas = parent_base_fee_per_gas - base_fee_per_gas_delta
		assert expected_base_fee_per_gas == block.base_fee_per_gas, &apos;invalid block: base fee not correct&apos;

		# execute transactions and do gas accounting
		cumulative_transaction_gas_used = 0
		for unnormalized_transaction in transactions:
			# Note: this validates transaction signature and chain ID which must happen before we normalize below since normalized transactions don&apos;t include signature or chain ID
			signer_address = self.validate_and_recover_signer_address(unnormalized_transaction)
			transaction = self.normalize_transaction(unnormalized_transaction, signer_address)

			signer = self.account(signer_address)

			signer.balance -= transaction.amount
			assert signer.balance &gt;= 0, &apos;invalid transaction: signer does not have enough ETH to cover attached value&apos;
			# the signer must be able to afford the transaction
			assert signer.balance &gt;= transaction.gas_limit * transaction.max_fee_per_gas

			# ensure that the user was willing to at least pay the base fee
			assert transaction.max_fee_per_gas &gt;= block.base_fee_per_gas

			# Prevent impossibly large numbers
			assert transaction.max_fee_per_gas &lt; 2**256
			# Prevent impossibly large numbers
			assert transaction.max_priority_fee_per_gas &lt; 2**256
			# The total must be the larger of the two
			assert transaction.max_fee_per_gas &gt;= transaction.max_priority_fee_per_gas

			# priority fee is capped because the base fee is filled first
			priority_fee_per_gas = min(transaction.max_priority_fee_per_gas, transaction.max_fee_per_gas - block.base_fee_per_gas)
			# signer pays both the priority fee and the base fee
			effective_gas_price = priority_fee_per_gas + block.base_fee_per_gas
			signer.balance -= transaction.gas_limit * effective_gas_price
			assert signer.balance &gt;= 0, &apos;invalid transaction: signer does not have enough ETH to cover gas&apos;
			gas_used = self.execute_transaction(transaction, effective_gas_price)
			gas_refund = transaction.gas_limit - gas_used
			cumulative_transaction_gas_used += gas_used
			# signer gets refunded for unused gas
			signer.balance += gas_refund * effective_gas_price
			# miner only receives the priority fee; note that the base fee is not given to anyone (it is burned)
			self.account(block.author).balance += gas_used * priority_fee_per_gas

		# check if the block spent too much gas transactions
		assert cumulative_transaction_gas_used == block.gas_used, &apos;invalid block: gas_used does not equal total gas used in all transactions&apos;

		# TODO: verify account balances match block&apos;s account balances (via state root comparison)
		# TODO: validate the rest of the block

	def normalize_transaction(self, transaction: Transaction, signer_address: int) -&gt; NormalizedTransaction:
		# legacy transactions
		if isinstance(transaction, TransactionLegacy):
			return NormalizedTransaction(
				signer_address = signer_address,
				signer_nonce = transaction.signer_nonce,
				gas_limit = transaction.gas_limit,
				max_priority_fee_per_gas = transaction.gas_price,
				max_fee_per_gas = transaction.gas_price,
				destination = transaction.destination,
				amount = transaction.amount,
				payload = transaction.payload,
				access_list = [],
			)
		# 2930 transactions
		elif isinstance(transaction, Transaction2930Envelope):
			return NormalizedTransaction(
				signer_address = signer_address,
				signer_nonce = transaction.payload.signer_nonce,
				gas_limit = transaction.payload.gas_limit,
				max_priority_fee_per_gas = transaction.payload.gas_price,
				max_fee_per_gas = transaction.payload.gas_price,
				destination = transaction.payload.destination,
				amount = transaction.payload.amount,
				payload = transaction.payload.payload,
				access_list = transaction.payload.access_list,
			)
		# 1559 transactions
		elif isinstance(transaction, Transaction1559Envelope):
			return NormalizedTransaction(
				signer_address = signer_address,
				signer_nonce = transaction.payload.signer_nonce,
				gas_limit = transaction.payload.gas_limit,
				max_priority_fee_per_gas = transaction.payload.max_priority_fee_per_gas,
				max_fee_per_gas = transaction.payload.max_fee_per_gas,
				destination = transaction.payload.destination,
				amount = transaction.payload.amount,
				payload = transaction.payload.payload,
				access_list = transaction.payload.access_list,
			)
		else:
			raise Exception(&apos;invalid transaction: unexpected number of items&apos;)

	@abstractmethod
	def parent(self, block: Block) -&gt; Block: pass

	@abstractmethod
	def block_hash(self, block: Block) -&gt; int: pass

	@abstractmethod
	def transactions(self, block: Block) -&gt; Sequence[Transaction]: pass

	# effective_gas_price is the value returned by the GASPRICE (0x3a) opcode
	@abstractmethod
	def execute_transaction(self, transaction: NormalizedTransaction, effective_gas_price: int) -&gt; int: pass

	@abstractmethod
	def validate_and_recover_signer_address(self, transaction: Transaction) -&gt; int: pass

	@abstractmethod
	def account(self, address: int) -&gt; Account: pass
```

## Backwards Compatibility
Legacy Ethereum transactions will still work and be included in blocks, but they will not benefit directly from the new pricing system.  This is due to the fact that upgrading from legacy transactions to new transactions results in the legacy transaction&apos;s `gas_price ` entirely being consumed either by the `base_fee_per_gas` and the `priority_fee_per_gas`.

### Block Hash Changing
The datastructure that is passed into keccak256 to calculate the block hash is changing, and all applications that are validating blocks are valid or using the block hash to verify block contents will need to be adapted to support the new datastructure (one additional item).  If you only take the block header bytes and hash them you should still correctly get a hash, but if you construct a block header from its constituent elements you will need to add in the new one at the end.

### GASPRICE
Previous to this change, `GASPRICE` represented both the ETH paid by the signer per gas for a transaction as well as the ETH received by the miner per gas.  As of this change, `GASPRICE` now only represents the amount of ETH paid by the signer per gas, and the amount a miner was paid for the transaction is no longer accessible directly in the EVM.

## Security Considerations
### Increased Max Block Size/Complexity
This EIP will increase the maximum block size, which could cause problems if miners are unable to process a block fast enough as it will force them to mine an empty block.  Over time, the average block size should remain about the same as without this EIP, so this is only an issue for short term size bursts.  It is possible that one or more clients may handle short term size bursts poorly and error (such as out of memory or similar) and client implementations should make sure their clients can appropriately handle individual blocks up to max size.

### Transaction Ordering
With most people not competing on priority fees and instead using a baseline fee to get included, transaction ordering now depends on individual client internal implementation details such as how they store the transactions in memory.  It is recommended that transactions with the same priority fee be sorted by time the transaction was received to protect the network from spamming attacks where the attacker throws a bunch of transactions into the pending pool in order to ensure that at least one lands in a favorable position.  Miners should still prefer higher gas premium transactions over those with a lower gas premium, purely from a selfish mining perspective.

### Miners Mining Empty Blocks
It is possible that miners will mine empty blocks until such time as the base fee is very low and then proceed to mine half full blocks and revert to sorting transactions by the priority fee.  While this attack is possible, it is not a particularly stable equilibrium as long as mining is decentralized.  Any defector from this strategy will be more profitable than a miner participating in the attack for as long as the attack continues (even after the base fee reached 0).  Since any miner can anonymously defect from a cartel, and there is no way to prove that a particular miner defected, the only feasible way to execute this attack would be to control 50% or more of hashing power.  If an attacker had exactly 50% of hashing power, they would make no Ether from priority fee while defectors would make double the Ether from priority fees.  For an attacker to turn a profit, they need to have some amount over 50% hashing power, which means they can instead execute double spend attacks or simply ignore any other miners which is a far more profitable strategy.

Should a miner attempt to execute this attack, we can simply increase the elasticity multiplier (currently 2x) which requires they have even more hashing power available before the attack can even be theoretically profitable against defectors.

### ETH Burn Precludes Fixed Supply
By burning the base fee, we can no longer guarantee a fixed Ether supply.  This could result in economic instability as the long term supply of ETH will no longer be constant over time.  While a valid concern, it is difficult to quantify how much of an impact this will have.  If more is burned on base fee than is generated in mining rewards then ETH will be deflationary and if more is generated in mining rewards than is burned then ETH will be inflationary.  Since we cannot control user demand for block space, we cannot assert at the moment whether ETH will end up inflationary or deflationary, so this change causes the core developers to lose some control over Ether&apos;s long term quantity.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 13 Apr 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1559</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1559</guid>
      </item>
    
      <item>
        <title>EthereumStratum/2.0.0</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://github.com/AndreaLanfranchi/EthereumStratum-2.0.0/issues</comments>
        
        <description>## Abstract

This draft contains the guidelines to define a new standard for the Stratum protocol used by Ethereum miners to communicate with mining pool servers.

### Conventions

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](https://tools.ietf.org/html/rfc2119).
The definition `mining pool server`, and it&apos;s plural form, is to be interpreted as `work provider` and later in this document can be shortened as `pool` or `server`.
The definition `miner(s)`, and it&apos;s plural form, is to be interpreted as `work receiver/processor` and later in this document can be shortened as `miner` or `client`.

### Rationale

Ethereum does not have an official Stratum implementation yet. It officially supports only getWork which requires miners to constantly pool the work provider. Only recently go-ethereum have implemented a [push mechanism](https://github.com/ethereum/go-ethereum/pull/17347) to notify clients for mining work, but whereas the vast majority of miners do not run a node, it&apos;s main purpose is to facilitate mining pools rather than miners.
The Stratum protocol on the other hand relies on a standard stateful TCP connection which allows two-way exchange of line-based messages. Each line contains the string representation of a JSON object following the rules of either [JSON-RPC 1.0](https://www.jsonrpc.org/specification_v1) or [JSON-RPC 2.0](https://www.jsonrpc.org/specification).
Unfortunately, in absence of a well defined standard, various flavours of Stratum have bloomed for Ethereum mining as a derivative work for different mining pools implementations. The only attempt to define a standard was made by NiceHash with their [EthereumStratum/1.0.0](https://github.com/nicehash/Specifications/blob/master/EthereumStratum_NiceHash_v1.0.0.txt) implementation which is the main source this work inspires from.
Mining activity, thus the interaction among pools and miners, is at it&apos;s basics very simple, and can be summarized with &quot;_please find a number (nonce) which coupled to this data as input for a given hashing algorithm produces, as output, a result which is below a certain target_&quot;. Other messages which may or have to be exchanged among parties during a session are needed to support this basic concept.
Due to the simplicity of the subject, the proponent, means to stick with JSON formatted objects rather than investigating more verbose solutions, like for example  [Google&apos;s Protocol Buffers](https://developers.google.com/protocol-buffers/docs/overview) which carry the load of strict object definition.

### Stratum design flaws

The main Stratum design flaw is the absence of a well defined standard. This implies that miners (and mining software developers) have to struggle with different flavours which make their life hard when switching from one pool to another or even when trying to &quot;guess&quot; which is the flavour implemented by a single pool. Moreover all implementations still suffer from an excessive verbosity for a chain with a very small block time like Ethereum. A few numbers may help understand. A normal `mining.notify` message weigh roughly 240 bytes: assuming the dispatch of 1 work per block to an audience of 50k connected TCP sockets means the transmission of roughly 1.88TB of data a month. And this can be an issue for large pools. But if we see the same figures the other way round, from a miner&apos;s perspective, we totally understand how mining decentralization is heavily affected by the quality of internet connections.

### Sources of inspiration

- [NiceHash EthereumStratum/1.0.0](https://github.com/nicehash/Specifications/blob/master/EthereumStratum_NiceHash_v1.0.0.txt)
- [Zcash variant of the Stratum protocol](https://github.com/zcash/zips/blob/23d74b0373c824dd51c7854c0e3ea22489ba1b76/drafts/str4d-stratum/draft1.rst#json-rpc-1-0)

## Specification

The Stratum protocol is an instance of [JSON-RPC-2.0](https://www.jsonrpc.org/specification). The miner is a JSON-RPC client, and the server is a JSON-RPC server. All communications exist within the scope of a `session`. A session starts at the moment a client opens a TCP connection to the server till the moment either party do voluntary close the very same connection or it gets broken. Servers **MAY** support session resuming if this is initially negotiated (on first session handshaking) between the client and the server. During a session all messages exchanged among server and client are line-based which means all messages are JSON strings terminated by ASCII LF character (which may also be denoted as `\n` in this document). The LF character **MUST NOT** appear elsewhere in a message. Client and server implementations **MUST** assume that once they read a LF character, the current message has been completely received and can be processed.
Line messages are of three types:

- `Requests` : messages for which the issuer expects a response. The receiver **MUST** reply back to any request individually
- `Responses` : solicited messages by a previous request. The responder **MUST** label the response with the same identifier of the originating request.
- `Notifications` : unsolicited messages for which the issuer is not interested nor is expecting a response. Nevertheless a response (eg. an acknowledgement) **MAY** be sent by the receiver.

During a `session` both parties **CAN** exchange messages of the above depicted three types.

### JSON-RPC-2.0 Compliances

As per [JSON-RPC-2.0](https://www.jsonrpc.org/specification) specification requests and responses differ from notifications by the identifier (`id`) member in the JSON object:

- Requests **MUST** have an `id` member
- Responses **MUST** have an `id` member valued exactly as the `id` member of the request this response is for
- Notifications **MUST NOT** have an `id` member

### JSON-RPC-2.0 Defiances

In order to get the most concise messages among parties of a session/conversation this implementation enforces the following defiances:

- JSON member `jsonrpc` (always valued to &quot;2.0&quot;) **MUST ALWAYS BE OMITTED**
- JSON member `id` **MUST NOT** be `null`. When member is present, mandatorily in requests and responses, it **MUST** be valued to an integer Number ranging from 0 to 65535. Please note that a message with `&quot;id&quot;: 0` **MUST NOT** be interpreted as a notification: it&apos;s a request with identifier 0
- JSON member `id` **MUST** be only of type primitive number. The removal of other identifier types (namely strings) is due to the need to reduce the number of bytes transferred.

## Conventions

- The representation of a JSON object is, at it&apos;s base, a string 
- The conversation among the client and the server is made of strings. Each string ending with a LF (ASCII char 10) denotes a `line`. Each line **MUST** contain only one JSON root object. Eventually the root object **MAY** contain additional JSON objects in it&apos;s members.
- Aside the `LF` delimiter each `line` **MUST** be made of printable ASCII chars in the range 32..126
- It&apos;s implicit and mandatory that each line message corresponds to a well formatted JSON object: see [JSON documentation](https://www.json.org/)
- JSON objects are made of `members` which can be of type : primitive of string/number, JSON object, JSON arrays
- JSON `member`&apos;s names are strings which **MUST** be composed of printable chars only in the ASCII range 48..57 (numbers) and 97..122 (lower case letters).
- JSON `member`&apos;s names **MUST NOT** begin with a number.
- JSON values `arrays` : although the JSON notation allows the insertion of different data types within the same array, this behavior is generally not accepted in coding languages. Due to this, by the means of EthereumStratum/2.0.0, all implementers **MUST** assume that an array is made of elements of the very same data type.
- JSON values `booleans` : the JSON notation allows to express boolean values as `true` or `false`. In EthereumStratum/2.0.0, for better compatibility within arrays, boolean values will be expressed in the hex form of &quot;0&quot; (false) or &quot;1&quot; (true)
- JSON values `strings` : any string value **MUST** be composed of printable ASCII chars only in the ASCII range 32..126. Each string is delimited by a `&quot;` (ASCII 34) at the beginning and at the end. Should the string value contain a `&quot;` this must be escaped as `\&quot;`
- Hex values : a Hexadecimal representation of a number is actually a string data type. As a convention, and to reduce the number of transmitted bytes, the prefix &quot;0x&quot; **MUST** always be omitted. In addition any hex number **MUST** be transferred only for their significant part i.e. the non significant zeroes **MUST** be omitted (example : the decimal `456` must be represented as `&quot;1c8&quot;` and not as `&quot;01c8&quot;` although the conversion produces the same decimal value). This directive **DOES NOT APPLY** to hashes and extranonces
- Hex values casing : all letters in Hexadecimal values **MUST** be lower case. (example : the decimal `456` must be represented as `&quot;1c8&quot;` and not as `&quot;1C8&quot;` although the conversion produces the same decimal value). This directive **DOES NOT APPLY** to hashes.
- Numbers : any non-fractional number **MUST** be transferred by it&apos;s hexadecimal representation

### Requests

The JSON representation of `request` object is made of these parts:

- mandatory `id` member of type Integer : the identifier established by the issuer
- mandatory `method` member of type String : the name of the method to be invoked on the receiver side
- optional `params` member : in case the method invocation on the receiver side requires the application of additional parameters to be executed. The type **CAN** be Object (with named members of different types) or Array of single type. In case of an array the parameters will be applied by their ordinal position. If the method requested for invocation on the receiver side does not require the application of additional parameters this member **MUST NOT** be present. The notation `&quot;params&quot; : null` **IS NOT PERMITTED**

### Responses

The JSON representation of `response` object is made of these parts:

- mandatory `id` member of type Integer : the identifier of the request this response corresponds to
- optional `error` member : whether an error occurred during the parsing of the method or during it&apos;s execution this member **MUST** be present and valued. If no errors occurred this member **MUST NOT** be present. For a detailed structure of the `error` member see below.
- optional `result` member : This has to be set, if the corresponding request requires a result from the user. If no errors occurred by invoking the corresponding function, this member **MUST** be present even if one or more information are null. The type can be of Object or single type Array or Primitive string/number. If no data is meant back for the issuer (the method is void on the receiver) or an error occurred this member **MUST NOT** be present.

You&apos;ll notice here some differences with standard JSON-RPC-2.0. Namely the result member is not always required. Basically a response like this:

```json
{&quot;id&quot;: 2}
```

means &quot;request received and processed correctly with no data to send back&quot;.

To better clarify the concept and clear the field of free interpretations let&apos;s take another example of **wrong response**

```json
{&quot;id&quot;: 2, &quot;result&quot;: false}
```

This response syntax leaves room to many interpretations: is it an error? is `false` the legit response value to the issued request?

For this reason responses, we reiterate, **MUST BE** of two types:

- success responses : no error occurred during the processing, the request was legit, syntactically correct, and the receiver had no issues processing it. This kind of responses **MUST NOT** have the `error` member and **MAY** have the `result` member if a value is expected back to the issuer.
- failure responses : something wrong with the request, it&apos;s syntax, it&apos;s validity scope, or server processing problems. This kind of responses **MUST HAVE** the `error` member and **MAY** have the `result` member.

The latter deserves a better explanation: failure responses can be distinguished by a severity degree. 
Example 1 : a client submits a solution and server rejects it cause it&apos;s not below target. Server **MUST** respond like this; 

```json
{
  &quot;id&quot;: 31,
  &quot;error&quot;: {
      &quot;code&quot;: 406,
      &quot;message&quot; : &quot;Bad nonce&quot;
  }
}
```

Example 2 : a client submits a solution and server **accepts** it **but** it accounts the share as stale. Server **MUST** respond like this;

```json
{
  &quot;id&quot;: 31,
  &quot;error&quot;: {
      &quot;code&quot;: 202,
      &quot;message&quot; : &quot;Stale&quot;
  }
}
```

Example 3 : a client submits an authorization request specifying an invalid workername. Server authorizes the account but rejects worker name. Server **MUST** respond like this;

```json
{
  &quot;id&quot;: 1,
  &quot;error&quot;: {
      &quot;code&quot;: 215,
      &quot;message&quot; : &quot;Invalid Worker Name&quot;
  }
}
```

Example 1 depicts the condition of a severe failure while Example 2 and 3 depict a situation where the request has been accepted and processed properly but the result **MAY NOT** be what expected by the client.
It&apos;s up to the client to evaluate the severity of the error and decide whether to proceed or not.

Using proper error codes pools may properly inform miners of the condition of their requests. Error codes **MUST** honor this scheme:

- Error codes 2xx : request accepted and processed but some additional info in the `error` member may give hint
- Error codes 3xx : server could not process the request due to a lack of authorization by the client
- Error codes 4xx : server could not process the request due to syntactic problems (method not found, missing params, wrong data types ecc.) or passed `param` values are not valid.
- Error codes 5xx : server could not process the request due to internal errors

### Notifications

A notification message has the very same representation of a `request` with the only difference the `id` member **MUST NOT** be present. This means the issuer is not interested nor expects any response to this message. It&apos;s up to the receiver to take actions accordingly. For instance the receiver **MAY** decide to execute the method, or, in case of errors or methods not allowed, drop the connection thus closing the session.

#### Error member

As seen above a `response` **MAY** contain an `error` member. When present this member **MUST** be an Object with:

- mandatory member `code` : a Number which identifies the error occurred
- mandatory member `message` : a short human readable sentence describing the error occurred
- optional member `data` : a Structured or Primitive value that contains additional information about the error. The value of this member is defined by the Server (e.g. detailed error information, nested errors etc.).

## Protocol Flow

- Client starts session by opening a TCP socket to the server
- Client advertises and request protocol compatibility
- Server confirms compatibility and declares ready
- Client starts/resumes a session
- Client sends request for authorization for each of it&apos;s workers
- Server replies back with responses for each authorization
- Server sends `mining.set` for constant values to be adopted for following mining jobs
- Server sends `mining.notify` with minimal job info
- Client mines on job
- Client sends `mining.submit` if any solution found for the job
- Server replies whether solution is accepted
- Server optionally sends `mining.set` for constant values to be adopted for following mining jobs (if something changed)
- Server sends `mining.notify` with minimal job info
- ... (continue)
- Eventually either party closes session and TCP connection

### Session Handling - Hello

~~One of the worst annoyances until now is that server, at the very moment of socket connection, does not provide any useful information about the stratum flavour implemented. This means the client has to start a conversation by iteratively trying to connect via different protocol flavours. This proposal amends the situation making mandatory for the server to advertise itself to the client. 
When a new client connects to the server, the server **MUST** send a `mining.hello` notification :~~

It&apos;s been noted that charging the server of the duty to advertise itself as first message of the conversation could potentially be harmful in respect of traffic amplification attacks using spoofed IP addresses or in traditional DDos attacks where an attacker need to spend very little resources to force the server to send a large packet back.
For this reason the duty of first advertisement is kept on client which will issue a `mining.hello` request like this:

```json
{
  &quot;id&quot; : 0,
  &quot;method&quot;: &quot;mining.hello&quot;, 
  &quot;params&quot;: 
  { 
    &quot;agent&quot;: &quot;ethminer-0.17&quot;,
    &quot;host&quot; : &quot;somemininigpool.com&quot;,
    &quot;port&quot; : &quot;4d2&quot;,
    &quot;proto&quot;: &quot;EthereumStratum/2.0.0&quot;
  }
}
```

The `params` member object has these mandatory members:

- `agent` (string) the mining software version
- `host` (string) the host name of the server this client is willing to connect to
- `port` (hex) the port number of the server this client is willing to connect to
- `proto` (string) which reports the stratum flavour requested and expected to be implemented by the server;

The rationale behind sending host and port is it enables virtual hosting, where virtual pools or private URLs might be used for DDoS protection, but that are aggregated on Stratum server backends. As with HTTP, the server CANNOT trust the host string. The port is included separately to parallel the client.reconnect method (see below).

If the server is prepared to start/resume a session with such requirements it **MUST** reply back with a response like this:

```json
{
  &quot;id&quot; : 0,
  &quot;result&quot;: 
  { 
    &quot;proto&quot; : &quot;EthereumStratum/2.0.0&quot;,
    &quot;encoding&quot; : &quot;gzip&quot;,
    &quot;resume&quot; : &quot;1&quot;,
    &quot;timeout&quot; : &quot;b4&quot;,
    &quot;maxerrors&quot; : &quot;5&quot;,
    &quot;node&quot; : &quot;Geth/v1.8.18-unstable-f08f596a/linux-amd64/go1.10.4&quot;
  } 
}
```

Where the `result` is an object made of 5 mandatory members

- `proto` (string) which **MUST** match the exact version requested by the client
- `encoding` (string) which value states whether or not all **next messages** should be gzip compressed or not. Possible values are &quot;gzip&quot; or &quot;plain&quot;
- `resume` (hex) which value states whether or not the host can resume a previously created session;
- `timeout` (hex) which reports the number of seconds after which the server is allowed to drop connection if no messages from the client
- `maxerrors` (hex) the maximum number of errors the server will bear before abruptly close connection
- `node` (string) the node software version underlying the pool

When the server replies back with `&quot;encoding&quot; : &quot;gzip&quot;` to the client, both parties **MUST** gzip compress all next messages. In case the client is not capable of compression it **MUST** close the connection immediately.
Should the server, after this reply, receive other messages as plain text, it **MUST** close the connection.

Eventually the client will continue with `mining.subscribe` (further on descripted)

Otherwise, in case of errors or rejection to start the conversation, the server **MAY** reply back with an error giving the other party useful information or, at server&apos;s maintainers discretion, abruptly close the connection.

```json
{
  &quot;id&quot; : 0,
  &quot;error&quot;: 
  { 
      &quot;code&quot;: 400,
      &quot;message&quot; : &quot;Bad protocol request&quot;
  } 
}
```

or 

```json
{
  &quot;id&quot; : 0,
  &quot;error&quot;: 
  { 
      &quot;code&quot;: 403,
      &quot;message&quot; : &quot;Forbidden - Banned IP address&quot;
  } 
}
```

_The above two JSON error values are only samples_
Eventually the server will close the connection.

Why a pool should advertise the node&apos;s version? It&apos;s a matter of transparency : miners should know whether or not pool have upgraded to latest patches/releases for node&apos;s software.

### Session Handling - Bye

Disconnection are not gracefully handled in Stratum. Client disconnections from pool may be due to several errors and this leads to waste of TCP sockets on server&apos;s side which wait for keepalive timeouts to trigger. A useful notification is `mining.bye` which, once processed, allows both parties of the session to stop receiving and gracefully close TCP connections

```json
{
  &quot;method&quot;: &quot;mining.bye&quot;
}
```

The party receiving this message aknowledges the other party wants to stop the conversation and closes the socket. The issuer will close too. The explicit issuance of this notification implies the session gets abandoned so no session resuming will be possible even on server which support session-resuming. Client reconnecting to the same server which implements session resuming **SHOULD** expect a new session id and **MUST** re-authorize all their workers.

### Session Handling - Session Subscription

After receiving the response to `mining.hello` from server, the client, in case the server does support session resuming **MAY** request to resume a previously interrupted session with `mining.subscribe` request:

```json
{
  &quot;id&quot;: 1,
  &quot;method&quot;: &quot;mining.subscribe&quot;, 
  &quot;params&quot;: &quot;s-12345&quot;
}
```

where `params` is the id of the session the client wants to resume.

Otherwise, if client wants to start a new session **OR** server does not support session resuming, the request of subscription **MUST** omit the `params` member:

```json
{
  &quot;id&quot;: 1,
  &quot;method&quot;: &quot;mining.subscribe&quot;
}
```

### Session Handling - Response to Subscription

A server receiving a client session subscription **MUST** reply back with

```json
{
  &quot;id&quot;: 1,
  &quot;result&quot;: &quot;s-12345&quot;
}
```

A server receiving a subscription request with `params` being a string holding the session id. This cases may apply

- If session resuming is not supported `result` will hold a new session Id which **MUST** be a different value from the `session` member issued by client in previous `mining.subscribe` method 
- If session resuming is supported it will retrieve working values from cache and `result` will have the same id requested by the client. This means a session is &quot;resumed&quot;: as a consequence the server **CAN** start pushing jobs omitting to precede them with `mining.set` (see below) and the client **MUST** continue to use values lastly received within the same session scope. In addition the client **CAN** omit to re-authorize all it&apos;s workers.
- If session resuming is supported but the requested session has expired or it&apos;s cache values have been purged `result` will hold a new session Id which **MUST** be a different value from the `session` member issued by client in previous `mining.subscribe` method. As a consequence the server **MUST** wait for client to request authorization for it&apos;s workers and **MUST** send `mining.set` values before pushing jobs. The client **MUST** prepare for a new session discarding all previously cached values (if any).

A server implementing session-resuming **MUST** cache:

- The session Ids
- Any active job per session
- The extraNonce
- Any authorized worker

Servers **MAY** drop entries from the cache on their own schedule. It&apos;s up to server to enforce session validation for same agent and/or ip.

A client which successfully subscribes and resumes session (the `session` value in server response is identical to `session` value requested by client on `mining.subscribe`) **CAN** omit to issue the authorization request for it&apos;s workers.

### Session Handling - Noop

There are cases when a miner struggles to find a solution in a reasonable time so it may trigger the timeout imposed by the server in case of no communications (the server, in fact, may think the client got disconnected). To mitigate the problem a new method `mining.noop`(with no additional parameters) may be requested by the client. 

```json
{
  &quot;id&quot;: 50,
  &quot;method&quot;: &quot;mining.noop&quot;
}
```

### Session Handling - Reconnect

Under certain circumstances the server may need to free some resources and or to relocate miners to another machine. Until now the only option for servers was to abruptly close the connection. On the miner&apos;s side this action is interpreted as a server malfunction and they, more often than not, switch to a failover pool. 
The implementation of the notification `mining.reconnect` helps client to better merge with logic of handling of large mining pools. 

```json
{
  &quot;method&quot;: &quot;mining.reconnect&quot;,
  &quot;params&quot;: {
      &quot;host&quot;: &quot;someotherhost.com&quot;,
      &quot;port&quot;: &quot;d80&quot;,
      &quot;resume&quot;: &quot;1&quot;
  }
}
```

This notification is meant only from servers to clients. Should a server receive such a notification it will simply ignore it. After the notification has been properly sent, the server is ALLOWED to close the connection, while the client will take the proper actions to reconnect to the suggested end-point.
The `host` member in `params` object **SHOULD** report a host DNS name and not an IP address: TLS encrypted connections require to validate the CN name in the certificate which, 99% of the cases, is a host name. 
The third member `resume` of the `params` object sets whether or not the receiving server is prepared for session resuming.
After this notification has been issued by the server, the client should expect no further messages and **MUST** disconnect.

### Workers Authorization

The miner **MUST** authorize at least one worker in order to begin receiving jobs and submit solutions or hashrates. The miner **MAY** authorize multiple workers in the same session. The server **MUST** allow authorization for multiple workers within a session and **MUST** validate at least one authorization from the client before starting to send jobs. A `worker` is a tuple of the address where rewards must be credited coupled with identifier of the machine actually doing the work. For Ethereum the most common form is `&lt;account&gt;.&lt;MachineName&gt;`. The same account can be bound to multiple machines. For pool&apos;s allowing anonymous mining the account is the address where rewards must be credited, while, for pools requiring registration, the account is the login name. Each time a solution is submitted by the client it must be labelled with the Worker identifier. It&apos;s up to server to keep the correct accounting for different addresses.

The syntax for the authorization request is the following:

```json
{
  &quot;id&quot;: 2,
  &quot;method&quot;: &quot;mining.authorize&quot;, 
  &quot;params&quot;: [&quot;&lt;account&gt;[.&lt;MachineName&gt;]&quot;, &quot;password&quot;]
}
```

`params` member must be an Array of 2 string elements. For anonymous mining the &quot;password&quot; can be any string value or empty but not null. Pools allowing anonymous mining will simply ignore the value.
The server **MUST** reply back either with an error or, in case of success, with

```json
{
  &quot;id&quot;: 2,
  &quot;result&quot;: &quot;w-123&quot;
}
```

Where the `result` member is a string which holds an unique - within the scope of the `session` - token which identifies the authorized worker. For every further request issued by the client, and related to a Worker action, the client **MUST** use the token given by the server in response to an `mining.authorize` request. This reduces the number of bytes transferred for solution and /or hashrate submission.

If client is resuming a previous session it **CAN** omit the authorization request for it&apos;s workers and, in this case, **MUST** use the tokens assigned in the originating session. It&apos;s up to the server to keep the correct map between tokens and workers.
The server receiving an authorization request where the credentials match previously authorized ones within the same session **MUST** reply back with the previously generated unique token.

### Prepare for mining

A lot of data is sent over the wire multiple times with useless redundancy. For instance the seed hash is meant to change only every 30000 blocks (roughly 5 days) while fixed-diff pools rarely change the work target. Moreover pools must optimize the search segments among miners trying to assign to every session a different &quot;startNonce&quot; (AKA extraNonce).
For this purpose the `notification` method `mining.set` allows to set (on miner&apos;s side) only those params which change less frequently. The server will keep track of seed, target and extraNonce at session level and will push a notification `mining.set` whenever any (or all) of those values change to the connected miner.

```json
{
  &quot;method&quot;: &quot;mining.set&quot;, 
  &quot;params&quot;: {
      &quot;epoch&quot; : &quot;dc&quot;,
      &quot;target&quot; : &quot;0112e0be826d694b2e62d01511f12a6061fbaec8bc02357593e70e52ba&quot;,
      &quot;algo&quot; : &quot;ethash&quot;,
      &quot;extranonce&quot; : &quot;af4c&quot;
  }
}
```

At the beginning of each `session` the server **MUST** send this notification before any `mining.notify`. All values passed by this notification will be valid for all **NEXT** jobs until a new `mining.set` notification overwrites them. Description of members is as follows:

- optional `epoch` (hex) : unlike all actual Stratum implementations the server should inform the client of the epoch number instead of passing the seed hash. This is enforced by two reasons: the main one is that client has only one way to compute the epoch number and this is by a linear search from epoch 0 iteratively trying increasing epochs till the hash matches the seed hash. Second reason is that epoch number is more concise than seed hash. In the end the seed hash is only transmitted to inform the client about the epoch and is not involved in the mining algorithm.
- optional `target` (hex) : this is the boundary hash already adjusted for pool difficulty. Unlike in EthereumStratum/1.0.0, which provides a `mining.set_difficulty` notification of an _index of difficulty_, the proponent opt to pass directly the boundary hash. If omitted the client **MUST** assume a boundary of `&quot;0x00000000ffff0000000000000000000000000000000000000000000000000000&quot;`
- optional `algo` (string) : the algorithm the miner is expected to mine on. If omitted the client **MUST** assume `&quot;algo&quot;: &quot;ethash&quot;`
- optional `extranonce` (hex) : a starting search segment nonce assigned by server to clients so they possibly do not overlap their search segments. If server wants to &quot;cancel&quot; a previously set extranonce it must pass this member valued as an empty string.

Whenever the server detects that one, or two, or three or four values change within the session, the server will issue a notification with one, or two or three or four members in the `param` object. For this reason on each **new** session the server **MUST** pass all four members. As a consequence the miner is instructed to adapt those values on **next** job which gets notified.
The new `algo` member is defined to be prepared for possible presence of algorithm variants to ethash, namely ethash1a or ProgPow.
Pools providing multicoin switching will take care to send a new `mining.set` to miners before pushing any job after a switch.
The client which can&apos;t support the data provided in the `mining.set` notification **MAY** close connection or stay idle till new values satisfy it&apos;s configuration (see `mining.noop`).
All client&apos;s implementations **MUST** be prepared to accept new extranonces during the session: unlike in EthereumStratum/1.0.0 the optional client advertisement `mining.extranonce.subscribe` is now implicit and mandatory.

The miner receiving the `extranonce` **MUST** initialize the search segment for next job resizing the extranonce to a hex of 16 bytes thus appending as many zeroes as needed.
Extranonce &quot;af4c&quot; means &quot;_search segment of next jobs starts from 0xaf4c000000000000_&quot;
If `extranonce` is valued to an empty string, or it&apos;s never been set within the session scope, the client is free pick any starting point of it&apos;s own search segment on subsequent `mining.notify` jobs.

### A detail of &quot;extranonce&quot;

Miners connected to a pool might likely process the very same nonces thus wasting a lot of duplicate jobs. A `nonce` is any valid number which, applied to algorithm and job specifications, produces a result which is below a certain target. For every job pushed by server to client(s) there are 2^64 possible nonces to test.

To be noted that:

- Any nonce in the 2^64 has the very same possibility to be the right one. 
- A certain hashing job can be solved by more than one nonce

Every &quot;test&quot; over a number is called a hash. Assuming a miner should receive a job for each block and considering the actual average block time of 15 seconds that would mean a miner should try

```
  ( 2^64 / 15 ) / 1T ~ 1,229,782.94 TeraHashes per second
```

This computation capacity is well beyond any miner on the market (including ASICs). For this reason single miners can process only small chunks (segments) of this humongous range. The way miners pick the segments to search on is beyond the scope of this work. Fact is as miners are not coordinated there is no knowledge - for a single miner - of segments picked by other miners.
Extranonce concept is here to mitigate this possibility of duplicate jobs charging the server (the work provider) to give miners, at the maximum possible extent, different segments to search on.

Giving the above assumptions we can depict a nonce as any number in the hex range:

```
  Min 0x0000000000000000
  Max 0xffffffffffffffff
```

_the prefix 0x is voluntarily inserted here only to give a better visual representation_.

The `extranonce` is, at it&apos;s basics, the message of the server saying the client &quot;_I give you the first number to start search from_&quot;. More in detail the `extranonce` is the leftmost part of that number.
Assume a pool notifies the client the usage of extranonce `ab5d` this means the client will see it&apos;s search segment narrowed as
 
```
  Min 0xab5d000000000000
  Max 0xab5dffffffffffff
```

Pushing an extranonce of 4 bytes (like in the example) will give pool the possibility to separate segment 65535 different miners ( or if you prefer 0xffff miners ) while leaving the miner still a segment of 2^48 possible nonces to search on.
Recalculating, as above, the computation capacity needed to search this segment we get

```
  ( 2^48 / 15 ) / 1T ~ 18.76 TeraHashes per second
```

Which is still a wide segment where miners can randomly (or using other ergodic techniques) pick their internal search segments.

Extranonce **MUST** be passed with all relevant bytes (no omission of left zeroes) for a specific reason. Assume an extranonce of &quot;01ac&quot; : it  has the same decimal value of &quot;1ac&quot; but the number of bytes changes thus changing available search segment

```
  When &quot;01ac&quot;               When &quot;1ac&quot;
  Segment is                Segment is
  Min  0x01ac000000000000   Min  0x1ac0000000000000
  Max  0x01acffffffffffff   Max  0x1acfffffffffffff
```

As you can see resulting segments are quite different

This all said pools (server), when making use of extranonce, **MUST** observe a maximum length of 6 bytes (hex).

### Jobs notification

When available server will dispatch jobs to connected miners issuing a `mining.notify` notification.

```json
{
  &quot;method&quot;: &quot;mining.notify&quot;, 
  &quot;params&quot;: [
      &quot;bf0488aa&quot;,
      &quot;6526d5&quot;
      &quot;645cf20198c2f3861e947d4f67e3ab63b7b2e24dcc9095bd9123e7b33371f6cc&quot;,
      &quot;0&quot;
  ]
}
```

`params` member is made of 4 mandatory elements:

- 1st element is jobId as specified by pool. To reduce the amount of data sent over the wire pools **SHOULD** keep their job IDs as concise as possible. Pushing a Job id which is identical to headerhash is a bad practice and is highly discouraged.
- 2nd element is the hex number of the block id
- 3rd element is the headerhash. 
- 4th element is an hex boolean indicating whether or not eventually found shares from previous jobs will be accounted for sure as stale.

### Solution submission

When a miner finds a solution for a job he is mining on it sends a `mining.submit` request to server.

```json
{
  &quot;id&quot;: 31,
  &quot;method&quot;: &quot;mining.submit&quot;, 
  &quot;params&quot;: [
      &quot;bf0488aa&quot;,
      &quot;68765fccd712&quot;,
      &quot;w-123&quot;
  ]
}
```

First element of `params` array is the jobId this solution refers to (as sent in the `mining.notify` message from the server). Second element is the `miner nonce` as hex. Third element is the token given to the worker previous `mining.authorize` request. Any `mining.submit` request bound to a worker which was not successfully authorized - i.e. the token does not exist in the session - **MUST** be rejected.

You&apos;ll notice in the sample above the `miner nonce` is only 12 bytes wide (should be 16). Why?
That&apos;s because in the previous `mining.set` the server has set an `extranonce` of `af4c`. This means the full nonce is `af4c68765fccd712`
In presence of extranonce the miner **MUST** submit only the chars to append to the extranonce to build the final hex value. If no extranonce is set for the session or for the work the miner **MUST** send all 16 bytes.

It&apos;s server duty to keep track of the tuples `job ids &lt;-&gt; extranonces` per session.

When the server receives this request it either responds success using the short form

```json
{&quot;id&quot;: 31}
```

or, in case of any error or condition with a detailed error object

```json
{
  &quot;id&quot;: 31,
  &quot;error&quot;: {
      &quot;code&quot;: 404,
      &quot;message&quot; : &quot;Job not found&quot;
  }
}
```

Client **should** treat errors as &quot;soft&quot; errors (stales) or &quot;hard&quot; (bad nonce computation, job not found etc.). Errors in 5xx range are server errors and suggest the miner to abandon the connection and switch to a failover.

### Hashrate

Most pools offer statistic information, in form of graphs or by API calls, about the calculated hashrate expressed by the miner while miners like to compare this data with the hashrate they read on their devices. Communication about parties of these information have never been coded in Stratum and most pools adopt the method from getWork named `eth_submitHashrate`.
In this document we propose an official implementation of the `mining.hashrate` request.
This method behaves differently when issued from client or from server.

#### Client communicates it&apos;s hashrate to server.

```json
{
  &quot;id&quot; : 16,
  &quot;method&quot;: &quot;mining.hashrate&quot;,
  &quot;params&quot;: [
      &quot;500000&quot;,
      &quot;w-123&quot;
      ]
}
```

where `params` is an array made of two elements: the first is a hexadecimal string representation (32 bytes) of the hashrate the miner reads on it&apos;s devices and the latter is the authorization token issued to worker this hashrate is refers to (see above for `mining.authorization`).
Server **MUST** respond back with either an aknowledgment message

```json
{&quot;id&quot;: 16 }
```

Optionally the server can reply back reporting it&apos;s findings about calculated hashrate **for the same worker**.

```json
{
  &quot;id&quot;: 16,
  &quot;result&quot; : [
      &quot;4f0000&quot;,
      &quot;w-123&quot;
      ]
}
```

In case of errors - for example when the client submits too frequently - with

```json
{
  &quot;id&quot;: 16,
  &quot;error&quot; : {
    &quot;code&quot;: 220,
    &quot;message&quot;: &quot;Enhance your calm. Too many requests&quot;
  }
}
```

#### Server communicates hashrate to client

Optionally the server can **notify** client about it&apos;s overall performance (according to schedule set on server) with a `mining.hashrate` notification composed like this

```json
{
  &quot;method&quot;: &quot;mining.hashrate&quot;,
  &quot;params&quot;: {
      &quot;interval&quot;: 60,
      &quot;hr&quot;: &quot;500000&quot;,
      &quot;accepted&quot;: [3692,20],
      &quot;rejected&quot;: 0,
  }
}
```

Where `params` is an object which holds these members for values of the **whole session**:

- `interval` (number) the width, in minutes, of the observation window. &quot;_in the last x minutes we calculated ..._&quot;
- `hr` (hex) representation of the hashrate the pool has calculated for the miner
- `accepted` is an array of two number elements : the first is the overall count of accepted shares and the second is the number of stale shares. The array must be interpreted as &quot;total accepted of which x are stale&quot;
- `rejected` (number) the overall number of rejected shares

The client will eventually take internal actions to reset/restart it&apos;s workers.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 09 Nov 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1571</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1571</guid>
      </item>
    
      <item>
        <title>contenthash field for ENS</title>
        <category>Standards Track/ERC</category>
        
        <description>## Abstract

This EIP introduces the new `contenthash` field for ENS resolvers, allowing for a better defined system of mapping names to network and content addresses. Additionally the `content` and `multihash` fields are deprecated.

## Motivation

Multiple applications including [Metamask](https://metamask.io/) and mobile clients such as [Status](https://status.im) have begun resolving ENS names to content hosted on distributed systems such as [IPFS](https://ipfs.io/) and [Swarm](https://swarm-guide.readthedocs.io). Due to the various ways content can be stored and addressed, a standard is required so these applications know how to resolve names and that domain owners know how their content will be resolved.

The `contenthash` field allows for easy specification of network and content addresses in ENS.

## Specification

The field `contenthash` is introduced, which permits a wide range of protocols to be supported by ENS names. Resolvers supporting this field MUST return `true` when the `supportsInterface` function is called with argument `0xbc1c58d1`.

The fields `content` and `multihash` are deprecated.

The value returned by `contenthash` MUST be represented as a machine-readable [multicodec](https://github.com/multiformats/multicodec). The format is specified as follows:

```
&lt;protoCode uvarint&gt;&lt;value []byte&gt;
```

protoCodes and their meanings are specified in the [multiformats/multicodec](https://github.com/multiformats/multicodec) repository.

The encoding of the value depends on the content type specified by the protoCode. Values with protocodes of 0xe3 and 0xe4 represent IPFS and Swarm content; these values are encoded as v1 [CIDs](https://github.com/multiformats/cid) without a base prefix, meaning their value is formatted as follows:

```
&lt;protoCode uvarint&gt;&lt;cid-version&gt;&lt;multicodec-content-type&gt;&lt;multihash-content-address&gt;
```

When resolving a `contenthash`, applications MUST use the protocol code to determine what type of address is encoded, and resolve the address appropriately for that protocol, if supported.

### Example

#### IPFS

Input data:

```
storage system: IPFS (0xe3)
CID version: 1 (0x01)
content type: dag-pb (0x70)
hash function: sha2-256 (0x12)
hash length: 32 bytes (0x20)
hash: 29f2d17be6139079dc48696d1f582a8530eb9805b561eda517e22a892c7e3f1f
```

Binary format:

```
0xe3010170122029f2d17be6139079dc48696d1f582a8530eb9805b561eda517e22a892c7e3f1f
```

Text format:

```
ipfs://QmRAQB6YaCyidP37UdDnjFY5vQuiBrcqdyoW1CuDgwxkD4
```

### Swarm

Input data:

```
storage system: Swarm (0xe4)
CID version: 1 (0x01)
content type: swarm-manifest (0xfa)
hash function: keccak256 (0x1b)
hash length: 32 bytes (0x20)
hash: d1de9994b4d039f6548d191eb26786769f580809256b4685ef316805265ea162
```

Binary format:
```
0xe40101fa011b20d1de9994b4d039f6548d191eb26786769f580809256b4685ef316805265ea162
```

Text format:
```
bzz://d1de9994b4d039f6548d191eb26786769f580809256b4685ef316805265ea162
```

Example usage with swarm hash:
```
$ swarm hash ens contenthash d1de9994b4d039f6548d191eb26786769f580809256b4685ef316805265ea162                                 
&gt; e40101fa011b20d1de9994b4d039f6548d191eb26786769f580809256b4685ef316805265ea162
```

### Fallback

In order to support names that have an IPFS or Swarm hash in their `content` field, a grace period MUST be implemented offering those name holders time to update their names. If a resolver does not support the `multihash` interface, it MUST be checked whether they support the `content` interface. If they do, the value of that field SHOULD be treated in a context dependent fashion and resolved. This condition MUST be enforced until at least March 31st, 2019.

### Implementation

To support `contenthash`, a new resolver has been developed and can be found [here](https://github.com/ensdomains/resolvers/blob/master/contracts/PublicResolver.sol), you can also find this smart contract deployed on:

* Mainnet : [0xd3ddccdd3b25a8a7423b5bee360a42146eb4baf3](https://etherscan.io/address/0xd3ddccdd3b25a8a7423b5bee360a42146eb4baf3)
* Ropsten : [0xde469c7106a9fbc3fb98912bb00be983a89bddca](https://ropsten.etherscan.io/address/0xde469c7106a9fbc3fb98912bb00be983a89bddca)

There are also implementations in multiple languages to encode and decode `contenthash`:

* [JavaScript](https://github.com/pldespaigne/content-hash)
* [Python](https://github.com/filips123/ContentHashPy)

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 13 Nov 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1577</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1577</guid>
      </item>
    
      <item>
        <title>Non-wallet usage of keys derived from BIP-32 trees</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/non-wallet-usage-of-keys-derived-from-bip-32-trees/1817</comments>
        
        <description>## Abstract
BIP32 defines a way to generate hierarchical trees of keys which can be derived from a common master key. BIP32 and [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) defines the usage of these keys as wallets. In this EIP we describe the usage of such keys outside the scope of the blockchain defining a logical tree for key usage which can coexist (and thus share the same master) with existing BIP44 compatible wallets.

## Motivation
Applications interacting with the blockchain often make use of additional, non-blockchain technologies to perform the task they are designed for. For privacy and security sensitive mechanisms, sets of keys are needed. Reusing keys used for wallets can prove to be insecure, while keeping completely independent keys make backup and migration of the full set of credentials more complex. Defining a separate (from BIP44 compliant wallets) derivation branch allows combining the security of independent keys with the convenience of having a single piece of information which needs to be backup or migrated.

## Specification

### Path levels
We define the following levels in BIP32 path:

```m / purpose&apos; / coin_type&apos; / subpurpose&apos; / key_type&apos; / key_index```

Apostrophe in the path indicates that BIP32 hardened derivation is used.

This structure follows the [BIP43](https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki) recommendations and its [amendments for non-Bitcoin usage](https://github.com/bitcoin/bips/pull/523/files). Each level has a special meaning, described in the chapters below.

### Purpose/Coin Type/Subpurpose
This part is constant and set to ```m / 43&apos; / 60&apos; / 1581&apos;```, meaning BIP 43 -&gt; Ethereum -&gt; This EIP.

All subtrees under this prefix are the scope of this EIP.

### Key type
Describes the purpose for which the key is being used. Key types should be generic. &quot;Instant messaging&quot; is a good example whereas &quot;Whisper&quot; is not. The reason is that you want to be able to use the same identity across different services. Key types are defined at: TBD

Hardened derivation is used at this level.

### Key index
The key index is a field of variable length identifying a specific key. In its simplest case, it is a number from 0 to 2^31-1. If a larger identifier is desired (for example representing a hash or a GUID), the value must be split
across several BIP32 nesting levels, most significant bit first and left aligned, bit-padded with 0s if needed. All levels, except the last one must used hardened key derivation. The last level must use public derivation. This means that every level can carry 31-bit of the identifier to represent.

As an example, let&apos;s assume we have a key with key type 4&apos; and a key_index representing a 62-bit ID represented as hexadecimal 0x2BCDEFFEDCBAABCD the complete keypath would be  ```m / 43&apos; / 60&apos; / 1581&apos; / 4&apos; / ‭1469833213‬&apos; / ‭1555737549‬ ```. If you are using random identifiers, it might be convenient to generate a conventional GUID, for example 128-bit just fix the value of the most significant bit of each 32-bit word to 1 for all of them, except the last one which will be 0.

## Rationale
The structure proposed above follows the BIP43 generic structure and is similar to the widely adopted BIP44 specification.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 13 Nov 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1581</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1581</guid>
      </item>
    
      <item>
        <title>Hardfork Meta: Ethereum ProgPoW</title>
        <category>Meta/</category>
        
        <description>## Abstract

This meta-EIP specifies the changes included in the alternative Ethereum hardfork named Ethereum ProgPoW.

## Specification

- Codename: Ethereum ProgPoW
- Aliases: N/A
- Activation:
  - `Block &gt;= 7280000` on the Ethereum mainnet
- Included EIPs:
  - [EIP-1057](/EIPs/EIPS/eip-1057): ProgPoW, a Programmatic Proof-of-Work

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 16 Nov 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1588</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1588</guid>
      </item>
    
      <item>
        <title>Address and ERC20-compliant transfer rules</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1597</comments>
        
        <description>## Simple Summary

We propose a standard and an interface to define transfer rules, in the context of ERC20 tokens and possibly beyond.


A rule can act based on sender, destination and amount, and is triggered (and rejects the transfer) according to any required business logic.


To ease rule reusability and composition, we also propose an interface and base implementation for a rule engine.

## Abstract

This standard proposal should answer the following challenges:
- Enable integration of rules with interacting platforms such as exchanges, decentralized wallets and DApps.
- Externale code and storage, improve altogether reusability, gas costs and contracts&apos; memory footprint.
- Highlight contract behavior and its evolution, in order to ease user interaction with such contract. 


If these challenges are answered, this proposal will provide a unified basis for transfer rules and hopefully address the transfer restriction needs of other EIPs as well, e.g. 
[EIP-902](/EIPs/EIPS/eip-902), 
[EIP-1066](/EIPs/EIPS/eip-1066)
and [EIP-1175](/EIPs/EIPS/eip-1175).

This document proposes specifications for a standard of **transfer rules** and interfaces to both the rules and the rule engine, which was made to be inherited by a token, but may have a much broader scope in the authors&apos; opinion.

The last section of this document illustrates the proposal with a rule template and links to rule implementations.

## Motivation

ERC20 was designed as a standard interface allowing any token on Ethereum to be handled by other applications: from wallets to decentralized exchanges. This has been extremely powerful, but future developments in the industry of tokenization are bringing new challenges. For example it is already hard to know exactly why an ERC20 transfer failed, and it will become even harder when many tokens add their own transfer rules to the mix; we propose that it should be trivial to determine before a tx is sent, whether the transfer should turn out valid or invalid, and why (unless conditions change in the meantime obviously). On the other hand, if the rules were changed, it should also be easily detected, so that the interacting party knows it must adjust its expectations or model.

## Specification

We define below an interface for a rule. Rules are meant to be as simple as possible, to limit gas expenditure, since that logic will be executed on every transfer. Another reason for keeping rules simple and short, and strive for atomicity, is to facilitate both composition and interpretation of rejected transfers. By knowing which rule was triggered, we obtain a clear picture of the reason for rejection.

The engine we propose executes all the rules defined by its owner, on every transfer and it is easy to add and remove rules individually, although we have chosen to use quite a raw rule update method, to save on deployment costs, which are often tight when it comes to token smart contracts.

Rules are deployed on the blockchain as individual smart contracts, and called upon by the rule engine they were attached to. But any third party, for example an exchange preparing a cashout for a customer, can very cheaply query the rule engine of the token, or a single rule directly, to verify the validity of a transfer before execution, so as to never get a rejected transaction.

## Rule interface

`IRule` interface should provide a way to validate if an address or a transfer is valid.

If one of these two methods is not applicable, it can simply be made to return true systematically.
If any parameter of `isTransferValid` is not needed, its name should be commented out with `/* */`.

```js
pragma solidity ^0.4.25;

interface IRule {
  function isAddressValid(address _address) external view returns (bool);
  function isTransferValid(address _from, address _to, uint256 _amount)
    external view returns (bool);
}
```

## WithRules interface

`WithRules` interface describes the integration of rules to a rule engine.
Developers may choose to not implement this interface if their code will only deal with one rule, or if it is not desirable to update the rules.

The rules ordering must be thought through carefully.
Rules which are cheaper to validate or have a higher chance to break should be put first to reduce global gas expenditure, then business logic should guide the ordering of rules. That is why rules for a given context should be defined as a whole and not individually.

```js
pragma solidity ^0.4.25;

import &quot;./IRule.sol&quot;;

interface IWithRules {
  function ruleLength() public view returns (uint256);
  function rule(uint256 _ruleId) public view returns (IRule);
  function validateAddress(address _address) public view returns (bool);
  function validateTransfer(address _from, address _to, uint256 _amount)
    public view returns (bool);

  function defineRules(IRule[] _rules) public;

  event RulesDefined(uint256 count);
}
```

## WithRules implementation

We also propose a simple implementation of the rule engine, available [here](https://github.com/MtPelerin/MtPelerin-protocol/blob/master/contracts/rule/WithRules.sol). It has been kept minimal both to save on gas costs on each transfer, and to reduce the deployment cost overhead for the derived smart contract.


On top of implementing the interface above, this engine also defines two modifiers (`whenAddressRulesAreValid`and  `whenTransferRulesAreValid`), which can be used throughout the token contract to restrict `transfer()`, `transferFrom` and any other function that needs to respect either a simple whitelist or complex transfer rules.


## Integration

To use rules within a token is as easy as having the token inherit from WithRules, then writing rules according to the IRule interface and deploying each rule individually. The token owner can then use `defineRules()` to attach all rules in the chosen order, within a single transaction.

Below is a template for a rule.

```solidity
import &quot;../interface/IRule.sol&quot;;

contract TemplateRule is IRule {
  
  // state vars for business logic

  constructor(/* arguments for init */) public {

    // initializations

  }

  function isAddressValid(address _from) public view returns (bool) {
    boolean isValid;

    // business logic 

    return isValid;
  }

  function isTransferValid(
    address _from,
    address _to,
    uint256 _amount)
    public view returns (bool)
  {
    boolean isValid;

    // business logic 

    return isValid;
  }
}
```

*** Notes ***
The MPS (Mt Pelerin&apos;s Share) token is the current live implementation of this standard.
Other implementations may be written with different trade-offs: from gas savings to improved security.

#### Example of rules implementations

- [YesNo rule](https://github.com/MtPelerin/MtPelerin-protocol/tree/master/contracts/rule/YesNoRule.sol): Trivial rule used to demonstrate both a rule and the rule engine.

- [Freeze rule](https://github.com/MtPelerin/MtPelerin-protocol/tree/master/contracts/rule/FreezeRule.sol): This rule allows to prevent any transfer of tokens to or from chosen addresses. A smart blacklist.

- [Lock rule](https://github.com/MtPelerin/MtPelerin-protocol/tree/master/contracts/rule/LockRule.sol): Define a global transfer policy preventing either sending or receiving tokens within a period of time. Exceptions may be granted to some addresses by the token admin. A smart whitelist.

- [User Kyc Rule](https://github.com/MtPelerin/MtPelerin-protocol/tree/master/contracts/rule/UserKycRule.sol): Rule example relying on an existing whitelist to assert transfer and addresses validity. It is a good example of a rule that completely externalizes it&apos;s tasks.

#### Example implementations are available at
- [Mt Pelerin Bridge protocol rules implementation](https://github.com/MtPelerin/MtPelerin-protocol/tree/master/contracts/rule)
- [Mt Pelerin Token with rules](https://github.com/MtPelerin/MtPelerin-protocol/blob/master/contracts/token/component/TokenWithRules.sol)

## History

Historical links related to this standard:

- The first regulated tokenized share issued by Mt Pelerin (MPS token) is using an early version of this proposal: https://www.mtpelerin.com/blog/world-first-tokenized-shares
The rule engine was updated several times, after the token issuance and during the tokensale, to match changing business and legal requirements, showcasing the solidity and flexibility of the rule engine.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
External references outside this repository will have their own specific copyrights.
</description>
        <pubDate>Fri, 09 Nov 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1592</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1592</guid>
      </item>
    
      <item>
        <title>Gas stations network</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/yoav-tabookey/EIPs/issues/1</comments>
        
        <description>## Simple Summary
Make smart contracts (e.g. dapps) accessible to non-ether users by allowing contracts to accept &quot;[collect-calls](https://en.wikipedia.org/wiki/Collect_call)&quot;, paying for incoming calls. 
Let contracts &quot;listen&quot; on publicly accessible channels (e.g. web URL or a whisper address). 
Incentivize nodes to run &quot;gas stations&quot; to facilitate this. 
Require no network changes, and minimal contract changes.

## Abstract
Communicating with dapps currently requires paying ETH for gas, which limits dapp adoption to ether users. 
Therefore, contract owners may wish to pay for the gas to increase user acquisition, or let their users pay for gas with fiat money. 
Alternatively, a 3rd party may wish to subsidize the gas costs of certain contracts. 
Solutions such as described in [EIP-1077](/EIPs/EIPS/eip-1077) could allow transactions from addresses that hold no ETH.

The gas stations network is an [EIP-1077](/EIPs/EIPS/eip-1077) compliant effort to solve the problem by creating an incentive for nodes to run gas stations, where gasless transactions can be &quot;fueled up&quot;. 
It abstracts the implementation details from both the dapp maintainer and the user, making it easy to convert existing dapps to accept &quot;collect-calls&quot;.

The network consists of a single public contract trusted by all participating dapp contracts, and a decentralized network of relay nodes (gas stations) incentivized to listen on non-ether interfaces such as web or whisper, 
pay for transactions and get compensated by that contract. The trusted contract can be verified by anyone, and the system is otherwise trustless. 
Gas stations cannot censor transactions as long as there&apos;s at least one honest gas station. Attempts to undermine the system can be proven on-chain and offenders can be penalized.

## Motivation

* Increase user adoption of smart contracts by:
    * Removing the user hassle of acquiring ETH. Transactions are still paid by ETH but costs can be borne by the dapp or paid by the user through other means.
    * Removing the need to interact directly with the blockchain, while maintaining decentralization and censorship-resistance. 
      Contracts can &quot;listen&quot; on multiple public channels, and users can interact with the contracts through common protocols that are generally permitted even in restrictive environments.
* Ethereum nodes get a revenue source without requiring mining equipment. The entire network benefits from having more nodes.
* No protocol changes required. The gas station network is self-organized via a smart contract, and dapps interact with the network by implementing an interface.

## Specification

The system consists of a `RelayHub` singleton contract, participating contracts inheriting the `RelayRecipient` contract, a decentralized network of `Relay` nodes, a.k.a. Gas Stations, 
and user applications (e.g. mobile or web) interacting with contracts via relays.

Roles of the `RelayHub`:

* Maintain a list of active relays. Senders select a `Relay` from this list for each transaction. The selection process is discussed below.
* Mediate all communication between relays and contracts.
* Provide contracts with trusted versions of the real msg.sender and msg.data.
* Hold ETH stakes placed by relays. A minimum stake size is enforced.  Stake can be withdrawn after a relay unregisters and waits for a cooldown period.
* Hold ETH prepayments made by contracts and use them to compensate relays.
* Penalize provably-offensive relays by giving their stakes to an address providing the proof, thus keeping relays honest.
* Provide a free way for relays to know whether they&apos;ll be compensated for a future transaction.

Roles of a `Relay` node:

* Maintain a hot wallet with a small amount of ETH, to pay for gas.
* Provide a public interface for user apps to send gasless transactions via channels such as https or whisper.
* Publish it&apos;s public interfaces and its price (as a multiplier of the actual transaction gas cost) in `RelayHub`.
* Optionally monitor reverted transactions of other relays through RelayHub, catching offending relays and claiming their stakes. This can be done by anyone, not just a relay.

Implementing a `RelayRecipient` contract:

* Know the address of `RelayHub` and trust it to provide information about the transaction.
* Maintain a small balance of ETH gas prepayment deposit in `RelayHub`. Can be paid directly by the `RelayRecipient` contract, or by the dapp&apos;s owner on behalf of the `RelayRecipient` address. 
  The dapp owner is responsible for ensuring sufficient balance for the next transactions, and can stop depositing if something goes wrong, thus limiting the potential for abuse of system bugs. In DAO usecases it will be up to the DAO logic to maintain a sufficient deposit.
* Use `getSender()` and `getMessageData()` instead of `msg.sender` and `msg.data`, everywhere. `RelayRecipient` provides these functions and gets the information from `RelayHub`.
* Implement a `acceptRelayedCall(address relay, address from, bytes memory encodedFunction, uint gasPrice, uint transactionFee, bytes memory approval)` view function that returns **zero** if and only if it is willing to accept a transaction and pay for it. 
  `acceptRelayedCall` is called by `RelayHub` as a view function when a `Relay` inquires it, and also during the actual transaction. Transactions are reverted if **non-zero**, and `Relay` only gets compensated for transactions (whether successful or reverted) if `acceptRelayedCall` returns **zero**. Some examples of `acceptRelayedCall()` implementations:
    * Whitelist of trusted dapp members.
    * Balance sheet of registered users, maintained by the dapp owner. Users pay the dapp with a credit card or other non-ETH means, and are credited in the `RelayRecipient` balance sheet. 
      Users can never cost the dapp more than they were credited for.
    * A dapp can provide off-chain a signed message called `approval` to a transaction sender and validate it.
    * Whitelist of known transactions used for onboarding new users. This allows certain anonymous calls and is subject to Sybil attacks. 
      Therefore it should be combined with a restricted gasPrice, and a whitelist of trusted relays, to reduce the incentive for relays to create bogus transactions and rob the dapp&apos;s prepaid gas deposit. 
      Dapps allowing anonymous onboarding transactions might benefit from registering their own `Relay` and accepting anonymous transactions only from that `Relay`, whereas other transactions can be accepted from any relay. 
      Alternatively, dapps may use the balance sheet method for onboarding as well, by applying the methods suggested in the attacks/mitigations section below.   
* Implement `preRelayedCall(address relay, address from, bytes memory encodedFunction, uint transactionFee) returns (bytes32)`. This method is called before a transaction is relayed. By default, it does nothing.
  
* Implement `postRelayedCall(ddress relay, address from, bytes memory encodedFunction, bool success, uint usedGas, uint transactionFee, bytes32 preRetVal)`. This method is called after a transaction is relayed. By default, it does nothing.
  
  These two methods can be used to charge the user in dapp-specific manner. 

Glossary of terms used in the processes below:

* `RelayHub` - the RelayHub singleton contract, used by everyone.
* `Recipient` - a contract implementing `RelayRecipient`, accepting relayed transactions from the RelayHub contract and paying for the incoming transactions.
* `Sender` - an external address with a valid key pair but no ETH to pay for gas.
* `Relay` - a node holding ETH in an external address, listed in RelayHub and relaying transactions from Senders to RelayHub for a fee.

![Sequence Diagram](/EIPs/assets/eip-1613/sequence.png)

The process of registering/refreshing a `Relay`:

* Relay starts listening as a web app (or on some other communication channel).
* If starting for the first time (no key yet), generate a key pair for Relay&apos;s address.
* If Relay&apos;s address doesn&apos;t hold sufficient funds for gas (e.g. because it was just generated), Relay stays inactive until its owner funds it.
* Relay&apos;s owner funds it.
* Relay&apos;s owner sends the required stake to `RelayHub` by calling `RelayHub.stake(address relay, uint unstakeDelay)`.
* `RelayHub` puts the `owner` and `unstake delay` in the relays map, indexed by `relay` address.
* Relay calls `RelayHub.registerRelay(uint transactionFee, string memory url)` with the relay&apos;s `transaction fee` (as a multiplier on transaction gas cost), and a URL for incoming transactions. 
* `RelayHub` ensures that Relay has a sufficient stake.
* `RelayHub` puts the `transaction fee` in the relays map.
* `RelayHub` emits an event, `RelayAdded(Relay, owner, transactionFee, relayStake, unstakeDelay, url)`.
* Relay starts a timer to perform a `keepalive` transaction every 6000 blocks.
* `Relay` goes to sleep and waits for signing requests.

The process of sending a relayed transaction:

* `Sender` selects a live `Relay` from RelayHub&apos;s list by looking at `RelayAdded` events from `RelayHub`, and sorting based on its own criteria. Selection may be based on a mix of:
    * Relay published transaction fees.
    * Relay stake size and lock-up time.
    * Recent relay transactions (visible through `TransactionRelayed` events from `RelayHub`).
    * Optionally, reputation/blacklist/whitelist held by the sender app itself, or its backend, on per-app basis (not part of the gas stations network).
* Sender prepares the transaction with Sender&apos;s address, the recipient address, the actual transaction data, Relay&apos;s transaction fee, gas price, gas limit, its current nonce from `RelayHub.nonces`, RelayHub&apos;s address, and Relay&apos;s address, and then signs it.
* Sender verifies that `RelayHub.balances[recipient]` holds enough ETH to pay Relay&apos;s fee.
* Sender verifies that `Relay.balance` has enough eth to send the transaction
* Sender reads the Relay&apos;s current `nonce` value and decides on the `max_nonce` parameter.
* Sender sends the signed transaction amd metadata to Relay&apos;s web interface.
* `Relay` wraps the transaction with a transaction to `RelayHub`, with zero ETH value.
* `Relay` signs the wrapper transaction with its key in order to pay for gas.
* `Relay` verifies that:
    * The transaction&apos;s recipient contract will accept this transaction when submitted, by calling `RelayHub.canRelay()`, a view function, 
      which checks the recipient&apos;s `acceptRelayedCall`, also a view function, stating whether it&apos;s willing to accept the charges).
    * The transaction nonce matches `RelayHub.nonces[sender]`.
    * The relay address in the transaction matches Relay&apos;s address.
    * The transaction&apos;s recipient has enough ETH deposited in `RelayHub` to pay the transaction fee.
    * Relay has enough ETH to pay for the gas required by the transaction.
    * Value of `max_nonce` is higher than current Relay&apos;s `nonce`
* If any of Relay&apos;s checks fail, it returns an error to sender, and doesn&apos;t proceed.
* Relay submits the signed wrapped transaction to the blockchain.
* Relay immediately returns the signed wrapped transaction to the sender.  This step is discussed below, in attacks/mitigations.
* `Sender` receives the wrapped transaction and verifies that:
    * It&apos;s a valid relay call to `RelayHub`. from Relay&apos;s address.
    * The transaction&apos;s ethereum nonce matches Relay&apos;s current nonce.
    * The transaction&apos;s ethereum nonce is lower than or equal to `max_nonce`.
    * `Relay` is sufficiently funded to pay for it.
    * The wrapped transaction is valid and signed by `sender`.
    * Recipient contract has sufficient funds in `RelayHub.balances` to pay for Relay&apos;s fee as stated in the transaction.
* If any of sender&apos;s checks fails, it goes back to selecting a new Relay. Sender may also file a report on the unresponsive relay to its backend or save it locally, to down-sort this relay in future transactions.
* `Sender` may also submit the raw wrapped transaction to the blockchain without paying for gas, through any Ethereum node. 
  This submission is likely ignored because an identical transaction is already in the network&apos;s pending transactions, but no harm in putting it twice, to ensure that it happens. 
  This step is not strictly necessary, for reasons discussed below in attacks/mitigations, but may speed things up.
* `Sender` monitors the blockchain, waiting for the transaction to be mined. 
  The transaction was verified, with Relay&apos;s current nonce, so mining must be successful unless Relay submitted another (different) transaction with the same nonce. 
  If mining fails due to such attack, sender may call `RelayHub.penalizeRepeatedNonce` through another relay, to collect his reward and burn the remainder of the offending relay&apos;s stake, and then go back to selecting a new Relay for the transaction. 
  See discussion in the attacks/mitigations section below.
* `RelayHub` receives the transaction:
    * Records `gasleft()` as `initialGas` for later payment.
    * Verifies the transaction is sent from a registered relay.
    * Verifies that the signature of the internal transaction matches its stated origin (sender&apos;s key).
    * Verifies that the relay address written in the transaction matches msg.sender.
    * Verifies that the transaction&apos;s `nonce` matches the stated origin&apos;s nonce in `RelayHub.nonces`.
    * Calls recipient&apos;s `acceptRelayedCall` function, asking whether it&apos;s going to accept the transaction. If not, the `TransactionRelayed` will be emitted with status `CanRelayFailed`, and `chargeOrCanRelayStatus` will contain the return value of `acceptRelayedCall`. In this case, Relay doesn&apos;t get paid, as it was its responsibility to check `RelayHub.canRelay` before releasing the transaction.
    * Calls recipient&apos;s `preRelayedCall` function. If this call reverts the `TransactionRelayed` will be emitted with status `PreRelayedFailed`.
    * Sends the transaction to the recipient.  If this call reverts the `TransactionRelayed` will be emitted with status `RelayedCallFailed`.
      When passing gas to `call()`, enough gas is preserved by `RelayHub`, for post-call handling. Recipient may run out of gas, but `RelayHub` never does. 
      `RelayHub` also sends sender&apos;s address at the end of `msg.data`, so `RelayRecipient.getSender()` will be able to extract the real sender, and trust it because the transaction came from the known `RelayHub` address.
* Recipient contract handles the transaction.
* `RelayHub` calls recipient&apos;s `postRelayedCall`.
* `RelayHub` checks call&apos;s return value of call, and emits `TransactionRelayed(address relay, address from, address to, bytes4 selector, uint256 status, uint256 chargeOrCanRelayStatus)`.
* `RelayHub` increases `RelayHub.nonces[sender]`.
* `RelayHub` transfers ETH balance from recipient to `Relay.owner`, to pay the transaction fee, based on the measured transaction cost. 
  Note on relay payment: The relay gets paid for actual gas used, regardless of whether the recipient reverted. 
  The only case where the relay sustains a loss, is if `canRelay` returns non-zero, since the relay was responsible to verify this view function prior to submitting. 
  Any other revert is caught and paid for. See attacks/mitigations below.
* `Relay` keeps track of transactions it sent, and waits for `TransactionRelayed` events to see the charge. 
  If a transaction reverts and goes unpaid, which means the recipient&apos;s `acceptRelayedCall()` function was inconsistent, `Relay` refuses service to that recipient for a while (or blacklists it indefinitely, if it happens often). 
  See attacks/mitigations below.

The process of winding a `Relay` down:

* Relay&apos;s owner (the address that initially funded it) calls `RelayHub.removeRelayByOwner(Relay)`.
* `RelayHub` ensures that the sender is indeed Relay&apos;s owner, then removes `Relay`, and emits `RelayRemoved(Relay)`.
* `RelayHub` starts the countdown towards releasing the owner&apos;s stake.
* `Relay` receives its `RelayRemoved` event.
* `Relay` sends all its remaining ETH to its owner.
* `Relay` shuts down.
* Once the owner&apos;s unstake delay is over, owner calls `RelayHub.unstake()`, and withdraws the stake.

## Rationale
The rationale for the gas stations network design is a combination of two sets of requirements: Easy adoption, and robustness.

For easy adoption, the design goals are:

* No network changes.
* Minimal changes to contracts, apps and frameworks.

The robustness requirement translates to decentralization and attack resistance. The gas stations network is decentralized, and we have to assume that any entity may attack other entities in the system.

Specifically we&apos;ve considered the following types of attacks:

* Denial-of-service attacks against individual senders, i.e. transactions censorship.
* Denial-of-service and financial attacks against individual relays.
* Denial-of-service and financial attacks against individual contracts.
* Denial-of-service attacks against the entire network, either by attacking existing entities, or by introducing any number of malicious entities.

#### Attacks and mitigations

##### Attack: Relay attempts to censor a transaction by not signing it, or otherwise ignoring a user request.
Relay is expected to return the signed transaction to the sender, immediately. 
Sender doesn&apos;t need to wait for the transaction to be mined, and knows immediately whether it&apos;s request has been served. 
If a relay doesn&apos;t return a signed transaction within a couple of seconds, sender cancels the operation, drops the connection, and switches to another relay. 
It also marks Relay as unresponsive in its private storage to avoid using it in the near future.

Therefore, the maximal damage a relay can cause with such attack, is a one-time delay of a couple of seconds. After a while, senders will avoid it altogether.

##### Attack: Relay attempts to censor a transaction by signing it, returning it to the sender, but never putting it on the blockchain.
This attack will backfire and not censor the transaction. 
The sender can submit the transaction signed by Relay to the blockchain as a raw transaction through any node, so the transaction does happen, 
but Relay may be unaware and therefore be stuck with a bad nonce which will break its next transaction.

##### Attack: Relay attempts to censor a transaction by signing it, but publishing a different transaction with the same nonce.
Reusing the nonce is the only DoS performed by a Relay, that cannot be detected within a couple of seconds during the http request. 
It will only be detected when the malicious transaction with the same nonce gets mined and triggers the `RelayHub.TransactionRelayed` event. 
However, the attack will backfire and cost Relay its entire stake.

Sender has a signed transaction from Relay with nonce N, and also gets a mined transaction from the blockchain with nonce N, also signed by Relay. 
This proves that Relay performed a DoS attack against the sender. 
The sender calls `RelayHub.penalizeRepeatedNonce(bytes transaction1, bytes transaction2)`, which verifies the attack, confiscates Relay&apos;s stake, 
and sends half of it to the sender who delivered the `penalizeRepeatedNonce` call. The other half of the stake is burned by sending it to `address(0)`. Burning is done to prevent cheating relays from effectively penalizing themselves and getting away without any loss.
The sender then proceeds to select a new relay and send the original transaction.

The result of such attack is a delay of a few blocks in sending the transaction (until the attack is detected) but the relay gets removed and loses its entire stake. 
Scaling such attack would be prohibitively expensive, and actually quite profitable for senders and honest relays.

##### Attack: Relay attempts to censor a transaction by signing it, but using a nonce higher than it&apos;s current nonce.
In this attack, the Relay did create and return a perfectly valid transaction, but it will not be mined until this Relay fills the gap in the nonce with &apos;missing&apos; transactions.
This may delay the relaying of some transactions indefinitely. In order to mitigate that, the sender includes a `max_nonce` parameter with it&apos;s signing request.
It is suggested to be higher by 2-3 from current nonce, to allow the relay process several transactions.

When the sender receives a transaction signed by a Relay he validates that the nonce used is valid, and if it is not, the client will ignore the given relay and use other relays to relay given transaction. Therefore, there will be no actual delay introduced by such attack.

##### Attack: Dapp attempts to burn relays funds by implementing an inconsistent acceptRelayedCall() and using multiple sender addresses to generate expensive transactions, thus performing a DoS attack on relays and reducing their profitability.
In this attack, a contract sets an inconsistent acceptRelayedCall (e.g. return zero for even blocks, nonzero for odd blocks), and uses it to exhaust relay resources through unpaid transactions. 
Relays can easily detect it after the fact. 
If a transaction goes unpaid, the relay knows that the recipient contract&apos;s acceptRelayedCall has acted inconsistently, because the relay has verified its view function before sending the transaction. 
It might be the result of a rare race condition where the contract&apos;s state has changed between the view call and the transaction, but if it happens too frequently, relays will blacklist this contract and refuse to serve transactions to it. 
Each offending contract can only cause a small damage (e.g. the cost of 2-3 transactions) to a relay, before getting blacklisted.

Relays may also look at recipients&apos; history on the blockchain, looking for past unpaid transactions (reverted by RelayHub without pay), and denying service to contracts with a high failure rate. 
If a contract caused this minor loss to a few relays, all relays will stop serving it, so it can&apos;t cause further damage.

This attack doesn&apos;t scale because the cost of creating a malicious contract is in the same order of magnitude as the damage it can cause to the network. 
Causing enough damage to exhaust the resources of all relays, would be prohibitively expensive.

The attack can be made even more impractical by setting RelayHub to require a stake from dapps before they can be served, and enforcing an unstaking delay, 
so that attackers will have to raise a vast amount of ETH in order to simultaneously create enough malicious contracts and attack relays. 
This protection is probably an overkill, since the attack doesn&apos;t scale regardless.

##### Attack: User attempts to rob dapps by registering its own relay and sending expensive transactions to dapps.
If a malicious sender repeatedly abuses a recipient by sending meaningless/reverted transactions and causing the recipient to pay a relay for nothing, 
it is the recipient&apos;s responsibility to blacklist that sender and have its acceptRelayedCall function return nonzero for that sender. 
Collect calls are generally not meant for anonymous senders unknown to the recipient. 
Dapps that utilize the gas station networks should have a way to blacklist malicious users in their system and prevent Sybil attacks.

A simple method that mitigates such Sybil attack, is that the dapp lets users buy credit with a credit card, and credit their account in the dapp contract, 
so acceptRelayedCall() only returns zero for users that have enough credit, and deduct the amount paid to the relay from the user&apos;s balance, whenever a transaction is relayed for the user. 
With this method, the attacker can only burn its own resources, not the dapp&apos;s.

A variation of this method, for free dapps (that don&apos;t charge the user, and prefer to pay for their users transactions) is to require a captcha during user creation in their web interface, 
or to login with a Google/Facebook account, which limits the rate of the attack to the attacker&apos;s ability to open many Google/Facebook accounts. 
Only a user that passed that process is given credit in RelayRecipient. The rate of such Sybil attack would be too low to cause any real damage.

##### Attack: Attacker attempts to reduce network availability by registering many unreliable relays.
Registering a relay requires placing a stake in RelayHub, and the stake can only be withdrawn after the relay is unregistered and a long cooldown period has passed, e.g. a month.

Each unreliable relay can only cause a couple of seconds delay to senders, once, and then it gets blacklisted by them, as described in the first attack above. 
After it caused this minor delay and got blacklisted, the attacker must wait a month before reusing the funds to launch another unreliable relay. 
Simultaneously bringing up a number of unreliable relays, large enough to cause a noticeable network delay, would be prohibitively expensive due to the required stake, 
and even then, all those relays will get blacklisted within a short time.

##### Attack: Attacker attempts to replay a relayed transaction.
Transactions include a nonce. RelayHub maintains a nonce (counter) for each sender. Transactions with bad nonces get reverted by RelayHub. Each transaction can only be relayed once.

##### Attack: User does not execute the raw transaction received from the Relayer, therefore blocking the execution of all further transactions signed by this relayer
The user doesn&apos;t really have to execute the raw transaction. It&apos;s enough that the user can. The relationship between relay and sender is mutual distrust. The process described above incentivizes the relay to execute the transaction, so the user doesn&apos;t need to wait for actual mining to know that the transaction has been executed.

Once relay returns the signed transaction, which should happen immediately, the relay is incentivized to also execute it on chain, so that it can advance its nonce and serve the next transaction. The user can (but doesn&apos;t have to) also execute the transaction. To understand why the attack isn&apos;t viable, consider the four possible scenarios after the signed transaction was returned to the sender:

1. Relay executes the transaction, and the user doesn&apos;t. In this scenario the transaction is executed, so no problem. This is the case described in this attack.
2. Relay doesn&apos;t execute the transaction, but the user does. Similarly to 1, the transaction is executed, so no problem.
3. Both of them execute the transaction. The transactions are identical in the pending transactions pool, so the transaction gets executed once. No problem.
4. None of them execute the transaction. In this case the transaction doesn&apos;t get executed, but the relay is stuck. It can&apos;t serve the next transaction with the next nonce, because its nonce hasn&apos;t been advanced on-chain. It also can&apos;t serve the next transaction with the current nonce, as this can be proven by the user, having two different transactions signed by the same relay, with the same nonce. The user could use this to take the relay&apos;s nonce. So the relay is stuck unless it executes the transaction.

As this matrix shows, the relay is __always__ incentivized to execute the transaction, once it returned it to the user, in order to end up in #1 or #3, and avoid the risk of #4. It&apos;s just a way to commit the relay to do its work, without requiring the user to wait for on-chain confirmation.

## Backwards Compatibility

The gas stations network is implemented as smart contracts and external entities, and does not require any network changes.

Dapps adding gas station network support remain backwards compatible with their existing apps/users. The added methods apply on top of the existing ones, so no changes are required for existing apps.

## Implementation

A working implementation of the [**gas stations network**](https://github.com/tabookey-dev/tabookey-gasless) is being developed by **TabooKey**. It consists of `RelayHub`, `RelayRecipient`, `web3 hooks`, an implementation of a gas station inside `geth`, and sample dapps using the gas stations network.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 18 Nov 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1613</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1613</guid>
      </item>
    
      <item>
        <title>Attribute Registry Standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1616</comments>
        
        <description>## Simple Summary
EIP-1616 provides a basic interface for querying a registry for attribute metadata assigned to Ethereum accounts.

## Abstract
This EIP contains the following core ideas:
1. Instead of relying directly on the reputation of a claims issuer to assess the veracity of a given claim, trust can be brought up to the level of a registry curator. This registry which we call an &quot;**Attribute Registry**&quot; allows for reduced complexity in implementation since a party needing to verify an attribute can now work with a trusted claims aggregator instead of relying on individual claim providers.
2. Claims are abstracted as standard &quot;attributes&quot; which represent metadata assigned to an account, with claims decoupled from the issuing party. Attributes are registered as a flat `uint256 -&gt; uint256` key-value pair on each account, with the important property that **each attribute type has one canonical value per address**. This property allows for composability of attribute registries and advanced attribute formation.
3. There is a generic method for determining the set of attribute keys or IDs made available by the registry. The standard does not specify requirements or recommendations for how attributes and their values are managed, or what additional metadata may be associated with attributes. It is likely that a standard set of attribute names and metadata schema could be proposed in a separate EIP.

Potential advanced uses of attribute registries include:
* Encoding complex boolean expressions which combine multiple attributes into a single uint256 key, which is then parsed and evaluated by the registry logic.
* Using values associated with an attribute to query additional on-chain or off-chain metadata.
* Resolving attribute values by calling into separate attribute registries or other contracts, delegating authority without changing the interface of the registry.

## Motivation
This EIP is motivated by the need for contracts and external accounts to be able to verify information about a given address from a single trusted source **without concerning themselves with the particular details of how the information was obtained**, and to do so in as simple a manner as possible. It is also motivated by the desire to promote broad **cross-compatibility and composability** between attribute registries, a property which is amplified by both the simplicity of the interface as well as by the guarantees on uniqueness provided by the proposed standard.

Existing EIPs for assigning metadata to an account include EIP-735 and EIP-780, which both allow for multiple claims to be issued on the same address for any given claim topic. This forces verifiers of said metadata to assess the veracity of each claim, taking into account the relative reputation of each claim issuer. It also prescribes a methodology for adding and removing claims, which may not be appropriate for all use cases.

This EIP proposes a light-weight abstraction layer for a standard account metadata registry interface. This abstraction layer can sit on top of claims registries like EIP-735 and EIP-780 or others as the attribute registry curator selects trusted data sources.

## Specification
The Attribute Registry interface contains four functions, outlined as follows:
```solidity
/**
 * @title EIP-1616 Attribute Registry Standard interface. EIP-165 ID: 0x5f46473f
 */
interface AttributeRegistryInterface {
  function hasAttribute(address account, uint256 attributeTypeID) external view returns (bool);
  function getAttributeValue(address account, uint256 attributeTypeID) external view returns (uint256);
  function countAttributeTypes() external view returns (uint256);
  function getAttributeTypeID(uint256 index) external view returns (uint256);
}
```

Contracts that comply with the Attribute Registry EIP MUST implement the above interface.

As an additional requirement, the ERC-165 interface MUST be included:
```solidity
/**
 * @title EIP-165 interface. EIP-165 ID: 0x01ffc9a7
 */
interface EIP-165 {
  /**
   * @notice EIP-165 support. Attribute Registry interface ID is 0x5f46473f.
   * @param _interfaceID The interface identifier, as specified in EIP-165
   * @return True for 0x01ffc9a7 &amp; 0x5f46473f, false for unsupported interfaces.
   */
  function supportsInterface(bytes4 _interfaceID) external view returns (bool);
}
```

The implementation MUST follow the specifications described below.

### View Functions
The view functions detailed below MUST be implemented.

#### `hasAttribute` function
```solidity
function hasAttribute(address account, uint256 attributeTypeID) external view returns (bool)
```

Check if an attribute has been assigned to a given account on the registry and is currently valid.

_**NOTE**_: This function MUST return either true or false - i.e. calling this function MUST NOT cause the caller to revert. Implementations that wish to call into another contract during execution of this function MUST catch any `revert` and instead return `false`.

_**NOTE**_: This function MUST return two equal values when performing two directly consecutive function calls with identical `account` and `attributeTypeID` parameters, regardless of differences in the caller&apos;s address, the transaction origin, or other out-of-band information.



#### `getAttributeValue` function
```solidity
function getAttributeValue(address account, uint256 attributeTypeID) external view returns (uint256)
```

Retrieve the `uint256` value of an attribute on a given account on the registry, assuming the attribute is currently valid.

_**NOTE**_: This function MUST revert if a directly preceding or subsequent function call to `hasAttribute` with identical `account` and `attributeTypeID` parameters would return false.

_**NOTE**_: This function MUST return two equal values when performing two directly consecutive function calls with identical `account` and `attributeTypeID` parameters, regardless of differences in the caller&apos;s address, the transaction origin, or other out-of-band information.

#### `countAttributeTypes` function
```solidity
function countAttributeTypes() external view returns (uint256)
```

Retrieve the total number of valid attribute types defined on the registry. Used alongside `getAttributeTypeID` to determine all of the attribute types that are available on the registry.

_**NOTE**_: This function MUST return a positive integer value  - i.e. calling this function MUST NOT cause the caller to revert.

_**NOTE**_: This function MUST return a value that encompasses all indexes of attribute type IDs whereby a call to `hasAttribute` on some address with an attribute type ID at the given index would return `true`.

#### `getAttributeTypeID` function
```solidity
function getAttributeTypeID(uint256 index) external view returns (uint256)
```

Retrieve an ID of an attribute type defined on the registry by index. Used alongside `countAttributeTypes` to determine all of the attribute types that are available on the registry.

_**NOTE**_: This function MUST revert if the provided `index` value falls outside of the range of the value returned from a directly preceding or subsequent function call to `countAttributeTypes`. It MUST NOT revert if the provided `index` value falls inside said range.

_**NOTE**_: This function MUST return an `attributeTypeID` value on *some* index if the same `attributeTypeID` value would cause a given call to `hasAttribute` to return `true` when passed as a parameter.

## Rationale
This standard extends the applicability of metadata assignment to those use cases that are not adequately represented by EIP-735, EIP-780, or similar proposals. Namely, it enforces the constraint of one attribute value per attribute ID per address, as opposed to one value per ID per address *per issuer*.

Aside from the prescribed attribute value, attribute properties are deliberately omitted from the standard. While many attribute registries will require additional metadata on attributes at both the instance and the class level, reliable and flexible interoperability between highly variable registry extensions is facilitated more effectively by enforcing a widely-applicable base layer for attributes.

## Backwards Compatibility
There are no backwards compatibility concerns.

## Test Cases
Targeted test cases with 100% code coverage can be found at [this repository](https://github.com/0age/AttributeRegistry). See [here](https://github.com/TPL-protocol/tpl-contracts) for tests on a more complex contract that implements the application registry interface.

## Implementation
The basic implementation that follows can be found at [this repository](https://github.com/0age/AttributeRegistry) (see [here](https://github.com/TPL-protocol/tpl-contracts/blob/master/contracts/BasicJurisdiction.sol#L399) for an example of a more complex implementing contract):

```solidity
pragma solidity ^0.4.25;

/**
 * @title Attribute Registry interface. EIP-165 ID: 0x5f46473f
 */
interface AttributeRegistryInterface {
  /**
   * @notice Check if an attribute of the type with ID `attributeTypeID` has
   * been assigned to the account at `account` and is currently valid.
   * @param account address The account to check for a valid attribute.
   * @param attributeTypeID uint256 The ID of the attribute type to check for.
   * @return True if the attribute is assigned and valid, false otherwise.
   * @dev This function MUST return either true or false - i.e. calling this
   * function MUST NOT cause the caller to revert.
   */
  function hasAttribute(
    address account,
    uint256 attributeTypeID
  ) external view returns (bool);

  /**
   * @notice Retrieve the value of the attribute of the type with ID
   * `attributeTypeID` on the account at `account`, assuming it is valid.
   * @param account address The account to check for the given attribute value.
   * @param attributeTypeID uint256 The ID of the attribute type to check for.
   * @return The attribute value if the attribute is valid, reverts otherwise.
   * @dev This function MUST revert if a directly preceding or subsequent
   * function call to `hasAttribute` with identical `account` and
   * `attributeTypeID` parameters would return false.
   */
  function getAttributeValue(
    address account,
    uint256 attributeTypeID
  ) external view returns (uint256);

  /**
   * @notice Count the number of attribute types defined by the registry.
   * @return The number of available attribute types.
   * @dev This function MUST return a positive integer value  - i.e. calling
   * this function MUST NOT cause the caller to revert.
   */
  function countAttributeTypes() external view returns (uint256);

  /**
   * @notice Get the ID of the attribute type at index `index`.
   * @param index uint256 The index of the attribute type in question.
   * @return The ID of the attribute type.
   * @dev This function MUST revert if the provided `index` value falls outside
   * of the range of the value returned from a directly preceding or subsequent
   * function call to `countAttributeTypes`. It MUST NOT revert if the provided
   * `index` value falls inside said range.
   */
  function getAttributeTypeID(uint256 index) external view returns (uint256);
}


/**
 * @title A simple example of an Attribute Registry implementation.
 */
contract AttributeRegistry is AttributeRegistryInterface {
  // This particular implementation just defines two attribute types.
  enum Affiliation { Whitehat, Blackhat }

  // Top-level information about attribute types held in a static array.
  uint256[2] private _attributeTypeIDs;

  // The number of attributes currently issued tracked in a static array.
  uint256[2] private _issuedAttributeCounters;

  // Issued attributes held in a nested mapping by account &amp; attribute type.
  mapping(address =&gt; mapping(uint256 =&gt; bool)) private _issuedAttributes;

  // Issued attribute values held in a nested mapping by account &amp; type.
  mapping(address =&gt; mapping(uint256 =&gt; uint256)) private _issuedAttributeValues;

  /**
  * @notice The constructor function, defines the two attribute types available
  * on this particular registry.
  */
  constructor() public {
    // Set the attribute type IDs for whitehats (8008) and blackhats (1337).
    _attributeTypeIDs = [8008, 1337];
  }

  /**
   * @notice Assign a &quot;whitehat&quot; attribute type to `msg.sender`.
   * @dev The function may not be called by accounts with a &quot;blackhat&quot; attribute
   * type already assigned. This function is arbitrary and not part of the
   * Attribute Registry specification.
   */
  function joinWhitehats() external {
    // Get the index of the blackhat attribute type on the attribute registry.
    uint256 blackhatIndex = uint256(Affiliation.Blackhat);

    // Get the attribute type ID of the blackhat attribute type.
    uint256 blackhatAttributeTypeID = _attributeTypeIDs[blackhatIndex];

    // Do not allow the whitehat attribute to be set if blackhat is already set.
    require(
      !_issuedAttributes[msg.sender][blackhatAttributeTypeID],
      &quot;no blackhats allowed!&quot;
    );

    // Get the index of the whitehat attribute type on the attribute registry.
    uint256 whitehatIndex = uint256(Affiliation.Whitehat);

    // Get the attribute type ID of the whitehat attribute type.
    uint256 whitehatAttributeTypeID = _attributeTypeIDs[whitehatIndex];

    // Mark the attribute as issued on the given address.
    _issuedAttributes[msg.sender][whitehatAttributeTypeID] = true;

    // Calculate the new number of total whitehat attributes.
    uint256 incrementCounter = _issuedAttributeCounters[whitehatIndex] + 1;

    // Set the attribute value to the new total assigned whitehat attributes.
    _issuedAttributeValues[msg.sender][whitehatAttributeTypeID] = incrementCounter;

    // Update the value of the counter for total whitehat attributes.
    _issuedAttributeCounters[whitehatIndex] = incrementCounter;
  }

  /**
   * @notice Assign a &quot;blackhat&quot; attribute type to `msg.sender`.
   * @dev The function may be called by any account, but assigned &quot;whitehat&quot;
   * attributes will be removed. This function is arbitrary and not part of the
   * Attribute Registry specification.
   */
  function joinBlackhats() external {
    // Get the index of the blackhat attribute type on the attribute registry.
    uint256 blackhatIndex = uint256(Affiliation.Blackhat);

    // Get the attribute type ID of the blackhat attribute type.
    uint256 blackhatAttributeTypeID = _attributeTypeIDs[blackhatIndex];

    // Mark the attribute as issued on the given address.    
    _issuedAttributes[msg.sender][blackhatAttributeTypeID] = true;

    // Calculate the new number of total blackhat attributes.    
    uint256 incrementCounter = _issuedAttributeCounters[blackhatIndex] + 1;

    // Set the attribute value to the new total assigned blackhat attributes.    
    _issuedAttributeValues[msg.sender][blackhatAttributeTypeID] = incrementCounter;

    // Update the value of the counter for total blackhat attributes.    
    _issuedAttributeCounters[blackhatIndex] = incrementCounter;

    // Get the index of the whitehat attribute type on the attribute registry.
    uint256 whitehatIndex = uint256(Affiliation.Whitehat);

    // Get the attribute type ID of the whitehat attribute type.
    uint256 whitehatAttributeTypeID = _attributeTypeIDs[whitehatIndex];

    // Determine if a whitehat attribute type has been assigned.
    if (_issuedAttributes[msg.sender][whitehatAttributeTypeID]) {
      // If so, delete the attribute.
      delete _issuedAttributes[msg.sender][whitehatAttributeTypeID];

      // Delete the attribute value as well.
      delete _issuedAttributeValues[msg.sender][whitehatAttributeTypeID];

      // Set the attribute value to the new total assigned whitehat attributes.      
      uint256 decrementCounter = _issuedAttributeCounters[whitehatIndex] - 1;

      // Update the value of the counter for total whitehat attributes.
      _issuedAttributeCounters[whitehatIndex] = decrementCounter;
    }
  }

  /**
   * @notice Get the total number of assigned whitehat and blackhat attributes.
   * @return Array with counts of assigned whitehat and blackhat attributes.
   * @dev This function is arbitrary and not part of the Attribute Registry
   * specification.
   */
  function totalHats() external view returns (uint256[2]) {
    // Return the array containing counter values.
    return _issuedAttributeCounters;
  }

  /**
   * @notice Check if an attribute of the type with ID `attributeTypeID` has
   * been assigned to the account at `account` and is currently valid.
   * @param account address The account to check for a valid attribute.
   * @param attributeTypeID uint256 The ID of the attribute type to check for.
   * @return True if the attribute is assigned and valid, false otherwise.
   * @dev This function MUST return either true or false - i.e. calling this
   * function MUST NOT cause the caller to revert.
   */
  function hasAttribute(
    address account,
    uint256 attributeTypeID
  ) external view returns (bool) {
    // Return assignment status of attribute by account and attribute type ID
    return _issuedAttributes[account][attributeTypeID];
  }

  /**
   * @notice Retrieve the value of the attribute of the type with ID
   * `attributeTypeID` on the account at `account`, assuming it is valid.
   * @param account address The account to check for the given attribute value.
   * @param attributeTypeID uint256 The ID of the attribute type to check for.
   * @return The attribute value if the attribute is valid, reverts otherwise.
   * @dev This function MUST revert if a directly preceding or subsequent
   * function call to `hasAttribute` with identical `account` and
   * `attributeTypeID` parameters would return false.
   */
  function getAttributeValue(
    address account,
    uint256 attributeTypeID
  ) external view returns (uint256 value) {
    // Revert if attribute with given account &amp; attribute type ID is unassigned
    require(
      _issuedAttributes[account][attributeTypeID],
      &quot;could not find a value with the provided account and attribute type ID&quot;
    );

    // Return the attribute value.
    return _issuedAttributeValues[account][attributeTypeID];
  }

  /**
   * @notice Count the number of attribute types defined by the registry.
   * @return The number of available attribute types.
   * @dev This function MUST return a positive integer value  - i.e. calling
   * this function MUST NOT cause the caller to revert.
   */
  function countAttributeTypes() external view returns (uint256) {
    // Return the length of the attribute type IDs array.
    return _attributeTypeIDs.length;
  }

  /**
   * @notice Get the ID of the attribute type at index `index`.
   * @param index uint256 The index of the attribute type in question.
   * @return The ID of the attribute type.
   * @dev This function MUST revert if the provided `index` value falls outside
   * of the range of the value returned from a directly preceding or subsequent
   * function call to `countAttributeTypes`. It MUST NOT revert if the provided
   * `index` value falls inside said range.
   */
  function getAttributeTypeID(uint256 index) external view returns (uint256) {
    // Revert if the provided index is out of range.
    require(
      index &lt; _attributeTypeIDs.length,
      &quot;provided index is outside of the range of defined attribute type IDs&quot;
    );

    // Return the attribute type ID at the given index in the array.
    return _attributeTypeIDs[index];
  }
}
```

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 23 Nov 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1616</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1616</guid>
      </item>
    
      <item>
        <title>Money Streaming</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1620</comments>
        
        <description>## Simple Summary
Money streaming represents the idea of continuous payments over a finite period of time. Block numbers are used as a proxy of time to continuously update balances.

## Abstract
The following describes a standard whereby time is measured using block numbers and streams are mappings in a master contract.

1. A provider sets up a money streaming contract.
2. A prospective payer can interact with the contract and start the stream right away by depositing the funds required for the chosen period.
3. The payee is able to withdraw money from the contract based on its ongoing solvency. That is: `payment rate * (current block height - starting block height)`
4. The stream terms (payment rate, length, metadata) can be updated at any time if both parties pledge their signatures.
5. The stream can be stopped at any point in time by any party without on-chain consensus.
6. If the stream period ended and it was not previously stopped by any party, the payee is entitled to withdraw all the deposited funds.

## Motivation
This standardised interface aims to change the way we think about long-term financial commitments. Thanks to blockchains, payments need not be sent in chunks (e.g. monthly salaries), as there is much less overhead in paying-as-you-go. Money as a function of time would better align incentives in a host of scenarios.

### Use Cases

This is just a preliminary list of use cases. There are other spooky ideas interesting to explore, such as time-dependent disincetivisation, but, for brevity, we have not included them here.

- Salaries
- Subscriptions
- Consultancies
- CDPs
- Rent
- Parking

### Crowdsales
[RICOs](https://github.com/lukso-network/rico), or Reversible ICOs, were introduced at Devcon4 by @frozeman. The idea is to endow investors with more power and safety guarantees by allowing them to &quot;reverse&quot; the investment based on the evolution of the project. We previously discussed a similar concept called SICOs, or Streamable ICOs, in this research [thread](https://ethresear.ch/t/chronos-a-quirky-application-proposal-for-plasma/2928/14?u=paulrberg).

Instead of investing a lump sum and giving the money away to the project developers, funds are held in a smart contract which allocates money based on the passage of time. Project developers can withdraw funds as the stream stays active, while investors have the power to get back a significant percentage of their initial commitment if the project halts.

## Specification

### Structs

The structure of a `stream` should be as follows:

- `stream`
    - `sender`: the `address` of the entity funding the stream
    - `recipient`: the `address` where the money is being delivered to
    - `tokenAddress`: the `address` of the ERC20 token used as payment asset
    - `balance`: the total funds left in the stream
    - `timeframe`: as defined below
    - `rate`: as defined below

```solidity
  struct Stream {
    address sender;
    address recipient;
    address tokenAddress;
    uint256 balance;
    Timeframe timeframe;
    Rate rate;
  }
```

- `timeframe`
    - `start`: the starting block number of the stream
    - `stop`: the stopping block number of the stream

```solidity
struct Timeframe {
    uint256 start;
    uint256 stop;
}
```

- `rate`
    - `payment`: how much money moves from `sender` to `recipient`
    - `interval`: how often `payment` moves from `sender` to `recipient`

```solidity
struct Rate {
  uint256 payment;
  uint256 interval;
}
```

---

### Methods

#### balanceOf

Returns available funds for the given stream id and address.

```solidity
function balanceOf(uint256 _streamId, address _addr)
```

#### getStream

Returns the full stream data, if the id points to a valid stream.

```solidity
function getStream(uint256 _streamId) returns (address sender, address recipient, address tokenAddress, uint256 balance, uint256 startBlock, uint256 stopBlock, uint256 payment, uint256 interval)
```

#### create

Creates a new stream between `msg.sender` and `_recipient`.

MUST allow senders to create multiple streams in parallel. SHOULD not accept Ether and only use ERC20-compatible tokens.

**Triggers Event**: [LogCreate](#logcreate)

```solidity
function create(address _recipient, address _tokenAddress, uint256 _startBlock, uint256 _stopBlock, uint256 _payment, uint256 _interval)
```

#### withdraw

Withdraws all or a fraction of the available funds.

MUST allow only the recipient to perform this action.

**Triggers Event**: [LogWithdraw](#logwithdraw)

```solidity
function withdraw(uint256 _streamId, uint256 _funds)
```

#### redeem

Redeems the stream by distributing the funds to the sender and the recipient.

SHOULD allow any party to redeem the stream.

**Triggers Event**: [LogRedeem](#logredeem)

```solidity
function redeem(uint256 _streamId)
```

#### confirmUpdate

Signals one party&apos;s willingness to update the stream

SHOULD allow any party to do this but MUST NOT be executed without consent from all involved parties.

**Triggers Event**: [LogConfirmUpdate](#logconfirmupdate)

**Triggers Event**: [LogExecuteUpdate](#logexecuteupdate) when the last involved party calls this function

```solidity
function update(uint256 _streamId, address _tokenAddress, uint256 _stopBlock, uint256 _payment, uint256 _interval)
```

#### revokeUpdate

Revokes an update proposed by one of the involved parties. 

MUST allow any party to do this.

**Triggers Event**: [LogRevokeUpdate](#logrevokeupdate)

```solidity
function confirmUpdate(uint256 _streamId, address _tokenAddress, uint256 _stopBlock, uint256 _payment, uint256 _interval)
```

---

### Events

#### LogCreate

MUST be triggered when `create` is successfully called.

```solidity
event LogCreate(uint256 indexed _streamId, address indexed _sender, address indexed _recipient, address _tokenAddress, uint256 _startBlock, uint256 _stopBlock, uint256 _payment, uint256 _interval)
```

#### LogWithdraw

MUST be triggered when `withdraw` is successfully called.

```solidity
event LogWithdraw(uint256 indexed _streamId, address indexed _recipient, uint256 _funds)
```

#### LogRedeem

MUST be triggered when `redeem` is successfully called.

```solidity
event LogRedeem(uint256 indexed _streamId, address indexed _sender, address indexed _recipient, uint256 _senderBalance, uint256 _recipientBalance)
```

#### LogConfirmUpdate

MUST be triggered when `confirmUpdate` is successfully called.

```solidity
event LogConfirmUpdate(uint256 indexed _streamId, address indexed _confirmer, address _newTokenAddress, uint256 _newStopBlock, uint256 _newPayment, uint256 _newInterval);
```

#### LogRevokeUpdate

MUST be triggered when `revokeUpdate` is successfully called.

```solidity
event LogRevokeUpdate(uint256 indexed _streamId, address indexed revoker, address _newTokenAddress, uint256 _newStopBlock, uint256 _newPayment, uint256 _newInterval)
```

#### LogExecuteUpdate

MUST be triggered when an update is approved by all involved parties.

```solidity
event LogExecuteUpdate(uint256 indexed _newStreamId, address indexed _sender, address indexed _recipient, address _newTokenAddress, uint256 _newStopBlock, uint256 _newPayment, uint256 _newInterval)
```

## Rationale

This specification was designed to serve as an entry point to the quirky concept of money as a function of time and it is definitely not set in stone. Several other designs, including payment channels and Plasma chains were also considered, but they were eventually deemed dense in assumptions unnecessary for an initial version.

&lt;!--
- Block times and oracles for time calculation
    - GCD
    - Miners
- Sidechain-compatible (and preferable)
- The `update` function
- Multi-hop streams
--&gt;

Block times are a reasonable, trustless proxy for time on the blockchain. Between 2016 and 2018, the Ethereum block time average value [hovered](https://etherscan.io/chart/blocktime) around 14 seconds, excluding the last two quarters of 2017. Mathematically speaking, it would be ideal to have a standard deviation as close to 0 as possible, but that is not how things work in the real world. This has huge implications on the feasibility of this ERC which we shall investigate below.

### GCD
When setting up a stream, a payer and a payee may want to make the total streaming duration a multiple of the &quot;greatest common denominator&quot; (GCD) of the chain they operate on; that is, the average block time. This is not imperative in the smart contracts per se, but there needs to be an off-chain process to map streams to real world time units in order to create a sound and fair payment mechanism.

### Block Times
Because there is uncertainty regarding block times, streams may not be settled on the blockchain as initially planned. Let `$d` be the total streaming duration measured in seconds, `$t` the average block time before the stream started and `$t&apos;` the actual average block time over `$d` after the stream started. We distinguish two undesirable scenarios:

1. `$t` &lt; `$t&apos;`: the payee will get their funds *later* than expected

2. `$t` &gt; `$t&apos;`: the payee will get their funds *sooner* than expected

If the combined error delta is smaller than the payment rate (fifth parameter of the `create` method, measured in wei), there is no problem at all. Conversely, we stumble upon trust issues because real-world time frames do not correspond to the stream terms. For instance, if an employee is normally entitled to withdraw all the funds from the stream at the end of the month, but block times cause case 1 from above to occur, the employee is in a financial disadvantage because their continuous effort is not compensated as promised.

Limiting the problem scope only to Ethereum, we propose two remedies:

1. Consensus on calling the `update` function to correct the stream terms. This might sound preposterous, but in most cases the stakes are low and stream participants are involved in long-term financial commitments. There is a high disincentive to refuse to cooperate.

2. Autonomously fix significant error deltas. In theory, we could achieve this using previous blocks&apos; timestamps, &quot;checkpointing&quot; the stream once in a predefined number of blocks. This is still an area of active research because of potentially high overheads in gas costs.

Nonetheless, it is important to note that this is still a major improvement on the traditional model where absolute trust is required.

### Sidechains

It could be more efficient to implement this standard on independent sidechains like [POA Network](https://poa.network) or [xDai](https://medium.com/poa-network/poa-network-partners-with-makerdao-on-xdai-chain-the-first-ever-usd-stable-blockchain-65a078c41e6a) - thanks to their rather predictable nature. Admittedly, security is traded for scalability, but proper cryptoeconomic stakes could alleviate potential problems.

Furthermore, it is intriguing to explore the prospect of stream-specific sidechains.

### Oracles

The proposed specification uses block numbers to proxy time, but this need not be the only method. Albeit it would imply different trust assumptions, oracles could be used to provide a feed of timestamps. Coupled with the aforementioned idea of stream-specific sidechains, oracles could efficiently solve the problems outlined in [Block Times](#block-times).

### Multi-Hop Streams

Future or upgraded versions of this standard may describe &quot;multi-hop&quot; streams. If:

1. There is a stream between A and B
2. There is another stream between B and C

There could be a way to avoid running two different streams in parallel. That is, a fraction or all of the funds being streamed from A to B could be automatically wired to C. An interesting use case for this is taxes. Instead of manually moving money around, proactively calculating how much you owe and then transfer it, a stream could atomically perform those operations for you.

## Implementation

- [ChronosProtocol WIP implementation](https://github.com/ChronosProtocol/monorepo)

## Additional References
- [Chronos Protocol Ethresear.ch Plasma Proposal](https://ethresear.ch/t/chronos-a-quirky-application-proposal-for-plasma/2928?u=paulrberg)
- [Chronos Protocol White Paper](http://chronosprotocol.org/chronos-white-paper.pdf)
- [Flipper: Streaming Salaries @ CryptoLife Hackathon](https://devpost.com/software/flipper-3gvl4b)
- [SICOs or Streamed ICOs](https://ethresear.ch/t/chronos-a-quirky-application-proposal-for-plasma/2928/14?u=paulrberg)
- [RICOs or Reversible ICOs](https://twitter.com/feindura/status/1058057076306518017)
- [Andreas Antonopoulos&apos; Keynote on Bitcoin, Lightning and Money Streaming](https://www.youtube.com/watch?v=gF_ZQ_eijPs)

## Final Notes

Many thanks to @mmilton41 for countless brainstorming sessions. We have been doing research on the topic of money streaming for quite a while within the context of @ChronosProtocol. In August this year, we published the first version of our white paper describing a Plasma approach. However, in the meantime, we realised that it would be much more [fun](https://twitter.com/PaulRBerg/status/1056595919116910592) and easier to start small on Ethereum itself and sidechains like [xDai](https://blockscout.com/poa/dai).

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 24 Nov 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1620</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1620</guid>
      </item>
    
      <item>
        <title>Re-Fungible Token Standard (RFT)</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1634</comments>
        
        <description>## Simple Summary
[ERC-20](/EIPs/EIPS/eip-20) extension for proportional ownership of an [ERC-721](/EIPs/EIPS/eip-721) token.

## Abstract
The intention of this proposal, the Re-Fungible Token Standard, is to extend the ERC-20 Token Standard and utilize ERC-165 Standard Interface Detection in order to represent the shared ownership of an ERC-721 Non-Fungible Token. The ERC-20 Token Standard was modified as little as possible in order to allow this new class of token to operate in all of the ways and locations which are familiar to assets that follow the original ERC-20 specification. While there are many possible variations of this specification that would enable many different capabilities and scenarios for shared ownership, this proposal is focused on the minimal commonalities to enable as much flexibility as possible for various further extensions. This proposal makes it possible to verify, from the contract level or from an external query, whether a fungible token represents a form of shared ownership of a non-fungible token. The inclusion of ERC-165 makes it possible to verify, from the contract level or from an external query, whether a non-fungible token is owned by ERC-20 token representing shared ownership.

## Motivation
Shared ownership occurs across many industries and for many reasons. As more assets are registered, regulated and/or represented by the ERC-721 Non-Fungible Token Standard there will be more instances where the need for shared ownership of these assets will arise. For example, ARTBLX Inc. is working towards facilitating a protocol for collective ownership of physical, digital and conceptual artworks. The fungible tokens created from this process will have a value attached to the non-fungible tokens which they represent. This will be useful for price discovery of the underlying asset, liquidity for shared owners and as a new class of asset which can be used as collateral for loans or other financial instruments like stable coins. Providing an interface to this special class of fungible tokens is necessary to allow third parties to recognize them as a special class of fungible token and to recognize when a non-fungible token is collectively owned. This might be useful in the case of a wallet who would want to utilize the metadata of the underlying NFT to show additional info next to an RFT, or on an exchange who might want to make that sort of info similarly available, or an NFT marketplace who may want to direct customers to a relevant exchange who wish to purchase shares in a NFT which is owned by an RFT. Anywhere an ERC-20 is applicable it would be useful for a user to know whether that token represents a shared NFT, and what attributes that NFT may have.

## Specification
At a minimum, third parties need two things: 1) to be able to distinguish re-fungible tokens from other token standards and 2) to determine when a non-fungible token is collectively owned. These two scenarios can be encountered from the perspective of initial contact with the non-fungible token or from the perspective of initial contact with the re-fungible token.

#### Initial Contact with the Re-Fungible Token

In order for a third party to confirm which non-fungible token is owned by the re-fungible token there needs to be a pointer from the RFT contract to the NFT contract and the relevant token id. This is possible with two public getters named `parentToken()` and `parentTokenId()`. The first getter returns a variable of type `address` and designates the contract address of the Non-Fungible Token contract. The second getter returns a variable of type `uint256` and designates the token ID of the Non-Fungible Token. With these getters, the identity of the Non-Fungible Token can be determined. Below is an example of the Re-Fungible Token Standard interface that includes these getter functions:

```solidity
pragma solidity ^0.4.20;

/// @dev Note: the ERC-165 identifier for this interface is 0x5755c3f2.
interface RFT /* is ERC20, ERC165 */ {

  function parentToken() external view returns(address _parentToken);
  function parentTokenId() external view returns(uint256 _parentTokenId);

}
```

The validity of this claim can be confirmed from another contract (on-chain) or from interacting with an RPC endpoint (off-chain). Below is an example of the on-chain scenario:

```solidity
pragma solidity ^0.4.20;

import &apos;./RFT.sol&apos;;
import &apos;./ERC721.sol&apos;;

contract ConfirmRFT {

  function confirmRFT(address _RFT) external view returns(bool) {
    address _NFT = RFT(_RFT).parentToken(); // returns address of NFT contract
    uint256 _tokenId = RFT(_RFT).parentTokenId(); // returns id of ID of NFT

    return
      NFT(_NFT).supportsInterface(0x80ac58cd) &amp;&amp; // confirm it is ERC-721
      NFT(_NFT).ownerOf(_tokenId) == _RFT; // confirm the owner of the NFT is the RFT contract address
  }

}
```

Below is an off-chain example using an instance of web3.js in javascript:
```javascript
async function confirmRFT(web3) {

  const ERC721ABI = [...] // abi for ERC721
  const RFTABI = [...] // abi for RFT
  const RFTAddress = &apos;0x0123456789abcdef0123456789abcdef&apos; // address for the deployed RFT

  const RFTContract = new web3.eth.Contract(RFTABI, RFTAddress) // deployed RFT contract instance
  const ERC721Address = await RFTcontract.methods.parentToken().call() // returns address of NFT contract
  const ERC721TokenId = await RFTcontract.methods.parentTokenId().call() // returns id of ID of NFT

  const ERC721Contract = new web3.eth.Contract(ERC721ABI, ERC721Address) // deployed ERC721 (as reported by RFT)
  const isERC721 = await ERC721Contract.methods.supportsInterface(&apos;0x80ac58cd&apos;).call() // confirm it is ERC-721
  const ownerOfAddress = await ERC721Contract.methods.ownerOf(ERC721TokenId).call() // get the owner of the NFT

  return ERC721Response.toLowerCase() === RFTAddress.toLowerCase() // confirm the owner of the NFT is the RFT contract
}
```

#### Initial Contact with the Non-Fungible Token

When checking the owner of a specific non-fungible token it&apos;s important to be able to determine whether owner is in fact a re-fungible token contract. This is possible by utilizing ERC-165 Standard Interface Detection. In order to comply with that standard a contract must include the following getter function which returns `true` when passed the `bytes4` parameter `0x01ffc9a7`:
```
function supportsInterface(bytes4 interfaceID) external view returns (bool);
```
After establishing support for this interface it becomes useful in determining whether the contract adheres to the Re-Fungible Token Standard. To do so the `supportsInterface(bytes4 interfaceID)` getter function must return `true` when passed the `bytes4` parameter `0x5755c3f2` which is the result of `bytes4(keccak256(&apos;parentToken()&apos;)) ^ bytes4(keccak256(&apos;parentTokenId()&apos;))` or `parentToken.selector ^ parentTokenId.selector`. This could be achieved with the following code:
```solidity
pragma solidity ^0.4.20;

import &quot;./ERC20.sol&quot;;

/// @dev Note: the ERC-165 identifier for this interface is 0x5755c3f2.
interface RFT is ERC20 /*, ERC165 */ {

  function supportsInterface(bytes4 interfaceID) external view returns(bool) {
    return
      interfaceID == this.supportsInterface.selector || // ERC165
      interfaceID == this.parentToken.selector || // parentToken()
      interfaceID == this.parentTokenId.selector || // parentTokenId()
      interfaceID == this.parentToken.selector ^ this.parentTokenId.selector; // RFT
  }

  function parentToken() external view returns(address _parentToken);
  function parentTokenId() external view returns(uint256 _parentTokenId);

}
```
The flow of actually checking the status of a non-fungible token owner as a re-fungible token contract can be done from another contract (on-chain) as well as with an RPC endpoint (off-chain). Below is an example of the on-chain scenario:
```solidity
pragma solidity ^0.4.20;

import &apos;./RFT.sol&apos;;
import &apos;./ERC721.sol&apos;;

contract ConfirmRFT {

  function confirmRFT(address _NFT, uint256 _tokenId) external view returns(bool) {
    address _RFT = ERC721(_NFT).ownerOf(_tokenId); // get the owner of the NFT

    return
      RFT(_RFT).supportsInterface(0x01ffc9a7) &amp;&amp; // confirm it supports ERC-165
      RFT(_RFT).supportsInterface(0x5755c3f2) // confirm it is RFT
  }

}
```
Below is an off-chain example using web3.js in javascript:
```javascript
async function confirmRFT(web3) {

  const ERC721ABI = [...] // abi for ERC721
  const RFTABI = [...] // abi for RFT
  const ERC721Address = &apos;0x0123456789abcdef0123456789abcdef&apos; // address for the deployed NFT
  const ERC721TokenId = &apos;7&apos; // token Id of the NFT

  const ERC721Contract = new web3.eth.Contract(ERC721ABI, ERC721Address) // deployed ERC721
  const RFTAddress = await ERC721Contract.methods.ownerOf(ERC721TokenId).call() // owner address of the NFT


  const RFTContract = new web3.eth.Contract(RFTABI, RFTAddress) // deployed RFT contract instance
  const isERC165 = await RFTContract.methods.supportsInterface(&apos;0x01ffc9a7&apos;).call() // confirm it is ERC-165
  return isERC165 &amp;&amp; await RFTContract.methods.supportsInterface(&apos;0x5755c3f2&apos;).call() // confirm it is RFT

}
```
## Rationale
Most of the decisions made around the design of this standard were done in the hopes of keeping it as flexible as possible for as many use cases as possible. This includes making the standard 100% backwards compatible with ERC-20 Token Standard and able to interact with any previously deployed or future ERC-721 non-fungible token. This allows for each project to determine their own system for minting, burning and governing their re-fungible tokens depending on their specific use case.

## Backwards Compatibility
The Re-Fungible Token Standard is 100% backwards compatible with ERC-20 Token Standard. It is a small extension to the original specification and meant to be further extended for more specific use cases. Keeping the standard compatible with ERC-20 is important to allow for this token to benefit from the ecosystem that has grown around supporting the ubiquitous ERC-20 Token Standard.

The Re-Fungible Token Standard is intended to interact with the ERC-721 Non-Fungible Token Standard. It is kept purposefully agnostic to extensions beyond the standard in order to allow specific projects to design their own token relationships such as governance over, rights to or permissions on each non-fungible token relative to the respective re-fungible token owners.

## Implementation
```solidity
pragma solidity ^0.4.20;

/// @dev Note: the ERC-165 identifier for this interface is 0x5755c3f2.
interface RFT /* is ERC20, ERC165 */ {

  function parentToken() external view returns(address _parentToken);
  function parentTokenId() external view returns(uint256 _parentTokenId);

}
```

## Security Considerations
TBD

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 18 Nov 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1633</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1633</guid>
      </item>
    
      <item>
        <title>Hardfork Meta: Istanbul</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/hardfork-meta-istanbul-discussion/3207</comments>
        
        <description>## Abstract

This meta-EIP specifies the changes included in the Ethereum hardfork named Istanbul.

## Specification

- Codename: Istanbul

### Activation
  - `Block &gt;= 9,069,000` on the Ethereum Mainnet
  - `Block &gt;= 6,485,846` on the Ropsten testnet
  - `Block &gt;= 14,111,141` on the Kovan testnet
  - `Block &gt;= 5,435,345` on the Rinkeby testnet
  - `Block &gt;= 1,561,651` on the Görli testnet

### Included EIPs
  - [EIP-152](/EIPs/EIPS/eip-152): Add Blake2 compression function `F` precompile
  - [EIP-1108](/EIPs/EIPS/eip-1108): Reduce alt_bn128 precompile gas costs
  - [EIP-1344](/EIPs/EIPS/eip-1344): Add ChainID opcode
  - [EIP-1884](/EIPs/EIPS/eip-1884): Repricing for trie-size-dependent opcodes
  - [EIP-2028](/EIPs/EIPS/eip-2028): Calldata gas cost reduction
  - [EIP-2200](/EIPs/EIPS/eip-2200): Rebalance net-metered SSTORE gas cost with consideration of SLOAD gas cost change

## References

1. Included EIPs were finalized in [All Core Devs Call #68](https://github.com/ethereum/pm/blob/master/AllCoreDevs-EL-Meetings/Meeting%2068.md)
2. https://medium.com/ethereum-cat-herders/istanbul-testnets-are-coming-53973bcea7df

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 04 Jan 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1679</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1679</guid>
      </item>
    
      <item>
        <title>Temporal Replay Protection</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/temporal-replay-protection/2355</comments>
        
        <description>## Simple Summary

This EIP proposes adding a &apos;temporal&apos; replay protection to transactions, in the form of a `valid-until` timestamp. 
This EIP is very similar to https://github.com/ethereum/EIPs/pull/599 by Nick Johnson and Konrad Feldmeier, the main difference
being that this EIP is based on clock-time / walltime instead of block numbers. 


## Motivation

There are a couple of different motivators for introducing a timebased transaction validity. 

- If any form of dust-account clearing is introduced, e.g. (https://github.com/ethereum/EIPs/issues/168), it will be necessary
to introduce a replay protection, such as https://github.com/ethereum/EIPs/issues/169 . Having temporal replay protection removes the need
to change nonce-behaviour in the state, since transactions would not be replayable at a later date than explicitly set by the user. 
- In many cases, such as during ICOs, a lot of people want their transactions to either become included soon (within a couple of hours) or not at all. Currently, 
transactions are queued and may not execute for several days, at a cost for both the user (who ends up paying gas for a failing purchase) and the network, dealing with the large transaction queues.  
- Node implementations have no commonly agreed metric for which transactions to keep, discard or propagate. Having a TTL on transactions would make it easier to remove stale transactions from the system. 

## Specification

The roll-out would be performed in two phases, `X` (hardfork), and `Y` (softfork).

At block `X`, 

- Add an optional field `valid-until` to the RLP-encoded transaction, defined as a `uint64` (same as `nonce`). 
- If the field is present in transaction `t`, then
  - `t` is only eligible for inclusion in a block if `block.timestamp` &lt; `t.valid-until`. 

At block `Y`, 
- Make `valid-until` mandatory, and consider any transaction without `valid-until` to be invalid. 

## Rationale

### Rationale for this EIP

For the dust-account clearing usecase, 
- This change is much less invasive in the consensus engine. 
  - No need to maintain a consensus-field of &apos;highest-known-nonce&apos; or cap the number of transactions from a sender in a block. 
  - Only touches the transaction validation part of the consensus engine
  - Other schemas which uses the `nonce` can have unintended side-effects, 
    - such as inability to create contracts at certain addresses.
    - more difficult to integrate with offline signers, since more elaborate nonce-schemes requires state access to determine. 
    - More intricate schemes like `highest-nonce` are a lot more difficult, since highest-known-nonce will be a consensus-struct that is incremented and possibly reverted during transaction execution, requiring one more journalled field.  


### Rationale for walltime
 
Why use walltime instead of block numbers, as proposed in https://github.com/ethereum/EIPs/pull/599 ? 

- The UTC time is generally available in most settings, even on a computer which is offline. This means that even a setup where blockchain information is unavailable, the party signing a transaction can generate a transaction with the desired properties. 
- The correlation between time and block number is not fixed; even though a 14s blocktime is &apos;desired&apos;, this varies due to both network hashrate and difficulty bomb progression. 
- The block number is even more unreliable as a timestamp for testnets and private networks.
- UTC time is more user-friendly, a user can more easily decide on reasonable end-date for a transaction, rather than a suitalbe number of valid blocks.


## Backwards Compatibility

This EIP means that all software/hardware that creates transactions need to add timestamps to the transactions, or will otherwise be incapable of signing transactions after block `Y`. Note: this EIP does not introduce any maximum `valid-until` date, so it would still be possible to create
transactions with near infinite validity. 

## Test Cases

todo

## Implementation

None yet

## Security considerations

The most notable security impact is that pre-signed transactions stored on paper backups, will become invalid as of block `Y`. There are a couple of cases where this might be used
   - Pregenerated onetime &apos;bootstrap&apos; transactions, e.g. to onboard a user into Ethereum. Instead of giving a user a giftcard with actual ether on it, someone may instead give the person a one-time pregenerated transaction that will only send those ether to the card once the 
user actively wants to start using it.
   - If a user has an offline paper-wallet, he may have pregenerated transactions to send value to e.g. an exchange. This is sometimes done to be able to send ether to an exchange without having to go through all the hoops of bringing the paper wallet back to &apos;life&apos;. 

Secondary security impacts are that the addition of a timestamp would make the transactions a little bit larger. 

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Tue, 08 Jan 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1681</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1681</guid>
      </item>
    
      <item>
        <title>Storage Rent</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/storage-rent-eip/2357</comments>
        
        <description>## Abstract

This EIP describes a scheme to charge for data in state, and &apos;archive&apos; data which is no longer being paid for. It also describes how resurrection of &apos;archived&apos; data happens.

## Motivation

The Ethereum blockchain in its current form is not sustainable because it grows
indefinitely. This is true of any blockchain, but Ethereum grows faster than most chains.
Many implementation strategies to slow down growth exist. A common strategy is &apos;state
pruning&apos; which discards historical state, keeping only the active copy of contract data
and a few recent versions to deal with short-range chain reorganizations. Several
implementations also employ compression techniques to keep the active copy of the state as
small as possible.

A full node participating in consensus today requires storing large amounts of data even
with advanced storage optimizations applied. Future storage requirements are unbounded
because any data stored in a contract must be retained forever as dictated by the
protocol. This EIP attempts to correct this by adding new consensus rules that put an
upper bound on the size of the Ethereum state.

Adding these new rules changes fundamental guarantees of the system and requires a hard
fork. Users of Ethereum already pay for the creation and modification of accounts and
their storage entries. Under the rules introduced in this EIP, users must also pay to keep
accounts accessible. A similar rent scheme was proposed in [EIP-103] but rejected
even back then because the proposal would&apos;ve upset peoples expectations. As implementers
of Ethereum, we still feel that state rent is the right path to long-term sustainability
of the Ethereum blockchain and that its undesirable implications can be overcome with
off-protocol tooling and careful design.

[EIP-103]: https://github.com/ethereum/EIPs/issues/35

## Specification

The cost of storing an account over time is called `rent`. The amount of `rent` due depends
on the size of the account. The `ether` that is paid for `rent` is destroyed. The `rent` is deducted whenever an account is touched.

`rent` can be paid from the account&apos;s regular `balance` or from its &apos;rent balance&apos;. Accounts
can be endowed with `rent balance` through a new EVM opcode. When `rent` is charged, it is
first taken from the `rent balance`. When `rent balance` is zero, it is instead charged from the account&apos;s regular `balance` instead.

The reason to separate `balance` and `rent balance` is that certain contracts do not accept `ether` sends, or always send the entire balance off to some other destination. For these cases, a separate`rent balance` is required. 

When an account&apos;s `balance` is insufficient to pay rent, the account becomes `inactive`. Its
storage and contract code are removed. Inactive accounts cannot be interacted with, i.e.
it behaves as if it has no contract code.

Inactive accounts can be restored by re-uploading their storage. To restore an inactive
account `A`, a new account `B` is created with arbitrary code and its storage modified
with `SSTORE` operations until it matches the storage root of `A`. Account `B` can restore
`A` through the `RESTORETO` opcode. This means the cost of restoring an account is
equivalent to recreating it via successive `SSTORE` operations.

### Changes To State

At the top level, a new key `size` is added to the accounts trie. This key tracks the
total number of trie nodes across all accounts, including storage trie nodes. To track
rent, the structure of account entries is changed as well.

Before processing the block in which this EIP becomes active, clients iterate the whole
state once to count the number of trie nodes and to change the representation of all
accounts to the new format.

#### Account Representation

```text
account = [nonce, balance, storageroot, codehash, rentbalance, rentblock, storagesize]
```

Each account gets three additional properties: `rentbalance`, `rentblock` and
`storagesize`.

The `rentbalace` field tracks the amount of `rent balance` available to the account. Upon
self-destruction any remaining `rent balance` is transferred to the beneficiary. Any
modification of the account recomputes its current `rent balance`.

The `rentblock` field tracks the block number in which the `rent balance` was last
recomputed. Upon creation, this field is initialized with the current block number.
`rentblock` is also updated with the current block number whenever the account is
modified.

The `storagesize` field tracks the amount of storage related to the account. It is a
number containing the number of storage slots currently set. The `storagesize` of an
inactive account is zero.

### Charging Rent

There is a new protocol constant `MAX_STORAGE_SIZE` that specifies the upper bound on the
number of state tree nodes:

```python
MAX_STORAGE_SIZE = 2**32 # ~160GB of state
```

A &apos;storage fee factor&apos; for each block is derived from this constant such that fees
increase as the limit is approached.

```python
def storagefee_factor(block):
    ramp = MAX_STORAGE_SIZE / (MAX_STORAGE_SIZE - total_storage_size(block))
    return 2**22 * ramp
```

When a block is processed, `rent` is deducted from all accounts modified by transactions in
the block after the transactions have been processed. The amount due for each account is
based on the account&apos;s storage size.

```python
def rent(prestate, poststate, addr, currentblock):
    fee = 0
    for b in range(prestate[addr].rentblock+1, currentblock-1):
        fee += storagefee_factor(b) * prestate[addr].storagesize
    return fee + storagefee_factor(currentblock) * poststate[addr].storagesize

def charge_rent(prestate, poststate, addr, currentblock):
    fee = rent(prestate, poststate, addr, currentblock)
    if fee &lt;= poststate[addr].rentbalance:
        poststate[addr].rentbalance -= fee
    else:
        fee -= poststate[addr].rentbalance
        poststate[addr].rentbalance = 0
        poststate[addr].balance -= min(poststate[addr].balance, fee)
    poststate[addr].rentblock = currentblock
```

### New EVM Opcodes

#### `PAYRENT &lt;amount&gt; &lt;addr&gt;`

At any time, the `rent balance` of an account may be topped up by the `PAYRENT` opcode.
`PAYRENT` deducts the given amount of `ether` from the account executing the opcode and adds
it to the `rent balance` of the address specified as beneficiary.

Any participant can pay the rent for any other participant. 

Gas cost: TBD

#### `RENTBALANCE &lt;addr&gt;`

The `rent balance` of an account may be queried through the `RENTBALANCE` opcode. It pushes the
`rentbalance` field of the given address to the stack.

Gas cost: like `EXTCODEHASH`.

#### `SSIZE &lt;addr&gt;`

This opcode pushes the `storagesize` field of the given account to the stack.

Gas cost: like `EXTCODEHASH`.

#### `RESTORETO &lt;addr&gt; &lt;codeaddr&gt;`

This opcode restores the inactive account at the given address. This is a bit like
`SELFDESTRUCT` but has more specific semantics.

The account at `addr` must be `inactive` (i.e. have `storagesize` zero) and its
`storageroot` must match the `storageroot` of the contract executing `RESTORETO`. The
`codeaddr` specifies the address of a contract from which code is taken. The code of the
`codeaddr` account must match the `codehash` of `addr`.

If all these preconditions are met, `RESTORETO` transfers the storage of the account
executing the opcode to `addr` and resets its `storagesize` to the full size of the
storage. The code of `addr` is restored as well. `RESTORETO` also transfers any remaining
balance and rent balance to `addr`. The contract executing `RESTORETO` is deleted.

Gas cost: TBD

## Rationale

### Why do we need a separate rent balance?

Accounts need a separate rent balance because some contracts are non-payable, i.e. they
reject regular value transfers. Such contracts might not be able to keep themselves alive,
but users of those contracts can keep them alive by paying rent for them.

Having the additional balance also makes things easier for contracts that hold balance on
behalf of a user. Consider the canonical crowdfunding example, a contract which changes
behavior once a certain balance is reached and which tracks individual user&apos;s balances.
Deducting rent from the main balance of the contract would mess up the contract&apos;s
accounting, leaving it unable to pay back users accurately if the threshold balance isn&apos;t
reached.

### Why restoration?

One of the fundamental guarantees provided by Ethereum is that changes to contract storage
can only be made by the contract itself and storage will persist forever. If you hold a
token balance in a contract, you&apos;ll have those tokens forever. By adding restoration, we
can maintain this guarantee to a certain extent.

### Implementation Impact

The proposed changes tries to fit within the existing state transition model. Note that
there is no mechanism for deactivating accounts the moment they can&apos;t pay rent. Users must
touch accounts to ensure their storage is removed because we&apos;d need to track all accounts
and their rent requirements in an auxlilary data structure otherwise.

## Backwards Compatibility

TBA

## Test Cases

TBA

## Implementation

TBA

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 10 Nov 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1682</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1682</guid>
      </item>
    
      <item>
        <title>Generalized Account Versioning Scheme</title>
        <category>Standards Track/Core</category>
        
          <comments>https://github.com/sorpaas/EIPs/issues/2</comments>
        
        <description>## Simple Summary

Introduce account versioning for smart contracts so upgrading the VM
or introducing new VMs can be easier.

## Abstract

This defines a method of hard forking while maintaining the exact
functionality of existing account by allowing multiple versions of the
virtual machines to execute in the same block. This is also useful to
define future account state structures when we introduce the on-chain
WebAssembly virtual machine.

## Motivation

By allowing account versioning, we can execute different virtual
machine for contracts created at different times. This allows breaking
features to be implemented while making sure existing contracts work
as expected.

Note that this specification might not apply to all hard forks. We
have emergency hard forks in the past due to network attacks. Whether
they should maintain existing account compatibility should be
evaluated in individual basis. If the attack can only be executed once
against some particular contracts, then the scheme defined here might
still be applicable. Otherwise, having a plain emergency hard fork
might still be a good idea.

## Specification

### Account State

Re-define account state stored in the world state trie to have 5
items: `nonce`, `balance`, `storageRoot`, `codeHash`, and
`version`. The newly added field `version` is a 256-bit **scalar**. We
use the definition of &quot;scalar&quot; from Yellow Paper. Note that this is
the same type as `nonce` and `balance`, and it is equivalent to a RLP
variable-sized byte array with no leading zero, of maximum length 32.

When `version` is zero, the account is RLP-encoded with the first 4
items. When `version` is not zero, the account is RLP-encoded with 5
items.

Account versions can also optionally define additional account state
RLP fields, whose meaning are specified through its `version`
field. In those cases, the parsing strategy is defined in &quot;Additional
Fields in Account State RLP&quot; section.

### Contract Execution

When fetching an account code from state, we always fetch the
associated version field together. We refer to this as the *code&apos;s
version* below. The code of the account is always executed in the
*code&apos;s version*.

In particular, this means that for `DELEGATECALL` and `CALLCODE`, the
version of the execution call frame is the same as
delegating/receiving contract&apos;s version.

### Contract Deployment

In Ethereum, a contract has a deployment method, either by a contract
creation transaction, or by another contract. If we regard this
deployment method a contract&apos;s *parent*, then we find them forming a
family of contracts, with the *root* being a contract creation
transaction.

We let a family of contracts to always have the same `version`. That
is, `CREATE` and `CREATE2` will always deploy contract that has the
same `version` as the *code&apos;s version*.

In other words, `CREATE` and `CREATE2` will execute the init code
using the current *code&apos;s version*, and deploy the contract of the
current *code&apos;s version*. This holds even if the to-be-deployed code
is empty.

### Validation

A new phrase, *validation* is added to contract deployment (by
`CREATE` / `CREATE2` opcodes, or by contract creation
transaction). When `version` is `0`, the phrase does nothing and
always succeeds. Future VM versions can define additional validation
that has to be passed.

If the validation phrase fails, deployment does not proceed and return
out-of-gas.

### Contract Creation Transaction

Define `LATEST_VERSION` in a hard fork to be the latest supported VM
version. A contract creation transaction is always executed in
`LATEST_VERSION` (which means the *code&apos;s version* is
`LATEST_VERSION`), and deploys contracts of `LATEST_VERSION`. Before a
contract creation transaction is executed, run *validation* on the
contract creation code. If it does not pass, return out-of-gas.

### Precompiled Contract and Externally-owned Address

Precompiled contracts and externally-owned addresses do not have
`version`. If a message-call transaction or `CALL` / `CALLCODE` /
`STATICCALL` / `DELEGATECALL` touches a new externally-owned address
or a non-existing precompiled contract address, it is always created
with `version` field being `0`.

### Additional Fields in Account State RLP

In the future we may need to associate more information into an
account, and we already have some EIPs that define new additional
fields in the account state RLP. In this section, we define the
parsing strategy when additional fields are added.

* Check the RLP list length, if it is 4, then set account version to
  `0`, and do not parse any additional fields.
* If the RLP list length more than 4, set the account version to the
  scalar at position `4` (counting from `0`).
  * Check version specification for the number of additional fields
    defined `N`, if the RLP list length is not equal to `5 + N`,
    return parse error.
  * Parse RLP position `5` to `4 + N` as the meaning specified in
    additional fields.

## Extensions

In relation to the above &quot;Specification&quot; section, we have defined the
base account versioning layer. The base account versioning layer is
already useful by itself and can handle most EVM improvements. Below
we define two specifications that can be deployed separately, which
improves functionality of base layer account versioning.

Note that this section is provided only for documentation
purpose. When &quot;enabling EIP-1702&quot;, those extensions should not be
enabled unless the extension specification is also included.

* [44-VERTXN: Account Versioning Extension for Contract Creation
  Transaction](https://corepaper.org/ethereum/compatibility/versioning/#extensions-for-state-based-account-versioning)
* [45-VEROP: Account Versioning Extension for CREATE and
  CREATE2](https://corepaper.org/ethereum/compatibility/versioning/#create-and-create2-extension)

## Usage Template

This section defines how other EIPs might use this account
versioning specification. Note that currently we only define the usage
template for base layer.

Account versioning is usually applied directly to a hard fork
meta. EIPs in the hard fork are grouped by the virtual machine
type, for example, EVM and eWASM. For each of them, we define:

* **Version**: a non-zero scalar less than `2^256` that uniquely
  identifies this version. Note that it does not need to be
  sequential.
* **Parent version**: the base that all new features derived
  from. With parent version of `0` we define the base to be legacy
  VM. Note that once a version other than `0` is defined, the legacy
  VM&apos;s feature set must be frozen. When defining an entirely new VM
  (such as eWASM), parent version does not apply.
* **Features**: all additional features that are enabled upon this
  version.

If a meta EIP includes EIPs that provide additional account state RLP
fields, we also define:

* **Account fields**: all account fields up to the end of this meta
  EIP, excluding the basic 5 fields (`nonce`, `balance`,
  `storageRoot`, `codeHash` and `version`). If EIPs included that are
  specific to modifying account fields do not modify VM execution
  logic, it is recommended that we specify an additional version whose
  execution logic is the same as previous version, but only the
  account fields are changed.

## Rationale

This introduces account versioning via a new RLP item in account
state. The design above gets account versioning by making the contract
*family* always have the same version. In this way, versions are only
needed to be provided by contract creation transaction, and there is
no restrictions on formats of code for any version. If we want to
support multiple newest VMs (for example, EVM and WebAssembly running
together), then this will requires extensions such as 44-VERTXN and
45-VEROP.

Alternatively, account versioning can also be done through:

* **[26-VER](https://corepaper.org/ethereum/compatibility/versioning/#prefix-based-account-versioning)** and
  **[40-UNUSED](https://corepaper.org/ethereum/compatibility/forward/)**: This makes an
  account&apos;s versioning solely dependent on its code header prefix. If
  with only 26-VER, it is not possible to certify any code is valid,
  because current VM allows treating code as data. This can be fixed
  by 40-UNUSED, but the drawback is that it&apos;s potentially backward
  incompatible.
* **EIP-1891**: Instead of writing version field into account RLP
  state, we write it in a separate contract. This can accomplish the
  same thing as this EIP and potentially reduces code complexity, but
  the drawback is that every code execution will require an additional
  trie traversal, which impacts performance.

## Backwards Compatibility

Account versioning is fully backwards compatible, and it does not
change how current contracts are executed.

## Discussions

### Performance

Currently nearly all full node implementations uses config parameters
to decide which virtual machine version to use. Switching virtual
machine version is simply an operation that changes a pointer using a
different set of config parameters. As a result, this scheme has
nearly zero impact to performance.

### WebAssembly

This scheme can also be helpful when we deploy on-chain WebAssembly
virtual machine. In that case, WASM contracts and EVM contracts can
co-exist and the execution boundary and interaction model are clearly
defined as above.

## Test Cases and Implementations

To be added.

## References

The source of this specification can be found at
[43-VER](https://corepaper.org/ethereum/compatibility/versioning/#state-based-account-versioning).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 30 Dec 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1702</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1702</guid>
      </item>
    
      <item>
        <title>Disable SSTORE with gasleft lower than call stipend</title>
        <category>Standards Track/Core</category>
        
          <comments>https://github.com/alex-forshtat-tbk/EIPs/issues/1</comments>
        
        <description>## Simple Summary
The proposal that had been accepted changes security properties of a large portion of an existing contract code base that may be infeasible to update and validate. This proposal will make the old assumptions hold even after a network upgrade.

## Abstract
[EIP-1283](/EIPs/EIPS/eip-1283) significantly lowers the gas costs of writing to contract&apos;s storage. This created a danger of a new kind of reentrancy attacks on existing contracts as Solidity by default grants a &apos;stipend&apos; of 2300 gas to simple transfer calls.
This danger is easily mitigated if SSTORE is not allowed in low gasleft state, without breaking the backward compatibility and the original intention of this EIP.

## Motivation

An attack that is described in [this article](https://medium.com/chainsecurity/constantinople-enables-new-reentrancy-attack-ace4088297d9).
Explicitly specifying the call stipend as an invariant will have a positive effect on Ethereum protocol security: 
https://www.reddit.com/r/ethereum/comments/agdqsm/security_alert_ethereum_constantinople/ee5uvjt

## Specification

Add the following condition to the SSTORE opcode gas cost calculation:

* If *gasleft* is less than or equal to 2300, fail the current call frame
  with &apos;out of gas&apos; exception.

## Rationale
In order to keep in place the implicit reentrancy protection of existing contracts, transactions should not be allowed to modify state if the remaining gas is lower then the 2300 stipend given to &apos;transfer&apos;/&apos;send&apos; in Solidity.
These are other proposed remediations and objections to implementing them:

* Drop EIP-1283 and abstain from modifying SSTORE cost
  * EIP-1283 is an important update 
  * It was accepted and implemented on test networks and in clients.
* Add a new call context that permits LOG opcodes but not changes to state.
  * Adds another call type beyond existing regular/staticcall
* Raise the cost of SSTORE to dirty slots to &gt;=2300 gas
  * Makes net gas metering much less useful.
* Reduce the gas stipend
  * Makes the stipend almost useless.
* Increase the cost of writes to dirty slots back to 5000 gas, but add 4800 gas to the refund counter
  * Still doesn’t make the invariant explicit.
  * Requires callers to supply more gas, just to have it refunded
* Add contract metadata specifying per-contract EVM version, and only apply SSTORE changes to contracts deployed with the new version.


## Backwards Compatibility
Performing SSTORE has never been possible with less than 5000 gas, so it does not introduce incompatibility to the Ethereum mainnet. Gas estimation should account for this requirement.

## Test Cases
Test cases for an implementation are mandatory for EIPs that are affecting consensus changes. Other EIPs can choose to include links to test cases if applicable.
TODO
## Implementation
TODO
## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 15 Jan 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1706</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1706</guid>
      </item>
    
      <item>
        <title>URL Format for Web3 Browsers</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/standarize-url-format-for-web3-browsers/2422</comments>
        
        <description>## Simple Summary

A standard way of representing web3 browser URLs for decentralized applications.

## Abstract

Since most normal web browsers (specifically on mobile devices) can not run decentralized applications correctly because of the lack of web3 support, it is necessary to differentiate them from normal urls, so they can be opened in web3 browsers if available.

## Motivation

Lots of dApps that are trying to improve their mobile experience are currently (deep)linking to specific mobile web3 browsers which are currently using their own url scheme.

In order to make the experience more seamless, dApps should still be able to recommend a specific mobile web3 browser via [deferred deeplinking](https://en.wikipedia.org/wiki/Deferred_deep_linking) but by having a standard url format, if the user already has a web3 browser installed that implements this standard, it will be automatically linked to it.

There is also a compatibility problem with the current `ethereum:` url scheme described in [EIP-831](/EIPs/EIPS/eip-831) where any ethereum related app (wallets, identity management, etc) already registered it and because of iOS unpredictable behavior for multiple apps handling a single url scheme, users can end up opening an `ethereum:` link in an app that doesn not include a web3 browser and will not be able to handle the deeplink correctly.

## Specification

### Syntax

Web3 browser URLs contain &quot;dapp&quot; in their schema (protocol) part and are constructed as follows:

    request                 = &quot;dapp&quot; &quot;:&quot; [chain_id &quot;@&quot;] dapp_url
    chain_id                = 1*DIGIT
    dapp_url                = URI

### Semantics

`chain_id` is optional and it is a parameter for the browser to automatically select the corresponding chain ID as specified in [EIP-155](/EIPs/EIPS/eip-155) before opening the dApp.

`dapp_url` is a valid [RFC3986](https://www.ietf.org/rfc/rfc3986.txt) URI

This a complete example url:

`dapp:1@peepeth.com/brunobar79?utm_source=github`

which will open the web3 browser, select `mainnet` (chain_id = 1) and then navigate to:

`https://peepeth.com/brunobar79?utm_source=github`

## Rationale

The proposed format attempts to solve the problem of vendor specific protocols for web3 browsers, avoiding conflicts with the existing &apos;ethereum:&apos; URL scheme while also adding an extra feature: `chain_id` which will help dApps to be accessed with the right network preselected, optionally extracting away that complexity from end users.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 13 Jan 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1710</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1710</guid>
      </item>
    
      <item>
        <title>Hardfork Meta: Petersburg</title>
        <category>Meta/</category>
        
        <description>## Abstract

This meta-EIP specifies the changes included in the Ethereum hardfork that removes [EIP-1283](/EIPs/EIPS/eip-1283) from [Constantinople](/EIPs/EIPS/eip-1013).

## Specification

- Codename: Petersburg
- Aliases: St. Petersfork, Peter&apos;s Fork, Constantinople Fix
- Activation:
  - `Block &gt;= 7_280_000` on the Ethereum Mainnet
  - `Block &gt;= 4_939_394` on the Ropsten testnet
  - `Block &gt;= 10_255_201` on the Kovan testnet
  - `Block &gt;= 4_321_234` on the Rinkeby testnet
  - `Block &gt;= 0` on the Görli testnet
- Removed EIPs:
  - [EIP-1283](/EIPs/EIPS/eip-1283): Net gas metering for SSTORE without dirty maps

If `Petersburg` and `Constantinople` are applied at the same block, `Petersburg` takes precedence: with the net effect of EIP-1283 being _disabled_.

If `Petersburg` is defined with an earlier block number than `Constantinople`, then there is _no immediate effect_ from the `Petersburg` fork. However, when `Constantinople` is later activated, EIP-1283 should be _disabled_.

## References

1. The list above includes the EIPs that had to be removed from Constantinople due to a [potential reentrancy attack vector](https://medium.com/chainsecurity/constantinople-enables-new-reentrancy-attack-ace4088297d9). Removing this was agreed upon at the [All-Core-Devs call #53 in January 2019](https://github.com/ethereum/pm/issues/70).
2. https://blog.ethereum.org/2019/02/22/ethereum-constantinople-st-petersburg-upgrade-announcement/

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 21 Jan 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1716</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1716</guid>
      </item>
    
      <item>
        <title>Smart Contract Interface for Licences</title>
        <category>Standards Track/ERC</category>
        
        <description>## Abstract

This Ethereum Improvement Proposal (EIP) proposes an Ethereum standard for the issuance of licences, permits and grants (Licences). 

A Licence is a limited and temporary authority, granted to a natural (e.g. you) or legal person (e.g. a corporation), to do something that would otherwise be unlawful pursuant to a legal framework. A public Licence is granted by the government, directly (e.g. by the New South Wales Department of Primary Industries, Australia) or indirectly (e.g. by an agent operating under the government’s authority), and derives its authority from legislation, though this is often practically achieved via delegated legislation such as regulations. This can be contrasted to a private licence – for example, the licence you grant to a visitor who comes onto your property.

A Licence has the following properties:

* granted personally to the licencee (Licencee), though it may be transferrable to another person or company;
* conferring a temporary right to the Licencee to own, use or do something that would otherwise be prohibited, without conferring any property interest in the underlying thing. For example, you may be granted a licence to visit a national park without acquiring any ownership in or over the park itself;
* allowing the government authority responsible for the Licence to amend, revoke, renew, suspend or deny the issuance of the Licence, or to impose conditions or penalties for non-compliance; and
* usually issued only after the payment of a fee or the meeting of some criteria.

Additionally, a Licence may be granted in respect of certain information. For example, a Licence may be issued in respect of a vehicle registration number and attaching to that specific registered vehicle.

## Motivation

Governments are responsible for the issuance and management of Licences. However, maintaining and sharing this data can be complicated and inefficient. The granting of Licences usually requires the filing of paper-based application forms, manual oversight of applicable legislation and data entry into registries, as well as the issuance of paper based Licences. If individuals wish to sight information on Licence registries, they often need to be present at the government office and complete further paper-based enquiry forms in order to access that data (if available publicly).

This EIP seeks to define a standard that will allow for the granting and/or management of Licences via Ethereum smart contracts. The motivation is, in essence, to address the inefficiencies inherent in current licencing systems.

## Specification

### Methods

**NOTES**:
 - The following specifications use syntax from Solidity `0.4.17` (or above)
 - Callers MUST handle `false` from `returns (bool success)`.  Callers MUST NOT assume that `false` is never returned!


#### name

Returns the name of the permit - e.g. `&quot;MyPermit&quot;`.

``` js
function name() public view returns (string);
```

#### totalSupply

Returns the total permit supply.

``` js
function totalSupply() public view returns (uint256);
```

#### grantAuthority

Adds an ethereum address to a white list of addresses that have authority to modify a permit.

``` js
function grantAuthority(address who) public;
```

#### revokeAuthority

Removes an ethereum address from a white list of addresses that have authority to modify a permit.

``` js
function revokeAuthority(address who) public;
```

#### hasAuthority

Checks to see if the address has authority to grant or revoke permits.

``` js
function hasAuthority(address who) public view;
```

#### issue

Issues an ethereum address a permit between the specified date range.

``` js
function issue(address who, uint256 validFrom, uint256 validTo) public;
```

#### revoke

Revokes a permit from an ethereum address.
	
``` js
function revoke(address who) public;
```

#### hasValid

Checks to see if an ethereum address has a valid permit.
	
``` js
function hasValid(address who) external view returns (bool);
```

#### purchase

Allows a user to self procure a licence.
	
``` js
function purchase(uint256 validFrom, uint256 validTo) external payable;
```

## Rationale

The use of smart contracts to apply for, renew, suspend and revoke Licences will free up much needed government resources and allow for the more efficient management of Licences. The EIP also seeks to improve the end user experience of the Licence system. In an era of open government, there is also an increased expectation that individuals will be able to easily access Licence registries, and that the process will be transparent and fair.

By creating an EIP, we hope to increase the use of Ethereum based and issued Licences, which will address these issues.

The Ethereum blockchain is adaptable to various Licences and government authorities. It will also be easily translatable into other languages and can be used by other governmental authorities across the world. Moreover, a blockchain will more effectively protect the privacy of Licence-holders’ data, particularly at a time of an ever-increasing volume of government data breaches.

The EIP has been developed following the review of a number of licensing regulations at the national and state level in Australia. The review allowed the identification of the common licence requirements and criteria for incorporation into the EIP. We have included these in the proposed standard but seek feedback on whether these criteria are sufficient and universal.

## Test Cases

A real world example of a Licence is a permit required to camp in a national park in Australia (e.g. Kakadu national park in the Northern Territory of Australia) under the Environment Protection and Biodiversity Conservation Regulations 2000 (Cth) (EPBC Act) and the Environment Protection and Biodiversity Conservation Regulations 2000 (the Regulations). Pursuant to the EPBC Act and the Regulations, the Director of National Parks oversees a camping permit system, which is intended to help regulate certain activities in National Parks. Permits allowing access to National Parks can be issued to legal or natural persons if the applicant has met certain conditions.

The current digital portal and application form to camp at Kakadu National Park (the Application) can be accessed at: https://www.environment.gov.au/system/files/resources/b3481ed3-164b-4e72-a9f8-91fc987d90e7/files/kakadu-camping-permit-form-19jan2015-pdf.pdf

The user must provide the following details when making an Application:

* The full name and contact details of each person to whom the permit is to be issued;

* If the applicant is a company or other incorporated body:

o the name, business address and postal address of the company or incorporated body;

o if the applicant is a company—

* the full name of each of the directors of the company;

* the full name and contact details of the person completing the application form;

* the ACN or ABN of the company or other incorporated body (if applicable);

* Details of the proposed camping purpose (e.g. private camping, school group, etc.);

* A start date and duration for the camping (up to the maximum duration allowed by law);

* Number of campers (up to the maximum allowed by law);

* All other required information not essential to the issuance of the Licence (e.g. any particular medical needs of the campers); and

* Fees payable depending on the site, duration and number of campers.

The Regulations also set out a number of conditions that must be met by licensees when the permit has been issued. The Regulations allow the Director of National Parks to cancel, renew or transfer the licence. The above workflow could be better performed by way of a smart contract.

The key criteria required as part of this process form part of the proposed Ethereum standard. We have checked this approach by also considering the issuance of a Commercial Fishing Licence under Part 8 “Licensing and other commercial fisheries management” of the Fisheries Management (General) Regulation 2010 (NSW) (Fisheries Regulations) made pursuant to the Fisheries Management Act 1994 (NSW) (Fisheries Act).

## Implementation

The issuance and ownership of a Licence can be digitally represented on the Ethereum blockchain.

Smart contracts can be used to embed regulatory requirements with respect to the relevant Licence in the blockchain. The Licence would be available electronically in the form of a token. This might be practically represented by a QR code, for example, displaying the current Licence information. The digital representation of the Licence would be stored in a digital wallet, typically an application on a smartphone or tablet computer. The proposed standard allows issuing authorities or regulators to amend, revoke or deny Licences from time to time, with the result of their determinations reflected in the Licence token in near real-time. Licence holders will therefore be notified almost instantly of any amendments, revocations or issues involving their Licence.

## Interface 

### Solidity Example
```solidity
interface EIP1753 {
	
	function grantAuthority(address who) external;
	function revokeAuthority(address who) external;
	function hasAuthority(address who) external view returns (bool);
	
	function issue(address who, uint256 from, uint256 to) external;
	function revoke(address who) external;
	
	function hasValid(address who) external view returns (bool);
	function purchase(uint256 validFrom, uint256 validTo) external payable;
}

pragma solidity ^0.5.3;

contract EIP is EIP1753 {

	string public name = &quot;Kakadu National Park Camping Permit&quot;;
	uint256 public totalSupply;

	address private _owner;
	mapping(address =&gt; bool) private _authorities;
	mapping(address =&gt; Permit) private _holders;
	
	struct Permit {
		address issuer;
		uint256 validFrom;
		uint256 validTo;
	}
	
	constructor() public {
		_owner = msg.sender;
	}
	
	function grantAuthority(address who) public onlyOwner() {
		_authorities[who] = true;
	}
	
	function revokeAuthority(address who) public onlyOwner() {
		delete _authorities[who];
	}
	
	function hasAuthority(address who) public view returns (bool) {
		return _authorities[who] == true;
	}
	
	function issue(address who, uint256 start, uint256 end) public onlyAuthority() {
		_holders[who] = Permit(_owner, start, end);
		totalSupply += 1;
	}
	
	function revoke(address who) public onlyAuthority() {
		delete _holders[who];
	}
	
	function hasValid(address who) external view returns (bool) {
	    return _holders[who].validFrom &gt; now &amp;&amp; _holders[who].validTo &lt; now;
	}

	function purchase(uint256 validFrom, uint256 validTo) external payable {
	    require(msg.value == 1 ether, &quot;Incorrect fee&quot;);
	    issue(msg.sender, validFrom, validTo);
	}
	
	modifier onlyOwner() {
		require(msg.sender == _owner, &quot;Only owner can perform this function&quot;);
		_;
	}
	
	modifier onlyAuthority() {
		require(hasAuthority(msg.sender), &quot;Only an authority can perform this function&quot;);
        _;
	}
}
```

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 06 Feb 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1753</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1753</guid>
      </item>
    
      <item>
        <title>Scoped Approval Interface</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1761</comments>
        
        <description>## Simple Summary

A standard interface to permit restricted approval in token contracts by defining &quot;scopes&quot; of one or more Token IDs.

## Abstract

This interface is designed for use with token contracts that have an &quot;ID&quot; domain, such as ERC-1155 or ERC-721. This enables restricted approval of one or more Token IDs to a specific &quot;scope&quot;. When considering a smart contract managing tokens from multiple different domains, it makes sense to limit approvals to those domains. Scoped approval is a generalization of this idea. Implementors can define scopes as needed.

Sample use cases for scopes:

* A company may represent its fleet of vehicles on the blockchain and it could create a scope for each regional office.
* Game developers could share an [ERC-1155](/EIPs/EIPS/eip-1155) contract where each developer manages tokens under a specified scope.
* Tokens of different value could be split into separate scopes. High-value tokens could be kept in smaller separate scopes while low-value tokens might be kept in a shared scope. Users would approve the entire low-value token scope to a third-party smart contract, exchange, or other application without concern about losing their high-value tokens in the event of a problem.

## Motivation

It may be desired to restrict approval in some applications. Restricted approval can prevent losses in cases where users do not audit the contracts they&apos;re approving. No standard API is supplied to manage scopes as this is implementation specific. Some implementations may opt to offer a fixed number of scopes, or assign a specific set of scopes to certain types. Other implementations may open up scope configuration to its users and offer methods to create scopes and assign IDs to them.

# Specification

```solidity
pragma solidity ^0.5.2;

/**
    Note: The ERC-165 identifier for this interface is 0x30168307.
*/
interface ScopedApproval {
    /**
        @dev MUST emit when approval changes for scope.
    */
    event ApprovalForScope(address indexed _owner, address indexed _operator, bytes32 indexed _scope, bool _approved);

    /**
        @dev MUST emit when the token IDs are added to the scope.
        By default, IDs are in no scope.
        The range is inclusive: _idStart, _idEnd, and all IDs in between have been added to the scope.
        _idStart must be lower than or equal to _idEnd.
    */
    event IdsAddedToScope(uint256 indexed _idStart, uint256 indexed _idEnd, bytes32 indexed _scope);

    /**
        @dev MUST emit when the token IDs are removed from the scope.
        The range is inclusive: _idStart, _idEnd, and all IDs in between have been removed from the scope.
        _idStart must be lower than or equal to _idEnd.
    */
    event IdsRemovedFromScope(uint256 indexed _idStart, uint256 indexed _idEnd, bytes32 indexed _scope);

    /** @dev MUST emit when a scope URI is set or changes.
        URIs are defined in RFC 3986.
        The URI MUST point a JSON file that conforms to the &quot;Scope Metadata JSON Schema&quot;.
    */
    event ScopeURI(string _value, bytes32 indexed _scope);

    /**
        @notice     Returns the number of scopes that contain _id.
        @param _id  The token ID
        @return     The number of scopes containing the ID
    */
    function scopeCountForId(uint256 _id) public view returns (uint32);

    /**
        @notice             Returns a scope that contains _id.
        @param _id          The token ID
        @param _scopeIndex  The scope index to  query (valid values are 0 to scopeCountForId(_id)-1)
        @return             The Nth scope containing the ID
    */
    function scopeForId(uint256 _id, uint32 _scopeIndex) public view returns (bytes32);

    /**
        @notice Returns a URI that can be queried to get scope metadata. This URI should return a JSON document containing, at least the scope name and description. Although supplying a URI for every scope is recommended, returning an empty string &quot;&quot; is accepted for scopes without a URI.
        @param  _scope  The queried scope
        @return         The URI describing this scope.
    */
    function scopeUri(bytes32 _scope) public view returns (string memory);

    /**
        @notice Enable or disable approval for a third party (&quot;operator&quot;) to manage the caller&apos;s tokens in the specified scope.
        @dev MUST emit the ApprovalForScope event on success.
        @param _operator    Address to add to the set of authorized operators
        @param _scope       Approval scope (can be identified by calling scopeForId)
        @param _approved    True if the operator is approved, false to revoke approval
    */
    function setApprovalForScope(address _operator, bytes32 _scope, bool _approved) external;

    /**
        @notice Queries the approval status of an operator for a given owner, within the specified scope.
        @param _owner       The owner of the Tokens
        @param _operator    Address of authorized operator
        @param _scope       Scope to test for approval (can be identified by calling scopeForId)
        @return             True if the operator is approved, false otherwise
    */
    function isApprovedForScope(address _owner, address _operator, bytes32 _scope) public view returns (bool);
}
```

## Scope Metadata JSON Schema

This schema allows for localization. `{id}` and `{locale}` should be replaced with the appropriate values by clients.

```json
{
    &quot;title&quot;: &quot;Scope Metadata&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;required&quot;: [&quot;name&quot;],
    &quot;properties&quot;: {
        &quot;name&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Identifies the scope in a human-readable way.&quot;,
        },
        &quot;description&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Describes the scope to allow users to make informed approval decisions.&quot;,
        },
        &quot;localization&quot;: {
            &quot;type&quot;: &quot;object&quot;,
            &quot;required&quot;: [&quot;uri&quot;, &quot;default&quot;, &quot;locales&quot;],
            &quot;properties&quot;: {
                &quot;uri&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;The URI pattern to fetch localized data from. This URI should contain the substring `{locale}` which will be replaced with the appropriate locale value before sending the request.&quot;
                },
                &quot;default&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;The locale of the default data within the base JSON&quot;
                },
                &quot;locales&quot;: {
                    &quot;type&quot;: &quot;array&quot;,
                    &quot;description&quot;: &quot;The list of locales for which data is available. These locales should conform to those defined in the Unicode Common Locale Data Repository (http://cldr.unicode.org/).&quot;
                }
            }
        }
    }
}
```

### Localization

Metadata localization should be standardized to increase presentation uniformity across all languages. As such, a simple overlay method is proposed to enable localization. If the metadata JSON file contains a `localization` attribute, its content may be used to provide localized values for fields that need it. The `localization` attribute should be a sub-object with three attributes: `uri`, `default` and `locales`. If the string `{locale}` exists in any URI, it MUST be replaced with the chosen locale by all client software.

## Rationale

The initial design was proposed as an extension to ERC-1155: [Discussion Thread - Comment 1](https://github.com/ethereum/EIPs/issues/1155#issuecomment-459505728). After some discussion: [Comment 2](https://github.com/ethereum/EIPs/issues/1155#issuecomment-460603439) and suggestions by the community to implement this approval mechanism in an external contract [Comment 3](https://github.com/ethereum/EIPs/issues/1155#issuecomment-461758755), it was decided that as an interface standard, this design would allow many different token standards such as ERC-721 and ERC-1155 to implement scoped approvals without forcing the system into all implementations of the tokens.

### Metadata JSON

The Scope Metadata JSON Schema was added in order to support human-readable scope names and descriptions in more than one language.

## References

**Standards**
- [ERC-1155 Multi Token Standard](/EIPs/EIPS/eip-1155)
- [ERC-165 Standard Interface Detection](/EIPs/EIPS/eip-165)
- [JSON Schema](https://json-schema.org/)

**Implementations**
- [Enjin Coin](https://enjincoin.io) ([github](https://github.com/enjin))

**Articles &amp; Discussions**
- [GitHub - Original Discussion Thread](https://github.com/ethereum/EIPs/issues/1761)
- [GitHub - ERC-1155 Discussion Thread](https://github.com/ethereum/EIPs/issues/1155)

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 18 Feb 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1761</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1761</guid>
      </item>
    
      <item>
        <title>GraphQL interface to Ethereum node data</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/graphql-interface-to-ethereum-node-data/2710</comments>
        
        <description>## Abstract
This EIP specifies a GraphQL schema for accessing data stored on an Ethereum node. It aims to provide a complete replacement to the read-only information exposed via the present JSON-RPC interface, while improving on usability, consistency, efficiency, and future-proofing.

## Motivation
The current JSON-RPC interface for Ethereum nodes has a number of shortcomings. It&apos;s informally and incompletely specified in areas, which has led to incompatibilities around issues such as representation of empty byte strings (&quot;&quot; vs &quot;0x&quot; vs &quot;0x0&quot;), and it has to make educated guesses about the data a user will request, which often leads to unnecessary work.

For example, the `totalDifficulty` field is stored separately from the block header in common Ethereum node implementations, and many callers do not require this field. However, every call to `eth_getBlock` still retrieves this field, requiring a separate disk read, because the RPC server has no way of knowing if the user requires this field or not.

Similarly, transaction receipts in go-ethereum are stored on disk as a single binary blob for each block. Fetching a receipt for a single transaction requires fetching and deserializing this blob, then finding the relevant entry and returning it; this is accomplished by the `eth_getTransactionReceipt` API call. A common task for API consumers is to fetch all the receipts in a block; as a result, node implementations end up fetching and deserializing the same data repeatedly, leading to `O(n^2)` effort to fetch all transaction receipts from a block instead of `O(n)`.

Some of these issues could be fixed with changes to the existing JSON-RPC interface, at the cost of complicating the interface somewhat. Instead, we propose adopting a standard query language, GraphQL, which facilitates more efficient API implementations, while also increasing flexibility.

## Prior Art

Nick Johnson and [EthQL](https://github.com/ConsenSys/ethql) independently developed a GraphQL schema for node data. Once the parties were made aware of the shared effort, they made efforts to bring their schemas into alignment. The current schema proposed in this EIP is derived primarily from the EthQL schema.

## Specification

### Node API

Compatible nodes MUST provide a GraphQL endpoint available over HTTP. This SHOULD be offered on port 8547 by default. The path to the GraphQL endpoint SHOULD be &apos;/graphql&apos;.

Compatible nodes MAY offer a GraphiQL interactive query explorer on the root path (&apos;/&apos;).

### Schema

The GraphQL schema for this service is defined as follows:
```
# Bytes32 is a 32 byte binary string, represented as 0x-prefixed hexadecimal.
scalar Bytes32
# Address is a 20 byte Ethereum address, represented as 0x-prefixed hexadecimal.
scalar Address
# Bytes is an arbitrary length binary string, represented as 0x-prefixed hexadecimal.
# An empty byte string is represented as &apos;0x&apos;. Byte strings must have an even number of hexadecimal nybbles.
scalar Bytes
# BigInt is a large integer. Input is accepted as either a JSON number or as a string.
# Strings may be either decimal or 0x-prefixed hexadecimal. Output values are all
# 0x-prefixed hexadecimal.
scalar BigInt
# Long is a 64 bit unsigned integer.
scalar Long

schema {
    query: Query
    mutation: Mutation
}

# Account is an Ethereum account at a particular block.
type Account {
    # Address is the address owning the account.
    address: Address!
    # Balance is the balance of the account, in wei.
    balance: BigInt!
    # TransactionCount is the number of transactions sent from this account,
    # or in the case of a contract, the number of contracts created. Otherwise
    # known as the nonce.
    transactionCount: Long!
    # Code contains the smart contract code for this account, if the account
    # is a (non-self-destructed) contract.
    code: Bytes!
    # Storage provides access to the storage of a contract account, indexed
    # by its 32 byte slot identifier.
    storage(slot: Bytes32!): Bytes32!
}

# Log is an Ethereum event log.
type Log {
    # Index is the index of this log in the block.
    index: Int!
    # Account is the account which generated this log - this will always
    # be a contract account.
    account(block: Long): Account!
    # Topics is a list of 0-4 indexed topics for the log.
    topics: [Bytes32!]!
    # Data is unindexed data for this log.
    data: Bytes!
    # Transaction is the transaction that generated this log entry.
    transaction: Transaction!
}

# Transaction is an Ethereum transaction.
type Transaction {
    # Hash is the hash of this transaction.
    hash: Bytes32!
    # Nonce is the nonce of the account this transaction was generated with.
    nonce: Long!
    # Index is the index of this transaction in the parent block. This will
    # be null if the transaction has not yet been mined.
    index: Int
    # From is the account that sent this transaction - this will always be
    # an externally owned account.
    from(block: Long): Account!
    # To is the account the transaction was sent to. This is null for
    # contract-creating transactions.
    to(block: Long): Account
    # Value is the value, in wei, sent along with this transaction.
    value: BigInt!
    # GasPrice is the price offered to miners for gas, in wei per unit.
    gasPrice: BigInt!
    # Gas is the maximum amount of gas this transaction can consume.
    gas: Long!
    # InputData is the data supplied to the target of the transaction.
    inputData: Bytes!
    # Block is the block this transaction was mined in. This will be null if
    # the transaction has not yet been mined.
    block: Block

    # Status is the return status of the transaction. This will be 1 if the
    # transaction succeeded, or 0 if it failed (due to a revert, or due to
    # running out of gas). If the transaction has not yet been mined, this
    # field will be null.
    status: Long
    # GasUsed is the amount of gas that was used processing this transaction.
    # If the transaction has not yet been mined, this field will be null.
    gasUsed: Long
    # CumulativeGasUsed is the total gas used in the block up to and including
    # this transaction. If the transaction has not yet been mined, this field
    # will be null.
    cumulativeGasUsed: Long
    # CreatedContract is the account that was created by a contract creation
    # transaction. If the transaction was not a contract creation transaction,
    # or it has not yet been mined, this field will be null.
    createdContract(block: Long): Account
    # Logs is a list of log entries emitted by this transaction. If the
    # transaction has not yet been mined, this field will be null.
    logs: [Log!]
}

# BlockFilterCriteria encapsulates log filter criteria for a filter applied
# to a single block.
input BlockFilterCriteria {
    # Addresses is list of addresses that are of interest. If this list is
    # empty, results will not be filtered by address.
    addresses: [Address!]
    # Topics list restricts matches to particular event topics. Each event has a list
  # of topics. Topics matches a prefix of that list. An empty element array matches any
  # topic. Non-empty elements represent an alternative that matches any of the
  # contained topics.
  #
  # Examples:
  #  - [] or nil          matches any topic list
  #  - [[A]]              matches topic A in first position
  #  - [[], [B]]          matches any topic in first position, B in second position
  #  - [[A], [B]]         matches topic A in first position, B in second position
  #  - [[A, B]], [C, D]]  matches topic (A OR B) in first position, (C OR D) in second position
    topics: [[Bytes32!]!]
}

# Block is an Ethereum block.
type Block {
    # Number is the number of this block, starting at 0 for the genesis block.
    number: Long!
    # Hash is the block hash of this block.
    hash: Bytes32!
    # Parent is the parent block of this block.
    parent: Block
    # Nonce is the block nonce, an 8 byte sequence determined by the miner.
    nonce: Bytes!
    # TransactionsRoot is the keccak256 hash of the root of the trie of transactions in this block.
    transactionsRoot: Bytes32!
    # TransactionCount is the number of transactions in this block. if
    # transactions are not available for this block, this field will be null.
    transactionCount: Int
    # StateRoot is the keccak256 hash of the state trie after this block was processed.
    stateRoot: Bytes32!
    # ReceiptsRoot is the keccak256 hash of the trie of transaction receipts in this block.
    receiptsRoot: Bytes32!
    # Miner is the account that mined this block.
    miner(block: Long): Account!
    # ExtraData is an arbitrary data field supplied by the miner.
    extraData: Bytes!
    # GasLimit is the maximum amount of gas that was available to transactions in this block.
    gasLimit: Long!
    # GasUsed is the amount of gas that was used executing transactions in this block.
    gasUsed: Long!
    # Timestamp is the unix timestamp at which this block was mined.
    timestamp: BigInt!
    # LogsBloom is a bloom filter that can be used to check if a block may
    # contain log entries matching a filter.
    logsBloom: Bytes!
    # MixHash is the hash that was used as an input to the PoW process.
    mixHash: Bytes32!
    # Difficulty is a measure of the difficulty of mining this block.
    difficulty: BigInt!
    # TotalDifficulty is the sum of all difficulty values up to and including
    # this block.
    totalDifficulty: BigInt!
    # OmmerCount is the number of ommers (AKA uncles) associated with this
    # block. If ommers are unavailable, this field will be null.
    ommerCount: Int
    # Ommers is a list of ommer (AKA uncle) blocks associated with this block.
    # If ommers are unavailable, this field will be null. Depending on your
    # node, the transactions, transactionAt, transactionCount, ommers,
    # ommerCount and ommerAt fields may not be available on any ommer blocks.
    ommers: [Block]
    # OmmerAt returns the ommer (AKA uncle) at the specified index. If ommers
    # are unavailable, or the index is out of bounds, this field will be null.
    ommerAt(index: Int!): Block
    # OmmerHash is the keccak256 hash of all the ommers (AKA uncles)
    # associated with this block.
    ommerHash: Bytes32!
    # Transactions is a list of transactions associated with this block. If
    # transactions are unavailable for this block, this field will be null.
    transactions: [Transaction!]
    # TransactionAt returns the transaction at the specified index. If
    # transactions are unavailable for this block, or if the index is out of
    # bounds, this field will be null.
    transactionAt(index: Int!): Transaction
    # Logs returns a filtered set of logs from this block.
    logs(filter: BlockFilterCriteria!): [Log!]!
    # Account fetches an Ethereum account at the current block&apos;s state.
    account(address: Address!): Account
    # Call executes a local call operation at the current block&apos;s state.
    call(data: CallData!): CallResult
    # EstimateGas estimates the amount of gas that will be required for
    # successful execution of a transaction at the current block&apos;s state.
    estimateGas(data: CallData!): Long!
}

# CallData represents the data associated with a local contract call.
# All fields are optional.
input CallData {
    # From is the address making the call.
    from: Address
    # To is the address the call is sent to.
    to: Address
    # Gas is the amount of gas sent with the call.
    gas: Long
    # GasPrice is the price, in wei, offered for each unit of gas.
    gasPrice: BigInt
    # Value is the value, in wei, sent along with the call.
    value: BigInt
    # Data is the data sent to the callee.
    data: Bytes
}

# CallResult is the result of a local call operation.
type CallResult {
    # Data is the return data of the called contract.
    data: Bytes!
    # GasUsed is the amount of gas used by the call, after any refunds.
    gasUsed: Long!
    # Status is the result of the call - 1 for success or 0 for failure.
    status: Long!
}

# FilterCriteria encapsulates log filter criteria for searching log entries.
input FilterCriteria {
    # FromBlock is the block at which to start searching, inclusive. Defaults
    # to the latest block if not supplied.
    fromBlock: Long
    # ToBlock is the block at which to stop searching, inclusive. Defaults
    # to the latest block if not supplied.
    toBlock: Long
    # Addresses is a list of addresses that are of interest. If this list is
    # empty, results will not be filtered by address.
    addresses: [Address!]
    # Topics list restricts matches to particular event topics. Each event has a list
  # of topics. Topics matches a prefix of that list. An empty element array matches any
  # topic. Non-empty elements represent an alternative that matches any of the
  # contained topics.
  #
  # Examples:
  #  - [] or nil          matches any topic list
  #  - [[A]]              matches topic A in first position
  #  - [[], [B]]          matches any topic in first position, B in second position
  #  - [[A], [B]]         matches topic A in first position, B in second position
  #  - [[A, B]], [C, D]]  matches topic (A OR B) in first position, (C OR D) in second position
    topics: [[Bytes32!]!]
}

# SyncState contains the current synchronisation state of the client.
type SyncState{
    # StartingBlock is the block number at which synchronisation started.
    startingBlock: Long!
    # CurrentBlock is the point at which synchronisation has presently reached.
    currentBlock: Long!
    # HighestBlock is the latest known block number.
    highestBlock: Long!
    # PulledStates is the number of state entries fetched so far, or null
    # if this is not known or not relevant.
    pulledStates: Long
    # KnownStates is the number of states the node knows of so far, or null
    # if this is not known or not relevant.
    knownStates: Long
}

# Pending represents the current pending state.
type Pending {
  # TransactionCount is the number of transactions in the pending state.
  transactionCount: Int!
  # Transactions is a list of transactions in the current pending state.
  transactions: [Transaction!]
  # Account fetches an Ethereum account for the pending state.
  account(address: Address!): Account
  # Call executes a local call operation for the pending state.
  call(data: CallData!): CallResult
  # EstimateGas estimates the amount of gas that will be required for
  # successful execution of a transaction for the pending state.
  estimateGas(data: CallData!): Long!  
}

type Query {
    # Block fetches an Ethereum block by number or by hash. If neither is
    # supplied, the most recent known block is returned.
    block(number: Long, hash: Bytes32): Block
    # Blocks returns all the blocks between two numbers, inclusive. If
    # to is not supplied, it defaults to the most recent known block.
    blocks(from: Long!, to: Long): [Block!]!
    # Pending returns the current pending state.
    pending: Pending!
    # Transaction returns a transaction specified by its hash.
    transaction(hash: Bytes32!): Transaction
    # Logs returns log entries matching the provided filter.
    logs(filter: FilterCriteria!): [Log!]!
    # GasPrice returns the node&apos;s estimate of a gas price sufficient to
    # ensure a transaction is mined in a timely fashion.
    gasPrice: BigInt!
    # ProtocolVersion returns the current wire protocol version number.
    protocolVersion: Int!
    # Syncing returns information on the current synchronisation state.
    syncing: SyncState
}

type Mutation {
    # SendRawTransaction sends an RLP-encoded transaction to the network.
    sendRawTransaction(data: Bytes!): Bytes32!
}
```

Nodes MAY offer a superset of this schema, by adding new fields or types. Experimental or client-specific fields MUST be prefixed with &apos;_client_&apos; (eg, &apos;_geth_&apos; or &apos;_parity_&apos;). Unprefixed fields MUST be specified in a new EIP that extends this one.

## Rationale
Ethereum nodes have been moving away from providing read-write functionality such as transaction and message signing, and from other services such as code compilation, in favor of a more &apos;unix-like&apos; approach where each task is performed by a dedicated process. We have thus specified a core set of types and fields that reflects this trend, leaving out functionality that is presently, or intended to be, deprecated:

 - `eth_compile*` calls are deprecated, and hence not provided here.
 - `eth_accounts`, `eth_sign`, and `eth_sendTransaction` are considered by many to be deprecated, and are not provided here; callers should use local accounts or a separate signing daemon instead.

Further, two areas of the current API interface have been omitted for simplicity in this initial standard, with the intention that they will be defined in a later EIP:

 - Filters will require use of GraphQL subscriptions, and require careful consideration around the desire for nodes without local per-caller state.
 - Mining functionality is less-used and benefits less from reimplementation in GraphQL, and should be specified in a separate EIP.

## Backwards Compatibility

This schema implements the bulk of the current read-only functionality provided by the JSON-RPC node interface. Existing RPC calls can be mapped to GraphQL queries as follows:

| RPC | Status | Description |
| --- | ------ | ----------- |
| eth_blockNumber | IMPLEMENTED |  `{ block { number } }` |
| eth_call | IMPLEMENTED | `{ call(data: { to: &quot;0x...&quot;, data: &quot;0x...&quot; }) { data status gasUsed } }` |
| eth_estimateGas | IMPLEMENTED | `{ estimateGas(data: { to: &quot;0x...&quot;, data: &quot;0x...&quot; }) }` |
| eth_gasPrice | IMPLEMENTED | `{ gasPrice }` |
| eth_getBalance | IMPLEMENTED |  `{ account(address: &quot;0x...&quot;) { balance } }` |
| eth_getBlockByHash | IMPLEMENTED |  `{ block(hash: &quot;0x...&quot;) { ... } }` |
| eth_getBlockByNumber | IMPLEMENTED |  `{ block(number: 123) { ... } }` |
| eth_getBlockTransactionCountByHash | IMPLEMENTED |  `{ block(hash: &quot;0x...&quot;) { transactionCount } }` |
| eth_getBlockTransactionCountByNumber | IMPLEMENTED |  `{ block(number: x) { transactionCounnt } }` |
| eth_getCode | IMPLEMENTED |  `{ account(address: &quot;0x...&quot;) { code } }` |
| eth_getLogs | IMPLEMENTED | `{ logs(filter: { ... }) { ... } }` or `{ block(...) { logs(filter: { ... }) { ... } } }` |
| eth_getStorageAt | IMPLEMENTED |  `{ account(address: &quot;0x...&quot;) { storage(slot: &quot;0x...&quot;) } }` |
| eth_getTransactionByBlockHashAndIndex | IMPLEMENTED | `{ block(hash: &quot;0x...&quot;) { transactionAt(index: x) { ... } } }` |
| eth_getTransactionByBlockNumberAndIndex | IMPLEMENTED | `{ block(number: n) { transactionAt(index: x) { ... } } }` |
| eth_getTransactionByHash | IMPLEMENTED |  `{ transaction(hash: &quot;0x...&quot;) { ... } }` |
| eth_getTransactionCount | IMPLEMENTED |  `{ account(address: &quot;0x...&quot;) { transactionCount } }` |
| eth_getTransactionReceipt | IMPLEMENTED |  `{ transaction(hash: &quot;0x...&quot;) { ... } }` |
| eth_getUncleByBlockHashAndIndex | IMPLEMENTED |  `{ block(hash: &quot;0x...&quot;) { ommerAt(index: x) { ... } } }` |
| eth_getUncleByBlockNumberAndIndex | IMPLEMENTED |  `{ block(number: n) { ommerAt(index: x) { ... } } }` |
| eth_getUncleCountByBlockHash | IMPLEMENTED |  `{ block(hash: &quot;0x...&quot;) { ommerCount } }` |
| eth_getUncleCountByBlockNumber | IMPLEMENTED |  `{ block(number: x) { ommerCount } }` |
| eth_protocolVersion | IMPLEMENTED | `{ protocolVersion }` |
| eth_sendRawTransaction | IMPLEMENTED | `mutation { sendRawTransaction(data: data) }` |
| eth_syncing | IMPLEMENTED | `{ syncing { ... } }` |
| eth_getCompilers | NOT IMPLEMENTED | Compiler functionality is deprecated in JSON-RPC. |
| eth_compileLLL | NOT IMPLEMENTED | Compiler functionality is deprecated in JSON-RPC. |
| eth_compileSolidity | NOT IMPLEMENTED | Compiler functionality is deprecated in JSON-RPC. |
| eth_compileSerpent | NOT IMPLEMENTED | Compiler functionality is deprecated in JSON-RPC. |
| eth_newFilter | NOT IMPLEMENTED | Filter functionality may be specified in a future EIP. |
| eth_newBlockFilter | NOT IMPLEMENTED | Filter functionality may be specified in a future EIP. |
| eth_newPendingTransactionFilter | NOT IMPLEMENTED | Filter functionality may be specified in a future EIP. |
| eth_uninstallFilter | NOT IMPLEMENTED | Filter functionality may be specified in a future EIP. |
| eth_getFilterChanges | NOT IMPLEMENTED | Filter functionality may be specified in a future EIP. |
| eth_getFilterLogs | NOT IMPLEMENTED | Filter functionality may be specified in a future EIP. |
| eth_accounts | NOT IMPLEMENTED | Accounts functionality is not part of the core node API. |
| eth_sign | NOT IMPLEMENTED | Accounts functionality is not part of the core node API. |
| eth_sendTransaction | NOT IMPLEMENTED | Accounts functionality is not part of the core node API. |
| eth_coinbase | NOT IMPLEMENTED | Mining functionality to be defined separately. |
| eth_getWork | NOT IMPLEMENTED | Mining functionality to be defined separately. |
| eth_hashRate | NOT IMPLEMENTED | Mining functionality to be defined separately. |
| eth_mining | NOT IMPLEMENTED | Mining functionality to be defined separately. |
| eth_submitHashrate | NOT IMPLEMENTED | Mining functionality to be defined separately. |
| eth_submitWork | NOT IMPLEMENTED | Mining functionality to be defined separately. |

For specific reasoning behind omitted functionality, see the Rationale section.

## Test Cases
TBD.

## Implementation

- Implemented and released in [Go-ethereum 1.9.0](https://github.com/ethereum/go-ethereum/releases/tag/v1.9.0)
- Implemented and released in [Pantheon 1.1.1](https://github.com/PegaSysEng/pantheon/blob/master/CHANGELOG.md#111)
- Work in progress in [Trinity](https://github.com/ethereum/trinity/issues/302)
- Work in progress in [Parity](https://github.com/paritytech/parity-ethereum/issues/10933)

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 14 Feb 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1767</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1767</guid>
      </item>
    
      <item>
        <title>App Keys, application specific wallet accounts</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-erc-app-keys-application-specific-wallet-accounts/2742</comments>
        
        <description>## Simple Summary

Among others cryptographic applications, scalability and privacy solutions for ethereum blockchain require that an user performs a significant amount of signing operations. It may also require her to watch some state and be ready to sign data automatically (e.g. sign a state or contest a withdraw). The way wallets currently implement accounts poses several obstacles to the development of a complete web3.0 experience both in terms of UX, security and privacy.

This proposal describes a standard and api for a new type of wallet accounts that are derived specifically for a each given application. We propose to call them `app keys`. They allow to isolate the accounts used for each application, thus potentially increasing privacy. They also allow to give more control to the applications developers over account management and signing delegation. For these app keys, wallets can have a more permissive level of security (e.g. not requesting user&apos;s confirmation) while keeping main accounts secure. Finally wallets can also implement a different behavior such as allowing to sign transactions without broadcasting them.

This new accounts type can allow to significantly improve UX and permit new designs for applications of the crypto permissionned web.

## Abstract
In a wallet, an user often holds most of her funds in her main accounts. These accounts require a significant level of security and should not be delegated in any way, this significantly impacts the design of cryptographic applications if a user has to manually confirm every action. Also often an user uses the same accounts across apps, which is a privacy and potentially also a security issue.

We introduce here a new account type, app keys, which permits signing delegation and accounts isolation across applications for privacy and security.

In this EIP, we provide a proposal on how to uniquely identify and authenticate each application, how to derive a master account (or app key) unique for the domain from an user private key (her root private key or any other private key of an account derived or not from her root one). This EIP aims at becoming a standard on how to derive keys specific to each application that can be regenerated from scratch without further input from the user if she restores her wallet and uses again the application for which this key was derived.
These app keys can then be endowed a different set of permissions (through the requestPermission model introduced in [EIP-2255](/EIPs/EIPS/eip-2255)). This will potentially allow an user to partly trust some apps to perform some crypto operations on their behalf without compromising any security with respect to her main accounts.

## Motivation
Wallets developers have agreed on an HD derivation path for ethereum accounts using BIP32, BIP44, SLIP44, [(see the discussion here)](https://github.com/ethereum/EIPs/issues/84). Web3 wallets have implemented in a roughly similar way the rpc eth api. [EIP-1102](/EIPs/EIPS/eip-1102) introduced privacy through non automatic opt-in of a wallet account into an app increasing privacy.

However several limitations remain in order to allow for proper design and UX for crypto permissioned apps.

Most of GUI based current wallets don&apos;t allow to:
* being able to automatically and effortlessly use different keys / accounts for each apps,
* being able to sign some app&apos;s action without prompting the user with the same level of security as sending funds from their main accounts,
* being able to use throwable keys to improve anonymity,
* effortlessly signing transactions for an app without broadcasting these while still being able to perform other transaction signing as usual from their main accounts,
* All this while being fully restorable using the user&apos;s mnemonic or hardware wallet and the HD Path determined uniquely by the app&apos;s ens name.

We try to overcome these limitations by introducing a new account&apos;s type, app keys, made to be used along side the existing main accounts.

These new app keys can permit to give more power and flexibility to the crypto apps developers. This can allow to improve a lot the UX of crypto dapps and to create new designs that were not possible before leveraging the ability to create and handle many accounts, to presign messages and broadcast them later. These features were not compatible with the level of security we were requesting for main accounts that hold most of an user&apos;s funds.


## Specification

### Applications

An app is a website (or other) that would like to request from a wallet to access a cryptographic key specifically derived for this usage. It can be any form of cryptography/identity relying application, Ethereum based but not only.

Once connected to a wallet, an application can request to access an account derived exclusively for that application using the following algorithm.

### Private App Key generation algorithm

We now propose an algorithm to generate application keys that:
- are uniquely defined, with respect to the account that the user selected to generate these keys,
- and thus can be isolated when changing the user account, allowing persona management (see next section),
- are specific to each application,
- can be fully restored from the user master seed mnemonic and the applications&apos; names.

#### Using different accounts as personas

We allow the user to span a different set of application keys by changing the account selected to generate each key. Thus from the same master seed mnemonic, an user can use each of her account index to generate an alternative set of application keys. One can describe this as using different personas.
This would allow potentially an user to fully isolate her interaction with a given app across personas. One can use this for instance to create a personal and business profile for a given&apos;s domain both backup up from the same mnemonic, using 2 different accounts to generate these. The app or domain, will not be aware that it is the same person and mnemonic behind both.
If an application interacts with several main accounts of an user, one of these accounts, a master account can be used as persona and the others as auxiliary accounts.

This EIP is agnostic about the way one generates the private keys used to span different app keys spaces. However for compatibility purposes and for clean disambiguation between personas and cryptocurrency accounts, a new EIP, distinct from this one but to be used alongside, will be proposed soon introducing clean persona generation and management.

#### Applications&apos; Unique Identifiers

Each application is uniquely defined and authenticated by its origin, a domain string. It can be a Domain Name Service (DNS) name or, in the future, an Ethereum Name Service (ENS) name or IPFS hash.

For Ipfs or swam origins, but we could probably use the ipfs or swarm addresses as origin or we could require those to be pointed at through an ENS entry and use the ENS address as origin, although this would mean that the content it refers to could change. It would thus allow for different security and updatibility models.

We will probably require for protocol prefixes when using an ENS domain to point to an IPFS address:
`ens://ipfs.snap.eth`


#### Private App Key generation algorithm

Using the domain name of an application, we generate a private key for each application (and per main account) :

`const appKeyPrivKey = keccak256(privKey + originString)`

where `+` is concatenation, `privKey` is the private key of the user&apos;s account selected to span the application key and `originString` represents the origin url from which the permission call to access the application key is originated from.

This is exposed as an RPC method to allow any domain to request its own app key associated with the current requested account (if available):

```
const appKey = await provider.send({
  method: &apos;wallet_getAppKeyForAccount&apos;,
  params: [address1]
});
```

See here for an implementation:
https://github.com/MetaMask/eth-simple-keyring/blob/master/index.js#L169

#### App keys and Hierarchical Deterministic keys

The app keys generated using the algorithm described in the previous section will not be BIP32 compliant. Therefore apps will not be able to create several app keys or use non-hardening and extended public keys techniques directly. They get a single private key (per origin, per persona).
Yet they can use this as initial entropy to span a new HD tree and generate addresses that can be either hardened or not. Thus we should not be losing use cases.

## Rationale

### Sharing application keys across domains:
While this does not explicit cover cases of sharing these app keys between pages on its own, this need can be met by composition:

Since a domain would get a unique key per persona, and because domains can intercommunicate, one domain (app) could request another domain (signer) to perform its cryptographic operation on some data, with its appKey as a seed, potentially allowing new signing strategies to be added as easily as new websites.

This could also pass it to domains that are loading specific signing strategies. This may sound dangerous at first, but if a domain represents a static hash of a trusted cryptographic function implementation, it could be as safe as calling any audited internal dependency.

### Privacy and the funding trail

If all an application needs to do with its keys is to sign messages and it does not require funding, then this EIP allows for privacy through the use of distinct keys for each application with a simple deterministic standard compatible across wallets.

However if these application keys require funding, there can be trail and the use of app keys would not fully solve the privacy problem there.

Mixers or anonymous ways of funding an ethereum address (ring signatures) along with this proposal would guarantee privacy.

Even if privacy is not solved fully without this anonymous funding method, we still need a way to easily create and restore different accounts/addresses for each application

## Backwards Compatibility
From a wallet point of view, there does not seem to be compatibility issues since these are separate accounts from those that were used previously by wallets and they are supposed to be used along-side in synergy.

However, for applications that associated in some way their users to their main accounts may want to reflect on if and how they would like to leverage the power offered by `app keys` to migrate to them and leverage on the new app designs they permit.

## Implementation

Here is an early implementation of app keys for standard (non HW) MetaMask accounts.
https://github.com/MetaMask/eth-simple-keyring/blob/6d12bd9d73adcccbe0b0c7e32a99d279085e2934/index.js#L139-L152

See here for a fork of MetaMask that implements app keys along side plugins:
https://github.com/MetaMask/metamask-snaps-beta
https://github.com/MetaMask/metamask-snaps-beta/wiki/Plugin-API

## Example use cases

* signing transactions without broadcasting them
https://github.com/MetaMask/metamask-extension/issues/3475

* token contract
https://github.com/ethereum/EIPs/issues/85

* default account for dapps
https://ethereum-magicians.org/t/default-accounts-for-dapps/904

* non wallet/crypto accounts
[EIP1581: Non-wallet usage of keys derived from BIP32 trees](/EIPs/EIPS/eip-1581)

* state channel application

* privacy solution

* non custodian cross cryptocurrency exchange...

## Acknowledgements
MetaMask team, Christian Lundkvist, Counterfactual team, Liam Horne, Erik Bryn, Richard Moore, Jeff Coleman.


## References

### HD and mnemonics
#### BIPs
* [BIP32: Hierarchical Deterministic Wallets:](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)

* [BIP39: Mnemonic code for generating deterministic keys:](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki)

* [SLIP44: Registered coin types for BIP44](https://github.com/satoshilabs/slips/blob/master/slip-0044.md)


#### Derivation path for eth
* [Issue 84](https://github.com/ethereum/EIPs/issues/84)

* [Issue 85](https://github.com/ethereum/EIPs/issues/85)

* [EIP600 Ethereum purpose allocation for Deterministic Wallets](/EIPs/EIPS/eip-600)


* [EIP601 Ethereum hierarchy for deterministic wallets](/EIPs/EIPS/eip-601)


### Previous proposals and discussions related to app keys
* [Meta: we should value privacy more](https://ethereum-magicians.org/t/meta-we-should-value-privacy-more/2475)

* [EIP1102: Opt-in account exposure](/EIPs/EIPS/eip-1102)

* [EIP1581: Non-wallet usage of keys derived from BIP-32 trees](/EIPs/EIPS/eip-1581)

* [EIP1581: discussion](https://ethereum-magicians.org/t/non-wallet-usage-of-keys-derived-from-bip-32-trees/1817/4)

* [SLIP13: Authentication using deterministic hierarchy](https://github.com/satoshilabs/slips/blob/master/slip-0013.md)


## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 20 Feb 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1775</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1775</guid>
      </item>
    
      <item>
        <title>Rename opcodes for clarity</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-1803-rename-opcodes-for-clarity/3345</comments>
        
        <description>## Abstract

Rename the `BALANCE`, `SHA3`, `NUMBER`, `GASLIMIT`, `GAS` and `INVALID` opcodes to reflect their true meaning.

## Specification

Rename the opcodes as follows:
- `BALANCE` (`0x31`) to `EXTBALANCE` to be in line with `EXTCODESIZE`, `EXTCODECOPY` and `EXTCODEHASH`
- `SHA3` (`0x20`) to `KECCAK256`
- `NUMBER` (`0x43`) to `BLOCKNUMBER`
- `GASLIMIT` (`0x45`) to `BLOCKGASLIMIT` to avoid confusion with the gas limit of the transaction
- `GAS` (`0x5a`) to `GASLEFT` to be clear what it refers to
- `INVALID` (`0xfe`) to `ABORT` to clearly articulate when someone refers this opcode as opposed to &quot;any invalid opcode&quot;

## Backwards Compatibility

This has no effect on any code. It can influence what mnemonics assemblers will use.

## Implementation

Not applicable.

## References

[EIP-6](/EIPs/EIPS/eip-6) previously renamed `SUICIDE` (`0xff`) to `SELFDESTRUCT`.
Renaming `SHA3` was previously proposed by [EIP-59](https://github.com/ethereum/EIPs/issues/59).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 28 Jul 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1803</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1803</guid>
      </item>
    
      <item>
        <title>Ethereum Verifiable Claims</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-1812-ethereum-verifiable-claims/2814</comments>
        
        <description># Ethereum Verifiable Claims

## Simple Summary

Reusable Verifiable Claims using [EIP 712 Signed Typed Data](/EIPs/EIPS/eip-712).

## Abstract
A new method for Off-Chain Verifiable Claims built on [EIP-712](/EIPs/EIPS/eip-712). These Claims can be issued by any user with a EIP 712 compatible web3 provider. Claims can be stored off chain and verified on-chain by Solidity Smart Contracts, State Channel Implementations or off-chain libraries.

## Motivation
Reusable Off-Chain Verifiable Claims provide an important piece of integrating smart contracts with real world organizational requirements such as meeting regulatory requirements such as KYC, GDPR, Accredited Investor rules etc.

[ERC-735](https://github.com/ethereum/EIPs/issues/735) and [ERC-780](https://github.com/ethereum/EIPs/issues/780) provide methods of making claims that live on chain. This is useful for some particular use cases, where some claim about an address must be verified on chain. 

In most cases though it is both dangerous and in some cases illegal (according to EU GDPR rules for example) to record Identity Claims containing Personal Identifying Information (PII) on an immutable public database such as the Ethereum blockchain.

The W3C [Verifiable Claims Data Model and Representations](https://www.w3.org/TR/verifiable-claims-data-model/) as well as uPorts [Verification Message Spec](https://developer.uport.me/messages/verification) are proposed off-chain solutions. 

While built on industry standards such as [JSON-LD](https://json-ld.org) and [JWT](https://jwt.io) neither of them are easy to integrate with the Ethereum ecosystem.

[EIP-712](/EIPs/EIPS/eip-712) introduces a new method of signing off chain Identity data. This provides both a data format based on Solidity ABI encoding that can easily be parsed on-chain an a new JSON-RPC call that is easily supported by existing Ethereum wallets and Web3 clients.

This format  allows reusable off-chain Verifiable Claims to be cheaply issued to users, who can present them when needed.

## Prior Art
Verified Identity Claims such as those proposed by [uPort](https://developer.uport.me/messages/verification) and [W3C Verifiable Claims Working Group](https://www.w3.org/2017/vc/WG/) form an important part of building up reusable identity claims.

[ERC-735](https://github.com/ethereum/EIPs/issues/735) and [ERC-780](https://github.com/ethereum/EIPs/issues/780) provide on-chain storage and lookups of Verifiable Claims.

## Specification
### Claims
Claims can be generalized like this:

&gt; Issuer makes the claim that Subject is something or has some attribute and value.    

Claims should be deterministic, in that the same claim signed multiple times by the same signer.

### Claims data structure
Each claim should be typed based on its specific use case, which EIP 712 lets us do effortlessly. But there are 3 minimal attributes required of the claims structure.

* `subject` the subject of the claim as an `address` (who the claim is about)
* `validFrom` the time in seconds encoded as a `uint256` of start of validity of claim. In most cases this would be the time of issuance, but some claims may be valid in the future or past.
* `validTo` the time in seconds encoded as a `uint256` of when the validity of  the claim expires. If you intend for the claim not to expire use `0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff`.

The basic minimal claim data structure as a Solidity struct:

```solidity
struct [CLAIM TYPE] {
	address subject;
	uint256 validFrom;
	uint256 validTo;
}
```

The CLAIM TYPE is the actual name of the claim. While not required, in most cases use the taxonomy developed by [schema.org](https://schema.org/docs/full.html) which is also commonly used in other Verifiable Claims formats.

Example claim that issuer knows a subject:

```solidity
struct Know {
	address subject;
	uint256 validFrom;
	uint256 validTo;
}
```

### Presenting a Verifiable Claim
#### Verifying Contract
When defining Verifiable Claims formats a Verifying Contract should be created with a public `verify()`  view function. This makes it very easy for other smart contracts to verify a claim correctly. 

It also provides a convenient interface for web3 and state channel apps to verify claims securely.

```solidity
function verifyIssuer(Know memory claim, uint8 v, bytes32 r, bytes32 s) public returns (address) {
	bytes32 digest = keccak256(
	  abi.encodePacked(
	    &quot;\x19\x01&quot;,
	    DOMAIN_SEPARATOR,
	    hash(claim)
	  )
	);
	require(
		(claim.validFrom &gt;= block.timestamp) &amp;&amp; (block.timestamp &lt; claim.validTo)
, &quot;invalid issuance timestamps&quot;);
	return ecrecover(digest, v, r, s);
}
```

#### Calling a SmartContract function
Verifiable Claims can be presented to a solidity function call as it’s struct together with the `v`, `r` and `s` signature components.

```solidity
function vouch(Know memory claim, uint8 v, bytes32 r, bytes32 s) public returns (bool) {
	address issuer = verifier.verifyIssuer(claim, v, r, s);
	require(issuer !== &apos;0x0&apos;);
	knows[issuer][claim.subject] = block.number;
	return true;
}
```

#### Embedding a Verifiable Claim in another Signed Typed Data  structure
The Claim struct should be embedded in another struct together with the `v`, `r` and `s` signature parameters.

```solidity
struct Know {
	address subject;
	uint256 validFrom;
	uint256 validTo;
}

struct VerifiableReference {
	Know delegate;
	uint8 v;
	bytes32 r;
	bytes32 s;
}

struct Introduction {
	address recipient;
	VerifiableReference issuer;
}
```

Each Verifiable Claim should be individually verified  together with the parent Signed Typed Data structure.

Verifiable Claims issued to different EIP 712 Domains can be embedded within each other.

#### State Channels
This proposal will not show how to use Eth Verifiable Claims  as part of a specific State Channel method.

Any State Channel based on EIP712 should be able to include the embeddable Verifiable Claims as part of its protocol. This could be useful for exchanging private Identity Claims between the parties for regulatory reasons, while ultimately not posting them to the blockchain on conclusion of a channel.

### Key Delegation
In most simple cases the issuer of a Claim is the signer of the data. There are cases however where signing should be delegated to an intermediary key.

KeyDelegation can be used to implement off chain signing for smart contract based addresses, server side key rotation as well as employee permissions in complex  business use cases.

#### ERC1056 Signing Delegation

[ERC-1056](/EIPs/EIPS/eip-1056) provides a method for addresses to assign delegate signers. One of the primary use cases for this is that a smart contract can allow a key pair to sign on its behalf for a certain period. It also allows server based issuance tools to institute key rotation.

To support this an additional `issuer` attribute can be added to the Claim Type struct. In this case the verification code should lookup the EthereumDIDRegistry to see if the signer of the data is an allowed signing delegate for the `issuer`

The following is the minimal struct for a Claim containing an issuer:

```solidity
struct [CLAIM TYPE] {
	address subject;
  address issuer;
	uint256 validFrom;
	uint256 validTo;
}
```

If the `issuer` is specified in the struct In addition to performing the standard ERC712 verification the verification code MUST also verify that the signing address is a valid `veriKey` delegate for the address specified in the issuer.

```solidity
registry.validDelegate(issuer, &apos;veriKey&apos;, recoveredAddress)
```


#### Embedded Delegation Proof
There may be applications, in particularly where organizations want to allow delegates to issue claims about specific domains and types.

For this purpose instead of the `issuer` we allow a special claim to be embedded following this same format:

```solidity
struct Delegate {
	address issuer;
	address subject;
	uint256 validFrom;
	uint256 validTo;
}

struct VerifiableDelegate {
	Delegate delegate;
	uint8 v;
	bytes32 r;
	bytes32 s;
}


struct [CLAIM TYPE] {
	address subject;
	VerifiedDelegate issuer;
	uint256 validFrom;
	uint256 validTo;
}
```

Delegates should be created for specific EIP 712 Domains and not be reused across Domains.

Implementers of new EIP 712 Domains can add further data to the `Delegate` struct to allow finer grained application specific rules to it.

### Claim Types
#### Binary Claims
A Binary claim is something that doesn’t have a particular value. It either is issued or not.

Examples:
* subject is a Person
* subject is my owner (eg. Linking an ethereum account to an owner identity)

Example:

```solidity
struct Person {
	address issuer;
	address subject;
	uint256 validFrom;
	uint256 validTo;
}
```

This is exactly the same as the minimal claim above with the CLAIM TYPE set to [Person](https://schema.org/Person).

### Value Claims
Value claims can be used to make a claim about the subject containing a specific readable value.

**WARNING**: Be very careful about  using Value Claims  as part of Smart Contract transactions. Identity Claims containing values could be a GDPR violation for the business or developer encouraging a user to post it to a public blockchain.

Examples:
* subject’s name is Alice
* subjects average account balance is 1234555

Each value should use the `value` field to indicate the value.

A Name Claim

```solidity
struct Name {
	address issuer;
	address subject;
	string name;
	uint256 validFrom;
	uint256 validTo;
}
```

Average Balance

```solidity
struct AverageBalance {
	address issuer;
	address subject;
	uint256 value;
	uint256 validFrom;
	uint256 validTo;
}
```

### Hashed Claims
Hashed claims can be used to make a claim about the subject containing the hash of a claim value. Hashes should use ethereum standard `keccak256` hashing function.

**WARNING**: Be very careful about  using Hashed Claims  as part of Smart Contract transactions. Identity Claims containing hashes of known values could be a GDPR violation for the business or developer encouraging a user to post it to a public blockchain.

Examples:
- [ ] hash of subject’s name is `keccak256(“Alice Torres”)`
- [ ] hash of subject’s email is `keccak256(“alice@example.com”)`

Each value should use the `keccak256 ` field to indicate the hashed value. Question. The choice of using this name  is that we can easily add support for future algorithms as well as maybe zkSnark proofs.

A Name Claim

```solidity
struct Name {
	address issuer;
	address subject;
	bytes32 keccak256;
	uint256 validFrom;
	uint256 validTo;
}
```

Email Claim

```solidity
struct Email {
	address issuer;
	address subject;
	bytes32 keccak256;
	uint256 validFrom;
	uint256 validTo;
}
```

### EIP 712 Domain
The EIP 712 Domain specifies what kind of message that is to be signed and is used to differentiate between signed data types. The content MUST contain the following:

```solidity
{
  name: &quot;EIP1???Claim&quot;,
  version: 1,
  chainId: 1, // for mainnet
  verifyingContract: 0x // TBD
  salt: ...
}
```

#### Full Combined format for EIP 712 signing:

Following the EIP 712 standard we can combine the Claim Type with the EIP 712 Domain and the claim itself (in the `message`)  attribute.

Eg:
```solidity
  {
    &quot;types&quot;: {
      &quot;EIP712Domain&quot;: [
        {
          &quot;name&quot;: &quot;name&quot;,
          &quot;type&quot;: &quot;string&quot;
        },
        {
          &quot;name&quot;: &quot;version&quot;,
          &quot;type&quot;: &quot;string&quot;
        },
        {
          &quot;name&quot;: &quot;chainId&quot;,
          &quot;type&quot;: &quot;uint256&quot;
        },
        {
          &quot;name&quot;: &quot;verifyingContract&quot;,
          &quot;type&quot;: &quot;address&quot;
        }
      ],
      &quot;Email&quot;: [
        { 
          &quot;name&quot;: &quot;subject&quot;,
          &quot;type&quot;: &quot;address&quot;
        },
        {
          &quot;name&quot;: &quot;keccak256&quot;,
          &quot;type&quot;: &quot;bytes32&quot;
        },
        {
          &quot;name&quot;: &quot;validFrom&quot;,
          &quot;type&quot;: &quot;uint256&quot;
        },
        {
          &quot;name&quot;: &quot;validTo&quot;,
          &quot;type&quot;: &quot;uint256&quot;
        }
      ]
    },
    &quot;primaryType&quot;: &quot;Email&quot;,
    &quot;domain&quot;: {
      &quot;name&quot;: &quot;EIP1??? Claim&quot;,
      &quot;version&quot;: &quot;1&quot;,
      &quot;chainId&quot;: 1,
      &quot;verifyingContract&quot;: &quot;0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC&quot;
    },
    &quot;message&quot;: {
      &quot;subject&quot;: &quot;0x5792e817336f41de1d8f54feab4bc200624a1d9d&quot;,
      &quot;value&quot;: &quot;9c8465d9ae0b0bc167dee7f62880034f59313100a638dcc86a901956ea52e280&quot;,
      &quot;validFrom&quot;: &quot;0x0000000000000000000000000000000000000000000000000001644b74c2a0&quot;,
      &quot;validTo&quot;: &quot;0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff&quot;
    }
  }
```


### Revocation
Both Issuers and Subjects should be allowed to revoke Verifiable Claims. Revocations can be handled through a simple on-chain registry. 

The ultimate rules of who should be able to revoke a claim is determined by the Verifying contract.

The `digest` used for revocation is the EIP712 Signed Typed Data digest.

```solidity
contract RevocationRegistry {
  mapping (bytes32 =&gt; mapping (address =&gt; uint)) public revocations;

  function revoke(bytes32 digest) public returns (bool) {
    revocations[digest][msg.sender] = block.number;
    return true;
  }

  function revoked(address party, bytes32 digest) public view returns (bool) {
    return revocations[digest][party] &gt; 0;
  }
}
```

A verifying contract can query the Revocation Registry as such:

```solidity
bytes32 digest = keccak256(
  abi.encodePacked(
    &quot;\x19\x01&quot;,
    DOMAIN_SEPARATOR,
    hash(claim)
  )
);
require(valid(claim.validFrom, claim.validTo), &quot;invalid issuance timestamps&quot;);
address issuer = ecrecover(digest, v, r, s);
require(!revocations.revoked(issuer, digest), &quot;claim was revoked by issuer&quot;);
require(!revocations.revoked(claim.subject, digest), &quot;claim was revoked by subject&quot;);
```

### Creation of Verifiable Claims Domains

Creating specific is Verifiable Claims Domains is out of the scope of this EIP.   The Example Code has a few examples.

EIP’s or another process could be used to standardize specific important Domains that are universally useful across the Ethereum world.

## Rationale
Signed Typed Data provides a strong foundation for Verifiable Claims that can be used in many different kinds of applications built on both Layer 1 and Layer 2 of Ethereum.

### Rationale for using not using a single EIP 712 Domain
EIP712 supports complex types and domains in itself, that we believe are perfect building blocks for building Verifiable Claims for specific purposes.

The Type and Domain of a Claim is itself an important part of a claim and ensures that Verifiable Claims are used for the specific purposes required and not misused.

EIP712 Domains also allow rapid experimentation, allowing taxonomies to be built up by the community.

## Test Cases
There is a repo with a few example verifiers and consuming smart contracts written in Solidity:

**Example Verifiers**
* [Verifier for very simple IdVerification Verifiable Claims containing minimal Personal Data](https://github.com/uport-project/eip712-claims-experiments/blob/master/contracts/IdentityClaimsVerifier.sol)
* [Verifier for OwnershipProofs signed by a users wallet](https://github.com/uport-project/eip712-claims-experiments/blob/master/contracts/OwnershipProofVerifier.sol)

**Example Smart Contracts**
* [KYCCoin.sol](https://github.com/uport-project/eip712-claims-experiments/blob/master/contracts/KYCCoin.sol) - Example Token allows reusable IdVerification claims issued by trusted verifiers and users to whitelist their own addresses using OwnershipProofs
* [ConsortiumAgreement.sol](https://github.com/uport-project/eip712-claims-experiments/blob/master/contracts/ConsortiumAgreements.sol) - Example Consortium Agreement smart contract. Consortium Members can issue Delegated Claims to employees or servers to interact on their behalf.

**Shared Registries**
* [RevocationRegistry.sol](https://github.com/uport-project/eip712-claims-experiments/blob/master/contracts/RevocationRegistry.sol)

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 03 Mar 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1812</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1812</guid>
      </item>
    
      <item>
        <title>Pseudo-introspection Registry Contract</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/pull/1820</comments>
        
        <description>&gt; :information_source: **[ERC-1820] has superseded [ERC-820].** :information_source:  
&gt; [ERC-1820] fixes the incompatibility in the [ERC-165] logic which was introduced by the Solidity 0.5 update.  
&gt; Have a look at the [official announcement][erc1820-annoucement], and the comments about the [bug][erc820-bug] and the [fix][erc820-fix].  
&gt; Apart from this fix, [ERC-1820] is functionally equivalent to [ERC-820].
&gt;
&gt; :warning: [ERC-1820] MUST be used in lieu of [ERC-820]. :warning:

## Simple Summary

This standard defines a universal registry smart contract where any address (contract or regular account) can register which interface it supports and which smart contract is responsible for its implementation.

This standard keeps backward compatibility with [ERC-165].

## Abstract

This standard defines a registry where smart contracts and regular accounts can publish which functionality they implement---either directly or through a proxy contract.

Anyone can query this registry to ask if a specific address implements a given interface and which smart contract handles its implementation.

This registry MAY be deployed on any chain and shares the same address on all chains.

Interfaces with zeroes (`0`) as the last 28 bytes are considered [ERC-165] interfaces,
and this registry SHALL forward the call to the contract to see if it implements the interface.

This contract also acts as an [ERC-165] cache to reduce gas consumption.

## Motivation

There have been different approaches to define pseudo-introspection in Ethereum.
The first is [ERC-165] which has the limitation that it cannot be used by regular accounts.
The second attempt is [ERC-672] which uses reverse [ENS]. Using reverse [ENS] has two issues. 
First, it is unnecessarily complicated, and second, [ENS] is still a centralized contract controlled by a multisig.
This multisig theoretically would be able to modify the system.

This standard is much simpler than [ERC-672], and it is *fully* decentralized.

This standard also provides a *unique* address for all chains.
Thus solving the problem of resolving the correct registry address for different chains.

## Specification

### [ERC-1820] Registry Smart Contract

&gt; This is an exact copy of the code of the [ERC1820 registry smart contract].

``` solidity
/* ERC1820 Pseudo-introspection Registry Contract
 * This standard defines a universal registry smart contract where any address (contract or regular account) can
 * register which interface it supports and which smart contract is responsible for its implementation.
 *
 * Written in 2019 by Jordi Baylina and Jacques Dafflon
 *
 * To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to
 * this software to the public domain worldwide. This software is distributed without any warranty.
 *
 * You should have received a copy of the CC0 Public Domain Dedication along with this software. If not, see
 * &lt;http://creativecommons.org/publicdomain/zero/1.0/&gt;.
 *
 *    ███████╗██████╗  ██████╗ ██╗ █████╗ ██████╗  ██████╗
 *    ██╔════╝██╔══██╗██╔════╝███║██╔══██╗╚════██╗██╔═████╗
 *    █████╗  ██████╔╝██║     ╚██║╚█████╔╝ █████╔╝██║██╔██║
 *    ██╔══╝  ██╔══██╗██║      ██║██╔══██╗██╔═══╝ ████╔╝██║
 *    ███████╗██║  ██║╚██████╗ ██║╚█████╔╝███████╗╚██████╔╝
 *    ╚══════╝╚═╝  ╚═╝ ╚═════╝ ╚═╝ ╚════╝ ╚══════╝ ╚═════╝
 *
 *    ██████╗ ███████╗ ██████╗ ██╗███████╗████████╗██████╗ ██╗   ██╗
 *    ██╔══██╗██╔════╝██╔════╝ ██║██╔════╝╚══██╔══╝██╔══██╗╚██╗ ██╔╝
 *    ██████╔╝█████╗  ██║  ███╗██║███████╗   ██║   ██████╔╝ ╚████╔╝
 *    ██╔══██╗██╔══╝  ██║   ██║██║╚════██║   ██║   ██╔══██╗  ╚██╔╝
 *    ██║  ██║███████╗╚██████╔╝██║███████║   ██║   ██║  ██║   ██║
 *    ╚═╝  ╚═╝╚══════╝ ╚═════╝ ╚═╝╚══════╝   ╚═╝   ╚═╝  ╚═╝   ╚═╝
 *
 */
pragma solidity 0.5.3;
// IV is value needed to have a vanity address starting with &apos;0x1820&apos;.
// IV: 53759

/// @dev The interface a contract MUST implement if it is the implementer of
/// some (other) interface for any address other than itself.
interface ERC1820ImplementerInterface {
    /// @notice Indicates whether the contract implements the interface &apos;interfaceHash&apos; for the address &apos;addr&apos; or not.
    /// @param interfaceHash keccak256 hash of the name of the interface
    /// @param addr Address for which the contract will implement the interface
    /// @return ERC1820_ACCEPT_MAGIC only if the contract implements &apos;interfaceHash&apos; for the address &apos;addr&apos;.
    function canImplementInterfaceForAddress(bytes32 interfaceHash, address addr) external view returns(bytes32);
}


/// @title ERC1820 Pseudo-introspection Registry Contract
/// @author Jordi Baylina and Jacques Dafflon
/// @notice This contract is the official implementation of the ERC1820 Registry.
/// @notice For more details, see https://eips.ethereum.org/EIPS/eip-1820
contract ERC1820Registry {
    /// @notice ERC165 Invalid ID.
    bytes4 constant internal INVALID_ID = 0xffffffff;
    /// @notice Method ID for the ERC165 supportsInterface method (= `bytes4(keccak256(&apos;supportsInterface(bytes4)&apos;))`).
    bytes4 constant internal ERC165ID = 0x01ffc9a7;
    /// @notice Magic value which is returned if a contract implements an interface on behalf of some other address.
    bytes32 constant internal ERC1820_ACCEPT_MAGIC = keccak256(abi.encodePacked(&quot;ERC1820_ACCEPT_MAGIC&quot;));

    /// @notice mapping from addresses and interface hashes to their implementers.
    mapping(address =&gt; mapping(bytes32 =&gt; address)) internal interfaces;
    /// @notice mapping from addresses to their manager.
    mapping(address =&gt; address) internal managers;
    /// @notice flag for each address and erc165 interface to indicate if it is cached.
    mapping(address =&gt; mapping(bytes4 =&gt; bool)) internal erc165Cached;

    /// @notice Indicates a contract is the &apos;implementer&apos; of &apos;interfaceHash&apos; for &apos;addr&apos;.
    event InterfaceImplementerSet(address indexed addr, bytes32 indexed interfaceHash, address indexed implementer);
    /// @notice Indicates &apos;newManager&apos; is the address of the new manager for &apos;addr&apos;.
    event ManagerChanged(address indexed addr, address indexed newManager);

    /// @notice Query if an address implements an interface and through which contract.
    /// @param _addr Address being queried for the implementer of an interface.
    /// (If &apos;_addr&apos; is the zero address then &apos;msg.sender&apos; is assumed.)
    /// @param _interfaceHash Keccak256 hash of the name of the interface as a string.
    /// E.g., &apos;web3.utils.keccak256(&quot;ERC777TokensRecipient&quot;)&apos; for the &apos;ERC777TokensRecipient&apos; interface.
    /// @return The address of the contract which implements the interface &apos;_interfaceHash&apos; for &apos;_addr&apos;
    /// or &apos;0&apos; if &apos;_addr&apos; did not register an implementer for this interface.
    function getInterfaceImplementer(address _addr, bytes32 _interfaceHash) external view returns (address) {
        address addr = _addr == address(0) ? msg.sender : _addr;
        if (isERC165Interface(_interfaceHash)) {
            bytes4 erc165InterfaceHash = bytes4(_interfaceHash);
            return implementsERC165Interface(addr, erc165InterfaceHash) ? addr : address(0);
        }
        return interfaces[addr][_interfaceHash];
    }

    /// @notice Sets the contract which implements a specific interface for an address.
    /// Only the manager defined for that address can set it.
    /// (Each address is the manager for itself until it sets a new manager.)
    /// @param _addr Address for which to set the interface.
    /// (If &apos;_addr&apos; is the zero address then &apos;msg.sender&apos; is assumed.)
    /// @param _interfaceHash Keccak256 hash of the name of the interface as a string.
    /// E.g., &apos;web3.utils.keccak256(&quot;ERC777TokensRecipient&quot;)&apos; for the &apos;ERC777TokensRecipient&apos; interface.
    /// @param _implementer Contract address implementing &apos;_interfaceHash&apos; for &apos;_addr&apos;.
    function setInterfaceImplementer(address _addr, bytes32 _interfaceHash, address _implementer) external {
        address addr = _addr == address(0) ? msg.sender : _addr;
        require(getManager(addr) == msg.sender, &quot;Not the manager&quot;);

        require(!isERC165Interface(_interfaceHash), &quot;Must not be an ERC165 hash&quot;);
        if (_implementer != address(0) &amp;&amp; _implementer != msg.sender) {
            require(
                ERC1820ImplementerInterface(_implementer)
                    .canImplementInterfaceForAddress(_interfaceHash, addr) == ERC1820_ACCEPT_MAGIC,
                &quot;Does not implement the interface&quot;
            );
        }
        interfaces[addr][_interfaceHash] = _implementer;
        emit InterfaceImplementerSet(addr, _interfaceHash, _implementer);
    }

    /// @notice Sets &apos;_newManager&apos; as manager for &apos;_addr&apos;.
    /// The new manager will be able to call &apos;setInterfaceImplementer&apos; for &apos;_addr&apos;.
    /// @param _addr Address for which to set the new manager.
    /// @param _newManager Address of the new manager for &apos;addr&apos;. (Pass &apos;0x0&apos; to reset the manager to &apos;_addr&apos;.)
    function setManager(address _addr, address _newManager) external {
        require(getManager(_addr) == msg.sender, &quot;Not the manager&quot;);
        managers[_addr] = _newManager == _addr ? address(0) : _newManager;
        emit ManagerChanged(_addr, _newManager);
    }

    /// @notice Get the manager of an address.
    /// @param _addr Address for which to return the manager.
    /// @return Address of the manager for a given address.
    function getManager(address _addr) public view returns(address) {
        // By default the manager of an address is the same address
        if (managers[_addr] == address(0)) {
            return _addr;
        } else {
            return managers[_addr];
        }
    }

    /// @notice Compute the keccak256 hash of an interface given its name.
    /// @param _interfaceName Name of the interface.
    /// @return The keccak256 hash of an interface name.
    function interfaceHash(string calldata _interfaceName) external pure returns(bytes32) {
        return keccak256(abi.encodePacked(_interfaceName));
    }

    /* --- ERC165 Related Functions --- */
    /* --- Developed in collaboration with William Entriken. --- */

    /// @notice Updates the cache with whether the contract implements an ERC165 interface or not.
    /// @param _contract Address of the contract for which to update the cache.
    /// @param _interfaceId ERC165 interface for which to update the cache.
    function updateERC165Cache(address _contract, bytes4 _interfaceId) external {
        interfaces[_contract][_interfaceId] = implementsERC165InterfaceNoCache(
            _contract, _interfaceId) ? _contract : address(0);
        erc165Cached[_contract][_interfaceId] = true;
    }

    /// @notice Checks whether a contract implements an ERC165 interface or not.
    //  If the result is not cached a direct lookup on the contract address is performed.
    //  If the result is not cached or the cached value is out-of-date, the cache MUST be updated manually by calling
    //  &apos;updateERC165Cache&apos; with the contract address.
    /// @param _contract Address of the contract to check.
    /// @param _interfaceId ERC165 interface to check.
    /// @return True if &apos;_contract&apos; implements &apos;_interfaceId&apos;, false otherwise.
    function implementsERC165Interface(address _contract, bytes4 _interfaceId) public view returns (bool) {
        if (!erc165Cached[_contract][_interfaceId]) {
            return implementsERC165InterfaceNoCache(_contract, _interfaceId);
        }
        return interfaces[_contract][_interfaceId] == _contract;
    }

    /// @notice Checks whether a contract implements an ERC165 interface or not without using nor updating the cache.
    /// @param _contract Address of the contract to check.
    /// @param _interfaceId ERC165 interface to check.
    /// @return True if &apos;_contract&apos; implements &apos;_interfaceId&apos;, false otherwise.
    function implementsERC165InterfaceNoCache(address _contract, bytes4 _interfaceId) public view returns (bool) {
        uint256 success;
        uint256 result;

        (success, result) = noThrowCall(_contract, ERC165ID);
        if (success == 0 || result == 0) {
            return false;
        }

        (success, result) = noThrowCall(_contract, INVALID_ID);
        if (success == 0 || result != 0) {
            return false;
        }

        (success, result) = noThrowCall(_contract, _interfaceId);
        if (success == 1 &amp;&amp; result == 1) {
            return true;
        }
        return false;
    }

    /// @notice Checks whether the hash is a ERC165 interface (ending with 28 zeroes) or not.
    /// @param _interfaceHash The hash to check.
    /// @return True if &apos;_interfaceHash&apos; is an ERC165 interface (ending with 28 zeroes), false otherwise.
    function isERC165Interface(bytes32 _interfaceHash) internal pure returns (bool) {
        return _interfaceHash &amp; 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0;
    }

    /// @dev Make a call on a contract without throwing if the function does not exist.
    function noThrowCall(address _contract, bytes4 _interfaceId)
        internal view returns (uint256 success, uint256 result)
    {
        bytes4 erc165ID = ERC165ID;

        assembly {
            let x := mload(0x40)               // Find empty storage location using &quot;free memory pointer&quot;
            mstore(x, erc165ID)                // Place signature at beginning of empty storage
            mstore(add(x, 0x04), _interfaceId) // Place first argument directly next to signature

            success := staticcall(
                30000,                         // 30k gas
                _contract,                     // To addr
                x,                             // Inputs are stored at location x
                0x24,                          // Inputs are 36 (4 + 32) bytes long
                x,                             // Store output over input (saves space)
                0x20                           // Outputs are 32 bytes long
            )

            result := mload(x)                 // Load the result
        }
    }
}

```

### Deployment Transaction

Below is the raw transaction which MUST be used to deploy the smart contract on any chain.

```
0xf90a388085174876e800830c35008080b909e5608060405234801561001057600080fd5b506109c5806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a5576000357c010000000000000000000000000000000000000000000000000000000090048063a41e7d5111610078578063a41e7d51146101d4578063aabbb8ca1461020a578063b705676514610236578063f712f3e814610280576100a5565b806329965a1d146100aa5780633d584063146100e25780635df8122f1461012457806365ba36c114610152575b600080fd5b6100e0600480360360608110156100c057600080fd5b50600160a060020a038135811691602081013591604090910135166102b6565b005b610108600480360360208110156100f857600080fd5b5035600160a060020a0316610570565b60408051600160a060020a039092168252519081900360200190f35b6100e06004803603604081101561013a57600080fd5b50600160a060020a03813581169160200135166105bc565b6101c26004803603602081101561016857600080fd5b81019060208101813564010000000081111561018357600080fd5b82018360208201111561019557600080fd5b803590602001918460018302840111640100000000831117156101b757600080fd5b5090925090506106b3565b60408051918252519081900360200190f35b6100e0600480360360408110156101ea57600080fd5b508035600160a060020a03169060200135600160e060020a0319166106ee565b6101086004803603604081101561022057600080fd5b50600160a060020a038135169060200135610778565b61026c6004803603604081101561024c57600080fd5b508035600160a060020a03169060200135600160e060020a0319166107ef565b604080519115158252519081900360200190f35b61026c6004803603604081101561029657600080fd5b508035600160a060020a03169060200135600160e060020a0319166108aa565b6000600160a060020a038416156102cd57836102cf565b335b9050336102db82610570565b600160a060020a031614610339576040805160e560020a62461bcd02815260206004820152600f60248201527f4e6f7420746865206d616e616765720000000000000000000000000000000000604482015290519081900360640190fd5b6103428361092a565b15610397576040805160e560020a62461bcd02815260206004820152601a60248201527f4d757374206e6f7420626520616e204552433136352068617368000000000000604482015290519081900360640190fd5b600160a060020a038216158015906103b85750600160a060020a0382163314155b156104ff5760405160200180807f455243313832305f4143434550545f4d4147494300000000000000000000000081525060140190506040516020818303038152906040528051906020012082600160a060020a031663249cb3fa85846040518363ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018083815260200182600160a060020a0316600160a060020a031681526020019250505060206040518083038186803b15801561047e57600080fd5b505afa158015610492573d6000803e3d6000fd5b505050506040513d60208110156104a857600080fd5b5051146104ff576040805160e560020a62461bcd02815260206004820181905260248201527f446f6573206e6f7420696d706c656d656e742074686520696e74657266616365604482015290519081900360640190fd5b600160a060020a03818116600081815260208181526040808320888452909152808220805473ffffffffffffffffffffffffffffffffffffffff19169487169485179055518692917f93baa6efbd2244243bfee6ce4cfdd1d04fc4c0e9a786abd3a41313bd352db15391a450505050565b600160a060020a03818116600090815260016020526040812054909116151561059a5750806105b7565b50600160a060020a03808216600090815260016020526040902054165b919050565b336105c683610570565b600160a060020a031614610624576040805160e560020a62461bcd02815260206004820152600f60248201527f4e6f7420746865206d616e616765720000000000000000000000000000000000604482015290519081900360640190fd5b81600160a060020a031681600160a060020a0316146106435780610646565b60005b600160a060020a03838116600081815260016020526040808220805473ffffffffffffffffffffffffffffffffffffffff19169585169590951790945592519184169290917f605c2dbf762e5f7d60a546d42e7205dcb1b011ebc62a61736a57c9089d3a43509190a35050565b600082826040516020018083838082843780830192505050925050506040516020818303038152906040528051906020012090505b92915050565b6106f882826107ef565b610703576000610705565b815b600160a060020a03928316600081815260208181526040808320600160e060020a031996909616808452958252808320805473ffffffffffffffffffffffffffffffffffffffff19169590971694909417909555908152600284528181209281529190925220805460ff19166001179055565b600080600160a060020a038416156107905783610792565b335b905061079d8361092a565b156107c357826107ad82826108aa565b6107b85760006107ba565b815b925050506106e8565b600160a060020a0390811660009081526020818152604080832086845290915290205416905092915050565b6000808061081d857f01ffc9a70000000000000000000000000000000000000000000000000000000061094c565b909250905081158061082d575080155b1561083d576000925050506106e8565b61084f85600160e060020a031961094c565b909250905081158061086057508015155b15610870576000925050506106e8565b61087a858561094c565b909250905060018214801561088f5750806001145b1561089f576001925050506106e8565b506000949350505050565b600160a060020a0382166000908152600260209081526040808320600160e060020a03198516845290915281205460ff1615156108f2576108eb83836107ef565b90506106e8565b50600160a060020a03808316600081815260208181526040808320600160e060020a0319871684529091529020549091161492915050565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff161590565b6040517f01ffc9a7000000000000000000000000000000000000000000000000000000008082526004820183905260009182919060208160248189617530fa90519096909550935050505056fea165627a7a72305820377f4a2d4301ede9949f163f319021a6e9c687c292a5e2b2c4734c126b524e6c00291ba01820182018201820182018201820182018201820182018201820182018201820a01820182018201820182018201820182018201820182018201820182018201820
```

The strings of `1820`&apos;s at the end of the transaction are the `r` and `s` of the signature.
From this deterministic pattern (generated by a human), anyone can deduce that no one knows the private key for the deployment account.

### Deployment Method

This contract is going to be deployed using the keyless deployment method---also known as [Nick]&apos;s method---which relies on a single-use address.
(See [Nick&apos;s article] for more details). This method works as follows:

1. Generate a transaction which deploys the contract from a new random account.
  - This transaction MUST NOT use [EIP-155] in order to work on any chain.
  - This transaction MUST have a relatively high gas price to be deployed on any chain. In this case, it is going to be 100 Gwei.

2. Set the `v`, `r`, `s` of the transaction signature to the following values:

   ```
   v: 27,
   r: 0x1820182018201820182018201820182018201820182018201820182018201820&apos;
   s: 0x1820182018201820182018201820182018201820182018201820182018201820&apos;
   ```

   Those `r` and `s` values---made of a repeating pattern of `1820`&apos;s---are predictable &quot;random numbers&quot; generated deterministically by a human.

3. We recover the sender of this transaction, i.e., the single-use deployment account.

    &gt; Thus we obtain an account that can broadcast that transaction, but we also have the warranty that nobody knows the private key of that account.

4. Send exactly 0.08 ether to this single-use deployment account.

5. Broadcast the deployment transaction.

This operation can be done on any chain, guaranteeing that the contract address is always the same and nobody can use that address with a different contract.


### Single-use Registry Deployment Account

```
0xa990077c3205cbDf861e17Fa532eeB069cE9fF96
```

This account is generated by reverse engineering it from its signature for the transaction. 
This way no one knows the private key, but it is known that it is the valid signer of the deployment transaction.

&gt; To deploy the registry, 0.08 ether MUST be sent to this account *first*.

### Registry Contract Address

```
0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24
```

The contract has the address above for every chain on which it is deployed.

&lt;details&gt;
&lt;summary&gt;Raw metadata of &lt;code&gt;./contracts/ERC1820Registry.sol&lt;/code&gt;&lt;/summary&gt;

```json
{
        &quot;compiler&quot;: {
          &quot;version&quot;: &quot;0.5.3+commit.10d17f24&quot;
        },
        &quot;language&quot;: &quot;Solidity&quot;,
        &quot;output&quot;: {
          &quot;abi&quot;: [
            {
              &quot;constant&quot;: false,
              &quot;inputs&quot;: [
                {
                  &quot;name&quot;: &quot;_addr&quot;,
                  &quot;type&quot;: &quot;address&quot;
                },
                {
                  &quot;name&quot;: &quot;_interfaceHash&quot;,
                  &quot;type&quot;: &quot;bytes32&quot;
                },
                {
                  &quot;name&quot;: &quot;_implementer&quot;,
                  &quot;type&quot;: &quot;address&quot;
                }
              ],
              &quot;name&quot;: &quot;setInterfaceImplementer&quot;,
              &quot;outputs&quot;: [],
              &quot;payable&quot;: false,
              &quot;stateMutability&quot;: &quot;nonpayable&quot;,
              &quot;type&quot;: &quot;function&quot;
            },
            {
              &quot;constant&quot;: true,
              &quot;inputs&quot;: [
                {
                  &quot;name&quot;: &quot;_addr&quot;,
                  &quot;type&quot;: &quot;address&quot;
                }
              ],
              &quot;name&quot;: &quot;getManager&quot;,
              &quot;outputs&quot;: [
                {
                  &quot;name&quot;: &quot;&quot;,
                  &quot;type&quot;: &quot;address&quot;
                }
              ],
              &quot;payable&quot;: false,
              &quot;stateMutability&quot;: &quot;view&quot;,
              &quot;type&quot;: &quot;function&quot;
            },
            {
              &quot;constant&quot;: false,
              &quot;inputs&quot;: [
                {
                  &quot;name&quot;: &quot;_addr&quot;,
                  &quot;type&quot;: &quot;address&quot;
                },
                {
                  &quot;name&quot;: &quot;_newManager&quot;,
                  &quot;type&quot;: &quot;address&quot;
                }
              ],
              &quot;name&quot;: &quot;setManager&quot;,
              &quot;outputs&quot;: [],
              &quot;payable&quot;: false,
              &quot;stateMutability&quot;: &quot;nonpayable&quot;,
              &quot;type&quot;: &quot;function&quot;
            },
            {
              &quot;constant&quot;: true,
              &quot;inputs&quot;: [
                {
                  &quot;name&quot;: &quot;_interfaceName&quot;,
                  &quot;type&quot;: &quot;string&quot;
                }
              ],
              &quot;name&quot;: &quot;interfaceHash&quot;,
              &quot;outputs&quot;: [
                {
                  &quot;name&quot;: &quot;&quot;,
                  &quot;type&quot;: &quot;bytes32&quot;
                }
              ],
              &quot;payable&quot;: false,
              &quot;stateMutability&quot;: &quot;pure&quot;,
              &quot;type&quot;: &quot;function&quot;
            },
            {
              &quot;constant&quot;: false,
              &quot;inputs&quot;: [
                {
                  &quot;name&quot;: &quot;_contract&quot;,
                  &quot;type&quot;: &quot;address&quot;
                },
                {
                  &quot;name&quot;: &quot;_interfaceId&quot;,
                  &quot;type&quot;: &quot;bytes4&quot;
                }
              ],
              &quot;name&quot;: &quot;updateERC165Cache&quot;,
              &quot;outputs&quot;: [],
              &quot;payable&quot;: false,
              &quot;stateMutability&quot;: &quot;nonpayable&quot;,
              &quot;type&quot;: &quot;function&quot;
            },
            {
              &quot;constant&quot;: true,
              &quot;inputs&quot;: [
                {
                  &quot;name&quot;: &quot;_addr&quot;,
                  &quot;type&quot;: &quot;address&quot;
                },
                {
                  &quot;name&quot;: &quot;_interfaceHash&quot;,
                  &quot;type&quot;: &quot;bytes32&quot;
                }
              ],
              &quot;name&quot;: &quot;getInterfaceImplementer&quot;,
              &quot;outputs&quot;: [
                {
                  &quot;name&quot;: &quot;&quot;,
                  &quot;type&quot;: &quot;address&quot;
                }
              ],
              &quot;payable&quot;: false,
              &quot;stateMutability&quot;: &quot;view&quot;,
              &quot;type&quot;: &quot;function&quot;
            },
            {
              &quot;constant&quot;: true,
              &quot;inputs&quot;: [
                {
                  &quot;name&quot;: &quot;_contract&quot;,
                  &quot;type&quot;: &quot;address&quot;
                },
                {
                  &quot;name&quot;: &quot;_interfaceId&quot;,
                  &quot;type&quot;: &quot;bytes4&quot;
                }
              ],
              &quot;name&quot;: &quot;implementsERC165InterfaceNoCache&quot;,
              &quot;outputs&quot;: [
                {
                  &quot;name&quot;: &quot;&quot;,
                  &quot;type&quot;: &quot;bool&quot;
                }
              ],
              &quot;payable&quot;: false,
              &quot;stateMutability&quot;: &quot;view&quot;,
              &quot;type&quot;: &quot;function&quot;
            },
            {
              &quot;constant&quot;: true,
              &quot;inputs&quot;: [
                {
                  &quot;name&quot;: &quot;_contract&quot;,
                  &quot;type&quot;: &quot;address&quot;
                },
                {
                  &quot;name&quot;: &quot;_interfaceId&quot;,
                  &quot;type&quot;: &quot;bytes4&quot;
                }
              ],
              &quot;name&quot;: &quot;implementsERC165Interface&quot;,
              &quot;outputs&quot;: [
                {
                  &quot;name&quot;: &quot;&quot;,
                  &quot;type&quot;: &quot;bool&quot;
                }
              ],
              &quot;payable&quot;: false,
              &quot;stateMutability&quot;: &quot;view&quot;,
              &quot;type&quot;: &quot;function&quot;
            },
            {
              &quot;anonymous&quot;: false,
              &quot;inputs&quot;: [
                {
                  &quot;indexed&quot;: true,
                  &quot;name&quot;: &quot;addr&quot;,
                  &quot;type&quot;: &quot;address&quot;
                },
                {
                  &quot;indexed&quot;: true,
                  &quot;name&quot;: &quot;interfaceHash&quot;,
                  &quot;type&quot;: &quot;bytes32&quot;
                },
                {
                  &quot;indexed&quot;: true,
                  &quot;name&quot;: &quot;implementer&quot;,
                  &quot;type&quot;: &quot;address&quot;
                }
              ],
              &quot;name&quot;: &quot;InterfaceImplementerSet&quot;,
              &quot;type&quot;: &quot;event&quot;
            },
            {
              &quot;anonymous&quot;: false,
              &quot;inputs&quot;: [
                {
                  &quot;indexed&quot;: true,
                  &quot;name&quot;: &quot;addr&quot;,
                  &quot;type&quot;: &quot;address&quot;
                },
                {
                  &quot;indexed&quot;: true,
                  &quot;name&quot;: &quot;newManager&quot;,
                  &quot;type&quot;: &quot;address&quot;
                }
              ],
              &quot;name&quot;: &quot;ManagerChanged&quot;,
              &quot;type&quot;: &quot;event&quot;
            }
          ],
          &quot;devdoc&quot;: {
            &quot;author&quot;: &quot;Jordi Baylina and Jacques Dafflon&quot;,
            &quot;methods&quot;: {
              &quot;getInterfaceImplementer(address,bytes32)&quot;: {
                &quot;params&quot;: {
                  &quot;_addr&quot;: &quot;Address being queried for the implementer of an interface. (If &apos;_addr&apos; is the zero address then &apos;msg.sender&apos; is assumed.)&quot;,
                  &quot;_interfaceHash&quot;: &quot;Keccak256 hash of the name of the interface as a string. E.g., &apos;web3.utils.keccak256(\&quot;ERC777TokensRecipient\&quot;)&apos; for the &apos;ERC777TokensRecipient&apos; interface.&quot;
                },
                &quot;return&quot;: &quot;The address of the contract which implements the interface &apos;_interfaceHash&apos; for &apos;_addr&apos; or &apos;0&apos; if &apos;_addr&apos; did not register an implementer for this interface.&quot;
              },
              &quot;getManager(address)&quot;: {
                &quot;params&quot;: {
                  &quot;_addr&quot;: &quot;Address for which to return the manager.&quot;
                },
                &quot;return&quot;: &quot;Address of the manager for a given address.&quot;
              },
              &quot;implementsERC165Interface(address,bytes4)&quot;: {
                &quot;params&quot;: {
                  &quot;_contract&quot;: &quot;Address of the contract to check.&quot;,
                  &quot;_interfaceId&quot;: &quot;ERC165 interface to check.&quot;
                },
                &quot;return&quot;: &quot;True if &apos;_contract&apos; implements &apos;_interfaceId&apos;, false otherwise.&quot;
              },
              &quot;implementsERC165InterfaceNoCache(address,bytes4)&quot;: {
                &quot;params&quot;: {
                  &quot;_contract&quot;: &quot;Address of the contract to check.&quot;,
                  &quot;_interfaceId&quot;: &quot;ERC165 interface to check.&quot;
                },
                &quot;return&quot;: &quot;True if &apos;_contract&apos; implements &apos;_interfaceId&apos;, false otherwise.&quot;
              },
              &quot;interfaceHash(string)&quot;: {
                &quot;params&quot;: {
                  &quot;_interfaceName&quot;: &quot;Name of the interface.&quot;
                },
                &quot;return&quot;: &quot;The keccak256 hash of an interface name.&quot;
              },
              &quot;setInterfaceImplementer(address,bytes32,address)&quot;: {
                &quot;params&quot;: {
                  &quot;_addr&quot;: &quot;Address for which to set the interface. (If &apos;_addr&apos; is the zero address then &apos;msg.sender&apos; is assumed.)&quot;,
                  &quot;_implementer&quot;: &quot;Contract address implementing &apos;_interfaceHash&apos; for &apos;_addr&apos;.&quot;,
                  &quot;_interfaceHash&quot;: &quot;Keccak256 hash of the name of the interface as a string. E.g., &apos;web3.utils.keccak256(\&quot;ERC777TokensRecipient\&quot;)&apos; for the &apos;ERC777TokensRecipient&apos; interface.&quot;
                }
              },
              &quot;setManager(address,address)&quot;: {
                &quot;params&quot;: {
                  &quot;_addr&quot;: &quot;Address for which to set the new manager.&quot;,
                  &quot;_newManager&quot;: &quot;Address of the new manager for &apos;addr&apos;. (Pass &apos;0x0&apos; to reset the manager to &apos;_addr&apos;.)&quot;
                }
              },
              &quot;updateERC165Cache(address,bytes4)&quot;: {
                &quot;params&quot;: {
                  &quot;_contract&quot;: &quot;Address of the contract for which to update the cache.&quot;,
                  &quot;_interfaceId&quot;: &quot;ERC165 interface for which to update the cache.&quot;
                }
              }
            },
            &quot;title&quot;: &quot;ERC1820 Pseudo-introspection Registry Contract&quot;
          },
          &quot;userdoc&quot;: {
            &quot;methods&quot;: {
              &quot;getInterfaceImplementer(address,bytes32)&quot;: {
                &quot;notice&quot;: &quot;Query if an address implements an interface and through which contract.&quot;
              },
              &quot;getManager(address)&quot;: {
                &quot;notice&quot;: &quot;Get the manager of an address.&quot;
              },
              &quot;implementsERC165InterfaceNoCache(address,bytes4)&quot;: {
                &quot;notice&quot;: &quot;Checks whether a contract implements an ERC165 interface or not without using nor updating the cache.&quot;
              },
              &quot;interfaceHash(string)&quot;: {
                &quot;notice&quot;: &quot;Compute the keccak256 hash of an interface given its name.&quot;
              },
              &quot;setInterfaceImplementer(address,bytes32,address)&quot;: {
                &quot;notice&quot;: &quot;Sets the contract which implements a specific interface for an address. Only the manager defined for that address can set it. (Each address is the manager for itself until it sets a new manager.)&quot;
              },
              &quot;setManager(address,address)&quot;: {
                &quot;notice&quot;: &quot;Sets &apos;_newManager&apos; as manager for &apos;_addr&apos;. The new manager will be able to call &apos;setInterfaceImplementer&apos; for &apos;_addr&apos;.&quot;
              },
              &quot;updateERC165Cache(address,bytes4)&quot;: {
                &quot;notice&quot;: &quot;Updates the cache with whether the contract implements an ERC165 interface or not.&quot;
              }
            },
            &quot;notice&quot;: &quot;This contract is the official implementation of the ERC1820 Registry.For more details, see https://eips.ethereum.org/EIPS/eip-1820&quot;
          }
        },
        &quot;settings&quot;: {
          &quot;compilationTarget&quot;: {
            &quot;./contracts/ERC1820Registry.sol&quot;: &quot;ERC1820Registry&quot;
          },
          &quot;evmVersion&quot;: &quot;byzantium&quot;,
          &quot;libraries&quot;: {},
          &quot;optimizer&quot;: {
            &quot;enabled&quot;: true,
            &quot;runs&quot;: 200
          },
          &quot;remappings&quot;: []
        },
        &quot;sources&quot;: {
          &quot;./contracts/ERC1820Registry.sol&quot;: {
            &quot;content&quot;: &quot;/* ERC1820 Pseudo-introspection Registry Contract\n * This standard defines a universal registry smart contract where any address (contract or regular account) can\n * register which interface it supports and which smart contract is responsible for its implementation.\n *\n * Written in 2019 by Jordi Baylina and Jacques Dafflon\n *\n * To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to\n * this software to the public domain worldwide. This software is distributed without any warranty.\n *\n * You should have received a copy of the CC0 Public Domain Dedication along with this software. If not, see\n * &lt;http://creativecommons.org/publicdomain/zero/1.0/&gt;.\n *\n *    ███████╗██████╗  ██████╗ ██╗ █████╗ ██████╗  ██████╗\n *    ██╔════╝██╔══██╗██╔════╝███║██╔══██╗╚════██╗██╔═████╗\n *    █████╗  ██████╔╝██║     ╚██║╚█████╔╝ █████╔╝██║██╔██║\n *    ██╔══╝  ██╔══██╗██║      ██║██╔══██╗██╔═══╝ ████╔╝██║\n *    ███████╗██║  ██║╚██████╗ ██║╚█████╔╝███████╗╚██████╔╝\n *    ╚══════╝╚═╝  ╚═╝ ╚═════╝ ╚═╝ ╚════╝ ╚══════╝ ╚═════╝\n *\n *    ██████╗ ███████╗ ██████╗ ██╗███████╗████████╗██████╗ ██╗   ██╗\n *    ██╔══██╗██╔════╝██╔════╝ ██║██╔════╝╚══██╔══╝██╔══██╗╚██╗ ██╔╝\n *    ██████╔╝█████╗  ██║  ███╗██║███████╗   ██║   ██████╔╝ ╚████╔╝\n *    ██╔══██╗██╔══╝  ██║   ██║██║╚════██║   ██║   ██╔══██╗  ╚██╔╝\n *    ██║  ██║███████╗╚██████╔╝██║███████║   ██║   ██║  ██║   ██║\n *    ╚═╝  ╚═╝╚══════╝ ╚═════╝ ╚═╝╚══════╝   ╚═╝   ╚═╝  ╚═╝   ╚═╝\n *\n */\npragma solidity 0.5.3;\n// IV is value needed to have a vanity address starting with &apos;0x1820&apos;.\n// IV: 53759\n\n/// @dev The interface a contract MUST implement if it is the implementer of\n/// some (other) interface for any address other than itself.\ninterface ERC1820ImplementerInterface {\n    /// @notice Indicates whether the contract implements the interface &apos;interfaceHash&apos; for the address &apos;addr&apos; or not.\n    /// @param interfaceHash keccak256 hash of the name of the interface\n    /// @param addr Address for which the contract will implement the interface\n    /// @return ERC1820_ACCEPT_MAGIC only if the contract implements &apos;interfaceHash&apos; for the address &apos;addr&apos;.\n    function canImplementInterfaceForAddress(bytes32 interfaceHash, address addr) external view returns(bytes32);\n}\n\n\n/// @title ERC1820 Pseudo-introspection Registry Contract\n/// @author Jordi Baylina and Jacques Dafflon\n/// @notice This contract is the official implementation of the ERC1820 Registry.\n/// @notice For more details, see https://eips.ethereum.org/EIPS/eip-1820\ncontract ERC1820Registry {\n    /// @notice ERC165 Invalid ID.\n    bytes4 constant internal INVALID_ID = 0xffffffff;\n    /// @notice Method ID for the ERC165 supportsInterface method (= `bytes4(keccak256(&apos;supportsInterface(bytes4)&apos;))`).\n    bytes4 constant internal ERC165ID = 0x01ffc9a7;\n    /// @notice Magic value which is returned if a contract implements an interface on behalf of some other address.\n    bytes32 constant internal ERC1820_ACCEPT_MAGIC = keccak256(abi.encodePacked(\&quot;ERC1820_ACCEPT_MAGIC\&quot;));\n\n    /// @notice mapping from addresses and interface hashes to their implementers.\n    mapping(address =&gt; mapping(bytes32 =&gt; address)) internal interfaces;\n    /// @notice mapping from addresses to their manager.\n    mapping(address =&gt; address) internal managers;\n    /// @notice flag for each address and erc165 interface to indicate if it is cached.\n    mapping(address =&gt; mapping(bytes4 =&gt; bool)) internal erc165Cached;\n\n    /// @notice Indicates a contract is the &apos;implementer&apos; of &apos;interfaceHash&apos; for &apos;addr&apos;.\n    event InterfaceImplementerSet(address indexed addr, bytes32 indexed interfaceHash, address indexed implementer);\n    /// @notice Indicates &apos;newManager&apos; is the address of the new manager for &apos;addr&apos;.\n    event ManagerChanged(address indexed addr, address indexed newManager);\n\n    /// @notice Query if an address implements an interface and through which contract.\n    /// @param _addr Address being queried for the implementer of an interface.\n    /// (If &apos;_addr&apos; is the zero address then &apos;msg.sender&apos; is assumed.)\n    /// @param _interfaceHash Keccak256 hash of the name of the interface as a string.\n    /// E.g., &apos;web3.utils.keccak256(\&quot;ERC777TokensRecipient\&quot;)&apos; for the &apos;ERC777TokensRecipient&apos; interface.\n    /// @return The address of the contract which implements the interface &apos;_interfaceHash&apos; for &apos;_addr&apos;\n    /// or &apos;0&apos; if &apos;_addr&apos; did not register an implementer for this interface.\n    function getInterfaceImplementer(address _addr, bytes32 _interfaceHash) external view returns (address) {\n        address addr = _addr == address(0) ? msg.sender : _addr;\n        if (isERC165Interface(_interfaceHash)) {\n            bytes4 erc165InterfaceHash = bytes4(_interfaceHash);\n            return implementsERC165Interface(addr, erc165InterfaceHash) ? addr : address(0);\n        }\n        return interfaces[addr][_interfaceHash];\n    }\n\n    /// @notice Sets the contract which implements a specific interface for an address.\n    /// Only the manager defined for that address can set it.\n    /// (Each address is the manager for itself until it sets a new manager.)\n    /// @param _addr Address for which to set the interface.\n    /// (If &apos;_addr&apos; is the zero address then &apos;msg.sender&apos; is assumed.)\n    /// @param _interfaceHash Keccak256 hash of the name of the interface as a string.\n    /// E.g., &apos;web3.utils.keccak256(\&quot;ERC777TokensRecipient\&quot;)&apos; for the &apos;ERC777TokensRecipient&apos; interface.\n    /// @param _implementer Contract address implementing &apos;_interfaceHash&apos; for &apos;_addr&apos;.\n    function setInterfaceImplementer(address _addr, bytes32 _interfaceHash, address _implementer) external {\n        address addr = _addr == address(0) ? msg.sender : _addr;\n        require(getManager(addr) == msg.sender, \&quot;Not the manager\&quot;);\n\n        require(!isERC165Interface(_interfaceHash), \&quot;Must not be an ERC165 hash\&quot;);\n        if (_implementer != address(0) &amp;&amp; _implementer != msg.sender) {\n            require(\n                ERC1820ImplementerInterface(_implementer)\n                    .canImplementInterfaceForAddress(_interfaceHash, addr) == ERC1820_ACCEPT_MAGIC,\n                \&quot;Does not implement the interface\&quot;\n            );\n        }\n        interfaces[addr][_interfaceHash] = _implementer;\n        emit InterfaceImplementerSet(addr, _interfaceHash, _implementer);\n    }\n\n    /// @notice Sets &apos;_newManager&apos; as manager for &apos;_addr&apos;.\n    /// The new manager will be able to call &apos;setInterfaceImplementer&apos; for &apos;_addr&apos;.\n    /// @param _addr Address for which to set the new manager.\n    /// @param _newManager Address of the new manager for &apos;addr&apos;. (Pass &apos;0x0&apos; to reset the manager to &apos;_addr&apos;.)\n    function setManager(address _addr, address _newManager) external {\n        require(getManager(_addr) == msg.sender, \&quot;Not the manager\&quot;);\n        managers[_addr] = _newManager == _addr ? address(0) : _newManager;\n        emit ManagerChanged(_addr, _newManager);\n    }\n\n    /// @notice Get the manager of an address.\n    /// @param _addr Address for which to return the manager.\n    /// @return Address of the manager for a given address.\n    function getManager(address _addr) public view returns(address) {\n        // By default the manager of an address is the same address\n        if (managers[_addr] == address(0)) {\n            return _addr;\n        } else {\n            return managers[_addr];\n        }\n    }\n\n    /// @notice Compute the keccak256 hash of an interface given its name.\n    /// @param _interfaceName Name of the interface.\n    /// @return The keccak256 hash of an interface name.\n    function interfaceHash(string calldata _interfaceName) external pure returns(bytes32) {\n        return keccak256(abi.encodePacked(_interfaceName));\n    }\n\n    /* --- ERC165 Related Functions --- */\n    /* --- Developed in collaboration with William Entriken. --- */\n\n    /// @notice Updates the cache with whether the contract implements an ERC165 interface or not.\n    /// @param _contract Address of the contract for which to update the cache.\n    /// @param _interfaceId ERC165 interface for which to update the cache.\n    function updateERC165Cache(address _contract, bytes4 _interfaceId) external {\n        interfaces[_contract][_interfaceId] = implementsERC165InterfaceNoCache(\n            _contract, _interfaceId) ? _contract : address(0);\n        erc165Cached[_contract][_interfaceId] = true;\n    }\n\n    /// @notice Checks whether a contract implements an ERC165 interface or not.\n    //  If the result is not cached a direct lookup on the contract address is performed.\n    //  If the result is not cached or the cached value is out-of-date, the cache MUST be updated manually by calling\n    //  &apos;updateERC165Cache&apos; with the contract address.\n    /// @param _contract Address of the contract to check.\n    /// @param _interfaceId ERC165 interface to check.\n    /// @return True if &apos;_contract&apos; implements &apos;_interfaceId&apos;, false otherwise.\n    function implementsERC165Interface(address _contract, bytes4 _interfaceId) public view returns (bool) {\n        if (!erc165Cached[_contract][_interfaceId]) {\n            return implementsERC165InterfaceNoCache(_contract, _interfaceId);\n        }\n        return interfaces[_contract][_interfaceId] == _contract;\n    }\n\n    /// @notice Checks whether a contract implements an ERC165 interface or not without using nor updating the cache.\n    /// @param _contract Address of the contract to check.\n    /// @param _interfaceId ERC165 interface to check.\n    /// @return True if &apos;_contract&apos; implements &apos;_interfaceId&apos;, false otherwise.\n    function implementsERC165InterfaceNoCache(address _contract, bytes4 _interfaceId) public view returns (bool) {\n        uint256 success;\n        uint256 result;\n\n        (success, result) = noThrowCall(_contract, ERC165ID);\n        if (success == 0 || result == 0) {\n            return false;\n        }\n\n        (success, result) = noThrowCall(_contract, INVALID_ID);\n        if (success == 0 || result != 0) {\n            return false;\n        }\n\n        (success, result) = noThrowCall(_contract, _interfaceId);\n        if (success == 1 &amp;&amp; result == 1) {\n            return true;\n        }\n        return false;\n    }\n\n    /// @notice Checks whether the hash is a ERC165 interface (ending with 28 zeroes) or not.\n    /// @param _interfaceHash The hash to check.\n    /// @return True if &apos;_interfaceHash&apos; is an ERC165 interface (ending with 28 zeroes), false otherwise.\n    function isERC165Interface(bytes32 _interfaceHash) internal pure returns (bool) {\n        return _interfaceHash &amp; 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0;\n    }\n\n    /// @dev Make a call on a contract without throwing if the function does not exist.\n    function noThrowCall(address _contract, bytes4 _interfaceId)\n        internal view returns (uint256 success, uint256 result)\n    {\n        bytes4 erc165ID = ERC165ID;\n\n        assembly {\n            let x := mload(0x40)               // Find empty storage location using \&quot;free memory pointer\&quot;\n            mstore(x, erc165ID)                // Place signature at beginning of empty storage\n            mstore(add(x, 0x04), _interfaceId) // Place first argument directly next to signature\n\n            success := staticcall(\n                30000,                         // 30k gas\n                _contract,                     // To addr\n                x,                             // Inputs are stored at location x\n                0x24,                          // Inputs are 36 (4 + 32) bytes long\n                x,                             // Store output over input (saves space)\n                0x20                           // Outputs are 32 bytes long\n            )\n\n            result := mload(x)                 // Load the result\n        }\n    }\n}\n&quot;,
            &quot;keccak256&quot;: &quot;0x64025ecebddb6e126a5075c1fd6c01de2840492668e2909cef7157040a9d1945&quot;
          }
        },
        &quot;version&quot;: 1
      }
```

&lt;/details&gt;

### Interface Name

Any interface name is hashed using `keccak256` and sent to `getInterfaceImplementer()`.

If the interface is part of a standard, it is best practice to explicitly state the interface name and link to this published [ERC-1820] such that other people don&apos;t have to come here to look up these rules.

For convenience, the registry provides a function to compute the hash on-chain:

``` solidity
function interfaceHash(string _interfaceName) public pure returns(bytes32)
```

Compute the keccak256 hash of an interface given its name.

&gt; &lt;small&gt;**identifier:** `65ba36c1`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`_interfaceName`: Name of the interface.&lt;/small&gt;  
&gt; &lt;small&gt;**returns:** The `keccak256` hash of an interface name.&lt;/small&gt;

#### **Approved ERCs**

If the interface is part of an approved ERC, it MUST be named `ERC###XXXXX` where `###` is the number of the ERC and XXXXX should be the name of the interface in CamelCase. 
The meaning of this interface SHOULD be defined in the specified ERC.

Examples:

- `keccak256(&quot;ERC20Token&quot;)`
- `keccak256(&quot;ERC777Token&quot;)`
- `keccak256(&quot;ERC777TokensSender&quot;)`
- `keccak256(&quot;ERC777TokensRecipient&quot;)`

#### **[ERC-165] Compatible Interfaces**

&gt; The compatibility with [ERC-165], including the [ERC165 Cache], has been designed and developed with [William Entriken].

Any interface where the last 28 bytes are zeroes (`0`) SHALL be considered an [ERC-165] interface.

**[ERC-165] Lookup**

Anyone can explicitly check if a contract implements an [ERC-165] interface using the registry by calling one of the two functions below:

``` solidity
function implementsERC165Interface(address _contract, bytes4 _interfaceId) public view returns (bool)
```

Checks whether a contract implements an [ERC-165] interface or not.

If the result is not cached a direct lookup on the contract address is performed.

*NOTE*: If the result is not cached or the cached value is out-of-date, the cache MUST be updated manually by calling `updateERC165Cache` with the contract address.
(See [ERC165 Cache] for more details.)

&gt; &lt;small&gt;**identifier:** `f712f3e8`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`_contract`: Address of the contract to check.&lt;/small&gt;  
&gt; &lt;small&gt;`_interfaceId`: [ERC-165] interface to check.&lt;/small&gt;  
&gt; &lt;small&gt;**returns:** `true` if `_contract` implements `_interfaceId`, `false` otherwise.&lt;/small&gt;

``` solidity
function implementsERC165InterfaceNoCache(address _contract, bytes4 _interfaceId) public view returns (bool)
```

Checks whether a contract implements an [ERC-165] interface or not without using nor updating the cache.

&gt; &lt;small&gt;**identifier:** `b7056765`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`_contract`: Address of the contract to check.&lt;/small&gt;  
&gt; &lt;small&gt;`_interfaceId`: [ERC-165] interface to check.&lt;/small&gt;  
&gt; &lt;small&gt;**returns:** `true` if `_contract` implements `_interfaceId`, false otherwise.&lt;/small&gt;

**[ERC-165] Cache** &lt;a id=&quot;erc165-cache&quot;&gt;&lt;/a&gt;

Whether a contract implements an [ERC-165] interface or not can be cached manually to save gas.

If a contract dynamically changes its interface and relies on the [ERC-165] cache of the [ERC-1820] registry, the cache MUST be updated manually---there is no automatic cache invalidation or cache update. 
Ideally the contract SHOULD automatically update the cache when changing its interface. 
However anyone MAY update the cache on the contract&apos;s behalf.

The cache update MUST be done using the `updateERC165Cache` function:

``` solidity
function updateERC165Cache(address _contract, bytes4 _interfaceId) external
```

&gt; &lt;small&gt;**identifier:** `a41e7d51`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`_contract`: Address of the contract for which to update the cache.&lt;/small&gt;  
&gt; &lt;small&gt;`_interfaceId`: [ERC-165] interface for which to update the cache.&lt;/small&gt;

#### **Private User-defined Interfaces**

This scheme is extensible. 
You MAY make up your own interface name and raise awareness to get other people to implement it and then check for those implementations.
Have fun but please, you MUST not conflict with the reserved designations above.

### Set An Interface For An Address

For any address to set a contract as the interface implementation, it must call the following function of the [ERC-1820] registry:

``` solidity
function setInterfaceImplementer(address _addr, bytes32 _interfaceHash, address _implementer) external
```

Sets the contract which implements a specific interface for an address.

Only the `manager` defined for that address can set it. 
(Each address is the manager for itself, see the [manager] section for more details.)

*NOTE*: If  `_addr` and `_implementer` are two different addresses, then:

- The `_implementer` MUST implement the `ERC1820ImplementerInterface` (detailed below).
- Calling `canImplementInterfaceForAddress` on `_implementer` with the given `_addr` and  `_interfaceHash` MUST return the `ERC1820_ACCEPT_MAGIC` value.

*NOTE*: The `_interfaceHash` MUST NOT be an [ERC-165] interface---it MUST NOT end with 28 zeroes (`0`).

*NOTE*: The `_addr` MAY be `0`, then `msg.sender` is assumed. 
This default value simplifies interactions via multisigs where the data of the transaction to sign is constant regardless of the address of the multisig instance.

&gt; &lt;small&gt;**identifier:** `29965a1d`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`_addr`: Address for which to set the interface. (If `_addr` is the zero address then `msg.sender` is assumed.)&lt;/small&gt;  
&gt; &lt;small&gt;`_interfaceHash`: Keccak256 hash of the name of the interface as a string, for example `web3.utils.keccak256(&apos;ERC777TokensRecipient&apos;)` for the ERC777TokensRecipient interface.&lt;/small&gt;  
&gt; &lt;small&gt;`_implementer`: Contract implementing `_interfaceHash` for `_addr`.&lt;/small&gt;

### Get An Implementation Of An Interface For An Address

Anyone MAY query the [ERC-1820] Registry to obtain the address of a contract implementing an interface on behalf of some address using the `getInterfaceImplementer` function.

``` solidity
function getInterfaceImplementer(address _addr, bytes32 _interfaceHash) external view returns (address)
```

Query if an address implements an interface and through which contract.

*NOTE*: If the last 28 bytes of the `_interfaceHash` are zeroes (`0`), then the first 4 bytes are considered an [ERC-165] interface and the registry SHALL forward the call to the contract at `_addr` to see if it implements the [ERC-165] interface (the first 4 bytes of `_interfaceHash`). 
The registry SHALL also cache [ERC-165] queries to reduce gas consumption. Anyone MAY call the `erc165UpdateCache` function to update whether a contract implements an interface or not.

*NOTE*: The `_addr` MAY be `0`, then `msg.sender` is assumed. 
This default value is consistent with the behavior of the `setInterfaceImplementer` function and simplifies interactions via multisigs where the data of the transaction to sign is constant regardless of the address of the multisig instance.

&gt; &lt;small&gt;**identifier:** `aabbb8ca`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`_addr`: Address being queried for the implementer of an interface. (If `_addr` is the zero address then `msg.sender` is assumed.)&lt;/small&gt;  
&gt; &lt;small&gt;`_interfaceHash`: keccak256 hash of the name of the interface as a string. E.g. `web3.utils.keccak256(&apos;ERC777Token&apos;)`&lt;/small&gt;  
&gt; &lt;small&gt;**returns:** The address of the contract which implements the interface `_interfaceHash` for `_addr` or `0` if `_addr` did not register an implementer for this interface.&lt;/small&gt;


### Interface Implementation (`ERC1820ImplementerInterface`)

``` solidity
interface ERC1820ImplementerInterface {
    /// @notice Indicates whether the contract implements the interface `interfaceHash` for the address `addr` or not.
    /// @param interfaceHash keccak256 hash of the name of the interface
    /// @param addr Address for which the contract will implement the interface
    /// @return ERC1820_ACCEPT_MAGIC only if the contract implements `interfaceHash` for the address `addr`.
    function canImplementInterfaceForAddress(bytes32 interfaceHash, address addr) external view returns(bytes32);
}
```

Any contract being registered as the implementation of an interface for a given address MUST implement said interface. 
In addition if it implements an interface on behalf of a different address, the contract MUST implement the `ERC1820ImplementerInterface` shown above.

``` solidity
function canImplementInterfaceForAddress(bytes32 interfaceHash, address addr) external view returns(bytes32)
```

Indicates whether a contract implements an interface (`interfaceHash`) for a given address (`addr`).

If a contract implements the interface (`interfaceHash`) for a given address (`addr`), it MUST return `ERC1820_ACCEPT_MAGIC` when called with the `addr` and the `interfaceHash`. 
If it does not implement the `interfaceHash` for a given address (`addr`), it MUST NOT return `ERC1820_ACCEPT_MAGIC`.

&gt; &lt;small&gt;**identifier:** `f0083250`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`interfaceHash`: Hash of the interface which is implemented&lt;/small&gt;  
&gt; &lt;small&gt;`addr`: Address for which the interface is implemented&lt;/small&gt;  
&gt; &lt;small&gt;**returns:** `ERC1820_ACCEPT_MAGIC` only if the contract implements `ìnterfaceHash` for the address `addr`.&lt;/small&gt;

The special value `ERC1820_ACCEPT_MAGIC` is defined as the `keccka256` hash of the string `&quot;ERC1820_ACCEPT_MAGIC&quot;`.

``` solidity
bytes32 constant internal ERC1820_ACCEPT_MAGIC = keccak256(abi.encodePacked(&quot;ERC1820_ACCEPT_MAGIC&quot;));
```

&gt; The reason to return `ERC1820_ACCEPT_MAGIC` instead of a boolean is to prevent cases where a contract fails to implement the `canImplementInterfaceForAddress` but implements a fallback function which does not throw. In this case, since `canImplementInterfaceForAddress` does not exist, the fallback function is called instead, executed without throwing and returns `1`. Thus making it appear as if `canImplementInterfaceForAddress` returned `true`.

### Manager

The manager of an address (regular account or a contract) is the only entity allowed to register implementations of interfaces for the address. 
By default, any address is its own manager.

The manager can transfer its role to another address by calling `setManager` on the registry contract with the address for which to transfer the manager and the address of the new manager.

**`setManager` Function**

``` solidity
function setManager(address _addr, address _newManager) external
```

Sets `_newManager` as manager for `_addr`.

The new manager will be able to call `setInterfaceImplementer` for `_addr`.

If `_newManager` is `0x0`, the manager is reset to `_addr` itself as the manager.

&gt; &lt;small&gt;**identifier:** `5df8122f`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`_addr`: Address for which to set the new manager.&lt;/small&gt;  
&gt; &lt;small&gt;`_newManager`: The address of the new manager for `_addr`. (Pass `0x0` to reset the manager to `_addr`.)&lt;/small&gt;

**`getManager` Function**

``` solidity
function getManager(address _addr) public view returns(address)
```

Get the manager of an address.

&gt; &lt;small&gt;**identifier:** `3d584063`&lt;/small&gt;  
&gt; &lt;small&gt;**parameters**&lt;/small&gt;  
&gt; &lt;small&gt;`_addr`: Address for which to return the manager.&lt;/small&gt;  
&gt; &lt;small&gt;**returns:** Address of the manager for a given address.&lt;/small&gt;

## Rationale

This standards offers a way for any type of address (externally owned and contracts) to implement an interface and potentially delegate the implementation of the interface to a proxy contract. 
This delegation to a proxy contract is necessary for externally owned accounts and useful to avoid redeploying existing contracts such as multisigs and DAOs.

The registry can also act as a [ERC-165] cache in order to save gas when looking up if a contract implements a specific [ERC-165] interface. 
This cache is intentionally kept simple, without automatic cache update or invalidation. 
Anyone can easily and safely update the cache for any interface and any contract by calling the `updateERC165Cache` function.

The registry is deployed using a keyless deployment method relying on a single-use deployment address to ensure no one controls the registry, thereby ensuring trust.

## Backward Compatibility

This standard is backward compatible with [ERC-165], as both methods MAY be implemented without conflicting with each other.

## Test Cases

Please check the [0xjac/ERC1820] repository for the full test suite.

## Implementation

The implementation is available in the repo: [0xjac/ERC1820].

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[EIP-155]: /EIPs/EIPS/eip-155

[ERC-165]: /EIPs/EIPS/eip-165
[ERC-672]: https://github.com/ethereum/EIPs/issues/672

[ERC-820]: /EIPs/EIPS/eip-820

[ERC-1820]: /EIPs/EIPS/eip-1820
[ERC1820 registry smart contract]: https://github.com/0xjac/ERC1820/blob/master/contracts/ERC1820Registry.sol
[erc1820-annoucement]: https://github.com/ethereum/EIPs/issues/820#issuecomment-464109166
[erc820-bug]: https://github.com/ethereum/EIPs/issues/820#issuecomment-452465748
[erc820-fix]: https://github.com/ethereum/EIPs/issues/820#issuecomment-454021564
[manager]: #manager
[lookup]: #get-an-implementation-of-an-interface-for-an-address
[ERC165 Cache]: #erc165-cache
[Nick&apos;s article]: https://medium.com/@weka/how-to-send-ether-to-11-440-people-187e332566b7
[0xjac/ERC1820]: https://github.com/0xjac/ERC1820
[Nick]: https://github.com/Arachnid/
[William Entriken]: https://github.com/fulldecent
[ENS]: https://ens.domains/
</description>
        <pubDate>Mon, 04 Mar 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1820</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1820</guid>
      </item>
    
      <item>
        <title>Universal Upgradeable Proxy Standard (UUPS)</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-1822-universal-upgradeable-proxy-standard-uups</comments>
        
        <description>## Simple Summary

Standard upgradeable proxy contract.

## Abstract

The following describes a standard for proxy contracts which is universally compatible with all contracts, and does not create incompatibility between the proxy and business-logic contracts. This is achieved by utilizing a unique storage position in the proxy contract to store the Logic Contract&apos;s address. A compatibility check ensures successful upgrades. Upgrading can be performed unlimited times, or as determined by custom logic. In addition, a method for selecting from multiple constructors is provided, which does not inhibit the ability to verify bytecode.

## Motivation

- Improve upon existing proxy implementations to improve developer experience for deploying and maintaining Proxy and Logic Contracts.

- Standardize and improve the methods for verifying the bytecode used by the Proxy Contract.

## Terminology

- `delegatecall()` - Function in contract **A** which allows an external contract **B** (delegating) to modify **A**&apos;s storage (see diagram below, [Solidity docs](https://solidity.readthedocs.io/en/v0.5.3/introduction-to-smart-contracts.html#delegatecall-callcode-and-libraries))
- **Proxy Contract** - The contract **A** which stores data, but uses the logic of external contract **B** by way of `delegatecall()`.
- **Logic Contract** - The contract **B** which contains the logic used by Proxy Contract **A**
- **Proxiable Contract** - Inherited in Logic Contract **B** to provide the upgrade functionality

![](/EIPs/assets/eip-1822/proxy-diagram.png)

## Specification

The Proxy Contract proposed here should be deployed _as is_, and used as a drop-in replacement for any existing methods of lifecycle management of contracts. In addition to the Proxy Contract, we propose the Proxiable Contract interface/base which establishes a pattern for the upgrade which does not interfere with existing business rules. The logic for allowing upgrades can be implemented as needed.

### Proxy Contract

#### Functions

##### `fallback`

The proposed fallback function follows the common pattern seen in other Proxy Contract implementations such as [Zeppelin][1] or [Gnosis][2].

However, rather than forcing use of a variable, the address of the Logic Contract is stored at the defined storage position `keccak256(&quot;PROXIABLE&quot;)`. This eliminates the possibility of collision between variables in the Proxy and Logic Contracts, thus providing &quot;universal&quot; compatibility with any Logic Contract.

```javascript
function() external payable {
    assembly { // solium-disable-line
        let contractLogic := sload(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7)
        calldatacopy(0x0, 0x0, calldatasize)
        let success := delegatecall(sub(gas, 10000), contractLogic, 0x0, calldatasize, 0, 0)
        let retSz := returndatasize
        returndatacopy(0, 0, retSz)
        switch success
        case 0 {
            revert(0, retSz)
        }
        default {
            return(0, retSz)
        }
    }
}
```

#### `constructor`

The proposed constructor accepts any number of arguments of any type, and thus is compatible with any Logic Contract constructor function.

In addition, the arbitrary nature of the Proxy Contract&apos;s constructor provides the ability to select from one or more constructor functions available in the Logic Contract source code (e.g., `constructor1`, `constructor2`, ... etc. ). Note that if multiple constructors are included in the Logic Contract, a check should be included to prohibit calling a constructor again post-initialization.

It&apos;s worth noting that the added functionality of supporting multiple constructors does not inhibit verification of the Proxy Contract&apos;s bytecode, since the initialization tx call data (input) can be decoded by first using the Proxy Contract ABI, and then using the Logic Contract ABI.

The contract below shows the proposed implementation of the Proxy Contract.

```javascript
contract Proxy {
    // Code position in storage is keccak256(&quot;PROXIABLE&quot;) = &quot;0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7&quot;
    constructor(bytes memory constructData, address contractLogic) public {
        // save the code address
        assembly { // solium-disable-line
            sstore(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7, contractLogic)
        }
        (bool success, bytes memory _ ) = contractLogic.delegatecall(constructData); // solium-disable-line
        require(success, &quot;Construction failed&quot;);
    }

    function() external payable {
        assembly { // solium-disable-line
            let contractLogic := sload(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7)
            calldatacopy(0x0, 0x0, calldatasize)
            let success := delegatecall(sub(gas, 10000), contractLogic, 0x0, calldatasize, 0, 0)
            let retSz := returndatasize
            returndatacopy(0, 0, retSz)
            switch success
            case 0 {
                revert(0, retSz)
            }
            default {
                return(0, retSz)
            }
        }
    }
}
```

### Proxiable Contract

The Proxiable Contract is included in the Logic Contract, and provides the functions needed to perform an upgrade. The compatibility check `proxiable` prevents irreparable updates during an upgrade.

&gt; :warning: Warning: `updateCodeAddress` and `proxiable` must be present in the Logic Contract. Failure to include these may prevent upgrades, and could allow the Proxy Contract to become entirely unusable. See below [Restricting dangerous functions](#restricting-dangerous-functions)

#### Functions

##### `proxiable`

Compatibility check to ensure the new Logic Contract implements the Universal Upgradeable Proxy Standard. Note that in order to support future implementations, the `bytes32` comparison could be changed e.g., `keccak256(&quot;PROXIABLE-ERC1822-v1&quot;)`.

##### `updateCodeAddress`

Stores the Logic Contract&apos;s address at storage `keccak256(&quot;PROXIABLE&quot;)` in the Proxy Contract.

The contract below shows the proposed implementation of the Proxiable Contract.

```javascript
contract Proxiable {
    // Code position in storage is keccak256(&quot;PROXIABLE&quot;) = &quot;0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7&quot;

    function updateCodeAddress(address newAddress) internal {
        require(
            bytes32(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7) == Proxiable(newAddress).proxiableUUID(),
            &quot;Not compatible&quot;
        );
        assembly { // solium-disable-line
            sstore(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7, newAddress)
        }
    }
    function proxiableUUID() public pure returns (bytes32) {
        return 0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7;
    }
}
```

## Pitfalls when using a proxy

The following common best practices should be employed for all Logic Contracts when using a proxy contract.

### Separating Variables from Logic

Careful consideration should be made when designing a new Logic Contract to prevent incompatibility with the existing storage of the Proxy Contract after an upgrade. Specifically, the order in which variables are instantiated in the new contract should not be modified, and any new variables should be added after all existing variables from the previous Logic Contract

To facilitate this practice, we recommend utilizing a single &quot;base&quot; contract which holds all variables, and which is inherited in subsequent logic contract(s). This practice greatly reduces the chances of accidentally reordering variables or overwriting them in storage.

### Restricting dangerous functions

The compatibility check in the Proxiable Contract is a safety mechanism to prevent upgrading to a Logic Contract which does not implement the Universal Upgradeable Proxy Standard. However, as occurred in the parity wallet hack, it is still possible to perform irreparable damage to the Logic Contract itself.

In order to prevent damage to the Logic Contract, we recommend restricting permissions for any potentially damaging functions to `onlyOwner`, and giving away ownership of the Logic Contract immediately upon deployment to a null address (e.g., address(1)). Potentially damaging functions include native functions such as `SELFDESTRUCT`, as well functions whose code may originate externally such as `CALLCODE`, and `delegatecall()`. In the [ERC-20 Token](#erc-20-token) example below, a `LibraryLock` contract is used to prevent destruction of the logic contract.

## Examples

### Owned

In this example, we show the standard ownership example, and restrict the `updateCodeAddress` to only the owner.

```javascript
contract Owned is Proxiable {
    // ensures no one can manipulate this contract once it is deployed
    address public owner = address(1);

    function constructor1() public{
        // ensures this can be called only once per *proxy* contract deployed
        require(owner == address(0));
        owner = msg.sender;
    }

    function updateCode(address newCode) onlyOwner public {
        updateCodeAddress(newCode);
    }

    modifier onlyOwner() {
        require(msg.sender == owner, &quot;Only owner is allowed to perform this action&quot;);
        _;
    }
}
```

### ERC-20 Token

#### Proxy Contract

```javascript
pragma solidity ^0.5.1;

contract Proxy {
    // Code position in storage is keccak256(&quot;PROXIABLE&quot;) = &quot;0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7&quot;
    constructor(bytes memory constructData, address contractLogic) public {
        // save the code address
        assembly { // solium-disable-line
            sstore(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7, contractLogic)
        }
        (bool success, bytes memory _ ) = contractLogic.delegatecall(constructData); // solium-disable-line
        require(success, &quot;Construction failed&quot;);
    }

    function() external payable {
        assembly { // solium-disable-line
            let contractLogic := sload(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7)
            calldatacopy(0x0, 0x0, calldatasize)
            let success := delegatecall(sub(gas, 10000), contractLogic, 0x0, calldatasize, 0, 0)
            let retSz := returndatasize
            returndatacopy(0, 0, retSz)
            switch success
            case 0 {
                revert(0, retSz)
            }
            default {
                return(0, retSz)
            }
        }
    }
}
```

#### Token Logic Contract

``` javascript

contract Proxiable {
    // Code position in storage is keccak256(&quot;PROXIABLE&quot;) = &quot;0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7&quot;

    function updateCodeAddress(address newAddress) internal {
        require(
            bytes32(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7) == Proxiable(newAddress).proxiableUUID(),
            &quot;Not compatible&quot;
        );
        assembly { // solium-disable-line
            sstore(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7, newAddress)
        }
    }
    function proxiableUUID() public pure returns (bytes32) {
        return 0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7;
    }
}


contract Owned {

    address owner;

    function setOwner(address _owner) internal {
        owner = _owner;
    }
    modifier onlyOwner() {
        require(msg.sender == owner, &quot;Only owner is allowed to perform this action&quot;);
        _;
    }
}

contract LibraryLockDataLayout {
  bool public initialized = false;
}

contract LibraryLock is LibraryLockDataLayout {
    // Ensures no one can manipulate the Logic Contract once it is deployed.
    // PARITY WALLET HACK PREVENTION

    modifier delegatedOnly() {
        require(initialized == true, &quot;The library is locked. No direct &apos;call&apos; is allowed&quot;);
        _;
    }
    function initialize() internal {
        initialized = true;
    }
}

contract ERC20DataLayout is LibraryLockDataLayout {
  uint256 public totalSupply;
  mapping(address=&gt;uint256) public tokens;
}

contract ERC20 {
    //  ...
    function transfer(address to, uint256 amount) public {
        require(tokens[msg.sender] &gt;= amount, &quot;Not enough funds for transfer&quot;);
        tokens[to] += amount;
        tokens[msg.sender] -= amount;
    }
}

contract MyToken is ERC20DataLayout, ERC20, Owned, Proxiable, LibraryLock {

    function constructor1(uint256 _initialSupply) public {
        totalSupply = _initialSupply;
        tokens[msg.sender] = _initialSupply;
        initialize();
        setOwner(msg.sender);
    }
    function updateCode(address newCode) public onlyOwner delegatedOnly  {
        updateCodeAddress(newCode);
    }
    function transfer(address to, uint256 amount) public delegatedOnly {
        ERC20.transfer(to, amount);
    }
}
```

## References

- [&quot;Escape-hatch&quot; proxy Medium Post](https://medium.com/terminaldotco/escape-hatch-proxy-efb681de108d)

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[1]: https://github.com/maraoz/solidity-proxy/blob/master/contracts/Dispatcher.sol
[2]: https://blog.gnosis.pm/solidity-delegateproxy-contracts-e09957d0f201
</description>
        <pubDate>Mon, 04 Mar 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1822</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1822</guid>
      </item>
    
      <item>
        <title>Precompile for Elliptic Curve Linear Combinations</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/ewasm-precompile-for-general-elliptic-curve-math/2581</comments>
        
        <description># Precompile for Elliptic Curve Linear Combinations

## Simple Summary

Currently the EVM only supports *secp256k1* in a limited way through `ecrecover` and *altbn128* through two pre-compiles. There are draft proposals to add more curves. There are many more elliptic curves that have useful applications for integration with existing systems or newly developed curves for zero-knowledge proofs.

This EIP adds a precompile that allows whole classes of curves to be used.

## Abstract

A precompile that takes a curve and computes a linear combination of curve points.

## Motivation

## Specification

Given integers `m, α` and `β`, scalars `s_i`, and curve points `A_i` construct the elliptic curve

```
y² = x³ + α ⋅ x + β  mod  m
```

and compute the following

```
C = s₀ ⋅ A₀ + s₁ ⋅ A₁ + ⋯ + s_n ⋅ A_n
```

aka *linear combination*, *inner product*, *multi-multiplication* or even *multi-exponentiation*.

```
(Cx, Cy) := ecmul(m, α, β,  s0, Ax0, As0, s1, Ax1, As1, ...)
```

### Gas cost

```
BASE_GAS = ...
ADD_GAS  = ...
MUL_GAS  = ...
```

The total gas cost is `BASE_GAS` plus `ADD_GAS` for each `s_i` that is `1` and `MUL_GAS` for each `s_i &gt; 1` (`s_i = 0` is free).

### Encoding of points

Encode as `(x, y&apos;)` where `s` indicates whether `y` or `-y` is to be taken. It follows SEC 1 v 1.9 2.3.4, except uncompressed points (`y&apos; = 0x04`) are not supported.

|  `y&apos;`  | `(x, y)` |
|--------|-----|
| `0x00` | Point at infinity |
| `0x02` | Solution with `y` even |
| `0x03` | Solution with `y` odd |

Conversion from affine coordinates to compressed coordinates is trivial: `y&apos; = 0x02 | (y &amp; 0x01)`.

### Special cases

**Coordinate recovery.** Set `s₀ = 1`. The output will be the recovered coordinates of `A₀`.

**On-curve checking.** Do coordinate recovery and compare `y` coordinate.

**Addition.** Set `s₀ = s₁ = 1`, the output will be `A₀ + A₁`.

**Doubling.** Set `s₀ = 2`. The output will be `2 ⋅ A₀`. (Note: under the current gas model, this may be more costly than self-addition!)

**Scalar multiplication.** Set only `s₀` and `A₀`.

**Modular square root.** Set `α = s₀ = A = 0` the output will have `Cy² = β   mod  m`.

### Edge cases

* Non-prime moduli or too small modulus
* Field elements larger than modulus
* Curve has singular points (`4 α³ + 27 β² = 0`)
* Invalid sign bytes
* x coordinate not on curve
* Returning the point at infinity
* (Please add if you spot more)

## Rationale

**Generic Field and Curve.** Many important optimizations are independent of the field and curve used. Some missed specific optimizations are:

* Reductions specific to the binary structure of the field prime.
* Precomputation of Montgomery factors.
* Precomputation of multiples of certain popular points like the generator.
* Special point addition/doubling [formulas][formulas] for `α = -3`, `α = -1`, `α = 0`, `β = 0`.


[formulas]: https://www.hyperelliptic.org/EFD/g1p/auto-shortw.html

TODO: The special cases for `α` and `β` might be worth implementing and offering a gas discount.

**Compressed Coordinates.** Compressed coordinates allow contract to work with only `x` coordinates and sign bytes. It also prevents errors around points not being on-curve. Conversion to compressed coordinates is trivial.

**Linear Combination.** We could instead have a simple multiply `C = r ⋅ A`. In this case we would need a separate pre-compile for addition. In addition, a linear combination allows for optimizations that like Shamir&apos;s trick that are not available in a single scalar multiplication. ECDSA requires `s₀ ⋅ A₀ + s₁ ⋅ A₁` and would benefit from this.

The BN254 (aka alt_bn8) multiplication operation introduced by the [EIP-196][EIP-196] precompile only handles a single scalar multiplication. The missed performance is such that for two or more points it is cheaper to use EVM, as practically demonstrated by [Weierstrudel][ws].

[EIP-196]: /EIPs/EIPS/eip-196
[ws]: https://medium.com/aztec-protocol/huffing-for-crypto-with-weierstrudel-9c9568c06901

**Variable Time Math.** When called during a transaction, there is no assumption of privacy and no mitigations for side-channel attacks are necessary.

**Prime Fields.** This EIP is for fields of large characteristic. It does not cover Binary fields and other fields of non-prime characteristic.

**256-bit modulus.** This EIP is for field moduli less than `2^{256}`. This covers many of the popular curves while still having all parameters fit in a single EVM word.

TODO: Consider a double-word version. 512 bits would cover all known curves except E-521. In particular it will cover the NIST P-384 curve used by the Estonian e-Identity and the BLS12-381 curve used by [ZCash Sappling][sappling].

[sappling]: https://z.cash/blog/new-snark-curve/

**Short Weierstrass Curves.** This EIP is for fields specified in short Weierstrass form. While any curve can be converted to short Weierstrass form through a [substitution of variables][cov], this misses out on the performance advantages of those specific forms.

[cov]: https://safecurves.cr.yp.to/equation.html

## Backwards Compatibility

## Test Cases

## Implementation

There will be a reference implementation in Rust based on the existing libraries (in particular those by ZCash and The Matter Inc.).

The reference implementation will be production grade and compile to a native library with a C api and a webassembly version. Node developers are encouraged to use the reference implementation and can use either the rust library, the native C bindings or the webassembly module. Node developers can of course always decide to implement their own.

## References

This EIP overlaps in scope with

* [EIP-196](/EIPs/EIPS/eip-196): ecadd, ecmul for altbn128
* [EIP issue 603](https://github.com/ethereum/EIPs/issues/603): ecadd, ecmul for SECP256k1.
* [EIP-665](/EIPs/EIPS/eip-665): ECDSA verify for ED25519.
* [EIP-1108](/EIPs/EIPS/eip-1108): Optimize ecadd and ecmul for altbn128.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Wed, 06 Mar 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1829</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1829</guid>
      </item>
    
      <item>
        <title>ENS Interface Discovery</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/ens-interface-discovery/2924</comments>
        
        <description>## Simple Summary
Defines a method of associating contract interfaces with ENS names and addresses, and of discovering those interfaces.

## Abstract
This EIP specifies a method for exposing interfaces associated with an ENS name or an address (typically a contract address) and allowing applications to discover those interfaces and interact with them. Interfaces can be implemented either by the target contract (if any) or by any other contract.

## Motivation
EIP 165 supports interface discovery - determining if the contract at a given address supports a requested interface. However, in many cases it&apos;s useful to be able to discover functionality associated with a name or an address that is implemented by other contracts.

For example, a token contract may not itself provide any kind of &apos;atomic swap&apos; functionality, but there may be associated contracts that do. With ENS interface discovery, the token contract can expose this metadata, informing applications where they can find that functionality.

## Specification
A new profile for ENS resolvers is defined, consisting of the following method:

```solidity
function interfaceImplementer(bytes32 node, bytes4 interfaceID) external view returns (address);
```

The EIP-165 interface ID of this interface is `0xb8f2bbb4`.

Given an ENS name hash `node` and an EIP-165 `interfaceID`, this function returns the address of an appropriate implementer of that interface. If there is no interface matching that interface ID for that node, 0 is returned.

The address returned by `interfaceImplementer` MUST refer to a smart contract.

The smart contract at the returned address SHOULD implement EIP-165.

Resolvers implementing this interface MAY utilise a fallback strategy: If no matching interface was explicitly provided by the user, query the contract returned by `addr()`, returning its address if the requested interface is supported by that contract, and 0 otherwise. If they do this, they MUST ensure they return 0, rather than reverting, if the target contract reverts.

This field may be used with both forward resolution and reverse resolution.

## Rationale

A naive approach to this problem would involve adding this method directly to the target contract. However, doing this has several shortcomings:

 1. Each contract must maintain its own list of interface implementations.
 2. Modifying this list requires access controls, which the contract may not have previously required.
 3. Support for this must be designed in when the contract is written, and cannot be retrofitted afterwards.
 4. Only one canonical list of interfaces can be supported.

Using ENS resolvers instead mitigates these shortcomings, making it possible for anyone to associate interfaces with a name, even for contracts not previously built with this in mind.

## Backwards Compatibility
There are no backwards compatibility issues.

## Test Cases
TBD

## Implementation
The PublicResolver in the [ensdomains/resolvers](https://github.com/ensdomains/resolvers/) repository implements this interface.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 15 Mar 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1844</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1844</guid>
      </item>
    
      <item>
        <title>Ethereum Network Upgrade Windows</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-1872-ethereum-network-upgrade-windows/2993</comments>
        
        <description>## Simple Summary

A proposal to define a limited number of annual time windows in which network
upgrades (aka hard forks) should be performed within. Policies for scheduling
network upgrades outside these windows are also described.

## Abstract

Four different weeks, spaced roughly evenly throughout the year, are targeted
for network upgrades to be launched. Regular network upgrades should announce
their intention to launch in a particular window early in their process and
choose a block number four to six weeks prior to that window. If a network
upgrade is cancelled then it would be rescheduled for the next window. Not all
windows will be used. Priority upgrades outside the roadmap may be scheduled in
the third week of any month, but such use is discouraged. Critical upgrades are
scheduled as needed.

## Motivation

The aim of this EIP is to provide some level of regularity and predictability to
the Ethereum network upgrade/hard fork process. This will allow service
providers such as exchanges and node operators a predictable framework to
schedule activities around. This also provides a framework to regularize the
delivery of network upgrades.

## Specification

Scheduling is defined for three categories of network upgrades. First are
`Roadmap` network upgrades that include deliberate protocol improvements. Next
are `Priority` network updates, where there are technical reasons that
necessitate a prompt protocol change but these reasons do not present a systemic
risk to the protocol or the ecosystem. Finally, `Critical` network upgrades are
to address issues that present a systemic risk to the protocol or the ecosystem.

### Roadmap Network Upgrades

Roadmap network upgrades are network upgrades that are deliberate and measured
to improve the protocol and ecosystem. Historical examples are Homestead,
Byzantium, and Constantinople.

Roadmap network upgrades should be scheduled in one of four windows: the week
with the third Wednesday in January, April, July, and October. When initiating a
network upgrade or early in the planning process a particular window should be
targeted.

&gt; **Note to reviewers:** The months and week chosen are to provide an initial
&gt; recommendation and are easily modifiable prior to final call. They thread the
&gt; needle between many third quarter and fourth quarter holidays.

Implementors are expected to have software for a Roadmap network upgrade ready
two to four weeks prior to the upgrade. Hence a block number for the network
upgrade should be chosen four to six weeks prior to the network upgrade window.
Scheduling details such as whether this choice is made prior to or after testnet
deployment are out of scope of this EIP.

Depending on the release cadence of Roadmap network upgrades some windows will
not be used. For example if a six month release cadence is chosen a roadmap
upgrade would not occur in adjacent upgrade windows. Hence for a six month
cadence if a roadmap upgrade occurred in April then the July window would not be
used for network upgrades.

If a planned roadmap upgrade needs to be rescheduled then strong consideration
should be given to rescheduling the upgrade for the next window in three months
time. For the case of a six month cadence this may cause releases to be in
adjacent release windows. For a three month cadence the next network upgrade
would be merged with the current upgrade or the next network upgrade would be
delayed.

To be compatible with the scheduled release windows the cadence of the Roadmap
Network Upgrades should be a multiple of three months. Whether it is three, six,
nine, or more month cadence is out of scope of this EIP.

### Priority Network Upgrades

Priority network upgrades are reserved for upgrades that require more urgency
than a roadmap network upgrade yet do not present a systemic risk to the network
or the ecosystem. To date there have been no examples of a priority upgrade.
Possible examples may include roadmap upgrades that need to occur in multiple
upgrades or for security risks that have a existing mitigation in place that
would be better served by a network upgrade. Another possible reason may be to
defuse the difficulty bomb due to postponed roadmap upgrades.

Priority network upgrades are best launched in unused roadmap launch windows,
namely the third week of January, April, July, and October. If necessary they
may be launched in the third week of any month, but strong consideration and
preference should be given to unused roadmap launch windows.

Priority network upgrades should be announced and a block chosen far enough in
advance so major clients implementors can release software with the needed block
number in a timely fashion. These releases should occur at least a week before
the launch window. Hence priority launch windows should be chosen two to four
weeks in advance.

### Critical Network Upgrades

Critical network upgrades are network upgrades that are designed to address
systemic risks to the protocol or to the ecosystem. Historical examples include
Dao Fork, Tangerine Whistle, and Spurious Dragon.

This EIP provides neither guidance nor restrictions to the development and
deployment of these emergency hard forks. These upgrades are typically launched
promptly after a solution to the systemic risk is agreed upon between the client
implementors.

It is recommended that such upgrades perform the minimum amount of changes
needed to address the issues that caused the need for the Critical network
upgrade and that other changes be integrated into subsequent Priority and
Roadmap network upgrades.

### Network Upgrade Block Number Choice

When choosing an activation block the number can be used to communicate the role
of a particular network in the Ethereum Ecosystem. Networks that serve as a
value store or are otherwise production grade have different stability concerns
than networks that serve as technology demonstration or are explicitly
designated for testing.

To date all Mainnet activation blocks have ended in three or more zeros,
including Critical Network Upgrades. Ropsten and Kovan initially started with
three zeros but switched to palindromic numbers. Rinkeby has always had
palindromic activation blocks. Goerli has yet to perform a network upgrade.

To continue this pattern network upgrade activation block numbers for mainnet
deployments and production grade networks should chose a number whose base 10
representation ends with three or more zeros.

For testnet and testing or development grades network operators are encouraged
to choose a block activation number that is a palindrome in base 10.

Block numbers for Roadmap and Priority network upgrades should be chosen so that
it is forecast to occur relatively close to Wednesday at 12:00 UTC+0 during the
launch window. This should result in an actual block production occurring
sometime between Monday and Friday of the chosen week.

## Rationale

The rationale for defining launch windows is to give business running Ethereum
infrastructure a predictable schedule for when upgrades may or may not occur.
Knowing when a upgrade is not going to occur gives the businesses a clear time
frame within which to perform internal upgrades free from external changes. It
also provides a timetable for developers and IT professionals to schedule time
off against.

## Backwards Compatibility

Except for the specific launch windows the previous network upgrades would have
complied with these policies. Homestead, Byzantium, and Constantinople would
have been Roadmap Network Upgrades. There were no Priority Network Upgrades,
although Spurious Dragon would have been a good candidate. Dao Fork was a
Critical Network Upgrade in response to TheDao. Tangerine Whistle and Spurious
Dragon were critical upgrades in response to the Shanghai Spam Attacks.
Constantinople Fix (as it is termed in the reference tests) was in response to
the EIP-1283 security issues.

If this policy were in place prior to Constantinople then the initial 2018
launch would likely have been bumped to the next window after the Ropsten
testnet consensus failures. The EIP-1283 issues likely would have resulted in an
out of window upgrade because of the impact of the difficulty bomb.

&lt;!-- ## Test Cases --&gt;
&lt;!-- no test cases are relevant for this EIP --&gt;

## Implementation

The windows in this EIP are expected to start after the Istanbul Network
upgrade, which is the next planned Roadmap upgrade. Istanbul is currently slated
for mainnet launch on 2019-10-16, which is compatible with the schedule in this
EIP.

The Roadmap Upgrade windows starting with Istanbul would be as follows:

| Block Target | Launch Week Range        |
| ------------ | ------------------------ |
| 2019-10-16   | 2019-10-14 to 2019-10-18 |
| 2020-01-15   | 2020-01-13 to 2020-01-17 |
| 2020-04-15   | 2020-04-13 to 2020-04-17 |
| 2020-07-15   | 2020-07-13 to 2020-07-17 |
| 2020-10-21   | 2020-10-19 to 2020-10-23 |
| 2021-01-20   | 2021-01-18 to 2021-01-22 |
| 2021-04-21   | 2021-04-19 to 2021-04-23 |
| 2021-07-21   | 2021-07-19 to 2021-07-23 |
| 2021-10-20   | 2021-10-18 to 2021-10-22 |
| 2022-01-19   | 2022-01-17 to 2022-01-21 |
| 2022-04-20   | 2022-04-18 to 2022-04-22 |
| 2022-07-20   | 2022-07-18 to 2022-07-22 |
| 2022-10-19   | 2022-10-17 to 2022-10-21 |

The Priority windows through next year, excluding Roadmap windows, are as
follows:

| Block Target | Launch Week Range        |
| ------------ | ------------------------ |
| 2019-11-20   | 2019-11-18 to 2019-11-22 |
| 2019-12-18   | 2019-12-16 to 2019-12-20 |
| 2020-02-19   | 2020-02-17 to 2020-02-21 |
| 2020-03-18   | 2020-03-16 to 2020-03-20 |
| 2020-05-20   | 2020-05-18 to 2020-05-22 |
| 2020-06-17   | 2020-06-15 to 2020-06-19 |
| 2020-08-19   | 2020-08-18 to 2020-08-21 |
| 2020-09-16   | 2020-09-14 to 2020-09-18 |
| 2020-11-18   | 2020-11-16 to 2020-11-20 |
| 2020-12-16   | 2020-12-14 to 2020-12-18 |

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 25 Mar 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1872</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1872</guid>
      </item>
    
      <item>
        <title>Repricing for trie-size-dependent opcodes</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/opcode-repricing/3024</comments>
        
        <description>## Simple Summary

This EIP proposes repricing certain opcodes, to obtain a good balance between gas expenditure and resource consumption.

## Abstract

The growth of the Ethereum state has caused certain opcodes to be more resource-intensive at this point than 
they were previously. This EIP proposes to raise the `gasCost` for those opcodes.

## Motivation

An imbalance between the price of an operation and the resource consumption (CPU time, memory etc)
has several drawbacks:

- It could be used for attacks, by filling blocks with underpriced operations which causes excessive block processing time.
- Underpriced opcodes cause a skewed block gas limit, where sometimes blocks finish quickly but other blocks with similar gas use finish slowly.

If operations are well-balanced, we can maximise the block gaslimit and have a more stable processing time.

## Specification

At block `N`, 

- The `SLOAD` (`0x54`) operation changes from `200` to `800` gas,
- The `BALANCE` (`0x31`) operation changes from `400` to `700` gas,
- The `EXTCODEHASH` (`0x3F`) operation changes from `400` to `700` gas,
- A new opcode, `SELFBALANCE` is introduced at `0x47`. 
  - `SELFBALANCE` pops `0` arguments off the stack, 
  - `SELFBALANCE` pushes the `balance` of the current address to the stack,
  - `SELFBALANCE` is priced as `GasFastStep`, at `5` gas. 

## Rationale

Here are two charts, taken from a full sync using Geth. The execution time was measured for every opcode, and aggregated for 10K blocks. These bar charts show the top 25 &apos;heavy&apos; opcodes in the ranges 5M to 6M and 6M to 7M:

![bars1](/EIPs/assets/eip-1884/run3.total-bars-5.png) 
![bars2](/EIPs/assets/eip-1884/run3.total-bars-6.png) 

Note: It can also be seen that the `SLOAD` moves towards the top position. The `GASPRICE` (`0x3a`) opcode has position one which I believe can be optimized away within the client -- which is not the case with `SLOAD`/`BALANCE`.

Here is another chart, showing a full sync with Geth. It represents the blocks `0` to `5.7M`, and highlights what the block processing time is spent on.

![geth](/EIPs/assets/eip-1884/geth_processing.png)

It can be seen that `storage_reads` and `account_reads` are the two most significant factors contributing to the block processing time. 

### `SLOAD`

`SLOAD` was repriced at [EIP-150][eip-150], from `50` to `200`. 
The following graph shows a go-ethereum full sync, where each data point represents
 10K blocks. During those 10K blocks, the execution time for the opcode was aggregated.

![graph](/EIPs/assets/eip-1884/SLOAD-run3.png)

It can be seen that the repricing at [EIP-150][eip-150] caused a steep drop, from around `67` to `23`. 
Around block `5M`, it started reaching pre-[EIP-150][eip-150] levels, and at block `7M` 
it was averaging on around `150` - more than double pre-eip-150 levels. 

Increasing the cost of `SLOAD` by `4` would bring it back down to around `40`. 
It is to be expected that it will rise again in the future, and may need future repricing, unless 
state clearing efforts are implemented before that happens. 

### `BALANCE` 

`BALANCE` (a.k.a `EXTBALANCE`) is an operation which fetches data from the state trie. It was repriced at [EIP-150][eip-150] from `20` to `400`.

![graph](/EIPs/assets/eip-1884/BALANCE-run3.png)

It is comparable to `EXTCODESIZE` and `EXTCODEHASH`, which are priced at `700` already. 

It has a built-in high variance, since it is often used for checking the balance of `this`, 
which is an inherently cheap operation, however, it can be used to lookup the balance of arbitrary account which often require trie (disk) access. 

In hindsight, it might have been a better choice to have two 
opcodes: `EXTBALANCE(address)` and `SELFBALANCE`, and have two different prices. 

* This EIP proposes to extend the current opcode set.
  * Unfortunately, the opcode span `0x3X` is already full, hence the suggestion to place `SELFBALANCE` in the `0x4X` range.  
  * As for why it is priced at `5` (`GasFastStep`) instead of `2` (`GasQuickStep`), like other similar operations: the EVM execution engine still needs a lookup into the (cached) trie, and `balance`, unlike `gasPrice` or `timeStamp`, is not constant during the execution, so it has a bit more inherent overhead. 


### `EXTCODEHASH`

`EXTCODEHASH` was introduced in Constantinople, with [EIP-1052](/EIPs/EIPS/eip-1052). It was priced at `400` with the reasoning:

&gt; The gas cost is the same as the gas cost for the `BALANCE` opcode because the execution of the `EXTCODEHASH` requires the same account lookup as in `BALANCE`.

Ergo, if we increase `BALANCE`, we should also increase `EXTCODEHASH`


## Backwards Compatibility

The changes require a hardfork. The changes have the following consequences:

- Certain calls will become more expensive.
- Default-functions which access the storage and may in some cases require more than`2300` gas (the minimum gas that is always available in calls). 
- Contracts that assume a certain fixed gas cost for calls (or internal sections) may cease to function.
  - A fixed gas cost is specified in [ERC-165](/EIPs/EIPS/eip-165) and implementations of this interface do use the affected opcodes.
    - The ERC-165 method `supportsInterface` must return a `bool` and use at most `30,000` gas.
    - The two example implementations from the EIP were, at the time of writing 
      1. `586` gas for any input, and 
      2. `236` gas, but increases linearly with a higher number of supported interfaces
  - It is unlikely that any ERC-165 `supportsInterface` implementation will go above `30.000` gas. That would require that the second variant is used, and thirty:ish interfaces are supported.  
  - However, these operations have already been repriced earlier, so there is a historical precedent that &apos;the gascost for these operations may change&apos;, which should have prevented such fixed-gas-cost assumptions from being implemented.

I expect that certain patterns will be less used, for example the use of multiple modifiers which `SLOAD`s the same opcode will be merged into one. It may also lead to less `log` operations containing `SLOAD`ed values that are not strictly necessary.

## Test Cases

Testcases that should be implemented: 
- Test that `selfbalance == balance(address)`, 
- Test that `balance(this)` costs as before, 
- Test that `selfbalance` does not pop from stack
- Gascost verification of `SLOAD`, `EXTCODEHASH` and `SELFBALANCE`
- Verify that `SELFBALANCE` is invalid before Istanbul

Some testcases have been implemented as statetests at https://github.com/holiman/IstanbulTests/tree/master/GeneralStateTests

## Implementation

This EIP has not yet been implemented in any client. 
Both these opcodes have been repriced before, and the client internals for managing reprices are already in place.

### `SELFBALANCE`

This is the implementation for the new opcode in go-ethereum:

```golang

func opSelfBalance(pc *uint64, interpreter *EVMInterpreter, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
	stack.push(interpreter.intPool.get().Set(interpreter.evm.StateDB.GetBalance(contract.Address())
	return nil, nil
}

```

## Security considerations

- See backwards compatibility section. 
- There are no special edgecases regarding `SELFBALANCE`, if we define it as `BALANCE` with `address` instead of popping an address from the stack -- since `BALANCE` is already well-defined.
- It should be investigated if Solidity contains any hardcoded expectations on the gas cost of these operations.
- In many cases, a recipient of `ether` from a `CALL` will want to issue a `LOG`. The `LOG` operation costs `375` plus `375` per topic. If the `LOG` also wants to do an `SLOAD`, this change may make some such transfers fail. 

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[eip-150]: /EIPs/EIPS/eip-150
</description>
        <pubDate>Thu, 28 Mar 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1884</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1884</guid>
      </item>
    
      <item>
        <title>Commitment to Sustainable Ecosystem Funding</title>
        <category>Standards Track/Core</category>
        
          <comments>https://t.me/joinchat/DwEd_xahL5hHvzNYH2RnQA</comments>
        
        <description># Commitment to Sustainable Ecosystem Funding

## Simple Summary

Ethereum currently provides a block reward to proof of work miners every block, but it does not capture any block rewards for ecosystem funding. This EIP adds a simple mechanism for capturing a portion of block rewards for ecosystem funding as a credible commitment to doing so in future, but it does not actually capture any such rewards.

## Abstract

A mechanism that allows specification of two parameters, a beneficiary address and a per-block reward denominated in wei, that allows a portion of block rewards to be captured for the purpose of ecosystem funding. Both values are set to zero.

## Motivation

In order for Ethereum to succeed, it needs talented, motivated researchers and developers to continue to develop and maintain the platform. Those talented researchers and developers deserve to be paid fairly for their work. At present there is no mechanism in the Ethereum ecosystem that rewards R&amp;D teams fairly for their work on the platform.

We recognize that, while technically trivial, the real challenge in inflation-based funding is social: how to fairly capture, govern, and distribute block rewards. It will take time to work out the answer to these questions. For this reason, this EIP only seeks to make a credible commitment on the part of core developers to securing the funding they need to keep Ethereum alive and healthy by adding a mechanism to do so, but the actual amount of rewards captured remains at zero, i.e., there is no change at present to Ethereum’s economics. Raising the amount captured above zero would require a future EIP.

## Specification

Two new constants are introduced: BENEFICIARY_ADDRESS, an Address, and DEVFUND_BLOCK_REWARD, an amount denominated in wei. Both are set to zero.

Beginning with block ISTANBUL_BLOCK_HEIGHT, DEVFUND_BLOCK_REWARD wei is added to the balance of BENEFICIARY_ADDRESS at each block.

We may optionally add another constant, DECAY_FACTOR, which specifies a linear or exponenential decay factor that reduces the reward at every block &gt; ISTANBUL_BLOCK_HEIGHT until it decays to zero. For simplicity, it has been omitted from this proposal.

## Rationale

We believe that the technical design of this EIP is straightforward. The social rationale is explained in [this article](https://medium.com/gitcoin/funding-open-source-in-the-blockchain-era-8ded753bf05f).

## Backwards Compatibility

This EIP has no impact on backwards compatibility.

## Test Cases

This EIP makes no changes to existing state transitions. Existing consensus tests should be sufficient.

## Implementation

Reference implementations are included for the Trinity, go-ethereum, and parity clients.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 31 Mar 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1890</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1890</guid>
      </item>
    
      <item>
        <title>Support for an Elliptic Curve Cycle</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethresear.ch/t/reducing-the-verification-cost-of-a-snark-through-hierarchical-aggregation/5128</comments>
        
        <description>## Simple Summary

The EVM currently supports elliptic curves operations for curve *alt-bn128* thanks to precompiles `ecadd` and `ecmul` and `ecpairing`. The classes MNT4 and 6 contain cycles of curves. Those cycles enable doing operations on one curve inside a SNARK on the other curve (and reversely). This EIP suggests adding support for those curves.

## Abstract

Adds supports for the following operations through precompiles:

* `ecadd` on MNT4
* `ecmul` on MNT4
* `ecpairing` on MNT4

## Motivation

Elliptic curve is the basic block of recursive SNARKs (ie: verifying a SNARK inside a SNARK) and this addresses the issue of scalable zero-knowledge. More generally this addresses partly the scalability issue as SNARKs verification are constant time in the size of the circuit being verified.

More concretely, today if the EVM has to deal with 1000s of SNARK verification it would take around 1.5 billion gas and would be impractical for Ethereum. Recursive SNARKs for instance make it possible to aggregate multiple proofs into a single one that can be verified like any other SNARK. It results in a massive cost reduction for the verification.

However, this is impossible using *alt-bn128* and in my knowledge, the only family of pairing-friendly curves known to produce cycles are MNT4 and MNT6. A complete characterization of the cycles existing between those two families is proposed in [On cycles of pairing-friendly elliptic curves
](https://arxiv.org/pdf/1803.02067.pdf)

## Specification

### The curve

The proposed cycle has been introduced in [Scalable Zero Knowledge via Cycles of Elliptic Curves](https://eprint.iacr.org/2014/595.pdf).

### MNT4 definition

The groups `G_1` and `G_2` are cyclic groups of prime order :

```.
q = 475922286169261325753349249653048451545124878552823515553267735739164647307408490559963137
```

`G_1` is defined over the field `F_p` of prime order :

```.
p = 475922286169261325753349249653048451545124879242694725395555128576210262817955800483758081
```

with generator P:

```.
P = (
    60760244141852568949126569781626075788424196370144486719385562369396875346601926534016838,
    363732850702582978263902770815145784459747722357071843971107674179038674942891694705904306
)
```

Both p and q can be written in 298 bits.

The group G_1 is defined on the curve defined by the equation `Y² = X³ + aX + b` where:

```.
    a = 2
    b = 423894536526684178289416011533888240029318103673896002803341544124054745019340795360841685
```

The twisted group G_2 is defined over the field `F_p^2 = F_p / &lt;&lt;To be completed&gt;&gt;`

The twisted group G_2 is defined on the curve defined by the equation `Y² = X² + aX + b` where :

```.
    a = 34 + i * 0
    b = 0 + i * 67372828414711144619833451280373307321534573815811166723479321465776723059456513877937430
```

G_2 generator is generated by :

```.
    P2 = (
        438374926219350099854919100077809681842783509163790991847867546339851681564223481322252708 +
        i * 37620953615500480110935514360923278605464476459712393277679280819942849043649216370485641,
        37437409008528968268352521034936931842973546441370663118543015118291998305624025037512482 +
        i * 424621479598893882672393190337420680597584695892317197646113820787463109735345923009077489
    )
```

### The operations and gas cost

The following operations and their gas cost would be implemented

```.
MNT_X_ADD = &lt;&lt;To be estimated&gt;&gt;
MNT_X_MUL = &lt;&lt;To be estimated&gt;&gt;
MNT_X_PAIRING = &lt;&lt;To be estimated&gt;&gt;
```

Where `X` is either 4.

### Encoding

The curves points P(X, Y) over F_p are represented in their compressed form C(X, Y):

```.
    C = X | s
```

where `s` represents `Y` as follow:

```.
    |  `s&apos;`  | `Y`                      |
    |--------|--------------------------|
    | `0x00` | Point at infinity        |
    | `0x02` | Solution with `y` even   |
    | `0x03` | Solution with `y` odd    |
```

Compression operation from affine coordinate is trivial:

```.
    s = 0x02 | (s &amp; 0x01)
```

In the EVM the compressed form allows us to represents curve points with 2 uint256 instead of 3.

### Edge cases

* Several acceptable representations for the point at infinity

## Rationale

The curve has 80 bits of security (whereas MNT6 has 120 bits) which might not be considered enough for critical security level, (for instance transferring several billions), but enough for others. If it turns out this is not enough security for adoption, there is another option : another cycle is being used by Coda but is defined over a 753 bits sized field which might also be prohibitively low (no reference to this curve from Coda&apos;s publications found).

Independently of the cycle chosen, the groups and field elements are represented with integers larger than 256 bits (even for the 80 bits of security), therefore it might be necessary to also add support for larger field size operations.

We currently don&apos;t know more efficient pairing-friendly cycles and don&apos;t know if there are. It might be possible to circumvent this problem though by relaxing the constraint that all the curves of the cycle must be pairing friendly). If we had a cycle with only one pairing friendly curve we would still be able to compose proofs by alternating between SNARKs and any other general purpose zero-knowledge cryptosystems.

Assuming we find a convenient cycle, we don&apos;t need to implement support for all the curves it contains, only one. The best choice would be the fastest one as the overall security of the recursive snark do not depends on which curve the verification is made.

Proper benchmarks will be done in order to make this choice and to price the operations in gas.

## Test Cases

## References

* *Eli-Ben-Sasson, Alessandro Chiesa, Eran Tromer, Madars Virza, [BCTV14], April 28, 2015, Scalable Zero Knowledge via Cycles of Elliptic Curves : https://eprint.iacr.org/2014/595.pdf*
* *Alessandro Chiesa, Lynn Chua, Matthew Weidner, [CCW18], November 5, 2018, On cycles of pairing-friendly elliptic curves : https://arxiv.org/pdf/1803.02067.pdf*

## Implementation

* [go-boojum](https://github.com/AlexandreBelling/go-boojum) : A PoC demo of an application of recursive SNARKs
* [libff](https://github.com/scipr-lab/libff) : a C++ library for finite fields and elliptic curves
* [coda](https://github.com/CodaProtocol/coda) : a new cryptocurrency protocol with a lightweight, constant sized blockchain.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 31 Mar 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1895</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1895</guid>
      </item>
    
      <item>
        <title>Add `blockHash` to defaultBlock methods</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-1898-add-blockhash-option-to-json-rpc-methods-that-currently-support-defaultblock-parameter/11757</comments>
        
        <description>## Abstract

For JSON-RPC methods which currently accept a default block parameter, additionally allow the parameter to be a block hash.

This EIP can be considered a generalization of [EIP-234](/EIPs/EIPS/eip-234). It would enable clients to unambiguously specify the block they want to query for certain JSON-RPC methods, even if the block is not in the canonical chain. This allows clients to maintain a coherent picture of blockchain state that they are interested in, even in the presence of reorgs, without requiring that the node maintain a persistent connection with the client or store any client-specific state.

## Specification

The following JSON-RPC methods are affected:

- `eth_getBalance`
- `eth_getStorageAt`
- `eth_getTransactionCount`
- `eth_getCode`
- `eth_call`
- `eth_getProof`

The following options, quoted from the Ethereum JSON-RPC spec, are currently possible for the defaultBlock parameter:

&gt; - HEX String - an integer block number
&gt; - String &quot;earliest&quot; for the earliest/genesis block
&gt; - String &quot;latest&quot; - for the latest canonical block
&gt; - String &quot;pending&quot; - for the pending state/transactions
&gt; - String &quot;safe&quot; - for the most recent safe block
&gt; - String &quot;finalized&quot; - for the most recent finalized block

Since there is no way to clearly distinguish between a DATA parameter and a QUANTITY parameter, this EIP proposes a new scheme for the block parameter. The following option is additionally allowed:

- OBJECT
  - `blockNumber`: QUANTITY - a block number
  - `blockHash`: DATA - a block hash

If the block is not found, the callee SHOULD raise a JSON-RPC error (the recommended error code is `-32001: Resource not found`).

If the tag is `blockHash`, an additional boolean field may be supplied to the block parameter, `requireCanonical`, which defaults to `false` and defines whether the block must be a canonical block according to the callee. If `requireCanonical` is `false`, the callee should raise a JSON-RPC error only if the block is not found (as described above). If `requireCanonical` is `true`, the callee SHOULD additionally raise a JSON-RPC error if the block is not in the canonical chain (the recommended error code is `-32000: Invalid input` and in any case should be different than the error code for the block not found case so that the caller can distinguish the cases). The block-not-found check SHOULD take precedence over the block-is-canonical check, so that if the block is not found the callee raises block-not-found rather than block-not-canonical.

To maintain backwards compatibility, the block number MAY be specified either as a hex string or using the new block parameter scheme. In other words, the following are equivalent for the default block parameter:

- `&quot;earliest&quot;`
- `&quot;0x0&quot;`
- `{ &quot;blockNumber&quot;: &quot;0x0&quot; }`
- `{ &quot;blockHash&quot;: &quot;0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3&quot; }` (hash of the genesis block on the Ethereum main chain)
- `{ &quot;blockHash&quot;: &quot;0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3&quot;, &quot;requireCanonical&quot;: true }`
- `{ &quot;blockHash&quot;: &quot;0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3&quot;, &quot;requireCanonical&quot;: false }`

## Rationale

Currently, the state-querying JSON-RPC methods specified above have no option to unambiguously specify which block to query the state for. This can cause issues for applications which need to make multiple calls to the RPC. For instance, a wallet which just executed a transfer may want to display the balances of both the sender and recipient. If there is a re-org in between when the balance of the sender is queried via `eth_getBalance` and when the balance of the recipient is queried, the balances may not reconcile. As a slightly more complicated example, the UI for a decentralized exchange (which hosts orders on-chain) may walk a list of orders by calling `eth_call` for each of them to get the order data. Another type of use case is where an application needs to make a decision based on multiple pieces of state, e.g. a payout predicated on simultaneous ownership of two NFTs.

In order to ensure that the state is coherent (i.e., `eth_call` was called with exactly the same block for every call), the application may currently use one of several strategies:

- Decide on a block number to use (e.g., the latest block number known to the application). After each `eth_call` using that block number, call `eth_getBlockByNumber`, also with that block number. If the block hash does not match the known hash for that block number, rollback the current activity and retry from the beginning. This adds `O(n)` invocations as baseline overhead and another `O(n)` invocations for every retry needed. Moreover, there is no way to detect the (unlikely but possible) case that the relevant block was reorged out before `eth_call`, and then reorged back in before `eth_getBlockByNumber`.
- Rely on logs, which *can* be queried unambiguously thanks to the `blockHash` parameter. However, this requires semantic support from the smart contract; if the smart contract does not emit appropriate events, the client will not be able to reconstruct the specific state it is interested in.
- Rely on non-standard extensions like `parity_subscribe`. This requires a persistent connection between the client and node (via IPC or websockets), increases coupling between the client and the node, and cannot handle use cases where there are dependencies between invocations of `eth_call`, for example, walking a linked list.

Allowing `eth_call` and friends to unambiguously specify the block to be queried give the application developer a robust and intuitive way to solve these problems. Multiple sequential queries will query the same state, enabling the application developer to not worry about inconsistencies in their view of the blockchain state.

## Backwards Compatibility

Backwards compatible.

## Test Cases

- `eth_getStorageAt [ &quot;0x&lt;address&gt;&quot;, { &quot;blockNumber&quot;: &quot;0x0&quot; }` -&gt; return storage at given address in genesis block
- `eth_getStorageAt [ &quot;0x&lt;address&gt;&quot;, { &quot;blockHash&quot;: &quot;0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3&quot; }` -&gt; return storage at given address in genesis block
- `eth_getStorageAt [ &quot;0x&lt;address&gt;&quot;, { &quot;blockHash&quot;: &quot;0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3&quot;, &quot;requireCanonical&quot;: false }` -&gt; return storage at given address in genesis block
- `eth_getStorageAt [ &quot;0x&lt;address&gt;&quot;, { &quot;blockHash&quot;: &quot;0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3&quot;, &quot;requireCanonical&quot;: true }` -&gt; return storage at given address in genesis block
- `eth_getStorageAt [ &quot;0x&lt;address&gt;&quot;, { &quot;blockHash&quot;: &quot;0x&lt;non-existent-block-hash&gt;&quot; }` -&gt; raise block-not-found error
- `eth_getStorageAt [ &quot;0x&lt;address&gt;&quot;, { &quot;blockHash&quot;: &quot;0x&lt;non-existent-block-hash&gt;&quot;, &quot;requireCanonical&quot;: false }` -&gt; raise block-not-found error
- `eth_getStorageAt [ &quot;0x&lt;address&gt;&quot;, { &quot;blockHash&quot;: &quot;0x&lt;non-existent-block-hash&gt;&quot;, &quot;requireCanonical&quot;: true }` -&gt; raise block-not-found error
- `eth_getStorageAt [ &quot;0x&lt;address&gt;&quot;, { &quot;blockHash&quot;: &quot;0x&lt;non-canonical-block-hash&gt;&quot; }` -&gt; return storage at given address in specified block
- `eth_getStorageAt [ &quot;0x&lt;address&gt;&quot;, { &quot;blockHash&quot;: &quot;0x&lt;non-canonical-block-hash&gt;&quot;, &quot;requireCanonical&quot;: false }` -&gt; return storage at given address in specified block
- `eth_getStorageAt [ &quot;0x&lt;address&gt;&quot;, { &quot;blockHash&quot;: &quot;0x&lt;non-canonical-block-hash&gt;&quot;, &quot;requireCanonical&quot;: true }` -&gt; raise block-not-canonical error

## Security Considerations

None


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 01 Apr 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1898</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1898</guid>
      </item>
    
      <item>
        <title>dType - Decentralized Type System for EVM</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1882</comments>
        
        <description>## Simple Summary

The EVM and related languages such as Solidity need consensus on an extensible Type System in order to further evolve into the Singleton Operating System (The World Computer).

## Abstract

We are proposing a decentralized Type System for Ethereum, to introduce data definition (and therefore ABI) consistency. This ERC focuses on defining an on-chain Type Registry (named `dType`) and a common interface for creating types, based on `struct`s.


## Motivation

In order to build a network of interoperable protocols on Ethereum, we need data standardization, to ensure a smooth flow of on-chain information. Off-chain, the Type Registry will allow a better analysis of blockchain data (e.g. for blockchain explorers) and creation of smart contract development tools for easily using existing types in a new smart contract.

However, this is only the first phase. As defined in this document and in the future proposals that will be based on this one, we are proposing something more: a decentralized Type System with Data Storage - [ERC-2158](https://github.com/ethereum/EIPs/pull/2158). In addition, developers can create libraries of `pure` functions that know how to interact and modify the data entries - [dType Functions Extension](https://github.com/ethereum/EIPs/issues/1921). This will effectively create the base for a general functional programming system on Ethereum, where developers can use previously created building blocks.

To summarize:

* We would like to have a good decentralized medium for integrating all Ethereum data, and relationships between the different types of data. Also, a way to address the behavior related to each data type.
* Functional programming becomes easier. Functions like `map`, `reduce`, `filter`, are implemented by each type library.
* Solidity development tools could be transparently extended to include the created types (For example in IDEs like Remix). At a later point, the EVM itself can have precompiled support for these types.
* The system can be easily extended to types pertaining to other languages. (With type definitions in the source (Swarm stored source code in the respective language))
* The dType database should be part of the System Registry for the Operating System of The World Computer


## Specification

The Type Registry can have a governance protocol for its CRUD operations. However, this, and other permission guards are not covered in this proposal.

### Type Definition and Metadata

The dType registry should support the registration of Solidity&apos;s elementary and complex types. In addition, it should also support contract events definitions. In this EIP, the focus will be on describing the minimal on-chain type definition and metadata needed for registering Solidity user-defined types.

#### Type Definition: TypeLibrary

A type definition consists of a type library containing:
- the nominal `struct` used to define the type
- additional functions:
  - `isInstanceOf`: checks whether a given variable is an instance of the defined type. Additional rules can be defined for each type fields, e.g. having a specific range for a `uint16 amount`.
  - provide HOFs such as `map`, `filter`, `reduce`
  - `structureBytes` and `destructureBytes`: provide type structuring and destructuring. This can be useful for low-level calls or assembly code, when importing contract interfaces is not an efficient option. It can also be used for type checking.

A simple example is:

```solidity
pragma solidity ^0.5.0;
pragma experimental ABIEncoderV2;

library myBalanceLib {

    struct myBalance {
        string accountName;
        uint256 amount;
    }

    function structureBytes(bytes memory data) pure public returns(myBalance memory balance)

    function destructureBytes(myBalance memory balance) pure public returns(bytes memory data)

    function isInstanceOf(myBalance memory balance) pure public returns(bool isInstance)

    function map(
        address callbackAddr,
        bytes4 callbackSig,
        myBalance[] memory balanceArr
    )
        view
        internal
        returns (myBalance[] memory result)
}
```

Types can also use existing types in their composition. However, this will always result in a directed acyclic graph.

```solidity
library myTokenLib {
    using myBalanceLib for myBalanceLib.myBalance;

    struct myToken {
        address token;
        myBalanceLib.myBalance;
    }
}
```

#### Type Metadata: dType Registry

Type metadata will be registered on-chain, in the dType registry contract. This consists of:
- `name` - the type&apos;s name, as it would be used in Solidity; it can be stored as a `string` or encoded as `bytes`. The name can have a human-readable part and a version number.
- `typeChoice` - used for storing additional ABI data that differentiate how types are handled on and off chain. It is defined as an `enum` with the following options: `BaseType`, `PayableFunction`, `StateFunction`, `ViewFunction`, `PureFunction`, `Event`
- `contractAddress` - the Ethereum `address` of the `TypeRootContract`. For this proposal, we can consider the Type Library address as the `TypeRootContract`. Future EIPs will make it more flexible and propose additional TypeStorage contracts that will modify the scope of `contractAddress` - [ERC-2158](https://github.com/ethereum/EIPs/pull/2158).
- `source` - a `bytes32` Swarm hash where the source code of the type library and contracts can be found; in future EIPs, where dType will be extended to support other languages (e.g. JavaScript, Rust), the file identified by the Swarm hash will contain the type definitions in that language.
- `types` - metadata for subtypes: the first depth level internal components. This is an array of objects (`structs`), with the following fields:
  - `name` - the subtype name, of type `string`, similar to the above `name` definition
  - `label` - the subtype label
  - `dimensions` - `string[]` used for storing array dimensions. E.g.:
    - `[]` -&gt; `TypeA`
    - `[&quot;&quot;]` -&gt; `TypeA[]`
    - `[&quot;2&quot;]` -&gt; `TypeA[2]`
    - `[&quot;&quot;,&quot;&quot;]` -&gt; `TypeA[][]`
    - `[&quot;2&quot;,&quot;3&quot;]` -&gt; `TypeA[2][3]`

Examples of metadata, for simple, value types:
```javascript
{
  &quot;contractAddress&quot;: &quot;0x0000000000000000000000000000000000000000&quot;,
  &quot;typeChoice&quot;: 0,
  &quot;source&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
  &quot;name&quot;: &quot;uint256&quot;,
  &quot;types&quot;: []
}

{
  &quot;contractAddress&quot;: &quot;0x0000000000000000000000000000000000000000&quot;,
  &quot;typeChoice&quot;: 0,
  &quot;source&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
  &quot;name&quot;: &quot;string&quot;,
  &quot;types&quot;: []
}
```

Composed types can be defined as:
```javascript
{
  &quot;contractAddress&quot;: &quot;0x105631C6CdDBa84D12Fa916f0045B1F97eC9C268&quot;,
  &quot;typeChoice&quot;: 0,
  &quot;source&quot;: &lt;a SWARM hash for type source code files&gt;,
  &quot;name&quot;: &quot;myBalance&quot;,
  &quot;types&quot;: [
    {&quot;name&quot;: &quot;string&quot;, &quot;label&quot;: &quot;accountName&quot;, dimensions: []},
    {&quot;name&quot;: &quot;uint256&quot;, &quot;label&quot;: &quot;amount&quot;, dimensions: []}
  ]
}
```

Composed types can be further composed:
```javascript
{
  &quot;contractAddress&quot;: &quot;0x91E3737f15e9b182EdD44D45d943cF248b3a3BF9&quot;,
  &quot;typeChoice&quot;: 0,
  &quot;source&quot;: &lt;a SWARM hash for type source code files&gt;,
  &quot;name&quot;: &quot;myToken&quot;,
  &quot;types&quot;: [
    {&quot;name&quot;: &quot;address&quot;, &quot;label&quot;: &quot;token&quot;, dimensions: []},
    {&quot;name&quot;: &quot;myBalance&quot;, &quot;label&quot;: &quot;balance&quot;, dimensions: []}
  ]
}
```

`myToken` type will have the final data format: `(address,(string,uint256))` and a labeled format: `(address token, (string accountName, uint256 amount))`.

##### dType Registry Data Structures and Interface

To store this metadata, the dType registry will have the following data structures:

```solidity
enum TypeChoices {
    BaseType,
    PayableFunction,
    StateFunction,
    ViewFunction,
    PureFunction,
    Event
}

struct dTypes {
    string name;
    string label;
    string[] dimensions;
}

struct dType {
    TypeChoices typeChoice;
    address contractAddress;
    bytes32 source;
    string name;
    dTypes[] types;
}

```

For storage, we propose a pattern which isolates the type metadata from additional storage-specific data and allows CRUD operations on records.

```solidity
// key: identifier
mapping(bytes32 =&gt; Type) public typeStruct;

// array of identifiers
bytes32[] public typeIndex;

struct Type {
  dType data;
  uint256 index;
}
```

Note that we are proposing to define the type&apos;s primary identifier, `identifier`, as `keccak256(abi.encodePacked(name))`. If the system is extended to other programming languages, we can define `identifier` as `keccak256(abi.encodePacked(language, name))`.
Initially, single word English names can be disallowed, avoiding name squatting.


The dType registry interface is:

```solidity
import &apos;./dTypeLib.sol&apos;;
interface dType {
    event LogNew(bytes32 indexed identifier, uint256 indexed index);
    event LogUpdate(bytes32 indexed identifier, uint256 indexed index);
    event LogRemove(bytes32 indexed identifier, uint256 indexed index);

    function insert(dTypeLib.dType calldata data) external returns (bytes32 identifier);

    function remove(bytes32 identifier) external returns(uint256 index);

    function count() external view returns(uint256 counter);

    function getTypeIdentifier(string memory name) pure external returns (bytes32 identifier);

    function getByIdentifier(bytes32 identifier) view external returns(dTypeLib.dType memory dtype);

    function get(string memory name) view external returns(dTypeLib.dType memory dtype);

    function isRegistered(bytes32 identifier) view external returns(bool registered);
}
```

**Notes:**

To ensure backward compatibility, we suggest that updating types should not be supported.

The `remove` function can also be removed from the interface, to ensure immutability. One reason for keeping it would be clearing up storage for types that are not in use or have been made obsolete. However, this can have undesired effects and should be accompanied by a solid permissions system, testing and governance process. This part will be updated when enough feedback has been received.

## Rationale

The Type Registry must store the minimum amount of information for rebuilding the type ABI definition. This allows us to:
* support on-chain interoperability
* decode blockchain side effects off-chain (useful for block explorers)
* allow off-chain tools to cache and search through the collection (e.g. editor plugin for writing typed smart contracts)

There is one advantage that has become clear with the emergence of global operating systems, like Ethereum: we can have a global type system through which the system’s parts can interoperate. Projects should agree on standardizing types and a type registry, continuously working on improving them, instead of creating encapsulated projects, each with their own types.

The effort of having consensus on new types being added or removing unused ones is left to the governance system.

After the basis of such a system is specified, we can move forward to building a static type checking system at compile time, based on the type definitions and rules stored in the dType registry.

The Type Library must express the behavior strictly pertinent to its defined type. Additional behavior, required by various project&apos;s business logic can be added later, through libraries containing functions that handle the respective type. These can also be registered in dType, but will be detailed in a future ERC.

This is an approach that will separate definitions from stored data and behavior, allowing for easier and more secure fine-grained upgrades.

## Backwards Compatibility

This proposal does not affect extant Ethereum standards or implementations. It uses the present experimental version of ABIEncoderV2.

## Test Cases

Will be added.

## Implementation

An in-work implementation can be found at https://github.com/pipeos-one/dType/tree/master/contracts/contracts.
This proposal will be updated with an appropriate implementation when consensus is reached on the specifications.

A video demo of the current implementation (a more extended version of this proposal) can be seen at https://youtu.be/pcqi4yWBDuQ.


## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 28 Mar 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1900</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1900</guid>
      </item>
    
      <item>
        <title>Add OpenRPC Service Discovery To JSON-RPC Services</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1902</comments>
        
        <description>## Abstract
### What is this?

This is a proposal to add [OpenRPC](https://github.com/open-rpc/spec) support to existing and future JSON-RPC services by adding the method [`rpc.discover`](https://github.com/open-rpc/spec#service-discovery-method) to the projects [JSON-RPC](https://www.jsonrpc.org/specification) APIs, enabling automation and tooling.

The OpenRPC Document and generated Documentation that specifies all the methods an EVM-based blockchain should implement can be found [here](https://github.com/etclabscore/ethereum-json-rpc-specification).

This was first proposed [here as an ECIP](https://github.com/etclabscore/ECIPs/blob/master/ECIPs/ecip-1053.md), but the benefits of this kind of tooling is apparent across Bitcoin, Ethereum Classic, Ethereum and other JSON-RPC accessible blockchains.

## Motivation

Although [EIP-1474](/EIPs/EIPS/eip-1474) outlines a JSON-RPC specification. Ethereum still lacks a machine-readable JSON-RPC Specification that can be used as the industry standard for tooling. This proposal attempts to standardize such a specification in a way that is versionable, and both human and machine readable.

Ethereum clients can expose RPC endpoints with different method signatures and cause compatibility issues between clients.

Developers need a reliable developer experience, and an industry standard way to describe Ethereum JSON-RPC 2.0 APIs.

## Specification

### What is OpenRPC?

The [OpenRPC](https://github.com/open-rpc/spec) Specification defines a standard, programming language-agnostic interface description for [JSON-RPC 2.0](https://www.jsonrpc.org/specification) APIs, which allows both humans and computers to discover and understand the capabilities of a service without requiring access to source code, additional documentation, or inspection of network traffic. When properly defined via OpenRPC, a consumer can understand and interact with the remote service with a minimal amount of implementation logic, and share these logic patterns across use cases. Similar to what interface descriptions have done for lower-level programming, the OpenRPC Specification removes guesswork in calling a service.

##### Structure

This is the structure of an OpenRPC Document:

![openrpc-spec-structure](/EIPs/assets/eip-1901/OpenRPC_structure.png)

JSON-RPC APIs can support the OpenRPC specification by implementing a service discovery method that will return the [OpenRPC document](https://github.com/open-rpc/spec#openrpc-document) for the JSON-RPC API. The method MUST be named `rpc.discover`. The `rpc.` prefix is a reserved method prefix for [JSON-RPC 2.0 Specification](https://www.jsonrpc.org/specification) system extensions.

### Use Case

This is the vision for the use case of OpenRPC and how it would relate to a client implementation like multi-geth:

![MultGethRpc-usecase](/EIPs/assets/eip-1901/multi-geth-use-case.png)

## Rationale

### Why would we do this?
Services need to figure out how to talk to each other. If we really want to build the next generation of automation, then having up to date libraries, documented APIs, and modern tools are going to provide easy discovery, on-boarding, and enable end user and developer interaction.

Use cases for machine-readable [JSON-RPC 2.0](https://www.jsonrpc.org/specification) API definition documents include, but are not limited to:

- A common vocabulary and document will keep developers, testers, architects, and technical writers all in sync.
- Server stubs/skeletons generated in many languages
- Clients generated in many languages
- Mock Server generated in many languages
- Tests generated in many languages
- Documentation Generation

### Alternative

[OpenRPC](https://github.com/open-rpc/spec) documents just describe [JSON-RPC](https://www.jsonrpc.org/specification) APIs services, and are represented in JSON format. These documents may be produced and served statically OR generated dynamically from an application and returned via the [`rpc.discover`](https://github.com/open-rpc/spec#service-discovery-method) method. This gives projects and communities the opportunity to adopt tools, documentation, and clients outlined in the [etclabscore/ethereum-json-rpc-specification](/EIPs/EIPS/eip-1474) before the [`rpc.discover`](https://github.com/open-rpc/spec#service-discovery-method) method is implemented for a particular client.

## Implementation

- [Multi-Geth OpenRPC Discovery](https://github.com/multi-geth/multi-geth#openrpc-discovery)

### Tooling

#### Interactive Documentation Playground

You can view the interactive documentation [here](https://playground.open-rpc.org/?schemaUrl=https://raw.githubusercontent.com/etclabscore/ethereum-json-rpc-specification/master/openrpc.json). 

**OR**

Using `rpc.discover` via multi-geth, the playground can discover and display the documentation for the Ethereum JSON-RPC API:

![eth-playground-openrpc](/EIPs/assets/eip-1901/eth-playground-openrpc.gif)


#### Generated Client

The [clients](https://github.com/etclabscore/ethereum-json-rpc-specification#clients) are generated from the OpenRPC Document openrpc.json outlined in this EIP, and can be used as an alternative to web3.js or ethers.js but for various languages:

![eth-generated-client-openrpc](/EIPs/assets/eip-1901/eth-generated-client-openrpc.gif)

#### Mock Server

The [OpenRPC mock server](https://github.com/open-rpc/mock-server) provides a mock server for any given OpenRPC Document which allows testing without booting up a real network.

![inspector-mock-server-openrpc](/EIPs/assets/eip-1901/inspector-mock-server-openrpc.png)

## Resources

- [Multi-Geth OpenRPC Discovery](https://github.com/multi-geth/multi-geth#openrpc-discovery)
- [EDCON 2019 talk on OpenRPC and The Future of JSON-RPC Tooling](https://www.youtube.com/watch?v=UgSPMZ9FQ4Q)
- [etclabscore/ethereum-json-rpc-specification](https://github.com/etclabscore/ethereum-json-rpc-specification)
- [open-rpc.org](https://open-rpc.org)

## Copyright

 Copyright and related rights waived via [CC0](/EIPs/LICENSE).</description>
        <pubDate>Mon, 25 Feb 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1901</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1901</guid>
      </item>
    
      <item>
        <title>dType Functions Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1921</comments>
        
        <description>## Simple Summary
In the context of dType, the Decentralized Type System described in [EIP-1900](/EIPs/EIPS/eip-1900), we are proposing to add support for registering functions (with a preference for `pure` and `view`) in the dType Registry.

## Abstract

This proposal is part of a series of EIPs focused on expanding the concept of a Decentralized Type System, as explained in [EIP-1900](/EIPs/EIPS/eip-1900).
The current EIP specifies the data definitions and interfaces needed to support registering individual smart contract functions, as entries in the dType Registry.

## Motivation

In order to evolve the EVM into a Singleton Operating System, we need a way to register, find and address contract functions that we want to run in an automated way.
This implies having access to all the data needed to run the function inside the EVM.

Aside from the above motivation, there are also near future benefits for this proposal. Having a globally available, non-custodial functions registry, will democratize the development of tools, such as those targeting: blockchain data analysis (e.g. block explorers), smart contract IDEs, security analysis of smart contracts.

Registering new smart contract functions can be done through the same consensus mechanism as [EIP-1900](/EIPs/EIPS/eip-1900) mentions, in order to avoid burdening the chain state with redundant or improper records.


## Specification

This specification targets `pure` and `view` functions.

For each function, we can store:
* `name` - type `string` unique function name, as defined in EIP-1900; required
* `types` - the type data and label of each input, as defined in EIP-1900; required
* `outputs` - the type data and label of each output; required
* `contractAddress` - type `address` - smart contract where the function resides, as defined in EIP-1900; optional for interfaces
* `source` - type `bytes32` - reference to an external file containing the function source code, as defined in EIP-1900; optional

Therefore, this proposal adds `outputs` to the EIP-1900 type registration definition.

An example of a function registration object for the dType registry is:

```
{
    &quot;name&quot;: &quot;setStaked&quot;,
    &quot;types&quot;: [
        {&quot;name&quot;: &quot;TypeA&quot;, &quot;label&quot;: &quot;typeA&quot;, &quot;relation&quot;:0, &quot;dimensions&quot;:[]}
    ],
    &quot;typeChoice&quot;: 4,
    &quot;contractAddress&quot;: &lt;address of the deployed smart contract where the function is defined&gt;,
    &quot;source&quot;: &lt;bytes32 hash for referencing source files&gt;,
    &quot;outputs&quot;: [
        {&quot;name&quot;: &quot;TypeB&quot;, &quot;label&quot;: &quot;typeB&quot;, &quot;relation&quot;:0, &quot;dimensions&quot;:[]}
    ]
}
```

The above object will be passed to `&lt;dType registry&gt;.insert({...})`

An additional `setOutputs` function is proposed for the dType registry:

```
function setOutputs(
    bytes32 identifier,
    dTypes[] memory outputs
)
    public
```

- `identifier` - type `bytes32`, the type&apos;s identifier, as defined in EIP-1900
- `outputs` - type `dTypes`, as defined in EIP-1900

### Implementation Suggestions


In the dType registry implementation, `outputs` can be stored in a `mapping`:

```
mapping(bytes32 =&gt; dTypes[]) public outputs;
```

## Rationale


The suggestion to treat each `pure` or `view` function as a separate entity instead of having a contract-based approach allows us to:
* have a global context of readily available functions
* scale designs through functional programming patterns rather than contract-encapsulated logic (which can be successfully used to scale development efforts independently)
* bidirectionally connect functions with the types they use, making automation easier
* cherry-pick functions from already deployed contracts if the other contract functions do not pass community consensus
* have scope-restricted improvements - instead of redeploying entire contracts, we can just redeploy the new function versions that we want to be added to the registry
* enable fine-grained auditing of individual functions, for the common good
* enable testing directly on a production chain, without state side-effects

The proposal to store the minimum ABI information on-chain, for each function, allows us to:
* enable on-chain automation (e.g. function chaining and composition)
* be backward compatible in case the function signature format changes (e.g. from `bytes4` to `bytes32`): multiple signature calculation functions can be registered with dType. Examples:

```
function getSignatureBytes4(bytes32 identifier)
    view
    public
    returns (bytes4 signature)

function getSignatureBytes32(bytes32 identifier)
    view
    public
    returns (bytes32 signature)
```

- `identifier` - the type&apos;s identifier, as defined in EIP-1900
- `signature` - the function&apos;s signature


Concerns about this design might be:
* redundancy of storing `contractAddress` for each function that is part of the same contract

We think that state/storage cost will be compensated through DRYness across the chain, due to reusing types and functions that have already been registered and are now easy to find. Other state/storage cost calculations will be added once the specification and implementation are closer to be finalized.


Note that the input and output types are based on types that have already been registered. This lowers the amount of ABI information needed to be stored for each function and enables developers to aggregate and find functions that use the same types for their I/O. This can be a powerful tool for interoperability and smart contract composition.


## Backwards Compatibility

This proposal does not affect extant Ethereum standards or implementations. Registering functions for existing contract deployments should be fully supported.

## Test Cases

Will be added.


## Implementation

In-work implementation examples can be found at https://github.com/pipeos-one/dType.
This proposal will be updated with an appropriate implementation when consensus is reached on the specifications.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 06 Apr 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1921</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1921</guid>
      </item>
    
      <item>
        <title>zk-SNARK Verifier Standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1922</comments>
        
        <description>## Simple Summary

A standard interface for &quot;Verifier&quot; contracts which verify zk-SNARKs.

## Abstract
The following standard allows for the implementation of a standard contract API for the verification of zk-SNARKs (&quot;Zero-Knowledge Succinct Non-Interactive Arguments of Knowledge&quot;), also known as &quot;proofs&quot;, &quot;arguments&quot;, or &quot;commitments&quot;.

This standard provides basic functionality to load all necessary parameters for the verification of any zk-SNARK into a verifier contract, so that the proof may ultimately return a `true` or `false` response; corresponding to whether it has been verified or not verified.

## Motivation
zk-SNARKs are a promising area of interest for the Ethereum community. Key applications of zk-SNARKs include:
- Private transactions
- Private computations
- Improved transaction scaling through proofs of &quot;bundled&quot; transactions

A standard interface for verifying all zk-SNARKs will allow applications to more easily implement private transactions, private contracts, and scaling solutions; and to extract and interpret the limited information which gets emitted during zk-SNARK verifications.

This standard was initially proposed by EY, and was inspired in particular by the requirements of businesses wishing to keep their agreements, transactions, and supply chain activities confidential—all whilst still benefiting from the commonly cited strengths of blockchains and smart contracts.

:warning: TODO: Explain the benefits to and perspective of a consumer of information. I.e. the thing that interfaces with the standard verifier.

## Specification
The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

Terminology in this specification is used consistently with libsnark, as provided in that project&apos;s README.

* Adhering Contract — A Verifier contract which adheres to this specification.
* Arithmetic circuit: An abstraction of logical statements into addition and multiplication gates.
* Public Inputs: often denoted as a vector &apos;x&apos; in zk-SNARKs literature, and denoted `inputs` in this interface. An arithmetic circuit can be thought of as taking two parameters; the Public Inputs, &apos;x&apos;, and a secret &apos;witness&apos;, &apos;w&apos;. This interface standardises functions which can load the `inputs` into an Adhering Contract.
* Proof: A &apos;prover&apos; who wants to &apos;prove&apos; knowledge of some secret witness &apos;w&apos; (which satisfies an arithmetic circuit), generates a `proof` from: the circuit&apos;s Proving Key; their secret witness &apos;w&apos;; and its corresponding Public Inputs &apos;x&apos;. Together, a pair `(proof, inputs)` of satisfying `inputs` and their corresponding `proof` forms a zk-SNARK.
* Verification Key: A &apos;trusted setup&apos; calculation creates both a public &apos;Proving Key&apos; and a public &apos;Verification Key&apos; from an arithmetic circuit. This interface does not provide a method for loading a Verification Key onto the blockchain. An Adhering Contract SHALL be able to accept arguments of knowledge (`(proof, inputs)` pairs) for at least one Verification Key. We shall call such Verification Keys &apos;in-scope&apos; Verification Keys. An Adhering Contract MUST be able to interpret unambiguously a unique `verificationKeyId` for each of its &apos;in-scope&apos; Verification Keys.

**Every ERC-XXXX compliant verifier contract must implement the `ERCXXXX` and `ERC165` interfaces** (subject to &quot;caveats&quot; below):


```solidity
pragma solidity ^0.5.6;

/// @title EIP-XXXX zk-SNARK Verifier Standard
/// @dev See https://github.com/EYBlockchain/zksnark-verifier-standard
///  Note: the ERC-165 identifier for this interface is 0xXXXXXXXX.
/// ⚠️ TODO: Calculate interface identifier
interface EIPXXXX /* is ERC165 */ {
    /// @notice Checks the arguments of Proof, through elliptic curve
    ///  pairing functions.
    /// @dev
    ///  MUST return `true` if Proof passes all checks (i.e. the Proof is
    ///  valid).
    ///  MUST return `false` if the Proof does not pass all checks (i.e. if the
    ///  Proof is invalid).
    /// @param proof A zk-SNARK.
    /// @param inputs Public inputs which accompany Proof.
    /// @param verificationKeyId A unique identifier (known to this verifier
    ///  contract) for the Verification Key to which Proof corresponds.
    /// @return result The result of the verification calculation. True
    ///  if Proof is valid; false otherwise.
    function verify(uint256[] calldata proof, uint256[] calldata inputs, bytes32 verificationKeyId) external returns (bool result);
}
```
### Interface
``` solidity
interface ERC165 {
    /// @notice Query if a contract implements an interface
    /// @param interfaceID The interface identifier, as specified in ERC-165
    /// @dev Interface identification is specified in ERC-165. This function
    ///  uses less than 30,000 gas.
    /// @return `true` if the contract implements `interfaceID` and
    ///  `interfaceID` is not 0xffffffff, `false` otherwise
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
```

## Rationale

### Taxonomy

⚠️ TODO: Add a specific reference to libsnark here, explaining the choice of variable names.

:warning: TODO: Explain how _C_ may not necessarily be a satisfiable arithmetic circuit of logical statements. As current, this is a limitation to certain kinds of SNARKS. Whereas the source references also mention polynomials, and other applications.

_C_ — A satisfiable arithmetic circuit abstraction of logical statements.

_lambda​_ - A random number, generated at the &apos;setup&apos; phase - commonly referred to as &apos;toxic waste&apos;, because knowledge of _lambda​_ would allow an untrustworthy party to create &apos;false&apos; proofs which would verify as &apos;true&apos;. _lambda​_ must be destroyed.

_pk​_ - The proving key for a particular circuit _C​_.

_vk_ - The verification key for a particular circuit _C_.

Both _pk​_ and _vk​_ are generated as a pair by some function _G​_:
_(pk, vk) = G(lambda, C)​_

Note: _C_ can be represented unambiguously by either of _pk_ or _vk_. In zk-SNARK constructions, _vk_ is much smaller in size than _pk_, so as to enable succinct verification on-chain. Hence, _vk_ is the representative of _C_ that is &apos;known&apos; to the contract. Therefore, we can identify each circuit uniquely through some `verificationKeyId`, where `verificationKeyId` serves as a more succinct mapping to _vk_.

_w_ - A &apos;private witness&apos; string. A private argument to the circuit _C_ known only to the prover, which, when combined with the `inputs` argument _x_, comprises an argument of knowledge which satisfies the circuit _C_.

_x_ or `inputs` - A vector of &apos;Public Inputs&apos;. A public argument to the circuit _C_ which, when combined with the private witness string _w_, comprises an argument of knowledge which satisfies the circuit _C_.

_pi_ or `proof` - an encoded vector of values which represents the &apos;prover&apos;s&apos; &apos;argument of knowledge&apos; of values _w_ and _x_ which satisfy the circuit _C_.
_pi = P(pk, x, w)_.

The ultimate purpose of a Verifier contract, as specified in this EIP, is to verify a proof (of the form _pi​_) through some verification function _V​_.

_V(vk, x, pi) = 1_, if there exists a _w_ s.t. _C(x,w)=1_.
_V(vk, x, pi) = 0_, otherwise.

The `verify()` function of this specification serves the purpose of _V​_; returning either `true` (the proof has been verified to satisfy the arithmetic circuit) or `false` (the proof has not been verified).

### Functions

#### `verify`
The `verify` function forms the crux this standard. The parameters are intended to be as generic as possible, to allow for verification of any zk-SNARK:

- `proof`
  Specified as `uint256[]`.
  `uint256` is the most appropriate type for elliptic curve operations over a finite field. Indeed, this type is used in the predominant &apos;Pairing library&apos; implementation of zk-SNARKs by Christian Reitweissner.
  A one-dimensional dynamic array has been chosen for several reasons:
  - Dynamic: There are several possible methods for producing a zk-SNARK proof, including PGHR13, G16, GM17, and future methods might be developed in future. Although each method may produce differently sized proof objects, a dynamic array allows for these differing sizes.
  - Array: An array has been chosen over a &apos;struct&apos; object, because it is currently easier to pass dynamic arrays between functions in Solidity. Any proof &apos;struct&apos; can be &apos;flattened&apos; to an array and passed to the `verify` function. Interpretation of that flattened array is the responsibility of the implemented body of the function. Example implementations demonstrate that this can be achieved.
  - One-dimensional: A one-dimensional array has been chosen over multi-dimensional array, because it is currently easier to work with one-dimensional arrays in Solidity. Any proof can be &apos;flattened&apos; to a one-dimensional array and passed to the `verify` function. Interpretation of that flattened array is the responsibility of the implemented body of the Adhering Contract. Example implementations demonstrate that this can be achieved.

- `inputs`
  Specified as `uint256[]`.
  `uint256` is the most appropriate type for elliptic curve operations over a finite field. Indeed, this type is used in the predominant &apos;Pairing library&apos; implementation of zk-SNARKs by Christian Reitweissner.
  The number of inputs will vary in size, depending on the number of &apos;public inputs&apos; of the arithmetic circuit being verified against. In a similar vein to the `proof` parameter, a one-dimensional dynamic array is general enough to cope with any set of inputs to a zk-SNARK.

- `verificationKeyId`
  A verification key (referencing a particular arithmetic circuit) only needs to be stored on-chain once. Any proof (relating to the underlying arithmetic circuit) can then be verified against that verification key. Given this, it would be unnecessary (from a &apos;gas cost&apos; point of view) to pass a duplicate of the full verification key to the `verify` function every time a new `(proof, inputs)` pair is passed in. We do however need to tell the Adhering Verifier Contract which verification key corresponds to the `(proof, inputs)` pair being passed in. A `verificationKeyId` serves this purpose - it uniquely represents a verification key as a `bytes32` id. A method for uniquely assigning a `verificationKeyId` to a verification key is the responsibility of the implemented body of the Adhering Contract.


## Backwards Compatibility
- At the time this EIP was first proposed, there was one implementation on the Ethereum main net - deployed by [EY](https://www.ey.com). This was compiled with Solidity 0.4.24 for compatibility with [Truffle](https://github.com/trufflesuite/truffle) but otherwise compatible with this standard, which is presented at the latest current version of Solidity.
- Dr Christian Reitwiessner&apos;s excellent [example](https://gist.github.com/chriseth/f9be9d9391efc5beb9704255a8e2989d) of a Verifier contract and elliptic curve pairing library has been instrumental in the Ethereum community&apos;s experimentation and development of zk-SNARK protocols. Many of the naming conventions of this EIP have been kept consistent with his example.
- Existing zk-SNARK compilers such as [ZoKrates](https://github.com/Zokrates/ZoKrates), which produce &apos;Verifier.sol&apos; contracts, do not currently produce Verifier contracts which adhere to this EIP specification.
  - :warning: TODO: Provide a converter contract or technique which allows ZoKrates verifier.sol contracts to adhere with this EIP.


## Test Cases

Truffle tests of example implementations are included in the test case repository.

⚠️ TODO: Reference specific test cases because there are many currently in the repository.


## Implementations
Detailed example implementations and Truffle tests of these example implementations are included in this repository.

:warning: TODO: Update referenced verifier implementations so that they are ready-to-deploy or reference deployed versions of those implementations. At current, the referenced code specifically states &quot;DO NOT USE THIS IN PRODUCTION&quot;.

:warning: TODO: Provide reference to an implementation which interrogates a standard verifier contract that implements this standard.


## References

:warning: TODO: Update references and confirm that each reference is cited (parenthetical documentation not necessary) in the text.

**Standards**

1. ERC-20 Token Standard. ./eip-20.md

1. ERC-165 Standard Interface Detection. ./eip-165.md
1. ERC-173 Contract Ownership Standard (DRAFT). ./eip-173.md
1. ERC-196 Precompiled contracts for addition and scalar multiplication on the elliptic curve alt_bn128. ./eip-196.md
1. ERC-197 Precompiled contracts for optimal ate pairing check on the elliptic curve alt_bn128. ./eip-197.md
1. Ethereum Name Service (ENS). https://ens.domains
1. RFC 2119 Key words for use in RFCs to Indicate Requirement Levels. https://www.ietf.org/rfc/rfc2119.txt

##### Educational material:  zk-SNARKs
1. Zcash. What are zk-SNARKs? https://z.cash/technology/zksnarks.html
1. Vitalik Buterin. zk-SNARKs: Under the Hood. https://medium.com/@VitalikButerin/zk-snarks-under-the-hood-b33151a013f6
1. Christian Reitweissner. zk-SNARKs in a Nutshell. https://blog.ethereum.org/2016/12/05/zksnarks-in-a-nutshell/
1. Ben-Sasson, Chiesa, Tromer, et. al. Succinct Non-Interactive Zero Knowledge for a von Neumann Architecture. https://eprint.iacr.org/2013/879.pdf

##### Notable applications of zk-SNARKs
 1. EY. Implementation of a business agreement through Token Commitment transactions on the Ethereum mainnet. https://github.com/EYBlockchain/ZKPChallenge
 1. Zcash. https://z.cash
 1. Zcash. How Transactions Between Shielded Addresses Work. https://blog.z.cash/zcash-private-transactions/

##### Notable projects relating to zk-SNARKs
  1. libsnark: A C++ Library for zk-SNARKs (&quot;project README)&quot;. https://github.com/scipr-lab/libsnark
  1. ZoKrates: Scalable Privacy-Preserving Off-Chain Computations. https://www.ise.tu-berlin.de/fileadmin/fg308/publications/2018/2018_eberhardt_ZoKrates.pdf
  1. ZoKrates Project Repository. https://github.com/JacobEberhardt/ZoKrates
  1. Joseph Stockermans. zkSNARKs: Driver&apos;s Ed. https://github.com/jstoxrocky/zksnarks_example
  1. Christian Reitweissner - snarktest.solidity. https://gist.github.com/chriseth/f9be9d9391efc5beb9704255a8e2989d

##### Notable &apos;alternatives&apos; to zk-SNARKs - areas of ongoing zero-knowledge proof research
  1. Vitalik Buterin. STARKs. https://web.archive.org/web/20230425101334/https://vitalik.ca/general/2017/11/09/starks_part_1.html
  1. Bu ̈nz, Bootle, Boneh, et. al. Bulletproofs. https://eprint.iacr.org/2017/1066.pdf
  1. Range Proofs. https://www.cosic.esat.kuleuven.be/ecrypt/provpriv2012/abstracts/canard.pdf
  1. Apple. Secure Enclaves. https://developer.apple.com/documentation/security/certificate_key_and_trust_services/keys/storing_keys_in_the_secure_enclave
  1. Intel Software Guard Extensions. https://software.intel.com/en-us/sgx


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 14 Sep 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1922</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1922</guid>
      </item>
    
      <item>
        <title>zk-SNARK Verifier Registry Standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1923</comments>
        
        <description>## Simple Summary


A standard interface for a &quot;Verifier Registry&quot;&apos;&quot; contract, through which all zk-SNARK verification activity can be registered.

## Abstract
The following standard allows for the implementation of a standard contract API for the registration of zk-SNARKs (&quot;Zero-Knowledge Succinct Non-Interactive Arguments of Knowledge&quot;), also known as &quot;proofs&quot;, &quot;arguments&quot;, or &quot;commitments&quot;.

TODO: Which functionality is exposed in this standard interface?

## Motivation
zk-SNARKs are a promising area of interest for the Ethereum community. Key applications of zk-SNARKs include:
- Private transactions
- Private computations
- Ethereum scaling through proofs of &apos;bundled&apos; transactions

A standard interface for registering all zk-SNARKs will allow applications to more easily implement private transactions, private contracts, and scaling solutions; and to extract and interpret the limited information which gets emitted during zk-SNARK verifications.

:warning: TODO: Explain the motivation for standardizing a registry, other than simply standardizing the verifier interactions.

⚠️ TODO: Explain the benefits to and perspective of a consumer of information. I.e. the thing that interfaces with the standard verifier registry.

## Specification
The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.


```solidity
pragma solidity ^0.5.6;

/// @title EIP-XXXX zk-SNARK Verifier Registry Standard
/// @dev See https://github.com/EYBlockchain/zksnark-verifier-standard
///  Note: the ERC-165 identifier for this interface is 0xXXXXXXXXX.
/// ⚠️ TODO: Set the interface identifier
interface EIP-XXXX /* is ERC165 */ {

  event NewProofSubmitted(bytes32 indexed _proofId, uint256[] _proof, uint64[] _inputs);

  event NewVkRegistered(bytes32 indexed _vkId);

  event NewVerifierContractRegistered(address indexed _contractAddress);

  event NewAttestation(bytes32 indexed _proofId, address indexed _verifier, bool indexed _result);


  function getVk(bytes32 _vkId) external returns (uint256[] memory);

  function registerVerifierContract(address _verifierContract) external returns (bool);

  function registerVk(uint256[] calldata _vk, address[] calldata _verifierContracts) external returns (bytes32);

  function submitProof(uint256[] calldata _proof, uint64[] calldata _inputs, bytes32 _vkId) external returns (bytes32);

  function submitProof(uint256[] calldata _proof, uint64[] calldata _inputs, bytes32 _vkId, address _verifierContract) external returns (bytes32);

  function submitProofAndVerify(uint256[] calldata _proof, uint64[] calldata _inputs, bytes32 _vkId, address _verifierContract) external returns (bytes32);

  function attestProof(bytes32 _proofId, bytes32 _vkId, bool _result) external;

  function attestProofs(bytes32[] calldata _proofIds, bytes32[] calldata _vkIds, bool[] calldata _results) external;

  function challengeAttestation(bytes32 _proofId, uint256[] calldata _proof, uint64[] calldata  _inputs, address _verifierContract) external;

  function createNewVkId(uint256[] calldata _vk) external pure returns (bytes32);

  function createNewProofId(uint256[] calldata _proof, uint64[] calldata _inputs) external pure returns (bytes32);

}
```
### Interface
``` solidity
interface ERC165 {
    /// @notice Query if a contract implements an interface
    /// @param interfaceID The interface identifier, as specified in ERC-165
    /// @dev Interface identification is specified in ERC-165. This function
    ///  uses less than 30,000 gas.
    /// @return `true` if the contract implements `interfaceID` and
    ///  `interfaceID` is not 0xffffffff, `false` otherwise
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
```

## Rationale

⚠️ TODO: Add Rationale section.

### Backwards Compatibility

⚠️ TODO: Add Backwards Compatibility section.

### Test Cases

Truffle tests of example implementations are included in this Repo.

⚠️ TODO: Reference specific test cases because there are many currently in the repository.


## Implementations
Detailed example implementations and Truffle tests of these example implementations are included in this Repo.

⚠️ TODO: Update referenced verifier registry implementations so that they are ready-to-deploy or reference deployed versions of those implementations. At current, the referenced code specifically states &quot;DO NOT USE THIS IN PRODUCTION&quot;.

⚠️ TODO: Provide reference to an implementation which interrogates a standard verifier registry contract that implements this standard.


## References

⚠️ TODO: Update references and confirm that each reference is cited (parenthetical documentation not necessary) in the text.

**Standards**

1. ERC-20 Token Standard. ./eip-20.md

1. ERC-165 Standard Interface Detection. ./eip-165.md
2. ERC-173 Contract Ownership Standard (DRAFT). ./eip-173.md
3. ERC-196 Precompiled contracts for addition and scalar multiplication on the elliptic curve alt_bn128. ./eip-196.md
4. ERC-197 Precompiled contracts for optimal ate pairing check on the elliptic curve alt_bn128. ./eip-197.md
5. Ethereum Name Service (ENS). https://ens.domains
6. RFC 2119 Key words for use in RFCs to Indicate Requirement Levels. https://www.ietf.org/rfc/rfc2119.txt

##### Educational material:  zk-SNARKs

1. Zcash. What are zk-SNARKs? https://z.cash/technology/zksnarks.html
2. Vitalik Buterin. zk-SNARKs: Under the Hood. https://medium.com/@VitalikButerin/zk-snarks-under-the-hood-b33151a013f6
3. Christian Reitweissner. zk-SNARKs in a Nutshell. https://blog.ethereum.org/2016/12/05/zksnarks-in-a-nutshell/
4. Ben-Sasson, Chiesa, Tromer, et. al. Succinct Non-Interactive Zero Knowledge for a von Neumann Architecture. https://eprint.iacr.org/2013/879.pdf

##### Notable applications of zk-SNARKs

1. EY. Implementation of a business agreement through Token Commitment transactions on the Ethereum mainnet. https://github.com/EYBlockchain/ZKPChallenge
2. Zcash. https://z.cash
3. Zcash. How Transactions Between Shielded Addresses Work. https://blog.z.cash/zcash-private-transactions/

##### Notable projects relating to zk-SNARKs

1. libsnark: A C++ Library for zk-SNARKs (&quot;project README)&quot;. https://github.com/scipr-lab/libsnark
2. ZoKrates: Scalable Privacy-Preserving Off-Chain Computations. https://www.ise.tu-berlin.de/fileadmin/fg308/publications/2018/2018_eberhardt_ZoKrates.pdf
3. ZoKrates Project Repository. https://github.com/JacobEberhardt/ZoKrates
4. Joseph Stockermans. zkSNARKs: Driver&apos;s Ed. https://github.com/jstoxrocky/zksnarks_example
5. Christian Reitweissner - snarktest.solidity. https://gist.github.com/chriseth/f9be9d9391efc5beb9704255a8e2989d

##### Notable &apos;alternatives&apos; to zk-SNARKs - areas of ongoing zero-knowledge proof research

1. Vitalik Buterin. STARKs. https://web.archive.org/web/20230425101334/https://vitalik.ca/general/2017/11/09/starks_part_1.html
2. Bu ̈nz, Bootle, Boneh, et. al. Bulletproofs. https://eprint.iacr.org/2017/1066.pdf
3. Range Proofs. https://www.cosic.esat.kuleuven.be/ecrypt/provpriv2012/abstracts/canard.pdf
4. Apple. Secure Enclaves. https://developer.apple.com/documentation/security/certificate_key_and_trust_services/keys/storing_keys_in_the_secure_enclave
5. Intel Software Guard Extensions. https://software.intel.com/en-us/sgx


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 22 Dec 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1923</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1923</guid>
      </item>
    
      <item>
        <title>CALLs with strict gas semantic. Revert if not enough gas available.</title>
        <category>Standards Track/Core</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/1930</comments>
        
        <description>## Simple Summary

Add the ability for smart contract to execute calls with a specific amount of gas. If this is not possible the execution should revert.

## Abstract

The current CALL, DELEGATE_CALL, STATIC_CALL opcode do not enforce the gas being sent, they simply consider the gas value as a maximum. This pose serious problem for applications that require the call to be executed with a precise amount of gas. 

This is for example the case for meta-transaction where the contract needs to ensure the call is executed exactly as the signing user intended. 

But this is also the case for common use cases, like checking &quot;on-chain&quot; if a smart contract support a specific interface (via [EIP-165](/EIPs/EIPS/eip-165) for example).

The solution presented here is to add new call semantic that enforce the amount of gas specified : the call either proceed with the exact amount of gas or do not get executed and the current call revert.


### Specification

There are 2 possibilities

a) one is to add opcode variant that have a stricter gas semantic

b) The other is to consider a specific gas value range (one that have never been used before) to have strict gas semantic, while leaving other values as before

Here are the details description

#### option a)

- add a new variant of the CALL opcode where the gas specified is enforced so that if the gas left at the point of call is not enough to give the specified gas to the destination, the current call revert
- add a new variant of the DELEGATE_CALL opcode where the gas specified is enforced so that if the gas left at the point of call is not enough to give the specified gas to the destination, the current call revert
- add a new variant of the STATIC_CALL opcode where the gas specified is enforced so that if the gas left at the point of call is not enough to give the specified gas to the destination, the current call revert

##### Rational for a)
This solution has the merit to avoid any possibility of old contract be affected by the change. On the other hand it introduce 3 new opcodes. With EIP-1702, we could render the old opcode obsolete though. 

#### option b)

For all opcode that allow to pass gas to another contract, do the following:
- If the most significant bit is one, consider the 31 less significant bit as the amount of gas to be given to the receiving contract in the strict sense. SO like a) if the gas left at the point of call is not enough to give the specified gas to the destination, the current call revert.
- If the 2nd most significant bit is zero, consider the whole value to behave like before, that is, it act as a maximum value, and even if not enough gas is present, the gas that can be given is given to the receiving contract 

##### Rational for b)
This solution relies on the fact that no contract would have given any value bigger or equal to 0x8000000000000000000000000000000000000000000000000000000000000000

Note that solidity for example do not use value like 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF as it is more expensive than passing the gasLeft.

Its main benefit though is that it does not require extra opcodes.

#### strict gas semantic

To be precise, regarding the strict gas semantic, based on [EIP-150](/EIPs/EIPS/eip-150), the current call must revert unless G &gt;= I x 64/63 where G is gas left at the point of call (after deducing the cost of the call itself) and I is the gas specified.

So instead of
```
availableGas = availableGas - base
gas := availableGas - availableGas/64
...
if !callCost.IsUint64() || gas &lt; callCost.Uint64() {
    return gas, nil
}
```
see https://github.com/ethereum/go-ethereum/blob/7504dbd6eb3f62371f86b06b03ffd665690951f2/core/vm/gas.go#L41-L48

we would have
```
availableGas = availableGas - base
gas := availableGas - availableGas/64
if !callCost.IsUint64() || gas &lt; callCost.Uint64() {
    return 0, errNotEnoughGas
}
```

### Rationale

Currently the gas specified as part of these opcodes is simply a maximum value. And due to the behavior of [EIP-150](/EIPs/EIPS/eip-150) it is possible for an external call to be given less gas than intended (less than the gas specified as part of the CALL) while the rest of the current call is given enough to continue and succeed. Indeed since with EIP-150, the external call is given at max  ```G - Math.floor(G/64)``` where G is the gasleft() at the point of the CALL, the rest of the current call is given ```Math.floor(G/64)``` which can be plenty enough for the transaction to succeed. For example, when G = 6,400,000 the rest of the transaction will be given 100,000 gas plenty enough in many case to succeed.

This is an issue for contracts that require external call to only fails if they would fails with enough gas. This requirement is present in smart contract wallet and meta transaction in general, where the one executing the transaction is not the signer of the execution data. Because in such case, the contract needs to ensure the call is executed exactly as the signing user intended.

But this is also true for simple use case, like checking if a contract implement an interface via EIP-165. Indeed as specified by such EIP, the ```supporstInterface``` method is bounded to use 30,000 gas so that it is theoretically possible to ensure that the throw is not a result of a lack of gas. Unfortunately due to how the different CALL opcodes behave contracts can&apos;t simply rely on the gas value specified. They have to ensure by other means that there is enough gas for the call.

Indeed, if the caller do not ensure that 30,000 gas or more is provided to the callee, the callee might throw because of a lack of gas (and not because it does not support the interface), and the parent call will be given up to 476 gas to continue. This would result in the caller interpreting wrongly that the callee is not implementing the interface in question. 

While such requirement can be enforced by checking the gas left according to EIP-150 and the precise gas required before the call (see solution presented in that [bug report](https://web.solidified.io/contract/5b4769b1e6c0d80014f3ea4e/bug/5c83d86ac2dd6600116381f9) or after the call (see the native meta transaction implementation [here](https://github.com/pixowl/thesandbox-contracts/blob/623f4d4ca10644dcee145bcbd9296579a1543d3d/src/Sand/erc20/ERC20MetaTxExtension.sol#L176), it would be much better if the EVM allowed us to strictly specify how much gas is to be given to the CALL so contract implementations do not need to follow [EIP-150](/EIPs/EIPS/eip-150) behavior and the current gas pricing so closely.

This would also allow the behaviour of [EIP-150](/EIPs/EIPS/eip-150) to be changed without having to affect contract that require this strict gas behaviour.

As mentioned, such strict gas behaviour is important for smart contract wallet and meta transaction in general.
The issue is actually already a problem in the wild as can be seen in the case of Gnosis safe which did not consider the behavior of EIP-150 and thus fails to check the gas properly, requiring the safe owners to add otherwise unnecessary extra gas to their signed message to avoid the possibility of losing funds. See https://github.com/gnosis/safe-contracts/issues/100

As for EIP-165, the issue already exists in the example implementation presented in the EIP. Please see the details of the issue [here](https://github.com/ethereum/EIPs/pull/881#issuecomment-491677748)

The same issue exists also on OpenZeppelin implementation, a library used by many. It does not for perform any check on gas before calling ```supportsInterface``` with 30,000 gas (see [here](https://github.com/OpenZeppelin/openzeppelin-solidity/blob/fa004a7f5de572b3dbcde1a8a81f9a87e353e799/contracts/introspection/ERC165Checker.sol#L37) and is thus vulnerable to the issue mentioned.


While such issue can be prevented today by checking the gas with EIP-150 in mind, a solution at the opcode level is more elegant.

Indeed, the two possible ways to currently enforce that the correct amount of gas is sent are as follow :

1) check done before the call 

```
uint256 gasAvailable = gasleft() - E;
require(gasAvailable - gasAvailable / 64  &gt;= `txGas`, &quot;not enough gas provided&quot;)
to.call.gas(txGas)(data); // CALL
```
where E is the gas required for the operation between the call to ```gasleft()``` and the actual call PLUS the gas cost of the call itself.
While it is possible to simply over estimate ```E``` to prevent call to be executed if not enough gas is provided to the current call it would be better to have the EVM do the precise work itself. As gas pricing continue to evolve, this is important to have a mechanism to ensure a specific amount of gas is passed to the call so such mechanism can be used without having to relies on a specific gas pricing.


2) check done after the call:

```
to.call.gas(txGas)(data); // CALL
require(gasleft() &gt; txGas / 63, &quot;not enough gas left&quot;);
```
This solution does not require to compute a ```E``` value and thus do not relies on a specific gas pricing (except for the behaviour of EIP-150) since if the call is given not enough gas and fails for that reason, the condition above will always fail, ensuring the current call will revert.
But this check still pass if the gas given was less AND the external call reverted or succeeded EARLY (so that the gas left after the call &gt; txGas / 63).
This can be an issue if the code executed as part of the CALL is reverting as a result of a check against the gas provided. Like a meta transaction in a meta transaction.

Similarly to the previous solution, an EVM mechanism would be much better.

## Backwards Compatibility

for specification a) : Backwards compatible as it introduce new opcodes.

for specification b) : Backwards compatible as it use value range outside of what is used by existing contract (to be verified)

## Test Cases

## Implementation

None fully implemented yet. But see Specifications for an example in geth.

## References

1. EIP-150, ./eip-150.md

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 10 Apr 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1930</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1930</guid>
      </item>
    
      <item>
        <title>Non-fungible Data Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-non-fungible-data-token/3139</comments>
        
        <description>## Simple Summary

Some NFT use-cases require to have dynamic data associated with a non-fungible token that can change during its lifetime. Examples for dynamic data:
- cryptokitties that can change color
- intellectual property tokens that encode rights holders
- tokens that store data to transport them across chains

The existing metadata standard does not suffice as data can only be set at minting time and not modified later.

## Abstract

Non-fungible tokens (NFTs) are extended with the ability to store dynamic data. A 32 bytes data field is added and a read function allows to access it. The write function allows to update it, if the caller is the owner of the token. An event is emitted every time the data updates and the previous and new value is emitted in it.

## Motivation

The proposal is made to standardize on tokens with dynamic data. Interactions with bridges for side-chains like xDAI or Plasma chains will profit from the ability to use such tokens. Protocols that build on data tokens like [distributed breeding](https://ethresear.ch/t/a-distributed-breeding-function/5264) will be enabled.

## Specification

An extension of [ERC-721](/EIPs/EIPS/eip-721) interface with the following functions and events is suggested:

``` solidity
pragma solidity ^0.5.2;

/**
 * @dev Interface of the ERC1948 contract.
 */
interface IERC1948 {

  /**
   * @dev Emitted when `oldData` is replaced with `newData` in storage of `tokenId`.
   *
   * Note that `oldData` or `newData` may be empty bytes.
   */
  event DataUpdated(uint256 indexed tokenId, bytes32 oldData, bytes32 newData);

  /**
   * @dev Reads the data of a specified token. Returns the current data in
   * storage of `tokenId`.
   *
   * @param tokenId The token to read the data off.
   *
   * @return A bytes32 representing the current data stored in the token.
   */
  function readData(uint256 tokenId) external view returns (bytes32);

  /**
   * @dev Updates the data of a specified token. Writes `newData` into storage
   * of `tokenId`.
   *
   * @param tokenId The token to write data to.
   * @param newData The data to be written to the token.
   *
   * Emits a `DataUpdated` event.
   */
  function writeData(uint256 tokenId, bytes32 newData) external;

}
```

## Rationale

The suggested data field in the NFT is used either for storing data directly, like a counter or address. If more data is required the implementer should fall back to authenticated data structures, like merkle- or patricia-trees.

The proposal for this ERC stems from the [distributed breeding proposal](https://ethresear.ch/t/a-distributed-breeding-function/5264) to allow better integration of NFTs across side-chains. [ost.com](https://ost.com/), [Skale](https://skalelabs.com/), [POA](https://poa.network/), and [LeapDAO](https://leapdao.org/) have been part of the discussion.

## Backwards Compatibility

🤷‍♂️ No related proposals are known to the author, hence no backwards compatibility to consider.

## Test Cases

Simple happy test:

``` javascript
const ERC1948 = artifacts.require(&apos;./ERC1948.sol&apos;);

contract(&apos;ERC1948&apos;, (accounts) =&gt; {
  const firstTokenId = 100;
  const empty = &apos;0x0000000000000000000000000000000000000000000000000000000000000000&apos;;
  const data = &apos;0x0101010101010101010101010101010101010101010101010101010101010101&apos;;
  let dataToken;

  beforeEach(async () =&gt; {
    dataToken = await ERC1948.new();
    await dataToken.mint(accounts[0], firstTokenId);
  });

  it(&apos;should allow to write and read&apos;, async () =&gt; {
    let rsp = await dataToken.readData(firstTokenId);
    assert.equal(rsp, empty);
    await dataToken.writeData(firstTokenId, data);
    rsp = await dataToken.readData(firstTokenId);
    assert.equal(rsp, data);
  });

});
```


## Implementation

An example implementation of the interface in solidity would look like this:

``` solidity
/**
 * @dev Implementation of ERC721 token and the `IERC1948` interface.
 *
 * ERC1948 is a non-fungible token (NFT) extended with the ability to store
 * dynamic data. The data is a bytes32 field for each tokenId. If 32 bytes
 * do not suffice to store the data, an authenticated data structure (hash or
 * merkle tree) shall be used.
 */
contract ERC1948 is IERC1948, ERC721 {

  mapping(uint256 =&gt; bytes32) data;

  /**
   * @dev See `IERC1948.readData`.
   *
   * Requirements:
   *
   * - `tokenId` needs to exist.
   */
  function readData(uint256 tokenId) external view returns (bytes32) {
    require(_exists(tokenId));
    return data[tokenId];
  }

  /**
   * @dev See `IERC1948.writeData`.
   *
   * Requirements:
   *
   * - `msg.sender` needs to be owner of `tokenId`.
   */
  function writeData(uint256 tokenId, bytes32 newData) external {
    require(msg.sender == ownerOf(tokenId));
    emit DataUpdated(tokenId, data[tokenId], newData);
    data[tokenId] = newData;
  }

}
```

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 18 Apr 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1948</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1948</guid>
      </item>
    
      <item>
        <title>New Opcode to check if a chainID is part of the history of chainIDs</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-1959-valid-chainid-opcode/3170</comments>
        
        <description>## Simple Summary
To protect off-chain messages from being reused across different chain, a mechanism need to be given to smart contract to only accept messages for that chain. Since a chain can change its chainID, the mechanism should consider old chainID valid.

## Abstract
This EIP adds an opcode that returns whether the specific number passed in has been a valid chainID (EIP-155 unique identifier) in the history of the chain (including the current chainID).

## Motivation
[EIP-155](/EIPs/EIPS/eip-155) proposes to use the chain ID to prevent replay attacks between different chains. It would be a great benefit to have the same possibility inside smart contracts when handling signatures, especially for Layer 2 signature schemes using [EIP-712](/EIPs/EIPS/eip-712).

[EIP-1344](/EIPs/EIPS/eip-1344) is attempting to solve this by giving smart contract access to the tip of the chainID history. This is insufficient as such value is changing. Hence why EIP-1344 describes a contract based solution to work around the problem. It would be better to solve it in a simpler, cheaper and safer manner, removing the potential risk of misuse present in EIP-1344.

## Specification
Adds a new opcode ```VALID_CHAINID``` at 0x46, which uses 1 stack argument : a 32 bytes value that represent the chainID to test. It will push ```0x1``` onto the stack if the uint256 value is part of the history (since genesis) of chainIDs of that chain, ```0x0``` otherwise. 

The operation costs `G_blockhash` to execute.

The cost of the operation might need to be adjusted later as the number of chainID in the history of the chain grows.

Note though that the alternative to keep track of old chainID is to implement a smart contract based caching solution as EIP-1344 proposes comes with an overall higher gas cost. As such the gas cost is simply a necessary cost for the feature.

## Rationale
The only approach available today is to specify the chain ID at compile time. Using this approach will result in problems after a contentious hardfork as the contract can&apos;t accept message signed with a new chainID. 

The approach proposed by EIP-1344 is to give access to the latest chainID. This is in itself not sufficient and pose the opposite of the problem mentioned above since as soon as a hardfork that change the chainID happens, every L2 messages signed as per [EIP-712](/EIPs/EIPS/eip-712) (with the previous chainID) will fails to be accepted by the contracts after the fork. 

That&apos;s why in the rationale of EIP-1344 it is mentioned that users need to implement/use a mechanism to verify the validity of past chainID via a trustless cache implemented via smart contract. 

While this works (except for a temporary gap where the immediately previous chainID is not considered valid), this is actually a required procedure for all contracts that want to accept L2 messages since without it, messages signed before a hardfork that updated the chainID would be rejected. In other words, EIP-1344 expose such risk and it is easy for contract to not consider it by simply checking ```chainID == CHAIN_ID()``` without considering past chainIDs.

Indeed letting contracts access the latest chainID for L2 message verification is dangerous. The latest chainID is only the tip of the chainID history. As a changing value, the latest chainID is thus not appropriate to ensure the validity of L2 messages.

Users signing off-chain messages expect their messages to be valid from the time of signing and do not expect these message to be affected by a future hardfork. If the contract use the latest chainID as is for verification, the messages would be invalid as soon as a hardfork that update the chainID happens. For some applications, this will require users to resubmit a new message (think meta transaction), causing them potential loss (or some inconvenience during the hardfork transition), but for some other applications (think state channel) the whole off-chain state become inaccessible, resulting in potentially disastrous situations. 

In other words, we should consider all off-chain messages (with valid chainID) as part of the chain&apos;s offchain state. The opcode proposed here, offer smart contracts a simple and safe method to ensure that the offchain state stay valid across fork.

As for replay protection, the idea of considering all of the off-chain messages signed with valid chainID as part of the chain&apos;s offchain-state means that all of these off-chain messages can be reused on the different forks which share a common chainID history (up to where they differ). This is actually an important feature since as mentioned, users expect their signed messages to be valid from the time of signing. From that time onwards these messages should be considered as part of the chain&apos;s offchain state. A hardfork should not thus render them invalid. This is similar to how the previous on-chain state is shared between 2 hardforks.

The wallets will make sure that at any time, a signing message request use the latest chainID of the chain being used. This prevent replay attack onto chain that have different chainID histories (they would not have the same latest chainID).

Now it is argued in the [EIP1344 discussion](https://ethereum-magicians.org/t/eip-1344-add-chain-id-opcode/1131) that when a contentious hardfork happen and one side of the fork decide to not update its chainID, that side of the chain would be vulnerable to replays since users will keep signing with a chainID that is also valid in the chain that forked. An issue also present in EIP-1344.

This is simply a natural consequence of using chainID as the only anti-replay information for L2 messages. But this can indeed be an issue if the hardfork is created by a small minority. In that case if the majority ignore the fork and do not update its chainID, then all new message from the majority chain (until they update their chainID) can be replayed on the minority-led hardfork since the majority&apos;s current chainID is also part of the minority-led fork&apos;s chainID history.

To fix this, every message could specify the block number representing the time it was signed. The contract could then verify that chainID specified as part of that message was valid at that particular block. 


While EIP-1344 can&apos;t do that accurately as the caching system might leave a gap, this proposal can solve it if it is modified to return the blockNumber at which a chainID become invalid. Unfortunately, this would be easy for contracts to not perform that check. And since it suffice of only one important applications to not follow this procedure to put the minority-led fork at a disadvantage, this would fail to achieve the desired goal of protecting the minority-led fork from replay.

Since a minority-led fork ignored by the majority means that the majority will not keep track of the messages to be submitted (state channel, ...), if such fork get traction later, this would be at the expense of majority users who were not aware of it. As such this proposal assume that minority-led fork will not get traction later and thus do not require to be protected.

## Test Cases
TBD

## Implementation
TBD

## Backwards Compatibility
This EIP is fully backwards compatible with all chains which implement EIP-155 chain ID domain separator for transaction signing. Existing contract are not affected.

Similarly to EIP-1344, it might be beneficial to update EIP-712 (still in Draft) to deal with chainID separately from the domain separator. Indeed since chainID is expected to change, if the domain separator include chainID, it would have to be dynamically computed. A caching mechanism could be used by smart contract instead though.

## References
This was previously suggested as part of [EIP-1344 discussion](https://ethereum-magicians.org/t/eip-1344-add-chain-id-opcode/1131/39).

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 20 Apr 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1959</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1959</guid>
      </item>
    
      <item>
        <title>EC arithmetic and pairings with runtime definitions</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/generalised-precompile-for-elliptic-curve-arithmetics-and-pairings-working-group/3208/2</comments>
        
        <description># Simple summary

This proposal is an extension and formalization of [EIP-1829](/EIPs/EIPS/eip-1829) with an inclusion of pairings. [EIP-1109](/EIPs/EIPS/eip-1109) is required due to low cost of some operations compared to the `STATICCALL` opcode (more information in the corresponding section below).

## Abstract

This EIP proposes a new precompile to bring cryptographic functionality desired for privacy and scaling solutions. Functionality of such precompile will require the following:

- Implementation the following operations over elliptic curves in the Weierstrass form with curve parameters such as base field, A, B coefficients defined in runtime:
    - Point addition
    - Multiplication of a single point over a scalar
    - Multiexponentiation
- Implementation pairing operation over elliptic curves from the following &quot;families&quot; with parameters such as base field, extension tower structure, coefficients defined in runtime:
    - BLS12
    - BN
    - MNT4/6 (Ate pairing)

Full functionality of the precompile is described below in `Specification` section.

## Motivation

- There is a pending proposal to implement base elliptic curve arithmetic is covered by [EIP-1829](/EIPs/EIPS/eip-1829) and will allow to implement various privacy-preserving protocols with a reasonable gas costs per operation.
- Pairings are an important extension for basic arithmetic and so this new precompile is proposed with the following benefits:
    - Extended set of curves will be available to allow Ethereum users to choose their security parameters and required functionality.
    - Generic approach of this precompile will allow Ethereum users to experiment with newly found curves of their choice and new constructions constructions without waiting for new forks.
    - EC arithmetic is indeed re-implemented in this precompile, but it&apos;s strictly required. Most of the pairing-based protocols still need to perform standard EC multiplications or additions and thus such operations must be available on generic set of curves.
- Gas costs - this EIP is designed to estimate gas-cost of performed operation as early as possible during the call and base if solely on specified parameters and operation type. This is a strict requirement for any precompile to allow Ethereum nodes to efficiently reject transactions and operations as early as possible.

Functionality of this newly proposed precompile is different from [EIP-1829](/EIPs/EIPS/eip-1829) in the following aspects:
- Operation on arbitrary-length modulus (up to some upper-limit) for a base field and scalar field of the curve
- Pairing operations are introduced
- Different ABI due to variable parameter length

## Specification

If `block.number &gt;= XXXXX`, define a set of `10` new precompiles with an addresses `[0x.., 0x.., ...]` and the following functionality. 

- Addition of points on the curve defined over base field
- Multiplication of a point on the curve defined over base field
- Multiexponentiation for `N` pairs of `(scalar, point)` on the curve defined over base field
- Addition of points on the curve defined over quadratic or cubic extension of the base field
- Multiplication of a point on the curve defined over quadratic or cubic extension of the base field
- Multiexponentiation for `N` pairs of `(scalar, point)` on the curve defined over quadratic or cubic extension of the base field
- Pairing operation on the curve of `BLS12` family
- Pairing operation on the curve of `BN` family
- Pairing operation on the curve of `MNT4` family
- Pairing operation on the curve of `MNT6` family

Due to actuve development of the precompile and a lot of ongoing changes there is a single [source of truth](https://github.com/matter-labs/eip1962/tree/master/documentation). It covers binary interface, gas schedule, integration guide for existing implementations.

### Possible simplifications

Due to high complexity of the proposed operations in the aspects of implementation, debugging and evaluation of the factors for gas costs it may be appropriate to either limit the set of curves at the moment of acceptance to some list and then extend it. Another approach (if it&apos;s technically possible) would be to have the &quot;whilelist&quot; contract that can be updated without consensus changes (w/o fork).

In the case of limited set of curve the following set is proposed as a minimal:
- BN254 curve from the current version of Ethereum
- BN curve from DIZK with 2^32 roots of unity
- BLS12-381 
- BLS12-377 from ZEXE with large number of roots of unity
- MNT4/6 cycle from the original [paper](https://eprint.iacr.org/2014/595.pdf). It&apos;s not too secure, but may give some freedom for experiments.
- MNT4/6 cycle from Coda if performance allows
- Set of CP generated curves that would allow embedding of BLS12-377 and may be some BN curve that would have large power of two divisor for both base field and scalar field modulus (example of CP curve for BLS12-377 can be found in ZEXE). 

## Rationale

Only the largest design decisions will be covered:
- While there is no arithmetic over the scalar field (which is modulo size of the main group) of the curve, it&apos;s required for gas estimation purposes.
- Multiexponentiation is a separate operation due to large cost saving
- There are no point decompressions due to impossibility to get universal gas estimation of square root operation. For a limited number of &quot;good&quot; cases prices would be too different, so specifying the &quot;worst case&quot; is expensive and inefficient, while introduction of another level if complexity into already complicated gas costs formula is not worth is.

### This precompile and EIP 1109

While there is no strict requirement of EIP 1109 for functionality, here is an example why it would be desired:
- BLS12-381 curve, 381 bit modulus, 255 bit scalar field, no native arithmetic is available in EVM for this
- Point addition would take 5000ns (quite overestimated)
- Point multiplication would take roughly 150000ns
- Crude gas schedule 15 Mgas/second from ECRecover precompile 
- Point addition would cost 75 gas, with `STATICCALL` adding another 700
- Point multiplication would cost 2250 gas
- One should also add the cost of memory allocation that is at least `1 + 1 + 48 + 48 + 48 + 1 + 32 + 2*48 + 2*48 = 371 byte` that is around 12 native Ethereum &quot;words&quot; and will require extra 36 gas (with negligible price for memory extension)

Based on these quite crude estimations one can see that `STATICCALL` price will dominate the total cost (in case of addition) or bring significant overhead (in case of multiplication operation) in case of calls to this precompile.


## Backwards Compatibility

This change is not backwards compatible and requires hard fork to be activated.

Functionality of the new precompile itself does not affect any existing functionality of Ethereum or EVM. 

This precompile may serve as a complete replacement of the current set of `ECADD`, `ECMUL` and pairing check precompiles (`0x06`, `0x07`, `0x08`)

## Test Cases
Test cases are the part of the implementation with a link below.

## Implementation
There is an ongoing implementation effort [here](https://github.com/matter-labs/eip1829). Right now:
- Non-pairing operations are implemented and tested.
- BLS12 family is completed and tested for BLS12-381 and BLS12-377 curves. 
- BN family is completed and tested with BN254 curve.
- Cocks-Pinch method curve is tested for k=6 curve from ZEXE.

## Preliminary benchmarks

cp6 in benchmarks is a Cocks-Pinch method curve that embeds BLS12-377. Machine: Core i7, 2.9 GHz.

Multiexponentiation benchmarks take 100 pairs `(generator, random scalar)` as input. Due to the same &quot;base&quot; it may be not too representative benchmark and will be updated.

```
test pairings::bls12::tests::bench_bls12_381_pairing    ... bench:   2,348,317 ns/iter (+/- 605,340)
test pairings::cp::tests::bench_cp6_pairing             ... bench:  86,328,825 ns/iter (+/- 11,802,073)
test tests::bench_addition_bn254                        ... bench:         388 ns/iter (+/- 73)
test tests::bench_doubling_bn254                        ... bench:         187 ns/iter (+/- 4)
test tests::bench_field_inverse                         ... bench:       2,478 ns/iter (+/- 167)
test tests::bench_field_mont_inverse                    ... bench:       2,356 ns/iter (+/- 51)
test tests::bench_multiplication_bn254                  ... bench:      81,744 ns/iter (+/- 6,984)
test tests::bench_multiplication_bn254_into_affine      ... bench:      81,925 ns/iter (+/- 3,323)
test tests::bench_multiplication_bn254_into_affine_wnaf ... bench:      74,716 ns/iter (+/- 4,076)
test tests::bench_naive_multiexp_bn254                  ... bench:  10,659,911 ns/iter (+/- 559,790)
test tests::bench_peppinger_bn254                       ... bench:   2,678,743 ns/iter (+/- 148,914)
test tests::bench_wnaf_multiexp_bn254                   ... bench:   9,161,281 ns/iter (+/- 456,137)
```

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).</description>
        <pubDate>Mon, 22 Apr 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1962</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1962</guid>
      </item>
    
      <item>
        <title>Method to check if a chainID is valid at a specific block Number</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-1965-valid-chainid-for-specific-blocknumber-protect-all-forks/3181</comments>
        
        <description>## Abstract

This EIP adds a precompile that returns whether a specific chainID (EIP-155 unique identifier) is valid at a specific blockNumber. ChainID are assumed to be valid up to the blockNumber at which they get replaced by a new chainID.

## Motivation

[EIP-155](/EIPs/EIPS/eip-155) proposes to use the chain ID to prevent the replay of transactions between different chains. It would be a great benefit to have the same possibility inside smart contracts when handling off-chain message signatures, especially for Layer 2 signature schemes using [EIP-712](/EIPs/EIPS/eip-712).

[EIP-1344](/EIPs/EIPS/eip-1344) is attempting to solve this by giving smart contract access to the tip of the chainID history. This is insufficient as such value is changing. Hence why EIP-1344 describes a contract based solution to work around the problem. It would be better to solve it in a simpler, cheaper and safer manner, removing the potential risk of misuse present in EIP-1344. Furthermore EIP-1344 can&apos;t protect replay properly for minority-led hardfork as the caching system cannot guarantee accuracy of the blockNumber at which the new chainID has been introduced.

[EIP-1959](/EIPs/EIPS/eip-1959) solves the issue of EIP-1344 but does not attempt to protect from minority-led hardfork as mentioned in the rationale. We consider this a mistake, since it removes some freedom to fork. We consider that all fork should be given equal opportunities. And while there will always be issues we can&apos;t solve for the majority that ignore a particular fork, **users that decide to use both the minority-fork and the majority-chain should be protected from replay without having to wait for the majority chain to update its chainID.**

## Specification

Adds a new precompile which uses 2 arguments : a 32 bytes value that represents the chainID to test and a 32 bytes value representing the blockNumber at which the chainID is tested. It returns 0x1  if the chainID is valid at the specific blockNumber, 0x0 otherwise. Note that chainID are considered valid up to the blockNumber at which they are replaced. So they are valid for every blockNumber past their replacement.

The operation will costs no more than `G_blockhash` + `G_verylow` to execute. This could be lower as chainID are only introduced during hardfork.

The cost of the operation might need to be adjusted later as the number of chainID in the history of the chain grows.

Note though that the alternative to keep track of old chainID is to implement a smart contract based caching solution as EIP-1344 proposes comes with an overall higher gas cost and exhibit issues for minority-led hardfork (see Rationale section below). As such the gas cost is simply a necessary cost for the feature.

## Rationale

The rationale at EIP-1959 applies here as well too :

- An opcode is better than a caching system for past chainID, It is cheaper, safer and does not include gaps.
- Direct access to the latest chainID is dangerous since it makes it easy for contracts to use it as a replay protection mechanism while preventing otherwise valid old messages to be valid after a fork that changes the chainID. This can have disastrous consequences on users.
- all off-chain messages signed before a fork should be valid across all side of the fork.

The only difference is that this current proposal proposes a solution to protect hardfork led by a minority.

To summarize there is 2 possible fork scenario :

1) The majority decide to make a hardfork but a minority disagree with it (ETC is such example). The fork is planned for block X. If the majority is not taking any action to automate the process of assigning a different chainID for both, the minority has plenty of time to plan for a chainID upgrade to happen at that same block X. Now if they do not do it, their users will face the problem that their messages will be replayable on the majority chain (Note that this is not true the other way around as we assume the majority decided to change the chainID). As such there is no reason that they will leave it that way.

2) A minority decide to create a hardfork that the majority disagree with (or simply ignore). Now, the same as above can happen but since we are talking about a minority there is a chance that the majority does not care about the minority. In that case, there would be no incentive for the majority to upgrade the chainID. This means that users of both sides of the fork will have the messages meant for the majority chain replayable on the minority-chain (even if this one changed its chainID) unless extra precaution is taken.

The solution is to add the blockNumber representing the time at which the message was signed and use it as an argument to the opcode proposed here. This way, when the minority forks with a new chainID, the previous chainID become invalid from that time onward. So new messages destined to the majority chain can&apos;t be replayed on the minority fork.


## Backwards Compatibility

EIP-712 is still in draft but would need to be updated to include the blockNumber as part of the values that wallets need to verify for the protection of their users.

Since chainID and blockNumber will vary, they should not be part of the domain separator (meant to be generated once) but another part of the message.

While the pair could be optional for contract that do not care about replays or have other ways to prevent them, if chainID is present, the blockNumber must be present too. And if any of them is present, wallet need to ensure that the chainID is indeed the latest one of the chain being used, while the blockNumber is the latest one at the point of signing. During fork transition, the wallet can use the blockNumber to know which chainID to use.

## References

This was previously suggested as part of [EIP1959 discussion](https://ethereum-magicians.org/t/eip-1959-valid-chainid-opcode/3170).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 20 Apr 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1965</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1965</guid>
      </item>
    
      <item>
        <title>Proxy Storage Slots</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-1967-standard-proxy-storage-slots/3185</comments>
        
        <description>## Abstract
Delegating **proxy contracts** are widely used for both upgradeability and gas savings. These proxies rely on a **logic contract** (also known as implementation contract or master copy) that is called using `delegatecall`. This allows proxies to keep a persistent state (storage and balance) while the code is delegated to the logic contract.

To avoid clashes in storage usage between the proxy and logic contract, the address of the logic contract is typically saved in a specific storage slot (for example `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` in OpenZeppelin contracts) guaranteed to be never allocated by a compiler. This EIP proposes a set of standard slots to store proxy information. This allows clients like block explorers to properly extract and show this information to end users, and logic contracts to optionally act upon it.

## Motivation
Delegating proxies are widely in use, as a means to both support upgrades and reduce gas costs of deployments. Examples of these proxies are found in OpenZeppelin Contracts, Gnosis, AragonOS, Melonport, Limechain, WindingTree, Decentraland, and many others.

However, the lack of a common interface for obtaining the logic address for a proxy makes it impossible to build common tools that act upon this information.

A classic example of this is a block explorer. Here, the end user wants to interact with the underlying logic contract and not the proxy itself. Having a common way to retrieve the logic contract address from a proxy allows a block explorer to show the ABI of the logic contract and not that of the proxy. The explorer checks the storage of the contract at the distinguished slots to determine if it is indeed a proxy, in which case it shows information on both the proxy and the logic contract. As an example, this is how `0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48` is shown on Etherscan:

![Sample proxy on Etherscan](/EIPs/assets/eip-1967/Sample-proxy-on-etherscan.png)

Another example is logic contracts that explicitly act upon the fact that they are being proxied. This allows them to potentially trigger a code update as part of their logic. A common storage slot allows these use cases independently of the specific proxy implementation being used.

## Specification
Monitoring of proxies is essential to the security of many applications. It is thus essential to have the ability to track changes to the implementation and admin slots. Unfortunately, tracking changes to storage slots is not easy. Consequently, it is recommended that any function that changes any of these slots SHOULD also emit the corresponding event. This includes initialization, from `0x0` to the first non-zero value.

The proposed storage slots for proxy-specific information are the following. More slots for additional information can be added in subsequent ERCs as needed.

### Logic contract address

Storage slot `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
(obtained as `bytes32(uint256(keccak256(&apos;eip1967.proxy.implementation&apos;)) - 1)`).

Holds the address of the logic contract that this proxy delegates to. SHOULD be empty if a beacon is used instead. Changes to this slot SHOULD be notified by the event:

```solidity
event Upgraded(address indexed implementation);
```

### Beacon contract address

Storage slot `0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50` (obtained as `bytes32(uint256(keccak256(&apos;eip1967.proxy.beacon&apos;)) - 1)`).

Holds the address of the beacon contract this proxy relies on (fallback). SHOULD be empty if a logic address is used directly instead, and should only be considered if the logic contract slot is empty. Changes to this slot SHOULD be notified by the event:

```solidity
event BeaconUpgraded(address indexed beacon);
```

Beacons are used for keeping the logic address for multiple proxies in a single location, allowing the upgrade of multiple proxies by modifying a single storage slot. A beacon contract MUST implement the function:

```
function implementation() returns (address)
```

Beacon based proxy contracts do not use the logic contract slot. Instead, they use the beacon contract slot to store the address of the beacon they are attached to. In order to know the logic contract used by a beacon proxy, a client SHOULD:

- Read the address of the beacon for the beacon logic storage slot;
- Call the `implementation()` function on the beacon contract.

The result of the `implementation()` function on the beacon contract SHOULD NOT depend on the caller (`msg.sender`).


### Admin address

Storage slot `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
(obtained as `bytes32(uint256(keccak256(&apos;eip1967.proxy.admin&apos;)) - 1)`).

Holds the address that is allowed to upgrade the logic contract address for this proxy (optional). Changes to this slot SHOULD be notified by the event:

```solidity
event AdminChanged(address previousAdmin, address newAdmin);
```

## Rationale

This EIP standardises the **storage slot** for the logic contract address, instead of a public method on the proxy contract. The rationale for this is that proxies should never expose functions to end users that could potentially clash with those of the logic contract.

Note that a clash may occur even among functions with different names, since the ABI relies on just four bytes for the function selector. This can lead to unexpected errors, or even exploits, where a call to a proxied contract returns a different value than expected, since the proxy intercepts the call and answers with a value of its own.

From _Malicious backdoors in Ethereum proxies_ by Nomic Labs:

&gt; Any function in the Proxy contract whose selector matches with one in the implementation contract will be called directly, completely skipping the implementation code.
&gt;
&gt; Because the function selectors use a fixed amount of bytes, there will always be the possibility of a clash. This isn’t an issue for day to day development, given that the Solidity compiler will detect a selector clash within a contract, but this becomes exploitable when selectors are used for cross-contract interaction. Clashes can be abused to create a seemingly well-behaved contract that’s actually concealing a backdoor.

The fact that proxy public functions are potentially exploitable makes it necessary to standardise the logic contract address in a different way.

The main requirement for the storage slots chosen is that they must never be picked by the compiler to store any contract state variable. Otherwise, a logic contract could inadvertently overwrite this information on the proxy when writing to a variable of its own.

Solidity maps variables to storage based on the order in which they were declared, after the contract inheritance chain is linearized: the first variable is assigned the first slot, and so on. The exception is values in dynamic arrays and mappings, which are stored in the hash of the concatenation of the key and the storage slot. The Solidity development team has confirmed that the storage layout is to be preserved among new versions:

&gt; The layout of state variables in storage is considered to be part of the external interface of Solidity due to the fact that storage pointers can be passed to libraries. This means that any change to the rules outlined in this section is considered a breaking change of the language and due to its critical nature should be considered very carefully before being executed. In the event of such a breaking change, we would want to release a compatibility mode in which the compiler would generate bytecode supporting the old layout.

Vyper seems to follow the same strategy as Solidity. Note that contracts written in other languages, or directly in assembly, may incur in clashes.

They are chosen in such a way so they are guaranteed to not clash with state variables allocated by the compiler, since they depend on the hash of a string that does not start with a storage index. Furthermore, a `-1` offset is added so the preimage of the hash cannot be known, further reducing the chances of a possible attack.

## Reference Implementation

```solidity
/**
 * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
 * implementation address that can be changed. This address is stored in storage in the location specified by
 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn&apos;t conflict with the storage layout of the
 * implementation behind the proxy.
 */
contract ERC1967Proxy is Proxy, ERC1967Upgrade {
    /**
     * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
     *
     * If `_data` is nonempty, it&apos;s used as data in a delegate call to `_logic`. This will typically be an encoded
     * function call, and allows initializing the storage of the proxy like a Solidity constructor.
     */
    constructor(address _logic, bytes memory _data) payable {
        assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(&quot;eip1967.proxy.implementation&quot;)) - 1));
        _upgradeToAndCall(_logic, _data, false);
    }

    /**
     * @dev Returns the current implementation address.
     */
    function _implementation() internal view virtual override returns (address impl) {
        return ERC1967Upgrade._getImplementation();
    }
}

/**
 * @dev This abstract contract provides getters and event emitting update functions for
 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
 */
abstract contract ERC1967Upgrade {
    // This is the keccak-256 hash of &quot;eip1967.proxy.rollback&quot; subtracted by 1
    bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;

    /**
     * @dev Storage slot with the address of the current implementation.
     * This is the keccak-256 hash of &quot;eip1967.proxy.implementation&quot; subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

    /**
     * @dev Emitted when the implementation is upgraded.
     */
    event Upgraded(address indexed implementation);

    /**
     * @dev Returns the current implementation address.
     */
    function _getImplementation() internal view returns (address) {
        return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 implementation slot.
     */
    function _setImplementation(address newImplementation) private {
        require(Address.isContract(newImplementation), &quot;ERC1967: new implementation is not a contract&quot;);
        StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
    }

    /**
     * @dev Perform implementation upgrade
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeTo(address newImplementation) internal {
        _setImplementation(newImplementation);
        emit Upgraded(newImplementation);
    }

    /**
     * @dev Perform implementation upgrade with additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCall(
        address newImplementation,
        bytes memory data,
        bool forceCall
    ) internal {
        _upgradeTo(newImplementation);
        if (data.length &gt; 0 || forceCall) {
            Address.functionDelegateCall(newImplementation, data);
        }
    }

    /**
     * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCallSecure(
        address newImplementation,
        bytes memory data,
        bool forceCall
    ) internal {
        address oldImplementation = _getImplementation();

        // Initial upgrade and setup call
        _setImplementation(newImplementation);
        if (data.length &gt; 0 || forceCall) {
            Address.functionDelegateCall(newImplementation, data);
        }

        // Perform rollback test if not already in progress
        StorageSlot.BooleanSlot storage rollbackTesting = StorageSlot.getBooleanSlot(_ROLLBACK_SLOT);
        if (!rollbackTesting.value) {
            // Trigger rollback using upgradeTo from the new implementation
            rollbackTesting.value = true;
            Address.functionDelegateCall(
                newImplementation,
                abi.encodeWithSignature(&quot;upgradeTo(address)&quot;, oldImplementation)
            );
            rollbackTesting.value = false;
            // Check rollback was effective
            require(oldImplementation == _getImplementation(), &quot;ERC1967Upgrade: upgrade breaks further upgrades&quot;);
            // Finally reset to the new implementation and log the upgrade
            _upgradeTo(newImplementation);
        }
    }

    /**
     * @dev Storage slot with the admin of the contract.
     * This is the keccak-256 hash of &quot;eip1967.proxy.admin&quot; subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;

    /**
     * @dev Emitted when the admin account has changed.
     */
    event AdminChanged(address previousAdmin, address newAdmin);

    /**
     * @dev Returns the current admin.
     */
    function _getAdmin() internal view returns (address) {
        return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 admin slot.
     */
    function _setAdmin(address newAdmin) private {
        require(newAdmin != address(0), &quot;ERC1967: new admin is the zero address&quot;);
        StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
    }

    /**
     * @dev Changes the admin of the proxy.
     *
     * Emits an {AdminChanged} event.
     */
    function _changeAdmin(address newAdmin) internal {
        emit AdminChanged(_getAdmin(), newAdmin);
        _setAdmin(newAdmin);
    }

    /**
     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
     * This is bytes32(uint256(keccak256(&apos;eip1967.proxy.beacon&apos;)) - 1)) and is validated in the constructor.
     */
    bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;

    /**
     * @dev Emitted when the beacon is upgraded.
     */
    event BeaconUpgraded(address indexed beacon);

    /**
     * @dev Returns the current beacon.
     */
    function _getBeacon() internal view returns (address) {
        return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
    }

    /**
     * @dev Stores a new beacon in the EIP1967 beacon slot.
     */
    function _setBeacon(address newBeacon) private {
        require(Address.isContract(newBeacon), &quot;ERC1967: new beacon is not a contract&quot;);
        require(
            Address.isContract(IBeacon(newBeacon).implementation()),
            &quot;ERC1967: beacon implementation is not a contract&quot;
        );
        StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
    }

    /**
     * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
     * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
     *
     * Emits a {BeaconUpgraded} event.
     */
    function _upgradeBeaconToAndCall(
        address newBeacon,
        bytes memory data,
        bool forceCall
    ) internal {
        _setBeacon(newBeacon);
        emit BeaconUpgraded(newBeacon);
        if (data.length &gt; 0 || forceCall) {
            Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
        }
    }
}

/**
 * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
 * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
 * be specified by overriding the virtual {_implementation} function.
 *
 * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
 * different contract through the {_delegate} function.
 *
 * The success and return data of the delegated call will be returned back to the caller of the proxy.
 */
abstract contract Proxy {
    /**
     * @dev Delegates the current call to `implementation`.
     *
     * This function does not return to its internal call site, it will return directly to the external caller.
     */
    function _delegate(address implementation) internal virtual {
        assembly {
            // Copy msg.data. We take full control of memory in this inline assembly
            // block because it will not return to Solidity code. We overwrite the
            // Solidity scratch pad at memory position 0.
            calldatacopy(0, 0, calldatasize())

            // Call the implementation.
            // out and outsize are 0 because we don&apos;t know the size yet.
            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)

            // Copy the returned data.
            returndatacopy(0, 0, returndatasize())

            switch result
            // delegatecall returns 0 on error.
            case 0 {
                revert(0, returndatasize())
            }
            default {
                return(0, returndatasize())
            }
        }
    }

    /**
     * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function
     * and {_fallback} should delegate.
     */
    function _implementation() internal view virtual returns (address);

    /**
     * @dev Delegates the current call to the address returned by `_implementation()`.
     *
     * This function does not return to its internal call site, it will return directly to the external caller.
     */
    function _fallback() internal virtual {
        _beforeFallback();
        _delegate(_implementation());
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
     * function in the contract matches the call data.
     */
    fallback() external payable virtual {
        _fallback();
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
     * is empty.
     */
    receive() external payable virtual {
        _fallback();
    }

    /**
     * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
     * call, or as part of the Solidity `fallback` or `receive` functions.
     *
     * If overridden should call `super._beforeFallback()`.
     */
    function _beforeFallback() internal virtual {}
}

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        assembly {
            r.slot := slot
        }
    }
}
```

## Security Considerations

This ERC relies on the fact that the chosen storage slots are **not** to be allocated by the solidity compiler. This guarantees that an implementation contract will not accidentally overwrite any of the information required for the proxy to operate. As such, locations with a high slot number were chosen to avoid clashes with the slots allocated by the compiler. Also, locations with no known preimage were picked, to ensure that a write to mapping with a maliciously crafted key could not overwrite it.

Logic contracts that intend to modify proxy-specific information must do so deliberately (as is the case with UUPS) by writing to the specific storage slot.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 24 Apr 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1967</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1967</guid>
      </item>
    
      <item>
        <title>Scalable Rewards</title>
        <category>Standards Track/ERC</category>
        
        <description>## Simple Summary

 A mintable token rewards interface that mints &apos;n&apos; tokens per block which are distributed equally among the &apos;m&apos; participants in the DAPP&apos;s ecosystem.

## Abstract

 The mintable token rewards interface allows DApps to build a token economy where token rewards are distributed equally among the active participants. The tokens are minted based on per block basis that are configurable (E.g. 10.2356 tokens per block, 0.1 token per block, 1350 tokens per block) and the mint function can be initiated by any active participant. The token rewards distributed to each participant is dependent on the number of participants in the network. At the beginning, when the network has low volume, the tokens rewards per participant is high but as the network scales the token rewards decreases dynamically.
 

 ## Motivation

Distributing tokens through a push system to a large amount of participants fails due to block gas limit. As the number of participants in the network grow to tens of thousands, keeping track of the iterable registry of participants and their corresponding rewards in a push system becomes unmanagable. E.g. Looping through 5000 addresses to distribute 0.0000001 reward tokens is highly inefficient. Furthermore, the gas fees in these transactions are high and needs to be undertaken by the DApp developer or the respective company, leading to centralization concerns. 

A pull system is required to keep the application completely decentralized and to avoid the block gas limit problem. However, no standard solution has been proposed to distribute scalable rewards to tens of thousands participants with a pull system. This is what we propose with this EIP through concepts like TPP, round mask, participant mask. 

## Specification

### Definitions 

 `token amount per participant in the ecosytem or TPP (token per participant)`: TPP = (token amount to mint / total active participants)

 `roundMask`: the cumulative snapshot of TPP over time for the token contract. E.g. transactionOne = 10 tokens are minted with 100 available participants (TPP = 10 / 100) , transactionTwo = 12 tokens are minted with 95 participants (TPP = 12 / 95 ) 

 roundMask = (10/100) + (12/95)

 `participantMask`: is used to keep track of a `msg.sender` (participant) rewards over time. When a `msg.sender` joins or leaves the ecosystem, the player mask is updated

 participantMask = previous roundMask OR (current roundMask - TPP)

 `rewards for msg.sender`: roundMask - participantMask 

 E.g. Let&apos;s assume a total of 6 transactions (smart contract triggers or functions calls) are in place with 10 existing participants (denominator) and 20 tokens (numerator) are minted per transaction. At 2nd transaction, the 11th participant joins the network and exits before 5th transaction, the 11th participant&apos;s balance is as follows:
 
 ``` 
 t1 roundMask = (20/10)
 t2 roundMask = (20/10) + (20/11) 
 t3 roundMask = (20/10) + (20/11) + (20/11)
 t4 roundMask = (20/10) + (20/11) + (20/11) + (20/11)
 t5 roundMask = (20/10) + (20/11) + (20/11) + (20/11)+ (20/10)
 t6 roundMask = (20/10) + (20/11) + (20/11) + (20/11)+ (20/10) + (20/10)
 ``` 

 Total tokens released in 6 transactions = 60 tokens 

 As the participant joins at t2 and leaves before t5, the participant deserves the rewards between t2 and t4. When the participant joins at t2, the &apos;participantMask = (20/10)&apos;, when the participant leaves before t5, the cumulative deserved reward tokens are :

 rewards for msg.sender: `[t4 roundMask = (20/10) + (20/11)+ (20/11) + (20/11)] - [participantMask = (20/10)] = [rewards = (20/11)+ (20/11) + (20/11)]`

 When the same participant joins the ecosystem at a later point (t27 or t35), a new &apos;participantMask&apos; is given that is used to calculate the new deserved reward tokens when the participant exits. This process continues dynamically for each participant. 

 `tokensPerBlock`: the amount of tokens that will be released per block

 `blockFreezeInterval`: the number of blocks that need to pass until the next mint. E.g. if set to 50 and &apos;n&apos; tokens were minted at block &apos;b&apos;, the next &apos;n&apos; tokens won&apos;t be minted until &apos;b + 50&apos; blocks have passed

 `lastMintedBlockNumber`: the block number on which last &apos;n&apos; tokens were minted

 `totalParticipants` : the total number of participants in the DApp network

 `tokencontractAddress` : the contract address to which tokens will be minted, default is address(this) 

```solidity

pragma solidity ^0.5.2;

import &quot;openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol&quot;;
import &quot;openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol&quot;;

contract Rewards is ERC20Mintable, ERC20Detailed {

using SafeMath for uint256;

uint256 public roundMask;
uint256 public lastMintedBlockNumber;
uint256 public totalParticipants = 0;
uint256 public tokensPerBlock; 
uint256 public blockFreezeInterval; 
address public tokencontractAddress = address(this);
mapping(address =&gt; uint256) public participantMask; 

/**
 * @dev constructor, initializes variables.
 * @param _tokensPerBlock The amount of token that will be released per block, entered in wei format (E.g. 1000000000000000000)
 * @param _blockFreezeInterval The amount of blocks that need to pass (E.g. 1, 10, 100) before more tokens are brought into the ecosystem.
 */
 constructor(uint256 _tokensPerBlock, uint256 _blockFreezeInterval) public ERC20Detailed(&quot;Simple Token&quot;, &quot;SIM&quot;, 18){ 
lastMintedBlockNumber = block.number;
tokensPerBlock = _tokensPerBlock;
blockFreezeInterval = _blockFreezeInterval;
}

/**
 * @dev Modifier to check if msg.sender is whitelisted as a minter. 
 */
modifier isAuthorized() {
require(isMinter(msg.sender));
_;
}

/**
 * @dev Function to add participants in the network. 
 * @param _minter The address that will be able to mint tokens.
 * @return A boolean that indicates if the operation was successful.
 */
function addMinters(address _minter) external returns (bool) {
_addMinter(_minter);
totalParticipants = totalParticipants.add(1);
updateParticipantMask(_minter);
return true;
}


/**
 * @dev Function to remove participants in the network. 
 * @param _minter The address that will be unable to mint tokens.
 * @return A boolean that indicates if the operation was successful.
 */
function removeMinters(address _minter) external returns (bool) {
totalParticipants = totalParticipants.sub(1);
_removeMinter(_minter); 
return true;
}


/**
 * @dev Function to introduce new tokens in the network. 
 * @return A boolean that indicates if the operation was successful.
 */
function trigger() external isAuthorized returns (bool) {
bool res = readyToMint();
if(res == false) {
return false;
} else {
mintTokens();
return true;
}
}

/**
 * @dev Function to withdraw rewarded tokens by a participant. 
 * @return A boolean that indicates if the operation was successful.
 */
function withdraw() external isAuthorized returns (bool) {
uint256 amount = calculateRewards();
require(amount &gt;0);
ERC20(tokencontractAddress).transfer(msg.sender, amount);
}

/**
 * @dev Function to check if new tokens are ready to be minted. 
 * @return A boolean that indicates if the operation was successful.
 */
function readyToMint() public view returns (bool) {
uint256 currentBlockNumber = block.number;
uint256 lastBlockNumber = lastMintedBlockNumber;
if(currentBlockNumber &gt; lastBlockNumber + blockFreezeInterval) { 
return true;
} else {
return false;
}
}

/**
 * @dev Function to calculate current rewards for a participant. 
 * @return A uint that returns the calculated rewards amount.
 */
function calculateRewards() private returns (uint256) {
uint256 playerMask = participantMask[msg.sender];
uint256 rewards = roundMask.sub(playerMask);
updateParticipantMask(msg.sender);
return rewards;
}

/**
 * @dev Function to mint new tokens into the economy. 
 * @return A boolean that indicates if the operation was successful.
 */
function mintTokens() private returns (bool) {
uint256 currentBlockNumber = block.number;
uint256 tokenReleaseAmount = (currentBlockNumber.sub(lastMintedBlockNumber)).mul(tokensPerBlock);
lastMintedBlockNumber = currentBlockNumber;
mint(tokencontractAddress, tokenReleaseAmount);
calculateTPP(tokenReleaseAmount);
return true;
}

 /**
* @dev Function to calculate TPP (token amount per participant).
* @return A boolean that indicates if the operation was successful.
*/
function calculateTPP(uint256 tokens) private returns (bool) {
uint256 tpp = tokens.div(totalParticipants);
updateRoundMask(tpp);
return true;
}

 /**
* @dev Function to update round mask. 
* @return A boolean that indicates if the operation was successful.
*/
function updateRoundMask(uint256 tpp) private returns (bool) {
roundMask = roundMask.add(tpp);
return true;
}

 /**
* @dev Function to update participant mask (store the previous round mask)
* @return A boolean that indicates if the operation was successful.
*/
function updateParticipantMask(address participant) private returns (bool) {
uint256 previousRoundMask = roundMask;
participantMask[participant] = previousRoundMask;
return true;
}

}
``` 

## Rationale

Currently, there is no standard for a scalable reward distribution mechanism. In order to create a sustainable cryptoeconomic environment within DAPPs, incentives play a large role. However, without a scalable way to distribute rewards to tens of thousands of participants, most DAPPs lack a good incentive structure. The ones with a sustainable cryptoeconomic environment depend heavily on centralized servers or a group of selective nodes to trigger the smart contracts. But, in order to keep an application truly decentralized, the reward distribution mechanism must depend on the active participants itself and scale as the number of participants grow. This is what this EIP intends to accomplish.

## Backwards Compatibility

Not Applicable. 

## Test Cases

WIP, will be added.

## Implementation

WIP, a proper implementation will be added later.A sample example is below: 

`etherscan rewards contract` : https://ropsten.etherscan.io/address/0x8b0abfc541ab7558857816a67e186221adf887bc#tokentxns

`Step 1` : deploy Rewards contract with the following parameters_tokensPerBlock = 1e18, _blockFreezeInterval = 1

`Step 2` : add Alice(0x123) and Bob(0x456) as minters, addMinters(address _minter) 

`Step 3` : call trigger() from Alice / Bob&apos;s account. 65 blocks are passed, hence 65 SIM tokens are minted. The RM is 32500000000000000000

`Step 4` : Alice withdraws and receives 32.5 SIM tokens (65 tokens / 2 participants) and her PM = 32500000000000000000 

`Step 5` : add Satoshi(0x321) and Vitalik(0x654) as minters, addMinters(address _minter) 

`Step 6` : call trigger() from Alice / Bob&apos;s / Satoshi / Vitalik account. 101 blocks are passed, hence 101 SIM tokens are minted. The RM is 57750000000000000000

`Step 7` : Alice withdraws and receives 25.25 SIM tokens (101 tokens / 4 participants) and her PM = 57750000000000000000

`Step 8` : Bob withdraws and receives 57.75 SIM tokens ((65 tokens / 2 participants) + (101 tokens / 4 participants)). Bob&apos;s PM = 57750000000000000000
 
## Copyright

Copyright and related rights waived via CC0.

## References

1. Scalable Reward Distribution on the Ethereum Blockchain by Bogdan Batog, Lucian Boca and Nick Johnson

2. Fomo3d DApp, https://fomo3d.hostedwiki.co/
</description>
        <pubDate>Mon, 01 Apr 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1973</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1973</guid>
      </item>
    
      <item>
        <title>Sane limits for certain EVM parameters</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-1985-sane-limits-for-certain-evm-parameters/3224</comments>
        
        <description>## Abstract

Introduce an explicit value range for certain EVM parameters
(such as gas limit, block number, block timestamp, size field when returning/copying data within EVM).
Some of these already have an implicit value range due to various (practical) reasons.

## Motivation

Having such an explicit value range can help in creating compatible client implementations,
in certain cases it can also offer minor speed improvements,
and can reduce the effort needed to create consensus critical test cases
by eliminating unrealistic edge cases.

## Specification

If `block.number &gt;= {FORK_BLOCK}`, the following value ranges are introduced.
They restrict the results (i.e. values pushed to the stack) of the instructions listed below.

1. *gas*, *gas limit*, *block gas limit*
   is a range between `0` and `0x7fffffffffffffff` (`2**63 - 1`, `9223372036854775807`).
   It affects the following instructions:
   - `GASLIMIT` (`0x45`),
   - `GAS` (`0x5a`).

2. *block number*, *timestamp*
   is a range between `0` and `0x7fffffffffffffff` (`2**63 - 1`, `9223372036854775807`).
   It affects the following instructions:
   - `TIMESTAMP` (`0x42`),
   - `NUMBER` (`0x43`).

3. *account address*
   is a range between `0` and `0xffffffffffffffffffffffffffffffffffffffff` (`2**160 - 1`, `1461501637330902918203684832716283019655932542975`)
   i.e. the address occupies the 160 low bits of the 256-bit value and the remaining top 96 bits must be zeros.
   It affects the following instructions:
   - `ADDRESS` (`0x30`),
   - `ORIGIN` (`0x32`),
   - `CALLER` (`0x33`),
   - `COINBASE` (`0x41`),
   - `CREATE` (`0xf0`),
   - `CREATE2` (`0xf5`).

4. *buffer size*, *code size*, *memory size*
   is a range between `0` and `0xffffffff` (`2**32 - 1`, `4294967295`).
   It affects the following instructions:
   - `CALLDATASIZE` (`0x36`),
   - `CODESIZE` (`0x38`),
   - `EXTCODESIZE` (`0x3b`),
   - `RETURNDATASIZE` (`0x3d`),
   - `MSIZE` (`0x59`),
   - `PC` (`0x58`).


## Rationale

These limits have been:
- proposed by [EVMC]
- implemented partially by certain clients, such as [Aleth], [geth], [Parity] and [ethereumjs]
- allowed by certain test cases in the [Ethereum testing suite]
- and implicitly also allowed by certain assumptions, such as due to gas limits some of these values cannot grow past a certain limit

Most of the limits proposed in this document have been previously explored and tested in [EVMC].

Using the `2**63 - 1` constant to limit some of the ranges:
- allows using signed 64-bit integer type to represent it,
  what helps programming languages not having unsigned types,
- makes arithmetic simpler (e.g. checking out-of-gas conditions is simple as `gas_counter &lt; 0`).

### Timestamp

The [Yellow Paper] defines the timestamp in block as &quot;A scalar value equal to the reasonable output of Unix’s time() at this block’s inception&quot;.
IEEE Std 1003.1-2001 (POSIX.1) leaves that definition implementation defined.

### Addresses

The size of addresses is specified in the [Yellow Paper] as 20 bytes.
E.g. the `COINBASE` instruction is specified to return *H*&lt;sub&gt;c&lt;/sub&gt; ∈ 𝔹&lt;sub&gt;20&lt;/sub&gt; which has 20 bytes.

### Memory size

Memory expansion cost is not linear and is determined by the following formula:
        cost = cost_per_word * number_of_words + (number_of_words ^ 2 / 512)

Expanding to over `2^32 - 1` bytes would cost `35184774742016` gas. This number fits into the gas limit imposed above (`2 ^ 63 - 1`) and would cost around 35184 Ether in a transaction to exhaust, with a 1 GWei gas cost, which can be attained on mainnet.

However, setting the limit `2^32 - 1` is beneficial from a VM design perspective and we believe limiting memory should be done via carefully selecting the block gas limit.

### Code size

[EIP-170](/EIPs/EIPS/eip-170) has implemented a code size limit of 0x6000, however even before that, it was practically impossible to deploy a code blob exceeding `2**32 - 1` bytes in size.

### Comparing current implementations

- Timestamp is implemented as a 64-bit value in [Aleth], [geth] and [Parity]
- Block gas limit is implemented as a 64-bit in [Aleth] and [geth]
- Memory, buffer and code sizes are implemented as 64-bit values in [geth]

## Backwards Compatibility

All of these limits are already enforced mostly through the block gas limit. Since the out of range case results in a transaction failure, there should not be a change in behaviour.

## Test Cases

TBA

## Implementation

TBA

## References

- [EIP-92](https://github.com/ethereum/EIPs/issues/92) proposed the transaction gas limit to be limited at `2**63 - 1` and had a lengthy discussion about other limits.
- [EIP-106](https://github.com/ethereum/EIPs/issues/106) proposed the block gas limit to be limited at `2**63 - 1`.

## TODO

1. Does the gas limit apply to the gas argument for call instructions?

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[EVMC]: https://github.com/ethereum/evmc
[Aleth]: https://github.com/ethereum/aleth
[geth]: https://github.com/ethereum/go-ethereum
[Parity]: https://github.com/paritytech/parity-ethereum
[ethereumjs]: https://github.com/ethereumjs
[Ethereum testing suite]: https://github.com/ethereum/tests
[Yellow Paper]: https://github.com/ethereum/yellowpaper
</description>
        <pubDate>Wed, 01 Aug 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1985</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1985</guid>
      </item>
    
      <item>
        <title>Holdable Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2103</comments>
        
        <description>## Simple Summary
An extension to the ERC-20 standard token that allows tokens to be put on hold. This guarantees a future transfer and makes the held tokens unavailable for transfer in the mean time. Holds are similar to escrows in that are firm and lead to final settlement.

## Actors

#### Operator
An account which has been approved by an account to create holds on its behalf.

#### Hold issuer
The account, which creates a hold. This can be the account owner itself, or any account, which has been approved as an operator for the account.

#### Notary
The account which decides if a hold should be executed. 

## Abstract
A hold specifies a payer, a payee, a maximum amount, a notary and an expiration time. When the hold is created, the specified token balance from the payer is put on hold. A held balance cannot be transferred until the hold is either executed or released. The hold can only be executed by the notary, which triggers the transfer of the tokens from the payer to the payee. If a hold is released, either by the notary at any time, or by anyone after the expiration, no transfer is carried out and the amount is available again for the payer.

A hold can be partially executed, if the execution specifies an amount less than the maximum amount. In this case the specified amount is transferred to the payee and the remaining amount is available again to the payer.

Holds can be specified to be perpetual. In this case, the hold cannot be released upon expiration, and thus can only be executed by the notary or released by the notary or payee.

## Motivation

A hold has to be used in different scenarios where a immediate transfer between accounts is not possible or has to be guaranteed beforehand:

1. A regulated token may not allow to do a token transfer between accounts without verifying first, that it follows all the regulations. In this case a clearable transfer has to be used. During the clearing process a hold is created to ensure, that the transfer is successful after all checks have passed. If the transfer violates any of the regulations, it is cleared and not further processed. 

1. In certain business situations a payment has to be guaranteed before its services can be used. For example: When checking in a hotel, the hotel will put a hold on the guest&apos;s account to ensure that enough balance is available to pay for the room before handing over the keys.

1. In other occasions a payment has to be guaranteed without knowing the exact amount beforehand. To stay with the hotel example: The hotel can put a hold on the guest&apos;s account as a guarantee for any possible extras, like room service. When the guest checks out the hold is partially executed and the remaining amount is available again on the guest&apos;s account.

The ERC-20 `approve` function provides some of the necessary functionality for the use cases above. The main difference to holds, is that `approve` does not ensure a payment, as the approved money is not blocked and can be transferred at any moment.

## Specification

```solidity
interface IHoldable /* is ERC-20 */ {
    enum HoldStatusCode {
        Nonexistent,
        Ordered,
        Executed,
        ReleasedByNotary,
        ReleasedByPayee,
        ReleasedOnExpiration
    }

    function hold(string calldata operationId, address to, address notary, uint256 value, uint256 timeToExpiration) external returns (bool); 
    function holdFrom(string calldata operationId, address from, address to, address notary, uint256 value, uint256 timeToExpiration) external returns (bool);
    function releaseHold(string calldata operationId) external returns (bool);
    function executeHold(string calldata operationId, uint256 value) external returns (bool);
    function renewHold(string calldata operationId, uint256 timeToExpiration) external returns (bool);
    function retrieveHoldData(string calldata operationId) external view returns (address from, address to, address notary, uint256 value, uint256 expiration, HoldStatusCode status);

    function balanceOnHold(address account) external view returns (uint256);
    function netBalanceOf(address account) external view returns (uint256);
    function totalSupplyOnHold() external view returns (uint256);

    function authorizeHoldOperator(address operator) external returns (bool);
    function revokeHoldOperator(address operator) external returns (bool);
    function isHoldOperatorFor(address operator, address from) external view returns (bool);

    event HoldCreated(address indexed holdIssuer, string  operationId, address from, address to, address indexed notary, uint256 value, uint256 expiration);
    event HoldExecuted(address indexed holdIssuer, string operationId, address indexed notary, uint256 heldValue, uint256 transferredValue);
    event HoldReleased(address indexed holdIssuer, string operationId, HoldStatusCode status);
    event HoldRenewed(address indexed holdIssuer, string operationId, uint256 oldExpiration, uint256 newExpiration);
    event AuthorizedHoldOperator(address indexed operator, address indexed account);
    event RevokedHoldOperator(address indexed operator, address indexed account);
}
```

### Functions

#### hold

Creates a hold on behalf of the msg.sender in favor of the payee. It specifies a notary who is responsible to either execute or release the hold. The function must revert if the operation ID has been used before.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify the hold |
| to | The address of the payee, to whom the tokens are to be transferred if executed |
| notary | The address of the notary who is going to determine whether the hold is to be executed or released |
| value | The amount to be transferred. Must be less or equal than the balance of the payer. |
| timeToExpiration | The duration until the hold is expired. If it is &apos;0&apos; the hold must be perpetual.  |

#### holdFrom

Creates a hold on behalf of the payer in favor of the payee. The `from` account has to approve beforehand, that another account can issue holds on its behalf by calling `approveToHold`. The function must revert if the operation ID has been used before.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify the hold |
| from | The address of the payer, from whom the tokens are to be taken if executed |
| to | The address of the payee, to whom the tokens are to be transferred if executed |
| notary | The address of the notary who is going to determine whether the hold is to be executed or released |
| value | The amount to be transferred. Must be less or equal than the balance of the payer. |
| timeToExpiration | The duration until the hold is expired. If it is &apos;0&apos; the hold must be perpetual.  |

#### releaseHold

Releases a hold. Release means that the transfer is not executed and the held amount is available again for the payer. Until a hold has expired it can only be released by the notary or the payee. After it has expired it can be released by anyone.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify the hold |

#### executeHold

Executes a hold. Execute means that the specified value is transferred from the payer to the payee. If the specified value is less than the hold value the remaining amount is available again to the payer. The implementation must verify that only the notary is able to successfully call the function.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify the hold |
| value | The amount to be transferred. This amount has to be less or equal than the hold value |

#### renewHold

Renews a hold. The new expiration time must be the block timestamp plus the given `timeToExpiration`, independently if the hold was perpetual or not before that. Furthermore a hold must be made perpetual if `timeToExpiration` is &apos;0&apos;. The implementation must verify that only the payer or operator are able to successfully call the function. Furthermore the only a hold, which has not yet expired can be successfully renewed.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify the hold |
| timeToExpiration | The new duration until the hold is expired. |

#### retrieveHoldData

Retrieves all the information available for a particular hold.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify the hold |

#### balanceOnHold

Retrieves how much of the balance is currently held and therefore not available for transfer.

| Parameter | Description |
| ---------|-------------|
| account | The address which held balance should be returned |

#### netBalanceOf

Retrieves the net balance, which is the sum of `balanceOf` and `balanceOnHold`.

| Parameter | Description |
| ---------|-------------|
| account | The address which net balance should be returned |

#### totalSupplyOnHold

Retrieves the total sum of how many tokens are on hold.

| Parameter | Description |
| ---------|-------------|
| - | - |

#### authorizeHoldOperator

Approves an operator to issue holds on behalf of msg.sender.

| Parameter | Description |
| ---------|-------------|
| operator | The address to be approved as operator of holds |

#### revokeHoldOperator

Revokes the approval to issue holds on behalf of msg.sender.

| Parameter | Description |
| ---------|-------------|
| operator | The address to be revoked as operator of holds |

#### isHoldOperatorFor

Retrieves if an operator is approved to create holds on behalf of `from`.

| Parameter | Description |
| ---------|-------------|
| operator | The address to be a operator of holds |
| from | The address on which the holds would be created |

#### balanceOf

The standard implementation of ERC-20 has to be changed in order to deduct the held balance from the ERC-20 balance.

#### transfer

The standard implementation of ERC-20 has to be changed in order to deduct the held balance from the ERC-20 balance. Any amount that is held must not be transferred.

#### transferFrom

The standard implementation of ERC-20 has to be changed in order to deduct the held balance from the ERC-20 balance. Any amount that is held must not be transferred.

### Events

#### HoldCreated

Emitted when a hold has been created.

| Parameter | Description |
| ---------|-------------|
| holdIssuer | The address of the hold issuer of the hold |
| operationId | The unique ID to identify the hold |
| from | The address of the payer, from whom the tokens are to be taken if executed |
| to | The address of the payee, to whom the tokens are to be paid if executed |
| notary | The address of the notary who is going to determine whether the hold is to be executed or released |
| value | The amount to be transferred. Must be less or equal than the balance of the payer. |
| expiration | The unix timestamp when the hold is expired |

#### HoldExecuted

Emitted when a hold has been executed.

| Parameter | Description |
| ---------|-------------|
| holdIssuer | The address of the hold issuer of the hold |
| operationId | The unique ID to identify the hold |
| notary | The address of the notary who executed the hold |
| heldValue | The amount which was put on hold during creation |
| transferredValue | The amount which was used for the transfer |

#### HoldReleased

Emitted when a hold has been released.

| Parameter | Description |
| ---------|-------------|
| holdIssuer | The address of the hold issuer of the hold |
| operationId | The unique ID to identify the hold |
| status | Can be one of the following values: `ReleasedByNotary`, `ReleasedByPayee`, `ReleasedOnExpiration` |

#### HoldRenewed

Emitted when a hold has been renewed.

| Parameter | Description |
| ---------|-------------|
| holdIssuer | The address of the hold issuer of the hold |
| operationId | The unique ID to identify the hold |
| oldExpiration | The expiration time before the renewal |
| newExpiration | The expiration time after the renewal |

#### AuthorizedHoldOperator

Emitted when an operator has been approved to create holds on behalf of another account.

| Parameter | Description |
| ---------|-------------|
| operator | The address to be a operator of holds |
| account | Address on which behalf holds will potentially be created |

#### RevokedHoldOperator

Emitted when an operator has been revoked from creating holds on behalf of another account.

| Parameter | Description |
| ---------|-------------|
| operator | The address to be a operator of holds |
| account | Address on which behalf holds could potentially be created |

## Rationale

This standards provides a functionality, to guarantee future payments, which is needed for many business cases where transfers have to be guaranteed.

It goes a step further than the ERC-20 `approve` function by ensuring that the held balance will be available when the transfer is done. Something that can not be done with `approve`, as the approved amount is only a maximum spending amount, but never guaranteed to be available.

While not requiring it, the naming of the functions `authorizeHoldOperator`, `revokeHoldOperator` and `isHoldOperatorFor` follows the naming convention of [ERC-777](/EIPs/EIPS/eip-777).

The `operationId` is a string and not something more gas efficient to allow easy traceability of the hold and allow human readable ids. It is up to the implementer if the string should be stored on-chain or only its hash, as it is enough to identify a hold.

The `operationId` is a competitive resource. It is recommended, but nor required, that the hold issuers used a unique prefix to avoid collisions. 

## Backwards Compatibility
This EIP is fully backwards compatible as its implementation extends the functionality of ERC-20.

## Implementation
The GitHub repository [IoBuilders/holdable-token](https://github.com/IoBuilders/holdable-token) contains the reference implementation.

## Contributors
This proposal has been collaboratively implemented by [adhara.io](https://adhara.io/) and [io.builders](https://io.builders/).

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 10 Apr 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-1996</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-1996</guid>
      </item>
    
      <item>
        <title>EVMC modules for implementations of precompiled contracts</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://github.com/ethereum/evmc/issues/259</comments>
        
        <description>## Abstract

[EVMC] specifies a generic API for Ethereum execution engines.
This EIP specifies a way of providing implementations of Ethereum precompiled contracts
using the [EVMC VM API].


## Specification

For the complete [EVMC] specification visit the [EVMC documentation] first.
This EIP is based on and is compatible with EVMC ABI version 6.

The EVMC module with implementations of precompiled contracts SHOULD:

1. Advertise the [`EVMC_CAPABILITY_PRECOMPILES`] capability
   in the [`get_capabilities()`] method.

2. Implement the [`execute()`] method in the following way:

   1. Validate the incoming execution request requirements:

      1. The message kind ([`evmc_message::kind`]) is a call ([`EVMC_CALL`]).

      2. The call destination address ([`evmc_message::destination`])
         is within the range of precompiled contracts defined by [EIP-1352].

      3. There is no code provided (the `code` argument is `NULL` and `code_size` argument is `0`).

      If the requirements are not fulfilled, abort execution with the [`EVMC_REJECTED`] status code.

   2. Check if the call destination address ([`evmc_message::destination`])
      targets existing precompiled contract.
      Consider the EVM revision ([`evmc_revision`]) requested by
      the `rev` parameter of [`execute()`].

      If yes, execute as follows:

      1. Inspect the input data ([`evmc_message::input_data`], [`evmc_message::input_size`])
         and calculate the _gas cost_ of the execution.

      2. Compute the amount of _gas left_ after execution by
         subtracting the _gas cost_ from the call gas limit ([`evmc_message::gas`]).

      3. If _gas left_ is negative,
         abort execution with the [`EVMC_OUT_OF_GAS`] status code.

      4. Otherwise,
         execute the code of the precompiled contract,
         return the [`EVMC_SUCCESS`] status code, the output and _gas left_
         ([`evmc_result::output_data`], [`evmc_result::output_size`], [`evmc_result::gas_left`]).

   3. Otherwise, emulate execution of empty code by returning
      the [`EVMC_SUCCESS`] status code
      and _gas left_ equal the call gas limit ([`evmc_message::gas`]).

Precompiled contract implementations are allowed to return two more EVMC error codes:
- [`EVMC_FAILURE`] if the failure was caused due to something other than out of gas (e.g. input validation error)
- [`EVMC_REVERT`] if the precompile doesn&apos;t want to forfeit all supplied gas (as of May 2019 no such precompile exists)

The Client is not required to provide the Host interface ([`evmc_context`] argument of [`execute()`] is set to NULL).
Therefore, the precompiled contracts implementation MUST NOT access the `evmc_context`.


## Rationale

It is very unlikely that any precompile will need to access or modify a contract state.
Not requiring the Client to implement the EVMC Host interface removes the big portion of work
needed for full EVMC integration.


## Test Cases

EVMC provides the [evmc-vmtester] tool for checking compatibility with the EVMC specification.


## Implementations

- [Example of Precompiles VM implementation][example_precompiles_vm.cpp]
- [ewasm precompiles]
- Aleth code for precompiles
- Parity code for precompiles
- [EIP-1962 implemented as an EVMC precompile module](https://github.com/axic/eip1962-evmc)


## References

- [EVMC – Ethereum Client-VM Connector API][EVMC]
- [EVMC documentation]
- [EVMC VM Implementation Guide][EVMC VM API]
- [EIP 1352: Specify restricted address range for precompiles/system contracts][EIP-1352]


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[EIP-1352]: /EIPs/EIPS/eip-1352
[EVMC]: https://github.com/ethereum/evmc
[EVMC documentation]: https://ethereum.github.io/evmc/
[EVMC VM API]: https://ethereum.github.io/evmc/vmguide.html
[evmc-vmtester]: https://evmc.ethereum.org/vmtester.html
[example_precompiles_vm.cpp]: https://github.com/ethereum/evmc/blob/master/examples/example_precompiles_vm/example_precompiles_vm.cpp
[ewasm precompiles]: https://github.com/ewasm/ewasm-precompiles

[`EVMC_CALL`]: https://ethereum.github.io/evmc/group__EVMC.html#ggab2fa68a92a6828064a61e46060abc634abcf3ae29d9a88ff70b98374fc665694a
[`EVMC_CAPABILITY_PRECOMPILES`]: https://ethereum.github.io/evmc/group__EVMC.html#gga44f9ecb88cf6422a0072936494fd6ac7a43ea2aa7b099a2d67bc53c118ff3683d
[`EVMC_FAILURE`]: https://ethereum.github.io/evmc/group__EVMC.html#gga4c0be97f333c050ff45321fcaa34d920aed5b2a4afa5a47af732569445920a4a9
[`EVMC_OUT_OF_GAS`]: https://ethereum.github.io/evmc/group__EVMC.html#gga4c0be97f333c050ff45321fcaa34d920abfc47f75656c996c0b29c0553c00fc18
[`EVMC_REJECTED`]: https://ethereum.github.io/evmc/group__EVMC.html#gga4c0be97f333c050ff45321fcaa34d920a2f3e0d8777f8d974ead27ae2a6eb2005
[`EVMC_REVERT`]: https://ethereum.github.io/evmc/group__EVMC.html#gga4c0be97f333c050ff45321fcaa34d920aed708e84d49cc1270e54ec20b0ca0a05
[`EVMC_SUCCESS`]: https://ethereum.github.io/evmc/group__EVMC.html#gga4c0be97f333c050ff45321fcaa34d920a4bc3069fec2bab2a55355a72b7db68b7
[`execute()`]: https://ethereum.github.io/evmc/structevmc__instance.html#a0823ebff21f9b0395b157e8c6b14a207
[`get_capabilities()`]: https://ethereum.github.io/evmc/structevmc__instance.html#ae63b9ca898aa41cbd1e2fe86ca8f4e1c
[`evmc_message::destination`]: https://ethereum.github.io/evmc/structevmc__message.html#a88ecfaa03a85a31c6da36fa043b98cea
[`evmc_message::input_data`]: https://ethereum.github.io/evmc/structevmc__message.html#a1adee3454b105eb29cd659ee0cf65c77
[`evmc_message::input_size`]: https://ethereum.github.io/evmc/structevmc__message.html#a2cf1deebd0dbbb20f25ecdfa299f4b5d
[`evmc_message::gas`]: https://ethereum.github.io/evmc/structevmc__message.html#ae8deff46588584fa27890e74c82db5e7
[`evmc_message::kind`]: https://ethereum.github.io/evmc/structevmc__message.html#a691cb93e81d6dfd4fd7e2fa3d06a6bfa
[`evmc_result::gas_left`]: https://ethereum.github.io/evmc/structevmc__result.html#af8478c93dbcc3cb2876037c5a5afd4c0
[`evmc_result::output_data`]: https://ethereum.github.io/evmc/structevmc__result.html#a61978e85f9d795a7b9695b9cbf1748d6
[`evmc_result::output_size`]: https://ethereum.github.io/evmc/structevmc__result.html#a93bb7419aff492cdef754421c6d74e26
[`evmc_revision`]: https://ethereum.github.io/evmc/group__EVMC.html#gae5759b1590071966ccf6a505b52a0ef7
</description>
        <pubDate>Thu, 09 May 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2003</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2003</guid>
      </item>
    
      <item>
        <title>Compliance Service</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2022</comments>
        
        <description>## Simple Summary

This EIP proposes a service for decentralized compliance checks for regulated tokens. 

## Actors

#### Operator
An account which has been approved by a token to update the tokens accumulated.

#### Token
An account, normally a smart contract, which uses the `Compliance Service` to check if the an action can be executed or not.

#### Token holder
An account which is in possession of tokens and on for which the checks are made.

## Abstract

A regulated token needs to comply with several legal requirements, especially [KYC][KYC-Wikipedia] and [AML][AML-Wikipedia]. If the necessary checks have to be made off-chain the token transfer becomes centralized. Further the transfer in this case takes longer to complete as it can not be done in one transaction, but requires a second confirmation step. The goal of this proposal is to make this second step unnecessary by providing a service for compliance checks.

## Motivation

Currently there is no proposal on how to accomplish decentralized compliance checks. [ERC-1462][ERC-1462] proposes a basic set of functions to check if `transfer`, `mint` and `burn` are allowed for a user, but not how those checks should be implemented. This EIP proposes a way to implement them fully on-chain while being generic enough to leave the actual implementation of the checks up to the implementers, as these may vary a lot between different tokens.  

The proposed `Compliance Service` supports more than one token. Therefore it could be used by law-makers to maintain the compliance rules of regulated tokens in one smart contract. This smart contract could be used by all of the tokens that fall under this jurisdiction and ensure compliance with the current laws.

By having a standard for compliance checks third-party developers can use them to verify if token movements for a specific account are allowed and act accordingly.

## Specification

```solidity
interface CompliantService {
    function checkTransferAllowed(bytes32 tokenId, address from, address to, uint256 value) external view returns (byte);
    function checkTransferFromAllowed(bytes32 tokenId, address sender, address from, address to, uint256 value) external view returns (byte);
    function checkMintAllowed(bytes32 tokenId, address to, uint256 value) external view returns (byte);
    function checkBurnAllowed(bytes32 tokenId, address from, uint256 value) external view returns (byte);
    
    function updateTransferAccumulated(bytes32 tokenId, address from, address to, uint256 value) external;
    function updateMintAccumulated(bytes32 tokenId, address to, uint256 value) external;
    function updateBurnAccumulated(bytes32 tokenId, address from, uint256 value) external;
    
    function addToken(bytes32 tokenId, address token) external;
    function replaceToken(bytes32 tokenId, address token) external;
    function removeToken(bytes32 tokenId) external;
    function isToken(address token) external view returns (bool);
    function getTokenId(address token) external view returns (bytes32);
    
    function authorizeAccumulatedOperator(address operator) external returns (bool);
    function revokeAccumulatedOperator(address operator) external returns (bool);
    function isAccumulatedOperatorFor(address operator, bytes32 tokenId) external view returns (bool);
    
    event TokenAdded(bytes32 indexed tokenId, address indexed token);
    event TokenReplaced(bytes32 indexed tokenId, address indexed previousAddress, address indexed newAddress);
    event TokenRemoved(bytes32 indexed tokenId);
    event AuthorizedAccumulatedOperator(address indexed operator, bytes32 indexed tokenId);
    event RevokedAccumulatedOperator(address indexed operator, bytes32 indexed tokenId);
}
```

### Mandatory checks

The checks must be verified in their corresponding actions. The action must only be successful if the check return an `Allowed` status code. In any other case the functions must revert.

### Status codes

If an action is allowed `0x11` (Allowed) or an issuer-specific code with equivalent but more precise meaning must be returned. If the action is not allowed the status must be `0x10` (Disallowed) or an issuer-specific code with equivalent but more precise meaning. 

### Functions

#### checkTransferAllowed

Checks if the `transfer` function is allowed to be executed with the given parameters.

| Parameter | Description |
| ---------|-------------|
| tokenId | The unique ID which identifies a token |
| from | The address of the payer, from whom the tokens are to be taken if executed |
| to | The address of the payee, to whom the tokens are to be transferred if executed |
| value | The amount to be transferred |

#### checkTransferFromAllowed

Checks if the `transferFrom` function is allowed to be executed with the given parameters.

| Parameter | Description |
| ---------|-------------|
| tokenId | The unique ID which identifies a token |
| sender | The address of the sender, who initiated the transaction |
| from | The address of the payer, from whom the tokens are to be taken if executed |
| to | The address of the payee, to whom the tokens are to be transferred if executed |
| value | The amount to be transferred |

#### checkMintAllowed

Checks if the `mint` function is allowed to be executed with the given parameters.

| Parameter | Description |
| ---------|-------------|
| tokenId | The unique ID which identifies a token |
| to | The address of the payee, to whom the tokens are to be given if executed |
| value | The amount to be minted |

#### checkBurnAllowed

Checks if the `burn` function is allowed to be executed with the given parameters.

| Parameter | Description |
| ---------|-------------|
| tokenId | The unique ID which identifies a token |
| from | The address of the payer, from whom the tokens are to be taken if executed |
| value | The amount to be burned |

#### updateTransferAccumulated

Must be called in the same transaction as `transfer` or `transferFrom`. It must revert if the update violates any of the compliance rules. It is up to the implementer which specific logic is executed in the function.

| Parameter | Description |
| ---------|-------------|
| tokenId | The unique ID which identifies a token |
| from | The address of the payer, from whom the tokens are to be taken if executed |
| to | The address of the payee, to whom the tokens are to be transferred if executed |
| value | The amount to be transferred |

#### updateMintAccumulated

Must be called in the same transaction as `mint`. It must revert if the update violates any of the compliance rules. It is up to the implementer which specific logic is executed in the function.

| Parameter | Description |
| ---------|-------------|
| tokenId | The unique ID which identifies a token |
| to | The address of the payee, to whom the tokens are to be given if executed |
| value | The amount to be minted |

#### updateBurnAccumulated

Must be called in the same transaction as `burn`. It must revert if the update violates any of the compliance rules. It is up to the implementer which specific logic is executed in the function.

| Parameter | Description |
| ---------|-------------|
| tokenId | The unique ID which identifies a token |
| from | The address of the payer, from whom the tokens are to be taken if executed |
| value | The amount to be minted |

#### addToken

Adds a token to the service, which allows the token to call the functions to update the accumulated. If an existing token id is used the function must revert. It is up to the implementer if adding a token should be restricted or not.

| Parameter | Description |
| ---------|-------------|
| tokenId | The unique ID which identifies a token |
| token | The address from which the update functions will be called |

#### replaceToken

Replaces the address of a added token with another one. It is up to the implementer if replacing a token should be restricted or not, but a token should be able to replace its own address.

| Parameter | Description |
| ---------|-------------|
| tokenId | The unique ID which identifies a token |
| token | The address from which the update functions will be called |

#### removeToken

Removes a token from the service, which disallows the token to call the functions to update the accumulated. It is up to the implementer if removing a token should be restricted or not.

| Parameter | Description |
| ---------|-------------|
| tokenId | The unique ID which identifies a token |

#### isToken

Returns `true` if the address has been added to the service, `false` if not.

| Parameter | Description |
| ---------|-------------|
| token | The address which should be checked |

#### getTokenId

Returns the token id of a token. If the token has not been added to the service, &apos;0&apos; must be returned.

| Parameter | Description |
| ---------|-------------|
| token | The address which token id should be returned |

#### authorizeAccumulatedOperator

Approves an operator to update accumulated on behalf of the token id of msg.sender.

| Parameter | Description |
| ---------|-------------|
| operator | The address to be approved as operator of accumulated updates |

#### revokeAccumulatedOperator

Revokes the approval to update accumulated on behalf the token id the token id ofof msg.sender.

| Parameter | Description |
| ---------|-------------|
| operator | The address to be revoked as operator of accumulated updates |

#### isAccumulatedOperatorFor

Retrieves if an operator is approved to create holds on behalf of `tokenId`.

| Parameter | Description |
| ---------|-------------|
| operator | The address which is operator of updating the accumulated |
| tokenId | The unique ID which identifies a token |

### Events

#### TokenAdded

Must be emitted after a token has been added.

| Parameter | Description |
| ---------|-------------|
| tokenId | The unique ID which identifies a token |
| token | The address from which the update functions will be called |

#### TokenReplaced

Must be emitted after the address of a token has been replaced.

| Parameter | Description |
| ---------|-------------|
| tokenId | The unique ID which identifies a token |
| previousAddress | The previous address which was used before |
| newAddress | The address which will be used from now on |

#### TokenRemoved

Must be emitted after the a token has been removed.

| Parameter | Description |
| ---------|-------------|
| tokenId | The unique ID which identifies a token |

#### AuthorizedAccumulatedOperator

Emitted when an operator has been approved to update the accumulated on behalf of a token.

| Parameter | Description |
| ---------|-------------|
| operator | The address which is operator of updating the accumulated |
| tokenId | Token id on which behalf updates of the accumulated will potentially be made |

#### RevokedHoldOperator

Emitted when an operator has been revoked from updating the accumulated on behalf of a token.

| Parameter | Description |
| ---------|-------------|
| operator | The address which was operator of updating the accumulated |
| tokenId | Token id on which behalf updates of the accumulated could be made |

## Rationale

The usage of a token id instead of the address has been chosen to give tokens the possibility to update their smart contracts and keeping all their associated accumulated. If the address would be used, a migration process would needed to be done after a smart contract update.

No event is emitted after updating the accumulated as those are always associated with a `transfer`, `mint` or `burn` of a token which already emits an event of itself.

While not requiring it, the naming of the functions `checkTransferAllowed`, `checkTransferFromAllowed`, `checkMintAllowed` and `checkBurnAllowed` was adopted from [ERC-1462][ERC-1462].

While not requiring it, the naming of the functions `authorizeAccumulatedOperator`, `revokeAccumulatedOperator` and `isAccumulatedOperatorFor` follows the naming convention of [ERC-777][ERC-777].

Localization is not part of this EIP, but [ERC-1066][ERC-1066] and [ERC-1444][ERC-1444] can be used together to achieve it.

## Backwards Compatibility

As the EIP is not using any existing EIP there are no backwards compatibilities to take into consideration.

## Implementation

The GitHub repository [IoBuilders/compliance-service](https://github.com/IoBuilders/compliance-service) contains the work in progress implementation.

## Contributors
This proposal has been collaboratively implemented by [adhara.io](https://adhara.io/) and [io.builders](https://io.builders/).

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[KYC-Wikipedia]: https://en.wikipedia.org/wiki/Know_your_customer
[AML-Wikipedia]: https://en.wikipedia.org/wiki/Money_laundering#Anti-money_laundering

[ERC-777]: /EIPs/EIPS/eip-777

[ERC-1066]: /EIPs/EIPS/eip-1066

[ERC-1444]: /EIPs/EIPS/eip-1444

[ERC-1462]: /EIPs/EIPS/eip-1462
</description>
        <pubDate>Thu, 09 May 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2009</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2009</guid>
      </item>
    
      <item>
        <title>Extended State Oracle</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2014-extended-state-oracle/3301</comments>
        
        <description>## Simple Summary

## Abstract

Introduce a new system contract with an extensible interface following the [Contract ABI Encoding] to access extended data sets, such as chain identifiers, block hashes, etc.

This allows Ethereum contract languages to interact with this contract as if it were a regular contract and not needing any language support.

## Motivation

Over the past couple of years several proposals were made to extend the EVM with more data. Some examples include extended access to block hashes ([EIP-210]) and chain identifiers ([EIP-1344]).

Adding them as EVM opcodes seems to be using the scarce opcode space for relatively less frequently used features, while adding them as precompiles is perceived as more complicated due to an interface
needs to be defined and agreed on for every case.

This proposal tries to solve both issues with defining an extensible standard interface.

## Specification

A new system contract (&quot;precompile&quot;) is introduced at address `0x0000000000000000000000000000000000000009` called ESO (Extended State Oracle).

It can be queried using `CALL` or `STATICCALL` and follows the [Contract ABI Encoding] for the inputs and outputs. Using elementary types in the ABI encoding is encouraged to keep complexity low.

In the future it could be possible to extend ESO to have a state and accept transactions from a system address to store the passed data -- similarly to what [EIP-210] proposed.

Proposals wanting to introduce more data to the state, which is not part of blocks or transactions, should aim to extend the ESO.

At this time it is not proposed to make the ESO into a contract existing in the state, but to include it as a precompile and leave the implementation details to the client.
In the future if it is sufficiently extended and a need arises to have a state, it would make sense to move it from being a precompile and have actual code.

### Chain identifier

Initially, a feature to read the current chain identifier is introduced: `getCurrentChainId()` returns the current chain identifier as a `uint64` encoded value.
It should be a non-payable function, which means sending any value would revert the transaction as described in [EIP-140].
This has been proposed as [EIP-1344].

The contract ABI JSON is the following:
```json
[
    {
	&quot;constant&quot;: true,
	&quot;inputs&quot;: [],
	&quot;name&quot;: &quot;getCurrentChainId&quot;,
	&quot;outputs&quot;: [
	    {
		&quot;name&quot;: &quot;&quot;,
		&quot;type&quot;: &quot;uint64&quot;
	    }
	],
	&quot;payable&quot;: false,
	&quot;stateMutability&quot;: &quot;pure&quot;,
	&quot;type&quot;: &quot;function&quot;
    }
]
```

This will be translated into sending the bytes `5cf0e8a4` to the ESO and returning the bytes `0000000000000000000000000000000000000000000000000000000000000001` for Ethereum mainnet.

**Note:** It should be possible to introduce another interface checking the validity of a chain identifier in the chain history or for a given block (see [EIP-1959] and [EIP-1965]).

## Rationale

TBA

## Backwards Compatibility

TBA

## Test Cases

TBA

## Implementation

TBA

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[Contract ABI Encoding]: https://solidity.readthedocs.io/en/latest/abi-spec.html

[EIP-140]: /EIPs/EIPS/eip-140

[EIP-210]: /EIPs/EIPS/eip-210

[EIP-1344]: /EIPs/EIPS/eip-1344
[EIP-1959]: https://github.com/ethereum/EIPs/pull/1959
[EIP-1965]: https://github.com/ethereum/EIPs/pull/1965
</description>
        <pubDate>Fri, 10 May 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2014</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2014</guid>
      </item>
    
      <item>
        <title>wallet_updateEthereumChain RPC Method</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2015-wallet-update-chain-json-rpc-method-wallet-updatechain/3274</comments>
        
        <description>## Abstract

This EIP adds a wallet-namespaced RPC endpoint, `wallet_updateEthereumChain`, providing a standard interface for switching chains. The method takes the minimal parameters of `chainId`, `chainName`, `rpcUrl`, `nativeCurrency` and `blockExplorerUrl`.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

This proposal adds a method to a wallet&apos;s web3 provider API: `wallet_updateEthereumChain`.

### `wallet_updateEthereumChain`

The `wallet_updateEthereumChain` method is used to switch to a network, and registering it with the wallet if it isn&apos;t already recognized.

The `wallet_updateEthereumChain` method takes one parameter, an `EthereumChainSwitchRequest` object, defined below:

```typescript
interface NativeCurrencyData {
  name: string;
  symbol: string;
  decimals: number;
}

interface EthereumChainSwitchRequest {
  chainId: string;
  chainName?: string;
  rpcUrls?: string[];
  nativeCurrency?: NativeCurrencyData;
  blockExplorerUrl?: string;
}
```

The `chainId` is the `0x`-prefixed [EIP-155](/EIPs/EIPS/eip-155)-compliant chain ID. The `chainName` is a suggested human-readable name of the chain, to be displayed to the user. The `rpcUrls` array is a list of RPC endpoints for the given `chainId`. The `nativeCurrency` object suggests how the native currency should be displayed. Its parameters, `name`, `symbol`, and `decimals`, should be interpreted like in [ERC-20](/EIPs/EIPS/eip-20). Finally, the `blockExplorerUrl` should link to a block explorer compatible with the given `chainId`.

All keys other than the `chainId` are optional. All keys other than `chainId` are suggestions to the wallet. Wallets can choose to ignore or display other data to users. Wallets should prompt the user before switching or adding chains. Wallets should also store a default list of data for commonly-used chains, in order to avoid phishing attacks. Wallets MUST sanitize each RPC url before using it to send other requests, including ensuring that it responds correctly to the `net_version` and `eth_chainId` methods.

The `wallet_updateEthereumChain` method returns `true` if the active chain matches the requested chain, regardless of whether the chain was already active or was added to the wallet previously. If the user rejects the request, it must return an error with code `4001`.

## Rationale

The `wallet_updateEthereumChain` method is designed to be as simple as possible, while still providing the necessary information for a wallet to switch to a new chain. The `chainId` is the only required parameter, as it is the only parameter that is guaranteed to be unique. The `chainName` is included to provide a human-readable name for the chain, and the `rpcUrls` array is included to provide a list of RPC endpoints for the chain. The `nativeCurrency` object is included to provide a suggestion for how the native currency should be displayed. Finally, the `blockExplorerUrl` is included to provide a link to a block explorer for the chain.

The `wallet_updateEthereumChain` method is namespaced under `wallet_` to avoid conflicts with other methods. The `wallet_` prefix is used by other methods that are wallet-specific, such as `wallet_addEthereumChain` and `wallet_switchEthereumChain`.

## Backwards Compatibility

This EIP is fully backwards compatible.

## Security Considerations

### Server-Side Request Forgery (SSRF)

The `rpcUrls` parameter is a list of RPC endpoints for the chain. Wallets should sanitize each RPC url before using it to send other requests, including ensuring that it responds correctly to the `net_version` and `eth_chainId` methods.

### Phishing

Wallets should store a default list of data for commonly-used chains, in order to avoid phishing attacks.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 12 May 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2015</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2015</guid>
      </item>
    
      <item>
        <title>Clearable Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2104</comments>
        
        <description>## Simple Summary

&gt; &quot;In banking and finance, clearing denotes all activities from the time a commitment is made for a transaction until it is settled.&quot; [[1]][Clearing-Wikipedia] 

## Actors

#### Clearing Agent

An account which processes, executes or rejects a clearable transfer.

#### Operator
An account which has been approved by an account to order clearable transfers on its behalf.

#### Orderer
The account which orders a clearable transfer. This can be the account owner itself, or any account, which has been approved as an operator for the account.

## Abstract

The clearing process turns the promise of a transfer into the actual movement of money from one account to another. A clearing agent decides if the transfer can be executed or not. The amount which should be transferred is not deducted from the balance of the payer, but neither is it available for another transfer and therefore ensures, that the execution of the transfer will be successful when it is executed.

## Motivation

A regulated token needs to comply with all the legal requirements, especially [KYC][KYC-Wikipedia] and [AML][AML-Wikipedia]. Some of these checks may not be able to be done on-chain and therefore a transfer may not be completed in one step. Currently there is no EIP to make such off-chain checks possible. This proposal allows a user to order a transfer, which can be checked by a clearing agent off-chain. Depending on the result of it, the clearing agent will either execute or cancel the transfer. To provide more information why a transfer is cancelled, the clearing agent can add a reason why it is not executed.

## Specification

```solidity
interface ClearableToken /* is ERC-1996 */ {
    enum ClearableTransferStatusCode { Nonexistent, Ordered, InProcess, Executed, Rejected, Cancelled }

    function orderTransfer(string calldata operationId, address to, uint256 value) external returns (bool);
    function orderTransferFrom(string calldata operationId, address from, address to, uint256 value) external returns (bool);
    function cancelTransfer(string calldata operationId) external returns (bool);
    function processClearableTransfer(string calldata operationId) external returns (bool);
    function executeClearableTransfer(string calldata operationId) external returns (bool);
    function rejectClearableTransfer(string calldata operationId, string calldata reason) external returns (bool);
    function retrieveClearableTransferData(string calldata operationId) external view returns (address from, address to, uint256 value, ClearableTransferStatusCode status);

    function authorizeClearableTransferOperator(address operator) external returns (bool);
    function revokeClearableTransferOperator(address operator) external returns (bool);
    function isClearableTransferOperatorFor(address operator, address from) external view returns (bool);

    event ClearableTransferOrdered(address indexed orderer, string operationId, address indexed from, address indexed to, uint256 value);
    event ClearableTransferInProcess(address indexed orderer, string operationId);
    event ClearableTransferExecuted(address indexed orderer, string operationId);
    event ClearableTransferRejected(address indexed orderer, string operationId, string reason);
    event ClearableTransferCancelled(address indexed orderer, string operationId);
    event AuthorizedClearableTransferOperator(address indexed operator, address indexed account);
    event RevokedClearableTransferOperator(address indexed operator, address indexed account);
}
```

### Functions

#### orderTransfer

Orders a clearable transfer on behalf of the msg.sender in favor of `to`. A clearing agent is responsible to either execute or reject the transfer. The function must revert if the operation ID has been used before.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify the clearable transfer |
| to | The address of the payee, to whom the tokens are to be paid if executed |
| value | The amount to be transferred. Must be less or equal than the balance of the payer. |

#### orderTransferFrom

Orders a clearable transfer on behalf of the payer in favor of the `to`. A clearing agent is responsible to either execute or reject the transfer. The function must revert if the operation ID has been used before.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify the clearable transfer |
| from | The address of the payer, from whom the tokens are to be taken if executed |
| to | The address of the payee, to whom the tokens are to be paid if executed |
| value | The amount to be transferred. Must be less or equal than the balance of the payer. |

#### cancelTransfer

Cancels the order of a clearable transfer. Only the orderer can cancel their own orders. It must not be successful as soon as the transfer is in status `InProcess`.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify the clearable transfer |

#### processClearableTransfer

Sets a clearable transfer to status `InProcess`. Only a clearing agent can successfully execute this action. This status is optional, but without it the orderer can cancel the transfer at any time.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify the clearable transfer |

#### executeClearableTransfer

Executes a clearable transfer, which means that the tokens are transferred from the payer to the payee. Only a clearing agent can successfully execute this action.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify the clearable transfer |

#### rejectClearableTransfer

Rejects a clearable transfer, which means that the amount that is held is available again to the payer and no transfer is done. Only a clearing agent can successfully execute this action.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify the clearable transfer |
| reason | A reason given by the clearing agent why the transfer has been rejected |

#### retrieveClearableTransferData

Retrieves all the information available for a particular clearable transfer.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify the clearable transfer |

#### authorizeClearableTransferOperator

Approves an operator to order transfers on behalf of msg.sender.

| Parameter | Description |
| ---------|-------------|
| operator | The address to be approved as operator of clearable transfers |

#### revokeClearableTransferOperator

Revokes the approval to order transfers on behalf of msg.sender.

| Parameter | Description |
| ---------|-------------|
| operator | The address to be revoked as operator of clearable transfers |

#### isClearableTransferOperatorFor

Returns if an operator is approved to order transfers on behalf of `from`.

| Parameter | Description |
| ---------|-------------|
| operator | The address to be an operator of clearable transfers |
| from | The address on which the holds would be created |

#### transfer

It is up to the implementer of the EIP if the `transfer` function of ERC-20 should always revert or is allowed under certain circumstances.

#### transferFrom

It is up to the implementer of the EIP if the `transferFrom` function of ERC-20 should always revert or is allowed under certain circumstances.


### Events

#### ClearableTransferOrdered

Must be emitted when a clearable transfer is ordered.

| Parameter | Description |
| ---------|-------------|
| orderer | The address of the orderer of the transfer |
| operationId | The unique ID to identify the clearable transfer |
| from | The address of the payer, from whom the tokens are to be taken if executed |
| to | The address of the payee, to whom the tokens are to be paid if executed |
| value | The amount to be transferred if executed |

#### ClearableTransferInProcess

Must be emitted when a clearable transfer is put in status `ÌnProcess`.

| Parameter | Description |
| ---------|-------------|
| orderer | The address of the orderer of the transfer |
| operationId | The unique ID to identify the clearable transfer |

#### ClearableTransferExecuted

Must be emitted when a clearable transfer is executed.

| Parameter | Description |
| ---------|-------------|
| orderer | The address of the orderer of the transfer |
| operationId | The unique ID to identify the clearable transfer |

#### ClearableTransferRejected

Must be emitted when a clearable transfer is rejected.

| Parameter | Description |
| ---------|-------------|
| orderer | The address of the orderer of the transfer |
| operationId | The unique ID to identify the clearable transfer |
| reason | A reason given by the clearing agent why the transfer has been rejected |

#### ClearableTransferCancelled

Must be emitted when a clearable transfer is cancelled by its orderer.

| Parameter | Description |
| ---------|-------------|
| orderer | The address of the orderer of the transfer |
| operationId | The unique ID to identify the clearable transfer |

#### AuthorizedClearableTransferOperator

Emitted when an operator has been approved to order transfers on behalf of another account.

| Parameter | Description |
| ---------|-------------|
| operator | The address which has been approved as operator of clearable transfers |
| account | Address on which behalf transfers will potentially be ordered |

#### RevokedClearableTransferOperator

Emitted when an operator has been revoked from ordering transfers on behalf of another account.

| Parameter | Description |
| ---------|-------------|
| operator | The address which has been revoked as operator of clearable transfers |
| account | Address on which behalf transfers could potentially be ordered |

## Rationale

This EIP uses [EIP-1996][EIP-1996] to hold the money after a transfer is ordered. A clearing agent, whose implementation is not part of this proposal, acts as a predefined notary to decide if the transfer complies with the rules of the token or not.

The `operationId` is a string and not something more gas efficient to allow easy traceability of the hold and allow human readable ids. It is up to the implementer if the string should be stored on-chain or only its hash, as it is enough to identify a hold.

The `operationId` is a competitive resource. It is recommended, but not required, that the hold issuers used a unique prefix to avoid collisions.

While not requiring it, the naming of the functions `authorizeClearableTransferOperator`, `revokeClearableTransferOperator` and `isClearableTransferOperatorFor` follows the naming convention of [ERC-777](/EIPs/EIPS/eip-777).

## Backwards Compatibility

This EIP is fully backwards compatible as its implementation extends the functionality of [EIP-1996][EIP-1996].

## Implementation

The GitHub repository [IoBuilders/clearable-token](https://github.com/IoBuilders/clearable-token) contains the reference implementation.

## Contributors
This proposal has been collaboratively implemented by [adhara.io](https://adhara.io/) and [io.builders](https://io.builders/).

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[1] https://en.wikipedia.org/wiki/Clearing_(finance)

[Clearing-Wikipedia]: https://en.wikipedia.org/wiki/Clearing_(finance)
[KYC-Wikipedia]: https://en.wikipedia.org/wiki/Know_your_customer
[AML-Wikipedia]: https://en.wikipedia.org/wiki/Money_laundering#Anti-money_laundering

[EIP-1996]: /EIPs/EIPS/eip-1996
</description>
        <pubDate>Tue, 30 Apr 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2018</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2018</guid>
      </item>
    
      <item>
        <title>Fundable Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2105</comments>
        
        <description>## Simple Summary
An extension to the [ERC-20] standard token that allows Token wallet owners to request a wallet to be funded, by calling the smart contract and attaching a fund instruction string.

## Actors

#### Token Wallet Owners
The person or company who owns the wallet, and will order a token fund request into the wallet.

#### Token contract owner / agent 
The entity, company responsible/owner of the token contract, and token issuing/minting. This actor is in charge of trying to fulfill all fund request(s), reading the fund instruction(s), and correlate the private payment details.

#### Orderer
An actor who is enabled to initiate funding orders on behalf of a token wallet owner.

## Abstract
Token wallet owners (or approved addresses) can order tokenization requests through  blockchain. This is done by calling the ```orderFund``` or ```orderFundFrom``` methods, which initiate the workflow for the token contract operator to either honor or reject the fund request. In this case, fund instructions are provided when submitting the request, which are used by the operator to determine the source of the funds to be debited in order to do fund the token wallet (through minting).

In general, it is not advisable to place explicit routing instructions for debiting funds on a verbatim basis on the blockchain, and it is advised to use a private communication alternatives, such as private channels, encrypted storage or similar,  to do so (external to the blockchain ledger). Another (less desirable) possibility is to place these instructions on the instructions field in encrypted form.

## Motivation
Nowadays most of the token issuing/funding request, based on any fiat based payment method  need a previous centralized transaction, to be able to get the desired tokens issued on requester&apos;s wallet.
In the aim of trying to bring all the needed steps into decentralization, exposing all the needed steps of token lifecycle and payment transactions, a funding request can allow wallet owner to initiate the funding request via  blockchain.
Key benefits:

* Funding and payment traceability is enhanced bringing the initiation into the ledger. All payment stat
s can be stored on chain.
* Almost all money/token lifecycle is covered via a decentralized approach, complemented with private communications which is common use in the ecosystem.

## Specification

```solidity
interface IFundable /* is ERC-20 */ {
    enum FundStatusCode {
        Nonexistent,
        Ordered,
        InProcess,
        Executed,
        Rejected,
        Cancelled
    }
    function authorizeFundOperator(address orderer) external returns (bool);
    function revokeFundOperator(address orderer) external returns (bool) ;
    function orderFund(string calldata operationId, uint256 value, string calldata instructions) external returns (bool);
    function orderFundFrom(string calldata operationId, address walletToFund, uint256 value, string calldata instructions) external returns (bool);
    function cancelFund(string calldata operationId) external returns (bool);
    function processFund(string calldata operationId) external returns (bool);
    function executeFund(string calldata operationId) external returns (bool);
    function rejectFund(string calldata operationId, string calldata reason) external returns (bool);

    function isFundOperatorFor(address walletToFund, address orderer) external view returns (bool);
    function retrieveFundData(address orderer, string calldata operationId) external view returns (address walletToFund,       uint256 value, string memory instructions, FundStatusCode status);

    event FundOrdered(address indexed orderer, string indexed operationId, address indexed , uint256 value,         string instructions);
    event FundInProcess(address indexed orderer, string indexed operationId);
    event FundExecuted(address indexed orderer, string indexed operationId);
    event FundRejected(address indexed orderer, string indexed operationId, string reason);
    event FundCancelled(address indexed orderer, string indexed operationId);
    event FundOperatorAuthorized(address indexed walletToFund, address indexed orderer);
    event FundOperatorRevoked(address indexed walletToFund, address indexed orderer);
}
```

### Functions

#### authorizeFundOperator

Wallet owner, authorizes a given address to be fund orderer.

| Parameter | Description |
| ---------|-------------|
| orderer | The address of the orderer.

#### revokeFundOperator

Wallet owner, revokes a given address to be fund orderer.

| Parameter | Description |
| ---------|-------------|
| orderer | The address of the orderer.

#### orderFund

Creates a fund request, that will be processed by the token operator. The function must revert if the operation ID has been used before.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify the request |
| value | The amount to be funded. |
| instruction | A string including the payment instruction. |

#### orderFundFrom

Creates a fund request, on behalf of a wallet owner, that will be processed by the token operator. The function must revert if the operation ID has been used before.

| Parameter | Description |
| ---------|-------------|
| operationId |The unique ID to identify the request |
| walletToFund | The wallet to be funded on behalf.
| value | The amount to be funded. |
| instruction | A string including the payment instruction. |

#### cancelFund

Cancels a funding request.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify the request that is going to be cancelled. This can only be done by token holder, or the fund initiator. |

#### processFund

Marks a funding request as on process. After the status is on process, order cannot be cancelled.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify the request is in process.

#### executeFund

Issues the amount of tokens and marks a funding request as executed.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify the request that has been executed.

#### rejectFund

Rejects a given operation with a reason.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify the request that has been executed.
| reason | The specific reason that explains why the fund request was rejected. EIP 1066 codes can be used |

#### isFundOperatorFor

Checks that given player is allowed to order fund requests, for a given wallet.

| Parameter | Description |
| ---------|-------------|
| walletToFund | The wallet to be funded, and checked for approval permission.
| orderer | The address of the orderer, to be checked for approval permission.

#### retrieveFundData

Retrieves all the fund request data. Only operator, tokenHolder, and orderer can get the given operation data.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify the fund order.

### Events

#### FundOrdered

Emitted when an token wallet owner orders a funding request.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify the request |
| walletToFund | The wallet that the player is allowed to start funding requests |
| value | The amount to be funded. |
| instruction | A string including the payment instruction. |

#### FundInProcess

Emitted when an operator starts a funding request after validating the instruction, and the operation is marked as in process.

| Parameter | Description |
| ---------|-------------|
| orderer | The address of the fund request orderer. |
| operationId | The unique ID to identify the fund. |

#### FundExecuted

Emitted when an operator has executed a funding request.

| Parameter | Description |
| ---------|-------------|
| orderer | The address of the fund request orderer. |
| operationId | The unique ID to identify the fund. |

#### FundRejected

Emitted when an operator has rejected a funding request.

| Parameter | Description |
| ---------|-------------|
| orderer | The address of the fund request orderer. |
| operationId | The unique ID to identify the fund. |
| reason | The specific reason that explains why the fund request was rejected. EIP 1066 codes can be used |

#### FundCancelled

Emitted when a token holder, orderer,  has cancelled a funding request. This can only be done if the operator hasn&apos;t put the funding order in process.

| Parameter | Description |
| ---------|-------------|
| orderer | The address of the fund request orderer. |
| operationId | The unique ID to identify the fund. |

#### FundOperatorAuthorized

Emitted when a given player, operator, company or a given persona, has been approved to start fund request for a given token holder.

| Parameter | Description |
| ---------|-------------|
| walletToFund | The wallet that the player is allowed to start funding requests |
| orderer | The address that allows the player to start requests. |

#### FundOperatorRevoked

Emitted when a given player has been revoked initiate funding requests.

| Parameter | Description |
| ---------|-------------|
| walletToFund | The wallet that the player is allowed to start funding requests |
| orderer | The address that allows the player to start requests. |

## Rationale
This standards provides a functionality to allow token holders to start funding requests in a decentralized way.

It&apos;s important to highlight that the token operator, need to process all funding request, updating the fund status based on the linked payment that will be done.

Funding instruction format is open. ISO payment standard like is a good start point,

The `operationId` is a string and not something more gas efficient to allow easy traceability of the hold and allow human readable ids. It is up to the implementer if the string should be stored on-chain or only its hash, as it is enough to identify a hold.

The `operationId` is a competitive resource. It is recommended, but not required, that the hold issuers used a unique prefix to avoid collisions.

## Backwards Compatibility
This EIP is fully backwards compatible as its implementation extends the functionality of [ERC-20].

## Implementation
The GitHub repository [IoBuilders/fundable-token](https://github.com/IoBuilders/fundable-token) contains the work in progress implementation.

## Contributors
This proposal has been collaboratively implemented by [adhara.io](https://adhara.io/) and [io.builders](https://io.builders/).

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[ERC-20]: /EIPs/EIPS/eip-20
</description>
        <pubDate>Fri, 10 May 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2019</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2019</guid>
      </item>
    
      <item>
        <title>E-Money Standard Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2407</comments>
        
        <description>## Simple Summary

The E-Money Standard Token aims to enable the issuance of regulated electronic money on blockchain networks, and its practical usage in real financial applications. 

## Actors

#### Operator
An account, which has been approved by an account to perform an action on the behalf of another account.

## Abstract

Financial institutions work today with electronic systems, which hold account balances in databases on core banking systems. In order for an institution to be allowed to maintain records of client balances segregated and available for clients, such institution must be regulated under a known legal framework and must possess a license to do so. Maintaining a license under regulatory supervision entails ensuring compliance (i.e. performing KYC on all clients and ensuring good AML practices before allowing transactions) and demonstrating technical and operational solvency through periodic audits, so clients depositing funds with the institution can rest assured that their money is safe.

## Motivation

There are only a number of potential regulatory license frameworks that allow institutions to issue and hold money balances for customers (be it retail corporate or institutional types). The most important and practical ones are three:
* **Electronic money entities**: these are legally regulated vehicles that are mostly used today for cash and payments services, instead of more complex financial services. For example prepaid cards or online payment systems such as PayPal run on such schemes. In most jurisdictions, electronic money balances are required to be 100% backed by assets, which often entails holding cash on an omnibus account at a bank with 100% of the funds issued to clients in the electronic money ledger.
* **Banking licenses**: these include commercial and investment banks, which segregate client funds using current and other type of accounts implemented on core banking systems. Banks can create money by lending to clients, so bank money can be backed by promises to pay and other illiquid assets.
* **Central banks**: central banks hold balances for banks in RTGS systems, similar to core banking systems but with much more restricted yet critical functionality. Central banks create money by lending it to banks, which pledge their assets to central banks as a lender of last resort for an official interest rate.

Regulations for all these types of electronic money are local, i.e. only valid for each jurisdiction and not valid in others. Regulations can vary as well dramatically in different jurisdictions — for example there are places with no electronic money frameworks, on everything has to be done through banking licenses or directly with a central bank. But in all cases compliance with existing regulation needs to ensured, in particular:
* **Know Your Customer (KYC)**: the institution needs to identify the client before providing them with the possibility of depositing money or transact. In different jurisdictions and for different types of licenses there are different levels of balance and activity that can be allowed for different levels of KYC. For example, low KYC requirements with little checks or even no checks at all can usually be acceptable in many jurisdictions if cashin balances are kept low (i.e. hundreds of dollars)
* **Anti Money Laundering (AML)**: the institution needs to perform checks of parties transacting with its clients, typically checking against black lists and doing sanction screening, most notably in the context of international transactions

Beyond cash, financial instruments such as equities or bonds are also registered in electronic systems in most cases, although all these systems and the bank accounting systems are only connected through rudimentary messaging means, which leads to the need for reconciliations and manual management in many cases. Cash systems to provide settlement of transactions in the capital markets are not well-connected to the transactional systems, and often entail delays and settlement risk.

The E-Money Standard Token builds on Ethereum standards currently in use such as [ERC-20], but it extends them to provide few key additional pieces of functionality, needed in the regulated financial world:
* **Compliance**: E-Money Standard Token implements a set of methods to check in advance whether user-initiated transactions can be done from a compliance point of view. Implementations must `require` that these methods return a positive answer before executing the transaction.
* **Clearing**: In addition to the standard [ERC-20] `transfer` method, E-Money Standard Token provides a way to submit transfers that need to be cleared by the token issuing authority off-chain. These transfers are then executed in two steps:
    1. transfers are ordered
    1. after clearing them, transfers are executed or rejected by the operator of the token contract
* **Holds**: token balances can be put on hold, which will make the held amount unavailable for further use until the hold is resolved (i.e. either executed or released). Holds have a payer, a payee, and a notary who is in charge of resolving the hold. Holds also implement expiration periods, after which anyone can release the hold Holds are similar to escrows in that are firm and lead to final settlement. Holds can also be used to implement collateralization.
* **Funding requests**: users can request for a wallet to be funded by calling the smart contract and attaching a debit instruction string. The tokenizer reads this request, interprets the debit instructions, and triggers a transfer in the bank ledger to initiate the tokenization process.
* **Payouts**: users can request payouts by calling the smart contract and attaching a payment instruction string. The (de)tokenizer reads this request, interprets the payment instructions, and triggers the transfer of funds (typically from the omnibus account) into the destination account, if possible. Note that a redemption request is a special type of payout in which the destination (bank) account for the payout is the bank account linked to the token wallet.

The E-Money Standard Token is thus different from other tokens commonly referred to as &quot;stable coins&quot; in that it is designed to be issued, burnt and made available to users in a compliant manner (i.e. with full KYC and AML compliance) through a licensed vehicle (an electronic money entity, a bank, or a central bank), and in that it provides the additional functionality described above, so it can be used by other smart contracts implementing more complex financial applications such as interbank payments, supply chain finance instruments, or the creation of E-Money Standard Token denominated bonds and equities with automatic delivery-vs-payment.

## Specification

```solidity
interface EMoneyToken /* is ERC-1996, ERC-2018, ERC-2019, ERC-2021 */ {
    function currency() external view returns (string memory);
    function version() external pure returns (string memory);
    
    function availableFunds(address account) external view returns (uint256);
    
    function checkTransferAllowed(address from, address to, uint256 value) external view returns (byte status);
    function checkApproveAllowed(address from, address spender, uint256 value) external view returns (byte status);
    
    function checkHoldAllowed(address from, address to, address notary, uint256 value) external view returns (byte status);
    function checkAuthorizeHoldOperatorAllowed(address operator, address from) external view returns (byte status);    

    function checkOrderTransferAllowed(address from, address to, uint256 value) external view returns (byte status);
    function checkAuthorizeClearableTransferOperatorAllowed(address operator, address from) external view returns (byte status);
    
    function checkOrderFundAllowed(address to, address operator, uint256 value) external view returns (byte status);
    function checkAuthorizeFundOperatorAllowed(address operator, address to) external view returns (byte status);
    
    function checkOrderPayoutAllowed(address from, address operator, uint256 value) external view returns (byte status);
    function checkAuthorizePayoutOperatorAllowed(address operator, address from) external view returns (byte status);
}
```

### Mandatory checks

The checks must be verified in their corresponding actions. The action must only be successful if the check return an `Allowed` status code. In any other case the functions must revert.

### Status codes

If an action is allowed `0x11` (Allowed), or an issuer-specific code with equivalent but more precise meaning must be returned. If the action is not allowed the status must be `0x10` (Disallowed), or an issuer-specific code with equivalent but more precise meaning.

### Functions

#### currency

Returns the currency that backs the token. The value must be a code defined in [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217).

| Parameter | Description |
| ---------|-------------|
| - | - |

#### version

Returns the current version of the smart contract. The format of the version is up to the implementer of the EIP.

| Parameter | Description |
| ---------|-------------|
| - | - |

#### availableFunds

Returns the total net funds of an account. Taking into consideration the outright balance and the held balances.

| Parameter | Description |
| ---------|-------------|
| account | The account which available funds should be returned |

#### checkTransferAllowed

Checks if the `transfer` or `transferFrom` function is allowed to be executed with the given parameters.

| Parameter | Description |
| ---------|-------------|
| from | The address of the payer, from whom the tokens are to be taken if executed |
| to | The address of the payee, to whom the tokens are to be transferred if executed |
| value | The amount to be transferred |

#### checkApproveAllowed

Checks if the `approve` function is allowed to be executed with the given parameters.

| Parameter | Description |
| ---------|-------------|
| from | The address of the payer, from whom the tokens are to be taken if executed |
| spender | The address of the spender, which potentially can initiate transfers on behalf of `from` |
| value | The maximum amount to be transferred |

#### checkHoldAllowed

Checks if the `hold` function is allowed to be executed with the given parameters.

| Parameter | Description |
| ---------|-------------|
| from | The address of the payer, from whom the tokens are to be taken if executed |
| to | The address of the payee, to whom the tokens are to be transferred if executed |
| notary | The address of the notary who is going to determine whether the hold is to be executed or released |
| value | The amount to be transferred. Must be less or equal than the balance of the payer |

#### checkAuthorizeHoldOperatorAllowed

Checks if the `checkAuthorizeHoldOperatorAllowed` function is allowed to be executed with the given parameters.

| Parameter | Description |
| ---------|-------------|
| operator | The address to be approved as operator of clearable transfers |
| from | The address on which behalf holds could potentially be issued |

#### checkOrderTransferAllowed

Checks if the `orderTransfer` function is allowed to be executed with the given parameters.

| Parameter | Description |
| ---------|-------------|
| from | The address of the payer, from whom the tokens are to be taken if executed |
| to | The address of the payee, to whom the tokens are to be paid if executed |
| value | The amount to be transferred. Must be less or equal than the balance of the payer |

#### checkAuthorizeClearableTransferOperatorAllowed

Checks if the `authorizeClearableTransferOperator` function is allowed to be executed with the given parameters.

| Parameter | Description |
| ---------|-------------|
| operator | The address to be approved as operator of clearable transfers |
| from | The address on which behalf clearable transfers could potentially be ordered |

#### checkOrderFundAllowed

Checks if the `orderFund` function is allowed to be executed with the given parameters.

| Parameter | Description |
| ---------|-------------|
| to | The address to which the tokens are to be given if executed |
| operator | The address of the requester, which initiates the funding order | 
| value | The amount to be funded |

#### checkAuthorizeFundOperatorAllowed

Checks if the `authorizeFundOperator` function is allowed to be executed with the given parameters.

| Parameter | Description |
| ---------|-------------|
| operator | The address to be approved as operator of ordering funding |
| to | The address which the tokens are to be given if executed |

#### checkOrderPayoutAllowed

Checks if the `orderPayout` function is allowed to be executed with the given parameters.

| Parameter | Description |
| ---------|-------------|
| from | The address from whom the tokens are to be taken if executed |
| operator | The address of the requester, which initiates the payout request | 
| value | The amount to be paid out |

#### checkAuthorizePayoutOperatorAllowed

Checks if the `authorizePayoutOperator` function is allowed to be executed with the given parameters.

| Parameter | Description |
| ---------|-------------|
| operator | The address to be approved as operator of ordering payouts |
| from | The address from which the tokens are to be taken if executed |

## Rationale

This EIP unifies [ERC-1996][ERC-1996], [ERC-2018][ERC-2018], [ERC-2019][ERC-2019] and [ERC-2021][ERC-2021] and adds the checks for the compliance on top of it. By this way the separate EIPs are otherwise independent of each other, and the E-Money Standard Token offers a solution for all necessary functionality of regulated electronic money.

While not requiring it, the naming of the check functions was adopted from [ERC-1462][ERC-1462].

## Backwards Compatibility

This EIP is fully backwards compatible as its implementation extends the functionality of [ERC-1996][ERC-1996], [ERC-2018][ERC-2018], [ERC-2019][ERC-2019], [ERC-2021][ERC-2021] and [ERC-1066][ERC-1066].

## Implementation

The GitHub repository [IoBuilders/em-token](https://github.com/IoBuilders/em-token) contains the work in progress implementation.

## Contributors
This proposal has been collaboratively implemented by [adhara.io](https://adhara.io/) and [io.builders](https://io.builders/).

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[ERC-20]: /EIPs/EIPS/eip-20

[ERC-1066]: /EIPs/EIPS/eip-1066

[ERC-1462]: /EIPs/EIPS/eip-1462

[ERC-1996]: /EIPs/EIPS/eip-1996

[ERC-2018]: /EIPs/EIPS/eip-2018

[ERC-2019]: /EIPs/EIPS/eip-2019

[ERC-2021]: /EIPs/EIPS/eip-2021
</description>
        <pubDate>Fri, 10 May 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2020</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2020</guid>
      </item>
    
      <item>
        <title>Payoutable Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2106</comments>
        
        <description>## Simple Summary
An extension to the [ERC-20] standard token that allows Token wallet owners to request payout from their wallet, by calling the smart contract and attaching a payout instruction string.

## Actors

#### Token Wallet Owners
The person or company who owns the wallet, and will order payout.

#### Token contract owner / agent
The entity, company responsible/owner of the token contract, and token issuing/minting. This actor is in charge of trying to fulfill all payout request(s), reading the payout instruction(s), and correlate the payout details.

#### Orderer
An actor who is enabled to initiate payout orders on behalf of a token wallet owner.

## Abstract
Token wallet owners (or approved addresses) can order payout requests through  blockchain. This is done by calling the ```orderPayoutFrom``` or ```orderPayoutFrom``` methods, which initiate the workflow for the token contract operator to either honor or reject the payout request. In this case, payout instructions are provided when submitting the request, which are used by the operator to determine the destination of the funds.

In general, it is not advisable to place explicit routing instructions for the payouts on a verbatim basis on the blockchain, and it is advised to use a private communication alternatives, such as private channels, encrypted storage or similar, to do so (external to the blockchain ledger). Another (less desirable) possibility is to place these instructions on the instructions field in encrypted form.

## Motivation
Nowadays most of the token payout requests, need a previous centralized transaction, to be able to define the payout destination to be able to execute the payout (burn transaction).
In the aim of trying to bring all the needed steps into decentralization, exposing all the needed steps of token lifecycle and payment transactions, a payout request can allow wallet owner to initiate the payout order via blockchain.
Key benefits:

* Payout, burning  traceability is enhanced bringing the initiation into the ledger. All payment, payout statuses can be stored on chain.
* Almost all money/token lifecycle is covered via a decentralized approach, complemented with private communications which is common use in the ecosystem.

In this case, the following movement of tokens are done as the process progresses:

* Upon launch of the payout request, the appropriate amount of funds are placed on a hold with a predefined notary defined by the platform, and the payout is placed into a ```Ordered``` state
* The operator then can put the payout request ```InProcess```, which prevents the _orderer_ of the payout from being able to cancel the payout request
* After checking the payout is actually possible the operator then executes the hold, which moves the funds to a suspense wallet and places the payout into the ```FundsInSuspense``` state
* The operator then moves the funds offchain (usually from the omnibus account)  to the appropriate destination account, then burning the tokens from the suspense wallet and rendering the payout into the ```Executed``` state
* Either before or after placing the request ```InProcess```, the operator can also reject the payout, which returns the funds to the payer and eliminates the hold. The resulting end state of the payout is ```Rejected```
* When the payout is ```Ordered``` and before the operator places it into the ```InProcess``` state, the orderer of the payout can also cancel it, which frees up the hold and puts the payout into the final ```Cancelled``` state

## Specification

```solidity
interface IPayoutable /* is ERC-20 */ {
    enum PayoutStatusCode {
        Nonexistent,
        Ordered,
        InProcess,
        FundsInSuspense,
        Executed,
        Rejected,
        Cancelled
    }
    function authorizePayoutOperator(address orderer) external returns (bool);
    function revokePayoutOperator(address orderer) external returns (bool);
    function orderPayout(string calldata operationId, uint256 value, string calldata instructions) external returns (bool);
    function orderPayoutFrom(string calldata operationId, address walletToBePaidOut, uint256 value, string calldata instructions) external returns (bool);
    function cancelPayout(string calldata operationId) external returns (bool);
    function processPayout(string calldata operationId) external returns (bool);
    function putFundsInSuspenseInPayout(string calldata operationId) external returns (bool);
    function executePayout(string calldata operationId) external returns (bool);
    function rejectPayout(string calldata operationId, string calldata reason) external returns (bool);

    function isPayoutOperatorFor(address walletToDebit, address orderer) external view returns (bool);
    function retrievePayoutData(string calldata operationId) external view returns (address walletToDebit, uint256 value, string memory instructions, PayoutStatusCode status);

    event PayoutOrdered(address indexed orderer, string indexed operationId, address indexed walletToDebit, uint256 value, string instructions);
    event PayoutInProcess(address indexed orderer, string indexed operationId);
    event PayoutFundsInSuspense(address indexed orderer, string indexed operationId);
    event PayoutExecuted(address indexed orderer, string indexed operationId);
    event PayoutRejected(address indexed orderer, string indexed operationId, string reason);
    event PayoutCancelled(address indexed orderer, string indexed operationId);
    event PayoutOperatorAuthorized(address indexed walletToBePaidOut, address indexed orderer);
    event PayoutOperatorRevoked(address indexed walletToBePaidOut, address indexed orderer);
}
```

### Functions

#### authorizePayoutOperator

Wallet owner, allows a given address to be payout orderer.

| Parameter | Description |
| ---------|-------------|
| orderer | The address of the orderer. |

#### revokePayoutOperator

Wallet owner, Revokes a given address to be payout orderer.

| Parameter | Description |
| ---------|-------------|
| orderer | The address of the orderer. |

#### orderPayout

Creates a payout request, that will be processed by the token operator. The function must revert if the operation ID has been used before.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify the request |
| value | The amount to be paid out. |
| instruction | A string including the payment instruction. |

#### orderPayoutFrom

Creates a payout request, on behalf of a wallet owner, that will be processed by the token operator. The function must revert if the operation ID has been used before.

| Parameter | Description |
| ---------|-------------|
| operationId |The unique ID to identify the request |
| walletToBePaidOut | The wallet to be paid out on behalf. |
| value | The amount to be paid out. |
| instruction | A string including the payment instruction. |

#### cancelPayout

Cancels a payout request.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify the request that is going to be cancelled. This can only be done by token holder, or the payout initiator/orderer. |
| reason | The specific reason that explains why the payout request was rejected. [EIP-1066] codes can be used. |


#### processPayout

Marks a payout request as on process. After the status is on process, order cannot be cancelled.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify that the request is in process. |

#### putFundsInSuspenseInPayout

Put a given payout in suspense. Can only be done if it is in process.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify that the request is in process. |

#### executePayout

Burn the amount of tokens and marks a payout request as executed.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify the request that has been executed. |

#### rejectPayout

Rejects a given operation with a reason.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify the request that has been executed. |
| reason | The specific reason that explains why the payout request was rejected. [EIP-1066] codes can be used |

#### isApprovedToOrderPayout

Checks that given player is allowed to order payout  requests, for a given wallet.

| Parameter | Description |
| ---------|-------------|
| walletToBePaidOut | The wallet to be paid out, and checked for approval permission. |
| orderer | The address of the orderer, to be checked for approval permission. |

#### retrievePayoutData

Retrieves all the payout request data. Only operator, tokenHolder, and orderer can get the given operation data.

| Parameter | Description |
| ---------|-------------|
| orderer | The address of the orderer, to correlate the right data. |
| operationId | The unique ID to identify the payout order. |

### Events

#### Payout Ordered

Emitted when an token wallet owner orders a payout request.

| Parameter | Description |
| ---------|-------------|
| operationId | The unique ID to identify the request |
| walletToBePaidOut | The wallet that is requested to be paid out |
| value | The amount to be funded. |
| instruction | A string including the payment instruction. |

#### PayoutFundsInSuspense

Emitted when an operator puts fund in suspense.

| Parameter | Description |
| ---------|-------------|
| orderer | The address of the payout request orderer. |
| operationId | The unique ID to identify the payout. |

#### PayoutInProcess

Emitted when an operator accepts a payout request, and the operation is in process.

| Parameter | Description |
| ---------|-------------|
| orderer | The address of the payout request orderer. |
| operationId | The unique ID to identify the payout. |

#### PayoutExecuted

Emitted when an operator has executed a payout request.

| Parameter | Description |
| ---------|-------------|
| orderer | The address of the payout request orderer. |
| operationId | The unique ID to identify the payout. |

#### PayoutRejected

Emitted when an operator has rejected a payout request.

| Parameter | Description |
| ---------|-------------|
| orderer | The address of the payout request orderer. |
| operationId | The unique ID to identify the payout. |
| reason | The specific reason that explains why the payout request was rejected. [EIP-1066] codes can be used |

#### PayoutCancelled

Emitted when a token holder, orderer,  has cancelled a payout request. This can only be done if the operator hasn&apos;t put the payout order in process.

| Parameter | Description |
| ---------|-------------|
| orderer | The address of the payout request orderer. |
| operationId | The unique ID per payout issuer to identify the payout. |

#### PayoutOperatorAuthorized

Emitted when a given player, operator, company or a given persona, has been approved to start payout request for a given token holder.

| Parameter | Description |
| ---------|-------------|
| walletToBePaidOut | The wallet that the player is allowed to start payout requests |
| orderer |The address that allows the player to start requests. |

#### PayoutOperatorRevoked

Emitted when a given player has been revoked initiate payout requests.

| Parameter | Description |
| ---------|-------------|
| walletToBePaidOut | The wallet that the player is allowed to start payout requests |
| orderer |The address that allows the player to start requests. |

## Rationale
This standards provides a functionality to allow token holders to start payout requests in a decentralized way.

It&apos;s important to highlight that the token operator, need to process all payout request, updating the payout status based on the linked payment that will be done.

Payout instruction format is open. ISO payment standard like is a good start point.

This EIP uses [EIP-1996] to hold the money after a payout is ordered. The token contract owner or agent, whose implementation is not part of this proposal, acts as a predefined notary to decide if the payout is executed or not.

The `operationId` is a string and not something more gas efficient to allow easy traceability of the hold and allow human readable ids. It is up to the implementer if the string should be stored on-chain or only its hash, as it is enough to identify a hold.

The `operationId` is a competitive resource. It is recommended, but not required, that the hold issuers used a unique prefix to avoid collisions.

## Backwards Compatibility
This EIP is fully backwards compatible as its implementation extends the functionality of [ERC-20] and [ERC-1996].

## Implementation
The GitHub repository [IoBuilders/payoutable-token](https://github.com/IoBuilders/payoutable-token) contains the reference implementation.

## Contributors
This proposal has been collaboratively implemented by [adhara.io](https://adhara.io/) and [io.builders](https://io.builders/).

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[ERC-20]: /EIPs/EIPS/eip-20

[EIP-1066]: /EIPs/EIPS/eip-1066

[EIP-1996]: /EIPs/EIPS/eip-1996
</description>
        <pubDate>Fri, 10 May 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2021</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2021</guid>
      </item>
    
      <item>
        <title>Block Rewards Proposal for funding Eth1.x</title>
        <category>Standards Track/Core</category>
        
          <comments>https://github.com/MadeofTin/EIPs/issues</comments>
        
        <description>## Simple Summary

Add `0.0055 ETH` per block for 18 months (A total of 17050 ETH) as a developer block reward reserved for funding specific Ethereum1.X working groups. The working groups are State rent (750k), Better sync (360k), Finality gadget (360k), Fee market (360k), Testing infrastructure (360k). Governance of the funds will be through a multisig of trusted individuals from the ecosystem including client teams, the foundation, and the community.

[EIP-1890](/EIPs/EIPS/eip-1890) proposes a mechanism to capture a portion of block rewards for sustainably funding ongoing network development. That EIP sets values and addresses to zero and so does not actually collect any rewards. This proposal is to explicitly set those values and begin collecting a portion of block rewards for 18 months in order to fund Ethereum 1.X working groups and organization efforts. This funding will be used to repay an initial loan provided by investors in the community funding this work with a small amount of interest. After 18 months the block reward would again reduce to zero.

## Abstract

This EIP extends the mechanism established in EIP-1890 to add `0.0055 ETH` to the block reward for a specific distribution period of `3,100,000 BLOCKS`(≈ 18 months). The `RECIPIENT_ADDRESS` is set to a smart contract with hardcoded denominations that distributes incoming ETH to a set of addresses for the purpose of Eth1.X development. The emission schedule would start at the hard fork block number and continue for `3,100,000 BLOCKS` (≈ 18 months) at which point the address and amount would again return to 0. Any further distribution would require a future hard fork.

## Motivation

The context for this proposal came from attending the [Core Dev Eth1.X Meeting](https://www.youtube.com/watch?v=Au1Qll-86v0) in Berlin. Development is needed to move Eth1.X forward, and I observed that a lack of funding is the primary barrier to this work. This work can only be effectively conducted by working groups forming around these issues, and these working groups need funding in order to pay dedicated contractors and project managers. This proposal is a plan for funding these groups and supporting their operation.

## Specification

Two constants will be introduced:

- `REWARD_DURATION_IN_BLOCKS`, which specifies the number of blocks after `ISTANBUL_BLOCK_HEIGHT` when the reward collection will terminate (i.e., at block `ISTANBUL_BLOCK_HEIGHT + REWARD_DURATION_IN_BLOCKS`)
- `BENEFICIARY_ADDRESSES`, a list of tuples containing the address and the amount to be transferred to this address per block. These amounts will be determined as the loan is collected from participating organizations and the addresses for repayment will be specified by them. The total of the amounts will sum to 0.0055. At the end of `REWARD_DURATION_IN_BLOCKS` the loan will be completely repaid.

```

REWARD_DURATION_IN_BLOCKS = 3100000
DEVFUND_BLOCK_REWARD = 0.0055



BENEFICIARY_ADDRESSES = [
 (&lt;address&gt;, &lt;amount_in_eth&gt;),
 (&lt;address&gt;, &lt;amount_in_eth&gt;)
]
```

Beginning with block `ISTANBUL_BLOCK_HEIGHT`, the reward is added to the participating addresses within `BENEFICIARY_ADDRESSES` at each block until the end of the `REWARD_DURATION_IN_BLOCKS`.

```
IF (CURRENT_BLOCK - ISTANBUL_BLOCK_HEIGHT &lt;= REWARD_DURATION_IN_BLOCKS)

FOR BENEFICIARY in BENEFICIARY_ADDRESSES:
  BENEFICIARY[0].balance += BENEFICIARY[1]

```

## Rewards Distribution Rationale

```
 Development loan repayment: 0.005 ETH per block: 15500 ETH total
 Development loan interest (10% total over the period, simple interest): 0.0005 ETH per block: 1550 ETH total

 Total Block Reward Increase = `0.0055` ETH per block: 17050 ETH Total
```

*With a price of Ethereum at $150.00 this will raise approx USD $2,325,000.00 for developing Eth1.X over the next 18 months.*

![Block Rewards Distribution](/EIPs/assets/eip-2025/block_rewards_distribution.png) *Specific Addresses to be determined

- [FAQ - Why hardcoded values?]( #why-hardcoded-values )


## Rationale

There has been great public debate concerning EIP-1890, and one of the primary concerns is that it is difficult to evaluate the proposal without more complete information on how funds would be raised, how they would be administered, and how they would be used. There is a need for funding Eth1.x development and it is currently unclear where those funds will come from. This proposal is intended to give a more comprehensive proposal for its funding. In the case that ETH1.x is fully funded before the Istanbul upgrade I will withdraw this EIP. Until that point I intend to continue championing this proposal as a valid funding mechanism for this work.

### Why a loan?

The Eth1x initiative needs funding now, not in 18 months. A loan is necessary to complete certain stages of work before the funding mechanism begins to provide funds. A loan would provide this necessary funding today, and the investors willing to front this cost can recoup their contribution + a reward of *a fixed interest rate* for the risk on their loan. This arrangement will make it easier to find investors willing to participate who have sufficient funds.

### Loan Repayment

![Loan State Diagram](/EIPs/assets/eip-2025/loan_state.png)

There is a risk that the investors lose part of their contribution in the case that this EIP is rejected by the community between the time the funds have been collected and the beginning of the payout schedule. In this case all remaining funds will be returned to the contributors. The interest on the loan is an incentive for investors to participate in spite of this risk. Their downside is limited to the amount of funds spent before this EIP is accepted or rejected, which should be no more than about 5%, while their upside consists of the 10% simple interest paid over the period.

### Development Loan


`Development Loan: 0.005` over 3.1 Million blocks = 15500 ETH 
 
**Funding Working Groups on 1.X**

- Funding Contractors, Coordinators, and project managers
- Working Groups defined with clear mandates

Budget

Working groups

 - State rent (750k)
 - Better sync (360k)
 - finality gadget (360k)
 - Fee market (360k)
 - testing infrastructure (360k) 


**ETH1.X Core Dev Gatherings**

Funding hosting, traveling, and accommodations for necessary in-person gatherings of ETH1.X core developers similar to the Stanford and Berlin ETH1.X Core Dev Meeting held earlier this year.

At the end of the 18 Months, the whole process would be torn down to prevent any internal tyranny of structurelessness forming within.



- [FAQ - How will the funding of the devs be organized?]( #how-will-funding-the-devs-be-organized)

## Accountability

The funds will be transferred into DAI and secured in a multi-sig comprised of members of the community. Representatives from the following groups will receive a key.


 - EIP Editors
 - Geth
 - Parity
 - ConsenSys/PegaSys (PegaSys)
 - The Ethereum Foundation (Hudson Jameson)
 - Community

## Personal Notes and Disclosure 

I want to address any concerns about conflicts of interests directly. My participation with Eth1.X currently has been as a volunteer. I am in talks about a possible funded role helping with testing and coordination. If my work for with Eth1.x is funded, I will accept no additional funding collected by the mechanism proposed in this EIP.

Eth1.X is the now of Ethereum and I would like to see it succeed. This is the intent of my proposal.

### COI

Previously I was PM for Tennagraph, a signalling solution for Ethereum. An Aragon grant funded this project and was distributed through Giveth and an AragonDAO. I have not received any funding from the project beyond this grant. All of this is verifiable on-chain. I am stepping down from any paid role on the project to continue as an advisor. I am also stepping down as a moderator for stances as there is a COI moderating stances for EIPs I am working with directly.

### Disclaimer

I do not claim to represent the community with my views; any members who wish to join supporting me with this proposal are free to do so. This is as fair of a proposal as I can personally conceive.

## Backwards Compatibility

This EIP has no impact on backwards compatibility.

## Test Cases

Not Implemented

## Implementation

Not Implemented

## FAQ

### Why Hardcoded Values?

Why not use a smart contract with some governance mechanism to allow changing the distribution of funds? Wouldn’t that be more flexible and effective?

*TLDR: This EIP is not about governance reform*

First, the payment of the loan will be hardcoded. Once agreed, the terms must be kept to give the lenders confidence in the repayment of the loan. As long as blocks are created the debt will be paid back. This is the essence of a trustless smart contract.

After the loan, there is the option to allow the amounts (limited to less than .05ETH), and the locations (orgs that receive ecosystem funding) to be changed throughout the emission schedule. It is pretty easy to imagine a smart contract or DAO fulfilling this role. However, there are three classes of options available today we can consider when governing changes.

- **Give the Keys to the Hands of the Few (Oligarchy)**

Create a multisig that allows a group of individuals to update the smart contract. The most likely candidates for this are the Core Devs themselves, but it could also be a trusted few from the community/stakeholders. No matter how you slice it, there is a fundamental issue in deciding who gets to decide. There currently is not a trusted/adopted governance mechanism to make these decisions within the Ethereum ecosystem. Also, preventing changing the contract in self interest is difficult without a well-engineered governance system of checks and balances. This EIP does not claim nor aim to solve these issues.

- **Give the Keys to the Hands of the Many (Plutarchy)**

Allow ethereum holders with coin votes to update the smart contract. Using holographic consensus could overcome the issue of voter turnout as it scales as participation scales, even to the size of the whole network. This has some benefits as the entire network can participate. However, the problem is that some individuals in the network are over represented -- the wealthy. Without a solution to identity that has been agreed to and implemented by the entire Ethereum Network, there is no way around giving more power in votes to the rich. This EIP does not claim, nor aim to solve these issues.

- **Use Ethereum Governance as it is Today**

Criticisms or support aside, there is a system that governs Ethereum today. It is a mix of rough consensus among core devs, miners running nodes, clients implementing changes, and stakeholders adopting those changes. It includes yelling or not yelling on twitter and reddit. It is complicated and I don’t claim to understand it. Even without a clear view of how it works, there is evidence of its existence. This evidence is there are changes that have allowed to be implemented, and changes that have not allowed to be implemented in Ethereum.

I do not aim to change Ethereum governance. Because this EIP has hardcoded values, it must go through the existing governance process, whatever that is, before it is implemented. It will then continue to operate until the end of the emission schedule. This is intentional. This makes it uncapturable. No party other then the ecosystem itself can modify the contract once it has been deployed.

This EIP is not about governance reform.

### Why not allow current client implementors fund this work? (EF, Consensys, Parity, etc...) 

Historically there has been a precedent that the Ethereum Foundation is solely responsible for funding the development of Ethereum. This process has evolved as the development has become more distributed. Aya Miyaguchi observed in a recent [Coindesk article](https://www.coindesk.com/ethereum-foundation-director-sets-new-vision-for-blockchain-non-profit), “it really is not only Ethereum Foundation people who are building [Ethereum]”. Yes, we could rely on the Ethereum Foundation to fund Eth1.X. But, why should we? This is a call for the network to come together and fund its own development. Ethereum *the network* is not owned by any one organization or group of people. We are lucky to have the EF and I consider this EIP in support of their coordination efforts.

### How Will Funding the Devs be Organized

I do not profess to know the best way to organize these funds. There is work already in progress to organize these efforts championed by Alexey Akhunov. The following is a quote from a [recent medium article](https://medium.com/@akhounov/ethereum-1x-as-an-attempt-to-change-the-process-783efa23cf60):

&gt; “Going from funding a few implementation teams continuously and letting them do &apos;their stuff&apos; to funding more specific and temporary initiatives requires looking at funding through different lenses. How much &apos;due diligence&apos; and oversight is too much (in terms of overhead), who can decide whether working groups actually deliver, etc. This is also solvable, and also more on this will come later (not in this post).&quot;

My suggestion would be to create an Eth1.X core developer DAO using [DaoStack](https://daostack.io/) to coordinate membership and payment of the Core Devs, but ultimately they are capable of determining the system that works best for them. As long as the system is transparent and mature enough to distribute funds when the time comes, this is sufficient for now.

### Isn&apos;t a loan considered a security, or is it?

I am not a lawyer and will seek further guidance from lawyers in the field on this point in particular. From the research I have done and conversations I have had there is a very good argument that a loan of this nature will not be considered a security by the US Supreme Court.
As the result of [REVES ET AL. v . ERNST YOUNG 1990](https://casetext.com/case/reves-v-ernst-young), the court stated that a home loan, consumer financing, a loan secured by a lien on a small business or some assets of a small business, short term notes, or notes that formalize a debt incurred in the ordinary course of business are not securities. If the note resembles the items listed above (home loans, etc.) then the note will not be deemed a security. The Supreme Court provided four factors to determine if a note sufficiently resembles the types of notes that are not classified as securities. ([source](https://www.invigorlaw.com/loan-subject-securities-regulations/))

**Family Resemblance Test**

 1) The intentions of the company and the individual—if the company raised money for general use in a business enterprise, then the note is more likely to be a security; if the individual agreed to the loan primarily for the profit the note was expected to generate, the note is more likely to be a security.
 2) The plan of distribution—the more widely the note is offered, the more likely it is to be found a security.
 3) The expectations of the investing public—if the investors thought they were investing in a business to make a profit on their investment, the note is more likely to be found a security.
 4) Other risk-reducing factor—if the note is collateralized or otherwise less risky than common notes, the note is less likely to be found to be a security.

The loan is for the specific use of supporting Eth1.X research and development. The distribution will not be widely offered and the note will be collateralized by the network itself, provided in ETH and repaid in ETH. In coordinating the collection of these funds recognise I may be legally liable for some of this work and I will do all of the due dilegence I can, seek legal counsel, and accept any legal repercussions resulting from this work. 

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 20 Apr 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2025</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2025</guid>
      </item>
    
      <item>
        <title>State Rent H - Fixed Prepayment for accounts</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2026-fixed-rent-prepayment-for-all-accounts-change-h-from-state-rent-v3-proposal/3273</comments>
        
        <description>## Simple Summary
Creation of new accounts (both contracts and non-contracts) requires a fixed one-off rent prepayment. Pre-existed accounts require the same prepayment upon
the first modification. The act of rent prepayment causes the addition of an extra field to accounts, called `rentbalance`. This field becomes part of state.

## Abstract
This is part of the State Rent roadmap. This particular change introduces a fixed charge for state expansion that comes from adding new accounts to the state. Theoretically, it puts a bound on the number of accounts that can be ever created, because that fixed charge cannot be recycled via mining.

## Motivation
The penalty is levied to the transaction sender. Rather than raising the gas cost of account creation (that would direct levy towards the miner), this change directs prepayment into the account&apos;s special field, `rentbalance`. It addresses several shortcomings of the simple raising of the gas cost:
1. Prepayments cannot be recycled via mining, which puts a theoretical bound on number of accounts in the state (though it is unlikely to ever be reached).
2. It is not possible for miners to circumvent the penalty or to extend such circumventions onto other users (via private fee rebates, for example).
3. This prepayment will be used to cover state rent in the future, and it will allow newly created contracts with 0 endowment not to be evicted in the same block.
4. It makes is possible to refund `rentbalance` upon self-destruction - when contract is self-destructed, both `balance` and `rentbalance` are returned.
5. Prepayments on pre-existing accounts are necessary to prevent hoarding of accounts ahead of this change.

## Specification
On and after block `H`, every newly created account gets a new field `rentbalance` of type unsigned 256-bit integer.
On and after block `H`, any operation that leads to the creation of a new account, deducts the amount `ACCOUNT_PREPAYMENT` from `tx.origin`. This amount is added to the `rentbalance` field of the created account.
On and after block `H`, any operation that modifies an account that does not yet have `rentbalance` field, deducts the amount `ACCOUNT_PREPAYEMENT` from `tx.origin`. This amount is added to the `rentbalance` field of the modified account. This is an anti-hoarding measure.

Operations leading to the creations of a new account:
1. Creation of a non-contract account by sending non-zero ETH to an address with no associated account
2. Creation of a non-contract account by the block with `coinbase` pointing to an address with no associated account
3. Creation of a non-contract account by `SELFDESTRUCT` with the argument being an address with no associated account
4. Creation of a contract by transaction without destination but with data. This can result in either converting a non-countract account into a contract account, or creation of a contract account.
5. Creation of a contract by execution of `CREATE` or `CREATE2`. This can result in either converting a non-countract account into a contract account, or creation of a contract account.
 
After prepayments are introduced, there can be two reasons for ether to be deducted from `tx.origin`: purchasing and spending gas, and spending gas for prepayments. Gaslimit of a transaction currently plays a role of safety limit, where `gaslimit`  * `gasprice` represents the maximum amount of wei the sender (`tx.origin`) authorises the transaction to deduct from its account.
After prepayments are introduced, `gaslimit` * `gasprice` will still represent the maximum amount of wei spend, but it will be used for both gas purchases and prepayments, as necessary.

## Rationale
Prior to rent prepayments, other alternatives were considered:
1. Simple raising of the gas cost - discussed in the Motivation section.
1. In [first version of State Rent proposal](https://github.com/ledgerwatch/eth_state/blob/master/State_rent.pdf), there was no notion of extra levy upon account creation. It created a slight usability issue, where newly created contracts with 0 endowment would be evicted in the same block (when rent is introduced). It delays the benefits of the State Rent programme until the actual introduction of rent (in second or third hard-fork).
2. In the [second version of State Rent proposal](https://github.com/ledgerwatch/eth_state/blob/master/State_Rent_2.pdf), there was a notion of lock-up. It is very similar to rent prepayment, with the different that lock-up would not be covering future rent payments.

An alternative approach to limiting the prepayments (instead of the using `gaslimit` * `gasprice` as the limit) is to introduce a new dedicated field `prepaymenlimit` into the transaction. This field would only limit prepayments. Such approach would require changes in the transaction format, as well as changes in the user interface for transaction sender, and having two counters during the transaction execution - one for gas, and one for prepayments.

## Backwards Compatibility
This change is not backwards compatible and requires hard fork to be activated.
It might have some adverse effects on the existing contracts, due to more gas needed to be allocated for the creation of new accounts. These adverse effects need to analysed in more detail.

## Test Cases
Tests cases will be generated out of a reference implementation.

## Implementation
There will be proof of concept implementation to refine and clarify the specification.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 14 May 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2026</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2026</guid>
      </item>
    
      <item>
        <title>State Rent C - Net contract size accounting</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2027-net-contract-size-accounting-change-c-from-state-rent-v3-proposal/3275</comments>
        
        <description>## Simple Summary
Ethereum starts counting the number of storage slots filled and emptied in the contracts. Since the number of pre-existing slots is not currently accounted
in the state, effectively, only net change in the number of slots is tracked. In the subsequent change, called *Gross contract size accounting*, the total
number of storage slots starts being tracked.

## Abstract
This is part of the State Rent roadmap. This particular change introduces initial, net accounting of the number of the contract storage slots. Though not very
useful on its own, it makes it possible to introduce gross accounting of the number of storage slots, which is useful for number of things:
1. Gas cost of operations suchs as `SLOAD` and `SSTORE` will need to be increased to compensate for extra bandwidth consumed by the block proofs. Although in
the beginning the cost would be fixed, it will later be automatically calibrated depending on the size of the contract `SLOAD` and `SSTORE` operate on.
2. Snapshot sync protocols, like *fast sync*, *warp sync*, *firehose*, *red queen*, and perhaps others, will benefit from having the correct size of the
contract storage present in the state (and therefore being provable via Merkle proofs).

## Motivation
Ethereum currently does not track the number of contract storage slots at all, and producing such number given the downloaded state cannot be done in
constant *O(1)* time.

## Specification
Each contract (account with `codeHash` field not equal to 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470, which the hash of the empty code) gets a new uint64 field, called `storagesize`. On and after block `C`, the semantics of the operation `SSTORE` (`location`, `value`) changes as follows:
- If previous value of the [`location`] is 0, and value is not 0, *increment* `storagesize` (semantics of *increment* described below)
- If previous value of the [`location`] is not 0, and value is 0, *decrement* `storagesize` (semantics of *decrement* described below)
- As with other state changes, changes of `storagesize` get reverted when the execution frame reverts, i.e. it needs to use the same techniques as storage values, like journalling (in Geth), and substates (in Parity).
Value of `storagesize` is not observable from contracts at this point.

### Semantics of *increment* `storagesize`
If `storagesize` is not present, `storagesize` = `HUGE_NUMBER` + 1.
If `storagesize` is present, `storagesize` = `storagesize` + 1.

### Semantics of *decrement* `storagesize`
If `storagesize` is not present, `storagesize` = `HUGE_NUMBER` - 1.
If `storagesize` is present, `storagesize` = `storagesize` - 1.

### Note of `HUGE_NUMBER`
There is a constant `HUGE_NUMBER`. It needs to be large enough so that no real metrics (contract storage size, number of accounts, number of contracts, total size of code, total size of storage) will never reach that number, and small enough that it fits in an unsigned 64-bit integer.
Current suggestion is to have `HUGE_NUMBER` = 2^63, which is binary representation is the a single bit in a 64-bit number.

The idea is to make it decidable later whether the storagesize was ever incremented/decremented (presence of the field), and whether it has been converted from net to gross (by value being smaller than `HUGE_NUMBER/2` - because it will not be possible for any contract be larger than 2^62 at the block `C`).

## Rationale
A mechanism for estimation of contract storage size has been proposed [here](https://medium.com/@akhounov/estimation-approximate-of-the-size-of-contracst-in-ethereum-4642fe92d6fe). But it does have a big drawback of introducing a lot of complexity into the consensus
(in the form of estimation algorithm, which has quite a few edge cases to cater for different sizes of the storage).

## Backwards Compatibility
This change is not backwards compatible and requires hard fork to be activated. Since the newly introduced field is not observable, this change does not impact any operations of the existing smart contracts. 

## Test Cases
Tests cases will be generated out of a reference implementation.

## Implementation
There will be proof of concept implementation to refine and clarify the specification.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 14 May 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2027</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2027</guid>
      </item>
    
      <item>
        <title>Transaction data gas cost reduction</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2028-calldata-gas-cost-reduction/3280</comments>
        
        <description>## Simple Summary
We propose to reduce the gas cost of Calldata (`GTXDATANONZERO`) from its current value of 68 gas per byte to 16 gas per byte, to be backed by mathematical modeling and empirical estimates. The mathematical model is the one used in the works of Sompolinsky and Zohar [1] and Pass, Seeman and Shelat [2], which relates network security to network delay. We shall (1) evaluate the theoretical impact of lower Calldata gas cost on network delay using this model, (2) validate the model empirically, and (3) base the proposed gas cost on our findings.

## Motivation
There are a couple of main benefits to accepting this proposal and lowering gas cost of Calldata
On-Chain Scalability: Generally speaking, higher bandwidth of Calldata improves scalability, as more data can fit within a single block.
* Layer two scalability: Layer two scaling solutions can improve scalability by moving storage and computation off-chain, but often introduce data transmission instead.
	- Proof systems such as STARKs and SNARKs use a single proof that attests to the computational integrity of a large computation, say, one that processes a large batch of transactions.
	- Some solutions use fraud proofs which requires a transmission of merkle proofs.
	- Moreover, one optional data availability solution to layer two is to place data on the main chain, via Calldata.
* Stateless clients: The same model will be used to determine the price of the state access for the stateless client regime, which will be proposed in the State Rent (from version 4). There, it is expected that the gas cost of state accessing operation will increase roughly proportional to the extra bandwidth required to transmit the “block proofs” as well as extra processing required to verify those block proofs.

## Specification
The gas per non-zero byte is reduced from 68 to 16. Gas cost of zero bytes is unchanged.

## Rationale
Roughly speaking, reducing the gas cost of Calldata leads to potentially larger blocks, which increases the network delay associated with data transmission over the network. This is only part of the full network delay, other factors are block processing time (and storage access, as part of it). Increasing network delay affects security by lowering the cost of attacking the network, because at any given point in time fewer nodes are updated on the latest state of the blockchain.

Yonatan Sompolinsky and Aviv Zohar suggested in [1] an elegant model to relate network delay to network security, and this model is also used in the work of Rafael Pass, Lior Seeman and Abhi Shelat [2]. We briefly explain this model below, because we shall study it theoretically and validate it by empirical measurements to reach the suggested lower gas cost for Calldata.

The model uses the following natural parameters:
* _lambda_  denotes the block creation rate [1/s]: We treat the process of finding a PoW
solution as a poisson process with rate _lambda_.
* _beta_ - chain growth rate [1/s]: the rate at which new blocks are added to
the heaviest chain.
* _D_ - block delay [s]: The time that elapses between the mining of a new block and its acceptance by all the miners (all miners switched to mining on top of that block).

### _Beta_ Lower Bound
Notice that _lambda_ =&gt; _beta_, because not all blocks that are found will enter the main chain (as is the case with uncles). In [1] it was shown that for a blockchain using the longest chain rule, one may bound _beta_ from below by _lambda_/ (1+ D * _lambda_). This lower bound holds in the extremal case where the topology of the network is a clique in which the delay between each pair of nodes is D, the maximal possible delay. Recording both the lower and upper bounds on _beta_ we get

	_lambda_ &gt;= _beta_ &gt;= _lambda_ / (1 + D * _lambda_)               (*)

Notice, as a sanity check, that when there is no delay (D=0) then _beta_ equals _lambda_, as expected.

### Security of the network
An attacker attempting to reorganize the main chain needs to generate blocks at a rate that is greater than _beta_.
Fixing the difficulty level of the PoW puzzle, the total hash rate in the system is correlated to _lambda_. Thus, _beta_ / _lambda_ is defined as the *efficiency* of the system, as it measures the fraction of total hash power that is used to generate the main chain of the network.

Rearranging (*) gives the following lower bound on efficiency in terms of delay:

	_beta_ / _lambda_ &gt;= 1 / (1 + D * _lambda_)                 (**)

### The _delay_ parameter D
The network delay depends on the location of the mining node within the network and on the current network topology (which changes dynamically), and consequently is somewhat difficult to measure directly.
Previously, Christian Decker and Roger Wattenhofer [3] showed that propagation time scales with blocksize,  and Vitalik Buterin showed that uncle rate, which is tightly related to efficiency (**) measure, also scales with block size [4].

However, the delay function can be decomposed into two parts D = *D_t* + *D_p*, where _D_t_ is the delay caused by the transmission of the block and _D_p_ is the delay caused by the processing of the block by the node. Our model and tests will examine the effect of Calldata on each of _D_t_ and _D_p_, postulating that their effect is different. This may be particularly relevant for Layer 2 Scalability and for Stateless Clients (Rationales 2, 3 above) because most of the Calldata associated with these goals are Merkle authentication paths that have a large _D_t_ component but relatively small _D_p_ values.

## Test Cases
To suggest the gas cost of calldata we shall conduct two types of tests:
1. Network tests, conducted on the Ethereum mainnet, used to estimate the effect on increasing block size on _D_p_ and _D_t_, on the overall network delay D and the efficiency ratio (**), as well as delays between different mining pools. Those tests will include regression tests on existing data, and stress tests to introduce extreme scenarios.
2. Local tests, conducted on a single node and measuring the processing time as a function of Calldata amount and general computation limits.

## Reference Implementation
[Parity](https://github.com/liorgold2/parity-ethereum/pull/1)
[Geth](https://github.com/liorgold2/go-ethereum/pull/1)

## References
[1] Yonatan Sompolinsky, Aviv Zohar: [Secure High-Rate Transaction Processing in Bitcoin](https://eprint.iacr.org/2013/881.pdf). Financial Cryptography 2015: 507-527

[2] Rafael Pass, Lior Seeman, Abhi Shelat: [Analysis of the Blockchain Protocol in Asynchronous Networks](https://eprint.iacr.org/2016/454.pdf), ePrint report 2016/454

[3] Christian Decker, Roger Wattenhofer: [Information propagation in the Bitcoin network](https://www.gsd.inesc-id.pt/~ler/docencia/rcs1314/papers/P2P2013_041.pdf). P2P 2013: 1-10

[4] Vitalik Buterin: [Uncle Rate and Transaction Fee Analysis](https://blog.ethereum.org/2016/10/31/uncle-rate-transaction-fee-analysis/)

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 03 May 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2028</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2028</guid>
      </item>
    
      <item>
        <title>State Rent A - State counters contract</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2029-state-counters-contract-change-a-from-state-rent-v3-proposal/3279</comments>
        
        <description>## Simple Summary
A smart contract is deployed on all Ethereum networks, at a pre-determined address, with the code that simply reads the slot in its storage specified by the
only parameter. Later, this contract becomes &quot;special&quot; in that Ethereum start writing state counters (number of total transactions, number of accounts,
etc.) into that contract.

## Abstract
This is part of the State Rent roadmap. This particular change introduces a place in the Ethereum state where various state counters can be stored. At this
point, the most important counter is the total number of transactions happened, and this counter will be used to populate the nonces of newly created
non-contract accounts. This way of populating nonce ensures replay protection for accounts that were evicted and then brought back by sending ether to them.

## Motivation
Ethereum currently does not have a special place in the state for tracking state counters such as number of transactions or number of accounts.

## Specification
Prior to the block A, a contract is deployed with the following code:
`0x60 0x20 0x60 0x00 0x80 0x80 0x35 0x54 0x90 0x52 0xF3`, which corresponds to this assembly:
`PUSH1 32 PUSH1 0 DUP1 DUP1 CALLDATALOAD SLOAD SWAP1 MSTORE RETURN`
Call to this contract accepts one 32-byte argument, `x`, and returns the value of the storage item [`x`].

This contract is deployed using `CREATE2` opcode in such a way that it has the same address on any network.

## Rationale
Two alternative solutions were considered so far:
1. Extending the structure of the Ethereum state to introduce more fields, and hence change the way the state root is constructed. The main downside of this
approach is the impact on the software what is currently coupled with the particular way the state root is constructed. Particularly it affects the software
that deals with merkle proofs derived from the state root.
2. Extended State Oracle ([EIP-2014](/EIPs/EIPS/eip-2014)). Under such proposal, there will be a precompile contract with standardised interface, capable of returning
current values of the counters. However, the actual data being returned by such oracle is not explicitly in the state, and is not Merkelised. It means that all the counters need to be added to the snapshots when the snapshot sync is perform, so they still present in the state, but implicitly.

## Backwards Compatibility
This change is backwards compatible and does not require hard fork to be activated.

## Test Cases
Tests cases will be created to ensure that the state counter contract returns its storage items correctly.

## Implementation
Implementation is envisaged as a transaction that can be posted from any Ethereum address and will cause the deployment of the state counter contract.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 15 May 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2029</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2029</guid>
      </item>
    
      <item>
        <title>State Rent B - Net transaction counter</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2031-net-transaction-counter-change-b-from-state-rent-v3-proposal/3283</comments>
        
        <description>## Simple Summary
Ethereum starts to track the number of transactions inside its state (for now, only number of transactions after this change is introduced, therefore
it is called *Net* transaction count).
It is done by incrementing a storage slot in the special contract, called *State counter contract* ([EIP-2029](/EIPs/EIPS/eip-2029)).

## Abstract
It is part of the State Rent roadmap. This particular change makes any Ethereum transaction increment the transaction counter, which is a special storage slot
in the *State counter contract*. This counter will be used to populate the nonces of newly created
non-contract accounts. This way of populating nonce ensures replay protection for accounts that were evicted and then brought back by sending ether to them.

## Motivation
Ethereum currently does not have a special place in the state for tracking number of transactions.

## Specification
A new field, with the location 0 (that means it resides in the storage slot 0 in the state counter contract, and can
be read by calling that contract with argument being 32 zero bytes), is added to the state counter contract. It will eventually contain `txCount`, the total number of transactions processed up until that point.
On an after block B, or after the deployment of the state counter contract (which comes first), the field `txCount` is incremented after each transaction. Updating `txCount` means updating the storage of state counter contract at the location 0. These changes are never reverted.

## Rationale
Two main alternatives were proposed for the replay protection of the accounts that were evicted by subsequently brought back by sending ether to them:
1. Temporal replay protection. The nonce of the new accounts (and those brought back) is still zero, but a new `valid-until` field is introduced, making
transactions invalid for inclusion after the time specified in this field. This, however, has unwanted side effected related to the fact that account
nonces are not only used for replay protection, but also for computing the addresses of the deployed contracts (except those created by `CREATE2`).
2. Setting nonce of new accounts (and those brought back) to something depending on the current block number. This approach requires coming up with
an arbitrary parameter, which is the maximum number of transaction in the block, so that the new nonces never clash with the existing nonces.
This is mostly a concern for private networks at the moment, because they will potentially have significantly more transactions in a block.

## Backwards Compatibility
This change is not backwards compatible and requires hard fork to be activated.

## Test Cases
Tests cases will be generated out of a reference implementation.

## Implementation
There will be proof of concept implementation to refine and clarify the specification.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Wed, 15 May 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2031</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2031</guid>
      </item>
    
      <item>
        <title>Stateless Clients - Repricing SLOAD and SSTORE to pay for block proofs</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2035-stateless-clients-repricing-sload-and-sstore-to-pay-for-block-proofs/3284</comments>
        
        <description>## Simple Summary

The gas cost of EVM opcodes `SLOAD` and `SSTORE` increases in order to accommodate extra bandwidth required to propagate block proof together with the block
headers and block bodies, as explained [here](https://medium.com/@akhounov/data-from-the-ethereum-stateless-prototype-8c69479c8abc).

## Abstract

It is part of the State Rent roadmap. This particular change prepares Ethereum for introduction of the block proofs (current understanding is that they
can be introduced without a hard fork). The introduction of the block proofs allows any Ethereum node that wishes to receive them, to process transactions
in the blocks without needing to access the Ethereum state. All necessary information for the execution (and the proof of validity) is continued in the
block proofs. In most Ethereum nodes, it will speed up the block processing and reduce the memory footprint of such processing. For mining nodes, however,
there will be more work to do to construct and transmit the block proofs. Therefore, the extra charge (payable to the miners) is introduced. In the first
phase, only contract storage will be covered by the block proofs. It means that the Ethereum nodes will still need access to the accounts in the state,
but block proofs will make it optional to have access to contract storage for executing transactions. Therefore, only `SSTORE` and `SLOAD` opcodes are
affected.

## Motivation

There is [empirical analysis](https://github.com/holiman/vmstats/blob/master/README.md) showing that `SLOAD` opcode is currently underpriced in terms
of execution latency it adds to the block processing. The hypothesis is that it is due to the latency of the database accesses. In the same
analysis, `SSTORE` is not considered, because its effect on the database accesses can be (and are in many implementations) delayed until the end of
the block. Stateless clients approach to the contract storage will largely negate that latency because no database accesses will be required.
Instead, bandwidth consumption goes up. There is empirical analysis (unpublished, but will be) suggesting that 1 uncached `SSTORE` or `SLOAD` adds
at most 1 kB to the block proofs. At the current cost of data transmission (68 gas per byte), this translates to the increase of gas cost of both
operations by 69k gas. However, in light of proposal in [EIP-2028](/EIPs/EIPS/eip-2028), the increase can be made much smaller.

## Specification

Not very formal at the moment, but will be formalised with more research and prototyping. Gas of operations `SLOAD` and `SSTORE` increases by `X` gas when the storage slots accessed (read by `SLOAD` or written by `SSTORE`) were not previously accessed (by another `SLOAD` or `SSTORE`) during the same transaction.

Future variant (will be possible after the implementation of the *Gross contract size accounting*) is researched, where the increase is varied
depending on the size of the contract storage, i.e. `SLOAD` and `SSTORE` for smaller contracts will be cheaper.

## Rationale

[EIP-1884](/EIPs/EIPS/eip-1884) seeks to increase the gas cost of `SLOAD` but using a different justification
(latency of the execution as described in the Motivation). This EIP is likely to increase the cost of `SLOAD` by a larger amount, therefore partially
(because EIP-1884 also proposed other increases) supersedes EIP-1884.

[EIP-2028](/EIPs/EIPS/eip-2028) describes the model that can be used for deciding the gas cost of data transmission. It is relevant
because in the stateless client regime `SSTORE` and `SLOAD` operations add more data to be transmitted (as well as computation to verify the proofs).

The main alternate design is the rent proportional to the size of the contract storage, which unfortunately introduces a serious griefing
vulnerability problem, and so far the solution seems to be in redesigning and rewriting smart contracts in a way, which makes them not vulnerable.
However, this approach is likely to be very expensive on the non-technical (ecosystem) level.

## Backwards Compatibility

This change is not backwards compatible and requires hard fork to be activated.
There might also be an adverse effect of this change on the already deployed contract. It is expected that after this EIP and
[EIP-2026](/EIPs/EIPS/eip-2026) (rent prepayment for accounts), the recommendation will be made to raise the gas limit. This can somewhat dampen the
adverse effect of EIP. The most problematic cases would be with the contracts that assume certain gas costs of `SLOAD`
and `SSTORE` and hard-code them in their internal gas computations. For others, the cost of interacting with the contract
storage will rise and may make some dApps based on such interactions, non-viable. This is a trade off to avoid even bigger
adverse effect of the rent proportional to the contract storage size. However, more research is needed to more fully
analyse the potentially impacted contracts.

## Test Cases

Tests cases will be generated out of a reference implementation.

## Implementation

There will be proof of concept implementation to refine and clarify the specification.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Thu, 16 May 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2035</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2035</guid>
      </item>
    
      <item>
        <title>Particle gas costs for EVM opcodes</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2045-fractional-gas-costs/3311</comments>
        
        <description>## Abstract
According to recent benchmarks, EVM opcodes for computation (`ADD`, `SUB`, `MUL`, etc.) are generally overpriced relative to opcodes for storage I/O (`SLOAD`, `SSTORE`, etc.). Currently the minimum gas cost is 1 (i.e. one unit of gas), and most computational opcodes have a cost near to 1 (e.g. 3, 5, or 8), so the range in possible cost reduction is limited. A new minimum unit of gas, called a &quot;particle&quot;, which is a fraction of 1 gas, would expand the range of gas costs and thus enable reductions below the current minimum.

## Motivation
The transaction capacity of an Ethereum block is determined by the gas cost of transactions relative to the block gas limit. One way to boost the transaction capacity is to raise the block gas limit. Unfortunately, raising the block gas limit would also increase the rate of state growth, unless the costs of state-expanding storage opcodes (`SSTORE`, `CREATE`, etc.) are simultaneously increased to the same proportion. Increasing the cost of storage opcodes may have adverse side effects, such as shifting the economic assumptions around gas fees of deployed contracts, or possibly breaking invariants in current contract executions (as mentioned in [EIP-2035](/EIPs/EIPS/eip-2035)&lt;sup&gt;[1](#eip2035)&lt;/sup&gt;, more research is needed on the potential effects of increasing the cost of storage opcodes).

Another way to boost the transaction capacity of a block is to reduce the gas cost of transactions. Reducing the gas costs of computational opcodes while keeping the cost of storage opcodes the same, is effectively equivalent to raising the block gas limit and simultaneously increasing the cost of storage opcodes. However, reducing the cost of computational opcodes might avoid the adverse side effects of an increase in cost of storage opcodes (again, more research is needed on this topic).

Currently, computational opcode costs are already too close to the minimum unit of 1 gas to achieve the large degree of cost reductions that recent benchmarks&lt;sup&gt;[2](#evmbenchmarks)&lt;/sup&gt; indicate would be needed to tune opcode gas costs to the performance of optimized EVM implementations. A smaller minimum unit called a &quot;particle&quot;, which is a fraction (or subdivision) of 1 gas, would enable large cost reductions.

## Specification
A new gas counter `particlesUsed` is added to the EVM, in addition to the existing gas counter `gasUsed`. The unit 1 gas is equal to 10000 particles (`PARTICLES_PER_GAS`). The `particlesUsed` counter is only increased for opcodes priced in particles (i.e. opcodes that cost less than 1 gas). If increasing `particlesUsed` results in an excess of 1 gas, then 1 gas is added to `gasUsed` (and deducted from `particlesUsed`).

Where the current gas logic looks like this:
```python
def vm_execute(ext, msg, code):
    # Initialize stack, memory, program counter, etc
    compustate = Compustate(gas=msg.gas)
    codelen = len(code)

    while compustate.pc &lt; codelen:
        opcode = code[compustate.pc]
        compustate.pc += 1

        compustate.gasUsed += opcode.gas_fee

        # out of gas error
        if compustate.gasUsed &gt; compustate.gasLimit:
            return vm_exception(&apos;OUT OF GAS&apos;)

        if op == &apos;STOP&apos;:
            return peaceful_exit()
        elif op == &apos;ADD&apos;:
            stk.append(stk.pop() + stk.pop())
        elif op == &apos;SUB&apos;:
            stk.append(stk.pop() - stk.pop())
        elif op == &apos;MUL&apos;:
            stk.append(stk.pop() * stk.pop())

.....
```

The new gas logic using particles might look like this:
```python
PARTICLES_PER_GAS = 10000

def vm_execute(ext, msg, code):
    # Initialize stack, memory, program counter, etc
    compustate = Compustate(gas=msg.gas)
    codelen = len(code)

    while compustate.pc &lt; codelen:
        opcode = code[compustate.pc]
        compustate.pc += 1

        if opcode.gas_fee:
            compustate.gasUsed += opcode.gas_fee
        elif opcode.particle_fee:
            compustate.particlesUsed += opcode.particle_fee
            if compustate.particlesUsed &gt;= PARTICLES_PER_GAS:
                # particlesUsed will be between 1 and 2 gas (over 10000 but under 20000)
                compustate.gasUsed += 1
                # remainder stays in particle counter
                compustate.particlesUsed = compustate.particlesUsed % PARTICLES_PER_GAS

        # out of gas error
        if compustate.gasUsed &gt; compustate.gasLimit:
            return vm_exception(&apos;OUT OF GAS&apos;)

        if op == &apos;STOP&apos;:
            return peaceful_exit()
        elif op == &apos;ADD&apos;:
            stk.append(stk.pop() + stk.pop())
        elif op == &apos;SUB&apos;:
            stk.append(stk.pop() - stk.pop())
        elif op == &apos;MUL&apos;:
            stk.append(stk.pop() * stk.pop())

.....
```

The above pseudocode is written for clarity. A more performant implementation might instead keep a single `particlesUsed` counter by multiplying opcode gas costs by 10000 and the `gasLimit` by 10000, and convert particles back to gas with `ceil(particlesUsed / PARTICLES_PER_GAS)` at the end of execution. It may also be more performant to use a `PARTICLES_PER_GAS` ratio that is a power of 2 (such as 8192 or 16384) instead of 10000; the spec above is a draft and updates in response to feedback are expected.

#### Opcode cost changes
Many computational opcodes will undergo a cost reduction, with new costs suggested by benchmark analyses. For example, the cost of `DUP` and `SWAP` are reduced from 3 gas to 3000 particles (i.e. 0.3 gas). The cost of `ADD` and `SUB` are reduced from 3 gas to 6000 particles. The cost of `MUL` is reduced from 5 gas to 5000 particles (i.e. 0.5 gas).

## Rationale
Adoption of fractional gas costs should only be an implementation detail inside the EVM, and not alter the current user experience around transaction gas limits and block gas limits. The concept of `particles` need not be exposed to Ethereum users nor most contract authors, but only to EVM implementers and contract developers concerned with optimized gas usage. Furthermore, only the EVM logic for charging gas per opcode executed should be affected by this change. All other contexts dealing with gas and gas limits, such as block headers and transaction formats, should be unaffected.

### Ewasm
The term &quot;particles&quot; was first introduced for Ewasm&lt;sup&gt;[3](#particle)&lt;/sup&gt; to enable gas accounting for low cost wasm instructions, while remaining compatible with EVM gas costs. This EIP proposes introducing particles as a new minimum gas unit for EVM opcodes, and is not related to Ewasm.

## Backwards Compatibility
This change is not backwards compatible and requires a hard fork to be activated.

## Test Cases
TODO

## Implementation
TODO

## References
&lt;a name=&quot;eip2035&quot;&gt;1&lt;/a&gt;. [EIP-2035](/EIPs/EIPS/eip-2035): Stateless Clients - Repricing SLOAD and SSTORE to pay for block proofs

&lt;a name=&quot;evmbenchmarks&quot;&gt;2&lt;/a&gt;. https://github.com/ewasm/benchmarking

&lt;a name=&quot;particle&quot;&gt;3&lt;/a&gt;. The term &quot;particle&quot; was inspired by a proposal for [Ewasm gas costs](https://github.com/ewasm/design/blob/e77d8e3de42784f40a803a23f58ef06881142d9f/determining_wasm_gas_costs.md).

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 17 May 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2045</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2045</guid>
      </item>
    
      <item>
        <title>Reduced gas cost for static calls made to precompiles</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2046-reduced-gas-cost-for-static-calls-made-to-precompiles/3291</comments>
        
        <description>## Simple Summary

This change reduces the gas cost of using precompiled contracts.

## Abstract

Reduce the base gas cost of calling precompiles using `STATICCALL` from 700 to 40. This should allow more efficient use of precompiles as well as precompiles with a total cost below 700.

## Motivation

The Spurious Dragon hard fork increased the cost of calls significantly to account for loading contract code from the state without making an exception for precompiles, whose &quot;code&quot; is always loaded.

This made use of certain precompiles impractical.

FIXME: extend this with recent reasoning about ECC repricings.

## Specification

After block `HF` the `STATICCALL` (`0xfa`) instruction charges different basic gas cost (G&lt;sub&gt;call&lt;/sub&gt; in [Yellow Paper]&apos;s notation) depending on the destination address provided:
- for precompiles (address range as per [EIP-1352]) the cost is `40`
- for every other address the cost remains unchanged (`700`)

## Rationale

Only the `STATICCALL` instruction was changed to reduce the impact of the change. This should not be a limiting factor, given precompiles (currently) do not have a state and cannot change the state.
However, contracts created and deployed before Byzantium likely will not use `STATICCALL` and as a result this change will not reduce their costs.

Contrary to EIP-1109 gas reduction to `0` is not proposed. The cost `40` is kept as a cost representing the context switching needed.

## Backwards Compatibility

This EIP should be backwards compatible. The only effect is that the cost is reduced. Since the cost is not reduced to zero, it should not be possible for a malicious proxy contract, when deployed before
the `HF`, to do any state changing operation.

## Test Cases

TBA

## Implementation

TBA

## References

This has been previously suggested as part of [EIP-1109](/EIPs/EIPS/eip-1109) and [EIP-1231](https://github.com/ethereum/EIPs/pull/1231).
However EIP-1109 was later changed to a very different approach. The author [has suggested to change EIP-1109](https://ethereum-magicians.org/t/eip-1109-remove-call-costs-for-precompiled-contracts/447/7).

## Acknowledgements

Jordi Baylina (@jbaylina) and Matthew Di Ferrante (@mattdf) who have proposed this before.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[Yellow Paper]: https://github.com/ethereum/yellowpaper

[EIP-1352]: /EIPs/EIPS/eip-1352
</description>
        <pubDate>Fri, 17 May 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2046</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2046</guid>
      </item>
    
      <item>
        <title>Recommendation for using YAML ABI in ERCs/EIPs</title>
        <category>Informational/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2069-recommendation-for-using-yaml-abi-in-specifications/3347</comments>
        
        <description>## Simple Summary

Recommendation for including contract ABI descriptions in EIPs and ERCs as YAML.

## Motivation

In the past, most ERCs/EIPs included an ABI description purely as a Solidity contract and/or interface. This has several drawbacks:

- Prefers a single language over others and could hinder the development of new languages. 
- Locks the specification to a certain version of the Solidity language.
- Allows the use of syntactical elements and features of the Solidity language, which may not be well representable in the ABI. This puts other languages at even more disadvantage.

This proposal aims to solve all these issues.

## Specification

The [Standard Contract ABI] is usually represented as a JSON object.  This works well and several tools – including compilers and clients – support it to handle data encoding.

One shortcoming of the JSON description is its inability to contain comments.  To counter this, we suggest the use of YAML for providing user readable specifications.  Given YAML was designed to be compatible with JSON, several tools exist to convert between the two formats.

The following example contains a single function, `transfer` with one input and one output in YAML:

```yaml
# The transfer function. Takes the recipient address
# as an input and returns a boolean signaling the result.
- name: transfer
  type: function
  payable: false
  constant: false
  stateMutability: nonpayable
  inputs:
  - name: recipient
    type: address
  - name: amount
    type: uint256
  outputs:
  - name: &apos;&apos;
    type: bool
```

Specifications are encouraged to include comments in the YAML ABI.

For details on what fields and values are valid in the ABI, please consult the [Standard Contract ABI] specification.

The same in JSON:

```json
[
  {
    &quot;name&quot;: &quot;transfer&quot;,
    &quot;type&quot;: &quot;function&quot;,
    &quot;payable&quot;: false,
    &quot;constant&quot;: false,
    &quot;stateMutability&quot;: &quot;nonpayable&quot;,
    &quot;inputs&quot;: [
      {
        &quot;name&quot;: &quot;recipient&quot;,
        &quot;type&quot;: &quot;address&quot;
      },
      {
        &quot;name&quot;: &quot;amount&quot;,
        &quot;type&quot;: &quot;uint256&quot;
      }
    ],
    &quot;outputs&quot;: [
      {
        &quot;name&quot;: &quot;&quot;,
        &quot;type&quot;: &quot;bool&quot;
      }
    ]
  }
]
```

## Rationale

The aim was to choose a representation which is well supported by tools and supports comments. While inventing a more concise description language seems like a good idea, it felt as an unnecessary layer of complexity.

## Backwards Compatibility

This has no effect on backwards compatibility.

## Test Cases

TBA

## Implementation

[yamabi] is a Javascript tool to convert between the above YAML and the more widely used JSON format.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[Standard Contract ABI]: https://solidity.readthedocs.io/en/latest/abi-spec.html
[yamabi]: https://github.com/axic/yamabi/
</description>
        <pubDate>Sat, 11 Feb 2017 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2069</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2069</guid>
      </item>
    
      <item>
        <title>Hardfork Meta: Berlin</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/hardfork-meta-eip-2070-berlin-discussion/3561</comments>
        
        <description>## Abstract

This meta-EIP specifies the changes included in the Ethereum hardfork named Berlin.

## Specification

- Codename: Berlin

In the current stage of coordination, the changes are tracked and discussed in the [eth1.0-specs](https://github.com/ethereum/eth1.0-specs) repository.
For an accurate status please refer to the [`berlin.md`](https://github.com/ethereum/eth1.0-specs/blob/master/network-upgrades/mainnet-upgrades/berlin.md) file.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 20 May 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2070</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2070</guid>
      </item>
    
      <item>
        <title>Compact Signature Representation</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2440</comments>
        
        <description>## Abstract

The secp256k1 curve permits the computation of the public key of signed
digest when coupled with a signature, which is used implicitly to
establish the origin of a transaction from an Externally Owned Account
as well as on-chain in EVM contracts for example, in meta-transactions and
multi-sig contracts.

Currently signatures require 65 bytes to represent, which when aligned
to 256-bit words, requires 96 bytes (with 31 zero bytes injected). The
yParity in RLP-encoded transactions also require (on average) 1.5 bytes.
With compact signatures, this can be reduced to 64 bytes, which remains 64
bytes when word-aligned, and in the case of RLP-encoded transactions
saves the 1.5 bytes required for the yParity.

## Motivation

The motivations for a compact representation are to simplify handling
transactions in client code, reduce gas costs and reduce transaction sizes.


## Specification

A secp256k1 signature is made up of 3 parameters, `r`, `s` and `yParity`.
The `r` represents the `x` component on the curve (from which the `y` can be
computed), and the `s` represents the challenge solution for signing by a
private key. Due to the symmetric nature of an elliptic curve, a `yParity`
is required, which indicates which of the 2 possible solutions was intended,
by indicating its parity (odd-ness).

Two key observations are required to create a compact representation.

First, the `yParity` parameter is always either 0 or 1 (canonically the values
used have historically been 27 and 28, as these values didn&apos;t collide with other
binary prefixes used in Bitcoin).

Second, the top bit of the `s` parameters is **always** 0, due to the use of
canonical signatures which flip the solution parity to prevent negative values,
which was introduced as [a constraint in Homestead](/EIPs/EIPS/eip-2).

So, we can hijack the top bit in the `s` parameter to store the value of
`yParity`, resulting in:

```
[256-bit r value][1-bit yParity value][255-bit s value]
```


### Example Implementation In Python

```python
# Assume yParity is 0 or 1, normalized from the canonical 27 or 28
def to_compact(r, s, yParity):
    return {
        &quot;r&quot;: r,
        &quot;yParityAndS&quot;: (yParity &lt;&lt; 255) | s
    }

def to_canonical(r, yParityAndS):
    return {
        &quot;r&quot;: r,
        &quot;s&quot;: yParityAndS &amp; ((1 &lt;&lt; 255) - 1),
        &quot;yParity&quot;: (yParityAndS &gt;&gt; 255)
    }
```


## Rationale

The compact representation proposed is simple to both compose and decompose
in clients and in Solidity, so that it can be easily (and intuitively) supported,
while reducing transaction sizes and gas costs.


## Backwards Compatibility

The Compact Representation does not collide with canonical signature as
it uses 2 parameters (r, yParityAndS) and is 64 bytes long while canonical
signatures involve 3 separate parameters (r, s, yParity) and are 65 bytes long.


## Test Cases

```
Private Key: 0x1234567890123456789012345678901234567890123456789012345678901234
Message: &quot;Hello World&quot;
Signature:
  r:  0x68a020a209d3d56c46f38cc50a33f704f4a9a10a59377f8dd762ac66910e9b90
  s:  0x7e865ad05c4035ab5792787d4a0297a43617ae897930a6fe4d822b8faea52064
  v:  27
Compact Signature:
  r:           0x68a020a209d3d56c46f38cc50a33f704f4a9a10a59377f8dd762ac66910e9b90
  yParityAndS: 0x7e865ad05c4035ab5792787d4a0297a43617ae897930a6fe4d822b8faea52064
```

```
Private Key: 0x1234567890123456789012345678901234567890123456789012345678901234
Message: &quot;It&apos;s a small(er) world&quot;
Signature:
  r:  0x9328da16089fcba9bececa81663203989f2df5fe1faa6291a45381c81bd17f76
  s:  0x139c6d6b623b42da56557e5e734a43dc83345ddfadec52cbe24d0cc64f550793
  v:  28
Compact Signature:
  r:           0x9328da16089fcba9bececa81663203989f2df5fe1faa6291a45381c81bd17f76
  yParityAndS: 0x939c6d6b623b42da56557e5e734a43dc83345ddfadec52cbe24d0cc64f550793  
```


## Reference Implementation

The ethers.js library [supports this in v5](https://github.com/ethers-io/ethers.js/blob/ethers-v5-beta/packages/bytes/src.ts/index.ts#L323)
as an unofficial property of split signatures (i.e. `sig._vs`), but should be
considered an internal property that may change at discretion of the community
and any changes to this EIP.


## Security Considerations 

There are no additional security concerns introduced by this EIP.


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 14 Mar 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2098</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2098</guid>
      </item>
    
      <item>
        <title>Fork identifier for chain compatibility checks</title>
        <category>Standards Track/Networking</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2125</comments>
        
        <description>## Simple Summary

Currently nodes in the Ethereum network try to find each other by establishing random connections to remote machines &quot;looking&quot; like an Ethereum node (public networks, private networks, test networks, etc), hoping that they found a useful peer (same genesis, same forks). This wastes time and resources, especially for smaller networks.

To avoid this overhead, Ethereum needs a mechanism that can precisely identify whether a node will be useful, as early as possible. Such a mechanism requires a way to summarize chain configurations, as well as a way to disseminate said summaries in the network.

This proposal focuses only on the definition of said summary - a generally useful *fork identifier* - and it&apos;s validation rules, allowing it to be embedded into arbitrary network protocols (e.g. [discovery ENRs](/EIPs/EIPS/eip-778) or `eth/6x` handshakes).

## Abstract

There are many public and private Ethereum networks, but the discovery protocol doesn&apos;t differentiate between them. The only way to check if a peer is good or bad (same chain or not), is to establish a TCP/IP connection, wrap it with RLPx cryptography, then execute an `eth` handshake. This is an extreme cost to bear if it turns out that the remote peer is on a different network and it&apos;s not even precise enough to differentiate Ethereum and Ethereum Classic. This cost is magnified for small networks, where a lot more trial and errors are needed to find good nodes.

Even if the peer **is** on the same chain, during non-controversial consensus upgrades, not everybody updates their nodes in time (developer nodes, leftovers, etc). These stale nodes put a meaningless burden on the peer-to-peer network, since they just latch on to good nodes, but don&apos;t accept upgraded blocks. This causes valuable peer slots and bandwidth to be lost until the stale nodes finally update. This is a serious issue for test networks, where leftovers can linger for months.

This EIP proposes a new identity scheme to both precisely and concisely summarize the chain&apos;s current status (genesis and all applied forks). The conciseness is particularly important to make the identity useful across datagram protocols too. The EIP solves a number of issues:

 * If two nodes are on different networks, they should never even consider connecting.
 * If a hard fork passes, upgraded nodes should reject non-upgraded ones, but **NOT** before.
 * If two chains share the same genesis, but not forks (ETH / ETC), they should reject each other.

This EIP does not attempt to solve the clean separation of 3-way-forks! If at the same future block number, the network splits into three (non-fork, fork-A and fork-B), separating the forkers from each another will need case-by-case special handling. Not handling this keeps the proposal pragmatic, simple and also avoids making it too easy to fork off mainnet.

To keep the scope limited, this EIP only defines the identity scheme and validation rules. The same scheme and algorithm can be embedded into various networking protocols, allowing both the `eth/6x` handshake to be more precise (Ethereum vs. Ethereum Classic); as well as the discovery to be more useful (reject surely peers without ever connecting).

## Motivation

Peer-to-peer networking is messy and hard due to firewalls and network address translation (NAT). Generally only a small fraction of nodes have publicly routed addresses and P2P networks rely mainly on these for forwarding data for everyone else. The best way to maximize the utility of the public nodes is to ensure their resources aren&apos;t wasted on tasks that are worthless to the network.

By aggressively cutting off incompatible nodes from each other we can extract a lot more value from the public nodes, making the entire P2P network much more robust and reliable. Supporting this network partitioning at a discovery layer can further enhance performance as we avoid the costly crypto and latency/bandwidth hit associated with establishing a stream connection in the first place.

## Specification

Each node maintains the following values:

- **`FORK_HASH`**: IEEE CRC32 checksum (`[4]byte`) of the genesis hash and fork blocks numbers that already passed.
  - The fork block numbers are fed into the CRC32 checksum in ascending order.
  - If multiple forks are applied at the same block, the block number is checksummed only once.
  - Block numbers are regarded as `uint64` integers, encoded in big endian format when checksumming.
  - If a chain is configured to start with a non-Frontier ruleset already in its genesis, that is NOT considered a fork.
- **`FORK_NEXT`**: Block number (`uint64`) of the next upcoming fork, or `0` if no next fork is known.

E.g. `FORK_HASH` for mainnet would be:

- forkhash₀ = `0xfc64ec04` (Genesis) = `CRC32(&lt;genesis-hash&gt;)`
- forkhash₁ = `0x97c2c34c` (Homestead) = `CRC32(&lt;genesis-hash&gt; || uint64(1150000))`
- forkhash₂ = `0x91d1f948` (DAO fork) = `CRC32(&lt;genesis-hash&gt; || uint64(1150000) || uint64(1920000))`

The *fork identifier* is defined as `RLP([FORK_HASH, FORK_NEXT])`. This `forkid` is cross validated (**NOT** naively compared) to assess a remote chain&apos;s compatibility. Irrespective of fork state, both parties must come to the same conclusion to avoid indefinite reconnect attempts from one side.

#### Validation rules

- 1) If local and remote `FORK_HASH` matches, compare local head to `FORK_NEXT`.
  - The two nodes are in the same fork state currently. They might know of differing future forks, but that&apos;s not relevant until the fork triggers (might be postponed, nodes might be updated to match).
    - 1a) A remotely announced but remotely not passed block is already passed locally, disconnect, since the chains are incompatible.
    - 1b) No remotely announced fork; or not yet passed locally, connect.

- 2) If the remote `FORK_HASH` is a subset of the local past forks and the remote `FORK_NEXT` matches with the locally following fork block number, connect.
  - Remote node is currently syncing. It might eventually diverge from us, but at this current point in time we don&apos;t have enough information.
- 3) If the remote `FORK_HASH` is a superset of the local past forks and can be completed with locally known future forks, connect.
  - Local node is currently syncing. It might eventually diverge from the remote, but at this current point in time we don&apos;t have enough information.
- 4) Reject in all other cases.

#### Stale software examples

The examples below try to exhaust the fork combination possibilities that arise when nodes do not run matching software versions, but otherwise follow the same chain (mainnet nodes, testnet nodes, etc).

| Past forks | Future forks | Head | Remote `FORK_HASH` | Remote `FORK_NEXT` | Connect | Reason |
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
| A | | | A | | Yes (1b) | Same forks, same sync state. |
| A | | &lt; B | A | B | Yes (1b) | Remote is advertising a future fork, but that is uncertain. |
| A | | &gt;= B | A | B | No (1a) | Remote is advertising a future fork that passed locally. |
| A | B | | A |  | Yes (1b) | Local knows about a future fork, but that is uncertain. |
| A | B | | A | B | Yes (1b) | Both know about a future fork, but that is uncertain. |
| A | B1 | &lt; B2 | A | B2 | Yes (1b) | Both know about differing future forks, but those are uncertain. |
| A | B1 | &gt;= B2 | A | B2 | No (1a) | Both know about differing future forks, but the remote one passed locally. |
| [A,B] | | | A | B | Yes (2) | Remote out of sync. |
| [A,B,C] | | | A | B | Yes¹ (2) | Remote out of sync. Remote will need a software update, but we don&apos;t know it yet. |
| A | B | | A ⊕ B | | Yes (3) | Local out of sync. |
| A | B,C | | A ⊕ B | | Yes (3) | Local out of sync. Local also knows about a future fork, but that is uncertain yet. |
| A | | | A ⊕ B | | No (4) | Local needs software update. |
| A | B | | A ⊕ B ⊕ C | | No² (4) | Local needs software update. |
| [A,B] | | | A | | No (4) | Remote needs software update. |

*Note, there&apos;s one asymmetry in the table, marked with ¹ and ². Since we don&apos;t have access to a remote node&apos;s future fork list (just the next one), we can&apos;t detect that it&apos;s software is stale until it syncs up. This is acceptable as 1) the remote node will disconnect from us anyway, and 2) this is a temporary fluke during sync, not permanent with a leftover node.*

## Rationale

##### Why flatten `FORK_HASH` into 4 bytes? Why not share the entire genesis and fork list?

Whilst the `eth` devp2p protocol permits arbitrarily much data to be transmitted, the discovery protocol&apos;s total space allowance for all ENR entries is 300 bytes.

Reducing the `FORK_HASH` into a 4 bytes checksum ensures that we leave ample room in the ENR for future extensions; and 4 bytes is more than enough for arbitrarily many Ethereum networks from a (practical) collision perspective.

##### Why use IEEE CRC32 as the checksum instead of Keccak256?

We need a mechanism that can flatten arbitrary data into 4 bytes, without ignoring any of the input. Any other checksum or hashing algorithm would work, but since nodes can lie at any time, there&apos;s no value in cryptographic hash functions.

Instead of just taking the first 4 bytes of a Keccak256 hash (seems odd) or XOR-ing all the 4-byte groups (messy), CRC32 is a better alternative, as this is exactly what it was designed for. IEEE CRC32 is also used by ethernet, gzip, zip, png, etc, so every programming language support should not be a problem.

##### We&apos;re not using `FORK_NEXT` for much, can&apos;t we get rid of it somehow?

We need to be able to differentiate whether a remote node is out of sync or whether its software is stale. Sharing only the past forks cannot tell us if the node is legitimately behind or stuck.

##### Why advertise only one next fork, instead of &quot;hashing&quot; all known future ones like the `FORK_HASH`?

Opposed to past forks that have already passed (for us locally) and can be considered immutable, we don&apos;t know anything about future ones. Maybe we&apos;re out of sync or maybe the fork didn&apos;t pass yet. If it didn&apos;t pass yet, it might be postponed, so enforcing it would split the network apart. It could also happen that we&apos;re not yet aware of all future forks (haven&apos;t updated our software in a while).

## Backwards Compatibility

This EIP only defines an identity scheme, it does not define functional changes.

## Test Cases

Here&apos;s a full suite of tests for all possible fork IDs that Mainnet, Ropsten, Rinkeby and Görli can advertise given the Petersburg fork cap (time of writing).

```go
type testcase struct {
	head uint64
	want ID
}
tests := []struct {
	config  *params.ChainConfig
	genesis common.Hash
	cases   []testcase
}{
	// Mainnet test cases
	{
		params.MainnetChainConfig,
		params.MainnetGenesisHash,
		[]testcase{
			{0, ID{Hash: 0xfc64ec04, Next: 1150000}},       // Unsynced
			{1149999, ID{Hash: 0xfc64ec04, Next: 1150000}}, // Last Frontier block
			{1150000, ID{Hash: 0x97c2c34c, Next: 1920000}}, // First Homestead block
			{1919999, ID{Hash: 0x97c2c34c, Next: 1920000}}, // Last Homestead block
			{1920000, ID{Hash: 0x91d1f948, Next: 2463000}}, // First DAO block
			{2462999, ID{Hash: 0x91d1f948, Next: 2463000}}, // Last DAO block
			{2463000, ID{Hash: 0x7a64da13, Next: 2675000}}, // First Tangerine block
			{2674999, ID{Hash: 0x7a64da13, Next: 2675000}}, // Last Tangerine block
			{2675000, ID{Hash: 0x3edd5b10, Next: 4370000}}, // First Spurious block
			{4369999, ID{Hash: 0x3edd5b10, Next: 4370000}}, // Last Spurious block
			{4370000, ID{Hash: 0xa00bc324, Next: 7280000}}, // First Byzantium block
			{7279999, ID{Hash: 0xa00bc324, Next: 7280000}}, // Last Byzantium block
			{7280000, ID{Hash: 0x668db0af, Next: 0}},       // First and last Constantinople, first Petersburg block
			{7987396, ID{Hash: 0x668db0af, Next: 0}},       // Today Petersburg block
		},
	},
	// Ropsten test cases
	{
		params.TestnetChainConfig,
		params.TestnetGenesisHash,
		[]testcase{
			{0, ID{Hash: 0x30c7ddbc, Next: 10}},            // Unsynced, last Frontier, Homestead and first Tangerine block
			{9, ID{Hash: 0x30c7ddbc, Next: 10}},            // Last Tangerine block
			{10, ID{Hash: 0x63760190, Next: 1700000}},      // First Spurious block
			{1699999, ID{Hash: 0x63760190, Next: 1700000}}, // Last Spurious block
			{1700000, ID{Hash: 0x3ea159c7, Next: 4230000}}, // First Byzantium block
			{4229999, ID{Hash: 0x3ea159c7, Next: 4230000}}, // Last Byzantium block
			{4230000, ID{Hash: 0x97b544f3, Next: 4939394}}, // First Constantinople block
			{4939393, ID{Hash: 0x97b544f3, Next: 4939394}}, // Last Constantinople block
			{4939394, ID{Hash: 0xd6e2149b, Next: 6485846}}, // First Petersburg block
			{6485845, ID{Hash: 0xd6e2149b, Next: 6485846}}, // Last Petersburg block
			{6485846, ID{Hash: 0x4bc66396, Next: 0}},       // First Istanbul block
			{7500000, ID{Hash: 0x4bc66396, Next: 0}},       // Future Istanbul block
		},
	},
	// Rinkeby test cases
	{
		params.RinkebyChainConfig,
		params.RinkebyGenesisHash,
		[]testcase{
			{0, ID{Hash: 0x3b8e0691, Next: 1}},             // Unsynced, last Frontier block
			{1, ID{Hash: 0x60949295, Next: 2}},             // First and last Homestead block
			{2, ID{Hash: 0x8bde40dd, Next: 3}},             // First and last Tangerine block
			{3, ID{Hash: 0xcb3a64bb, Next: 1035301}},       // First Spurious block
			{1035300, ID{Hash: 0xcb3a64bb, Next: 1035301}}, // Last Spurious block
			{1035301, ID{Hash: 0x8d748b57, Next: 3660663}}, // First Byzantium block
			{3660662, ID{Hash: 0x8d748b57, Next: 3660663}}, // Last Byzantium block
			{3660663, ID{Hash: 0xe49cab14, Next: 4321234}}, // First Constantinople block
			{4321233, ID{Hash: 0xe49cab14, Next: 4321234}}, // Last Constantinople block
			{4321234, ID{Hash: 0xafec6b27, Next: 5435345}}, // First Petersburg block
			{5435344, ID{Hash: 0xafec6b27, Next: 5435345}}, // Last Petersburg block
			{5435345, ID{Hash: 0xcbdb8838, Next: 0}},       // First Istanbul block
			{6000000, ID{Hash: 0xcbdb8838, Next: 0}},       // Future Istanbul block
		},
	},
	// Goerli test cases
	{
		params.GoerliChainConfig,
		params.GoerliGenesisHash,
		[]testcase{
			{0, ID{Hash: 0xa3f5ab08, Next: 1561651}},       // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople and first Petersburg block
			{1561650, ID{Hash: 0xa3f5ab08, Next: 1561651}}, // Last Petersburg block
			{1561651, ID{Hash: 0xc25efa5c, Next: 0}},       // First Istanbul block
			{2000000, ID{Hash: 0xc25efa5c, Next: 0}},       // Future Istanbul block
		},
	},
}
```

 Here&apos;s a suite of tests of the different states a Mainnet node might be in and the different remote fork identifiers it might be required to validate and decide to accept or reject:

```go
tests := []struct {
	head uint64
	id   ID
	err  error
}{
	// Local is mainnet Petersburg, remote announces the same. No future fork is announced.
	{7987396, ID{Hash: 0x668db0af, Next: 0}, nil},

	// Local is mainnet Petersburg, remote announces the same. Remote also announces a next fork
	// at block 0xffffffff, but that is uncertain.
	{7987396, ID{Hash: 0x668db0af, Next: math.MaxUint64}, nil},

	// Local is mainnet currently in Byzantium only (so it&apos;s aware of Petersburg), remote announces
	// also Byzantium, but it&apos;s not yet aware of Petersburg (e.g. non updated node before the fork).
	// In this case we don&apos;t know if Petersburg passed yet or not.
	{7279999, ID{Hash: 0xa00bc324, Next: 0}, nil},

	// Local is mainnet currently in Byzantium only (so it&apos;s aware of Petersburg), remote announces
	// also Byzantium, and it&apos;s also aware of Petersburg (e.g. updated node before the fork). We
	// don&apos;t know if Petersburg passed yet (will pass) or not.
	{7279999, ID{Hash: 0xa00bc324, Next: 7280000}, nil},

	// Local is mainnet currently in Byzantium only (so it&apos;s aware of Petersburg), remote announces
	// also Byzantium, and it&apos;s also aware of some random fork (e.g. misconfigured Petersburg). As
	// neither forks passed at neither nodes, they may mismatch, but we still connect for now.
	{7279999, ID{Hash: 0xa00bc324, Next: math.MaxUint64}, nil},

	// Local is mainnet Petersburg, remote announces Byzantium + knowledge about Petersburg. Remote
	// is simply out of sync, accept.
	{7987396, ID{Hash: 0xa00bc324, Next: 7280000}, nil},

	// Local is mainnet Petersburg, remote announces Spurious + knowledge about Byzantium. Remote
	// is definitely out of sync. It may or may not need the Petersburg update, we don&apos;t know yet.
	{7987396, ID{Hash: 0x3edd5b10, Next: 4370000}, nil},

	// Local is mainnet Byzantium, remote announces Petersburg. Local is out of sync, accept.
	{7279999, ID{Hash: 0x668db0af, Next: 0}, nil},

	// Local is mainnet Spurious, remote announces Byzantium, but is not aware of Petersburg. Local
	// out of sync. Local also knows about a future fork, but that is uncertain yet.
	{4369999, ID{Hash: 0xa00bc324, Next: 0}, nil},

	// Local is mainnet Petersburg. remote announces Byzantium but is not aware of further forks.
	// Remote needs software update.
	{7987396, ID{Hash: 0xa00bc324, Next: 0}, ErrRemoteStale},

	// Local is mainnet Petersburg, and isn&apos;t aware of more forks. Remote announces Petersburg +
	// 0xffffffff. Local needs software update, reject.
	{7987396, ID{Hash: 0x5cddc0e1, Next: 0}, ErrLocalIncompatibleOrStale},

	// Local is mainnet Byzantium, and is aware of Petersburg. Remote announces Petersburg +
	// 0xffffffff. Local needs software update, reject.
	{7279999, ID{Hash: 0x5cddc0e1, Next: 0}, ErrLocalIncompatibleOrStale},

	// Local is mainnet Petersburg, remote is Rinkeby Petersburg.
	{7987396, ID{Hash: 0xafec6b27, Next: 0}, ErrLocalIncompatibleOrStale},

	// Local is mainnet Petersburg, far in the future. Remote announces Gopherium (non existing fork)
	// at some future block 88888888, for itself, but past block for local. Local is incompatible.
	//
	// This case detects non-upgraded nodes with majority hash power (typical Ropsten mess).
	{88888888, ID{Hash: 0x668db0af, Next: 88888888}, ErrLocalIncompatibleOrStale},

	// Local is mainnet Byzantium. Remote is also in Byzantium, but announces Gopherium (non existing
	// fork) at block 7279999, before Petersburg. Local is incompatible.
	{7279999, ID{Hash: 0xa00bc324, Next: 7279999}, ErrLocalIncompatibleOrStale},
}
```

Here&apos;s a couple of tests to verify the proper RLP encoding (since `FORK_HASH` is a 4 byte binary but `FORK_NEXT` is an 8 byte quantity):

```go
tests := []struct {
  id   ID
  want []byte
}{
  {
    ID{Hash: 0, Next: 0},
    common.Hex2Bytes(&quot;c6840000000080&quot;),
  },
  {
    ID{Hash: 0xdeadbeef, Next: 0xBADDCAFE},
    common.Hex2Bytes(&quot;ca84deadbeef84baddcafe&quot;),
  },
  {
    ID{Hash: math.MaxUint32, Next: math.MaxUint64},
    common.Hex2Bytes(&quot;ce84ffffffff88ffffffffffffffff&quot;),
  },
}
```

## Implementation

Geth: https://github.com/ethereum/go-ethereum/tree/master/core/forkid

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 03 May 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2124</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2124</guid>
      </item>
    
      <item>
        <title>Consumable Interface (Tickets, etc)</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2135-erc-consumable-interface/3439</comments>
        
        <description>## Abstract

This EIP defines an interface to mark a digital asset as &quot;consumable&quot; and to react to its &quot;consumption.&quot;

## Motivation

Digital assets sometimes need to be consumed. One of the most common examples is a concert ticket.
It is &quot;consumed&quot; when the ticket-holder enters the concert hall.

Having a standard interface enables interoperability for services, clients, UI, and inter-contract functionalities on top of this use-case.

## Specification

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.

1. Any compliant contract **MUST** implement the following interface:

```solidity
pragma solidity &gt;=0.7.0 &lt;0.9.0;

/// The ERC-165 identifier of this interface is 0xdd691946
interface IERC2135 {
    /// @notice The consume function consumes a token every time it succeeds.
    /// @param _consumer the address of consumer of this token. It doesn&apos;t have
    ///                  to be the EOA or contract Account that initiates the TX.
    /// @param _assetId  the NFT asset being consumed
    /// @param _data     extra data passed in for consume for extra message
    ///                  or future extension.
    function consume(
        address _consumer,
        uint256 _assetId,
        uint256 _amount,
        bytes calldata _data
    ) external returns (bool _success);

    /// @notice The interface to check whether an asset is consumable.
    /// @param _consumer the address of consumer of this token. It doesn&apos;t have
    ///                  to be the EOA or contract Account that initiates the TX.
    /// @param _assetId  the NFT asset being consumed.
    /// @param _amount   the amount of the asset being consumed.
    function isConsumableBy(
        address _consumer,
        uint256 _assetId,
        uint256 _amount
    ) external view returns (bool _consumable);

    /// @notice The event emitted when there is a successful consumption.
    /// @param consumer the address of consumer of this token. It doesn&apos;t have
    ///                  to be the EOA or contract Account that initiates the TX.
    /// @param assetId  the NFT asset being consumed
    /// @param amount   the amount of the asset being consumed.
    /// @param data     extra data passed in for consume for extra message
    ///                  or future extension.
    event OnConsumption(
        address indexed consumer,
        uint256 indexed assetId,
        uint256 amount,
        bytes data
    );
}
```

2. If the compliant contract is an [ERC-721](/EIPs/EIPS/eip-721) or [ERC-1155](/EIPs/EIPS/eip-1155) token, in addition to `OnConsumption`, it **MUST** also emit the `Transfer` / `TransferSingle` event (as applicable) as if a token has been transferred from the current holder to the zero address if the call to `consume` method succeeds.

3. `supportsInterface(0xdd691946)` **MUST** return `true` for any compliant contract, as per [ERC-165](/EIPs/EIPS/eip-165).

## Rationale

1. The function `consume` performs the consume action. This EIP does not assume:

- who has the power to perform consumption
- under what condition consumption can occur

It does, however, assume the asset can be identified in a `uint256` asset id as in the parameter. A design convention and compatibility consideration is put in place to follow the ERC-721 pattern.

2. The event notifies subscribers whoever are interested to learn an asset is being consumed.

3. To keep it simple, this standard *intentionally* contains no functions or events related to the creation of a consumable asset. This is because the creation of a consumable asset will need to make assumptions about the nature of an actual use-case. If there are common use-cases for creation, another follow up standard can be created.

4. Metadata associated to the consumables is not included the standard. If necessary, related metadata can be created with a separate metadata extension interface like `ERC721Metadata` from [ERC-721](/EIPs/EIPS/eip-721)

5. We choose to include an `address consumer` for `consume` function and `isConsumableBy` so that an NFT MAY be consumed for someone other than the transaction initiator.

6. We choose to include an extra `_data` field for future extension, such as
adding crypto endorsements.

7. We explicitly stay opinion-less about whether ERC-721 or ERC-1155 shall be required because
while we design this EIP with ERC-721 and ERC-1155 in mind mostly, we don&apos;t want to rule out
the potential future case someone use a different token standard or use it in different use cases.

8. The boolean view function of `isConsumableBy` can be used to check whether an asset is
consumable by the `_consumer`.

## Backwards Compatibility

This interface is designed to be compatible with ERC-721 and NFT of ERC-1155. It can be tweaked to used for [ERC-20](/EIPs/EIPS/eip-20), [ERC-777](/EIPs/EIPS/eip-777) and Fungible Token of ERC-1155.

## Test Cases

```ts

  describe(&quot;Consumption&quot;, function () {
    it(&quot;Should consume when minted&quot;, async function () {
      const fakeTokenId = &quot;0x1234&quot;;
      const { contract, addr1 } = await loadFixture(deployFixture);
      await contract.safeMint(addr1.address, fakeTokenId);
      expect(await contract.balanceOf(addr1.address)).to.equal(1);
      expect(await contract.ownerOf(fakeTokenId)).to.equal(addr1.address);
      expect(await contract.isConsumableBy(addr1.address, fakeTokenId, 1)).to.be.true;
      const tx = await contract.consume(addr1.address, fakeTokenId, 1, []);
      const receipt = await tx.wait();
      const events = receipt.events.filter((x: any) =&gt; { return x.event == &quot;OnConsumption&quot; });
      expect(events.length).to.equal(1);
      expect(events[0].args.consumer).to.equal(addr1.address);
      expect(events[0].args.assetId).to.equal(fakeTokenId);
      expect(events[0].args.amount).to.equal(1);
      expect(await contract.balanceOf(addr1.address)).to.equal(0);
      await expect(contract.ownerOf(fakeTokenId))
        .to.be.rejectedWith(&apos;ERC721: invalid token ID&apos;);
      await expect(contract.isConsumableBy(addr1.address, fakeTokenId, 1))
        .to.be.rejectedWith(&apos;ERC721: invalid token ID&apos;);
    });
  });

  describe(&quot;EIP-165 Identifier&quot;, function () {
    it(&quot;Should match&quot;, async function () {
      const { contract } = await loadFixture(deployFixture);
      expect(await contract.get165()).to.equal(&quot;0xdd691946&quot;);
      expect(await contract.supportsInterface(&quot;0xdd691946&quot;)).to.be.true;
    });
  });
```

## Reference Implementation

A deployment of version 0x1002 has been deployed onto `goerli` testnet at address `0x3682bcD67b8A5c0257Ab163a226fBe07BF46379B`.

Find the reference contract verified source code on Etherscan&apos;s
`goerli` site for the address above.

## Security Considerations

Compliant contracts should pay attention to the balance change when a token is consumed.
When the contract is being paused, or the user is being restricted from transferring a token,
the consumeability should be consistent with the transferral restriction.

Compliant contracts should also carefully define access control, particularly whether any EOA or contract account may or may not initiate a `consume` method in their own use case.

Security audits and tests should be used to verify that the access control to the `consume`
function behaves as expected.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 23 Jun 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2135</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2135</guid>
      </item>
    
      <item>
        <title>dType Storage Extension - Decentralized Type System for EVM</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2157</comments>
        
        <description>## Simple Summary

This ERC is an extension of ERC-1900, proposing an optional storage extension for dType, a decentralized type system, specifying a general ABI for all storage contracts that contain type instances.

## Abstract

The storage extension will enable easy navigation and retrieval of type data that is intended to be of public use. This is possible through standardizing the ABI of the dType storage contracts, with the effect of having a deterministic path to a type instance record. This standardization enables a more effective on-chain and off-chain use of data and opens up possibilities for decentralized applications, enabling developers to build on top of public global data.

## Motivation

Currently, Ethereum does not have standardization of data addressability. This might not be needed for data that is meant to be quasi-private, however, it is needed for data that is meant for public consumption. ERC-1900 has started standardizing data types for increasing interoperability between projects, but this is not enough if we want to build a global ecosystem. Deterministic data addressability will enable anyone to build upon the same public data sets, off-chain or on-chain.

It is true that with ERC-1900, blockchain data analysis and type-specific data retrieval will be possible off-chain, but this implies relying on centralized data caches (blockchain explorers) or maintaining your own data cache. Moreover, this option does not allow on-chain standardization on data retrieval paths, therefore limiting the type of on-chain interoperable operations that can be done.

Having a clear way of retrieving data, instead of analyzing the blockchain for contracts that have a certain type in their ABI or bytecode, will make development easier and more decentralized for applications that target global data on specific types.

For example, a decentralized market place can be built on top of some marketplace-specific types, and by knowing exactly where the type data is stored, it is easy to create custom algorithms that provide the user with the product information they seek. Everyone has access to the data and the data path is standardized.

Moreover, by standardizing storage contract interfaces, ABI inference is possible. The common interface, together with the dType registry will provide all the data needed to reconstruct the ABI.

This system can be extended with access and mutability control later on, in a future proposal. Access and mutability control will be necessary for public-use global systems. Moreover, we can have a homogeneous application of permissions across system components. This is not detailed in the present proposal.

Another use case is data bridges between Ethereum shards or between Ethereum and other chains. Data syncing between shards/chains can be done programmatically, across data types (from various projects). Imagine a user having a public profile/identity contract on one chain, wishing to move that profile on Ethereum. By supporting the origin chain types and having a standardized storage mechanism, data moving processes will be the same.

This pattern of separating data type definitions and storage allows developers to create functional programming-like patterns on Ethereum, even though languages such as Solidity are not functional.

## Specification

### TypeRootContract

ERC-1900 defines a `contractAddress` field in the type metadata. For the limited purpose of ERC-1900, this field contains the value of the Ethereum type library in which the type definition exists. For the purpose of this ERC, the `contractAddress` will contain the Etherereum address of a `TypeRootContract`.

```solidity
contract TypeRootContract {
  address public libraryAddress;
  address public storageAddress;

  constructor(address _library, address _storage) public {
    libraryAddress = _library;
    storageAddress = _storage;
  }
}
```

- `libraryAddress` - Ethereum address of the type definition library, from ERC-1900
- `storageAddress` - Ethereum address of the type data storage contract


### TypeStorageContract

This contract will use the type library to define the internal data stored in it. Each record will be a type instance, addressable by a primary identifier. The primary identifier is calculated by the type library&apos;s `getIdentifier` function, based on the type instance values.

We propose a Solidity CRUD pattern, as described in https://medium.com/robhitchens/solidity-crud-part-1-824ffa69509a, where records can also be retrieved using their index - a monotonically increasing counter.

An stub implementation for the TypeStorageContract would look like:

```solidity
import &apos;./TypeALib.sol&apos;;

contract TypeAStorage {
    using TypeALib for TypeALib.TypeA;

    bytes32[] public typeIndex;
    mapping(bytes32 =&gt; Type) public typeStruct;

    struct Type {
        TypeALib.TypeA data;
        uint256 index;
    }

    event LogNew(bytes32 indexed identifier, uint256 indexed index);
    event LogUpdate(bytes32 indexed identifier, uint256 indexed index);
    event LogRemove(bytes32 indexed identifier, uint256 indexed index);

    function insert(TypeALib.TypeA memory data) public returns (bytes32 identifier);

    function insertBytes(bytes memory data) public returns (bytes32 identifier);

    function remove(bytes32 identifier) public returns(uint256 index);

    function update(bytes32 identifier, TypeALib.TypeA memory data) public returns(bytes32 identifier)

    function isStored(bytes32 identifier) public view returns(bool stored);

    function getByHash(bytes32 identifier) public view returns(TypeALib.TypeA memory data);

    function getByIndex(uint256 index) public view returns(TypeALib.TypeA memory data);

    function count() public view returns(uint256 counter);
}
```

## Rationale

We are now thinking about a building block as a smart contract with an encapsulated object that contains state changing functions that are only understood from within. This is more akin to Object-Oriented Programming and poses interoperability and scalability issues. Not necessarily for an individual project, but for a global Ethereum OS. This is why we are proposing to separate data from business logic and data structure definitions.

When you have public aggregated data, categorized on each type, anyone can build tools on top of it. This is a radical change from the closed or dispersed data patterns that we find in web2.

We have chosen to define a `TypeRootContract` instead of extending the dType registry with fields for the TypeStorage contract, because this approach enables easier interface updates in the future. It is more extensible.

The storage pattern used for dType itself and all the Type Storage contracts can be the same. This lowers the cost of building, testing and auditing the code.

The `TypeStorageContract` pattern should ensure:
- type instance addressability by the primary identifier
- a way to retrieve all records from the contract
- counting the number of records


## Backwards Compatibility

This proposal does not affect existent Ethereum standards or implementations. It uses the present experimental version of ABIEncoderV2.

## Test Cases

Will be added.

## Implementation

An in-work implementation can be found at https://github.com/pipeos-one/dType/tree/master/contracts/contracts.
This proposal will be updated with an appropriate implementation when consensus is reached on the specifications.


## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 28 Jun 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2157</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2157</guid>
      </item>
    
      <item>
        <title>Common Prometheus Metrics Names for Clients</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/common-chain-metrics/3415</comments>
        
        <description>## Simple Summary
Standardized names of common metrics for Ethereum clients to use with Prometheus, a widely used monitoring and alerting solution.

## Abstract
Many Ethereum clients expose a range of metrics in a format compatible with Prometheus to allow operators to monitor the client&apos;s behaviour and performance and raise alerts if the chain isn&apos;t progressing or there are other indications of errors.
While the majority of these metrics are highly client-specific, reporting on internal implementation details of the client, some are applicable to all clients.
By standardizing the naming and format of these common metrics, operators are able to monitor the operation of multiple clients in a single dashboard or alerting configuration. 

## Motivation
Using common names and meanings for metrics which apply to all clients allows node operators to monitor clusters of nodes using heterogeneous clients using a single dashboard and alerting configuration.
Currently there are no agreed names or meanings, leaving client developers to invent their own making it difficult to monitor a heterogeneous cluster. 

## Specification
The table below defines metrics which may be captured by Ethereum clients which expose metrics to Prometheus. Clients may expose additional metrics however these should not use the `ethereum_` prefix.

| Name                             | Metric type | Definition                                                        | JSON-RPC Equivalent                                                 |
|----------------------------------|-------------|-------------------------------------------------------------------|---------------------------------------------------------------------|
| ethereum_blockchain_height       | Gauge       | The current height of the canonical chain                         | `eth_blockNumber`                                                   |
| ethereum_best_known_block_number | Gauge       | The estimated highest block available                             | `highestBlock` of `eth_syncing` or `eth_blockNumber` if not syncing | 
| ethereum_peer_count              | Gauge       | The current number of peers connected                             | `net_peerCount`                                                     |
| ethereum_peer_limit              | Gauge       | The maximum number of peers this node allows to connect           | No equivalent                                                       |

Note that `ethereum_best_known_block_number` always has a value. When the `eth_syncing` JSON-RPC method would return `false`, the current chain height is used.

## Rationale
The defined metrics are independent of Ethereum client implementation but provide sufficient information to create an overview dashboard to support monitoring a group of Ethereum nodes.

There is a similar, though more prescriptive, specification for beacon chain client metrics.
The specific details of how to expose the metrics has been omitted as there is variance in existing implementations and standardising this does not provide any significant benefit.

## Backwards Compatibility
This is *not* a consensus affecting change.

Clients may already be publishing these metrics using different names and changing to the new form may break existing alerts or dashboards. Clients that want to avoid this incompatibility can expose the metrics under both the old and new names.

Clients may also be publishing metrics with a different meaning using these names. Backwards compatibility cannot be preserved in this case.


## Implementation
Pantheon switched to using these standard metric names in its 1.2 release: https://github.com/PegaSysEng/pantheon/pull/1634.

## References

 1. Prometheus. https://prometheus.io
 2. Beacon chain metrics specification. https://github.com/ethereum/eth2.0-metrics/blob/master/metrics.md

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 01 Jul 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2159</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2159</guid>
      </item>
    
      <item>
        <title>dType Alias Extension - Decentralized Type System</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2192</comments>
        
        <description>## Simple Summary

We are proposing Alias - a semantic standard for identifying on-chain resources by human-readable qualifiers, supporting any type of data.

## Abstract

The dType Alias is a system for providing human-readable resource identifiers to on-chain content. A resource identifier is based on the type of data (identifier provided by dType, [EIP-1900](/EIPs/EIPS/eip-1900)) and the data content (identifier provided by a dType Storage Contract, [EIP-2157](/EIPs/EIPS/eip-2157)). It is a universal way of addressing content, supporting any type of data.

## Motivation

There are standards that currently address the need for attaching human-readable identifiers to Ethereum accounts, such as [EIP-137](/EIPs/EIPS/eip-137). These standards are an attempt to bring domain names to Ethereum, following the same format as DNS: `subdomain.domain.tld`. This leaf -&gt; root format is unintuitive and contradicts the semantic meaning that `.` has in programming languages, which is a root -&gt; leaf connection (e.g. in OOP, when accessing an object&apos;s property). A more intuitive and widely used approach is a root-&gt;leaf format, used in file browsers, hierarchical menus, and even in other decentralized systems, which give unique identifiers to resources (e.g. `0x56.Currency.TCoin` in [Libra](https://medium.com/r/?url=https%3A%2F%2Fdevelopers.libra.org).

Moreover, [EIP-137](/EIPs/EIPS/eip-137) is not flexible enough to address smart contract content,  which can contain heterogeneous data that belongs to various accounts. For example, a `PaymentChannel` smart contract can have an domain name. However, the `Alice-Bob` channel data from inside the smart contract, cannot have a subdomain name. Having uniquely identified, granular resources opens the way to creating both human and machine-readable protocols on top of Ethereum. It also provides a basis for protocols based on functional programming.

This ERC proposes a set of separators which maintain their semantic meaning and provides a way to address any type of resource - from Ethereum addresses, to individual `struct` instances inside smart contracts.

Imagine the following dType types: `SocialNetwork` and `Profile`, with related storage data about user profiles. One could access such a profile using an alias for the data content: `alice@socialnetwork.profile`. For a `PaymentChannel` type, Alice can refer to her channel with Bob with `alice-bob.paymentchannel`.
This alias system can be used off-chain, to replace the old DNS system with a deterministic and machine-readable way of displaying content, based on the dType type&apos;s metadata.

## Specification

The dType registry will provide domain and subdomain names for the resource type. Subdomains can be attributed recursively, to dType types which contain other complex types in their composition.

We define an `Alias` registry contract, that keeps track of the human-readable identifiers for data resources, which exist in dType storage contracts.
Anyone can set an alias in the `Alias` registry, as long as the Ethereum address that signs the alias data has ownership on the resource, in the dType storage contract. Storage contract data ownership will be detailed in [EIP-2157](/EIPs/EIPS/eip-2157). An owner can update or delete an alias at any time.

```solidity
interface Alias {

    event AliasSet(bytes32 dtypeIdentifier, bytes1 separator, string name, bytes32 indexed identifier);

    function setAlias(bytes32 dtypeIdentifier, bytes1 separator, string memory name, bytes32 identifier, bytes memory signature) external;

    function getAliased(bytes1 separator, string memory name) view external returns (bytes32 identifier);
}
```

- `dtypeIdentifier`: Type identifier from the dType registry, needed to ensure uniqueness of `name` for a dType type. `dtypeIdentifier` is checked to see if it exists in the dType registry. The dType registry also links the type&apos;s data storage contract, where the existence and ownership of the `identifier` is checked.
- `name`: user-defined human-readable name for the resource referenced by `identifier`
- `separator`: Character acting as a separator between the name and the rest of the alias. Allowed values:
  - `.`: general domain separation, using root-&gt;leaf semantics. E.g. `domain.subdomain.leafsubdomain.resource`
  - `@`: identifying actor-related data, such as user profiles, using leaf-&gt;root semantics. E.g. `alice@socialnetwork.profile` or `alice@dao@eth`
  - `#`: identifying concepts, using root-&gt;leaf semantics. E.g. `topicX#postY`
  - `/`: general resource path definition, using root-&gt;leaf semantics. E.g. `resourceRoot/resource`
- `identifier`: Resource identifier from a smart contract linked with dType
- `signature`: Alias owner signature on `dtypeIdentifier`, `identifier`, `name`, `separator`, `nonce`, `aliasAddress`, `chainId`.
  - `nonce`: monotonically increasing counter, used to prevent replay attacks
  - `aliasAddress`: Ethereum address of `Alias` contract
  - `chainId`: chain on which the `Alias` contract is deployed, as detailed in [EIP-155](/EIPs/EIPS/eip-155), used to prevent replay attacks when updating the `identifier` for an alias.

Content addressability can be done:
- using the `bytes32` identifiers directly, e.g. `0x0b5e76559822448f6243a6f76ac7864eba89c810084471bdee2a63429c92d2e7@0x9dbb9abe0c47484c5707699b3ceea23b1c2cca2ac72681256ab42ae01bd347da`
- using the human identifiers, e.g. `alice@socialnetwork`

Both of the above examples will resolve to the same content.


## Rationale

Current attempts to solve content addressability, such as [EIP-137](/EIPs/EIPS/eip-137), only target Ethereum accounts. These are based on inherited concepts from HTTP and DNS, which are not machine friendly.

With [EIP-1900](/EIPs/EIPS/eip-1900) and [EIP-2157](/EIPs/EIPS/eip-2157), general content addressability can be achieved. dType provides type information and a reference to the smart contract where the type instances are stored. Additionally, Alias uses the semantic meaning of subdomain separators to have a [intuitive order rule](https://github.com/loredanacirstea/articles/blob/master/articles/Flexible_Alias_or_Why_ENS_is_Obsolete.md).

Multiple aliases can be assigned to a single resource. Either by using a different `name` or by using a different `separator`. Each `separator` can have a specific standard for displaying and processing data, based on its semantic meaning.

## Backwards Compatibility

Will be added.

## Test Cases

Will be added.

## Implementation

An in-work implementation can be found at https://github.com/pipeos-one/dType/blob/master/contracts/contracts/Alias.sol.
This proposal will be updated with an appropriate implementation when consensus is reached on the specifications.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 16 Jul 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2193</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2193</guid>
      </item>
    
      <item>
        <title>Structured Definitions for Net Gas Metering</title>
        <category>Standards Track/Core</category>
        
          <comments>https://github.com/sorpaas/EIPs/issues/1</comments>
        
        <description>## Simple Summary

This is an EIP that implements net gas metering. It&apos;s a combined
version of [EIP-1283] and [EIP-1706], with a structured definition so as
to make it interoperable with other gas changes such as [EIP-1884].

## Abstract

This EIP provides a structured definition of net gas metering changes
for `SSTORE` opcode, enabling new usages for contract storage, and
reducing excessive gas costs where it doesn’t match how most
implementation works.

This is a combination of [EIP-1283] and [EIP-1706].

## Motivation

This EIP proposes a way for gas metering on `SSTORE`, using information
that is more universally available to most implementations, and
require as little change in implementation structures as possible.

* Storage slot’s original value.
* Storage slot’s current value.
* Refund counter.

Usages that benefits from this EIP’s gas reduction scheme includes:

* Subsequent storage write operations within the same call frame. This
  includes reentry locks, same-contract multi-send, etc.
* Exchange storage information between sub call frame and parent call
  frame, where this information does not need to be persistent outside
  of a transaction. This includes sub-frame error codes and message
  passing, etc.

The original definition of EIP-1283 created a danger of a new kind of
reentrancy attacks on existing contracts as Solidity by default grants
a &quot;stipend&quot; of 2300 gas to simple transfer calls. This danger is
easily mitigated if `SSTORE` is not allowed in low gasleft state,
without breaking the backward compatibility and the original intention
of EIP-1283.

This EIP also replaces the original EIP-1283 value definitions of gas
by parameters, so that it&apos;s more structured, and easier to define
changes in the future.

## Specification

Define variables `SLOAD_GAS`, `SSTORE_SET_GAS`, `SSTORE_RESET_GAS` and
`SSTORE_CLEARS_SCHEDULE`. The old and new values for those variables
are:

* `SLOAD_GAS`: changed from `200` to `800`.
* `SSTORE_SET_GAS`: `20000`, not changed.
* `SSTORE_RESET_GAS`: `5000`, not changed.
* `SSTORE_CLEARS_SCHEDULE`: `15000`, not changed.

Change the definition of EIP-1283 using those variables. The new
specification, combining EIP-1283 and EIP-1706, will look like
below. The terms *original value*, *current value* and *new value* are
defined in EIP-1283.

Replace `SSTORE` opcode gas cost calculation (including refunds) with
the following logic:

* If *gasleft* is less than or equal to gas stipend, fail the current
  call frame with &apos;out of gas&apos; exception.
* If *current value* equals *new value* (this is a no-op), `SLOAD_GAS`
  is deducted.
* If *current value* does not equal *new value*
  * If *original value* equals *current value* (this storage slot has
    not been changed by the current execution context)
    * If *original value* is 0, `SSTORE_SET_GAS` is deducted.
    * Otherwise, `SSTORE_RESET_GAS` gas is deducted. If *new value* is
      0, add `SSTORE_CLEARS_SCHEDULE` gas to refund counter.
  * If *original value* does not equal *current value* (this storage
    slot is dirty), `SLOAD_GAS` gas is deducted. Apply both of the
    following clauses.
    * If *original value* is not 0
      * If *current value* is 0 (also means that *new value* is not
        0), remove `SSTORE_CLEARS_SCHEDULE` gas from refund
        counter.
      * If *new value* is 0 (also means that *current value* is not
        0), add `SSTORE_CLEARS_SCHEDULE` gas to refund counter.
    * If *original value* equals *new value* (this storage slot is
      reset)
      * If *original value* is 0, add `SSTORE_SET_GAS - SLOAD_GAS` to
        refund counter.
      * Otherwise, add `SSTORE_RESET_GAS - SLOAD_GAS` gas to refund
        counter.

An implementation should also note that with the above definition, if
the implementation uses call-frame refund counter, the counter can go
negative. If the implementation uses transaction-wise refund counter,
the counter always stays positive.

## Rationale

This EIP mostly achieves what a transient storage tries to do
([EIP-1087] and [EIP-1153]), but without the complexity of introducing the
concept of &quot;dirty maps&quot;, or an extra storage struct.

* We don&apos;t suffer from the optimization limitation of
  EIP-1087. EIP-1087 requires keeping a dirty map for storage changes,
  and implicitly makes the assumption that a transaction&apos;s storage
  changes are committed to the storage trie at the end of a
  transaction. This works well for some implementations, but not for
  others. After [EIP-658], an efficient storage cache implementation
  would probably use an in-memory trie (without RLP encoding/decoding)
  or other immutable data structures to keep track of storage changes,
  and only commit changes at the end of a block. For them, it is
  possible to know a storage&apos;s original value and current value, but
  it is not possible to iterate over all storage changes without
  incurring additional memory or processing costs.
* It never costs more gas compared with the current scheme.
* It covers all usages for a transient storage. Clients that are easy
  to implement EIP-1087 will also be easy to implement this
  specification. Some other clients might require a little bit extra
  refactoring on this. Nonetheless, no extra memory or processing cost
  is needed on runtime.

Regarding `SSTORE` gas cost and refunds, see Appendix for proofs of
properties that this EIP satisfies.

* For *absolute gas used* (that is, actual *gas used* minus *refund*),
  this EIP is equivalent to EIP-1087 for all cases.
* For one particular case, where a storage slot is changed, reset to
  its original value, and then changed again, EIP-1283 would move more
  gases to refund counter compared with EIP-1087.

Examine examples provided in EIP-1087&apos;s Motivation (with `SLOAD_GAS` being
`200`):

* If a contract with empty storage sets slot 0 to 1, then back to 0,
  it will be charged `20000 + 200 - 19800 = 400` gas.
* A contract with empty storage that increments slot 0 5 times will be
  charged `20000 + 5 * 200 = 21000` gas.
* A balance transfer from account A to account B followed by a
  transfer from B to C, with all accounts having nonzero starting and
  ending balances, it will cost `5000 * 3 + 200 - 4800 = 10400` gas.

In order to keep in place the implicit reentrancy protection of
existing contracts, transactions should not be allowed to modify state
if the remaining gas is lower than the gas stipend given to
&quot;transfer&quot;/&quot;send&quot; in Solidity. These are other proposed remediations
and objections to implementing them:

* Drop EIP-1283 and abstain from modifying `SSTORE` cost
  * EIP-1283 is an important update 
  * It was accepted and implemented on test networks and in clients.
* Add a new call context that permits LOG opcodes but not changes to state.
  * Adds another call type beyond existing regular/staticcall
* Raise the cost of `SSTORE` to dirty slots to &gt;=2300 gas
  * Makes net gas metering much less useful.
* Reduce the gas stipend
  * Makes the stipend almost useless.
* Increase the cost of writes to dirty slots back to 5000 gas, but add
  4800 gas to the refund counter
  * Still doesn’t make the invariant explicit.
  * Requires callers to supply more gas, just to have it refunded
* Add contract metadata specifying per-contract EVM version, and only
  apply `SSTORE` changes to contracts deployed with the new version.

## Backwards Compatibility

This EIP requires a hard fork to implement. No gas cost increase is
anticipated, and many contracts will see gas reduction.

Performing `SSTORE` has never been possible with less than 5000 gas, so
it does not introduce incompatibility to the Ethereum Mainnet. Gas
estimation should account for this requirement.

## Test Cases

| Code                               | Used Gas | Refund | Original | 1st | 2nd | 3rd |
|------------------------------------|----------|--------|----------|-----|-----|-----|
| `0x60006000556000600055`           | 1612     | 0      | 0        | 0   | 0   |     |
| `0x60006000556001600055`           | 20812    | 0      | 0        | 0   | 1   |     |
| `0x60016000556000600055`           | 20812    | 19200  | 0        | 1   | 0   |     |
| `0x60016000556002600055`           | 20812    | 0      | 0        | 1   | 2   |     |
| `0x60016000556001600055`           | 20812    | 0      | 0        | 1   | 1   |     |
| `0x60006000556000600055`           | 5812     | 15000  | 1        | 0   | 0   |     |
| `0x60006000556001600055`           | 5812     | 4200   | 1        | 0   | 1   |     |
| `0x60006000556002600055`           | 5812     | 0      | 1        | 0   | 2   |     |
| `0x60026000556000600055`           | 5812     | 15000  | 1        | 2   | 0   |     |
| `0x60026000556003600055`           | 5812     | 0      | 1        | 2   | 3   |     |
| `0x60026000556001600055`           | 5812     | 4200   | 1        | 2   | 1   |     |
| `0x60026000556002600055`           | 5812     | 0      | 1        | 2   | 2   |     |
| `0x60016000556000600055`           | 5812     | 15000  | 1        | 1   | 0   |     |
| `0x60016000556002600055`           | 5812     | 0      | 1        | 1   | 2   |     |
| `0x60016000556001600055`           | 1612     | 0      | 1        | 1   | 1   |     |
| `0x600160005560006000556001600055` | 40818    | 19200  | 0        | 1   | 0   | 1   |
| `0x600060005560016000556000600055` | 10818    | 19200  | 1        | 0   | 1   | 0   |

## Implementation

To be added.

## Appendix: Proof

Because the *storage slot&apos;s original value* is defined as the value
when a reversion happens on the *current transaction*, it&apos;s easy to
see that call frames won&apos;t interfere `SSTORE` gas calculation. So
although the below proof is discussed without call frames, it applies
to all situations with call frames. We will discuss the case
separately for *original value* being zero and not zero, and use
*induction* to prove some properties of `SSTORE` gas cost.

*Final value* is the value of a particular storage slot at the end of
a transaction. *Absolute gas used* is the absolute value of *gas used*
minus *refund*. We use `N` to represent the total number of `SSTORE`
operations on a storage slot. For states discussed below, refer to
*State Transition* in *Explanation* section.

Below we do the proof under the assumption that all parameters are
unchanged, meaning `SLOAD_GAS` is `200`. However, note that the proof
still applies no matter how `SLOAD_GAS` is changed.

### Original Value Being Zero

When *original value* is 0, we want to prove that:

* **Case I**: If the *final value* ends up still being 0, we want to charge `200 *
  N` gases, because no disk write is needed.
* **Case II**: If the *final value* ends up being a non-zero value, we want to
  charge `20000 + 200 * (N-1)` gas, because it requires writing this
  slot to disk.
  
#### Base Case

We always start at state A. The first `SSTORE` can:

* Go to state A: 200 gas is deducted. We satisfy *Case I* because
  `200 * N == 200 * 1`.
* Go to state B: 20000 gas is deducted. We satisfy *Case II* because
  `20000 + 200 * (N-1) == 20000 + 200 * 0`.
  
#### Inductive Step

* From A to A. The previous gas cost is `200 * (N-1)`. The current
  gas cost is `200 + 200 * (N-1)`. It satisfy *Case I*.
* From A to B. The previous gas cost is `200 * (N-1)`. The current
  gas cost is `20000 + 200 * (N-1)`. It satisfy *Case II*.
* From B to B. The previous gas cost is `20000 + 200 * (N-2)`. The
  current gas cost is `200 + 20000 + 200 * (N-2)`. It satisfy
  *Case II*.
* From B to A. The previous gas cost is `20000 + 200 * (N-2)`. The
  current gas cost is `200 - 19800 + 20000 + 200 * (N-2)`. It satisfy
  *Case I*.
  
### Original Value Not Being Zero

When *original value* is not 0, we want to prove that:

* **Case I**: If the *final value* ends up unchanged, we want to
  charge `200 * N` gases, because no disk write is needed.
* **Case II**: If the *final value* ends up being zero, we want to
  charge `5000 - 15000 + 200 * (N-1)` gas. Note that `15000` is the
  refund in actual definition.
* **Case III**: If the *final value* ends up being a changed non-zero
  value, we want to charge `5000 + 200 * (N-1)` gas.
  
#### Base Case

We always start at state X. The first `SSTORE` can:

* Go to state X: 200 gas is deducted. We satisfy *Case I* because
  `200 * N == 200 * 1`.
* Go to state Y: 5000 gas is deducted. We satisfy *Case III* because
  `5000 + 200 * (N-1) == 5000 + 200 * 0`.
* Go to state Z: The absolute gas used is `5000 - 15000` where 15000
  is the refund. We satisfy *Case II* because `5000 - 15000 + 200 *
  (N-1) == 5000 - 15000 + 200 * 0`.
  
#### Inductive Step

* From X to X. The previous gas cost is `200 * (N-1)`. The current gas
  cost is `200 + 200 * (N-1)`. It satisfy *Case I*.
* From X to Y. The previous gas cost is `200 * (N-1)`. The current gas
  cost is `5000 + 200 * (N-1)`. It satisfy *Case III*.
* From X to Z. The previous gas cost is `200 * (N-1)`. The current
  absolute gas cost is `5000 - 15000 + 200 * (N-1)`. It satisfy *Case
  II*.
* From Y to X. The previous gas cost is `5000 + 200 * (N-2)`. The
  absolute current gas cost is `200 - 4800 + 5000 + 200 * (N-2)`. It
  satisfy *Case I*.
* From Y to Y. The previous gas cost is `5000 + 200 * (N-2)`. The
  current gas cost is `200 + 5000 + 200 * (N-2)`. It satisfy *Case
  III*.
* From Y to Z. The previous gas cost is `5000 + 200 * (N-2)`. The
  current absolute gas cost is `200 - 15000 + 5000 + 200 * (N-2)`. It
  satisfy *Case II*.
* From Z to X. The previous gas cost is `5000 - 15000 + 200 *
  (N-2)`. The current absolute gas cost is `200 + 10200 + 5000 -
  15000 + 200 * (N-2)`. It satisfy *Case I*.
* From Z to Y. The previous gas cost is `5000 - 15000 + 200 *
  (N-2)`. The current absolute gas cost is `200 + 15000 + 5000 -
  15000 + 200 * (N-2)`. It satisfy *Case III*.
* From Z to Z. The previous gas cost is `5000 - 15000 + 200 *
  (N-2)`. The current absolute gas cost is `200 + 5000 - 15000 + 200 *
  (N-2)`. It satisfy *Case II*.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[EIP-1283]: /EIPs/EIPS/eip-1283

[EIP-1706]: /EIPs/EIPS/eip-1706

[EIP-1884]: /EIPs/EIPS/eip-1884

[EIP-1087]: /EIPs/EIPS/eip-1087

[EIP-1153]: /EIPs/EIPS/eip-1153

[EIP-658]: /EIPs/EIPS/eip-658
</description>
        <pubDate>Thu, 18 Jul 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2200</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2200</guid>
      </item>
    
      <item>
        <title>Canonicalize the name of network ID 1 and chain ID 1</title>
        <category>Informational/</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2228</comments>
        
        <description>## Simple Summary

The Ethereum network with network ID 1 and chain ID 1 is named Ethereum Mainnet.

## Abstract

The name for the Ethereum network with network ID 1 and chain ID 1 shall be Ethereum Mainnet or just Mainnet. This is a proper noun.

This standard specifies the name for this network and provides reference examples in an effort to standardize the word choice and provide a common language for use to refer to this network.

## Motivation

The Ethereum network with network ID 1 and chain ID 1 is referenced using several conflicting names across EIPs, client implementations, and information published on the internet at large. In several locations, even documents written by the same author use inconsistent names to refer to the Ethereum network with network ID 1 and chain ID 1. Names in use at the time of this writing include:

* &quot;main net&quot;
* &quot;mainnet&quot;
* &quot;Main net&quot;
* &quot;Mainnet&quot;

## Specification

The network name for network ID 1 and chain ID 1 shall be Ethereum Mainnet, or just Mainnet if the context is known to be discussing Ethereum networks. This IS a proper noun. Several examples are given below which differentiate between usage of the name of the network versus a descriptive reference to the network.

Any name or word styling (i.e. capitalization of the letters) of the network which is inconsistent with the test cases cited below shall NOT be used.

### Trademark note

&quot;Ethereum&quot; is trademarked by the Ethereum Foundation. For more information on your obligations when mentioning &quot;Ethereum&quot;, and possibly &quot;Ethereum Mainnet&quot;, see:

* USPTO registration number 5110579 by Ethereum Foundation
* The note &quot;you must not use [this mark] without the prior written permission of the Foundation&quot; on the Ethereum Foundation website, Terms of Use page

## Rationale

Choosing common word use promotes interoperability of implementations and increases customer awareness. Also, it adds a sense of professionalism when customers see the same word and word styling (i.e. capitalization of letters) across different implementations.

Anybody that has travelled to certain countries and seen an &quot;IPhone [sic]&quot; repair store should immediately recognize that this is off-brand and unofficial. Likewise, the astute customer of Ethereum should recognize if they see the network referred to using inconsistent names in different software, so let&apos;s avoid this.

## Backwards Compatibility

- MetaMask previously used &quot;Main Ethereum Network&quot; in the account network chooser. MetaMask has been updated consistent with this EIP.

- References to Mainnet that are inconsistent with this specification are made in: [EIP-2](/EIPs/EIPS/eip-2), [EIP-779](/EIPs/EIPS/eip-779), [EIP-150](/EIPs/EIPS/eip-150), [EIP-155](/EIPs/EIPS/eip-155), [EIP-190](/EIPs/EIPS/eip-190), [EIP-225](/EIPs/EIPS/eip-225), [EIP-1013](/EIPs/EIPS/eip-1013), [EIP-2028](/EIPs/EIPS/eip-2028), and [EIP-2387](/EIPs/EIPS/eip-2387). For consistency, we recommend the editor will update EIPs to consistently use the name as specified in this EIP.

## Test Cases

### Examples referencing the name of the network ✅

&gt; The contract was deployed to Ethereum Mainnet.

&gt; Ethereum runs many applications, this Dapp was deployed to Mainnet.

No specification is made on whether Dapp, dapp, dApp, etc. is preferred.

&gt; SWITCH TO MAINNET

This example shows a user interface which is in uppercase. To be semantically correct, this could be written in HTML as `&lt;span style=&quot;text-transform: uppercase&quot;&gt;Switch to Mainnet&lt;/span&gt;`.

&gt; switch to mainnet

This example shows a user interface which is in lowercase. To be semantically correct, this could be written in HTML as `&lt;span style=&quot;text-transform: lowercase&quot;&gt;Switch to Mainnet&lt;/span&gt;`.

### Examples referencing the network in a descriptive way ✅

&gt; Mainnet has ### times the number of transactions as the test networks.

### Examples of other correct word usage ✅

&gt; The main network on Ethereum is Mainnet

This shows that &quot;main&quot; is used as a descriptive word, but Mainnet is the specific network which is having network ID 1 and chain ID 1.

### Examples of poor word choice (avoid this) ❌

&gt; Deploy your contract to the Ethereum main network.

This is referring to a &quot;main&quot; network which is context-dependent. If you were reading this text on a page about Ethereum Classic, they would be referring to network ID 2 and chain ID 62. Therefore this word usage is less crisp. Do NOT use wording like this.

&gt; Connect to mainnet.

These words literally mean nothing. The lowercase, not-proper-noun word &quot;mainnet&quot; is not a plain English word and it should not be in any dictionary. Do NOT use wording like this.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 04 Aug 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2228</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2228</guid>
      </item>
    
      <item>
        <title>Transaction Postdata</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2242-transaction-postdata/3557</comments>
        
        <description>## Simple Summary
An additional, optional transaction field is added for &quot;postdata,&quot; data that is posted on-chain but that cannot be read from the EVM.

## Abstract
A paradigm shift in how blockchains are used has been seen recently in Eth 2.0, with the rise of [_Execution Environments_](https://notes.ethereum.org/w1Pn2iMmSTqCmVUTGV4T5A?view) (EEs), and [_stateless clients_](https://ethresear.ch/t/the-stateless-client-concept/172). This shift involves blockchains serving as a secure data availability and arbitration layer, _i.e._, they provide a globally-accepted source of available data, and process fraud/validity and data availability proofs. This same paradigm can be applied on Eth 1.x, replacing EEs with [trust-minimized side chains](https://ethresear.ch/t/building-scalable-decentralized-payment-systems-request-for-feedback/5312).

## Motivation
While [EIP-2028](/EIPs/EIPS/eip-2028) provides a reduction in gas cost of calldata, and is a step in the right direction of encouraging use of history rather than state, the EVM does not actually need to see all data that is posted on-chain. Following the principle of &quot;don&apos;t pay for what you don&apos;t use,&quot; a distinct way of posting data on-chain, but without actually being usable within the EVM, is needed.

For [trust-minimized side chains with fraud proofs](https://ethresear.ch/t/minimal-viable-merged-consensus/5617), we simply need to ensure that the side chain block proposer has attested that _some_ data is available. Authentication can be performed as part of a fraud proof should that data end up invalid. Note that [trust-minimized side chains with validity proofs](https://ethresear.ch/t/on-chain-scaling-to-potentially-500-tx-sec-through-mass-tx-validation/3477) can&apos;t make use of the changes proposed in this EIP, as they required immediate authentication of the posted data. This will be [the topic of a future EIP](https://ethresear.ch/t/multi-threaded-data-availability-on-eth-1/5899).

## Specification
We propose a consensus modification, beginning at `FORK_BLKNUM`:

An additional optional field, `postdata`, is added to transactions. Serialized transactions now have the format:
```
&quot;from&quot;: bytes20,
&quot;to&quot;: bytes20,
&quot;startGas&quot;: uint256,
&quot;gasPrice&quot;: uint256,
&quot;value&quot;: uint256,
&quot;data&quot;: bytes,
&quot;nonce&quot;: uint256,
[&quot;postdata&quot;: bytes],
```
with witnesses signing over the [RLP encoding](https://github.com/ethereum/wiki/wiki/RLP) of the above. `postdata` is data that is posted on-chain, for later historical retrieval by layer-2 systems.

`postdata` is an RLP-encoded twople `(version: uint64, data: bytes)`.
1. `version` is `0`.
1. `data` is an RLP-encoded list of binary data. This EIP does not interpret the data in any way, simply considering it as a binary blob, though future EIPs may introduce different interpretation schemes for different values of `version`.

The gas cost of the posted data is `1 gas per byte`. This cost is deducted from the `startGas`; if the remaining gas is non-positive the transaction immediately reverts with an out of gas exception.

## Rationale
The changes proposed are as minimal and non-disruptive to the existing EVM and transaction format as possible while also supporting possible [future extensions](https://ethresear.ch/t/multi-threaded-data-availability-on-eth-1/5899) through a version code.

## Backwards Compatibility
The new transaction format is backwards compatible, as the new `postdata` field is optionally appended to existing transactions.

The proposed changes are not forwards-compatible, and will require a hard fork.

## Test Cases
TODO

## Implementation
TODO

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 16 Aug 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2242</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2242</guid>
      </item>
    
      <item>
        <title>Wallet Permissions System</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/web3-login-permissions/3583</comments>
        
        <description>## Abstract

This EIP adds two new wallet-namespaced RPC endpoints, `wallet_getPermissions` and `wallet_requestPermissions`, providing a standard interface for requesting and checking permissions.

## Motivation

Wallets are responsible for mediating interactions between untrusted applications and users&apos; keys through appropriate user consent. Today, wallets always prompt the user for every action. This provides security at the cost of substantial user friction. We believe that a single permissions request can achieve the same level of security with vastly improved UX.

The pattern of permissions requests (typically using Oauth2) is common around the web, making it a very familiar pattern:

![Facebook Permissions](/EIPs/assets/eip-2255/facebook_permissions.png)

![Log in With Apple](/EIPs/assets/eip-2255/log_in_with_apple.jpeg)

Many web3 applications today begin their sessions with a series of repetitive requests:

- Reveal your wallet address to this site.
- Switch to a preferred network.
- Sign a cryptographic challenge.
- Grant a token allowance to our contract.
- Send a transaction to our contract.

Many of these (and possibly all), and many more (like decryption), could be generalized into a set of human-readable permissions prompts on the original sign-in screen, and additional permissions could be requested only as needed:

![Sample prompt screenshot](/EIPs/assets/eip-2255/permissions.png)

Each of these permissions could be individually rejected, or even _attenuated_--adjusted to meet the user&apos;s terms (for example, a sign-in request could have a user-added expiration date, and a token allowance could be adjusted by the user when it is requested).

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

This proposal adds two new methods to a wallet&apos;s web3 provider API: `wallet_getPermissions` and `wallet_requestPermissions`.

### `wallet_getPermissions`

The `wallet_getPermissions` method is used for getting an array of current permissions (empty by default). It takes no parameters and returns an array of `Permission` objects.

#### `wallet_getPermissions` Returns

The format of the returned permissions MUST be an array of `Permission` objects, which are defined as follows:

```typescript
interface Caveat {
  type: string;
  value: any;
}

interface Permission {
  invoker: string;
  parentCapability: string;
  caveats: Caveat[];
}
```

The `invoker` is a URI used to identify the source of the current dapp (e.g. `https://your-site.com/`). The term `parentCapability` refers to the method that is being permitted (e.g. `eth_accounts`). The `caveats` array represents the specific restrictions applied to the permitted method. The `type` of a `Caveat` is a string, and the `value` is an arbitrary JSON value. The `value` of a `Caveat` is only meaningful in the context of the `type` of the `Caveat`.

### `wallet_requestPermissions`

The `wallet_requestPermissions` method is used for an application to request additional permissions. It MUST take a single parameter, a `PermissionRequest` object, and MUST return an array of `RequestedPermission` objects.

#### `wallet_requestPermissions` Parameters

The `wallet_requestPermissions` method takes a single parameter, a `PermissionRequest` object, which is defined as follows:

```typescript
interface PermissionRequest {
  [methodName: string]: {
    [caveatName: string]: any;
  };
}
```

The `methodName` is the name of the method for which the permission is being requested (e.g. `eth_accounts`). The `caveatName` is the name of the caveat being applied to the permission (e.g. `requiredMethods`). The caveat value is the value of the caveat (e.g. `[&quot;signTypedData_v3&quot;]`).

Attempted requests to a restricted method must fail with an error, until a `wallet_requestPermissions` request is made and accepted by the user.

If a `wallet_requestPermissions` request is rejected, it should throw an error with a `code` value equal to `4001` as per [EIP-1193](/EIPs/EIPS/eip-1193).

#### `wallet_requestPermissions` Returns

The `wallet_requestPermissions` method returns an array of `RequestedPermission` objects, which are defined as follows:

```typescript
interface RequestedPermission {
  parentCapability: string;
  date?: number;
}
```

The `parentCapability` is the name of the method for which the permission is being requested (e.g. `eth_accounts`). The `date` is the timestamp of the request, in Unix time, and is optional.

## Rationale

While the current model of getting user consent on a per-action basis has high security, there are huge usability gains to be had bo getting more general user consent which can cover broad categories of usage, which can be expressed in a more human-readable way. This pattern has a variety of benefits to offer different functions within a web3 wallet.

The `requestPermissions` method can be expanded to include other options related to the requested permissions, for example, sites could request accounts with specific abilities. For example, a website like an exchange that requires `signTypedData_v3` (which is not supported by some hardware wallets), might want to specify that requirement. This would allow wallets to display only compatible accounts, while preserving the user&apos;s privacy and choice regarding how they are storing their keys.

## Test Cases

### Requesting permissions

The following example should prompt the user to approve the `eth_accounts` permission, and return the permission object if approved.

```javascript
provider.request({
  method: &apos;requestPermissions&apos;,
  params: [
    {
      &apos;eth_accounts&apos;: {
        requiredMethods: [&apos;signTypedData_v3&apos;]
      }
    }
  ]
});
```

### Getting permissions

The following example should return the current permissions object.

```javascript
provider.request({
  method: &apos;getPermissions&apos;
});
```

## Security Considerations

### Server-Side Request Forgery (SSRF)

This consideration is applicable if the favicon of a website is to be displayed.

Wallets should be careful about making arbitrary requests to URLs. As such, it is recommended for wallets to sanitize the URI by whitelisting specific schemes and ports. A vulnerable wallet could be tricked into, for example, modifying data on a locally-hosted redis database.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 22 Aug 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2255</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2255</guid>
      </item>
    
      <item>
        <title>wallet_getOwnedAssets JSON-RPC Method</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2256-add-wallet-getownedassets-json-rpc-method/3600</comments>
        
        <description>## Simple Summary

This is a proposal for a new JSON-RPC call for retrieving from a wallet a selection of owned assets by an Ethereum address, with the user&apos;s permission.

## Abstract

There is no standardized way for a dApp to request a list of owned assets from a user. Now, each dApp needs to keep a list of all the popular or existing assets and check the user&apos;s balance against the blockchain, for each of these assets. This leads to duplicated effort across dApps. It also leads to the user being presented with asset options that the user does not care about, from various, unwanted airdrops.

## Motivation

There are financial dApps that require a list of owned assets from a user, for various purposes - calculating taxes, selecting customized payment options, etc. Each of these dApps are now forced to keep a list of popular assets (smart contract addresses, ABIs) and retrieve the user&apos;s data from the blockchain, for each asset. This leads to effort duplication and nonoptimal UX where the user is presented with either more or less asset options than the user would like - various airdrops, incomplete list of assets kept by the dApp.

This list of owned assets can be retrieved from the wallet used by the user. The wallet can allow the user to manage only the assets that the user is interested in. Therefore, a new JSON-RPC method is proposed: `wallet_getOwnedAssets`. This method is complementary to [EIP-747](/EIPs/EIPS/eip-747), which proposes a way for sites to suggest users new assets to watch on their wallet.

## Specification

New JSON-RPC method to be added to web3 browsers: `wallet_getOwnedAssets`. This method is for dApp-wallet communication and only targets the assets that have already been whitelisted by the wallet, for the user account.

**Arguments:**
- type `address`, Ethereum address that owns the assets
- options object, optional:
  - `chainId` - type `uint`, chain id respecting [EIP-155](/EIPs/EIPS/eip-155); optional
  - `limit` - type `uint`, the maximum number of owned assets expected by the dApp to be returned; optional
  - `types` - type `string[]`, array of asset interface identifiers such as `[&apos;ERC20&apos;, &apos;ERC721&apos;]`; optional
  - `justification` - type `string`, human-readable text provided by the dApp, explaining the intended purpose of this request; optional but recommended

**Result:**
- array with asset records:
  - `address` - type `address`, Ethereum checksummed address
  - `chainId` - type `uint`, identifier for the chain on which the assets are deployed
  - `type` - type `string`, asset interface ERC identifier; e.g. `ERC20`; optional - [EIP-1820](/EIPs/EIPS/eip-1820) could be used
  - `options` - an object with asset-specific fields; `ERC20` tokens example:
    - `name` - type `string`, token name; optional if the token does not implement it
    - `symbol` - type `string`, token symbol; optional if the token does not implement it
    - `icon`- type `base64`, token icon; optional
    - `balance` - type `uint`, the number of tokens that the user owns, in the smallest token denomination
    - `decimals` - type `uint`, the number of decimals implemented by the token; optional

### Examples

**1) A request to return all of the user&apos;s owned assets:**
```json
{
  &quot;id&quot;:1,
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;method&quot;: &quot;wallet_getOwnedAssets&quot;,
  &quot;params&quot;: [
    &quot;0x3333333333333333333333333333333333333333&quot;,
    {
      &quot;justification&quot;: &quot;The dApp needs to know about all your assets in order to calculate your taxes properly.&quot;
    }
  ]
}
```
Result:

```json
{
  &quot;id&quot;:1,
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;result&quot;: [
    {
      &quot;address&quot;: &quot;0x0000000000000000000000000000000000000001&quot;,
      &quot;chainId&quot;: 1,
      &quot;type&quot;: &quot;ERC20&quot;,
      &quot;options&quot;: {
        &quot;name&quot;: &quot;TokenA&quot;,
        &quot;symbol&quot;: &quot;TKA&quot;,
        &quot;icon&quot;: &quot;data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==&quot;,
        &quot;balance&quot;: 1000000000000,
        &quot;decimals&quot;: 18
      }
    },
    {
      &quot;address&quot;: &quot;0x0000000000000000000000000000000000000002&quot;,
      &quot;chainId&quot;: 3,
      &quot;type&quot;: &quot;ERC20&quot;,
      &quot;options&quot;: {
        &quot;name&quot;: &quot;TokenB&quot;,
        &quot;symbol&quot;: &quot;TKB&quot;,
        &quot;icon&quot;: &quot;data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==&quot;,
        &quot;balance&quot;: 2000000000000,
        &quot;decimals&quot;: 18
      }
    },
    {
      &quot;address&quot;: &quot;0x0000000000000000000000000000000000000003&quot;,
      &quot;chainId&quot;: 42,
      &quot;type&quot;: &quot;ERC721&quot;,
      &quot;options&quot;: {
        &quot;name&quot;: &quot;TokenC&quot;,
        &quot;symbol&quot;: &quot;TKC&quot;,
        &quot;icon&quot;: &quot;data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==&quot;,
        &quot;balance&quot;: 10
      }
    },
  ]
}
```

**2) A request to return one `ERC20` owned asset, deployed on `chainId` 1:**
```json
{
  &quot;id&quot;:1,
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;method&quot;: &quot;wallet_getOwnedAssets&quot;,
  &quot;params&quot;: [
    &quot;0x3333333333333333333333333333333333333333&quot;,
    {
      &quot;chainId&quot;: 1,
      &quot;limit&quot;: 1,
      &quot;types&quot;: [&quot;ERC20&quot;],
      &quot;justification&quot;: &quot;Select your token of choice, in order to pay for our services.&quot;
    }
  ]
}
```
Result:

```json
{
  &quot;id&quot;:1,
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;result&quot;: [
    {
      &quot;address&quot;: &quot;0x0000000000000000000000000000000000000001&quot;,
      &quot;chainId&quot;: 1,
      &quot;type&quot;: &quot;ERC20&quot;,
      &quot;options&quot;: {
        &quot;name&quot;: &quot;TokenA&quot;,
        &quot;symbol&quot;: &quot;TKA&quot;,
        &quot;icon&quot;: &quot;data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==&quot;,
        &quot;balance&quot;: 1000000000000,
        &quot;decimals&quot;: 18
      }
    }
  ]
}
```

### UI Best Practices

The wallet should display a UI to the user, showing the request.
The user can:
- accept the request, in which case the dApp receives all the requested assets
- reject the request
- amend the request by lowering the number of owned assets returned to the dApp


If all owned assets are requested, the total number of owned assets will be shown to the user. The user can also choose to select the assets that will be returned to the dApp, amending the request.

If a selection is requested, the user will select from the list of owned assets.

As an optimization, wallets can keep a list of frequently used assets by the user, and show that list first, with the option of expanding that list with owned assets that the user uses less frequently.

## Rationale

In order to avoid duplication of effort for dApps that require keeping a list of all or popular assets and to provide optimal UX, the `wallet_getOwnedAssets` JSON-RPC method is proposed.

The `chainId` and `types` optional parameters enable dApps to provide options in order to restrict the selection list that the user will be presented with by the wallet, in accordance with the dApp&apos;s functionality. The `limit` parameter enables the dApp to tell the user an upper limit of accounts that the user can select. It remains to be seen if a lower bound should also be provided. At the moment, this lower bound can be considered as being `1`.

The `options` response field provides the dApp with asset-specific options, enabling better UX through using the same visual and text identifiers that the wallet uses, making it easier for the user to understand the dApp&apos;s UI.

The `address`, `type` response fields provide enough information about the asset, enabling dApps to provide additional asset-specific functionality.

The `balance` response field is an optimization, allowing dApps to show the user&apos;s balance without querying the blockchain. Usually, this information is already public.


## Backwards Compatibility

Not relevant, as this is a new method.


## Test Cases

To be done.


## Implementation

To be done.


## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 29 Aug 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2256</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2256</guid>
      </item>
    
      <item>
        <title>Atomic Swap-based American Call Option Contract Standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2266</comments>
        
        <description>## Simple Summary

A standard for token contracts providing Atomic Swap-based American Call Option functionalities.

## Abstract

This standard provides functionality to make Atomic Swap-based American Call Option payment. The Atomic Swap protocol based on Hashed Time-Locked Contract (HTLC) [^1] has optionality [^2], 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.


## Motivation

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[^2] 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[^3] 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&apos;s money maliciously. This EIP aims at providing the standard of implementing this protocol in existing token standards.

## Specification

The Atomic Swap-based American Call Option smart contract should follow the syntax and semantics of Ethereum smart contracts.

### Definitions

+ `initiator`: the party who publishes the advertisement of the swap.
+ `participant`: the party who agrees on the advertisement and participates in the swap with `initiator`.
+ `asset`: the amount of token(s) to be exchanged.
+ `premium`: the amount of token(s) that `initiator` pays to `participant` as the premium.
+ `redeem`: the action to claim the token from the other party.
+ `refund`: the action to claim the token from the party herself/himself, because of timelock expiration.
+ `secrect`: a random string chosen by `initiator` as the preimage of a hash.
+ `secrectHash`: a string equals to the hash of `secrect`, used for constructing HTLCs.
+ `timelock`: a timestamp representing the timelimit, before when the asset can be redeemed, and otherwise can only be refunded.

### Storage Variables

#### swap

This mapping stores the metadata of the swap contracts, including the parties and tokens involved. Each contract uses different `secretHash`, and is distinguished by `secretHash`.

```solidity
mapping(bytes32 =&gt; Swap) public swap;
```

#### initiatorAsset

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 `secretHash`.

```solidity
mapping(bytes32 =&gt; InitiatorAsset) public initiatorAsset;
```

#### participantAsset

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 `secretHash`.

```solidity
mapping(bytes32 =&gt; ParticipantAsset) public participantAsset;
```

#### premiumAsset

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 `secretHash`.

```solidity
mapping(bytes32 =&gt; Premium) public premium;
```


### Methods

#### setup

This function sets up the swap contract, including the both parties involved, the tokens to exchanged, and so on.

```solidity
function setup(bytes32 secretHash, address payable initiator, address tokenA, address tokenB, uint256 initiatorAssetAmount, address payable participant, uint256 participantAssetAmount, uint256 premiumAmount) public payable
```

#### initiate

The initiator invokes this function to fill and lock the token she/he wants to sell and join the contract.

```solidity
function initiate(bytes32 secretHash, uint256 assetRefundTime) public payable
```

#### fillPremium

The initiator invokes this function to fill and lock the premium.

```solidity
function fillPremium(bytes32 secretHash, uint256 premiumRefundTime) public payable
```

#### participate

The participant invokes this function to fill and lock the token she/he wants to sell and join the contract.

```solidity
function participate(bytes32 secretHash, uint256 assetRefundTime) public payable
```

#### redeemAsset

One of the parties invokes this function to get the token from the other party, by providing the preimage of the hash lock `secret`.

```solidity
function redeemAsset(bytes32 secret, bytes32 secretHash) public
```

#### refundAsset

One of the parties invokes this function to get the token back after the timelock expires.

```solidity
function refundAsset(bytes32 secretHash) public
```

#### redeemPremium

The participant invokes this function to get the premium. This can be invoked only if the participant has already invoked `participate` and the participant&apos;s token is redeemed or refunded.

```solidity
function redeemPremium(bytes32 secretHash) public
```

#### refundPremium

The initiator invokes this function to get the premium back after the timelock expires.

```solidity
function refundPremium(bytes32 secretHash) public
```


### Events

#### SetUp

This event indicates that one party has set up the contract using the function `setup()`.

```solidity
event SetUp(bytes32 secretHash, address initiator, address participant, address tokenA, address tokenB, uint256 initiatorAssetAmount, uint256 participantAssetAmount, uint256 premiumAmount);
```

#### Initiated

This event indicates that `initiator` has filled and locked the token to be exchanged using the function `initiate()`.

```solidity
event Initiated(uint256 initiateTimestamp, bytes32 secretHash, address initiator, address participant, address initiatorAssetToken, uint256 initiatorAssetAmount, uint256 initiatorAssetRefundTimestamp);
```

#### Participated

This event indicates that `participant` has filled and locked the token to be exchanged using the function `participate()`.

```solidity
event Participated(uint256 participateTimestamp, bytes32 secretHash, address initiator, address participant, address participantAssetToken, uint256 participantAssetAmount, uint256 participantAssetRefundTimestamp);
```

#### PremiumFilled

This event indicates that `initiator` has filled and locked `premium` using the function `fillPremium()`.

```solidity
event PremiumFilled(uint256 fillPremiumTimestamp, bytes32 secretHash, address initiator, address participant, address premiumToken, uint256 premiumAmount, uint256 premiumRefundTimestamp);
```

#### InitiatorAssetRedeemed/ParticipantAssetRedeemed

These two events indicate that `asset` has been redeemed by the other party before the timelock by providing `secret`.

```solidity
event InitiatorAssetRedeemed(uint256 redeemTimestamp, bytes32 secretHash, bytes32 secret, address redeemer, address assetToken, uint256 amount);
```

```solidity
event ParticipantAssetRedeemed(uint256 redeemTimestamp, bytes32 secretHash, bytes32 secret, address redeemer, address assetToken, uint256 amount);
```

#### InitiatorAssetRefunded/ParticipantAssetRefunded

These two events indicate that `asset` has been refunded by the original owner after the timelock expires.

```solidity
event InitiatorAssetRefunded(uint256 refundTimestamp, bytes32 secretHash, address refunder, address assetToken, uint256 amount);
```

```solidity
event ParticipantAssetRefunded(uint256 refundTimestamp, bytes32 secretHash, address refunder, address assetToken, uint256 amount);
```

#### PremiumRedeemed

This event indicates that `premium` has been redeemed by `participant`. This implies that `asset` is either redeemed by `initiator` if it can provide the preimage of `secrectHash` before  `asset` timelock expires; or refunded by `participant` if `asset` timelock expires.

```solidity
event PremiumRedeemed(uint256 redeemTimestamp,bytes32 secretHash,address redeemer,address token,uint256 amount);
```

#### PremiumRefunded

This event indicates that `premium` has been refunded back to `initiator`, because of `participant` doesn&apos;t participate at all, by the time of `premium` timelock expires.

```solidity
event PremiumRefunded(uint256 refundTimestamp, bytes32 secretHash, address refunder, address token, uint256 amount);
```

## Rationale

+ To achieve the atomicity, HTLC is used.
+ The participant should decide whether to participate after the initiator locks the token and sets up the timelock.
+ 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.
+ Premium is redeemable for the participant only if the participant participates in the swap and redeems the initiator&apos;s token before premium&apos;s timelock expires.
+ Premium is refundable for the initiator only if the initiator initiates but the participant does not participate in the swap at all.


## Security Considerations

+ The `initiateTimestamp` should cover the whole swap process.
+ The participant should never participate before the premium has been deposited.


## Backwards Compatibility

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.


## Implementation

Please visit [here](/EIPs/assets/eip-2266/Example.sol) to find our example implementation.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

## References

[^1]: [Hash Time Locked Contracts](https://en.bitcoin.it/wiki/Hash_Time_Locked_Contracts)

[^2]: [An Argument For Single-Asset Lightning Network](https://lists.linuxfoundation.org/pipermail/lightning-dev/2019-January/001798.html)

[^3]: [On the optionality and fairness of Atomic Swaps](https://eprint.iacr.org/2019/896)
</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>Explicit bound to Chain ID size</title>
        <category>Informational/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2294-explicit-bound-to-chain-id/11090</comments>
        
        <description>## Abstract

This EIP informationally defines the &quot;Safe Range&quot; and &quot;Max Range&quot; of ChainId based on a few known restrictions such as [EIP-155](/EIPs/EIPS/eip-155) and major wallet and JSON-RPC representation of ChainId.

## Motivation

1. We want chainId to be safe across the different components of the ecosystem such as smart contract, wallet, dApp and JSON-RPC etc.
2. We want to enable Cross-Chain function call
3. We want to ensure [EIP-712](/EIPs/EIPS/eip-712) domains have a clear definition of how to pack ChainID.
4. Enable possible expansion of chains, such as increasing amount of L2s, L3s, or shards of Ethereum mainnets.
5. Enable hashed based temporary chain: There have been suggestions of using a hash-based identifier in place on Chain ID to allow the value to adapt over time to different contentious forks and other scenarios. This proposal does not describe this behavior, but ~63 bits of entropy should be enough to ensure that no collisions are likely for reasonable (e.g. non-malicious) uses of this feature for that purpose.

## Specification

We declared the following chainID range

1. (1, 2^31 - 1): &quot;Safe Range&quot;, the higher bound is decided by Javascript number 
2. (1, MAX_CHAIN_ID);  &quot;Max Range&quot;, in which `MAX_CHAIN_ID := floor(MAX_UINT64 / 2) - 36 = 9,223,372,036,854,775,771`:

## Rationale

### Beyond &quot;Max Range&quot;, the EIP-155 will overflow as discussed below

The `MAX_CHAIN_ID` is calculated to avoid overflow when performing uint64 math. For reference, a value of 0 or less is also disallowed.

Due to how the calculation for chain ID is performed, the maximum value seen during the arithmetic is `CHAIN_ID * 2 + 36`, so clients must test to ensure no overflow conditions are encountered when the highest value is used. No underflow is possible.

EIP-155 introduces the Chain ID parameter, which is an important parameter used for domain separation (replay protection) of Ethereum protocol signed messages. However, it does not specify any properties about the size that this parameter takes. Allowing it to be 256-bit wide means that the RLP encoding of a transaction must use &gt;256-bit arithmetic to calculate the v field.

and suggests a reasonable maximum enforced size in order to ensure that there are no issues when encoding this parameter. This would allow a sufficient amount of different values for this parameter, which is typically chosen by community consensus as a genesis parameter for a given chain and thus does not change often.

Without a well-chosen value of Chain ID, there could be differences in the implementation of [EIP-155](/EIPs/EIPS/eip-155) (and [EIP-1344](/EIPs/EIPS/eip-1344) by derivative) in both client codebase and external tooling that could lead to consensus-critical vulnerabilities being introduced to the network. By making this limit explicit, we avoid this scenario for Ethereum and any project which uses the Ethereum codebase.

Also, the field `chainID` has experienced increasing usage and dependencies, due more and more contracts are depending on [EIP-1344](/EIPs/EIPS/eip-1344) to expose CHAIN ID in the smart contract execution. For example when used with [EIP-712](/EIPs/EIPS/eip-712), [ERC-1271](/EIPs/EIPS/eip-1271) for on-contract signature verification, chainId has been increasingly introduced for replay attack prevention. It&apos;s security critical to ensure clients depending on the chainId computation in cryptography yields identical result for verification in
all cases.

## Backwards Compatibility

This EIP introduces a change that affects previous implementations of this feature. However, as of time of writing(2022-10-18) no known chain makes use of a value outside of the suggested bounds, there should not be an issue in adopting this limit on the size of this parameter, therefore the impact should be non-existent.

If any other chain is operating with an incompatible `chainId`, we advised they make proper arrangement when this EIP becomes adopted.

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 19 Sep 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2294</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2294</guid>
      </item>
    
      <item>
        <title>Multichain address resolution for ENS</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://discuss.ens.domains/t/new-standard-proposal-ens-multicoin-support/1148</comments>
        
        <description>## Abstract

This EIP introduces new overloads for the `addr` field for ENS resolvers, which permit resolution of addresses for other blockchains via ENS.

## Motivation

With the increasing uptake of ENS by multi-coin wallets, wallet authors have requested the ability to resolve addresses for non-Ethereum chains inside ENS. This specification standardises a way to enter and retrieve these addresses in a cross-client fashion.

## Specification

A new accessor function for resolvers is specified:

```solidity
function addr(bytes32 node, uint coinType) external view returns(bytes memory);
```

The EIP165 interface ID for this function is 0xf1cb7e06.

When called on a resolver, this function must return the cryptocurrency address for the specified namehash and coin type. A zero-length string must be returned if the specified coin ID does not exist on the specified node.

`coinType` is the cryptocurrency coin type index from [SLIP44](https://github.com/satoshilabs/slips/blob/master/slip-0044.md).

The return value is the cryptocurency address in its native binary format. Detailed descriptions of the binary encodings for several popular chains are provided in the Address Encoding section below.

A new event for resolvers is defined:

```solidity
event AddressChanged(bytes32 indexed node, uint coinType, bytes newAddress);
```

Resolvers MUST emit this event on each change to the address for a name and coin type.

### Recommended accessor functions

The following function provides the recommended interface for changing the addresses stored for a node. Resolvers SHOULD implement this interface for setting addresses unless their needs dictate a different interface.

```solidity
function setAddr(bytes32 node, uint coinType, bytes calldata addr);
```

`setAddr` adds or replaces the address for the given node and coin type.  The parameters for this function are as per those described in `addr()` above.

This function emits an `AddressChanged` event with the new address; see also the backwards compatibility section below for resolvers that also support `addr(bytes32)`.

### Address Encoding

In general, the native binary representation of the address should be used, without any checksum commonly used in the text representation.

A table of encodings for common blockchains is provided, followed by a more detailed description of each format. In the table, &apos;encodings&apos; lists the address encodings supported by that chain, along with any relevant parameters. Details of those address encodings are described in the following sections.

| Cryptocurrency | Coin Type | Encoding |
| --- | --- | --- |
| Bitcoin | 0 | P2PKH(0x00), P2SH(0x05), SegWit(&apos;bc&apos;) |
| Litecoin | 2 | P2PKH(0x30), P2SH(0x32), P2SH(0x05), SegWit(&apos;ltc&apos;) |
| Dogecoin | 3 | P2PKH(0x1e), P2SH(0x16) |
| Monacoin | 22 | P2PKH(0x32), P2SH(0x05) |
| Ethereum | 60 | ChecksummedHex |
| Ethereum Classic | 61 | ChecksummedHex |
| Rootstock | 137 | ChecksummedHex(30) |
| Ripple | 144 | Ripple |
| Bitcoin Cash | 145 | P2PKH(0x00), P2SH(0x05), CashAddr |
| Binance | 714 | Bech32(&apos;bnb&apos;) |

#### P2PKH(version)

Pay to Public Key Hash addresses are [base58check](https://en.bitcoin.it/wiki/Base58Check_encoding) encoded. After decoding, the first byte is a version byte. For example, the Bitcoin address `1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa` base58check decodes to the 21 bytes `0062e907b15cbf27d5425399ebf6f0fb50ebb88f18`.

P2PKH addresses have a version byte, followed by a 20 byte pubkey hash. Their canonical encoding is their scriptPubkey encoding (specified [here](https://en.bitcoin.it/wiki/Transaction#Types_of_Transaction)) is `OP_DUP OP_HASH160 &lt;pubKeyHash&gt; OP_EQUALVERIFY OP_CHECKSIG`.

The above example address is thus encoded as the 25 bytes `76a91462e907b15cbf27d5425399ebf6f0fb50ebb88f1888ac`.

##### P2SH(version)

P2SH addresses are base58check encoded in the same manner as P2PKH addresses.
P2SH addresses have a version, followed by a 20 byte script hash. Their scriptPubkey encoding (specified [here](https://en.bitcoin.it/wiki/Transaction#Pay-to-Script-Hash)) is `OP_HASH160 &lt;scriptHash&gt; OP_EQUAL`. A Bitcoin address of `3Ai1JZ8pdJb2ksieUV8FsxSNVJCpoPi8W6` decodes to the 21 bytes `0562e907b15cbf27d5425399ebf6f0fb50ebb88f18` and is encoded as the 23 bytes `a91462e907b15cbf27d5425399ebf6f0fb50ebb88f1887`.

##### SegWit(hrp)

SegWit addresses are encoded with [bech32](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki). Bech32 addresses consist of a human-readable part - &apos;bc&apos; for Bitcoin mainnet - and a machine readable part. For SegWit addresses, this decodes to a &apos;witness version&apos;, between 0 and 15, and a &apos;witness program&apos;, as defined in [BIP141](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki).

The scriptPubkey encoding for a bech32 address, as defined in BIP141, is `OP_n`, where `n` is the witness version, followed by a push of the witness program. Note this warning from BIP173:

&gt; Implementations should take special care when converting the address to a scriptPubkey, where witness version n is stored as OP_n. OP_0 is encoded as 0x00, but OP_1 through OP_16 are encoded as 0x51 though 0x60 (81 to 96 in decimal). If a bech32 address is converted to an incorrect scriptPubKey the result will likely be either unspendable or insecure.

For example, the Bitcoin SegWit address `BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4` decodes to a version of `0` and a witness script of `751e76e8199196d454941c45d1b3a323f1433bd6`, and then encodes to a scriptPubkey of `0014751e76e8199196d454941c45d1b3a323f1433bd6`.

#### ChecksummedHex(chainId?)

To translate a text format checksummed hex address into binary format, simply remove the &apos;0x&apos; prefix and hex decode it. `0x314159265dD8dbb310642f98f50C066173C1259b` is hex-decoded and stored as the 20 bytes `314159265dd8dbb310642f98f50c066173c1259b`.

A checksum format is specified by [EIP-55](/EIPs/EIPS/eip-55), and extended by [RSKIP60](https://github.com/rsksmart/RSKIPs/blob/master/IPs/RSKIP60.md), which specifies a means of including the chain ID in the checksum. The checksum on a text format address must be checked. Addresses with invalid checksums that are not all uppercase or all lowercase MUST be rejected with an error. Implementations may choose whether to accept non-checksummed addresses, but the authors recommend at least providing a warning to users in this situation.

When encoding an address from binary to text, an EIP55/RSKIP60 checksum MUST be used - so the correct encoding of the above address for Ethereum is `0x314159265dD8dbb310642f98f50C066173C1259b`.

#### Ripple

Ripple addresses are encoded using a version of base58check with an alternative alphabet, described [here](https://xrpl.org/base58-encodings.html). Two types of ripple addresses are supported, &apos;r-addresses&apos;, and &apos;X-addresss&apos;. r-addresses consist of a version byte followed by a 20 byte hash, while X-addresses consist of a version byte, a 20 byte hash, and a tag, specified [here](https://github.com/xrp-community/standards-drafts/issues/6).

Both address types should be stored in ENS by performing ripple&apos;s version of base58check decoding and storing them directly (including version byte). For example, the ripple address `rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn` decodes to and is stored as `004b4e9c06f24296074f7bc48f92a97916c6dc5ea9`, while the address `X7qvLs7gSnNoKvZzNWUT2e8st17QPY64PPe7zriLNuJszeg` decodes to and is stored as `05444b4e9c06f24296074f7bc48f92a97916c6dc5ea9000000000000000000`.

#### CashAddr

Bitcoin Cash defines a new address format called &apos;CashAddr&apos;, specified [here](https://github.com/bitcoincashorg/bitcoincash.org/blob/master/spec/cashaddr.md). This uses a variant of bech32 encoding to encode and decode (non-segwit) Bitcoin Cash addresses, using a prefix of &apos;bitcoincash:&apos;. A CashAddr should be decoded using this bech32 variant, then converted and stored based on its type (P2PKH or P2SH) as described in the relevant sections above.

#### Bech32

[Bech32](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki) addresses consist of a human-readable part - for example, &apos;bnb&apos; for Binance - and a machine readable part. The encoded data is simply the address, which can be converted to binary and stored directly.

For example, the BNB address `bnb1grpf0955h0ykzq3ar5nmum7y6gdfl6lxfn46h2` decodes to the binary representation `40c2979694bbc961023d1d27be6fc4d21a9febe6`, which is stored directly in ENS.

### Example

An example implementation of a resolver that supports this EIP is provided here:

```solidity
pragma solidity ^0.5.8;

contract AddrResolver is ResolverBase {
    bytes4 constant private ADDR_INTERFACE_ID = 0x3b3b57de;
    bytes4 constant private ADDRESS_INTERFACE_ID = 0xf1cb7e06;
    uint constant private COIN_TYPE_ETH = 60;

    event AddrChanged(bytes32 indexed node, address a);
    event AddressChanged(bytes32 indexed node, uint coinType, bytes newAddress);

    mapping(bytes32=&gt;mapping(uint=&gt;bytes)) _addresses;

    /**
     * Sets the address associated with an ENS node.
     * May only be called by the owner of that node in the ENS registry.
     * @param node The node to update.
     * @param a The address to set.
     */
    function setAddr(bytes32 node, address a) external authorised(node) {
        setAddr(node, COIN_TYPE_ETH, addressToBytes(a));
    }

    /**
     * Returns the address associated with an ENS node.
     * @param node The ENS node to query.
     * @return The associated address.
     */
    function addr(bytes32 node) public view returns (address) {
        bytes memory a = addr(node, COIN_TYPE_ETH);
        if(a.length == 0) {
            return address(0);
        }
        return bytesToAddress(a);
    }

    function setAddr(bytes32 node, uint coinType, bytes memory a) public authorised(node) {
        emit AddressChanged(node, coinType, a);
        if(coinType == COIN_TYPE_ETH) {
            emit AddrChanged(node, bytesToAddress(a));
        }
        _addresses[node][coinType] = a;
    }

    function addr(bytes32 node, uint coinType) public view returns(bytes memory) {
        return _addresses[node][coinType];
    }

    function supportsInterface(bytes4 interfaceID) public pure returns(bool) {
        return interfaceID == ADDR_INTERFACE_ID || interfaceID == ADDRESS_INTERFACE_ID || super.supportsInterface(interfaceID);
    }
}
```

### Implementation

An implementation of this interface is provided in the [ensdomains/resolvers](https://github.com/ensdomains/resolvers/) repository.

## Backwards Compatibility

If the resolver supports the `addr(bytes32)` interface defined in EIP137, the resolver MUST treat this as a special case of this new specification in the following ways:

 1. The value returned by `addr(node)` from EIP137 should always match the value returned by `addr(node, 60)` (60 is the coin type ID for Ethereum).
 2. Anything that causes the `AddrChanged` event from EIP137 to be emitted must also emit an `AddressChanged` event from this EIP, with the `coinType` specified as 60, and vice-versa.

## Tests

The table below specifies test vectors for valid address encodings for each cryptocurrency described above.

| Cryptocurrency | Coin Type | Text | Onchain (hex) |
| --- | --- | --- | --- |
| Bitcoin | 0 | `1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa` | `76a91462e907b15cbf27d5425399ebf6f0fb50ebb88f1888ac` |
| |  | `3Ai1JZ8pdJb2ksieUV8FsxSNVJCpoPi8W6` | `a91462e907b15cbf27d5425399ebf6f0fb50ebb88f1887` |
| | | `BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4` | `0014751e76e8199196d454941c45d1b3a323f1433bd6` |
| Litecoin | 2 | `LaMT348PWRnrqeeWArpwQPbuanpXDZGEUz` | `76a914a5f4d12ce3685781b227c1f39548ddef429e978388ac` |
| | | `MQMcJhpWHYVeQArcZR3sBgyPZxxRtnH441` | `a914b48297bff5dadecc5f36145cec6a5f20d57c8f9b87` |
| | | `ltc1qdp7p2rpx4a2f80h7a4crvppczgg4egmv5c78w8` | `0014687c150c26af5493befeed7036043812115ca36c` |
| Dogecoin | 3 | `DBXu2kgc3xtvCUWFcxFE3r9hEYgmuaaCyD` | `76a9144620b70031f0e9437e374a2100934fba4911046088ac` |
| | | `AF8ekvSf6eiSBRspJjnfzK6d1EM6pnPq3G` | `a914f8f5d99a9fc21aa676e74d15e7b8134557615bda87` |
| Monacoin | 22 | `MHxgS2XMXjeJ4if2PRRbWYcdwZPWfdwaDT` | `76a9146e5bb7226a337fe8307b4192ae5c3fab9fa9edf588ac` |
| Ethereum | 60 | `0x314159265dD8dbb310642f98f50C066173C1259b` | `314159265dd8dbb310642f98f50c066173c1259b` |
| Ethereum Classic | 61 | `0x314159265dD8dbb310642f98f50C066173C1259b` | `314159265dd8dbb310642f98f50c066173c1259b` |
| Rootstock | 137 | `0x5aaEB6053f3e94c9b9a09f33669435E7ef1bEAeD` | `5aaeb6053f3e94c9b9a09f33669435e7ef1beaed` |
| Ripple | 144 | `rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn` | `004b4e9c06f24296074f7bc48f92a97916c6dc5ea9` |
| | | `X7qvLs7gSnNoKvZzNWUT2e8st17QPY64PPe7zriLNuJszeg` | `05444b4e9c06f24296074f7bc48f92a97916c6dc5ea9000000000000000000` |
| Bitcoin Cash | 145 | `1BpEi6DfDAUFd7GtittLSdBeYJvcoaVggu` | `76a91476a04053bda0a88bda5177b86a15c3b29f55987388ac` |
| | | `bitcoincash:qpm2qsznhks23z7629mms6s4cwef74vcwvy22gdx6a` | `76a91476a04053bda0a88bda5177b86a15c3b29f55987388ac` |
| | | `3CWFddi6m4ndiGyKqzYvsFYagqDLPVMTzC` | `a91476a04053bda0a88bda5177b86a15c3b29f55987387` |
| | | `bitcoincash:ppm2qsznhks23z7629mms6s4cwef74vcwvn0h829pq` | `a91476a04053bda0a88bda5177b86a15c3b29f55987387` |
| Binance | 714 | `bnb1grpf0955h0ykzq3ar5nmum7y6gdfl6lxfn46h2` | `40c2979694bbc961023d1d27be6fc4d21a9febe6` |

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 09 Sep 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2304</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2304</guid>
      </item>
    
      <item>
        <title>ERC-721 Consecutive Transfer Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2309</comments>
        
        <description>## Simple Summary

A standardized event emitted when creating/transferring one, or many non-fungible tokens using consecutive token identifiers.

## Abstract

The optional ERC-721 Consecutive Transfer Extension provides a standardized event which could be emitted during the creation/transfer of one, or many non-fungible tokens. This standard does not set the expectation of how you might create/transfer many tokens it is only concerned with the event emitted after the creation, or transfer of ownership of these tokens. This extension assumes that token identifiers are in consecutive order.

## Motivation

This extension provides even more scalibility of the [ERC-721 specification](/EIPs/EIPS/eip-721). It is possible to create, transfer, and burn 2^256 non-fungible tokens in one transaction. However, it is not possible to emit that many `Transfer` events in one transaction. The `Transfer` event is part of the original specification which states:

&gt; This emits when ownership of any NFT changes by any mechanism.
&gt; This event emits when NFTs are created (`from` == 0) and destroyed
&gt; (`to` == 0). Exception: during contract creation, any number of NFTs
&gt; may be created and assigned without emitting Transfer. At the time of
&gt; any transfer, the approved address for that NFT (if any) is reset to none.

This allows for the original `Transfer` event to be emitted for one token at a time, which in turn gives us O(n) time complexity. Minting one billion NFTs can be done in one transaction using efficient data structures, but in order to emit the `Transfer` event - according to the original spec - one would need a loop with one billion iterations which is bound to run out of gas, or exceed transaction timeout limits. This cannot be accomplished with the current spec. This extension solves that problem.

Many decentralized marketplaces and block explorers utilize the `Transfer` event as a way to determine which NFTs an address owns. The Consecutive Transfer Extension provides a standard mechanism for these platforms to use to determine ownership of many tokens.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL
NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and
&quot;OPTIONAL&quot; in this document are to be interpreted as described in
RFC 2119.

**ERC-721 compliant contracts MAY implement this Consecutive Transfer Extension to provide a standard event to be emitted at the time of creation, burn, or transfer of one or many consecutive tokens**

The address executing the transaction **MUST** own all the tokens within the range of `fromTokenId` and `toTokenId`, or **MUST** be an approved operator to act on the owners behalf.

The `fromTokenId` and `toTokenId` **MUST** be a consecutive range of tokens IDs.

The `fromTokenId`, `fromAddress`, and `toAddress` **MUST** be indexed parameters

The `toTokenId` **MUST NOT** be an indexed parameter

When minting/creating tokens, the `fromAddress` argument **MUST** be set to `0x0` (i.e. zero address).

When burning/destroying tokens, the `toAddress` argument **MUST** be set to `0x0` (i.e. zero address).

When emitting the ConsecutiveTransfer event the Transfer event **MUST NOT** be emitted

Contracts that implement the `ConsecutiveTransfer` event **MAY** still use the original `Transfer` event, however when emitting the `ConsecutiveTransfer` event the `Transfer` event **MUST NOT** be emitted. 

```solidity
  event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed fromAddress, address indexed toAddress);
```

### Examples

The `ConsecutiveTransfer` event can be used for a single token as well as many tokens:

**Single token creation**

`emit ConsecutiveTransfer(1, 1, address(0), toAddress);`

**Batch token creation**

`emit ConsecutiveTransfer(1, 100000, address(0), toAddress);`

**Batch token transfer**

`emit ConsecutiveTransfer(1, 100000, fromAddress, toAddress);`

**Burn**

`emit ConsecutiveTransfer(1, 100000, from, address(0));`


## Rationale

Standardizing the `ConsecutiveTransfer` event gives decentralized platforms a standard way of determining ownership of large quantities of non-fungible tokens without the need to support a new token standard. There are many ways in which the batch creation and transfer of NFTs can be implemented. The Consecutive Transfer Extension allows contract creators to implement batch creation, transfer, and burn methods however they see fit, but provides a standardized event in which all implementations can use. By specifying a range of consecutive token identifiers we can easily cover the transfer, or creation of 2^(256) tokens and decentralized platforms can react accordingly.

Take this example. I sell magical fruit and have a farm with 10,000 magical fruit trees each with different fruit and 1,000 new trees every few years. I want to turn each tree into a non-fungible token that people can own. Each person that owns one of my non-fungible tree tokens will receive a quarterly percentage of each harvest from that tree. The problem is that I would need to create and transfer each of these tokens individually - which will cost me a lot of time and money and frankly would keep me from doing this.

With this extension I would be able to mint my initial 10,000  tree tokens in one transaction. I would be able to quickly and cheaply mint my additional 1,000  tree tokens when a new batch is planted. I would then be able to transfer all of the 10,000+ tree tokens to a special smart contract that keeps track of the selling and distribution of funds in one transaction all while adhering to a specified standard.

**Rationale to have a single event that covers minting, burning, and transferring**

The `ConsecutiveTransfer` event can be used to cover minting, burning, and transferring events. While there may have been confusion in the beginning adhering to transfer to/from &quot;0&quot; pattern this is mitigated by checking for the `ConsecutiveTransfer` topic and verifying the emitting contract supports the ERC-721 interface by using the ERC-165 standard. 

**Indexed event parameters**

Events in Solidity can have up to three indexed parameters which will make it possible to filter for specific values of indexed arguments. This standard sets the `fromAddress`, `toAddress`, and `fromTokenId` as the indexed parameters. The `toTokenId` can be retrieved from the data part of the log. The reason for this is that more often than not one may be searching for events to learn about the history of ownership for a given address. The `fromTokenId` can then be retrieved along with the other two indexed parameters for simplicity. Then one only needs to decode the log data which is ensured to be the `toTokenId`.

**Rationale to not emit `Transfer` when `ConsecutiveTransfer` is also emitted**

This can lead to bugs and unnecessary complex logic for platforms using these events to track token ownership. When transferring a single token it is acceptable to emit the original `Transfer` event, but the `ConsecutiveTransfer` event should not be emitted during the same transaction and vice-versa.

**Comparing 2309 and 1155**

As the NFT market continues to grow so does the need for the ability to scale the smart contracts. Users need to be able to do things like mint a massive amount of tokens at one time, transfer a massive amount of tokens, and be able to track ownership of all these assets. We need to do this in a way that is cost effective and doesn’t fail under the confines of the Ethereum blockchain. As millions of tokens are minted we need contracts with the ability to scale.

[ERC-1155](/EIPs/EIPS/eip-1155) was created and added as a standard in 2019 to try to solve these problems, but it falls short when it comes to minting massive amounts of unique tokens in a cost-effective way. With ERC-1155 it’s either going to cost hundreds (or thousands) of dollars or it’s going to run out of gas. ERC-1155 works well when minting many semi-fungible tokens but falls short when minting many unique tokens. Using the 2309 standard you could mint millions of blank NFTs upfront and update the metadata for each one in a cost effective way.


## Backwards Compatibility

This extension was written to allow for the smallest change possible to the original ERC-721 spec while still providing a mechanism to track the creation, transfer, and deletion of a massive amount of tokens. While it is a minimal change the effects on platforms that only use the original `Transfer` event to index token ownership would be severe. They would not be properly recording token ownership information that could be known by listening for the `ConsecutiveTransfer` event. For platforms that wish to support the `ConsecutiveTransfer` event it would be best to support both the original `Transfer` event and the `ConsecutiveTransfer` event to track token ownership. 

## Security Considerations
There are no security considerations related directly to the implementation of this standard.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 08 Oct 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2309</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2309</guid>
      </item>
    
      <item>
        <title>Simple Subroutines for the EVM</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2315-simple-subroutines-for-the-evm/3941</comments>
        
        <description>## Abstract

This proposal provides a _complete_, _efficient_, _safe_ and _static_ control-flow facility.

It introduces two new opcodes to support calling and returning from subroutines:

* `RJUMPSUB relative_offset` -- relative jump to subroutine
* `RETURNSUB` -- return to `PC` after most recent `RJUMPSUB`.

It depends on the two new opcodes proposed by [EIP-4200](/EIPs/EIPS/eip-4200) to support static jumps:

* `RJUMP relative_offset` — relative jump to `PC + relative_offset`
* `RJUMPI relative_offset` — conditional relative jump

It deprecates `JUMP` and `JUMPI`, allowing valid code to support streaming, one-pass, and other near-linear compilers.

In concert with [EIP-3540](/EIPs/EIPS/eip-3540) and [EIP-3670](/EIPs/EIPS/eip-3670) it ensures, at initialization time, that valid code will not execute invalid instructions or jump to invalid locations, will not underflow stack, will maintain consistent numbers of inputs and outputs for subroutines, and will have bounded stack height in the absence of recursion.

This is among the simplest possible proposals that meets these requirements.

## Motivation

### A complete control-flow facility.

Jumps, conditional jumps and subroutines were proposed by Alan Turing in 1945 as a means of organizing the logic of the code and the design of the memory crystals for his Automatic Computing Engine:
&gt; We wish to be able to arrange that sequences of orders can divide at various points, continuing in different ways according to the outcome of the calculations to date...  We also wish to be able to arrange for the splitting up of operations into subsidiary operations... To start on a subsidiary operation we need only make a note of where we left off the major operation and then apply the first instruction of the subsidiary.  When the subsidiary is over we look up the note and continue with the major operation.
&gt;
&gt; — Alan Turing — in B.E. Carpenter, R.W. Doran, &quot;The other Turing machine.&quot; The Computer Journal, Volume 20, Issue 3, January 1977.

In more contemporary terms, we have sequences of instructions, jumps and conditional jumps that divide sequences into blocks, subroutine calls, and a stack of addresses to return to.  The details vary, but similar facilities have proven their value across a long line of important machines over the last 75 years, including most all of the machines we have programmed or implemented -- physical machines including the Burroughs 5000, CDC 7600, IBM 360, DEC PDP-11 and VAX, Motorola 68000, Sun SPARC, and Intel x86s, as well as virtual machines for Scheme, Forth, Pascal, Java, Wasm, and others.

Unlike these machines, the Ethereum Virtual Machine _does not_ provide subroutine operations. Instead, they must be synthesized using the dynamic `JUMP` instruction, which takes its destination on the stack. Further, the EVM provides _only_ dynamic jumps, impeding the static analysis we need.

### Efficient control-flow.

Efficient to write by hand, compile from high level labguages, validate at deploy time, interpret by VMs, and compile to machine code.

Static jumps, conditional jumps, and subroutines are sufficient and efficient in space and time, as shown by historical experience and as we will show for the EVM below.

### Safe control-flow.

The EVM has unusually high requirements for safety.  Not only do many smart contracts control inordinately large amounts of valuable Ether, but once placed on the blockchain any defects are visible to attackers and cannot be repaired.  We propose to statically validate important safety constraints on code at initialization time.

### Static control-flow.

The EVM&apos;s dynamic jumps cause two major problems. First, the need to synthesize static jumps and subroutines with dynamic jumps wastes space and gas with needlessly complex code, as we will show below.

Worse, jumps that can dynamically branch to any destination in the code can cause quadratic &quot;path explosions&quot; when traversing the flow of control. For Ethereum, this is a denial-of-service vulnerability that prevents us, at initialization time, from validating the safe use of EVM code and from compiling EVM code to machine code.

We _need_ static control-flow to validate program safety and to compile EVM bytecode to machine code -- in time and space linear in the size of the code.

## Specification

### Opcodes

#### `RJUMPSUB (0x5f) relative_offset`

Transfers control to a subroutine.

1. Decode the `relative_offset` from the immediate data at `PC`.
2. Push the current `PC + 3` to the `return stack`.
3. Set `PC` to `PC + relative_offset`.

The `relative_offset` is relative to the current `PC`. The offset is encoded as a two-byte, twos-complement signed integer, stored MSB-first.

The gas cost is _low_.

#### `RETURNSUB (0x5e)`

Returns control to the caller of a subroutine.

1. Pop the `return stack` to `PC`.

The gas cost is _verylow_.

_Notes:_

* _Values popped off the `return stack` do not need to be validated, since they are alterable only by `RJUMPSUB` and `RETURNSUB`._
* _The description above lays out the semantics of these instructions in terms of a `return stack`.  But the actual state of the `return stack` is not observable by EVM code or consensus-critical to the protocol.  (For example, a node implementer may code `RJUMPSUB` to unobservably push `PC` on the `return stack` rather than `PC + 1`, which is allowed so long as `RETURNSUB` observably returns control to the `PC + 3` location.)_

### Validity

_Execution_ is defined in the Yellow Paper as a sequence of changes in the EVM state.  The conditions on valid code are preserved by state changes.  At runtime, if execution of an instruction would violate a condition the execution is in an exceptional halting state.  The Yellow Paper defines six such states.

1. Insufficient gas
2. More than 1024 stack items
3. State modification during a static call
4. Insufficient stack items
5. Invalid jump destination
6. Invalid instruction

We would like to consider EVM code valid iff no execution of the program can lead to an exceptional halting state.  In practice, we must test at runtime for the first three conditions.  We don’t know how much gas there will be, we don’t know how deep a recursion may go, analysis of stack depth even for non-recursive programs is nontrivial, and we don&apos;t know whether a call will be static.  All of the remaining conditions MUST be validated statically, in time and space quasi-linear in the size of the code.

#### Static Constraints on Valid Code

* Every instruction MUST be valid:
   * The `JUMP` and `JUMPI` instructions ARE NOT valid.
* Every jump MUST be valid:
   * The `RJUMP`, `RJUMPI`, or `RJUMPSUB` instructions MUST NOT address immediate data or addresses outside of their code section.
* The stacks MUST be valid:
   * The number of items on the `data stack` MUST always be positive.
   * The number of items on the `return stack `MUST always be positive.
* The data stack MUST be consistently aligned:
   * The data stack height is
     * the absolute difference between the current `stack pointer` and the `stack pointer` on entry to the current subroutine.
   * It MUST be the same for every reachable path through a given `PC` and
   * MUST NOT exceed 1024.

## Rationale

This is a purely semantic specification, placing no constraints on the syntax of code sections beyond being a sequence of opcodes and immediate data – a subroutine is not a contiguous sequence of bytecode, it is a subgraph of the bytecode&apos;s control-flow graph.  The EVM is a simple state machine.  We only promise that valid code will not, as it were, jam up the gears of the machine.

By avoiding syntactic constraints we allow for optimizations like tail call elimination, multiple-entry subroutines, moving &quot;cold&quot; code out of line, and other ways of reducing redundancy and keeping &quot;hot&quot; code in cache.   Since we wish to support one-pass compilation of EVM code to machine code it is crucial that the EVM code be as well optimized as possible up front.

### Validation

Rather than enforce constraints via syntax, we enforce them via validation.

The constraints on valid code cover all of the exceptional halting states that we can validate and allow code to be validated and compiled in time and space quasi-linear in the size of the code.

The `RJUMP`, `RJUMPI` and `RJUMPSUB` instructions take their *relative_offset* as immediate arguments, which cannot change at runtime.  Having constant destinations for all jumps means that all jump destinations can be validated at initialization time, not runtime.  Dynamic jumps can branch to any destination in the code, so exploitable quadratic &quot;path explosions&quot; are possible when traversing the control flow graph. Deprecating `JUMP` and `JUMPI` prevents this.

Requiring a consistently aligned `data stack`

* prevents stack underflow
* ensures that all calls to a subroutine have the same number of inputs and the same number of outputs and
* ensures that stack height is bounded in the absence of recursion.

Requiring a consistently aligned `data stack` also allows some algorithms that traverse the control-flow graph -- including code validation and compilation -- to break cycles at joins, again preventing quadratic path explosion.  When a traversal gets to a `PC` it has visited before it is either at the beginning of a loop or the entry to a function.  Since the stack height at that `PC` is constant we know that loops will not grow stack, and that the number of arguments to a subroutine will always be the same -- there may be no need to traverse that path again.

_Note: The JVM and Wasm enforce similar constraints for similar reasons._

### Alternative Designs

There are a few major designs for a subroutine facility, two of which are considered here.  The others are mostly not appropriate for the EVM, such as the Wheeler Jump -- self-modifying code that writes return addresses into called subroutines.

*1. Keep return addresses on a dedicated return stack.* Turing&apos;s design is often used by stack machines, including those for Forth, Java, Wasm, and others.  The data stack is used for computation, with a dedicated stack for return addresses.  A single instruction suffices to call, and another to return from a routine.

*2. Keep return addresses on the data stack.*  This design is often used by register machines, including those from CDC, IBM, DEC, Intel, and ARM.  The registers are used primarily for computation, and the stack maintains call frames for return addresses, arguments, and local variables.  On the EVM there are no registers for computation, so using the stack for both purposes can cause the sort of inefficiencies we see below.  Pascal p-code does use this design, but as part of a complex calling convention with dedicated registers.

#### We prefer the dedicated return stack.

* It maintains a clear separation between calculation and flow of control:
  * the data stack is free of vulnerable return addresses and
  * it&apos;s impossible to overwrite the return stack.
* It improves efficiency:
  * it uses native arithmetic rather than 256-bit EVM instructions for the return address,
  * doesn&apos;t use up a `data stack` slot for the return address and
  * needs less motion of 256-bit data on the stack.

### Efficiency

We illustrate here how subroutine instructions can be used to reduce the complexity and gas costs of both ordinary and optimized subroutine calls compared to using `JUMP`.

#### **Simple Subroutine Call**

Consider these examples of a fairly minimal subroutine, including the code to call it.

Subroutine call, using `RJUMPSUB`:
```
SQUARE:
    dup1            ; 3 gas
    mul             ; 5 gas
    returnsub       ; 3 gas

CALL_SQUARE:
    push 0x02       ; 3 gas
    rjumpsub SQUARE ; 5 gas
```
_Total gas: 19_

Subroutine call, using `JUMP`:
```
SQUARE:
    jumpdest        ; 1 gas
    swap1           ; 3 gas
    dup1            ; 3 gas
    mul             ; 5 gas
    swap1           ; 3 gas
    jump            ; 8 gas

CALL_SQUARE:
    jumpdest        ; 1 gas
    push 0x02       ; 3 gas
    push RTN_CALL:  ; 3 gas
    push SQUARE     ; 3 gas
    jump            ; 8 gas
RTN_CALL:
    jumpdest        ; 1 gas
```
_Total: 41 gas_.

Using `RJUMPSUB` versus `JUMP` saves _41 - 19 = 22 gas_ — a _54%_ improvement.

#### **Tail Call Optimization**

Of course in cases like this one we can optimize the tail call, so that the return from `SQUARE` actually returns from `TEST_SQUARE`.

Tail call optimization, using `RJUMPSUB` and `RETURNSUB`:
```SQUARE:
    dup1            ; 3 gas
    mul             ; 5 gas
    returnsub       ; 3 gas

CALL_SQUARE:
    push 0x02       ; 3 gas
    rjump SQUARE    ; 3 gas
```
_Total: 17 gas_


Tail call optimization, using `JUMP`:
```
SQUARE:
    jumpdest        ; 1 gas
    swap1           ; 3 gas
    dup1            ; 3 gas
    mul             ; 5 gas
    swap2           ; 3 gas
    jump            ; 8 gas

CALL_SQUARE:
    jumpdest        ; 1 gas
    push 0x02       ; 3 gas
    push SQUARE     ; 3 gas
    jump            ; 8 gas
```
_Total: 38 gas_

Using `RJUMPSUB` versus `JUMP` saves _38 - 17 = 21 gas_ — a _55%_ improvement.

#### Efficiency Caveats

We can see that these instructions provide a simpler and more gas-efficient subroutine mechanism than using `JUMP` — in our examples they cut gas use by about half.

Clearly, the benefits of this efficiency are greater for programs that have been factored into smaller subroutines.  How small?  Wrapping code in a subroutine costs only _8 gas_ using `RJUMPSUB` and `RETURNSUB` versus _30 gas_ using `JUMP`, `PUSH` and `SWAP` as above.

### Costs

The _low_ cost of `RJUMPSUB` versus the _mid_ cost of `JUMP` is justified by needing only to decode the immediate two byte destination to the `PC` and push the return address on the `return stack`, all using native arithmetic, versus using the data stack with emulated 256-bit instructions.

The _verylow_ cost of `RETURNSUB` is justified by needing only to pop the `return stack` into the `PC`.  Benchmarking will be needed to tell if the costs are well-balanced.

## Backwards Compatibility

These changes affect the semantics of existing EVM code: bytes that would have been interpreted as valid jump destinations may now be interpreted as immediate data.  Since this proposal depends on the Ethereum Object Format to signal the change this is not a practical issue.

## Test Cases

### Simple routine

This should jump into a subroutine, back out and stop.

Bytecode: `0x5f0003005e` (`RJUMPSUB 3, RETURNSUB, STOP`)

|  Pc   |      Op     | Cost |   Stack   |   RStack  |
|-------|-------------|------|-----------|-----------|
|    0  |   RJUMPSUB  |    5 |        [] |        [] |
|    2  |       STOP  |    0 |        [] |        [] |
|    3  |  RETURNSUB  |    3 |        [] |        [] |

Output: 0x
Consumed gas: `10`

### Two levels of subroutines

This should execute fine, going into one two depths of subroutines

Bytecode: `0x5f00045F00025200` (`RJUMPSUB 4, RJUMPSUB 2, RETURNSUB, RETURNSUB, STOP`)

|  Pc   |      Op     | Cost |   Stack   |   RStack  |
|-------|-------------|------|-----------|-----------|
|    0  |   RJUMPSUB  |    5 |        [] |        [] |
|    3  |   RJUMPSUB  |    5 |        [] |        [] |
|    4  |  RETURNSUB  |    5 |        [] |        [] |
|    5  |  RETURNSUB  |    5 |        [] |        [] |
|    6  |       STOP  |    0 |        [] |        [] |

Consumed gas: `20`

### Failure 1: invalid jump

This should fail, since the given location is outside of the code-range.

Bytecode: `0X5fff`(`RJUMPSUB -1`)

|  Pc   |      Op     | Cost |   Stack   |   RStack  |
|-------|-------------|------|-----------|-----------|
|    0  |   RJUMPSUB  |   10 |        [] |        [] |

```
Error: at pc=0, op=RJUMPSUB: invalid jump destination
```

### Failure 2: shallow `return stack`

This should fail at first opcode, due to shallow `return_stack`

Bytecode: `0x5e` (`RETURNSUB`)

|  Pc   |      Op     | Cost |   Stack   |   RStack  |
|-------|-------------|------|-----------|-----------|
|    0  |  RETURNSUB  |    5 |        [] |        [] |

```
Error: at pc=0, op=RETURNSUB: invalid retsub
```

### Subroutine at end of code

In this example the RJUMPSUB is on the last byte of code. When the subroutine returns, it should hit the &apos;virtual stop&apos; _after_ the bytecode, and not exit with error

Bytecode: `0x5c00045e5fffff` (`RJUMP 4, RETURNSUB, RJUMPSUB -1`)

|  Pc   |      Op     | Cost |   Stack   |   RStack  |
|-------|-------------|------|-----------|-----------|
|    0  |      RJUMP  |    5 |        [] |        [] |
|    3  |  RETURNSUB  |    5 |        [] |        [] |
|    4  |   RJUMPSUB  |    5 |        [] |        [] |
|    7  |       STOP  |    0 |        [] |        [] |

Consumed gas: `15`

## Reference Implementation

The following is a pseudo-Python implementation of an algorithm for predicating code validity.  An equivalent algorithm must be run at initialization time.

This algorithm performs a symbolic execution of the program that recursively traverses the _code_, emulating its control flow and stack use and checking for violations of the rules above.

It runs in time equal to `O(vertices + edges)` in the program&apos;s control-flow graph, where edges represent control flow and the vertices represent _basic blocks_ — thus the algorithm takes time proportional to the size of the _code_. It maintains a stack of continuations for conditional jumps, the size of which is at most proportional to the size of the _code_.

### Validation Function

** Note: this function is known to be incomplete and incorrect. **

For simplicity&apos;s sake we assume that all jumpdest analysis and prior validation has been done, including EIP-3540, EIP-3670, and EIP-4200, so EOF headers and sections are well-formed, and there are no invalid instructions or jumps.  In practice, all passes of validation can be folded into a single loop no recursion.

We also assume some helper functions.
* `is_valid(opcode)` returns true iff opcode is valid.
* `is_terminator(opcode)` returns true iff opcode is terminator.
* `is_valid_jumpdest(pc)` returns true iff `pc` is a valid jump destination.
* `immediate_data(pc)` returns the immediate data for the instruction at `pc`.
* `immediate_size(opcode)` returns the size of the immediate data for an opcode.
* `removed_items(opcode)` returns the number of items removed from the `data_stack` by the `opcode`.
* `added_items(opcode)` returns the number of items added to the `data_stack` by the `opcode`.

```
# returns true iff code is valid
def validate_code(code: bytes, pc: int, sp: int, bp: int) -&gt; boolean:
    continuations = []
    do
        while pc &lt; len(code):
            opcode = code[pc]
            if !is_valid(opcode):
                return false
            if is_terminator(opcode):
                return true

            # check stack height and return if we have been here before
            stack_height = sp - bp
            if stack_height &gt; 1024
                return false
            if pos in stack_heights:
                if stack_height != stack_heights[pos]:
                    return false
                return true
            else:
                stack_heights[pos] = stack_height

            if opcode == RJUMP:

                # reset pc to destination of jump
                jumpdest = immediate_data(pc)
                pc += jumpdest
                if !is_valid_jumpdest(pc)
                    return false

            elif opcode == RJUMPI:

                jumpdest = pc + immediate_data(pc)
                if !is_valid_jumpdest(pc)
                    return false

                # continue true side of conditional later
                continations.push((jumpdest, sp, bp))

                # continue false side of conditional now

            elif opcode == RJUMPSUB:

                # will enter subroutine at destination
                bp = sp

                # push return address and reset pc to destination
                jumpdest = pc + immediate_data(pc)
                if !is_valid_jumpdest(pc)
                    return false
                push(return_stack, pc + 3)
                pc = jumpdest
                continue

            elif opcode == RETURNSUB:

                # will return to subroutine at destination
                bp = sp

                # pop return address and check for preceding call
                pc = pop(return_stack)
                if code[pc - 3] != RJUMPSUB:
                   return false

            # apply instructions to stack
            sp -= removed_items(opcode)
            if sp &lt; 0
                return false
            sp += added_items(opcode)

            # Skip opcode and immediate data
            pc += 1 + immediate_size(opcode)

        while (pc, sp, bp) = continuations.pop()

    return true
```

## Security Considerations

These changes introduce new flow control instructions.  They do not introduce any new security considerations. This EIP is intended to improve security by validating a higher level of safety for EVM code deployed on the blockchain.  The validation algorithm must be quasi-linear in time and space to not be a denial of service vulnerability.  The algorithm here makes one linear-time pass of the bytecode, and uses a stack of continuations that cannot exceed the number of `RJUMPI` instructions in the code.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 17 Oct 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2315</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2315</guid>
      </item>
    
      <item>
        <title>BEGINDATA opcode</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/new-opcode-begindata/3727</comments>
        
        <description>## Simple Summary
Introduces a new opcode `BEGINDATA`, which indicates that the remaining bytes of the contract should be regarded as data rather than contract code
and cannot be executed.

## Abstract
It is common for smart contracts to efficiently store data directly in the contract bytecode. Examples include constructor arguments, constant variables, compiler metadata and the contract runtime during the init phase. Currently, such data is not distinguished from normal bytecode and is still being analysed for `JUMPDEST`s by EVM interpreters. This EIP introduces a new opcode `BEGINDATA` at byte `0xb6`, which marks the remainding bytecode as data, indicating to EVM interpreters, static analysis tools and chain explorers that the remaining bytes do not represent opcodes.

## Motivation
The `BEGINDATA` opcode has been suggested before as part of the EIP `Subroutines and Static Jumps for the EVM` [EIP-615](/EIPs/EIPS/eip-615) as a way to determine the position of jumptables in contract bytecode. It is here introduced in its own right in order to exclude data from the `JUMPDEST` analysis of contracts, making it impossible to jump to data. This makes it easier for static analysis tools to analyse contracts, allows disassemblers, chain explorers and debuggers to not display data as a mess of INVALID opcodes and may even provide a marginal improvement in performance. It also helps scalability because it improves on-chain evaluation of transactions from other chains in that the validation that the code conforms to a certain pattern does not need to do a full jumpdest analysis to see that data is not executed and thus does not have to conform to the pattern (used by the optimism project). Additionally, it paves the way for suggestions such as [EIP-1712](https://github.com/ethereum/EIPs/pull/1712) to disallow unused opcodes, jumptables [EIP-615](/EIPs/EIPS/eip-615) and speculative proposals to disallow for deployment of contracts with stack usage violations.

## Specification
While computing the valid `JUMPDEST`s of a contract, halt analysis once the first `BEGINDATA` is encountered. In other words: A jump to any codelocation equal to or greater than the location of the first `BEGINDATA` causes a `BAD_JUMP_DESTINATION` error.
If `BEGINDATA` is encountered during contract execution, it has the same semantics as `STOP`. It uses 0 gas.

Bytes past `BEGINDATA` remain accessible via `CODECOPY` and `EXTCODECOPY`. `BEGINDATA` does not influence `CODESIZE` or `EXTCODESIZE`.

## Rationale
The byte `0xb6` was chosen to align with [EIP-615](/EIPs/EIPS/eip-615).
The choice to `STOP` if `BEGINDATA` is encountered is somewhat arbitrary. An alternative would be to be to abort the execution with an out-of-gas error.

## Backwards Compatibility
The proposal will not change any existing contracts unless their current behaviour relies upon the usage of unused opcodes.

Since contracts have been using data from the very start, in a sense all of them use unused opcodes,
but they would have to use data in a way that it is skipped during execution and jumped over.
The Solidity compiler never generated such code. It has to be evaluated whether contracts created by other means
could have such a code structure.

## Test Cases
Test cases should include:
1) A contract which jumps to a destination `X`, where `X` has a pc value higher than the `BEGINDATA` opcode, and the byte at `X` is `0x5b`. This should fail with a `BAD_JUMP_DESTINATION` error.
2) A contract which encounters the `BEGINDATA` opcode (should stop executing the current call frame)

## Implementation
Not yet.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 28 Oct 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2327</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2327</guid>
      </item>
    
      <item>
        <title>EXTSLOAD opcode</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2330-extsload-and-abi-for-lower-gas-cost-and-off-chain-apps/3733</comments>
        
        <description>## Abstract

This proposal adds a new opcode `EXTSLOAD` at `0x5c` which pops two items from the stack: `&lt;account address&gt; &lt;storage key&gt;` and pushes one item: `&lt;storage value&gt;`. The gas cost is sum of account access cost and storage read based on [EIP-2929](/EIPs/EIPS/eip-2929) Access Lists.

## Motivation

While any off-chain application can read all contract storage data of all contracts, this is not possible for deployed smart contracts themselves. These are bound to use contract calls for any interaction including reading data from other contracts. This EIP adds an EVM opcode to directly read external contract storage.

The gas cost when reading from registry style contract such as [EIP-20s](/EIPs/EIPS/eip-20), ENS and other data contracts is very high, because they incur cross contract call cost, cost for ABI encoding, decoding and dispatching and finally loading the data. In many cases the underlying storage that is being queried is though just a simple mapping. On top of that, the view function may SLOAD many other slots which caller may not be interested in, which further adds to the gas costs. In these cases a new `EXTSLOAD` call directly accessing the mapping in storage could not only **reduce the gas cost** of the interaction more than 10x, but also it would make the gas cost **predictable** for the reading contract.

## Specification

A new EVM instruction `EXTSLOAD (0x5c)` that works like `SLOAD (0x54)` but an additional parameter representing the contract that is to be read from.

```shell
EXTSLOAD (0x5c)
```

The `EXTSLOAD` instruction pops 2 values from the stack, first `contract` a contract address and then second `slot` a storage address within `contract`. As result `EXTSLOAD` pushes on the stack the value from the contract storage of `contract` at the storage `slot` address or `0` in case the account `contract` does not exist.

### Gas cost pre-verkle

Gas to be charged before Verkle Tree change is specified as `ACCOUNT_ACCESS_COST + STORAGE_READ_COST` where:

- `ACCOUNT_ACCESS_COST` is `0` if the account address is already in `accessed_addresses` set, otherwise `COLD_ACCOUNT_ACCESS_COST`.
- `STORAGE_READ_COST` is `WARM_STORAGE_READ_COST` if storage key is already in `accessed_storage_keys` set, otherwise `COLD_STORAGE_READ_COST`.

### Gas cost post-verkle

It is important to consider that post Verkle tree change, `ACCOUNT_ACCESS_COST` will not be needed since a single account&apos;s storage would be spread across the entire global trie. Hence gas to be charged post Verkle Tree change is just `STORAGE_READ_COST`, which is as specified in [Gas cost pre-verkle](#gas-cost-pre-verkle).

## Rationale

- Without this EIP, a contract can still opt-in to make their entire state public, by having a method that simply SLOADs and returns the values ([example](/EIPs/assets/eip-2330/Extsload.sol)). The complexity of the gas cost can be seen as `1`x CALL cost + `N`x SLOAD cost. Hence, the gas cost specified for using EXTSLOAD opcode on an account for `N` times, the charge of `1`x `COLD_ACCOUNT_ACCESS_COST` and `N`x `STORAGE_READ_COST` is hereby justified.
- Without this EIP, a contract can still use internal state of other contracts. An external party can supply a value and proof to a contract, which the contract can verify using `BLOCKHASH`. This is only possible for the previous blocks and not the latest state (since current blockhash cannot be determined before execution).
- This opcode can be seen as breaking object-oriented (OO) model because it allows to read storage of other contracts. In usual systems using OO is net positive, because there is no limit on machine code and it hardly adds any cost to add more methods or use single method to get a ton of data while the caller needs to just a small portion of data. However on EVM, there are visible costs, i.e. about $0.2 per SLOAD (20 gwei and ETHUSD 2000). Also, OO has caused misleading assumptions for developers where variables marked as &quot;private&quot; in smart contracts are encrypted in some way/impossible to read which has resulted bad designs. Hence, this EIP can be beneficial in terms of making smart contract systems more efficient as well as preventing misconceptions as well.

## Backwards Compatibility

This change is fully backwards compatible since it adds a new instruction.

## Security Considerations

- Since the opcode is similar to SLOAD, it should be easy to implement in various clients.
- This opcode allows the callee `A` to re-enter a caller contract `B` and read state of `B` and `B` cannot stop `A` from doing that. Since this does not change any state, it should not be a security issue. Contracts generally use re-entrancy guards, but that is only added to write methods. So even currently without EXTSLOAD, `A` can re-enter `B` and read their state exposed by any view methods and it has not been an issue.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 29 Oct 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2330</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2330</guid>
      </item>
    
      <item>
        <title>BLS12-381 Key Generation</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/bls-keys-related-erc-discussion-erc-2333-2334-2335/19774</comments>
        
        <description>## Abstract

This standard is a method for deriving a tree-hierarchy of BLS12-381 keys based on an entropy seed. Starting with the aforementioned seed, a tree of keys is built out using only the parent node&apos;s private key and the index of the desired child. This allows for a practically limitless number of keys to be derived for many different purposes while only requiring knowledge of a single ancestor key in the tree. This allows for keys, or families thereof, to be provisioned for different purposes by further standards.

In addition to the above, this method of deriving keys provides an emergency backup signature scheme that is resistant to quantum computers for in the event that BLS12-381 is ever deemed insecure.

## Motivation

### Deficiencies of the existing mechanism

The curve BLS12-381 used for BLS signatures within the Beacon chain (alongside many other projects) mandates a new key derivation scheme. The most commonly used scheme for key derivation within Ethereum for secp256k1 keys is [BIP32](https://github.com/bitcoin/bips/blob/43ce3a461dfb48e62ffa0cfc70f5f54d1eb5c577/bip-0032.mediawiki) (also known as HD derivation) which deems keys greater than the curve order invalid. Based on the order of the private key subgroup of BLS12-381 and the size of the entropy utilised, more than 54% of keys generated by BIP32 would be invalid. (secp256k1 keys derived by BIP32 are invalid with probability less than 1 in 2&lt;sup&gt;-127&lt;/sup&gt;.)

### Establishing a multi-chain standard early on

By establishing a standard before the first users begin to generate their keys, the hope is that a single standard is highly pervasive and therefore can be assumed to be the method by which the majority of keys are provided. This is valuable for two reasons, firstly in order for a post-quantum backup mechanism to be effective, there needs to be an enshrined mechanism whereby users can switch to a post-quantum signature scheme with pre-shared public keys (something this EIP provides at 0 extra storage cost). Secondly, this unifies the inter- and intra-chain ecosystem by having common tooling ideally allowing users to switch between key-management systems.

### A post-quantum backup

This key derivation scheme has a Lamport key pair which is generated as a intermediate step in the key generation process. This key pair can be used to provide a Lamport signature which is a useful backup in the event of BLS12-381 no longer being considered secure (in the event of quantum computing making a sudden advancement, for example). The idea is the Lamport signature will act as a bridge to a new signature scheme which is deemed to be secure.

## Specification

### Version

Due to the evolving BLS signatures CFRG draft (currently v4), the `KeyGen` function was updated, meaning that `hkdf_mod_r` no longer reflected what appeared in the BLS standard. This EIP was updated on the 17th of September 2020 to reflect this new method for deriving keys, **if you are implementing this EIP, please make sure your version is up to date.**

### Specification

Keys are defined in terms of a tree structure where a key is determined by the tree&apos;s seed and a tree path. This is very useful as one can start with a single source of entropy and build out a practically unlimited number of keys. The specification can be broken into two sub-components: generating the master key, and constructing a child key from its parent. The master key is used as the root of the tree and then the tree is built in layers on top of this root.

### The Tree Structure

The key tree is defined purely through the relationship between a child-node and its ancestors. Starting with the root of the tree, the *master key*, a child node can be derived by knowing the parent&apos;s private key and the index of the child. The tree is broken up into depths which are indicated by `/` and the master node is described as `m`. The first child of the master node is therefore described as `m / 0` and `m / 0`&apos;s siblings are `m / i` for all `0 &lt;= i &lt; 2**32`.

```text
      [m / 0] - [m / 0 / 0]
     /        \
    /           [m / 0 / 1]
[m] - [m / 1]
    \
     ...
      [m / i]
```

### Key derivation

Every key generated via the key derivation process derives a child key via a set of intermediate Lamport keys. The idea behind the Lamport keys is to provide a post-quantum backup in case BLS12-381 is no longer deemed secure. At a high level, the key derivation process works by using the parent node&apos;s privkey as an entropy source for the Lamport private keys which are then hashed together into a compressed Lamport public key, this public key is then hashed into BLS12-381&apos;s private key group.

#### `IKM_to_lamport_SK`

##### Inputs

* `IKM`, a secret octet string
* `salt`, an octet string

##### Outputs

* `lamport_SK`, an array of 255 32-octet strings

##### Definitions

* `HKDF-Extract` is as defined in [RFC5869](https://www.rfc-editor.org/rfc/rfc5869), instantiated with SHA256
* `HKDF-Expand` is as defined in [RFC5869](https://www.rfc-editor.org/rfc/rfc5869), instantiated with SHA256
* `K = 32` is the digest size (in octets) of the hash function (SHA256)
* `L = K * 255` is the HKDF output size (in octets)
* `&quot;&quot;` is the empty string
* `bytes_split` is a function takes in an octet string and splits it into `K`-byte chunks which are returned as an array

##### Procedure

``` text
0. PRK = HKDF-Extract(salt, IKM)
1. OKM = HKDF-Expand(PRK, &quot;&quot; , L)
2. lamport_SK = bytes_split(OKM, K)
3. return lamport_SK
```

#### `parent_SK_to_lamport_PK`

##### Inputs

* `parent_SK`, the BLS Secret Key of the parent node
* `index`, the index of the desired child node, an integer `0 &lt;= index &lt; 2^32`

##### Outputs

* `lamport_PK`, the compressed lamport PK, a 32 octet string

##### Definitions

* `I2OSP` is as defined in [RFC3447](https://www.rfc-editor.org/rfc/rfc3447) (Big endian decoding)
* `flip_bits` is a function that returns the bitwise negation of its input
* `&quot;&quot;` is the empty string
* `a | b` is the concatenation of `a` with `b`

##### Procedure

```text
0. salt = I2OSP(index, 4)
1. IKM = I2OSP(parent_SK, 32)
2. lamport_0 = IKM_to_lamport_SK(IKM, salt)
3. not_IKM = flip_bits(IKM)
4. lamport_1 = IKM_to_lamport_SK(not_IKM, salt)
5. lamport_PK = &quot;&quot;
6. for i  in 1, .., 255
       lamport_PK = lamport_PK | SHA256(lamport_0[i])
7. for i  in 1, .., 255
       lamport_PK = lamport_PK | SHA256(lamport_1[i])
8. compressed_lamport_PK = SHA256(lamport_PK)
9. return compressed_lamport_PK
```

**Note:** The indexing, `i`, in the above procedure iterates from 1 to 255 (inclusive). This is due to the limit to which HKDF can stretch the input bytes (255 times the length of the input bytes). The result of this is that the security of the lamport-backup signature is \*only\* 127.5 bit.

#### `HKDF_mod_r`

`hkdf_mod_r()` is used to hash 32 random bytes into the subgroup of the BLS12-381 private keys.

##### Inputs

* `IKM`, a secret octet string &gt;= 256 bits in length
* `key_info`, an optional octet string (default=`&quot;&quot;`, the empty string)

##### Outputs

* `SK`, the corresponding secret key, an integer 0 &lt;= SK &lt; r.

##### Definitions

* `HKDF-Extract` is as defined in RFC5869, instantiated with hash H.
* `HKDF-Expand` is as defined in RFC5869, instantiated with hash H.
* `L` is the integer given by `ceil((3 * ceil(log2(r))) / 16)`.(`L=48`)
* `&quot;BLS-SIG-KEYGEN-SALT-&quot;` is an ASCII string comprising 20 octets.
* `OS2IP` is as defined in [RFC3447](https://www.rfc-editor.org/rfc/rfc3447) (Big endian encoding)
* `I2OSP` is as defined in [RFC3447](https://www.rfc-editor.org/rfc/rfc3447) (Big endian decoding)
* `r` is the order of the BLS 12-381 curve defined in the draft IETF BLS signature scheme standard.`r=52435875175126190479447740508185965837690552500527637822603658699938581184513`

##### Procedure

```text
1. salt = &quot;BLS-SIG-KEYGEN-SALT-&quot;
2. SK = 0
3. while SK == 0:
4.     salt = H(salt)
5.     PRK = HKDF-Extract(salt, IKM || I2OSP(0, 1))
6.     OKM = HKDF-Expand(PRK, key_info || I2OSP(L, 2), L)
7.     SK = OS2IP(OKM) mod r
8. return SK
```

### `derive_child_SK`

The child key derivation function takes in the parent&apos;s private key and the index of the child and returns the child private key.

##### Inputs

* `parent_SK`, the secret key of the parent node, a big endian encoded integer
* `index`, the index of the desired child node, an integer `0 &lt;= index &lt; 2^32`

##### Outputs

* `child_SK`, the secret key of the child node, a big endian encoded integer

##### Procedure

```text
0. compressed_lamport_PK = parent_SK_to_lamport_PK(parent_SK, index)
1. SK = HKDF_mod_r(compressed_lamport_PK)
2. return SK
```

### `derive_master_SK`

The child key derivation function takes in the parent&apos;s private key and the index of the child and returns the child private key. The seed should ideally be derived from a mnemonic, with the intention being that the [BIP-39 mnemonic_to_seed method](https://github.com/bitcoin/bips/blob/43ce3a461dfb48e62ffa0cfc70f5f54d1eb5c577/bip-0039.mediawiki) be used.

##### Inputs

* `seed`, the source entropy for the entire tree, a octet string &gt;= 256 bits in length

##### Outputs

* `SK`, the secret key of master node within the tree, a big endian encoded integer

##### Procedure

```text
0. SK = HKDF_mod_r(seed)
1. return SK
```

## Rationale

### Lamport signatures

Lamport signatures are used as the backup mechanism because of their relative simplicity for a post-quantum signature scheme. Lamport signatures are very easy both to explain and implement as the sole cryptographic dependency is a secure hash function. This is important as it minimises the complexity of implementing this standard as well as the compute time for deriving a key. Lamport signatures have very large key sizes which make them impractical for many use cases, but this is not deemed to be an issue in this case as this scheme is only meant to be a once-off event to migrate to a new scheme.

Revealing the associated Lamport public key for a corresponding BLS key is done by verifying that the Lamport public key is the pre-image of the corresponding BLS private key (which in turn is verified against the BLS public key). This means that using a key&apos;s Lamport signature reveals the BLS private key rendering the BLS key pair unsafe. This has the upside of not requiring additional storage space for backup keys alongside BLS keys but does require that the Lamport signatures be used once and that the BLS key is no longer trusted after that point.

The Lamport signatures used within this scheme have 255 bits worth of security, not 256. This is done because HKDF-SHA256, the mechanism used to stretch a key&apos;s entropy, has a length-limit of `255 * hash_function_digest_size`. The 1-bit reduction in security is deemed preferable over increasing the complexity of the entropy stretching mechanism.

### SHA256

SHA256 is used as the hash function throughout this standard as it is the hash function chosen by the IETF BLS signature proposed standard. Using a single hash function for everything decreases the number of cryptographic primitives required to implement the entire BLS standardised key-stack while reducing the surface for flaws in the overall system.

### `hkdf_mod_r()`

The function `hkdf_mod_r()` in this standard is the same as the `KeyGen` function described in the draft IETF signature standard and therefore the private key obtained from `KeyGen` is equal to that obtained from `hkdf_mod_r` for the same seed bytes. This means that common engineering can be done when implementing this function. Additionally because of its inclusion in an IETF standard, it has had much scrutiny by many cryptographers and cryptanalysts, thereby lending credence to its safety as a key derivation mechanism.

While `hkdf_mod_r()` has modulo bias, the magnitude of this bias is minuscule (the output size of HKDF is set to 48 bytes which is greater 2&lt;sup&gt;128&lt;/sup&gt; time larger than the curve order). This bias is deemed acceptable in light of the simplicity of the constant time scheme.

### Only using hardened keys

Widely accepted standards that existed before this one ([BIP32](https://github.com/bitcoin/bips/blob/43ce3a461dfb48e62ffa0cfc70f5f54d1eb5c577/bip-0032.mediawiki) and [BIP44](https://github.com/bitcoin/bips/blob/43ce3a461dfb48e62ffa0cfc70f5f54d1eb5c577/bip-0044.mediawiki)) utilise the notion of hardened and non-hardened keys whereas this specification only offers the former. Non-hardened keys are primarily useful in a UTXO system in which having one&apos;s balance spilt amongst many accounts does not present much additionally complexity, but such keys are much less useful outside of this context. Further complicating matters is the problem of deriving non-hardened keys using a post-quantum signature scheme as non-hardened keys are made possible by the very group arithmetic quantum computers gain an advantage over.

## Backwards Compatibility

There are no major backwards compatibility issues brought upon by this EIP as it is not designed for use with secp256k1 keys. That said, this standard is not compatible with BIP32/ BIP44 style paths as paths specified by these systems make use of non-hardened keys, something that does not exist within this standard.

## Test Cases

### Test Case 0

```text
seed = 0xc55257c360c07c72029aebc1b53c05ed0362ada38ead3e3e9efa3708e53495531f09a6987599d18264c1e1c92f2cf141630c7a3c4ab7c81b2f001698e7463b04
master_SK = 6083874454709270928345386274498605044986640685124978867557563392430687146096
child_index = 0
child_SK = 20397789859736650942317412262472558107875392172444076792671091975210932703118
```

This test case can be extended to test the entire mnemonic-to-`child_SK` stack, assuming [BIP39](https://github.com/bitcoin/bips/blob/43ce3a461dfb48e62ffa0cfc70f5f54d1eb5c577/bip-0039.mediawiki) is used as the mnemonic generation mechanism. Using the following parameters, the above seed can be calculated:

```test
mnemonic = &quot;abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about&quot;
passphrase = &quot;TREZOR&quot;
```

This test case can be extended to test the entire `mnemonic-to -child_SK` stack, assuming [BIP39](https://github.com/bitcoin/bips/blob/43ce3a461dfb48e62ffa0cfc70f5f54d1eb5c577/bip-0039.mediawiki) is used as the mnemonic generation mechanism. Using the following parameters, the above seed can be calculated:

```text
mnemonic = &quot;abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about&quot;
passphrase = &quot;TREZOR&quot;
```

### Test Case 1

```text
seed = 0x3141592653589793238462643383279502884197169399375105820974944592
master_SK = 29757020647961307431480504535336562678282505419141012933316116377660817309383
child_index = 3141592653
child_SK = 25457201688850691947727629385191704516744796114925897962676248250929345014287
```

### Test Case 2

```text
seed = 0x0099FF991111002299DD7744EE3355BBDD8844115566CC55663355668888CC00
master_SK = 27580842291869792442942448775674722299803720648445448686099262467207037398656
child_index = 4294967295
child_SK = 29358610794459428860402234341874281240803786294062035874021252734817515685787
```

### Test Case 3

```text
seed = 0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3
master_SK = 19022158461524446591288038168518313374041767046816487870552872741050760015818
child_index = 42
child_SK = 31372231650479070279774297061823572166496564838472787488249775572789064611981
```

### Test Vector with Intermediate values

```text
seed = 0xc55257c360c07c72029aebc1b53c05ed0362ada38ead3e3e9efa3708e53495531f09a6987599d18264c1e1c92f2cf141630c7a3c4ab7c81b2f001698e7463b04
master_SK = 6083874454709270928345386274498605044986640685124978867557563392430687146096
child_index = 0
lamport_0 = [0xe345d0ad7be270737de05cf036f688f385d5f99c7fddb054837658bdd2ebd519,
0x65050bd4db9c77c051f67dcc801bf1cdf33d81131e608505bb3e4523868eb76c,
0xc4f8e8d251fbdaed41bdd9c135b9ed5f83a614f49c38fffad67775a16575645a,
0x638ad0feace7567255120a4165a687829ca97e0205108b8b73a204fba6a66faa,
0xb29f95f64d0fcd0f45f265f15ff7209106ab5f5ce6a566eaa5b4a6f733139936,
0xbcfbdd744c391229f340f02c4f2d092b28fe9f1201d4253b9045838dd341a6bf,
0x8b9cf3531bfcf0e4acbfd4d7b4ed614fa2be7f81e9f4eaef53bedb509d0b186f,
0xb32fcc5c4e2a95fb674fa629f3e2e7d85335f6a4eafe7f0e6bb83246a7eced5f,
0xb4fe80f7ac23065e30c3398623b2761ac443902616e67ce55649aaa685d769ce,
0xb99354f04cfe5f393193c699b8a93e5e11e6be40ec16f04c739d9b58c1f55bf3,
0x93963f58802099ededb7843219efc66a097fab997c1501f8c7491991c780f169,
0x430f3b027dbe9bd6136c0f0524a0848dad67b253a11a0e4301b44074ebf82894,
0xd635c39b4a40ad8a54d9d49fc8111bd9d11fb65c3b30d8d3eaef7d7556aac805,
0x1f7253a6474cf0b2c05b02a7e91269137acddedcb548144821f9a90b10eccbab,
0x6e3bdb270b00e7b6eb8b044dbfae07b51ea7806e0d24218c59a807a7fd099c18,
0x895488ad2169d8eaae332ce5b0fe1e60ffab70e62e1cb15a2a1487544af0a6e8,
0x32d45a99d458c90e173a3087ea3661ab62d429b285089e92806a9663ba825342,
0xc15c52106c3177f5848a173076a20d46600ca65958a1e3c7d45a593aaa9670ed,
0xd8180c550fbe4cd6d5b676ff75e0728729d8e28a3b521d56152594ac6959d563,
0x58fe153fac8f4213aaf175e458435e06304548024bcb845844212c774bdffb2a,
0x10fff610a50f4bee5c978f512efa6ab4fafacb65929606951ba5b93eeb617b5a,
0x78ac9819799b52eba329f13dd52cf0f6148a80bf04f93341814c4b47bb4aa5ec,
0xa5c3339caa433fc11e74d1765bec577a13b054381a44b23c2482e750696876a9,
0x9f716640ab5cdc2a5eb016235cddca2dc41fa4ec5acd7e58af628dade99ec376,
0x2544364320e67577c4fed8c7c7c839deed93c24076d5343c5b8faca4cc6dc2d8,
0x62553e782541f822c589796be5d5c83bfc814819100b2be0710b246f5aa7149c,
0x229fb761c46c04b22ba5479f2696be0f936fded68d54dd74bcd736b8ba512afb,
0x0af23996a65b98a0ebaf19f3ec0b3ef20177d1bfd6eb958b3bd36e0bdbe04c8c,
0x6f0954f9deab52fd4c8d2daba69f73a80dea143dd49d9705c98db3d653adf98c,
0xfa9221dd8823919a95b35196c1faeb59713735827f3e84298c25c83ac700c480,
0x70c428e3ff9e5e3cda92d6bb85018fb89475c19f526461cca7cda64ebb2ff544,
0xdcaac3413e22314f0f402f8058a719b62966b3a7429f890d947be952f2e314ba,
0xb6b383cb5ec25afa701234824491916bfe6b09d28cf88185637e2367f0cf6edc,
0x7b0d91488fc916aba3e9cb61a5a5645b9def3b02e4884603542f679f602afb8d,
0xe9c20abca284acfde70c59584b9852b85c52fa7c263bb981389ff8d638429cd7,
0x838524f798daee6507652877feb9597f5c47e9bb5f9aa52a35fb6fff796813b9,
0xbe1ca18faf9bf322474fad1b3d9b4f1bc76ae9076e38e6dd2b16e2faf487742b,
0xbf02d70f1a8519343a16d24bade7f7222912fd57fe4f739f367dfd99d0337e8e,
0xc979eb67c107ff7ab257d1c0f4871adf327a4f2a69e01c42828ea27407caf058,
0xf769123d3a3f19eb7b5c3fd4f467a042944a7c5ff8834cebe427f47dbd71460c,
0xaefc8edc23257e1168a35999fe3832bcbc25053888cc89c38667482d6748095b,
0x8ff399f364d3a2428b1c92213e4fdc5341e7998007da46a5a2f671929b42aaab,
0xcf2a3d9e6963b24c5001fbba1e5ae7f45dd6cf520fd24861f745552db86bab48,
0xb380e272d7f3091e5c887fa2e7c690c67d59f4d95f8376d150e555da8c738559,
0xc006a749b091d91204dbb64f59059d284899de5986a7f84f8877afd5e0e4c253,
0x818d8bb9b7da2dafa2ef059f91975e7b6257f5e199d217320de0a576f020de5c,
0x7aabf4a1297d2e550a2ee20acb44c1033569e51b6ec09d95b22a8d131e30fd32,
0xdd01c80964a5d682418a616fb10810647c9425d150df643c8ddbbe1bfb2768b7,
0x1e2354e1d97d1b06eb6cfe9b3e611e8d75b5c57a444523e28a8f72a767eff115,
0x989c9a649dca0580256113e49ea0dd232bbfd312f68c272fe7c878acc5da7a2c,
0x14ee1efe512826fff9c028f8c7c86708b841f9dbf47ce4598298b01134ebdc1a,
0x6f861dba4503f85762d9741fa8b652ce441373f0ef2b7ebbd5a794e48cdab51b,
0xda110c9492ffdb87efe790214b7c9f707655a5ec08e5af19fb2ab2acc428e7dc,
0x5576aa898f6448d16e40473fcb24c46c609a3fc46a404559faa2d0d34d7d49ce,
0x9bd9a35675f2857792bc45893655bfdf905ffeaee942d93ad39fbcadd4ca9e11,
0xfa95e4c37db9303d5213890fd984034089cbc9c6d754741625da0aa59cc45ccf,
0xfef7d2079713f17b47239b76c8681bf7f800b1bfeac7a53265147579572ddf29,
0x39aa7c0fecf9a1ed037c685144745fda16da36f6d2004844cf0e2d608ef6ed0e,
0x5530654d502d6ba30f2b16f49cc5818279697308778fd8d40db8e84938144fb6,
0xb1beaa36397ba1521d7bf7df16536969d8a716e63510b1b82a715940180eb29f,
0x21abe342789f7c15a137afa373f686330c0db8c861572935a3cd8dcf9e4e1d45,
0x27b5a1acda55b4e0658887bd884d3203696fcae0e94f19e31bfe931342b1c257,
0x58401a02502d7708a812c0c72725f768f5a556480517258069f2d72543cda888,
0x4b38f291548f51bee7e4cf8cc5c8aa8f4ad3ec2461dba4ccbab70f1c1bfd7feb,
0x9b39a53fdafaaf1d23378e0aa8ae65d38480de69821de2910873eefc9f508568,
0x932200566a3563ee9141913d12fd1812cb008cb735724e8610890e101ec10112,
0x6a72f70b4ec5491f04780b17c4776a335fcc5bff5073d775150e08521dc74c91,
0x86d5c60e627a4b7d5d075b0ba33e779c45f3f46d22ed51f31360afd140851b67,
0x5ca2a736bb642abc4104faa781c9aff13d692a400d91dc961aec073889836946,
0xa14bca5a262ac46ceac21388a763561fc85fb9db343148d786826930f3e510cd,
0x87be03a87a9211504aa70ec149634ee1b97f7732c96377a3c04e98643dcba915,
0x8fe283bc19a377823377e9c326374ebb3f29527c12ea77bfb809c18eef8943b0,
0x8f519078b39a3969f7e4caeca9839d4e0eccc883b89e4a86d0e1731bfc5e33fc,
0x33d7c28c3d26fdfc015a8c2131920e1392ef0aea55505637b54ea63069c7858e,
0xe57de7c189fcc9170320c7acedb38798562a48dbc9943b2a8cd3441d58431128,
0x513dac46017050f82751a07b6c890f14ec43cadf687f7d202d2369e35b1836b4,
0xfd967d9f805bb7e78f7b7caa7692fdd3d6b5109c41ad239a08ad0a38eeb0ac4c,
0xf2013e4da9abcc0f03ca505ed94ec097556dbfd659088cd24ec223e02ac43329,
0xe0dcfac50633f7417f36231df2c81fa1203d358d5f57e896e1ab4b512196556b,
0xf022848130e73fe556490754ef0ecfcdaaf3b9ff16ae1eda7d38c95c4f159ded,
0x2147163a3339591ec7831d2412fb2d0588c38da3cd074fa2a4d3e5d21f9f1d2d,
0x11ee2404731962bf3238dca0d9759e06d1a5851308b4e6321090886ec5190b69,
0xf7679ecd07143f8ac166b66790fa09aed39352c09c0b4766bbe500b1ebace5a5,
0xc7a0e95f09076472e101813a95e6ea463c35bd5ee9cfda3e5d5dbccb35888ef0,
0xde625d3b547eb71bea5325a0191a592fa92a72e4b718a499fdba32e245ddf37e,
0x7e5bdccd95df216e8c59665073249072cb3c9d0aef6b341afc0ca90456942639,
0xc27f65fd9f797ede374e06b4ddb6e8aa59c7d6f36301f18b42c48b1889552fe3,
0x8175730a52ea571677b035f8e2482239dda1cfbff6bc5cde00603963511a81af,
0x09e440f2612dad1259012983dc6a1e24a73581feb1bd69d8a356eea16ba5fd0e,
0x59dcc81d594cbe735a495e38953e8133f8b3825fd84767af9e4ea06c49dbabfa,
0x6c8480b59a1a958c434b9680edea73b1207077fb9a8a19ea5f9fbbf6f47c4124,
0x81f5c89601893b7a5a231a7d37d6ab9aa4c57f174fcfc6b40002fa808714c3a1,
0x41ba4d6b4da141fcc1ee0f4b47a209cfd143d34e74fc7016e9956cedeb2db329,
0x5e0b5b404c60e9892040feacfb4a84a09c2bc4a8a5f54f3dad5dca4acdc899dc,
0xe922eebf1f5f15000d8967d16862ed274390cde808c75137d2fb9c2c0a80e391,
0xbf49d31a59a20484f0c08990b2345dfa954509aa1f8901566ab9da052b826745,
0xb84e07da828ae668c95d6aa31d4087504c372dbf4b5f8a8e4ded1bcf279fd52b,
0x89288bf52d8c4a9561421ad199204d794038c5d19ae9fee765ee2b5470e68e7e,
0xf6f618be99b85ec9a80b728454a417c647842215e2160c6fe547dd5a69bd9302,
0xdd9adc002f98c9a47c7b704fc0ce0a5c7861a5e2795b6014749cde8bcb8a034b,
0xd119a4b2c0db41fe01119115bcc35c4b7dbfdb42ad3cf2cc3f01c83732acb561,
0x9c66bc84d416b9193bad9349d8c665a9a06b835f82dc93ae0cccc218f808aad0,
0xd4b50eefcd2b5df075f14716cf6f2d26dfc8ae02e3993d711f4a287313038fde,
0xaf72bfb346c2f336b8bc100bff4ba35d006a3dad1c5952a0adb40789447f2704,
0xc43ca166f01dc955e7b4330227635feb1b0e0076a9c5633ca5c614a620244e5b,
0x5efca76970629521cfa053fbbbda8d3679cadc018e2e891043b0f52989cc2603,
0x35c57de1c788947f187051ce032ad1e899d9887d865266ec6fcfda49a8578b2b,
0x56d4be8a65b257216eab7e756ee547db5a882b4edcd12a84ed114fbd4f5be1f1,
0x257e858f8a4c07a41e6987aabaa425747af8b56546f2a3406f60d610bcc1f269,
0x40bd9ee36d52717ab22f1f6b0ee4fb38b594f58399e0bf680574570f1b4b8c90,
0xcb6ac01c21fc288c12973427c5df6eb8f6aefe64b92a6420c6388acdf36bc096,
0xa5716441312151a5f0deb52993a293884c6c8f445054ce1e395c96adeee66c6d,
0xe15696477f90113a10e04ba8225c28ad338c3b6bdd7bdeb95c0722921115ec85,
0x8faeaa52ca2f1d791cd6843330d16c75eaf6257e4ba236e3dda2bc1a644aee00,
0xc847fe595713bf136637ce8b43f9de238762953fed16798878344da909cc76ae,
0xb5740dc579594dd110078ce430b9696e6a308078022dde2d7cfe0ef7647b904e,
0x551a06d0771fcd3c53aea15aa8bf700047138ef1aa22265bee7fb965a84c9615,
0x9a65397a5907d604030508d41477de621ce4a0d79b772e81112d634455e7a4da,
0x6462d4cc2262d7faf8856812248dc608ae3d197bf2ef410f00c3ae43f2040995,
0x6782b1bd319568e30d54b324ab9ed8fdeac6515e36b609e428a60785e15fb301,
0x8bcdcf82c7eb2a07e14db20d80d9d2efea8d40320e121923784c92bf38250a8e,
0x46ed84fa17d226d5895e44685747ab82a97246e97d6237014611aaaba65ed268,
0x147e87981673326c5a2bdb06f5e90eaaa9583857129451eed6dde0c117fb061f,
0x4141d6fe070104c29879523ba6669552f3d457c0929bb878d2751f4ff059b895,
0xd866ce4ef226d74841f950fc28cdf2235db21e0e3f07a0c8f807704464db2210,
0xa804f9118bf92558f684f90c2bda832a4f51ef771ffb2765cde3ec6f48124f32,
0xc436d4a65910124e00cded9a637178914a8fbc090400f3f031c03eac4d0295a5,
0x643fdb9243656512316528de04dcc7344ca33783580ad0c3debf8c4a6e7c8bc4,
0x7f4a345b41706b281b2de998e91ff62d908eb29fc333ee336221757753c96e23,
0x6bdc086a5b11de950cabea33b72d98db886b291c4c2f02d3e997edc36785d249,
0xfb10b5b47d374078c0a52bff7174bf1cd14d872c7d20b4a009e2afd3017a9a17,
0x1e07e605312db5380afad8f3d7bd602998102fdd39565b618ac177b13a6527e6,
0xc3161b5a7b93aabf05652088b0e5b4803a18be693f590744c42c24c7aaaeef48,
0xa47e4f25112a7d276313f153d359bc11268b397933a5d5375d30151766bc689a,
0xb24260e2eff88716b5bf5cb75ea171ac030f5641a37ea89b3ac45acb30aae519,
0x2bcacbebc0a7f34406db2c088390b92ee34ae0f2922dedc51f9227b9afb46636,
0xc78c304f6dbe882c99c5e1354ce6077824cd42ed876db6706654551c7472a564,
0x6e2ee19d3ee440c78491f4e354a84fa593202e152d623ed899e700728744ac85,
0x2a3f438c5dc012aa0997b66f661b8c10f4a0cd7aa5b6e5922b1d73020561b27f,
0xd804f755d93173408988b95e9ea0e9feae10d404a090f73d9ff84df96f081cf7,
0xe06fda941b6936b8b33f00ffa02c8b05fd78fbec953da61da2043f5644b30a50,
0x45ee279b465d53148850a16cc7f6bd33e7627aef554a9418ed012ca8f9717f80,
0x9c79348c1bcd6aa2135452491d73564413a247ea8cc38fa7dcc6c43f8a2d61d5,
0x7c91e056f89f2a77d3e3642e595bcf4973c3bca68dd2b10f51ca0d8945e4255e,
0x669f976ebe38cbd22c5b1f785e14b76809d673d2cb1458983dbda41f5adf966b,
0x8bc71e99ffcc119fd8bd604af54c0663b0325a3203a214810fa2c588089ed5a7,
0x36b3f1ffeae5d9855e0965eef33f4c5133d99685802ac5ce5e1bb288d308f889,
0x0aad33df38b3f31598e04a42ec22f20bf2e2e9472d02371eb1f8a06434621180,
0x38c5632b81f90efbc51a729dcae03626a3063aa1f0a102fd0e4326e86a08a732,
0x6ea721753348ed799c98ffa330d801e6760c882f720125250889f107915e270a,
0xe700dd57ce8a653ce4269e6b1593a673d04d3de8b79b813354ac7c59d1b99adc,
0xe9294a24b560d62649ca898088dea35a644d0796906d41673e29e4ea8cd16021,
0xf20bb60d13a498a0ec01166bf630246c2f3b7481919b92019e2cfccb331f2791,
0xf639a667209acdd66301c8e8c2385e1189b755f00348d614dc92da14e6866b38,
0x49041904ee65c412ce2cd66d35570464882f60ac4e3dea40a97dd52ffc7b37a2,
0xdb36b16d3a1010ad172fc55976d45df7c03b05eab5432a77be41c2f739b361f8,
0x71400cdd2ea78ac1bf568c25a908e989f6d7e2a3690bc869c7c14e09c255d911,
0xf0d920b2d8a00b88f78e7894873a189c580747405beef5998912fc9266220d98,
0x1a2baefbbd41aa9f1cc5b10e0a7325c9798ba87de6a1302cf668a5de17bc926a,
0x449538a20e52fd61777c45d35ff6c2bcb9d9165c7eb02244d521317f07af6691,
0x97006755b9050b24c1855a58c4f4d52f01db4633baff4b4ef3d9c44013c5c665,
0xe441363a27b26d1fff3288222fa8ed540f8ca5d949ddcc5ff8afc634eec05336,
0xed587aa8752a42657fea1e68bc9616c40c68dcbbd5cb8d781e8574043e29ef28,
0x47d896133ba81299b8949fbadef1c00313d466827d6b13598685bcbb8776c1d2,
0x7786bc2cb2d619d07585e2ea4875f15efa22110e166af87b29d22af37b6c047d,
0x956b76194075fe3daf3ca508a6fad161deb05d0026a652929e37c2317239cbc6,
0xec9577cb7b85554b2383cc4239d043d14c08d005f0549af0eca6994e203cb4e7,
0x0722d0c68d38b23b83330b972254bbf9bfcf32104cc6416c2dad67224ac52887,
0x532b19d54fb6d77d96452d3e562b79bfd65175526cd793f26054c5f6f965df39,
0x4d62e065e57cbf60f975134a360da29cabdcea7fcfc664cf2014d23c733ab3b4,
0x09be0ea6b363fd746b303e482cb4e15ef25f8ae57b7143e64cbd5c4a1d069ebe,
0x69dcddc3e05147860d8d0e90d602ac454b609a82ae7bb960ee2ecd1627d77777,
0xa5e2ae69d902971000b1855b8066a4227a5be7234ac9513b3c769af79d997df4,
0xc287d4bc953dcff359d707caf2ccba8cc8312156eca8aafa261fb72412a0ea28,
0xb27584fd151fb30ed338f9cba28cf570f7ca39ebb03eb2e23140423af940bd96,
0x7e02928194441a5047af89a6b6555fea218f1df78bcdb5f274911b48d847f5f8,
0x9ba611add61ea6ba0d6d494c0c4edd03df9e6c03cafe10738cee8b7f45ce9476,
0x62647ec3109ac3db3f3d9ea78516859f0677cdde3ba2f27f00d7fda3a447dd01,
0xfa93ff6c25bfd9e17d520addf5ed2a60f1930278ff23866216584853f1287ac1,
0x3b391c2aa79c2a42888102cd99f1d2760b74f772c207a39a8515b6d18e66888a,
0xcc9ae3c14cbfb40bf01a09bcde913a3ed208e13e4b4edf54549eba2c0c948517,
0xc2b8bce78dd4e876da04c54a7053ca8b2bedc8c639cee82ee257c754c0bea2b2,
0xdb186f42871f438dba4d43755c59b81a6788cb3b544c0e1a3e463f6c2b6f7548,
0xb7f8ba137c7783137c0729de14855e20c2ac4416c33f5cac3b235d05acbab634,
0x282987e1f47e254e86d62bf681b0803df61340fdc9a8cf625ef2274f67fc6b5a,
0x04aa195b1aa736bf8875777e0aebf88147346d347613b5ab77bef8d1b502c08c,
0x3f732c559aee2b1e1117cf1dec4216a070259e4fa573a7dcadfa6aab74aec704,
0x72699d1351a59aa73fcede3856838953ee90c6aa5ef5f1f7e21c703fc0089083,
0x6d9ce1b8587e16a02218d5d5bed8e8d7da4ac40e1a8b46eeb412df35755c372c,
0x4f9c19b411c9a74b8616db1357dc0a7eaf213cb8cd2455a39eb7ae4515e7ff34,
0x9163dafa55b2b673fa7770b419a8ede4c7122e07919381225c240d1e90d90470,
0x268ff4507b42e623e423494d3bb0bc5c0917ee24996fb6d0ebedec9ce8cd9d5c,
0xff6e6169d233171ddc834e572024586eeb5b1bda9cb81e5ad1866dbc53dc75fe,
0xb379a9c8279205e8753b6a5c865fbbf70eb998f9005cd7cbde1511f81aed5256,
0x3a6b145e35a592e037c0992c9d259ef3212e17dca81045e446db2f3686380558,
0x60fb781d7b3137481c601871c1c3631992f4e01d415841b7f5414743dcb4cfd7,
0x90541b20b0c2ea49bca847e2db9b7bba5ce15b74e1d29194a12780e73686f3dd,
0xe2b0507c13ab66b4b769ad1a1a86834e385b315da2f716f7a7a8ff35a9e8f98c,
0xeefe54bc9fa94b921b20e7590979c28a97d8191d1074c7c68a656953e2836a72,
0x8676e7f59d6f2ebb0edda746fc1589ef55e07feab00d7008a0f2f6f129b7bb3a,
0x78a3d93181b40152bd5a8d84d0df7f2adde5db7529325c13bc24a5b388aed3c4,
0xcc0e2d0cba7aaa19c874dbf0393d847086a980628f7459e9204fda39fad375c0,
0x6e46a52cd7745f84048998df1a966736d2ac09a95a1c553016fef6b9ec156575,
0x204ac2831d2376d4f9c1f5c106760851da968dbfc488dc8a715d1c764c238263,
0xbdb8cc7b7e5042a947fca6c000c10b9b584e965c3590f92f6af3fe4fb23e1358,
0x4a55e4b8a138e8508e7b11726f617dcf4155714d4600e7d593fd965657fcbd89,
0xdfe064bb37f28d97b16d58b575844964205e7606dce914a661f2afa89157c45b,
0x560e374fc0edda5848eef7ff06471545fcbdd8aefb2ecddd35dfbb4cb03b7ddf,
0x10a66c82e146da5ec6f48b614080741bc51322a60d208a87090ad7c7bf6b71c6,
0x62534c7dc682cbf356e6081fc397c0a17221b88508eaeff798d5977f85630d4f,
0x0138bba8de2331861275356f6302b0e7424bbc74d88d8c534479e17a3494a15b,
0x580c7768bf151175714b4a6f2685dc5bcfeb088706ee7ed5236604888b84d3e4,
0xd290adb1a5dfc69da431c1c0c13da3be788363238d7b46bc20185edb45ab9139,
0x1689879db6c78eb4d3038ed81be1bc106f8cfa70a7c6245bd4be642bfa02ebd7,
0x6064c384002c8b1594e738954ed4088a0430316738def62822d08b2285514918,
0x01fd23493f4f1cc3c5ff4e96a9ee386b2a144b50a428a6b5db654072bddadfe7,
0xd5d05bb7f23ab0fa2b82fb1fb14ac29c2477d81a85423d0a45a4b7d5bfd81619,
0xd72b9a73ae7b24db03b84e01106cea734d4b9d9850b0b7e9d65d6001d859c772,
0x156317cb64578db93fee2123749aff58c81eae82b189b0d6f466f91de02b59df,
0x5fba299f3b2c099edbac18d785be61852225890fc004bf6be0787d62926a79b3,
0x004154f28f685bdbf0f0d6571e7a962a4c29b6c3ebedaaaf66097dfe8ae5f756,
0x4b45816f9834c3b289affce7a3dc80056c2b7ffd3e3c250d6dff7f923e7af695,
0x6ca53bc37816fff82346946d83bef87860626bbee7fd6ee9a4aeb904d893a11f,
0xf48b2f43184358d66d5b5f7dd2b14a741c7441cc7a33ba3ebcc94a7b0192d496,
0x3cb98f4baa429250311f93b46e745174f65f901fab4eb8075d380908aaaef650,
0x343dfc26b4473b3a20e706a8e87e5202a4e6b96b53ed448afb9180c3f766e5f8,
0x1ace0e8a735073bcbaea001af75b681298ef3b84f1dbab46ea52cee95ab0e7f9,
0xd239b110dd71460cdbc41ddc99494a7531186c09da2a697d6351c116e667733b,
0x22d6955236bd275969b8a6a30c23932670a6067f68e236d2869b6a8b4b493b83,
0x53c1c01f8d061ac89187e5815ef924751412e6a6aa4dc8e3abafb1807506b4e0,
0x2f56dd20c44d7370b713e7d7a1bfb1a800cac33f8a6157f278e17a943806a1f7,
0xc99773d8a5b3e60115896a65ac1d6c15863317d403ef58b90cb89846f4715a7f,
0x9f4b6b77c254094621cd336da06fbc6cbb7b8b1d2afa8e537ceca1053c561ef5,
0x87944d0b210ae0a6c201cba04e293f606c42ebaed8b4a5d1c33f56863ae7e1b5,
0xa7d116d962d03ca31a455f9cda90f33638fb36d3e3506605aa19ead554487a37,
0x4042e32e224889efd724899c9edb57a703e63a404129ec99858048fbc12f2ce0,
0x36759f7a0faeea1cd4cb91e404e4bf09908de6e53739603d5f0db52b664158a3,
0xa4d50d005fb7b9fea8f86f1c92439cc9b8446efef7333ca03a8f6a35b2d49c38,
0x80cb7c3e20f619006542edbe71837cdadc12161890a69eea8f41be2ee14c08a3,
0xbb3c44e1df45f2bb93fb80e7f82cee886c153ab484c0095b1c18df03523629b4,
0x04cb749e70fac3ac60dea779fceb0730b2ec5b915b0f8cf28a6246cf6da5db29,
0x4f5189b8f650687e65a962ef3372645432b0c1727563777433ade7fa26f8a728,
0x322eddddf0898513697599b68987be5f88c0258841affec48eb17cf3f61248e8,
0x6416be41cda27711d9ec22b3c0ed4364ff6975a24a774179c52ef7e6de9718d6,
0x0622d31b8c4ac7f2e30448bdadfebd5baddc865e0759057a6bf7d2a2c8b527e2,
0x40f096513588cc19c08a69e4a48ab6a43739df4450b86d3ec2fb3c6a743b5485,
0x09fcf7d49290785c9ea2d54c3d63f84f6ea0a2e9acfcdbb0cc3a281ce438250e,
0x2000a519bf3da827f580982d449b5c70fcc0d4fa232addabe47bb8b1c471e62e,
0xf4f80008518e200c40b043f34fb87a6f61b82f8c737bd784292911af3740245e,
0x939eaab59f3d2ad49e50a0220080882319db7633274a978ced03489870945a65,
0xadcad043d8c753fb10689280b7670f313253f5d719039e250a673d94441ee17c,
0x58b7b75f090166b8954c61057074707d7e38d55ce39d9b2251bbc3d72be458f8,
0xf61031890c94c5f87229ec608f2a9aa0a3f455ba8094b78395ae312cbfa04087,
0x356a55def50139f94945e4ea432e7a9defa5db7975462ebb6ca99601c614ea1d,
0x65963bb743d5db080005c4db59e29c4a4e86f92ab1dd7a59f69ea7eaf8e9aa79]
lamport_1 = [0x9c0bfb14de8d2779f88fc8d5b016f8668be9e231e745640096d35dd5f53b0ae2,
0x756586b0f3227ab0df6f4b7362786916bd89f353d0739fffa534368d8d793816,
0x710108dddc39e579dcf0819f9ad107b3c56d1713530dd94325db1d853a675a37,
0x8862b5f428ce5da50c89afb50aa779bb2c4dfe60e6f6a070b3a0208a4a970fe5,
0x54a9cd342fa3a4bf685c01d1ce84f3068b0d5b6a58ee22dda8fbac4908bb9560,
0x0fa3800efeaddd28247e114a1cf0f86b9014ccae9c3ee5f8488168b1103c1b44,
0xbb393428b7ebfe2eda218730f93925d2e80c020d41a29f4746dcbb9138f7233a,
0x7b42710942ef38ef2ff8fe44848335f26189c88c22a49fda84a51512ac68cd5d,
0x90e99786a3e8b04db95ccd44d01e75558d75f3ddd12a1e9a2c2ce76258bf4813,
0x3f6f71e40251728aa760763d25deeae54dc3a9b53807c737deee219120a2230a,
0xe56081a7933c6eaf4ef2c5a04e21ab8a3897785dd83a34719d1b62d82cfd00c2,
0x76cc54fa15f53e326575a9a2ac0b8ed2869403b6b6488ce4f3934f17db0f6bee,
0x1cd9cd1d882ea3830e95162b5de4beb5ddff34fdbf7aec64e83b82a6d11b417c,
0xb8ca8ae36d717c448aa27405037e44d9ee28bb8c6cc538a5d22e4535c8befd84,
0x5c4492108c25f873a23d5fd7957b3229edc22858e8894febe7428c0831601982,
0x907bcd75e7465e9791dc34e684742a2c0dc7007736313a95070a7e6b961c9c46,
0xe7134b1511559e6b2440672073fa303ec3915398e75086149eb004f55e893214,
0x2ddc2415e4753bfc383d48733e8b2a3f082883595edc5515514ebb872119af09,
0xf2ad0f76b08ffa1eee62228ba76f4982fab4fbede5d4752c282c3541900bcd5b,
0x0a84a6b15abd1cbc2da7092bf7bac418b8002b7000236dfba7c8335f27e0f1d4,
0x97404e02b9ff5478c928e1e211850c08cc553ebac5d4754d13efd92588b1f20d,
0xfa6ca3bcff1f45b557cdec34cb465ab06ade397e9d9470a658901e1f0f124659,
0x5bd972d55f5472e5b08988ee4bccc7240a8019a5ba338405528cc8a38b29bc21,
0x52952e4f96c803bb76749800891e3bfe55f7372facd5b5a587a39ac10b161bcc,
0xf96731ae09abcad016fd81dc4218bbb5b2cb5fe2e177a715113f381814007314,
0xe7d79e07cf9f2b52623491519a21a0a3d045401a5e7e10dd8873a85076616326,
0xe4892f3777a4614ee6770b22098eaa0a3f32c5c44b54ecedacd69789d676dffe,
0x20c932574779e2cc57780933d1dc6ce51a5ef920ce5bf681f7647ac751106367,
0x057252c573908e227cc07797117701623a4835f4b047dcaa9678105299e48e70,
0x20bad780930fa2a036fe1dea4ccbf46ac5b3c489818cdb0f97ae49d6e2f11fbf,
0xc0d7dd26ffecdb098585a1694e45a54029bb1e31c7c5209289058efebb4cc91b,
0x9a8744beb1935c0abe4b11812fc02748ef7c8cb650db3024dde3c5463e9d8714,
0x8ce6eea4585bbeb657b326daa4f01f6aef34954338b3ca42074aedd1110ba495,
0x1c85b43f5488b370721290d2faea19d9918d094c99963d6863acdfeeca564363,
0xe88a244347e448349e32d0525b40b18533ea227a9d3e9b78a9ff14ce0a586061,
0x352ca61efc5b8ff9ee78e738e749142dd1606154801a1449bbb278fa6bcc3dbe,
0xa066926f9209220b24ea586fb20eb8199a05a247c82d7af60b380f6237429be7,
0x3052337ccc990bfbae26d2f9fe5d7a4eb8edfb83a03203dca406fba9f4509b6e,
0x343ce573a93c272688a068d758df53c0161aa7f9b55dec8beced363a38b33069,
0x0f16b5593f133b58d706fe1793113a10750e8111eadee65301df7a1e84f782d3,
0x808ae8539357e85b648020f1e9d255bc4114bee731a6220d7c5bcb5b85224e03,
0x3b2bd97e31909251752ac57eda6015bb05b85f2838d475095cfd146677430625,
0xe4f857c93b2d8b250050c7381a6c7c660bd29066195806c8ef11a2e6a6640236,
0x23d91589b5070f443ddcefa0838c596518d54928119251ecf3ec0946a8128f52,
0xb72736dfad52503c7f5f0c59827fb6ef4ef75909ff9526268abc0f296ee37296,
0x80a8c66436d86b8afe87dde7e53a53ef87e057a5d4995963e76d159286de61b6,
0xbec92c09ee5e0c84d5a8ba6ca329683ff550ace34631ea607a3a21f99cd36d67,
0x83c97c9807b9ba6d9d914ae49dabdb4c55e12e35013f9b179e6bc92d5d62222b,
0x8d9c79f6af3920672dc4cf97a297c186e75083d099aeb5c1051207bad0c98964,
0x2aaa5944a2bd852b0b1be3166e88f357db097b001c1a71ba92040b473b30a607,
0x46693d27ec4b764fbb516017c037c441f4558aebfe972cdcd03da67c98404e19,
0x903b25d9e12208438f203c9ae2615b87f41633d5ffda9cf3f124c1c3922ba08f,
0x3ec23dc8bc1b49f5c7160d78008f3f235252086a0a0fa3a7a5a3a53ad29ec410,
0xa1fe74ceaf3cccd992001583a0783d7d7b7a245ea374f369133585b576b9c6d8,
0xb2d6b0fe4932a2e06b99531232398f39a45b0f64c3d4ebeaaebc8f8e50a80607,
0xe19893353f9214eebf08e5d83c6d44c24bffe0eceee4dc2e840d42eab0642536,
0x5b798e4bc099fa2e2b4b5b90335c51befc9bbab31b4dd02451b0abd09c06ee79,
0xbab2cdec1553a408cac8e61d9e6e19fb8ccfb48efe6d02bd49467a26eeeca920,
0x1c1a544c28c38e5c423fe701506693511b3bc5f2af9771b9b2243cd8d41bebfc,
0x704d6549d99be8cdefeec9a58957f75a2be4af7bc3dc4655fa606e7f3e03b030,
0x051330f43fe39b08ed7d82d68c49b36a8bfa31357b546bfb32068712df89d190,
0xe69174c7b03896461cab2dfaab33d549e3aac15e6b0f6f6f466fb31dae709b9b,
0xe5f668603e0ddbbcde585ac41c54c3c4a681fffb7a5deb205344de294758e6ac,
0xca70d5e4c3a81c1f21f246a3f52c41eaef9a683f38eb7c512eac8b385f46cbcd,
0x3173a6b882b21cd147f0fc60ef8f24bbc42104caed4f9b154f2d2eafc3a56907,
0xc71469c192bf5cc36242f6365727f57a19f924618b8a908ef885d8f459833cc3,
0x59c596fc388afd8508bd0f5a1e767f3dda9ed30f6646d15bc59f0b07c4de646f,
0xb200faf29368581f551bd351d357b6fa8cbf90bdc73b37335e51cad36b4cba83,
0x275cede69b67a9ee0fff1a762345261cb20fa8191470159cc65c7885cfb8313c,
0x0ce4ef84916efbe1ba9a0589bed098793b1ea529758ea089fd79151cc9dc7494,
0x0f08483bb720e766d60a3cbd902ce7c9d835d3f7fdf6dbe1f37bcf2f0d4764a2,
0xb30a73e5db2464e6da47d10667c82926fa91fceb337d89a52db5169008bc6726,
0x6b9c50fed1cc404bf2dd6fffbfd18e30a4caa1500bfeb080aa93f78d10331aaf,
0xf17c84286df03ce175966f560600dd562e0f59f18f1d1276b4d8aca545d57856,
0x11455f2ef96a6b2be69854431ee219806008eb80ea38c81e45b2e58b3f975a20,
0x9a61e03e2157a5c403dfcde690f7b7d704dd56ea1716cf14cf7111075a8d6491,
0x30312c910ce6b39e00dbaa669f0fb7823a51f20e83eaeb5afa63fb57668cc2f4,
0x17c18d261d94fba82886853a4f262b9c8b915ed3263b0052ece5826fd7e7d906,
0x2d8f6ea0f5b9d0e4bc1478161f5ed2ad3d8495938b414dcaec9548adbe572671,
0x19954625f13d9bab758074bf6dee47484260d29ee118347c1701aaa74abd9848,
0x842ef2ad456e6f53d75e91e8744b96398df80350cf7af90b145fea51fbbcf067,
0x34a8b0a76ac20308aa5175710fb3e75c275b1ff25dba17c04e3a3e3c48ca222c,
0x58efcbe75f32577afe5e9ff827624368b1559c32fcca0cf4fd704af8ce019c63,
0x411b4d242ef8f14d92bd8b0b01cb4fa3ca6f29c6f9073cfdd3ce614fa717463b,
0xf76dbda66ede5e789314a88cff87ecb4bd9ca418c75417d4d920e0d21a523257,
0xd801821a0f87b4520c1b003fe4936b6852c410ee00b46fb0f81621c9ac6bf6b4,
0x97ad11d6a29c8cf3c548c094c92f077014de3629d1e9053a25dbfaf7eb55f72d,
0xa87012090cd19886d49521d564ab2ad0f18fd489599050c42213bb960c9ee8ff,
0x8868d8a26e758d50913f2bf228da0444a206e52853bb42dd8f90f09abe9c859a,
0xc257fb0cc9970e02830571bf062a14540556abad2a1a158f17a18f14b8bcbe95,
0xfe611ce27238541b14dc174b652dd06719dfbcda846a027f9d1a9e8e9df2c065,
0xc9b25ea410f420cc2d4fc6057801d180c6cab959bce56bf6120f555966e6de6d,
0x95437f0524ec3c04d4132c83be7f1a603e6f4743a85ede25aa97a1a4e3f3f8fc,
0x82a12910104065f35e983699c4b9187aed0ab0ec6146f91728901efecc7e2e20,
0x6622dd11e09252004fb5aaa39e283333c0686065f228c48a5b55ee2060dbd139,
0x89a2879f25733dab254e4fa6fddb4f04b8ddf018bf9ad5c162aea5c858e6faaa,
0x8a71b62075a6011fd9b65d956108fa79cc9ebb8f194d64d3105a164e01cf43a6,
0x103f4fe9ce211b6452181371f0dc4a30a557064b684645a4495136f4ebd0936a,
0x97914adc5d7ce80147c2f44a6b29d0b495d38dedd8cc299064abcc62ed1ddabc,
0x825c481da6c836a8696d7fda4b0563d204a9e7d9e4c47b46ded26db3e2d7d734,
0xf8c0637ba4c0a383229f1d730db733bc11d6a4e33214216c23f69ec965dcaaad,
0xaed3bdaf0cb12d37764d243ee0e8acdefc399be2cabbf1e51dc43454efd79cbd,
0xe8427f56cc5cec8554e2f5f586b57adccbea97d5fc3ef7b8bbe97c2097cf848c,
0xba4ad0abd5c14d526357fd0b6f8676ef6126aeb4a6d80cabe1f1281b9d28246c,
0x4cff20b72e2ab5af3fafbf9222146949527c25f485ec032f22d94567ff91b22f,
0x0d32925d89dd8fed989912afcbe830a4b5f8f7ae1a3e08ff1d3a575a77071d99,
0xe51a1cbeae0be5d2fdbc7941aea904d3eade273f7477f60d5dd6a12807246030,
0xfb8615046c969ef0fa5e6dc9628c8a9880e86a5dc2f6fc87aff216ea83fcf161,
0x64dd705e105c88861470d112c64ca3d038f67660a02d3050ea36c34a9ebf47f9,
0xb6ad148095c97528180f60fa7e8609bf5ce92bd562682092d79228c2e6f0750c,
0x5bae0cd81f3bd0384ca3143a72068e6010b946462a73299e746ca639c026781c,
0xc39a0fc7764fcfc0402b12fb0bbe78fe3633cbfb33c7f849279585a878a26d7c,
0x2b752fda1c0c53d685cc91144f78d371db6b766725872b62cc99e1234cca8c1a,
0x40ee6b9635d87c95a528757729212a261843ecb06d975de91352d43ca3c7f196,
0x75e2005d3726cf8a4bb97ea5287849a361e3f8fdfadc3c1372feed1208c89f6b,
0x0976f8ab556153964b58158678a5297da4d6ad92e284da46052a791ee667aee4,
0xdbeef07841e41e0672771fb550a5b9233ae8e9256e23fa0d34d5ae5efe067ec8,
0xa890f412ab6061c0c5ee661e80d4edc5c36b22fb79ac172ddd5ff26a7dbe9751,
0xb666ae07f9276f6d0a33f9efeb3c5cfcba314fbc06e947563db92a40d7a341e8,
0x83a082cf97ee78fbd7f31a01ae72e40c2e980a6dab756161544c27da86043528,
0xfa726a919c6f8840c456dc77b0fec5adbed729e0efbb9317b75f77ed479c0f44,
0xa8606800c54faeab2cbc9d85ff556c49dd7e1a0476027e0f7ce2c1dc2ba7ccbf,
0x2796277836ab4c17a584c9f6c7778d10912cb19e541fb75453796841e1f6cd1c,
0xf648b8b3c7be06f1f8d9cda13fd6d60f913e5048a8e0b283b110ca427eeb715f,
0xa21d00b8fdcd77295d4064e00fbc30bed579d8255e9cf3a9016911d832390717,
0xe741afcd98cbb3bb140737ed77bb968ac60d5c00022d722f9f04f56e97235dc9,
0xbeecc9638fac39708ec16910e5b02c91f83f6321f6eb658cf8a96353cfb49806,
0x912eee6cabeb0fed8d6e6ca0ba61977fd8e09ea0780ff8fbec995e2a85e08b52,
0xc665bc0bb121a1229bc56ecc07a7e234fd24c523ea14700aa09e569b5f53ad33,
0x39501621c2bdff2f62ab8d8e3fe47fe1701a98c665697c5b750ee1892f11846e,
0x03d32e16c3a6c913daefb139f131e1e95a742b7be8e20ee39b785b4772a50e44,
0x4f504eb46a82d440f1c952a06f143994bc66eb9e3ed865080cd9dfc6d652b69c,
0xad753dc8710a46a70e19189d8fc7f4c773e4d9ccc7a70c354b574fe377328741,
0xf7f5464a2d723b81502adb9133a0a4f0589b4134ca595a82e660987c6b011610,
0x216b60b1c3e3bb4213ab5d43e04619d13e1ecedbdd65a1752bda326223e3ca3e,
0x763664aa96d27b6e2ac7974e3ca9c9d2a702911bc5d550d246631965cf2bd4a2,
0x292b5c8c8431b040c04d631f313d4e6b67b5fd3d4b8ac9f2edb09d13ec61f088,
0x80db43c2b9e56eb540592f15f5900222faf3f75ce62e78189b5aa98c54568a5e,
0x1b5fdf8969bcd4d65e86a2cefb3a673e18d587843f4f50db4e3ee77a0ba2ef1c,
0x11e237953fff3e95e6572da50a92768467ffdfd0640d3384aa1c486357e7c24a,
0x1fabd4faa8dba44808cc87d0bc389654a98496745578f3d17d134adc7f7b10f3,
0x5eca4aa96f20a56197772ae6b600762154ca9d2702cab12664ea47cbff1a440c,
0x0b4234f5bb02abcf3b5ce6c44ea85f55ec7db98fa5a7b90abef6dd0df034743c,
0x316761e295bf350313c4c92efea591b522f1df4211ce94b22e601f30aefa51ef,
0xe93a55ddb4d7dfe02598e8f909ff34b3de40a1c0ac8c7fba48cb604ea60631fb,
0xe6e6c877b996857637f8a71d0cd9a6d47fdeb03752c8965766f010073332b087,
0xa4f95c8874e611eddd2c4502e4e1196f0f1be90bfc37db35f8588e7d81d34aeb,
0x9351710a5633714bb8b2d226e15ba4caa6f50f56c5508e5fa1239d5cc6a7e1aa,
0x8d0aef52ec7266f37adb572913a6213b8448caaf0384008373dec525ae6cdff1,
0x718e24c3970c85bcb14d2763201812c43abac0a7f16fc5787a7a7b2f37288586,
0x3600ce44cebc3ee46b39734532128eaf715c0f3596b554f8478b961b0d6e389a,
0x50dd1db7b0a5f6bd2d16252f43254d0f5d009e59f61ebc817c4bbf388519a46b,
0x67861ed00f5fef446e1f4e671950ac2ddae1f3b564f1a6fe945e91678724ef03,
0x0e332c26e169648bc20b4f430fbf8c26c6edf1a235f978d09d4a74c7b8754aad,
0x6c9901015adf56e564dfb51d41a82bde43fb67273b6911c9ef7fa817555c9557,
0x53c83391e5e0a024f68d5ade39b7a769f10664e12e4942c236398dd5dbce47a1,
0x78619564f0b2399a9fcb229d938bf1e298d62b03b7a37fe6486034185d7f7d27,
0x4625f15381a8723452ec80f3dd0293c213ae35de737c508f42427e1735398c3a,
0x69542425ddb39d3d3981e76b41173eb1a09500f11164658a3536bf3e292f8b6a,
0x82ac4f5bb40aece7d6706f1bdf4dfba5c835c09afba6446ef408d8ec6c09300f,
0x740f9180671091b4c5b3ca59b9515bd0fc751f48e488a9f7f4b6848602490e21,
0x9a04b08b4115986d8848e80960ad67490923154617cb82b3d88656ec1176c24c,
0xf9ffe528eccffad519819d9eef70cef317af33899bcaee16f1e720caf9a98744,
0x46da5e1a14b582b237f75556a0fd108c4ea0d55c0edd8f5d06c59a42e57410df,
0x098f3429c8ccda60c3b5b9755e5632dd6a3f5297ee819bec8de2d8d37893968a,
0x1a5b91af6025c11911ac072a98b8a44ed81f1f3c76ae752bd28004915db6f554,
0x8bed50c7cae549ed4f8e05e02aa09b2a614c0af8eec719e4c6f7aee975ec3ec7,
0xd86130f624b5dcc116f2dfbb5219b1afde4b7780780decd0b42694e15c1f8d8b,
0x4167aa9bc0075f624d25d40eb29139dd2c452ebf17739fab859e14ac6765337a,
0xa258ce5db20e91fb2ea30d607ac2f588bdc1924b21bbe39dc881e19889a7f5c6,
0xe5ef8b5ab3cc8894452d16dc875b69a55fd925808ac7cafef1cd19485d0bb50a,
0x120df2b3975d85b6dfca56bb98a82025ade5ac1d33e4319d2e0105b8de9ebf58,
0xc964291dd2e0807a468396ebba3d59cfe385d949f6d6215976fc9a0a11de209a,
0xf23f14cb709074b79abe166f159bc52b50de687464df6a5ebf112aa953c95ad5,
0x622c092c9bd7e30f880043762e26d8e9c73ab7c0d0806f3c5e472a4152b35a93,
0x8a5f090662731e7422bf651187fb89812419ab6808f2c62da213d6944fccfe9f,
0xfbea3c0d92e061fd2399606f42647d65cc54191fa46d57b325103a75f5c22ba6,
0x2babfbcc08d69b52c3747ddc8dcad4ea5511edabf24496f3ff96a1194d6f680e,
0x4d3d019c28c779496b616d85aee201a3d79d9eecf35f728d00bcb12245ace703,
0xe76fcee1f08325110436f8d4a95476251326b4827399f9b2ef7e12b7fb9c4ba1,
0x4884d9c0bb4a9454ea37926591fc3eed2a28356e0506106a18f093035638da93,
0x74c3f303d93d4cc4f0c1eb1b4378d34139220eb836628b82b649d1deb519b1d3,
0xacb806670b278d3f0c84ba9c7a68c7df3b89e3451731a55d7351468c7c864c1c,
0x8660fb8cd97e585ea7a41bccb22dd46e07eee8bbf34d90f0f0ca854b93b1ebee,
0x2fc9c89cdca71a1c0224d469d0c364c96bbd99c1067a7ebe8ef412c645357a76,
0x8ec6d5ab6ad7135d66091b8bf269be44c20af1d828694cd8650b5479156fd700,
0x50ab4776e8cabe3d864fb7a1637de83f8fbb45d6e49645555ffe9526b27ebd66,
0xbf39f5e17082983da4f409f91c7d9059acd02ccbefa69694aca475bb8d40b224,
0x3135b3b981c850cc3fe9754ec6af117459d355ad6b0915beb61e84ea735c31bf,
0xa7971dab52ce4bf45813223b0695f8e87f64b614c9c5499faac6f842e5c41be9,
0x9e480f5617323ab104b4087ac4ef849a5da03427712fb302ac085507c77d8f37,
0x57a6d474654d5e8d408159be39ad0e7026e6a4c6a6543e23a63d30610dc8dfc1,
0x09eb3e01a5915a4e26d90b4c58bf0cf1e560fdc8ba53faed9d946ad3e9bc78fa,
0x29c6d25da80a772310226b1b89d845c7916e4a4bc94d75aa330ec3eaa14b1e28,
0x1a1ccfee11edeb989ca02e3cb89f062612a22a69ec816a625835d79370173987,
0x1cb63dc541cf7f71c1c4e8cabd2619c3503c0ea1362dec75eccdf1e9efdbfcfc,
0xac9dff32a69e75b396a2c250e206b36c34c63b955c9e5732e65eaf7ccca03c62,
0x3e1b4f0c3ebd3d38cec389720147746774fc01ff6bdd065f0baf2906b16766a8,
0x5cc8bed25574463026205e90aad828521f8e3d440970d7e810d1b46849681db5,
0x255185d264509bd3a768bb0d50b568e66eb1fec96d573e33aaacc716d7c8fb93,
0xe81b86ba631973918a859ff5995d7840b12511184c2865401f2693a71b9fa07e,
0x61e67e42616598da8d36e865b282127c761380d3a56d26b8d35fbbc7641433c5,
0x60c62ffef83fe603a34ca20b549522394e650dad5510ae68b6e074f0cd209a56,
0x78577f2caf4a54f6065593535d76216f5f4075af7e7a98b79571d33b1822920c,
0xfd4cb354f2869c8650200de0fe06f3d39e4dbebf19b0c1c2677da916ea84f44d,
0x453769cef6ff9ba2d5c917982a1ad3e2f7e947d9ea228857556af0005665e0b0,
0xe567f93f8f88bf1a6b33214f17f5d60c5dbbb531b4ab21b8c0b799b6416891e0,
0x7e65a39a17f902a30ceb2469fe21cba8d4e0da9740fcefd5c647c81ff1ae95fa,
0x03e4a7eea0cd6fc02b987138ef88e8795b5f839636ca07f6665bbae9e5878931,
0xc3558e2b437cf0347cabc63c95fa2710d3f43c65d380feb998511903f9f4dcf0,
0xe3a615f80882fb5dfbd08c1d7a8b0a4d3b651d5e8221f99b879cb01d97037a9c,
0xb56db4a5fea85cbffaee41f05304689ea321c40d4c108b1146fa69118431d9b2,
0xab28e1f077f18117945910c235bc9c6f9b6d2b45e9ef03009053006c637e3e26,
0xefcabc1d5659fd6e48430dbfcc9fb4e08e8a9b895f7bf9b3d6c7661bfc44ada2,
0xc7547496f212873e7c3631dafaca62a6e95ac39272acf25a7394bac6ea1ae357,
0xc482013cb01bd69e0ea9f447b611b06623352e321469f4adc739e3ee189298eb,
0x5942f42e91e391bb44bb2c4d40da1906164dbb6d1c184f00fa62899baa0dba2c,
0xb4bcb46c80ad4cd603aff2c1baf8f2c896a628a46cc5786f0e58dae846694677,
0xd0a7305b995fa8c317c330118fee4bfef9f65f70b54558c0988945b08e90ff08,
0x687f801b7f32fdfa7d50274cc7b126efedbdae8de154d36395d33967216f3086,
0xeb19ec10ac6c15ffa619fa46792971ee22a9328fa53bd69a10ed6e9617dd1bbf,
0xa2bb3f0367f62abdb3a9fa6da34b20697cf214a4ff14fd42826da140ee025213,
0x070a76511f32c882374400af59b22d88974a06fbc10d786dd07ca7527ebd8b90,
0x8f195689537b446e946b376ec1e9eb5af5b4542ab47be550a5700fa5d81440d5,
0x10cc09778699fc8ac109e7e6773f83391eeba2a6db5226fbe953dd8d99126ca5,
0x8cc839cb7dc84fd3b8c0c7ca637e86a2f72a8715cc16c7afb597d12da717530b,
0xa32504e6cc6fd0ee441440f213f082fcf76f72d36b5e2a0f3b6bdd50cdd825a2,
0x8f45151db8878e51eec12c450b69fa92176af21a4543bb78c0d4c27286e74469,
0x23f5c465bd35bcd4353216dc9505df68324a27990df9825a242e1288e40a13bb,
0x35f409ce748af33c20a6ae693b8a48ba4623de9686f9834e22be4410e637d24f,
0xb962e5845c1db624532562597a99e2acc5e434b97d8db0725bdeddd71a98e737,
0x0f8364f99f43dd52b4cfa9e426c48f7b6ab18dc40a896e96a09eceebb3363afe,
0xa842746868da7644fccdbb07ae5e08c71a6287ab307c4f9717eadb414c9c99f4,
0xa59064c6b7fe7d2407792d99ed1218d2dc2f240185fbd8f767997438241b92e9,
0xb6ea0d58e8d48e05b9ff4d75b2ebe0bd9752c0e2691882f754be66cdec7628d3,
0xf16b78c9d14c52b2b5156690b6ce37a5e09661f49674ad22604c7d3755e564d1,
0xbfa8ef74e8a37cd64b8b4a4260c4fc162140603f9c2494b9cf4c1e13de522ed9,
0xf4b89f1776ebf30640dc5ec99e43de22136b6ef936a85193ef940931108e408a,
0xefb9a4555d495a584dbcc2a50938f6b9827eb014ffae2d2d0aae356a57894de8,
0x0627a466d42a26aca72cf531d4722e0e5fc5d491f4527786be4e1b641e693ac2,
0x7d10d21542de3d8f074dbfd1a6e11b3df32c36272891aae54053029d39ebae10,
0x0f21118ee9763f46cc175a21de876da233b2b3b62c6f06fa2df73f6deccf37f3,
0x143213b96f8519c15164742e2350cc66e814c9570634e871a8c1ddae4d31b6b5,
0x8d2877120abae3854e00ae8cf5c8c95b3ede10590ab79ce2be7127239507e18d,
0xaccd0005d59472ac04192c059ed9c10aea42c4dabec9e581f6cb10b261746573,
0x67bc8dd5422f39e741b9995e6e60686e75d6620aa0d745b84191f5dba9b5bb18,
0x11b8e95f6a654d4373cefbbac29a90fdd8ae098043d1969b9fa7885318376b34,
0x431a0b8a6f08760c942eeff5791e7088fd210f877825ce4dcabe365e03e4a65c,
0x704007f11bae513f428c9b0d23593fd2809d0dbc4c331009856135dafec23ce4,
0xc06dee39a33a05e30c522061c1d9272381bde3f9e42fa9bd7d5a5c8ef11ec6ec,
0x66b4157baaae85db0948ad72882287a80b286df2c40080b8da4d5d3db0a61bd2,
0xef1983b1906239b490baaaa8e4527f78a57a0a767d731f062dd09efb59ae8e3d,
0xf26d0d5c520cce6688ca5d51dee285af26f150794f2ea9f1d73f6df213d78338,
0x8b28838382e6892f59c42a7709d6d38396495d3af5a8d5b0a60f172a6a8940bd,
0x261a605fa5f2a9bdc7cffac530edcf976e7ea7af4e443b625fe01ed39dad44b6]
compressed_lamport_PK = 0xdd635d27d1d52b9a49df9e5c0c622360a4dd17cba7db4e89bce3cb048fb721a5
child_SK = 20397789859736650942317412262472558107875392172444076792671091975210932703118
```

## Security Considerations

None.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 30 Sep 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2333</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2333</guid>
      </item>
    
      <item>
        <title>BLS12-381 Deterministic Account Hierarchy</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/bls-keys-related-erc-discussion-erc-2333-2334-2335/19774</comments>
        
        <description>## Abstract

A standard for allocating keys generated by [ERC-2333](/EIPs/EIPS/eip-2333) to a specific purpose. It defines a `path` which is a string that parses into the indices to be used when traversing the tree of keys that [ERC-2333](/EIPs/EIPS/eip-2333) generates.

## Motivation

The Beacon chain uses BLS signatures over BLS12-381. This new scheme requires a new key derivation mechanism, which is established within [ERC-2333](/EIPs/EIPS/eip-2333). This new scheme is incompatible with [BIP44](https://github.com/bitcoin/bips/blob/43ce3a461dfb48e62ffa0cfc70f5f54d1eb5c577/bip-0044.mediawiki) due to the exclusive use of hardened keys, the increased number of keys per level, not using [BIP32](https://github.com/bitcoin/bips/blob/43ce3a461dfb48e62ffa0cfc70f5f54d1eb5c577/bip-0032.mediawiki) for key derivation. It is therefore necessary to establish a new *path* for traversing the [ERC-2333](/EIPs/EIPS/eip-2333) key-tree.

The path structure specified in this ERC aims to be more general than [BIP44](https://github.com/bitcoin/bips/blob/43ce3a461dfb48e62ffa0cfc70f5f54d1eb5c577/bip-0044.mediawiki) by not having UTXO-centric features which gave rise to the 4 different types of wallet paths being used within Ethereum in the past and gave rise to (draft) [ERC-600](/EIPs/EIPS/eip-600) &amp; [ERC-601](/EIPs/EIPS/eip-601)

## Specification

### Path

The path traversed through the tree of keys is defined by integers (which indicate the sibling index) separated by `/` which denote ancestor relations. There are 4 levels (plus the master node) in the path and at least 4 (5 including the master node) MUST be used.

```text
m / purpose / coin_type /  account / use
```

#### Notation

The notation used within the path is specified within the [ERC-2333](/EIPs/EIPS/eip-2333), but is summarized again below for convenience.

* `m` Denotes the master node (or root) of the tree
* `/` Separates the tree into depths, thus `i / j` signifies that `j` is a child of `i`

### Purpose

The `purpose` is set to `12381` which is the name of the new curve (BLS12-381). In order to be in compliance with this standard, the [ERC-2333](/EIPs/EIPS/eip-2333) MUST be implemented as the KDF and therefore, the purpose `12381` MAY NOT be used unless this is the case.

### Coin Type

The `coin_type` here reflects the coin number for an individual coin thereby acting as a means of separating the keys used for different chains.

### Account

`account` is a field that provides the ability for a user to have distinct sets of keys for different purposes, if they so choose. This is the level at which different accounts for a single user SHOULD to be implemented.

### Use

This level is designed to provide a set of related keys that can be used for any purpose. The idea being that a single account has many uses which are related yet should remain separate for security reasons. It is required to support this level in the tree, although, for many purposes it will remain `0`.

### Beacon Chain Specific Parameters

#### Coin type

The coin type used for the BLS12-381 keys in Ethereum is `3600`.

#### Validator keys

Each Beacon chain validator has two keys, one for withdrawals and transfers (called the *withdrawal key*), and the other for performing their duties as a validator (henceforth referred to as the *signing key*).

The path for withdrawal keys is `m/12381/3600/i/0` where `i` indicates the `i`th set of validator keys.

The path for the signing key is `m/12381/3600/i/0/0` where again, `i` indicates the `i`th set of validator keys. Another way of phrasing this is that the signing key is the `0`th child of the associated withdrawal key for that validator.

**Note:** If the above description of key paths is not feasible in a specific use case (eg. with secret-shared or custodial validators), then the affected keys may be omitted and derived via another means. Implementations of this ERC, must endeavour to use the appropriate keys for the given use case to the extent that is reasonably possible. (eg, in the case of custodial staking, the user making the deposits will follow this standard for their withdrawal keys which has no bearing on how the service provide derives the corresponding signing keys.)

## Rationale

`purpose`, `coin_type`, and `account` are widely-adopted terms as per [BIP43](https://github.com/bitcoin/bips/blob/43ce3a461dfb48e62ffa0cfc70f5f54d1eb5c577/bip-0043.mediawiki) and [BIP44](https://github.com/bitcoin/bips/blob/43ce3a461dfb48e62ffa0cfc70f5f54d1eb5c577/bip-0044.mediawiki) and therefore reusing these terms and their associated meanings makes sense.

The purpose needs to be distinct from these standards as the KDF and path are not inter-compatible and `12381` is an obvious choice.

`account` separates user activity into distinct categories thereby allowing users to separate their concerns however they desire.

`use` will commonly be determined at the application level providing distinct keys for non-intersecting use cases.

### Beacon Chain Specific Parameters

A new coin type is chosen for Beacon Chain BLS keys to help ensure a clean separation between BLS12-381 and secp256k1 keys.  `3600` is chosen specifically because it is the square of the Ethereum&apos;s secp256k1 `coin_type` (`3600==60^2`).

The primary reason validators have separate signing and withdrawal keys is to allow for the different security concerns of actions within the Beacon Chain. The signing key is given to the validator client where it signs messages as per the requirements of being a validator, it is therefore a &quot;hot key&quot;. If this key is compromised, the worst that can happen (locally) is that a slashable message is signed, resulting in the validator being slashed and forcibly exited. The withdrawal key is only needed when a validator wishes to perform an action not related to validating and has access to the full funds at stake for that validator. The withdrawal key therefore has higher security concerns and should be handled as a &quot;cold key&quot;. By having the signing key be a child of the withdrawal key, secure storage of the withdrawal key is sufficient to recover the signing key should the need arise.

## Backwards Compatibility

[BIP43](https://github.com/bitcoin/bips/blob/43ce3a461dfb48e62ffa0cfc70f5f54d1eb5c577/bip-0043.mediawiki) and [BIP44](https://github.com/bitcoin/bips/blob/43ce3a461dfb48e62ffa0cfc70f5f54d1eb5c577/bip-0044.mediawiki). Due to the use of a new KDF within [ERC-2333](/EIPs/EIPS/eip-2333), a new path standard is required. This ERC implements this, with minor changes.

`purpose` `12381` paths do not support hardened keys and therefore the `&apos;` character is invalid.

## Security Considerations

None.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 30 Sep 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2334</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2334</guid>
      </item>
    
      <item>
        <title>BLS12-381 Keystore</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/bls-keys-related-erc-discussion-erc-2333-2334-2335/19774</comments>
        
        <description>## Abstract

A keystore is a mechanism for storing private keys. It is a JSON file that encrypts a private key and is the standard for interchanging keys between devices as until a user provides their password, their key is safe.

## Motivation

The secure storage and exchange of keys is a vital component of the user experience as people are expected to hold their own keys. It allows users to control access to individual keys and their use by applications.

In Ethereum, Web3 Secret Storage (commonly referred to as &quot;keystores&quot;) fulfills these requirements, however it is not perfectly suitable for these purposes moving forward. Specifically the problems with the existing standard are:

* __The use of Keccak256.__ Web3 Secret Stores use Keccak for their checksum. BLS signatures, [keys (ERC-2333)](/EIPs/EIPS/eip-2333), and key-storage are inter-chain standards, the establishment and proliferation of which hinges on them being neutral to all chains, something which Keccak is not.

* __A lack of abstraction.__ Web3 Secret Stores are a result of an iterative design process whereby functionality was added and modified as needed without considering how abstractions could simplify the notion of different properties.

## Specification

The process of decrypting the secret held within a keystore can be broken down into 3 sub-processes: obtaining the decryption key, verifying the password and decrypting the secret. Each process has its own functions which can be selected from as well as parameters required for the function all of which are specified within the keystore file itself.

### Password requirements

The password is a string of arbitrary unicode characters. The password is first converted to its NFKD representation, then the control codes (specified below) are stripped from the password and finally it is UTF-8 encoded.

#### Control codes removal

The C0, C1, and `Delete` control codes are not valid characters in the password and should therefore be stripped from the password. C0 are the control codes between `0x00` - `0x1F` (inclusive) and C1 codes lie between `0x80` and `0x9F` (inclusive). `Delete`, commonly known as &quot;backspace&quot;, is the UTF-8 character `7F` which must also be stripped. Note that space (`Sp` UTF-8 `0x20`) is a valid character in passwords despite it being a pseudo-control character.

### Modules

This standard makes use of the notion of a _module_ which serves to represent, in an abstract sense, the different  cryptographic constructions and corresponding parameters for each component of the keystore. The idea being that components can be swapped out without affecting the rest of the specification should the need arise.

A module is comprised of a `function`, which defines which cryptographic construct is being used, `params`, the parameters required by the function, and `message` the primary input to the function.

### Decryption key

The decryption key is an intermediate key which is used both to verify the user-supplied password is correct, as well as for the final secret decryption. This key is simply derived from the password, the `function`, and the `params` specified by the`kdf` module as per the keystore file.

| KDF            | `&quot;function&quot;` | `&quot;params&quot;`                                                                               | `&quot;message&quot;` | Definition                                         |
|----------------|--------------|------------------------------------------------------------------------------------------|-------------|----------------------------------------------------|
| PBKDF2-SHA-256 | `&quot;pbkdf2&quot;`   | &lt;ul&gt;&lt;li&gt;`&quot;c&quot;`&lt;/li&gt;&lt;li&gt;`&quot;dklen&quot;`&lt;/li&gt;&lt;li&gt;`&quot;prf: &quot;hmac-sha256&quot;`&lt;/li&gt;&lt;li&gt;`&quot;salt&quot;`&lt;/li&gt;&lt;/ul&gt; |             | [RFC 2898](https://www.rfc-editor.org/rfc/rfc2898) |
| scrypt         | `&quot;scrypt&quot;`   | &lt;ul&gt;&lt;li&gt;`&quot;dklen&quot;`&lt;/li&gt;&lt;li&gt;`&quot;n&quot;`&lt;/li&gt;&lt;li&gt;`&quot;p&quot;`&lt;/li&gt;&lt;li&gt;`&quot;r&quot;`&lt;/li&gt;&lt;li&gt;`&quot;salt&quot;`&lt;/li&gt;&lt;/ul&gt;   |             | [RFC 7914](https://www.rfc-editor.org/rfc/rfc7914) |

### Password verification

The password verification step verifies that the password is correct with respect to the `checksum.message`, `cipher.message`, and `kdf`. This is done by appending the `cipher.message` to the 2nd 16 bytes of the decryption key, obtaining its SHA256 hash and verifying whether it matches the `checksum.message`.

#### Inputs

* `decryption_key`, the octet string obtained from decryption key process
* `cipher_message`, the octet string obtained from keystore file from `crypto.cipher.message`
* `checksum_message`, the octet string obtained from keystore file from `crypto.checksum.message`

#### Outputs

* `valid_password`, a boolean value indicating whether the password is valid

#### Definitions

* `a[0:3]` returns a slice of `a` including octets 0, 1, 2
* `a | b` is the concatenation of `a` with `b`

#### Procedure

```text
0. DK_slice = decryption_key[16:32]
1. pre_image = DK_slice | cipher_message
2. checksum = SHA256(pre_image)
3. valid_password = checksum == checksum_message
4. return valid_password
```

| Hash       | `&quot;function&quot;`    | `&quot;params&quot;` | `&quot;message&quot;` | Definition                                      |
|------------|-----------------|------------|-------------|-------------------------------------------------|
| SHA-256    | `&quot;sha256&quot;`      |            |             | [RFC 6234](https://www.rfc-editor.org/rfc/rfc6234) |

### Secret decryption

The `cipher.function` encrypts the secret using the decryption key, thus to decrypt it, the decryption key along with the `cipher.function` and `cipher.params` must be used. If the `decryption_key` is longer than the key size required by the cipher, it is truncated to the correct number of bits. In the case of aes-128-ctr, only the first 16 bytes of the `decryption_key` are used as the AES key.

| Cipher               | `&quot;function&quot;`    | `&quot;params&quot;`               | `&quot;message&quot;` | Definition                                      |
|----------------------|-----------------|--------------------------|-------------|-------------------------------------------------|
| AES-128 Counter Mode | `&quot;aes-128-ctr&quot;` | &lt;ul&gt;&lt;li&gt;`&quot;iv&quot;`&lt;/li&gt;&lt;/ul&gt; |             | [RFC 3686](https://www.rfc-editor.org/rfc/rfc3686) |

### Description

This field is an optional field to help explain the purpose and identify a particular keystores in a user-friendly manner. While this field can, and should, be used to help distinguish keystores from one-another, the `description` **is not necessarily unique**.

### PubKey

The `pubkey` is the public key associated with the private key secured within the keystore. It is stored here to improve user experience and security which is achieved by not requiring users to enter their password just to obtain their public keys. This field is required if the secret being stored within the keystore is a private key. The encoding of the `pubkey` is specified in the in the appropriate signature standard (eg. [ERC-2333](/EIPs/EIPS/eip-2333)), but can be seen as a byte-string in the abstract and should be directly compatible with the appropriate signature library.

### Path

The `path` indicates where in the key-tree a key originates from. It is a string defined by [ERC-2334](/EIPs/EIPS/eip-2334), if no path is known or the path is not relevant, the empty string, `&quot;&quot;` indicates this. The `path` can specify an arbitrary depth within the tree and the deepest node within the tree indicates the depth of the key stored within this file.

### UUID

The `uuid` provided in the keystore is a randomly generated UUID as specified by [RFC 4122](https://www.rfc-editor.org/rfc/rfc4122). It is used as a 128-bit proxy for referring to a particular set of keys or account.

### Version

The `version` is set to `4`.

### JSON schema

The keystore, at its core, is constructed with modules which allow for the configuration of the cryptographic constructions used password hashing, password verification and secret decryption. Each module is composed of: `function`, `params`, and `message` which corresponds with which construction is to be used, what the configuration for the construction is, and what the input is.

```json
{
    &quot;$ref&quot;: &quot;#/definitions/Keystore&quot;,
    &quot;definitions&quot;: {
        &quot;Keystore&quot;: {
            &quot;type&quot;: &quot;object&quot;,
            &quot;properties&quot;: {
                &quot;crypto&quot;: {
                    &quot;type&quot;: &quot;object&quot;,
                    &quot;properties&quot;: {
                        &quot;kdf&quot;: {
                            &quot;$ref&quot;: &quot;#/definitions/Module&quot;
                        },
                        &quot;checksum&quot;: {
                            &quot;$ref&quot;: &quot;#/definitions/Module&quot;
                        },
                        &quot;cipher&quot;: {
                            &quot;$ref&quot;: &quot;#/definitions/Module&quot;
                        }
                    }
                },
                &quot;description&quot;: {
                    &quot;type&quot;: &quot;string&quot;
                },
                &quot;pubkey&quot;: {
                    &quot;type&quot;: &quot;string&quot;
                },
                &quot;path&quot;: {
                    &quot;type&quot;: &quot;string&quot;
                },
                &quot;uuid&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;format&quot;: &quot;uuid&quot;
                },
                &quot;version&quot;: {
                    &quot;type&quot;: &quot;integer&quot;
                }
            },
            &quot;required&quot;: [
                &quot;crypto&quot;,
                &quot;path&quot;,
                &quot;uuid&quot;,
                &quot;version&quot;
            ],
            &quot;title&quot;: &quot;Keystore&quot;
        },
        &quot;Module&quot;: {
            &quot;type&quot;: &quot;object&quot;,
            &quot;properties&quot;: {
                &quot;function&quot;: {
                    &quot;type&quot;: &quot;string&quot;
                },
                &quot;params&quot;: {
                    &quot;type&quot;: &quot;object&quot;
                },
                &quot;message&quot;: {
                    &quot;type&quot;: &quot;string&quot;
                }
            },
            &quot;required&quot;: [
                &quot;function&quot;,
                &quot;message&quot;,
                &quot;params&quot;
            ]
        }
    }
}
```

## Security Considerations

None.

## Rationale

The rationale behind the design of this specification is largely the same as that behind the Ethereum Web3 Secret Storage Definition except for the lack of support for Keccak (explained in [motivation above](#motivation)) and the notion of modules.

Modules provide a very useful level of abstraction which allow the Key-Derivation-Function, Checksum, and Cipher to be thought of as instances of the same thing allowing for their substitution with minimal effort.

The `version` is set to 4 to prevent collisions with the existing Ethereum keystore standard.

## Backwards Compatibility

This specification is not backwards compatible with the Ethereum Web3 Secret Storage Definition due to the lack of Keccak256 checksums as explained above. While this format is capable of supporting Keccak checksums via the Checksum module, it would defeat the purpose of this standard to include it as this standard could no longer be considered neutral with respect to other projects in the industry.

## Test Cases

### Scrypt Test Vector

Password `&quot;𝔱𝔢𝔰𝔱𝔭𝔞𝔰𝔰𝔴𝔬𝔯𝔡🔑&quot;`
Encoded Password: `0x7465737470617373776f7264f09f9491`
Secret `0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f`

```json
{
    &quot;crypto&quot;: {
        &quot;kdf&quot;: {
            &quot;function&quot;: &quot;scrypt&quot;,
            &quot;params&quot;: {
                &quot;dklen&quot;: 32,
                &quot;n&quot;: 262144,
                &quot;p&quot;: 1,
                &quot;r&quot;: 8,
                &quot;salt&quot;: &quot;d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3&quot;
            },
            &quot;message&quot;: &quot;&quot;
        },
        &quot;checksum&quot;: {
            &quot;function&quot;: &quot;sha256&quot;,
            &quot;params&quot;: {},
            &quot;message&quot;: &quot;d2217fe5f3e9a1e34581ef8a78f7c9928e436d36dacc5e846690a5581e8ea484&quot;
        },
        &quot;cipher&quot;: {
            &quot;function&quot;: &quot;aes-128-ctr&quot;,
            &quot;params&quot;: {
                &quot;iv&quot;: &quot;264daa3f303d7259501c93d997d84fe6&quot;
            },
            &quot;message&quot;: &quot;06ae90d55fe0a6e9c5c3bc5b170827b2e5cce3929ed3f116c2811e6366dfe20f&quot;
        }
    },
    &quot;description&quot;: &quot;This is a test keystore that uses scrypt to secure the secret.&quot;,
    &quot;pubkey&quot;: &quot;9612d7a727c9d0a22e185a1c768478dfe919cada9266988cb32359c11f2b7b27f4ae4040902382ae2910c15e2b420d07&quot;,
    &quot;path&quot;: &quot;m/12381/60/3141592653/589793238&quot;,
    &quot;uuid&quot;: &quot;1d85ae20-35c5-4611-98e8-aa14a633906f&quot;,
    &quot;version&quot;: 4
}
```

### PBKDF2 Test Vector

Password `&quot;𝔱𝔢𝔰𝔱𝔭𝔞𝔰𝔰𝔴𝔬𝔯𝔡🔑&quot;`
Encoded Password: `0x7465737470617373776f7264f09f9491`
Secret `0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f`

```json
{
    &quot;crypto&quot;: {
        &quot;kdf&quot;: {
            &quot;function&quot;: &quot;pbkdf2&quot;,
            &quot;params&quot;: {
                &quot;dklen&quot;: 32,
                &quot;c&quot;: 262144,
                &quot;prf&quot;: &quot;hmac-sha256&quot;,
                &quot;salt&quot;: &quot;d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3&quot;
            },
            &quot;message&quot;: &quot;&quot;
        },
        &quot;checksum&quot;: {
            &quot;function&quot;: &quot;sha256&quot;,
            &quot;params&quot;: {},
            &quot;message&quot;: &quot;8a9f5d9912ed7e75ea794bc5a89bca5f193721d30868ade6f73043c6ea6febf1&quot;
        },
        &quot;cipher&quot;: {
            &quot;function&quot;: &quot;aes-128-ctr&quot;,
            &quot;params&quot;: {
                &quot;iv&quot;: &quot;264daa3f303d7259501c93d997d84fe6&quot;
            },
            &quot;message&quot;: &quot;cee03fde2af33149775b7223e7845e4fb2c8ae1792e5f99fe9ecf474cc8c16ad&quot;
        }
    },
    &quot;description&quot;: &quot;This is a test keystore that uses PBKDF2 to secure the secret.&quot;,
    &quot;pubkey&quot;: &quot;9612d7a727c9d0a22e185a1c768478dfe919cada9266988cb32359c11f2b7b27f4ae4040902382ae2910c15e2b420d07&quot;,
    &quot;path&quot;: &quot;m/12381/60/0/0&quot;,
    &quot;uuid&quot;: &quot;64625def-3331-4eea-ab6f-782f3ed16a83&quot;,
    &quot;version&quot;: 4
}
```

## Security Considerations

None.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 30 Sep 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2335</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2335</guid>
      </item>
    
      <item>
        <title>eth/64: forkid-extended protocol handshake</title>
        <category>Standards Track/Networking</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2365</comments>
        
        <description>## Abstract

This EIP specifies the inclusion of the `forkid`, originally defined in [(EIP-2124)](/EIPs/EIPS/eip-2124), as a new field in the Ethereum wire protocol (`eth`) handshake. This change is implemented as a new version of the wire protocol, `eth/64`.

## Motivation

The [`forkid` (EIP-2124)](/EIPs/EIPS/eip-2124) was designed to permit two Ethereum nodes to quickly and cheaply decide if they are compatible or not, not only at a genesis/networking level, but also from the perspective of the currently passed network updates (i.e. forks).

[EIP-2124](/EIPs/EIPS/eip-2124) only defines how the `forkid` is calculated and validated, but does not specify how the `forkid` should be exchanged between peers. This EIP specifies the inclusion of the `forkid` as a new field in the Ethereum wire protocol (`eth`) handshake (releasing a new version, `eth/64`).

By cross-validating `forkid` during the handshake, incompatible nodes can disconnect before expensive block exchanges and validations take place (PoW check, EVM execution, state reconstruction). This further prevents peer slots from being taken up by nodes that are incompatible, but have not yet been detected as such.

From a micro perspective, cutting off incompatible nodes from one another ensures that a node only spends its resources on tasks that are genuinely useful to it. The sooner we can decide the remote peer is useless, the less time and processing we expend in vain.

From a macro perspective, keeping incompatible nodes partitioned from one another ensures that disjoint clusters retain more resources for maintaining their own chain, thus raising the quality of service for all networks globally.

## Specification

- Implement `forkid` generation and validation per [EIP-2124](/EIPs/EIPS/eip-2124).
- Advertise a new `eth` protocol capability (version) at `eth/64`.
  - The old `eth/63` protocol should still be kept alive side-by-side, until `eth/64` is sufficiently adopted by implementors.
- Redefine `Status (0x00)` for `eth/64` to add a trailing `forkid` field:
  - Old packet: `[protocolVersion, networkId, td, bestHash, genesisHash]`
  - New packet: `[protocolVersion, networkId, td, bestHash, genesisHash, forkid]`,
  where `forkid` is `[forkHash: [4]byte, forkNext: uint64]` (fields per [EIP-2124](/EIPs/EIPS/eip-2124) ).

Whenever two peers connect using the `eth/64` protocol, the updated `Status` message must be sent as the protocol handshake, and each peer must validate the remote `forkid`, disconnecting at a detected incompatibility.

## Rationale

The specification is tiny since most parts are already specified in EIP-2124. `eth/63` is not specified as an EIP, but is maintained in the [ethereum/devp2p](https://github.com/ethereum/devp2p) Github repository.

### EIP-2124 mentions advertising the `forkid` in the discovery protocol too. How does that compare to advertising in the `eth` protocol? Why is the redundancy needed?

Advertising and validating the `forkid` in the discovery protocol is a more optimal solution, as it can help avoid the cost of setting up the TCP connection and cryptographic RLPx stream, only to be torn down if `eth/64` rejects it.

Compared to the `eth` protocol however, discovery is a bit fuzzy. The goal there is to suggest potential peers, not to be fool-proof. Information may be outdated, nodes may have changed or disappeared. Discovery can do a rough filtering, but more precision is still needed afterwards.

Additionally, `forkid` validation via the discovery protocol requires ENR implementation ([EIP-778](/EIPs/EIPS/eip-778)) and ENR extension support ([EIP-868](/EIPs/EIPS/eip-868)), which is not mandated by the Ethereum network currently. Lastly, the discovery protocol is just one way to find peers, but systems that cannot use UDP or that rely on other mechanism (e.g. DNS discovery)) still need a way to filter connections.

### The `forkid` implicitly contains the genesis hash checksummed into the `FORK_HASH` field. Why doesn&apos;t this proposal remove the `genesisHash` field from the `eth` handshake?

Originally this EIP did remove it as redundant data, since filtering based on the `forkid` is a superset of filtering based on genesis hash. The reason for backing out of that decision was that the genesis hash may be useful for other things too, not just connection filtering (network crawlers use it currently to split nodes across networks).

Although the `forkid` will hopefully take over all the roles of the genesis hash currently in use, there&apos;s no reason to be overly aggressive in deduplicating data. It&apos;s fine to keep both side-by-side for now, and remove in a future version when 3rd party infrastructures switch over.

## Backwards Compatibility

This EIP extends the `eth` protocol handshake in a backwards incompatible way and requires rolling out a new version, `eth/64`. However, `devp2p` supports running multiple versions of the same wire protocol side-by-side, so rolling out `eth/64` does not require client coordination, since non-updated clients can keep using `eth/63`.

This EIP does not change the consensus engine, thus does _not_ require a hard fork.

## Test Cases

For calculating and validating fork IDs, see test cases in [EIP-2124](/EIPs/EIPS/eip-2124).

## Security Considerations

None.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 08 Nov 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2364</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2364</guid>
      </item>
    
      <item>
        <title>EIPs Eligible for Inclusion</title>
        <category>Meta/</category>
        
          <comments>https://gitter.im/ethereum/EIPs</comments>
        
        <description>## Simple Summary

As part of an EIP centric forking model, this EIP tracks the first step in the approval process for any EIP to be included in a fork or upgrade. Specifically, the stage where the Core Developers vet the concept of an EIP and give a &quot;green light&quot; sufficient for EIP authors to move forward in development.

## Abstract

The pipeline for Core EIPs, per the EIP-Centric upgrade model, is as follows.
```
[ DRAFT ] -&gt; [ ELLIGLE FOR INCLUSION ] -&gt; [ IMPLEMENTATION ] -&gt; [ TESTING ] -&gt; [ ACCEPTED ] -&gt; [ DEPLOYED ]
```

This EIP documents all EIPs marked as **Eligible For Inclusion** by the All Core Devs. Typically to reach this stage, an EIP must be discussed in brief on an AllCoreDevs Call and motioned by rough consenses to be moved to this stage. Any additions to this list are required to provide a link to the meeting notes when this discussion and decision took place.

The requirements for **Eligible for Inclusion** is that the AllCoreDevs, representing the major clients and ecosystem stakeholders etc:

 - Are positive towards the EIP,
 - Would accept (well written) PRs to include the EIP into the codebase.
    - So that it could be toggled on for testing…
    - …but not with an actual block number for activation

## Motivation

Development of clear specifications and pull requests to existing Ethereum Clients is a large investment of time and resources. The state of *Eligible for Inclusion* is a signal from the Ethereum Core Developers to an EIP Author validiating the idea behind an EIP and  confirms investing their time further pursing it is worthwhile.

## Specification

| EIP      | Title                              | Pipeline Status | Date of Initial Decision | REF |
| -------- | ----------------------------------------------------- | -------- | ---------- | ---- | 
| EIP-663  | Unlimited SWAP and DUP instructions                   | ELIGIBLE | 2019-11-01 | [🔗](https://github.com/ethereum/pm/blob/master/AllCoreDevs-EL-Meetings/Meeting%2074.md) |
| EIP-1057  | ProgPoW, a Programmatic Proof-of-Work                   | ELIGIBLE | 2019-11-01 | [🔗](https://github.com/ethereum/pm/blob/master/AllCoreDevs-EL-Meetings/Meeting%2074.md) |
| EIP-1380 | Reduced gas cost for call to self                     | ELIGIBLE | 2019-11-01 | [🔗](https://github.com/ethereum/pm/blob/master/AllCoreDevs-EL-Meetings/Meeting%2074.md) |
| EIP-1559 | Fee market change for ETH 1.0 chain                   | ELIGIBLE | 2019-11-01 | [🔗](https://github.com/ethereum/pm/blob/master/AllCoreDevs-EL-Meetings/Meeting%2074.md) |
| EIP-1702 | Generalized Account Versioning Scheme                 | ELIGIBLE | 2019-11-01 | [🔗](https://github.com/ethereum/pm/blob/master/AllCoreDevs-EL-Meetings/Meeting%2074.md) |
| EIP-1962 | EC arithmetic and pairings with runtime definitions   | ELIGIBLE | 2019-11-01 | [🔗](https://github.com/ethereum/pm/blob/master/AllCoreDevs-EL-Meetings/Meeting%2074.md) |
| EIP-1985 | Sane limits for certain EVM parameters                | ELIGIBLE | 2019-11-01 | [🔗](https://github.com/ethereum/pm/blob/master/AllCoreDevs-EL-Meetings/Meeting%2074.md) |
| EIP-2046 | Reduced gas cost for static calls made to precompiles | ELIGIBLE | 2019-11-01 | [🔗](https://github.com/ethereum/pm/blob/master/AllCoreDevs-EL-Meetings/Meeting%2074.md) |
| EIP-2315 | Simple Subroutines for the EVM                        | ELIGIBLE | 2020-02-21 | [🔗](https://github.com/ethereum/pm/blob/master/All%20Core%20Devs%20Meetings/Meeting%2081.md#decisions) |
| EIP-2537 | Precompile for BLS12-381 curve operations             | ELIGIBLE | 2020-03-06 | [🔗](https://github.com/ethereum/pm/blob/master/All%20Core%20Devs%20Meetings/Meeting%2082.md) |

## Rationale

**EIP Number**

**Title**

**Pipeline Status** : Show the current status in the context of the EIP centric model. The list is sorted by furthest along in the process.

**Date of Initial Decision** : Date of the initial decision for Eligibility for Inclusion

**REF** : Link to the decision on the AllCoreDevs Notes


## References

 - EIP Centric Forking Model Proposal by @holiman - https://notes.ethereum.org/@holiman/S1ELAYY7S?type=view



## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 13 Nov 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2378</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2378</guid>
      </item>
    
      <item>
        <title>Muir Glacier Difficulty Bomb Delay</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2384-difficulty-bomb-delay</comments>
        
        <description>## Simple Summary
The average block times are increasing due to the difficulty bomb (also known as the &quot;_ice age_&quot;) and slowly accelerating. This EIP proposes to delay the difficulty bomb for another 4,000,000 blocks (~611 days).

## Abstract
Starting with `MUIR_GLACIER_FORK_BLKNUM` the client will calculate the difficulty based on a fake block number suggesting to the client that the difficulty bomb is adjusting 9 million blocks later than the Homestead fork, which is also 7 million blocks later than the Byzantium fork and 4 million blocks later than the Constantinople fork.

## Motivation
The difficulty bomb started to become noticeable again on October 5th 2019 at block 8,600,000. Block times have been around 13.1s on average and now as of block 8,900,000 are around 14.3s. This will start to accelerate exponentially every 100,000 blocks. Estimating the added impact from the difficulty bomb on block times shows that we will see 20s block times near the end of December 2019 and 30s+ block times starting February 2020. This will start making the chain bloated and more costly to use. It&apos;s best to delay the difficulty bomb again to around the time of expected launch of the Eth2 finality gadget.

## Specification
#### Relax Difficulty with Fake Block Number
For the purposes of `calc_difficulty`, simply replace the use of `block.number`, as used in the exponential ice age component, with the formula:

    fake_block_number = max(0, block.number - 9_000_000) if block.number &gt;= MUIR_GLACIER_FORK_BLKNUM else block.number

## Rationale
This will delay the ice age by 52 million seconds (approximately 611 days), so the chain would be back at 20 second block times around July 2021. It&apos;s important to note this pushes the ice age 4,000,000 blocks from ~block 8,800,000 NOT from when this EIP is activated in a fork.

## Backwards Compatibility
This EIP is not forward compatible and introduces backwards incompatibilities in the difficulty calculation. Therefore, it should be included in a scheduled hardfork at a certain block number. It&apos;s suggested to include this EIP shortly after the Istanbul fork.

## Test Cases
Test cases shall be created once the specification is to be accepted by the developers or implemented by the clients.

## Implementation
The implementation in it&apos;s logic does not differ from [EIP-649](/EIPs/EIPS/eip-649) or [EIP-1234](/EIPs/EIPS/eip-1234); an implementation for Parity-Ethereum is available in [parity-ethereum#9187](https://github.com/paritytech/parity-ethereum/pull/9187).

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 20 Nov 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2384</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2384</guid>
      </item>
    
      <item>
        <title>Ethereum 2 Hierarchical Deterministic Walletstore</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2386-walletstore/3792</comments>
        
        <description>## Simple Summary

A JSON format for the storage and retrieval of Ethereum 2 hierarchical deterministic (HD) wallet definitions.

## Abstract

Ethereum has the concept of keystores: pieces of data that define a key (see [EIP-2335](https://eips.ethereum.org/EIPS/eip-2335) for details).  This adds the concept of walletstores: stores that define wallets and how keys in said wallets are created.

## Motivation

Hierarchical deterministic wallets create keys from a _seed_ and a _path_.  The seed needs to be accessible to create new keys, however it should also be protected to the same extent as private keys to stop it from becoming an easy attack vector.  The path, or at least the variable part of it, needs to be stored to ensure that keys are not duplicated.  Providing a standard method to do this can promote interoperability between wallets and similar software.

Given that a wallet has an amount of data and metadata that is useful when accessing existing keys and creating new keys, standardizing this information and how it is stored allows it to be portable between different wallet providers with minimal effort.

## Specification

The elements of a hierarchical deterministic walletstore are as follows:

### UUID

The `uuid` provided in the walletstore is a randomly-generated type 4 UUID as specified by [RFC 4122](https://tools.ietf.org/html/rfc4122). It is intended to be used as a 128-bit proxy for referring to a particular wallet, used to uniquely identify wallets.

This element MUST be present.  It MUST be a string following the syntactic structure as laid out in [section 3 of RFC 4122](https://tools.ietf.org/html/rfc4122#section-3).

### Name

The `name` provided in the walletstore is a UTF-8 string.  It is intended to serve as the user-friendly accessor.  The only restriction on the name is that it MUST NOT start with the underscore (`_`) character.

This element MUST be present.  It MUST be a string.

### Version

The `version` provided is the version of the walletstore.

This element MUST be present.  It MUST be the integer `1`.

### Type

The `type` provided is the type of wallet.  This informs mechanisms such as key generation.

This element MUST be present.  It MUST be the string `hierarchical deterministic`.

### Crypto

The `crypto` provided is the secure storage of a secret for wallets that require this information.  For hierarchical deterministic wallets this is the seed from which they calculate individual private keys.

This element MUST be present.  It MUST be an object that follows the definition described in [EIP-2335](https://eips.ethereum.org/EIPS/eip-2335).

### Next Account

The `nextaccount` provided is the index to be supplied to the path `m/12381/60/&lt;index&gt;/0` when creating a new private key from the seed.  The path follows [EIP-2334](https://eips.ethereum.org/EIPS/eip-2334).

This element MUST be present if the wallet type requires it.  It MUST be a non-negative integer.

### JSON schema

The walletstore follows a similar format to that of the keystore described in [EIP-2335](https://eips.ethereum.org/EIPS/eip-2335).

```json
{
    &quot;$ref&quot;: &quot;#/definitions/Walletstore&quot;,
    &quot;definitions&quot;: {
        &quot;Walletstore&quot;: {
            &quot;type&quot;: &quot;object&quot;,
            &quot;properties&quot;: {
                &quot;crypto&quot;: {
                    &quot;type&quot;: &quot;object&quot;,
                    &quot;properties&quot;: {
                        &quot;kdf&quot;: {
                            &quot;$ref&quot;: &quot;#/definitions/Module&quot;
                        },
                        &quot;checksum&quot;: {
                            &quot;$ref&quot;: &quot;#/definitions/Module&quot;
                        },
                        &quot;cipher&quot;: {
                            &quot;$ref&quot;: &quot;#/definitions/Module&quot;
                        }
                    }
                },
                &quot;name&quot;: {
                    &quot;type&quot;: &quot;string&quot;
                },
                &quot;nextaccount&quot;: {
                    &quot;type&quot;: &quot;integer&quot;
                },
                &quot;type&quot;: {
                    &quot;type&quot;: &quot;string&quot;
                },
                &quot;uuid&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;format&quot;: &quot;uuid&quot;
                },
                &quot;version&quot;: {
                    &quot;type&quot;: &quot;integer&quot;
                }
            },
            &quot;required&quot;: [
                &quot;name&quot;,
                &quot;type&quot;,
                &quot;uuid&quot;,
                &quot;version&quot;
                &quot;crypto&quot;
                &quot;nextaccount&quot;
            ],
            &quot;title&quot;: &quot;Walletstore&quot;
        },
        &quot;Module&quot;: {
            &quot;type&quot;: &quot;object&quot;,
            &quot;properties&quot;: {
                &quot;function&quot;: {
                    &quot;type&quot;: &quot;string&quot;
                },
                &quot;params&quot;: {
                    &quot;type&quot;: &quot;object&quot;
                },
                &quot;message&quot;: {
                    &quot;type&quot;: &quot;string&quot;
                }
            },
            &quot;required&quot;: [
                &quot;function&quot;,
                &quot;message&quot;,
                &quot;params&quot;
            ]
        }
    }
}
```

## Rationale

A standard for walletstores, similar to that for keystores, provides a higher level of compatibility between wallets and allows for simpler wallet and key interchange between them.

## Test Cases

### Test Vector

Password `&apos;testpassword&apos;`
Seed `0x147addc7ec981eb2715a22603813271cce540e0b7f577126011eb06249d9227c`

```json
{
  &quot;crypto&quot;: {
    &quot;checksum&quot;: {
      &quot;function&quot;: &quot;sha256&quot;,
      &quot;message&quot;: &quot;8bdadea203eeaf8f23c96137af176ded4b098773410634727bd81c4e8f7f1021&quot;,
      &quot;params&quot;: {}
    },
    &quot;cipher&quot;: {
      &quot;function&quot;: &quot;aes-128-ctr&quot;,
      &quot;message&quot;: &quot;7f8211b88dfb8694bac7de3fa32f5f84d0a30f15563358133cda3b287e0f3f4a&quot;,
      &quot;params&quot;: {
        &quot;iv&quot;: &quot;9476702ab99beff3e8012eff49ffb60d&quot;
      }
    },
    &quot;kdf&quot;: {
      &quot;function&quot;: &quot;pbkdf2&quot;,
      &quot;message&quot;: &quot;&quot;,
      &quot;params&quot;: {
        &quot;c&quot;: 16,
        &quot;dklen&quot;: 32,
        &quot;prf&quot;: &quot;hmac-sha256&quot;,
        &quot;salt&quot;: &quot;dd35b0c08ebb672fe18832120a55cb8098f428306bf5820f5486b514f61eb712&quot;
      }
    }
  },
  &quot;name&quot;: &quot;Test wallet 2&quot;,
  &quot;nextaccount&quot;: 0,
  &quot;type&quot;: &quot;hierarchical deterministic&quot;,
  &quot;uuid&quot;: &quot;b74559b8-ed56-4841-b25c-dba1b7c9d9d5&quot;,
  &quot;version&quot;: 1
}
```

## Implementation

A Go implementation of the hierarchical deterministic wallet can be found at [https://github.com/wealdtech/go-eth2-wallet-hd](https://github.com/wealdtech/go-eth2-wallet-hd).

## Security Considerations

The seed stored in the `crypto` section of the wallet can be used to generate any key along the derived path.  As such, the security of all keys generated by HD wallets is reduced to the security of the passphrase and strength of the encryption used to protect the seed, regardless of the security of the passphrase and strength of the encryption used to protect individual keystores.

It is possible to work with only the walletstore plus an index for each key, in which case stronger passphrases can be used as decryption only needs to take place once.  It is also possible to use generated keystores without the walletstore, in which case a breach of security will expose only the keystore.

An example high-security configuration may involve the walletstore existing on an offline computer, from which keystores are generated.  The keystores can then be moved individually to an online computer to be used for signing.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 21 Nov 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2386</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2386</guid>
      </item>
    
      <item>
        <title>Hardfork Meta: Muir Glacier</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/hard-fork-to-address-the-ice-age-eip-2387</comments>
        
        <description>## Abstract

This meta-EIP specifies the changes included in the Ethereum hard fork named Muir Glacier. This hard fork addresses the impending Ice Age on Ethereum Mainnet and includes a commitment to solving the problems with the ice age more permanently.

## Motivation

Ethereum achieves a consistent block time due to its&apos; difficulty retargeting algorithm. If a block-time is higher than 20 seconds, it reduces the difficulty, and if a block time is lower than 10 seconds, it increases the difficulty. This mechanism reaches typically an equilibrium of around 13-14 seconds. Included within this mechanism is something we refer to as the Difficulty Bomb or the Ice Age. It artificially adds to the difficulty in such a way that the retargeting mechanism, at some point, can not adapt to the increase, and we see increased block times throughout the network. The ice age increments every 100,000 blocks. It at first is barely noticeable, but once it is visible, there is a drastic effect on block-times in the network.

The primary problem with the Ice Age is that it is included in the complex mechanism that targets block times, which is an entirely separate in purpose. What is worse is due to being intwined with that algorithm, it is very difficult to simulate or predict its effect on the network. To predict the impact of the ice age, you must both make assumptions about the difficulty of main-net in the future, and predict the effect of changes in difficulty to the impact on the ice age and thus block-times.

This fork will push back the Iceage as far as far as is reasonable and will give us time to update the Iceage to no longer have these design problems. There are two solutions to consider within that time frame.

 - Update the mechanism so that behavior is predictable.
 - Remove the Iceage entirely

## Specification

- Codename: Muir Glacier

### Activation
  - `Block &gt;= 9,200,000` on the Ethereum mainnet
  - `Block &gt;= 7,117,117` on the Ropsten testnet
  - `Block &gt;= N/A` on the Kovan testnet
  - `Block &gt;= N/A` on the Rinkeby testnet
  - `Block &gt;= N/A` on the Görli testnet

### Included EIPs
  - [EIP-2384](/EIPs/EIPS/eip-2384): Istanbul/Berlin Difficulty Bomb Delay

## Rationale

I want to address the rationale for the intention of the Iceage and the implementation of the Iceage separately.

**The original intentions of the ice age include:** 

 - At the time of upgrades, inhibit unintentional growth of the resulting branching forks leading up to Eth 2.0. *
 - Encourage a prompt upgrade schedule for the path to Eth 2.0. *
 - Forces the community to come back into agreement repeatedly...and it gives whatever portion of the community that wants to a chance to fork off
 - Is a check for the Core Devs in the case that a decision is made to freeze the code base of clients without the blessing of the community.

*Note: None of these effects the Freedom to Fork. They are meant to encourage core-devs and the community to upgrade along with the network and prevent the case where sleeper forks remain dormant only later to be resurrected. The requirement for an active fork is to change a client in a way to respond to the ice age. This is in fact what Ethereum Classic has done.

This is not meant to be exhaustive, but the ideas above capture much of what has been written on the original intentions and process of creating the fork. Any additions to this list that need to be made, I am happy to include. Regardless, to effectively implement an updated design for the ice age, all of the intentions need to be revisited and clarified as part of any updates. This clarification will give a clear expectation for the community and core developers moving forward.

**The implementation**

The existing implementation of the ice age, while it does work in practice, is unnecessarily complex to model and confusing to communicate to the community. Any updates to the design should be: 

 - Easy to model the effect on the network
 - Easy to predict when it occurs

This fork would give us time to address the community to understand their priorities better as far as the intentions of the Ice Age, and give time for proposals for better mechanisms to achieve those goals.

### POA Testnets

Muir Glacier never activates on PoA chains – thus will have zero impact on [forkid](/EIPs/EIPS/eip-2124).

### Note on Issuance Reduction

Previous Hardforks to address the Ice Age have also included reductions in the block reward from 5 Eth to 3 Eth to 2 Eth, respectively. In this case, there is no change in issuance, and the block reward remains 2 Eth per block.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 22 Nov 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2387</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2387</guid>
      </item>
    
      <item>
        <title>Geo-ENS</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2959</comments>
        
        <description>## Simple Summary
GeoENS brings geographic split horizon capabilities to ENS. It&apos;s GeoDNS for ENS!

## Abstract
This EIP specifies an ENS resolver interface for geographically split horizon DNS.
Geographic split horizon DNS returns resource records that are specific to an end
user&apos;s location.
This technique is commonly used by CDNs to direct traffic to content caches nearest users.
Geographic split horizon resolution is primarily geared towards ENS
resolvers storing DNS resource records [EIP-1185](/EIPs/EIPS/eip-1185), although the technique could be
used on other interfaces like IPFS content hash storage [EIP-1062](/EIPs/EIPS/eip-1062).

## Motivation
There are many use cases for traditional GeoDNS systems, like Amazon&apos;s Route53,
in the centralized web.
These use cases include proximity-based load balancing and serving content
specific to the geographic location of the query.
Unfortunately the ENS specification does not provide a mechanism for
geo-specific resolution.
ENS can respond to queries with IP addresses (as described in [EIP-1185](/EIPs/EIPS/eip-1185))
however there is no way to respond to geo-specific queries.
This EIP proposes a standard to give the ENS system geo-proximal awareness
to serve a similar purpose as GeoDNS.

GeoENS can do more than DNS-based solutions.
In addition to geographic split horizon DNS, GeoENS can be used for the following:
 - Locating digital resources (like smart contracts) that represent physical objects in the real world.
 - Smart contract managing access to a physical object associated with a specific location.
 - ENS + IPFS web hosting (as described in [EIP-1062](/EIPs/EIPS/eip-1062)) with content translated to the native language of the query source.
 - Tokenizing objects with a physical location.

Because of the decentralized nature of ENS, geo-specific resolution is different than traditional GeoDNS.
GeoDNS works as follows. DNS queries are identified by their source IP address.
This IP is looked up in a database like [GeoIP2](https://www.maxmind.com/en/geoip2-services-and-databases)
from MaxMind which maps the IP address to a location.
This method of locating the source of a query is error prone and unreliable.
If the GeoIP database is out of date, queried locations can be vastly different than their true location.
GeoENS does not rely on a database because the user includes a location in their query.

It follows that queries can be made by users for any location, not just their location.
Traditional DNS will only return the resource assigned to a query&apos;s provenance.
GeoENS does not correlate a query&apos;s provinance with a location, allowing the
entire globe to be queried from a single location.

An additional shortcoming of traditional DNS is the fact that there is no way to return a list of servers in a certain proximity.
This is paramount for uses cases that require discovering the resource with the lowest latency.
GeoENS allows a list of resources, like IP addresses, to be gathered within a specific location.
Then a client to determine themselves which resource has the lowest latency.

Lastly, publicly facing GeoDNS services do not give fine granularity control
over geographic regions for GeoDNS queries.
Cloud based DNS services like [Amazon&apos;s Route 53](https://aws.amazon.com/route53/)
only allow specifying geographic regions at the granularity of a State in
the United States.
GeoENS on the other hand gives 8 characters of geohash resolution which
corresponds to +-20 meter accuracy.

## Specification
This EIP proposes a new interface to ENS resolvers such that geo-spacial information
can be recorded and retrieved from the blockchain.
The interface changes are described below for &quot;address resolvers&quot; described in EIP137
however the idea applies to any record described in EIP1185 and EIP1062, namely DNS
Resolvers, Text Resolvers, ABI Resolvers, etc.

### What is a geohash?
A [Geohash](https://en.m.wikipedia.org/wiki/Geohash#Algorithm_and_example)
is an interleaving of latitude and longitude bits, whose
length determines it&apos;s precision.
Geohashes are typically encoded in base 32 characters.

### function setGeoAddr(bytes32 node, string calldata geohash, address addr) external authorised(node)
Sets a resource (contract address, IP, ABI, TEXT, etc.) by node and geohash.
Geohashes must be unique per address and are exactly 8 characters long.
This leads to an accuracy of +-20 meters.
Write default initialized resource value, `address(0)`, to remove a resource from the resolver.

### function geoAddr(bytes32 node, string calldata geohash) external view returns (address[] memory ret)
Query the resolver contract for a specific node and location.
All resources (contract addresses, IP addresses, ABIs, TEXT records, etc.) matching
the node and prefix geohash provided are returned.
This permits querying by exact geohash of 8 characters to return the content at that location,
or querying by geographic bounding box described by a geohash of less than 8 character precision.

Any type of geohash can be used including [Z-order](https://en.wikipedia.org/wiki/Z-order_curve)
[Hilbert](https://en.wikipedia.org/wiki/Hilbert_curve) or the more accurate
[S2 Geometry](https://s2geometry.io/devguide/s2cell_hierarchy.html) library
from Google.
There are also ways to search the geographic data using geohashes without
always ending up with a rectangular query region.
[Searching circular shaped regions](https://github.com/ashwin711/proximityhash) is
slightly more complex as it requires multiple queries.

## Rationale
The proposed implementation uses a sparse [Quadtree](https://dl.acm.org/doi/10.1007/BF00288933) trie as an index for
resource records as it has low storage overhead and good search performance.
The leaf nodes of the tree store resource records while non-leaves represent one geohash character.
Each node in the tree at depth d corresponds to a geohash of precision d.
The tree has depth 8 because the maximum precision of a geohash is 8 characters.
The tree has fanout 32 because the radix of a geohash character is 32.
The path to get to a leaf node always has depth 8 and the leaf contains the content (like IP address)
of the geohash represented by the path to the leaf.
The tree is sparse as 71% of the Earth&apos;s surface is covered by water.
The tree facilitates common traversal algorithms (DFS, BFS) to return
lists of resource records within a geographic bounding box.

## Backwards Compatibility
This EIP does not introduce issues with backwards compatibility.

## Test Cases
See https://github.com/james-choncholas/resolvers/blob/master/test/TestPublicResolver.js

## Implementation
This address resolver, written in Solidity, implements the specifications outlined above.
The same idea presented here can be applied to other resolver interfaces as specified in EIP137.
Note that geohashes are passed and stored using 64 bit unsigned integers.
Using integers instead of strings for geohashes is more performant, especially in the `geomap` mapping.
For comparison purposes, see https://github.com/james-choncholas/geoens/tree/master/contracts/StringOwnedGeoENSResolver.sol for the inefficient string implementation.


```solidity
pragma solidity ^0.5.0;

import &quot;../ResolverBase.sol&quot;;

contract GeoENSResolver is ResolverBase {
    bytes4 constant ERC2390 = 0x8fbcc5ce;
    uint constant MAX_ADDR_RETURNS = 64;
    uint constant TREE_VISITATION_QUEUESZ = 64;
    uint8 constant ASCII_0 = 48;
    uint8 constant ASCII_9 = 57;
    uint8 constant ASCII_a = 97;
    uint8 constant ASCII_b = 98;
    uint8 constant ASCII_i = 105;
    uint8 constant ASCII_l = 108;
    uint8 constant ASCII_o = 111;
    uint8 constant ASCII_z = 122;

    struct Node {
        address data; // 0 if not leaf
        uint256 parent;
        uint256[] children; // always length 32
    }

    // A geohash is 8, base-32 characters.
    // A geomap is stored as tree of fan-out 32 (because
    // geohash is base 32) and height 8 (because geohash
    // length is 8 characters)
    mapping(bytes32=&gt;Node[]) private geomap;

    event GeoENSRecordChanged(bytes32 indexed node, bytes8 geohash, address addr);

    // only 5 bits of ret value are used
    function chartobase32(byte c) pure internal returns (uint8 b) {
        uint8 ascii = uint8(c);
        require( (ascii &gt;= ASCII_0 &amp;&amp; ascii &lt;= ASCII_9) ||
                (ascii &gt; ASCII_a &amp;&amp; ascii &lt;= ASCII_z));
        require(ascii != ASCII_a);
        require(ascii != ASCII_i);
        require(ascii != ASCII_l);
        require(ascii != ASCII_o);

        if (ascii &lt;= (ASCII_0 + 9)) {
            b = ascii - ASCII_0;

        } else {
            // base32 b = 10
            // ascii &apos;b&apos; = 0x60
            // note base32 skips the letter &apos;a&apos;
            b = ascii - ASCII_b + 10;

            // base32 also skips the following letters
            if (ascii &gt; ASCII_i)
                b --;
            if (ascii &gt; ASCII_l)
                b --;
            if (ascii &gt; ASCII_o)
                b --;
        }
        require(b &lt; 32); // base 32 can&apos;t be larger than 32
        return b;
    }

    function geoAddr(bytes32 node, bytes8 geohash, uint8 precision) external view returns (address[] memory ret) {
        bytes32(node); // single node georesolver ignores node
        assert(precision &lt;= geohash.length);

        ret = new address[](MAX_ADDR_RETURNS);
        if (geomap[node].length == 0) { return ret; }
        uint ret_i = 0;

        // walk into the geomap data structure
        uint pointer = 0; // not actual pointer but index into geomap
        for(uint8 i=0; i &lt; precision; i++) {

            uint8 c = chartobase32(geohash[i]);
            uint next = geomap[node][pointer].children[c];
            if (next == 0) {
                // nothing found for this geohash.
                // return early.
                return ret;
            } else {
                pointer = next;
            }
        }

        // pointer is now node representing the resolution of the query geohash.
        // DFS until all addresses found or ret[] is full.
        // Do not use recursion because blockchain...
        uint[] memory indexes_to_visit = new uint[](TREE_VISITATION_QUEUESZ);
        indexes_to_visit[0] = pointer;
        uint front_i = 0;
        uint back_i = 1;

        while(front_i != back_i) {
            Node memory cur_node = geomap[node][indexes_to_visit[front_i]];
            front_i ++;

            // if not a leaf node...
            if (cur_node.data == address(0)) {
                // visit all the chilins
                for(uint i=0; i&lt;cur_node.children.length; i++) {
                    // only visit valid children
                    if (cur_node.children[i] != 0) {
                        assert(back_i &lt; TREE_VISITATION_QUEUESZ);
                        indexes_to_visit[back_i] = cur_node.children[i];
                        back_i ++;

                    }
                }
            } else {
                ret[ret_i] = cur_node.data;
                ret_i ++;
                if (ret_i &gt; MAX_ADDR_RETURNS) break;
            }
        }

        return ret;
    }

    // when setting, geohash must be precise to 8 digits.
    function setGeoAddr(bytes32 node, bytes8 geohash, address addr) external authorised(node) {
        bytes32(node); // single node georesolver ignores node

        // create root node if not yet created
        if (geomap[node].length == 0) {
            geomap[node].push( Node({
                data: address(0),
                parent: 0,
                children: new uint256[](32)
            }));
        }

        // walk into the geomap data structure
        uint pointer = 0; // not actual pointer but index into geomap
        for(uint i=0; i &lt; geohash.length; i++) {

            uint8 c = chartobase32(geohash[i]);

            if (geomap[node][pointer].children[c] == 0) {
                // nothing found for this geohash.
                // we need to create a path to the leaf
                geomap[node].push( Node({
                    data: address(0),
                    parent: pointer,
                    children: new uint256[](32)
                }));
                geomap[node][pointer].children[c] = geomap[node].length - 1;
            }
            pointer = geomap[node][pointer].children[c];
        }

        Node storage cur_node = geomap[node][pointer]; // storage = get reference
        cur_node.data = addr;

        emit GeoENSRecordChanged(node, geohash, addr);
    }

    function supportsInterface(bytes4 interfaceID) public pure returns (bool) {
        return interfaceID == ERC2390 || super.supportsInterface(interfaceID);
    }
}
```

## Security Considerations
This contract has similar functionality to ENS Resolvers - refer there for security considerations.
Additionally, this contract has a dimension of data privacy.
Users query via the geoAddr function specifying a geohash of less than 8 characters
which defines the query region.
Users who run light clients leak the query region to their connected full-nodes.
Users who rely on nodes run by third parties (like Infura) will also leak
the query region.
Users who run their own full node or have access to a trusted full node do
not leak any location data.

Given the way most location services work, the query region is likely to contain
the user&apos;s actual location.
The difference between API access, light, and full nodes has always had
an impact on privacy but now the impact is underscored by the involvement
of coarse granularity user location.



## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 15 Nov 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2390</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2390</guid>
      </item>
    
      <item>
        <title>Transaction Receipt URI</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2400-transaction-receipt-uri/</comments>
        
        <description>## Abstract

A transaction hash is not very meaningful on its own, because it looks just like any other hash, and it might lack important information for reading a transaction. 

This standard includes all needed information for displaying a transaction and its details, such as `chainId`, `method` signature called, and `events` signatures emitted.

## Motivation

Interoperability between ethereum clients, allowing different systems to agree on a standard way of representing submitted transactions hashes, optionally with necessary information for decoding transaction details.

### Use-cases 

Transaction Receipt URIs embedded in QR-codes, hyperlinks in web-pages, emails or chat messages provide for robust cross-application signaling between very loosely coupled applications. A standardized URI format allows for instant invocation of the user’s preferred transaction explorer application. Such as:

- In web3 (dapps, mining pools, exchanges), links would automatically open user&apos;s preferred transaction explorer; 
- In wallets, for users sharing transaction receipts easier; 
- In chat applications, as a reply to an [EIP-681] transaction request;
- In crypto vending machines, a QRCode can be displayed when transactions are submitted;
- Anywhere transaction receipts are presented to users.

## Specification

### Syntax

Transaction receipt URLs contain &quot;ethereum&quot; in their schema (protocol) part and are constructed as follows:

    receipt                 = schema_part transaction_hash [ &quot;@&quot; chain_id ] [ &quot;?&quot; parameters ]
    schema_part             = &quot;ethereum:tx-&quot; 
    transaction_hash        = &quot;0x&quot; 64*HEXDIG 
    chain_id                = 1*DIGIT
    parameters              = parameter *( &quot;&amp;&quot; parameter )
    parameter               = key &quot;=&quot; value
    key                     = &quot;method&quot; / &quot;events&quot;
    value                   = function_signature / event_list
    function_signature      = function_name &quot;(&quot; TYPE *( &quot;,&quot; TYPE) &quot;)&quot;
    function_name           = STRING
    event_list              = event_signature *( &quot;;&quot; event_signature )
    event_signature         = event_name &quot;(&quot; event_type *( &quot;,&quot; event_type) &quot;)&quot;
    event_name              = STRING
    event_type              = [&quot;!&quot;] TYPE


Where `TYPE` is a standard ABI type name, as defined in Ethereum Contract ABI specification. `STRING` is a URL-encoded unicode string of arbitrary length.

The exclamation symbol (`!`), in `event_type`, is used to identify indexed event parameters. 

### Semantics

`transaction_hash` is mandatory. The hash must be looked up in the corresponding `chain_id` transaction history, if not found it should be looked into the pending transaction queue and rechecked until is found. If not found anequivalent error as &quot;transaction not found error&quot; should be shown instead of the transaction. When the transaction is pending, it should keep checking until the transaction is included in a block and becomes &quot;unrevertable&quot; (usually 12 blocks after transaction is included).


`chain_id` is specified by [EIP-155] optional and contains the decimal chain ID, such that transactions on various test and private networks can be represented as well. If no `chain_id` is present, the $ETH/mainnet (`1`) is considered.

If `method` is not present, this means that the transaction receipt URI does not specify details, or that it was a transaction with no calldata. When present it needs to be validated by comparing the first 4 bytes of transaction calldata with the first 4 bytes of the keccak256 hash of `method`, if invalid, an equivalent error as &quot;method validation error&quot; must be shown instead of the transaction.

If `events` is not present, this means that the transaction receipt URI does not specify details, or that the transaction did not raised any events. Pending and failed transactions don&apos;t validate events, however, when transaction is successful (or changes from pending to success) and events are present in URI, each event in the `event_list` must occur at least once in the transaction receipt event logs, otherwise an equivalent error as &quot;event validation error: {event(s) [$event_signature, ...] not found}&quot; should be shown instead of the transaction. A URI might contain the event signature for all, some or none of the raised events. 

#### Examples

##### Simple ETH transfer: 
`ethereum:tx-0x1143b5e38fe3cf585fb026fb9b5ce35c85a691786397dc8a23a07a62796d8172@1`  

##### Standard Token transfer:

`ethereum:tx-0x5375e805b0c6afa20daab8d37352bf09a533efb03129ba56dee869e2ce4f2f92@1?method=&quot;transfer(address,uint256)&quot;&amp;events=&quot;Transfer(!address,!address,uint256)&quot;` 

##### Complex contract transaction: 

`ethereum:tx-0x4465e7cce3c784f264301bfe26fc17609855305213ec74c716c7561154b76fec@1?method=&quot;issueAndActivateBounty(address,uint256,string,uint256,address,bool,address,uint256)&quot;&amp;events=&quot;Transfer(!address,!address,uint256);BountyIssued(uint256);ContributionAdded(uint256,!address,uint256);BountyActivated(uint256,address)&quot;`  

## Rationale

The goal of this standard envolves only the transport of submitted transactions, and therefore transaction data must be loaded from blockchain or pending transaction queue, which also serves as a validation of the transaction existence. 

Transaction hash not found is normal in fresh transactions, but can also mean that effectively a transaction was never submitted or have been replaced (through &quot;higher gasPrice&quot; nonce override or through an uncle/fork). 

In order to decode transaction parameters and events, a part of the ABI is required. The transaction signer have to know the ABI to sign a transaction, and is also who is creating a transaction receipt, so the transaction receipt can optionally be shared with the information needed to decode the transaction call data and it&apos;s events. 

## Backwards Compatibility

Future upgrades that are partially or fully incompatible with this proposal must use a prefix other than `tx-` that is separated by a dash (-) character from whatever follows it.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[EIP-155]: /EIPs/EIPS/eip-155

[EIP-681]: /EIPs/EIPS/eip-681
</description>
        <pubDate>Tue, 05 Nov 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2400</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2400</guid>
      </item>
    
      <item>
        <title>Updates and Updated-by Header</title>
        <category>Informational/</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2453</comments>
        
        <description>## Simple Summary

Adds EIP header options `updates` and `updated-by` to frontmatter of `active` EIPs for use as needed.

## Abstract

EIP headers `updates` and `updated-by` are used for updating `active` EIPs. This is to make the improvement process of EIPs more modular, and have updates to existing `active` EIPs receive similar exposures to EIPs which replace existing `final` EIPs. 

## Motivation

Currently, EIP1 specifies EIP headers: `updated`, `replaces`, and `superseded-by`. Headers `replaces` and `superseded-by` indicates when an entire EIP is being replaced by another EIP, indicating when an EIP is now historical, and is updated by a new standard. 

The header `updated` indicates the date an EIP has received an update by EIP authors and editors, an example EIP being EIP1. `updated` is reserved for EIPs in `draft` or `active` status. 

In the case of `active` status, an EIP may receive an update, but these updates don&apos;t operate as with EIPs in `final` status, where a historical EIP is created, and the new EIP is referenced by the historical one. While these updates are not kept immutably, updates to active EIPs can be done modularly by creating a new EIP that goes through the standard discussion and auditing process EIPs undergo. The EIP headers `updates` and `updated-by` are to facilitate this modularity. Creating a new EIP also provides sufficient notification to affected stakeholders of an active EIP before that EIP is `updated`. 

## Specification

### `updated-by` 

`updated-by` is reserved for EIPs in `active` status. For an EIP in status `active`, updates to that EIP, which update the header `updated`, should be started by opening a new EIP to start vetting for that update. When an `active` EIP receives a new entry to header `updated`, an associated `updated-by` EIP listing should be included, where that newly listed EIP has reached `final` status.

`updates` should be included as an EIP header, as all EIP headers, and include a reference to an EIP designation. When multiple EIP designations are referenced, each should be separated by a comma. Example:

```
---
updated-by: 9999, 9998, 9997
---
```

### `updates` 

`updates` is reserved for EIPs updating EIPs in `active` status. An EIP listed as `updates` is implied to also be `requires`; only `updates` is needed for those EIP listings. Having an EIP listing `updates` does not necessarily mean that referenced EIP must reference back with an `updated-by` listing.

`updates` should be included as an EIP header, as all EIP headers, and include a reference to an EIP designation. When multiple EIP designations are referenced, each should be separated by a comma. Example:

```
---
updates: 1
---
```

## Rationale

`updates` and `updated-by` apply only to EIPs in `active` status as updates to EIPs in `final` status are already handled by EIP headers `superseded-by` and `replaces`.

The syntax should align with previous EIP header syntax, as this EIP is not updating syntax, simply adding header options.

## Backwards Compatibility

These EIP headers are optional and do not introduce compatibility issues.


## Implementation

An implementation is adding a header option. 

## Security Considerations

This standard is informational and does not introduce technical security issues.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).


</description>
        <pubDate>Mon, 06 Jan 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2458</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2458</guid>
      </item>
    
      <item>
        <title>eth/65: transaction announcements and retrievals</title>
        <category>Standards Track/Networking</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2465</comments>
        
        <description>## Abstract

This EIP introduces three additional message types into the `eth` protocol (releasing a new version, `eth/65`): `NewPooledTransactionHashes (0x08)` to announce a set of transactions without their content; `GetPooledTransactions (0x09)` to request a batch of transactions by their announced hash; and `PooledTransactions (0x0a)` to reply to a transaction request. This permits reducing the bandwidth used for transaction propagation from linear complexity in the number of peers to square root; and also reducing the initial transaction exchange from 10s-100s MB to `len(pool) * 32B ~= 128KB`.

## Motivation

The `eth` network protocol has two ways to propagate a newly mined block: it can be broadcast to a peer in its entirety (via `NewBlock (0x07)` in `eth/64` and prior or it can be announced only (via `NewBlockHashes (0x01)`). This duality allows nodes to do the high-bandwidth broadcasting (10s-100s KB) for a square root number of peers; and the low-bandwidth announcing (10s-100s B) for the remaining linear number of peers. The square root broadcast is enough to reach all well connected nodes, but the linear announce is needed to get across degenerate topologies. This works well.

The `eth` protocol, however, does not have a similar dual mechanism for propagating transactions, so nodes need to rely on broadcasting (via `Transactions (0x02)`). To cater for degenerate topologies, transactions cannot be broadcast square rooted, rather they need to be transferred linearly to all peers. With N peers, each node will transfer the same transaction N times (counting both directions), whereas 1 would be enough in a perfect world. This is a significant waste.

A similar issue arises when a new network connection is made between two nodes, as they need to sync up their transaction pools, but the pool is just a soup of dangling transactions. Without a way to deduplicate transactions remotely, each node is forced to naively transfer their entire list of transactions to the other side. With pools containing thousands of transactions, a naive transfer amounts to 10s-100s MB, most of which is useless. There is no better way, however.

This EIP introduces three additional message types into the `eth` protocol (releasing a new version, `eth/65`): `NewPooledTransactionHashes (0x08)` to announce a set of transactions without their content; `GetPooledTransactions (0x09)` to request a batch of transactions by their announced hash; and `PooledTransactions (0x0a)` to reply to a transaction request. This permits reducing the bandwidth used for transaction propagation from linear complexity in the number of peers to square root; and also reducing the initial transaction exchange from 10s-100s MB to `len(pool) * 32B ~= 128KB`.

With transaction throughput (and size) picking up in Ethereum, transaction propagation is the current dominant component of the used network resources. Most of these resources are however wasted, as the `eth` protocol does not have a mechanism to deduplicate transactions remotely, so the same data is transferred over and over again across all network connections.

This EIP proposes a tiny extension to the `eth` protocol, which permits nodes to agree on the set of transactions that need to be transferred across a network connection, before doing the costly exchange. This should help reduce the global (operational) bandwidth usage of the Ethereum network by at least an order of magnitude.

## Specification

Add three new message types to the `eth` protocol:
 * `NewPooledTransactionHashes (0x08): [hash_0: B_32, hash_1: B_32, ...]`
   * Specify one or more transactions that have appeared in the network and which have **not yet been included in a block**. To be maximally helpful, nodes should inform peers of all transactions that they may not be aware of.
   * There is **no protocol violating hard cap** on the number of hashes a node may announce to a remote peer (apart from the 10MB `devp2p` network packet limit), but 4096 seems a sane chunk (128KB) to avoid a single packet hogging a network connection.
   * Nodes should only announce hashes of transactions that the remote peer could reasonably be considered not to know, but it is better to be over zealous than to have a nonce gap in the pool.
 * `GetPooledTransactions (0x09): [hash_0: B_32, hash_1: B_32, ...]`
   * Specify one or more transactions to retrieve from a remote peer&apos;s **transaction pool**.
   * There is **no protocol violating hard cap** on the number of transactions a node may request from a remote peer (apart from the 10MB `devp2p` network packet limit), but the recipient may enforce an arbitrary cap on the reply (size or serving time), which **must not** be considered a protocol violation. To keep wasted bandwidth down (unanswered hashes), 256 seems like a sane upper limit.
 * `PooledTransactions (0x0a): [[nonce: P, receivingAddress: B_20, value: P, ...], ...]`
   * Specify transactions **from the local transaction pool** that the remote node requested via a `GetPooledTransactions (0x09)` message. The items in the list are transactions in the format described in the main Ethereum specification.
   * The transactions **must** be in same order as in the request, but it is **ok** to skip transactions that are not available. This way if the response size limit is reached, requesters will know which hashes to request again (everything from the last returned transaction) and which to assume unavailable (all gaps before the last returned transaction).
   * A peer may respond with an empty reply **iff** none of the hashes match transactions in its pool. It is allowed to announce a transaction that will not be served later if it gets included in a block in between.

## Rationale

**Q: Why limit `GetPooledTransactions (0x09)` to retrieving items from the pool?**

Apart from the transaction pool, transactions in Ethereum are always bundled together by the hundreds in block bodies and existing network retrievals honor this data layout. Allowing direct access to individual transactions in the database has no actionable use case, but would expose costly database reads into the network.

For transaction propagation purposes there is no reason to allow disk access, as any transaction finalized to disk will be broadcast inside a block anyway, so at worse there is a few hundred millisecond delay when a node gets the transaction.

Block propagation may be made a bit more optimal by transferring the contained transactions on demand only, but that is a whole EIP in itself, so better relax the protocol when all the requirements are known and not in advance. It would probably be enough to maintain a set of transactions included in recent blocks in memory.

**Q: Should `NewPooledTransactionHashes (0x08)` deduplicate from disk?**

Similarly to `GetPooledTransactions (0x09)`, `NewPooledTransactionHashes (0x08)` should also only operate on the transaction pool and should ignore the disk altogether. During healthy network conditions, a transaction will propagate through much faster than it&apos;s included in a block, so it will essentially be non-existent that a newly announced transaction is already on disk. By avoiding disk deduplication, we can avoid a DoS griefing by remote transaction announces.

If we want to be really correct and avoid even the slightest data race when deduplicating announcements, we can use the same recently-included-transactions trick that we discussed above to discard announcements that have recently become stale.

**Q: Why not reuse `Transaction (0x02)` instead of a new `PooledTransactions (0x0a)`?**

Originally this EIP reused the existing `Transaction (0x02)` message as the reply to the `GetPooledTransactions (0x09)` request. This makes client code more complicated, because nodes constantly gossip `Transaction (0x02)` messages to each other as broadcasts, so it&apos;s hard to match up which of the many messages is the actual reply to the request.

By keeping `Transaction (0x02)` and `PooledTransactions (0x0a)` as separate messages, we can also leave the protocol more flexible for future optimizations (e.g. adding request IDs, which are meaningless for gossip broadcasts).

## Backwards Compatibility

This EIP extends the `eth` protocol in a backwards incompatible way and requires rolling out a new version, `eth/65`. However, `devp2p` supports running multiple versions of the same wire protocol side-by-side, so rolling out `eth/65` does not require client coordination, since non-updated clients can keep using `eth/64`.

This EIP does not change the consensus engine, thus does _not_ require a hard fork.

## Security Considerations

None.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 13 Jan 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2464</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2464</guid>
      </item>
    
      <item>
        <title>Singleton Factory</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-2470-singleton-factory/3933</comments>
        
        <description>## Simple Summary

Some DApps needs one, and only one, instance of an contract, which have the same address on any chain.

A permissionless factory for deploy of keyless deterministic contracts addresses based on its bytecode. 

## Abstract

Some contracts are designed to be Singletons which have the same address no matter what chain they are, which means that should exist one instance for all, such as [EIP-1820] and [EIP-2429]. These contracts are usually deployed using a method known as [Nick]&apos;s method, so anyone can deploy those contracts on any chain and they have a deterministic address.
This standard proposes the creation of a CREATE2 factory using this method, so other projects requiring this feature can use this factory in any chain with the same setup, even in development chains.    

## Motivation

Code reuse, using the factory becomes easier to deploy singletons.

## Specification

### [ERC-2470] Singleton Factory

&gt; This is an exact copy of the code of the [ERC2470 factory smart contract].

```solidity
pragma solidity 0.6.2;


/**
 * @title Singleton Factory (EIP-2470)
 * @notice Exposes CREATE2 (EIP-1014) to deploy bytecode on deterministic addresses based on initialization code and salt.
 * @author Ricardo Guilherme Schmidt (Status Research &amp; Development GmbH)
 */
contract SingletonFactory {
    /**
     * @notice Deploys `_initCode` using `_salt` for defining the deterministic address.
     * @param _initCode Initialization code.
     * @param _salt Arbitrary value to modify resulting address.
     * @return createdContract Created contract address.
     */
    function deploy(bytes memory _initCode, bytes32 _salt)
        public
        returns (address payable createdContract)
    {
        assembly {
            createdContract := create2(0, add(_initCode, 0x20), mload(_initCode), _salt)
        }
    }
}
// IV is a value changed to generate the vanity address.
// IV: 6583047
```

### Deployment Transaction

Below is the raw transaction which MUST be used to deploy the smart contract on any chain.

```
0xf9016c8085174876e8008303c4d88080b90154608060405234801561001057600080fd5b50610134806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80634af63f0214602d575b600080fd5b60cf60048036036040811015604157600080fd5b810190602081018135640100000000811115605b57600080fd5b820183602082011115606c57600080fd5b80359060200191846001830284011164010000000083111715608d57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550509135925060eb915050565b604080516001600160a01b039092168252519081900360200190f35b6000818351602085016000f5939250505056fea26469706673582212206b44f8a82cb6b156bfcc3dc6aadd6df4eefd204bc928a4397fd15dacf6d5320564736f6c634300060200331b83247000822470
```

The strings of `2470`&apos;s at the end of the transaction are the `r` and `s` of the signature.
From this deterministic pattern (generated by a human), anyone can deduce that no one knows the private key for the deployment account.

### Deployment Method

This contract is going to be deployed using the keyless deployment method---also known as [Nick]&apos;s method---which relies on a single-use address.
(See [Nick&apos;s article] for more details). This method works as follows:

1. Generate a transaction which deploys the contract from a new random account.
  - This transaction MUST NOT use [EIP-155] in order to work on any chain.
  - This transaction MUST have a relatively high gas price to be deployed on any chain. In this case, it is going to be 100 Gwei.

2. Forge a transaction with the following parameters:
    ```js
    {
        nonce: 0,
        gasPrice: 100000000000,
        value: 0,
        data: &apos;0x608060405234801561001057600080fd5b50610134806100206000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80634af63f0214602d575b600080fd5b60cf60048036036040811015604157600080fd5b810190602081018135640100000000811115605b57600080fd5b820183602082011115606c57600080fd5b80359060200191846001830284011164010000000083111715608d57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550509135925060eb915050565b604080516001600160a01b039092168252519081900360200190f35b6000818351602085016000f5939250505056fea26469706673582212206b44f8a82cb6b156bfcc3dc6aadd6df4eefd204bc928a4397fd15dacf6d5320564736f6c63430006020033&apos;,
        gasLimit: 247000,
        v: 27,
        r: &apos;0x247000&apos;,
        s: &apos;0x2470&apos;
    }
    ```
    &gt; The `r` and `s` values, made of starting `2470`, are obviously a human determined value, instead of a real signature.

3. We recover the sender of this transaction, i.e., the single-use deployment account.

    &gt; Thus we obtain an account that can broadcast that transaction, but we also have the warranty that nobody knows the private key of that account.

4. Send exactly 0.0247 ether to this single-use deployment account.

5. Broadcast the deployment transaction.

    &gt; Note: 247000 is the double of gas needed to deploy the smart contract, this ensures that future changes in OPCODE pricing are unlikely to cause this deploy transaction to fail out of gas. A left over will sit in the address of about 0.01 ETH will be forever locked in the single use address. 

The resulting transaction hash is `0x803351deb6d745e91545a6a3e1c0ea3e9a6a02a1a4193b70edfcd2f40f71a01c`.

This operation can be done on any chain, guaranteeing that the contract address is always the same and nobody can use that address with a different contract.


### Single-use Factory Deployment Account

![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAB0UlEQVR4nO3asW1CQRBAQdpyCa6CIpxTjgujDGTJNEC2QqvjTbDx33c3P7vL79f1fzLf98dobn8/o5nuP53p/tPzm+5/AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4CMBnH6B0/23L2AbEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ8JYPsCtw+w3g9AvB+AeD8A8X4A4v0AxPsBiPcDEO8HIN4PQLwfgHg/APF+AOL9AMT7AYj3AxDvP/5ByOkApt/PvwgCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgJYDtA9w+gO0fYHsAAGB/CQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOAdALYfNExnun+9H4B4PwDxfgDi/QDE+wGI9wMQ7wcg3g9AvB+AeD8A8X4A4v0AxPsBiPcDEO8HIN4/fhCy/aDidADb5wcAAGcHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO8CsH2ApwPY/j4Ah+8PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPB6nlegoDNgrfyiAAAAAElFTkSuQmCC)

`0xBb6e024b9cFFACB947A71991E386681B1Cd1477D`

This account is generated by reverse engineering it from its signature for the transaction. 
This way no one knows the private key, but it is known that it is the valid signer of the deployment transaction.

&gt; To deploy the registry, 0.0247 ether MUST be sent to this account *first*.

### Factory Contract Address
![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAABn0lEQVR4nO3coRECMRRF0S2GutCUQzd4WqAMLB4qQGWYP+EecXXeZo/OcTrf35Ndbq+l7F/rmB6w+wXuvh+A+H4A4vsBiO8HIL4fgPh+AOL7AYjvByC+H4D4fgDi+wGI7wcgvh+A+H4A4vuXAUxfwPX5GG33+wMAgL0/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgGYHrA9A+cbhoQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wlgesD0+bvvXz0fgM33AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8ATB9gZoNgHgAxAMgHgDxAIgHQDwA4gEQD4B4AMQDIB4A8QCIB0A8AOId0w8caK3V/wfA5gEQD4B4AMQDIB4A8QCIB0A8AOIBEA+AeADEAyAeAPEAiAdAPADiARAPgHgAxAMgHgDxAIgHQDwA4gEQD4B4AMQDIB4A8QCItwxg+oECDT8QMT1AAAgAASAABIAAEAACQAAIAAEgAASAANAv+gDxVDRR1CVqRAAAAABJRU5ErkJggg==)

`0xce0042B868300000d44A59004Da54A005ffdcf9f`

The contract has the address above for every chain on which it is deployed.
### ABI for SingletonFactory:
```json
[
    {
        &quot;constant&quot;: false,
        &quot;inputs&quot;: [
            {
                &quot;internalType&quot;: &quot;bytes&quot;,
                &quot;name&quot;: &quot;_initCode&quot;,
                &quot;type&quot;: &quot;bytes&quot;
            },
            {
                &quot;internalType&quot;: &quot;bytes32&quot;,
                &quot;name&quot;: &quot;_salt&quot;,
                &quot;type&quot;: &quot;bytes32&quot;
            }
        ],
        &quot;name&quot;: &quot;deploy&quot;,
        &quot;outputs&quot;: [
            {
                &quot;internalType&quot;: &quot;address payable&quot;,
                &quot;name&quot;: &quot;createdContract&quot;,
                &quot;type&quot;: &quot;address&quot;
            }
        ],
        &quot;payable&quot;: false,
        &quot;stateMutability&quot;: &quot;nonpayable&quot;,
        &quot;type&quot;: &quot;function&quot;
    }
]
```

## Rationale

SingletonFactory does not allow sending value on create2, this was done to prevent different results on the created object. 
SingletonFactory allows user defined salt to facilitate the creation of vanity addresses for other projects. If vanity address is not necessary, salt `bytes(0)` should be used.
Contracts that are constructed by the SingletonFactory MUST not use `msg.sender` in their constructor, all variables must came through initialization data. This is intentional, as if allowing a callback after creation to aid initialization state would lead to contracts with same address (but different chains) to have the same address but different initial state.
The resulting address can be calculated in chain by any contract using this formula: `address(keccak256(bytes1(0xff), 0xce0042B868300000d44A59004Da54A005ffdcf9f, _salt, keccak256(_code)) &lt;&lt; 96)` or in javascript using https://github.com/ethereumjs/ethereumjs-util/blob/master/docs/README.md#const-generateaddress2.

## Backwards Compatibility

Does not apply as there are no past versions of Singleton Factory being used.

## Test Cases

TBD

## Implementation

https://github.com/3esmit/ERC2470

## Security Considerations

Some contracts can possibly not support being deployed on any chain, or require a different address per chain, that can be safely done by using comparison in [EIP-1344] in constructor.
Account contracts are singletons in the point of view of each user, when wallets want to signal what chain id is intended, [EIP-1191] should be used. 
Contracts deployed on factory must not use `msg.sender` in constructor, instead use constructor parameters, otherwise the factory would end up being the controller/only owner of those. 

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[EIP-155]: /EIPs/EIPS/eip-155

[EIP-1191]: /EIPs/EIPS/eip-1191

[EIP-1344]: /EIPs/EIPS/eip-1344

[EIP-1820]: /EIPs/EIPS/eip-1820
[EIP-2429]: https://gitlab.com/status-im/docs/EIPs/blob/secret-multisig-recovery/EIPS/eip-2429.md
[Nick&apos;s article]: https://medium.com/@weka/how-to-send-ether-to-11-440-people-187e332566b7
[Nick]: https://github.com/Arachnid/

</description>
        <pubDate>Wed, 15 Jan 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2470</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2470</guid>
      </item>
    
      <item>
        <title>Coinbase calls</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethresear.ch/t/gas-abstraction-non-signed-block-validator-only-procedures/4388/2</comments>
        
        <description>## Simple Summary

Allow contracts to be called directly by `block.coinbase` (block validator), without a transaction.

## Abstract

_In proof-of-work blockchains, validators are known as miners._

The validator might want to execute functions directly, without having to sign a transaction. Some examples might be presenting a proof in a contract for a change which also benefits the validator. 

A notable example would be when a validator want to act as an [EIP-1077](/EIPs/EIPS/eip-1077) Gas Relayer, incentivized to pick up fees from meta transactions.
Without this change, they can do so by signing from any address a `gasPrice = 0` transaction with the gas relayed call. 
However this brings an overhead of a signed transaction by validator that does nothing, as `msg.sender` is never used, and there is no gas cost to EVM charge. 

This proposal makes possible to remove this unused ecrecover.

## Motivation

In order to reduce the overhead of calls that don&apos;t use `msg.sender` and are being called by validator with `tx.gasPrice = 0`. 

## Specification

The calls to be executed by `block.coinbase` would be included first at block, and would consume normally the gas of block, however they won&apos;t pay/cost gas, instead the call logic would pay the validator in other form. 

Would be valid to execute any calls without a transaction by the block coinbase, except when the validator call tries to read `msg.sender`, which would throw an invalid jump.

Calls included by the validator would have `tx.origin = block.coinbase` and `gas.price = 0` for the rest of call stack, the rest follows as normal calls.

## Rationale

TBD

## Backwards Compatibility

`tx.origin = block.coinbase` could cause some issues on bad designed contracts, such as using `tx.origin` to validate a signature, an analysis on how contracts use tx.origin might be useful to decide if this is a good choice.

## Test Cases

TBD

## Implementation

TBD

## Security Considerations

TBD

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 19 Jan 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2474</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2474</guid>
      </item>
    
      <item>
        <title>Token Metadata Integrity</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2483</comments>
        
        <description>## Simple Summary

This specification defines a mechanism by which clients may verify that a fetched token metadata document has been delivered without unexpected manipulation.

This is the Web3 counterpart of the W3C Subresource Integrity (SRI) specification.

## Abstract

An interface `ERC2477` with two functions `tokenURIIntegrity` and `tokenURISchemaIntegrity` are specified for smart contracts and a narrative is provided to explain how this improves the integrity of the token metadata documents.

## Motivation

Tokens are being used in many applications to represent, trace and provide access to assets off-chain. These assets include in-game digital items in mobile apps, luxury watches and products in our global supply chain, among many other creative uses.

Several token standards allow attaching metadata to specific tokens using a URI (RFC 3986) and these are supported by the applications mentioned above. These metadata standards are:

* ERC-721 metadata extension (`ERC721Metadata`)
* ERC-1155 metadata extension (`ERC1155Metadata_URI`)
* ERC-1046 (DRAFT) ERC-20 Metadata Extension

Although all these standards allow storing the metadata entirely on-chain (using the &quot;data&quot; URI, RFC 2397), or using a content-addressable system (e.g. IPFS&apos;s Content IDentifiers [sic]), nearly every implementation we have found is using Uniform Resource Locators (the exception is The Sandbox which uses IPFS URIs). These URLs provide no guarantees of content correctness or immutability. This standard adds such guarantees.

## Design

**Approach A:** A token contract may reference metadata by using its URL. This provides no integrity protection because  the referenced metadata and/or schema could change at any time if the hosted content is mutable. This is the world before EIP-2477: 

```
┌───────────────────────┐       ┌────────┐      ┌────────┐
│        TokenID        │──────▶│Metadata│─────▶│ Schema │
└───────────────────────┘       └────────┘      └────────┘
```

Note: according to the JSON Schema project, a metadata document referencing a schema using a URI in the `$schema` key is a known approach, but it is not standardized.

**Approach B:** EIP-2477 provides mechanisms to establish integrity for these references. In one approach, there is integrity for the metadata document. Here, the on-chain data includes a hash of the metadata document. The metadata may or may not reference a schema. In this approach, changing the metadata document will require updating on-chain `tokenURIIntegrity`:

```
┌───────────────────────┐       ┌────────┐      ┌ ─ ─ ─ ─ 
│        TokenID        │──────▶│Metadata│─ ─ ─▶  Schema │
└───────────────────────┘       └────────┘      └ ─ ─ ─ ─ 
┌───────────────────────┐            ▲                    
│   tokenURIIntegrity   │════════════╝                    
└───────────────────────┘                                 
```

**Approach C:** In a stronger approach, the schema is referenced by the metadata using an extension to JSON Schema, providing integrity. In this approach, changing the metadata document or the schema will require updating on-chain `tokenURIIntegrity` and the metadata document, additionally changing the schema requires updating the on-chain `tokenURISchemaIntegrity`:

```
┌───────────────────────┐       ┌────────┐      ┌────────┐
│        TokenID        │──────▶│Metadata│═════▶│ Schema │
└───────────────────────┘       └────────┘      └────────┘
┌───────────────────────┐            ▲                    
│   tokenURIIntegrity   │════════════╝                    
└───────────────────────┘                                 
```

**Approach D:** Equally strong, the metadata can make a normal reference (no integrity protection) to the schema and on-chain data also includes a hash of the schema document. In this approach, changing the metadata document will require updating on-chain `tokenURIIntegrity` and updating the schema document will require updating the `tokenURISchemaIntegrity`:

```
┌───────────────────────┐       ┌────────┐      ┌────────┐
│        TokenID        │──────▶│Metadata│─────▶│ Schema │
└───────────────────────┘       └────────┘      └────────┘
┌───────────────────────┐            ▲               ▲    
│   tokenURIIntegrity   │════════════╝               ║    
└───────────────────────┘                            ║    
┌───────────────────────┐                            ║    
│tokenURISchemaIntegrity│════════════════════════════╝    
└───────────────────────┘
```

**Approach E:** Lastly, the schema can be referenced with integrity from the metadata and also using on-chain data. In this approach, changing the metadata document or the schema will require updating on-chain `tokenURIIntegrity` and the metadata document, additionally changing the schema requires updating the on-chain `tokenURISchemaIntegrity`:

```
┌───────────────────────┐       ┌────────┐      ┌────────┐
│        TokenID        │──────▶│Metadata│═════▶│ Schema │
└───────────────────────┘       └────────┘      └────────┘
┌───────────────────────┐            ▲               ▲    
│   tokenURIIntegrity   │════════════╝               ║    
└───────────────────────┘                            ║    
┌───────────────────────┐                            ║    
│tokenURISchemaIntegrity│════════════════════════════╝    
└───────────────────────┘                                 
```

## Specification

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.

### Smart contracts

**Smart contracts implementing the ERC-2477 standard MUST implement the `ERC2477` interface.**

```solidity
// SPDX-License-Identifier: CC0-1.0

pragma solidity ^0.8.7;

/// @title ERC-2477 Token Metadata Integrity
/// @dev See https://eips.ethereum.org/EIPS/eip-2477
/// @dev The ERC-165 identifier for this interface is 0x832a7e0e
interface ERC2477 /* is ERC165 */ {
    /// @notice Get the cryptographic hash of the specified tokenID&apos;s metadata
    /// @param  tokenId       Identifier for a specific token
    /// @return digest        Bytes returned from the hash algorithm, or &quot;&quot; if not available
    /// @return hashAlgorithm The name of the cryptographic hash algorithm, or &quot;&quot; if not available
    function tokenURIIntegrity(uint256 tokenId) external view returns(bytes memory digest, string memory hashAlgorithm);

    /// @notice Get the cryptographic hash for the specified tokenID&apos;s metadata schema
    /// @param  tokenId       Identifier for a specific token
    /// @return digest        Bytes returned from the hash algorithm, or &quot;&quot; if not available
    /// @return hashAlgorithm The name of the cryptographic hash algorithm, or &quot;&quot; if not available
    function tokenURISchemaIntegrity(uint256 tokenId) external view returns(bytes memory digest, string memory hashAlgorithm);
}
```

The returned cryptographic hashes correspond to the token&apos;s metadata document and that metadata document&apos;s schema, respectively.

For example, with ERC-721 `tokenURIIntegrity(21)` would correspond to `tokenURI(21)`. With ERC-1155, `tokenURIIntegrity(16)` would correspond to `uri(16)`. In both cases, `tokenURISchemaIntegrity(32)` would correspond to the schema of the document matched by `tokenURIIntegrity(32)`.

**Smart contracts implementing the ERC-2477 standard MUST implement the ERC-165 standard, including the interface identifiers above.**

Smart contracts implementing the ERC-2477 standard MAY use any hashing or content integrity scheme.

Smart contracts implementing the ERC-2477 standard MAY use or omit a mechanism to notify when the integrity is updated (e.g. an Ethereum logging operation).

Smart contracts implementing the ERC-2477 standard MAY use any mechanism to provide schemas for metadata documents and SHOULD use JSON-LD on the metadata document for this purpose (i.e.  `&quot;@schema&quot;:...`).

### Metadata

A metadata document MAY conform to this schema to provide referential integrity to its schema document.

```json
{
  &quot;title&quot;: &quot;EIP-2477 JSON Object With Refererential Integrity to Schema&quot;,
  &quot;type&quot;: &quot;object&quot;,
  &quot;properties&quot;: {
    &quot;$schema&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;format&quot;: &quot;uri&quot;
    },
    &quot;$schemaIntegrity&quot;: {
      &quot;type&quot;: &quot;object&quot;,
      &quot;properties&quot;: {
        &quot;digest&quot;: {
          &quot;type&quot;: &quot;string&quot;
        },
        &quot;hashAlgorithm&quot;: {
          &quot;type&quot;: &quot;string&quot;
        }
      },
      &quot;required&quot;: [&quot;digest&quot;, &quot;hashAlgorithm&quot;]
    }
  },
  &quot;required&quot;: [&quot;$schema&quot;, &quot;$schemaIntegrity&quot;]
}
```

### Clients

A client implementing the ERC-2477 standard MUST support at least the `sha256` hash algorithm and MAY support other algorithms.

### Caveats

* This EIP metadata lists ERC-721 and ERC-1155 as &quot;required&quot; for implementation, due to a technical limitation of EIP metadata. In actuality, this standard is usable with any token implementation that has a `tokenURI(uint id)` or similar function. 

## Rationale

**Function and parameter naming**

The W3C Subresource Integrity (SRI) specification uses the attribute &quot;integrity&quot; to perform integrity verification. This ERC-2477 standard provides a similar mechanism and reuses the integrity name so as to be familiar to people that have seen SRI before.

**Function return tuple**

The SRI integrity attribute encodes elements of the tuple $$(cryptographic\ hash\ function, digest, options)$$. This ERC-2477 standard returns a digest and hash function name and omits forward-compatibility options.

Currently, the SRI specification does not make use of options. So we cannot know what format they might be when implemented. This is the motivation to exclude this parameter.

The digest return value is first, this is an optimization because we expect on-chain implementations will be more likely to use this return value if they will only be using one of the two.

**Function return types**

The digest is a byte array and supports various hash lengths. This is consistent with SRI. Whereas SRI uses base64 encoding to target an HTML document, we use a byte array because Ethereum already allows this encoding.

The hash function name is a string. Currently there is no universal taxonomy of hash function names. SRI recognizes the names `sha256`, `sha384` and `sha512` with case-insensitive matching. We are aware of two authorities which provide taxonomies and canonical names for hash functions: ETSI Object Identifiers and NIST Computer Security Objects Register. However, SRI&apos;s approach is easier to follow and we have adopted this here.

**Function return type — hash length**

Clients must support the SHA-256 algorithm and may optionally support others. This is a departure from the SRI specification where SHA-256, SHA-384 and SHA-512 are all required. The rationale for this less-secure requirement is because we expect some clients to be on-chain. Currently SHA-256 is simple and cheap to do on Ethereum whereas SHA-384 and SHA-512 are more expensive and cumbersome.

The most popular hash function size below 256 bits in current use is SHA-1 at 160 bits. Multiple collisions (the &quot;Shattered&quot; PDF file, the 320 byte file, the chosen prefix) have been published and a recipe is given to generate infinitely more collisions. SHA-1 is broken. The United States National Institute of Standards and Technology (NIST) has first deprecated SHA-1 for certain use cases in November 2015 and has later further expanded this deprecation.

The most popular hash function size above 256 bits in current use is SHA-384 as specified by NIST.

The United States National Security Agency requires a hash length of 384 or more bits for the SHA-2 (CNSA Suite Factsheet) algorithm suite for use on TOP SECRET networks. (No unclassified documents are currently available to specify use cases at higher classification networks.)

We suspect that SHA-256 and the 0xcert Asset Certification will be popular choices to secure token metadata for the foreseeable future.

**In-band signaling**

One possible way to achieve strong content integrity with the existing token standards would be to include, for example, a `?integrity=XXXXX` at the end of all URLs. This approach is not used by any existing implementations we know about. There are a few reasons we have not chosen this approach. The strongest reason is that the World Wide Web has the same problem and they chose to use the Sub-Resource Integrity approach, which is a separate data field than the URL.

Other supplementary reasons are:

* For on-chain consumers of data, it is easier to parse a direct hash field than to perform string operations.

* Maybe there are some URIs which are not amenable to being modified in that way, therefore limiting the generalizability of that approach.

This design justification also applies to `tokenURISchemaIntegrity`. The current JSON-LD specification allows a JSON document to link to a schema document. But it does not provide integrity. Rather than changing how JSON-LD works, or changing JSON Schemas, we have the `tokenURISchemaIntegrity` property to just provide the integrity.

## Backwards Compatibility

Both ERC-721 and ERC-1155 provide compatible token metadata specifications that use URIs and JSON schemas. The ERC-2477 standard is compatible with both, and all specifications are additive. Therefore, there are no backward compatibility regressions.

ERC-1523 Standard for Insurance Policies as ERC-721 Non Fungible Tokens (DRAFT) proposes an extension to ERC-721 which also tightens the requirements on metadata. Because it is wholly an extension of ERC-721, ERC-1523 is automatically supported by ERC-2477 (since this standard already supports ERC-721).

ERC-1046 (DRAFT) ERC-20 Metadata Extension proposes a comparate extension for ERC-20. Such a concept is outside the scope of this ERC-2477 standard. Should ERC-1046 (DRAFT) be finalized, we will welcome a new ERC which copies ERC-2477 and removes the `tokenId` parameter.

Similarly, ERC-918 (DRAFT) Mineable Token Standard proposes an extension for ERC-20 and also includes metadata. The same comment applies here as ERC-1046.

## Test Cases

Following is a token metadata document which is simultaneously compatible with ERC-721, ERC-1155 and ERC-2477 standards.

```json
{
  &quot;$schema&quot;: &quot;https://URL_TO_SCHEMA_DOCUMENT&quot;,
  &quot;name&quot;: &quot;Asset Name&quot;,
  &quot;description&quot;: &quot;Lorem ipsum...&quot;,
  &quot;image&quot;: &quot;https://s3.amazonaws.com/your-bucket/images/{id}.png&quot;
}
```

This above example shows how JSON-LD is employed to reference the schema document (`$schema`).

Following is a corresponding schema document which is accessible using the URI `&quot;https://URL_TO_SCHEMA_DOCUMENT&quot;` above.

```json
{
  &quot;type&quot;: &quot;object&quot;,
  &quot;properties&quot;: {
    &quot;name&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Identifies the asset to which this NFT represents&quot;
    },
    &quot;description&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Describes the asset to which this NFT represents&quot;
    },
    &quot;image&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive.&quot;
    }
  }
}
```

Assume that the metadata and schema above apply to a token with identifier 1234. (In ERC-721 this would be a specific token, in ERC-1155 this would be a token type.) Then these two function calls MAY have the following output:

* `function tokenURIIntegrity(1234)`
  * `bytes digest `: `3fc58b72faff20684f1925fd379907e22e96b660`
  * `string hashAlgorithm`: `sha256`
* `function tokenURISchemaIntegrity(1234)`
  * `bytes digest `: `ddb61583d82e87502d5ee94e3f2237f864eeff72`
  * `string hashAlgorithm`: `sha256`

To avoid doubt: the previous paragraph specifies &quot;MAY&quot; have that output because other hash functions are also acceptable.

## Implementation

0xcert Framework supports ERC-2477.

## Reference

Normative standard references

1. RFC 2119 Key words for use in RFCs to Indicate Requirement Levels. https://www.ietf.org/rfc/rfc2119.txt
2. ERC-165 Standard Interface Detection. ./eip-165.md
3. ERC-721 Non-Fungible Token Standard. ./eip-721.md
4. ERC-1155 Multi Token Standard. ./eip-1155.md
5. JSON-LD. https://www.w3.org/TR/json-ld/
6. Secure Hash Standard (SHS). https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf

Other standards

1. ERC-1046 ERC-20 Metadata Extension (DRAFT). ./eip-1046.md
2. ERC-918 Mineable Token Standard (DRAFT). ./eip-918.md
3. ERC-1523 Standard for Insurance Policies as ERC-721 Non Fungible Tokens (DRAFT). ./eip-1523.md
4. W3C Subresource Integrity (SRI). https://www.w3.org/TR/SRI/
5. The &quot;data&quot; URL scheme. https://tools.ietf.org/html/rfc2397
6. Uniform Resource Identifier (URI): Generic Syntax. https://tools.ietf.org/html/rfc3986
7. CID [Specification] (DRAFT). https://github.com/multiformats/cid

Discussion

1. JSON-LD discussion of referential integrity. https://lists.w3.org/Archives/Public/public-json-ld-wg/2020Feb/0003.html
2. JSON Schema use of `$schema` key for documents. https://github.com/json-schema-org/json-schema-spec/issues/647#issuecomment-417362877

Other

1. [0xcert Framework supports ERC-2477]. https://github.com/0xcert/framework/pull/717
2. [Shattered] The first collision for full SHA-1. https://shattered.io/static/shattered.pdf
3. [320 byte file] The second SHA Collision. https://privacylog.blogspot.com/2019/12/the-second-sha-collision.html
4. [Chosen prefix] https://sha-mbles.github.io
5. Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths. (Rev. 1. Superseded.) https://csrc.nist.gov/publications/detail/sp/800-131a/rev-1/archive/2015-11-06
6. Commercial National Security Algorithm (CNSA) Suite Factsheet. https://apps.nsa.gov/iaarchive/library/ia-guidance/ia-solutions-for-classified/algorithm-guidance/commercial-national-security-algorithm-suite-factsheet.cfm
7. ETSI Assigned ASN.1 Object Identifiers. https://portal.etsi.org/pnns/oidlist
8. Computer Security Objects Register. https://csrc.nist.gov/projects/computer-security-objects-register/algorithm-registration
9. The Sandbox implementation. https://github.com/pixowl/sandbox-smart-contracts/blob/7022ce38f81363b8b75a64e6457f6923d91960d6/src/Asset/ERC1155ERC721.sol

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Thu, 02 Jan 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2477</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2477</guid>
      </item>
    
      <item>
        <title>eth/66 request identifier</title>
        <category>Standards Track/Networking</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2481-eth-66-request-identifiers/12132</comments>
        
        <description>## Abstract

The `eth` protocol defines various request and response commands that are used to exchange data between Ethereum nodes. For example, to ask a peer node for a specific set of headers, a node sends it the [`GetBlockHeaders`](https://github.com/ethereum/devp2p/blob/40ab248bf7e017e83cc9812a4e048446709623e8/caps/eth.md#getblockheaders-0x03) command.

*Citing from the [`GetBlockHeaders` spec definition](https://github.com/ethereum/devp2p/blob/40ab248bf7e017e83cc9812a4e048446709623e8/caps/eth.md#getblockheaders-0x03):*

&gt;`[block: {P, B_32}, maxHeaders: P, skip: P, reverse: P in {0, 1}]`

&gt;Require peer to return a `BlockHeaders` message. Reply must contain a number of block
headers, of rising number when `reverse` is `0`, falling when `1`, `skip` blocks apart,
beginning at block `block` (denoted by either number or hash) in the canonical chain, and
with at most `maxHeaders` items.

The node that receives the `GetBlockHeaders` command should answer it with the [`BlockHeaders`](https://github.com/ethereum/devp2p/blob/40ab248bf7e017e83cc9812a4e048446709623e8/caps/eth.md#blockheaders-0x04) response command accordingly.

*Citing from the [`BlockHeaders` spec definition](https://github.com/ethereum/devp2p/blob/40ab248bf7e017e83cc9812a4e048446709623e8/caps/eth.md#blockheaders-0x04):* 

&gt;`[blockHeader_0, blockHeader_1, ...]`

&gt;Reply to `GetBlockHeaders`. The items in the list (following the message ID) are block
headers in the format described in the main Ethereum specification, previously asked for
in a GetBlockHeaders message. This may validly contain no block headers if none of the
requested block headers were found. The number of headers that can be requested in a
single message may be subject to implementation-defined limits.

Let&apos;s consider a client making many simultaneous requests for `GetBlockHeaders` to one of its peers. By nature it can not be guaranteed that the expected responses arrive in the same order as they were sent. For the client to associate the incoming responses to the correct requests it has to loop through all pending requests trying to match it with the incoming response based on its contents.

This can be particular tricky for responses that are ambiguous such as empty responses.

This EIP proposes to change the `GetBlockHeaders` and the `BlockHeaders` command to include a `request_id`.

The `request_id` is a 64-bit integer set by the client when it makes the request. On the responding side, the exact same `request_id` from the incoming request is put back into the response object.

This change allows the requesting client to match incoming responses **directly** back to their pending requests without going through all of the pending requests to check if they might match based on the response data.

The selected request/response pair serves as an example for many similar request/response pairs in the `eth` networking protocol.

## Motivation

The lack of request identifiers in the request / response paris of the `eth` protocol puts unnecessary burden of code complexity into every Ethereum client. It also makes the communication slightly less efficient. Another argument can be made that the addition of request identifiers makes the protocol more aligned with the `les` protocol which **does** already defines request identifiers for each request / response pair.

## Specification

Change the following message types in the `eth` protocol:

* `GetBlockHeaders (0x03)`
   * **Current (eth/65):** `[block: {P, B_32}, maxHeaders: P, skip: P, reverse: P in {0, 1}]`
   * **Then (eth/66)**: `[request_id: P, [block: {P, B_32}, maxHeaders: P, skip: P, reverse: P in {0, 1}]]`
* `BlockHeaders (0x04)`
   * **Current (eth/65):** `[blockHeader_0, blockHeader_1, ...]`
   * **Then (eth/66)**: `[request_id: P, [blockHeader_0, blockHeader_1, ...]]`
* `GetBlockBodies (0x05)`
   * **Current (eth/65):** `[hash_0: B_32, hash_1: B_32, ...]`
   * **Then (eth/66)**: `[request_id: P, [hash_0: B_32, hash_1: B_32, ...]]`
* `GetPooledTransactions (0x09)`:
   * **Current (eth/65)**`[hash_0: B_32, hash_1: B_32, ...]`
   * **Then (eth/66)**`[request_id: P, [hash_0: B_32, hash_1: B_32, ...]]`
* `PooledTransactions (0x0a)`:
   * **Current (eth/65)**`[[nonce: P, receivingAddress: B_20, value: P, ...], ...]`
   * **Then (eth/66)**`[request_id: P, [[nonce: P, receivingAddress: B_20, value: P, ...], ...]]`
* `BlockBodies (0x06)`
   * **Current (eth/65):** `[hash_0: B_32, hash_1: B_32, ...]`
   * **Then (eth/66)**: `[request_id: P, [hash_0: B_32, hash_1: B_32, ...]]`
* `GetNodeData (0x0d)`
   * **Current (eth/65):** `[hash_0: B_32, hash_1: B_32, ...]`
   * **Then (eth/66)**: `[request_id: P, [hash_0: B_32, hash_1: B_32, ...]]`
* `NodeData (0x0e)`
   * **Current (eth/65):** `[value_0: B, value_1: B, ...]`
   * **Then (eth/66)**: `[request_id: P, [value_0: B, value_1: B, ...]]`
* `GetReceipts (0x0f)`
   * **Current (eth/65):** `[blockHash_0: B_32, blockHash_1: B_32, ...]`
   * **Then (eth/66)**: `[request_id: P, [blockHash_0: B_32, blockHash_1: B_32, ...]]`
* `Receipts (0x10)`
   * **Current (eth/65):** `[[receipt_0, receipt_1], ...]`
   * **Then (eth/66)**: `[request_id: P, [[receipt_0, receipt_1], ...]]`


To elaborate, each command is altered in the following way:

1. Create a list with the `request_id` being the first element.
2. Make the second element the list that defines the whole command in the current scheme.

The ``request_id`` has the following characteristics:

* 64 bit integer
* Doesn&apos;t need to be sequential (can be random)
* Does allow duplicates

## Rationale

**Q: The efficiency gains might encourage clients to flood their peers with too many simultaneous requests**

Peers can always throttle or disconnect if they don&apos;t feel treated well. This is the same as today.

**Q: If `les` already defines the commands like this, why not just use the `les` protocol?**

In practice, peers that serve the `les` protocol are much harder to find in the network. The reasons for this are varied but might boil down to client defaults, immature implementations or missing incentives.

**Q: Networking works today, isn&apos;t this just adding bloat?**

This is adding a single integer per command while at the same time reducing code complexity and improving networking efficiency. The addition seems justified.

**Q: Why not demand request ids to be sequential?**

Assuming request ids start always to count from `0` upon connection, things will become messy when
connections are lost and clients reconnect and start over with the same request ids that they had used
in the previous session.

**Q: Why allow duplicate request ids?**

The main benefit is flexibility and simplicity on the implementation side. Clients could decide to share
the same ids across multiple different request types since they are naturally separated anyway. Clients
could even decide to not rely on request ids at all, therefore using the same constant request id across
all requests.

**Q: Why choose a 64-bit integer for the request ids**

64-bit integer were chosen to keep compatibility with the `les` protocol.

## Backwards Compatibility

This EIP extends the `eth` protocol in a backwards incompatible way and requires rolling out a new version, `eth/66`. However, `devp2p` supports running multiple versions of the same wire protocol side-by-side, so rolling out `eth/66` does not require client coordination, since non-updated clients can keep using `eth/65`.

This EIP does not change the consensus engine, thus does *not* require a hard fork.

## Test Cases

These testcases cover RLP-encoding of all the redefined messages types, where the `rlp` portion is the rlp-encoding of the message defined in the `data` portion. 


```json
{
  &quot;type&quot;: &quot;GetBlockHeadersPacket66&quot;,
  &quot;rlp&quot;: &quot;0xe8820457e4a000000000000000000000000000000000000000000000000000000000deadc0de050580&quot;,
  &quot;data&quot;: {
    &quot;RequestId&quot;: 1111,
    &quot;Origin&quot;: {
      &quot;Hash&quot;: &quot;0x00000000000000000000000000000000000000000000000000000000deadc0de&quot;,
      &quot;Number&quot;: 0
    },
    &quot;Amount&quot;: 5,
    &quot;Skip&quot;: 5,
    &quot;Reverse&quot;: false
  }
}
```

```json
{
  &quot;type&quot;: &quot;GetBlockHeadersPacket66&quot;,
  &quot;rlp&quot;: &quot;0xca820457c682270f050580&quot;,
  &quot;data&quot;: {
    &quot;RequestId&quot;: 1111,
    &quot;Origin&quot;: {
      &quot;Hash&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
      &quot;Number&quot;: 9999
    },
    &quot;Amount&quot;: 5,
    &quot;Skip&quot;: 5,
    &quot;Reverse&quot;: false
  }
}
```

```json
{
  &quot;type&quot;: &quot;BlockHeadersPacket66&quot;,
  &quot;rlp&quot;: &quot;0xf90202820457f901fcf901f9a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008208ae820d0582115c8215b3821a0a827788a00000000000000000000000000000000000000000000000000000000000000000880000000000000000&quot;,
  &quot;data&quot;: {
    &quot;RequestId&quot;: 1111,
    &quot;BlockHeadersPacket&quot;: [
      {
        &quot;parentHash&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
        &quot;sha3Uncles&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
        &quot;miner&quot;: &quot;0x0000000000000000000000000000000000000000&quot;,
        &quot;stateRoot&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
        &quot;transactionsRoot&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
        &quot;receiptsRoot&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
        &quot;logsBloom&quot;: &quot;0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000&quot;,
        &quot;difficulty&quot;: &quot;0x8ae&quot;,
        &quot;number&quot;: &quot;0xd05&quot;,
        &quot;gasLimit&quot;: &quot;0x115c&quot;,
        &quot;gasUsed&quot;: &quot;0x15b3&quot;,
        &quot;timestamp&quot;: &quot;0x1a0a&quot;,
        &quot;extraData&quot;: &quot;0x7788&quot;,
        &quot;mixHash&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
        &quot;nonce&quot;: &quot;0x0000000000000000&quot;,
        &quot;hash&quot;: &quot;0x8c2f2af15b7b563b6ab1e09bed0e9caade7ed730aec98b70a993597a797579a9&quot;
      }
    ]
  }
}
```

```json
{
  &quot;type&quot;: &quot;GetBlockBodiesPacket66&quot;,
  &quot;rlp&quot;: &quot;0xf847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef&quot;,
  &quot;data&quot;: {
    &quot;RequestId&quot;: 1111,
    &quot;GetBlockBodiesPacket&quot;: [
      &quot;0x00000000000000000000000000000000000000000000000000000000deadc0de&quot;,
      &quot;0x00000000000000000000000000000000000000000000000000000000feedbeef&quot;
    ]
  }
}
```

```json
{
  &quot;type&quot;: &quot;BlockBodiesPacket66&quot;,
  &quot;rlp&quot;: &quot;0xf902dc820457f902d6f902d3f8d2f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afbf901fcf901f9a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000940000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008208ae820d0582115c8215b3821a0a827788a00000000000000000000000000000000000000000000000000000000000000000880000000000000000&quot;,
  &quot;data&quot;: {
    &quot;RequestId&quot;: 1111,
    &quot;BlockBodiesPacket&quot;: [
      {
        &quot;Transactions&quot;: [
          {
            &quot;nonce&quot;: &quot;0x8&quot;,
            &quot;gasPrice&quot;: &quot;0x4a817c808&quot;,
            &quot;gas&quot;: &quot;0x2e248&quot;,
            &quot;to&quot;: &quot;0x3535353535353535353535353535353535353535&quot;,
            &quot;value&quot;: &quot;0x200&quot;,
            &quot;input&quot;: &quot;0x&quot;,
            &quot;v&quot;: &quot;0x25&quot;,
            &quot;r&quot;: &quot;0x64b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12&quot;,
            &quot;s&quot;: &quot;0x64b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10&quot;,
            &quot;hash&quot;: &quot;0x588df025c4c2d757d3e314bd3dfbfe352687324e6b8557ad1731585e96928aed&quot;
          },
          {
            &quot;nonce&quot;: &quot;0x9&quot;,
            &quot;gasPrice&quot;: &quot;0x4a817c809&quot;,
            &quot;gas&quot;: &quot;0x33450&quot;,
            &quot;to&quot;: &quot;0x3535353535353535353535353535353535353535&quot;,
            &quot;value&quot;: &quot;0x2d9&quot;,
            &quot;input&quot;: &quot;0x&quot;,
            &quot;v&quot;: &quot;0x25&quot;,
            &quot;r&quot;: &quot;0x52f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb&quot;,
            &quot;s&quot;: &quot;0x52f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb&quot;,
            &quot;hash&quot;: &quot;0xf39c7dac06a9f3abf09faf5e30439a349d3717611b3ed337cd52b0d192bc72da&quot;
          }
        ],
        &quot;Uncles&quot;: [
          {
            &quot;parentHash&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
            &quot;sha3Uncles&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
            &quot;miner&quot;: &quot;0x0000000000000000000000000000000000000000&quot;,
            &quot;stateRoot&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
            &quot;transactionsRoot&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
            &quot;receiptsRoot&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
            &quot;logsBloom&quot;: &quot;0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000&quot;,
            &quot;difficulty&quot;: &quot;0x8ae&quot;,
            &quot;number&quot;: &quot;0xd05&quot;,
            &quot;gasLimit&quot;: &quot;0x115c&quot;,
            &quot;gasUsed&quot;: &quot;0x15b3&quot;,
            &quot;timestamp&quot;: &quot;0x1a0a&quot;,
            &quot;extraData&quot;: &quot;0x7788&quot;,
            &quot;mixHash&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
            &quot;nonce&quot;: &quot;0x0000000000000000&quot;,
            &quot;hash&quot;: &quot;0x8c2f2af15b7b563b6ab1e09bed0e9caade7ed730aec98b70a993597a797579a9&quot;
          }
        ]
      }
    ]
  }
}
```

```json
{
  &quot;type&quot;: &quot;GetNodeDataPacket66&quot;,
  &quot;rlp&quot;: &quot;0xf847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef&quot;,
  &quot;data&quot;: {
    &quot;RequestId&quot;: 1111,
    &quot;GetNodeDataPacket&quot;: [
      &quot;0x00000000000000000000000000000000000000000000000000000000deadc0de&quot;,
      &quot;0x00000000000000000000000000000000000000000000000000000000feedbeef&quot;
    ]
  }
}
```

```json
{
  &quot;type&quot;: &quot;NodeDataPacket66&quot;,
  &quot;rlp&quot;: &quot;0xce820457ca84deadc0de84feedbeef&quot;,
  &quot;data&quot;: {
    &quot;RequestId&quot;: 1111,
    &quot;NodeDataPacket&quot;: [
      &quot;0xdeadc0de&quot;,
      &quot;0xfeedbeef&quot;
    ]
  }
}
```

```json
{
  &quot;type&quot;: &quot;GetReceiptsPacket66&quot;,
  &quot;rlp&quot;: &quot;0xf847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef&quot;,
  &quot;data&quot;: {
    &quot;RequestId&quot;: 1111,
    &quot;GetReceiptsPacket&quot;: [
      &quot;0x00000000000000000000000000000000000000000000000000000000deadc0de&quot;,
      &quot;0x00000000000000000000000000000000000000000000000000000000feedbeef&quot;
    ]
  }
}
```

```json
{
  &quot;type&quot;: &quot;ReceiptsPacket66&quot;,
  &quot;rlp&quot;: &quot;0xf90172820457f9016cf90169f901668001b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f85ff85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff&quot;,
  &quot;data&quot;: {
    &quot;RequestId&quot;: 1111,
    &quot;ReceiptsPacket&quot;: [
      [
        {
          &quot;root&quot;: &quot;0x&quot;,
          &quot;status&quot;: &quot;0x0&quot;,
          &quot;cumulativeGasUsed&quot;: &quot;0x1&quot;,
          &quot;logsBloom&quot;: &quot;0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000&quot;,
          &quot;logs&quot;: [
            {
              &quot;address&quot;: &quot;0x0000000000000000000000000000000000000011&quot;,
              &quot;topics&quot;: [
                &quot;0x000000000000000000000000000000000000000000000000000000000000dead&quot;,
                &quot;0x000000000000000000000000000000000000000000000000000000000000beef&quot;
              ],
              &quot;data&quot;: &quot;0x0100ff&quot;,
              &quot;blockNumber&quot;: &quot;0x0&quot;,
              &quot;transactionHash&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
              &quot;transactionIndex&quot;: &quot;0x0&quot;,
              &quot;blockHash&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
              &quot;logIndex&quot;: &quot;0x0&quot;,
              &quot;removed&quot;: false
            }
          ],
          &quot;transactionHash&quot;: &quot;0x00000000000000000000000000000000000000000000000000000000deadc0de&quot;,
          &quot;contractAddress&quot;: &quot;0x0000000000000000000000000000000000011111&quot;,
          &quot;gasUsed&quot;: &quot;0x1b207&quot;,
          &quot;blockHash&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
          &quot;transactionIndex&quot;: &quot;0x0&quot;
        }
      ]
    ]
  }
}
```

```json
{
  &quot;type&quot;: &quot;GetPooledTransactionsPacket66&quot;,
  &quot;rlp&quot;: &quot;0xf847820457f842a000000000000000000000000000000000000000000000000000000000deadc0dea000000000000000000000000000000000000000000000000000000000feedbeef&quot;,
  &quot;data&quot;: {
    &quot;RequestId&quot;: 1111,
    &quot;GetPooledTransactionsPacket&quot;: [
      &quot;0x00000000000000000000000000000000000000000000000000000000deadc0de&quot;,
      &quot;0x00000000000000000000000000000000000000000000000000000000feedbeef&quot;
    ]
  }
}
```

```json
{
  &quot;type&quot;: &quot;PooledTransactionsPacket66&quot;,
  &quot;rlp&quot;: &quot;0xf8d7820457f8d2f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb&quot;,
  &quot;data&quot;: {
    &quot;RequestId&quot;: 1111,
    &quot;PooledTransactionsPacket&quot;: [
      {
        &quot;nonce&quot;: &quot;0x8&quot;,
        &quot;gasPrice&quot;: &quot;0x4a817c808&quot;,
        &quot;gas&quot;: &quot;0x2e248&quot;,
        &quot;to&quot;: &quot;0x3535353535353535353535353535353535353535&quot;,
        &quot;value&quot;: &quot;0x200&quot;,
        &quot;input&quot;: &quot;0x&quot;,
        &quot;v&quot;: &quot;0x25&quot;,
        &quot;r&quot;: &quot;0x64b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12&quot;,
        &quot;s&quot;: &quot;0x64b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10&quot;,
        &quot;hash&quot;: &quot;0x588df025c4c2d757d3e314bd3dfbfe352687324e6b8557ad1731585e96928aed&quot;
      },
      {
        &quot;nonce&quot;: &quot;0x9&quot;,
        &quot;gasPrice&quot;: &quot;0x4a817c809&quot;,
        &quot;gas&quot;: &quot;0x33450&quot;,
        &quot;to&quot;: &quot;0x3535353535353535353535353535353535353535&quot;,
        &quot;value&quot;: &quot;0x2d9&quot;,
        &quot;input&quot;: &quot;0x&quot;,
        &quot;v&quot;: &quot;0x25&quot;,
        &quot;r&quot;: &quot;0x52f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb&quot;,
        &quot;s&quot;: &quot;0x52f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb&quot;,
        &quot;hash&quot;: &quot;0xf39c7dac06a9f3abf09faf5e30439a349d3717611b3ed337cd52b0d192bc72da&quot;
      }
    ]
  }
}
```

## Security Considerations

None

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 17 Jan 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2481</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2481</guid>
      </item>
    
      <item>
        <title>Deprecate the CALLCODE opcode</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2488-deprecate-the-callcode-opcode/3957</comments>
        
        <description>## Abstract

Deprecate `CALLCODE` in a *somewhat* backwards compatible way, by making it always return failure.

## Motivation

`CALLCODE` was part of the Frontier release of Ethereum. In the first few weeks/months it became clear
that it cannot accomplish its intended design goal. This was rectified with introducing `DELEGATECALL`
([EIP-7](/EIPs/EIPS/eip-7)) in the Homestead update (early 2016).

`CALLCODE` became never utilized, but it still puts a burden on EVM implementations.

Disabling it will not improve the situation for any client whose goal is to sync from genesis, but would
help light clients or clients planning to sync from a later point in time.

## Specification

If `block.number &gt;= FORK_BLOCK`, the `CALLCODE` (`0xf2`) instruction always returns `0`, which signals failure.

## Rationale

It would be possible just to remove the opcode and exceptionally abort if it is encountered.
However, by returning failure, the contract has a chance to act on it and potentially recover.

## Backwards Compatibility

This is a breaking change and has a potential to break contracts. The author expects no contracts of any value
should be affected.

TODO: validate this claim.

## Security Considerations

TBA

## Test Cases

TBA

## Implementation

TBA

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 20 Dec 2019 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2488</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2488</guid>
      </item>
    
      <item>
        <title>Baby Jubjub Elliptic Curve</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2494-baby-jubjub-elliptic-curve/3968</comments>
        
        <description>## Simple Summary

This proposal defines Baby Jubjub, an elliptic curve designed to work inside zk-SNARK circuits in Ethereum.

## Abstract

Two of the main issues behind why blockchain technology is not broadly used by individuals and industry are scalability and privacy guarantees. With a set of cryptographic tools called zero-knowledge proofs (ZKP) it is possible to address both of these problems. More specifically, the most suitable protocols for blockchain are called zk-SNARKs (zero-knowledge Succinct Non-interactive ARguments of Knowledge), as they are non-interactive, have succinct proof size and sublinear verification time. These types of protocols allow proving generic computational statements that can be modelled with arithmetic circuits defined over a finite field (also called zk-SNARK circuits). 

To verify a zk-SNARK proof, it is necessary to use an elliptic curve. In Ethereum, the curve is alt_bn128 (also referred as BN254), which has primer order `r`. With this curve, it is possible to generate and validate proofs of any `F_r`-arithmetic circuit. This EIP describes *Baby Jubjub*, an elliptic curve defined over the finite field `F_r` which can be used inside any zk-SNARK circuit, allowing for the implementation of cryptographic primitives that make use of elliptic curves, such as the Pedersen Hash or the Edwards Digital Signature Algorithm (EdDSA). 

## Motivation

A [zero knowledge proof](https://en.wikipedia.org/wiki/Zero-knowledge_proof) (ZKP) is a protocol that enables one party, the prover, to convince another, the verifier, that a statement is true without revealing any information beyond the veracity of the statement. [Non-Interactive ZKPs](https://people.csail.mit.edu/silvio/Selected%20Scientific%20Papers/Zero%20Knowledge/Noninteractive_Zero-Knowkedge.pdf) (NIZK) are a particular type of zero-knowledge proofs in which the prover can generate the proof without interaction with the verifier. NIZK protocols are very suitable for Ethereum applications, because they allow a smart contract to act as a verifier. This way, anyone can generate a proof and send it as part of a transaction to the smart contract, which can perform some action depending on whether the proof is valid or not. In this context, the most preferable NIZK are [zk-SNARK](https://eprint.iacr.org/2013/279.pdf) (Zero-knowledge Succinct Non Interactive ARgument of Knowledge), a set of non-interactive zero-knowledge protocols that have succinct proof size and sublinear verification time. The importance of these protocols is double: on the one hand, they help improve privacy guarantees, and on the other, they are a possible solution to scalability issues (e.g. see [zk-Rollup](https://github.com/barryWhiteHat/roll_up) project). 

Like most ZKPs, zk-SNARKs permit proving computational statements. For example, one can prove things like: the knowledge of a private key associated with a certain public key, the correct computation of a transaction, or the knowledge of the preimage of a particular hash. Importantly, one can do these things without leaking any information about the statements in question. In other words, without leaking any information about the private key, the transaction details, or the value of the preimage. More specifically, zk-SNARKs permit proving any computational statement that can be modelled with an `F_r`-arithmetic circuit, a circuit consisting of set of wires that carry values from the field `F_r` and connect them to addition and multiplication gates `mod r`. This type of circuits are often called zk-SNARK circuits. 

The implementation of most zk-SNARK protocols (e.g. [[Pinnochio]](https://eprint.iacr.org/2013/279.pdf) and [[Groth16]](https://eprint.iacr.org/2016/260.pdf)) make use of an elliptic curve for validating a proof. In Ethereum, the curve used is alt_bn128 (also referred as BN254), which has prime order `r`. While it is possible to generate and validate proofs of `F_r`-arithmetic circuits with BN254, it is not possible to use BN254 to implement elliptic-curve cryptography within these circuits. To implement functions that require the use of elliptic curves inside a zk-SNARK circuit -- such as the [Pedersen Hash](https://github.com/zcash/zips/blob/master/protocol/protocol.pdf) or the [Edwards Digital Signature Algorithm](https://tools.ietf.org/html/rfc8032) (EdDSA) -- a new curve with coordinates in `F_r` is needed. To this end, we propose in this EIP *Baby Jubjub*, an elliptic curve defined over `F_r` that can be used inside any `F_r`-arithmetic circuit. In the next sections we describe in detail the characteristics of the curve, how it was generated, and which security considerations were taken.

``` 
    inputs                zk-SNARK (alt_bn128)             output
            +--------------------------------------------+
            |   +--------------------+                   |
        ---&gt;|   | EdDSA (Baby Jubjub)|                   |
            |   +--------------------+                   | 
        ---&gt;|                                            |---&gt;
            |          +-----------------------------+   |
        ---&gt;|          | Pedersen Hash (Baby Jubjub) |   |
            |          +-----------------------------+   |
            +--------------------------------------------+
```

## Specification

### Definitions
Let `F_r` be the prime finite field with `r` elements, where
```
r = 21888242871839275222246405745257275088548364400416034343698204186575808495617
``` 

Let `E` be the twisted Edwards elliptic curve defined over `F_r` described by equation
```
ax^2 + y^2 = 1 + dx^2y^2
``` 
with parameters
```
a = 168700
d = 168696
```
We call **Baby Jubjub** the curve `E(F_r)`, that is, the subgroup of `F_r`-rational points of `E`.

### Order

Baby Jubjub has order 

```
n = 21888242871839275222246405745257275088614511777268538073601725287587578984328
```

which factors in 
```
n = h x l
```
where
```
h = 8
l = 2736030358979909402780800718157159386076813972158567259200215660948447373041
```
The parameter `h` is called *cofactor* and `l` is a prime number of 251 bits.

### Generator Point

The point `G = (x,y)` with coordinates 
```
x = 995203441582195749578291179787384436505546430278305826713579947235728471134
y = 5472060717959818805561601436314318772137091100104008585924551046643952123905
```
generates all `n` points of the curve.

### Base Point

The point `B = (x,y)` with coordinates

```
x = 5299619240641551281634865583518297030282874472190772894086521144482721001553
y = 16950150798460657717958625567821834550301663161624707787222815936182638968203
```
generates the subgroup of points `P` of Baby Jubjub satisfying `l * P = O`. That is, it generates the set of points of order `l` and origin `O`.

### Arithmetic

Let `P1 = (x1, y1)` and `P2 = (x2, y2)` be two arbitrary points of Baby Jubjub. Then `P1 + P2 = (x3, y3)` is calculated in the following way:
```
x3 = (x1*y2 + y1*x2)/(1 + d*x1*x2*y1*y2)
y3 = (y1*y2 - a*x1*x2)/(1 - d*x1*x2*y1*y2)
```
Note that both addition and doubling of points can be computed using a single formula. 

## Rationale

The search for Baby Jubjub was motivated by the need for an elliptic curve that allows the implementation of elliptic-curve cryptography in `F_r`-arithmetic circuits. The curve choice was based on three main factors: type of curve, generation process and security criteria. This section describes how these factors were addressed. 

**Form of the Curve**

Baby Jubjub is a **twisted Edwards** curve birationally equivalent to a **Montgomery** curve. The choice of this form of curve was based on the following facts: 
1. The Edwards-curve Digital Signature Scheme is based on twisted Edwards curves.
2. Twisted Edwards curves have a single complete formula for addition of points, which makes the implementation of the group law inside circuits very efficient [[Crypto08/013, Section 6]](https://eprint.iacr.org/2008/013.pdf).
3. As a twisted Edwards curve is generally birationally equivalent to a Montgomery curve [[Crypto08/13,Theorem 3.2]](https://eprint.iacr.org/2008/013.pdf), the curve can be easily converted from one form to another. As addition and doubling of points in a Montgomery curve can be performed very efficiently, computations outside the circuit can be done faster using this form and sped up inside circuits by combining it with twisted Edwards form (see [here](http://hyperelliptic.org/EFD/g1p/index.html)) for more details).

**Generation of the Curve**

Baby Jubjub was conceived as a solution to the circuit implementation of cryptographic schemes that require elliptic curves. As with any cryptographic protocol, it is important to reduce the possibility of a backdoor being present. As a result, we designed the generation process to be **transparent** and **deterministic** -- in order to make it clear that no external considerations were taken into account, and to ensure that the process can be reproduced and followed by anyone who wishes to do so.

The algorithm chosen for generating Baby Jubjub is based in the criteria defined in [[RFC7748, Appendix A.1]](https://tools.ietf.org/html/rfc7748) and can be found in [this github repository](https://github.com/barryWhiteHat/baby_jubjub). Essentially, the algorithm takes a prime number `p = 1 mod 4` and returns the lowest `A&gt;0` such that `A-2` is a multiple of 4 and such that the set of solutions in `F_p` of `y^2 = x^3 + Ax^2 + x` defines a Montgomery curve with cofactor 8. 

Baby Jubjub was generated by running the algorithm with the prime

`r =  21888242871839275222246405745257275088548364400416034343698204186575808495617`, 

which is the order of alt_bn128, the curve used to verify zk-SNARK proofs in Ethereum. The output of the algorithm was `A=168698`. Afterwards, the corresponding Montgomery curve was transformed into twisted Edwards form. Using SAGE libraries for curves, the order `n` of the curve and its factorization `n = 8*l` was calculated.

- **Choice of generator** : the generator point `G` is the point of order `n` with smallest positive `x`-coordinate in `F_r`. 
- **Choice of base point**: the base point `B` is chosen to be `B = 8*G`, which has order `l`. 

**Security Criteria**

It is crucial that Baby Jubjub be safe against well-known attacks. To that end, we decided that the curve should pass [SafeCurves](https://safecurves.cr.yp.to/) security tests, as they are known for gathering the best known attacks against elliptic curves. Supporting evidence that Baby Jubjub satisfies the SafeCurves criteria can be found [here](https://github.com/barryWhiteHat/baby_jubjub).


## Backwards Compatibility

Baby Jubjub is a twisted Edwards elliptic curve birational to different curves. So far, the curve has mainly been used in its original form, in Montomgery form, and in another (different representation) twisted Edwards form -- which we call the reduced twisted Edwards form.

Below are the three representations and the birational maps that make it possible to map points from one form of the curve to another. In all cases, the generator and base points are written in the form **`(x,y)`.**

### Forms of the Curve

All generators and base points are written in the form (x,y).

**Twisted Edwards Form** (standard)

- Equation: ``ax^2 + y^2 = 1 + dx^2y^2``
- Parameters: ``a = 168700, d = 168696``
- Generator point:
    ```
    (995203441582195749578291179787384436505546430278305826713579947235728471134, 5472060717959818805561601436314318772137091100104008585924551046643952123905)
    ```
- Base point:
    ```
    (5299619240641551281634865583518297030282874472190772894086521144482721001553, 16950150798460657717958625567821834550301663161624707787222815936182638968203)
    ```

**Montgomery Form**

- Equation: ``By^2 = x^3 + A x^2 + x``
- Parameters: ``A = 168698, B = 1``
- Generator point:
    ```
    (7, 4258727773875940690362607550498304598101071202821725296872974770776423442226)
    ```
- Base point:
    ```
    (7117928050407583618111176421555214756675765419608405867398403713213306743542, 14577268218881899420966779687690205425227431577728659819975198491127179315626)
    ```

**Reduced Twisted Edwards Form**

- Equation: ``a&apos; x^2 + y^2 = 1 + d&apos; x^2y^2``
- Parameters: 
    ```
    a&apos; = -1 
    d&apos; = 12181644023421730124874158521699555681764249180949974110617291017600649128846
    ```
- Generator point: 
    ```
    (4986949742063700372957640167352107234059678269330781000560194578601267663727, 5472060717959818805561601436314318772137091100104008585924551046643952123905)
    ```
- Base point:
    ```
    (9671717474070082183213120605117400219616337014328744928644933853176787189663, 16950150798460657717958625567821834550301663161624707787222815936182638968203)
    ```

### Conversion of Points

Following formulas allow to convert points from one form of the curve to another. We will denote the coordinates

* ``(u, v)`` for points in the Montomgery form, 
* ``(x, y)`` for points in the Twisted Edwards form and 
* ``(x&apos;, y&apos;)`` for points in reduced Twisted Edwards form.

Note that in the last conversion -- from Twisted Edwards to Reduced Twisted Edwards and back -- we also use the scaling factor `f`, where:
```
f = 6360561867910373094066688120553762416144456282423235903351243436111059670888
```
In the expressions one can also use directly `-f`, where:
```
-f = 15527681003928902128179717624703512672403908117992798440346960750464748824729
```

**Montgomery --&gt; Twisted Edwards**
```
(u, v) --&gt; (x, y)

x = u/v
y = (u-1)/(u+1)
```

**Twisted Edwards --&gt; Montgomery**
```
(x, y) --&gt; (u, v)

u = (1+y)/(1-y) 
v = (1+y)/((1-y)x)
```

**Montgomery --&gt; Reduced Twisted Edwards** 
```
(u, v) --&gt; (x&apos;, y&apos;)

x&apos; = u*(-f)/v 
y&apos; = (u-1)/(u+1) 
```

**Reduced Twisted Edwards --&gt; Montgomery**
```
(x&apos;, y&apos;) --&gt; (u, v)

u = (1+y&apos;)/(1-y&apos;)
v = (-f)*(1+y&apos;)/((1-y&apos;)*x&apos;)
```

**Twisted Edwards --&gt; Reduced Twisted Edwards** 
```
(x, y) --&gt; (x&apos;, y&apos;)

x&apos; = x*(-f)
y&apos; = y
```

**Reduced Twisted Edwards --&gt; Twisted Edwards** 
```
(x&apos;, y&apos;) --&gt; (x, y)

x = x&apos;/(-f)
y = y&apos;
```
## Security Considerations

This section specifies the safety checks done on Baby Jubjub. The choices of security parameters are based on [SafeCurves criteria](https://safecurves.cr.yp.to), and supporting evidence that Baby Jubjub satisfies the following requisites can be found [here](https://github.com/barryWhiteHat/baby_jubjub).

**Curve Parameters**

Check that all parameters in the specification of the curve describe a well-defined elliptic curve over a prime finite field.

- The number `r` is prime.
- Parameters `a` and `d` define an equation that corresponds to an elliptic curve.
- The product of `h` and `l` results into the order of the curve and the `G` point is a generator.
- The number `l` is prime and the `B` point has order `l`.

**Elliptic Curve Discrete Logarithm Problem**

Check that the discrete logarithm problem remains difficult in the given curve. We checked Baby Jubjub is resistant to the following known attacks.

- *Rho method* [[Blake-Seroussi-Smart, Section V.1]](https://www.cambridge.org/core/books/elliptic-curves-in-cryptography/16A2B60636EFA7EBCC3D5A5D01F28546): we require the cost for the rho method, which takes on average around `0.886*sqrt(l)` additions, to be above `2^100`.
- *Additive and multiplicative transfers* [[Blake-Seroussi-Smart, Section V.2]](https://www.cambridge.org/core/books/elliptic-curves-in-cryptography/16A2B60636EFA7EBCC3D5A5D01F28546): we require the embedding degree to be at least `(l − 1)/100`.
- *High discriminant* [[Blake-Seroussi-Smart, Section IX.3]](https://www.cambridge.org/core/books/elliptic-curves-in-cryptography/16A2B60636EFA7EBCC3D5A5D01F28546): we require the complex-multiplication field discriminant `D` to be larger than `2^100`.

**Elliptic Curve Cryptography**

- *Ladders* [[Montgomery]](https://wstein.org/edu/Fall2001/124/misc/montgomery.pdf): check the curve supports the Montgomery ladder.
- *Twists* [[SafeCurves, twist]](https://safecurves.cr.yp.to/twist.html): check it is secure against the small-subgroup attack, invalid-curve attacks and twisted-attacks.
- *Completeness* [[SafeCurves, complete]](https://safecurves.cr.yp.to/complete.html): check if the curve has complete single-scalar and multiple-scalar formulas.
- *Indistinguishability* [[IACR2013/325]](https://eprint.iacr.org/2013/325): check availability of maps that turn elliptic-curve points indistinguishable from uniform random strings.

## Test Cases

**Test 1 (Addition)**

Consider the points ``P1 = (x1, y1)`` and ``P2 = (x2, y2)`` with the following coordinates:
```
x1 = 17777552123799933955779906779655732241715742912184938656739573121738514868268
y1 = 2626589144620713026669568689430873010625803728049924121243784502389097019475

x2 = 16540640123574156134436876038791482806971768689494387082833631921987005038935
y2 = 20819045374670962167435360035096875258406992893633759881276124905556507972311
```
Then their sum `` P1+P2 = (x3, y3)`` is equal to:
```
x3 = 7916061937171219682591368294088513039687205273691143098332585753343424131937
y3 = 14035240266687799601661095864649209771790948434046947201833777492504781204499
```

**Test 2 (Doubling)**

Consider the points ``P1 = (x1, y1)`` and ``P2 = (x2, y2)`` with the following coordinates:
```
x1 = 17777552123799933955779906779655732241715742912184938656739573121738514868268,
y1 = 2626589144620713026669568689430873010625803728049924121243784502389097019475

x2 = 17777552123799933955779906779655732241715742912184938656739573121738514868268
y2 = 2626589144620713026669568689430873010625803728049924121243784502389097019475
```
Then their sum `` P1+P2 = (x3, y3)`` is equal to:
```
x3 = 6890855772600357754907169075114257697580319025794532037257385534741338397365
y3 = 4338620300185947561074059802482547481416142213883829469920100239455078257889
```

**Test 3 (Doubling the identity)**

Consider the points ``P1 = (x1, y1)`` and ``P2 = (x2, y2)`` with the following coordinates:
```
x1 = 0
y1 = 1

x2 = 0
y2 = 1
```
Then their sum `` P1+P2 = (x3, y3)`` results in the same point:
```
x3 = 0
y3 = 1
```

**Test 4 (Curve membership)**

Point ``(0,1)`` is a point on Baby Jubjub. 

Point ``(1,0)`` is not a point on Baby Jubjub.

**Test 5 (Base point choice)**

Check that the base point `` B = (Bx, By)`` with coordinates

```
Bx = 5299619240641551281634865583518297030282874472190772894086521144482721001553
By = 16950150798460657717958625567821834550301663161624707787222815936182638968203
```
is 8 times the generator point ``G = (Gx, Gy)``, where 
``` 
Gx = 995203441582195749578291179787384436505546430278305826713579947235728471134
Gy = 5472060717959818805561601436314318772137091100104008585924551046643952123905
```
That is, check that ``B = 8 x G``.

**Test 6 (Base point order)**

Check that the base point `` B = (Bx, By)`` with coordinates

```
Bx = 5299619240641551281634865583518297030282874472190772894086521144482721001553
By = 16950150798460657717958625567821834550301663161624707787222815936182638968203
```
multiplied by `l`, where
```
l = 2736030358979909402780800718157159386076813972158567259200215660948447373041
```
results in the origin point `O = (0, 1)`. This test checks that the base point `B` has order `l`. 

## Implementation

Arithmetic of Baby Jubjub and some cryptographic primitives using the curve have already been implemented in different languages. Here are a few such implementations:

- Python: https://github.com/barryWhiteHat/baby_jubjub_ecc
- JavaScript: https://github.com/iden3/circomlib/blob/master/src/babyjub.js
- Circuit (circom): https://github.com/iden3/circomlib/blob/master/circuits/babyjub.circom
- Rust: https://github.com/arnaucube/babyjubjub-rs
- Solidity: https://github.com/yondonfu/sol-baby-jubjub
- Go: https://github.com/iden3/go-iden3-crypto/tree/master/babyjub

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 29 Jan 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2494</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2494</guid>
      </item>
    
      <item>
        <title>Implement Difficulty Freeze</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2515-replace-the-difficulty-bomb-with-a-difficulty-freeze/3995</comments>
        
        <description>## Simple Summary
The difficulty Freeze is an alternative to the Difficulty Bomb that is implemented within the protocols difficulty adjustment algorithm. The Difficulty Freeze begins at a certain block height, determined in advance, freezes the difficulty and increases by 1% after that block forever. This does not stop the chain, but it incentivizes devs to upgrade at a regular cadence and requires any chain split to address the difficulty freeze.

## Abstract
The difficulty Freeze is a mechanism that is easy to predict and model, and the pressures of missing it are more readily felt by the core developers and client maintainers. The client maintainers are also positioned as the group that is most able to respond to an incoming Difficulty Freeze. This combined with the predictability is more likely to lead to the timely diffusual of the bomb. 


## Motivation
The current difficulty bombs&apos; effect on the Block Time Targeting mechanism is rather complex to model, and it has both appeared when it was not expected (Muir Glacier) and negatively affected miners when they are not the target (in the case of delaying forks due to technical difficulties). Miners are affected by a reduction in block rewards due to the increase in block time. Users are affected as a function of the usability of the chain is affected by increased block times. Both of these groups are unable on their own to address the difficulty bomb. In the case of the Difficulty Freeze, the consequences of missing it are more directly felt by the client maintainers and it is more predictiable and so knowing when to make the change is readily apparent.

## Specification

Add variable `DIFFICULTY_FREEZE_HEIGHT`


The logic of the Difficulty Freeze is defined as follows:

```
if (BLOCK_HEIGHT &lt;= DIFFICULTY_FREEZE_HEIGHT):
   block_diff = parent_diff + parent_diff // 2048 * max(
                1 - (block_timestamp - parent_timestamp) // 10, -99)

else:
 block_diff = parent_diff + parent_diff * 0.01
```

**Optional Implementation**

Add the variable `DIFFICULTY_FREEZE_DIFFERENCE` and use the `LAST_FORK_HEIGHT` to calculate when the Difficulty Freeze would occur.

For example we can set the `DFD = 1,800,000 blocks` or approximately 9 months. The Difficulty Calculation would then be.

```
if (BLOCK_HEIGHT  &lt;= LAST_FORK_HEIGHT + DIFFICULTY_FREEZE_DIFFERENCE) :
   block_diff = parent_diff + parent_diff // 2048 * max(
                1 - (block_timestamp - parent_timestamp) // 10, -99)

else:
 block_diff = parent_diff + parent_diff * 0.01
```

This approach would have the added benefit that updating the Difficulty Freeze is easier as it happens automatically at the time of every upgrade. The trade-off is that the logic for checking is more complex and would require further analysis and test cases to ensure no consensus bugs arise. 

## Rationale
Block height is very easy to predict and evaluate within the system. This removes the effect of the Difficulty Bomb on block time, simplifying the block time targeting mechanism. The addition of an increase in the difficulty was added after feedback that the game theory of the mechanism did not reliably result in .

https://twitter.com/quentinc137/status/1227110578235330562

## Backwards Compatibility
No backward incompatibilities

## Test Cases
TBD 
## Implementation
TBD

## Security Considerations
The effect of missing the Difficulty Freeze has a different impact than missing the Difficulty Bomb. At the point of a Difficulty freeze, the protocol is no longer able to adapt to changes in hash power on the network. This can lead to one of three scenarios.

 - The Hash rate Increases:
   Block Times would increase on the network for short time until the increase in difficulty is too high for the network to add any more miners.
 - The Hash rate decreases:
   Block times would increase. 
 - The Hash rate stays the same:
   A consistent increase in blocktimes.

Clients are motivated to have their client sync fully to the network and so are very motivated to keep this situation from occurring. Simultaneously delaying the Difficulty Freeze is most easily implemented by client teams. Therefore the group that is most negatively affected is also the group that can most efficiently address it.

## Economic Considerations

Under the current Difficult, Bomb issuance of ETH is reduced as the Ice Age takes affect. Under the Difficulty Freeze, it is more likely that issuance would increase for a short time; however, clients are motivated to prevent this and keep clients syncing effectively. This means it is much less likely to occur. The increase to the difficulty over time will eventually reduce blocktimes and also issuance.

It is also easy to predict when this change would happen, and stakeholders who are affected (Eth Holders) can keep client developers accountable by observing when the Difficulty Freeze is approaching and yell at them on twitter.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 10 Feb 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2515</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2515</guid>
      </item>
    
      <item>
        <title>Multiple contenthash records for ENS</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2393</comments>
        
        <description>## Simple Summary
ENS support for multiple `contenthash` records on a single ENS name.

## Motivation
Many applications are resolving ENS names to content hosted on distributed systems. To do this, they use `contenthash` record from ENS domain to know how to resolve names and which distributed system should be used.

However, the domain can store only one `contenthash` record which means that the site owner needs to decide which hosting system to use. Because there are many ENS-compatible hosting systems available (IPFS, Swarm, recently Onion and ZeroNet), and there will probably be even more in the future, lack of support for multiple records could become problematic. Instead, domains should be able to store multiple `contenthash` records to allow applications to resolve to multiple hosting systems.

## Specification
Setting and getting functions **MUST** have the same public interface as specified in EIP 1577. Additionally, they **MUST** also have new public interfaces introduced by this EIP:

* For setting a `contenthash` record, the `setContenthash` **MUST** provide additional `proto` parameter and use it to save the `contenthash`. When `proto` is not provided, it **MUST** save the record as default record.

  ```solidity
  function setContenthash(bytes32 node, bytes calldata proto, bytes calldata hash) external authorised(node);
  ```

* For getting a `contenthash` record, the `contenthash` **MUST** provide additional `proto` parameter and use it to get the `contenthash` for requested type. When `proto` is not provided, it **MUST** return the default record.

  ```solidity
  function contenthash(bytes32 node, bytes calldata proto) external view returns (bytes memory);
  ```

* Resolver that supports multiple `contenthash` records **MUST** return `true` for `supportsInterface` with interface ID `0x6de03e07`.

Applications that are using ENS `contenthash` records **SHOULD** handle them in the following way:

* If the application only supports one hosting system (like directly handling ENS from IPFS/Swarm gateways), it **SHOULD** request `contenthash` with a specific type. The contract **MUST** then return it and application **SHOULD** correctly handle it.

* If the application supports multiple hosting systems (like MetaMask), it **SHOULD** request `contenthash` without a specific type (like in EIP 1577). The contract **MUST** then return the default `contenthash` record.

## Rationale
The proposed implementation was chosen because it is simple to implement and supports all important requested features. However, it doesn&apos;t support multiple records for the same type and priority order, as they don&apos;t give much advantage and are harder to implement properly.

## Backwards Compatibility
The EIP is backwards-compatible with EIP 1577, the only differences are additional overloaded methods. Old applications will still be able to function correctly, as they will receive the default `contenthash` record.

## Implementation
```solidity
contract ContentHashResolver {
    bytes4 constant private MULTI_CONTENT_HASH_INTERFACE_ID = 0x6de03e07;
    mapping(bytes32=&gt;mapping(bytes=&gt;bytes)) hashes;

    function setContenthash(bytes32 node, bytes calldata proto, bytes calldata hash) external {
        hashes[node][proto] = hash;
        emit ContenthashChanged(node, hash);
    }

    function contenthash(bytes32 node, bytes calldata proto) external view returns (bytes memory) {
        return hashes[node][proto];
    }

    function supportsInterface(bytes4 interfaceID) public pure returns(bool) {
        return interfaceID == MULTI_CONTENT_HASH_INTERFACE_ID;
    }
}
```

## Security Considerations
TBD

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 18 Feb 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2520</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2520</guid>
      </item>
    
      <item>
        <title>ENSLogin</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/discussion-ens-login/3569</comments>
        
        <description>## 1. Abstract

This presents a method to improve a universal method of login to the ethereum blockchain, leveraging the metadata storage provided by the ENS. We consider a user to be logged in when we have an [EIP-1193](/EIPs/EIPS/eip-1193) provider that can sign transaction and messages on his behalf. This method is inspired by [Alex Van de Sande&apos;s work](https://www.youtube.com/watch?v=1LVwWknE-NQ) and [Web3Connect](https://web3connect.com). In the future, the approach described here-after should be extended to work with any blockchain.

## 2. Motivation

Multiple wallet solutions can be used to interact with the Ethereum blockchain. Some (metamask, gnosis, ...) are compatible as they inject a standardized wallet object in the browser without requiring any effort from the Dapp developers, but they require an effort on the user side (user has to install the plugin). Other solutions (Portis, Authereum, Torus, Universal Login, ...) propose a more seamless flow to non-crypto-aware users but require an integration effort from the Dapp developers. Hardware wallet (ledger, trezor, keepkey, ...) also require integration effort from the Dapp developers.

When Dapps integrate login with multiple solutions, they rely on the user choosing the correct wallet-provider. This could prove increasingly difficult as the number of wallet-provider increases, particularly for novice users. Additionally, if decentralized applications pick and choose only a handful of wallets to support, the current incumbent wallets will have a distinct advantage and new wallets will struggle to find adoption. This will create a less competitive environment and stifle innovation. Rather than relying on the user choosing which wallet-provider to connect with (as does Web3Connect), ENSLogin proposes to use user-owned ENS domain as entry points. Metadata attached to these ENS domains is used to detect which wallet-provider if used by the corresponding account.

That way, ENSLogin would allow any user to connect to any Dapp with any wallet, using a simple domain as a login.

## 3. Description

### 3.1. Overview

The ENSLogin works as follow:

* Request an ENS domain from the user
* Resolve the ENS domain to retrieve (see [EIP-137](/EIPs/EIPS/eip-137))
	* An address (see [EIP-137](/EIPs/EIPS/eip-137))
	* A text entry (see [EIP-634](/EIPs/EIPS/eip-634))
* Interpret the text entry and download the file it points to
* Evaluate the content of the downloaded file
* Return the corresponding object to the Dapp

At this point, the app should process like with any web3 provider. Calling the `enable()` functions should ask the users for wallet specific credentials is needed.

This workflow is to be implemented by an SDK that Dapp could easily import. The SDK would contain the resolution mechanism and support for both centralized and decentralized storage solution. Wallet-provider specific code should NOT be part of SDK. Wallet-provider specific code should only be present in the external file used to generate the web3 provider.

### 3.2. Details

* **Text entry resolution:** A pointer to the code needed to instantiate the wallet-provider is recorded using the ENS support for text entries (see [EIP-634](/EIPs/EIPS/eip-634)). The corresponding key is `enslogin` (**subject to change**). If no value is associated with the key `enslogin` at the targeted domain, we fallback to metadata store on the parent&apos;s node with the key `enslogin-default` (**subject to change**).
**Example:** for the ens domain `username.domain.eth`, the resolution would look for (in order):
	* `resolver.at(ens.owner(nodehash(&quot;username.domain.eth&quot;))).text(nodehash(&quot;username.domain.eth&quot;), &apos;enslogin&apos;)`
	* `resolver.at(ens.owner(nodehash(&quot;domain.eth&quot;))).text(nodehash(&quot;domain.eth&quot;), &apos;enslogin-default&apos;)`

* **Provider link:** Code for instantiating the wallet-provider must be pointed to in a standardized manner. **This is yet not specified.** The current approach uses a human-readable format `scheme://path` such as:

	* `ipfs://Qm12345678901234567890123456789012345678901234`
	* `https://server.com/enslogin-module-someprovider`

	And adds a suffix depending on the targeted blockchain type (see [SLIP 44](https://github.com/satoshilabs/slips/blob/master/slip-0044.md)) and language. Canonical case is a webapp using ethereum so the target would be:

	* `ipfs://Qm12345678901234567890123456789012345678901234/60/js`
	* `https://server.com/enslogin-module-someprovider/60/js`

	Note that this suffix mechanism is compatible with http/https as well as IPFS. It is a constraint on the storage layer as some may not be able to do this kind of resolution.

* **Provider instantiation:**
	* [JAVASCRIPT/ETHEREUM] The file containing the wallet-provider&apos;s code should inject a function `global.provider: (config) =&gt; Promise&lt;web3provider&gt;` that returns a promise to a standardized provider object. For EVM blockchains, the object should follow [EIP-1193](/EIPs/EIPS/eip-1193).
	* Other blockchain types/langages should be detailed in the future.


* **Configuration object:** In addition to the username (ENS domain), the Dapp should have the ability to pass a configuration object that could be used by the wallet-provider instantiating function. This configuration should include:
	* A body (common to all provider) that specify details about the targeted chain (network name / node, address of the ens entrypoint ...). If any of these are missing, a fallback can be used (mainnet as a default network, bootstrapping an in-browser IPFS node, ...).
	* Wallet provider-specific fields (**optional**, starting with one underscore `_`) can be added to pass additional, wallet-provider specific, parameters / debugging flags.
	* SDK specific fields (**optional**, starting with two underscores `__`) can be used to pass additional arguments.

	Minimal configuration:
	```
	{
		provider: {
			network: &apos;goerli&apos;
		}
	}
	```
	Example of advanced configuration object:
	```
	{
		provider: {
			network: &apos;goerli&apos;,
			ens:     &apos;0x112234455c3a32fd11230c42e7bccd4a84e02010&apos;
		},
		ipfs: {
			host: &apos;ipfs.infura.io&apos;,
			port: 5001,
			protocol: &apos;https&apos;
		},
		_authereum: {...},
		_portis: {...},
		_unilogin: {...},
		_torus: {...},
		__callbacks: {
			resolved: (username, addr, descr) =&gt; {
				console.log(`[CALLBACKS] resolved: ${username} ${addr} ${descr}`);
			},
			loading: (protocol, path) =&gt; {
				console.log(`[CALLBACKS] loading: ${protocol} ${path}`);
			},
			loaded: (protocol, path) =&gt; {
				console.log(`[CALLBACKS] loaded: ${protocol} ${path}`);
			}
		}
	}
	```

**TODO** *(maybe move that part to section 6.1)*:
Add [SLIP 44](https://github.com/satoshilabs/slips/blob/master/slip-0044.md) compliant blockchain description to the config for better multichain support. This will require a additional field `ENS network` to know which ethereum network to use for resolution when the targeted blockchain/network is not ethereum (could also be used for cross chain resolution on ethereum, for example xDAI login with metadata stored on mainnet)

### 3.3. Decentralization

Unlike solution like Web3Connect, ENSLogin proposes a modular approach that is decentralized by nature.
The code needed for a Dapp to use ENSLogin (hereafter referred to as the SDK) only contains lookup mechanism for the ethereum blockchain and the data storages solutions. The solution is limited by the protocols (https / ipfs / ...) that the SDK can interact with. Beyond that, any wallet-provider that follows the expected structure and that is available through one of the supported protocol is automatically compatible with all the Dapps proposing ENSLogin support. There is no need to go through a centralized approval process. Furthermore, deployed SDK do not need to be upgraded to benefit from the latest wallet updates. The only permissioned part of the protocol is in the ENS control of the users over the metadata that describes their wallet-provider implementation. Users could also rely on the fallback mechanism to have the wallet-provider update it for them.

### 3.4. Incentives

We believe ENSLogin&apos;s biggest strength is the fact that it aligns the incentives of Dapp developers and wallet-providers to follow this standard.

* A wallet-provider that implements the required file and make them available will ensure the compatibility of its wallet with all Dapps using ENSLogin. This will remove the burden of asking all Dapps to integrate their solutions, which Dapps are unlikely to do until the wallet as strong userbase. Consequently, ENSLogin will improve the competition between wallet-providers and encourage innovation in that space
* A Dapp that uses ENSLogin protocol, either by including the ENSLogin&apos;s SDK or by implementing compatible behaviour, will make itself available to all the users of all the compatible wallet. At some point, being compatible with ENSLogin will be the easiest to reach a large user-base.
* ENSLogin should be mostly transparent for the users. Most wallet provider will set up the necessary entries without requiring any effort from the user. Advanced users can take control over the wallet resolution process, which will be simple once the right tooling is available.

### 3.5. Drawbacks

While ENSLogin allows dapps to support any wallet for logging in, dapps still must choose which wallets they suggest to users for registration. This can be done through a component like Web3Connect or BlockNative&apos;s

## 4. Prototype

**TODO**

## 5. Support by the community

### 5.1. Adoption

| Name           | Live | Module | Assigns ENS names | support by default |
| -------------- | ---- | ------ | ----------------- | ------------------ |
| Argent         | yes  | no     | yes               | no                 |
| Authereum      | yes  | yes    | yes               | no                 |
| Fortmatic      | yes  | no     | no                | no                 |
| Gnosis Safe    | yes  | yes\*  | no                | no                 |
| Ledger         | yes  | beta   | no                | no                 |
| KeepKey        | yes  | no     | no                | no                 |
| Metamask       | yes  | yes    | no                | no                 |
| Opera          | yes  | yes\*  | no                | no                 |
| Portis         | yes  | yes    | no                | no                 |
| SquareLink     | yes  | no     | no                | no                 |
| Shipl          | no   | no     | no                | no                 |
| Torus          | yes  | yes    | no                | no                 |
| Trezor         | yes  | no     | no                | no                 |
| UniLogin       | beta | beta   | yes               | no                 |

\*use the metamask module

## 6. Possible evolutions

### 6.1. Multichain support

**TODO**

## 7. FAQ

### 7.1. Can anyone connect with my login? Where are my private keys stored?

ENSLogin only has access to what is recorded on the ENS, namely your address and the provider you use. Private key management is a is handled by the provider and is outside ENSLogin&apos;s scope. Some might store the key on disk. Other might rely on custodial keys stored on a remote (hopefully secure) server. Others might use a dedicated hardware component to handle signature and never directly have access to the private key.

### 7.2. How do I get an ENS Login?

**TODO** (this might need a separate ERC)
</description>
        <pubDate>Wed, 19 Feb 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2525</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2525</guid>
      </item>
    
      <item>
        <title>Diamonds, Multi-Facet Proxy</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/discussion-for-eip2535-diamonds/10459/</comments>
        
        <description>## Abstract

&lt;img align=&quot;right&quot; src=&quot;../assets/eip-2535/diamond.svg&quot; width=&quot;230&quot; height=&quot;230&quot; alt=&quot;Diamonds contract structure&quot;&gt;

This proposal standardizes diamonds, which are modular smart contract systems that can be upgraded/extended after deployment, and have virtually no size limit. More technically, a **diamond** is a contract with external functions that are supplied by contracts called **facets**. Facets are separate, independent contracts that can share internal functions, libraries, and state variables.

## Motivation

There are a number of different reasons to use diamonds. Here are some of them:

1. **A single address for unlimited contract functionality.** Using a single address for contract functionality makes deployment, testing and integration with other smart contracts, software and user interfaces easier.
1. **Your contract exceeds the 24KB maximum contract size.** You may have related functionality that it makes sense to keep in a single contract, or at a single contract address. A diamond does not have a max contract size.
1. **A diamond provides a way to organize contract code and data.** You may want to build a contract system with a lot of functionality. A diamond provides a systematic way to isolate different functionality and connect them together and share data between them as needed in a gas-efficient way. 
1. **A diamond provides a way to upgrade functionality.** Upgradeable diamonds can be upgraded to add/replace/remove functionality. Because diamonds have no max contract size, there is no limit to the amount of functionality that can be added to diamonds over time. Diamonds can be upgraded without having to redeploy existing functionality. Parts of a diamond can be added/replaced/removed while leaving other parts alone.
1. **A diamond can be immutable.** It is possible to deploy an immutable diamond or make an upgradeable diamond immutable at a later time.
1. **A diamond can reuse deployed contracts.** Instead of deploying contracts to a blockchain, existing already deployed, onchain contracts can be used to create diamonds. Custom diamonds can be created from existing deployed contracts. This enables the creation of on-chain smart contract platforms and libraries.

This standard is an improvement of [EIP-1538](/EIPs/EIPS/eip-1538). The same motivations of that standard apply to this standard.

A deployed facet can be used by any number of diamonds.

The diagram below shows two diamonds using the same two facets.

- `FacetA` is used by `Diamond1`
- `FacetA` is used by `Diamond2`
- `FacetB` is used by `Diamond1`
- `FacetB` is used by `Diamond2`

&lt;img src=&quot;../assets/eip-2535/facetreuse.png&quot; alt=&quot;Facet reuse&quot;&gt;

### Upgradeable Diamond vs. Centralized Private Database

Why have an upgradeable diamond instead of a centralized, private, mutable database?

1. Decentralized Autonomous Organizations (DAOs) and other governance systems can be used to upgrade diamonds.
1. Wide interaction and integration with the Ethereum ecosystem.
1. With open storage data and verified source code it is possible to show a provable history of trustworthiness.
1. With openness bad behavior can be spotted and reported when it happens.
1. Independent security and domain experts can review the change history of contracts and vouch for their history of trustworthiness.
1. It is possible for an upgradeable diamond to become immutable and trustless.

### Some Diamond Benefits

1. A stable contract address that provides needed functionality.
1. A single address with the functionality of multiple contracts (facets) that are independent from each other but can share internal functions, libraries and state variables.
1. Emitting events from a single address can simplify event handling.
1. A way to add, replace and remove multiple external functions atomically (in the same transaction).
1. Fine-grained upgrades, so you can change just the parts of a diamond that need to be changed.
1. Have greater control over when and what functions exist.
1. Decentralized Autonomous Organizations (DAOs), multisig contracts and other governance systems can be used to upgrade diamonds.
1. An event that shows what functions are added, replaced and removed.
1. The ability to show all changes made to a diamond.
1. Increase trust over time by showing all changes made to a diamond.
1. A way to look at a diamond to see its current facets and functions.
1. Have an immutable, trustless diamond.
1. Solves the 24KB maximum contract size limitation. Diamonds can be any size.
1. Separate functionality can be implemented in separate facets and used together in a diamond.
1. Diamonds can be created from already deployed, existing onchain contracts.
1. Larger contracts have to reduce their size by removing error messages and other things. You can keep your full functionality that you need by implementing a diamond.
1. Enables zero, partial or full diamond immutability as desired, and when desired.
1. The ability to develop and improve an application over time with an upgradeable diamond and then make it immutable and trustless if desired.
1. Develop incrementally and let your diamond grow with your application.
1. Upgrade diamonds to fix bugs, add functionality and implement new standards.
1. Organize your code with a diamond and facets.
1. Diamonds can be large (have many functions) but still be modular because they are compartmented with facets.
1. Contract architectures that call multiple contracts in a single transaction can save gas by condensing those contracts into a single diamond and accessing state variables directly.
1. Save gas by converting external functions to internal functions. This done by sharing internal functions between facets.
1. Save gas by creating external functions for gas-optimized specific use cases, such as bulk transfers.
1. Diamonds are designed for tooling and user-interface software.


## Specification

### Terms

1. A **diamond** is a facade smart contract that `delegatecall`s into its facets to execute function calls. A diamond is stateful. Data is stored in the contract storage of a diamond.
1. A **facet** is a stateless smart contract or Solidity library with external functions. A facet is deployed and one or more of its functions are added to one or more diamonds. A facet does not store data within its own contract storage but it can define state and read and write to the storage of one or more diamonds. The term facet comes from the diamond industry. It is a side, or flat surface of a diamond.
1. A **loupe facet** is a facet that provides introspection functions. In the diamond industry, a loupe is a magnifying glass that is used to look at diamonds.
1. An **immutable function** is an external function that cannot be replaced or removed (because it is defined directly in the diamond, or because the diamond&apos;s logic does not allow it to be modified).
1. A **mapping** for the purposes of this EIP is an association between two things and does not refer to a specific implementation.

The term **contract** is used loosely to mean a smart contract or deployed Solidity library.

When this EIP uses **function** without specifying internal or external, it means external function.

In this EIP the information that applies to external functions also applies to public functions.

### Overview

A diamond calls functions from its facets using `delegatecall`.

In the diamond industry diamonds are created and shaped by being cut, creating facets. In this standard diamonds are cut by adding, replacing or removing functions from facets.

### A Note on Implementing Interfaces

Because of the nature of diamonds, a diamond can implement an interface in one of two ways: directly (`contract Contract is Interface`), or by adding functions to it from one or more facets. For the purposes of this proposal, when a diamond is said to implement an interface, either method of implementation is permitted.

### Fallback Function

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 call data (known as the function selector) and executes that function from the facet using `delegatecall`.

A diamond&apos;s fallback function and `delegatecall` enable a diamond to execute a facet&apos;s function as if it was implemented by the diamond itself. The `msg.sender` and `msg.value` values do not change and only the diamond&apos;s storage is read and written to.

Here is an illustrative example of how a diamond&apos;s fallback function might be implemented:

```solidity
// Find facet for function that is called and execute the
// function if a facet is found and return any value.
fallback() external payable {
  // get facet from function selector
  address facet = selectorTofacet[msg.sig];
  require(facet != address(0));
  // Execute external function from facet using delegatecall and return any value.
  assembly {
    // copy function selector and any arguments
    calldatacopy(0, 0, calldatasize())
    // execute function call using the facet
    let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)
    // get any return value
    returndatacopy(0, 0, returndatasize())
    // return any return value or error back to the caller
    switch result
      case 0 {revert(0, returndatasize())}
      default {return (0, returndatasize())}
  }
}
```

This diagram shows the structure of a diamond:

&lt;img src=&quot;../assets/eip-2535/DiamondDiagram.png&quot; alt=&quot;Mapping facets and storage&quot;&gt;

### Storage

A state variable or storage layout organizational pattern is needed because Solidity&apos;s builtin storage layout system doesn&apos;t support proxy contracts or diamonds. The particular layout of storage is not defined in this EIP, but may be defined by later proposals. Examples of storage layout patterns that work with diamonds are [Diamond Storage](/EIPs/assets/eip-2535/storage-examples/DiamondStorage.sol) and [AppStorage](/EIPs/assets/eip-2535/storage-examples/AppStorage.sol).

Facets can share state variables by using the same structs at the same storage positions. Facets can share internal functions and libraries by inheriting the same contracts or using the same libraries. In these ways facets are separate, independent units but can share state and functionality.

The diagram below shows facets with their own data and data shared between them.

Notice that all data is stored in the diamond&apos;s storage, but different facets have different access to data.

In this diagram

- Only `FacetA` can access `DataA`
- Only `FacetB` can access `DataB`
- Only the diamond&apos;s own code can access `DataD`.
- `FacetA` and `FacetB` share access to `DataAB`.
- The diamond&apos;s own code, `FacetA` and `FacetB` share access to `DataABD`.

&lt;img src=&quot;../assets/eip-2535/diamondstorage1.png&quot; alt=&quot;Mapping code, data, and facets&quot;&gt;

### Solidity Libraries as Facets

Smart contracts or deployed Solidity libraries can be facets of diamonds.

Only Solidity libraries that have one or more external functions can be deployed to a blockchain and be a facet. 

Solidity libraries that contain internal functions only cannot be deployed and cannot be a facet. Internal functions from Solidity libraries are included in the bytecode of facets and contracts that use them. Solidity libraries with internal functions only are useful for sharing internal functions between facets. 

Solidity library facets have a few properties that match their use as facets:
* They cannot be deleted.
* They are stateless. They do not have contract storage.
* Their syntax prevents declaring state variables outside Diamond Storage.

### Adding/Replacing/Removing Functions

#### `IDiamond` Interface

All diamonds must implement the `IDiamond` interface.

During the deployment of a diamond any immutable functions and any external functions added to the diamond must be emitted in the `DiamondCut` event.

**A `DiamondCut` event must be emitted any time external functions are added, replaced, or removed.** This applies to all upgrades, all functions changes, at any time, whether through `diamondCut` or not. 

```solidity
interface IDiamond {
    enum FacetCutAction {Add, Replace, Remove}
    // Add=0, Replace=1, Remove=2

    struct FacetCut {
        address facetAddress;
        FacetCutAction action;
        bytes4[] functionSelectors;
    }

    event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);
}
```

The `DiamondCut` event records all function changes to a diamond.

#### `IDiamondCut` Interface

A diamond contains within it a mapping of function selectors to facet addresses. Functions are added/replaced/removed by modifying this mapping.

Diamonds should implement the `IDiamondCut` interface if after their deployment they allow modifications to their function selector mapping.

The `diamondCut` function updates any number of functions from any number of facets in a single transaction. Executing all changes within a single transaction prevents data corruption which could occur in upgrades done over multiple transactions.

`diamondCut` is specified for the purpose of interoperability. Diamond tools, software and user-interfaces should expect and use the standard `diamondCut` function.

```solidity
interface IDiamondCut is IDiamond {
    /// @notice Add/replace/remove any number of functions and optionally execute
    ///         a function with delegatecall
    /// @param _diamondCut Contains the facet addresses and function selectors
    /// @param _init The address of the contract or facet to execute _calldata
    /// @param _calldata A function call, including function selector and arguments
    ///                  _calldata is executed with delegatecall on _init
    function diamondCut(
        FacetCut[] calldata _diamondCut,
        address _init,
        bytes calldata _calldata
    ) external;
}
```

The `_diamondCut` argument is an array of `FacetCut` structs.

Each `FacetCut` struct contains a facet address and array of function selectors that are updated in a diamond.

For each `FacetCut` struct:

 * If the `action` is `Add`, update the function selector mapping for each `functionSelectors` item to the `facetAddress`. If any of the `functionSelectors` had a mapped facet, revert instead.
 * If the `action` is `Replace`, update the function selector mapping for each `functionSelectors` item to the `facetAddress`. If any of the `functionSelectors` had a value equal to `facetAddress` or the selector was unset, revert instead.
 * If the `action` is `Remove`, remove the function selector mapping for each `functionSelectors` item. If any of the `functionSelectors` were previously unset, revert instead.

Any attempt to replace or remove an immutable function must revert.

Being intentional and explicit about adding/replacing/removing functions helps catch and prevent upgrade mistakes.

##### Executing `_calldata`

After adding/replacing/removing functions the `_calldata` argument is executed with `delegatecall` on `_init`. This execution is done to initialize data or setup or remove anything needed or no longer needed after adding, replacing and/or removing functions.

If the `_init` value is `address(0)` then `_calldata` execution is skipped. In this case `_calldata` can contain 0 bytes or custom information.

### Inspecting Facets &amp; Functions

&gt; A loupe is a small magnifying glass used to look at diamonds.

Diamonds must support inspecting facets and functions by implementing the `IDiamondLoupe` interface.

#### `IDiamondLoupe` Interface

```solidity
// A loupe is a small magnifying glass used to look at diamonds.
// These functions look at diamonds
interface IDiamondLoupe {
    struct Facet {
        address facetAddress;
        bytes4[] functionSelectors;
    }

    /// @notice Gets all facet addresses and their four byte function selectors.
    /// @return facets_ Facet
    function facets() external view returns (Facet[] memory facets_);

    /// @notice Gets all the function selectors supported by a specific facet.
    /// @param _facet The facet address.
    /// @return facetFunctionSelectors_
    function facetFunctionSelectors(address _facet) external view returns (bytes4[] memory facetFunctionSelectors_);

    /// @notice Get all the facet addresses used by a diamond.
    /// @return facetAddresses_
    function facetAddresses() external view returns (address[] memory facetAddresses_);

    /// @notice Gets the facet that supports the given selector.
    /// @dev If facet is not found return address(0).
    /// @param _functionSelector The function selector.
    /// @return facetAddress_ The facet address.
    function facetAddress(bytes4 _functionSelector) external view returns (address facetAddress_);
}
```

See a [reference implementation](#reference-implementation) to see how this can be implemented.

The loupe functions can be used in user-interface software. A user interface calls these functions to provide information about and visualize diamonds.

The loupe functions can be used in deployment functionality, upgrade functionality, testing and other software.

### Implementation Points

A diamond must implement the following:

1. A diamond contains a fallback function and zero or more immutable functions that are defined within it.
1. A diamond associates function selectors with facets.
1. When a function is called on a diamond it executes immediately if it is an &quot;immutable function&quot; defined directly in the diamond. Otherwise the diamond&apos;s fallback function is executed. The fallback function finds the facet associated with the function and executes the function using `delegatecall`. If there is no facet for the function then optionally a default function may be executed. If there is no facet for the function and no default function and no other mechanism to handle it then execution reverts.
1. Each time functions are added, replaced or removed a `DiamondCut` event is emitted to record it.
1. A diamond implements the DiamondLoupe interface.
1. All immutable functions must be emitted in the `DiamondCut` event as new functions added. And the loupe functions must return information about immutable functions if they exist. The facet address for an immutable function is the diamond&apos;s address. Any attempt to delete or replace an immutable function must revert.

A diamond may implement the following:

1. [EIP-165](/EIPs/EIPS/eip-165)&apos;s `supportsInterface`. If a diamond has the `diamondCut` function then the interface ID used for it is `IDiamondCut.diamondCut.selector`. The interface ID used for the diamond loupe interface is `IDiamondLoupe.facets.selector ^ IDiamondLoupe.facetFunctionSelectors.selector ^ IDiamondLoupe.facetAddresses.selector ^ IDiamondLoupe.facetAddress.selector`.

The diamond address is the address that users interact with. The diamond address does not change. Only facet addresses can change by using the `diamondCut` function, or other function.

## Rationale

### Using Function Selectors

User interface software can be used to retrieve function selectors and facet addresses from a diamond in order show what functions a diamond has.

This standard is designed to make diamonds work well with user-interface software. Function selectors with the ABI of a contract provide enough information about functions to be useful for user-interface software.

### Gas Considerations

Delegating function calls does have some gas overhead. This is mitigated in several ways:

1. Because diamonds do not have a max size limitation it is possible to add gas optimizing functions for use cases. For example someone could use a diamond to implement the [EIP-721](/EIPs/EIPS/eip-721) standard and implement batch transfer functions to reduce gas (and make batch transfers more convenient).
1. Some contract architectures require calling multiple contracts in one transaction. Gas savings can be realized by condensing those contracts into a single diamond and accessing contract storage directly.
1. Facets can contain few external functions, reducing gas costs. Because it costs more gas to call a function in a contract with many functions than a contract with few functions.
1. The Solidity optimizer can be set to a high setting causing more bytecode to be generated but the facets will use less gas when executed.

### Versions of Functions

Software or a user can verify what version of a function is called by getting the facet address of the function. This can be done by calling the `facetAddress` function from the `IDiamondLoupe` interface. This function takes a function selector as an argument and returns the facet address where it is implemented.

### Default Function

Solidity provides the `fallback` function so that specific functionality can be executed when a function is called on a contract that does not exist in the contract. This same behavior can optionally be implemented in a diamond by implementing and using a default function, which is a function that is executed when a function is called on a diamond that does not exist in the diamond.

A default function can be implemented a number of ways and this standard does not specify how it must be implemented.

### Loupe Functions &amp; `DiamondCut` Event

To find out what functions a regular contract has it is only necessary to look at its verified source code.

The verified source code of a diamond does not include what functions it has so a different mechanism is needed.

A diamond has four standard functions called the loupe functions that are used to show what functions a diamond has.

The loupe functions can be used for many things including:
1. To show all functions used by a diamond.
1. To query services like Etherscan or files to retrieve and show all source code used by a diamond.
1. To query services like Etherscan or files to retrieve ABI information for a diamond.
1. To test or verify that a transaction that adds/replaces/removes functions on a diamond succeeded.
1. To find out what functions a diamond has before calling functions on it.
1. To be used by tools and programming libraries to deploy and upgrade diamonds.
1. To be used by user interfaces to show information about diamonds.
1. To be used by user interfaces to enable users to call functions on diamonds.

Diamonds support another form of transparency which is a historical record of all upgrades on a diamond. This is done with the `DiamondCut` event which is used to record all functions that are added, replaced or removed on a diamond. 

### Sharing Functions Between Facets

In some cases it might be necessary to call a function defined in a different facet. Here are ways to do this:

1. Copy internal function code in one facet to the other facet.
1. Put common internal functions in a contract that is inherited by multiple facets.
1. Put common internal functions in a Solidity library and use the library in facets.
1. A type safe way to call an external function defined in another facet is to do this: `MyOtherFacet(address(this)).myFunction(arg1, arg2)`
1. A more gas-efficient way to call an external function defined in another facet is to use delegatecall. Here is an example of doing that:
```solidity
DiamondStorage storage ds = diamondStorage();
bytes4 functionSelector = bytes4(keccak256(&quot;myFunction(uint256)&quot;));
// get facet address of function
address facet = ds.selectorToFacet[functionSelector];
bytes memory myFunctionCall = abi.encodeWithSelector(functionSelector, 4);
(bool success, bytes memory result) = address(facet).delegatecall(myFunctionCall);
```
6. Instead of calling an external function defined in another facet you can instead create an internal function version of the external function. Add the internal version of the function to the facet that needs to use it.

### Facets can be Reusable and Composable

A deployed facet can be used by any number of diamonds.

Different combinations of facets can be used with different diamonds.

It is possible to create and deploy a set of facets that are reused by different diamonds over time.

The ability to use the same deployed facets for many diamonds reduces deployment costs.

It is possible to implement facets in a way that makes them usable/composable/compatible with other facets. It is also possible to implement facets in a way that makes them not usable/composable/compatible with other facets.

A function signature is the name of a function and its parameter types. Example function signature: `myfunction(uint256)`. A limitation is that two external functions with the same function signature can’t be added to the same diamond at the same time because a diamond, or any contract, cannot have two external functions with the same function signature.

All the functions of a facet do not have to be added to a diamond. Some functions in a facet can be added to a diamond while other functions in the facet are not added to the diamond.

## Backwards Compatibility

This standard makes upgradeable diamonds compatible with future standards and functionality because new functions can be added and existing functions can be replaced or removed.

## Reference Implementation

All the Solidity code for a complete reference implementation has been put in a single file here: [Diamond.sol](/EIPs/assets/eip-2535/reference/Diamond.sol)

The same reference implementation has been organized into multiple files and directories and also includes a deployment script and tests. Download it as a zip file: [`EIP2535-Diamonds-Reference-Implementation.zip`](/EIPs/assets/eip-2535/reference/EIP2535-Diamonds-Reference-Implementation.zip)

## Security Considerations

### Ownership and Authentication

&gt; **Note:** The design and implementation of diamond ownership/authentication is **not** part of this standard. The examples given in this standard and in the reference implementation are just **examples** of how it could be done.

It is possible to create many different authentication or ownership schemes with this proposal. Authentication schemes can be very simple or complex, fine grained or coarse. This proposal does not limit it in any way. For example ownership/authentication could be as simple as a single account address having the authority to add/replace/remove functions. Or a decentralized autonomous organization could have the authority to only add/replace/remove certain functions.

Consensus functionality could be implemented such as an approval function that multiple different people call to approve changes before they are executed with the `diamondCut` function. These are just examples.

The development of standards and implementations of ownership, control and authentication of diamonds is encouraged.

### Arbitrary Execution with `diamondCut`

The `diamondCut` function allows arbitrary execution with access to the diamond&apos;s storage (through `delegatecall`). Access to this function must be restricted carefully.

### Do Not Self Destruct
Use of `selfdestruct` in a facet is heavily discouraged. Misuse of it can delete a diamond or a facet.

### Function Selector Clash

A function selector clash occurs when two different function signatures hash to the same four-byte hash. This has the unintended consequence of replacing an existing function in a diamond when the intention was to add a new function. This scenario is not possible with a properly implemented `diamondCut` function because it prevents adding function selectors that already exist.

### Transparency

Diamonds emit an event every time one or more functions are added, replaced or removed. All source code can be verified. This enables people and software to monitor changes to a contract. If any bad acting function is added to a diamond then it can be seen.

Security and domain experts can review the history of change of a diamond to detect any history of foul play.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 22 Feb 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2535</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2535</guid>
      </item>
    
      <item>
        <title>Precompile for BLS12-381 curve operations</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip2537-bls12-precompile-discussion-thread/4187</comments>
        
        <description>## Abstract

Add functionality to efficiently perform operations over the BLS12-381 curve, including those for BLS signature verification.

Along with the curve arithmetic, multi-scalar-multiplication operations are included to efficiently aggregate public keys or individual signer&apos;s signatures during BLS signature verification.

## Motivation

The motivation of this precompile is to add a cryptographic primitive that allows to get 120+ bits of security for operations over pairing friendly curve compared to the existing BN254 precompile that only provides 80 bits of security.

## Specification

### Constants

| Name                | Value | Comment            |
|---------------------|-------|--------------------|
| BLS12_G1ADD         | 0x0b  | precompile address |
| BLS12_G1MSM         | 0x0c  | precompile address |
| BLS12_G2ADD         | 0x0d  | precompile address |
| BLS12_G2MSM         | 0x0e  | precompile address |
| BLS12_PAIRING_CHECK | 0x0f  | precompile address |
| BLS12_MAP_FP_TO_G1  | 0x10  | precompile address |
| BLS12_MAP_FP2_TO_G2 | 0x11  | precompile address |

We introduce *seven* separate precompiles to perform the following operations:

- BLS12_G1ADD - to perform point addition in G1 (curve over base prime field) with a gas cost of `375` gas
- BLS12_G1MSM - to perform multi-scalar-multiplication (MSM) in G1 (curve over base prime field) with a gas cost formula defined in the corresponding section
- BLS12_G2ADD - to perform point addition in G2 (curve over quadratic extension of the base prime field) with a gas cost of `600` gas
- BLS12_G2MSM - to perform multi-scalar-multiplication (MSM) in G2 (curve over quadratic extension of the base prime field) with a gas cost formula defined in the corresponding section
- BLS12_PAIRING_CHECK - to perform a pairing operations between a set of *pairs* of (G1, G2) points a gas cost formula defined in the corresponding section
- BLS12_MAP_FP_TO_G1 - maps base field element into the G1 point with a gas cost of `5500` gas
- BLS12_MAP_FP2_TO_G2 - maps extension field element into the G2 point with a gas cost of `23800` gas

A mapping functions specification is included as a separate [document](/EIPs/assets/eip-2537/field_to_curve). This mapping function does NOT perform mapping of the byte string into a field element (as it can be implemented in many different ways and can be efficiently performed in EVM), but only does field arithmetic to map a field element into a curve point. Such functionality is required for signature schemes.

### Curve parameters

The BLS12 curve is fully defined by the following set of parameters (coefficient `A=0` for all BLS12 curves):

```
Base field modulus = p = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab
Fp - finite field of size p
Curve Fp equation: Y^2 = X^3+B (mod p)
B coefficient = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004
Main subgroup order = q = 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001
Extension tower
Fp2 construction:
Fp quadratic non-residue = nr2 = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa
Fp2 is Fp[X]/(X^2-nr2)
Curve Fp2 equation: Y^2 = X^3 + B*(v+1) where v is the square root of nr2
Fp6/Fp12 construction:
Fp2 cubic non-residue c0 = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
Fp2 cubic non-residue c1 = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
Twist parameters:
Twist type: M
B coefficient for twist c0 = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004
B coefficient for twist c1 = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004
Generators:
H1:
X = 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb
Y = 0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1
H2:
X c0 = 0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8
X c1 = 0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e
Y c0 = 0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801
Y c1 = 0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be
Pairing parameters:
|x| (miller loop scalar) = 0xd201000000010000
x is negative = true
```

One should note that base field modulus `p` is equal to `3 mod 4` that allows an efficient square root extraction, although as described below gas cost of decompression is larger than gas cost of supplying decompressed point data in `calldata`.

### Fields and Groups

Field Fp is defined as the finite field of size `p` with elements represented as integers between 0 and p-1 (both inclusive).

Field Fp2 is defined as `Fp[X]/(X^2-nr2)` with elements  `el = c0 + c1 * v`, where `v` is the formal square root of `nr2` represented as integer pairs `(c0,c1)`.

Group G1 is defined as a set of Fp pairs (points) `(x,y)` such that either `(x,y)` is  `(0,0)` or `x,y` satisfy the curve Fp equation.

Group G2 is defined as a set of Fp2 pairs (points) `(x&apos;,y&apos;)` such that either `(x,y)` is `(0,0)` or `(x&apos;,y&apos;)` satisfy the curve Fp2 equation.

### Fine points and encoding of base elements

#### Field elements encoding:

In order to produce inputs to an operation, one encodes elements of the base field and the extension field.

A base field element (Fp) is encoded as `64` bytes by performing the BigEndian encoding of the corresponding (unsigned) integer. Due to the size of `p`, the top `16` bytes are always zeroes. `64` bytes are chosen to have `32` byte aligned ABI (representable as e.g. `bytes32[2]` or `uint256[2]` with the latter assuming the BigEndian encoding). The corresponding integer **must** be less than field modulus.

For elements of the quadratic extension field (Fp2), encoding is byte concatenation of individual encoding of the coefficients totaling in `128` bytes for a total encoding. For an Fp2 element in a form `el = c0 + c1 * v` where `v` is the formal square root of a quadratic non-residue and `c0` and `c1` are Fp elements the corresponding byte encoding will be `encode(c0) || encode(c1)` where `||` means byte concatenation (or one can use `bytes32[4]` or `uint256[4]` in terms of Solidity types).

*Note on the top `16` bytes being zero*: it is required that an encoded element is &quot;in a field&quot;, which means strictly `&lt; modulus`. In BigEndian encoding it automatically means that for a modulus that is just `381` bit long the top `16` bytes in `64` bytes encoding are zeroes and this **must** be checked even if only a subslice of input data is used for actual decoding.

On inputs that can not be a valid encodings of field elements the precompile *must* return an error.

#### Encoding of points in G1/G2:

Points of G1 and G2 are encoded as byte concatenation of the respective encodings of the `x` and `y` coordinates. Total encoding length for a G1 point is thus `128` bytes and for a G2 point is `256` bytes.

#### Point of infinity encoding:

Also referred to as the &quot;zero point&quot;. For BLS12 curves, the point with coordinates `(0, 0)` (zeroes in Fp or Fp2) is *not* on the curve, so a sequence of `128` resp. `256` zero bytes, which naively would decode as `(0, 0)` is instead used by convention to encode the point of infinity of G1 resp. G2.

#### Encoding of scalars for multiplication operation:

A scalar for the multiplication operation is encoded as `32` bytes by performing BigEndian encoding of the corresponding (unsigned) integer. The corresponding integer is **not** required to be less than or equal to main subgroup order `q`.

#### Behavior on empty inputs:

Certain operations have variable length input, such as MSMs (takes a list of pairs `(point, scalar)`), or pairing (takes a list of `(G1, G2)` points). While their behavior is well-defined (from an arithmetic perspective) on empty inputs, this EIP discourages such use cases and variable input length operations must return an error if the input is empty.

### ABI for operations

#### ABI for G1 addition

G1 addition call expects `256` bytes as an input that is interpreted as byte concatenation of two G1 points (`128` bytes each). Output is an encoding of addition operation result - single G1 point (`128` bytes).

Error cases:

- Invalid coordinate encoding
- An input is neither a point on the G1 elliptic curve nor the infinity point
- Input has invalid length

Note:

There is no subgroup check for the G1 addition precompile.

#### ABI for G1 MSM

G1 MSM call expects `160*k` (`k` being a **positive** integer) bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of a G1 point (`128` bytes) and encoding of a scalar value (`32` bytes). Output is an encoding of MSM operation result - a single G1 point (`128` bytes).

Error cases:

- Invalid coordinate encoding
- An input is neither a point on the G1 elliptic curve nor the infinity point
- An input is on the G1 elliptic curve but not in the correct subgroup
- Input has invalid length

#### ABI for G2 addition

G2 addition call expects `512` bytes as an input that is interpreted as byte concatenation of two G2 points (`256` bytes each). Output is an encoding of addition operation result - a single G2 point (`256` bytes).

Error cases:

- Invalid coordinate encoding
- An input is neither a point on the G2 elliptic curve nor the infinity point
- Input has invalid length

Note:

There is no subgroup check for the G2 addition precompile.

#### ABI for G2 MSM

G2 MSM call expects `288*k` (`k` being a **positive** integer) bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes). Output is an encoding of MSM operation result - a single G2 point (`256` bytes).

Error cases:

- Invalid coordinate encoding
- An input is neither a point on the G2 elliptic curve nor the infinity point
- An input is on the G2 elliptic curve but not in the correct subgroup
- Input has invalid length

#### ABI for pairing check

Pairing check call expects `384*k`  (`k` being a **positive** integer)  bytes as an inputs that is interpreted as byte concatenation of `k` slices. Each slice has the following structure:

- `128` bytes of G1 point encoding
- `256` bytes of G2 point encoding

Each point is expected to be in the subgroup of order `q`.

It checks the equation `e(P1, Q1) * e(P2, Q2) * ... * e(Pk, Qk) == 1` in the pairing target field where `e` is the pairing operation. Output is `32` bytes where first `31` bytes are equal to `0x00` and the last byte is either `0x00` (false) or `0x01` (true).

Error cases:

- Invalid coordinate encoding
- An input is neither a point on its respective elliptic curve nor the infinity point
- An input is on its respective elliptic curve but not in the correct subgroup
- Input has invalid length

#### ABI for mapping Fp element to G1 point

Field-to-curve call expects `64` bytes as an input that is interpreted as an element of Fp. Output of this call is `128` bytes and is an encoded G1 point.

Error cases:

- Input has invalid length
- Input is not correctly encoded

#### ABI for mapping Fp2 element to G2 point

Field-to-curve call expects `128` bytes as an input that is interpreted as an element of Fp2. Output of this call is `256` bytes and is an encoded G2 point.

Error cases:

- Input has invalid length
- Input is not correctly encoded

### Gas burning on error

Following the current state of all other precompiles, if a call to one of the precompiles in this EIP results in an error then all the gas supplied along with a `CALL` or `STATICCALL` is burned.

### DDoS protection

A sane implementation of this EIP *should not* contain potential infinite loops (it is possible and not even hard to implement all the functionality without `while` loops) and the gas schedule accurately reflects the time spent on computations of the corresponding function (precompiles pricing reflects an amount of gas consumed in the worst case where such a case exists).

### Gas schedule

Assuming `EcRecover` precompile as a baseline.

#### G1 addition

`375` gas

#### G1 multiplication

`12000` gas

#### G2 addition

`600` gas

#### G2 multiplication

`22500` gas

#### G1/G2 MSM

MSMs are expected to be performed by Pippenger&apos;s algorithm (we can also say that it **must** be performed by Pippenger&apos;s algorithm to have a speedup that results in a discount over naive implementation by multiplying each pair separately and adding the results). For this case there was a table prepared for discount in case of `k &lt;= 128` points in the MSM with a discount cap `max_discount` for `k &gt; 128`.

The call cost is calculated as `(k * multiplication_cost * discount) // multiplier` where `multiplier = 1000`, `k` is a number of (scalar, point) pairs for the call, `multiplication_cost` is a corresponding G1/G2 multiplication cost presented above and `//` is an integer division.

G1 and G2 are priced separately, each having their own discount table and `max_discount`.

##### G1 discounts

Discounts table for G1 MSM as a vector of pairs `[k, discount]`:

```
[[1, 1000], [2, 949], [3, 848], [4, 797], [5, 764], [6, 750], [7, 738], [8, 728], [9, 719], [10, 712], [11, 705], [12, 698], [13, 692], [14, 687], [15, 682], [16, 677], [17, 673], [18, 669], [19, 665], [20, 661], [21, 658], [22, 654], [23, 651], [24, 648], [25, 645], [26, 642], [27, 640], [28, 637], [29, 635], [30, 632], [31, 630], [32, 627], [33, 625], [34, 623], [35, 621], [36, 619], [37, 617], [38, 615], [39, 613], [40, 611], [41, 609], [42, 608], [43, 606], [44, 604], [45, 603], [46, 601], [47, 599], [48, 598], [49, 596], [50, 595], [51, 593], [52, 592], [53, 591], [54, 589], [55, 588], [56, 586], [57, 585], [58, 584], [59, 582], [60, 581], [61, 580], [62, 579], [63, 577], [64, 576], [65, 575], [66, 574], [67, 573], [68, 572], [69, 570], [70, 569], [71, 568], [72, 567], [73, 566], [74, 565], [75, 564], [76, 563], [77, 562], [78, 561], [79, 560], [80, 559], [81, 558], [82, 557], [83, 556], [84, 555], [85, 554], [86, 553], [87, 552], [88, 551], [89, 550], [90, 549], [91, 548], [92, 547], [93, 547], [94, 546], [95, 545], [96, 544], [97, 543], [98, 542], [99, 541], [100, 540], [101, 540], [102, 539], [103, 538], [104, 537], [105, 536], [106, 536], [107, 535], [108, 534], [109, 533], [110, 532], [111, 532], [112, 531], [113, 530], [114, 529], [115, 528], [116, 528], [117, 527], [118, 526], [119, 525], [120, 525], [121, 524], [122, 523], [123, 522], [124, 522], [125, 521], [126, 520], [127, 520], [128, 519]]
```

`max_discount = 519`

##### G2 discounts

Discounts table for G2 MSM as a vector of pairs `[k, discount]`:

```
[[1, 1000], [2, 1000], [3, 923], [4, 884], [5, 855], [6, 832], [7, 812], [8, 796], [9, 782], [10, 770], [11, 759], [12, 749], [13, 740], [14, 732], [15, 724], [16, 717], [17, 711], [18, 704], [19, 699], [20, 693], [21, 688], [22, 683], [23, 679], [24, 674], [25, 670], [26, 666], [27, 663], [28, 659], [29, 655], [30, 652], [31, 649], [32, 646], [33, 643], [34, 640], [35, 637], [36, 634], [37, 632], [38, 629], [39, 627], [40, 624], [41, 622], [42, 620], [43, 618], [44, 615], [45, 613], [46, 611], [47, 609], [48, 607], [49, 606], [50, 604], [51, 602], [52, 600], [53, 598], [54, 597], [55, 595], [56, 593], [57, 592], [58, 590], [59, 589], [60, 587], [61, 586], [62, 584], [63, 583], [64, 582], [65, 580], [66, 579], [67, 578], [68, 576], [69, 575], [70, 574], [71, 573], [72, 571], [73, 570], [74, 569], [75, 568], [76, 567], [77, 566], [78, 565], [79, 563], [80, 562], [81, 561], [82, 560], [83, 559], [84, 558], [85, 557], [86, 556], [87, 555], [88, 554], [89, 553], [90, 552], [91, 552], [92, 551], [93, 550], [94, 549], [95, 548], [96, 547], [97, 546], [98, 545], [99, 545], [100, 544], [101, 543], [102, 542], [103, 541], [104, 541], [105, 540], [106, 539], [107, 538], [108, 537], [109, 537], [110, 536], [111, 535], [112, 535], [113, 534], [114, 533], [115, 532], [116, 532], [117, 531], [118, 530], [119, 530], [120, 529], [121, 528], [122, 528], [123, 527], [124, 526], [125, 526], [126, 525], [127, 524], [128, 524]]
```

`max_discount = 524`

#### Pairing check operation

The cost of the pairing check operation is `32600*k + 37700` where `k` is a number of pairs.

#### Fp-to-G1 mapping operation

Fp -&gt; G1 mapping is `5500` gas.

#### Fp2-to-G2 mapping operation

Fp2 -&gt; G2 mapping is `23800` gas

#### Gas schedule clarifications for the variable-length input

For MSM and pairing functions, the gas cost depends on the input length. The current state of how the gas schedule is implemented in major clients (at the time of writing) is that the gas cost function does *not* perform any validation of the length of the input and never returns an error. So we present a list of rules how the gas cost functions **must** be implemented to ensure consistency between clients and safety.

##### Gas schedule clarifications for G1/G2 MSM

Define a constant `LEN_PER_PAIR` that is equal to `160` for G1 operation and to `288` for G2 operation. Define a function `discount(k)` following the rules in the corresponding section, where `k` is number of pairs.

The following pseudofunction reflects how gas should be calculated:

```
k = floor(len(input) / LEN_PER_PAIR);
if k == 0 {
  return 0;
}
gas_cost = k * multiplication_cost * discount(k) // multiplier;
return gas_cost;
```

We use floor division to get the number of pairs. If the length of the input is not divisible by `LEN_PER_PAIR` we still produce *some* result, but later on the precompile will return an error. Also, the case when `k = 0` is safe: `CALL` or `STATICCALL` cost is non-zero, and the case with formal zero gas cost is already used in `Blake2f` precompile. In any case, the main precompile routine **must** produce an error on such an input because it violated encoding rules.

##### Gas schedule clarifications for pairing

Define a constant `LEN_PER_PAIR = 384`;

The following pseudofunction reflects how gas should be calculated:

```
k = floor(len(input) / LEN_PER_PAIR);
gas_cost = 32600*k + 37700;
return gas_cost;
```

We use floor division to get the number of pairs. If the length of the input is not divisible by `LEN_PER_PAIR` we still produce *some* result, but later on the precompile will return an error (the precompile routine **must** produce an error on such an input because it violated encoding rules).

## Rationale

The motivation section covers a total motivation to have operations over the BLS12-381 curves available. We also extend a rationale for more specific fine points.

### MSM as a separate call

Explicit separate MSM operation that allows one to save execution time (so gas) by both the algorithm used (namely Pippenger&apos;s algorithm) and (usually forgotten) by the fact that `CALL` operation in Ethereum is expensive (at the time of writing), so one would have to pay non-negligible overhead if e.g. for MSM of `100` points would have to call the multiplication precompile `100` times and addition for `99` times (roughly `138600` would be saved).

### No dedicated MUL call

Dedicated MUL precompiles which perform single G1/G2 point by scalar multiplication have exactly the same ABI as MSM with `k == 1`.
MSM has to inspect the input length to reject inputs of invalid lengths. Therefore, it should recognize the case of `k == 1` and invoke the underlying implementation of single point multiplication to avoid the overhead of more complex multi-scalar multiplication algorithm.

## Backwards Compatibility

There are no backward compatibility questions.

### Subgroup checks

MSMs and pairings MUST perform a subgroup check.
Implementations SHOULD use the optimized subgroup check method detailed in a dedicated [document](/EIPs/assets/eip-2537/fast_subgroup_checks).
On any input that fails the subgroup check, the precompile MUST return an error.
As endomorphism acceleration requires input on the correct subgroup, implementers MAY use endomorphism acceleration.

### Field to curve mapping

The algorithms and set of parameters for SWU mapping method are provided by a separate [document](/EIPs/assets/eip-2537/field_to_curve)

## Test Cases

Due to the large test parameters space, we first provide properties that various operations must satisfy. We use additive notation for point operations, capital letters (`P`, `Q`) for points, small letters (`a`, `b`) for scalars. The generator for G1 is labeled as `G`, the generator for G2 is labeled as `H`, otherwise we assume random points on a curve in a correct subgroup. `0` means either scalar zero or point at infinity. `1` means either scalar one or multiplicative identity. `group_order` is the main subgroup order. `e(P, Q)` means pairing operation where `P` is in G1, `Q` is in G2.

Required properties for basic ops (add/multiply):

- Commutativity: `P + Q = Q + P`
- Identity element: `P + 0 = P`
- Additive negation: `P + (-P) = 0`
- Doubling `P + P = 2*P`
- Subgroup check: `group_order * P = 0`
- Trivial multiplication check: `1 * P = P`
- Multiplication by zero: `0 * P = 0`
- Multiplication by the unnormalized scalar `(scalar + group_order) * P = scalar * P`

Required properties for pairing operation:

- Bilinearity `e(a*P, b*Q) = e(a*b*P, Q) = e(P, a*b*Q)`
- Non-degeneracy `e(P, Q) != 1`
- `e(P, 0*Q) = e(0*P, Q) = 1`
- `e(P, -Q) = e(-P, Q)`

Test vectors can be found [in the test vectors files](/EIPs/assets/eip-2537/test-vectors).

### Benchmarking test cases

A set of test vectors for quick benchmarking on new implementations is located in a separate [file](/EIPs/assets/eip-2537/bench_vectors)

## Reference Implementation

There are two fully spec compatible implementations on the day of writing:

- One in Rust language that is based on the [EIP-196](/EIPs/EIPS/eip-196) code and integrated with OpenEthereum for this library
- One implemented specifically for Geth as a part of the current codebase

## Security Considerations

Strictly following the spec will eliminate security implications or consensus implications in a contrast to the previous BN254 precompile.

Important topic is a &quot;constant time&quot; property for performed operations. We explicitly state that this precompile **IS NOT REQUIRED** to perform all the operations using constant time algorithms.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 21 Feb 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2537</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2537</guid>
      </item>
    
      <item>
        <title>BLS12-377 curve operations</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2539-bls12-377-precompile-discussion-thread/4659</comments>
        
        <description>## Abstract

This precompile adds operation on BLS12-377 curve (from Zexe paper) as a precompile in a set necessary to *efficiently* perform operations such as BLS signature verification and perform SNARKs verifications. Unique properties of BLS12-377 also later allow to have SNARKs that check BLS12-377 pairing in an efficient way and allow e.g. constant-size BLS signature aggregation.

If `block.number &gt;= X` we introduce *nine* separate precompiles to perform the following operations:

- BLS12_377_G1ADD - to perform point addition on a curve defined over prime field
- BLS12_377_G1MUL - to perform point multiplication on a curve defined over prime field
- BLS12_377_G1MULTIEXP - to perform multiexponentiation on a curve defined over prime field
- BLS12_377_G2ADD - to perform point addition on a curve twist defined over quadratic extension of the base field
- BLS12_377_G2MUL - to perform point multiplication on a curve twist defined over quadratic extension of the base field
- BLS12_377_G2MULTIEXP - to perform multiexponentiation on a curve twist defined over quadratic extension of the base field
- BLS12_377_PAIRING - to perform a pairing operations between a set of *pairs* of (G1, G2) points
- BLS12_377_MAP_FP_TO_G1 - maps base field element into the G1 point
- BLS12_377_MAP_FP2_TO_G2 - maps extension field element into the G2 point

Multiexponentiation operation is included to efficiently aggregate public keys or individual signer&apos;s signatures during BLS signature verification.

### Proposed addresses table

| Precompile              | Address |
| ----------------------- | ------- |
| BLS12_377_G1ADD         | 0x15    |
| BLS12_377_G1MUL         | 0x16    |
| BLS12_377_G1MULTIEXP    | 0x17    |
| BLS12_377_G2ADD         | 0x18    |
| BLS12_377_G2MUL         | 0x19    |
| BLS12_377_G2MULTIEXP    | 0x1a    |
| BLS12_377_PAIRING       | 0x1b    |
| BLS12_377_MAP_FP_TO_G1  | 0x1c    |
| BLS12_377_MAP_FP2_TO_G2 | 0x1d    |

## Motivation

Motivation of this precompile is to add a cryptographic primitive that allows to get 120+ bits of security for operations over pairing friendly curve compared to the existing BN254 precompile that only provides 80 bits of security. In addition it allows efficient one-time recursive proof aggregations, e.g. proofs about existence of BLS12-377 based signature.

## Specification

Curve parameters:

BLS12-377 curve is fully defined by the following set of parameters (coefficient `A=0` for all BLS12 curves):

```
Base field modulus = 0x01ae3a4617c510eac63b05c06ca1493b1a22d9f300f5138f1ef3622fba094800170b5d44300000008508c00000000001
B coefficient = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
Main subgroup order = 0x12ab655e9a2ca55660b44d1e5c37b00159aa76fed00000010a11800000000001
Extension tower:
Fp2 construction:
Fp quadratic non-residue = 0x01ae3a4617c510eac63b05c06ca1493b1a22d9f300f5138f1ef3622fba094800170b5d44300000008508bffffffffffc
Fp6/Fp12 construction:
Fp2 cubic non-residue c0 = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Fp2 cubic non-residue c1 = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
Twist parameters:
Twist type: D
B coefficient for twist c0 = 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
B coefficient for twist c1 = 0x010222f6db0fd6f343bd03737460c589dc7b4f91cd5fd889129207b63c6bf8000dd39e5c1ccccccd1c9ed9999999999a
Generators:
G1:
X = 0x008848defe740a67c8fc6225bf87ff5485951e2caa9d41bb188282c8bd37cb5cd5481512ffcd394eeab9b16eb21be9ef
Y = 0x01914a69c5102eff1f674f5d30afeec4bd7fb348ca3e52d96d182ad44fb82305c2fe3d3634a9591afd82de55559c8ea6
G2:
X c0 = 0x018480be71c785fec89630a2a3841d01c565f071203e50317ea501f557db6b9b71889f52bb53540274e3e48f7c005196
X c1 = 0x00ea6040e700403170dc5a51b1b140d5532777ee6651cecbe7223ece0799c9de5cf89984bff76fe6b26bfefa6ea16afe
Y c0 = 0x00690d665d446f7bd960736bcbb2efb4de03ed7274b49a58e458c282f832d204f2cf88886d8c7c2ef094094409fd4ddf
Y c1 = 0x00f8169fd28355189e549da3151a70aa61ef11ac3d591bf12463b01acee304c24279b83f5e52270bd9a1cdd185eb8f93
Pairing parameters:
|x| (miller loop scalar) = 0x8508c00000000001
x is negative = false
```

### Fine points and encoding of base elements

#### Field elements encoding:

To encode points involved in the operation one has to encode elements of the base field and the extension field.

Base field element (Fp) is encoded as `64` bytes by performing BigEndian encoding of the corresponding (unsigned) integer (top `16` bytes are always zeroes). `64` bytes are chosen to have `32` byte aligned ABI (representable as e.g. `bytes32[2]` or `uint256[2]`). Corresponding integer **must** be less than field modulus.

For elements of the quadratic extension field (Fp2) encoding is byte concatenation of individual encoding of the coefficients totaling in `128` bytes for a total encoding. For an Fp2 element in a form `el = c0 + c1 * v` where `v` is formal quadratic non-residue and `c0` and `c1` are Fp elements the corresponding byte encoding will be `encode(c0) || encode(c1)` where `||` means byte concatenation (or one can use `bytes32[4]` or `uint256[4]` in terms of Solidity types).

If encodings do not follow this spec anywhere during parsing in the precompile the precompile *must* return an error.

#### Encoding of points in G1/G2:

Points in either G1 (in base field) or in G2 (in extension field) are encoded as byte concatenation of encodings of the `x` and `y` affine coordinates. Total encoding length for G1 point is thus `128` bytes and for G2 point is `256` bytes.

#### Point of infinity encoding:

Also referred as &quot;zero point&quot;. For BLS12 curves point with coordinates `(0, 0)` (formal zeroes in Fp or Fp2) is *not* on the curve, so encoding of such point `(0, 0)` is used as a convention to encode point of infinity.

#### Encoding of scalars for multiplication operation:

Scalar for multiplication operation is encoded as `32` bytes by performing BigEndian encoding of the corresponding (unsigned) integer. Corresponding integer is **not** required to be less than or equal than main subgroup size.

### ABI for operations

#### ABI for G1 addition

G1 addition call expects `256` bytes as an input that is interpreted as byte concatenation of two G1 points (`128` bytes each). Output is an encoding of addition operation result - single G1 point (`128` bytes).

Error cases:
	- Either of points being not on the curve must result in error
	- Field elements encoding rules apply (obviously)
	- Input has invalid length

#### ABI for G1 multiplication

G1 multiplication call expects `160` bytes as an input that is interpreted as byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes). Output is an encoding of multiplication operation result - single G1 point (`128` bytes).

Error cases:
	- Point being not on the curve must result in error
	- Field elements encoding rules apply (obviously)
	- Input has invalid length

#### ABI for G1 multiexponentiation

G1 multiexponentiation call expects `160*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes). Output is an encoding of multiexponentiation operation result - single G1 point (`128` bytes).

Error cases:
	- Any of G1 points being not on the curve must result in error
	- Field elements encoding rules apply (obviously)
	- Input has invalid length

#### ABI for G2 addition

G2 addition call expects `512` bytes as an input that is interpreted as byte concatenation of two G2 points (`256` bytes each). Output is an encoding of addition operation result - single G2 point (`256` bytes).

Error cases:
	- Either of points being not on the curve must result in error
	- Field elements encoding rules apply (obviously)
	- Input has invalid length

#### ABI for G2 multiplication

G2 multiplication call expects `288` bytes as an input that is interpreted as byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes). Output is an encoding of multiplication operation result - single G2 point (`256` bytes).

Error cases:
	- Point being not on the curve must result in error
	- Field elements encoding rules apply (obviously)
	- Input has invalid length

#### ABI for G2 multiexponentiation

G2 multiexponentiation call expects `288*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes). Output is an encoding of multiexponentiation operation result - single G2 point (`256` bytes).

Error cases:
	- Any of G2 points being not on the curve must result in error
	- Field elements encoding rules apply (obviously)
	- Input has invalid length

#### ABI for pairing

Pairing call expects `384*k` bytes as an inputs that is interpreted as byte concatenation of `k` slices. Each slice has the following structure:
	- `128` bytes of G1 point encoding
	- `256` bytes of G2 point encoding

Output is a `32` bytes where first `31` bytes are equal to `0x00` and the last byte is `0x01` if pairing result is equal to multiplicative identity in a pairing target field and `0x00` otherwise.

Error cases:
	- Invalid encoding of any boolean variable must result in error
	- Any of G1 or G2 points being not on the curve must result in error
	- Any of G1 or G2 points are not in the correct subgroup
	- Field elements encoding rules apply (obviously)
	- Input has invalid length

#### ABI for mapping Fp element to G1 point

Field-to-curve call expects `64` bytes as input that is interpreted as an element of the base field. Output of this call is `128` bytes and is G1 point following respective encoding rules.

Error cases:
	- Input has invalid length
	- Input is not a valid field element

#### ABI for mapping Fp2 element to G2 point

Field-to-curve call expects `128` bytes as input that is interpreted as an element of the quadratic extension field. Output of this call is `256` bytes and is G2 point following respective encoding rules.

Error cases:
	- Input has invalid length
	- Input is not a valid field element

### Prevention of DDoS on error handling

This precompile performs extensive computations and in case of any errors during execution it MUST consume all gas from the gas schedule for the corresponding operation.

### Gas schedule

Assuming a constant `30 MGas/second` following prices are suggested.

#### G1 addition

`600` gas

#### G1 multiplication

`12000` gas

#### G2 addition

`4500` gas

#### G2 multiplication

`55000` gas

#### G1/G2 Multiexponentiation

Multiexponentiations are expected to be performed by the Peppinger algorithm (we can also say that it **must** be performed by Peppinger algorithm to have a speedup that results in a discount over naive implementation by multiplying each pair separately and adding the results). For this case there was a table prepared for discount in case of `k &lt;= 128` points in the multiexponentiation with a discount cap `max_discount` for `k &gt; 128`.

To avoid non-integer arithmetic call cost is calculated as `k * multiplication_cost * discount / multiplier` where `multiplier = 1000`, `k` is a number of (scalar, point) pairs for the call, `multiplication_cost` is a corresponding single multiplication call cost for G1/G2.

Discounts table as a vector of pairs `[k, discount]`:

```
[[1, 1200], [2, 888], [3, 764], [4, 641], [5, 594], [6, 547], [7, 500], [8, 453], [9, 438], [10, 423], [11, 408], [12, 394], [13, 379], [14, 364], [15, 349], [16, 334], [17, 330], [18, 326], [19, 322], [20, 318], [21, 314], [22, 310], [23, 306], [24, 302], [25, 298], [26, 294], [27, 289], [28, 285], [29, 281], [30, 277], [31, 273], [32, 269], [33, 268], [34, 266], [35, 265], [36, 263], [37, 262], [38, 260], [39, 259], [40, 257], [41, 256], [42, 254], [43, 253], [44, 251], [45, 250], [46, 248], [47, 247], [48, 245], [49, 244], [50, 242], [51, 241], [52, 239], [53, 238], [54, 236], [55, 235], [56, 233], [57, 232], [58, 231], [59, 229], [60, 228], [61, 226], [62, 225], [63, 223], [64, 222], [65, 221], [66, 220], [67, 219], [68, 219], [69, 218], [70, 217], [71, 216], [72, 216], [73, 215], [74, 214], [75, 213], [76, 213], [77, 212], [78, 211], [79, 211], [80, 210], [81, 209], [82, 208], [83, 208], [84, 207], [85, 206], [86, 205], [87, 205], [88, 204], [89, 203], [90, 202], [91, 202], [92, 201], [93, 200], [94, 199], [95, 199], [96, 198], [97, 197], [98, 196], [99, 196], [100, 195], [101, 194], [102, 193], [103, 193], [104, 192], [105, 191], [106, 191], [107, 190], [108, 189], [109, 188], [110, 188], [111, 187], [112, 186], [113, 185], [114, 185], [115, 184], [116, 183], [117, 182], [118, 182], [119, 181], [120, 180], [121, 179], [122, 179], [123, 178], [124, 177], [125, 176], [126, 176], [127, 175], [128, 174]]
```

`max_discount = 174`

#### Pairing operation

Cost of the pairing operation is `55000*k + 65000` where `k` is a number of pairs.

#### Fp-to-G1 mapping operation

Fp -&gt; G1 mapping is `5500` gas.

#### Fp2-to-G2 mapping operation

Fp2 -&gt; G2 mapping is `75000` gas

## Rationale

Motivation section covers a total motivation to have operations over BLS12-377 curve available. We also extend a rationale for move specific fine points.

### Multiexponentiation as a separate call

Explicit separate multiexponentiation operation that allows one to save execution time (so gas) by both the algorithm used (namely Peppinger algorithm) and (usually forgotten) by the fact that `CALL` operation in Ethereum is expensive (at the time of writing), so one would have to pay non-negigible overhead if e.g. for multiexponentiation of `100` points would have to call the multipication precompile `100` times and addition for `99` times (roughly `138600` would be saved).

## Backwards Compatibility

There are no backward compatibility questions.

### Important notes

#### Subgroup checks

Subgroup check **is mandatory** during the pairing call. Implementations *should* use fast subgroup checks: at the time of writing multiplication gas cost is based on `double-and-add` multiplication method that has a clear &quot;worst case&quot; (all bits are equal to one). For pairing operation it&apos;s expected that implementation uses faster subgroup check, e.g. by using wNAF multiplication method for elliptic curves that is ~ `40%` cheaper with windows size equal to 4. (Tested empirically. Savings are due to lower hamming weight of the group order and even lower hamming weight for wNAF. Concretely, subgroup check for both G1 and G2 points in a pair are around `35000` combined).

## Test Cases

Due to the large test parameters space we first provide properties that various operations must satisfy. We use additive notation for point operations, capital letters (`P`, `Q`) for points, small letters (`a`, `b`) for scalars. Generator for G1 is labeled as `G`, generator for G2 is labeled as `H`, otherwise we assume random point on a curve in a correct subgroup. `0` means either scalar zero or point of infinity. `1` means either scalar one or multiplicative identity. `group_order` is a main subgroup order. `e(P, Q)` means pairing operation where `P` is in G1, `Q` is in G2. 

Requeired properties for basic ops (add/multiply):
	- Commutativity: `P + Q = Q + P`
	- Additive negation: `P + (-P) = 0`
	- Doubling `P + P = 2*P`
	- Subgroup check: `group_order * P = 0`
	- Trivial multiplication check: `1 * P = P`
	- Multiplication by zero: `0 * P = 0`
	- Multiplication by the unnormalized scalar `(scalar + group_order) * P = scalar * P`

Required properties for pairing operation:
	- Degeneracy `e(P, 0*Q) = e(0*P, Q) = 1` 
	- Bilinearity `e(a*P, b*Q) = e(a*b*P, Q) = e(P, a*b*Q)` (internal test, not visible through ABI)

Test vector for all operations are expanded in this `csv` files in matter-labs&apos; 1962 proposol.

## Reference Implementation

There is a various choice of existing implementations of the curve operations. It may require extra work to add an ABI:
	- Code bases with fixed parameters
	  - Rust: matter-labs
	  - C++: matter-labs
	- Original implementation linked in Zexe paper in Rust: github.com/scipr-lab/zexe
	- Standalone in Go: github.com/kilic/bls12-377

## Security Considerations

Strictly following the spec will eliminate security implications or consensus implications in a contrast to the previous BN254 precompile.

Important topic is a &quot;constant time&quot; property for performed operations. We explicitly state that this precompile **IS NOT REQUIRED** to perform all the operations using constant time algorithms.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 26 Feb 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2539</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2539</guid>
      </item>
    
      <item>
        <title>New opcodes TXGASLIMIT and CALLGASLIMIT</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2542-add-txgaslimit-callgaslimit-txgasrefund-opcodes</comments>
        
        <description>## Simple Summary
A mechanism to allow smart contracts to access information on gas limits for the current transaction and execution frame.

## Abstract
Currently, there is an existing opcode `0x45 GASLIMIT` that provides access to the block gas limit. While this information may be useful in some cases, it is probably not a value that smart contract developers may be concerned about. The opcode `0x5a GAS` provides the remaining gas, not the initial one. Also, it is worth noting how existing `0x32 ORIGIN`, `0x33 CALLER`, `0x34 CALLVALUE` and `0x3a GASPRICE` opcodes set a pattern of having access to both the transaction and current execution frame state.
TBD: as 0x30 opcode range is exhausted, the proposed opcodes can be added to 0x50 range, or a new range can be added.

## Motivation
As concepts of relaying, meta-transactions, gas fees, and account abstraction gain popularity, it becomes critical for some contracts to be able to track gas expenditure with absolute precision. Without access to this data on an EVM level, such contracts resort to approximation, mimicking EVM logic on-chain, and some use-cases even become infeasible.

## Specification
If block.number &gt;= TBD, add three new opcodes:

TXGASLIMIT: 0x5c

Pushes the gas limit of the entire transaction onto the stack. This is a value of the &apos;startgas&apos; parameter signed by the externally owned account.    
Gas costs: 2 (same as `GASLIMIT`)

CALLGASLIMIT: 0x5d

Pushes the gas limit of the current execution frame onto the stack. This is the &apos;callGas&apos; value that was obtained after the application of the EIP-150 “all but one 64th” rule.  
Gas costs: 2 (same as `GASLIMIT`)

Also, consider renaming `0x45 GASLIMIT` to `BLOCKGASLIMIT` to avoid confusion.

## Rationale
Consider a solidity smart contract that wants to know how much gas the entire transaction or a part of it had consumed. It is not entirely possible with the current EVM. With proposed changes, using a pseudo-Solidity syntax, this information would be easily available:
```
function keepTrackOfGas(string memory message, uint256 number) public {
    ...
    uint gasUsed = msg.gasLimit - gasleft();
}
```
This is an extremely common use case, and multiple implementations suffer from not taking the non-accessible expenses into consideration. The state-of-the-art solution for the `gasUsed` problem is to access &apos;gasleft()&apos; as the first line of your smart contract.  
Note how variable transaction input size means the gas used by the transaction depends on the number of zero and non-zero bytes of input, as well `GTXDATANONZERO`. Another issue is that Solidity handles `public` methods by loading the entire input from `calldata` to `memory`, spending an unpredictable amount of gas.

Another application is for a method to have a requirement for a gas limit given to it. This situation arises quite commonly in the context of meta-transactions, where the msg.sender&apos;s account holder may not be too interested in the inner transaction&apos;s success. Exaggerated pseudocode:

```
function verifyGasLimit(uint256 desiredGasLimit, bytes memory signature, address signer, bytes memory someOtherData) public {
    require(ecrecover(abi.encodePacked(desiredGasLimit, someOtherData), signature) == signer, &quot;Signature does not match&quot;);
    require(tx.gasLimit == desiredGasLimit, &quot;Transaction limit does not match the signed value. The signer did not authorize that.&quot;);
    ...
}
``` 
In this situation it is not possible to rely on &apos;gasleft()&apos; value, because it is dynamic, depends on opcode and calldata pricing, and cannot be signed.


## Backwards Compatibility
This proposal introduces two new opcodes and renames an existing one, but stays fully backwards compatible apart from that.

## Forwards Compatibility
A major consideration for this proposal is its alignment with one or many possible future modifications to the EVM:

1. EIP-2489 Deprecate the GAS opcode (a.k.a. 39-UNGAS proposal)  
 There is a sentiment that the ability of smart contracts to perform &quot;gas introspection&quot; leads to the contracts being dependent on current opcode pricing.  
 While criticizing said misconception is beyond the scope of this EIP, in case there is a need to make a breaking change to the behavior of the existing `0x5a GAS` opcode, the same considerations will apply to the proposed opcodes. This means this EIP does not add any new restraints on EMV evolution.
 
2. Stateless Ethereum  
 The UNGAS proposal is said to be related to the ongoing project of Stateless Ethereum. It’s not strictly necessary for stateless Ethereum, but it is an idea for how to make future breaking changes to gas schedules easier.  
 As long as the concept of &apos;gas limit&apos; is part of the EVM, the author sees no reason proposed opcodes would conflict with Stateless Ethereum. Gas schedules are not exposed by this proposal.
 
3. Comparison with other controversial opcodes   
 There are opcodes that are not proposed for deprecation but face criticism. Examples include `0x32 ORIGIN` being misused by smart contract developers, or `0x46 CHAINID` making some smart-contracts &apos;unforkable&apos;.  
 This EIP neither encourages nor enables any bad security practices, and does not introduce any concepts that are new for EVM either.  
  
## Security considerations 

Existing smart contracts are not affected by this change.  
Smart contracts that will use proposed opcodes must not use them for the core of any security features, but only as a source of information about their execution environment.

## Implementation
The implementations must be completed before any EIP is given status &quot;Final&quot;, but it need not be completed before the EIP is accepted. While there is merit to the approach of reaching consensus on the specification and rationale before writing code, the principle of &quot;rough consensus and running code&quot; is still useful when it comes to resolving many discussions of API details.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 29 Feb 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2542</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2542</guid>
      </item>
    
      <item>
        <title>ENS Wildcard Resolution</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2544-ens-wildcard-resolution</comments>
        
        <description>## Abstract

The Ethereum Name Service Specification (EIP-137) establishes a two-step name resolution process. First, an ENS client performs the namehash algorithm on the name to determine the associated &quot;node&quot;, and supplies that node to the ENS Registry contract to determine the resolver. Then, if a resolver has been set on the Registry, the client supplies that same node to the resolver contract, which will return the associated address or other record.

As currently specified, this process terminates if a resolver is not set on the ENS Registry for a given node. This EIP changes the name resolution process by adding an additional step if a resolver is not set for a domain. This step strips out the leftmost label from the name, derives the node of the new fragment, and supplies that node to the ENS Registry. If a resolver is located for that node, the client supplies the original, complete node to that resolver contract to derive the relevant records. This step is repeated until a node with a resolver is found.

Further, this specification defines a new way for resolvers to resolve names, using a unified `resolve()` method that permits more flexible handling of name resolution.

## Motivation

Many applications such as wallet providers, exchanges, and dapps have expressed a desire to issue ENS names for their users via custom subdomains on a shared parent domain. However, the cost of doing so is currently prohibitive for large user bases, as a distinct record must be set on the ENS Registry for each subdomain.

Furthermore, users cannot immediately utilize these subdomains upon account creation, as the transaction to assign a resolver for the node of the subdomain must first be submitted and mined on-chain. This adds unnecessary friction when onboarding new users, who coincidentally would often benefit greatly from the usability improvements afforded by an ENS name.

Enabling wildcard support allows for the design of more advanced resolvers that deterministically generate addresses and other records for unassigned subdomains. The generated addresses could map to counterfactual contract deployment addresses (i.e. `CREATE2` addresses), to designated &quot;fallback&quot; addresses, or other schemes. Additionally, individual resolvers would still be assignable to any given subdomain, which would supersede the wildcard resolution using the parent resolver.

Another critical motivation with EIP-2544 is to enable wildcard resolution in a backwards-compatible fashion. It does not require modifying the current ENS Registry contract or any existing resolvers, and continues to support existing ENS records — legacy ENS clients would simply fail to resolve wildcard records.

## Specification

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.

Let:
 - `namehash` be the algorithm defined in EIP 137.
 - `dnsencode` be the process for encoding DNS names specified in section 3.1 of RFC1035, with the exception that there is no limit on the total length of the encoded name. The empty string is encoded identically to the name &apos;.&apos;, as a single 0-octet.
 - `parent` be a function that removes the first label from a name (eg, `parent(&apos;foo.eth&apos;) = &apos;eth&apos;`). `parent(&apos;tld&apos;)` is defined as the empty string &apos;&apos;.
 - `ens` is the ENS registry contract for the current network.

EIP-2544-compliant ENS resolvers MAY implement the following function interface:

```
interface ExtendedResolver {
    function resolve(bytes calldata name, bytes calldata data) external view returns(bytes);
}
```

If a resolver implements this function, it MUST return true when `supportsInterface()` is called on it with the interface&apos;s ID, 0xTBD.

ENS clients will call `resolve` with the DNS-encoded name to resolve and the encoded calldata for a resolver function (as specified in EIP-137 and elsewhere); the function MUST either return valid return data for that function, or revert if it is not supported.

EIP-2544-compliant ENS clients MUST perform the following procedure when determining the resolver for a given name:

1. Set `currentname = name`
2. Set `resolver = ens.resolver(namehash(currentname))`
3. If `resolver` is not the zero address, halt and return `resolver`.
4. If `name` is the empty name (&apos;&apos; or &apos;.&apos;), halt and return null.
5. Otherwise, set `currentname = parent(currentname)` and go to 2.

If the procedure above returns null, name resolution MUST terminate unsuccessfully. Otherwise, EIP-2544-compliant ENS clients MUST perform the following procedure when resolving a record:

1. Set `calldata` to the ABI-encoded call data for the resolution function required - for example, the ABI encoding of `addr(namehash(name))` when resolving the `addr` record.
2. Set `supports2544 = resolver.supportsInterface(0xTBD)`.
3. If `supports2544` is true, set `result = resolver.resolve(dnsencode(name), calldata)`
4. Otherwise, set `result` to the result of calling `resolver` with `calldata`.
5. Return `result` after decoding it using the return data ABI of the corresponding resolution function (eg, for `addr()`, ABI-decode the result of `resolver.resolve()` as an `address`).

Note that in all cases the resolution function (`addr()` etc) and the `resolve` function are supplied the original `name`, *not* the `currentname` found in the first stage of resolution.

### Pseudocode
```
function getResolver(name) {
    for(let currentname = name; currentname !== &apos;&apos;; currentname = parent(currentname)) {
        const node = namehash(currentname);
        const resolver = ens.resolver(node);
        if(resolver != &apos;0x0000000000000000000000000000000000000000&apos;) {
            return resolver;
        }
    }
    return null;
}

function resolve(name, func, ...args) {
    const resolver = getResolver(name);
    if(resolver === null) {
        return null;
    }
    const supports2544 = resolver.supportsInterface(&apos;0xTBD&apos;);
    let result;
    if(supports2544) {
        const calldata = resolver[func].encodeFunctionCall(namehash(name), ...args);
        result = resolver.resolve(dnsencode(name), calldata);
        return resolver[func].decodeReturnData(result);
    } else {
        return resolver[func](...args);
    }
}
```

## Rationale

The proposed implementation supports wildcard resolution in a manner that minimizes the impact to existing systems. It also reuses existing algorithms and procedures to the greatest possible extent, thereby easing the burden placed on authors and maintainers of various ENS clients.

It also recognizes an existing consensus concerning the desirability of wildcard resolution for ENS, enabling more widespread adoption of the original specification by solving for a key scalability obstacle.

While introducing an optional `resolve` function for resolvers, taking the unhashed name and calldata for a resolution function increases implementation complexity, it provides a means for resolvers to obtain plaintext labels and act accordingly, which enables many wildcard-related use-cases that would otherwise not be possible - for example, a wildcard resolver could resolve `id.nifty.eth` to the owner of the NFT with id `id` in some collection. With only namehashes to work with, this is not possible. Resolvers with simpler requirements can continue to simply implement resolution functions directly and omit support for the `resolve` function entirely.

The DNS wire format is used for encoding names as it permits quick and gas-efficient hashing of names, as well as other common operations such as fetching or removing individual labels; in contrast, dot-separated names require iterating over every character in the name to find the delimiter.

## Backwards Compatibility

Existing ENS clients that are compliant with EIP-137 will fail to resolve wildcard records and refuse to interact with them, while those compliant with EIP-2544 will continue to correctly resolve, or reject, existing ENS records. Resolvers wishing to implement the new `resolve` function for non-wildcard use-cases (eg, where the resolver is set directly on the name being resolved) should consider what to return to legacy clients that call the individual resolution functions for maximum compatibility.

## Security Considerations

While compliant ENS clients will continue to refuse to resolve records without a resolver, there is still the risk that an improperly-configured client will refer to an incorrect resolver, or will not reject interactions with the null address when a resolver cannot be located.

Additionally, resolvers supporting completely arbitrary wildcard subdomain resolution will increase the likelihood of funds being sent to unintended recipients as a result of typos. Applications that implement such resolvers should consider making additional name validation available to clients depending on the context, or implementing features that support recoverability of funds.

There is also the possibility that some applications might require that no resolver be set for certain subdomains. For this to be problematic, the parent domain would need to successfully resolve the given subdomain node — to the knowledge of the authors, no application currently supports this feature or expects that subdomains should not resolve to a record.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 28 Feb 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2544</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2544</guid>
      </item>
    
      <item>
        <title>ModExp Gas Cost</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/big-integer-modular-exponentiation-eip-198-gas-cost/4150</comments>
        
        <description>## Simple Summary
Defines the gas cost of the `ModExp` (`0x00..05`) precompile.

## Abstract
To accurately reflect the real world operational cost of the `ModExp` precompile, this EIP specifies an algorithm for calculating the gas cost. This algorithm approximates the multiplication complexity cost and multiplies that by an approximation of the iterations required to execute the exponentiation.

## Motivation
Modular exponentiation is a foundational arithmetic operation for many cryptographic functions including signatures, VDFs, SNARKs, accumulators, and more. Unfortunately, the ModExp precompile is currently over-priced, making these operations inefficient and expensive. By reducing the cost of this precompile, these cryptographic functions become more practical, enabling improved security, stronger randomness (VDFs), and more.

## Specification
As of `FORK_BLOCK_NUMBER`, the gas cost of calling the precompile at address `0x0000000000000000000000000000000000000005` will be calculated as follows:
```
def calculate_multiplication_complexity(base_length, modulus_length):
    max_length = max(base_length, modulus_length)
    words = math.ceil(max_length / 8)
    return words**2

def calculate_iteration_count(exponent_length, exponent):
    iteration_count = 0
    if exponent_length &lt;= 32 and exponent == 0: iteration_count = 0
    elif exponent_length &lt;= 32: iteration_count = exponent.bit_length() - 1
    elif exponent_length &gt; 32: iteration_count = (8 * (exponent_length - 32)) + ((exponent &amp; (2**256 - 1)).bit_length() - 1)
    return max(iteration_count, 1)

def calculate_gas_cost(base_length, modulus_length, exponent_length, exponent):
    multiplication_complexity = calculate_multiplication_complexity(base_length, modulus_length)
    iteration_count = calculate_iteration_count(exponent_length, exponent)
    return max(200, math.floor(multiplication_complexity * iteration_count / 3))
```

## Rationale
After benchmarking the ModExp precompile, we discovered that it is ‘overpriced’ relative to other precompiles. We also discovered that the current gas pricing formula could be improved to better estimate the computational complexity of various ModExp input variables. The following changes improve the accuracy of the `ModExp` pricing:

### 1. Modify ‘computational complexity’ formula to better reflect the computational complexity
The complexity function defined in [EIP-198](/EIPs/EIPS/eip-198) is as follow:

```
def mult_complexity(x):
    if x &lt;= 64: return x ** 2
    elif x &lt;= 1024: return x ** 2 // 4 + 96 * x - 3072
    else: return x ** 2 // 16 + 480 * x - 199680
```
where is `x` is `max(length_of_MODULUS, length_of_BASE)`

The complexity formula in [EIP-198](/EIPs/EIPS/eip-198) was meant to approximate the difficulty of Karatsuba multiplication. However, we found a better approximation for modelling modular exponentiation. In the complexity formula defined in this EIP, `x` is divided by 8 to account for the number of limbs in multiprecision arithmetic. A comparison of the current ‘complexity’ function and the proposed function against the execution time can be seen below:

![Option 1 Graph](/EIPs/assets/eip-2565/Complexity_Regression.png)

The complexity function defined here has a better fit vs. the execution time when compared to the [EIP-198](/EIPs/EIPS/eip-198) complexity function. This better fit is because this complexity formula accounts for the use of binary exponentiation algorithms that are used by ‘bigint’ libraries for large exponents. You may also notice the regression line of the proposed complexity function bisects the test vector data points. This is because the run time varies depending on if the modulus is even or odd.

### 2. Change the value of GQUADDIVISOR
After changing the &apos;computational complexity&apos; formula in [EIP-198](/EIPs/EIPS/eip-198) to the one defined here it is necessary to change `QGUADDIVSOR` to bring the gas costs inline with their runtime. By setting the `QGUADDIVISOR` to `3` the cost of the ModExp precompile will have a higher cost (gas/second) than other precompiles such as ECRecover.

![Option 2 Graph](/EIPs/assets/eip-2565/GQuad_Change.png)

### 3. Set a minimum gas cost to prevent abuse
This prevents the precompile from underpricing small input values.

## Test Cases
There are no changes to the underlying interface or arithmetic algorithms, so the existing test vectors can be reused. Below is a table with the updated test vectors:

| Test Case  | EIP-198 Pricing | EIP-2565 Pricing |
| ------------- | ------------- | ------------- |
| modexp_nagydani_1_square | 204  | 200  |
| modexp_nagydani_1_qube | 204  | 200  |
| modexp_nagydani_1_pow0x10001 | 3276  | 341  |
| modexp_nagydani_2_square  | 665  | 200  |
| modexp_nagydani_2_qube  | 665  | 200  |
| modexp_nagydani_2_pow0x10001  | 10649  | 1365  |
| modexp_nagydani_3_square  | 1894  | 341  |
| modexp_nagydani_3_qube  | 1894  | 341  |
| modexp_nagydani_3_pow0x10001  | 30310  | 5461  |
| modexp_nagydani_4_square  | 5580  | 1365  |
| modexp_nagydani_4_qube  | 5580  | 1365  |
| modexp_nagydani_4_pow0x10001  | 89292  | 21845  |
| modexp_nagydani_5_square  | 17868  | 5461  |
| modexp_nagydani_5_qube  | 17868  | 5461  |
| modexp_nagydani_5_pow0x10001  | 285900 | 87381  |

## Implementations
[Geth](https://github.com/ethereum/go-ethereum/pull/21607)

[Python](https://gist.github.com/ineffectualproperty/60e34f15c31850c5b60c8cf3a28cd423)

## Security Considerations
The biggest security consideration for this EIP is creating a potential DoS vector by making ModExp operations too inexpensive relative to their computation time.

## References
[EIP-198](/EIPs/EIPS/eip-198) 

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 20 Mar 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2565</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2565</guid>
      </item>
    
      <item>
        <title>Human Readable Parameters for Contract Function Execution</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/human-readable-parameters-for-contract-function-execution/4154</comments>
        
        <description>## Simple Summary
New Ethereum RPC method `eth_sendTransactionToContractFunction` that parallels `eth_sendTransaction` but allows for human-readable contract function execution data to be displayed to users.

## Abstract
When a dapp prompts a user to execute a smart contract function via a ProviderWallet, confirmation screens displayed in the ProviderWallet layer cannot display the human readable details of the function to be called and the arguments to be passed. This is because the Ethereum RPC method used for contract function execution (`eth_sendTransaction`) accepts information about what function to call in a non-human readable (and non-recoverable) format. As such, when a ProviderWallet receives this non-human readable information from a dapp, they are unable to display a human readable version since they never received one and cannot recover one from the data.

This creates a poor and potentially dangerous user experience. For example, a malicious dapp could swap out the `address` argument in a token contract&apos;s `transfer(address,uint256)` function and reroute the tokens intended for someone else to themselves. This sleight-of-hand would be quiet and unlikely to be picked up by a casual user glancing over the non-human readable data. By adding a new Ethereum RPC method (`eth_sendTransactionToContractFunction`) that accepts the function ABI, ProviderWallets can recreate and display the human readable details of contract function execution to users.

## Motivation
### ProviderWallet Definition
ProviderWallets like Metamask and Geth are hybrid software that combine an Ethereum API provider with an Ethereum wallet. This allows them to sign transactions on behalf of their users and also broadcast those signed transactions to the Ethereum network. ProviderWallets are used for both convenience and for the protection they give users through human readable confirmation prompts.

### Existing Solutions
Much discussion has been made in the past few years on the topic of human readable Ethereum transaction data. Aragon&apos;s [Radspec](https://github.com/aragon/radspec) addresses this issue by requiring contract developers to amend their contract functions with human readable comments. ProviderWallets can then use Aragon&apos;s Radspec software to parse these comments from the contract code and display them to the end user - substituting in argument values where necessary. Unfortunately, this approach cannot work with contracts that do not have Radspec comments (and may require integration with IPFS).

[EIP 1138](https://github.com/ethereum/EIPs/issues/1138) also addresses this issue directly but contains serious security issues - allowing untrusted dapps to generate the human readable message displayed to users. In a similar train of thought, [Geth&apos;s #2940 PR](https://github.com/ethereum/go-ethereum/pull/2940) and [EIPs 191](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-191.md), [712](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md) all highlight the Ethereum community&apos;s desire for ProviderWallets to better inform users about what data they are actually acting upon.

Finally, the ProviderWallet Metamask already includes some built-in magic for interactions with ERC20 contracts that allows confirmation prompts to display the intended *token* recipient and *token* value. Although this is accomplished in an ad hoc fashion for ERC20-like contracts only, the motivation is the same: users deserve better information about the execution of contract functions they are relying on ProviderWallets to perform.

### Background
At one point or another, a dapp will ask a user to interact with a contract. The interaction between dapps and contracts is a large part of the Ethereum ecosystem and is most commonly brokered by a ProviderWallet. When a dapp asks a user to interact with a contract, it will do so by sending the `eth_sendTransaction` method name to the Ethereum API exposed by a ProviderWallet along with the relevant transaction data. The `data` field of the transaction data contains the information necessary for the Ethereum virtual machine to identify and execute the contract&apos;s function. This field has a specific formatting that is both non-human readable and non-recoverable to its human readable state.

The accepted format for `eth_sendTransaction`&apos;s `data` field is the hexadecimal encoding of the first four bytes of the keccak256 digest of the function signature. This abbreviated hash is then concatenated with the ABI encoded arguments to the function. Since the keccak256 digest of the function signature cannot be converted back into the function signature, the `data` field is not only non-human readable, its non-recoverable as well. On top of this, additional insight into the concatenated argument values is further obfuscated as information about their data types are held in the function signature preimage.

## Specification
This EIP proposes increasing the set of Ethereum RPC methods to include a new method - `eth_sendTransactionToContractFunction`. This method parallels `eth_sendTransaction` with the only difference being the inclusion of the contract function&apos;s `abi` field.

Parameters

1. `Object` - The transaction object
  * `from`: `DATA`, 20 Bytes - The address the transaction is sent from.
  * `to`: `DATA`, 20 Bytes - (optional when creating new contract) The address the transaction is directed to.
  * `gas`: `QUANTITY` - (optional, default: 90000) Integer of the gas provided for the transaction execution. It will return unused gas.
  * `gasPrice`: `QUANTITY` - (optional, default: To-Be-Determined) Integer of the gasPrice used for each paid gas
  * `value`: `QUANTITY` - (optional) Integer of the value sent with this transaction
  * `data`: `DATA` - The hash of the invoked method signature and encoded parameters
  * `abi`: `DATA` - The function ABI
  * `nonce`: `QUANTITY` - (optional) Integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce.

Example Parameters
```
  params: [{
    &quot;from&quot;: &quot;0x69e6F1b01f34A702Ce63bA6EF83c64fAEC37a227&quot;,
    &quot;to&quot;: &quot;0xe44127f6fA8A00ee0228730a630fc1F3162C4d52&quot;,
    &quot;gas&quot;: &quot;0x76c0&quot;, // 30400
    &quot;gasPrice&quot;: &quot;0x9184e72a000&quot;, // 10000000000000
    &quot;value&quot;: &quot;0x9184e72a&quot;, // 2441406250
    &quot;abi&quot;: &quot;{
      &quot;inputs&quot;: [{
        &quot;name&quot;: &quot;_address&quot;,
        &quot;type&quot;: &quot;address&quot;
      }, {
        &quot;name&quot;: &quot;_value&quot;,
        &quot;type&quot;: &quot;uint256&quot;
      }],
      &quot;name&quot;: &quot;transferTokens&quot;,
      &quot;outputs&quot;: [{
        &quot;name&quot;: &quot;success&quot;,
        &quot;type&quot;: &quot;bool&quot;
      }],
      &quot;stateMutability&quot;: &quot;nonpayable&quot;,
      &quot;type&quot;: &quot;function&quot;
    }&quot;,
   &quot;data&quot;: &quot;0xbec3fa170000000000000000000000006Aa89e52c9a826496A8f311c1a9db62fd477E256000000000000000000000000000000000000000000000000000000174876E800&quot;               
  }]
```

Returns
DATA, 32 Bytes - the transaction hash, or the zero hash if the transaction is not yet available.

Example
// Request
curl -X POST --data &apos;{&quot;jsonrpc&quot;:&quot;2.0&quot;,&quot;method&quot;:&quot;eth_sendTransactionToContractFunction&quot;,&quot;params&quot;:[{see above}],&quot;id&quot;:1}&apos;

// Result
{
  &quot;id&quot;:1,
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;result&quot;: &quot;0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;
}

## Rationale
This EIP&apos;s proposed `eth_sendTransactionToContractFunction` method is intended to parallel `eth_sendTransaction` as much as possible since both methods result in the same behaviour when executing a contract function. The newly introduced `abi` field is an element of the contract&apos;s ABI that corresponds to the intended function. The `data` field is the same `data` field from `eth_sendTransaction`. The `abi` field can be combined with values parsed from the `data` field to recreate human readable contract function execution information.

## Implementation
The `data` field in `eth_sendTransactionToContractFunction` is the same as that required for `eth_sendTransaction` allowing the transaction to be completed via the existing mechanisms used for `eth_sendTransaction`. The input argument values can be parsed from the `data` field and since we know their types from the `abi` field, the provider wallet can use this info to encode and display the values in an appropriate human readable format. Furthermore, the hashed and truncated function signature in the `data` field can be reconstructed using the information provided in the `abi` field providing an additional check to ensure that the supplied ABI matches the `data` field.

## Backwards Compatibility
With backwards compatibility in mind, this EIP proposes augmenting the set of Ethereum RPC methods with an additional method instead of mutating the existing method. Precedent for adding a new RPC method comes from [EIP 712](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md) in which adding the method `eth_signTypedData` is proposed for confirmation prompt security. As an alternate approach, the `eth_sendTransaction` method could be changed to accept an additional `abi` argument, but this would break all existing code attempting to execute a contract function.

## Security Considerations
Displaying the contract address, function name, and argument values can provide additional security to users, but it is not a guarantee that a function will execute as the user expects. A poorly implemented contract can still name its function `transfer` and accept `address` and `uint256` arguments - but there is nothing short of contract examination that will let a user know that this contract is indeed a valid ERC20 contract. This EIP does not intend to solve the larger problem around trust in a contract&apos;s code, but instead intends to give users better tools to understand exactly what is contained within the data they are broadcasting to the Ethereum network.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 23 Mar 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2566</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2566</guid>
      </item>
    
      <item>
        <title>Saving and Displaying Image Onchain for Universal Tokens</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-2569-saving-and-displaying-image-onchain-for-universal-tokens/4167</comments>
        
        <description>## Abstract
This set of interfaces allow a smart contract to save an SVG image in Ethereum and to retrieve an SVG image from Ethereum for fungible tokens, non-fungible tokens and tokens based on standards that will be developed in the future. 

The interface set has two interfaces: one to save an SVG file in Ethereum and the other to retrieve an SVG file from Ethereum. 

Typical applications include but not limited to:
* A solution for storage of a fungible token&apos;s icon.
* A solution for storage of a non-fungible token&apos;s icon.
* A solution for storage of the icon/logo of a DAO&apos;s reputation token.

## Motivation
The ERC-721 token standard is a popular standard to define a non-fungible token in Ethereum. This standard is widely used to specify a crypto gift, crypto medal, crypto collectible etc. The most famous use case is the [cryptokitty](https://www.cryptokitties.co/). 

In most of these applications an image is attached to an ERC-721 token. For example, in the cryptokitty case each kitty has a unique image. While the token&apos;s code is saved in Ethereum permanently, the image attached to the token is not. 

The existing solutions still keep such an image in a centralized server instead of Ethereum. When these applications display an image for a token they retrieve the token&apos;s information from Ethereum and search the centralized server for the token&apos;s associated image by using the token&apos;s information.

Although this is an applicable way to display an image for a token, the image is still vulnerable to risks of being damaged or lost when saved in a centralized server.

Hence we propose a set of interfaces to save an image for a universal token in Ethereum to keep the image permanent and tamper-resistant, and to retrieve an image for a universal token from Ethereum. 

## Specification

An EIP-2569 compatible contract MUST have a method with the signature getTokenImageSvg(uint256) view returns (string memory) and a method with the signature setTokenImageSvg(uint256 tokenId, string memory imagesvg) internal. 

These methods define how a smart contract saves an image for a universal token in Ethereum which keeps the image permanent and tamper-resistant, and how a smart contract retrieves an image from Ethereum for a universal token.  

By calling the methods users should access an SVG image. 

* getTokenImageSvg(uint256 tokenId) external view returns (string memory): for an ERC-721 or ERC-1155 token or a token implemented by a contract which has a member &quot;ID&quot; to specify its token type or token index we define an interface to get an SVG image by using the token&apos;s ID number. For an ERC-20 token or a token implemented by a contract which doesn&apos;t have a member &quot;ID&quot; to specify its token type or token index we define an interface to get an SVG image for it if the token has a member variable string to save the image.

It has the following parameter:

tokenId: for a non-fungible token such as an ERC-721 token or a multi-token such as an ERC-1155 token which has a member &quot;ID&quot; to specify its token type or token index our proposed interface assigns an SVG image&apos;s file content to a string variable of the token&apos;s contract and  associates the SVG image to this &quot;ID&quot; number. This unique ID is used to access its SVG image in both a &quot;set&quot; operation and a &quot;get&quot; operation. 
For a fungible token such as an ERC-20 token no such an ID is needed and our proposed interface just assigns an SVG image&apos;s file content to a string variable of the token&apos;s contract.

* setTokenImageSvg(uint256 tokenId, string memory imagesvg) internal: for an ERC-721 or ERC-1155 token or a token implemented by a contract which has a member &quot;ID&quot; to specify its token type or token index we define an interface to associate an SVG image to the token&apos;s ID number. For an ERC-20 token or a token implemented by a contract which doesn&apos;t have a member &quot;ID&quot; to specify its token type or token index we define an interface to assign an SVG image to a member variable string of this token&apos;s contract.

It has the following two parameters:

tokenId: for a non-fungible token such as an ERC-721 token or a multi-token such as an ERC-1155 token which has a member &quot;ID&quot; to specify its token type or token index our proposed interface assigns an SVG image&apos;s file content to a string variable of the token&apos;s contract and  associates the SVG image to this &quot;ID&quot; number. This unique ID is used to access its SVG image in both a &quot;set&quot; operation and a &quot;get&quot; operation. 
For a fungible token such as an ERC-20 token no such an ID is needed and our proposed interface just assigns an SVG image&apos;s file content to a string variable of the token&apos;s contract.

imageSvg: we use a string variable to save an SVG image file&apos;s content.
An SVG image that will be saved in the imageSvg string should include at least two attributes:&quot;name&quot;, &quot;desc&quot;(description).

The procedure to save an image for a token in Ethereum is as follows:

**Step1:** define a string variable or an array of strings to hold an image or an array of images.

**Step 2:** define a function to set an (SVG) image&apos;s file content or an array of image file&apos;s contents to the string variable or the array of strings.

Step 1: for a token such as an ERC-721 or ERC-1155 token which has a member variable &quot;ID&quot;  to specify a token type or index and a member variable string to keep an (SVG) image associated with the &quot;ID&quot;, retrieve the (SVG) image from Ethereum by calling our proposed &quot;get&quot; interface with the token&apos;s ID; 
for a token which doesn&apos;t have a member variable &quot;ID&quot; to specify a token type of index but has a member variable string to keep an (SVG) image, retrieve the (SVG) image from Ethereum by calling our proposed &quot;get&quot; without an &quot;ID&quot;. 

## Rationale
After Bitcoin was created people have found ways to keep information permanent and tamper-resistant by encoding text messages they want to preserve permanently and tamper-resistantly in blockchain transactions. However existing applications only do this for text information and there are no solutions to keep an image permanent and tamper-resistant.

One of the most significant reasons for not doing so is that in general the size of an image is much bigger than the size of a text file, thus the gas needed to save an image in Ethereum would exceed a block&apos;s gas limit. 

However this changed a lot after the SVG(Scalable Vector Graphics) specification was developed by W3C since 1999. 

The SVG specification offers several advantages (for more details about the advantages please refer to a reference link:https://en.wikipedia.org/wiki/Scalable_Vector_Graphics) over raster images. One of these advantages is its compact file-size.

&quot;Compact file-size – Pixel-based images are saved at a large size from the start because you can only retain the quality when you make the image smaller, but not when you make it larger. This can impact a site’s download speed. Since SVGs are scalable, they can be saved at a minimal file size&quot;.

This feature well fixes the painpoint of saving an image file in Ethereum, therefore we think saving an SVG image in Ethereum is a good solution for keep the image permanent and tamper-resistant.

In most ERC-721 related DAPPs they display an image for a non-fungible token. In most ERC-20 related DAPPs they don&apos;t have an image for a fungible token. We think displaying an image for a token either based on existing token standards such as ERC-20, ERC-721, ERC-1155 or based on future standards is needed in many use cases. Therefore those DAPPs which currently don&apos;t display an image for a token will eventually need such a function. 

However with regard to most of the existing DAPPs which can display an image for a token they save such an image in a centralized server which, we think, is just a compromised solution. By utilizing the SVG specification we think converting a token&apos;s image to an SVG image and saving it in Ethereum provides a better solution for DAPPs to access an image for a token.

This solution not only works for tokens based on ERC-721, ERC-1155 and ERC-20 but will work for tokens based on future standards. 

## Backwards Compatibility
There are no backward compatibility issues.

## Reference Implementation
`tokenId`: a token index in an ERC-721 token or a token type/index in an ERC-1155 token. It is a uint256 variable.  

`imageSvg`: an SVG image&apos;s file content. It is a string variable. Note: the SVG image should include at least three attributes:&quot;name&quot;, &quot;description&quot; and &quot;issuer&quot;.

`setTokenImageSvg`: interface to set an SVG image to a token with or without an ID number.

`getTokenImageSvg`: interface to get an SVG image for a token with or without an ID number.

We propose to add three sol files in the existing ERC-721 implementation.
Here are the details for the proposed sol files.

```solidity
// ----- IERC721GetImageSvg.sol -------------------------

pragma solidity ^0.5.0;

import &quot;@openzeppelin/contracts/token/ERC721/IERC721.sol&quot;;

/**
 * @title ERC-721 Non-Fungible Token Standard, optional retrieving SVG image extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
contract IERC721GetImageSvg is IERC721 {
    function getTokenImageSvg(uint256 tokenId) external view returns (string memory);
}


// ----- ERC721GetImageSvg.sol -------------------------

pragma solidity ^0.5.0;

import &quot;@openzeppelin/contracts/GSN/Context.sol&quot;;
import &quot;@openzeppelin/contracts/token/ERC721/./ERC721.sol&quot;;
import &quot;@openzeppelin/contracts/introspection/ERC165.sol&quot;;
import &quot;./IERC721GetImageSvg.sol&quot;;

contract ERC721GetImageSvg is Context, ERC165, ERC721, IERC721GetImageSvg {
    // Mapping for token Images
    mapping(uint256 =&gt; string) private _tokenImageSvgs;

    /*
     *     bytes4(keccak256(&apos;getTokenImageSvg(uint256)&apos;)) == 0x87d2f48c
     *
     *     =&gt; 0x87d2f48c == 0x87d2f48c
     */
    bytes4 private constant _INTERFACE_ID_ERC721_GET_TOKEN_IMAGE_SVG = 0x87d2f48c;

    /**
     * @dev Constructor function
     */
    constructor () public {
        // register the supported interfaces to conform to ERC721 via ERC165
        _registerInterface(_INTERFACE_ID_ERC721_GET_TOKEN_IMAGE_SVG);
    }

    /**
     * @dev Returns an SVG Image for a given token ID.
     * Throws if the token ID does not exist. May return an empty string.
     * @param tokenId uint256 ID of the token to query
     */
    function getTokenImageSvg(uint256 tokenId) external view returns (string memory) {
        require(_exists(tokenId), &quot;ERC721GetImageSvg: SVG Image query for nonexistent token&quot;);
        return _tokenImageSvgs[tokenId];
    }

    /**
     * @dev Internal function to set the token SVG image for a given token.
     * Reverts if the token ID does not exist.
     * @param tokenId uint256 ID of the token to set its SVG image
     * @param imagesvg string SVG  to assign
     */
    function setTokenImageSvg(uint256 tokenId, string memory imagesvg) internal {
        require(_exists(tokenId), &quot;ERC721GetImageSvg: SVG image set of nonexistent token&quot;);
        _tokenImageSvgs[tokenId] = imagesvg;
    }

}


// ----- ERC721ImageSvgMintable.sol -------------------------

pragma solidity ^0.5.0;

import &quot;@openzeppelin/contracts/token/ERC721/ERC721Metadata.sol&quot;;
import &quot;@openzeppelin/contracts/access/roles/MinterRole.sol&quot;;
import &quot;./ERC721GetImageSvg.sol&quot;;

/**
 * @title ERC721ImageSvgMintable
 * @dev ERC721 minting logic with imagesvg.
 */
contract ERC721ImageSvgMintable is ERC721, ERC721Metadata, ERC721GetImageSvg, MinterRole {
    /**
     * @dev Function to mint tokens.
     * @param to The address that will receive the minted tokens.
     * @param tokenId The token id to mint.
     * @param tokenImageSvg The token SVG image of the minted token.
     * @return A boolean that indicates if the operation was successful.
     */
    function mintWithTokenImageSvg(address to, uint256 tokenId, string memory tokenImageSvg) public onlyMinter returns (bool) {
        _mint(to, tokenId);
        setTokenImageSvg(tokenId, tokenImageSvg);
        return true;
    }
}


We propose to add three sol files in the existing ERC-1155 implementation.
Here are the details for the proposed sol files.

// ----- IERC1155GetImageSvg.sol -------------------------

pragma solidity ^0.5.0;

import &quot;./IERC1155.sol&quot;;

/**
 * @title ERC-1155 Multi Token Standard, retrieving SVG image for a token
 * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md
 */
contract IERC1155GetImageSvg is IERC1155 {
    function getTokenImageSvg(uint256 tokenId) external view returns (string memory);
}


// ----- ERC1155GetImageSvg.sol -------------------------

pragma solidity ^0.5.0;

import &quot;./ERC1155.sol&quot;;
import &quot;./IERC1155GetImageSvg.sol&quot;;

contract ERC1155GetImageSvg is ERC165, ERC1155, IERC1155GetImageSvg {
    // Mapping for token Images
    mapping(uint256 =&gt; string) private _tokenImageSvgs;

    /*
     *     bytes4(keccak256(&apos;getTokenImageSvg(uint256)&apos;)) == 0x87d2f48c
     *
     *     =&gt; 0x87d2f48c == 0x87d2f48c
     */
    bytes4 private constant _INTERFACE_ID_ERC1155_GET_TOKEN_IMAGE_SVG = 0x87d2f48c;

    /**
     * @dev Constructor function
     */
    constructor () public {
        // register the supported interfaces to conform to ERC1155 via ERC165
        _registerInterface(_INTERFACE_ID_ERC1155_GET_TOKEN_IMAGE_SVG);
    }


    /**
     * @dev Returns an SVG Image for a given token ID.
     * Throws if the token ID does not exist. May return an empty string.
     * @param tokenId uint256 ID of the token to query
     */
    function getTokenImageSvg(uint256 tokenId) external view returns (string memory) {
        require(_exists(tokenId), &quot;ERC1155GetImageSvg: SVG Image query for nonexistent token&quot;);
        return _tokenImageSvgs[tokenId];
    }

    /**
     * @dev Internal function to set the token SVG image for a given token.
     * Reverts if the token ID does not exist.
     * @param tokenId uint256 ID of the token to set its SVG image
     * @param imagesvg string SVG  to assign
     */
    function setTokenImageSvg(uint256 tokenId, string memory imagesvg) internal {
        require(_exists(tokenId), &quot;ERC1155GetImageSvg: SVG image set of nonexistent token&quot;);
        _tokenImageSvgs[tokenId] = imagesvg;
    }

}



// ----- ERC1155MixedFungibleWithSvgMintable.sol -------------------------

pragma solidity ^0.5.0;

import &quot;./ERC1155MixedFungibleMintable.sol&quot;;
import &quot;./ERC1155GetImageSvg.sol&quot;;

/**
    @dev Mintable form of ERC1155 with SVG images
    Shows how easy it is to mint new items with SVG images
*/

contract ERC1155MixedFungibleWithSvgMintable is ERC1155, ERC1155MixedFungibleMintable, ERC1155GetImageSvg {
    /**
     * @dev Function to mint non-fungible tokens.
     * @param _to The address that will receive the minted tokens.
     * @param _type The token type to mint.
     * @param tokenImageSvg The token SVG image of the minted token.
     */
    function mintNonFungibleWithImageSvg(uint256 _type, address[] calldata _to, string memory tokenImageSvg) external creatorOnly(_type) {
        mintNonFungible(_type, _to);
        setTokenImageSvg(_type, tokenImageSvg);
    }


    /**
     * @dev Function to mint fungible tokens.
     * @param _to The address that will receive the minted tokens.
     * @param _id The token type to mint.
     * @param _quantities The number of tokens for a type to mint.
     * @param tokenImageSvg The token SVG image of the minted token.
     */
    function mintFungibleWithImageSvg(uint256 _id, address[] calldata _to, uint256[] calldata _quantities, string memory tokenImageSvg) external creatorOnly(_id) {
        mintFungible(_id, _to, _quantities, tokenImageSvg)  {
        setTokenImageSvg(_id, tokenImageSvg);
    }
}



We propose to add three sol files in the existing ERC-20 implementation.
Here are the details for the proposed sol files.


// ----- IERC20GetImageSvg.sol -------------------------

pragma solidity ^0.5.0;
import &quot;@openzeppelin/contracts/token/ERC20/IERC20.sol&quot;;

/**
 * @title ERC-20 Fungible Token Standard, retrieving SVG image for a token
 * @dev See https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol
 */
contract IERC20GetImageSvg is IERC20 {
    function getTokenImageSvg() external view returns (string memory);
}


// ----- ERC20GetImageSvg.sol -------------------------

pragma solidity ^0.5.0;
import &quot;@openzeppelin/contracts/token/ERC20/ERC20.sol&quot;;
import &quot;./IERC20GetImageSvg.sol&quot;;

contract ERC20GetImageSvg is ERC20, IERC20GetImageSvg {
    string private _tokenImageSvg;
//将图片实现写在构造器中
    constructor(string calldata svgCode) public {
_tokenImageSvg = svgCode
}

    /**
     * @dev Returns an SVG Image.
     */
    function getTokenImageSvg() external view returns (string memory) {
        return _tokenImageSvg;
    }

}


```

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Sat, 28 Mar 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2569</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2569</guid>
      </item>
    
      <item>
        <title>Penalty for account trie misses</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2583-penalties-for-trie-misses/4190</comments>
        
        <description>## Simple Summary

This EIP introduces a gas penalty for opcodes which access the account for trie non-existent accounts.

## Abstract

This EIP adds a gas penalty for accesses to the account trie, where the address being looked up does not exist. Non-existing accounts can be used in 
DoS attacks, since they bypass cache mechanisms, thus creating a large discrepancy between &apos;normal&apos; mode of execution and &apos;worst-case&apos; execution of an opcode. 

## Motivation

As the ethereum trie becomes more and more saturated, the number of disk lookups that a node is required to do in order to access a piece of state increases too. This means that checking e.g. `EXTCODEHASH` of an account at block `5` was _inherently_ a cheaper operation that it is at, say `8.5M`. 

From an implementation perspective, a node can (and does) use various caching mechanisms to cope with the problem, but there&apos;s an inherent problem with caches: when they yield a &apos;hit&apos;, they&apos;re great, but when they &apos;miss&apos;, they&apos;re useless. 

This is attackable. By forcing a node to lookup non-existent keys, an attacker can maximize the number of disk lookups. 
Sidenote: even if the &apos;non-existence&apos; is cached, it&apos;s trivial to use a new non-existent key the next time, and never hit the same non-existent key again. Thus, caching &apos;non-existence&apos; might be dangerous, since it will evict &apos;good&apos; entries. 

So far, the attempts to handle this problem has been in raising the gas cost, e.g. [EIP-150](/EIPs/EIPS/eip-150), [EIP-1884](/EIPs/EIPS/eip-1884). 

However, when determining gas-costs, a secondary problem that arises due to the large discrepancy between &apos;happy-path&apos; and &apos;notorious path&apos; -- how do we determine the pricing?

- The &apos;happy-path&apos;, assuming all items are cached? 
  - Doing so would that would underprice all trie-accesses, and could be DoS-attacked. 
- The &apos;normal&apos; usage, based on benchmarks of actual usage? 
  - This is basically what we do now, but that means that intentionally notorious executions are underpriced -- which constitutes a DoS vulnerability.
- The &apos;paranoid&apos; case: price everything as if caching did not exist?
  - This would severely harm basically every contract due to the gas-cost increase. Also, if the gas limits were raised in order to allow the same amount of computation as before, the notorious case could again be used for DoS attacks.  

From an engineering point of view, a node implementor is left with few options: 

- Implement bloom filters for existence. This is difficult, not least because of the problems of reorgs, and the fact that it&apos;s difficult to undo bloom filter modifications. 
- Implement flattened account databases. This is also difficult, both because of reorgs and also because it needs to be an _additional_ data structure aside from the `trie` -- we need the `trie` for consensus. So it&apos;s an extra data structure of around `15G` that needs to be kept in check. This is currently being pursued by the Geth-team.  

This EIP proposes a mechanism to alleviate the situation. 

## Specification

We define the constant `penalty` as `TBD` (suggested `2000` gas).

For opcodes which access the account trie, whenever the operation is invoked targeting an `address` which does not exist in the trie, then `penalty` gas is deducted from the available `gas`. 

### Detailed specification

These are the opcodes which triggers lookup into the main account trie:

| Opcode | Affected | Comment | 
| -----  | ---------| ----------|
| BALANCE| Yes      | `balance(nonexistent_addr)` would incur `penalty`|
| EXTCODEHASH| Yes      | `extcodehash(nonexistent_addr)` would incur `penalty`|
| EXTCODECOPY| Yes      | `extcodecopy(nonexistent_addr)` would incur `penalty`|
| EXTCODESIZE| Yes      | `extcodesize(nonexistent_addr)` would incur `penalty`|
| CALL | Yes| See details below about call variants|
| CALLCODE | Yes| See details below about call variants|
| DELEGATECALL | Yes| See details below about call variants|
| STATICCALL | Yes| See details below about call variants|
| SELFDESTRUCT | No| See details below. | 
| CREATE   | No | Create destination not explicitly settable, and assumed to be nonexistent already.|
| CREATE2  | No | Create destination not explicitly settable, and assumed to be nonexistent already.| 


### Notes on Call-derivatives

A `CALL` triggers a lookup of the `CALL` destination address. The base cost for `CALL` is at `700` gas. A few other characteristics determine the actual gas cost of a call:

1. If the `CALL` (or `CALLCODE`) transfers value, an additional `9K` is added as cost. 
    1.1 If the `CALL` destination did not previously exist, an additional `25K` gas is added to the cost.

This EIP adds a second rule in the following way:

2. If the call does _not_ transfer value and the callee does _not_ exist, then `penalty` gas is added to the cost.

In the table below, 
- `value` means non-zero value transfer, 
- `!value` means zero value transfer, 
- `dest` means destination already exists, or is a `precompile`
- `!dest` means destination does not exist and is not a `precompile`

| Op | value,dest| value, !dest |!value, dest| !value, !dest|  
| -- | ---------  | -- | --| -- |
|CALL |  no change | no change| no change| `penalty`|
|CALLCODE |  no change | no change| no change| `penalty`|
|DELEGATECALL | N/A | N/A| no change| `penalty` |
|STATICCALL | N/A | N/A| no change| `penalty` |

Whether the rules of this EIP is to be applied for regular ether-sends in `transactions` is TBD. See the &apos;Backwards Compatibility&apos;-section for some more discussion on that topic. 

### Note on `SELFDESTRUCT`

The `SELFDESTRUCT` opcode also triggers an account trie lookup of the `beneficiary`. However, due to the following reasons, it has been omitted from having a `penalty` since it already costs `5K` gas. 

### Clarifications:

- The `base` costs of any opcodes are not modified by the EIP.
- The opcode `SELFBALANCE` is not modified by this EIP, regardless of whether the `self` address exists or not. 


## Rationale

With this scheme, we could continue to price these operations based on the &apos;normal&apos; usage, but gain protection from attacks that try to maximize disk lookups/cache misses. 
This EIP does not modify anything regarding storage trie accesses, which might be relevant for a future EIP. However, there are a few crucial differences. 


1. Storage tries are typically small, and there&apos;s a high cost to populate a storage trie with sufficient density for it to be in the same league as the account trie. 
2. If an attacker wants to use an existing large storage trie, e.g. some popular token, he would typically have to make a `CALL` to cause a lookup in that token -- something like `token.balanceOf(&lt;nonexistent-address&gt;)`. 
   That adds quite a lot of extra gas-impediments, as each `CALL` is another `700` gas, plus gas for arguments to the `CALL`. 
   
### Determining the `penalty`

A transaction with `10M` gas can today cause ~`14K` trie lookups.

- A `penalty` of `1000`would lower the number to ~`5800` lookups, `41%` of the original.
- A `penalty` of `2000`would lower the number to ~`3700` lookups, `26%` of the original.
- A `penalty` of `3000`would lower the number to ~`2700` lookups, `20%` of the original. 
- A `penalty` of `4000`would lower the number to ~`2100` lookups, `15%` of the original. 

There exists a roofing function for the `penalty`. Since the `penalty` is deducted from `gas`, that means that a malicious contract can always invoke a malicious relay to perform the trie lookup. Let&apos;s refer to this as the &apos;shielded relay&apos; attack. 

In such a scenario, the `malicious` would spend `~750` gas each call to `relay`, and would need to provide the `relay` with at least `700` gas to do a trie access.

Thus, the effective `cost` would be on the order of `1500`. It can thus be argued that `penalty` above `~800` would not achieve better protection against trie-miss attacks. 


## Backwards Compatibility

This EIP requires a hard-fork. 

### Ether transfers

A regular `transaction` from one EOA to another, with value, is not affected. 

A `transaction` with `0` value, to a destination which does not exist, would be. This scenario is highly unlikely to matter, since such a `transaction` is useless -- even during success, all it would accomplish would be to spend some `gas`. With this EIP, it would potentially spend some more gas.

### Layer 2

Regarding layer-2 backward compatibility, this EIP is a lot less disruptive than EIPs which modify the `base` cost of an opcode. For state accesses, there are 
seldom legitimate scenarios where

1. A contract checks `BALANCE`/`EXTCODEHASH`/`EXTCODECOPY`/`EXTCODESIZE` of another contract `b`, _and_, 
2. If such `b` does not exist, continues the execution

#### Solidity remote calls
Example: When a remote call is made in Solidity: 
```
    recipient.invokeMethod(1)
```

- Solidity does a pre-flight `EXTCODESIZE` on `recipient`. 
- If the pre-flight check returns `0`, then `revert(0,0)` is executed, to stop the execution.
- If the pre-flight check returns non-zero, then the execution continues and the `CALL` is made.
 
With this EIP in place, the &apos;happy-path&apos; would work as previously, and the &apos;notorious&apos;-path where `recipient` does not exist would cost an extra `penalty` gas, but the actual execution-flow would be unchanged.  

#### ERC223

[ERC223 Token Standard](https://github.com/ethereum/EIPs/issues/223) is, at the time of writing, marked as &apos;Draft&apos;, but is deployed and in use on mainnet today.

The ERC specifies that when a token `transfer(_to,...)` method is invoked, then:

&gt; This function must transfer tokens and invoke the function `tokenFallback (address, uint256, bytes)` in `_to`, if `_to` is a contract.
&gt; ...
&gt; NOTE: The recommended way to check whether the `_to` is a contract or an address is to assemble the code of `_to`. If there is no code in `_to`, then this is an externally owned address, otherwise it&apos;s a contract.

The reference implementations from [Dexaran](https://github.com/Dexaran/ERC223-token-standard/tree/development/token/ERC223) and [OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/1bc923b6a222e79a90f20305a459b0ee779eb918/contracts/token/ERC721/ERC721.sol#L499) both implement the `isContract` check using an `EXTCODESIZE` invocation. 

This scenario _could_ be affected, but in practice should not be. Let&apos;s consider the possibilities: 

1. The `_to` is a contract: Then `ERC223` specifies that the function `tokenFallback(...)` is invoked. 
    - The gas expenditure for that call is at least`700` gas.
    - In order for the `callee` to be able to perform any action, best practice it to ensure that it has at least `2300` gas along with the call. 
   - In summary: this path requires there to be least `3000` extra gas available (which is not due to any `penalty`)
2. The `_to` exists, but is no contract. The flow exits here, and is not affected by this EIP 
2. The `_to` does not exist: A `penalty` is deducted. 

In summary, it would seem that `ERC223` should not be affected, as long as the `penalty` does not go above around `3000` gas.


### Other

The contract [`Dentacoin`](https://etherscan.io/address/0x08d32b0da63e2c3bcf8019c9c5d849d7a9d791e6#code) would be affected. 

```
    function transfer(address _to, uint256 _value) returns (bool success) {
    ... // omitted for brevity
        if (balances[msg.sender] &gt;= _value &amp;&amp; balances[_to] + _value &gt; balances[_to]) {               // Check if sender has enough and for overflows
            balances[msg.sender] = safeSub(balances[msg.sender], _value);   // Subtract DCN from the sender

            if (msg.sender.balance &gt;= minBalanceForAccounts &amp;&amp; _to.balance &gt;= minBalanceForAccounts) {    // Check if sender can pay gas and if recipient could
                balances[_to] = safeAdd(balances[_to], _value);             // Add the same amount of DCN to the recipient
                Transfer(msg.sender, _to, _value);                          // Notify anyone listening that this transfer took place
                return true;
            } else {
                balances[this] = safeAdd(balances[this], DCNForGas);        // Pay DCNForGas to the contract
                balances[_to] = safeAdd(balances[_to], safeSub(_value, DCNForGas));  // Recipient balance -DCNForGas
                Transfer(msg.sender, _to, safeSub(_value, DCNForGas));      // Notify anyone listening that this transfer took place

                if(msg.sender.balance &lt; minBalanceForAccounts) {
                    if(!msg.sender.send(gasForDCN)) throw;                  // Send eth to sender
                  }
                if(_to.balance &lt; minBalanceForAccounts) {
                    if(!_to.send(gasForDCN)) throw;                         // Send eth to recipient
                }
            }
        } else { throw; }
    }
```    

The contract checks `_to.balance &gt;= minBalanceForAccounts`, and if the `balance` is too low, some `DCN` is converted to `ether` and sent to the `_to`. This is a mechanism to ease on-boarding, whereby a new user who has received some `DCN` can immediately create a transaction.

Before this EIP:

- When sending `DCN` to a non-existing address, the additional `gas` expenditure would be:
  - `9000` for an ether-transfer
  - `25000` for a new account-creation
  - (`2300` would be refunded to the caller later)
  - A total runtime `gas`-cost of `34K` gas would be required to handle this case.

After this EIP: 

- In addition to the `34K` an additional `penalty` would be added. 
    - Possibly two, since the reference implementation does the balance-check twice, but it&apos;s unclear whether the compiled code would indeed perform the check twice. 
- A total runtime `gas`-cost of `34K+penalty` (or `34K + 2 * penalty`) would be required to handle this case. 

It can be argued that the extra penalty of `2-3K` gas can be considered marginal in relation to the other `34K` gas already required to handle this.

## Test Cases

The following cases need to be considered and tested: 

- That during creation of a brand new contract, within the constructor, the `penalty` should not be applied for calls concerning the self-address. 
- TBD: How the `penalty` is applied in the case of a contract which has performed a `selfdestruct` 
  - a) previously in the same call-context, 
  - b) previously in the same transaction, 
  - c) previously in the same block,
  For any variant of `EXTCODEHASH(destructed)`, `CALL(destructed)`, `CALLCODE(destructed)` etc. 
- The effects on a `transaction` with `0` value going to a non-existent account.

## Security Considerations

See &apos;Backwards Compatibility&apos;

## Implementation

Not yet available. 

## Alternative variants

### Alt 1: Insta-refunds

Bump all trie accesses with `penalty`. `EXTCODEHASH` becomes `2700` instead of `700`. 
- If a trie access hit an existing item, immediately refund penalty (`2K` )

Upside:

- This eliminates the &apos;shielded relay&apos; attack

Downside: 

- This increases the up-front cost of many ops (CALL/EXTCODEHASH/EXTCODESIZE/STATICCALL/EXTCODESIZE etc)
  - Which may break many contracts. 

### Alt 2: Parent bail

Use `penalty` as described, but if a child context goes OOG on the `penalty`, then the remainder is subtracted from the 
parent context (recursively).

Upside:

- This eliminates the &apos;shielded relay&apos; attack

Downside: 

- This breaks the current invariant that a child context is limited by whatever `gas` was allocated for it. 
  - However, the invariant is not _totally_ thrown out, the new invariant becomes that it is limited to `gas + penalty`.
- This can be seen as &apos;messy&apos; -- since only _some_ types of OOG (penalties) becomes passed up the call chain, but not others, e.g. OOG due to trying
  to allocate too much memory. There is a distinction, however: 
  - Gas-costs which arise due to not-yet-consumed resources do not get passed to parent. For example: a huge allocation is not actually performed if there is insufficient gas. 
  - Whereas gas-costs which arise due to already-consumed resources _do_ get passed to parent; in this case the penalty is paid post-facto for a trie iteration. 


## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 21 Feb 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2583</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2583</guid>
      </item>
    
      <item>
        <title>Trie format transition with overlay trees</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethresear.ch/t/overlay-method-for-hex-bin-tree-conversion/7104</comments>
        
        <description>## Simple Summary

This EIP proposes a method to convert the state trie format from hexary to binary: new values are directly stored in a binary trie “laid over” the hexary trie. Meanwhile, the hexary trie is converted to a binary trie in the background. When the process is finished, both layers are merged.

## Abstract

This EIP describes a four phase process to complete the conversion.

  * In the first phase, all new state writes are made to an overlay binary trie, while the hexary trie is being converted to binary. The block format is changed to have two storage roots: the root of the hexary trie (hereafter called the &quot;base&quot; trie) and the root of the overlay binary trie.
  * After enough time has been given to miners to perform the conversion, the second phase begins. The overlay tree is progressively merged back into the newly converted binary base trie. A constant number of entries are deleted from the overlay and inserted into the base trie.
  * The third and final phase begins when the overlay trie is empty. The field holding its root is removed from the block header.

## Motivation

There is a long running interest in switching the state trie from a hexary format to a binary format, for reasons pertaining to proof and storage sizes. The conversion process poses a catch-up issue, caused by the sheer size of the full state: it can not be translated in a reasonable time (i.e. on the same order of magnitude as the block time). 

## Specification

This specification follows the notation introduced by the [Yellow Paper](https://ethereum.github.io/yellowpaper). Prior to reading it is advisable to be familiar with the Yellow Paper.

### Binary tries

This EIP assumes that a binary trie is defined like the MPT, except that:

  * The series of bytes in I₀ is seen as a series of _bits_ and so ∀i≤256, I₀[i] is the ith bit in key I₀
  * The first item of an **extension** or a **leaf** is replacing nibbles with bits;
  * A **branch** is a 2 item structure in which both items correspond to each of the two possible bit values for the keys at this point in their traversal;
  * c(𝕴,i) ≡ RLP((u(0), u(1)) at a branch, where u(j) = n({I : I ∈ 𝕴 ⋀ I₀[i] = j}, i+1)

Let ß be the function that, given a hexary trie, computes the equivalent representation of that trie in the aforementioned binary trie format.

### Phase 1

Let _h₁_ be the previously agreed-upon block height at which phase 1 starts, and _h₂_ the block at which phase 2 starts. For each block of height h₁ ≤ _h_ &lt; h₂:

  0. A conversion process is started in the background, to turn the hexary trie into its binary equivalent. The end goal of this process is the calculation of the _root hash of the converted binary trie_, denoted Hᵣ². The root of the hexary trie is hereafter called Hᵣ¹⁶. Formally, this process is written as Hᵣ² ≡ ß(Hᵣ¹⁶).
  1. Block headers contain a new Hₒ field, which is the _root of the overlay binary trie_;
  2. Hᵣ ≡ P(H)ᵣ¹⁶, i.e. as long as the conversion from hexary to binary is not complete, the hexary trie root is the same as that of its parent block.

The following is changed in the execution environment:

  * Upon executing a _state read_, ϒ first searches for the address in the overlay trie. If the key can not be found there, ϒ then searches the base trie as it did at block heights h&apos; &lt; h₁;
  * Upon executing a _state write_, ϒ inserts or updates the value into the overlay tree. The base tree is left untouched;
  * If an account is deleted, ϒ inserts the empty hash H(∅) at the address of that account in order to mark its deletion; reads from such an address behave the same as a missing account, regardless of what is present in the base trie.

Phase 1 ends at block height h₂, which is set far enough from h₁ to offer miners enough time to perform the conversion.

### Phase 2

  This phase differs from the previous one on the following points:

  * At block height h₂, before the execution of ϒ, Hᵣ ≡ Hᵣ², i.e. the value before the execution of the transition function is set to the root of the converted _binary base trie_;
  * Hₒ is still present in the block tree, however the overlay trie content can only be _read from or deleted_;
  * At block height h ≥ h₂, before the execution of ϒ, N accounts are being deleted from the binary overlay trie and inserted into the binary base trie;
  * Upon executing a _state write_, ϒ will insert or update the value into the _base_ trie. If the search key exists in the overlay trie, it is deleted.

Account deletion is performed according to the following rules:

  * The first N accounts (in lexicographic order) remaining in the overlay tree are selected; For each of these accounts:
  * If the value is the empty hash, remove the account at the same address from the binary base trie;
  * Otherwise, insert/update the account at the corresponding address in the base trie with its overlay trie value.

When the overlay trie is empty, phase 2 ends and phase 3 begins.

### Phase 3

Phase 3 is the same as phase 2, except for the following change:

  * Hₒ is dropped from the block header

## Rationale

Methods that have been discussed until now include a &quot;stop the world&quot; approach, in which the chain is stopped for the significant amount of time that is required by the conversion, and a &quot;copy on write&quot; approach, in which branches are converted upon being accessed.
The approach suggested here has the advantage that the chain continues to operate normally during the conversion process, and that the tree is fully converted to a binary format, in a predictable time.

## Backwards Compatibility

This requires a fork and will break backwards compatibility, as the hashes and block formats will necessarily be different. This will cause a fork in clients that don&apos;t implement the overlay tree, and those that do not accept the new binary root. No mitigation is proposed, as this is a hard fork.

## Test Cases

  * For testing phase 1, it suffices to check that every key in the hexary trie is also available in the binary trie. A looser but faster test picks 1% of keys in the hexary trie at random, and checks that they are present in the binary trie;
  * TBD for phase 2 &amp; 3

## Implementation

A prototype version of the conversion process (phase 1) is available for `geth` in [this PR](https://github.com/holiman/go-ethereum/pull/12).

## Security Considerations

There are three attack vectors that I can foresee:

  * A targeted attack that would cause the overlay trie to be unreasonably large. Since gas costs will likely increase during the transition process, lengthening phase 2 will make Ethereum more expensive during an extended period of time. This could be solved by increasing the cost of `SSTORE` during phase 1.
  * Conversely, if h₂ comes too soon, a majority of miners might not be able to produce the correct value for Hᵣ² in time.
  * If a group of miners representing more than 51% of the network are reporting an invalid value, they could be stealing funds without anyone having a say.

## Community feedback

  * Preliminary tests indicate that a fast machine can perform the conversion in roughly 30 minutes.
  * The initial version of this EIP expected miners to vote on the value of the binary base root. This has been removed because of the complexity of this process, and because this functionality is already guaranteed by the &quot;longest chain&quot; rule.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 03 Apr 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2584</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2584</guid>
      </item>
    
      <item>
        <title>Escalator fee market change for ETH 1.0 chain</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethresear.ch/t/another-simple-gas-fee-model-the-escalator-algorithm-from-the-agoric-papers/6399</comments>
        
        <description>## Simple Summary
The current &quot;first price auction&quot; fee model in Ethereum is inefficient and needlessly costly to users. This EIP proposes a way to replace this with a mechanism that allows dynamically priced transaction fees and efficient transaction price discovery.

## Abstract

Based on [The Agoric Papers](https://agoric.com/papers/incentive-engineering-for-computational-resource-management/full-text/).

Each transaction would have the option of providing parameters that specify an &quot;escalating&quot; bid, creating a time-based auction for validators to include that transaction.

This creates highly efficient price discovery, where the price will always immediately fall to the highest bid price, which is not necessarily that user&apos;s highest price they would pay.

![escalator algorithm price chart](https://ethresear.ch/uploads/default/original/2X/0/042795efa4c2680d644bc66386cd2984a70293f8.gif)

## Motivation
Ethereum currently prices transaction fees using a simple first-price auction, which leads to well documented inefficiencies (some of which are documented in [EIP-1559](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md)) when users are trying to estimate what price will get a transaction included in a block, especially during times of price volatility and full blocks.

EIP 1559 is currently being championed as an improvement for the Ethereum protocol, and while I agree that the gas market is very inefficient, since a change like this will affect all client and wallet implementations, the Ethereum community should make sure to make a selection based on solid reasoning and justifications, which I believe 1559 is currently lacking.

To facilitate a more productive and concrete discussion about the gas fee market, I felt it was important to present an alternative that is clearly superior to the status quo, so that any claimed properties of EIP-1559 can be compared to a plausible alternative improvement.

I suggest the three gas payment algorithms be compared under all combinations of these conditions:

- Blocks that are regularly half full, Blocks that are regularly less than half full, and blocks that repeatedly full in a surprising (&quot;black swan&quot;) series.
- Users that are willing to wait for a price that may be below the market rate, vs users who value inclusion urgently and are willing to pay above market rate.

We should then ask:
- Is the user willing to pay the most in a given scenario also likely to have their transaction processed in a time period they find acceptable?
- Are users who want a good price likely to get included in a reasonable period of time? (Ideally within one block)

I believe that under this analysis we will find that the escalator algorithm outperforms EIP-1559 in both normal and volatile conditions, for both high-stakes transactions and more casual users looking for a good price.

While I think a deeper simulation/analysis should be completed, I will share my expected results under these conditions.

Furthermore, by introducing tx fee payment related to the current time, we create an incentive for miners to more honestly report the current time.

### User Strategies Under Various Conditions and Algorithms

First I will suggest a likely optimal strategy for different players under the conditions of the different algorithms being considered.

| Gas Strategy                                                        | Current Single-Price                                                                                                                                                    | EIP 1559                                                                                                                                                                       | Escalator                                                                                                                                                                                    |
|---------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Blocks regularly half full, user wants urgent inclusion.            | User bids within the range of prices that have been recently accepted, likely over-pays slightly.                                                                       | User bids one price tier over the current rate, and is likely included.                                                                                                        | User bids a range from the low end of recently included to the high end, and is likely included at the lowest rate possible.                                                                 |
| Blocks regularly half full, user willing to wait for a good price.  | User bids below or near the low end of the recently accepted prices, may need to wait for a while. If waiting too long, user may need to re-submit with a higher price. | User bids under or at the current price tier, and may wait for the price to fall. If waiting too long, user may need to re-submit with a higher price.                         | User bids as low as they&apos;d like, but set an upper bound on how long they&apos;re willing to wait before increasing price.                                                                         |
| Blocks regularly full, user wants urgent inclusion.                 | User bids over the price of all recently accepted transactions, almost definitely over-paying significantly.                                                            | User bids over the current price tier, and needs to increase their `tip` parameter to be competitive on the next block, recreating the single-price auction price problem.     | User bids over a price that has been accepted consistently, with an escalating price in case that price is not high enough.                                                                  |
| Blocks regularly full, user willing to wait for a good price.       | User bids below the low end of the recently accepted prices, may need to wait for a while. If waiting too long, user may need to re-submit with a higher price.         | User bids under or at the current price tier, and may wait for the price to fall. If waiting too long, user may need to re-submit with a higher price.                         | User bids as low as they&apos;d like, but set an upper bound on how long they&apos;re willing to wait before increasing price.                                                                         |
| Blocks regularly under-full, user wants urgent inclusion.           | User bids within or over the range of prices that have been recently accepted, likely over-pays slightly, and is likely included in the next block.                     | User bids at or over the current price tier, and is likely included in the next block.                                                                                         | User submits bid starting within recently accepted prices, is likely accepted in the next block.                                                                                             |
| Blocks regularly under-full, user willing to wait for a good price. | User bids below the low end of the recently accepted prices, may need to wait for a while. If waiting too long, user may need to re-submit with a higher price.         | User bids at or under the current price tier, and is likely included in the next block. If bidding under and waiting too long, user may need to re-submit with a higher price. | User bids as low as they&apos;d like, but set an upper bound on how long they&apos;re willing to wait before increasing price, is likely included in the next few blocks at the lowest possible price. |

### User Results Under Various Conditions and Algorithms

Now I will consider the ultimate results of the strategies listed above. Are users happy under these conditions? Did we save users money? Were users who wanted urgent inclusion able to secure it?

| Gas Strategy                                                        | Current Single-Price                                                                                                                                            | EIP 1559                                                                                     | Escalator                                                                                                          |
|---------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------|
| Blocks regularly half full, user wants urgent inclusion.            | User pays an expected amount, and gets transaction mined reliably.                                                                                              | User pays an expected amount, and gets transaction mined reliably.                           | User pays an expected amount, and gets transaction mined reliably.                                                 |
| Blocks regularly half full, user willing to wait for a good price.  | User can wait for a better price, but may need to resubmit re-signed transactions.                                                                              | User can wait for a better price, but may need to resubmit re-signed transactions.           | User can discover the lowest price within their time preference with a single signature.                           |
| Blocks regularly full, user wants urgent inclusion.                 | User over-pays, but reliably gets transaction included.                                                                                                         | Due to `tip` parameter &quot;breaking tie&quot; within a block, user over-pays for reliable inclusion. | User is able to balance the amount of overpayment they risk with the urgency they require.                         |
| Blocks regularly full, user willing to wait for a good price.       | User chooses their price, and waits for it, or manually re-submits.                                                                                             | User chooses their price, and waits for it, or manually re-submits.                          | User chooses their lowest price, but also their highest price and maximum wait time, so no resubmission is needed. |
| Blocks regularly under-full, user wants urgent inclusion.           | User over-pays, but reliably gets transaction included.                                                                                                         | User bids at or over current price tier, gets transaction mined reliably.                    | User pays an expected amount, and gets transaction mined reliably.                                                 |
| Blocks regularly under-full, user willing to wait for a good price. | User bids below the low end of the recently accepted prices, may need to wait for a while. If waiting too long, user may need to re-submit with a higher price. | User chooses their price, and waits for it, or manually re-submits.                          | User chooses their lowest price, but also their highest price and maximum wait time, so no resubmission is needed. |

In all cases, the escalator algorithm as I have described is able to perform optimally.

The current gas auction model works well under half-full and less conditions, but for users with urgent needs, has the downside of overpayment. For users seeking a low price, the current model has the downside of requiring re-submission, but has the benefit of always giving users a path towards reliable block inclusion.

EIP-1559 also performs well under normal conditions, but under conditions where blocks are regularly full, the price discovery mechanism breaks, and miners will fall back to the `TIP` parameter to choose the transactions to include, meaning that under network congestion, EIP-1559 forces users to _either_ choose efficient prices or certainty of next-block inclusion.

EIP-1559 also has all the re-submission issues of the current model in situations where a user would like to pay under the current market rate, but has certain time constraints limiting their patience. The Escalator algorithm is the only strategy listed here that allows users to discover the lowest possible price given the network conditions and their time constraints.

## Specification
**Client-Wide Parameters**
* `INITIAL_FORK_BLKNUM`: TBD

**Transaction Parameters**
The transaction `gasPrice` parameter is now optional, and if excluded can be replaced by these parameters instead:

* `START_PRICE`: The lowest price that the user would like to pay for the transaction.
* `START_TIME`: The first time that this transaction is valid at.
* `MAX_PRICE`: The maximum price the sender would be willing to pay to have this transaction processed.
* `MAX_TIME`: The time at which point the user&apos;s `MAX_PRICE` is achieved. The transaction remains valid after this time at that price.

**Proposal**

For all blocks where `block.number &gt;= INITIAL_FORK_BLKNUM`:

When processing a transaction with the new pricing parameters, miners now receive a fee based off of the following linear function, where `BLOCK` is the current block number:

* IF `BLOCK &gt; MAX_TIME` then `TX_FEE = MAX_PRICE`.
* `TX_FEE = START_PRICE + ((MAX_PRICE - START_PRICE) / (MAX_TIME - START_TIME) * (BLOCK - START_TIME))`

As a JavaScript function:
```javascript
function txFee (startTime, startPrice, maxTime, maxPrice, currentTime) {

  if (currentTime &gt;= maxTime) return maxPrice

  const priceRange = maxPrice - startPrice
  const blockRange = maxTime - startTime
  const slope = priceRange / blockRange

  return startPrice + (slope * (currentTime - startTime))
}
```

## Backwards Compatibility

Since a current `gasPrice` transaction is effectively a flat-escalated transaction bid, it is entirely compatible with this model, and so there is no concrete requirement to deprecate current transaction processing logic, allowing cold wallets and hardware wallets to continue working for the foreseeable future.

## Test Cases
TBD

## Implementation
TBD

## Security Considerations
The security considerations for this EIP are:
- None currently known.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 13 Mar 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2593</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2593</guid>
      </item>
    
      <item>
        <title>Permit Extension for EIP-20 Signed Approvals</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2613</comments>
        
        <description>## Abstract

Arguably one of the main reasons for the success of [EIP-20](/EIPs/EIPS/eip-20) tokens lies in the interplay between `approve` and `transferFrom`, which allows for tokens to not only be transferred between externally owned accounts (EOA), but to be used in other contracts under application specific conditions by abstracting away `msg.sender` as the defining mechanism for token access control.

However, a limiting factor in this design stems from the fact that the EIP-20 `approve` function itself is defined in terms of `msg.sender`. This means that user&apos;s _initial action_ involving EIP-20 tokens must be performed by an EOA (_but see Note below_). If the user needs to interact with a smart contract, then they need to make 2 transactions (`approve` and the smart contract call which will internally call `transferFrom`). Even in the simple use case of paying another person, they need to hold ETH to pay for transaction gas costs.

This ERC extends the EIP-20 standard with a new function `permit`, which allows users to modify the `allowance` mapping using a signed message, instead of through `msg.sender`.

For an improved user experience, the signed data is structured following [EIP-712](/EIPs/EIPS/eip-712), which already has wide spread adoption in major RPC providers.

**_Note:_** EIP-20 must be performed by an EOA unless the address owning the token is actually a contract wallet. Although contract wallets solves many of the same problems that motivates this EIP, they are currently only scarcely adopted in the ecosystem. Contract wallets suffer from a UX problem -- since they separate the EOA `owner` of the contract wallet from the contract wallet itself (which is meant to carry out actions on the `owner`s behalf and holds all of their funds), user interfaces need to be specifically designed to support them. The `permit` pattern reaps many of the same benefits while requiring little to no change in user interfaces.

## Motivation

While EIP-20 tokens have become ubiquitous in the Ethereum ecosystem, their status remains that of second class tokens from the perspective of the protocol. The ability for users to interact with Ethereum without holding any ETH has been a long outstanding goal and the subject of many EIPs.

So far, many of these proposals have seen very little adoption, and the ones that have been adopted (such as [EIP-777](/EIPs/EIPS/eip-777)), introduce a lot of additional functionality, causing unexpected behavior in mainstream contracts.

This ERC proposes an alternative solution which is designed to be as minimal as possible and to only address _one problem_: the lack of abstraction in the EIP-20 `approve` method.

While it may be tempting to introduce `*_by_signature` counterparts for every EIP-20 function, they are intentionally left out of this EIP-20 for two reasons:

- the desired specifics of such functions, such as decision regarding fees for `transfer_by_signature`, possible batching algorithms, varies depending on the use case, and,
- they can be implemented using a combination of `permit` and additional helper contracts without loss of generality.

## Specification

Compliant contracts must implement 3 new functions in addition to EIP-20:

```sol
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external
function nonces(address owner) external view returns (uint)
function DOMAIN_SEPARATOR() external view returns (bytes32)
```

The semantics of which are as follows:

For all addresses `owner`, `spender`, uint256s `value`, `deadline` and `nonce`, uint8 `v`, bytes32 `r` and `s`,
a call to `permit(owner, spender, value, deadline, v, r, s)` will set
`allowance[owner][spender]` to `value`,
increment `nonces[owner]` by 1,
and emit a corresponding `Approval` event,
if and only if the following conditions are met:

- The current blocktime is less than or equal to `deadline`.
- `owner` is not the zero address.
- `nonces[owner]` (before the state update) is equal to `nonce`.
- `r`, `s` and `v` is a valid `secp256k1` signature from `owner` of the message:

If any of these conditions are not met, the `permit` call must revert.

```sol
keccak256(abi.encodePacked(
   hex&quot;1901&quot;,
   DOMAIN_SEPARATOR,
   keccak256(abi.encode(
            keccak256(&quot;Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)&quot;),
            owner,
            spender,
            value,
            nonce,
            deadline))
))
```

where `DOMAIN_SEPARATOR` is defined according to EIP-712. The `DOMAIN_SEPARATOR` should be unique to the contract and chain to prevent replay attacks from other domains,
and satisfy the requirements of EIP-712, but is otherwise unconstrained.
A common choice for `DOMAIN_SEPARATOR` is:

```solidity
DOMAIN_SEPARATOR = keccak256(
    abi.encode(
        keccak256(&apos;EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)&apos;),
        keccak256(bytes(name)),
        keccak256(bytes(version)),
        chainid,
        address(this)
));
```

In other words, the message is the EIP-712 typed structure:

```js
{
  &quot;types&quot;: {
    &quot;EIP712Domain&quot;: [
      {
        &quot;name&quot;: &quot;name&quot;,
        &quot;type&quot;: &quot;string&quot;
      },
      {
        &quot;name&quot;: &quot;version&quot;,
        &quot;type&quot;: &quot;string&quot;
      },
      {
        &quot;name&quot;: &quot;chainId&quot;,
        &quot;type&quot;: &quot;uint256&quot;
      },
      {
        &quot;name&quot;: &quot;verifyingContract&quot;,
        &quot;type&quot;: &quot;address&quot;
      }
    ],
    &quot;Permit&quot;: [
      {
        &quot;name&quot;: &quot;owner&quot;,
        &quot;type&quot;: &quot;address&quot;
      },
      {
        &quot;name&quot;: &quot;spender&quot;,
        &quot;type&quot;: &quot;address&quot;
      },
      {
        &quot;name&quot;: &quot;value&quot;,
        &quot;type&quot;: &quot;uint256&quot;
      },
      {
        &quot;name&quot;: &quot;nonce&quot;,
        &quot;type&quot;: &quot;uint256&quot;
      },
      {
        &quot;name&quot;: &quot;deadline&quot;,
        &quot;type&quot;: &quot;uint256&quot;
      }
    ],
  },
  &quot;primaryType&quot;: &quot;Permit&quot;,
  &quot;domain&quot;: {
    &quot;name&quot;: erc20name,
    &quot;version&quot;: version,
    &quot;chainId&quot;: chainid,
    &quot;verifyingContract&quot;: tokenAddress
  },
  &quot;message&quot;: {
    &quot;owner&quot;: owner,
    &quot;spender&quot;: spender,
    &quot;value&quot;: value,
    &quot;nonce&quot;: nonce,
    &quot;deadline&quot;: deadline
  }
}
```

Note that nowhere in this definition we refer to `msg.sender`. The caller of the `permit` function can be any address.

## Rationale

The `permit` function is sufficient for enabling any operation involving EIP-20 tokens to be paid for using the token itself, rather than using ETH.

The `nonces` mapping is given for replay protection.

A common use case of `permit` has a relayer submit a `Permit` on behalf of the `owner`. In this scenario, the relaying party is essentially given a free option to submit or withhold the `Permit`. If this is a cause of concern, the `owner` can limit the time a `Permit` is valid for by setting `deadline` to a value in the near future. The `deadline` argument can be set to `uint(-1)` to create `Permit`s that effectively never expire.

EIP-712 typed messages are included because of its wide spread adoption in many wallet providers.

## Backwards Compatibility

There are already a couple of `permit` functions in token contracts implemented in contracts in the wild, most notably the one introduced in the `dai.sol`.

Its implementation differs slightly from the presentation here in that:

- instead of taking a `value` argument, it takes a bool `allowed`, setting approval to 0 or `uint(-1)`.
- the `deadline` argument is instead called `expiry`. This is not just a syntactic change, as it effects the contents of the signed message.

There is also an implementation in the token `Stake` (Ethereum address `0x0Ae055097C6d159879521C384F1D2123D1f195e6`) with the same ABI as `dai` but with different semantics: it lets users issue &quot;expiring approvals&quot;, that only allow `transferFrom` to occur while `expiry &gt;= block.timestamp`.

The specification presented here is in line with the implementation in Uniswap V2.

The requirement to revert if the permit is invalid was added when the EIP was already widely deployed, but at the moment it was consistent with all found implementations.

## Security Considerations

Though the signer of a `Permit` may have a certain party in mind to submit their transaction, another party can always front run this transaction and call `permit` before the intended party. The end result is the same for the `Permit` signer, however.

Since the ecrecover precompile fails silently and just returns the zero address as `signer` when given malformed messages, it is important to ensure `owner != address(0)` to avoid `permit` from creating an approval to spend &quot;zombie funds&quot; belong to the zero address.

Signed `Permit` messages are censorable. The relaying party can always choose to not submit the `Permit` after having received it, withholding the option to submit it. The `deadline` parameter is one mitigation to this. If the signing party holds ETH they can also just submit the `Permit` themselves, which can render previously signed `Permit`s invalid.

The standard EIP-20 race condition for approvals (SWC-114) applies to `permit` as well.

If the `DOMAIN_SEPARATOR` contains the `chainId` and is defined at contract deployment instead of reconstructed for every signature, there is a risk of possible replay attacks between chains in the event of a future chain split.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 13 Apr 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2612</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2612</guid>
      </item>
    
      <item>
        <title>Non-Fungible Token with mortgage and rental functions</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2616</comments>
        
        <description>## Simple Summary

This standard proposes an extension to ERC721 Non-Fungible Tokens (NFTs) to support rental and mortgage functions. These functions are necessary for NFTs to emulate real property, just like those in the real world.

## Abstract

This standard is an extension of ERC721. It proposes additional roles, the right of tenants to enable rentals, and the right of lien.

With ERC2615, NFT owners will be able to rent out their NFTs and take out a mortgage by collateralizing their NFTs. For example, this standard can apply to:

- Virtual items (in-game assets, virtual artwork, etc.)
- Physical items (houses, automobiles, etc.)
- Intellectual property rights
- DAO membership tokens

NFT developers are also able to easily integrate ERC2615 since it is fully backwards-compatible with the ERC721 standard.

One notable point is that the person who has the right to use an application is not the owner but the user (i.e. tenant). Application developers must implement this specification into their applications.

## Motivation

It has been challenging to implement rental and mortgage functions with the ERC721 standard because it only has one role defined (which is the Owner).

Currently, a security deposit is needed for trustless renting with ERC721, and ownership lockup within a contract is necessary whenever one chooses to mortgage their ERC721 property. The tracking and facilitation of these relationships must be done separately from the ERC721 standard.

This proposal eliminates these requirements by integrating basic rights of tenantship and liens. By standardizing these functions, developers can more easily integrate rental and mortgage functions for their applications.

## Specification

This standard proposes three user roles: the **Lien Holder**, the **Owner**, and the **User**. Their rights are as follows:

- A **Lien Holder** has the right to:

  1. Transfer the **Owner** role
  2. Transfer the **User** role

- An **Owner** has the right to:

  1. Transfer the **Owner** role
  2. Transfer the **User** role

- A **User** has the right to:
  1. Transfer the **User** role

### ERC-2615 Interface

```solidity
event TransferUser(address indexed from, address indexed to, uint256 indexed itemId, address operator);
event ApprovalForUser(address indexed user, address indexed approved, uint256 itemId);
event TransferOwner(address indexed from, address indexed to, uint256 indexed itemId, address operator);
event ApprovalForOwner(address indexed owner, address indexed approved, uint256 itemId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
event LienApproval(address indexed to, uint256 indexed itemId);
event TenantRightApproval(address indexed to, uint256 indexed itemId);
event LienSet(address indexed to, uint256 indexed itemId, bool status);
event TenantRightSet(address indexed to, uint256 indexed itemId,bool status);

function balanceOfOwner(address owner) public view returns (uint256);
function balanceOfUser(address user) public view returns (uint256);
function userOf(uint256 itemId) public view returns (address);
function ownerOf(uint256 itemId) public view returns (address);

function safeTransferOwner(address from, address to, uint256 itemId) public;
function safeTransferOwner(address from, address to, uint256 itemId, bytes memory data) public;
function safeTransferUser(address from, address to, uint256 itemId) public;
function safeTransferUser(address from, address to, uint256 itemId, bytes memory data) public;

function approveForOwner(address to, uint256 itemId) public;
function getApprovedForOwner(uint256 itemId) public view returns (address);
function approveForUser(address to, uint256 itemId) public;
function getApprovedForUser(uint256 itemId) public view returns (address);
function setApprovalForAll(address operator, bool approved) public;
function isApprovedForAll(address requester, address operator) public view returns (bool);

function approveLien(address to, uint256 itemId) public;
function getApprovedLien(uint256 itemId) public view returns (address);
function setLien(uint256 itemId) public;
function getCurrentLien(uint256 itemId) public view returns (address);
function revokeLien(uint256 itemId) public;

function approveTenantRight(address to, uint256 itemId) public;
function getApprovedTenantRight(uint256 itemId) public view returns (address);
function setTenantRight(uint256 itemId) public;
function getCurrentTenantRight(uint256 itemId) public view returns (address);
function revokeTenantRight(uint256 itemId) public;
```

### ERC-2615 Receiver

```solidity
function onERCXReceived(address operator, address from, uint256 itemId, uint256 layer, bytes memory data) public returns(bytes4);
```

### ERC-2615 Extensions

Extensions here are provided to help developers build with this standard.

#### 1. ERC721 Compatible functions

This extension makes this standard compatible with ERC721. By adding the following functions, developers can take advantage of the existing tools for ERC721.

Transfer functions in this extension will transfer both the **Owner** and **User** roles when the tenant right has not been set. Conversely, when the tenant right has been set, only the **Owner** role will be transferred.

```solidity
function balanceOf(address owner) public view returns (uint256)
function ownerOf(uint256 itemId) public view returns (address)
function approve(address to, uint256 itemId) public
function getApproved(uint256 itemId) public view returns (address)
function transferFrom(address from, address to, uint256 itemId) public
function safeTransferFrom(address from, address to, uint256 itemId) public
function safeTransferFrom(address from, address to, uint256 itemId, bytes memory data) pubic
```

#### 2. Enumerable

This extension is analogous to the enumerable extension of the ERC721 standard.

```solidity
function totalNumberOfItems() public view returns (uint256);
function itemOfOwnerByIndex(address owner, uint256 index, uint256 layer)public view returns (uint256 itemId);
function itemByIndex(uint256 index) public view returns (uint256);
```

#### 3. Metadata

This extension is analogous to the metadata extension of the ERC721 standard.

```solidity
function itemURI(uint256 itemId) public view returns (string memory);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
```

## How rentals and mortgages work

This standard does not deal with token or value transfer. Other logic (outside the scope of this standard) must be used to orchestrate these transfers and to implement validation of payment.

### Mortgage functions

The following diagram demonstrates the mortgaging functionality.

![concept image](../assets/eip-2615/mortgage-sequential.jpg &quot;mortgage&quot;)

Suppose Alice owns an NFT and wants to take out a mortgage, and Bob wants to earn interest by lending tokens to Alice.

1. Alice approves the setting of a lien for the NFT Alice owns.
2. Alice sends a loan request to the mortgage contract.
3. Bob fills the loan request and transfers tokens to the mortgage contract. The lien is then set on the NFT by the mortgage contract.
4. Alice can now withdraw the borrowed tokens from the mortgage contract.
5. Alice registers repayment (anyone can pay the repayment).
6. Bob can finish the agreement if the agreement period ends and the agreement is kept (i.e. repayment is paid without delay).
7. Bob can revoke the agreement if the agreement is breached (e.g. repayment is not paid on time) and execute the lien and take over the ownership of the NFT.

### Rental functions

The following diagram demonstrates the rental functionality.

![concept image](../assets/eip-2615/rental-sequential.jpg &quot;rental&quot;)

Suppose Alice owns NFTs and wants to rent out a NFT, and Bob wants to lease a NFT.

1. Alice approves the setting of a tenant-right for the NFT Alice owns.
2. Alice sends a rental listing to the rental contract.
3. Bob fills the rental request, and the right to use the NFT is transferred to Bob. At the same time, the tenant-right is set, and Alice becomes not able to transfer the right to use the NFT.
4. Bob registers rent (anyone can pay the rent).
5. Alice can withdraw the rent from the rental contract.
6. Alice can finish the agreement if the agreement period has ended and the agreement is kept (i.e. rent is paid without delay).
7. Alice can revoke the agreement if the agreement is breached (e.g. rent is not paid on time) and revoke the tenant-right and take over the right to use the NFT.

## Rationale

There have been some attempts to achieve rentals or mortgages with ERC721. However, as I noted before, it has been challenging to achieve. I will explain the reasons and advantages of this standard below.

### No security lockup for rentals

To achieve trustless rental of NFTs with ERC721, it has been necessary to deposit funds as security. This is required to prevent malicious activity from tenants, as it is impossible to take back ownership once it is transferred.

With this standard, security deposits are no longer needed since the standard natively supports rental and tenantship functions.

### No ownership escrow when taking out a mortgage

In order to take out a mortgage on NFTs, it has been necessary to transfer the NFTs to a contract as collateral. This is required to prevent the potential default risk of the mortgage.

However, secured collateral with ERC721 hurts the utility of the NFT. Since most NFT applications provide services to the canonical owner of a NFT, the NFT essentially cannot be utilized under escrow.

With ERC2615, it is possible to collateralize NFTs and use them at the same time.

### Easy integration

Because of the above reasons, a great deal of effort is required to implement rental and mortgage functions with ERC721. Adopting this standard is a much easier way to integrate rental and mortgage functionality.

### No money/token transactions within tokens

A NFT itself does not handle lending or rental functions directly. This standard is open-source, and there is no platform lockup. Developers can integrate it without having to worry about those risks.

## Backward compatibility

As mentioned in the specifications section, this standard can be fully ERC721 compatible by adding an extension function set.

In addition, new functions introduced in this standard have many similarities with the existing functions in ERC721. This allows developers to easily adopt the standard quickly.

## Test Cases

When running the tests, you need to create a test network with Ganache-CLI:

```
ganache-cli -a 15  --gasLimit=0x1fffffffffffff -e 1000000000
```

And then run the tests using Truffle: 

```
truffle test -e development
```

Powered by Truffle and Openzeppelin test helper.

## Implementation

[Github Repository](https://github.com/kohshiba/ERC-X).

## Security Considerations

Since the external contract will control lien or tenant rights, flaws within the external contract directly lead to the standard&apos;s unexpected behavior.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Sat, 25 Apr 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2615</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2615</guid>
      </item>
    
      <item>
        <title>Hierarchical Deterministic Wallet for Layer-2</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/hierarchical-deterministic-wallet-for-computation-integrity-proof-cip-layer-2/4286</comments>
        
        <description>## Simple Summary
In the context of Computation Integrity Proof (CIP) Layer-2 solutions such as ZK-Rollups, users are required to sign messages on new elliptic curves optimized for those environments. We leverage existing work on Key Derivation ([BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki), [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) and [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)) to define an efficient way to securely produce CIP L2s private keys, as well as creating domain separation between Layer-2 applications.

## Abstract
We provide a Derivation Path allowing a user to derive hierarchical keys for Layer-2 solutions depending on the zk-technology, the application, the user’s Layer-1 address, as well as an efficient grinding method to enforce the private key distribution within the curve domain. The propose Derivation Path is defined as follow
```
m / purpose&apos; / layer&apos; / application&apos; / eth_address_1&apos; / eth_address_2&apos; / index
```

## Motivation
In the context of Computation Integrity Proof (CIP) Layer-2 solutions such as ZK-Rollups, users are required to sign messages on new elliptic curves optimized for those environments. Extensive work has been done to make it secure on Bitcoin via [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki), [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) and [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki). These protocols are the standard for wallets in the entire industry, independent of the underlying blockchain. As Layer-2 solutions are taking off, it is a necessary requirement to maintain the same standard and security in this new space.

## Specification
Starkware keys are derived with the following [BIP43](https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki)-compatible derivation path, with direct inspiration from [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki):
```
m / purpose&apos; / layer&apos; / application&apos; / eth_address_1&apos; / eth_address_2&apos; / index
```
where:
* `m` - the seed.
* `purpose` - `2645` (the number of this EIP).
* `layer` - the 31 lowest bits of sha256 on the layer name. Serve as a domain separator between different technologies. In the context of `starkex`, the value would be `579218131`.
* `application` - the 31 lowest bits of sha256 of the application name. Serve as a domain separator between different applications. In the context of DeversiFi in June 2020, it is the 31 lowest bits of sha256(starkexdvf) and the value would be `1393043894`.
* `eth_address_1 / eth_address_2` - the first and second 31 lowest bits of the corresponding eth_address.
* `index` - to allow multiple keys per eth_address.

As example, the expected path for address 0x0000....0000 assuming seed `m` and index 0 in the context of DeversiFi in June 2020: `m/2645&apos;/579218131&apos;/1393043894&apos;/0&apos;/0&apos;/0`

The key derivation should follow the following algorithm
```
N = 2**256
n = Layer2 curve order
path = stark derivation path
BIP32() = Official BIP-0032 derivation function on secp256k1
hash = SHA256
i = 0
root_key = BIP32(path)
while True:
	key = hash(root_key|i)
	if (key &lt; (N - (N % n))):
		return key % n
	i++
```
This algorithm has been defined to maintain efficiency on existing restricted devices.

Nota Bene: At each round, the probability for a key to be greater than (N - (N % n)) is &lt; 2^(-5).

## Rationale
This EIP specifies two aspects of keys derivation in the context of Hierarchical Wallets:
- Derivation Path
- Grinding Algorithm to enforce a uniform distribution over the elliptic curve.
The derivation path is defined to allow efficient keys separation based on technology and application while maintaining a 1-1 relation with the Layer-1 wallet. In such a way, losing EIP-2645 wallets falls back to losing the Layer-1 wallet.

## Backwards Compatibility
This standard complies with BIP43.

## Security Considerations
This EIP has been defined to maintain separation of keys while providing foolproof logic on key derivation.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 13 May 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2645</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2645</guid>
      </item>
    
      <item>
        <title>Ephemeral Testnet Yolo</title>
        <category>Meta/</category>
        
          <comments>https://gitter.im/ethereum/AllCoreDevs</comments>
        
        <description>**Disclaimer: This is for testing basic infrastructure. It will be nuked. It is not for deploying dapps, nor does it define what will go into mainnet. For information on network upgrades, please follow the relevant meta EIPs and ongoing discussion on Ethereum/pm.**

## Abstract

The specification for Ephemeral Testnet Yolo. Clients who wish to sync need to implement the following features into their client. It is for testing basic infrastructure and will be nuked.

## Specification 

Name: Yolo
ID: `YOLO-v1`

  - [x] EIP 2537 Commit Hash - [5edff4ae6ff62c7e0bbfad624fc3d0ba7dc84392](https://github.com/ethereum/EIPs/commit/5edff4ae6ff62c7e0bbfad624fc3d0ba7dc84392)
  - [x] EIP 2315 Commit Hash - [e8accf22cdc5562d6982c560080c6cd6b7f94867](https://github.com/ethereum/EIPs/commit/e8accf22cdc5562d6982c560080c6cd6b7f94867)

*[ ] Proposed - [x] Consensus to include.*
## Timeline

 - Deployed: June 3rd 2020
 
## Client Consensus -&gt; Implementation 

YOLO-v1
| **Client**   | Signal | Spec | Merged | Syncing |
|--------------|--------|------|--------|---------|
| Besu         | x      | x    |        |         |
| EthereumJS   | x      |      |        |         |
| Geth         | x      | x    | x      | x       |
| Nethermind   | x      | x    |        |         |
| OpenEthereum | x      | x    |        |         |
| Trinity      |        |      |        |         |

**Signal** -
Client intends to participate. *(You are on the bus)*

**Spec** -
Client is satisfied with the proposed specification. *(You agree with the direction)*

**Merge** -
Changes are implemented in the client and configurable for YOLO. *(You are ready to hit the gas and go)*

**Syncing**
Client syncs with the network


## Syncing Instructions

**Geth**
- Yolo V1 testnet is up and running https://yolonet.xyz/
- Support is baked into Geth master branch via --yolov1
- Genesis config json is at https://yolonet.xyz/yolo.json
- EF bootnode at enode://9e1096aa59862a6f164994cb5cb16f5124d6c992cdbf4535ff7dea43ea1512afe5448dca9df1b7ab0726129603f1a3336b631e4d7a1a44c94daddd03241587f9@35.178.210.161:30303
- Stats page secret is YOLOv1, with geth you can --ethstats=&apos;yournode:YOLOv1@stats.yolonet.xyz&apos;
- Faucet is unauthenticated, you can reach it from the dashboard

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 19 Apr 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2657</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2657</guid>
      </item>
    
      <item>
        <title>Repricing of precompiles and Keccak256 function</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip2666-global-precompiles-repricing-and-many-more-discussion-thread/4332</comments>
        
        <description>## Simple Summary

This EIP tries to set prices of certain precompiles and built-in EVM function to be in line with their performance, consumed resources and newer changes in EVM itself.

New price formulas are proposed for:
- SHA256 precompile (`0x02`)
- RIPEMD precompile (`0x03`)
- KECCAK256 opcode (`0x20`)

## Abstract

Costs of many precompiles and built-in functions are invalid at the current state of the clients. This EIP contains a list of changes to the pricing formulas to better reflect underlying computations&apos; structure.

## Motivation

Historical pricing for these functions in EVM does not reflect inner structure of the underlying computations (inner structure of the hash functions).

- EIP-2046 changes a `STATICCALL (0xfa)` cost to precompile and it may be necessary to adjust costs of some precompiles that *may* have taken old large cost (`700` gas) into account and tried to compensate for it
- Some precompiles are overpriced and their pricing formulas do not reflect the structure of underlying functions
- Keccak256 built-in function (opcode) in EVM has pricing that does not reflect underlying hash function structure

## Specification

If `block_number &gt;= X` set the gas cost of the following precompiles and Keccak256 opcode:
- SHA256 (precompile `0x02`): `10 + ((len(input) + 8)/64 + 1) * 9`
- RIPEMD (precompile `0x03`): `6 + ((len(input) + 8)/64 + 1) * 12`
- KECCAK256 (`0x20`): `13 + (len(input)/136 + 1)*15`

This EIP *ideally* requires that `MODEXP` repricing is [implemented](/EIPs/EIPS/eip-2565) to also accurately reflect that there is no implicit compensation for an old `STATICCALL (0xfa)` cost (pre-2046).

## Rationale
Cost of functions being executed must accurately reflect real CPU time spent on computations, so benchmarking was performed for current precompiles and Keccak256 function to measure running time versus input parameters. 

### Detailed summary of repricing approach

This EIP relies on two facts:
- apriori knowledge of the inner strucute of the hash functions
- benchmarks provided by the client teams for some reasonable range of input lengths for random inputs (random byte strings of a given length)

### Benchmarks on the most popular clients

Necessary benchmarks for EIP-2666 were provided by the clients and raw form is assembled in [here](https://docs.google.com/spreadsheets/d/1aCQnk7prrp3Mbcf011BE5zZnkbc3Iw7QAixn6mLbKS0/edit?usp=sharing)

- SHA256 precompile

Currently it&apos;s `60` gas + `12` gas per `32` byte word (number of words is `ceil(len(input)/word_len)` here and in similar places. If there is no `floor` or `ceil` specifier all divisions below are integer divisions (floor divisions)). Proposed formula is `A * ((len(input) + 8) / 64 + 1) + B`, with coefficients below

|   |   | A  | B  |
|---|---|---|---|
| Geth  |   | 5  | 3  |
| OE  |   | 9  | 4  |
| Besu  |   | 5  | 10  |
| Nethermind  |   | 10  | 5  |

EIP-2666 proposes `A = 9`, `B = 10`. There are no large one-off costs in this precompile, so it&apos;s EIP-2046 - safe.

- RIPEMD precompile

Currently it&apos;s `600` gas + `120` gas per `32` byte word. Proposed formula is `A * ((len(input) + 8) / 64 + 1) + B`, with coefficients below

|   |   | A  | B  |
|---|---|---|---|
| Geth  |   | 12  | 6  |
| OE  |   | 8  | 2  |
| Besu  |   | 29  | 16  |
| Nethermind  |   | 10  | 6  |

EIP-2666 proposes `A = 12`, `B = 6`. There are no large one-off costs in this precompile, so it&apos;s EIP-2046 - safe. Besu expects to have performance improvements by the end of the year.

- Keccak256 performance

Currently it&apos;s `30` gas + `6` gas per `32` byte word. Proposed formula is `A * (len(input) / 136 + 1) + B`, with coefficients below

|   |   | A  | B  |
|---|---|---|---|
| Geth  |   | 13  | 13  |
| OE  |   | 15  | 2  |
| Besu  |   | 19  | 28  |
| Nethermind  |   | 16  | 3  |

EIP-2666 proposes `A = 15`, `B = 13`. There are no large one-off costs in this precompile, so it&apos;s EIP-2046 - safe. Besu expects to have performance improvements by the end of the year.

### Tooling and data

Reference material (from benchmarks of different clients) with raw data can be found [here](https://docs.google.com/spreadsheets/d/1aCQnk7prrp3Mbcf011BE5zZnkbc3Iw7QAixn6mLbKS0/edit?usp=sharing).

There is a repository available with inputs for benchmarking and precompiles testing [here](https://github.com/shamatar/bench_precompiles) that can be used by client teams to perform all the necessary measurements.

Raw Besu [benchmarks](https://gist.github.com/shemnon/0ddba91be501fa23291bdec9107fe99a).

### Note on formulas structure

There are terms in formulas that look like `A * 1` and those are explicitly not combined to the `B` coefficient to reflect that hash of an empty byte array requires to perform a round of hashing anyway.

## Backwards Compatibility
Precompile repricings has happened in a past and can be considered standard procedure. Gas costs of many contracts is expected to reduce that may break re-entrancy protection measures based on fixed gas costs. In any case, such protection should have never been considered good and final.

## Test Cases

Let&apos;s consider a simple example of Keccak256 hash of `0`, `64` and `160` bytes that can is a simple sanity check for implementation.

- Hash `0` bytes:
  - Old price: `30 + 6 * ceil(0 / 32) = 30` gas
  - New price: `15 * (0/136 + 1) + 13 = 28` gas
- Hash `64` bytes
  - Old price: `30 + 6 * ceil(64 / 32) = 42` gas
  - New price: `15 * (64/136 + 1) + 13 = 28` gas
- Hash `160` bytes
  - Old price: `30 + 6 * ceil(160 / 32) = 60` gas
  - New price: `15 * (160/136 + 1) + 13 = 43` gas

## Implementation

There is no reference implementation at the time of writing as it requires just a simple change of constants in major clients.

## Security Considerations

As described in backward compatibility section in some cases reduction of cost may allow e.g. re-entrancy that was not expected before, but we think that re-entrancy protection based on fixed gas costs is anyway flawed design decision.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 22 May 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2666</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2666</guid>
      </item>
    
      <item>
        <title>Limit size of `initcode`</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2677-limit-size-of-initcode/4550</comments>
        
        <description>## Simple Summary

Enforce a maximum size limit (`max_initcode_size`) of `49152` (`0xc000`) for `initcode`.

## Abstract

Enforce a maximum size limit (`max_initcode_size`) for `initcode`. If the size of `initcode` exceeds `max_initcode_size`, then contract creation fails with an out of gas error.

Since [EIP-170](/EIPs/EIPS/eip-170) was implemented, there has been a size limit of `24576` (`0x6000`) on contract code. We propose to also limit the size of executable code to `2x` the above limit, i.e. `49152` (`0xc000`).

This also leads to two nice properties:

- instruction offset in code fits 16-bit value,
- code size fits 16-bit value.

## Motivation

When a client executes `initcode`, the client has to perform a jumpdest analysis. In some cases, the client also performs a `hash` of the code:

* To use as a key in a mapping containing the result of a jumpdest analysis 
* To use for address calculation within `CREATE2`.

The work performed during a jumpdest analysis scales linearly with the size of the code. Currently, a transaction can expand the memory once, and reuse the same memory segment (with minor modifications) to force the client to perform a lot of analysis/hashing, leading to slow block processing. 

Historically, this was exploited in June 2017, precipitating the 1.6.5-patch release of [geth](https://github.com/ethereum/go-ethereum/releases/tag/v1.6.5)

The work performed during address calculation within `CREATE2` is charged in proportion with size of the code.

## Specification

There are three situations where this is applicable:

* `CREATE`,
* `CREATE2`,
* creation using a transaction with empty receiver. 

In all these (and future) cases, the EVM should fail with Out Of Gas error if the code has a length more than `max_initcode_size`.

## Rationale

TBA

## Backwards Compatibility

This EIP requires a &quot;network upgrade&quot;, since it modifies consensus-rules.

## Security Considerations

For client implementations, this EIP makes attacks based on jumpdest-analysis or hashing of code less problematic, so should increase the robustness of clients. 

For layer 2, this EIP introduces failure-modes where there previously were none. There _could_ exist factory-contracts which deploy multi-level contract hierarchies, such that the code for multiple contracts are included in the initcode of the first contract. The author(s) of this EIP are not aware of any such contracts. 

## Test Cases

Test cases should include the following cases, 

- `CREATE`/`CREATE2`/`tx create` with `initcode_size` at `max_initcode_size`
- `CREATE`/`CREATE2`/`tx create` with `initcode_size` at `max_initcode_size+1`

## Implementation

TBA

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 18 May 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2677</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2677</guid>
      </item>
    
      <item>
        <title>Revised Ethereum Smart Contract Packaging Standard (EthPM v3)</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/ethpm-v3-specification-working-group/4086</comments>
        
        <description>## Simple Summary

A data format describing a smart contract software package.


## Abstract

This EIP defines a data format for *package manifest* documents,
representing a package of one or more smart contracts, optionally
including source code and any/all deployed instances across multiple
networks. Package manifests are minified JSON objects, to be distributed
via content addressable storage networks, such as IPFS. Packages
are then published to on-chain EthPM registries, defined in
[EIP-1319](/EIPs/EIPS/eip-1319), from where they can be freely accessed.

This document presents a natural language description of a formal
specification for version **3** of this format.


## Motivation

This standard aims to encourage the Ethereum development ecosystem
towards software best practices around code reuse. By defining an open,
community-driven package data format standard, this effort seeks to
provide support for package management tools development by offering a
general-purpose solution that has been designed with observed common
practices in mind.

-   Updates the schema for a *package manifest* to be compatible with
	the [metadata](https://solidity.readthedocs.io/en/latest/metadata.html) output for compilers.
-   Updates the `&quot;sources&quot;` object definition to support a wider range of source file types and serve as [JSON input](https://solidity.readthedocs.io/en/latest/using-the-compiler.html#compiler-input-and-output-json-description) for a compiler.
-   Moves compiler definitions to a top-level `&quot;compilers&quot;` array in order to:
	-   Simplify the links between a compiler version, sources, and the
		compiled assets.
	-   Simplify packages that use multiple compiler versions.
-   Updates key formatting from `snake_case` to `camelCase` to be
	more consistent with [JSON convention](https://google.github.io/styleguide/jsoncstyleguide.xml?showone=Property_Name_Format#Property_Name_Format).

### Guiding Principles

This specification makes the following assumptions about the document
lifecycle.

1.  Package manifests are intended to be generated programmatically by
    package management software as part of the release process.

2.  Package manifests will be consumed by package managers during tasks
    like installing package dependencies or building and deploying new
    releases.

3.  Package manifests will typically **not** be stored alongside the
    source, but rather by package registries *or* referenced by package
    registries and stored in something akin to IPFS.

4.  Package manifests can be used to verify public deployments of source 
	contracts.

### Use Cases

The following use cases were considered during the creation of this
specification.

* **owned**: A package which contains contracts which are not meant to be used by themselves but rather as base contracts to provide functionality to other contracts through inheritance.
* **transferable**: A package which has a single dependency.
* **standard-token**: A package which contains a reusable contract.
* **safe-math-lib**: A package which contains deployed instance of one of the package contracts.
* **piper-coin**: A package which contains a deployed instance of a reusable contract from a dependency.
* **escrow**: A package which contains a deployed instance of a local contract which is linked against a deployed instance of a local library.
* **wallet**: A package with a deployed instance of a local contract which is linked against a deployed instance of a library from a dependency.
* **wallet-with-send**: A package with a deployed instance which links against a deep dependency.
* **simple-auction**: Compiler `&quot;metadata&quot;` field output.

## Package Specification

### Conventions

#### RFC2119

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;https://www.ietf.org/rfc/rfc2119.txt&gt;


#### Prefixed vs Unprefixed

A [prefixed](#prefixed) hexadecimal value begins with `0x`.
[Unprefixed](#unprefixed) values have no prefix. Unless otherwise
specified, all hexadecimal values **should** be represented with the
`0x` prefix.

* **Prefixed**: `0xdeadbeef`
* **Unprefixed**: `deadbeef`

### Document Format

The canonical format is a single JSON object. Packages **must** conform
to the following serialization rules.

-   The document **must** be tightly packed, meaning no linebreaks or
    extra whitespace.

-   The keys in all objects **must** be sorted alphabetically.

-   Duplicate keys in the same object are invalid.

-   The document **must** use
    [UTF-8](https://en.wikipedia.org/wiki/UTF-8)
    encoding.

-   The document **must** not have a trailing newline.

-   To ensure backwards compatibility, `manifest_version` is a forbidden
    top-level key.


### Document Specification

The following fields are defined for the package. Custom fields **may**
be included. Custom fields **should** be prefixed with `x-` to prevent
name collisions with future versions of the specification.

* **See Also**: Formalized ([JSON-Schema](https://json-schema.org)) version of this specification: [package.spec.json](/EIPs/assets/eip-2678/package.spec.json)
* **Jump To**: [Definitions](#object-definitions)

### EthPM Manifest Version

The `manifest` field defines the specification version that this
document conforms to.

-   Packages **must** include this field.

* **Required**: Yes
* **Key**: `manifest`
* **Type**: String
* **Allowed Values**: `ethpm/3`

### Package Name

The `name` field defines a human readable name for this package.

-   Packages **should** include this field to be released on an EthPM
    registry.

-   Package names **must** begin with a lowercase letter and be
    comprised of only the lowercase letters `a-z`, numeric characters `0-9`, and the
    dash character `-`.

-   Package names **must** not exceed 255 characters in length.

* **Required**: If `version` is included.
* **Key**: `name`
* **Type**: String
* **Format**: **must** match the regular expression `^[a-z][-a-z0-9]{0,255}$`

### Package Version

The `version` field declares the version number of this release.

-   Packages **should** include this field to be released on an EthPM
    registry.

-   This value **should** conform to the
    [semver](http://semver.org/) version numbering
    specification.

* **Required**: If `name` is included.
* **Key**: `version`
* **Type**: String

### Package Metadata

The `meta` field defines a location for metadata about the package which
is not integral in nature for package installation, but may be important
or convenient to have on-hand for other reasons.

-   This field **should** be included in all Packages.

* **Required**: No
* **Key**: `meta`
* **Type**: [Package Meta Object](#the-package-meta-object)

### Sources

The `sources` field defines a source tree that **should** comprise the
full source tree necessary to recompile the contracts contained in this
release.

* **Required**: No
* **Key**: `sources`
* **Type**: Object (String: [Sources Object](#the-source-object))

### Contract Types

The `contractTypes` field hosts the [Contract
Types](#contract-type) which have been included in this release.

-   Packages **should** only include contract types that can be found in
    the source files for this package.

-   Packages **should not** include contract types from dependencies.

-   Packages **should not** include abstract contracts in the contract
    types section of a release.

* **Required**: No
* **Key**: `contractTypes`
* **Type**: Object (String: [Contract Type Object](#the-contract-type-object))
* **Format**: Keys **must** be valid [Contract Aliases](#contract-alias). &lt;br&gt; Values **must** conform to the [Contract Type Object](#the-contract-type-object) definition.

### Compilers

The `compilers` field holds the information about the compilers and
their settings that have been used to generate the various
`contractTypes` included in this release.

* **Required**: No
* **Key**: `compilers`
* **Type**: Array ([Compiler Information Object](#the-compiler-information-object))

### Deployments

The `deployments` field holds the information for the chains on which
this release has [Contract Instances](#contract-instance) as well
as the [Contract Types](#contract-type) and other deployment
details for those deployed contract instances. The set of chains defined
by the [BIP122 URI](#bip122-uri) keys for this object **must** be
unique. There cannot be two different URI keys in a deployments field
representing the same blockchain.

* **Required**: No
* **Key**: `deployments`
* **Type**: Object (String: Object(String: [Contract Instance Object](#the-contract-instance-object)))
* **Format**: Keys **must** be a valid BIP122 URI chain definition. &lt;br&gt;Values **must** be objects which conform to the following format:&lt;br&gt;- Keys **must** be valid [Contract Instance Names](#contract-instance-name)&lt;br&gt;- Values **must** be a valid [Contract Instance Object](#the-contract-instance-object)

### Build Dependencies

The `buildDependencies` field defines a key/value mapping of EthPM
packages that this project depends on.

* **Required**: No
* **Key**: `buildDependencies`
* **Type**: Object (String: String)
* **Format**: Keys **must** be valid [package names](#package-name).&lt;br&gt;Values **must** be a [Content Addressable URI](#content-addressable-uri) which resolves to a valid package that conforms the same EthPM manifest version as its parent.

### Object Definitions

Definitions for different objects used within the Package. All objects
allow custom fields to be included. Custom fields **should** be prefixed
with `x-` to prevent name collisions with future versions of the
specification.


### The *Link Reference* Object

A [Link Reference](#link-reference) object has the following
key/value pairs. All link references are assumed to be associated with
some corresponding [Bytecode](#bytecode).

#### Offsets: `offsets`

The `offsets` field is an array of integers, corresponding to each of
the start positions where the link reference appears in the bytecode.
Locations are 0-indexed from the beginning of the bytes representation
of the corresponding bytecode. This field is invalid if it references a
position that is beyond the end of the bytecode.

* **Required**: Yes
* **Type**: Array

#### Length: `length`

The `length` field is an integer which defines the length in bytes of
the link reference. This field is invalid if the end of the defined link
reference exceeds the end of the bytecode.

* **Required**: Yes
* **Type**: Integer

#### Name: `name`

The `name` field is a string which **must** be a valid
[Identifier](#identifier). Any link references which **should** be
linked with the same link value **should** be given the same name.

* **Required**: No
* **Type**: String
* **Format**: **must** conform to the [Identifier](#identifier) format.

### The *Link Value* Object

Describes a single [Link Value](#link-value).

A **Link Value object** is defined to have the following key/value
pairs.


#### Offsets: `offsets`

The `offsets` field defines the locations within the corresponding
bytecode where the `value` for this link value was written. These
locations are 0-indexed from the beginning of the bytes representation
of the corresponding bytecode.

* **Required**: Yes
* **Type**: Integer
* **Format**: See below.

Format

Array of integers, where each integer **must** conform to all of the
following.

-   greater than or equal to zero

-   strictly less than the length of the unprefixed hexadecimal
    representation of the corresponding bytecode.

#### Type: `type`

The `type` field defines the `value` type for determining what is
encoded when [linking](#linking) the corresponding bytecode.

* **Required**: Yes
* **Type**: String
* **Allowed Values**: `&quot;literal&quot;` for bytecode literals.&lt;br&gt;`&quot;reference&quot;` for named references to a particular [Contract Instance](#contract-instance)

#### Value: `value`

The `value` field defines the value which should be written when [linking](#linking) the corresponding bytecode.

* **Required**: Yes
* **Type**: String
* **Format**: Determined based on `type`, see below.

Format

For static value *literals* (e.g. address), value **must** be a 0x-prefixed
hexadecimal string representing bytes.


To reference the address of a [Contract
Instance](#contract-instance) from the current package the value
should be the name of that contract instance.

-   This value **must** be a valid [Contract Instance
    Name](#contract-instance-name).

-   The chain definition under which the contract instance that this
    link value belongs to must contain this value within its keys.

-   This value **may not** reference the same contract instance that
    this link value belongs to.

To reference a contract instance from a [Package](#package) from
somewhere within the dependency tree the value is constructed as
follows.

-   Let `[p1, p2, .. pn]` define a path down the dependency tree.

-   Each of `p1, p2, pn` **must** be valid package names.

-   `p1` **must** be present in keys of the `buildDependencies` for the
    current package.

-   For every `pn` where `n &gt; 1`, `pn` **must** be present in the keys
    of the `buildDependencies` of the package for `pn-1`.

-   The value is represented by the string
    `&lt;p1&gt;:&lt;p2&gt;:&lt;...&gt;:&lt;pn&gt;:&lt;contract-instance&gt;` where all of `&lt;p1&gt;`,
    `&lt;p2&gt;`, `&lt;pn&gt;` are valid package names and `&lt;contract-instance&gt;` is
    a valid [Contract Name](#contract-name).

-   The `&lt;contract-instance&gt;` value **must** be a valid [Contract
    Instance Name](#contract-instance-name).

-   Within the package of the dependency defined by `&lt;pn&gt;`, all of the
    following must be satisfiable:

    -   There **must** be *exactly* one chain defined under the
        `deployments` key which matches the chain definition that this
        link value is nested under.

    -   The `&lt;contract-instance&gt;` value **must** be present in the keys
        of the matching chain.
  
### The *Bytecode* Object

A bytecode object has the following key/value pairs.

#### Bytecode: `bytecode`

The `bytecode` field is a string containing the `0x` prefixed
hexadecimal representation of the bytecode.

* **Required**: Yes
* **Type**:  String
* **Format**: `0x` prefixed hexadecimal.

#### Link References: `linkReferences`

The `linkReferences` field defines the locations in the corresponding
bytecode which require [linking](#linking).

* **Required**: No
* **Type**:  Array
* **Format**: All values **must** be valid [Link Reference objects](#the-link-reference-object). See also below.

Format

This field is considered invalid if *any* of the [Link
References](#link-reference) are invalid when applied to the
corresponding `bytecode` field, *or* if any of the link references
intersect.

Intersection is defined as two link references which overlap.

#### Link Dependencies: `linkDependencies`

The `linkDependencies` defines the [Link Values](#link-value) that
have been used to link the corresponding bytecode.

* **Required**: No
* **Type**:  Array
* **Format**: All values **must** be valid [Link Value objects](#the-link-value-object). See also below.

Format

Validation of this field includes the following:

-   Two link value objects **must not** contain any of the same values
    for `offsets`.

-   Each [link value object](#the-link-value-object) **must** have a
    corresponding [link reference object](#the-link-reference-object) under
    the `linkReferences` field.

-   The length of the resolved `value` **must** be equal to the `length`
    of the corresponding [Link Reference](#link-reference).


### The *Package Meta* Object

The *Package Meta* object is defined to have the following key/value
pairs.

#### Authors

The `authors` field defines a list of human readable names for the
authors of this package. Packages **may** include this field.

* **Required**: No
* **Key**: `authors`
* **Type**:  Array(String)

#### License

The `license` field declares the license associated with this package.
This value **should** conform to the
[SPDX](https://spdx.org/licenses/)
format. Packages **should** include this field. If a file [Source
Object](#the-source-object) defines its own license, that license takes
precedence for that particular file over this package-scoped `meta`
license.

* **Required**: No
* **Key**: `license`
* **Type**:  String

#### Description

The `description` field provides additional detail that may be relevant
for the package. Packages **may** include this field.

* **Required**: No
* **Key**: `description`
* **Type**:  String

#### Keywords

The `keywords` field provides relevant keywords related to this package.

* **Required**: No
* **Key**: `keywords`
* **Type**:  Array(String)

#### Links

The `links` field provides URIs to relevant resources associated with
this package. When possible, authors **should** use the following keys
for the following common resources.

-   `website`: Primary website for the package.

-   `documentation`: Package Documentation

-   `repository`: Location of the project source code.

* **Required**: No
* **Key**: `links`
* **Type**:  Object (String: String)

### The *Sources* Object

A *Sources* object is defined to have the following fields.

* **Key**: A unique identifier for the source file. (String)
* **Value**: [Source Object](#the-source-object)

### The *Source* Object

#### Checksum: `checksum`

Hash of the source file.

* **Required**: Only **if** the `content` field is missing and none of the provided URLs contain a content hash.
* **Key**: `checksum`
* **Value**: [Checksum Object](#the-checksum-object)

#### URLS: `urls`

Array of urls that resolve to the same source file.  
-   Urls **should** be stored on a content-addressable filesystem.
    **If** they are not, then either `content` or `checksum` **must** be
    included.

-   Urls **must** be prefixed with a scheme.

-   If the resulting document is a directory the key **should** be
    interpreted as a directory path.

-   If the resulting document is a file the key **should** be
    interpreted as a file path.

* **Required**: If `content` is not included.
* **Key**: `urls`
* **Value**: Array(String)

#### Content: `content`

Inlined contract source. If both `urls` and `content` are provided, the `content` value
**must** match the content of the files identified in `urls`.

* **Required**: If `urls` is not included.
* **Key**: `content`
* **Value**: String

#### Install Path: `installPath`

Filesystem path of source file.  
-   **Must** be a relative filesystem path that begins with a `./`.

-   **Must** resolve to a path that is within the current virtual
    working directory.

-   **Must** be unique across all included sources.

-   **Must not** contain `../` to avoid accessing files outside of 
	the source folder in improper implementations.

* **Required**: This field **must** be included for the package to be writable to disk.
* **Key**: `installPath`
* **Value**: String

#### Type: `type`

The `type` field declares the type of the source file. The field
**should** be one of the following values: `solidity`, `vyper`,
`abi-json`, `solidity-ast-json`.

* **Required**: No
* **Key**: `type`
* **Value**: String

#### License: `license`

The `license` field declares the type of license associated with
this source file. When defined, this license overrides the
package-scoped [meta license](#license).

* **Required**: No
* **Key**: `license`
* **Value**: String

### The *Checksum* Object

A *Checksum* object is defined to have the following key/value pairs.

#### Algorithm: `algorithm`

The `algorithm` used to generate the corresponding hash. Possible 
algorithms include, but are not limited to `sha3`, `sha256`, `md5`,
`keccak256`.

* **Required**: Yes
* **Type**:  String

#### Hash: `hash`

The `hash` of a source files contents generated with the corresponding
algorithm.

* **Required**: Yes
* **Type**:  String

### The *Contract Type* Object

A *Contract Type* object is defined to have the following key/value
pairs.

#### Contract Name: `contractName`

The `contractName` field defines the [Contract
Name](#contract-name) for this [Contract
Type](#contract-type).

* **Required**: If the [Contract Name](#contract-name) and [Contract Alias](#contract-alias) are not the same.
* **Type**:  String
* **Format**: **Must** be a valid [Contract Name](#contract-name)

#### Source ID: `sourceId`

The global source identifier for the source file from which this
contract type was generated.

* **Required**: No
* **Type**:  String
* **Format**: **Must** match a unique source ID included in the [Sources Object](#the-sources-object) for this package.

#### Deployment Bytecode: `deploymentBytecode`

The `deploymentBytecode` field defines the bytecode for this [Contract
Type](#contract-type).

* **Required**: No
* **Type**:  Object
* **Format**: **Must** conform to the [Bytecode object](#the-bytecode-object) format.

#### Runtime Bytecode: `runtimeBytecode`

The `runtimeBytecode` field defines the unlinked `0x`-prefixed runtime
portion of [Bytecode](#bytecode) for this [Contract
Type](#contract-type).

* **Required**: No
* **Type**:  Object
* **Format**: **Must** conform to the [Bytecode object](#the-bytecode-object) format.

#### ABI: `abi`

* **Required**: No
* **Type**:  Array
* **Format**: **Must** conform to the [Ethereum Contract ABI JSON](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI#json) format.

#### UserDoc: `userdoc`

* **Required**: No
* **Type**:  Object
* **Format**: **Must** conform to the [UserDoc](https://github.com/ethereum/wiki/wiki/Ethereum-Natural-Specification-Format#user-documentation) format.

#### DevDoc: `devdoc`

* **Required**: No
* **Type**:  Object
* **Format**: **Must** conform to the [DevDoc](https://github.com/ethereum/wiki/wiki/Ethereum-Natural-Specification-Format#developer-documentation) format.

### The *Contract Instance* Object

A **Contract Instance Object** represents a single deployed [Contract
Instance](#contract-instance) and is defined to have the following
key/value pairs.

#### Contract Type: `contractType`

The `contractType` field defines the [Contract
Type](#contract-type) for this [Contract
Instance](#contract-instance). This can reference any of the
contract types included in this [Package](#package) *or* any of the
contract types found in any of the package dependencies from the
`buildDependencies` section of the [Package
Manifest](#package-manifest).

* **Required**: Yes
* **Type**:  String
* **Format**: See below.

Format

Values for this field **must** conform to *one of* the two formats
herein.

To reference a contract type from this Package, use the format
`&lt;contract-alias&gt;`.

-   The `&lt;contract-alias&gt;` value **must** be a valid [Contract
    Alias](#contract-alias).

-   The value **must** be present in the keys of the `contractTypes`
    section of this Package.

To reference a contract type from a dependency, use the format
`&lt;package-name&gt;:&lt;contract-alias&gt;`.

-   The `&lt;package-name&gt;` value **must** be present in the keys of the
    `buildDependencies` of this Package.

-   The `&lt;contract-alias&gt;` value **must** be be a valid [Contract
    Alias](#contract-alias).

-   The resolved package for `&lt;package-name&gt;` must contain the
    `&lt;contract-alias&gt;` value in the keys of the `contractTypes` section.

#### Address: `address`

The `address` field defines the [Address](#address) of the
[Contract Instance](#contract-instance).

* **Required**: Yes
* **Type**:  String
* **Format**: Hex encoded `0x` prefixed Ethereum address matching the regular expression `^0x[0-9a-fA-F]{40}$`.

#### Transaction: `transaction`

The `transaction` field defines the transaction hash in which this
[Contract Instance](#contract-instance) was created.

* **Required**: No
* **Type**:  String
* **Format**: `0x` prefixed hex encoded transaction hash.

#### Block: `block`

The `block` field defines the block hash in which this the transaction
which created this *contract instance* was mined.

* **Required**: No
* **Type**:  String
* **Format**: `0x` prefixed hex encoded block hash.

#### Runtime Bytecode: `runtimeBytecode`

The `runtimeBytecode` field defines the runtime portion of bytecode for
this [Contract Instance](#contract-instance). When present, the
value from this field supersedes the `runtimeBytecode` from the
[Contract Type](#contract-type) for this [Contract
Instance](#contract-instance).

* **Required**: No
* **Type**:  Object
* **Format**: **Must** conform to the [Bytecode Object](#the-bytecode-object) format.

Every entry in the `linkReferences` for this bytecode **must** have a
corresponding entry in the `linkDependencies` section.

### The *Compiler Information* Object

The `compilers` field defines the various compilers and settings used
during compilation of any [Contract Types](#contract-type) or
[Contract Instance](#contract-instance) included in this package.

A *Compiler Information* object is defined to have the following
key/value pairs.

#### Name: `name`

The `name` field defines which compiler was used in compilation.

* **Required**: Yes
* **Key**: `name`
* **Type**:  String

#### Version: `version`

The `version` field defines the version of the compiler. The field
**should** be OS agnostic (OS not included in the string) and take the
form of either the stable version in
[semver](http://semver.org/) format or if built on a
nightly should be denoted in the form of `&lt;semver&gt;-&lt;commit-hash&gt;` ex:
`0.4.8-commit.60cc1668`.

* **Required**: Yes
* **Key**: `version`
* **Type**:  String

#### Settings: `settings`

The `settings` field defines any settings or configuration that was used
in compilation. For the `&quot;solc&quot;` compiler, this **should** conform to
the [Compiler Input and Output
Description](http://solidity.readthedocs.io/en/latest/using-the-compiler.html#compiler-input-and-output-json-description).

* **Required**: No
* **Key**: `settings`
* **Type**:  Object

#### Contract Types: `contractTypes`

A list of the [Contract Alias](#contract-alias) or [Contract Types](#contract-type) in this package
that used this compiler to generate its outputs.

-   All `contractTypes` that locally declare `runtimeBytecode`
    **should** be attributed for by a compiler object.

-   A single `contractTypes` **must** not be attributed to more than one
    compiler.

* **Required**: No
* **Key**: `contractTypes`
* **Type**:  Array([Contract Alias](#contract-alias))


### BIP122 URI

BIP122 URIs are used to define a blockchain via a subset of the
[BIP-122](https://github.com/bitcoin/bips/blob/master/bip-0122.mediawiki)
spec.

    blockchain://&lt;genesis_hash&gt;/block/&lt;latest confirmed block hash&gt;

The `&lt;genesis hash&gt;` represents the blockhash of the first block on the
chain, and `&lt;latest confirmed block hash&gt;` represents the hash of the
latest block that’s been reliably confirmed (package managers should be
free to choose their desired level of confirmations).

### Glossary

The terms in this glossary have been updated to reflect the changes made
in V3.

#### ABI  
The JSON representation of the application binary interface. See the
official
[specification](https://solidity.readthedocs.io/en/develop/abi-spec.html)
for more information.

#### Address  
A public identifier for an account on a particular chain

#### Bytecode  
The set of EVM instructions as produced by a compiler. Unless otherwise
specified this should be assumed to be hexadecimal encoded, representing
a whole number of bytes, and [prefixed](#prefixed) with `0x`.

Bytecode can either be linked or unlinked. (see
[Linking](#linking))

* **Unlinked Bytecode**: The hexadecimal representation of a contract’s EVM instructions that contains sections of code that requires [linking](#linking) for the contract to be functional.&lt;br&gt;The sections of code which are unlinked **must** be filled in with zero bytes.&lt;br&gt;**Example**: `0x606060405260e06000730000000000000000000000000000000000000000634d536f`
* **Linked Bytecode**: The hexadecimal representation of a contract’s EVM instructions which has had all [Link References](#link-reference) replaced with the desired [Link Values](#link-value). **Example**: `0x606060405260e06000736fe36000604051602001526040518160e060020a634d536f`

#### Chain Definition  
This definition originates from [BIP122
URI](https://github.com/bitcoin/bips/blob/master/bip-0122.mediawiki).

A URI in the format `blockchain://&lt;chain_id&gt;/block/&lt;block_hash&gt;`

-   `chain_id` is the unprefixed hexadecimal representation of the
    genesis hash for the chain.

-   `block_hash` is the unprefixed hexadecimal representation of the
    hash of a block on the chain.

A chain is considered to match a chain definition if the genesis
block hash matches the `chain_id` and the block defined by `block_hash`
can be found on that chain. It is possible for multiple chains to match
a single URI, in which case all chains are considered valid matches

#### Content Addressable URI  
Any URI which contains a cryptographic hash which can be used to verify
the integrity of the content found at the URI.

The URI format is defined in RFC3986

It is **recommended** that tools support IPFS and Swarm.

#### Contract Alias  
This is a name used to reference a specific [Contract
Type](#contract-type). Contract aliases **must** be unique within a
single [Package](#package).

The contract alias **must** use *one of* the following naming schemes:

-   `&lt;contract-name&gt;`

-   `&lt;contract-name&gt;&lt;identifier&gt;`

The `&lt;contract-name&gt;` portion **must** be the same as the [Contract
Name](#contract-name) for this contract type.

The `&lt;identifier&gt;` portion **must** match the regular expression
`^[-a-zA-Z0-9]{1,256}$`.

#### Contract Instance  
A contract instance a specific deployed version of a [Contract
Type](#contract-type).

All contract instances have an [Address](#address) on some specific
chain.

#### Contract Instance Name  
A name which refers to a specific [Contract
Instance](#contract-instance) on a specific chain from the
deployments of a single [Package](#package). This name **must** be
unique across all other contract instances for the given chain. The name
must conform to the regular expression
`^[a-zA-Z_$][a-zA-Z0-9_$]{0,255}$`

In cases where there is a single deployed instance of a given [Contract
Type](#contract-type), package managers **should** use the
[Contract Alias](#contract-alias) for that contract type for this
name.

In cases where there are multiple deployed instances of a given contract
type, package managers **should** use a name which provides some added
semantic information as to help differentiate the two deployed instances
in a meaningful way.

#### Contract Name  
The name found in the source code that defines a specific [Contract
Type](#contract-type). These names **must** conform to the regular
expression `^[a-zA-Z_$][a-zA-Z0-9_$]{0,255}$`.

There can be multiple contracts with the same contract name in a
projects source files.

#### Contract Type  
Refers to a specific contract in the package source. This term can be
used to refer to an abstract contract, a normal contract, or a library.
Two contracts are of the same contract type if they have the same
bytecode.

Example:

    contract Wallet {
        ...
    }

A deployed instance of the `Wallet` contract would be of of type
`Wallet`.

#### Identifier  
Refers generally to a named entity in the [Package](#package).

A string matching the regular expression
`^[a-zA-Z][-_a-zA-Z0-9]{0,255}$`

#### Link Reference  
A location within a contract’s bytecode which needs to be linked. A link
reference has the following properties.

* **`offset`**: Defines the location within the bytecode where the link reference begins.
* **`length`**: Defines the length of the reference.
* **`name`**: (optional) A string to identify the reference.

#### Link Value  
A link value is the value which can be inserted in place of a [Link
Reference](#link-reference)

#### Linking  
The act of replacing [Link References](#link-reference) with [Link
Values](#link-value) within some [Bytecode](#bytecode).

#### Package  
Distribution of an application’s source or compiled bytecode along with
metadata related to authorship, license, versioning, et al.

For brevity, the term **Package** is often used metonymously to mean
[Package Manifest](#package-manifest).

#### Package Manifest  
A machine-readable description of a package.

#### Prefixed  
[Bytecode](#bytecode) string with leading `0x`.

* **Example**: `0xdeadbeef`

#### Unprefixed  
Not [Prefixed](#prefixed).

* **Example**: `deadbeef`

## Rationale

### Minification

EthPM packages are distributed as alphabetically-ordered &amp; minified JSON to ensure consistency.
Since packages are published on content-addressable filesystems (eg. IPFS), this restriction
guarantees that any given set of contract assets will always resolve to the same content-addressed URI.

### Package Names

Package names are restricted to lower-case characters, numbers, and `-` to improve the readability
of the package name, in turn improving the security properties for a package. A user is more likely
to accurately identify their target package with this restricted set of characters, and not confuse
a malicious package that disguises itself as a trusted package with similar but different 
characters (e.g. `O` and `0`).

### BIP122

The BIP-122 standard has been used since EthPM v1 since it is an industry standard URI scheme for
identifying different blockchains and distinguishing between forks.

### Compilers

Compilers are now defined in a top-level array, simplifying the task for tooling to identify the compiler types
needed to interact with or validate the contract assets. This also removes unnecessarily duplicated
information, should multiple `contractTypes` share the same compiler type.

## Backwards Compatibility

To improve understanding and readability of the EthPM spec, the
`manifest_version` field was updated to `manifest` in v3. To ensure 
backwards compatibility, v3 packages **must** define a top-level
`&quot;manifest&quot;` with a value of `&quot;ethpm/3&quot;`. Additionally,
`&quot;manifest_version&quot;` is a forbidden top-level key in v3 packages.


## Security Considerations

Using EthPM packages implicitly requires importing &amp;/or executing code written by others. The EthPM spec
guarantees that when using a properly constructed and released EthPM package, the user will have the exact same
code that was included in the package by the package author. However, it is impossible to guarantee that this code
is safe to interact with. Therefore, it is critical that end users only interact with EthPM packages authored and
released by individuals or organizations that they trust to include non-malicious code.


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 26 May 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2678</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2678</guid>
      </item>
    
      <item>
        <title>Ethereum 2 wallet layout</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2680-ethereum-2-wallet-layout/4323</comments>
        
        <description>## Simple Summary

A standard layout and naming format for walletstore and keystore for both hierarchical (e.g. filesystem, Amazon S3) and non-hierarchical (key/value) storage systems.

## Abstract

Ethereum wallets have no standards for their layout in persistent storage, making different wallet implementations incompatible.  This defines a standard for the placement of Ethereum walletstores and keystores, making it possible for different software to work with the same wallets and keys.

## Motivation

A standard layout for wallets and accounts allows interoperability between validators.  This benefits users, as they can move from one validator software to another (and back) without requiring movement of files.  This is important because any movement of files containing keys involves danger of either deleting them or duplicating them, both of which could cause loss of access to funds.

## Specification

There are four elements for a wallet that need to be addressed.  These are defined below.

### Base location
The base location is required to be well-known, either pre-defined or defined by the storage system&apos;s connection parameters.

For filesystems the pre-defined base location for different operating systems is as follows:

  - Windows: `%APPDATA%\ethereum2\wallets`
  - MacOSX: `${HOME}/Library/Application Support/ethereum2/wallets`
  - Linux: `${HOME}/.config/ethereum2/wallets`

For other hierarchical stores, for example Amazon S3, the base location MUST be the lower-case hex string representing the [SHA-256](/EIPs/assets/eip-2680/sha256-384-512.pdf) hash of the string &quot;Ethereum 2 wallet:&quot; appended with the identifier for the hierarchical store.  For example, if the account ID for a user&apos;s Amazon S3 account is &quot;AbC0438EB&quot; then:

  - string would be `Ethereum 2 wallet:AbC0438EB`
  - SHA-256 hash of string would be the byte array `0x991ec14a8d13836b10d8c3039c9e30876491cb8aa9c9c16967578afc815c9229`
  - base location would be the string `991ec14a8d13836b10d8c3039c9e30876491cb8aa9c9c16967578afc815c9229`

For non-hierarchical stores there is no base location.

### Wallet container
The wallet container holds the walletstore and related keystores.

The wallet container is identified by the wallet&apos;s UUID.  It MUST be a string following the syntactic structure as laid out in [section 3 of RFC 4122](https://tools.ietf.org/html/rfc4122#section-3).

### Walletstore
The walletstore element contains the walletstore and is held within the wallet container.  It is identified by the wallet&apos;s UUID.  It MUST be a string following the syntactic structure as laid out in [section 3 of RFC 4122](https://tools.ietf.org/html/rfc4122#section-3).

### Keystore
The keystore element contains the keystore for a given key and is held within the wallet container.  It is identified by the key&apos;s UUID.  It MUST be a string following the syntactic structure as laid out in [section 3 of RFC 4122](https://tools.ietf.org/html/rfc4122#section-3).

## Hierarchical store example
Hierarchical stores are a common way to store and organize information.  The most common example is the filesystem, but a number of object-based stores such as Amazon S3 also provide hierarchical naming.

Putting these elements together for a sample wallet with wallet UUID `1f031fff-c51d-44fc-8baf-d6b304cb70a7` and key UUIDs `1302106c-8441-4e2e-b687-6c77f49fc624` and `4a320100-83fd-4db7-8126-6d6d205ba834` gives the following layout:

```
- 1f031fff-c51d-44fc-8baf-d6b304cb70a7
+- 1302106c-8441-4e2e-b687-6c77f49fc624
+- 1f031fff-c51d-44fc-8baf-d6b304cb70a7
+- 4a320100-83fd-4db7-8126-6d6d205ba834
```

### Non-hierarchical store example
Non-hierarchical stores use a simplified approach where the wallet UUID and key UUIDs are concatenated using the &apos;:&apos; character.  Using the same example wallet and key UUIDs as above would result in objects with the following keys:

```
1f031fff-c51d-44fc-8baf-d6b304cb70a7:1302106c-8441-4e2e-b687-6c77f49fc624
1f031fff-c51d-44fc-8baf-d6b304cb70a7:1f031fff-c51d-44fc-8baf-d6b304cb70a7
1f031fff-c51d-44fc-8baf-d6b304cb70a7:4a320100-83fd-4db7-8126-6d6d205ba834
```

### Protecting against concurrent write access
TBD

### Iterating over wallets
In the case of hierarchical stores and iteration-capable non-hierarchical stores iteration over wallets is a matter of iterating over the files in the root container.

An implementer MAY include an index in the base location.  If so then it MUST follow the structure as specified in the following &quot;Index format&quot; section.

### Iterating over accounts
In the case of hierarchical stores iteration over accounts is a matter of iterating over the files in the wallet container.

An implementer MAY include an index within a wallet container for accounts within that wallet.  If so then it MUST follow the structure as specified in the following &quot;Index format&quot; section.

### Index format
The index format is the same for both wallets and accounts, following a standard JSON schema.

```json
{
    &quot;type&quot;: &quot;array&quot;,
    &quot;items&quot;: {
        &quot;type&quot;: &quot;object&quot;,
        &quot;properties&quot;: {
            &quot;uuid&quot;: {
                &quot;type&quot;: &quot;string&quot;
            },
            &quot;name&quot;: {
                &quot;type&quot;: &quot;string&quot;
            }
        },
        &quot;required&quot;: [
            &quot;uuid&quot;,
            &quot;name&quot;
        ]
    }
}
```

The index MUST use the identifier &apos;index&apos;.

Public keys must NOT be stored in the index.

## Rationale

A standard for walletstores, similar to that for keystores, provides a higher level of compatibility between wallets and allows for simpler wallet and key interchange between them.

## Implementation

A Go implementation of the filesystem layout can be found at [https://github.com/wealdtech/go-eth2-wallet-filesystem](https://github.com/wealdtech/go-eth2-wallet-filesystem).

A Go implementation of the Amazon S3 layout can be found at [https://github.com/wealdtech/go-eth2-wallet-s3](https://github.com/wealdtech/go-eth2-wallet-s3).

## Security Considerations

Locations for wallet stores are defined to be within each user&apos;s personal space, reducing the possibility of accidental exposure of information.  It is, however, still possible for permissions to be set such that this data is world-readable, and applications implementing this EIP should attempt to set, and reset, permissions to ensure that only the relevant user has access to the information.

The names for both wallet and key stores are UUIDs, ensuring that no data is leaked from the metadata.
  
## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 29 May 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2680</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2680</guid>
      </item>
    
      <item>
        <title>Limit account nonce to 2^64-1</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2681-limit-account-nonce-to-2-64-1/4324</comments>
        
        <description>## Abstract

Limit account nonce to be between `0` and `2^64-1`.

## Motivation

Account nonces are currently specified to be arbitrarily long unsigned integers. Dealing with arbitrary length data in the state witnesses is not optimal, therefore this EIP will allow proofs to represent the nonce in a more optimized way.

Additionally it could prove beneficial to transaction formats, where some improvements are potentially sought by at least three other proposals.

Lastly, this facilitates a minor optimisation in clients, because the nonce no longer needs to be kept as a 256-bit number.

## Specification

Introduce two new restrictions retroactively from genesis:

1. Consider any transaction invalid, where the nonce exceeds or equals to `2^64-1`.
2. The `CREATE` and `CREATE2` instructions&apos; execution ends with the result `0` pushed on stack, where the account nonce is `2^64-1`. Gas for initcode execution is not deducted in this case.

## Rationale

1. It is unlikely for any nonce to reach or exceed the proposed limit. If one would want to reach that limit via external transactions, it would cost at least `21000 * (2^64-1) = 387_381_625_547_900_583_915_000` gas.

2. It must be noted that in the past, in the Morden testnet, each new account had a starting nonce of `2^20` in order to differentiate transactions from mainnet transactions.
This mode of replay protection is out of fashion since [EIP-155](/EIPs/EIPS/eip-155) introduced a more elegant way using chain identifiers.

3. Most clients already consider the nonce field to be 64-bit, such as go-ethereum.

4. The reason a transaction with nonce `2^64-1` is invalid, because otherwise after inclusion the sender account&apos;s nonce would exceed `2^64-1`.

## Backwards Compatibility

While this is a breaking change, no actual effect should be visible:

1. There is no account in the state currently which would have a nonce exceeding that value. As of November 2020, the account `0xea674fdde714fd979de3edf0f56aa9716b898ec8` is responsible for the highest account nonce at approximately 29 million.

2. go-ethereum already has this restriction partially in place (`state.Account.Nonce` and `types.txdata.AccountNonce` it as a 64-bit number).

## Security Considerations

None.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 25 Apr 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2681</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2681</guid>
      </item>
    
      <item>
        <title>JavaScript `request` method RPC transport</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2697</comments>
        
        <description>## Simple Summary
A standard for remote procedure calls between an Ethereum Provider and an Ethereum Client when both are able to interface with each other via a shared JavaScript object.

## Abstract
This standard provides the description of an object that is made available to JavaScript applications which they can use to communicate with the Ethereum blockchain through.  This standard only describes the transport mechanism, it does not specify the payloads that are valid nor does it specify how the client or the provider will discover or agree on payload content.

How/where this Ethereum object is exposed is left to future standards.

## Motivation
When working within a JavaScript runtime (such as NodeJS, Electron, Browser, etc.) it may be possible for the runtime or a runtime plugin to inject objects into the runtime.  Someone authoring a runtime or a runtime plugin may choose to expose an Ethereum Provider to any JavaScript apps or scripts running within that runtime in order to provide indirect access to an Ethereum-like blockchain and potentially signing tools.  In order to achieve maximum compatibility between the provider and the client, a standard is necessary for what the shape of that object is.

## Specification

### RFC-2119

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;,  &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC-2119](https://www.ietf.org/rfc/rfc2119.txt).

### Interface

TypeScript interface definition:
```ts
interface RequestArguments {
	readonly method: string;
	readonly params?: readonly unknown[] | object;
}

interface EthereumProvider {
	request(args: RequestArguments): Promise&lt;unknown&gt;
}
```
The Provider **MUST** implement a `request` method on the exposed `EthereumProvider` object.  The `request` method **MUST** be callable with a single parameter which contains the arguments for the request as defined in the TypeScript `interface` above.

If the Provider supports a JSON-RPC (https://www.jsonrpc.org/specification) request as specified elsewhere, then it **MUST** accept a `request` call for that JSON-RPC method with the `RequestArguments.method` argument matching the JSON-RPC `method` string for the RPC call and the `RequestArguments.params` matching the `params` object of the RPC call.  The `RequestArguments.params` should be encoded as a JavaScript object matching the specified JSON-RPC type, not encoded as a JSON string as would normally be the case when transporting JSON-RPC.

#### Example
If the JSON-RPC request would contain a payload like:
```typescript
&apos;{ &quot;jsonrpc&quot;: &quot;2.0&quot;, &quot;id&quot;: 1, &quot;method&quot;: &quot;do_work&quot;, &quot;params&quot;: [ 5, &quot;hello&quot; ] }&apos;
```
Then the matching `EthereumProvider.request` call would be:
```typescript
declare const provider: EthereumProvider
provider.request({ method: &apos;method&apos;, params: [ 5, &apos;hello&apos; ] })
```

### Results
If the Provider supports a JSON-RPC request as specified elsewhere, then it **MUST** return an object that matches the expected `result` definition for the associated JSON-RPC request.

#### Example
If the JSON-RPC response would contain a payload like:
```typescript
&apos;{ &quot;jsonrpc&quot;: &quot;2.0&quot;, &quot;id&quot;: 1, &quot;result&quot;: { &quot;color&quot;: &quot;red&quot;, &quot;value&quot;: 5 } }&apos;
```
Then the matching `EthereumProvider.request` response would be:
```typescript
{ color: &apos;red&apos;, value: 5 }
```

### Errors
```ts
interface ProviderRpcError extends Error {
	message: string;
	code: number;
	data?: unknown;
}
```

| code | message               | meaning                                                                  |
| -----| --------------------- | ------------------------------------------------------------------------ |
| 4001 | User Rejected Request | The user rejected the request.                                           |
| 4100 | Unauthorized          | The requested method and/or account has not been authorized by the user. |
| 4200 | Unsupported Method    | The Provider does not support the requested method.                      |
| 4900 | Disconnected          | The Provider is disconnected from all chains.                            |
| 4901 | Chain Disconnected    | The Provider is not connected to the requested chain.                    |

If the Provider is unable to fulfill a request for any reason, it **MUST** resolve the promise as an error.  The resolved error **MUST** be shaped as a `ProviderRpcError` defined above whenever possible.  _While it is impossible to guaranteed that a JavaScript application will never throw an out of memory or stack overflow error, care should be taken to ensure that promise rejections conform to the above shape whenever possible._

If a `code` is provided that is listed in the list above, or in the JSON-RPC specification (https://www.jsonrpc.org/specification#error_object), or in the associated JSON-RPC request standard being followed, then the error reason **MUST** align with the established meaning of that code and the `message` **MUST** match the provided `message`

The `data` field **MAY** contain any data that is relevant to the error or would help the user understand or troubleshoot the error.

## Rationale
While this standard is perhaps not the greatest mechanism for communicating between an application and a blockchain, it is closely aligned with established practices within the community so migration from existing systems to this one should be relatively easy.  Most communication is currently done via JSON-RPC, so aligning with the JSON-RPC standard was desired to enable quick integration with existing systems.

## Security Considerations
The relationship between Ethereum Provider and client is a trusted one, where it is assumed that the user implicitly trusts the Ethereum Provider which is how it managed to get injected into the client, or the client expressly pulled in a connection to it.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 04 Jun 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2696</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2696</guid>
      </item>
    
      <item>
        <title>JavaScript Provider Event Emitter</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2701</comments>
        
        <description>## Simple Summary
A standard mechanism for JavaScript Ethereum Providers to notify clients about chain state changes when both are able to interface with each other via a shared JavaScript object.

## Abstract
This standard provides the description of an object that is made available to JavaScript applications which they can use to receive notifications from an Ethereum Provider.  This standard only describes the notification mechanism, it does not specify the payloads that are valid nor does it specify how the client or the provider will discover or agree on payload content.

How/where this Ethereum Provider object is exposed is left to future standards.

## Motivation
When working within a JavaScript runtime (such as NodeJS, Electron, Browser, etc.) it may be possible for the runtime or a runtime plugin to inject objects into the runtime.  Someone authoring a runtime or a runtime plugin may choose to expose an Ethereum Provider to any JavaScript apps or scripts running within that runtime in order to provide notifications of blockchain state changes.  In order to achieve maximum compatibility between the provider and the client, a standard is necessary for what the shape of that object is.

## Specification
### RFC-2119
The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;,  &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC-2119](https://www.ietf.org/rfc/rfc2119.txt).

### Interface
```ts
interface EthereumProvider {
	on(eventName: string, listener: (...params: unknown[]) =&gt; void): void
	removeListener(eventName: string, listener: (...params: unknown[]) =&gt; void): void
}
```
The specific events that can be listened to and the shape of their listener callback functions is left to be defined in separate standards.

If `on` is called with an `eventName` that the provider is familiar with then the provider **MUST** call the provided `listener` when the named event occurs.  If the same `listener` is added multiple times to the same event via `on`, the provider **MAY** choose to either callback the listener one time or one time per call to `on`.

If `removeListener` is called with an `eventName` and `listener` that was previously added via `on` then the provider **MUST** decrease the number of times it calls the `listener` per event by one.

## Rationale
This EIP is mostly a retrospective EIP meaning it codifies an already existing specification so there isn&apos;t a lot of room for improving things such as by using a discriminated union object for listener parameters or having a tighter definition of `on`.  The specific events are intentionally left out of this specification as that set will be an ever-evolving collection and having the first few listed here doesn&apos;t add value to this specification (especially if, over time, the first few end up deprecated or unused).

## Security Considerations
The relationship between Ethereum Provider and client is a trusted one, where it is assumed that the user implicitly trusts the Ethereum Provider which is how it managed to get injected into the client, or the client expressly pulled in a connection to it.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 05 Jun 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2700</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2700</guid>
      </item>
    
      <item>
        <title>Sponsored, expiring and batch transactions.</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2711-separate-gas-payer-from-msg-sender/4353</comments>
        
        <description>## Simple Summary
Creates a new transaction type that supports sponsored transactions (separate gas payer from sender), batch transactions (multiple transactions executed in sequence), and expiring transactions (transactions which are not valid after a certain timestamp).

## Abstract
An EIP-2718 transaction with the type number `2` is a new type of transaction that includes support for:
1. **Sponsored Transactions**: an optional additional signature from which the account that will pay for gas (`GAS_PAYER`) can be recovered
2. **Batch Transactions**: multiple transactions from the same sender that will be executed in sequence
3. **Expiring Transactions**: an optional `validUntil` field that makes the transaction invalid after a certain point in time

## Motivation
### Sponsored Transactions
With the advent of tokens and especially stable coins, it has become common for users to not hold ETH in an account while they may have other assets of value in that account.  Some users don&apos;t want to be exposed to the perceived volatility of ETH and instead would prefer to transact using other assets.  Unfortunately, since gas **MUST** be paid for with ETH, this prevents the user from transacting with their assets without first acquiring some ETH using some other means, and then using that ETH to pay fees.

This EIP proposes a mechanism by which we can allow people to transact without ever having to own any ETH by allowing someone else to cover gas costs.  The arrangements that enable the covering of gas costs is out of scope for this EIP but it could be an extra-protocol monthly subscription, payment could occur as part of the transaction being submitted, the recipient may be willing to cover gas costs, or it could be a free service offered as a value-add by a company that you are working with.

While it is possible to implement these sort of mechanisms at the individual contract layer, such solutions require integration by just about every contract and those solutions also end up depending on gas costs being stable with time in order to appropriately bake them into contracts without putting either party at risk of malicious participants in the system.  For this reason, it is believed that separating out `GAS_PAYER` from `msg.sender` at the protocol layer is valuable.

### Batch Transactions
Often times an EOA may want to execute a series of transactions with a strong guarantee that they happen in order with nothing occurring between them.  For example, one may want to send some tokens to a contract and then follow that up with another transaction that makes a contract call on the destination address that causes those tokens to be registered to them.  By supporting transaction batching at layer 1, we can ensure that the user can get strong guarantees at signing time of cross-transaction atomicity.

### Expiring Transactions
* If any form of dust-account clearing is introduced, e.g. (https://github.com/ethereum/EIPs/issues/168), it will be necessary to introduce a replay protection, such as https://github.com/ethereum/EIPs/issues/169 . Having temporal replay protection removes the need to change nonce-behaviour in the state, since transactions would not be replayable at a later date than explicitly set by the user.
* In many cases, such as during ICOs, a lot of people want their transactions to either become included soon (within a couple of hours) or not at all. Currently, transactions are queued and may not execute for several days, at a cost for both the user (who ends up paying gas for a failing purchase) and the network, dealing with the large transaction queues.
* Node implementations have no commonly agreed metric for which transactions to keep, discard or propagate. Having a TTL on transactions would make it easier to remove stale transactions from the system.

## Specification
### Definitions
**`TransactionType`** 2.  See [EIP-2718](/EIPs/EIPS/eip-2718)

**`TransactionSubtype`** is either 1, 2, 3, or 4.

**`ChainId`** The transaction is valid if this value is `0` or it is included in a block on a chain whose ID is equal to this value.

**`ValidUntil`** The transaction is valid if this value is `0` or it is included in a block whose `timestamp` is less than or equal to this value.

**`YParity`** The parity (0 for even, 1 for odd) of the y-value of a secp256k1 signature.

**`ChildTransaction`** A nested transaction consisting of `[to, value, data]`.

**`SenderPayload`** Defined based on the `TransactionSubtype` as follows:
1. `[1, ChildTransaction[], nonce, ChainId, ValidUntil, gasLimit, gasPrice]`
2. `[2, ChildTransaction[], nonce, ChainId, ValidUntil, gasLimit, gasPrice]`
3. `[3, ChildTransaction[], nonce, ChainId, ValidUntil, gasLimit]`
4. `[4, ChildTransaction[], nonce, ChainId, ValidUntil]`

**`SenderSignature`** `[YParity, r, s]` of `secp256k1(keccak256(rlp([TransactionType, SenderPayload])))`

**`GasPayerPayload`** Defined based on the `TransactionSubtype` as follows:
1. `[]`
2. `[]`
3. `[gasPrice]`
4. `[gasLimit, gasPrice]`

**`GasPayerSignature`** is `[]` for `TransactionSubType` `1` or `[YParity, r, s]` of `secp256k1(keccak256(rlp([SenderPayload, SenderSignature, GasPayerPayload])))` for others.

### New Transaction Type

As of `FORK_BLOCK_NUMBER` an [EIP-2718](/EIPs/EIPS/eip-2718) transaction with a `TransactionType` of `2` will have its `Payload` interpreted as an RLP encoded tuple of:
```
[...SenderPayload, ...SenderSignature, ...GasPayerPayload, ...GasPayerSignature]
```

The address recovered from `SenderSignature` is the address...
1. ...returned by the `CALLER` opcode (0x33, aka `msg.sender`) during the first call frame of the transaction
2. ...returned by the `ORIGIN` opcode (0x32, aka `tx.origin`)
3. ...whose `nonce` is used
4. ...whose ETH balance is deducted if any value is attached to the transaction
5. ...whose ETH balance is deducted to pay for gas if `GasPayerSignature` is not present

If `GasPayerSignature` is present, then the address recovered from it is the address...
1. ...whose ETH balance is deducted to pay for gas

The base gas cost of transactions of this type will be `TRANSACTION_TYPE_2_BASE_GAS_PRICE` + `TRANSACTION_TYPE_2_CHILD_GAS_PRICE` * `n`, rather than the cost associated with transactions of type `0` and legacy transactions.

### New Transaction Receipt

As of `FORK_BLOCK_NUMBER` an [EIP-2718](/EIPs/EIPS/eip-2718) transaction receipt with a `TransactionType` of `2` will have its `Payload` interpreted as a `rlp([status, cumulativeGasUsed, logsBloom, logs][])` where each item of the array corresponds to the child-transaction at matching offset in the transaction type 2 `Payload`.

## Rationale
### One Monolithic EIP
This EIP could be split up into multiple EIPs, one for each of the subtypes and one for the meta-type.  Alternatively, each of the subtypes could be a unique TransactionType.  The reason we chose to go with a single EIP with subtypes is because these 4 transactions all have a *lot* in common and each separate EIP would be almost identical to the previous.  We felt that in this case, splitting into multiple EIPs wasn&apos;t worth the duplication of EIP content.
### ChainID not encoded with `v`
While we could save one byte in the common case by bundling the y-parity bit of the signature with the Chain ID like in EIP-155, this adds complexity to signing tools that the authors deem not worth it given the size of the transaction overall.
### Optionality of ChainID
Sometimes it is useful to have a transaction that *can* be replayed on multiple chains.  An example of this is when you construct a vanity signature for a transaction and have the `from` be whatever address that signature recovers to.  With the ability to have someone else be a gas payer (setting both the gas limit and the gas price), one can have transactions that deploy contracts which live at the same address on every chain.  While this can be accomplished with CREATE2 using legacy transactions, we have the opportunity here to simplify the process and enable potentially other future uses of deterministic transactions by making ChainID optional.
### Optionality of ValidUntil
A user can set `ValidUntil` to a very large number which effectively makes it non-expiring.  By making `ValidUntil` optional, we can save some bytes on the wire by allowing such transactions to simply have a `0` (1 byte in RLP) value for this field.
### `SENDER` sets `gasLimit` and `gasPrice`
This type of transaction is useful when the transaction may execute differently depending on what these values are set to.  By having the `SENDER` set both, we ensure that the `SENDER` has full control over the transaction details.
### `SENDER` sets `gasLimit`, `GAS_PAYER` sets `gasPrice`
This type of transaction is useful when the transaction may execute differently depending on how much gas it is allowed (e.g., number of loops) but where the `SENDER` would like to give the `GAS_PAYER` the ability to price the transaction to maximize chances of inclusion.
### `GAS_PAYER` sets `gasLimit` and `gasPrice`
This type of transaction allows the `SENDER` to define what they want to do, and leaves all worry about gas to the `GAS_PAYER`.  This is useful for transactions where the sender doesn&apos;t care how much gas is used or the price that is paid and also either trusts the `GAS_PAYER` to be non-malicious or doesn&apos;t care if the `SENDER`&apos;s nonce is increased.  Such situations are useful when you have extra-protocol trust between the `SENDER` and `GAS_PAYER` and you want to separate concerns (what to do vs how to get included) for security or complexity reasons.
### Nonces
The inner transaction needs a nonce to protect themselves from replay attacks.  Since the inner transaction has a nonce, we get replay protection on the outer transaction as well, so it is not critical for security to have multiple parties provide a nonce.

We could have the `GAS_PAYER` provide a second nonce, but this would increase the payload size and require `GAS_PAYER` to do replace-by-fee (noisy for gossip) if they want to slip in a new (different inner) transaction with a higher gas price.  It would also create the possibility of a deadlock if the `SENDER` nonces aren&apos;t ordered the same as the `GAS_PAYER` nonces, and if the `SENDER` nonce isn&apos;t the lowest valid nonce for the `SENDER` then the `GAS_PAYER` can&apos;t sign and submit yet.  Finally, client complexity increases slightly if a transaction has two nonces because you have to protect yourself from deadlocks and do more work to determine validity.
### ValidUntil
For the dust-account clearing usecase, 
- This change is much less invasive in the consensus engine. 
  - No need to maintain a consensus-field of &apos;highest-known-nonce&apos; or cap the number of transactions from a sender in a block. 
  - Only touches the transaction validation part of the consensus engine
  - Other schemas which uses the `nonce` can have unintended side-effects, 
    - such as inability to create contracts at certain addresses.
    - more difficult to integrate with offline signers, since more elaborate nonce-schemes requires state access to determine. 
    - More intricate schemes like `highest-nonce` are a lot more difficult, since highest-known-nonce will be a consensus-struct that is incremented and possibly reverted during transaction execution, requiring one more journalled field.  

### ValidUntil as timestamp instead of block number
- The unix time is generally available in most settings, even on a computer which is offline. This means that even a setup where blockchain information is unavailable, the party signing a transaction can generate a transaction with the desired properties. 
- The correlation between time and block number is not fixed; even though a 13s blocktime is &apos;desired&apos;, this varies due to both network hashrate and difficulty bomb progression. 
- The block number is even more unreliable as a timestamp for testnets and private networks.
- unix time is more user-friendly, a user can more easily decide on reasonable end-date for a transaction, rather than a suitable number of valid blocks.

## Backwards Compatibility
No known issues.

## Test Cases

## Implementation

## Security Considerations

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 11 Jun 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2711</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2711</guid>
      </item>
    
      <item>
        <title>Typed Transaction Envelope</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2718-typed-transaction-envelope/4355</comments>
        
        <description>## Abstract
`TransactionType || TransactionPayload` is a valid transaction and `TransactionType || ReceiptPayload` is a valid transaction receipt where `TransactionType` identifies the format of the transaction and `*Payload` is the transaction/receipt contents, which are defined in future EIPs.

## Motivation
In the past, when we have wanted to add new transaction types we have had to ensure they were backward compatible with all other transactions, meaning that you could differentiate them based only on the encoded payload, and it was not possible to have a transaction that matched both types.
This was seen in [EIP-155](/EIPs/EIPS/eip-155) where the new value was bit-packed into one of the encoded fields.
There are multiple proposals in discussion that define new transaction types such as one that allows EOA accounts to execute code directly within their context, one that enables someone besides `msg.sender` to pay for gas, and proposals related to layer 1 multi-sig transactions.
These all need to be defined in a way that is mutually compatible, which quickly becomes burdensome to EIP authors and to clients who now have to follow complex rules for differentiating transaction type.

By introducing an envelope transaction type, we only need to ensure backward compatibility with existing transactions and from then on we just need to solve the much simpler problem of ensuring there is no numbering conflict between `TransactionType`s.

## Specification
### Definitions
* `||` is the byte/byte-array concatenation operator.

### Transactions
As of `FORK_BLOCK_NUMBER`, the transaction root in the block header **MUST** be the root hash of `patriciaTrie(rlp(Index) =&gt; Transaction)` where:
* `Index` is the index in the block of this transaction
* `Transaction` is either `TransactionType || TransactionPayload` or `LegacyTransaction`
* `TransactionType` is a positive unsigned 8-bit number between `0` and `0x7f` that represents the type of the transaction
* `TransactionPayload` is an opaque byte array whose interpretation is dependent on the `TransactionType` and defined in future EIPs
* `LegacyTransaction` is `rlp([nonce, gasPrice, gasLimit, to, value, data, v, r, s])`

All signatures for future transaction types **SHOULD** include the `TransactionType` as the first byte of the signed data.
This makes it so we do not have to worry about signatures for one transaction type being used as signatures for a different transaction type.

### Receipts
As of `FORK_BLOCK_NUMBER`, the receipt root in the block header **MUST** be the root hash of `patriciaTrie(rlp(Index) =&gt; Receipt)` where:
* `Index` is the index in the block of the transaction this receipt is for
* `Receipt` is either `TransactionType || ReceiptPayload` or `LegacyReceipt`
* `TransactionType` is a positive unsigned 8-bit number between `0` and `0x7f` that represents the type of the transaction
* `ReceiptPayload` is an opaque byte array whose interpretation is dependent on the `TransactionType` and defined in future EIPs
* `LegacyReceipt` is `rlp([status, cumulativeGasUsed, logsBloom, logs])`

The `TransactionType` of the receipt **MUST** match the `TransactionType` of the transaction with a matching `Index`.

## Rationale
### TransactionType only goes up to 0x7f
For the forseable future, 0x7f is plenty and it leaves open a number of options for extending the range such as using the high bit as a continuation bit.
This also prevents us from colliding with legacy transaction types, which always start with a byte `&gt;= 0xc0`.
### **SHOULD** instead of **MUST** for the TransactionType being first byte of signed data
While it is strongly recommended that all future transactions sign the first byte to ensure that there is no problem with signature reuse, the authors acknowledge that this may not always make sense or be possible.
One example where this isn&apos;t possible is wrapped legacy transactions that are signature compatible with the legacy signing scheme.
Another potential situation is one where transactions don&apos;t have a signature in the traditional sense and instead have some other mechanism for determining validity.
### TransactionType selection algorithm
There was discussion about defining the `TransactionType` identifier assignment/selection algorithm in this standard.
While it would be nice to have a standardized mechanism for assignment, at the time of writing of this standard there is not a strong need for it so it was deemed out of scope.
A future EIP may introduce a standard for TransactionType identifier assignment if it is deemed necessary.
### Opaque byte array rather than an RLP array
By having the second byte on be opaque bytes, rather than an RLP (or other encoding) list, we can support different encoding formats for the transaction payload in the future such as SSZ, LEB128, or a fixed width format.
### ORIGIN and CALLER
There was discussion about having ORIGIN and CALLER opcodes become dependent on the transaction type, so that each transaction type could define what those opcodes returned.
However, there is a desire to make transaction type opaque to the contracts to discourage contracts treating different types of transactions differently.
There also were concerns over backward compatibility with existing contracts which make assumptions about ORIGIN and CALLER opcodes.
Going forward, we will assume that all transaction types will have an address that reasonably represents a `CALLER` of the first EVM frame and `ORIGIN` will be the same address in all cases.
If a transaction type needs to supply additional information to contracts, they will need a new opcode.

## Backwards Compatibility
Clients can differentiate between the legacy transactions and typed transactions by looking at the first byte.
If it starts with a value in the range `[0, 0x7f]` then it is a new transaction type, if it starts with a value in the range `[0xc0, 0xfe]` then it is a legacy transaction type.
`0xff` is not realistic for an RLP encoded transaction, so it is reserved for future use as an extension sentinel value.

## Security Considerations
When designing a new 2718 transaction type, it is **STRONGLY** recommended to include the transaction type as the first byte of the signed payload.  If you fail to do this, it is possible that your transaction may be signature compatible with transactions of another type which can introduce security vulnerabilities for users.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 13 Jun 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2718</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2718</guid>
      </item>
    
      <item>
        <title>Transaction Package</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-transaction-package/4365</comments>
        
        <description>## Simple Summary
Creates a new transaction type which executes a package of one or more
transactions, while passing status information to subsequent transactions.

## Abstract
Introduce a new transaction type which includes a list of transactions that
must be executed serially by clients. Execution information (e.g. success,
gas_used, etc.) will be propagated forward to the next transaction.

## Motivation
Onboarding new users to Ethereum has been notoriously difficult due to the need
for new users to acquire enough ether to pay for their transactions. This
hurdle has seen a significant allocation of resources over the years to solve.
Today, that solution is meta-transactions. This is, unfortunately, a brittle
solution that requires signatures to be recovered within a smart contract to
authenticate the message. This EIP aims to provide a flexible framework for
relayers to &quot;sponsor&quot; many transactions at once, trustlessly.

Meta-transactions often use relay contracts to maintain nonces and allow users
to pay for gas using alternative assets. They have historically been designed
to catch reversions in their inner transactions by only passing a portion of
the available gas to the subcall. This allows them to be certain the outer call
will have enough gas to complete any required account, like processing a gas
payment. This type of subcall has been considered bad practice for a long time,
but in the case of where you don&apos;t trust the subcalls, it is the only available
solution.

Transaction packages are an alternative that allow multiple transactions to be
bundled into one package and executed atomically, similarly to how relay
contracts operate. Transactions are able to pass their result to subsequent
transactions. This allows for conditional workflows based on the outcome of
previous transactions. Although this functionality is already possible as
described above, workflows using transaction packages are more robust, because
they are protected from future changes to the gas schedule.

An important byproduct of this EIP is that it also facilitates bundling
transactions for single users.

## Specification
Introduce a new [EIP-2718](/EIPs/EIPS/eip-2718) transaction type where `id = 2`.

#### Structure
```
struct TransactionPackage {
    chain_id: u256,
    children: [ChildPackage],
    nonce: u64,
    gas_price: u256,
    v: u256,
    r: u256,
    s: u256
}
```

##### Hash
`keccak256(rlp([2, chain_id, children, nonce, gas_price, v, r, s])`

##### Signature Hash
`keccak256(rlp([2, chain_id, children, nonce, gas_price])`

##### Receipt
Each `ChildTransaction` transaction will generate a `ChildReceipt` after execution. Each
of these receipts will be aggregated into a `Receipt`.

```
type Receipt = [ChildReceipt]
```

```
struct ChildReceipt {
    status: u256,
    cumulative_gas_used: u256,
    logs_bloom: [u8; 256],
    logs: [u8]
}
```

#### Child Transaction
Let `ChildPackage` be interpreted as follows.

```
struct ChildPackage {
    type: u8,
    nonce: u64,
    transactions: [ChildTransaction],
    max_gas_price: u256,
    v: u256,
    r: u256,
    s: u256
}
```

```
struct ChildTransaction {
    flags: u8,
    to: Address,
    value: u256,
    data: [u8],
    extra: [u8],
    gas_limit: u256
}
```

##### Types
The `type` field is used to denote whether the `Child` signer wishes to
delegate the `max_gas_price` and `gas_limit` choice to the `TransactionPackage`
signer.

| type  | signature hash  |
|---|---|
| `0x00` | `keccak256(rlp([0, nonce, transactions, max_gas_price])` |
| `0x01` | `keccak256(rlp([1, nonce, transactions_without_gas_limit])` |

### Validity

A `TransactionPackage` can be deemed valid or invalid as follows.

```rust    
fn is_valid(config: &amp;Config, state: &amp;State, tx: TransactionPackage) bool {
    if (
        config.chain_id() != tx.chain_id ||
        tx.children.len() == 0 ||
        state.nonce(tx.from()) + 1 != tx.nonce
    ) {
        return false;
    }

    let cum_limit = tx.children.map(|x| x.gas_limit).sum();
    if state.balance(tx.from()) &lt; cum_limit * tx.gas_price + intrinsic_gas(tx) {
        return false;
    }
    
    for child in tx.children {
        if (
            child.nonce != state.nonce(child.from()) + 1 ||
            child.value &gt; state.balance(child.from()) ||
            child.max_gas_price &lt; tx.gas_price
        ) {
            return false;
        }
        
        for tx in child.txs {
            if (
                tx.flags != 0 ||
                tx.extra.len() != 0 ||
                tx.gas_limit &lt; intrinsic_gas(tx)
            ) {
                return false;
            }
        }
    }
    
    true
}
```

### Results

Subsequent `ChildTransaction`s will be able to receive the result of the
previous `ChildTransaction` via `RETURNDATACOPY (0x3E)` in first frame of
execution, before making any subcalls. Each element, except the last, will be
`0`-padded left to 32 bytes.

```
struct Result {
    // Status of the previous transaction
    success: bool,
    
    // Total gas used by the previous transaction
    gas_used: u256,
    
    // Cumulative gas used by previous transactions
    cum_gas_used: u256,
    
    // The size of the return value
    return_size: u256,
    
    // The return value of the previous transaction
    return_value: [u8]
}
```

### Intrinsic Cost
Let the intrinsic cost of the transaction package be defined as follows:

```
fn intrinsic_gas(tx: TransactionPackage) u256 {
    let data_gas = tx.children.map(|c| c.txs.map(|t| data_cost(&amp;c.data)).sum()).sum();
    17000 + 8000 * tx.children.len() + data_gas
}
```

### Execution
Transaction packages should be executed as follows:
1. Deduct the cumulative cost from the outer signer&apos;s balance.
2. Load the first child package, and execute the first child transaction.
3. Record all state changes, logs, the receipt, and refund any unused gas.
4. If there are no more child transactions, goto `8`.
5. Compute `Result` for the previously executed transaction.
6. Prepare `Result` to be available via return opcodes in the next
   transaction&apos;s first frame.
7. Execute the next transaction, then goto `3`.
8. Load the next child package, then goto `7`.

## Rationale

### Each `Child` has its own signature
For simplicity, the author has chosen to require each child package to specify
its own signature, even if the signer is the same as the package signer. This
choice is made to allow for maximum flexibility, with minimal client changes.
This transaction can still be used by a single user at the cost of only one
additional signature recovery.

### `ChildPackage` specifies `max_gas_price` instead of `gas_price`
Allowing child packages to specify a range of acceptable gas prices is
strictly more versatile than a static price. It gives relayers more flexibility
in terms of building transaction bundles, and it makes it possible for relayers
to try and achieve the best price for the transaction sender. With a fixed
price, the relayer may require the user to sign multiple different
transactions, with varying prices. This can be avoided by specifying a max
price, and communicating out-of-band how the urgency of the transaction (e.g.
the relayer should package it with the max price immediately vs. slowly
increasing the gas price).
A future transaction type can be specified with only a single
signature, if such an optimization is desired.

### `ChildPackage` is also typed
The type element serves a modest role in the transaction type, denoting whether
the transaction signer wishes to delegate control of the gas price and gas
limit to the outer signer. This is a useful UX improvement when interacting
with a trusted relayer, as once the user decides to make a transaction the
relayer can ensure it is included on chain by choosing the best gas price and
limit.

### The `flags` and `extra` fields aren&apos;t used
These fields are included to better support future changes to the transaction
type. This would likely be used in conjunction with the `flags` and `type`
fields. A benefit of explicitly defining them is that specialized serialization
of RLP can be avoided, simplifying clients and downstream infrastructure. The
author believe the cost of 2 bytes per transaction is acceptable for smoother
integration of future features.

## Backwards Compatibility
Contracts which rely on `ORIGIN (0x32) == CALLER (0x33) &amp;&amp; RETURNDATASIZE
(0x3D) == 0x00` will now always fail in transaction packages, unless they are
the first executed transaction. It’s unknown if any contracts conduct this
check.

## Test Cases
TBD

## Implementation
TBD

## Security Considerations
### Managing packages efficiently in the mempool
The introduction of a new transaction type brings along new concerns regarding
the mempool. Done naively, it could turn into a DDoS vector for clients. This
EIP has been written to reduce as much validation complexity as possible.

An existing invariant in the mempool that is desirable for new transactions to
maintain, is that transactions can be validated in constant time. This is also
possible for packaged transactions. There is an inherent 10Mb limit for RLPx
frames, so that would be the upper bound on transactions that could be included
in a package. On the other hand, clients can also just configure their own
bound locally (e.g. packages must be less than 1Mb). Validity can then be
determined by using the function above.

Once a package has been validated, it must continuously be monitored for nonce
invalidations within its package. One potential way to achieve this efficiently
is to modify the mempool to operate on thin pointers to the underlying
transaction. This will allow packages to ingest as many &quot;single&quot; transactions,
simplifying the facilities for monitoring changes. These &quot;parts&quot; of the package
can maintain a pointer to a structure with pointers to all the parts of the
package. This way, as soon as one part becomes invalid, it can request the
parent to invalidate all outstanding parts of the package.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 16 Jun 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2733</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2733</guid>
      </item>
    
      <item>
        <title>Rules Engine Standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2746-rules-engine-interface/4435</comments>
        
        <description>## Simple Summary
An interface for using a smart contract as a rules engine.  A single deployed contract can register a data domain, create sets of rules that perform actions on that domain, and then invoke a set as an atomic transaction. 

## Abstract
This standard proposes an interface that will allow the creation of hierarchal sets of rules (i.e., RuleTrees) that can be invoked to evaluate and manipulate a registered data domain.  At the time of this draft, all intentions to insert additional functionality onto the blockchain requires the coding and creation of a newly deployed contract.  However, this standard will allow users to deploy a contract just once, one which will then allow them to create (and invoke) pipelines of commands within that contract.

## Motivation
At the time of this draft, all development for Ethereum requires writing the code that forms smart contracts and then deploying those contracts to Ethereum.  In order to create a proper contract, many considerations must be taken into account when designing and implementing the code, especially in terms of efficiency (i.e., gas cost) and security.  Even the simplest contracts require a certain amount of vigilance and examination, before and after deployment. These requirements pertain to all cases, even for simple cases of examining a value and/or altering it.

These technical challenges might form an obstacle for many others who might wish to create software around Ethereum.  Less technical companies and users might also want to configure and deploy simple functionality onto the chain, without knowing the relevant languages or details necessary.  By having the data domain and the predefined actions (i.e., types of rules) implemented along with this interface, a deployed instance of such a rules engine contract can provide efficient and safe functionality to no-code or little-code clients, allowing more users of various technical proficiency to interact with the Ethereum ecosystem.

## Specification
For the clarification of terminology, an Attribute is a registered data point within the data domain, representing data that exists either in the rules engine contract or elsewhere.  A Rule is an predefined action that occurs upon a single data point (i.e., Attribute) in the predefined data domain.  For example, a Rule could check whether the Attribute &apos;TokenAmt&apos; has a value less than the RHL (i.e., right-hand value) of 10.   A RuleSet is a collection of Rules, where their collection invocation creates a boolean result that determines the navigational flow of execution between RuleSets.  A RuleTree is a collection of RuleSets that are organized within a hierarchy, where RuleSets can contain other RuleSets.

```solidity
pragma solidity ^0.6.0;

/**
    @title ERC-2746 Rules Engine Standard
    @dev See https://eips.ethereum.org/EIPS/eip-2746
 */
 interface ERCRulesEngine {

    /**
        @dev Should emit when a RuleTree is invoked.
        The `ruler` is the ID and owner of the RuleTree being invoked.  It is also likely msg.sender.
    */
    event CallRuleTree(
        address indexed ruler
    );

    /**
        @dev Should emit when a RuleSet is invoked.
        The `ruler` is the ID and owner of the RuleTree in which the RuleSet is stored.  It is also likely msg.sender.
        The &apos;ruleSetId&apos; is the ID of the RuleSet being invoked.
    */
    event CallRuleSet(
        address indexed ruler,
        bytes32 indexed tmpRuleSetId
    );

    /**
        @dev Should emit when a Rule is invoked.
        The `ruler` is the ID and owner of the RuleTree in which the RuleSet is stored.  It is also likely msg.sender.
        The &apos;ruleSetId&apos; is the ID of the RuleSet being invoked.
        The &apos;ruleId&apos; is the ID of the Rule being invoked.
        The &apos;ruleType&apos; is the type of the rule being invoked.        
    */
    event CallRule(
        address indexed ruler,
        bytes32 indexed ruleSetId,
        bytes32 indexed ruleId,
        uint ruleType
    );

    /**
        @dev Should emit when a RuleSet fails.
        The `ruler` is the ID and owner of the RuleTree in which the RuleSet is stored.  It is also likely msg.sender.
        The &apos;ruleSetId&apos; is the ID of the RuleSet being invoked.
        The &apos;severeFailure&apos; is the indicator of whether or not the RuleSet is a leaf with a &apos;severe&apos; error flag.
    */
    event RuleSetError (
        address indexed ruler,
        bytes32 indexed ruleSetId,
        bool severeFailure
    );	

    /**
        @notice Adds a new Attribute to the data domain.
        @dev Caller should be the deployer/owner of the rules engine contract.  An Attribute value can be an optional alternative if it&apos;s not a string or numeric.
        @param _attrName    Name/ID of the Attribute
        @param _maxLen      Maximum length of the Attribute (if it is a string)
        @param _maxNumVal   Maximum numeric value of the Attribute (if it is numeric)
        @param _defaultVal  The default value for the Attribute (if one is not found from the source)
        @param _isString    Indicator of whether or not the Attribute is a string
        @param _isNumeric   Indicator of whether or not the Attribute is numeric
    */    
    function addAttribute(bytes32 _attrName, uint _maxLen, uint _maxNumVal, string calldata _defaultVal, bool _isString, bool _isNumeric) external;

    /**
        @notice Adds a new RuleTree.
        @param _owner          Owner/ID of the RuleTree
        @param _ruleTreeName   Name of the RuleTree
        @param _desc           Verbose description of the RuleTree&apos;s purpose
    */
    function addRuleTree(address _owner, bytes32 _ruleTreeName, string calldata _desc) external;

    /**
        @notice Adds a new RuleSet onto the hierarchy of a RuleTree.
        @dev RuleSets can have child RuleSets, but they will only be called if the parent&apos;s Rules execute to create boolean &apos;true&apos;.
        @param _owner           Owner/ID of the RuleTree
        @param _ruleSetName     ID/Name of the RuleSet
        @param _desc            Verbose description of the RuleSet
        @param _parentRSName    ID/Name of the parent RuleSet, to which this will be added as a child
        @param _severalFailFlag Indicator of whether or not the RuleSet&apos;s execution (as failure) will result in a failure of the RuleTree.  (This flag only applies to leaves in the RuleTree.)
        @param _useAndOp        Indicator of whether or not the rules in the RuleSet will execute with &apos;AND&apos; between them.  (Otherwise, it will be &apos;OR&apos;.)
        @param _failQuickFlag   Indicator of whether or not the RuleSet&apos;s execution (as failure) should immediately stop the RuleTree.
    */    
    function addRuleSet(address _owner, bytes32 _ruleSetName, string calldata _desc, bytes32 _parentRSName, bool _severalFailFlag, bool _useAndOp, bool _failQuickFlag) external;

    /**
        @notice Adds a new Rule into a RuleSet.
        @dev Rule types can be implemented as any type of action (greater than, less than, etc.)
        @param _owner           Owner/ID of the RuleTree
        @param _ruleSetName     ID/Name of the RuleSet to which the Rule will be added
        @param _ruleName        ID/Name of the Rule being added
        @param _attrName        ID/Name of the Attribute upon which the Rule is invoked
        @param _ruleType        ID of the type of Rule
        @param _rightHandValue  The registered value to be used by the Rule when performing its action upon the Attribute
        @param _notFlag         Indicator of whether or not the NOT operator should be performed on this Rule.
    */    
    function addRule(address _owner, bytes32 _ruleSetName, bytes32 _ruleName, bytes32 _attrName, uint _ruleType, string calldata _rightHandValue, bool _notFlag) external;

    /**
        @notice Executes a RuleTree.
        @param _owner           Owner/ID of the RuleTree
    */
    function executeRuleTree(address _owner) external returns (bool);
    
    /**
        @notice Retrieves the properties of a Rule.
        @param _owner           Owner/ID of the RuleTree
        @param _ruleSetName     ID/Name of the RuleSet where the Rule resides
        @param _ruleIdx         Index of the rule in the RuleSet&apos;s listing 
        @return bytes32         ID/Name of Rule
        @return uint            Type of Rule
        @return bytes32         Target Attribute of Rule
        @return string          Value mentioned in Rule
        @return bool            Flag for NOT operator in Rule
        @return bytes32[]       Values that should be provided in delegated call (if Rule is custom operator)
    */
    function getRuleProps(address _owner, bytes32 _ruleSetName, uint _ruleIdx) external returns (bytes32, uint, bytes32, string memory, bool, bytes32[] memory);

    /**
        @notice Retrieves the properties of a RuleSet
        @param _owner        Owner/ID of the RuleTree
        @param _ruleSetName  ID/Name of the RuleSet
        @return string       Verbose description of the RuleSet
        @return bool         Flag that indicates whether this RuleSet&apos;s failure (if a leaf) will cause the RuleTree to fail
        @return bool         Flag that indicates whether this RuleSet uses the AND operator when executing rules collectively
        @return uint         Indicates the number of rules hosted by this RuleSet
        @return bytes32[]    The list of RuleSets that are children of this RuleSet
    */
    function getRuleSetProps(address _owner, bytes32 _ruleSetName) external returns (string memory, bool, bool, uint, uint, bytes32[] memory);

    /**
        @notice Retrieves the properties of a RuleSet
        @param _owner        Owner/ID of the RuleTree
        @return bytes32      Name of the RuleTree
        @return string       Verbose description of the RuleTree
        @return bytes32      ID/Name of the RuleSet that serves as the root node for the RuleTree
    */
    function getRuleTreeProps(address _owner) external returns (bytes32, string memory, bytes32);
    
    /**
        @notice Removes a RuleTree.
        @param _owner           Owner/ID of the RuleTree
    */
    function removeRuleTree(address _owner) external returns (bool);    
}
```

### Considerations

An argument could be made for interface functions that allow a RuleTree&apos;s owner to include others users as executors of the RuleTree.

Another argument could be made for interface functions that allow an administrator to configure the origin point of an Attribute, such as whether the Attribute&apos;s value comes from a data structure (internal to the rules engine contract) or from calling a contract method (like an implementation of the [Diamond Standard](https://github.com/ethereum/EIPs/issues/2535)).

Yet another argument could be made for interface functions that allow an administrator to extend the functionality catalog provided by the rules engine, by allowing other contracts&apos; methods to be added as a rule operation.

Also, an argument could be made for functions that calculate and report the range of potential cost for invoking a RuleTree.  Unlike the normal execution of a contract method, the Ethereum transaction costs of invoking a RuleTree are more dynamic, depending on its depth/breadth and the navigational flow during invocation.  Since the general cost of a RuleTree is unknown until the time of invocation, these functions could report the minimal amount of gas for a transaction (i.e., none of the Rules in a RuleTree are invoked) and the maximum amount for a transaction (i.e., all Rules in a RuleTree are invoked).

### Example

A company wishes to deploy a contract with data points and functionality that are predefined and/or under the control of an administrator, and it aims to build a no-code client that will allow less-technical users to define actions within the rules engine contract.  In this example, the company wants one of its users to write the rules in a proprietary markup language, in order for the calculation of a VAT to be determined.  For the sake of transparency, [these rules](https://ipfs.infura.io/ipfs/QmPrZ9959c7SzzqdLkVgX28xM7ZrqLeT3ydvRAHCaL1Hsn) are published onto IPFS, so that they are accessible to auditors and possibly government officials.  The no-code client will then know how to parse the rules from the markup and communicate with the rules engine contract, establishing the RuleTree to be invoked later by the company&apos;s user(s) or off-chain programs.

In order to calculate the value of the VAT, these provided rules invoke simple mathematical operations that can perform the calculation.  However, the implementation of the rules engine contract could possess other functionality called by rules, ones that could execute more complicated logic or call the methods of other contracts.

## Rationale

### Attributes

The data points are abstracted in order to let the implementation provide the mechanism for retrieving/populating the data.  Data can be held by an internal data structure, another contract&apos;s method, or any number of other options.

### Events

The events specified will help the caller of the RuleTree after execution, so that they may ascertain the navigational flow of RuleSet execution within the RuleTree and so that they may understand which RuleSets failed.

### Right-Hand Value

In the function addRule(), the data type for the right-hand value is &apos;string&apos; since the rule&apos;s action depends on its type, meaning that the value must be provided in a generic form.  In the case of a Rule that performs numerical operations, the provided value could be transformed into a number when stored in the Rule.

## Implementation
- [Wonka](https://github.com/Nethereum/Wonka/tree/master/Solidity/WonkaEngine)
- [Wonka Rules Editor](https://github.com/jaerith/WonkaRulesBlazorEditor)

The Wonka implementation supports this proposed interface and also implements all of the additional considerations mentioned above. 

## Security Considerations

The deployer of the contract should be the owner and administrator, allowing for the addition of Attributes and RuleTrees.  Since a RuleTree is owned by a particular EOA (or contract address), the only accounts that should be able to execute the RuleTree should be its owner or the contract&apos;s owner/administrator.  If Attributes are defined to exist as data within other contracts, the implementation must take into account the possibility that RuleTree owners must have the security to access the data in those contracts.

## References

**Standards**
- [EIP-2535 Diamond Standard](/EIPs/EIPS/eip-2535)

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 20 Jun 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2746</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2746</guid>
      </item>
    
      <item>
        <title>Contract Ownership Governance</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2766</comments>
        
        <description>## Simple Summary

A standard for Governance contracts that holds the administrative ownership of other smart contracts with voting power distributed as `ERC-20` tokens.

## Abstract

The following standard defines the implementation of a standard API for a Governance smart contract based on `ERC-20`. Existing `ERC-173` compatible contracts can upgrade from private key wallet ownership to a Governance smart contract. Adhering to a standard API enables general tools to populate governance information of various projects, thus increasing transparency.

## Motivation

Traditionally, many contracts that require that they be owned or controlled in some way use `ERC-173` which standardized the use of ownership in the smart contracts. For example to withdraw funds or perform administrative actions.

```solidity
contract dApp {
  function doSomethingAdministrative() external onlyOwner {
    // admin logic that can be performed by a single wallet
  }
}
```

Often, such administrative rights for a contract are written for maintenance purpose but users need to trust the owner. Rescue operations by an owner have raised questions on decentralised nature of the projects. Also, there is a possibility of compromise of an owner&apos;s private key.

At present, many governance implementations by ambitious projects need users to visit a specific UI to see governance information about their project. Some examples of live implementations having different API that does the same thing are [Compound Governance](https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/GovernorAlpha.sol#L27), [Uniswap Governance](https://github.com/Uniswap/governance/blob/master/contracts/GovernorAlpha.sol#L27) and [Sushiswap Governance](https://github.com/sushiswap/sushiswap/blob/master/contracts/GovernorAlpha.sol#L45). It&apos;s just like if the ERC-20 standard wasn&apos;t finalized, then token projects would have their own block explorer. Adhering to a standard API would enable general tools (like Etherscan) to populate governance information, thus increasing transparency to users. Using widely popular `ERC-20` token as a governance token, existing tools built to work with `ERC-20` can already display voters. This can result in a wide adoption for contract governance over private key based ownership.

## Specification

A Governance contract that is compliant with `ERC-2767` shall implement the following interfaces:

```solidity
/// @title ERC-2767 Governance
/// @dev ERC-165 InterfaceID: 0xd8b04e0e
interface ERC2767 is ERC165 {
    /// @notice Gets number votes required for achieving consensus
    /// @dev Should cost less than 30000 gas
    /// @return Required number of votes for achieving consensus
    function quorumVotes() external view returns (uint256);

    /// @notice The address of the Governance ERC20 token
    function token() external view returns (address);
}
```

### `ERC-20` Governance Token

An `ERC-2767` Governance Contract should reference an address through `token()` that implements `ERC-20` interface. `token()` is allowed to return self address (`address(this)`), if `ERC-20` functionalities are implemented in the same contract (one can consider checking out Diamond Standard [`ERC-2535`](https://eips.ethereum.org/EIPS/eip-2535) to optimise contract size).

Implementations are allowed to have varying `ERC-20`&apos;s `totalSupply()` (through any standard of minting or burning). But having a fixed `quorumVotes()` return value in this case would cause required votes consensus in `%` with respect to `totalSupply()` to change. To automatically account for this, any custom logic under `quorumVotes()` is allowed to return for e.g. `51%` of `totalSupply()`.

### `ERC-165` Interface Identification

An `ERC-2767` Governance Contract should also implement `ERC-165`. This helps general tools to identify whether a contract is a `ERC-2767` Governance contract.

```solidity
interface ERC165 {
    /// @notice Query if a contract implements an interface
    /// @param interfaceID The interface identifier, as specified in ERC-165
    /// @dev Interface identification is specified in ERC-165. This function
    ///  uses less than 30,000 gas.
    /// @return `true` if the contract implements `interfaceID` and
    ///  `interfaceID` is not 0xffffffff, `false` otherwise
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
```

## Rationale

The goals of this EIP have been the following:

- Standardize API of Governance contracts to make it easy for analysis tools to be built.
- Encourage use of `ERC-20` based weighted governance over existing multi-sig (_generally limited to 50 max owners_) for big projects.
- Encourage existing `ERC-173` ownership smart contracts / projects to move to Governance based ownership by removing the effort needed to host custom UI for their project.
- Encourage availability of publicly audited governance contracts, just like `ERC-20` which anyone can use.
- Make it possible to utilize existing `ERC-20` tools for owners of governance token analysis.
- Make future protocols possible that need to interact with governances of multiple projects.
- Keep this EIP minimal and allow another EIPs to standardize any specific functionalities.

## Backwards Compatibility

Smart contracts that are `ERC-173` compliant can transfer their ownership to a Governance contract. This enables such contracts to become compatible with `ERC-2767` Governance.

However, there are some existing projects with governance implementations and most of them have custom APIs ([Compound Governance](https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/GovernorAlpha.sol#L27), [Uniswap Governance](https://github.com/Uniswap/governance/blob/master/contracts/GovernorAlpha.sol#L27) and [Sushiswap Governance](https://github.com/sushiswap/sushiswap/blob/master/contracts/GovernorAlpha.sol#L45)), since a standard did not exist. Not having an `ERC-2767` compatible governance contract means only that general tools might not be able to populate their governance information without including some special code for the project.

For existing governance contracts to get compatible with `ERC-2767`:

1. Projects can deploy a new governance contract and transfer ownership to it to be `ERC-2767` compatible. This is suitable for those who use Multi-sig wallets for Governance.
2. It is understood that redeploying governance contracts would be a troublesome task, and contracts who already have functionality similar to `ERC-20` based (weighted votes) have a bit advanced way to avoid it. Basically, they can create a forwarder contract implements `ERC-2767` and forwards all calls to the actual non-standard methods. Projects can list the forwarder contract to display the information project&apos;s governance info without requiring any custom code in analysys tool, but this might have certain limitations depending on the project&apos;s existing governance implementation. Specification of forwarder contract is out of scope for this EIP and it may be addressed in another EIP if required.

&lt;!-- ## Test Cases --&gt;

## Implementation

The reference implementations are available in this [repository](https://github.com/zemse/contract-ownership-governance). Publicly audited implementations will be included in future.

## Security Considerations

Implementers are free to choose between On-chain and Off-chain consensus. Exact specification is out of scope for this standard (open for other EIPs to standardize). However, this section mentions points that implementers can consider.

#### On-chain

In such implementations, community can create transaction proposals and vote on it by sending on-chain transactions.

- OpenZeppelin Snapshots can be used to prevent double voting.

#### Off-chain

- The signatures in off-chain governance implementation can follow recommendations of `ERC-191` or `ERC-712`.
- To prevent replaying signatures, it&apos;d be best if executer is required to sort the signatures based on increasing addresses.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 04 Jul 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2767</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2767</guid>
      </item>
    
      <item>
        <title>Meta-Transactions Forwarder Contract</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-2770-meta-transactions-forwarder-contract/5391</comments>
        
        <description>## Simple Summary
Standardized contract interface for extensible meta-transaction forwarding.

## Abstract

This proposal defines an external API of an extensible Forwarder whose responsibility is to validate transaction
signatures on-chain and expose the signer to the destination contract, that is expected to accommodate all use-cases.
The ERC-712 structure of the forwarding request can be extended allowing wallets to display readable data even
for types not known during the Forwarder contract deployment.

## Motivation

There is a growing interest in making it possible for Ethereum contracts to
accept calls from externally owned accounts that do not have ETH to pay for
gas.

This can be accomplished with meta-transactions, which are transactions that have been signed as plain data by one
externally owned account first and then wrapped into an Ethereum transaction by a different account.

`msg.sender` is a transaction parameter that can be inspected by a contract to
determine who signed the transaction. The integrity of this parameter is
guaranteed by the Ethereum EVM, but for a meta-transaction verifying
`msg.sender` is insufficient, and signer address must be recovered as well.

The Forwarder contract described here allows multiple Gas Relays and Relay Recipient contracts to rely
on a single instance of the signature verifying code, improving reliability and security
of any participating meta-transaction framework, as well as avoiding on-chain code duplication.

## Specification
The Forwarder contract operates by accepting a signed typed data together with it&apos;s ERC-712 signature,
performing signature verification of incoming data, appending the signer address to the data field and
performing a call to the target.

### Forwarder data type registration
Request struct MUST contain the following fields in this exact order:
```
struct ForwardRequest {
   address from;
   address to;
   uint256 value;
   uint256 gas;
   uint256 nonce;
   bytes data;
   uint256 validUntil;
}
```
`from` - an externally-owned account making the request \
`to` - a destination address, normally a smart-contract\
`value` - an amount of Ether to transfer to the destination\
`gas` - an amount of gas limit to set for the execution\
`nonce` - an on-chain tracked nonce of a transaction\
`data` - the data to be sent to the destination\
`validUntil` - the highest block number the request can be forwarded in, or 0 if request validity is not time-limited

The request struct MAY include any other fields, including nested structs, if necessary.
In order for the Forwarder to be able to enforce the names of the fields of this struct, only registered types are allowed.

Registration MUST be performed in advance by a call to the following method:
```
function registerRequestType(string typeName, string typeSuffix)
```
`typeName` - a name of a type being registered\
`typeSuffix` - an ERC-712 compatible description of a type

For example, after calling 
```
registerRequestType(&quot;ExtendedRequest&quot;, &quot;uint256 x,bytes z,ExtraData extraData)ExtraData(uint256 a,uint256 b,uint256 c)&quot;)
```
the following ERC-712 type will be registered with forwarder:
```
/* primary type */
struct ExtendedRequest {
   address from;
   address to;
   uint256 value;
   uint256 gas;
   uint256 nonce;
   bytes data;
   uint256 validUntil;
   uint256 x;
   bytes z;
   ExtraData extraData;
}

/* subtype */
struct ExtraData {
   uint256 a;
   uint256 b;
   uint256 c;
}
```

### Signature verification

The following method performs an ERC-712 signature check on a request:
```
function verify(
   ForwardRequest forwardRequest,
   bytes32 domainSeparator,
   bytes32 requestTypeHash,
   bytes suffixData,
   bytes signature
) view;
```
`forwardRequest` - an instance of the `ForwardRequest` struct  
`domainSeparator` - caller-provided domain separator to prevent signature reuse across dapps (refer to ERC-712)
`requestTypeHash` - hash of the registered relay request type
`suffixData` - RLP-encoding of the remainder of the request struct
`signature` - an ERC-712 signature on the concatenation of `forwardRequest` and `suffixData`

### Command execution

In order for the Forwarder to perform an operation, the following method is to be called: 
```
function execute(
   ForwardRequest forwardRequest,
   bytes32 domainSeparator,
   bytes32 requestTypeHash,
   bytes suffixData,
   bytes signature
)
public
payable
returns (
   bool success,
   bytes memory ret
)
```
 
Performs the ‘verify’ internally and if it succeeds performs the following call:
```
bytes memory data = abi.encodePacked(forwardRequest.data, forwardRequest.from);
...
(success, ret) = forwardRequest.to.call{gas: forwardRequest.gas, value: forwardRequest.value}(data);
```
Regardless of whether the inner call succeeds or reverts, the nonce is incremented, invalidating the signature and preventing a replay of the request.

Note that `gas` parameter behaves according to EVM rules, specifically EIP-150. The forwarder validates internally that
there is enough gas for the inner call. In case the `forwardRequest` specifies non-zero value, extra `40000 gas` is
reserved in case inner call reverts or there is a remaining Ether so there is a need to transfer value from the `Forwarder`:
```solidity
uint gasForTransfer = 0;
if ( req.value != 0 ) {
   gasForTransfer = 40000; // buffer in case we need to move Ether after the transaction.
}
...
require(gasleft()*63/64 &gt;= req.gas + gasForTransfer, &quot;FWD: insufficient gas&quot;);
```
In case there is not enough `value` in the Forwarder the execution of the inner call fails.\
Be aware that if the inner call ends up transferring Ether to the `Forwarder` in a call that did not originally have `value`, this
Ether will remain inside `Forwarder` after the transaction is complete.
 
### ERC-712 and &apos;suffixData&apos; parameter
`suffixData` field must provide a valid &apos;tail&apos; of an ERC-712 typed data.
For instance, in order to sign on the `ExtendedRequest` struct, the data will be a concatenation of the following chunks:
* `forwardRequest` fields will be RLP-encoded as-is, and variable-length `data` field will be hashed
* `uint256 x` will be appended entirely as-is
* `bytes z` will be hashed first
* `ExtraData extraData` will be hashed as a typed data

So a valid `suffixData` is calculated as following:
```
function calculateSuffixData(ExtendedRequest request) internal pure returns (bytes) {
    return abi.encode(request.x, keccak256(request.z), hashExtraData(request.extraData));
}

function hashExtraData(ExtraData extraData) internal pure returns (bytes32) {
    return keccak256(abi.encode(
            keccak256(&quot;ExtraData(uint256 a,uint256 b,uint256 c)&quot;),
            extraData.a,
            extraData.b,
            extraData.c
        ));
}
```

### Accepting Forwarded calls
In order to support calls performed via the Forwarder, the Recipient contract must read the signer address from the
last 20 bytes of `msg.data`, as described in ERC-2771.

## Rationale
Further relying on `msg.sender` to authenticate end users by their externally-owned accounts is taking the Ethereum dapp ecosystem to a dead end.

A need for users to own Ether before they can interact with any contract has made a huge portion of use-cases for smart contracts non-viable,
which in turn limits the mass adoption and enforces this vicious cycle.

`validUntil` field uses a block number instead of timestamp in order to allow for better precision and integration
with other common block-based timers.

## Security Considerations
All contracts introducing support for the Forwarded requests thereby authorize this contract to perform any operation under any account.
It is critical that this contract has no vulnerabilities or centralization issues.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 01 Jul 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2770</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2770</guid>
      </item>
    
      <item>
        <title>Secure Protocol for Native Meta Transactions</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-2771-secure-protocol-for-native-meta-transactions/4488</comments>
        
        <description>## Abstract

This EIP defines a contract-level protocol for `Recipient` contracts to accept meta-transactions through trusted `Forwarder` contracts. No protocol changes are made. `Recipient` contracts are sent the effective `msg.sender` (referred to as `_msgSender()`) and `msg.data` (referred to as `_msgData()`) by appending additional calldata. 

## Motivation

There is a growing interest in making it possible for Ethereum contracts to accept calls from externally owned accounts that do not have ETH to pay for gas. Solutions that allow for third parties to pay for gas costs are called meta transactions. For the purposes of this EIP, meta transactions are transactions that have been authorized by a **Transaction Signer** and relayed by an untrusted third party that pays for the gas (the **Gas Relay**). 

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### Definitions

**Transaction Signer**: Signs &amp; sends transactions to a Gas Relay

**Gas Relay**: Receives signed requests off-chain from Transaction Signers and pays gas to turn it into a valid transaction that goes through a Trusted Forwarder

**Trusted Forwarder**: A contract trusted by the `Recipient` to correctly verify signatures and nonces before forwarding the request from Transaction Signers

**Recipient**: A contract that accepts meta-transactions through a Trusted Forwarder

### Example Flow

![Example flow](/EIPs/assets/eip-2771/example-flow.png)

### Extracting The Transaction Signer address

The **Trusted Forwarder** is responsible for calling the **Recipient** contract and MUST append the address of the **Transaction Signer** (20 bytes of data) to the end of the call data.

For example :

```solidity
(bool success, bytes memory returnData) = to.call.value(value)(abi.encodePacked(data, from));
```

The **Recipient** contract can then extract the **Transaction Signer** address by performing 3 operations:

1. Check that the **Forwarder** is trusted. How this is implemented is out of the scope of this proposal.
2. Extract the **Transaction Signer** address from the last 20 bytes of the call data and use that as the original `sender` of the transaction (instead of `msg.sender`)
3. If the `msg.sender` is not a trusted forwarder (or if the `msg.data` is shorter than 20 bytes), then return the original `msg.sender` as it is.

The **Recipient** MUST check that it trusts the Forwarder to prevent it from
extracting address data appended from an untrusted contract. This could result
in a forged address.

### Protocol Support Discovery Mechanism

Unless a **Recipient** contract is being used by a particular frontend that knows that this contract has support for native meta transactions, it would not be possible to offer the user the choice of using meta-transaction to interact with the contract. We thus need a mechanism by which the **Recipient** can let the world know that it supports meta transactions. 

This is especially important for meta transactions to be supported at the Web3 wallet level. Such wallets may not necessarily know anything about the **Recipient** contract users may wish to interact with.

As a **Recipient** could trust forwarders with different interfaces and capabilities (e.g., transaction batching, different message signing formats), we need to allow wallets to discover which Forwarder is trusted.

To provide this discovery mechanism a **Recipient** contract MUST implement this function:

```solidity
function isTrustedForwarder(address forwarder) external view returns(bool);
```

`isTrustedForwarder` MUST return `true` if the forwarder is trusted by the Recipient, otherwise it MUST return `false`. `isTrustedForwarder` MUST NOT revert.

Internally, the **Recipient** MUST then accept a request from forwarder.

`isTrustedForwarder` function MAY be called on-chain, and as such gas restrictions MUST be put in place. It SHOULD NOT consume more than 50,000 gas

## Rationale

* Make it easy for contract developers to add support for meta
  transactions by standardizing the simplest viable contract interface.
* Without support for meta transactions in the recipient contract, an externally owned 
  account can not use meta transactions to interact with the recipient contract.
* Without a standard contract interface, there is no standard way for a client
  to discover whether a recipient supports meta transactions.
* Without a standard contract interface, there is no standard way to send a
  meta transaction to a recipient.
* Without the ability to leverage a trusted forwarder every recipient contract
  has to internally implement the logic required to accept meta transactions securely.
* Without a discovery protocol, there is no mechanism for a client to discover
  whether a recipient supports a specific forwarder.
* Making the contract interface agnostic to the internal implementation
  details of the trusted forwarder, makes it possible for a recipient contract
  to support multiple forwarders with no change to code.
* `msg.sender` is a transaction parameter that can be inspected by a contract to determine who signed the transaction. The integrity of this parameter is guaranteed by the Ethereum EVM, but for a meta transaction securing `msg.sender` is insufficient.
  * The problem is that for a contract that is not natively aware of meta transactions, the `msg.sender` of the transaction will make it appear to be coming from the **Gas Relay** and not the **Transaction Signer**. A secure protocol for a contract to accept meta transactions needs to prevent the **Gas Relay** from forging, modifying or duplicating requests by the **Transaction Signer**.

## Reference Implementation

### Recipient Example 

```solidity
contract RecipientExample {

    function purchaseItem(uint256 itemId) external {
        address sender = _msgSender();
        // ... perform the purchase for sender
    }

    address immutable _trustedForwarder;
    constructor(address trustedForwarder) internal {
        _trustedForwarder = trustedForwarder;
    }

    function isTrustedForwarder(address forwarder) public returns(bool) {
        return forwarder == _trustedForwarder;
    }

    function _msgSender() internal view returns (address payable signer) {
        signer = msg.sender;
        if (msg.data.length&gt;=20 &amp;&amp; isTrustedForwarder(signer)) {
            assembly {
                signer := shr(96,calldataload(sub(calldatasize(),20)))
            }
        }    
    }

}
```

## Security Considerations

A malicious forwarder may forge the value of `_msgSender()` and effectively send transactions from any address. Therefore, `Recipient` contracts must be very careful in trusting forwarders. If a forwarder is upgradeable, then one must also trust that the contract won&apos;t perform a malicious upgrade.

In addition, modifying which forwarders are trusted must be restricted, since an attacker could &quot;trust&quot; their own address to forward transactions, and therefore be able to forge transactions. It is recommended to have the list of trusted forwarders be immutable, and if this is not feasible, then only trusted contract owners should be able to modify it.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 01 Jul 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2771</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2771</guid>
      </item>
    
      <item>
        <title>Reduce intrinsic transaction gas</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2780-reduce-intrinsic-cost-of-transactions/4413</comments>
        
        <description>## Abstract

Reduce the intrinsic cost `TX_BASE_COST` from `21,000` to `4,500` and define a consistent gas accounting model based on actual state operations. This more granular approach makes a simple ETH transfer `7,756` due to additional costs related to the `to` account and the [EIP-7708](/EIPs/EIPS/eip-7708) transfer log.

If a non-create transaction has `value &gt; 0` and targets a non-existent account, charge `GAS_NEW_ACCOUNT = 25,000` to align with `CALL` account creation and price in state growth. When this surcharge applies, the recipient pays exactly one cold non-code touch; no code-load cost applies.

This EIP does not change calldata or access-list metering. It also refines related gas schedule items used in derivation and execution accounting:

- Split cold-account touches into `COLD_ACCOUNT_COST_CODE = 2,600` and `COLD_ACCOUNT_COST_NOCODE = 500`.
- Introduce `STATE_UPDATE = 1,000` as the price of a single account-leaf write.
- Reprice value-moving calls as account-leaf writes, replacing `CALL_VALUE_COST = 9,000` with `CALL_VALUE_COST = 2 * STATE_UPDATE + TRANSFER_LOG_COST = 3,756`.
- Charge `TRANSFER_LOG_COST = 1,756` for the [EIP-7708](/EIPs/EIPS/eip-7708) transfer log emitted on every nonzero-value transfer to a different account.

Capacity impact (illustrative):

| Metric                      |            Result |  Change | Description                                                  |
| --------------------------- | ----------------: | ------: |------------------------------------------------------------- |
| Max (minimal txs)           | 13,333 tx / block |   +367% | 4,500-gas minimal transactions per 60 M block                |
| Max (ETH transfers)         |  7,735 tx / block |   +171% | 7,756-gas ETH transfers per 60 M block                       |
| Throughput (minimal txs)    |        ~1,111 TPS |   +367% | 4,500-gas minimal transactions per 60 M block per 12sec      |
| Throughput (ETH transfers)  |          ~645 TPS |   +171% | 7,756-gas ETH transfers per 60 M block per 12sec             |
| Equivalent gas-limit uplift |          ≈ +20.8% |       - | Effective throughput gain for avg tx usage (e.g., 60 M =&gt; ~72.5 M) |

## Motivation

**Monetary Context**

Money has three basic functions: a unit of account, a medium of exchange, and a store of value. ETH already meets the last two by design. It carries value without an issuer and settles with finality. Where it falls short is in everyday exchange - the friction of use rather than the nature of the asset.

ETH underpins most onchain liquidity. Pairs are denominated in it, and gas is paid in it - a de-facto tax base that anchors value. Bitcoin&apos;s monetary role now runs mainly through exchange pairs, hence its drift in focus to store-of-value rather than medium-of-exchange. ETH still clears real activity onchain, yet outside NFTs few people think in ETH terms. In that niche ETH already functions as both unit and medium, but only for high-value items.

For ETH to operate fully as money, it must also handle small transactions. That was impractical when gas sat at 300 gwei, or even 90 gwei on quiet weekends. Post-4844, blobs absorb L2&apos;s &quot;pay at any price&quot; data and higher gas limits ease congestion; cost, not capacity, is the bottleneck.

EIP-2780 lowers that fixed cost. By aligning the base gas with the real work of a transaction and by correcting `CALL` value pricing, it removes the legacy penalty on simple payments. Small transfers become viable again without subsidising calldata or storage. The same logic charges properly for new-account creation, so state growth remains priced in.

- **Unit of account:** When transfers are cheap and regular, people price in ETH because they use it directly. This proposal turns that habit into equilibrium rather than idealism.

- **Medium of exchange:** Reducing `TX_BASE_COST` eliminates the old friction that slowed native circulation. Settlement becomes frequent, not occasional.

- **Store of value:** Honest pricing reinforces confidence that ETH&apos;s cost structure is grounded in real computation, not arbitrary constants.

- **Velocity:** Lower friction raises the rate of final settlement; more frequent, smaller clears in native ETH, without altering calldata or storage economics.

- **Monetary competition:** Stablecoins and LSTs are welcome, but they compete for onchain &quot;moneyness&quot;. Making native ETH easy to spend keeps it central; not just the fuel, but the money of the system.

**Note:** This proposal doesn&apos;t target ETH specifically, the lower base cost applies to every transaction type. However since `TX_BASE_COST` makes up nearly all of an ETH transfer&apos;s gas, while it&apos;s only a small fraction of contract calls, ETH loses the most friction and gains the most velocity.

**Specifics**

The legacy `21,000` base no longer matches the universal work path under warm/cold accounting. Decomposed into signature recovery, one account-leaf write for the sender (nonce + balance coalesced), and one cold non-code touch (sender), the universal path totals `4,500` gas.

State growth is underpriced for top-level value transfers that create accounts, while `CALL` pays explicit creation. Charging `25,000` when a transfer creates an account aligns entry points and internalizes state growth.

A lower base removes the distortion that over-incentivized batching solely to dodge `TX_BASE_COST`, without subsidizing calldata or storage. The refinement of value-transfer costs and cold-account pricing makes execution charges proportional to actual state work: account touches and leaf writes.

We intentionally do **not** charge per-byte gas for the transaction envelope (`nonce`, `gas*`, `to`, `value`, `v`, `r`, `s`). Calldata pricing applies only to `tx.data`. A plain ETH payment has empty `tx.data`, so it pays zero calldata gas. Lowering `TX_BASE_COST` to the universal work path makes ETH payments cheaper without subsidizing arbitrary calldata.

### Throughput, payload, and basefee dynamics

This EIP affects three independent levers:

1. **Gas-limit equivalence:** Reducing the base cost from `21,000` to `4,500` increases transaction capacity at a fixed block gaslimit by approximately +20.8%.

2. **Payload-size bounds:** Per [EIP-7934](/EIPs/EIPS/eip-7934) the execution payload cap is `MAX_RLP_BLOCK_SIZE = 10,485,760 - 2,097,152 = 8,388,608` bytes. Payload size, not gas, may become the dominant block-size constraint at high gaslimits.

3. **Basefee market dynamics:** Lower intrinsic gas reduces the average gas per tx, temporarily increasing utilisation and causing short-term downward adjustment in basefee. Over time, equilibrium restores as inclusion policies adapt.

These levers are independent; this proposal changes only intrinsic gas, not calldata metering or access-list pricing.

### Monetary Effects

Reducing ETH transfer cost from `21,000` =&gt; `7,756` gas increases both transaction frequency and viable payment granularity. At a fixed basefee, smaller payments become economical, raising the **velocity of money** - how often ETH changes hands on L1.

Let $g$ be gas per transaction, $b$ the basefee (in gwei), and $r$ the user&apos;s tolerated fee share of payment value.

$v_{\text{min}} = \frac{g \times b \times 10^{-9}}{r}$

Since $g$ drops from $21,000$ to $7,756$:

$\frac{v_{\text{min,new}}}{v_{\text{min,old}}} = \frac{7{,}756}{21{,}000} \approx 0.37$

The minimum economical L1 payment falls by about **63 %**, allowing more, smaller transfers to clear directly in ETH.

From the quantity relation $M V = P Q$, with $M$ and $P$ roughly constant over short periods:

$V_{\text{new}} / V_{\text{old}} \approx Q_{\text{new}} / Q_{\text{old}}$

Pure ETH-transfer capacity rises roughly **2.7x** (+171 %), and the lower $v_{\text{min}}$ further increases $Q$ as more small-value payments become viable.

Together these effects lift $V$, more frequent, smaller, native settlements without changing monetary supply.

ETH thus gains moneyness:

- **Medium of exchange:** direct use becomes routine, not exceptional.
- **Unit of account:** frequent native settlement encourages ETH-denominated pricing.
- **Store of value:** workload-based fees reinforce trust in cost realism.

Price volatility may still lead users to prefer stablecoins for predictability, but this change removes unnecessary friction, restoring ETH’s competitiveness wherever volatility is tolerable.

The `25,000` surcharge for new-account creation continues to price state growth honestly while everyday transfers become cheaper and faster.

### Equivalent gas-limit increase

Lowering `TX_BASE_COST` from `21,000` to `4,500` removes up to `16,500` gas per transaction. Using recent totals of 163 Ggas/day and 1.7 M tx/day:

| Metric                       | Calculation     | Result          | Change    |
| ---------------------------- | ---------------:| ---------------:| ---------:|
| Avg gas per tx               | 163Bn / 1.7M    | ≈ 95,882 gas    | -         |
| New avg gas per tx           | 95,882 − 16,500 | ≈ 79,382 gas    | -         |
| Throughput at fixed gaslimit | 95,882 / 79,382 | ≈ x1.208        | +20.08%   |
| Daily tx at same gas usage   | 1.7M × 1.208    | ≈ 2.053M tx/day | +340k/day |

Perfnet measurements show EL clients handle &gt;300 MGas/s for pure ETH transfers. Expressed under a 4.5k base this corresponds to `300 * (4.5/21) ~ 64.3 MGas/s`, i.e. `~771 MGas` per 12 s slot. This indicates sufficient headroom and that the current base is significantly overcharged, so no extra engineering is required to improve performance to support this change.

Net effect equals raising a 45 M gas limit to ~54.4 M at unchanged calldata and access-list metering. This directly advances Scaling L1.

## Specification

After `FORK_BLOCK`, set the following parameters and rules:

### Parameters

| Name                       |  Value | Description                                                             |
| -------------------------- | -----: | ----------------------------------------------------------------------- |
| `TX_BASE_COST`             |  4,500 | Base cost of any transaction                                            |
| `GAS_NEW_ACCOUNT`          | 25,000 | Surcharge when a value-transferring transaction creates a new account   |
| `STATE_UPDATE`             |  1,000 | One account-leaf write in the account trie (nonce and balance coalesce) |
| `COLD_ACCOUNT_COST_CODE`   |  2,600 | Cold touch of an account with code                                      |
| `COLD_ACCOUNT_COST_NOCODE` |    500 | Cold touch of an account known to have no code                          |
| `WARM_STATE_READ`          |    100 | Touch of an already-warm account (same as `WARM_STORAGE_READ_COST`)     |
| `TRANSFER_LOG_COST`        |  1,756 | [EIP-7708](/EIPs/EIPS/eip-7708) LOG3 transfer event (375 + 3×375 + 32×8)     |

The intrinsic gas accounting defined here overrides [EIP-2929](/EIPs/EIPS/eip-2929)&apos;s blanket &quot;all tx addresses are warm&quot; rule.

A transaction’s intrinsic base is decomposed into explicit primitives, so warmth must be priced explicitly.

- `tx.sender` is charged as a cold non-code account (`COLD_ACCOUNT_COST_NOCODE = 500`), representing the first access and coalesced account-leaf update.

- `tx.to` is charged based on its type:

  - if a contract create, charge under those rules.

  - if an EOA or an empty account, use `COLD_ACCOUNT_COST_NOCODE = 500`.

  - if a contract, use `COLD_ACCOUNT_COST_CODE = 2,600`.

  - if a precompile, it is warm at tx start and charged zero.

- Warmth discovered through an access list still applies and overrides the cold cost.

This decomposition replaces the implicit warmth assumptions of [EIP-2929](/EIPs/EIPS/eip-2929) and makes the per-account cost explicit in the base or the execution phase as appropriate.

Notes:

- `STATE_UPDATE` counts writes at the account-leaf granularity. If a single account&apos;s nonce and balance both change in one transition, charge one `STATE_UPDATE`.
- `COLD_ACCOUNT_COST_NOCODE` reflects that non-code accounts do not load code or a storage trie, so have a lower warming cost.
- A regular ETH transfer additionally includes a cold touch of at least `COLD_ACCOUNT_COST_NOCODE`, a `STATE_UPDATE` of the `to` address, and a `TRANSFER_LOG_COST` for the [EIP-7708](/EIPs/EIPS/eip-7708) transfer log, so the effective minimal productive tx cost is `7,756`.
- Not including the `to` cold warming and `STATE_UPDATE` in `TX_BASE_COST` means a contract-interaction transaction that does not transfer value does not unnecessarily pay these additional costs.

### Derivation (non-normative)

Decomposition of the base cost into universal primitives:

| Component                |      Cost | Notes                                              |
| ------------------------ | --------: | -------------------------------------------------- |
| ECRECOVER                |     3,000 | Elliptic curve signature recovery                  |
| STATE_UPDATE             |     1,000 | One account-leaf write (nonce + balance coalesced) |
| COLD_ACCOUNT_COST_NOCODE |       500 | Sender is cold and has no code                     |
| **TX_BASE_COST**         | **4,500** | Sum of above (3,000 + 1,000 + 500)                 |


### New-account surcharge

Apply `GAS_NEW_ACCOUNT` when **all** are true:

1. The transaction is not a `CREATE` transaction.
2. `value &gt; 0`.
3. `to` is not a precompile.
4. `to` is non-existent per [EIP-161](/EIPs/EIPS/eip-161) emptiness at the start of transaction execution.

The `GAS_NEW_ACCOUNT = 25,000` charge covers state growth (new leaf creation and one `STATE_UPDATE`).
An additional `COLD_ACCOUNT_COST_NOCODE = 500` applies for the initial lookup to determine that the account does not exist.

Thus, the **total** intrinsic gas for a value-transferring transaction to a new account is `31,756` (`4,500 base + 500 lookup + 25,000 new-account surcharge + 1,756 transfer log`).

For reference, the **total** charges for such transfers change from 21,000 to 31,756.

| Component                |     Cost   | Notes                                    |
| ------------------------ | ----------:| ---------------------------------------- |
| TX_BASE_COST             |     4,500  | Base transaction cost                    |
| COLD_ACCOUNT_COST_NOCODE |       500  | Recipient cold lookup (execution charge) |
| GAS_NEW_ACCOUNT          |    25,000  | Account creation, includes leaf write    |
| TRANSFER_LOG_COST        |     1,756  | EIP-7708 transfer log                    |
| **Total**                | **31,756** | Sum of above (4,500 + 500 + 25,000 + 1,756) |

Notes:

- If `value = 0` and `to` is empty per [EIP-161](/EIPs/EIPS/eip-161), no account is created and no surcharge applies.
- `CREATE` transactions are unchanged; their cost already includes account creation.

### Intrinsic gas computation

Clients compute intrinsic gas as today for each typed transaction **except**:

- Replace any hardcoded `21,000` with `TX_BASE_COST = 4,500`.
- Add `GAS_NEW_ACCOUNT` when the *New-account surcharge* conditions hold.

### Pseudocode (normative):

```python
def CalculateIntrinsicGas(tx, state_at_start):
    gasCost = TX_BASE_COST

    # Existing rules for calldata and access lists remain unchanged by this EIP.
    gasCost += GasForCalldata(tx.data)                  # per active calldata pricing EIPs
    if tx.has_access_list():
        gasCost += GasForAccessList(tx.access_list)     # per EIP-2930

    if tx.is_create() == False and tx.value &gt; 0 and tx.sender != tx.to:
        gasCost += TRANSFER_LOG_COST                    # EIP-7708 transfer log

    if tx.is_create() == False
       and tx.value &gt; 0
       and is_precompile(tx.to) == False
       and is_nonexistent_per_eip161(state_at_start, tx.to):
        gasCost += GAS_NEW_ACCOUNT

    return gasCost
```

### EVM gas schedule adjustments

These changes refine execution-layer accounting to align with the primitives above.

- **Value-moving calls.** Replace the legacy `CALL_VALUE_COST = 9,000` with:

  - If `caller == to` (self-call): `CALL_VALUE_COST = STATE_UPDATE = 1,000`. No `TRANSFER_LOG_COST` is charged because [EIP-7708](/EIPs/EIPS/eip-7708) does not emit a transfer log for self-transfers.
  - If recipient exists and `caller != to`: `CALL_VALUE_COST = 2 * STATE_UPDATE + TRANSFER_LOG_COST = 3,756`.
  - If recipient is EIP-161-empty and `caller != to`: `CALL_VALUE_COST = STATE_UPDATE + GAS_NEW_ACCOUNT + TRANSFER_LOG_COST = 27,756`.
  - This charge is in addition to warm/cold account-touch costs per EIP-2929 and the existing `CALL` base cost. This EIP does not modify the `CALL` base cost.
  - `TRANSFER_LOG_COST` covers the [EIP-7708](/EIPs/EIPS/eip-7708) transfer log emitted for every nonzero-value transfer to a different account.

  The `CALL_VALUE_COST` applies for all value-carrying calls, regardless of whether the callee&apos;s account has already been updated earlier in the same transaction. This ensures the 2300-gas stipend mechanism remains safe and consistent for simple value forwarding and does not retroactively depend on account-update history.

- **Cold-account touches.**

  - Use `COLD_ACCOUNT_COST_CODE = 2,600` when touching an account with code.
  - Use `COLD_ACCOUNT_COST_NOCODE = 500` when touching an account known to have no code.

- **Warmth policy.**

  - Access-list entries (charged via [EIP-2930](/EIPs/EIPS/eip-2930)) and precompiles are warm at tx start.
  - `CALL` warms its `to` after charging the appropriate cold cost if cold.

- **Self-transfers.** If `from == to`, only one `STATE_UPDATE` occurs. The sender&apos;s nonce and balance update are coalesced into the same leaf write. No recipient lookup or separate write is charged. (It is a NOP tx other than charging gas and incrementing nonce).

### Transaction reference cases

| Case                                | Formula                                                          | Total Cost                |
| ----------------------------------- | ---------------------------------------------------------------- | -------------------------:|
| (NOP) No-transfer to EOA            | `TX_BASE_COST`                                                   | 4,500                 |
| (NOP) No-transfer to empty account  | `TX_BASE_COST`                                                   | 4,500                 |
| (NOP) ETH transfer to self          | `TX_BASE_COST`                                                   | 4,500                 |
| ETH Transfer to existing EOA        | `TX_BASE_COST` + `COLD_ACCOUNT_COST_NOCODE` + `STATE_UPDATE` + `TRANSFER_LOG_COST` | 7,756                 |
| No-transfer to contract             | `TX_BASE_COST` + `COLD_ACCOUNT_COST_CODE` + **execution**                | 7,100 + **execution**     |
| ETH Transfer to contract            | `TX_BASE_COST` + `COLD_ACCOUNT_COST_CODE` + `STATE_UPDATE` + `TRANSFER_LOG_COST` + **execution** | 9,856 + **execution**     |
| ETH Transfer creating new account   | `TX_BASE_COST` + `COLD_ACCOUNT_COST_NOCODE` + `GAS_NEW_ACCOUNT` + `TRANSFER_LOG_COST` | 31,756                |

This aligns costs with actual state work rather than legacy flat surcharges.

### Edits and interactions with other EIPs

- **[EIP-2930](/EIPs/EIPS/eip-2930) (Access List).** Intrinsic gas is `TX_BASE_COST` after `FORK_BLOCK`. Access lists keep their existing per-entry charges and warming semantics.
- **[EIP-2929](/EIPs/EIPS/eip-2929) (Gas cost increases for state access).** Refined by this EIP to price non-code cold touches at `500` and code-account cold touches at `2,600`.
- **[EIP-7702](/EIPs/EIPS/eip-7702) (Set EOA Code).** `TX_BASE_COST` remains `4,500` even if the sender temporarily assumes code for the transaction. Clients must not perform any disk code-load to determine sender type, since 7702 provides code inline. If the transaction executes code that reads or executes its own code, normal `COLD_ACCOUNT_COST_CODE` or `WARM_STATE_READ` costs apply at execution time as per the standard cold/warm model.
- **[EIP-7708](/EIPs/EIPS/eip-7708) (ETH transfers emit a log).** EIP-7708 emits a LOG3 transfer event for every nonzero-value ETH transfer. Under the legacy `21,000` base this cost was absorbed; with a reduced base it must be charged explicitly. This EIP introduces `TRANSFER_LOG_COST = 1,756` (LOG3 equivalent: `375 + 3×375 + 32×8`) applied to top-level value transfers, value-moving `CALL`s, and nonzero-value `SELFDESTRUCT` when it transfers value to a different account; for `SELFDESTRUCT`, the charge is applied at the point that transfer is processed.
- **Calldata-pricing EIPs (e.g. [EIP-7623](/EIPs/EIPS/eip-7623)).** Unchanged. This EIP does not alter calldata pricing.

## Rationale

Price only what every transaction always does: ECDSA recovery, warming `sender` and `to`, and one account-leaf write for the sender (nonce + balance change). That sums to `4,500` gas. Anything not universal should be metered separately.

Calldata remains metered per byte. No calldata allowance is folded into the base. This reinforces ETH as money and payments: a plain ETH transfer carries no calldata, executes no bytecode, and touches no contract storage slots. It adds exactly one recipient touch (when not a smart contract), one recipient leaf write, and one [EIP-7708](/EIPs/EIPS/eip-7708) transfer log, so its total is `7,756`.

`CREATE` is unchanged because its cost already includes account creation. Access-list pricing is unchanged.

Legacy pricing undercharged top-level ETH transfers that created new accounts relative to internal `CALL`-based creations. This EIP corrects that by charging `GAS_NEW_ACCOUNT = 25,000`, identical to the `CALL` account-creation surcharge, ensuring consistent pricing for state growth regardless of entry path.

This removes cross-subsidies, aligns charges with resources, and keeps costs equal across paths that perform the same state growth.

Do not fold any calldata allowance into the base. The envelope RLP (`nonce`, `gas*`, `to`, `value`, `v`, `r`, `s`) is not charged as calldata and remains unmetered per byte. Only `tx.data` bytes are metered at the existing calldata schedule, and access lists keep their per-entry costs. A vanilla ETH transfer executes no bytecode and touches no contract storage slots; it performs signature recovery, warms the sender, and updates sender and recipient accounts. It therefore receives the base discount and pays only the additional recipient costs.

Bundling multiple transfers into a single contract call avoids repeated `TX_BASE_COST`, but those transfers then execute serially inside one EVM context. That blocks parallel execution. With a lower per-tx base cost, users have less incentive to bundle, so more transfers remain independent transactions. Independent transactions can be scheduled across threads, which improves parallelism at the client and execution-layer level.

Thus, reducing `TX_BASE_COST` not only corrects mispricing but also increases the share of transactions that are naturally parallelizable.

This EIP composes cleanly with calldata-pricing proposals such as [EIP-7623](/EIPs/EIPS/eip-7623) and [EIP-7976](/EIPs/EIPS/eip-7976). Those EIPs affect `tx.data` metering, while this EIP adjusts only transaction-level intrinsic accounting. There is no overlapping scope.

### Why not charge full tx data as calldata?

- **Intrinsic coupling to signed fields.** Pricing full-transaction bytes would make intrinsic gas depend on `gas_limit` and variable-length signature elements, creating fixed-point estimation issues and incentives for signature-length selection as well as iteration instability as `gas_limit` depends on signature which contains `gas_limit`.

- **Serialization neutrality.** A fee rule keyed to RLP size couples costs to one encoding and weakens [EIP-2718](/EIPs/EIPS/eip-2718) type neutrality and future formats such as SSZ. Calldata is treated as opaque bytes so it avoids this coupling.

- **Policy targeting and market floor.** Calldata floors (for example [EIP-7623](/EIPs/EIPS/eip-7623) or [EIP-7976](/EIPs/EIPS/eip-7976)) price bytes in `tx.data` to bound EL payload and steer data to blobs; envelope bytes are control-plane. The `TX_BASE_COST` is the smallest tx size, and having a low encoding-agnostic intrinsic base keeps the minimum inclusion price coupled to the basefee market, without opening a DoS vector.

- **Native settlement and unit-of-account.** Even though all transactions receive the same absolute gas reduction, it proportionally improves pristine ETH transfers more. With an ETH transfer at ~7,756 gas vs a permissioned ERC-20/LST/stablecoin transfer at ~48,000 gas, you get ~6x higher payment throughput per unit gas, which reinforces ETH as the settlement asset and reduces reliance on contract-based money (which carries smart contract risk, operator risk, governance risk and censorship risks via smart contract operator).

![Figure 1](/EIPs/assets/eip-2780/1.png)

### Effects on transactions per block

For execution-payload size, use [EIP-7934](/EIPs/EIPS/eip-7934)’s 8 MiB uncompressed cap: `8,388,608 bytes`. A typical EIP-1559 ETH transfer encodes at roughly `~110 bytes`, yielding a size cap of `floor(8,388,608 / 110) = 76,260 tx` per block when size, not gas, is the binding constraint.

There are two useful ceilings to consider:

- Minimal transaction with no value and no execution: `TX_BASE_COST = 4,500` gas.
- Minimal ETH payment to an existing EOA: `7,756` gas (`TX_BASE_COST + COLD_ACCOUNT_COST_NOCODE + STATE_UPDATE + TRANSFER_LOG_COST`).

Counts below are `floor(gaslimit / per-tx-gas)`, then capped by `76,260` when the 8 MiB size limit binds. TPS figures round to the nearest integer.

#### Scenario A: minimal txs at 4,500 gas

Binding point for size-cap dominance: `76,260 * 4,500 = 343,170,000` gas. At gaslimits above ~343.17 M, block size, not gas, limits the tx count for 4,500-gas transactions.

| Block gaslimit | Old tx/bk (21k) | New tx/bk (4.5k) | TPS @ 12s | TPS @ 6s | TPS @ 3s | TPS @ 1.5s |
| -------------: | --------------: | ---------------: | --------: | -------: | -------: | ---------: |
|           45 M |           2,142 |           10,000 |       833 |    1,667 |    3,333 |      6,667 |
|           60 M |           2,857 |           13,333 |     1,111 |    2,222 |    4,444 |      8,889 |
|          100 M |           4,761 |           22,222 |     1,852 |    3,704 |    7,407 |     14,815 |
|          200 M |           9,523 |           44,444 |     3,704 |    7,407 |   14,815 |     29,629 |
|          450 M |          21,428 |          †76,260 |     6,355 |   12,710 |   25,420 |     50,840 |

  † Size cap binds at 450 M because 450 M &gt; 343.17 M.

#### Scenario B: ETH transfers at 7,756 gas

Binding point for size-cap dominance: `76,260 * 7,756 = 591,472,560` gas. At gaslimits below ~591.47 M, gas limits tx count; above it, the 8 MiB size cap dominates.

| Block gaslimit | Old tx/bk (21k) | New tx/bk (7,756) | TPS @ 12s | TPS @ 6s | TPS @ 3s | TPS @ 1.5s |
| -------------: | --------------: | ----------------: | --------: | -------: | -------: | ---------: |
|           45 M |           2,142 |             5,801 |       483 |      967 |    1,934 |      3,867 |
|           60 M |           2,857 |             7,735 |       644 |    1,289 |    2,578 |      5,157 |
|          100 M |           4,761 |            12,893 |     1,074 |    2,149 |    4,298 |      8,595 |
|          200 M |           9,523 |            25,786 |     2,149 |    4,298 |    8,595 |     17,191 |
|          450 M |          21,428 |            58,019 |     4,835 |    9,670 |   19,340 |     38,680 |

#### Changes for common types of txs

| Transaction Type                   | Old Cost | New Cost | Change |
| ---------------------------------- | -------: | -------: | -----: |
| Simple ETH transfer (existing EOA) |   21,000 |    7,756 |  −63 % |
| ETH transfer creating new EOA      |   21,000 |   31,756 |  +51 % |
| ERC-20 transfer (typical)          |   63,200 |   48,200 |  −24 % |
| ERC-20 transfer (Solady)           |   33,400 |   18,400 |  −45 % |
| Uniswap v3 swap                    |  184,500 |  169,500 |   −8 % |
| Uniswap v3 add-liquidity           |  216,900 |  201,900 |   −7 % |


#### Reference MGas/s for gaslimit vs slot time

| Block gaslimit | MGas/s @ 12s | MGas/s @ 6s | MGas/s @ 3s | MGas/s @ 1.5s |
| -------------: | -----------: | ----------: | ----------: | ------------: |
|           45 M |         3.75 |        7.50 |       15.00 |         30.00 |
|           60 M |         5.00 |       10.00 |       20.00 |         40.00 |
|          100 M |         8.33 |       16.67 |       33.33 |         66.67 |
|          200 M |        16.67 |       33.33 |       66.67 |        133.33 |
|          450 M |        37.50 |       75.00 |      150.00 |        300.00 |

## Backwards Compatibility

This EIP is **not** backward compatible. It is a consensus gas repricing that must be activated at `FORK_BLOCK`.

Wallets, RPCs, gas estimators, and any logic that assumes a `21,000` base must update.

## Test Cases

While the benefits of reducing transactions&apos; intrinsic cost are apparent, such a change should be applied if it imposes no negative externalities, or if such effects are negligible.

Tests should be created with blocks of just ETH transfers and tested on Perfnet across all EL clients to ensure the pricing is correct.

Add explicit test vectors (intrinsic gas only):

1. `value &gt; 0` to an empty EOA (non-existent per EIP-161): intrinsic `31,756` (4,500 base + 500 + 25,000 surcharge + 1,756 transfer log).
2. `value &gt; 0` to a precompile: intrinsic `6,256` (4,500 base + 1,756 transfer log; no surcharge; precompiles are warm at tx start).
3. `value = 0` to an empty address: intrinsic `4,500` (no creation, no surcharge).
4. `CREATE` transaction: unchanged from prior rules.
5. EIP-7702 transaction with and without access list: intrinsic uses `TX_BASE_COST` plus unchanged access-list costs.
6. Block of txs calling minimal gas contract execution with maximal contract size addresses (so VM is activated for every tx).
7. Warmth and access list interplay
    - ETH transfer to existing EOA without access list: charge `COLD_ACCOUNT_COST_NOCODE = 500` for recipient lookup.
    - Same transaction with recipient in access list: charge `WARM_STATE_READ = 100`.
8. 7702 interactions
    - 7702 tx where sender assumes code and calls nothing: intrinsic = 4,500, no extra cold-code cost.
    - 7702 tx where sender assumes code and executes self-code: charge `COLD_ACCOUNT_COST_CODE` when first loaded.
9. Precompile transfers
    - `value &gt; 0` to `0x01`–`0x09`: intrinsic = 6,256 (4,500 base + 1,756 transfer log), no surcharge.
10. Self-transfer `from == to`: total = 4,500.
11. Internal CALL repricing
    - Internal `CALL` to existing EOA with value: `CALL_VALUE_COST = 3,756` plus cold/warm costs.
    - Internal `CALL` to EIP-161-empty: `CALL_VALUE_COST = 27,756`.
12. Zero-value edge cases `value = 0` to empty address: intrinsic = `4,500`.
13. Perfnet stress
    - Fill block with minimal 4,500-gas tx and 7,756-gas ETH transfers; confirm gas vs byte-size binding per [EIP-7934](/EIPs/EIPS/eip-7934).
14. SELFDESTRUCT test: Create-and-destroy in one tx; confirm normal value-transfer costs apply, no deletion repricing.

## Security Considerations

As this significantly increases the max tx per block, this carries risk.

However, this pricing should be the same as performing the component changes inside the transaction; and it factors in the additional costs from state growth which were not originally in the transaction base price.

Current gaslimit testing mostly uses a block with a single transaction; so this should not cause unexpected load compared to what is already being tested.

The semantics of `SELFDESTRUCT` remain unchanged. Following [EIP-6780](/EIPs/EIPS/eip-6780), only contracts created within the same transaction may be fully deleted. This EIP does not reprice or modify any `SELFDESTRUCT` side-effects.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Ethereum Provider Connect/Disconnect Events</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2787</comments>
        
        <description>## Simple Summary

When an Ethereum Provider becomes connected or disconnected, it will emit a `connect`/`disconnect` event.

## Abstract

The Provider is said to be “connected” when it can service RPC requests to at least one chain.
The Provider is said to be “disconnected” when it cannot service RPC requests to any chain at all.
When the Provider switches from a &quot;connected&quot; state to a &quot;disconnected&quot; state, it will emit a `connect` event.
When the Provider switches from a &quot;disconnected&quot; state to a &quot;connected&quot; state, it will emit a `disconnect` event.

## Motivation

When an application is hooked up to an Ethereum provider, there is value in having the application be alerted of connect/disconnect events that may occur so the application can appropriately inform the user of the situation.
It is left up to the application to decide whether to listen in on these events, and how to handle them.

## Specification

### Definitions

#### Connected

The Provider is considered `connected` when it is able to service RPC requests to at least one chain.

#### Disconnected

The Provider is considered `disconnected` when it is unable to service RPC requests to any chain.

### Events

#### `connect`

The Provider **MUST** emit a `connect` event to all attached [EIP-2700](/EIPs/EIPS/eip-2700) listeners if it transitions from a `disconnected` state to a `connected` state.
All attached listeners **MUST** be called with the parameter `{ chainId }`.
`chainId` **MUST** specify the integer ID of the connected chain encoded as a hexadecimal string.
If the Provider supports the `eth_chainId` JSON-RPC method or a derivation of it, then the `chainId` **MUST** match the return value of `eth_chainId`.
The Provider **MAY** call the attached listeners in any order.

## Rationale

This EIP is mostly a retrospective EIP meaning it codifies an already existing specification so there isn’t a lot of room for improving things such as by having a connect/disconnect event per chain.

## Security Considerations

The relationship between Ethereum Provider and client is a trusted one, where it is assumed that the user implicitly trusts the Ethereum Provider which is how it managed to get injected into the client, or the client expressly pulled in a connection to it.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

## Appendix I: Examples

```javascript
// connect
provider.on(&apos;connect&apos;, ({ chainId }) =&gt; {
  console.log(`Provider connected to: ${chainId}`);
});
```
</description>
        <pubDate>Wed, 15 Jul 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2786</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2786</guid>
      </item>
    
      <item>
        <title>Rich Transactions</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/rich-transactions-via-evm-bytecode-execution-from-externally-owned-accounts/4025</comments>
        
        <description>## Abstract
If a transaction has a `to` of address `x`, then the `data` of the transaction will be treated as EVM bytecode and it will be executed from the context of the `CALLER` of the transaction (aka: the transaction signer).

## Motivation
Many Ethereum DApps presently require users to approve multiple transactions in order to produce one effect - for example, the common pattern of first approving a contract to spend a token, then calling that contract. This results in a poor user-experience, and complicates the experience of interacting with DApps.

Making it possible for externally owned accounts to execute EVM bytecode directly allows a single transaction to execute multiple contract calls, allowing DApps to provide a streamlined experience, where every interaction results in at most one transaction.

While this is in principle possible today using contract wallets, other UX issues, such as the need to fund a sending account with gas money, lack of support for contract wallets in browser integrations, and lack of a consistent API for contract wallets has led to poor adoption of these.This EIP is a way of enhancing the utility of existing EOAs, in the spirit of &quot;don&apos;t let the perfect be the enemy of the good&quot;.

## Specification
A new reserved address is specified at `x`, in the range used for precompiles. When a transaction is sent to this address from an externally owned account, the payload of the transaction is treated as EVM bytecode, and executed with the signer of the transaction as the current account. For clarity:
 - The `ADDRESS` opcode returns the address of the EOA that signed the transaction.
 - The `BALANCE` opcode returns the balance of the EOA that signed the transaction.
 - Any `CALL` operations that send value take their value from the EOA that signed the transaction.
 - `CALL` will set the `CALLER` to the EOA (not `x`).
 - `DELEGATECALL` preserves the EOA as the owning account.
 - The `CALLER` and `ORIGIN` opcodes both return the address of the EOA that signed the transaction.
 - There is no code associated with the precompile address. `CODE*` and `EXTCODE*` opcodes behave the same as they do for any empty address.
 - `CALLDATA*` opcodes operate on the transaction payload as expected. 
 - `SLOAD` and `SSTORE` operate on the storage of the EOA. As a result, an EOA can have data in storage, that persists between transactions.
 - The `SELFDESTRUCT` opcode does nothing.
 - All other opcodes behave as expected for a call to a contract address.
 - The transaction is invalid if there is any value attached.
 - A call to the precompile address from a contract has no special effect and is equivalent to a call to a nonexistent precompile or an empty address.

## Rationale
The intent of this EIP is for the new precompile to act in all ways possible like a `DELEGATECALL` from an externally owned account. Some changes are required to reflect the fact that the code being executed is not stored on chain, and for special cases such as `SELFDESTRUCT`, to prevent introducing new edge-cases such as the ability to zero-out an EOA&apos;s nonce.

A precompile was used rather than a new EIP-2718 transaction type because a precompile allows us to have a rich transaction with any type of EIP-2718 transaction.

## Backwards Compatibility
This EIP introduces a new feature that will need to be implemented in a future hard fork. No backwards compatibility issues with existing code are expected.

Contracts or DApps that assume that an EOA cannot atomically perform multiple operations may be affected by this change, as this now makes it possible for EOAs to execute multiple atomic operations together. The authors do not believe this is a significant use-case, as this &apos;protection&apos; is already trivially defeated by miners.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 18 Jul 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2803</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2803</guid>
      </item>
    
      <item>
        <title>Transaction Replacement Message Type</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2831-transaction-replacement-message-type/4448</comments>
        
        <description>## Summary

An extension to the JavaScript Ethereum Provider API ([EIP-1193](/EIPs/EIPS/eip-1193)) this creates a new message type in the event a transaction replacement occurs.

## Abstract

The current communication between providers and consumers of providers are fundamentally broken in the event that a transaction in the mempool has been superseded by a newer transactions. Providers currently have no way of communicating a transaction replacement, and consumers are required to poll block by block for the resulting transaction.

## Motivation

Exert from EIP-1193
&gt; A common convention in the Ethereum web application (&quot;dapp&quot;) ecosystem is for key management software (&quot;wallets&quot;) to expose their API via a JavaScript object in the web page.
This object is called &quot;the Provider&quot;.

Many ingenious developments have been made by wallet developers to improve the overall user experience while interacting with the Ethereum blockchain. One specific innovation was transaction replacement, offering users the ability to effectively cancel a previously sent transaction.

Transaction replacement is not a new concept, but unfortunately causes major user experience problems for dapp developers as the replaced transaction is near impossible to track. 

This EIP formalizes a way for both providers and dapp developers to track transaction replacements seamlessly.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC-2119](https://www.ietf.org/rfc/rfc2119.txt).

### Definitions

_This section is non-normative._

- Provider
  - A JavaScript object made available to a consumer, that provides access to Ethereum by means of a Client.
- Wallet
  - An end-user application that manages private keys, performs signing operations, and acts as a middleware between the Provider and the Client.
- Transaction Replacement
  - Submitting a transaction with both: the same nonce and a 10% increase in the gas price, of a previous transaction which a user no longer wishes to send. This must occur before the original transaction is included in the blockchain.

### Events

These methods **MUST** be implemented per the Node.js [`EventEmitter` API](https://nodejs.org/api/events.html).

The following three events must be implemented: `tx_replacement`, `tx_speedup` and `tx_cancel`.

A `tx_speedup` is defined as a transaction replacement in which the user wishes to adjust the `gasPrice`, to potentially receive a fast block inclusion. For a `tx_speedup` to be considered valid, the replacement tx must contain the **same** following properties as the one it supersedes:
- Nonce
- To
- Value
- Data

```typescript
interface txSpeedupInfo {
  readonly oldTx: string;
  readonly newTx: string;
  readonly nonce: string;
  readonly from: string;
}

Provider.on(&apos;tx_speedup&apos;, listener: (txSpeedupInfo: txSpeedupInfo) =&gt; void): Provider;
```
This event emits the old transaction hash (`oldTx`), the new transaction hash (`newTx`), the nonce used for both transactions (`nonce`), and the signing address for the transaction (`from`).

A `tx_cancel` is defined as a transaction replacement in which the user wishes to nullify a previous transaction before its inclusion. For a `tx_cancel` to be considered valid, the replacement tx must contain the following properties:
- The same nonce as the superseded transaction
- The same From and To
- Zero value
- No data

```typescript
interface txCancelInfo {
  readonly oldTx: string;
  readonly newTx: string;
  readonly nonce: string;
  readonly from: string;
}

Provider.on(&apos;tx_cancel&apos;, listener: (txCancelInfo: txCancelInfo) =&gt; void): Provider;
```
This event emits the old transaction hash (`oldTx`), the new transaction hash (`newTx`), the nonce used for both transactions (`nonce`), and the signing address for the transaction (`from`).

A `tx_replacement` is defined as a transaction replacement in which a user has completely replaced a previous transaction with a completely brand new one. The replacement tx must contain the following properties:
- The same nonce as the superseded transaction

```typescript
interface txReplacementInfo {
  readonly oldTx: string;
  readonly newTx: string;
  readonly nonce: string;
  readonly from: string;
}

Provider.on(&apos;tx_replacement&apos;, listener: (txReplacementInfo: txReplacementInfo) =&gt; void): Provider;
```
This event emits the old transaction hash (`oldTx`), the new transaction hash (`newTx`), the nonce used for both transactions (`nonce`), and the signing address for the transaction (`from`).

## Rationale

The implementation was chosen to help the ease of implementation for both providers and dapp developers. Since `ProviderMessage` is widely used by dapp developers already it means that the implementation path would be as trivial as adding and additional `if` clause to their existing message listener. This also provides a benefit to dapps in the event that a provider has not yet implemented the events, it will not cause the dapp panic with `undefined` should it be implemented natively (eg: `ethereum.txCancel(...)` which would error with `ethereum.txReplacement()` is not a function).

## Backwards Compatibility

Many Providers adopted EIP-1193, as this EIP extends the same event logic, there should be no breaking changes. All providers that do not support the new events should either I) Ignore the subscription or II) Provide some error to the user.

## Implementations

- [Web3.js](https://github.com/ethereum/web3.js/issues/3723)
- [MetaMask](https://github.com/MetaMask/metamask-extension/issues/9174)

## Security Considerations

None at the current time.

## References

- [Web3.js issue with metamask tx cancel](https://github.com/ethereum/web3.js/issues/3585)
- [Browser doesn&apos;t know when a transaction is replace](https://github.com/MetaMask/metamask-extension/issues/3347)

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

## Appendix I: Examples

These examples assume a web browser environment.

```javascript
// Most Providers are available as window.ethereum on page load.
// This is only a convention, not a standard, and may not be the case in practice.
// Please consult the Provider implementation&apos;s documentation.
const ethereum = window.ethereum;

const transactionParameters = { ... } // Fill in parameters

ethereum
  .request({ 
    method: &apos;eth_sendTransaction&apos;,
    params: [transactionParameters],
  })
  .then((txHash) =&gt; {
    ethereum.on(&apos;tx_cancel&apos;, (info) =&gt; {
      const { oldTx, newTx, nonce, from } = message.data;
      console.log(`Tx ${oldTx} with nonce ${nonce} from ${from} was cancelled, the new hash is ${newTx}`)
    });
    ethereum.on(&apos;tx_speedup&apos;, (info) =&gt; {
      const { oldTx, newTx, nonce, from } = message.data;
      console.log(`Tx ${oldTx} with nonce ${nonce} from ${from} was sped up, the new hash is ${newTx}`)
    });
    ethereum.on(&apos;tx_replacement&apos;, (info) =&gt; {
      const { oldTx, newTx, nonce, from } = message.data;
      console.log(`Tx ${oldTx} with nonce ${nonce} from ${from} was replaced, the new hash is ${newTx}`)
    });


    console.log(`Transaction hash ${txHash}`)
  })
  .catch((error) =&gt; {
    console.error(`Error sending transaction: ${error.code}: ${error.message}`);
  });

```
</description>
        <pubDate>Sun, 26 Jul 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2831</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2831</guid>
      </item>
    
      <item>
        <title>Add DID related methods to the JSON-RPC</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2845</comments>
        
        <description>## Simple Summary
Add new methods to the JSON-RPC for signing and decrypting JOSE objects under a new `did_*` prefix.

## Abstract
This EIP describes three new methods to add to the JSON-RPC that enables wallets to support *Decentralized Identifiers* (DIDs) as well as *JSON Object Signing and Encryption* (JOSE). These standards enables wallets to support data decryption as well as authenticated data, both in standard formats using JOSE. With these new methods apps can request the DID from a users wallet, from which a DID document can be resolved. The DID document contains public keys that can be used for encryption and signature verification. This enables Alice to discover Bobs public keys by only knowing Bobs DID. This EIP does not enforce the user of any particular DID method or JOSE algorithms, wallets are free to implement these however they wish.

## Motivation
There has been one main previous effort ([#130](https://github.com/ethereum/EIPs/issues/130), [#1098](https://github.com/ethereum/EIPs/pull/1098)) to add decryption to Ethereum wallets in a standard way. This previous approach used a non standard way to encode and represent data encrypted using `x25519-xsalsa20-poly1305`. While this approach does provide a functional way to add encryption support to wallets, it does not take into account similar work that has gone into standardizing the way encrypted data is represented, namely using [JOSE](https://datatracker.ietf.org/wg/jose/documents/). This is a standard from IETF for representing signed and encrypted objects. Another shortcoming of the previous approach is that it&apos;s impossible to retrieve the `x25519` public key from another user if only an Ethereum address is known. Public key discoverability is at the core of the work that is happening with the [W3C DID standard](https://w3c.github.io/did-core), where given a DID a document which contains public keys can always be discovered. Implementations of this standard already exist and are adopted within the Ethereum community, e.g. [`did:ethr`](https://github.com/decentralized-identity/ethr-did-resolver/) and [`did:3`](https://github.com/3box/3id-resolver). Interoperability between JOSE and DIDs [already exists](https://github.com/decentralized-identity/did-jwt), and work is being done to [strengthen it](https://github.com/decentralized-identity/did-jose-extensions). Adding support for JOSE and DIDs will enable Ethereum wallets to support a wide range of new use cases such as more traditional authentication using JWTs, as well as new emerging technologies such as [Secure Data Stores](https://identity.foundation/secure-data-store/) and [encrypted data in IPFS](https://github.com/ipld/specs/pull/269).

## Specification
Three new JSON-RPC methods are specified under the new `did_*` prefix.

### Auth

Authenticate the current rpc connection to the DID methods.

Prompt the user to give permission to the current connection to access the user DID and the given `paths`.

##### Method: 

`did_authenticate`

##### Params:

* `nonce` - a random string used as a challenge
* `aud` - the intended audience of the authentication response
* `paths` - an array of strings

##### Returns:

A JWS with general serialization containing the following properties:

* `nonce ` - the random string which was given as a challenge

* `did` - the DID which authentication was given for
* `paths` - the paths which was given permission for
* `exp` - a unix timestamp after which the JWS should be considered invalid
* `aud` - optional audience for the JWS, should match the domain which made the request

An additional property `kid` with the value which represents the DID, and the `keyFragment` that was used to sign the JWS should be added to the protected header ([details](https://github.com/decentralized-identity/did-jose-extensions/issues/2)).


#### CreateJWS

Creates a JSON Web Signature (JWS).

An additional property `kid` with the value which represents the DID, and the `keyFragment` that was used to sign the JWS should be added to the protected header ([details](https://github.com/decentralized-identity/did-jose-extensions/issues/2)). When `revocable` is set to false the JWS signature should not be possible to revoke. For some DID methods like. `did:key` this is always the case. For other methods which support key revocation it is necessary to include the `version-id` in the `kid` to refer to a specific version of the DID document. When `revocable` is set to true `version-id` must not be included in the `kid` for DID methods that support key revocation.

##### Method:

`did_createJWS`

##### Params:

* `payload` - the payload to sign, json object or `base64url` encoded string
* `protected` - the protected header, json object
* `did` - the DID that should sign the message, may include the key fragment, string
* `revocable` - makes the JWS revocable when rotating keys, boolean default to `false`

##### Returns:

An object containing a JWS with general serialization on the `jws` property.

##### Recommendation:

Use `secp256k1` for signing, alternatively `ed25519`.



#### DecryptJWE

Decrypt the given JWE.

If the cleartext object contains a property `paths` that contains an array of strings and one of the paths in there are already authenticated using `did_authenticate` the decryption should happen without user confirmation.

##### Method: 

`did_decryptJWE`

##### Params:

* `jwe` - a JWE with general serialization, string
* `did` - the DID that should try to decrypt the JWE, string

##### Returns:

An object containing the cleartext, encoded using [`base64pad`](https://github.com/multiformats/multibase), assigned to the `cleartext` property.

##### Recommendation:

Implement decryption using `xchacha20poly1305` and `x25519` for key agreement.



## Rationale
This EIP chooses to rely on DIDs and JOSE since there is already support for these standards in many places, by current systems and new systems. By using DIDs and JOSE wallet implementers can also choose which signing and encryption algorithms that they want to support, since these formats are fairly agnostic to specific crypto implementations.

### Permission system

A simple permission system is proposed where clients can request permissions though path prefixes, e.g. `/some/permission`. When decryption of a JWE is requested the wallet should check if the decrypted payload contains a `paths` property. If this property doesn&apos;t exist the user may be prompted to confirm that the given rpc connection (app) is allowed to read the decrypted data. If the `paths` property is present in the decrypted data it should contain an array of string paths. If one of the these path prefixes matches with one of the path prefixes the user has already granted permission for then decryption should happen automatically without any user confirmation.

This simple permission system was inspired by some previous comments ([1](https://github.com/ethereum/EIPs/issues/130#issuecomment-329770999), [2](https://medium.com/@wighawag/3-proposals-for-making-web3-a-better-experience-974f97765700)) but avoids data lock in around origins.

## Implementation

[IdentityWallet](https://github.com/3box/identity-wallet-js/): An implementation of the wallet side `did_*` methods using the 3ID DID.

[key-did-provider-ed25519](https://github.com/ceramicnetwork/key-did-provider-ed25519):  An implementation of the wallet side `did_*` methods using the `did:key` method.

[js-did](https://github.com/ceramicnetwork/js-did): A small library which consumes the `did_*` methods.

[MinimalCipher](https://github.com/digitalbazaar/minimal-cipher): An implementation of DID related encryption for JWE.

## Security Considerations

Both JOSE and DIDs are standards that have gone though a lot of scrutiny. Their security will not be considered in this document. In the specification section, recommendations are given for which algorithms to use. For signatures `secp256k1` is already used by ethereum and for decryption `xchacha20poly1305` is widely available, very performant, and already used in TLS.

The main security consideration of this EIP is the suggested permission system. Here various threat models could be considered. However, this EIP does not go into details about how it should work other than suggesting an approach. In the end it is up to wallet implementations to choose how to ask their users for consent.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 01 Aug 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2844</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2844</guid>
      </item>
    
      <item>
        <title>My Own Messages (MOM)</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/InternetOfPeers/EIPs/issues/1</comments>
        
        <description>## Simple Summary

My Own Messages (MOM) is a standard to create your very own public, always updated, unstoppable, verifiable, message board.

## Abstract

My Own Messages (MOM) use Ethereum as a certification layer for commands and multihash of your messages. It don&apos;t use smart contracts but simple self-send transactions with specific payload attached.

To ge more insights, you can test a [live client](http://internetofpeers.org/mom-client/), watch a [full video overview and demo](https://www.youtube.com/watch?v=z1SnoQkQYkU) and read a [brief presentation](/EIPs/assets/eip-2848/presentation.pdf).

## Motivation

As a _developer_ or _pool&apos;s owner_, I&apos;d like to send messages to my users in a decentralized way. They must be able to easily verify my role in the smart contract context (owner, user, and so on) and they must be able to do it without relying on external, insecure and hackable social media sites (Facebook, Twitter, you name it). Also, I&apos;d like to read messages from my userbase, in the same secure and verifiable manner.

As a _user_, I want a method to easily share my thoughts and idea, publish content, send messages, receive feedback, receive tips, and so on, without dealing with any complexity: just write a message, send it and it&apos;s done. Also, I want to write to some smart contract&apos;s owner or to the sender of some transaction.

As an _explorer service_, I want to give my users an effective way to read information by smart contract owners and a place to share ideas and information without using third party services (i.e. Etherscan uses Disqus, and so on)

And in _any role_, I want a method that does not allow scams - transactions without values, no smart contract&apos;s address to remember or to fake - and it does not allow spam - it&apos;s cheap but not free, and even if you can link/refer other accounts, you cannot send them messages directly, and others must explicitly follow and listen to your transactions if they want to read your messages.

Main advantages:

- You can send messages to users of your ÐApp or Smart Contract, and they always know it is a voice reliable as the smart contract is.
- Create your Ethereum account dedicated to your personal messages, say something only once and it can be seen on every social platform (no more reply of the same post/opinion on dozens of sites like Reddit, Twitter, Facebook, Medium, Disqus, and so on...)
- Small fee to be free: pay just few cents of dollar to notarize your messages, and distribute them with IPFS, Swarm or any other storage you prefer. Because the multihash of the content is notarized, you can always check the integrity of the message you download even from centralized storage services.
- Finally, you can ask and get tips for your words directly into your wallet.

I know, My Own Messages (MOM) sounds like _mom_. And yes, pun intended :)

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;,  &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt) when, and only when, they appear in all capitals as shown here.

Clients following MOM standard **MUST** allow users to send and to read MOM transaction, creating an _updated message list_ for each address the users are interested in.

Reading MOM transactions, MOM clients **MUST** be able to show the current and updated message list, and they **SHOULD** be able to show also all the message history if users ask for it.

Apart from message list, MOM clients **SHOULD** be able to download the content of the messages and to show them to the user.

Clients **SHOULD** allow users to choose and set the source to download content from, and they **SHOULD** be able to use common Content Addressable Networks - i.e. IPFS or Swarm - or HTTP servers. If content is downloaded from HTTP servers, clients **MUST** check the content against the declared multihash.

As the default setting, clients **MUST** consider `text/markdown` ([RFC 7763](https://www.ietf.org/rfc/rfc7763.txt)) as the media type of the content represented by a multihash, and in particular [Markdown](https://en.wikipedia.org/wiki/Markdown) text in [UTF-8](https://en.wikipedia.org/wiki/UTF-8) without [BOM](https://en.wikipedia.org/wiki/Byte_order_mark).

Clients **MAY** let users choose to parse messages considering other content types. In this case they **SHOULD** cast a warning to users stating that a content type other than `text/markdown` is used while processing messages.

It&apos;s **RECOMMENDED** that clients inform users about the actual setting of the default content type.

### MOM transactions

Clients **MUST** assume that **invalid MOM transactions don&apos;t exist**. If a transaction does not strictly follow the MOM standard, clients **MUST** ignore it and they **MUST NOT** consider it a MOM transaction at all.

Because there can be security implications parsing data sent by users, clients **SHOULD NOT** try to keep track or interpret transactions as _invalid_ MOM transactions.

#### Valid MOM transaction&apos;s data structure

| ATTRIBUTE | VALUE |
|:--------|:------------|
| `to` | **MUST** be the same account signing the transaction. |
| `value` |  **MUST** be `0` wei. |
| `data` | **MUST** be at least `2` bytes. The first byte **MUST** be operational code and following bytes **MUST** be based on the operational codes listed below. |

#### List of supported operations and messages

Each operational code has one or more parameters, and all parameters **MUST** be considered mandatory.

Optional parameters don&apos;t exist: if parameters for the specific operational code are not all present or they don&apos;t follow the rules, clients **MUST** ignore the transaction completely.

Messages **MUST** be always referenced with the multihash of their content.

Operations are divided into two sets: **CORE** and **EXTENDED** operations. 

- Clients **MUST** support all core operations and they **SHOULD** support as much extended operations as possible.
- Clients **SHOULD** support and implement as much extended operations as possible, but they **MAY** choose to implement only some specific extended operations they are interested in.

#### Core operations

| OPERATION | CODE | PARAMETERS | MEANING | EFFECT |
|-----------|:--------:|------------|---------|--------|
| ADD | `0x00` | multihash | Add a message. The parameter **MUST** be the multihash of the message. | Clients **MUST** add the message to the message list of the sender. |
| UPDATE | `0x01` | multihash, multihash | Update a message. The first parameter **MUST** be the multihash of the message to be updated. The second parameter **MUST** be the multihash of the updated message. | Clients **MUST** update the message list to show the updated message. |
| REPLY | `0x02` | multihash, multihash | Reply to a message. The first parameter **MUST** be the multihash of the message to reply to. The second parameter **MUST** the multihash of the message. | Clients **MUST** insert a new message in the message list and they **MUST** preserve the relationship with the referenced message. |
| DELETE | `0x03` | multihash | Delete a message. The parameter **MUST** be the multihash of the message to delete. | Clients **MUST** remove the message from the message list. |
| CLOSE ACCOUNT | `0xFD` | multihash | Close an account. The parameter **MUST** be the multihash of the message with the motivations for closing the account. | Clients **MUST** add the message with motivations to the message list and they **MUST NOT** consider MOM messages sent by that address to be valid anymore, ever. In other words, MOM clients **MUST** ignore any other transaction sent by that address while creating the message list. This is useful when users want to change account, for example because the private key seems compromised. |
| RAW | `0xFF` | any | The parameter **MUST** be at least `1` byte. Content type is not disclosed and it **MUST NOT** be considered as `text/markdown`. | Clients **MUST** add the message to the message list but they **MUST NOT** try to decode the content. Clients **SHOULD** allow users to see this message only if explicitly asked for. This operation can be used for _blind_ notarization that general client can ignore. |

#### Note about `DELETE` operational code

Please note that sending a `DELETE` command users are not asking to actually delete anything from the blockchain, they are just asking clients to hide that specific message because it&apos;s not valid anymore for some reasons. You can think of it like if users say: _I changed my mind so please ÐApps don&apos;t show this anymore_. As already stated in the specifications above, clients **MUST** follow this request by the author, unless expressly asked otherwise by the user. 

Please also note that, because it&apos;s usually up to the author of a message to be sure the content is available to everyone, if a `DELETE` message was sent it&apos;s very likely the content referenced by the multihash isn&apos;t available anymore, simply because probably it&apos;s not shared by anyone.

#### Extended operations

| OPERATION | CODE | PARAMETERS | MEANING | EFFECT |
|-----------|:--------:|------------|---------|--------|
| ADD &amp; REFER | `0x04` | multihash, address | Add a message and refer an account. The first parameter **MUST** be the multihash of the message. The second parameter **MUST** be an address referenced by the message. | Clients **MUST** add the message to the message list and they **MUST** track the reference to the specified account. This can be useful _to invite_ the owner of the referenced account to read this specific message. |
| UPDATE &amp; REFER | `0x05` | multihash, multihash, address | Update a message. The first parameter **MUST** be the multihash of the message to be updated. The second parameter **MUST** be the multihash of the updated message. The third parameter **MUST** be an address referenced by the message.| Clients **MUST** update the message list to show the updated message and they **MUST** track the reference to the specified account. This can be useful _to invite_ the owner of the referenced account to read this specific message. |
| ENDORSE | `0x06` | multihash | Endorse a message identified by the specified multihash. The parameter **MUST** be the multihash of the message to be endorsed. | Clients **MUST** record and track the endorsement for that specific message. Think it as a _like_, a _retwitt_, etc. |
| REMOVE ENDORSEMENT | `0x07` | multihash | Remove endorsement to the message identified by the specified multihash. The parameter **MUST** be the multihash of the message. | Clients **MUST** remove the endorsement for that specific message. |
| DISAPPROVE | `0x08` | multihash | Disapprove a message identified by the specified multihash. The parameter **MUST** be the multihash of the message to disapprove. | Clients **MUST** record and track the disapproval for that specific message. Think it as a _I don&apos;t like it_. |
| REMOVE DISAPPROVAL | `0x09` | multihash | Remove disapproval of a message identified by the specified multihash. The parameter **MUST** be the multihash of the message. | Clients **MUST** remove the disapproval for that specific message. |
| ENDORSE &amp; REPLY | `0x0A` | multihash, multihash | Endorse a message and reply to it. The first parameter **MUST** be the multihash of the message to reply to. The second parameter **MUST** be the multihash of the message. | Clients **MUST** insert a new message in the message list and they **MUST** preserve the relationship with the referenced message. Clients **MUST** also record and track the endorsement for that specific message. |
| DISAPPROVE &amp; REPLY | `0x0B` | multihash, multihash | Disapprove a message and reply to it. The first parameter **MUST** be the multihash of the message to reply to. The second parameter **MUST** be the multihash of the message. | Clients **MUST** insert a new message in the message list and they **MUST** preserve the relationship with the referenced message. Clients **MUST** also record and track the disapproval for that specific message. |

## Rationale

Ethereum is _account based_, so it&apos;s good to be identified as a single source of information.

It is also able of doing notarization very well and to impose some restrictions on transaction&apos;s structure, so it&apos;s good for commands.

IPFS, Swarm or other CANs (Content Addressable Networks) or storage methods are good to store a lot of information. So, the union of both worlds it&apos;s a good solution to achieve the objectives of this message standard.

The objective is also to avoid in the first place any kind of scam and malicious behaviors, so MOM don&apos;t allow to send transactions to other accounts and the value of a MOM transaction is always 0.

### Why not using a smart contract?

MOM wants to be useful, easy to implement and read, error proof, fast and cheap, but:

- using a smart contract for messages can leads more easily to errors and misunderstandings:
  - address of the contract can be wrong
  - smart contract must be deployed on that specific network to send messages
- executing a smart contract costs much more than sending transactions
- executing a smart contract just to store static data is the best example of an anti-pattern (expensive and almost useless)

Without a specific smart contract to rely on, the MOM standard can be implemented and used right now in any existing networks, and even in future ones.

Finally, if you can achieve exactly the same result without a smart contract, you didn&apos;t need a smart contract at the first place.

### Why not storing messages directly on-chain?

There&apos;s no benefit to store _static_ messages on-chain, if they are not related to some smart contract&apos;s state or if they don&apos;t represent exchange of value. The cost of storing data on-chain is also very high.

### Why not storing op codes inside the message?

While cost effectiveness is a very important feature in a blockchain related standard, there&apos;s also a compromise to reach with usability and usefulness.

Storing commands inside the messages forces the client to actually download messages to understand what to do with them. This is very inefficient, bandwidth and time consuming.

Being able to see the commands before downloading the content, it allows the client to recreate the history of all messages and then, at the end, download only updated messages.

Creating a structure for the content of the messages leads to many issues and considerations in parsing the content, if it&apos;s correct, misspelled, and so on.

Finally, the **content must remain clean**. You really want to notarize the content and not to refer to a data structure, because this can lead to possible false-negative when checking if a content is the same of another.

### Why multihash?

[Multihash](https://github.com/multiformats/multihash) is flexible, future-proof and there are already tons of library supporting it. Ethereum must be easily integrable with many different platforms and architectures, so MOM standard follows that idea.

## Backwards Compatibility

You can already find few transactions over the Ethereum network that use a pattern similar to this EIP. Sometimes it&apos;s done to invalidate a previous transaction in memory pool, using the same nonce but with more gas price, so that transaction is mined cancelling the previous one still in the memory pool. This kind of transactions can be easily ignored if created before the approval of this EIP or just checking if the payload follows the correct syntax.

## Test Cases

A MOM-compliant client can be found and tested on [GitHub](https://github.com/InternetOfPeers/mom-client).

You can use the latest version of MOM client directly via [GitHub Pages](https://internetofpeers.github.io/mom-client) or via IPFS (see the [client repo](https://github.com/InternetOfPeers/mom-client) for the latest updated address).

## Implementation

You can use an already working MOM JavaScript package on [GitHub Packages](https://github.com/InternetOfPeers/mom-js/packages/323930) or [npmjs](https://www.npmjs.com/package/@internetofpeers/mom-js). The package is already used by the MOM client above, and you can use it in your ÐApps too with:

```bash
npm install @internetofpeers/mom-js
```

Transaction [`0x8e49485c56897757a6f2707b92cd5dad06126afed92261b9fe1a19b110bc34e6`](https://etherscan.io/tx/0x8e49485c56897757a6f2707b92cd5dad06126afed92261b9fe1a19b110bc34e6) is an example of a valid MOM transaction already mined on the Main net; it&apos;s an `ADD` message.

## Security Considerations

MOM is very simple and it has no real security concerns by itself. The standard already considers valid only transactions with `0` value and where `from` and `to` addresses are equals.

The only concerns can come from the payload, but it is more related to the client and not to the standard itself, so here you can find some security suggestions related to clients implementing the standard.

### Parsing commands

MOM standard involves parsing payloads generated by potentially malicious clients, so attention must be made to avoid unwanted code execution.

- Strictly follow only the standard codes
- Don&apos;t execute any commands outside of the standard ones, unless expressly acknowledged by the user
- Ignore malformed transactions (transactions that don&apos;t strictly follow the rules)

### Messages

Default content-type of a message following the MOM standard is Markdown text in UTF8 without BOM. It is highly recommended to disallow the reading of any not-text content-type, unless expressly acknowledged by the user.

Because content multihash is always stored into the chain, clients can download that content from Content Addressable Network (like IPFS or Swarm) or from central servers. In the latter case, a client should always check the integrity of the received messages, or it must warn the user if it cannot do that (feature not implemented or in error).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 02 Aug 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2848</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2848</guid>
      </item>
    
      <item>
        <title>Deposit contract and address standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/junderw/deposit-contract-poc/issues/1</comments>
        
        <description>## Simple Summary
This ERC defines a simple contract interface for managing deposits. It also defines a new address format that encodes the extra data passed into the interface&apos;s main deposit function.

## Abstract
An ERC-2876 compatible **deposit system** can accept ETH payments from multiple depositors without the need for managing multiple keys or requiring use of a hot wallet.

An ERC-2876 compatible **wallet application** can send ETH to ERC-2876 compatible **deposit systems** in a way that the **deposit system** can differentiate their payment using the 8 byte id specified in this standard.

Adoption of ERC-2876 by all exchanges (as a deposit system and as a wallet for their withdrawal systems), merchants, and all wallet applications/libraries will likely decrease total network gas usage by these systems, since two value transactions cost 42000 gas while a simple ETH forwarding contract will cost closer to 30000 gas depending on the underlying implementation.

This also has the benefit for deposit system administrators of allowing for all deposits to be forwarded to a cold wallet directly without any manual operations to gather deposits from multiple external accounts.

## Motivation
Centralized exchanges and merchants (Below: &quot;apps&quot;) require an address format for accepting deposits. Currently the address format used refers to an account (external or contract), but this creates a problem. It requires that apps create a new account for every invoice / user. If the account is external, that means the app must have the deposit addresses be hot wallets, or have increased workload for cold wallet operators (as each deposit account will create 1 value tx to sweep). If the account is contract, generating an account costs at least 60k gas for a simple proxy, which is cost-prohibitive.

Therefore, merchant and centralized exchange apps are forced between taking on one of the following:

- Large security risk (deposit accounts are hot wallets)
- Large manual labor cost (cold account manager spends time sweeping thousands of cold accounts)
- Large service cost (deploying a contract-per-deposit-address model).

The timing of this proposal is within the context of increased network gas prices. During times like this, more and more services who enter the space are being forced into hot wallets for deposits, which is a large security risk.

The motivation for this proposal is to lower the cost of deploying and managing a system that accepts deposits from many users, and by standardizing the methodology for this, services across the world can easily use this interface to send value to and from each other without the need to create multiple accounts.

## Specification

### Definitions
- The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;,  &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.
- `The contract interface` is the contract component of this ERC.
- `The deposit address format` is the newly made format described in &quot;Deposit Address Format&quot; for encoding the 20 byte account address and the 8 byte id.
- `The contract` refers to the contract that implements `the contract interface` of this ERC.
- `The 8 byte &quot;id&quot;` is an 8 byte id used as the input parameter for the contract interface.
- `The 5 byte &quot;nonce&quot;` is the first 5 most significant bytes of the `&quot;id&quot;`.
- `The 3 byte &quot;checksum&quot;` is the last 3 least significant bytes of the `&quot;id&quot;`
- `deposit(bytes8)` refers to the function of that signature, which is defined in `the contract interface`.
- `The parent application` refers to the application that will use the information gained within the `deposit(bytes8)` function. (ie. an exchange backend or a non-custodial merchant application)
- `The depositor` refers to the person that will send value to `the contract` via the `deposit(bytes8)` call.
- `The wallet` refers to any application or library that sends value transactions upon the request of `the depositor`. (ie. MyEtherWallet, Ledger, blockchain.com, various libraries)

### Deposit Address Format

In order to add the 8 byte &quot;id&quot; data, we need to encode it along with the 20 byte
account address. The 8 bytes are appended to the 20 byte address.

A 3 byte checksum is included in the id, which is the first 3 bytes of the keccak256
hash of the 20 byte address and first 5 byte nonce of the id concatenated (25 bytes).

The Deposit Address format can be generated with the following JavaScript code:

```js
/**
 * Converts a 20 byte account address and a 5 byte nonce to a deposit address.
 * The format of the return value is 28 bytes as follows. The + operator is byte
 * concatenation.
 * (baseAddress + nonce + keccak256(baseAddress + nonce)[:3])
 *
 * @param {String} baseAddress the given HEX address (20 byte hex string with 0x prepended)
 * @param {String} nonce the given HEX nonce (5 byte hex string with 0x prepended)
 * @return {String}
 */
function generateAddress (baseAddress, nonce) {
  if (
    !baseAddress.match(/^0x[0-9a-fA-F]{40}$/) ||
    !nonce.match(/^0x[0-9a-fA-F]{10}$/)
  ) {
    throw new Error(&apos;Base Address and nonce must be 0x hex strings&apos;);
  }
  const ret =
    baseAddress.toLowerCase() + nonce.toLowerCase().replace(/^0x/, &apos;&apos;);
  const myHash = web3.utils.keccak256(ret);
  return ret + myHash.slice(2, 8); // first 3 bytes from the 0x hex string
};
```

The checksum can be verified within the deposit contract itself using the following:

```solidity
function checksumMatch(bytes8 id) internal view returns (bool) {
    bytes32 chkhash = keccak256(
        abi.encodePacked(address(this), bytes5(id))
    );
    bytes3 chkh = bytes3(chkhash);
    bytes3 chki = bytes3(bytes8(uint64(id) &lt;&lt; 40));
    return chkh == chki;
}
```

### The Contract Interface

A contract that follows this ERC:

- `The contract` MUST revert if sent a transaction where `msg.data` is null (A pure value transaction).
- `The contract` MUST have a deposit function as follows:

```solidity
interface DepositEIP {
  function deposit(bytes8 id) external payable returns (bool);
}
```

- `deposit(bytes8)` MUST return `false` when the contract needs to keep the value, but signal to the depositor that the deposit (in terms of the parent application) itself has not yet succeeded. (This can be used for partial payment, ie. the invoice is for 5 ETH, sending 3 ETH returns false, but sending a second tx with 2 ETH will return true.)
- `deposit(bytes8)` MUST revert if the deposit somehow failed and the contract does not need to keep the value sent.
- `deposit(bytes8)` MUST return `true` if the value will be kept and the payment is logically considered complete by the parent application (exchange/merchant).
- `deposit(bytes8)` SHOULD check the checksum contained within the 8 byte id. (See &quot;Deposit Address Format&quot; for an example)
- `The parent application` SHOULD return any excess value received if the deposit id is a one-time-use invoice that has a set value and the value received is higher than the set value. However, this SHOULD NOT be done by sending back to `msg.sender` directly, but rather should be noted in the parent application and the depositor should be contacted out-of-band to the best of the application manager&apos;s ability.

### Depositing Value to the Contract from a Wallet

- `The wallet` MUST accept `the deposit address format` anywhere the 20-byte address format is accepted for transaction destination.
- `The wallet` MUST verify the 3 byte checksum and fail if the checksum doesn&apos;t match.
- `The wallet` MUST fail if the destination address is `the deposit address format` and the `data` field is set to anything besides null.
- `The wallet` MUST set the `to` field of the underlying transaction to the first 20 bytes of the deposit address format, and set the `data` field to `0x3ef8e69aNNNNNNNNNNNNNNNN000000000000000000000000000000000000000000000000` where `NNNNNNNNNNNNNNNN` is the last 8 bytes of the deposit address format. (ie. if the deposit address format is set to `0x433e064c42e87325fb6ffa9575a34862e0052f26913fd924f056cd15` then the `to` field is `0x433e064c42e87325fb6ffa9575a34862e0052f26` and the `data` field is `0x3ef8e69a913fd924f056cd15000000000000000000000000000000000000000000000000`)

## Rationale
The contract interface and address format combination has one notable drawback, which was brought up in discussion. This ERC can only handle deposits for native value (ETH) and not other protocols such as ERC-20. However, this is not considered a problem, because it is best practice to logically AND key-wise separate wallets for separate currencies in any exchange/merchant application for accounting reasons and also for security reasons. Therefore, using this method for the native value currency (ETH) and another method for ERC-20 tokens etc. is acceptable. Any attempt at doing something similar for ERC-20 would require modifying the ERC itself (by adding the id data as a new input argument to the transfer method etc.) which would grow the scope of this ERC too large to manage. However, if this address format catches on, it would be trivial to add the bytes8 id to any updated protocols (though adoption might be tough due to network effects).

The 8 byte size of the id and the checksum 3 : nonce 5 ratio were decided with the following considerations:

- 24 bit checksum is better than the average 15 bit checksum of an EIP-55 address.
- 40 bit nonce allows for over 1 trillion nonces.
- 64 bit length of the id was chosen as to be long enough to support a decent checksum and plenty of nonces, but not be too long. (Staying under 256 bits makes hashing cheaper in gas costs as well.)

## Backwards Compatibility
An address generated with the deposit address format will not be considered a valid address for applications that don&apos;t support it. If the user is technical enough, they can get around lack of support by verifying the checksum themselves, creating the needed data field by hand, and manually input the data field. (assuming the wallet app allows for arbitrary data input on transactions) A tool could be hosted on github for users to get the needed 20 byte address and msg.data field from a deposit address.

Since a contract following this ERC will reject any plain value transactions, there is no risk of extracting the 20 byte address and sending to it without the calldata.

However, this is a simple format, and easy to implement, so the author of this ERC will first implement in web3.js and encourage adoption with the major wallet applications.

## Test Cases
```
[
  {
    &quot;address&quot;: &quot;0x083d6b05729c58289eb2d6d7c1bb1228d1e3f795&quot;,
    &quot;nonce&quot;: &quot;0xbdd769c69b&quot;,
    &quot;depositAddress&quot;: &quot;0x083d6b05729c58289eb2d6d7c1bb1228d1e3f795bdd769c69b3b97b9&quot;
  },
  {
    &quot;address&quot;: &quot;0x433e064c42e87325fb6ffa9575a34862e0052f26&quot;,
    &quot;nonce&quot;: &quot;0x913fd924f0&quot;,
    &quot;depositAddress&quot;: &quot;0x433e064c42e87325fb6ffa9575a34862e0052f26913fd924f056cd15&quot;
  },
  {
    &quot;address&quot;: &quot;0xbbc6597a834ef72570bfe5bb07030877c130e4be&quot;,
    &quot;nonce&quot;: &quot;0x2c8f5b3348&quot;,
    &quot;depositAddress&quot;: &quot;0xbbc6597a834ef72570bfe5bb07030877c130e4be2c8f5b3348023045&quot;
  },
  {
    &quot;address&quot;: &quot;0x17627b07889cd22e9fae4c6abebb9a9ad0a904ee&quot;,
    &quot;nonce&quot;: &quot;0xe619dbb618&quot;,
    &quot;depositAddress&quot;: &quot;0x17627b07889cd22e9fae4c6abebb9a9ad0a904eee619dbb618732ef0&quot;
  },
  {
    &quot;address&quot;: &quot;0x492cdf7701d3ebeaab63b4c7c0e66947c3d20247&quot;,
    &quot;nonce&quot;: &quot;0x6808043984&quot;,
    &quot;depositAddress&quot;: &quot;0x492cdf7701d3ebeaab63b4c7c0e66947c3d202476808043984183dbe&quot;
  }
]
```

## Implementation
A sample implementation with an example contract and address generation (in the tests) is located here:

https://github.com/junderw/deposit-contract-poc

## Security Considerations
In general, contracts that implement the contract interface should forward funds received to the deposit(bytes8) function to their cold wallet account. This address SHOULD be hard coded as a constant OR take advantage of the `immutable` keyword in solidity versions `&gt;=0.6.5`.

To prevent problems with deposits being sent after the parent application is shut down, a contract SHOULD have a kill switch that will revert all calls to deposit(bytes8) rather than using `selfdestruct(address)` (since users who deposit will still succeed, since an external account will receive value regardless of the calldata, and essentially the self-destructed contract would become a black hole for any new deposits)

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 13 Aug 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2876</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2876</guid>
      </item>
    
      <item>
        <title>Staking Reward Calculation</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2925</comments>
        
        <description>## Simple Summary
ERC2917 is a new standardization for on-chain calculation of staking reward.

## Abstract
Based on the product of effective collateral and time, ERC2917 calculates the reward a user can get at any time, and realize the real decentralized DeFi. Here below is the formula for the calculation of reward for a user U:

![concept image](../assets/eip-2917/erc-reward-formula.png &quot;erc-reward-formula&quot;)

where ∆p&lt;sub&gt;i&lt;/sub&gt; denotes individual productivity of the user U between the consecutive block numbers t&lt;sub&gt;i-1&lt;/sub&gt;  and t&lt;sub&gt;i&lt;/sub&gt;, ∆P&lt;sub&gt;i&lt;/sub&gt; denotes global productivity between the consecutive block numbers t&lt;sub&gt;i-1&lt;/sub&gt;  and t&lt;sub&gt;i&lt;/sub&gt;, and ∆G&lt;sub&gt;i&lt;/sub&gt; denotes gross product between the consecutive block numbers t&lt;sub&gt;i-1&lt;/sub&gt;  and t&lt;sub&gt;i&lt;/sub&gt;. The formula ensures that there is no benefit in case of exiting earlier or entering later in the computation. The reward a user can get for a period is based on his total productivity during that specific time. The formula has been simplified through Solidity and generalized design to make it available across all DeFi products. 
We note that the smart contract can be triggered for every computation of on the following events: 	
- whenever the productivity of a user changes (increase/decrease), 
- whenever a user withdraws.

## Motivation

One of the main drawbacks of many DeFi projects is the reward distribution mechanism within the smart contract. In fact, there are two main mechanisms are adopted so far.
1.	Distribution of rewards is only given when all users exit the contract
2.	The project collects on-chain data, conducts calculation off-chain, and sends the results
to the chain before starting rewards distribution accordingly

The first approach conducts all calculation in an on-chain fashion, the cycle of its rewards distribution is too long. Furthermore, users need to remove their collateral before getting the rewards, which can be harmful for their rewards. The second approach is a semi-decentralized model since the main algorithm involves an off-chain computation. Therefore, the fairness and transparency properties cannot be reflected and this can even create the investment barrier for users.

Since there is more DeFi projects coming out everyday, users could not find a proper way  to get to know:
1) amount of interests he/she would get
2) how the interest calculated
3) what is his/her contribution compare to the overall

By standardizing ERC2917, it abstracts the interface for interests generation process. Making wallet applications easier to collect each DeFi&apos;s metrics, user friendlier.

## Specification

Every ERC-2917 compliant contract must implement the ERC2917 and ERC20 interfaces (if necessary):

```solidity
interface IERC2917 is IERC20 {

    /// @dev This emit when interests amount per block is changed by the owner of the contract.
    /// It emits with the old interests amount and the new interests amount.
    event InterestRatePerBlockChanged (uint oldValue, uint newValue);

    /// @dev This emit when a users&apos; productivity has changed
    /// It emits with the user&apos;s address and the value after the change.
    event ProductivityIncreased (address indexed user, uint value);

    /// @dev This emit when a users&apos; productivity has changed
    /// It emits with the user&apos;s address and the value after the change.
    event ProductivityDecreased (address indexed user, uint value);

    
    /// @dev Return the current contract&apos;s interests rate per block.
    /// @return The amount of interests currently producing per each block.
    function interestsPerBlock() external view returns (uint);

    /// @notice Change the current contract&apos;s interests rate.
    /// @dev Note the best practice will be restrict the gross product provider&apos;s contract address to call this.
    /// @return The true/false to notice that the value has successfully changed or not, when it succeed, it will emite the InterestRatePerBlockChanged event.
    function changeInterestRatePerBlock(uint value) external returns (bool);

    /// @notice It will get the productivity of given user.
    /// @dev it will return 0 if user has no productivity proved in the contract.
    /// @return user&apos;s productivity and overall productivity.
    function getProductivity(address user) external view returns (uint, uint);

    /// @notice increase a user&apos;s productivity.
    /// @dev Note the best practice will be restrict the callee to prove of productivity&apos;s contract address.
    /// @return true to confirm that the productivity added success.
    function increaseProductivity(address user, uint value) external returns (bool);

    /// @notice decrease a user&apos;s productivity.
    /// @dev Note the best practice will be restrict the callee to prove of productivity&apos;s contract address.
    /// @return true to confirm that the productivity removed success.
    function decreaseProductivity(address user, uint value) external returns (bool);

    /// @notice take() will return the interests that callee will get at current block height.
    /// @dev it will always calculated by block.number, so it will change when block height changes.
    /// @return amount of the interests that user are able to mint() at current block height.
    function take() external view returns (uint);

    /// @notice similar to take(), but with the block height joined to calculate return.
    /// @dev for instance, it returns (_amount, _block), which means at block height _block, the callee has accumulated _amount of interests.
    /// @return amount of interests and the block height.
    function takeWithBlock() external view returns (uint, uint);

    /// @notice mint the available interests to callee.
    /// @dev once it mint, the amount of interests will transfer to callee&apos;s address.
    /// @return the amount of interests minted.
    function mint() external returns (uint);
}
```

### InterestRatePerBlockChanged

This emit when interests amount per block is changed by the owner of the contract. It emits with the old interests amount and the new interests amount.
 

### ProductivityIncreased

It emits with the user&apos;s address and the value after the change.
 

### ProductivityDecreased

It emits with the user&apos;s address and the value after the change. 

### interestsPerBlock

It returns the amount of interests currently producing per each block.
 
### changeInterestRatePerBlock

Note the best practice will be restrict the gross product provider&apos;s contract address to call this.

The true/false to notice that the value has successfully changed or not, when it succeed, it will emite the InterestRatePerBlockChanged event.
 
### getProductivity

It returns user&apos;s productivity and overall productivity. It returns 0 if user has no productivity proved in the contract. 

### increaseProductivity

It increases a user&apos;s productivity.

### decreaseProductivity

It decreases a user&apos;s productivity.

### take

It returns the interests that callee will get at current block height.

###  takeWithBlock

Similar to take(), but with the block height joined to calculate return.

For instance, it returns (_amount, _block), which means at block height _block, the callee has accumulated _amount of interests.

It returns amount of interests and the block height.

### mint
it mints the amount of interests will transfer to callee&apos;s address. It returns the amount of interests minted.

## Rationale
TBD

## Implementation
The implementation code is on the github:

- [ERC2917 Demo](https://github.com/gnufoo/ERC3000-Proposal)

## Security Considerations
TBD

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 28 Aug 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2917</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2917</guid>
      </item>
    
      <item>
        <title>Chunk-Based Code Merkleization</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2926-chunk-based-code-merkleization/4555</comments>
        
        <description>## Abstract

Code merkleization, along with binarification of the trie and gas cost bump of state-accessing opcodes, are considered as the main levers for decreasing block witness sizes in stateless or partial-stateless Eth1x roadmaps. Here we specify a fixed-sized chunk approach to code merkleization and outline how the transition of existing contracts to this model would look like.

## Motivation

Bytecode is currently the second contributor to block witness size, after the proof hashes. Transitioning the trie from hexary to binary reduces the hash section of the witness by 3x, thereby making code the first contributor. By breaking contract code into chunks and committing to those chunks in a merkle tree, stateless clients would only need the chunks that were touched during a given transaction to execute it.

## Specification

What follows is structured to have two sections:

1. How a given contract code is split into chunks and then merkleized
2. How to merkleize all existing contract codes during a hardfork

### Constants and Definitions

#### Constants

- `CHUNK_SIZE`: 31 (bytes)
- `VERSION_KEY`: `max(u256)`
- `VERSION`: 0
- `EMPTY_CODE_ROOT`: `0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470` (==`keccak256(&apos;&apos;)`)
- `HF_TIMESTAMP`: to be defined
- `ITERATOR_STRIDE`: `TBC` but based on verkle numbers, first devnets should use `50_000`

#### Definitions

- `BE(x, N)`: casts `x` to an unsigned integer of `N` bytes and returns its big-endian representation

### Code merkleization

For an account record `A` with code `C`, two extra optional fields are added: `A.codeSize` and `A.codeRoot`. `A.codeHash` is retained to serve `EXTCODEHASH`.

If `C` is empty, i.e. in the case of an EoA, `A.codeRoot` and `A.codeSize` are omitted from the account&apos;s RLP. This is intended to limit the size overhead of this change.

If `C` is not empty:

 - `A.codeSize = len(code)`
 - `A.codeRoot` contains the root of `codeTrie`, a trie with the following leaves:
   - Key: `VERSION_KEY`, value: `BE(VERSION, 1)`
   - A list of code `chunks = [(FIO_0, code_0), ..., (FIO_n, code_n)]` which are derived from `C` as follows:
     - `code_0 || ... || code_n == C`.
     - `length(code_i) == CHUNK_SIZE` where `0 &lt;= i &lt; n`.
     - `length(code_n) &lt;= CHUNK_SIZE`.
     - `FIO_i` is the offset of the first instruction within the chunk. It should only be greater than zero if the last instruction in `code_i-1` is a multi-byte instruction (like `PUSHN`) crossing the chunk boundary. It is set to `CHUNK_SIZE` in the case where all bytes of a chunk are data.

The `i`th element of `chunks` is stored in `codeTrie` with:

- Key: `BE(i, 4)`
- Value: `BE(FIO_i, 1) || code_i`, where `||` stands for byte-wise concatenation

#### Contract creation gas cost

As of now there is a charge of 200 gas per byte of the code stored in state by contract creation operations, be it initiated via `CREATE`, `CREATE2`, or an external transaction. This per byte cost is to be increased from `200` to `500` to account for the chunking and merkleization costs. This number is inherited from [EIP-4762](/EIPs/EIPS/eip-4762) and is picked for forward-compatibility.

### Updating existing code (transition process)

The transition process involves reading all contracts in the state and applying the above procedure to them. A process similar to [EIP-7612](/EIPs/EIPS/eip-7612) is to be used, as the total code size at the time of this EIP edit is &gt;10GB and can not be processed in a single block.

Note that:

 - Because multiple accounts can share the same code hash, the whole account tree needs to be iterated over to convert each account. Only iterating over the bytecodes isn&apos;t enough.
 - Nonetheless, the conversion process should take a few hours, instead of days for a full tree change.

At `HF_TIMESTAMP` the EIP gets activated:

 - any contract creation and 7702 delegation updates must use the new format.
   - for 7702 accounts, the code size is set to `23`, and `CODESIZE`/`CODECOPY` are forwarded to the delegated account. `EXTCODESIZE`/`EXTCODEHASH`/`EXTCODECOPY` behave the same as they did before the activation of this EIP.
   - accounts are NOT converted in case of a balance or nonce update: accounts are converted by the iterator sweep or automatically at creation time.
 - at the end of block processing, and after all transactions have been executed but before recomputing the tree root hash, the client iterates over `ITERATOR_STRIDE` accounts in the tree, and for each account:
   - if the account has empty code, or is a contract using the new format, leave that account untouched,
   - if the account is a &quot;legacy&quot; contract, convert it and write it back to the tree

The value for `ITERATOR_STRIDE` has been chosen to be safe while ensuring the transition process does not last too long. At the current state size and block time, this represents about 10000 blocks, which is about one and a half day.

Following the transition process described in [EIP-8032](/EIPs/EIPS/eip-8032), the transition process uses a system contract to store its progress pointers. The transition process has been designed in such a way that if both EIPs are activated at the same time, their transition process can be merged. Refer to that EIP for more details.

Note that for a bytecode used by multiple contracts, the chunking need happen only once. Such contract only need to update their code size and code root, which MAY be cached during the transition process.

## Rationale

### Hexary vs binary trie

The trie format is chosen to be the same as that of the account trie. If a tree conversion happens at a later stage, the chunk tree will have to be converted as well, e.g. the way it is in [EIP-6800](/EIPs/EIPS/eip-6800) or [EIP-7864](/EIPs/EIPS/eip-7864).

### Chunk size

The current recommended chunk size of 31 bytes has been selected based on a few observations. Smaller chunks are more efficient (i.e. have higher chunk utilization), but incur a larger hash overhead (i.e. number of hashes as part of the proof) due to a higher trie depth. Larger chunks are less efficient, but incur less hash overhead. We plan to run a larger experiment comparing various chunk sizes to arrive at a final recommendation.

### First instruction offset

The `firstInstructionOffset` field allows safe jumpdest analysis when a client doesn&apos;t have all the chunks, e.g. a stateless clients receiving block witnesses.

Note: there could be an edge case when computing FIO for the chunks where the data bytes at the end of a bytecode (last chunk) resemble a multi-byte instruction. This case can be safely ignored.

### Gas cost of code-accessing opcodes

Details of how the code is stored, is left to the client implementers. However, to reflect the removal of the max code limit and the fact that larger codes will be more expensive to load, reading a non-accessed chunk will incur a 200 warming cost, and chunks written beyond the 24kb limit will cost 500 gas instead of 200.

### Different chunking logic

We have considered an alternative option to package chunks, where each chunk is prepended with its `chunkLength` and would only contain complete opcodes (i.e. any multi-byte opcode not fitting the `CHUNK_SIZE` would be deferred to the next chunk).

This approach has downsides compared to the one specified:

1) Requires a larger `CHUNK_SIZE` -- at least 33 bytes to accommodate the `PUSH32` instruction.
2) It is more wasteful. For example, `DUP1 PUSH32 &lt;32-byte payload&gt;` would be encoded as two chunks, the first chunk contains only `DUP1`, and the second contains only the `PUSH32` instruction with its payload.
3) Calculating the number of chunks is not trivial and would have to be stored explicitly in the metadata.

Additionally we have reviewed many other options (basic block based, Solidity subroutines (requires determining the control flow), EIP-2315 subroutines). This EIP however only focuses on the chunk-based option.

## Backwards Compatibility

From the perspective of contracts, the design aims to be transparent, with the exception of changes in gas costs.

Outside of the interface presented for contracts, this proposal introduces major changes to the way contract code is stored, and needs a substantial modification of the Ethereum state. Therefore it can only be introduced via a hard fork.

## Test Cases

TBD

Show the `codeRoot` for the following cases:

1. `code=&apos;&apos;`
2. `code=&apos;PUSH1(0) DUP1 REVERT&apos;`
3. `code=&apos;PUSH32(-1)&apos;` (data passing through a chunk boundary)

## Security Considerations

TBA

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 25 Aug 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2926</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2926</guid>
      </item>
    
      <item>
        <title>Gas cost increases for state access opcodes</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2929-gas-cost-increases-for-state-access-opcodes/4558</comments>
        
        <description>## Simple Summary

Increases gas cost for `SLOAD`, `*CALL`, `BALANCE`, `EXT*` and `SELFDESTRUCT` when used for the first time in a transaction.

## Abstract

Increase the gas cost of `SLOAD` (`0x54`) to 2100, and the `*CALL` opcode family (`0xf1`, `f2`, `f4`, `fA`), `BALANCE` `0x31` and the `EXT*` opcode family (`0x3b`, `0x3c`, `0x3f`) to 2600. Exempts (i) precompiles, and (ii) addresses and storage slots that have already been accessed in the same transaction, which get a decreased gas cost. Additionally reforms `SSTORE` metering and `SELFDESTRUCT` to ensure &quot;de-facto storage loads&quot; inherent in those opcodes are priced correctly.

## Motivation

Generally, the main function of gas costs of opcodes is to be an estimate of the time needed to process that opcode, the goal being for the gas limit to correspond to a limit on the time needed to process a block. However, storage-accessing opcodes (`SLOAD`, as well as the `*CALL`, `BALANCE` and `EXT*` opcodes) have historically been underpriced. In the 2016 Shanghai DoS attacks, once the most serious client bugs were fixed, one of the more durably successful strategies used by the attacker was to simply send transactions that access or call a large number of accounts.

Gas costs were increased to mitigate this, but recent numbers suggest they were not increased enough. Quoting [https://arxiv.org/pdf/1909.07220.pdf](https://arxiv.org/pdf/1909.07220.pdf): 

&gt; Although by itself, this issue might seem benign, `EXTCODESIZE` forces the  client to search the contract ondisk, resulting in IO heavy transactions.  While replaying the Ethereum history on our hardware, the malicious transactions took around 20 to 80 seconds to execute, compared to a few milliseconds for the average transactions

This proposed EIP increases the costs of these opcodes by a factor of ~3, reducing the worst-case processing time to ~7-27 seconds. Improvements in database layout that involve redesigning the client to read storage directly instead of hopping through the Merkle tree would decrease this further, though these technologies may take a long time to fully roll out, and even with such technologies the IO overhead of accessing storage would remain substantial.

A secondary benefit of this EIP is that it also performs most of the work needed to make [stateless witness sizes](https://ethereum-magicians.org/t/protocol-changes-to-bound-witness-size/3885) in Ethereum acceptable. Assuming [a switch to binary tries](https://ethresear.ch/t/binary-trie-format/7621), the theoretical maximum witness size not including code size (hence &quot;most of the work&quot; and not &quot;all&quot;) would decrease from `(12500000 gas limit) / (700 gas per BALANCE) * (800 witness bytes per BALANCE) ~= 14.3M bytes` to `12500000 / 2600 * 800 ~= 3.85M bytes`. Pricing for code access could be changed when code merklization is implemented.

In the further future, there are similar benefits in the case of SNARK/STARK witnesses. Recent numbers from Starkware suggest that they are able to prove 10000 Rescue hashes per second on a consumer desktop; assuming 25 hashes per Merkle branch, and a block full of state accesses, at present this would imply a witness would take `12500000 / 700 * 25 / 10000 ~= 44.64` seconds to generate, but after this EIP that would reduce to `12500000 / 2500 * 25 / 10000 ~= 12.5` seconds, meaning that a single desktop computer would be able to generate witnesses on time under any conditions. Future gains in STARK proving could be spent on either (i) using a more expensive but robust hash function or (ii) reducing proving times further, reducing the delay and hence improving user experience of stateless clients that rely on such witnesses.

## Specification

### Parameters

| Constant | Value |
| - | - |
| `FORK_BLOCK` | 12244000 |
| `COLD_SLOAD_COST` | 2100 |
| `COLD_ACCOUNT_ACCESS_COST` | 2600 |
| `WARM_STORAGE_READ_COST` | 100 |

For blocks where `block.number &gt;= FORK_BLOCK`, the following changes apply.

When executing a transaction, maintain a set `accessed_addresses: Set[Address]` and `accessed_storage_keys: Set[Tuple[Address, Bytes32]]` . 

The sets are transaction-context-wide, implemented identically to other transaction-scoped constructs such as the self-destruct-list and global `refund` counter. In particular, if a scope reverts, the access lists should be in the state they were in before that scope was entered. 

When a transaction execution begins, 
  - `accessed_storage_keys` is initialized to empty, and
  - `accessed_addresses` is initialized to include
    - the `tx.sender`, `tx.to` (or the address being created if it is a contract creation transaction)
    - and the set of all precompiles.


### Storage read changes

When an address is either the target of a (`EXTCODESIZE` (`0x3B`), `EXTCODECOPY` (`0x3C`), `EXTCODEHASH` (`0x3F`) or `BALANCE` (`0x31`)) opcode or the target of a (`CALL` (`0xF1`), `CALLCODE` (`0xF2`), `DELEGATECALL` (`0xF4`), `STATICCALL` (`0xFA`)) opcode, the gas costs are computed as follows:

* If the target is not in `accessed_addresses`, charge `COLD_ACCOUNT_ACCESS_COST` gas, and add the address to `accessed_addresses`.
* Otherwise, charge `WARM_STORAGE_READ_COST` gas.

In all cases, the gas cost is charged and the map is updated at the time that the opcode is being called. 
When a `CREATE` or `CREATE2` opcode is called, immediately (ie. before checks are done to determine whether or not the address is unclaimed) add the address being created to `accessed_addresses`, but gas costs of `CREATE` and `CREATE2` are unchanged.
Clarification: If a `CREATE`/`CREATE2` operation fails later on, e.g during the execution of `initcode` or has insufficient gas to store the code in the state, the `address` of the contract itself remains in `access_addresses` (but any additions made within the inner scope are reverted). 

For `SLOAD`, if the `(address, storage_key)` pair (where `address` is the address of the contract whose storage is being read) is not yet in `accessed_storage_keys`, charge `COLD_SLOAD_COST` gas and add the pair to `accessed_storage_keys`. If the pair is already in `accessed_storage_keys`, charge `WARM_STORAGE_READ_COST` gas.

Note: For call-variants, the `100`/`2600` cost is applied immediately (exactly like how `700` was charged before this EIP), i.e: before calculating the `63/64ths` available for entering the call. 

Note 2: There is currently no way to perform a &apos;cold sload read/write&apos; on a &apos;cold account&apos;, simply because in order to read/write a `slot`, the execution must already be inside the `account`. Therefore, the behaviour of cold  storage reads/writes on cold accounts is undefined as of this EIP. Any future EIP which 
proposes to add &apos;remote read/write&apos; would need to define the pricing behaviour of that change.

### SSTORE changes

When calling `SSTORE`, check if the `(address, storage_key)` pair is in `accessed_storage_keys`. If it is not, charge an additional `COLD_SLOAD_COST` gas, and add the pair to `accessed_storage_keys`. Additionally, modify the parameters defined in [EIP-2200](/EIPs/EIPS/eip-2200) as follows:

| Parameter | Old value | New value |
| - | - | - |
| `SLOAD_GAS` | 800 | `= WARM_STORAGE_READ_COST` |
| `SSTORE_RESET_GAS` | 5000 | `5000 - COLD_SLOAD_COST` |

The other parameters defined in EIP 2200 are unchanged.
Note: The constant `SLOAD_GAS` is used in several places in EIP 2200, e.g `SSTORE_SET_GAS - SLOAD_GAS`. Implementations that are using composite definitions have to ensure to update those definitions too.

### SELFDESTRUCT changes

If the ETH recipient of a `SELFDESTRUCT` is not in `accessed_addresses` (regardless of whether or not the amount sent is nonzero), charge an additional `COLD_ACCOUNT_ACCESS_COST` on top of the existing gas costs, and add the ETH recipient to the set.

Note: `SELFDESTRUCT` does not charge a `WARM_STORAGE_READ_COST` in case the recipient is already warm, which differs from how the other call-variants work. The reasoning behind this is to keep the changes small, a `SELFDESTRUCT` already costs `5K` and is a no-op if invoked more than once. 

## Rationale

### Opcode costs vs charging per byte of witness data

The natural alternative path to changing gas costs to reflect witness sizes is to charge per byte of witness data. However, that would take a longer time to implement, hampering the goal of providing short-term security relief. Furthermore, following that path faithfully would lead to extremely high gas costs to transactions that touch contract code, as one would need to charge for all 24576 contract code bytes; this would be an unacceptably high burden on developers. It is better to wait for [code merklization](https://medium.com/ewasm/evm-bytecode-merklization-2a8366ab0c90) to start trying to properly account for gas costs of accessing individual chunks of code; from a short-term DoS prevention standpoint, accessing 24 kB from disk is not much more expensive than accessing 32 bytes from disk, so worrying about code size is not necessary.

### Adding the accessed_addresses / accessed_storage_keys sets

The sets of already-accessed accounts and storage slots are added to avoid needlessly charging for things that can be cached (and in all performant implementations already are cached). Additionally, it removes the current undesirable status quo where it is needlessly unaffordable to do self-calls or call precompiles, and enables contract breakage mitigations that involve pre-fetching some storage key allowing a future execution to still take the expected amount of gas.

### SSTORE gas cost change

The change to SSTORE is needed to avoid the possibility of a DoS attack that &quot;pokes&quot; a randomly chosen zero storage slot, changing it from 0 to 0 at a cost of 800 gas but requiring a de-facto storage load. The `SSTORE_RESET_GAS` reduction ensures that the total cost of SSTORE (which now requires paying the `COLD_SLOAD_COST`) remains unchanged. Additionally, note that applications that do `SLOAD` followed by `SSTORE` (eg. `storage_variable += x`) _would actually get cheaper_!

### Change SSTORE accounting only minimally

The SSTORE gas costs continue to use Wei Tang&apos;s original/current/new approach, instead of being redesigned to use a dirty map, because Wei Tang&apos;s approach correctly accounts for the actual costs of changing storage, which only care about current vs final value and not intermediate values.

### How would gas consumption of average applications increase under this proposal?

#### Rough analysis from witness sizes

We can look at [Alexey Akhunov&apos;s earlier work](https://medium.com/@akhounov/data-from-the-ethereum-stateless-prototype-8c69479c8abc) for data on average-case blocks. In summary, average blocks have witness sizes of ~1000 kB, of which ~750 kB is Merkle proofs and not code. Assuming a conservative 2000 bytes per Merkle branch this implies ~375 accesses per block (SLOADs have a similar gas-increase-to-bytes ratio so there&apos;s no need to analyze them separately).

Data on [txs per day](https://etherscan.io/chart/tx) and [blocks per day](https://etherscan.io/chart/blocks) from Etherscan gives ~160 transactions per block (reference date: Jul 1), implying a large portion of those accesses are just the `tx.sender` and `tx.to` which are excluded from gas cost increases, though likely less than 320 due to duplicate addresses.

Hence, this implies ~50-375 chargeable accesses per block, and each access suffers a gas cost increase of 1900; `50 * 1900 = 95000` and `375 * 1900 = 712500`, implying the gas limit would need to be raised by ~1-6% to compensate. However, this analysis may be complicated further in either direction by (i) accounts / storage keys being accessed in multiple transactions, which would appear once in the witness but twice in gas cost increases, and (ii) accounts / storage keys being accessed multiple times in the same transaction, which lead to gas cost _decreases_.

#### Goerli analysis

A more precise analysis can be found by scanning Goerli transactions, as done by Martin Swende here: https://github.com/holiman/gasreprice

The conclusion is that on average gas costs increase by ~2.36%. One major contributing factor to reducing gas costs is that a large number of contracts inefficiently read the same storage slot multiple times, which leads to this EIP giving a few transactions gas cost _savings_ of over 10%.

## Backwards Compatibility

These gas cost increases may potentially break contracts that depend on fixed gas costs; see the security considerations section for details and arguments for why we expect the total risks to be low and how if desired they can be reduced further.

## Test Cases

Some test cases can be found here: https://gist.github.com/holiman/174548cad102096858583c6fbbb0649a

Ideally we would test the following:

* SLOAD the same storage slot {1, 2, 3} times
* CALL the same address {1, 2, 3} times
* (SLOAD | CALL) in a sub-call, then revert, then (SLOAD | CALL) the same (storage slot | address) again
* Sub-call, SLOAD, sub-call again, revert the inner sub-call, SLOAD the same storage slot
* SSTORE the same storage slot {1, 2, 3} times, using all combinations of zero/nonzero for original value and the value being set
* SSTORE then SLOAD the same storage slot
* `OP_1` then `OP_2` to the same address where `OP_1` and `OP_2` are all combinations of (`*CALL`, `EXT*`, `SELFDESTRUCT`) 
* Try to `CALL` an address but with all possible failure modes (not enough gas, not enough ETH...), then (`CALL` | `EXT*`) that address again successfully

## Implementation

A WIP early-draft implementation for Geth can be found here: https://github.com/holiman/go-ethereum/tree/access_lists

## Security Considerations

As with any gas cost increasing EIP, there are three possible cases where it could cause applications to break:

1. Fixed gas limits to sub-calls in contracts
2. Applications relying on contract calls that consume close to the full gas limit
3. The 2300 base limit given to the callee by ETH-transferring calls

These risks have been studied before in the context of an earlier gas cost increase, EIP-1884. See [Martin Swende&apos;s earlier report](https://github.com/holiman/eip-1884-security) and [Hubert Ritzdorf&apos;s analysis](https://gist.github.com/ritzdorf/1c6bd72955391e831f8a397d3152b4e0/) focusing on (1) and (3). (2) has received less analysis, though one can argue that it is very unlikely both because applications tend to very rarely use close to the entire gas limit in a transaction, and because gas limits were very recently raised from 10 million to 12.5 million. EIP-1884 in practice [did lead to a small number of contracts breaking](https://www.coindesk.com/ethereums-istanbul-upgrade-will-break-680-smart-contracts-on-aragon) for this reason.

There are two ways to look at these risks. First, we can note that as of today developers have had years of warning; gas cost increases on storage-accessing opcodes have been [discussed for a long time](https://ethereum-magicians.org/t/protocol-changes-to-bound-witness-size/3885), with multiple statements made including to major dapp developers around the likelihood of such changes. EIP-1884 itself provided an important wake-up call. Hence, we can argue that risks this time will be significantly lower than EIP-1884.

### Contract breakage mitigations

A second way to look at the risks is to explore mitigations. First of all, the existence of an `accessed_addresses` and `accessed_storage_keys` map (present in this EIP, absent in EIP-1884) already makes some cases recoverable: in any case where a contract A needs to send funds to some address B, where that address accepts funds from any source but leaves a storage-dependent log, one can recover by first sending a separate call to B to pull it into the cache, and then call A, knowing that the execution of B triggered by A will only charge 100 gas per SLOAD. This fact does not fix all situations, but it does reduce risks significantly.

But there are ways to further expand the usability of this pattern. One possibility is to add a `POKE` precompile, which would take an address and a storage key as input and allow transactions that attempt to &quot;rescue&quot; stuck contracts by pre-poking all of the storage slots that they will access. This works even if the address only accepts transactions from the contract, and works in many other contexts with present gas limits. The only case where this will not work would be the case where a transaction call _must_ go from an EOA straight into a specific contract that then sub-calls another contract.

Another option is [EIP-2930](/EIPs/EIPS/eip-2930), which would have a similar effect to `POKE` but is more general: it also works for the EOA -&gt; contract -&gt; contract case, and generally should work for all known cases of breakage due to gas cost increases. This option is more complex, though it is arguably a stepping stone toward access lists being used for other use cases (regenesis, account abstraction, SSA all demand access lists).

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 01 Sep 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2929</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2929</guid>
      </item>
    
      <item>
        <title>Optional access lists</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2930-optional-access-lists/4561</comments>
        
        <description>## Simple Summary

Adds a transaction type which contains an access list, a list of addresses and storage keys that the transaction plans to access. Accesses outside the list are possible, but become more expensive.

## Abstract

We introduce a new [EIP-2718](/EIPs/EIPS/eip-2718) transaction type, with the format `0x01 || rlp([chainId, nonce, gasPrice, gasLimit, to, value, data, accessList, signatureYParity, signatureR, signatureS])`.

The `accessList` specifies a list of addresses and storage keys; these addresses and storage keys are added into the `accessed_addresses` and `accessed_storage_keys` global sets (introduced in [EIP-2929](/EIPs/EIPS/eip-2929)). A gas cost is charged, though at a discount relative to the cost of accessing outside the list.

## Motivation

This EIP serves two functions:

1. Mitigates contract breakage risks introduced by [EIP-2929](/EIPs/EIPS/eip-2929), as transactions could pre-specify and pre-pay for the accounts and storage slots that the transaction plans to access; as a result, in the actual execution, the SLOAD and EXT* opcodes would only cost 100 gas: low enough that it would not only prevent breakage due to that EIP but also &quot;unstuck&quot; any contracts that became stuck due to EIP 1884.
2. Introduces the access list format and the logic for handling the format. This logic can later be repurposed for many other purposes, including block-wide witnesses, use in ReGenesis, moving toward static state access over time, and more.

## Specification

### Definitions

**`TransactionType`** `1`.  See [EIP-2718](/EIPs/EIPS/eip-2718)

**`ChainId`** The transaction only valid on networks with this `chainID`.

**`YParity`** The parity (0 for even, 1 for odd) of the y-value of a secp256k1 signature.


### Parameters

| Constant | Value |
| - | - |
| `FORK_BLOCK` | 12244000 |
| `ACCESS_LIST_STORAGE_KEY_COST` | 1900 |
| `ACCESS_LIST_ADDRESS_COST` | 2400 |

As of `FORK_BLOCK_NUMBER`, a new [EIP-2718](/EIPs/EIPS/eip-2718) transaction is introduced with `TransactionType` `1`.

The [EIP-2718](/EIPs/EIPS/eip-2718) `TransactionPayload` for this transaction is `rlp([chainId, nonce, gasPrice, gasLimit, to, value, data, accessList, signatureYParity, signatureR, signatureS])`.

The `signatureYParity, signatureR, signatureS` elements of this transaction represent a secp256k1 signature over `keccak256(0x01 || rlp([chainId, nonce, gasPrice, gasLimit, to, value, data, accessList]))`.

The [EIP-2718](/EIPs/EIPS/eip-2718) `ReceiptPayload` for this transaction is `rlp([status, cumulativeGasUsed, logsBloom, logs])`.

For the transaction to be valid, `accessList` must be of type `[[{20 bytes}, [{32 bytes}...]]...]`, where `...` means &quot;zero or more of the thing to the left&quot;. For example, the following is a valid access list (all hex strings would in reality be in byte representation):

```
[
    [
        &quot;0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae&quot;,
        [
            &quot;0x0000000000000000000000000000000000000000000000000000000000000003&quot;,
            &quot;0x0000000000000000000000000000000000000000000000000000000000000007&quot;
        ]
    ],
    [
        &quot;0xbb9bc244d798123fde783fcc1c72d3bb8c189413&quot;,
        []
    ]
]
```

At the beginning of execution (ie. at the same time as the `21000 + 4 * zeroes + 16 * nonzeroes` start gas is charged according to [EIP-2028](/EIPs/EIPS/eip-2028) rules), we charge additional gas for the access list: `ACCESS_LIST_ADDRESS_COST` gas per address and `ACCESS_LIST_STORAGE_KEY_COST` gas per storage key. For example, the above example would be charged `ACCESS_LIST_ADDRESS_COST * 2 + ACCESS_LIST_STORAGE_KEY_COST * 2` gas.

Note that non-unique addresses and storage keys are not disallowed, though they will be charged for multiple times, and aside from the higher gas cost there is no other difference in execution flow or outcome from multiple-inclusion of a value as opposed to the recommended single-inclusion.

The address and storage keys would be immediately loaded into the `accessed_addresses` and `accessed_storage_keys` global sets; this can be done using the following logic (which doubles as a specification-in-code of validation of the RLP-decoded access list)

```python
def process_access_list(access_list) -&gt; Tuple[List[Set[Address], Set[Pair[Address, Bytes32]]], int]:
    accessed_addresses = set()
    accessed_storage_keys = set()
    gas_cost = 0
    assert isinstance(access_list, list)
    for item in access_list:
        assert isinstance(item, list) and len(item) == 2
        # Validate and add the address
        address = item[0]
        assert isinstance(address, bytes) and len(address) == 20
        accessed_addresses.add(address)
        gas_cost += ACCESS_LIST_ADDRESS_COST
        # Validate and add the storage keys
        assert isinstance(item[1], list)
        for key in item[1]:
            assert isinstance(key, bytes) and len(key) == 32
            accessed_storage_keys.add((address, key))
            gas_cost += ACCESS_LIST_STORAGE_KEY_COST
    return (
        accessed_addresses,
        accessed_storage_keys,
        gas_cost
    )
```

The access list is NOT charged per-byte fees like tx data is; the per-item costs described above are meant to cover the bandwidth costs of the access list data in addition to the costs of accessing those accounts and storage keys when evaluating the transaction.

## Rationale

### Charging less for accesses in the access list

This is done to encourage transactions to use the access list as much as possible, and because processing transactions is easier when their storage reads are predictable (because clients can pre-load the data from databases and/or ask for witnesses at the time the transaction is received, or at least load the data in parallel).

### Allowing duplicates

This is done because it maximizes simplicity, avoiding questions of what to prevent duplication against: just between two addresses/keys in the access list, between the access list and the tx sender/recipient/newly created contract, other restrictions? Because gas is charged per item, there is no gain and only cost in including a value in the access list twice, so this should not lead to extra chain bloat in practice.

### Signature signs over the transaction type as well as the transaction data

This is done to ensure that the transaction cannot be &quot;re-interpreted&quot; as a transaction of a different type.

## Backwards Compatibility

This EIP does make it more gas-expensive to perform &quot;unexpected&quot; SLOADs and account accesses. Because gas is prepaid and so does not affect fixed-gas local calls, it does not break contracts in the way that previous gas cost increases would risk. However, it does make applications that heavily rely on storage access much less economically viable.

## Security Considerations

### Access list generation

Access lists are difficult to construct in real-time in many situations, and this is exacerbated in environments where there is a high time lag between transaction generation and signing or simplicity of the transaction generator is highly valued (eg. either or both may apply in hardware wallets).

However, this EIP proposes only a 10% initial discount to access lists, so there is almost no cost to not bothering with access list generation and only making a simple transaction. The cost of accessing state outside the access list is expected to be ramped up in future hard forks over time as tools are developed and access list generation becomes more mature.

### Transaction size bloating

Average block size will increase as a result of access lists being used. However, the per-byte cost of access lists is `1900 / 32 = 59.375` for storage keys and `2400 / 20 = 120` for addresses, making it much more expensive than calldata; hence, worst-case block size will not increase. Additionally, increases in average block size will be partially compensated for by the ability to pre-fetch storage at time of receiving a transaction and/or load storage in parallel upon receiving a block.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 29 Aug 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2930</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2930</guid>
      </item>
    
      <item>
        <title>Serve historical block hashes from state</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2935-save-historical-block-hashes-in-state/4565</comments>
        
        <description>## Abstract

Store last `HISTORY_SERVE_WINDOW` historical block hashes in the storage of a system contract as part of the block processing logic. Furthermore this EIP has no impact on `BLOCKHASH` resolution mechanism (and hence its range/costs etc).

## Motivation

EVM implicitly assumes the client has the recent block (hashes) at hand. This assumption is not future-proof given the prospect of stateless clients. Including the block hashes in the state will allow bundling these hashes in the witness provided to a stateless client. This is already possible in the MPT and will become more efficient post-Verkle.

Extending the range of blocks which `BLOCKHASH` can serve (`BLOCKHASH_SERVE_WINDOW`) would have been a semantics change. Using extending that via this contract storage would allow a soft-transition. Rollups can benefit from the longer history window through directly querying this contract.

A side benefit of this approach could be that it allows building/validating proofs related to last `HISTORY_SERVE_WINDOW` ancestors directly against the current state.

## Specification

| Parameter | Value |
| - | - |
| `BLOCKHASH_SERVE_WINDOW`  | `256` |
| `HISTORY_SERVE_WINDOW`    | `8191` |
| `SYSTEM_ADDRESS`          | `0xfffffffffffffffffffffffffffffffffffffffe` |
| `HISTORY_STORAGE_ADDRESS` | `0x0000F90827F1C53a10cb7A02335B175320002935` |

This EIP specifies for storing last `HISTORY_SERVE_WINDOW` block hashes in a ring buffer storage of `HISTORY_SERVE_WINDOW` length. Note that `HISTORY_SERVE_WINDOW` &gt; `BLOCKHASH_SERVE_WINDOW` (which remains unchanged).

### Block processing

At the start of processing any block where this EIP is active (ie. before processing any transactions), call to `HISTORY_STORAGE_ADDRESS` as `SYSTEM_ADDRESS` with the 32-byte input of `block.parent.hash`, a gas limit of `30_000_000`, and `0` value. This will trigger the `set()` routine of the history contract. This is a system operation following the same convention as [EIP-4788](/EIPs/EIPS/eip-4788) and therefore:

* the call must execute to completion
* the call does not count against the block&apos;s gas limit
* the call does not follow the [EIP-1559](/EIPs/EIPS/eip-1559) burn semantics - no value should be transferred as part of the call
* if no code exists at `HISTORY_STORAGE_ADDRESS`, the call must fail silently

Note: Alternatively clients can choose to directly write to the storage of the contract but EVM calling the contract remains preferred. Refer to the rationale for more info.

Note that, it will take `HISTORY_SERVE_WINDOW` blocks after the EIP&apos;s activation to completely fill up the ring buffer. The contract will only contain the parent hash of the fork block and no hashes prior to that.


### EVM Changes

The `BLOCKHASH` opcode semantics remains the same as before.

### Block hash history contract

The history contract has two operations: `get` and `set`. The `set` operation is invoked only when the `caller` is equal to the `SYSTEM_ADDRESS` as per [EIP-4788](/EIPs/EIPS/eip-4788). Otherwise the `get` operation is performed.

#### `get`

It is used from the EVM for looking up block hashes.

* Callers provide the block number they are querying in a big-endian encoding.
* If calldata is not 32 bytes, revert.
* For any request outside the range of [block.number-`HISTORY_SERVE_WINDOW`, block.number-1], revert.

#### `set`

* Caller provides `block.parent.hash` as calldata to the contract.
* Set the storage value at `block.number-1 % HISTORY_SERVE_WINDOW` to be `calldata[0:32]`.

#### Bytecode

Exact evm assembly that can be used for the history contract:

```
// https://github.com/lightclient/sys-asm/blob/f1c13e285b6aeef2b19793995e00861bf0f32c9a/src/execution_hash/main.eas
caller
push20 0xfffffffffffffffffffffffffffffffffffffffe
eq
push1 0x46
jumpi
push1 0x20
calldatasize
sub
push1 0x42
jumpi
push0
calldataload
push1 0x01
number
sub
dup2
gt
push1 0x42
jumpi
push2 0x1fff
dup2
number
sub
gt
push1 0x42
jumpi
push2 0x1fff
swap1
mod
sload
push0
mstore
push1 0x20
push0
return
jumpdest
push0
push0
revert
jumpdest
push0
calldataload
push2 0x1fff
push1 0x01
number
sub
mod
sstore
stop
```

#### Deployment

A special synthetic address is generated by working backwards from the desired deployment transaction:

```json
{
  &quot;type&quot;: &quot;0x0&quot;,
  &quot;nonce&quot;: &quot;0x0&quot;,
  &quot;to&quot;: null,
  &quot;gas&quot;: &quot;0x3d090&quot;,
  &quot;gasPrice&quot;: &quot;0xe8d4a51000&quot;,
  &quot;maxPriorityFeePerGas&quot;: null,
  &quot;maxFeePerGas&quot;: null,
  &quot;value&quot;: &quot;0x0&quot;,
  &quot;input&quot;: &quot;0x60538060095f395ff33373fffffffffffffffffffffffffffffffffffffffe14604657602036036042575f35600143038111604257611fff81430311604257611fff9006545f5260205ff35b5f5ffd5b5f35611fff60014303065500&quot;,
  &quot;v&quot;: &quot;0x1b&quot;,
  &quot;r&quot;: &quot;0x539&quot;,
  &quot;s&quot;: &quot;0xaa12693182426612186309f02cfe8a80a0000&quot;,
  &quot;hash&quot;: &quot;0x67139a552b0d3fffc30c0fa7d0c20d42144138c8fe07fc5691f09c1cce632e15&quot;
}
```

Note, the input in the transaction has a simple constructor prefixing the desired runtime code.

The sender of the transaction can be calculated as `0x3462413Af4609098e1E27A490f554f260213D685`. The address of the first contract deployed from the account is `rlp([sender, 0])` which equals `0x0000F90827F1C53a10cb7A02335B175320002935`. This is how `HISTORY_STORAGE_ADDRESS` is determined. Although this style of contract creation is not tied to any specific initcode like create2 is, the synthetic address is cryptographically bound to the input data of the transaction (e.g. the initcode).


Some activation scenarios:

 * For the fork to be activated at genesis, no history is written to the genesis state, and at the start of block `1`, genesis hash will be written as a normal operation to slot `0`.
 * for activation at block `1`, only genesis hash will be written at slot `0`.
 * for activation at block `32`, block `31`&apos;s hash will be written to slot `31`. Every other slot will be `0`.

### [EIP-161](/EIPs/EIPS/eip-161) handling

The bytecode above will be deployed à la [EIP-4788](/EIPs/EIPS/eip-4788). As such the account at `HISTORY_STORAGE_ADDRESS` will have code and a nonce of 1, and will be exempt from EIP-161 cleanup.

### Gas costs

The system update at the beginning of the block, i.e. `process_block_hash_history` (or via system call to the contract with `SYSTEM_ADDRESS` caller), will not warm the `HISTORY_STORAGE_ADDRESS` account or its storage slots as per [EIP-2929](/EIPs/EIPS/eip-2929) rules. As such the first call to the contract will pay for warming up the account and storage slots it accesses.To clarify further any contract call to the `HISTORY_STORAGE_ADDRESS` will follow normal EVM execution semantics.

Since `BLOCKHASH` semantics doesn&apos;t change, this EIP has no impact on `BLOCKHASH` mechanism and costs.

## Rationale

Very similar ideas were proposed before. This EIP is a simplification, removing two sources of needless complexity:

1. Having a tree-like structure with multiple layers as opposed to a single list
2. Writing the EIP in EVM code
3. Serial unbounded storage of hashes for a deep access to the history

However after weighing pros and cons, we decided to go with just a limited ring buffer to only serve the requisite `HISTORY_SERVE_WINDOW` as [EIP-4788](/EIPs/EIPS/eip-4788) and beacon state accumulators allow (albeit a bit more complex) proof against any ancestor since merge.

Second concern was how to best transition the BLOCKHASH resolution logic post fork by:

1. Either waiting for  `HISTORY_SERVE_WINDOW` blocks for the entire relevant history to persist
2. Storing of all last `HISTORY_SERVE_WINDOW` block hashes on the fork block.

We choose to go with the former. It simplifies the logic greatly. It will take roughly a day to bootstrap the contract. Given that this is a new way of accessing history and no contract depends on it, it is deemed a favorable tradeoff.

### Inserting the parent block hash

Clients have generally two options for inserting the parent block hash into state:

1. Performing a system call to `HISTORY_STORAGE_ADDRESS` and letting that handle the storing in state.
2. Avoid EVM processing and directly write to the state trie.

The latter option is as follows:

```python
def process_block_hash_history(block: Block, state: State):
    if block.timestamp &gt;= FORK_TIMESTAMP: // FORK_TIMESTAMP should be defined outside of the EIP
        state.insert_slot(HISTORY_STORAGE_ADDRESS, (block.number-1) % HISTORY_SERVE_WINDOW , block.parent.hash)
```

The first option is recommended until the Verkle fork, to stay consistent with [EIP-4788](/EIPs/EIPS/eip-4788) and to issues for misconfigured networks where this EIP is activated but history contract hasn&apos;t been deployed. The recommendation may be reconsidered at the Verkle fork if filtering the system contract code chunks is deemed too complex.

### Size of ring buffers

The ring buffer data structure is sized to hold 8191 hashes. In other system contracts a prime ring buffer size is chosen in because using a prime as the modulus ensures that no value is overwritten until the entire ring buffer has been saturated and thereafter, each value will be updated once per iteration, regardless of if some slot are missing or the slot time changes. However, in this EIP the block number is the value in the modulo operation and it only ever increases by 1 each iteration. Which means we can be confident that the ring buffer will always remain saturated.

For consistency with other system contracts, we have decided to retain the buffer size of 8191. Given the current mainnet values, 8191 roots provides about a day of coverage. This also gives users plenty of time to make a transaction with a verification against a specific hash and get the transaction included on-chain.

## Backwards Compatibility

This EIP introduces backwards incompatible changes to the block validation rule set. But neither of these changes break anything related to current user activity and experience.

## Test Cases

[EIP-2935 Execution Spec Tests](https://github.com/ethereum/execution-spec-tests/tree/3810d22f84f206866f66f4f6bf856187c2893ab1/tests/prague/eip2935_historical_block_hashes_from_state)

## Security Considerations

Having contracts (system or otherwise) with hot update paths (branches) poses a risk of &quot;branch&quot; poisoning attacks where attacker could sprinkle trivial amounts of eth around these hot paths (branches). But it has been deemed that cost of attack would escalate significantly to cause any meaningful slow down of state root updates.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 03 Sep 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2935</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2935</guid>
      </item>
    
      <item>
        <title>EXTCLEAR Opcode For SELFDESTRUCTed contracts</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2936-extclear-for-selfdestruct/4569</comments>
        
        <description>## Simple Summary
Enable new opcode to clear storage for `SELFDESTRUCTED`ed contracts.

## Abstract
Changes `SELFDESTRUCT` (`0xff`) to not clear any storage and adds a new `EXTCLEAR` (`0x5c`) opcode that will clear a specific storage slot for a contract that has previously been self destructed.

## Motivation
`SELFDESTRUCT` (`0xFF`) is unnecessarily complex because it clears an unbounded amount of contract storage.
It is computationally expensive for nodes to track all of the storage used in every contract in case the contract `SELFDESTRUCT`s.
Further, contracts can be re-initialized using `CREATE2` (`0xF5`), and then `SLOAD` (`0x54`) prior storage.
Therefore, several ethereum clients do not clear storage at all, and just check if the contract was initiated since `SSTORE` (`0x55`) during `SLOAD`.
`CREATE2` was not intended to complicate `SLOAD`, and this change reverts that complexity.
Also, bugs in this implementation could split the network.

Instead this defers the time of storage cleanup, and leaves the storage in-place, which reduces the complexity of `SLOAD` and `SELFDESTRUCT`.

This empowers the `CREATE2` reincarnation proxy pattern by retaining storage during upgrade, which would otherwise have to be reset again.
An atomic reincarnation upgrade could clear a subset of storage during the upgrade, while the contract is destroyed, before reinstating it.

## Specification

After `FORK_BLOCK_NUM`, a new opcode, `EXTCLEAR`, is enabled at `0x5C` to clear storage for `SELFDESTRUCT`ed contracts.
`EXTCLEAR`:
* does not push any words onto the stack
* pops two words off the stack: the destroyed contract address and a storage address
* if the contract exists, charge the same gas cost as `EXTCODEHASH` (`0x3F`)
* otherwise, if the storage is zero, charge the same gas as `EXTCODEHASH` plus `SLOAD`
* otherwise, the destroyed contract&apos;s slot is reset to 0, charging the same gas as `EXTCODEHASH` and `SSTORE` when resetting storage, while also refunding the amount specified in `SSTORE`.

`SELFDESTRUCT` is modified to not clear contract storage.
This change also works retroactively: all prior destroyed contracts can be cleaned up.

## Rationale
`0x5C` is available in the same range as `SSTORE` and `SLOAD`.

## Backwards Compatibility
A reincarnation upgrade mechanism that expects all internal storage to be cleared might break, but such an upgrade mechanism would allow adaptation to this new behavior.

## Test Cases
TODO

## Implementation
Implementation is required on all major clients to add the opcode.

## Security Considerations
A reincarnated contract that does not expect its state to be cleared by malicious actors SHOULD reinitialize itself to avoid antagonistic `EXTCLEAR`.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 03 Sep 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2936</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2936</guid>
      </item>
    
      <item>
        <title>SET_INDESTRUCTIBLE opcode</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2937-set-indestructible/4571</comments>
        
        <description>## Simple Summary

Add a `SET_INDESTRUCTIBLE (0xA8)` opcode that prevents the contract from calling `SELFDESTRUCT (0xFF)`.

## Abstract

## Motivation

The intended use case would be for contracts to make their first byte of code be the `SET_INDESTRUCTIBLE` opcode if they wish to serve as libraries that guarantee to users that their code will exist unmodified forever. This is useful in account abstraction as well as other contexts.

Unlike EIPs that disable the `SELFDESTRUCT` opcode entirely, this EIP does not modify behavior of any existing contracts.

## Specification

Add a transaction-wide global variable `globals.indestructible: Set[Address]` (i.e. a variable that operates the same way as the selfdestructs set), initialized to the empty set.

Add a `SET_INDESTRUCTIBLE` opcode at `0xA8`, with gas cost `G_base`, that adds the current `callee` to the `globals.indestructible` set. If in the current execution context the `callee` is in `globals.indestructible`, the `SELFDESTRUCT` opcode throws an exception.

## Rationale

Alternative proposals to this include:

* Simply banning `SELFDESTRUCT` outright. This would be ideal, but has larger backwards compatibility issues.
* Using a local variable instead of a global variable. This is problematic because it would be broken by `DELEGATECALL`.

## Backwards Compatibility

TBD

## Security Considerations

This breaks forward compatibility with _some_ forms of state rent, which would simply delete contracts that get too old without paying some maintenance fee. However, this is not the case with all state size control schemes; for example this is not an issue if we use [ReGenesis](https://ledgerwatch.github.io/regenesis_plan.html).

If `SELFDESTRUCT` is ever removed in the future, this EIP would simply become a no-op.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 04 Sep 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2937</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2937</guid>
      </item>
    
      <item>
        <title>Account Abstraction</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2938-account-abstraction/4630</comments>
        
        <description>## Simple Summary

Account abstraction (AA) allows a contract to be the top-level account that pays fees and starts transaction execution.

## Abstract

**See also: [https://ethereum-magicians.org/t/implementing-account-abstraction-as-part-of-eth1-x/4020](https://ethereum-magicians.org/t/implementing-account-abstraction-as-part-of-eth1-x/4020) and the links therein for historical work and motivation.**

Transaction validity, as of Muir Glacier, is defined rigidly by the protocol: ECDSA signature, a simple nonce, and account balance. Account abstraction extends the validity conditions of transactions with the execution of arbitrary EVM bytecode (with some limits on what state may be accessed.) To signal validity, we propose a new EVM opcode `PAYGAS`, which also sets the gas price and gas limit the contract is willing to pay.

We split account abstraction into two tiers: **single-tenant AA**, which is intended to support wallets or other use cases with few participants, and **multi-tenant AA**, which is intended to support applications with many participants (eg. tornado.cash, Uniswap).

## Motivation

The existing limitations preclude innovation in a number of important areas, particularly:

1. Smart contract wallets that use signature verification other than ECDSA (eg. Schnorr, BLS, post-quantum...)
2. Smart contract wallets that include features such as multisig verification or social recovery, reducing the highly prevalent risk of funds being lost or stolen
3. Privacy-preserving systems like [tornado.cash](http://tornado.cash)
4. Attempts to improve gas efficiency of DeFi protocols by preventing transactions that don&apos;t satisfy high-level conditions (eg. existence of a matching order) from being included on chain
5. Users being able to pay for transaction fees in a token other than ETH (eg. by converting that token into the ETH needed for fees inside the transaction in real-time)

Most of the above use cases are currently possible using intermediaries, most notably the [Gas Station Network](https://www.opengsn.org/) and application-specific alternatives. These implementations are (i) technically inefficient, due to the extra 21000 gas to pay for the relayer, (ii) economically inefficient, as relayers need to make a profit on top of the gas fees that they pay. Additionally, use of intermediary protocols means that these applications cannot simply rely on base Ethereum infrastructure and need to rely on extra protocols that have smaller userbases and higher risk of no longer being available at some future date.

Out of the five use cases above, single-tenant AA approximately supports (1) and (2), and multi-tenant AA approximately supports (3) and (4). We discuss the differences between the two tiers in the specification and rationale sections below.

## Specification

### Single Tenant

After `FORK_BLOCK`, the following changes will be recognized by the protocol.

#### Constants

| Constant | Value |
| - | - |
| **`AA_ENTRY_POINT`** | `0xffffffffffffffffffffffffffffffffffffffff` |
| **`AA_TX_TYPE`** | `2` |
| **`FORK_BLOCK`** | TBD |
| **`AA_BASE_GAS_COST`** | 15000 |

#### New Transaction Type

A new [EIP-2718](/EIPs/EIPS/eip-2718) transaction with type `AA_TX_TYPE` is introduced. Transactions of this type are referred to as &quot;AA transactions&quot;. Their payload should be interpreted as `rlp([nonce, target, data])`.

The base gas cost of this transaction is set to `AA_BASE_GAS_COST` instead of 21000 to reflect the lack of &quot;intrinsic&quot; ECDSA and signature.

Nonces are processed analogously to existing transactions (check `tx.nonce == tx.target.nonce`, transaction is invalid if this fails, otherwise proceed and immediately set `tx.nonce += 1`).

Note that this transaction type has no intrinsic gas limit; when beginning execution, the gas limit is simply set to the remaining gas in the block (ie. `block.gas_limit` minus gas spent on previous transactions), and the `PAYGAS` opcode (see below) can adjust the gas limit downwards.

#### Transaction-wide global variables

Introduce some new transaction-wide global variables. These variables work similarly (in particular, have similar reversion logic) to the SSTORE refunds counter.

| Variable | Type | Initial value |
| - | - | - |
| `globals.transaction_fee_paid` | `bool` | `False if type(tx) == AA_TX_TYPE else True` |
| `globals.gas_price` | `int` | `0 if type(tx) == AA_TX_TYPE else tx.gas_price` |
| `globals.gas_limit` | `int` | `0 if type(tx) == AA_TX_TYPE else tx.gas_limit` |

#### `NONCE (0x48)` Opcode

A new opcode `NONCE (0x48)` is introduced, with gas cost `G_base`, which pushes the `nonce` of the callee onto the stack.

#### `PAYGAS (0x49)` Opcode

A new opcode `PAYGAS (0x49)` is introduced, with gas cost `G_base`. It takes two arguments off the stack: (top) `version_number`, (second from top) `memory_start`. In the initial implementation, it will `assert version_number == 0` and read:

* `gas_price = bytes_to_int(vm.memory[memory_start: memory_start + 32])`
* `gas_limit = bytes_to_int(vm.memory[memory_start + 32: memory_start + 64])`

Both reads use similar mechanics to MLOAD and CALL, so memory expands if needed.

Future hard forks may add support for different version numbers, in which case the opcode may take different-sized memory slices and interpret them differently. Two particular potential use cases are [EIP 1559](https://notes.ethereum.org/@vbuterin/BkSQmQTS8) and [the escalator mechanism](https://ethresear.ch/t/another-simple-gas-fee-model-the-escalator-algorithm-from-the-agoric-papers/6399).

The opcode works as follows. If all three of the following conditions (in addition to the version number check above) are satisfied:

1. The account&apos;s balance is `&gt;= gas_price * gas_limit`
2. `globals.transaction_fee_paid == False`
3. We are in a top-level AA execution frame (ie. if the currently running EVM execution exits or reverts, the EVM execution of the entire transaction is finished)

Then do the following:

* Subtract `gas_price * gas_limit` from the contract&apos;s balance
* Set `globals.transaction_fee_paid` to `True`
* Set `globals.gas_price` to `gas_price`, and `globals.gas_limit` to `gas_limit`
* Set the remaining gas in the current execution context to equal `gas_limit` minus the gas that was already consumed

If any of the above three conditions are not satisfied, throw an exception.

At the end of execution of an AA transaction, it is mandatory that `globals.transaction_fee_paid == True`; if it is not, then the transaction is invalid. At the end of execution, the contract is refunded `globals.gas_price * remaining_gas` for any remaining gas, and `(globals.gas_limit - remaining_gas) * globals.gas_price` is transferred to the miner.

`PAYGAS` also serves as an EVM execution _checkpoint_: if the top-level execution frame reverts after `PAYGAS` has been called, then the execution only reverts up to the point right after `PAYGAS` was called, and exits there. In that case, the contract receives no refund, and `globals.gas_limit * globals.gas_price` is transferred to the miner.

#### Replay Protection

One of the two following approaches must be implemented to safeguard against replay attacks.

##### Require `SET_INDESTRUCTIBLE`

Require that contracts targeted by AA transactions begin with [EIP-2937]&apos;s `SET_INDESTRUCTIBLE` opcode. AA transactions targeting contracts that do not begin with `SET_INDESTRUCTIBLE` are invalid, and cannot be included in blocks.

`AA_PREFIX` would need to be modified to include this opcode.

[EIP-2937]: /EIPs/EIPS/eip-2937

##### Preserve Nonce on `SELFDESTRUCT`

The other option is to preserve contract nonces across `SELFDESTRUCT` invocations, instead of setting the nonce to zero.

#### Miscellaneous

* If `CALLER (0x33)` is invoked in the first frame of
  execution of a call initiated by an AA transaction, then it must return `AA_ENTRY_POINT`.
* If `ORIGIN (0x32)` is invoked in any frame of execution of an AA
  transaction it must return `AA_ENTRY_POINT`.
* The `GASPRICE (0x3A)` opcode now pushes the value `globals.gas_price`

Note that the new definition of `GASPRICE` does not lead to any changes in behavior in non-AA transactions, because `globals.gas_price` is initialized to `tx.gas_price` and cannot be changed as `PAYGAS` cannot be called.

#### Mining and Rebroadcasting Strategies

Much of the complexity in account abstraction originates from the strategies used by miners and validating nodes to determine whether or not to accept and rebroadcast transactions. Miners need to determine if a transaction will actually pay the fee if they include it after only a small amount of processing to avoid [DoS attacks](https://hackingdistributed.com/2016/06/28/ethereum-soft-fork-dos-vector/). Validating nodes need to perform an essentially identical verification to determine whether or not to rebroadcast the transaction.

By keeping the consensus changes minimal, this EIP allows for gradual introduction of AA mempool support by miners and validating nodes. Initial support would be focused on enabling simple, single-tenant use cases, while later steps would additionally allow for more complex, multi-tenant use cases. Earlier stages are deliberately more fully fleshed-out than later stages, as there is still more time before later stages need to be implemented.

##### Transactions with Fixed Nonces

| Constant | Value |
| - | - |
| `VERIFICATION_GAS_MULTIPLIER` | `6` |
| `VERIFICATION_GAS_CAP` | `= VERIFICATION_GAS_MULTIPLIER * AA_BASE_GAS_COST = 90000` |
| `AA_PREFIX` | `if(msg.sender != shr(-1, 12)) { LOG1(msg.sender, msg.value); return }`; compilation to EVM TBD |

When a node receives an AA transaction, they process it (i.e. attempt to execute it against the current chain head&amp;#39;s post-state) to determine its validity, continuing to execute until one of several events happens:

* If the code of the `target` is NOT prefixed with `AA_PREFIX`, exit with failure
* If the execution hits any of the following, exit with failure:
    * An environment opcode (`BLOCKHASH`, `COINBASE`, `TIMESTAMP`, `NUMBER`, `DIFFICULTY`, `GASLIMIT`)
    * `BALANCE` (of any account, including the `target` itself)
    * An external call/create that changes the `callee` to anything but the `target` or a precompile (`CALL`, `CALLCODE`, `STATICCALL`, `CREATE`, `CREATE2`).
    * An external state access that reads code (`EXTCODESIZE`, `EXTCODEHASH`, `EXTCODECOPY`, but also `CALLCODE` and `DELEGATECALL`), unless the address of the code that is read is the `target`.
* If the execution consumes more gas than `VERIFICATION_GAS_CAP` (specified above), or more gas than is available in the block, exit with failure
* If the execution reaches `PAYGAS`, then exit with success or failure depending on whether or not the balance is sufficient (e.g. `balance &gt;= gas_price * gas_limit`).

Nodes do not keep transactions with nonces higher than the current valid nonce in the mempool. If the mempool already contains a transaction with a currently valid nonce, another incoming transaction to the same contract and with the same nonce either replaces the existing one (if its gas price is sufficiently higher) or is dropped. Thus, the mempool keeps only at most one pending transaction per account.

While processing a new block, take note of which accounts were the `target` of an AA transaction (each block currently has `12500000` gas and an AA transaction costs `&gt;= 15000` so there would be at most `12500000 // 15000 = 833` targeted accounts). Drop all pending transactions targeting those accounts. All other transactions remain in the mempool.

### Single Tenant+

If the [indestructible contracts EIP](http://github.com/ethereum/EIPs/pull/2937) is added, Single Tenant AA can be adapted to allow for `DELEGATECALL` during transaction verification: during execution of a new AA transaction, external state access that reads code (`EXTCODESIZE`, `EXTCODEHASH`, `EXTCODECOPY`, `CALLCODE`, `DELEGATECALL`) of any contract whose first byte is the `SET_INDESTRUCTIBLE` opcode is no longer banned. However, calls to anything but the `target` or a precompile that change the `callee` (i.e., calls other than `CALLCODE` and `DELEGATECALL`) are still not permitted.

If the [IS_STATIC EIP](http://github.com/ethereum/EIPs/pull/2975) is added, the list of allowed prefixes can be extended to allow a prefix that enables incoming static calls but not state-changing calls.

The list of allowed prefixes can also be extended to enable other benign use cases (eg. logging incoming payments).

External calls _into_ AA accounts can be allowed as follows. We can add an opcode `RESERVE_GAS`, which takes as argument a value `N` and has simple behavior: immediately burn `N` gas and add `N` gas to the refund. We then add an allowed `AA_PREFIX` that reserves `&gt;= AA_BASE_GAS_COST * 2` gas. This ensures that at least `AA_BASE_GAS_COST` gas must be spent (as refunds can refund max 50% of total consumption) in order to call into an account and invalidate transactions targeting that account in the mempool, preserving that invariant.

Note that accounts may also opt to set a higher `RESERVE_GAS` value in order to safely have a higher `VERIFICATION_GAS_CAP`; the goal would be to preserve a `VERIFICATION_GAS_MULTIPLIER`-to-1 ratio between the minimum gas cost to edit an account (ie. half its `RESERVE_GAS`) and the `VERIFICATION_GAS_CAP` that is permitted that account. This would also preserve invariants around maximum reverification gas consumption that are implied by the previous section.

### Multi-Tenant &amp; Beyond

In a later stage, we can add support for multiple pending transactions per account in the mempool. The main challenge here is that a single transaction can potentially cause state changes that invalidate all other transactions to that same account. Additionally, if we naively prioritize transactions by gasprice, there is an attack vector where the user willing to pay the highest gasprice publishes many (mutually exclusive) versions of their transaction with small alterations, thereby pushing everyone else&apos;s transactions out of the mempool.

Here is a sketch of a strategy for mitigating this problem. We would require incoming transactions to contain an [EIP-2930](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2930.md)-style access list detailing the storage slots that the transaction reads or modifies, and make it binding; that is, accesses outside the access list would be invalid. A transaction would only be included in the mempool if its access list is disjoint from the access lists of other transactions in the mempool (or if its gasprice is higher). An alternative way to think about this is to have per-storage-slot mempools instead of just per-account mempools, except a transaction could be part of multiple per-storage-slot mempools (if desired it could be capped to eg. 5 storage slots).

Note also that multi-tenant AA will almost certainly require allowing miners to edit the nonces of incoming transactions to put them into sequence, with the result that the final hash of a transaction is unpredictable at publication time. Clients will need to explicitly work around this.

More research is required to refine these ideas, and this is left for later work.

## Rationale

The core problem in an account abstraction setup is always that miners and network nodes need to be able to verify that a transaction that they attempt to include, or rebroadcast, will actually pay a fee. Currently, this is fairly simple, because a transaction is guaranteed to be includable and pay a fee as long as the signature and nonce are valid and the balance and gasprice are sufficient. These checks can be done quickly.

In an account abstraction setup, the goal is to allow accounts to specify EVM code that can establish more flexible conditions for a transaction&apos;s validity, but with the requirement that this EVM code can be quickly verified, with the same safety properties as the existing setup.

In a normal transaction, the top-level call goes from the `tx.sender` to `tx.to` and carries with it `tx.value`. In an AA transaction, the top-level call goes from the _entry point address_ (`0xFFFF...FF`) to the `tx.target`.

The top-level code execution is expected to be split into two phases: the shorter **verification phase** (before `PAYGAS`) and the longer **execution phase** (after `PAYGAS`). If execution throws an exception during the verification phase, the transaction is invalid, much like a transaction with an invalid signature in the current system. If execution throws an exception after the verification phase, the transaction pays fees, and so the miner can still include it.

The transition between different stages of AA is entirely done through changes in miner strategy. The first stage supports **single-tenant AA**, where the only use cases that can be easily implemented are where the `tx.target` is a contract representing a user account (that is, a smart contract wallet, eg. multisig). Later stages improve support for eg. logs and libraries, and also move toward supporting **multi-tenant AA**, where the goal is to try to support cases where the `tx.target` represents an _application_ that processes incoming activity from multiple users.

### Nonces still enshrined in single-tenant AA

Nonces are still enforced in single-tenant AA to ensure that single-target AA does not break the invariant that each transaction (and hence each transaction hash) can only be included in the chain once. While there is some limited value in allowing arbitrary-order transaction inclusion in single-tenant AA, there is not enough value to justify breaking that invariant.

Note that nonces in AA accounts do end up having a dual-purpose: they are both there for replay protection and for contract address generation when using the `CREATE` opcode. This does mean that a single transaction could increment the nonce by more than 1. This is deemed acceptable, as the other mechanics introduced by AA already break the ability to easily verify that a chain longer than one transaction can be processed. However, we strongly recommend that AA contracts use `CREATE2` instead of `CREATE`.

In multi-tenant AA, as mentioned above, nonces are expected to become malleable and applications that use multi-tenant AA systems would need to manage this.

### Nonces are exposed to the EVM

This is done to allow signature checking done in validation code to validate the nonce.

### Replay Protection

One of the above two approaches (requiring `SET_INDESTRUCTIBLE` or modifying `SELFDESTRUCT` behavior) must be implemented so that nonces cannot be reused. It must be a consensus change, and not simply part of `AA_PREFIX`, so that transaction hash uniqueness is maintained.

### Miners refuse transactions that access external data or the target&apos;s own balance, before PAYGAS

An important property of traditional transactions is that activity happening as part of transactions that originate outside of some given account X cannot make transactions whose sender is X invalid. The only state change that an outside transaction can impose on X is increasing its balance, which cannot invalidate a transaction.

Allowing AA contracts to access external data (both other accounts and environment variables such as GASPRICE, DIFFICULTY, etc.) before they call `PAYGAS` (ie. during the verification phase) breaks this invariant. For example, imagine someone sends many thousands of AA transactions that perform an external call `if FOO.get_number() != 5: throw()`. `FOO.number` might be set to `5` when those transactions are all sent, but a single transaction to `FOO` could set the `number` to something else, invalidating _all of the thousands of AA transactions_ that depend on it. This would be a serious DoS vector.

The one allowed exception is contracts that are indestructible (that is, whose first byte is the `SET_INDESTRUCTIBLE` opcode defined in [this EIP](https://hackmd.io/@HWeNw8hNRimMm2m2GH56Cw/SyNT3Cdmw)). This is a safe exception, because the data that is being read cannot be changed.

Disallowing reading `BALANCE` blocks a milder attack vector: an attacker could force a transaction to be reprocessed at a mere cost of 6700 gas (not 15000 or 21000), in the worst case more than doubling the number of transactions that would need to be reprocessed.

In the long term, AA could be expanded to allow reading external data, though protections such as mandatory access lists would be required.

### AA transactions must call contracts with prefix

The prelude is used to ensure that *only* AA transactions can call the contract. This is another measure taken to ensure the invariant described above. If this check did not occur, it would be possible for a transaction originating outside some AA account X to call into X and make a storage change, forcing transactions targeting that account to be reprocessed at the cost of a mere 5000 gas.

### Multi-tenant AA

Multi-tenant AA extends single-tenant AA by **better handling cases where distinct and uncoordinated users attempt to send transactions for/to the same account and those transactions may interfere with each other**.

We can understand the value of multi-tenant AA by examining two example use cases: (i) [tornado.cash](http://tornado.cash) and (ii) [Uniswap](http://uniswap.exchange). In both of these cases, there is a single central contract that represents the application, and not any specific user. Nevertheless, there is important value in using abstraction to do application-specific validation of transactions.

#### Tornado Cash

The tornado.cash workflow is as follows:

1. A user sends a transaction to the TC contract, depositing some standard quantity of coins (eg. 1 ETH). A record of their deposit, containing the hash of a secret known by the user, is added to a Merkle tree whose root is stored in the TC contract.
2. When that user later wants to withdraw, they generate and send a ZK-SNARK proving that they know a secret whose hash is in a leaf somewhere in the deposit tree (without revealing where). The TC contract verifies the ZK-SNARK, and also verifies that a nullifier value (also derivable from the secret) has not yet been spent. The contract sends 1 ETH to the user&apos;s desired address, and saves a record that the user&apos;s nullifier has been spent.

The privacy provided by TC arises because when a user makes a withdrawal, they can prove that it came from _some_ unique deposit, but no one other than the user knows which deposit it came from. However, implementing TC naively has a fatal flaw: the user usually does not yet have ETH in their withdrawal address, and if the user uses their deposit address to pay for gas, that creates an on-chain link between their deposit address and their withdrawal address.

Currently, this is solved via relayers; a third-party relayer verifies the ZK-SNARK and unspent status of the nullifier, publishes the transaction using their own ETH to pay for gas, and collects the fee back from the user from the TC contract.

AA allows this without relayers: the user could simply send an AA transaction targeting the TC contract, the ZK-SNARK verification and the nullifier checking can be done in the verification step, and PAYGAS can be called directly after that. This allows the withdrawer to pay for gas directly out of the coins going to their withdrawal address, avoiding the need for relayers or for an on-chain link to their deposit address.

Note that fully implementing this functionality requires AA to be structured in a way that supports multiple users sending withdrawals at the same time (requiring nonces would make this difficult), and that allows a single account to support both AA transactions (the withdrawals) and externally-initiated calls (the deposits).

#### Uniswap

A new version of Uniswap could be built that allows transactions to be sent that directly target the Uniswap contract. Users could deposit tokens into Uniswap ahead of time, and Uniswap would store their balances as well as a public key that transactions spending those balances could be verified against. An AA-initiated Uniswap trade would only be able to spend these internal balances.

This would be useless for normal traders, as normal traders have their coins outside the Uniswap contract, but it would be a powerful boon to arbitrageurs. Arbitrageurs would deposit their coins into Uniswap, and they would be able to send transactions that perform arbitrage every time external market conditions change, and logic such as price limits could be enforced during the verification step. Hence, transactions that do not get in (eg. because some other arbitrageur made the trade first) would not be included on-chain, allowing arbitrageurs to not pay gas, and reducing the number of &quot;junk&quot; transactions that get included on-chain. This could significantly increase both de-facto blockchain scalability as well as market efficiency, as arbitrageurs would be able to much more finely correct for cross-exchange discrepancies between prices.

Note that here also, Uniswap would need to support both AA transactions and externally-initiated calls.

## Backwards Compatibility

This AA implementation preserves the existing transaction type. The use of `assert origin == caller` to verify that an account is an EOA remains sound, but is not extensible to AA accounts; AA transactions will always have `origin == AA_ENTRY_POINT`.

Badly-designed single-tenant AA contracts will break the transaction non-malleability invariant. That is, it is possible to take an AA transaction in-flight, modify it, and have the modified version still be valid; AA account contracts can be designed in such a way as to make that not possible, but it is their responsibility. Multi-tenant AA will break the transaction non-malleability invariant much more thoroughly, making the transaction hash unpredictable even for legitimate applications that use the multi-tenant AA features (though the invariant will not further break for applications that existed before then).

AA contracts may not have replay protection unless they build it in explicitly; this can be done with the `CHAINID (0x46)` opcode introduced in [EIP 1344](/EIPs/EIPS/eip-1344).

## Test Cases
See: [https://github.com/quilt/tests/tree/account-abstraction](https://github.com/quilt/tests/tree/account-abstraction)

## Implementation
See: [https://github.com/quilt/go-ethereum/tree/account-abstraction](https://github.com/quilt/go-ethereum/tree/account-abstraction)

## Security Considerations

See [https://ethresear.ch/t/dos-vectors-in-account-abstraction-aa-or-validation-generalization-a-case-study-in-geth/7937](https://ethresear.ch/t/dos-vectors-in-account-abstraction-aa-or-validation-generalization-a-case-study-in-geth/7937) for an analysis of DoS issues.

### Re-validation

When a transaction enters the mempool, the client is able to quickly ascertain whether the transaction is valid. Once it determines this, it can be confident that the transaction will continue to be valid unless a transaction from the same account invalidates it.

There are, however, cases where an attacker can publish a transaction that invalidates existing transactions and requires the network to perform more recomputation than the computation in the transaction itself. The EIP maintains the invariant that recomputation is bounded to a theoretical maximum of six times the block gas limit in a single block; this is somewhat more expensive than before, but not that much more expensive.

#### Peer denial-of-service

Denial-of-Service attacks are difficult to defend against, due to the difficulty in identifying sybils within a peer list. At any moment, one may decide (or be bribed) to initiate an attack. This is not a problem that Account Abstraction introduces. It can be accomplished against existing clients today by inundating a target with transactions whose signatures are invalid. However, due to the increased allotment of validation work allowed by AA, it&apos;s important to bound the amount of computation an adversary can force a client to expend with invalid transactions. For this reason, it&apos;s best for the miner to follow the recommended mining strategies.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 04 Sep 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2938</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2938</guid>
      </item>
    
      <item>
        <title>EthPM URI Specification</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/ethpm-v3-specification-working-group/4086/7</comments>
        
        <description>## Simple Summary
A custom URI scheme to identify an EthPM registry, package, release, or specific contract asset within a release.

## Abstract
When interacting with the EthPM ecosystem, users and tooling can benefit from a URI scheme to identify EthPM assets. Being able to specify a package, registry, or release with a single string makes simplifies the steps required to install, publish, or distribute EthPM packages.

## Specification
`scheme://registry_address[:chain_id][/package_name[@package_version[/json_pointer]]]`

#### `scheme`
- Required
- Must be one of `ethpm` or `erc1319`. If future versions of the EthPM registry standard are designed and published via the ERC process, those ERCs will also be valid schemes.

#### `registry_address`
- Required
- This **SHOULD** be either an ENS name or a 0x-prefixed, checksummed address. ENS names are more suitable for cases where mutability of the underlying asset is acceptable and there is implicit trust in the owner of the name. 0x prefixed addresses are more preferable in higher security cases to avoid needing to trust the controller of the name.

#### `chain_id`
- Optional
- Integer representing the chain id on which the registry is located
- If omitted, defaults to `1` (mainnet).

#### `package_name`
- Optional
- String of the target package name

#### `package_version`
- Optional
- String of the target package version
- If the package version contains any [url unsafe characters](https://en.wikipedia.org/wiki/Percent-encoding), they **MUST** be safely escaped
- Since semver is not strictly enforced by the ethpm spec, if the `package_version` is omitted from a uri, tooling **SHOULD** avoid guessing in the face of any ambiguity and present the user with a choice from the available versions.

#### `json_pointer`
- Optional
- A path that identifies a specific asset within a versioned package release.
- This path **MUST** conform to the [JSON pointer](https://tools.ietf.org/html/rfc6901) spec and resolve to an available asset within the package.

## Rationale
Most interactions within the EthPM ecosystem benefit from a single-string representation of EthPM assets; from installing a package, to identifying a registry, to distributing a package. A single string that can faithfully represent any kind of EthPM asset, across the mainnet or testnets, reduces the mental overload for new users, minimizes configuration requirements for frameworks, and simplifies distribution of packages for package authors.

## Test Cases
A JSON file for testing various URIs can be found in the [`ethpm-spec`](https://github.com/ethpm/ethpm-spec/) repository fixtures.

## Implementation
The EthPM URI scheme has been implemented in the following libraries:
- [Brownie](https://eth-brownie.readthedocs.io/en/stable/)
- [Truffle](https://www.trufflesuite.com/docs/truffle/overview)
- [EthPM CLI](https://ethpm-cli.readthedocs.io/en/latest/)

## Security Considerations
In most cases, an EthPM URI points to an immutable asset, giving full security that the target asset has not been modified. However, in the case where an EthPM URI uses an ENS name as its registry address, it is possible that the ENS name has been redirected to a new registry, in which case the guarantee of immutability no longer exists.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 04 Sep 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2942</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2942</guid>
      </item>
    
      <item>
        <title>IS_STATIC opcode</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/is-static-opcode-useful-for-aa/4609</comments>
        
        <description>## Simple Summary

Add a `IS_STATIC (0x4A)` opcode that pushes `1` if the current context is static (ie. the execution is in a `STATICCALL` or a descendant thereof, so state-changing operations are not possible), and `0` if it is not.

## Abstract

## Motivation

The main intended use case is to allow account abstraction (EIP 2938) to be extended so that accounts can allow static calls from the outside (which are harmless to AA&apos;s security model) but not state-changing calls.

## Specification

Add a `IS_STATIC (0x4A)` opcode that pushes `1` if the current context is static (ie. the execution is in a `STATICCALL` or a descendant thereof, so state-changing operations are not possible), and `0` if it is not.

## Rationale

Determining staticness is already possibly using the following hacky technique: make a `CALL` with limited gas, and inside that `CALL` issue one `LOG` and exit. If the context is static, the `CALL` would fail and leave a 0 on the stack; if the context is non-static, the `CALL` would succeed. However, this technique is fragile against changes to gas costs, and is needlessly wasteful. Hence, the status quo neither allows a reasonably effective way of determining whether or not the context is static, nor provides any kind of invariant that executions that do not fail outright will execute the same way in a static and non-static context. This EIP provides a cleaner way of determining staticness.

## Backwards Compatibility

TBD

## Security Considerations

TBD

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 13 Sep 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2970</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2970</guid>
      </item>
    
      <item>
        <title>Wrapped Legacy Transactions</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2972-wrapped-legacy-transactions/4604</comments>
        
        <description>## Simple Summary
Two new transaction types for wrapping legacy transactions with and without a chain ID.

## Abstract
Introduces two new [EIP-2718](/EIPs/EIPS/eip-2718) transactions that are signature compatible with legacy transactions and can be automatically upgraded by any client.

* `0x00 || ssz.serialize(yParity, r, s, rlp([nonce, gasPrice, gasLimit, to, value, data]))`
* `0x01 || ssz.serialize(yParity, r, s, rlp([nonce, gasPrice, gasLimit, to, value, data, chainId, 0, 0]))`

## Motivation
We would like to eventually deprecate legacy transactions so we no longer have to retain code in the networking and signer layer that deals with them.
However, we also want to ensure that signatures for transactions that were generated prior to that deprecation are still valid and funds don&apos;t end up stuck because of an inability to sign a new style transaction.
This EIP provides a mechanism for transmitting/including transactions in a way that is [EIP-2718](/EIPs/EIPS/eip-2718) compatible while still being signature compatible with legacy transactions.

## Specification
### Definitions
* `||` is the byte/byte-array concatenation operator.
* `yParity` is the parity (0 for even, 1 for odd) of the `y` value of the curve point for which `r` is the `x` value in the secp256k1 signing process.

### Transactions
As of `FORK_BLOCK_NUMBER`, `0x00 || ssz.serialize(yParity, r, s, rlp([nonce, gasPrice, gasLimit, to, value, data]))` will be a valid transaction where:
* the RLP encoded transaction portion is signed/processed/handled exactly the same as legacy transactions were signed/processed/handled, with the exception of the final encoding
* TODO: Hashing or Merkleizing for block transaction root

As of `FORK_BLOCK_NUMBER`, `0x01 || ssz.serialize(yParity, r, s, rlp([nonce, gasPrice, gasLimit, to, value, data, chainId, 0, 0]))` will be a valid transaction where:
* the RLP encoded transaction portion is signed/processed/handled exactly the same as legacy transactions were signed/processed/handled, with the exception of the final encoding
* TODO: Hashing or Merkleizing for block transaction root

The SSZ schema for both transaction types is:
  ```
  Transaction[
    yParity: boolean,
    r: bytes32,
    s: bytes32,
    signedData: bytes,
  ]
  ```

Note: `sszencode(yParity, r, s, rlp(...))` is the same as `yParity || r || s || 0x45000000 || rlp(...)`

As of `FORK_BLOCK_NUMBER`, `rlp(nonce, gasPrice, gasLimit, to, value, data, v, r, s)` will no longer be a valid transaction in a block.

### Receipts
As of `FORK_BLOCK_NUMBER`, `0 || ssz.serialize(status, cumulativeGasUsed, logsBloom, logs)` will be a valid receipt where:
* the `ReceiptPayload` will be generated/processed/handled exactly the same as legacy receipts were processed/handled with the exception of its encoding
* TODO: Hashing or Merkleizing for block receipt root

As of `FORK_BLOCK_NUMBER`, `1 || ssz.serialize(status, cumulativeGasUsed, logsBloom, logs)` will be a valid receipt where:
* the `ReceiptPayload` will be generated/processed/handled exactly the same as legacy receipts were processed/handled with the exception of its encoding
* TODO: Hashing or Merkleizing for block receipt root

The SSZ schema for both receipt types is:
```
Log[
  address: bytes20,
  topics: List[bytes32, 4],
  data: List[uint8, 0xffffff],
]
Receipt[
  status: uint8,
  cumulativeGasUsed: uint64,
  logsBloom: BitVector[2048],
  logs: List[Log, 0xffffff],
]
```

As of `FORK_BLOCK_NUMBER`, `rlp(status, cumulativeGasUsed, logsBloom, logs)` will no longer be a valid receipt in a block.

## Rationale
### Signature doesn&apos;t include transaction type as first signature byte
These transaction types are explicitly designed to be signature compatible with legacy transactions, which means we cannot change the data being signed.
See Security Considerations section for more details.
### Two transaction types instead of one
With the introduction of typed transactions, we no longer need to do bit packing to avoid changing the shape of the signature.
Legacy transactions introduced chain ID in [EIP-155](/EIPs/EIPS/eip-155) and wanted to avoid changing the transaction array length, so it bitpacked the chainID into the signature&apos;s `v` value.
Since we no longer need to guarantee consistent payload lengths between transaction types, we have opted to have two transaction types with clear fields.
### Signature separate from signed data
When validating a signature, one must first separate out the signed data from the signature and then validate the signature against the signed data.
In the case of legacy transactions, this was a bit of a burden since you had to first RLP decode the transaction, then extract out the signature, then RLP encode a subset of the transaction.
EIP-155 made this process even worse by requiring the validator to further decode the `v` signature value to extract the chain ID (if present) and include that in the signed data payload.
By having the signed data encoded exactly as it is signed, we make it so one can verify the transaction&apos;s signature without having to do any decoding before hand.
By having the signature SSZ encoded up front, we can easily extract the signature without even having to use a decoder.
### SSZ for serialization
There is a weak consensus that RLP is not a particularly good encoding scheme for hashed data partially due to its inability to be streamed.
SSZ is almost certainly going to be included in Ethereum at some point in the future, so clients likely have access to an SSZ decoder.
For this particular case, manual decoding without a full SSZ decoder isn&apos;t too complicated, though it does require doing a bit of &quot;pointer math&quot; since `logs` is an array of variable length items.
### Deprecating legacy transactions
By deprecating legacy transactions, we make it easier for clients as they can always deal with typed transactions in blocks.
### Max length of logs and logs data
[EIP-706](/EIPs/EIPS/eip-706) limits devp2p messages to 24 bit length, which gives us a pragmatic cap at that for any single transaction at the moment.
This number seems to far exceed what is reasonable anytime in the near future, so feels like as reasonable of a cap as any.

## Backwards Compatibility
The new transactions are signature compatible with legacy transactions.
Legacy transactions can be decoded and then encoded as type 0 or type 1 transactions.
This EIP does not introduce any deprecation process for legacy encoded transactions, though the authors do encourage client developers to upgrade legacy encoded transactions to typed transactions as soon as it is reasonable.

The signature compatibility means that a client may see the same transaction encoded both ways.
In such a case the client can choose which to retain, but it is encouraged to retain the typed transaction rather than the legacy encoded transaction.
Since the two transactions would share a nonce, only one will ever be valid in a chain at a time.

## Test Cases
TBD

## Implementation
TBD

## Security Considerations
While [EIP-2718](/EIPs/EIPS/eip-2718) strongly recommends including the transaction type as the first byte of the signed data, we cannot accomplish that in this case because we need to remain signature compatible with legacy transactions.
Luckily, [EIP-2718](/EIPs/EIPS/eip-2718) also excludes transaction types `0xc0` to `0xfe` from valid transaction types, and the first byte of the signature in this case is in that range so we can be sure this will not conflict with any future transaction types.

A signature for these transaction types **does** collide with legacy transactions, but the transactions will be processed the same so it doesn&apos;t matter if the transaction ends up included as a legacy transaction or a typed transaction.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 12 Sep 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2972</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2972</guid>
      </item>
    
      <item>
        <title>Typed Transactions over Gossip</title>
        <category>Standards Track/Networking</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2976-eth-typed-transactions-over-gossip/4610</comments>
        
        <description>## Abstract
[Typed Transactions](/EIPs/EIPS/eip-2718) can be sent over devp2p as `TransactionType || TransactionPayload`.
The exact contents of the `TransactionPayload` are defined by the `TransactionType` in future EIPs, and clients may start supporting their gossip without incrementing the devp2p version.
If a client receives a `TransactionType` that it doesn&apos;t recognize, it **SHOULD** disconnect from the peer who sent it.
Clients **MUST NOT** send new transaction types before they believe the fork block is reached.

## Motivation
[EIP-2718](/EIPs/EIPS/eip-2718) introduced new transaction types for blocks (which presents itself in the makeup of a block header&apos;s transaction root and receipts root).
However, without a mechanism for gossiping these transactions, no one can actually include them in a block.
By updating devp2p to support the gossip of Typed Transactions, we can benefit from these new transaction types.

*Note: See [EIP-2718](/EIPs/EIPS/eip-2718) for additional motivations of Typed Transactions.*

## Specification
All changes specified below apply to all protocol/versions retroactively.

### Definitions
* `||` is the byte/byte-array concatenation operator.
* `|` is the type union operator.
* `DEVP2P_VERSION = TBD`
* `Transaction` is either `TypedTransaction` or `LegacyTransaction`
* `TypedTransaction` is a byte array containing `TransactionType || TransactionPayload`
* `TypedTransactionHash` is `keccak256(TypedTransaction)`
* `TransactionType` is a positive unsigned 8-bit number between `0` and `0x7f` that represents the type of the transaction
* `TransactionPayload` is an opaque byte array whose interpretation is dependent on the `TransactionType` and defined in future EIPs
* `LegacyTransaction` is an array of the form `[nonce, gasPrice, gasLimit, to, value, data, v, r, s]`
* `LegacyTransactionHash` is `keccak256(rlp(LegacyTransaction))`
* `TransactionId` is `keccak256(TypedTransactionHash | LegacyTransactionHash)`
* `Receipt` is either `TypedReceipt` or `LegacyReceipt`
* `TypedReceipt` is a byte array containing `TransactionType || ReceiptPayload`
* `ReceiptPayload` is an opaque byte array whose interpretation is dependent on the `TransactionType` and defined in future EIPs
* `LegacyReceipt` is an array of the form `[status, cumulativeGasUsed, logsBloom, logs]`
* `LegacyReceiptHash` is `keccak256(rlp(LegacyReceipt))`

### Protocol Behavior
If a client receives a `TransactionType` it doesn&apos;t recognize via any message, it **SHOULD** disconnect the peer that sent it.

If a client receives a `TransactionPayload` that isn&apos;t valid for the `TransactionType`, it **SHOULD** disconnect the peer that sent it.

Clients **MUST NOT** send transactions of a new `TransactionType` until that transaction type&apos;s introductory fork block.

Clients **MAY** disconnect peers who send transactions of a new `TransactionType` significantly before that transaction type&apos;s introductory fork block.

### Protocol Messages
`Transactions (0x02)`: `[Transaction_0, Transaction_1, ..., Transaction_n]`

`BlockBodies (0x06)`: `[BlockBody_0, BlockBody_1, ..., BlockBody_n]` where:
* `BlockBody` is `[TransactionList, UncleList]`
* `TransactionList` is `[Transaction_0, Transaction_1, ..., Transaction_n]`
* `UnclesList` is defined in previous versions of the devp2p specification

`NewBlock (0x07)`: `[[BlockHeader, TransactionList, UncleList], TotalDifficulty]` where:
* `BlockHeader` is defined in previous versions of the devp2 specification
* `TransactionList` is `[Transaction_0, Transaction_1, ..., Transaction_n]`
* `UnclesList` is defined in previous versions of the devp2p specification
* `TotalDifficulty` is defined in previous versions of the devp2p specification

`NewPooledTransactionIds (0x08)`: `[TransactionId_0, TransactionId_1, ..., TransactionId_n]`

`GetPooledTransactions (0x09)`: `[TransactionId_0, TransactionId_1, ..., TransactionId_n]`

`PooledTransactions (0x0a)`: `[Transaction_0, Transaction_1, ..., Transaction_n]`

`Receipts (0x10)`: `[ReceiptList_0, ReceiptList_1, ..., ReceiptList_n]` where:
* `ReceiptList` is `[Receipt_0, Receipt_1, ..., Receipt_n]`

## Rationale
### Why not specify each transaction type at the protocol layer?
We could have chosen to make the protocol aware of the shape of the transaction payloads.
The authors felt that it would be too much maintenance burden long term to have every new transaction type require an update to devp2p, so instead we merely define that typed transactions are supported.
### Why have peers disconnect if they receive an unknown transaction type?
We could encourage peers to remain connected to peers that submit an unknown transaction type, in case the transaction is some new transaction type that the receiver isn&apos;t aware of it.
However, doing so may open clients up to DoS attacks where someone would send them transactions of an undefined `TransactionType` in order to avoid being disconnected for spamming.
Also, in most cases we expect that by the time new transaction types are being sent over devp2p, a hard fork that requires all connected clients to be aware of the new transaction type is almost certainly imminent.

## Backwards Compatibility
Legacy transactions are still supported.

## Security Considerations
If a client chooses to ignore the **SHOULD** recommendation for disconnecting peers that send unknown transaction types they may be susceptible to DoS attacks.
Ignoring this recommendation should be limited to trusted peers only, or other situations where the risk of DoS is extremely low.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 13 Sep 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2976</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2976</guid>
      </item>
    
      <item>
        <title>Swiss Compliant Asset Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2983</comments>
        
        <description>## Abstract

This new standard is an [ERC-20](/EIPs/EIPS/eip-20) compatible token with restrictions that comply with the following Swiss laws: the [Stock Exchange Act](/EIPs/assets/eip-2980/Swiss-Confederation-SESTA.pdf), the [Banking Act](/EIPs/assets/eip-2980/Swiss-Confederation-BA.pdf), the [Financial Market Infrastructure Act](/EIPs/assets/eip-2980/Swiss-Confederation-FMIA.pdf), the [Act on Collective Investment Schemes](/EIPs/assets/eip-2980/Swiss-Confederation-CISA.pdf) and the [Anti-Money Laundering Act](/EIPs/assets/eip-2980/Swiss-Confederation-AMLA.pdf). The [Financial Services Act](/EIPs/assets/eip-2980/Swiss-Confederation-FINSA.pdf) and the [Financial Institutions Act](/EIPs/assets/eip-2980/Swiss-Confederation-FINIA.pdf) must also be considered. The solution achieved meet also the European jurisdiction.

This new standard meets the new era of asset tokens (known also as &quot;security tokens&quot;). These new methods manage securities ownership during issuance and trading. The issuer is the only role that can manage a white-listing and the only one that is allowed to execute “freeze” or “revoke” functions.

## Motivation

In its ICO guidance dated February 16, 2018, FINMA (Swiss Financial Market Supervisory Authority) defines asset tokens as tokens representing assets and/or relative rights ([FINMA ICO Guidelines](/EIPs/assets/eip-2980/Finma-ICO-Guidelines.pdf)). It explicitly mentions that asset tokens are analogous to and can economically represent shares, bonds, or derivatives. The long list of relevant financial market laws mentioned above reveal that we need more methods than with Payment and Utility Token.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

The words &quot;asset tokens&quot; and &quot;security tokens&quot; can be considered synonymous.

Every ERC-2980 compliant contract MUST implement the ERC-2980 interface.

### ERC-2980 (Token Contract)

``` solidity
interface ERC2980 extends ERC20 {
  
  /// @dev This emits when funds are reassigned
  event FundsReassigned(address from, address to, uint256 amount);

  /// @dev This emits when funds are revoked
  event FundsRevoked(address from, uint256 amount);

  /// @dev This emits when an address is frozen
  event FundsFrozen(address target);

  /**
  * @dev getter to determine if address is in frozenlist
  */
  function frozenlist(address _operator) external view returns (bool);

  /**
  * @dev getter to determine if address is in whitelist
  */
  function whitelist(address _operator) external view returns (bool);

}
```

The ERC-2980 extends [ERC-20](/EIPs/EIPS/eip-20). Due to the indivisible nature of asset tokens, the decimals number MUST be zero.

### Whitelist and Frozenlist

The accomplishment of the Swiss Law requirements is achieved by the use of two distinct lists of address: the Whitelist and the Frozenlist.
Addresses can be added to one or the other list at any time by operators with special privileges, called Issuers, and described below.
Although these lists may look similar, they differ for the following reasons: the Whitelist members are the only ones who can receive tokens from other addresses. There is no restriction on the possibility that these addresses can transfer the tokens already in their ownership.
This can occur when an address, present in the Whitelist, is removed from this list, without however being put in the Frozenlist and remaining in possession of its tokens.
On the other hand, the addresses assigned to the Frozenlist, as suggested by the name itself, have to be considered &quot;frozen&quot;, so they cannot either receive tokens or send tokens to anyone.

Below is an example interface for the implementation of a whitelist-compatible and a frozenlist-compratible contract.

``` solidity
Interface Whitelistable {

  /**
   * @dev add an address to the whitelist
   * Throws unless `msg.sender` is an Issuer operator
   * @param _operator address to add
   * @return true if the address was added to the whitelist, false if the address was already in the whitelist
   */
  function addAddressToWhitelist(address _operator) external returns (bool);

  /**
   * @dev remove an address from the whitelist
   * Throws unless `msg.sender` is an Issuer operator
   * @param _operator address to remove
   * @return true if the address was removed from the whitelist, false if the address wasn&apos;t in the whitelist in the first place
   */
  function removeAddressFromWhitelist(address _operator) external returns (bool);

}

Interface Freezable {

  /**
   * @dev add an address to the frozenlist
   * Throws unless `msg.sender` is an Issuer operator
   * @param _operator address to add
   * @return true if the address was added to the frozenlist, false if the address was already in the frozenlist
   */
  function addAddressToFrozenlist(address _operator) external returns (bool);

  /**
   * @dev remove an address from the frozenlist
   * Throws unless `msg.sender` is an Issuer operator
   * @param _operator address to remove
   * @return true if the address was removed from the frozenlist, false if the address wasn&apos;t in the frozenlist in the first place
   */
  function removeAddressFromFrozenlist(address _operator) external returns (bool);

}
```

### Issuers

A key role is played by the Issuer. This figure has the permission to manage Whitelists and Frozenlists, to revoke tokens and reassign them and to transfer the role to another address. No restrictions on the possibility to have more than one Issuer per contract. Issuers are nominated by the Owner of the contract, who also is in charge of remove the role. The possibility of nominating the Owner itself as Issuer at the time of contract creation (or immediately after) is not excluded.

Below is an example interface for the implementation of the Issuer functionalities.

``` solidity
Interface Issuable {

  /**
   * @dev getter to determine if address has issuer role
   */
  function isIssuer(address _addr) external view returns (bool);

  /**
   * @dev add a new issuer address
   * Throws unless `msg.sender` is the contract owner
   * @param _operator address
   * @return true if the address was not an issuer, false if the address was already an issuer
   */
  function addIssuer(address _operator) external returns (bool);

  /**
   * @dev remove an address from issuers
   * Throws unless `msg.sender` is the contract owner
   * @param _operator address
   * @return true if the address has been removed from issuers, false if the address wasn&apos;t in the issuer list in the first place
   */
  function removeIssuer(address _operator) external returns (bool);

  /**
   * @dev Allows the current issuer to transfer its role to a newIssuer
   * Throws unless `msg.sender` is an Issuer operator
   * @param _newIssuer The address to transfer the issuer role to
   */
  function transferIssuer(address _newIssuer) external;

}
```

### Revoke and Reassign

Revoke and Reassign methods allow Issuers to move tokens from addresses, even if they are in the Frozenlist. The Revoke method transfers the entire balance of the target address to the Issuer who invoked the method. The Reassign method transfers the entire balance of the target address to another address. These rights for these operations MUST be allowed only to Issuers.

Below is an example interface for the implementation of the Revoke and Reassign functionalities.

``` solidity
Interface RevokableAndReassignable {

  /**
   * @dev Allows the current Issuer to transfer token from an address to itself
   * Throws unless `msg.sender` is an Issuer operator
   * @param _from The address from which the tokens are withdrawn
   */
  function revoke(address _from) external;

  /**
   * @dev Allows the current Issuer to transfer token from an address to another
   * Throws unless `msg.sender` is an Issuer operator
   * @param _from The address from which the tokens are withdrawn
   * @param _to The address who receives the tokens
   */
  function reassign(address _from, address _to) external;

}
```

## Rationale

There are currently no token standards that expressly facilitate conformity to securities law and related regulations. EIP-1404 (Simple Restricted Token Standard) it’s not enough to address FINMA requirements around re-issuing securities to Investors.
In Swiss law, an issuer must eventually enforce the restrictions of their token transfer with a “freeze” function. The token must be “revocable”, and we need to apply a white-list method for AML/KYC checks.

## Backwards Compatibility

This EIP does not introduce backward incompatibilities and is backward compatible with the older ERC-20 token standard.
This standard allows the implementation of ERC-20 functions transfer, transferFrom, approve and allowance alongside to make a token fully compatible with ERC-20.
The token MAY implement decimals() for backward compatibility with ERC-20. If implemented, it MUST always return 0.

## Security Considerations

The security considerations mainly concern the role played by the Issuers. This figure, in fact, is not generally present in common ERC-20 tokens but has very powerful rights that allow him to move tokens without being in possession and freeze other addresses, preventing them from transferring tokens. It must be the responsibility of the owner to ensure that the addresses that receive this charge remain in possession of it only for the time for which they have been designated to do so, thus preventing any abuse.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 08 Sep 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2980</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2980</guid>
      </item>
    
      <item>
        <title>NFT Royalty Standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/2907</comments>
        
        <description>## Simple Summary

A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal support for royalty payments across all NFT marketplaces and ecosystem participants.

## Abstract

This standard allows contracts, such as NFTs that support [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155) interfaces, to signal a royalty amount to be paid to the NFT creator or rights holder every time the NFT is sold or re-sold. This is intended for NFT marketplaces that want to support the ongoing funding of artists and other NFT creators. The royalty payment must be voluntary, as transfer mechanisms such as `transferFrom()` include NFT transfers between wallets, and executing them does not always imply a sale occurred. Marketplaces and individuals implement this standard by retrieving the royalty payment information with `royaltyInfo()`, which specifies how much to pay to which address for a given sale price. The exact mechanism for paying and notifying the recipient will be defined in future EIPs. This ERC should be considered a minimal, gas-efficient building block for further innovation in NFT royalty payments.

## Motivation
There are many marketplaces for NFTs with multiple unique royalty payment implementations that are not easily compatible or usable by other marketplaces. Just like the early days of ERC-20 tokens, NFT marketplace smart contracts are varied by ecosystem and not standardized. This EIP enables all marketplaces to retrieve royalty payment information for a given NFT. This enables accurate royalty payments regardless of which marketplace the NFT is sold or re-sold at.

Many of the largest NFT marketplaces have implemented bespoke royalty payment solutions that are incompatible with other marketplaces. This standard implements standardized royalty information retrieval that can be accepted across any type of NFT marketplace. This minimalist proposal only provides a mechanism to fetch the royalty amount and recipient. The actual funds transfer is something which the marketplace should execute.

This standard allows NFTs that support [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155) interfaces, to have a standardized way of signalling royalty information. More specifically, these contracts can now calculate a royalty amount to provide to the rightful recipient.

Royalty amounts are always a percentage of the sale price. If a marketplace chooses *not* to implement this EIP, then no funds will be paid for secondary sales. It is believed that the NFT marketplace ecosystem will voluntarily implement this royalty payment standard; in a bid to provide ongoing funding for artists/creators. NFT buyers will assess the royalty payment as a factor when making NFT purchasing decisions.

Without an agreed royalty payment standard, the NFT ecosystem will lack an effective means to collect royalties across all marketplaces and artists and other creators will not receive ongoing funding. This will hamper the growth and adoption of NFTs and demotivate NFT creators from minting new and innovative tokens.

Enabling all NFT marketplaces to unify on a single royalty payment standard will benefit the entire NFT ecosystem.

While this standard focuses on NFTs and compatibility with the ERC-721 and ERC-1155 standards, EIP-2981 does not require compatibility with ERC-721 and ERC-1155 standards. Any other contract could integrate with EIP-2981 to return royalty payment information. ERC-2981 is, therefore, a universal royalty standard for many asset types.

At a glance, here&apos;s an example conversation summarizing NFT royalty payments today:

&gt;**Artist**: &quot;Do you support royalty payments on your platform?&quot;          
&gt;**Marketplace**: &quot;Yes we have royalty payments, but if your NFT is sold on another marketplace then we cannot enforce this payment.&quot;              
&gt;**Artist**: &quot;What about other marketplaces that support royalties, don&apos;t you share my royalty information to make this work?&quot;              
&gt;**Marketplace**: &quot;No, we do not share royalty information.&quot;

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL
NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and
&quot;OPTIONAL&quot; in this document are to be interpreted as described in
RFC 2119.

**ERC-721 and ERC-1155 compliant contracts MAY implement this ERC for royalties to provide a standard method of specifying royalty payment information.**

Marketplaces that support this standard **SHOULD** implement some method of transferring royalties to the royalty recipient. Standards for the actual transfer and notification of funds will be specified in future EIPs.

Marketplaces **MUST** pay the royalty in the same unit of exchange as that of the `_salePrice` passed to `royaltyInfo()`. This is equivalent to saying that the `_salePrice` parameter and the `royaltyAmount` return value **MUST** be denominated in the same monetary unit. For example, if the sale price is in ETH, then the royalty payment must also be paid in ETH, and if the sale price is in USDC, then the royalty payment must also be paid in USDC.

Implementers of this standard **MUST** calculate a percentage of the `_salePrice` when calculating the royalty amount. Subsequent invocations of `royaltyInfo()` **MAY** return a different `royaltyAmount`. Though there are some important considerations for implementers if they choose to perform different percentage calculations between `royaltyInfo()` invocations.

The `royaltyInfo()` function is not aware of the unit of exchange for the sale and royalty payment. With that in mind, implementers **MUST NOT** return a fixed/constant `royaltyAmount`, wherein they&apos;re ignoring the `_salePrice`. For the same reason, implementers **MUST NOT** determine the `royaltyAmount` based on comparing the `_salePrice` with constant numbers. In both cases, the `royaltyInfo()` function makes assumptions on the unit of exchange, which **MUST** be avoided.

The percentage value used must be independent of the sale price for reasons previously mentioned (i.e. if the percentage value 10%, then 10% **MUST** apply whether `_salePrice` is 10, 10000 or 1234567890). If the royalty fee calculation results in a remainder, implementers **MAY** round up or round down to the nearest integer. For example, if the royalty fee is 10% and `_salePrice` is 999, the implementer can return either 99 or 100 for `royaltyAmount`, both are valid.

The implementer **MAY** choose to change the percentage value based on other predictable variables that do not make assumptions about the unit of exchange. For example, the percentage value may drop linearly over time. An approach like this **SHOULD NOT** be based on variables that are unpredictable like `block.timestamp`, but instead on other more predictable state changes. One more reasonable approach **MAY** use the number of transfers of an NFT to decide which percentage value is used to calculate the `royaltyAmount`. The idea being that the percentage value could decrease after each transfer of the NFT. Another example could be using a different percentage value for each unique `_tokenId`.

Marketplaces that support this standard **SHOULD NOT** send a zero-value transaction if the `royaltyAmount` returned is `0`. This would waste gas and serves no useful purpose in this EIP.

Marketplaces that support this standard **MUST** pay royalties no matter where the sale occurred or in what currency, including on-chain sales, over-the-counter (OTC) sales and off-chain sales such as at auction houses. As royalty payments are voluntary, entities that respect this EIP must pay no matter where the sale occurred - a sale conducted outside of the blockchain is still a sale. The exact mechanism for paying and notifying the recipient will be defined in future EIPs.

Implementers of this standard **MUST** have all of the following functions:

```solidity
pragma solidity ^0.6.0;
import &quot;./IERC165.sol&quot;;

///
/// @dev Interface for the NFT Royalty Standard
///
interface IERC2981 is IERC165 {
    /// ERC165 bytes to add to interface array - set in parent contract
    /// implementing this standard
    ///
    /// bytes4(keccak256(&quot;royaltyInfo(uint256,uint256)&quot;)) == 0x2a55205a
    /// bytes4 private constant _INTERFACE_ID_ERC2981 = 0x2a55205a;
    /// _registerInterface(_INTERFACE_ID_ERC2981);

    /// @notice Called with the sale price to determine how much royalty
    //          is owed and to whom.
    /// @param _tokenId - the NFT asset queried for royalty information
    /// @param _salePrice - the sale price of the NFT asset specified by _tokenId
    /// @return receiver - address of who should be sent the royalty payment
    /// @return royaltyAmount - the royalty payment amount for _salePrice
    function royaltyInfo(
        uint256 _tokenId,
        uint256 _salePrice
    ) external view returns (
        address receiver,
        uint256 royaltyAmount
    );
}

interface IERC165 {
    /// @notice Query if a contract implements an interface
    /// @param interfaceID The interface identifier, as specified in ERC-165
    /// @dev Interface identification is specified in ERC-165. This function
    ///  uses less than 30,000 gas.
    /// @return `true` if the contract implements `interfaceID` and
    ///  `interfaceID` is not 0xffffffff, `false` otherwise
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
```

### Examples

This standard being used on an ERC-721 during deployment:

#### Deploying an ERC-721 and signaling support for ERC-2981

```solidity
constructor (string memory name, string memory symbol, string memory baseURI) {
        _name = name;
        _symbol = symbol;
        _setBaseURI(baseURI);
        // register the supported interfaces to conform to ERC721 via ERC165
        _registerInterface(_INTERFACE_ID_ERC721);
        _registerInterface(_INTERFACE_ID_ERC721_METADATA);
        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);
        // Royalties interface
        _registerInterface(_INTERFACE_ID_ERC2981);
    }
```

#### Checking if the NFT being sold on your marketplace implemented royalties

```solidity  
bytes4 private constant _INTERFACE_ID_ERC2981 = 0x2a55205a;

function checkRoyalties(address _contract) internal returns (bool) {
    (bool success) = IERC165(_contract).supportsInterface(_INTERFACE_ID_ERC2981);
    return success;
 }
```

## Rationale

### Optional royalty payments

It is impossible to know which NFT transfers are the result of sales, and which are merely wallets moving or consolidating their NFTs. Therefore, we cannot force every transfer function, such as `transferFrom()` in ERC-721, to involve a royalty payment as not every transfer is a sale that would require such payment. We believe the NFT marketplace ecosystem will voluntarily implement this royalty payment standard to provide ongoing funding for artists/creators. NFT buyers will assess the royalty payment as a factor when making NFT purchasing decisions.

### Simple royalty payments to a single address

This EIP does not specify the manner of payment to the royalty recipient. Furthermore, it is impossible to fully know and efficiently implement all possible types of royalty payments logic. With that said, it is on the royalty payment receiver to implement all additional complexity and logic for fee splitting, multiple receivers, taxes, accounting, etc. in their own receiving contract or off-chain processes. Attempting to do this as part of this standard, it would dramatically increase the implementation complexity, increase gas costs, and could not possibly cover every potential use-case. This ERC should be considered a minimal, gas-efficient building block for further innovation in NFT royalty payments. Future EIPs can specify more details regarding payment transfer and notification.

### Royalty payment percentage calculation

This EIP mandates a percentage-based royalty fee model. It is likely that the most common case of percentage calculation will be where the `royaltyAmount` is always calculated from the `_salePrice` using a fixed percent i.e. if the royalty fee is 10%, then a 10% royalty fee must apply whether `_salePrice` is 10, 10000 or 1234567890.

As previously mentioned, implementers can get creative with this percentage-based calculation but there are some important caveats to consider. Mainly, ensuring that the `royaltyInfo()` function is not aware of the unit of exchange and that unpredictable variables are avoided in the percentage calculation. To follow up on the earlier `block.timestamp` example, there is some nuance which can be highlighted if the following events ensued:

1. Marketplace sells NFT.
2. Marketplace delays `X` days before invoking `royaltyInfo()` and sending payment.
3. Marketplace receives `Y` for `royaltyAmount` which was significantly different from the `royaltyAmount` amount that would&apos;ve been calculated `X` days prior if no delay had occurred.
4. Royalty recipient is dissatisfied with the delay from the marketplace and for this reason, they raise a dispute.

Rather than returning a percentage and letting the marketplace calculate the royalty amount based on the sale price, a `royaltyAmount` value is returned so there is no dispute with a marketplace over how much is owed for a given sale price. The royalty fee payer must pay the `royaltyAmount` that `royaltyInfo()` stipulates.

### Unit-less royalty payment across all marketplaces, both on-chain and off-chain

This EIP does not specify a currency or token used for sales and royalty payments. The same percentage-based royalty fee must be paid regardless of what currency, or token was used in the sale, paid in the same currency or token. This applies to sales in any location including on-chain sales, over-the-counter (OTC) sales, and off-chain sales using fiat currency such as at auction houses. As royalty payments are voluntary, entities that respect this EIP must pay no matter where the sale occurred - a sale outside of the blockchain is still a sale. The exact mechanism for paying and notifying the recipient will be defined in future EIPs.

### Universal Royalty Payments

Although designed specifically with NFTs in mind, this standard does not require that a contract implementing EIP-2981 is compatible with either ERC-721 or ERC-1155 standards. Any other contract could use this interface to return royalty payment information, provided that it is able to uniquely identify assets within the constraints of the interface. ERC-2981 is, therefore, a universal royalty standard for many other asset types.

## Backwards Compatibility

This standard is compatible with current ERC-721 and ERC-1155 standards.

## Security Considerations

There are no security considerations related directly to the implementation of this standard.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 15 Sep 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2981</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2981</guid>
      </item>
    
      <item>
        <title>Serenity Phase 0</title>
        <category>Informational/</category>
        
          <comments>https://ethereum-magicians.org/t/serenity-phase-0-eip/4621</comments>
        
        <description>## Abstract

This EIP specifies Phase 0 of Serenity (eth2), a multi-phased upgrade to the consensus mechanism for Ethereum mainnet. In Phase 0, the existing PoW chain and mechanics are entirely unaffected, while a PoS chain -- the beacon chain -- is built in parallel to serve as the core of the upgraded consensus. In subsequent phases, the beacon chain is enhanced to support and secure the consensus of a number of parallel shard chains, ultimately incorporating current Ethereum mainnet as one of those shards.

At the core of the beacon chain is a proof of stake consensus mechanism called Casper the Friendly Finality Gadget (FFG) and a fork-choice rule called Latest Message Driven Greedy Heaviest Observed Sub-Tree (LMD-GHOST). Phase 0 is centered primarily around the mechanics and incentives of validators executing these algorithms. The detailed specifications for eth2 are contained in an independent repository from this EIP, and safety and liveness proofs can be found in the [Combining GHOST and Casper](/EIPs/assets/eip-2982/arxiv-2003.03052-Combining-GHOST-and-Casper.pdf) paper. To avoid duplication, this EIP just references relevant spec files and releases.

Early phases of eth2 are executed without any breaking consensus changes on current Ethereum mainnet. This EIP serves to document the bootstrapping of this consensus mechanism and note the path for eth2 to supplant Ethereum&apos;s current proof-of-work (PoW) consensus.

## Motivation

Eth2 aims to fulfill the original vision of Ethereum to support an efficient, global-scale, general-purpose transactional platform while retaining high cryptoeconomic security and decentralization.

Today, Ethereum blocks are consistently full due to increasingly high demand for decentralized applications. Ever since the first serious spikes in adoption in 2017 (cryptokitties), the Ethereum community has consistently and vocally demanded scaling solutions.

Since day 0 of Ethereum, the investigation and expectation in scaling solutions has been two-pronged -- scale from both Layer 1 upgrades and Layer 2 adoption. This EIP represents the start to a multi-phased rollout of the former.

### Scaling through sharding

As the Ethereum network and the applications built upon it have seen increasing usage over the past 5 years, blocks have become regularly full and the gas price market continues to climb. Simple increases to the block gas-limit of the current Ethereum chain are unable to account for the increase in demand of the system without inducing an unsustainably high resource burden (in the form of bandwidth, computational, and disk resources) on consumer nodes. To retain decentralization while scaling up the Ethereum network, another path must be taken.

To provide more scale to Ethereum, while not inducing a restrictively high burden on both consumer and consensus nodes, eth2 introduces a &quot;sharded&quot; solution in which a number of blockchain shards -- each of similar capacity to Ethereum mainnet today -- run in parallel under a unified consensus mechanism. The core consensus (the beacon chain) and a small number of these shards can be processed via a single consumer machine, while the aggregate of the system provides much higher capacity.

### Decentralization and economic finality through proof-of-stake

Since the early days of Ethereum, proof-of-stake has been a long-awaited desideratum for the following:
* Increased decentralization of the core consensus by lowering the barrier to entry and technical requirements of participation 
* Increased cryptoeconomic security via in-protocol penalties for misbehaviour and the addition of economic finality
* Elimination of the energy hungry mining of the current PoW consensus mechanism

In addition to the above, PoS has synergies with the sharding scaling solution. Due to the random sampling requirement of sharding, PoS provides a more simple and direct access to the &quot;active validator set&quot; than PoW and thus allows for a more direct sharded protocol construction.


## Specification

Phase 0 is designed to require _no breaking consensus changes_ to existing Ethereum mainnet. Instead, this is the bootstrapping a new PoS consensus that can, once stable, supplant the current PoW consensus.

Phase 0 specifications are maintained in a repository independent of this EIP. `SPEC_RELEASE_VERSION` release of the specs at `SPEC_RELEASE_COMMIT` are considered the canonical Phase 0 specs for this EIP.

This EIP provides a high level view on the Phase 0 mechanisms, especially those that are relevant to Ethereum mainnet (e.g. the deposit contract) and users (e.g. validator mechanics and eth2 issuance). The extended and low level details remain in the `consensus-specs` repository

### Parameters

| Parameter | Value |
| - | - |
| `SPEC_RELEASE_VERSION` | `v1.0.0` |
| `SPEC_RELEASE_COMMIT` | `579da6d2dc734b269dbf67aa1004b54bb9449784` |
| `DEPOSIT_CONTRACT_ADDRESS` | `0x00000000219ab540356cBB839Cbe05303d7705Fa` |
| `MIN_GENESIS_TIME` | `1606824000` |
| `BASE_REWARD_FACTOR` | `2**6` (64) |
| `INACTIVITY_PENALTY_QUOTIENT` | `2**26` (67,108,864) |
| `PROPORTIONAL_SLASHING_MULTIPLIER` | `1` |
| `MIN_SLASHING_PENALTY_QUOTIENT` | `2**7` (128) |

_Note:_ Eth2 has many more Phase 0 configuration parameters but the majority are left out of this EIP for brevity.

### Validator deposit contract

In Phase 0, eth2 uses a contract deployed on Ethereum mainnet -- the Deposit Contract -- at `DEPOSIT_CONTRACT_ADDRESS` to onboard validators into the PoS consensus of the beacon chain.

To participate in the PoS consensus, users submit validator deposits to the deposit contract. The beacon chain comes to consensus on the state of this contract and processes new validator deposits. This uni-directional deposit mechanism is the only technical link between the two components of the system (Ethereum mainnet and beacon chain) in Phase 0.

### Beacon chain and validator mechanics

Users who choose to participate in eth2 consensus deposit ETH collateral into the deposit contract in order to be inducted into the beacon chain validator set. From there, these validators are responsible for constructing the **beacon chain** (note that these consensus participants in PoS are akin to miners in PoW).

The beacon chain is a pure PoS chain that in Phase 0 is primarily concerned with maintaining its own consensus and managing the registry of validators. The consensus rules define _roles_ (e.g. block proposal, block attesting) that validators are expected to participate in; validators who perform their roles well are rewarded, and validators who perform their roles poorly or are offline are penalized. Phase 0 does not yet include any ETH transfer, sharding or smart contract / VM execution capabilities.

In subsequent phases, additional mechanisms and validator responsibilities will be added to the beacon chain to manage the consensus of a number of parallel shard chains (&quot;Phase 1&quot;), to integrate the existing Ethereum system (&quot;Phase 1.5&quot;) and to add full support for sharded smart contract execution (&quot;Phase 2&quot;).

### Issuance

To incentivize validators to deposit ether collateral and participate in the eth2 consensus, we propose that rewards (in the form of Ethereum&apos;s native asset, ether) be regularly issued to consensus participants. Due to the beacon chain operating in parallel to the existing PoW chain in early phases of eth2, this issuance is _in addition to_ any PoW rewards until the existing chain is merged into eth2 as a shard.

The amount of ether issued to validators on the beacon chain is proportional to the square root of the total ether deposited. This issuance curve was chosen as a more stable and sustainable curve to the two obvious alternatives -- fixed total issuance and fixed issuance per ether staked. For a more technical discussion on this choice see [here](/EIPs/assets/eip-2982/ef-Discouragement-Attacks.pdf).

In eth2, this curve is parameterized by `BASE_REWARD_FACTOR` in the context of slot time and epoch length. Below is the issuance curve as a function of ether staked, along with a table of examples for illustration. Note, all figures shown are annualized.

![](/EIPs/assets/eip-2982/2982-issuance.png)

| Active Deposits | Max Annual Validator Reward\* | Max Annual ETH Issued\* |
| -------- | -------: | --------: |
| 0.5M ETH | 23.50%   | 117,527   |
| 1M ETH   | 16.60%   | 166,208   |
| 2M ETH   | 11.75%   | 235,052   |
| 4M ETH   |  8.31%   | 332,411   |
| 8M ETH   |  5.88%   | 470,104   |
| 16M ETH  |  4.16%   | 664,801   |
| 32M ETH  |  2.94%   | 940,167   |
| 64M ETH  |  2.08%   | 1,329,603 |
| 128M ETH |  1.47%   | 1,880,334 |

_\*Assuming validators are online 100% of the time and behaving optimally. Suboptimal validator behavior will lead to reduced rewards and/or penalties that reduce total issuance._

### Initial punitive parameters

For PoS protocols to be crypto-economically secure, in-protocol penalties are required. Small offline penalties incentivize validator liveness, whereas (potentially) much larger penalties provide protocol security in the event of tail-risk scenarios.

Specifically, the following significant penalties exist:
* **Inactivity Leak**: an offline penalty that increases each epoch is applied to validators during extended times of no finality (e.g. if one-third or more are offline or not on the canonical chain). This ensures the chain can eventually regain finality even under catastrophic conditions.
* **Slashing**: a penalty applied to validators that sign _explicitly malicious_ messages that could lead to the construction and finalization of two conflicting chains (e.g. two blocks or attestations in the same slot). This penalty is designed to scale up in proportion to the number of slashable validators in the same time period such that if a critical number (wrt chain safety) of slashings have occurred, validators are _maximally_ punished.

For the initial launch of Phase 0, the parameters defining the magnitude of these penalties -- `INACTIVITY_PENALTY_QUOTIENT`, `PROPORTIONAL_SLASHING_MULTIPLIER`, and `MIN_SLASHING_PENALTY_QUOTIENT` -- have been tuned to be less punitive than their final intended values. This provides a more forgiving environment for early validators and client software in an effort to encourage validation in this early, higher technical-risk stage.

_`INACTIVITY_PENALTY_QUOTIENT` is configured initially to four times its final value_. This results in a slower inactivity leak during times of non-finality, which means the chain is less responsive to such an event. If there is an extended time of non-finality during the early months of eth2, it is far more likely to be due to technical issues with client software rather than some sort of global catastrophic event. 

_`PROPORTIONAL_SLASHING_MULTIPLIER` is configured initially to one-third of its final value_. This results in a lower accountable safety margin in the event of an attack. If any validators are slashed in the early months of eth2, it is far more likely to be the result of user mismanagement of keys and/or issues with client software than an organized attack.

_`MIN_SLASHING_PENALTY_QUOTIENT` configured initially to four times its final value_. This results in a lower guaranteed minimum penalty for a slashable offense and thus reduces the baseline punitive incentive to keep an individual validator&apos;s system secure. As with `PROPORTIONAL_SLASHING_MULTIPLIER`, slashings during the early months of eth2 are far more likely to be due to user mismanagement, or issues with client software, than an organized attack.

## Rationale

### Principles

* **Simplicity**: especially since cryptoeconomic proof of stake and quadratic sharding are inherently complex, the protocol should strive for maximum simplicity in its decisions as much as possible. This is important because it (i) minimizes development costs, (ii) reduces risk of unforeseen security issues, and (iii) allows protocol designers to more easily convince users that parameter choices are legitimate. When complexity is unavoidable to achieve a given level of functionality, the preference order for where the complexity goes is: layer 2 protocols &gt; client implementations &gt; protocol spec.
* **Long-term stability**: the low levels of the protocol should ideally be built so that there is no need to change them for a decade or longer, and any needed innovation can happen on higher levels (client implementations or layer 2 protocols).
* **Sufficiency**: it should be fundamentally possible to build as many classes of applications as possible on top of the protocol.
* **Defense in depth**: the protocol should continue to work as well as possible under a variety of possible security assumptions (eg. regarding network latency, fault count, the motivations of users)
* **Full light-client verifiability**: given some assumptions (eg. network latency, bounds on attacker budget, 1-of-N or few-of-N honest minority), a client verifying a small fixed amount of data (ideally just the beacon chain) should be able to gain indirect assurance that all of the data in the full system is available and valid, even under a 51% attack (note: this is a form of defense-in-depth but it&apos;s important enough to be separate)

### The Layer 1 vs Layer 2 Tradeoff

The Ethereum roadmap uses a mixed layer 1 / layer 2 approach. We focus on serving a particular type of layer 2 (rollups) because it&apos;s the only kind of layer 2 that both inherits the security of layer 1 and provides scaling of general-purpose applications. However, rollups come at a cost: they require some on-chain data _per transaction_, and so a blockchain with really high capacity rollups must be able to handle a still quite high amount of data bandwidth. So make this more feasible, we are implementing on scalable data layer technologies, particularly data availability sampling.

The reason to not take a pure layer 2 approach is that pure layer 2 scaling can only be done either with trust-based solutions (not desirable), or with channels or plasma (which have inherent limitations and cannot support the full EVM.

The reason to not take a pure layer 1 approach is to enable more room for experimentation in execution layers, and allow the base protocol to be simpler and have less intensive governance.

### Why proof of stake

In short:

* **No need to consume large quantities of electricity** in order to secure a blockchain (e.g. it&apos;s estimated that both Bitcoin and Ethereum burn over $1 million worth of electricity and hardware costs per day as part of their consensus mechanism).
* Because of the lack of high electricity consumption, there is **not as much need to issue as many new coins** in order to motivate participants to keep participating in the network. It may theoretically even be possible to have negative net issuance, where a portion of transaction fees is &quot;burned&quot; and so the supply goes down over time.
* Proof of stake opens the door to a wider array of techniques that use game-theoretic mechanism design in order to better **discourage centralized cartels** from forming and, if they do form, from acting in ways that are harmful to the network (e.g. like selfish mining in proof of work).
* **Reduced centralization risks**, as economies of scale are much less of an issue. $10 million of coins will get you exactly 10 times higher returns than $1 million of coins, without any additional disproportionate gains because at the higher level you can afford better mass-production equipment, which is an advantage for Proof-of-Work.
* Ability to use economic penalties to **make various forms of 51% attacks vastly more expensive** to carry out than proof of work - to paraphrase Vlad Zamfir, &quot;it&apos;s as though your ASIC farm burned down if you participated in a 51% attack&quot;.

### Why Casper

There are currently three major schools of proof of stake consensus algorithm:

* **Nakamoto-inspired** (Peercoin, NXT, Ouroboros...)
* **PBFT-inspired** (Tendermint, Casper FFG, Hotstuff...)
* **CBC Casper**

Within the latter two camps, there is also the question of whether and how to use security deposits and slashing (Nakamoto-inspired algorithms are incompatible with non-trivial slashing). All three are superior to proof of work, but we want to defend our own approach.

#### Slashing

Ethereum 2.0 uses a **slashing** mechanism where a validator that is detected to have misbehaved can be penalized, in the best case ~1% but in the worst case up to its entire deposit.

We defend our use of slashing as follows:

1. **Raising the cost of attack**: We want to be able to make a hard claim that a 51% attack on a proof of stake blockchain forces the attacker to incur a very large amount of expense (think: hundreds of millions of dollars worth of coins) that get burned, and any attack can be recovered from quickly. This makes the attack/defense calculus very unfavorable for attackers, and in fact makes attacks potentially _counterproductive_, because the disruption to service is outweighed by price gains to legitimate coin holders.
2. **Overcoming the validator&apos;s dilemma**: the most realistic immediate way for nodes to start to deviate from &quot;honest&quot; behavior is _laziness_ (ie. not validating things that one should be validating, signing everything just in case, etc). See [the validator&apos;s dilemma paper](/EIPs/assets/eip-2982/iacr-2015-702-Demystifying-Incentives-in-the-Consensus-Computer.pdf) (Luu et al., CC BY) for theoretical reasoning and the Bitcoin SPV mining fork for examples of this happening and leading to very harmful consequences in the wild. Having very large penalties for self-contradicting or for signing incorrect things helps to alleviate this.

A more subtle instance of (2) can be seen as follows. In July 2019 a validator on Cosmos was slashed for signing two conflicting blocks. An investigation revealed that this happened because that validator was running a primary and a backup node (to ensure that one of the two going offline would not prevent them from getting rewards) and the two were accidentally turned on at the same time, leading to them contradicting each other.

If it became standard practice to have a primary and backup node, then an attacker could partition the network and get the primaries and the backups of all the validators to commit to different blocks, and thereby lead to two conflicting blocks being finalized. Slashing penalties help to heavily disincentivize this practice, reducing the risk of such a scenario taking place.

#### Choice of consensus algorithm

Only the BFT-inspired and CBC schools of consensus algorithm have a notion of finality, where a block is confirmed in such a way that a large portion (1/3 in BFT-inspired, 1/4 in CBC) of validators would need to misbehave and get slashed for that block to get reverted in favor of some conflicting block; Nakamoto-inspired (ie. longest-chain-rule) consensus algorithms have no way of achieving finality in this sense.

Note that finality requires a (super)majority of validators being online, but this is a requirement of the sharding mechanism already, as it requires 2/3 of a randomly sampled committee of validators to sign off on a crosslink for that crosslink to be accepted.

Our choice of [Casper FFG](/EIPs/assets/eip-2982/arxiv-1710.09437-Casper-the-Friendly-Finality-Gadget.pdf) was simply a matter of it being the simplest algorithm available at the time that part of the protocol was being finalized. Details are still subject to long-term change; in particular, we are actively exploring solutions to achieve single slot finality.

### Sharding - or, why do we hate supernodes?

The main alternative to sharding for layer-1 scaling is the use of supernodes - simply requiring every consensus node to have a powerful server so that it can individually process every transaction. Supernode-based scaling is convenient because it is simple to implement: it works just the same way blockchains do now, except that more software-engineering work is required to build things in a way that is more parallelizable.

Our main objections to this approach are as follows:

* **Pool centralization risk**: in a supernode-based system, running a node has a high fixed cost, so far fewer users can participate. This is usually rebutted with &quot;well consensus in most PoW and PoS coins is dominated by 5-20 pools anyway, and the pools will be able to run nodes just fine&quot;. However, this response ignores the risk of centralization pressure even between pools that can afford it. If the fixed cost of running a validator is significant relative to the returns, then larger pools will be able to offer smaller fees than smaller ones and this could lead to smaller pools being pushed out or feeling pressure to merge. In a sharded system, on the other hand, validators with more ETH need to verify more transactions, so costs are not fixed.
* **AWS centralization risk**: in a supernode-based system, home staking is infeasible and so it&apos;s more likely that most staking will happen inside cloud computing environments, of which there are only a few options to choose from. This creates a single point of failure.
* **Reduced censorship resistance**: making it impossible to participate in consensus without high computation+bandwidth requirements makes detection and censorship of validators easier.
* **Scalability**: as transaction throughput increases, in a supernode-based system the above risks increase, whereas sharded systems can more easily handle the increased load.

These centralization risks are also why we are NOT attempting to achieve super-low-latency (&lt;1s) of the blockchain, instead opting for (relatively!) conservative numbers.

Instead, Ethereum is taking an approach where each validator is only assigned to process a small portion of all data. Only validators staking large amounts of ETH (think: tens of thousands or more) are required to process the entire data in the chain.

Note that there is a possible middle-ground in sharding design where block _production_ is centralized but (i) block _verification_ is decentralized and (ii) there exist &quot;bypass channels&quot; where users can send transactions and block producers are forced to include them, so even a monopoly producer cannot censor. We are actively considering sharding designs that lean somewhat in this direction to increase simplicity so that scaling can be deployed faster, though if desired even within this spec it&apos;s possible to run distributed builders and avoid centralization even there.


### Security models

It&apos;s commonly assumed that blockchains depend on an &quot;honest majority&quot; assumption for their security: that &gt;=50% of participants will faithfully follow a prescribed protocol, even forgoing opportunities to defect for their own personal interest. In reality, (i) an honest majority model is unrealistic, with participants being &quot;lazy&quot; and signing off on blocks without validating them (see [the validator&apos;s dilemma paper](/EIPs/assets/eip-2982/iacr-2015-702-Demystifying-Incentives-in-the-Consensus-Computer.pdf) and the Bitcoin SPV mining fork) being a very common form of defection, but fortunately (ii) blockchains maintain many or all of their security properties under much harsher models, and it&apos;s really important to preserve those extra guarantees.

A common harsher model is the _uncoordinated rational majority_ model, which states that participants act in their own self-interest, but no more than some percentage (eg. 23.21% in simple PoW chains) are cooperating with each other. An even harsher model is the worst-case model where there is a single actor that controls more than 50% of hashpower or stake, and the question becomes:

* Can we, even under that scenario, force the attacker to have to pay a very high cost to break the chain&apos;s guarantees?
* What guarantees can we unconditionally preserve?

Slashing in proof of stake chains accomplishes the first objective. In non-sharded chains, every node verifying every block accomplishes the second objective for two specific guarantees: (i) that the longest chain is valid, and (ii) that the longest chain is _available_.

A major challenge in sharding is getting the same two properties without requiring each node to verify the full chain. Our defense-in-depth approach with sharding accomplishes just that. The core idea is to combine together random committee sampling, proof of custody, fraud proofs, [data availability sampling (DAS)](/EIPs/assets/eip-2982/arxiv-1809.09044-Fraud-and-Data-Availability-Proofs--Maximising-Light-Client-Security-and-Scaling-Blockchains-with-Dishonest-Majorities.pdf) and eventually ZK-SNARKs, to allow clients to detect and reject invalid or unavailable chains without downloading and verifying all of the data, even if the invalid chains are supported by a majority of all proof of stake validators.

Censorship of transactions can potentially be detected by clients in a consensus-preserving way, but this research has not yet been incorporated into the ethereum roadmap.

Here is the current expected security properties expressed in a table:

| | Network delay &lt;3s |Network delay 3s - 6 min|Network delay &gt; 6 min|
|---|---|---|---|
|&gt;2/3 validators honest|Perfect operation|Imperfect but acceptable operation. No rigorous proof of liveness, but liveness expected in practice.|Likely intermittent liveness failures, no safety failures|
|&gt;2/3 validators rational, &lt;1/3 coordinated|Perfect operation|Imperfect but acceptable operation, heightened centralization risk|Likely intermittent liveness failures, no safety failures, very high centralization risk|
|51% attacker|Can revert finality or censor, but at high cost; cannot force through invalid or unavailable chains|Can revert finality or censor, but at high cost; cannot force through invalid or unavailable chains|Can revert finality or censor; cannot force through invalid or unavailable chains|

### Why are the Casper incentives set the way they are?

#### Base rewards

During each epoch, every validator is expected to make an &quot;attestation&quot;, a signature that expresses that validator&apos;s opinion on what the head of the chain is. There is a reward for having one&apos;s attestation included, with four components (called &quot;duties&quot;):

1. Reward for the attestation getting included at all
2. Reward for the attestation specifying the correct epoch checkpoint
3. Reward for the attestation specifying the correct chain head
4. Reward for correctly participating in sync committee signatures

Note also that mixed into these duties is a timeliness requirement: your attestation has to be included within a certain time to be eligible for the rewards, and for the &quot;correct head&quot; duty that time limit is 1 slot.

For each duty, the actual reward is computed as follows. If:

* $R = B * \frac{nom}{den}$ equals the base reward multiplied by the fraction $\frac{nom}{den}$ that corresponds to that particular duty
* $P$ is the portion of validators that did the desired action

Then:

* Any validator that fulfilled the duty gets a reward of $R * P$
* Any validator that did not fulfill the duty gets a penalty $-R$

The purpose of this &quot;collective reward&quot; scheme where &quot;if anyone performs better, everyone performs better&quot; is to bound griefing factors (see [this paper](/EIPs/assets/eip-2982/ef-Discouragement-Attacks.pdf) for one description of griefing factors and why they are important).

The base reward $B$ is itself calculated as $k * \frac{D_i}{\sqrt{\sum_{j=1}^{n} D_j}}$ where $D_1 ... D_n$ are deposit sizes and $k$ is a constant; this is a halfway compromise between two common models, (i) fixed reward rate, ie. $k * D_i$, and (ii) fixed total reward, ie. $k * \frac{D_i}{\sum_{j=1}^{n} D_j}$.

The main argument against (i) is that it imposes too much uncertainty on the network of two kinds: uncertainty of the total level of issuance, and uncertainty of the total level of deposits (as if a fixed reward rate is set too low then almost no one will participate, threatening the network, and if a rate is set too high then very many validators will participate, leading to unexpectedly high issuance). The main argument against (ii) is greater vulnerability to discouragement attacks (again see the [discouragement attacks paper](/EIPs/assets/eip-2982/ef-Discouragement-Attacks.pdf)). The inverse-square-root approach compromises between the two and avoids the worst consequences of each one.

When an attestation gets a reward, the proposer gets a fraction of that reward. This is to encourage proposers to listen well for messages and accept as many as possible.

Note also that the rewards are designed to be forgiving to validators who are offline often: being offline 1% of the time only sacrifices about 1.6% of your reward. This is also to promote decentralization: the goal of a decentralized system is to create a reliable whole out of unreliable parts, so we should not be trying to force each individual node to be extremely reliable.

#### Inactivity leak

If the chain fails to finalize for $tsf &gt; 4$ epochs ($tsf$ = &quot;time since finality&quot;), then a penalty is added so that the maximum possible reward is zero (validators performing imperfectly get penalized), and a second penalty component is added, proportional to $tsf$ (that is, the longer the chain has not finalized, the higher the _per-epoch_ penalty for being offline). This ensures that if more than 1/3 of validators drop off, validators that are not online get penalized much more heavily, and the total penalty goes up quadratically over time.

This has three consequences:

* Penalizes being offline much more heavily in the case where you being offline is actually preventing blocks from being finalized
* Serves the goals of being an anti-correlation penalty (see section below)
* Ensures that if more than 1/3 do go offline, eventually the portion online goes back up to 2/3 because of the declining deposits of the offline validators

With the current parametrization, if blocks stop being finalized, validators lose 1% of their deposits after 2.6 days, 10% after 8.4 days, and 50% after 21 days. This means for example that if 50% of validators drop offline, blocks will start finalizing again after 21 days.

#### Slashing and anti-correlation penalties

If a validator is caught violating the Casper FFG slashing condition, they get penalized a portion of their deposit equal to three times the portion of validators that were penalized around the same time as them (specifically, between 18 days before they were penalized and roughly the time they withdrew). This is motivated by several goals:

* A validator misbehaving is only really bad for the network if they misbehave at the same time as many other validators, so it makes sense to punish them more in that case
* It heavily penalizes actual attacks, but applies very light penalties to single isolated failures that are likely to be honest mistakes
* It ensures that smaller validators take on less risk than larger validators (as in the normal case, a large validator would be the only one failing at the same time as themselves)
* It creates a disincentive against everyone joining the largest pool

### BLS Signatures

BLS signatures are used because of their aggregation-friendliness: any two signatures $S_1$ and $S_2$ of a message $M$ signed by keys $k_1$ and $k_2$ (corresponding pubkeys $K_1 = G * k_1$ and $K_2 = G * k_2$ where $G$ is the generator of the elliptic curve) can simply be aggregated by elliptic curve point addition: $S_1 + S_2$, which verifies against the public key $K_1 + K_2$. This allows many thousands of signatures to be aggregated, with the marginal cost of one signature being one bit of data (to express that a particular public key is present in the aggregate signature) and one elliptic curve addition for computation.

Note that BLS signatures of this form are vulnerable to _rogue key attacks_: if you see that other validators have already published public keys $K_1 ... K_n$, then you can generate a private key $r$ and publish a public key $G * r - K_1 - ... - K_n$. The aggregate public key would simply be $G * r$, so you would be able to make a signature that verifies against the combined public key by yourself. The standard way to get around this is to require a _proof of possession_: basically, a signature of a message (that depends on the public key, and that would normally not be signed) that verifies against the public key by itself (ie. $sign(message=H&apos;(K), key=k)$ for privkey $k$ and pubkey $K$, where $H&apos;$ is a hash function). This ensures that you personally control the private key connected to the public key that you publish.

We use the signature of a deposit message (which specifies the signing key but also other important data such as the withdrawal key) as a proof of possession.

### Why 32 ETH validator sizes?

Any BFT consensus algorithm with accountable fault tolerance (ie. if two conflicting blocks get finalized you can identify which 1/3 of nodes were responsible) must have all validators participate, and furthermore for technical reasons you need two rounds of every validator participating to finalize a message.

This leads to the decentralization / finality time / overhead tradeoff: if $n$ is the number of validators in a network, $f$ is the time to finalize a block, and $\omega$ is the overhead in messages per second, then we have:

$$\omega \ge \frac{2 * n}{f}$$

For example, if we are ok with an overhead of 10 messages per second, then a 10000-node network could only have a finality time of at least 2000 seconds (~33 minutes).

In Ethereum&apos;s case, if we assume a total ETH supply of $\approx 2^{27}$ ETH, then with 32 ETH deposit sizes, there are at most $2^{22}$ validators (and that&apos;s if everyone validates; in general we expect ~10x less ETH validating). With a finality time of 2 epochs (2 * 32 * 12 = 768 seconds), that implies a max overhead of $\frac{2^{22}}{768} \approx 5461$ messages per second. We can tolerate such high overhead due to BLS aggregation reducing the marginal size of each signature to 1 bit and the marginal verification complexity to one elliptic curve addition.

32 slots is a safe minimum for another reason: if an attacker manipulates the randomness used for proposer selection, this number still provides enough space to ensure that there will be at least one honest proposer in each epoch, which is sufficient to ensure blocks keep finalizing. Our calculations suggest that current levels of overhead are acceptable, but higher levels would make running a node too difficult. Finally, the validator deposit size is ideal for shard crosslinking (see below).

### Random sampling

#### Seed selection

The seed used for randomness is updated every block by &quot;mixing in&quot; (ie. `seed &lt;- xor(seed, new_data)`) a value that must be revealed by the proposer of the block. Just like proof of custody subkeys, a validator&apos;s values are all pre-determined once the validator has deposited, third parties cannot compute subkeys but can verify subkeys that are revealed voluntarily (this mechanism is sometimes called RANDAO).

This ensures that each proposer has one &quot;bit of manipulation&quot; over the seed: they can either make a block or not make a block. Not making a block is expensive in that the proposer misses out on many rewards. Furthermore, because the persistent and beacon committee sizes (see below) are large, manipulation of the randomness almost certainly cannot allow minority attackers to get 2/3 of any committee.

In the future we plan to use verifiable delay functions (VDFs) to further increase the random seeds&apos; robustness against manipulation.

#### Shuffling

We use the swap-or-not shuffle described by Viet Tung Hoang, Ben Morris, and Phillip Rogaway to shuffle the validator set and assign responsibilities every epoch. This algorithm ensures that:

* As the shuffle is a permutation, each validator is assigned to be a member of exactly one committee during each epoch (keeping their load stable and reducing the chance manipulation of randomness can be profitable)
* As the shuffle is pointwise-evaluable in the forward direction, a validator can determine their own responsibilities in O(1) time
* As the shuffle is pointwise-evaluable in the reverse direction, the members of any specific committee or the proposer of any specific block can be computed in O(1) time

#### Shuffling by slot

There are 32 slots in an epoch, and the validators responsible for attesting to each slot are chosen by shuffling. This ensures that attackers with a significant but still small portion of total stake cannot take over specific slots and cause short-range reorgs.

#### Beacon committees

The committee for each slot is in turn split up into some number of _beacon committees_. Today (2022 Jan), this design does serve one useful function, allowing different subsets of attestations to get aggregated in separate subnets and thus making the p2p network more efficient. However, it does not serve any other useful consensus-related role.

In the original sharding design, the intention was that each beacon committee would be responsible for verifying a specific shard. However, this approach is likely deprecated if we switch to a single-proposer model. Hence, the more fine-grained beacon committees may well only be there vestigially and could eventually be removed or re-structured in a different way to focus on facilitating attestation aggregation.

#### Sync committee

A sync committee of 512 validators is selected once every ~27 hours to sign a block; this committee&apos;s pubkeys are saved in an easily accessible list, allowing signatures to be easily verified by ultra-light clients.

### LMD GHOST fork choice rule

The beacon chain uses an LMD GHOST fork choice rule.

The LMD GHOST fork choice rule incorporates information from all validators, hundreds in each slot, making it extremely unlikely in the normal case that even a single block will be reverted. Because the fork choice is dependent on all validators, this also ensures that blocks cannot be reverted unless an attacker really does control close to 50% of the entire validator set; one cannot achieve a large advantage by manipulating the randomness.

### The proof of custody game

For each 9-day period, each validator has the ability to privately generate a &quot;period subkey&quot;. The validator&apos;s public key uniquely determines their period subkey for every period, so once a validator has deposited they have no further freedom to choose what their subkeys are. No one can compute any given validator&apos;s subkey except the validator themselves, but once a validator reveals a subkey voluntarily, anyone can verify its correctness (this is all done via BLS magic, and if quantum-safety is required in the future it can be done with hash-based commitments).

When signing a block with data $D$ with root $R$ during period $j$, letting $s$ being the period-$j$ secret of that validator, a validator is required to compute a bitfield $M$ as follows:

* Split $D$ into 512-byte chunks $D[0] ... D[n-1]$
* Set $M$ to be the bitfield where the i&apos;th bit is $M[i] = mix(s, D[i])$

They include `get_chunk_bits_root(M)` (this is called the **custody bit**) as part of what they are signing. `mix` and `get_chunk_bits_root` can both be viewed as hash-like functions that output a single bit (but are designed for multi-party-computation friendliness).

If a crosslink includes multiple blocks $B_1 ... B_n$ and the validator computes custody bits $c_1 ... c_n$ for these blocks, then the validator signs all $(B_i, c_i, i)$ tuples and aggregates them. This unconventional self-aggregation is used to ensure that there are only $2n$ different messages (n different block/index pairs * 2 different bit values) being signed by different validators, reducing the number of pairings needed to verify the signatures.

If a validator publishes their period $j$ subkey during or before period $j$, any other validator can publish a proof-of-knowledge of the subkey to the chain, which then penalizes the validator whose subkey was revealed. The proof of knowledge also proves which validator created it; this prevents block proposers from &quot;stealing&quot; the whistleblowing reward (once again all done via BLS magic, if quantum-safety is required in the future this can be done with STARKs). The goal of this is to make it dangerous to outsource computation of $M$.

After a validator publishes their period $j$ subkey, anyone else can check their work for any block that they signed. If they discover that a validator provided an incorrect custody bit, they can challenge this on-chain, and slash that validator. In general, random guessing (or any procedure that does not involve all of $D$) will only give a correct answer half the time, leading to a 50% risk of slashing per block signed.

The purpose of this mechanism is to mitigate the [validator&apos;s dilemma](/EIPs/assets/eip-2982/iacr-2015-702-Demystifying-Incentives-in-the-Consensus-Computer.pdf) problem, where validators have an incentive to avoid verifying data out of laziness and piggyback on the assumption that all _other_ validators are honest; if too many validators think in this way, it could lead to a tragedy of the commons leading to the chain accepting invalid blocks. With this scheme, if a validator attempts to commit to data that they did not personally process, then they would not be able to compute $M$, and so would lose the interactive challenge game.

### SSZ

The SimpleSerialize suite contains the following algorithms:

* A serialization algorithm
* A hashing algorithm (called `SSZTreeHash` or `hash_tree_root`)
* A generalized Merkle proof algorithm (called &quot;SSZ partials&quot;) that can handle proofs for multiple values and optimally deduplicates Merkle tree sister nodes in such cases.

The serialization algorithm has the following design goals:

* Simplicity (eg. no three clauses like RLP has for long / list encoding depending on item length)
* Being equivalent to simple concatenation in the case of entirely fixed-size objects
* Being usable as both a consensus-layer serialization algorithm and an application-layer ABI

Note that the resulting SSZ serialization spec is very similar to the ethereum 1.0 ABI, with the major differences being (i) different basic data types and (ii) replacing the 32 byte length/position record size with a 4 byte size.

The hashing algorithm has the following design goals:

* Efficiency of computing the hash of an updated object, especially in the case where the object is very large and/or complex and the change is relatively small
* Efficiency (in terms of verification complexity _and_ witness size) of proving the value of a specific field even in a large or complex object with a given hash

These requirements together make a Merkle tree structure the obvious choice.

#### Generalized indices

See https://github.com/ethereum/eth2.0-specs/blob/dev/ssz/merkle-proofs.md for a description of generalized indices, and how they allow for very easy verification of Merkle proofs &quot;poking into&quot; arbitrary positions in an object by representing paths as an integer or bitfield.

### The validator lifecycle

#### Depositing

A validator deposits by sending a transaction that calls a function on the deposit contract on the eth1 chain (eventually, a way to deposit from inside eth2 will also be added). A deposit specifies:

* The public key corresponding to the private key that will be used to sign messages
* The withdrawal credentials (hash of the public key that will be used to withdraw funds once the validator is done validating)
* The deposit amount

These values are all signed by the signing key. The goal of having separate signing and withdrawal keys is to allow the more dangerous withdrawal key to be kept more securely (offline, not shared with any staking pools, etc) while the signing key is used to actively sign a message every epoch.

The deposit contract maintains a Merkle root of all deposits made so far. Once a merkle root containing the deposit gets included into the eth2 chains (via the Eth1Data voting mechanism), an eth2 block proposer can submit a Merkle proof of the deposit and start the deposit process.

#### Activation

The validator immediately joins the validator registry, but is at first inactive. The validator becomes active after $N \ge 4$ epochs; the minimum of 4 is there to ensure the RANDAO is not manipulable, and $N$ may exceed 4 if too many validators try to join at the same time. If the active validator set has size $|V|$, a maximum of $max(4, \frac{|V|}{65536})$ validators can join per epoch; if more validators try to join, they are put in a queue and processed as quickly as possible.

#### Exiting

When a validator exits (whether by publishing a voluntary exit message or being slashed), they are similarly put into an exit queue with the same maximum throughput.

The reason for the entrance/exit queue limits is to ensure that the validator set cannot change too quickly between any two points in time, which ensures that finality guarantees still remain between two chains as long as a validator logs on often enough (once every ~1-2 months if $|V| \ge 262144$). See here https://ethresear.ch/t/rate-limiting-entry-exits-not-withdrawals/4942 for rationale (and specifically why to use a rate limit instead of a fixed waiting time) and https://ethresear.ch/t/weak-subjectivity-under-the-exit-queue-model/5187 for how to calculate safety margin for a client that has been offline for some amount of time.

#### Withdrawal

Once a validator leaves the exit queue, there is a ~27 hour period until they can withdraw. This period has several functions:

* It ensures that if a validator misbehaved there is a period of time within which the error can be caught and the validator can be slashed even if the exit queue is nearly empty.
* It provides time for the last period of shard rewards to be included.
* It provides time for proof of custody challenges to be made.

If a validator is slashed, a further delay of ~36 days is imposed. This further penalizes them (and forces them to hold the ETH; this makes the penalty somewhat larger for malicious validators that are trying to destroy the ethereum blockchain than those validators that want to support the platform but just made a mistake, as the former category would have to risk the exposure or pay for derivatives to cancel it out), but also allows for a period during which the number of other validators that got slashed can be calculated.

In phase 0, a &quot;withdrawn&quot; validator cannot actually withdraw to anywhere yet; the only distinction is that it is protected from validator penalties and does not have any responsibilities. In later phases, the ability to move funds from a withdrawn validator slot to an execution environment will be made available.

#### Effective balances

Most calculations based on a validator&apos;s balance use the validator&apos;s &quot;effective balance&quot;; the only exception is calculations that increase or decrease the validator&apos;s balance. Only when the validators&apos;s balance $B$ falls below $EB$ or goes above $EB + 1.5$ is $EB$ adjusted to equal $floor(B)$. This is done to ensure that effective balance changes infrequently, reducing the amount of hashing needed to recompute the state every epoch; on average, only the balances need to all be updated, and the effective balances only get updated relatively rarely per validator. Balances are all stored in a dedicated vector, so $2 * \frac{N * 8}{32} = \frac{N}{2}$ hashes are needed to recompute a balance array, whereas effective balances are stored in validator record objects, where at least $5N$ hashes would be needed per validator to adjust the SSZ hash roots. Additionally, $EB$ can be compressed more easily into a CompactValidator object, as it&apos;s only one byte.

### Fork mechanism

The `Fork` data structure contains (i) the current &quot;fork ID&quot;, (ii) the previous fork ID and (iii) the switchover slot. The fork ID at the current height influences the valid signatures of all messages; hence, a message signed with one fork ID is invalid to a verification function using any other fork ID.

A fork is done by adding a state transition at some &quot;fork slot&quot; $n$ which sets the previous fork ID to the current fork ID, the current fork ID to a new value, and the switchover slot to $n$. Signature verification functions will verify messages using the fork ID at the slot the message is for, which could be the previous fork ID or the current one (eg. consider the case of attestations included after a delay; an attestation from before the fork slot could be included after the fork slot).

If any users do not want to join the fork, they can simply continue the chain that does not change the fork ID at the fork slot. The two chains would be able to proceed and validators would be free to validate on both without getting slashed.

## Backwards Compatibility

Although this EIP does not introduce any immediate changes to the current Ethereum mainnet, this EIP lays the groundwork for future backwards incompatibilities through the introduction of the new eth2 consensus mechanism in which Ethereum will be integrated in subsequent phases. To secure this mechanism, users move ether into the beacon chain and additional ether is issued. This EIP is a commitment to this path being canonical, as well as directly informing the future and roadmap of Ethereum mainnet.

## Security Considerations

Eth2 is a major overhaul of the Ethereum&apos;s core consensus from PoW to a sharded PoS. There are inherent risks in this migration but there is extensive research literature analyzing security and trade-offs. _The following only represents a high level selection of the resources available:_

* [Casper FFG](/EIPs/assets/eip-2982/arxiv-1710.09437-Casper-the-Friendly-Finality-Gadget.pdf)
* [Combining GHOST and Casper](/EIPs/assets/eip-2982/arxiv-2003.03052-Combining-GHOST-and-Casper.pdf)

In addition to the research supporting this path, a number of audits and formal verification of specs, cryptography, and client implementations have been performed. _Many client and utility library audits are currently in progress and will be appended here upon completion._

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 15 Sep 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2982</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2982</guid>
      </item>
    
      <item>
        <title>IMPERSONATECALL Opcode</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethresear.ch/t/impersonatecall-opcode/8020</comments>
        
        <description>## Abstract

Add a new opcode, `IMPERSONATECALL` at `0xf6`, which is similar in idea to `CALL (0xF1)`, except that it impersonates a sender, i.e. the callee sees a sender different from the real caller. The impersonated sender address is derived from the real caller address and a salt.

## Motivation

This proposal enables native multi-user wallets (wallets that serve multiple users) that can be commanded by EIP-712 based messages and therefore enable meta-transactions. Multi-user wallets also enable the aggregation of transfer operations in batches similar to rollups, but maintaining the same address space as normal onchain transactions, so the sender&apos;s wallet does not need to be upgraded to support sinding ether or tokens to a user of a multi-user wallet. 
Additionally, many times a sponsor company wants to deploy non-custodial smart wallets for all its users. The sponsor does not want to pay the deployment cost of each user contract in advance. Counterfactual contract creation enables this, yet it forces the sponsor to create the smart wallet (or a proxy contract to it) when the user wants to transfer ether or tokens out of his/her account for the first time. This proposal avoids this extra cost, which is at least 42000 gas per user. 


## Specification

`IMPERSONATECALL`: `0xf6`, takes 7 operands:

- `gas`: the amount of gas the code may use in order to execute;
- `to`: the destination address whose code is to be executed;
- `in_offset`: the offset into memory of the input;
- `in_size`: the size of the input in bytes;
- `ret_offset`: the offset into memory of the output;
- `ret_size`: the size of the scratch pad for the output.
- `salt` is a `32` bytes value (a stack item). 

### Computation of impersonated sender

The impersonated sender address is computed as `keccak256( 0xff ++ address ++ salt ++ zeros32)[12:]`.

- `0xff` is a single byte, 
- `address` is always `20` bytes, and represents the address of the real caller contract.
- `salt` is always `32` bytes. 

- The field zeros32 corresponds to 32 zero bytes.

This scheme emulates `CREATE2` address derivation, but it cannot practically collude with the `CREATE2` address space.

### Notes
- The opcode behaves exactly as `CALL` in terms of gas consumption.
- In the called context `CALLER (0x33)` returns the impersonated address.
- If value transfer is non-zero in the call, the value is transferred from the impersonated account, and not from the real caller. This can be used to transfer ether out of an impersonated account.

## Rationale

Even if `IMPERSONATECALL` requires hashing 3 words, implying an additional cost of 180 gas, we think the benefit of accounting for hashing doesn&apos;t not compensate increasing the complexity of the implementation.

We use the zeros32 field to base address derivation in a pre-image of similar size than CREATE2 and reuse the existing address derivation functions. We also avoid worrying about address collisions between EOA derivation (65 bytes pre-image), CREATE derivation (from 23 to 27 bytes pre-image, for a 32bit nonce) and CREATE2 derivation (85 bytes pre-image). 

An option is to omit the zeros32 field: the resulting length of the Keccak pre-image for IMPERSONATECALL address is 53 bytes , which does not generate address collision.

While the same functionality could be provided in a pre-compiled contract, we believe using a new opcode is a cleaner solution.


## Clarifications

- This EIP makes address collisions possible, yet practically impossible.

- If a contract already exists with an impersonated address, the `IMPERSONATECALL` is executed in the same way, and the existing code will not be executed. It should  be noted that `SELFDESTRUCT` (`0xff`) cannot be executed directly with `IMPERSONATECALL` as no opcode is executed in the context of the impersonated account.

## Backward Compatibility

The opcode number  `0xf6` is currently unused and results in an out-of-gas (OOG) exception.  Solidity uses the `INVALID (0xfe)` opcode (called `ABORT` by EIP-1803) to raise OOG exceptions, so the  `0xf6` opcode does not appear in normal Solidity programs. Programmers are already advised not to include this opcode in contracts written in EVM assembly.  Therefore is does not pose any backward compatibility risk.

## Test Cases

We present 4 examples of impersonated address derivation:

Example 0

* address `0x0000000000000000000000000000000000000000`
* salt `0x0000000000000000000000000000000000000000000000000000000000000000`
* result: `0xFFC4F52F884A02BCD5716744CD622127366F2EDF`

Example 1
* address `0xdeadbeef00000000000000000000000000000000`
* salt `0x0000000000000000000000000000000000000000000000000000000000000000`
* result: `0x85F15E045E1244AC03289B48448249DC0A34AA30`

Example 2
* address `0xdeadbeef00000000000000000000000000000000`
* salt `0x000000000000000000000000feed000000000000000000000000000000000000`
* result: `0x2DB27D1D6BE32C9ABFA484BA3D591101881D4B9F`

Example 3
* address `0x00000000000000000000000000000000deadbeef`
* salt `0x00000000000000000000000000000000000000000000000000000000cafebabe`
* result: `0x5004E448F43EFE3C7BF32F94B83B843D03901457`

## Security Considerations

The address derivation scheme prevents address collision with another deployed contract or an externally owned account, as the impersonated sender address is derived from the real caller address and a salt.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 24 Sep 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-2997</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-2997</guid>
      </item>
    
      <item>
        <title>Optimistic enactment governance standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/3042</comments>
        
        <description>## Simple Summary

Interface for scheduling, executing and challenging contract executions based on off-chain approval

## Abstract

ERC-3000 presents a basic on-chain spec for contracts to optimistically enact governance decisions made off-chain.

The standard is opinionated in defining the 6 entrypoint functions to contracts supporting the standard. But it allows for any sort of resolver mechanism for the challenge/response games characteristic of optimistic contracts.

While the authors currently believe resolving challenges [using a subjective oracle](https://aragon.org/blog/snapshot) is the right tradeoff, the standard has been designed such that changing to another mechanism is possible (a deterministic resolver like [Optimism&apos;s OVM](https://optimism.io) uses), even allowing to hot-swap it in the same live instance.

## Specification

### Data structures

Some data structures are defined which are later used in the standard interfaces:

```solidity
library ERC3000Data {
    struct Container {
        Payload payload;
        Config config;
    }

    struct Payload {
        uint256 nonce;
        uint256 executionTime;
        address submitter;
        IERC3000Executor executor;
        Action[] actions;
        bytes proof;
    }

    struct Action {
        address to;
        uint256 value;
        bytes data;
    }

    struct Config {
        uint256 executionDelay;
        Collateral scheduleDeposit;
        Collateral challengeDeposit;
        Collateral vetoDeposit;
        address resolver;
        bytes rules;
    }

    struct Collateral {
        address token;
        uint256 amount;
    }
}
```

### Interface and events

Given the data structures above, by taking advantage of the Solidity ABI encoder v2, we define four required functions and two optional functions as the interface for contracts to comply with ERC-3000.

All standard functions are expected to revert (whether to include error messages/revert reasons as part of the standard is yet to be determined) when pre-conditions are not met or an unexpected error occurs. On success, each function must emit its associated event once and only once.

```solidity
abstract contract IERC3000 {
    /**
     * @notice Schedules an action for execution, allowing for challenges and vetos on a defined time window
     * @param container A Container struct holding both the paylaod being scheduled for execution and
       the current configuration of the system
     */
    function schedule(ERC3000Data.Container memory container) virtual public returns (bytes32 containerHash);
    event Scheduled(bytes32 indexed containerHash, ERC3000Data.Payload payload, ERC3000Data.Collateral collateral);

    /**
     * @notice Executes an action after its execution delayed has passed and its state hasn&apos;t been altered by a challenge or veto
     * @param container A ERC3000Data.Container struct holding both the paylaod being scheduled for execution and
       the current configuration of the system
     * should be a MUST payload.executor.exec(payload.actions)
     */
    function execute(ERC3000Data.Container memory container) virtual public returns (bytes[] memory execResults);
    event Executed(bytes32 indexed containerHash, address indexed actor, bytes[] execResults);

    /**
     * @notice Challenge a container in case its scheduling is illegal as per Config.rules. Pulls collateral and dispute fees from sender into contract
     * @param container A ERC3000Data.Container struct holding both the paylaod being scheduled for execution and
       the current configuration of the system
     * @param reason Hint for case reviewers as to why the scheduled container is illegal
     */
    function challenge(ERC3000Data.Container memory container, bytes memory reason) virtual public returns (uint256 resolverId);
    event Challenged(bytes32 indexed containerHash, address indexed actor, bytes reason, uint256 resolverId, ERC3000Data.Collateral collateral);

    /**
     * @notice Apply arbitrator&apos;s ruling over a challenge once it has come to a final ruling
     * @param container A ERC3000Data.Container struct holding both the paylaod being scheduled for execution and
       the current configuration of the system
     * @param resolverId disputeId in the arbitrator in which the dispute over the container was created
     */
    function resolve(ERC3000Data.Container memory container, uint256 resolverId) virtual public returns (bytes[] memory execResults);
    event Resolved(bytes32 indexed containerHash, address indexed actor, bool approved);

    /**
     * @dev OPTIONAL
     * @notice Apply arbitrator&apos;s ruling over a challenge once it has come to a final ruling
     * @param payloadHash Hash of the payload being vetoed
     * @param config A ERC3000Data.Config struct holding the config attached to the payload being vetoed
     */
    function veto(bytes32 payloadHash, ERC3000Data.Config memory config, bytes memory reason) virtual public;
    event Vetoed(bytes32 indexed containerHash, address indexed actor, bytes reason, ERC3000Data.Collateral collateral);

    /**
     * @dev OPTIONAL: implementer might choose not to implement (initial Configured event MUST be emitted)
     * @notice Apply a new configuration for all *new* containers to be scheduled
     * @param config A ERC3000Data.Config struct holding all the new params that will control the queue
     */
    function configure(ERC3000Data.Config memory config) virtual public returns (bytes32 configHash);
    event Configured(bytes32 indexed containerHash, address indexed actor, ERC3000Data.Config config);
}
```

## Rationale

The authors believe that it is very important that this standard leaves the other open to any resolver mechanism to be implemented and adopted.

That&apos;s why a lot of the function and variable names were left intentionally bogus to be compatible with future resolvers without changing the standard.

ERC-3000 should be seen as a public good of top of which public infrastrastructure will be built, being way more important than any particular implementation or the interests of specific companies or projects.

## Security Considerations

The standard allows for the resolver for challenges to be configured, and even have different resolvers for coexisting scheduled payloads. Choosing the right resolver requires making the right tradeoff between security, time to finality, implementation complexity, and external dependencies.

Using a subjective oracle as resolver has its risks, since security depends on the crypto-economic properties of the system. For an analysis of crypto-economic considerations of Aragon Court, you can check [the following doc](https://github.com/aragon/aragon-court/tree/master/docs/3-cryptoeconomic-considerations).

On the other hand, implementing a deterministic resolver is prone to dangerous bugs given its complexity, and will rely on a specific version of the off-chain protocol, which could rapidly evolve while the standard matures and gets adopted.

## Implementations

### 1. Aragon Govern

- [ERC-3000 interface (MIT license)](https://github.com/aragon/govern/blob/master/packages/erc3k)
- [Implementation (GPL-3.0 license)](https://github.com/aragon/govern/blob/master/packages/govern-core)

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 24 Sep 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3000</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3000</guid>
      </item>
    
      <item>
        <title>Batched meta transactions</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3005-the-economic-viability-of-batched-meta-transactions/4673</comments>
        
        <description>## Simple Summary

Defines an extension function for ERC-20 (and other fungible token standards), which allows receiving and processing a batch of meta transactions.

## Abstract

This EIP defines a new function called `processMetaBatch()` that extends any fungible token standard, and enables batched meta transactions coming from many senders in one on-chain transaction. 

The function must be able to receive multiple meta transactions data and process it. This means validating the data and the signature, before proceeding with token transfers based on the data.

The function enables senders to make gasless transactions, while reducing the relayer&apos;s gas cost due to batching.

## Motivation

Meta transactions have proven useful as a solution for Ethereum accounts that don&apos;t have any ether, but hold ERC-20 tokens and would like to transfer them (gasless transactions).

The current meta transaction relayer implementations only allow relaying one meta transaction at a time. Some also allow batched meta transactions from the same sender. But none offers batched meta transactions from **multiple** senders.

The motivation behind this EIP is to find a way to allow relaying batched meta transactions from **many senders** in **one on-chain transaction**, which also **reduces the total gas cost** that a relayer needs to cover.

![](/EIPs/assets/eip-3005/meta-txs-directly-to-token-smart-contract.png)

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;,  &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

The key words &quot;MUST (BUT WE KNOW YOU WON&apos;T)&quot;, &quot;SHOULD CONSIDER&quot;, &quot;REALLY SHOULD NOT&quot;, &quot;OUGHT TO&quot;, &quot;WOULD PROBABLY&quot;, &quot;MAY WISH TO&quot;, &quot;COULD&quot;, &quot;POSSIBLE&quot;, and &quot;MIGHT&quot; in this document are to be interpreted as described in RFC 6919.  

### Meta transaction data

In order to successfully validate and transfer tokens, the `processMetaBatch()` function MUST process the following data about a meta transaction:

- sender address
- receiver address
- token amount
- relayer fee
- a (meta tx) nonce
- an expiration date (this COULD be a block number, or it COULD be a block timestamp)
- a token address
- a relayer address
- a signature

Not all of the data needs to be sent to the function by the relayer (see the function interface specification). Some of the data can be deduced or extracted from other sources (from transaction data and contract state).

### `processMetaBatch()` function input data

The `processMetaBatch()` function MUST receive the following data:

- sender address
- receiver address
- token amount
- relayer fee
- an expiration date (this COULD be a block number, or it COULD be a block timestamp)
- a signature

The following data is OPTIONAL to be sent to the function, because it can be extracted or derived from other sources:

- a (meta tx) nonce
- a token address
- a relayer address

### Meta transaction data hash

The pseudocode for creating a hash of meta transaction data is the following:

```
keccak256(address(sender)
	   ++ address(recipient)
	   ++ uint256(amount)
	   ++ uint256(relayerFee)
	   ++ uint256(nonce)
	   ++ uint256(expirationDate)
	   ++ address(tokenContract)
	   ++ address(relayer)
)
```

The created hash MUST then be signed with the sender&apos;s private key.

### Validation rules

- Nonce of a new transaction MUST always be bigger by exactly 1 from the nonce of the last successfully processed meta transaction of the same sender to the same token contract.
- Sending to and from a 0x0 address MUST be prohibited.
- A meta transaction MUST be processed before the expiration date.
- Each sender&apos;s token balance MUST be equal or greater than the sum of their respective meta transaction token amount and relayer fee.
- A transaction where at least one meta transaction in the batch does not satisfy the above requirements MUST not be reverted. Instead, a failed meta transaction MUST be skipped or ignored.

### `processMetaBatch()` function interface

The `processMetaBatch()` function MUST have the following interface:

```solidity
function processMetaBatch(address[] memory senders,
                          address[] memory recipients,
                          uint256[] memory amounts,
                          uint256[] memory relayerFees,
                          uint256[] memory blocks,
                          uint8[] memory sigV,
                          bytes32[] memory sigR,
                          bytes32[] memory sigS) public returns (bool);
```

The overview of parameters that are passed:

- `senders`: an array of meta transaction sender addresses (token senders)
- `recipients `: an array of token recipients addresses
- `amounts`: an array of token amounts that are sent from each sender to each recipient, respectively
- `relayerFees`: an array of the relayer fees paid in tokens by senders. The fee receiver is a relayer (`msg.address`)
- `blocks`: an array of block numbers that represent an expiration date by which the meta transaction must be processed (alternatively, a timestamp could be used instead of a block number)
- `sigV`, `sigR`, `sigS`: three arrays that represent parts of meta transaction signatures

Each entry in each of the arrays MUST represent data from one meta transaction. The order of the data is very important. Data from a single meta transaction MUST have the same index in every array.

### Meta transaction nonce

The token smart contract must keep track of a meta transaction nonce for each token holder.

```solidity
mapping (address =&gt; uint256) private _metaNonces;
```

The interface for the `nonceOf()` function is the following:

```solidity
function nonceOf(address account) public view returns (uint256);
```

### Token transfers

After a meta transaction is successfully validated, the meta nonce of the meta transaction sender MUST be increased by 1. 

Then two token transfers MUST occur:

- The specified token amount MUST go to the recipient.
- The relayer fee MUST go to the relayer (`msg.sender`).

## Implementation

The **reference implementation** adds a couple of functions to the existing ERC-20 token standard:

- `processMetaBatch()`
- `nonceOf()`

You can see the implementation of both functions in this file: [ERC20MetaBatch.sol](https://github.com/defifuture/erc20-batched-meta-transactions/blob/master/contracts/ERC20MetaBatch.sol). This is an extended ERC-20 contract with added meta transaction batch transfer capabilities.

### `processMetaBatch()`

The `processMetaBatch()` function is responsible for receiving and processing a batch of meta transactions that change token balances.

```solidity
function processMetaBatch(address[] memory senders,
                          address[] memory recipients,
                          uint256[] memory amounts,
                          uint256[] memory relayerFees,
                          uint256[] memory blocks,
                          uint8[] memory sigV,
                          bytes32[] memory sigR,
                          bytes32[] memory sigS) public returns (bool) {
    
    address sender;
    uint256 newNonce;
    uint256 relayerFeesSum = 0;
    bytes32 msgHash;
    uint256 i;

    // loop through all meta txs
    for (i = 0; i &lt; senders.length; i++) {
        sender = senders[i];
        newNonce = _metaNonces[sender] + 1;

        if(sender == address(0) || recipients[i] == address(0)) {
            continue; // sender or recipient is 0x0 address, skip this meta tx
        }

        // the meta tx should be processed until (including) the specified block number, otherwise it is invalid
        if(block.number &gt; blocks[i]) {
            continue; // if current block number is bigger than the requested number, skip this meta tx
        }

        // check if meta tx sender&apos;s balance is big enough
        if(_balances[sender] &lt; (amounts[i] + relayerFees[i])) {
            continue; // if sender&apos;s balance is less than the amount and the relayer fee, skip this meta tx
        }

        // check if the signature is valid
        msgHash = keccak256(abi.encode(sender, recipients[i], amounts[i], relayerFees[i], newNonce, blocks[i], address(this), msg.sender));
        if(sender != ecrecover(keccak256(abi.encodePacked(&quot;\x19Ethereum Signed Message:\n32&quot;, msgHash)), sigV[i], sigR[i], sigS[i])) {
            continue; // if sig is not valid, skip to the next meta tx
        }

        // set a new nonce for the sender
        _metaNonces[sender] = newNonce;

        // transfer tokens
        _balances[sender] -= (amounts[i] + relayerFees[i]);
        _balances[recipients[i]] += amounts[i];
        relayerFeesSum += relayerFees[i];
    }

	// give the relayer the sum of all relayer fees
    _balances[msg.sender] += relayerFeesSum;

    return true;
}
```

### `nonceOf()`

Nonces are needed due to the replay protection (see *Replay attacks* under *Security Considerations*).

```solidity
mapping (address =&gt; uint256) private _metaNonces;

// ...

function nonceOf(address account) public view returns (uint256) {
    return _metaNonces[account];
}
```

The link to the complete implementation (along with gas usage results) is here: [https://github.com/defifuture/erc20-batched-meta-transactions](https://github.com/defifuture/erc20-batched-meta-transactions).

&gt; Note that the OpenZeppelin ERC-20 implementation was used here. Some other implementation may have named the `_balances` mapping differently, which would require minor changes in the `processMetaBatch()` function.

## Rationale

### All-in-one

Alternative implementations (like GSN) use multiple smart contracts to enable meta transactions, although this increases gas usage. This implementation (EIP-3005) intentionally keeps everything within one function which reduces complexity and gas cost.

The `processMetaBatch()` function thus does the job of receiving a batch of meta transactions, validating them, and then transferring tokens from one address to another.

### Function parameters

As you can see, the `processMetaBatch()` function in the reference implementation takes the following parameters:

- an array of **sender addresses** (meta txs senders, not relayers)
- an array of **receiver addresses**
- an array of **amounts**
- an array of **relayer fees** (relayer is `msg.sender`)
- an array of **block numbers** (a due &quot;date&quot; for meta tx to be processed)
- Three arrays that represent parts of a **signature** (v, r, s)

**Each item** in these arrays represents **data of one meta transaction**. That&apos;s why the **correct order** in the arrays is very important.

If a relayer gets the order wrong, the `processMetaBatch()` function would notice that (when validating a signature), because the hash of the meta transaction values would not match the signed hash. A meta transaction with an invalid signature is **skipped**.

### The alternative way of passing meta transaction data into the function

The reference implementation takes parameters as arrays. There&apos;s a separate array for each meta transaction data category (the ones that cannot be deduced or extracted from other sources).

A different approach would be to bitpack all data of a meta transaction into one value and then unpack it within the smart contract. The data for a batch of meta transactions would be sent in an array, but there would need to be only one array (of packed data), instead of multiple arrays.

### Why is nonce not one of the parameters in the reference implementation?

Meta nonce is used for constructing a signed hash (see the `msgHash` line where a `keccak256` hash is constructed - you&apos;ll find a nonce there). 

Since a new nonce has to always be bigger than the previous one by exactly 1, there&apos;s no need to include it as a parameter array in the `processMetaBatch()` function, because its value can be deduced.

This also helps avoid the &quot;Stack too deep&quot; error.

### Can EIP-2612 nonces mapping be re-used?

The EIP-2612 (`permit()` function) also requires a nonce mapping. At this point, I&apos;m not sure yet if this mapping should be **re-used** in case a smart contract implements both EIP-3005 and EIP-2612. 

At the first glance, it seems the `nonces` mapping from EIP-2612 could be re-used, but this should be thought through (and tested) for possible security implications.

### Token transfers

Token transfers in the reference implementation could alternatively be done by calling the `_transfer()` function (part of the OpenZeppelin ERC-20 implementation), but it would increase the gas usage and it would also revert the whole batch if some meta transaction was invalid (the current implementation just skips it).

Another gas usage optimization is to assign total relayer fees to the relayer at the end of the function, and not with every token transfer inside the for loop (thus avoiding multiple SSTORE calls that cost 5&apos;000 gas).

## Backwards Compatibility

The code implementation of batched meta transactions is backwards compatible with any fungible token standard, for example, ERC-20 (it only extends it with one function).

## Test Cases

Link to tests: [https://github.com/defifuture/erc20-batched-meta-transactions/tree/master/test](https://github.com/defifuture/erc20-batched-meta-transactions/tree/master/test).

## Security Considerations

Here is a list of potential security issues and how are they addressed in this implementation.

### Forging a meta transaction

The solution against a relayer forging a meta transaction is for a user to sign the meta transaction with their private key.

The `processMetaBatch()` function then verifies the signature using `ecrecover()`.

### Replay attacks

The `processMetaBatch()` function is secure against two types of a replay attack:

**Using the same meta transaction twice in the same token smart contract**

A nonce prevents a replay attack where a relayer would send the same meta transaction more than once.

**Using the same meta transaction twice in different token smart contracts**

A token smart contract address must be added into the signed hash (of a meta transaction). 

This address does not need to be sent as a parameter into the `processMetaBatch()` function. Instead, the function uses `address(this)` when constructing a hash in order to verify the signature. This way a meta transaction not intended for the token smart contract would be rejected (skipped).

### Signature validation

Signing a meta transaction and validating the signature is crucial for this whole scheme to work.

The `processMetaBatch()` function validates a meta transaction signature, and if it&apos;s **invalid**, the meta transaction is **skipped** (but the whole on-chain transaction is **not reverted**).

```solidity
msgHash = keccak256(abi.encode(sender, recipients[i], amounts[i], relayerFees[i], newNonce, blocks[i], address(this), msg.sender));

if(sender != ecrecover(keccak256(abi.encodePacked(&quot;\x19Ethereum Signed Message:\n32&quot;, msgHash)), sigV[i], sigR[i], sigS[i])) {
    continue; // if sig is not valid, skip to the next meta tx
}
```

Why not reverting the whole on-chain transaction? Because there could be only one problematic meta transaction, and the others should not be dropped just because of one rotten apple.

That said, it is expected of relayers to validate meta transactions in advance before relaying them. That&apos;s why relayers are not entitled to a relayer fee for an invalid meta transaction.

### Malicious relayer forcing a user into over-spending

A malicious relayer could delay sending some user&apos;s meta transaction until the user would decide to make the token transaction on-chain.

After that, the relayer would relay the delayed meta transaction which would mean that the user would have made two token transactions (over-spending).

**Solution:** Each meta transaction should have an &quot;expiry date&quot;. This is defined in a form of a block number by which the meta transaction must be relayed on-chain.

```solidity
function processMetaBatch(...
                          uint256[] memory blocks,
                          ...) public returns (bool) {
    
    //...

	// loop through all meta txs
    for (i = 0; i &lt; senders.length; i++) {

        // the meta tx should be processed until (including) the specified block number, otherwise it is invalid
        if(block.number &gt; blocks[i]) {
            continue; // if current block number is bigger than the requested number, skip this meta tx
        }

        //...
```

### Front-running attack

A malicious relayer could scout the Ethereum mempool to steal meta transactions and front-run the original relayer.

**Solution:** The protection that `processMetaBatch()` function uses is that it requires the meta transaction sender to add the relayer&apos;s Ethereum address as one of the values in the hash (which is then signed).

When the `processMetaBatch()` function generates a hash it includes the `msg.sender` address in it:

```solidity
msgHash = keccak256(abi.encode(sender, recipients[i], amounts[i], relayerFees[i], newNonce, blocks[i], address(this), msg.sender));

if(sender != ecrecover(keccak256(abi.encodePacked(&quot;\x19Ethereum Signed Message:\n32&quot;, msgHash)), sigV[i], sigR[i], sigS[i])) {
    continue; // if sig is not valid, skip to the next meta tx
}
```

If the meta transaction was &quot;stolen&quot;, the signature check would fail because the `msg.sender` address would not be the same as the intended relayer&apos;s address.

### A malicious (or too impatient) user sending a meta transaction with the same nonce through multiple relayers at once

A user that is either malicious or just impatient could submit a meta transaction with the same nonce (for the same token contract) to various relayers. Only one of them would get the relayer fee (the first one on-chain), while the others would get an invalid meta transaction.

**Solution:** Relayers could **share a list of their pending meta transactions** between each other (sort of an info mempool).

The relayers don&apos;t have to fear that someone would steal their respective pending transactions, due to the front-running protection (see above).

If relayers see meta transactions from a certain sender address that have the same nonce and are supposed to be relayed to the same token smart contract, they can decide that only the first registered meta transaction goes through and others are dropped (or in case meta transactions were registered at the same time, the remaining meta transaction could be randomly picked).

At a minimum, relayers need to share this meta transaction data (in order to detect meta transaction collision):

- sender address
- token address
- nonce

### Too big due block number

The relayer could trick the meta transaction sender into adding too big due block number - this means a block by which the meta transaction must be processed. The block number could be far in the future, for example, 10 years in the future. This means that the relayer would have 10 years to submit the meta transaction.

**One way** to solve this problem is by adding an upper bound constraint for a block number within the smart contract. For example, we could say that the specified due block number must not be bigger than 100&apos;000 blocks from the current one (this is around 17 days in the future if we assume 15 seconds block time).

```solidity
// the meta tx should be processed until (including) the specified block number, otherwise it is invalid
if(block.number &gt; blocks[i] || blocks[i] &gt; (block.number + 100000)) {
    // If current block number is bigger than the requested due block number, skip this meta tx.
    // Also skip if the due block number is too big (bigger than 100&apos;000 blocks in the future).
    continue;
}
```

This addition could open new security implications, that&apos;s why it is left out of this proof-of-concept. But anyone who wishes to implement it should know about this potential constraint, too.

**The other way** is to keep the `processMetaBatch()` function as it is and rather check for the too big due block number **on the relayer level**. In this case, the user could be notified about the problem and could issue a new meta transaction with another relayer that would have a much lower block parameter (and the same nonce).

## Copyright

Copyright and related rights are waived via [CC0](/EIPs/LICENSE).</description>
        <pubDate>Fri, 25 Sep 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3005</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3005</guid>
      </item>
    
      <item>
        <title>Transfer With Authorization</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-3009-transfer-with-authorization/25698</comments>
        
        <description>## Abstract

A set of functions to enable meta-transactions and atomic interactions with [ERC-20](/EIPs/EIPS/eip-20) token contracts via signatures conforming to the [EIP-712](/EIPs/EIPS/eip-712) typed message signing specification.

This enables the user to:

- delegate the gas payment to someone else,
- pay gas in the token itself rather than in ETH,
- perform one or more token transfers and other operations in a single atomic transaction,
- transfer ERC-20 tokens to another address, and have the recipient submit the transaction,
- batch multiple transactions with minimal overhead, and
- create and perform multiple transactions without having to worry about them failing due to accidental nonce-reuse or improper ordering by the miner.

Please note that this ERC does not apply to smart contract accounts, as the `transfer` and `approve`/`transferFrom` functions from the ERC-20 standards can directly be used.

&lt;!-- TODO (Editor&apos;s note): we don&apos;t permit links outside of the EIP/ERC repositories, with some exceptions noted in EIP-1

This ERC has been live in production within the USDC smart contract since 2020, and serves as a critical component of the [x402](https://www.x402.org/) standard.

--&gt;

## Motivation

There is an existing spec, [ERC-2612](/EIPs/EIPS/eip-2612), that also allows meta-transactions, and it is encouraged that a contract implements both for maximum compatibility. The two primary differences between this spec and ERC-2612 are that:

- ERC-2612 uses sequential nonces, but this uses random 32-byte nonces, and that
- ERC-2612 relies on the ERC-20 `approve`/`transferFrom` (&quot;ERC-20 allowance&quot;) pattern.

The biggest issue with the use of sequential nonces is that it does not allow users to perform more than one transaction at a time without risking their transactions failing, because:

- DApps may unintentionally reuse nonces that have not yet been processed in the blockchain.
- Miners may process the transactions in the incorrect order.

This can be especially problematic if the gas prices are very high and transactions often get queued up and remain unconfirmed for a long time. Non-sequential nonces allow users to create as many transactions as they want at the same time.

The ERC-20 allowance mechanism is susceptible to the &lt;!-- TODO (Editor&apos;s note): same note as above.
[multiple withdrawal attack](https://blockchain-projects.readthedocs.io/multiple_withdrawal.html) --&gt;/&lt;!-- TODO (Editor&apos;s note): you can copy the SWC into your assets directory because it&apos;s MIT licensed. [SWC-114](https://swcregistry.io/docs/SWC-114) --&gt;, and encourages antipatterns such as the use of the &quot;infinite&quot; allowance. The wide prevalence of upgradeable contracts has made the conditions favorable for these attacks to happen in the wild.

The deficiencies of the ERC-20 allowance pattern brought about the development of alternative token standards such as the [ERC-777](/EIPs/EIPS/eip-777) and &lt;!-- TODO (Editor&apos;s note): if you&apos;d like to link to ERC-677, you&apos;ll need to pull request it into the repository (i.e. upgrade it) [ERC-677](https://github.com/ethereum/EIPs/issues/677) --&gt;. However, they haven&apos;t been able to gain much adoption due to compatibility and potential security issues.

## Specification

### Event

```solidity
event AuthorizationUsed(
    address indexed authorizer,
    bytes32 indexed nonce
);

// keccak256(&quot;TransferWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)&quot;)
bytes32 public constant TRANSFER_WITH_AUTHORIZATION_TYPEHASH = 0x7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a2267;

// keccak256(&quot;ReceiveWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)&quot;)
bytes32 public constant RECEIVE_WITH_AUTHORIZATION_TYPEHASH = 0xd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de8;

/**
 * @notice Returns the state of an authorization
 * @dev Nonces are randomly generated 32-byte data unique to the authorizer&apos;s
 * address
 * @param authorizer    Authorizer&apos;s address
 * @param nonce         Nonce of the authorization
 * @return True if the nonce is used
 */
function authorizationState(
    address authorizer,
    bytes32 nonce
) external view returns (bool);

/**
 * @notice Execute a transfer with a signed authorization
 * @param from          Payer&apos;s address (Authorizer)
 * @param to            Payee&apos;s address
 * @param value         Amount to be transferred
 * @param validAfter    The time after which this is valid (unix time)
 * @param validBefore   The time before which this is valid (unix time)
 * @param nonce         Unique nonce
 * @param v             v of the signature
 * @param r             r of the signature
 * @param s             s of the signature
 */
function transferWithAuthorization(
    address from,
    address to,
    uint256 value,
    uint256 validAfter,
    uint256 validBefore,
    bytes32 nonce,
    uint8 v,
    bytes32 r,
    bytes32 s
) external;

/**
 * @notice Receive a transfer with a signed authorization from the payer
 * @dev This has an additional check to ensure that the payee&apos;s address matches
 * the caller of this function to prevent front-running attacks. (See security
 * considerations)
 * @param from          Payer&apos;s address (Authorizer)
 * @param to            Payee&apos;s address
 * @param value         Amount to be transferred
 * @param validAfter    The time after which this is valid (unix time)
 * @param validBefore   The time before which this is valid (unix time)
 * @param nonce         Unique nonce
 * @param v             v of the signature
 * @param r             r of the signature
 * @param s             s of the signature
 */
function receiveWithAuthorization(
    address from,
    address to,
    uint256 value,
    uint256 validAfter,
    uint256 validBefore,
    bytes32 nonce,
    uint8 v,
    bytes32 r,
    bytes32 s
) external;
```

**Optional:**

```
event AuthorizationCanceled(
    address indexed authorizer,
    bytes32 indexed nonce
);

// keccak256(&quot;CancelAuthorization(address authorizer,bytes32 nonce)&quot;)
bytes32 public constant CANCEL_AUTHORIZATION_TYPEHASH = 0x158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a1597429;

/**
 * @notice Attempt to cancel an authorization
 * @param authorizer    Authorizer&apos;s address
 * @param nonce         Nonce of the authorization
 * @param v             v of the signature
 * @param r             r of the signature
 * @param s             s of the signature
 */
function cancelAuthorization(
    address authorizer,
    bytes32 nonce,
    uint8 v,
    bytes32 r,
    bytes32 s
) external;
```


The arguments `v`, `r`, and `s` must be obtained using the [EIP-712](/EIPs/EIPS/eip-712) typed message signing spec.

**Example:**

```
DomainSeparator := Keccak256(ABIEncode(
  Keccak256(
    &quot;EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)&quot;
  ),
  Keccak256(&quot;USD Coin&quot;),                      // name
  Keccak256(&quot;2&quot;),                             // version
  1,                                          // chainId
  0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48  // verifyingContract
))
```

With the domain separator, the typehash, which is used to identify the type of the EIP-712 message being used, and the values of the parameters, you are able to derive a Keccak-256 hash digest which can then be signed using the token holder&apos;s private key.

**Example:**

```
// Transfer With Authorization
TypeHash := Keccak256(
  &quot;TransferWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)&quot;
)
Params := { From, To, Value, ValidAfter, ValidBefore, Nonce }

// ReceiveWithAuthorization
TypeHash := Keccak256(
  &quot;ReceiveWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)&quot;
)
Params := { From, To, Value, ValidAfter, ValidBefore, Nonce }

// CancelAuthorization
TypeHash := Keccak256(
  &quot;CancelAuthorization(address authorizer,bytes32 nonce)&quot;
)
Params := { Authorizer, Nonce }
```

```
// &quot;‖&quot; denotes concatenation.
Digest := Keccak256(
  0x1901 ‖ DomainSeparator ‖ Keccak256(ABIEncode(TypeHash, Params...))
)

{ v, r, s } := Sign(Digest, PrivateKey)
```

Smart contract functions that wrap `receiveWithAuthorization` call may choose to reduce the number of arguments by accepting the full ABI-encoded set of arguments for the `receiveWithAuthorization` call as a single argument of the type `bytes`.

**Example:**

```solidity
// keccak256(&quot;receiveWithAuthorization(address,address,uint256,uint256,uint256,bytes32,uint8,bytes32,bytes32)&quot;)[0:4]
bytes4 private constant _RECEIVE_WITH_AUTHORIZATION_SELECTOR = 0xef55bec6;

function deposit(address token, bytes calldata receiveAuthorization)
    external
    nonReentrant
{
    (address from, address to, uint256 amount) = abi.decode(
        receiveAuthorization[0:96],
        (address, address, uint256)
    );
    require(to == address(this), &quot;Recipient is not this contract&quot;);

    (bool success, ) = token.call(
        abi.encodePacked(
            _RECEIVE_WITH_AUTHORIZATION_SELECTOR,
            receiveAuthorization
        )
    );
    require(success, &quot;Failed to transfer tokens&quot;);

    ...
}
```

### Use with web3 providers

The signature for an authorization can be obtained using a web3 provider with the `eth_signTypedData{_v4}` method.

**Example:**

```javascript
const data = {
  types: {
    EIP712Domain: [
      { name: &quot;name&quot;, type: &quot;string&quot; },
      { name: &quot;version&quot;, type: &quot;string&quot; },
      { name: &quot;chainId&quot;, type: &quot;uint256&quot; },
      { name: &quot;verifyingContract&quot;, type: &quot;address&quot; },
    ],
    TransferWithAuthorization: [
      { name: &quot;from&quot;, type: &quot;address&quot; },
      { name: &quot;to&quot;, type: &quot;address&quot; },
      { name: &quot;value&quot;, type: &quot;uint256&quot; },
      { name: &quot;validAfter&quot;, type: &quot;uint256&quot; },
      { name: &quot;validBefore&quot;, type: &quot;uint256&quot; },
      { name: &quot;nonce&quot;, type: &quot;bytes32&quot; },
    ],
  },
  domain: {
    name: tokenName,
    version: tokenVersion,
    chainId: selectedChainId,
    verifyingContract: tokenAddress,
  },
  primaryType: &quot;TransferWithAuthorization&quot;,
  message: {
    from: userAddress,
    to: recipientAddress,
    value: amountBN.toString(10),
    validAfter: 0,
    validBefore: Math.floor(Date.now() / 1000) + 3600, // Valid for an hour
    nonce: Web3.utils.randomHex(32),
  },
};

const signature = await ethereum.request({
  method: &quot;eth_signTypedData_v4&quot;,
  params: [userAddress, JSON.stringify(data)],
});

const v = &quot;0x&quot; + signature.slice(130, 132);
const r = signature.slice(0, 66);
const s = &quot;0x&quot; + signature.slice(66, 130);
```

## Rationale

### Unique Random Nonce, Instead of Sequential Nonce

One might say transaction ordering is one reason why sequential nonces are preferred. However, sequential nonces do not actually help achieve transaction ordering for meta transactions in practice:

- For native Ethereum transactions, when a transaction with a nonce value that is too-high is submitted to the network, it will stay pending until the transactions consuming the lower unused nonces are confirmed.
- However, for meta-transactions, when a transaction containing a sequential nonce value that is too high is submitted, instead of staying pending, it will revert and fail immediately, resulting in wasted gas.
- The fact that miners can also reorder transactions and include them in the block in the order they want (assuming each transaction was submitted to the network by different meta-transaction relayers) also makes it possible for the meta-transactions to fail even if the nonces used were correct. (e.g. User submits nonces 3, 4 and 5, but miner ends up including them in the block as 4,5,3, resulting in only 3 succeeding)
- Lastly, when using different applications simultaneously, in the absence of some sort of an off-chain nonce tracker, it is not possible to determine what the correct next nonce value is if there exists nonces that are used but haven&apos;t been submitted and confirmed by the network.
- Under high gas price conditions, transactions can often &quot;get stuck&quot; in the pool for a long time. Under such a situation, it is much more likely for the same nonce to be unintentionally reused twice. For example, if you make a meta-transaction that uses a sequential nonce from one app, and switch to another app to make another meta-transaction before the previous one confirms, the same nonce will be used if the app relies purely on the data available on-chain, resulting in one of the transactions failing.
- In conclusion, the only way to guarantee transaction ordering is for relayers to submit transactions one at a time, waiting for confirmation between each submission (and the order in which they should be submitted can be part of some off-chain metadata), rendering sequential nonce irrelevant.

### Valid After and Valid Before

- Relying on relayers to submit transactions for you means you may not have exact control over the timing of transaction submission.
- These parameters allow the user to schedule a transaction to be only valid in the future or before a specific deadline, protecting the user from potential undesirable effects that may be caused by the submission being made either too late or too early.

### EIP-712

- EIP-712 ensures that the signatures generated are valid only for this specific instance of the token contract and cannot be replayed on a different network with a different chain ID.
- This is achieved by incorporating the contract address and the chain ID in a Keccak-256 hash digest called the domain separator. The actual set of parameters used to derive the domain separator is up to the implementing contract, but it is highly recommended that the fields `verifyingContract` and `chainId` are included.

## Backwards Compatibility

New contracts benefit from being able to directly utilize [ERC-3009](/EIPs/EIPS/eip-3009) in order to create atomic transactions, but existing contracts may still rely on the conventional ERC-20 allowance pattern (`approve`/`transferFrom`).

In order to add support for ERC-3009 to existing contracts (&quot;parent contract&quot;) that use the ERC-20 allowance pattern, a forwarding contract (&quot;forwarder&quot;) can be constructed that takes an authorization and does the following:

1. Extract the user and deposit amount from the authorization
2. Call `receiveWithAuthorization` to transfer specified funds from the user to the forwarder
3. Approve the parent contract to spend funds from the forwarder
4. Call the method on the parent contract that spends the allowance set from the forwarder
5. Transfer the ownership of any resulting tokens back to the user

**Example:**

```solidity
interface IDeFiToken {
    function deposit(uint256 amount) external returns (uint256);

    function transfer(address account, uint256 amount)
        external
        returns (bool);
}

contract DepositForwarder {
    bytes4 private constant _RECEIVE_WITH_AUTHORIZATION_SELECTOR = 0xef55bec6;

    IDeFiToken private _parent;
    IERC20 private _token;

    constructor(IDeFiToken parent, IERC20 token) public {
        _parent = parent;
        _token = token;
    }

    function deposit(bytes calldata receiveAuthorization)
        external
        nonReentrant
        returns (uint256)
    {
        (address from, address to, uint256 amount) = abi.decode(
            receiveAuthorization[0:96],
            (address, address, uint256)
        );
        require(to == address(this), &quot;Recipient is not this contract&quot;);

        (bool success, ) = address(_token).call(
            abi.encodePacked(
                _RECEIVE_WITH_AUTHORIZATION_SELECTOR,
                receiveAuthorization
            )
        );
        require(success, &quot;Failed to transfer to the forwarder&quot;);

        require(
            _token.approve(address(_parent), amount),
            &quot;Failed to set the allowance&quot;
        );

        uint256 tokensMinted = _parent.deposit(amount);
        require(
            _parent.transfer(from, tokensMinted),
            &quot;Failed to transfer the minted tokens&quot;
        );

        uint256 remainder = _token.balanceOf(address(this));
        if (remainder &gt; 0) {
            require(
                _token.transfer(from, remainder),
                &quot;Failed to refund the remainder&quot;
            );
        }

        return tokensMinted;
    }
}
```

&lt;!-- TODO (Editor&apos;s note): please move your test cases into your assets directory (assuming they&apos;re under a permissive license)
## Test Cases

See [EIP3009.test.ts](https://github.com/CoinbaseStablecoin/eip-3009/blob/master/test/EIP3009.test.ts).
--&gt;

## Reference Implementation

### `EIP3009.sol`

```solidity
abstract contract EIP3009 is IERC20Transfer, EIP712Domain {
    // keccak256(&quot;TransferWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)&quot;)
    bytes32 public constant TRANSFER_WITH_AUTHORIZATION_TYPEHASH = 0x7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a2267;

    // keccak256(&quot;ReceiveWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)&quot;)
    bytes32 public constant RECEIVE_WITH_AUTHORIZATION_TYPEHASH = 0xd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de8;

    mapping(address =&gt; mapping(bytes32 =&gt; bool)) internal _authorizationStates;

    event AuthorizationUsed(address indexed authorizer, bytes32 indexed nonce);

    string internal constant _INVALID_SIGNATURE_ERROR = &quot;EIP3009: invalid signature&quot;;

    function authorizationState(address authorizer, bytes32 nonce)
        external
        view
        returns (bool)
    {
        return _authorizationStates[authorizer][nonce];
    }

    function transferWithAuthorization(
        address from,
        address to,
        uint256 value,
        uint256 validAfter,
        uint256 validBefore,
        bytes32 nonce,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external {
        require(now &gt; validAfter, &quot;EIP3009: authorization is not yet valid&quot;);
        require(now &lt; validBefore, &quot;EIP3009: authorization is expired&quot;);
        require(
            !_authorizationStates[from][nonce],
            &quot;EIP3009: authorization is used&quot;
        );

        bytes memory data = abi.encode(
            TRANSFER_WITH_AUTHORIZATION_TYPEHASH,
            from,
            to,
            value,
            validAfter,
            validBefore,
            nonce
        );
        require(
            EIP712.recover(DOMAIN_SEPARATOR, v, r, s, data) == from,
            &quot;EIP3009: invalid signature&quot;
        );

        _authorizationStates[from][nonce] = true;
        emit AuthorizationUsed(from, nonce);

        _transfer(from, to, value);
    }
}
```

### `IERC20Transfer.sol`

```solidity
abstract contract IERC20Transfer {
    function _transfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal virtual;
}
```

### `EIP712Domain.sol`

```solidity
abstract contract EIP712Domain {
    bytes32 public DOMAIN_SEPARATOR;
}
```

### `EIP712.sol`

```solidity
library EIP712 {
    // keccak256(&quot;EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)&quot;)
    bytes32 public constant EIP712_DOMAIN_TYPEHASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;

    function makeDomainSeparator(string memory name, string memory version)
        internal
        view
        returns (bytes32)
    {
        uint256 chainId;
        assembly {
            chainId := chainid()
        }

        return
            keccak256(
                abi.encode(
                    EIP712_DOMAIN_TYPEHASH,
                    keccak256(bytes(name)),
                    keccak256(bytes(version)),
                    chainId,
                    address(this)
                )
            );
    }

    function recover(
        bytes32 domainSeparator,
        uint8 v,
        bytes32 r,
        bytes32 s,
        bytes memory typeHashAndData
    ) internal pure returns (address) {
        bytes32 digest = keccak256(
            abi.encodePacked(
                &quot;\x19\x01&quot;,
                domainSeparator,
                keccak256(typeHashAndData)
            )
        );
        address recovered = ecrecover(digest, v, r, s);
        require(recovered != address(0), &quot;EIP712: invalid signature&quot;);
        return recovered;
    }
}
```

A fully working implementation of ERC-3009 can be found in [this repository](/EIPs/assets/eip-3009/ERC3009.sol). The repository also includes [an implementation of ERC-2612](/EIPs/assets/eip-3009/ERC2612.sol) that uses the EIP-712 library code presented above.

## Security Considerations

Use `receiveWithAuthorization` instead of `transferWithAuthorization` when calling from other smart contracts. It is possible for an attacker watching the transaction pool to extract the transfer authorization and front-run the `transferWithAuthorization` call to execute the transfer without invoking the wrapper function. This could potentially result in unprocessed, locked up deposits. `receiveWithAuthorization` prevents this by performing an additional check that ensures that the caller is the payee. Additionally, if there are multiple contract functions accepting receive authorizations, the app developer could dedicate some leading bytes of the nonce as an identifier to prevent cross-use.

When submitting multiple transfers simultaneously, be mindful of the fact that relayers and miners will decide the order in which they are processed. This is generally not a problem if the transactions are not dependent on each other, but for transactions that are highly dependent on each other, it is recommended that the signed authorizations are submitted one at a time.

The zero address must be rejected when `ecrecover` is used to prevent unauthorized transfers and approvals of funds from the zero address. The built-in `ecrecover` returns the zero address when a malformed signature is provided.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 28 Sep 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3009</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3009</guid>
      </item>
    
      <item>
        <title>eth_symbol JSON-RPC method</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/3012</comments>
        
        <description>## Simple Summary
Add `eth_symbol` method to the JSON-RPC that returns the symbol of the native coin of the network.

## Abstract
The new method `eth_symbol` (`eth_`-namespaced) has no parameters and returns a string of the native coin of the network. For the Ethereum mainnet this will be `ETH`, other networks will have other symbols.

## Motivation
Wallets that deal with multiple networks need some basic information for every blockchain that they connect to. One of those things is the symbol of the native coin of the network. Instead of requiring the user to research and manually add the symbol it could be provided to the wallet via this proposed JSON-RPC endpoint and used automatically. There are lists of networks with symbols like https://github.com/ethereum-lists/chains where a user can manually look up the correct values. But this information could easily come from the network itself.

## Specification
Method: `eth_symbol`.

Params: none.

Returns: `result` - the native coin symbol, string

Example:

```js
curl -X POST --data &apos;{&quot;jsonrpc&quot;:&quot;2.0&quot;,&quot;method&quot;:&quot;eth_symbol&quot;,&quot;params&quot;:[],&quot;id&quot;:1}&apos;

// Result
{
  &quot;id&quot;: 1,
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;result&quot;: &quot;ETH&quot;
}
```

## Rationale
This endpoint is similar to [EIP-695](/EIPs/EIPS/eip-695) but it provides the symbol instead of `chainId`. It provides functionality that is already there for [ERC-20](/EIPs/EIPS/eip-20) tokens, but not yet for the native coin of the network. Alternative naming of `eth_nativeCurrencySymbol` was considered, but the context and the fact that it just returns one value makes it clear that that it returns the symbol for the native coin of the network.

## Security Considerations
It is a read only endpoint. The information is only as trusted as the JSON-RPC node itself, it could supply wrong information and thereby trick the user in believing he/she is dealing with another native coin.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3014</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3014</guid>
      </item>
    
      <item>
        <title>BW6-761 curve operations</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3026-bw6-761-curve-operations/4790</comments>
        
        <description>## Abstract

This precompile adds operations for the BW6-761 curve (from the EY/Inria **Optimized and secure pairing-friendly elliptic curves suitable for one layer proof composition** research paper) as a precompile in a set necessary to *efficiently* perform verification of one-layer composed zkSNARKs proofs.
If `block.number &gt;= X` we introduce *seven* separate precompiles to perform the following operations (addresses to be determined):

- BW6_G1_ADD - to perform point addition on a curve defined over a prime field
- BW6_G1_MUL - to perform point multiplication on a curve defined over a prime field
- BW6_G1_MULTIEXP - to perform multiexponentiation on a curve defined over a prime field
- BW6_G2_ADD - to perform point addition on a curve twist defined the base a prime field
- BW6_G2_MUL - to perform point multiplication on a curve twist defined over a prime field
- BW6_G2_MULTIEXP - to perform multiexponentiation on a curve twist defined over a prime field
- BW6_PAIRING - to perform a pairing operations between a set of *pairs* of (G1, G2) points

The multiexponentiation operations are a generalization of point multiplication, but separate precompiles are prosposed because running a single MUL through MULTIEXP seems to be 20% more expensive.

## Motivation

This EIP is based on and tends to replace matter-labs&apos; proposal for significant performance reasons. In most applications, BW6-761 is used as an outer curve to BLS12-377 considered in [EIP-2539](/EIPs/EIPS/eip-2539).
The motivation of this precompile is to allow efficient one-layer composition of SNARK proofs. Currently this is done by Zexe using the BLS12-377/CP6-782 pair of curves. This precompile proposes a replacement of CP6-782 by BW6-761, which allows much faster operations. For example, it was shown that verifying a Groth16 proof with BW6-761 is 30 times faster than with CP6-782.

### Proposed addresses table

| Precompile      | Address |
| --------------- | ------- |
| BW6_G1_ADD      | 0x1e    |
| BW6_G1_MUL      | 0x1f    |
| BW6_G1_MULTIEXP | 0x20    |
| BW6_G2_ADD      | 0x21    |
| BW6_G2_MUL      | 0x22    |
| BW6_G2_MULTIEXP | 0x23    |
| BW6_PAIRING     | 0x24    |

## Specification

Curve parameters:

The BW6-761 `y^2=x^3-1` curve is fully defined by the following set of parameters:

```
Base field modulus = 0x122e824fb83ce0ad187c94004faff3eb926186a81d14688528275ef8087be41707ba638e584e91903cebaff25b423048689c8ed12f9fd9071dcd3dc73ebff2e98a116c25667a8f8160cf8aeeaf0a437e6913e6870000082f49d00000000008b
A coefficient = 0x0
B coefficient = 0x122e824fb83ce0ad187c94004faff3eb926186a81d14688528275ef8087be41707ba638e584e91903cebaff25b423048689c8ed12f9fd9071dcd3dc73ebff2e98a116c25667a8f8160cf8aeeaf0a437e6913e6870000082f49d00000000008a
Main subgroup order = 0x1ae3a4617c510eac63b05c06ca1493b1a22d9f300f5138f1ef3622fba094800170b5d44300000008508c00000000001
Extension tower:
Fp3 construction: (Fp3 = Fp[u]/u^3+4)
Fp cubic non-residue = 0x122e824fb83ce0ad187c94004faff3eb926186a81d14688528275ef8087be41707ba638e584e91903cebaff25b423048689c8ed12f9fd9071dcd3dc73ebff2e98a116c25667a8f8160cf8aeeaf0a437e6913e6870000082f49d000000000087
Twist parameters:
Twist type: M
twist curve A coefficient c0 = 0x0
                          c1 = 0x0
twist curve B coefficient c0 = 0x4
                        c1 = 0x0
Generators:
G1:
X = 0x1075b020ea190c8b277ce98a477beaee6a0cfb7551b27f0ee05c54b85f56fc779017ffac15520ac11dbfcd294c2e746a17a54ce47729b905bd71fa0c9ea097103758f9a280ca27f6750dd0356133e82055928aca6af603f4088f3af66e5b43d
Y = 0x58b84e0a6fc574e6fd637b45cc2a420f952589884c9ec61a7348d2a2e573a3265909f1af7e0dbac5b8fa1771b5b806cc685d31717a4c55be3fb90b6fc2cdd49f9df141b3053253b2b08119cad0fb93ad1cb2be0b20d2a1bafc8f2db4e95363
G2:
X = 0x110133241d9b816c852a82e69d660f9d61053aac5a7115f4c06201013890f6d26b41c5dab3da268734ec3f1f09feb58c5bbcae9ac70e7c7963317a300e1b6bace6948cb3cd208d700e96efbc2ad54b06410cf4fe1bf995ba830c194cd025f1c
Y = 0x17c3357761369f8179eb10e4b6d2dc26b7cf9acec2181c81a78e2753ffe3160a1d86c80b95a59c94c97eb733293fef64f293dbd2c712b88906c170ffa823003ea96fcd504affc758aa2d3a3c5a02a591ec0594f9eac689eb70a16728c73b61
Pairing parameters:
e(P,Q)=(ML1(P,Q)*ML2(P,Q)^q)^FE
|loop_count_1| (first miller loop ML1 count) = 0x8508c00000000002
|loop_count_2| (second miller loop ML2 count) = 0x23ed1347970dec008a442f991fffffffffffffffffffffff
loop_count_1 is negative = false
loop_count_2 is negative = false
```

### Encoding

#### Field elements encoding:

To encode points involved in the operation one has to encode elements of only the base field.

The base field element (Fp) is encoded as `96` bytes by performing BigEndian encoding of the corresponding (unsigned) integer. The corresponding integer **MUST** be less than the base field modulus.

If encodings do not follow this spec anywhere during parsing in the precompile, the precompile **MUST** revert with &quot;endoding error&quot;.

#### Encoding of uncompressed points:

Points in both G1 and G2 can be expressed as `(x, y)` affine coordinates, where `x` and `y` are elements of the base field.
Therefore, points in both G1 and G2 are encoded as the byte concatenation of the field element encodings of the `x` and `y` affine coordinates. The total encoding length for a G1/G2 point is thus `192` bytes.

#### Point at infinity encoding:

Also referred as the &quot;zero point&quot;. For BW6-761 (`y^2=x^3-1`) and its M-twisted curves (`y^3=x^3+4`), the point with coordinates `(0, 0)` (formal zeros in Fp) is *not* on the curve, and so the encoding of `(0, 0)` is used as a convention to encode the point at infinity.

#### Encoding of scalars for multiplication and multiexponentiation operations:

For multiplication and multiexponentiation operations, a scalar is encoded as `64` bytes by performing BigEndian encoding of the corresponding (unsigned) integer.

Note that the main subgroup order for BW6-761 is actually only `377` bits (`48` bytes), but an encoding of `64` bytes has been chosen to have a `32`-byte-aligned ABI (representable as e.g. `bytes32[2]` or `uint256[2]`).

The corresponding integer **MAY** be greater than the main subgroup order.

### ABI for operations

#### ABI for G1 addition

G1 addition call expects `384` bytes as an input that is interpreted as the byte concatenation of two G1 points (point-encoded as `192` bytes each). Output is a point-encoding of the addition operation result.

Error cases:

- Either of the points being not on the curve
- Input has invalid length
- Field element encoding rules apply (obviously)

#### ABI for G1 multiplication

G1 multiplication call expects `256` bytes as an input that is interpreted as the byte concatenation of the point-encoding of a G1 point (`192` bytes) and the encoding of a scalar value (`64` bytes). Output is a point-encoding of the multiplication operation result.

Error cases:

- Point being not on the curve
- Input has invalid length
- Field element encoding rules apply (obviously)
- Scalar encoding rules apply (obviously)

#### ABI for G1 multiexponentiation

G1 multiplication call expects `256*k` bytes as an input that is interpreted as the byte concatenation of `k` slices, each of them being a byte concatenation of the point-encoding of a G1 point (`192` bytes) and the encoding of a scalar value (`64` bytes). Output is an encoding of the multiexponentiation operation result.

Error cases:

- Any of the G1 points being not on the curve
- Input has invalid length
- Field element encoding rules apply (obviously)
- Scalar encoding rules apply (obviously)

#### ABI for G2 addition

G2 addition call expects `384` bytes as an input that is interpreted as the byte concatenation of two G2 points (point-encoded as `192` bytes each). Output is a point-encoding of the addition operation result.

Error cases:

- Either of points being not on the curve
- Input has invalid length
- Field elements encoding rules apply (obviously)

#### ABI for G2 multiplication

G2 multiplication call expects `256` bytes as an input that is interpreted as the byte concatenation of the point-encoding of a G2 point (`192` bytes) and the encoding of a scalar value (`64` bytes). Output is an encoding of multiplication operation result.

Error cases:

- Point being not on the curve must result in error
- Field elements encoding rules apply (obviously)
- Input has invalid length

#### ABI for G2 multiexponentiation

G2 multiplication call expects `240*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G2 point (`192` bytes) and encoding of a scalar value (`48` bytes). Output is an encoding of multiexponentiation operation result.

Error cases:

- Any of G2 points being not on the curve must result in error
- Field elements encoding rules apply (obviously)
- Input has invalid length

#### ABI for pairing

Pairing call expects `384*k` bytes as an input, that is interpreted as the byte concatenation of `k` slices. Each slice has the following structure:

- `192` bytes G1 point encoding
- `192` bytes G2 point encoding

Output is `32` bytes representing a boolean:

- `0x0000000000000000000000000000000000000000000000000000000000000001` if the pairing result is equal the to multiplicative identity in the pairing target field; and
- `0x0000000000000000000000000000000000000000000000000000000000000000` otherwise.

Error cases:

- Any of the G1 or G2 points being not on the curve
- Any of the G1 or G2 points being not in the correct subgroup
- Input has invalid length
- Field elements encoding rules apply (obviously)

### Prevention of DDoS on error handling

This precompile performs extensive computations and in case of any errors during execution it **MUST** consume all gas from the gas schedule for the corresponding operation.

### Gas schedule

#### G1 addition

`180` gas

#### G1 multiplication

`64000` gas

#### G2 addition

`180` gas

#### G2 multiplication

`64000` gas

#### G1/G2 Multiexponentiation

Discounts table as a vector of pairs `[k, discount]`:

```
[[1, 1266], [2, 733], [3, 561], [4, 474], [5, 422], [6, 387], [7, 362], [8, 344], [9, 329], [10, 318], [11, 308], [12, 300], [13, 296], [14, 289], [15, 283], [16, 279], [17, 275], [18, 272], [19, 269], [20, 266], [21, 265], [22, 260], [23, 259], [24, 256], [25, 255], [26, 254], [27, 252], [28, 251], [29, 250], [30, 249], [31, 249], [32, 220], [33, 228], [34, 225], [35, 223], [36, 219], [37, 216], [38, 214], [39, 212], [40, 209], [41, 209], [42, 205], [43, 203], [44, 202], [45, 200], [46, 198], [47, 196], [48, 199], [49, 195], [50, 192], [51, 192], [52, 191], [53, 190], [54, 187], [55, 186], [56, 185], [57, 184], [58, 184], [59, 181], [60, 181], [61, 181], [62, 180], [63, 178], [64, 179], [65, 176], [66, 177], [67, 176], [68, 175], [69, 174], [70, 173], [71, 171], [72, 171], [73, 170], [74, 170], [75, 169], [76, 168], [77, 168], [78, 167], [79, 167], [80, 166], [81, 165], [82, 167], [83, 166], [84, 166], [85, 165], [86, 165], [87, 164], [88, 164], [89, 163], [90, 163], [91, 162], [92, 162], [93, 160], [94, 163], [95, 159], [96, 162], [97, 159], [98, 160], [99, 159], [100, 159], [101, 158], [102, 158], [103, 158], [104, 158], [105, 157], [106, 157], [107, 156], [108, 155], [109, 155], [110, 156], [111, 155], [112, 155], [113, 154], [114, 155], [115, 154], [116, 153], [117, 153], [118, 153], [119, 152], [120, 152], [121, 152], [122, 152], [123, 151], [124, 151], [125, 151], [126, 151], [127, 151], [128, 150]]
```

`max_discount = 150`

#### Pairing operation

Base cost of the pairing operation is `120000*k + 320000` where `k` is a number of pairs.

## Rationale

Gas costs are based on [EIP-1962](/EIPs/EIPS/eip-1962) estimation strategy (but do not fully include yet parsing of ABI, decoding and encoding of the result as a byte array).

### Gas estimation strategy

Gas cost is derived by taking the average timing of the same operations over different implementations and assuming a constant `30 MGas/second`. Since the execution time is machine-specific, this constant is determined based on execution times of *ECRECOVER* and *BNPAIR* precompiles on my machine and their proposed gas price (`43.5 MGas/s` for ECRECOVER and `16.5 MGas/s` for BNPAIR). Following are the proposed methods to time the precompile operations:

- G1 addition: Average timing of 1000 random samples.
- G1 multiplication: Average timing of 1000 samples of random worst-case of double-and-add algorithm (scalar of max bit length and max hamming weight and random base points in G1)
- G2 addition: Average timing of 1000 random samples
- G2 multiplication: Average timing of 1000 samples of random worst-case of double-and-add algorithm (scalar of max bit length and max hamming weight and random base points in G2)
- G1 and G2 multiexponentiations: Expected to be performed by the Peppinger algorithm, with a table prepared for discount in case of `k &lt;= 128` points in the multiexponentiation with a discount cup `max_discount` for `k &gt; 128`. To avoid non-integer arithmetic call cost is calculated as `k * multiplication_cost * discount / multiplier` where `multiplier = 1000`, `k` is a number of (scalar, point) pairs for the call, `multiplication_cost` is a corresponding single multiplication call cost for G1/G2.
- Pairing: Average timing of 1000 random samples (random points in G1 and G2) for different number of pairs with linear lifting.

### Multiexponentiation as a separate call

Explicit separate multiexponentiation operation that allows one to save execution time (so gas) by both the algorithm used (namely Peppinger algorithm) and (usually forgotten) by the fact that `CALL` operation in Ethereum is expensive (at the time of writing), so one would have to pay non-negigible overhead if e.g. for multiexponentiation of `100` points would have to call the multiplication precompile `100` times and addition for `99` times (roughly `138600` would be saved).

### Explicit subgroup checks

G2 subgroup check has the same cost as G1 subgroup check. Endomorphisms can be leverages to optimize this operation.

## Backwards Compatibility

There are no backward compatibility questions.

## Test Cases

Due to the large test parameters space we first provide properties that various operations must satisfy. We use additive notation for point operations, capital letters (`P`, `Q`) for points, small letters (`a`, `b`) for scalars. Generator for G1 is labeled as `G`, generator for G2 is labeled as `H`, otherwise we assume random point on a curve in a correct subgroup. `0` means either scalar zero or point of infinity. `1` means either scalar one or multiplicative identity. `group_order` is a main subgroup order. `e(P, Q)` means pairing operation where `P` is in G1, `Q` is in G2.

Requeired properties for basic ops (add/multiply):

- Commutativity: `P + Q = Q + P`
- Additive negation: `P + (-P) = 0`
- Doubling `P + P = 2*P`
- Subgroup check: `group_order * P = 0`
- Trivial multiplication check: `1 * P = P`
- Multiplication by zero: `0 * P = 0`
- Multiplication by the unnormalized scalar `(scalar + group_order) * P = scalar * P`

Required properties for pairing operation:

- Degeneracy `e(P, 0*Q) = e(0*P, Q) = 1`
- Bilinearity `e(a*P, b*Q) = e(a*b*P, Q) = e(P, a*b*Q)` (internal test, not visible through ABI)

## Reference Implementation

There is a various choice of existing implementations:

**Libraries:**

- Rust implementation (EY/Zexe): github.com/yelhousni/zexe/tree/youssef/BW6-761-Fq-ABLR-2ML-M
- C++ implementation (EY/libff): github.com/EYBlockchain/zk-swap-libff
- Golang implementation (Consensys/gurvy): github.com/ConsenSys/gurvy

**Stand-alone implementation:**

- Golang implementation with Intel assembly (Onur Kilic): github.com/kilic/bw6

**Precompiles:**

- OpenEthereum (EY/Parity): github.com/EYBlockchain/solidity-elliptic-curves
- Frontier (Parity): github.com/paritytech/frontier/pull/1049/files

**Scripts:**

- SageMath and Magma scripts: gitlab.inria.fr/zk-curves/bw6-761/

## Security Considerations

Strictly following the spec will eliminate security implications or consensus implications in a contrast to the previous BN254 precompile.

Important topic is a &quot;constant time&quot; property for performed operations. We explicitly state that this precompile **IS NOT REQUIRED** to perform all the operations using constant time algorithms.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 05 Oct 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3026</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3026</guid>
      </item>
    
      <item>
        <title>BLS Remote Signer HTTP API</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3030-bls-remote-signer-http-api-standard/4810</comments>
        
        <description>## Simple Summary
This EIP defines a HTTP API standard for a BLS remote signer, consumed by validator clients to sign block proposals and attestations in the context of Ethereum 2.0 (eth2).

## Abstract
A [validator](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/phase0/validator.md) client contributes to the consensus of the Eth2 blockchain by signing proposals and attestations of blocks, using a BLS private key which must be available to this client at all times.

The BLS remote signer API is designed to be consumed by validator clients, looking for a more secure avenue to store their BLS12-381 private key(s), enabling them to run in more permissive and scalable environments.

## Motivation
Eth2 utilizes [BLS12-381](https://github.com/cfrg/draft-irtf-cfrg-bls-signature/) signatures.

Consensus on the eth2 Blockchain is achieved via the proposal and attestation of blocks from validator clients, using a BLS private key (_signing_ key) which must be available each time a message is signed: that is, at least once every epoch (6.4 minutes), during a small window of time within this epoch (a _slot_, i.e. 12 seconds), as each validator is expected to attest exactly once per epoch.

The [eth2 specification](https://github.com/ethereum/eth2.0-specs) does not explicitly provide a directive on where this BLS private key must/should be stored, leaving this implementation detail to the client teams, who assume that this cryptographic secret is stored on the same host as the validator client.

This assumption is sufficient in the use case where the validator client is running in a physically secure network (i.e. nobody, but the operator, has a chance to log-in into the machine hosting the validator client), as such configuration would only allow _outbound_ calls from the validator client. In this situation, only a physical security breach, or a Remote Code Execution (RCE) vulnerability can allow an attacker to either have arbitrary access to the storage or to the memory of the device.

There are, however, use cases where it is required by the operator to run a validator client node in less constrained security environments, as the ones given by a cloud provider. Notwithstanding any security expectation, nothing prevents a rogue operator from gaining arbitrary access to the assets running inside a node.

The situation is not better when the requirement is to execute the validators by leveraging a container orchestration solution (e.g. Kubernetes). The handling of secret keys across nodes can become a burden both from an operational as well as a security perspective.

The proposed solution comprises running a specialized node with exclusive access to the secret keys, listening to a simple API (defined in the [Specification](#specification) section), and returning the requested signatures. Operators working under this schema must utilize clients with the adequate feature supporting the consumption of this API.

The focus of this specification is the supply of BLS signatures _on demand_. The aspects of authentication, key management (creation, update, and deletion), and transport encryption are discussed in the [Rationale](#rationale) section of this document. Moreover, the [Threat Model](#threat-model) section of this document provides a (non-exhaustive) list of threats and attack vectors, along with the suggested related mitigation strategy.

## Specification

### `GET /upcheck`

_**Responses**_

Success | &lt;br&gt;
--- | ---
Code | `200`
Content | `{&quot;status&quot;: &quot;OK&quot;}`

---

### `GET /keys`

Returns the identifiers of the keys available to the signer.

_**Responses**_

Success | &lt;br&gt;
--- | ---
Code | `200`
Content | `{&quot;keys&quot;: &quot;[identifier]&quot;}`

---

### `POST /sign/:identifier`

URL Parameter | &lt;br&gt;
--- | ---
`:identifier` | `public_key_hex_string_without_0x`

_**Request**_

JSON Body | &lt;br&gt; | &lt;br&gt;
--- | --- | ---
`bls_domain` | **Required** | The BLS Signature domain.&lt;br&gt;As defined in the [specification](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/phase0/beacon-chain.md#domain-types), in lowercase, omitting the `domain` prefix.&lt;br&gt;Supporting `beacon_proposer`, `beacon_attester`, and `randao`.
`data` | **Required** | The data to be signed.&lt;br&gt;As defined in the specifications for [block](https://github.com/ethereum/eth2.0-APIs/blob/master/types/block.yaml), [attestation](https://github.com/ethereum/eth2.0-APIs/blob/master/types/attestation.yaml), and [epoch](https://github.com/ethereum/eth2.0-APIs/blob/master/types/misc.yaml).
`fork` | **Required** | A `Fork` object containing previous and current versions.&lt;br&gt;As defined in the [specification](https://github.com/ethereum/eth2.0-APIs/blob/master/types/misc.yaml)
`genesis_validators_root` | **Required** | A `Hash256` for domain separation and chain versioning.
&lt;br&gt; | Optional | Any other field will be ignored by the signer

_**Responses**_

Success | &lt;br&gt;
--- | ---
Code |  `200`
Content | `{&quot;signature&quot;: &quot;&lt;signature_hex_string&gt;&quot;}`

Where signature is a [BLS signature](https://github.com/ethereum/eth2.0-specs/blob/dev/specs/phase0/beacon-chain.md#bls-signatures) byte array encoded as a hexadecimal string.

_or_

Error | &lt;br&gt;
--- | ---
Code |  `400`
Content | `{&quot;error&quot;: &quot;&lt;Bad Request Error Message&gt;&quot;}`

_or_

Error | &lt;br&gt;
--- | ---
Code |  `404`
Content | `{&quot;error&quot;: &quot;Key not found: &lt;identifier&gt;&quot;}`

---

## Rationale

### UNIX philosophy: Simple API

This API specification contains only three methods: one for **status**, one for **listing the available keys**, and one to **produce a signature**. There are no methods for authentication, key management, nor transport encryption.

The following subsections discuss aspects to be considered by the client implementers relative to these subjects.

#### Implementation of additional features

From an API pipeline view, we have two nodes: The validator client (1) that makes requests to the remote signer (2). A more sophisticated chain can be built by introducing elements between these two nodes. Either by setting up reverse proxy services, or by adding plugins to the remote signer implementation.

#### Authentication

Can be accomplished through the use of an HTTP Request Header. There are several ways to negotiate and issue a valid token to authenticate the communication between the validator client and the remote signer, each of them with potential drawbacks (e.g replay attacks, challenges in distributing the token to the validator client, etc.). In general, any method of authentication must be combined with transport encryption to be effective.

The operator can also implement network Access Control Lists (ACLs) between the validator client&apos;s network and the remote signer&apos;s network, reducing the attack surface by requiring a potential attacker to be positioned in the same network as the validator client.

#### Key management

There are several ways to store secret keys, namely Hardware Security Modules (HSM), Secrets management applications (e.g. Hashicorp Vault), cloud storage with tight private network ACL rules, or even raw files in a directory. In general the remote signer implementers will abstract the storage medium from the HTTP API.

It is in this perspective, that any procedure to create, update, or delete keys should be built separate from the client implementation.

#### Transport Encryption

If the operator is working with self-signed certificates, it is required that the client enhancement consuming the remote signer allows this option.

## Test Cases

### Test Data

* BLS Pair
  * Public key: `0xb7354252aa5bce27ab9537fd0158515935f3c3861419e1b4b6c8219b5dbd15fcf907bddf275442f3e32f904f79807a2a`.
  * Secret key: `0x68081afeb7ad3e8d469f87010804c3e8d53ef77d393059a55132637206cc59ec`.
* Signing root: `0xb6bb8f3765f93f4f1e7c7348479289c9261399a3c6906685e320071a1a13955c`.
* Expected signature: `0xb5d0c01cef3b028e2c5f357c2d4b886f8e374d09dd660cd7dd14680d4f956778808b4d3b2ab743e890fc1a77ae62c3c90d613561b23c6adaeb5b0e288832304fddc08c7415080be73e556e8862a1b4d0f6aa8084e34a901544d5bb6aeed3a612`.

### `GET /upcheck`

```bash
# Success

## Request
curl -v localhost:9000/upcheck

## Response
*   Trying 127.0.0.1:9000...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 9000 (#0)
&gt; GET /upcheck HTTP/1.1
&gt; Host: localhost:9000
&gt; User-Agent: curl/7.68.0
&gt; Accept: */*
&gt;
* Mark bundle as not supporting multiuse
&lt; HTTP/1.1 200 OK
&lt; content-type: application/json
&lt; content-length: 15
&lt; date: Wed, 30 Sep 2020 02:25:08 GMT
&lt;
* Connection #0 to host localhost left intact
{&quot;status&quot;:&quot;OK&quot;}
```

### `GET /keys`

```bash
# Success

## Request
curl -v localhost:9000/keys

## Response
*   Trying 127.0.0.1:9000...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 9000 (#0)
&gt; GET /publicKeys HTTP/1.1
&gt; Host: localhost:9000
&gt; User-Agent: curl/7.68.0
&gt; Accept: */*
&gt;
* Mark bundle as not supporting multiuse
&lt; HTTP/1.1 200 OK
&lt; content-type: application/json
&lt; content-length: 116
&lt; date: Wed, 30 Sep 2020 02:25:36 GMT
&lt;
* Connection #0 to host localhost left intact
{&quot;keys&quot;:[&quot;b7354252aa5bce27ab9537fd0158515935f3c3861419e1b4b6c8219b5dbd15fcf907bddf275442f3e32f904f79807a2a&quot;]}

# Server Error

## Preparation
## `chmod` keys directory to the octal 311 (-wx--x--x).

## Request
curl -v localhost:9000/keys

## Response
*   Trying 127.0.0.1:9000...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 9000 (#0)
&gt; GET /publicKeys HTTP/1.1
&gt; Host: localhost:9000
&gt; User-Agent: curl/7.68.0
&gt; Accept: */*
&gt;
* Mark bundle as not supporting multiuse
&lt; HTTP/1.1 500 Internal Server Error
&lt; content-length: 43
&lt; date: Wed, 30 Sep 2020 02:26:09 GMT
&lt;
* Connection #0 to host localhost left intact
{&quot;error&quot;:&quot;Storage error: PermissionDenied&quot;}
```

### `POST /sign/:identifier`

```bash
# Success

## Request
curl -v -X POST -d @payload.json -H &apos;Content-Type: application/json&apos; localhost:9000/sign/b7354252aa5bce27ab9537fd0158515935f3c3861419e1b4b6c8219b5dbd15fcf907bddf275442f3e32f904f79807a2a

## Response
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying 127.0.0.1:9000...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 9000 (#0)
&gt; POST /sign/b7354252aa5bce27ab9537fd0158515935f3c3861419e1b4b6c8219b5dbd15fcf907bddf275442f3e32f904f79807a2a HTTP/1.1
&gt; Host: localhost:9000
&gt; User-Agent: curl/7.68.0
&gt; Accept: */*
&gt; Content-Type: application/json
&gt; Content-Length: 84
&gt;
* upload completely sent off: 84 out of 84 bytes
* Mark bundle as not supporting multiuse
&lt; HTTP/1.1 200 OK
&lt; content-type: application/json
&lt; content-length: 210
&lt; date: Wed, 30 Sep 2020 02:16:02 GMT
&lt;
* Connection #0 to host localhost left intact
{&quot;signature&quot;:&quot;0xb5d0c01cef3b028e2c5f357c2d4b886f8e374d09dd660cd7dd14680d4f956778808b4d3b2ab743e890fc1a77ae62c3c90d613561b23c6adaeb5b0e288832304fddc08c7415080be73e556e8862a1b4d0f6aa8084e34a901544d5bb6aeed3a612&quot;}

# Bad Request Error

## Request
curl -v -X POST -d &apos;foobar&apos; -H &apos;Content-Type: application/json&apos; localhost:9000/sign/b7354252aa5bce27ab9537fd0158515935f3c3861419e1b4b6c8219b5dbd15fcf907bddf275442f3e32f904f79807a2a

## Response
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying 127.0.0.1:9000...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 9000 (#0)
&gt; POST /sign/b7354252aa5bce27ab9537fd0158515935f3c3861419e1b4b6c8219b5dbd15fcf907bddf275442f3e32f904f79807a2a HTTP/1.1
&gt; Host: localhost:9000
&gt; User-Agent: curl/7.68.0
&gt; Accept: */*
&gt; Content-Type: application/json
&gt; Content-Length: 23
&gt;
* upload completely sent off: 23 out of 23 bytes
* Mark bundle as not supporting multiuse
&lt; HTTP/1.1 400 Bad Request
&lt; content-length: 38
&lt; date: Wed, 30 Sep 2020 02:15:05 GMT
&lt;
* Connection #0 to host localhost left intact
{&quot;error&quot;:&quot;Unable to parse body message from JSON: Error(\&quot;expected ident\&quot;, line: 1, column: 2)&quot;}

# No Keys Available

## Request
curl -v -X POST -d @payload.json -H &apos;Content-Type: application/json&apos; localhost:9000/sign/000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

## Response
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying 127.0.0.1:9000...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 9000 (#0)
&gt; POST /sign/000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 HTTP/1.1
&gt; Host: localhost:9000
&gt; User-Agent: curl/7.68.0
&gt; Accept: */*
&gt; Content-Type: application/json
&gt; Content-Length: 84
&gt;
* upload completely sent off: 84 out of 84 bytes
* Mark bundle as not supporting multiuse
&lt; HTTP/1.1 404 Not Found
&lt; content-length: 123
&lt; date: Wed, 30 Sep 2020 02:18:53 GMT
&lt;
* Connection #0 to host localhost left intact
{&quot;error&quot;:&quot;Key not found: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000&quot;}

# Server Error

## Preparation
## `chmod` both keys directory and file to the octal 311 (-wx--x--x).
## `chmod` back to 755 to delete them afterwards.

## Request
curl -v -X POST -d @payload.json -H &apos;Content-Type: application/json&apos; localhost:9000/sign/b7354252aa5bce27ab9537fd0158515935f3c3861419e1b4b6c8219b5dbd15fcf907bddf275442f3e32f904f79807a2a

## Response
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying 127.0.0.1:9000...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 9000 (#0)
&gt; POST /sign/b7354252aa5bce27ab9537fd0158515935f3c3861419e1b4b6c8219b5dbd15fcf907bddf275442f3e32f904f79807a2a HTTP/1.1
&gt; Host: localhost:9000
&gt; User-Agent: curl/7.68.0
&gt; Accept: */*
&gt; Content-Type: application/json
&gt; Content-Length: 84
&gt;
* upload completely sent off: 84 out of 84 bytes
* Mark bundle as not supporting multiuse
&lt; HTTP/1.1 500 Internal Server Error
&lt; content-length: 43
&lt; date: Wed, 30 Sep 2020 02:21:08 GMT
&lt;
* Connection #0 to host localhost left intact
{&quot;error&quot;:&quot;Storage error: PermissionDenied&quot;}
```

## Implementation

Repository Url | Language | Organization | Commentary
--- | --- | --- | ---
[BLS Remote Signer](https://github.com/sigp/rust-bls-remote-signer) | Rust | Sigma Prime | Supports proposed specification.
[Web3signer](https://github.com/PegaSysEng/web3signer) | Java | PegaSys | Supports proposed specification, although with [slightly different methods](https://pegasyseng.github.io/web3signer/web3signer-eth2.html):&lt;br&gt;{`/sign` =&gt; `/api/v1/eth2/sign`, `/publicKeys` =&gt; `/api/v1/eth2/publicKeys`}.
[Remote Signing Wallet](https://docs.prylabs.network/docs/wallet/remote/) | Golang | Prysmatics Labs | Supports both gRPC and JSON over HTTP.

## Security Considerations

### Threat model

Let&apos;s consider the following threats and their mitigations:

Threat | Mitigation(s)
--- | ---
An attacker can spoof the validator client. | See the discussion at [Authentication](#authentication).
An attacker can send a crafted message to the signer, leading to a slashing offense. | It is the responsibility of the operator of the remote signer to add a validation module, as discussed at [Implementation of additional features](#implementation-of-additional-features).
An attacker can create, update, or delete secret keys. | Keys are not to be writable via any interface of the remote signer.
An attacker can repudiate a sent message. | Implement logging in the signer. Enhance it by sending logs to a syslog box.
An attacker can disclose the contents of a private key by retrieving the key from storage. | Storage in Hardware security module (HSM).&lt;br&gt;_or_&lt;br&gt;Storage in Secrets management applications (e.g. Hashicorp Vault).
An attacker can eavesdrop on the uploading of a secret key. | Upload the keys using a secure channel, based on each storage specification.
An attacker can eavesdrop on the retrieval of a key from the remote signer. | Always pass the data between storage and remote signer node using a secure channel.
An attacker can dump the memory in the remote signer to disclose a secret key. | Prevent physical access to the node running the remote signer.&lt;br&gt;_or_&lt;br&gt;Prevent access to the terminal of the node running the remote signer: Logs being sent to a syslog box. Deployments triggered by a simple, non-parameterized API.&lt;br&gt;_or_&lt;br&gt;Implement zeroization of the secret key at memory.&lt;br&gt;_or_&lt;br&gt;Explore the compilation and running of the remote signer in a Trusted execution environment (TEE).
An attacker can DoS the remote signer. | Implement IP filtering.&lt;br&gt;_or_&lt;br&gt;Implement Rate limiting.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 30 Sep 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3030</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3030</guid>
      </item>
    
      <item>
        <title>Adds `baseFee` to `eth_getBlockByHash`</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3041-add-basefee-in-eth-getblockbyhash-response/4825</comments>
        
        <description>## Simple Summary
Add basefee field to `eth_getBlockByHash` RPC endpoint response.

## Abstract
Adds `baseFee` property to the `eth_getBlockByHash` JSON-RPC request `result` object.  This property will contain the value of the base fee for any block after the EIP-1559 fork.

## Motivation
[EIP-1559](/EIPs/EIPS/eip-1559) introduces a base fee per gas in protocol.
This value is maintained under consensus as a new field in the block header structure.
Users may need value of the base fee at a given block. Base fee value is important to make gas price predictions more accurate.

## Specification

### `eth_getBlockByHash`

#### Description

Returns information about a block specified by hash.
Every block returned by this endpoint whose block number is before the [EIP-1559](/EIPs/EIPS/eip-1559) fork block **MUST NOT** include a `baseFee` field.
Every block returned by this endpoint whose block number is on or after the [EIP-1559](/EIPs/EIPS/eip-1559) fork block **MUST** include a `baseFee` field.

#### Parameters

Parameters remain unchanged.

#### Returns
For the full specification of `eth_getBlockByHash` see [EIP-1474](/EIPs/EIPS/eip-1474).
Add a new JSON field to the `result` object for block headers containing a base fee (post [EIP-1559](/EIPs/EIPS/eip-1559) fork block).

- {[`Quantity`](/EIPs/EIPS/eip-1474#quantity)} `baseFee` - base fee for this block

#### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1559,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_getBlockByHash&quot;,
    &quot;params&quot;:[&quot;0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;, true]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1559,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: {
        &quot;difficulty&quot;: &quot;0x027f07&quot;,
        &quot;extraData&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
        &quot;baseFee&quot;: &quot;0x7&quot;
        &quot;gasLimit&quot;: &quot;0x9f759&quot;,
        &quot;gasUsed&quot;: &quot;0x9f759&quot;,
        &quot;hash&quot;: &quot;0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;,
        &quot;logsBloom&quot;: &quot;0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;,
        &quot;miner&quot;: &quot;0x4e65fda2159562a496f9f3522f89122a3088497a&quot;,
        &quot;nonce&quot;: &quot;0xe04d296d2460cfb8472af2c5fd05b5a214109c25688d3704aed5484f9a7792f2&quot;,
        &quot;number&quot;: &quot;0x1b4&quot;,
        &quot;parentHash&quot;: &quot;0x9646252be9520f6e71339a8df9c55e4d7619deeb018d2a3f2d21fc165dde5eb5&quot;,
        &quot;sha3Uncles&quot;: &quot;0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347&quot;,
        &quot;size&quot;:  &quot;0x027f07&quot;,
        &quot;stateRoot&quot;: &quot;0xd5855eb08b3387c0af375e9cdb6acfc05eb8f519e419b874b6ff2ffda7ed1dff&quot;,
        &quot;timestamp&quot;: &quot;0x54e34e8e&quot;
        &quot;totalDifficulty&quot;:  &quot;0x027f07&quot;,
        &quot;transactions&quot;: []
        &quot;transactionsRoot&quot;: &quot;0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421&quot;,
        &quot;uncles&quot;: []
    }
}
```

## Rationale
The addition of a single parameter instead of introducing a whole new endpoint was the simplest change that would be easiest to get integrated.
For backward compatibility we decided to not include the base fee in the response for pre-1559 blocks.  

## Backwards Compatibility
Backwards compatible. Calls related to block prior to [EIP-1559](/EIPs/EIPS/eip-1559) fork block will omit the base fee field in the response.

## Security Considerations
The added field (`baseFee`) is informational and does not introduce technical security issues.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 13 Oct 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3041</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3041</guid>
      </item>
    
      <item>
        <title>Adds `baseFee` to `eth_getBlockByNumber`</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3044-add-basefee-to-eth-getblockbynumber/4828</comments>
        
        <description>## Simple Summary
Add basefee field to `eth_getBlockByNumber` RPC endpoint response.

## Abstract
Adds `baseFee` property to the `eth_getBlockByNumber` JSON-RPC request `result` object.  This property will contain the value of the base fee for any block after the EIP-1559 fork.

## Motivation
[EIP-1559](/EIPs/EIPS/eip-1559) introduces a base fee per gas in protocol.
This value is maintained under consensus as a new field in the block header structure.
Users may need value of the base fee at a given block. Base fee value is important to make gas price predictions more accurate.

## Specification

### `eth_getBlockByNumber`

#### Description

Returns information about a block specified by number.
Every block returned by this endpoint whose block number is before the [EIP-1559](/EIPs/EIPS/eip-1559) fork block **MUST NOT** include a `baseFee` field.
Every block returned by this endpoint whose block number is on or after the [EIP-1559](/EIPs/EIPS/eip-1559) fork block **MUST** include a `baseFee` field.

#### Parameters

Parameters remain unchanged.

#### Returns
For the full specification of `eth_getBlockByNumber` see [EIP-1474](/EIPs/EIPS/eip-1474).
Add a new JSON field to the `result` object for block headers containing a base fee (post [EIP-1559](/EIPs/EIPS/eip-1559) fork block).

- {[`Quantity`](/EIPs/EIPS/eip-1474#quantity)} `baseFee` - base fee for this block

#### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1559,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_getBlockByNumber&quot;,
    &quot;params&quot;:[&quot;latest&quot;, true]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1559,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: {
        &quot;difficulty&quot;: &quot;0x027f07&quot;,
        &quot;extraData&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
        &quot;baseFee&quot;: &quot;0x7&quot;
        &quot;gasLimit&quot;: &quot;0x9f759&quot;,
        &quot;gasUsed&quot;: &quot;0x9f759&quot;,
        &quot;hash&quot;: &quot;0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;,
        &quot;logsBloom&quot;: &quot;0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;,
        &quot;miner&quot;: &quot;0x4e65fda2159562a496f9f3522f89122a3088497a&quot;,
        &quot;nonce&quot;: &quot;0xe04d296d2460cfb8472af2c5fd05b5a214109c25688d3704aed5484f9a7792f2&quot;,
        &quot;number&quot;: &quot;0x1b4&quot;,
        &quot;parentHash&quot;: &quot;0x9646252be9520f6e71339a8df9c55e4d7619deeb018d2a3f2d21fc165dde5eb5&quot;,
        &quot;sha3Uncles&quot;: &quot;0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347&quot;,
        &quot;size&quot;:  &quot;0x027f07&quot;,
        &quot;stateRoot&quot;: &quot;0xd5855eb08b3387c0af375e9cdb6acfc05eb8f519e419b874b6ff2ffda7ed1dff&quot;,
        &quot;timestamp&quot;: &quot;0x54e34e8e&quot;
        &quot;totalDifficulty&quot;:  &quot;0x027f07&quot;,
        &quot;transactions&quot;: []
        &quot;transactionsRoot&quot;: &quot;0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421&quot;,
        &quot;uncles&quot;: []
    }
}
```

## Rationale
The addition of a single parameter instead of introducing a whole new endpoint was the simplest change that would be easiest to get integrated.
For backward compatibility we decided to not include the base fee in the response for pre-1559 blocks.

## Backwards Compatibility
Backwards compatible. Calls related to block prior to [EIP-1559](/EIPs/EIPS/eip-1559) fork block will omit the base fee field in the response.

## Security Considerations
The added field (`baseFee`) is informational and does not introduce technical security issues.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 14 Oct 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3044</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3044</guid>
      </item>
    
      <item>
        <title>Adds `baseFee` to `eth_getUncleByBlockHashAndIndex`</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/add-basefee-to-eth-getunclebyblockhashandindex/4829</comments>
        
        <description>## Simple Summary
Add basefee field to `eth_getUncleByBlockHashAndIndex` RPC endpoint response.

## Abstract
Adds `baseFee` property to the `eth_getUncleByBlockHashAndIndex` JSON-RPC request `result` object.  This property will contain the value of the base fee for any block after the EIP-1559 fork.

## Motivation
[EIP-1559](/EIPs/EIPS/eip-1559) introduces a base fee per gas in protocol.
This value is maintained under consensus as a new field in the block header structure.
Users may need value of the base fee at a given block. Base fee value is important to make gas price predictions more accurate.

## Specification

### `eth_getUncleByBlockHashAndIndex`

#### Description

Returns information about an uncle specified by block hash and uncle index position
Every block returned by this endpoint whose block number is before the [EIP-1559](/EIPs/EIPS/eip-1559) fork block **MUST NOT** include a `baseFee` field.
Every block returned by this endpoint whose block number is on or after the [EIP-1559](/EIPs/EIPS/eip-1559) fork block **MUST** include a `baseFee` field.

#### Parameters

Parameters remain unchanged.

#### Returns
For the full specification of `eth_getUncleByBlockHashAndIndex` see [EIP-1474](/EIPs/EIPS/eip-1474).
Add a new JSON field to the `result` object for block headers containing a base fee (post [EIP-1559](/EIPs/EIPS/eip-1559) fork block).

- {[`Quantity`](/EIPs/EIPS/eip-1474#quantity)} `baseFee` - base fee for this block

#### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1559,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_getUncleByBlockHashAndIndex&quot;,
    &quot;params&quot;:[&quot;0xc6ef2fc5426d6ad6fd9e2a26abeab0aa2411b7ab17f30a99d3cb96aed1d1055b&quot;, &quot;0x0&quot;]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1559,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: {
        &quot;difficulty&quot;: &quot;0x027f07&quot;,
        &quot;extraData&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
        &quot;baseFee&quot;: &quot;0x7&quot;
        &quot;gasLimit&quot;: &quot;0x9f759&quot;,
        &quot;gasUsed&quot;: &quot;0x9f759&quot;,
        &quot;hash&quot;: &quot;0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;,
        &quot;logsBloom&quot;: &quot;0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;,
        &quot;miner&quot;: &quot;0x4e65fda2159562a496f9f3522f89122a3088497a&quot;,
        &quot;nonce&quot;: &quot;0xe04d296d2460cfb8472af2c5fd05b5a214109c25688d3704aed5484f9a7792f2&quot;,
        &quot;number&quot;: &quot;0x1b4&quot;,
        &quot;parentHash&quot;: &quot;0x9646252be9520f6e71339a8df9c55e4d7619deeb018d2a3f2d21fc165dde5eb5&quot;,
        &quot;sha3Uncles&quot;: &quot;0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347&quot;,
        &quot;size&quot;:  &quot;0x027f07&quot;,
        &quot;stateRoot&quot;: &quot;0xd5855eb08b3387c0af375e9cdb6acfc05eb8f519e419b874b6ff2ffda7ed1dff&quot;,
        &quot;timestamp&quot;: &quot;0x54e34e8e&quot;
        &quot;totalDifficulty&quot;:  &quot;0x027f07&quot;,
        &quot;transactions&quot;: []
        &quot;transactionsRoot&quot;: &quot;0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421&quot;,
        &quot;uncles&quot;: []
    }
}
```

## Rationale
The addition of a single parameter instead of introducing a whole new endpoint was the simplest change that would be easiest to get integrated.
For backward compatibility we decided to not include the base fee in the response for pre-1559 blocks.

## Backwards Compatibility
Backwards compatible. Calls related to block prior to [EIP-1559](/EIPs/EIPS/eip-1559) fork block will omit the base fee field in the response.

## Security Considerations
The added field (`baseFee`) is informational and does not introduce technical security issues.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 14 Oct 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3045</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3045</guid>
      </item>
    
      <item>
        <title>Adds `baseFee` to `eth_getUncleByBlockNumberAndIndex`</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/add-basefee-to-eth-getunclebyblocknumberandindex/4830</comments>
        
        <description>## Simple Summary
Add basefee field to `eth_getUncleByBlockNumberAndIndex` RPC endpoint response.

## Abstract
Adds `baseFee` property to the `eth_getUncleByBlockNumberAndIndex` JSON-RPC request `result` object.  This property will contain the value of the base fee for any block after the EIP-1559 fork.

## Motivation
[EIP-1559](/EIPs/EIPS/eip-1559) introduces a base fee per gas in protocol.
This value is maintained under consensus as a new field in the block header structure.
Users may need value of the base fee at a given block. Base fee value is important to make gas price predictions more accurate.

## Specification

### `eth_getUncleByBlockNumberAndIndex`

#### Description

Returns information about an uncle specified by block number and uncle index position
Every block returned by this endpoint whose block number is before the [EIP-1559](/EIPs/EIPS/eip-1559) fork block **MUST NOT** include a `baseFee` field.
Every block returned by this endpoint whose block number is on or after the [EIP-1559](/EIPs/EIPS/eip-1559) fork block **MUST** include a `baseFee` field.

#### Parameters

Parameters remain unchanged.

#### Returns
For the full specification of `eth_getUncleByBlockNumberAndIndex` see [EIP-1474](/EIPs/EIPS/eip-1474).
Add a new JSON field to the `result` object for block headers containing a base fee (post [EIP-1559](/EIPs/EIPS/eip-1559) fork block).

- {[`Quantity`](/EIPs/EIPS/eip-1474#quantity)} `baseFee` - base fee for this block

#### Example

```sh
# Request
curl -X POST --data &apos;{
    &quot;id&quot;: 1559,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;method&quot;: &quot;eth_getUncleByBlockNumberAndIndex&quot;,
    &quot;params&quot;:[&quot;latest&quot;, &quot;0x0&quot;]
}&apos; &lt;url&gt;

# Response
{
    &quot;id&quot;: 1559,
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;result&quot;: {
        &quot;difficulty&quot;: &quot;0x027f07&quot;,
        &quot;extraData&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;,
        &quot;baseFee&quot;: &quot;0x7&quot;
        &quot;gasLimit&quot;: &quot;0x9f759&quot;,
        &quot;gasUsed&quot;: &quot;0x9f759&quot;,
        &quot;hash&quot;: &quot;0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;,
        &quot;logsBloom&quot;: &quot;0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;,
        &quot;miner&quot;: &quot;0x4e65fda2159562a496f9f3522f89122a3088497a&quot;,
        &quot;nonce&quot;: &quot;0xe04d296d2460cfb8472af2c5fd05b5a214109c25688d3704aed5484f9a7792f2&quot;,
        &quot;number&quot;: &quot;0x1b4&quot;,
        &quot;parentHash&quot;: &quot;0x9646252be9520f6e71339a8df9c55e4d7619deeb018d2a3f2d21fc165dde5eb5&quot;,
        &quot;sha3Uncles&quot;: &quot;0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347&quot;,
        &quot;size&quot;:  &quot;0x027f07&quot;,
        &quot;stateRoot&quot;: &quot;0xd5855eb08b3387c0af375e9cdb6acfc05eb8f519e419b874b6ff2ffda7ed1dff&quot;,
        &quot;timestamp&quot;: &quot;0x54e34e8e&quot;
        &quot;totalDifficulty&quot;:  &quot;0x027f07&quot;,
        &quot;transactions&quot;: []
        &quot;transactionsRoot&quot;: &quot;0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421&quot;,
        &quot;uncles&quot;: []
    }
}
```

## Rationale
The addition of a single parameter instead of introducing a whole new endpoint was the simplest change that would be easiest to get integrated.
For backward compatibility we decided to not include the base fee in the response for pre-1559 blocks.

## Backwards Compatibility
Backwards compatible. Calls related to block prior to [EIP-1559](/EIPs/EIPS/eip-1559) fork block will omit the base fee field in the response.

## Security Considerations
The added field (`baseFee`) is informational and does not introduce technical security issues.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 14 Oct 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3046</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3046</guid>
      </item>
    
      <item>
        <title>Precompile for BN256 HashToCurve Algorithms</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/pre-compile-for-bls/3973</comments>
        
        <description>## Simple Summary
This EIP defines a hash-to-curve precompile for use in BN256
and would allow for cheaper BLS signature verification.

## Abstract
There is currently no inexpensive way to perform BLS signature
verification for arbitrary messages.
This stems from the fact that there is no precompiled contract
in the EVM for a hash-to-curve algorithm for the BN256 elliptic curve.
The gas cost of calling a deterministic hash-to-curve algorithm
written in Solidity is approximately that of one pairing check,
although the latter requires an order of magnitude
more computation.
This EIP remedies this by implementing a hash-to-curve algorithm
for the BN256 G1 curve, which would reduce the cost of
signature verification to essentially that of the pairing check
precompiled contract.
We also include a hash-to-curve algorithm for the BN256 G2 group.

## Motivation
The precompiled contracts in
[EIP-198](/EIPs/EIPS/eip-198) and
[EIP-1108](/EIPs/EIPS/eip-1108)
increased usage of cryptographic operations in the EVM
by reducing the gas costs.
In particular, the cost reduction from
[EIP-1108](/EIPs/EIPS/eip-1108)
helps increase the use of SNARKs in Ethereum
via an elliptic curve pairing check;
however, a hash-to-curve algorithm enabling arbitrary
BLS signature verification on BN256 in the EVM was noticeably missing.
There is interest in having a precompiled contract which would allow
for signature verification, as noted
[here](https://ethereum-magicians.org/t/pre-compile-for-bls/3973).

At this time, we are able to perform addition, scalar multiplication,
and pairing checks in BN256.
Reducing these costs in
[EIP-1108](/EIPs/EIPS/eip-1108)
made [ETHDKG](https://github.com/PhilippSchindler/ethdkg),
a distributed key generation protocol in Ethereum,
less expensive.
ETHDKG by itself is useful; however, what it is lacking is
the ability to verify arbitrary BLS signatures.
Creating group signatures by aggregating partial signatures
is one goal of a DKG protocol.
The DKG enables the computation of partial signatures to be
combined into a group signature offline, but there is no
easy way to verify partial signatures or group signatures
in the EVM.

In order to perform BLS signature validation, a hash-to-curve
algorithm is required.
While the MapToGroup method initially discussed in the original BLS
[paper](/EIPs/assets/eip-3068/weilsigs.pdf)
works in practice, the nondeterministic nature of the algorithm
leaves something to be desired as we would like to bound
the overall computational cost in the EVM.
A deterministic method for mapping to BN curves is given
[here](/EIPs/assets/eip-3068/latincrypt12.pdf);
in the paper, Fouque and Tibouchi proved their mapping
was indifferentiable from a random oracle.
This gives us the desired algorithm.

## Specification
Here is the pseudocode for the `HashToG1` function:

```
function HashToG1(msg)
    fieldElement0 = HashToBase(msg, 0x00, 0x01)
    fieldElement1 = HashToBase(msg, 0x02, 0x03)
    curveElement0 = BaseToG1(fieldElement0)
    curveElement1 = BaseToG1(fieldElement1)
    g1Element = ECAdd(curveElement0, curveElement1)
    return g1Element
end function
```

Here is the pseudocode for `HashToBase`;
`msg` is the byte slice to be hashed while `dsp1` and `dsp2`
are domain separation parameters.
`fieldPrime` is the prime of the underlying field.

```
function HashToBase(msg, dsp1, dsp2)
    hashResult0 = uint256(Keccak256(dsp1||msg))
    hashResult1 = uint256(Keccak256(dsp2||msg))
    constant = 2^256 mod fieldPrime
    fieldElement0 = hashResult0*constant          mod fieldPrime
    fieldElement1 = hashResult1                   mod fieldPrime
    fieldElement  = fieldElement0 + fieldElement1 mod fieldPrime
    return fieldElement
end function
```

Here is the pseudocode for `BaseToG1`.
All of these operations are performed in the finite field.
`inverse` computes the multiplicative inverse in the underlying
finite field; we have the convention `inverse(0) == 0`.
`is_square(a)` computes the Legendre symbol of the element,
returning 1 if `a` is a square, -1 if `a` is not a square,
and 0 if `a` is 0.
`sqrt` computes the square root of the element in the finite
field; a square root is assumed to exist.
`sign0` returns the sign of the finite field element.

```
function BaseToG1(t)
    # All operations are done in the finite field GF(fieldPrime)
    # Here, the elliptic curve satisfies the equation
    #       y^2 == g(x) == x^3 + curveB
    constant1 = (-1 + sqrt(-3))/2
    constant2 = -3
    constant3 = 1/3
    constant4 = g(1)
    s = (constant4 + t^2)^3
    alpha = inverse(t^2*(constant4 + t^2))
    x1 = constant1 - constant2*t^4*alpha
    x2 = -1 - x1
    x3 = 1 - constant3*s*alpha
    a1 = x1^3 + curveB
    a2 = x2^3 + curveB
    residue1 = is_square(a1)
    residue2 = is_square(a2)
    index = (residue1 - 1)*(residue2 - 3)/4 + 1
    coef1 = ConstantTimeEquality(1, index)
    coef2 = ConstantTimeEquality(2, index)
    coef3 = ConstantTimeEquality(3, index)
    x = coef1*x1 + coef2*x2 + coef3*x3
    y = sign0(t)*sqrt(x^3 + curveB)
    return (x, y)
end function

function sign0(t)
    if t &lt;= (fieldPrime-1)/2
        return 1
    else
        return fieldPrime-1
    end if
end function

function ConstantTimeEquality(a, b)
    # This function operates in constant time
    if a == b
        return 1
    else
        return 0
    end if
end function
```

In `HashToG2`, we first map to the underlying twist curve
and then clear the cofactor to map to G2.
Here is the pseudocode for `HashToG2`:

```
function HashToG2(msg)
    fieldElement00 = HashToBase(msg, 0x04, 0x05)
    fieldElement01 = HashToBase(msg, 0x06, 0x07)
    fieldElement10 = HashToBase(msg, 0x08, 0x09)
    fieldElement11 = HashToBase(msg, 0x0a, 0x0b)
    fieldElement0 = (fieldElement00, fieldElement01)
    fieldElement1 = (fieldElement10, fieldElement11)
    twistElement0 = BaseToTwist(fieldElement0)
    twistElement1 = BaseToTwist(fieldElement1)
    twistElement = ECAdd(twistElement0, twistElement1)
    g2Element = ClearCofactor(twistElement)
    return g2Element
end function

function ClearCofactor(twistElement)
    return ECMul(twistElement, cofactor)
end function
```

Here is the pseudocode for `BaseToTwist`.

```
function BaseToTwist(t)
    # All operations are done in the finite field GF(fieldPrime^2)
    # Here, the twist curve satisfies the equation
    #       y^2 == g&apos;(x) == x^3 + curveBPrime
    constant1 = (-1 + sqrt(-3))/2
    constant2 = -3
    constant3 = 1/3
    constant4 = g&apos;(1)
    s = (constant4 + t^2)^3
    alpha = inverse(t^2*(constant4 + t^2))
    x1 = constant1 - constant2*t^4*alpha
    x2 = -1 - x1
    x3 = 1 - constant3*s*alpha
    a1 = x1^3 + curveBPrime
    a2 = x2^3 + curveBPrime
    residue1 = is_square(a1)
    residue2 = is_square(a2)
    index = (residue1 - 1)*(residue2 - 3)/4 + 1
    coef1 = ConstantTimeEquality(1, index)
    coef2 = ConstantTimeEquality(2, index)
    coef3 = ConstantTimeEquality(3, index)
    x = coef1*x1 + coef2*x2 + coef3*x3
    y = sign0(t)*sqrt(x^3 + curveBPrime)
    return (x, y)
end function
```

## Rationale
The BaseToG1 algorithm is based on the original Fouque and Tibouchi
[paper](/EIPs/assets/eip-3068/latincrypt12.pdf)
with modifications based on Wahby and Boneh&apos;s
[paper](/EIPs/assets/eip-3068/2019-403_BLS12_H2C.pdf).
There is freedom in choosing the HashToBase function
and this could easily be changed.
Within HashToBase, the particular hashing algorithm
(Keccak256 in our case) could also be modified.
It may be desired to change the call to `sign0`
at the end of BaseToG1 and BaseToTwist with `is_square`,
as this would result in the same deterministic map to curve from the
Fouque and Tibouchi
[paper](/EIPs/assets/eip-3068/latincrypt12.pdf)
and ensure HashToG1 is indifferentiable from a random oracle;
they proved this result in their paper.
It may be possible to show that switching the `is_square`
call with `sign0` does not affect indifferentiability,
although this has not been proven.

The HashToG2 algorithm follows from the Wahby and Boneh
[paper](/EIPs/assets/eip-3068/2019-403_BLS12_H2C.pdf).
Algorithms for computing `inverse`, `is_square`, and `sqrt`
in finite field GF(fieldPrime^2) can be found
[here](/EIPs/assets/eip-3068/2012-685_Square_Root_Even_Ext.pdf).

We now discuss the potential gas cost for the HashToG1
and HashToG2 operations.
On a local machine, ECMul was clocked at 68 microseconds
per operation.
The same machine clocked HashToG1 at 94 microseconds per operation
when hashing 32 bytes into G1 and 105 microseconds per operation
when hashing 1024 bytes into G1.
Given that it currently costs 6000 gas for ECMul, this gives us
an estimated gas cost for HashToG1 at `8500 + len(bytes)`.
Similarly, HashToG2 was clocked at 886 microseconds per operation
when hashing 32 bytes into G2 and 912 microseconds per operation when
hashing 1024 bytes into G2.
This allows us to estimate the gas cost at `80000 + 3*len(bytes)`.

## Backwards Compatibility
There are no backward compatibility concerns.

## Test Cases
TBD

## Implementation
TBD

## Security Considerations
Due to recent [work](/EIPs/assets/eip-3068/2015-1027_exTNFS.pdf), the
128-bit security promised by the BN256 elliptic curve no longer applies;
this was mentioned in the Cloudflare BN256
[library](https://github.com/cloudflare/bn256).
There has been some discussion on the exact security decrease
from this advancement; see these
[two](/EIPs/assets/eip-3068/2016-1102_Assessing_NFS_Advances.pdf)
[papers](/EIPs/assets/eip-3068/2017-334.pdf)
for different estimates.
The more conservative estimate puts the security of BN256 at
100-bits.
While this is likely still out of reach for many adversaries,
it should give us pause.
This reduced security was noted in the recent MadNet
[whitepaper](/EIPs/assets/eip-3068/madnet.pdf),
and this security concern was partially mitigated by
requiring Secp256k1 signatures of the partial group signatures
in order for those partial signatures to be valid.
Full disclosure: the author of this EIP works for MadHive,
assisted in the development of MadNet, and
helped write the MadNet whitepaper.

The security concerns of the BN256 elliptic curve
affect any operation using pairing check because it is
related to the elliptic curve pairing;
they are independent of this EIP.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 23 Oct 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3068</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3068</guid>
      </item>
    
      <item>
        <title>AUTH and AUTHCALL opcodes</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3074-sponsored-transaction-precompile/4880</comments>
        
        <description>## Abstract

This EIP introduces two EVM instructions `AUTH` and `AUTHCALL`. The first sets a context variable `authorized` based on an ECDSA signature. The second sends a call as the `authorized` account. This essentially delegates control of the externally owned account (EOA) to a smart contract.

## Motivation

Adding more functionality to EOAs has been a long-standing feature request. The requests have spanned from implementing batching capabilities, allowing for gas sponsoring, expirations, scripting, and beyond. These changes often mean increased complexity and rigidity of the protocol. In some cases, it also means increased attack surfaces.

This EIP takes a different approach. Instead of enshrining these capabilities in the protocol as transaction validity requirements, it allows users to *delegate* control of their EOA to a contract. This gives developers a flexible framework for developing novel transaction schemes for EOAs. A motivating use case of this EIP is that it allows any EOA to act like a smart contract wallet *without* deploying a contract.

Although this EIP provides great benefit to individual users, the leading motivation for this EIP is &quot;sponsored transactions&quot;. This is where the fee for a transaction is provided by a different account than the one that originates the call.

With the extraordinary growth of tokens on Ethereum, it has become common for EOAs to hold valuable assets without holding any ether at all. Today, these assets must be converted to ether before they can be used to pay gas fees. However, without ether to pay for the conversion, it&apos;s impossible to convert them. Sponsored transactions break the circular dependency.

## Specification

### Conventions

 - **`top - N`** - the `N`th most recently pushed value on the EVM stack, where `top - 0` is the most recent.
 - **`||`** - byte concatenation operator.
 - **invalid execution** - execution that is invalid and must exit the current execution frame immediately, consuming all remaining gas (in the same way as a stack underflow or invalid jump).

### Constants

|     Constant     | Value  |
| ---------------- | ------ |
| `MAGIC`          | `0x04` |

`MAGIC` is used for [EIP-3074](/EIPs/EIPS/eip-3074) signatures to prevent signature collisions with other signing formats.

### Context Variables

|     Variable        | Type      | Initial Value |
| ------------------- | --------- |:------------- |
| `authorized`        | `address` | unset         |

The context variable `authorized` shall indicate the active account for `AUTHCALL` instructions in the current frame of execution. If set, `authorized` shall only contain an account which has given the contract authorization to act on its behalf. An unset value shall indicate that no such account is set and that there is not yet an active account for `AUTHCALL` instructions in the current frame of execution.

The variable has the same scope as the program counter -- `authorized` persists throughout a single frame of execution of the contract, but is not passed through any calls (including `DELEGATECALL`). If the same contract is being executed in separate execution frames (ex. a `CALL` to self), both frames shall have independent values for `authorized`. Initially in each frame of execution, `authorized` is always unset, even if a previous execution frame for the same contract has a value.

### `AUTH` (`0xf6`)

A new opcode `AUTH` shall be created at `0xf6`. It shall take three stack element inputs (the last two describing a memory range), and it shall return one stack element.

#### Input

##### Stack

| Stack      | Value        |
| ---------- | ------------ |
| `top - 0`  | `authority`  |
| `top - 1`  | `offset`     |
| `top - 2`  | `length`     |

##### Memory

The final two stack arguments (`offset` and `length`) describe a range of memory. The format of the contents of that range is:

 - `memory[offset    : offset+1 ]` - `yParity`
 - `memory[offset+1  : offset+33]` - `r`
 - `memory[offset+33 : offset+65]` - `s`
 - `memory[offset+65 : offset+97]` - `commit`

#### Output

##### Stack

| Stack      | Value        |
| ---------- | -------------|
| `top - 0`  | `success`    |

##### Memory

Memory is not modified by this instruction.

#### Behavior

If `length` is greater than 97, the extra bytes are ignored for signature verification (they still incur a gas cost as defined later). Bytes outside the range (in the event `length` is less than 97) are treated as if they had been zeroes.

`authority` is the address of the account which generated the signature. If `EXTCODESIZE` of `authority` is not zero, consider the operation unsuccessful and unset `authorized`.

The arguments (`yParity`, `r`, `s`) are interpreted as an ECDSA signature on the secp256k1 curve over the message `keccak256(MAGIC || chainId || nonce || invokerAddress || commit)`, where:

 - `chainId` is the current chain&apos;s [EIP-155](/EIPs/EIPS/eip-155) unique identifier padded to 32 bytes.
 - `nonce` is the signer&apos;s current nonce, left-padded to 32 bytes.
 - `invokerAddress` is the address of the contract executing `AUTH` (or the active state address in the context of `CALLCODE` or `DELEGATECALL`), left-padded with zeroes to a total of 32 bytes (ex. `0x000000000000000000000000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA`).
 - `commit`, one of the arguments passed into `AUTH`, is a 32-byte value that can be used to commit to specific additional validity conditions in the invoker&apos;s pre-processing logic.

Signature validity and signer recovery are handled analogously to transaction signatures, including the stricter `s` range for preventing ECDSA malleability. Note that `yParity` is expected to be `0` or `1`.

If the signature is valid and the signer address is equal to `authority`, the context variable `authorized` is set to the `authority`. In particular, this is also true if `authority == tx.origin`, which used to be handled separately in earlier versions of this EIP (see Security Considerations). If the signature is instead invalid or the signer address does not equal `authority`, `authorized` is reset to an unset value.

`AUTH` returns `1` if `authorized` is set, or `0` otherwise.

#### Gas Cost

The gas cost for `AUTH` is equal to the sum of:

 - fixed fee `3100`.
 - memory expansion gas cost (`auth_memory_expansion_fee`).
 - `100` if `authority` is warm, `2600` if it is cold (per [EIP-2929](/EIPs/EIPS/eip-2929)).

The fixed fee is equal to the cost for the `ecrecover` precompile, plus a bit extra to cover a keccak256 hash and some additional logic.

The memory expansion gas cost (`auth_memory_expansion_fee`) shall be calculated in the same way as `RETURN`, where memory is expanded if the specified range is outside the current allocation.

### `AUTHCALL` (`0xf7`)

A new opcode `AUTHCALL` shall be created at `0xf7`. It shall take seven stack elements and return one stack element. It matches the behavior of the existing `CALL` (`0xF1`) instruction, except where noted below.

#### Input

| Stack     | Value        |
| --------- | ------------ |
| `top - 0` | `gas`        |
| `top - 1` | `addr`       |
| `top - 2` | `value`      |
| `top - 3` | `argsOffset` |
| `top - 4` | `argsLength` |
| `top - 5` | `retOffset`  |
| `top - 6` | `retLength`  |

#### Output

| Stack      | Value     |
| ---------- | --------- |
| `top - 0`  | `success` |

#### Behavior

`AUTHCALL` is interpreted the same as `CALL`, except for (note: this list is also the order of precedence for the logical checks):

 - If `authorized` is unset, execution is invalid (as defined above). Otherwise, the caller address for the call is set to `authorized`.
 - The gas cost, including how much gas is available for the subcall, is specified in the Gas Cost section.
 - If the `gas` operand is equal to `0`, the instruction will send all available gas as per [EIP-150](./eip-150).
 - If the gas available for the subcall would be less than `gas`, execution is invalid.
 - There is no gas stipend, even for non-zero `value`.
 - `value` is deducted from the balance of `authorized`. If `value` is higher than the balance of `authorized`, execution is invalid.

`AUTHCALL` must increase the call depth by one. `AUTHCALL` must not increase the call depth by two as it would if it first called into the authorized account and then into the target.

The return data area accessed with `RETURNDATASIZE` (`0x3d`) and `RETURNDATACOPY` (`0x3e`) must be set in the same way as the `CALL` instruction.

Importantly, `AUTHCALL` does not reset `authorized`, but leaves it unchanged.

#### Gas Cost

The gas cost for `AUTHCALL` shall be the **sum** of:

 - static gas cost (`warm_storage_read`)
 - memory expansion gas cost (`memory_expansion_fee`)
 - dynamic gas cost (`dynamic_gas`)
 - gas available for execution in the subcall (`subcall_gas`)

The memory expansion gas cost (`memory_expansion_fee`) shall be calculated in the same way as `CALL`.

The dynamic gas portion (`dynamic_gas`), and the gas available for execution in the subcall (`subcall_gas`) shall be calculated as:

```
dynamic_gas = 0

if addr not in accessed_addresses:
    dynamic_gas += 2500         # cold_account_access - warm_storage_read

if value &gt; 0:
    dynamic_gas += 6700         # NB: Not 9000, like in `CALL`
    if is_empty(addr):
        dynamic_gas += 25000

remaining_gas = available_gas - dynamic_gas
all_but_one_64th = remaining_gas - (remaining_gas // 64)

if gas == 0:
    subcall_gas = all_but_one_64th
elif all_but_one_64th &lt; gas:
    raise                       # Execution is invalid.
else:
    subcall_gas = gas
```

As with `CALL`, the full gas cost is charged immediately, independently of actually executing the call.

## Rationale

### Signature in Memory

The signature format (`yParity`, `r`, and `s`) is fixed, so it might seem curious that `auth` accepts a dynamic memory range. The signature is placed in memory so that `auth` can be upgraded in the future to work with contract accounts (which might use non-ECDSA signatures) and not just EOAs.

### Signing Address `auth` Argument

Including `authority` (the signing address) as an argument to `auth` allows future upgrades to the instruction to work with contract accounts, and not just EOAs.

If `authority` were not included and multiple signature schemes allowed, it would not be possible to compute the authorizing account&apos;s address from just the signature alone.

### Reserving One Sixty-Fourth of Available Gas

`AUTHCALL` will not pass more than 63/64th of the available gas for the reasons enumerated in [EIP-150](/EIPs/EIPS/eip-150).

### Throwing for Unset `authorized` During `AUTHCALL`

A well-behaved contract should never reach an `AUTHCALL` without having successfully set `authorized` beforehand. The safest behavior, therefore, is to exit the current frame of execution immediately. This is especially important in the context of transaction sponsoring / relaying, which is expected to be one of the main use cases for this EIP. In a sponsored transaction, the inability to distinguish between a sponsee-attributable fault (like a failing sub-call) and a sponsor-attributable fault (like a failing `AUTH`) is especially dangerous and should be prevented because it charges unfair fees to the sponsee.

### Another Sponsored Transaction EIP

There are two general approaches to separating the &quot;fee payer&quot; from the &quot;action originator&quot;.

The first is introducing a new transaction type. This requires significant changes to clients to support and is generally less upgradeable than other solutions (e.g. this EIP). This approach is also not immediately compatible with account abstraction (AA). These proposals require a *signed* transaction from the sponsor&apos;s account, which is not possible from an AA contract, because it has no private key to sign with. The main advantage of new transaction types is that the validity requirements are enforced by the protocol, therefore invalid transactions do not pollute block space.

The other main approach is to introduce a new mechanism in the EVM to masquerade as other accounts. This EIP introduces `AUTH` and `AUTHCALL` to make calls as EOAs. There are many different permutations of this mechanism. An alternative mechanism would be to add an opcode that can make arbitrary calls based on a similar address creation scheme as `CREATE2`. Although this mechanism would not benefit users today, it would immediately allow for those accounts to send and receive ether -- making it feel like a more first-class primitive.

Besides better compatibility with AA, introducing a new mechanism into the EVM is a much less intrusive change than a new transaction type. This approach requires no changes in existing wallets, and little change in other tooling.

`AUTHCALL`&apos;s single deviation from `CALL` is to set `CALLER`. It implements the minimal functionality to enable sender abstraction for sponsored transactions. This single mindedness makes `AUTHCALL` significantly more composable with existing Ethereum features.

More logic can be implemented around the `AUTHCALL` instruction, giving more control to invokers and sponsors without sacrificing security or user experience for sponsees.

### What to Sign?

As originally written, this proposal specified a precompile with storage to track nonces. Since a precompile with storage is unprecedented, a revision moved replay protection into the invoker contract, necessitating a certain level of user trust in the invoker. Expanding on this idea of trusted invokers, the other signed fields were eventually eliminated, one by one, until only `invoker` and `commit` remained. To appease concerns about cross-chain replay attacks and irrevocable signatures, the `chainId` and `nonce` fields returned to the signed message.

The `invoker` binds a particular signed message to a single invoker. If invoker was not part of the message, any invoker could reuse the signature to completely compromise the EOA. This allows users to trust that their message will be validated as they expect, particularly the values committed to in `commit`.

### Understanding `commit`

Earlier iterations of this EIP included mechanisms for replay protection, and also signed over value, gas, and other arguments to `AUTHCALL`. After further investigation, we revised this EIP to its current state: explicitly delegate these responsibilities to the invoker contract.

A user will specifically interact with an invoker they trust. Because they trust this contract to execute faithfully, they will &quot;commit&quot; to certain properties of a call they would like to make by computing a hash of the call values. They can be certain that the invoker will only allow the call to proceed if it is able to verify the values committed to (e.g. a nonce to protect against replay attacks). This certainty arises from the `commit` value that is signed over by the user. This is the hash of values which the invoker will validate. A safe invoker should accept the values from the user and compute the commit hash itself. This ensures that invoker operated on the same input that user authorized.

![auth message format](/EIPs/assets/eip-3074/auth-msg.png)

Using `commit` as a hash of values allows for invokers to implement arbitrary constraints. For example, they could allow accounts to have `N` parallel nonces. Or, they could allow a user to commit to multiple calls with a single signature. This would allow multi-tx flows, such as [ERC-20](/EIPs/EIPS/eip-20) `approve`-`transfer` actions, to be condensed into a single transaction with a single signature verification. A commitment to multiple calls would look something like the diagram below.

![multi-call auth message](/EIPs/assets/eip-3074/auth-msg-multi-call.png)

Another interesting use is to delegate control of the EOA to other key(s). This would mean the EOA signs a `commit` message with the address of the key(s) and an access policy, if applicable. When the delegate wants to make a call as the EOA it will construct a signature over the invoker-specified call format and relay it (with the actual call data) onto chain with the signature and commit that granted it access to the account. The invoker will then be able to determine that the EOA has allowed this alternative key to make calls on its behalf.

![delegate auth message](/EIPs/assets/eip-3074/auth-msg-delegate.png)


### Invoker Contracts

The invoker contract is a trustless intermediary between the sponsor and sponsee. A sponsee signs over `invoker` to require the transaction to be processed only by a contract they trust. This allows them to interact with sponsors without needing to trust them.

Choosing an invoker is similar to choosing a smart contract wallet implementation. It&apos;s important to choose one that has been thoroughly reviewed, tested, and accepted by the community as secure. We expect a few invoker designs to be utilized by most major transaction relay providers, with a few outliers that offer more novel mechanisms.

An important note is that invoker contracts **MUST NOT** be upgradeable. If an invoker can be redeployed to the same address with different code, it would be possible to redeploy the invoker with code that does not properly verify `commit` and any account that signed a message over that invoker would be compromised. Although this sounds scary, it is no different than using a smart contract wallet via `DELEGATECALL`. If the wallet is redeployed with different logic, all wallets using its code could be compromised.

### On Call Depth

The EVM limits the maximum number of nested calls, and naively allowing a sponsor to manipulate the call depth before reaching the invoker would introduce a griefing attack against the sponsee. That said, with the 63/64th gas rule, and the cost of `AUTHCALL`, the stack is effectively limited to a much smaller depth than the hard maximum by the `gas` parameter.

It is, therefore, sufficient for the invoker to guarantee a minimum amount of gas, because there is no way to reach the hard maximum call depth with any reasonable (i.e. less than billions) amount of gas.

### Source of `value`

In previous iterations of this EIP, it was thought that deducting value from an EOA mid-execution was problematic. This was due to an invariant of pending transactions which allows tx pools to statically determine the validity of a given transaction.

However, after further investigation we found that breaking the invariant is safe. This is mostly due to the fact that the worst case is similar in both instances.

Currently an attacker can queue many transactions in the tx pool, across many accounts, and invalidate them all at once with a block where each of the queued accounts send a tx moving their entire balance. This attack will become easier and cheaper after this EIP, because it will no longer require direct access to the block builder and will not cost a full 21000 gas to originate each tx. However, the attack does not have a substantial impact on the network, so reducing the difficulty and cost is not of concern.

### Allowing `tx.origin` as Signer

Allowing `authorized` to equal `tx.origin` enables simple transaction batching, where the sender of the outer transaction would be the signing account. The ERC-20 approve-then-transfer pattern, which currently requires two separate transactions, could be completed in a single transaction with this proposal.

`AUTH` allows for signatures to be signed by `tx.origin`. For any such signatures, subsequent `AUTHCALL`s have `msg.sender == tx.origin` in their first layer of execution. Without EIP-3074, this situation can only ever arise in the topmost execution layer of a transaction. This EIP breaks that invariant and so affects smart contracts containing `require(msg.sender == tx.origin)` checks. This check can be used for at least three purposes:

 1. Ensuring that `msg.sender` is an EOA (given that `tx.origin` always has to be an EOA). This invariant does not depend on the execution layer depth and, therefore, is not affected.
 2. Protecting against atomic sandwich attacks like flash loans, that rely on the ability to modify state before and after the execution of the target contract as part of the same atomic transaction. This protection would be broken by this EIP. However, relying on `tx.origin` in this way is considered bad practice, and can already be circumvented by miners conditionally including transactions in a block.
 3. Preventing reentrancy.

Examples of (1) and (2) can be found in contracts deployed on Ethereum mainnet, with (1) being more common (and unaffected by this proposal.) On the other hand, use case (3) is more severely affected by this proposal, but the authors of this EIP did not find any examples of this form of reentrancy protection, though the search was non-exhaustive.

This distribution of occurrences—many (1), some (2), and no (3)—is exactly what the authors of this EIP expect, because:

 - Determining if `msg.sender` is an EOA without `tx.origin` is difficult (if not impossible.)
 - The only execution context which is safe from atomic sandwich attacks is the topmost context, and `tx.origin == msg.sender` is the only way to detect that context.
 - In contrast, there are many direct and flexible ways of preventing reentrancy (ex. using a storage variable.) Since `msg.sender == tx.origin` is only true in the topmost context, it would make an obscure tool for preventing reentrancy, rather than other more common approaches.

There are other approaches to mitigate this restriction which do not break the invariant:

 - Set `tx.origin` to a constant `ENTRY_POINT` address for `AUTHCALL`s.
 - Set `tx.origin` to the invoker address for `AUTHCALL`s.
 - Set `tx.origin` to a special address derived from any of the sender, invoker, and/or signer addresses.
 - Disallow `authorized == tx.origin`. This would make the simple batching use cases impossible, but could be relaxed in the future.

### `AUTHCALL` cheaper than `CALL` when sending value

Sending non-zero value with `CALL` increases its cost by 9,000. Of that, 6,700 covers the increased overhead of the balance transfer and 2,300 is used as a stipend into the subcall to seed its gas counter. `AUTHCALL` does not provide a stipend and thus only charges the base 6,700.

### In-Protocol Revocation

This EIP has gone [back and forth](#what-to-sign) on how to deal with `AUTH` message revocation. Without revocation, this EIP is a supremely powerful and flexible primitive for developers. However, it does have risk for users who use insecure and/or actively malicious invokers.

Much of the risk is due to the new ability for users to batch many operations in a single transaction. It becomes easier for an account to be drained. This is a risk that will continue to grow, regardless of the adoption of this EIP, due to overwhelming desire for the feature and attempts to support it at the protocol level and at the app level.

A new class of risk is introduced for insecure and buggy invokers. If an invoker has implemented replay protection, as per the authors&apos; recommendation, this should substantially contain the blast radius. However, if the bug allows an adversary to circumvent the replay protection mechanism, it may give them full access to any EOA which has interacted with the vulnerable invoker.

Although this is a truly catastrophic event which is not expected to be possible via reputable wallets, it is a serious consideration. Without in-protocol revocation, users have no way to remove their account from the vulnerable invoker.

For this reason, `AUTH` requires the `nonce` in the message to be equal to the signer&apos;s current nonce. This way, a single tx from the EOA will cause the nonce to increase, invalidating all outstanding authorizations.

### Failing on `EXTCODESIZE` check

In [EIP-3607](./eip-3607), it was determined that the protocol should reject any transaction which originates from an account with code. Although this EIP focused on transaction origination, the authors of EIP-3074 feel the intention is clear: an account that has both code and a known private key should not be allowed to make arbitrary calls on behalf of said account. Therefore, the property is upheld in this EIP. For full rationale, please refer to [EIP-3607](./eip-3607).

## Backwards Compatibility

Although this EIP poses no issues for backwards compatibility, there are concerns that it limits future changes to accounts by further enshrining ECDSA signatures. For example, it might be desirable to eradicate the concept of EOAs altogether, and replace them with smart contract wallets that emulate the same behavior. This is fully compatible with the EIP as written, however, it gets tricky if users can then elect to &quot;upgrade&quot; their smart contract wallets to use other methods of authentication -- e.g. convert into a multi-sig. Without any changes, `AUTH` would not respect this new logic and continue allowing the old private key to perform actions on behalf of the account.

A solution to this would be at the same time that EOAs are removed, to modify the logic of `AUTH` to actually call into the account with some standard message and allow the account to determine if the signature / witness is valid. Further research should be done to understand how invokers would need to change in this situation and how best to write them in a future-compatible manner.

## Security Considerations

### Secure Invokers

The following is a non-exhaustive list of checks/pitfalls/conditions that invokers *should* be wary of:

 - Replay protection (ex. a nonce) should be implemented by the invoker, and included in `commit`. Without it, a malicious actor can reuse a signature, repeating its effects.
 - `value` should be included in `commit`. Without it, a malicious sponsor could cause unexpected effects in the callee.
 - `gas` should be included in `commit`. Without it, a malicious sponsor could cause the callee to run out of gas and fail, griefing the sponsee.
 - `addr` and `calldata` should be included in `commit`. Without them, a malicious actor may call arbitrary functions in arbitrary contracts.

A poorly implemented invoker can *allow a malicious actor to take near complete control over a signer&apos;s EOA*.

### Allowing `tx.origin` as Signer

Allowing `authorized` to equal `tx.origin` has the possibility to:

 - Break atomic sandwich protections which rely on `tx.origin`;
 - Break reentrancy guards of the style `require(tx.origin == msg.sender)`.

The authors of this EIP believe the risks of allowing `authorized` to equal `tx.origin` are acceptable for the reasons outlined in the Rationale section.

### Sponsored Transaction Relayers

It is possible for the `authorized` account to cause sponsored transaction relayers to spend gas without being reimbursed by either invalidating the authorization (i.e. increasing the account&apos;s nonce) or by sweeping the relevant assets out of the account. Relayers should be designed with these cases in mind, possibly by requiring a bond to be deposited or by implementing a reputation system.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 15 Oct 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3074</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3074</guid>
      </item>
    
      <item>
        <title>Slashing Protection Interchange Format</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3076-validator-client-interchange-format-slashing-protection/4883</comments>
        
        <description>## Abstract

A standard format for transferring a key&apos;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&apos;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.

## Motivation

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.

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.

This can occur if client A and client B do not agree on what the present time is. For example, say client A&apos;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&apos;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.

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.

## Specification

### JSON Schema

A valid interchange file is one that adheres to the following JSON schema, and is interpreted according to the [Conditions](#conditions).

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

### Example JSON Instance

```json
{
  &quot;metadata&quot;: {
    &quot;interchange_format_version&quot;: &quot;5&quot;,
    &quot;genesis_validators_root&quot;: &quot;0x04700007fabc8282644aed6d1c7c9e21d38a03a0c4ba193f3afe428824b3a673&quot;
  },
  &quot;data&quot;: [
    {
      &quot;pubkey&quot;: &quot;0xb845089a1457f811bfc000588fbb4e713669be8ce060ea6be3c6ece09afc3794106c91ca73acda5e5457122d58723bed&quot;,
      &quot;signed_blocks&quot;: [
        {
          &quot;slot&quot;: &quot;81952&quot;,
          &quot;signing_root&quot;: &quot;0x4ff6f743a43f3b4f95350831aeaf0a122a1a392922c45d804280284a69eb850b&quot;
        },
        {
          &quot;slot&quot;: &quot;81951&quot;
        }
      ],
      &quot;signed_attestations&quot;: [
        {
          &quot;source_epoch&quot;: &quot;2290&quot;,
          &quot;target_epoch&quot;: &quot;3007&quot;,
          &quot;signing_root&quot;: &quot;0x587d6a4f59a58fe24f406e0502413e77fe1babddee641fda30034ed37ecc884d&quot;
        },
        {
          &quot;source_epoch&quot;: &quot;2290&quot;,
          &quot;target_epoch&quot;: &quot;3008&quot;
        }
      ]
    }
  ]
}
```

### Conditions

After importing an interchange file with data field `data`, a signer must respect the following conditions:

1. Refuse to sign any block that is slashable with respect to the blocks contained in `data.signed_blocks`. For details of what constitutes a slashable block, see `process_proposer_slashing` (from `consensus-specs`). If the `signing_root` is absent from a block, a signer must assume that any new block with the same `slot` is slashable with respect to the imported block.

2. Refuse to sign any block with `slot &lt;= min(b.slot for b in data.signed_blocks if b.pubkey == proposer_pubkey)`, except if it is a repeat signing as determined by the `signing_root`.

3. Refuse to sign any attestation that is slashable with respect to the attestations contained in `data.signed_attestations`. For details of what constitutes a slashable attestation, see `is_slashable_attestation_data`.

4. Refuse to sign any attestation with source epoch less than the minimum source epoch present in that signer&apos;s attestations (as seen in `data.signed_attestations`). In pseudocode:

```python3
source.epoch &lt;
    min(att.source_epoch
        for att in data.signed_attestations
        if att.pubkey == attester_pubkey)
```

{:start=&quot;5&quot;}
5. Refuse to sign any attestation with target epoch less than or equal to the minimum target epoch present in that signer&apos;s attestations (as seen in `data.signed_attestations`), except if it is a repeat signing as determined by the `signing_root`. In pseudocode:

```python3
target_epoch &lt;=
    min(att.target_epoch
        for att in data.signed_attestations
        if att.pubkey == attester_pubkey)
```

### Additional Information

- The `interchange_format_version` version is set to 5.

- A signed block or attestation&apos;s `signing_root` 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.

- The `signed_blocks` `signing_root`s are calculated using `compute_signing_root(block, domain)`: where `block` is the block (of type `BeaconBlock` or `BeaconBlockHeader`) that was signed, and `domain` is equal to `compute_domain(DOMAIN_BEACON_PROPOSER, fork, metadata.genesis_validators_root)`.

- The `signed_attestations` `signing_root`s are calculated using `compute_signing_root(attestation, domain)`: where `attestation` is the attestation (of type `AttestationData`) that was signed, and `domain` is equal to `compute_domain(DOMAIN_BEACON_ATTESTER, fork, metadata.genesis_validators_root)`.


## Rationale

### Supporting Different Strategies

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:

1. **Complete**: a database containing every message signed by each validator.
2. **Minimal**: a database containing only the latest messages signed by each validator.

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.

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).

The two strategies are unified in the interchange format through the inclusion of [conditions](#conditions) (2), (4) and (5). This allows the interchange to transfer detailed or succinct information, as desired.

### Integer Representation

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 `number` type is a 64-bit float). If a validator is yet to sign a block or attestation, the relevant list is simply left empty.

### Versioning

The `interchange_format_version` is set to 5 because the specification went through several breaking changes during its design, incorporating feedback from implementers.


## Backwards Compatibility

This specification is not backwards-compatible with previous draft versions that used version numbers less than 5.


## Security Considerations

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.

### Advice for Complete Databases

For implementers who use a complete record of signed messages to implement their slashing protection database, we make the following recommendations:

- You MUST ensure that, in addition to importing all of the messages from an interchange, all the [conditions](#conditions) 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, _irrespective_ of whether that minimum-slot block was imported from an interchange file, or inserted as part of your database&apos;s regular operation.
- 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 &quot;null&quot; value which is distinct from all other signing roots, although a value like `0x0` may be used instead (as it is extremely unlikely to collide with any real signing root).
- 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.

### Advice for Minimal Databases

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:

- During import, make sure you take the _maximum_ slot block and _maximum_ source and target attestations for each validator. Although the [conditions](#conditions) 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 `V` at slots 4, 98 and 243, then the latest signed block for validator `V` 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&apos;s existing value should remain unchanged.

### General Recommendations

- 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 _stopped_ -- in other words, when the client or signer is no longer adding new messages to the database.
- Similarly, your implementation should only allow an interchange file to be imported when the validator client is stopped.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>wallet_addEthereumChain RPC Method</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3085-wallet-addethereumchain/5469</comments>
        
        <description>## Abstract

This EIP adds a wallet-namespaced RPC method: `wallet_addEtherereumChain`, providing a standard interface for adding chains to Ethereum wallets.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

This proposal defines a new RPC method, `wallet_addEthereumChain`.

### `wallet_addEthereumChain`

The `wallet_addEthereumChain` method is used to suggest to the wallet that a new chain be added to the wallet&apos;s list of chains. It takes a single parameter and returns `null` if the chain was added successfully, or an error if the chain was not added.

#### `wallet_addEthereumChain` Parameters

The `wallet_addEthereumChain` method takes a single parameter, an `EthereumChainAddRequest` object, which is defined as follows:

```typescript
interface AddEthereumChainParameter {
  chainId: string;
  blockExplorerUrls?: string[];
  chainName?: string;
  iconUrls?: string[];
  nativeCurrency?: {
    name: string;
    symbol: string;
    decimals: number;
  };
  rpcUrls?: string[];
}
```

Only the `chainId` is required per this specification, but a wallet MAY require any other fields listed, impose additional requirements on them, or ignore them outright.

If a field does not meet the requirements of this specification and the wallet does not ignore the field, the wallet MUST reject the request.

The `chainId` is the integer ID of the chain as a hexadecimal string, as per [EIP-155](/EIPs/EIPS/eip-155). The `blockExplorerUrls`, `iconUrls`, and `rpcUrls` fields are arrays of strings, each of which MUST be a valid URL. The `nativeCurrency` field is an object with `name`, `symbol`, and `decimals` fields, where `decimals` is a non-negative integer, and is to be interpreted like in [EIP-20](/EIPs/EIPS/eip-20). The `chainName` field is a string that is the human-readable name of the chain.

The wallet MUST reject the request if the `chainId` is not a valid hexadecimal string, or if the `chainId` is not a valid chain ID.

The wallet MUST reject the request if the `rpcUrls` field is not provided, or if the `rpcUrls` field is an empty array. The wallet MUST reject the request if the `rpcUrls` contains any strings that are not valid URLs. The wallet must reject the request if the `chainId` does not match the value of the `eth_chainId` method for any of the RPC urls.

The wallet MUST reject the request if the `nativeCurrency` field is provided, and any of the `name`, `symbol`, or `decimals` fields are missing. The wallet MUST reject the request if the `decimals` field is a negative integer.

The wallet MUST reject the request if the `blockExplorerUrls` field is provided, and any of the URLs are not valid URLs.

The wallet MUST reject the request if the `iconUrls` field is provided, and any of the URLs are not valid URLs or do not point to a valid image.

The wallet MUST reject any URLs that use the `file:` or `http:` schemes.

#### `wallet_addEthereumChain` Returns

The method MUST return `null` if the request was successful, and an error otherwise. The wallet MAY reject the request for any reason.

The chain MUST NOT be assumed to be automatically selected by the wallet, even if the wallet does not reject the request.

A request to add a chain that was already added SHOULD be successful, unless the user declines the request or the validation fails.

The wallet MUST NOT allow the same `chainId` to be added multiple times. See [Security Considerations](#security-considerations) for more information.

## Rationale

The design of `wallet_addEthereumChain` is deliberately ignorant of what it means to &quot;add&quot; a chain to a wallet.
The meaning of &quot;adding&quot; a chain to a wallet depends on the wallet implementation.

When calling the method, specifying the `chainId` will always be necessary, since in the universe of Ethereum chains, the [EIP-155](/EIPs/EIPS/eip-155) chain ID is effectively the chain GUID.
The remaining parameters amount to what, in the estimation of the authors, a wallet will minimally require in order to effectively support a chain and represent it to the user.
The network ID (per the `net_version` RPC method) is omitted since it is effectively superseded by the chain ID.

For [security reasons](#security-considerations), a wallet should always attempt to validate the chain metadata provided by the requester, and may choose to fetch the metadata elsewhere entirely.
Either way, only the wallet can know which chain metadata it needs from the requester in order to &quot;add&quot; the chain.
Therefore, all parameters except `chainId` are specified as optional, even though a wallet may require them in practice.

This specification does not mandate that the wallet &quot;switches&quot; its &quot;active&quot; or &quot;currently selected&quot; chain after a successful request, if the wallet has a concept thereof.
Just like the meaning of &quot;adding&quot; a chain, &quot;switching&quot; between chains is a wallet implementation detail, and therefore out of scope.

## Security Considerations

`wallet_addEthereumChain` is a powerful method that exposes the end user to serious risks if implemented incorrectly.
Many of these risks can be avoided by validating the request data in the wallet, and clearly disambiguating different chains in the wallet UI.

### Chain IDs

Since the chain ID used for transaction signing determines which chain the transaction is valid for, handling the chain ID correctly is of utmost importance.
The wallet should:

- Ensure that a submitted chain ID is valid.
  - It should be a `0x`-prefixed hexadecimal string per [EIP-695](/EIPs/EIPS/eip-695), and parse to an integer number.
- Prevent the same chain ID from being added multiple times.
  - See the next section for how to handle multiple RPC endpoints.
- Only use the submitted chain ID to sign transactions, **never** a chain ID received from an RPC endpoint.
  - A malicious or faulty endpoint could return arbitrary chain IDs, and potentially cause the user to sign transactions for unintended chains.
- Verify that the specified chain ID matches the return value of `eth_chainId` from the endpoint, as described above.

### RPC Endpoints and RPC URLs

Wallets generally interact with chains via an RPC endpoint, identified by some URL.
Most wallets ship with a set of chains and corresponding trusted RPC endpoints.
The endpoints identified by the `rpcUrls` parameter cannot be assumed to be honest, correct, or even pointing to the same chain.
Moreover, even trusted endpoints can expose users to privacy risks depending on their data collection practices.

Therefore, the wallet should:

- Inform users that their on-chain activity and IP address will be exposed to RPC endpoints.
- If an endpoint is unknown to the wallet, inform users that the endpoint may behave in unexpected ways.
- Observe good web security practices when interacting with the endpoint, such as require HTTPS.
- Clearly inform the user which RPC URL is being used to communicate with a chain at any given moment, and inform the user of the risks of using multiple RPC endpoints to interact with the same chain.

### Validating Chain Data

A wallet that implements `wallet_addEthereumChain` should expect to encounter requests for chains completely unknown to the wallet maintainers.
That said, community resources exist that can be leveraged to verify requests for many Ethereum chains.
The wallet should maintain a list of known chains, and verify requests to add chains against that list.
Indeed, a wallet may even prefer its own chain metadata over anything submitted with a `wallet_addEthereumChain` request.

### UX

Adding a new chain to the wallet can have significant implications for the wallet&apos;s functionality and the experience of the user.
A chain should never be added without the explicit consent of the user, and different chains should be clearly differentiated in the wallet UI.
In service of these goals, the wallet should:

- When receiving a `wallet_addEthereumChain` request, display a confirmation informing the user that a specific requester has requested that the chain be added.
- Ensure that any chain metadata, such as `nativeCurrency` and `blockExplorerUrls`, are validated and used to maximum effect in the UI.
- If any images are provided via `iconUrls`, ensure that the user understands that the icons could misrepresent the actual chain added.
- If the wallet UI has a concept of a &quot;currently selected&quot; or &quot;currently active&quot; chain, ensure that the user understands when a chain added using `wallet_addEthereumChain` becomes selected.

### Preserving User Privacy

Although a request to add a chain that was already added should generally be considered a success, treating such requests as _automatic_ successes leaks information to requesters about the chains a user has added to their wallet.
In the interest of preserving user privacy, implementers of `wallet_addEthereumChain` should consider displaying user confirmations even in these cases.
If the user denies the request, the wallet should return the same user rejection error as normal so that requesters cannot learn which chains are supported by the wallet without explicit permission to do so.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 01 Nov 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3085</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3085</guid>
      </item>
    
      <item>
        <title>Block Explorer API Routes</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3091-block-explorer-api-routes/4907</comments>
        
        <description>## Abstract

This proposal brings standardization between block explorers API routes when linking transactions, blocks, accounts and tokens. 

## Motivation

Currently wallets and dapps link transactions and accounts to block explorer web pages but as chain diversity and layer two solutions grow it becomes harder to maintain a consistent user experience. Adding new chains or layer two solutions becomes harder given these endpoints are inconsistent. Standardizing the API routes to these links improves interoperability between wallets and block explorers.

## Specification

Block explorers will route their webpages accordingly for the following data:

### Blocks

`&lt;BLOCK_EXPLORER_URL&gt;/block/&lt;BLOCK_HASH_OR_HEIGHT&gt;`

### Transactions

`&lt;BLOCK_EXPLORER_URL&gt;/tx/&lt;TX_HASH&gt;`

### Accounts

`&lt;BLOCK_EXPLORER_URL&gt;/address/&lt;ACCOUNT_ADDRESS&gt;`

### Tokens

`&lt;BLOCK_EXPLORER_URL&gt;/token/&lt;TOKEN_ADDRESS&gt;`

## Rationale

The particular paths used in this proposal are chosen to be compatible with the majority of existing block explorers.

## Backwards Compatibility

Incompatible block explorers can use redirects to their existing API routes in order to conform to this EIP.

## Security Considerations

None

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 02 Nov 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3091</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3091</guid>
      </item>
    
      <item>
        <title>Binary trie structure</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethresear.ch/t/binary-trie-format/7621</comments>
        
        <description>## Simple Summary

Change the storage structure from hexary to binary, merge the account and storage tries, and use blake2b.

## Abstract

This proposal presents a binary structure and merkelization rule for the account and storage tries, which are merged into a single “state” trie. RLP and most of the MPT’s optimizations are dropped to simplify the design. Keccak256 is replaced with blake2b.

## Motivation

The current design of the Merkle Patricia Trie (MPT) uses an hexary trie. Hexary Merkle trees are more shallow than their binary counterparts, which means less hashing.
Over the course of the 5 years of Ethereum’s existence, it has become apparent that disk accesses are a greater bottleneck than hashing. Clients are therefore moving away from a storage model in which all internal nodes are stored, in favor of a flat (key, value) storage model first used by turbo-geth, in which the intermediate nodes are recalculated only when needed.

There is a push for making Ethereum easier to use in a stateless fashion. Binary tries make for smaller (~4x) proofs than hexary tries, making it the design of choice for a stateless-friendly Ethereum.

For that same reason, the account and storage tries are merged in order to have a single proof for all changes.

The MPT design is also rife with uncanny optimizations for size, that have a limited effect - at the cost of prohibitive complexity. For example, nesting for children whose RLP is less than 32 bytes saves an estimated 1MB of disk space. A paltry compared to the 300GB required by a fast sync at the time of this writing. These optimizations are a significant source of errors, and therefore a consensus-breaking risk.
The reliance on RLP has also been criticized for its complexity, while the overhead of a general-purpose encoding scheme isn’t warranted for the rigid structure of a Merkle trie.

The desire to switch the storage model from an hexary trie to a binary trie provides an opportunity to adopt a simpler trie architecture that pushes optimizations from the protocol level down to that of the client implementors.

## Specification

### Conventions

| Code      | Description                                      |
| :-:       | -                                                |
| `u256(x)` | Big endian, 32-byte representation of number _x_ |
|`||`          | Byte-wise concatenation operator|
| `++`         | Bit-wise concatenation operator                                                                                                |
| `0b0101`     | The binary string `0101`                                                                                                       |
| `hash()`     | The usual hashing function                                                                                                     |
| `empty_hash` | The empty hash: `hash(&quot;&quot;)`                                                                                                     |
| `length(x)`  | The byte length of object `x`                                                                                                  |
| `d[a..b]`    | The big-endian bit sequence taken from byte sequence `d`, starting at bit index `a`, up to and including the bit at index `b`. |

### Notable changes from the hexary structure

 * Account and storage tries are merged, with key length between 32 and 64 bytes;
 * RLP is no longer used;
 * The &quot;leaf marker&quot; bit used in the hex prefix is also dropped. Leaves are identified as nodes with no children;
 * Serialized nodes are hashed, no matter how small the byte length of the serialized nodes.

### The trie

#### Structure

The trie structure is made up of _nodes_. A node `N ≡ (N_l,N_r,N_p,N_v)` has the following 4 components:

 * `N_l` is the hash to the node&apos;s _left child_. If the node does not have a left child, then `N_l` is the empty hash `empty_hash`;
 * `N_r` is the hash to the node&apos;s _right child_. If the node does not have a right child, then `N_r` is the empty hash `empty_hash`;
 * the optional `N_p` is the node&apos;s _prefix_ : every key into the subtrie rooted at `N` is prefixed by this bit string;
 * `N_v` is the _value_ stored at this node. The value is **only present in leaf nodes**.

Nodes with `empty_hash` as both children are called _leaf nodes_, and the remaining nodes are known as _internal nodes_.

#### Accessing account&apos;s balance, nonce, code, storage root and storage slots

Assuming an account `A ≡ (A_b, A_n, A_c, A_s)` at address `A_a`, the following elements can be found at the following addresses:

 * The account balance `A_b` can be found at key `hash(A_a)[0..253] ++ 0b00` and is of type `uint256`;
 * The account nonce `A_n` can be found at key `hash(A_a)[0..253] ++ 0b01` and is of type `uint64`;
 * The code `A_c` is an arbitrary-length byte sequence that can be found at key `hash(A_a)[0..253] ++ 0b10`;
 * The root of the storage trie `A_s` can be found at key `hash(A_a)[0..253] ++ 0b11`
     * The storage slot number `k` can be found at key `hash(A_a)[0..253] ++ 0b11 ++ hash(k)`.

After [EIP-2926](/EIPs/EIPS/eip-2926) has been rolled out, `A_c` will represent the root of the code merkelization tree. The key accessing code chunk number `c` is `hash(A_a)[0..253] ++ 0b10 ++ u256(c)`.

In the unlikely future case that extra items are to be added to the trie at account level, a third bit can be reserved for future use.

### Node merkelization rule

Leaves and nodes that have no prefix are hashed according to the rule below:

```
internal_hash = hash(left_child_hash || right_child_hash)
leaf_hash = hash(hash(key) || hash(leaf_value))
```

If a prefix is present, the length of the path from the root to the prefixed node is further concatenated with the output of the prefix-less rule, and hashed again:

```
internal_hash_with_prefix = hash(u256(path_length_u256 - 1) || internal_hash)
leaf_hash_with_prefix = hash(u256(path_length_u256 - 1) || leaf_hash)
```

## Rationale

### blake2b

BLAKE2 offers better performance, which is key to compensate for the loss of performance associated to a ~4x increase in the number of nodes.

BLAKE3 offers even better performance. No official golang release exists at the time of the writing of this document. This presents a security risk, and therefore BLAKE2 is considered instead.

### Merging of the account and storage tries

The trend in clients is to store the keys and values in a &quot;flat&quot; database. Having the key of any storage slot prefixed with the address key of the account it belongs to helps grouping all of an account&apos;s data on disk, as well as simplifying the witness structure.

### Prefixes and extension nodes

An alternative proposal has been made, which provides optimal witnesses. The trade-off is that extension nodes must be removed.

```
node_hash = hash(left_child_hash || right_child_hash)
leaf_hash = hash(0 || leaf_value)
```

The removal of extension nodes induces 40x higher hashing costs (on the order of 25ms for a trie with only 1k leaves) and as a result they have been kept.

An attempt to keep extension nodes for witness and not the merkelization rule can be found [here](https://notes.ethereum.org/m5VMkX8FRvi0Q_OOR7TF4A).

Getting rid of complex methods like RLP, the hex prefix and children nesting is already offering great simplification.

### 2x32-byte inputs 

It has been requested to keep each node hash calculation as a function that takes two 256-bit integer as an input and outputs one 256-bit integer. This property is expected to play nice with circuit constructions and is therefore expected to greatly help with future zero-knowledge applications.

### Binary tries

Binary tries have been chosen primarily because they reduce the witness size. In general, in an `N`-element tree with each element having `k` children, the average length of a branch is roughly `32 * (k-1) * log(N) / log(k)` plus a few percent for overhead. 32 is the length of a hash; the `k-1` refers to the fact that a Merkle proof needs to provide all `k-1` sister nodes at each level, and `log(N) / log(k)` is an approximation of the number of levels in the tree (eg. a tree where each node has 5 children, with 625 nodes total, would have depth 4, as `625 = 5**4` and so `log(625) / log(5) = 4`).

For any `N`, the expression is minimized at `k = 2`. Here&apos;s a table of branch lengths for different `k` values assuming `N = 2**24`:

| `k` (children per node) | Branch length (chunks) | Branch length (bytes) |
| - | - | - |
| 2 | 1 * 24 = 24 | 768 |
| 4 | 3 * 12 = 36 | 1152 |
| 8 | 7 * 8 = 56 | 1792 |
| 16 | 15 * 6 = 90 | 2880 |

Actual branch lengths will be slightly larger than this due to uneven distribution and overhead, but the pattern of `k=2` being by far the best remains.

The ethereum tree was originally hexary because this would reduce the number of database reads (eg. 6 instead of 24 in the above example). It is now understood that this reasoning was flawed, because nodes can still &quot;pretend&quot; that a binary tree is a hexary (or even 256-ary) tree at the database layer (eg. see https://ethresear.ch/t/optimizing-sparse-merkle-trees/3751), and thereby get the best-of-both-worlds of having the low proof sizes of the tree being binary from a hash-structure perspective and at the same time a much more efficient representation in the database.

Additionally, binary trees are expected to be widely used in Eth2, so this path improves forward-compatibility and reduces long-run total complexity for the protocol.

### Path length instead of bit prefix

In order to remove the complexity associated with byte manipulation, only the bit-length of the extension is used to merkelize a node with a prefix.

Storing the length of the path from the root node instead of that from the parent node has the nice property that siblings need not be hashed when deleting a leaf.

![Sibling deletion diagram](/EIPs/assets/eip-3102/sibling.svg)

_On the left, a trie with the prefix length, and on the right, a trie with the full path length. Each both have values `10000100` and `10000000`. After deleting `10000100`,the sibling node has to be updated in the left tree, while it need not be in the case on the right._

### Value hashing

Except for the code, all values in the trie are less than 32 bytes. EIP-2926 introduces code chunks, with `CHUNK_SIZE = 32 bytes`. The hashing of the leaf&apos;s value could therefore be saved. The authors of the EIP are however considering a future increase of `CHUNK_SIZE`, making `hash(value)` the future-proof choice.

## Backwards Compatibility

A hard fork is required in order for blocks to have a trie root using a different structure.

## Test Cases

TBD

## Implementation

 * As of [commit 0db87e187dc0bfb96046a47e3d6768c93a2e3331](https://github.com/gballet/multiproof-rs/commit/6d22b1aef9548581826b3c04b3e00d6cc709388c), [multiproof-rs](https://github.com/gballet/multiproof-rs) implements this merkelization rule in the `hash_m5()` function, found in file `src/binary_tree.rs`.
 * An implementation of this structure for go-ethereum is available [in this branch](https://github.com/gballet/go-ethereum/tree/rebased-binary-trie-m5-full-path).

## Security Considerations

Issues could arise when performing the transition. In particular, a heavy conversion process could incentivize clients to wait the transition out. This could lead to a lowered network security at the time of the transition. A transition process has been proposed with [EIP-2584](/EIPs/EIPS/eip-2584).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 01 Sep 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3102</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3102</guid>
      </item>
    
      <item>
        <title>Exclusive Claimable Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/3132</comments>
        
        <description>## Simple Summary

This standard defines a token which can be claimed only by token issuer with payer&apos;s signature.

## Abstract

This EIP defines a set of additions to the default token standard such as ERC-20, that allows online/offline service providers establish micropayment channels with any number of users by signing and verifying messages about the consumption of token off chain. Using this mechanism will reduce interactions with blockchain to minimal for both participants, thus saving gas and improve performance.

## Motivation

There are two main purposes of this EIP, one is to reduce interactions with blockchain, the second is to link Ethereum to real-world payment problems.

Many small businesses want to build payment system based on blockchain but find it difficult. There are basically two ways: 

1. Directly pay with token. There are many wallet can receive and transfer token but transactions on Ethereum cost gas and take time to confirm.
2. User lock token on payment smart contract and service provider use payment messages signed by user to release token, establishing a micropayment channel. The advantage is interactions with blockchain is reduced and the signing/verifying process is off-chain. But interact with payment contract needs service provider to build a DApp, which require resources many small businesses do not have. Even if they managed to build DApps, they are all different, not standardized. Also, user should have a wallet with DApp browser and has to learn how to use it.

This EIP helps to standardize the interactions of micropayment system, and make it possible for wallet build a universal UI in the future.

## Specification

```solidity

/// @return Image url of this token or descriptive resources
function iconUrl() external view returns (string memory);

/// @return Issuer of this token. Only issuer can execute claim function
function issuer() external view returns (address);

/**
 *  @notice   Remove consumption from payer&apos;s deposite
 *  @dev      Check if msg.sender == issuer
 *  @param    from          Payer&apos;s address
 *  @param    consumption   How many token is consumed in this epoch, specified
 *  @param    epoch         Epoch increased by 1 after claim or withdraw, at the beginning of each epoch, consumption goes back to 0
 *  @param    signature     Signature of payment message signed by payer
*/
function claim(address from, uint256 consumption, uint256 epoch, bytes calldata signature) external;

function transferIssuer(address newIssuer) external;

/// @notice   Move amount from payer&apos;s token balance to deposite balance to ensure payment is sufficient
function deposit(uint256 amount) external;

/**
 *  @notice   Give remaining deposite balance back to &quot;to&quot; account, act as &quot;refund&quot; function
 *  @dev      In prepayment module, withdraw is executed from issuer account
 *            In lock-release module, withdraw is executed from user account
 *  @param    to            the account receiving remaining deposite
 *  @param    amount        how many token is returned
*/
function withdraw(address to, uint256 amount) external;

function depositBalanceOf(address user) external view returns(uint256 depositBalance, uint256 epoch);

event Deposit(
    address indexed from,
    uint256 amount
);

event Withdraw(
    address indexed to,
    uint256 amount
);
    
event TransferIssuer(
    address indexed oldIssuer,
    address indexed newIssuer
);

event Claim(
    address indexed from,
    address indexed to,
    uint256 epoch,
    uint256 consumption
);

```

### signature

the pseudo code generating an ECDSA signature:
```
sign(keccak256(abi_encode(
    &quot;\x19Ethereum Signed Message:\n32&quot;, 
        keccak256(abi_encode(
            token_address,
            payer_address,
            token_issuer,
            token_consumption,        //calculated by user client
            epoch
        ))
    ))
,private_key)

```

### verification process

the verification contains check about both signature and token_consumption

the pseudo code run by verification server is as follows:

```

serving_loop:

    for {
        /**
         * unpaied_consumption is calculated by provider
         * signed_consumption is claimable amount
         * tolerance allows payer &quot;owes&quot; provider to a certain degree
        */
        //getSignedConsumption returns amount that are already claimable 
        if(unpaied_consumption &lt;  signed_consumption + tolerance){
            informUser(&quot;user need charge&quot;, unpaied_consumption)
            interruptService() 
        }else{
            isServing() || recoverService()
        }
    }

verification_loop:

    for {
        message = incomingMessage()
        if(recover_signer(message, signature) != payer_address){
            informUser(&quot;check signature failed&quot;, hash(message))
            continue
        }

        /**
        * optional: when using echo server to sync messages between verification servers
        * more info about this in Security Considerations section
        */
        if(query(message) != message){
            informUser(&quot;message outdate&quot;, hash(message))
            continue   
        }

        if(epoch != message.epoch || message.consumption &gt; getDepositBalance()){
            informUser(&quot;invalid message&quot;, epoch, unpaied_consumption)
            continue
        }
       
        signed_consumption = message.consumption
        save(message)
    }
    
claim_process:

    if(claim()){
        unpaied_consumption -= signed_consumption
        signed_consumption = 0
        epoch+=1
    }

```
### About withdraw

The withdraw function is slightly different based on business models

1. prepayment model

In prepayment business model such as using token as recharge card of general store, the user pays (crypto)currency to store in advance for claimable token as recharge card (with bonus or discount). When checking out, the customer signs a message with updated consumption (old consumption + consumption this time) to store and store verifies this message off chain. The shopping process loops without any blockchain involved, until the customer wants to return the card and get money back. Because the store already holds all currency, the withdraw function should be executed by token issuer (store) to return remaining deposit balance after claim. The prepayment model can easily be built into a wallet with QR-code scanning function.

2. lock-release model

If we run a paid end-to-end encrypted e-mail service that accepts token as payment, we can use lock-release model. Unlike prepayment, we charge X * N token for an e-mail sent to N recipients. In this &quot;pay for usage&quot; scenario, the counting of services happens on both client and server side. The client should not trust charge amount given by server in case the it&apos;s malfunctioning or malicious. When client decide not to trust server, it stops signing messages, but some of token is taken hostage in deposit balance. To fix this problem, the withdraw function should be executed by payer account with limitation such as epoch didn&apos;t change in a month.

## Rationale

This EIP targets on ERC-20 tokens due to its widespread adoption. However, this extension is designed to be compatible with other token standard.

The reason we chose to implement those functions in token contract rather than a separate record contract is as follows:
- Token can transfer is more convenient and more general than interact with DApp
- Token is more standardized and has better UI support
- Token is equal to service, make token economy more prosperous
- Remove the approve process

## Backwards Compatibility

This EIP is fully backwards compatible as its implementation extends the functionality of [ERC-20](/EIPs/EIPS/eip-20).

## Implementation

```solidity

mapping (address =&gt; StampBalance) private _depositBalance;
    
struct StampBalance{
    uint256 balance;
    uint256 epoch;
}
    
function deposit(uint256 value) override external{
    require(value &lt;= _balances[msg.sender]);
    _balances[msg.sender] = _balances[msg.sender].sub(value);
    _depositBalance[msg.sender].balance = _depositBalance[msg.sender].balance.add(value);
    emit Deposit(msg.sender, value);
}

function withdraw(address to, uint256 value) override onlyIssuer external{
    require(value &lt;= _depositBalance[to].balance);
    _depositBalance[to].balance = _depositBalance[to].balance.sub(value);
    _depositBalance[to].epoch += 1;
    _balances[to] = _balances[to].add(value);
    emit Withdraw(to, value);
}
    
function depositBalanceOf(address user) override public view returns(uint256 depositBalance, uint256 epoch){
    return (_depositBalance[user].balance, _depositBalance[user].epoch);
}

// prepayment model
function claim(address from, uint credit, uint epoch, bytes memory signature) override onlyIssuer external{
    require(credit &gt; 0);
    require(_depositBalance[from].epoch + 1 == epoch);
    require(_depositBalance[from].balance &gt;= credit);
    bytes32 message = keccak256(abi.encode(this, from, _issuer, credit, epoch));
    bytes32 msgHash = prefixed(message);
    require(recoverSigner(msgHash, signature) == from);
    _depositBalance[from].balance = _depositBalance[from].balance.sub(credit);
    _balances[_issuer] = _balances[_issuer].add(credit);
    _depositBalance[from].epoch += 1;
    emit Claim(from, msg.sender, credit, epoch);
}

function prefixed(bytes32 hash) internal pure returns (bytes32) {
    return keccak256(abi.encode(&quot;\x19Ethereum Signed Message:\n32&quot;, hash));
}

function recoverSigner(bytes32 message, bytes memory sig) internal pure  returns (address) {
    (uint8 v, bytes32 r, bytes32 s) = splitSignature(sig);
    return ecrecover(message, v, r, s);
}

function splitSignature(bytes memory sig) internal pure returns (uint8 v, bytes32 r, bytes32 s) {
    require(sig.length == 65);
    assembly {
        r := mload(add(sig, 32))
        s := mload(add(sig, 64))
        v := byte(0, mload(add(sig, 96)))
    }
    return (v, r, s);
}

```

## Security Considerations

By restricting claim function to issuer, there is no race condition on chain layer. However double spending problem may occur when the issuer use multiple verifiers and payer signs many payment messages simultaneously. Some of those messages may get chance to be checked valid though only the message with the largest consumption can be claimed. This problem can be fixed by introducing an echo server which accepts messages from verifiers, returns the message sequentially with largest consumption and biggest epoch number. If a verifier gets an answer different from the message he send, it updates the message from echo server as the last message it receives along with local storage of the status about this payer. Then the verifier asks the payer again for a new message.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).</description>
        <pubDate>Mon, 10 Aug 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3135</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3135</guid>
      </item>
    
      <item>
        <title>Increase block rewards to 5 ETH</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3143-increase-block-rewards-to-5-eth/5061</comments>
        
        <description>## Simple Summary
Changes the block reward paid to proof-of-work (POW) miners to 5 ETH.

## Abstract
Starting with `FORK_BLKNUM` block rewards will be increased to a base of 5 ETH, uncle and nephew rewards will be adjusted accordingly.

## Motivation
Currently, the transaction fees (tx fees) portion of the mining rewards makes up a significant portion of the total rewards per block, at times almost exceeded the block reward of 2 ETH. This have resulted in situations where at times of low tx fees, POW miners decide to point their rigs away from ETH as they will always prefer to mine coins that are the most profitable at any point in time, reducing the security of the ETH network till transaction activity picks up again. By increasing the block rewards back to the original 5 ETH when the network first started, the voliatility will be reduced in terms of the percentage of tx fees that make up the mining rewards per block while increasing the total rewards per block, making it more financially attractive to POW miners to mine ETH barring any gigantic ETH price drops. The increase in block rewards will also allow smaller POW miners ample opporturnity to build up their stores of ETH so that when the time comes to fully transition to ETH 2.0, they may be more willing to become validators as they already have earned the requite amount of ETH needed to do so as opposed to having to spend tens of thousands of dollars to purchase the required ETH directly, increasing the number of validators in the network and therefore strengthening network security.

Therefore, the ultimate end goal for this EIP is to give POW miners more incentive to switch to POS once ETH 2.0 is fully implemented since the transition will take a few years to complete and during that time, they will be incentivised to hold on to the tokens instead of selling it straight away in order to prepare to be a validator for ETH 2.0, reducing the selling pressure on ETH and increasing it&apos;s value in the long run. A side effect of miners staying on Ethereum is that network security will be assured during the transition period.

## Specification
#### Adjust Block, Uncle, and Nephew rewards
Adjust the block reward to `new_block_reward`, where

    new_block_reward = 5_000_000_000_000_000_000 if block.number &gt;= FORK_BLKNUM else block.reward

(5E18 wei, or 5,000,000,000,000,000,000 wei, or 5 ETH).

Analogue, if an uncle is included in a block for `block.number &gt;= FORK_BLKNUM` such that `block.number - uncle.number = k`, the uncle reward is

    new_uncle_reward = (8 - k) * new_block_reward / 8

This is the existing formula for uncle rewards, simply adjusted with `new_block_reward`.

The nephew reward for `block.number &gt;= FORK_BLKNUM` is

    new_nephew_reward = new_block_reward / 32

This is the existing formula for nephew rewards, simply adjusted with `new_block_reward`.

## Rationale
A 5 ETH base reward was chosen as a middle ground between wanting to prevent too high of an inflation rate (10.4% per annum for the first year at 5 ETH per block) and converting as many POW miners as possible into POS validators by making it easier to amass the required ETH needed through POW mining.

## Backwards Compatibility
There are no known backward compatibility issues with the introduction of this EIP.

## Security Considerations
There are no known security issues presented by this change.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 01 Dec 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3143</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3143</guid>
      </item>
    
      <item>
        <title>EVM trace specification</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3155-create-evm-trace-specification/5007</comments>
        
        <description>## Abstract

Introduce a new JSON standard for EVM traces during execution of state tests.

## Motivation

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.

This EIP has multiple goals:

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

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.

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.

## Specification

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&apos;s
`evm` binary for code examples.

### Datatypes

| Type       | Explanation                                                    | Example             |
|------------|----------------------------------------------------------------|---------------------|
| Number     | Plain json number                                              | &quot;pc&quot;:0              |
| Hex-Number | Hex-encoded number                                             | &quot;gas&quot;:&quot;0x2540be400&quot; |
| String     | Plain string                                                   | &quot;opName&quot;:&quot;PUSH1&quot;    |
| Hex-String | Hex-encoded string                                             |                     |
| Array of x | Array of x encoded values                                      |                     |
| Key-Value  | Key-Value structure with key and values encoded as hex strings |                     |
| Boolean    | Json bool can either be true or false                          | &quot;pass&quot;: true        |

### Output

The CUT MUST output a `json` object for EACH operation.

#### Required Fields

| Name         | Type                 | Explanation                              |
|--------------|----------------------|------------------------------------------|
| `pc`         | Number               | Program Counter                          |
| `op`         | Number               | OpCode                                   |
| `gas`        | Hex-Number           | Gas left before executing this operation |
| `gasCost`    | Hex-Number           | Gas cost of this operation               |
| `memSize`    | Number               | Size of memory array                     |
| `stack`      | Array of Hex-Numbers | Array of all values on the stack         |
| `depth`      | Number               | Depth of the call stack                  |
| `returnData` | Hex-String           | Data returned by function call           |
| `refund`     | Hex-Number           | Amount of **global** gas refunded        |

#### Optional Fields

| Name          | Type                 | Explanation                                                         |
|---------------|----------------------|---------------------------------------------------------------------|
| `opName`      | String               | Name of the operation                                               |
| `error`       | Hex-String           | Description of an error (should contain revert reason if supported) |
| `memory`      | Array of Hex-Strings | Array of all allocated values                                       |
| `storage`     | Key-Value            | Array of all stored values                                          |

*Example:*

```
{&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;}
```

- The `stack`, `memory` and `memSize` are the values *before* execution of the op.
- All array attributes (`stack`, `memory`) MUST be initialized to empty arrays (`&quot;stack&quot;:[]`) NOT to null.
- If the CUT will not be outputting values for `memory` or `storage` then the `memory` and `storage` 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.
- The `memSize` field MUST be present regardless of `memory` support.
- Clients SHOULD implement a way to disable recording the storage as the stateroot includes all storage updates.
- Clients SHOULD output the fields in the same order as listed in this EIP.

The CUT MUST NOT output a line for the `STOP` operation if an error occurred:
  
*Example:*

```
{&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;}
```

### Summary and Error Handling

At the end of execution, the CUT MUST print summary info; this info SHOULD have the following fields.
The summary should be a single `jsonl` object.

#### Required Fields

| Name        | Type       | Explanation                                            |
|-------------|------------|--------------------------------------------------------|
| `stateRoot` | Hex-String | Root of the state trie after executing the transaction |
| `output`    |            | Return values of the function                          |
| `gasUsed`   | Hex-Number | All gas used by the transaction                        |
| `pass`      | Boolean    | Bool whether transaction was executed successfully     |

#### Optional Fields

| Name   | Type   | Explanation                                           |
|--------|--------|-------------------------------------------------------|
| `time` | Number | Time in nanoseconds needed to execute the transaction |
| `fork` | String | Name of the fork rules used for execution             |

*Example*:

```
{&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}
```

## Rationale

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.

## Backwards Compatibility

This EIP is fully backward compatible with ethereum as it only introduces a better tracing infrastructure that is optional for clients to implement.

### Clients

This EIP is fully backward compatible with go-ethereum. OpenEthereum, Besu and Nethermind clients would have to change their JSON output of
`openethereum-evm` `evmtool` and
`nethtest` 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.

## Test Cases

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

## Security Considerations

Tracing is expensive.

Exposing an endpoint for creating traces publicly could open up a denial of service vector.

Clients should consider putting trace endpoints behind a separate flag from other endpoints.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Flash Loans</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-3156-flash-loans-review-discussion/5077</comments>
        
        <description>## Simple Summary

This ERC provides standard interfaces and processes for single-asset flash loans.

## Abstract

A flash loan is a smart contract transaction in which a lender smart contract lends assets to a borrower smart contract with the condition that the assets are returned, plus an optional fee, before the end of the transaction. This ERC specifies interfaces for lenders to accept flash loan requests, and for borrowers to take temporary control of the transaction within the lender execution. The process for the safe execution of flash loans is also specified.

## Motivation

Flash loans allow smart contracts to lend an amount of tokens without a requirement for collateral, with the condition that they must be returned within the same transaction.

Early adopters of the flash loan pattern have produced different interfaces and different use patterns. The diversification is expected to intensify, and with it the technical debt required to integrate with diverse flash lending patterns.

Some of the high level differences in the approaches across the protocols include:
- Repayment approaches at the end of the transaction, where some pull the principal plus the fee from the loan receiver, and others where the loan receiver needs to manually return the principal and the fee to the lender.
- Some lenders offer the ability to repay the loan using a token that is different to what was originally borrowed, which can reduce the overall complexity of the flash transaction and gas fees.
- Some lenders offer a single entry point into the protocol regardless of whether you&apos;re buying, selling, depositing or chaining them together as a flash loan, whereas other protocols offer discrete entry points.
- Some lenders allow to flash mint any amount of their native token without charging a fee, effectively allowing flash loans bounded by computational constraints instead of asset ownership constraints.

## Specification

A flash lending feature integrates two smart contracts using a callback pattern. These are called the LENDER and the RECEIVER in this EIP.

### Lender Specification

A `lender` MUST implement the IERC3156FlashLender interface.
```
pragma solidity ^0.7.0 || ^0.8.0;
import &quot;./IERC3156FlashBorrower.sol&quot;;


interface IERC3156FlashLender {

    /**
     * @dev The amount of currency available to be lent.
     * @param token The loan currency.
     * @return The amount of `token` that can be borrowed.
     */
    function maxFlashLoan(
        address token
    ) external view returns (uint256);

    /**
     * @dev The fee to be charged for a given loan.
     * @param token The loan currency.
     * @param amount The amount of tokens lent.
     * @return The amount of `token` to be charged for the loan, on top of the returned principal.
     */
    function flashFee(
        address token,
        uint256 amount
    ) external view returns (uint256);

    /**
     * @dev Initiate a flash loan.
     * @param receiver The receiver of the tokens in the loan, and the receiver of the callback.
     * @param token The loan currency.
     * @param amount The amount of tokens lent.
     * @param data Arbitrary data structure, intended to contain user-defined parameters.
     */
    function flashLoan(
        IERC3156FlashBorrower receiver,
        address token,
        uint256 amount,
        bytes calldata data
    ) external returns (bool);
}
```

The `maxFlashLoan` function MUST return the maximum loan possible for `token`. If a `token` is not currently supported `maxFlashLoan` MUST return 0, instead of reverting.

The `flashFee` function MUST return the fee charged for a loan of `amount` `token`. If the token is not supported `flashFee` MUST revert.

The `flashLoan` function MUST include a callback to the `onFlashLoan` function in a `IERC3156FlashBorrower` contract.

```
function flashLoan(
    IERC3156FlashBorrower receiver,
    address token,
    uint256 amount,
    bytes calldata data
) external returns (bool) {
  ...
  require(
      receiver.onFlashLoan(msg.sender, token, amount, fee, data) == keccak256(&quot;ERC3156FlashBorrower.onFlashLoan&quot;),
      &quot;IERC3156: Callback failed&quot;
  );
  ...
}
```

The `flashLoan` function MUST transfer `amount` of `token` to `receiver` before the callback to the receiver.

The `flashLoan` function MUST include `msg.sender` as the `initiator` to `onFlashLoan`.

The `flashLoan` function MUST NOT modify the `token`, `amount` and `data` parameter received, and MUST pass them on to `onFlashLoan`.

The `flashLoan` function MUST include a `fee` argument to `onFlashLoan` with the fee to pay for the loan on top of the principal, ensuring that `fee == flashFee(token, amount)`.

The `lender` MUST verify that the `onFlashLoan` callback returns the keccak256 hash of &quot;ERC3156FlashBorrower.onFlashLoan&quot;.

After the callback, the `flashLoan` function MUST take the `amount + fee` `token` from the `receiver`, or revert if this is not successful.

If successful, `flashLoan` MUST return `true`.

### Receiver Specification

A `receiver` of flash loans MUST implement the IERC3156FlashBorrower interface:

```
pragma solidity ^0.7.0 || ^0.8.0;


interface IERC3156FlashBorrower {

    /**
     * @dev Receive a flash loan.
     * @param initiator The initiator of the loan.
     * @param token The loan currency.
     * @param amount The amount of tokens lent.
     * @param fee The additional amount of tokens to repay.
     * @param data Arbitrary data structure, intended to contain user-defined parameters.
     * @return The keccak256 hash of &quot;ERC3156FlashBorrower.onFlashLoan&quot;
     */
    function onFlashLoan(
        address initiator,
        address token,
        uint256 amount,
        uint256 fee,
        bytes calldata data
    ) external returns (bytes32);
}
```

For the transaction to not revert, `receiver` MUST approve `amount + fee` of `token` to be taken by `msg.sender` before the end of `onFlashLoan`.

If successful, `onFlashLoan` MUST return the keccak256 hash of &quot;ERC3156FlashBorrower.onFlashLoan&quot;.

## Rationale

The interfaces described in this ERC have been chosen as to cover the known flash lending use cases, while allowing for safe and gas efficient implementations.

`flashFee` reverts on unsupported tokens, because returning a numerical value would be incorrect.

`flashLoan` has been chosen as a function name as descriptive enough, unlikely to clash with other functions in the lender, and including both the use cases in which the tokens lent are held or minted by the lender.

`receiver` is taken as a parameter to allow flexibility on the implementation of separate loan initiators and receivers.

Existing flash lenders all provide flash loans of several token types from the same contract. Providing a `token` parameter in both the `flashLoan` and `onFlashLoan` functions matches closely the observed functionality.

A `bytes calldata data` parameter is included for the caller to pass arbitrary information to the `receiver`, without impacting the utility of the `flashLoan` standard.

`onFlashLoan` has been chosen as a function name as descriptive enough, unlikely to clash with other functions in the `receiver`, and following the `onAction` naming pattern used as well in EIP-667.

A `initiator` will often be required in the `onFlashLoan` function, which the lender knows as `msg.sender`. An alternative implementation which would embed the `initiator` in the `data` parameter by the caller would require an additional mechanism for the receiver to verify its accuracy, and is not advisable.

The `amount` will be required in the `onFlashLoan` function, which the lender took as a parameter. An alternative implementation which would embed the `amount` in the `data` parameter by the caller would require an additional mechanism for the receiver to verify its accuracy, and is not advisable.

A `fee` will often be calculated in the `flashLoan` function, which the `receiver` must be aware of for repayment. Passing the `fee` as a parameter instead of appended to `data` is simple and effective.

The `amount + fee` are pulled from the `receiver` to allow the `lender` to implement other features that depend on using `transferFrom`, without having to lock them for the duration of a flash loan. An alternative implementation where the repayment is transferred to the `lender` is also possible, but would need all other features in the lender to be also based in using `transfer` instead of `transferFrom`. Given the lower complexity and prevalence of a &quot;pull&quot; architecture over a &quot;push&quot; architecture, &quot;pull&quot; was chosen.

## Backwards Compatibility

No backwards compatibility issues identified.

## Implementation

### Flash Borrower Reference Implementation

```
pragma solidity ^0.8.0;

import &quot;./interfaces/IERC20.sol&quot;;
import &quot;./interfaces/IERC3156FlashBorrower.sol&quot;;
import &quot;./interfaces/IERC3156FlashLender.sol&quot;;


contract FlashBorrower is IERC3156FlashBorrower {
    enum Action {NORMAL, OTHER}

    IERC3156FlashLender lender;

    constructor (
        IERC3156FlashLender lender_
    ) {
        lender = lender_;
    }

    /// @dev ERC-3156 Flash loan callback
    function onFlashLoan(
        address initiator,
        address token,
        uint256 amount,
        uint256 fee,
        bytes calldata data
    ) external override returns(bytes32) {
        require(
            msg.sender == address(lender),
            &quot;FlashBorrower: Untrusted lender&quot;
        );
        require(
            initiator == address(this),
            &quot;FlashBorrower: Untrusted loan initiator&quot;
        );
        (Action action) = abi.decode(data, (Action));
        if (action == Action.NORMAL) {
            // do one thing
        } else if (action == Action.OTHER) {
            // do another
        }
        return keccak256(&quot;ERC3156FlashBorrower.onFlashLoan&quot;);
    }

    /// @dev Initiate a flash loan
    function flashBorrow(
        address token,
        uint256 amount
    ) public {
        bytes memory data = abi.encode(Action.NORMAL);
        uint256 _allowance = IERC20(token).allowance(address(this), address(lender));
        uint256 _fee = lender.flashFee(token, amount);
        uint256 _repayment = amount + _fee;
        IERC20(token).approve(address(lender), _allowance + _repayment);
        lender.flashLoan(this, token, amount, data);
    }
}
```

### Flash Mint Reference Implementation

```
pragma solidity ^0.8.0;

import &quot;../ERC20.sol&quot;;
import &quot;../interfaces/IERC20.sol&quot;;
import &quot;../interfaces/IERC3156FlashBorrower.sol&quot;;
import &quot;../interfaces/IERC3156FlashLender.sol&quot;;


/**
 * @author Alberto Cuesta Cañada
 * @dev Extension of {ERC20} that allows flash minting.
 */
contract FlashMinter is ERC20, IERC3156FlashLender {

    bytes32 public constant CALLBACK_SUCCESS = keccak256(&quot;ERC3156FlashBorrower.onFlashLoan&quot;);
    uint256 public fee; //  1 == 0.01 %.

    /**
     * @param fee_ The percentage of the loan `amount` that needs to be repaid, in addition to `amount`.
     */
    constructor (
        string memory name,
        string memory symbol,
        uint256 fee_
    ) ERC20(name, symbol) {
        fee = fee_;
    }

    /**
     * @dev The amount of currency available to be lent.
     * @param token The loan currency.
     * @return The amount of `token` that can be borrowed.
     */
    function maxFlashLoan(
        address token
    ) external view override returns (uint256) {
        return type(uint256).max - totalSupply();
    }

    /**
     * @dev The fee to be charged for a given loan.
     * @param token The loan currency. Must match the address of this contract.
     * @param amount The amount of tokens lent.
     * @return The amount of `token` to be charged for the loan, on top of the returned principal.
     */
    function flashFee(
        address token,
        uint256 amount
    ) external view override returns (uint256) {
        require(
            token == address(this),
            &quot;FlashMinter: Unsupported currency&quot;
        );
        return _flashFee(token, amount);
    }

    /**
     * @dev Loan `amount` tokens to `receiver`, and takes it back plus a `flashFee` after the ERC3156 callback.
     * @param receiver The contract receiving the tokens, needs to implement the `onFlashLoan(address user, uint256 amount, uint256 fee, bytes calldata)` interface.
     * @param token The loan currency. Must match the address of this contract.
     * @param amount The amount of tokens lent.
     * @param data A data parameter to be passed on to the `receiver` for any custom use.
     */
    function flashLoan(
        IERC3156FlashBorrower receiver,
        address token,
        uint256 amount,
        bytes calldata data
    ) external override returns (bool){
        require(
            token == address(this),
            &quot;FlashMinter: Unsupported currency&quot;
        );
        uint256 fee = _flashFee(token, amount);
        _mint(address(receiver), amount);
        require(
            receiver.onFlashLoan(msg.sender, token, amount, fee, data) == CALLBACK_SUCCESS,
            &quot;FlashMinter: Callback failed&quot;
        );
        uint256 _allowance = allowance(address(receiver), address(this));
        require(
            _allowance &gt;= (amount + fee),
            &quot;FlashMinter: Repay not approved&quot;
        );
        _approve(address(receiver), address(this), _allowance - (amount + fee));
        _burn(address(receiver), amount + fee);
        return true;
    }

    /**
     * @dev The fee to be charged for a given loan. Internal function with no checks.
     * @param token The loan currency.
     * @param amount The amount of tokens lent.
     * @return The amount of `token` to be charged for the loan, on top of the returned principal.
     */
    function _flashFee(
        address token,
        uint256 amount
    ) internal view returns (uint256) {
        return amount * fee / 10000;
    }
}
```

### Flash Loan Reference Implementation

```
pragma solidity ^0.8.0;

import &quot;../interfaces/IERC20.sol&quot;;
import &quot;../interfaces/IERC3156FlashBorrower.sol&quot;;
import &quot;../interfaces/IERC3156FlashLender.sol&quot;;


/**
 * @author Alberto Cuesta Cañada
 * @dev Extension of {ERC20} that allows flash lending.
 */
contract FlashLender is IERC3156FlashLender {

    bytes32 public constant CALLBACK_SUCCESS = keccak256(&quot;ERC3156FlashBorrower.onFlashLoan&quot;);
    mapping(address =&gt; bool) public supportedTokens;
    uint256 public fee; //  1 == 0.01 %.


    /**
     * @param supportedTokens_ Token contracts supported for flash lending.
     * @param fee_ The percentage of the loan `amount` that needs to be repaid, in addition to `amount`.
     */
    constructor(
        address[] memory supportedTokens_,
        uint256 fee_
    ) {
        for (uint256 i = 0; i &lt; supportedTokens_.length; i++) {
            supportedTokens[supportedTokens_[i]] = true;
        }
        fee = fee_;
    }

    /**
     * @dev Loan `amount` tokens to `receiver`, and takes it back plus a `flashFee` after the callback.
     * @param receiver The contract receiving the tokens, needs to implement the `onFlashLoan(address user, uint256 amount, uint256 fee, bytes calldata)` interface.
     * @param token The loan currency.
     * @param amount The amount of tokens lent.
     * @param data A data parameter to be passed on to the `receiver` for any custom use.
     */
    function flashLoan(
        IERC3156FlashBorrower receiver,
        address token,
        uint256 amount,
        bytes calldata data
    ) external override returns(bool) {
        require(
            supportedTokens[token],
            &quot;FlashLender: Unsupported currency&quot;
        );
        uint256 fee = _flashFee(token, amount);
        require(
            IERC20(token).transfer(address(receiver), amount),
            &quot;FlashLender: Transfer failed&quot;
        );
        require(
            receiver.onFlashLoan(msg.sender, token, amount, fee, data) == CALLBACK_SUCCESS,
            &quot;FlashLender: Callback failed&quot;
        );
        require(
            IERC20(token).transferFrom(address(receiver), address(this), amount + fee),
            &quot;FlashLender: Repay failed&quot;
        );
        return true;
    }

    /**
     * @dev The fee to be charged for a given loan.
     * @param token The loan currency.
     * @param amount The amount of tokens lent.
     * @return The amount of `token` to be charged for the loan, on top of the returned principal.
     */
    function flashFee(
        address token,
        uint256 amount
    ) external view override returns (uint256) {
        require(
            supportedTokens[token],
            &quot;FlashLender: Unsupported currency&quot;
        );
        return _flashFee(token, amount);
    }

    /**
     * @dev The fee to be charged for a given loan. Internal function with no checks.
     * @param token The loan currency.
     * @param amount The amount of tokens lent.
     * @return The amount of `token` to be charged for the loan, on top of the returned principal.
     */
    function _flashFee(
        address token,
        uint256 amount
    ) internal view returns (uint256) {
        return amount * fee / 10000;
    }

    /**
     * @dev The amount of currency available to be lent.
     * @param token The loan currency.
     * @return The amount of `token` that can be borrowed.
     */
    function maxFlashLoan(
        address token
    ) external view override returns (uint256) {
        return supportedTokens[token] ? IERC20(token).balanceOf(address(this)) : 0;
    }
}

```

## Security Considerations


### Verification of callback arguments

The arguments of `onFlashLoan` are expected to reflect the conditions of the flash loan, but cannot be trusted unconditionally. They can be divided in two groups, that require different checks before they can be trusted to be genuine.

0. No arguments can be assumed to be genuine without some kind of verification. `initiator`, `token` and `amount` refer to a past transaction that might not have happened if the caller of `onFlashLoan` decides to lie. `fee` might be false or calculated incorrectly. `data` might have been manipulated by the caller.
1. To trust that the value of `initiator`, `token`, `amount` and `fee` are genuine a reasonable pattern is to verify that the `onFlashLoan` caller is in a whitelist of verified flash lenders. Since often the caller of `flashLoan` will also be receiving the `onFlashLoan` callback this will be trivial. In all other cases flash lenders will need to be approved if the arguments in `onFlashLoan` are to be trusted.
2. To trust that the value of `data` is genuine, in addition to the check in point 1, it is recommended to verify that the `initiator` belongs to a group of trusted addresses. Trusting the `lender` and the `initiator` is enough to trust that the contents of `data` are genuine.

### Flash lending security considerations

#### Automatic approvals
The safest approach is to implement an approval for `amount+fee` before the `flashLoan` is executed.    

Any `receiver` that keeps an approval for a given `lender` needs to include in `onFlashLoan` a mechanism to verify that the initiator is trusted.

Any `receiver` that includes in `onFlashLoan` the approval for the `lender` to take the `amount + fee` needs to be combined with a mechanism to verify that the initiator is trusted.

If an unsuspecting contract with a non-reverting fallback function, or an EOA, would approve a `lender` implementing ERC3156, and not immediately use the approval, and if the `lender` would not verify the return value of `onFlashLoan`, then the unsuspecting contract or EOA could be drained of funds up to their allowance or balance limit. This would be executed by an `initiator` calling `flashLoan` on the victim. The flash loan would be executed and repaid, plus any fees, which would be accumulated by the `lender`. For this reason, it is important that the `lender` implements the specification in full and reverts if `onFlashLoan` doesn&apos;t return the keccak256 hash for &quot;ERC3156FlashBorrower.onFlashLoan&quot;.

### Flash minting external security considerations

The typical quantum of tokens involved in flash mint transactions will give rise to new innovative attack vectors.

#### Example 1 - interest rate attack
If there exists a lending protocol that offers stable interests rates, but it does not have floor/ceiling rate limits and it does not rebalance the fixed rate based on flash-induced liquidity changes, then it could be susceptible to the following scenario:

FreeLoanAttack.sol
1. Flash mint 1 quintillion STAB
2. Deposit the 1 quintillion STAB + $1.5 million worth of ETH collateral
3. The quantum of your total deposit now pushes the stable interest rate down to 0.00001% stable interest rate
4. Borrow 1 million STAB on 0.00001% stable interest rate based on the 1.5M ETH collateral
5. Withdraw and burn the 1 quint STAB to close the original flash mint
6. You now have a 1 million STAB loan that is practically interest free for perpetuity ($0.10 / year in interest)

The key takeaway being the obvious need to implement a flat floor/ceiling rate limit and to rebalance the rate based on short term liquidity changes.

#### Example 2 - arithmetic overflow and underflow
If the flash mint provider does not place any limits on the amount of flash mintable tokens in a transaction, then anyone can flash mint 2^256-1 amount of tokens. 

The protocols on the receiving end of the flash mints will need to ensure their contracts can handle this, either by using a compiler that embeds overflow protection in the smart contract bytecode, or by setting explicit checks.

### Flash minting internal security considerations
    
The coupling of flash minting with business specific features in the same platform can easily lead to unintended consequences.

#### Example - Treasury draining
Assume a smart contract that flash lends its native token. The same smart contract borrows from a third party when users burn the native token. This pattern would be used to aggregate in the smart contract the collateralized debt of several users into a single account in the third party. The flash mint could be used to cause the lender to borrow to its limit, and then pushing interest rates in the underlying lender, liquidate the flash lender:
1. Flash mint from `lender` a very large amount of FOO.
2. Redeem FOO for BAR, causing `lender` to borrow from `underwriter` all the way to its borrowing limit.
3. Trigger a debt rate increase in `underwriter`, making `lender` undercollateralized.
4. Liquidate the `lender` for profit.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 15 Nov 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3156</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3156</guid>
      </item>
    
      <item>
        <title>BASEFEE opcode</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3198-basefeeopcode/5162</comments>
        
        <description>## Simple Summary
Adds an opcode that gives the EVM access to the block&apos;s base fee.

## Abstract

Add a `BASEFEE (0x48)` that returns the value of the base fee of the current block it is executing in.

## Motivation
The intended use case would be for contracts to get the value of the base fee. This feature would enable or improve existing use cases, such as:
- Contracts that need to set bounties for anyone to &quot;poke&quot; them with a transaction could set the bounty to be `BASEFEE + x`, or `BASEFEE * (1 + x)`. This makes the mechanism more reliable, because they will always pay &quot;enough&quot; regardless of market conditions.
- Gas futures can be implemented based on it. This would be more precise than gastokens.
- Improve the security for state channels, plasma, optirolls and other fraud proof driven solutions. Having the `BASEFEE` as an input allows you to lengthen the challenge period automatically if you see that the `BASEFEE` is high.

## Specification
Add a `BASEFEE` opcode at `(0x48)`, with gas cost `G_base`.

|  Op  	| Input 	| Output 	| Cost 	|
|:----:	|:-----:	|:------:	|:----:	|
| 0x48 	|   0   	|    1   	|   2  	|

## Rationale

### Gas cost
The value of the base fee is needed to process transactions. That means it&apos;s value is already available before running the EVM code.
The opcode does not add extra complexity and additional read/write operations, hence the choice of `G_base` gas cost.

## Backwards Compatibility
There are no known backward compatibility issues with this opcode.

## Test Cases

### Nominal case
Assuming current block base fee is `7 wei`.
This should push the value `7` (left padded byte32) to the stack.

Bytecode: `0x4800` (`BASEFEE, STOP`)

|  Pc   |      Op     | Cost |   Stack   |   RStack  |
|-------|-------------|------|-----------|-----------|
|    0  |    BASEFEE  |    2 |        [] |        [] |
|    1  |    STOP     |    0 |       [7] |        [] |

Output: 0x
Consumed gas: `2`

## Security Considerations
The value of the base fee is not sensitive and is publicly accessible in the block header. There are no known security implications with this opcode.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 13 Jan 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3198</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3198</guid>
      </item>
    
      <item>
        <title>Crosschain Identifier Specification</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3220-crosschain-id-specification/5446</comments>
        
        <description>## Simple Summary

A self-verifying unique blockchain identifier that deals with forks.

## Abstract

The crosschain-id is a 32 byte hex string and with some bytes extracted from blockchain hash and some manually defined to characterize a blockchain.
We also propose a registration and lookup service to retrieve blockchain metadata from the crosschain-id.

## Motivation

With the success of Bitcoin and Ethereum, various blockchains such as EOS, Ripple, Litecoin, Besu, Wanchain and the like have been developed and are growing at a fast pace.  There are also other private and consortium blockchains such as Hyperledger Fabric, Hyperledger Besu, Stellar, Corda, Quorum that only allow nodes with permitted identities to join the blockchain network.  The growth of public and private blockchains imposes challenges for inter-chain interoperability, particularly when these chains are heterogeneous and incompatible. Enterprise Ethereum Alliance formed Crosschain Interoperability Task Force (CITF) to look into common crosschain problems and solutions. CITF team noticed that there is a lack of unique identifier to charaterise and describe a blockchain. Several proprosals were discussed in EEA Crosschain Interoperability Task Force meetings and discussions.

[EIP-155](/EIPs/EIPS/eip-155) provides a unique identifier to a blockchain to provide simple relay attack protection.  This specification defines an integer for Chainid for a blockchain and sign the chainid into a transaction data and hence present attackers to send same transaction to different blockchains. This specification will require blockchains to define a chainid and register the chainid in a public repository.

The challenge of using an integer for chainid is that it is not broad enough to cover all blockchains and it does not prevent different blockchains using the same chainid.  Also, it does not address the issue for two forked blockchains having the same chainid.

Hence there is need for a more robust blockchain identifier that will overcome these drawbacks, especially for crosschain operations where multiple chains are involved. A blockchain identifier (crosschain id) should be unique and satisfy the following requirements:

* should provide identification, description, and discovery of blockchains.
* should provide unique identification of each blockchain in the crosschain service ecosystem.
* should provide descriptions for a blockchain identities such as chainId, name, type, consensus scheme etc.
* should provide discovery mechanism for supported blockchains and also for new blockchains in the ecosystem.
* should provide a mechanism for a joining blockchain to register to the ecosystem.
* should provide a mechanism for a blockchain to edit properties or unregister from the crosschain ecosystem.
* should provide a mechanism to get some critical information of the blockchain
* should provide a mechanism to differentiate an original blockchain and a forked blockchain
* should provide a mechanism to verify a chainid without external registration service

## Specification

### Definition of a 32 byte crosschain id

| Name          | Size(bytes) | Description |
|---------------|-------------|-------------|
| Truncated Block Hash | 16 | This is the block hash of the genesis block or the block hash of the block immediate prior to the fork for a fork of a blockchain. The 16 bytes is the 16 least significant bytes, assuming network byte order.|
|Native Chain ID| 8 | This is the **Chain Id** value that should be used with the blockchain when signing transactions. For blockchains that do not have a concept of **Chain Id**, this value is zero.|
|Chain Type| 2 |  Reserve 0x00 as undefined chaintype. 0x01 as mainnet type. 0x1[0-A]: testnet, 0x2[0-A]: private development network|
| Governance Identifier | 2 |  For new blockchains, a governance_identifier can be specified to identify an original **owner** of a blockchain, to help settle forked / main chain disputes. For all existing blockchains and for blockchains that do not have the concept of an **owner**, this field is zero. |
| Reserved | 3 | Reserved for future use. Use 000000 for now. |
| Checksum | 1 | Used to verify the integrity of the identifier. This integrity check is targeted at detecting Crosschain Identifiers mis-typed by human users. The value is calculated as the truncated SHA256 message digest of the rest of the identifier, using the least significant byte, assuming network byte order. Note that this checksum byte only detects integrity with a probability of one in 256. This probability is adequate for the intended usage of detecting typographical errors by people manually entering the Crosschain Identifier. |


## Rationale

We have considered various alternative specifications such as using a random unique hex string to represent a blockchain.  The drawback of this method is that the random id can not be used to verify a blockchain&apos;s intrinsic identity such as the blockhash of the genesis block.  A second alternative is simply using a genesis blockhash to represent a blockchain id for crosschain operations.  The drawback of this is that this id does not have information about the property of the blockchain and it has problem when a blockchain is forked into two blockchain.

## Backwards Compatibility

Crosschainid can be backward compatible with EIP-155.  The crosschain id contains an 8 byte segment to record the `Native Chain ID`.
For Ethereum chains, that can be used for a value intended to be used with EIP-155.

## Security Considerations

Collision of crosschain id:  Two blockchains can contain the same crosschain id and hence making the mistakenly transfer assets to a wrong blockchain.  
This security concern is addressed by comparing the hash of the crosschain id with the hash of the genesis block.  If it matches, then the crosschain id is verified.  If not, the crosschain id can be compared with the forked blockhash.  If none of the blockhash match the crosschain id hash, then the crosschain id cannot be verified.

Preventing relay attack: Although crosschain id by itself is different from chainid and it is not signed into blockchain transaction, the crosschain id can still be used for presenting relay attack. An application that handles crosschain transaction can verified the crosschain id with its blockhash and decide whether the transaction is valid or not. Any transaction with a non-verifiable crosschain id should be rejected.

The crosschain-id are not required to be signed into blockchaid tx.
For blockchains that do not cryptographically sign crosschain id into the blocks, the crosschain id cannot be verified with the blocks itself and have to be verified with external smart contract address and offchain utilities implemented based on the crosschain id specification.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 21 Oct 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3220</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3220</guid>
      </item>
    
      <item>
        <title>Described Data</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/3225</comments>
        
        <description>## Abstract

Human-readable descriptions for machine executable operations,
described in higher level machine readable data, so that wallets
can provide meaningful feedback to the user describing the
action the user is about to perform.


## Motivation

When using an Ethereum Wallet (e.g. MetaMask, Clef, Hardware
Wallets) users must accept and authorize signing messages or
sending transactions.

Due to the complexity of Ethereum transactions, wallets are very
limitd in their ability to provide insight into the contents of
transactions user are approving; outside special-cased support
for common transactions such as ERC20 transfers, this often amounts
to asking the user to sign an opaque blob of binary data.

This EIP presents a method for dapp developers to enable a more
comfortable user experience by providing wallets with a means
to generate a better description about what the contract claims
will happen.

It does not address malicious contracts which wish to lie, it
only addresses honest contracts that want to make their user&apos;s
life better. We believe that this is a reasonable security model,
as transaction descriptions can be audited at the same time as
contract code, allowing auditors and code reviewers to check that
transaction descriptions are accurate as part of their review.


## Specification

The **description string** and **described data** are generated
simultaneously by evaluating the contract
(i.e. the **describer**), passing the **describer inputs** to the 
method:

```solidity
function eipXXXDescribe(bytes describer_inputs) view returns (string description_string, bytes described_data);
```

The method must be executable in a static context, (i.e. any
side effects, such as logX, sstore, etc.), including through
indirect calls may be ignored.

During evaluation, the `ADDRESS` (i.e. `to`), `CALLER`
(i.e. `from`), `VALUE`, and `GASPRICE` must be the same as the
values for the transaction being described, so that the
code generating the description can rely on them. For signing
**described messages**, `VALUE` should always be 0.

When executing the bytecode, best efforts should be made to
ensure `BLOCKHASH`, `NUMBER`, `TIMESTAMP` and `DIFFICULTY`
match the `&quot;latest&quot;` block. The `COINBASE` should be the zero
address.

The method may revert, in which case the signing must be aborted.


### New JSON-RPC Methods

Clients which manage private keys should expose additional
methods for interacting with the related accounts.

If an user interface is not present or expected for any other
account-based operations, the description strings should be
ignored and the described data used directly.

These JSON-RPC methods will also be implemented in standard
Ethereum libraries, so the JSON-RPC description is meant more
of a canonical way to describe them.


### Signing Described Messages

```solidity
eth_signDescribedMessage(address, describer, describerInput)
// Result: {
//   description: &quot;text/plain;Hello World&quot;,
//   data: &quot;0x...&quot;, // described data
//   signature: &quot;0x...&quot;
// }
```

Compute the **description string** and **described data** by
evaluating the call to **describer**, with the
**describerInput** passed to the ABI encoded call to
`eipXXXDescription(bytes)`. The `VALUE` during execution must
be 0.

If the wallet contains a user interface for accepting or
denying signing a message, it should present the description
string to the user. Optionally, a wallet may wish to
additionally provide a way to examine the described data.

If accepted, the computed **described data** is signed
according to [EIP-191](/EIPs/EIPS/eip-191), with the *version
byte* of `0x00` and the *version specific data* of describer
address.

That is:

```
0x19   0x00   DESCRIBER_ADDRESS   0xDESCRIBED_DATA
```

The returned result includes the **described data**, allowing
dapps that use parameters computed in the contract to be
available.

### Sending Described Transactions

```solidity
eth_sendDescribedTransaction(address, {
  to: &quot;0x...&quot;,
  value: 1234,
  nonce: 42,
  gas: 42000,
  gasPrice: 9000000000,
  describerInput: &quot;0x1234...&quot;,
})
// Result: {
//   description: &quot;text/plain;Hello World&quot;,
//   transaction: &quot;0x...&quot;, // serialized signed transaction
// }
```

Compute the **description string** and **described data** by
evaluating the call to the **describer** `to`, with the
**describerInput** passed  to the ABI encoded call to
`eipXXXDescription(bytes)`.

If the wallet contains a user interface for accepting or
denying a transaction, it should present the description string
along with fee and value information. Optionally, a wallet may
wish to additionally provide a way to further examine the
transaction.

If accepted, the transaction data is set to the computed
**described data**, the derived transaction is signed and sent,
and the **description string** and serialized signed
transaction is returned.


### Signing Described Transaction

```solidity
eth_signDescribedTransaction(address, {
  to: &quot;0x...&quot;,
  value: 1234,
  nonce: 42,
  gas: 42000,
  gasPrice: 9000000000,
  describerInput: &quot;0x1234...&quot;,
})
// Result: {
//   description: &quot;text/plain;Hello World&quot;,
//   transaction: &quot;0x...&quot;, // serialized signed transaction
// }
```

Compute the **description string** and **described data** by
evaluating the call to the **describer** `to`, with the
**describerInput** passed  to the ABI encoded call to
`eipXXXDescription(bytes)`.

If the wallet contains a user interface for accepting or
denying a transaction, it should present the description string
along with fee and value information. Optionally, a wallet may
wish to additionally provide a way to further examine the
transaction.

If accepted, the transaction data is set to the computed
**described data**, the derived transaction is signed (and not
sent) and the **description string** and serialized signed
transaction is returned.

### Description Strings

A **description string** must begin with a mime-type followed
by a semi-colon (`;`). This EIP specifies only the `text/plain`
mime-type, but future EIPs may specify additional types to
enable more rich processing, such as `text/markdown` so that
addresses can be linkable within clients or to enable
multi-locale options, similar to multipart/form-data.


## Rationale

### Meta Description

There have been many attempts to solve this problem, many of
which attempt to examine the encoded transaction data or
message data directly.

In many cases, the information that would be necessary for a
meaningful description is not present in the final encoded
transaction data or message data.

Instead this EIP uses an indirect description of the data.

For example, the `commit(bytes32)` method of ENS places a
commitement **hash** on-chain. The hash contains the
**blinded** name and address; since the name is blinded, the
encoded data (i.e. the hash) no longer contains the original
values and is insufficient to access the necessary values to
be included in a description.

By instead describing the commitment indirectly (with the
original information intact: NAME, ADDRESS and SECRET) a
meaningful description can be computed (e.g. &quot;commit to NAME for ADDRESS (with SECRET)&quot;)
and the matching data can be computed (i.e. `commit(hash(name, owner, secret))`).

### Entangling the Contract Address

To prevent data being signed from one contract being used
against another, the contract address is entanlged into
both the transaction (implicitly via the `to` field) and
in messages by the EIP-191 versions specific data.

The use of the zero address is reserved.

### Alternatives

- NatSpec and company are a class of more complex languages that attempt to describe the encoded data directly. Because of the language complexity they often end up being quite large requiring entire runtime environments with ample processing power and memory, as well as additional sandboxing to reduce security concerns. One goal of this is to reduce the complexity to something that could execute on hardware wallets and other simple wallets. These also describe the data directly, which in many cases (such as blinded data), cannot adequately describe the data at all

- Custom Languages; due to the complexity of Ethereum transactions, any language used would require a lot of expressiveness and re-inventing the wheel. The EVM already exists (it may not be ideal), but it is there and can handle everything necessary. 

- Format Strings (e.g. Trustless Signing UI Protocol; format strings can only operate on the class of regular languages, which in many cases is insufficient to describe an Ethereum transaction. This was an issue quite often during early attempts at solving this problem.

- The signTypedData [EIP-712](/EIPs/EIPS/eip-712) has many parallels to what this EIP aims to solve

- @TODO: More


## Backwards Compatibility

All signatures for messages are generated using [EIP-191](/EIPs/EIPS/eip-191)
which had a previously compatible version byte of `0x00`, so
there should be no concerns with backwards compatibility.


## Test Cases

All test cases operate against the published and verified contracts:

- Formatter: Ropsten @ 0x7a89c0521604008c93c97aa76950198bca73d933
- TestFormatter: Ropsten @ 0xab3045aa85cbcabb06ed3f3fe968fa5457727270

The private key used for signing messages and transactions is:

```
privateKey = &quot;0x6283185307179586476925286766559005768394338798750211641949889184&quot;
```


### Messages

**Example: login with signed message**

- sends selector login()
- received data with selector doLogin(bytes32 timestamp)

```
Input:
  Address:         0xab3045AA85cBCaBb06eD3F3FE968fA5457727270
  Describer Input: 0xb34e97e800000000000000000000000000000000000000000000000000000000
  i.e.             encode(
                       [ &quot;bytes4&quot; ],
                       [ SEL(&quot;login()&quot;) ]
                   )

Output:
  Description:     text/plain;Log into ethereum.org?
  Data:            0x14629d78000000000000000000000000000000000000000000000000000000006010d607
  i.e.             encodeWithSelector(&quot;doLogin(bytes32)&quot;, &quot;0x000000000000000000000000000000000000000000000000000000006010d607&quot; ]

Signing:
  Preimage:  0x1900ab3045aa85cbcabb06ed3f3fe968fa545772727014629d78000000000000000000000000000000000000000000000000000000006010d607
  Signature: 0x8b9def29343c85797a580c5cd3607c06e78a53351219f9ba706b9985c1a3c91e702bf678e07f5daf5ef48b3e3cc581202de233904b72cf2c4f7d714ce92075b21c
```

### Transactions

All transaction test cases use the ropsten network (chainId: 3)
and for all unspecified properties use 0.

**Example: ERC-20 transfer**

```
Input:
  Address:            0xab3045AA85cBCaBb06eD3F3FE968fA5457727270
  Describer Input:    0xa9059cbb000000000000000000000000000000000000000000000000000000000000000000000000000000008ba1f109551bd432803012645ac136ddd64dba720000000000000000000000000000000000000000000000002b992b75cbeb6000
  i.e.                encode(
                          [ &quot;bytes4&quot;, &quot;address&quot;, &quot;uint&quot;],
                          [ SEL(&quot;transfer(address,uint256)&quot;), &quot;0x8ba1f109551bD432803012645Ac136ddd64DBA72&quot;, 3.14159e18 ]
                      )
Output:
  Description:        text/plain;Send 3.14159 TOKN to &quot;ricmoose.eth&quot; (0x8ba1f109551bD432803012645Ac136ddd64DBA72)?
  Described Data:     0xa9059cbb0000000000000000000000000000000000000000000000002b992b75cbeb60000000000000000000000000008ba1f109551bd432803012645ac136ddd64dba72
  i.e.                encodeWithSelector(&quot;transfer(address,uint256)&quot;, &quot;0x8ba1f109551bD432803012645Ac136ddd64DBA72&quot;, 3.14159e18)

Signing:
  Signed Transaction: 0xf8a280808094ab3045aa85cbcabb06ed3f3fe968fa545772727080b844a9059cbb0000000000000000000000000000000000000000000000002b992b75cbeb60000000000000000000000000008ba1f109551bd432803012645ac136ddd64dba7229a0f33ea492d326ac32d9b7ae203c61bf7cf0ac576fb0cf8be8e4c63dc89c90de12a06c8efb28aaf3b70c032b3bd1edfc664578c49f040cf749bb19b000da56507fb2
```

**Example: ERC-20 approve**

```
Input:
  Address:            0xab3045AA85cBCaBb06eD3F3FE968fA5457727270
  Describer Input:    0x095ea7b3000000000000000000000000000000000000000000000000000000000000000000000000000000008ba1f109551bd432803012645ac136ddd64dba720000000000000000000000000000000000000000000000002b992b75cbeb6000
  i.e.                encode(
                          [ &quot;bytes4&quot;, &quot;address&quot;, &quot;uint&quot;],
                          [ SEL(&quot;approve(address,uint256)&quot;), &quot;0x8ba1f109551bD432803012645Ac136ddd64DBA72&quot;, 3.14159e18 ]
                      )

Output:
  Description:        text/plain;Approve &quot;ricmoose.eth&quot; (0x8ba1f109551bD432803012645Ac136ddd64DBA72) to manage 3.14159 TOKN tokens?
  Described Data:     0xa9059cbb0000000000000000000000000000000000000000000000002b992b75cbeb60000000000000000000000000008ba1f109551bd432803012645ac136ddd64dba72
  i.e.                encodeWithSelector(&quot;approve(address,uint256)&quot;, &quot;0x8ba1f109551bD432803012645Ac136ddd64DBA72&quot;, 3.14159e18)

Signing:
  Signed Transaction: 0xf8a280808094ab3045aa85cbcabb06ed3f3fe968fa545772727080b844a9059cbb0000000000000000000000000000000000000000000000002b992b75cbeb60000000000000000000000000008ba1f109551bd432803012645ac136ddd64dba7229a0f33ea492d326ac32d9b7ae203c61bf7cf0ac576fb0cf8be8e4c63dc89c90de12a06c8efb28aaf3b70c032b3bd1edfc664578c49f040cf749bb19b000da56507fb2
```

**Example: ENS commit**

```
Input:
  Address:            0xab3045AA85cBCaBb06eD3F3FE968fA5457727270
  Describer Input:    0x0f0e373f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000e31f43c1d823afaa67a8c5fbb8348176d225a79e65462b0520ef7d3df61b9992ed3bea0c56ead753be7c8b3614e0ce01e4cac41b00000000000000000000000000000000000000000000000000000000000000087269636d6f6f7365000000000000000000000000000000000000000000000000
  i.e.                encode(
                          [ &quot;bytes4&quot;, &quot;string&quot;, &quot;address&quot;, &quot;bytes32&quot;],
                          [ SEL(&quot;commit(string,address,bytes32)&quot;), &quot;ricmoose&quot;, &quot;0xE31f43C1d823AfAA67A8C5fbB8348176d225A79e&quot;, &quot;0x65462b0520ef7d3df61b9992ed3bea0c56ead753be7c8b3614e0ce01e4cac41b&quot; ]
                      )
  
Output:
  Description:        text/plain;Commit to the ENS name &quot;ricmoose.eth&quot; for 0xE31f43C1d823AfAA67A8C5fbB8348176d225A79e?
  Described Data:     0xf14fcbc8e4a4f2bb818545497be34c7ab30e6e87e0001df4ba82e7c8b3f224fbaf255b91
  i.e.                encodeWithSelector(&quot;commit(bytes32)&quot;, makeCommitment(&quot;ricmoose&quot;, &quot;0xE31f43C1d823AfAA67A8C5fbB8348176d225A79e&quot;, &quot;0x65462b0520ef7d3df61b9992ed3bea0c56ead753be7c8b3614e0ce01e4cac41b&quot;))

Signing:
  Signed Transaction: 0xf88180808094ab3045aa85cbcabb06ed3f3fe968fa545772727080a4f14fcbc8e4a4f2bb818545497be34c7ab30e6e87e0001df4ba82e7c8b3f224fbaf255b912aa0a62b41d1ebda584fe84cf8a05f61b429fe4ec361e13c17f30a23281106b38a8da00bcdd896fe758d8f0cfac46445a48f76f5e9fe27790d67c51412cb98a12a0844
```

**Example: WETH mint()**

```
Input:
  Address:            0xab3045AA85cBCaBb06eD3F3FE968fA5457727270
  Describer Input:    0x1249c58b00000000000000000000000000000000000000000000000000000000
  i.e.                encode(
                          [ &quot;bytes4&quot; ],
                          [ SEL(&quot;mint()&quot;) ]
                      )
  Value:              1.23 ether

Output:
  Description:        text/plain;Mint 1.23 WETH (spending 1.23 ether)?
  Described Data:     0x1249c58b
  i.e.                encodeWithSelector(&quot;mint()&quot;)

Signing:
  Signed Transaction: 0xf86980808094ab3045aa85cbcabb06ed3f3fe968fa5457727270881111d67bb1bb0000841249c58b29a012df802e1394a97caab23c15c3a8c931668df4b2d6d604ca23f3f6b836d0aafca0071a2aebef6a9848616b4d618912f2003fb4babde3dba451b5246f866281a654
```

## Reference Implementation

@TODO (consider adding it as one or more files in `../assets/eip-####/`)

I will add examples in Solidity and JavaScript.


## Security Considerations

### Escaping Text

Wallets must be careful when displaying text provided by
contracts and proper efforts must be taken to sanitize
it, for example, be sure to consider:

- HTML could be embedded to attempt to trick web-based wallets into executing code using the script tag (possibly uploading any private keys to a server)
- In general, extreme care must be used when rendering HTML; consider the ENS names `&lt;span style=&quot;display:none&quot;&gt;not-&lt;/span&gt;ricmoo.eth` or `&amp;thinsp;ricmoo.eth`, which if rendered without care would appear as `ricmoo.eth`, which it is not
- Other marks which require escaping could be included, such as quotes (`&quot;`), formatting (`\n` (new line), `\f` (form feed), `\t` (tab), any of many non-standard whitespaces), back-slassh (`\`)
- UTF-8 has had bugs in the past which could allow arbitrary code execution and crashing renderers; consider using the UTF-8 replacement character (or *something*) for code-points outside common planes or common sub-sets within planes
- Homoglyphs attacks
- Right-to-left marks may affect rendering
- Many other things, deplnding on your environment

### Distinguished Signed Data

Applications implementing this EIP to sign message data should
ensure there are no collisions within the data which could
result in ambiguously signed data.

@TODO: Expand on this; compare packed data to ABI encoded data?

### Enumeration

If an abort occurs during signing, the response from this call
should match the response from a declined signing request;
otherwise this could be used for enumeration attacks, etc. A
random interactive-scale delay should also be added, otherwise
a &lt; 10ms response could be interpreted as an error.

### Replayablility

Transactions contain an explicit nonce, but signed messages do
not.

For many purposes, such as signing in, a nonce could be
injected (using block.timestamp) into the data. The log in
service can verify this is a recent timestamp. The timestamp
may or may not be omitted from the description string in this
case, as it it largely useful internally only.

In general, when signing messages a nonce often makes sense to
include to prevent the same signed data from being used in the
future.


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 23 Jan 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3224</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3224</guid>
      </item>
    
      <item>
        <title>Batch Flash Loans</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-3234-batch-flash-loans/5271</comments>
        
        <description>## Simple Summary

This ERC provides standard interfaces and processes for multiple-asset flash loans.

## Motivation

Flash loans of multiple assets, or batch flash loans, are a common offering of flash lenders, and have a strong use case in the simultaneous refinance of several positions between platforms. At the same time, batch flash loans are more complicated to use than single asset flash loans (ER3156). This divergence of use cases and user profiles calls for independent, but consistent, standards for single asset flash loans and batch flash loans.


## Specification

A batch flash lending feature integrates two smart contracts using a callback pattern. These are called the LENDER and the RECEIVER in this EIP.

### Lender Specification

A `lender` MUST implement the IERC3234BatchFlashLender interface.
```
pragma solidity ^0.7.0 || ^0.8.0;
import &quot;./IERC3234BatchFlashBorrower.sol&quot;;


interface IERC3234BatchFlashLender {

    /**
     * @dev The amount of currency available to be lended.
     * @param tokens The currency for each loan in the batch.
     * @return The maximum amount that can be borrowed for each loan in the batch.
     */
    function maxFlashLoan(
        address[] calldata tokens
    ) external view returns (uint256[]);

    /**
     * @dev The fees to be charged for a given batch loan.
     * @param tokens The loan currencies.
     * @param amounts The amounts of tokens lent.
     * @return The amount of each `token` to be charged for each loan, on top of the returned principal.
     */
    function flashFee(
        address[] calldata tokens,
        uint256[] calldata amounts
    ) external view returns (uint256[]);

    /**
     * @dev Initiate a batch flash loan.
     * @param receiver The receiver of the tokens in the loan, and the receiver of the callback.
     * @param tokens The loan currencies.
     * @param amounts The amount of tokens lent.
     * @param data Arbitrary data structure, intended to contain user-defined parameters.
     */
    function batchFlashLoan(
        IERC3234BatchFlashBorrower receiver,
        address[] calldata tokens,
        uint256[] calldata amounts,
        bytes[] calldata data
    ) external returns (bool);
}
```

The `maxFlashLoan` function MUST return the maximum loan possible for each `token`. If a `token` is not currently supported `maxFlashLoan` MUST return 0, instead of reverting.

The `flashFee` function MUST return the fees charged for each loan of `amount` `token`. If a token is not supported `flashFee` MUST revert.

The `batchFlashLoan` function MUST include a callback to the `onBatchFlashLoan` function in a `IERC3234BatchFlashBorrower` contract.

```
function batchFlashLoan(
    IERC3234BatchFlashBorrower receiver,
    address[] calldata tokens,
    uint256[] calldata amounts,
    bytes calldata data
) external returns (bool) {
  ...
    require(
        receiver.onBatchFlashLoan(
            msg.sender,
            tokens,
            amounts,
            fees,
            data
        ) == keccak256(&quot;ERC3234BatchFlashBorrower.onBatchFlashLoan&quot;),
        &quot;IERC3234: Callback failed&quot;
    );
  ...
}
```

The `batchFlashLoan` function MUST transfer `amounts[i]` of each `tokens[i]` to `receiver` before the callback to the borrower.

The `batchFlashLoan` function MUST include `msg.sender` as the `initiator` to `onBatchFlashLoan`.

The `batchFlashLoan` function MUST NOT modify the `tokens`, `amounts` and `data` parameters received, and MUST pass them on to `onBatchFlashLoan`.

The `lender` MUST verify that the `onBatchFlashLoan` callback returns the keccak256 hash of &quot;ERC3234BatchFlashBorrower.onBatchFlashLoan&quot;.

The `batchFlashLoan` function MUST include a `fees` argument to `onBatchFlashLoan` with the fee to pay for each individual `token` and `amount` lent, ensuring that `fees[i] == flashFee(tokens[i], amounts[i])`.

After the callback, for each `token` in `tokens`, the `batchFlashLoan` function MUST take the `amounts[i] + fees[i]` of `tokens[i]` from the `receiver`, or revert if this is not successful.

If successful, `batchFlashLoan` MUST return `true`.

### Receiver Specification

A `receiver` of flash loans MUST implement the IERC3234BatchFlashBorrower interface:

```
pragma solidity ^0.7.0 || ^0.8.0;


interface IERC3234BatchFlashBorrower {

    /**
     * @dev Receive a flash loan.
     * @param initiator The initiator of the loan.
     * @param tokens The loan currency.
     * @param amounts The amount of tokens lent.
     * @param fees The additional amount of tokens to repay.
     * @param data Arbitrary data structure, intended to contain user-defined parameters.
     * @return The keccak256 hash of &quot;ERC3234BatchFlashBorrower.onBatchFlashLoan&quot;
     */
    function onBatchFlashLoan(
        address initiator,
        address[] calldata tokens,
        uint256[] calldata amounts,
        uint256[] calldata fees,
        bytes calldata data
    ) external returns (bytes32);
}
```

For the transaction to not revert, for each `token` in `tokens`, `receiver` MUST approve `amounts[i] + fees[i]` of `tokens[i]` to be taken by `msg.sender` before the end of `onBatchFlashLoan`.

If successful, `onBatchFlashLoan` MUST return the keccak256 hash of &quot;ERC3156BatchFlashBorrower.onBatchFlashLoan&quot;.

## Rationale

The interfaces described in this ERC have been chosen as to cover the known flash lending use cases, while allowing for safe and gas efficient implementations.

`flashFee` reverts on unsupported tokens, because returning a numerical value would be incorrect.

`batchFlashLoan` has been chosen as a function name as descriptive enough, unlikely to clash with other functions in the lender, and including both the use cases in which the tokens lended are held or minted by the lender.

`receiver` is taken as a parameter to allow flexibility on the implementation of separate loan initiators and receivers.

Existing flash lenders (Aave, dYdX and Uniswap) all provide flash loans of several token types from the same contract (LendingPool, SoloMargin and UniswapV2Pair). Providing a `token` parameter in both the `batchFlashLoan` and `onBatchFlashLoan` functions matches closely the observed functionality.

A `bytes calldata data` parameter is included for the caller to pass arbitrary information to the `receiver`, without impacting the utility of the `batchFlashLoan` standard.

`onBatchFlashLoan` has been chosen as a function name as descriptive enough, unlikely to clash with other functions in the `receiver`, and following the `onAction` naming pattern used as well in EIP-667.

An `initiator` will often be required in the `onBatchFlashLoan` function, which the lender knows as `msg.sender`. An alternative implementation which would embed the `initiator` in the `data` parameter by the caller would require an additional mechanism for the receiver to verify its accuracy, and is not advisable.

The `amounts` will be required in the `onBatchFlashLoan` function, which the lender took as a parameter. An alternative implementation which would embed the `amounts` in the `data` parameter by the caller would require an additional mechanism for the receiver to verify its accuracy, and is not advisable.

The `fees` will often be calculated in the `batchFlashLoan` function, which the `receiver` must be aware of for repayment. Passing the `fees` as a parameter instead of appended to `data` is simple and effective.

The `amount + fee` are pulled from the `receiver` to allow the `lender` to implement other features that depend on using `transferFrom`, without having to lock them for the duration of a flash loan. An alternative implementation where the repayment is transferred to the `lender` is also possible, but would need all other features in the lender to be also based in using `transfer` instead of `transferFrom`. Given the lower complexity and prevalence of a &quot;pull&quot; architecture over a &quot;push&quot; architecture, &quot;pull&quot; was chosen.

## Security Considerations

### Verification of callback arguments

The arguments of `onBatchFlashLoan` are expected to reflect the conditions of the flash loan, but cannot be trusted unconditionally. They can be divided in two groups, that require different checks before they can be trusted to be genuine.

0. No arguments can be assumed to be genuine without some kind of verification. `initiator`, `tokens` and `amounts` refer to a past transaction that might not have happened if the caller of `onBatchFlashLoan` decides to lie. `fees` might be false or calculated incorrectly. `data` might have been manipulated by the caller.
1. To trust that the value of `initiator`, `tokens`, `amounts` and `fees` are genuine a reasonable pattern is to verify that the `onBatchFlashLoan` caller is in a whitelist of verified flash lenders. Since often the caller of `batchFlashLoan` will also be receiving the `onBatchFlashLoan` callback this will be trivial. In all other cases flash lenders will need to be approved if the arguments in `onBatchFlashLoan` are to be trusted.
2. To trust that the value of `data` is genuine, in addition to the check in point 1, it is recommended that the `receiver` verifies that the `initiator` is in some list of trusted addresses. Trusting the `lender` and the `initiator` is enough to trust that the contents of `data` are genuine.

### Flash lending security considerations

#### Automatic approvals for untrusted borrowers
The safest approach is to implement an approval for `amount+fee` before the `batchFlashLoan` is executed.    

Including in `onBatchFlashLoan` the approval for the `lender` to take the `amount + fee` needs to be combined with a mechanism to verify that the borrower is trusted, such as those described above.

If an unsuspecting contract with a non-reverting fallback function, or an EOA, would approve a `lender` implementing ERC3156, and not immediately use the approval, and if the `lender` would not verify the return value of `onBatchFlashLoan`, then the unsuspecting contract or EOA could be drained of funds up to their allowance or balance limit. This would be executed by a `borrower` calling `batchFlashLoan` on the victim. The flash loan would be executed and repaid, plus any fees, which would be accumulated by the `lender`. For this reason, it is important that the `lender` implements the specification in full and reverts if `onBatchFlashLoan` doesn&apos;t return the keccak256 hash for &quot;ERC3156FlashBorrower.onBatchFlashLoan&quot;.

### Flash minting external security considerations

The typical quantum of tokens involved in flash mint transactions will give rise to new innovative attack vectors.

#### Example 1 - interest rate attack
If there exists a lending protocol that offers stable interests rates, but it does not have floor/ceiling rate limits and it does not rebalance the fixed rate based on flash-induced liquidity changes, then it could be susceptible to the following scenario:

FreeLoanAttack.sol
1. Flash mint 1 quintillion DAI
2. Deposit the 1 quintillion DAI + $1.5 million worth of ETH collateral
3. The quantum of your total deposit now pushes the stable interest rate down to 0.00001% stable interest rate
4. Borrow 1 million DAI on 0.00001% stable interest rate based on the 1.5M ETH collateral
5. Withdraw and burn the 1 quint DAI to close the original flash mint
6. You now have a 1 million DAI loan that is practically interest free for perpetuity ($0.10 / year in interest)

The key takeaway being the obvious need to implement a flat floor/ceiling rate limit and to rebalance the rate based on short term liquidity changes.

#### Example 2 - arithmetic overflow and underflow
If the flash mint provider does not place any limits on the amount of flash mintable tokens in a transaction, then anyone can flash mint 2^256-1 amount of tokens. 

The protocols on the receiving end of the flash mints will need to ensure their contracts can handle this. One obvious way is to leverage OpenZeppelin&apos;s SafeMath libraries as a catch-all safety net, however consideration should be given to when it is or isn&apos;t used given the gas tradeoffs.

If you recall there was a series of incidents in 2018 where exchanges such as OKEx, Poloniex, HitBTC and Huobi had to shutdown deposits and withdrawls of ERC20 tokens due to integer overflows within the ERC20 token contracts.
    

### Flash minting internal security considerations
    
The coupling of flash minting with business specific features in the same platform can easily lead to unintended consequences.

#### Example - Treasury draining
In early implementations of the Yield Protocol flash loaned fyDai could be redeemed for Dai, which could be used to liquidate the Yield Protocol CDP vault in MakerDAO:
1. Flash mint a very large amount of fyDai.
2. Redeem for Dai as much fyDai as the Yield Protocol collateral would allow.
3. Trigger a stability rate increase with a call to `jug.drip` which would make the Yield Protocol uncollateralized.
4. Liquidate the Yield Protocol CDP vault in MakerDAO.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 31 Jan 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3234</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3234</guid>
      </item>
    
      <item>
        <title>Difficulty Bomb Delay to Q2/2022</title>
        <category>Standards Track/Core</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/3239</comments>
        
        <description>## Simple Summary
Delays the difficulty bomb so 30 second blocks won&apos;t happen until around Q2/2022.

## Abstract
Starting with `FORK_BLOCK_NUMBER` the client will calculate the difficulty based on a fake block number suggesting to the client that the difficulty bomb is adjusting eleven million blocks later than the actual block number.

## Motivation
Even after the Ethereum 2.0 mainnet launch, Ethash proof-of-work mining on the legacy chain should be feasible. It should allow miners sealing new blocks every 13~15 seconds on average for another ten months and allow both Ethereum 1.x and Ethereum 2.0 developers to conclude the merge.

## Specification
#### Relax Difficulty with Fake Block Number
For the purposes of `calc_difficulty`, simply replace the use of `block.number`, as used in the exponential ice age component, with the formula:

    fake_block_number = max(0, block.number - 11_000_000) if block.number &gt;= FORK_BLOCK_NUMBER else block.number

## Rationale
This will delay the ice age by another ~26 million seconds (approximately ~9.89 months), so the chain would be back at ~30 second block times in Q2/2022. Hopefully, by then the Eth1-to-Eth2 merge will be concluded and the ice age fulfilled its task.

## Backwards Compatibility
This EIP is not forward compatible and introduces backwards incompatibilities in the difficulty calculation. Therefore, it should be included in a scheduled hardfork at a certain block number. It&apos;s suggested to consider this EIP either with or shortly after the Berlin hard-fork but not later than July 2021.

Alternatively, in order to maintain stability of the system, a it can be considered to activate this EIP along with EIP-1559 fee market changes in a bundle. With the delay of the ice age, there is a desire to no further increase inflation and rather incentivize users to participate in proof-of-stake consensus instead. 

## Security Considerations
There are no known security issues with this proposal.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 25 Jan 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3238</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3238</guid>
      </item>
    
      <item>
        <title>Giving Ethereum fees to Future Salaries</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/discussion-of-eip-3267/5343</comments>
        
        <description>## Simple Summary
Transfer a part of Ethereum transfer/mining fees to Future Salaries contract

## Abstract
Transfer a part (exact fractions - TBD) of mining/transfer fees + (probably: TBD) some minted ETH to the `DonateETH` contract configured to transfer to `SalaryWithDAO` contract.

## Motivation
This proposal solves two problems at once:

1. It provides a big amount of &quot;money&quot; to common good producers. That obviously personally benefits common good producers, allowing them to live better human lives, it increases peoples&apos; and organizations&apos; both abilities and incentives to produce common goods. That benefits the humanity as a whole and the Ethereum ecosystem in particular. See more in the discussion why it&apos;s crucial.

2. This would effectively decrease circulating ETH supply. The necessity to decrease the (circulating) ETH supply (by locking ETH in Future Salaries system for a long time) is a well-known important thing to be done.

Paradoxically, it will directly benefit miners/validators, see the discussion.

## Specification
(TBD)

`SalaryWithDAO` = `TBD` (`address`)

`DefaultDAOInterface` = `TBD` (`address`)

`MintPerPeriod` = `TBD` (`uint256`)

`TransferFraction` = `TBD` (0..1)

`MineFraction` = `TBD` (0..1)

[The contract&apos;s source](/EIPs/assets/eip-3267/contracts/)

Prior to `FORK_BLOCK_NUMBER`, `SalaryWithDAO` and `DefaultDAOInterface` contracts will be deployed to the network and exist at the above specified addresses.

Change the Ethereum clients to transfer at every ETH transfer and every ETH mine a fixed fraction `TransferFraction` of the transferred ETH and `MineFraction` of the mined ETH to a fixed account (decide the account number, it can be for example `0x00000000000000000000000000000000000000001` or even `0x00000000000000000000000000000000000000000` or a random account).

Change the Ethereum clients to mint `MintPerPeriod` ETH to the contract `DonateETH` every some time (e.g. the first transaction of the first block every UTC day - TBD how often).

Change the Ethereum clients to every some time (e.g. the second transaction of the first block every UTC day - TBD how often) transfer the entire ETH from this account to the contract `DonateETH`.

Because this EIP solves a similar problem, cancel any other EIPs that burn ETH (except gas fees) during transfers or mining. (TBD: We should transfer more ETH in this EIP than we burned accordingly older accepted EIPs, because this EIP has the additional advantages of: 1. funding common goods; 2. better aligning values of ETH and values of tokens).

## Rationale
The Future Salaries is the _only_ known system of distributing significant funds to common good producers. (Quadratic funding aimed to do a similar thing, but in practice as we see on GitCoin it favors a few developers, ignores project of highly advanced scientific research that is hard to explain to an average developer, and encourages colluding, and it just highly random due to small number of donors. Also quadratic funding simply does not gather enough funds to cover common good needs). So this EIP is the only known way to recover the economy.

The economical model of Future Salaries is described in [this research article preprint](/EIPs/assets/eip-3267/science-salaries.pdf).

Funding multiple oracles with different finish time would alleviate the future trouble that the circulating ETH (or other tokens) supply would suddenly increase when the oracle finishes. It would effectively exclude some ETH from the circulation forever.

## Backwards Compatibility
Because transferring to the aforementioned account is neither mining nor a transaction, we get a new kinds of ETH transfers, so there may be some (expected moderate impact) troubles with applications that have made assumptions about ETH transfers all occurring either as miner payments or transactions.

## Security Considerations
The security considerations are:
- The DAO that controls account restoration may switch to a non-effective or biased way of voting (for example to being controlled by one human) thus distributing funds unfairly. This problem could be solved by a future fork of Ethereum that would &quot;confiscate&quot; control from the DAO.

See more in the discussion.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 13 Feb 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3267</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3267</guid>
      </item>
    
      <item>
        <title>Removal of refunds</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3298-removal-of-refunds/5430</comments>
        
        <description>## Simple Summary

Remove gas refunds for SSTORE and SELFDESTRUCT.

## Motivation

Gas refunds for SSTORE and SELFDESTRUCT were originally introduced to motivate application developers to write applications that practice &quot;good state hygiene&quot;, clearing storage slots and contracts that are no longer needed. However, they are not widely used for this, and poor state hygiene continues to be the norm. It is now widely accepted that the only solution to state growth is some form of [statelessness or state expiry](https://hackmd.io/@HWeNw8hNRimMm2m2GH56Cw/state_size_management), and if such a solution is implemented, then disused storage slots and contracts would start to be ignored automatically.

Gas refunds additionally have multiple harmful consequences:

* Refunds give rise to [GasToken](https://gastoken.io/). GasToken has benefits in moving gas space from low-fee periods to high-fee periods, but it also has downsides to the network, particularly in exacerbating state size (as state slots are effectively used as a &quot;battery&quot; to save up gas) and inefficiently clogging blockchain gas usage
* Refunds increase block size variance. The theoretical maximum amount of actual gas consumed in a block is nearly twice the on-paper gas limit (as refunds add gas space for subsequent transactions in a block, though refunds are capped at 50% of a transaction&apos;s gas used). This is [not fatal](https://notes.ethereum.org/@vbuterin/eip_1559_spikes), but is still undesirable, especially given that refunds can be used to maintain 2x usage spikes for far longer than EIP 1559 can.

## Specification

### Parameters

| Constant | Value |
| - | - |
| `FORK_BLOCK` | TBD |

For blocks where `block.number &gt;= FORK_BLOCK`, the following changes apply.

Do not apply the `refund`. 

The description above is sufficient to describe the change, but for the sake of clarity we enumerate all places where gas refunds are currently used and which should/could be removed within a node implementation. 

1. Remove all use of the &quot;refund counter&quot; in SSTORE gas accounting, as defined in [EIP 2200](https://eips.ethereum.org/EIPS/eip-2200). Particularly:

    * If a storage slot is changed and the _current value_ equals the _original value_, but does not equal the _new value_, `SSTORE_RESET_GAS` is deducted (plus `COLD_SLOAD_COST` if [prescribed by EIP 2929 rules](https://eips.ethereum.org/EIPS/eip-2929#sstore-changes)), but no modifications to the refund counter are made.
    * If a storage slot is changed and the _current value_ equals neither the _new value_ nor the _original value_ (regardless of whether or not the latter two are equal), `SLOAD_GAS` is deducted (plus `COLD_SLOAD_COST` if [prescribed by EIP 2929 rules](https://eips.ethereum.org/EIPS/eip-2929#sstore-changes)), but no modifications to the refund counter are made.

2. Remove the `SELFDESTRUCT` refund.

## Rationale

A full removal of refunds is the simplest way to solve the issues with refunds; any gains from partial retention of the refund mechanism are not worth the complexity that that would leave remaining in the Ethereum protocol.

## Backwards Compatibility

Refunds are currently only applied _after_ transaction execution, so they cannot affect how much gas is available to any particular call frame during execution. Hence, removing them will not break the ability of any code to execute, though it will render some applications economically nonviable.

[GasToken](https://gastoken.io/) in particular will become valueless. DeFi arbitrage bots, which today frequently use either established GasToken schemes or a custom alternative to reduce on-chain costs, would benefit from rewriting their code to remove calls to these no-longer-functional gas storage mechanisms.

## Implementation

An implementation can be found here: https://gist.github.com/holiman/460f952716a74eeb9ab358bb1836d821#gistcomment-3642048

## Test case changes

* The &quot;original&quot;, &quot;1st&quot;, &quot;2nd&quot;, &quot;3rd&quot; columns refer to the value of storage slot 0 before the execution and after each SSTORE.
* The &quot;Berlin (cold)&quot; column gives the post-Berlin (EIP 2929) gas cost assuming the storage slot had not yet been accessed.
* The &quot;Berlin (hot)&quot; column gives the post-Berlin gas cost assuming the storage slot has already been accessed.
* The &quot;Berlin (hot) + norefund&quot; column gives the post-Berlin gas cost assuming the storage slot has already been accessed, **and assuming this EIP has been implemented**.

Gas costs are provided with refunds subtracted; if the number is negative this means that refunds exceed gas costs. The 50% refund limit is not applied (due to the implied assumption that this code is only a small fragment of a much larger execution).

If refunds were to be removed, this would be the comparative table
| Code | Original | 1st | 2nd | 3rd |  Istanbul | Berlin (cold) | Berlin (hot)| Berlin (hot)+norefund |
| -- | -- | -- | -- | -- |  -- | -- | -- | -- | 
| `0x60006000556000600055` | 0 |  0 |  0 |  |  1612 | 2312 | 212 | 212 |
| `0x60006000556001600055` | 0 |  0 |  1 |  |  20812 | 22212 | 20112 | 20112 |
| `0x60016000556000600055` | 0 |  1 |  0 |  |  1612 | 2312 | 212 | 20112 |
| `0x60016000556002600055` | 0 |  1 |  2 |  |  20812 | 22212 | 20112 | 20112 |
| `0x60016000556001600055` | 0 |  1 |  1 |  |  20812 | 22212 | 20112 | 20112 |
| `0x60006000556000600055` | 1 |  0 |  0 |  |  -9188 | -9888 | -11988 | 3012 |
| `0x60006000556001600055` | 1 |  0 |  1 |  |  1612 | 2312 | 212 | 3012 |
| `0x60006000556002600055` | 1 |  0 |  2 |  |  5812 | 5112 | 3012 | 3012 |
| `0x60026000556000600055` | 1 |  2 |  0 |  |  -9188 | -9888 | -11988 | 3012 |
| `0x60026000556003600055` | 1 |  2 |  3 |  |  5812 | 5112 | 3012 | 3012 |
| `0x60026000556001600055` | 1 |  2 |  1 |  |  1612 | 2312 | 212 | 3012 |
| `0x60026000556002600055` | 1 |  2 |  2 |  |  5812 | 5112 | 3012 | 3012 |
| `0x60016000556000600055` | 1 |  1 |  0 |  |  -9188 | -9888 | -11988 | 3012 |
| `0x60016000556002600055` | 1 |  1 |  2 |  |  5812 | 5112 | 3012 | 3012 |
| `0x60016000556001600055` | 1 |  1 |  1 |  |  1612 | 2312 | 212 | 212 |
| `0x600160005560006000556001600055` | 0 |  1 |  0 |  1 |  21618 | 22318 | 20218 | 40118 |
| `0x600060005560016000556000600055` | 1 |  0 |  1 |  0 |  -8382 | -9782 | -11882 | 5918 |

## Security Considerations

TBD

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 26 Feb 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3298</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3298</guid>
      </item>
    
      <item>
        <title>Phase out refunds</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3300-phase-out-refunds/5434</comments>
        
        <description>## Simple Summary
Phases out the `SSTORE` and `SELFDESTRUCT` gas refunds.

## Abstract
This EIP would define a block when the `SSTORE` and `SELFDESTRUCT` refunds would begin to diminish.
The refund would step linearly downward, eroding the implicit value of such refunds at an accelerating pace.

## Motivation
Refunds increase block elasticity, so the block gas target can exceed the number established by miners by up to 2x.
This can cause hesitancy for miners to increase the block gas target.

Refunds, tokenized or not, are valuable to their holders, especially during congestion.
If refunds must be removed, a gradual change in their value would be less-disruptive to the gas market than sudden abolition.
Refund consumption would proceed, especially during periods of congestion, and the refunds would be cleaned up from the state.
Refund creation, driven by demand, would naturally diminish as the efficiency of the refunds fall.
As the refund value approaches the activation cost, the implicit value of the refunds will approach zero, but in periods of congestion they will be cleaned up.

This change is less work for the protocol developers than compensation and cleanup, while likely still achieving cleanup.


## Specification
Parameters:
* `FORK_BLOCK_NUM`: EIP-3300 activation block
* `REFUND_DECAY_STEP`: 1 gas
* `REFUND_DECAY_FREQUENCY`: 100 blocks

Computed:
* `REFUND_DECAY`: `REFUND_DECAY_STEP * ceil((block.number + 1 - FORK_BLOCK_NUM) / REFUND_DECAY_FREQUENCY)`


On the block this EIP activates, and again every `REFUND_DECAY_FREQUENCY` blocks, all gas refunds, including `SELFDESTRUCT` and `SSTORE` would diminish by `REFUND_DECAY_STEP`, until 0.
The current difference is called the `REFUND_DECAY`, which shall be subtracted from each gas refund.

For gas-cost regimes with refund removals that cancel prior refunds, the invariant that the refund counter cannot go negative will be preserved by diminishing the magnitude of those removals by `REFUND_DECAY`, until 0.


### EIP-2929
The refunds as of EIP-2929 are as follows:

* 24000 for SELFDESTRUCT
* `SSTORE_RESET_GAS - SLOAD_GAS` (5000 - 100)
* `SSTORE_SET_GAS - SLOAD_GAS` (20000 - 100)
* `SSTORE_SET_GAS - SLOAD_GAS` (20000 - 100)
* `SSTORE_CLEARS_SCHEDULE` (15000)


Each of these refunds would be decreased by the current `REFUND_DECAY`.

There is also a case where `SSTORE_CLEARS_SCHEDULE` is removed from the refund counter.
That removal will also diminish by `REFUND_DECAY_STEP` until 0, maintaining the non-negative refund counter invariant.


## Rationale
Persisted refunds would become worthless before they fall below their activation cost.
Once the refunds are worthless, they can be removed by another hard fork without waiting for 0.
The rate of diminishing specified would currently require (24000-5000) * 100 = 1,900,000 blocks for `SELFDESTRUCT` and (15000-5000) * 100 = 1,000,000 blocks for `SSTORE`.
This timeframe is currently about a year, which should be enough flexibility for the remaining refunds to be consumed.


## Backwards Compatibility
This proposal breaks gas refunds, which contribute to block elasticity.
The effect of this will be increased gas price volatility: higher highs and lower lows.

Because the refund counter is separate from the gas counter, the block-to-block gas changes will not break `eth_estimateGas`.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 26 Feb 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3300</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3300</guid>
      </item>
    
      <item>
        <title>Account gas storage opcodes</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3322-efficient-gas-storage/5470</comments>
        
        <description>## Simple Summary
Allows contract accounts to store gas that can be transferred to the refund counter.

## Abstract
Contracts can persist gas for later transfer to the refund counter.
Three opcodes are introduced to read, add to, and use this gas counter.

## Motivation
The refund mechanism is currently being used by gas tokens to arbitrage gas price.
This brings gas supply elasticity and price stability by moving gas from blocks with less demand to blocks with more demand.
Unfortunately this rewards unnecessary state growth.
By introducing a superior gas storage mechanism, the gas market will require less storage and computation.

## Specification
Contract accounts gain an unsigned gas refund counter, initially zero.

Three new opcodes are introduced to manage this state.

* `SELFGAS` (`0x49`): Pushes the current account&apos;s gas refund counter onto the stack.
Shares gas pricing with `SELFBALANCE`.
* `USEGAS` (`0x4a`): Pops `amount` from the stack.
The minimum of `amount` and the current account&apos;s gas refund counter is transferred to the execution context&apos;s refund counter.
Costs `5000` gas.
* `STOREGAS` (`0x4b`): Pops `amount` from the stack.
Costs `5000 + amount` gas.
Increases the current account&apos;s gas refund counter by `amount`.

## Rationale
By reusing the execution context&apos;s refund counter we can reuse its 50% DoS protection, which limits its block elasticity contribution to 2x.

The gas costs are based on similar opcodes `SELFBALANCE` and `SSTORE`.

Most accounts will store no gas, so the per-account storage overhead should be minimal or even zero in the normal case.

The opcode numbers chosen are in the same `0x4X` range as `SELFBALANCE` and `GASLIMIT`.

## Backwards Compatibility
Because the gas is added to the refund counter, no compatibility issues are anticipated.

## Test Cases
| Code             | Used Gas | Refund | Original | Final |
|------------------|----------|--------|----------|-------|
| 0x60004900       |     5003 |      0 |        0 |     0 |
| 0x60034900       |     5003 |      2 |        2 |     0 |
| 0x60034900       |     5003 |      3 |        3 |     0 |
| 0x60034900       |     5003 |      3 |        4 |     1 |
| 0x60034960034900 |    10006 |      4 |        4 |     0 |
| 0x60034960034900 |    10006 |      6 |        6 |     0 |
| 0x484900         |     5010 | 100000 |   100000 |     0 |
| 0x61ffff4a00     |    70538 |      0 |        0 | 65535 |


## Security Considerations
DoS is already limited by the 50% refund limit.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 04 Mar 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3322</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3322</guid>
      </item>
    
      <item>
        <title>Wallet Switch Ethereum Chain RPC Method (`wallet_switchEthereumChain`)</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3326-wallet-switchethereumchain</comments>
        
        <description>## Simple Summary

An RPC method for switching the wallet&apos;s active Ethereum chain.

## Abstract

The `wallet_switchEthereumChain` RPC method allows Ethereum applications (&quot;dapps&quot;) to request that the wallet switches its active Ethereum chain, if the wallet has a concept thereof.
The caller must specify a chain ID.
The wallet application may arbitrarily refuse or accept the request.
`null` is returned if the active chain was switched, and an error otherwise.

Important cautions for implementers of this method are included in the [Security Considerations](#security-considerations) section.

## Motivation

All dapps require the user to interact with one or more Ethereum chains in order to function.
Some wallets only supports interacting with one chain at a time.
We call this the wallet&apos;s &quot;active chain&quot;.
`wallet_switchEthereumChain` enables dapps to request that the wallet switches its active chain to whichever one is required by the dapp.
This enables UX improvements for both dapps and wallets.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC-2119](https://www.ietf.org/rfc/rfc2119.txt).

### `wallet_switchEthereumChain`

The method accepts a single object parameter with a `chainId` field.
The method returns `null` if the wallet switched its active chain, and an error otherwise.

The method presupposes that the wallet has a concept of a single &quot;active chain&quot;.
The active chain is defined as the chain that the wallet is forwarding RPC requests to.

#### Parameters

`wallet_switchEthereumChain` accepts a single object parameter, specified by the following TypeScript interface:

```typescript
interface SwitchEthereumChainParameter {
  chainId: string;
}
```

If a field does not meet the requirements of this specification, the wallet **MUST** reject the request.

- `chainId`
  - **MUST** specify the integer ID of the chain as a hexadecimal string, per the [`eth_chainId`](/EIPs/EIPS/eip-695) Ethereum RPC method.
  - The chain ID **MUST** be known to the wallet.
  - The wallet **MUST** be able to switch to the specified chain and service RPC requests to it.

#### Returns

The method **MUST** return `null` if the request was successful, and an error otherwise.

If the wallet does not have a concept of an active chain, the wallet **MUST** reject the request.

### Examples

These examples use JSON-RPC, but the method could be implemented using other RPC protocols.

To switch to Mainnet:

```json
{
  &quot;id&quot;: 1,
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;method&quot;: &quot;wallet_switchEthereumChain&quot;,
  &quot;params&quot;: [
    {
      &quot;chainId&quot;: &quot;0x1&quot;,
    }
  ]
}
```

To switch to the Goerli test chain:

```json
{
  &quot;id&quot;: 1,
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;method&quot;: &quot;wallet_switchEthereumChain&quot;,
  &quot;params&quot;: [
    {
      &quot;chainId&quot;: &quot;0x5&quot;,
    }
  ]
}
```

## Rationale

The purpose `wallet_switchEthereumChain` is to provide dapps with a way of requesting to switch the wallet&apos;s active chain, which they would otherwise have to ask the user to do manually.

The method accepts a single object parameter to allow for future extensibility at virtually no cost to implementers and consumers.

For related work, see [EIP-3085: `wallet_addEthereumChain`](/EIPs/EIPS/eip-3085) and [EIP-2015: `wallet_updateEthereumChain`](/EIPs/EIPS/eip-2015).
`wallet_switchEthereumChain` intentionally forgoes the chain metadata parameters included in those EIPs, since it is purely concerned with switching the active chain, regardless of RPC endpoints or any other metadata associated therewith.

## Security Considerations

For wallets with a concept of an active chain, switching the active chain has significant implications for pending RPC requests and the user&apos;s experience.
If the active chain switches without the user&apos;s awareness, a dapp could induce the user to take actions for unintended chains.

In light of this, the wallet should:

- Display a confirmation whenever a `wallet_switchEthereumChain` is received, clearly identifying the requester and the chain that will be switched to.
  - The confirmation used in [EIP-1102](/EIPs/EIPS/eip-1102) may serve as a point of reference.
- When switching the active chain, cancel all pending RPC requests and chain-specific user confirmations.

### Preserving User Privacy

Automatically rejecting requests for chains that aren&apos;t supported or have yet to be added by the wallet allows requesters to infer which chains are supported by the wallet.
Wallet implementers should consider whether this communication channel violates any security properties of the wallet, and if so, take appropriate steps to mitigate it.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 04 Mar 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3326</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3326</guid>
      </item>
    
      <item>
        <title>MEDGASPRICE Opcode</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/medgasprice-opcode-eip/5480</comments>
        
        <description>## Simple Summary

An opcode for getting the median gas price of the parent block.

## Abstract

Adds `MEDGASPRICE (0x46)` opcode that returns the median gas price for the parent block.

## Motivation

With the emergence of rollups as core mechanisms in scaling Ethereum there are a number of common transactions that can be front-run. Optimistic rollups rely on the submission of fraud proofs to maintain the integrity of their systems. As a result actors submitting fraud proofs typically receive a financial reward for doing so. This opens a trivial front-running strategy of watching the mempool for fraud proof submissions and copying such transactions with a much higher gas price to reap the reward. Such front-runners do not perform validation independently and de-incentivize others from performing validation. Adding a mechanism enforcing an upper bound on gas prices for a transaction could be an effective defense against such front-running attacks.

Consider a smart contract that wants to implement a first come first serve mechanism. Such a mechanism must defeat the inherently pay-to-win nature of the gas price market. Enforcing a maximum gas price for a transaction relies on the fact that transactions of the same gas price are generally processed in a first in first out way by Ethereum miners. A contract currently has few options for setting a max gas price:

- Set a constant value at a reasonable rate given the current gas prices
- Allow an individual or group of individuals to adjust a max gas price over time

More elaborate schemes could likely be constructed but all would involve storing gas price information on chain increasing the number of transactions and costing Ether.

Given a median gas price opcode a contract can set a maximum gas price as a function of the last blocks gas price. This can easily be implemented using a strategy such as the following:

```
// Assume that block.medgasprice is bound to MEDGASPRICE (0x46)

function submitFraudProof(bytes calldata proof) public {
  require(tx.gasprice &lt;= maxGasPrice());
  // process the fraud proof and provide a reward (if valid)
}

function maxGasPrice() public view returns (uint) {
  return 3 * block.medgasprice;
}
```

Given the contract implementation above a client would simply call `maxGasPrice` to determine the gas price to use when submitting a fraud proof. This particular implementation allows up to 3x the median gas price of the last block to be used.

### Forwards Compatibility

[EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) plans to change the fee market in a number of ways. Most notably is the creation of a base fee that is burned. In this context an &quot;inclusion fee&quot; still exists as a part of the total fee. Consider the following two cases:

#### Block sizes are increasing (all available gas is being consumed)

In this case there will be bidding contention in the inclusion fee to incentivize miners to include transactions. A median gas price operator would still be helpful as an attacker could supply a high inclusion fee to bump honest transactions.

#### Block sizes are decreasing (excess gas is available)

In this case an attacker could specify a high inclusion fee to incentivize miners to include their transaction early in the block. Miners are incentivized to do so as including expensive transactions first reduces the risk of a revert (and partial refund) occurring.

Given these two cases this EIP seems relevant in the context of EIP-1559.

Post EIP-1559 `MEDGASPRICE (0x46)` should return the median `effective_gas_price` of the previous block.

[EIP-3198](https://eips.ethereum.org/EIPS/eip-3198) is required for the above strategies to be implemented. With the inclusion of `BASEFEE (0x48)` a contract can subtract the `base_fee_per_gas` from the `effective_gas_price` to determine the inclusion fee per gas being paid for the transaction and thus implement an upper bound.

## Specification

If `block.number &gt;= TBD`, add a new opcode `MEDGASPRICE (0x46)`:

Pushes the median gas price of the parent block onto the stack.

|  Op  	| Input 	| Output 	| Cost 	|
|:----:	|:-----:	|:------:	|:----:	|
| 0x46 	|   0   	|    1   	|   8  	|

## Rationale

Having access to the current gas price economy allows contracts to implement more robust and automated logic surrounding acceptable transaction gas prices.

### Naming note

The name `MEDGASPRICE` was chosen because the median gas price of the network can only be calculated from the latest complete block. Thus transactions being executed should expect the median gas price to be calculated from the previous block.

## Backwards Compatibility

There are no known backwards incompabitility issues.

## Security Considerations

The strategy described for preventing front-running by setting an upper bound on the gas price of transactions has a few caveats:

1. It relies on miners being impartial. Reordering transactions with the same gas price is a trivial means of defeating this strategy.
2. The value returned by `MEDGASPRICE (0x46)` may fluctuate rapidly between blocks. If a transaction is not included immediately it may either fail (if the gas price drops) or become vulnerable to front-running (if the gas price increases).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 05 Mar 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3332</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3332</guid>
      </item>
    
      <item>
        <title>Paged memory allocation for the EVM</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eips-3336-and-3337-improving-the-evms-memory-model/5482</comments>
        
        <description>## Simple Summary
Changes the memory model for the EVM to use pagination.

## Abstract
Presently, the EVM charges for memory as a linear array starting at address 0 and extending to the highest address that has been read from or written to. This suffices for simple uses, but means that compilers have to generate programs that use memory compactly, which leads to wasted gas with reallocation of memory elements, and makes some memory models such as separate heap and stack areas impractical. This EIP proposes changing to a page-based billing model, which adds minimal complexity to implementations, while providing for much more versatility in EVM programs.

## Motivation
Most modern computers implement &quot;virtual memory&quot; for userspace programs, where programs have access to a large address space, with pages of RAM that are allocated as needed by the OS. This allows them to distribute data throughout memory in ways that minimises the amount of reallocation and copying that needs to go on, and permits flexible use of memory for data with different lifetimes. Implementing a simple version of paged memory inside the EVM will provide the same flexibility to compilers targeting the EVM.

## Specification
### Parameters

| Constant | Value |
| - | - |
| `FORK_BLOCK` | TBD |
| `PAGE_BITS` | 10 |
| `PAGE_BASE_COST` | 96 |

For blocks where `block.number &gt;= FORK_BLOCK`, the following changes apply.

### Changes to memory allocation in EVM implementations
Memory is now allocated in pages of `2**PAGE_BITS` bytes each. The most significant `256 - PAGE_BITS` bits of each memory address denote the page number, while the least significant `PAGE_BITS` bits of the memory address denote the location in the page. Pages are initialized to contain all zero bytes and allocated when the first byte from a page is read or written.

EVM implementations are encouraged to store the pagetable as an associative array (eg, hashtable or dict) mapping from page number to an array of bytes for the page.

### Changes to memory expansion gas cost
Presently, the total cost to extend the memory to `a` words long is `Cmem(a) = 3 * a + floor(a ** 2 / 512)`. If the memory is already `b` words long, the incremental cost is `Cmem(a) - Cmem(b)`. `a` is the number of words required to cover the range from memory address 0 to the last word that has been read or written by the EVM.

Under this EIP, we define a new memory cost function, based on the number of allocated pages. This function is `Cmem&apos;(p) = max(PAGE_BASE_COST * (p - 1) + floor(2 * (p - 1) ** 2), 0)`. As above, if the memory already contains `q` pages, the incremental cost is `Cmem&apos;(p) - Cmem&apos;(q)`.

### Changes to `MLOAD` and `MSTORE`
Loading a word from memory or storing a word to memory requires instantiating any pages that it touches that do not already exist, with the resulting gas cost as described above. If the word being loaded or stored resides in a single page, the gas cost remains unchanged at 3 gas. If the word being loaded spans two pages, the cost is 6 gas.

### Changes to other memory-touching opcodes
`CALLDATACOPY`, `CODECOPY`, `EXTCODECOPY`, `CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL`, `CREATE`, `MSTORE8` and any other opcodes that read or write memory are modified as follows:
 - Any page they touch for reading or writing is instantiated if it is not already.
 - Memory expansion gas is charged as described above.

## Rationale
### Memory expansion gas cost
The new gas cost follows the same curve as the previous one, while ensuring that the new gas cost is always less than or equal to the previous cost. This prevents existing programs that make assumptions about memory allocation gas costs from resulting in errors, without unduly discounting memory below what it costs today. Intuitively, a program that uses up to a page boundary pays for one page less than they would under the old model, while a program that uses one word more than a page boundary pays for one word less than they would under the old model.

We believe that this incremental reduction will not have a significant impact on the effective gas limit, as it gets proportionally smaller as programs use more RAM.

### Additional cost for MLOADs and MSTOREs spanning two pages
Loading or storing data spanning two memory pages requires more work from the EVM implementation, which must split the word at the page boundary and update the two (possibly disjoint) pages. Since we cannot guarantee loads and stores in existing EVM programs are page-aligned, we cannot prohibit this behaviour for efficiency. Instead, we propose treating each as two loads or stores for gas accounting purposes. This discourages the use of this functionality, and accounts for the additional execution cost, without prohibiting it outright.

This will result in additional gas costs for any programs that perform these operations. We believe this to be minimal, and hope to do future analysis to confirm this.

## Backwards Compatibility
The new function for memory expansion gas cost is designed specifically to avoid backwards compatibility issues by always charging less than or equal to the amount the current EVM would charge. Under some circumstances existing programs will be charged more for MLOADs and MSTOREs that span page boundaries as described above; we believe these changes will affect a minimum of programs and have only a small impact on their gas consumption.

## Test Cases
TBD

## Security Considerations
Potential CPU DoS issues arising from additional work done under the new model are alleviated by charging more for non-page-aligned reads and writes. Charges for memory expansion asymptotically approach those currently in force, so this change will not permit programs to allocate substantially more memory than they can today.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 06 Mar 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3336</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3336</guid>
      </item>
    
      <item>
        <title>Frame pointer support for memory load and store operations</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eips-3336-and-3337-improving-the-evms-memory-model/5482</comments>
        
        <description>## Simple Summary
Introduces four new opcodes for loading data from and storing data to memory offset by a frame pointer.

## Abstract
This EIP introduces four new opcodes, `MLOADFP`, `MSTOREFP`, `GETFP` and `SETFP` that allow for more efficient memory access offset by a user-controlled quantity called the &quot;frame pointer&quot;. This permits compilers to more efficiently offload ephemeral data such as local variables to memory instead of the EVM&apos;s evaluation stack, which has a number of benefits, including the effective elimination of restrictions on the number of local variables in a function.

## Motivation
In most commonly used VMs, ephemeral data such as local variables, function arguments, and return addresses is stored in a region of memory called the stack. In contrast to the EVM&apos;s evaluation stack, this area of memory is randomly accessible, and thus can store an arbitrary amount of data, which can be referenced from anywhere they remain in scope. Although this model is possible in the current EVM design, it is made difficult by the linear model of memory (addressed in [EIP-3336](/EIPs/EIPS/eip-3336)) and by the lack of opcodes for relative memory access commonly found in other architectures. This EIP proposes new opcodes that permit this form of memory use, without imposing undue burden on EVM implementers or on runtime efficiency.

In the current EVM model, a compiler wishing to use this pattern would have to store the frame pointer - which points to the start or end of the current memory stack frame - in memory, and load it each time they wish to reference it. For example, loading a value from memory offset by the frame pointer would require the following sequence of operations:

| Opcode    | Gas used |
|-----------|----------|
| `PUSHn x` | 3        |
| `PUSH1 0` | 3        |
| `MLOAD`   | 3        |
| `ADD`     | 3        |
| `MLOAD`   | 3        |

This consumes a total of 15 gas, and takes up at least 7 bytes of bytecode each time it is referenced. In contrast, after this EIP, the equivalent sequence of operations is:

| Opcode    | Gas used |
|-----------|----------|
| `PUSH1 x` | 3        |
| `MLOADFP` | 3        |

This consumes only 6 gas, and takes at least 3 bytes of bytecode. The effort required from the EVM implementation is equivalent, costing only one extra addition operation over a regular `MLOAD`. The alternative of storing values on the stack, which requires 3 gas and 1 byte of bytecode for a `DUPn` operation, but it is now at most twice as efficient rather than 5 times as efficient, making storing values in memory a viable alternative.

Likewise, before this EIP a frame-pointer relative store requires the following sequence of operations:
| Opcode    | Gas used |
|-----------|----------|
| `PUSHn x` | 3        |
| `PUSH1 0` | 3        |
| `MLOAD`   | 3        |
| `ADD`     | 3        |
| `MSTORE`  | 3        |

This consumes 15 gas and at least 7 bytes of bytecode. After this EIP, the equivalent sequence of operations is:

| Opcode    | Gas used |
|-----------|----------|
| `PUSHn x` | 3        |
| `MSTOREFP`| 3        |

Consuming only 6 gas and at least 3 bytes of bytecode, while once again only requiring EVM implementations to do one extra addition operation. The alternative of storing values on the stack requires 6 gas and 2 bytes of bytecode for the sequence `SWAPn POP`, making it no more efficient than memory storage.

## Specification
### Parameters

| Constant | Value |
| - | - |
| `FORK_BLOCK` | TBD |

For blocks where `block.number &gt;= FORK_BLOCK`, the following changes apply.

### Frame pointer
A new EVM internal state variable called the &quot;frame pointer&quot; is introduced. This is a signed integer that starts at 0.

### `SETFP` opcode
A new opcode, `SETFP` is introduced with value `0x5c`. This opcode costs `G_low` (3 gas) and takes one argument from the stack. The argument is stored as the new value of the frame pointer.

### `GETFP` opcode
A new opcode, `GETFP` is introduced with value `0x5d`. This opcode costs `G_low` (3 gas) and takes no arguments. It takes the current value of the frame pointer and pushes it to the stack.

### `MLOADFP` opcode
A new opcode `MLOADFP` is introduced with value `0x5e`. This opcode acts in all ways identical to `MLOAD`, except that the value of the frame pointer is added to the address before loading data from memory. An attempt to load data from a negative address should be treated identically to an invalid opcode, consuming all gas and reverting the current execution context.

### `MSTOREFP` opcode
A new opcode `MSTOREFP` is introduced with value `0x5f`. This opcode acts in all ways identical to `MSTORE`, except that the value of the frame pointer is added to the address before storing data to memory. An attempt to store data to a negative address should be treated identically to an invalid opcode, consuming all gas and reverting the current execution context.

## Rationale
### Cost of new opcodes
The cost of the new opcodes `MLOADFP` and `MSTOREFP` reflects the cost of `MLOAD` and `MSTORE`. They are generally equivalent in cost with the exception of an extra addition operation, which imposes negligible cost.

The cost of the new opcodes `SETFP` and `GETFP` is based on other common low-cost opcodes such as `PUSH` and `POP`.

### Absence of `MSTORE8FP`
`MSTORE8FP` opcode was not included because it is expected that it would be used infrequently, and there is a desire to minimise the size of the instruction set and to conserve opcodes for future use.

## Backwards Compatibility
This EIP exclusively introduces new opcodes, and as a result should not impact any existing programs unless they operate under the assumption that these opcodes are undefined, which we believe will not be the case.

## Security Considerations
DoS risks are mitigated by correct pricing of opcodes to reflect current execution costs. No other security considerations pertain to this EIP.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 06 Mar 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3337</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3337</guid>
      </item>
    
      <item>
        <title>Limit account nonce to 2^52</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-2681-limit-account-nonce-to-2-64-1/4324</comments>
        
        <description>## Abstract

Limit account nonce to be between `0` and `2^52`.

## Motivation

Account nonces are currently specified to be arbitrarily long unsigned integers. Dealing with arbitrary length data in the state witnesses is not optimal, therefore this EIP will allow proofs to represent the nonce in a more optimized way.

Additionally it could prove beneficial to transaction formats, where some improvements are potentially sought by at least three other proposals.

Lastly, this facilitates a minor optimisation in clients, because the nonce no longer needs to be kept as a 256-bit number.

## Specification

If `block.number &gt;= FORK_BLOCK` introduce two new restrictions:

1. Consider any transaction invalid, where the nonce exceeds `2^52`.
2. The `CREATE` instruction to abort with an exceptional halt, where the account nonce is `2^52`.

## Rationale

1. It is unlikely for any nonce to reach or exceed the proposed limit. If one would want to reach that limit via external transactions, it would cost at least `21000 * (2^64-1) = 387_381_625_547_900_583_915_000` gas.

2. It must be noted that in the past, in the Morden testnet, each new account had a starting nonce of `2^20` in order to differentiate transactions from mainnet transactions.
This mode of replay protection is out of fashion since [EIP-155](/EIPs/EIPS/eip-155) introduced a more elegant way using chain identifiers.

3. Most clients already consider the nonce field to be 64-bit, such as go-ethereum.

4. All integer values &lt;= 2^52 can be encoded in a 64-bit floating point without any loss of precision, making this value easy to work with in languages that only have floating point number support.

## Backwards Compatibility

While this is a breaking change, no actual effect should be visible:

1. There is no account in the state currently which would have a nonce exceeding that value. As of November 2020, the account `0xea674fdde714fd979de3edf0f56aa9716b898ec8` is responsible for the highest account nonce at approximately 29 million.

## Security Considerations

None.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 07 Mar 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3338</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3338</guid>
      </item>
    
      <item>
        <title>Increase block rewards to 3 ETH, with 2 Year Decay to 1 ETH Scheduled</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3368-block-reward-increase-w-decay-for-next-two-years/5550</comments>
        
        <description>## Simple Summary
Changes the block reward paid to proof-of-work (POW) miners to 3 ETH from existing 2 ETH and starts a decay schedule for next two years to 1 ETH Block Reward.

## Abstract
Set the block reward to 3 ETH and then decrease it slightly every block for 4,724,000 blocks (approximately 2 years) until it reaches 1 ETH.

## Motivation
A sudden drop in PoW mining rewards could result in a sudden precipitous decrease in mining profitability that may drive miners to auction off their hashrate to the highest bidder while they figure out what to do with their now &quot;worthless&quot; hardware. If enough hashrate is auctioned off in this way at the same time, an attacker will be able to rent a large amount of hashing power for a short period of time at relatively low cost vs. reward and potentially attack the network. By setting the block reward to X (where X is enough to offset the sudden profitability decrease) and then decreasing it over time to Y (where Y is a number below the sudden profitability decrease), we both avoid introducing long term inflation while at the same time spreading out the rate that individual miners cross into a transitional range. This approach offers a higher level of confidence and published schedule of yield, while allowing mining participants time to gracefully repurpose/sell their hardware. This greatly increases ethereums PoW security by keeping incentives aligned to ethereum and not being force projected to short term brokerage for the highest bidder. Additionally the decay promotes a known schedule of a deflationary curve, aligning to the overall Minimal Viable Issuance directive aligned to a 2 year transition schedule for Proof of Stake, consensus replacement of Proof of Work. Security is paramount in cryptocurrency blockchains and the risk to a 51% non-resistant chain is real. The scope of Ethereum&apos;s current hashrate has expanded to hundreds of thousands of new participants and over 2.5x original ATH hashrate/difficulty. While the largest by hashrate crypto is bitcoin, ethereum is not far behind the total network size in security aspects. This proposal is focused to keep that superiority in security one of the key aspects.

## Specification
Adjust block, uncle, and nephew rewards
### Constants
* `TRANSITION_START_BLOCK_NUMBER: TBD`
* `TRANSITION_DURATION: 4_724_000` (about two years)
* `TRANSITION_END_BLOCK_NUMBER: FORK_BLOCK_NUMBER + TRANSITION_DURATION`
* `STARTING_REWARD: 3_000_000_000_000_000_000`
* `ENDING_REWARD: 1_000_000_000_000_000_000`
* `REWARD_DELTA: STARTING_REWARD - ENDING_REWARD`
### Block Reward
```py
if block.number &gt;= TRANSITION_END_BLOCK_NUMBER:
    block_reward = ENDING_REWARD
elif block.number = TRANSITION_START_BLOCK_NUMBER:
    block_reward = STARTING_REWARD
elif block.number &gt; TRANSITION_START_BLOCK_NUMBER:
    block_reward = STARTING_REWARD - REWARD_DELTA * TRANSITION_DURATION / (block.number - TRANSITION_START_BLOCK_NUMBER)
```

## Rationale
2 years was chosen because it gives miners sufficient time to find alternative uses for their hardware and/or get their hardware back out onto the open market (e.g., in the form of gaming GPUs) without flooding the market suddenly. This proposal should ONLY be considered as a last resort as something we have in our pocket should the &quot;network need to attract hashing power quickly and then bleed it off over time&quot; rather than &quot;something that is scheduled to be included in X hard fork&quot; ; Recommendation to have in a fast track state, but NOT deployed to mainnet unless needed.

## Backwards Compatibility
There are no known backward compatibility issues with the introduction of this EIP.

## Security Considerations
There are no known security issues with the introduction of this EIP.

## Copyright
Copyright and related rights waived via CC0.
</description>
        <pubDate>Fri, 12 Mar 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3368</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3368</guid>
      </item>
    
      <item>
        <title>5 FNV primes for ethash</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3372-apply-minor-modifications-to-the-ethash-algorithm-to-break-current-asic-implementations-eip-969-resubmission/5655</comments>
        
        <description>## Simple Summary

Introduce 5 new FNV primes into the ethash algorithm.

## Abstract

This EIP is to kick current ASIC implementations out of the network to keep the Ethereum network secure and healthy by changing the `fnv` constants.

## Motivation

ASICs provide a severe centralization risk for the Ethereum network. If we do not get rid of them, small GPU miners will be forced to exit the Ethereum mining because EIP-1559 will make them mining at a loss. Furthermore, ASIC production will be concentrated only at one or two parties, which will make the Ethereum hashrate centralized. Also, it is worth noting that Ethash ASIC machines cost 10k+ USD, while GPUs are priced less than 1000 USD.

With GPUs, miners can switch to other mining algorithms, but with ASICs, it is impossible. Leaving everything as-is will almost certainly a very tough (from the side of miners) integration of the Ethereum 2.0.

In short, this EIP is required to keep the Ethereum network stable and decentralized by keeping the ASIC business away.

## Specification

If `block.number &gt;= ETHASH11_BLKNUM`, activate the `ethash1.1` algorithm version.

### ethash1.1

Prior to this change, `fnv` hash function is used throughout the `hashimoto` function. `fnv` is identical for all steps, `ethash1.1` will introduce additional `fnvA`, `fnvB`, `fnvC`, `fnvD`, and `fnvE` functions. All those functions will have different FNV constants.

```
// Previously used FNV prime
#define FNV_PRIME_0 0x1000193

// New FNV primes
#define FNV_PRIME_A 0x10001a7
#define FNV_PRIME_B 0x10001ab
#define FNV_PRIME_C 0x10001cf
#define FNV_PRIME_D 0x10001e3
#define FNV_PRIME_E 0x10001f9
```

Prior to this EIP, all parts of Ethash are using the `fnv` (hereinafter referenced as `fnv0`) function.  As of the introduction of this EIP:
* `fnvA` replaces `fnv0` in the DAG item selection step
* `fnvB` replaces `fnv0` in the DAG item mix step
* `fnvC(fnvD(fnvE` replaces `fnv0(fnv0(fnv0(` in the compress mix step
* `fnv0` in the DAG generation step should remain unchanged.

## Rationale

ASIC Miners have become a threat to the future of Ethereum and a hard fork is required to remove them from the network before additional damage is caused. EIP-3372 proposes the minimum necessary to do so and will not affect ETH stakeholders or the network like Ethash 2.0 would. The threat ASICs pose is legal, social, moral, technical, monetary, and environmental. As we continue to come closer to the merge ASICs will attack the network and the developers personally as they have done in the past because miners will always pursue profits.

Legally and socially ASIC&apos;s have previously been a threat and a nuisance. As Hudson describes Linzhi attacked the EF and developers personally seeking to spread lies and misinformation while sending legal threats during discussions around EIP-1057. His account is [here](https://github.com/Souptacular/linzhi) and in his own words

&gt; ASIC manufacturer Linzhi has both pressured me and told lies

With their attacks and harassment on staff demonstrated in the below image:
![](upload://n8TJsS8hEEH4DXYJ2WDzblm5qJo.jpeg)

Socially and morally the Ethereum community must adopt a no-tolerance policy towards personal attacks on its developers. It is only because of the core developers that Ethereum has value, the community cannot allow large companies free reign to attack them personally and must seek to protect each developer as they are a resource that keeps Ethereum viable. Multiple developers were &quot;burned&quot; during this event. As we accelerate the merge, it is likely that ASIC companies will repeat their actions and again attack the developers personally while pursuing legal options. This is seen not only by their actions during EIP-1057 but recent discussion around EIP-969 where legal threats from them caused the champion of that EIP to dropout and forcing me to submit this EIP anonymously. Ethereum cannot allow its actors to be threatened without consequence and this is a fight that must happen now while they are weak rather than pre-merge where they are stronger which will result in a delayed merge and hurt the value of Ethereum.

ASICs have the greatest incentives and resources to commit bad acts because they are centralized in farms this is why Vitalik designed ETH to be ASIC-resistant because ASICs had ruined BTC&apos;s principles of decentralization. Each day their power and control over the network grows. ASICs are against the founding principles of Ethereum which promotes a decentralized system run by common people, not a single owner of large warehouses. F2Pool which consists largely of ASIC farms has become the #3 largest pool controlling around 10% of hashrate. Their farms can be viewed on their webpage. In November 2020 they were 23TH/s yet today they are 45.6 TH/s. That&apos;s a doubling in 4 months and their growth is accelerating as additional ASICs come online. ASICs are becoming a threat that will soon dominate the network and action must be taken now to head them off.

ASICs on F2Pool have long been known to be &quot;bad actors&quot; on the BTC network. They are known for market manipulation and dumping BTC to manipulate prices (I could not post the source link as this is a new account). What will these ASICs do once they find out that they are about to lose millions prior to the merge? Ethereum is not just a network it is a community and they will use their financial resources and pour millions into delaying the merge as they launch legal case after legal case. They will attack the developers and the community as they seek to squeeze every last dollar. 

The reason Ethereum was founded on the principle of being anti-ASIC is because Vitalik had seen the damage ASICs had caused to the BTC network as they pursued profits rather than the betterment of the network. GPU miners are decentralized and disorganized which makes them a much lower threat than warehouses under one central corporation that is outside the legal system and thus cannot be held to account for bad acts.

EIP-3372 also works to protect the environment. Post merge, gpus will go into the secondary market or move to other coins. However, ASICs will become junk. As more ASICs are produced, Ethereum increases its environmental footprint. These ASICs are being mass produced in greater numbers despite it being public that the merge is being accelerated. It is clear that these ASIC manufacturers and buyers must either be ignorant of the accelerated merge or plan to delay it. Because they dump their ETH they have no stake in the network except the money they can squeeze from it and if by making trouble they can give themselves another day than they will do it.

Finally, Ethereum has always sought to pursue &quot;minimum issuance&quot;. By reducing the amount of miners that can pose a threat to the network, Ethereum also decreases how much it needs to pay for protection. Some EIP&apos;s are being prepared to increase miner incomes post EIP-1559 should a threat appear. EIP-3372 eliminates the need to pay more for security and allows miners to be paid less without compromising the network&apos;s security. As we go forward closer to the merge, the community must reduce attack vectors so as to reduce the cost of the merge itself and maximize the security of the network. The community already pays too much for protection and by reducing threats we can reduce this cost. ASIC warehouse farms are dumping all the ETH they make which is suppressing the price of ETH. Although rare, several individual GPU miners are taking part in staking or have gone on to join the community in development or our financial endeavors. They thus are more valuable to the community than a warehouse of future junk. There is no need for the Ethereum community to continue to pay for soon-to-be obsolete hardware that will end up in landfills.

### Technical Overview

Ethash 1.1 will replace the only FNV prime with five new primes at the stage of the hash computation. The prime used for the DAG generation is remained unchanged, while all others are be changed. This will not prevent ASIC companies from creating new ASICs that adapt but so close to the merge it is unlikely they will do so, and even if they do they are unlikely to be able to produce enough to again be a threat.
The choice of FNV constants are based on the formal specification that is available on [https://tools.ietf.org/html/draft-eastlake-fnv-14#section-2.1](https://ietf)

We apologize for the delay in submitting the justification for this EIP. As the community may or may not be aware, the original champion was forced to stop working on this EIP due to legal attacks from ASIC companies. It has taken us this long to review his work and find a new champion. To protect ourselves we are submitting this anonymously and would request the community&apos;s aid in our endeavor to maintain our anonymity and some lenience given the circumstances and threats we face pursuing this EIP.

## Backwards Compatibility

Mining hardware that is optimized for ethash may no longer work if the `fnv` constants are baked into the hardware and cannot be changed.

## Test Vectors

```json
{
  &quot;first&quot;: {
    &quot;nonce&quot;: &quot;4242424242424242&quot;,
    &quot;mixHash&quot;: &quot;aa6a928db9b548ebf20fc9a74e9200321426f1c2db1571636cdd3a33eb162b36&quot;,
    &quot;header&quot;: &quot;f901f3a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a09178d0f23c965d81f0834a4c72c6253ce6830f4022b1359aaebfc1ecba442d4ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080830f4240808080a058f759ede17a706c93f13030328bcea40c1d1341fb26f2facd21ceb0dae57017884242424242424242&quot;,
    &quot;seed&quot;: &quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,
    &quot;result&quot;: &quot;3972318778d2af9d3c5c3dfc463bc2a5ebeebd1a7a04392708ff94d29aa18c5f&quot;,
    &quot;cache_size&quot;: 16776896,
    &quot;full_size&quot;: 1073739904,
    &quot;header_hash&quot;: &quot;2a8de2adf89af77358250bf908bf04ba94a6e8c3ba87775564a41d269a05e4ce&quot;,
    &quot;cache_hash&quot;: &quot;35ded12eecf2ce2e8da2e15c06d463aae9b84cb2530a00b932e4bbc484cde353&quot;
  },
  &quot;second&quot;: {
    &quot;nonce&quot;: &quot;307692cf71b12f6d&quot;,
    &quot;mixHash&quot;: &quot;4a2ef8287dc21f5def0d4e9694208c56e574b1692d7b254822a3f4704d8ad1ba&quot;,
    &quot;header&quot;: &quot;f901f7a01bef91439a3e070a6586851c11e6fd79bbbea074b2b836727b8e75c7d4a6b698a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794ea3cb5f94fa2ddd52ec6dd6eb75cf824f4058ca1a00c6e51346be0670ce63ac5f05324e27d20b180146269c5aab844d09a2b108c64a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302004002832fefd880845511ed2a80a0e55d02c555a7969361cf74a9ec6211d8c14e4517930a00442f171bdb1698d17588307692cf71b12f6d&quot;,
    &quot;seed&quot;: &quot;0000000000000000000000000000000000000000000000000000000000000000&quot;,
    &quot;result&quot;: &quot;5ab98957ba5520d4e367080f442e37a047cfd9d2857b6e00dd12d82900d108a6&quot;,
    &quot;cache_size&quot;: 16776896,
    &quot;full_size&quot;: 1073739904,
    &quot;header_hash&quot;: &quot;100cbec5e5ef82991290d0d93d758f19082e71f234cf479192a8b94df6da6bfe&quot;,
    &quot;cache_hash&quot;: &quot;35ded12eecf2ce2e8da2e15c06d463aae9b84cb2530a00b932e4bbc484cde353&quot;
  }
}
```

## Security Considerations

There are no known security issues with this change.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 13 Mar 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3372</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3372</guid>
      </item>
    
      <item>
        <title>Predictable Proof-of-Work (POW) Sunsetting</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3374-predictable-proof-of-work-sunsetting</comments>
        
        <description>## Simple Summary
Sets block reward to 3 and reduces it to 1 linearly over the course of about 1 year.

## Abstract
Sets the block reward to 3 ETH and then incrementally decreases it every block for 2,362,000 blocks (approximately 1 year) until it reaches 1 ETH.

## Motivation
Unnecessarily abrupt changes to the Ethereum ecosystem cause disruption and disharmony resulting in the disenfranchisement of community members while undermining stability and confidence.  While moves from Proof-of-Work to Proof-of-Stake will undoubtedly cause friction between those community members vested in either, all benefit from a measured, predictable transition.

This proposal:

1) Is issuance neutral over 1 year, and reduces issuance beyond that.
2) Sets an initial block reward of 3;
3) Introduces an ongoing, predictable reduction in future mining rewards down to 1, effectively &quot;sunsetting&quot; POW and codifying the move to POS;
4) Reduces economic incentives for continued development of ASICs;
5) Allows the impacts of decreasing miner rewards to be measured and monitored rather than relying on conjecture and game theory, so adjustments can be made if necessary.


## Specification
### Constants
* `TRANSITION_START_BLOCK_NUMBER: TBD`
* `TRANSITION_DURATION: 2_362_000` // (about one year)
* `TRANSITION_END_BLOCK_NUMBER: FORK_BLOCK_NUMBER + TRANSITION_DURATION`
* `STARTING_REWARD: 3_000_000_000_000_000_000`
* `ENDING_REWARD: 1_000_000_000_000_000_000`
* `REWARD_DELTA: STARTING_REWARD - ENDING_REWARD`
### Block Reward
```py
if block.number &gt;= TRANSITION_END_BLOCK_NUMBER:
    block_reward = ENDING_REWARD
elif block.number == TRANSITION_START_BLOCK_NUMBER:
    block_reward = STARTING_REWARD
elif block.number &gt; TRANSITION_START_BLOCK_NUMBER:
    block_reward = STARTING_REWARD - REWARD_DELTA * TRANSITION_DURATION / (block.number - TRANSITION_START_BLOCK_NUMBER)
```

## Rationale
Picking starting and ending block reward values that are equidistant from the current block reward rate of 2 ensures the impact of this EIP will be issuance neutral over the one year time frame.  Temporarily raising the block reward to 3 blunts the initial impact of a sudden miner revenue decrease and the continual reductions thereafter codify Ethereum&apos;s move to POS by increasingly disincentivizing POW.  Importantly, this approach moderates the rate of change so impacts and threats can be measured and monitored.

## Backwards Compatibility
There are no known backward compatibility issues with the introduction of this EIP.

## Security Considerations
There are no known security issues with the introduction of this EIP.

## Copyright
Copyright and related rights waived via CC0.
</description>
        <pubDate>Sat, 13 Mar 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3374</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3374</guid>
      </item>
    
      <item>
        <title>Hardcoded Block Gas Limit</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3382-hardcoded-gas-limit</comments>
        
        <description>## Simple Summary

Hardcode the block gas limit to `12,500,000` gas per block.

## Abstract

Updates the block validation rules such that a block is invalid if the `gas_limit` header field is not equal to `12,500,000`.

## Motivation

Both Ethereum&apos;s Proof of Work and Proof of Stake designs assume that block producers are financially rational, but does not assume block producers to be benevolent. There is one exception however, and it is when block producers choose the gas limit of a block where it is assumed that block producers care about the long term health and decentralisation of the chain. Indeed, the block gas limit is one of the only parameters in Ethereum that is not dictated by node consensus, but instead is chosen by block producers. This decision was initially made to allow urgent changes in the block gas limit if necessary. Both drastically increasing or decreasing this parameter could have serious consequences that may not be desired. It is therefore a critical parameter that should require node consensus to avoid any sudden harmful change imposed by a small number of actors on the rest of the network.

## Specification
Refer to `gasLimit` as `gasTarget` post EIP-1559.

### Added Consensus Constraint

As of `FORK_BLOCK_NUMBER`, the `header.gasLimit` **MUST** be equal to `BLOCK_GAS_LIMIT`, where `BLOCK_GAS_LIMIT` is a hardcoded constant set to `12,500,000`.

## Rationale

### Keeping gasLimit in Block Headers

While it would be possible to remove the `gasLimit` field from block headers, it would change the data structure to be hashed, which could lead to unintended consequences. It is therefore easier to leave the gasLimit as part of block headers. 

### Chosen Gas Limit

The `12,500,000` value is being proposed as it&apos;s the current block gas limit as of time of writing this EIP. The actual amount could be altered with a subsequent EIP to avoid deviating from the core intent of this EIP.

## Backwards Compatibility

This EIP is backward compatible.

## Security Considerations
Rapid changes to the gas limit will likely be more difficult to execute, which could be problematic if an urgent situation arise that required changing the gas limit.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 13 Mar 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3382</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3382</guid>
      </item>
    
      <item>
        <title>ERC-721 and ERC-1155 to ERC-20 Wrapper</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/3384</comments>
        
        <description>## Simple Summary
A standard interface for contracts that create generic ERC-20 tokens which derive from a pool of unique ERC-721/ERC-1155 tokens.

## Abstract

This standard outlines a smart contract interface to wrap identifiable tokens with fungible tokens. This allows for derivative [ERC-20](/EIPs/EIPS/eip-20) tokens to be minted by locking the base [ERC-721](/EIPs/EIPS/eip-721) non-fungible tokens and [ERC-1155](/EIPs/EIPS/eip-1155) multi tokens into a pool. The derivative tokens can be burned to redeem base tokens out of the pool. These derivatives have no reference to the unique id of these base tokens, and should have a proportional rate of exchange with the base tokens. As representatives of the base tokens, these generic derivative tokens can be traded and otherwise utilized according to ERC-20, such that the unique identifier of each base token is irrelevant.

ERC-721 and ERC-1155 tokens are considered valid base, tokens because they have unique identifiers and are transferred according to similar rules. This allows for both ERC-721 NFTs and ERC-1155 Multi-Tokens to be wrapped under a single common interface.

## Motivation

The ERC-20 token standard is the most widespread and liquid token standard on Ethereum. ERC-721 and ERC-1155 tokens on the other hand can only be transferred by their individual ids, in whole amounts. Derivative tokens allow for exposure to the base asset while benefiting from contracts which utilize ERC-20 tokens. This allows for the base tokens to be fractionalized, traded and pooled generically on AMMs, collateralized, and be used for any other ERC-20 type contract. Several implementations of this proposal already exist without a common standard.

Given a fixed exchange rate between base and derivative tokens, the value of the derivative token is proportional to the floor price of the pooled tokens. With the derivative tokens being used in AMMs, there is opportunity for arbitrage between derived token markets and the base NFT markets. By specifying a subset of base tokens which may be pooled, the difference between the lowest and highest value token in the pool may be minimized. This allows for higher value tokens within a larger set to be poolable. Additionally, price calculations using methods such as Dutch auctions, as implemented by NFT20, allow for price discovery of subclasses of base tokens. This allows the provider of a higher value base token to receive a proportionally larger number of derivative tokens than a token worth the floor price would receive.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt).

**Every IWrapper compliant contract must implement the `IWrapper` and `ERC165` interfaces** :


```solidity
pragma solidity ^0.8.0;

/**
    @title IWrapper Identifiable Token Wrapper Standard
    @dev {Wrapper} refers to any contract implementing this interface.
    @dev {Base} refers to any ERC-721 or ERC-1155 contract. It MAY be the {Wrapper}.
    @dev {Pool} refers to the contract which holds the {Base} tokens. It MAY be the {Wrapper}.
    @dev {Derivative} refers to the ERC-20 contract which is minted/burned by the {Wrapper}. It MAY be the {Wrapper}.
    @dev All uses of &quot;single&quot;, &quot;batch&quot; refer to the number of token ids. This includes individual ERC-721 tokens by id, and multiple ERC-1155 by id. An ERC-1155 `TransferSingle` event may emit with a `value` greater than `1`, but it is still considered a single token.
    @dev All parameters named `_amount`, `_amounts` refer to the `value` parameters in ERC-1155. When using this interface with ERC-721, `_amount` MUST be 1, and `_amounts` MUST be either an empty list or a list of 1 with the same length as `_ids`.
*/
interface IWrapper /* is ERC165 */ {
    /**
     * @dev MUST emit when a mint occurs where a single {Base} token is received by the {Pool}.
     * The `_from` argument MUST be the address of the account that sent the {Base} token.
     * The `_to` argument MUST be the address of the account that received the {Derivative} token(s).
     * The `_id` argument MUST be the id of the {Base} token transferred.
     * The `_amount` argument MUST be the number of {Base} tokens transferred.
     * The `_value` argument MUST be the number of {Derivative} tokens minted.
     */
    event MintSingle (address indexed _from, address indexed _to, uint256 _id, uint256 _amount, uint256 _value);

    /**
     * @dev MUST emit when a mint occurs where multiple {Base} tokens are received by the {Wrapper}.
     * The `_from` argument MUST be the address of the account that sent the {Base} tokens.
     * The `_to` argument MUST be the address of the account that received the {Derivative} token(s).
     * The `_ids` argument MUST be the list ids of the {Base} tokens transferred.
     * The `_amounts` argument MUST be the list of the numbers of {Base} tokens transferred.
     * The `_value` argument MUST be the number of {Derivative} tokens minted.
     */
    event MintBatch (address indexed _from, address indexed _to, uint256[] _ids, uint256[] _amounts, uint256 _value);

    /**
     * @dev MUST emit when a burn occurs where a single {Base} token is sent by the {Wrapper}.
     * The `_from` argument MUST be the address of the account that sent the {Derivative} token(s).
     * The `_to` argument MUST be the address of the account that received the {Base} token.
     * The `_id` argument MUST be the id of the {Base} token transferred.
     * The `_amount` argument MUST be the number of {Base} tokens transferred.
     * The `_value` argument MUST be the number of {Derivative} tokens burned.
     */
    event BurnSingle (address indexed _from, address indexed _to, uint256 _id, uint256 _amount, uint256 _value);

    /**
     * @dev MUST emit when a mint occurs where multiple {Base} tokens are sent by the {Wrapper}.
     * The `_from` argument MUST be the address of the account that sent the {Derivative} token(s).
     * The `_to` argument MUST be the address of the account that received the {Base} tokens.
     * The `_ids` argument MUST be the list of ids of the {Base} tokens transferred.
     * The `_amounts` argument MUST be the list of the numbers of {Base} tokens transferred.
     * The `_value` argument MUST be the number of {Derivative} tokens burned.
     */
    event BurnBatch (address indexed _from, address indexed _to, uint256[] _ids, uint256[] _amounts, uint256 _value);

    /**
     * @notice Transfers the {Base} token with `_id` from `msg.sender` to the {Pool} and mints {Derivative} token(s) to `_to`.
     * @param _to       Target address.
     * @param _id       Id of the {Base} token.
     * @param _amount   Amount of the {Base} token.
     *
     * Emits a {MintSingle} event.
     */
    function mint(
        address _to,
        uint256 _id,
        uint256 _amount
    ) external;

    /**
     * @notice Transfers `_amounts[i]` of the {Base} tokens with `_ids[i]` from `msg.sender` to the {Pool} and mints {Derivative} token(s) to `_to`.
     * @param _to       Target address.
     * @param _ids      Ids of the {Base} tokens.
     * @param _amounts  Amounts of the {Base} tokens.
     *
     * Emits a {MintBatch} event.
     */
    function batchMint(
        address _to,
        uint256[] calldata _ids,
        uint256[] calldata _amounts
    ) external;

    /**
     * @notice Burns {Derivative} token(s) from `_from` and transfers `_amounts` of some {Base} token from the {Pool} to `_to`. No guarantees are made as to what token is withdrawn.
     * @param _from     Source address.
     * @param _to       Target address.
     * @param _amount   Amount of the {Base} tokens.
     *
     * Emits either a {BurnSingle} or {BurnBatch} event.
     */
    function burn(
        address _from,
        address _to,
        uint256 _amount
    ) external;

    /**
     * @notice Burns {Derivative} token(s) from `_from` and transfers `_amounts` of some {Base} tokens from the {Pool} to `_to`. No guarantees are made as to what tokens are withdrawn.
     * @param _from     Source address.
     * @param _to       Target address.
     * @param _amounts  Amounts of the {Base} tokens.
     *
     * Emits either a {BurnSingle} or {BurnBatch} event.
     */
    function batchBurn(
        address _from,
        address _to,
        uint256[] calldata _amounts
    ) external;

    /**
     * @notice Burns {Derivative} token(s) from `_from` and transfers `_amounts[i]` of the {Base} tokens with `_ids[i]` from the {Pool} to `_to`.
     * @param _from     Source address.
     * @param _to       Target address.
     * @param _id       Id of the {Base} token.
     * @param _amount   Amount of the {Base} token.
     *
     * Emits either a {BurnSingle} or {BurnBatch} event.
     */
    function idBurn(
        address _from,
        address _to,
        uint256 _id,
        uint256 _amount
    ) external;

    /**
     * @notice Burns {Derivative} tokens from `_from` and transfers `_amounts[i]` of the {Base} tokens with `_ids[i]` from the {Pool} to `_to`.
     * @param _from     Source address.
     * @param _to       Target address.
     * @param _ids      Ids of the {Base} tokens.
     * @param _amounts   Amounts of the {Base} tokens.
     *
     * Emits either a {BurnSingle} or {BurnBatch} event.
     */
    function batchIdBurn(
        address _from,
        address _to,
        uint256[] calldata _ids,
        uint256[] calldata _amounts
    ) external;
}
```

## Rationale

### Naming

The ERC-721/ERC-1155 tokens which are pooled are called {Base} tokens. Alternative names include:
- Underlying.
- NFT. However, ERC-1155 tokens may be considered &quot;semi-fungible&quot;.

The ERC-20 tokens which are minted/burned are called {Derivative} tokens. Alternative names include:
- Wrapped.
- Generic.

The function names `mint` and `burn` are borrowed from the minting and burning extensions to ERC-20. Alternative names include:
- `mint`/`redeem` ([NFTX](https://nftx.org))
- `deposit`/`withdraw` ([WrappedKitties](https://wrappedkitties.com/))
- `wrap`/`unwrap` ([MoonCatsWrapped](https://etherscan.io/address/0x7c40c393dc0f283f318791d746d894ddd3693572))

The function names `*idBurn` are chosen to reduce confusion on what is being burned. That is, the {Derivative} tokens are burned in order to redeem the id(s).

The wrapper/pool itself can be called an &quot;Index fund&quot; according to NFTX, or a &quot;DEX&quot; according to [NFT20](https://nft20.io). However, the {NFT20Pair} contract allows for direct NFT-NFT swaps which are out of the scope of this standard.

### Minting
Minting requires the transfer of the {Base} tokens into the {Pool} in exchange for {Derivative} tokens. The {Base} tokens deposited in this way MUST NOT be transferred again except through the burning functions. This ensures the value of the {Derivative} tokens is representative of the value of the {Base} tokens.

Alternatively to transferring the {Base} tokens into the {Pool}, the tokens may be locked as collateral in exchange for {Derivative} loans, as proposed in NFTX litepaper, similarly to Maker vaults. This still follows the general minting pattern of removing transferability of the {Base} tokens in exchange for {Derivative} tokens.

### Burning
Burning requires the transfer of {Base} tokens out of the {Pool} in exchange for burning {Derivative} tokens. The burn functions are distinguished by the quantity and quality of {Base} tokens redeemed. 
- For burning without specifying the `id`: `burn`, `batchBurn`.
- For burning with specifying the `id`(s): `idBurn`, `batchIdBurn`.

By allowing for specific ids to be targeted, higher value {Base} tokens may be selected out of the pool. NFTX proposes an additional fee to be applied for such targeted withdrawals, to offset the desire to drain the {Pool} of {Base} tokens worth more than the floor price.

### Pricing
Prices should not be necessarily fixed. therefore, Mint/Burn events MUST include the ERC-20 `_value` minted/burned.

Existing pricing implementations are as follows (measured in base:derivative):
- Equal: Every {Base} costs 1 {Derivative}
    - NFTX
    - Wrapped Kitties
- Proportional
    - NFT20 sets a fixed rate of 100 {Base} tokens per {Derivative} token.
- Variable
    - NFT20 also allows for Dutch auctions when minting.
    - NFTX proposes an additional fee to be paid when targeting the id of the {Base} token.

Due to the variety of pricing implementations, the Mint\* and Burn\* events MUST include the number {Derivative} tokens minted/burned.

### Inheritance
#### ERC-20
The {Wrapper} MAY inherit from {ERC20}, in order to directly call `super.mint` and `super.burn`.
If the {Wrapper} does not inherit from {ERC20}, the {Derivative} contract MUST be limited such that the {Wrapper} has the sole power to `mint`, `burn`, and otherwise change the supply of tokens.

#### ERC721Receiver, ERC1155Receiver
If not inheriting from {ERC721Receiver} and/or {ERC1155Receiver}, the pool MUST be limited such that the base tokens can only be transferred via the Wrapper&apos;s `mint`, `burn`.

There exists only one of each ERC-721 token of with a given (address, id) pair. However, ERC-1155 tokens of a given (address, id) may have quantities greater than 1. Accordingly, the meaning of &quot;Single&quot; and &quot;Batch&quot; in each standard varies. In both standards, &quot;single&quot; refers to a single id, and &quot;batch&quot; refers to multiple ids. In ERC-1155, a single id event/function may involve multiple tokens, according to the `value` field.

In building a common set of events and functions, we must be aware of these differences in implementation. The current implementation treats ERC-721 tokens as a special case where, in reference to the quantity of each {Base} token:
- All parameters named `_amount`, MUST be `1`.
- All parameters named `_amounts` MUST be either an empty list or a list of `1` with the same length as `_ids`.

This keeps a consistent enumeration of tokens along with ERC-1155. Alternative implementations include:
- A common interface with specialized functions. EX: `mintFromERC721`.
- Separate interfaces for each type. EX: `ERC721Wrapper`, `ERC1155Wrapper`.

#### ERC721, ERC1155
The {Wrapper} MAY inherit from {ERC721} and/or {ERC1155} in order to call `super.mint`, directly. This is optional as minting {Base} tokens is not required in this standard. An &quot;Initial NFT Offering&quot; could use this to create a set of {Base} tokens within the contract, and directly distribute {Derivative} tokens.

If the {Wrapper} does not inherit from {ERC721} or {ERC1155}, it MUST include calls to {IERC721} and {IERC1155} in order to transfer {Base} tokens.

### Approval
All of the underlying transfer methods are not tied to the {Wrapper}, but rather call the ERC-20/721/1155 transfer methods. Implementations of this standard MUST:
- Either implement {Derivative} transfer approval for burning, and {Base} transfer approval for minting.
- Or check for Approval outside of the {Wrapper} through {IERC721} / {IERC1155} before attempting to execute.

## Backwards Compatibility
Most existing implementations inherit from ERC-20, using functions `mint` and `burn`.
Events:
- Mint
    - WK: DepositKittyAndMintToken
    - NFTX: Mint

- Burn
    - WK: BurnTokenAndWithdrawKity
    - NFTX: Redeem

## Reference Implementation
[ERC-3386 Reference Implementation](https://github.com/ashrowz/erc-3386)

## Security Considerations
Wrapper contracts are RECOMMENDED to inherit from burnable ERC-20 tokens. If they are not, the supply of the {Derivative} tokens MUST be controlled by the Wrapper. Similarly, price implementations MUST ensure that the supply of {Base} tokens is reflected by the {Derivative} tokens.

With the functions `idBurn`, `idBurns`, users may target the most valuable NFT within the generic lot.  If there is a significant difference between tokens values of different ids, the contract SHOULD consider creating specialized pools (NFTX) or pricing (NFT20) to account for this.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 12 Mar 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3386</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3386</guid>
      </item>
    
      <item>
        <title>Partial removal of refunds</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3298-removal-of-refunds/5430</comments>
        
        <description>## Simple Summary

Remove gas refunds for SELFDESTRUCT, and restrict gas refunds for SSTORE to one specific case.

## Motivation

Gas refunds for SSTORE and SELFDESTRUCT were originally introduced to motivate application developers to write applications that practice &quot;good state hygiene&quot;, clearing storage slots and contracts that are no longer needed. However, they are not widely used for this, and poor state hygiene continues to be the norm. It is now widely accepted that the only solution to state growth is some form of statelessness or state expiry, and if such a solution is implemented, then disused storage slots and contracts would start to be ignored automatically.

Gas refunds additionally have multiple harmful consequences:

* Refunds give rise to GasToken. GasToken has benefits in moving gas space from low-fee periods to high-fee periods, but it also has downsides to the network, particularly in exacerbating state size (as state slots are effectively used as a &quot;battery&quot; to save up gas) and inefficiently clogging blockchain gas usage
* Refunds increase block size variance. The theoretical maximum amount of actual gas consumed in a block is nearly twice the on-paper gas limit (as refunds add gas space for subsequent transactions in a block, though refunds are capped at 50% of a transaction&apos;s gas used). This is not fatal, but is still undesirable, especially given that refunds can be used to maintain 2x usage spikes for far longer than EIP 1559 can.

### The mutex usecase

There are two typical ways to implement mutexes: &apos;0-1-0&apos; and &apos;1-2-1. Let&apos;s see how they differ

- &apos;0-1-0&apos;:
  - Istanbul: 1612
  - Berlin: 212
  - NoRefund: 20112
  - EIP-3403: 1112
- &apos;1-2-1&apos;:
  - Istanbul: 1612
  - Berlin: 212
  - NoRefund: 3012
  - EIP-3403: 3012


**Note**: In reality, there are never a negative gas cost, since the refund is capped at 0.5 * gasUsed. 
However, these tables show the negative values, since a more real-world scenario would likely spend the 
extra gas on other operations.&apos;

## Specification

### Parameters

| Constant | Value |
| - | - |
| `FORK_BLOCK` | TBD |
| `SSTORE_REFUND_GAS` | 19000 |

For blocks where `block.number &gt;= FORK_BLOCK`, the following changes apply.

1. Remove the `SELFDESTRUCT` refund.
2. Remove the `SSTORE` refund in all cases except for one specific case: if the _new value_ and _original value_ of the storage slot both equal 0 but the _current value_ does not (those terms being defined as in [EIP-1283](https://eips.ethereum.org/EIPS/eip-1283)), refund `SSTORE_REFUND_GAS` gas.

## Rationale

Preserving refunds in the `new = original = 0 != current` case ensures that a few key use cases that deserve favorable gas cost treatment continue to receive favorable gas cost treatment, particularly:

* Anti-reentrancy locks (typically flipped from 0 to 1 right before a child call begins, and then flipped back to 0 when the child call ends)
* ERC20 approve-and-send (the &quot;approved value&quot; goes from zero to nonzero when the token transfer is approved, and then back to zero when the token transfer processes)

It also preserves two key goals of EIP 3298:

1. Gas tokens continue to be non-viable, because each 19000 refund is only possible because of 19000 extra gas that was paid for flipping that storage slot from zero to nonzero earlier in the same transaction, so you can&apos;t clear some storage slots and use that saved gas to fill others.
2. The total amount of gas _spent on execution_ is capped at the gas limit. Every 19000 refund for flipping a storage slot non from zero -&gt; zero is only possible because of 19000 extra gas paid for flipping that slot from zero -&gt; nonzero earlier in the same transaction; that gas paid for a storage write and expansion that were both reverted and so do not actually need to be applied to the Merkle tree. Hence, this extra gas does not contribute to risk.

## Backwards Compatibility

Refunds are currently only applied _after_ transaction execution, so they cannot affect how much gas is available to any particular call frame during execution. Hence, removing them will not break the ability of any code to execute, though it will render some applications economically nonviable.

Gas tokens in particular will become valueless. DeFi arbitrage bots, which today frequently use either established gas token schemes or a custom alternative to reduce on-chain costs, would benefit from rewriting their code to remove calls to these no-longer-functional gas storage mechanisms.

## Test Cases

### 2929 Gas Costs

Note, there is a difference between &apos;hot&apos; and &apos;cold&apos; slots. This table shows the values as of [EIP-2929](/EIPs/EIPS/eip-2929) assuming that all touched storage slots were already &apos;hot&apos; (the difference being a one-time cost of `2100` gas).

| Code | Used Gas | Refund | Original | 1st | 2nd | 3rd | Effective gas (after refund)
| -- | -- | -- | -- | -- | -- | -- | -- | 
| `0x60006000556000600055` | 212 | 0| 0 | 0 |  0 |  |  212 |
| `0x60006000556001600055` | 20112 | 0| 0 | 0 |  1 |  |  20112 |
| `0x60016000556000600055` | 20112 | 19900| 0 | 1 |  0 |  |  212 |
| `0x60016000556002600055` | 20112 | 0| 0 | 1 |  2 |  |  20112 |
| `0x60016000556001600055` | 20112 | 0| 0 | 1 |  1 |  |  20112 |
| `0x60006000556000600055` | 3012 | 15000| 1 | 0 |  0 |  |  -11988 |
| `0x60006000556001600055` | 3012 | 2800| 1 | 0 |  1 |  |  212 |
| `0x60006000556002600055` | 3012 | 0| 1 | 0 |  2 |  |  3012 |
| `0x60026000556000600055` | 3012 | 15000| 1 | 2 |  0 |  |  -11988 |
| `0x60026000556003600055` | 3012 | 0| 1 | 2 |  3 |  |  3012 |
| `0x60026000556001600055` | 3012 | 2800| 1 | 2 |  1 |  |  212 |
| `0x60026000556002600055` | 3012 | 0| 1 | 2 |  2 |  |  3012 |
| `0x60016000556000600055` | 3012 | 15000| 1 | 1 |  0 |  |  -11988 |
| `0x60016000556002600055` | 3012 | 0| 1 | 1 |  2 |  |  3012 |
| `0x60016000556001600055` | 212 | 0| 1 | 1 |  1 |  |  212 |
| `0x600160005560006000556001600055` | 40118 | 19900| 0 | 1 |  0 |  1 |  20218 |
| `0x600060005560016000556000600055` | 5918 | 17800| 1 | 0 |  1 |  0 |  -11882 |

### With EIP-3403 partial refunds 

If refunds were to be partially removed, as specified [here](https://github.com/ethereum/EIPs/pull/3403/), this would be the comparative table. **This table also assumes touched storage slots were already &apos;hot&apos;**.

| Code | Used Gas | Refund | Original | 1st | 2nd | 3rd | Effective gas (after refund)
| -- | -- | -- | -- | -- | -- | -- | -- | 
| `0x60006000556000600055` | 212 | 0| 0 | 0 |  0 |  |  212 |
| `0x60006000556001600055` | 20112 | 0| 0 | 0 |  1 |  |  20112 |
| `0x60016000556000600055` | 20112 | 19000| 0 | 1 |  0 |  |  1112 |
| `0x60016000556002600055` | 20112 | 0| 0 | 1 |  2 |  |  20112 |
| `0x60016000556001600055` | 20112 | 0| 0 | 1 |  1 |  |  20112 |
| `0x60006000556000600055` | 3012 | 0| 1 | 0 |  0 |  |  3012 |
| `0x60006000556001600055` | 3012 | 0| 1 | 0 |  1 |  |  3012 |
| `0x60006000556002600055` | 3012 | 0| 1 | 0 |  2 |  |  3012 |
| `0x60026000556000600055` | 3012 | 0| 1 | 2 |  0 |  |  3012 |
| `0x60026000556003600055` | 3012 | 0| 1 | 2 |  3 |  |  3012 |
| `0x60026000556001600055` | 3012 | 0| 1 | 2 |  1 |  |  3012 |
| `0x60026000556002600055` | 3012 | 0| 1 | 2 |  2 |  |  3012 |
| `0x60016000556000600055` | 3012 | 0| 1 | 1 |  0 |  |  3012 |
| `0x60016000556002600055` | 3012 | 0| 1 | 1 |  2 |  |  3012 |
| `0x60016000556001600055` | 212 | 0| 1 | 1 |  1 |  |  212 |
| `0x600160005560006000556001600055` | 40118 | 19000| 0 | 1 |  0 |  1 |  21118 |
| `0x600060005560016000556000600055` | 5918 | 0| 1 | 0 |  1 |  0 |  5918 |

## Security Considerations

Refunds are not visible to transaction execution, so this should not have any impact on transaction execution logic.

The maximum amount of gas that can be spent on execution in a block is limited to the gas limit, if we do not count zero-to-nonzero SSTOREs that were later reset back to zero. It is okay to not count those, because if such an SSTORE is reset, storage is not expanded and the client does not need to actually adjust the Merke tree; the gas consumption is refunded, but the effort normally required by the client to process those opcodes is also cancelled. **Clients should make sure to not do a storage write if `new_value = original_value`; this was a prudent optimization since the beginning of Ethereum but it becomes more important now.**

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 16 Mar 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3403</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3403</guid>
      </item>
    
      <item>
        <title>Median Gas Premium</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3416-median-gas-premium/5755</comments>
        
        <description>## Simple Summary

A transaction pricing mechanism with a fixed-per-block network fee and a median inclusion fee with additive updates.

## Abstract

There is a base fee per gas in protocol, which can move up or down by a maximum of 1/8 in each block. The base fee per gas is adjusted by the protocol to target an average gas usage per block instead of an absolute gas usage per block.  The base fee is increased when blocks are over the gas limit target and decreases when blocks are under the gas limit target. Transaction senders specify their fees by providing *only one value*:

* The fee cap which represents the maximum total (base fee + gas premium) that the transaction sender would be willing to pay to get their transaction included, resembles the current maximum gas price specified by senders but in this protocol change proposal the final gas price paid, most of the time, will be lower than the proposed by the transaction sender. 

Then there is a gas premium that is directly computed as 50% of (fee cap - base fee). This gas premium gets added onto the base fee to calculate the gas price that will be used in the weighted median computation. The gas premium, determined directly by a specified fee cap, can either be set to a fairly low value to compensate miners for uncle rate risk only with the base fee, or to a high value to compete during sudden bursts of activity. Using all transactions that the miner wants to include in the block, a **weighted median gas premium** is computed, not considering in the computation 5% of gas price outliers on the upper-side for extra robustness against miner manipulation.

## Motivation

We target the following goals:

* Gas prices spikes are mathematically smoothed out. EIP1559 does not seems to really tackle gas premium volatility and UX.
* Maintain gas price preference, i.e. transaction senders willing to pay extra in fees will be rewarded with early preferential inclusion in the blocks, because the miners want to maximize their profits and include transactions with higher fee caps first to maximize the median.
* Final gas price paid by the sender is, most of the time, smaller than the maximum gas price specified by sender. 
* Gas pricing is more robust to sender manipulation or miner manipulation.

Ethereum currently prices transaction fees using a simple auction mechanism, where users send transactions with bids (&quot;gasprices&quot;) and miners choose transactions with the highest bids, and transactions that get included pay the bid that they specify. This leads to several large sources of inefficiency:

* **Current extreme volatility of gas prices is hurting user experience**: if you observe  online gas price metrics, the current trends in recommended gas prices can change substantially by the minute, making the user experience in the network very awkward. Also, gas volatility makes the mining business more unpredictable and costly, because miners need to spend money hedging the risks.
* **Mismatch between volatility of transaction fee levels and social cost of transactions**: bids to include transactions on mature public blockchains, that have enough usage so that blocks are full, tend to be extremely volatile. On Ethereum, minimum bids range between 1 nanoeth (10^9 nanoeth = 1 ETH), but sometimes go over 100 nanoeth and have reached over 200 nanoeth. This clearly creates many inefficiencies, because it&apos;s absurd to suggest that the cost incurred by the network from accepting one more transaction into a block actually is 200x more when gas prices are 200 nanoeth than when they are 1 nanoeth; in both cases, it&apos;s a difference between 8 million gas and 8.02 million gas.
* **Needless delays for users**: because of the hard per-block gas limit coupled with natural volatility in transaction volume, transactions often wait for several blocks before getting included, but this is socially unproductive; no one significantly gains from the fact that there is no &quot;slack&quot; mechanism that allows one block to be bigger and the next block to be smaller to meet block-by-block differences in demand.
* **Inefficiencies of first price auctions**: The current approach, where transaction senders publish a transaction with a bid a maximum fee, miners choose the highest-paying transactions, and everyone pays what they bid. This is well-known in mechanism design literature to be highly inefficient, and so complex fee estimation algorithms are required. But even these algorithms often end up not working very well, leading to frequent fee overpayment. We need a more stable fee metric that is computed inside the protocol.

The proposal in this EIP is to start with a base fee amount which is adjusted up and down by the protocol based on how congested the network is. When the network exceeds the target per-block gas usage, the base fee increases slightly and when capacity is below the target, it decreases slightly. Because these base fee changes are constrained, the maximum difference in base fee from block to block is predictable. This then allows wallets to auto-set the gas fees for users in a highly reliable fashion. It is expected that most users will not have to manually adjust gas fees, even in periods of high network activity. For most users the base fee will be estimated by their wallet and a small gas premium related to the urgency and the priority they want to instill into the transaction. 

## Specification

### Definitions

This is a classic fork without a long migration time.

* `FORK_BLOCK_NUMBER`: TBD.  Block number at or after which EIP-3416 transactions are valid.
* `GAS_TARGET_MAX_CHANGE`: `1 // 1024`.
* `BLOCK_GAS_USED`: total gas consumed by transaction included in the block.
* `PARENT_GAS_USED`: same as `BLOCK_GAS_USED` for parent block. 
* `CURRENT_BLOCK`: The current block that is being worked with (either being validated, or being produced).
* `BASE_FEE`: 16th item in the block header. Represents the amount of attoeth burned for every unit of gas a transaction uses.
* `PARENT_BASE_FEE`: same as `BASE_FEE` for parent block.
* `BASE_FEE_MAX_CHANGE`: `1 // 8`
* `INITIAL_BASE_FEE` : Median gas price in `FORK_BLOCK_NUMBER - 1`.

### Process

* At `block.number == FORK_BLOCK_NUMBER` we set `BASE_FEE = INITIAL_BASE_FEE`
* `BASE_FEE` is set, from `FORK_BLOCK_NUMBER + 1`, as follows
  * Let `GAS_DELTA = (PARENT_GAS_USED - PARENT_GAS_TARGET) // PARENT_GAS_TARGET` (possibly negative).
  * Set `BASE_FEE = PARENT_BASE_FEE + GAS_DELTA * BASE_FEE_MAX_CHANGE`
* Transactions since `FORK_BLOCK_NUMBER` are encoded the same as the current ones `rlp([nonce, gasPrice, gasLimit, to, value, data, v, r, s])` where `v,r,s` is a signature of `rlp([nonce, gasPrice, gasLimit, to, value, data])` and `gasPrice` is the `FEE_CAP` specified by the sender according to this proposal.
* To produce transactions since `FORK_BLOCK_NUMBER`, the new `FEE_CAP` field (maintaining legacy name of `gasPrice` in the transaction) is set as follows (and the `GAS_PREMIUM` is computed as specified):
  * `FEE_CAP`: `tx.gasPrice`, serves as the absolute maximum that the transaction sender is willing to pay.
  * `GAS_PREMIUM = (FEE_CAP - BASE_FEE) / 2` serves as a sender-preferred median premium to the miner, beyond the base fee.
  * If `FEE_CAP &lt; BASE_FEE` then the transaction is considered invalid and cannot be included in the current block, but might be included in future blocks.
* During transaction execution, for EIP3416 transactions we calculate the cost to the `tx.origin` and the gain to the `block.coinbase` as follows:
  * Set `GASPRICE = BASE_FEE + median((tx_i.gasPrice - BASE_FEE) / 2)` among all transactions `tx_i` included in the same block, *weighted by gas consumed* and not including the top 5% of outlier gas price in calculation. By weighted median without 5% of the upper-side outliers, we mean that each gas unit spent is ordered according to the corresponding transaction by `BASE_FEE + tx.gasPrice / 2` and then the value chosen will be the one separating the lower 95% in two parts.
  * Let `GASUSED` be the gas used during the transaction execution/state transition.
  * The `tx.origin` initially pays `GASPRICE * tx.gasLimit`, and gets refunded `GASPRICE * (tx.gasLimit - GASUSED)`.

The miners can still use a `greedy` strategy to include new transactions in the proposed blocks by adding the transactions ordered by larger `FEE_CAP` first. This is similar to how current blocks are filled, and is a consequence of `FEE_CAP` and `GAS_PREMIUM` being a positive linear function of each other.

## Rationale 

The rationale behind the premium being 50% of (fee cap - base fee) is that at any given point the average network sender has an average fee cap, and we assume that between base fee and fee cap the sender has no specific preference, as long as the transaction is included in some block. Then, the sender is happy with a median premium among this uniform range. Another justification can be that the user also knows that this new version of the pricing protocol for the complete block uses a median, then is fair for him to apply a median within his preferential range, assuming an uniform sampling there. Simulations ([here](https://hackmd.io/c6kyRNMuTnKf_SlolmevRg#An-improvement-for-the-premium)) with Ethereum gas data shows indeed that median one of the most robust metric.s

The 5% top outliers removal, not considered in the median, or similar number, is to give extra robustness against miner manipulation, because as current network utilization has been around 97% for the last 6 months the miners can include their own transactions on the empty 3% to try to manipulate and increase the median price (even this manipulation effect will be very small on the final price).

The rationale for the `BASE_FEE` update formula is that we are using an additive version (`PARENT_BASE_FEE + GAS_DELTA * BASE_FEE_MAX_CHANGE`) to avoid an attack of senders sending this fee to zero. This attack was simulated and observed for multiplicative formula proposed in previous version (`PARENT_BASE_FEE + PARENT_BASE_FEE * GAS_DELTA * BASE_FEE_MAX_CHANGE`). See an article about the attack and the simulation [here](https://mtefagh.github.io/fee/).

Another rationale for the additive `BASE_FEE` update formula is that it guarantees (see [this](https://pdfs.semanticscholar.org/3d2d/773983c5201b58586af463f045befae5bbf2.pdf) article) that the optimal execution strategy (scheduling broadcasts in order to pay less fee) for a batch of nonurgent transactions is to spread the transactions across different blocks which in turn helps to avoid network congestion and lowers volatility. For the multiplicative formula, it is exactly the reverse, that is, spikes (dumping all your transactions at once) are incentivized as described [here](https://ethresear.ch/t/path-dependence-of-eip-1559-and-the-simulation-of-the-resulting-permanent-loss/8964).

The rationale for the `BASE_FEE_MAX_CHANGE` being `1 // 8` is that the `BASE_FEE` is designed to be very adaptative to block utilization changes.

## Backwards Compatibility

The backward compatibility is very straightforward because there are no new fields added to the transactions. Pricing of the gas per block on the miner/validator side is still fast to compute but a little more complex. Changes only affect miners/validators. Wallets are no affected by this proposal.

## Test Cases

TBD.

## Security Considerations

* Senders cannot manipulate the minimum fee because the minimum `BASE_FEE` is controlled by the miners with small increments or decrements on each new block proposed.
* Above the `BASE_FEE` the senders have a very limited ability to manipulate and lower the final gas price they pay because they have to move the weighted median close to `BASE_FEE` and, as we know, this is a very robust statistic.
* Miners have a very limited ability to manipulate and raise the final gas price paid by senders above `BASE_FEE` because to influence the final gas price they have to stuff fake transactions beyond the top 5% of the blocks. In average and currently, only the top 3% of the block is empty, so to fill-up 5% of the block they need to start dropping profitable transactions to reach 5%. Only beyond 5% of the top block gas they can start moving the median a little and the median is still a very robust statistic, not liable to being easily manipulated.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 18 Mar 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3416</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3416</guid>
      </item>
    
      <item>
        <title>Expanded Clique Block Choice Rule</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3436-expanded-clique-block-choice-rule/5809</comments>
        
        <description>## Simple Summary

Add a four step block rule to Clique that should reduce block production deadlocks

## Abstract

The current specification of Clique allows for multiple competing blocks from producers but does not
provide any strategies to pick blocks aside from the current &quot;highest total difficulty&quot; rule. This
EIP proposes a four step choice rule of highest total difficulty, shortest chain, most recently
in-turn, and lowest hash. This would prevent deadlocks that have occurred in production systems. 

## Motivation

There has been more than one deadlock in the Goerli multi-client Clique network. The number of
active validators was greater than 1/2 of the available validators so a chain halt should not have
occurred. The halt was resolved by an inactive validator coming back on line. The state of the chain
was in one of two configurations of 8 validators that can result in a chain halt. Three of the four
clients observed a choice sequence of lowest total difficulty followed by first observed block. Geth
added one extra rule of preferring the shortest chain before preferring the first observed block.
This fork would have resolved itself with Geth&apos;s rule, but there is still a configuration where the
chain can halt with a shortest chain rule.

## Specification

When a Clique validator is arbitrating the canonical status between two different chain head blocks,
they should choose the canonical block with the following ordered priorities.

1. Choose the block with the most total difficulty.
2. Then choose the block with the lowest block number.
3. Then choose the block whose validator had the least recent in-turn block assignment.
4. Then choose the block with the lowest hash.

When resolving rule 3 clients should use the following formula, where `validator_index` is the integer
index of the validator that signed the block when sorted as per epoch checkpointing,
`header_number` is the number of the header, and `validator_count` is the count of the current
validators. Clients should choose the block with the **largest** value. Note that an in-turn block
is considered to be the most recent in-turn block.

```
(header_number - validator_index) % validator_count
```

When resolving rule 4 the hash should be converted into an unsigned 256 bit integer.

## Rationale

Two scenarios of a halted chain are known based on the current total difficulty then first observed
rule. One of the scenarios is also resistant to the shortest chain rule.

For the first scenario where chains of different lengths can halt consider a block with 8
validators, whose addresses sort to the same order as their designation in this example. A fully
in-order chain exists and validator number 8 has just produced an in-turn block and then validators
5, 7 and 8 go offline, leaving validators 1 to 6 to produce blocks. Two forks form, one with an
in-order block from validator 1 and then an out of order block from validator 3. The second fork
forms from validators 2, 4, and 6 in order. Both have a net total difficulty of 3 more than the
common ancestor. So in this case if both forks become aware of the other fork then both are
considered equally viable and neither set of validators should switch to the newly observed fork. In
this case, adding a shortest chain rule would break the deadlock as the even numbered validators
would adopt the shorter chain.

For the second scenario with the same validator set and in-order chain with validator 7 having just
produced an in order block, then validators 7 and 8 go offline. Two forks form, 1,3,5 on one side
and 2,4,6 on the other. Both forks become aware of the other fork after producing their third block.
In this case both forks have equal total difficulty and equal length. So Geth&apos;s rule would not break
the tie and only the arrival of one of the missing validators fix the chain. In a worst case
scenario the odd and even chains would produce a block for 7 and 8 respectively, and chain halt
would result with no validators that have not chosen a fork. Only a manual rollback would fix this.

One consideration when formulating the rules is that the block choice should be chosen so that it
would encourage the maximum amount of in-order blocks. Selecting a chain based on shortest chain
implicitly prefers the chain with more in-order blocks. When selecting between competing out of
order chains the validator who is closest to producing an in-order block in the future should have
their chain declined so that they are available to produce an in-order block sooner.

At least one client has been observed producing multiple blocks at the same height with the same
difficulty, so a final catch-all standard of lowest block hash should break any remaining ties.

## Backwards Compatibility

The current block choice rules are a mix of most total difficulty and most total difficulty plus
shortest chain.

As long as the majority of the active validators implement the block choice rules then a client who
only implements the existing difficulty based rule will eventually align with the chain preferred by
these rules. If less than a majority implement these rules then deadlocks can still occur, and
depend on the first observation of problematic blocks, which is no worse than the current situation.

If clients only partially implement the rule as long as every higher ranked rule is also implemented
then the situation will be no worse than today.

## Security Considerations

Malicious and motivated attackers who are participating in the network can force the chain to halt
with well crafted block production. With a fully deterministic choice rule the opportunity to halt
is diminished. Attackers still have the same opportunities to flood the network with multiple blocks
at the same height. A deterministic rule based on the lowest hash reduces the impact of such a
flooding attack. A malicious validator could exploit this deterministic rule to produce a
replacement block. Such an attack exists in current implementations but a deterministic hash rule
makes such replacements more likely. However the impact of such an attack seems low to trivial at
this time.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 25 Mar 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3436</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3436</guid>
      </item>
    
      <item>
        <title>ERC-721 Editions Standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3340-nft-editions-standard-extension/6044</comments>
        
        <description>## Simple Summary

This standard addresses an extension to the [ERC-721 specification](/EIPs/EIPS/eip-721) by allowing signatures on NFTs representing works of art. This provides improved provenance by creating functionality for an artist to designate an original and signed limited-edition prints of their work. 

## Abstract

ERC-3440 is an ERC-721 extension specifically designed to make NFTs more robust for works of art. This extends the original ERC-721 spec by providing the ability to designate the original and limited-edition prints with a specialized enumeration extension similar to the [original 721 extension](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/extensions/ERC721Enumerable.sol) built-in. The key improvement of this extension is allowing artists to designate the limited nature of their prints and provide a signed piece of data that represents their unique signature to a given token Id, much like an artist would sign a print of their work.

## Motivation
Currently the link between a NFT and the digital work of art is only enforced in the token metadata stored in the shared `tokenURI` state of a NFT. While the blockchain provides an immutable record of history back to the origin of an NFT, often the origin is not a key that an artist maintains as closely as they would a hand written signature.

An edition is a printed replica of an original piece of art. ERC-721 is not specifically designed to be used for works of art, such as digital art and music. ERC-721 (NFT) was originally created to handle deeds and other contracts. Eventually ERC-721 evolved into gaming tokens, where metadata hosted by servers may be sufficient. This proposal takes the position that we can create a more tangible link between the NFT, digital art, owner, and artist. By making a concise standard for art, it will be easier for an artist to maintain a connection with the Ethereum blockchain as well as their fans that purchase their tokens.

The use cases for NFTs have evolved into works of digital art, and there is a need to designate an original NFT and printed editions with signatures in a trustless manner. ERC-721 contracts may or may not be deployed by artists, and currently, the only way to understand that something is uniquely touched by an artist is to display it on 3rd party applications that assume a connection via metadata that exists on servers, external to the blockchain. This proposal helps remove that distance with readily available functionality for artists to sign their work and provides a standard for 3rd party applications to display the uniqueness of a NFT for those that purchase them. The designation of limited-editions combined with immutable signatures, creates a trustlessly enforced link. This signature is accompanied by view functions that allow applications to easily display these signatures and limited-edition prints as evidence of uniqueness by showing that artists specifically used their key to designate the total supply and sign each NFT.

## Specification
The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

ERC-721 compliant contracts MAY implement this ERC for editions to provide a standard method for designating the original and limited-edition prints with signatures from the artist.

Implementations of ERC-3440 MUST designate which token Id is the original NFT (defaulted to Id 0), and which token Id is a unique replica. The original print SHOULD be token Id number 0 but MAY be assigned to a different Id. The original print MUST only be designated once. The implementation MUST designate a maximum number of minted editions, after which new Ids MUST NOT be printed / minted.

Artists MAY use the signing feature to sign the original or limited edition prints but this is OPTIONAL. A standard message to sign is RECOMMENDED to be simply a hash of the integer of the token Id. 

Signature messages MUST use the [EIP-712](https://eips.ethereum.org/EIPS/eip-712) standard.

A contract that is compliant with ERC-3440 shall implement the following abstract contract (referred to as ERC3440.sol):

```solidity
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol&quot;;
import &quot;@openzeppelin/contracts/utils/cryptography/ECDSA.sol&quot;;

/**
 * @dev ERC721 token with editions extension.
 */
abstract contract ERC3440 is ERC721URIStorage {

    // eip-712
    struct EIP712Domain {
        string  name;
        string  version;
        uint256 chainId;
        address verifyingContract;
    }
    
    // Contents of message to be signed
    struct Signature {
        address verificationAddress; // ensure the artists signs only address(this) for each piece
        string artist;
        address wallet;
        string contents;
    }

    // type hashes
    bytes32 constant EIP712DOMAIN_TYPEHASH = keccak256(
        &quot;EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)&quot;
    );

    bytes32 constant SIGNATURE_TYPEHASH = keccak256(
        &quot;Signature(address verifyAddress,string artist,address wallet, string contents)&quot;
    );

    bytes32 public DOMAIN_SEPARATOR;
    
    // Optional mapping for signatures
    mapping (uint256 =&gt; bytes) private _signatures;
    
    // A view to display the artist&apos;s address
    address public artist;

    // A view to display the total number of prints created
    uint public editionSupply = 0;
    
    // A view to display which ID is the original copy
    uint public originalId = 0;
    
    // A signed token event
    event Signed(address indexed from, uint256 indexed tokenId);

    /**
     * @dev Sets `artist` as the original artist.
     * @param `address _artist` the wallet of the signing artist (TODO consider multiple
     * signers and contract signers (non-EOA)
     */
    function _designateArtist(address _artist) internal virtual {
        require(artist == address(0), &quot;ERC721Extensions: the artist has already been set&quot;);

        // If there is no special designation for the artist, set it.
        artist = _artist;
    }
    
    /**
     * @dev Sets `tokenId as the original print` as the tokenURI of `tokenId`.
     * @param `uint256 tokenId` the nft id of the original print
     */
    function _designateOriginal(uint256 _tokenId) internal virtual {
        require(msg.sender == artist, &quot;ERC721Extensions: only the artist may designate originals&quot;);
        require(_exists(_tokenId), &quot;ERC721Extensions: Original query for nonexistent token&quot;);
        require(originalId == 0, &quot;ERC721Extensions: Original print has already been designated as a different Id&quot;);

        // If there is no special designation for the original, set it.
        originalId = _tokenId;
    }
    

    /**
     * @dev Sets total number printed editions of the original as the tokenURI of `tokenId`.
     * @param `uint256 _maxEditionSupply` max supply
     */
    function _setLimitedEditions(uint256 _maxEditionSupply) internal virtual {
        require(msg.sender == artist, &quot;ERC721Extensions: only the artist may designate max supply&quot;);
        require(editionSupply == 0, &quot;ERC721Extensions: Max number of prints has already been created&quot;);

        // If there is no max supply of prints, set it. Leaving supply at 0 indicates there are no prints of the original
        editionSupply = _maxEditionSupply;
    }

    /**
     * @dev Creates `tokenIds` representing the printed editions.
     * @param `string memory _tokenURI` the metadata attached to each nft
     */
    function _createEditions(string memory _tokenURI) internal virtual {
        require(msg.sender == artist, &quot;ERC721Extensions: only the artist may create prints&quot;);
        require(editionSupply &gt; 0, &quot;ERC721Extensions: the edition supply is not set to more than 0&quot;);
        for(uint i=0; i &lt; editionSupply; i++) {
            _mint(msg.sender, i);
            _setTokenURI(i, _tokenURI);
        }
    }

    /**
     * @dev internal hashing utility 
     * @param `Signature memory _message` the signature message struct to be signed
     * the address of this contract is enforced in the hashing
     */
    function _hash(Signature memory _message) internal view returns (bytes32) {
        return keccak256(abi.encodePacked(
            &quot;\x19\x01&quot;,
            DOMAIN_SEPARATOR,
            keccak256(abi.encode(
                SIGNATURE_TYPEHASH,
                address(this),
                _message.artist,
                _message.wallet,
                _message.contents
            ))
        ));
    }

    /**
     * @dev Signs a `tokenId` representing a print.
     * @param `uint256 _tokenId` id of the NFT being signed
     * @param `Signature memory _message` the signed message
     * @param `bytes memory _signature` signature bytes created off-chain
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Signed} event.
     */
    function _signEdition(uint256 _tokenId, Signature memory _message, bytes memory _signature) internal virtual {
        require(msg.sender == artist, &quot;ERC721Extensions: only the artist may sign their work&quot;);
        require(_signatures[_tokenId].length == 0, &quot;ERC721Extensions: this token is already signed&quot;);
        bytes32 digest = hash(_message);
        address recovered = ECDSA.recover(digest, _signature);
        require(recovered == artist, &quot;ERC721Extensions: artist signature mismatch&quot;);
        _signatures[_tokenId] = _signature;
        emit Signed(artist, _tokenId);
    }

    
    /**
     * @dev displays a signature from the artist.
     * @param `uint256 _tokenId` NFT id to verify isSigned
     * @returns `bytes` gets the signature stored on the token
     */
    function getSignature(uint256 _tokenId) external view virtual returns (bytes memory) {
        require(_signatures[_tokenId].length != 0, &quot;ERC721Extensions: no signature exists for this Id&quot;);
        return _signatures[_tokenId];
    }
    
    /**
     * @dev returns `true` if the message is signed by the artist.
     * @param `Signature memory _message` the message signed by an artist and published elsewhere
     * @param `bytes memory _signature` the signature on the message
     * @param `uint _tokenId` id of the token to be verified as being signed
     * @returns `bool` true if signed by artist
     * The artist may broadcast signature out of band that will verify on the nft
     */
    function isSigned(Signature memory _message, bytes memory _signature, uint _tokenId) external view virtual returns (bool) {
        bytes32 messageHash = hash(_message);
        address _artist = ECDSA.recover(messageHash, _signature);
        return (_artist == artist &amp;&amp; _equals(_signatures[_tokenId], _signature));
    }

    /**
    * @dev Utility function that checks if two `bytes memory` variables are equal. This is done using hashing,
    * which is much more gas efficient then comparing each byte individually.
    * Equality means that:
    *  - &apos;self.length == other.length&apos;
    *  - For &apos;n&apos; in &apos;[0, self.length)&apos;, &apos;self[n] == other[n]&apos;
    */
    function _equals(bytes memory _self, bytes memory _other) internal pure returns (bool equal) {
        if (_self.length != _other.length) {
            return false;
        }
        uint addr;
        uint addr2;
        uint len = _self.length;
        assembly {
            addr := add(_self, /*BYTES_HEADER_SIZE*/32)
            addr2 := add(_other, /*BYTES_HEADER_SIZE*/32)
        }
        assembly {
            equal := eq(keccak256(addr, len), keccak256(addr2, len))
        }
    }
}
```

## Rationale

A major role of NFTs is to display uniqueness in digital art. Provenance is a desired feature of works of art, and this standard will help improve a NFT by providing a better way to verify uniqueness. Taking this extra step by an artist to explicitly sign tokens provides a better connection between the artists and their work on the blockchain. Artists can now retain their private key and sign messages in the future showing that the same signature is present on a unique NFT.

## Backwards Compatibility

This proposal combines already available 721 extensions and is backwards compatible with the ERC-721 standard.

## Test Cases
An example implementation including tests can be found [here](https://github.com/nginnever/NFT-editions).

## Reference Implementation
```solidity
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import &quot;./ERC3440.sol&quot;;

/**
 * @dev ERC721 token with editions extension.
 */
contract ArtToken is ERC3440 {

    /**
     * @dev Sets `address artist` as the original artist to the account deploying the NFT.
     */
     constructor (
        string memory _name, 
        string memory _symbol,
        uint _numberOfEditions,
        string memory tokenURI,
        uint _originalId
    ) ERC721(_name, _symbol) {
        _designateArtist(msg.sender);
        _setLimitedEditions(_numberOfEditions);
        _createEditions(tokenURI);
        _designateOriginal(_originalId);

        DOMAIN_SEPARATOR = keccak256(abi.encode(
            EIP712DOMAIN_TYPEHASH,
            keccak256(bytes(&quot;Artist&apos;s Editions&quot;)),
            keccak256(bytes(&quot;1&quot;)),
            1,
            address(this)
        ));
    }
    
    /**
     * @dev Signs a `tokenId` representing a print.
     */
    function sign(uint256 _tokenId, Signature memory _message, bytes memory _signature) public {
        _signEdition(_tokenId, _message, _signature);
    }
}

```

## Security Considerations
This extension gives an artist the ability to designate an original edition, set the maximum supply of editions as well as print the editions and uses the `tokenURI` extension to supply a link to the art work. To minimize the risk of an artist changing this value after selling an original piece this function can only happen once. Ensuring that these functions can only happen once provides consistency with uniqueness and verifiability. Due to this, the reference implementation handles these features in the constructor function. An edition may only be signed once, and care should be taken that the edition is signed correctly before release of the token/s.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 20 Apr 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3440</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3440</guid>
      </item>
    
      <item>
        <title>MetaProxy Standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-3448-metaproxy-factory/5834</comments>
        
        <description>## Abstract
By standardizing on a known minimal bytecode proxy implementation with support for immutable metadata, this standard allows users and third party tools (e.g. Etherscan) to:
(a) simply discover that a contract will always redirect in a known manner and
(b) depend on the behavior of the code at the destination contract as the behavior of the redirecting contract and
(c) verify/view the attached metadata.

Tooling can interrogate the bytecode at a redirecting address to determine the location of the code that will run along with the associated metadata - and can depend on representations about that code (verified source, third-party audits, etc).
This implementation forwards all calls via `DELEGATECALL` and any (calldata) input plus the metadata at the end of the bytecode to the implementation contract and then relays the return value back to the caller.
In the case where the implementation reverts, the revert is passed back along with the payload data.

## Motivation
This standard supports use-cases wherein it is desirable to clone exact contract functionality with different parameters at another address.

## Specification
The exact bytecode of the MetaProxy contract is:
```
                                              20 bytes target contract address
                                          ----------------------------------------
363d3d373d3d3d3d60368038038091363936013d7300000000000000000000000000000000000000005af43d3d93803e603457fd5bf3
```
wherein the bytes at indices 21 - 41 (inclusive) are replaced with the 20 byte address of the master functionality contract.
Additionally, everything after the MetaProxy bytecode can be arbitrary metadata and the last 32 bytes (one word) of the bytecode must indicate the length of the metadata in bytes.

```
&lt;54 bytes metaproxy&gt; &lt;arbitrary data&gt; &lt;length in bytes of arbitrary data (uint256)&gt;
```

## Rationale
The goals of this effort have been the following:
- a cheap way of storing immutable metadata for each child instead of using storage slots
- inexpensive deployment of clones
- handles error return bubbling for revert messages

## Backwards Compatibility
There are no backwards compatibility issues.

## Test Cases
Tested with:
- invocation with no arguments
- invocation with arguments
- invocation with return values
- invocation with revert (confirming reverted payload is transferred)

A solidity contract with the above test cases can be found [in the EIP asset directory](/EIPs/assets/eip-3448/MetaProxyTest.sol).

## Reference Implementation
A reference implementation can be found [in the EIP asset directory](/EIPs/assets/eip-3448/MetaProxyFactory.sol).

### Deployment bytecode
A annotated version of the deploy bytecode:
```
// PUSH1 11;
// CODESIZE;
// SUB;
// DUP1;
// PUSH1 11;
// RETURNDATASIZE;
// CODECOPY;
// RETURNDATASIZE;
// RETURN;
```

### MetaProxy
A annotated version of the MetaProxy bytecode:
```
// copy args
// CALLDATASIZE;   calldatasize
// RETURNDATASIZE; 0, calldatasize
// RETURNDATASIZE; 0, 0, calldatasize
// CALLDATACOPY;

// RETURNDATASIZE; 0
// RETURNDATASIZE; 0, 0
// RETURNDATASIZE; 0, 0, 0
// RETURNDATASIZE; 0, 0, 0, 0

// PUSH1 54;       54, 0, 0, 0, 0
// DUP1;           54, 54, 0, 0, 0, 0
// CODESIZE;       codesize, 54, 54, 0, 0, 0, 0
// SUB;            codesize-54, 54, 0, 0, 0, 0
// DUP1;           codesize-54, codesize-54, 54, 0, 0, 0, 0
// SWAP2;          54, codesize-54, codesize-54, 0, 0, 0, 0
// CALLDATASIZE;   calldatasize, 54, codesize-54, codesize-54, 0, 0, 0, 0
// CODECOPY;       codesize-54, 0, 0, 0, 0

// CALLDATASIZE;   calldatasize, codesize-54, 0, 0, 0, 0
// ADD;            calldatasize+codesize-54, 0, 0, 0, 0
// RETURNDATASIZE; 0, calldatasize+codesize-54, 0, 0, 0, 0
// PUSH20 0;       addr, 0, calldatasize+codesize-54, 0, 0, 0, 0 - zero is replaced with shl(96, address())
// GAS;            gas, addr, 0, calldatasize+codesize-54, 0, 0, 0, 0
// DELEGATECALL;   (gas, addr, 0, calldatasize() + metadata, 0, 0) delegatecall to the target contract;
//
// RETURNDATASIZE; returndatasize, retcode, 0, 0
// RETURNDATASIZE; returndatasize, returndatasize, retcode, 0, 0
// SWAP4;          0, returndatasize, retcode, 0, returndatasize
// DUP1;           0, 0, returndatasize, retcode, 0, returndatasize
// RETURNDATACOPY; (0, 0, returndatasize) - Copy everything into memory that the call returned

// stack = retcode, 0, returndatasize # this is for either revert(0, returndatasize()) or return (0, returndatasize())

// PUSH1 _SUCCESS_; push jumpdest of _SUCCESS_
// JUMPI;          jump if delegatecall returned `1`
// REVERT;         (0, returndatasize()) if delegatecall returned `0`
// JUMPDEST _SUCCESS_;
// RETURN;         (0, returndatasize()) if delegatecall returned non-zero (1)
```

### Examples
The following code snippets serve only as suggestions and are not a discrete part of this standard.

#### Proxy construction with bytes from abi.encode
```solidity
/// @notice MetaProxy construction via abi encoded bytes.
function createFromBytes (
  address a,
  uint256 b,
  uint256[] calldata c
) external payable returns (address proxy) {
  // creates a new proxy where the metadata is the result of abi.encode()
  proxy = MetaProxyFactory._metaProxyFromBytes(address(this), abi.encode(a, b, c));
  require(proxy != address(0));
  // optional one-time setup, a constructor() substitute
  MyContract(proxy).init{ value: msg.value }();
}
```

#### Proxy construction with bytes from calldata
```solidity
/// @notice MetaProxy construction via calldata.
function createFromCalldata (
  address a,
  uint256 b,
  uint256[] calldata c
) external payable returns (address proxy) {
  // creates a new proxy where the metadata is everything after the 4th byte from calldata.
  proxy = MetaProxyFactory._metaProxyFromCalldata(address(this));
  require(proxy != address(0));
  // optional one-time setup, a constructor() substitute
  MyContract(proxy).init{ value: msg.value }();
}
```

#### Retrieving the metadata from calldata and abi.decode
```solidity
/// @notice Returns the metadata of this (MetaProxy) contract.
/// Only relevant with contracts created via the MetaProxy standard.
/// @dev This function is aimed to be invoked with- &amp; without a call.
function getMetadataWithoutCall () public pure returns (
  address a,
  uint256 b,
  uint256[] memory c
) {
  bytes memory data;
  assembly {
    let posOfMetadataSize := sub(calldatasize(), 32)
    let size := calldataload(posOfMetadataSize)
    let dataPtr := sub(posOfMetadataSize, size)
    data := mload(64)
    // increment free memory pointer by metadata size + 32 bytes (length)
    mstore(64, add(data, add(size, 32)))
    mstore(data, size)
    let memPtr := add(data, 32)
    calldatacopy(memPtr, dataPtr, size)
  }
  return abi.decode(data, (address, uint256, uint256[]));
}
```

#### Retrieving the metadata via a call to self
```solidity
/// @notice Returns the metadata of this (MetaProxy) contract.
/// Only relevant with contracts created via the MetaProxy standard.
/// @dev This function is aimed to be invoked via a call.
function getMetadataViaCall () public pure returns (
  address a,
  uint256 b,
  uint256[] memory c
) {
  assembly {
    let posOfMetadataSize := sub(calldatasize(), 32)
    let size := calldataload(posOfMetadataSize)
    let dataPtr := sub(posOfMetadataSize, size)
    calldatacopy(0, dataPtr, size)
    return(0, size)
  }
}
```

Apart from the examples above, it is also possible to use Solidity Structures or any custom data encoding.

## Security Considerations
This standard only covers the bytecode implementation and does not include any serious side effects of itself.
The reference implementation only serves as a example. It is highly recommended to research side effects depending on how the functionality is used and implemented in any project.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 29 Mar 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3448</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3448</guid>
      </item>
    
      <item>
        <title>Standardized Shamir Secret Sharing Scheme for BIP-39 Mnemonics</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-3450-standard-for-applying-shamirs-to-bip-39-mnemonics/5844</comments>
        
        <description>## Simple Summary

A standardized algorithm for applying Shamir&apos;s Secret Sharing Scheme to BIP-39 mnemonics.

## Abstract

A standardized approach to splitting a BIP-39 mnemonic into _N_ BIP-39 mnemonics, called shares, so that _T_ shares are required to recover the original mnemonic and no information about the original mnemonic, other than its size, is leaked with less than _T_ shares.

## Motivation

We&apos;d like to make it easier for less-technical users to store keys securely.

Currently, many users use BIP-39 mnemonics to store entropy values underlying their keys. These mnemonics are a single point of failure. If lost, the user may never regain access to the assets locked by the keys. If stolen, a malicious actor can steal the assets.

Shamir&apos;s Secret Sharing Scheme addresses this concern directly. It creates &quot;shares&quot; of the secret, such that a subset can be used to recover the secret, but only if a minimum threshold of shares is reached. Without the minimum, no information about the original secret is leaked.

One concern with Shamir&apos;s Secret Sharing Scheme is there is no canonical, standard implementation. This puts recovery at risk, as tooling may change over time.

Here, we propose a standardized implementation of Shamir&apos;s Secret Sharing Scheme applied specifically to BIP-39 mnemonics, so users can easily create shares of their mnemonic, destroy the original, store the shares appropriately, and confidently recover the original mnemonic at a later date.

## Specification

### Shamir&apos;s Secret Sharing Scheme

Shamir&apos;s Secret Sharing Scheme is a cryptographic method to split a secret into _N_ unique parts, where any _T_ of them are required to reconstruct the secret.

First, a polynomial _f_ of degree _T_ − 1 is constructed. Then, each share is a point on the polynomial&apos;s curve: an integer _x_, and its corresponding _y_ point _f_(_x_).

With any set of _T_ shares (or points), the initial polynomial can be recovered using polynomial interpolation.

When constructing the initial polynomial, the secret is stored as the coefficient of x&lt;sup&gt;0&lt;/sup&gt; and the rest of the coefficients are randomly generated.

### BIP-39 Mnemonics

BIP-39 is a common standard for storing entropy as a list of words. It is easier to work with for human interactions than raw binary or hexadecimal representations of entropy.

BIP-39 mnemonics encode two pieces of data: the original entropy and a checksum of that entropy. The checksum allows the mnemonic to be validated, ensuring that the user entered it correctly.

#### Generating the Mnemonic

The mnemonic must encode entropy in a multiple of 32 bits. With more entropy security is improved but the sentence length increases. We refer to the initial entropy length as ENT. The allowed size of ENT is 128-256 bits.

First, an initial entropy of ENT bits is generated. A checksum is generated by taking the first `ENT / 32` bits of its SHA256 hash. This checksum is appended to the end of the initial entropy. Next, these concatenated bits are split into groups of 11 bits, each encoding a number from 0-2047, serving as an index into a word list. Finally, we convert these numbers into words and use the joined words as a mnemonic sentence.

The following table describes the relation between the initial entropy length (ENT), the checksum length (CS), and the length of the generated mnemonic sentence (MS) in words.

```
CS = ENT / 32
MS = (ENT + CS) / 11

|  ENT  | CS | ENT+CS |  MS  |
+-------+----+--------+------+
|  128  |  4 |   132  |  12  |
|  160  |  5 |   165  |  15  |
|  192  |  6 |   198  |  18  |
|  224  |  7 |   231  |  21  |
|  256  |  8 |   264  |  24  |
```

#### Recovering the Entropy

The initial entropy can be recovered by reversing the process above. The mnemonic is converted to bits, where each word is converted to 11 bits representing its index in the word list. The entropy portion is defined in the table above, based on the size of the mnemonic.

#### Word List

This specification only supports the BIP-39 English word list, but this may be expanded in the future.

See [word list](/EIPs/assets/eip-3450/wordlist.txt).

### Applying Shamir&apos;s Scheme to BIP-39 Mnemonics

To ensure that the shares are valid BIP-39 mnemonics, we:

1. Convert the target BIP-39 mnemonic to its underlying entropy
2. Apply Shamir&apos;s Scheme to the entropy
3. Convert each resulting share&apos;s _y_ value to a BIP-39 mnemonic

By converting to entropy before applying Shamir&apos;s Scheme, we omit the checksum from the initial secret, allowing us to calculate a new checksum for each share when converting the share _y_ values to mnemonics, ensuring that they are valid according to BIP-39.

When applying Shamir&apos;s Scheme to the entropy, we apply it separately to each byte of the entropy and GF(256) is used as the underlying finite field. Bytes are interpreted as elements of GF(256) using polynomial representation with operations modulo the Rijndael irreducible polynomial _x_&lt;sup&gt;8&lt;/sup&gt; + _x_&lt;sup&gt;4&lt;/sup&gt; + _x_&lt;sup&gt;3&lt;/sup&gt; + _x_ + 1, following AES.

### Share Format

A share represents a point on the curve described by the underlying polynomial used to split the secret. It includes two pieces of data:

- An ID: the _x_ value of the share
- A BIP-39 mnemonic: the _y_ value of the share represented by a mnemonic

### Creating Shares

Inputs: BIP-39 mnemonic, number of shares (_N_), threshold (_T_)

Output: N Shares, each share including an ID, { _x_ | 0 &amp;lt; _x_ &amp;lt; 256 }, and a BIP-39 mnemonic of the same length as the input one

1. Check the following conditions:
   - 1 &lt; T &lt;= N &lt; 256
   - The mnemonic is valid according to [BIP-39](#generating-the-mnemonic)
2. [Recover the underlying entropy of the mnemonic](#recovering-the-entropy) as a vector of bytes
3. Define values:
   - Let _E_ be the byte-vector representation of the mnemonic&apos;s entropy
   - Let _n_ be the length of _E_
   - Let _coeff&lt;sub&gt;1&lt;/sub&gt;_, ... , _coeff&lt;sub&gt;T - 1&lt;/sub&gt;_ be byte-vectors belonging to GF(256)_&lt;sup&gt;n&lt;/sup&gt;_ generated randomly, independently with uniform distribution from a source suitable for generating cryptographic keys
4. Evaluate the polynomial for each share
   - For each _x_ from 1 to _N_, evaluate the polynomial _f(x)_ = _E_ + _coeff&lt;sub&gt;1&lt;/sub&gt;x&lt;sup&gt;1&lt;/sup&gt;_ + ... + _coeff&lt;sub&gt;T - 1&lt;/sub&gt;x&lt;sup&gt;T - 1&lt;/sup&gt;_, where _x_ is the share ID and _f(x)_ is the share value (as a vector of bytes)
5. Using _f(x)_ as the underlying entropy, [generate a mnemonic](#generating-the-mnemonic) for each share
6. Return the ID and mnemonic for each share

### Recovering the Mnemonic

To recover the original mnemonic, we interpolate a polynomial _f_ from the given set of shares (or points on the polynomial) and evaluate _f(0)_.

#### Polynomial Interpolation

Given a set of _m_ points (_x&lt;sub&gt;i&lt;/sub&gt;_, _y&lt;sub&gt;i&lt;/sub&gt;_), 1 &amp;le; _i_ &amp;le; _m_, such that no two _x&lt;sub&gt;i&lt;/sub&gt;_ values equal, there exists a polynomial that assumes the value _y&lt;sub&gt;i&lt;/sub&gt;_ at each point _x&lt;sub&gt;i&lt;/sub&gt;_. The polynomial of lowest degree that satisfies these conditions is uniquely determined and can be obtained using the Lagrange interpolation formula given below.

Since Shamir&apos;s Secret Sharing Scheme is applied separately to each of the _n_ bytes of the shared mnemonic&apos;s entropy, we work with _y&lt;sub&gt;i&lt;/sub&gt;_ as a vector of _n_ values, where _y&lt;sub&gt;i&lt;/sub&gt;_[_k_] = _f&lt;sub&gt;k&lt;/sub&gt;_(_x&lt;sub&gt;i&lt;/sub&gt;_), 1 &amp;le; _k_ &amp;le; _n_, and _f&lt;sub&gt;k&lt;/sub&gt;_ is the polynomial in the _k_-th instance of the scheme.

#### Interpolate(_x_, {(_x&lt;sub&gt;i&lt;/sub&gt;_, _y&lt;sub&gt;i&lt;/sub&gt;_), 1 &amp;le; _i_ &amp;le; _m_})

Input: the desired index _x_, a set of index/value-vector pairs {(_x&lt;sub&gt;i&lt;/sub&gt;_, _y_&lt;sub&gt;_i_&lt;/sub&gt;), 1 &amp;le; _i_ &amp;le; _m_} &amp;subseteq; GF(256) &amp;times; GF(256)&lt;sup&gt;_n_&lt;/sup&gt;

Output: the value-vector (_f_&lt;sub&gt;1&lt;/sub&gt;(_x_), ... , _f&lt;sub&gt;n&lt;/sub&gt;_(_x_))

![f_k(x) = \sum_{i=1}^m y_i[k] \prod_{\underset{j \neq i}{j=1}}^m \frac{x - x_j}{x_i - x_j}](/EIPs/assets/eip-3450/lagrange.gif)

#### Recover the Mnemonic

Input: A set of _m_ Shares

Output: The original mnemonic

1. [Recover the underlying entropy of each share&apos;s mnemonic](#recovering-the-entropy) as a vector of bytes
2. Calculate _E_ = Interpolate(0, [(_x&lt;sub&gt;1&lt;/sub&gt;_, _y&lt;sub&gt;1&lt;/sub&gt;_),...,(_x&lt;sub&gt;m&lt;/sub&gt;_, _y&lt;sub&gt;m&lt;/sub&gt;_)]), where _x_ is the share ID and _y_ is the byte-vector of the share&apos;s mnemonic&apos;s entropy
3. Using _E_ as the underlying entropy, [generate a mnemonic](#generating-the-mnemonic) and return it

## Rationale

### Choice of Field

The field GF(256) was chosen, because the field arithmetic is easy to implement in any programming language and many implementations are already available since it is used in the AES cipher. Although using GF(256) requires that we convert the mnemonic to its underlying entropy as a byte-vector, this is also easy to implement and many implementations of it exist in a variety of programming languages.

GF(2048) was also considered. Using GF(2048), we could have applied Shamir&apos;s Scheme directly to the mnemonic, using the word indexes as the values. This would have allowed us to avoid converting the mnemonic to its underlying entropy. But, the resulting shares would not have been valid BIP-39 mnemonics - the checksum portion would not be a valid checksum of the entropy. And, working around this would add considerable complexity.

Another option was GF(2&lt;sup&gt;_n_&lt;/sup&gt;) where _n_ is the size of the entropy in bits. We&apos;d still convert the mnemonic to entropy, but then apply Shamir&apos;s Scheme over the entire entropy rather than on a vector of values. The downside of this approach is we&apos;d need a different field for each mnemonic strength along with an associated irreducible polynomial. Additionally, this would require working with very large numbers that can be cumbersome to work with in some languages.

### Valid Share Mnemonics and Share IDs

The shares produced by the specification include an ID, in addition to the BIP-39 mnemonic.

Other options could have encoded the share ID into the mnemonic, simplifying storage - only the mnemonic would need to be stored.

One possibility would be to store the ID instead of the checksum in the mnemonic. The downside of this approach is that the shares would not be _valid_ BIP-39 mnemonics because the &quot;checksum&quot; section of the mnemonic would not match the &quot;entropy&quot; section. Shares with valid BIP-39 mnemonics are useful because they are indistinguishable from any other. And users could store the ID in a variety of ways that obscure it.

### Validation on Recovery

We decided _not_ to include a validation mechanism on recovering the original mnemonic. This leaks less information to a potential attacker. There is no indication they&apos;ve gotten the requisite number of shares until they&apos;ve obtained _T_ + 1 shares.

We could provide recovery validation by replacing one of the random coefficients with a checksum of the original mnemonic. Then, when recovering the original mnemonic and the polynomial, we could validate that the checksum coefficient is the valid checksum of recovered mnemonic.

## Test Cases

Coming soon.

All implementations must be able to:

- Split and recover each `mnemonic` with the given `numShares` and `threshold`.
- Recover the `mnemonic` from the given `knownShares`.

## Security Considerations

The shares produced by the specification include an ID in addition to the BIP-39 mnemonic. This raises two security concerns:

Users **must** keep this ID in order to recover the original mnemonic. If the ID is lost, or separated from the share mnemonic, it may not be possible to recover the original. (Brute force recovery may or may not be possible depending on how much is known about the number of shares and threshold)

The additional data may hint to an attacker of the existence of other keys and the scheme under which they are stored. Therefore, the ID should be stored in a way that obscures its use.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 29 Mar 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3450</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3450</guid>
      </item>
    
      <item>
        <title>SUDO Opcode</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3455-sudo-opcode/5860</comments>
        
        <description>## Abstract
A new opcode, `SUDO`, is introduced with the same parameters as `CALL`, plus another parameter to specify the sender address.

## Motivation
There are many use cases for being able to set the sender.

Many tokens are stuck irretrievably because nobody has the key for the owner address.
In particular, at address zero there is approximately 17 billion USD in tokens and ether, according to etherscan.
With `SUDO`, anyone could free that value, leading to an economic boom that would end poverty and world hunger.
Instead it is sitting there idle like the gold in Fort Knox.
`SUDO` fixes this.

It is a common mistake to send [ERC-20](/EIPs/EIPS/eip-20) tokens to the token address instead of the intended recipient.
This happens because users paste the token address into the recipient fields.
Currently there is no way to recover these tokens.
`SUDO` fixes this.

Many scammers have fraudulently received tokens and ETH via trust-trading.
Their victims currently have no way to recover their funds.
`SUDO` fixes this.

Large amounts of users have accidentally locked up tokens and ether by losing their private keys.
This is inefficient and provides a bad user experience.
To accommodate new and inexperienced users, there needs to be a way to recover funds after the private key has been lost.
`SUDO` fixes this.

Finally, there are many tokens and ether sitting in smart contracts locked due to a bug.
We could finally close EIP issue #156.
We cannot currently reclaim ether from stuck accounts.
`SUDO` fixes this.

## Specification
Adds a new opcode (`SUDO`) at `0xf8`.
`SUDO` pops 8 parameters from the stack.
Besides the sender parameter, the parameters shall match `CALL`.

1. Gas: Integer; Maximum gas allowance for message call, safely using current gas counter if the counter is lower
2. Sender: Address, truncated to lower 40 bytes; Sets `CALLER` inside the call frame
3. To: Address, truncated to lower 40 bytes; sets `ADDRESS`
4. Value: Integer, raises exception amount specified is less than the value in Sender account; transferred with call to recipient balance, sets `CALLVALUE`
5. InStart: Integer; beginning of memory to use for `CALLDATA`
6. InSize: Integer; length of memory to use for `CALLDATA`
7. OutStart: Integer; beginning of memory to replace with `RETURNDATA`
8. OutSize: Integer; maximum `RETURNDATA` to place in memory

Following execution, `SUDO` pushes a result value to the stack, indicating success or failure.
If the call ended with `STOP`, `RETURN`, or `SELFDESTRUCT`, `1` is pushed.
If the call ended with `REVERT`, `INVALID`, or an EVM assertion, `0` is pushed.

## Rationale
The `GAS` parameter is first so that callers can tediously compute how much of their remaining gas to send at the last possible moment.
The remaining parameters inherited from `CALL` are in the same order, with sender inserted between.


## Security Considerations
It will be fine.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 01 Apr 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3455</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3455</guid>
      </item>
    
      <item>
        <title>Abstract Storage Bonds</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3475-multiple-callable-bonds-standard/8691</comments>
        
        <description>## Abstract

- This EIP allows the creation of tokenized obligations with abstract on-chain metadata storage. Issuing bonds with multiple redemption data cannot be achieved with existing token standards.

- This EIP enables each bond class ID to represent a new configurable token type and corresponding to each class, corresponding bond nonces to represent an issuing condition or any other form of data in uint256. Every single nonce of a bond class can have its metadata, supply, and other redemption conditions.

- Bonds created by this EIP can also be batched for issuance/redemption conditions for efficiency on gas costs and UX side. And finally, bonds created from this standard can be divided and exchanged in a secondary market.

## Motivation

Current LP (Liquidity Provider) tokens are simple [EIP-20](/EIPs/EIPS/eip-20) tokens with no complex data structure. To allow more complex reward and redemption logic to be stored on-chain, we need a new token standard that:

- Supports multiple token IDs
- Can store on-chain metadata
- Doesn&apos;t require a fixed storage pattern
- Is gas-efficient.

Also Some benefits:

- This EIP allows the creation of any obligation with the same interface.
- It will enable any 3rd party wallet applications or exchanges to read these tokens&apos; balance and redemption conditions. 
- These bonds can also be batched as tradeable instruments. Those instruments can then be divided and exchanged in secondary markets.

## Specification

**Definition**

Bank: an entity that issues, redeems, or burns bonds after getting the necessary amount of liquidity. Generally, a single entity with admin access to the pool.

**Functions**

```solidity
pragma solidity ^0.8.0;

/**
* transferFrom
* @param _from argument is the address of the bond holder whose balance is about to decrease.
* @param _to argument is the address of the bond recipient whose balance is about to increase.
* @param _transactions is the `Transaction[] calldata` (of type [&apos;classId&apos;, &apos;nonceId&apos;, &apos;_amountBonds&apos;]) structure defined in the rationale section below.
* @dev transferFrom MUST have the `isApprovedFor(_from, _to, _transactions[i].classId)` approval to transfer `_from` address to `_to` address for given classId (i.e for Transaction tuple corresponding to all nonces).
e.g:
* function transferFrom(0x2d03B6C79B75eE7aB35298878D05fe36DC1fE8Ef, 0x82a55a613429Aeb3D01fbE6841bE1AcA4fFD5b2B, [IERC3475.Transaction(1,14,500)]);
* transfer from `_from` address, to `_to` address, `500000000` bonds of type class`1` and nonce `42`.
*/

function transferFrom(address _from, address _to, Transaction[] calldata _transactions) external;

/**
* transferAllowanceFrom
* @dev allows the transfer of only those bond types and nonces being allotted to the _to address using allowance().
* @param _from is the address of the holder whose balance is about to decrease.
* @param _to is the address of the recipient whose balance is about to increase.
* @param _transactions is the `Transaction[] calldata` structure defined in the section `rationale` below.
* @dev transferAllowanceFrom MUST have the `allowance(_from, msg.sender, _transactions[i].classId, _transactions[i].nonceId)` (where `i` looping for [ 0 ...Transaction.length - 1] ) 
e.g:
* function transferAllowanceFrom(0x2d03B6C79B75eE7aB35298878D05fe36DC1fE8Ef, 0x82a55a613429Aeb3D01fbE6841bE1AcA4fFD5b2B, [IERC3475.Transaction(1,14,500)]);
* transfer from `_from` address, to `_to` address, `500000000` bonds of type class`1` and nonce `42`.
*/

function transferAllowanceFrom(address _from,address _to, Transaction[] calldata _transactions) public ;

/**
* issue 
* @dev allows issuing any number of bond types (defined by values in Transaction tuple as param) to an address.
* @dev it MUST be issued by a single entity (for instance, a role-based ownable contract that has integration with the liquidity pool of the deposited collateral by `_to` address).
* @param `_to` argument is the address to which the bond will be issued.
* @param `_transactions` is the `Transaction[] calldata` (ie array of issued bond class, bond nonce and amount of bonds to be issued).
* @dev transferAllowanceFrom MUST have the `allowance(_from, msg.sender, _transactions[i].classId, _transactions[i].nonceId)` (where `i` looping for [ 0 ...Transaction.length - 1] ) 
e.g:
example: issue(0x2d03B6C79B75eE7aB35298878D05fe36DC1fE8Ef,[IERC3475.Transaction(1,14,500)]);
issues `1000` bonds with a class of `0` to address `0x2d03B6C79B75eE7aB35298878D05fe36DC1fE8Ef` with a nonce of `5`.
*/
function issue(address _to, Transaction[] calldata _transaction) external; 

/**
* redeem
* @dev permits redemption of bond from an address.
* @dev the calling of this function needs to be restricted to the bond issuer contract.
* @param `_from` is the address from which the bond will be redeemed.
* @param `_transactions` is the `Transaction[] calldata` structure (i.e., array of tuples with the pairs of (class, nonce and amount) of the bonds that are to be redeemed). Further defined in the rationale section.
* @dev redeem function for a given class, and nonce category MUST BE done after certain conditions for maturity (can be end time, total active liquidity, etc.) are met. 
* @dev furthermore, it SHOULD ONLY be called by the bank or secondary market maker contract.
e.g:
* redeem(0x2d03B6C79B75eE7aB35298878D05fe36DC1fE8Ef, [IERC3475.Transaction(1,14,500)]);
means “redeem from wallet address(0x2d03B6C79B75eE7aB35298878D05fe36DC1fE8Ef), 500000000 of bond class1 and nonce 42.
*/

function redeem(address _from, Transaction[] calldata _transactions) external; 

/**
* burn
* @dev permits nullifying of the bonds (or transferring given bonds to address(0)).
* @dev burn function for given class and nonce MUST BE called by only the controller contract.
* @param _from is the address of the holder whose bonds are about to burn.
* @param `_transactions` is the `Transaction[] calldata` structure (i.e., array of tuple with the pairs of (class, nonce and amount) of the bonds that are to be burned). further defined in the rationale.
* @dev burn function for a given class, and nonce category MUST BE done only after certain conditions for maturity (can be end time, total active liquidity, etc). 
* @dev furthermore, it SHOULD ONLY be called by the bank or secondary market maker contract.
* e.g:  
* burn(0x82a55a613429Aeb3D01fbE6841bE1AcA4fFD5b2B,[IERC3475.Transaction(1,14,500)]);
* means burning 500000000 bonds of class 1 nonce 42 owned by address 0x82a55a613429Aeb3D01fbE6841bE1AcA4fFD5b2B.
*/
function burn(address _from, Transaction[] calldata _transactions) external; 

/**
* approve
* @dev Allows `_spender` to withdraw from the msg.sender the bonds of `_amount` and type (classId and nonceId).
* @dev If this function is called again, it overwrites the current allowance with the amount.
* @dev `approve()` should only be callable by the bank, or the owner of the account.
* @param `_spender` argument is the address of the user who is approved to transfer the bonds.
* @param `_transactions` is the `Transaction[] calldata` structure (ie array of tuple with the pairs of (class,nonce, and amount) of the bonds that are to be approved to be spend by _spender). Further defined in the rationale section.
* e.g: 
* approve(0x82a55a613429Aeb3D01fbE6841bE1AcA4fFD5b2B,[IERC3475.Transaction(1,14,500)]);
* means owner of address 0x82a55a613429Aeb3D01fbE6841bE1AcA4fFD5b2B is approved to manage 500 bonds from class 1 and Nonce 14.
*/

function approve(address _spender, Transaction[] calldata _transactions) external;

/**
* SetApprovalFor
* @dev enable or disable approval for a third party (“operator”) to manage all the Bonds in the given class of the caller’s bonds.
* @dev If this function is called again, it overwrites the current allowance with the amount.
* @dev `approve()` should only be callable by the bank or the owner of the account.
* @param `_operator` is the address to add to the set of authorized operators.
* @param `classId` is the class id of the bond.
* @param `_approved` is true if the operator is approved (based on the conditions provided), false meaning approval is revoked.
* @dev contract MUST define internal function regarding the conditions for setting approval and should be callable only by bank or owner.
* e.g: setApprovalFor(0x82a55a613429Aeb3D01fbE6841bE1AcA4fFD5b2B,0,true);
* means that address 0x82a55a613429Aeb3D01fbE6841bE1AcA4fFD5b2B is authorized to transfer bonds from class 0 (across all nonces).
*/

function setApprovalFor(address _operator, bool _approved) external returns(bool approved);

/**
* totalSupply
* @dev Here, total supply includes burned and redeemed supply.
* @param classId is the corresponding class Id of the bond.
* @param nonceId is the nonce Id of the given bond class.
* @return the supply of the bonds
* e.g:
* totalSupply(0, 1);
* it finds the total supply of the bonds of classid 0 and bond nonce 1.
*/
function totalSupply(uint256 classId, uint256 nonceId) external view returns (uint256);

/**
* redeemedSupply
* @dev Returns the redeemed supply of the bond identified by (classId,nonceId).
* @param classId is the corresponding class id of the bond.
* @param nonceId is the nonce id of the given bond class.
* @return the supply of bonds redeemed.
*/
function redeemedSupply(uint256 classId, uint256 nonceId) external view returns (uint256);

/**
* activeSupply
* @dev Returns the active supply of the bond defined by (classId,NonceId).
* @param classId is the corresponding classId of the bond.
* @param nonceId is the nonce id of the given bond class.
* @return the non-redeemed, active supply. 
*/
function activeSupply(uint256 classId, uint256 nonceId) external view returns (uint256);

/**
* burnedSupply
* @dev Returns the burned supply of the bond in defined by (classId,NonceId).
* @param classId is the corresponding classId of the bond.
* @param nonceId is the nonce id of the given bond class.
* @return gets the supply of bonds for given classId and nonceId that are already burned.
*/
function burnedSupply(uint256 classId, uint256 nonceId) external view returns (uint256);

/**
* balanceOf
* @dev Returns the balance of the bonds (nonReferenced) of given classId and bond nonce held by the address `_account`.
* @param classId is the corresponding classId of the bond.
* @param nonceId is the nonce id of the given bond class.
* @param _account address of the owner whose balance is to be determined.
* @dev this also consists of bonds that are redeemed.
*/
function balanceOf(address _account, uint256 classId, uint256 nonceId) external view returns (uint256);

/**
* classMetadata
* @dev Returns the JSON metadata of the classes.
* @dev The metadata SHOULD follow a set of structures explained later in the metadata.md
* @param metadataId is the index-id given bond class information.
* @return the JSON metadata of the nonces. — e.g. `[title, type, description]`.
*/
function classMetadata(uint256 metadataId) external view returns (Metadata memory);

/**
* nonceMetadata 
* @dev Returns the JSON metadata of the nonces.
* @dev The metadata SHOULD follow a set of structures explained later in metadata.md
* @param classId is the corresponding classId of the bond.
* @param nonceId is the nonce id of the given bond class.
* @param metadataId is the index of the JSON storage for given metadata information. more is defined in metadata.md.
* @returns the JSON metadata of the nonces. — e.g. `[title, type, description]`.
*/
function nonceMetadata(uint256 classId, uint256 metadataId) external view returns (Metadata memory);

/**
* classValues
* @dev allows anyone to read the values (stored in struct Values for different class) for given bond class `classId`.
* @dev the values SHOULD follow a set of structures as explained in metadata along with correct mapping corresponding to the given metadata structure
* @param classId is the corresponding classId of the bond.
* @param metadataId is the index of the JSON storage for given metadata information of all values of given metadata. more is defined in metadata.md.
* @returns the Values of the class metadata. — e.g. `[string, uint, address]`.
*/
function classValues(uint256 classId, uint256 metadataId) external view returns (Values memory);

/**
* nonceValues
* @dev allows anyone to read the values (stored in struct Values for different class) for given bond (`nonceId`,`classId`).
* @dev the values SHOULD follow a set of structures explained in metadata along with correct mapping corresponding to the given metadata structure
* @param classId is the corresponding classId of the bond.
* @param metadataId is the index of the JSON storage for given metadata information of all values of given metadata. More is defined in metadata.md.
* @returns the Values of the class metadata. — e.g. `[string, uint, address]`.
*/
function nonceValues(uint256 classId, uint256 nonceId, uint256 metadataId) external view returns (Values memory);

/**
* getProgress
* @dev Returns the parameters to determine the current status of bonds maturity.
* @dev the conditions of redemption SHOULD be defined with one or several internal functions. 
* @param classId is the corresponding classId of the bond.
* @param nonceId is the nonceId of the given bond class . 
* @returns progressAchieved defines the metric (either related to % liquidity, time, etc.) that defines the current status of the bond.
* @returns progressRemaining defines the metric that defines the remaining time/ remaining progress. 
*/
function getProgress(uint256 classId, uint256 nonceId) external view returns (uint256 progressAchieved, uint256 progressRemaining);

/** 
* allowance
* @dev Authorizes to set the allowance for given `_spender` by `_owner` for all bonds identified by (classId, nonceId).
* @param _owner address of the owner of bond(and also msg.sender).
* @param _spender is the address authorized to spend the bonds held by _owner of info (classId, nonceId).
* @param classId is the corresponding classId of the bond.
* @param nonceId is the nonceId of the given bond class. 
* @notice Returns the _amount which spender is still allowed to withdraw from _owner.
*/
function allowance(address _owner, address _spender, uint256 classId, uint256 nonceId) external returns(uint256);

/** 
* isApprovedFor
* @dev returns true if address _operator is approved for managing the account’s bonds class.
* @notice Queries the approval status of an operator for a given owner.
* @dev _owner is the owner of bonds. 
* @dev _operator is the EOA /contract, whose status for approval on bond class for this approval is checked.
* @returns “true” if the operator is approved, “false” if not.
*/
function isApprovedFor(address _owner, address _operator) external view returns (bool);
```

### Events

```solidity
/** 
* Issue
* @notice Issue MUST trigger when Bonds are issued. This SHOULD not include zero value Issuing.
* @dev This SHOULD not include zero value issuing.
* @dev Issue MUST be triggered when the operator (i.e Bank address) contract issues bonds to the given entity.
* eg: emit Issue(_operator, 0x2d03B6C79B75eE7aB35298878D05fe36DC1fE8Ef,[IERC3475.Transaction(1,14,500)]); 
* issue by address(operator) 500 Bonds(nonce14,class 1) to address 0x2d03B6C79B75eE7aB35298878D05fe36DC1fE8Ef.
*/

event Issue(address indexed _operator, address indexed _to, Transaction[] _transactions); 

/** 
* Redeem
* @notice Redeem MUST trigger when Bonds are redeemed. This SHOULD not include zero value redemption.
*e.g: emit Redeem(0x2d03B6C79B75eE7aB35298878D05fe36DC1fE8Ef,0x492Af743654549b12b1B807a9E0e8F397E44236E,[IERC3475.Transaction(1,14,500)]);
* emit event when 5000 bonds of class 1, nonce 14 owned by address 0x492Af743654549b12b1B807a9E0e8F397E44236E are being redeemed by 0x2d03B6C79B75eE7aB35298878D05fe36DC1fE8Ef.
*/

event Redeem(address indexed _operator, address indexed _from, Transaction[] _transactions);


/** 
* Burn.
* @dev `Burn` MUST trigger when the bonds are being redeemed via staking (or being invalidated) by the bank contract.
* @dev `Burn` MUST trigger when Bonds are burned. This SHOULD not include zero value burning.
* e.g : emit Burn(0x2d03B6C79B75eE7aB35298878D05fe36DC1fE8Ef,0x492Af743654549b12b1B807a9E0e8F397E44236E,[IERC3475.Transaction(1,14,500)]);
* emits event when 500 bonds of owner 0x492Af743654549b12b1B807a9E0e8F397E44236E of type (class 1, nonce 14) are burned by operator  0x2d03B6C79B75eE7aB35298878D05fe36DC1fE8Ef.
*/

event burn(address _operator, address _owner, Transaction[] _transactions);

/** 
* Transfer
* @dev its emitted when the bond is transferred by address(operator) from owner address(_from) to address(_to) with the bonds transferred, whose params are defined by _transactions struct array. 
* @dev Transfer MUST trigger when Bonds are transferred. This SHOULD not include zero value transfers.
* @dev Transfer event with the _from `0x0` MUST not create this event(use `event Issued` instead). 
* e.g  emit Transfer(0x2d03B6C79B75eE7aB35298878D05fe36DC1fE8Ef, 0x492Af743654549b12b1B807a9E0e8F397E44236E, _to, [IERC3475.Transaction(1,14,500)]);
* transfer by address(_operator) amount 500 bonds with (Class 1 and Nonce 14) from 0x2d03B6C79B75eE7aB35298878D05fe36DC1fE8Ef, to address(_to).
*/

event Transfer(address indexed _operator, address indexed _from, address indexed _to, Transaction[] _transactions);

/**
* ApprovalFor
* @dev its emitted when address(_owner) approves the address(_operator) to transfer his bonds.
* @notice Approval MUST trigger when bond holders are approving an _operator. This SHOULD not include zero value approval. 
* eg: emit ApprovalFor(0x2d03B6C79B75eE7aB35298878D05fe36DC1fE8Ef, 0x492Af743654549b12b1B807a9E0e8F397E44236E, true);
* this means 0x2d03B6C79B75eE7aB35298878D05fe36DC1fE8Ef gives 0x492Af743654549b12b1B807a9E0e8F397E44236E access permission for transfer of its bonds.
*/

event ApprovalFor(address indexed _owner, address indexed _operator, bool _approved);
```

**Metadata**:
The metadata of a bond class or nonce is stored as an array of JSON objects, represented by the following types. 

**NOTE: all of the metadata schemas are referenced from [here](/EIPs/assets/eip-3475/Metadata)**

### 1. Description:

This defines the additional information about the nature of data being stored in the nonce/class metadata structures. They are defined using the structured explained [here](/EIPs/assets/eip-3475/Metadata#1-description-metadata). this will then be used by the frontend of the respective entities participating in the bond markets to interpret the data which is compliant with their jurisdiction. 

### 2. Nonce:

The key value for indexing the information is the &apos;class&apos; field. Following are the rules:

- The title can be any alphanumeric type that is differentiated by the description of metadata (although it can be dependent on certain jurisdictions).
- The title SHOULD not be EMPTY.

Some specific examples of metadata can be the localization of bonds, jurisdiction details etc., and they can be found in the [metadata.md](/EIPs/assets/eip-3475/Metadata) example description.

### 3. Class metadata:

This structure defines the details of the class information (symbol, risk information, etc.). the example is explained [here](/EIPs/assets/eip-3475/Metadata) in the class metadata section.

### 4. Decoding data

First, the functions for analyzing the metadata (i.e `ClassMetadata` and `NonceMetadata`) are to be used by the corresponding frontend to decode the information of the bond.

This is done via overriding the function interface for functions `classValues` and `nonceValues` by defining the key (which SHOULD be an index) to read the corresponding information stored as a JSON object.

```JSON
{
&quot;title&quot;: &quot;symbol&quot;,
&quot;_type&quot;: &quot;string&quot;,
&quot;description&quot;: &quot;defines the unique identifier name in following format: (symbol, bondType, maturity in months)&quot;,
&quot;values&quot;: [&quot;Class Name 1&quot;,&quot;Class Name 2&quot;,&quot;DBIT Fix 6M&quot;],
}
```

e.g. In the above example, to get the `symbol` of the given class id, we can use the class id as a key to get the `symbol` value in the values, which then can be used for fetching the detail for instance.

## Rationale

### Metadata structure

Instead of storing the details about the class and their issuances to the user (ie nonce) externally, we store the details in the respective structures. Classes represent the different bond types, and nonces represent the various period of issuances. Nonces under the same class share the same metadata. Meanwhile, nonces are non-fungible. Each nonce can store a different set of metadata. Thus, upon transfer of a bond, all the metadata will be transferred to the new owner of the bond.

```solidity
 struct Values{
 string stringValue;
 uint uintValue;
 address addressValue;
 bool boolValue;
 bytes bytesValue;
 }
```

```solidity
 struct Metadata {
 string title;
 string _type;
 string description;
 }
```

### Batch function

 This EIP supports batch operations. It allows the user to transfer different bonds along with their metadata to a new address instantaneously in a single transaction. After execution, the new owner holds the right to reclaim the face value of each of the bonds. This mechanism helps with the &quot;packaging&quot; of bonds–helpful in use cases like trades on a secondary market.

```solidity
 struct Transaction {
 uint256 classId;
 uint256 nonceId;
 uint256 _amount;
 }
```

Where:
The `classId` is the class id of the bond.

The `nonceId` is the nonce id of the given bond class. This param is for distinctions of the issuing conditions of the bond.

The `_amount` is the amount of the bond for which the spender is approved.

### AMM optimization

 One of the most obvious use cases of this EIP is the multilayered pool. The early version of AMM uses a separate smart contract and an [EIP-20](/EIPs/EIPS/eip-20) LP token to manage a pair. By doing so, the overall liquidity inside of one pool is significantly reduced and thus generates unnecessary gas spent and slippage. Using this EIP standard, one can build a big liquidity pool with all the pairs inside (thanks to the presence of the data structures consisting of the liquidity corresponding to the given class and nonce of bonds). Thus by knowing the class and nonce of the bonds, the liquidity can be represented as the percentage of a given token pair for the owner of the bond in the given pool. Effectively, the [EIP-20](/EIPs/EIPS/eip-20) LP token (defined by a unique smart contract in the pool factory contract) is aggregated into a single bond and consolidated into a single pool.

- The reason behind the standard&apos;s name (abstract storage bond) is its ability to store all the specifications (metadata/values and transaction as defined in the following sections) without needing external storage on-chain/off-chain.

## Backwards Compatibility

Any contract that inherits the interface of this EIP is compatible. This compatibility exists for issuer and receiver of the bonds. Also any client EOA wallet can be compatible with the standard if they are able to sign `issue()` and `redeem()` commands.

However, any existing [EIP-20](/EIPs/EIPS/eip-20) token contract can issue its bonds by delegating the minting role to a bank contract with the interface of this standard built-in. Check out our reference implementation for the correct interface definition.

To ensure the indexing of transactions throughout the bond lifecycle (i.e &quot;Issue&quot;, &quot;Redeem&quot; and &quot;Transfer&quot; functions), events cited in specification section MUST be emitted when such transaction is passed.

**Note that the this standard interface is also compatible with [EIP-20](/EIPs/EIPS/eip-20) and [EIP-721](/EIPs/EIPS/eip-721) and [EIP-1155](/EIPs/EIPS/eip-1155)interface.**

However, creating a separate bank contract is recommended for reading the bonds and future upgrade needs.

Acceptable collateral can be in the form of fungible (like [EIP-20](/EIPs/EIPS/eip-20)), non-fungible ([EIP-721](/EIPs/EIPS/eip-721), [EIP-1155](/EIPs/EIPS/eip-1155)) , or other bonds represented by this standard.

## Test Cases

Test-case for the minimal reference implementation is [here](/EIPs/assets/eip-3475/ERC3475.test.ts). Use the Truffle box to compile and test the contracts.

## Reference Implementation

- [Interface](/EIPs/assets/eip-3475/interfaces/IERC3475.sol).

- [Basic Example](/EIPs/assets/eip-3475/ERC3475.sol).
  - This demonstration shows only minimalist implementation.

## Security Considerations

- The `function setApprovalFor(address _operatorAddress)` gives the operator role to `_operatorAddress`. It has all the permissions to transfer, burn and redeem bonds by default.

- If the owner wants to give a one-time allocation to an address for specific bonds(classId,bondsId), he should call the `function approve()` giving the `Transaction[]` allocated rather than approving all the classes using `setApprovalFor`.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 05 Apr 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3475</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3475</guid>
      </item>
    
      <item>
        <title>Transaction Data Opcodes</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-draft-transaction-data-opcodes/6017</comments>
        
        <description>## Simple Summary

Provide access to original transaction data.

## Abstract

This EIP introduces the following three EVM instructions: `ORIGINDATALOAD`, `ORIGINDATASIZE`, and `ORIGINDATACOPY`.

These three instructions are meant to provide access to the original transaction&apos;s `data` payload, enabling a gas-efficient way of accessing large data payloads in cross-contract calls.

## Motivation

As the Ethereum development scene matures, more ambitious and complex features are introduced into smart contracts more often than not requiring the utilization of complex and at times large data structures. Given the inherent limits of the EVM, however, transporting large data structures in between contracts is a costly task that can at times lead to even futile scenarios whereby the gas consumption of such an operation is impossible to execute within the gas limit bounds as well as without sacrificing a large chunk of ETH to facilitate its gas cost.

The purpose of this EIP is to render these features viable by introducing a way via which multi-contract systems are able to access the same in-memory data source without necessarily transmitting the full payload between them.

This EIP enables elaborate smart contract features to become part of a larger call-chain by efficiently reading data from the original transaction payload rather than requiring the data to be passed in as call-level data. Its inclusion will mainly benefit advanced trustless schemes to manifest, such as efficient verification of Merkle Patricia trees validating the storage value of a particular Ethereum block or EVM-based layer 2 solutions.

A side-effect of this change is that smart contract systems relying entirely on origin data inherently guarantee that the data they receive has not been malformed by an intermediate smart contract call.

## Specification

### ORIGINDATALOAD (`0x47`), ORIGINDATASIZE (`0x48`) and ORIGINDATACOPY (`0x49`)

These instructions are meant to operate similarly to their call-prefixed counterparts with the exception that they instead operate on the original `data` of a transaction instead of the current call&apos;s data. In detail:

- ORIGINDATALOAD (`0x47`) performs similarly to CALLDATALOAD (`0x35`)
- ORIGINDATASIZE (`0x48`) performs similarly to CALLDATASIZE (`0x36`)
- ORIGINDATACOPY (`0x49`) performs similarly to CALLDATACOPY (`0x37`)

As the data is retrieved once again from the execution environment, the costs for the three instructions will be `G_verylow`, `G_base` and `G_base + G_verylow * (number of words copied, rounded up)` respectively.

The transaction data the `ORIGINDATA*` opcodes operate on will be equivalent to the `calldata` specified in the `args*` parameter to the nearest `AUTHCALL` (`0xf7`) up the stack.  If there is no `AUTHCALL` in the stack then `ORIGINDATA*` will operate on the transaction&apos;s original `data` field.

This interaction ensures full compatibility with [EIP-3074](/EIPs/EIPS/eip-3074) and ensures that no form of discrimination is introduced back into the system by this EIP e.g. by contracts entirely relying on `ORIGINDATA*` and thus allowing only EOAs to supply data to them.

## Rationale

### AUTHCALL (`0xf7`) Interaction

The [EIP-3074](/EIPs/EIPS/eip-3074) that will be part of the London fork has introduced a new call instruction called `AUTHCALL` (`0xf7`) that will replace a transaction&apos;s `ORIGIN` (`0x32`) with the context variable `authorized`. The intention of `AUTHCALL` is to prevent discrimination between smart contracts and EOAs which `ORIGIN` initially facilitated and as a result, it is sensible also replace the values retrieved by the `ORIGINDATA*` opcodes to the ones used in the `AUTHCALL`.

### Naming Conventions

The `ORIGIN`-prefixed instructions attempted to conform to the existing naming convention of `CALL`-prefixed instructions given the existence of the `ORIGIN` (`0x32`) instruction which is equivalent to the `CALLER` (`0x33`) instruction but on the original transaction&apos;s context.

### Instruction Address Space

The instruction address space of the `0x30-0x3f` has been exhausted by calls that already provide information about the execution context of a call so a new range had to be identified that is suitable for the purposes of the EIP.

Given that the [EIP-1344](/EIPs/EIPS/eip-1344) `CHAINID` opcode was included at `0x46`, it made sense to include additional transaction-related data beyond it since the Chain ID is also included in transaction payloads apart from the blocks themselves, rendering the `0x46-0x4f` address space reserved for more transaction-related data that may be necessary in the future, such as the EOA&apos;s nonce.

### Gas Costs

The opcodes ORIGINDATALOAD (`0x47`), ORIGINDATASIZE (`0x48`), and ORIGINDATACOPY (`0x49`) essentially perform the same thing as opcodes CALLDATALOAD (`0x35`), CALLDATASIZE (`0x36`), and CALLDATACOPY (`0x37`) respectively and thus share the exact same gas costs.

### Instruction Space Pollution

One can argue that multiple new EVM instructions pollute the EVM instruction address space and could cause issues in assigning sensible instruction codes to future instructions. This particular issue was assessed and a methodology via which the raw RLP encoded transaction may be accessible to the EVM was ideated. This would _future-proof_ the new instruction set as it would be usable for other members of the transaction that may be desired to be accessible on-chain in the future, however, it would also cause a redundancy in the `ORIGIN` opcode.

## Backwards Compatibility

The EIP does not alter or adjust existing functionality provided by the EVM and as such, no known issues exist.

## Test Cases

TODO.

## Security Considerations

### Introspective Contracts

Atomically, the `ORIGINDATALOAD` and `ORIGINDATACOPY` values should be considered insecure as they can easily be spoofed by creating an entry smart contract with the appropriate function signature and arguments that consequently invokes other contracts within the call chain. In brief, one should always assume that `tx.data != calldata` and these instructions should not be used as an introspection tool alone.

### Denial-of-Service Attack

An initial concern that may arise from this EIP is the additional contextual data that must be provided at the software level of nodes to the EVM in order for it to be able to access the necessary data via the `ORIGINDATALOAD` and `ORIGINDATACOPY` instructions.

This would lead to an increase in memory consumption, however, this increase should be negligible if at all existent given that the data of a transaction should already exist in memory as part of its execution process; a step in the overall inclusion of a transaction within a block.

### Multi-Contract System Gas Reduction

Given that most complex smart contract systems deployed on Ethereum today rely on cross-contract interactions whereby values are passed from one contract to another via function calls, the `ORIGIN`-prefixed instruction set would enable a way for smart contract systems to acquire access to the original transaction data at any given step in the call chain execution which could result in cross-contract calls ultimately consuming less gas if the data passed between them is reduced as a side-effect of this change.

The gas reduction, however, would be an implementation-based optimization that would also be solely applicable for rudimentary memory arguments rather than storage-based data, the latter of which is most commonly utilized in these types of calls. As a result, the overall gas reduction observed by this change will be negligible for most implementations.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 16 Apr 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3508</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3508</guid>
      </item>
    
      <item>
        <title>Transaction Destination Opcode</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3520-transaction-destination-opcode/6058</comments>
        
        <description>## Simple Summary

Provide access to the original recipient of a transaction.

## Abstract

This EIP introduces the following EVM instruction: `ENTRYPOINT`.

This instruction is meant to provide access to the original recipient of the transaction, the `to` address, enabling new ways of introspection to be applied in conjunction with [EIP-3508](/EIPs/EIPS/eip-3508).

## Motivation

It is undeniable that smart contracts are becoming more interconnected than ever. Up until this point, smart contracts have entirely relied on compliant interfaces and introspection to introduce a new step in the call chain of a complex multi-contract interaction. However, this presents a forwards-only approach which limits the types of interactions that can manifest.

The purpose of this EIP is to provide a way via which a contract is able to identify the entry-point of a transaction on the blockchain and deduce what was the original intention of the transaction by applying introspection on the original transaction data itself.

This EIP enables the development of new types of smart contracts as it can open new pathways for [EIP-721](./eip-721) NFTs and [EIP-20](./eip-20) tokens to detect which action their transaction is part of, such as detecting a liquidity provision to a decentralized exchange or a loan within a collateralized lending protocol.

## Specification

### ENTRYPOINT (`0x4a`)

The `ENTRYPOINT` instruction uses 0 stack arguments and pushes the original `to` member of the transaction onto the stack. The address yielded by the instruction is a 160-bit value padded to 256-bits. The operation costs `G_base` to execute, similarly to `ORIGIN` (`0x32`).

The address returned by the `ENTRYPOINT` opcode will be equivalent to the `to` address parameter specified in the nearest `AUTHCALL` up the stack.  If there is no `AUTHCALL` in the stack then `ENTRYPOINT` will retrieve the original transaction&apos;s `to` field.

## Rationale

### AUTHCALL (`0xf7`) Interaction

The [EIP-3074](/EIPs/EIPS/eip-3074) introduced a new call instruction called `AUTHCALL` (`0xf7`) that will replace a transaction&apos;s `ORIGIN` (`0x32`) with the context variable `authorized`. The intention of `AUTHCALL` is to prevent discrimination between smart contracts and EOAs which `ORIGIN` initially facilitated. The `ENTRYPOINT` opcode by itself re-introduces discrimination into the system as it indirectly allows one to evaluate whether the smart contract code being executed is done so by an EOA by validating that `ENTRYPOINT == ADDRESS` where `ADDRESS` (`0x30`) retrieves the currently executing account address. Therefore, it is sensible also replace the values retrieved by the `ENTRYPOINT` opcode to the target of an `AUTHCALL`.

This interaction ensures full compatibility with [EIP-3074](/EIPs/EIPS/eip-3074) and ensures that no form of discrimination is introduced back into the system by this EIP.

### Naming Conventions

The `ENTRYPOINT` instruction came to be by defining a sensible name that immediately and clearly depicts what it is meant to achieve by signaling the first interaction of a particular call, i.e. the entry-point.

### Instruction Address Space

Equivalent to [EIP-3508](./eip-3508).

### Gas Cost

The opcode ENTRYPOINT (`0x4a`) essentially performs the same thing as the opcode ORIGIN (`0x32`) and thus shares the exact same gas cost.

### Dependency on EIP-3508

The `ENTRYPOINT` (`0x4a`) instruction alone has no perceivable benefit as it can be replaced by the `AUTHCALL` (`0xf7`) instruction and as such should solely be introduced to the system in conjunction with the `ORIGINDATA*` opcodes defined in [EIP-3508](/EIPs/EIPS/eip-3508).

## Backwards Compatibility

The EIP does not alter or adjust existing functionality provided by the EVM and as such, no known issues exist.

## Test Cases

TODO.

## Security Considerations

### Introspective Contracts

The `ENTRYPOINT` instruction allows the association of the `ORIGINDATALOAD` and `ORIGINDATACOPY` values with a particular smart contract address and interface, enabling introspection to be applied based on the function signature invoked and the arguments provided to reliably deduce the call-path via which a particular smart contract was invoked and allowing a more granular level of interaction to be defined in such special cases.

However, this type of introspection should solely be applied on pre-approved contracts rather than user-defined ones as the value stemming from this type of introspection entirely relies on a contract&apos;s code immutability and proper function, both of which a user supplied contract can easily bypass.

### Caller Discrimination

The instructions of this EIP should not be utilized as a way to discriminate between EOA callers and smart contracts, as this type of differentiation can be broken by an `AUTHCALL` as defined in the specification chapter.

### Contract Creation Behaviour

The behaviour of the `ENTRYPOINT` opcode during a contract creation will result in the opcode yielding the zero-address as the first address interacted with in the transaction. This should be taken into account by contract implementations in a similar fashion to how `ecrecover` invalid signatures are handled to prevent software misbehaviours from arising.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 16 Apr 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3520</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3520</guid>
      </item>
    
      <item>
        <title>Reduce access list cost</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3521-reduce-access-list-cost/6072</comments>
        
        <description>## Simple Summary

Reduce the cost of declaring `tx.to` storage keys in access lists.

## Motivation

Currently, a transaction must read at least 25 distinct storage slots in `tx.to`
before it&apos;s more expensive to forego an access list.

```
ACCESS_LIST_ADDRESS_COST + (ACCESS_LIST_STORAGE_KEY_COST + WARM_STORAGE_READ_COST) * x = COLD_SLOAD_COST * x
x = 24
```

EIP-2930 requires the address under which the storage keys reside be declared
explicitly, since it must be added to the EIP-2929 `accessed_addresses` list.
However, `tx.to` is a special case that is added by default, so paying
`ACCESS_LIST_ADDRESS_COST` for `tx.to` is essentially paying twice for the same
address. Avoiding overpayment here will reduce the differential to just 5 unique
reads before using an access list is cheaper -- making them a more attractive
option.

## Specification

Treat the first occurrence of `tx.to` in an access list as `calldata` for gas
accounting purposes. Do not charge `ACCESS_LIST_ADDRESS_COST` for it. Storage
keys underneath the address are unaffected.

If `tx.to == nil`, `tx.to` is defined be the derived contract address created by
the transaction.

##  Rationale

### Why charge at all?

EIP-2930 is specifically written to make access lists simple to reason about and
validate. It may be possible to modify the structure of the access list to avoid
including `tx.to` explicitly, but this would renege on the spirit of EIP-2930.

### Why charge as `calldata`?

The cost of `calldata` was  thoroughly analyzed in EIP-2028 to determine
a fair value that is not susceptible to denial-of-service attacks. We consider
this the lower bound on how much transaction data should cost. Since there is
no computation burden imposed for adding `tx.to` to the `accessed_addresses`
map (it&apos;s added by default by [EIP-2929](/EIPs/EIPS/eip-2929)), there is no reason to charge more than
the absolute minimum for the data.

## Test Cases
```
{
    &quot;0xffffffffffffffffffffffffffffffffffffffff&quot;: []
}
cost = 320

{
    &quot;0x00ffffffffffffffffffffffffffffffffffffff&quot;: []
}
cost = 308

{
    &quot;0xffffffffffffffffffffffffffffffffffffffff&quot;: []
    &quot;0xffffffffffffffffffffffffffffffffffffffff&quot;: []
}
cost = 2720

{
    &quot;0xffffffffffffffffffffffffffffffffffffffff&quot;: [
        &quot;0x00&quot;
    ]
    &quot;0xffffffffffffffffffffffffffffffffffffffff&quot;: []
}
cost = 4620

{
    &quot;0xffffffffffffffffffffffffffffffffffffffff&quot;: [
        &quot;0x00&quot;
    ]
    &quot;0xffffffffffffffffffffffffffffffffffffffff&quot;: [
        &quot;0x00&quot;
    ]
}
cost = 6520
```

## Backwards Compatibility
No issues.

## Security Considerations
None.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 15 Apr 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3521</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3521</guid>
      </item>
    
      <item>
        <title>Semi-Fungible Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3525-the-semi-fungible-token</comments>
        
        <description>## Abstract

This is a standard for semi-fungible tokens. The set of smart contract interfaces described in this document defines an [ERC-721](/EIPs/EIPS/eip-721) compatible token standard. This standard introduces an `&lt;ID, SLOT, VALUE&gt;` triple scalar model that represents the semi-fungible structure of a token. It also introduces new transfer models as well as approval models that reflect the semi-fungible nature of the tokens.

Token contains an ERC-721 equivalent ID property to identify itself as a universally unique entity, so that the tokens can be transferred between addresses and approved to be operated in ERC-721 compatible way.

Token also contains a `value` property, representing the quantitative nature of the token. The meaning of the &apos;value&apos; property is quite like that of the &apos;balance&apos; property of an [ERC-20](/EIPs/EIPS/eip-20) token. Each token has a &apos;slot&apos; attribute, ensuring that the value of two tokens with the same slot be treated as fungible, adding fungibility to the value property of the tokens.

This EIP introduces new token transfer models for semi-fungibility, including value transfer between two tokens of the same slot and value transfer from a token to an address.

## Motivation

Tokenization is one of the most important trends by which to use and control digital assets in crypto. Traditionally, there have been two approaches to do so: fungible and non-fungible tokens. Fungible tokens generally use the ERC-20 standard, where every unit of an asset is identical to each other. ERC-20 is a flexible and efficient way to manipulate fungible tokens. Non-fungible tokens are predominantly ERC-721 tokens, a standard capable of distinguishing digital assets from one another based on identity. 

However, both have significant drawbacks. For example, ERC-20 requires that users create a separate ERC-20 contract for each individual data structure or combination of customizable properties. In practice, this results in an extraordinarily large amount of ERC-20 contracts that need to be created. On the other hand, ERC-721 tokens provide no quantitative feature, significantly undercutting their computability, liquidity, and manageability. For example, if one was to create financial instruments such as bonds, insurance policy, or vesting plans using ERC-721, no standard interfaces are available for us to control the value in them, making it impossible, for example, to transfer a portion of the equity in the contract represented by the token. 

A more intuitive and straightforward way to solve the problem is to create a semi-fungible token that has the quantitative features of ERC-20 and qualitative attributes of ERC-721. The backwards-compatibility with ERC-721 of such semi-fungible tokens would help utilize existing infrastructures already in use and lead to faster adoption.

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

**Every [ERC-3525](/EIPs/EIPS/eip-3525) compliant contract must implement the ERC-3525, ERC-721 and [ERC-165](/EIPs/EIPS/eip-165) interfaces**

```solidity
pragma solidity ^0.8.0;

/**
 * @title ERC-3525 Semi-Fungible Token Standard
 * Note: the ERC-165 identifier for this interface is 0xd5358140.
 */
interface IERC3525 /* is IERC165, IERC721 */ {
    /**
     * @dev MUST emit when value of a token is transferred to another token with the same slot,
     *  including zero value transfers (_value == 0) as well as transfers when tokens are created
     *  (`_fromTokenId` == 0) or destroyed (`_toTokenId` == 0).
     * @param _fromTokenId The token id to transfer value from
     * @param _toTokenId The token id to transfer value to
     * @param _value The transferred value
     */
    event TransferValue(uint256 indexed _fromTokenId, uint256 indexed _toTokenId, uint256 _value);

    /**
     * @dev MUST emit when the approval value of a token is set or changed.
     * @param _tokenId The token to approve
     * @param _operator The operator to approve for
     * @param _value The maximum value that `_operator` is allowed to manage
     */
    event ApprovalValue(uint256 indexed _tokenId, address indexed _operator, uint256 _value);
    
    /**
     * @dev MUST emit when the slot of a token is set or changed.
     * @param _tokenId The token of which slot is set or changed
     * @param _oldSlot The previous slot of the token
     * @param _newSlot The updated slot of the token
     */ 
    event SlotChanged(uint256 indexed _tokenId, uint256 indexed _oldSlot, uint256 indexed _newSlot);

    /**
     * @notice Get the number of decimals the token uses for value - e.g. 6, means the user
     *  representation of the value of a token can be calculated by dividing it by 1,000,000.
     *  Considering the compatibility with third-party wallets, this function is defined as
     *  `valueDecimals()` instead of `decimals()` to avoid conflict with ERC-20 tokens.
     * @return The number of decimals for value
     */
    function valueDecimals() external view returns (uint8);

    /**
     * @notice Get the value of a token.
     * @param _tokenId The token for which to query the balance
     * @return The value of `_tokenId`
     */
    function balanceOf(uint256 _tokenId) external view returns (uint256);

    /**
     * @notice Get the slot of a token.
     * @param _tokenId The identifier for a token
     * @return The slot of the token
     */
    function slotOf(uint256 _tokenId) external view returns (uint256);

    /**
     * @notice Allow an operator to manage the value of a token, up to the `_value`.
     * @dev MUST revert unless caller is the current owner, an authorized operator, or the approved
     *  address for `_tokenId`.
     *  MUST emit the ApprovalValue event.
     * @param _tokenId The token to approve
     * @param _operator The operator to be approved
     * @param _value The maximum value of `_toTokenId` that `_operator` is allowed to manage
     */
    function approve(
        uint256 _tokenId,
        address _operator,
        uint256 _value
    ) external payable;

    /**
     * @notice Get the maximum value of a token that an operator is allowed to manage.
     * @param _tokenId The token for which to query the allowance
     * @param _operator The address of an operator
     * @return The current approval value of `_tokenId` that `_operator` is allowed to manage
     */
    function allowance(uint256 _tokenId, address _operator) external view returns (uint256);

    /**
     * @notice Transfer value from a specified token to another specified token with the same slot.
     * @dev Caller MUST be the current owner, an authorized operator or an operator who has been
     *  approved the whole `_fromTokenId` or part of it.
     *  MUST revert if `_fromTokenId` or `_toTokenId` is zero token id or does not exist.
     *  MUST revert if slots of `_fromTokenId` and `_toTokenId` do not match.
     *  MUST revert if `_value` exceeds the balance of `_fromTokenId` or its allowance to the
     *  operator.
     *  MUST emit `TransferValue` event.
     * @param _fromTokenId The token to transfer value from
     * @param _toTokenId The token to transfer value to
     * @param _value The transferred value
     */
    function transferFrom(
        uint256 _fromTokenId,
        uint256 _toTokenId,
        uint256 _value
    ) external payable;


    /**
     * @notice Transfer value from a specified token to an address. The caller should confirm that
     *  `_to` is capable of receiving ERC-3525 tokens.
     * @dev This function MUST create a new ERC-3525 token with the same slot for `_to`, 
     *  or find an existing token with the same slot owned by `_to`, to receive the transferred value.
     *  MUST revert if `_fromTokenId` is zero token id or does not exist.
     *  MUST revert if `_to` is zero address.
     *  MUST revert if `_value` exceeds the balance of `_fromTokenId` or its allowance to the
     *  operator.
     *  MUST emit `Transfer` and `TransferValue` events.
     * @param _fromTokenId The token to transfer value from
     * @param _to The address to transfer value to
     * @param _value The transferred value
     * @return ID of the token which receives the transferred value
     */
    function transferFrom(
        uint256 _fromTokenId,
        address _to,
        uint256 _value
    ) external payable returns (uint256);
}
```

The slot&apos;s enumeration extension is OPTIONAL. This allows your contract to publish its full list of `SLOT`s and make them discoverable.

```solidity
pragma solidity ^0.8.0;

/**
 * @title ERC-3525 Semi-Fungible Token Standard, optional extension for slot enumeration
 * @dev Interfaces for any contract that wants to support enumeration of slots as well as tokens 
 *  with the same slot.
 * Note: the ERC-165 identifier for this interface is 0x3b741b9e.
 */
interface IERC3525SlotEnumerable is IERC3525 /* , IERC721Enumerable */ {

    /**
     * @notice Get the total amount of slots stored by the contract.
     * @return The total amount of slots
     */
    function slotCount() external view returns (uint256);

    /**
     * @notice Get the slot at the specified index of all slots stored by the contract.
     * @param _index The index in the slot list
     * @return The slot at `index` of all slots.
     */
    function slotByIndex(uint256 _index) external view returns (uint256);

    /**
     * @notice Get the total amount of tokens with the same slot.
     * @param _slot The slot to query token supply for
     * @return The total amount of tokens with the specified `_slot`
     */
    function tokenSupplyInSlot(uint256 _slot) external view returns (uint256);

    /**
     * @notice Get the token at the specified index of all tokens with the same slot.
     * @param _slot The slot to query tokens with
     * @param _index The index in the token list of the slot
     * @return The token ID at `_index` of all tokens with `_slot`
     */
    function tokenInSlotByIndex(uint256 _slot, uint256 _index) external view returns (uint256);
}
```

The slot level approval is OPTIONAL. This allows any contract that wants to support approval for slots, which allows an operator to manage one&apos;s tokens with the same slot.

```solidity
pragma solidity ^0.8.0;

/**
 * @title ERC-3525 Semi-Fungible Token Standard, optional extension for approval of slot level
 * @dev Interfaces for any contract that wants to support approval of slot level, which allows an
 *  operator to manage one&apos;s tokens with the same slot.
 *  See https://eips.ethereum.org/EIPS/eip-3525
 * Note: the ERC-165 identifier for this interface is 0xb688be58.
 */
interface IERC3525SlotApprovable is IERC3525 {
    /**
     * @dev MUST emit when an operator is approved or disapproved to manage all of `_owner`&apos;s
     *  tokens with the same slot.
     * @param _owner The address whose tokens are approved
     * @param _slot The slot to approve, all of `_owner`&apos;s tokens with this slot are approved
     * @param _operator The operator being approved or disapproved
     * @param _approved Identify if `_operator` is approved or disapproved
     */
    event ApprovalForSlot(address indexed _owner, uint256 indexed _slot, address indexed _operator, bool _approved);

    /**
     * @notice Approve or disapprove an operator to manage all of `_owner`&apos;s tokens with the
     *  specified slot.
     * @dev Caller SHOULD be `_owner` or an operator who has been authorized through
     *  `setApprovalForAll`.
     *  MUST emit ApprovalSlot event.
     * @param _owner The address that owns the ERC-3525 tokens
     * @param _slot The slot of tokens being queried approval of
     * @param _operator The address for whom to query approval
     * @param _approved Identify if `_operator` would be approved or disapproved
     */
    function setApprovalForSlot(
        address _owner,
        uint256 _slot,
        address _operator,
        bool _approved
    ) external payable;

    /**
     * @notice Query if `_operator` is authorized to manage all of `_owner`&apos;s tokens with the
     *  specified slot.
     * @param _owner The address that owns the ERC-3525 tokens
     * @param _slot The slot of tokens being queried approval of
     * @param _operator The address for whom to query approval
     * @return True if `_operator` is authorized to manage all of `_owner`&apos;s tokens with `_slot`,
     *  false otherwise.
     */
    function isApprovedForSlot(
        address _owner,
        uint256 _slot,
        address _operator
    ) external view returns (bool);
}
```


### ERC-3525 Token Receiver

If a smart contract wants to be informed when they receive values from other addresses, it should implement all of the functions in the `IERC3525Receiver` interface, in the implementation it can decide whether to accept or reject the transfer. See &quot;Transfer Rules&quot; for further detail.

```solidity
 pragma solidity ^0.8.0;

/**
 * @title ERC-3525 token receiver interface
 * @dev Interface for a smart contract that wants to be informed by ERC-3525 contracts when receiving values from ANY addresses or ERC-3525 tokens.
 * Note: the ERC-165 identifier for this interface is 0x009ce20b.
 */
interface IERC3525Receiver {
    /**
     * @notice Handle the receipt of an ERC-3525 token value.
     * @dev An ERC-3525 smart contract MUST check whether this function is implemented by the recipient contract, if the
     *  recipient contract implements this function, the ERC-3525 contract MUST call this function after a 
     *  value transfer (i.e. `transferFrom(uint256,uint256,uint256,bytes)`).
     *  MUST return 0x009ce20b (i.e. `bytes4(keccak256(&apos;onERC3525Received(address,uint256,uint256,
     *  uint256,bytes)&apos;))`) if the transfer is accepted.
     *  MUST revert or return any value other than 0x009ce20b if the transfer is rejected.
     * @param _operator The address which triggered the transfer
     * @param _fromTokenId The token id to transfer value from
     * @param _toTokenId The token id to transfer value to
     * @param _value The transferred value
     * @param _data Additional data with no specified format
     * @return `bytes4(keccak256(&apos;onERC3525Received(address,uint256,uint256,uint256,bytes)&apos;))` 
     *  unless the transfer is rejected.
     */
    function onERC3525Received(address _operator, uint256 _fromTokenId, uint256 _toTokenId, uint256 _value, bytes calldata _data) external returns (bytes4);

}
```

### Token Manipulation

#### Scenarios

**_Transfer:_**

Besides ERC-721 compatible token transfer methods, this EIP introduces two new transfer models: value transfer from ID to ID, and value transfer from ID to address.

```solidity
function transferFrom(uint256 _fromTokenId, uint256 _toTokenId, uint256 _value) external payable;
	
function transferFrom(uint256 _fromTokenId, address _to, uint256 _value) external payable returns (uint256 toTokenId_);
```

The first one allows value transfers from one token (specified by `_fromTokenId`) to another token (specified by `_toTokenId`) within the same slot, resulting in the `_value` being subtracted from the value of the source token and added to the value of the destination token; 

The second one allows value transfers from one token (specified by `_fromTokenId`) to an address (specified by `_to`), the value is actually transferred to a token owned by the address, and the id of the destination token should be returned. Further explanation can be found in the &apos;design decision&apos; section for this method.

#### Rules

**_approving rules:_**

This EIP provides four kinds of approving functions indicating different levels of approvals, which can be described as full level approval, slot level approval, token ID level approval as well as value level approval.

- `setApprovalForAll`, compatible with ERC-721, SHOULD indicate the full level of approval, which means that the authorized operators are capable of managing all the tokens, including their values, owned by the owner.
- `setApprovalForSlot` (optional) SHOULD indicate the slot level of approval, which means that the authorized operators are capable of managing all the tokens with the specified slot, including their values, owned by the owner.
- The token ID level `approve` function, compatible with ERC-721, SHOULD indicate that the authorized operator is capable of managing only the specified token ID, including its value, owned by the owner.
- The value level `approve` function, SHOULD indicate that the authorized operator is capable of managing the specified maximum value of the specified token owned by the owner.
- For any approving function, the caller MUST be the owner or has been approved with a higher level of authority.

**_transferFrom rules:_**

- The `transferFrom(uint256 _fromTokenId, uint256 _toTokenId, uint256 _value)` function, SHOULD indicate value transfers from one token to another token, in accordance with the rules below:

  - MUST revert unless `msg.sender` is the owner of `_fromTokenId`, an authorized operator or an operator who has been approved the whole token or at least `_value` of it.
  - MUST revert if `_fromTokenId` or `_toTokenId` is zero token id or does not exist.
  - MUST revert if slots of `_fromTokenId` and `_toTokenId` do not match.
  - MUST revert if `_value` exceeds the value of `_fromTokenId` or its allowance to the operator.
  - MUST check for the `onERC3525Received` function if the owner of _toTokenId is a smart contract, if the function exists, MUST call this function after the value transfer, MUST revert if the result is not equal to 0x009ce20b;
  - MUST emit `TransferValue` event.

- The `transferFrom(uint256 _fromTokenId, address _to, uint256 _value)` function, which transfers value from one token ID to an address, SHOULD follow the rule below:

  - MUST either find a ERC-3525 token owned by the address `_to` or create a new ERC-3525 token, with the same slot of `_fromTokenId`, to receive the transferred value.
  - MUST revert unless `msg.sender` is the owner of `_fromTokenId`, an authorized operator or an operator who has been approved the whole token or at least `_value` of it.
  - MUST revert if `_fromTokenId` is zero token id or does not exist.
  - MUST revert if `_to` is zero address.
  - MUST revert if `_value` exceeds the value of `_fromTokenId` or its allowance to the operator.
  - MUST check for the `onERC3525Received` function if the _to address is a smart contract, if the function exists, MUST call this function after the value transfer, MUST revert if the result is not equal to 0x009ce20b;
  - MUST emit `Transfer` and `TransferValue` events.


### Metadata

#### Metadata Extensions

ERC-3525 metadata extensions are compatible ERC-721 metadata extensions.

This optional interface can be identified with the ERC-165 Standard Interface Detection.

```solidity
pragma solidity ^0.8.0;

/**
 * @title ERC-3525 Semi-Fungible Token Standard, optional extension for metadata
 * @dev Interfaces for any contract that wants to support query of the Uniform Resource Identifier
 *  (URI) for the ERC-3525 contract as well as a specified slot. 
 *  Because of the higher reliability of data stored in smart contracts compared to data stored in 
 *  centralized systems, it is recommended that metadata, including `contractURI`, `slotURI` and 
 *  `tokenURI`, be directly returned in JSON format, instead of being returned with a url pointing 
 *  to any resource stored in a centralized system. 
 *  See https://eips.ethereum.org/EIPS/eip-3525
 * Note: the ERC-165 identifier for this interface is 0xe1600902.
 */
interface IERC3525Metadata is
    IERC3525 /* , IERC721Metadata */
{
    /**
     * @notice Returns the Uniform Resource Identifier (URI) for the current ERC-3525 contract.
     * @dev This function SHOULD return the URI for this contract in JSON format, starting with
     *  header `data:application/json;`.
     *  See https://eips.ethereum.org/EIPS/eip-3525 for the JSON schema for contract URI.
     * @return The JSON formatted URI of the current ERC-3525 contract
     */
    function contractURI() external view returns (string memory);

    /**
     * @notice Returns the Uniform Resource Identifier (URI) for the specified slot.
     * @dev This function SHOULD return the URI for `_slot` in JSON format, starting with header
     *  `data:application/json;`.
     *  See https://eips.ethereum.org/EIPS/eip-3525 for the JSON schema for slot URI.
     * @return The JSON formatted URI of `_slot`
     */
    function slotURI(uint256 _slot) external view returns (string memory);
}
```

#### ERC-3525 Metadata URI JSON Schema

This is the &quot;ERC-3525 Metadata JSON Schema for `contractURI()`&quot; referenced above.

```json
{
  &quot;title&quot;: &quot;Contract Metadata&quot;,
  &quot;type&quot;: &quot;object&quot;,
  &quot;properties&quot;: {
    &quot;name&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Contract Name&quot;
    },
    &quot;description&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Describes the contract&quot;
    },
    &quot;image&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Optional. Either a base64 encoded imgae data or a URI pointing to a resource with mime type image/* representing what this contract represents.&quot;
    },
    &quot;external_link&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Optional. A URI pointing to an external resource.&quot;
    },
    &quot;valueDecimals&quot;: {
      &quot;type&quot;: &quot;integer&quot;,
      &quot;description&quot;: &quot;The number of decimal places that the balance should display - e.g. 18, means to divide the token value by 1000000000000000000 to get its user representation.&quot;
    }
  }
}
```

This is the &quot;ERC-3525 Metadata JSON Schema for `slotURI(uint)`&quot; referenced above.

```json
{
  &quot;title&quot;: &quot;Slot Metadata&quot;,
  &quot;type&quot;: &quot;object&quot;,
  &quot;properties&quot;: {
    &quot;name&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Identifies the asset category to which this slot represents&quot;
    },
    &quot;description&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Describes the asset category to which this slot represents&quot;
    },
    &quot;image&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Optional. Either a base64 encoded imgae data or a URI pointing to a resource with mime type image/* representing the asset category to which this slot represents.&quot;
    },
    &quot;properties&quot;: {
      &quot;type&quot;: &quot;array&quot;,
      &quot;description&quot;: &quot;Each item of `properties` SHOULD be organized in object format, including name, description, value, order (optional), display_type (optional), etc.&quot;
      &quot;items&quot;: {
        &quot;type&quot;: &quot;object&quot;,
        &quot;properties&quot;: {
          &quot;name&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;The name of this property.&quot;
          },
          &quot;description&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Describes this property.&quot;
          }
          &quot;value&quot;: {
            &quot;description&quot;: &quot;The value of this property, which may be a string or a number.&quot;
          },
          &quot;is_intrinsic&quot;: {
            &quot;type&quot;: &quot;boolean&quot;,
            &quot;description&quot;: &quot;According to the definition of `slot`, one of the best practice to generate the value of a slot is utilizing the `keccak256` algorithm to calculate the hash value of multi properties. In this scenario, the `properties` field should contain all the properties that are used to calculate the value of `slot`, and if a property is used in the calculation, is_intrinsic must be TRUE.&quot;
          },
          &quot;order&quot;: {
            &quot;type&quot;: &quot;integer&quot;,
            &quot;description&quot;: &quot;Optional, related to the value of is_intrinsic. If is_intrinsic is TRUE, it must be the order of this property appeared in the calculation method of the slot.&quot;
          },
          &quot;display_type&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Optional. Specifies in what form this property should be displayed.&quot;
          }
        }
      }
    }
  }
}
```


This is the &quot;ERC-3525 Metadata JSON Schema for `tokenURI(uint)`&quot; referenced above.

```json
{
  &quot;title&quot;: &quot;Token Metadata&quot;,
  &quot;type&quot;: &quot;object&quot;,
  &quot;properties&quot;: {
    &quot;name&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Identifies the asset to which this token represents&quot;
    },
    &quot;description&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Describes the asset to which this token represents&quot;
    },
    &quot;image&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Either a base64 encoded imgae data or a URI pointing to a resource with mime type image/* representing the asset to which this token represents.&quot;
    },
    &quot;balance&quot;: {
      &quot;type&quot;: &quot;integer&quot;,
      &quot;description&quot;: &quot;THe value held by this token.&quot;
    },
    &quot;slot&quot;: {
      &quot;type&quot;: &quot;integer&quot;,
      &quot;description&quot;: &quot;The id of the slot that this token belongs to.&quot;
    },
    &quot;properties&quot;: {
      &quot;type&quot;: &quot;object&quot;,
      &quot;description&quot;: &quot;Arbitrary properties. Values may be strings, numbers, objects or arrays. Optional, you can use the same schema as the properties section of ERC-3525 Metadata JSON Schema for slotURI(uint) if you need a better description attribute.&quot;
    }
  }
}
```


## Rationale

### Metadata generation

This token standard is designed to represent semi-fungible assets, which are most suited for financial instruments rather than collectibles or in-game items. For maximum transparency and safety of digital assets, we strongly recommend that all implementations should generate metadata directly from contract code rather than giving out an off-chain server URL.

### Design decision: Value transfer from token to address

The &apos;value&apos; of a token is a property of the token and is not linked to an address, so to transfer the value to an address would be actually transferring it to a token owned by that address, not the address itself.

From the implementation perspective, the process of transferring values from token to address could be done as follows: (1) create a new token for the recipient&apos;s address, (2) transfer the value to the new token from the &apos;source token&apos;. So that this method is not fully independent from the ID-to-ID transfer method, and can be viewed as syntactic sugar that wraps the process described above.

In a special case, if the destination address owns one or more tokens with the same slot value as the source token, this method will have an alternative implementation as follows: (1) find one token owned by the address with the same slot value of the source token, (2) transfer the value to the found token. 

Both implementations described above should be treated as compliant with this standard.

The purpose of maintaining id-to-address transfer function is to maximize the compatibility with most wallet apps, since for most of the token standards, the destination of token transfer are addresses. This syntactic wrapping will help wallet apps easily implement the value transfer function from a token to any address.

### Design decision: Notification/acceptance mechanism instead of &apos;Safe Transfer&apos;

ERC-721 and some later token standards introduced &apos;Safe Transfer&apos; model, for better control of the &apos;safety&apos; when transferring tokens, this mechanism leaves the choice of different transfer modes (safe/unsafe) to the sender, and may cause some potential problems: 

1. In most situations the sender does not know how to choose between two kinds of transfer methods (safe/unsafe);
2. If the sender calls the `safeTransferFrom` method, the transfer may fail if the recipient contract did not implement the callback function, even if that contract is capable of receiving and manipulating the token without issue.

This EIP defines a simple &apos;Check, Notify and Response&apos; model for better flexibility as well as simplicity:

1. No extra `safeTransferFrom` methods are needed, all callers only need to call one kind of transfer;
2. All ERC-3525 contracts MUST check for the existence of `onERC3525Received` on the recipient contract and call the function when it exists;
3. Any smart contract can implement `onERC3525Received` function for the purpose of being notified after receiving values; this function MUST return 0x009ce20b (i.e. `bytes4(keccak256(&apos;onERC3525Received(address,uint256,uint256,uint256,bytes)&apos;))`) if the transfer is accepted, or any other value if the transfer is rejected.

There is a special case for this notification/acceptance mechanism: since ERC-3525 allows value transfer from an address to itself, when a smart contract which implements `onERC3525Received` transfers value to itself, `onERC3525Received` will also be called. This allows for the contract to implement different rules of acceptance between self-value-transfer and receiving value from other addresses.

### Design decision: Relationship between different approval models

For semantic compatibility with ERC-721 as well as the flexibility of value manipulation of tokens, we decided to define the relationships between some of the levels of approval like that:

1. Approval of an id will lead to the ability to partially transfer values from this id by the approved operator; this will simplify the value approval for an id. However, the approval of total values in a token should not lead to the ability to transfer the token entity by the approved operator.
2. `setApprovalForAll` will lead to the ability to partially transfer values from any token, as well as the ability to approve partial transfer of values from any token to a third party; this will simplify the value transfer and approval of all tokens owned by an address.

## Backwards Compatibility

As mentioned in the beginning, this EIP is backward compatible with ERC-721.

## Reference Implementation

- [ERC-3525 implementation](/EIPs/assets/eip-3525/contracts/ERC3525.sol)

## Security Considerations

The value level approval and slot level approval (optional) is isolated from ERC-721 approval models, so that approving value should not affect ERC-721 level approvals. Implementations of this EIP must obey this principle.

Since this EIP is ERC-721 compatible, any wallets and smart contracts that can hold and manipulate standard ERC-721 tokens will have no risks of asset loss for ERC-3525 tokens due to incompatible standards implementations.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 01 Dec 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3525</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3525</guid>
      </item>
    
      <item>
        <title>Reduction in refunds</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3529-reduction-in-refunds-alternative-to-eip-3298-and-3403-that-better-preserves-existing-clearing-incentives/6097</comments>
        
        <description>## Simple Summary

Remove gas refunds for `SELFDESTRUCT`, and reduce gas refunds for `SSTORE` to a lower level where the refunds are still substantial, but they are no longer high enough for current &quot;exploits&quot; of the refund mechanism to be viable.

## Motivation

Gas refunds for `SSTORE` and `SELFDESTRUCT` were originally introduced to motivate application developers to write applications that practice &quot;good state hygiene&quot;, clearing storage slots and contracts that are no longer needed. However, the benefits of this technique have proven to be far lower than anticipated, and gas refunds have had multiple unexpected harmful consequences:

* Refunds give rise to GasToken. GasToken has benefits in moving gas space from low-fee periods to high-fee periods, but it also has downsides to the network, particularly in exacerbating state size (as state slots are effectively used as a &quot;battery&quot; to save up gas) and inefficiently clogging blockchain gas usage
* Refunds increase block size variance. The theoretical maximum amount of actual gas consumed in a block is nearly twice the on-paper gas limit (as refunds add gas space for subsequent transactions in a block, though refunds are capped at 50% of a transaction&apos;s gas used). This is not fatal, but is still undesirable, especially given that refunds can be used to maintain 2x usage spikes for far longer than EIP-1559 can.


## Specification

### Parameters

| Constant | Value |
| - | - |
| `FORK_BLOCK` | TBD |
| `MAX_REFUND_QUOTIENT` | 5 |

For blocks where `block.number &gt;= FORK_BLOCK`, the following changes apply.

1. Remove the `SELFDESTRUCT` refund.
2. Replace `SSTORE_CLEARS_SCHEDULE` (as defined in [EIP-2200](/EIPs/EIPS/eip-2200)) with `SSTORE_RESET_GAS + ACCESS_LIST_STORAGE_KEY_COST` (4,800 gas as of [EIP-2929](/EIPs/EIPS/eip-2929) + [EIP-2930](/EIPs/EIPS/eip-2930))
3. Reduce the max gas refunded after a transaction to `gas_used // MAX_REFUND_QUOTIENT`

Remark: Previously _max gas refunded_ was defined as `gas_used // 2`. Here we
name the constant `2` as `MAX_REFUND_QUOTIENT` and change its value to `5`.

## Rationale

In [EIP-2200](/EIPs/EIPS/eip-2200#specification), three cases for refunds were introduced:

1. If the original value is nonzero, and the new value is zero, add `SSTORE_CLEARS_SCHEDULE` (currently 15,000) gas to the refund counter
2. If the original value is zero, the current value is nonzero, and the new value is zero, add `SSTORE_SET_GAS - SLOAD_GAS` (currently 19,900) gas to the refund counter
3. If the original value is nonzero, the current value is a different nonzero value, and the new value equals the original value, add `SSTORE_RESET_GAS - SLOAD_GAS` (currently 4,900) gas to the refund counter

Of these three, only (1) enables gastokens and allows a block to expend more gas on execution than the block gas limit. (2) does not have this property, because for the 19,900 refund to be obtained, _the same storage slot_ must have been changed from zero to nonzero previously, costing 20,000 gas. The inability to obtain gas from clearing one storage slot and use it to edit another storage slot means that it cannot be used for gas tokens. Additionally, obtaining the refund requires _reverting_ the effect of the storage write and expansion, so the refunded gas does not contribute to a client&apos;s load in processing a block. (3) behaves similarly: the 4,900 refund can only be obtained when 5,000 gas had previously been spent on the same storage slot.

This EIP deals with case (1). We can establish under what conditions a gastoken is nonviable (ie. you cannot get more gas out of a storage slot than you put in) by using a similar &quot;pairing&quot; argument, mapping each refund to a previous expenditure in the same transaction on the same storage slot. lf a storage slot is changed to zero when its original value is nonzero, there are two possibilities:

1. This could be the first time that the storage slot is set to zero. In this case, we can pair this event with the `SSTORE_RESET_GAS + ACCESS_LIST_STORAGE_KEY_COST` minimum cost of reading and editing the storage slot for the first time.
2. This could be the second or later time that the storage slot is set to zero. In this case, we can pair this event with the most recent previous time that the value was set _away_ from zero, in which `SSTORE_CLEARS_SCHEDULE` gas is _removed_ from the refund.

For the second and later event, it does not matter what value `SSTORE_CLEARS_SCHEDULE` has, because every refund of that size is paired with a refund _removal_ of the same size. This leaves the first event. For the total gas expended on the slot to be guaranteed to be positive, we need `SSTORE_CLEARS_SCHEDULE &lt;= SSTORE_RESET_GAS + ACCESS_LIST_STORAGE_KEY_COST`. And so this EIP simply decreases `SSTORE_CLEARS_SCHEDULE` to the sum of those two costs.

One alternative intuition for this EIP is that there will not be a net refund for clearing data that has not yet been read (which is often &quot;useless&quot; data), but there will continue to be a net refund for clearing data that has been read (which is likely to be &quot;useful&quot; data).

## Backwards Compatibility

Refunds are currently only applied _after_ transaction execution, so they cannot affect how much gas is available to any particular call frame during execution. Hence, removing them will not break the ability of any code to execute, though it will render some applications economically nonviable.

Gas tokens will become valueless. DeFi arbitrage bots, which today frequently use either established gas token schemes or a custom alternative to reduce on-chain costs, would benefit from rewriting their code to remove calls to these no-longer-functional gas storage mechanisms.

However, fully preserving refunds in the `new = original = 0 != current` case, and keeping _some_ refund in the other `nonzero -&gt; zero` cases, ensures that a few key use cases that receive (and deserve) favorable gas cost treatment continue to do so. For example, `zero -&gt; nonzero -&gt; zero` storage set patterns continue to cost only ~100 gas. Two important examples of such patterns include:

* Anti-reentrancy locks (typically flipped from 0 to 1 right before a child call begins, and then flipped back to 0 when the child call ends)
* ERC20 approve-and-send (the &quot;approved value&quot; goes from zero to nonzero when the token transfer is approved, and then back to zero when the token transfer processes)

### Effect on storage clearing incentives

A criticism of earlier refund removal EIPs ([EIP-3298](/EIPs/EIPS/eip-3298) and [EIP-3403](/EIPs/EIPS/eip-3403)) is that these EIPs fully remove the incentive to set a value to zero, encouraging users to not fully clear a storage slot if they expect even the smallest probability that they will want to use that storage slot again.

For example, if you have 1 unit of an ERC20 token and you are giving away or selling your entire balance, you could instead only give away 0.999999 units and leave the remainder behind. If you ever decide to re-acquire more of that token with the same account in the future, you would only have to pay 5000 gas (2100 for the read + 2900 for nonzero-to-nonzero set) for the `SSTORE` instead of 22100 (20000 for the zero-to-nonzero set). Today, this is counterbalanced by the 15000 refund for clearing, so you only have an incentive to do this if you are more than `15000 / 17100 = 87.7%` sure that you will use the slot again; with EIP-3298 or EIP-3403 the counterbalancing incentive would not exist, so setting to nonzero is better if your chance of using the slot again is _any_ value greater than 0%.

A refund of 4800 gas remains, so there is only be an incentive to keep a storage slot nonzero if you expect a probability of more than `4800 / 17100 = 28.1%` that you will use that slot again. This is not perfect, but it is likely higher than the average person&apos;s expectations of later re-acquiring a token with the same address if they clear their entire balance of it.

The capping of refunds to 1/5 of gas expended means that this refund can only be used to increase the amount of storage write operations needed to process a block by at most 25%, limiting the ability to use this mechanic for storage-write-focused denial-of-service attacks.

## Test Cases

### EIP-2929 Gas Costs

Note, there is a difference between &apos;hot&apos; and &apos;cold&apos; slots. This table shows the values as of [EIP-2929](/EIPs/EIPS/eip-2929) assuming that all touched storage slots were already &apos;hot&apos; (the difference being a one-time cost of `2100` gas).

| Code | Used Gas | Refund | Original | 1st | 2nd | 3rd | Effective gas (after refund)
| -- | -- | -- | -- | -- | -- | -- | -- |
| `0x60006000556000600055` | 212 | 0| 0 | 0 |  0 |  |  212 |
| `0x60006000556001600055` | 20112 | 0| 0 | 0 |  1 |  |  20112 |
| `0x60016000556000600055` | 20112 | 19900| 0 | 1 |  0 |  |  212 |
| `0x60016000556002600055` | 20112 | 0| 0 | 1 |  2 |  |  20112 |
| `0x60016000556001600055` | 20112 | 0| 0 | 1 |  1 |  |  20112 |
| `0x60006000556000600055` | 3012 | 15000| 1 | 0 |  0 |  |  -11988 |
| `0x60006000556001600055` | 3012 | 2800| 1 | 0 |  1 |  |  212 |
| `0x60006000556002600055` | 3012 | 0| 1 | 0 |  2 |  |  3012 |
| `0x60026000556000600055` | 3012 | 15000| 1 | 2 |  0 |  |  -11988 |
| `0x60026000556003600055` | 3012 | 0| 1 | 2 |  3 |  |  3012 |
| `0x60026000556001600055` | 3012 | 2800| 1 | 2 |  1 |  |  212 |
| `0x60026000556002600055` | 3012 | 0| 1 | 2 |  2 |  |  3012 |
| `0x60016000556000600055` | 3012 | 15000| 1 | 1 |  0 |  |  -11988 |
| `0x60016000556002600055` | 3012 | 0| 1 | 1 |  2 |  |  3012 |
| `0x60016000556001600055` | 212 | 0| 1 | 1 |  1 |  |  212 |
| `0x600160005560006000556001600055` | 40118 | 19900| 0 | 1 |  0 |  1 |  20218 |
| `0x600060005560016000556000600055` | 5918 | 17800| 1 | 0 |  1 |  0 |  -11882 |

### With reduced refunds

If refunds were to be partially removed, by changing `SSTORE_CLEARS_SCHEDULE` from 15000 to 4800 (and removing selfdestruct refund) this would be the comparative table.

| Code | Used Gas | Refund | Original | 1st | 2nd | 3rd | Effective gas (after refund)
| -- | -- | -- | -- | -- | -- | -- | -- |
| `0x60006000556000600055` | 212 | 0| 0 | 0 |  0 |  |  212 |
| `0x60006000556001600055` | 20112 | 0| 0 | 0 |  1 |  |  20112 |
| `0x60016000556000600055` | 20112 | 19900| 0 | 1 |  0 |  |  212 |
| `0x60016000556002600055` | 20112 | 0| 0 | 1 |  2 |  |  20112 |
| `0x60016000556001600055` | 20112 | 0| 0 | 1 |  1 |  |  20112 |
| `0x60006000556000600055` | 3012 | 4800| 1 | 0 |  0 |  |  -1788 |
| `0x60006000556001600055` | 3012 | 2800| 1 | 0 |  1 |  |  212 |
| `0x60006000556002600055` | 3012 | 0| 1 | 0 |  2 |  |  3012 |
| `0x60026000556000600055` | 3012 | 4800| 1 | 2 |  0 |  |  -1788 |
| `0x60026000556003600055` | 3012 | 0| 1 | 2 |  3 |  |  3012 |
| `0x60026000556001600055` | 3012 | 2800| 1 | 2 |  1 |  |  212 |
| `0x60026000556002600055` | 3012 | 0| 1 | 2 |  2 |  |  3012 |
| `0x60016000556000600055` | 3012 | 4800| 1 | 1 |  0 |  |  -1788 |
| `0x60016000556002600055` | 3012 | 0| 1 | 1 |  2 |  |  3012 |
| `0x60016000556001600055` | 212 | 0| 1 | 1 |  1 |  |  212 |
| `0x600160005560006000556001600055` | 40118 | 19900| 0 | 1 |  0 |  1 |  20218 |
| `0x600060005560016000556000600055` | 5918 | 7600| 1 | 0 |  1 |  0 |  -1682 |

## Security Considerations

Refunds are not visible to transaction execution, so this should not have any impact on transaction execution logic.

The maximum amount of gas that can be spent on execution in a block is limited to the gas limit, if we do not count zero-to-nonzero `SSTORE`s that were later reset back to zero. It is okay to not count those, because if such an `SSTORE` is reset, storage is not expanded and the client does not need to actually adjust the Merke tree; the gas consumption is refunded, but the effort normally required by the client to process those opcodes is also cancelled. **Clients should make sure to not do a storage write if `new_value = original_value`; this was a prudent optimization since the beginning of Ethereum but it becomes more important now.**

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 22 Apr 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3529</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3529</guid>
      </item>
    
      <item>
        <title>Restricted Chain Context Type Transactions</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3534-restricted-chain-context-transaction-type/6112</comments>
        
        <description>## Simple Summary

Defines a new transaction type with constraints on ancestor block hash, block author, and/or block timestamp.

## Abstract

We introduce a new EIP-2718 transaction type with the format `0x4 || rlp([chainId, chainContext, nonce, gasPrice, gasLimit, to, value, data, access_list, yParity, senderR, senderS])`. 

This proposed `chainContext` element adds a constraint on the validity of a transaction to a chain segment meeting the referenced value(s). Four contexts are defined as subclasses of this type:

- `segmentId`
- `eligibleMinerList`
- `ineligibleMinerList`
- `expiry`

These contexts can be used in arbitrary combinations. Annotated context value combinations are referenced by a composite integer prefix on the annotation.

## Motivation

Establish a protocol-based mechanism with which transactions are able to articulate constraints on eligible chain contexts.
Generally, these constraints give the consumer (the transactor) an ability to express requirements about the transaction&apos;s relationship to blockchain data and its provenance.

- Restrict transaction applicability to a chain context that is currently available and reasoned about under some subjective view.
    - Introduces a way for transactions to describe a dependency on their current view of a chain.
- Restrict transaction applicability to a chain context following some foregoing block (and its transactions).
    - Introduces a way for transactions to describe ancestral dependencies at a &quot;macro&quot; (block) level. 
    Indirectly, this offers a way for a transaction to depend on the presence of another, so long as the dependent transaction is in a different block.
- Restrict transaction applicability to blocks benefitting, or _not_ benefitting, a preferred/spurned miner address or addresses.
    - Introduces an opportunity/market for miners to compete for consumers&apos; transactions; under the status quo, the current miner-transaction processing service is almost perfectly homogeneous from the consumer perspective.
- Restrict transaction applicability time span.
    - Introduces an alternative (to the status quo) way for consumers/transactors to have transactions invalidated/ejected from the transaction pool.

## Specification

### Parameters

- `FORK_BLOCK_NUMBER` `TBD`
- `TRANSACTION_TYPE_NUMBER` `0x4`.  See EIP-2718.

As of `FORK_BLOCK_NUMBER`, a new EIP-2718 transaction is introduced with `TransactionType` `TRANSACTION_TYPE_NUMBER`.

The EIP-2718 `TransactionPayload` for this transaction is `rlp([chainId, chainContext, nonce, gasPrice, gasLimit, to, value, data, access_list, yParity, senderR, senderS])`.

The EIP-2718 `ReceiptPayload` for this transaction is `rlp([status, cumulativeGasUsed, logsBloom, logs])`.

### Definitions

- `chainContext`. The transaction is only valid for blockchain data satisfying ALL OF the annotations.
- `ANNOTATION_COMPOSITE_PREFIX`. A positive integer between `1` and `0xff` that represents the set of subclass annotations in the `chainContext` (_ie._ _which_ chain context subclasses should the provided values be applied to). This value should be the sum of the subclass&apos; `ANNOTATION_PREFIX`s.
- `ANNOTATION_PREFIX`s are defined for Subclasses as octal-derived positive integers, limited to the set `2^0,2^1,2^2,2^3,2^4,2^5,2^6,2^7`.

The `chainContext` value should be of the form `ANNOTATION_COMPOSITE_PREFIX || [{subclass value}...]`, where 
- `...` means &quot;zero or more of the things to the left,&quot; and 
- `||` denotes the byte/byte-array concatenation operator.

The `chainContext` value should be encoded as `ANNOTATION_COMPOSITE_PREFIX || rlp[{subclass value}...]`.

### Validation

The values defined as subclasses below acts as constraints on transaction validity for specific chain contexts.
Transactions defining constraints which are not satisfied by their chain context should be rejected as invalid.
Blocks containing invalid transactions should be rejected as invalid themselves, per the _status quo_.

### Subclass Combination

`chainContext` values annotating more than one subclass reference should provide those values in the following sequential order:

1. `ANCESTOR_ID`
2. `ELIGIBLE_MINER_LIST`
3. `INELIGIBLE_MINER_LIST`
4. `EXPIRY`

As above, the `ANNOTATION_COMPOSITE_PREFIX` should be the sum of the designated subclass&apos; `ANNOTATION_PREFIX`s.
### Subclasses

- An `ANNOTATION_PREFIX` value is used to represent each of the available context subclasses.

#### `ancestorId`

- `ANNOTATION_PREFIX` `1`.
- `ANCESTOR_ID` `bytes`. A byte array between 4 and 12 bytes in length.

The `ANCESTOR_ID` is a reference to a specific block by concatenating the byte representation of a block number and the first 4 bytes of its hash. 
The block number&apos;s should be encoded as a big endian value and should have left-padding 0&apos;s removed.
The block number value may be omitted in case of reference to the genesis block.

The `ANCESTOR_ID` value should be RLP encoded as a byte array for hashing and transmission.

#### `eligibleMinerList`

- `ANNOTATION_PREFIX` `2`.
- `ELIGIBLE_MINER_LIST` `[address...]`. A list of addresses.
- `MAX_ELEMENTS` `3`. The maximum number of addresses that can be provided.

The `ELIGIBLE_MINER_LIST` value is an array of unique, valid addresses.
Any block containing a transaction using this value must have a block beneficiary included in this set.

The `ELIGIBLE_MINER_LIST` value should be of the type `[{20 bytes}+]`, where `+` means &quot;one or more of the thing to the left.&quot; 
Non-unique values are not permitted.

The `ELIGIBLE_MINER_LIST` value should be RLP encoded for hashing and transmission.

An `ELIGIBLE_MINER_LIST` value may NOT be provided adjacent to an `INELIGIBLE_MINER_LIST` value.

#### `ineligibleMinerList`

- `ANNOTATION_PREFIX` `4`.
- `INELIGIBLE_MINER_LIST` `[address...]`. A list of addresses.
- `MAX_ELEMENTS` `3`. The maximum number of addresses that can be provided.

The `INELIGIBLE_MINER_LIST` value is an array of unique, valid addresses.
Any block containing a transaction using this value must not have a block beneficiary included in this set.

The `INELIGIBLE_MINER_LIST` value should be of the type `[{20 bytes}+]`, where `+` means &quot;one or more of the thing to the left.&quot; 
Non-unique values are not permitted.

The `INELIGIBLE_MINER_LIST` value should be RLP encoded for hashing and transmission.

An `INELIGIBLE_MINER_LIST` value may NOT be provided adjacent to an `ELIGIBLE_MINER_LIST` value.

#### `expiry`

- `ANNOTATION_PREFIX` `8`.
- `EXPIRY` `integer`. A positive, unsigned scalar.

The `EXPIRY` value is a scalar equal to the maximum valid block `timestamp` for a block including this transaction.

The `EXPIRY` value should be RLP encoded as an integer for hashing and transmission.

## Rationale

### Subclasses

Subclasses are defined with a high level of conceptual independence, and can be modified and/or extended independently from this EIP.
Their specification definitions allow arbitrary mutual (`AND`) combinations.

This design is intended to form a proposal which offers a concrete set of specifics while doing so with enough flexibility for extension or modification later.

#### `ANNOTATION_PREFIX`

`ANNOTATION_PREFIX` values&apos; use of octal-derived values, ie. `1, 2, 4, 8, 16, 32, 64, 128`, follows a conventional pattern of representing combinations from a limited set uniquely and succinctly, eg. Unix-style file permissions.
This EIP defines four of the eight possible context subclasses; this seems to leave plenty of room for future growth in this direction if required.
If this limit is met or exceeded, doing so will require a hard fork _de facto_ (by virtue of making consensus protocol facing changes to transaction validation schemes), so revising this scheme as needed should be only incidental and trivial.

#### `ancestorId`

Constrains the validity of a transaction by referencing a prior canonical block by number and hash.
The transaction is only valid when included in a block which has the annotated block as an ancestor.

Practically, the &quot;designated allowable chain segment&quot; can be understood as the segment of blocks from `0..ancestorId` inclusive.

##### Redundancy to `chainId`

This pattern can be understood as a correlate of [EIP-155](./eip-155)&apos;s `chainId` specification.
EIP155 defines the restriction of transactions between chains; limiting the applicability of any EIP-155 transaction to a chain with the annotated ChainID. 
`ancestorId` further restricts transaction application to one subsection (&quot;segment&quot;) of one chain.

From this constraint hierarchy, we note that an implementation of `ancestorId` can make `chainId` conceptually redundant.

##### So why keep `chainId`?

`chainId` is maintained as an invariant because:

- The use of the transaction type proposed by this EIP is optional, implying the continued necessity of `chainId` in the protocol infrastructure and tooling for legacy and other transaction types.
- The presence of `ancestorId` in the transaction type proposed by this EIP is optional. If the value is not filled by an RCC transaction, the demand for `chainId` remains.
- A `chainId` value is not necessarily redundant to `ancestorId`, namely in cases where forks result in living chains. For example, an `ancestorId` reference to block `1_919_999` would be ambiguous between Ethereum and Ethereum Classic.
- It would be possible to specify the omission of `chainId` in case of `ancestorId`&apos;s use. This would add infrastructural complexity for the sake of removing the few bytes `chainId` typically requires; we do not consider this trade-off worth making.
    - `chainId` is used as the `v` value (of `v,r,s`) in the transaction signing scheme; removing or modifying this incurs complexity at a level below encoded transaction fields, demanding additional infrastructural complexity for implementation.
- The proposed design for `ancestorId` does not provide perfect precision (at the benefit of byte-size savings). 
  In the small chance that the value is ambiguous, the `chainId` maintains an infallible guarantee for a transaction&apos;s chain specificity.

#### `eligibleMinerList`

The transaction is only valid when included in a block having an `etherbase` contained in the annotated list of addresses.
The use of &quot;whitelist&quot; (`eligibleMinerList`) in conjunction with a &quot;blacklist&quot; (`ineligibleMinerList`) is logically inconsistent; their conjunction is not allowed.

A `MAX_ELEMENTS` limit of `3` is chosen to balance the interests of limiting the potential size of transactions, and to provide a sufficient level of articulation for the user. At the time of writing, the top 3 miners of Ethereum (by block, measured by known public addresses) account for 52% of all blocks produced.

#### `ineligibleMinerList`

The transaction is only valid when included in a block having an `etherbase` _not_ contained in the annotated list of addresses.
The use of &quot;blacklist&quot; (`ineligibleMinerList`) in conjunction with a &quot;whitelist&quot; (`eligibleMinerList`) is logically inconsistent; their conjunction is not allowed.

A `MAX_ELEMENTS` limit of `3` is chosen to balance the interests of limiting the potential size of transactions, and to provide a sufficient level of articulation for the user. At the time of writing, the top 3 miners of Ethereum (by block, measured by known public addresses) account for 52% of all blocks produced.

#### `expiry`

The transaction is only valid when included in a block having a `timestamp` less than the value annotated.
A positive integer is used because that corresponds to the specified type of block `timestamp` header values.

### Subclass Combination

Since subclasses use octal-based values for `ANNOTATION_PREFIX`, they can be distinguishably combined as sums, provided as we assume annotation cardinality (ie ordering).
For example:

- `ANNOTATION_PREFIX` `1` signals `ancestorId` exclusively. 
- `ANNOTATION_PREFIX` `2` signals `eligibleMinerList` exclusively. 
- `ANNOTATION_PREFIX` `4` signals `ineligibleMinerList` exclusively. 
- `ANNOTATION_PREFIX` `8` signals `expiry` exclusively.
- `ANNOTATION_PREFIX` `1+2=3` combines `ancestorId` and `eligibleMinerList`.
- `ANNOTATION_PREFIX` `1+4=5` combines `ancestorId` and `ineligibleMinerList`. 
- `ANNOTATION_PREFIX` `1+8=9` combines `ancestorId` and `expiry`. 
- `ANNOTATION_PREFIX` `1+2+8=11` combines `ancestorId` and `eligibleMinerList` and `expiry`. 
- `ANNOTATION_PREFIX` `1+4+8=13` combines `ancestorId` and `ineligibleMinerList` and `expiry`. 
- `ANNOTATION_PREFIX` `2+4=6` is NOT PERMITTED. It would combine `eligibleMinerList` and `ineligibleMinerList`. 
- `ANNOTATION_PREFIX` `1+2+4+8=15` is NOT PERMITTED. It would combine `eligibleMinerList` and `ineligibleMinerList` (and `ancestorId` and `expiry`). 

Since ordering is defined and demanded for multiple values, annotated references remain distinguishable. For example:

- `chainContext` `3[e4e1c0e78b1ec3,[Df7D7e053933b5cC24372f878c90E62dADAD5d42]]` - Transaction can only be included in a block having a canonical ancestor block numbered `15_000_000` and with a hash prefixed with the bytes `e78b1ec3`, and if the containing block uses `Df7D7e053933b5cC24372f878c90E62dADAD5d42` as the beneficiary.
- `chainContext` `10[[Df7D7e053933b5cC24372f878c90E62dADAD5d42],1619008030]` - Transaction can only be included in a block naming `Df7D7e053933b5cC24372f878c90E62dADAD5d42` as the `etherbase` beneficiary, and which has a timestamp greater than `1619008030` (Wed Apr 21 07:27:10 CDT 2021).


### EIP-2930 Inheritance
The [EIP-2930 Optional Access List Type Transaction](https://eips.ethereum.org/EIPS/eip-2930) is used as an assumed &quot;base&quot; transaction type for this proposal. 
However, this is NOT a conceptual dependency; the included `accessList` portion of this proposal (the only differential from post-EIP-155 legacy transaction fields) can readily be removed. 
Standing on the shoulders of EIP-2930 is only intended to support and further the adoption of next-generation transactions.

### Signature target

The signature signs over the transaction type as well as the transaction data.
This is done to ensure that the transaction cannot be “re-interpreted” as a transaction of a different type.

## Backwards Compatibility

There are no known backward compatibility issues.

## Test Cases

| Segment ID | Block Number | Canonical Block Hash |
| --- | --- | --- |
| `e78b1ec3` | `0` | `0xe78b1ec31bcb535548ce4b6ef384deccad1e7dc599817b65ab5124eeaaee3e58` |
| `01e78b1ec3` | `1` | `0xe78b1ec31bcb535548ce4b6ef384deccad1e7dc599817b65ab5124eeaaee3e58` |
| `e4e1c0e78b1ec3` | `15_000_000` | `0xe78b1ec31bcb535548ce4b6ef384deccad1e7dc599817b65ab5124eeaaee3e58` |
| `e8d4a50fffe78b1ec3` | `999_999_999_999` | `0xe78b1ec31bcb535548ce4b6ef384deccad1e7dc599817b65ab5124eeaaee3e58` |
| `7fffffffffffffffe78b1ec3` | `9223372036854775807` | `0xe78b1ec31bcb535548ce4b6ef384deccad1e7dc599817b65ab5124eeaaee3e58` |

Further test cases, TODO.

## Security Considerations

### Why 4 bytes of a block hash is &quot;safe enough&quot; for the `ancestorId`

__TL;DR__: The chance of an ineffectual `ancestorId` is about 1 in between ~4 billion and ~40 billion, with the greater chance for intentional duplication scenarios, eg. malicious reorgs.

__If a collision _does_ happen__, that means the transaction will be valid on both segments (as is the case under the status quo).

Four bytes, instead of the whole hash (32 bytes), was chosen only to reduce the amount of information required to cross the wire to implement this value.
Using the whole hash would result in a &quot;perfectly safe&quot; implementation, and every additional byte reduces the chance of collision exponentially.

The goal of the `ancestorId` is to disambiguate one chain segment from another, and in doing so, enable a transaction to define with adequate precision which chain it needs to be on.
When a transaction&apos;s `ancestorId` references a block, we want to be pretty sure that that reference won&apos;t get confused with a different block than the one the author of the transaction had in mind.

We assume the trait of collision resistance is uniformly applicable to all possible subsets of the block hash value, so our preference of using the _first_ 4 bytes is arbitrary and functionally equivalent to any other subset of equal length.

For the sake of legibility and accessibility, the following arguments will reference the hex representation of 4 bytes, which is 8 characters in length, eg. `e78b1ec3`. 

The chance of a colliding `ancestorId` is `1/(16^8=4_294_967_296)` times whatever we take the chance of the existence of an equivalently-numbered block (on an alternative chain) to be. Assuming a generous ballpark chance of 10% (`1/10`) for any given block having a public uncle, this yields `(1/(16^8=4_294_967_296) * 1/10`. Note that this ballpark assumes &quot;normal&quot; chain and network behavior. In the case of an enduring competing chain segment, this value rises to 100% (`1`).

### `eligibleMinerList`

Miners who do not find themselves listed in an annotated `eligibleMinerList` should be expected to immediately remove the transaction from their transaction pool. 

In a pessimistic outlook, we should also expect that these ineligible nodes would not offer rebroadcasts of these transactions, potentially impacting the distribution (and availability) of the transactions to their intended miners. On the other hand, miners are incentivized to make themselves available for reception of such transactions, and there are many ways this is feasible both on-network and off-.

The author of a transaction using the `eligibleMinerList` must assume that the &quot;general availability&quot; of the blockchain state database for such a transaction will be lower than a nonrestrictive transaction (since only a subset of miners will be able to process the transaction). 

A final consideration is the economics of a whitelisted miner concerning the processing order of transactions in which they are whitelisted and those without whitelists.
Transactions without whitelists would appear at first glean to be more competitive, and thus should be processed with priority.
However, miners following such a strategy may find their reputation diminished, and, in the worst case, see the assertive preferences of transaction authors shift to their competitors and beyond their reach.

### `ineligibleMinerList`

In addition to the concerns and arguments presented by `eligibleMinerList` above, there is a unique concern for `ineligibleMinerList`: in order for a miner entity to avoid ineligibility by a blacklist, they only need to use an alternative adhoc address as the block beneficiary.
In principle, this is ineluctable.

However, there are associated costs to the &quot;dodging&quot; miner that should be considered.

- The creation of an account requires time and energy. But indeed, this work can be done at any convenient time and circumstance. Probably marginal, but non-zero.
- The transfer of funds from multiple accounts requires a commensurate number of transactions. Block rewards are applied after transactions are processed, so the miner is unable to simultaneously shift funds from an adhoc account to a target account in the same block they mine (which would otherwise be a &quot;free&quot; transaction).
- In using an adhoc address to dodge a blacklist, the miner may also cause their ineligibility from contemporary whitelist transactions.

### Validation costs

Miner lists and expiry depend on easily cached and contextually available conditions (ie. the containing block header). The infrastructural overhead costs for enforcing these validations are expected to be nominal.

Validation of `ancestorId` demands the assertion of a positive database hit by block number (thereby cross-referencing a stored block&apos;s hash). 
This necessary lookup can be (and maybe already is) cached, but we must expect less than 100% hits on cached values, since the lookup value is arbitrary.
With that in mind, however, the value provided to a transaction using a deep `ancestorId` is increasingly marginal, so we should expect
most transactions using this field to use a relatively small set of common, shallow, cache-friendly values.

### Transaction size increase

The proposed additional fields potentially increase transaction size.
The proposed fields are not associated with any gas costs, establishing no protocol-defined economic mitigation for potential spam.
However, transactions which are considered by a miner to be undesirable can be simply dropped from the transaction pool and ignored.

## Copyright

Copyright and related rights waved via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 20 Apr 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3534</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3534</guid>
      </item>
    
      <item>
        <title>EOF - EVM Object Format v1</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/evm-object-format-eof/5727</comments>
        
        <description>## Abstract

We introduce an extensible and versioned container format for the EVM with a once-off validation at deploy time. The version described here brings the tangible benefit of code and data separation, and allows for easy introduction of a variety of changes in the future. This change relies on the reserved byte introduced by [EIP-3541](/EIPs/EIPS/eip-3541).

To summarise, EOF bytecode has the following layout:

```
magic, version, (section_kind, section_size_or_sizes)+, 0, &lt;section contents&gt;
```

## Motivation

On-chain deployed EVM bytecode contains no pre-defined structure today. Code is typically validated in clients to the extent of `JUMPDEST` analysis at runtime, every single time prior to execution. This poses not only an overhead, but also a challenge for introducing new or deprecating existing features.

Validating code during the contract creation process allows code versioning without an additional version field in the account. Versioning is a useful tool for introducing or deprecating features, especially for larger changes (such as significant changes to control flow, or features like account abstraction).

The format described in this EIP introduces a simple and extensible container with a minimal set of changes required to both clients and languages, and introduces validation.

The first tangible feature it provides is separation of code and data. This separation is especially beneficial for on-chain code validators (like those utilised by layer-2 scaling tools, such as Optimism), because they can distinguish code and data (this includes deployment code and constructor arguments too). Currently, they a) require changes prior to contract deployment; b) implement a fragile method; or c) implement an expensive and restrictive jump analysis. Code and data separation can result in ease of use and significant gas savings for such use cases. Additionally, various (static) analysis tools can also benefit, though off-chain tools can already deal with existing code, so the impact is smaller.

A non-exhaustive list of proposed changes which could benefit from this format:

- Including a `JUMPDEST`-table (to avoid analysis at execution time) and/or removing `JUMPDEST`s entirely.
- Introducing static jumps (with relative addresses) and jump tables, and disallowing dynamic jumps at the same time.
- Multibyte opcodes without any workarounds.
- Representing functions as individual code sections instead of subroutines.
- Introducing special sections for different use cases, notably Account Abstraction.

## Specification

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.

In order to guarantee that every EOF-formatted contract in the state is valid, we need to prevent already deployed (and not validated) contracts from being recognized as such format. This is achieved by choosing a byte sequence for the *magic* that doesn&apos;t exist in any of the already deployed contracts.

### Remarks

If code starts with the `MAGIC`, it is considered to be EOF formatted, otherwise it is considered to be *legacy* code. For clarity, the `MAGIC` together with a version number *n* is denoted as the *EOFn prefix*, e.g. *EOF1 prefix*.

EOF-formatted contracts are created using new instructions which are introduced in a separate EIP.

The opcode `0xEF` is currently an undefined instruction, therefore: *It pops no stack items and pushes no stack items, and it causes an exceptional abort when executed.* This means legacy *initcode* or already deployed legacy *code* starting with this instruction will continue to abort execution.

Unless otherwise specified, all integers are encoded in big-endian byte order.

### Code validation

We introduce *code validation* for new contract creation. To achieve this, we define a format called EVM Object Format (EOF), containing a version indicator, and a ruleset of validity tied to a given version.

Legacy code is not affected by EOF code validation.

Code validation is performed during contract creation, and is elaborated on in separate EIPs.
The EOF format itself and its formal validation are described in the following sections.

### Container specification

EOF container is a binary format with the capability of providing the EOF version number and a list of EOF sections.

The container starts with the EOF prefix:

| description | length   | value      |                    |
|-------------|----------|------------|--------------------|
| magic       | 2-bytes  | 0xEF00     |                    |
| version     | 1-byte   | 0x01–0xFF  | EOF version number |

The EOF prefix is followed by at least one section header. Each section header contains two fields, `section_kind` and either `section_size` or `section_size_list`, depending on the kind. `section_size_list` is a list of size values when multiple sections of this kind are allowed, encoded as a count of items followed by the items.

| description       | length  | value         |                   |
|-------------------|---------|---------------|-------------------|
| section_kind      | 1-byte  | 0x01–0xFF     | `uint8`           |
| section_size      | 2-bytes | 0x0000–0xFFFF | `uint16`          |
| section_size_list | dynamic | n/a           | `uint16, uint16+` |

The list of section headers is terminated with the *section headers terminator byte* `0x00`. The body content follows immediately after.

#### Container validation rules

1. `version` MUST NOT be `0`.
2. `section_kind` MUST NOT be `0`. The value `0` is reserved for *section headers terminator byte*.
3. There MUST be at least one section (and therefore section header).
5. Stray bytes outside of sections MUST NOT be present. This includes trailing bytes after the last section.

### EOF version 1

EOF version 1 is made up of several EIPs, including this one. Some values in this specification are only discussed briefly. To understand the full scope of EOF, it is necessary to review each EIP in-depth.

#### Container

The EOF version 1 container consists of a `header` and `body`.

```
container := header, body
header := 
    magic, version, 
    kind_type, type_size, 
    kind_code, num_code_sections, code_size+,
    [kind_container, num_container_sections, container_size+,]
    kind_data, data_size,
    terminator
body := types_section, code_section+, container_section*, data_section
types_section := (inputs, outputs, max_stack_increase)+
```

*note: `,` is a concatenation operator, `+` should be interpreted as &quot;one or more&quot; of the preceding item, `*` should be interpreted as &quot;zero or more&quot; of the preceding item, and `[item]` should be interpreted as an optional item.*

#### Header

| name                   | length  | value                 | description                                                                                                  |
|------------------------|---------|-----------------------|--------------------------------------------------------------------------------------------------------------|
| magic                  | 2 bytes | 0xEF00                |                                                                                                              |
| version                | 1 byte  | 0x01                  | EOF version                                                                                                  |
| kind_type              | 1 byte  | 0x01                  | kind marker for type section                                                                                 |
| type_size              | 2 bytes | 0x0004-0x1000         | 16-bit unsigned big-endian integer denoting the length of the type section content, 4 bytes per code section |
| kind_code              | 1 byte  | 0x02                  | kind marker for code size section                                                                            |
| num_code_sections      | 2 bytes | 0x0001-0x0400         | 16-bit unsigned big-endian integer denoting the number of the code sections                                  |
| code_size              | 2 bytes | 0x0001-0xFFFF         | 16-bit unsigned big-endian integer denoting the length of the code section content                           |
| kind_container         | 1 byte  | 0x03                  | kind marker for container size section                                                                       |
| num_container_sections | 2 bytes | 0x0001-0x0100         | 16-bit unsigned big-endian integer denoting the number of the container sections                             |
| container_size         | 4 bytes | 0x00000001-0xFFFFFFFF | 32-bit unsigned big-endian integer denoting the length of the container section content                      |
| kind_data              | 1 byte  | 0xFF                  | kind marker for data size section                                                                            |
| data_size              | 2 bytes | 0x0000-0xFFFF         | 16-bit unsigned big-endian integer denoting the length of the data section content (*)                       |
| terminator             | 1 byte  | 0x00                  | marks the end of the header                                                                                  |

(*) For not yet deployed containers this can be greater than the actual content length.

#### Body

| name               | length   | value         | description                                                      |
|--------------------|----------|---------------|------------------------------------------------------------------|
| types_section      | variable | n/a           | stores code section metadata                                     |
| inputs             | 1 byte   | 0x00-0x7F     | number of stack elements the code section consumes               |
| outputs            | 1 byte   | 0x00-0x7F     | number of stack elements the code section returns                |
| max_stack_increase | 2 bytes  | 0x0000-0x03FF | maximum increase of the operand stack height by the code section |
| code_section       | variable | n/a           | arbitrary bytecode                                               |
| container_section  | variable | n/a           | arbitrary EOF-formatted container                                |
| data_section       | variable | n/a           | arbitrary sequence of bytes                                      |

**NOTE**: A special value of `outputs` being `0x80` is designated to denote non-returning functions as defined in a separate EIP.

#### EOF version 1 validation rules

The following validity constraints are placed on the container format:

- `types_size` is divisible by `4`
- the number of code sections must be equal to `types_size / 4`
- data body length may be shorter than `data_size` for a not yet deployed container
- the total size of a container must not exceed `MAX_INITCODE_SIZE` (as defined in [EIP-3860](/EIPs/EIPS/eip-3860))

### Changes to execution semantics

For an EOF contract:

- Execution starts at the first byte of code section 0
- `CODESIZE`, `CODECOPY`, `EXTCODESIZE`, `EXTCODECOPY`, `EXTCODEHASH`, `GAS` are rejected by validation in EOF contracts, with no replacements
- `CALL`, `DELEGATECALL`, `STATICCALL` are rejected by validation in EOF contracts, replacement instructions to be introduced in a separate EIP.
- `DELEGATECALL` (or any replacement instruction for EOF) from an EOF contract to a non-EOF contract (legacy contract, EOA, empty account) is disallowed, and it should fail in the same mode as if the call depth check failed. We allow legacy to EOF path for existing proxy contracts to be able to use EOF upgrades.

For a legacy contract:

- If the target account of `EXTCODECOPY` is an EOF contract, then it will copy up to 2 bytes from `EF00`, as if that would be the code.
- If the target account of `EXTCODEHASH` is an EOF contract, then it will return `0x9dbf3648db8210552e9c4f75c6a1c3057c0ca432043bd648be15fe7be05646f5` (the hash of `EF00`, as if that would be the code).
- If the target account of `EXTCODESIZE` is an EOF contract, then it will return 2.

**NOTE** Like for legacy targets, the aforementioned behavior of `EXTCODECOPY`, `EXTCODEHASH` and `EXTCODESIZE` does not apply to EOF contract targets mid-creation, i.e. those report same as accounts without code.

## Rationale

EVM and/or account versioning has been discussed numerous times over the past years. This proposal aims to learn from them.
See &quot;Ethereum account versioning&quot; on the Fellowship of Ethereum Magicians Forum for a good starting point.

### Execution vs. creation time validation

This specification introduces creation time validation, which means:

- All created contracts with *EOFn* prefix are valid according to version *n* rules. This is very strong and useful property. The client can trust that the deployed code is well-formed.
- In the future, this allows to serialize `JUMPDEST` map in the EOF container and eliminate the need of implicit `JUMPDEST` analysis required before execution.
- Or to completely remove the need for `JUMPDEST` instructions.
- This helps with deprecating EVM instructions and/or features.
- The biggest disadvantage is that deploy-time validation of EOF code must be enabled in two hard-forks. However, the first step ([EIP-3541](/EIPs/EIPS/eip-3541)) is already deployed in London.

The alternative is to have execution time validation for EOF. This is performed every single time a contract is executed, however clients may be able to cache validation results. This *alternative* approach has the following properties:

- Because the validation is consensus-level execution step, it means the execution always requires the entire code. This makes *code merkleization impractical*.
- Can be enabled via a single hard-fork.
- Better backwards compatibility: data contracts starting with the `0xEF` byte or the *EOF prefix* can be deployed. This is a dubious benefit, however.

### The MAGIC

1. The first byte `0xEF` was chosen because it is reserved for this purpose by [EIP-3541](/EIPs/EIPS/eip-3541).

2. The second byte `0x00` was chosen to avoid clashes with three contracts which were deployed on **Mainnet**:
   - `0xca7bf67ab492b49806e24b6e2e4ec105183caa01`: `EFF09f918bf09f9fa9`
   - `0x897da0f23ccc5e939ec7a53032c5e80fd1a947ec`: `EF`
   - `0x6e51d4d9be52b623a3d3a2fa8d3c5e3e01175cd0`: `EF`

3. No contracts starting with `0xEF` bytes exist on public testnets: Goerli, Ropsten, Rinkeby, Kovan and Sepolia at their London fork block.

**NOTE**: This EIP MUST NOT be enabled on chains which contain bytecodes starting with `MAGIC` and not being valid EOF.

### EOF version range start with 1

The version number 0 will never be used in EOF, so we can call legacy code *EOF0*.
Also, implementations may use APIs where 0 version number denotes legacy code.

### Section structure

We have considered different questions for the sections:

- Streaming headers (i.e. `section_header, section_data, section_header, section_data, ...`) are used in some other formats (such as WebAssembly). They are handy for formats which are subject to editing (adding/removing sections). That is not a useful feature for EVM. One minor benefit applicable to our case is that they do not require a specific &quot;header terminator&quot;. On the other hand they seem to play worse with code chunking / merkleization, as it is better to have all section headers in a single chunk.
- Whether to have a header terminator or to encode `number_of_sections` or `total_size_of_headers`. Both raise the question of how large of a value these fields should be able to hold. A terminator byte seems to avoid the problem of choosing a size which is too small without any perceptible downside, so it is the path taken.
- (EOF1) Whether to encode section sizes as fixed 16-bit (32-bit for container section size) values or some kind of variable length field (e.g. LEB128). We have opted for fixed size. Should this be limiting in the future, a new EOF version could change the format. Besides simplifying client implementations, not using LEB128 also greatly simplifies on-chain parsing.
- Whether or not to have more structure to the container header for all EOF versions to follow. In order to allow future formats optimized for chunking and merkleization (verkleization) it was decided to keep it generic and specify the structure only for a specific EOF version.

### Data-only contracts

See section [Lack of `EXTDATACOPY` in EIP-7480](/EIPs/EIPS/eip-7480#lack-of-extdatacopy).

### EOF1 contracts can only `DELEGATECALL` EOF1 contracts

Currently contracts can selfdestruct in three different ways (directly through `SELFDESTRUCT`, indirectly through `CALLCODE` and indirectly through `DELEGATECALL`). [EIP-3670](/EIPs/EIPS/eip-3670) disables the first two possibilities, however the third possibility remains. Allowing EOF1 contracts to only `DELEGATECALL` other EOF1 contracts allows the following strong statement: EOF1 contract can never be destructed. Attacks based on `SELFDESTRUCT` completely disappear for EOF1 contracts. These include destructed library contracts (e.g. Parity Multisig).

### EOF1 containers have a size limit

Imposing an EOF-validation time limit for the size of EOF containers provides a reference limit of how large the containers should EVM implementations be able to handle when validating and processing containers. `MAX_INITCODE_SIZE` was chosen for EOF1, as it is what contract creation currently allows for.

Given one of the main reasons for the limit is to avoid attack vectors on `JUMPDEST`-analysis, and EOF removes the need for `JUMPDEST`-analysis and introduces a cost structure for deploy-time analysis, in the future this limit could be increased or even lifted for EOF.

### `kind_data` could be `0x04` not `0xff`

Putting the data section last as `0xff` has the advantage of aligning with the fact that it always comes last. We&apos;re avoiding a situation that a new section kind would need to go before the data section and break the section kind ordering. At the same time, data section being last is advantageous because it is the section which gets data appended to during contract deployment.

## Backwards Compatibility

This is a breaking change given that any code starting with `0xEF` was not deployable before (and resulted in exceptional abort if executed), but now some subset of such codes can be deployed and executed successfully.

The choice of `MAGIC` guarantees that none of the contracts existing on the chain are affected by the new rules.

## Security Considerations

With the anticipated EOF extensions, the validation is expected to have linear computational and space complexity.
We think that the validation cost is sufficiently covered by:

- [EIP-3860](/EIPs/EIPS/eip-3860) for *initcode*,
- high per-byte cost of deploying *code*.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 16 Mar 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3540</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3540</guid>
      </item>
    
      <item>
        <title>Reject new contract code starting with the 0xEF byte</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/evm-object-format-eof/5727</comments>
        
        <description>## Abstract

Disallow new code starting with the `0xEF` byte to be deployed. Code already existing in the account trie starting with `0xEF` byte is not affected semantically by this change.

## Motivation

Contracts conforming to the EVM Object Format (EOF) are going to be validated at deploy time. In order to guarantee that every EOF-formatted contract in the state is valid, we need to prevent already deployed (and not validated) contracts from being recognized as such format. This will be achieved by choosing a byte sequence for the *magic* that doesn&apos;t exist in any of the already deployed contracts. To prevent the growth of the search space and to limit the analysis to the contracts existing before this fork, we disallow the starting byte of the format (the first byte of the magic).

Should the EVM Object Format proposal not be deployed in the future, the *magic* can be used by other features depending on versioning. In the case versioning becomes obsolete, it is simple to roll this back by allowing contracts starting with the `0xEF` byte to be deployed again.

## Specification

After `block.number == HF_BLOCK` new contract creation (via create transaction, `CREATE` or `CREATE2` instructions) results in an exceptional abort if the _code_&apos;s first byte is `0xEF`. 

### Remarks

The *initcode* is the code executed in the context of the *create* transaction, `CREATE`, or `CREATE2` instructions. The *initcode* returns *code* (via the `RETURN` instruction), which is inserted into the account. See section 7 (&quot;Contract Creation&quot;) in the Yellow Paper for more information.

The opcode `0xEF` is currently an undefined instruction, therefore: *It pops no stack items and pushes no stack items, and it causes an exceptional abort when executed.* This means *initcode* or already deployed *code* starting with this instruction will continue to abort execution.

The exceptional abort due to *code* starting with `0xEF` behaves exactly the same as any other exceptional abort that can occur during *initcode* execution, i.e. in case of abort all gas provided to a `CREATE*` or create transaction is consumed.

## Rationale

The `0xEF` byte was chosen because it resembles **E**xecutable **F**ormat.

Contracts using unassigned opcodes are generally understood to be at risk of changing semantics. Hence using the unassigned `0xEF` should have lesser effects, than choosing an assigned opcode, such as `0xFD` (`REVERT`), `0xFE` (`INVALID)`, or `0xFF` (`SELFDESTRUCT`). Arguably while such contracts may not be very useful, they are still using valid opcodes.

Analysis in May 2021, on `18084433` contracts in state, showed that there are 0 existing contracts starting with the `0xEF` byte, as opposed to 1, 4, and 12 starting with `0xFD`, `0xFE`, and `0xFF`, respectively.

## Test Cases

Each test case below may be executed in 3 different contexts:
- create transaction (no account code)
- `CREATE`, with account code: `0x6000356000523660006000f0151560165760006000fd5b` (Yul code: `mstore(0, calldataload(0)) if iszero(create(0, 0, calldatasize())) { revert(0, 0) }`),
- `CREATE2`, with account code: `0x60003560005260003660006000f5151560185760006000fd5b` (Yul code: `mstore(0, calldataload(0)) if iszero(create2(0, 0, calldatasize(), 0)) { revert(0, 0) }`)

| Case  | Calldata | Expected result |
| -------- | -------- | -------- |
| deploy one byte `ef` | `0x60ef60005360016000f3` | new contract not deployed, transaction fails |
| deploy two bytes `ef00` | `0x60ef60005360026000f3` | new contract not deployed, transaction fails |
| deploy three bytes `ef0000` | `0x60ef60005360036000f3` | new contract not deployed, transaction fails |
| deploy 32 bytes `ef00...00` | `0x60ef60005360206000f3` | new contract not deployed, transaction fails |
| deploy one byte `fe` | `0x60fe60005360016000f3` | new contract deployed, transaction succeeds |

## Backwards Compatibility

This is a breaking change given new code starting with the `0xEF` byte will not be deployable, and contract creation will result in a failure. However, given bytecode is executed starting at its first byte, code deployed with `0xEF` as the first byte is not executable anyway.

While this means no currently executable contract is affected, it does rejects deployment of new data contracts starting with the `0xEF` byte.

## Security Considerations

The authors are not aware of any security or DoS risks posed by this change.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 16 Mar 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3541</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3541</guid>
      </item>
    
      <item>
        <title>Difficulty Bomb Delay to December 2021</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3554-ice-age-delay-targeting-december-2021/6188</comments>
        
        <description>## Simple Summary
Delays the difficulty bomb to show effect the first week of December 2021.

## Abstract
Starting with `FORK_BLOCK_NUMBER` the client will calculate the difficulty based on a fake block number suggesting to the client that the difficulty bomb is adjusting 9,700,000 blocks later than the actual block number.

## Motivation
Targeting for the Shanghai upgrade and/or the Merge to occur before December 2021. Either the bomb can be readjusted at that time, or removed all together.

## Specification
#### Relax Difficulty with Fake Block Number
For the purposes of `calc_difficulty`, simply replace the use of `block.number`, as used in the exponential ice age component, with the formula:
```py
    fake_block_number = max(0, block.number - 9_700_000) if block.number &gt;= FORK_BLOCK_NUMBER else block.number
```
## Rationale

The following script predicts a .1 second delay to blocktime the first week of december and a 1 second delay by the end of the month. This gives reason to address because the effect will be seen, but not so much urgency we don&apos;t have space to work around if needed.

```python
def predict_diff_bomb_effect(current_blknum, current_difficulty, block_adjustment, months):
    &apos;&apos;&apos;
    Predicts the effect on block time (as a ratio) in a specified amount of months in the future.
    Vars used in last prediction:
    current_blknum = 12382958
    current_difficulty = 7393633000000000
    block adjustment = 9700000
    months = 6
    &apos;&apos;&apos;
    blocks_per_month = (86400 * 30) // 13.3
    future_blknum = current_blknum + blocks_per_month * months
    diff_adjustment = 2 ** ((future_blknum - block_adjustment) // 100000 - 2)
    diff_adjust_coeff = diff_adjustment / current_difficulty * 2048
    return diff_adjust_coeff 


diff_adjust_coeff = predict_diff_bomb_effect(12382958,7393633000000000,9700000,6)
```

## Backwards Compatibility
No known backward compatibility issues.

## Security Considerations
Misjudging the effects of the difficulty can mean longer blocktimes than anticipated until a hardfork is released. Wild shifts in difficulty can affect this number severely. Also, gradual changes in blocktimes due to longer-term adjustments in difficulty can affect the timing of difficulty bomb epochs. This affects the usability of the network but unlikely to have security ramifications.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 06 May 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3554</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3554</guid>
      </item>
    
      <item>
        <title>Trust Minimized Upgradeability Proxy</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/trust-minimized-proxy/5742</comments>
        
        <description>## Abstract

Removing trust from upgradeability proxy is necessary for anonymous developers. In order to accomplish this, instant and potentially malicious upgrades must be prevented. This EIP introduces additional storage slots for upgradeability proxy which are assumed to decrease trust in interaction with upgradeable smart contracts. Defined by the admin implementation logic can be made an active implementation logic only after Zero Trust Period allows.

## Motivation

Anonymous developers who utilize upgradeability proxies typically struggle to earn the trust of the community.

Fairer, better future for humanity absolutely requires some developers to stay anonymous while still attract vital attention to solutions they propose and at the same time leverage the benefits of possible upgradeability.

## Specification

The specification is an addition to the standard [EIP-1967](/EIPs/EIPS/eip-1967) transparent proxy design.
The specification focuses on the slots it adds. All admin interactions with trust minimized proxy must emit an event to make admin actions trackable, and all admin actions must be guarded with `onlyAdmin()` modifier.

### Next Logic Contract Address

Storage slot `0x19e3fabe07b65998b604369d85524946766191ac9434b39e27c424c976493685` (obtained as `bytes32(uint256(keccak256(&apos;eip3561.proxy.next.logic&apos;)) - 1)`).
Desirable implementation logic address must be first defined as next logic, before it can function as actual logic implementation stored in EIP-1967 `IMPLEMENTATION_SLOT`.
Admin interactions with next logic contract address correspond with these methods and events:

```solidity
// Sets next logic contract address. Emits NextLogicDefined
// If current implementation is address(0), then upgrades to IMPLEMENTATION_SLOT
// immedeatelly, therefore takes data as an argument
function proposeTo(address implementation, bytes calldata data) external IfAdmin
// As soon UPGRADE_BLOCK_SLOT allows, sets the address stored as next implementation
// as current IMPLEMENTATION_SLOT and initializes it.
function upgrade(bytes calldata data) external IfAdmin
// cancelling is possible for as long as upgrade() for given next logic was not called
// emits NextLogicCanceled
function cancelUpgrade() external onlyAdmin;

event NextLogicDefined(address indexed nextLogic, uint earliestArrivalBlock); // important to have
event NextLogicCanceled(address indexed oldLogic);
```

### Upgrade Block

Storage slot `0xe3228ec3416340815a9ca41bfee1103c47feb764b4f0f4412f5d92df539fe0ee` (obtained as `bytes32(uint256(keccak256(&apos;eip3561.proxy.next.logic.block&apos;)) - 1)`).
On/after this block next logic contract address can be set to EIP-1967 `IMPLEMENTATION_SLOT` or, in other words, `upgrade()` can be called. Updated automatically according to Zero Trust Period, shown as `earliestArrivalBlock` in the event `NextLogicDefined`.

### Propose Block

Storage slot `0x4b50776e56454fad8a52805daac1d9fd77ef59e4f1a053c342aaae5568af1388` (obtained as `bytes32(uint256(keccak256(&apos;eip3561.proxy.propose.block&apos;)) - 1)`).
Defines after/on which block *proposing* next logic is possible. Required for convenience, for example can be manually set to a year from given time. Can be set to maximum number to completely seal the code.
Admin interactions with this slot correspond with this method and event:

```solidity
function prolongLock(uint b) external onlyAdmin;
event ProposingUpgradesRestrictedUntil(uint block, uint nextProposedLogicEarliestArrival);
```

### Zero Trust Period

Storage slot `0x7913203adedf5aca5386654362047f05edbd30729ae4b0351441c46289146720` (obtained as `bytes32(uint256(keccak256(&apos;eip3561.proxy.zero.trust.period&apos;)) - 1)`).
Zero Trust Period in amount of blocks, can only be set higher than previous value. While it is at default value(0), the proxy operates exactly as standard EIP-1967 transparent proxy. After zero trust period is set, all above specification is enforced.
Admin interactions with this slot should correspond with this method and event:

```solidity
function setZeroTrustPeriod(uint blocks) external onlyAdmin;
event ZeroTrustPeriodSet(uint blocks);
```

### Implementation Example

```solidity
pragma solidity &gt;=0.8.0; //important

// EIP-3561 trust minimized proxy implementation https://github.com/ethereum/EIPs/blob/master/EIPS/eip-3561.md
// Based on EIP-1967 upgradeability proxy: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1967.md

contract TrustMinimizedProxy {
    event Upgraded(address indexed toLogic);
    event AdminChanged(address indexed previousAdmin, address indexed newAdmin);
    event NextLogicDefined(address indexed nextLogic, uint earliestArrivalBlock);
    event ProposingUpgradesRestrictedUntil(uint block, uint nextProposedLogicEarliestArrival);
    event NextLogicCanceled();
    event ZeroTrustPeriodSet(uint blocks);

    bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
    bytes32 internal constant LOGIC_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
    bytes32 internal constant NEXT_LOGIC_SLOT = 0x19e3fabe07b65998b604369d85524946766191ac9434b39e27c424c976493685;
    bytes32 internal constant NEXT_LOGIC_BLOCK_SLOT = 0xe3228ec3416340815a9ca41bfee1103c47feb764b4f0f4412f5d92df539fe0ee;
    bytes32 internal constant PROPOSE_BLOCK_SLOT = 0x4b50776e56454fad8a52805daac1d9fd77ef59e4f1a053c342aaae5568af1388;
    bytes32 internal constant ZERO_TRUST_PERIOD_SLOT = 0x7913203adedf5aca5386654362047f05edbd30729ae4b0351441c46289146720;

    constructor() payable {
        require(
            ADMIN_SLOT == bytes32(uint256(keccak256(&apos;eip1967.proxy.admin&apos;)) - 1) &amp;&amp;
                LOGIC_SLOT == bytes32(uint256(keccak256(&apos;eip1967.proxy.implementation&apos;)) - 1) &amp;&amp;
                NEXT_LOGIC_SLOT == bytes32(uint256(keccak256(&apos;eip3561.proxy.next.logic&apos;)) - 1) &amp;&amp;
                NEXT_LOGIC_BLOCK_SLOT == bytes32(uint256(keccak256(&apos;eip3561.proxy.next.logic.block&apos;)) - 1) &amp;&amp;
                PROPOSE_BLOCK_SLOT == bytes32(uint256(keccak256(&apos;eip3561.proxy.propose.block&apos;)) - 1) &amp;&amp;
                ZERO_TRUST_PERIOD_SLOT == bytes32(uint256(keccak256(&apos;eip3561.proxy.zero.trust.period&apos;)) - 1)
        );
        _setAdmin(msg.sender);
    }

    modifier IfAdmin() {
        if (msg.sender == _admin()) {
            _;
        } else {
            _fallback();
        }
    }

    function _logic() internal view returns (address logic) {
        assembly {
            logic := sload(LOGIC_SLOT)
        }
    }

    function _nextLogic() internal view returns (address nextLogic) {
        assembly {
            nextLogic := sload(NEXT_LOGIC_SLOT)
        }
    }

    function _proposeBlock() internal view returns (uint b) {
        assembly {
            b := sload(PROPOSE_BLOCK_SLOT)
        }
    }

    function _nextLogicBlock() internal view returns (uint b) {
        assembly {
            b := sload(NEXT_LOGIC_BLOCK_SLOT)
        }
    }

    function _zeroTrustPeriod() internal view returns (uint ztp) {
        assembly {
            ztp := sload(ZERO_TRUST_PERIOD_SLOT)
        }
    }

    function _admin() internal view returns (address adm) {
        assembly {
            adm := sload(ADMIN_SLOT)
        }
    }

    function _setAdmin(address newAdm) internal {
        assembly {
            sstore(ADMIN_SLOT, newAdm)
        }
    }

    function changeAdmin(address newAdm) external IfAdmin {
        emit AdminChanged(_admin(), newAdm);
        _setAdmin(newAdm);
    }

    function upgrade(bytes calldata data) external IfAdmin {
        require(block.number &gt;= _nextLogicBlock(), &apos;too soon&apos;);
        address logic;
        assembly {
            logic := sload(NEXT_LOGIC_SLOT)
            sstore(LOGIC_SLOT, logic)
        }
        (bool success, ) = logic.delegatecall(data);
        require(success, &apos;failed to call&apos;);
        emit Upgraded(logic);
    }

    fallback() external payable {
        _fallback();
    }

    receive() external payable {
        _fallback();
    }

    function _fallback() internal {
        require(msg.sender != _admin());
        _delegate(_logic());
    }

    function cancelUpgrade() external IfAdmin {
        address logic;
        assembly {
            logic := sload(LOGIC_SLOT)
            sstore(NEXT_LOGIC_SLOT, logic)
        }
        emit NextLogicCanceled();
    }

    function prolongLock(uint b) external IfAdmin {
        require(b &gt; _proposeBlock(), &apos;can be only set higher&apos;);
        assembly {
            sstore(PROPOSE_BLOCK_SLOT, b)
        }
        emit ProposingUpgradesRestrictedUntil(b, b + _zeroTrustPeriod());
    }

    function setZeroTrustPeriod(uint blocks) external IfAdmin {
        // before this set at least once acts like a normal eip 1967 transparent proxy
        uint ztp;
        assembly {
            ztp := sload(ZERO_TRUST_PERIOD_SLOT)
        }
        require(blocks &gt; ztp, &apos;can be only set higher&apos;);
        assembly {
            sstore(ZERO_TRUST_PERIOD_SLOT, blocks)
        }
        _updateNextBlockSlot();
        emit ZeroTrustPeriodSet(blocks);
    }

    function _updateNextBlockSlot() internal {
        uint nlb = block.number + _zeroTrustPeriod();
        assembly {
            sstore(NEXT_LOGIC_BLOCK_SLOT, nlb)
        }
    }

    function _setNextLogic(address nl) internal {
        require(block.number &gt;= _proposeBlock(), &apos;too soon&apos;);
        _updateNextBlockSlot();
        assembly {
            sstore(NEXT_LOGIC_SLOT, nl)
        }
        emit NextLogicDefined(nl, block.number + _zeroTrustPeriod());
    }

    function proposeTo(address newLogic, bytes calldata data) external payable IfAdmin {
        if (_zeroTrustPeriod() == 0 || _logic() == address(0)) {
            _updateNextBlockSlot();
            assembly {
                sstore(LOGIC_SLOT, newLogic)
            }
            (bool success, ) = newLogic.delegatecall(data);
            require(success, &apos;failed to call&apos;);
            emit Upgraded(newLogic);
        } else {
            _setNextLogic(newLogic);
        }
    }

    function _delegate(address logic_) internal {
        assembly {
            calldatacopy(0, 0, calldatasize())
            let result := delegatecall(gas(), logic_, 0, calldatasize(), 0, 0)
            returndatacopy(0, 0, returndatasize())
            switch result
            case 0 {
                revert(0, returndatasize())
            }
            default {
                return(0, returndatasize())
            }
        }
    }
}
```

## Rationale

An argument &quot;just don&apos;t make such contracts upgadeable at all&quot; fails when it comes to complex systems which do or do not heavily rely on human factor, which might manifest itself in unprecedented ways. It might be impossible to model some systems right on first try. Using decentralized governance for upgrade management coupled with EIP-1967 proxy might become a serious bottleneck for certain protocols before they mature and data is at hand.

A proxy without a time delay before an actual upgrade is obviously abusable. A time delay is probably unavoidable, even if it means that inexperienced developers might not have confidence using it. Albeit this is a downside of this EIP, it&apos;s a critically important option to have in smart contract development today.

## Security Considerations

Users must ensure that a trust-minimized proxy they interact with does not allow overflows, ideally represents the exact copy of the code in implementation example above, and also they must ensure that Zero Trust Period length is reasonable(at the very least two weeks if upgrades are usually being revealed beforehand, and in most cases at least a month).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 09 May 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3561</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3561</guid>
      </item>
    
      <item>
        <title>Sealed NFT Metadata Standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3569-sealed-nft-metadata-standard/7130</comments>
        
        <description>## Simple Summary

The Sealed NFT Metadata Extension provides a mechanism to immortalize NFT metadata in a cost-effective manner.

## Abstract

This standard accomplishes three things; it provides a way for potential collectors to verify that the NFT metadata will not change, allows creators to immortalize metadata for multiple tokens at one time, and allows metadata for many NFTs to be read and cached from one file. A creator can call the `seal` function for a range of one or many sequential NFTs. Included as an argument is a URI which points to a decentralized storage service like IPFS and will be stored in the smart contract. The URI will return a JSON object in which the keys are token IDs and the values are either a string which is a URI pointing to a metadata file stored on a decentralized file system, or raw metadata JSON for each token ID. The token ID(s) will then be marked as sealed in the smart contract and cannot be sealed again. The `seal` function can be called after NFT creation, or during the NFT creation process.

## Motivation

In the original ERC-721 standard, the metadata extension specifies a `tokenURI` function which returns a URI for a single token ID. This may be hosted on IPFS or might be hosted on a centralized server. There&apos;s no guarantee that the NFT metadata will not change. This is the same for the ERC-1155 metadata extension. In addition to that - if you want to update the metadata for many NFTs you would need to do so in O(n) time, which as we know is not financially feasible at scale. By allowing for a decentralized URI to point to a JSON object of many NFT IDs we can solve this issue by providing metadata for many tokens at one time rather than one at a time. We can also provide methods which give transparency into whether the NFT has be explicitly &quot;sealed&quot; and that the metadata is hosted on a decentralized storage space.

There is not a way for the smart contract layer to communicate with a storage layer and as such we need a solution which provides a way for potential NFT collectors on Ethereum to verify that their NFT will not be &quot;rug pulled&quot;. This standard provides a solution for that. By allowing creators to seal their NFTs during or after creation, they are provided with full flexibility when it comes to creating their NFTs. Decentralized storage means permanence - in the fast-moving world of digital marketing campaigns, or art projects mistakes can happen. As such, it is important for creators to have flexibility when creating their projects. Therefore, this standard allows creators to opt in at a time of their choosing. Mistakes do happen and metadata should be flexible enough so that creators can fix mistakes or create dynamic NFTs (see Beeple&apos;s CROSSROAD NFT). If there comes a time when the NFT metadata should be immortalized, then the creator can call the `seal` method. Owners, potential owners, or platforms can verify that the NFT was sealed and can check the returned URI. If the `sealedURI` return value is not hosted on a decentralized storage platform, or the `isSealed` method does not return `true` for the given NFT ID then it can be said that one cannot trust that these NFTs will not change at a future date and can then decide if they want to proceed with collecting the given NFT.

## Specification

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.

```
interface SealedMetadata {
  /**
    @notice This function is used to set a sealed URI for the given range of tokens.
    @dev
      - If the sealed URI is being set for one token then the fromTokenId and toTokenId
      values MUST be the same.

      - If any token within the range of tokens specified has already
      been sealed then this function MUST throw.

      - This function MAY be called at the time of NFT creation, or after the NFTs have been created.

      - It is RECOMMENDED that this function only be executable by either the creator of the smart contract,
        or the creator of the NFTs, but this is OPTIONAL and should be implemented based on use case.

      - This function MUST emit the Sealed event

      - The URI argument SHOULD point to a JSON file hosted within a decentralized file system like IPFS

    @param fromTokenId The first token in a consecutive range of tokens
    @param toTokenId The ending token in a consecutive range of tokens
    @param uri A URI which points to a JSON file hosted on a decentralized file system.
  */
  function seal(uint256 fromTokenId, uint256 toTokenId, string memory uri) external;

  /**
    @notice This function returns the URI which the sealed metadata can be found for the given token ID
    @dev
      - This function MUST throw if the token ID does not exist, or is not sealed

    @param tokenId Token ID to retrieve the sealed URI for

    @return The sealed URI in which the metadata for the given token ID can be found
  */
  function sealedURI(uint256 tokenId) external view returns (string);

  /**
    @notice This function returns a boolean stating if the token ID is sealed or not
    @dev This function should throw if the token ID does not exist

    @param tokenId The token ID that will be checked if sealed or not

    @return Boolean stating if token ID is sealed
  */
  function isSealed(uint256 tokenId) external view returns (bool)

  /// @dev This emits when a range of tokens is sealed
  event Sealed(uint256 indexed fromTokenId, uint256 indexed toTokenId, string memory uri);

}
```

### Sealed Metadata JSON Format

The sealed metadata JSON file MAY contain metadata for many different tokens. The top level keys of the JSON object MUST be token IDs.

```

type ERC721Metadata = {
  name?: string;
  image?: string;
  description?: string;
}

type SealedMetaDataJson = {
  [tokenId: string]: string | ERC721Metadata;
}

const sealedMetadata: SealedMetaDataJson = {
    &apos;1&apos;: {
        name: &apos;Metadata for token with ID 1&apos;
    },
    &apos;2&apos;: {
        name: &apos;Metadata for token with ID 2&apos;
    },
    // Example pointing to another file
    &apos;3&apos;: &apos;ipfs://SOME_HASH_ON_IPFS&apos;
};
```

## Rationale

**Rationale for rule not explicitly requiring that sealed URI be hosted on decentralized filestorage**

In order for this standard to remain future proof there is no validation within the smart contract that would verify the sealed URI is hosted on IPFS or another decentralized file storage system. The standard allows potential collectors and platforms to validate the URI on the client.

**Rationale to include many NFT metadata objects, or URIs in one JSON file**

By including metadata for many NFTs in one JSON file we can eliminate the need for many transactions to set the metadata for multiple NFTs. Given that this file should not change NFT platforms, or explorers can cache the metadata within the file.

**Rationale for emitting `Sealed` event**

Platforms and explorers can use the `Sealed` event to automatically cache metadata, or update information regarding specified NFTs.

**Rationale for allowing URIs as values in the JSON file**

If a token&apos;s metadata is very large, or there are many tokens you can save file space by referencing another URI rather than storing the metadata JSON within the top level metadata file.

## Backwards Compatibility

There is no backwards compatibility with existing standards. This is an extension which could be added to existing NFT standards.

## Security Considerations

There are no security considerations related directly to the implementation of this standard.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 07 May 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3569</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3569</guid>
      </item>
    
      <item>
        <title>Block Access List</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethresear.ch/t/block-access-list-v0-1/9505</comments>
        
        <description>## Simple Summary
A proposal to build a block&apos;s `access_list` and include its fingerprint `AccessListRoot` in the block header.

## Abstract
[EIP-2929](/EIPs/EIPS/eip-2929)/[EIP-2930](/EIPs/EIPS/eip-2930) centers around normalizing the (low) gas costs of data/storage accesses made by a transaction as well as providing for (and encouraging) a new transaction type format:
```
0x01 || rlp([chainId, nonce, gasPrice, gasLimit, to, value, data, access_list, yParity, senderR, senderS])
```
that makes upfront `access_list` declarations, where `access_list` is some `[[{20 bytes}, [{32 bytes}...]]...]` map of `AccessedAddress=&gt; AccessedStorageKeys`.

The first *accesses* of these upfront *declarations* are charged at discounted price (roughly ~`10%`) and first accesses outside this list are charged higher price. Reason is upfront access declaration provides for a way to *preload/optimize/batch* loading these locations while executing the transaction.
This inadvertently leads to generation of transaction `access_list` that has all (first) accesses (declared or not) made by a transaction.
This proposal is to collate these *transaction* `access_list`s for all the transactions in a **block** `access_list` document and include its *fingerprint* in the block header.

## Motivation
Motivation for collating the *transaction* `access_list`s for all the transactions in a **block**’s `access_list` is to have an *access index* of the block with following benefits:
1. Block execution/validation optimizations/parallelization/cache warm-up by enabling construction of *a partial order* for access and hence execution (hint: *chains* in this *poset* can be parallelized).
2. Enabling partial inspection and fetching/serving of a block data/state by *light sync* or *fast sync* protocols concerned with a subset of addresses.
3. Possible future extension of this list to serve as index for bundling, serving and fetching witness data for *stateless* protocols.

## Specification
A block `access_list` represents:
```
Set [ 
    AccessedAddress, 
    List [AccessedStorageKeys] , 
    Set  [ AccessedInBlockTransactionNumber, List [ AccessedStorageKeys ]]  
]
```
A **canonical** construction of such an `access_list` is specified as below.

### Canonical Block Access List
An `access_list` is defined to be comprised of many `access_list_entry` elements:
```
access_list   :=  [access_list_entry, ...]
```

An `access_list_entry` is a 3-tuple of:
* address
* sorted list of storage keys of the address accessed across the entire block
* sorted list of 2-tuples of:
    * transaction index in which the address or any of its storage keys were accessed
    * sorted list of storage keys which were accessed

```
access_list                 := [access_list_entry, ...]
access_list_entry           := [address, storage_keys, accesses_by_txn_index]
address                     := bytes20
accesses_by_txn_index       := [txn_index_and_keys, ...]
txn_index_and_keys          := [txn_index, storage_keys]
txn_index                   := uint64  # or uint256 or whatever
storage_keys                := [storage_key, ...]
storage_key                 := bytes32
```

Additional sorting rules for the above are that:
* `access_list` is sorted by the `address`
* `storage_keys` is sorted
* `accesses_by_txn_index` is sorted by `txn_index`

Additional validation rules for the above are that:
* Each unique `address` may only appear at most once in `access_list`
* Each `storage_key` may only appear at most once in `storage_keys`
* Each `txn_index` may only appear at most once in `txn_index_and_keys`

All sorting is in increasing order.

### AccessListRoot
An `AccessListRoot` is a URN *like* encoding `Hash/Commitment` of the canonical `access_list` as well as the construction type ( `sha256` ) and serialization type ( `json` ), i.e.
```
AccessListRoot := &quot;urn:sha256:json:0x${ SHA256( access_list.toJSONString(&apos;utf8&apos;) ).toHexString() }&quot;
```
where `0x${ SHA256 (...)...}` is the `SHA256` hashed `32` bytes hex string as indicated by leading `0x`.

### Additional Block Validation
Validating a new block requires an additional validation check that the block’s `AccessListRoot` matches the one generated by executing the block using the construction as defined by the `AccessListRoot` URN.

## Rationale
### Sorting of canonical `access_list`
It is specified to be sorted in lexicographic ordering or integer sorting wherever applicable and specified. Sorting with respect to access time was considered but didn&apos;t seem to provide any additional benefit at the cost of adding implementation complexity and bookkeeping.

### `AccessListRoot` 
`AccessListRoot` is generated to prevent any *griefing* attacks and hence will need to be included (and validated) in the *block header*.
Even though `AccessListRoot` is currently specified to be a simple `sha256` hash of the canonical `access_list`, it would be beneficial to consider other constructions
* a tree structure (`merkle`/`verkle`). It will be a bit more expensive but will enable partial downloading, inspection and validation of the `access_list`. 
* a normal `kate` commitment can also be generated to enable this partial capability and is recommended as validating partial fetch of access list chunks would be very simple. 

Also serialization of the `access_list` is currently specified as a normal `JSON String` dump and these parameters could vary from construction to construction, but for the sake of simplicity, it can always be `sha256` hashed to get a consistent `32` bytes hex string root.

So this AccessListRoot could evolve to `urn:merkle:ssz:...` or to `urn:kate:...` or to any other scheme as per requirement. And the idea of having the `AccessListRoot` as URN *like* structure is to enable upgradation to these paths without affecting block structure.


### Future extensions of `access_list`
We can extend the notion of a block’s `access_list` to include witnesses:
```
access_list := Set[ 
    Address,
    List [ AddressWitnesses ],
    Set  [ AccessedStorageKey, List [ StorageKeyWitnesses] ],        
    Set  [ AccessedInBlockTransactionNumber, List [ AccessedStorageKeys ] ]
]
```
and then get to define the a canonical specification for building the fingerprint.
This will allow an incremental path to partial or full statelessness, where it would be easy to bundle/request **witnesses** using this `access_list`.

## Backwards Compatibility
The extra block validation will only be mandatory post the block number this EIP comes into effect, but the clients can still provide a way to generate (and possibly store) this access list  on request (via the `JSON/RPC` api). However this is optional and client dependent.

## Security Considerations
There are no known security issues as a result of this change.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 22 May 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3584</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3584</guid>
      </item>
    
      <item>
        <title>Assemble assets into NFTs</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/3590</comments>
        
        <description>## Simple Summary
This standard defines a ERC-721 token called assembly token which can represent a combination of assets.

## Abstract
The ERC-1155 multi-token contract defines a way to batch transfer tokens, but those tokens must be minted by the ERC-1155 contract itself. This EIP is an ERC-721 extension with ability to assemble assets such as ether, ERC-20 tokens, ERC-721 tokens and ERC-1155 tokens into one ERC-721 token whose token id is also the asset&apos;s signature. As assets get assembled into one, batch transfer or swap can be implemented very easily.

## Motivation
As NFT arts and collectors rapidly increases, some collectors are not satisfied with traditional trading methods. When two collectors want to swap some of their collections, currently they can list their NFTs on the market and notify the other party to buy, but this is inefficient and gas-intensive. Instead, some collectors turn to social media or chat group looking for a trustworthy third party to swap NFTs for them. The third party takes NFTs from both collector A and B, and transfer A&apos;s collections to B and B&apos;s to A. This is very risky.

The safest way to do batch swap, is to transform batch swap into atomic swap, i.e. one to one swap. But first we should &quot;assemble&quot; those ether, ERC-20 tokens, ERC-721 tokens and ERC-1155 tokens together, and this is the main purpose of this EIP.

## Specification
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.

ERC-721 compliant contracts MAY implement this ERC to provide a standard method to assemble assets.

`mint` and `safeMint` assemble assets into one ERC-721 token. `mint` SHOULD be implemented for normal ERC-20 tokens whose `_transfer` is lossless. `safeMint` MUST takes care for lossy token such as PIG token whose `_transfer` function is taxed.

`_salt` of `hash` function MAY be implemented other way, even provided as user input. But the token id MUST be generated by `hash` function.

Implementations of the standard MAY supports different set of assets.

Implementers of this standard MUST have all of the following functions:

```
pragma solidity ^0.8.0;

interface AssemblyNFTInterface {

  event AssemblyAsset(address indexed firstHolder,
                    uint256 indexed tokenId,
                    uint256 salt,
                    address[] addresses,
                    uint256[] numbers);

  /**
  * @dev hash function assigns the combination of assets with salt to bytes32 signature that is also the token id.
  * @param `_salt` prevents hash collision, can be chosen by user input or increasing nonce from contract.
  * @param `_addresses` concat assets addresses, e.g. [ERC-20_address1, ERC-20_address2, ERC-721_address_1, ERC-1155_address_1, ERC-1155_address_2]
  * @param `_numbers` describes how many eth, ERC-20 token addresses length, ERC-721 token addresses length, ERC-1155 token addresses length,
  * ERC-20 token amounts, ERC-721 token ids, ERC-1155 token ids and amounts.
  */
  function hash(uint256 _salt, address[] memory _addresses, uint256[] memory _numbers) external pure returns (uint256 tokenId);

  /// @dev to assemble lossless assets
  /// @param `_to` the receiver of the assembly token
  function mint(address _to, address[] memory _addresses, uint256[] memory _numbers) payable external returns(uint256 tokenId);

  /// @dev mint with additional logic that calculates the actual received value for tokens.
  function safeMint(address _to, address[] memory _addresses, uint256[] memory _numbers) payable external returns(uint256 tokenId);

  /// @dev burn this token and releases assembled assets
  /// @param `_to` to which address the assets is released
  function burn(address _to, uint256 _tokenId, uint256 _salt, address[] calldata _addresses, uint256[] calldata _numbers) external;

}

```

## Rationale
There are many reasons why people want to pack their NFTs together. For example, a collector want to pack a set of football players into a football team; a collector has hundreds of of NFTs with no categories to manage them; a collector wants to buy a full collection of NFTs or none of them. They all need a way a assemble those NFTs together.

The reason for choosing ERC-721 standard as a wrapper is ERC-721 token is already widely used and well supported by NFT wallets. And assembly token itself can also be assembled again. Assembly token is easier for smart contract to use than a batch of assets, in scenarios like batch trade, batch swap or collections exchange.

This standard has AssemblyAsset event which records the exact kinds and amounts of assets the assembly token represents. The wallet can easily display those NFTs to user just by the token id.

## Backwards Compatibility
This proposal combines already available 721 extensions and is backwards compatible with the ERC-721 standard.

## Implementation
```
pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/token/ERC20/IERC20.sol&quot;;
import &quot;@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol&quot;;
import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;
import &quot;@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol&quot;;
import &quot;@openzeppelin/contracts/token/ERC1155/ERC1155.sol&quot;;
import &quot;@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol&quot;;
import &quot;./AssemblyNFTInterface.sol&quot;;

abstract contract AssemblyNFT is ERC721, ERC721Holder, ERC1155Holder, AssemblyNFTInterface{
  using SafeERC20 for IERC20;

  function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC1155Receiver) returns (bool) {
        return ERC721.supportsInterface(interfaceId) || ERC1155Receiver.supportsInterface(interfaceId);
  }

  uint256 nonce;

  /**
  * layout of _addresses:
  *     erc20 addresses | erc721 addresses | erc1155 addresses
  * layout of _numbers:
  *     eth | erc20.length | erc721.length | erc1155.length | erc20 amounts | erc721 ids | erc1155 ids | erc1155 amounts
   */

  function hash(uint256 _salt, address[] memory _addresses, uint256[] memory _numbers) public pure override returns (uint256 tokenId){
      bytes32 signature = keccak256(abi.encodePacked(_salt));
      for(uint256 i=0; i&lt; _addresses.length; i++){
        signature = keccak256(abi.encodePacked(signature, _addresses[i]));
      }
      for(uint256 j=0; j&lt;_numbers.length; j++){
        signature = keccak256(abi.encodePacked(signature, _numbers[j]));
      }
      assembly {
        tokenId := signature
      }
  }

  function mint(address _to, address[] memory _addresses, uint256[] memory _numbers) payable external override returns(uint256 tokenId){
      require(_to != address(0), &quot;can&apos;t mint to address(0)&quot;);
      require(msg.value == _numbers[0], &quot;value not match&quot;);
      require(_addresses.length == _numbers[1] + _numbers[2] + _numbers[3], &quot;2 array length not match&quot;);
      require(_addresses.length == _numbers.length -4 - _numbers[3], &quot;numbers length not match&quot;);
      uint256 pointerA; //points to first erc20 address, if there is any
      uint256 pointerB =4; //points to first erc20 amount, if there is any
      for(uint256 i = 0; i&lt; _numbers[1]; i++){
        require(_numbers[pointerB] &gt; 0, &quot;transfer erc20 0 amount&quot;);
        IERC20(_addresses[pointerA++]).safeTransferFrom(_msgSender(), address(this), _numbers[pointerB++]);
      }
      for(uint256 j = 0; j&lt; _numbers[2]; j++){
        IERC721(_addresses[pointerA++]).safeTransferFrom(_msgSender(), address(this), _numbers[pointerB++]);
      }
      for(uint256 k =0; k&lt; _numbers[3]; k++){
        IERC1155(_addresses[pointerA++]).safeTransferFrom(_msgSender(), address(this), _numbers[pointerB], _numbers[_numbers[3] + pointerB++], &quot;&quot;);
      }
      tokenId = hash(nonce, _addresses, _numbers);
      super._mint(_to, tokenId);
      emit AssemblyAsset(_to, tokenId, nonce, _addresses, _numbers);
      nonce ++;
  }

  function safeMint(address _to, address[] memory _addresses, uint256[] memory _numbers) payable external override returns(uint256 tokenId){
      require(_to != address(0), &quot;can&apos;t mint to address(0)&quot;);
      require(msg.value == _numbers[0], &quot;value not match&quot;);
      require(_addresses.length == _numbers[1] + _numbers[2] + _numbers[3], &quot;2 array length not match&quot;);
      require(_addresses.length == _numbers.length -4 - _numbers[3], &quot;numbers length not match&quot;);
      uint256 pointerA; //points to first erc20 address, if there is any
      uint256 pointerB =4; //points to first erc20 amount, if there is any
      for(uint256 i = 0; i&lt; _numbers[1]; i++){
        require(_numbers[pointerB] &gt; 0, &quot;transfer erc20 0 amount&quot;);
        IERC20 token = IERC20(_addresses[pointerA++]);
        uint256 orgBalance = token.balanceOf(address(this));
        token.safeTransferFrom(_msgSender(), address(this), _numbers[pointerB]);
        _numbers[pointerB++] = token.balanceOf(address(this)) - orgBalance;
      }
      for(uint256 j = 0; j&lt; _numbers[2]; j++){
        IERC721(_addresses[pointerA++]).safeTransferFrom(_msgSender(), address(this), _numbers[pointerB++]);
      }
      for(uint256 k =0; k&lt; _numbers[3]; k++){
        IERC1155(_addresses[pointerA++]).safeTransferFrom(_msgSender(), address(this), _numbers[pointerB], _numbers[_numbers[3] + pointerB++], &quot;&quot;);
      }
      tokenId = hash(nonce, _addresses, _numbers);
      super._mint(_to, tokenId);
      emit AssemblyAsset(_to, tokenId, nonce, _addresses, _numbers);
      nonce ++;
  }

  function burn(address _to, uint256 _tokenId, uint256 _salt, address[] calldata _addresses, uint256[] calldata _numbers) override external {
      require(_msgSender() == ownerOf(_tokenId), &quot;not owned&quot;);
      require(_tokenId == hash(_salt, _addresses, _numbers));
      super._burn(_tokenId);
      payable(_to).transfer(_numbers[0]);
      uint256 pointerA; //points to first erc20 address, if there is any
      uint256 pointerB =4; //points to first erc20 amount, if there is any
      for(uint256 i = 0; i&lt; _numbers[1]; i++){
        require(_numbers[pointerB] &gt; 0, &quot;transfer erc20 0 amount&quot;);
        IERC20(_addresses[pointerA++]).safeTransfer(_to, _numbers[pointerB++]);
      }
      for(uint256 j = 0; j&lt; _numbers[2]; j++){
        IERC721(_addresses[pointerA++]).safeTransferFrom(address(this), _to, _numbers[pointerB++]);
      }
      for(uint256 k =0; k&lt; _numbers[3]; k++){
        IERC1155(_addresses[pointerA++]).safeTransferFrom(address(this), _to, _numbers[pointerB], _numbers[_numbers[3] + pointerB++], &quot;&quot;);
      }
  }

}
```

## Security Considerations
Before using `mint` or `safeMint` functions, user should be aware that some implementations of tokens are pausable. If one of the assets get paused after assembled into one NFT, the `burn` function may not be executed successfully. Platforms using this standard should make support lists or block lists to avoid this situation.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 24 May 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3589</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3589</guid>
      </item>
    
      <item>
        <title>Reject transactions from senders with deployed code</title>
        <category>Standards Track/Core</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/3608</comments>
        
        <description>## Abstract

Ethereum addresses are currently only 160 bits long. This means it is possible to create a collision between a contract account and an Externally Owned Account (EOA) using an estimated `2**80` computing operations, which is feasible now given a large budget (ca. 10 billion USD). The fix in this EIP prevents the worst possible attack, where a safe looking contract (e.g. a token wrapper or an AMM-type contract) is deployed to attract user funds, which can then be spent using the EOA key for the same address. The fix is to never allow to use an address that already has code deployed as an EOA address.

## Motivation

### Generating address collisions

By creating keys for `2**80` EOAs and simulating the deployment of `2**80` contracts from these EOAs (one each), one expects to find about one collision where an EOA has the same address as one contract.

This very simple form of the attack requires the storage of `2**80` addresses, which is a practical barrier: It would require `2.4*10**25` bytes of memory (24 Yottabyte). However, there are cycle finding algorithms that can perform the collision search without requiring large amounts of storage. An estimate for the complexity has been made [here](https://hackmd.io/Vzhp5YJyTT-LhWm_s0JQpA). We estimate that a collision between a contract and an EOA could be found in about one year with an investment of ca. US$10 billion in hardware and electricity.

### Background

There is currently a discussion to move to 256-bit addresses on Ethereum, which would increase collision resistance to a complexity of `2**128` which is currently thought infeasible for the foreseeable future. However, with 160 bit addresses, the collision problem can be effectively solved now, as demonstrated above.

Most attacks that can occur via address collisions are quite impractical: They involve users sending funds to an address before a contract is deployed. This is a very rare application in practice and users can easily circumvent the attack by never sending funds to a contract until it has been safely deployed with enough confirmations.

However, the yellow paper does not explicitly specify how a client should handle the case where a transaction is sent from an account that already has contract code deployed; presumably because this was considered infeasible at the time. The assumption is that most client would allow this transaction in their current state.

This EIP is to specify this behaviour to always forbid such transactions. This fixes most realistic or serious attacks due to address collisions.


## Specification

Any transaction where `tx.sender` has a `CODEHASH != EMPTYCODEHASH` MUST be rejected as invalid, where `EMPTYCODEHASH = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470`.
The invalid transaction MUST be rejected by the client and not be included in a block.
A block containing such a transaction MUST be considered invalid.

## Rationale

We note that it was always expected that a contract account&apos;s behaviour is constrained by the code in that contract -- which means that the account&apos;s funds should not suddenly be spendable by some private key. It was just implicitly assumed in the past that a 160 bit address length is enough to provide collision resistance, and thus that this case could never occur. In that sense, this EIP should be seen as a clarification of protocol behaviour in a previously undefined case rather than an explicit upgrade of consensus rules.

This does not exclude all possible attack vectors, only the most serious one. Further possible attack vectors via address collisions between contracts and EOAs are:
1. An attacker can convince a user to send funds to an account before it is deployed. Some applications require this behaviour (e.g. state channels).
2. A chain reorg can happen after a contract is deployed. If the reorg removes the contract deployment transaction the funds can still be accessed using the private key.
3. A contract can self destruct, with the stated intention that ERC20s (or other tokens) in the contract would be burned. However, they can now be accessed by a key for that address.

All these scenarios are much harder to exploit for an attacker, and likely have much lower yield making the attacks unlikely to be economically viable.

## Backwards Compatibility

It is unlikely that an attack like this has already occurred on the Ethereum mainnet, or we would very likely have heard of it. It is inconceivable that someone would use this as a &quot;feature&quot; to make a contract an EOA at the same time, when they could simply do this by adding some methods to the contract instead of spending billions on building hardware to find hash collisions.

Private networks may have deployed contracts which also work as EOAs at genesis and should check that this upgrade does not impact their workflows.

Clients might choose to disable this rule for RPC calls like `eth_call` and `eth_estimateGas` as some Multi-Sig contracts use these calls to create transactions as if they originated from the multisig contract itself. 

## Test Cases

Given a genesis allocation of  
```
Address: 0x71562b71999873DB5b286dF957af199Ec94617F7
Balance: 1000000000000000000 // 1 ether
Nonce:   0,
Code:    0xB0B0FACE&quot;,
```
Every transaction sent by the private key corresponding to `0x715656...` (
`b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291`) should be rejected.
These transaction must be rejected and not included in a block.

## Reference Implementation

The following check must be added to the state transition checks after checking that the nonce of the sender is correct.
The sender is the address recovered from the signature of the transaction.
```
// Make sure the sender is an EOA
Set ch to the CodeHash of the sender account
if ch is not equal to EmptyCodeHash then
	return ErrSenderNoEOA
end if
```

A diff to implement EIP-3607 in go-ethereum can be found [here](/EIPs/assets/eip-3607/geth.diff)

## Security Considerations

This EIP is a strict security upgrade: It simply makes some transactions that were formerly valid now invalid. There is no legitimate use for such transactions, so there should be no security downsides.

This EIP can be implemented as a soft fork because the new validity rules are a strict superset of the previous validity rules.


## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 10 Jun 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3607</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3607</guid>
      </item>
    
      <item>
        <title>T-REX - Token for Regulated EXchanges</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3643-proposition-of-the-t-rex-token-standard-for-securities/6844</comments>
        
        <description>## Abstract

The T-REX token is an institutional grade security token standard. This standard provides a library of interfaces for the management and compliant transfer of security tokens, using an automated onchain validator system leveraging onchain identities for eligibility checks.

The standard defines several interfaces that are described hereunder:

- Token 
- Identity Registry
- Identity Registry Storage
- Compliance 
- Trusted Issuers Registry 
- Claim Topics Registry

## Motivation

The advent of blockchain technology has brought about a new era of efficiency, accessibility, and liquidity in the world of asset transfer. This is particularly evident in the realm of cryptocurrencies, where users can transfer token ownership peer-to-peer without intermediaries. However, when it comes to tokenized securities or security tokens, the situation is more complex due to the need for compliance with securities laws. These tokens cannot be permissionless like utility tokens; they must be permissioned to track ownership and ensure that only eligible investors can hold tokens.

The existing Ethereum protocol, while powerful and versatile, does not fully address the unique challenges posed by security tokens. There is a need for a standard that supports compliant issuance and management of permissioned tokens, suitable for representing a wide range of asset classes, including small businesses and real estate.

The proposed [ERC-3643](/EIPs/EIPS/eip-3643) standard is motivated by this need. It aims to provide a comprehensive framework for managing the lifecycle of security tokens, from issuance to transfers between eligible investors, while enforcing compliance rules at every stage. The standard also supports additional features such as token pausing and freezing, which can be used to manage the token in response to regulatory requirements or changes in the status of the token or its holders.

Moreover, the standard is designed to work in conjunction with an on-chain Identity system, allowing for the validation of the identities and credentials of investors through signed attestations issued by trusted claim issuers. This ensures compliance with legal and regulatory requirements for the trading of security tokens.

In summary, the motivation behind the proposed standard is to bring the benefits of blockchain technology to the world of securities, while ensuring compliance with existing securities laws. It aims to provide a robust, flexible, and efficient framework for the issuance and management of security tokens, thereby accelerating the evolution of capital markets.

## Specification

The proposed standard has the following requirements:

- **MUST** be [ERC-20](/EIPs/EIPS/eip-20) compatible.
- **MUST** be used in combination with an onchain Identity system
- **MUST** be able to apply any rule of compliance that is required by the regulator or by the token issuer (about the factors of eligibility of an identity or about the rules of the token itself)
- **MUST** have a standard interface to pre-check if a transfer is going to pass or fail before sending it to the blockchain
- **MUST** have a recovery system in case an investor loses access to his private key
- **MUST** be able to freeze tokens on the wallet of investors if needed, partially or totally
- **MUST** have the possibility to pause the token
- **MUST** be able to mint and burn tokens
- **MUST** define an Agent role and an Owner (token issuer) role
- **MUST** be able to force transfers from an Agent wallet
- **MUST** be able to issue transactions in batch (to save gas and to have all the transactions performed in the same block)

While this standard is backwards compatible with ERC-20 and all ERC-20 functions can be called on an ERC-3643 token, the implementation of these functions differs due to the permissioned nature of ERC-3643. Each token transfer under this standard involves a compliance check to validate the transfer and the eligibility of the stakeholder’s identities.

### Agent Role Interface

The standard defines an Agent role, which is crucial for managing access to various functions of the smart contracts. The interface for the Agent role is as follows:

```solidity
interface IAgentRole {

  // events
  event AgentAdded(address indexed _agent);
  event AgentRemoved(address indexed _agent);
  
  // functions
  // setters
  function addAgent(address _agent) external;
  function removeAgent(address _agent) external;

  // getters
  function isAgent(address _agent) external view returns (bool);
}
 ```

The `IAgentRole` interface allows for the addition and removal of agents, as well as checking if an address is an agent. In this standard, it is the owner role, as defined by [ERC-173](/EIPs/EIPS/eip-173), that has the responsibility of appointing and removing agents. Any contract that fulfills the role of a Token contract or an Identity Registry within the context of this standard must be compatible with the `IAgentRole` interface.

### Main functions

#### Transfer

To be able to perform a transfer on T-REX you need to fulfill several conditions :

- The sender **MUST** hold enough free balance (total balance - frozen tokens, if any)
- The receiver **MUST** be whitelisted on the Identity Registry and verified (hold the necessary claims on his onchain Identity)
- The sender&apos;s wallet **MUST NOT** be frozen
- The receiver&apos;s wallet **MUST NOT** be frozen
- The token **MUST NOT** be paused
- The transfer **MUST** respect all the rules of compliance defined in the Compliance smart contract (canTransfer needs to return TRUE)

Here is an example of `transfer` function implementation :

```solidity
function transfer(address _to, uint256 _amount) public override whenNotPaused returns (bool) {
        require(!_frozen[_to] &amp;&amp; !_frozen[msg.sender], &quot;ERC-3643: Frozen wallet&quot;);
        require(_amount &lt;= balanceOf(msg.sender) - (_frozenTokens[msg.sender]), &quot;ERC-3643: Insufficient Balance&quot;);
        require( _tokenIdentityRegistry.isVerified(to), &quot;ERC-3643: Invalid identity&quot; ); 
        require( _tokenCompliance.canTransfer(from, to, amount), &quot;ERC-3643: Compliance failure&quot; );
        _transfer(msg.sender, _to, _amount);
        _tokenCompliance.transferred(msg.sender, _to, _amount);
        return true;
    }
 ```

The `transferFrom` function works the same way while the `mint` function and the `forcedTransfer` function only require the receiver to be whitelisted and verified on the Identity Registry (they bypass the compliance rules). The `burn` function bypasses all checks on eligibility.

#### isVerified

The `isVerified` function is called from within the transfer functions `transfer`, `transferFrom`, `mint` and 
`forcedTransfer` to instruct the `Identity Registry` to check if the receiver is a valid investor, i.e. if his 
wallet address is in the `Identity Registry` of the token, and if the `Identity`contract linked to his wallet 
contains the claims (see [Claim Holder](/EIPs/assets/eip-3643/ONCHAINID/IERC735.sol)) required in the `Claim Topics Registry` and 
if these claims are signed by an authorized Claim Issuer as required in the `Trusted Issuers Registry`.
If all the requirements are fulfilled, the `isVerified` function returns `TRUE`, otherwise it returns `FALSE`. An 
implementation of this function can be found on the T-REX repository of Tokeny.

#### canTransfer

The `canTransfer` function is also called from within transfer functions. This function checks if the transfer is compliant with global compliance rules applied to the token, in opposition with `isVerified` that only checks the eligibility of an investor to hold and receive tokens, the `canTransfer` function is looking at global compliance rules, e.g. check if the transfer is compliant in the case there is a fixed maximum number of token holders to respect (can be a limited number of holders per country as well), check if the transfer respects rules setting a maximum amount of tokens per investor, ...
If all the requirements are fulfilled, the `canTransfer` function will return `TRUE` otherwise it will return 
`FALSE` and the transfer will not be allowed to happen. An implementation of this function can be found on the T-REX 
repository of Tokeny.

#### Other functions

Description of other functions of the ERC-3643 can be found in the `interfaces` folder. An implementation of the 
ERC-3643 suite of smart contracts can be found on the T-REX repository of Tokeny.

### Token interface

ERC-3643 permissioned tokens build upon the standard ERC-20 structure, but with additional functions to ensure compliance in the transactions of the security tokens. The functions `transfer` and `transferFrom` are implemented in a conditional way, allowing them to proceed with a transfer only if the transaction is valid. The permissioned tokens are allowed to be transferred only to validated counterparties, in order to avoid tokens being held in wallets/Identity contracts of ineligible/unauthorized investors. The ERC-3643 standard also supports the recovery of security tokens in case an investor loses access to their wallet private key. A history of recovered tokens is maintained on the blockchain for transparency reasons.

ERC-3643 tokens implement a range of additional functions to enable the owner or their appointed agents to manage supply, transfer rules, lockups, and any other requirements in the management of a security. The standard relies on ERC-173 to define contract ownership, with the owner having the responsibility of appointing agents. Any contract that fulfills the role of a Token contract within the context of this standard must be compatible with the `IAgentRole` interface.

A detailed description of the functions can be found in the [interfaces folder](/EIPs/assets/eip-3643/interfaces/IERC3643.sol).

```solidity
interface IERC3643 is IERC20 {

   // events
    event UpdatedTokenInformation(string _newName, string _newSymbol, uint8 _newDecimals, string _newVersion, address _newOnchainID);
    event IdentityRegistryAdded(address indexed _identityRegistry);
    event ComplianceAdded(address indexed _compliance);
    event RecoverySuccess(address _lostWallet, address _newWallet, address _investorOnchainID);
    event AddressFrozen(address indexed _userAddress, bool indexed _isFrozen, address indexed _owner);
    event TokensFrozen(address indexed _userAddress, uint256 _amount);
    event TokensUnfrozen(address indexed _userAddress, uint256 _amount);
    event Paused(address _userAddress);
    event Unpaused(address _userAddress);


    // functions
    // getters
    function onchainID() external view returns (address);
    function version() external view returns (string memory);
    function identityRegistry() external view returns (IIdentityRegistry);
    function compliance() external view returns (ICompliance);
    function paused() external view returns (bool);
    function isFrozen(address _userAddress) external view returns (bool);
    function getFrozenTokens(address _userAddress) external view returns (uint256);

    // setters
    function setName(string calldata _name) external;
    function setSymbol(string calldata _symbol) external;
    function setOnchainID(address _onchainID) external;
    function pause() external;
    function unpause() external;
    function setAddressFrozen(address _userAddress, bool _freeze) external;
    function freezePartialTokens(address _userAddress, uint256 _amount) external;
    function unfreezePartialTokens(address _userAddress, uint256 _amount) external;
    function setIdentityRegistry(address _identityRegistry) external;
    function setCompliance(address _compliance) external;

    // transfer actions
    function forcedTransfer(address _from, address _to, uint256 _amount) external returns (bool);
    function mint(address _to, uint256 _amount) external;
    function burn(address _userAddress, uint256 _amount) external;
    function recoveryAddress(address _lostWallet, address _newWallet, address _investorOnchainID) external returns (bool);

    // batch functions
    function batchTransfer(address[] calldata _toList, uint256[] calldata _amounts) external;
    function batchForcedTransfer(address[] calldata _fromList, address[] calldata _toList, uint256[] calldata _amounts) external;
    function batchMint(address[] calldata _toList, uint256[] calldata _amounts) external;
    function batchBurn(address[] calldata _userAddresses, uint256[] calldata _amounts) external;
    function batchSetAddressFrozen(address[] calldata _userAddresses, bool[] calldata _freeze) external;
    function batchFreezePartialTokens(address[] calldata _userAddresses, uint256[] calldata _amounts) external;
    function batchUnfreezePartialTokens(address[] calldata _userAddresses, uint256[] calldata _amounts) external;
}

```

### Identity Registry Interface

The Identity Registry is linked to storage that contains a dynamic whitelist of identities. It establishes the link between a wallet address, an Identity smart contract, and a country code corresponding to the investor&apos;s country of residence. This country code is set in accordance with the ISO-3166 standard. The Identity Registry also includes a function called `isVerified()`, which returns a status based on the validity of claims (as per the security token requirements) in the user’s Identity contract.

The standard relies on ERC-173 to define contract ownership, with the owner having the responsibility of appointing agents. Any contract that fulfills the role of an Identity Registry within the context of this standard must be compatible with the `IAgentRole` interface. The Identity Registry is managed by the agent wallet(s), meaning only the agent(s) can add or remove identities in the registry. Note that the agent role on the Identity Registry is set by the owner, therefore the owner could set themselves as the agent if they want to maintain full control. There is a specific identity registry for each security token.

A detailed description of the functions can be found in the [interfaces folder](/EIPs/assets/eip-3643/interfaces/IIdentityRegistry.sol).

Note that [`IClaimIssuer`](/EIPs/assets/eip-3643/ONCHAINID/IClaimIssuer.sol) and [`IIdentity`](/EIPs/assets/eip-3643/ONCHAINID/IIdentity.sol) are needed in this interface as they are required for the Identity eligibility checks.

```solidity
interface IIdentityRegistry {


    // events
    event ClaimTopicsRegistrySet(address indexed claimTopicsRegistry);
    event IdentityStorageSet(address indexed identityStorage);
    event TrustedIssuersRegistrySet(address indexed trustedIssuersRegistry);
    event IdentityRegistered(address indexed investorAddress, IIdentity indexed identity);
    event IdentityRemoved(address indexed investorAddress, IIdentity indexed identity);
    event IdentityUpdated(IIdentity indexed oldIdentity, IIdentity indexed newIdentity);
    event CountryUpdated(address indexed investorAddress, uint16 indexed country);


    // functions
    // identity registry getters
    function identityStorage() external view returns (IIdentityRegistryStorage);
    function issuersRegistry() external view returns (ITrustedIssuersRegistry);
    function topicsRegistry() external view returns (IClaimTopicsRegistry);

    //identity registry setters
    function setIdentityRegistryStorage(address _identityRegistryStorage) external;
    function setClaimTopicsRegistry(address _claimTopicsRegistry) external;
    function setTrustedIssuersRegistry(address _trustedIssuersRegistry) external;

    // registry actions
    function registerIdentity(address _userAddress, IIdentity _identity, uint16 _country) external;
    function deleteIdentity(address _userAddress) external;
    function updateCountry(address _userAddress, uint16 _country) external;
    function updateIdentity(address _userAddress, IIdentity _identity) external;
    function batchRegisterIdentity(address[] calldata _userAddresses, IIdentity[] calldata _identities, uint16[] calldata _countries) external;

    // registry consultation
    function contains(address _userAddress) external view returns (bool);
    function isVerified(address _userAddress) external view returns (bool);
    function identity(address _userAddress) external view returns (IIdentity);
    function investorCountry(address _userAddress) external view returns (uint16);
}
```

### Identity Registry Storage Interface

The Identity Registry Storage stores the identity addresses of all the authorized investors in the security token(s) linked to the storage contract. These are all identities of investors who have been authorized to hold the token(s) after having gone through the appropriate KYC and eligibility checks. The Identity Registry Storage can be bound to one or several Identity Registry contract(s). The goal of the Identity Registry storage is to separate the Identity Registry functions and specifications from its storage. This way, it is possible to keep one single Identity Registry contract per token, with its own Trusted Issuers Registry and Claim Topics Registry, but with a shared whitelist of investors used by the `isVerifed()` function implemented in the Identity Registries to check the eligibility of the receiver in a transfer transaction.

The standard relies on ERC-173 to define contract ownership, with the owner having the responsibility of appointing agents(in this case through the `bindIdentityRegistry` function). Any contract that fulfills the role of an Identity Registry Storage within the context of this standard must be compatible with the `IAgentRole` interface. The Identity Registry Storage is managed by the agent addresses (i.e. the bound Identity Registries), meaning only the agent(s) can add or remove identities in the registry. Note that the agent role on the Identity Registry Storage is set by the owner, therefore the owner could set themselves as the agent if they want to modify the storage manually. Otherwise it is the bound Identity Registries that are using the agent role to write in the Identity Registry Storage.

A detailed description of the functions can be found in the [interfaces folder](/EIPs/assets/eip-3643/interfaces/IIdentityRegistryStorage.sol).

```solidity
interface IIdentityRegistryStorage {

    //events
    event IdentityStored(address indexed investorAddress, IIdentity indexed identity);
    event IdentityUnstored(address indexed investorAddress, IIdentity indexed identity);
    event IdentityModified(IIdentity indexed oldIdentity, IIdentity indexed newIdentity);
    event CountryModified(address indexed investorAddress, uint16 indexed country);
    event IdentityRegistryBound(address indexed identityRegistry);
    event IdentityRegistryUnbound(address indexed identityRegistry);

    //functions
    // storage related functions
    function storedIdentity(address _userAddress) external view returns (IIdentity);
    function storedInvestorCountry(address _userAddress) external view returns (uint16);
    function addIdentityToStorage(address _userAddress, IIdentity _identity, uint16 _country) external;
    function removeIdentityFromStorage(address _userAddress) external;
    function modifyStoredInvestorCountry(address _userAddress, uint16 _country) external;
    function modifyStoredIdentity(address _userAddress, IIdentity _identity) external;

    // role setter
    function bindIdentityRegistry(address _identityRegistry) external;
    function unbindIdentityRegistry(address _identityRegistry) external;

    // getter for bound IdentityRegistry role
    function linkedIdentityRegistries() external view returns (address[] memory);
}
```

### Compliance Interface

The Compliance contract is used to set the rules of the offering itself and ensures these rules are respected during the whole lifecycle of the token. For example, the Compliance contract will define the maximum amount of investors per country, the maximum amount of tokens per investor, and the accepted countries for the circulation of the token (using the country code corresponding to each investor in the Identity Registry). The Compliance smart contract can be either “tailor-made”, following the legal requirements of the token issuer, or can be deployed under a generic modular form, which can then add and remove external compliance `Modules` to fit the legal requirements of the token in the same way as a custom &quot;tailor-made&quot; contract would.

This contract is triggered at every transaction by the Token and returns `TRUE` if the transaction is compliant with the rules of the offering and `FALSE` otherwise.

The standard relies on ERC-173 to define contract ownership, with the owner having the responsibility of setting the Compliance parameters and binding the Compliance to a Token contract.

A detailed description of the functions can be found in the [interfaces folder](/EIPs/assets/eip-3643/interfaces/ICompliance.sol).

```solidity
interface ICompliance {

    // events
    event TokenBound(address _token);
    event TokenUnbound(address _token);

    // functions
    // initialization of the compliance contract
    function bindToken(address _token) external;
    function unbindToken(address _token) external;

    // check the parameters of the compliance contract
    function isTokenBound(address _token) external view returns (bool);
    function getTokenBound() external view returns (address);

    // compliance check and state update
    function canTransfer(address _from, address _to, uint256 _amount) external view returns (bool);
    function transferred(address _from, address _to, uint256 _amount) external;
    function created(address _to, uint256 _amount) external;
    function destroyed(address _from, uint256 _amount) external;
}
```

### Trusted Issuer&apos;s Registry Interface

The Trusted Issuer&apos;s Registry stores the contract addresses ([IClaimIssuer](/EIPs/assets/eip-3643/ONCHAINID/IClaimIssuer.sol)) of all the trusted claim issuers for a specific security token. The Identity contract ([IIdentity](/EIPs/assets/eip-3643/ONCHAINID/IIdentity.sol)) of token owners (the investors) must have claims signed by the claim issuers stored in this smart contract in order to be able to hold the token.

The standard relies on ERC-173 to define contract ownership, with the owner having the responsibility of managing this registry as per their requirements. This includes the ability to add, remove, and update the list of Trusted Issuers.

A detailed description of the functions can be found in the [interfaces folder](/EIPs/assets/eip-3643/interfaces/ITrustedIssuersRegistry.sol).

```solidity
interface ITrustedIssuersRegistry {

    // events
    event TrustedIssuerAdded(IClaimIssuer indexed trustedIssuer, uint[] claimTopics);
    event TrustedIssuerRemoved(IClaimIssuer indexed trustedIssuer);
    event ClaimTopicsUpdated(IClaimIssuer indexed trustedIssuer, uint[] claimTopics);

    // functions
    // setters
    function addTrustedIssuer(IClaimIssuer _trustedIssuer, uint[] calldata _claimTopics) external;
    function removeTrustedIssuer(IClaimIssuer _trustedIssuer) external;
    function updateIssuerClaimTopics(IClaimIssuer _trustedIssuer, uint[] calldata _claimTopics) external;

    // getters
    function getTrustedIssuers() external view returns (IClaimIssuer[] memory);
    function isTrustedIssuer(address _issuer) external view returns(bool);
    function getTrustedIssuerClaimTopics(IClaimIssuer _trustedIssuer) external view returns(uint[] memory);
    function getTrustedIssuersForClaimTopic(uint256 claimTopic) external view returns (IClaimIssuer[] memory);
    function hasClaimTopic(address _issuer, uint _claimTopic) external view returns(bool);
}
```

### Claim Topics Registry Interface

The Claim Topics Registry stores all the trusted claim topics for the security token. The Identity contract ([IIdentity](/EIPs/assets/eip-3643/ONCHAINID/IIdentity.sol)) of token owners must contain claims of the claim topics stored in this smart contract.

The standard relies on ERC-173 to define contract ownership, with the owner having the responsibility of managing this registry as per their requirements. This includes the ability to add and remove required Claim Topics.

A detailed description of the functions can be found in the [interfaces folder](/EIPs/assets/eip-3643/interfaces/IClaimTopicsRegistry.sol).

```solidity
interface IClaimTopicsRegistry {

    // events
    event ClaimTopicAdded(uint256 indexed claimTopic);
    event ClaimTopicRemoved(uint256 indexed claimTopic);

    // functions
    // setters
    function addClaimTopic(uint256 _claimTopic) external;
    function removeClaimTopic(uint256 _claimTopic) external;

    // getter
    function getClaimTopics() external view returns (uint256[] memory);
}
```

## Rationale

### Transfer Restrictions

Transfers of securities can fail for a variety of reasons. This is in direct contrast to utility tokens, which generally only require the sender to have a sufficient balance. These conditions can be related to the status of an investor’s wallet, the identity of the sender and receiver of the securities (i.e., whether they have been through a KYC process, whether they are accredited or an affiliate of the issuer) or for reasons unrelated to the specific transfer but instead set at the token level (i.e., the token contract enforces a maximum number of investors or a cap on the percentage held by any single investor). For ERC-20 tokens, the `balanceOf` and `allowance` functions provide a way to check that a transfer is likely to succeed before executing the transfer, which can be executed both on-chain and off-chain. For tokens representing securities, the T-REX standard introduces a function `canTransfer` which provides a more general-purpose way to achieve this. I.e., when the reasons for failure are related to the compliance rules of the token and a function `isVerified` which allows checking the eligibility status of the identity of the investor. Transfers can also fail if the address of the sender and/or receiver is frozen, or if the free balance of the sender (total balance - frozen tokens) is lower than the amount to transfer. Ultimately, the transfer could be blocked if the token is `paused`.

### Identity Management

Security and compliance of transfers are enforced through the management of on-chain identities. These include:

- Identity contract: A unique identifier for each investor, which is used to manage their identity and claims.
- Claim: Signed attestations issued by a trusted claim issuer that confirm certain attributes or qualifications of the token holders, such as their identity, location, investor status, or KYC/AML clearance.
- Identity Storage/Registry: A storage system for all Identity contracts and their associated wallets, which is used to 
  verify the eligibility of investors during transfers.

### Token Lifecycle Management

The T-REX standard provides a comprehensive framework for managing the lifecycle of security tokens. This includes the issuance of tokens, transfers between eligible investors, and the enforcement of compliance rules at every stage of the token&apos;s lifecycle. The standard also supports additional features such as token pausing and freezing, which can be used to manage the token in response to regulatory requirements or changes in the status of the token or its holders.

### Additional Compliance Rules

The T-REX standard supports the implementation of additional compliance rules through modular compliance. These modules can be used to enforce a wide range of rules and restrictions, such as caps on the number of investors or the percentage of tokens held by a single investor, restrictions on transfers between certain types of investors, and more. This flexibility allows issuers to tailor the compliance rules of their tokens to their specific needs and regulatory environment.

### Inclusion of Agent-Related Functions

The inclusion of Agent-scoped functions within the standard interfaces is deliberate. The intent is to accommodate secure and adaptable token management practices that surpass the capabilities of EOA management. We envision scenarios where the agent role is fulfilled by automated systems or smart contracts, capable of programmatically executing operational functions like minting, burning, and freezing in response to specified criteria or regulatory triggers. For example, a smart contract might automatically burn tokens to align with redemption requests in an open-ended fund, or freeze tokens associated with wallets engaged in fraudulent activities.

Consequently, these functions are standardized to provide a uniform interface for various automated systems interacting with different ERC-3643 tokens, allowing for standardized tooling and interfaces that work across the entire ecosystem. This approach ensures that ERC-3643 remains flexible, future-proof, and capable of supporting a wide array of operational models.

## Backwards Compatibility

T-REX tokens should be backwards compatible with ERC-20 and ERC-173
and should be able to interact with a [Claim Holder contract](/EIPs/assets/eip-3643/ONCHAINID/IERC735.sol) to validate 
the claims linked to an [Identity contract](/EIPs/assets/eip-3643/ONCHAINID/IIdentity.sol).


## Security Considerations

This specification has been audited by Kapersky and Hacken, and no notable security considerations were found. 
While the audits were primarily focused on the specific implementation by Tokeny, they also challenged and validated the core principles of the T-REX standard. The auditing teams approval of these principles provides assurance that the standard itself is robust and does not present any significant security concerns. 

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 09 Jul 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3643</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3643</guid>
      </item>
    
      <item>
        <title>Warm COINBASE</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3651-warm-coinbase/6640</comments>
        
        <description>## Abstract

The `COINBASE` address shall be warm at the start of transaction execution, in accordance with the actual cost of reading that account.

## Motivation

Direct `COINBASE` payments are becoming increasingly popular because they allow conditional payments, which provide benefits such as implicit cancellation of transactions that would revert.
But accessing `COINBASE` is overpriced; the address is initially cold under the access list framework introduced in [EIP-2929](/EIPs/EIPS/eip-2929).
This gas cost mismatch can incentivize alternative payments besides ETH, such as [ERC-20](/EIPs/EIPS/eip-20), but ETH should be the primary means of paying for transactions on Ethereum.

## Specification

At the start of transaction execution, `accessed_addresses` shall be initialized to also include the address returned by `COINBASE` (`0x41`).

## Rationale

The addresses currently initialized warm are the addresses that should already be loaded at the start of transaction validation.
The `ORIGIN` address is always loaded to check its balance against the gas limit and the gas price.
The `tx.to` address is always loaded to begin execution.
The `COINBASE` address should also be always be loaded because it receives the block reward and the transaction fees.

## Backwards Compatibility

There are no known backward compatibility issues presented by this change.

## Security Considerations

There are no known security considerations introduced by this change.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 12 Jul 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3651</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3651</guid>
      </item>
    
      <item>
        <title>CCIP Read—Secure offchain data retrieval</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/durin-secure-offchain-data-retrieval/6728</comments>
        
        <description>## Abstract
Contracts wishing to support lookup of data from external sources may, instead of returning the data directly, revert using `OffchainLookup(address sender, string[] urls, bytes callData, bytes4 callbackFunction, bytes extraData)`. Clients supporting this specification then make an RPC call to a URL from `urls`, supplying `callData`, and getting back an opaque byte string `response`. Finally, clients call the function specified by `callbackFunction` on the contract, providing `response` and `extraData`. The contract can then decode and verify the returned data using an implementation-specific method.

This mechanism allows for offchain lookups of data in a way that is transparent to clients, and allows contract authors to implement whatever validation is necessary; in many cases this can be provided without any additional trust assumptions over and above those required if data is stored onchain.

## Motivation
Minimising storage and transaction costs on Ethereum has driven contract authors to adopt a variety of techniques for moving data offchain, including hashing, recursive hashing (eg Merkle Trees/Tries) and L2 solutions. While each solution has unique constraints and parameters, they all share in common the fact that enough information is stored onchain to validate the externally stored data when required.

Thus far, applications have tended to devise bespoke solutions rather than trying to define a universal standard. This is practical - although inefficient - when a single offchain data storage solution suffices, but rapidly becomes impractical in a system where multiple end-users may wish to make use of different data storage and availability solutions based on what suits their needs.

By defining a common specification allowing smart contract to fetch data from offchain, we facilitate writing clients that are entirely agnostic to the storage solution being used, which enables new applications that can operate without knowing about the underlying storage details of the contracts they interact with.

Examples of this include:
 - Interacting with &apos;airdrop&apos; contracts that store a list of recipients offchain in a merkle trie.
 - Viewing token information for tokens stored on an L2 solution as if they were native L1 tokens.
 - Allowing delegation of data such as ENS domains to various L2 solutions, without requiring clients to support each solution individually.
 - Allowing contracts to proactively request external data to complete a call, without requiring the caller to be aware of the details of that data.

## Specification
### Overview
Answering a query via CCIP read takes place in three steps:

 1. Querying the contract.
 2. Querying the gateway using the URL provided in (1).
 3. Querying or sending a transaction to the contract using the data from (1) and (2).

In step 1, a standard blockchain call operation is made to the contract. The contract reverts with an error that specifies the data to complete the call can be found offchain, and provides the url to a service that can provide the answer, along with additional contextual information required for the call in step (3).

In step 2, the client calls the gateway service with the `callData` from the revert message in step (1). The gateway responds with an answer `response`, whose content is opaque to the client.

In step 3, the client calls the original contract, supplying the `response` from step (2) and the `extraData` returned by the contract in step (1). The contract decodes the provided data and uses it to validate the response and act on it - by returning information to the client or by making changes in a transaction. The contract could also revert with a new error to initiate another lookup, in which case the protocol starts again at step 1.

```
┌──────┐                                          ┌────────┐ ┌─────────────┐
│Client│                                          │Contract│ │Gateway @ url│
└──┬───┘                                          └───┬────┘ └──────┬──────┘
   │                                                  │             │
   │ somefunc(...)                                    │             │
   ├─────────────────────────────────────────────────►│             │
   │                                                  │             │
   │ revert OffchainLookup(sender, urls, callData,    │             │
   │                     callbackFunction, extraData) │             │
   │◄─────────────────────────────────────────────────┤             │
   │                                                  │             │
   │ HTTP request (sender, callData)                  │             │
   ├──────────────────────────────────────────────────┼────────────►│
   │                                                  │             │
   │ Response (result)                                │             │
   │◄─────────────────────────────────────────────────┼─────────────┤
   │                                                  │             │
   │ callbackFunction(result, extraData)              │             │
   ├─────────────────────────────────────────────────►│             │
   │                                                  │             │
   │ answer                                           │             │
   │◄─────────────────────────────────────────────────┤             │
   │                                                  │             │
```

### Contract interface

A CCIP read enabled contract MUST revert with the following error whenever a function that requires offchain data is called:

```solidity
error OffchainLookup(address sender, string[] urls, bytes callData, bytes4 callbackFunction, bytes extraData)
```

`sender` is the address of the contract that raised the error, and is used to determine if the error was thrown by the contract the client called, or &apos;bubbled up&apos; from a nested call.

`urls` specifies a list of URL templates to services (known as gateways) that implement the CCIP read protocol and can formulate an answer to the query. `urls` can be the empty list `[]`, in which case the client MUST specify the URL template. The order in which URLs are tried is up to the client, but contracts SHOULD return them in order of priority, with the most important entry first.

Each URL may include two substitution parameters, `{sender}` and `{data}`. Before a call is made to the URL, `sender` is replaced with the lowercase 0x-prefixed hexadecimal formatted `sender` parameter, and `data` is replaced by the 0x-prefixed hexadecimal formatted `callData` parameter.

`callData` specifies the data to call the gateway with. This value is opaque to the client. Typically this will be ABI-encoded, but this is an implementation detail that contracts and gateways can standardise on as desired.

`callbackFunction` is the 4-byte function selector for a function on the original contract to which a callback should be sent.

`extraData` is additional data that is required by the callback, and MUST be retained by the client and provided unmodified to the callback function. This value is opaque to the client.

The contract MUST also implement a callback method for decoding and validating the data returned by the gateway. The name of this method is implementation-specific, but it MUST have the signature `(bytes response, bytes extraData)`, and MUST have the same return type as the function that reverted with `OffchainLookup`.

If the client successfully calls the gateway, the callback function specified in the `OffchainLookup` error will be invoked by the client, with `response` set to the value returned by the gateway, and `extraData` set to the value returned in the contract&apos;s `OffchainLookup` error. The contract MAY initiate another CCIP read lookup in this callback, though authors should bear in mind that the limits on number of recursive invocations will vary from client to client.

In a call context (as opposed to a transaction), the return data from this call will be returned to the user as if it was returned by the function that was originally invoked.

#### Example

Suppose a contract has the following method:

```solidity
function balanceOf(address addr) public view returns(uint balance);
```

Data for these queries is stored offchain in some kind of hashed data structure, the details of which are not important for this example. The contract author wants the gateway to fetch the proof information for this query and call the following function with it:

```solidity
function balanceOfWithProof(bytes calldata response, bytes calldata extraData) public view returns(uint balance);
```

One example of a valid implementation of `balanceOf` would thus be:

```solidity
function balanceOf(address addr) public view returns(uint balance) {
    revert OffchainLookup(
        address(this),
        [url],
        abi.encodeWithSelector(Gateway.getSignedBalance.selector, addr),
        ContractName.balanceOfWithProof.selector,
        abi.encode(addr)
    );
}
```

Note that in this example the contract is returning `addr` in both `callData` and `extraData`, because it is required both by the gateway (in order to look up the data) and the callback function (in order to verify it). The contract cannot simply pass it to the gateway and rely on it being returned in the response, as this would give the gateway an opportunity to respond with an answer to a different query than the one that was initially issued.

#### Recursive calls in CCIP-aware contracts

When a CCIP-aware contract wishes to make a call to another contract, and the possibility exists that the callee may implement CCIP read, the calling contract MUST catch all `OffchainLookup` errors thrown by the callee, and revert with a different error if the `sender` field of the error does not match the callee address.

The contract MAY choose to replace all `OffchainLookup` errors with a different error. Doing so avoids the complexity of implementing support for nested CCIP read calls, but renders them impossible.

Where the possibility exists that a callee implements CCIP read, a CCIP-aware contract MUST NOT allow the default solidity behaviour of bubbling up reverts from nested calls. This is to prevent the following situation:

 1. Contract A calls non-CCIP-aware contract B.
 2. Contract B calls back to A.
 3. In the nested call, A reverts with `OffchainLookup`.
 4. Contract B does not understand CCIP read and propagates the `OffchainLookup` to its caller.
 5. Contract A also propagates the `OffchainLookup` to its caller.

The result of this sequence of operations would be an `OffchainLookup` that looks valid to the client, as the `sender` field matches the address of the contract that was called, but does not execute correctly, as it only completes a nested invocation.

#### Example

The code below demonstrates one way that a contract may support nested CCIP read invocations. For simplicity this is shown using Solidity&apos;s try/catch syntax, although as of this writing it does not yet support catching custom errors.

```solidity
contract NestedLookup {
    error InvalidOperation();
    error OffchainLookup(address sender, string[] urls, bytes callData, bytes4 callbackFunction, bytes extraData);

    function a(bytes calldata data) external view returns(bytes memory) {
        try target.b(data) returns (bytes memory ret) {
            return ret;
        } catch OffchainLookup(address sender, string[] urls, bytes callData, bytes4 callbackFunction, bytes extraData) {
            if(sender != address(target)) {
                revert InvalidOperation();
            }
            revert OffchainLookup(
                address(this),
                urls,
                callData,
                NestedLookup.aCallback.selector,
                abi.encode(address(target), callbackFunction, extraData)
            );
        }
    }

    function aCallback(bytes calldata response, bytes calldata extraData) external view returns(bytes memory) {
        (address inner, bytes4 innerCallbackFunction, bytes memory innerExtraData) = abi.decode(extraData, (address, bytes4, bytes));
        return abi.decode(inner.call(abi.encodeWithSelector(innerCallbackFunction, response, innerExtraData)), (bytes));
    }
}
```

### Gateway Interface
The URLs returned by a contract may be of any schema, but this specification only defines how clients should handle HTTPS URLs.

Given a URL template returned in an `OffchainLookup`, the URL to query is composed by replacing  `sender` with the lowercase 0x-prefixed hexadecimal formatted `sender` parameter, and replacing `data` with the 0x-prefixed hexadecimal formatted `callData` parameter.

For example, if a contract returns the following data in an `OffchainLookup`:

```
urls = [&quot;https://example.com/gateway/{sender}/{data}.json&quot;]
sender = &quot;0xaabbccddeeaabbccddeeaabbccddeeaabbccddee&quot;
callData = &quot;0x00112233&quot;
```

The request URL to query is `https://example.com/gateway/0xaabbccddeeaabbccddeeaabbccddeeaabbccddee/0x00112233.json`.

If the URL template contains the `{data}` substitution parameter, the client MUST send a GET request after replacing the substitution parameters as described above.

If the URL template does not contain the `{data}` substitution parameter, the client MUST send a POST request after replacing the substitution parameters as described above. The POST request MUST be sent with a Content-Type of `application/json`, and a payload matching the following schema:

```
{
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;data&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;0x-prefixed hex string containing the `callData` from the contract&quot;
        },
        &quot;sender&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;0x-prefixed hex string containing the `sender` parameter from the contract&quot;
        }
    }
}
```

Compliant gateways MUST respond with a Content-Type of `application/json`, with the body adhering to the following JSON schema:
```
{
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;data&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description: &quot;0x-prefixed hex string containing the result data.&quot;
        }
    }
}
```

Unsuccessful requests MUST return the appropriate HTTP status code - for example, 404 if the `sender` address is not supported by this gateway, 400 if the `callData` is in an invalid format, 500 if the server encountered an internal error, and so forth. If the Content-Type of a 4xx or 5xx response is `application/json`, it MUST adhere to the following JSON schema:
```
{
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;message&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description: &quot;A human-readable error message.&quot;
        }
    }
}
```

#### Examples

***GET request***

```
# Client returned a URL template `https://example.com/gateway/{sender}/{data}.json`
# Request
curl -D - https://example.com/gateway/0x226159d592E2b063810a10Ebf6dcbADA94Ed68b8/0xd5fa2b00.json

# Successful result
    HTTP/2 200
    content-type: application/json; charset=UTF-8
    ...
    
    {&quot;data&quot;: &quot;0xdeadbeefdecafbad&quot;}

# Error result
    HTTP/2 404
    content-type: application/json; charset=UTF-8
    ...

    {&quot;message&quot;: &quot;Gateway address not supported.&quot;}
}
```

***POST request***

```
# Client returned a URL template `https://example.com/gateway/{sender}.json`
# Request
curl -D - -X POST -H &quot;Content-Type: application/json&quot; --data &apos;{&quot;data&quot;:&quot;0xd5fa2b00&quot;,&quot;sender&quot;:&quot;0x226159d592E2b063810a10Ebf6dcbADA94Ed68b8&quot;}&apos; https://example.com/gateway/0x226159d592E2b063810a10Ebf6dcbADA94Ed68b8.json

# Successful result
    HTTP/2 200
    content-type: application/json; charset=UTF-8
    ...
    
    {&quot;data&quot;: &quot;0xdeadbeefdecafbad&quot;}

# Error result
    HTTP/2 404
    content-type: application/json; charset=UTF-8
    ...

    {&quot;message&quot;: &quot;Gateway address not supported.&quot;}
}
```

Clients MUST support both GET and POST requests. Gateways may implement either or both as needed.

### Client Lookup Protocol

A client that supports CCIP read MUST make contract calls using the following process:

 1. Set `data` to the call data to supply to the contract, and `to` to the address of the contract to call.
 2. Call the contract at address `to` function normally, supplying `data` as the input data. If the function returns a successful result, return it to the caller and stop.
 3. If the function returns an error other than `OffchainLookup`, return it to the caller in the usual fashion.
 4. Otherwise, decode the `sender`, `urls`, `callData`, `callbackFunction` and `extraData` arguments from the `OffchainLookup` error.
 5. If the `sender` field does not match the address of the contract that was called, return an error to the caller and stop.
 6. Construct a request URL by replacing `sender` with the lowercase 0x-prefixed hexadecimal formatted `sender` parameter, and replacing `data` with the 0x-prefixed hexadecimal formatted `callData` parameter. The client may choose which URLs to try in which order, but SHOULD prioritise URLs earlier in the list over those later in the list.
 7. Make an HTTP GET request to the request URL.
 8. If the response code from step (7) is in the range 400-499, return an error to the caller and stop.
 9. If the response code from step (7) is in the range 500-599, go back to step (5) and pick a different URL, or stop if there are no further URLs to try.
 10. Otherwise, replace `data` with an ABI-encoded call to the contract function specified by the 4-byte selector `callbackFunction`, supplying the data returned from step (7) and `extraData` from step (4), and return to step (1).

Clients MUST handle HTTP status codes appropriately, employing best practices for error reporting and retries.

Clients MUST handle HTTP 4xx and 5xx error responses that have a content type other than application/json appropriately; they MUST NOT attempt to parse the response body as JSON.

This protocol can result in multiple lookups being requested by the same contract. Clients MUST implement a limit on the number of lookups they permit for a single contract call, and this limit SHOULD be at least 4.

The lookup protocol for a client is described with the following pseudocode:

```javascript
async function httpcall(urls, to, callData) {
    const args = {sender: to.toLowerCase(), data: callData.toLowerCase()};
    for(const url of urls) {
        const queryUrl = url.replace(/\{([^}]*)\}/g, (match, p1) =&gt; args[p1]);
        // First argument is URL to fetch, second is optional data for a POST request.
        const response = await fetch(queryUrl, url.includes(&apos;{data}&apos;) ? undefined : args);
        const result = await response.text();
        if(result.statusCode &gt;= 400 &amp;&amp; result.statusCode &lt;= 499) {
            throw new Error(data.error.message);
        }
        if(result.statusCode &gt;= 200 &amp;&amp; result.statusCode &lt;= 299) {
            return result;
        }
    }
}
async function durin_call(provider, to, data) {
    for(let i = 0; i &lt; 4; i++) {
        try {
            return await provider.call(to, data);
        } catch(error) {
            if(error.code !== &quot;CALL_EXCEPTION&quot;) {
                throw(error);
            }
            const {sender, urls, callData, callbackFunction, extraData} = error.data;
            if(sender !== to) {
                throw new Error(&quot;Cannot handle OffchainLookup raised inside nested call&quot;);
            }
            const result = httpcall(urls, to, callData);
            data = abi.encodeWithSelector(callbackFunction, result, extraData);
        }
    }
    throw new Error(&quot;Too many CCIP read redirects&quot;);
}
```

Where:
 - `provider` is a provider object that facilitates Ethereum blockchain function calls.
 - `to` is the address of the contract to call.
 - `data` is the call data for the contract.

If the function being called is a standard contract function, the process terminates after the original call, returning the same result as for a regular call. Otherwise, a gateway from `urls` is called with the `callData` returned by the `OffchainLookup` error, and is expected to return a valid response. The response and the `extraData` are then passed to the specified callback function. This process can be repeated if the callback function returns another `OffchainLookup` error.

### Use of CCIP read for transactions
While the specification above is for read-only contract calls (eg, `eth_call`), it is simple to use this method for sending transactions (eg, `eth_sendTransaction` or `eth_sendRawTransaction`) that require offchain data. While &apos;preflighting&apos; a transaction using `eth_estimateGas` or `eth_call`, a client that receives an `OffchainLookup` revert can follow the procedure described above in [Client lookup protocol](#client-lookup-protocol), substituting a transaction for the call in the last step. This functionality is ideal for applications such as making onchain claims supported by offchain proof data.

### Glossary
 - Client: A process, such as JavaScript executing in a web browser, or a backend service, that wishes to query a blockchain for data. The client understands how to fetch data using CCIP read.
 - Contract: A smart contract existing on Ethereum or another blockchain.
 - Gateway: A service that answers application-specific CCIP read queries, usually over HTTPS.

## Rationale
### Use of `revert` to convey call information
For offchain data lookup to function as desired, clients must either have some way to know that a function depends on this specification for functionality - such as a specifier in the ABI for the function - or else there must be a way for the contract to signal to the client that data needs to be fetched from elsewhere.

While specifying the call type in the ABI is a possible solution, this makes retrofitting existing interfaces to support offchain data awkward, and either results in contracts with the same name and arguments as the original specification, but with different return data - which will cause decoding errors for clients that do not expect this - or duplicating every function that needs support for offchain data with a different name (eg, `balanceOf -&gt; offchainBalanceOf`). Neither solutions is particularly satisfactory.

Using a revert, and conveying the required information in the revert data, allows any function to be retrofitted to support lookups via CCIP read so long as the client understands the specification, and so facilitates translation of existing specifications to use offchain data.

### Passing contract address to the gateway service
`address` is passed to the gateway in order to facilitate the writing of generic gateways, thus reducing the burden on contract authors to provide their own gateway implementations. Supplying `address` allows the gateway to perform lookups to the original contract for information needed to assist with resolution, making it possible to operate one gateway for any number of contracts implementing the same interface.

### Existence of `extraData` argument
`extraData` allows the original contract function to pass information to a subsequent invocation. Since contracts are not persistent, without this data a contract has no state from the previous invocation. Aside from allowing arbitrary contextual information to be propagated between the two calls, this also allows the contract to verify that the query the gateway answered is in fact the one the contract originally requested.

### Use of GET and POST requests for the gateway interface
Using a GET request, with query data encoded in the URL, minimises complexity and enables entirely static implementations of gateways - in some applications a gateway can simply be an HTTP server or IPFS instance with a static set of responses in text files.

However, URLs are limited to 2 kilobytes in size, which will impose issues for more complex uses of CCIP read. Thus, we provide for an option to use POST data. This is made at the contract&apos;s discretion (via the choice of URL template) in order to preserve the ability to have a static gateway operating exclusively using GET when desired.

## Backwards Compatibility
Existing contracts that do not wish to use this specification are unaffected. Clients can add support for CCIP read to all contract calls without introducing any new overhead or incompatibilities.

Contracts that require CCIP read will not function in conjunction with clients that do not implement this specification. Attempts to call these contracts from non-compliant clients will result in the contract throwing an exception that is propagaged to the user.

## Security Considerations

### Gateway Response Data Validation
In order to prevent a malicious gateway from causing unintended side-effects or faulty results, contracts MUST include sufficient information in the `extraData` argument to allow them to verify the relevance and validity of the gateway&apos;s response. For example, if the contract is requesting information based on an `address` supplied to the original call, it MUST include that address in the `extraData` so that the callback can verify the gateway is not providing the answer to a different query.

Contracts must also implement sufficient validation of the data returned by the gateway to ensure it is valid. The validation required is application-specific and cannot be specified on a global basis. Examples would include verifying a Merkle proof of inclusion for an L2 or other Merkleized state, or verifying a signature by a trusted signer over the response data.

### Client Extra Data Validation
In order to prevent a malicious client from causing unintended effects when making transactions using CCIP read, contracts MUST implement appropriate checks on the `extraData` returned to them in the callback. Any sanity/permission checks performed on input data for the initial call MUST be repeated on the data passed through the `extraData` field in the callback. For example, if a transaction should only be executable by an authorised account, that authorisation check MUST be done in the callback; it is not sufficient to perform it with the initial call and embed the authorised address in the `extraData`.

### HTTP requests and fingerprinting attacks
Because CCIP read can cause a user&apos;s browser to make HTTP requests to an address controlled by the contract, there is the potential for this to be used to identify users - for example, to associate their wallet address with their IP address.

The impact of this is application-specific; fingerprinting a user when they resolve an ENS domain may have little privacy impact, as the attacker will not learn the user&apos;s wallet address, only the fact that the user is resolving a given ENS name from a given IP address - information they can also learn from running a DNS server. On the other hand, fingerprinting a user when they attempt a transaction to transfer an NFT may give an attacker everything they need to identify the IP address of a user&apos;s wallet.

To minimise the security impact of this, we make the following recommendations:

 1. Client libraries should provide clients with a hook to override CCIP read calls - either by rewriting them to use a proxy service, or by denying them entirely. This mechanism or another should be written so as to easily facilitate adding domains to allowlists or blocklists.
 2. Client libraries should disable CCIP read for transactions (but not for calls) by default, and require the caller to explicitly enable this functionality. Enablement should be possible both on a per-contract, per-domain, or global basis.
 3. App authors should not supply a &apos;from&apos; address for contract calls (&apos;view&apos; operations) where the call could execute untrusted code (that is, code not authored or trusted by the application author). As a precuationary principle it is safest to not supply this parameter at all unless the author is certain that no attacker-determined smart contract code will be executed.
 4. Wallet authors that are responsible for fetching user information - for example, by querying token contracts - should either ensure CCIP read is disabled for transactions, and that no contract calls are made with a &apos;from&apos; address supplied, or operate a proxy on their users&apos; behalf, rewriting all CCIP read calls to take place via the proxy, or both.

We encourage client library authors and wallet authors not to disable CCIP read by default, as many applications can be transparently enhanced with this functionality, which is quite safe if the above precautions are observed.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 19 Jul 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3668</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3668</guid>
      </item>
    
      <item>
        <title>EOF - Code Validation</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3670-eof-code-validation/6693</comments>
        
        <description>## Abstract

Introduce code validation at contract creation time for EOF formatted ([EIP-3540](/EIPs/EIPS/eip-3540))
contracts. Reject contracts which contain truncated `PUSH`-data or undefined instructions.
Legacy bytecode (code which is not EOF formatted) is unaffected by this change.

## Motivation

Currently existing contracts require no validation of correctness and EVM implementations can decide
how they handle truncated bytecode or undefined instructions. This change aims to bring code
validity into consensus, so that it becomes easier to reason about bytecode.
Moreover, EVM implementations may require fewer paths to decide which instruction is valid in
the current execution context.

If there&apos;s a desire to introduce new instructions without bumping the EOF version, having undefined instructions already deployed could potentially break such contracts, as some instructions might change their behavior. Rejecting to deploy undefined instructions allows
introducing new instructions with or without bumping the EOF version.

### EOF1 forward compatibility

The EOF1 format provides following forward compatibility properties:

1. New instructions can be defined for previously unassigned opcodes. These instructions may have immediate values.
2. Mandatory EOF sections may be made optional.
3. New optional EOF sections may be introduced. They can be placed in any order in relation to previously defined sections.

## Specification

This feature is introduced on the same block EIP-3540 is enabled, therefore every EOF1-compatible bytecode MUST be validated according to these rules.

1. Previously deprecated instructions `CALLCODE` (0xf2) and `SELFDESTRUCT` (0xff), as well as instructions deprecated in EIP-3540, are invalid and their opcodes are undefined. (**NOTE** there are more instructions deprecated and rejected in EOF, as specced out by separate EIPs)
2. At contract creation time *code validation* is performed on each code section of the EOF container. The code is invalid if any of the checks below fails. For each instruction:
   1. Check if the opcode is defined. The `INVALID` (0xfe) is considered defined.
   2. Check if all instructions&apos; immediate bytes are present in the code (code does not end in the middle of instruction).

## Rationale

### Immediate data

Allowing implicit zero immediate data for `PUSH` instructions introduces inefficiencies to EVM implementations without any practical use-case (the value of a `PUSH` instruction at the code end cannot be observed by EVM). This EIP requires all immediate bytes to be explicitly present in the code.

### Rejection of deprecated instructions

The deprecated instructions `CALLCODE` (0xf2) and `SELFDESTRUCT` (0xff) are removed from the `valid_opcodes` list to prevent their use in the future.

### BLOCKHASH instruction

The `BLOCKHASH` instruction is well replaced by the system contract introduced in [EIP-2935](./eip-2935).
However, despite a replacement being introduced this opcode has not been deprecated.
This opcode will remain valid in EOF not to differentiate from legacy bytecode.

## Backwards Compatibility

This change poses no risk to backwards compatibility, as it is introduced at the same time EIP-3540 is. The validation does not cover legacy bytecode (code which is not EOF formatted).

## Test Cases

### Contract creation

Each case should be tested by submitting an EOF container to EOF contract creation (as specced out in a separate EIP). Each case should be tested with code placed in code sections at different indices.

### Valid codes

- EOF code containing `INVALID`
- EOF code with data section containing bytes that are undefined instructions

### Invalid codes

- EOF code containing an undefined instruction
- EOF code ending with incomplete `PUSH` instruction

## Reference Implementation

```python
# The ranges below are as specified by Execution Specs for Shanghai.
# Note: range(s, e) excludes e, hence the +1
shanghai_opcodes = [
    *range(0x00, 0x0b + 1),
    *range(0x10, 0x1d + 1),
    0x20,
    *range(0x30, 0x3f + 1),
    *range(0x40, 0x48 + 1),
    *range(0x50, 0x5b + 1),
    0x5f,
    *range(0x60, 0x6f + 1),
    *range(0x70, 0x7f + 1),
    *range(0x80, 0x8f + 1),
    *range(0x90, 0x9f + 1),
    *range(0xa0, 0xa4 + 1),
    # Note: 0xfe is considered assigned.
    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xfa, 0xfd, 0xfe, 0xff
]

# Drop the opcodes deprecated and rejected in here and in EIP-3540
rejected_in_eof = [
    0x38, 0x39, 0x3b, 0x3c, 0x3f, 0x5a, 0xf1, 0xf2, 0xf4, 0xfa, 0xff
]
valid_opcodes = [op for op in shanghai_opcodes not in rejected_in_eof]

immediate_sizes = 256 * [0]
immediate_sizes[0x60:0x7f + 1] = range(1, 32 + 1)  # PUSH1..PUSH32


# Raises ValidationException on invalid code
def validate_instructions(code: bytes):
    # Note that EOF1 already asserts this with the code section requirements
    assert len(code) &gt; 0

    pos = 0
    while pos &lt; len(code):
        # Ensure the opcode is valid
        opcode = code[pos]
        if opcode not in valid_opcodes:
            raise ValidationException(&quot;undefined opcode&quot;)

        # Skip immediate data
        pos += 1 + immediate_sizes[opcode]

    # Ensure last instruction&apos;s immediate doesn&apos;t go over code end
    if pos != len(code):
        raise ValidationException(&quot;truncated immediate&quot;)
```

## Security Considerations

See [Security Considerations of EIP-3540](/EIPs/EIPS/eip-3540#security-considerations).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 23 Jun 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3670</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3670</guid>
      </item>
    
      <item>
        <title>Upgrade consensus to Proof-of-Stake</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3675-upgrade-consensus-to-proof-of-stake/6706</comments>
        
        <description>## Abstract

This EIP deprecates Proof-of-Work (PoW) and supersedes it with the new Proof-of-Stake consensus mechanism (PoS) driven by the beacon chain. Information on the bootstrapping of the new consensus mechanism is documented in [EIP-2982](/EIPs/EIPS/eip-2982). Full specification of the beacon chain can be found in the `ethereum/consensus-specs` repository.

This document specifies the set of changes to the block structure, block processing, fork choice rule and network interface introduced by the consensus upgrade.


## Motivation

The beacon chain network has been up and running since December 2020. Neither safety nor liveness failures were detected during this period of time. This long period of running without failure demonstrates the sustainability of the beacon chain system and its readiness to become a security provider for the Ethereum Mainnet.

To understand the motivation of introducing the Proof-of-Stake consensus see the Motivation section of [EIP-2982](/EIPs/EIPS/eip-2982#motivation).


## Specification

### Definitions

* **PoW block**: Block that is built and verified by the existing proof-of-work mechanism. In other words, a block of the Ethereum network before the consensus upgrade.
* **PoS block**: Block that is built and verified by the new proof-of-stake mechanism.
* **Terminal PoW block**: A PoW block that satisfies the following conditions --
`pow_block.total_difficulty &gt;= TERMINAL_TOTAL_DIFFICULTY` *and* `pow_block.parent_block.total_difficulty &lt; TERMINAL_TOTAL_DIFFICULTY`.
There can be more than one terminal PoW block in the network, e.g. multiple children of the same pre-terminal block.
* **`TERMINAL_TOTAL_DIFFICULTY`** The amount of total difficulty reached by the network that triggers the consensus upgrade. Ethereum Mainnet configuration **MUST** have this parameter set to the value `58750000000000000000000`.
* **`TRANSITION_BLOCK`** The earliest PoS block of the canonical chain, i.e. the PoS block with the lowest block height.
* **`POS_FORKCHOICE_UPDATED`** An event occurring when the state of the proof-of-stake fork choice is updated.
* **`FORK_NEXT_VALUE`** A block number set to the `FORK_NEXT` parameter for the upcoming consensus upgrade.
* **`TERMINAL_BLOCK_HASH`** Designates the hash of the terminal PoW block if set, i.e. if not stubbed with `0x0000000000000000000000000000000000000000000000000000000000000000`.
* **`TERMINAL_BLOCK_NUMBER`** Designates the number of the terminal PoW block if `TERMINAL_BLOCK_HASH` is set.

#### PoS events

Events having the `POS_` prefix in the name (PoS events) are emitted by the new proof-of-stake consensus mechanism. They signify the corresponding assertion that has been made regarding a block specified by the event. The underlying logic of PoS events can be found in the beacon chain specification. On the occurrence of each PoS event the corresponding action that is specified by this EIP **MUST** be taken.

The details provided below must be taken into account when reading those parts of the specification that refer to the PoS events:
* Reference to a block that is contained by PoS events is provided in a form of a block hash unless another is explicitly specified.
* A `POS_FORKCHOICE_UPDATED` event contains references to the head of the canonical chain and to the most recent finalized block. Before the first finalized block occurs in the system the finalized block hash provided by this event is stubbed with `0x0000000000000000000000000000000000000000000000000000000000000000`. 
* **`FIRST_FINALIZED_BLOCK`** The first finalized block that is designated by `POS_FORKCHOICE_UPDATED` event and has the hash that differs from the stub.


### Client software configuration

The following set of parameters is a part of client software configuration and **MUST** be included into its binary distribution:
* `TERMINAL_TOTAL_DIFFICULTY`
* `FORK_NEXT_VALUE`
* `TERMINAL_BLOCK_HASH`
* `TERMINAL_BLOCK_NUMBER`

*Note*: If `TERMINAL_BLOCK_HASH` is stubbed with `0x0000000000000000000000000000000000000000000000000000000000000000` then `TERMINAL_BLOCK_HASH` and `TERMINAL_BLOCK_NUMBER` parameters **MUST NOT** take an effect.


### PoW block processing

PoW blocks that are descendants of any terminal PoW block **MUST NOT** be imported. This implies that a terminal PoW block will be the last PoW block in the canonical chain.


### Constants

| Name | Value |
|-|-|
| **`MAX_EXTRA_DATA_BYTES`** | `32` |

### Block structure

Beginning with `TRANSITION_BLOCK`, a number of previously dynamic block fields are deprecated by enforcing these values to instead be constants. Each block field listed in the table below **MUST** be replaced with the corresponding constant value.

| Field | Constant value | Comment |
|-|-|-|
| **`ommersHash`** | `0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347` | `= Keccak256(RLP([]))` |
| **`difficulty`** | `0` |  |
| **`mixHash`** | `0x0000000000000000000000000000000000000000000000000000000000000000` |  |
| **`nonce`** | `0x0000000000000000` |  |
| **`ommers`** | `[]` | `RLP([]) = 0xc0`  |

Beginning with `TRANSITION_BLOCK`, the validation of the block&apos;s **`extraData`** field changes: The length of the block&apos;s **`extraData`** **MUST** be less than or equal to **`MAX_EXTRA_DATA_BYTES`** bytes.

*Note*: Logic and validity conditions of block fields that are *not* specified here **MUST** remain unchanged. Additionally, the overall block format **MUST** remain unchanged.

*Note*: Subsequent EIPs may override the constant values specified above to provide additional functionality. For an example, see [EIP-4399](/EIPs/EIPS/eip-4399).


### Block validity

Beginning with `TRANSITION_BLOCK`, the block validity conditions **MUST** be altered by the following:
* Remove verification of the block&apos;s **`difficulty`** value with respect to the difficulty formula.
* Remove verification of the block&apos;s **`nonce`** and **`mixHash`** values with respect to the Ethash function.
* Remove all validation rules that are evaluated over the list of ommers and each member of this list.
* Add verification of the fields noted in the [block structure](#block-structure) section.

*Note*: If one of the new rules fails then the block **MUST** be invalidated.

*Note*: Validity rules that are not specified in the list above **MUST** remain unchanged.

#### Transition block validity

In addition to satisfying the above conditions, `TRANSITION_BLOCK` **MUST** be a child of a terminal PoW block. That is, a parent of `TRANSITION_BLOCK` **MUST** satisfy terminal PoW block conditions.


### Block and ommer rewards

Beginning with `TRANSITION_BLOCK`, block and ommer rewards are deprecated. Specifically, the following actions **MUST** be taken:
* Remove increasing the balance of the block&apos;s **`beneficiary`** account by the block reward.
* Remove increasing the balance of the block&apos;s **`beneficiary`** account by the ommer inclusion reward per each ommer.
* Remove increasing the balance of the ommer&apos;s **`beneficiary`** account by the ommer block reward per each ommer.

*Note*: Transaction fee mechanics affecting the block&apos;s `beneficiary` account **MUST** remain unchanged.


### Fork choice rule

If set, `TERMINAL_BLOCK_HASH` parameter affects the PoW heaviest chain rule in the following way:
* Canonical blockchain **MUST** contain a block with the hash defined by `TERMINAL_BLOCK_HASH` parameter at the height defined by `TERMINAL_BLOCK_NUMBER` parameter.

*Note*: This rule is akin to block hash whitelisting functionality already present in client software implementations.

As of the first `POS_FORKCHOICE_UPDATED` event, the fork choice rule **MUST** be altered in the following way:
* Remove the existing PoW heaviest chain rule.
* Adhere to the new PoS LMD-GHOST rule.

The new PoS LMD-GHOST fork choice rule is specified as follows. On each occurrence of a `POS_FORKCHOICE_UPDATED` event including the first one, the following actions **MUST** be taken:
* Consider the chain starting at genesis and ending with the head block nominated by the event as the canonical blockchain.
* Set the head of the canonical blockchain to the corresponding block nominated by the event.
* Beginning with the `FIRST_FINALIZED_BLOCK`, set the most recent finalized block to the corresponding block nominated by the event.

Changes to the block tree store that are related to the above actions **MUST** be applied atomically.

*Note*: This rule **MUST** be strictly enforced. &quot;Optimistic&quot; updates to the head **MUST NOT** be made. That is -- if a new block is processed on top of the current head block, this new block becomes the new head if and only if an accompanying `POS_FORKCHOICE_UPDATED` event occurs.

### Network

#### Fork identifier

For the purposes of the [EIP-2124](/EIPs/EIPS/eip-2124) fork identifier, nodes implementing this EIP **MUST** set the `FORK_NEXT` parameter to the `FORK_NEXT_VALUE`.

#### devp2p

The networking stack **SHOULD NOT** send the following messages if they advertise the descendant of any terminal PoW block:
* `NewBlockHashes (0x01)`
* `NewBlock (0x07)`

Beginning with receiving the `FIRST_FINALIZED_BLOCK`, the networking stack **MUST** discard the following ingress messages:
* `NewBlockHashes (0x01)`
* `NewBlock (0x07)`

Beginning with receiving the finalized block next to the `FIRST_FINALIZED_BLOCK`, the networking stack **MUST** remove the handlers corresponding to the following messages:
* `NewBlockHashes (0x01)`
* `NewBlock (0x07)`

Peers that keep sending these messages after the handlers have been removed **SHOULD** be disconnected.

*Note:* The logic of message handlers that are not affected by this section **MUST** remain unchanged.


## Rationale

The changes specified in this EIP target a minimal requisite set of consensus and client software modifications to safely replace the existing proof-of-work consensus algorithm with the new proof-of-stake consensus represented by the already in-production beacon chain.

This EIP was designed to minimize the complexity of hot-swapping the live consensus of the Ethereum network. Both the safety of the operation and time to production were taken into consideration. Additionally, a minimal changeset helps ensure that *most* smart contracts and services will continue to function as intended during and after the transition with little to no required intervention.

### Total difficulty triggering the upgrade

See [Security considerations](#terminal-total-difficulty-vs-block-number).

### Parameterizing terminal block hash

See [Security considerations](#terminal-pow-block-overriding).

### Halting the import of PoW blocks

See [Security considerations](#halt-the-importing-of-pow-blocks).

### Replacing block fields with constants

Deprecated block fields are replaced with constant values to ensure the block format remains backwards compatible. Preserving the block format aids existing smart contracts and services in providing uninterrupted service during and after this transition.

Particularly, this is important for those smart contracts that verify Merkle proofs of transaction/receipt inclusion and state by validating the hash of externally provided block header against the corresponding value returned by the `BLOCKHASH` operation.

This change introduces an additional validity rule that enforces the replacement of deprecated block fields.

### Replacing `difficulty` with `0`

After deprecating the proof-of-work the notion of difficulty no longer exists and replacing the block header **`difficulty`** field with `0` constant is semantically sound.

### Changing block validity rules

The rule set enforcing the PoW seal validity is replaced with the corresponding PoS rules along with the consensus upgrade as the rationale behind this change.

An additional rule validating a set of deprecated block fields is required by the block format changes introduced by this specification.

### Removing block rewards

Existing rewards for producing and sealing blocks are deprecated along with the PoW mechanism. The new PoS consensus becomes both responsible for sealing blocks and for issuing block rewards once this specification enters into effect.

### Supplanting fork choice rule

The fork choice rule of the PoW mechanism becomes completely irrelevant after the upgrade and is replaced with the corresponding rule of the new PoS consensus mechanism.

### Remove of `POS_CONSENSUS_VALIDATED`

In prior draft versions of this EIP, an additional POS event -- `POS_CONSENSUS_VALIDATED` -- was required as a validation condition for blocks. This event gave the signal to either fully incorporate or prune the block from the block tree.

This event was removed for two reasons:
1. This event was an unnecessary optimization to allow for pruning of &quot;bad&quot; blocks from the block tree. This optimization was unnecessary because the PoS consensus would never send `POS_FORKCHOICE_UPDATED` for any such bad blocks or their descendants, and eventually any such blocks would be able to be pruned after a PoS finality event of an alternative branch in the block tree.
2. This event was dangerous in some scenarios because a block could be referenced by two *different* and conflicting PoS branches. Thus for the same block in some scenarios, both a `POS_CONSENSUS_VALIDATED == TRUE` and `POS_CONSENSUS_VALIDATED == FALSE` event could sent, entirely negating the ability to safely perform the optimization in (1).

### EIP-2124 fork identifier

The value of `FORK_NEXT` in EIP-2124 refers to the block number of the next fork a given node knows about and `0` otherwise.

The number of `TRANSITION_BLOCK` cannot be known ahead of time given the dynamic nature of the transition trigger condition. As the block will not be known a priori, nodes can&apos;t use its number for `FORK_NEXT` and in light of this fact an explicitly set `FORK_NEXT_VALUE` is used instead.

### Removing block gossip

After the upgrade of the consensus mechanism only the beacon chain network will have enough information to validate a block. Thus, block gossip provided by the `eth` network protocol will become unsafe and is deprecated in favour of the block gossip existing in the beacon chain network.

It is recommended for the client software to not propagate descendants of any terminal PoW block to reduce the load on processing the P2P component and stop operating in the environment with unknown security properties.

### Restricting the length of `extraData`

The `extraData` field is defined as a maximum of `32` bytes in the yellow paper. Thus mainnet and most PoW testnets cap the value at `32` bytes.  `extraData` fields of greater length are used by clique testnets and other networks to carry special signature/consensus schemes. This EIP restricts the length of `extraData` to `32` bytes because any network that is transitioning from another consensus mechanism to a beacon chain PoS consensus mechanism no longer needs extended or unbounded `extraData`.

## Backwards Compatibility

This EIP introduces backward incompatibilities in block validity, block rewards and fork choice rule.

The design of the consensus upgrade specified by this document does not introduce backward incompatibilities for existing applications and services built on top of Ethereum except for those that are described in the [EVM](#evm) section below or heavily depends on the PoW consensus in any other way.


### EVM

Although this EIP does not introduce any explicit changes to the EVM there are a couple of places where it may affect the logic of existing smart contracts.

#### DIFFICULTY

`DIFFICULTY` operation will always return `0` after this EIP takes effect and deprecates the **`difficulty`** field by replacing it with `0` constant.

*Note:* Altering the `DIFFICULTY` semantics to return randomness accumulated by the beacon chain is under consideration but will be introduced in a separate EIP.

#### BLOCKHASH

Pseudo-random numbers obtained as the output of `BLOCKHASH` operation become more insecure after this EIP takes effect and the PoW mechanism (which decreases the malleability of block hashes) gets supplanted by PoS.


## Test Cases

* Block validity
	* Beginning with `TRANSITION_BLOCK`, block is invalidated if any of the following is true:
		* `ommersHash != Keccak256(RLP([]))`
		* `difficulty != 0`
		* `nonce != 0x0000000000000000`
		* `len(extraData) &gt; MAX_EXTRA_DATA_BYTES`
  * Beginning with `TRANSITION_BLOCK`, block rewards aren&apos;t added to `beneficiary` account
* Client software adheres to PoS LMD-GHOST rule
  * Head and finalized blocks are set according to the recent `POS_FORKCHOICE_UPDATED` event
  * No fork choice state is updated unless `POS_FORKCHOICE_UPDATED` event is received
* Transition process
  * Client software doesn&apos;t process any PoW block beyond a terminal PoW block
  * Beginning with `TRANSITION_BLOCK`, client software applies new block validity rules
  * Beginning with the first `POS_FORKCHOICE_UPDATED`, client software switches its fork choice rule to PoS LMD-GHOST
  * `TRANSITION_BLOCK` must be a child of a terminal PoW block
  * `NewBlockHashes (0x01)` and `NewBlock (0x07)` network messages are discarded after receiving the `FIRST_FINALIZED_BLOCK`


## Security Considerations

### Beacon chain

See Security Considerations section of [EIP-2982](/EIPs/EIPS/eip-2982#security-considerations).

### Transition process

The transition process used to take this specification into effect is a more sophisticated version of a hardfork -- the regular procedure of applying backwards incompatible changes in the Ethereum network. This process has multiple successive steps instead of the normal block-height point condition of simpler hardforks.

The complexity of this upgrade process stems from this fork targeting the underlying consensus mechanism rather than the execution layer within the consensus mechanism. Although the design seeks simplicity where possible, safety and liveness considerations during this transition have been prioritized.

#### Terminal total difficulty vs block number

Using a pre-defined block number for the hardfork is unsafe in this context due to the PoS fork choice taking priority during the transition.

An attacker may use a minority of hash power to build a malicious chain fork that would satisfy the block height requirement. Then the first PoS block may be maliciously proposed on top of the PoW block from this adversarial fork, becoming the head and subverting the security of the transition.

To protect the network from this attack scenario, difficulty accumulated by the chain (total difficulty) is used to trigger the upgrade.

#### Ability to jump between terminal PoW blocks

There could be the case when a terminal PoW block is not observed by the majority of network participants due to (temporal) network partitioning. In such a case, this minority would switch their fork choice to the new rule provided by the PoS rooted on the minority terminal PoW block that they observed.

The transition process allows the network to re-org between forks with different terminal PoW blocks as long as (a) these blocks satisfy the terminal PoW block conditions and (b) the `FIRST_FINALIZED_BLOCK` has not yet been received. This provides resilience against adverse network conditions during the transition process and prevents irreparable forks/partitions.

#### Halt the importing of PoW blocks

Suppose the part of the client software that is connected to the beacon chain network goes offline before the Ethereum network reaches the `TERMINAL_TOTAL_DIFFICULTY` and stays offline while the network meets this threshold. Such an event makes the client software unable to switch to PoS and allows it to keep following the PoW chain if this chain is being built beyond the terminal PoW block. Depending on how long the beacon chain part was offline, it could result in different adverse effects such as:
* The client has no post-state for the terminal PoW block (the state has been pruned) which prevents it from doing the re-org to the PoS chain and leaving syncing from scratch as the only option to recover.
* An application, a user or a service uses the data from the wrong fork (PoW chain that is kept being built) which can cause security issues on their side.

Not importing PoW blocks that are beyond the terminal PoW block prevents these adverse effects on safety/re-orgs in the event of software or configuration failures *in favor* of a liveness failure.

#### Terminal PoW block overriding

There is a mechanism allowing for accelerating the consensus upgrade in emergency cases.
This EIP considers the following emergency case scenarios for the acceleration to come into effect:
* A drop of the network hashing rate which delays the upgrade significantly.
* Attacks on the PoW network before the upgrade.

The first case can be safely accelerated by updating the following parameters:
* `TERMINAL_TOTAL_DIFFICULTY` -- reset to a value that is closer in time than the original one.
* `FORK_NEXT_VALUE` -- adjust accordingly.

The second, more dire attack scenario requires a more invasive override:
* `TERMINAL_BLOCK_HASH` -- set to the hash of a certain block to become the terminal PoW block.
* `TERMINAL_BLOCK_NUMBER` -- set to the number of a block designated by `TERMINAL_BLOCK_HASH`.
* `TERMINAL_TOTAL_DIFFICULTY` -- set to the total difficulty value of a block designated by `TERMINAL_BLOCK_HASH`.
* `FORK_NEXT_VALUE` -- adjust accordingly.

*Note*: Acceleration in the second case is considered for the most extreme of scenarios because it will result in a non-trivial liveness failure on Ethereum Mainnet.

### Ancient blocks are no longer a requisite for a network security

Keeping historical blocks starting from genesis is essential in the PoW network. A header of every block that belongs to a particular chain is required to justify the validity of this chain with respect to the PoW seal.

Validating the entire history of the chain is not required by the new PoS mechanism. Instead, the sync process in the PoS network relies on weak subjectivity checkpoints, which are historical snapshots shared by peers on the network. This means historical blocks beyond weak subjectivity checkpoint are no longer a requisite for determining the canonical blockchain.

Specification of weak subjectivity checkpoints can be found in the `ethereum/consensus-specs` repository.


## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 22 Jul 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3675</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3675</guid>
      </item>
    
      <item>
        <title>EOF - JUMPDEST Table</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3690-eof-jumpdest-table/6806</comments>
        
        <description>## Abstract

Introduce a section in the EOF format ([EIP-3540](/EIPs/EIPS/eip-3540)) for storing the list of `JUMPDEST`s, validate the correctness of this list at the time of contract creation, and remove the need for `JUMPDEST`-analysis at execution time. In EOF contracts, the `JUMPDEST` instruction is not needed anymore and becomes invalid. Legacy contracts are entirely unaffected by this change.

## Motivation

Currently existing contracts require no validation of correctness, but every time they are executed, a list must be built containing all the valid jump-destinations. This is an overhead which can be avoided, albeit the effect of the overhead depends on the client implementation.

With the structure provided by EIP-3540 it is easy to store and transmit a table of valid jump-destinations instead of using designated `JUMPDEST` (0x5b) opcodes in the code.

The goal of this change is that we trade less complexity (and processing time) at execution time for more complexity at contract creation time. Through benchmarks we have identified that the mandatory execution preparation time is the same as before for extreme cases (i.e. deliberate edge cases), while it is ~10x faster for the average case.

Finally, this change puts an implicit bound on &quot;initcode analysis&quot; which is now limited to jumpdests section loading of max size of 0xffff. The legacy code remains vulnerable.

## Specification

This feature is introduced on the very same block [EIP-3540](/EIPs/EIPS/eip-3540) is enabled, therefore every EOF1-compatible bytecode MUST have a JUMPDEST-table if it uses jumps.

*Remark:* We rely on the notation of *initcode*, *code* and *creation* as defined by [EIP-3540](/EIPs/EIPS/eip-3540), and extend validation rules of [EIP-3670](/EIPs/EIPS/eip-3670).

### EOF container changes

1. A new EOF section called `jumpdests` (`section_kind = 3`) is introduced. It contains a sequence of *n* unsigned integers *jumploc&lt;sub&gt;i&lt;/sub&gt;*.
2. The *jumploc&lt;sub&gt;i&lt;/sub&gt;* values are encoded with [unsigned LEB128](https://en.wikipedia.org/wiki/LEB128#Unsigned_LEB128).

   | description         | encoding        |
   |---------------------|-----------------|
   | jumploc&lt;sub&gt;0&lt;/sub&gt; | unsigned LEB128 |
   | jumploc&lt;sub&gt;1&lt;/sub&gt; | unsigned LEB128 |
   | ...                 |                 |
   | jumploc&lt;sub&gt;n&lt;/sub&gt; | unsigned LEB128 |

3. The jump destinations represent the set of valid code positions as arguments to jump instructions. They are delta-encoded therefore partial sum must be performed to retrieve the absolute offsets.
   ```python
   def jumpdest(n: int, jumpdests_table: list[int]) -&gt; int:
       return sum(jumpdests_table[:n+1])
   ```

### Validation rules

&gt; This section extends contract creation validation rules (as defined in EIP-3540).

4. The `jumpdests` section MUST be present if and only if the `code` section contains `JUMP` or `JUMPI` opcodes.
5. If the `jumpdests` section is present it MUST directly precede the `code` section. In this case a valid EOF bytecode will have the form of `format, magic, version, [jumpdests_section_header], code_section_header, [data_section_header], 0, [jumpdests_section_contents], code_section_contents, [data_section_contents]`.
6. The LEB128 encoding of a `jumploc` must be valid: the encoding must be complete and not read out of `jumpdests` section. As an additional constraint, the shortest possible encoding must be used.
7. With an exception of the first entry, the value of `jumploc` MUST NOT be 0.
8. Every `jumploc` MUST point to a valid opcode. They MUST NOT point into PUSH-data or outside of the code section.
9. The `JUMPDEST` (0x5b) instruction becomes undefined (Note: According to rules of EIP-3670, deploying the code will fail if it contains `JUMPDEST`)

### Execution

10. When executing `JUMP` or `JUMPI` instructions, the jump destination MUST be in the `jumpdests` table. Otherwise, the execution aborts with *bad jump destination*. In case of `JUMPI`, the check is done only when the jump is to be taken (no change to the previous behaviour).

## Rationale

### Jumpdests section is bounded

The length of the `jumpdests` section is bounded by the EOF maximum section size value 0xffff. Moreover, for deployed code this is additionally limited by the max bytecode size 0x6000. Then any valid `jumpdests` section may not be larger than 0x3000.

### Delta encoding

Delta-encoding is very efficient for this job. From a quick analysis of a small set of contracts `JUMPDEST` opcodes are relatively close to each other. In the delta-encoding the values almost never exceed 128. Combined with any form of variable-length quantity (VLQ) where values &lt; 128 occupy one byte, encoding of single jumpdest takes ~1 byte. We also remove `JUMPDEST` opcodes from the code section therefore the total bytecode length remains the same if extreme examples are ignored.

By extreme examples we mean contracts having a distance between two subsequent JUMPDESTs larger than 128. Then the LEB128 encoding of such distance requires more than one byte and the total bytecode size will increase by the additional number of bytes used.

### LEB128 for offsets

The LEB128 encoding is the most popular VLQ used in DWARF and WebAssembly.

LEB128 allows encoding a fixed value with arbitrary number of bytes by having zero payloads for most significant bits of the value. To ensure there exists only single encoding of a given value, we additionally require the shortest possible LEB128 encoding to be used. This constraint is also required by WebAssembly.

### Size-prefix for offsets

This is another option for encoding inspired by UTF-8. The benefit is that the number of following bytes is encoded in the first byte (the top two bits), so the expected length is known upfront.

A simple decoder is the following:
```python
def decode(input: bytes) -&gt; int:
    size_prefix = input[0] &gt;&gt; 6
    if size_prefix == 0:
        return input[0] &amp; 0x3f
    elif size_prefix == 1:
        return (input[0] &amp; 0x3f) &lt;&lt; 8 | input[1]
    elif size_prefix == 2:
        return (input[0] &amp; 0x3f) &lt;&lt; 16 | (input[1] &lt;&lt; 8) | input[2]
    # Do not support case 3
    assert(False)
```

### Empty table

In case code does not use jumps, an empty JUMPDEST table is represented by omitting `jumpdests` section as opposed to a section that is always present, but allowed to be empty. This is consistent with the requirement of EIP-3540 for section size to be non-zero. Additionally, omitting the section saves 3 bytes of code storage.

### Why jumpdests before code?

The contents of `jumpdests` section are always needed to start EVM execution. For chunked and/or merkleized bytecode it is more efficient to have `jumpdests` just after the EOF header so they can share the same first chunk(s).

### Code chunking / merkleization

In code chunking the contract code is split into (fixed size) chunks. Due to the requirement of jumpdest-analysis, it must be known where the first instruction starts in a given chunk, in case the split happened within a PUSH-data. This is commonly accomplished with reserving the first byte of the chunk as the &quot;first instruction offset&quot; (FIO) field.

With this EIP, code chunking does not need to have such a field. However, the jumpdest table must be provided instead (for all the chunks up until the last jump location used during execution).

### Benchmarks / performance analysis

We compared the performance of `jumpdests` section loading to JUMPDEST analysis in evmone/Baseline interpreter. In both cases a bitset of valid jumpdest positions is built.

We used the worst case for `jumpdests` section as the benchmark baseline. This is the case where every position in the code section is valid jumpdest. I.e. the bytecode has as many jumpdests as possible making the jumpdests section as large as possible. The encoded representation is `0x00, 0x01, 0x01, 0x01, ...`.

This also happen to be the worst case for the JUMPDEST analysis.

Further, we picked 5 popular contracts from the Ethereum mainnet.

| case | size | num JUMPDESTs | JUMPDEST analysis (cycles/byte) | jumpdests load (cycles/byte) | performance change |
| ----------------- | ----- | ----- | ---- | ---- | ------- |
| worst             | 65535 | 65535 | 9.11 | 9.36 |   2.75% |
| RoninBridge       |  1760 |    71 | 3.57 |      | -89.41% |
| UniswapV2ERC20    |  2319 |    61 | 2.10 |      | -88.28% |
| DepositContract   |  6358 |   123 | 1.86 |      | -90.24% |
| TetherToken       | 11075 |   236 | 1.91 |      | -89.58% |
| UniswapV2Router02 | 21943 |   468 | 2.26 |      | -91.17% |

For the worst case the performance difference between JUMPDEST analysis and jumpdests section loading is very small. The performance very slow compared to memory copy (0.15 cycles/byte).

However, the maximum length for the worst cases is different. For JUMPDEST analysis this is 24576 (0x6000) for deployed contracts and only limited by EVM memory cost in case of _initcode_ (can be over 1MB). For jumpdests sections, the limit is 12288 for deployed contracts (the deployed bytecode length limit must be split equally between jumpdests and code sections). For _initcode_ case, the limit is 65535 because this is the maximum section size allowed by EOF.

For &quot;popular&quot; contracts the gained efficiency is ~10x because the jumpdests section is relatively small compared to the code section and therefore there is much less bytes to loop over than in JUMPDEST analysis.

## Reference Implementation

We extend the `validate_code()` function of [EIP-3670](/EIPs/EIPS/eip-3670):
```python
# The same table as in EIP-3670
valid_opcodes = ...

# Remove JUMPDEST from the list of valid opcodes
valid_opcodes.remove(0x5b)

# This helper decodes a single unsigned LEB128 encoded value
# This will abort on truncated (short) input
def leb128u_decode(input: bytes) -&gt; (int, int):
  ret = 0
  shift = 0
  consumed_bytes = 0
  while True:
      # Check for truncated input
      assert(consumed_bytes &lt; len(input))
      # Only allow up to 4-byte long leb128 encodings
      assert(consumed_bytes &lt;= 3)
      input_byte = input[consumed_bytes]
      consumed_bytes += 1
      ret |= (input_byte &amp; 0x7f) &lt;&lt; shift
      if (input_byte &amp; 0x80) == 0:
          # Do not allow additional leading zero bits.
          assert(input_byte != 0 || consumed_bytes == 0)
          break
      shift += 7
  return (ret, consumed_bytes)

# This helper parses the jumpdest table into a list of relative offsets
# This will abort on truncated (short) input
def parse_table(input: bytes) -&gt; list[int]:
  jumpdests = []
  pos = 0
  while pos &lt; len(input):
      value, consumed_bytes = leb128u_decode(input[pos:])
      jumpdests.append(value)
      pos += consumed_bytes
  return jumpdests

# This helper translates the delta offsets into absolute ones
# This will abort on invalid 0-value entries
def process_jumpdests(delta: list[int]) -&gt; list[int]:
    jumpdests = []
    partial_sum = 0
    first = True
    for d in delta:
        if first:
            first = False
        else:
            assert(d != 0)
        partial_sum += d
        jumpdests.append(partial_sum)
    return jumpdests

# Fails with assertion on invalid code
# Expects list of absolute jumpdest offsets
def validate_code(code: bytes, jumpdests: list[int]):
    pos = 0
    while pos &lt; len(code):
        # Ensure the opcode is valid
        opcode = code[pos]
        pos += 1
        assert(opcode in valid_opcodes)

        # Remove touched offset
        try:
            jumpdests.remove(pos)
        except ValueError:
            pass

        # Skip pushdata
        if opcode &gt;= 0x60 and opcode &lt;= 0x7f:
            pos += opcode - 0x60 + 1

    # Ensure last PUSH doesn&apos;t go over code end
    assert(pos == len(code))

    # The table is invalid if there are untouched locations
    assert(len(jumpdests) == 0)
```

## Test Cases

#### Valid bytecodes

- No jumpdests
- Every byte is a jumpdest
- Distant jumpdests (0x7f and 0x3f01 bytes apart)
- Max number of jumpdests
    - 1-byte offset encoding: initcode of max size (64K) with jumpdest at each byte - table contains 65536 1-byte offsets, first one is 0x00, all others equal 0x01
    - 2-byte offset encoding: inicode of max size with jumpdests 0x80 (128) bytes apart - table contains 512 offsets, first one is 0x7f (127), all others equal 0x8001
    - 3-byte offset encoding: inicode of max size with jumpdests 0x4000 (16384) bytes apart - table contains 4 offsets: 0xFF7F (16383), 0x808001, 0x808001, 0x808001

#### Invalid bytecodes

- Empty jumpdest section
- Multiple jumpdest sections
- jumpdest section after the code section
- jumpdest section after the data section
- Final jumploc in the table is truncated (not a valid LEB128)
- LEB128 encoding with extra 0s (non-minimal encoding)
- Jumpdest location pointing to PUSH data
- Jumpdest location out of code section bounds
    - pointing into data section
    - pointing into jumpdest section
    - pointing outside container bounds
- Duplicate jumpdest locations (0 deltas in table other than 1st offset)
- Code containing `JUMP` but no jumpdest table
- Code containing `JUMPI` but no jumpdest table
- Code containing jumpdest table but not `JUMP`/`JUMPI`
- Code containing `JUMPDEST`

## Backwards Compatibility

This change poses no risk to backwards compatibility, as it is introduced at the same time EIP-3540 is. The requirement of a JUMPDEST table does not cover legacy bytecode.

## Security Considerations

The authors are not aware of any security or DoS risks posed by this change.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 23 Jun 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3690</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3690</guid>
      </item>
    
      <item>
        <title>Remove Support for Type 1 Transactions</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3709-deprecate-type-1-transactions/6810</comments>
        
        <description>## Simple Summary

Deprecates usage of [EIP-2718](/EIPs/EIPS/eip-2718) `TransactionType` 1 in wallets and providers, upgrading all type 1 transactions to a type 2 transaction.

## Abstract

Since both `TransactionType` 1 and 2 contain `access_list`, we propose the removal of offering `TransactionType` 1 from wallets and providers, instead the transaction will be converted to `TransactionType` 2 to make use of the new gas properties introduced by [EIP-1559](/EIPs/EIPS/eip-1559).

## Motivation

[EIP-2930](/EIPs/EIPS/eip-2930) was introduced as the first `TransactionType`, type 1, with the intention of adding `access_list` to the `TransactionPayload`. [EIP-1559](/EIPs/EIPS/eip-1559) introduced the second `TransactionType` 2, which is represented as `rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, amount, data, access_list, signature_y_parity, signature_r, signature_s])`. The intention behind EIP-1559 was to enhance the user experience surrounding gas fees, and as we move forward we expect that the majority of the network will begin to using `TransactionType` 2 instead of the legacy style transactions. `TransactionType` 1 is a legacy transaction with the addition of `access_list` meaning that users will not benefit from enhancements made by EIP-1559. `TransactionType` 2 contains `access_list`, thus there is no reason to further support `TransactionType` 1 if the end goal is to push users towards using `TransactionType` 2 anyway.


## Specification

For wallets and providers, if a user submits a transaction for signing with where `TransactionType == 0x1`, the developer should upgrade the transaction to meet the criteria of transaction of type 2.

The following fields need to be changed, or amended:
- `access_list`: Nothing changes and it should remain in the transaction.
- `type`: Should change from `0x1` to `0x2`.
- `gas_price`: Should be removed in favour of `max_fee_per_gas` &amp; `max_priority_fee_per_gas` (see [EIP-1559](/EIPs/EIPS/eip-1559) for proper usage).

## Rationale

Improve the user experience for submitting transactions, and move away from legacy style transactions.

## Security Considerations

There are no known security considerations at this time.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 07 Aug 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3709</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3709</guid>
      </item>
    
      <item>
        <title>Poster</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-poster-a-ridiculously-simple-general-purpose-social-media-smart-contract/6751</comments>
        
        <description># Poster

## Abstract
A ridiculously simple general purpose social media smart contract.
It takes two strings (`content` and `tag`) as parameters and emits those strings, along with msg.sender, as an event. That&apos;s it.
The EIP also includes a proposed standard json format for a Twitter-like application, where each `post()` call can include multiple posts and/or operations. The assumption being that application state will be constructed off-chain via some indexer.

## Motivation
Poster is intended to be used as a base layer for decentralized social media. It can be deployed to the same address (via the singleton factory) on just about any EVM compatible network. Any Ethereum account can make posts to the deployment of Poster on its local network.

## Specification

### Contract

```solidity
contract Poster {

    event NewPost(address indexed user, string content, string indexed tag);

    function post(string calldata content, string calldata tag) public {
        emit NewPost(msg.sender, content, tag);
    }
}
```

### ABI
```json
[
    {
      &quot;anonymous&quot;: false,
      &quot;inputs&quot;: [
        {
          &quot;indexed&quot;: true,
          &quot;internalType&quot;: &quot;address&quot;,
          &quot;name&quot;: &quot;user&quot;,
          &quot;type&quot;: &quot;address&quot;
        },
        {
          &quot;indexed&quot;: false,
          &quot;internalType&quot;: &quot;string&quot;,
          &quot;name&quot;: &quot;content&quot;,
          &quot;type&quot;: &quot;string&quot;
        },
        {
          &quot;indexed&quot;: true,
          &quot;internalType&quot;: &quot;string&quot;,
          &quot;name&quot;: &quot;tag&quot;,
          &quot;type&quot;: &quot;string&quot;
        }
      ],
      &quot;name&quot;: &quot;NewPost&quot;,
      &quot;type&quot;: &quot;event&quot;
    },
    {
      &quot;inputs&quot;: [
        {
          &quot;internalType&quot;: &quot;string&quot;,
          &quot;name&quot;: &quot;content&quot;,
          &quot;type&quot;: &quot;string&quot;
        },
        {
          &quot;internalType&quot;: &quot;string&quot;,
          &quot;name&quot;: &quot;tag&quot;,
          &quot;type&quot;: &quot;string&quot;
        }
      ],
      &quot;name&quot;: &quot;post&quot;,
      &quot;outputs&quot;: [],
      &quot;stateMutability&quot;: &quot;nonpayable&quot;,
      &quot;type&quot;: &quot;function&quot;
    }
]
```

### Standard json format for Twitter-like posts

```json
{
  &quot;content&quot;: [
    {
      &quot;type&quot;: &quot;microblog&quot;,
      &quot;text&quot;: &quot;this is the first post in a thread&quot;
    },
    {
      &quot;type&quot;: &quot;microblog&quot;,
      &quot;text&quot;: &quot;this is the second post in a thread&quot;,
      &quot;replyTo&quot;: &quot;this[0]&quot;
    },
    {
      &quot;type&quot;: &quot;microblog&quot;,
      &quot;text&quot;: &quot;this is a reply to some other post&quot;,
      &quot;replyTo&quot;: &quot;some_post_id&quot;
    },
    {
      &quot;type&quot;: &quot;microblog&quot;,
      &quot;text&quot;: &quot;this is a post with an image&quot;,
      &quot;image&quot;: &quot;ipfs://ipfs_hash&quot;
    },
    {
      &quot;type&quot;: &quot;microblog&quot;,
      &quot;text&quot;: &quot;this post replaces a previously posted post&quot;,
      &quot;edit&quot;: &quot;some_post_id&quot;
    },
    {
      &quot;type&quot;: &quot;delete&quot;,
      &quot;target&quot;: &quot;some_post_id&quot;
    },
    {
      &quot;type&quot;: &quot;like&quot;,
      &quot;target&quot;: &quot;some_post_id&quot;
    },
    {
      &quot;type&quot;: &quot;repost&quot;,
      &quot;target&quot;: &quot;some_post_id&quot;
    },
    {
      &quot;type&quot;: &quot;follow&quot;,
      &quot;target&quot;: &quot;some_account&quot;
    },
    {
      &quot;type&quot;: &quot;unfollow&quot;,
      &quot;target&quot;: &quot;some_account&quot;
    },
    {
      &quot;type&quot;: &quot;block&quot;,
      &quot;target&quot;: &quot;some_account&quot;
    },
    {
      &quot;type&quot;: &quot;report&quot;,
      &quot;target&quot;: &quot;some_account or some_post_id&quot;
    },
    {
      &quot;type&quot;: &quot;permissions&quot;,
      &quot;account&quot;: &quot;&lt;account_to_set_permissions&gt;&quot;,
      &quot;permissions&quot;: {
        &quot;post&quot;: true,
        &quot;delete&quot;: true,
        &quot;like&quot;: true,
        &quot;follow&quot;: true,
        &quot;block&quot;: true,
        &quot;report&quot;: true,
        &quot;permissions&quot;: true
      }
    },
    {
      &quot;type&quot;: &quot;microblog&quot;,
      &quot;text&quot;: &quot;This is a post from an account with permissions to post on behalf of another account.&quot;,
      &quot;from&quot;: &quot;&lt;from_address&gt;&quot;
    }
  ]
}

```

## Rationale
There was some discussion around whether or not an post ID should also be emitted, whether the content should be a string or bytes, and whether or not anything at all should actually be emitted.

We decided not to emit an ID, since it meant adding state or complexity to the contract and there is a fairly common pattern of assigning IDs on the indexer layer based on transactionHash + logIndex.

We decided to emit a string, rather than bytes, simply because that would make content human readable on many existing interfaces, like Etherscan for example. This did, unfortunately, eliminate some of the benefit that we might have gotten from a more compact encoding scheme like CBOR, rather than JSON. But this also would not have satisfied the human readable criteria.

While there would have been some gas savings if we decided against emitting anything at all, it would have redically increased the node requirements to index posts. As such, we decided it was worth the extra gas to actually emit the content.

## Reference Implementation

Poster has been deployed at `0x000000000000cd17345801aa8147b8D3950260FF` on multiple networks using the [Singleton Factory](https://eips.ethereum.org/EIPS/eip-2470). If it is not yet deployed on your chosen network, you can use the Singleton Factory to deploy an instance of Poster at the same address on just about any EVM compatible network using these parameters:

&gt; **initCode:** `0x608060405234801561001057600080fd5b506101f6806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80630ae1b13d14610030575b600080fd5b61004361003e3660046100fa565b610045565b005b8181604051610055929190610163565b60405180910390203373ffffffffffffffffffffffffffffffffffffffff167f6c7f3182d7e4cb876251f9ae1489975fdbbf15d9f35d393f2ac9b1ff57cec69f86866040516100a5929190610173565b60405180910390a350505050565b60008083601f8401126100c4578182fd5b50813567ffffffffffffffff8111156100db578182fd5b6020830191508360208285010111156100f357600080fd5b9250929050565b6000806000806040858703121561010f578384fd5b843567ffffffffffffffff80821115610126578586fd5b610132888389016100b3565b9096509450602087013591508082111561014a578384fd5b50610157878288016100b3565b95989497509550505050565b6000828483379101908152919050565b60006020825282602083015282846040840137818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016010191905056fea2646970667358221220ee0377bd266748c5dbaf0a3f15ebd97be153932f2d14d460d9dd4271fee541b564736f6c63430008000033`
&gt;
&gt; **salt:** `0x9245db59943806d06245bc7847b3efb2c899d11b621a0f01bb02fd730e33aed2`

When verifying on the source code on a block explorer, make sure to set the optimizer to `yes` and the runs to `10000000`.

The source code is available in the [Poster contract repo](https://github.com/ETHPoster/contract/blob/master/contracts/Poster.sol).


## Security Considerations
Given the ridiculously simple implementation of Poster, there does not appear to be any real security concerns at the contract level.

At the application level, clients should confirm that posts including a `&quot;from&quot;` field that differs from `msg.sender` have been authorized by the `&quot;from&quot;` address via a `&quot;permissions&quot;` post, otherwise they should be considerred invalid or a post from `msg.sender`.

Clients should also be sure to sanitize post data.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 31 Jul 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3722</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3722</guid>
      </item>
    
      <item>
        <title>A Vanilla Non-Fungible Token Standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/3753</comments>
        
        <description>## Abstract
In this standard, a non-fungible token stands as atomic existence and encourages
layers of abstraction built on top of it. Ideal for representing concepts like
rights, a form of abstract ownership. Such right can take the form of NFT options,
oracle membership, virtual coupons, etc., and can then be made liquid because of
this tokenization.

## Motivation
Non-fungible tokens are popularized by the [ERC-721](/EIPs/EIPS/eip-721) NFT standard
for representing &quot;ownership over digital or physical assets&quot;. Over the course of
development, reputable NFT projects are about crypto-assets, digital collectibles,
etc. The proposed standard aims to single out a special type of NFTs that are
ideal for representing abstract ownership such as rights. Examples include the
right of making a function call to a smart contract, an NFT option that gives
the owner the right, but not obligation, to purchase an ERC-721 NFT, and the prepaid
membership (time-dependent right) of accessing to data feeds provided by oracles
without having to pay the required token fees. An on-chain subscription business
model can then be made available by this standard. The conceptual clarity of an
NFT is hence improved by this standard.

## Specification
```
interface IERC3754 {
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    function balanceOf(address owner) external view returns (uint256);
    function ownerOf(uint256 tokenId) external view returns (address);
    function approve(address to, uint256 tokenId) external;
    function getApproved(uint256 tokenId) external view returns (address);
    function setApprovalForAll(address operator, bool approved) external;
    function isApprovedForAll(address owner, address operator) external view returns (bool);
    function transferFrom(address from, address to, uint256 tokenId) external;
    function safeTransferFrom(address from, address to, uint256 tokenId) external;
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) external;
}
```

## Rationale
The NFTs defined in the [ERC-721](/EIPs/EIPS/eip-721) standard are already largely
accepted and known as representing ownership of digital assets, and the NFTs by
this standard aim to be accepted and known as representing abstract ownership.
This is achieved by allowing and encouraging layers of abstract utilities built
on top of them. Ownership of such NFTs is equivalent with having the rights to
perform functions assigned to such tokens. Transfer of such rights is also made
easier because of this tokenization. To further distinguish this standard
from [ERC-721](/EIPs/EIPS/eip-721), data fields and functions related to `URI` are
excluded.

## Backwards Compatibility
There is no further backwards compatibility required.

## Reference Implementation
https://github.com/simontianx/ERC3754

## Security Considerations
The security is enhanced from ERC721, given tokens are minted without having to
provide `URI`s. Errors in dealing with `URI`s can be avoided.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 21 Aug 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3754</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3754</guid>
      </item>
    
      <item>
        <title>Gas Limit Cap</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3756-gas-limit-cap/6921</comments>
        
        <description>## Abstract

Set an in-protocol cap for the gas limit of 30,000,000.

## Motivation

A high gas limit increases pressure on the network. In the benign case, it
increases the size of the state and history faster than we can sustain. In the
malicious case, it amplifies the devastation of certain denial-of-service
attacks.

## Specification

As of the fork block `N`, consider blocks with a `gas_limit` greater than
`30,000,000` invalid.

## Rationale

### Why Cap the Gas Limit

The gas limit is currently under the control of block proposers. They have the
ability to increase the gas limit to whatever value they desire. This allows
them to bypass the EIP and All Core Devs processes in protocol decisions that
may negatively affect the security and/or decentralization of the network.

### No Fixed Gas Limit

A valuable property of proposers choosing the gas limit is they can scale it
down quickly if the network becomes unstable or is undergoing certain types of
attacks. For this reason, we maintain their ability to lower the gas limit
_below_ 30,000,000.

## Backwards Compatibility
No backwards compatibility issues.

## Test Cases
TBD

## Security Considerations
No security considerations.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 21 Aug 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3756</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3756</guid>
      </item>
    
      <item>
        <title>Chain-specific addresses</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/chain-specific-addresses/6449</comments>
        
        <description>## Abstract

[ERC-3770](/EIPs/EIPS/eip-3770) introduces a new address standard to be adapted by wallets and dApps to display chain-specific addresses by using a human-readable prefix.

## Motivation

The need for this proposal emerges from the increasing adoption of non-Ethereum Mainnet chains that use the Ethereum Virtual Machine (EVM). In this context, addresses become ambiguous, as the same address may refer to an EOA on chain X or a smart contract on chain Y. This will eventually lead to Ethereum users losing funds due to human error. For example, users sending funds to a smart contract wallet address which was not deployed on a particular chain.

Therefore we should prefix addresses with a unique identifier that signals to Dapps and wallets on what chain the target account is. In theory, this prefix could be a [EIP-155](/EIPs/EIPS/eip-155) chainID. However, these chain IDs are not meant to be displayed to users in dApps or wallets, and they were optimized for developer interoperability, rather than human readability.

## Specification

This proposal extends addresses with a human-readable blockchain short name.

### Syntax

A chain-specific address is prefixed with a chain shortName, separated with a colon sign (:).

Chain-specific address = &quot;`shortName`&quot; &quot;`:`&quot; &quot;`address`&quot;

- `shortName` = STRING

- `address` = STRING

### Semantics

* `shortName` is mandatory and MUST be a valid chain short name from https://github.com/ethereum-lists/chains
* `address` is mandatory and MUST be a [ERC-55](/EIPs/EIPS/eip-55) compatible hexadecimal address

### Examples

![Chain-specific addresses](../assets/eip-3770/examples.png &quot;Examples of chain-specific addresses&quot;)

## Rationale

To solve the initial problem of user-facing addresses being ambiguous in a multichain context, we need to map EIP-155 chain IDs with a user-facing format of displaying chain identifiers.

## Backwards Compatibility

Ethereum addresses without the chain specifier will continue to require additional context to understand which chain the address refers to.

## Security Considerations

Similar looking chain short names can be used to confuse users.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 26 Aug 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3770</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3770</guid>
      </item>
    
      <item>
        <title>Compressed Integers</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/3772</comments>
        
        <description>## Abstract

This document specifies compression of `uint256` to smaller data structures like `uint64`, `uint96`, `uint128`, for optimizing costs for storage. The smaller data structure (represented as `cintx`) is divided into two parts, in the first one we store `significant` bits and in the other number of left `shift`s needed on the significant bits to decompress. This document also includes two specifications for decompression due to the nature of compression being lossy, i.e. it causes underflow.

## Motivation

- Storage is costly, each storage slot costs almost $0.8 to initialize and $0.2 to update (20 gwei, 2000 ETHUSD).
- Usually, we store money amounts in `uint256` which takes up one entire slot.
- If it&apos;s DAI value, the range we work with most is 0.001 DAI to 1T DAI (or 10&lt;sup&gt;12&lt;/sup&gt;). If it&apos;s ETH value, the range we work with most is 0.000001 ETH to 1B ETH. Similarly, any token of any scale has a reasonable range of 10&lt;sup&gt;15&lt;/sup&gt; amounts that we care/work with.
- However, uint256 type allows us to represent $10&lt;sup&gt;-18&lt;/sup&gt; to $10&lt;sup&gt;58&lt;/sup&gt;, and most of it is a waste. In technical terms, we have the probability distribution for values larger than $10&lt;sup&gt;15&lt;/sup&gt; and smaller than $10&lt;sup&gt;-3&lt;/sup&gt; as negligible (i.e. P[val &gt; 10&lt;sup&gt;15&lt;/sup&gt;] ≈ 0 and P[val &lt; 10&lt;sup&gt;-3&lt;/sup&gt;] ≈ 0).
- Number of bits required to represent 10&lt;sup&gt;15&lt;/sup&gt; values = log&lt;sub&gt;2&lt;/sub&gt;(10&lt;sup&gt;15&lt;/sup&gt;) = 50 bits. So just 50 bits (instead of 256) are reasonably enough to represent a practical range of money, causing a very negligible difference.

## Specification

In this specification, the structure for representing a compressed value is represented using `cintx`, where x is the number of bits taken by the entire compressed value. On the implementation level, an `uintx` can be used for storing a `cintx` value.

### Compression

#### uint256 into cint64 (up to cint120)

The rightmost, or least significant, 8 bits in `cintx` are reserved for storing the shift and the rest available bits are used to store the significant bits starting from the first `1` bit in `uintx`.

```solidity
struct cint64 { uint56 significant; uint8 shift; }

// ...

struct cint120 { uint112 significant; uint8 shift; }
```

#### uint256 into cint128 (up to cint248)

The rightmost, or least significant, 7 bits in `cintx` are reserved for storing the shift and the rest available bits are used to store the significant bits starting from the first one bit in `uintx`.

&gt; In the following code example, `uint7` is used just for representation purposes only, but it should be noted that uints in Solidity are in multiples of 8.

```solidity
struct cint128 { uint121 significant; uint7 shift; }

// ...

struct cint248 { uint241 significant; uint7 shift; }
```

Examples:

```
Example:
uint256 value: 2**100, binary repr: 1000000...(hundred zeros)
cint64 { significant: 10000000...(55 zeros), shift: 00101101 (45 in decimal)}

Example:
uint256 value: 2**100-1, binary repr: 111111...(hundred ones)
cint64 { significant: 11111111...(56 ones), shift: 00101100 (44 in decimal) }
```

### Decompression

Two decompression methods are defined: a normal `decompress` and a `decompressRoundingUp`.

```solidity
library CInt64 {
    // packs the uint256 amount into a cint64
    function compress(uint256) internal returns (cint64) {}

    // unpacks cint64, by shifting the significant bits left by shift
    function decompress(cint64) internal returns (uint256) {}

    // unpacks cint64, by shifting the significant bits left by shift
    // and having 1s in the shift bits
    function decompressRoundingUp(cint64) internal returns (uint256) {}
}
```

#### Normal Decompression

The `significant` bits in the `cintx` are moved to a `uint256` space and shifted left by `shift`.

&gt; NOTE: In the following example, cint16 is used for visual demonstration purposes. But it should be noted that it is definitely not safe for storing money amounts because its significant bits capacity is 8, while at least 50 bits are required for storing money amounts.

```
Example:
cint16{significant:11010111, shift:00000011}
decompressed uint256: 11010111000 // shifted left by 3

Example:
cint64 { significant: 11111111...(56 ones), shift: 00101100 (44 in decimal) }
decompressed uint256: 1111...(56 ones)0000...(44 zeros)
```

#### Decompression along with rounding up

The `significant` bits in the `cintx` are moved to a `uint256` space and shifted left by `shift` and the least significant `shift` bits are `1`s.

```
Example:
cint16{significant:11011110, shift:00000011}
decompressed rounded up value: 11011110111 // shifted left by 3 and 1s instead of 0s

Example:
cint64 { significant: 11111111...(56 ones), shift: 00101100 (44 in decimal) }
decompressed uint256: 1111...(100 ones)
```

This specification is to be used by a new smart contract for managing its internal state so that any state mutating calls to it can be cheaper. These compressed values on a smart contract&apos;s state are something that should not be exposed to the external world (other smart contracts or clients). A smart contract should expose a decompressed value if needed.

## Rationale

- The `significant` bits are stored in the most significant part of `cintx` while `shift` bits in the least significant part, to help prevent obvious dev mistakes. For e.g. a number smaller than 2&lt;sup&gt;56&lt;/sup&gt;-1 its compressed `cint64` value would be itself if the arrangement were to be opposite than specified. If a developer forgets to uncompress a value before using it, this case would still pass if the compressed value is the same as decompressed value.
- It should be noted that using `cint64` doesn&apos;t render gas savings automatically. The solidity compiler needs to pack more data into the same storage slot.
- Also the packing and unpacking adds some small cost too.
- Though this design can also be seen as a binary floating point representation, however using floating point numbers on EVM is not in the scope of this ERC. The primary goal of floating point numbers is to be able to represent a wider range in an available number of bits, while the goal of compression in this ERC is to keep as much precision as possible. Hence, it specifies for the use of minimum exponent/shift bits (i.e 8 up to `uint120` and 7 up to `uint248`).

```solidity
// uses 3 slots
struct UserData1 {
    uint64 amountCompressed;
    bytes32 hash;
    address beneficiary;
}

// uses 2 slots
struct UserData2 {
    uint64 amountCompressed;
    address beneficiary;
    bytes32 hash;
}
```

## Backwards Compatibility

There are no known backward-incompatible issues.

## Reference Implementation

On the implementation level `uint64` may be used directly, or with custom types introduced in 0.8.9.

```soldity
function compress(uint256 full) public pure returns (uint64 cint) {
    uint8 bits = mostSignificantBitPosition(full);
    if (bits &lt;= 55) {
        cint = uint64(full) &lt;&lt; 8;
    } else {
        bits -= 55;
        cint = (uint64(full &gt;&gt; bits) &lt;&lt; 8) + bits;
    }
}

function decompress(uint64 cint) public pure returns (uint256 full) {
    uint8 bits = uint8(cint % (1 &lt;&lt; 9));
    full = uint256(cint &gt;&gt; 8) &lt;&lt; bits;
}

function decompressRoundingUp(uint64 cint) public pure returns (uint256 full) {
    uint8 bits = uint8(cint % (1 &lt;&lt; 9));
    full = uint256(cint &gt;&gt; 8) &lt;&lt; bits + ((1 &lt;&lt; bits) - 1);
}
```

The above gist has `library CInt64` that contains demonstrative logic for compression, decompression, and arithmetic for `cint64`. The gist also has an example contract that uses the library for demonstration purposes.

The CInt64 format is intended only for storage, while dev should convert it to uint256 form using suitable logic (decompress or decompressRoundingUp) to perform any arithmetic on it.

## Security Considerations

The following security considerations are discussed:

1. Effects due to lossy compression
   - Error estimation for `cint64`
   - Handling the error
2. Losing precision due to incorrect use of `cintx`
3. Compressing something other than money `uint256`s.

### 1. Effects due to lossy compression

When a value is compressed, it causes underflow, i.e. some less significant bits are sacrificed. This results in a `cintx` value whose decompressed value is less than or equal to the actual `uint256` value.

```solidity
uint a = 2**100 - 1; // 100 # of 1s in binary format
uint c = a.compress().decompress();

a &gt; c; // true
a - (2**(100 - 56) - 1) == c; // true

// Visual example:
// before: 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
// after:  1111111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000
```

#### Error estimation for cint64

Let&apos;s consider we have a `value` of the order 2&lt;sup&gt;m&lt;/sup&gt; (less than 2&lt;sup&gt;m&lt;/sup&gt; and greater than or equal to 2&lt;sup&gt;m-1&lt;/sup&gt;).

For all values such that 2&lt;sup&gt;m&lt;/sup&gt; - 1 - (2&lt;sup&gt;m-56&lt;/sup&gt; - 1) &lt;= `value` &lt;= 2&lt;sup&gt;m&lt;/sup&gt; - 1, the compressed value `cvalue` is 2&lt;sup&gt;m&lt;/sup&gt; - 1 - (2&lt;sup&gt;m-56&lt;/sup&gt; - 1).

The maximum error is 2&lt;sup&gt;m-56&lt;/sup&gt; - 1, approximating it to decimal: 10&lt;sup&gt;n-17&lt;/sup&gt; (log&lt;sub&gt;2&lt;/sub&gt;(56) is 17). Here `n` is number of decimal digits + 1.

For e.g. compressing a value of the order $1,000,000,000,000 (or 1T or 10&lt;sup&gt;12&lt;/sup&gt;) to `cint64`, the maximum error turns out to be 10&lt;sup&gt;12+1-17&lt;/sup&gt; = $10&lt;sup&gt;-4&lt;/sup&gt; = $0.0001. This means the precision after 4 decimal places is lost, or we can say that the uncompressed value is at maximum $0.0001 smaller. Similarly, if someone is storing $1,000,000 into `cint64`, the uncompressed value would be at maximum $0.0000000001 smaller. In comparison, the storage costs are almost $0.8 to initialize and $0.2 to update (20 gwei, 2000 ETHUSD).

#### Handling the error

Note that compression makes the value slightly smaller (underflow). But we also have another operation that also does that. In integer math, the division is a lossy operation (causing underflow). For instance,

```solidity
10000001 / 2 == 5000000 // true
```

The result of the division operation is not always exact, but it&apos;s smaller than the actual value, in some cases as in the above example. Though, most engineers try to reduce this effect by doing all the divisions at the end.

```
1001 / 2 * 301 == 150500 // true
1001 * 301 / 2 == 150650 // true
```

The division operation has been in use in the wild, and plenty of lossy integer divisions have taken place, causing DeFi users to get very very slightly less withdrawal amounts, which they don&apos;t even notice. If been careful, then the risk is very negligible. Compression is similar, in the sense that it is also a division by 2&lt;sup&gt;shift&lt;/sup&gt;. If been careful with this too, the effects are minimized.

In general, one should follow the rule:

1. When a smart contract has to transfer a compressed amount to a user, they should use a rounded down value (by using `amount.decompress()`).
2. When a smart contract has to transferFrom a compressed amount from a user to itself, i.e charging for some bill, they should use a rounded up value (by using `amount.decompressUp()`).

The above ensures that smart contract does not loose money due to the compression, it is the user who receives less funds or pays more funds. The extent of rounding is something that is negligible enough for the user. Also just to mention, this rounding up and down pattern is observed in many projects including UniswapV3.

### 2. Losing precision due to incorrect use of `cintx`

This is an example where dev errors while using compression can be a problem.

Usual user amounts mostly have an max entropy of 50, i.e. 10&lt;sup&gt;15&lt;/sup&gt; (or 2&lt;sup&gt;50&lt;/sup&gt;) values in use, that is the reason why we find uint56 enough for storing significant bits. However, let&apos;s see an example:

```solidity
uint64 sharesC = // reading compressed value from storage;
uint64 price = // CALL;
uint64 amountC = sharesC.cmuldiv(price, PRICE_UNIT);
user.transfer(amountC.uncompress());
```

The above code results in a serious precision loss. `sharesC` has an entropy of 50, as well as `priceC` also has an entropy of 50. When we multiply them, we get a value that contains entropies of both, and hence, an entropy of 100. After multiplication is done, `cmul` compresses the value, which drops the entropy of `amountC` to 56 (as we have uint56 there to store significant bits).

To prevent entropy/precision from dropping, we get out from compression.

```solidity
uint64 sharesC = shares.compress();
uint64 priceC = price.compress();
uint256 amount = sharesC.uncompress() * price / PRICE_UNIT;
user.transfer(amount);
```

Compression is only useful when writing to storage while doing arithmetic with them should be done very carefully.

### 3. Compressing something other than money `uint256`s.

Compressed Integers is intended to only compress money amount. Technically there are about 10&lt;sup&gt;77&lt;/sup&gt; values that a `uint256` can store but most of those values have a flat distribution i.e. the probability is 0 or extremely negligible. (What is a probability that a user would be depositing 1000T DAI or 1T ETH to a contract? In normal circumstances it doesn&apos;t happen, unless someone has full access to the mint function). Only the amounts that people work with have a non-zero distribution ($0.001 DAI to $1T or 10&lt;sup&gt;15&lt;/sup&gt; to 10&lt;sup&gt;30&lt;/sup&gt; in uint256). 50 bits are enough to represent this information, just to round it we use 56 bits for precision.

Using the same method for compressing something else which have a completely different probability distribution will likely result in a problem. It&apos;s best to just not compress if you&apos;re not sure about the distribution of values your `uint256` is going to take. And also, for things you think you are sure about using compression for, it&apos;s better to give more thought if compression can result in edge cases (e.g. in previous multiplication example).

### 4. Compressing Stable vs Volatile money amounts

Since we have a dynamic `uint8 shift` value that can move around. So even if you wanted to represent 1 Million SHIBA INU tokens or 0.0002 WBTC (both $10 as of this writing), cint64 will pick its top 56 significant bits which will take care of the value representation.

It can be a problem for volatile tokens if the coin is extremely volatile wrt user&apos;s native currency. Imagine a very unlikely case where a coin goes 2&lt;sup&gt;56&lt;/sup&gt;x up (price went up by 10&lt;sup&gt;16&lt;/sup&gt; lol). In such cases `uint56` might not be enough as even its least significant bit is very valuable. If such insanely volatile tokens are to be stored, you should store more significant bits, i.e. using `cint96` or `cint128`.

`cint64` has 56 bits for storing significant, when only 50 were required. Hence there are 6 extra bits, which means that it is fine if the $ value of the cryptocurrency stored in cint64 increases by 2&lt;sup&gt;6&lt;/sup&gt; or 64x. If the value goes down it&apos;s not a problem.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 27 Aug 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3772</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3772</guid>
      </item>
    
      <item>
        <title>Safer Control Flow for the EVM</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3779-safe-control-flow-for-the-evm/6975</comments>
        
        <description>## Abstract

We define a safe EVM contract as one that cannot encounter an exceptional halting state.  In general, we cannot prove safety for Turing-complete programs. But we can prove a useful subset.

This EIP specifies validity rules to ensure that:
&gt; Valid contracts will not halt with an exception unless they either
&gt; * throw `out of gas` or
&gt; * recursively overflow stack.

This EIP does not introduce any new opcodes.  Rather, it restricts the use of existing and proposed control-flow instructions.  The restrictions must be validated at contract initialization time – not at runtime – by the provided algorithm or its equivalent. This algorithm must take time and space near-linear in the size of the contract, so as not to be a denial of service vulnerability.

This specification is entirely semantic.  It imposes no further syntax on bytecode, as none is required to ensure the specified level of safety.  Ethereum Virtual Machine bytecode is just that -- a sequence of bytes that when executed causes a sequence of changes to the machine state.  The safety we seek here is simply to not, as it were, jam up the gears.

## Motivation

### Safety

For our purposes we define a safe EVM contract as one that cannot encounter an exceptional halting state.  From the standpoint of security it would be best if unsafe contracts were never placed on the blockchain.  Unsafe code can attempt to overflow stack, underflow stack, execute invalid instructions, and jump to invalid locations.

Unsafe contracts are exploits waiting to happen.

Validating contract safety requires traversing the contract code.  So in order to prevent denial of service attacks all jumps, including the existing `JUMP` and `JUMPI`, and also the other proposed jumps -- `RJUMP`, `RJUMPI`, `RJUMPSUB` and `RETURNSUB` -- must be validated at initialization time, and in time and space linear in the size of the code.

#### Static Jumps and Subroutines

The relative jumps of [EIP-4200](./eip-4200) and the simple subroutines of [EIP-2315](./eip-2315) provide a complete set of static control flow instructions:
&gt; `RJUMP` _offset_
* Jumps to _IP+offset_. 
&gt; `RJUMPI` _offset_
* Jumps if the top of stack is non-zero.
&gt; `RJUMPSUB` offset
* Pushes _IP+1_ on the return stack and jumps to _IP+offset_.
&gt; `RETURNSUB`
* Jumps to the address popped off the return stack.

Note that each jump creates at most two paths of control through the code, such that the complexity of traversing the entire control-flow graph is linear in the size of the code.

#### *Dynamic Jumps*

Dynamic jumps, where the destination of a `JUMP` or `JUMPI` is not known until runtime, are an obstacle to proving validity in linear time -- any jump can be to any destination in the code, potentially requiring time quadratic in the size of code. For this reason we have two real choices.

1. Deprecate dynamic jumps. This is easily done:

&gt; Define `JUMP` and `JUMPI` as `INVALID` for the purposes of EOF Code Validation

2. Constrain dynamic jumps. This requires static analysis.

Consider the simplest and most common case.
```
PUSH address
JUMP
```
This is effectively a static jump.

Another important use of `JUMP` is to implement the return jump from a subroutine. So consider this example of calling and returning from a minimal subroutine:
```
TEST_SQUARE:
    jumpdest
    push RTN_SQUARE 
    0x02
    push SQUARE
    jump
RTN_SQUARE
    jumpdest
    swap1
    jump

SQUARE:
    jumpdest
    dup1
    mul
    swap1
    jump
```
The return address -`RTN_SQUARE` - and the destination address - `SQUARE` - are pushed on the stack as constants and remain unchanged as they move on the stack, such that only those constants are passed to each `JUMP`. They are effectively static.  We can track the motion of constants on the `data stack` at validation time, so *we do not need unconstrained dynamic jumps to implement subroutines.*

*The above is the simplest analysis that suffices.  A more powerful analysis that takes in more use cases is possible -- slower, but still linear-time.*

#### Validation

We can validate the safety of contracts with a static analysis that takes time and space linear in the size of the *code*, as shown below.  And since we can, we should.

### Performance

Validating safe control flow at initialization time has potential performance advantages.
* Static jumps do not need to be checked at runtime.
* Stack underflow does not need to be checked for at runtime.

## Specification

### Validity

&gt; In theory, theory and practice are the same. In practice, they&apos;re not. -- Albert Einstein

We define a _safe_ EVM contract as one that cannot encounter an exceptional halting state.  We validate _safety_ at initialization time to the extent practical.

#### *Exceptional Halting States*

The *execution* of each instruction is defined in the Yellow Paper as a change to the EVM state that preserves the invariants of EVM state.  At runtime, if the execution of an instruction would violate an invariant the EVM is in an exceptional halting state.  The Yellow Paper defined five such states.
1. Insufficient gas
2. More than 1024 stack items
3. Insufficient stack items
4. Invalid jump destination
5. Invalid instruction

*A program is safe iff no execution can lead to an exceptional halting state.*

*We would like to consider EVM programs valid iff they are safe.*

*In practice*, we must be able to validate *code* in linear time to avoid denial of service attacks. And we must support dynamically-priced instructions, loops, and recursion, which can use arbitrary amounts of gas and stack. 

Thus our validation cannot consider concrete computations -- it only performs a limited symbolic execution of the _code_.  This means we will reject programs if we detect any invalid execution paths, even if those paths are not reachable at runtime.  And we will count as valid programs that may not always produce correct results.

We can detect only _non-recursive_ stack overflows at *validation time*, so we must check for the first two states at _runtime_:
* `out of gas` and
* stack overflow.

The remaining three states we can check at *validation time*:
* stack underflow,
* invalid jump, and
* invalid instruction.

That is to say:
&gt; Valid contracts will not halt with an exception unless they either
&gt; * throw `out of gas` or
&gt; * recursively overflow stack.

#### *Constraints on Valid Code*

* Every instruction is valid.
* Every jump is valid:
   * Every`JUMP` and `JUMPI` is *static*.
   * No `JUMP`, `JUMPI`, `RJUMP`, `RJUMPI`, or `RJUMPSUB` addresses immediate data.
* The stacks are always valid:
   * The _number_ of items on the `data stack` is always positive, and at most 1024.
   * The _number_ of items on the `return stack` is always positive, and at most 1024.
* The data stack is consistently aligned:
   * The _number_ of items on the `data stack` between the current `stack pointer` and the `stack pointer` on entry to the most recent basic block is the same for each _execution_ of a _byte_code_.

We define a `JUMP` or `JUMPI` instruction to be *static* if its `jumpsrc` argument was first placed on the stack via a `PUSH…` and that value has not changed since, though it may have been copied via a `DUP…` or `SWAP…`.

The `RJUMP`, `RJUMPI` and `RJUMPSUB`instructions take their destination as an immediate argument, so they are *static*.

Taken together, these rules allow for code to be validated by traversing the control-flow graph, in time and space linear in the size of the code, following each edge only once. 

_Note: The definition of &apos;static&apos; for `JUMP` and `JUMPI` is the bare minimum needed to implement subroutines.  Deeper analyses could be proposed that would validate a larger and probably more useful set of jumps, at the cost of more expensive (but still linear) validation._


## Rationale

Demanding *static* destinations for all jumps means that all jump destinations can be validated at initialization time, not runtime.

Bounding the stack pointers catches all `data stack` and non-recursive`return stack` overflows.

Requiring a consistently aligned`data stack` prevents stack underflow. It can also catch such errors as misaligned stacks due to irreducible control flows and calls to subroutines with the wrong number of arguments.

## Backwards Compatibility

These changes affect the semantics of EVM code – the use of `JUMP`, `JUMPI`, and the stack are restricted, such that some *code* that would otherwise run correctly will nonetheless be invalid EVM *code*. 

## Reference Implementation 

The following is a pseudo-Go implementation of an algorithm for predicating code validity.  An equivalent algorithm must be run at initialization time.  

This algorithm performs a symbolic execution of the program that recursively traverses the _code_, emulating its control flow and stack use and checking for violations of the rules above.

It runs in time equal to `O(vertices + edges)` in the program&apos;s control-flow graph, where edges represent control flow and the vertices represent _basic blocks_ -- thus the algorithm takes time proportional to the size of the _code_.

_Note: All valid code has a control-flow graph that can be traversed in time and space linear in the length of the code.  That means that some other static analyses and code transformations that might otherwise require quadratic time can also be written to run in near-linear time, including one-pass and streaming compilers._  

### Validation Function

***Note:** This function is a work in progress, and the version below is known to be incorrect.*  

For simplicity&apos;s sake we assume that _jumpdest analysis_ has been done and that we have some helper functions.
* `isValidInstruction(pc)` returns true if `pc` points at a valid instruction
* `isValidJumpdest(dest)` returns true if `dest` is a valid jumpdest
* `immediateData(pc)` returns the immediate data for the instruction at `pc`.
* `advancePC(pc)` returns next `pc`,  skipping any immediate data.
* `removed_items(pc)` returns the number of items removed from the `dataStack` by the instruction at `pc`.
* `added_items(pc)` returns the number of items added to the `dataStack` by the instruction at `pc`.

```
var bytecode      [codeLen]byte
var subMin        [codeLen]int
var subMax        [codeLen]int
var subDelta      [codeLen]int
var visited       [codeLen]bool
var dataStack     [1024]int

// validate a path through the control flow of the bytecode at pc
// and return the maximum number of stack items used down that path
// or else the PC and an error
//
// by starting at pc:=0 the entire program is recursively evaluated
//
func validate(pc := 0, sp := 0, rp := 0) int, error {
   minStack := 0 
   maxStack := 0 
   deltaStack := 0 
   for pc &lt; codeLen {
      if !isValidInstruction(pc) {
         return 0,0,0,invalid_instruction
      }
      
      // if we have jumped here before return to break cycle
      if visited[pc] {

          // stack is not aligned if deltas not the same
          if ??? {
            return 0,0,0,invalid_stack
          }
          return minStack, maxStack, sp
      }
      visited[pc] = true
      switch bytecode[pc] {

      // successful termination
      case STOP:
         return minStack, maxStack, sp
      case RETURN:
         return minStack, maxStack, sp

      case SELFDESTRUCT:
         return minStack, maxStack, sp
      case REVERT:
         return minStack, maxStack, sp
      case INVALID:
         return 0,0,0,invalid_instruction
    
      case RJUMP:

         // check for valid jump destination
         if !isValidJumpdest(jumpdest) {
            return 0,0,0,invalid_destination
         }
         
         // reset pc to destination of jump
         pc += immediateData(pc)

      case RJUMPI:
      
         // recurse to validate true side of conditional
         jumpdest = pc + immediateData(pc)
         if !isValidJumpdest(pc + jumpdest) {
            return 0,0,0,invalid_destination
         }
         minRight, maxLeft, deltaRight, err =
            validate(jumpdest, sp, rp)
  
     err {
            return 0,0,0,err
         }
         
         // recurse to validate false side of conditional
         pc = advancePC(pc)
         minRight, maxRight, deltaRight, err =
            validate(pc, sp, rp)
         if err {
            return 0,0,0,err
         }
         
         // both paths valid, so return max
         minStack = min(minStack, min(minLeft, minRight))
         maxStack += max(maxLeft, maxRight)
         deltaStack += max(deltaLeft, deltaRight)
         return minStack, maxStack, deltaStack

      case RJUMPSUB:

         // check for valid jump destination
         jumpdest = immediateData(pc)
         if !isValidJumpdest(pc + jumpdest) {
            return 0,0,0,invalid_destination
         }

         pc += jumpdest

         // recurse to validate subroutine call
         minSub, maxSub, deltaSub, err = validate(jumpdest, sp, rp)
         if err {
            return 0,0,0,err
         }
         subMin[pc] = minSub
         subMax[pc] = maxSub
         subDelta[pc] = deltaSub
         minStack = min(minStack, sp)
         maxStack = max(maxStack, sp)
         pc = advancePC(pc)

      case RETURNSUB:
      
         maxStack = max(maxStack, sp)
         return minStack, maxStack, sp, nil

      /////////////////////////////////////////////////////
      //
      // The following are to be included only if we take
      //
      //    Option 2
      //
      // and do not deprecate JUMP and JUMPI
      //
      case JUMP:
         // pop jump destination
         jumpdest = dataStack[--sp]
         if !valid_jumpdest(jumpdest) {
            return 0,0,0,invalid_destination
         }
         pc = jumpdest
      case JUMPI:
         // pop jump destination and conditional
         jumpdest = dataStack[--sp]
         jumpif = dataStack[--sp]
         if sp &lt; 0 {}
            return 0,0,0,stack_underflow
         }
         if !valid_jumpdest(jumpdest) {
            return 0,0,0,invalid_destination
         }

         // recurse to validate true side of conditional
         if !isValidJumpdest(jumpdest) {
            return 0,0,0,invalid_destination
         }
         maxLeft, err = validate(jumpdest, sp, rp)
         if err {
            return 0,0,0,err
         }
         
         // recurse to validate false side of conditional
         pc = advance_pc(pc)
         maxRight, err = validate(pc, sp, rp)
         if err {
            return 0,0,0,err
         }
         
         // both sides valid, return max
         maxStack += max(maxLeft, maxRight)
         return minStack, maxStack, sp
      case PUSH1 &lt;= bytecode[pc] &amp;&amp; bytecode[pc] &lt;= PUSH32 {
         sp++
         if (sp &gt; 1023) {
            return 0,0,0,stack_overflow
         }
         maxStack = max(maxStack, sp)
         dataStack[sp] = immediateData(pc)
         pc = advancePC(pc)
      case DUP1 &lt;= bytecode[pc] &amp;&amp; bytecode[pc] &lt;= DUP32 {
         dup = sp - (bytecode[pc] - DUP1)
         if dup &lt; 0 {
            return 0,0,0,stack_underflow
         }
         sp++
         if (sp &gt; 1023) {
            return 0,0,0,stack_overflow
         }
         maxStack = max(maxStack, sp)
         dataStack[sp] = dataStack[dup]
         pc = advancePC(pc)
      case SWAP1 &lt;= bytecode[pc] &amp;&amp; bytecode[pc] &lt;= SWAP32 {
         swap = sp - (bytecode[pc] - SWAP1)
         if swap &lt; 0 {
            return 0,0,0,stack_underflow
         }
         temp := dataStack[swap]
         dataStack[swap] = dataStack[0]
         dataStack[0] = temp
         pc = advancePC(pc)
      //
      /////////////////////////////////////////////////////

      default:

         // apply other instructions to stack pointer
         sp -= removed_items(pc)
         if (sp &lt; 0) {
            return 0,0,0,stack_underflow
         }
         minStack = min(minStack, sp)
         sp += added_items(pc)
         if (sp &gt; 1023) {
            return 0,0,0,stack_overflow
         }
         maxStack = max(maxStack, sp)
         pc = advancePC(pc)
      }
   }

   // successful termination
   return minStack, maxStack, sp
}
```
## Security Considerations

This EIP is intended to ensure an essential level of safety for EVM code deployed on the blockchain.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Mon, 30 Aug 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3779</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3779</guid>
      </item>
    
      <item>
        <title>Strict enforcement of chainId</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/discussion-to-eip-3788-strict-enforcement-of-chainid/7001</comments>
        
        <description>## Abstract

Reject transactions that do not explicitly have the same chainId as the node&apos;s configuration.

## Motivation

Per [EIP-155](/EIPs/EIPS/eip-155) a transaction with a `chainId = 0` is considered to be a valid 
transaction. This was a feature to offer developers the ability to submit replayable transactions 
across different chains. With the rise of evm compatible chains, many of which use forks, or packages
from popular Ethereum clients, we are putting user funds at risk. This is because most wallet
interfaces do not expose the chainId to the user, meaning they typically do not have insight
into what chainId they are signing. Should a malicious actor (or accidental) choose to, they
can easily have users submit transactions with a `chainId = 0` on a non-mainnet network, allowing
the malicious actor to replay the transaction on ethereum mainnet (or other networks for that matter)
as a grief or sophisticated attack.

## Specification

As of the fork block `N`, consider transactions with a `chaindId = 0` to be invalid. Such that 
transactions are verified based on the nodes configuration. Eg:
```
if (node.cfg.chainId != tx.chainId) {
    // Reject transaction
}
```

## Rationale

The configuration set by the node is the main source of truth, and thus should be explicitly used
when deciding how to filter out a transaction. This check should exist in two places, as a filter
on the JSON-RPC (eg: `eth_sendTransaction`), and strictly enforced on the EVM during transaction 
validation.

This ensures that users will not have transactions pending that will be guaranteed to fail, and
prevents the transaction from being included in a block.

## Backwards Compatibility
This breaks all applications or tooling that submit transactions with a `chainId == 0` after block number `N`.

## Test Cases
TBD

## Security Considerations
It should be noted this will not prevent a malicious actor from deploying a network with `chainId = 1`, or copying any other networks chainId.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 02 Sep 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3788</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3788</guid>
      </item>
    
      <item>
        <title>PUSH0 instruction</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3855-push0-instruction/7014</comments>
        
        <description>## Abstract

Introduce the `PUSH0` (`0x5f`) instruction, which pushes the constant value 0 onto the stack.

## Motivation

Many instructions expect offsets as inputs, which in a number of cases are zero. A good example is the return data parameters of `CALLs`, which are set to zeroes in case the contract prefers using `RETURNDATA*`. This is only one example, but there are many other reasons why a contract would need to push a zero value. They can achieve that today by `PUSH1 0`, which costs 3 gas at runtime, and is encoded as two bytes which means `2 * 200` gas deployment cost.

Because of the overall cost many try to use various other instructions to achieve the same effect. Common examples include `PC`, `MSIZE`, `CALLDATASIZE`, `RETURNDATASIZE`, `CODESIZE`, `CALLVALUE`, and `SELFBALANCE`. Some of these cost only 2 gas and are a single byte long, but their value can depend on the context.

We have conducted an analysis on Mainnet (block ranges 8,567,259…8,582,058 and 12,205,970…12,817,405), and ~11.5% of all the `PUSH*` instructions executed push a value of zero.

The main motivations for this change include:
1. Reducing contract code size.
2. Reducing the risk of contracts (mis)using various instructions as an optimisation measure. Repricing/changing those instructions can be more risky.
3. Reduce the need to use `DUP` instructions for duplicating zeroes.

To put the &quot;waste&quot; into perspective, across existing accounts 340,557,331 bytes are wasted on `PUSH1 00` instructions, which means 68,111,466,200 gas was spent to deploy them. In practice a lot of these accounts share identical bytecode with others, so their total stored size in clients is lower, however the deploy time cost must have been paid nevertheless.

An example for 2) is changing the behaviour of `RETURNDATASIZE` such that it may not be guaranteed to be zero at the beginning of the call frame. 

## Specification

The instruction `PUSH0` is introduced at `0x5f`. It has no immediate data, pops no items from the stack, and places a single item with the value 0 onto the stack. The cost of this instruction is 2 gas (aka `base`).

## Rationale

### Gas cost

The `base` gas cost is used for instructions which place constant values onto the stack, such as `ADDRESS`, `ORIGIN`, and so forth.

### Opcode

`0x5f` means it is in a &quot;contiguous&quot; space with the rest of the `PUSH` implementations and potentially could share the implementation.

## Backwards Compatibility

This EIP introduces a new opcode which did not exist previously. Already deployed contracts using this opcode could change their behaviour after this EIP.

## Test Cases

- `5F` -- successful execution, stack consist of a single item, set to zero
- `5F5F..5F` (1024 times) -- successful execution, stack consists of 1024 items, all set to zero
- `5F5F..5F` (1025 times) -- execution aborts due to out of stack

## Security Considerations

The authors are not aware of any impact on security. Note that jumpdest-analysis is unaffected, as `PUSH0` has no immediate data bytes.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 19 Feb 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3855</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3855</guid>
      </item>
    
      <item>
        <title>Limit and meter initcode</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3860-limit-and-meter-initcode/7018</comments>
        
        <description>## Abstract

We extend [EIP-170](/EIPs/EIPS/eip-170) by introducing a maximum size limit for `initcode` (`MAX_INITCODE_SIZE = 2 * MAX_CODE_SIZE = 49152`).

Furthermore, we introduce a charge of `2` gas for every 32-byte chunk of `initcode` to represent the cost of jumpdest-analysis.

Lastly, the size limit results in the nice-to-have property that EVM code size, code offset (`PC`), and jump offset fits a 16-bit value.

## Motivation

During contract creation the client has to perform jumpdest-analysis on the `initcode` prior to execution. The work performed scales linearly with the size of the `initcode`. This work currently is not metered, nor is there a protocol enforced upper bound for the size.

There are three costs charged today:

1. Cost for calldata aka `initcode`: 4 gas for a byte with the value of zero, and 16 gas otherwise.
2. Cost for the resulting deployed code: 200 gas per byte.
3. Cost of address calculation (hashing of code) in case of `CREATE2` only: 6 gas per word.

Only the first cost applies to `initcode`, but only in the case of contract creation transactions. For the case of `CREATE`/`CREATE2` there is no such cost, and it is possible to programmatically generate variations of `initcode` in a relatively cheap manner. In the past it was possible to craft malicious `initcode` due to a vulnerability fixed in 2017 by geth 1.6.5.

Furthermore, the lack of a limit has caused lengthy discussions for some EVM proposals, influencing the design, or even causing a delay or cancellation of a feature.

We are motivated by three reasons:

1. Ensuring `initcode` is fairly charged (most importantly cost is proportional to `initcode`&apos;s length) to minimize the risks for the future.
2. To have a cost system which is extendable in the future.
3. To simplify EVM engines by the explicit limits (code size, code offsets (`PC`), and jump offsets fit 16-bits).

## Specification

### Parameters

| Constant             | Value               |
| -------------------- | ------------------- |
| `INITCODE_WORD_COST` | `2`                 |
| `MAX_INITCODE_SIZE`  | `2 * MAX_CODE_SIZE` |

Where `MAX_CODE_SIZE` is defined by [EIP-170](/EIPs/EIPS/eip-170) as `24576`.

We define `initcode_cost(initcode)` to equal `INITCODE_WORD_COST * ceil(len(initcode) / 32)`.

### Rules

1. If length of transaction data (`initcode`) in a create transaction exceeds `MAX_INITCODE_SIZE`, transaction is invalid. (*Note that this is similar to transactions considered invalid for not meeting the intrinsic gas cost requirement.*)
2. For a create transaction, extend the transaction data cost formula to include `initcode_cost(initcode)`. (*Note that this is included in transaction intrinsic cost, i.e. transaction with not enough gas to cover initcode cost is invalid.*)
3. If length of `initcode` to `CREATE` or `CREATE2` instructions exceeds `MAX_INITCODE_SIZE`, instruction execution exceptionally aborts (as if it runs out of gas).
4. For the `CREATE` and `CREATE2` instructions charge an extra gas cost equaling to `initcode_cost(initcode)`. This cost is deducted before the calculation of the resulting contract address and the execution of `initcode`. (*Note that this means before or at the same time as the hashing cost is applied in `CREATE2`.*)

## Rationale

### Gas cost constant

The value of `INITCODE_WORD_COST` is selected based on performance benchmarks of differing worst-cases per implementation. The baseline for the benchmarks is the performance of `KECCAK256` hashing in geth 1.10.9, which matches the 70 Mgas/s gas limit target on a 4.0 GHz x86_64 CPU.

| EVM             | version | MB/s | B/CPUcycle | CPUcycle/B | cost of 1 B | cost of 32 B |
| --------------- | ------- | ---- | ---- | ---- | ---- | ---- |
| geth/KECCAK256  | 1.10.9  |  357 |  1.8 |  0.6 |  0.2 |  6.0 |
| geth            | 1.10.9  | 1091 |  5.5 |  0.2 |  0.1 |  2.0 |
| evmone/Baseline | 0.8.2   |  727 |  3.7 |  0.3 |  0.1 |  2.9 |
| evmone/Advanced | 0.8.2   |  155 |  0.8 |  1.3 |  0.4 | 13.8 |

### Gas cost per word (32-byte chunk)

We have chosen the cost of 2 gas per word based on Geth&apos;s implementation and comparing with `KECCAK256` performance. This means the per byte cost is `0.0625`. While fractional gas costs are not permitted in the EVM, we can approximate it by charging per-word.

Moreover, calculating gas per word is compatible with the calculation of `CREATE2`&apos;s *hashcost* of [EIP-1014](/EIPs/EIPS/eip-1014). Therefore, the same implementation may be used for `CREATE` and `CREATE2` with different cost constants: before activation `0` for `CREATE` and `6` for `CREATE2`, after activation `2` for `CREATE` and `6 + 2` for `CREATE2`.

### Reason for size limit of initcode

Estimating and creating worst case scenarios is easier with an upper bound in place, given one parameter for the search is greatly reduced. This allows for selecting a much more optimistic gas per byte.

Should there be no upper bound, the cost would need to be higher accounting for unknown unknowns. Given most *initcode* (*TODO: state maximum initcode size resulting in deployment seen on mainnet here*) does not exceed the proposed limit, penalising contracts by overly conservative costs seems unnecessary.

### Effect of size limit of initcode

In most, if not all cases when a new contract is being created, the resulting runtime code is copied from the initcode itself. For the basic case the `2 * MAX_CODE_SIZE` limit allows `MAX_CODE_SIZE` for runtime code and another `MAX_CODE_SIZE` for contract constructor code. However, the limit may have practical implications for cases where multiple contracts are deployed in a single create transaction.

### Initcode cost for create transaction

The initcode cost for create transaction data (0.0625 gas per byte) is negligible compared to the transaction data cost (4 or 16 gas per byte). Despite that, we decided to include it in the specification for consistency, and more importantly for forward compatibility.

### How to report initcode limit violation?

We specified that initcode size limit violation for `CREATE`/`CREATE2` results in exceptional abort of the execution. This places it in the group of early out-of-gas checks, including: stack underflow, memory expansion, static call violation, initcode hashing cost, and initcode cost introduced by this EIP. They precede the later &quot;light&quot; checks: call depth and balance. The choice gives consistency to the order of checks and lowers implementation complexity (out-of-gas checks can be performed in any order).

## Backwards Compatibility

This EIP requires a &quot;network upgrade&quot;, since it modifies consensus rules.

Already deployed contracts should not be affected, but certain transactions (with `initcode` beyond the proposed limit) would still be includable in a block, but result in an exceptional abort.

## Test Cases

Tests should include the following cases:

- Creation transaction with gas limit enough to cover initcode cost
- Creation transaction with gas limit enough to cover intrinsic cost except initcode cost
- `CREATE`/`CREATE2`/creation transaction with `len(initcode)` at `MAX_INITCODE_SIZE`
- `CREATE`/`CREATE2`/creation transaction with `len(initcode)` at `MAX_INITCODE_SIZE+1`

## Security Considerations

For client implementations, this EIP makes attacks based on jumpdest-analysis less problematic, so should increase the robustness of clients.

For layer 2, this EIP introduces failure-modes where there previously were none. There *could* exist factory-contracts which deploy multi-level contract hierarchies, such that the code for multiple contracts are included in the initcode of the first contract. The author(s) of this EIP are not aware of any such contracts.

Currently, on London, with `30M` gas limit, it would be possible to trigger jumpdest-analysis of a total `~1.3GB` of initcode. With this EIP, the cost for such an attack would increase by roughly `80M` gas.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 16 Jul 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3860</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3860</guid>
      </item>
    
      <item>
        <title>Gas refunds on reverts</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-3978-gas-refunds-on-reverts/7071/</comments>
        
        <description>## Abstract

For reverted state modification operations, keep access cost, but refund modification cost.

## Motivation

Reverting a transaction, or any of its sub-calls, drops any state modifications that happened inside.
But now, users are being charged for the dropped modifications as if they persisted.

Since [EIP-3298](/EIPs/EIPS/eip-3298), the gas refund mechanism works for storage restores only inside the same transaction. But on revert, the gas refund is not increased; it is completely erased.
It can even be cheaper to transfer tokens back at the end of a transaction instead of reverting, to keep the existing gas refund.
This should be changed.

- Reverted SSTORE deserves to be repriced to SLOAD gas (100 gas)
- Reverted LOG0, LOG1, LOG2, LOG3 and LOG4 deserve to be repriced to 100 gas
- Reverted CALL with value (`positive_value_cost` = 9,000 gas) deserves to be repriced to 100 gas
- Reverted CALL with value and account creation (`value_to_empty_account_cost` = 25,000 gas) deserves to be repriced to 100 gas
- Reverted CREATE and CREATE2 (32,000 gas) deserve to be repriced to 100 gas
- Reverted SELFDESTRUCT (5,000 or 25,000 gas) deserves to be repriced to 100 gas

Moreover, it seems fair to charge CREATE and CREATE2 operations 32,000 fix price conditionally only if returned bytecode is not empty.


## Specification
For each callframe, track `revert_gas_refund`, initially 0.

The set of operations that modify `revert_gas_refund` are:
- SSTORE
- LOG0, LOG1, LOG2, LOG3, LOG4
- CALL
- CREATE, CREATE2
- SELFDESTRUCT

They increase `revert_gas_refund` as follows:
```javascript
call.revert_gas_refund += operation.gas - WARM_STORAGE_READ_COST
```

And in case of revert let&apos;s use this value instead of just erasing `gas_refund`:
```javascript
if (call.reverted) {
    // existing behavior
    tx.gas_refund -= call.gas_refund;
    
    // New behavior added to existing according to the EIP-3978
    tx.gas_refund += call.revert_gas_refund;
}
```

## Rationale

Gas should reflect the cost of use.
The revert cost reflects the cost of access during execution, but not the cost of modification.

## Backwards Compatibility

No known backward incompatibilities.

## Test Cases

TBD

## Reference Implementation

TBD

## Security Considerations

TBD

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 16 Sep 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-3978</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-3978</guid>
      </item>
    
      <item>
        <title>EOF - Static relative jumps</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4200-static-relative-jumps/7108</comments>
        
        <description>## Abstract

Three new EVM jump instructions are introduced (`RJUMP`, `RJUMPI` and `RJUMPV`) which encode destinations as signed immediate values. These can be useful in the majority of (but not all) use cases and offer a cost reduction.

## Motivation

A recurring discussion topic is that EVM only has a mechanism for dynamic jumps. They provide a very flexible architecture with only 2 (!) instructions. This flexibility comes at a cost however: it makes analysis of code more complicated and it also (partially) resulted in the need to have the `JUMPDEST` marker.

In a great many cases control flow is actually static and there is no need for any dynamic behaviour, though not every use case can be solved by static jumps.

There are various ways to reduce the need for dynamic jumps, some examples:

1. With native support for functions / subroutines
2. A &quot;return to caller&quot; instruction
3. A &quot;switch-case&quot; table with dynamic indexing

This change does not attempt to solve these, but instead introduces a minimal feature set to allow compilers to decide which is the most adequate option for a given use case. It is expected that compilers will use `RJUMP`/`RJUMPI` almost exclusively, with the exception of returning to the caller continuing to use `JUMP`.

This functionality does not preclude the EVM from introducing other forms of control flow later on. `RJUMP`/`RJUMPI` can efficiently co-exists with a higher-level declaration of functions, where static relative jumps should be used for intra-function control flow.

The main benefit of these instruction is reduced gas cost (both at deploy and execution time) and better analysis properties.

## Specification

We introduce three new instructions on the same block number [EIP-3540](/EIPs/EIPS/eip-3540) is activated on:

1. `RJUMP` (0xe0) - relative jump
2. `RJUMPI` (0xe1) - conditional relative jump
3. `RJUMPV` (0xe2) - relative jump via jump table

If the code is legacy bytecode, all of these instructions result in an *exceptional halt*. (*Note: This means no change to behaviour.*)

If the code is valid EOF1:

1. `RJUMP relative_offset` sets the `PC` to `PC_post_instruction + relative_offset`.
2. `RJUMPI relative_offset` pops a value (`condition`) from the stack, and sets the `PC` to `PC_post_instruction + ((condition == 0) ? 0 : relative_offset)`.
3. `RJUMPV max_index relative_offset+` pops a value (`case`) from the stack, and sets the `PC` to `PC_post_instruction + ((case &gt; max_index) ? 0 : relative_offset[case])`.

The immediate argument `relative_offset` is encoded as a 16-bit **signed** (two&apos;s-complement) big-endian value. Under `PC_post_instruction` we mean the `PC` position after the entire immediate value.

The immediate encoding of `RJUMPV` is more special: the unsigned 8-bit `max_index` value determines the maximum index in the jump table. The number of `relative_offset` values following is `max_index+1`. This allows table sizes up to 256. The encoding of `RJUMPV` must have at least one `relative_offset` and thus it will take at minimum 4 bytes. Furthermore, the `case &gt; max_index` condition falling through means that in many use cases, one would place the *default* path following the `RJUMPV` instruction. An interesting feature is that `RJUMPV 0 relative_offset` is an inverted-`RJUMPI`, which can be used in many cases instead of `ISZERO RJUMPI relative_offset`.

We also extend the validation algorithm of [EIP-3670](/EIPs/EIPS/eip-3670) to verify that each `RJUMP`/`RJUMPI`/`RJUMPV` has a `relative_offset` pointing to an instruction. This means it cannot point to an immediate data of `PUSHn`/`RJUMP`/`RJUMPI`/`RJUMPV`. It cannot point outside of code bounds. It is allowed to point to a `JUMPDEST`, but is not required to.

Because the destinations are validated upfront, the cost of these instructions are less than their dynamic counterparts: `RJUMP` should cost 2, and `RJUMPI` and `RJUMPV` should cost 4.

## Rationale

### Relative addressing

We chose relative addressing in order to support code which is relocatable. This also means a code snippet can be injected. A technique seen used prior to this EIP to achieve the same goal was to inject code like `PUSHn PC ADD JUMPI`.

We do not see any significant downside to relative addressing and it allows us to also deprecate the `PC` instruction.

### Immediate size

The signed 16-bit immediate means that the largest jump distance possible is 32767. In the case the bytecode at `PC=0` starts with an `RJUMP`, it will be possible to jump as far as `PC=32770`.

Given `MAX_CODE_SIZE = 24576` (in [EIP-170](/EIPs/EIPS/eip-170)) and `MAX_INITCODE_SIZE = 49152` (in [EIP-3860](/EIPs/EIPS/eip-3860)), we think the 16-bit immediate is large enough.

A version with an 8-bit immediate would only allow moving `PC` backward by 125 or forward by 127 bytes. While that seems to be a good enough distance for many for-loops, it is likely not good enough for cross-function jumps, and since the 16-bit immediate is the same size as what a dynamic jump would take in such cases (3 bytes: `JUMP PUSH1 n`), we think having less instructions is better.

Should there be a need to have immediate encodings of other size (such as 8-bits, 24-bits or 32-bits), it would be possible to introduce new opcodes, similarly to how multiple `PUSH` instructions exist.

### `PUSHn JUMP` sequences

If we chose absolute addressing, then `RJUMP` could be viewed similar to the sequence `PUSHn JUMP` (and `RJUMPI` similar to `PUSHn JUMPI`). In that case one could argue that instead of introducing a new instruction, such sequences should get a discount, because EVMs could optimise them.

We think this is a bad direction to go:

1. It further complicates the already complex rules of gas calculation.
2. And it either requires a consensus defined internal representation for EVM code, or forces EVM implementations to do optimisations on their own.

Both of these are risky. Furthermore we think that EVM implementations should be free to chose what optimisations they apply, and the savings do not need to be passed down at all cost.

Additionally it requires a potentially significant change to the current implementations which depend on a streaming one-by-one execution without a lookahead.

### Relation to dynamic jumps

The goal was not to completely replace the current control flow system of the EVM, but to augment it. There are many cases where dynamic jumps are useful, such as returning to the caller.

It is possible to introduce a new mechanism for having a pre-defined table of valid jump destinations, and dynamically supplying the index within this table to accomplish some form of dynamic jumps. This is very useful for efficiently encoding a form of &quot;switch-cases&quot; statements. It could also be used for &quot;return to caller&quot; cases, however it is likely inefficient or awkward.

### Lack of `JUMPDEST`

`JUMPDEST` serves two purposes:

1. To efficiently partition code -- this can be useful for pre-calculating total gas usage for a given *block* (i.e. instructions between `JUMPDEST`s), and for JIT/AOT translation.
2. To explicitly show valid locations (otherwise any non-data location would be valid).

This functionality is not needed for static jumps, as the analysers can easily tell destinations from the static jump immediates during jumpdest-analysis.

There are two benefits here:

1. Not wasting a byte for a `JUMPDEST` also means a saving of 200 gas during deployment, for each jump destination.
2. Saving an extra 1 gas per jump during execution, given `JUMPDEST` itself cost 1 gas and is &quot;executed&quot; during jumping.

### `RJUMPV` fallback case

If no match is found (i.e. the *default* case) in the `RJUMPV` instruction execution will continue without branching. This allows for gaps in the arguments to be filled with `0`s, and a choice of implementation by the programmer. Alternate options would include exceptional aborts in case of no match.

## Backwards Compatibility

This change poses no risk to backwards compatibility, as it is introduced at the same time EIP-3540 is. The new instructions are not introduced for legacy bytecode (code which is not EOF formatted).

## Test Cases

### Validation

#### Valid cases

- `RJUMP`/`RJUMPI`/`RJUMPV` with `JUMPDEST` as target
    - `relative_offset` is positive/negative/`0`
- `RJUMP`/`RJUMPI`/`RJUMPV` with instruction other than `JUMPDEST` as target
    - `relative_offset` is positive/negative/`0`
- `RJUMPV` with various valid table sizes from 1 to 256
- `RJUMP` as a final instruction in code section

#### Invalid cases

- `RJUMP`/`RJUMPI`/`RJUMPV` with truncated immediate
- `RJUMPI`/`RJUMPV` as a final instruction in code section
- `RJUMP`/`RJUMPI`/`RJUMPV` target outside of code section bounds
- `RJUMP`/`RJUMPI`/`RJUMPV` target push data
- `RJUMP`/`RJUMPI`/`RJUMPV` target another `RJUMP`/`RJUMPI`/`RJUMPV` immediate argument

### Execution

- `RJUMP`/`RJUMPI`/`RJUMPV` in legacy code aborts execution
- `RJUMP`
    - `relative_offset` is positive/negative/`0`
- `RJUMPI`
    - `relative_offset` is positive/negative/`0`
        - `condition` equals `0`
        - `condition` does not equal `0` 
- `RJUMPV 0 relative_offset`
    - `case` equals `0`
    - `case` does not equal `0` 
- `RJUMPV` with table containing positive, negative, `0` offsets
    - `case` equals `0`
    - `case` does not equal `0` 
    - `case` outside of table bounds (`case &gt; max_index`, fallback case)
    - `case` &gt; 255

## Security Considerations

Adding new instructions with immediate arguments should be carefully considered when implementing the EOF container validation algorithm.

Static relative jump execution does not require runtime check of the jump destination. It greatly reduces execution cost. Therefore the gas cost of the new instructions can also be significantly reduced.

The `RJUMPV` instruction relative offset table can have up to 256 one-byte entries, so reading an offset cannot be a potential attack surface.         

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 16 Jul 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4200</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4200</guid>
      </item>
    
      <item>
        <title>Account Abstraction Using Alt Mempool</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-4337-account-abstraction-via-entry-point-contract-specification/7160</comments>
        
        <description>## Abstract

An account abstraction proposal which completely avoids the need for consensus-layer protocol changes. Instead of adding new protocol features and changing the bottom-layer transaction type, this proposal instead introduces a higher-layer pseudo-transaction object called a `UserOperation`. Users send `UserOperation` objects into a separate mempool. A special class of actor called bundlers package up a set of these objects into a transaction making a `handleOps` call to a special contract, and that transaction then gets included in a block.

## Motivation

Historically, introducing Account Abstraction has been a long-standing goal of the Ethereum protocol.
A number of proposals have been thoroughly discussed, but so far none of them have been implemented in the protocol.

This proposal takes a different approach, avoiding any adjustments to the consensus layer. It seeks to achieve the following goals:

* **Achieve the key goal of Account Abstraction**: allow users to use Smart Contract Accounts containing arbitrary verification logic instead of EOAs as their primary account. Completely remove any need at all for users to also have EOAs,
 as required by both status quo Smart Contract Accounts and [EIP-7702](/EIPs/EIPS/eip-7702).
* **Decentralization**
    * Allow any bundler (think: block builder) to participate in the process of including account-abstracted `UserOperations`
    * Work with all activity happening over a public mempool; users do not need to know the direct communication addresses (eg. IP, onion) of any specific actors
    * Avoid trust assumptions on bundlers
* **Do not require any Ethereum consensus changes**: Ethereum consensus layer development is focusing on scalability-oriented features, and there may not be any opportunity for further protocol changes for a long time. Hence, to increase the chance of faster adoption, this proposal avoids Ethereum consensus changes.
* **Support other use cases**
    * Privacy-preserving applications
    * Atomic multi-operations (similar goal to [EIP-7702](/EIPs/EIPS/eip-7702))
    * Pay tx fees with [ERC-20](/EIPs/EIPS/eip-20) tokens, allow developers to pay fees for their users, and [EIP-7702](/EIPs/EIPS/eip-7702)-like **sponsored transaction** use cases more generally
    * abstracting the validation allows the contract to use different signature schemes, multisig configuration, custom recovery, and more.
    * abstracting gas payments allows easy onboarding by 3rd party payments, paying with tokens, cross-chain gas payments
    * abstracting execution allows bundled transactions

## Specification

### Definitions

* **UserOperation** - a structure that describes a transaction to be sent on behalf of a user. To avoid confusion, it is not named &quot;transaction&quot;.
  * Like a transaction, it contains `to`, `calldata`, `maxFeePerGas`, `maxPriorityFeePerGas`, `nonce`, `signature`.
  * Unlike a transaction, it contains several other fields, described below.
  * Notably, the `signature` field usage is not defined by the protocol, but by the Smart Contract Account implementation.
* **Sender** - the Smart Contract Account sending a `UserOperation`.
* **EntryPoint** - a singleton contract to execute bundles of `UserOperations`. Bundlers should whitelist the supported `EntryPoint`.
* **Bundler** - a node (block builder) that can handle `UserOperations`,
  create a valid `entryPoint.handleOps()` transaction,
  and add it to the block while it is still valid.
  This can be achieved by a number of ways:
  * Bundler can act as a block builder itself.
  * If the bundler is not a block builder, it should work with the block builder through an infrastructure such as `mev-boost`, or any other kind of proposer-builder separation.
* **Paymaster** - a helper contract that agrees to pay for the transaction, instead of the sender itself.
* **Factory** - a helper contract that performs a deployment for a new `sender` contract if necessary.
* **Aggregator** - also known as &quot;authorizer contract&quot; - a contract that enables multiple `UserOperations` to share a single validation. The full design of such contracts is outside the scope of this proposal.
* **Canonical `UserOperation` mempool** - a decentralized permissionless P2P network where bundlers exchange `UserOperations` that are valid and conform with the same shared set of rules applied to the validation code. The full specification of such rules is outside the scope of this proposal.
* **Alternative `UserOperation` mempool** - any other P2P mempool where the validity of `UserOperations` is determined by rules that are different from the shared set of rules, applied to the validation code, in any way.
* **Deposit** - an amount of Ether (or any L2 native currency) that a `Sender` or `Paymaster` contract has transferred to the `EntryPoint` contract intended to pay gas costs of the future `UserOperations`.

### The `UserOperation` structure

To avoid Ethereum consensus changes, we do not attempt to create new transaction types for account-abstracted transactions. Instead, users package up the action they want their Smart Contract Account to take in a struct named `UserOperation`:

| Field                           | Type      | Description                                                                                           |
|---------------------------------|-----------|-------------------------------------------------------------------------------------------------------|
| `sender`                        | `address` | The Account making the `UserOperation`                                                                |
| `nonce`                         | `uint256` | Anti-replay parameter (see &quot;Semi-abstracted Nonce Support&quot; )                                          |
| `factory`                       | `address` | Account Factory for new Accounts OR `0x7702` flag for EIP-7702 Accounts, otherwise `address(0)`       |
| `factoryData`                   | `bytes`   | data for the Account Factory if `factory` is provided OR EIP-7702 initialization data, or empty array |
| `callData`                      | `bytes`   | The data to pass to the `sender` during the main execution call                                       |
| `callGasLimit`                  | `uint256` | The amount of gas to allocate the main execution call                                                 |
| `verificationGasLimit`          | `uint256` | The amount of gas to allocate for the verification step                                               |
| `preVerificationGas`            | `uint256` | Extra gas to pay the bundler                                                                          |
| `maxFeePerGas`                  | `uint256` | Maximum fee per gas (similar to [EIP-1559](/EIPs/EIPS/eip-1559) `max_fee_per_gas`)                          |
| `maxPriorityFeePerGas`          | `uint256` | Maximum priority fee per gas (similar to EIP-1559 `max_priority_fee_per_gas`)                         |
| `paymaster`                     | `address` | Address of paymaster contract, (or empty, if the `sender` pays for gas by itself)                     |
| `paymasterVerificationGasLimit` | `uint256` | The amount of gas to allocate for the paymaster validation code (only if paymaster exists)            |
| `paymasterPostOpGasLimit`       | `uint256` | The amount of gas to allocate for the paymaster post-operation code (only if paymaster exists)        |
| `paymasterData`                 | `bytes`   | Data for paymaster (only if paymaster exists)                                                         |
| `signature`                     | `bytes`   | Data passed into the `sender` to verify authorization                                                 |

Users send `UserOperation` objects to a dedicated `UserOperation` mempool.

To prevent replay attacks, either cross-chain or with multiple `EntryPoint` contract versions,
the `signature` MUST depend on `chainid` and the `EntryPoint` address.

Note that one [EIP-7702](/EIPs/EIPS/eip-7702) &quot;authorization tuple&quot; value can be provided alongside the `UserOperation` struct,
but &quot;authorization tuples&quot; are not included in the `UserOperation` itself.

### `EntryPoint` interface

When passed on-chain, to the `EntryPoint` contract, the `Account` and the `Paymaster`, a &quot;packed&quot; version of the above structure called `PackedUserOperation` is used:

| Field                | Type      | Description                                                                                                           |
|----------------------|-----------|-----------------------------------------------------------------------------------------------------------------------|
| `sender`             | `address` |                                                                                                                       |
| `nonce`              | `uint256` |                                                                                                                       |
| `initCode`           | `bytes`   | concatenation of factory address and factoryData (or empty), or [EIP-7702 data](#support-for-eip-7702-authorizations) |
| `callData`           | `bytes`   |                                                                                                                       |
| `accountGasLimits`   | `bytes32` | concatenation of verificationGasLimit (16 bytes) and callGasLimit (16 bytes)                                          |
| `preVerificationGas` | `uint256` |                                                                                                                       |
| `gasFees`            | `bytes32` | concatenation of maxPriorityFeePerGas (16 bytes) and maxFeePerGas (16 bytes)                                          |
| `paymasterAndData`   | `bytes`   | concatenation of paymaster fields (or empty)                                                                          |
| `signature`          | `bytes`   |                                                                                                                       |


The core interface of the `EntryPoint` contract is as follows:

```solidity
function handleOps(PackedUserOperation[] calldata ops, address payable beneficiary);
```

The `beneficiary` is the address that will be paid with all the gas fees collected during the execution of the bundle.

### Smart Contract Account Interface

The core interface required for the Smart Contract Account to have is:

```solidity
interface IAccount {
  function validateUserOp
      (PackedUserOperation calldata userOp, bytes32 userOpHash, uint256 missingAccountFunds)
      external returns (uint256 validationData);
}
```

The `userOpHash` is a hash over the `userOp` (except `signature`), `entryPoint` and `chainId`.

The Smart Contract Account:

* MUST validate the caller is a trusted `EntryPoint`
* MUST validate that the signature is a valid signature of the `userOpHash`, and
  SHOULD return `SIG_VALIDATION_FAILED` (`1`) without reverting on signature mismatch. Any other error MUST revert.
* SHOULD not return early when returning `SIG_VALIDATION_FAILED` (`1`). Instead, it SHOULD complete the normal flow to enable performing a gas estimation for the validation function.
* MUST pay the `EntryPoint` (caller) at least the `missingAccountFunds` (which might be zero, in case the current `sender`&apos;s deposit is sufficient)
* The `sender` MAY pay more than this minimum to cover future transactions. It can also call `withdrawTo` to retrieve it later at any time.
* The return value MUST be packed of `aggregator`/`authorizer`, `validUntil` and `validAfter` timestamps.
  * `aggregator`/`authorizer` - 0 for valid signature, 1 to mark signature failure. Otherwise, an address of an `aggregator`/`authorizer` contract.
  * `validUntil` is 6-byte timestamp value, or zero for &quot;infinite&quot;. The `UserOperation` is valid only up to this time.
  * `validAfter` is 6-byte timestamp. The `UserOperation` is valid only after this time.
  * In order to specify a validity range using block numbers, both the `validUntil` and `validAfter` need to set their highest bit to 1.
  * **Note:** The validity range can be expressed by two block timestamps or two block numbers, but one timestamp and one block number cannot be mixed in the same UserOperation&apos;s validity range.

The Smart Contract Account MAY implement the interface `IAccountExecute`

```solidity
interface IAccountExecute {
  function executeUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) external;
}
```

This method will be called by the `EntryPoint` with the current UserOperation, instead of executing the `callData` itself directly on the `sender`.

### Semi-abstracted Nonce Support

In Ethereum protocol, the sequential transaction `nonce` value is used as a replay protection method as well as to
determine the valid order of transaction being included in blocks.

It also contributes to the transaction hash uniqueness, as a transaction by the same sender with the same
nonce may not be included in the chain twice.

However, requiring a single sequential `nonce` value is limiting to the senders&apos; ability to define their custom logic
with regard to transaction ordering and replay protection.

Instead of sequential `nonce` we implement a nonce mechanism that uses a single `uint256` nonce value in the `UserOperation`,
but treats it as two values:

* 192-bit &quot;key&quot;
* 64-bit &quot;sequence&quot;

These values are represented on-chain in the `EntryPoint` contract.
We define the following method in the `EntryPoint` interface to expose these values:

```solidity
function getNonce(address sender, uint192 key) external view returns (uint256 nonce);
```

For each `key` the `sequence` is validated by the `EntryPoint` for each UserOperation.
If the nonce validation fails the `UserOperation` is considered invalid and the bundle is reverted.
The `sequence` value is incremented sequentially and monotonically for the `sender` for each UserOperation.
A new `key` can be introduced with an arbitrary value at any point, with its `sequence` starting at `0`.

This approach maintains the guarantee of `UserOperation` hash uniqueness on-chain on the protocol level while allowing
Accounts to implement any custom logic they may need operating on a 192-bit &quot;key&quot; field, while fitting the 32 byte word.

#### Reading and validating the nonce

When preparing the `UserOperation` bundlers may make a view call to this method to determine a valid value for the `nonce` field.

Bundler&apos;s validation of a `UserOperation` SHOULD start with `getNonce` to ensure the transaction has a valid `nonce` field.

If the bundler is willing to accept multiple `UserOperations` by the same sender into their mempool,
this bundler is supposed to track the `key` and `sequence` pair of the `UserOperations` already added in the mempool.

#### Usage examples

1. Classic sequential nonce.

   In order to require the Account to have classic, sequential nonce, the validation function MUST perform:

   ```solidity
   require(userOp.nonce&lt;type(uint64).max)
   ```

2. Ordered administrative events

   In some cases, an account may need to have an &quot;administrative&quot; channel of operations running in parallel to normal
   operations.

   In this case, the account may use a specific `key` when calling methods on the account itself:

   ```solidity
   bytes4 sig = bytes4(userOp.callData[0 : 4]);
   uint key = userOp.nonce &gt;&gt; 64;
   if (sig == ADMIN_METHODSIG) {
       require(key == ADMIN_KEY, &quot;wrong nonce-key for admin operation&quot;);
   } else {
       require(key == 0, &quot;wrong nonce-key for normal operation&quot;);
   }
   ```

### Required `EntryPoint` contract functionality

The `EntryPoint` method is `handleOps`, which handles an array of `UserOperations`

The `EntryPoint`&apos;s `handleOps` function must perform the following steps (we first describe the simpler non-paymaster case). It must make two loops, the **verification loop** and the **execution loop**.
In the verification loop, the `handleOps` call must perform the following steps for each `UserOperation`:

* **Create the `sender` Smart Contract Account if it does not yet exist**, using the `initcode` provided in the `UserOperation`.
  * If the `factory` address is &quot;0x7702&quot;, then the sender MUST be an EOA with an [EIP-7702](/EIPs/EIPS/eip-7702) authorization designation. The `EntryPoint` validates the authorized address matches the one specified in the `UserOperation` signature (see [Support for [EIP-7702] authorizations](#support-for-eip-7702-authorizations)).
  * If the `sender` does not exist, _and_ the `initcode` is empty, or does not deploy a contract at the &quot;sender&quot; address, the call must fail.
  * **WARNING**: If the `sender` does exist, _and_ the `initcode` is _not_ empty, then the `initcode` is ignored.
* calculate the maximum possible fee the `sender` needs to pay based on validation and call gas limits, and current gas values.
* calculate the fee the `sender` must add to its &quot;deposit&quot; in the `EntryPoint`
* **Call `validateUserOp` on the `sender` contract**, passing in the `UserOperation`, its hash and the required fee.
  The Smart Contract Account MUST verify the `UserOperation`&apos;s `signature` parameter, and pay the fee if the `sender` considers the `UserOperation` valid. If any `validateUserOp` call fails, `handleOps` must skip execution of at least that `UserOperation`, and may revert entirely.
* Validate the account&apos;s deposit in the `EntryPoint` is high enough to cover the max possible cost (cover the already-done verification and max execution gas)

In the execution loop, the `handleOps` call must perform the following steps for each `UserOperation`:

* **Call the account with the `UserOperation`&apos;s calldata**. It&apos;s up to the account to choose how to parse the calldata; an expected workflow is for the account to have an `execute` function that parses the remaining calldata as a series of one or more calls that the account should make.
* If the calldata starts with the methodsig `IAccountExecute.executeUserOp`, then the `EntryPoint` must build a calldata by encoding `executeUserOp(userOp,userOpHash)` and call the account using that calldata.
* After the call, refund the account&apos;s deposit with the excess gas cost that was pre-charged.\
 A penalty of `10%` (`UNUSED_GAS_PENALTY_PERCENT`) is applied on the amounts of `callGasLimit` and `paymasterPostOpGasLimit` gas that remains **unused**.\
 This penalty is only applied if the amount of the remaining unused gas is greater than or equal `40000` (`PENALTY_GAS_THRESHOLD`).\
 This penalty is necessary to prevent the `UserOperations` from reserving large parts of the gas space in the bundle but leaving it unused and preventing the bundler from including other `UserOperations`.
* After the execution of all calls, pay the collected fees from all `UserOperations` to the `beneficiary` address provided by the bundler.

![](/EIPs/assets/eip-4337/bundle-seq.svg)

Before accepting a `UserOperation`, bundlers SHOULD use an RPC method to locally call the `handleOps` function on the `EntryPoint`,
to verify that the signature is correct and the `UserOperation` actually pays fees; see the [Simulation section below](#useroperation-simulation) for details.
A node/bundler MUST reject a `UserOperation` that fails the validation, meaning not adding it to the local mempool
and not propagating it to other peers.

### JSON-RPC API for [ERC-4337](./eip-4337)

In order to support sending `UserOperation` objects to bundlers, which in turn propagate them through the P2P mempool,
we introduce a set of JSON-RPC APIs including `eth_sendUserOperation` and `eth_getUserOperationReceipt`.

The full definition of the new JSON-RPC API is outside the scope of this proposal.

### Support for [EIP-712](/EIPs/EIPS/eip-712) signatures

The `userOpHash` is calculated as an [EIP-712] typed message hash with the following parameters:

```solidity
bytes32 constant TYPE_HASH =
    keccak256(
        &quot;EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)&quot;
    );

bytes32 constant PACKED_USEROP_TYPEHASH =
    keccak256(
        &quot;PackedUserOperation(address sender,uint256 nonce,bytes initCode,bytes callData,bytes32 accountGasLimits,uint256 preVerificationGas,bytes32 gasFees,bytes paymasterAndData)&quot;
    );
```

### Support for [EIP-7702](/EIPs/EIPS/eip-7702) authorizations

On networks with [EIP-7702](/EIPs/EIPS/eip-7702) enabled, the `eth_sendUserOperation` method accepts an extra `eip7702Auth` parameter.
If this parameter is set, it MUST be a valid [EIP-7702](/EIPs/EIPS/eip-7702) authorization tuple, and signed by the `sender` address.
The bundler MUST add all required `eip7702Auth` of all `UserOperations` in a bundle to the `authorizationList` and execute
the bundle using a transaction type `SET_CODE_TX_TYPE`.
Additionally, the `UserOperation` hash calculation is updated to include the desired [EIP-7702](/EIPs/EIPS/eip-7702) delegation address.

If the `initCode` field starts with `0x7702` right-padded with 18 zeros, and this account was deployed using an EIP-7702 transaction, then the hash is calculated as follows:

* For the purpose of hash calculation, the first 20 bytes of the `initCode` field of the `UserOperation` are set to account&apos;s EIP-7702 delegate address (fetched with EXTCODECOPY)
* The `initCode` is not used to call a factory contract.
* If the `initCode` is longer than 20 bytes, then the rest of the initCode is used to call an initialization function in the account itself.

Note that a `UserOperation` may still be executed without such `initCode`.
In this case the `EntryPoint` doesn&apos;t hash the current [EIP-7702 delegate](/EIPs/EIPS/eip-7702), and can be potentially executed against a modified account.

Additionally, EIP-7702 defines the gas cost of executing an authorization equal to `PER_EMPTY_ACCOUNT_COST = 25000`.
This gas consumption is not observable on-chain by the `EntryPoint` contract and MUST be included in the `preVerificationGas` value.

### Extension: paymasters

We extend the `EntryPoint` logic to support **paymasters** that can sponsor transactions for other users. This feature can be used to allow application developers to subsidize fees for their users, allow users to pay fees with [ERC-20] tokens and many other use cases. When the `paymasterAndData` field in the `UserOperation` is not empty, the `EntryPoint` implements a different flow for that UserOperation:

![](/EIPs/assets/eip-4337/bundle-seq-pm.svg)

During the verification loop, in addition to calling `validateUserOp`, the `handleOps` execution also must check that the paymaster has enough ETH deposited with the `EntryPoint` to pay for the `UserOperation`, and then call `validatePaymasterUserOp` on the paymaster to verify that the paymaster is willing to pay for the `UserOperation`. Note that in this case, the `validateUserOp` is called with a `missingAccountFunds` of 0 to reflect that the account&apos;s deposit is not used for payment for this `UserOperation`.

If the paymaster&apos;s `validatePaymasterUserOp` returns a non-empty `context` byte array, then `handleOps` must call `postOp` on the paymaster after making the main execution call.
Otherwise, no call is done to the `postOp` function.

Maliciously crafted paymasters could pose a risk of a DoS attack against the system and bundlers should take steps to mitigate it.
As a mitigation, bundlers should use a reputation system for contracts they serve, and the paymaster must either limit its storage usage, or deposit a stake in a reputation system.
Full specification of a reputation system is outside the scope of this proposal.

#### The `paymasterAndData` field encoding and `paymasterSignature`

The `paymasterAndData` field is a byte array that contains a non-standard encoding of the following fields:
* `paymasterAddress` - 20 bytes — the address of the paymaster contract
* `paymasterVerificationGasLimit` - 16 bytes - the gas limit for the verification function
* `postOpGasLimit` - 16 bytes - the gas limit for the postOp function
* `paymasterData` - the data that the paymaster contract will receive in the `validatePaymasterUserOp` call

The following data can optionally be appended to the `paymasterAndData` field:
* `paymasterSignature` - the &quot;signature&quot; value byte array to be checked by the paymaster contract; this value can be provided **without affecting the UserOperation hash**
* `paymasterSignatureLength` - 2 bytes - the exact length of the `paymasterSignature` parameter byte array
* `PAYMASTER_SIG_MAGIC` (`0x22e325a297439656`) - the magic value that is appended to indicate the use of the `paymasterSignature` feature by the UserOperation

Note that as both the `signature` and the `paymasterSignature` fields do not affect the UserOperation hash, the signing by the Sender and the Paymaster can be performed in parallel.

The paymaster interface is as follows:

```solidity
function validatePaymasterUserOp
    (PackedUserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost)
    external returns (bytes memory context, uint256 validationData);

function postOp
    (PostOpMode mode, bytes calldata context, uint256 actualGasCost, uint256 actualUserOpFeePerGas)
    external;

enum PostOpMode {
    opSucceeded, // UserOperation succeeded
    opReverted // UserOperation reverted. paymaster still has to pay for gas.
}
```

The `EntryPoint` must implement the following API to let entities like paymasters have a stake, and thus have more flexibility in their storage access.

```solidity
// add a stake to the calling entity
function addStake(uint32 _unstakeDelaySec) external payable;

// unlock the stake (must wait unstakeDelay before can withdraw)
function unlockStake() external;

// withdraw the unlocked stake
function withdrawStake(address payable withdrawAddress) external;
```

The paymaster must also have a deposit, which the `EntryPoint` will charge `UserOperation` costs from.
The deposit (for paying gas fees) is separate from the stake (which is locked).

The `EntryPoint` must implement the following interface to allow Paymasters (and optionally Accounts) to manage their deposit:

```solidity
// return the deposit of an account
function balanceOf(address account) public view returns (uint256);

// add to the deposit of the given account
function depositTo(address account) public payable;

// add to the deposit of the calling account
receive() external payable;

// withdraw from the deposit of the current account
function withdrawTo(address payable withdrawAddress, uint256 withdrawAmount) external;

// get the currently executing UserOperation hash, or 0 if not called during the execution
function getCurrentUserOpHash() public view returns (bytes32);
```

### Bundler behavior upon receiving a UserOperation

![](/EIPs/assets/eip-4337/bundle-build-full-seq.svg)

Similar to an Ethereum transaction, the offchain flow of a `UserOperation` can be described as follows:
1. Client sends a `UserOperation` to the bundler through an RPC call `eth_sendUserOperation`.
2. Before including the `UserOperation` in the mempool, the bundler runs the *first validation* of the newly received UserOperation. If the `UserOperation` fails validation, the bundler drops it and returns an error in response to `eth_sendUserOperation`.
3. Later, once building a bundle, the bundler takes `UserOperations` from the mempool and runs the *second validation* of a single `UserOperation` on each of them. If it succeeds, it is scheduled for inclusion in the next bundle, and dropped otherwise.
4. Before submitting the new bundle onchain, the bundler performs the *third validation* of the entire `UserOperations` bundle. If any of the `UserOperations` fail validation, the bundler drops them. The bundler should keep track of the peers&apos; reputation. The full design of such a reputation system is outside the scope of this proposal.

When a bundler receives a `UserOperation`, it must first run some basic sanity checks, namely that:

* Either the `sender` is an existing contract, or the `initCode` is not empty (but not both)
* If `initCode` is not empty, parse its first 20 bytes as a factory address or an [EIP-7702](/EIPs/EIPS/eip-7702) flag.\
  Record whether the factory is staked, in case the later simulation indicates that it needs to be. If the factory accesses the global state, it must be staked.
* The `verificationGasLimit` and `paymasterVerificationGasLimits` are lower than `MAX_VERIFICATION_GAS` (`500000`) and the `preVerificationGas` is high enough to pay for the calldata gas cost of serializing the `UserOperation` plus `PRE_VERIFICATION_OVERHEAD_GAS` (`50000`).
* The `paymasterAndData` is either empty, or starts with the **paymaster** address, which is a contract that (i) currently has nonempty code on chain, (ii) has a sufficient deposit to pay for the UserOperation, and (iii) is not currently banned. During simulation, the paymaster&apos;s stake is also checked, depending on its storage usage.
* The `callGasLimit` is at least the cost of a `CALL` with non-zero value.
* The `maxFeePerGas` and `maxPriorityFeePerGas` are above a configurable minimum value that the bundler is willing to accept. At the minimum, they are sufficiently high to be included with the upcoming `block.basefee`.
* The `sender` doesn&apos;t have another `UserOperation` already present in the mempool (or it replaces an existing entry with the same sender and nonce, with a higher `maxPriorityFeePerGas` and an equally increased `maxFeePerGas`).
  Only one `UserOperation` per sender may be included in a single bundle.
  A sender is exempt from this rule and may have multiple `UserOperations` in the mempool and in a bundle if it is staked.
### UserOperation Simulation

We define `UserOperation` simulation, as the offchain view call (or trace call) to the `EntryPoint` contract with the `UserOperation`, and the enforcement of the shared set of rules applied to the validation code, as part of the `UserOperation` validation.

#### Simulation Rationale
To validate a normal Ethereum transaction `tx`, the bundler performs static checks, like:
1. `ecrecover(tx.v, tx.r, tx.s)` has to return a valid EOA
2. `tx.nonce` has to be the current nonce of the recovered EOA
3. `balance` of the recovered EOA has to be sufficient to pay for the transaction
4. `tx.gasLimit` has to be sufficient to cover the intrinsic gas cost of a transaction
5. `chainId` has to match the current chain

All of these checks do not rely on EVM state, and cannot be affected by other Accounts&apos; transactions.

In contrast, `UserOperation` validation rely on EVM state (calls to `validateUserOp`, `validatePaymasterUserOp`), can be changed by other `UserOperations` (or normal Ethereum transactions). Therefore, we introduce simulation as a new mechanism to check its validity.
Intuitively, the aim of the simulation is to ensure the onchain validation code of a `UserOperation` is sandboxed, isolated from other `UserOperations` in the same bundle.

#### Simulation Specification:

To simulate a `UserOperation` validation, the bundler makes a view call to the `handleOps()` method with the `UserOperation` to check.

Simulation should run only on the validation section of the `sender` and `paymaster`, and is not required for the `UserOperation`&apos;s execution.
A bundler MAY add second &quot;always failed&quot; `UserOperation` to the bundle, so that the simulation will 
end as soon as the first UserOperation&apos;s validation complete.

The bundler MUST drop the `UserOperation` if the simulation reverts

The simulated call performs the full validation, by calling:

1. If `initCode` is present, create the `sender` Account.
2. `account.validateUserOp`.
3. if specified a paymaster: `paymaster.validatePaymasterUserOp`.

Either `sender` or `paymaster` may return a time-range (`validAfter`/`validUntil`).
The `UserOperation` MUST be valid at the current time to be considered valid, defined as `validAfter&lt;=block.timestamp`.

A bundler MUST drop a `UserOperation` if it expires too soon and is likely to become invalid before the next block.
To decode the returned time-ranges, the bundler MUST run the validation using tracing, to decode the return value from the `validateUserOp` and `validatePaymasterUserOp` methods.

To prevent DoS attacks on bundlers, they must make sure the validation methods above pass the validation rules, which constrain their usage of opcodes and storage.
The full design of such a shared set of rules, applied to the validation code, is outside the scope of this proposal.

### Estimating `preVerificationGas`

This document does not specify a canonical way to estimate this value,
as it depends on non-permanent network properties such as operation and data gas pricing and the expected bundle size.

However, the requirement is for the estimated value to be sufficient to cover the following costs:

* Base bundle transaction cost. On Ethereum, `21000` gas divided by the number of `UserOperations`.
* The calldata gas cost related to the `UserOperation` as defined in [EIP-2028](/EIPs/EIPS/eip-2028).
* Static `EntryPoint` contract code execution.
* Static memory cost when loading the fixed size fields of the `UserOperation` into EVM memory
* Memory cost (including expansion cost) due to context returned by paymaster `validatePaymasterUserOp` function, if relevant.
  * External call to the `innerHandleOp()` function which is a major part of the `EntryPoint` implementation.
  Note that this value is not static and depends on the `UserOperation`&apos;s position in the bundle.
* [EIP-7702] authorization cost, if any.
* [EIP-7623](/EIPs/EIPS/eip-7623) calldata floor price increase is estimated as follows:
  * Apply the new formula for `tx.gasUsed`, replacing the `execution_gas_used` value with an estimate for value made for this UserOperation.
  * The estimate is calculated as a sum of all verification gas used during simulation (account creation, validation and paymaster validation) and 10% of the sum of execution and `postOp` gas limit.

The bundler MUST require a slack in `PreVerificationGas` value, to accommodate memory expansion costs in the future bundle, and the expected position of the `UserOperation` in it.

### Alternative Mempools

The simulation rules above are strict and prevent the ability of paymasters to grief the system.
However, there might be use cases where specific paymasters can be validated
(through manual auditing) and verified that they cannot cause any problem, while still require relaxing of the opcode rules.
A bundler cannot simply &quot;whitelist&quot; a request from a specific paymaster: if that paymaster is not accepted by all
bundlers, then its support will be sporadic at best.
Instead, we introduce the term &quot;alternate mempool&quot;: a modified validation rules, and procedure of propagating them to other bundlers.

The procedure of using alternate mempools is outside the scope of this proposal.

### Bundling

Bundling is the process where a node/bundler collects multiple `UserOperations` and creates a single transaction to submit on-chain.

During bundling, the bundler MUST:

* Exclude `UserOperations` that access any sender address of another `UserOperation` in the same bundle.
* Exclude `UserOperations` that access any address created by another `UserOperation` validation in the same bundle (via a factory).
* For each paymaster used in the bundle, keep track of the balance while adding `UserOperations`. Ensure that it has sufficient deposit to pay for all the `UserOperations` that use it.

After creating the bundle, before including the transaction in a block, the bundler SHOULD:

* Run `debug_traceCall` with maximum possible gas, to enforce the validation rules on opcode and storage access,
  as well as to verify the entire `handleOps` bundle transaction,
  and use the consumed gas for the actual transaction execution.
* If the call reverted, the bundler MUST use the trace result to find the entity that reverted the call. \
  This is the last entity that is CALL&apos;ed by the `EntryPoint` prior to the revert. \
  (the bundler cannot assume the revert is `FailedOp`)
* If any verification context rule was violated the bundlers MUST treat it the same as
  if this `UserOperation` reverted.
* Remove the offending `UserOperation` from the current bundle and from mempool.
* If the error is caused by a `factory` or a `paymaster`, and the `sender`
  of the `UserOperation` **is not** a staked entity, then issue a &quot;ban&quot; for the guilty factory or paymaster.
* If the error is caused by a `factory` or a `paymaster`, and the `sender`
  of the `UserOperation` **is** a staked entity, do not ban the `factory` / `paymaster` from the mempool.
  Instead, issue a &quot;ban&quot; for the staked `sender` entity.
* Repeat until `debug_traceCall` succeeds.

As staked entries may use some kind of transient storage to communicate data between `UserOperations` in the same bundle,
it is critical that the exact same opcode and precompile banning rules as well as storage access rules are enforced
for the `handleOps` validation in its entirety as for individual `UserOperations`.
Otherwise, attackers may be able to use the banned opcodes to detect running on-chain and trigger a `FailedOp` revert.

When a bundler includes a bundle in a block it must ensure that earlier transactions in the block don&apos;t make any `UserOperation` fail.


### Error codes.

While performing validation, the `EntryPoint` must revert on failures. During simulation, the calling bundler MUST be able to determine which entity (`sender`,`factory` or `paymaster`) caused the failure.
The attribution of a revert to an entity is done using call-tracing: the last entity called by the `EntryPoint` prior to the revert is the entity that caused the revert.
* For diagnostic purposes, the `EntryPoint` must only revert with explicit `SignatureValidationFailed()`, `FailedOp()` or `FailedOpWithRevert()` errors.
* The message of the error starts with event code, AA##
* Event code starting with &quot;AA1&quot; signifies an error during `sender` creation
* Event code starting with &quot;AA2&quot; signifies an error during `sender` validation (`validateUserOp`)
* Event code starting with &quot;AA3&quot; signifies an error during `paymaster` validation (`validatePaymasterUserOp`)


## Rationale

The main challenge with a purely &quot;Smart Contract Accounts&quot; based Account Abstraction system is DoS safety: how can a block builder including an operation make sure that it will actually pay fees, without having to first execute the entire operation?
Requiring the block builder to execute the entire operation opens a DoS attack vector, as an attacker could easily send many operations that pretend to pay a fee but then revert at the last moment after a long execution.
Similarly, to prevent attackers from cheaply clogging the mempool, nodes in the P2P network need to check if an operation will pay a fee before they are willing to forward it.

The first step is a clean separation between validation (acceptance of UserOperation, and acceptance to pay) and execution.
In this proposal, we expect Accounts to have a `validateUserOp` method that takes as input a `UserOperation`, verifies the signature and pays the fee.
Only if this method returns successfully, the execution will happen.

The `EntryPoint`-based approach allows for a clean separation between verification and execution, and keeps Smart Contract Accounts&apos; logic simple. It enforces the simple rule that only after validation is successful and the `UserOperation` can pay, the execution is done and only done once, and also guarantees the fee payment.

### Validation Rules Rationale
The next step is protecting the bundlers from denial-of-service attacks by a mass number of `UserOperations` that appear to be valid (and pay) but that eventually revert, and thus block the bundler from processing valid `UserOperations`.

There are two types of `UserOperations` that can fail validation:
1. `UserOperations` that succeed in initial validation (and accepted into the mempool), but rely on the environment state to fail later when attempting to include them in a block.
2. `UserOperations` that are valid when checked independently but fail when bundled together to be put on-chain.
To prevent such rogue `UserOperations`, the bundler is required to follow a set of shared set of rules applied to the validation code, to prevent such denial-of-service attacks.

### Reputation Rationale

UserOperation&apos;s storage access rules prevent them from interfering with each other.
But &quot;global&quot; entities - paymasters and factories are accessed by multiple `UserOperations`, and thus might invalidate multiple previously valid `UserOperations`.

To prevent abuse, we throttle down (or completely ban for a period of time) an entity that causes invalidation of a large number of `UserOperations` in the mempool.
To prevent such entities from &quot;Sybil-attack&quot;, we require them to stake with the system, and thus make such DoS attack very expensive.
Note that this stake is never slashed. There is no slashing mechanism involved and the only use for the stake in sybil attack prevention.
The stake can be withdrawn at any time after the specified unstake delay.

Unstaked entities are allowed, under the rules below.

When staked, an entity is less restricted in its use of contract storage.

The stake value is not enforced on-chain, but specifically by each bundler while simulating a transaction.

### Paymasters

Paymaster contracts allow the abstraction of gas: having a contract, that is not the sender of the transaction, to pay for the transaction fees.

Paymaster architecture allows them to follow the model of &quot;pre-charge, and later refund&quot;.
E.g. a token-paymaster may pre-charge the user with the max possible price of the transaction, and refund the user with the excess afterwards.

### First-time Smart Contract Account creation

NOTE: for contracts using EIP-7702 this flow is described in [Support for [EIP-7702] authorizations](#support-for-eip-7702-authorizations).

It is an important design goal of this proposal to replicate the key property of EOAs that users do not need to perform some custom action or rely on an existing user to create their Smart Contract Account;
they can simply generate an address locally and immediately start accepting funds.

The Smart Contract Account creation itself is done by a &quot;factory&quot; contract, with some Account-specific data.
The Factory is expected to use `CREATE2 0xF5` (not `CREATE 0xF0`) to create the Account, so that the order of creation of the Accounts doesn&apos;t interfere with the generated addresses.
The `initCode` field (if non-zero length) is parsed as a 20-byte `factory` address, followed by `calldata` to pass to this address.
This method call is expected to create the Account and return its address.
If the factory does use `CREATE2 0xF5` or some other deterministic method to create the Account, it&apos;s expected to return the Account address even if it had already been created.
This comes to make it easier for bundlers to query the address without knowing if the Account has already been deployed, by simulating a call to `entryPoint.getSenderAddress()`, which calls the `factory` under the hood.
When `initCode` is specified, if either the `sender` address points to an existing contract or the `sender` address still does not exist after calling the `initCode`,
then the operation is aborted.
The `initCode` MUST NOT be called directly from the `EntryPoint`, but from another address.
The contract created by this factory method MUST accept a call to `validateUserOp` to validate the `UserOperation`&apos;s signature.
For security reasons, it is important that the generated contract address will depend on the initial signature.
This way, even if someone can deploy an Account at that address, he can&apos;t set different credentials to control it.
The Factory has to be staked if it accesses global storage.
NOTE: In order for the Wallet Application to determine the &quot;counterfactual&quot; address of the Account prior to its creation,
it SHOULD make a static call to the `entryPoint.getSenderAddress()`

## Backwards Compatibility

This ERC does not change the consensus layer, so there are no backwards compatibility issues for Ethereum as a whole. Unfortunately it is not easily compatible with pre-[ERC-4337](/EIPs/EIPS/eip-4337) Smart Contract Accounts, because those Accounts do not have a `validateUserOp` function. If the Smart Contract Account has a function for authorizing a trusted `UserOperation` submitter, then this could be fixed by creating an [ERC-4337](/EIPs/EIPS/eip-4337) compatible Account that re-implements the verification logic as a wrapper and setting it to be the original Account&apos;s trusted `UserOperation` submitter.

## Security Considerations

The `EntryPoint` contract will need to be audited and formally verified, because it will serve as a central trust point for _all_ [ERC-4337]. In total, this architecture reduces auditing and formal verification load for the ecosystem, because the amount of work that individual _accounts_ have to do becomes much smaller (they need only verify the `validateUserOp` function and its &quot;check signature and pay fees&quot; logic) and check that other functions are `msg.sender == ENTRY_POINT` gated (perhaps also allowing `msg.sender == self`), but it is nevertheless the case that this is done precisely by concentrating security risk in the `EntryPoint` contract that needs to be verified to be very robust.

Verification would need to cover two primary claims (not including claims needed to protect paymasters, and claims needed to establish p2p-level DoS resistance):

* **Safety against arbitrary hijacking**: The `EntryPoint` only calls to the `sender` with `userOp.calldata` and only if `validateUserOp` to that specific `sender` has passed.
* **Safety against fee draining**: If the `EntryPoint` calls `validateUserOp` and passes, it also must make the generic call with calldata equal to `userOp.calldata`

### Factory contracts

All `factory` contracts MUST check that all calls to the `createAccount()` function originate from the `entryPoint.senderCreator()` address.

### Paymasters contracts

All `paymaster` contracts MUST check that all calls to the `validatePaymasterUserOp()` and `postOp()` functions originate from the `EntryPoint`.

### Aggregator contracts

All `aggregator` contracts MUST check that all calls to the `validateSignatures()` function originates from the `EntryPoint`.

### EIP-7702 delegated Smart Contract Accounts

All EIP-7702 delegated Smart Contract Account implementations MUST check that all calls to the initialization function originate from the `entryPoint.senderCreator()` address.

There is no way for the `EntryPoint` contract to know whether an EIP-7702 account has been initialized or not, and therefore the EIP-7702 account initialization code, can be called multiple times through `EntryPoint`.
The Account code SHOULD only allow calling it once and the Wallet Application SHOULD NOT pass the `initCode` repeatedly.

### Smart Contract Accounts

#### Storage layout collisions

It is expected that most of ERC-4337 Smart Contract Account will be upgradeable,
either via on-chain delegate proxy contracts or via EIP-7702.

When changing the underlying implementation, all Accounts MUST ensure that there are no conflicts in the storage layout
of the two contracts.

One common approach to this problem is often referred to as &quot;diamond storage&quot; and is fully described in [ERC-7201](./eip-7201).

### Transient Storage

Contracts using the [EIP-1153](./eip-1153) transient storage MUST take into account that ERC-4337 allows multiple
`UserOperations` from different unrelated `sender` addresses to be included in the same underlying transaction.
The transient storage MUST be cleaned up manually if contains any sensitive information or is used for access control.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 29 Sep 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4337</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4337</guid>
      </item>
    
      <item>
        <title>Ordered NFT Batch Standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://github.com/ethereum/EIPs/issues/3782</comments>
        
        <description>## Abstract
This standard introduces a smart contract interface that can represent a batch
of non-fungible tokens of which the ordering information shall be retained and
managed. Such information is particularly useful if `tokenId`s are encoded with
the sets of `unicodes` for logographic characters and emojis. As a result, NFTs
can be utilized as carriers of meanings.

## Motivation
Non-fungible tokens are widely accepted as carriers of crypto-assets, hence in both
[ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155), the ordering information of 
multiple NFTs is discarded. However, as proposed in [EIP-3754](/EIPs/EIPS/eip-3754), 
non-fungible tokens are thought of as basic units on a blockchain and can carry 
abstract meanings with unicoded `tokenId`s. Transferring such tokens is transmitting 
an ordered sequence of unicodes, thus effectively transmitting phrases or meanings 
on a blockchain.

A **[logograph](https://en.wikipedia.org/wiki/Logogram)** is a written character
that represents a word or morpheme, examples include _hanzi_ in Mandarin, _kanji_
in Japanese, _hanja_ in Korean, and etc. A [unicode](https://en.wikipedia.org/wiki/Unicode) 
is an information technology standard for the consistent encoding, representation, and
handling of texts.

It is natural to combine the two to create unicoded NFTs to represent logographic
characters. Since a rich amount of meanings can be transmitted in just a few
characters in such languages, it is technically practical and valuable to create
a standard for it. Emojis are similar with logographs and can be included as well.
For non-logographic languages such as English, although the same standard can be
applied, it is tedious to represent each letter with an NFT, hence the gain is
hardly justifiable.

A motivating example is instead of sending the two Chinese characters of the
Great Wall `长城`, two NFTs with IDs `#38271` and `#22478` respectively can be
transferred in a batch. The two IDs are corresponding to the decimal unicode of
the two characters. The receiving end decodes the IDs and retrieves the original
characters. A key point is the ordering information matters in this scenario
since the tuples `(38271, 22478)` and `(22478, 38271)` can be decoded as
`长城` and `城长`, respectively, and both are legitimate words in the Chinese
language. This illustrates the key difference between this standard and [ERC-1155](/EIPs/EIPS/eip-1155).

Besides, in the eastern Asian culture, characters are sometimes considered or
practically used as gifts in holidays such as Spring Feastival, etc.
`(24685, 21916, 21457, 36001)` `恭喜发财` can be used literally as a gift to
express the best wishes for financial prosperity. It is therefore cuturally
natural to transfer tokens to express meanings with this standard.

Also in logographic language systems, ancient teachings are usually written in
concise ways such that a handful of characters can unfold a rich amount of
meanings. Modern people now get a reliable technical means to pass down their
words, poems and proverbs to the future generations by sending tokens.

Other practical and interesting applications include Chinese chess, wedding
vows, family generation quotes and sayings, funeral commendation words, prayers,
anecdotes and etc.

## Specification
```
pragma solidity ^0.8.0;

/**
    @title EIP-4341 Multi Ordered NFT Standard
    @dev See https://eips.ethereum.org/EIPS/eip-4341
 */
interface ERC4341 /* is ERC165 */ {
    event Transfer(address indexed from, address indexed to, uint256 id, uint256 amount);

    event TransferBatch(address indexed from, address indexed to, uint256[] ids, uint256[] amounts);

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;

    function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;

    function safePhraseTransferFrom(address from, address to, uint256[] calldata phrase, bytes calldata data) external;

    function balanceOf(address owner, uint256 id) external view returns (uint256);

    function balanceOfPhrase(address owner) external view returns (uint256);

    function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) external view returns (uint256[] memory);

    function retrievePhrase(address owner, uint256 phraseId) external view returns (uint256[] memory);

    function setApprovalForAll(address operator, bool approved) external;

    function isApprovedForAll(address owner, address operator) external view returns (bool);
}
```

## Rationale
In [ERC-1155](/EIPs/EIPS/eip-1155) and [ERC-721](/EIPs/EIPS/eip-721), NFTs are used to represent
crypto-assets, and in this standard together with [EIP-3754](/EIPs/EIPS/eip-3754), NFTs
are equipped with utilities. In this standard, the ordering information of a batch
of NFTs is retained and managed through a construct `phrase`.

### Phrase
A `phrase` is usually made of a handful of basic characters or an orderred sequence
of unicodes and is able to keep the ordering information in a batch of tokens.
Technically, it is stored in an array of unsigned integers, and is not supposed
to be disseminated. A phrase does not increase or decrease the amount of any NFT
in anyway. A phrase cannot be transferred, however, it can be retrieved and
decoded to restore the original sequence of unicodes. The phrase information
is kept in storage and hence additional storage than [ERC-1155](/EIPs/EIPS/eip-1155) is required.

## Backwards Compatibility
[EIP-3754](/EIPs/EIPS/eip-3754) is the pre-requisite to this standard.

## Reference Implementation
https://github.com/simontianx/ERC4341

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 01 Oct 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4341</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4341</guid>
      </item>
    
      <item>
        <title>Difficulty Bomb Delay to June 2022</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4345-difficulty-bomb-delay-to-may-2022/7209</comments>
        
        <description>## Abstract
Starting with `FORK_BLOCK_NUMBER` the client will calculate the difficulty based on a fake block number suggesting to the client that the difficulty bomb is adjusting 10,700,000 blocks later than the actual block number.

## Motivation
Targeting for The Merge to occur before June 2022. If it is not ready by then, the bomb can be delayed further.

## Specification
#### Relax Difficulty with Fake Block Number
For the purposes of `calc_difficulty`, simply replace the use of `block.number`, as used in the exponential ice age component, with the formula:
```py
    fake_block_number = max(0, block.number - 10_700_000) if block.number &gt;= FORK_BLOCK_NUMBER else block.number
```
## Rationale

The following script predicts a ~0.1 second delay to block time by June 2022 and a ~0.5 second delay by July 2022. This gives reason to address because the effect will be seen, but not so much urgency we don&apos;t have space to work around if needed.

```python
def predict_diff_bomb_effect(current_blknum, current_difficulty, block_adjustment, months):
    &apos;&apos;&apos;
    Predicts the effect on block time (as a ratio) in a specified amount of months in the future.
    Vars used for predictions:
    current_blknum = 13423376 # Oct 15, 2021
    current_difficulty = 9545154427582720
    block adjustment = 10700000
    months = 7.5 # June 2022
    months = 8.5 # July 2022
    &apos;&apos;&apos;
    blocks_per_month = (86400 * 30) // 13.3
    future_blknum = current_blknum + blocks_per_month * months
    diff_adjustment = 2 ** ((future_blknum - block_adjustment) // 100000 - 2)
    diff_adjust_coeff = diff_adjustment / current_difficulty * 2048
    return diff_adjust_coeff


diff_adjust_coeff = predict_diff_bomb_effect(13423376,9545154427582720,10700000,7.5)
diff_adjust_coeff = predict_diff_bomb_effect(13423376,9545154427582720,10700000,8.5)
```

## Backwards Compatibility
No known backward compatibility issues.

## Security Considerations
Misjudging the effects of the difficulty can mean longer blocktimes than anticipated until a hardfork is released. Wild shifts in difficulty can affect this number severely. Also, gradual changes in blocktimes due to longer-term adjustments in difficulty can affect the timing of difficulty bomb epochs. This affects the usability of the network but unlikely to have security ramifications.

In this specific instance, it is possible that the network hashrate drops considerably before The Merge, which could accelerate the timeline by which the bomb is felt in block times. The offset value chosen aimed to take this into account.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 05 Oct 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4345</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4345</guid>
      </item>
    
      <item>
        <title>Interface for Staked Tokens in NFTs</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4353-viewing-staked-tokens-in-nft/7234</comments>
        
        <description>## Abstract
[EIP-721](/EIPs/EIPS/eip-721) tokens can be deposited or staked in NFTs for a variety of reasons including escrow, rewards, benefits, and others. There is currently no means of retrieving the number of tokens staked and/or bound to an NFT. This proposal outlines a standard that may be implemented by all wallets and marketplaces easily to correctly retrieve the staked token amount of an NFT.

## Motivation
Without staked token data, the actual amount of staked tokens cannot be conveyed from token owners to other users, and cannot be displayed in wallets, marketplaces, or block explorers. The ability to identify and verify an exogenous value derived from the staking process may be critical to the aims of an NFT holder.

## Specification
```solidity
// SPDX-License-Identifier: CC0-1.0

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC4353 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-4353.
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others.
 *
 * Note: The ERC-165 identifier for this interface is 0x3a3d855f.
 *
 */
interface IERC721Staked {
    
     /**
     * @dev Returns uint256 amount of on-chain tokens staked to the NFT.
     * 
     * @dev Wallets and marketplaces would need to call this for displaying
     *      the amount of tokens staked and/or bound to the NFT.
     */
    function stakedAmount(uint256 tokenId) external view returns (uint256);
    
}
```

### Suggested flow:

#### Constructor/deployment
* Creator - the owner of an NFT with its own rules for depositing tokens at and/or after the minting of a token.
* Token Amount - the current amount of on-chain [EIP-20](/EIPs/EIPS/eip-20) or derived tokens bound to an NFT from one or more deposits.
* Withdraw Mechanism - rules based approach for withdrawing staked tokens and making sure to update the balance of the staked tokens.

### Staking at mint and locking tokens in NFT
The suggested and intended implementation of this standard is to stake tokens at the time of minting an NFT, and not implementing any outbound transfer of tokens outside of `burn`. Therefore, only to stake at minting and withdraw only at burning.

#### NFT displayed in wallet or marketplace
A wallet or marketplace checks if an NFT has publicly staked tokens available for display - if so, call `stakedAmount(tokenId)` to get the current amount of tokens staked and/or bound to the NFT.

The logical code looks something like this and inspired by William Entriken:

```solidity
// contracts/Token.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol&quot;;
import &quot;@openzeppelin/contracts/access/Ownable.sol&quot;;

/**
 * @title Token
 * @dev Very simple ERC721 example with stake interface example.
 * Note this implementation enforces recommended procedure:
 *  1) stake at mint
 *  2) withdraw at burn
 */
contract ERC721Staked is ERC721URIStorage, Ownable {
    /// @dev track original minter of tokenId
    mapping (uint256 =&gt; address payable) private payees;
    /// @dev map tokens to stored staked token value
    mapping (uint256 =&gt; uint256) private tokenValue;

    /// @dev metadata
    constructor() ERC721 (
        &quot;Staked NFT&quot;, 
        &quot;SNFT&quot;
    ){}

    /// @dev mints a new NFT
    /// @param _to address that will own the minted NFT
    /// @param _tokenId id the NFT
    /// @param _uri metadata
    function mint(
        address payable _to,
        uint256 _tokenId,
        string calldata _uri
    )
        external 
        payable
        onlyOwner
    {
        _mint(_to, _tokenId);
        _setTokenURI(_tokenId, _uri);
        payees[_tokenId] = _to;
        tokenValue[_tokenId] = msg.value;
    }

    /// @dev staked interface
    /// @param _tokenId id of the NFT
    /// @return _value staked value
    function stakedAmount(
        uint256 _tokenId
    ) external view returns (uint256 _value) {
        _value = tokenValue[_tokenId];
        return _value;
    }

    /// @dev removes NFT &amp; transfers crypto to minter
    /// @param _tokenId the NFT we want to remove
    function burn(
        uint256 _tokenId
    )
        external
        onlyOwner
    {
        super._burn(_tokenId);
        payees[_tokenId].transfer(tokenValue[_tokenId]);
        tokenValue[_tokenId] = 0;
    }

}
```

## Rationale
This standard is completely agnostic to how tokens are deposited or handled by the NFT. It is, therefore, the choice and responsibility of the author to encode and communicate the encoding of their tokenomics to purchasees of their token and/or to make their contracts viewable by purchasees.

Although the intention of this standard is for tokens staked at mint and withdrawable only upon burn, the interface may be modified for dynamic withdrawing and depositing of tokens especially under DeFi application settings. In its current form, the contract logic may be the determining factor whether a deviation from the standard exists.

## Backward Compatibility
TBD

## Test Cases
```js
const { expect } = require(&quot;chai&quot;);
const { ethers, waffle } = require(&quot;hardhat&quot;);
const provider = waffle.provider;

describe(&quot;StakedNFT&quot;, function () {
    let _id = 1234567890;
    let value = &apos;1.5&apos;;
    let Token;
    let Interface;
    let owner;
    let addr1;
    let addr2;

    beforeEach(async function () {
        Token = await ethers.getContractFactory(&quot;ERC721Staked&quot;);
        [owner, addr1, ...addr2] = await ethers.getSigners();
        Interface = await Token.deploy();
    });

    describe(&quot;Staked NFT&quot;, function () {
        it(&quot;Should set the right owner&quot;, async function () {
            let mint = await Interface.mint(
                addr1.address, _id, &apos;http://foobar&apos;)
            expect(await Interface.ownerOf(_id)).to.equal(addr1.address);
        });

        it(&quot;Should not have staked balance without value&quot;, async function () {
            let mint = await Interface.mint(
                addr1.address, _id, &apos;http://foobar&apos;)
            expect(await Interface.stakedAmount(_id)).to.equal(
                ethers.utils.parseEther(&apos;0&apos;));
        });

        it(&quot;Should set and return the staked amount&quot;, async function () {
            let mint = await Interface.mint(
                addr1.address, _id, &apos;http://foobar&apos;,
                {value: ethers.utils.parseEther(value)})
            expect(await Interface.stakedAmount(_id)).to.equal(
                ethers.utils.parseEther(value));
        });

        it(&quot;Should decrease owner eth balance on mint (deposit)&quot;, async function () {
            let balance1 = await provider.getBalance(owner.address);
            let mint = await Interface.mint(
                addr1.address, _id, &apos;http://foobar&apos;,
                {value: ethers.utils.parseEther(value)})
            let balance2 = await provider.getBalance(owner.address);
            let diff = parseFloat(ethers.utils.formatEther(
                balance1.sub(balance2))).toFixed(1);
            expect(diff === value);
        });

        it(&quot;Should add to payee&apos;s eth balance on burn (withdraw)&quot;, async function () {
            let balance1 = await provider.getBalance(addr1.address);
            let mint = await Interface.mint(
                addr1.address, _id, &apos;http://foobar&apos;,
                {value: ethers.utils.parseEther(value)})
            await Interface.burn(_id);
            let balance2 = await provider.getBalance(addr1.address);
            let diff = parseFloat(ethers.utils.formatEther(
                balance2.sub(balance1))).toFixed(1);
            expect(diff === value);
        });

        it(&quot;Should update balance after transfer&quot;, async function () {
            let mint = await Interface.mint(
                addr1.address, _id, &apos;http://foobar&apos;,
                {value: ethers.utils.parseEther(value)})
            await Interface.burn(_id);
            expect(await Interface.stakedAmount(_id)).to.equal(
                ethers.utils.parseEther(&apos;0&apos;));
        });
    });
});
```

## Security Considerations
The purpose of this standard is to simply and publicly identify whether an NFT claims to have staked tokens.

Staked claims will be unreliable without a locking mechanism enforced, for example, if staked tokens can only be transferred at burn. Otherwise, tokens may be deposited and/or withdrawn at any time via arbitrary methods. Also, contracts that may allow arbitrary transfers without updating the correct balance will result in potential issues. A strict rules-based approach should be taken with these edge cases in mind.

A dedicated service may exist to verify the claims of a token by analyzing transactions on the explorer. In this manner, verification may be automated to ensure a token&apos;s claims are valid. The logical extension of this method may be to extend the interface and support flagging erroneous claims, all the while maintaining a simple goal of validating and verifying a staked amount exists to benefit the operator experience.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 08 Oct 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4353</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4353</guid>
      </item>
    
      <item>
        <title>Sign-In with Ethereum</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4361-sign-in-with-ethereum/7263</comments>
        
        <description>## Abstract

Sign-In with Ethereum describes how Ethereum accounts authenticate with off-chain services by signing a standard message format parameterized by scope, session details, and security mechanisms (e.g., a nonce). The goals of this specification are to provide a self-custodied alternative to centralized identity providers, improve interoperability across off-chain services for Ethereum-based authentication, and provide wallet vendors a consistent machine-readable message format to achieve improved user experiences and consent management.

## Motivation

When signing in to popular non-blockchain services today, users will typically use identity providers (IdPs) that are centralized entities with ultimate control over users&apos; identifiers, for example, large internet companies and email providers. Incentives are often misaligned between these parties. Sign-In with Ethereum offers a new self-custodial option for users who wish to assume more control and responsibility over their own digital identity.

Already, many services support workflows to authenticate Ethereum accounts using message signing, such as to establish a cookie-based web session which can manage privileged metadata about the authenticating address. This is an opportunity to standardize the sign-in workflow and improve interoperability across existing services, while also providing wallet vendors a reliable method to identify signing requests as Sign-In with Ethereum requests for improved UX.

## Specification

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

### Overview

Sign-In with Ethereum (SIWE) works as follows:

1. The relying party generates a SIWE Message and prefixes the SIWE Message with `\x19Ethereum Signed Message:\n&lt;length of message&gt;` as defined in [ERC-191](/EIPs/EIPS/eip-191).
2. The wallet presents the user with a structured plaintext message or equivalent interface for signing the SIWE Message with the [ERC-191](/EIPs/EIPS/eip-191) signed data format.
3. The signature is then presented to the relying party, which checks the signature&apos;s validity and SIWE Message content.
4. The relying party might further fetch data associated with the Ethereum address, such as from the Ethereum blockchain (e.g., ENS, account balances, [ERC-20](/EIPs/EIPS/eip-20)/[ERC-721](/EIPs/EIPS/eip-721)/[ERC-1155](/EIPs/EIPS/eip-1155) asset ownership), or other data sources that might or might not be permissioned.

### Message Format

#### ABNF Message Format

A SIWE Message MUST conform with the following Augmented Backus–Naur Form (ABNF, [RFC 5234](https://www.rfc-editor.org/rfc/rfc5234)) expression (note that `%s` denotes case sensitivity for a string term, as per [RFC 7405](https://www.rfc-editor.org/rfc/rfc7405)).

```abnf
sign-in-with-ethereum =
    [ scheme &quot;://&quot; ] domain %s&quot; wants you to sign in with your Ethereum account:&quot; LF
    address LF
    LF
    [ statement LF ]
    LF
    %s&quot;URI: &quot; uri LF
    %s&quot;Version: &quot; version LF
    %s&quot;Chain ID: &quot; chain-id LF
    %s&quot;Nonce: &quot; nonce LF
    %s&quot;Issued At: &quot; issued-at
    [ LF %s&quot;Expiration Time: &quot; expiration-time ]
    [ LF %s&quot;Not Before: &quot; not-before ]
    [ LF %s&quot;Request ID: &quot; request-id ]
    [ LF %s&quot;Resources:&quot;
    resources ]

scheme = ALPHA *( ALPHA / DIGIT / &quot;+&quot; / &quot;-&quot; / &quot;.&quot; )
    ; See RFC 3986 for the fully contextualized
    ; definition of &quot;scheme&quot;.

domain = authority
    ; From RFC 3986:
    ;     authority     = [ userinfo &quot;@&quot; ] host [ &quot;:&quot; port ]
    ; See RFC 3986 for the fully contextualized
    ; definition of &quot;authority&quot;.

address = &quot;0x&quot; 40*40HEXDIG
    ; Must also conform to capitalization
    ; checksum encoding specified in EIP-55
    ; where applicable (EOAs).

statement = *( reserved / unreserved / &quot; &quot; )
    ; See RFC 3986 for the definition
    ; of &quot;reserved&quot; and &quot;unreserved&quot;.
    ; The purpose is to exclude LF (line break).

uri = URI
    ; See RFC 3986 for the definition of &quot;URI&quot;.

version = &quot;1&quot;

chain-id = 1*DIGIT
    ; See EIP-155 for valid CHAIN_IDs.

nonce = 8*( ALPHA / DIGIT )
    ; See RFC 5234 for the definition
    ; of &quot;ALPHA&quot; and &quot;DIGIT&quot;.

issued-at = date-time
expiration-time = date-time
not-before = date-time
    ; See RFC 3339 (ISO 8601) for the
    ; definition of &quot;date-time&quot;.

request-id = *pchar
    ; See RFC 3986 for the definition of &quot;pchar&quot;.

resources = *( LF resource )

resource = &quot;- &quot; URI
```

#### Message Fields

This specification defines the following SIWE Message fields that can be parsed from a SIWE Message by following the rules in [ABNF Message Format](#abnf-message-format):

- `scheme` OPTIONAL. The URI scheme of the origin of the request. Its value MUST be an RFC 3986 URI scheme.
- `domain` REQUIRED. The domain that is requesting the signing. Its value MUST be an RFC 3986 authority. The authority includes an OPTIONAL port. If the port is not specified, the default port for the provided `scheme` is assumed (e.g., 443 for HTTPS). If `scheme` is not specified, HTTPS is assumed by default.
- `address` REQUIRED. The Ethereum address performing the signing. Its value SHOULD be conformant to mixed-case checksum address encoding specified in [ERC-55](/EIPs/EIPS/eip-55) where applicable.
- `statement` OPTIONAL. A human-readable ASCII assertion that the user will sign which MUST NOT include `&apos;\n&apos;` (the byte `0x0a`).
- `uri` REQUIRED. An RFC 3986 URI referring to the resource that is the subject of the signing (as in the _subject of a claim_).
- `version` REQUIRED. The current version of the SIWE Message, which MUST be `1` for this specification.
- `chain-id` REQUIRED. The [EIP-155](/EIPs/EIPS/eip-155) Chain ID to which the session is bound, and the network where Contract Accounts MUST be resolved.
- `nonce` REQUIRED. A random string typically chosen by the relying party and used to prevent replay attacks, at least 8 alphanumeric characters.
- `issued-at` REQUIRED. The time when the message was generated, typically the current time. Its value MUST be an [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339) datetime string.
- `expiration-time` OPTIONAL. The time when the signed authentication message is no longer valid. Its value MUST be an [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339) datetime string.
- `not-before` OPTIONAL. The time when the signed authentication message will become valid. Its value MUST be an [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339) datetime string.
- `request-id` OPTIONAL. A system-specific identifier that MAY be used to uniquely refer to the sign-in request.
- `resources` OPTIONAL. A list of information or references to information the user wishes to have resolved as part of authentication by the relying party. Every resource MUST be an RFC 3986 URI separated by `&quot;\n- &quot;` where `\n` is the byte `0x0a`.

#### Informal Message Template

A Bash-like informal template of the full SIWE Message is presented below for readability and ease of understanding, and it does not reflect the allowed optionality of the fields. Field descriptions are provided in the following section. A full ABNF description is provided in [ABNF Message Format](#abnf-message-format).

```
${scheme}:// ${domain} wants you to sign in with your Ethereum account:
${address}

${statement}

URI: ${uri}
Version: ${version}
Chain ID: ${chain-id}
Nonce: ${nonce}
Issued At: ${issued-at}
Expiration Time: ${expiration-time}
Not Before: ${not-before}
Request ID: ${request-id}
Resources:
- ${resources[0]}
- ${resources[1]}
...
- ${resources[n]}
```

#### Examples

The following is an example SIWE Message with an implicit scheme:

```
example.com wants you to sign in with your Ethereum account:
0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2

I accept the ExampleOrg Terms of Service: https://example.com/tos

URI: https://example.com/login
Version: 1
Chain ID: 1
Nonce: 32891756
Issued At: 2021-09-30T16:25:24Z
Resources:
- ipfs://bafybeiemxf5abjwjbikoz4mc3a3dla6ual3jsgpdr4cjr3oz3evfyavhwq/
- https://example.com/my-web2-claim.json
```

The following is an example SIWE Message with an implicit scheme and explicit port:

```
example.com:3388 wants you to sign in with your Ethereum account:
0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2

I accept the ExampleOrg Terms of Service: https://example.com/tos

URI: https://example.com/login
Version: 1
Chain ID: 1
Nonce: 32891756
Issued At: 2021-09-30T16:25:24Z
Resources:
- ipfs://bafybeiemxf5abjwjbikoz4mc3a3dla6ual3jsgpdr4cjr3oz3evfyavhwq/
- https://example.com/my-web2-claim.json
```

The following is an example SIWE Message with an explicit scheme:

```
https://example.com wants you to sign in with your Ethereum account:
0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2

I accept the ExampleOrg Terms of Service: https://example.com/tos

URI: https://example.com/login
Version: 1
Chain ID: 1
Nonce: 32891756
Issued At: 2021-09-30T16:25:24Z
Resources:
- ipfs://bafybeiemxf5abjwjbikoz4mc3a3dla6ual3jsgpdr4cjr3oz3evfyavhwq/
- https://example.com/my-web2-claim.json
```

### Signing and Verifying Messages with Ethereum Accounts

- For Externally Owned Accounts (EOAs), the verification method specified in [ERC-191](/EIPs/EIPS/eip-191) MUST be used.

- For Contract Accounts,
    - The verification method specified in [ERC-1271](/EIPs/EIPS/eip-1271) SHOULD be used, and if it is not, the implementer MUST clearly define the verification method to attain security and interoperability for both wallets and relying parties.
    - When performing [ERC-1271](/EIPs/EIPS/eip-1271) signature verification, the contract performing the verification MUST be resolved from the specified `chain-id`.
    - Implementers SHOULD take into consideration that [ERC-1271](/EIPs/EIPS/eip-1271) implementations are not required to be pure functions, and can return different results for the same inputs depending on blockchain state. This can affect the security model and session validation rules. For example, a service with [ERC-1271](/EIPs/EIPS/eip-1271) signing enabled could rely on webhooks to receive notifications when state affecting the results is changed. When it receives a notification, it invalidates any matching sessions.

### Resolving Ethereum Name Service (ENS) Data

- The relying party or wallet MAY additionally perform resolution of ENS data, as this can improve the user experience by displaying human-friendly information that is related to the `address`. Resolvable ENS data include:
    - The [primary ENS name](/EIPs/EIPS/eip-181).
    - The ENS avatar.
    - Any other resolvable resources specified in the ENS documentation.
- If resolution of ENS data is performed, implementers SHOULD take precautions to preserve user privacy and consent, as their `address` could be forwarded to third party services as part of the resolution process.

### Relying Party Implementer Steps

#### Specifying the Request Origin

- The `domain` and, if present, the `scheme`, in the SIWE Message MUST correspond to the origin from where the signing request was made. For instance, if the signing request is made within a cross-origin iframe embedded in a parent browser window, the `domain` (and, if present, the `scheme`) have to match the origin of the iframe, rather than the origin of the parent. This is crucial to prevent the iframe from falsely asserting the origin of one of its ancestor windows for security reasons. This behavior is enforced by conforming wallets.

#### Verifying a signed Message

- The SIWE Message MUST be checked for conformance to the ABNF Message Format in the previous sections, checked against expected values after parsing (e.g., `expiration-time`, `nonce`, `request-uri` etc.), and its signature MUST be checked as defined in [Signing and Verifying Messages with Ethereum Accounts](#signing-and-verifying-messages-with-ethereum-accounts).

#### Creating Sessions

- Sessions MUST be bound to the `address` and not to further resolved resources that can change.

#### Interpreting and resolving Resources

- Implementers SHOULD ensure that URIs in the listed `resources` are human-friendly when expressed in plaintext form.
- The interpretation of the listed `resources` in the SIWE Message is out of scope of this specification.

### Wallet Implementer Steps

#### Verifying the Message Format

- The full SIWE message MUST be checked for conformance to the ABNF defined in [ABNF Message Format](#abnf-message-format).
- Wallet implementers SHOULD warn users if the substring `&quot;wants you to sign in
  with your Ethereum account&quot;` appears anywhere in an [ERC-191](/EIPs/EIPS/eip-191) message signing
  request unless the message fully conforms to the format defined [ABNF Message Format](#abnf-message-format).

#### Verifying the Request Origin

- Wallet implementers MUST prevent phishing attacks by verifying the origin of the request against the `scheme` and `domain` fields in the SIWE Message. For example, when processing the SIWE message beginning with `&quot;example.com wants you to sign in...&quot;`, the wallet checks that the request actually originated from `https://example.com`.
- The origin SHOULD be read from a trusted data source such as the browser window or over WalletConnect ([ERC-1328](/EIPs/EIPS/eip-1328)) sessions for comparison against the signing message contents.
- Wallet implementers MAY warn instead of rejecting the verification if the origin is pointing to localhost.

The following is a RECOMMENDED algorithm for Wallets to conform with the requirements on request origin verification defined by this specification.

The algorithm takes the following input variables:

- fields from the SIWE message.
- `origin` of the signing request - in the case of a browser wallet implementation - the origin of the page which requested the signin via the provider.
- `allowedSchemes` - a list of schemes allowed by the Wallet.
- `defaultScheme` - a scheme to assume when none was provided. Wallet implementers in the browser SHOULD use `https`.
- developer mode indication - a setting deciding if certain risks should be a warning instead of rejection. Can be manually configured or derived from `origin` being localhost.

The algorithm is described as follows:

- If `scheme` was not provided, then assign `defaultScheme` as `scheme`.
- If `scheme` is not contained in `allowedSchemes`, then the `scheme` is not expected and the Wallet MUST reject the request. Wallet implementers in the browser SHOULD limit the list of `allowedSchemes` to just `&apos;https&apos;` unless a developer mode is activated.
- If `scheme` does not match the scheme of `origin`, the Wallet SHOULD reject the request. Wallet implementers MAY show a warning instead of rejecting the request if a developer mode is activated. In that case the Wallet continues processing the request.
- If the `host` part of the `domain` and `origin` do not match, the Wallet MUST reject the request unless the Wallet is in developer mode. In developer mode the Wallet MAY show a warning instead and continues processing the request.
- If `domain` and `origin` have mismatching subdomains, the Wallet SHOULD reject the request unless the Wallet is in developer mode. In developer mode the Wallet MAY show a warning instead and continues processing the request.
- Let `port` be the port component of `domain`, and if no port is contained in `domain`, assign `port` the default port specified for the `scheme`.
- If `port` is not empty, then the Wallet SHOULD show a warning if the `port` does not match the port of `origin`.
- If `port` is empty, then the Wallet MAY show a warning if `origin` contains a specific port. (Note &apos;https&apos; has a default port of 443 so this only applies if `allowedSchemes` contain unusual schemes)
- Return request origin verification completed.

#### Creating Sign-In with Ethereum Interfaces

- Wallet implementers MUST display to the user the following fields from the SIWE Message request by default and prior to signing, if they are present: `scheme`, `domain`, `address`, `statement`, and `resources`. Other present fields MUST also be made available to the user prior to signing either by default or through an extended interface.
- Wallet implementers displaying a plaintext SIWE Message to the user SHOULD require the user to scroll to the bottom of the text area prior to signing.
- Wallet implementers MAY construct a custom SIWE user interface by parsing the ABNF terms into data elements for use in the interface. The display rules above still apply to custom interfaces.

#### Supporting internationalization (i18n)

- After successfully parsing the message into ABNF terms, translation MAY happen at the UX level per human language.

## Rationale

### Requirements

Write a specification for how Sign-In with Ethereum should work. The specification should be simple and generally follow existing practices. Avoid feature bloat, particularly the inclusion of lesser-used projects who see getting into the specification as a means of gaining adoption. The core specification should be decentralized, open, non-proprietary, and have long-term viability. It should have no dependence on a centralized server except for the servers already being run by the application that the user is signing in to. The basic specification should include: Ethereum accounts used for authentication, ENS names for usernames (via reverse resolution), and data from the ENS name’s text records for additional profile information (e.g. avatar, social media handles, etc).

Additional functional requirements:

1. The user must be presented a human-understandable interface prior to signing, mostly free of machine-targeted artifacts such as JSON blobs, hex codes (aside from the Ethereum address), and baseXX-encoded strings.
2. The application server must be able to implement fully usable support for its end without forcing a change in the wallets.
3. There must be a simple and straightforward upgrade path for both applications and wallets already using Ethereum account-based signing for authentication.
4. There must be facilities and guidelines for adequate mitigation of Man-in-the-Middle (MITM) attacks, replay attacks, and malicious signing requests.

### Design Goals

1. Human-Friendly
2. Simple to Implement
3. Secure
4. Machine Readable
5. Extensible

### Technical Decisions

- Why [ERC-191](/EIPs/EIPS/eip-191) (Signed Data Standard) over [EIP-712](/EIPs/EIPS/eip-712) (Ethereum typed structured data hashing and signing)
    - [ERC-191](/EIPs/EIPS/eip-191) is already broadly supported across wallets UX, while [EIP-712](/EIPs/EIPS/eip-712) support for friendly user display is pending. **(1, 2, 3, 4)**
    - [ERC-191](/EIPs/EIPS/eip-191) is simple to implement using a pre-set prefix prior to signing, while [EIP-712](/EIPs/EIPS/eip-712) is more complex to implement requiring the further implementations of a bespoke Solidity-inspired type system, RLP-based encoding format, and custom keccak-based hashing scheme. **(2)**
    - [ERC-191](/EIPs/EIPS/eip-191) produces more human-readable messages, while [EIP-712](/EIPs/EIPS/eip-712) creates signing outputs for machine consumption, with most wallets not displaying the payload to be signed in a manner friendly to humans. **(1)**![](/EIPs/assets/eip-4361/signing.png)

    - [EIP-712](/EIPs/EIPS/eip-712) has the advantage of on-chain representation and on-chain verifiability, such as for their use in metatransactions, but this feature is not relevant for the specification&apos;s scope. **(2)**
- Why not use JWTs? Wallets don&apos;t support JWTs. The keccak hash function is not assigned by IANA for use as a JOSE algorithm. **(2, 3)**
- Why not use YAML or YAML with exceptions? YAML is loose compared to ABNF, which can readily express character set limiting, required ordering, and strict whitespacing. **(2, 3)**

### Out of Scope

The following concerns are out of scope for this version of the specification to define:

- Additional authentication not based on Ethereum addresses.
- Authorization to server resources.
- Interpretation of the URIs in the `resources` field as claims or other resources.
- The specific mechanisms to ensure domain-binding.
- The specific mechanisms to generate nonces and evaluation of their appropriateness.
- Protocols for use without TLS connections.

### Considerations for Forwards Compatibility

The following items are considered for future support either through an iteration of this specification or new work items using this specification as a dependency.

- Possible support for Decentralized Identifiers and Verifiable Credentials.
- Possible cross-chain support.
- Possible SIOPv2 support.
- Possible future support for [EIP-712](/EIPs/EIPS/eip-712).
- Version interpretation rules, e.g., sign with minor revision greater than understood, but not greater major version.

## Backwards Compatibility

- Most wallet implementations already support [ERC-191](/EIPs/EIPS/eip-191), so this is used as a base pattern with additional features.
- Requirements were gathered from existing implementations of similar sign-in workflows, including statements to allow the user to accept a Terms of Service, nonces for replay protection, and inclusion of the Ethereum address itself in the message.

## Reference Implementation

A reference implementation is available [here](/EIPs/assets/eip-4361/example.js).

## Security Considerations

### Identifier Reuse

- Towards perfect privacy, it would be ideal to use a new uncorrelated identifier (e.g., Ethereum address) per digital interaction, selectively disclosing the information required and no more.
- This concern is less relevant to certain user demographics who are likely to be early adopters of this specification, such as those who manage an Ethereum address and/or ENS names intentionally associated with their public presence. These users often prefer identifier reuse to maintain a single correlated identity across many services.
- This consideration will become increasingly important with mainstream adoption. There are several ways to move towards this model, such as using HD wallets, signed delegations, and zero-knowledge proofs. However, these approaches are out of scope for this specification and better suited for follow-on specifications.

### Key Management

- Sign-In with Ethereum gives users control through their keys. This is additional responsibility that mainstream users may not be accustomed to accepting, and key management is a hard problem especially for individuals. For example, there is no &quot;forgot password&quot; button as centralized identity providers commonly implement.
- Early adopters of this specification are likely to be already adept at key management, so this consideration becomes more relevant with mainstream adoption.
- Certain wallets can use smart contracts and multisigs to provide an enhanced user experience with respect to key usage and key recovery, and these can be supported via [ERC-1271](/EIPs/EIPS/eip-1271) signing.

### Wallet and Relying Party combined Security

- Both the wallet and relying party have to implement this specification for improved security to the end user. Specifically, the wallet has to confirm that the SIWE Message is for the correct request origin or provide the user means to do so manually (such as instructions to visually confirming the correct domain in a TLS-protected website prior to connecting via QR code or deeplink), otherwise the user is subject to phishing attacks.

### Minimizing Wallet and Server Interaction

- In some implementations of wallet sign-in workflows, the server first sends parameters of the SIWE Message to the wallet. Others generate the SIWE message for signing entirely in the client side (e.g., dapps). The latter approach without initial server interaction SHOULD be preferred when there is a user privacy advantage by minimizing wallet-server interaction. Often, the backend server first produces a `nonce` to prevent replay attacks, which it verifies after signing. Privacy-preserving alternatives are suggested in the next section on preventing replay attacks.
- Before the wallet presents the SIWE message signing request to the user, it MAY consult the server for the proper contents of the message to be signed, such as an acceptable `nonce` or requested set of `resources`. When communicating to the server, the wallet SHOULD take precautions to protect user privacy by mitigating user information revealed as much as possible.
- Prior to signing, the wallet MAY consult the user for preferences, such as the selection of one `address` out of many, or a preferred ENS name out of many.

### Preventing Replay Attacks

- A `nonce` SHOULD be selected per session initiation with enough entropy to prevent replay attacks, a man-in-the-middle attack in which an attacker is able to capture the user&apos;s signature and resend it to establish a new session for themselves.
- Implementers MAY consider using privacy-preserving yet widely-available `nonce` values, such as one derived from a recent Ethereum block hash or a recent Unix timestamp.

### Preventing Phishing Attacks

- To prevent phishing attacks Wallets have to implement request origin verification as described in [Verifying the Request Origin](#verifying-the-request-origin).

### Channel Security

- For web-based applications, all communications SHOULD use HTTPS to prevent man-in-the-middle attacks on the message signing.
- When using protocols other than HTTPS, all communications SHOULD be protected with proper techniques to maintain confidentiality, data integrity, and sender/receiver authenticity.

### Session Invalidation

There are several cases where an implementer SHOULD check for state changes as they relate to sessions.

- If an [ERC-1271](/EIPs/EIPS/eip-1271) implementation or dependent data changes the signature computation, the server SHOULD invalidate sessions appropriately.
- If any resources specified in `resources` change, the server SHOULD invalidate sessions appropriately. However, the interpretation of `resources` is out of scope of this specification.

### Maximum Lengths for ABNF Terms

- While this specification does not contain normative requirements around maximum string lengths, implementers SHOULD choose maximum lengths for terms that strike a balance across the prevention of denial of service attacks, support for arbitrary use cases, and user readability.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 11 Oct 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4361</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4361</guid>
      </item>
    
      <item>
        <title>Micropayments for NFTs and Multi Tokens</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-proposal-micropayments-standard-for-nfts-and-multi-tokens/7366</comments>
        
        <description>## Abstract

This standard outlines a smart contract interface for tipping to non-fungible and multi tokens. Holders of the tokens are able to withdraw the tips as [EIP-20](/EIPs/EIPS/eip-20) rewards.

For the purpose of this EIP, a micropayment is termed as a financial transaction that involves usually a small sum of money called &quot;tips&quot; that are sent to specific [EIP-721](/EIPs/EIPS/eip-721) NFTs and [EIP-1155](/EIPs/EIPS/eip-1155) multi tokens, as rewards to their holders. A holder (also referred to as controller) is used as a more generic term for owner, as NFTs may represent non-digital assets such as services.

## Motivation

A cheap way to send tips to any type of NFT or multi token. This can be achieved by gas optimising the tip token contract and sending the tips in batches using the `tipBatch` function from the interface.

To make it easy to implement into dapps a tipping service to reward the NFT and multi token holders. Allows for fairer distribution of revenue back to NFT holders from the user community.

To make the interface as minimal as possible in order to allow adoption into many different use cases.

Some use cases include:

- In game purchases and other virtual goods

- Tipping messages, posts, music and video content

- Donations/crowdfunding

- Distribution of royalties

- Pay per click advertising

- Incentivising use of services

- Reward cards and coupons

These can all leverage the security, immediacy and transparency of blockchain.

## Specification

This standard proposal outlines a generalised way to allow tipping via implementation of an `ITipToken` interface. The interface is intentionally kept to a minimum in order to allow for maximum use cases.

Smart contracts implementing this EIP standard MUST implement all of the functions in this EIP interface. MUST also emit the events specified in the interface so that a complete state of the tip token contract can be derived from the events emitted alone.

Smart contracts implementing this EIP standard MUST implement the [EIP-165](/EIPs/EIPS/eip-165) supportsInterface function and MUST return the constant value true if 0xE47A7022 is passed through the interfaceID argument. Note that revert in this document MAY mean a require, throw (not recommended as depreciated) or revert solidity statement with or without error messages.

Note that, nft (or NFT in caps) in the code and as mentioned in this document, MAY also refer to an EIP-1155 fungible token.

```solidity
interface ITipToken {
    /**
        @dev This emits when the tip token implementation approves the address
        of an NFT for tipping.
        The holders of the &apos;nft&apos; are approved to receive rewards.
        When an NFT Transfer event emits, this also indicates that the approved
        addresses for that NFT (if any) is reset to none.
        Note: the ERC-165 identifier for this interface is 0x985A3267.
    */
    event ApprovalForNFT(
        address[] holders,
        address indexed nft,
        uint256 indexed id,
        bool approved
    );

    /**
        @dev This emits when a user has deposited an ERC-20 compatible token to
        the tip token&apos;s contract address or to an external address.
        This also indicates that the deposit has been exchanged for an
        amount of tip tokens
    */
    event Deposit(
        address indexed user,
        address indexed rewardToken,
        uint256 amount,
        uint256 tipTokenAmount
    );

    /**
        @dev This emits when a holder withdraws an amount of ERC-20 compatible
        reward. This reward comes from the tip token&apos;s contract address or from
        an external address, depending on the tip token implementation
    */
    event WithdrawReward(
        address indexed holder,
        address indexed rewardToken,
        uint256 amount
    );

    /**
        @dev This emits when the tip token constructor or initialize method is
        executed.
        Importantly the ERC-20 compatible token &apos;rewardToken_&apos; to use as reward
        to NFT holders is set at this time and remains the same throughout the
        lifetime of the tip token contract.
        The &apos;rewardToken_&apos; and &apos;tipToken_&apos; MAY be the same.
    */
    event InitializeTipToken(
        address indexed tipToken_,
        address indexed rewardToken_,
        address owner_
    );

    /**
        @dev This emits every time a user tips an NFT holder.
        Also includes the reward token address and the reward token amount that
        will be held pending until the holder withdraws the reward tokens.
    */
    event Tip(
        address indexed user,
        address[] holder,
        address indexed nft,
        uint256 id,
        uint256 amount,
        address rewardToken,
        uint256[] rewardTokenAmount
    );

    /**
        @notice Enable or disable approval for tipping for a single NFT held
        by a holder or a multi token shared by holders
        @dev MUST revert if calling nft&apos;s supportsInterface does not return
        true for either IERC721 or IERC1155.
        MUST revert if any of the &apos;holders&apos; is the zero address.
        MUST revert if &apos;nft&apos; has not approved the tip token contract address as operator.
        MUST emit the &apos;ApprovalForNFT&apos; event to reflect approval or not approval.
        @param holders The holders of the NFT (NFT controllers)
        @param nft The NFT contract address
        @param id The NFT token id
        @param approved True if the &apos;holder&apos; is approved, false to revoke approval
    */
    function setApprovalForNFT(
        address[] calldata holders,
        address nft,
        uint256 id,
        bool approved
    ) external;

    /**
        @notice Checks if &apos;holder&apos; and &apos;nft&apos; with token &apos;id&apos; have been approved
        by setApprovalForNFT
        @dev This does not check that the holder of the NFT has changed. That is
        left to the implementer to detect events for change of ownership and to
        take appropriate action
        @param holder The holder of the NFT (NFT controller)
        @param nft The NFT contract address
        @param id The NFT token id
        @return True if &apos;holder&apos; and &apos;nft&apos; with token &apos;id&apos; have previously been
        approved by the tip token contract
    */
    function isApprovalForNFT(
        address holder,
        address nft,
        uint256 id
    ) external returns (bool);

    /**
        @notice Sends tip from msg.sender to holder of a single NFT or
        to shared holders of a multi token
        @dev If &apos;nft&apos; has not been approved for tipping, MUST revert
        MUST revert if &apos;nft&apos; is zero address.
        MUST burn the tip &apos;amount&apos; to the &apos;holder&apos; and send the reward to
        an account pending for the holder(s).
        If &apos;nft&apos; is a multi token that has multiple holders then each holder
        MUST receive tip amount in proportion of their balance of multi tokens
        MUST emit the &apos;Tip&apos; event to reflect the amounts that msg.sender tipped
        to holder(s) of &apos;nft&apos;.
        @param nft The NFT contract address
        @param id The NFT token id
        @param amount Amount of tip tokens to send to the holder of the NFT
    */
    function tip(
        address nft,
        uint256 id,
        uint256 amount
    ) external;

    /**
        @notice Sends a batch of tips to holders of &apos;nfts&apos; for gas efficiency
        @dev If NFT has not been approved for tipping, revert
        MUST revert if the input arguments lengths are not all the same
        MUST revert if any of the user addresses are zero
        MUST revert the whole batch if there are any errors
        MUST emit the &apos;Tip&apos; events so that the state of the amounts sent to
        each holder and for which nft and from whom, can be reconstructed.
        @param users User accounts to tip from
        @param nfts The NFT contract addresses whose holders to tip to
        @param ids The NFT token ids that uniquely identifies the &apos;nfts&apos;
        @param amounts Amount of tip tokens to send to the holders of the NFTs
    */
    function tipBatch(
        address[] calldata users,
        address[] calldata nfts,
        uint256[] calldata ids,
        uint256[] calldata amounts
    ) external;

    /**
        @notice Deposit an ERC-20 compatible token in exchange for tip tokens
        @dev The price of tip tokens can be different for each deposit as
        the amount of reward token sent ultimately is a ratio of the
        amount of tip tokens to tip over the user&apos;s tip tokens balance available
        multiplied by the user&apos;s deposit balance.
        The deposited tokens can be held in the tip tokens contract account or
        in an external escrow. This will depend on the tip token implementation.
        Each tip token contract MUST handle only one type of ERC-20 compatible
        reward for deposits.
        This token address SHOULD be passed in to the tip token constructor or
        initialize method. SHOULD revert if ERC-20 reward for deposits is
        zero address.
        MUST emit the &apos;Deposit&apos; event that shows the user, deposited token details
        and amount of tip tokens minted in exchange
        @param user The user account
        @param amount Amount of ERC-20 token to deposit in exchange for tip tokens.
        This deposit is to be used later as the reward token
    */
    function deposit(address user, uint256 amount) external payable;

    /**
        @notice An NFT holder can withdraw their tips as an ERC-20 compatible
        reward at a time of their choosing
        @dev MUST revert if not enough balance pending available to withdraw.
        MUST send &apos;amount&apos; to msg.sender account (the holder)
        MUST reduce the balance of reward tokens pending by the &apos;amount&apos; withdrawn.
        MUST emit the &apos;WithdrawReward&apos; event to show the holder who withdrew, the reward
        token address and &apos;amount&apos;
        @param amount Amount of ERC-20 token to withdraw as a reward
    */
    function withdrawReward(uint256 amount) external payable;

    /**
        @notice MUST have identical behaviour to ERC-20 balanceOf and is the amount
        of tip tokens held by &apos;user&apos;
        @param user The user account
        @return The balance of tip tokens held by user
    */
    function balanceOf(address user) external view returns (uint256);

    /**
        @notice The balance of deposit available to become rewards when
        user sends the tips
        @param user The user account
        @return The remaining balance of the ERC-20 compatible token deposited
    */
    function balanceDepositOf(address user) external view returns (uint256);

    /**
        @notice The amount of reward token owed to &apos;holder&apos;
        @dev The pending tokens can come from the tip token contract account
        or from an external escrow, depending on tip token implementation
        @param holder The holder of NFT(s) (NFT controller)
        @return The amount of reward tokens owed to the holder from tipping
    */
    function rewardPendingOf(address holder) external view returns (uint256);
}
```

### Tipping and rewards to holders

A user first deposits a compatible EIP-20 to the tip token contract that is then held (less any agreed fee) in escrow, in exchange for tip tokens. These tip tokens can then be sent by the user to NFTs and multi tokens (that have been approved by the tip token contract for tipping) to be redeemed for the original EIP-20 deposits on withdrawal by the holders as rewards.

### Tip Token transfer and value calculations

Tip token values are exchanged with EIP-20 deposits and vice-versa. It is left to the tip token implementer to decide on the price of a tip token and hence how much tip to mint in exchange for the EIP-20 deposited. One possibility is to have fixed conversion rates per geographical region so that users from poorer countries are able to send the same number of tips as those from richer nations for the same level of appreciation for content/assets etc. Hence, not skewed by average wealth when it comes to analytics to discover what NFTs are actually popular, allowing creators to have a level playing field.

Whenever a user sends a tip, an equivalent value of deposited EIP-20 MUST be transferred to a pending account for the NFT or multi token holder, and the tip tokens sent MUST be burnt. This equivalent value is calculated using a simple formula:

_total user balance of EIP-20 deposit _ tip amount / total user balance of tip tokens\*

Thus adding \*free\* tips to a user&apos;s balance of tips for example, simply dilutes the overall value of each tip for that user, as collectively they still refer to the same amount of EIP-20 deposited.

Note if the tip token contract inherits from an EIP-20, tips can be transferred from one user to another directly. The deposit amount would be already in the tip token contract (or an external escrow account) so only tip token contract&apos;s internal mapping of user account to deposit balances needs to be updated. It is RECOMMENDED that the tip amount be burnt from user A and then minted back to user B in the amount that keeps user B&apos;s average EIP-20 deposited value per tip the same, so that the value of the tip does not fluctuate in the process of tipping.

If not inheriting from EIP-20, then minting the tip tokens MUST emit `event Transfer(address indexed from, address indexed to, uint256 value)` where sender is the zero address for a mint and to is the zero address for a burn. The Transfer event MUST be the same signature as the Transfer function in the `IERC20` interface.

### Royalty distribution

EIP-1155 allows for shared holders of a token id. Imagine a scenario where an article represented by an NFT was written by multiple contributors. Here, each contributor is a holder and the fractional sharing percentage between them can be represented by the balance that each holds in the EIP-1155 token id. So for two holders A and B of EIP-1155 token 1, if holder A&apos;s balance is 25 and holder B&apos;s is 75 then any tip sent to token 1 would distribute 25% of the reward pending to holder A and the remaining 75% pending to holder B.

Here is an example implementation of ITipToken contract data structures:

```solidity
    /// Mapping from NFT/multi token to token id to holder(s)
    mapping(address =&gt; mapping(uint256 =&gt; address[])) private _tokenIdToHolders;

    /// Mapping from user to user&apos;s deposit balance
    mapping(address =&gt; uint256) private _depositBalances;

    /// Mapping from holder to holder&apos;s reward pending amount
    mapping(address =&gt; uint256) private _rewardsPending;
```

This copes with EIP-721 contracts that must have unique token ids and single holders (to be compliant with the standard), and EIP-1155 contracts that can have multiple token ids and multiple holders per instance. The `tip` function implementation would then access `_tokenIdToHolders` via indices NFT/multi token address and token id to distribute to holder&apos;s or holders&apos; `_rewardsPending`.

For scenarios where royalties are to be distributed to holders directly, then implementation of the `tip` method of `ITipToken` contract MAY send the royalty amount straight from the user&apos;s account to the holder of a single NFT or to the shared holders of a multi token, less an optional agreed fee. In this case, the tip token type is the reward token.

### Caveats

To keep the `ITipToken` interface simple and general purpose, each tip token contract MUST use one EIP-20 compatible deposit type at a time. If tipping is required to support many EIP-20 deposits then each tip token contract MUST be deployed separately per EIP-20 compatible type required. Thus, if tipping is required from both ETH and BTC wrapper EIP-20 deposits then the tip token contract is deployed twice. The tip token contract&apos;s constructor is REQUIRED to pass in the address of the EIP-20 token supported for the deposits for the particular tip token contract. Or in the case for upgradeable tip token contracts, an initialize method is REQUIRED to pass in the EIP-20 token address.

This EIP does not provide details for where the EIP-20 reward deposits are held. It MUST be available at the time a holder withdraws the rewards that they are owed. A RECOMMENDED implementation would be to keep the deposits locked in the tip token contract address. By keeping a mapping structure that records the balances pending to holders then the
deposits can remain where they are when a user tips, and only transferred out to a holder&apos;s address when a holder withdraws it as their reward.

This standard does not specify the type of EIP-20 compatible deposits allowed. Indeed, could be tip tokens themselves. But it is RECOMMENDED that balances of the deposits be checked after transfer to find out the exact amount deposited to keep internal accounting consistent. In case, for example, the EIP-20 contract takes fees and hence reduces the actual amount deposited.

This standard does not specify any functionality for refunds for deposits nor for tip tokens sent, it is left to the implementor to add this to their smart contract(s). The reasoning for this is to keep the interface light and not to enforce upon implementors the need for refunds but to leave that as a choice.

### Minimising Gas Costs

By caching tips off-chain and then batching them up to call the `tipBatch` method of the ITipToken interface then essentially the cost of initialising transactions is paid once rather than once per tip. Plus, further gas savings can be made off-chain if multiple tips sent by the same user to the same NFT token are accumulated together and sent as one entry in the batch.

Further savings can be made by grouping users together sending to the same NFT, so that checking the validity of the NFT and whether it is an EIP-721 or EIP-1155, is performed once for each group.

Clever ways to minimise on-chain state updating of the deposit balances for each user and the reward balances of each holder, can help further to minimise the gas costs when sending in a batch if the batch is ordered beforehand. For example, can avoid the checks if the next NFT in the batch is the same. This left to the tip token contract implementer. Whatever optimisation is applied, it MUST still allow information of which account tipped which account and for what NFT to be reconstructed from the Tip and the TipBatch events emitted.

## Rationale

### Simplicity

ITipToken interface uses a minimal number of functions, in order to keep its use as general purpose as possible, whilst there being enough to guide implementation that fulfils its purpose for micropayments to NFT holders.

### Use of NFTs

Each NFT is a unique non-fungible token digital asset stored on the blockchain that are uniquely identified by its address and token id. It&apos;s truth burnt using cryptographic hashing on a secure blockchain means that it serves as an anchor for linking with a unique digital asset, service or other contractual agreement. Such use cases may include (but only really limited by imagination and acceptance):

- Digital art, collectibles, music, video, licenses and certificates, event tickets, ENS names, gaming items, objects in metaverses, proof of authenticity of physical items, service agreements etc.

This mechanism allows consumers of the NFT a secure way to easily tip and reward the NFT holder.

### New Business Models

To take the music use case for example. Traditionally since the industry transitioned from audio distributed on physical medium such as CDs, to an online digital distribution model via streaming, the music industry has been controlled by oligopolies that served to help in the transition. They operate a fixed subscription model and from that they set the amount of royalty distribution to content creators; such as the singers, musicians etc. Using tip tokens represent an additional way for fans of music to reward the content creators. Each song or track is represented by an NFT and fans are able to tip the song (hence the NFT) that they like, and in turn the content creators of the NFT are able to receive the EIP-20 rewards that the tips were bought for. A fan led music industry with decentralisation and tokenisation is expected to bring new revenue, and bring fans and content creators closer together.

Across the board in other industries a similar ethos can be applied where third party controllers move to a more facilitating role rather than a monetary controlling role that exists today.

### Guaranteed audit trail

As the Ethereum ecosystem continues to grow, many dapps are relying on traditional databases and explorer API services to retrieve and categorize data. This EIP standard guarantees that event logs emitted by the smart contract MUST provide enough data to create an accurate record of all current tip token and EIP-20 reward balances. A database or explorer can provide indexed and categorized searches of every tip token and reward sent to NFT holders from the events emitted by any tip token contract that implements this standard. Thus, the state of the tip token contract can be reconstructed from the events emitted alone.

## Backwards Compatibility

A tip token contract can be fully compatible with EIP-20 specification and inherit some functions such as transfer if the tokens are allowed to be sent directly to other users. Note that balanceOf has been adopted and MUST be the number of tips held by a user&apos;s address. If inheriting from, for example, OpenZeppelin&apos;s implementation of EIP-20 token then their contract is responsible for maintaining the balance of tip token. Therefore, tip token balanceOf function SHOULD simply directly call the parent (super) contract&apos;s balanceOf function.

What hasn&apos;t been carried over to tip token standard, is the ability for a spender of other users&apos; tips. For the moment, this standard does not foresee a need for this.

This EIP does not stress a need for tip token secondary markets or other use cases where identifying the tip token type with names rather than addresses might be useful, so these functions were left out of the ITipToken interface and is the remit for implementers.

## Security Considerations

Though it is RECOMMENDED that users&apos; deposits are kept locked in the tip token contract or external escrow account, and SHOULD NOT be used for anything but the rewards for holders, this cannot be enforced. This standard stipulates that the rewards MUST be available for when holders withdraw their rewards from the pool of deposits.

Before any users can tip an NFT, the holder of the NFT has to give their approval for tipping from the tip token contract. This standard stipulates that holders of the NFTs receive the rewards. It SHOULD be clear in the tip token contract code that it does so, without obfuscation to where the rewards go. Any fee charges SHOULD be made obvious to users before acceptance of their deposit. There is a risk that rogue implementers may attempt to \*hijack\* potential tip income streams for their own purposes. But additionally the number and frequency of transactions of the tipping process should make this type of fraud quicker to be found out.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 24 Oct 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4393</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4393</guid>
      </item>
    
      <item>
        <title>Time-Aware Base Fee Calculation</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4396-time-aware-base-fee-calculation/7363</comments>
        
        <description>## Abstract
This EIP proposes accounting for time between blocks in the base fee calculation to target a stable throughput by time, instead of by block. Aiming to minimize changes to the calculation, it only introduces a variable block gas target proportional to the block time. The EIP can, in principle, be applied to either a Proof-of-Work or a Proof-of-Stake chain, however the security implications for the Proof-of-Work case remain unexplored.

## Motivation

The current base fee calculation chooses the gas usage of a block as the signal to determine whether demand for block space is too low (indicating that the base fee should be lowered) or too high (indicating that the base fee should be increased). While simple, this choice of signal has drawbacks: it does not take the block time into account. Assuming a relatively constant demand, a proposer constructing a block after 20 seconds will have transactions available with twice the gas of a proposer constructing a block after 10 seconds. Using the same gas target for both is accordingly sub-optimal. In practice, there are several undesirable consequences of this flawed signal:

### Base Fee Volatility Under Proof-of-Work

Under Proof-of-Work (PoW), block times are stochastic, and for that reason there exists large block time variability. This variability contributes to the base fee volatility, where the base fee can be expected to oscillate around the equilibrium value even under perfectly stable demand.

### Missed Slots

Under Proof-of-Stake (PoS), block times are ideally uniform (always 12s), but missed slots lead to individual blocks with increased block time (24s, 36s, ...). Such missed slots will result in the next block being overfull, and with the current update rule, signal a fake demand spike and thus cause a small unwarranted base fee spike.

More importantly, these missed slots directly reduce the overall throughput of the execution chain by the gas target of one block. While the next block can be expected to include the &quot;delayed&quot; transactions of the missed slot, the resulting base fee spike then results in some number of under-full blocks. In the end the block space of the missed slot is lost for the chain.

This is particularly problematic because a Denial-of-Service (DoS) attack on block proposers can cause them to miss slots, and compromises the overall chain performance.

### Throughput Degradation During Consensus Issues

A more severe version of individual missed slots can be caused by consensus issues that prevent a significant portion of block proposers from continuing to create blocks. This can be due to block proposers forking off (and creating blocks on their own fork), being unable to keep up with the current chain head for another reason, or simply being unable to create valid blocks.

In all these situations, average block times go up significantly, causing chain throughput to fall by the same fraction. While this effect is already present under PoW, the self-healing mechanism of difficulty adjustments is relatively quick to kick in and restore normal block times. On the other hand, under PoS the automatic self-healing mechanism can be extremely slow: potentially several months to return to normal with up to a third of slots missed, or several weeks if more than a third of slots are missed.

For all these reasons, it would be desirable to target a stable throughput per time instead of per block, by taking block time into account during the base fee calculation.

To maximize the chance of this EIP being included in the merge fork, the adjustments are kept to a minimum, with more involved changes discussed in the rationale section.

## Specification
Using the pseudocode language of [EIP-1559](/EIPs/EIPS/eip-1559), the updated base fee calculation becomes:

```python
...

BASE_FEE_MAX_CHANGE_DENOMINATOR = 8
BLOCK_TIME_TARGET = 12
MAX_GAS_TARGET_PERCENT = 95

class World(ABC):
    def validate_block(self, block: Block) -&gt; None:
        parent_gas_limit = self.parent(block).gas_limit
        parent_block_time = self.parent(block).timestamp - self.parent(self.parent(block)).timestamp
        parent_base_gas_target = parent_gas_limit // ELASTICITY_MULTIPLIER
        parent_adjusted_gas_target = min(parent_base_gas_target * parent_block_time // BLOCK_TIME_TARGET, parent_gas_limit * MAX_GAS_TARGET_PERCENT // 100)
        parent_base_fee_per_gas = self.parent(block).base_fee_per_gas
        parent_gas_used = self.parent(block).gas_used

        ...

        if parent_gas_used == parent_adjusted_gas_target:
            expected_base_fee_per_gas = parent_base_fee_per_gas
        elif parent_gas_used &gt; parent_adjusted_gas_target:
            gas_used_delta = parent_gas_used - parent_adjusted_gas_target
            base_fee_per_gas_delta = max(parent_base_fee_per_gas * gas_used_delta // parent_base_gas_target // BASE_FEE_MAX_CHANGE_DENOMINATOR, 1)
            expected_base_fee_per_gas = parent_base_fee_per_gas + base_fee_per_gas_delta
        else:
            gas_used_delta = parent_adjusted_gas_target - parent_gas_used
            base_fee_per_gas_delta = parent_base_fee_per_gas * gas_used_delta // parent_base_gas_target // BASE_FEE_MAX_CHANGE_DENOMINATOR
            expected_base_fee_per_gas = parent_base_fee_per_gas - base_fee_per_gas_delta
        
        ...

    ...
```

## Rationale

### Mechanism

The proposed new base fee calculation only adjusts the block gas target by scaling it with the block time, capped at a maximum percent of the overall block gas limit:

#### Current Base Fee Calculation

![](/EIPs/assets/eip-4396/old_formula.png)

#### Proposed Base Fee Calculation

![](/EIPs/assets/eip-4396/new_formula.png)

This new calculation thus targets a stable throughput per time instead of per block.

### Limitations

Under PoS, block time increases always come in multiples of full blocks (e.g. a single missed slot = 24s instead of 12s block time). Accounting for this already requires doubling the block gas target, even for a single missed slot. However, with the block elasticity currently set to 2, this target would be equal to the block gas limit. Having the new target equal to the block gas limit is less than ideal, and thus is reduced slightly, according to the `MAX_GAS_TARGET_PERCENT` parameter. The reason for the existence of this parameter is twofold:

- Ensure that the signal remains meaningful: A target equal to or greater than the gas limit could never be reached, so the base fee would always be reduced after a missed slot.
- Ensure that the base fee can still react to genuine demand increases: During times of many offline block proposers (and thus many missed slots), genuine demand increases still need a way to eventually result in a base fee increase, to avoid a fallback to a first-price priority fee auction.

However, this means that even a single missed slot cannot be fully compensated. Even worse, any second or further sequential missed slot cannot be compensated for at all, as the gas target is already at its max. This effect becomes more pronounced as the share of offline validators increases:

![](/EIPs/assets/eip-4396/degradation.png)

As can be observed, while this EIP does indeed increase the robustness of the network throughput in cases of offline validators, it does so imperfectly. Furthermore, there is a tradeoff effected by the `MAX_GAS_TARGET_PERCENT` parameter, with a higher value resulting in a higher network robustness, but a more impaired base fee adjustment mechanism during times of frequent missed slots.

### Possible Extensions

These limitations directly result from the design goal of a minimal change, to maximize chances of being included in the merge. There are natural ways of extending the EIP design to more effectively handle offline validators, at the expense of somewhat more extensive changes:

#### Persistent Multi-Slot Buffer

To be able to compensate multiple consecutive missed slots, a gas buffer could be introduced, that would allow the gas beyond the block elasticity to be carried forward to future blocks. To avoid long-run buffer accumulation that would delay a return to normal operations once block proposers are back online, a cap on the buffer would be added. Even for a relatively small buffer cap, the throughput robustness is significantly improved:

![](/EIPs/assets/eip-4396/degradation_buffers.png)

With an elasticity still at 2, there is no way of avoiding the eventual breakdown for more than 50% offline block proposers.

The main implementation complexity for this approach comes from the introduction of the buffer as a new persistent field. To retain the ability for calculating base fees only based on headers, it would have to be added to the block header.

#### Increased Block Elasticity

In addition to the introduction of a buffer, increasing the block elasticity is another tool for increasing throughput robustness. The following diagram shows the effect of different elasticity levels, both in the presence and absence of a persistent buffer:

![](/EIPs/assets/eip-4396/degradation_elasticity.png)

Again, a clear positive effect can be observed.

The main additional complexity here would come from the increased peak load (networking, compute &amp; disk access) of multiple sequential overfull blocks. Note though that PoS with its minimum block time of 12s significantly reduces worst case peak stress as compared to PoW.

## Backwards Compatibility

The EIP has minimal impact on backwards compatibility, only requiring updates to existing base fee calculation tooling.

## Test Cases
tbd

## Reference Implementation
tbd

## Security Considerations

### Timestamp Manipulation

Under PoW, miners are in control over the timestamp field of their blocks. While there are some enforced limits to valid timestamps, implications regarding potential timestamp manipulation are nontrivial and remain unexplored for this EIP.

Under PoS, each slot has a [fixed assigned timestamp](https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/merge/beacon-chain.md#process_execution_payload), rendering any timestamp manipulation by block proposers impossible.

### Suppressing Base Fee Increases
As discussed in the rationale, a high value for `MAX_GAS_TARGET_PERCENT` during times of many offline block proposers results in a small remaining signal space for genuine demand increases that should result in base fee increases. This in turn decreases the cost for block proposers for suppresing these base fee increases, instead forcing the fallback to a first-price priority fee auction.

While the arguments of incentive incompatibility for base fee suppression of the base EIP-1559 case still apply here, with a decreasing cost of this individually irrational behavior the risk for overriding psychological factors becomes more significant.

Even in such a case the system degradation would however be graceful, as it would only temporarily suspend the base fee burn. As soon as the missing block proposers would come back online, the system would return to its ordinary EIP-1559 equilibrium.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 28 Oct 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4396</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4396</guid>
      </item>
    
      <item>
        <title>Supplant DIFFICULTY opcode with PREVRANDAO</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4399-supplant-difficulty-opcode-with-random/7368</comments>
        
        <description>## Abstract

This EIP supplants the semantics of the return value of existing `DIFFICULTY (0x44)` opcode and renames the opcode to `PREVRANDAO (0x44)`.

The return value of the `DIFFICULTY (0x44)` instruction after this change is the output of the randomness beacon provided by the beacon chain.


## Motivation

Applications may benefit from using the randomness accumulated by the beacon chain. Thus, randomness outputs produced by the beacon chain should be accessible in the EVM.

At the point of `TRANSITION_BLOCK` of the Proof-of-Stake (PoS) upgrade described in [EIP-3675](/EIPs/EIPS/eip-3675), the `difficulty` block field **MUST** be `0` thereafter because there is no longer any Proof-of-Work (PoW) seal on the block. This means that the `DIFFICULTY (0x44)` instruction no longer has it&apos;s previous semantic meaning, nor a clear &quot;correct&quot; value to return.

Given prior analysis on the usage of `DIFFICULTY`, the value returned by the instruction mixed with other values is a common pattern used by smart contracts to obtain randomness. The instruction with the same number as the `DIFFICULTY` opcode returning outputs of the beacon chain RANDAO implementation makes the upgrade to PoS backwards compatible for existing smart contracts obtaining randomness from the `DIFFICULTY` instruction.

Additionally, changes proposed by this EIP allow for smart contracts to determine whether the upgrade to the PoS has already happened. This can be done by analyzing the return value of the `DIFFICULTY` instruction. A value greater than `2**64` indicates that the transaction is being executed in the PoS block. Decompilers and other similar tooling may also use this trick to discern the new semantics of the instruction if data of the block including the transaction in question is available.


## Specification

### Definitions

* **`TRANSITION_BLOCK`** The definition of this block can be found in the Definitions section of [EIP-3675](/EIPs/EIPS/eip-3675#definitions).

### Block structure

Beginning with `TRANSITION_BLOCK`, client software **MUST** set the value of the `mixHash`, i.e. the field with the number `13` (0-indexed) in a block header, to the latest RANDAO mix of the post beacon state of the previous block.

### EVM

Beginning with `TRANSITION_BLOCK`, the `DIFFICULTY (0x44)` instruction **MUST** return the value of the `mixHash` field.

*Note*: The gas cost of the `DIFFICULTY (0x44)` opcode remains unchanged.

### Renaming

The `mixHash` field **SHOULD** further be renamed to `prevRandao`.

The `DIFFICULTY (0x44)` opcode **SHOULD** further be renamed to `PREVRANDAO (0x44)`.


## Rationale

### Including RANDAO output in the block header

Including a RANDAO output in the block header provides a straightforward method of accessing it from inside of the EVM as block header data is already available in the EVM context.

Additionally, this ensures that the execution layer can be fully executed with the block alone rather than requiring extra inputs from the PoS consensus layer.

Mixing the randomness into a block header may contribute to uniqueness of the block hash in the case when values of other fields of the block header match the corresponding values of the header of another block.

### Using `mixHash` field instead of `difficulty`

The `mixHash` header field is used instead of `difficulty` to avoid a class of hidden forkchoice bugs after the PoS upgrade.

Client software implementing pre-EIP-3675 logic heavily depends on the `difficulty` value as total difficulty computation is the basis of the PoW fork choice rule. Setting the `difficulty` field to `0` at the PoS upgrade aims to reduce the surface of bugs related to the total difficulty value growing after the upgrade.

Additionally, any latent total difficulty computation after the PoS upgrade would become overflow prone if the randomness output supplanted the value of the `difficulty` field.

### Reusing existing field instead of appending a new one

The `mixHash` field is deprecated at the PoS upgrade and set to zero bytes array thereafter. Reusing an existing field as a place for the randomness output saves 32 bytes per block and effectively removes the deprecation of one of the fields induced by the upgrade.

### Reusing the `DIFFICULTY` opcode instead of introducing a new one

See the [Motivation](#motivation).

### Renaming the field and the opcode

The renaming should be done to make the field and the opcode names semantically sound.

### Using `TRANSITION_BLOCK` rather than a block or slot number

By utilizing `TRANSITION_BLOCK` to trigger the change in logic defined in this EIP rather than a block or slot number, this EIP is tightly coupled to the PoS upgrade defined by [EIP-3675](/EIPs/EIPS/eip-3675).

By tightly coupling to the PoS upgrade, we ensure that there is no discontinuity for the usecase of this opcode for randomness -- the primary [motivation](#motivation) for re-using `DIFFICULTY` rather than creating a new opcode.

### Using `2**64` threshold to determine PoS blocks

The probability of RANDAO value to fall into the range between `0` and `2**64` and, thus, to be mixed with PoW difficulty values, is drastically low. Though, proposed threshold might seem to have insufficient distance from difficulty values on Ethereum Mainnet (they are currently around `2**54`), it requires a thousand times increase of the hashrate to make this threshold insecure. Such an increase is considered impossible to occur before the upcoming consensus upgrade.


## Backwards Compatibility

This EIP introduces backward incompatible changes to the execution and validation of EVM state transitions. As written, this EIP utilizes `TRANSITION_BLOCK` and is thus tightly coupled with the PoS upgrade introduced in [EIP-3675](/EIPs/EIPS/eip-3675). If this EIP is to be adopted, it **MUST** be scheduled at the same time as EIP-3675.

Additionally, the changes proposed might be backward incompatible for the following categories of applications:
* Applications that use the value returned by the `DIFFICULTY` opcode as the PoW `difficulty` parameter
* Applications with logic that depends on the `DIFFICULTY` opcode returning a relatively small number with respect to the full 256-bit size of the field.

The first category is already affected by switching the consensus mechanism to PoS and no additional breaking changes are introduced by this specification.

The second category is comprised of applications that use the return value of the `DIFFICULTY` opcode in operations that might cause either overflow or underflow errors. While it is theoretically possible to author an application where a change in the range of possible values this opcode may return could lead to a security vulnerability, the chances of that are negligible.


## Test Cases

* In one of ancestors of `TRANSITION_BLOCK` deploy a contract that stores return value of  `DIFFICULTY (0x44)` to the state
* Check that value returned by `DIFFICULTY (0x44)` in transaction executed within the parent of `TRANSITION_BLOCK` equals `difficulty` field value
* Check that value returned by `PREVRANDAO (0x44)` in transaction executed within `TRANSITION_BLOCK` equals `prevRandao` field value


## Security Considerations

The `PREVRANDAO (0x44)` opcode in PoS Ethereum (based on the beacon chain RANDAO implementation) is a source of randomness with different properties to the randomness supplied by `BLOCKHASH (0x40)` or `DIFFICULTY (0x44)` opcodes in the PoW network.

### Biasability

The beacon chain RANDAO implementation gives every block proposer 1 bit of influence power per slot. Proposer may deliberately refuse to propose a block on the opportunity cost of proposer and transaction fees to prevent beacon chain randomness (a RANDAO mix) from being updated in a particular slot.

An effect of proposer&apos;s influence power is limited in time and lasts until the first honest RANDAO reveal is made afterwards. This limitation does also exist in the case when proposers of `n` consecutive slots are colluding to get `n` bits of influence power. Simply speaking, one honest block proposal is enough to unbias the RANDAO even if it was biased during several slots in a row.

Additionally, semantics of the `PREVRANDAO (0x44)` instruction gives proposers another way to gain 1 bit of influence power on applications. Biased proposer may censor a rolling the dice transaction to force it to be included into the next block, thus, force it to use a RANDAO mix that the proposer knows in advance. The opportunity cost in this case would be negligible.

### Predictability

Obviously, historical randomness provided by any decentralized oracle is 100% predictable. On the contrary, the randomness that is revealed in the future is predictable up to a limited extent.

A list of inputs influencing future randomness on the beacon chain consists of but is not limited to the following items:
* **Accumulated randomness.** A RANDAO mix produced by the beacon chain in the last slot of epoch `N` is the main input to the function defining block proposers in each slot of epoch `N + MIN_SEED_LOOKAHEAD + 1`, i.e. it is the main factor defining future RANDAO revealers.
* **Number of active validators.** A number of active validators throughout an epoch is another input to the block proposer function.
* **Effective balance.** All else being equal, the lower the effective balance of a validator the lower the chance this validator has to be designated as a proposer in a slot.
* **Accidentally missed proposals.** Network conditions and other factors that are resulting in accidentally missed proposals is a source of highly qualitative entropy that impacts RANDAO mixes. Usual rate of missed proposals on the Mainnet is about `1%`.

These inputs may be predictable and malleable on a short range of slots but the longer the attempted lookahead the more entropy is accumulated by the beacon chain.

### Tips for application developers

The following tips attempt to reduce predictability and biasability of randomness outputs returned by `PREVRANDAO (0x44)`:

1. Make your applications rely on the future randomness with a reasonably high lookahead. For example, an application stops accepting bids at the end of epoch `K` and uses a RANDAO mix produced in slot `K + N + ε` to roll the dice, where `N` is a lookahead in epochs and `ε` is a few slots into epoch `N + 1`.
2. At least four epochs of lookahead results in the following outcome:
  * A proposer set of epoch `N + 1` isn&apos;t known at the end of epoch `K` breaking a direct link between bidders and dice rollers
  * A number of active validators is updated at the end of each epoch affecting a set of proposers of next epochs, thus, impacting a RANDAO mix used by the application to roll the dice
  * Due to Mainnet statistics, there is about a `100%` chance for the network to accidentally miss a proposal during this period of time which reduces predictability of a RANDAO mix used to roll the dice.
3. Setting `ε` to a small number, e.g. 2 or 4 slots, gives a third party a little time to gain influence power on the future randomness that is being used to roll the dice. This amount of time is defined by `MIN_SEED_LOOKAHEAD` parameter and is about 6 minutes on the Mainnet.

A reasonably high distance between bidding and rolling the dice attempts to leave low chance for bidders controlling a subset of validators to directly exploit their influence power. Ultimately, this chance depends on the type of the game and on a number of controlled validators. For instance, a chance of a single validator to affect a one-time game is negligible, and becomes bigger for multiple validators in a repeated game scenario.


## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 30 Oct 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4399</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4399</guid>
      </item>
    
      <item>
        <title>EIP-721 Consumable Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/EIP-4400-EIP721consumer-extension/7371</comments>
        
        <description>## Abstract

This specification defines standard functions outlining a `consumer` role for instance(s) of [EIP-721](/EIPs/EIPS/eip-721). An implementation allows reading the current `consumer` for a given NFT (`tokenId`) along with a standardized event for when an `consumer` has changed. The proposal depends on and extends the existing [EIP-721](/EIPs/EIPS/eip-721).

## Motivation

Many [EIP-721](/EIPs/EIPS/eip-721) contracts introduce their own custom role that grants permissions for utilising/consuming a given NFT instance. The need for that role stems from the fact that other than owning the NFT instance, there are other actions that can be performed on an NFT. For example, various metaverses use `operator` / `contributor` roles for Land (EIP-721), so that owners of the land can authorise other addresses to deploy scenes to them (f.e. commissioning a service company to develop a scene).

It is common for NFTs to have utility other than ownership. That being said, it requires a separate standardized consumer role, allowing compatibility with user interfaces and contracts, managing those contracts.

Having a `consumer` role will enable protocols to integrate and build on top of dApps that issue EIP-721 tokens. One example is the creation of generic/universal NFT renting marketplaces.

Example of kinds of contracts and applications that can benefit from this standard are:
- metaverses that have land and other types of digital assets in those metaverses (scene deployment on land, renting land / characters / clothes / passes to events etc.)
- NFT-based yield-farming. Adopting the standard enables the &quot;staker&quot; (owner of the NFT) to have access to the utility benefits even after transferring his NFT to the staking contract

## Specification

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.

Every contract compliant to the `EIP721Consumable` extension MUST implement the `IEIP721Consumable` interface. The **consumer extension** is OPTIONAL for EIP-721 contracts.

```solidity
/// @title EIP-721 Consumer Role extension
///  Note: the EIP-165 identifier for this interface is 0x953c8dfa
interface IEIP721Consumable /* is EIP721 */ {

    /// @notice Emitted when `owner` changes the `consumer` of an NFT
    /// The zero address for consumer indicates that there is no consumer address
    /// When a Transfer event emits, this also indicates that the consumer address
    /// for that NFT (if any) is set to none
    event ConsumerChanged(address indexed owner, address indexed consumer, uint256 indexed tokenId);

    /// @notice Get the consumer address of an NFT
    /// @dev The zero address indicates that there is no consumer
    /// Throws if `_tokenId` is not a valid NFT
    /// @param _tokenId The NFT to get the consumer address for
    /// @return The consumer address for this NFT, or the zero address if there is none
    function consumerOf(uint256 _tokenId) view external returns (address);

    /// @notice Change or reaffirm the consumer address for an NFT
    /// @dev The zero address indicates there is no consumer address
    /// Throws unless `msg.sender` is the current NFT owner, an authorised
    /// operator of the current owner or approved address
    /// Throws if `_tokenId` is not valid NFT
    /// @param _consumer The new consumer of the NFT
    function changeConsumer(address _consumer, uint256 _tokenId) external;
}
```

Every contract implementing the `EIP721Consumable` extension is free to define the permissions of a `consumer` (e.g. what are consumers allowed to do within their system) with only one exception - consumers MUST NOT be considered owners, authorised operators or approved addresses as per the EIP-721 specification. Thus, they MUST NOT be able to execute transfers &amp; approvals.

The `consumerOf(uint256 _tokenId)` function MAY be implemented as `pure` or `view`.

The `changeConsumer(address _consumer, uint256 _tokenId)` function MAY be implemented as `public` or `external`.

The `ConsumerChanged` event MUST be emitted when a consumer is changed.

On every `transfer`, the consumer MUST be changed to a default address. It is RECOMMENDED for implementors to use `address(0)` as that default address.

The `supportsInterface` method MUST return `true` when called with `0x953c8dfa`.

## Rationale

Key factors influencing the standard:

- Keeping the number of functions in the interfaces to a minimum to prevent contract bloat
- Simplicity
- Gas Efficiency
- Not reusing or overloading other already existing roles (e.g. owners, operators, approved addresses)

### Name

The chosen name resonates with the purpose of its existence. Consumers can be considered entities that utilise the token instances, without necessarily having ownership rights to it.

The other name for the role that was considered was `operator`, however it is already defined and used within the `EIP-721` standard.

### Restriction on the Permissions

There are numerous use-cases where a distinct role for NFTs is required that MUST NOT have owner permissions. A contract that implements the consumer role and grants ownership permissions to the consumer renders this standard pointless.

## Backwards Compatibility

This standard is compatible with current EIP-721 standards. There are no other standards that define a similar role for NFTs and the name (`consumer`) is not used by other EIP-721 related standards.

## Test Cases

Test cases are available in the reference implementation [here](/EIPs/assets/eip-4400/test/erc721-consumable.ts).

## Reference Implementation

The reference implementation can be found [here](/EIPs/assets/eip-4400/contracts/ERC721Consumable.sol).

## Security Considerations

Implementors of the `EIP721Consumable` standard must consider thoroughly the permissions they give to `consumers`. Even if they implement the standard correctly and do not allow transfer/burning of NFTs, they might still provide permissions to the `consumers` that they might not want to provide otherwise and should be restricted to `owners` only.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 30 Oct 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4400</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4400</guid>
      </item>
    
      <item>
        <title>Described Transactions</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/discussion-eip-4430-described-transactions/8762</comments>
        
        <description>## Abstract

Use a contract method to provide *virtual functions* which can generate
a human-readable description at the same time as the machine-readable
bytecode, allowing the user to agree to the human-readable component
in a UI while the machine can execute the bytecode once accepted.


## Motivation

When using an Ethereum Wallet (e.g. MetaMask, Clef, Hardware Wallets)
users must accept a transaction before it can be submitted (or the user
may decline).

Due to the complexity of Ethereum transactions, wallets are very limited
in their ability to provide insight into the effects of a transaction
that the user is approving; outside special-cased support for common
transactions such as ERC20 transfers, this often amounts to asking the
user to sign an opaque blob of binary data.

This EIP presents a method for dapp developers to enable a more comfortable
user experience by providing wallets with a means to generate a better
description about what the contract claims will happen.

It does not address malicious contracts which wish to lie, it only addresses
honest contracts that want to make their user&apos;s life better. We believe
that this is a reasonable security model, as transaction descriptions can be
audited at the same time as contract code, allowing auditors and code
reviewers to check that transaction descriptions are accurate as part of
their review.


## Specification

The **description** (a string) and the matching **execcode** (bytecode)
are generated simultaneously by evaluating the method on a contract:

```solidity
function eipXXXDescribe(bytes inputs, bytes32 reserved) view returns (string description, bytes execcode)
```

The human-readable **description** can be shown in any client which supports
user interaction for approval, while the **execcode** is the data that
should be included in a transaction to the contract to perform that operation.

The method must be executable in a static context, (i.e. any side effects,
such as logX, sstore, etc.), including through indirect calls may be ignored.

During evaluation, the `ADDRESS` (i.e. `to`), `CALLER` (i.e. `from`), `VALUE`,
and `GASPRICE` must be the same as the values for the transaction being
described, so that the code generating the description can rely on them.

When executing the bytecode, best efforts should be made to ensure `BLOCKHASH`,
`NUMBER`, `TIMESTAMP` and `DIFFICULTY` match the `&quot;latest&quot;` block. The
`COINBASE` should be the zero address.

The method may revert, in which case the signing must be aborted.


## Rationale

### Meta Description

There have been many attempts to solve this problem, many of which attempt
to examine the encoded transaction data or message data directly.

In many cases, the information that would be necessary for a meaningful
description is not present in the final encoded transaction data or message
data.

Instead this EIP uses an indirect description of the data.

For example, the `commit(bytes32)` method of ENS places a commitment
**hash** on-chain. The hash contains the **blinded** name and address; 
since the name is blinded, the encoded data (i.e. the hash) no longer 
contains the original values and is insufficient to access the necessary 
values to be included in a description.

By instead describing the commitment indirectly (with the original information
intact: NAME, ADDRESS and SECRET) a meaningful description can be computed
(e.g. &quot;commit to NAME for ADDRESS (with SECRET)&quot;) and the matching data can
be computed (i.e. `commit(hash(name, owner, secret))`).

This technique of blinded data will become much more popular with L2
solutions, which use blinding not necessarily for privacy, but for 
compression.

### Entangling the Contract Address

To prevent signed data being used across contracts, the contract address
is entanlged into both the transaction implicitly via the `to` field.


### Alternatives

- NatSpec and company are a class of more complex languages that attempt to describe the encoded data directly. Because of the language complexity they often end up being quite large requiring entire runtime environments with ample processing power and memory, as well as additional sandboxing to reduce security concerns. One goal of this is to reduce the complexity to something that could execute on hardware wallets and other simple wallets. These also describe the data directly, which in many cases (such as blinded data), cannot adequately describe the data at all

- Custom Languages; due to the complexity of Ethereum transactions, any language used would require a lot of expressiveness and re-inventing the wheel. The EVM already exists (it may not be ideal), but it is there and can handle everything necessary.

- Format Strings (e.g. Trustless Signing UI Protocol; format strings can only operate on the class of regular languages, which in many cases is insufficient to describe an Ethereum transaction. This was an issue quite often during early attempts at solving this problem.

- The signTypedData [EIP-712](/EIPs/EIPS/eip-712) has many parallels to what this EIP aims to solve


## Backwards Compatibility

This does not affect backwards compatibility.


## Reference Implementation

I will add deployed examples by address and chain ID.


## Security Considerations

### Escaping Text

Wallets must be careful when displaying text provided by contracts and proper
efforts must be taken to sanitize it, for example, be sure to consider:

- HTML could be embedded to attempt to trick web-based wallets into executing code using the script tag (possibly uploading any private keys to a server)
- In general, extreme care must be used when rendering HTML; consider the ENS names `&lt;span style=&quot;display:none&quot;&gt;not-&lt;/span&gt;ricmoo.eth` or `&amp;thinsp;ricmoo.eth`, which if rendered without care would appear as `ricmoo.eth`, which it is not
- Other marks which require escaping could be included, such as quotes (`&quot;`), formatting (`\n` (new line), `\f` (form feed), `\t` (tab), any of many non-standard whitespaces), back-slassh (`\`)
- UTF-8 has had bugs in the past which could allow arbitrary code execution and crashing renderers; consider using the UTF-8 replacement character (or *something*) for code-points outside common planes or common sub-sets within planes
- Homoglyphs attacks
- Right-to-left mark may affect rendering
- Many other things, deplnding on your environment


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 07 Nov 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4430</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4430</guid>
      </item>
    
      <item>
        <title>Bound Historical Data in Execution Clients</title>
        <category>Standards Track/Networking</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4444-bound-historical-data-in-execution-clients/7450</comments>
        
        <description>## Abstract

Clients must stop serving historical headers, bodies, and receipts older than one year on the p2p layer. Clients may locally prune this historical data.

## Motivation

Historical blocks and receipts currently occupy more than 400GB of disk space (and growing!). Therefore, to validate the chain, users must typically have a 1TB disk.

Historical data is not necessary for validating new blocks, so once a client has synced the tip of the chain, historical data is only retrieved when requested explicitly over the JSON-RPC or when a peer attempts to sync the chain. By pruning the history, this proposal reduces the disk requirements for users. Pruning history also allows clients to remove code that processes historical blocks. This means that execution clients don&apos;t need to maintain code paths that deal with each upgrade&apos;s compounding changes.

Finally, this change will result in less bandwidth usage on the network as clients adopt more lightweight sync strategies based on the PoS weak subjectivity assumption.

## Specification

| Parameter | Value | Description |
| - | - | - |
| `HISTORY_PRUNE_EPOCHS` | 82125 | A year in beacon chain epochs |

Clients SHOULD NOT serve headers, block bodies, and receipts that are older than `HISTORY_PRUNE_EPOCHS` epochs on the p2p network.

Clients MAY locally prune headers, block bodies, and receipts that are older than `HISTORY_PRUNE_EPOCHS` epochs.

#### Bootstrapping and syncing

This EIP impacts the way clients bootstrap and sync. Clients will not be able to full sync using devp2p since historical data will no longer be served.

Clients MUST use a valid Weak Subjectivity Checkpoint to bootstrap from a more recent view of the chain. For the purpose of syncing, clients treat weak subjectivity checkpoints as the genesis block. We call this method &quot;checkpoint sync&quot;.

For the purposes of this proposal, we assume clients always start with a configured and valid weak subjectivity checkpoint. The way this is achieved is out-of-scope for this proposal.

## Rationale

This proposal forces clients to stop serving old historical data over p2p. We make this explicit to force clients to seek historical data from other sources, instead of relying on the optional behavior of some clients which would result in quality degradation.

### Why a year?

This proposal sets `HISTORY_PRUNE_EPOCHS` to 82125 epochs (one earth year). This constant is large enough to provide sufficient room for the Weak Subjectivity Period to grow, and it&apos;s also small enough so as to not occupy too much disk space.

## Backwards Compatibility

### Preserving historical data

This proposal impacts nodes that make use of historical data (e.g. web3 applications that display history of blocks, transactions or accounts). Preserving the history of Ethereum is fundamental and we believe there are various out-of-band ways to achieve this.

Historical data can be packaged and shared via torrent magnet links or over networks like IPFS. Furthermore, systems like the Portal Network or The Graph can be used to acquire historical data.

Clients should allow importing and exporting of historical data. Clients can provide scripts that fetch/verify data and automatically import them.

### Full syncing from genesis

Full syncing will no longer be possible over the p2p network. However, we do want to allow interested parties to do so on their own.

We suggest that a specialized &quot;full sync&quot; client is built. The client is a shim that pieces together different releases of execution engines and can import historical blocks to validate the entire Ethereum chain from genesis and generate all other historical data.

It&apos;s important to also note that although archive nodes with &quot;state sync&quot; functionality are in development, full sync is currently the only reliable way to bootstrap them. Clients that wish to continue providing archive support would need the ability to import historical blocks retrieved out-of-band and retain support for each historical upgrade of the network.

### User experience

This proposal impacts the UX for setting up applications that use historical data. Hence we suggest that clients introduce this change in two phases:

In the first phase, clients don&apos;t prune historical data by default. They introduce a command line option similar to geth&apos;s `--txlookuplimit` that users can use if they want to prune historical data.

In the second phase, history is pruned by default and the command line option is removed. Clients assume that users will find and import data in an out-of-band way.

### JSON-RPC changes

After this proposal is implemented, certain JSON-RPC endpoints (e.g. like `getBlockByHash`) won&apos;t be able to tell whether a given hash is invalid or just outdated. Other endpoints like `getLogs` will simply no longer have the data the user is requesting. The way this regression should be handled by applications or clients is out-of-scope for this proposal.

## Security Considerations

### Relying on weak subjectivity

With the move to PoS, it&apos;s essential for security to use valid weak subjectivity checkpoints because of long-range attacks.

This proposal relies on the weak subjectivity assumption and assumes that clients will not bootstrap with an invalid or old WS checkpoint.

This proposal also assumes that the weak subjectivity period will never be longer than `HISTORY_PRUNE_EPOCHS`. If that were to happen, clients with an old weak subjectivity checkpoint would never be able to &quot;checkpoint sync&quot; since the p2p network would not be able to provide the required data.

### Centralization/censorship risk

There are censorship/availability risks if there is a lack of incentives to keep historical data.

It&apos;s important that Ethereum historical data are preserved and seeded by independent organizations, and their availability should be checked frequently. We consider these mechanisms as out-of-scope for this proposal.

Furthermore, there is a risk that more dapps will rely on centralized services for acquiring historical data because it will be harder to setup a full node.

### Confusion with other proposals

Because there are a number of alternative proposals for reducing the execution client&apos;s footprint on disk, we&apos;ve decided to enforce a specific pronunciation of the EIP. When pronouncing the EIP number, it **MUST** be pronounced EIP &quot;four fours&quot;. All other pronunciation are incorrect.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Tue, 02 Nov 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4444</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4444</guid>
      </item>
    
      <item>
        <title>Transaction calldata gas cost reduction with total calldata limit</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4488-transaction-calldata-gas-cost-reduction-with-total-calldata-limit/7555</comments>
        
        <description>## Abstract

Decrease transaction calldata gas cost, and add a limit of how much total transaction calldata can be in a block.

## Motivation

Rollups are in the short and medium term, and possibly the long term, the only trustless scaling solution for Ethereum. Transaction fees on L1 have been very high for months and there is greater urgency in doing anything required to help facilitate an ecosystem-wide move to rollups. Rollups are significantly reducing fees for many Ethereum users: Optimism and Arbitrum frequently provide fees that are ~3-8x lower than the Ethereum base layer itself, and ZK rollups, which have better data compression and can avoid including signatures, have fees ~40-100x lower than the base layer.

However, even these fees are too expensive for many users. The long-term solution to the long-term inadequacy of rollups by themselves has always been [data sharding](https://github.com/ethereum/consensus-specs#sharding), which would add ~1-2 MB/sec of dedicated data space for rollups to the chain. However, data sharding will still take a considerable amount of time to finish implementing and deploying. Hence, a short-term solution to further cut costs for rollups, and to incentivize an ecosystem-wide transition to a rollup-centric Ethereum, is desired.

This EIP presents a quick-to-implement short-term solution that also mitigates security risks.

## Specification

| Parameter | Value |
| - | - |
| `NEW_CALLDATA_GAS_COST` | `3` |
| `BASE_MAX_CALLDATA_PER_BLOCK` | `1,048,576` |
| `CALLDATA_PER_TX_STIPEND` | `300` |

Reduce the gas cost of transaction calldata to `NEW_CALLDATA_GAS_COST` per byte, regardless of whether the byte is zero or nonzero.

Add a rule that a block is only valid if `sum(len(tx.calldata) for tx in block.txs) &lt;= BASE_MAX_CALLDATA_PER_BLOCK + len(block.txs) * CALLDATA_PER_TX_STIPEND`.

## Rationale

A natural alternative proposal is to decrease `NEW_CALLDATA_GAS_COST` without adding a limit. However, this presents a security concern: today, the average block size [is 60-90 kB](https://etherscan.io/chart/blocksize), but the _maximum_ block size is `30M / 16 = 1,875,000` bytes (plus about a kilobyte of block and tx overhead). Simply decreasing the calldata gas cost from 16 to 3 would increase the maximum block size to 10M bytes. This would push the Ethereum p2p networking layer to unprecedented levels of strain and risk breaking the network; some previous live tests of ~500 kB blocks a few years ago had already taken down a few bootstrap nodes.

The decrease-cost-and-cap proposal achieves most of the benefits of the decrease, as rollups are unlikely to _dominate_ Ethereum block space in the short term future and so 1.5 MB will be sufficient, while preventing most of the security risk.

Historically, the Ethereum protocol community has been suspicious of multi-dimensional resource limit rules (in this case, gas and calldata) because such rules greatly increase the complexity of the block packing problem that proposers (today miners, post-merge validators) need to solve. Today, proposers can generate blocks with near-optimal fee revenue by simply choosing transactions in highest-to-lowest order of priority fee. In a multi-dimensional world, proposers would have to deal with multi-dimensional constraints. Multi-dimensional knapsack problems are much more complicated than the single-dimensional equivalent, and well-optimized proprietary implementations built by pools may well outperform default open source implementations.

Today, there are two key reasons why this is less of a problem than before:

1. [EIP-1559](/EIPs/EIPS/eip-1559) means that, at least most of the time, the problem that block proposers are solving is _not_ a knapsack problem. Rather, block proposers are simply including all the transactions they can find with sufficient base fee and priority fee. Hence, naive algorithms will also frequently generate close-to-optimal results.
2. The existence of sophisticated proprietary strategies for miner extractable value (MEV) extraction means that decentralized optimal block production is already in the medium and long term a lost cause. Research is instead going into solutions that separate away the specialization-friendly task of block body generation from the role of a validator (&quot;proposer/builder separation&quot;). Instead of being a fundamental change, two-dimensional knapsack problems today would be merely &quot;yet another&quot; MEV opportunity.

Hence, it&apos;s worth rethinking the historical opposition to multi-dimensional resource limits and considering them as a pragmatic way to simultaneously achieve moderate scalability gains while retaining security.

Additionally, the stipend mechanism makes the two-dimensional optimization problem even less of an issue in practice. 90% of all transactions ([sample](/EIPs/assets/eip-4488/gas_and_calldata_sample.csv) taken from blocks `13500000, 13501000 ... 13529000`) have &lt;300 bytes of calldata. Hence, if a naive transaction selection algorithm overfills the calldata of a block that the proposer is creating, the proposer will still be able to keep adding transactions from 90% of their mempool.

## Backwards Compatibility

This is a backwards incompatible gas repricing that requires a scheduled network upgrade.

Users will be able to continue operating with no changes.

Miners will be able to continue operating with no changes except for a rule to stop adding new transactions into a block when the total calldata size reaches the maximum. However, there are pragmatic heuristics that they could add to achieve closer-to-optimal returns in such cases: for example, if a block fills up to the size limit, they could repeatedly remove the last data-heavy transaction and replace it with as many data-light transactions as possible, until doing so is no longer profitable.

## Security Considerations

The _burst_ data capacity of the chain does not increase as a result of this proposal (in fact, it slightly decreases). However, the _average_ data capacity will increase. This means that the storage requirements of history-storing will go up. A worst-case scenario would be a theoretical long-run maximum of ~1,262,861 bytes per 12 sec slot, or ~3.0 TB per year.

We recommend [EIP-4444](/EIPs/EIPS/eip-4444) or some similar history expiry proposal be implemented either at the same time or soon after this EIP to mitigate this risk.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
 
</description>
        <pubDate>Tue, 23 Nov 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4488</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4488</guid>
      </item>
    
      <item>
        <title>Permit for ERC-721 NFTs</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-extending-erc2612-style-permits-to-erc721-nfts/7519/2</comments>
        
        <description>## Abstract
The &quot;Permit&quot; approval flow outlined in [ERC-2612](/EIPs/EIPS/eip-2612) has proven a very valuable advancement in UX by creating gasless approvals for ERC20 tokens. This EIP extends the pattern to ERC-721 NFTs. This EIP borrows heavily from ERC-2612.

This requires a separate EIP due to the difference in structure between ERC-20 and ERC-721 tokens. While ERC-20 permits use value (the amount of the ERC-20 token being approved) and a nonce based on the owner&apos;s address, ERC-721 permits focus on the `tokenId` of the NFT and increment nonce based on the transfers of the NFT.

## Motivation
The permit structure outlined in [ERC-2612](/EIPs/EIPS/eip-2612) allows for a signed message (structured as outlined in [ERC-712](/EIPs/EIPS/eip-712)) to be used in order to create an approval. Whereas the normal approval-based pull flow generally involves two transactions, one to approve a contract and a second for the contract to pull the asset, which is poor UX and often confuses new users, a permit-style flow only requires signing a message and a transaction. Additional information can be found in [ERC-2612](/EIPs/EIPS/eip-2612).

[ERC-2612](/EIPs/EIPS/eip-2612) only outlines a permit architecture for ERC-20 tokens. This ERC proposes an architecture for ERC-721 NFTs, which also contain an approve architecture that would benefit from a signed message-based approval flow.

## Specification
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.

Three new functions MUST be added to [ERC-721](/EIPs/EIPS/eip-721):
```solidity
pragma solidity 0.8.10;

import &quot;./IERC165.sol&quot;;

///
/// @dev Interface for token permits for ERC-721
///
interface IERC4494 is IERC165 {
  /// ERC165 bytes to add to interface array - set in parent contract
  ///
  /// _INTERFACE_ID_ERC4494 = 0x5604e225

  /// @notice Function to approve by way of owner signature
  /// @param spender the address to approve
  /// @param tokenId the index of the NFT to approve the spender on
  /// @param deadline a timestamp expiry for the permit
  /// @param sig a traditional or EIP-2098 signature
  function permit(address spender, uint256 tokenId, uint256 deadline, bytes memory sig) external;
  /// @notice Returns the nonce of an NFT - useful for creating permits
  /// @param tokenId the index of the NFT to get the nonce of
  /// @return the uint256 representation of the nonce
  function nonces(uint256 tokenId) external view returns(uint256);
  /// @notice Returns the domain separator used in the encoding of the signature for permits, as defined by EIP-712
  /// @return the bytes32 domain separator
  function DOMAIN_SEPARATOR() external view returns(bytes32);
}
```
The semantics of which are as follows:

For all addresses `spender`, `uint256`s `tokenId`, `deadline`, and `nonce`, and `bytes` `sig`, a call to `permit(spender, tokenId, deadline, sig)` MUST set `spender` as approved on `tokenId` as long as the owner of `tokenId` remains in possession of it, and MUST emit a corresponding `Approval` event, if and only if the following conditions are met:

* the current blocktime is less than or equal to `deadline`
* the owner of the `tokenId` is not the zero address
* `nonces[tokenId]` is equal to `nonce`
* `sig` is a valid `secp256k1` or [EIP-2098](/EIPs/EIPS/eip-2098) signature from owner of the `tokenId`:
```
keccak256(abi.encodePacked(
   hex&quot;1901&quot;,
   DOMAIN_SEPARATOR,
   keccak256(abi.encode(
            keccak256(&quot;Permit(address spender,uint256 tokenId,uint256 nonce,uint256 deadline)&quot;),
            spender,
            tokenId,
            nonce,
            deadline))
));
```
where `DOMAIN_SEPARATOR` MUST be defined according to [EIP-712](/EIPs/EIPS/eip-712). The `DOMAIN_SEPARATOR` should be unique to the contract and chain to prevent replay attacks from other domains, and satisfy the requirements of EIP-712, but is otherwise unconstrained. A common choice for `DOMAIN_SEPARATOR` is:
```
DOMAIN_SEPARATOR = keccak256(
    abi.encode(
        keccak256(&apos;EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)&apos;),
        keccak256(bytes(name)),
        keccak256(bytes(version)),
        chainid,
        address(this)
));
```
In other words, the message is the following ERC-712 typed structure:
```json
{
  &quot;types&quot;: {
    &quot;EIP712Domain&quot;: [
      {
        &quot;name&quot;: &quot;name&quot;,
        &quot;type&quot;: &quot;string&quot;
      },
      {
        &quot;name&quot;: &quot;version&quot;,
        &quot;type&quot;: &quot;string&quot;
      },
      {
        &quot;name&quot;: &quot;chainId&quot;,
        &quot;type&quot;: &quot;uint256&quot;
      },
      {
        &quot;name&quot;: &quot;verifyingContract&quot;,
        &quot;type&quot;: &quot;address&quot;
      }
    ],
    &quot;Permit&quot;: [
      {
        &quot;name&quot;: &quot;spender&quot;,
        &quot;type&quot;: &quot;address&quot;
      },
      {
        &quot;name&quot;: &quot;tokenId&quot;,
        &quot;type&quot;: &quot;uint256&quot;
      },
      {
        &quot;name&quot;: &quot;nonce&quot;,
        &quot;type&quot;: &quot;uint256&quot;
      },
      {
        &quot;name&quot;: &quot;deadline&quot;,
        &quot;type&quot;: &quot;uint256&quot;
      }
    ],
    &quot;primaryType&quot;: &quot;Permit&quot;,
    &quot;domain&quot;: {
      &quot;name&quot;: erc721name,
      &quot;version&quot;: version,
      &quot;chainId&quot;: chainid,
      &quot;verifyingContract&quot;: tokenAddress
  },
  &quot;message&quot;: {
    &quot;spender&quot;: spender,
    &quot;value&quot;: value,
    &quot;nonce&quot;: nonce,
    &quot;deadline&quot;: deadline
  }
}}
```
In addition:
* the `nonce` of a particular `tokenId` (`nonces[tokenId]`) MUST be incremented upon any transfer of the `tokenId`
* the `permit` function MUST check that the signer is not the zero address

Note that nowhere in this definition do we refer to `msg.sender`. The caller of the `permit` function can be any address.

This EIP requires [EIP-165](/EIPs/EIPS/eip-165). EIP165 is already required in [ERC-721](/EIPs/EIPS/eip-721), but is further necessary here in order to register the interface of this EIP. Doing so will allow easy verification if an NFT contract has implemented this EIP or not, enabling them to interact accordingly. The interface of this EIP (as defined in EIP-165) is `0x5604e225`. Contracts implementing this EIP MUST have the `supportsInterface` function return `true` when called with `0x5604e225`.

## Rationale
The `permit` function is sufficient for enabling a `safeTransferFrom` transaction to be made without the need for an additional transaction.

The format avoids any calls to unknown code.

The `nonces` mapping is given for replay protection.

A common use case of permit has a relayer submit a Permit on behalf of the owner. In this scenario, the relaying party is essentially given a free option to submit or withhold the Permit. If this is a cause of concern, the owner can limit the time a Permit is valid for by setting deadline to a value in the near future. The deadline argument can be set to uint(-1) to create Permits that effectively never expire.

ERC-712 typed messages are included because of its use in [ERC-2612](/EIPs/EIPS/eip-2612), which in turn cites widespread adoption in many wallet providers.

While ERC-2612 focuses on the value being approved, this EIP focuses on the `tokenId` of the NFT being approved via `permit`. This enables a flexibility that cannot be achieved with ERC-20 (or even [ERC-1155](/EIPs/EIPS/eip-1155)) tokens, enabling a single owner to give multiple permits on the same NFT. This is possible since each ERC-721 token is discrete (oftentimes referred to as non-fungible), which allows assertion that this token is still in the possession of the `owner` simply and conclusively.

Whereas ERC-2612 splits signatures into their `v,r,s` components, this EIP opts to instead take a `bytes` array of variable length in order to support [EIP-2098](./eip-2098) signatures (64 bytes), which cannot be easily separated or reconstructed from `r,s,v` components (65 bytes).

## Backwards Compatibility
There are already some ERC-721 contracts implementing a `permit`-style architecture, most notably Uniswap v3. 

Their implementation differs from the specification here in that: 
 * the `permit` architecture is based on `owner`
 * the `nonce` is incremented at the time the `permit` is created
 * the `permit` function must be called by the NFT owner, who is set as the `owner`
 * the signature is split into `r,s,v` instead of `bytes`

 Rationale for differing on design decisions is detailed above.

## Test Cases

Basic test cases for the reference implementation can be found [here](https://github.com/dievardump/erc721-with-permits/tree/main/test).

In general, test suites should assert at least the following about any implementation of this EIP:
* the nonce is incremented after each transfer
* `permit` approves the `spender` on the correct `tokenId`
* the permit cannot be used after the NFT is transferred
* an expired permit cannot be used

## Reference Implementation

A reference implementation has been set up [here](https://github.com/dievardump/erc721-with-permits).

## Security Considerations

Extra care should be taken when creating transfer functions in which `permit` and a transfer function can be used in one function to make sure that invalid permits cannot be used in any way. This is especially relevant for automated NFT platforms, in which a careless implementation can result in the compromise of a number of user assets.

The remaining considerations have been copied from [ERC-2612](/EIPs/EIPS/eip-2612) with minor adaptation, and are equally relevant here:

Though the signer of a `Permit` may have a certain party in mind to submit their transaction, another party can always front run this transaction and call `permit` before the intended party. The end result is the same for the `Permit` signer, however.

Since the ecrecover precompile fails silently and just returns the zero address as `signer` when given malformed messages, it is important to ensure `ownerOf(tokenId) != address(0)` to avoid `permit` from creating an approval to any `tokenId` which does not have an approval set.

Signed `Permit` messages are censorable. The relaying party can always choose to not submit the `Permit` after having received it, withholding the option to submit it. The `deadline` parameter is one mitigation to this. If the signing party holds ETH they can also just submit the `Permit` themselves, which can render previously signed `Permit`s invalid.

The standard [ERC-20 race condition for approvals](https://swcregistry.io/docs/SWC-114) applies to `permit` as well.

If the `DOMAIN_SEPARATOR` contains the `chainId` and is defined at contract deployment instead of reconstructed for every signature, there is a risk of possible replay attacks between chains in the event of a future chain split.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 25 Nov 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4494</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4494</guid>
      </item>
    
      <item>
        <title>Non-Fungible Tokens Tied to Physical Assets</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/new-proposal-of-smart-non-fungible-token/7677</comments>
        
        <description>## Abstract

This EIP standardizes an interface for non-fungible tokens representing physical assets, such as Internet of Things (IoT) devices. These NFTs are tied to physical assets and can verify the authenticity of the tie. They can include an Ethereum address of the physical asset, permitting physical assets to sign messages and transactions. Physical assets can operate with an operating mode defined by its corresponding NFT.
 
## Motivation

This standard was developed because [EIP-721](/EIPs/EIPS/eip-721) only tracks ownership (not usage rights) and does not track the Ethereum addresses of the asset. The popularity of smart assets, such as IoT devices, is increasing. To permit secure and traceable management, these NFTs can be used to establish secure communication channels between the physical asset, its owner, and its user.

## Specification

The attributes `addressAsset` and `addressUser` are, respectively, the Ethereum addresses of the physical asset and the user. They are optional attributes but at least one of them should be used in an NFT. In the case of using only the attribute `addressUser`, two states define if the token is assigned or not to a user. `Figure 1` shows these states in a flow chart. When a token is created, transferred or unassigned, the token state is set to `notAssigned`. If the token is assigned to a valid user, the state is set to `userAssigned`.

![Figure 1 : Flow chart of the token states with `addressUser` defined (and `addressAsset` undefined)](/EIPs/assets/eip-4519/images/Figure1.jpg)
  
In the case of defining the attribute `addressAsset` but not the attribute `addressUser`, two states define if the token is waiting for authentication with the owner or if the authentication has finished successfully. `Figure 2` shows these states in a flow chart. When a token is created or transferred to a new owner, then the token changes its state to `waitingForOwner`. In this state, the token is waiting for the mutual authentication between the asset and the owner. Once authentication is finished successfully, the token changes its state to `engagedWithOwner`.

![Figure 2 : Flow chart of the token states with `addressAsset` defined (and `addressUser` undefined)](/EIPs/assets/eip-4519/images/Figure2.jpg)
 
Finally, if both the attributes `addressAsset` and `addressUser` are defined, the states of the NFT define if the asset has been engaged or not with the owner or the user (`waitingForOwner`, `engagedWithOwner`, `waitingForUser` and `engagedWithUser`). The flow chart in `Figure 3` shows all the possible state changes. The states related to the owner are the same as in `Figure 2`. The difference is that, at the state `engagedWithOwner`, the token can be assigned to a user. If a user is assigned (the token being at states `engagedWithOwner`, `waitingForUser` or `engagedWithUser`), then the token changes its state to `waitingForUser`. Once the asset and the user authenticate each other, the state of the token is set to `engagedWithUser`, and the user is able to use the asset.

 ![Figure 3 : Flow chart of the token states with `addressUser` and `addressUser` defined](/EIPs/assets/eip-4519/images/Figure3.jpg)
 
In order to complete the ownership transfer of a token, the new owner must carry out a mutual authentication process with the asset, which is off-chain with the asset and on-chain with the token, by using their Ethereum addresses. Similarly, a new user must carry out a mutual authentication process with the asset to complete a use transfer. NFTs define how the authentication processes start and finish. These authentication processes allow deriving fresh session cryptographic keys for secure communication between assets and owners, and between assets and users. Therefore, the trustworthiness of the assets can be traced even if new owners and users manage them.

When the NFT is created or when the ownership is transferred, the token state is `waitingForOwner`. The asset sets its operating mode to `waitingForOwner`. The owner generates a pair of keys using the elliptic curve secp256k1 and the primitive element P used on this curve: a secret key SK&lt;sub&gt;O_A&lt;/sub&gt; and a Public Key PK&lt;sub&gt;O_A&lt;/sub&gt;, so that PK&lt;sub&gt;O_A&lt;/sub&gt; = SK&lt;sub&gt;O_A&lt;/sub&gt; * P. To generate the shared key between the owner and the asset, K&lt;sub&gt;O&lt;/sub&gt;, the public key of the asset, PK&lt;sub&gt;A&lt;/sub&gt;, is employed as follows:

K&lt;sub&gt;O&lt;/sub&gt; = PK&lt;sub&gt;A&lt;/sub&gt; * SK&lt;sub&gt;O_A&lt;/sub&gt;

Using the function `startOwnerEngagement`, PK&lt;sub&gt;O_A&lt;/sub&gt; is saved as the attribute `dataEngagement` and the hash of K&lt;sub&gt;O&lt;/sub&gt; as the attribute `hashK_OA`. The owner sends request engagement to the asset, and the asset calculates:

K&lt;sub&gt;A&lt;/sub&gt; = SK&lt;sub&gt;A&lt;/sub&gt; * PK&lt;sub&gt;O_A&lt;/sub&gt;

If everything is correctly done, K&lt;sub&gt;O&lt;/sub&gt; and K&lt;sub&gt;A&lt;/sub&gt; are the same since:

K&lt;sub&gt;O&lt;/sub&gt; = PK&lt;sub&gt;A&lt;/sub&gt; * SK&lt;sub&gt;O_A&lt;/sub&gt; = (SK&lt;sub&gt;A&lt;/sub&gt; * P) * SK&lt;sub&gt;O_A&lt;/sub&gt; = SK&lt;sub&gt;A&lt;/sub&gt; * (SK&lt;sub&gt;O_A&lt;/sub&gt; * P) = SK&lt;sub&gt;A&lt;/sub&gt; * PK&lt;sub&gt;O_A&lt;/sub&gt;

Using the function `ownerEngagement`, the asset sends the hash of K&lt;sub&gt;A&lt;/sub&gt;, and if it is the same as the data in `hashK_OA`, then the state of the token changes to `engagedWithOwner` and the event `OwnerEngaged` are sent. Once the asset receives the event, it changes its operation mode to `engagedWithOwner`. This process is shown in `Figure 4`. From this moment, the asset can be managed by the owner and they can communicate in a secure way using the shared key. 

 ![Figure 4: Steps in a successful owner and asset mutual authentication process](/EIPs/assets/eip-4519/images/Figure4.jpg)

If the asset consults Ethereum and the state of its NFT is `waitingForUser`, the asset (assuming it is an electronic physical asset) sets its operating mode to `waitingForUser`. Then, a mutual authentication process is carried out with the user, as already done with the owner. The user sends the transaction associated with the function `startUserEngagement`. As in `startOwnerEngagement`, this function saves the public key generated by the user, PK&lt;sub&gt;U_A&lt;/sub&gt;, as the attribute `dataEngagement` and the hash of K&lt;sub&gt;U&lt;/sub&gt; = PK&lt;sub&gt;A&lt;/sub&gt; * SK&lt;sub&gt;U_A&lt;/sub&gt; as the attribute `hashK_UA` in the NFT.

The user sends request engagement and the asset calculates:

K&lt;sub&gt;A&lt;/sub&gt; = SK&lt;sub&gt;A&lt;/sub&gt; * PK&lt;sub&gt;U_A&lt;/sub&gt;

If everything is correctly done, K&lt;sub&gt;U&lt;/sub&gt; and K&lt;sub&gt;A&lt;/sub&gt; are the same since:

K&lt;sub&gt;U&lt;/sub&gt; = PK&lt;sub&gt;A&lt;/sub&gt; * SK&lt;sub&gt;U_A&lt;/sub&gt; = (SK&lt;sub&gt;A&lt;/sub&gt; * P) * SK&lt;sub&gt;U_A&lt;/sub&gt; = SK&lt;sub&gt;A&lt;/sub&gt; * (SK&lt;sub&gt;U_A&lt;/sub&gt; * P) = SK&lt;sub&gt;A&lt;/sub&gt; * PK&lt;sub&gt;U_A&lt;/sub&gt;

Using the function `userEngagement`, the asset sends the hash of K&lt;sub&gt;A&lt;/sub&gt; obtained and if it is the same as the data in `hashK_UA`, then the state of the token changes to `engagedWithUser` and the event `UserEngaged` is sent. Once the asset receives the event, it changes its operation mode to `engagedWithUser`. This process is shown in `Figure 5`. From this moment, the asset can be managed by the user and they can communicate in a secure way using the shared key. 

 ![Figure 5: Steps in a successful user and asset mutual authentication process](/EIPs/assets/eip-4519/images/Figure5.jpg)

Since the establishment of a shared secret key is very important for a secure communication, NFTs include the attributes 
`hashK_OA`, `hashK_UA` and `dataEngagement`. The first two attributes define, respectively, the hash of the secret key shared between the asset and its owner and between the asset and its user. Assets, owners and users should check they are using the correct shared secret keys. The attribute `dataEngagement` defines the public data needed for the agreement. 

```solidity
pragma solidity ^0.8.0;
 /// @title EIP-4519 NFT: Extension of EIP-721 Non-Fungible Token Standard. 
///  Note: the EIP-165 identifier for this interface is 0x8a68abe3
 interface EIP-4519 NFT is EIP721/*,EIP165*/{
    /// @dev This emits when the NFT is assigned as utility of a new user.
    ///  This event emits when the user of the token changes.
    ///  (`_addressUser` == 0) when no user is assigned.
    event UserAssigned(uint256 indexed tokenId, address indexed _addressUser);
    
    /// @dev This emits when user and asset finish mutual authentication process successfully.
    ///  This event emits when both the user and the asset prove they share a secure communication channel.
    event UserEngaged(uint256 indexed tokenId);
    
    /// @dev This emits when owner and asset finish mutual authentication process successfully.
    ///  This event emits when both the owner and the asset prove they share a secure communication channel.
    event OwnerEngaged(uint256 indexed tokenId);
    
    /// @dev This emits when it is checked that the timeout has expired.
    ///  This event emits when the timestamp of the EIP-4519 NFT is not updated in timeout.
    event TimeoutAlarm(uint256 indexed tokenId);
    /// @notice This function defines how the NFT is assigned as utility of a new user (if &quot;addressUser&quot; is defined).
    /// @dev Only the owner of the EIP-4519 NFT can assign a user. If &quot;addressAsset&quot; is defined, then the state of the token must be
    /// &quot;engagedWithOwner&quot;,&quot;waitingForUser&quot; or &quot;engagedWithUser&quot; and this function changes the state of the token defined by &quot;_tokenId&quot; to
    /// &quot;waitingForUser&quot;. If &quot;addressAsset&quot; is not defined, the state is set to &quot;userAssigned&quot;. In both cases, this function sets the parameter 
    /// &quot;addressUser&quot; to &quot;_addressUser&quot;. 
    /// @param _tokenId is the tokenId of the EIP-4519 NFT tied to the asset.
    /// @param _addressUser is the address of the new user.
    function setUser(uint256 _tokenId, address _addressUser) external payable; 
    /// @notice This function defines the initialization of the mutual authentication process between the owner and the asset.
    /// @dev Only the owner of the token can start this authentication process if &quot;addressAsset&quot; is defined and the state of the token is &quot;waitingForOwner&quot;.
    /// The function does not change the state of the token and saves &quot;_dataEngagement&quot; 
    /// and &quot;_hashK_OA&quot; in the parameters of the token.
    /// @param _tokenId is the tokenId of the EIP-4519 NFT tied to the asset.
    /// @param _dataEngagement is the public data proposed by the owner for the agreement of the shared key.
    /// @param _hashK_OA is the hash of the secret proposed by the owner to share with the asset.
    function startOwnerEngagement(uint256 _tokenId, uint256 _dataEngagement, uint256 _hashK_OA) external payable;
 
    /// @notice This function completes the mutual authentication process between the owner and the asset.
    /// @dev Only the asset tied to the token can finish this authentication process provided that the state of the token is
    /// &quot;waitingForOwner&quot; and dataEngagement is different from 0. This function compares hashK_OA saved in
    /// the token with hashK_A. If they are equal then the state of the token changes to &quot;engagedWithOwner&quot;, dataEngagement is set to 0,
    /// and the event &quot;OwnerEngaged&quot; is emitted.
    /// @param _hashK_A is the hash of the secret generated by the asset to share with the owner.
    function ownerEngagement(uint256 _hashK_A) external payable; 
 
    /// @notice This function defines the initialization of the mutual authentication process between the user and the asset.
    /// @dev Only the user of the token can start this authentication process if &quot;addressAsset&quot; and &quot;addressUser&quot; are defined and
    /// the state of the token is &quot;waitingForUser&quot;. The function does not change the state of the token and saves &quot;_dataEngagement&quot; 
    /// and &quot;_hashK_UA&quot; in the parameters of the token.
    /// @param _tokenId is the tokenId of the EIP-4519 NFT tied to the asset.
    /// @param _dataEngagement is the public data proposed by the user for the agreement of the shared key.
    /// @param _hashK_UA is the hash of the secret proposed by the user to share with the asset.
    function startUserEngagement(uint256 _tokenId, uint256 _dataEngagement, uint256 _hashK_UA) external payable;
    
    /// @notice This function completes the mutual authentication process between the user and the asset.
    /// @dev Only the asset tied to the token can finish this authentication process provided that the state of the token is
    /// &quot;waitingForUser&quot; and dataEngagement is different from 0. This function compares hashK_UA saved in
    /// the token with hashK_A. If they are equal then the state of the token changes to &quot;engagedWithUser&quot;, dataEngagement is set to 0,
    /// and the event &quot;UserEngaged&quot; is emitted.
    /// @param _hashK_A is the hash of the secret generated by the asset to share with the user.
    function userEngagement(uint256 _hashK_A) external payable; 
 
    /// @notice This function checks if the timeout has expired.
    /// @dev Everybody can call this function to check if the timeout has expired. The event &quot;TimeoutAlarm&quot; is emitted
    /// if the timeout has expired.
    /// @param _tokenId is the tokenId of the EIP-4519 NFT tied to the asset.
    /// @return true if timeout has expired and false in other case.
    function checkTimeout(uint256 _tokenId) external returns (bool);
    
    /// @notice This function sets the value of timeout.
    /// @dev Only the owner of the token can set this value provided that the state of the token is &quot;engagedWithOwner&quot;,
    /// &quot;waitingForUser&quot; or &quot;engagedWithUser&quot;.
    /// @param _tokenId is the tokenId of the EIP-4519 NFT tied to the asset.
    /// @param _timeout is the value to assign to timeout.
    function setTimeout(uint256 _tokenId, uint256 _timeout) external; 
    
    /// @notice This function updates the timestamp, thus avoiding the timeout alarm.
    /// @dev Only the asset tied to the token can update its own timestamp.
    function updateTimestamp() external; 
    
    /// @notice This function lets obtain the tokenId from an address. 
    /// @dev Everybody can call this function. The code executed only reads from Ethereum.
    /// @param _addressAsset is the address to obtain the tokenId from it.
    /// @return tokenId of the token tied to the asset that generates _addressAsset.
    function tokenFromBCA(address _addressAsset) external view returns (uint256);
    
    /// @notice This function lets know the owner of the token from the address of the asset tied to the token.
    /// @dev Everybody can call this function. The code executed only reads from Ethereum.
    /// @param _addressAsset is the address to obtain the owner from it.
    /// @return owner of the token bound to the asset that generates _addressAsset.
    function ownerOfFromBCA(address _addressAsset) external view returns (address);
    
    /// @notice This function lets know the user of the token from its tokenId.
    /// @dev Everybody can call this function. The code executed only reads from Ethereum.
    /// @param _tokenId is the tokenId of the EIP-4519 NFT tied to the asset.
    /// @return user of the token from its _tokenId.
    function userOf(uint256 _tokenId) external view returns (address);
    
    /// @notice This function lets know the user of the token from the address of the asset tied to the token.
    /// @dev Everybody can call this function. The code executed only reads from Ethereum.
    /// @param _addressAsset is the address to obtain the user from it.
    /// @return user of the token tied to the asset that generates _addressAsset.
    function userOfFromBCA(address _addressAsset) external view returns (address);
    
    /// @notice This function lets know how many tokens are assigned to a user.
    /// @dev Everybody can call this function. The code executed only reads from Ethereum.
    /// @param _addressUser is the address of the user.
    /// @return number of tokens assigned to a user.
    function userBalanceOf(address _addressUser) external view returns (uint256);
    
    /// @notice This function lets know how many tokens of a particular owner are assigned to a user.
    /// @dev Everybody can call this function. The code executed only reads from Ethereum.
    /// @param _addressUser is the address of the user.
    /// @param _addressOwner is the address of the owner.
    /// @return number of tokens assigned to a user from an owner.
    function userBalanceOfAnOwner(address _addressUser, address _addressOwner) external view returns (uint256);
}
```
 
## Rationale

### Authentication

This EIP uses smart contracts to verify the mutual authentication process since smart contracts are trustless.

### Tie Time

This EIP proposes including the attribute timestamp (to register in Ethereum the last time that the physical asset checked the tie with its token) and the attribute timeout (to register the maximum delay time established for the physical asset to prove again the tie). These attributes avoid that a malicious owner or user could use the asset endlessly.

When the asset calls `updateTimestamp`, the smart contract must call `block.timestamp`, which provides current block timestamp as seconds since Unix epoch. For this reason, `timeout`  must be provided in seconds.

### EIP-721-based

[EIP-721](/EIPs/EIPS/eip-721) is the most commonly-used standard for generic NFTs. This EIP extends EIP-721 for backwards compatibility.
  
## Backwards Compatibility

This standard is an extension of EIP-721. It is fully compatible with both of the commonly used optional extensions (`IERC721Metadata` and `IERC721Enumerable`) mentioned in the EIP-721 standard.

## Test Cases

The test cases presented in the paper shown below are available [here](/EIPs/assets/eip-4519/PoC_SmartNFT/).

## Reference Implementation

A first version was presented in a paper of the Special Issue **Security, Trust and Privacy in New Computing Environments** of **Sensors** journal of **MDPI** editorial. The paper, entitled [Secure Combination of IoT and Blockchain by Physically Binding IoT Devices to Smart Non-Fungible Tokens Using PUFs](/EIPs/assets/eip-4519/sensors-21-03119.pdf), was written by the same authors of this EIP.

## Security Considerations

In this EIP, a generic system has been proposed for the creation of non-fungible tokens tied to physical assets. A generic point of view based on the improvements of the current EIP-721 NFT is provided, such as the implementation of the user management mechanism, which does not affect the token&apos;s ownership. The physical asset should have the ability to generate an Ethereum address from itself in a totally random way so that only the asset is able to know the secret from which the Ethereum address is generated. In this way, identity theft is avoided and the asset can be proven to be completely genuine. In order to ensure this, it is recommended that only the manufacturer of the asset has the ability to create its associated token. In the case of an IoT device, the device firmware will be unable to share and modify the secret. Instead of storing the secrets, it is recommended that assets reconstruct their secrets from non-sensitive information such as the helper data associated with Physical Unclonable Functions (PUFs). Although a secure key exchange protocol based on elliptic curves has been proposed, the token is open to coexist with other types of key exchange.  

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 03 Dec 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4519</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4519</guid>
      </item>
    
      <item>
        <title>Multi-byte opcodes prefixed by EB and EC.</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/multi-byte-opcodes/7681</comments>
        
        <description>## Abstract
Reserve `0xEB` and `0xEC` for usage as extended opcode space.

## Motivation
It would be convenient to introduce new opcodes that are likely to be infrequently used, whilst also being able to have greater than 256 opcodes in total. As a single byte opcode is half the size of a double byte opcode, the greatest efficiency in code sizes will be one where frequently used opcodes are single bytes. Two prefix bytes are used to accommodate up to 510 double byte opcodes.

## Specification
For example, a new arithmetic opcode may be allocated to `0xEC 01`(`ADD`), and a novel opcode may be introduced at `0xEB F4`(`DELEGATECALL`). 

Triple byte opcodes may be doubly-prefixed by `0xEB EB`, `0xEC EC`, `0xEB EC` and `0xEC EB`. It is possible to allocate experimental opcodes to this triple-byte space initially, and if they prove safe and useful, they could later be allocated a location in double-byte or single-byte space. 

Only `0xEB EB`, `0xEC EC`, `0xEC EC`, and `0xEB EC` may be interpreted as further extensions of the opcode space. `0xEB` and `0xEC` do not themselves affect the stack or memory, however opcodes specified by further bytes may. If a multi-byte opcode is yet to be defined, it is to be treated as `INVALID` rather than as a `NOP`, as per usual for undefined opcodes.

## Rationale
It was considered that two prefix bytes rather than one would be adequate for reservation as extension addresses. Both `0xEB` and `0xEC` were chosen to be part of the E-series of opcodes. For example, the `0xEF` byte is reserved for contracts conforming to the Ethereum Object Format. By having unassigned opcodes for extending the opcode space, there will be a lower risk of breaking the functionalities of deployed contracts compared to choosing assigned opcodes.  

## Backwards Compatibility
Previous usage of `0xEB` and `0xEC` may result in unexpected behaviour and broken code.

## Security Considerations
There are no known security considerations.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 01 Dec 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4520</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4520</guid>
      </item>
    
      <item>
        <title>721/20-compatible transfer</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4521-721-20-compatible-transfer/7903</comments>
        
        <description>## Abstract
ERC-721, the popular standard for non-fungible tokens (NFTs), includes send functions, such as `transferFrom()` and `safeTransferFrom()`, but does not include a backwards-compatible `transfer()` found in fungible ERC-20 tokens. This standard provides references to add such a `transfer()`.

## Motivation
This standard proposes a simple extension to allow NFTs to work with contracts designed to manage ERC-20s and many consumer wallets which expect to be able to execute a token `transfer()`. For example, if an NFT is inadvertently sent to a contract that typically handles ERC-20, that NFT will be locked. It should also simplify the task for contract programmers if they can rely on `transfer()` to both handle ERC-20 and NFTs.

## Specification
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.

The interface for ERC-4521 `transfer()` MUST conform to ERC-20 and resulting transfers MUST fire the `Transfer` event as described in ERC-721.

```sol
function transfer(address to, uint256 tokenId) external returns (bool success);
```

## Rationale
Replicating ERC-20 `transfer()` with just a minor change to accurately reflect that a unique `tokenId` rather than fungible sum is being sent is desirable for code simplicity and to make integration easier.

## Backwards Compatibility
This EIP does not introduce any known backward compatibility issues.

## Reference Implementation
A reference implementation of an ERC-4521 `transfer()`:

```sol
function transfer(address to, uint256 tokenId) public virtual returns (bool success) {
        require(msg.sender == ownerOf[tokenId], &quot;NOT_OWNER&quot;);

        unchecked {
            balanceOf[msg.sender]--; 
        
            balanceOf[to]++;
        }
        
        delete getApproved[tokenId];
        
        ownerOf[tokenId] = to;
        
        emit Transfer(msg.sender, to, tokenId); 
        
        success = true;
}
```

## Security Considerations
Implementers must be sure to include the relevant return `bool` value for an ERC-4521 in order to conform with existing contracts that use ERC-20 interfaces, otherwise, NFTs may be locked unless a `safeTransfer` is used in such contracts.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 13 Dec 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4521</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4521</guid>
      </item>
    
      <item>
        <title>Safer ERC-20</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/why-isnt-there-an-erc-for-safetransfer-for-erc20/7604</comments>
        
        <description>## Abstract

This standard extends [ERC-20](/EIPs/EIPS/eip-20) tokens with [EIP-165](/EIPs/EIPS/eip-165), and adds familiar functions from [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155) ensuring receiving contracts have implemented proper functionality.

## Motivation

[EIP-165](/EIPs/EIPS/eip-165) adds (among other things) the ability to tell if a target recipient explicitly signals compatibility with an ERC. This is already used in the EIPs for NFTs, [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155). In addition, EIP-165 is a valuable building block for extensions on popular standards to signal implementation, a trend we&apos;ve seen in a number of NFT extensions. This EIP aims to bring these innovations back to ERC-20.

The importance of [EIP-165](/EIPs/EIPS/eip-165) is perhaps felt most for app developers looking to integrate with a generic standard such as ERC-20 or ERC-721, while integrating newer innovations built atop these standards. An easy example would be token permits, which allow for a one-transaction approval and transfer. This has already been implemented in many popular ERC-20 tokens using the [ERC-2612](/EIPs/EIPS/eip-2612) standard or similar. A platform integrating ERC-20 tokens has no easy way of telling if a particular token has implemented token permits or not. (As of this writing, ERC-2612 does not require EIP-165.) With EIP-165, the app (or contracts) could query `supportsInterface` to see if the `interfaceId` of a particular EIP is registered (in this case, EIP-2612), allowing for easier and more modular functions interacting with ERC-20 contracts. It is already common in NFT extensions to include an EIP-165 interface with a standard, we would argue this is at least in part due to the underlying [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155) standards integrating EIP-165. Our hope is that this extension to ERC-20 would also help future extensions by making them easier to integrate.

## Specification
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.

In order to be compliant with this EIP, and ERC-20-compliant contract MUST also implement the following functions:
```solidity
pragma solidity 0.8.10;

import &apos;./IERC20.sol&apos;;
import &apos;./IERC165.sol&apos;;

// the EIP-165 interfaceId for this interface is 0x534f5876

interface SaferERC-20 is IERC20, IERC165 {
  function safeTransfer(address to, uint256 amount) external returns(bool);
  function safeTransfer(address to, uint256 amount, bytes memory data) external returns(bool);
  function safeTransferFrom(address from, address to, uint256 amount) external returns(bool);
  function safeTransferFrom(address from, address to, uint256 amount, bytes memory data) external returns(bool);
}
```
`safeTransfer` and `safeTransferFrom` MUST transfer as expected to EOA addresses, and to contracts implementing `ERC20Receiver` and returning the function selector (`0x4fc35859`) when called, and MUST revert when transferring to a contract which either does not have `ERC20Receiver` implemented, or does not return the function selector when called.

In addition, a contract accepting safe transfers MUST implement the following if it wishes to accept safe transfers, and MUST return the function selector (`0x4fc35859`):
```solidity
pragma solidity 0.8.10;

import &apos;./IERC165.sol&apos;;

interface ERC20Receiver is IERC165 {
  function onERC20Received(
    address _operator,
    address _from,
    uint256 _amount,
    bytes _data
  ) external returns(bytes4);
}
```

## Rationale

This EIP is meant to be minimal and straightforward. Adding EIP-165 to ERC-20 is useful for a number of applications, and outside of a minimal amount of code increasing contract size, carries no downside. The `safeTransfer` and `safeTransferFrom` functions are well recognized from ERC-721 and ERC-1155, and therefore keeping identical naming conventions is reasonable, and the benefits of being able to check for implementation before transferring are as useful for ERC-20 tokens as they are for ERC-721 and ERC-1155.

Another easy backport from EIP721 and EIP1155 might be the inclusion of a metadata URI for tokens, allowing them to easily reference logo and other details. This has not been included, both in order to keep this EIP as minimal as possible, and because it is already sufficiently covered by [EIP-1046](/EIPs/EIPS/eip-1046).

## Backwards Compatibility

There are no issues with backwards compatibility in this EIP, as the full suite of ERC-20 functions is unchanged.

## Test Cases
Test cases have been provided in the implementation repo [here](https://github.com/wschwab/SaferERC-20/blob/main/src/SaferERC-20.t.sol).

## Reference Implementation
A sample repo demonstrating an implementation of this EIP has been created [here](https://github.com/wschwab/SaferERC-20). It is (as of this writing) in a Dapptools environment, for details on installing and running Dapptools see the Dapptools repo.

## Security Considerations

`onERC20Received`  is a callback function. Callback functions have been exploited in the past as a reentrancy vector, and care should be taken to make sure implementations are not vulnerable.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 05 Dec 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4524</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4524</guid>
      </item>
    
      <item>
        <title>QR Code transmission protocol for wallets</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/add-qr-code-scanning-between-software-wallet-cold-signer-hardware-wallet/6568</comments>
        
        <description>## Abstract

The purpose of this EIP is to provide a process and data transmission protocol via QR Code between offline signers and watch-only wallets.

## Motivation

There is an increasing number of users whom like to use complete offline signers to manage their private keys, signers like hardware wallets and mobile phones in offline mode. In order to sign transactions or data, these offline signers have to rely on a watch-only wallet since it would prepare the data to be signed. Currently, there are 4 possible data transmission methods between offline signers and watch-only wallets: QR Code, USB, Bluetooth, and file transfer. The QR Code data transmission method have the following advantages when compared to the other three methods mentioned above:

- Transparency and Security: Compared to USB or Bluetooth, users can easily decode the data via QR Code (with the help of some tools). It can also help users clearly identify what they are going to sign, which improves transparency and thus better security.
- Improved Compatibility: Compared to USB and Bluetooth, QR Code data transmissions has a wider range of compatibility. Normally, it wouldn’t be broken by software changes like browser upgrades, system upgrade, and etc.
- Improved User experience: QR Code data transmissions can provide a better user experience compared to USB, Bluetooth, and file transfer especially when the user is using a mobile device.
- A smaller attack surface: USB and Bluetooth have a bigger attack surface than QR-Codes.

Due to these advantages, QR Code data transmissions is a better choice. Unfortunately, there is no modern standard for how offline signers should work with watch-only wallets nor how data should be encoded.
This EIP presents a standard process and data transmission protocol for offline signers to work with watch-only wallets.

## Specification

**Offline signer**: An offline signer is a device or application which holds the user’s private keys and does not have network access.

**Watch-only wallet**: A watch-only wallet is a wallet that has network access and can interact with the Ethereum blockchain.

### Process

In order to work with offline signers, the watch-only wallet should follow the following process.

1. The offline signer provides the public key information to the watch-only wallet to generate addresses, sync balances and etc via QR Codes.
2. The watch-only wallet generates the unsigned data and sends it to an offline signer for signing via QR Code, data that can include transactions, typed data, and etc.
3. The offline signer signs the data and provides a signature back to the watch-only wallet via QR Code.
4. The watch-only wallet receives the signature, constructs the signed data (transaction) and performs the following activities like broadcasting the transaction etc.

### Data Transmission Protocol

Since a single QR Code can only contain a limited amount of data, animated QR Codes should be utilized for data transmission. The `BlockchainCommons` have published a series of data transmission protocol called Uniform Resources (UR). It provides a basic method to encode data into animated QR Codes. This EIP will use UR and extend its current definition. 

`Concise Binary Object Representation(CBOR)` will be used for binary data encoding. `Concise Data Definition Language(CDDL)` will be used for expressing the CBOR.

### Setting up the watch-only wallet with the offline signer

In order to allow a watch-only wallet to collect information from the Ethereum blockchain, the offline signer would need to provide the public keys to the watch-only wallet in which the wallet will use them to query the necessary information from the Ethereum blockchain.

In such a case, offline signers should provide the extended public keys and derivation path. The UR Type called `crypto-hdkey` will be used to encode this data and the derivation path will be encoded as `crypto-keypath`.

 
#### CDDL for Key Path

The `crypto-keypath` will be used to specify the key path.The following specification is written in Concise Data Definition Language(CDDL) for `crypto-key-path`

``` 
; Metadata for the derivation path of a key.
;
; `source-fingerprint`, if present, is the fingerprint of the
; ancestor key from which the associated key was derived.
;
; If `components` is empty, then `source-fingerprint` MUST be a fingerprint of
; a master key.
;
; `depth`, if present, represents the number of derivation steps in
; the path of the associated key, even if not present in the `components` element
; of this structure.
    crypto-keypath = {
        components: [path-component], ; If empty, source-fingerprint MUST be present
        ? source-fingerprint: uint32 .ne 0 ; fingerprint of ancestor key, or master key if components is empty
        ? depth: uint8 ; 0 if this is a public key derived directly from a master key
    }
    path-component = (
        child-index / child-index-range / child-index-wildcard-range,
        is-hardened
    )
    uint32 = uint .size 4
    uint31 = uint32 .lt 2147483648 ;0x80000000
    child-index = uint31
    child-index-range = [child-index, child-index] ; [low, high] where low &lt; high
    child-index-wildcard = []
    is-hardened = bool
    components = 1
    source-fingerprint = 2
    depth = 3
```

#### CDDL for Extended Public Keys

Since the purpose is to transfer public key data, the definition of `crypto-hdkey` will be kept only for public key usage purposes.

The following specification is written in Concise Data Definition Language `CDDL` and includes the crypto-keypath spec above.

```
; An hd-key must be a derived key.
hd-key = {
    derived-key
}
; A derived key must be public, has an optional chain code, and
; may carry additional metadata about its use and derivation.
; To maintain isomorphism with [BIP32] and allow keys to be derived from
; this key `chain-code`, `origin`, and `parent-fingerprint` must be present.
; If `origin` contains only a single derivation step and also contains `source-fingerprint`,
; then `parent-fingerprint` MUST be identical to `source-fingerprint` or may be omitted.
derived-key = (
    key-data: key-data-bytes,
    ? chain-code: chain-code-bytes       ; omit if no further keys may be derived from this key
    ? origin: #6.304(crypto-keypath),    ; How the key was derived
    ? name: text,                        ; A short name for this key.
    ? source: text,                      ; The device info or any other description for this key
)
key-data = 3
chain-code = 4
origin = 6
name = 9
source = 10

uint8 = uint .size 1
key-data-bytes = bytes .size 33
chain-code-bytes = bytes .size 32
```

If the chain-code is provided, then it can be used to derive child keys but if it isn’t provided, it is simply a solo key and the origin can be provided to indicate the derivation key path.

If the signer would like to provide multiple public keys instead of the extended public key for any reason, the signer can use `crypto-account` for that.

### Sending the unsigned data from the watch-only wallet to the offline signer

To send the unsigned data from a watch-only wallet to an offline signer, the new UR type `eth-sign-request` will be introduced to encode the signing request.

#### CDDL for Eth Sign Request.

The following specification is written in Concise Data Definition Language `CDDL`.
UUIDs in this specification notated UUID are CBOR binary strings tagged with #6.37, per the IANA `CBOR Tags Registry`.

```
; Metadata for the signing request for Ethereum.
; 
sign-data-type = {
    type: int .default 1 transaction data; the unsigned data type
}

eth-transaction-data = 1; legacy transaction rlp encoding of unsigned transaction data
eth-typed-data = 2; EIP-712 typed signing data
eth-raw-bytes=3;   for signing message usage, like EIP-191 personal_sign data
eth-typed-transaction=4; EIP-2718 typed transaction of unsigned transaction data

; Metadata for the signing request for Ethereum.
; request-id: the identifier for this signing request.
; sign-data: the unsigned data
; data-type: see sign-data-type definition
; chain-id: chain id definition see https://github.com/ethereum-lists/chains for detail
; derivation-path: the key path of the private key to sign the data
; address: Ethereum address of the signing type for verification purposes which is optional

eth-sign-request = (
    sign-data: sign-data-bytes, ; sign-data is the data to be signed by offline signer, currently it can be unsigned transaction or typed data
    data-type: #3.401(sign-data-type),
    chain-id: int .default 1,
    derivation-path: #5.304(crypto-keypath), ;the key path for signing this request
    ?request-id: uuid, ; the uuid for this signing request
    ?address: eth-address-bytes,            ;verification purpose for the address of the signing key
    ?origin: text  ;the origin of this sign request, like wallet name
)
request-id = 1
sign-data = 2
data-type = 3
chain-id = 4 ;it will be the chain id of ethereum related blockchain
derivation-path = 5
address = 6
origin = 7
eth-address-bytes = bytes .size 20
sign-data-bytes = bytes ; for unsigned transactions it will be the rlp encoding for unsigned transaction data and ERC 712 typed data it will be the bytes of json string.
```

### The signature provided by offline signers to watch-only wallets

After the data is signed, the offline signer should send the signature back to the watch-only wallet. The new UR type called `eth-signature` is introduced here to encode this data.

#### CDDL for Eth Signature.

The following specification is written in Concise Data Definition Language `CDDL`.

```
eth-signature  = (
    request-id: uuid,
    signature: eth-signature-bytes,
    ? origin: text, ; The device info for providing this signature
)

request-id = 1
signature = 2
origin = 3

eth-signature-bytes = bytes .size 65; the signature of the signing request (r,s,v)
```

## Rationale

This EIP uses some existing UR types like `crypto-keypath` and `crypto-hdkey` and also introduces some new UR types like `eth-sign-request` and `eth-signature`. Here are the reasons we choose UR for the QR Code data transmission protocol:

### UR provides a solid foundation for QR Code data transmission

- Uses the alphanumeric QR code mode for efficiency.
- Includes a CRC32 checksum of the entire message in each part to tie the different parts of the QR code together and ensure the transmitted message has been reconstructed.
- uses `Fountain Code` for the arbitrary amount of data which can be both a minimal, finite sequence of parts and an indefinite sequence of parts. The Fountain Code can ultimately help the receiver to make the data extraction easier.

### UR provides existing helpful types and scalability for new usages

Currently, UR has provided some existing types like `crypto-keypath` and `crypto-hdkey` so it is quite easy to add a new type and definitions for new usages.

### UR has an active air-gapped wallet community.

Currently, the UR has an active `airgapped wallet community` which continues to improve the UR forward.

## Backwards Compatibility

Currently, there is no existing protocol to define data transmissions via QR Codes so there are no backward compatibility issues that needs to be addressed now.

## Test Cases

The test cases can be found on the `ur-registry-eth` package released by the Keystone team.

## Reference Implementation

The reference implementation can be found on the `ur-registry-eth` package released by the Keystone team.

## Security Considerations

The offline signer should decode all the data from `eth-sign-request` and show them to the user for confirmation prior to signing. It is recommended to provide an address field in the `eth-sign-request`. If provided, the offline signer should verify the address being the same one as the address associated with the signing key.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 07 Dec 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4527</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4527</guid>
      </item>
    
      <item>
        <title>Wrapped Deposits</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/wrapped-deposit-contract-eip/7740</comments>
        
        <description>## Abstract
The wrapped deposit contract handles deposits of assets (Ether, [ERC-20](/EIPs/EIPS/eip-20), [ERC-721](/EIPs/EIPS/eip-721)) on behalf of a user. A user must only approve a spend limit once and then an asset may be deposited to any number of different applications that support deposits from the contract.

## Motivation
The current user flow for depositing assets in dapps is unnecessarily expensive and insecure. To deposit an ERC-20 asset a user must either:

  - send an approve transaction for the exact amount being sent, before making a deposit, and then repeat this process for every subsequent deposit.
  - send an approve transaction for an infinite spend amount before making deposits.

The first option is inconvenient, and expensive. The second option is insecure. Further, explaining approvals to new or non-technical users is confusing. This has to be done in _every_ dapp that supports ERC20 deposits.

## Specification
The wrapped deposit contract SHOULD be deployed at an identifiable address (e.g. `0x1111119a9e30bceadf9f939390293ffacef93fe9`). The contract MUST be non-upgradable with no ability for state variables to be changed.

The wrapped deposit contract MUST have the following public functions:

```js
depositERC20(address to, address token, uint amount) external;
depositERC721(address to, address token, uint tokenId) external;
safeDepositERC721(address to, address token, uint tokenId, bytes memory data) external;
safeDepositERC1155(address to, address token, uint tokenId, uint value, bytes calldata data) external;
batchDepositERC1155(address to, address token, uint[] calldata tokenIds, uint[] calldata values, bytes calldata data) external;
depositEther(address to) external payable;
```

Each of these functions MUST revert if `to` is an address with a zero code size. Each function MUST attempt to call a method on the `to` address confirming that it is willing and able to accept the deposit. If this function call does not return a true value execution MUST revert. If the asset transfer is not successful execution MUST revert.

The following interfaces SHOULD exist for contracts wishing to accept deposits:

```ts
interface ERC20Receiver {
  function acceptERC20Deposit(address depositor, address token, uint amount) external returns (bool);
}

interface ERC721Receiver {
  function acceptERC721Deposit(address depositor, address token, uint tokenId) external returns (bool);
}

interface ERC1155Receiver {
  function acceptERC1155Deposit(address depositor, address token, uint tokenId, uint value, bytes calldata data) external returns (bool);
  function acceptERC1155BatchDeposit(address depositor, address token, uint[] calldata tokenIds, uint[] calldata values, bytes calldata data) external returns (bool);
}

interface EtherReceiver {
  function acceptEtherDeposit(address depositor, uint amount) external returns (bool);
}
```

A receiving contract MAY implement any of these functions as desired. If a given function is not implemented deposits MUST not be sent for that asset type.

## Rationale
Having a single contract that processes all token transfers allows users to submit a single approval per token to deposit to any number of contracts. The user does not have to trust receiving contracts with token spend approvals and receiving contracts have their complexity reduced by not having to implement token transfers themselves.

User experience is improved because a simple global dapp can be implemented with the messaging: &quot;enable token for use in other apps&quot;.

## Backwards Compatibility

This EIP is not backward compatible. Any contract planning to use this deposit system must implement specific functions to accept deposits. Existing contracts that are upgradeable can add support for this EIP retroactively by implementing one or more accept deposit functions.

Upgraded contracts can allow deposits using both the old system (approving the contract itself) and the proposed deposit system to preserve existing approvals. New users should be prompted to use the proposed deposit system.

## Reference Implementation
```ts
pragma solidity ^0.7.0;

interface ERC20Receiver {
  function acceptERC20Deposit(address depositor, address token, uint amount) external returns (bool);
}

interface ERC721Receiver {
  function acceptERC721Deposit(address depositor, address token, uint tokenId) external returns (bool);
}

interface ERC1155Receiver {
  function acceptERC1155Deposit(address depositor, address token, uint tokenId, uint value, bytes calldata data) external returns (bool);
  function acceptERC1155BatchDeposit(address depositor, address token, uint[] calldata tokenIds, uint[] calldata values, bytes calldata data) external returns (bool);
}

interface EtherReceiver {
  function acceptEtherDeposit(address depositor, uint amount) external returns (bool);
}

interface IERC20 {
  function transferFrom(address sender, address recipient, uint amount) external returns (bool);
}

interface IERC721 {
  function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
  function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes memory data) external payable;
}

interface IERC1155 {
  function safeTransferFrom(address _from, address _to, uint _id, uint _value, bytes calldata _data) external;
  function safeBatchTransferFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external;
}

contract WrappedDeposit {
  function depositERC20(address to, address token, uint amount) public {
    _assertContract(to);
    require(ERC20Receiver(to).acceptERC20Deposit(msg.sender, token, amount));
    bytes memory data = abi.encodeWithSelector(
      IERC20(token).transferFrom.selector,
      msg.sender,
      to,
      amount
    );
    (bool success, bytes memory returndata) = token.call(data);
    require(success);
    // backward compat for tokens incorrectly implementing the transfer function
    if (returndata.length &gt; 0) {
      require(abi.decode(returndata, (bool)), &quot;ERC20 operation did not succeed&quot;);
    }
  }

  function depositERC721(address to, address token, uint tokenId) public {
    _assertContract(to);
    require(ERC721Receiver(to).acceptERC721Deposit(msg.sender, token, tokenId));
    IERC721(token).transferFrom(msg.sender, to, tokenId);
  }

  function safeDepositERC721(address to, address token, uint tokenId, bytes memory data) public {
    _assertContract(to);
    require(ERC721Receiver(to).acceptERC721Deposit(msg.sender, token, tokenId));
    IERC721(token).safeTransferFrom(msg.sender, to, tokenId, data);
  }

  function safeDepositERC1155(address to, address token, uint tokenId, uint value, bytes calldata data) public {
    _assertContract(to);
    require(ERC1155Receiver(to).acceptERC1155Deposit(msg.sender, to, tokenId, value, data));
    IERC1155(token).safeTransferFrom(msg.sender, to, tokenId, value, data);
  }

  function batchDepositERC1155(address to, address token, uint[] calldata tokenIds, uint[] calldata values, bytes calldata data) public {
    _assertContract(to);
    require(ERC1155Receiver(to).acceptERC1155BatchDeposit(msg.sender, to, tokenIds, values, data));
    IERC1155(token).safeBatchTransferFrom(msg.sender, to, tokenIds, values, data);
  }

  function depositEther(address to) public payable {
    _assertContract(to);
    require(EtherReceiver(to).acceptEtherDeposit(msg.sender, msg.value));
    (bool success, ) = to.call{value: msg.value}(&apos;&apos;);
    require(success, &quot;nonpayable&quot;);
  }

  function _assertContract(address c) private view {
    uint size;
    assembly {
      size := extcodesize(c)
    }
    require(size &gt; 0, &quot;noncontract&quot;);
  }
}
```
## Security Considerations
The wrapped deposit implementation should be as small as possible to reduce the risk of bugs. The contract should be small enough that an engineer can read and understand it in a few minutes.

Receiving contracts MUST verify that `msg.sender` is equal to the wrapped deposit contract. Failing to do so allows anyone to simulate deposits.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 11 Dec 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4546</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4546</guid>
      </item>
    
      <item>
        <title>Procedures for the EVM</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4573-named-procedures-for-evm-code-sections/7776</comments>
        
        <description>## Abstract

Five EVM instructions are introduced to define, call, and return from named EVM _procedures_ and access their _call frames_ in memory - `ENTERPROC`, `LEAVEPROC`, `CALLPROC`, `RETURNPROC`, and `FRAMEADDRESS`.

## Motivation

Currently, Ethereum bytecode has no syntactic structure, and _subroutines_ have no defined interfaces.

We propose to add _procedures_ -- delimited blocks of code that can be entered only by calling into them via defined interfaces.

Also, the EVM currently has no automatic management of memory for _procedures_.  So we also propose to automatically reserve call frames on an in-memory stack.

Constraints on the use of _procedures_ must be validated at contract initialization time to maintain the safety properties of [EIP-3779](/EIPs/EIPS/eip-3779): Valid programs will not halt with an exception unless they run out of gas or recursively overflow stack.

### Prior Art

The terminology is not well-defined, but we will follow Intel in calling the low-level concept _subroutines_ and the higher level concept _procedures_.  The distinction is that _subroutines_ are little more than a jump that knows where it came from, whereas procedures have a defined interface and manage memory as a stack. [EIP-2315](/EIPs/EIPS/eip-2315) introduces _subroutines_, and this EIP introduces _procedures_.

## Specification

### Instructions

#### ENTERPROC (0x??) dest_section: uint8, dest_offset: uint8, n_inputs: uint16, n_outputs: uint16, n_locals: uint16
```
frame_stack.push(FP)
FP -= n_locals * 32
PC +- &lt;length of immediates&gt;
```
Marks the entry point to a procedure
* at offset `dest_offset` from the beginning of the `dest_section`.
* taking `n_inputs` arguments from the data stack, 
* returning `n_outputs` values on the `data stack`, and
* reserving `n_locals` words of data in memory on the `frame stack`.
 
Procedures can only be entered via a `CALLPROC` to their entry point.

#### LEAVEPROC (0x??)

```
   FP = frame_stack.pop()
   asm RETURNSUB
```
&gt; Pop the `frame stack` and return to the calling procedure using `RETURNSUB`.

Marks the end of a procedure.  Each `ENTERPROC` requires a closing `LEAVEPROC`.

*Note: Attempts to jump into a procedure (including its  `LEAVEPROC`) from outside of the procedure or to jump or step to `ENTERPROC` at all must be prevented at validation time.  `CALLPROC` is the only valid way to enter a procedure.*

#### CALLPROC (0x??) dest_section: uint16, dest_proc: uint16
 ```
   FP -= n_locals
   asm JUMPSUB &lt;offset of section&gt; + &lt;offset of procedure&gt;
```
&gt; Allocate a *stack frame* and transfer control and `JUMPSUB` to the Nth (N=*dest_proc*) _procedure_ in the Mth(M=*dest_section*) _section_ of the code.  _Section 0_ is the current code section, any other code sections are indexed starting at _1_. 

*Note: That the procedure is defined and the required `n_inputs` words are available on the `data stack` must be shown at validation time.* 

#### RETURNPROC (0x??)
```
   FP += n_locals
   asm RETURNSUB
```
&gt; Pop the `frame stack` and return control to the calling procedure using `RETURNSUB`.

*Note: That the promised `n_outputs` words are available on the `data stack` must be shown at validation time.*

#### FRAMEADDRESS (0x??) offset: int16
```
asm PUSH2 FP + offset
```
&gt; Push the address `FP + offset` onto the data stack.

Call frame data is addressed at an immediate `offset` relative to `FP`.

Typical usage includes storing data on a call frame
```
PUSH 0xdada
FRAMEADDRESS 32
MSTORE
```
and loading data from a call frame
```
FRAMEADDRESS 32
MLOAD
```

### Memory Costs

Presently,`MSTORE` is defined as
```
   memory[stack[0]...stack[0]+31] = stack[1]
   memory_size = max(memory_size,floor((stack[0]+32)÷32)
```
* where `memory_size` is the number of active words of memory above _0_.

We propose to treat memory addresses as signed, so the formula needs to be
```
   memory[stack[0]...stack[0]+31] = stack[1]
   if (stack[0])+32)÷32) &lt; 0
      negative_memory_size = max(negative_memory_size,floor((stack[0]+32)÷32))
   else
      positive_memory_size = max(positive_memory_size,floor((stack[0]+32)÷32))
   memory_size = positive_memory_size + negative_memory_size
```
* where `negative_memory_size` is the number of active words of memory below _0_ and
* where `positive_memory_size` is the number of active words of memory at or above _0_.

### Call Frame Stack

These instructions make use of a `frame stack` to allocate and free frames of local data for _procedures_ in memory.  Frame memory begins at address 0 in memory and grows downwards, towards more negative addresses.  A frame is allocated for each procedure when it is called, and freed when it returns.

Memory can be addressed relative to the frame pointer `FP` or by absolute address.  `FP` starts at 0, and moves downward towards more negative addresses to point to the frame for each `CALLPROC` and moving upward towards less negative addresses to point to the previous frame for the corresponding `RETURNPROC`.

Equivalently, in the EVM&apos;s twos-complement arithmetic, `FP` moves from the highest address down, as is common in many calling conventions.

For example, after an initial `CALLPROC` to a procedure needing two words of data the `frame stack` might look like this

```
     0-&gt; ........
         ........
    FP-&gt;
```
Then, after a further `CALLPROC` to a procedure needing three words of data the `frame stack` would like this

```
     0-&gt; ........
         ........
   -64-&gt; ........
         ........
         ........
    FP-&gt;
```
After a `RETURNPROC` from that procedure the `frame stack` would look like this
```
     0-&gt; ........
         ........
    FP-&gt; ........
         ........
         ........
```
and after a final `RETURNPROC`, like this
```
    FP-&gt; ........
         ........
         ........
         ........
         ........
```

## Rationale

There is actually not much new here.  It amounts to [EIP-615](/EIPs/EIPS/eip-615), refined and refactored into bite-sized pieces, along lines common to other machines.

This proposal uses the [EIP-2315](/EIPs/EIPS/eip-2315) return stack to manage calls and returns, and steals ideas from [EIP-615](/EIPs/EIPS/eip-615), [EIP-3336](/EIPs/EIPS/eip-3336), and  [EIP-4200](/EIPs/EIPS/eip-4200). `ENTERPROC` corresponds to `BEGINSUB` from EIP-615.  Like EIP-615 it uses a frame stack to track call-frame addresses with `FP` as _procedures_ are entered and left, but like EIP-3336 and EIP-3337 it moves call frames from the data stack to memory. 

Aliasing call frames with ordinary memory supports  addressing call-frame data with ordinary stores and loads.  This is generally useful, especially for languages like C that provide pointers to variables on the stack.

The design model here is the _subroutines_ and _procedures_ of the Intel x86 architecture.
* `JUMPSUB` and `RETURNSUB` (from [EIP-2315](/EIPs/EIPS/eip-2315) -- like `CALL` and `RET` -- jump to and return from _subroutines_.
* `ENTERPROC`  -- like `ENTER` -- sets up the stack frame for a _procedure_.
* `CALLPROC` amounts to a `JUMPSUB` to an `ENTERPROC`.
* `RETURNPROC` amounts to an early `LEAVEPROC`.
* `LEAVEPROC` -- like `LEAVE` -- takes down the stack frame for a _procedure_.  It then executes a `RETURNSUB`.

## Backwards Compatibility

This proposal adds new EVM opcodes.  It doesn&apos;t remove or change the semantics of any existing opcodes, so there should be no backwards compatibility issues.

## Security

Safe use of these constructs must be checked completely at validation time -- per EIP-3779 -- so there should be no security issues at runtime.

`ENTERPROC` and `LEAVEPROC` must follow the same safety rules as for `JUMPSUB` and `RETURNSUB` in EIP-2315. In addition, the following constraints must be validated:

* Every`ENTERPROC` must be followed by a `LEAVEPROC` to delimit the bodies of _procedures_.
* There can be no nested _procedures_.
* There can be no jump into the body of a procedure (including its `LEAVEPROC`) from outside of that body.
* There can be no jump or step to `BEGINPROC` at all -- only `CALLPROC`.
* The specified `n_inputs` and `n_outputs` must be on the stack.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 16 Dec 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4573</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4573</guid>
      </item>
    
      <item>
        <title>Tokenized Vaults</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4626-yield-bearing-vault-standard/7900</comments>
        
        <description>## Abstract

The following standard allows for the implementation of a standard API for tokenized Vaults
representing shares of a single underlying [EIP-20](/EIPs/EIPS/eip-20) token.
This standard is an extension on the EIP-20 token that provides basic functionality for depositing
and withdrawing tokens and reading balances.

## Motivation

Tokenized Vaults have a lack of standardization leading to diverse implementation details.
Some various examples include lending markets, aggregators, and intrinsically interest bearing tokens.
This makes integration difficult at the aggregator or plugin layer for protocols which need to conform to many standards, and forces each protocol to implement their own adapters which are error prone and waste development resources.

A standard for tokenized Vaults will lower the integration effort for yield-bearing vaults, while creating more consistent and robust implementation patterns.

## Specification

All [EIP-4626](/EIPs/EIPS/eip-4626) tokenized Vaults MUST implement EIP-20 to represent shares.
If a Vault is to be non-transferrable, it MAY revert on calls to `transfer` or `transferFrom`.
The EIP-20 operations `balanceOf`, `transfer`, `totalSupply`, etc. operate on the Vault &quot;shares&quot;
which represent a claim to ownership on a fraction of the Vault&apos;s underlying holdings.

All EIP-4626 tokenized Vaults MUST implement EIP-20&apos;s optional metadata extensions.
The `name` and `symbol` functions SHOULD reflect the underlying token&apos;s `name` and `symbol` in some way.

EIP-4626 tokenized Vaults MAY implement [EIP-2612](/EIPs/EIPS/eip-2612) to improve the UX of approving shares on various integrations.

### Definitions:

- asset: The underlying token managed by the Vault.
  Has units defined by the corresponding EIP-20 contract.
- share: The token of the Vault. Has a ratio of underlying assets
  exchanged on mint/deposit/withdraw/redeem (as defined by the Vault).
- fee: An amount of assets or shares charged to the user by the Vault. Fees can exists for
  deposits, yield, AUM, withdrawals, or anything else prescribed by the Vault.
- slippage: Any difference between advertised share price and economic realities of
  deposit to or withdrawal from the Vault, which is not accounted by fees.

### Methods

#### asset

The address of the underlying token used for the Vault for accounting, depositing, and withdrawing.

MUST be an EIP-20 token contract.

MUST _NOT_ revert.

```yaml
- name: asset
  type: function
  stateMutability: view

  inputs: []

  outputs:
    - name: assetTokenAddress
      type: address
```

#### totalAssets

Total amount of the underlying asset that is &quot;managed&quot; by Vault.

SHOULD include any compounding that occurs from yield.

MUST be inclusive of any fees that are charged against assets in the Vault.

MUST _NOT_ revert.

```yaml
- name: totalAssets
  type: function
  stateMutability: view

  inputs: []

  outputs:
    - name: totalManagedAssets
      type: uint256
```

#### convertToShares

The amount of shares that the Vault would exchange for the amount of assets provided, in an ideal scenario where all the conditions are met.

MUST NOT be inclusive of any fees that are charged against assets in the Vault.

MUST NOT show any variations depending on the caller.

MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.

MUST NOT revert unless due to integer overflow caused by an unreasonably large input.

MUST round down towards 0.

This calculation MAY NOT reflect the &quot;per-user&quot; price-per-share, and instead should reflect the &quot;average-user&apos;s&quot; price-per-share, meaning what the average user should expect to see when exchanging to and from.

```yaml
- name: convertToShares
  type: function
  stateMutability: view

  inputs:
    - name: assets
      type: uint256

  outputs:
    - name: shares
      type: uint256
```

#### convertToAssets

The amount of assets that the Vault would exchange for the amount of shares provided, in an ideal scenario where all the conditions are met.

MUST NOT be inclusive of any fees that are charged against assets in the Vault.

MUST NOT show any variations depending on the caller.

MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.

MUST NOT revert unless due to integer overflow caused by an unreasonably large input.

MUST round down towards 0.

This calculation MAY NOT reflect the &quot;per-user&quot; price-per-share, and instead should reflect the &quot;average-user&apos;s&quot; price-per-share, meaning what the average user should expect to see when exchanging to and from.

```yaml
- name: convertToAssets
  type: function
  stateMutability: view

  inputs:
    - name: shares
      type: uint256

  outputs:
    - name: assets
      type: uint256
```

#### maxDeposit

Maximum amount of the underlying asset that can be deposited into the Vault for the `receiver`, through a `deposit` call.

MUST return the maximum amount of assets `deposit` would allow to be deposited for `receiver` and not cause a revert, which MUST NOT be higher than the actual maximum that would be accepted (it should underestimate if necessary). This assumes that the user has infinite assets, i.e. MUST NOT rely on `balanceOf` of `asset`.

MUST factor in both global and user-specific limits, like if deposits are entirely disabled (even temporarily) it MUST return 0.

MUST return `2 ** 256 - 1` if there is no limit on the maximum amount of assets that may be deposited.

MUST NOT revert.

```yaml
- name: maxDeposit
  type: function
  stateMutability: view

  inputs:
    - name: receiver
      type: address

  outputs:
    - name: maxAssets
      type: uint256
```

#### previewDeposit

Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given current on-chain conditions.

MUST return as close to and no more than the exact amount of Vault shares that would be minted in a `deposit` call in the same transaction. I.e. `deposit` should return the same or more `shares` as `previewDeposit` if called in the same transaction.

MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the deposit would be accepted, regardless if the user has enough tokens approved, etc.

MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.

MUST NOT revert due to vault specific user/global limits. MAY revert due to other conditions that would also cause `deposit` to revert.

Note that any unfavorable discrepancy between `convertToShares` and `previewDeposit` SHOULD be considered slippage in share price or some other type of condition, meaning the depositor will lose assets by depositing.

```yaml
- name: previewDeposit
  type: function
  stateMutability: view

  inputs:
    - name: assets
      type: uint256

  outputs:
    - name: shares
      type: uint256
```

#### deposit

Mints `shares` Vault shares to `receiver` by depositing exactly `assets` of underlying tokens.

MUST emit the `Deposit` event.

MUST support EIP-20 `approve` / `transferFrom` on `asset` as a deposit flow.
MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the `deposit` execution, and are accounted for during `deposit`.

MUST revert if all of `assets` cannot be deposited (due to deposit limit being reached, slippage, the user not approving enough underlying tokens to the Vault contract, etc).

Note that most implementations will require pre-approval of the Vault with the Vault&apos;s underlying `asset` token.

```yaml
- name: deposit
  type: function
  stateMutability: nonpayable

  inputs:
    - name: assets
      type: uint256
    - name: receiver
      type: address

  outputs:
    - name: shares
      type: uint256
```

#### maxMint

Maximum amount of shares that can be minted from the Vault for the `receiver`, through a `mint` call.

MUST return the maximum amount of shares `mint` would allow to be deposited to `receiver` and not cause a revert, which MUST NOT be higher than the actual maximum that would be accepted (it should underestimate if necessary). This assumes that the user has infinite assets, i.e. MUST NOT rely on `balanceOf` of `asset`.

MUST factor in both global and user-specific limits, like if mints are entirely disabled (even temporarily) it MUST return 0.

MUST return `2 ** 256 - 1` if there is no limit on the maximum amount of shares that may be minted.

MUST NOT revert.

```yaml
- name: maxMint
  type: function
  stateMutability: view

  inputs:
    - name: receiver
      type: address

  outputs:
    - name: maxShares
      type: uint256
```

#### previewMint

Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given current on-chain conditions.

MUST return as close to and no fewer than the exact amount of assets that would be deposited in a `mint` call in the same transaction. I.e. `mint` should return the same or fewer `assets` as `previewMint` if called in the same transaction.

MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint would be accepted, regardless if the user has enough tokens approved, etc.

MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.

MUST NOT revert due to vault specific user/global limits. MAY revert due to other conditions that would also cause `mint` to revert.

Note that any unfavorable discrepancy between `convertToAssets` and `previewMint` SHOULD be considered slippage in share price or some other type of condition, meaning the depositor will lose assets by minting.

```yaml
- name: previewMint
  type: function
  stateMutability: view

  inputs:
    - name: shares
      type: uint256

  outputs:
    - name: assets
      type: uint256
```

#### mint

Mints exactly `shares` Vault shares to `receiver` by depositing `assets` of underlying tokens.

MUST emit the `Deposit` event.

MUST support EIP-20 `approve` / `transferFrom` on `asset` as a mint flow.
MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the `mint` execution, and are accounted for during `mint`.

MUST revert if all of `shares` cannot be minted (due to deposit limit being reached, slippage, the user not approving enough underlying tokens to the Vault contract, etc).

Note that most implementations will require pre-approval of the Vault with the Vault&apos;s underlying `asset` token.

```yaml
- name: mint
  type: function
  stateMutability: nonpayable

  inputs:
    - name: shares
      type: uint256
    - name: receiver
      type: address

  outputs:
    - name: assets
      type: uint256
```

#### maxWithdraw

Maximum amount of the underlying asset that can be withdrawn from the `owner` balance in the Vault, through a `withdraw` call.

MUST return the maximum amount of assets that could be transferred from `owner` through `withdraw` and not cause a revert, which MUST NOT be higher than the actual maximum that would be accepted (it should underestimate if necessary).

MUST factor in both global and user-specific limits, like if withdrawals are entirely disabled (even temporarily) it MUST return 0.

MUST NOT revert.

```yaml
- name: maxWithdraw
  type: function
  stateMutability: view

  inputs:
    - name: owner
      type: address

  outputs:
    - name: maxAssets
      type: uint256
```

#### previewWithdraw

Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block, given current on-chain conditions.

MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a `withdraw` call in the same transaction. I.e. `withdraw` should return the same or fewer `shares` as `previewWithdraw` if called in the same transaction.

MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though the withdrawal would be accepted, regardless if the user has enough shares, etc.

MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.

MUST NOT revert due to vault specific user/global limits. MAY revert due to other conditions that would also cause `withdraw` to revert.

Note that any unfavorable discrepancy between `convertToShares` and `previewWithdraw` SHOULD be considered slippage in share price or some other type of condition, meaning the depositor will lose assets by depositing.

```yaml
- name: previewWithdraw
  type: function
  stateMutability: view

  inputs:
    - name: assets
      type: uint256

  outputs:
    - name: shares
      type: uint256
```

#### withdraw

Burns `shares` from `owner` and sends exactly `assets` of underlying tokens to `receiver`.

MUST emit the `Withdraw` event.

MUST support a withdraw flow where the shares are burned from `owner` directly where `owner` is `msg.sender`.

MUST support a withdraw flow where the shares are burned from `owner` directly where `msg.sender` has EIP-20 approval over the shares of `owner`.

MAY support an additional flow in which the shares are transferred to the Vault contract before the `withdraw` execution, and are accounted for during `withdraw`.

SHOULD check `msg.sender` can spend owner funds, assets needs to be converted to shares and shares should be checked for allowance.

MUST revert if all of `assets` cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner not having enough shares, etc).

Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed. Those methods should be performed separately.

```yaml
- name: withdraw
  type: function
  stateMutability: nonpayable

  inputs:
    - name: assets
      type: uint256
    - name: receiver
      type: address
    - name: owner
      type: address

  outputs:
    - name: shares
      type: uint256
```

#### maxRedeem

Maximum amount of Vault shares that can be redeemed from the `owner` balance in the Vault, through a `redeem` call.

MUST return the maximum amount of shares that could be transferred from `owner` through `redeem` and not cause a revert, which MUST NOT be higher than the actual maximum that would be accepted (it should underestimate if necessary).

MUST factor in both global and user-specific limits, like if redemption is entirely disabled (even temporarily) it MUST return 0.

MUST NOT revert.

```yaml
- name: maxRedeem
  type: function
  stateMutability: view

  inputs:
    - name: owner
      type: address

  outputs:
    - name: maxShares
      type: uint256
```

#### previewRedeem

Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block, given current on-chain conditions.

MUST return as close to and no more than the exact amount of assets that would be withdrawn in a `redeem` call in the same transaction. I.e. `redeem` should return the same or more `assets` as `previewRedeem` if called in the same transaction.

MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the redemption would be accepted, regardless if the user has enough shares, etc.

MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.

MUST NOT revert due to vault specific user/global limits. MAY revert due to other conditions that would also cause `redeem` to revert.

Note that any unfavorable discrepancy between `convertToAssets` and `previewRedeem` SHOULD be considered slippage in share price or some other type of condition, meaning the depositor will lose assets by redeeming.

```yaml
- name: previewRedeem
  type: function
  stateMutability: view

  inputs:
    - name: shares
      type: uint256

  outputs:
    - name: assets
      type: uint256
```

#### redeem

Burns exactly `shares` from `owner` and sends `assets` of underlying tokens to `receiver`.

MUST emit the `Withdraw` event.

MUST support a redeem flow where the shares are burned from `owner` directly where `owner` is `msg.sender`.

MUST support a redeem flow where the shares are burned from `owner` directly where `msg.sender` has EIP-20 approval over the shares of `owner`.

MAY support an additional flow in which the shares are transferred to the Vault contract before the `redeem` execution, and are accounted for during `redeem`.

SHOULD check `msg.sender` can spend owner funds using allowance.

MUST revert if all of `shares` cannot be redeemed (due to withdrawal limit being reached, slippage, the owner not having enough shares, etc).

Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed. Those methods should be performed separately.

```yaml
- name: redeem
  type: function
  stateMutability: nonpayable

  inputs:
    - name: shares
      type: uint256
    - name: receiver
      type: address
    - name: owner
      type: address

  outputs:
    - name: assets
      type: uint256
```

### Events

#### Deposit

`sender` has exchanged `assets` for `shares`, and transferred those `shares` to `owner`.

MUST be emitted when tokens are deposited into the Vault via the `mint` and `deposit` methods.

```yaml
- name: Deposit
  type: event

  inputs:
    - name: sender
      indexed: true
      type: address
    - name: owner
      indexed: true
      type: address
    - name: assets
      indexed: false
      type: uint256
    - name: shares
      indexed: false
      type: uint256
```

#### Withdraw

`sender` has exchanged `shares`, owned by `owner`, for `assets`, and transferred those `assets` to `receiver`.

MUST be emitted when shares are withdrawn from the Vault in `EIP-4626.redeem` or `EIP-4626.withdraw` methods.

```yaml
- name: Withdraw
  type: event

  inputs:
    - name: sender
      indexed: true
      type: address
    - name: receiver
      indexed: true
      type: address
    - name: owner
      indexed: true
      type: address
    - name: assets
      indexed: false
      type: uint256
    - name: shares
      indexed: false
      type: uint256
```

## Rationale

The Vault interface is designed to be optimized for integrators with a feature complete yet minimal interface.
Details such as accounting and allocation of deposited tokens are intentionally not specified,
as Vaults are expected to be treated as black boxes on-chain and inspected off-chain before use.

EIP-20 is enforced because implementation details like token approval
and balance calculation directly carry over to the shares accounting.
This standardization makes the Vaults immediately compatible with all EIP-20 use cases in addition to EIP-4626.

The mint method was included for symmetry and feature completeness.
Most current use cases of share-based Vaults do not ascribe special meaning to the shares such that
a user would optimize for a specific number of shares (`mint`) rather than specific amount of underlying (`deposit`).
However, it is easy to imagine future Vault strategies which would have unique and independently useful share representations.

The `convertTo` functions serve as rough estimates that do not account for operation specific details like withdrawal fees, etc.
They were included for frontends and applications that need an average value of shares or assets, not an exact value possibly including slippage or other fees.
For applications that need an exact value that attempts to account for fees and slippage we have included a corresponding `preview` function to match each mutable function. These functions must not account for deposit or withdrawal limits, to ensure they are easily composable, the `max` functions are provided for that purpose.

## Backwards Compatibility

EIP-4626 is fully backward compatible with the EIP-20 standard and has no known compatibility issues with other standards.
For production implementations of Vaults which do not use EIP-4626, wrapper adapters can be developed and used.

## Reference Implementation

See [Solmate EIP-4626](https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC4626.sol):
a minimal and opinionated implementation of the standard with hooks for developers to easily insert custom logic into deposits and withdrawals.

See [Vyper EIP-4626](https://github.com/fubuloubu/ERC4626):
a demo implementation of the standard in Vyper, with hooks for share price manipulation and other testing needs.

## Security Considerations

Fully permissionless use cases could fall prey to malicious implementations which only conform to the interface but not the specification.
It is recommended that all integrators review the implementation for potential ways of losing user deposits before integrating.

If implementors intend to support EOA account access directly, they should consider adding an additional function call for `deposit`/`mint`/`withdraw`/`redeem` with the means to accommodate slippage loss or unexpected deposit/withdrawal limits, since they have no other means to revert the transaction if the exact output amount is not achieved.

The methods `totalAssets`, `convertToShares` and `convertToAssets` are estimates useful for display purposes,
and do _not_ have to confer the _exact_ amount of underlying assets their context suggests.

The `preview` methods return values that are as close as possible to exact as possible. For that reason, they are manipulable by altering the on-chain conditions and are not always safe to be used as price oracles. This specification includes `convert` methods that are allowed to be inexact and therefore can be implemented as robust price oracles. For example, it would be correct to implement the `convert` methods as using a time-weighted average price in converting between assets and shares.

Integrators of EIP-4626 Vaults should be aware of the difference between these view methods when integrating with this standard. Additionally, note that the amount of underlying assets a user may receive from redeeming their Vault shares (`previewRedeem`) can be significantly different than the amount that would be taken from them when minting the same quantity of shares (`previewMint`). The differences may be small (like if due to rounding error), or very significant (like if a Vault implements withdrawal or deposit fees, etc). Therefore integrators should always take care to use the preview function most relevant to their use case, and never assume they are interchangeable.

Finally, EIP-4626 Vault implementers should be aware of the need for specific, opposing rounding directions across the different mutable and view methods, as it is considered most secure to favor the Vault itself during calculations over its users:

- If (1) it&apos;s calculating how many shares to issue to a user for a certain amount of the underlying tokens they provide or (2) it&apos;s determining the amount of the underlying tokens to transfer to them for returning a certain amount of shares, it should round _down_.

- If (1) it&apos;s calculating the amount of shares a user has to supply to receive a given amount of the underlying tokens or (2) it&apos;s calculating the amount of underlying tokens a user has to provide to receive a certain amount of shares, it should round _up_.

The only functions where the preferred rounding direction would be ambiguous are the `convertTo` functions. To ensure consistency across all EIP-4626 Vault implementations it is specified that these functions MUST both always round _down_. Integrators may wish to mimic rounding up versions of these functions themselves, like by adding 1 wei to the result.

Although the `convertTo` functions should eliminate the need for any use of an EIP-4626 Vault&apos;s `decimals` variable, it is still strongly recommended to mirror
the underlying token&apos;s `decimals` if at all possible, to eliminate possible sources of confusion and simplify integration across front-ends and for other off-chain users.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 22 Dec 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4626</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4626</guid>
      </item>
    
      <item>
        <title>Non-Tradable Tokens Standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4671-non-tradable-token/7976</comments>
        
        <description>## Abstract

A non-tradable token, or NTT, represents inherently personal possessions (material or immaterial), such as university diplomas, online training certificates, government issued documents (national id, driving license, visa, wedding, etc.), labels, and so on.

As the name implies, non-tradable tokens are made to not be traded or transferred, they are &quot;soulbound&quot;. They don&apos;t have monetary value, they are personally delivered to **you**, and they only serve as a **proof of possession/achievement**.

In other words, the possession of a token carries a strong meaning in itself depending on **why** it was delivered.

## Motivation

We have seen in the past smart contracts being used to deliver university diplomas or driving licenses, for food labeling or attendance to events, and much more. All of these implementations are different, but they have a common ground: the tokens are **non-tradable**.

The blockchain has been used for too long as a means of speculation, and non-tradable tokens want to be part of the general effort aiming to provide usefulness through the blockchain.

By providing a common interface for non-tradable tokens, we allow more applications to be developed and we position blockchain technology as a standard gateway for verification of personal possessions and achievements.

## Specification

### Non-Tradable Token

A NTT contract is seen as representing **one type of certificate** delivered by **one authority**. For instance, one NTT contract for the French National Id, another for Ethereum EIP creators, and so on...

* An address might possess multiple tokens. Each token has a unique identifier: `tokenId`.
* An authority who delivers a certificate should be in position to revoke it. Think of driving licenses or weddings. However, it cannot delete your token, i.e. the record will show that you once owned a token from that contract.
* The most typical usage for third-parties will be to verify if a user has a valid token in a given contract.

```solidity
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import &quot;./IERC165.sol&quot;;

interface IERC4671 is IERC165 {
    /// Event emitted when a token `tokenId` is minted for `owner`
    event Minted(address owner, uint256 tokenId);

    /// Event emitted when token `tokenId` of `owner` is revoked
    event Revoked(address owner, uint256 tokenId);

    /// @notice Count all tokens assigned to an owner
    /// @param owner Address for whom to query the balance
    /// @return Number of tokens owned by `owner`
    function balanceOf(address owner) external view returns (uint256);

    /// @notice Get owner of a token
    /// @param tokenId Identifier of the token
    /// @return Address of the owner of `tokenId`
    function ownerOf(uint256 tokenId) external view returns (address);

    /// @notice Check if a token hasn&apos;t been revoked
    /// @param tokenId Identifier of the token
    /// @return True if the token is valid, false otherwise
    function isValid(uint256 tokenId) external view returns (bool);

    /// @notice Check if an address owns a valid token in the contract
    /// @param owner Address for whom to check the ownership
    /// @return True if `owner` has a valid token, false otherwise
    function hasValid(address owner) external view returns (bool);
}
```

#### Extensions

##### Metadata

An interface allowing to add metadata linked to each token.

```solidity
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import &quot;./IERC4671.sol&quot;;

interface IERC4671Metadata is IERC4671 {
    /// @return Descriptive name of the tokens in this contract
    function name() external view returns (string memory);

    /// @return An abbreviated name of the tokens in this contract
    function symbol() external view returns (string memory);

    /// @notice URI to query to get the token&apos;s metadata
    /// @param tokenId Identifier of the token
    /// @return URI for the token
    function tokenURI(uint256 tokenId) external view returns (string memory);
}
```

##### Enumerable

An interface allowing to enumerate the tokens of an owner.

```solidity
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import &quot;./IERC4671.sol&quot;;

interface IERC4671Enumerable is IERC4671 {
    /// @return emittedCount Number of tokens emitted
    function emittedCount() external view returns (uint256);

    /// @return holdersCount Number of token holders  
    function holdersCount() external view returns (uint256);

    /// @notice Get the tokenId of a token using its position in the owner&apos;s list
    /// @param owner Address for whom to get the token
    /// @param index Index of the token
    /// @return tokenId of the token
    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);

    /// @notice Get a tokenId by it&apos;s index, where 0 &lt;= index &lt; total()
    /// @param index Index of the token
    /// @return tokenId of the token
    function tokenByIndex(uint256 index) external view returns (uint256);
}
```

##### Delegation

An interface allowing delegation rights of token minting.

```solidity
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import &quot;./IERC4671.sol&quot;;

interface IERC4671Delegate is IERC4671 {
    /// @notice Grant one-time minting right to `operator` for `owner`
    /// An allowed operator can call the function to transfer rights.
    /// @param operator Address allowed to mint a token
    /// @param owner Address for whom `operator` is allowed to mint a token
    function delegate(address operator, address owner) external;

    /// @notice Grant one-time minting right to a list of `operators` for a corresponding list of `owners`
    /// An allowed operator can call the function to transfer rights.
    /// @param operators Addresses allowed to mint
    /// @param owners Addresses for whom `operators` are allowed to mint a token
    function delegateBatch(address[] memory operators, address[] memory owners) external;

    /// @notice Mint a token. Caller must have the right to mint for the owner.
    /// @param owner Address for whom the token is minted
    function mint(address owner) external;

    /// @notice Mint tokens to multiple addresses. Caller must have the right to mint for all owners.
    /// @param owners Addresses for whom the tokens are minted
    function mintBatch(address[] memory owners) external;

    /// @notice Get the issuer of a token
    /// @param tokenId Identifier of the token
    /// @return Address who minted `tokenId`
    function issuerOf(uint256 tokenId) external view returns (address);
}
```

##### Consensus

An interface allowing minting/revocation of tokens based on a consensus of a predefined set of addresses.

```solidity
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import &quot;./IERC4671.sol&quot;;

interface IERC4671Consensus is IERC4671 {
    /// @notice Get voters addresses for this consensus contract
    /// @return Addresses of the voters
    function voters() external view returns (address[] memory);

    /// @notice Cast a vote to mint a token for a specific address
    /// @param owner Address for whom to mint the token
    function approveMint(address owner) external;

    /// @notice Cast a vote to revoke a specific token
    /// @param tokenId Identifier of the token to revoke
    function approveRevoke(uint256 tokenId) external;
}
```

##### Pull

An interface allowing a token owner to pull his token to a another of his wallets (here `recipient`). The caller must provide a signature of the tuple `(tokenId, owner, recipient)` using the `owner` wallet.

```solidity
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import &quot;./IERC4671.sol&quot;;

interface IERC4671Pull is IERC4671 {
    /// @notice Pull a token from the owner wallet to the caller&apos;s wallet
    /// @param tokenId Identifier of the token to transfer
    /// @param owner Address that owns tokenId
    /// @param signature Signed data (tokenId, owner, recipient) by the owner of the token
    function pull(uint256 tokenId, address owner, bytes memory signature) external;
}
```

### NTT Store

Non-tradable tokens are meant to be fetched by third-parties, which is why there needs to be a convenient way for users to expose some or all of their tokens. We achieve this result using a store which must implement the following interface.

```solidity
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import &quot;./IERC165.sol&quot;;

interface IERC4671Store is IERC165 {
    // Event emitted when a IERC4671Enumerable contract is added to the owner&apos;s records
    event Added(address owner, address token);

    // Event emitted when a IERC4671Enumerable contract is removed from the owner&apos;s records
    event Removed(address owner, address token);

    /// @notice Add a IERC4671Enumerable contract address to the caller&apos;s record
    /// @param token Address of the IERC4671Enumerable contract to add
    function add(address token) external;

    /// @notice Remove a IERC4671Enumerable contract from the caller&apos;s record
    /// @param token Address of the IERC4671Enumerable contract to remove
    function remove(address token) external;

    /// @notice Get all the IERC4671Enumerable contracts for a given owner
    /// @param owner Address for which to retrieve the IERC4671Enumerable contracts
    function get(address owner) external view returns (address[] memory);
}
```

## Rationale

### On-chain vs Off-chain

A decision was made to keep the data off-chain (via `tokenURI()`) for two main reasons: 
* Non-tradable tokens represent personal possessions. Therefore, there might be cases where the data should be encrypted. The standard should not outline decisions about encryption because there are just so many ways this could be done, and every possibility is specific to the use-case.
* Non-tradable tokens must stay generic. There could have been a possibility to make a `MetadataStore` holding the data of tokens in an elegant way, unfortunately we would have needed a support for generics in solidity (or struct inheritance), which is not available today.

## Reference Implementation

You can find an implementation of this standard in [../assets/eip-4671](https://github.com/ethereum/EIPs/tree/master/assets/eip-4671).

Using this implementation, this is how you would create a token:

```solidity
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import &quot;./ERC4671.sol&quot;;

contract EIPCreatorBadge is ERC4671 {
    constructor() ERC4671(&quot;EIP Creator Badge&quot;, &quot;EIP&quot;) {}

    function giveThatManABadge(address owner) external {
        require(_isCreator(), &quot;You must be the contract creator&quot;);
        _mint(owner);
    }

    function _baseURI() internal pure override returns (string memory) {
        return &quot;https://eips.ethereum.org/ntt/&quot;;
    }
}
```

This could be a contract managed by the Ethereum foundation and which allows them to deliver tokens to EIP creators.

## Security Considerations

One security aspect is related to the `tokenURI` method which returns the metadata linked to a token. Since the standard represents inherently personal possessions, users might want to encrypt the data in some cases e.g. national id cards. Moreover, it is the responsibility of the contract creator to make sure the URI returned by this method is available at all times.

The standard does not define any way to transfer a token from one wallet to another. Therefore, users must be very cautious with the wallet they use to receive these tokens. If a wallet is lost, the only way to get the tokens back is for the issuing authorities to deliver the tokens again, akin real life.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 13 Jan 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4671</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4671</guid>
      </item>
    
      <item>
        <title>Multi-Fractional Non-Fungible Tokens</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4675-multi-fractional-non-fungible-token-standard/8008</comments>
        
        <description>## Abstract
This standard outlines a smart contract interface eligible to represent any number of fractionalized non-fungible tokens. Existing projects utilizing standards like [EIP-1633](/EIPs/EIPS/eip-1633) conventionally deploy separate [EIP-20](/EIPs/EIPS/eip-20) compatible token contracts to fractionalize the non-fungible token into EIP-20 tokens. In contrast, this ERC allows each token ID to represent a token type representing(fractionalizing) the non-fungible token.

This standard is approximate in terms of using `_id` for distinguishing token types. However, this ERC has a clear difference with [EIP-1155](/EIPs/EIPS/eip-1155) as each `_id` represents a distinct NFT.

## Motivation
The conventional fractionalization process of fractionalizing a NFT to FT requires deployment of a FT token contract representing the ownership of NFT. This leads to inefficient bytecode usage on Ethereum Blockchain and limits functionalities since each token contract is separated into its own permissioned address.
With the rise of multiple NFT projects needing to fractionalize NFT to FT, new type of token standard is needed to back up them.

## Specification

```solidity
/**
    @title Multi-Fractional Non-Fungible Token Standard
    @dev Note : The ERC-165 identifier for this interface is 0x83f5d35f.
*/
interface IMFNFT {
    /**
        @dev This emits when ownership of any token changes by any mechanism.
        The `_from` argument MUST be the address of an account/contract sending the token.
        The `_to` argument MUST be the address of an account/contract receiving the token.
        The `_id` argument MUST be the token type being transferred. (represents NFT)
        The `_value` argument MUST be the number of tokens the holder balance is decrease by and match the recipient balance is increased by.
    */
    event Transfer(address indexed _from, address indexed _to, uint256 indexed _id, uint256 _value);

    /**
        @dev This emits when the approved address for token is changed or reaffirmed.
        The `_owner` argument MUST be the address of account/contract approving to withdraw.
        The `_spender` argument MUST be the address of account/contract approved to withdraw from the `_owner` balance.
        The `_id` argument MUST be the token type being transferred. (represents NFT)
        The `_value` argument MUST be the number of tokens the `_approved` is able to withdraw from `_owner` balance.
    */
    event Approval(address indexed _owner, address indexed _spender, uint256 indexed _id, uint256 _value);

    /**
        @dev This emits when new token type is added which represents the share of the Non-Fungible Token.
        The `_parentToken` argument MUST be the address of the Non-Fungible Token contract.
        The `_parentTokenId` argument MUST be the token ID of the Non-Fungible Token.
        The `_id` argument MUST be the token type being added. (represents NFT)
        The `_totalSupply` argument MUST be the number of total token supply of the token type.
    */
    event TokenAddition(address indexed _parentToken, uint256 indexed _parentTokenId, uint256 _id, uint256 _totalSupply);

    /**
        @notice Transfers `_value` amount of an `_id` from the msg.sender address to the `_to` address specified
        @dev msg.sender must have sufficient balance to handle the tokens being transferred out of the account.
        MUST revert if `_to` is the zero address.
        MUST revert if balance of msg.sender for token `_id` is lower than the `_value` being transferred.
        MUST revert on any other error.
        MUST emit the `Transfer` event to reflect the balance change.
        @param _to      Source address
        @param _id      ID of the token type
        @param _value   Transfer amount
        @return         True if transfer was successful, false if not
    */
    function transfer(address _to, uint256 _id, uint256 _value) external returns (bool);

    /**
        @notice Approves `_value` amount of an `_id` from the msg.sender to the `_spender` address specified.
        @dev msg.sender must have sufficient balance to handle the tokens when the `_spender` wants to transfer the token on behalf.
        MUST revert if `_spender` is the zero address.
        MUST revert on any other error.
        MUST emit the `Approval` event.
        @param _spender Spender address(account/contract which can withdraw token on behalf of msg.sender)
        @param _id      ID of the token type
        @param _value   Approval amount
        @return         True if approval was successful, false if not
    */
    function approve(address _spender, uint256 _id, uint256 _value) external returns (bool);

    /**
        @notice Transfers `_value` amount of an `_id` from the `_from` address to the `_to` address specified.
        @dev Caller must be approved to manage the tokens being transferred out of the `_from` account.
        MUST revert if `_to` is the zero address.
        MUST revert if balance of holder for token `_id` is lower than the `_value` sent.
        MUST revert on any other error.
        MUST emit `Transfer` event to reflect the balance change.
        @param _from    Source address
        @param _to      Target Address
        @param _id      ID of the token type
        @param _value   Transfer amount
        @return         True if transfer was successful, false if not

    */
    function transferFrom(address _from, address _to, uint256 _id, uint256 _value) external returns (bool);

    /**
        @notice Sets the NFT as a new type token
        @dev The contract itself should verify if the ownership of NFT is belongs to this contract itself with the `_parentNFTContractAddress` &amp; `_parentNFTTokenId` before adding the token.
        MUST revert if the same NFT is already registered.
        MUST revert if `_parentNFTContractAddress` is address zero.
        MUST revert if `_parentNFTContractAddress` is not ERC-721 compatible.
        MUST revert if this contract itself is not the owner of the NFT.
        MUST revert on any other error.
        MUST emit `TokenAddition` event to reflect the token type addition.
        @param _parentNFTContractAddress    NFT contract address
        @param _parentNFTTokenId            NFT tokenID
        @param _totalSupply                 Total token supply
    */
    function setParentNFT(address _parentNFTContractAddress, uint256 _parentNFTTokenId, uint256 _totalSupply) external;

    /**
        @notice Get the token ID&apos;s total token supply.
        @param _id      ID of the token
        @return         The total token supply of the specified token type
    */
    function totalSupply(uint256 _id) external view returns (uint256);

    /**
        @notice Get the balance of an account&apos;s tokens.
        @param _owner  The address of the token holder
        @param _id     ID of the token
        @return        The _owner&apos;s balance of the token type requested
    */
    function balanceOf(address _owner, uint256 _id) external view returns (uint256);

    /**
        @notice Get the amount which `_spender` is still allowed to withdraw from `_owner`
        @param _owner   The address of the token holder
        @param _spender The address approved to withdraw token on behalf of `_owner`
        @param _id      ID of the token
        @return         The amount which `_spender` is still allowed to withdraw from `_owner`
    */
    function allowance(address _owner, address _spender, uint256 _id) external view returns (uint256);

    /**
        @notice Get the bool value which represents whether the NFT is already registered and fractionalized by this contract.
        @param _parentNFTContractAddress    NFT contract address
        @param _parentNFTTokenId            NFT tokenID
        @return                             The bool value representing the whether the NFT is already registered.
    */
    function isRegistered(address _parentNFTContractAddress, uint256 _parentNFTTokenId) external view returns (bool);
}

interface ERC165 {
    /**
        @notice Query if a contract implements an interface
        @param interfaceID The interface identifier, as specified in ERC-165
        @dev Interface identification is specified in ERC-165. This function
        uses less than 30,000 gas.
        @return `true` if the contract implements `interfaceID` and
        `interfaceID` is not 0xffffffff, `false` otherwise
    */
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
```

To receive Non-Fungible Token on `safe Transfer` the contract should include `onERC721Received()`.
Including `onERC721Received()` is needed to be compatible with Safe Transfer Rules.
```solidity
/**
    @notice Handle the receipt of an NFT
    @param _operator The address which called `safeTransferFrom` function
    @param _from The address which previously owned the token
    @param _tokenId The NFT identifier which is being transferred
    @param _data Additional data with no specified format
    @return `bytes4(keccak256(&quot;onERC721Received(address,address,uint256,bytes)&quot;))`
*/
function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data) external pure returns (bytes4);
```

## Rationale

**Metadata**

The `symbol()` &amp; `name()` functions were not included since the majority of users can just fetch it from the originating NFT contract. Also, copying the name &amp; symbol every time when token gets added might place a lot of redundant bytecode on the Ethereum blockchain. 
However, according to the need and design of the project it could also be added to each token type by fetching the metadata from the NFT contract.

**Design**

Most of the decisions made around the design of this ERC were done to keep it as flexible for diverse token design &amp; architecture.
These minimum requirement for this standard allows for each project to determine their own system for minting, governing, burning their MFNFT tokens depending on their programmable architecture.

## Backwards Compatibility

To make this standard compatible with existing standards, this standard `event` &amp; `function` names are identical with ERC-20 token standard with some more `events` &amp; `functions` to add token type dynamically.

Also, the sequence of parameter in use of `_id` for distinguishing token types in `functions` and `events` are very much similar to ERC-1155 Multi-Token Standard.

Since this standard is intended to interact with the EIP-721 Non-Fungible Token Standard, it is kept purposefully agnostic to extensions beyond the standard in order to allow specific projects to design their own token usage and scenario.

## Test Cases

Reference Implementation of MFNFT Token includes test cases written using hardhat. (Test coverage : 100%)

## Reference Implementation
[MFNFT - Implementation](/EIPs/assets/eip-4675/)

## Security Considerations

To fractionalize an already minted NFT, it is evident that ownership of NFT should be given to token contracts before fractionalization.
In the case of fractionalizing NFT, the token contract should thoroughly verify the ownership of NFT before fractionalizing it to prevent tokens from being a separate tokens with the NFT.

If an arbitrary account has the right to call `setParentNFT()` there might be a front-running issue. The caller of `setParentNFT()` might be different from the real NFT sender. 
To prevent this issue, implementors should just allow **admin** to call, or fractionalize and receive NFT in an atomic transaction similar to flash loan(swap).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 13 Jan 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4675</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4675</guid>
      </item>
    
      <item>
        <title>Consensus Layer Withdrawal Protection</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/consensus-layer-withdrawal-protection/8161</comments>
        
        <description>## Abstract

If a consensus layer mnemonic phrase is compromised, it is impossible for the consensus layer network to differentiate the legitimate holder of the key from an illegitimate holder. However, there are signals that can be considered in a wider sense without changing core Ethereum consensus. This proposal outlines ways in which on chain evidence such as the execution layer deposit address and list of signed messages could create a social consensus that would significantly favor but not guarantee legitimate mnemonic holders would win a race condition against an attacker.

## Motivation

The consensus layer `BLSToExecutionChange` message is secure for a single user who has certainty their keys and mnemonic have not been compromised. However, as validator withdrawals on the consensus layer are not possible until the Capella hard fork, no user can have absolute certainty that their keys are not compromised until the `BLSToExecutionChange` is on chain, and by then too late to change. All legitimate mnemonic phrase holders were originally in control of the execution layer deposit address. Beacon node clients and node operators may optionally load a list of verifiable `BLSToExecutionChange` messages to broadcasts that may create a social consensus for legitimate holders to successfully win a race condition against an attacker. If attackers compromise a significant number of consensus layer nodes, it would pose risks to the entire Ethereum community.

Setting a withdrawal address to an execution layer address was not supported by the eth2.0-deposit-cli until v1.1.1 on March 23, 2021, leaving early adopters wishing they could force set their execution layer address to a deposit address earlier. Forcing this change is not something that can be enforced in-protocol, partly due to lack of information on the beacon chain about the execution layer deposit address and partly due to the fact that this was never listed as a requirement. It is also possible that the execution layer deposit address is no longer under the control of the legitimate holder of the withdrawal private key. 

However, it is possible for individual nodes to locally restrict the changes they wish to include in blocks they propose, and which they propagate around the network, in a way that does not change consensus. It is also possible for client nodes to help broadcast signed `BLSToExecutionChange` requests to ensure as many nodes witness this message as soon as possible in a fair manner. Further, such `BLSToExecutionChange` signed messages can be preloaded into clients in advance to further help nodes filter attacking requests.
	
This proposal provides purely optional additional protection. It aims to request nodes set a priority on withdrawal credential claims that favour a verifiable execution layer deposit address in the event of two conflicting `BLSToExecutionChange` messages. It also establishes a list of `BLSToExecutionChange` signed messages to help broadcast &quot;as soon as possible&quot; when the network supports it, and encourage client teams to help use these lists to honour filter and prioritize accepting requests by REST and transmitting them via P2P. This will not change consensus, but may help prevent propagating an attack where a withdrawal key has been knowingly or unknowingly compromised. 
	
It is critical to understand that this proposal is not a consensus change. Nothing in this proposal restricts the validity of withdrawal credential operations within the protocol. It is a voluntary change by client teams to build this functionality in to their beacon nodes, and a voluntary change by node operators to accept any or all of the restrictions and broadcasting capabilities suggested by end users.

Because of the above, even if fully implemented, it will be down to chance as to which validators propose blocks, and which voluntary restrictions those validators’ beacon nodes are running. Node operators can do what they will to help the community prevent attacks on any compromised consensus layer keys, but there are no guarantees of success this will prevent a successful attack. 

## Specification

The Consensus Layer `BLSToExecutionChange` operation has the following fields:

* Validator index
* Current withdrawal BLS public key
* Proposed execution layer withdrawal address
* Signature by withdrawal private key over the prior fields
	
This proposal describes OPTIONAL and RECOMMENDED mechanisms which a client beacon node MAY implement, and end users are RECOMMENDED to use in their beacon node operation.

### `BLSToExecutionChange` Broadcast File

Beacon node clients MAY support an OPTIONAL file of lines specifying &quot;validator index&quot; , &quot;current withdrawal BLS public key&quot; , &quot;proposed execution layer withdrawal address&quot;, and &quot;signature&quot; which, if implemented and if provided, SHALL instruct nodes to automatically submit a one-time `BLSToExecutionChange` broadcast message for each valid signature at the Capella hard fork. This file SHALL give all node operators an OPTIONAL opportunity to ensure any valid `BLSToExecutionChange` messages are broadcast, heard, and shared by nodes at the Capella hard fork. This OPTIONAL file SHALL also instruct nodes to perpetually prefer accepting and repeating signatures matching the signature in the file, and SHALL reject accepting or rebroadcasting messages which do not match a signature for a given withdrawal credential. 
	
### `BLSToExecutionChange` Handling

Beacon node clients are RECOMMENDED to allow accepting &quot;`BLSToExecutionChange` Broadcast&quot; file of verifiable signatures, and then MAY fallback to accept a &quot;first request&quot; via P2P. All of this proposal is OPTIONAL for beacon nodes to implement or use, but all client teams are RECOMMENDED to allow a &quot;`BLSToExecutionChange` Broadcast File&quot; to be loaded locally before the Capella hard fork. This OPTIONAL protection will allow a user to attempt to set a withdrawal address message as soon as the network supports it without any change to consensus. 

## Rationale

This proposal is intended to protect legitimate validator mnemonic holders where it was knowingly or unknowingly compromised. As there is no safe way to transfer ownership of a validator without exiting, it can safely be assumed that all validator holders intend to set to a withdrawal address they specify. Using the deposit address in the execution layer to determine the legitimate holder is not possible to consider in consensus as it may be far back in history and place an overwhelming burden to maintain such a list. As such, this proposal outlines optional mechanism which protect legitimate original mnemonic holders and does so in a way that does not place any mandatory burden on client node software or operators. 

## Backwards Compatibility

As there is no existing `BLSToExecutionChange` operation prior to Capella, there is no documented backwards compatibility. As all of the proposal is OPTIONAL in both implementation and operation, it is expected that client beacon nodes that do not implement this functionality would still remain fully backwards compatible with any or all clients that do implement part or all of the functionality described in this proposal. Additionally, while users are RECOMMENDED to enable these OPTIONAL features, if they decide to either disable or ignore some or all of the features, or even purposefully load content contrary to the intended purpose, the beacon node client will continue to execute fully compatible with the rest of the network as none of the proposal will change core Ethereum consensus. 

## Reference Implementation

### `BLSToExecutionChange` Broadcast File

A &quot;change-operations.json&quot; file intended to be preloaded with all consensus layer withdrawal credential signatures and verifiable execution layer deposit addresses. This file may be generated by a script and able to be independently verified by community members using the consensus layer node, and intended to be included by all clients, enabled by default. Client nodes are encouraged to enable packaging this independently verifiable list with the client software, and enable it by default to help further protect the community from unsuspected attacks. 

The change-operations.json format is the &quot;`BLSToExecutionChange` File - Claim&quot; combined into a single JSON array.

### `BLSToExecutionChange` Broadcast File - Claim

A community collected and independently verifiable list of &quot;`BLSToExecutionChange` Broadcasts&quot; containing verifiable claims will be collected. Node operators may verify these claims independently and are suggested to load claims in compatible beacon node clients. 

To make a verifiable claim, users MAY upload a claim to any public repository in a text file &quot;[chain]/validatorIndex.json&quot; such as &quot;mainnet/123456.json&quot;.

123456.json:

```
[{&quot;message&quot;:{&quot;validator_index&quot;:&quot;123456&quot;,&quot;from_bls_pubkey&quot;:&quot;0x977cc21a067003e848eb3924bcf41bd0e820fbbce026a0ff8e9c3b6b92f1fea968ca2e73b55b3908507b4df89eae6bfb&quot;,&quot;to_execution_address&quot;:&quot;0x08f2e9Ce74d5e787428d261E01b437dC579a5164&quot;},&quot;signature&quot;:&quot;0x872935e0724b31b2f0209ac408b673e6fe2f35b640971eb2e3b429a8d46be007c005431ef46e9eb11a3937f920cafe610c797820ca088543c6baa0b33797f0a38f6db3ac68ffc4fd03290e35ffa085f0bfd56b571d7b2f13c03f7b6ce141c283&quot;}]
```

#### Claim Acceptance

In order for a submission to be merged into public repository, the submission must have:

1. Valid filename in the format validatorIndex.json
2. Valid validator index which is active on the consensus layer 
3. Verifiable signature
5. A single change operation for a single validator, with all required fields in the file with no other content present

All merge requests that fail will be provided a reason from above which must be addressed prior to merge. Any future verifiable amendments to accepted claims must be proposed by the same submitter, or it will be treated as a contention.

#### `BLSToExecutionChange` Broadcast

Anyone in the community will be able to independently verify the files from the claims provided using the Capella spec and command line clients such as &quot;ethdo&quot; which support the specification. 

A claim will be considered contested if a claim arrives where the verifiable consensus layer signatures differ between two or more submissions, where neither party has proven ownership of the execution layer deposit address. If a contested but verified &quot;`BLSToExecutionChange` Broadcast&quot; request arrives to a repository, all parties can be notified, and may try to convince the wider community by providing any publicly verifiable on chain evidence or off chain evidence supporting their claim to then include their claim in nodes. Node operators may decide which verifiable claims they wish to include based on social consensus. 

## Security Considerations

### 1: Attacker lacks EL deposit key, uncontested claim

* User A: Controls the CL keys and the EL key used for the deposit
* User B: Controls the CL keys, but does not control the EL key for the deposit

User A signs and submits a claim to the CLWP repository, clients load User A message into the &quot;`BLSToExecutionChange` Broadcast&quot; file. At the time of the first epoch support `BLSToExecutionChange`, many (not all) nodes begin to broadcast the message. User B also tries to submit a different but valid `BLSToExecutionChange` to an address that does not match the signature in the claim. This message is successfully received via REST API, but some (not all) nodes begin to silently drop this message as the signature does not match the signature in the &quot;`BLSToExecutionChange` Broadcast&quot; file. As such, these nodes do not replicate this message via P2P.  

### 2: Attacker has both EL deposit key and CL keys, uncontested claim

* User A: Controls the CL key/mnemonic and the EL key used for the deposit, and submits a claim to move to a new address
* User B: Controls the CL and EL key/mnemonic used for the EL deposit, but fails to submit a claim

It is possible/likely that User A would notice that all their funds in the EL deposit address had been stolen. This may signal that their CL key is compromised as well, so they decide to pick a new address for the withdrawal. The story will play out the same as Scenario 1 as the claim is uncontested. 

### 3: Same as #2, but the attacker submits a contested claim

* User A: Controls the CL keys/mnemonic and the EL key used for the deposit, and submits a claim to move to a new address
* User B: Controls the CL keys/mnemonic and the EL key used for the deposit, and submits a claim to move to a new address

This is a contested claim and as such there is no way to prove who is in control using on chain data. Instead, either user may try to persuade the community they are the rightful owner (identity verification, social media, etc.) in an attempt to get node operators to load their contested claim into their &quot;`BLSToExecutionChange` Broadcast&quot; file. However, there is no way to fully prove it. 

### 4: A user has lost either their CL key and/or mnemonic (no withdrawal key)

* User A: Lacks the CL keys and mnemonic

There is no way to recover this scenario with this proposal as we cannot prove a user has lost their keys, and the mnemonic is required to generate the withdrawal key. 

### 5: End game - attacker

* User A: Controls EL and CL key/mnemonic, successfully achieves a set address withdrawal
* User B: Controls CL key, decides to attack

Upon noticing User A has submitted a successful set address withdrawal, User B may run a validator and attempt to get User A slashed. Users who suspect their validator key or seed phrase is compromised should take action to exit their validator as early as possible.

### 6: Compromised key, but not vulnerable to withdrawal

* User A: Controls EL and CL key/mnemonic, but has a vulnerability which leaks their CL key but NOT their CL mnemonic
* User B: Controls the CL key, but lacks the CL mnemonic

User A may generate the withdrawal key (requires the mnemonic). User B can attack User A by getting them slashed, but will be unable to generate the withdrawal key. 

### 7: Attacker loads a malicious `BLSToExecutionChange` Broadcast file into one or multiple nodes, User A submits claim

* User A: Submits a valid uncontested claim which is broadcast out as soon as possible by many nodes
* User B: Submits no claim, but broadcasts a valid malicious claim out through their `BLSToExecutionChange` Broadcast list, and blocks User A&apos;s claim from their node.

User B&apos;s claim will make it into many nodes, but when it hits nodes that have adopted User A&apos;s signature they will be dropped and not rebroadcast. Statistically, User B will have a harder time achieving consensus among the entire community, but it will be down to chance. 

### 8: Same as #7, but User A submits no claim

The attacker will statistically likely win as they will be first to have their message broadcast to many nodes and, unless User A submits a request exactly at the time of support, it is unlikely to be heard by enough nodes to gain consensus. All users are encouraged to submit claims for this reason because nobody can be certain their mnemonic has not been compromised until it is too late. 

### Second Order Effects

1. A user who participates in the &quot;`BLSToExecutionChange` Broadcast&quot; may cause the attacker to give up early and instead start to slash. For some users, the thought of getting slashed is preferable to giving an adversary any funds. As the proposal is voluntary, users may choose not to participate if they fear this scenario.
2. The attacker may set up their own `BLSToExecutionChange` Broadcast to reject signatures not matching their attack. This is possible with or without this proposal. 
3. The attacker may be the one collecting &quot;`BLSToExecutionChange` Broadcast&quot; claims for this proposal and may purposefully reject legitimate requests. Anyone is free to set up their own community claim collection and gather their own community support using the same mechanisms described in this proposal to form an alternative social consensus. 

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 30 Jan 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4736</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4736</guid>
      </item>
    
      <item>
        <title>Simplify EIP-161</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4747-simplify-eip-161/8246</comments>
        
        <description>## Abstract

Simplify the definition of [EIP-161](/EIPs/EIPS/eip-161), removing the requirement for implementors to support edge cases that are impossible on Ethereum Mainnet.

## Motivation

EIP-161 is overly complex and has a number of edge cases that are poorly documented and tested. This EIP takes advantage of the complete removal of all remaining empty accounts in block 14049881 (tx `0xf955834bfa097458a9cf6b719705a443d32e7f43f20b9b0294098c205b4bcc3d`) to clarify it, and allows implementors to not implement various edge cases that never occurred and are not possible in the future.

In particular, this EIP permits implementors who do not wish to support historical blocks to not implement state clearing at all.

## Specification
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.

Retroactively replace EIP-161, starting from its introduction in block 2675000, with the following rules:

a. When creating an account, set it&apos;s nonce to `1` prior to executing initcode.

b. When performing EVM execution treat all empty accounts as if they do not exist. Any operation that would create an empty account instead leaves it non-existent.

c. If one of the following events happens to an empty account `X`, it is deleted:

1. `X` receives a zero value `CALL`.
2. `X` is the recipient of a zero value transaction.
3. `X` is the beneficiary of a `SELFDESTRUCT` with zero value.

If the transaction, `CALL` or `SELFDESTRUCT` is reverted, then the state clearing is also reverted. As a special case on Ethereum Mainnet, in block 2675119 (tx `0xcf416c536ec1a19ed1fb89e4ec7ffb3cf73aa413b3aa9b77d60e4fd81a4296ba`), an empty call is made to an empty account at `RIPEMD160` (precompile `0x3`), the call fails out of gas, but the empty account is removed anyway.

The deletion MAY happen immediately or be processed at the end of the transaction. A client may assume that `STATICCALL`s to empty accounts never occur and that `CALL`s to empty accounts in `STATICCALL` contexts never occur.

On Ethereum Mainnet, the only state clearing events after the start of Byzantium are the two listed below. Clients MAY implement post Byzantium state clearing by hardcoding those events.

* In block 4457731 (tx `0x63791f962e13e6b01ec13d38a8ab66c87c2f5a1768276f866300d900cca808fe`), `0xd29DFe5aE95B5C067a91F472Dac0d9be6700A4A9` receives a zero value `SELFDESTRUCT` and is cleared.

* In block 14049881 (tx `0xf955834bfa097458a9cf6b719705a443d32e7f43f20b9b0294098c205b4bcc3d`), the following accounts receive zero value calls and are cleared.
    &lt;details&gt;
    &lt;summary&gt;Accounts cleared&lt;/summary&gt;

    ```
    0x01a3dd7d158e3b4c9d8d2af0ddcf3df0f5e14463
    0x0366c731dd7c095dc08896806765a649c6c0885a
    0x056c68da52395f1d42c5ba15c4fb956146a4f2c1
    0x070ba92497cd4b88a8a9a60795ca7d7f7de0faa3
    0x07a1648ce2bed6721a5d25de3c228a296d03fd52
    0x07b14ba68f474529cc0bd6a9bffee2bc4090d185
    0x07ea32232e37d44134a3071319d228bdab249a60
    0x096b7382500fa11c22c54c0422c5e38899a2e933
    0x09f3200441bd60522bcf28f3666f8e8dbd19fb62
    0x0ad0f3c60696adece09367a9a11c968fb88560bb
    0x0af6181e1db22071f38fc162e1610e29d288de04
    0x0cdc7fef8f8d0ee77360060930aada1263b26ff7
    0x0dac3d571eb5b884a2550db2791d5ac1efca306b
    0x0ec857faba49392080b68dd5074d85f34724d04a
    0x0f5054f9c674b37d15915ca8925f231edb3afa8c
    0x0f78d535e1faad9a982dca2a76d16da4649f7021
    0x104c5b235166f26df54f52666d5e77d9e03e353e
    0x106b47175965b6d607008544267c91490672a54f
    0x1223d5c03b4d52ebed43f781251098c9138c3dd7
    0x1251d13cde439378349f039379e83c2641b6269f
    0x12c814cebee6bb08a5d1b9d009332bf8b536d645
    0x150c63df3da35e590a6d2f7accf2e6f241ea5f1a
    0x15ddf20e4eb8b53b823bc45c9bad2670aad907dd
    0x1712b1c428f89bc695b1871abfff6b5097350150
    0x178df2e27b781f024e90ab0abe9cff7e2f66a5fc
    0x1c2bd83dc29095173c4bcc14927811f5141c1373
    0x1d12f2fad3603ea871fcb13ac3e30674f9ad903f
    0x1f7391b6881b6f025aef25cff737ff3fcb9d7660
    0x219a3d724f596a4b75656e9b1569289c71782804
    0x21a7fd9228c46ec72f926978f791fc8bfcd277fa
    0x23acb760cebd01fe7c92361274a4077d37b59f4c
    0x23b249eeeeedd86bc40349f8bb8e2df34bd28f78
    0x28d006b1a2309e957005ee575f422af8034f93df
    0x28ef72d5614b2833d645aecf8ef7add075eb21e2
    0x292966802ffedb6f34f2c8c59df35c9d8f612c24
    0x2c2661ddd320017138075aba06999440a902695f
    0x2c632be2dc2f47affd07bfce91bd4a27c02f4563
    0x2f86de22ced85a7dd0d680fc4266929a72775e27
    0x2fa04f15123025ab487dce71668f5265649d0598
    0x30f78fd12c17855453e0db166fecf684bb239b8c
    0x31534e95353323209cd18ad35c22c2528db6d164
    0x336e0e1a14e0136c02bf8dcf0a9a3fe408548262
    0x340399588bba5b843883d1ad7afd771a3651447a
    0x341d2b82d0924ef42d75ce053654295d34839459
    0x34c2b8975b47e13818f496cf80b40566798cf968
    0x370e67f45db9c18d6551000e6c0918bc8d346ebf
    0x37149dae898296173d309f1de6981922ec1dc495
    0x377cb0d3427af7f06df47d2ab420458834bed1fc
    0x3d473af3e6ce45183c781b414e8a9edcb8b26f72
    0x42794c1d807079e16735e47e193825cec80ee28c
    0x45603aa97b67965b42b38ddc8884373edbcf2d56
    0x465cb9df2f6d3c8a1c1ce3f2338823f0638fefa5
    0x49fbe69c2897bce0340b5983a0f719213a8c6e6f
    0x4a84cbd3ef642e301aa59bedf4fa4d28e24e6204
    0x4d4d551bd6244b854e732572902f19f4ccaa6996
    0x4f62af4ec150ea121859b3368e6a61fb7bcf9002
    0x4fd1c530f73ddfff5c609a4a8b25af6ca489d1fd
    0x50010a4f0e429b398c66876dea7694d5f8b1a639
    0x522c9f65bc77ad9eed6bcdc3ec220236451c9583
    0x52b30ca3c2f8656e2c022e896bef7fad9a0449ca
    0x537a7030ecd9d159e8231ce31b0c2e83b4f9ed75
    0x5483a4c5583d5ba3db23676a3db346f47ba357e1
    0x55ec1a78a1187428dc0c67cbb77ae9fbdd61cc2a
    0x56cc1c0aadc2b8beb71f1ac61f03645483abe165
    0x58bea8cea61fad5c453731aaeed377f3d77a04cc
    0x58f632327fbc4f449bda3bd51e13f590e67a8627
    0x59d122afcbd68c731de85c2597004c6ddafbc7ed
    0x5da0228024cc084b9475470a7b7ae1d478d51bb7
    0x5e51d6621883afcbd4e999b93180a96909bdc766
    0x5e9a0a1bdfdd868706f4554aae21bb2c46da32c2
    0x5f3f0d3215db85faa693d99acfb03cca66556671
    0x5f6aa25f22edb2347b464312e2508cbc4c6e0162
    0x6006f79e4104850ab7c9b0f75918c1e2cf6311df
    0x60f5da58bccb716f58b5759a06fc2167fe237c26
    0x62d3a444d0af59f9de79f8abeb5c942fcfbfbef5
    0x630ea66c8c5dc205d45a978573fa86df5af1fe7a
    0x6464f0f96a29934087a955c67a6b53d5ed852e49
    0x6653cedb0b7f51c4b0c44079eb45c514df24ecfd
    0x66d69ac12b573299f36b108792be75a1e2ccdfdc
    0x690ed837d25b46dbf46727fcda7392d997c2bc97
    0x696eecbc97189c5b2a8245a8e32517db9960c171
    0x69aaff0b7babe85e0a95adfc540e689399db7f24
    0x6b71d2ceab5678b607aa1e69b6781f5c7abc9aaf
    0x6e03d9cce9d60f3e9f2597e13cd4c54c55330cfd
    0x6e278cfecfe96fa5e6d5411ba6eeb765dff4f118
    0x6e557f01c9dcb573b03909c9a5b3528aec263472
    0x6ec268f8bef9c685d7e04d5cdb61fbb544869a9f
    0x6f2ba051b3ce06a90705c22e0241c2b7e32c1af0
    0x7063732ced55cfa08aea520f3fe200c39b3df0f5
    0x7073a17a0172dfb1e46a62f054d11a775aeac32e
    0x71d3718cfa0f9ee8173688fe52bb499e1f36534b
    0x74e20aec156674945894d404f8dea602570e62f5
    0x783e45c2989e675ffc9d067914d7de3ff68aee58
    0x7a5f843f884bb15d070806e1ff59b6c6f74bbe2d
    0x7c6b1706c86ea76a0e232324f249e1508ca2dfda
    0x7d23a23584c83c1f6636124255cfd8e9cfc0e529
    0x7e8b5df0dec9168741c93d52d7045aca7ea632d3
    0x7ec5da0f1036750688084252b802befe41551205
    0x82c9fcef4dd2d374b000063d4899a38a7219cdc7
    0x82fa2ab30a566ceeac987eb5510485be9382f130
    0x83d927aca3266f94e8163eaa32700c70e9b76e6e
    0x8476f7e193c930f21e88dae84888e0d8bfaf3ed8
    0x85ec166cb81f5010b4a8d365821473dac0c0aa88
    0x8883c55943d5caf06b6484de9c1d73da8307cd82
    0x8c07456cffd4254c89aaaa9d4e95c8b3e36c2a3b
    0x8fef965e5db6f7f1a165008499e8b7901cd766b2
    0x9018e2967c15e1faed9b5d6439522f075535a683
    0x903f1d8a086c6af1afe24648b6409aade83c4340
    0x9127c398827d8db6b6d5f17b71f5db69d06e8b74
    0x917b5be6e3acd96d40a33c13e6748e4a88576c6d
    0x91edfd05112f0bc9d6cd43b65361713a50e9eb7f
    0x93026a2c4a0bc69de31515070bf086e0c1f789e5
    0x94863bbbc12ec5be148f60a7020fd49236fc1937
    0x94befc001e203f141462f16bde60873bcefae401
    0x94c408cf5934f241d4fdd55ff3825131635c6af2
    0x94cfdec548de92301735dc0b82d8e1f79404ff94
    0x96527f3311f44340887c926acc16f0997eb3b955
    0x974117faf194885c01513e8d87b38a2291083ed5
    0x993424827a5fb2fa97818814ea4027e28150f187
    0x9a6f30a5cb46840076edd780da2dbb4bc7c39f24
    0x9a74a096b0bb82adfd28494107f2c07f4545723e
    0x9af82ec46185641c0ea44679aac8a7e7570be202
    0x9e2287a60ed85f6bd80c62c1b7b4130ea1b521dd
    0x9fee5b81ee0cbf34c18c52061f1b257d4ccb2702
    0xa017226377e775af8e56450301cc035ae72267f8
    0xa1b423e024daf925f25296ea2efcf009cc328873
    0xa23c0cbfe59e8650277ffa635c59f287cece9087
    0xa340b7625eec76b372f2c317fe08a7733f05d09c
    0xa4cb6be13c2eace6c0f1157553e3c446f7b38b10
    0xa54326267784fae3ffd6800af38099753bb7f470
    0xa580086125d040fddd3af9d563285bd0ec4d13e3
    0xa88fc7a34ca36b952aa45d94c1e13155042b5e7d
    0xac8f4ce2e4eff39c738bf1941350b3b57e8eec4f
    0xacb17dca110db022b1aceb5399acba1e9bf577e3
    0xae0b03c8d8bf9cf71eda758e9e8b59c70a3b4580
    0xae365ff4b0c64413baf6f7dfdb5cd3fb65ad1376
    0xaf7e60d02b425b54730b7281a97d1640233704b0
    0xaf9846f8098656e7c2f0e53e9ff7d38ec7b7f679
    0xb2784c0a95e9b6b865aca13556fb32e2f37cb775
    0xb385fa211cd08326ff84b0d4f37cc8c3735aa3aa
    0xb3fb883cbbccb0551daf1507f87426fd38da087e
    0xb6515cfb82fa877fbadae5a87006a8d3deeeb7c9
    0xb78c4f0b8c9ec0b3058724eca65292d0d65586b9
    0xba25f341e16ee81ab80ea246d45bdead7cc339e5
    0xbab14024437285c2e3b3c521abff96b0ef2e919f
    0xbaf0996297cc70fca1bee30162eabcd892f0574a
    0xbb01ea95321a94242c89479995b7e3f264cb46a0
    0xc1b37a3b7f76947e24cc2470e0e948aab0181346
    0xc24431c1a1147456414355b1f1769de450e524da
    0xc467b893e29277f9b62b4ed6c9ba054bd8225bff
    0xc4bc101a168ea2228973a65564a7d40a68528dd2
    0xc784626571c2c25cd2cfe24192a149cad86d40d8
    0xc7acf90a9f442855b8f291288bb5fb612536ed9b
    0xc9956593dbfb46cfd24686a365b34051a55abce6
    0xca2eb2af7dd7a90777c8c6456efcc00fe56dbd6f
    0xcb4bb078edaae9393c8da27b809aa9c0f4c920b7
    0xcc8f68e8e2d8196e2ecd0caf2f35b1611739a21f
    0xcd67903318a805d63fe79bf9b8401c1b79c6babf
    0xcd7a2fe9cb80c95b03950daf5b6d476bec9ac24d
    0xd09476f5ee7979becca8ffe6dc22a72565fc3cea
    0xd1c4bd2b583f445354d1b644ea4b8353f2d23048
    0xd32bb8bceafc89ff59ba43ce8b6cd65bb06dd7b0
    0xd49e9fa792db9d9398c57eabf94ba1b2c709ace7
    0xd6b862cf0d009bde0f020ab9d8f96e475069c5c6
    0xd747c05d9c8057db608ef7aedabf07e4db0bbe97
    0xdb9b40d1b691ced3680e539261b6bc195388b3c0
    0xdbcc502093cadd0feb709708c633e2427aeb9c2d
    0xdc53001181ddc6a279deea6419443ea0ac0aec9c
    0xde3b38cb1050e7b5db39b4cbb2b2b63a1e32cbf6
    0xdf1b687a99216ad4ebf9176983bf165be7b25bbe
    0xe000662c02a02d8b40aabfcd661594312992311d
    0xe30c59e4dc19d7c9ed6eb10d734d4d7ef28403ac
    0xe415114089b4b4933e542a5c79af4b6e6cd7abc9
    0xe47f0a0e93241d390fe9b99de852682522e847bc
    0xe54abbd51e324bf8cf349b6b31c01b043d1ee0e4
    0xe57838f777b11fdc428d9e7e67f1187d6251ba1f
    0xe5e4b26325d0fbf551367f2cf3b5d01caed6abcf
    0xe6655208bd812d833238b560e847014b0aab3b51
    0xe6e16a1023af4a8fe54669f3fce7c406801bb333
    0xe727bba699fbe82a731dad9476b5234d0038cfa1
    0xec361d34a55e24e2f77de7121ae2b7bf11ed0d65
    0xed3bf94976eb11d55b955d1369a478620872b57c
    0xee93ad447fe6a0e2bbac4952e651b21c0175acad
    0xefc5d9cabc0bda8124e1b821e8c86c7e7bf1e4bc
    0xf272f72a00f166f491d994642c8243099b72d2cd
    0xf45f642034bbce869e31b05d1da919125c7331ee
    0xf4883b21724405b19e240f3309a64d16dd89adc7
    0xf5cb2a87ff1095f6d93e7b4bfc1bc47542380550
    0xf6ddd386c4f7f0b460032c8055d7f9c3503d7140
    0xf72093096c81b3e9e991f5b737baec9570a56927
    0xf7412232a7a731bca2e5554c8ee051274373c17c
    0xfc2321dc32c2e6e96a0e41c911fb73a7b278d5c8
    0xfc4dc782bf7e81a2ed5cc0519f80de36e7931bd9
    0xfcde1c261eb257e14491b4e7cb1949a7623c00c5
    0xfd17a22fd80075f2716e93268aa01bcdd7d70b22
    ```
    &lt;/details&gt;


## Rationale

EIP-161 provides that empty accounts (accounts that have zero nonce, zero balance and no code, but that might have storage) can no longer be created and provides mechanism to remove old empty accounts. The last empty accounts were removed in block 14049881 (tx `0xf955834bfa097458a9cf6b719705a443d32e7f43f20b9b0294098c205b4bcc3d`).

The complete removal of all empty accounts ensures that certain edgecases of EIP-161 can never occur on Ethereum Mainnet. Continuing to define and test those cases as part of the Ethereum Specification burdens future client implementors with unnecessary technical debt. This EIP declares those cases undefined and leaves clients free to assume they will not occur.

## Backwards Compatibility

This EIP is identical to EIP-161 except for the following differences, none of which affect Ethereum Mainnet. The differences are:

### &quot;Potentially state-changing operations&quot;

EIP-161 specifies 11 &quot;potentially state-changing operations&quot; that trigger state clearing. All but the 3 listed in this EIP are irrelevant, for the following reasons:

#### Impossible

* Receiving zero value mining reward/fees (this would become possible after the merge).

#### Cannot happen to an empty account

* Being the source of a `CREATE`.
* Being the source of a `CALL`.
* Being refunded by a `SELFDESTRUCT`

#### Causes the account to become non-empty

* Being the sender of a message call transaction.
* Being the sender of a contract creation transaction.
* Being created by a `CREATE`.
* Being created by a contract creation transaction.

### Interaction with `STATICCALL`

The interaction between `STATICCALL` and account clearing has never been specified in an EIP. The Ethereum currently testsuite requires that `STATICCALL` triggers state clearing.

This EIP formally undefines all interactions between `STATICCALL` and state clearing as it has never happened on Ethereum Mainnet and cannot happen in future.

### &quot;At the end of the transaction&quot;

This only makes a difference if an account is deleted and later recreated in the same transaction. This never happens on Ethereum Mainnet.

### Test Cases

All test cases involving empty accounts in the Ethereum execution layer test suite shall be removed unless they relate to the Spurious Dragon Hardfork. If a Spurious Dragon test relates involved deprecated edgecase the test must be removed or reworked.

### Other networks

Ropsten had empty accounts seeded at genesis. They appear to have been cleared early in Ropsten&apos;s history before the Byzantium hardfork. Ropsten has never been checked for edgecases occurring. All other Ethereum testnets have had EIP-161 from genesis.

As a security precaution all empty accounts on Ethereum Classic have been cleared, but no checks for edgecases occurring have been done. Due to EIP-161&apos;s age the vast majority of EVM compatible networks have supported it from genesis.

## Security considerations

This EIP is only equivalent to EIP-161 on Ethereum Mainnet if the following facts are true:

1. No empty accounts are ever touched and then reinstated in the same transaction.
2. The transactions in the Appendix are the only state clearing transactions on Ethereum Mainnet after block 4370000 (start of Byzantium).
3. All empty accounts have been removed on Ethereum Mainnet.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 02 Feb 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4747</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4747</guid>
      </item>
    
      <item>
        <title>EOF - Functions</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4750-eof-functions/8195</comments>
        
        <description>## Abstract

Introduce the ability to have several code sections in EOF-formatted ([EIP-3540](/EIPs/EIPS/eip-3540)) bytecode, each one representing a separate subroutine/function. Two new opcodes,`CALLF` and `RETF`, are introduced to call and return from such a function. Dynamic jump instructions are disallowed.

## Motivation

Currently, in the EVM everything is a dynamic jump. Languages like Solidity generate most jumps in a static manner (i.e. the destination is pushed to the stack right before, `PUSHn .. JUMP`). Unfortunately however this cannot be used by most EVM interpreters, because of added requirement of validation/analysis. This also restricts them from making optimisations and potentially reducing the cost of jumps.

[EIP-4200](/EIPs/EIPS/eip-4200) introduces static jump instructions, which remove the need for *most* dynamic jump use cases, but not everything can be solved with them.

This EIP aims to remove the need and disallow dynamic jumps as it offers the most important feature those are used for: calling into and returning from functions.

Furthermore, it aims to improve analysis opportunities by encoding the number of inputs and outputs for each given function, and isolating the stack of each function (i.e. a function cannot read the stack of the caller/callee).

## Specification

### Type Section

The type section of EOF containers must adhere to following requirements:

1. The section is a list of metadata where the metadata index in the type section corresponds to a code section index. Therefore, the type section size MUST be `n * 4` bytes, where `n` is the number of code sections.
2. Each metadata item has 3 attributes: a uint8 `inputs`, a uint8 `outputs`, and a uint16 `max_stack_increase`. *Note:* This implies that there is a limit of 255 stack for the input and in the output. This is further restricted to 127 stack items, because the upper bit of both the input and output bytes are reserved for future use (`outputs == 0x80` is already used in EOF1 to denote non-returning functions, as introduced in a separate EIP). `max_stack_increase` is further defined in [EIP-5450](/EIPs/EIPS/eip-5450).
3. The 0th code section MUST have 0 inputs and be non-returning.

Refer to [EIP-3540](/EIPs/EIPS/eip-3540) to see the full structure of a well-formed EOF bytecode.

### New execution state in EVM

A return stack is introduced, separate from the operand stack. It is a stack of items representing execution state to return to after function execution is finished. Each item is comprised of code section index and offset in the code section (PC value).

Note: Implementations are free to choose particular encoding for a stack item. In the specification below we assume that representation is two unsigned integers: `code_section_index`, `offset`.

The return stack is limited to a maximum of `1024` items.

Additionally, EVM keeps track of the index of currently executing section - `current_section_index`.

### New instructions

We introduce two new instructions:

1. `CALLF` (`0xe3`) - call a function
2. `RETF` (`0xe4`) - return from a function

If the code is legacy bytecode, any of these instructions results in an *exceptional halt*. (*Note: This means no change to behaviour.*)

First we define several helper values:

- `type[i].inputs = type_section_contents[i * 4]` - number of inputs of ith code section
- `type[i].outputs = type_section_contents[i * 4 + 1]` - number of outputs of ith code section
- `type[i].max_stack_increase = type_section_contents[i * 4 + 2:i * 4 + 4]` - maximum operand stack height increase of ith code section

If the code is valid EOF1, the following execution rules apply:

#### `CALLF`

1. Has one immediate argument,`target_section_index`, encoded as a 16-bit unsigned big-endian value.
2. *Note:* EOF validation [EIP-5450](/EIPs/EIPS/eip-5450) guarantees that operand stack has enough items to use as callee&apos;s inputs.
3. If operand stack size exceeds `1024 - type[target_section_index].max_stack_increase` (i.e. if the called function may exceed the global stack height limit), execution results in exceptional halt. This also guarantees that the stack height after the call is within the limits.
4. If return stack already has `1024` items, execution results in exceptional halt.
5. Charges `5` gas.
6. Pops nothing and pushes nothing to operand stack.
7. Pushes to return stack an item:

   ```
   (code_section_index = current_section_index, 
   offset = PC_post_instruction)
   ```
   
   Under `PC_post_instruction` we mean the PC position after the entire immediate argument of `CALLF`.
   
   *Note:* EOF validation [EIP-5450](/EIPs/EIPS/eip-5450) guarantees there is always an instruction following `CALLF` (since terminating instruction or unconditional jump is required to be final one in the section), therefore `PC_post_instruction` always points to an instruction inside section bounds.
8. Sets `current_section_index` to `target_section_index` and `PC` to `0`, and execution continues in the called section.

#### `RETF`

1. Does not have immediate arguments.
2. *Note:* EOF validation [EIP-5450](/EIPs/EIPS/eip-5450) guarantees that operand stack has exact number of items to use as outputs.
3. Charges `3` gas.
4. Pops nothing and pushes nothing to operand stack.
5. Pops an item from return stack and sets `current_section_index` and `PC` to values from this item.

*Note:* EOF validation requirement for 0th code section to be non-returning (non-returning sections introduced in a separate EIP) guarantees that return stack cannot be empty before `RETF`.

### Code Validation

In addition to container format validation rules above, we extend code section validation rules (as defined in [EIP-3670](/EIPs/EIPS/eip-3670)).

1. Code validation rules of [EIP-3670](/EIPs/EIPS/eip-3670) are applied to every code section.
2. Code section is invalid in case an immediate argument of any `CALLF` is greater than or equal to the total number of code sections.
3. `RJUMP`, `RJUMPI` and `RJUMPV` immediate argument value (jump destination relative offset) validation:
    1. Code section is invalid in case offset points to a position outside of section bounds.
    2. Code section is invalid in case offset points to one of two bytes directly following `CALLF` instruction.
5. No unreachable code sections are allowed, i.e. every code section can be reached from the 0th code section with a series of `CALLF` / `JUMPF` (`JUMPF` introduced in a separate EIP) instructions (0th code section is always reachable).

### Disallowed instructions

Dynamic jump instructions `JUMP` (`0x56`) and `JUMPI` (`0x57`) are invalid and their opcodes are undefined.

`JUMPDEST` (`0x5b`) instruction is renamed to `NOP` (&quot;no operation&quot;) without the change in behaviour: it pops nothing and pushes nothing to operand stack and has no other effects except for `PC` increment and charging 1 gas.

`PC` (0x58) instruction becomes invalid and its opcode is undefined.

*Note:* This change implies that JUMPDEST analysis is no longer required for EOF code.

### Execution

1. Execution starts at the first byte of the 0th code section, and `PC` is set to `0`.
2. Return stack is initialized empty.
3. Stack underflow check is not performed anymore. *Note:* EOF validation [EIP-5450](/EIPs/EIPS/eip-5450) guarantees that it cannot happen at run-time.
3. Stack overflow check is not performed anymore, except during `CALLF` as specified above.

## Rationale

### `RETF` in the top frame ends execution vs exceptionally halts vs is not allowed during validation

Alternative logic for `RETF` in the top frame could be to allow it during code validation and make it either:

- end execution if the return stack is emptied by the `RETF` or
- exceptionally halt if the return stack is empty before the `RETF`.

This has been superseded with the validation rule of top frame (0th code section) being non-returning (non-returning sections introduced in a separate EIP), because validating non-returning status of functions is valuable by itself for other reasons. Therefore all considerations of runtime behavior of `RETF` in the top frame were obsoleted.

### &quot;Minimal&quot; function type

Let&apos;s consider a trivial function with single instruction `RETF`.
Such function have the &quot;minimal&quot; type of `inputs = 0, outputs = 0`.
However, any other type like `inputs = k, outputs = k` is also valid for such function.
It has been considered to enforce usage of the &quot;minimal&quot; type for all functions.
This requires additional validation rule that checks if any instruction in the function accesses the bottom stack operand.
This rule can be obeyed by compilers, but causes quite significant annoyance.
On the other hand, it provides close to zero benefits for the EVM implementations.
In the end, it has been decided that this is not enforced.

### Code section limit and instruction size

The number of code sections is limited to 1024. This requires 2-byte immediate for `CALLF` and leaves room for increasing the limit in the future. The 256 limit (1-byte immediate) was discussed and concerns were raised that it might not be sufficient.

### `NOP` instruction

Instead of deprecating `JUMPDEST` we repurpose it as `NOP` instruction, because `JUMPDEST` effectively was a &quot;no-operation&quot; instruction and was already used as such in various contexts. It can be useful for some off-chain tooling, e.g. benchmarking EVM implementations (performance of `NOP` instruction is performance of EVM interpreter loop), as a padding to force code alignment, as a placeholder in dynamic code composition.

### Deprecating `JUMPDEST` analysis

The purpose of `JUMPDEST` analysis was to find in code the valid `JUMPDEST` bytes that do not happen to be inside `PUSH` immediate data. Only dynamic jump instructions (`JUMP`, `JUMPI`) required destination to be `JUMPDEST` instruction. Relative static jumps (`RJUMP`, `RJUMPI` and `RJUMPV`) do not have this requirement and are validated once at deploy-time during EOF instructions validation. Therefore, without dynamic jump instructions, `JUMPDEST` analysis is not required.

## Backwards Compatibility

This change poses no risk to backwards compatibility, as it is introduced only for EOF1 contracts, for which deploying undefined instructions is not allowed, therefore there are no existing contracts using these instructions. The new instructions are not introduced for legacy bytecode (code which is not EOF formatted).

The new execution state and multi-section control flow pose no risk to backwards compatibility, because it is a generalization of executing a single code section. Executing existing contracts (both legacy and EOF1) has no user-observable changes.

## Security Considerations

The gas cost of introduced instructions reflects the need to manipulate return stack entries and jumping to proper code section offset in memory when interpreting the bytecode.

These new instructions need to be carefully considered during implementation of the EOF container validation algorithm.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 10 Jan 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4750</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4750</guid>
      </item>
    
      <item>
        <title>Deactivate SELFDESTRUCT</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4758-deactivate-selfdestruct/8710</comments>
        
        <description>## Abstract

This EIP renames the `SELFDESTRUCT` opcode to `SENDALL`, and replaces its functionality. The new functionality will be only to send all Ether in the account to the caller.

## Motivation

The `SELFDESTRUCT` opcode requires large changes to the state of an account, in particular removing all code and storage. This will not be possible in the future with Verkle trees: Each account will be stored in many different account keys, which will not be obviously connected to the root account.

This EIP implements this change. Applications that only use `SELFDESTRUCT` to retrieve funds will still work.

## Specification

 * The `SELFDESTRUCT` opcode is renamed to `SENDALL`, and now only immediately moves all ETH in the account to the target; it no longer destroys code or storage or alters the nonce
 * All refunds related to `SELFDESTRUCT` are removed

## Rationale

Getting rid of the `SELFDESTRUCT` opcode has been considered in the past, and there are currently no strong reasons to use it. Disabling it will be a requirement for statelessness.

## Backwards Compatibility

This EIP requires a hard fork, since it modifies consensus rules.

Few applications are affected by this change. The only use that breaks is where a contract is re-created at the same address using `CREATE2` (after a `SELFDESTRUCT`).

## Security Considerations

The following applications of `SELFDESTRUCT` will be broken and applications that use it in this way are not safe anymore:

1. Any use where `SELFDESTRUCT` is used to burn non-ETH token balances, such as [EIP-20](/EIPs/EIPS/eip-20)), inside a contract. We do not know of any such use (since it can easily be done by sending to a burn address this seems an unlikely way to use `SELFDESTRUCT`)
2. Where `CREATE2` is used to redeploy a contract in the same place. There are two ways in which this can fail:
    * The destruction prevents the contract from being used outside of a certain context. For example, the contract allows anyone to withdraw funds, but `SELFDESTRUCT` is used at the end of an operation to prevent others from doing this. This type of operation can easily be modified to not depend on `SELFDESTRUCT`.
    * The `SELFDESTRUCT` operation is used in order to make a contract upgradable. This is not supported anymore and delegates should be used.


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 03 Feb 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4758</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4758</guid>
      </item>
    
      <item>
        <title>SELFDESTRUCT bomb</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4760-selfdestruct-bomb/8713</comments>
        
        <description>## Abstract

This EIP renames the `SELFDESTRUCT` opcode to `SENDALL`, and replaces its functionality. The new functionality will be only to send all Ether in the account to the caller.

In order to give apps more warning even if their developers are completely unaware of the EIP process, this version will exponentially increase the gas costs of the opcode, so any developer has time to see this change and react by implementing a version of their contract that does not rely on `SELFDESTRUCT` .

## Motivation

The `SELFDESTRUCT` opcode requires large changes to the state of an account, in particular removing all code and storage. This will not be possible in the future with Verkle trees: Each account will be stored in many different account keys, which will not be obviously connected to the root account.

This EIP implements this change. Applications that only use `SELFDESTRUCT` to retrieve funds will still work.

## Specification

### Constants

| Name | Value | Comment |
|------|-------|---------|
| `OLD_SELFDESTRUCT_COST` | 5000 | Current gas cost of `SELFDESTRUCT` opcode |
| `HARD_FORK_BLOCK` | TBD | (Shanghai HF block height) |
| `DOUBLING_SLOTS` | `2**16` | (Time for gas price to double, ca. 9 days) |
| `DOUBLINGS_BEFORE_SENDALL` | `13` | `SELFDESTRUCT` will be converted to `SENDALL` at `HARD_FORK_BLOCK + DOUBLING_SLOTS * DOUBLINGS_BEFORE_SENDALL` |

 * If `HARD_FORK_BLOCK &lt;= slot &lt; HARD_FORK_BLOCK + DOUBLING_SLOTS * DOUBLINGS_BEFORE_SENDALL`
     * `SELFDESTRUCT` functionality remains unchanged
     * `SELFDESTRUCT` gas cost is now `OLD_SELFDESTRUCT_COST * 2 ** ((slot - HARD_FORK_BLOCK) // DOUBLING_SLOTS)`
 * For `slot &gt;= HARD_FORK_BLOCK + DOUBLING_SLOTS * DOUBLINGS_BEFORE_SENDALL`
     * The cost reverts back to `OLD_SELFDESTRUCT_COST`
     * The `SELFDESTRUCT` opcode is renamed to `SENDALL`, and now only immediately moves all ETH in the account to the target; it no longer destroys code or storage or alters the nonce
     * All refunds related to `SELFDESTRUCT` are removed

## Rationale

The idea behind this EIP is to disable `SELFDESTRUCT` in a way that gives ample warning to Dapp developers. Many developers do not watch the EIP process closely and can therefore be caught by surprise when an opcode is deactivated and does not fulfill its original purpose anymore. However, at least if the smart contract has regular use, then users will notice the price of the operation going up tremendously. The period over which this is happening (`HARD_FORK_BLOCK + DOUBLING_SLOTS * DOUBLINGS_BEFORE_SENDALL`) is chosen to be long enough (ca. 4 months) such that it gives developers time to react to this change and prepare their application.

## Backward Compatibility

This EIP requires a hard fork, since it modifies consensus rules.

Few applications are affected by this change. The only use that breaks is where a contract is re-created at the same address using `CREATE2` (after a `SELFDESTRUCT`). The only application that is significantly affected (and where code can be analyzed) is able to switch to a different model, and should have ample time to do so.

## Security Considerations

The following applications of `SELFDESTRUCT` will be broken and applications that use it in this way are not safe anymore:

1. Any use where `SELFDESTRUCT` is used to burn non-ETH token balances, such as ERC20, inside a contract. We do not know of any such use (since it can easily be done by sending to a burn address this seems an unlikely way to use `SELFDESTRUCT`)
2. Where `CREATE2` is used to redeploy a contract in the same place. There are two ways in which this can fail:

    * The destruction prevents the contract from being used outside of a certain context. For example, the contract allows anyone to withdraw funds, but `SELFDESTRUCT` is used at the end of an operation to prevent others from doing this. This type of operation can easily be modified to not depend on `SELFDESTRUCT`.
    * The `SELFDESTRUCT` operation is used in order to make a contract upgradable. This is not supported anymore and delegates should be used.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 03 Feb 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4760</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4760</guid>
      </item>
    
      <item>
        <title>Statelessness gas cost changes</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4762-statelessness-gas-cost-changes/8714</comments>
        
        <description>## Abstract

This EIP introduces changes in the gas schedule to reflect the costs of creating a witness. It requires clients to update their database layout to match this, so as to avoid potential DoS attacks.

## Motivation

The introduction of Verkle trees into Ethereum requires fundamental changes and as a preparation, this EIP is targeting the fork coming right before the verkle tree fork, in order to incentivize Dapp developers to adopt the new storage model, and ample time to adjust to it. It also incentivizes client developers to migrate their database format ahead of the verkle fork.

## Specification

### Helper functions

```python
def get_storage_slot_tree_keys(storage_key: int) -&gt; [int, int]:
    if storage_key &lt; (CODE_OFFSET - HEADER_STORAGE_OFFSET):
        pos = HEADER_STORAGE_OFFSET + storage_key
    else:
        pos = MAIN_STORAGE_OFFSET + storage_key
    return (
        pos // 256,
        pos % 256
    )
```

### Access events

Whenever the state is read, one or more of the access events of the form `(address, sub_key, leaf_key)` take place, determining what data is being accessed. We define access events as follows:

#### Access events for account headers

When:

 1. a non-precompile which is also not a system contract is the target of a `*CALL`, `CALLCODE`, `SELFDESTRUCT`, `EXTCODESIZE`, or `EXTCODECOPY` opcode,
 2. a non-precompile which is also not a system contract is the target address of a contract creation whose initcode starts execution,
 3. any address is the target of the `BALANCE` opcode
 4. a _deployed_ contract calls `CODECOPY`

process this access event:

```
(address, 0, BASIC_DATA_LEAF_KEY)
```

Note: a non-value-bearing `SELFDESTRUCT`, `*CALL` or `CALLCODE`, targeting a precompile or a system contract, will not cause the `BASIC_DATA_LEAF_KEY` to be added to the witness.

If a `*CALL`, `CALLCODE` or `SELFDESTRUCT` is value-bearing (ie. it transfers nonzero wei), whether or not the `callee` is a precompile or a system contract, process this additional access event:

```
(caller, 0, BASIC_DATA_LEAF_KEY)
```

Note: when checking for the existence of the `callee`, the existence check is done by validating that there is an extension-and-suffix tree at the corresponding stem, and does not rely on `CODEHASH_LEAF_KEY`.

When calling `EXTCODEHASH`, process the access event:

```
(address, 0, CODEHASH_LEAF_KEY)
```

Note that precompiles and system contracts are excluded, as their hashes are known to the client.

When a contract is created, process these access events:

```
(contract_address, 0, BASIC_DATA_LEAF_KEY)
(contract_address, 0, CODEHASH_LEAF_KEY)
```

#### Access events for storage

`SLOAD` and `SSTORE` opcodes with a given address and key process an access event of the form

```
(address, tree_key, sub_key)
```

Where `tree_key` and `sub_key` are computed as `tree_key, sub_key = get_storage_slot_tree_keys(key)`

#### Access events for code

In the conditions below, “chunk `chunk_id` is accessed” is understood to mean an access event of the form

```
(address, (chunk_id + 128) // 256, (chunk_id + 128) % 256)
```

 * At each step of EVM execution, if and only if `PC &lt; len(code)`, chunk `PC // CHUNK_SIZE` (where `PC` is the current program counter) of the callee is accessed. In particular, note the following corner cases:
     * The destination of a `JUMP` (or positively evaluated `JUMPI`) is considered to be accessed, even if the destination is not a jumpdest or is inside pushdata
     * The destination of a `JUMPI` is not considered to be accessed if the jump conditional is `false`.
     * The destination of a jump is not considered to be accessed if the execution gets to the jump opcode but does not have enough gas to pay for the gas cost of executing the `JUMP` opcode (including chunk access cost if the `JUMP` is the first opcode in a not-yet-accessed chunk)
     * The destination of a jump is not considered to be accessed if it is beyond the code (`destination &gt;= len(code)`)
     * If code stops execution by walking past the end of the code, `PC = len(code)` is not considered to be accessed
 * If the current step of EVM execution is a `PUSH{n}`, all chunks `(PC // CHUNK_SIZE) &lt;= chunk_index &lt;= ((PC + n) // CHUNK_SIZE)` of the callee are accessed.
 * If a nonzero-read-size `CODECOPY` or `EXTCODECOPY` read bytes `x...y` inclusive, all chunks `(x // CHUNK_SIZE) &lt;= chunk_index &lt;= (min(y, code_size - 1) // CHUNK_SIZE)` of the accessed contract are accessed.
     * Example 1: for a `CODECOPY` with start position 100, read size 50, `code_size = 200`, `x = 100` and `y = 149`
     * Example 2: for a `CODECOPY` with start position 600, read size 0, no chunks are accessed
     * Example 3: for a `CODECOPY` with start position 1500, read size 2000, `code_size = 3100`, `x = 1500` and `y = 3099`
 * `CODESIZE`, `EXTCODESIZE` and `EXTCODEHASH` do NOT access any chunks.
    When a contract is created, access chunks `0 ... (len(code)+30)//31`

### Write Events

We define **write events** as follows. Note that when a write takes place, an access event also takes place (so the definition below should be a subset of the definition of access events). A write event is of the form `(address, sub_key, leaf_key)`, determining what data is being written to.

#### Write events for account headers

When a nonzero-balance-sending `CALL`, `CALLCODE` or `SELFDESTRUCT` with a given sender and recipient takes place, process these write events:

```
(caller, 0, BASIC_DATA_LEAF_KEY)
(callee, 0, BASIC_DATA_LEAF_KEY)
```

if no account exists at `callee_address`, also process:

```
(callee, 0, CODEHASH_LEAF_KEY)
```

When a contract creation is initialized, process these write events:

```
(contract_address, 0, BASIC_DATA_LEAF_KEY)
(contract_address, 0, CODEHASH_LEAF_KEY)
```

#### Write events for storage

`SSTORE` opcodes with a given `address` and `key` process a write event of the form

```
(address, tree_key, sub_key)
```

Where `tree_key` and `sub_key` are computed as `tree_key, sub_key = get_storage_slot_tree_keys(key)`

#### Write events for code

When a contract is created, process the write events:

```python
(
    address,
    (CODE_OFFSET + i) // VERKLE_NODE_WIDTH,
    (CODE_OFFSET + i) % VERKLE_NODE_WIDTH
)
```

For `i` in `0 ... (len(code)+30)//31`.

Note: since no access list existed for code up until this EIP, note that no warm costs are charged for code accesses.

### Transaction

#### Access events

For a transaction, make these access events:

```
(tx.origin, 0, BASIC_DATA_LEAF_KEY)
(tx.origin, 0, CODEHASH_LEAF_KEY)
(tx.target, 0, BASIC_DATA_LEAF_KEY)
(tx.target, 0, CODEHASH_LEAF_KEY)
```

#### Write events

```
(tx.origin, 0, BASIC_DATA_LEAF_KEY)
```

If `value` is non-zero:

```
(tx.target, 0, BASIC_DATA_LEAF_KEY)
```

### Witness gas costs

Remove the following gas costs:

 * Increased gas cost of `CALL` if it is nonzero-value-sending
 * [EIP-2200](/EIPs/EIPS/eip-2200) `SSTORE` gas costs except for the `SLOAD_GAS`
 * 200 per byte contract code cost
 * All `CALLCODE` costs related to nonzero-value-sending

Reduce gas cost:

 * `CREATE`/`CREATE2` to 1000

| Constant              | Value |
| --------------------- | ----- |
| `WITNESS_BRANCH_COST` | 1900  |
| `WITNESS_CHUNK_COST`  | 200   |
| `SUBTREE_EDIT_COST`   | 3000  |
| `CHUNK_EDIT_COST`     | 500   |
| `CHUNK_FILL_COST`     | 6200  |

When executing a transaction, maintain four sets:

 * `accessed_subtrees: Set[Tuple[address, int]]`
 * `accessed_leaves: Set[Tuple[address, int, int]]`
 * `edited_subtrees: Set[Tuple[address, int]]`
 * `edited_leaves: Set[Tuple[address, int, int]]`

When an **access** event of `(address, sub_key, leaf_key)` occurs, perform the following checks:

 * Perform the following steps unless event is a _Transaction access event_;
 * If `(address, sub_key)` is not in `accessed_subtrees`, charge `WITNESS_BRANCH_COST` gas and add that tuple to `accessed_subtrees`.
 * If `leaf_key` is not `None` and `(address, sub_key, leaf_key)` is not in `accessed_leaves`, charge `WITNESS_CHUNK_COST` gas and add it to `accessed_leaves`

When a **write** event of `(address, sub_key, leaf_key)` occurs, perform the following checks:

 * If event is _Transaction write event_, skip the following steps.
 * If `(address, sub_key)` is not in `edited_subtrees`, charge `SUBTREE_EDIT_COST` gas and add that tuple to `edited_subtrees`.
 * If `leaf_key` is not `None` and `(address, sub_key, leaf_key)` is not in `edited_leaves`, charge `CHUNK_EDIT_COST` gas and add it to `edited_leaves`
     * Additionally, if there was no value stored at `(address, sub_key, leaf_key)` (ie. the state held `None` at that position), charge `CHUNK_FILL_COST`

Note that tree keys can no longer be emptied: only the values `0...2**256-1` can be written to a tree key, and 0 is distinct from `None`. Once a tree key is changed from `None` to not-`None`, it can never go back to `None`.

Note that values should only be added to the witness if there is sufficient gas to cover their associated event costs. If there is not enough gas to cover the event costs, all the remaining gas should be consumed.

`CREATE*` and `*CALL` reserve 1/64th of the gas before the nested execution. In order to match the behavior of this charge with the pre-fork behavior of access lists: 

 * this minimum 1/64th gas reservation is checked **AFTER** charging the witness costs when performing a `CALL`, `CALLCODE`, `DELEGATECALL` or `STATICCALL`
 * this 1/64th of the gas is subtracted **BEFORE** charging the witness costs when performing a `CREATE` or `CREATE2`

### Block-level operations

None of:

* Precompile accounts, system contract accounts and slots of a system contract that are accessed during a system call,
* The coinbase account
* Withdrawal accounts

are warm at the start of a transaction.

### System contracts

When (and only when) calling a system contract either

 * _via a system call_ or
 * _to resolve a precompile/opcode_,

 the system contract&apos;s _code chunks_ and _account headers_ accesses should not appear in the witness as these should be known/cached in the clients. However any other accesses and all writes should appear in the witness.

Also corresponding witness costs need to be charged for _precompile/opcode resolution_ but are not charged in the _system call_.

### Account abstraction

TODO : still waiting on a final decision between 7702 and 3074

## Rationale

### Gas reform

Gas costs for reading storage and code are reformed to more closely reflect the gas costs under the new Verkle tree design. `WITNESS_CHUNK_COST` is set to charge 6.25 gas per byte for chunks, and `WITNESS_BRANCH_COST` is set to charge ~13,2 gas per byte for branches on average (assuming 144 byte branch length) and ~2.5 gas per byte in the worst case if an attacker fills the tree with keys deliberately computed to maximize proof length.

The main differences from gas costs in Berlin are:

 * 200 gas charged per 31 byte chunk of code. This has been estimated to increase average gas usage by ~6-12% (suggesting 10-20% gas usage increases at a 350 gas per chunk level).
 * Cost for accessing adjacent storage slots (`key1 // 256 == key2 // 256`) decreases from 2100 to 200 for all slots after the first in the group,
 * Cost for accessing storage slots 0…63 decreases from 2100 to 200, including the first storage slot. This is likely to significantly improve performance of many existing contracts, which use those storage slots for single persistent variables.

Gains from the latter two properties have not yet been analyzed, but are likely to significantly offset the losses from the first property. It’s likely that once compilers adapt to these rules, efficiency will increase further.

The precise specification of when access events take place, which makes up most of the complexity of the gas repricing, is necessary to clearly specify when data needs to be saved to the period 1 tree.

## Backwards Compatibility

This EIP requires a hard fork, since it modifies consensus rules.

The main backwards-compatibility-breaking change is the gas costs for code chunk access making some applications less economically viable. It can be mitigated by increasing the gas limit at the same time as implementing this EIP, reducing the risk that applications will no longer work at all due to transaction gas usage rising above the block gas limit. 

## Security Considerations

This EIP will mean that certain operations, mostly reading and writing several elements in the same suffix tree, become cheaper. If clients retain the same database structure as they have now, this would result in a DOS vector.

So some adaptation of the database is required in order to make this work:

 * In all possible futures, it is important to logically separate the commitment scheme from data storage. In particular, no traversal of the commitment scheme tree should be necessary to find any given state element
 * In order to make accesses to the same stem cheap as required for this EIP, the best way is probably to store each stem in the same location in the database. Basically the 256 leaves of 32 bytes each would be stored in an 8kB BLOB. The overhead of reading/writing this BLOB is small because most of the cost of disk access is seeking and not the amount transferred.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 03 Feb 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4762</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4762</guid>
      </item>
    
      <item>
        <title>Beacon block root in the EVM</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4788-beacon-root-in-evm/8281</comments>
        
        <description>## Abstract

Commit to the hash tree root of each beacon chain block in the corresponding execution payload header.

Store each of these roots in a smart contract.

## Motivation

Roots of the beacon chain blocks are cryptographic accumulators that allow proofs of arbitrary consensus state.
Exposing these roots inside the EVM allows for trust-minimized access to the consensus layer.
This functionality supports a wide variety of use cases that improve trust assumptions of staking pools,
restaking constructions, smart contract bridges, MEV mitigations and more.

## Specification

| constants                    | value                                        |
|---                           |---                                           |
| `FORK_TIMESTAMP`             | `1710338135`                                          |
| `HISTORY_BUFFER_LENGTH`      | `8191`                                       |
| `SYSTEM_ADDRESS`             | `0xfffffffffffffffffffffffffffffffffffffffe` |
| `BEACON_ROOTS_ADDRESS`       | `0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02` |

### Background

The high-level idea is that each execution block contains the parent beacon block&apos;s root. Even in the event of missed slots since the previous block root does not change,
we only need a constant amount of space to represent this &quot;oracle&quot; in each execution block. To improve the usability of this oracle, a small history of block roots
are stored in the contract.

To bound the amount of storage this construction consumes, a ring buffer is used that mirrors a block root accumulator on the consensus layer.

### Block structure and validity

Beginning at the execution timestamp `FORK_TIMESTAMP`, execution clients **MUST** extend the header schema with an additional field: the `parent_beacon_block_root`.
This root consumes 32 bytes and is exactly the [hash tree root](https://github.com/ethereum/consensus-specs/blob/fa09d896484bbe240334fa21ffaa454bafe5842e/ssz/simple-serialize.md#merkleization) of the parent beacon block for the given execution block.

The resulting RLP encoding of the header is therefore:

```python
rlp([
    parent_hash,
    0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347, # ommers hash
    coinbase,
    state_root,
    txs_root,
    receipts_root,
    logs_bloom,
    0, # difficulty
    number,
    gas_limit,
    gas_used,
    timestamp,
    extradata,
    prev_randao,
    0x0000000000000000, # nonce
    base_fee_per_gas,
    withdrawals_root,
    blob_gas_used,
    excess_blob_gas,
    parent_beacon_block_root,
])
```

Validity of the parent beacon block root is guaranteed from the consensus layer, much like how withdrawals are handled.

When verifying a block, execution clients **MUST** ensure the root value in the block header matches the one provided by the consensus client.

For a genesis block with no existing parent beacon block root the 32 zero bytes are used as a root placeholder.

#### Beacon roots contract

The beacon roots contract has two operations: `get` and `set`. The input itself is not used to determine which function to execute, for that the result of `caller` is used. If `caller` is equal to `SYSTEM_ADDRESS` then the operation to perform is `set`. Otherwise, `get`.

##### `get`

* Callers provide the `timestamp` they are querying encoded as 32 bytes in big-endian format.
* If the input is not exactly 32 bytes, the contract must revert.
* If the input is equal to 0, the contract must revert.
* Given `timestamp`, the contract computes the storage index in which the timestamp is stored by computing the modulo `timestamp % HISTORY_BUFFER_LENGTH` and reads the value.
* If the `timestamp` does not match, the contract must revert.
* Finally, the beacon root associated with the timestamp is returned to the user. It is stored at `timestamp % HISTORY_BUFFER_LENGTH + HISTORY_BUFFER_LENGTH`.

##### `set`

* Caller provides the parent beacon block root as calldata to the contract.
* Set the storage value at `header.timestamp % HISTORY_BUFFER_LENGTH` to be `header.timestamp`
* Set the storage value at `header.timestamp % HISTORY_BUFFER_LENGTH + HISTORY_BUFFER_LENGTH` to be `calldata[0:32]`

##### Pseudocode

```python
if evm.caller == SYSTEM_ADDRESS:
    set()
else:
    get()

def get():
    if len(evm.calldata) != 32:
        evm.revert()

    if to_uint256_be(evm.calldata) == 0:
        evm.revert()

    timestamp_idx = to_uint256_be(evm.calldata) % HISTORY_BUFFER_LENGTH
    timestamp = storage.get(timestamp_idx)

    if timestamp != evm.calldata:
        evm.revert()

    root_idx = timestamp_idx + HISTORY_BUFFER_LENGTH
    root = storage.get(root_idx)

    evm.return(root)

def set():
    timestamp_idx = to_uint256_be(evm.timestamp) % HISTORY_BUFFER_LENGTH
    root_idx = timestamp_idx + HISTORY_BUFFER_LENGTH

    storage.set(timestamp_idx, evm.timestamp)
    storage.set(root_idx, evm.calldata)
```

##### Bytecode

The exact contract bytecode is shared below.

```asm
caller
push20 0xfffffffffffffffffffffffffffffffffffffffe
eq
push1 0x4d
jumpi

push1 0x20
calldatasize
eq
push1 0x24
jumpi

push0
push0
revert

jumpdest
push0
calldataload
dup1
iszero
push1 0x49
jumpi

push3 0x001fff
dup2
mod
swap1
dup2
sload
eq
push1 0x3c
jumpi

push0
push0
revert

jumpdest
push3 0x001fff
add
sload
push0
mstore
push1 0x20
push0
return

jumpdest
push0
push0
revert

jumpdest
push3 0x001fff
timestamp
mod
timestamp
dup2
sstore
push0
calldataload
swap1
push3 0x001fff
add
sstore
stop
```

#### Deployment

The beacon roots contract is deployed like any other smart contract. A special synthetic address is generated
by working backwards from the desired deployment transaction:

```json
{
  &quot;type&quot;: &quot;0x0&quot;,
  &quot;nonce&quot;: &quot;0x0&quot;,
  &quot;to&quot;: null,
  &quot;gas&quot;: &quot;0x3d090&quot;,
  &quot;gasPrice&quot;: &quot;0xe8d4a51000&quot;,
  &quot;maxPriorityFeePerGas&quot;: null,
  &quot;maxFeePerGas&quot;: null,
  &quot;value&quot;: &quot;0x0&quot;,
  &quot;input&quot;: &quot;0x60618060095f395ff33373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500&quot;,
  &quot;v&quot;: &quot;0x1b&quot;,
  &quot;r&quot;: &quot;0x539&quot;,
  &quot;s&quot;: &quot;0x1b9b6eb1f0&quot;,
  &quot;hash&quot;: &quot;0xdf52c2d3bbe38820fff7b5eaab3db1b91f8e1412b56497d88388fb5d4ea1fde0&quot;
}
```

Note, the input in the transaction has a simple constructor prefixing the desired runtime code.

The sender of the transaction can be calculated as `0x0B799C86a49DEeb90402691F1041aa3AF2d3C875`. The address of the first contract deployed from the account is `rlp([sender, 0])` which equals `0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02`. This is how `BEACON_ROOTS_ADDRESS` is determined. Although this style of contract creation is not tied to any specific initcode like create2 is, the synthetic address is cryptographically bound to the input data of the transaction (e.g. the initcode).

### Block processing

At the start of processing any execution block where `block.timestamp &gt;= FORK_TIMESTAMP` (i.e. before processing any transactions), call `BEACON_ROOTS_ADDRESS` as `SYSTEM_ADDRESS` with the 32-byte input of `header.parent_beacon_block_root`, a gas limit of `30_000_000`, and `0` value. This will trigger the `set()` routine of the beacon roots contract. This is a system operation and therefore:

* the call must execute to completion
* the call does not count against the block&apos;s gas limit
* the call does not follow the [EIP-1559](/EIPs/EIPS/eip-1559) burn semantics - no value should be transferred as part of the call
* if no code exists at `BEACON_ROOTS_ADDRESS`, the call must fail silently

Clients may decide to omit an explicit EVM call and directly set the storage values. Note: While this is a valid optimization for Ethereum mainnet, it could be problematic on non-mainnet situations in case a different contract is used.

If this EIP is active in a genesis block, the genesis header&apos;s `parent_beacon_block_root` must be `0x0` and no system transaction may occur.

## Rationale

### Why not repurpose `BLOCKHASH`?

The `BLOCKHASH` opcode could be repurposed to provide the beacon root instead of some execution block hash.
To minimize code change, avoid breaking changes to smart contracts, and simplify deployment to mainnet, this EIP suggests leaving `BLOCKHASH` alone and adding new
functionality with the desired semantics.

### Beacon block root instead of state root

Block roots are preferred over state roots so there is a constant amount of work to do with each new execution block. Otherwise, skipped slots would require
a linear amount of work with each new payload. While skipped slots are quite rare on mainnet, it is best to not add additional load under what would already
be nonfavorable conditions.

Use of block root over state root does mean proofs will require a few additional nodes but this cost is negligible (and could be amortized across all consumers,
e.g. with a singleton state root contract that caches the proof per slot).

### Why two ring buffers?

The first ring buffer only tracks `HISTORY_BUFFER_LENGTH` worth of roots and so for all possible timestamp values would consume a constant amount of storage.
However, this design opens the contract to an attack where a skipped slot that has the same value modulo the ring buffer length would return an old root value,
rather than the most recent one.

To nullify this attack while retaining a fixed memory footprint, this EIP keeps track of the pair of data `(parent_beacon_block_root, timestamp)` for each index into the
ring buffer and verifies the timestamp matches the one originally used to write the root data when being read. Given the fixed size of storage slots (only 32 bytes), the requirement
to store a pair of values necessitates two ring buffers, rather than just one.

### Size of ring buffers

The ring buffer data structures are sized to hold 8191 roots from the consensus layer. Using a prime number as the ring buffer size ensures that no value is overwritten until the entire ring buffer has been saturated and thereafter, each value will be updated once per iteration. This also means that even if the slot times were to change, we would continue to use at most 8191 storage slots.

Given the current mainnet values, 8191 roots provides about a day of coverage. This gives users plenty of time to make a transaction with a verification against a specific root and get the transaction included on-chain.

## Backwards Compatibility

No issues.

## Test Cases

N/A

## Reference Implementation

N/A

## Security Considerations

N/A

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 10 Feb 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4788</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4788</guid>
      </item>
    
      <item>
        <title>Non-Fungible Token Ownership Designation Standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-4799-non-fungible-token-wrapping-standard/8396</comments>
        
        <description>## Abstract

The following defines a standard interface for designating ownership of an NFT to someone while the NFT is held in escrow by a smart contract. The standard allows for the construction of a directed acyclic graph of NFTs, where the designated owner of every NFT in a given chain is the terminal address of that chain. This enables the introduction of additional functionality to pre-existing NFTs, without having to give up the authenticity of the original. In effect, this means that all NFTs are composable and can be rented, used as collateral, fractionalized, and more. 

## Motivation

Many NFTs aim to provide their holders with some utility - utility that can come in many forms. This can be the right to inhabit an apartment, access to tickets to an event, an airdrop of tokens, or one of the infinitely many other potential applications. However, in their current form, NFTs are limited by the fact that the only verifiable wallet associated with an NFT is the owner, so clients that want to distribute utility are forced to do so to an NFT&apos;s listed owner. This means that any complex ownership agreements must be encoded into the original NFT contract - there is no mechanism by which an owner can link the authenticity of their original NFT to any external contract.

The goal of this standard is to allow users and developers the ability to define arbitrarily complex ownership agreements on NFTs that have already been minted. This way, new contracts with innovative ownership structures can be deployed, but they can still leverage the authenticity afforded by established NFT contracts - in the past a wrapping contract meant brand new NFTs with no established authenticity.

Prior to this standard, wrapping an NFT inside another contract was the only way to add functionality after the NFT contract had been deployed, but this meant losing access to the utility of holding the original NFT. Any application querying for the owner of that NFT would determine the wrapping smart contract to be the owner. Using this standard, applications will have a standardized method of interacting with wrapping contracts so that they can continue to direct their utility to users even when the NFT has been wrapped.

## Specification

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.

```solidity
import &quot;@openzeppelin/contracts/utils/introspection/IERC165.sol&quot;;

interface IERC4799NFT is IERC165 {
    /// @dev This emits when ownership of any NFT changes by any mechanism.
    ///  This event emits when NFTs are created (`from` == 0) and destroyed
    ///  (`to` == 0). Exception: during contract creation, any number of NFTs
    ///  may be created and assigned without emitting Transfer. At the time of
    ///  any transfer, the approved address for that NFT (if any) is reset to none.
    event Transfer(
        address indexed from,
        address indexed to,
        uint256 indexed tokenId
    );

    /// @notice Find the owner of an NFT
    /// @dev NFTs assigned to zero address are considered invalid, and queries
    ///  about them throw
    /// @param tokenId The identifier for an NFT
    /// @return The address of the owner of the NFT
    function ownerOf(uint256 tokenId) external view returns (address);
}
```
```solidity
/// @title ERC-4799 Non-Fungible Token Ownership Designation Standard
/// @dev See https://eips.ethereum.org/EIPS/eip-4799
/// Note: the ERC-165 identifier for this interface is [TODO].

import &quot;@openzeppelin/contracts/utils/introspection/IERC165.sol&quot;;
import &quot;./IERC4799NFT.sol&quot;;

interface IERC4799 is IERC165 {
    /// @dev Emitted when a source token designates its ownership to the owner of the target token
    event OwnershipDesignation(
        IERC4799NFT indexed sourceContract,
        uint256 sourceTokenId,
        IERC4799NFT indexed targetContract,
        uint256 targetTokenId
    );

    /// @notice Find the designated NFT
    /// @param sourceContract The contract address of the source NFT
    /// @param sourceTokenId The tokenId of the source NFT
    /// @return (targetContract, targetTokenId) contract address and tokenId of the parent NFT
    function designatedTokenOf(IERC4799NFT sourceContract, uint256 sourceTokenId)
        external
        view
        returns (IERC4799NFT, uint256);
}
```

The authenticity of designated ownership of an NFT is conferred by the designating ERC-4799 contract’s ownership of the original NFT according to the source contract. This MUST be verified by clients by querying the source contract.

Clients respecting this specification SHALL NOT distribute any utility to the address of the ERC-4799 contract. Instead, they MUST distribute it to the owner of the designated token that the ERC-4799 contract points them to.

## Rationale

To maximize the future compatibility of the wrapping contract, we first defined a canonical NFT interface. We created `IERC4799NFT`, an interface implicitly implemented by virtually all popular NFT contracts, including all deployed contracts that are [ERC-721](/EIPs/EIPS/eip-721) compliant. This interface represents the essence of an NFT: a mapping from a token identifier to the address of a singular owner, represented by the function `ownerOf`.

The core of our proposal is the `IERC4799` interface, an interface for a standard NFT ownership designation contract (ODC). ERC4799 requires the implementation of a `designatedTokenOf` function, which maps a source NFT to exactly one target NFT. Through this function, the ODC expresses its belief of designated ownership. This designated ownership is only authentic if the ODC is listed as the owner of the original NFT, thus maintaining the invariant that every NFT has exactly one designated owner.

## Backwards Compatibility

The `IERC4799NFT` interface is backwards compatible with `IERC721`, as `IERC721` implicitly extends `IERC4799NFT`. This means that the ERC-4799 standard, which wraps NFTs that implement `ERC4799NFT`, is fully backwards compatible with ERC-721.

## Reference Implementation

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity &gt;=0.8.0 &lt;0.9.0;

import &quot;./IERC4799.sol&quot;;
import &quot;./IERC4799NFT.sol&quot;;
import &quot;./ERC721.sol&quot;;
import &quot;@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol&quot;;

contract ERC721Composable is IERC4799, IERC721Receiver {
    mapping(IERC4799NFT =&gt; mapping(uint256 =&gt; IERC4799NFT)) private _targetContracts;
    mapping(IERC4799NFT =&gt; mapping(uint256 =&gt; uint256)) private _targetTokenIds;

    function designatedTokenOf(IERC4799NFT sourceContract, uint256 sourceTokenId)
        external
        view
        override
        returns (IERC4799NFT, uint256)
    {
        return (
            IERC4799NFT(_targetContracts[sourceContract][sourceTokenId]),
            _targetTokenIds[sourceContract][sourceTokenId]
        );
    }

    function designateToken(
        IERC4799NFT sourceContract,
        uint256 sourceTokenId,
        IERC4799NFT targetContract,
        uint256 targetTokenId
    ) external {
        require(
            ERC721(address(sourceContract)).ownerOf(sourceTokenId) == msg.sender ||
            ERC721(address(sourceContract)).getApproved(sourceTokenId) == msg.sender, 
            &quot;ERC721Composable: Only owner or approved address can set a designate ownership&quot;);
        _targetContracts[sourceContract][sourceTokenId] = targetContract;
        _targetTokenIds[sourceContract][sourceTokenId] = targetTokenId;
        emit OwnershipDesignation(
            sourceContract, 
            sourceTokenId,  
            targetContract,
            targetTokenId
        );
    }

    function onERC721Received(
        address,
        address from,
        uint256 sourceTokenId,
        bytes calldata
    ) external override returns (bytes4) {
        ERC721(msg.sender).approve(from, sourceTokenId);
        return IERC721Receiver.onERC721Received.selector;
    }

        function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override
        returns (bool)
    {
        return
            (interfaceId == type(IERC4799).interfaceId ||
            interfaceId == type(IERC721Receiver).interfaceId);
    }
}
```
```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity &gt;=0.8.0 &lt;0.9.0;

import &quot;./IERC4799.sol&quot;;
import &quot;./IERC4799NFT.sol&quot;;
import &quot;@openzeppelin/contracts/utils/introspection/ERC165Checker.sol&quot;;

contract DesignatedOwner {
    function designatedOwnerOf(
        IERC4799NFT tokenContract,
        uint256 tokenId,
        uint256 maxDepth
    ) public view returns (address owner) {
        owner = tokenContract.ownerOf(tokenId);
        if (ERC165Checker.supportsInterface(owner, type(IERC4799).interfaceId)) {
            require(maxDepth &gt; 0, &quot;designatedOwnerOf: depth limit exceeded&quot;);
            (tokenContract, tokenId) = IERC4799(owner).designatedTokenOf(
                tokenContract,
                tokenId
            );
            return designatedOwnerOf(tokenContract, tokenId, maxDepth - 1);
        }
    }
}
```

## Security Considerations

### Long/Cyclical Chains of Ownership

The primary security concern is that of malicious actors creating excessively long or cyclical chains of ownership, leading applications that attempt to query for the designated owner of a given token to run out of gas and be unable to function. To address this, clients are expected to always query considering a `maxDepth` parameter, cutting off computation after a certain number of chain traversals.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 13 Feb 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4799</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4799</guid>
      </item>
    
      <item>
        <title>Limit transaction gas to a maximum of 2^63-1</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4803-limit-transaction-gas-to-a-maximum-of-2-63-1/8296</comments>
        
        <description>## Abstract

Limit transaction gas to be between `0` and `2^63-1`.

## Motivation

The gas limit field in the transaction is specified to be an arbitrary long unsigned integer, but various clients put limits on this value. This EIP brings a reasonable limit into consensus.

## Specification

Introduce one new restriction retroactively from genesis: any transaction is invalid and not includeable in a block, where the gas limit exceeds `2^63-1`.

## Rationale

### `2^63-1` vs `2^64-1`

`2^63-1` is chosen because it allows representing the gas value as a signed integer, and so the out of gas check can be done as a simple &quot;less than zero&quot; check after subtraction.

### Consider `2^31-1`

An alternative is considering a lower limit, because this can be handled easily in Javascript, since it handles numbers as floating point (the actual upper bound is `2^53-1`).

### Current limit

Due to the nature of RLP encoding, there is no fixed upper bound for the value, but most implementations limit it to 256-bits. Furthermore, most client implementations (such as geth) internally handle gas as a 64-bit value.

## Backwards Compatibility

While this is a breaking change, no actual effect should be visible.

Before [EIP-1559](/EIPs/EIPS/eip-1559) it was possible to include transactions with `gasPrice = 0` and thus the `gasLimit * gasPrice &lt;= accountBalance` calculation could have allowed for arbitrarily large values of `gasLimit`. However, the rule that the transaction list cannot exceed the block gas limit, and the strict rules about how the block gas limit can change, prevented arbitrarily large values of `gasLimit` to be in the historical state.

## Security Considerations

None.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 02 Feb 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4803</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4803</guid>
      </item>
    
      <item>
        <title>Web3 URL to EVM Call Message Translation</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4804-web3-url-to-evm-call-message-translation/8300</comments>
        
        <description>## Abstract

This standard translates an RFC 2396 URI like `web3://uniswap.eth/` to an EVM message such as:

```
EVMMessage {
   To: 0xaabbccddee.... // where uniswap.eth&apos;s address registered at ENS
   Calldata: 0x
   ...
}
```

## Motivation

Currently, reading data from Web3 generally relies on a translation done by a Web2 proxy to Web3 blockchain. The translation is mostly done by the proxies such as dApp websites/node service provider/etherscan, which are out of the control of users. The standard here aims to provide a simple way for Web2 users to directly access the content of Web3, especially on-chain Web contents such as SVG/HTML.  Moreover, this standard enables interoperability with other standards already compatible with URIs, like SVG/HTML.

## Specification

This specification only defines read-only (i.e. Solidity&apos;s `view` functions) semantics. State modifying functions may be defined as a future extension.

A Web3 URL is in the following form

```
web3URL = web3Schema [userinfo &quot;@&quot;] contractName [&quot;:&quot; chainid] path [&quot;?&quot; query]
web3Schema = [ &quot;ethereum-web3://&quot; | &quot;eth-web3://&quot; | &quot;web3://&quot; ]
contractName = address | [name &quot;.&quot; [ subDomain0 &quot;.&quot; ... ]] nsProviderSuffix
path = [&quot;/&quot; method [&quot;/&quot; argument_0 [&quot;/&quot; argument_1 ... ]]]
argument = [type &quot;!&quot;] value
query = &quot;attribute_1=value_1 [ &quot;&amp;&quot; attribute_2=value_2 ... ]
attribute = &quot;returns&quot; | &quot;returnTypes&quot; | other_attribute
```

where

- **web3Schema** indicates the schema of the URL, which is `web3://` or `w3://` for short.
- **userinfo** indicates which user is calling the EVM, i.e., &quot;From&quot; field in EVM call message. If not specified, the protocol will use 0x0 as the sender address.
- **contractName** indicates the contract to be called, i.e., &quot;To&quot; field in the EVM call message. If the **contractName** is an **address**, i.e., 0x + 20-byte-data hex, then &quot;To&quot; will be the address. Otherwise, the name is from a name service. In the second case, **nsProviderSuffix** will be the suffix from name service providers such as &quot;eth&quot;, etc. The way to translate the name from a name service to an address will be discussed in later EIPs.
- **chainid** indicates which chain to resolve **contractName** and call the message. If not specified, the protocol will use the same chain as the name service provider, e.g., 1 for eth. If no name service provider is available, the default chainid is 1.
- **query** is an optional component containing a sequence of attribute-value pairs separated by &quot;&amp;&quot;.

### Resolve Mode

Once the &quot;To&quot; address and chainid are determined, the protocol will check the resolver mode of contract by calling &quot;resolveMode&quot; method. The protocol currently supports two resolve modes:

#### Manual Mode

The manual mode will not do any interpretation of **path** and **query**, and put **path** [ &quot;?&quot; **query** ] as the calldata of the message directly.

#### Auto Mode

The auto mode is the default mode to resolve (also applies when the &quot;resolveMode&quot; method is unavailable in the target contract). In the auto mode, if **path** is empty, then the protocol will call the target contract with empty calldata. Otherwise, the calldata of the EVM message will use standard Solidity contract ABI, where

- **method** is a string of function method be called
- **argument_i** is the ith argument of the method. If **type** is specified, the value will be translated to the corresponding type. The protocol currently supports the basic types such as uint256, bytes32, address, bytes, and string. If **type** is not specified, then the type will be automatically detected using the following rule in a sequential way:

1. **type**=&quot;uint256&quot;, if **value** is numeric; or
2. **type**=&quot;bytes32&quot;, if **value** is in the form of 0x+32-byte-data hex; or
3. **type**=&quot;address&quot;, if **value** is in the form of 0x+20-byte-data hex; or
4. **type**=&quot;bytes&quot;, if **value** is in the form of 0x followed by any number of bytes besides 20 or 32; or
5. else **type**=&quot;address&quot; and parse the argument as a domain name in the form of `[name &quot;.&quot; [ subDomain0 &quot;.&quot; ... ]] nsProviderSuffix`. In this case, the actual value of the argument will be obtained from **nsProviderSuffix**, e.g., eth.  If **nsProviderSuffix** is not supported, an unsupported NS provider error will be returned. 

Note that if **method** does not exist, i.e., **path** is empty or &quot;/&quot;, then the contract will be called with empty calldata.

- **returns** attribute in **query** tells the format of the returned data. If not specified, the returned message data will be parsed in &quot;(bytes32)&quot; and MIME will be set based on the suffix of the last argument. If **returns** is &quot;()&quot;, the returned data will be parsed in raw bytes in JSON.  Otherwise, the returned message will be parsed in the specified **returns** attribute in JSON.  If multiple **returns** attributes are present, the value of the last **returns** attribute will be applied. Note that **returnTypes** is the alias of **returns**, but it is not recommended to use and is mainly for backward-compatible purpose.

### Examples

#### Example 1

```
web3://w3url.eth/
```

The protocol will find the address of **w3url.eth** from ENS in chainid 1 (Mainnet), and then the protocol will call the address with &quot;From&quot; = &quot;0x...&quot; and &quot;Calldata&quot; = &quot;0x2F&quot;.

#### Example 2

```
web3://cyberbrokers-meta.eth/renderBroker/9999
```

The protocol will find the address of **cyberbrokers-meta.eth** from ENS on chainid 1 (Mainnet), and then call the address with &quot;To&quot; = &quot;0x...&quot; and &quot;Calldata&quot; = &quot;0x&quot; + `keccak(&quot;view(uint256)&quot;)[0:4] + abi.encode(uint256(9999))`.

#### Example 3

```
web3://vitalikblog.eth:5/
```

The protocol will find the address of **vitalikblog.eth** from ENS on chainid 5 (Goerli), and then call the address with &quot;From&quot; = &quot;0x...&quot; and &quot;Calldata&quot; = &quot;0x2F&quot; with chainid = 5.

#### Example 4

```
web3://0xe4ba0e245436b737468c206ab5c8f4950597ab7f:42170/
```

The protocol will call the address with &quot;To&quot; = &quot;0x9e081Df45E0D167636DB9C61C7ce719A58d82E3b&quot; and &quot;Calldata&quot; = &quot;0x&quot; with chainid = 42170 (Arbitrum Nova).

#### Example 5

```
web3://0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/balanceOf/vitalik.eth?returns=(uint256)
```

The protocol will find the addresses of **vitalik.eth** from ENS on chainid 1 (Mainnet) and then call the method &quot;balanceOf(address)&quot; of the contract with the **charles.eth**&apos;s address. The returned data will be parsed as uint256 like `[ &quot;10000000000000&quot; ]`.

#### Example 6

```
web3://0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/balanceOf/vitalik.eth?returns=()
```

The protocol will find the address of **vitalik.eth** from ENS on chainid 1 (Mainnet) and then call the method &quot;balanceOf(address)&quot; of the address. The returned data will be parsed as raw bytes like `[&quot;0x000000000000000000000000000000000000000000000000000009184e72a000&quot;]`.

## Rationale

The purpose of the proposal is to add a decentralized presentation layer for Ethereum.  With the layer, we are able to render any web content (including HTML/CSS/JPG/PNG/SVG, etc) on-chain using human-readable URLs, and thus EVM can be served as decentralized Backend.  The design of the standard is based on the following principles:

- **Human-readable**.  The Web3 URL should be easily recognized by human similar to Web2 URL (`http://`).  As a result, we support names from name services to replace address for better readability.  In addition, instead of using calldata in hex, we use human-readable method + arguments and translate them to calldata for better readability.

- **Maximum-Compatible with HTTP-URL standard**.  The Web3 URL should be compatible with HTTP-URL standard including relative pathing, query, fragment, etc so that the support of existing HTTP-URL (e.g., by browser) can be easily extended to Web3 URL with minimal modification.  This also means that existing Web2 users can easily migrate to Web3 with minimal extra knowledge of this standard.

- **Simple**.  Instead of providing explicit types in arguments, we use a &quot;maximum likelihood&quot; principle of auto-detecting the types of the arguments such as address, bytes32, and uint256.  This could greatly minimize the length of URL, while avoiding confusion.  In addition, explicit types are also supported to clear the confusion if necessary.

- **Flexible**.  The contract is able to override the encoding rule so that the contract has fine-control of understanding the actual Web resources that the users want to locate.

## Security Considerations

No security considerations were found.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 14 Feb 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4804</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4804</guid>
      </item>
    
      <item>
        <title>Common Interfaces for DAOs</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4824-decentralized-autonomous-organizations/8362</comments>
        
        <description>## Abstract

An API standard for decentralized autonomous organizations (DAOs), focused on relating on-chain and off-chain representations of membership and proposals.

## Motivation

DAOs, since being invoked in the Ethereum whitepaper, have been vaguely defined. This has led to a wide range of patterns but little standardization or interoperability between the frameworks and tools that have emerged. Standardization and interoperability are necessary to support a variety of use-cases. In particular, a standard daoURI, similar to tokenURI in [ERC-721](./eip-721), will enhance DAO discoverability, legibility, proposal simulation, and interoperability between tools. More consistent data across the ecosystem is also a prerequisite for future DAO standards.

## Specification

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.

Every contract implementing this EIP MUST implement the `IERC4824` interface below:

```solidity
pragma solidity ^0.8.1;

/// @title ERC-4824 DAOs
/// @dev See &lt;https://eips.ethereum.org/EIPS/eip-4824&gt;
interface IERC4824 {
    event DAOURIUpdate(address daoAddress, string daoURI);

    /// @notice A distinct Uniform Resource Identifier (URI) pointing to a JSON object following the &quot;ERC-4824 DAO JSON-LD Schema&quot;. This JSON file splits into four subsidiary URIs: membersURI, proposalsURI, activityLogURI, and governanceURI. The membersURI SHOULD point to a JSON file that conforms to the &quot;ERC-4824 Members JSON-LD Schema&quot;. The proposalsURI SHOULD point to a JSON file that conforms to the &quot;ERC-4824 Proposals JSON-LD Schema&quot;. The activityLogURI SHOULD point to a JSON file that conforms to the &quot;ERC-4824 Activity Log JSON-LD Schema&quot;. The governanceURI SHOULD point to a flatfile, normatively a .md file. Each of the JSON files named above MAY be statically-hosted or dynamically-generated. The content of subsidiary JSON files MAY be directly embedded as a JSON object directly within the top-level DAO JSON, in which case the relevant field MUST be renamed to remove the &quot;URI&quot; suffix. For example, &quot;membersURI&quot; would be renamed to &quot;members&quot;, &quot;proposalsURI&quot; would be renamed to &quot;proposals&quot;, and so on.
    function daoURI() external view returns (string memory _daoURI);
}
```

The DAO JSON-LD Schema mentioned above:

```json
{
    &quot;@context&quot;: &quot;http://www.daostar.org/schemas&quot;,
    &quot;type&quot;: &quot;DAO&quot;,
    &quot;name&quot;: &quot;&lt;name of the DAO&gt;&quot;,
    &quot;description&quot;: &quot;&lt;description&gt;&quot;,
    &quot;membersURI&quot;: &quot;&lt;URI&gt;&quot;,
    &quot;proposalsURI&quot;: &quot;&lt;URI&gt;&quot;,
    &quot;activityLogURI&quot;: &quot;&lt;URI&gt;&quot;,
    &quot;governanceURI&quot;: &quot;&lt;URI&gt;&quot;,
    &quot;contractsURI&quot;: &quot;&lt;URI&gt;&quot;
}
```

A DAO MAY inherit the `IERC4824` interface above or it MAY create an external registration contract that is compliant with this EIP. Whether the DAO inherits the above interface or it uses an external registration contract, the DAO SHOULD define a method for and implement some access control logic to enable efficient updating for daoURI. If a DAO creates an external registration contract, the registration contract MUST store the DAO’s primary address, typically the address of the primary governance contract. See the reference implementation of external registration contract in the attached assets folder to this EIP.

When reporting information in the DAO JSON-LD Schema, if a given field has no value (for example, `description`), it SHOULD be removed rather than left with an empty or `null` value.

### Indexing

If a DAO inherits the `IERC4824` interface from a 4824-compliant DAO factory, then the DAO factory SHOULD incorporate a call to an indexer contract as part of the DAO&apos;s initialization to enable efficient network indexing. If the DAO is [ERC-165](./eip-165)-compliant, the factory can do this without additional permissions. If the DAO is _not_ compliant with ERC-165, the factory SHOULD first obtain access control rights to the indexer contract and then call `logRegistration` directly with the address of the new DAO and the daoURI of the new DAO. Note that any user, including the DAO itself, MAY call `logRegistration` and submit a registration for a DAO which inherits the `IERC4824` interface and which is also ERC-165-compliant.

```solidity
pragma solidity ^0.8.1;

error ERC4824InterfaceNotSupported();

contract ERC4824Index is AccessControl {
    using ERC165Checker for address;

    bytes32 public constant REGISTRATION_ROLE = keccak256(&quot;REGISTRATION_ROLE&quot;);

    event DAOURIRegistered(address daoAddress);

    constructor() {
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _grantRole(REGISTRATION_ROLE, msg.sender);
    }

    function logRegistrationPermissioned(
        address daoAddress
    ) external onlyRole(REGISTRATION_ROLE) {
        emit DAOURIRegistered(daoAddress);
    }

    function logRegistration(address daoAddress) external {
        if (!daoAddress.supportsInterface(type(IERC4824).interfaceId))
            revert ERC4824InterfaceNotSupported();
        emit DAOURIRegistered(daoAddress);
    }
}
```

If a DAO uses an external registration contract, the DAO SHOULD use a common registration factory contract linked to a common indexer to enable efficient network indexing. See the reference implementation of the factory contract in the attached assets folder to this EIP.

#### Indexing priority
daoURIs may be published directly in the DAO&apos;s contract or through a call to a common registration factory contract. In cases where both occur, the daoURI (and all sub-URIs) published through a call to a registration factory contract SHOULD take precedence. If there are multiple registrations, the most recent registration SHOULD take precedence.

### Members

Members JSON-LD Schema. Every contract implementing this EIP SHOULD implement a membersURI pointing to a JSON object satisfying this schema. Below, DID refers to [Decentralized Identifiers](https://www.w3.org/TR/2022/REC-did-core-20220719/).

```json
{
    &quot;@context&quot;: &quot;https://www.daostar.org/schemas&quot;,
    &quot;type&quot;: &quot;DAO&quot;,
    &quot;members&quot;: [
        {
            &quot;id&quot;: &quot;&lt;CAIP-10 address, DID address, or other URI identifier&gt;&quot;
        },
        {
            &quot;id&quot;: &quot;&lt;CAIP-10 address, DID address, or other URI identifier&gt;&quot;
        }
    ]
}
```

For example, for an address on Ethereum Mainnet, the [CAIP-10](https://github.com/ChainAgnostic/CAIPs/blob/ad0cfebc45a4b8368628340bf22aefb2a5edcab7/CAIPs/caip-10.md) address would be of the form `eip155:1:0x1234abcd`, while the DID address would be of the form `did:ethr:0x1234abcd`.

### Proposals

Proposals JSON-LD Schema. Every contract implementing this EIP SHOULD implement a proposalsURI pointing to a JSON object satisfying this schema.

In particular, any on-chain proposal MUST be associated to an id of the form CAIP10_ADDRESS + “?proposalId=” + PROPOSAL_COUNTER, where CAIP10_ADDRESS is an address following the CAIP-10 standard and PROPOSAL_COUNTER is an arbitrary identifier such as a uint256 counter or a hash that is locally unique per CAIP-10 address. Off-chain proposals MAY use a similar id format where CAIP10_ADDRESS is replaced with an appropriate URI or URL.

```json
{
    &quot;@context&quot;: &quot;https://www.daostar.org/schemas&quot;,
    &quot;proposals&quot;: [
        {
            &quot;type&quot;: &quot;proposal&quot;,
            &quot;id&quot;: &quot;&lt;proposal ID&gt;&quot;,
            &quot;name&quot;: &quot;&lt;name or title of proposal&gt;&quot;,
            &quot;contentURI&quot;: &quot;&lt;URI to content/text of the proposal&gt;&quot;,
            &quot;discussionURI&quot;: &quot;&lt;URI to discussion or thread for the proposal&gt;&quot;,
            &quot;status&quot;: &quot;&lt;status of proposal&gt;&quot;,
            &quot;calls&quot;: [
                {
                    &quot;type&quot;: &quot;CallDataEVM&quot;,
                    &quot;operation&quot;: &quot;&lt;call or delegate call&gt;&quot;,
                    &quot;from&quot;: &quot;&lt;EthereumAddress&gt;&quot;,
                    &quot;to&quot;: &quot;&lt;EthereumAddress&gt;&quot;,
                    &quot;value&quot;: &quot;&lt;value&gt;&quot;,
                    &quot;data&quot;: &quot;&lt;call data&gt;&quot;
                }
            ]
        }
    ]
}
```

When deferenced, contentURI should return the content (i.e. the text) of the proposal. Similarly, discussionURI should return a discussion link, whether a forum post, Discord channel, or Twitter thread.

### Activity Log

Activity Log JSON-LD Schema. Every contract implementing this EIP SHOULD implement a activityLogURI pointing to a JSON object satisfying this schema.

```json
{
    &quot;@context&quot;: &quot;https://www.daostar.org/schemas&quot;,
    &quot;activities&quot;: [
        {
            &quot;id&quot;: &quot;&lt;activity ID&gt;&quot;,
            &quot;type&quot;: &quot;activity&quot;,
            &quot;proposal&quot;: {
                &quot;type&quot;: &quot;proposal&quot;
                &quot;id&quot;: &quot;&lt;proposal ID&gt;&quot;,
            },
            &quot;member&quot;: {
                &quot;id&quot;: &quot;&lt;CAIP-10 address, DID address, or other URI identifier&gt;&quot;
            }
        } 
    ]
}
```

### Contracts

Contracts JSON-LD Schema. Every contract implementing this EIP SHOULD implement a contractsURI pointing to a JSON object satisfying this schema.

contractsURI is especially important for DAOs with distinct or decentralized governance occurring across multiple different contracts, possibly across several chains. Multiple addresses may report the same daoURI.

To prevent spam or spoofing, all DAOs adopting this specification SHOULD publish through contractsURI the address of every contract associated to the DAO, including but not limited to those that inherit the `IERC4824` interface or those that interact with a registration factory contract. Note that this includes the contract address(es) of any actual registration contracts deployed through a registration factory.

```json
{
    &quot;@context&quot;: &quot;https://www.daostar.org/schemas&quot;,
    &quot;contracts&quot;: [
        {
            &quot;id&quot;: &quot;&lt;CAIP-10 address, DID address, or other URI identifier&gt;&quot;
            &quot;name&quot;: &quot;&lt;name, e.g. Treasury&gt;&quot;,
            &quot;description&quot;: &quot;&lt;description, e.g. Primary operating treasury for the DAO&gt;&quot;
        },
        {
            &quot;id&quot;: &quot;&lt;CAIP-10 address, DID address, or other URI identifier&gt;&quot;
            &quot;name&quot;: &quot;&lt;name, e.g. Governance Token&gt;&quot;,
            &quot;description&quot;: &quot;&lt;description, e.g. ERC20 governance token contract&gt;&quot;
        },
        {
            &quot;id&quot;: &quot;&lt;CAIP-10 address, DID address, or other URI identifier&gt;&quot;
            &quot;name&quot;: &quot;&lt;name, e.g. Registration Contract&gt;&quot;,
            &quot;description&quot;: &quot;&lt;description, e.g. ERC-4824 registration contract&gt;&quot;
        }
    ]
}
```

### URI fields
The content of subsidiary JSON files MAY be directly embedded as a JSON object directly within the top-level DAO JSON, in which case the relevant field MUST be renamed to remove the &quot;URI&quot; suffix. For example, `membersURI` would be renamed to `members`, `proposalsURI` would be renamed to `proposals`, and so on. In all cases, the embedded JSON object MUST conform to the relevant schema. A given field and a URI-suffixed field (e.g. `membersURI` and `members`) SHOULD NOT appear in the same JSON-LD; if they do, the field without the URI suffix MUST take precedence.

Fields which are not appended with URI MAY be appended with a URI, for example `name` and `description` may be renamed to `nameURI` and `descriptionURI`, in which case the dereferenced URI MUST return a JSON-LD object containing the `&quot;@context&quot;: &quot;https://www.daostar.org/schemas&quot;` field and the original key-value pair.

For example, descriptionURI should return:
```json
{
    &quot;@context&quot;: &quot;https://www.daostar.org/schemas&quot;,
    &quot;description&quot;: &quot;&lt;description&gt;&quot;
}
```

### Entities which are not DAOs

Entities which are not DAOs or which do not wish to identify as DAOs MAY still publish daoURIs. If so, they SHOULD use a different value for the `type` field than &quot;DAO&quot;, for example &quot;Organization&quot;, &quot;Foundation&quot;, &quot;Person&quot;, or, most broadly, &quot;Entity&quot;.

Entities which are not DAOs or which do not wish to identify as DAOs MAY also publish metadata information through an off-chain orgURI or entityURI, which are aliases of daoURI. If these entities are reporting their URI through an on-chain smart contract or registration, however, they MUST retain `IERC4824`&apos;s daoURI in order to enable network indexing.

The Entity JSON-LD Schema:

```json
{
    &quot;@context&quot;: &quot;https://www.daostar.org/schemas&quot;,
    &quot;type&quot;: &quot;&lt;type of entity&gt;&quot;,
    &quot;name&quot;: &quot;&lt;name of the entity&gt;&quot;,
    &quot;description&quot;: &quot;&lt;description&gt;&quot;,
    &quot;membersURI&quot;: &quot;&lt;URI&gt;&quot;,
    &quot;proposalsURI&quot;: &quot;&lt;URI&gt;&quot;,
    &quot;activityLogURI&quot;: &quot;&lt;URI&gt;&quot;,
    &quot;governanceURI&quot;: &quot;&lt;URI&gt;&quot;,
    &quot;contractsURI&quot;: &quot;&lt;URI&gt;&quot;
}
```

## Rationale

In this standard, we assume that all DAOs possess at least two primitives: _membership_ and _behavior_. _Membership_ is defined by a set of addresses. _Behavior_ is defined by a set of possible contract actions, including calls to external contracts and calls to internal functions. _Proposals_ relate membership and behavior; they are objects that members can interact with and which, if and when executed, become behaviors of the DAO.

### APIs, URIs, and off-chain data

DAOs themselves have a number of existing and emerging use-cases. But almost all DAOs need to publish data off-chain for a number of reasons: communicating to and recruiting members, coordinating activities, powering user interfaces and governance applications such as Snapshot or Tally, or enabling search and discovery via platforms like DeepDAO, Messari, and Etherscan. Having a standardized schema for this data organized across multiple URIs, i.e. an API specification, would strengthen existing use-cases for DAOs, help scale tooling and frameworks across the ecosystem, and build support for additional forms of interoperability.

While we considered standardizing on-chain aspects of DAOs in this standard, particularly on-chain proposal objects and proposal IDs, we felt that this level of standardization was premature given (1) the relative immaturity of use-cases, such as multi-DAO proposals or master-minion contracts, that would benefit from such standardization, (2) the close linkage between proposal systems and governance, which we did not want to standardize (see “governanceURI”, below), and (3) the prevalence of off-chain and L2 voting and proposal systems in DAOs (see “proposalsURI”, below). Further, a standard URI interface is relatively easy to adopt and has been actively demanded by frameworks (see “Community Consensus”, below).

We added the ability to append or remove the URI suffix to make dereferenced daoURIs easier to parse, especially in certain applications that did not want to maintain several services or flatfiles. Where there is a conflict, we decided that fields without the URI suffix should take precedence since they are more directly connected to the initial publication of daoURI.

In terms of indexing: we believe that the most trustworthy way of publishing a daoURI is through an on-chain registration contract, as it is the clearest reflection of the active will of a DAO. It is also the primary way a DAO may “overwrite” any other daoURI that has previously been published, through any means. If a DAO inherits daoURI directly through its contract, then this information is also trustworthy, though slightly less so as it often reflects the decisions of a DAO framework rather than the DAO directly.

### membersURI

Approaches to membership vary widely in DAOs. Some DAOs and DAO frameworks (e.g. Gnosis Safe, Tribute), maintain an explicit, on-chain set of members, sometimes called owners or stewards. But many DAOs are structured so that membership status is based on the ownership of a token or tokens (e.g. Moloch, Compound, DAOstack, 1Hive Gardens). In these DAOs, computing the list of current members typically requires some form of off-chain indexing of events.

In choosing to ask only for an (off-chain) JSON schema of members, we are trading off some on-chain functionality for more flexibility and efficiency. We expect different DAOs to use membersURI in different ways: to serve a static copy of on-chain membership data, to contextualize the on-chain data (e.g. many Gnosis Safe stewards would not say that they are the only members of the DAO), to serve consistent membership for a DAO composed of multiple contracts, or to point at an external service that computes the list, among many other possibilities. We also expect many DAO frameworks to offer a standard endpoint that computes this JSON file, and we provide a few examples of such endpoints in the implementation section.

We encourage extensions of the Membership JSON-LD Schema, e.g. for DAOs that wish to create a state variable that captures active/inactive status or different membership levels.

### proposalsURI

Proposals have become a standard way for the members of a DAO to trigger on-chain actions, e.g. sending out tokens as part of a grant or executing arbitrary code in an external contract. In practice, however, many DAOs are governed by off-chain decision-making systems on platforms such as Discourse, Discord, or Snapshot, where off-chain proposals may function as signaling mechanisms for an administrator or as a prerequisite for a later on-chain vote. (To be clear, on-chain votes may also serve as non-binding signaling mechanisms or as “binding” signals leading to some sort of off-chain execution.) The schema we propose is intended to support both on-chain and off-chain proposals, though DAOs themselves may choose to report only on-chain, only off-chain, or some custom mix of proposal types.

**Proposal ID**. In the specification, we state that every unique on-chain proposal must be associated to a proposal ID of the form CAIP10_ADDRESS + “?proposalId=” + PROPOSAL_COUNTER, where PROPOSAL_COUNTER is an arbitrary string which is unique per CAIP10_ADDRESS. Note that PROPOSAL_COUNTER may not be the same as the on-chain representation of the proposal; however, each PROPOSAL_COUNTER should be unique per CAIP10_ADDRESS, such that the proposal ID is a globally unique identifier. We endorse the CAIP-10 standard to support multi-chain / layer 2 proposals and the “?proposalId=” query syntax to suggest off-chain usage.

**ContentURI**. In many cases, a proposal will have some (off-chain) content such as a forum post or a description on a voting platform which predates or accompanies the actual proposal.

**Status**. Almost all proposals have a status or state, but the actual status is tied to the governance system, and there is no clear consensus between existing DAOs about what those statuses should be (see table below). Therefore, we have defined a “status” property with a generic, free text description field.

| Project | Proposal Statuses |
| --- | --- |
| Aragon | Not specified |
| Colony | [‘Null’, ‘Staking’, ‘Submit’, ‘Reveal’, ‘Closed’, ‘Finalizable’, ‘Finalized’, ‘Failed’] |
| Compound | [‘Pending’, ‘Active’, ‘Canceled’, ‘Defeated’, ‘Succeeded’, ‘Queued’, ‘Expired’, ‘Executed’] |
| DAOstack/ Alchemy | [‘None’, ‘ExpiredInQueue’, ‘Executed’, ‘Queued’, ‘PreBoosted’, ‘Boosted’, ‘QuietEndingPeriod’] |
| Moloch v2 | [sponsored, processed, didPass, cancelled, whitelist, guildkick] |
| Tribute | [‘EXISTS’, ‘SPONSORED’, ‘PROCESSED’] |

**ExecutionData**. For on-chain proposals with non-empty execution, we include an array field to expose the call data. The main use-case for this data is execution simulation of proposals.

### activityLogURI

The activity log JSON is intended to capture the interplay between a member of a DAO and a given proposal. Examples of activities include the creation/submission of a proposal, voting on a proposal, disputing a proposal, and so on.

_Alternatives we considered: history, interactions_

### governanceURI

Membership, to be meaningful, usually implies rights and affordances of some sort, e.g. the right to vote on proposals, the right to ragequit, the right to veto proposals, and so on. But many rights and affordances of membership are realized off-chain (e.g. right to vote on a Snapshot, gated access to a Discord). Instead of trying to standardize these wide-ranging practices or forcing DAOs to locate descriptions of those rights on-chain, we believe that a flatfile represents the easiest and most widely-acceptable mechanism for communicating what membership means and how proposals work. These flatfiles can then be consumed by services such as Etherscan, supporting DAO discoverability and legibility.

We chose the word “governance” as an appropriate word that reflects (1) the widespread use of the word in the DAO ecosystem and (2) the common practice of emitting a governance.md file in open-source software projects.

_Alternative names considered: description, readme, constitution_

### contractsURI

Over the course of community conversations, multiple parties raised the need to report on, audit, and index the different contracts belonging to a given DAO. Some of these contracts are deployed as part of the modular design of a single DAO framework, e.g. the core, voting, and timelock contracts within Open Zeppelin / Compound Governor. In other cases, a DAO might deploy multiple multsigs as treasuries and/or multiple subDAOs that are effectively controlled by the DAO. contractsURI offers a generic way of declaring these many instruments so that they can be efficiently aggregated by an indexer.

contractsURI is also important for spam prevention or spoofing. Some DAOs may spread governance power and control across multiple different governance contracts, possibly across several chains. To capture this reality, multiple addresses may wish to report the same daoURI, or different daoURIs with the same name&lt;!-- or the same ID--&gt;. However, unauthorized addresses may try to report the same daoURI or name&lt;!--, or ID --&gt;. Additional contract information can prevent attacks of this sort by allowing indexers to weed out spam information.

_Alternative names considered: contractsRegistry, contractsList_

### Why JSON-LD

We chose to use JSON-LD rather than the more widespread and simpler JSON standard because (1) we want to support use-cases where a DAO wants to include members using some other form of identification than their Ethereum address and (2) we want this standard to be compatible with future multi-chain standards. Either use-case would require us to implement a context and type for addresses, which is already implemented in JSON-LD.

Further, given the emergence of patterns such as subDAOs and DAOs of DAOs in large organizations such as Synthetix, as well as L2 and multi-chain use-cases, we expect some organizations will point multiple DAOs to the same URI, which would then serve as a gateway to data from multiple contracts and services. The choice of JSON-LD allows for easier extension and management of that data.

### **Community Consensus**

The initial draft standard was developed as part of the DAOstar roundtable series, which included representatives from all major EVM-based DAO frameworks (Aragon, Compound, DAOstack, Gnosis, Moloch, OpenZeppelin, and Tribute), a wide selection of DAO tooling developers, as well as several major DAOs. Thank you to all the participants of the roundtable. We would especially like to thank Fabien of Snapshot, Jake Hartnell, Auryn Macmillan, Selim Imoberdorf, Lucia Korpas, and Mehdi Salehi for their contributions.

In-person events for community comment were held at Schelling Point 2022, ETHDenver 2022, ETHDenver 2023, DAO Harvard 2023, DAO Stanford 2023 (also known as the Science of Blockchains Conference DAO Workshop). The team also hosted over 50 biweekly community calls as part of the DAOstar project.

## Backwards Compatibility

Existing contracts that do not wish to use this specification are unaffected. DAOs that wish to adopt the standard without updating or migrating contracts can do so via an external registration contract.

## Security Considerations

This standard defines the interfaces for the DAO URIs but does not specify the rules under which the URIs are set, or how the data is prepared. Developers implementing this standard should consider how to update this data in a way aligned with the DAO’s governance model, and keep the data fresh in a way that minimizes reliance on centralized service providers.

Indexers that rely on the data returned by the URI should take caution if DAOs return executable code from the URIs. This executable code might be intended to get the freshest information on membership, proposals, and activity log, but it could also be used to run unrelated tasks.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 17 Feb 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4824</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4824</guid>
      </item>
    
      <item>
        <title>Hierarchical Domains</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-4834-hierarchical-domains-standard/8388</comments>
        
        <description>## Abstract

This is a standard for generic name resolution with arbitrarily complex access control and resolution. It permits a contract that implements this EIP (referred to as a &quot;domain&quot; hereafter) to be addressable with a more human-friendly name, with a similar purpose to [ERC-137](/EIPs/EIPS/eip-137) (also known as &quot;ENS&quot;).

## Motivation

The advantage of this EIP over existing standards is that it provides a minimal interface that supports name resolution, adds standardized access control, and has a simple architecture. ENS, although useful, has a comparatively complex architecture and does not have standard access control.

In addition, all domains (including subdomains, TLDs, and even the root itself) are actually implemented as domains, meaning that name resolution is a simple iterative algorithm, not unlike DNS itself.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### Contract Interface

```solidity
interface IDomain {
    /// @notice     Query if a domain has a subdomain with a given name
    /// @param      name The subdomain to query, in right to left order
    /// @return     `true` if the domain has a subdomain with the given name, `false` otherwise
    function hasDomain(string[] memory name) external view returns (bool);

    /// @notice     Fetch the subdomain with a given name
    /// @dev        This should revert if `hasDomain(name)` is `false`
    /// @param      name The subdomain to fetch, in right to left order
    /// @return     The subdomain with the given name
    function getDomain(string[] memory name) external view returns (address);
}
```

### Name Resolution

To resolve a name (like `&quot;a.b.c&quot;`), split it by the delimiter (resulting in something like `[&quot;a&quot;, &quot;b&quot;, &quot;c&quot;]`). Set `domain` initially to the root domain, and `path` to be an empty list.

Pop off the last element of the array (`&quot;c&quot;`) and add it to the path, then call `domain.hasDomain(path)`. If it&apos;s `false`, then the domain resolution fails. Otherwise, set the domain to `domain.getDomain(path)`. Repeat until the list of split segments is empty.

There is no limit to the amount of nesting that is possible. For example, `0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z` would be valid if the root contains `z`, and `z` contains `y`, and so on.

Here is a solidity function that resolves a name:

```solidity
function resolve(string[] calldata splitName, IDomain root) public view returns (address) {
    IDomain current = root;
    string[] memory path = [];
    for (uint i = splitName.length - 1; i &gt;= 0; i--) {
        // Append to back of list
        path.push(splitName[i]);
        // Require that the current domain has a domain
        require(current.hasDomain(path), &quot;Name resolution failed&quot;);
        // Resolve subdomain
        current = current.getDomain(path);
    }
    return current;
}
```

### Optional Extension: Registerable

```solidity
interface IDomainRegisterable is IDomain {
    //// Events
    
    /// @notice     Must be emitted when a new subdomain is created (e.g. through `createDomain`)
    /// @param      sender msg.sender for createDomain
    /// @param      name name for createDomain
    /// @param      subdomain subdomain in createDomain
    event SubdomainCreate(address indexed sender, string name, address subdomain);

    /// @notice     Must be emitted when the resolved address for a domain is changed (e.g. with `setDomain`)
    /// @param      sender msg.sender for setDomain
    /// @param      name name for setDomain
    /// @param      subdomain subdomain in setDomain
    /// @param      oldSubdomain the old subdomain
    event SubdomainUpdate(address indexed sender, string name, address subdomain, address oldSubdomain);

    /// @notice     Must be emitted when a domain is unmapped (e.g. with `deleteDomain`)
    /// @param      sender msg.sender for deleteDomain
    /// @param      name name for deleteDomain
    /// @param      subdomain the old subdomain
    event SubdomainDelete(address indexed sender, string name, address subdomain);

    //// CRUD
    
    /// @notice     Create a subdomain with a given name
    /// @dev        This should revert if `canCreateDomain(msg.sender, name, pointer)` is `false` or if the domain exists
    /// @param      name The subdomain name to be created
    /// @param      subdomain The subdomain to create
    function createDomain(string memory name, address subdomain) external payable;

    /// @notice     Update a subdomain with a given name
    /// @dev        This should revert if `canSetDomain(msg.sender, name, pointer)` is `false` of if the domain doesn&apos;t exist
    /// @param      name The subdomain name to be updated
    /// @param      subdomain The subdomain to set
    function setDomain(string memory name, address subdomain) external;

    /// @notice     Delete the subdomain with a given name
    /// @dev        This should revert if the domain doesn&apos;t exist or if `canDeleteDomain(msg.sender, name)` is `false`
    /// @param      name The subdomain to delete
    function deleteDomain(string memory name) external;


    //// Parent Domain Access Control

    /// @notice     Get if an account can create a subdomain with a given name
    /// @dev        This must return `false` if `hasDomain(name)` is `true`.
    /// @param      updater The account that may or may not be able to create/update a subdomain
    /// @param      name The subdomain name that would be created/updated
    /// @param      subdomain The subdomain that would be set
    /// @return     Whether an account can update or create the subdomain
    function canCreateDomain(address updater, string memory name, address subdomain) external view returns (bool);

    /// @notice     Get if an account can update or create a subdomain with a given name
    /// @dev        This must return `false` if `hasDomain(name)` is `false`.
    ///             If `getDomain(name)` is also a domain implementing the subdomain access control extension, this should return `false` if `getDomain(name).canMoveSubdomain(msg.sender, this, subdomain)` is `false`.
    /// @param      updater The account that may or may not be able to create/update a subdomain
    /// @param      name The subdomain name that would be created/updated
    /// @param      subdomain The subdomain that would be set
    /// @return     Whether an account can update or create the subdomain
    function canSetDomain(address updater, string memory name, address subdomain) external view returns (bool);

    /// @notice     Get if an account can delete the subdomain with a given name
    /// @dev        This must return `false` if `hasDomain(name)` is `false`.
    ///             If `getDomain(name)` is a domain implementing the subdomain access control extension, this should return `false` if `getDomain(name).canDeleteSubdomain(msg.sender, this, subdomain)` is `false`.
    /// @param      updater The account that may or may not be able to delete a subdomain
    /// @param      name The subdomain to delete
    /// @return     Whether an account can delete the subdomain
    function canDeleteDomain(address updater, string memory name) external view returns (bool);
}
```

### Optional Extension: Enumerable

```solidity
interface IDomainEnumerable is IDomain {
    /// @notice     Query all subdomains. Must revert if the number of domains is unknown or infinite.
    /// @return     The subdomain with the given index.
    function subdomainByIndex(uint256 index) external view returns (string memory);
    
    /// @notice     Get the total number of subdomains. Must revert if the number of domains is unknown or infinite.
    /// @return     The total number of subdomains.
    function totalSubdomains() external view returns (uint256);
}
```

### Optional Extension: Access Control

```solidity
interface IDomainAccessControl is IDomain {
    /// @notice     Get if an account can move the subdomain away from the current domain
    /// @dev        May be called by `canSetDomain` of the parent domain - implement access control here!!!
    /// @param      updater The account that may be moving the subdomain
    /// @param      name The subdomain name
    /// @param      parent The parent domain
    /// @param      newSubdomain The domain that will be set next
    /// @return     Whether an account can update the subdomain
    function canMoveSubdomain(address updater, string memory name, IDomain parent, address newSubdomain) external view returns (bool);

    /// @notice     Get if an account can unset this domain as a subdomain
    /// @dev        May be called by `canDeleteDomain` of the parent domain - implement access control here!!!
    /// @param      updater The account that may or may not be able to delete a subdomain
    /// @param      name The subdomain to delete
    /// @param      parent The parent domain
    /// @return     Whether an account can delete the subdomain
    function canDeleteSubdomain(address updater, string memory name, IDomain parent) external view returns (bool);
}
```

## Rationale

This EIP&apos;s goal, as mentioned in the abstract, is to have a simple interface for resolving names. Here are a few design decisions and why they were made:

- Name resolution algorithm
  - Unlike ENS&apos;s resolution algorithm, this EIP&apos;s name resolution is fully under the control of the contracts along the resolution path.
  - This behavior is more intuitive to users.
  - This behavior allows for greater flexibility - e.g. a contract that changes what it resolves to based on the time of day.
- Parent domain access control
  - A simple &quot;ownable&quot; interface was not used because this specification was designed to be as generic as possible. If an ownable implementation is desired, it can be implemented.
  - This also gives parent domains the ability to call subdomains&apos; access control methods so that subdomains, too, can choose whatever access control mechanism they desire
- Subdomain access control
  - These methods are included so that subdomains aren&apos;t always limited to their parent domain&apos;s access control
  - The root domain can be controlled by a DAO with a non-transferable token with equal shares, a TLD can be controlled by a DAO with a token representing stake, a domain of that TLD can be controlled by a single owner, a subdomain of that domain can be controlled by a single owner linked to an NFT, and so on.
  - Subdomain access control functions are suggestions: an ownable domain might implement an owner override, so that perhaps subdomains might be recovered if the keys are lost.

## Backwards Compatibility

This EIP is general enough to support ENS, but ENS is not general enough to support this EIP.

## Security Considerations

### Malicious canMoveSubdomain (Black Hole)

#### Description: Malicious `canMoveSubdomain`

Moving a subdomain using `setDomain` is a potentially dangerous operation.

Depending on the parent domain&apos;s implementation, if a malicious new subdomain unexpectedly returns `false` on `canMoveSubdomain`, that subdomain can effectively lock the ownership of the domain.

Alternatively, it might return `true` when it isn&apos;t expected (i.e. a backdoor), allowing the contract owner to take over the domain.

#### Mitigation: Malicious `canMoveSubdomain`

Clients should help by warning if `canMoveSubdomain` or `canDeleteSubdomain` for the new subdomain changes to `false`. It is important to note, however, that since these are functions, it is possible for the value to change depending on whether or not it has already been linked. It is also still possible for it to unexpectedly return true. It is therefore recommended to **always** audit the new subdomain&apos;s source code before calling `setDomain`.

### Parent Domain Resolution

#### Description: Parent Domain Resolution

Parent domains have full control of name resolution for their subdomains. If a particular domain is linked to `a.b.c`, then `b.c` can, depending on its code, set `a.b.c` to any domain, and `c` can set `b.c` itself to any domain.

#### Mitigation: Parent Domain Resolution

Before acquiring a domain that has been pre-linked, it is recommended to always have the contract **and** all the parents up to the root audited.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 22 Feb 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4834</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4834</guid>
      </item>
    
      <item>
        <title>Shard Blob Transactions</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4844-shard-blob-transactions/8430</comments>
        
        <description>## Abstract

Introduce a new transaction format for &quot;blob-carrying transactions&quot; which contain a large amount of data that cannot be
accessed by EVM execution, but whose commitment can be accessed.
The format is intended to be fully compatible with the format that will be used in full sharding.

## Motivation

Rollups are in the short and medium term, and possibly in the long term, the only trustless scaling solution for Ethereum.
Transaction fees on L1 have been very high for months and there is greater urgency in doing anything required to help facilitate an ecosystem-wide move to rollups.
Rollups are significantly reducing fees for many Ethereum users: Optimism and Arbitrum frequently provide fees that are ~3-8x lower than the Ethereum base layer itself,
and ZK rollups, which have better data compression and can avoid including signatures, have fees ~40-100x lower than the base layer.

However, even these fees are too expensive for many users. The long-term solution to the long-term inadequacy of rollups
by themselves has always been data sharding, which would add ~16 MB per block of dedicated data space to the chain that rollups could use.
However, data sharding will still take a considerable amount of time to finish implementing and deploying.

This EIP provides a stop-gap solution until that point by implementing the _transaction format_ that would be used in sharding,
but not actually sharding those transactions. Instead, the data from this transaction format is simply part of the beacon chain and is fully downloaded
by all consensus nodes (but can be deleted after only a relatively short delay).
Compared to full data sharding, this EIP has a reduced cap on the number of these transactions that can be included, corresponding to a target of ~0.375 MB per block and a limit of ~0.75 MB.

## Specification

### Parameters

| Constant | Value |
| - | - |
| `BLOB_TX_TYPE` | `Bytes1(0x03)` |
| `BYTES_PER_FIELD_ELEMENT` | `32` |
| `FIELD_ELEMENTS_PER_BLOB` | `4096` |
| `BLS_MODULUS` | `52435875175126190479447740508185965837690552500527637822603658699938581184513` |
| `VERSIONED_HASH_VERSION_KZG` | `Bytes1(0x01)` |
| `POINT_EVALUATION_PRECOMPILE_ADDRESS` | `Bytes20(0x0A)` |
| `POINT_EVALUATION_PRECOMPILE_GAS` | `50000` |
| `MAX_BLOB_GAS_PER_BLOCK` | `786432` |
| `TARGET_BLOB_GAS_PER_BLOCK` | `393216` |
| `MIN_BASE_FEE_PER_BLOB_GAS` | `1` |
| `BLOB_BASE_FEE_UPDATE_FRACTION` | `3338477` |
| `GAS_PER_BLOB` | `2**17` |
| `HASH_OPCODE_BYTE` | `Bytes1(0x49)` |
| `HASH_OPCODE_GAS` | `3` |
| [`MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS`](https://github.com/ethereum/consensus-specs/blob/4de1d156c78b555421b72d6067c73b614ab55584/configs/mainnet.yaml#L148) | `4096` |

### Type aliases

| Type | Base type | Additional checks |
| - | - | - |
| `Blob` | `ByteVector[BYTES_PER_FIELD_ELEMENT * FIELD_ELEMENTS_PER_BLOB]` | |
| `VersionedHash` | `Bytes32` | |
| `KZGCommitment` | `Bytes48` | Perform IETF BLS signature &quot;KeyValidate&quot; check but do allow the identity point |
| `KZGProof` | `Bytes48` | Same as for `KZGCommitment` |

### Cryptographic Helpers

Throughout this proposal we use cryptographic methods and classes defined in the corresponding [consensus 4844 specs](https://github.com/ethereum/consensus-specs/blob/86fb82b221474cc89387fa6436806507b3849d88/specs/deneb).

Specifically, we use the following methods from [`polynomial-commitments.md`](https://github.com/ethereum/consensus-specs/blob/86fb82b221474cc89387fa6436806507b3849d88/specs/deneb/polynomial-commitments.md):

- [`verify_kzg_proof()`](https://github.com/ethereum/consensus-specs/blob/86fb82b221474cc89387fa6436806507b3849d88/specs/deneb/polynomial-commitments.md#verify_kzg_proof)
- [`verify_blob_kzg_proof_batch()`](https://github.com/ethereum/consensus-specs/blob/86fb82b221474cc89387fa6436806507b3849d88/specs/deneb/polynomial-commitments.md#verify_blob_kzg_proof_batch)

### Helpers

```python
def kzg_to_versioned_hash(commitment: KZGCommitment) -&gt; VersionedHash:
    return VERSIONED_HASH_VERSION_KZG + sha256(commitment)[1:]
```

Approximates `factor * e ** (numerator / denominator)` using Taylor expansion:

```python
def fake_exponential(factor: int, numerator: int, denominator: int) -&gt; int:
    i = 1
    output = 0
    numerator_accum = factor * denominator
    while numerator_accum &gt; 0:
        output += numerator_accum
        numerator_accum = (numerator_accum * numerator) // (denominator * i)
        i += 1
    return output // denominator
```

### Blob transaction

We introduce a new type of [EIP-2718](/EIPs/EIPS/eip-2718) transaction, &quot;blob transaction&quot;, where the `TransactionType` is `BLOB_TX_TYPE` and the `TransactionPayload` is the RLP serialization of the following `TransactionPayloadBody`:

```
[chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to, value, data, access_list, max_fee_per_blob_gas, blob_versioned_hashes, y_parity, r, s]
```

The fields `chain_id`, `nonce`, `max_priority_fee_per_gas`, `max_fee_per_gas`, `gas_limit`, `value`, `data`, and `access_list` follow the same semantics as [EIP-1559](/EIPs/EIPS/eip-1559).

The field `to` deviates slightly from the semantics with the exception that it MUST NOT be `nil` and therefore must always represent a 20-byte address. This means that blob transactions cannot have the form of a create transaction.

The field `max_fee_per_blob_gas` is a `uint256` and the field `blob_versioned_hashes` represents a list of hash outputs from `kzg_to_versioned_hash`.

The [EIP-2718](/EIPs/EIPS/eip-2718) `ReceiptPayload` for this transaction is `rlp([status, cumulative_transaction_gas_used, logs_bloom, logs])`.

#### Signature

The signature values `y_parity`, `r`, and `s` are calculated by constructing a secp256k1 signature over the following digest:

`keccak256(BLOB_TX_TYPE || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to, value, data, access_list, max_fee_per_blob_gas, blob_versioned_hashes]))`.

### Header extension

The current header encoding is extended with two new 64-bit unsigned integer fields:

- `blob_gas_used` is the total amount of blob gas consumed by the transactions within the block.
- `excess_blob_gas` is a running total of blob gas consumed in excess of the target, prior to the block. Blocks with above-target blob gas consumption increase this value, blocks with below-target blob gas consumption decrease it (bounded at 0).

The resulting RLP encoding of the header is therefore:

```
rlp([
    parent_hash,
    0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347, # ommers hash
    coinbase,
    state_root,
    txs_root,
    receipts_root,
    logs_bloom,
    0, # difficulty
    number,
    gas_limit,
    gas_used,
    timestamp,
    extradata,
    prev_randao,
    0x0000000000000000, # nonce
    base_fee_per_gas,
    withdrawals_root,
    blob_gas_used,
    excess_blob_gas,
])
```

The value of `excess_blob_gas` can be calculated using the parent header.

```python
def calc_excess_blob_gas(parent: Header) -&gt; int:
    if parent.excess_blob_gas + parent.blob_gas_used &lt; TARGET_BLOB_GAS_PER_BLOCK:
        return 0
    else:
        return parent.excess_blob_gas + parent.blob_gas_used - TARGET_BLOB_GAS_PER_BLOCK
```

For the first post-fork block, both `parent.blob_gas_used` and `parent.excess_blob_gas` are evaluated as `0`.

### Gas accounting

We introduce blob gas as a new type of gas. It is independent of normal gas and follows its own targeting rule, similar to EIP-1559.
We use the `excess_blob_gas` header field to store persistent data needed to compute the blob gas base fee. For now, only blobs are priced in blob gas.

```python
def calc_blob_fee(header: Header, tx: Transaction) -&gt; int:
    return get_total_blob_gas(tx) * get_base_fee_per_blob_gas(header)

def get_total_blob_gas(tx: Transaction) -&gt; int:
    return GAS_PER_BLOB * len(tx.blob_versioned_hashes)

def get_base_fee_per_blob_gas(header: Header) -&gt; int:
    return fake_exponential(
        MIN_BASE_FEE_PER_BLOB_GAS,
        header.excess_blob_gas,
        BLOB_BASE_FEE_UPDATE_FRACTION
    )
```

The block validity conditions are modified to include blob gas checks (see the [Execution layer validation](#execution-layer-validation) section below).

The actual `blob_fee` as calculated via `calc_blob_fee` is deducted from the sender balance before transaction execution and burned, and is not refunded in case of transaction failure.

### Opcode to get versioned hashes

We add an instruction `BLOBHASH` (with opcode `HASH_OPCODE_BYTE`) which reads `index` from the top of the stack
as big-endian `uint256`, and replaces it on the stack with `tx.blob_versioned_hashes[index]`
if `index &lt; len(tx.blob_versioned_hashes)`, and otherwise with a zeroed `bytes32` value.
The opcode has a gas cost of `HASH_OPCODE_GAS`.

### Point evaluation precompile

Add a precompile at `POINT_EVALUATION_PRECOMPILE_ADDRESS` that verifies a KZG proof which claims that a blob
(represented by a commitment) evaluates to a given value at a given point.

The precompile costs `POINT_EVALUATION_PRECOMPILE_GAS` and executes the following logic:

```python
def point_evaluation_precompile(input: Bytes) -&gt; Bytes:
    &quot;&quot;&quot;
    Verify p(z) = y given commitment that corresponds to the polynomial p(x) and a KZG proof.
    Also verify that the provided commitment matches the provided versioned_hash.
    &quot;&quot;&quot;
    # The data is encoded as follows: versioned_hash | z | y | commitment | proof | with z and y being padded 32 byte big endian values
    assert len(input) == 192
    versioned_hash = input[:32]
    z = input[32:64]
    y = input[64:96]
    commitment = input[96:144]
    proof = input[144:192]

    # Verify commitment matches versioned_hash
    assert kzg_to_versioned_hash(commitment) == versioned_hash

    # Verify KZG proof with z and y in big endian format
    assert verify_kzg_proof(commitment, z, y, proof)

    # Return FIELD_ELEMENTS_PER_BLOB and BLS_MODULUS as padded 32 byte big endian values
    return Bytes(U256(FIELD_ELEMENTS_PER_BLOB).to_be_bytes32() + U256(BLS_MODULUS).to_be_bytes32())
```

The precompile MUST reject non-canonical field elements (i.e. provided field elements MUST be strictly less than `BLS_MODULUS`).

### Consensus layer validation

On the consensus layer the blobs are referenced, but not fully encoded, in the beacon block body.
Instead of embedding the full contents in the body, the blobs are propagated separately, as &quot;sidecars&quot;.

This &quot;sidecar&quot; design provides forward compatibility for further data increases by black-boxing `is_data_available()`:
with full sharding `is_data_available()` can be replaced by data-availability-sampling (DAS) thus avoiding all blobs being downloaded by all beacon nodes on the network.

Note that the consensus layer is tasked with persisting the blobs for data availability, the execution layer is not.

The `ethereum/consensus-specs` repository defines the following consensus layer changes involved in this EIP:

- Beacon chain: process updated beacon blocks and ensure blobs are available.
- P2P network: gossip and sync updated beacon block types and new blob sidecars.
- Honest validator: produce beacon blocks with blobs; sign and publish the associated blob sidecars.

### Execution layer validation

On the execution layer, the block validity conditions are extended as follows:

```python
def validate_block(block: Block) -&gt; None:
    ...

    # check that the excess blob gas was updated correctly
    assert block.header.excess_blob_gas == calc_excess_blob_gas(block.parent.header)

    blob_gas_used = 0

    for tx in block.transactions:
        ...

        # modify the check for sufficient balance
        max_total_fee = tx.gas * tx.max_fee_per_gas
        if get_tx_type(tx) == BLOB_TX_TYPE:
            max_total_fee += get_total_blob_gas(tx) * tx.max_fee_per_blob_gas
        assert signer(tx).balance &gt;= max_total_fee

        ...

        # add validity logic specific to blob txs
        if get_tx_type(tx) == BLOB_TX_TYPE:
            # there must be at least one blob
            assert len(tx.blob_versioned_hashes) &gt; 0

            # all versioned blob hashes must start with VERSIONED_HASH_VERSION_KZG
            for h in tx.blob_versioned_hashes:
                assert h[0] == VERSIONED_HASH_VERSION_KZG

            # ensure that the user was willing to at least pay the current blob base fee
            assert tx.max_fee_per_blob_gas &gt;= get_base_fee_per_blob_gas(block.header)

            # keep track of total blob gas spent in the block
            blob_gas_used += get_total_blob_gas(tx)

    # ensure the total blob gas spent is at most equal to the limit
    assert blob_gas_used &lt;= MAX_BLOB_GAS_PER_BLOCK

    # ensure blob_gas_used matches header
    assert block.header.blob_gas_used == blob_gas_used

```

### Networking

Blob transactions have two network representations. During transaction gossip responses (`PooledTransactions`), the EIP-2718 `TransactionPayload` of the blob transaction is wrapped to become:

```
rlp([tx_payload_body, blobs, commitments, proofs])
```

Each of these elements are defined as follows:

- `tx_payload_body` - is the `TransactionPayloadBody` of standard EIP-2718 [blob transaction](#blob-transaction)
- `blobs` - list of `Blob` items
- `commitments` - list of `KZGCommitment` of the corresponding `blobs`
- `proofs` - list of `KZGProof` of the corresponding `blobs` and `commitments`

The node MUST validate `tx_payload_body` and verify the wrapped data against it. To do so, ensure that:

- There are an equal number of `tx_payload_body.blob_versioned_hashes`, `blobs`, `commitments`, and `proofs`.
- The KZG `commitments` hash to the versioned hashes, i.e. `kzg_to_versioned_hash(commitments[i]) == tx_payload_body.blob_versioned_hashes[i]`
- The KZG `commitments` match the corresponding `blobs` and `proofs`. (Note: this can be optimized using `verify_blob_kzg_proof_batch`, with a proof for a
  random evaluation at a point derived from the commitment and blob data for each blob)

For body retrieval responses (`BlockBodies`), the standard EIP-2718 blob transaction `TransactionPayload` is used.

Nodes MUST NOT automatically broadcast blob transactions to their peers.
Instead, those transactions are only announced using `NewPooledTransactionHashes` messages, and can then be manually requested via `GetPooledTransactions`.

## Rationale

### On the path to sharding

This EIP introduces blob transactions in the same format in which they are expected to exist in the final sharding specification.
This provides a temporary but significant scaling relief for rollups by allowing them to initially scale to 0.375 MB per slot,
with a separate fee market allowing fees to be very low while usage of this system is limited.

The core goal of rollup scaling stopgaps is to provide temporary scaling relief,
without imposing extra development burdens on rollups to take advantage of this relief.
Today, rollups use calldata. In the future, rollups will have no choice but to use sharded data (also called &quot;blobs&quot;)
because sharded data will be much cheaper.
Hence, rollups cannot avoid making a large upgrade to how they process data at least once along the way.
But what we _can_ do is ensure that rollups need to _only_ upgrade once.
This immediately implies that there are exactly two possibilities for a stopgap: (i) reducing the gas costs of existing calldata,
and (ii) bringing forward the format that will be used for sharded data, but not yet actually sharding it.
Previous EIPs were all a solution of category (i); this EIP is a solution of category (ii).

The main tradeoff in designing this EIP is that of implementing more now versus having to implement more later:
do we implement 25% of the work on the way to full sharding, or 50%, or 75%?

The work that is already done in this EIP includes:

- A new transaction type, of the exact same format that will need to exist in &quot;full sharding&quot;
- _All_ of the execution-layer logic required for full sharding
- _All_ of the execution / consensus cross-verification logic required for full sharding
- Layer separation between `BeaconBlock` verification and data availability sampling blobs
- Most of the `BeaconBlock` logic required for full sharding
- A self-adjusting independent base fee for blobs

The work that remains to be done to get to full sharding includes:

- A low-degree extension of the `commitments` in the consensus layer to allow 2D sampling
- An actual implementation of data availability sampling
- PBS (proposer/builder separation), to avoid requiring individual validators to process 32 MB of data in one slot
- Proof of custody or similar in-protocol requirement for each validator to verify a particular part of the sharded data in each block

This EIP also sets the stage for longer-term protocol cleanups. For example, its (cleaner) gas base fee update rule could be applied to the primary basefee calculation.

### How rollups would function

Instead of putting rollup block data in transaction calldata, rollups would expect rollup block submitters
to put the data into blobs. This guarantees availability (which is what rollups need) but would be much cheaper than calldata.
Rollups need data to be available once, long enough to ensure honest actors can construct the rollup state, but not forever.

Optimistic rollups only need to actually provide the underlying data when fraud proofs are being submitted.
The fraud proof can verify the transition in smaller steps, loading at most a few values of the blob at a time through calldata.
For each value it would provide a KZG proof and use the point evaluation precompile to verify the value against the versioned hash that was submitted before,
and then perform the fraud proof verification on that data as is done today.

ZK rollups would provide two commitments to their transaction or state delta data:
the blob commitment (which the protocol ensures points to available data) and the ZK rollup&apos;s own commitment using whatever proof system the rollup uses internally.
They would use a proof of equivalence protocol, using the point evaluation precompile,
to prove that the two commitments refer to the same data.

### Versioned hashes &amp; precompile return data

We use versioned hashes (rather than commitments) as references to blobs in the execution layer to ensure forward compatibility with future changes.
For example, if we need to switch to Merkle trees + STARKs for quantum-safety reasons, then we would add a new version,
allowing the point evaluation precompile to work with the new format.
Rollups would not have to make any EVM-level changes to how they work;
sequencers would simply have to switch over to using a new transaction type at the appropriate time.

However, the point evaluation happens inside a finite field, and it is only well defined if the field modulus is known. Smart contracts could contain a table mapping the commitment version to a modulus, but this would not allow smart contract to take into account future upgrades to a modulus that is not known yet. By allowing access to the modulus inside the EVM, the smart contract can be built so that it can use future commitments and proofs, without ever needing an upgrade.

In the interest of not adding another precompile, we return the modulus and the polynomial degree directly from the point evaluation precompile. It can then be used by the caller. It is also &quot;free&quot; in that the caller can just ignore this part of the return value without incurring an extra cost -- systems that remain upgradable for the foreseeable future will likely use this route for now.

### Base fee per blob gas update rule

The base fee per blob gas update rule is intended to approximate the formula `base_fee_per_blob_gas = MIN_BASE_FEE_PER_BLOB_GAS * e**(excess_blob_gas / BLOB_BASE_FEE_UPDATE_FRACTION)`,
where `excess_blob_gas` is the total &quot;extra&quot; amount of blob gas that the chain has consumed relative to the &quot;targeted&quot; number (`TARGET_BLOB_GAS_PER_BLOCK` per block).
Like EIP-1559, it&apos;s a self-correcting formula: as the excess goes higher, the `base_fee_per_blob_gas` increases exponentially, reducing usage and eventually forcing the excess back down.

The block-by-block behavior is roughly as follows.
If block `N` consumes `X` blob gas, then in block `N+1` `excess_blob_gas` increases by `X - TARGET_BLOB_GAS_PER_BLOCK`,
and so the `base_fee_per_blob_gas` of block `N+1` increases by a factor of `e**((X - TARGET_BLOB_GAS_PER_BLOCK) / BLOB_BASE_FEE_UPDATE_FRACTION)`.
Hence, it has a similar effect to the existing EIP-1559, but is more &quot;stable&quot; in the sense that it responds in the same way to the same total usage regardless of how it&apos;s distributed.

The parameter `BLOB_BASE_FEE_UPDATE_FRACTION` controls the maximum rate of change of the base fee per blob gas. It is chosen to target a maximum change rate of `e**(TARGET_BLOB_GAS_PER_BLOCK / BLOB_BASE_FEE_UPDATE_FRACTION) ≈ 1.125` per block.

### Throughput

The values for `TARGET_BLOB_GAS_PER_BLOCK` and `MAX_BLOB_GAS_PER_BLOCK` are chosen to correspond to a target of 3 blobs (0.375 MB) and maximum of 6 blobs (0.75 MB) per block. These small initial limits are intended to minimize the strain on the network created by this EIP and are expected to be increased in future upgrades as the network demonstrates reliability under larger blocks.

## Backwards Compatibility

### Blob non-accessibility

This EIP introduces a transaction type that has a distinct mempool version and execution-payload version,
with only one-way convertibility between the two. The blobs are in the network representation and not in the consensus representation;
instead, they are coupled with the beacon block. This means that there is now a part of a transaction that will not be accessible from the web3 API.

### Mempool issues

Blob transactions have a large data size at the mempool layer, which poses a mempool DoS risk,
though not an unprecedented one as this also applies to transactions with large amounts of calldata.

By only broadcasting announcements for blob transactions, receiving nodes will have control over which and how many transactions to receive,
allowing them to throttle throughput to an acceptable level.
[EIP-5793](/EIPs/EIPS/eip-5793) will give further fine-grained control to nodes by extending the `NewPooledTransactionHashes` announcement messages to include the transaction type and size.

In addition, we recommend including a 1.1x base fee per blob gas bump requirement to the mempool transaction replacement rules.

## Test Cases

Execution layer test cases for this EIP can be found in the [`eip4844_blobs`](https://github.com/ethereum/execution-spec-tests/tree/1983444bbe1a471886ef7c0e82253ffe2a4053e1/tests/cancun/eip4844_blobs) of the `ethereum/execution-spec-tests` repository. Consensus layer test cases can be found [here](https://github.com/ethereum/consensus-specs/tree/2297c09b7e457a13f7b2261a28cb45777be82f83/tests/core/pyspec/eth2spec/test/deneb). 

## Security Considerations

This EIP increases the bandwidth requirements per beacon block by a maximum of ~0.75 MB.
This is 40% larger than the theoretical maximum size of a block today (30M gas / 16 gas per calldata byte = 1.875M bytes), and so it will not greatly increase worst-case bandwidth.
Post-merge, block times are static rather than an unpredictable Poisson distribution, giving a guaranteed period of time for large blocks to propagate.

The _sustained_ load of this EIP is much lower than alternatives that reduce calldata costs, even if the calldata is limited,
because there is no expectation that the blobs need to be stored for as long as an execution payload.
This makes it possible to implement a policy that these blobs must be kept for at least a certain period. The specific value chosen is `MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS` epochs, which is around 18 days, 
a much shorter delay compared to proposed (but yet to be implemented) one-year rotation times for execution payload history.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 25 Feb 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4844</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4844</guid>
      </item>
    
      <item>
        <title>Beacon chain push withdrawals</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4863-beacon-chain-push-withdrawals/8465</comments>
        
        <description>## Abstract

Introduce a new [EIP-2718 transaction type](/EIPs/EIPS/eip-2718) to support validator withdrawals that are &quot;pushed&quot; from the beacon chain to the EVM.

Add block validations to ensure the withdrawal transactions are sound with respect to withdrawal processing on the beacon chain.

## Motivation

This EIP provides a way for validator withdrawals made on the beacon chain to enter into the EVM.
The architecture is &quot;push&quot;-based, rather than &quot;pull&quot;-based, where withdrawals are required to be processed in the execution block as soon as they are dequeued from the beacon chain.

This approach is more involved than &quot;pull&quot;-based alternatives (e.g. [EIP-4788](/EIPs/EIPS/eip-4788) + user-space withdrawal contract) with respect to the core protocol (by providing a new transaction type with special semantics) but does provide tighter integration of a critical feature into the protocol itself.

## Specification

| constants                     | value                                          | units
|---                            |---                                             |---
| `FORK_TIMESTAMP`              | TBD                                            |
| `WITHDRAWAL_TX_TYPE`          | `0x3`                                          | byte

Beginning with the execution timestamp `FORK_TIMESTAMP`, execution clients **MUST** introduce the following extensions to transaction processing and block validation:

### New transaction type

Define a new [EIP-2718](/EIPs/EIPS/eip-2718) transaction type with `TransactionType` `WITHDRAWAL_TX_TYPE`.

The `TransactionPayload` is an RLP-encoded list `RLP([index, address, amount])` where the `index` is a 64-bit value uniquely labeling a specific withdrawal, the `address` refers to an execution layer account and the `amount` refers to an ether value given in units of wei.

These values are provided by the consensus layer.

### Block validity

If a block contains *any* transactions with `WITHDRAWAL_TX_TYPE` type, they **MUST** come after **ALL** other transactions in the block.

If the execution client receives a block where this is not the case, it **MUST** consider the block invalid.

### Transaction processing

When processing a transaction with `WITHDRAWAL_TX_TYPE` type, the implementation should increase the balance of the `address` specified by
the `WithdrawalTransaction` by the `amount` of wei specified.

This balance change is unconditional and **MUST** not fail.

This transaction type has no associated gas costs.

TODO: add logs?

## Rationale

### Push vs pull approach

This push approach gives validators a small subsidy with respect to processing, in lieu of needing to buy gas via normal EVM processing that would be required for a pull-based approach.

This style also happens automatically when the requisite conditions are met on the beacon chain which is nicer UX for validators.

### Why a new transaction type?

This EIP suggests a new transaction type as it has special semantics different from other existing types of EVM transactions.

An entirely new transaction type firewalls off generic EVM execution from this type of processing to simplify testing and security review of withdrawals.

### Why no (gas) costs for new transaction type?

The maximum number of this transaction type that can reach the execution layer at a given time is bounded (enforced by the consensus layer) and this limit is kept small so that
any execution layer operational costs are negligible in the context of the broader block execution.

### Why only balance updates? No general EVM execution?

More general processing introduces the risk of failures, which complicates accounting on the beacon chain.

This EIP suggests a route for withdrawals that provides most of the benefits for a minimum of the (complexity) cost.

### Why new block validations?

The beacon chain must be able to efficiently validate that the withdrawal transactions in a given execution block are
the ones expected based on its own internal scheduling logic to maintain the soundness of the withdrawal mechanism.

By requiring all withdrawal transactions to be at the back of every block where they are applicable, the algorithm to
check consistency becomes a straightforward linear walk from the start of the set until a known, bounded (small) number.

Having a simple ordering scheme like this facilitates optimizations clients may do with respect to withdrawal processing, which
would be hampered if withdrawal transactions could be placed in the block freely.

## Backwards Compatibility

No issues.

## Security Considerations

Consensus-layer validation of withdrawal transactions is critical to ensure that the proper amount of ETH is withdrawn back into the execution layer.
This consensus-layer to execution-layer ETH transfer does not have a current analog in the EVM and thus deserves very high security scrutiny.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 28 Feb 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4863</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4863</guid>
      </item>
    
      <item>
        <title>Deposit Contract Snapshot Interface</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4881-deposit-contract-snapshot-interface/8554</comments>
        
        <description>## Abstract

This EIP defines a standard format for transmitting the deposit contract Merkle tree in a compressed form during weak subjectivity sync. This allows newly syncing consensus clients to reconstruct the deposit tree much faster than downloading all historical deposits. The format proposed also allows clients to prune deposits that are no longer needed to participate fully in consensus (see [Deposit Finalization Flow](#deposit-finalization-flow)).

## Motivation

To reconstruct the deposit Merkle tree, most client implementations require beacon nodes to download and store every deposit log since the launch of the deposit contract. However, this approach requires beacon nodes to store far more deposits than necessary to participate in consensus. Additionally, this leads to increased sync times for new nodes, which is particularly evident during weak subjectivity sync. This simplistic approach also prevents historical contract logs from being pruned from full nodes, a prospect frequently discussed in the context of limiting state growth.

## Specification

Consensus clients MAY continue to implement the deposit Merkle tree however they choose. However, when transmitting the tree to newly syncing nodes, clients MUST use the following format:

```python
class DepositTreeSnapshot:
    finalized: List[Hash32, DEPOSIT_CONTRACT_DEPTH]
    deposit_root: Hash32
    deposit_count: uint64
    execution_block_hash: Hash32
    execution_block_height: uint64
```

Where `finalized` is a variable-length list (of maximum size `DEPOSIT_CONTRACT_DEPTH`) containing the hashes defined in the [Deposit Finalization Flow](#deposit-finalization-flow) section below. The fields `deposit_root`, `deposit_count`, and `execution_block_hash` store the same information as the [`Eth1Data`](https://github.com/ethereum/consensus-specs/blob/2b45496fe48fa75450ad29a05bdd48866f86528a/specs/phase0/beacon-chain.md#eth1data) object that corresponds to the snapshot, and `execution_block_height` is the height of the execution block with hash `execution_block_hash`. Consensus clients MUST make this structure available via the Beacon Node API endpoint:

```
/eth/v1/beacon/deposit_snapshot
```

### Deposit Finalization Flow

During deposit processing, the beacon chain requires deposits to be submitted along with a Merkle path to the deposit root. This is required exactly once for each deposit. When a deposit has been processed by the beacon chain and the [deposit finalization conditions](#deposit-finalization-conditions) have been met, many of the hashes along the path to the deposit root will never be required again to construct Merkle proofs on chain. These unnecessary hashes MAY be pruned to save space. The image below illustrates the evolution of the deposit Merkle tree under this process alongside the corresponding `DepositTreeSnapshot` as new deposits are added and older deposits become finalized:

![deposit tree evolution](/EIPs/assets/eip-4881/deposit_tree_evolution.svg)

## Rationale

The format in this specification was chosen to achieve several goals simultaneously:

1. Enable reconstruction of the deposit contract Merkle tree without requiring full nodes to store all historical contract logs
2. Avoid requiring consensus nodes to retain more deposits than necessary to fully participate in consensus
3. Simplicity of implementation (see [Reference Implementation](#reference-implementation) section)
4. Increase speed of weak subjectivity sync
5. Compatibility with existing implementations of this mechanism (see discussion)

The proposed `DepositTreeSnapshot` structure includes both `execution_block_hash` and `execution_block_height` for convenience to consensus node implementors. While only one of these fields is strictly necessary, different clients may have already designed their block cache logic around one or the other. Sending only one of these would force some consensus clients to query the execution engine for the other information, but as this is happening in the context of a newly syncing consensus node, it is very likely that the execution engine will not be synced, especially post-merge. The `deposit_root` field is also not strictly necessary, but by including it, newly syncing consensus nodes can cheaply validate any received snapshot against itself (see the `calculate_root()` method in the [Reference Implementation](#reference-implementation)).

### Why not Reconstruct the Tree Directly from the Deposit Contract?

The deposit contract can only provide the tree at the head of the chain. Because the beacon chain&apos;s view of the deposit contract lags behind the execution chain by `ETH1_FOLLOW_DISTANCE`, there are almost always deposits which haven&apos;t yet been included in the chain that need proofs constructed from an earlier version of the tree than exists at the head.

### Why not Reconstruct the Tree from a Deposit in the Beacon Chain?

In principle, a node could scan backwards through the chain starting from the weak subjectivity checkpoint to locate a suitable [`Deposit`](https://github.com/ethereum/consensus-specs/blob/2b45496fe48fa75450ad29a05bdd48866f86528a/specs/phase0/beacon-chain.md#deposit), and then extract the rightmost branch of the tree from that. The node would also need to extract the `execution_block_hash` from which to start syncing new deposits from the `Eth1Data` in the corresponding `BeaconState`. This approach is less desirable for a few reasons:

* More difficult to implement due to the edge cases involved in finding a suitable deposit to anchor to (the rightmost branch of the latest not-yet-included deposit is required)
* This would make backfilling beacon blocks a requirement for reconstructing the deposit tree and therefore a requirement for block production
* This is inherently slower than getting this information from the weak subjectivity checkpoint

## Backwards Compatibility

This proposal is fully backwards compatible.

## Test Cases

Test cases are included in [test_cases.yaml](/EIPs/assets/eip-4881/test_cases.yaml). Each case is structured as follows:

```python
class DepositTestCase:
    deposit_data: DepositData     # These are all the inputs to the deposit contract&apos;s deposit() function
    deposit_data_root: Hash32     # The tree hash root of this deposit (calculated for convenience)
    eth1_data: Eth1Data           # An Eth1Data object that can be used to finalize the tree after pushing this deposit
    block_height: uint64          # The height of the execution block with this Eth1Data
    snapshot: DepositTreeSnapshot # The resulting DepositTreeSnapshot object if the tree were finalized after this deposit
```

This EIP also includes other files for testing:

* [deposit_snapshot.py](/EIPs/assets/eip-4881/deposit_snapshot.py) contains the same code as the [Reference Implementation](#reference-implementation)
* [eip_4881.py](/EIPs/assets/eip-4881/eip_4881.py) contains boilerplate declarations
* [test_deposit_snapshot.py](/EIPs/assets/eip-4881/test_deposit_snapshot.py) includes code for running test cases against the reference implementation

If these files are downloaded to the same directory, the test cases can be run by executing `pytest` in that directory.

## Reference Implementation

This implementation lacks full error checking and is optimized for readability over efficiency. If `tree` is a `DepositTree`, then the `DepositTreeSnapshot` can be obtained by calling `tree.get_snapshot()` and a new instance of the tree can be recovered from the snapshot by calling `DepositTree.from_snapshot()`. See the [Deposit Finalization Conditions](#deposit-finalization-conditions) section for discussion on when the tree can be pruned by calling `tree.finalize()`.

Generating proofs for deposits against an earlier version of the tree is relatively fast in this implementation; just create a copy of the finalized tree with `copy = DepositTree.from_snapshot(tree.get_snapshot())` and then append the remaining deposits to the desired count with `copy.push_leaf(deposit)`. Proofs can then be obtained with `copy.get_proof(index)`.

```python
from __future__ import annotations
from typing import List, Optional, Tuple
from dataclasses import dataclass
from abc import ABC,abstractmethod
from eip_4881 import DEPOSIT_CONTRACT_DEPTH,Hash32,sha256,to_le_bytes,zerohashes

@dataclass
class DepositTreeSnapshot:
    finalized: List[Hash32, DEPOSIT_CONTRACT_DEPTH]
    deposit_root: Hash32
    deposit_count: uint64
    execution_block_hash: Hash32
    execution_block_height: uint64

    def calculate_root(self) -&gt; Hash32:
        size = self.deposit_count
        index = len(self.finalized)
        root = zerohashes[0]
        for level in range(0, DEPOSIT_CONTRACT_DEPTH):
            if (size &amp; 1) == 1:
                index -= 1
                root = sha256(self.finalized[index] + root)
            else:
                root = sha256(root + zerohashes[level])
            size &gt;&gt;= 1
        return sha256(root + to_le_bytes(self.deposit_count))
    def from_tree_parts(finalized: List[Hash32],
                        deposit_count: uint64,
                        execution_block: Tuple[Hash32, uint64]) -&gt; DepositTreeSnapshot:
        snapshot = DepositTreeSnapshot(
            finalized, zerohashes[0], deposit_count, execution_block[0], execution_block[1])
        # A real implementation should store the deposit_root from the eth1_data passed to
        # DepositTree.finalize() instead of relying on calculate_root() here. This allows
        # the snapshot to be validated using calculate_root().
        snapshot.deposit_root = snapshot.calculate_root()
        return snapshot

@dataclass
class DepositTree:
    tree: MerkleTree
    mix_in_length: uint
    finalized_execution_block: Optional[Tuple[Hash32, uint64]]
    def new() -&gt; DepositTree:
        merkle = MerkleTree.create([], DEPOSIT_CONTRACT_DEPTH)
        return DepositTree(merkle, 0, None)
    def get_snapshot(self) -&gt; DepositTreeSnapshot:
        assert(self.finalized_execution_block is not None)
        finalized = []
        deposit_count = self.tree.get_finalized(finalized)
        return DepositTreeSnapshot.from_tree_parts(
            finalized, deposit_count, self.finalized_execution_block)
    def from_snapshot(snapshot: DepositTreeSnapshot) -&gt; DepositTree:
        # decent validation check on the snapshot
        assert(snapshot.deposit_root == snapshot.calculate_root())
        finalized_execution_block = (snapshot.execution_block_hash, snapshot.execution_block_height)
        tree = MerkleTree.from_snapshot_parts(
            snapshot.finalized, snapshot.deposit_count, DEPOSIT_CONTRACT_DEPTH)
        return DepositTree(tree, snapshot.deposit_count, finalized_execution_block)
    def finalize(self, eth1_data: Eth1Data, execution_block_height: uint64):
        self.finalized_execution_block = (eth1_data.block_hash, execution_block_height)
        self.tree.finalize(eth1_data.deposit_count, DEPOSIT_CONTRACT_DEPTH)
    def get_proof(self, index: uint) -&gt; Tuple[Hash32, List[Hash32]]:
        assert(self.mix_in_length &gt; 0)
        # ensure index &gt; finalized deposit index
        assert(index &gt; self.tree.get_finalized([]) - 1)
        leaf, proof = self.tree.generate_proof(index, DEPOSIT_CONTRACT_DEPTH)
        proof.append(to_le_bytes(self.mix_in_length))
        return leaf, proof
    def get_root(self) -&gt; Hash32:
        return sha256(self.tree.get_root() + to_le_bytes(self.mix_in_length))
    def push_leaf(self, leaf: Hash32):
        self.mix_in_length += 1
        self.tree = self.tree.push_leaf(leaf, DEPOSIT_CONTRACT_DEPTH)

class MerkleTree():
    @abstractmethod
    def get_root(self) -&gt; Hash32:
        pass
    @abstractmethod
    def is_full(self) -&gt; bool:
        pass
    @abstractmethod
    def push_leaf(self, leaf: Hash32, level: uint) -&gt; MerkleTree:
        pass
    @abstractmethod
    def finalize(self, deposits_to_finalize: uint, level: uint) -&gt; MerkleTree:
        pass
    @abstractmethod
    def get_finalized(self, result: List[Hash32]) -&gt; uint:
        # returns the number of finalized deposits in the tree
        # while populating result with the finalized hashes
        pass
    def create(leaves: List[Hash32], depth: uint) -&gt; MerkleTree:
        if not(leaves):
            return Zero(depth)
        if not(depth):
            return Leaf(leaves[0])
        split = min(2**(depth - 1), len(leaves))
        left = MerkleTree.create(leaves[0:split], depth - 1)
        right = MerkleTree.create(leaves[split:], depth - 1)
        return Node(left, right)
    def from_snapshot_parts(finalized: List[Hash32], deposits: uint, level: uint) -&gt; MerkleTree:
        if not(finalized) or not(deposits):
            # empty tree
            return Zero(level)
        if deposits == 2**level:
            return Finalized(deposits, finalized[0])
        left_subtree = 2**(level - 1)
        if deposits &lt;= left_subtree:
            left = MerkleTree.from_snapshot_parts(finalized, deposits, level - 1)
            right = Zero(level - 1)
            return Node(left, right)
        else:
            left = Finalized(left_subtree, finalized[0])
            right = MerkleTree.from_snapshot_parts(finalized[1:], deposits - left_subtree, level - 1)
            return Node(left, right)
    def generate_proof(self, index: uint, depth: uint) -&gt; Tuple[Hash32, List[Hash32]]:
        proof = []
        node = self
        while depth &gt; 0:
            ith_bit = (index &gt;&gt; (depth - 1)) &amp; 0x1
            if ith_bit == 1:
                proof.append(node.left.get_root())
                node = node.right
            else:
                proof.append(node.right.get_root())
                node = node.left
            depth -= 1
        proof.reverse()
        return node.get_root(), proof

@dataclass
class Finalized(MerkleTree):
    deposit_count: uint
    hash: Hash32
    def get_root(self) -&gt; Hash32:
        return self.hash
    def is_full(self) -&gt; bool:
        return True
    def finalize(self, deposits_to_finalize: uint, level: uint) -&gt; MerkleTree:
        return self
    def get_finalized(self, result: List[Hash32]) -&gt; uint:
        result.append(self.hash)
        return self.deposit_count

@dataclass
class Leaf(MerkleTree):
    hash: Hash32
    def get_root(self) -&gt; Hash32:
        return self.hash
    def is_full(self) -&gt; bool:
        return True
    def finalize(self, deposits_to_finalize: uint, level: uint) -&gt; MerkleTree:
        return Finalized(1, self.hash)
    def get_finalized(self, result: List[Hash32]) -&gt; uint:
        return 0

@dataclass
class Node(MerkleTree):
    left: MerkleTree
    right: MerkleTree
    def get_root(self) -&gt; Hash32:
        return sha256(self.left.get_root() + self.right.get_root())
    def is_full(self) -&gt; bool:
        return self.right.is_full()
    def push_leaf(self, leaf: Hash32, level: uint) -&gt; MerkleTree:
        if not(self.left.is_full()):
            self.left = self.left.push_leaf(leaf, level - 1)
        else:
            self.right = self.right.push_leaf(leaf, level - 1)
        return self
    def finalize(self, deposits_to_finalize: uint, level: uint) -&gt; MerkleTree:
        deposits = 2**level
        if deposits &lt;= deposits_to_finalize:
            return Finalized(deposits, self.get_root())
        self.left = self.left.finalize(deposits_to_finalize, level - 1)
        if deposits_to_finalize &gt; deposits / 2:
            remaining = deposits_to_finalize - deposits / 2
            self.right = self.right.finalize(remaining, level - 1)
        return self
    def get_finalized(self, result: List[Hash32]) -&gt; uint:
        return self.left.get_finalized(result) + self.right.get_finalized(result)

@dataclass
class Zero(MerkleTree):
    n: uint64
    def get_root(self) -&gt; Hash32:
        if self.n == DEPOSIT_CONTRACT_DEPTH:
            # Handle the entirely empty tree case. This is included for
            # consistency/clarity as the zerohashes array is typically
            # only defined from 0 to DEPOSIT_CONTRACT_DEPTH - 1.
            return sha256(zerohashes[self.n - 1] + zerohashes[self.n - 1])
        return zerohashes[self.n]
    def is_full(self) -&gt; bool:
        return False
    def push_leaf(self, leaf: Hash32, level: uint) -&gt; MerkleTree:
        return MerkleTree.create([leaf], level)
    def get_finalized(self, result: List[Hash32]) -&gt; uint:
        return 0
```

## Security Considerations

### Relying on Weak Subjectivity Sync

The upcoming switch to PoS will require newly synced nodes to rely on valid weak subjectivity checkpoints because of long-range attacks. This proposal relies on the weak subjectivity assumption that clients will not bootstrap with an invalid WS checkpoint.

### Deposit Finalization Conditions

Care must be taken not to send a snapshot which includes deposits that haven&apos;t been fully included in the finalized checkpoint. Let `state` be the [`BeaconState`](https://github.com/ethereum/consensus-specs/blob/2b45496fe48fa75450ad29a05bdd48866f86528a/specs/phase0/beacon-chain.md#beaconstate) at a given block in the chain. Under normal operation, the [`Eth1Data`](https://github.com/ethereum/consensus-specs/blob/2b45496fe48fa75450ad29a05bdd48866f86528a/specs/phase0/beacon-chain.md#eth1data) stored in `state.eth1_data` is replaced every `EPOCHS_PER_ETH1_VOTING_PERIOD` epochs. Thus, finalization of the deposit tree proceeds with increments of `state.eth1_data`. Let `eth1data` be some `Eth1Data`. Both of the following conditions MUST be met to consider `eth1data` finalized:

1. A finalized checkpoint exists where the corresponding `state` has `state.eth1_data == eth1data`
2. A finalized checkpoint exists where the corresponding `state` has `state.eth1_deposit_index &gt;= eth1data.deposit_count`

When these conditions are met, the tree can be pruned in the [reference implementation](#reference-implementation) by calling `tree.finalize(eth1data, execution_block_height)`

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 29 Jan 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4881</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4881</guid>
      </item>
    
      <item>
        <title>Composable SVG NFT</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4883-composable-svg-nft/8765</comments>
        
        <description>## Abstract

Compose an SVG (Scalable Vector Graphics) NFT by concatenating the SVG with the SVG of another NFT rendered as a string for a specific token ID.

## Motivation

Onchain SVG NFTs allow for NFTs to be entirely onchain by returning artwork as SVG in a data URI of the `tokenUri` function. Composability allows onchain SVG NFTs to be crafted. e.g. adding glasses &amp; hat NFTs to a profile pic NFT or a fish NFT to a fish tank NFT.

## Specification
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.

```solidity
/// @title EIP-4883 Non-Fungible Token Standard
interface IERC4883 {
    function renderTokenById(uint256 id) external view returns (string memory);
}
```

`renderTokenById` must return the SVG body for the specified token `id` and must either be an empty string or valid SVG element(s). 

## Rationale

SVG elements can be string concatenated to compose an SVG.

### Ordering of concatenation

SVG uses a &quot;painters model&quot; of rendering.  

**Scalable Vector Graphics (SVG) 1.1 (Second Edition)**, section: **3.3 Rendering Order**
&gt;Elements in an SVG document fragment have an implicit drawing order, with the first elements in the SVG document fragment getting &quot;painted&quot; first. Subsequent elements are painted on top of previously painted elements.

The ordering of the SVG concatenation determines the drawing order rather than any concept of a z-index.  

This EIP only specifies the rendering of the rendered SVG NFT and does not require any specific ordering when composing.  This allows the SVG NFT to use a rendered SVG NFT as a foreground or a background as required. 

### Alternatives to concatenation

SVG specifies a `link` tag.  Linking could allow for complex SVGs to be composed but would require creating a URI format and then getting ecosystem adoption.  As string concatenation of SVG&apos;s is already supported, the simpler approach of concatenation is used.  

### Sizing

This EIP doesn&apos;t specify any requirements on the size of the rendered SVG.  Any scaling based on sizing can be performed by the SVG NFT as required.

### Render function name

The render function is named `renderTokenById` as this function name was first used by Loogies and allows existing deployed NFTs to be compatible with this EIP.

## Backwards Compatibility
This EIP has no backwards compatibility concerns


## Security Considerations

- SVG uses a &quot;painters model&quot; of rendering. A rendered SVG body could be added and completely obscure the existing SVG NFT artwork.
- SVG is XML and can contain malicious content, and while it won&apos;t impact the contract, it could impact the use of the SVG.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 08 Mar 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4883</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4883</guid>
      </item>
    
      <item>
        <title>Subscription NFTs and Multi Tokens</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-subscription-token-standard/8531</comments>
        
        <description>## Abstract

The following standard allows for the implementation of a standard API for subscribing to non-fungible and multi tokens. [EIP-20](/EIPs/EIPS/eip-20) tokens are deposited in exchange for subscription tokens that give the right to use said non-fungible and multi tokens for a specified time limited or unlimited period.

## Motivation

This standard offers a flexible, general purpose way to subscribe to the use of assets or services offered by [EIP-721](/EIPs/EIPS/eip-721) or [EIP-1155](/EIPs/EIPS/eip-1155) contracts. From here on in, for the sake of simplicity, these contracts will be known as NFTs; the provider is the issuer of said NFTs and the subscriber(s) uses them.

This proposal was originally conceived from the want to give creators of music and film, back control. The distribution and delivery of digital content is currently the purview of centralised tech corporations who offer homogeneous subscription models to their customers. This proposal specifies a standard for dapp developers to give creators the ability to set their own custom subscription models and hence, open up new revenue streams that can lead to decentralised distribution and delivery models.

Use cases include any sort of periodic (e.g. daily, weekly, monthly, quarterly, yearly/annual, or seasonal) use of or access to assets or services such as:

- Subscriptions for streaming music, video, e-learning or book/news services
- Sharing of digital assets among subscribers
- Club memberships such as health clubs
- Season tickets for sports and e-sports
- Agreement between parties to exchange fixed rate subscription stream with variable income in DeFi
- Renting in-game assets
- Etc.

The subscription token borrows a few functions from the EIP-20 specification. An implementer is free to implement the rest of the standard; allowing for example subscription tokens to be transferred in secondary markets, sent as gifts or for refunds etc.

## Specification

The subscriber deposits EIP-20 to receive an NFT and subscription. Subscription tokens balance automatically decreases linearly over the lifetime of usage of the NFT, and use of the NFT is disabled once the subscription token balance falls to zero. The subscriber can top up the balance to extend the lifetime of the subscription by depositing EIP-20 tokens in exchange for more subscription tokens.

Smart contracts implementing this EIP standard MUST implement the [EIP-165](/EIPs/EIPS/eip-165) supportsInterface function and MUST return the constant value true if 0xC1A48422 is passed through the interfaceID argument. Note that revert in this document MAY mean a require, throw (not recommended as depreciated) or revert solidity statement with or without error messages.

```solidity
interface ISubscriptionToken {
    /**
        @dev This emits when the subscription token constructor or initialize method is
        executed.
        @param name The name of the subscription token
        @param symbol The symbol of the subscription token
        @param provider The provider of the subscription whom receives the deposits
        @param subscriptionToken The subscription token contract address
        @param baseToken The ERC-20 compatible token to use for the deposits.
        @param nft Address of the `nft` contract that the provider mints/transfers from.
        All tokenIds referred to in this interface MUST be token instances of this `nft` contract.
    */
    event InitializeSubscriptionToken(
        string name,
        string symbol,
        address provider,
        address indexed subscriptionToken,
        address indexed baseToken,
        address indexed nft,
        string uri
    );

    /**
        @dev This emits for every new subscriber to `nft` contract of token `tokenId`.
        `subscriber` MUST have received `nft` of token `tokenId` in their account.
        @param subscriber The subscriber account
        @param tokenId MUST be token id of `nft` sent to `subscriber`
        @param uri MUST be uri of the `nft` that was sent to `subscriber` or empty string
    */
    event SubscribeToNFT(
        address indexed subscriber,
        uint256 indexed tokenId,
        string uri
    );

    /**
        @dev Emits when `subscriber` deposits ERC-20 of token type `baseToken` via the `deposit method.
        This tops up `subscriber` balance of subscription tokens
        @param depositAmount The amount of ERC-20 of type `baseToken` deposited
        @param subscriptionTokenAmount The amount of subscription tokens sent in exchange to `subscriber`
        @param subscriptionPeriod Amount of additional time in seconds subscription is extended
    */
    event Deposit(
        address indexed subscriber,
        uint256 indexed tokenId,
        uint256 depositAmount,
        uint256 subscriptionTokenAmount,
        uint256 subscriptionPeriod
    );

    /**
        @return The name of the subscription token
    */
    function name() external view returns (string memory);

    /**
        @return The symbol of the subscription token
    */
    function symbol() external view returns (string memory);

    /**
        @notice Subscribes `subscriber` to `nft` of &apos;tokenId&apos;. `subscriber` MUST receive `nft`
        of token `tokenId` in their account.
        @dev MUST revert if `subscriber` is already subscribed to `nft` of &apos;tokenId&apos;
        MUST revert if &apos;nft&apos; has not approved the `subscriptionToken` contract address as operator.
        @param subscriber The subscriber account. MUST revert if zero address.
        @param tokenId MUST be token id of `nft` contract sent to `subscriber`
        `tokenId` emitted from event `SubscribeToNFT` MUST be the same as tokenId except when
        tokenId is zero; allows OPTIONAL tokenid that is then set internally and minted by
        `nft` contract
        @param uri The OPTIONAL uri of the `nft`.
        `uri` emitted from event `SubscribeToNFT` MUST be the same as uri except when uri is empty.
    */
    function subscribeToNFT(
        address subscriber,
        uint256 tokenId,
        string memory uri
    ) external;

    /**
        @notice Top up balance of subscription tokens held by `subscriber`
        @dev MUST revert if `subscriber` is not subscribed to `nft` of &apos;tokenId&apos;
        MUST revert if &apos;nft&apos; has not approved the `subscriptionToken` contract address as operator.
        @param subscriber The subscriber account. MUST revert if zero address.
        @param tokenId The token id of `nft` contract to subscribe to
        @param depositAmount The amount of ERC-20 token of contract address `baseToken` to deposit
        in exchange for subscription tokens of contract address `subscriptionToken`
    */
    function deposit(
        address subscriber,
        uint256 tokenId,
        uint256 depositAmount
    ) external payable;

    /**
        @return The balance of subscription tokens held by `subscriber`.
        RECOMMENDED that the balance decreases linearly to zero for time limited subscriptions
        RECOMMENDED that the balance remains the same for life long subscriptions
        MUST return zero balance if the `subscriber` does not hold `nft` of &apos;tokenId&apos;
        MUST revert if subscription has not yet started via the `deposit` function
        When the balance is zero, the use of `nft` of `tokenId` MUST NOT be allowed for `subscriber`
    */
    function balanceOf(address subscriber) external view returns (uint256);
}
```

### Subscription token balances

An example implementation mints an amount of subscription token that totals to one subscription token per day of the subscription period length paid for by the subscriber; for example a week would be for seven subscription tokens. The subscription token balance then decreases automatically at a rate of one token per day continuously and linearly over time until zero. The `balanceOf` function can be implemented lazily by calculating the amount of subscription tokens left only when it is called as a view function, thus has no gas cost.

### Subscription token price

Subscription token price paid per token per second can be calculated from the `Deposit` event parameters as
`depositAmount` / (`subscriptionTokenAmount` \* `subscriptionPeriod`)

### NFT metadata

The NFT&apos;s metadata can store information of the asset/service offered to the subscriber by the provider for the duration of the subscription. This MAY be the terms and conditions of the agreed subscription service offered by the provider to the subscriber. It MAY also be the metadata of the NFT asset if this is offered directly. This standard is kept purposely general to cater for many different use cases of NFTs.

### Subscription expiry

When the subscription token balance falls to zero for a subscriber (signifying that the subscription has expired) then it is up to the implementer on how to handle this for their particular use case. For example, a provider may stop streaming media service to a subscriber. For an NFT that represents an image stored off-chain, perhaps the NFT&apos;s `uri` function no longer returns back a link to its metadata.

### Caveats

With some traditional subscription models based on fiat currencies, the subscribers&apos; saved payment credentials are used to automatically purchase to extend the subscription period, at or just before expiry. This feature is not possible in this proposal specification as recurring payments will have to have allowance approved for signed by a subscriber for each payment when using purely cryptocurrencies.

This proposal does not deal with pausing subscriptions directly, implementers can write their own or inherit off 3rd party smart contract abstractions such as OpenZeppelin&apos;s Pausable. In that case, `balanceOf` method would need extra logic and storage to account for the length of time the subscription tokens were paused.

## Rationale

### Tokenisation of subscriptions

The subscription itself has value when it is exchanged for a deposit. This proposal enables subscriptions to be &apos;tokenised&apos; thus secondary markets can exist where the subscription tokens can be bought and sold. For example, a fan might want to sell their season ticket, that gives access to live sporting events, on to another fan. This would not be as easily possible if there was only a date expiry extension feature added to NFTs.
An implementer can simply implement the rest of the EIP-20 functions for subscription tokens to be traded. It is left to the implementer to decide if the subscription service offered is non-fungible or fungible. If non-fungible then buying the subscription tokens would simply give the same period left to expiration. If fungible and the purchaser already had an existing subscription for the same service then their total subscription period can be extended by the amount of subscription tokens bought.

### Cater for current and future uses of NFTs

This proposal purposely keeps `tokenId` and `uri` optional in the `subcribeToNFT` method to keep the specification general purpose. Some use cases such as pre-computed image NFT collections don&apos;t require a different &apos;uri&apos;, just a different `tokenId` for each NFT. However, in other use cases such as those that require legal contracts between both parties, individual `uri` links are probably required as the NFT&apos;s metadata may require information from both parties to be stored on immutable storage.

### Giving back users control

Traditional subscription models, particularly with streaming services, control of the subscription model is totally with that of the central service provider. This proposal gives decentralised services a standard way to give control back to their users. Hence each user is able to develop their own subscription eco system and administer it towards one that suits theirs and their subscribers&apos; needs.

## Backwards Compatibility

A subscription token contract can be fully compatible with EIP-20 specification to allow, for example, transfers from one subscriber to another subscriber or user. EIP-20 methods `name`, `symbol` and `balanceOf` are already part of the specification of this proposal, and it is left to the implementer to choose whether to implement the rest of EIP-20&apos;s interface by considering their own use case.

Use of subscription tokens is in effect an indirect way to control the lifetime of an NFT. As such it is assumed that this arrangement would work best when the NFTs and subscription token contracts subscribing to the NFTs, are deployed by the same platform or decentralised app. It MUST NOT have an impact or dependencies to existing NFTs that have not approved the subscription token as an operator. Indeed in this case, any other parties wouldn&apos;t be aware of and any NFT lifetime dependencies will be ignored, hence should not work anyway. To this end, this proposal specifies that the &apos;nft&apos; MUST have approved the `subscriptionToken` contract address as operator.

## Security Considerations

It is normal for service providers to receive subscriber payments upfront before the subscriber gets to use the service. Indeed this proposal via the `deposit` method follows this remit. It would therefore be possible that a service provider sets up, receives the deposits and then does not provide or provides the service poorly to its subscribers. This happens in the traditional world too and this proposal does not cover how to resolve this.

The `subscribeToNFT` method takes a parameter `uri` link to the `nft` metadata. It is possible if stored on centralised storage that the owners can change the metadata, or perhaps the metadata is hacked which is an issue with vanilla NFT contracts too. But because the `uri` is provided at the time of subscription rather then deployment, it is RECOMMENDED that where the use case requires, implementers ensure that the `uri` link is to immutable storage.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 08 Mar 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4885</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4885</guid>
      </item>
    
      <item>
        <title>Proxy Ownership Register</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4886-a-proxy-ownership-and-asset-delivery-register/8559</comments>
        
        <description>## Abstract

A proxy protocol that allows users to nominate a proxy address to act on behalf of another wallet address, together with a delivery address for new assets. Smart contracts and applications making use of the protocol can take a proxy address and lookup holding information for the nominator address. This has a number of practical applications, including allowing users to store valuable assets safely in a cold wallet and interact with smart contracts using a proxy address of low value. The assets in the nominator are protected as all contract interactions take place with the proxy address. This eliminates a number of exploits seen recently where users&apos; assets are drained through a malicious contract interaction. In addition, the register holds a delivery address, allowing new assets to be delivered directly to a cold wallet address.

## Motivation

To make full use of Ethereum users often need to prove their ownership of existing assets. For example:
 * Discord communities require users to sign a message with their wallet to prove they hold the tokens or NFTs of that community.
 * Whitelist events (for example recent airdrops, or NFT mints), require the user to interact using a given address to prove eligibility.
 * Voting in DAOs and other protocols require the user to sign using the address that holds the relevant assets.

 There are more examples, with the unifying theme being that the user must make use of the address with the assets to derive the platform benefit. This means the addresses holding these assets cannot be truly &apos;cold&apos;, and is a gift to malicious developers seeking to steal valuable assets. For example, a new project can offer free NFTs to holders of an existing NFT asset. The existing holders have to prove ownership by minting from the wallet with the asset that determined eligibility. This presents numerous possible attack vectors for a malicious developer who knows that all users interacting with the contract have an asset of that type.

 Possibly even more damaging is the effect on user confidence across the whole ecosystem. Users become reluctant to interact with apps and smart contracts for fear of putting their assets at risk. They may also decide not to store assets in cold wallet addresses as they need to prove they own them on a regular basis. A pertinent example is the user trying to decide whether to &apos;vault&apos; their NFT and lose access to a discord channel, or keep their NFT in another wallet, or even to connect their &apos;vault&apos; to discord.

 Ethereum is amazing at providing trustless proofs. The *only* time a user should need to interact using the wallet that holds an asset is if they intend to sell or transfer that asset. If a user merely wishes to prove ownership (to access a resource, get an airdrop, mint an NFT, or vote in a DAO), they should do this through a trustless proof stored on-chain.

 Furthermore, users should be able to decide where new assets are delivered, rather than them being delivered to the wallet providing the interaction. This allows hot wallets to acquire assets sent directly to a cold wallet &apos;vault&apos;, possibly even the one they are representing in terms of asset ownership.

 The aim of this EIP is to provide a convenient method to avoid this security concern and empower more people to feel confident leveraging the full scope of Ethereum functionality. Our vision is an Ethereum where users setup a new hardware wallet for assets they wish to hold long-term, then make one single contract interaction with that wallet: to nominate a hot wallet proxy. That user can always prove they own assets on that address, and they can specify it as a delivery address for new asset delivery.

## Specification

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.

### Definitions

 * Delivery address: The address that assets will be delivered to for the current Proxy Record, i.e. a new NFT minted by the Proxy address, representing the Nominator address, should be delivered to the Delivery address.
 * Nomination: Where a Nominator has nominated a Proxy address. Will only be active when the Proxy has accepted the nomination.
 * Nominator address: The address that proposes a proxy relationship. This address nominates another address to act as its proxy, representing it and its holdings in all interactions.
 * Proxy address: The address that will represent a Nominator on-chain.
 * Proxy Record: An active proxy relationship encompassing a Nominator, Proxy and Delivery.
 * Register: The main EPS contract, which holds details of both Nominations and Proxy Records.

### EPS Specification 

There are two main parts to the register - a nomination and a proxy record:

    Contract / Dapp                        Register

    Nominator: 0x1234..             Nominator: 0x1234..
    Proxy: 0x5678..     ---------&gt;  Proxy: 0x4567..
                                    Delivery: 0x9876..

The first step to creating a proxy record is for an address to nominate another address as its proxy. This creates a nomination that maps the nominator (the address making the nomination) to the proposed proxy address. 

This is not a proxy record on the register at this stage, as the proxy address needs to first accept the nomination. Until the nomination is accepted it can be considered to be pending. Once the proxy address has accepted the nomination a proxy record is added to the register.

When accepting a nomination the proxy address sets the delivery address for that proxy record. The proxy address remains in control of updating that delivery address as required. Both the nominator and proxy can delete the proxy record and nomination at any time. The proxy will continue forever if not deleted - it is eternal.

The register is a single smart contract that stores all nomination and register records. The information held for each is as follows:
 * Nomination:
    * The address of the Nominator
    * The address of the Proposed Proxy

* Proxy Record:
    * The address of the Nominator
    * The address of the Proxy
    * The delivery address for proxied deliveries

Any address can act as a Nominator or a Proxy. A Nomination must have been made first in order for an address to accept acting as a Proxy. 

A Nomination cannot be made to an address that is already active as either a Proxy or a Nominator, i.e. that address is already in an active proxy relationship.

The information for both Nominations and Proxy records is held as a mapping. For the Nomination this is address =&gt; address for the Nominator to the Proxy address. For the Proxy Record the mapping is from address =&gt; struct for the Proxy Address to a struct containing the Nominator and Delivery address.

Mapping between an address and its Nominator and Delivery address is a simple process as shown below:

    Contract / Dapp                        Register

      |                                       |
      |------------- 0x4567..---------------&gt; |
      |                                       |
      | &lt;-------nominator: 0x1234..---------- |
      |         delivery: 0x9876..            |
      |                                       |

The protocol is fully backwards compatible. If it is passed an address that does not have an active mapping it will pass back the received address as both the Nominator and Delivery address, thereby preserving functionality as the address is acting on its own behalf.

    Contract / Dapp                        Register

      |                                       |
      |------------- 0x0222..---------------&gt; |
      |                                       |
      | &lt;-------nominator: 0x0222..---------- |
      |         delivery: 0x0222..            |
      |                                       |

If the EPS register is passed the address of a Nominator it will revert. This is of vital importance. The purpose of the proxy is that the Proxy address is operating on behalf of the Nominator. The Proxy address therefore can derive the same benefits as the Nominator (for example discord roles based on the Nominator&apos;s holdings, or mint NFTs that require another NFT to be held). It is therefore imperative that the Nominator in an active proxy cannot also interact and derive these benefits, otherwise two addresses represent the same holding. A Nominator can of course delete the Proxy Record at any time and interact on it&apos;s own behalf, with the Proxy address instantly losing any benefits associated with the proxy relationship.

### Solidity Interface Definition

**Nomination Exists**

    function nominationExists(address _nominator) external view returns (bool);

Returns true if a Nomination exists for the address specified.

**Nomination Exists for Caller**

    function nominationExistsForCaller() external view returns (bool);

Returns true if a Nomination exists for the msg.sender.

**Proxy Record Exists**

    function proxyRecordExists(address _proxy) external view returns (bool);

Returns true if a Proxy Record exists for the passed Proxy address.

**Proxy Record Exists for Caller**

    function proxyRecordExistsForCaller() external view returns (bool);

Returns true if a Proxy Record exists for the msg.sender.

**Nominator Record Exists**

    function nominatorRecordExists(address _nominator) external view returns (bool);

Returns true if a Proxy Record exists for the passed Nominator address.

**Nominator Record Exists for Caller**

    function nominatorRecordExistsForCaller() external view returns (bool);

Returns true if a Proxy Record exists for the msg.sender.

**Get Proxy Record**

    function getProxyRecord(address _proxy) external view returns (address nominator, address proxy, address delivery);

Returns Nominator, Proxy and Delivery address for a passed Proxy address.

**Get Proxy Record for Caller**

    function getProxyRecordForCaller() external view returns (address nominator, address proxy, address delivery);

Returns Nominator, Proxy and Delivery address for msg.sender as Proxy address.

**Get Nominator Record**

    function getNominatorRecord(address _nominator) external view returns (address nominator, address proxy, address delivery);

Returns Nominator, Proxy and Delivery address for a passed Nominator address.

**Get Nominator Record for Caller**

    function getNominatorRecordForCaller() external view returns (address nominator, address proxy, address delivery);

Returns Nominator, Proxy and Delivery address for msg.sender address as Nominator.

**Address Is Active**

    function addressIsActive(address _receivedAddress) external view returns (bool);

Returns true if the passed address is Nominator or Proxy address on an active Proxy Record.

**Address Is Active for Caller**

    function addressIsActiveForCaller() external view returns (bool);

Returns true if msg.sender is Nominator or Proxy address on an active Proxy Record.

**Get Nomination**

function getNomination(address _nominator) external view returns (address proxy);

Returns the proxy address for a Nomination when passed a Nominator.

**Get Nomination for Caller**

function getNominationForCaller() external view returns (address proxy);

Returns the proxy address for a Nomination if msg.sender is a Nominator

**Get Addresses**

    function getAddresses(address _receivedAddress) external view returns (address nominator, address delivery, bool isProxied);

Returns the Nominator, Proxy, Delivery and a boolean isProxied for the passed address. If you pass an address that is not a Proxy address it will return address(0) for the Nominator, Proxy and Delivery address and isProxied of false. If you pass an address that is a Proxy address it will return the relvant addresses and isProxied of true.

**Get Addresses for Caller**

    function getAddressesForCaller() external view returns (address nominator, address delivery, bool isProxied);

Returns the Nominator, Proxy, Delivery and a boolean isProxied for msg.sender. If msg.sender is not a Proxy address it will return address(0) for the Nominator, Proxy and Delivery address and isProxied of false. If msg.sender is a Proxy address it will return the relvant addresses and isProxied of true.

**Get Role**

    function getRole(address _roleAddress) external view returns (string memory currentRole);

Returns a string value with a role for the passed address. Possible roles are:

None The address does not appear on the Register as either a Record or a Nomination.

Nominator - Pending The address is the Nominator on a Nomination which has yet to be accepted by the nominated Proxy address.

Nominator - Active The address is a Nominator on an active Proxy Record (i.e. the Nomination has been accepted).

Proxy - Active The address is a Proxy on an active Proxy Record.

**Get Role for Caller**

    function getRoleForCaller() external view returns (string memory currentRole);

Returns a string value with a role for msg.sender. Possible roles are:

None The msg.sender does not appear on the Register as either a Record or a Nomination.

Nominator - Pending The msg.sender is the Nominator on a Nomination which has yet to be accepted by the nominated Proxy address.

Nominator - Active The msg.sender is a Nominator on an active Proxy Record (i.e. the Nomination has been accepted).

Proxy - Active The msg.sender is a Proxy on an active Proxy Record.

**Make Nomination**

    function makeNomination(address _proxy, uint256 _provider) external payable;

Can be passed a Proxy address to create a Nomination for the msg.sender.

Provider is a required argument. If you do not have a Provider ID you can pass 0 as the default EPS provider. For details on the EPS Provider Program please see .

**Accept Nomination**

    function acceptNomination(address _nominator, address _delivery, uint256 _provider) external;

Can be passed a Nominator and Delivery address to accept a Nomination for a msg.sender. Note that to accept a Nomination the Nomination needs to exists with the msg.sender as the Proxy. The Nominator passed to the function and that on the Nomination must match.

Provider is a required argument. If you do not have a Provider ID you can pass 0 as the default EPS provider. For details on the EPS Provider Program please see .

**Update Delivery Record**

    function updateDeliveryAddress(address _delivery, uint256 _provider) external;

Can be passed a new Delivery address where the msg.sender is the Proxy on a Proxy Record.

Provider is a required argument. If you do not have a Provider ID you can pass 0 as the default EPS provider. For details on the EPS Provider Program please see .

**Delete Record by Nominator**

    function deleteRecordByNominator(uint256 _provider) external;

Can be called to delete a Record and Nomination when the msg.sender is a Nominator.

Note that when both a Record and Nomination exist both are deleted. If no Record exists (i.e. the Nomination hasn&apos;t been accepted by the Proxy address) the Nomination is deleted.

Provider is a required argument. If you do not have a Provider ID you can pass 0 as the default EPS provider. For details on the EPS Provider Program please see .

**Delete Record by Proxy**

    function deleteRecordByProxy(uint256 _provider) external;

Can be called to delete a Record and Nomination when the msg.sender is a Proxy.

## Rationale

The rationale for this EIP was to provide a way for all existing and future Ethereum assets to be have a &apos;beneficial owner&apos; (the proxy) that is different to the address custodying the asset. The use of a register to achieve this ensures that changes to existing tokens are not required. The register stores a trustless proof, signed by both the nominator and proxy, that can be relied upon as a true representation of asset ownership.

## Backwards Compatibility

The EIP is fully backwards compatible.

## Test Cases

The full SDLC for this proposal has been completed and it is operation at 0xfa3D2d059E9c0d348dB185B32581ded8E8243924 on mainnet, ropsten and rinkeby. The contract source code is validated and available on etherscan. The full unit test suite is available in `../assets/eip-4886/`, as is the source code and example implementations.

## Reference Implementation

Please see `../assets/eip-4886/contracts`

## Security Considerations

The core intention of the EIP is to improve user security by better safeguarding assets and allowing greater use of cold wallet storage. 

Potential negative security implications have been considered and none are envisaged. The proxy record can only become operational when a nomination has been confirmed by a proxy address, both addresses therefore having provided signed proof. 

From a usability perspective the key risk is in users specifying the incorrect asset delivery address, though it is noted that this burden of accuracy is no different to that currently on the network.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 03 Sep 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4886</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4886</guid>
      </item>
    
      <item>
        <title>Beacon chain push withdrawals as operations</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4895-beacon-chain-withdrawals-as-system-level-operations/8568</comments>
        
        <description>## Abstract

Introduce a system-level &quot;operation&quot; to support validator withdrawals that are &quot;pushed&quot; from the beacon chain to the EVM.

These operations create unconditional balance increases to the specified recipients.

## Motivation

This EIP provides a way for validator withdrawals made on the beacon chain to enter into the EVM.
The architecture is &quot;push&quot;-based, rather than &quot;pull&quot;-based, where withdrawals are required to be processed in the execution layer as soon as they are dequeued from the consensus layer.

Withdrawals are represented as a new type of object in the execution payload -- an &quot;operation&quot; -- that separates the withdrawals feature from user-level transactions.
This approach is more involved than the prior approach introducing a new transaction type but it cleanly separates this &quot;system-level&quot; operation from regular transactions.
The separation simplifies testing (so facilitates security) by reducing interaction effects generated by mixing this system-level concern with user data.

Moreover, this approach is more complex than &quot;pull&quot;-based alternatives with respect to the core protocol but does provide tighter integration of a critical feature into the protocol itself.

## Specification

| constants                     | value                                          | units
|---                            |---                                             |---
| `FORK_TIMESTAMP`              | 1681338455                                     |

Beginning with the execution timestamp `FORK_TIMESTAMP`, execution clients **MUST** introduce the following extensions to payload validation and processing:

### System-level operation: withdrawal

Define a new payload-level object called a `withdrawal` that describes withdrawals that have been validated at the consensus layer.
`Withdrawal`s are syntactically similar to a user-level transaction but live in a different domain than user-level transactions.

`Withdrawal`s provide key information from the consensus layer:

1. a monotonically increasing `index`, starting from 0, as a `uint64` value that increments by 1 per withdrawal to uniquely identify each withdrawal
2. the `validator_index` of the validator, as a `uint64` value, on the consensus layer the withdrawal corresponds to
3. a recipient for the withdrawn ether `address` as a 20-byte value
4. a nonzero `amount` of ether given in Gwei (1e9 wei) as a `uint64` value.

*NOTE*: the `index` for each withdrawal is a global counter spanning the entire sequence of withdrawals.

`Withdrawal` objects are serialized as a RLP list according to the schema: `[index, validator_index, address, amount]`.

### New field in the execution payload: withdrawals

The execution payload gains a new field for the `withdrawals` which is an RLP list of `Withdrawal` data.

For example:

```python
withdrawal_0 = [index_0, validator_index_0, address_0, amount_0]
withdrawal_1 = [index_1, validator_index_1, address_1, amount_1]
withdrawals = [withdrawal_0, withdrawal_1]
```

This new field is encoded after the existing fields in the execution payload structure and is considered part of the execution payload&apos;s body.

```python
execution_payload_rlp = RLP([header, transactions, [], withdrawals])

execution_payload_body_rlp = RLP([transactions, [], withdrawals])
```

NOTE: the empty list in this schema is due to [EIP-3675](/EIPs/EIPS/eip-3675) that sets the `ommers` value to a fixed constant.

### New field in the execution payload header: withdrawals root

The execution payload header gains a new field committing to the `withdrawals` in the execution payload.

This commitment is constructed identically to the transactions root in the existing execution payload header by inserting
each withdrawal into a Merkle-Patricia trie keyed by index in the list of `withdrawals`.

```python
def compute_trie_root_from_indexed_data(data):
    trie = Trie.from([(i, obj) for i, obj in enumerate(data)])
    return trie.root

execution_payload_header.withdrawals_root = compute_trie_root_from_indexed_data(execution_payload.withdrawals)
```

The execution payload header is extended with a new field containing the 32 byte root of the trie committing to the list of withdrawals provided in a given execution payload.

To illustrate:

```python
execution_payload_header_rlp = RLP([
  parent_hash,
  0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347, # ommers hash
  coinbase,
  state_root,
  txs_root,
  receipts_root,
  logs_bloom,
  0, # difficulty
  number,
  gas_limit,
  gas_used,
  timestamp,
  extradata,
  prev_randao,
  0x0000000000000000, # nonce
  base_fee_per_gas,
  withdrawals_root,
])
```

NOTE: field names and constant value in this example reflect [EIP-3675](/EIPs/EIPS/eip-3675) and [EIP-4399](/EIPs/EIPS/eip-4399). Refer to those EIPs for further information.

### Execution payload validity

Assuming the execution payload is well-formatted, the execution client has an additional payload validation to ensure that the `withdrawals_root` matches the expected value given the list in the payload.

```python
assert execution_payload_header.withdrawals_root == compute_trie_root_from_indexed_data(execution_payload.withdrawals)
```

### State transition

The `withdrawals` in an execution payload are processed **after** any user-level transactions are applied.

For each `withdrawal` in the list of `execution_payload.withdrawals`, the implementation increases the balance of the `address` specified by the `amount` given.

Recall that the `amount` is given in units of Gwei so a conversion to units of wei must be performed when working with account balances in the execution state.

This balance change is unconditional and **MUST** not fail.

This operation has no associated gas costs.

## Rationale

### Why not a new transaction type?

This EIP suggests a new type of object -- the &quot;withdrawal operation&quot; -- as it has special semantics different from other existing types of EVM transactions.

Operations are initiated by the overall system, rather than originating from end users like typical transactions.

An entirely new type of object firewalls off generic EVM execution from this type of processing to simplify testing and security review of withdrawals.

### Why no (gas) costs for the withdrawal type?

The maximum number of withdrawals that can reach the execution layer at a given time is bounded (enforced by the consensus layer) and this limit has been chosen so that
any execution layer operational costs are negligible in the context of the broader payload execution.

This bound applies to both computational cost (only a few balance updates in the state) and storage/networking cost as the additional payload footprint is kept small (current parameterizations put the additional overhead at ~1% of current average payload size).

### Why only balance updates? No general EVM execution?

More general processing introduces the risk of failures, which complicates accounting on the beacon chain.

This EIP suggests a route for withdrawals that provides most of the benefits for a minimum of the (complexity) cost.

## Backwards Compatibility

No issues.

## Security Considerations

Consensus-layer validation of withdrawal transactions is critical to ensure that the proper amount of ETH is withdrawn back into the execution layer.
This consensus-layer to execution-layer ETH transfer does not have a current analog in the EVM and thus deserves very high security scrutiny.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 10 Mar 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4895</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4895</guid>
      </item>
    
      <item>
        <title>EIP-721 Metadata Update Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip4906-erc-721-erc-1155-metadata-update-extension/8588</comments>
        
        <description>## Abstract

This standard is an extension of [EIP-721](/EIPs/EIPS/eip-721). It adds a `MetadataUpdate` event to EIP-721 tokens.

## Motivation

Many [EIP-721](/EIPs/EIPS/eip-721) contracts emit an event when one of its tokens&apos; metadata are changed. While tracking changes based on these different events is possible, it is an extra effort for third-party platforms, such as an NFT marketplace, to build individualized solutions for each NFT collection.

Having a standard `MetadataUpdate` event will make it easy for third-party platforms to timely update the metadata of many NFTs.

## Specification

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.

The **metadata update extension** is OPTIONAL for EIP-721 contracts.


```solidity
/// @title EIP-721 Metadata Update Extension
interface IERC4906 is IERC165, IERC721 {
    /// @dev This event emits when the metadata of a token is changed.
    /// So that the third-party platforms such as NFT market could
    /// timely update the images and related attributes of the NFT.
    event MetadataUpdate(uint256 _tokenId);

    /// @dev This event emits when the metadata of a range of tokens is changed.
    /// So that the third-party platforms such as NFT market could
    /// timely update the images and related attributes of the NFTs.    
    event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId);
}
```

The `MetadataUpdate` or `BatchMetadataUpdate` event MUST be emitted when the JSON metadata of a token, or a consecutive range of tokens, is changed.

Not emitting `MetadataUpdate` event is RECOMMENDED when a token is minted.

Not emitting `MetadataUpdate` event is RECOMMENDED  when a token is burned.

Not emitting `MetadataUpdate` event is RECOMMENDED  when the tokenURI changes but the JSON metadata does not.

The `supportsInterface` method MUST return `true` when called with `0x49064906`.

## Rationale

Different NFTs have different metadata, and metadata generally has multiple fields. `bytes data` could be used to represents the modified value of metadata.  It is difficult for third-party platforms to identify various types of `bytes data`, so as to avoid unnecessary complexity, arbitrary metadata is not included in the `MetadataUpdate` event.

After capturing the `MetadataUpdate` event, a third party can update the metadata with information returned from the `tokenURI(uint256 _tokenId)` of EIP-721. When a range of token ids is specified, the third party can query each token URI individually.

## Backwards Compatibility

No backwards compatibility issues were found

## Reference Implementation

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;
import &quot;./IERC4906.sol&quot;;

contract ERC4906 is ERC721, IERC4906 {

    constructor(string memory name_, string memory symbol_) ERC721(name_, symbol_) {
    }

    /// @dev See {IERC165-supportsInterface}.
    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
        return interfaceId == bytes4(0x49064906) || super.supportsInterface(interfaceId);
    }
}
```

## Security Considerations

If there is an off-chain modification of metadata, a method that triggers `MetadataUpdate` can be added, but ensure that the function&apos;s permission controls are correct.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 13 Mar 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4906</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4906</guid>
      </item>
    
      <item>
        <title>Rental NFT, an Extension of EIP-721</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/idea-erc-721-user-and-expires-extension/8572</comments>
        
        <description>## Abstract

This standard is an extension of [EIP-721](/EIPs/EIPS/eip-721). It proposes an additional role (`user`) which can be granted to addresses, and a time where the role is automatically revoked (`expires`). The `user` role represents permission to &quot;use&quot; the NFT, but not the ability to transfer it or set users.

## Motivation

Some NFTs have certain utilities. For example, virtual land can be &quot;used&quot; to build scenes, and NFTs representing game assets can be &quot;used&quot; in-game. In some cases, the owner and user may not always be the same. There may be an owner of the NFT that rents it out to a “user”. The actions that a “user” should be able to take with an NFT would be different from the “owner” (for instance, “users” usually shouldn’t be able to sell ownership of the NFT).  In these situations, it makes sense to have separate roles that identify whether an address represents an “owner” or a “user” and manage permissions to perform actions accordingly.

Some projects already use this design scheme under different names such as “operator” or “controller” but as it becomes more and more prevalent, we need a unified standard to facilitate collaboration amongst all applications.

Furthermore, applications of this model (such as renting) often demand that user addresses have only temporary access to using the NFT. Normally, this means the owner needs to submit two on-chain transactions, one to list a new address as the new user role at the start of the duration and one to reclaim the user role at the end. This is inefficient in both labor and gas and so an “expires” function is introduced that would facilitate the automatic end of a usage term without the need of a second transaction.

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot; and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### Contract Interface
Solidity Interface with NatSpec &amp; OpenZeppelin v4 Interfaces (also available at [`IERC4907.sol`](/EIPs/assets/eip-4907/contracts/IERC4907.sol)):

```solidity
interface IERC4907 {

    // Logged when the user of an NFT is changed or expires is changed
    /// @notice Emitted when the `user` of an NFT or the `expires` of the `user` is changed
    /// The zero address for user indicates that there is no user address
    event UpdateUser(uint256 indexed tokenId, address indexed user, uint64 expires);

    /// @notice set the user and expires of an NFT
    /// @dev The zero address indicates there is no user
    /// Throws if `tokenId` is not valid NFT
    /// @param user  The new user of the NFT
    /// @param expires  UNIX timestamp, The new user could use the NFT before expires
    function setUser(uint256 tokenId, address user, uint64 expires) external;

    /// @notice Get the user address of an NFT
    /// @dev The zero address indicates that there is no user or the user is expired
    /// @param tokenId The NFT to get the user address for
    /// @return The user address for this NFT
    function userOf(uint256 tokenId) external view returns(address);

    /// @notice Get the user expires of an NFT
    /// @dev The zero value indicates that there is no user
    /// @param tokenId The NFT to get the user expires for
    /// @return The user expires for this NFT
    function userExpires(uint256 tokenId) external view returns(uint256);
}
```

The `userOf(uint256 tokenId)` function MAY be implemented as `pure` or `view`.

The `userExpires(uint256 tokenId)` function MAY be implemented as `pure` or `view`.

The `setUser(uint256 tokenId, address user, uint64 expires)` function MAY be implemented as `public` or `external`.

The `UpdateUser` event MUST be emitted when a user address is changed or the user expires is changed.

The `supportsInterface` method MUST return `true` when called with `0xad092b5c`.

## Rationale

This model is intended to facilitate easy implementation. Here are some of the problems that are solved by this standard:

### Clear Rights Assignment

With Dual “owner” and “user” roles, it becomes significantly easier to manage what lenders and borrowers can and cannot do with the NFT (in other words, their rights). Additionally, owners can control who the user is and it’s easy for other projects to assign their own rights to either the owners or the users.

### Simple On-chain Time Management

Once a rental period is over, the user role needs to be reset and the “user” has to lose access to the right to use the NFT. This is usually accomplished with a second on-chain transaction but that is gas inefficient and can lead to complications because it’s imprecise. With the `expires` function, there is no need for another transaction because the “user” is invalidated automatically after the duration is over.

### Easy Third-Party Integration

In the spirit of permission less interoperability, this standard makes it easier for third-party protocols to manage NFT usage rights without permission from the NFT issuer or the NFT application. Once a project has adopted the additional `user` role and `expires`, any other project can directly interact with these features and implement their own type of transaction. For example, a PFP NFT using this standard can be integrated into both a rental platform where users can rent the NFT for 30 days AND, at the same time, a mortgage platform where users can use the NFT while eventually buying ownership of the NFT with installment payments. This would all be done without needing the permission of the original PFP project.

## Backwards Compatibility

As mentioned in the specifications section, this standard can be fully EIP-721 compatible by adding an extension function set.

In addition, new functions introduced in this standard have many similarities with the existing functions in EIP-721. This allows developers to easily adopt the standard quickly.

## Test Cases

### Test Contract
`ERC4907Demo` Implementation: [`ERC4907Demo.sol`](/EIPs/assets/eip-4907/contracts/ERC4907Demo.sol)

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

import &quot;./ERC4907.sol&quot;;

contract ERC4907Demo is ERC4907 {

    constructor(string memory name, string memory symbol)
     ERC4907(name,symbol)
     {         
     }

    function mint(uint256 tokenId, address to) public {
        _mint(to, tokenId);
    }

}
```

### Test Code
[test.js](/EIPs/assets/eip-4907/test/test.js)

```JavaScript
const { assert } = require(&quot;chai&quot;);

const ERC4907Demo = artifacts.require(&quot;ERC4907Demo&quot;);

contract(&quot;test&quot;, async accounts =&gt; {

    it(&quot;should set user to Bob&quot;, async () =&gt; {
        // Get initial balances of first and second account.
        const Alice = accounts[0];
        const Bob = accounts[1];

        const instance = await ERC4907Demo.deployed(&quot;T&quot;, &quot;T&quot;);
        const demo = instance;

        await demo.mint(1, Alice);
        let expires = Math.floor(new Date().getTime()/1000) + 1000;
        await demo.setUser(1, Bob, BigInt(expires));

        let user_1 = await demo.userOf(1);

        assert.equal(
            user_1,
            Bob,
            &quot;User of NFT 1 should be Bob&quot;
        );

        let owner_1 = await demo.ownerOf(1);
        assert.equal(
            owner_1,
            Alice ,
            &quot;Owner of NFT 1 should be Alice&quot;
        );
    });
});


```

run in Terminal：
```
truffle test ./test/test.js
```

## Reference Implementation
Implementation: [`ERC4907.sol`](/EIPs/assets/eip-4907/contracts/ERC4907.sol)
```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;
import &quot;./IERC4907.sol&quot;;

contract ERC4907 is ERC721, IERC4907 {
    struct UserInfo 
    {
        address user;   // address of user role
        uint64 expires; // unix timestamp, user expires
    }

    mapping (uint256  =&gt; UserInfo) internal _users;

    constructor(string memory name_, string memory symbol_)
     ERC721(name_, symbol_)
     {
     }
    
    /// @notice set the user and expires of an NFT
    /// @dev The zero address indicates there is no user
    /// Throws if `tokenId` is not valid NFT
    /// @param user  The new user of the NFT
    /// @param expires  UNIX timestamp, The new user could use the NFT before expires
    function setUser(uint256 tokenId, address user, uint64 expires) public virtual{
        require(_isApprovedOrOwner(msg.sender, tokenId), &quot;ERC4907: transfer caller is not owner nor approved&quot;);
        UserInfo storage info =  _users[tokenId];
        info.user = user;
        info.expires = expires;
        emit UpdateUser(tokenId, user, expires);
    }

    /// @notice Get the user address of an NFT
    /// @dev The zero address indicates that there is no user or the user is expired
    /// @param tokenId The NFT to get the user address for
    /// @return The user address for this NFT
    function userOf(uint256 tokenId) public view virtual returns(address){
        if( uint256(_users[tokenId].expires) &gt;=  block.timestamp){
            return  _users[tokenId].user;
        }
        else{
            return address(0);
        }
    }

    /// @notice Get the user expires of an NFT
    /// @dev The zero value indicates that there is no user
    /// @param tokenId The NFT to get the user expires for
    /// @return The user expires for this NFT
    function userExpires(uint256 tokenId) public view virtual returns(uint256){
        return _users[tokenId].expires;
    }

    /// @dev See {IERC165-supportsInterface}.
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC4907).interfaceId || super.supportsInterface(interfaceId);
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual override{
        super._beforeTokenTransfer(from, to, tokenId);

        if (from != to &amp;&amp; _users[tokenId].user != address(0)) {
            delete _users[tokenId];
            emit UpdateUser(tokenId, address(0), 0);
        }
    }
} 
```

## Security Considerations

This EIP standard can completely protect the rights of the owner, the owner can change the NFT user and expires at any time.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 11 Mar 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4907</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4907</guid>
      </item>
    
      <item>
        <title>Royalty Bearing NFTs</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/royalty-bearing-nfts/8453</comments>
        
        <description>## Abstract

The proposal directly connects NFTs and royalties in a smart contract architecture extending the [ERC-721](/EIPs/EIPS/eip-721) standard, with the aim of precluding central authorities from manipulating or circumventing payments to those who are legally entitled to them.

The proposal builds upon the OpenZeppelin Smart Contract Toolbox architecture, and extends it to include royalty account management (CRUD), royalty balance and payments management, simple trading capabilities -- Listing/De-Listing/Buying -- and capabilities to trace trading on exchanges. The royalty management capabilities allow for hierarchical royalty structures, referred to herein as royalty trees, to be established by logically connecting a &quot;parent&quot; NFT to its &quot;children&quot;, and recursively enabling NFT &quot;children&quot; to have more children. 

## Motivation

The management of royalties is an age-old problem characterized by complex contracts, opaque management, plenty of cheating and fraud. 

The above is especially true for a hierarchy of royalties, where one or more assets is derived from an original asset such as a print from an original painting, or a song is used in the creation of another song, or distribution rights and compensation are managed through a series of affiliates. 

In the example below, the artist who created the original is eligible to receive proceeds from every sale, and resale, of a print. 

![Fig1](/EIPs/assets/eip-4910/eip-4910-print-families.png)

The basic concept for hierarchical royalties utilizing the above &quot;ancestry concept&quot; is demonstrated in the figure below.

![Fig2](/EIPs/assets/eip-4910/eip-4910-royalties.png)


In order to solve for the complicated inheritance problem, this proposal breaks down the recursive problem of the hierarchy tree of depth N into N separate problems, one for each layer. This allows us to traverse the tree from its lowest level upwards to its root most efficiently.

This affords creators, and the distributors of art derived from the original, the opportunity to achieve passive income from the creative process, enhancing the value of an NFT, since it now not only has intrinsic value but also comes with an attached cash flow.

## Specification

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.

### Outline

This proposal introduces several new concepts as extensions to the ERC-721 standard that warrant explanation:

* **Royalty Account (RA)**
    * A Royalty Account is attached to each NFT through its `tokenId` and consists of several sub-accounts which can be accounts of individuals or other RAs. A Royalty Account is identified by an account identifier.
* **Account Type**
    * This specifies if an RA Sub Account belongs to an individual (user) or is another RA. If there is another RA as an RA Sub Account, the allocated balance needs to be reallocated to the Sub Accounts making up the referenced RA.
* **Royalty Split**
    * The percentage each Sub Account receives based on a sale of an NFT that is associated with an RA
* **Royalty Balance**
    * The royalty balance associated with an RA
* **Sub Account Royalty Balance**
    * The royalty balance associated to each RA Sub Account. Note that only individual accounts can carry a balance that can be paid out. That means that if an RA Sub Account is an RA, its final Sub Account balance must be zero, since all RA balances must be allocated to individual accounts. 
* **Token Type**
    * Token Type is given as either ETH or the symbol of the supported utility tokens such as `DAI`
* **Asset ID**
    * This is the `tokenId` the RA belongs to.
* **Parent**
    * This indicates which `tokenId` is the immediate parent of the `tokenId` to which an RA belongs.

Below a non-normative overview is given of the data structures and functionality that are covered by the requirements in this document. 

#### Data Structures

In order to create an interconnected data structure linking NFTs to RAs certain global data structures are required:

* A Royalty Account and associated Royalty Sub Accounts to establish the concept of a Royalty Account with sub accounts.
* Connecting a `tokenId` to a Royalty Account identifier.
* A structure mapping parent-to-child NFT relationships.
* A listing of token types and last validated balance (for trading and royalty payment purposes)
* A listing of registered payments to be made in the `executePayment` function and validated in `safeTransferFrom`. This is sufficient, because a payment once received and distributed in the `safeTransferFrom` function will be removed from the listing.
* A listing of NFTs to be sold

#### Royalty Account Functions

Definitions and interfaces for the Royalty Account RUD (Read-Update-Delete) functions. Because the RA is created in the minting function, there is no need to have a function to create a royalty account separately.

#### Minting of a Royalty Bearing NFT

When an NFT is minted, an RA must be created and associated with the NFT and the NFT owner, and, if there is an ancestor, with the ancestor&apos;s RA. To this end the specification utilizes the `_safemint` function in a newly defined `mint` function and applies various business rules on the input variables.

#### Listing NFTs for Sale and removing a Listing

Authorized user addresses can list NFTs for sale for non-exchange mediated NFT purchases.

#### Payment Function from Buyer to Seller

To avoid royalty circumvention, a buyer will always pay the NFT contract directly and not the seller. The seller is paid through the royalty distribution and can later request a payout.

The payment process depends on whether the payment is received in ETH or an [ERC-20](/EIPs/EIPS/eip-20) token:

* ERC-20 Token
    1. The Buyer must `approve` the NFT contract for the purchase price, `payment` for the selected payment token (ERC-20 contract address).
    2. For an ERC-20 payment token, the Buyer must then call the `executePayment` in the NFT contract -- the ERC-20 is not directly involved.
* For a non-ERC-20 payment, the Buyer must send a protocol token (ETH) to the NFT contract, and is required to send `msg.data` encoded as an array of purchased NFTs `uint256[] tokenId`.

#### Modified NFT Transfer Function including required Trade data to allocate Royalties

The input parameters must satisfy several requirements for the NFT to be transferred AFTER the royalties have been properly distributed. Furthermore, the ability to transfer more than one token at a time is also considered.

The proposal defines:

* Input parameter validation
* Payment Parameter Validation
* Distributing Royalties
* Update Royalty Account ownership with payout
* Transferring Ownership of the NFT 
* Removing the Payment entry in `registeredPayment` after successful transfer

Lastly, the approach to distributing royalties is to break down the hierarchical structure of interconnected Royalty Accounts into layers and then process one layer at time, where each relationship between a token and its ancestor is utilized to traverse the Royalty Account chain until the root ancestor and associated RA is reached.

#### Paying out Royalties to the NFT Owner -- `from` address in `safeTransferFrom` Function

This is the final part of the proposal.

There are two versions of the payout function -- a `public` function and an `internal` function.

The public function has the following interface:

```
function royaltyPayOut (uint256 tokenId, address RAsubaccount, address payable payoutAccount, uint256 amount) public virtual nonReentrant returns (bool)
```

where we only need the `tokenId`, the RA Sub Account address, `_RAsubaccount` which is the `owner`, and the amount to be paid out, `_amount`. Note that the function has `nonReentrant` modifier protection, because funds are being payed out.

To finally send a Payout payment, the following steps need to be taken:

* find the RA Sub Account based on `RAaccount` and the `subaccountPos` and extract the balance
* extract `tokenType` from the Sub Account
* based on the token type, send the payout payment (not exceeding the available balance)

### Data Structures

#### Royalty Account and Royalty Sub Accounts

In order to create an interconnected data structure linking NFTs to RAs that is search optimized requires to make the following additions to the global data structures of an ERC-721.

Note, a Royalty Account is defined as a collection of Royalty Sub Accounts linked to a meta account. This meta account is comprised of general account identifiers particular to the NFT it is linked to such as asset identifier, parent identifier etc.

&lt;a name=&quot;r1&quot;&gt;**[R1]**&lt;/a&gt; *One or more Royalty Sub-Account MUST be linked to a Royalty Account.*

&lt;a name=&quot;r2&quot;&gt;**[R2]**&lt;/a&gt; *The account identifier of a Royalty Account, `raAccountId`, MUST be unique.*

&lt;a name=&quot;r3&quot;&gt;**[R3]**&lt;/a&gt; *The `tokenId` of a NFT MUST be linked to a `raAccountID` in order to connect an `raAccountId` to a `tokenId`.*


#### Print (Child) NFTs

The set of requirement to manage Parent-Child NFT Relationships and constraints at each level of the NFT (family) tree e.g. number of children permitted, NFT parents have to be linked to their immediate NFT children are as follows.

&lt;a name=&quot;r4&quot;&gt;**[R4]**&lt;/a&gt; *There MUST be a link for direct parent-child relationships*

#### NFT Payment Tokens

In order to capture royalties, an NFT contract must be involved in NFT trading. Therefore, the NFT contract needs to be aware of NFT payments, which in turn requires the NFT contract to be aware which tokens can be used for trading.

&lt;a name=&quot;r5&quot;&gt;**[R5]**&lt;/a&gt; *There MUST be a listing of supported token types*

Since the NFT contract is managing royalty distributions and payouts as well as sales, it needs to track the last available balances of the allowed token types owned by the contract.  

&lt;a name=&quot;r6&quot;&gt;**[R6]**&lt;/a&gt; *There MUST be a link of the last validated balance of an allowed token type in the contract to the respective allowed token contract.*

#### NFT Listings and Payments

Since the contract is directly involved in the sales process, a capability to list one or more NFTs for sale is required.

&lt;a name=&quot;r7&quot;&gt;**[R7]**&lt;/a&gt; *There MUST be a list of NFTs for sale.*

&lt;a name=&quot;r8&quot;&gt;**[R8]**&lt;/a&gt; *A sales listing MUST have a unique identifier.*

Besides listings, the contract is required to manage sales as well. This requires the capability to register a payment, either for immediate execution or for later payment such as in an auction situation.

&lt;a name=&quot;r9&quot;&gt;**[R9]**&lt;/a&gt; *There MUST be a listing for registered payments*

&lt;a name=&quot;r10&quot;&gt;**[R10]**&lt;/a&gt; *A registered payment MUST have a unique identifier.*

#### Contract Constructor and Global Variables and their update functions

This standard extends the current ERC-721 constructor, and adds several global variables to recognize the special role of the creator of an NFT, and the fact that the contract is now directly involved in managing sales and royalties.

&lt;a name=&quot;r11&quot;&gt;**[R11]**&lt;/a&gt; *The minimal contract constructor MUST contain the following input elements.*

```
///
/// @dev Definition of the contract constructor
///
/// @param name as in ERC-721
/// @param symbol as in ERC-721
/// @param baseTokenURI as in ERC-721
/// @param allowedTokenTypes is the array of allowed tokens for payment

constructor(
        string memory name,
        string memory symbol,
        string memory baseTokenURI,
        address[] memory allowedTokenTypes
    ) ERC721(name, symbol) {...}
```


### Royalty Account Management

Below are the definitions and interfaces for the Royalty Account RUD (Read-Update-Delete) functions. Since a Royalty Account is created in the NFT minting function, there is no need to have a separate function to create a royalty account.

#### Get a Royalty Account

There is only one get function required because a Royalty Account and its sub accounts can be retrieved through the `tokenId` in the `ancestry` field of the Royalty Account. 

&lt;a name=&quot;r12&quot;&gt;**[R12]**&lt;/a&gt; *The `getRoyaltyAccount` function interface MUST adhere to the definition below:*

```
/// @dev Function to fetch a Royalty Account for a given tokenId
/// @param tokenId is the identifier of the NFT to which a Royalty Account is attached
/// @param RoyaltyAccount is a data structure containing the royalty account information
/// @param RASubAccount[] is an array of data structures containing the information of the royalty sub accounts associated with the royalty account

function getRoyaltyAccount (uint256 tokenId) public view virtual returns (address,
            RoyaltyAccount memory,
            RASubAccount[] memory);
```


&lt;a name=&quot;r13&quot;&gt;**[R13]**&lt;/a&gt; *The following business rules MUST be enforced in the `getRoyaltyAccount` function:*

* *`tokenId` exists and is not burned*

#### Update a Royalty Account

In order to update a Royalty Account, the caller must have both the &apos;tokenId&apos; and the `RoyaltyAccount` itself which can be obtained from the Royalty Account getter function. 


&lt;a name=&quot;r14&quot;&gt;**[R14]**&lt;/a&gt; *The `updateRoyaltyAccount` function interface MUST adhere to the definition below:*

```
/// @dev Function to update a Royalty Account and its Sub Accounts
/// @param tokenId is the identifier of the NFT to which the Royalty Account to be updated is attached
/// @param RoyaltyAccount is the Royalty Account and associated Royalty Sub Accounts with updated values  

function updateRoyaltyAccount (uint256 _tokenId, `RoyaltyAccount memory _raAccount) public virtual returns (bool)
```

The update functionality of a Royalty Account, while straightforward, is also highly nuanced. To avoid complicated change control rules such as multi-signature rules, Royalty Account changes are kept simple.

&lt;a name=&quot;r15&quot;&gt;**[R15]**&lt;/a&gt; *The business rules for the update function are as follows:*

1. *An NFTs asset identifier MUST NOT be changed.*
2. *An NFTs ancestor MUST NOT be updated.* 
3. *An NFTs token type accepted for payment MUST NOT be updated.* 
4. *The royalty balance in a Royalty Sub Account MUST NOT be changed.*
5. *The royalty split inherited by the children from the NFT parent MUST NOT be changed.*
6. *New royalty split values MUST be larger than, or less than, or equal to any established boundary value for royalty splits, if it exists.*
7. *The number of existing Royalty Sub Account plus the number of new Royalty Sub Accounts to be added MUST be smaller or equal to an established boundary value, if it exists.*
8. *The sum of all royalty splits across all existing and new Royalty Sub Accounts MUST equal to 1 or its equivalent numerical value at all times.*
9. *&apos;msg.sender` MUST be equal to an account identifier in the Royalty Sub Account of the Royalty Account to be modified and that royalty sub account must be identified as not belonging to the parent NFT* 
    
    9.1 *the Sub Account belonging to the account identifier MUST NOT be removed*
    
    9.2 *A royalty split MUST only be decreased, and either the existing sub account&apos;s  royalty split MUST be increased accordingly such that the sum of all royalty splits remains equal to 1 or its numerical equivalent, or one or more new Royalty Sub Accounts MUST be added according to rule 10.*
    
    9.3 *a royalty balance MUST NOT be changed*
    
    9.4 *an account identifier MUST NOT be NULL*

10. *If `msg.sender` is equal to the account identifier of one of the Sub Account owners which is not the parent NFT, an additional Royalty Sub Accounts MAY be added* 
    
    10.1 *if the royalty split of the Royalty Sub Account belonging to `msg.sender` is reduced*
    
    * then the royalty balance in each new Royalty Sub Account MUST be zero
    
    * and the sum of the new royalty splits data MUST be equal to the royalty split of the Royalty Sub Account of `msg.sender` before it was modified
    
    10.2 *new account identifier MUST not be NULL*

11. *If the Royalty Account update is correct, the function returns `true`, otherwise `false`.* 

#### Deleting a Royalty Account

While sometimes deleting a Royalty Account is necessary, even convenient, it is a very costly function in terms of gas, and should not be used unless one is absolutely sure that the conditions enumerated below are met.

&lt;a name=&quot;r16&quot;&gt;**[R16]**&lt;/a&gt; *The `deleteRoyaltyAccount` function interface MUST adhere to the definition below:*

```
/// @dev Function to delete a Royalty Account
/// @param tokenId is the identifier of the NFT to which the Royalty Account to be updated is attached

function deleteRoyaltyAccount (uint256 _tokenId) public virtual returns (bool)
```

&lt;a name=&quot;r17&quot;&gt;**[R17]**&lt;/a&gt; *The business rules for this function are as follows:*

* *`_tokenId` MUST be burned, i.e., have owner `address(0)`.*
* *all `tokenId` numbers genealogically related to `_tokenId` either as ancestors or offspring MUST also be burnt.* 
* *all balances in the Royalty Sub Accounts MUST be zero.*

### NFT Minting

In extension to the ERC-721 minting capability, a Royalty Account with Royalty Sub Accounts are required to be added during the minting, besides establishing the NFT token specific data structures supporting constraints such as the maximum number of children an NFT can have. 

&lt;a name=&quot;r18&quot;&gt;**[R18]**&lt;/a&gt; *When a new NFT is minted a Royalty Account with one or more Royalty Sub Accounts MUST be created and associated with the NFT and the NFT owner, and, if there is an ancestor, with the ancestor&apos;s Royalty Account.* 

To this end the specification utilizes the ERC-721 `_safemint` function in a newly defined `mint` function, and applies various business rules on the function&apos;s input variables.

&lt;a name=&quot;d1&quot;&gt;**[D1]**&lt;/a&gt; *Note, that the `mint` function SHOULD have the ability to mint more than one NFT at a time.* 

&lt;a name=&quot;r19&quot;&gt;**[R19]**&lt;/a&gt; *Also, note that the `owner` of a new NFT MUST be the NFT contract itself.* 

&lt;a name=&quot;r20&quot;&gt;**[R20]**&lt;/a&gt; *The non-contract owner of the NFT MUST be set as `isApproved` which allows the non-contract owner to operate just like the `owner`.* 

This strange choice in the two requirements above is necessary, because the NFT contract functions as an escrow for payments and royalties, and, hence, needs to be able to track payments received from buyers and royalties due to recipients, and to associate them with a valid `tokenId`.

&lt;a name=&quot;r21&quot;&gt;**[R21]**&lt;/a&gt; *For compactness of the input, and since the token meta data might vary from token to token the MUST be a minimal data structure containing:*

```
/// @param parent is the parent tokenId of the (child) token, and if set to 0 then there is no parent.
/// @param canBeParent indicates if a tokenId can have children or not.
/// @param maxChildren defines how many children an NFT can have.
/// @param royaltySplitForItsChildren is the royalty percentage split that a child has to pay to its parent.
/// @param uri is the unique token URI of the NFT
```

&lt;a name=&quot;r22&quot;&gt;**[R22]**&lt;/a&gt; *The `mint` function interface MUST adhere to the definition below:*

```
/// @dev Function creates one or more new NFTs with its relevant meta data necessary for royalties, and a Royalty Account with its associated met data for `to` address. The tokenId(s) will be automatically assigned (and available on the emitted {IERC-721-Transfer} event).
/// @param to is the address to which the NFT(s) are minted
/// @param nfttoken is an array of struct type NFTToken for the meta data of the minted NFT(s)
/// @param tokenType is the type of allowed payment token for the NFT

function mint(address to, NFTToken[] memory nfttoken, address tokenType) public virtual
```

&lt;a name=&quot;r23&quot;&gt;**[R23]**&lt;/a&gt; *The following business rules for the `mint` function&apos;s input data MUST be fulfilled:*

* *The number of tokens to be minted MUST NOT be zero.*
* *`msg.sender` MUST have either the `MINTER_ROLE` or the `CREATOR_Role` identifying the creator of the first NFT.*
* *`to` address MUST NOT be the zero address.*
* *`to` address MUST NOT be a contract, unless it has been whitelisted -- see [Security Considerations](#security-considerations) for more details.* 
* *`tokenType` MUST be a token type supported by the contract.*
* *`royaltySplitForItsChildren` MUST be less or equal to 100% or numerical equivalent thereof less any constraints such as platform fees* 
* *If the new NFT(s) cannot have children, `royaltySplitForItsChildren` MUST be zero.*
* *If the new NFT(s) has a parent, the parent NFT `tokenId` MUST exist.*
* *The ancestry level of the parent MUST be less than the maximum number of allowed NFT generations, if specified.*
* *The number of allowed children for an NFT to be minted MUST be less than the maximum number of allowed children, if specified.*

### Listing and De-Listing of NFTs for Direct Sales

In the sales process, we need to minimally distinguish two types of transactions

* Exchange-mediated sales
* Direct sales

The first type of transaction does not require that the smart contract is aware of a sales listing since the exchange contract will trigger payment and transfer transactions directly with the NFT contract as the owner. However, for the latter transaction type it is essential, since direct sales are required to be mediated at every step by the smart contract.

&lt;a name=&quot;r24&quot;&gt;**[R24]**&lt;/a&gt; *For direct sales, NFT listing, und de-listing, transactions MUST be executed through the NFT smart contract.*   

Exchange-mediated sales will be discussed when this document discusses payments.

In direct sales, authorized user addresses can list NFTs for sale, see the business rules below.

&lt;a name=&quot;r25&quot;&gt;**[R25]**&lt;/a&gt; *The `listNFT` function interface MUST adhere to the definition below:*

```
/// @dev Function to list one or more NFTs for direct sales
/// @param tokenIds is the array of tokenIds to be included in the listing
/// @param price is the price set by the owner for the listed NFT(s)
/// @param tokenType is the payment token type allowed for the listing

function listNFT (uint256[] calldata tokenIds, uint256 price, address tokenType) public virtual returns (bool)
```

The Boolean return value is `true` for a successful function execution, and `false` for an unsuccessful function execution.

&lt;a name=&quot;r26&quot;&gt;**[R26]**&lt;/a&gt; *The business rules of the `listNFT` function are as follows:*

* there MUST NOT already be a listing for one or more NFTs in the `listedNFT` mapping of the proposed listing.
* `seller` MUST be equal to `getApproved(tokenId[i])` for all NFTs in the proposed listing.
* `tokenType` MUST be supported by the smart contract.
* `price` MUST be larger than `0`.

&lt;a name=&quot;r27&quot;&gt;**[R27]**&lt;/a&gt; *If the conditions in [**[R26]**](#r26) are met, then the NFT sales list MUST be updated.*

Authorized user addresses can also remove a direct sale listing of NFTs. 

&lt;a name=&quot;r28&quot;&gt;**[R28]**&lt;/a&gt; *The `removeNFTListing` function interface MUST adhere to the definition below:*

```
/// @dev Function to de-list one or more NFTs for direct sales
/// @param listingId is the identifier of the NFT listing

function removeNFTListing (uint256 listingId) public virtual returns (bool)
```

The Boolean return value is `true` for a successful function execution, and `false` for an unsuccessful function execution.

&lt;a name=&quot;r29&quot;&gt;**[R29]**&lt;/a&gt; *The business rules of the `removeNFTListing` function below MUST be adhered to:*

* *the registered payment entry MUST be NULL*
* *`msg.sender = getApproved(tokenId)` for the NFT listing* 

&lt;a name=&quot;r30&quot;&gt;**[R30]**&lt;/a&gt; *If the conditions in [**[R29]**](#r29) are met, then the NFT sales listing MUST be removed.*

### Payments for NFT Sales

As noted before, a buyer will always pay the NFT contract directly and not the seller. The seller is paid through the royalty distribution and can later request a payout to their wallet.

&lt;a name=&quot;r31&quot;&gt;**[R31]**&lt;/a&gt; *The payment process requires either one or two steps:*

1. *For an ERC-20 token*
    * *The buyer MUST `approve` the NFT contract for the purchase price, `payment`, for the selected payment token type.*
    * *The buyer MUST call the `executePayment` function.*
2. *For a protocol token* 
    * *The buyer MUST call a payment fallback function with `msg.data` not NULL.*

&lt;a name=&quot;r32&quot;&gt;**[R32]**&lt;/a&gt; *For an ERC-20 token type, the required `executePayment` function interface MUST adhere to the definition below*:

```
/// @dev Function to make a NFT direct sales or exchange-mediate sales payment
/// @param receiver is the address of the receiver of the payment
/// @param seller is the address of the NFT seller 
/// @param tokenIds are the tokenIds of the NFT to be bought
/// @param payment is the amount of that payment to be made
/// @param tokenType is the type of payment token
/// @param trxnType is the type of payment transaction -- minimally direct sales or exchange-mediated

function executePayment (address receiver, address seller, uint 256[] tokenIds, uint256 payment, string tokenType, int256 trxnType) public virtual nonReentrant returns (bool)
```

The Boolean return value is `true` for a successful function execution, and `false` for an unsuccessful function execution.

&lt;a name=&quot;r33&quot;&gt;**[R33]**&lt;/a&gt; *Independent of `trxnType`, the business rules for the input data are as follows:*

* *All purchased NFTs in the `tokenIds` array MUST exist and MUST NOT be burned.*
* *`tokenType` MUST be a supported token.*
* *`trxnType` MUST be set to either `0` (direct sale) or `1` (exchange-mediate sale), or another supported type.*
* *`receiver` MAY be NULL but MUST NOT be the Zero Address.*
* *`seller` MUST be the address in the corresponding listing.*
* *`msg.sender` MUST not be a contract, unless it is whitelisted in the NFT contract.*

In the following, this document will only discuss the differences between the two minimally required transaction types.

&lt;a name=&quot;r34&quot;&gt;**[R34]**&lt;/a&gt; *For `trxnType = 0`, the payment data MUST to be validated against the listing, based on the following rules:*

* *NFT(s) MUST be listed*
* *`payment` MUST be larger or equal to the listing price.*
* *The listed NFT(s) MUST match the NFT(s) in the payment data.* 
* *The listed NFT(s) MUST be controlled by `seller`.*

&lt;a name=&quot;r35&quot;&gt;**[R35]**&lt;/a&gt; *If all checks in [**[R33]**](#r33), and in [**[R34]**](#r34) for `trxnType = 0`, are passed, the `executePayment` function MUST call the `transfer` function in the ERC-20 contract identified by `tokenType` with `recipient = address(this)` and `amount = payment`.* 

Note the NFT contract pays itself from the available allowance set in the `approve` transaction from the buyer.

&lt;a name=&quot;r36&quot;&gt;**[R36]**&lt;/a&gt; *For `trxnType = 1`, and for a successful payment, the `registeredPayment` mapping MUST updated with the payment, such that it can be validated when the NFT is transferred in a separate `safeTransferFrom` call, and `true` MUST be returned as the return value of the function, if successful, `false` otherwise.*

&lt;a name=&quot;r37&quot;&gt;**[R37]**&lt;/a&gt; *For `trxnType = 0`, an `internal` version of the `safeTransferFrom` function with message data MUST be called to transfer the NFTs to the buyer, and upon success, the buyer MUST be given the `MINTER_ROLE`, unless the buyer already has that role.*

Note, the `_safeTransferFrom` function has the same structure as `safeTransferFrom` but skips the input data validation.

&lt;a name=&quot;r38&quot;&gt;**[R38]**&lt;/a&gt; *For `trxnType = 0`, and if the NFT transfer is successful, the listing of the NFT MUST be removed.* 

&lt;a name=&quot;r39&quot;&gt;**[R39]**&lt;/a&gt; *For a protocol token as a payment token, and independent of `trxnType`, the buyer MUST send protocol tokens to the NFT contract as the escrow, and `msg.data` MUST encode the array of paid for NFTs `uint256[] tokenIds`.*

&lt;a name=&quot;r40&quot;&gt;**[R40]**&lt;/a&gt; *For the NFT contract to receive a protocol token, a payable fallback function (`fallback() external payable`) MUST be implemented.*

Note that since the information for which NFTs the payment was for must be passed, a simple `receive()` fallback function cannot be allowed since it does not allow for `msg.data` to be sent with the transaction.

&lt;a name=&quot;r41&quot;&gt;**[R41]**&lt;/a&gt; *`msg.data` for the fallback function MUST minimally contain the following data:
`address memory seller, uint256[] memory _tokenId, address memory receiver, int256 memory trxnType`*

&lt;a name=&quot;r42&quot;&gt;**[R42]**&lt;/a&gt; *If `trxnType` is not equal to either &apos;0&apos; or &apos;1&apos;, or another supported type, then the fallback function MUST `revert`.*

&lt;a name=&quot;r43&quot;&gt;**[R43]**&lt;/a&gt; *For `trxnType` equal to either &apos;0&apos; or &apos;1&apos;, the requirements [**[R33]**](#r33) through [**[R38]**](#r38) MUST be satisfied for the fallback function to successfully execute, otherwise the fallback function MUST `revert`.*

&lt;a name=&quot;r44&quot;&gt;**[R44]**&lt;/a&gt; *In case of a transaction failure (for direct sales, `trxnType = 0`), or the buyer of the NFT listing changing their mind (for exchange-mediated sales, `trxnType = 1`), the submitted payment MUST be able to revert using the `reversePayment` function where the function interface is defined below:*

```
/// @dev Definition of the function enabling the reversal of a payment before the sale is complete
/// @param paymentId is the unique identifier for which a payment was made
/// @param tokenType is the type of payment token used in the payment
function reversePayment(uint256 paymentId, string memory tokenType) public virtual returns (bool)
```

The Boolean return value is `true` for a successful function execution, and `false` for an unsuccessful function execution.

Note, `reentrancy` protection through e.g. `nonReentrant` from the Open Zeppelin library is strongly advised since funds are being paid out.

&lt;a name=&quot;r45&quot;&gt;**[R45]**&lt;/a&gt; *The business rules for the `reversePayment` function are as follows:*

* *There MUST be registered payment for a given `paymentId` and `tokenType`.*
* *`msg.sender` MUST be the buyer address in the registered payment.*
* *The payment amount must be larger than `0`.*
* *The registered payment MUST be removed when the payment has been successfully reverted, otherwise the function must fail.*


### Modified NFT Transfer function

This document adheres to the ERC-721 interface format for the `safeTransferFrom` function as given below:

```
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) external virtual override
```

Note, that the input parameters must satisfy several requirements for the NFT(s) to be transferred AFTER royalties have been properly distributed. Note also, that the ability to transfer more than one token at a time is required. However, the standard interface only allows one token to be transferred at a time. In order to remain compliant with the ERC-721 standard, this document uses `tokenId` only for the first NFT to be transferred. All other transfer relevant data is encoded in `_data`. 

The high-level requirements are as follows:

* The payment parameters of the trade encoded in `_data` must be validated.
* The seller and the sold NFT token(s) must exist, and the seller must be the owner of the token.
* `msg.sender` must be the seller address or an approved address.
* the payment of the trade received by the NFT smart contract is correctly disbursed to all Royalty Sub Account owners.
* the NFT token is transferred after all Royalty Sub Accounts and their holders associated with the NFT token(s) have been properly credited.

Also, note that in order to avoid royalty circumvention attacks, there is only one NFT transfer function. 

&lt;a name=&quot;r46&quot;&gt;**[R46]**&lt;/a&gt; *Therefore, `transferFrom` and `safeTransferFrom` without `data` MUST be disabled.*

This can be achieved through for example a `revert` statement in an `override` function.

&lt;a name=&quot;r47&quot;&gt;**[R47]**&lt;/a&gt; *The requirements on input parameters of the function are as follows*:

* *`from` MUST not be `address(0)`.*
* *`from` MUST be the owner or `approved` for `tokenId` and the other tokens included in `_data`.*
* *`from` MUST not be a smart contract unless whitelisted.*
* *a Royalty Account MUST be associated to `tokenId` and the other tokens included in `_data`.*
* *`_data` MUST NOT be NULL.*
* *`msg.sender` MUST be equal to `from` or an `approved` address, or a whitelisted contract.*

Note, that in the context of this document only the scenario where the calling contract is still being created, i.e., the constructor being executed is a possible attack vector, and should to be carefully treated in the transfer scenario.

Turning to the `_data` object.

&lt;a name=&quot;r48&quot;&gt;**[R48]**&lt;/a&gt; *The `_data` object MUST minimally contain the following payment parameters:*

* *Seller Address as `address`.*
* *Buyer Address as `address`.*
* *Receiver Address as `address.*
* *Token identifiers as `uint256[]`.*
* *Token type used for payment.*
* *Payment amount paid to NFT contract as `uint256`.*
* *a registered payment identifier.*
* *blockchain ID, `block.chainid`, of the underlying blockchain.*

&lt;a name=&quot;r49&quot;&gt;**[R49]**&lt;/a&gt; *The following business rules MUST be met for the payment data in &apos;_data&apos;:*

* *`seller == from`.*
* *`tokenId[0] == tokenId`.*
* *Each token in `_tokenId` has an associated Royalty Account.*
* *`chainid == block.chainid`.*
* *`buyer` is equal to the buyer address in the registered payment for the given ``paymentId.*
* *`receiver == to`.*
* *the receiver of the token is not the seller.*
* *the receiver of the token is not a contract or is a whitelisted contract*
* *For all NFTs in the payment, `tokenId[i] = registeredPayment[paymentId].boughtTokens[i]`.*
* *`tokenType` is supported in the contract.* 
* *`allowedToken[tokenType]` is not NULL.*
* *`tokenType = registeredPayment[paymentId].tokenType`.*
* *`payment &gt; lastBalanceAllowedToken[allowedToken[listingId]]`.*
* *`payment = registeredPayment[paymentId].payment`.*

### Distributing Royalties in the Transfer Function

The approach to distributing royalties is to break down the hierarchical structure of interconnected Royalty Accounts into layers, and then process one layer at time, where each relationship between a NFT and its ancestor is utilized to traverse the Royalty Account chain until the root ancestor and its associated Royalty Account.

Note, that the distribution function assumes that the payment made is for ALL tokens in the requested transfer. That means, that `payment` for the distribution function is equally divided between all NFTs included in the payment. 

&lt;a name=&quot;r5&quot;&gt;**[R50]**&lt;/a&gt; *The `distributePayment` function interface MUST adhere to the definition below:

```
/// @dev Function to distribute a payment as royalties to a chain of Royalty Accounts
/// @param tokenId is a tokenId included in the sale and used to look up the associated Royalty Account
/// @param payment is the payment (portion) to be distributed as royalties

function distributePayment (uint256 tokenId, uint265 payment) internal virtual returns (bool)
```

The Boolean return value is `true` for a successful function execution, and `false` for an unsuccessful function execution.

As mentioned before, the internal `distributePayment` function is called within the modified `safeTransferFrom` function.

Note, that it is necessary to multiply two `uint256` numbers with each other -- the payment amount with the royalty split percentage expressed as a whole number e.g. `10000 = 100%`. And then divide the result by the whole number representing `100%` in order to arrive at the correct application of the royalty split percentage to the payment amount. This requires careful treatment of numbers in the implementation to prevent issues such as buffer over or under runs.

&lt;a name=&quot;r51&quot;&gt;**[R51]**&lt;/a&gt; *The processing logic of `distributePayment` function MUST be as follows:*

* *Load the Royalty Account (`RA`) and associated Royalty Sub Accounts using the passed `tokenId`.*
* *For each Royalty Sub Account in `RA` apply the following rules:*
    * *If a Royalty Sub Account in `RA` has `isIndividual` set to `true` then*
        * *apply the royalty percentage of that Royalty Sub Account to `payment` and add the calculated amount, e.g. `royaltyAmountTemp`, to the `royaltybalance` of that Royalty Sub Account.*
        * *emit an event as a notification of payment to the `accountId` of the Royalty Sub Account containing: assetId, accountId, tokenType, royaltybalance.*
        * *in the RA add `royaltyamountTemp` amount to `balance`*
    * *If a Royalty Sub Account in `RA` has `isIndividual` set to `false` then*
        * *apply the royalty percentage of that Royalty Sub Account to `payment` and store temporarily in a new variable e.g. `RApaymenttemp`, but do not update the `royaltybalance` of the Royalty Sub Account which remains `0`.*
    * *then use `ancestor` to obtain the `RA` connected to `ancestor` e.g. via a look up through a Royalty Account mapping.*
    * *load the new RA*
        * *if `isIndividual` of the Royalty Sub Account is set to `true`, pass through the Royalty Sub Accounts of the next `RA`, and apply the rule for `isIndividual = true`.*
        * *if `isIndividual` of the Royalty Sub Account is set to `false`, pass through the Royalty Sub Accounts of the next `RA`, and apply the rule for `isIndividual = false`.*
    * *Repeat the procedures for `isIndividual` equal to `true` and `false` until a `RA` is reached that does not have an `ancestor`, and where all Royalty Sub Accounts have`isIndividual` set to `true`, and apply the rule for a Royalty Sub Account that has `isIndividual` set to `true` to all Royalty Sub Accounts in that `RA`.*

### Update Royalty Sub Account Ownership with Payout to approved Address (`from`)

In order to simplify the ownership transfer, first the approved address -- the non-contract NFT owner --, `from`, is paid out its share of the royalties. And then the Royalty Sub Account is updated with the new owner, `to`. This step repeats for each token to be transferred.

&lt;a name=&quot;r52&quot;&gt;**[R52]**&lt;/a&gt; *The business rules are as follows:*

* *the internal version of the`royaltyPayOut` function MUST pay out the entire royalty balance of the Royalty Sub Account owned by the `from` address to the `from` address.*
* *the Royalty Sub Account MUST only be updated with the new owner only once the payout function has successfully completed and the `royaltybalance = 0`.*

The last step in the process chain is transferring the NFTs in the purchase to the `to` address. 

&lt;a name=&quot;r53&quot;&gt;**[R53]**&lt;/a&gt; *For every NFT (in the batch) the &apos;to&apos; address MUST be `approved&apos; (ERC-721 function) to complete the ownership transfer:* 

```
_approve(to, tokenId[i]);
```

The technical NFT owner remains the NFT contract.

### Removing the Payment Entry after successful Transfer

Only after the real ownership of the NFT, the approved address, has been updated, the payment registry entry can be removed to allow the transferred NFTs to be sold again.

&lt;a name=&quot;r54&quot;&gt;**[R54]**&lt;/a&gt; *After the `approve` relationship has been successfully updated to the `to` address, the registered payment MUST be removed.*

### Paying out Royalties to the `from` Address in `safeTransferFrom` Function

There are two versions of the payout function -- a `public` and an `internal` function -- depending on whether there is a payout during a purchase, or a payout is requested by a Royalty Sub Account owner.

&lt;a name=&quot;r55&quot;&gt;**[R55]**&lt;/a&gt; *The public `royaltyPayOut` function interface MUST adhere to the definition below:*

```
/// @dev Function to payout a royalty payment
/// @param tokenId is the identifier of the NFT token
/// @param RAsubaccount is the address of the Royalty Sub Account from which the payout should happen
/// @param receiver is the address to receive the payout
/// @param amount is the amount to be paid out

function royaltyPayOut (uint256 tokenId, address RAsubaccount, address payable payoutAccount, uint256 amount) public virtual nonReentrant returns (bool)
```

The Boolean return value is `true` for a successful function execution, and `false` for an unsuccessful function execution.

Note, that the function has `reentrancy` protection through `nonReentrant` from the Open Zeppelin library since funds are being paid out.

&lt;a name=&quot;r56&quot;&gt;**[R56]**&lt;/a&gt; *The input parameters of the `royaltyPayOut` function MUST satisfy the following requirements:*

* *`msg.sender == RAsubaccount`.*
* *`tokenId` must exist and must not be burned.*
* *`tokenId` must be associated with a Royalty Account.*
* *`RAsubaccount` must be a valid `accountId` in a Royalty Sub Account of the Royalty Account of the `tokenId&apos;.*
* *`isIndividual == true` for the Royalty Sub Account, `RAsubaccount`.*
* *`amount &lt;= royaltybalance` of the Royalty Sub Account, `RAsubaccount.*`

&lt;a name=&quot;r57&quot;&gt;**[R57]**&lt;/a&gt; *The internal `_royaltyPayOut` function interface MUST adhere to the definition below*:

```
function _royaltyPayOut (uint256 tokenId, address RAsubaccount, address payable payoutAccount, uint256 amount) public virtual returns (bool)
```

&lt;a name=&quot;r58&quot;&gt;**[R58]**&lt;/a&gt; *The internal `_royaltyPayOut` function MUST perform the following actions:

* *send the payment to the `payoutaccount`.*
* *update the `royaltybalance` of the `RAsubaccount` of the Royalty Account upon successful transfer.*

&lt;a name=&quot;r59&quot;&gt;**[R59]**&lt;/a&gt; *The following steps MUST be taken to send out a royalty payment to its recipient:*

* *find the Royalty Sub Account.*
* *extract `tokenType` from the Royalty Sub Account.*
* *based on the token type send to the `payoutAccount` either*
    * *&apos;ETH&apos; / relevant protocol token or*
    * *another token based on token type* 
* *and only if the payout transaction is successful, deduct `amount` from `royaltybalance` of the Royalty Sub Account,`RAsubaccount`, and then return `true` as the function return parameter, otherwise return `false`.* 

## Rationale

Royalties for NFTs is at its core a distribution licensing problem. A buyer obtains the right to an asset/content which might or might not be reproducible, alterable etc. by the buyer or agents of the buyer. Therefore, a comprehensive specification must address a hierarchy of royalties, where one or more assets are derived from an original asset as described in the Motivation section in detail. Consequently, a design must solve for a multi-level inheritance, and thus, recursion problem. 

In order to solve for the complicated inheritance problem, this proposal design breaks down the recursive problem of the hierarchy first into a tree of depth N. And the further breaks down the tree structure into N separate problems, one for each layer. This design allows one to traverse the tree from its lowest level upwards to its root most efficiently. This is achieved with the design for the `distributePayment` function and the NFT data structures allowing for the tree structure e.g. `ancestry`,`royaltyAccount`, `RAsubaccount`. 

In order to avoid massive gas costs during the payout of royalties, possibly exceeding block gas limits for large royalty trees, the design needed to create a royalty accounting system to maintain royalty balances for recipients as done with the `royaltyAccount`, &apos;RAsubaccount&apos; data structures and the associated CRUD operations, as well as require that royalty payouts are done by individual and by request, only, as is achieved with the `royaltyPayout` function design.

Furthermore, the design had to ensure that in order to account for and payout royalties the smart contract must be in the &quot;know&quot; of all buying and selling of an NFT including the exchange of monies. This buying and selling can be either direct through the NFT contract or can be exchange-mediated as is most often the case today -- which is a centralizing factor! The chosen design for purchasing is accounting for those two modes. 

Keeping the NFT contract in the &quot;know&quot; at the beginning of the purchase process requires that authorized user addresses can list NFTs for sale for direct sales , whereas for exchange-mediated purchases, a payment must be registered with the NFT contract before the purchase can be completed.

The design needed to avoid royalty circumvention during the purchase process, therefore, the NFT must be kept in the &quot;know&quot;, a buyer will always have to pay the NFT contract directly and not the seller for both purchasing modes. The seller is subsequently paid through the royalty distribution function in the NFT contract. As a consequence, and a key design choice, and to stay compliant with ERC-721, the NFT contract must be the owner of the NFT, and the actual owner is an `approved` address. 

The specification design also needed to account for that the payment process depends on whether the payment is received in ETH or an ERC-20 token:

* ERC-20 Token
    1. The Buyer must `approve` the NFT contract for the purchase price, `payment` for the selected payment token (ERC-20 contract address).
    2. For an ERC-20 payment token, the Buyer must then call the `executePayment` in the NFT contract -- the ERC-20 is not directly involved.
* For a non-ERC-20 payment, the Buyer must send a protocol token (ETH) to the NFT contract, and is required to send encoded listing and payment information.

In addition, the `executePayment` function had to be designed to handle both direct sales (through the NFT contract) and exchange-mediated sales which required the introduction of an indicator whether the purchase is direct or exchange-mediated.

The `executePayment` function also has to  handle the NFT transfer and purchase clean up -- removal  of a listing, or removal of a registered payment, distribution of royalties, payment to the seller, and finally transfer to the seller.

To stay compliant with the ERC-721 design but avoid royalty circumvention, all transfer functions must be disabled save the one that allows for additional information to be submitted with the function in order to manage the complicated purchase cleanup process -- `safeTransferFrom`. To ensure safety, the design enforces that input parameters must satisfy several requirements for the NFT to be transferred AFTER the royalties have been properly distributed, not before. The design accounts for the fact that we need to treat transfer somewhat differently for direct sales versus exchange mediated sales.

Finally the specification needed to take into account that NFTs must be able to be `minted` and `burned` to maintain compliance with the ERC-721 specification while also having to set up all the data structures for the tree.

The design enforces that when an NFT is minted, a royalty account for that NFT must be created and associated with the NFT and the NFT owner, and, if there is an ancestor of the NFT with the ancestor&apos;s royalty account to enforces the tree structure. To this end the specification utilizes the ERC-721 `_safemint` function in a newly defined `mint` function and applies various business rules on the input variables required to ensure proper set-up.

An NFT with a royalty account can be burned. However, several things have to be true to avoid locking funds not only for the royalty account of the NFT but also its descendants, if they exist. That means that all royalties for the NFT and its descendants, if they exists, must be paid out. Furthermore, if descendants exist, they must have been burned before an ancestor can be burned. If those rules are not enforced the cleanly, the hierarchical royalty structure in part of the tree can break down and lead to lost funds, not paid out royalties etc.
 

## Backwards Compatibility

This EIP is backwards compatible to the ERC-721 standard introducing new interfaces and functionality but retaining the core interfaces and functionality of the ERC-721 standard.

## Test Cases

A full test suite is part of the reference implementation.

## Reference Implementation

The Treetrunk reference implementation of the standard can be found in the public treetrunkio Github repo under treetrunk-nft-reference-implementation.

## Security Considerations

Given that this EIP introduces royalty collection, distribution, and payouts to the ERC-721 standard, the number of attack vectors increases. The most important attack vector categories and their mitigation are discussed below:

* **Payments and Payouts**:
    * Reentrancy attacks are mitigated through a reentrancy protection on all payment functions. See for example the Open Zeppelin reference implementation .
    * Payouts from unauthorized accounts. Mitigation: Royalty Sub Accounts require at least that `msg.sender` is the Royalty Sub Account owner.
    * Payments could get stuck in the NFT contract if the `executePayment` function fails. Mitigation: For exchange-mediated sales, a buyer can always reverse a payment with `reversePayment` if the `executePayment` function fails. For direct sales, `reversePayment` will be directly triggered in the `executePayment` function.
* **Circumventing Royalties**:
    * Offchain Key exchanges
        * Exchanging a private key for money off chain can not be prevented in any scenario. 
    * Smart Contract Wallets as NFT owners
        * A Smart Contract Wallet controlled by multiple addresses could own an NFT and the owners could transfer the asset within the wallet with an off chain money exchange. Mitigation: Prohibit that Smart Contracts can own an NFT unless explicitly allowed to accommodate special scenarios such as collections.
    * Denial of Royalty Disbursement 
        * An attacker who has purchased one or more NFTs in a given generation of an NFT family can cause out of gas errors or run time errors for the contract, if they add many spurious royalty sub-accounts with very low royalty split percentages, and then mint more prints of those purchased NFTs, and then repeat that step until the set `maxGeneration` limit is reached. An NFT trade at the bottom of the hierarchy will then require a lot of code cycles because of the recursive nature of the royalty distribution function. Mitigation: Limit the number of royalty sub-accounts per NFT and impose a royalty split percentage limit.
        * Following the same approach as above but now targeting the `addListNFT` function, an attacker can force an out of gas error or run time errors in the `executePayment` function by listing many NFTs at a low price, and then performing a purchase from another account. Mitigation: Limit the number of NFTs that can be included in one listing.
        * The creator of the NFT family could set the number of generations too high such that the royalty distribution function could incur and out of gas or run time error because of the recursive nature of the function. Mitigation: Limiting the `maxNumberGeneration` by the creator.
    * General Considerations: The creator of an NFT family must carefully consider the business model for the NFT family and then set the parameters such as maximum number of generations, royalty sub-accounts, number of prints per print, number of NFTs in a listing, and the maximum and minimum royalty split percentage allowed. 
* **Phishing Attacks**
    * NFT phishing attacks often target the `approve` and `setApprovalForAll` functions by tricking owners of NFTs to sign transactions adding the attacker account as approved for one or all NFTs of the victim. Mitigation: This contract is not vulnerable to these type of phishing attacks because all NFT transfers are sales, and the NFT contract itself is the owner of all NFTs. This means that transfers after a purchase are achieved by setting the new owner in the `_approve` function. Calling the public `approve` function will cause the function call to error out because `msg.sender` of the malicious transaction cannot be the NFT owner.
    * NFT phishing attack targeting the `addListNFT` function to trick victim to list one or more NFTs at a very low price and the attacker immediately registering a payment, and executing that payment right away. Mitigation: Implement a waiting period for a purchase can be affected giving the victim time to call the `removeListNFT` function. In addition, an implementer could require Two-Factor-Authentication either built into the contract or by utilizing an authenticator app such as Google Authenticator built into a wallet software. 

Besides the usage of professional security analysis tools, it is also recommended that each implementation performs a security audit of its implementation.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 14 Mar 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4910</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4910</guid>
      </item>
    
      <item>
        <title>Generic Token Upgrade Standard</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4931-generic-token-upgrade-standard/8687</comments>
        
        <description>## Abstract

The following standard allows for the implementation of a standard API for [ERC-20](/EIPs/EIPS/eip-20) token upgrades. This standard specifies an interface that supports the conversion of tokens from one contract (called the &quot;source token&quot;) to those from another (called the &quot;destination token&quot;), as well as several helper methods to provide basic information about the token upgrade (i.e. the address of the source and destination token contracts, the ratio that source will be upgraded to destination, etc.). 

## Motivation

Token contract upgrades typically require each asset holder to exchange their old tokens for new ones using a bespoke interface provided by the developers. This standard interface will allow asset holders as well as centralized and decentralized exchanges to conduct token upgrades more efficiently since token contract upgrade scripts will be essentially reusable. Standardization will reduce the security overhead involved in verifying the functionality of the upgrade contracts. It will also provide asset issuers clear guidance on how to effectively implement a token upgrade.

## Specification
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.

Please Note: Methods marked with (Optional Ext.) are a part of the optional extension for downgrade functionality and may remain unimplemented if downgrade functionality is not required.
### Token Upgrade Interface Contract
``` solidity
interface IEIP4931 {
```
#### Methods

##### upgradeSource

Returns the address of the original (source) token that will be upgraded.

``` solidity
/// @dev A getter to determine the contract that is being upgraded from (&quot;source contract&quot;)
/// @return The address of the source token contract
function upgradeSource() external view returns(address)
```

##### upgradeDestination

Returns the address of the token contract that is being upgraded to. 

``` solidity
/// @dev A getter to determine the contract that is being upgraded to (&quot;destination contract&quot;)
/// @return The address of the destination token contract
function upgradeDestination() external view returns(address)
```

##### isUpgradeActive

Returns the current status of the upgrade functionality. Status MUST return `true` when the upgrade contract is functional and serving upgrades. It MUST return `false` when the upgrade contract is not currently serving upgrades.

``` solidity
/// @dev The method will return true when the contract is serving upgrades and otherwise false
/// @return The status of the upgrade as a boolean
function isUpgradeActive() external view returns(bool)
```
##### isDowngradeActive

Returns the current status of the downgrade functionality. Status MUST return `true` when the upgrade contract is functional and serving downgrades. It MUST return `false` when the upgrade contract is not currently serving downgrades. When the downgrade Optional Ext. is not implemented, this method will always return `false` to signify downgrades are not available.

``` solidity
/// @dev The method will return true when the contract is serving downgrades and otherwise false
/// @return The status of the downgrade as a boolean
function isDowngradeActive() external view returns(bool)
```
##### ratio

Returns the ratio of destination token to source token, expressed as a 2-tuple, that the upgrade will use. E.g. `(3, 1)` means the upgrade will provide 3 destination tokens for every 1 source token being upgraded.

``` solidity
/// @dev A getter for the ratio of destination tokens to source tokens received when conducting an upgrade
/// @return Two uint256, the first represents the numerator while the second represents
/// the denominator of the ratio of destination tokens to source tokens allotted during the upgrade
function ratio() external view returns(uint256, uint256)
```

##### totalUpgraded

Returns the total number of tokens that have been upgraded from source to destination. If the downgrade Optional Ext. is implemented, calls to `downgrade` will reduce the `totalUpgraded` return value making it possible for the value to decrease between calls. The return value will be strictly increasing if downgrades are not implemented.

``` solidity
/// @dev A getter for the total amount of source tokens that have been upgraded to destination tokens.
/// The value may not be strictly increasing if the downgrade Optional Ext. is implemented.
/// @return The number of source tokens that have been upgraded to destination tokens
function totalUpgraded() external view returns(uint256)
```
##### computeUpgrade

Computes the `destinationAmount` of destination tokens that correspond to a given `sourceAmount` of source tokens, according to the predefined conversion ratio, as well as the `sourceRemainder` amount of source tokens that can&apos;t be upgraded. For example, let&apos;s consider a (3, 2) ratio, which means that 3 destination tokens are provided for every 2 source tokens; then, for a source amount of 5 tokens, `computeUpgrade(5)` must return `(6, 1)`, meaning that 6 destination tokens are expected (in this case, from 4 source tokens) and 1 source token is left as remainder.
``` solidity
/// @dev A method to mock the upgrade call determining the amount of destination tokens received from an upgrade
/// as well as the amount of source tokens that are left over as remainder
/// @param sourceAmount The amount of source tokens that will be upgraded
/// @return destinationAmount A uint256 representing the amount of destination tokens received if upgrade is called
/// @return sourceRemainder A uint256 representing the amount of source tokens left over as remainder if upgrade is called
function computeUpgrade(uint256 sourceAmount) external view
        returns (uint256 destinationAmount, uint256 sourceRemainder)
```

##### computeDowngrade (Optional Ext.)

Computes the `sourceAmount` of source tokens that correspond to a given `destinationAmount` of destination tokens, according to the predefined conversion ratio, as well as the `destinationRemainder` amount of destination tokens that can&apos;t be downgraded. For example, let&apos;s consider a (3, 2) ratio, which means that 3 destination tokens are provided for every 2 source tokens; for a destination amount of 13 tokens, `computeDowngrade(13)` must return `(4, 1)`, meaning that 4 source tokens are expected (in this case, from 12 destination tokens) and 1 destination token is left as remainder.
``` solidity
/// @dev A method to mock the downgrade call determining the amount of source tokens received from a downgrade
/// as well as the amount of destination tokens that are left over as remainder
/// @param destinationAmount The amount of destination tokens that will be downgraded
/// @return sourceAmount A uint256 representing the amount of source tokens received if downgrade is called
/// @return destinationRemainder A uint256 representing the amount of destination tokens left over as remainder if upgrade is called
function computeDowngrade(uint256 destinationAmount) external view
        returns (uint256 sourceAmount, uint256 destinationRemainder)
```


##### upgrade

Upgrades the `amount` of source token to the destination token in the specified ratio. The destination tokens will be sent to the `_to` address. The function MUST lock the source tokens in the upgrade contract or burn them. If the downgrade Optional Ext. is implemented, the source tokens MUST be locked instead of burning. The function MUST `throw` if the caller&apos;s address does not have enough source token to upgrade or if `isUpgradeActive` is returning `false`. The function MUST also fire the `Upgrade` event. `approve` MUST be called first on the source contract.
``` solidity
/// @dev A method to conduct an upgrade from source token to destination token.
/// The call will fail if upgrade status is not true, if approve has not been called
/// on the source contract, or if sourceAmount is larger than the amount of source tokens at the msg.sender address.
/// If the ratio would cause an amount of tokens to be destroyed by rounding/truncation, the upgrade call will
/// only upgrade the nearest whole amount of source tokens returning the excess to the msg.sender address. 
/// Emits the Upgrade event
/// @param _to The address the destination tokens will be sent to upon completion of the upgrade
/// @param sourceAmount The amount of source tokens that will be upgraded 
function upgrade(address _to, uint256 sourceAmount) external
```


##### downgrade (Optional Ext.)
Downgrades the `amount` of destination token to the source token in the specified ratio. The source tokens will be sent to the `_to` address. The function MUST unwrap the destination tokens back to the source tokens. The function MUST `throw` if the caller&apos;s address does not have enough destination token to downgrade or if `isDowngradeActive` is returning `false`. The function MUST also fire the `Downgrade` event. `approve` MUST be called first on the destination contract.
``` solidity
/// @dev A method to conduct a downgrade from destination token to source token.
/// The call will fail if downgrade status is not true, if approve has not been called
/// on the destination contract, or if destinationAmount is larger than the amount of destination tokens at the msg.sender address.
/// If the ratio would cause an amount of tokens to be destroyed by rounding/truncation, the downgrade call will only downgrade
/// the nearest whole amount of destination tokens returning the excess to the msg.sender address. 
///  Emits the Downgrade event
/// @param _to The address the source tokens will be sent to upon completion of the downgrade
/// @param destinationAmount The amount of destination tokens that will be downgraded 
function downgrade(address _to, uint256 destinationAmount) external
```

#### Events

##### Upgrade

MUST trigger when tokens are upgraded.

``` solidity
/// @param _from Address that called upgrade
/// @param _to Address that destination tokens were sent to upon completion of the upgrade
/// @param sourceAmount Amount of source tokens that were upgraded
/// @param destinationAmount Amount of destination tokens sent to the _to address
event Upgrade(address indexed _from, address indexed _to, uint256 sourceAmount, uint256 destinationAmount)
```

##### Downgrade (Optional Ext.)

MUST trigger when tokens are downgraded.

``` solidity
/// @param _from Address that called downgrade
/// @param _to Address that source tokens were sent to upon completion of the downgrade
/// @param sourceAmount Amount of source tokens sent to the _to address
/// @param destinationAmount Amount of destination tokens that were downgraded
event Downgrade(address indexed _from, address indexed _to, uint256 sourceAmount, uint256 destinationAmount)
}
```

## Rationale
There have been several notable ERC20 upgrades (Ex. Golem: GNT -&gt; GLM) where the upgrade functionality is written directly into the token contracts. We view this as a suboptimal approach to upgrades since it tightly couples the upgrade with the existing tokens. This EIP promotes the use of a third contract to facilitate the token upgrade to decouple the functionality of the upgrade from the functionality of the token contracts. Standardizing the upgrade functionality will allow asset holders and exchanges to write simplified reusable scripts to conduct upgrades which will reduce the overhead of conducting upgrades in the future. The interface aims to be intentionally broad leaving much of the specifics of the upgrade to the implementer, so that the token contract implementations do not interfere with the upgrade process. Finally, we hope to create a greater sense of security and validity for token upgrades by enforcing strict means of disposing of the source tokens during the upgrade. This is achieved by the specification of the  `upgrade` method. The agreed upon norm is that burnable tokens shall be burned. Otherwise, tokens shall be effectively burned by being sent to the `0x00` address. When downgrade Optional Ext. is implemented, the default is instead to lock source tokens in the upgrade contract to avoid a series of consecutive calls to `upgrade` and `downgrade` from artificially inflating the supply of either token (source or destination).

## Backwards Compatibility
There are no breaking backwards compatibility issues. There are previously implemented token upgrades that likely do not adhere to this standard. In these cases, it may be relevant for the asset issuers to communicate that their upgrade is not EIP-4931 compliant.

## Reference Implementation
``` solidity
//SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.9;

import &quot;@openzeppelin/contracts/token/ERC20/IERC20.sol&quot;;
import &quot;@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol&quot;;
import &quot;./IEIP4931.sol&quot;;

contract SourceUpgrade is  IEIP4931 {
	using SafeERC20  for IERC20;

	uint256 constant RATIO_SCALE = 10**18;
    
	IERC20 private source;
	IERC20 private destination;
	bool private upgradeStatus;
	bool private downgradeStatus;
	uint256 private numeratorRatio;
	uint256 private denominatorRatio;
	uint256 private sourceUpgradedTotal;

	mapping(address =&gt; uint256) public upgradedBalance;

	constructor(address _source, address _destination, bool _upgradeStatus, bool _downgradeStatus, uint256 _numeratorRatio, uint256 _denominatorRatio) {
		require(_source != _destination, &quot;SourceUpgrade: source and destination addresses are the same&quot;);
		require(_source != address(0), &quot;SourceUpgrade: source address cannot be zero address&quot;);
		require(_destination != address(0), &quot;SourceUpgrade: destination address cannot be zero address&quot;);
		require(_numeratorRatio &gt; 0, &quot;SourceUpgrade: numerator of ratio cannot be zero&quot;);
		require(_denominatorRatio &gt; 0, &quot;SourceUpgrade: denominator of ratio cannot be zero&quot;);

		source = IERC20(_source);
		destination = IERC20(_destination);
		upgradeStatus = _upgradeStatus;
		downgradeStatus = _downgradeStatus;
		numeratorRatio = _numeratorRatio;
		denominatorRatio = _denominatorRatio;
	}

	/// @dev A getter to determine the contract that is being upgraded from (&quot;source contract&quot;)
	/// @return The address of the source token contract
	function upgradeSource() external view returns(address) {
		return address(source);
	}

	/// @dev A getter to determine the contract that is being upgraded to (&quot;destination contract&quot;)
	/// @return The address of the destination token contract
	function upgradeDestination() external view returns(address) {
		return address(destination);
	}

	/// @dev The method will return true when the contract is serving upgrades and otherwise false
	/// @return The status of the upgrade as a boolean
	function isUpgradeActive() external view returns(bool) {
		return upgradeStatus;
	}

	/// @dev The method will return true when the contract is serving downgrades and otherwise false
	/// @return The status of the downgrade as a boolean
	function isDowngradeActive() external view returns(bool) {
		return downgradeStatus;
	}

	/// @dev A getter for the ratio of destination tokens to source tokens received when conducting an upgrade
	/// @return Two uint256, the first represents the numerator while the second represents
	/// the denominator of the ratio of destination tokens to source tokens allotted during the upgrade
	function ratio() external view returns(uint256, uint256) {
		return (numeratorRatio, denominatorRatio);
	}

	/// @dev A getter for the total amount of source tokens that have been upgraded to destination tokens.
	/// The value may not be strictly increasing if the downgrade Optional Ext. is implemented.
	/// @return The number of source tokens that have been upgraded to destination tokens
	function totalUpgraded() external view returns(uint256) {
		return sourceUpgradedTotal;
	}

	/// @dev A method to mock the upgrade call determining the amount of destination tokens received from an upgrade
	/// as well as the amount of source tokens that are left over as remainder
	/// @param sourceAmount The amount of source tokens that will be upgraded
	/// @return destinationAmount A uint256 representing the amount of destination tokens received if upgrade is called
	/// @return sourceRemainder A uint256 representing the amount of source tokens left over as remainder if upgrade is called
	function computeUpgrade(uint256 sourceAmount)
		public
		view
		returns (uint256 destinationAmount, uint256 sourceRemainder)
	{
		sourceRemainder = sourceAmount % (numeratorRatio / denominatorRatio);
		uint256 upgradeableAmount = sourceAmount - (sourceRemainder * RATIO_SCALE);
		destinationAmount = upgradeableAmount * (numeratorRatio / denominatorRatio);
	}

	/// @dev A method to mock the downgrade call determining the amount of source tokens received from a downgrade
	/// as well as the amount of destination tokens that are left over as remainder
	/// @param destinationAmount The amount of destination tokens that will be downgraded
	/// @return sourceAmount A uint256 representing the amount of source tokens received if downgrade is called
	/// @return destinationRemainder A uint256 representing the amount of destination tokens left over as remainder if upgrade is called
	function computeDowngrade(uint256 destinationAmount)
		public
		view
		returns (uint256 sourceAmount, uint256 destinationRemainder)
	{
		destinationRemainder = destinationAmount % (denominatorRatio / numeratorRatio);
		uint256 upgradeableAmount = destinationAmount - (destinationRemainder * RATIO_SCALE);
		sourceAmount = upgradeableAmount / (denominatorRatio / numeratorRatio);
	}

	/// @dev A method to conduct an upgrade from source token to destination token.
	/// The call will fail if upgrade status is not true, if approve has not been called
	/// on the source contract, or if sourceAmount is larger than the amount of source tokens at the msg.sender address.
	/// If the ratio would cause an amount of tokens to be destroyed by rounding/truncation, the upgrade call will
	/// only upgrade the nearest whole amount of source tokens returning the excess to the msg.sender address.
	/// Emits the Upgrade event
	/// @param _to The address the destination tokens will be sent to upon completion of the upgrade
	/// @param sourceAmount The amount of source tokens that will be upgraded
	function upgrade(address _to, uint256 sourceAmount) external {
		require(upgradeStatus == true, &quot;SourceUpgrade: upgrade status is not active&quot;);
		(uint256 destinationAmount, uint256 sourceRemainder) = computeUpgrade(sourceAmount);
		sourceAmount -= sourceRemainder;
		require(sourceAmount &gt; 0, &quot;SourceUpgrade: disallow conversions of zero value&quot;);

		upgradedBalance[msg.sender] += sourceAmount;
		source.safeTransferFrom(
			msg.sender,
			address(this),
			sourceAmount
			);
		destination.safeTransfer(_to, destinationAmount);
		sourceUpgradedTotal += sourceAmount;
		emit Upgrade(msg.sender, _to, sourceAmount, destinationAmount);
	}

	/// @dev A method to conduct a downgrade from destination token to source token.
	/// The call will fail if downgrade status is not true, if approve has not been called
	/// on the destination contract, or if destinationAmount is larger than the amount of destination tokens at the msg.sender address.
	/// If the ratio would cause an amount of tokens to be destroyed by rounding/truncation, the downgrade call will only downgrade
	/// the nearest whole amount of destination tokens returning the excess to the msg.sender address.
	///  Emits the Downgrade event
	/// @param _to The address the source tokens will be sent to upon completion of the downgrade
	/// @param destinationAmount The amount of destination tokens that will be downgraded
	function downgrade(address _to, uint256 destinationAmount) external {
		require(upgradeStatus == true, &quot;SourceUpgrade: upgrade status is not active&quot;);
		(uint256 sourceAmount, uint256 destinationRemainder) = computeDowngrade(destinationAmount);
		destinationAmount -= destinationRemainder;
		require(destinationAmount &gt; 0, &quot;SourceUpgrade: disallow conversions of zero value&quot;);
		require(upgradedBalance[msg.sender] &gt;= sourceAmount,
			&quot;SourceUpgrade: can not downgrade more than previously upgraded&quot;
			);

		upgradedBalance[msg.sender] -= sourceAmount;
		destination.safeTransferFrom(
			msg.sender,
			address(this),
			destinationAmount
			);
		source.safeTransfer(_to, sourceAmount);
		sourceUpgradedTotal -= sourceAmount;
		emit Downgrade(msg.sender, _to, sourceAmount, destinationAmount);
	}
}
```


## Security Considerations
The main security consideration is ensuring the implementation of the interface handles the source tokens during the upgrade in such a way that they are no longer accessible. Without careful handling, the validity of the upgrade may come into question since source tokens could potentially be upgraded multiple times. This is why EIP-4931 will strictly enforce the use of `burn` for source tokens that are burnable. For non-burnable tokens, the accepted method is to send the source tokens to the `0x00` address. When the downgrade Optional Ext. is implemented, the constraint will be relaxed, so that the source tokens can be held by the upgrade contract.

## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).

</description>
        <pubDate>Tue, 02 Nov 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4931</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4931</guid>
      </item>
    
      <item>
        <title>eth/67 - Removal of GetNodeData</title>
        <category>Standards Track/Networking</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4938-removal-of-getnodedata/8893</comments>
        
        <description>## Abstract

The [Ethereum Wire Protocol](https://github.com/ethereum/devp2p/blob/40ab248bf7e017e83cc9812a4e048446709623e8/caps/eth.md) defines request and response messages for exchanging data between clients. The `GetNodeData` request retrieves a set of trie nodes or contract code from the state trie by hash. We propose to remove the `GetNodeData` and `NodeData` messages from the wire protocol.

## Motivation

`GetNodeData` and `NodeData` were introduced in protocol version `eth/63` to allow for a sync mode called &quot;fast sync&quot;, which downloads the Ethereum state without executing all blocks. The sync algorithm works by requesting all state trie nodes and contract codes by their hash.

Serving `GetNodeData` requests requires clients to store state as a mapping of hashes to trie nodes. Avoiding the need to store such a mapping in the database is the main motivation for removing this request type.

At this time, some client implementations cannot serve `GetNodeData` requests because they do not store the state in a compatible way. The Ethereum Wire Protocol should accurately reflect the capabilities of clients, and should not contain messages which are impossible to implement in some clients.

## Specification

Remove the following message types from the `eth` protocol:

* `GetNodeData (0x0d)`
   * **(eth/66)**: `[request_id: P, [hash_0: B_32, hash_1: B_32, ...]]`
* `NodeData (0x0e)`
   * **(eth/66)**: `[request_id: P, [value_0: B, value_1: B, ...]]`

## Rationale

A replacement for `GetNodeData` is available in the [snap protocol](https://github.com/ethereum/devp2p/blob/40ab248bf7e017e83cc9812a4e048446709623e8/caps/snap.md). Specifically, clients can use the [GetByteCodes](https://github.com/ethereum/devp2p/blob/40ab248bf7e017e83cc9812a4e048446709623e8/caps/snap.md#getbytecodes-0x04) and [GetTrieNodes](https://github.com/ethereum/devp2p/blob/40ab248bf7e017e83cc9812a4e048446709623e8/caps/snap.md#gettrienodes-0x06) messages instead of `GetNodeData`. The snap protocol can be used to implement the &quot;fast sync&quot; algorithm, though it is recommended to use it for &quot;snap sync&quot;.

## Backwards Compatibility

This EIP changes the `eth` protocol and requires rolling out a new version, `eth/67`. 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 `eth/66`.

This EIP does not change consensus rules of the EVM and does not require a hard fork.

## Security Considerations

None

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Wed, 23 Mar 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4938</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4938</guid>
      </item>
    
      <item>
        <title>Contract with Exactly One Non-fungible Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc721-minting-only-one-token/8602/2</comments>
        
        <description>## Abstract

The following describes standard functions for an [ERC-721](/EIPs/EIPS/eip-721) compatible contract with a total supply of one.
This allows an NFT to be associated uniquely with a single contract address.

## Motivation

If the ERC-721 was modified to mint only 1 token (per contract), then the contract address could be identified uniquely with that minted token (instead of the tuple contract address + token id, as ERC-721 requires).
This change would enable automatically all the capabilities of composable tokens [ERC-998](/EIPs/EIPS/eip-998) (own other ERC-721 or [ERC-20](/EIPs/EIPS/eip-20)) natively without adding any extra code, just forbidding to mint more than one token per deployed contract.
Then the NFT minted with this contract could operate with his &quot;budget&quot; (the ERC-20 he owned) and also trade with the other NFTs he could own. Just like an autonomous agent, that could decide what to do with his properties (sell his NFTs, buy other NFTs, etc).

The first use case that is devised is for value preservation. Digital assets, as NFTs, have value that has to be preserved in order to not be lost. If the asset has its own budget (in other ERC-20 coins), could use it to autopreserve itself.

## Specification

The constructor should mint the unique token of the contract, and then the mint function should add a restriction to avoid further minting.

Also, a `tokenTransfer` function should be added in order to allow the contract owner to transact with the ERC-20 tokens owned by the contract/NFT itself. So that if the contract receives a transfer of ERC-20 tokens, the owner of the NFT could spend it from the contract wallet.

## Rationale

The main motivation is to keep the contract compatible with current ERC-721 platforms.

## Backwards Compatibility

There are no backwards compatibility issues.

## Reference Implementation

Add the variable `_minted` in the contract:

``` solidity
    bool private _minted;
```

In the constructor, automint the first token and set the variable to true:

``` solidity
    constructor(string memory name, string memory symbol, string memory base_uri) ERC721(name, symbol) {
        baseUri = base_uri;
        mint(msg.sender,0);
        _minted = true;
    }
```

Add additional functions to interact with the NFT properties (for instance, ERC-20):

``` solidity
    modifier onlyOwner() {
        require(balanceOf(msg.sender) &gt; 0, &quot;Caller is not the owner of the NFT&quot;);
        _;
    }

    function transferTokens(IERC20 token, address recipient, uint256 amount) public virtual onlyOwner {
        token.transfer(recipient, amount);
    }
	
    function balanceTokens(IERC20 token) public view virtual returns (uint256) {
        return token.balanceOf(address(this));
    }
```

## Security Considerations

No security issues found.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 25 Mar 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4944</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4944</guid>
      </item>
    
      <item>
        <title>Entangled Tokens</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/entangled-tokens/8702</comments>
        
        <description>## Abstract

This EIP defines an interface for delegating control of a smart contract wallet to pairs of users using entangled [ERC-721](/EIPs/EIPS/eip-721) non-fungible tokens.

## Motivation

The motivation is to provide an easy way to share a wallet through NFTs, so that the act of buying an NFT (in a marketplace) gives the buyer the privilege to have access to a given wallet. This wallet could have budget in many tokens, or even be the owner of other NFTs.

A use case is to keep contact between an artist and an buyer of its NFTs. If an artist T has created a digital piece of art P with an NFT, then T creates 2 entangled tokens A and B so that he keeps A and transfer B to P. By construction of entangled tokens, only one transfer is possible for them, thus the artist proofs he’s been the creator of P by sending a transaction to A that is visible from B. Otherwise, the owner of P might check the authenticity of the artist by sending a transaction to B so that the artist might proof by showing the outcome out of A.

A version of this use case is when one user U mints his piece of art directly in the form of an entangled token A; then the user U sells/transfers it while keeping the entangled token B in the U&apos;s wallet. The piece of art and the artists will be entangled whoever is the A&apos;s owner.

These applications of entangled tokens are envisaged to be useful for:

1.	NFT authorship / art creation
2.	Distribution of royalties by the creator.
3.	Authenticity of a work of art: creation limited to the author (e.g. only 1000 copies if there are 1000 1000 entangled tokens in that NFT).
4.	Usowners (users that consume an NFT also become -partial- owners of the NFT)
5.	Reformulation of property rights: the one who owns the property receives it without having to follow in the footsteps of the owners.
6.	Identity: Only those credentials that have an entangled token with you are related to you.
7.	Vreservers (value-reservers).

## Specification

An entangled token contract implements [ERC-721](/EIPs/EIPS/eip-721) with the additional restriction that it only ever mints exactly two tokens at contract deployment: one with a `tokenId` of `0`, the other with a `tokenId` of `1`. The entangled token contract also implements a smart contract wallet that can be operated by the owners of those two tokens.

Also, a `tokenTransfer` function is to be be added in order to allow the token owners to transact with the [ERC-20](/EIPs/EIPS/eip-20) tokens owned by the contract/NFT itself. The function signature is as follows:

```solidity
    function tokenTransfer(IERC20 token, address recipient, uint256 amount) public onlyOwners;
```

## Rationale

We decide to extend [ERC-721](/EIPs/EIPS/eip-721) ([ERC-1155](/EIPs/EIPS/eip-1155) could be also possible) because the main purpose of this is to be compatible with current marketplaces platforms. This entangled NFTs will be listed in a marketplace, and the user who buys it will have then the possibility to transact with the wallet properties (fungible and non fungible tokens).

## Backwards Compatibility

No backwards compatibility issues.

## Reference Implementation

Mint two tokens, and only two, at the contract constructor, and set the `minted` property to true:

```solidity
bool private _minted;

constructor(string memory name, string memory symbol, string memory base_uri) ERC721(name, symbol) {
        baseUri = base_uri;
        _mint(msg.sender,0);
        _mint(msg.sender,1);
        _minted = true;
    }

function _mint(address to, uint256 tokenId) internal virtual override {
    require(!_minted, &quot;ERC4950: already minted&quot;);
    super._mint(to, tokenId);
}
```

Add additional functions to allow both NFT user owners to operate with other ERC-20 tokens owned by the contract:

```solidity
    modifier onlyOwners() {
        require(balanceOf(msg.sender) &gt; 0, &quot;Caller does not own any of the tokens&quot;);
        _;
    }

function tokenTransfer(IERC20 token, address recipient, uint256 amount) public onlyOwners {
        token.transfer(recipient, amount);
    }
```

## Security Considerations

There are no security considerations.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 28 Mar 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4950</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4950</guid>
      </item>
    
      <item>
        <title>Vendor Metadata Extension for NFTs</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4955-non-fungible-token-metadata-namespaces-extension/8746</comments>
        
        <description>## Abstract

This EIP standardizes a schema for NFTs metadata to add new field namespaces to the JSON schema for [EIP-721](/EIPs/EIPS/eip-721) and [EIP-1155](/EIPs/EIPS/eip-1155) NFTs.

## Motivation

A standardized NFT metadata schema allows wallets, marketplaces, metaverses, and similar applications to interoperate with any NFT. Applications such as NFT marketplaces and metaverses could usefully leverage NFTs by rendering them using custom 3D representations or any other new attributes.

Some projects like Decentraland, TheSandbox, Cryptoavatars, etc. need their own 3D model in order to represent an NFT. These models are not cross-compatible because of distinct aesthetics and data formats.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### Schema

(subject to &quot;caveats&quot; below)

A new property called `namespaces` is introduced. This property expects one object per project as shown in the example below.

```jsonc
{
    &quot;title&quot;: &quot;Asset Metadata&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;name&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Identifies the asset that this NFT represents&quot;
        },
        &quot;description&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Describes the asset that this NFT represents&quot;
        },
        &quot;image&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;A URI pointing to a resource with mime type image/* representing the asset that this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive.&quot;
        },
        &quot;namespaces&quot;: {
          &quot;type&quot;: &quot;object&quot;,
          &quot;description&quot;: &quot;Application-specific NFT properties&quot;
        }
    }
}
```

### Example

```jsonc
{
  &quot;name&quot;: &quot;My NFT&quot;,
  &quot;description&quot;: &quot;NFT description&quot;,
  &quot;image&quot;: &quot;ipfs://QmZfmRZHuawJDtDVMaEaPWfgWFV9iXoS9SzLvwX76wm6pa&quot;,
  &quot;namespaces&quot;: {
    &quot;myAwesomeCompany&quot;: {
      &quot;prop1&quot;: &quot;value1&quot;,
      &quot;prop2&quot;: &quot;value2&quot;,
    },
    &quot;myAwesomeCompany2&quot;: {
      &quot;prop3&quot;: &quot;value3&quot;,
      &quot;prop4&quot;: &quot;value4&quot;,
    },
  }
}

// Or by simply using a `URI` to reduce the size of the JSON response.

{
  &quot;name&quot;: &quot;My NFT&quot;,
  &quot;description&quot;: &quot;NFT description&quot;,
  &quot;image&quot;: &quot;ipfs://QmZfmRZHuawJDtDVMaEaPWfgWFV9iXoS9SzLvwX76wm6pa&quot;,
  &quot;namespaces&quot;: {
    &quot;myAwesomeCompany&quot;: &quot;URI&quot;,
    &quot;myAwesomeCompany2&quot;: &quot;URI&quot;,
  }
}
```

## Rationale

There are many projects which need custom properties in order to display a current NFT. Each project may have its own way to render the NFTs and therefore they need different values. An example of this is the metaverses like Decentraland or TheSandbox where they need different 3d models to render the NFT based on the visual/engine of each. NFTs projects like Cryptopunks, Bored Apes, etc. can create the 3d models needed for each project and therefore be supported out of the box.

The main differences between the projects that are rendering 3d NFTs (models) are:

### Armatures

Every metaverse uses its own armature. There is a standard for humanoids but it is not being used for every metaverse and not all the metaverses use humanoids. For example, Decentraland has a different aesthetic than Cryptovoxels and TheSandbox. It means that every metaverse will need a different model and they may have the same extension (GLB, GLTF)

![](/EIPs/assets/eip-4955/different-renders.jpeg)

### Metadata (Representations Files)

For example, every metaverse uses its own metadata representation files to make it work inside the engine depending on its game needs.

This is the JSON config of a wearable item in Decentraland:

```jsonc
&quot;data&quot;: {
  &quot;replaces&quot;: [],
  &quot;hides&quot;: [],
  &quot;tags&quot;: [],
  &quot;category&quot;: &quot;upper_body&quot;,
  &quot;representations&quot;: [
    {
      &quot;bodyShapes&quot;: [
        &quot;urn:decentraland:off-chain:base-avatars:BaseMale&quot;
      ],
      &quot;mainFile&quot;: &quot;male/Look6_Tshirt_A.glb&quot;,
      &quot;contents&quot;: [
        {
          &quot;key&quot;: &quot;male/Look6_Tshirt_A.glb&quot;,
          &quot;url&quot;: &quot;https://peer-ec2.decentraland.org/content/contents/QmX3yMhmx4AvGmyF3CM5ycSQB4F99zXh9rL5GvdxTTcoCR&quot;
        }
      ],
      &quot;overrideHides&quot;: [],
      &quot;overrideReplaces&quot;: []
    },
    {
      &quot;bodyShapes&quot;: [
        &quot;urn:decentraland:off-chain:base-avatars:BaseFemale&quot;
      ],
      &quot;mainFile&quot;: &quot;female/Look6_Tshirt_B (1).glb&quot;,
      &quot;contents&quot;: [
        {
          &quot;key&quot;: &quot;female/Look6_Tshirt_B (1).glb&quot;,
          &quot;url&quot;: &quot;https://peer-ec2.decentraland.org/content/contents/QmcgddP4L8CEKfpJ4cSZhswKownnYnpwEP4eYgTxmFdav8&quot;
        }
      ],
      &quot;overrideHides&quot;: [],
      &quot;overrideReplaces&quot;: []
    }
  ]
},
&quot;image&quot;: &quot;https://peer-ec2.decentraland.org/content/contents/QmPnzQZWAMP4Grnq6phVteLzHeNxdmbRhKuFKqhHyVMqrK&quot;,
&quot;thumbnail&quot;: &quot;https://peer-ec2.decentraland.org/content/contents/QmcnBFjhyFShGo9gWk2ETbMRDudiX7yjn282djYCAjoMuL&quot;,
&quot;metrics&quot;: {
  &quot;triangles&quot;: 3400,
  &quot;materials&quot;: 2,
  &quot;textures&quot;: 2,
  &quot;meshes&quot;: 2,
  &quot;bodies&quot;: 2,
  &quot;entities&quot;: 1
}
```

`replaces`, `overrides`, `hides`, and different body shapes representation for the same asset are needed for Decentraland in order to render the 3D asset correctly.

Using `namespaces` instead of objects like the ones below make it easy for the specific vendor/third-parties to access and index the required models. Moreover, `styles` do not exist because there are no standards around for how an asset will be rendered. As I mentioned above, each metaverse for example uses its own armature and aesthetic. There is no Decentraland-style or TheSandbox-style that other metaverses use. Each of them is unique and specific for the sake of the platform&apos;s reason of being. Projects like Cryptoavatars are trying to push different standards but without luck for the same reasons related to the uniquity of the armature/animations/metadata.

```jsonc
{
    &quot;id&quot;: &quot;model&quot;,
    &quot;type&quot;: &quot;model/gltf+json&quot;,
    &quot;style&quot;: &quot;Decentraland&quot;,
    &quot;uri&quot;: &quot;...&quot;
},

// Or

{
    &quot;id&quot;: &quot;model&quot;,
    &quot;type&quot;: &quot;model/gltf+json&quot;,
    &quot;style&quot;: &quot;humanoide&quot;,
    &quot;uri&quot;: &quot;...&quot;
},
```

With `namespaces`, each vendor will know how to render an asset by doing:

```ts
fetch(metadata.namespaces[&quot;PROJECT_NAME&quot;].uri).then(res =&gt; render(res))
```

The idea behind extending the [EIP-721](/EIPs/EIPS/eip-721) metadata schema is for backward compatibility. Most projects on Ethereum use non-upgradeable contracts. If this EIP required new implementations of those contracts, they would have to be re-deployed. This is time-consuming and wastes money. Leveraging EIP-721&apos;s existing metadata  field minimizes the number of changes necessary. Finally, the JSON metadata is already used to store representations using the `image` field. It seems reasonable to have all the representations of an asset in the same place.

## Backwards Compatibility

Existing projects that can&apos;t modify the metadata response (schema), may be able to create a new smart contract that based on the `tokenId` returns the updated metadata schema. Of course, the projects may need to accept these linked smart contracts as valid in order to fetch the metadata by the `tokenURI` function.

## Security Considerations

The same security considerations as with [EIP-721](/EIPs/EIPS/eip-721) apply related to using http gateways or IPFS for the tokenURI method.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 29 Mar 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4955</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4955</guid>
      </item>
    
      <item>
        <title>Name-Owned Account</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4972-name-owned-account/8822</comments>
        
        <description>## Abstract

The ERC suggests expanding the capabilities of the name service, such as ENS, by enabling each human-readable identity to be linked to a single smart contract account that can be controlled by the owner of the name identity.

## Motivation

Name itself cannot hold any context. We want to build an extension of name service to give name rich context by offering each name owner an extra ready to use smart contract account, which may help the general smart contract account adoption. With NOA, it is possible to hold assets and information for its name node, opening up new use cases such as name node transfers, which involve transferring ownership of the name node as well as the NOA, including any assets and information it holds.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### Name-Owned Account

An NOA has

- a human readable name defined by [ERC-137](/EIPs/EIPS/eip-137); and
- an owned account(NOA), which is an smart contract account whose address is derived from the name; and
- owner(s) of the name that can deploy and manipulate the owned account.

The following diagram illustrates the relationship between NOA, name node, and name owner, with the ownership being guaranteed by the name service.

      ┌───────────────┐        ┌───────────┐         ┌───────────────┐
      │ Owned Account ◄──own───┤ Name Node ◄───own───┤   Name Owner  │
      └───────────────┘        └───────────┘         └───────────────┘

### Interface

The core interface required for a name service to have is:

	interface INameServiceRegistry {
	    /// @notice get account address owned by the name node
	    /// @params node represents a name node
	    /// @return the address of an account
	    function ownedAccount(
	        bytes32 node
	    ) external view returns(address);
	}

The core interface required for the name owned account is:

	interface INameOwnedAccount {
	    /// @notice get the name node is mapped to this account address
	    /// @return return a name node
	    function name() external view returns(bytes32);

	    /// @notice get the name service contract address where
	    /// the name is registered
	    /// @return return the name service the name registered at
	    function nameService() external view returns(address);
	}

## Rationale

To achieve a one-to-one mapping from the name to the NOA, where each NOA&apos;s address is derived from the name node, we must include the name node information in each NOA to reflect its name node ownership. The &quot;name()&quot; function can be used to retrieve this property of each NOA and enable reverse tracking to its name node. The &quot;nameService()&quot; function can get the name service contract address where the name is registered, to perform behaviors such as validation checks. Through these two methods, the NOA has the ability to track back to its actual owner who owns the name node.

## Backwards Compatibility

The name registry interface is compatible with ERC-137.

## Reference Implementation

### Name Owned Account Creation

The NOA creation is done by a “factory” contract. The factory could be the name service itself and is expected to use CREATE2 (not CREATE) to create the NOA. NOAs should have identical initcode and factory contract in order to achieve deterministic preservation of address. The name node can be used as the salt to guarantee the bijection from name to its owned account.

## Security Considerations

No security considerations were found.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 04 Apr 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4972</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4972</guid>
      </item>
    
      <item>
        <title>Account-bound Tokens</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4973-non-transferrable-non-fungible-tokens-soulbound-tokens-or-badges/8825</comments>
        
        <description>## Abstract

Proposes a standard API for account-bound Tokens (ABT) within smart contracts. An ABT is a non-fungible token bound to a single account. ABTs don&apos;t implement a canonical interface for transfers. This EIP defines basic functionality to mint, assign, revoke and track ABTs.

## Motivation

In the popular MMORPG World of Warcraft, its game designers intentionally took some items out of the world&apos;s auction house market system to prevent them from having a publicly-discovered price and limit their accessibility.

Vanilla WoW&apos;s &quot;Thunderfury, Blessed Blade of the Windseeker&quot; was one such legendary item, and it required a forty-person raid, among other sub-tasks, to slay the firelord &quot;Ragnaros&quot; to gain the &quot;Essence of the Firelord,&quot; a material needed to craft the sword once.

Upon voluntary pickup, the sword permanently **binds** to a character&apos;s &quot;soul,&quot; making it impossible to trade, sell or even swap it between a player&apos;s characters.

In other words, &quot;Thunderfury&quot;&apos;s price was the aggregate of all social costs related to completing the difficult quest line with friends and guild members. Other players spotting Thunderfuries could be sure their owner had slain &quot;Ragnaros,&quot; the blistering firelord.

World of Warcraft players could **trash** legendary and soulbound items like the Thunderfury to permanently remove them from their account. It was their choice to visibly **equip** or **unequip** an item and hence show their achievements to everyone.

The Ethereum community has expressed a need for non-transferrable, non-fungible, and socially-priced tokens similar to WoW&apos;s soulbound items. Popular contracts implicitly implement account-bound interaction rights today. A principled standardization helps interoperability and improves on-chain data indexing.

The purpose of this document is to make ABTs a reality on Ethereum by creating consensus around a **maximally backward-compatible** but otherwise **minimal** interface definition.

## Specification

### Solidity Interface

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

ABTs _must_ implement the interfaces:

- [ERC-165](/EIPs/EIPS/eip-165)&apos;s `ERC165` (`0x01ffc9a7`)
- [ERC-721](/EIPs/EIPS/eip-721)&apos;s `ERC721Metadata` (`0x5b5e139f`)

ABTs _must not_ implement the interfaces:

- [ERC-721](/EIPs/EIPS/eip-721)&apos;s `ERC721` (`0x80ac58cd`)

An ABT receiver must be able to always call `function unequip(address _tokenId)` to take their ABT off-chain.

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.6;

/// @title Account-bound tokens
/// @dev See https://eips.ethereum.org/EIPS/eip-4973
/// Note: the ERC-165 identifier for this interface is 0xeb72bb7c
interface IERC4973 {
  /// @dev This emits when ownership of any ABT changes by any mechanism.
  ///  This event emits when ABTs are given or equipped and unequipped
  ///  (`to` == 0).
  event Transfer(
    address indexed from, address indexed to, uint256 indexed tokenId
  );

  /// @notice Count all ABTs assigned to an owner
  /// @dev ABTs assigned to the zero address are considered invalid, and this
  ///  function throws for queries about the zero address.
  /// @param owner An address for whom to query the balance
  /// @return The number of ABTs owned by `address owner`, possibly zero
  function balanceOf(address owner) external view returns (uint256);

  /// @notice Find the address bound to an ERC4973 account-bound token
  /// @dev ABTs assigned to zero address are considered invalid, and queries
  ///  about them do throw.
  /// @param tokenId The identifier for an ABT.
  /// @return The address of the owner bound to the ABT.
  function ownerOf(uint256 tokenId) external view returns (address);

  /// @notice Removes the `uint256 tokenId` from an account. At any time, an
  ///  ABT receiver must be able to disassociate themselves from an ABT
  ///  publicly through calling this function. After successfully executing this
  ///  function, given the parameters for calling `function give` or
  ///  `function take` a token must be re-equipable.
  /// @dev Must emit a `event Transfer` with the `address to` field pointing to
  ///  the zero address.
  /// @param tokenId The identifier for an ABT.
  function unequip(uint256 tokenId) external;

  /// @notice Creates and transfers the ownership of an ABT from the
  ///  transaction&apos;s `msg.sender` to `address to`.
  /// @dev Throws unless `bytes signature` represents a signature of the
  //   EIP-712 structured data hash
  ///  `Agreement(address active,address passive,bytes metadata)` expressing
  ///  `address to`&apos;s explicit agreement to be publicly associated with
  ///  `msg.sender` and `bytes metadata`. A unique `uint256 tokenId` must be
  ///  generated by type-casting the `bytes32` EIP-712 structured data hash to a
  ///  `uint256`. If `bytes signature` is empty or `address to` is a contract,
  ///  an EIP-1271-compatible call to `function isValidSignatureNow(...)` must
  ///  be made to `address to`. A successful execution must result in the
  ///  `event Transfer(msg.sender, to, tokenId)`. Once an ABT exists as an
  ///  `uint256 tokenId` in the contract, `function give(...)` must throw.
  /// @param to The receiver of the ABT.
  /// @param metadata The metadata that will be associated to the ABT.
  /// @param signature A signature of the EIP-712 structured data hash
  ///  `Agreement(address active,address passive,bytes metadata)` signed by
  ///  `address to`.
  /// @return A unique `uint256 tokenId` generated by type-casting the `bytes32`
  ///  EIP-712 structured data hash to a `uint256`.
  function give(address to, bytes calldata metadata, bytes calldata signature)
    external
    returns (uint256);

  /// @notice Creates and transfers the ownership of an ABT from an
  /// `address from` to the transaction&apos;s `msg.sender`.
  /// @dev Throws unless `bytes signature` represents a signature of the
  ///  EIP-712 structured data hash
  ///  `Agreement(address active,address passive,bytes metadata)` expressing
  ///  `address from`&apos;s explicit agreement to be publicly associated with
  ///  `msg.sender` and `bytes metadata`. A unique `uint256 tokenId` must be
  ///  generated by type-casting the `bytes32` EIP-712 structured data hash to a
  ///  `uint256`. If `bytes signature` is empty or `address from` is a contract,
  ///  an EIP-1271-compatible call to `function isValidSignatureNow(...)` must
  ///  be made to `address from`. A successful execution must result in the
  ///  emission of an `event Transfer(from, msg.sender, tokenId)`. Once an ABT
  ///  exists as an `uint256 tokenId` in the contract, `function take(...)` must
  ///  throw.
  /// @param from The origin of the ABT.
  /// @param metadata The metadata that will be associated to the ABT.
  /// @param signature A signature of the EIP-712 structured data hash
  ///  `Agreement(address active,address passive,bytes metadata)` signed by
  ///  `address from`.

  /// @return A unique `uint256 tokenId` generated by type-casting the `bytes32`
  ///  EIP-712 structured data hash to a `uint256`.
  function take(address from, bytes calldata metadata, bytes calldata signature)
    external
    returns (uint256);

  /// @notice Decodes the opaque metadata bytestring of an ABT into the token
  ///  URI that will be associated with it once it is created on chain.
  /// @param metadata The metadata that will be associated to an ABT.
  /// @return A URI that represents the metadata.
  function decodeURI(bytes calldata metadata) external returns (string memory);
}
```

See [ERC-721](/EIPs/EIPS/eip-721) for a definition of its metadata JSON Schema.

### [EIP-712](/EIPs/EIPS/eip-712) Typed Structured Data Hashing and Bytearray Signature Creation

To invoke `function give(...)` and `function take(...)` a bytearray signature must be created using [EIP-712](/EIPs/EIPS/eip-712). A tested reference implementation in Node.js is attached at [index.mjs](/EIPs/assets/eip-4973/sdk/src/index.mjs), [index_test.mjs](/EIPs/assets/eip-4973/sdk/test/index_test.mjs) and [package.json](/EIPs/assets/eip-4973/package.json). In Solidity, this bytearray signature can be created as follows:

```solidity
bytes32 r = 0x68a020a209d3d56c46f38cc50a33f704f4a9a10a59377f8dd762ac66910e9b90;
bytes32 s = 0x7e865ad05c4035ab5792787d4a0297a43617ae897930a6fe4d822b8faea52064;
uint8 v   = 27;
bytes memory signature = abi.encodePacked(r, s, v);
```

## Rationale

### Interface

ABTs shall be maximally backward-compatible but still only expose a minimal and simple to implement interface definition.

As [ERC-721](/EIPs/EIPS/eip-721) tokens have seen widespread adoption with wallet providers and marketplaces, using its `ERC721Metadata` interface with [ERC-165](/EIPs/EIPS/eip-165) for feature-detection potentially allows implementers to support ABTs out of the box.

If an implementer of [ERC-721](/EIPs/EIPS/eip-721) properly built [ERC-165](/EIPs/EIPS/eip-165)&apos;s `function supportsInterface(bytes4 interfaceID)` function, already by recognizing that [ERC-721](/EIPs/EIPS/eip-721)&apos;s track and transfer interface component with the identifier `0x80ac58cd` is not implemented, transferring of a token should not be suggested as a user interface option.

Still, since ABTs support [ERC-721](/EIPs/EIPS/eip-721)&apos;s `ERC721Metadata` extension, wallets and marketplaces should display an account-bound token with no changes needed.

Although other implementations of account-bound tokens are possible, e.g., by having all transfer functions revert, ABTs are superior as it supports feature detection through [ERC-165](/EIPs/EIPS/eip-165).

We expose `function unequip(address _tokenId)` and require it to be callable at any time by an ABT&apos;s owner as it ensures an owner&apos;s right to publicly disassociate themselves from what has been issued towards their account.

### Exception handling

Given the non-transferable between accounts property of ABTs, if a user&apos;s keys to an account or a contract get compromised or rotated, a user may lose the ability to associate themselves with the token. In some cases, this can be the desired effect. Therefore, ABT implementers should build re-issuance and revocation processes to enable recourse. We recommend implementing strictly decentralized, permissionless, and censorship-resistant re-issuance processes.

But this document is deliberately abstaining from offering a standardized form of exception handling in cases where user keys are compromised or rotated.

In cases where implementers want to make account-bound tokens shareable among different accounts, e.g., to avoid losing access when keys get compromised, we suggest issuing the account-bound token towards a contract&apos;s account that implements a multi-signature functionality.

### Provenance Indexing

ABTs can be indexed by tracking the emission of `event Transfer(address indexed from, address indexed to, uint256 indexed tokenId)`. As with [ERC-721](/EIPs/EIPS/eip-721), transfers between two accounts are represented by `address from` and `address to` being non-zero addresses. Unequipping a token is represented through emitting a transfer with `address to` being set to the zero address. Mint operations where `address from` is set to zero don&apos;t exist. To avoid being spoofed by maliciously-implemented `event Transfer` emitting contracts, an indexer should ensure that the transaction&apos;s sender is equal to `event Transfer`&apos;s `from` value.

## Backwards Compatibility

We have adopted the [ERC-165](/EIPs/EIPS/eip-165) and `ERC721Metadata` functions purposefully to create a high degree of backward compatibility with [ERC-721](/EIPs/EIPS/eip-721). We have deliberately used [ERC-721](/EIPs/EIPS/eip-721) terminology such as `function ownerOf(...)`, `function balanceOf(...)` to minimize the effort of familiarization for ABT implementers already familiar with, e.g., [ERC-20](/EIPs/EIPS/eip-20) or [ERC-721](/EIPs/EIPS/eip-721). For indexers, we&apos;ve re-used the widely-implemented `event Transfer` event signature.

## Reference Implementation

You can find an implementation of this standard in [ERC-4973-flat.sol](/EIPs/assets/eip-4973/ERC4973-flat.sol).

## Security Considerations

There are no security considerations related directly to the implementation of this standard.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 01 Apr 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4973</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4973</guid>
      </item>
    
      <item>
        <title>Ratings</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/8805</comments>
        
        <description>## Abstract

This standard defines a standardized interface for assigning and managing numerical ratings on the Ethereum blockchain. This allows ratings to be codified within smart contracts and recognized by other applications, enabling a wide range of new use cases for tokens.

## Motivation

Traditionally, blockchain applications have focused on buying and selling digital assets. However, the asset-centric model has often been detrimental to community-based blockchain projects, as seen in the pay-to-play dynamics of many EVM-based games and DAOs in 2021.

This proposal addresses this issue by allowing ratings to be assigned to contracts and wallets, providing a new composable primitive for blockchain applications. This allows for a diverse array of new use cases, such as:

- Voting weight in a DAO: Ratings assigned using this standard can be used to determine the voting weight of members in a decentralized autonomous organization (DAO). For example, a DAO may assign higher ratings to members who have demonstrated a strong track record of contributing to the community, and use these ratings to determine the relative influence of each member in decision-making processes.

- Experience points in a decentralized game ecosystem: Ratings can be used to track the progress of players in a decentralized game ecosystem, and to reward them for achieving specific milestones or objectives. For example, a game may use ratings to assign experience points to players, which can be used to unlock new content or abilities within the game.

- Loyalty points for customers of a business: Ratings can be used to track the loyalty of customers to a particular business or service, and to reward them for their continued support. For example, a business may use ratings to assign loyalty points to customers, which can be redeemed for special offers or discounts.

- Asset ratings for a decentralized insurance company: Ratings can be used to evaluate the risk profile of assets in a decentralized insurance company, and to determine the premiums and coverage offered to policyholders. For example, a decentralized insurance company may use ratings to assess the risk of different types of assets, and to provide lower premiums and higher coverage to assets with lower risk ratings.

This standard is influenced by the [EIP-20](/EIPs/EIPS/eip-20) and [EIP-721](/EIPs/EIPS/eip-721) token standards and takes cues from each in its structure, style, and semantics.

## Specification

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.

Every compliant contract MUST implement the following interfaces:

```
// SPDX-License-Identifier: CC0

pragma solidity ^0.8.0;

/// @title EIP-4974 Ratings
/// @dev See https://eips.ethereum.org/EIPS/EIP-4974
///  Note: the EIP-165 identifier for this interface is #######.
///  Must initialize contracts with an `operator` address that is not `address(0)`.
interface IERC4974 /* is ERC165 */ {

    /// @dev Emits when operator changes.
    ///  MUST emit when `operator` changes by any mechanism.
    ///  MUST ONLY emit by `setOperator`.
    event NewOperator(address indexed _operator);

    /// @dev Emits when operator issues a rating. 
    ///  MUST emit when rating is assigned by any mechanism.
    ///  MUST ONLY emit by `rate`.
    event Rating(address _rated, int8 _rating);

    /// @dev Emits when operator removes a rating. 
    ///  MUST emit when rating is removed by any mechanism.
    ///  MUST ONLY emit by `remove`.
    event Removal(address _removed);

    /// @notice Appoint operator authority.
    /// @dev MUST throw unless `msg.sender` is `operator`.
    ///  MUST throw if `operator` address is either already current `operator`
    ///  or is the zero address.
    ///  MUST emit an `Appointment` event.
    /// @param _operator New operator of the smart contract.
    function setOperator(address _operator) external;

    /// @notice Rate an address.
    ///  MUST emit a Rating event with each successful call.
    /// @param _rated Address to be rated.
    /// @param _rating Total EXP tokens to reallocate.
    function rate(address _rated, int8 _rating) external;

    /// @notice Remove a rating from an address.
    ///  MUST emit a Remove event with each successful call.
    /// @param _removed Address to be removed.
    function removeRating(address _removed) external;

    /// @notice Return a rated address&apos; rating.
    /// @dev MUST register each time `Rating` emits.
    ///  SHOULD throw for queries about the zero address.
    /// @param _rated An address for whom to query rating.
    /// @return int8 The rating assigned.
    function ratingOf(address _rated) external view returns (int8);
}

interface IERC165 {
    /// @notice Query if a contract implements an interface.
    /// @dev Interface identification is specified in EIP-165. This function
    ///  uses less than 30,000 gas.
    /// @param interfaceID The interface identifier, as specified in EIP-165.
    /// @return bool `true` if the contract implements `interfaceID` and
    ///  `interfaceID` is not 0xffffffff, `false` otherwise.
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
```

## Rationale

### Rating Assignment

Ratings SHALL be at the sole discretion of the contract operator. This party may be a sports team coach or a multisig DAO wallet. We decide not to specify how governance occurs, but only *that* governance occurs. This allows for a wider range of potential use cases than optimizing for particular decision-making forms.

This proposal standardizes a control mechanism to allocate community reputation without encouraging financialization of that recognition. While it does not ensure meritocracy, it opens the door.

### Choice of int8

It&apos;s signed: Reviewers should be able to give neutral and negative ratings for the wallets and contracts they interact with. This is especially important for decentralized applications that may be subject to malicious actors.

It&apos;s 8bit: The objective here is to keep ratings within some fathomably comparable range. Longer term, this could encourage easy aggregation of ratings, versus using larger numbers where users might employ a great variety of scales.

### Rating Changes

Ratings SHOULD allow rating updates by contract operators. If Bob has contributed greatly to the community, but then is caught stealing from Alice, the community may decide this should lower Bob&apos;s standing and influence in the community. Again, while this does not ensure an ethical standard within the community, it opens the door.

Relatedly, ratings SHOULD allow removal of ratings to rescind a rating if the rater does not have confidence in their ability to rate effectively.

### Interface Detection

We chose Standard Interface Detection ([EIP-165](/EIPs/EIPS/eip-165)) to expose the interfaces that a compliant smart contract supports.

### Metadata Choices

We have required `name` and `description` functions in the metadata extension. `name` common among major standards for blockchain-based primitives. We included a `description` function that may be helpful for games or other applications with multiple ratings systems.

We remind implementation authors that the empty string is a valid response to `name` and `description` if you protest to the usage of this mechanism. We also remind everyone that any smart contract can use the same name and description as your contract. How a client may determine which ratings smart contracts are well-known (canonical) is outside the scope of this standard.

### Drawbacks

One potential drawback of using this standard is that ratings are subjective and may not always accurately reflect the true value or quality of a contract or wallet. However, the standard provides mechanisms for updating and removing ratings, allowing for flexibility and evolution over time.

Users identified in the motivation section have a strong need to identify how a contract or community evaluates another. While some users may be proud of ratings they receive, others may rightly or wrongly receive negative ratings from certain contracts. Negative ratings may allow for nefarious activities such as bullying and discrimination. We implore all implementers to be mindful of the consequences of any ratings systems they create with this standard.

## Backwards Compatibility

We have adopted the `name` semantics from the EIP-20 and EIP-721 specifications.

## Reference Implementation

A reference implementation of this standard can be found in the assets folder.
&lt;!-- [../assets/EIP-4974/ERC4974.sol](../assets/EIP-4974/ERC4974.sol). --&gt;

## Security Considerations

One potential security concern with this standard is the risk of malicious actors assigning false or misleading ratings to contracts or wallets. This could be used to manipulate voting weights in a DAO, or to deceive users into making poor decisions based on inaccurate ratings.

To address this concern, the standard includes mechanisms for updating and removing ratings, allowing for corrections to be made in cases of false or misleading ratings. Additionally, the use of a single operator address to assign and update ratings provides a single point of control, which can be used to enforce rules and regulations around the assignment of ratings.

Another potential security concern is the potential for an attacker to gain control of the operator address and use it to manipulate ratings for their own benefit. To mitigate this risk, it is recommended that the operator address be carefully managed and protected, and that multiple parties be involved in its control and oversight.

Overall, the security of compliant contracts will depend on the careful management and protection of the operator address, as well as the development of clear rules and regulations around the assignment of ratings.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 02 Apr 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4974</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4974</guid>
      </item>
    
      <item>
        <title>Held token interface</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4987-held-token-standard-nfts-defi/7117</comments>
        
        <description>## Abstract

The proposed standard defines a lightweight interface to expose functional ownership and balances of held tokens. A held token is a token owned by a contract. This standard may be implemented by smart contracts which hold [EIP-20](/EIPs/EIPS/eip-20), [EIP-721](/EIPs/EIPS/eip-721), or [EIP-1155](/EIPs/EIPS/eip-1155) tokens and is intended to be consumed by both on-chain and off-chain systems that rely on ownership and balance verification.

## Motivation

As different areas of crypto (DeFi, NFTs, etc.) converge and composability improves, there will more commonly be a distinction between the actual owner (likely a contract) and the functional owner (likely a user) of a token. Currently, this results in a conflict between mechanisms that require token deposits and systems that rely on those tokens for ownership or balance verification.

This proposal aims to address that conflict by providing a standard interface for token holders to expose ownership and balance information. This will allow users to participate in these DeFi mechanisms without giving up existing token utility. Overall, this would greatly increase interoperability across systems, benefiting both users and protocol developers.

Example implementers of this ERC standard include

- staking or farming contracts
- lending pools
- time lock or vesting vaults
- fractionalized NFT contracts
- smart contract wallets

Example consumers of this ERC standard include

- governance systems
- gaming
- PFP verification
- art galleries or showcases
- token based membership programs

## Specification

Smart contracts implementing the `ERC20` held token standard MUST implement all of the functions in the `IERC20Holder` interface.

Smart contracts implementing the `ERC20` held token standard MUST also implement `ERC165` and return true when the interface ID `0x74c89d54` is passed.

```solidity
/**
 * @notice the ERC20 holder standard provides a common interface to query
 * token balance information
 */
interface IERC20Holder is IERC165 {
  /**
   * @notice emitted when the token is transferred to the contract
   * @param owner functional token owner
   * @param tokenAddress held token address
   * @param tokenAmount held token amount
   */
  event Hold(
    address indexed owner,
    address indexed tokenAddress,
    uint256 tokenAmount
  );

  /**
   * @notice emitted when the token is released back to the user
   * @param owner functional token owner
   * @param tokenAddress held token address
   * @param tokenAmount held token amount
   */
  event Release(
    address indexed owner,
    address indexed tokenAddress,
    uint256 tokenAmount
  );

  /**
   * @notice get the held balance of the token owner
   * @dev should throw for invalid queries and return zero for no balance
   * @param tokenAddress held token address
   * @param owner functional token owner
   * @return held token balance
   */
  function heldBalanceOf(address tokenAddress, address owner)
    external
    view
    returns (uint256);
}

```

Smart contracts implementing the `ERC721` held token standard MUST implement all of the functions in the `IERC721Holder` interface.

Smart contracts implementing the `ERC721` held token standard MUST also implement `ERC165` and return true when the interface ID `0x16b900ff` is passed.

```solidity
/**
 * @notice the ERC721 holder standard provides a common interface to query
 * token ownership and balance information
 */
interface IERC721Holder is IERC165 {
  /**
   * @notice emitted when the token is transferred to the contract
   * @param owner functional token owner
   * @param tokenAddress held token address
   * @param tokenId held token ID
   */
  event Hold(
    address indexed owner,
    address indexed tokenAddress,
    uint256 indexed tokenId
  );

  /**
   * @notice emitted when the token is released back to the user
   * @param owner functional token owner
   * @param tokenAddress held token address
   * @param tokenId held token ID
   */
  event Release(
    address indexed owner,
    address indexed tokenAddress,
    uint256 indexed tokenId
  );

  /**
   * @notice get the functional owner of a held token
   * @dev should throw for invalid queries and return zero for a token ID that is not held
   * @param tokenAddress held token address
   * @param tokenId held token ID
   * @return functional token owner
   */
  function heldOwnerOf(address tokenAddress, uint256 tokenId)
    external
    view
    returns (address);

  /**
   * @notice get the held balance of the token owner
   * @dev should throw for invalid queries and return zero for no balance
   * @param tokenAddress held token address
   * @param owner functional token owner
   * @return held token balance
   */
  function heldBalanceOf(address tokenAddress, address owner)
    external
    view
    returns (uint256);
}
```

Smart contracts implementing the `ERC1155` held token standard MUST implement all of the functions in the `IERC1155Holder` interface.

Smart contracts implementing the `ERC1155` held token standard MUST also implement `ERC165` and return true when the interface ID `0xced24c37` is passed.

```solidity
/**
 * @notice the ERC1155 holder standard provides a common interface to query
 * token balance information
 */
interface IERC1155Holder is IERC165 {
  /**
   * @notice emitted when the token is transferred to the contract
   * @param owner functional token owner
   * @param tokenAddress held token address
   * @param tokenId held token ID
   * @param tokenAmount held token amount
   */
  event Hold(
    address indexed owner,
    address indexed tokenAddress,
    uint256 indexed tokenId,
    uint256 tokenAmount
  );

  /**
   * @notice emitted when the token is released back to the user
   * @param owner functional token owner
   * @param tokenAddress held token address
   * @param tokenId held token ID
   * @param tokenAmount held token amount
   */
  event Release(
    address indexed owner,
    address indexed tokenAddress,
    uint256 indexed tokenId,
    uint256 tokenAmount
  );

  /**
   * @notice get the held balance of the token owner
   * @dev should throw for invalid queries and return zero for no balance
   * @param tokenAddress held token address
   * @param owner functional token owner
   * @param tokenId held token ID
   * @return held token balance
   */
  function heldBalanceOf(
    address tokenAddress,
    address owner,
    uint256 tokenId
  ) external view returns (uint256);
}
```

## Rationale

This interface is designed to be extremely lightweight and compatible with any existing token contract. Any token holder contract likely already stores all relevant information, so this standard is purely adding a common interface to expose that data.

The token address parameter is included to support contracts that can hold multiple token contracts simultaneously. While some contracts may only hold a single token address, this is more general to either scenario.

Separate interfaces are proposed for each token type (EIP-20, EIP-721, EIP-1155) because any contract logic to support holding these different tokens is likely independent. In the scenario where a single contract does hold multiple token types, it can simply implement each appropriate held token interface.


## Backwards Compatibility

Importantly, the proposed specification is fully compatible with all existing EIP-20, EIP-721, and EIP-1155 token contracts.

Token holder contracts will need to be updated to implement this lightweight interface.

Consumer of this standard will need to be updated to respect this interface in any relevant ownership logic.


## Reference Implementation

A full example implementation including [interfaces](/EIPs/assets/eip-4987/IERC721Holder.sol), a vault [token holder](/EIPs/assets/eip-4987/Vault.sol), and a [consumer](/EIPs/assets/eip-4987/Consumer.sol), can be found at `assets/eip-4987/`.

Notably, consumers of the `IERC721Holder` interface can do a chained lookup for the owner of any specific token ID using the following logic.

```solidity
  /**
   * @notice get the functional owner of a token
   * @param tokenId token id of interest
   */
  function getOwner(uint256 tokenId) external view returns (address) {
    // get raw owner
    address owner = token.ownerOf(tokenId);

    // if owner is not contract, return
    if (!owner.isContract()) {
      return owner;
    }

    // check for token holder interface support
    try IERC165(owner).supportsInterface(0x16b900ff) returns (bool ret) {
      if (!ret) return owner;
    } catch {
      return owner;
    }

    // check for held owner
    try IERC721Holder(owner).heldOwnerOf(address(token), tokenId) returns (address user) {
      if (user != address(0)) return user;
    } catch {}

    return owner;
  }
```


## Security Considerations

Consumers of this standard should be cautious when using ownership information from unknown contracts. A bad actor could implement the interface, but report invalid or malicious information with the goal of manipulating a governance system, game, membership program, etc.

Consumers should also verify the overall token balance and ownership of the holder contract as a sanity check.


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 21 Sep 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-4987</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-4987</guid>
      </item>
    
      <item>
        <title>MULDIV instruction</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/muldiv-instruction/9930</comments>
        
        <description>## Abstract

Introduce a new instruction, `MULDIV(x, y, z)`, to perform `((x * y) / z) % 2**256` in 512-bit precision. `z = 0` is a special case for `(x * y) / 2**256`.

## Motivation

Fixed point operations in high level languages are very commonly used on Ethereum, especially in the domain of financial applications.

While fixed point addition and subtraction can be done with merely `add` and `sub` respectively, being able to efficiently do fixedpoint multiplication and division is a very sought after feature. A commonly used workaround relies on a `mulmod`-based, rather complex implementation (taking around 50 instructions, excluding stack manipulation). This instruction reduces that to a single opcode.

A secondary use case is likely in cryptographic applications, where the `muldiv` instruction allows full precision 256x256-&gt;512 multiplication. `mul(x y)` (or `muldiv(x, y, 1)`) computes the lower order 256 bits and `muldiv(x, y, 0)` computes the higher order 256 bits.

Finally we aimed to provide an instruction which can be efficiently used both in *checked* and *unchecked arithmetic* use cases. By *checked* we mean to abort on conditions including division-by-zero and wrapping behaviour.

## Specification

A new instruction is introduced: `MULDIV` (`0x1e`).

- Pops 3 values from the stack, first `x`, then `y` and `z`.
- If `z == 0`, `r = (uint512(x) * y) / 2**256`.
- Otherwise `r = (uint512(x) * y / z) % 2**256`, where the intermediate calculation is performed with 512-bit precision.
- Pushes `r` on the stack.

```python
# operations `*` and `//` are done in 512 bit precision
def muldiv(x, y, z):
    if z == 0:
        return (x * y) // (2**256)
    else:
        return ((x * y) // z) % (2**256)
```

The cost of the instruction is 8 gas (aka `mid`), the same as for `addmod` and `mulmod`.

## Rationale

### The special 0 case

All the arithmetic instructions in EVM handle division or modulo 0 specially: the instructions return 0. We have decided to break consistency in order to provide a flexible opcode, which can be used to detect wrapping behaviour.

Alternate options include:

- Returning a flag for wrapping
- Returning two stack items, higher and lower order bits
- Compute the higher order 256 bits in EVM:

```solidity
/// Returns `hi` such that `x × y = hi × 2**256 + mul(x, y)`
function hob(uint x, uint y) returns (uint hi) {
    uint uint_max = type(uint).max;
    assembly {
        let lo := mul(x, y)
        let mm := mulmod(x, y, uint_max)
        hi := sub(sub(mm, lo), lt(mm, lo))
    }
}
```

While this feature is clever and useful, callers must be aware that unlike other EVM instructions, passing 0 will have a vastly different behaviour.

### Argument ordering

The order of arguments matches `addmod` and `mulmod`.

## Backwards Compatibility

This is a new instruction not present prior.

## Test Cases

```
PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
MULDIV
---
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
```


```
PUSH 0x0000000000000000000000000000000000000000000000000000000000000000
PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
MULDIV
---
0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe
```

```
PUSH 0x0000000000000000000000000000000000000000000000000de0b6b3a7640000
PUSH 0x000000000000000000000000000000000000000000000000016345785d8a0000
PUSH 0x00000000000000000000000000000000000000000000d3c21bcecceda1000000
MULDIV
---
0x00000000000000000000000000000000000000000000152d02c7e14af6800000
```

## Security Considerations

TBA

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 14 Mar 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5000</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5000</guid>
      </item>
    
      <item>
        <title>Insert Code into EOAs with AUTHUSURP</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5003-auth-usurp-publishing-code-at-an-eoa-address/8979</comments>
        
        <description>## Abstract

This EIP introduces a new opcode, `AUTHUSURP`, which deploys code at an [EIP-3074](/EIPs/EIPS/eip-3074) authorized address. For externally owned accounts (EOAs), together with [EIP-3607](/EIPs/EIPS/eip-3607), this effectively revokes the original signing key&apos;s authority.

## Motivation

EOAs currently hold a significant amount of user-controlled value on Ethereum blockchains, but are limited by the protocol in a variety of critical ways. These accounts do not support rotating keys for security, batching to save gas, or sponsored transactions to reduce the need to hold ether yourself. There are countless other benefits that come from having a contract account or account abstraction, like choosing one&apos;s own authentication algorithm, setting spending limits, enabling social recovery, allowing key rotation, arbitrarily and transitively delegating capabilities, and just about anything else we can imagine.

New users have access to these benefits using smart contract wallets, and new contracts can adopt recent standards to enable app-layer account abstraction (like [EIP-4337](/EIPs/EIPS/eip-4337)), but these would neglect the vast majority of existing Ethereum users&apos; accounts. These users exist today, and they also need a path to achieving their security goals.

Those added benefits would mostly come along with EIP-3074 itself, but with one significant shortcoming: the original signing key has ultimate authority for the account. While an EOA could delegate its authority to some _additional_ contract, the key itself would linger, continuing to provide an attack vector, and a constantly horrifying question lingering: have I been leaked? In other words, EIP-3074 can only grant authority to additional actors, but never revoke it.

Today&apos;s EOAs have no option to rotate their keys. A leaked private key (either through phishing, or accidental access) cannot be revoked. A prudent user concerned about their key security might migrate to a new secret recovery phrase but at best this requires a transaction per asset (making it extremely expensive), and at worst, some powers (like hard-coded owners in a smart contract) might not be transferable at all.

We know that EOAs cannot provide ideal user experience or safety, and there is a desire in the community to change the norm to contract-based accounts, but if that transition is designed without regard for the vast majority of users today—for whom Ethereum has always meant EOAs—we will be continually struggling against the need to support both of these userbases. This EIP provides a path not to enshrine EOAs, but to provide a migration path off of them, once and for all.

This proposal combines well with, but is distinct from, [EIP-3074](/EIPs/EIPS/eip-3074), which provides opcodes that could enable any externally owned account (EOA) to delegate its signing authority to an arbitrary smart contract. It allows an EOA to authorize a contract account to act on its behalf _without forgoing its own powers_, while this EIP provides a final migration path off the EOA&apos;s original signing key.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### Conventions

  - **`top - N`** - the `N`th most recently pushed value on the EVM stack, where `top - 0` is the most recent.
  - **invalid execution** - execution that is invalid and must exit the current execution frame immediately, consuming all remaining gas (in the same way as a stack underflow or invalid jump).
  - **empty account** - account where its balance is 0, its nonce is 0, and it has no code.

### `AUTHUSURP` (`0xf8`)

A new opcode `AUTHUSURP` shall be created at `0xf8`. It shall take two stack elements and return one stack element.

#### Input

| Stack     | Value        |
| --------- | ------------ |
| `top - 0` | `offset`     |
| `top - 1` | `length`     |

#### Output

| Stack      | Value     |
| ---------- | --------- |
| `top - 0`  | `address` |

#### Behavior

`AUTHUSURP` behaves identically to `CREATE` (`0xf0`), except as described below:

  - If `authorized` (as defined in EIP-3074) is unset, execution is invalid.
  - If `authorized` points to an empty account, then `static_gas` remains 32,000. Otherwise, `static_gas` shall be 7,000.
  - `AUTHUSURP` does not check the nonce of the `authorized` account.
  - The initcode runs at the address `authorized`.
  - If the initcode returns no bytes, its execution frame must be reverted, and `AUTHUSURP` returns zero.
  - After executing the initcode, but before the returned code is deployed, if the account&apos;s code is non-empty, the initcode&apos;s execution frame must be reverted, and `AUTHUSURP` returns zero.
  - The code is deployed into the account with the address `authorized`.

## Rationale

`AUTHUSURP` does not check the nonce of the `authorized` account because it must work with accounts that have previously sent transactions.

When using `AUTHUSURP`, if the initcode were to deploy a zero-length contract, there would be no way to prevent using `AUTHUSURP` again later.

The account&apos;s code must be checked immediately before deploying to catch the situation where the initcode attempts to `AUTHUSURP` at the same address. This is unnecessary with other deployment instructions because they increment and check the account&apos;s nonce.

## Backwards Compatibility

`AUTHUSURP` with EIP-3607 revokes the authority of the original ECDSA signature to send transactions from the account. This is completely new behavior, although it is somewhat similar to the `CREATE2` opcode.

## Security Considerations

Contracts using ECDSA signatures outside of transactions will not be aware that the usurped account is no longer controlled by a private key. This means that, for example, the private key will _always_ have access to the `permit` function on token contracts. This can—and should—be mitigated by modifying the `ecrecover` pre-compiled contract.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 26 Mar 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5003</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5003</guid>
      </item>
    
      <item>
        <title>Zodiac Modular Accounts</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-zodiac-a-composable-design-philosophy-for-daos/8963</comments>
        
        <description>## Abstract
This EIP standardizes interfaces for composable and interoperable tooling for programmable Ethereum accounts. These interfaces separate contract accounts (&quot;avatars&quot;) from their authentication and execution logic (&quot;guards&quot; and &quot;modules&quot;). Avatars implement the `IAvatar` interface, and guards implement the `IGuard` interface. Modules may take any form.

## Motivation
Currently, most programmable accounts (like DAO tools and frameworks) are built as monolithic systems where the authorization and execution logic are coupled, either within the same contract or in a tightly integrated system of contracts. This needlessly inhibits the flexibility of these tools and encourages platform lock-in via high switching costs.

By using the this EIP standard to separate concerns (decoupling authentication and execution logic), users are able to:

1. Enable flexible, module-based control of programmable accounts
2. Easily switch between tools and frameworks without unnecessary overhead.
3. Enable multiple control mechanism in parallel.
4. Enable cross-chain / cross-layer governance.
5. Progressively decentralize their governance as their project and community matures.

## Specification
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.

This EIP consists of four key concepts:

- **Avatars** are programmable Ethereum accounts. Avatars are the address that holds balances, owns systems, executes transaction, is referenced externally, and ultimately represents your DAO. Avatars MUST implement the `IAvatar` interface.
- **Modules** are contracts enabled by an avatar that implement some execution logic.
- **Modifiers** are contracts that sit between modules and avatars to modify the module&apos;s behavior. For example, they might enforce a delay on all functions a module attempts to execute or limit the scope of transactions that can be initiated by the module. Modifiers MUST implement the `IAvatar` interface.
- **Guards** are contracts that MAY be enabled on modules or modifiers and implement pre- or post-checks on each transaction executed by those modules or modifiers. This allows avatars to do things like limit the scope of addresses and functions that a module or modifier can call or ensure a certain state is never changed by a module or modifier. Guards MUST expose the `IGuard` interface. Modules, modifiers, and avatars that wish to be guardable MUST inherit `Guardable`, MUST call `checkTransaction()` before triggering execution on their target, and MUST call `checkAfterExecution()` after execution is complete.

```solidity
/// @title Avatar - A contract that manages modules that can execute transactions via this contract.

pragma solidity &gt;=0.7.0 &lt;0.9.0;

import &quot;./Enum.sol&quot;;


interface IAvatar {
    event EnabledModule(address module);
    event DisabledModule(address module);
    event ExecutionFromModuleSuccess(address indexed module);
    event ExecutionFromModuleFailure(address indexed module);

    /// @dev Enables a module on the avatar.
    /// @notice Can only be called by the avatar.
    /// @notice Modules should be stored as a linked list.
    /// @notice Must emit EnabledModule(address module) if successful.
    /// @param module Module to be enabled.
    function enableModule(address module) external;

    /// @dev Disables a module on the avatar.
    /// @notice Can only be called by the avatar.
    /// @notice Must emit DisabledModule(address module) if successful.
    /// @param prevModule Address that pointed to the module to be removed in the linked list
    /// @param module Module to be removed.
    function disableModule(address prevModule, address module) external;

    /// @dev Allows a Module to execute a transaction.
    /// @notice Can only be called by an enabled module.
    /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.
    /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.
    /// @param to Destination address of module transaction.
    /// @param value Ether value of module transaction.
    /// @param data Data payload of module transaction.
    /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.
    function execTransactionFromModule(
        address to,
        uint256 value,
        bytes memory data,
        Enum.Operation operation
    ) external returns (bool success);

    /// @dev Allows a Module to execute a transaction and return data
    /// @notice Can only be called by an enabled module.
    /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.
    /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.
    /// @param to Destination address of module transaction.
    /// @param value Ether value of module transaction.
    /// @param data Data payload of module transaction.
    /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.
    function execTransactionFromModuleReturnData(
        address to,
        uint256 value,
        bytes memory data,
        Enum.Operation operation
    ) external returns (bool success, bytes memory returnData);

    /// @dev Returns if an module is enabled
    /// @return True if the module is enabled
    function isModuleEnabled(address module) external view returns (bool);

    /// @dev Returns array of modules.
    /// @param start Start of the page.
    /// @param pageSize Maximum number of modules that should be returned.
    /// @return array Array of modules.
    /// @return next Start of the next page.
    function getModulesPaginated(address start, uint256 pageSize)
        external
        view
        returns (address[] memory array, address next);
}
```

```solidity
pragma solidity &gt;=0.7.0 &lt;0.9.0;

import &quot;./Enum.sol&quot;;

interface IGuard {
    function checkTransaction(
        address to,
        uint256 value,
        bytes memory data,
        Enum.Operation operation,
        uint256 safeTxGas,
        uint256 baseGas,
        uint256 gasPrice,
        address gasToken,
        address payable refundReceiver,
        bytes memory signatures,
        address msgSender
    ) external;

    function checkAfterExecution(bytes32 txHash, bool success) external;
}

```

```solidity
pragma solidity &gt;=0.7.0 &lt;0.9.0;

import &quot;./Enum.sol&quot;;
import &quot;./BaseGuard.sol&quot;;

/// @title Guardable - A contract that manages fallback calls made to this contract
contract Guardable {
    address public guard;

    event ChangedGuard(address guard);

    /// `guard_` does not implement IERC165.
    error NotIERC165Compliant(address guard_);

    /// @dev Set a guard that checks transactions before execution.
    /// @param _guard The address of the guard to be used or the 0 address to disable the guard.
    function setGuard(address _guard) external {
        if (_guard != address(0)) {
            if (!BaseGuard(_guard).supportsInterface(type(IGuard).interfaceId))
                revert NotIERC165Compliant(_guard);
        }
        guard = _guard;
        emit ChangedGuard(guard);
    }

    function getGuard() external view returns (address _guard) {
        return guard;
    }
}
```

```solidity
pragma solidity &gt;=0.7.0 &lt;0.9.0;

import &quot;./Enum.sol&quot;;
import &quot;./IERC165.sol&quot;;
import &quot;./IGuard.sol&quot;;

abstract contract BaseGuard is IERC165 {
    function supportsInterface(bytes4 interfaceId)
        external
        pure
        override
        returns (bool)
    {
        return
            interfaceId == type(IGuard).interfaceId || // 0xe6d7a83a
            interfaceId == type(IERC165).interfaceId; // 0x01ffc9a7
    }

    /// @dev Module transactions only use the first four parameters: to, value, data, and operation.
    /// Module.sol hardcodes the remaining parameters as 0 since they are not used for module transactions.
    function checkTransaction(
        address to,
        uint256 value,
        bytes memory data,
        Enum.Operation operation,
        uint256 safeTxGas,
        uint256 baseGas,
        uint256 gasPrice,
        address gasToken,
        address payable refundReceiver,
        bytes memory signatures,
        address msgSender
    ) external virtual;

    function checkAfterExecution(bytes32 txHash, bool success) external virtual;
}
```

```solidity
pragma solidity &gt;=0.7.0 &lt;0.9.0;

/// @title Enum - Collection of enums

contract Enum {

    enum Operation {Call, DelegateCall}

}
```

## Rationale
The interface defined in this standard is designed to be mostly compatible with most popular programmable accounts in use right now, to minimize the need for changes to existing tooling.

## Backwards Compatibility
No backward compatibility issues are introduced by this standard.

## Security Considerations
There are some considerations that module developers and users should take into account:
1. **Modules have absolute control:** Modules have absolute control over any avatar on which they are enabled, so any module implementation should be treated as security critical and users should be vary cautious about enabling new modules. ONLY ENABLE MODULES THAT YOU TRUST WITH THE FULL VALUE OF THE AVATAR.
2. **Race conditions:** A given avatar may have any number of modules enabled, each with unilateral control over the safe. In such cases, there may be race conditions between different modules and/or other control mechanisms.
3. **Don&apos;t brick your avatar:** There are no safeguards to stop you adding or removing modules. If you remove all of the modules that let you control an avatar, the avatar will cease to function and all funds will be stuck.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 14 Apr 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5005</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5005</guid>
      </item>
    
      <item>
        <title>Rental NFT, NFT User Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip5006-erc-1155-usage-rights-extension/8941</comments>
        
        <description>## Abstract

This standard is an extension of [ERC-1155](/EIPs/EIPS/eip-1155). It proposes an additional role (`user`) which can be granted to addresses that represent a `user` of the assets rather than an `owner`.

## Motivation

Like [ERC-721](/EIPs/EIPS/eip-721), [ERC-1155](/EIPs/EIPS/eip-1155) tokens may have utility of some kind. The people who “use” the token may be different than the people who own it (such as in a rental). Thus, it would be useful to have separate roles for the “owner” and the “user” so that the “user” would not be able to take actions that the owner could (for example, transferring ownership).

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot; and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

```solidity
// SPDX-License-Identifier: CC0-1.0

pragma solidity ^0.8.0;

interface IERC5006 {
    struct UserRecord {
        uint256 tokenId;
        address owner;
        uint64 amount;
        address user;
        uint64 expiry;
    }
    
    /**
     * @dev Emitted when permission for `user` to use `amount` of `tokenId` token owned by `owner`
     * until `expiry` are given.
     */
    event CreateUserRecord(
        uint256 recordId,
        uint256 tokenId,
        uint64  amount,
        address owner,
        address user,
        uint64  expiry
    );

    /**
     * @dev Emitted when record of `recordId` are deleted. 
     */
    event DeleteUserRecord(uint256 recordId);

    /**
     * @dev Returns the usable amount of `tokenId` tokens  by `account`.
     */
    function usableBalanceOf(address account, uint256 tokenId)
        external
        view
        returns (uint256);

    /**
     * @dev Returns the amount of frozen tokens of token type `id` by `account`.
     */
    function frozenBalanceOf(address account, uint256 tokenId)
        external
        view
        returns (uint256);

    /**
     * @dev Returns the `UserRecord` of `recordId`.
     */
    function userRecordOf(uint256 recordId)
        external
        view
        returns (UserRecord memory);

    /**
     * @dev Gives permission to `user` to use `amount` of `tokenId` token owned by `owner` until `expiry`.
     *
     * Emits a {CreateUserRecord} event.
     *
     * Requirements:
     *
     * - If the caller is not `owner`, it must be have been approved to spend ``owner``&apos;s tokens
     * via {setApprovalForAll}.
     * - `owner` must have a balance of tokens of type `id` of at least `amount`.
     * - `user` cannot be the zero address.
     * - `amount` must be greater than 0.
     * - `expiry` must after the block timestamp.
     */
    function createUserRecord(
        address owner,
        address user,
        uint256 tokenId,
        uint64 amount,
        uint64 expiry
    ) external returns (uint256);

    /**
     * @dev Atomically delete `record` of `recordId` by the caller.
     *
     * Emits a {DeleteUserRecord} event.
     *
     * Requirements:
     *
     * - the caller must have allowance.
     */
    function deleteUserRecord(uint256 recordId) external;
}

```

The `supportsInterface` method MUST return `true` when called with `0xc26d96cc`.

## Rationale

This model is intended to facilitate easy implementation. The following are some problems that are solved by this standard:

### Clear Rights Assignment

With Dual “owner” and “user” roles, it becomes significantly easier to manage what lenders and borrowers can and cannot do with the NFT (in other words, their rights).  For example, for the right to transfer ownership, the project simply needs to check whether the address taking the action represents the owner or the user and prevent the transaction if it is the user.  Additionally, owners can control who the user is and it is easy for other projects to assign their own rights to either the owners or the users.

### Easy Third-Party Integration

In the spirit of permissionless interoperability, this standard makes it easier for third-party protocols to manage NFT usage rights without permission from the NFT issuer or the NFT application. Once a project has adopted the additional `user` role, any other project can directly interact with these features and implement their own type of transaction. For example, a PFP NFT using this standard can be integrated into both a rental platform where users can rent the NFT for 30 days AND, at the same time, a mortgage platform where users can use the NFT while eventually buying ownership of the NFT with installment payments. This would all be done without needing the permission of the original PFP project.

## Backwards Compatibility

As mentioned in the specifications section, this standard can be fully ERC compatible by adding an extension function set, and there are no conflicts between [ERC-5006](/EIPs/EIPS/eip-5006) and ERC-1155.

In addition, new functions introduced in this standard have many similarities with the existing functions in ERC-1155. This allows developers to easily adopt the standard quickly.

## Test Cases

Test cases are included in [test.js](/EIPs/assets/eip-5006/test/test.ts). 

Run in terminal: 

1. ```cd ../assets/eip-5006```
1. ```npm install```
1. ```npx hardhat test```

## Reference Implementation

See [`ERC5006.sol`](/EIPs/assets/eip-5006/contracts/ERC5006.sol).

## Security Considerations

This EIP standard can completely protect the rights of the owner, the owner can change the NFT user, the user can not transfer the NFT.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 12 Apr 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5006</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5006</guid>
      </item>
    
      <item>
        <title>Time NFT, ERC-721 Time Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5007-eip-721-time-extension/8924</comments>
        
        <description>## Abstract

This standard is an extension of [ERC-721](/EIPs/EIPS/eip-721). It proposes some additional functions (`startTime`, `endTime`) to help with on-chain time management.

## Motivation

Some NFTs have a defined usage period and cannot be used outside of that period. With traditional NFTs that do not include time information, if you want to mark a token as invalid or enable it at a specific time, you need to actively submit a transaction—a process both cumbersome and expensive.

Some existing NFTs contain time functions, but their interfaces are not consistent, so it is difficult to develop third-party platforms for them.

By introducing these functions (`startTime`, `endTime`), it is possible to enable and disable NFTs automatically on chain.

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot; and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

```solidity
/**
 * @dev the ERC-165 identifier for this interface is 0xf140be0d.
 */
interface IERC5007 /* is IERC721 */ {
    /**
     * @dev Returns the start time of the NFT as a UNIX timestamp.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function startTime(uint256 tokenId) external view returns (uint64);
    
    /**
     * @dev Returns the end time of the NFT as a UNIX timestamp.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function endTime(uint256 tokenId) external view returns (uint64);

}
```

The **composable extension** is OPTIONAL for this standard. This allows your NFT to be minted from an existing NFT or to merge two NFTs into one NFT.

```solidity
/**
 * @dev the ERC-165 identifier for this interface is 0x75cf3842.
 */
interface IERC5007Composable /* is IERC5007 */ {
    /**
     * @dev Returns the asset id of the time NFT.
     * Only NFTs with same asset id can be merged.
     * 
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function assetId(uint256 tokenId) external view returns (uint256);

    /**
     * @dev Split an old token to two new tokens.
     * The assetId of the new token is the same as the assetId of the old token
     *
     * Requirements:
     *
     * - `oldTokenId` must exist.
     * - `newToken1Id` must not exist.
     * - `newToken1Owner` cannot be the zero address.
     * - `newToken2Id` must not exist.
     * - `newToken2Owner` cannot be the zero address.
     * - `splitTime`  require(oldToken.startTime &lt;= splitTime &amp;&amp; splitTime &lt; oldToken.EndTime)
     */
    function split(
        uint256 oldTokenId,
        uint256 newToken1Id,
        address newToken1Owner,
        uint256 newToken2Id,
        address newToken2Owner,
        uint64 splitTime
    ) external;

    /**
     * @dev Merge the first token and second token into the new token.
     *
     * Requirements:
     *
     * - `firstTokenId` must exist.
     * - `secondTokenId` must exist.
     * - require((firstToken.endTime + 1) == secondToken.startTime)
     * - require((firstToken.assetId()) == secondToken.assetId())
     * - `newTokenOwner` cannot be the zero address.
     * - `newTokenId` must not exist.
     */
    function merge(
        uint256 firstTokenId,
        uint256 secondTokenId,
        address newTokenOwner,
        uint256 newTokenId
    ) external;
}
```

## Rationale

### Time Data Type

The max value of `uint64` is 18,446,744,073,709,551,615. As a timestamp, 18,446,744,073,709,551,615 is about year 584,942,419,325. `uint256` is too big for C, C++, Java, Go, etc, and `uint64` is natively supported by mainstream programming languages.

## Backwards Compatibility

This standard is fully ERC-721 compatible.

## Test Cases

Test cases are included in [test.js](/EIPs/assets/eip-5007/test/test.js). 

Run in terminal:

```shell
cd ../assets/eip-5007
npm install truffle -g
npm install
truffle test
```
 
## Reference Implementation

See [`ERC5007.sol`](/EIPs/assets/eip-5007/contracts/ERC5007.sol).

## Security Considerations

No security issues found.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 13 Apr 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5007</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5007</guid>
      </item>
    
      <item>
        <title>ERC-721 Nonce Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip5008-eip-721-nonce-and-metadata-update-extension/8925</comments>
        
        <description>## Abstract

This standard is an extension of [ERC-721](/EIPs/EIPS/eip-721). It proposes adding a `nonce` function to ERC-721 tokens.

## Motivation

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.

This EIP proposes adding a `nonce` property to ERC-721 tokens, and the `nonce` will be changed when a token is transferred. If a `nonce` is added to an order, the order can be checked to avoid attacks.

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot; and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

```solidity

/// @dev the ERC-165 identifier for this interface is 0xce03fdab.
interface IERC5008 /* is IERC165 */ {
    /// @notice Emitted when the `nonce` of an NFT is changed
    event NonceChanged(uint256 tokenId, uint256 nonce);

    /// @notice Get the nonce of an NFT
    /// Throws if `tokenId` is not a valid NFT
    /// @param tokenId The id of the NFT
    /// @return The nonce of the NFT
    function nonce(uint256 tokenId) external view returns(uint256);
}
```

The `nonce(uint256 tokenId)` function MUST be implemented as `view`.

The `supportsInterface` method MUST return `true` when called with `0xce03fdab`.

## Rationale

At first `transferCount` was considered as function name, but there may some case to change the `nonce` besides transfer, such as important properties changed, then we changed `transferCount` to `nonce`.

## Backwards Compatibility

This standard is compatible with ERC-721.

## Test Cases

Test cases are included in [test.js](/EIPs/assets/eip-5008/test/test.ts).

Run:

```sh
cd ../assets/eip-5008
npm install
npm run test
```

## Reference Implementation

See [`ERC5008.sol`](/EIPs/assets/eip-5008/contracts/ERC5008.sol).

## Security Considerations

No security issues found.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Filesystem-like Interface for Contracts</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5018-directory-standard/8958</comments>
        
        <description>## Abstract

The following standardizes an API for directories and files within smart contracts, similar to traditional filesystems.
This standard provides basic functionality to read/write binary objects of any size, as well as allow reading/writing chunks of the object if the object is too large to fit in a single transaction.

## Motivation

A standard interface allows any binary objects on EVM-based blockchain to be re-used by other dApps.

With [EIP-4804](/EIPs/EIPS/eip-4804), we are able to locate a Web3 resource on blockchain using HTTP-style URIs. One application of Web3 resources are web contents that are referenced within a directory using relative paths such as HTML/SVG. This standard proposes a contract-based directory to simplify the mapping between local web contents and on-chain web contents. Further, with relative paths referenced in the web contents and EIP-4804, the users will have a consistent view of the web contents locally and on-chain.

## Specification

### Directory

#### Methods

##### write

Writes binary `data` to the file `name` in the directory by an account with write permission.

```
function write(bytes memory name, bytes memory data) external payable
```

##### read

Returns the binary `data` from the file `name` in the directory and existence of the file.

```
function read(bytes memory name) external view returns (bytes memory data, bool exist)
```

##### fallback read

Returns the binary `data` from the file `prefixedName` (prefixed with `/`) in the directory.

```
fallback(bytes calldata prefixedName) external returns (bytes memory data) 
```

##### size

Returns the size of the `data` from the file `name` in the directory and the number of chunks of the data.

```
function size(bytes memory name) external view returns (uint256 size, uint256 chunks)
```

##### remove

Removes the file `name` in the directory and returns the number of chunks removed (0 means the file does not exist) by an account with write permission.

```
function remove(bytes memory name) external returns (uint256 numOfChunksRemoved)
```

##### countChunks

Returns the number of chunks of the file `name`.

```
function countChunks(bytes memory name) external view returns (uint256 numOfChunks);
```

##### writeChunk

Writes a chunk of data to the file by an account with write permission. The write will fail if `chunkId &gt; numOfChunks`, i.e., the write must append the file or replace the existing chunk.

```
 function writeChunk(bytes memory name, uint256 chunkId, bytes memory chunkData) external payable;
```

##### readChunk

Returns the chunk data of the file `name` and the existence of the chunk.

```
function readChunk(bytes memory name, uint256 chunkId) external view returns (bytes memory chunkData, bool exist);
```

##### chunkSize

Returns the size of a chunk of the file `name` and the existence of the chunk.

```
function chunkSize(bytes memory name, uint256 chunkId) external view returns (uint256 chunkSize, bool exist);
```

##### removeChunk

Removes a chunk of the file `name` and returns `false` if such chunk does not exist. The method should be called by an account with write permission.

```
function removeChunk(bytes memory name, uint256 chunkId) external returns (bool exist);
```

##### truncate

Removes the chunks of the file `name` in the directory from the given `chunkId` and returns the number of chunks removed by an account with write permission. When `chunkId = 0`, the method is essentially the same as `remove()`.

```
function truncate(bytes memory name, uint256 chunkId) external returns (uint256 numOfChunksRemoved);
```

##### getChunkHash

Returns the hash value of the chunk data.

```
function getChunkHash(bytes memory name, uint256 chunkId) external view returns (bytes32);
```

## Rationale

One issue of uploading the web contents to the blockchain is that the web contents may be too large to fit into a single transaction. As a result, the standard provides chunk-based operations so that uploading a content can be split into several transactions. Meanwhile, the read operation can be done in a single transaction, i.e., with a single Web3 URL defined in EIP-4804.

### Interactions Between Unchunked/Chunked Functions

`read` method should return the concatenated chunked data written by `writeChunk` method. The following gives some examples of the interactions:

- `read(&quot;hello.txt&quot;)` =&gt; &quot;&quot; (file is empty)
- `writeChunk(&quot;hello.txt&quot;, 0, &quot;abc&quot;)` will succeed
- `read(&quot;hello.txt&quot;)` =&gt; &quot;abc&quot;
- `writeChunk(&quot;hello.txt&quot;, 1, &quot;efg&quot;)` will succeed
- `read(&quot;hello.txt&quot;)` =&gt; &quot;abcefg&quot;
- `writeChunk(&quot;hello.txt&quot;, 0, &quot;aaa&quot;)` will succeed (replace chunk 0&apos;s data)
- `read(&quot;hello.txt&quot;)` =&gt; &quot;aaaefg&quot;
- `writeChunk(&quot;hello.txt&quot;, 3, &quot;hij&quot;)` will fail because the operation is not replacement or append.

With `writeChunk` method, we allow writing a file with external data that exceeds the current calldata limit (e.g., 1.8MB now), and it is able to read the whole file in a single `read` method (which is friendly for large web objects such as HTML/SVG/PNG/JPG, etc).

For `write` method, calling a `write` method will replace all data chunks of the file with `write` method data, and one implementation can be:

1. `writeChunk(filename, chunkId=0, data_from_write)` to chunk 0 with the same `write` method data; and
2. `truncate(filename, chunkId=1)`, which will remove the rest chunks.

## Backwards Compatibility

No backwards compatibility issues were identified.

## Security Considerations

No security considerations were found.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 18 Apr 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5018</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5018</guid>
      </item>
    
      <item>
        <title>Increase price of SSTORE from zero to non-zero to 40k gas</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-proposal-increase-cost-of-sstore-from-20k-to-x-when-creating-new-storage/7614</comments>
        
        <description>### Abstract

Increase the price of the SSTORE opcode from `20_000` gas to `40_000` gas when the original slot is zero and the resultant slot is non-zero.

### Motivation

The cost of creating a piece of new state increases as state is larger. However, the price for creating every new storage slot has not increased.
All resources are merged into the same pricing mechanism. If the price for creating new storage slots is fixed, then it needs to be manually changed.

One of the main reasons for not increasing gas limit is the increase of state. In that regard, because the cost of creating storage is higher than its price, all the users of all the other opcodes are subsidizing the creation of state. If state creation was more precisely priced, raising gas limit would be more feasible, and would benefit the users.

## Rationale

### Why not also raise the cost of non-zero to non-zero?

Rewriting storage does not affect state growth, which is the main issue this EIP is addressing. Rewriting storage may also be underpriced.
Increasing the price of state growth will, at least, incentivize developers to reuse storage instead.

### Why not also increase the gas refund from setting non-zero to zero?

More discussion is needed on this.

### Why not a better state solution?

Whereas solutions like state rent, or state expiry have been researched for a long time, they will not be ready on the short to medium term. So, it is desirable to patch pricing for the short term. Opcode repricing has been done before, so it should not impose a large development time investment for clients.

### Why was that specific amount chosen?

The current pricing was made off a naive approach of benchmarking opcodes in a laptop. Not only it did not consider the long term problem of having the same price for a resource that costs more over time, the benchmark itself was wrong. This price is closer to what the naive original benchmark should have been. It could go higher, but that may be too disruptive.

### Is this too disruptive?

This change will severely impact the gas cost of many applications. The network does not have to subsidize state growth at the expense of more expensive regular transactions, so even if it is too disruptive, it will increase the health of the network.

### Specification

| Constant | Value |
| - | - |
| `FORK_BLOCK` | TBD |
| `NEW_STORAGE_PRICE` | `40_000`

For blocks where `block.number &gt;= FORK_BLOCK`, a new gas schedule applies. Make `SSTORE_SET_GAS`, the price when a slot is set from zero to non-zero, equal `NEW_STORAGE_PRICE`. All other costs remain the same.

### Backwards compatibility

Contracts that depend on hardcoded gas costs will break if they create state.

It is a gas schedule change, so transactions from an epoch before FORK_BLOCK should be treated with previous gas costs.

## Implementation

https://github.com/ethereum/go-ethereum/pull/24725

## Security considerations

TODO
</description>
        <pubDate>Wed, 20 Apr 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5022</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5022</guid>
      </item>
    
      <item>
        <title>Shareable Non-Fungible Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/new-nft-concept-shareable-nfts/8681</comments>
        
        <description>## Abstract

This EIP standardizes an interface for non-fungible value-holding shareable tokens. Shareability is accomplished by minting copies of existing tokens for new recipients. Sharing and associated events allow the construction of a graph describing who has shared what to which party.


## Motivation

NFT standards such as [EIP-721](/EIPs/EIPS/eip-721) and [EIP-1155](/EIPs/EIPS/eip-1155) have been developed to standardize scarce digital resources. However, many non-fungible digital resources need not be scarce.

We have attempted to capture positive externalities in ecosystems with new types of incentive mechanisms that exhibit anti-rival logic, serve as an unit of accounting and function as medium of sharing. We envision that shareable tokens can work both as incentives but also as representations of items that are typically digital in their nature and gain more value as they are shared.

These requirements have set us to define shareable NFTs and more specifically a variation of shareable NFTs called non-transferable shareable NFTs. These shareable NFTs can be “shared” in the same way digital goods can be shared, at an almost zero technical transaction cost. We have utilized them to capture anti-rival value in terms of accounting positive externalities in an economic system.

Typical NFT standards such as EIP-721 and EIP-1155 do not define a sharing modality. Instead ERC standards define interfaces for typical rival use cases such as token minting and token transactions that the NFT contract implementations should fulfil. The ‘standard contract implementations&apos; may extend the functionalities of these standards beyond the definition of interfaces. The shareable tokens that we have designed and developed in our experiments are designed to be token standard compatible at the interface level. However the implementation of token contracts may contain extended functionalities to match the requirements of the experiments such as the requirement of &apos;shareability&apos;. In reflection to standard token definitions, shareability of a token could be thought of as re-mintability of an existing token to another party while retaining the original version of it.

Sharing is an interesting concept as it can be thought and perceived in different ways. For example, when we talk about sharing we can think about it is as digital copying, giving a copy of a digital resource while retaining a version by ourselves. Sharing can also be fractional or sharing could be about giving rights to use a certain resource. The concept of shareability and the context of shareability can take different forms and one might use different types of implementatins for instances of shareable tokens. Hence we haven&apos;t restricted that the interface should require any specific token type.

Shareable tokens can be made non-transferable at the contract implementation level. Doing so, makes them shareable non-transferable tokens. In the reference implementation we have distilled a general case from our use cases that defines a shareable non-transferable NFTs using the shareable NFT interface.

We believe that the wider audience should benefit from an abstraction level higher definition for shareability, such as this interface implementation, that defines minimum amount of functions that would be implemented to satisfy the concept of shareability.

## Specification

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.

```solidity
///  Note: the ERC-165 identifier for this interface is 0xded6338b
interface IERC5023 is IERC165 {

  /// @dev This emits when a token is shared, reminted and given to another wallet that isn&apos;t function caller
  event Share(address indexed from, address indexed to, uint256 indexed tokenId, uint256 derivedFromtokenId);

  /// @dev Shares, remints an existing token, gives a newly minted token a fresh token id, keeps original token at function callers possession and transfers newly minted token to receiver which should be another address than function caller. 
  function share(address to, uint256 tokenIdToBeShared) external returns(uint256 newTokenId);

} 
```

The Share event is expected to be emitted when function method share is successfully called and a new token on basis of a given token id is minted and transferred to a recipient.

## Rationale

Current NFT standards define transferable non-fungible tokens, but not shareable non-fungible tokens. To be able to create shareable NFTs we see that existing NFT contracts could be extended with an interface which defines the basic principles of sharing, namely the Event of sharing and the function method of sharing. Definition of how transferability of tokens should be handled is left to the contract implementor. In case transferring is left enable shareable tokens behave similarly to the existing tokens, except when they are shared, a version of token is retained. In case transfering is disabled, shareable tokens become shareable non-transferable tokens, where they can be minted and given or shared to other people, but they cannot be transferred away.

Imagine that Bob works together with Alice on a project. Bob earns an unique NFT indicating that he has made effort to the project, but Bob feels that his accomplishments are not only out of his own accord. Bob wants to share his token with Alice to indicate that also Alice deserves recognition of having put effort on their project. Bob initiates token sharing by calling `Share` method on the contract which has his token and indicates which one of his tokens he wishes to share and to whom by passing address and token id parameters. A new token is minted for Alice and a `Share` event is initiated to communicate that it was Bob whom shared his token to Alice by logging addresses who shared a token id to whose address and which token id was this new token derived from.

Over time, a tree-like structures can be formed from the Share event information. If Bob shared to Alice, and Alice shared further to Charlie and Alice also shared to David a rudimentary tree structure forms out from sharing activity. This share event data can be later on utilized to gain more information of share activities that the tokens represent.

```text
B -&gt; A -&gt; C 
      \
       &gt;  D
```

These tree structures can be further aggregated and collapsed to network representations e.g. social graphs on basis of whom has shared to whom over a span of time. E.g. if Bob shared a token to Alice, and Alice has shared a different token to Charlie and Bob has shared a token to Charlie, connections form between all these parties through sharing activities.

```text
 B----A----C         
  \_______/
```

## Backwards Compatibility

This proposal is backwards compatible with EIP-721 and EIP-1155.

## Reference Implementation

Following reference implementation demonstrates a general use case of one of our pilots. In this case a shareable non-transferable token represents a contribution done to a community that the contract owner has decided to merit with a token. Contract owner can mint a merit token and give it to a person. This token can be further shared by the receiver to other parties for example to share the received merit to others that have participated or influenced his contribution.

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

import &quot;./IERC5023.sol&quot;;
import &quot;@openzeppelin/contracts/token/ERC721/IERC721.sol&quot;;
import &quot;@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol&quot;;
import &quot;@openzeppelin/contracts/utils/Address.sol&quot;;
import &quot;@openzeppelin/contracts/utils/Context.sol&quot;;
import &quot;@openzeppelin/contracts/utils/Strings.sol&quot;;
import &quot;@openzeppelin/contracts/utils/introspection/ERC165.sol&quot;;
import &quot;@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol&quot;;
import &quot;@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol&quot;;
import &quot;@openzeppelin/contracts/access/Ownable.sol&quot;;

contract ShareableERC721 is ERC721URIStorage, Ownable, IERC5023 /* EIP165 */ {

  string baseURI;

  uint256 internal _currentIndex;
    
  constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {}

  function mint(
        address account,
        uint256 tokenId
    ) external onlyOwner {
        _mint(account, tokenId);
  }

  function setTokenURI(
        uint256 tokenId, 
        string memory tokenURI
    ) external {
        _setTokenURI(tokenId, tokenURI);
  }

  function setBaseURI(string memory baseURI_) external {
        baseURI = baseURI_;
  }
    
  function _baseURI() internal view override returns (string memory) {
        return baseURI;
  }

  function share(address to, uint256 tokenIdToBeShared) external returns(uint256 newTokenId) {
      require(to != address(0), &quot;ERC721: mint to the zero address&quot;);
      require(_exists(tokenIdToBeShared), &quot;ShareableERC721: token to be shared must exist&quot;);
      
      require(msg.sender == ownerOf(tokenIdToBeShared), &quot;Method caller must be the owner of token&quot;);

      string memory _tokenURI = tokenURI(tokenIdToBeShared);
      _mint(to, _currentIndex);
      _setTokenURI(_currentIndex, _tokenURI);

      emit Share(msg.sender, to, _currentIndex, tokenIdToBeShared);

      return _currentIndex;
  }

  function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        revert(&apos;In this reference implementation tokens are not transferrable&apos;);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        revert(&apos;In this reference implementation tokens are not transferrable&apos;);
    }
}

```

## Security Considerations

Reference implementation should not be used as is in production.
There are no other security considerations related directly to implementation of this standard.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 28 Jan 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5023</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5023</guid>
      </item>
    
      <item>
        <title>Remove the limit on contract code size</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5027-unlimit-contract-code-size/9010</comments>
        
        <description>## Abstract

Remove the limit on the contract code size, i.e., only limit the contract code size by block gas limit, with minimal changes to existing code and proper gas metering adjustment to avoid possible attacks.


## Motivation

The motivation is to remove the limit on the code size so that users can deploy a large-code contract without worrying about splitting the contract into several sub-contracts.

With the dramatic growth of dApplications, the functionalities of smart contracts are becoming more and more complicated, and thus, the sizes of newly developed contracts are steadily increasing.  As a result, we are facing more and more issues with the 24576-bytes contract size limit.  Although several techniques such as splitting a large contract into several sub-contracts can alleviate the issue, these techniques inevitably increase the burden of developing/deploying/maintaining smart contracts.

The proposal implements a solution to remove the existing 24576-bytes limit of the code size.  Further, the proposal aims to minimize the changes in the client implementation (e.g., Geth) with
- proper gas metering to avoid abusing the node resources for contract-related opcodes, i.e, `CODESIZE (0x38)/CODECOPY (0x39)/EXTCODESIZE (0x3B)/EXTCODECOPY (0x3C)/EXTCODEHASH (0x3F)/DELEGATECALL (0xF4)/CALL (0xF1)/CALLCODE (0xF2)/STATICCALL (0xFA)/CREATE (0xF0)/CREATE2 (0xF5)`; and
- no change to the existing structure of the Ethereum state.


## Specification

### Parameters

| Constant                  | Value            |
| ------------------------- | ---------------- |
| `FORK_BLKNUM`             | TBD              |
| `CODE_SIZE_UNIT`          | 24576            |
| `COLD_ACCOUNT_CODE_ACCESS_COST_PER_UNIT`  | 2600             |
| `CREATE_DATA_GAS`         | 200              |

If `block.number &gt;= FORK_BLKNUM`, the contract creation initialization can return data with any length, but the contract-related opcodes will take extra gas as defined below:

- For `CODESIZE/CODECOPY/EXTCODESIZE/EXTCODEHASH`, the gas is unchanged.

- For CREATE/CREATE2, if the newly created contract size &gt; `CODE_SIZE_UNIT`, the opcodes will take extra write gas as

`(CODE_SIZE - CODE_SIZE_UNIT) * CREATE_DATA_GAS`.

- For `EXTCODECOPY/CALL/CALLCODE/DELEGATECALL/STATICCALL`, if the contract code size &gt; `CODE_SIZE_UNIT`, then the opcodes will take extra gas as

```
(CODE_SIZE - 1) // CODE_SIZE_UNIT * COLD_ACCOUNT_CODE_ACCESS_COST_PER_UNIT
```

if the contract is not in `accessed_code_in_addresses` or `0` if the contract is in `accessed_code_in_addresses`, where `//` is the integer divide operator, and `accessed_code_in_addresses: Set[Address]` is a transaction-context-wide set similar to `access_addresses` and `accessed_storage_keys`.

When a transaction execution begins, `accessed_code_in_addresses` will include `tx.sender`, `tx.to`, and all precompiles.

When `CREATE/CREATE2/EXTCODECOPY/CALL/CALLCODE/DELEGATECALL/STATICCALL` is called, immediately add the address to `accessed_code_in_addresses`.

## Rationale

### Gas Metering
The goal is to measure the CPU/IO cost of the contract read/write operations reusing existing gas metering so that the resources will not be abused.

- For code-size-related opcodes (`CODESIZE`/`EXTCODESIZE`), we would expect the client to implement a mapping from the hash of code to the size, so reading the code size of a large contract should still be O(1).

- For `CODECOPY`, the data is already loaded in memory (as part of `CALL/CALLCODE/DELEGATECALL/STATICCALL`), so we do not charge extra gas.

- For `EXTCODEHASH`, the value is already in the account, so we do not charge extra gas.

- For `EXTCODECOPY/CALL/CALLCODE/DELEGATECALL/STATICCALL`, since it will read extra data from the database, we will additionally charge `COLD_ACCOUNT_CODE_ACCESS_COST_PER_UNIT` per extra `CODE_SIZE_UNIT`.

- For `CREATE/CREATE2`, since it will create extra data to the database, we will additionally charge `CREATE_DATA_GAS` per extra bytes.


## Backwards Compatibility

All existing contracts will not be impacted by the proposal.

Only contracts deployed before [EIP-170](/EIPs/EIPS/eip-170) could possibly be longer than the current max code size, and the reference implementation was able to successfully import all blocks before that fork.

## Reference Implementation

The reference implementation on Geth is available at [0001-unlimit-code-size.patch](/EIPs/assets/eip-5027/0001-unlimit-code-size.patch).

## Security Considerations
TBD

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).


</description>
        <pubDate>Thu, 21 Apr 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5027</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5027</guid>
      </item>
    
      <item>
        <title>Interactive NFTs with Modular Environments</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5050-nft-interaction-standard/9922</comments>
        
        <description>## Abstract

This standard defines a broadly applicable action messaging protocol for the transmission of user-initiated actions between tokens. Modular statefulness is achieved with optional state controller contracts (i.e. environments) that manage shared state, and provide arbitration and settlement of the action process.

## Motivation

Tokenized item standards such as [EIP-721](/EIPs/EIPS/eip-721) and [EIP-1155](/EIPs/EIPS/eip-1155) serve as the objects of the Ethereum computing environment. A growing number of projects are seeking to build interactivity and *&quot;digital physics&quot;* into NFTs, especially in the contexts of gaming and decentralized identity. A standard action messaging protocol will allow this physics layer to be developed in the same open, Ethereum-native way as the objects they operate on.

The messaging protocol outlined defines how an action is initiated and transmitted between tokens and (optional) shared state environments. It is paired with a common interface for defining functionality that allows off-chain services to aggregate and query supported contracts for functionality and interoperability; creating a discoverable, human-readable network of interactive token contracts. Not only can contracts that implement this standard be automatically discovered by such services, their *policies for interaction* can be as well. This allows clients to easily discover compatible senders and receivers, and allowed actions.

Aggregators can also parse action event logs to derive analytics on new action types, trending/popular/new interactive contracts, which token and state contract pairs users are likely to interact with, and other discovery tools to facilitate interaction.
 
### Benefits

1. Make interactive token contracts **discoverable and usable** by applications
2. Create a decentralized &quot;digital physics&quot; layer for gaming and other applications
3. Provide developers a simple solution with viable validity guarantees to make dynamic NFTs and other tokens 
4. Allow for generalized action bridges to transmit actions between chains (enabling actions on L1 assets to be saved to L2s, L1 assets to interact with L2 assets, and L2 actions to be &quot;rolled-up&quot;/finalized on L1).

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

Smart contracts implementing this EIP standard MUST implement the [EIP-165](/EIPs/EIPS/eip-165) supportsInterface function and MUST return the constant value `true` if the `IERC5050Sender` interface ID `0xc8c6c9f3` and/or the `IERC5050Receiver` interface ID `0x1a3f02f4` is passed through the `interfaceID` argument (depending on which interface(s) the contract implements).

```solidity
pragma solidity ^0.8.0;

/// @param _address The address of the interactive object
/// @param tokenId The token that is interacting (optional)
struct Object {
    address _address;
    uint256 _tokenId;
}

/// @param selector The bytes4(keccack256()) encoding of the action string
/// @param user The address of the sender
/// @param from The initiating object
/// @param to The receiving object
/// @param state The state controller contract
/// @param data Additional data with no specified format
struct Action {
    bytes4 selector;
    address user;
    Object from;
    Object to;
    address state;
    bytes data;
}

/// @title EIP-5050 Interactive NFTs with Modular Environments
interface IERC5050Sender {
    /// @notice Send an action to the target address
    /// @dev The action&apos;s `fromContract` is automatically set to `address(this)`,
    /// and the `from` parameter is set to `msg.sender`.
    /// @param action The action to send
    function sendAction(Action memory action) external payable;

    /// @notice Check if an action is valid based on its hash and nonce
    /// @dev When an action passes through all three possible contracts
    /// (`fromContract`, `to`, and `state`) the `state` contract validates the
    /// action with the initiating `fromContract` using a nonced action hash.
    /// This hash is calculated and saved to storage on the `fromContract` before
    /// action handling is initiated. The `state` contract calculates the hash
    /// and verifies it and nonce with the `fromContract`.
    /// @param _hash The hash to validate
    /// @param _nonce The nonce to validate
    function isValid(bytes32 _hash, uint256 _nonce) external returns (bool);

    /// @notice Retrieve list of actions that can be sent.
    /// @dev Intended for use by off-chain applications to query compatible contracts,
    /// and to advertise functionality in human-readable form.
    function sendableActions() external view returns (string[] memory);

    /// @notice Change or reaffirm the approved address for an action
    /// @dev The zero address indicates there is no approved address.
    ///  Throws unless `msg.sender` is the `_account`, or an authorized
    ///  operator of the `_account`.
    /// @param _account The account of the account-action pair to approve
    /// @param _action The action of the account-action pair to approve
    /// @param _approved The new approved account-action controller
    function approveForAction(
        address _account,
        bytes4 _action,
        address _approved
    ) external returns (bool);

    /// @notice Enable or disable approval for a third party (&quot;operator&quot;) to conduct
    ///  all actions on behalf of `msg.sender`
    /// @dev Emits the ApprovalForAll event. The contract MUST allow
    ///  an unbounded number of operators per owner.
    /// @param _operator Address to add to the set of authorized operators
    /// @param _approved True if the operator is approved, false to revoke approval
    function setApprovalForAllActions(address _operator, bool _approved)
        external;

    /// @notice Get the approved address for an account-action pair
    /// @dev Throws if `_tokenId` is not a valid NFT.
    /// @param _account The account of the account-action to find the approved address for
    /// @param _action The action of the account-action to find the approved address for
    /// @return The approved address for this account-action, or the zero address if
    ///  there is none
    function getApprovedForAction(address _account, bytes4 _action)
        external
        view
        returns (address);

    /// @notice Query if an address is an authorized operator for another address
    /// @param _account The address on whose behalf actions are performed
    /// @param _operator The address that acts on behalf of the account
    /// @return True if `_operator` is an approved operator for `_account`, false otherwise
    function isApprovedForAllActions(address _account, address _operator)
        external
        view
        returns (bool);

    /// @dev This emits when an action is sent (`sendAction()`)
    event SendAction(
        bytes4 indexed name,
        address _from,
        address indexed _fromContract,
        uint256 _tokenId,
        address indexed _to,
        uint256 _toTokenId,
        address _state,
        bytes _data
    );

    /// @dev This emits when the approved address for an account-action pair
    ///  is changed or reaffirmed. The zero address indicates there is no
    ///  approved address.
    event ApprovalForAction(
        address indexed _account,
        bytes4 indexed _action,
        address indexed _approved
    );

    /// @dev This emits when an operator is enabled or disabled for an account.
    ///  The operator can conduct all actions on behalf of the account.
    event ApprovalForAllActions(
        address indexed _account,
        address indexed _operator,
        bool _approved
    );
}

interface IERC5050Receiver {
    /// @notice Handle an action
    /// @dev Both the `to` contract and `state` contract are called via
    /// `onActionReceived()`.
    /// @param action The action to handle
    function onActionReceived(Action calldata action, uint256 _nonce)
        external
        payable;

    /// @notice Retrieve list of actions that can be received.
    /// @dev Intended for use by off-chain applications to query compatible contracts,
    /// and to advertise functionality in human-readable form.
    function receivableActions() external view returns (string[] memory);

    /// @dev This emits when a valid action is received.
    event ActionReceived(
        bytes4 indexed name,
        address _from,
        address indexed _fromContract,
        uint256 _tokenId,
        address indexed _to,
        uint256 _toTokenId,
        address _state,
        bytes _data
    );
}
```

### Action Naming

Actions SHOULD use dot-separation for namespacing (e.g. `&quot;spells.cast&quot;` specifies the `&quot;cast&quot;` action with namespace `&quot;spells&quot;`), and arrow-separation for sequence specification (e.g. `&quot;settle&gt;build&quot;` indicating `&quot;settle&quot;` must be received before `&quot;build&quot;`).

### How State Contracts Work

Actions do not require that a state contract be used. Actions can be transmitted from one token contract (`Object`) to another, or from a user to a single token contract. In these cases, the sending and receiving contracts each control their own state.

State contracts allow arbitrary senders and receivers to share a user-specified state environment. Each `Object` MAY define its own action handling, which MAY include reading from the state contract during, but the action MUST be finalized by the state contract. This means the state contract serves as ground truth.

The intended workflow is for state contracts to define stateful game environments, typically with a custom `IState` interface for use by other contracts. `Objects` register with state contracts to initialize their state. Then, users commit actions using a specific state contract to make things happen in the game.

The modularity of state contracts allows multiple copies of the same or similar &quot;game environment&quot; to be created and swapped in or out by the client. There are many ways this modularity can be used:

- Aggregator services can analyze action events to determine likely state contracts for a given sender/receiver
- Sender/receiver contracts can require a specific state contract
- Sender/receiver contracts can allow any state contract, but set a default. This is important for NFTs that change their render based on state. This default can also be configurable by the token holder.
- State contracts can be bridges to state contracts on another chain, allowing for L1-verification, L2-storage usage pattern (validate action with layer-1 assets, save on l2 where storage is cheaper).

#### Example

State Contract `FightGame` defines a fighting game environment. Token holders call `FightGame.register(contract, tokenId)` to randomly initialize their stats (strength/hp/etc.). An account which holds a registered token A of contract `Fighters`, calls `Fighters.sendAction(AttackAction)`, specifying token A from `Fighters` as the sender, token B from `Pacifists` contract as the receiver, and `FightGame` as the state contract.

The action is passed to token B, which may handle the action in whatever way it wants before passing the action to the `FightGame` state contract. The state contract can verify the stored action hash with the `Fighters` contract to validate the action is authentic before updating the stats if the tokens, dealing damage to token B.

Tokens A and B may update their metadata based on stats in the `FightGame` state contract, or based on their own stored data updated in response to sending/receiving actions.

### Extensions

#### Interactive

Some contracts may have custom user interfaces that facilitate interaction.

```solidity
pragma solidity ^0.8.0;

/// @title EIP-5050 Interactive NFTs with Modular Environments
interface IERC5050Interactive {
    function interfaceURI(bytes4 _action) external view returns (string);
}
```

#### Action Proxies

Action proxies can be used to support backwards compatibility with non-upgradeable contracts, and potentially for cross-chain action bridging.

They can be implemented using a modified version of [EIP-1820](/EIPs/EIPS/eip-1820#erc-1820-registry-smart-contract) that allows [EIP-173](/EIPs/EIPS/eip-173) contract owners to call `setManager()`.

#### Controllable

Users of this standard may want to allow trusted contracts to control the action process to provide security guarantees, and support action bridging. Controllers step through the action chain, calling each contract individually in sequence.

Contracts that support Controllers SHOULD ignore require/revert statements related to action verification, and MUST NOT pass the action to the next contract in the chain.

```solidity
pragma solidity ^0.8.0;

/// @title EIP-5050 Action Controller
interface IControllable {
    
    /// @notice Enable or disable approval for a third party (&quot;controller&quot;) to force
    ///  handling of a given action without performing EIP-5050 validity checks.
    /// @dev Emits the ControllerApproval event. The contract MUST allow
    ///  an unbounded number of controllers per action.
    /// @param _controller Address to add to the set of authorized controllers
    /// @param _action Selector of the action for which the controller is approved / disapproved
    /// @param _approved True if the controller is approved, false to revoke approval
    function setControllerApproval(address _controller, bytes4 _action, bool _approved)
        external;

    /// @notice Enable or disable approval for a third party (&quot;controller&quot;) to force
    ///  action handling without performing EIP-5050 validity checks. 
    /// @dev Emits the ControllerApproval event. The contract MUST allow
    ///  an unbounded number of controllers per action.
    /// @param _controller Address to add to the set of authorized controllers
    /// @param _approved True if the controller is approved, false to revoke approval
    function setControllerApprovalForAll(address _controller, bool _approved)
        external;

    /// @notice Query if an address is an authorized controller for a given action.
    /// @param _controller The trusted third party address that can force action handling
    /// @param _action The action selector to query against
    /// @return True if `_controller` is an approved operator for `_account`, false otherwise
    function isApprovedController(address _controller, bytes4 _action)
        external
        view
        returns (bool);
    
    /// @dev This emits when a controller is enabled or disabled for the given
    ///  action. The controller can force `action` handling on the emitting contract, 
    ///  bypassing the standard EIP-5050 validity checks.
    event ControllerApproval(
        address indexed _controller,
        bytes4 indexed _action,
        bool _approved
    );
    
    /// @dev This emits when a controller is enabled or disabled for all actions.
    ///  Disabling all action approval for a controller does not override explicit action
    ///  action approvals. Controller&apos;s approved for all actions can force action handling 
    ///  on the emitting contract for any action.
    event ControllerApprovalForAll(
        address indexed _controller,
        bool _approved
    );
}
```

#### Metadata Update

Interactive NFTs are likely to update their metadata in response to certain actions and developers MAY want to implement [EIP-4906](/EIPs/EIPS/eip-4906) event emitters.

## Rationale

The critical features of this interactive token standard are that it 1) creates a common way to define, advertise, and conduct object interaction, 2) enables optional, brokered statefulness with *useful* validity assurances at minimum gas overhead, 3) is easy for developers to implement, and 4) is easy for end-users to use.

### Action Names &amp; Selectors

Actions are advertised using human-readable strings, and processed using function selectors (`bytes4(keccack256(action_key))`). Human-readable strings allow end-users to easily interpret functionality, while function selectors allow efficient comparison operations on arbitrarily long action keys. This scheme also allows for simple namespacing and sequence specification.

Off-chain services can easily convert the strings to `bytes4` selector encoding when interacting with contracts implementing this EIP or parsing `SendAction` and `ActionReceived` event logs.

### Validation

Validation of the initiating contract via a hash of the action data was satisfactory to nearly everyone surveyed and was the most gas efficient verification solution explored. We recognize that this solution does not allow the receiving and state contracts to validate the initiating `user` account beyond using `tx.origin`, which is vulnerable to phishing attacks.

We considered using a signed message to validate user-intiation, but this approach had two major drawbacks:

1. **UX** users would be required to perform two steps to commit each action (sign the message, and send the transaction)
2. **Gas** performing signature verification is computationally expensive

Most importantly, the consensus among the developers surveyed is that strict user validation is not necessary because the concern is only that malicious initiating contracts will phish users to commit actions *with* the malicious contract&apos;s assets. **This protocol treats the initiating contract&apos;s token as the prime mover, not the user.** Anyone can tweet at Bill Gates. Any token can send an action to another token. Which actions are accepted, and how they are handled is left up to the contracts. High-value actions can be reputation-gated via state contracts, or access-gated with allow/disallow-lists. [`Controllable`](#controllable) contracts can also be used via trusted controllers as an alternative to action chaining.

*Alternatives considered: action transmitted as a signed message, action saved to reusable storage slot on initiating contract*

### State Contracts

Moving state logic into dedicated, parameterized contracts makes state an action primitive and prevents state management from being obscured within the contracts. Specifically, it allows users to decide which &quot;environment&quot; to commit the action in, and allows the initiating and receiving contracts to share state data without requiring them to communicate.

The specifics of state contract interfaces are outside the scope of this standard, and are intended to be purpose-built for unique interactive environments.

### Gas and Complexity (regarding action chaining)

Action handling within each contract can be arbitrarily complex, and there is no way to eliminate the possibility that certain contract interactions will run out of gas. However, developers SHOULD make every effort to minimize gas usage in their action handler methods, and avoid the use of for-loops.

*Alternatives considered: multi-request action chains that push-pull from one contract to the next.*

## Backwards Compatibility

Non-upgradeable, already deployed token contracts will not be compatible with this standard unless a proxy registry extension is used.

## Reference Implementation

A reference implementation is included in `../assets/eip-5050` with a simple stateless example [`ExampleToken2Token.sol`](/EIPs/assets/eip-5050/ExampleToken2Token.sol), and a stateful example [`ExampleStateContract.sol`](/EIPs/assets/eip-5050/ExampleStateContract.sol)

## Security Considerations

The core security consideration of this protocol is action validation. Actions are passed from one contract to another, meaning it is not possible for the receiving contract to natively verify that the caller of the initiating contract matches the `action.from` address. One of the most important contributions of this protocol is that it provides an alternative to using signed messages, which require users to perform two operations for every action committed.

As discussed in [Validation](#validation), this is viable because the initiating contract / token is treated as the prime mover, not the user.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 18 Apr 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5050</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5050</guid>
      </item>
    
      <item>
        <title>Lockable Non-Fungible Tokens</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5058-erc-721-lockable-standard/9201</comments>
        
        <description>## Abstract

We propose to extend the [EIP-721](/EIPs/EIPS/eip-721) standard with a secure locking mechanism. The NFT owners approve the operator to lock the NFT through `setLockApprovalForAll()` or `lockApprove()`. The approved operator locks the NFT through `lock()`. The locked NFTs cannot be transferred until the end of the locking period. An immediate use case is to allow NFTs to participate in smart contracts without leaving the wallets of their owners.

## Motivation

NFTs, enabled by [EIP-721](/EIPs/EIPS/eip-721), have exploded in demand. The total market value and the ecosystem continue to grow with more and more blue chip NFTs, which are approximately equivalent to popular intellectual properties in a conventional sense. Despite the vast success, something is left to be desired. Liquidity has always been one of the biggest challenges for NFTs. Several attempts have been made to tackle the liquidity challenge: NFTFi and BendDAO, to name a few. Utilizing the currently prevalent EIP-721 standard, these projects require participating NFTs to be transferred to the projects&apos; contracts, which poses inconveniences and risks to the owners:

1. Smart contract risks: NFTs can be lost or stolen due to bugs or vulnerabilities in the contracts.
2. Loss of utility: NFTs have utility values, such as profile pictures and bragging rights, which are lost when the NFTs are no longer seen under the owners&apos; custody.
3. Missing Airdrops: The owners can no longer directly receive airdrops entitled to the NFTs. Considering the values and price fluctuation of some of the airdrops, either missing or not getting the airdrop on time can financially impact the owners.

All of the above are bad UX, and we believe the EIP-721 standard can be improved by adopting a native locking mechanism:

1. Instead of being transferred to a smart contract, an NFT remains in self-custody but locked.
2. While an NFT is locked, its transfer is prohibited. Other properties remain unaffected.
3. The owners can receive or claim airdrops themselves.

The value of an NFT can be reflected in two aspects: collection value and utility value. Collection value needs to ensure that the holder&apos;s wallet retains ownership of the NFT forever. Utility value requires ensuring that the holder can verify their NFT ownership in other projects. Both of these aspects require that the NFT remain in its owner&apos;s wallet.

The proposed standard allows the underlying NFT assets to be managed securely and conveniently by extending the EIP-721 standard to natively support common NFTFi use cases including locking, staking, lending, and crowdfunding. We believe the proposed standard will encourage NFT owners to participate more actively in NFTFi projects and, hence, improve the livelihood of the whole NFT ecosystem.

## Specification

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.

Lockable EIP-721 **MUST** implement the `IERC5058` interfaces:

```solidity
// SPDX-License-Identifier: CC0-1.0

pragma solidity ^0.8.8;

/**
 * @dev EIP-721 Non-Fungible Token Standard, optional lockable extension
 * ERC721 Token that can be locked for a certain period and cannot be transferred.
 * This is designed for a non-escrow staking contract that comes later to lock a user&apos;s NFT
 * while still letting them keep it in their wallet.
 * This extension can ensure the security of user tokens during the staking period.
 * If the nft lending protocol is compatible with this extension, the trouble caused by the NFT
 * airdrop can be avoided, because the airdrop is still in the user&apos;s wallet
 */
interface IERC5058 {
    /**
     * @dev Emitted when `tokenId` token is locked by `operator` from `from`.
     */
    event Locked(address indexed operator, address indexed from, uint256 indexed tokenId, uint256 expired);

    /**
     * @dev Emitted when `tokenId` token is unlocked by `operator` from `from`.
     */
    event Unlocked(address indexed operator, address indexed from, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to lock the `tokenId` token.
     */
    event LockApproval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to lock all of its tokens.
     */
    event LockApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the locker who is locking the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function lockerOf(uint256 tokenId) external view returns (address locker);

    /**
     * @dev Lock `tokenId` token until the block number is greater than `expired` to be unlocked.
     *
     * Requirements:
     *
     * - `tokenId` token must be owned by `owner`.
     * - `expired` must be greater than block.number
     * - If the caller is not `owner`, it must be approved to lock this token
     * by either {lockApprove} or {setLockApprovalForAll}.
     *
     * Emits a {Locked} event.
     */
    function lock(uint256 tokenId, uint256 expired) external;

    /**
     * @dev Unlock `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` token must be owned by `owner`.
     * - the caller must be the operator who locks the token by {lock}
     *
     * Emits a {Unlocked} event.
     */
    function unlock(uint256 tokenId) external;

    /**
     * @dev Gives permission to `to` to lock `tokenId` token.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved lock operator.
     * - `tokenId` must exist.
     *
     * Emits an {LockApproval} event.
     */
    function lockApprove(address to, uint256 tokenId) external;

    /**
     * @dev Approve or remove `operator` as an lock operator for the caller.
     * Operators can call {lock} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {LockApprovalForAll} event.
     */
    function setLockApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns the account lock approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getLockApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to lock all of the assets of `owner`.
     *
     * See {setLockApprovalForAll}
     */
    function isLockApprovedForAll(address owner, address operator) external view returns (bool);

    /**
     * @dev Returns if the `tokenId` token is locked.
     */
    function isLocked(uint256 tokenId) external view returns (bool);

    /**
     * @dev Returns the `tokenId` token lock expired time.
     */
    function lockExpiredTime(uint256 tokenId) external view returns (uint256);
}
```

## Rationale

### NFT lock approvals

An NFT owner can give another trusted operator the right to lock his NFT through the approve functions. The `lockApprove()` function only approves for the specified NFT, whereas `setLockApprovalForAll()` approves for all NFTs of the collection under the wallet. When a user participates in an NFTFi project, the project contract calls `lock()` to lock the user&apos;s NFT. Locked NFTs cannot be transferred, but the NFTFi project contract can use the unlock function `unlock()` to unlock the NFT.

### NFT lock/unlock

Authorized project contracts have permission to lock NFT with the `lock` method. Locked NFTs cannot be transferred until the lock time expires. The project contract also has permission to unlock NFT in advance through the `unlock` function. Note that only the address of the locked NFT has permission to unlock that NFT.

### NFT lock period

When locking an NFT, one must specify the lock expiration block number, which must be greater than the current block number. When the current block number exceeds the expiration block number, the NFT is automatically released and can be transferred.

### Bound NFT

Bound NFT is an extension of this EIP, which implements the ability to mint a boundNFT during the NFT locking period. The boundNFT is identical to the locked NFT metadata and can be transferred. However, a boundNFT only exists during the NFT locking period and will be destroyed after the NFT is unlocked.
BoundNFT can be used to lend, as a staking credential for the contract. The credential can be locked in the contract, but also to the user. In NFT leasing, boundNFT can be rented to users because boundNFT is essentially equivalent to NFT. This consensus, if accepted by all projects, boundNFT will bring more creativity to NFT.

### Bound NFT Factory

Bound NFT Factory is a common boundNFT factory, similar to Uniswap&apos;s [EIP-20](/EIPs/EIPS/eip-20) pairs factory. It uses the create2 method to create a boundNFT contract address for any NFT deterministic. BoundNFT contract that has been created can only be controlled by the original NFT contract.


## Backwards Compatibility

This standard is compatible with EIP-721.

## Test Cases

Test cases written using hardhat can be found [here](/EIPs/assets/eip-5058/test/test.ts)

## Reference Implementation

You can find an implementation of this standard in the [assets](/EIPs/assets/eip-5058/ERC5058.sol) folder.

## Security Considerations

After being locked, the NFT can not be transferred, so before authorizing locking rights to other project contracts, you must confirm that the project contract can unlock NFT. Otherwise there is a risk of NFT being permanently locked. It is recommended to give a reasonable locking period in use for projects. NFT can be automatically unlocked, which can reduce the risk to a certain extent.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 30 Apr 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5058</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5058</guid>
      </item>
    
      <item>
        <title>Instruction for transferring ether</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5065-instruction-for-transferring-ether/9107</comments>
        
        <description>## Abstract
Add a new instruction that transfers ether to a destination address without handing over the flow of execution to it. It should work similarly to how `SELFDESTRUCT (0xFF)` transfers ether to the destination without making a call to it.

## Motivation
From an architectural point of view, execution flow should never be handed over to an untrusted contract. Ethereum currently does not have any ideal way to transfer ether without transferring the flow of execution. People have come up with reentrancy guards and similar solutions to prevent some types of attacks but it&apos;s not an ideal solution. The only way to transfer ether from smart contracts without triggering a call is to create a dummy contract, send the precise amount of ether to it and then call `SELFDESTRUCT (0xFF)` from it.

## Specification
Introduce a new instruction, `AIRDROP` (`0xFG`) that transfers ether to the destination without making a call to it.

### Stack input
address: the account to send ether to.
value: value in wei to send to the account.

### Gas

The total gas cost should be the sum of a static cost + address_access_cost + value_to_empty_account_cost.
  - Static cost: 6700
  - Dynamic cost:
    1. address_access_cost: If the target is not in `accessed_addresses`, charge `COLD_ACCOUNT_ACCESS_COST` gas, and add the address to `accessed_addresses`. Otherwise, charge `WARM_STORAGE_READ_COST` gas. Currently, `COLD_ACCOUNT_ACCESS_COST` is 2600 while `WARM_STORAGE_READ_COST` is 100.
    2. value_to_empty_account_cost: If value is not 0 and the address given points to an empty account, then value_to_empty_account_cost is the account creation gas cost which currently is 25000. An account is empty if its balance is 0, its nonce is 0 and it has no code.


## Rationale
This behavior is already possible by deploying a new contract that does `SELFDESTRUCT (0xFF)` but it is prohibitively expensive. In most scenarios, the contract author only wants to transfer ether rather than transferring control of the execution. ERC20 can be used as a case study for this where most users transfer funds without a post-transfer hook.

This instruction allows contracts to safely pass ether to an untrusted address without worrying about reentrancy or other malicious things an untrusted contract can do on.

The static gas cost is derived by subtracting the gas stipend (2300) from the positive_value_cost of `CALL (0xF1)` opcode which is currently set to 9000.

## Backwards Compatibility
No known issues as this is a new instruction that does not affect any old instructions and does not break any valid assumptions since it make not anything impossible possible.

## Test Cases
TODO

## Security Considerations
No known security risks.

## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
</description>
        <pubDate>Sat, 30 Apr 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5065</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5065</guid>
      </item>
    
      <item>
        <title>EIP Editor Handbook</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/pr-5069-eip-editor-handbook/9137</comments>
        
        <description>## Introduction

We, the Ethereum Improvement Proposal (EIP) Editors, maintain a repository of documents related to the Ethereum protocol and its ecosystem. Consider us both _archivists_ making sure the community as a whole does not lose its history, and a _publisher_ making sure interested parties can stay up-to-date with the latest proposals.

## Mission

### What we Do

Our mission is to serve the broad Ethereum community, both present and future, by:

 - **Publishing Proposals**: Making proposals, including their history and associated discussions available over the long term at no cost.
    
    By doing so, we foster transparency and ensure that valuable insights from past proposals are accessible for future decision-making and learning.
 - **Facilitating Discussion**: Providing a forum for discussing proposals open to anyone who wants to participate civilly.
    
    By encouraging open dialogue and collaboration, we aim to harness the collective knowledge and expertise of the Ethereum community in shaping proposals.
 - **Upholding Quality**: Upholding a measure of minimally-subjective quality for each proposal as defined by its target audience.

    By adhering to defined criteria, we promote the development of high-quality and relevant proposals that drive the evolution of Ethereum.

### What we Don&apos;t

On the other hand, we do _not_:

 - **Decide Winners**: If there are multiple competing proposals, we will publish all of them. We are not in the business of deciding what is the right path for Ethereum, nor do we believe that there is One True Way to satisfy a need.

 - **Assert Correctness**: While we might offer technical feedback from time to time, we are not experts nor do we vet every proposal in depth. Publishing a proposal is not an endorsement or a statement of technical soundness.

 - **Manage**: We do not track implementation status, schedule work, or set fork dates or contents.

 - **Track Registries**: We want all proposals to eventually become immutable, but a registry will never get there if anyone can keep adding items. To be clear, exhaustive and/or static lists are fine. 
 - **Provide Legal Advice**: Trademarks, copyrights, patents, prior art, and other legal matters are the responsibility of authors and implementers, not EIP Editors. We are not lawyers, and while we may occasionally make comments touching on these areas, we cannot guarantee any measure of correctness.

Documenting all of the things we would not do is impossible, and the above are just a few examples. We reserve the right to do less work whenever possible!

## Structure

### EIP Editors

We, the Editors, consist of some number of EIP Editors and one Keeper of Consensus (or just Keeper for short) elected by and from the EIP Editors.

EIP Editors are responsible for governing the EIP process itself, electing a Keeper, and stewarding proposals.

The Keeper&apos;s two responsibilities (on top of their EIP Editor duties) are: to determine when rough consensus has been reached on a matter, and determine when/if it is appropriate to re-open an already settled matter.

## Membership

Anyone may apply to join as an EIP Editor. Specific eligibility requirements are left to individual current EIP Editors, but the general requirements are:

 - A strong belief in the above mission;
 - Proficiency with English (both written and spoken);
 - Reading and critiquing EIPs;
 - Participation in governance.

EIP Editors are expected to meet these requirements throughout their tenure, and not doing so is grounds for removal. Any member may delegate some or all of their responsibilities/powers to tools and/or to other people.

## Making Decisions

### Informally

For decisions that are unlikely to be controversial—especially for decisions affecting a single proposal—an EIP Editor may choose whatever option they deem appropriate in accordance with our mission.

### Formally

Electing a Keeper, adding/removing EIP Editors, and any possibly-controversial decisions must all be made using variations of this formal process.

#### Preparation

##### Call for Input

For any matter requiring a decision, a call for input must be published in writing to the usual channels frequented by EIP Editors.

##### Quorum

Within thirty days of the call for input, to establish a valid quorum, all EIP Editors must express their opinion, vote (where appropriate), or lack thereof on the matter under consideration.

After thirty days from the call for input, if not all EIP Editors have responded, the quorum is reduced to the Editors that have responded. This deadline may be extended in exceptional situations.

#### Deciding

##### Electing a Keeper of Consensus

Any EIP Editor can call for an election for Keeper. Business continues as usual while the election is running. The EIP Editor with the most votes once quorum is met is named Keeper until the next election completes. If there is a tie, we&apos;ll randomly choose between the EIP Editors with the most votes, using a fair and agreed upon method (for example, a coin toss over a video call or a commit/reveal game of rock paper scissors.)

##### Adding an EIP Editor

An EIP Editor is added once quorum is met, provided the candidate consents and no current EIP Editor objects.

##### Removing an EIP Editor

An EIP Editor is involuntarily retired once quorum is met, provided no current EIP Editor (aside from the one being removed) objects. An EIP Editor may voluntarily leave their position at any time.

If the departing Editor was also the Keeper, an election for a new Keeper begins immediately.

##### Other Decisions

All other decisions are made through a &quot;rough consensus&quot; process. This does not require all EIP Editors to agree, although this is preferred. In general, the dominant view of the Editors shall prevail. Dominance, in this process, is not determined by persistence or volume but rather a more general sense of agreement. Note that 51% does not mean &quot;rough consensus&quot; has been reached, and 99% is better than rough. It is up to the Keeper to determine if rough consensus has been reached. Every EIP Editor is entitled to have their opinion heard and understood before the Keeper makes that determination.

No one, not the EIP Editors and certainly not the Keeper, holds veto powers (except when adding/removing an Editor as defined above.) It is imperative that the EIP process evolve, albeit cautiously.

_This section has been adapted from [RFC 2418]._

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[RFC 2418]: https://www.rfc-editor.org/rfc/rfc2418
</description>
        <pubDate>Mon, 02 May 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5069</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5069</guid>
      </item>
    
      <item>
        <title>Expirable Transaction</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5081-expirable-transaction/9208</comments>
        
        <description>## Abstract
This EIP adds a new transaction type of that includes expiration with a blocknum.

## Motivation

When a user sends a transaction `tx0` with a low gas price, sometimes it might not be high enough to be executed.
A common resolution is for the user to submit the transaction again with the same nonce and higher gas price.

That previous `tx0` can theoretically be included in any time in the future unless a `tx` with the exact same nonce is already executed.

When network is congested, gas price are high, for critical transactions user might try gas price that is much higher than an average day. 
This cause the `tx0` choice might be very easy to executed in the average day.

If user already uses a `tx1` with different nonce or from another account to execute the intended transaction,
there is currently no clean way to cancel it,
except for signing a new `tx0&apos;` that shares the same nonce but with higher gas fee hoping that it will execute to *preempt*- than `tx0`.

Given `tx0` was already high gas price, the current way of *preempting* `tx0` could be both unreliable and very costly.

TODO(@xinbenlv): to include in the motivation:

- Expiring transactions are transactions that have low time preference, but can easily become invalid in the future. For example, you may want to do a swap on an AMM but you don&apos;t want to pay a very high fee for it so you set the max fee to a low number. However, your transaction will almost certainly fail if it takes longer than a couple minutes to be mined. In this scenario, you would rather fail cheaply if your transaction doesn&apos;t get included quickly.

- Similarly, there are situations where there is a limited window of availability of some asset and if your transaction doesn&apos;t mine within that period you know with certainty that it will fail. In these cases, it would be nice to be able to express that to the system and not waste unnecessary resources just to have the transaction fail.

## Specification
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.

### Parameters
- `FORK_BLKNUM` = `TBD`
- `CHAIN_ID` = `TBD`
- `TX_TYPE` = TBD, &gt; 0x02 ([EIP-1559](/EIPs/EIPS/eip-1559))


As of `FORK_BLOCK_NUMBER`, a new [EIP-2718](/EIPs/EIPS/eip-2718) transaction is introduced with `TransactionType` = `TX_TYPE(TBD)`.

The intrinsic cost of the new transaction is inherited from [EIP-2930](/EIPs/EIPS/eip-2930), specifically `21000 + 16 * non-zero calldata bytes + 4 * zero calldata bytes + 1900 * access list storage key count + 2400 * access list address count`.

The [EIP-2718](/EIPs/EIPS/eip-2718) `TransactionPayload` for this transaction is 

```
rlp([chain_id, expire_by, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, amount, data, access_list, signature_y_parity, signature_r, signature_s])
```

The definition of `expire_by` is a block number the latest possible block to
execute this transaction. Any block with a block number `block_num &gt; expire_by` MUST NOT execute this transaction.

The definitions of all other fields share the same meaning with [EIP-1559](/EIPs/EIPS/eip-1559)

The `signature_y_parity, signature_r, signature_s` elements of this transaction represent a secp256k1 signature over `keccak256(0x02 || rlp([chain_id, expire_by, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, amount, data, access_list]))`.

The [EIP-2718](/EIPs/EIPS/eip-2718) `ReceiptPayload` for this transaction is `rlp([status, cumulative_transaction_gas_used, logs_bloom, logs])`.


## Rationale
TODO

## Backwards Compatibility
TODO

## Security Considerations

1. If `current_block_num` is available, client MUST drop and stop propagating/broadcasting any transactions that has a
`transaction_type == TX_TYPE` AND `current_block_num &gt; expire_by`

2. It is suggested but not required that a `currentBlockNum` SHOULD be made available to client. Any client doing PoW calculation on blocks expire tx or propagating such are essentially penalized for wasting of work, mitigating possible denial of service attack.

3. It is suggested but not required that client SHOULD introduce a 
`gossip_ttl` in unit of block_num as a safe net so that it only propagate
a tx if `current_block_num + gossip_ttl &lt;= expire_by`. Backward compatibility:
for nodes that doesn&apos;t have `current_block_num` or `gossip_ttl` available,
they should be presumed to be `0`.
  
4. It is suggested by not required that any propagating client SHOULD properly deduct the `gossip_ttl` 
based on the network environment it sees fit.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 06 May 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5081</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5081</guid>
      </item>
    
      <item>
        <title>URL Format for Ethereum Network Switching</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/5094-uri-format-for-ethereum-network-switching/9277</comments>
        
        <description>## Abstract

This standard includes all needed information for adding a network to a wallet via URL, by including parameters such as `chainId`, `rpc_url`, `chain_name` and others, such that the network configuration is provided through the URL itself.

## Motivation

As observed with the use of [EIP-681](/EIPs/EIPS/eip-681) and its implementation in current mobile wallets, transactions can be made, approved, viewed, and used. However, if the wallet is instructed to perform a transaction on a chain they have not yet been configured before, the operation tends to fail.

This is understandable, as the `chain_id` provided makes up only one part of what is required to connect to a network. This EIP aims to introduce a new type of URL for usage with deep-linking, QR, and more, to allow users to seamlessly add new networks to their (for ex. mobile) wallet to then be able to more easily partake in `pay-`, `tx-`, or other Ethereum URL interactions.

As an extension to [EIP-831](/EIPs/EIPS/eip-831) and neighboring [EIP-681](/EIPs/EIPS/eip-681) and [EIP-2400](/EIPs/EIPS/eip-2400), this document aims to standardize the addition of new networks and switching thereof through the means of URLs. User convenience in this case is primary.

Introduction of this EIP is meant to bridge to a safer RPC listing system to be introduced in the near future.

## Specification

### Syntax

Network Switching URLs contain &quot;ethereum&quot; in their schema (protocol) part and are constructed as follows:

    network_add             = erc831_part &quot;add&quot; &quot;@&quot; chain_id [ &quot;/&quot; ] &quot;?&quot; parameters
    erc831_part             = &quot;ethereum:network-&quot;
    chain_id                = 1*DIGIT
    parameters              = parameter *( &quot;&amp;&quot; parameter )
    parameter               = key &quot;=&quot; value
    key                     = required_keys / optional_keys
    required_keys           = &quot;rpc_url&quot; / &quot;chain_name&quot;
    optional_keys           = &quot;name&quot; / &quot;symbol&quot; / &quot;decimals&quot; / &quot;explorer_url&quot; / &quot;icon_url&quot;
    value                   = STRING / number
    number                  = 1*DIGIT

`STRING` is a URL-encoded Unicode string of arbitrary length, where delimiters and the
percentage symbol (`%`) are mandatorily hex-encoded with a `%` prefix.

If the *key* in the parameter is `decimals` the *value* MUST be a `number`.

### Semantics

`chain_id` is mandatory and denotes the decimal chain ID, such that we have the identifier of the network we would like to add.

`rpc_url` is represented as an array of RPC URLs. A minimum of 1 `rpc_url` MUST be present, in the format of `rpc_url=https%3A%2F%2Fpolygon-rpc.com`, or when multiple present `rpc_url=https%3A%2F%2Fpolygon-rpc.com&amp;rpc_url=https%3A%2F%2Frpc-mainnet.matic.network`.

`chain_name` is required to specify the name of the network to be added.

`name` and `symbol` if provided, SHOULD be a human-readable string representing the native token.

`decimals` if provided, MUST be a non-negative integer representing the decimal precision of the native token.

`explorer_url` if provided, MUST specify one or more URLs pointing to block explorer web sites for the chain.

`icon_url` if provided, MUST specify one or more URLs pointing to reasonably sized images that can be used to visually identify the chain.

An example of adding a network with RPC endpoints `https://rpc-polygon.com` and `https://rpc-mainnet.matic.network`, the name `Polygon Mainnet`, token `Matic`, symbol `MATIC`, decimals `18`, explorer at `https://polygonscan.com/`, and Chain ID `137` would look as follows:

```URL
ethereum:network-add@137/?chain_name=Polygon%20Mainnet&amp;rpc_url=https%3A%2F%2Frpc-polygon.com&amp;rpc_url=https%3A%2F%2Frpc-mainnet.matic.network&amp;name=Matic&amp;symbol=MATIC&amp;decimals=18&amp;explorer_url=https%3A%2F%2Fpolygonscan.com
```

## Rationale

In furtherance of the Ethereum URL saga, network configuration is a needed addition to the possibility of Ethereum URLs. This would improve functionality for URLs, and offer non-mainnet users a way to connect without needing to configure their wallet by hand.

The URL follows [EIP-831](/EIPs/EIPS/eip-831) with the `PREFIX` being `network` and the `PAYLOAD` being a composite of `add` and [EIP-681](/EIPs/EIPS/eip-681)-like `chain_id` and parameters.

The choice for `PREFIX` being `network` is to allow further expansion and allow variants following the pattern `network-x`.

An example URL for adding the Optimism Network

```URL
ethereum:network-add@10/?chain_name=Optimistic%20Ethereum
&amp;rpc_url=https%3A%2F%2Fmainnet.optimism.io&amp;name=Ethereum&amp;symbol=ETH&amp;decimals=18&amp;explorer_url=https%3A%2F%2Foptimistic.etherscan.io
```

The specification allows for a multitude of `rpc_url` and `explorer_url` to be specified. This is done such to overlap with parsing of the `TYPE` mentioned in [EIP-681](/EIPs/EIPS/eip-681).

## Security Considerations

URLs can be malformed to deceive users. Users SHOULD confirm source of URL before using any links. As well as checking source and transaction details before confirming any transactions. Applications SHOULD display network config, prior to network addition, such that users can confirm the validity of the network configuration being added.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 13 May 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5094</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5094</guid>
      </item>
    
      <item>
        <title>Principal Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5095-principal-token-standard/9259</comments>
        
        <description>## Abstract

Principal tokens represent ownership of an underlying [EIP-20](/EIPs/EIPS/eip-20) token at a future timestamp.

This specification is an extension on the [EIP-20](/EIPs/EIPS/eip-20) token that provides basic functionality for depositing
and withdrawing tokens and reading balances and the [EIP-2612](/EIPs/EIPS/eip-2612) specification that provides
[EIP-712](/EIPs/EIPS/eip-712) signature based approvals.

## Motivation

Principal tokens lack standardization which has led to a difficult to navigate development space and diverse implementation
schemes.

The primary examples include yield tokenization platforms which strip future yield leaving a principal
token behind, as well as fixed-rate money-markets which utilize principal tokens as a medium
to lend/borrow.

This inconsistency in implementation makes integration difficult at the application layer as well as
wallet layer which are key catalysts for the space&apos;s growth. 
Developers are currently expected to implement individual adapters for each principal token, as well as adapters for
their pool contracts, and many times adapters for their custodial contracts as well, wasting significant developer resources. 

## Specification

All Principal Tokens (PTs) MUST implement [EIP-20](/EIPs/EIPS/eip-20) to represent ownership of future underlying redemption.
If a PT is to be non-transferrable, it MAY revert on calls to `transfer` or `transferFrom`.
The [EIP-20](/EIPs/EIPS/eip-20) operations `balanceOf`, `transfer`, `totalSupply`, etc. operate on the Principal Token balance.

All Principal Tokens MUST implement [EIP-20](/EIPs/EIPS/eip-20)&apos;s optional metadata extensions.
The `name` and `symbol` functions SHOULD reflect the underlying token&apos;s `name` and `symbol` in some way, as well as the origination protocol, and in the case of yield tokenization protocols, the origination money-market.

All Principal Tokens MAY implement [EIP-2612](/EIPs/EIPS/eip-2612) to improve the UX of approving PTs on various integrations.

### Definitions:

- underlying: The token that Principal Tokens are redeemable for at maturity.
  Has units defined by the corresponding [EIP-20](/EIPs/EIPS/eip-20) contract.
- maturity: The timestamp (unix) at which a Principal Token matures. Principal Tokens become redeemable for underlying at or after this timestamp.
- fee: An amount of underlying or Principal Token charged to the user by the Principal Token. Fees can exist on redemption or post-maturity yield.
- slippage: Any difference between advertised redemption value and economic realities of PT redemption, which is not accounted by fees.

### Methods

#### `underlying`

The address of the underlying token used by the Principal Token for accounting, and redeeming.

MUST be an EIP-20 token contract.

MUST _NOT_ revert.

```yaml
- name: underlying
  type: function
  stateMutability: view

  inputs: []

  outputs:
    - name: underlyingAddress
      type: address
```

#### `maturity`

The unix timestamp (uint256) at or after which Principal Tokens can be redeemed for their underlying deposit.

MUST _NOT_ revert.

```yaml
- name: maturity
  type: function
  stateMutability: view

  inputs: []

  outputs:
    - name: timestamp
      type: uint256
```

#### `convertToUnderlying`

The amount of underlying that would be exchanged for the amount of PTs provided, in an ideal scenario where all the conditions are met.

Before maturity, the amount of underlying returned is as if the PTs would be at maturity.

MUST NOT be inclusive of any fees that are charged against redemptions.

MUST NOT show any variations depending on the caller.

MUST NOT reflect slippage or other on-chain conditions, when performing the actual redemption.

MUST NOT revert unless due to integer overflow caused by an unreasonably large input.

MUST round down towards 0.

This calculation MAY NOT reflect the &quot;per-user&quot; price-per-principal-token, and instead should reflect the &quot;average-user&apos;s&quot; price-per-principal-token, meaning what the average user should expect to see when exchanging to and from.

```yaml
- name: convertToUnderlying
  type: function
  stateMutability: view

  inputs:
    - name: principalAmount
      type: uint256

  outputs:
    - name: underlyingAmount
      type: uint256
```

#### `convertToPrincipal`

The amount of principal tokens that the principal token contract would request for redemption in order to provide the amount of underlying specified, in an ideal scenario where all the conditions are met.

MUST NOT be inclusive of any fees.

MUST NOT show any variations depending on the caller.

MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.

MUST NOT revert unless due to integer overflow caused by an unreasonably large input.

MUST round down towards 0.

This calculation MAY NOT reflect the &quot;per-user&quot; price-per-principal-token, and instead should reflect the &quot;average-user&apos;s&quot; price-per-principal-token, meaning what the average user should expect to see when redeeming.

```yaml
- name: convertToPrincipal
  type: function
  stateMutability: view

  inputs:
    - name: underlyingAmount
      type: uint256

  outputs:
    - name: principalAmount
      type: uint256
```

#### `maxRedeem`

Maximum amount of principal tokens that can be redeemed from the `holder` balance, through a `redeem` call.

MUST return the maximum amount of principal tokens that could be transferred from `holder` through `redeem` and not cause a revert, which MUST NOT be higher than the actual maximum that would be accepted (it should underestimate if necessary).

MUST factor in both global and user-specific limits, like if redemption is entirely disabled (even temporarily) it MUST return 0.

MUST NOT revert.

```yaml
- name: maxRedeem
  type: function
  stateMutability: view

  inputs:
    - name: holder
      type: address

  outputs:
    - name: maxPrincipalAmount
      type: uint256
```

#### `previewRedeem`

Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block, given current on-chain conditions.

MUST return as close to and no more than the exact amount of underliyng that would be obtained in a `redeem` call in the same transaction. I.e. `redeem` should return the same or more `underlyingAmount` as `previewRedeem` if called in the same transaction.

MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the redemption would be accepted, regardless if the user has enough principal tokens, etc.

MUST be inclusive of redemption fees. Integrators should be aware of the existence of redemption fees.

MUST NOT revert due to principal token contract specific user/global limits. MAY revert due to other conditions that would also cause `redeem` to revert.

Note that any unfavorable discrepancy between `convertToUnderlying` and `previewRedeem` SHOULD be considered slippage in price-per-principal-token or some other type of condition.

```yaml
- name: previewRedeem
  type: function
  stateMutability: view

  inputs:
    - name: principalAmount
      type: uint256

  outputs:
    - name: underlyingAmount
      type: uint256
```

#### `redeem`

At or after maturity, burns exactly `principalAmount` of Principal Tokens from `from` and sends `underlyingAmount` of underlying tokens to `to`.

Interfaces and other contracts MUST NOT expect fund custody to be present. While custodial redemption of Principal Tokens through the Principal Token contract is extremely useful for integrators, some protocols may find giving the Principal Token itself custody breaks their backwards compatibility. 

MUST emit the `Redeem` event.

MUST support a redeem flow where the Principal Tokens are burned from `holder` directly where `holder` is `msg.sender` or `msg.sender` has EIP-20 approval over the principal tokens of `holder`.
MAY support an additional flow in which the principal tokens are transferred to the Principal Token contract before the `redeem` execution, and are accounted for during `redeem`.

MUST revert if all of `principalAmount` cannot be redeemed (due to withdrawal limit being reached, slippage, the holder not having enough Principal Tokens, etc).

Note that some implementations will require pre-requesting to the Principal Token before a withdrawal may be performed. Those methods should be performed separately.

```yaml
- name: redeem
  type: function
  stateMutability: nonpayable

  inputs:
    - name: principalAmount
      type: uint256
    - name: to
      type: address
    - name: from
      type: address

  outputs:
    - name: underlyingAmount
      type: uint256
```

#### `maxWithdraw`

Maximum amount of the underlying asset that can be redeemed from the `holder` principal token balance, through a `withdraw` call.

MUST return the maximum amount of underlying tokens that could be redeemed from `holder` through `withdraw` and not cause a revert, which MUST NOT be higher than the actual maximum that would be accepted (it should underestimate if necessary).

MUST factor in both global and user-specific limits, like if withdrawals are entirely disabled (even temporarily) it MUST return 0.

MUST NOT revert.

```yaml
- name: maxWithdraw
  type: function
  stateMutability: view

  inputs:
    - name: holder
      type: address

  outputs:
    - name: maxUnderlyingAmount
      type: uint256
```

#### `previewWithdraw`

Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block, given current on-chain conditions.

MUST return as close to and no fewer than the exact amount of principal tokens that would be burned in a `withdraw` call in the same transaction. I.e. `withdraw` should return the same or fewer `principalAmount` as `previewWithdraw` if called in the same transaction.

MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though the withdrawal would be accepted, regardless if the user has enough principal tokens, etc.

MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.

MUST NOT revert due to principal token contract specific user/global limits. MAY revert due to other conditions that would also cause `withdraw` to revert.

Note that any unfavorable discrepancy between `convertToPrincipal` and `previewWithdraw` SHOULD be considered slippage in price-per-principal-token or some other type of condition.

```yaml
- name: previewWithdraw
  type: function
  stateMutability: view

  inputs:
    - name: underlyingAmount
      type: uint256

  outputs:
    - name: principalAmount
      type: uint256
```

#### `withdraw`

Burns `principalAmount` from `holder` and sends exactly `underlyingAmount` of underlying tokens to `receiver`.

MUST emit the `Redeem` event.

MUST support a withdraw flow where the principal tokens are burned from `holder` directly where `holder` is `msg.sender` or `msg.sender` has [EIP-20](/EIPs/EIPS/eip-20) approval over the principal tokens of `holder`.
 MAY support an additional flow in which the principal tokens are transferred to the principal token contract before the `withdraw` execution, and are accounted for during `withdraw`.

MUST revert if all of `underlyingAmount` cannot be withdrawn (due to withdrawal limit being reached, slippage, the holder not having enough principal tokens, etc).

Note that some implementations will require pre-requesting to the principal token contract before a withdrawal may be performed. Those methods should be performed separately.

```yaml
- name: withdraw
  type: function
  stateMutability: nonpayable

  inputs:
    - name: underlyingAmount
      type: uint256
    - name: receiver
      type: address
    - name: holder
      type: address

  outputs:
    - name: principalAmount
      type: uint256
```

### Events

#### Redeem

`from` has exchanged `principalAmount` of Principal Tokens for `underlyingAmount` of underlying, and transferred that underlying to `to`.

MUST be emitted when Principal Tokens are burnt and underlying is withdrawn from the contract in the `EIP5095.redeem` method.

```yaml
- name: Redeem
  type: event

  inputs:
    - name: from
      indexed: true
      type: address
    - name: to
      indexed: true
      type: address
    - name: amount
      indexed: false
      type: uint256
```

## Rationale

The Principal Token interface is designed to be optimized for integrators with a core minimal interface alongside optional interfaces to enable backwards compatibility. Details such as accounting and management of underlying are intentionally not specified, as Principal Tokens are expected to be treated as black boxes on-chain and inspected off-chain before use.

[EIP-20](/EIPs/EIPS/eip-20) is enforced as implementation details such as token approval and balance calculation directly carry over. This standardization makes Principal Tokens immediately compatible with all [EIP-20](/EIPs/EIPS/eip-20) use cases in addition to EIP-5095.

All principal tokens are redeemable upon maturity, with the only variance being whether further yield is generated post-maturity. Given the ubiquity of redemption, the presence of `redeem` allows integrators to purchase Principal Tokens on an open market, and them later redeem them for a fixed-yield solely knowing the address of the Principal Token itself.

This EIP draws heavily on the design of [EIP-4626](/EIPs/EIPS/eip-4626) because technically Principal Tokens could be described as a subset of Yield Bearing Vaults, extended with a `maturity` variable and restrictions on the implementation. However, extending [EIP-4626](/EIPs/EIPS/eip-4626) would force PT implementations to include methods (namely, `mint` and `deposit`) that are not necessary to the business case that PTs solve. It can also be argued that partial redemptions (implemented via `withdraw`) are rare for PTs.

PTs mature at a precise second, but given the reactive nature of smart contracts, there can&apos;t be an event marking maturity, because there is no guarantee of any activity at or after maturity. Emitting an event to notify of maturity in the first transaction after maturity would be imprecise and expensive. Instead, integrators are recommended to either use the first `Redeem` event, or to track themselves when each PT is expected to have matured.

## Backwards Compatibility

This EIP is fully backward compatible with the [EIP-20](/EIPs/EIPS/eip-20) specification and has no known compatibility issues with other standards.
For production implementations of Principal Tokens which do not use EIP-5095, wrapper adapters can be developed and used, or wrapped tokens can be implemented.

## Reference Implementation

```
// SPDX-License-Identifier: MIT
pragma solidity 0.8.14;

import {ERC20} from &quot;yield-utils-v2/contracts/token/ERC20.sol&quot;;
import {MinimalTransferHelper} from &quot;yield-utils-v2/contracts/token/MinimalTransferHelper.sol&quot;;

contract ERC5095 is ERC20 {
    using MinimalTransferHelper for ERC20;

    /* EVENTS
     *****************************************************************************************************************/

    event Redeem(address indexed from, address indexed to, uint256 underlyingAmount);

    /* MODIFIERS
     *****************************************************************************************************************/

    /// @notice A modifier that ensures the current block timestamp is at or after maturity.
    modifier afterMaturity() virtual {
        require(block.timestamp &gt;= maturity, &quot;BEFORE_MATURITY&quot;);
        _;
    }

    /* IMMUTABLES
     *****************************************************************************************************************/

    ERC20 public immutable underlying;
    uint256 public immutable maturity;

    /* CONSTRUCTOR
     *****************************************************************************************************************/

    constructor(
        string memory name_,
        string memory symbol_,
        uint8 decimals_,
        ERC20 underlying_,
        uint256 maturity_
    ) ERC20(name_, symbol_, decimals_) {
        underlying = underlying_;
        maturity = maturity_;
    }

    /* CORE FUNCTIONS
     *****************************************************************************************************************/

    /// @notice Burns an exact amount of principal tokens in exchange for an amount of underlying.
    /// @dev This reverts if before maturity.
    /// @param principalAmount The exact amount of principal tokens to be burned.
    /// @param from The owner of the principal tokens to be redeemed.  If not msg.sender then must have prior approval.
    /// @param to The address to send the underlying tokens.
    /// @return underlyingAmount The total amount of underlying tokens sent.
    function redeem(
        uint256 principalAmount,
        address from,
        address to
    ) public virtual afterMaturity returns (uint256 underlyingAmount) {
        _decreaseAllowance(from, principalAmount);

        // Check for rounding error since we round down in previewRedeem.
        require((underlyingAmount = _previewRedeem(principalAmount)) != 0, &quot;ZERO_ASSETS&quot;);

        _burn(from, principalAmount);

        emit Redeem(from, to, principalAmount);

        _transferOut(to, underlyingAmount);
    }

    /// @notice Burns a calculated amount of principal tokens in exchange for an exact amount of underlying.
    /// @dev This reverts if before maturity.
    /// @param underlyingAmount The exact amount of underlying tokens to be received.
    /// @param from The owner of the principal tokens to be redeemed.  If not msg.sender then must have prior approval.
    /// @param to The address to send the underlying tokens.
    /// @return principalAmount The total amount of underlying tokens redeemed.
    function withdraw(
        uint256 underlyingAmount,
        address from,
        address to
    ) public virtual afterMaturity returns (uint256 principalAmount) {
        principalAmount = _previewWithdraw(underlyingAmount); // No need to check for rounding error, previewWithdraw rounds up.

        _decreaseAllowance(from, principalAmount);

        _burn(from, principalAmount);

        emit Redeem(from, to, principalAmount);

        _transferOut(to, underlyingAmount);
    }

    /// @notice An internal, overridable transfer function.
    /// @dev Reverts on failed transfer.
    /// @param to The recipient of the transfer.
    /// @param amount The amount of the transfer.
    function _transferOut(address to, uint256 amount) internal virtual {
        underlying.safeTransfer(to, amount);
    }

    /* ACCOUNTING FUNCTIONS
     *****************************************************************************************************************/

    /// @notice Calculates the amount of underlying tokens that would be exchanged for a given amount of principal tokens.
    /// @dev Before maturity, it converts to underlying as if at maturity.
    /// @param principalAmount The amount principal on which to calculate conversion.
    /// @return underlyingAmount The total amount of underlying that would be received for the given principal amount..
    function convertToUnderlying(uint256 principalAmount) external view returns (uint256 underlyingAmount) {
        return _convertToUnderlying(principalAmount);
    }

    function _convertToUnderlying(uint256 principalAmount) internal view virtual returns (uint256 underlyingAmount) {
        return principalAmount;
    }

    /// @notice Converts a given amount of underlying tokens to principal exclusive of fees.
    /// @dev Before maturity, it converts to principal as if at maturity.
    /// @param underlyingAmount The total amount of underlying on which to calculate the conversion.
    /// @return principalAmount The amount principal tokens required to provide the given amount of underlying.
    function convertToPrincipal(uint256 underlyingAmount) external view returns (uint256 principalAmount) {
        return _convertToPrincipal(underlyingAmount);
    }

    function _convertToPrincipal(uint256 underlyingAmount) internal view virtual returns (uint256 principalAmount) {
        return underlyingAmount;
    }

    /// @notice Allows user to simulate redemption of a given amount of principal tokens, inclusive of fees and other
    /// current block conditions.
    /// @dev This reverts if before maturity.
    /// @param principalAmount The amount of principal that would be redeemed.
    /// @return underlyingAmount The amount of underlying that would be received.
    function previewRedeem(uint256 principalAmount) external view afterMaturity returns (uint256 underlyingAmount) {
        return _previewRedeem(principalAmount);
    }

    function _previewRedeem(uint256 principalAmount) internal view virtual returns (uint256 underlyingAmount) {
        return _convertToUnderlying(principalAmount); // should include fees/slippage
    }

    /// @notice Calculates the maximum amount of principal tokens that an owner could redeem.
    /// @dev This returns 0 if before maturity.
    /// @param owner The address for which the redemption is being calculated.
    /// @return maxPrincipalAmount The maximum amount of principal tokens that can be redeemed by the given owner.
    function maxRedeem(address owner) public view returns (uint256 maxPrincipalAmount) {
        return block.timestamp &gt;= maturity ? _balanceOf[owner] : 0;
    }

    /// @notice Allows user to simulate withdraw of a given amount of underlying tokens.
    /// @dev This reverts if before maturity.
    /// @param underlyingAmount The amount of underlying tokens that would be withdrawn.
    /// @return principalAmount The amount of principal tokens that would be redeemed.
    function previewWithdraw(uint256 underlyingAmount) external view afterMaturity returns (uint256 principalAmount) {
        return _previewWithdraw(underlyingAmount);
    }

    function _previewWithdraw(uint256 underlyingAmount) internal view virtual returns (uint256 principalAmount) {
        return _convertToPrincipal(underlyingAmount); // should include fees/slippage
    }

    /// @notice Calculates the maximum amount of underlying tokens that can be withdrawn by a given owner.
    /// @dev This returns 0 if before maturity.
    /// @param owner The address for which the withdraw is being calculated.
    /// @return maxUnderlyingAmount The maximum amount of underlying tokens that can be withdrawn by a given owner.
    function maxWithdraw(address owner) public view returns (uint256 maxUnderlyingAmount) {
        return _previewWithdraw(maxRedeem(owner));
    }
}

```

## Security Considerations

Fully permissionless use cases could fall prey to malicious implementations which only conform to the interface in this EIP but not the specification, failing to implement proper custodial functionality but offering the ability to purchase Principal Tokens through secondary markets.

It is recommended that all integrators review each implementation for potential ways of losing user deposits before integrating.

The `convertToUnderlying` method is an estimate useful for display purposes,
and do _not_ have to confer the _exact_ amount of underlying assets their context suggests.

As is common across many standards, it is strongly recommended to mirror the underlying token&apos;s `decimals` if at all possible, to eliminate possible sources of confusion and simplify integration across front-ends and for other off-chain users.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 01 May 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5095</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5095</guid>
      </item>
    
      <item>
        <title>Soulbound Badge</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5114-soulbound-token/9417</comments>
        
        <description>## Abstract

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


## Specification

```solidity
interface IERC5114 {
	// fired anytime a new instance of this badge is minted
	// this event **MUST NOT** be fired twice for the same `badgeId`
	event Mint(uint256 indexed badgeId, address indexed nftAddress, uint256 indexed nftTokenId);

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

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

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

	// 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;)
	function metadataFormat() external pure returns (string format);
}
```

Implementers of this standard **SHOULD** also depend on a standard for interface detection so callers can easily find out if a given contract implements this interface.


## Rationale

### Immutability

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.

### Content Addressable URIs Required

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.

### No Specification for `badgeUri` Data Format

The format of the data pointed to by `collectionUri()` and `badgeUri(uint256)`, 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 `metadataFormat` 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.


## Backwards Compatibility

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 `[address,id]`).


## Security Considerations

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&apos;t.
For example, the contract could allow transfers via some mechanism and simply not utilize them initially.

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.

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.


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>SY Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5115-super-composable-yield-token-standard/9423</comments>
        
        <description>## Abstract

This standard proposes an API for wrapped yield-bearing tokens within smart contracts. It is an extension on the [ERC-20](/EIPs/EIPS/eip-20) token that provides basic functionality for transferring, depositing, withdrawing tokens, as well as reading balances.

## Motivation

Yield generating mechanisms are built in all shapes and sizes, necessitating a manual integration every time a protocol builds on top of another protocol’s yield generating mechanism. 

[ERC-4626](/EIPs/EIPS/eip-4626) tackled a significant part of this fragmentation by standardizing the interfaces for vaults, a major category among various yield generating mechanisms.

In this ERC, we’re extending the coverage to include assets beyond ERC-4626’s reach, namely:

- yield-bearing assets that have different input tokens used for minting vs accounting for the pool value.
  - This category includes AMM liquidity tokens (which are yield-bearing assets that yield swap fees) since the value of the pool is measured in “liquidity units” (for example, $\sqrt k$ in UniswapV2, as defined in UniswapV2 whitepaper) which can’t be deposited in (as they are not tokens).
  - This extends the flexibility in minting the yield-bearing assets. For example, there could be an ETH vault that wants to allow users to deposit cETH directly instead of ETH, for gas efficiency or UX reasons.
- Assets with reward tokens by default (e.g. COMP rewards for supplying in Compound). The reward tokens are expected to be sold to compound into the same asset.
- This ERC can be extended further to include the handling of rewards, such as the claiming of accrued multiple rewards tokens.

While ERC-4626 is a well-designed and suitable standard for most vaults, there will inevitably be some yield generating mechanisms that do not fit into their category (LP tokens for instance). A more flexible standard is required to standardize the interaction with all types of yield generating mechanisms.

Therefore, we are proposing Standardized Yield (SY), a flexible standard for wrapped yield-bearing tokens that could cover most mechanisms in DeFi. We foresee that:

- ERC-4626 will still be a popular vault standard, that most vaults should adopt.
- SY tokens can wrap over most yield generating mechanisms in DeFi, including ERC-4626 vaults for projects built on top of yield-bearing tokens.
- Whoever needs the functionalities of SY could integrate with the existing SY tokens or write a new SY (to wrap over the target yield-bearing token).
- Reward handling can be extended from the SY token.

### Use Cases

This ERC is designed for flexibility, aiming to accommodate as many yield generating mechanisms as possible. Particularly, this standard aims to be generalized enough that it supports the following use cases and more:

- Money market supply positions
    - Lending DAI in Compound, getting DAI interests and COMP rewards
    - Lending ETH in BenQi, getting ETH interests and QI + AVAX rewards
    - Lending USDC in Aave, getting USDC interests and stkAAVE rewards
- AMM liquidity provision
    - Provide ETH + USDC to ETHUSDC pool in SushiSwap, getting swap fees in more ETH+USDC
    - Provide ETH + USDC to ETHUSDC pool in SushiSwap and stake it in Sushi Onsen, getting swap fees and SUSHI rewards
    - Provide USDC+DAI+USDT to 3crv pool and stake it in Convex, getting 3crv swap fees and CRV + CVX rewards
- Vault positions
    - Provide ETH into Yearn ERC-4626 vault, where the vault accrues yield from Yearn’s ETH strategy
    - Provide DAI into Harvest and staking it, getting DAI interests and FARM rewards
- Liquid staking positions
    - Holding stETH (in Lido), getting yields in more stETH
- Liquidity mining programs
    - Provide USDC in Stargate, getting STG rewards
    - Provide LOOKS in LooksRare, getting LOOKS yield and WETH rewards
- Rebasing tokens
    - Stake OHM into sOHM/gOHM, getting OHM rebase yield

The ERC hopes to minimize, if not possibly eliminate, the use of customized adapters in order to interact with many different forms of yield-bearing token mechanisms.

## Specification

### Generic Yield Generating Pool

We will first introduce Generic Yield Generating Pool (GYGP), a model to describe most yield generating mechanisms in DeFi. In every yield generating mechanism, there is a pool of funds, whose value is measured in **assets**. There are a number of users who contribute liquidity to the pool, in exchange for **shares** of the pool, which represents units of ownership of the pool. Over time, the value (measured in **assets**) of the pool grows, such that each **share** is worth more **assets** over time. The pool could earn a number of **reward tokens** over time, which are distributed to the users according to some logic (for example, proportionally the number of **shares**).

Here are the more concrete definitions of the terms:

#### GYGP Definitions:

- **asset**: Is a unit to measure the value of the pool. At time *t*, the pool has a total value of *TotalAsset(t)* **assets**.
- **shares**: Is a unit that represents ownership of the pool. At time *t*, there are *TotalShares(t)* **shares** in total.
- **reward tokens**: Over time, the pool earns $n_{rewards}$ types of reward tokens $(n_{rewards} \ge 0)$. At time *t*, $TotalRewards_i(t)$ is the amount of **reward token *i*** that has accumulated for the pool up until time *t*.
- **exchange rate**: At time *t*, the **exchange rate** *ExchangeRate(t)* is simply how many **assets** each **shares** is worth $ExchangeRate(t) = \frac{TotalAsset(t)}{TotalShares(t)}$
- **users**: At time *t*, each user *u* has $shares_u(t)$ **shares** in the pool, which is worth $asset_u(t) = shares_u(t) \cdot ExchangeRate(t)$  **assets**. Until time *t*, user *u* is entitled to receive a total of $rewards_{u_i}(t)$ **reward token *i***. The sum of all users’ shares, assets and rewards should be the same as the total shares, assets and rewards of the whole pool.

#### State changes:

1. A user deposits $d_a$ **assets** into the pool at time $t$ ($d_a$ could be negative, which means a withdraw from the pool). $d_s = d_a / ExchangeRate(t)$ new **shares** will be created and given
to user (or removed and burned from the user when $d_a$ is negative).
2. The pool earns $d_a$ (or loses $−d_a$ if $d_a$ is negative) **assets** at time $t$. The **exchange rate** simply increases (or decreases if $d_a$ is negative) due to the additional assets.
3. The pool earns $d_r$ **reward token** $i$. Every user will receive a certain amount of **reward token** $i$.

#### Examples of GYGPs in DeFi:

| Yield generating mechanism | Asset | Shares | Reward tokens | Exchange rate |
| --- | --- | --- | --- | --- |
| Supply USDC in Compound | USDC | cUSDC | COMP | USDC value per cUSDC, increases with USDC supply interests |
| ETH liquid staking in Lido | stETH | wstETH | None | stETH value per wstETH, increases with ETH staking rewards |
| Stake LOOKS in LooksRare Compounder | LOOKS | shares (in contract) | WETH | LOOKS value per shares, increases with LOOKS rewards |
| Stake APE in $APE Compounder | sAPE | shares (in contract) | APE | sAPE value per shares, increases with APE rewards |
| Provide ETH+USDC liquidity on Sushiswap | ETHUSDC liquidity (a pool of x ETH + y USDC has sqrt(xy) ETHUSDC liquidity) | ETHUSDC Sushiswap LP (SLP) token | None | ETHUSDC liquidity value per ETHUSDC SLP, increases due to swap fees |
| Provide ETH+USDC liquidity on Sushiswap and stake into Onsen | ETHUSDC liquidity (a pool of x ETH + y USDC has sqrt(xy) ETHUSDC liquidity) | ETHUSDC Sushiswap LP (SLP) token | SUSHI | ETHUSDC liquidity value per ETHUSDC SLP, increases due to swap fees |
| Provide BAL+WETH liquidity in Balancer (80% BAL, 20% WETH) | BALWETH liquidity (a pool of x BAL + y WETH has x^0.8*y^0.2 BALWETH liquidity) | BALWETH Balancer LP token | None | BALWETH liquidity per BALWETH Balancer LP token, increases due to swap fees |
| Provide USDC+USDT+DAI liquidity in Curve | 3crv pool’s liquidity (amount of D per 3crv token) | 3crv token | CRV | 3crv pool’s liquidity per 3crv token, increases due to swap fees |
| Provide FRAX+USDC liquidity in Curve then stake LP in Convex | BALWETH liquidity (a pool of x BAL + y WETH has x^0.8*y^0.2 BALWETH liquidity) | BALWETH Balancer LP token | None | BALWETH liquidity per BALWETH Balancer LP token, increases due to swap fees |


### Standardized Yield Token Standard

#### Overview:

Standardized Yield (SY) is a token standard for any yield generating mechanism that conforms to the GYGP model. Each SY token represents **shares** in a GYGP and allows for interacting with the GYGP via a standard interface.

All SY tokens:

- **MUST** implement **`ERC-20`** to represent shares in the underlying GYGP.
- **MUST** implement ERC-20’s optional metadata extensions `name`, `symbol`, and `decimals`, which **SHOULD** reflect the underlying GYGP’s accounting asset’s `name`, `symbol`, and `decimals`.
- **MAY** implement [ERC-2612](/EIPs/EIPS/eip-2612) to improve the UX of approving SY tokens on various integrations.
- **MAY** revert on calls to `transfer` and `transferFrom` if a SY token is to be non-transferable.
- The ERC-20 operations `balanceOf`, `transfer`, `totalSupply`, etc. **SHOULD** operate on the GYGP “shares”, which represent a claim to ownership on a fraction of the GYGP’s underlying holdings.

#### SY Definitions:

On top of the definitions above for GYGPs, we need to define 2 more concepts:

- **input tokens**: Are tokens that can be converted into assets to enter the pool. Each SY can accept several possible input tokens $tokens_{in_{i}}$

- **output tokens**: Are tokens that can be redeemed from assets when exiting the pool. Each SY can have several possible output tokens $tokens_{out_{i}}$

#### Interface

```solidity
interface IStandardizedYield {
    event Deposit(
        address indexed caller,
        address indexed receiver,
        address indexed tokenIn,
        uint256 amountDeposited,
        uint256 amountSyOut
    );

    event Redeem(
        address indexed caller,
        address indexed receiver,
        address indexed tokenOut,
        uint256 amountSyToRedeem,
        uint256 amountTokenOut
    );

    function deposit(
        address receiver,
        address tokenIn,
        uint256 amountTokenToDeposit,
        uint256 minSharesOut,
        bool depositFromInternalBalance
    ) external returns (uint256 amountSharesOut);

    function redeem(
        address receiver,
        uint256 amountSharesToRedeem,
        address tokenOut,
        uint256 minTokenOut,
        bool burnFromInternalBalance
    ) external returns (uint256 amountTokenOut);

    function exchangeRate() external view returns (uint256 res);

    function getTokensIn() external view returns (address[] memory res);

    function getTokensOut() external view returns (address[] memory res);

    function yieldToken() external view returns (address);

    function previewDeposit(address tokenIn, uint256 amountTokenToDeposit)
        external
        view
        returns (uint256 amountSharesOut);

    function previewRedeem(address tokenOut, uint256 amountSharesToRedeem)
        external
        view
        returns (uint256 amountTokenOut);

    function name() external view returns (string memory);

    function symbol() external view returns (string memory);

    function decimals() external view returns (uint8);
}
```

#### Methods

```solidity
function deposit(
    address receiver,
    address tokenIn,
    uint256 amountTokenToDeposit,
    uint256 minSharesOut,
    bool depositFromInternalBalance
) external returns (uint256 amountSharesOut);
```

This function will deposit *amountTokenToDeposit* of input token $i$ (*tokenIn*) to mint new SY shares.

If *depositFromInternalBalance* is set to *false*, msg.sender will need to initially deposit *amountTokenToDeposit* of input token $i$ (*tokenIn*) into the SY contract, then this function will convert the *amountTokenToDeposit* of input token $i$ into $d_a$ worth of **asset** and deposit this amount into the pool for the *receiver*, who will receive *amountSharesOut* of SY tokens (**shares**). If *depositFromInternalBalance* is set to *true*, then *amountTokenToDeposit* of input token $i$ (*tokenIn*) will be taken from receiver directly (as msg.sender), and will be converted and shares returned to the receiver similarly to the first case.

This function should revert if $amountSharesOut \lt minSharesOut$.

- **MUST** emit the `Deposit` event.
- **MUST** support ERC-20’s `approve` / `transferFrom` flow where `tokenIn` are taken from receiver directly (as msg.sender) or if the msg.sender has ERC-20 approved allowance over the input token of the receiver.
- **MUST** revert if $amountSharesOut \lt minSharesOut$ (due to deposit limit being reached, slippage, or the user not approving enough `tokenIn` **to the SY contract, etc).
- **MAY** be payable if the `tokenIn` depositing asset is the chain&apos;s native currency (e.g. ETH).

```solidity
function redeem(
    address receiver,
    uint256 amountSharesToRedeem,
    address tokenOut,
    uint256 minTokenOut,
    bool burnFromInternalBalance
) external returns (uint256 amountTokenOut);
```

This function will redeem the $d_s$ shares, which is equivalent to $d_a = d_s \times ExchangeRate(t)$ assets, from the pool. The $d_a$ assets is converted into exactly *amountTokenOut* of output token $i$ (*tokenOut*).

If *burnFromInternalBalance* is set to *false*, the user will need to initially deposit *amountSharesToRedeem* into the SY contract, then this function will burn the floating amount $d_s$ of SY tokens (**shares**) in the SY contract to redeem to output token $i$ (*tokenOut*). This pattern is similar to UniswapV2 which allows for more gas efficient ways to interact with the contract. If *burnFromInternalBalance* is set to *true*, then this function will burn *amountSharesToRedeem* $d_s$ of SY tokens directly from the user to redeem to output token $i$ (*tokenOut*).

This function should revert if $amountTokenOut \lt minTokenOut$.

- **MUST** emit the `Redeem` event.
- **MUST** support ERC-20’s `approve` / `transferFrom` flow where the shares are burned from receiver directly (as msg.sender) or if the msg.sender has ERC-20 approved allowance over the shares of the receiver.
- **MUST** revert if $amountTokenOut \lt minTokenOut$ (due to redeem limit being reached, slippage, or the user not approving enough `amountSharesToRedeem` to the SY contract, etc).

```solidity
function exchangeRate() external view returns (uint256 res);
```

This method updates and returns the latest **exchange rate**, which is the **exchange rate** from SY token amount into asset amount, scaled by a fixed scaling factor of 1e18.

- **MUST** return $ExchangeRate(t_{now})$ such that $ExchangeRate(t_{now}) \times syBalance / 1e18 = assetBalance$.
- **MUST NOT** include fees that are charged against the underlying yield token in the SY contract.

```solidity
function getTokensIn() external view returns (address[] memory res);
```

This read-only method returns the list of all input tokens that can be used to deposit into the SY contract.

- **MUST** return ERC-20 token addresses.
- **MUST** return at least one address.
- **MUST NOT** revert.

```solidity
function getTokensOut() external view returns (address[] memory res);
```

This read-only method returns the list of all output tokens that can be converted into when exiting the SY contract.

- **MUST** return ERC-20 token addresses.
- **MUST** return at least one address.
- **MUST NOT** revert.

```solidity
function yieldToken() external view returns (address);
```

This read-only method returns the underlying yield-bearing token (representing a GYGP) address.

- **MUST** return a token address that conforms to the ERC-20 interface, or zero address
- **MUST NOT** revert.
- **MUST** reflect the exact underlying yield-bearing token address if the SY token is a wrapped token.
- **MAY** return 0x or zero address if the SY token is natively implemented, and not from wrapping.

```solidity
function previewDeposit(address tokenIn, uint256 amountTokenToDeposit)
    external
    view
    returns (uint256 amountSharesOut);
```

This read-only method returns the amount of shares that a user would have received if they deposit *amountTokenToDeposit* of *tokenIn*.

- **MUST** return less than or equal of *amountSharesOut* to the actual return value of the `deposit` method, and **SHOULD NOT** return greater than the actual return value of the `deposit` method.
- **SHOULD ONLY** revert if minting SY token with the entered parameters is forbidden (e.g. exceeding supply cap).

```solidity
function previewRedeem(address tokenOut, uint256 amountSharesToRedeem)
    external
    view
    returns (uint256 amountTokenOut);
```

This read-only method returns the amount of *tokenOut* that a user would have received if they redeem *amountSharesToRedeem* of *tokenOut*.

- **MUST** return less than or equal of *amountTokenOut* to the actual return value of the `redeem` method, and **SHOULD NOT** return greater than the actual return value of the `redeem` method.
- **SHOULD ONLY** revert if burning SY token with the entered parameters is forbidden.

#### Events

```solidity
event Deposit(
    address indexed caller,
    address indexed receiver,
    address indexed tokenIn,
    uint256 amountDeposited,
    uint256 amountSyOut
);
```

`caller` has converted exact *tokenIn* tokens into SY (shares) and transferred those SY to `receiver`.

- **MUST** be emitted when input tokens are deposited into the SY contract via `deposit` method.

```solidity
event Redeem(
    address indexed caller,
    address indexed receiver,
    address indexed tokenOut,
    uint256 amountSyToRedeem,
    uint256 amountTokenOut
);
```

`caller` has converted exact SY (shares) into input tokens and transferred those input tokens to `receiver`.

- **MUST** be emitted when input tokens are redeemed from the SY contract via `redeem` method.

**&quot;SY&quot; Word Choice:**

&quot;SY&quot; (pronunciation: */sʌɪ/*), an abbreviation of Standardized Yield, was found to be appropriate to describe a broad universe of standardized composable yield-bearing digital assets.

## Rationale

[ERC-20](/EIPs/EIPS/eip-20) is enforced because implementation details such as transfer, token approvals, and balance calculation directly carry over to the SY tokens. This standardization makes the SY tokens immediately compatible with all ERC-20 use cases.

[ERC-165](/EIPs/EIPS/eip-165) can optionally be implemented should you want integrations to detect the IStandardizedYield interface implementation.

[ERC-2612](/EIPs/EIPS/eip-2612) can optionally be implemented in order to improve the UX of approving SY tokens on various integrations.

## Backwards Compatibility

This ERC is fully backwards compatible as its implementation extends the functionality of [ERC-20](/EIPs/EIPS/eip-20), however the optional metadata extensions, namely `name`, `decimals`, and `symbol` semantics MUST be implemented for all SY token implementations.

## Security Considerations

Malicious implementations which conform to the interface can put users at risk. It is recommended that all integrators (such as wallets, aggregators, or other smart contract protocols) review the implementation to avoid possible exploits and users losing funds.

`yieldToken` must strongly reflect the address of the underlying wrapped yield-bearing token. For a native implementation wherein the SY token does not wrap a yield-bearing token, but natively represents a GYGP share, then the address returned MAY be a zero address. Otherwise, for wrapped tokens, you may introduce confusion on what the SY token represents, or may be deemed malicious.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 30 May 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5115</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5115</guid>
      </item>
    
      <item>
        <title>SAFE Authentication For ENS</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5131-ens-subdomain-authentication/9458</comments>
        
        <description>## Abstract
This EIP links one or more signing wallets via Ethereum Name Service Specification ([EIP-137](/EIPs/EIPS/eip-137)) to prove control and asset ownership of a main wallet.

## Motivation
Proving ownership of an asset to a third party application in the Ethereum ecosystem is common. Users frequently sign payloads of data to authenticate themselves before gaining access to perform some operation. However, this method--akin to giving the third party root access to one&apos;s main wallet--is both insecure and inconvenient.

***Examples:***
 1. In order for you to edit your profile on OpenSea, you must sign a message with your wallet.
 2. In order to access NFT gated content, you must sign a message with the wallet containing the NFT in order to prove ownership.
 3. In order to gain access to an event, you must sign a message with the wallet containing a required NFT in order to prove ownership.
 4. In order to claim an airdrop, you must interact with the smart contract with the qualifying wallet.
 5. In order to prove ownership of an NFT, you must sign a payload with the wallet that owns that NFT.

In all the above examples, one interacts with the dApp or smart contract using the wallet itself, which may be
 - inconvenient (if it is controlled via a hardware wallet or a multi-sig)
 - insecure (since the above operations are read-only, but you are signing/interacting via a wallet that has write access)

Instead, one should be able to approve multiple wallets to authenticate on behalf of a given wallet.

### Problems with existing methods and solutions
Unfortunately, we&apos;ve seen many cases where users have accidentally signed a malicious payload. The result is almost always a significant loss of assets associated with the signing address.

In addition to this, many users keep significant portions of their assets in &apos;cold storage&apos;. With the increased security from &apos;cold storage&apos; solutions, we usually see decreased accessibility because users naturally increase the barriers required to access these wallets.

Some solutions propose dedicated registry smart contracts to create this link, or new protocols to be supported. This is problematic from an adoption standpoint, and there have not been any standards created for them. 

### Proposal: Use the Ethereum Name Service (EIP-137)
Rather than &apos;re-invent the wheel&apos;, this proposal aims to use the widely adopted Ethereum Name Service in conjunction with the ENS Text Records feature ([EIP-634](/EIPs/EIPS/eip-634)) in order to achieve a safer and more convenient way to sign and authenticate, and provide &apos;read only&apos; access to a main wallet via one or more secondary wallets.

From there, the benefits are twofold. This EIP gives users increased security via outsourcing potentially malicious signing operations to wallets that are more accessible (hot wallets), while being able to maintain the intended security assumptions of wallets that are not frequently used for signing operations.

#### Improving dApp Interaction Security
Many dApps requires one to prove control of a wallet to gain access. At the moment, this means that you must interact with the dApp using the wallet itself. This is a security issue, as malicious dApps or phishing sites can lead to the assets of the wallet being compromised by having them sign malicious payloads.

However, this risk would be mitigated if one were to use a secondary wallet for these interactions. Malicious interactions would be isolated to the assets held in the secondary wallet, which can be set up to contain little to nothing of value.

#### Improving Multiple Device Access Security
In order for a non-hardware wallet to be used on multiple devices, you must import the seed phrase to each device. Each time a seed phrase is entered on a new device, the risk of the wallet being compromised increases as you are increasing the surface area of devices that have knowledge of the seed phrase.

Instead, each device can have its own unique wallet that is an authorized secondary wallet of the main wallet. If a device specific wallet was ever compromised or lost, you could simply remove the authorization to authenticate.

Further, wallet authentication can be chained so that a secondary wallet could itself authorize one or many tertiary wallets, which then have signing rights for both the secondary address as well as the root main address. This, can allow teams to each have their own signer while the main wallet can easily invalidate an entire tree, just by revoking rights from the root stem.

#### Improving Convenience
Many invididuals use hardware wallets for maximum security. However, this is often inconvenient, since many do not want to carry their hardware wallet with them at all times.

Instead, if you approve a non-hardware wallet for authentication activities (such as a mobile device), you would be able to use most dApps without the need to have your hardware wallet on hand.

## Specification
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.

Let:
 - `mainAddress` represent the wallet address we are trying to authenticate or prove asset ownership for.
 - `mainENS` represent the reverse lookup ENS string for `mainAddress`.
 - `authAddress` represent the address we want to use for signing in lieu of `mainAddress`.
 - `authENS` represent the reverse lookup ENS string for `authAddress`.
 - `authKey` represents a string in the format `[0-9A-Za-z]+`.

Control of `mainAddress` and ownership of `mainAddress` assets by `authAddress` is proven if all the following conditions are met:
 - `mainAddress` has an ENS resolver record and a reverse record set to `mainENS`.
 - `authAddress` has an ENS resolver record and a reverse record set to `authENS`.
 - `authENS` has an ENS TEXT record `eip5131:vault` in the format `&lt;authKey&gt;:&lt;mainAddress&gt;`.
 - `mainENS` has an ENS TEXT record `eip5131:&lt;authKey&gt;`.

### Setting up one or many `authAddress` records on a single ENS domain
The `mainAddress` MUST have an ENS resolver record and reverse record configured.
In order to automatically discover the linked account, the `authAddress` SHOULD have an ENS resolver record and reverse record configured.

1. Choose an unused `&lt;authKey&gt;`. This can be any string in the format `[0-0A-Za-z]+`.
2. Set a TEXT record `eip5131:&lt;authKey&gt;` on `mainENS`, with the value set to the desired `authAddress`.
3. Set a TEXT record `eip5131:vault` on `authENS`, with the value set to the `&lt;authKey&gt;:mainAddress`.

Currently this EIP does not enforce an upper-bound on the number of `authAddress` entries you can include. Users can repeat this process with as many address as they like.

### Authenticating `mainAddress` via `authAddress`
Control of `mainAddress` and ownership of `mainAddress` assets is proven if any associated `authAddress` is the `msg.sender` or has signed the message.

Practically, this would work by performing the following operations:
1. Get the resolver for `authENS`
2. Get the `eip5131:vault` TEXT record of `authENS`
3. Parse `&lt;authKey&gt;:&lt;mainAddress&gt;` to determine the `authKey` and `mainAddress`.
4. MUST get the reverse ENS record for `mainAddress` and verify that it matches `&lt;mainENS&gt;`.
    - Otherwise one could set up other ENS nodes (with auths) that point to `mainAddress` and authenticate via those.
5. Get the `eip5131:&lt;authKey&gt;` TEXT record of `mainENS` and ensure it matches `authAddress`.

Note that this specification allows for both contract level and client/server side validation of signatures.  It is not limited to smart contracts, which is why there is no proposed external interface definition.

### Revocation of `authAddress`
To revoke permission of `authAddress`, delete the `eip5131:&lt;authKey&gt;` TEXT record of `mainENS` or update it to point to a new `authAddress`.

## Rationale

### Usage of EIP-137
The proposed specification makes use of EIP-137 rather than introduce another registry paradigm. The reason for this is due to the existing wide adoption of EIP-137 and ENS.

However, the drawback to EIP-137 is that any linked `authAddress` must contain some ETH in order to set the `authENS` reverse record as well as the `eip5131:vault` TEXT record. This can be solved by a separate reverse lookup registry that enables `mainAddress` to set the reverse record and TEXT record with a message signed by `authAddress`.

With the advent of L2s and ENS Layer 2 functionalities, off chain verification of linked addresses is possible even with domains managed across different chains.

### One-to-Many Authentication Relationship
This proposed specification allows for a one (`mainAddress`) to many (`authAddress`) authentication relationship.  i.e. one `mainAddress` can authorize many `authAddress` to authenticate, but an `authAddress` can only authenticate itself or a single `mainAddress`.

The reason for this design choice is to allow for simplicity of authentication via client and smart contract code. You can determine which `mainAddress` the `authAddress` is signing for without any additional user input.

Further, you can design UX without any user interaction necessary to &apos;pick&apos; the interacting address by display assets owned by `authAddress` and `mainAddress` and use the appropriate address dependent on the asset the user is attempting to authenticate with.

## Reference Implementation

### Client/Server Side
In typescript, the validation function, using ethers.js would be as follows:
```
export interface LinkedAddress {
  ens: string,
  address: string,
}

export async function getLinkedAddress(
  provider: ethers.providers.EnsProvider, address: string
): Promise&lt;LinkedAddress | null&gt; {
  const addressENS = await provider.lookupAddress(address);
  if (!addressENS) return null;

  const vaultInfo = await (await provider.getResolver(addressENS))?.getText(&apos;eip5131:vault&apos;);
  if (!vaultInfo) return null;

  const vaultInfoArray = vaultInfo.split(&apos;:&apos;);
  if (vaultInfoArray.length !== 2) {
    throw new Error(&apos;EIP5131: Authkey and vault address not configured correctly.&apos;);
  }

  const [ authKey, vaultAddress ] = vaultInfoArray;

  const vaultENS = await provider.lookupAddress(vaultAddress);
  if (!vaultENS) {
    throw new Error(`EIP5131: No ENS domain with reverse record set for vault.`);
  };

  const expectedSigningAddress = await (
    await provider.getResolver(vaultENS)
  )?.getText(`eip5131:${authKey}`);

  if (expectedSigningAddress?.toLowerCase() !== address.toLowerCase()) {
    throw new Error(`EIP5131: Authentication mismatch.`);
  };

  return {
    ens: vaultENS,
    address: vaultAddress
  };
}
```

### Contract side

#### With a backend
If your application operates a secure backend server, you could run the client/server code above, then use the result in conjunction with specs like [EIP-1271](/EIPs/EIPS/eip-1271) : `Standard Signature Validation Method for Contracts` for a cheap and secure way to validate that the message signer is indeed authenticated for the main address.

#### Without a backend (JavaScript only)
Provided is a reference implementation for an internal function to verify that the message sender has an authentication link to the main address.

```
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/// @author: manifold.xyz

/**
 * ENS Registry Interface
 */
interface ENS {
    function resolver(bytes32 node) external view returns (address);
}

/**
 * ENS Resolver Interface
 */
interface Resolver {
    function addr(bytes32 node) external view returns (address);
    function name(bytes32 node) external view returns (string memory);
    function text(bytes32 node, string calldata key) external view returns (string memory);
}

/**
 * Validate a signing address is associtaed with a linked address
 */
library LinkedAddress {
    /**
     * Validate that the message sender is an authentication address for mainAddress
     *
     * @param ensRegistry    Address of ENS registry
     * @param mainAddress     The main address we want to authenticate for.
     * @param mainENSNodeHash The main ENS Node Hash
     * @param authKey         The TEXT record of the authKey we are using for validation
     * @param authENSNodeHash The auth ENS Node Hash
     */
    function validateSender(
        address ensRegistry,
        address mainAddress,
        bytes32 mainENSNodeHash,
        string calldata authKey,
        bytes32 authENSNodeHash
    ) internal view returns (bool) {
        return validate(ensRegistry, mainAddress, mainENSNodeHash, authKey, msg.sender, authENSNodeHash);
    }

    /**
     * Validate that the authAddress is an authentication address for mainAddress
     *
     * @param ensRegistry     Address of ENS registry
     * @param mainAddress     The main address we want to authenticate for.
     * @param mainENSNodeHash The main ENS Node Hash
     * @param authAddress     The address of the authentication wallet
     * @param authENSNodeHash The auth ENS Node Hash
     */
    function validate(
        address ensRegistry,
        address mainAddress,
        bytes32 mainENSNodeHash,
        string calldata authKey,
        address authAddress,
        bytes32 authENSNodeHash
    ) internal view returns (bool) {
        _verifyMainENS(ensRegistry, mainAddress, mainENSNodeHash, authKey, authAddress);
        _verifyAuthENS(ensRegistry, mainAddress, authKey, authAddress, authENSNodeHash);

        return true;
    }

    // *********************
    //   Helper Functions
    // *********************
    function _verifyMainENS(
        address ensRegistry,
        address mainAddress,
        bytes32 mainENSNodeHash,
        string calldata authKey,
        address authAddress
    ) private view {
        // Check if the ENS nodes resolve correctly to the provided addresses
        address mainResolver = ENS(ensRegistry).resolver(mainENSNodeHash);
        require(mainResolver != address(0), &quot;Main ENS not registered&quot;);
        require(mainAddress == Resolver(mainResolver).addr(mainENSNodeHash), &quot;Main address is wrong&quot;);

        // Verify the authKey TEXT record is set to authAddress by mainENS
        string memory authText = Resolver(mainResolver).text(mainENSNodeHash, string(abi.encodePacked(&quot;eip5131:&quot;, authKey)));
        require(
            keccak256(bytes(authText)) == keccak256(bytes(_addressToString(authAddress))),
            &quot;Invalid auth address&quot;
        );
    }

    function _verifyAuthENS(
        address ensRegistry,
        address mainAddress,
        string memory authKey,
        address authAddress,
        bytes32 authENSNodeHash
    ) private view {
        // Check if the ENS nodes resolve correctly to the provided addresses
        address authResolver = ENS(ensRegistry).resolver(authENSNodeHash);
        require(authResolver != address(0), &quot;Auth ENS not registered&quot;);
        require(authAddress == Resolver(authResolver).addr(authENSNodeHash), &quot;Auth address is wrong&quot;);

        // Verify the TEXT record is appropriately set by authENS
        string memory vaultText = Resolver(authResolver).text(authENSNodeHash, &quot;eip5131:vault&quot;);
        require(
            keccak256(abi.encodePacked(authKey, &quot;:&quot;, _addressToString(mainAddress))) ==
                keccak256(bytes(vaultText)),
            &quot;Invalid auth text record&quot;
        );
    }

    bytes16 private constant _HEX_SYMBOLS = &quot;0123456789abcdef&quot;;

    function sha3HexAddress(address addr) private pure returns (bytes32 ret) {
        uint256 value = uint256(uint160(addr));
        bytes memory buffer = new bytes(40);
        for (uint256 i = 39; i &gt; 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value &amp; 0xf];
            value &gt;&gt;= 4;
        }
        return keccak256(buffer);
    }

    function _addressToString(address addr) private pure returns (string memory ptr) {
        // solhint-disable-next-line no-inline-assembly
        assembly {
            ptr := mload(0x40)

            // Adjust mem ptr and keep 32 byte aligned
            // 32 bytes to store string length; address is 42 bytes long
            mstore(0x40, add(ptr, 96))

            // Store (string length, &apos;0&apos;, &apos;x&apos;) (42, 48, 120)
            // Single write by offsetting across 32 byte boundary
            ptr := add(ptr, 2)
            mstore(ptr, 0x2a3078)

            // Write string backwards
            for {
                // end is at &apos;x&apos;, ptr is at lsb char
                let end := add(ptr, 31)
                ptr := add(ptr, 71)
            } gt(ptr, end) {
                ptr := sub(ptr, 1)
                addr := shr(4, addr)
            } {
                let v := and(addr, 0xf)
                // if &gt; 9, use ascii &apos;a-f&apos; (no conditional required)
                v := add(v, mul(gt(v, 9), 39))
                // Add ascii for &apos;0&apos;
                v := add(v, 48)
                mstore8(ptr, v)
            }

            // return ptr to point to length (32 + 2 for &apos;0x&apos; - 1)
            ptr := sub(ptr, 33)
        }

        return string(ptr);
    }
}
```

## Security Considerations
The core purpose of this EIP is to enhance security and promote a safer way to authenticate wallet control and asset ownership when the main wallet is not needed and assets held by the main wallet do not need to be moved. Consider it a way to do &apos;read only&apos; authentication.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 03 Jun 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5131</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5131</guid>
      </item>
    
      <item>
        <title>Delaying Difficulty Bomb to mid-September 2022</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5133-delaying-difficulty-bomb-to-mid-september-2022/9622</comments>
        
        <description>## Abstract
Starting with `FORK_BLOCK_NUMBER` the client will calculate the difficulty based on a fake block number suggesting to the client that the difficulty bomb is adjusting 11,400,000 blocks later than the actual block number.

## Motivation
To avoid network degradation due to a premature activation of the difficulty bomb.

## Specification
#### Relax Difficulty with Fake Block Number
For the purposes of `calc_difficulty`, simply replace the use of `block.number`, as used in the exponential ice age component, with the formula:
```py
fake_block_number = max(0, block.number - 11_400_000) if block.number &gt;= FORK_BLOCK_NUMBER else block.number
```
## Rationale

The following script predicts the bomb will go off at block 15530314, which is expected to be mined around mid-September.

```python
import math
def predict_bomb_block(current_difficulty, diff_adjust_coeff, block_adjustment):
    &apos;&apos;&apos;
    Predicts the block number at which the difficulty bomb will become noticeable.

    current_difficulty: the current difficulty
    diff_adjust_coeff: intuitively, the percent increase in work that miners have to exert to find a PoW
    block_adjustment: the number of blocks to delay the bomb by
    &apos;&apos;&apos;
    return round(block_adjustment + 100000 * (2 + math.log2(diff_adjust_coeff * current_difficulty // 2048)))

# current_difficulty = 13891609586928851 (Jun 01, 2022)
# diff_adjust_coeff = 0.1 (historically, the bomb is noticeable when the coefficient is &gt;= 0.1)
# block_adjustment = 11400000
print(predict_bomb_block(13891609586928851, 0.1, 11400000))
```

Precise increases in block times are very difficult to predict (especially after the bomb is noticeable).
However, based on past manifestations of the bomb, we can anticipate 0.1s delays by mid-September and 0.6-1.2s delays by early October.

## Backwards Compatibility
No known backward compatibility issues.

## Security Considerations
Misjudging the effects of the difficulty can mean longer blocktimes than anticipated until a hardfork is released. Wild shifts in difficulty can affect this number severely. Also, gradual changes in blocktimes due to longer-term adjustments in difficulty can affect the timing of difficulty bomb epochs. This affects the usability of the network but unlikely to have security ramifications.

In this specific instance, it is possible that the network hashrate drops considerably before The Merge, which could accelerate the timeline by which the bomb is felt in block times. The offset value chosen aims to take this into account.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 01 Jun 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5133</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5133</guid>
      </item>
    
      <item>
        <title>Remote Procedure Call Provider Lists</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5139-remote-procedure-call-provider-lists/9517</comments>
        
        <description>## Abstract
This proposal specifies a JSON schema for describing lists of remote procedure call (RPC) providers for Ethereum-like chains, including their supported [EIP-155](/EIPs/EIPS/eip-155) `CHAIN_ID`.

## Motivation
The recent explosion of alternate chains, scaling solutions, and other mostly Ethereum-compatible ledgers has brought with it many risks for users. It has become commonplace to blindly add new RPC providers using [EIP-3085](/EIPs/EIPS/eip-3085) without evaluating their trustworthiness. At best, these RPC providers may be accurate, but track requests; and at worst, they may provide misleading information and frontrun transactions.

If users instead are provided with a comprehensive provider list built directly by their wallet, with the option of switching to whatever list they so choose, the risk of these malicious providers is mitigated significantly, without sacrificing functionality for advanced users.

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot; and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### List Validation &amp; Schema

List consumers (like wallets) MUST validate lists against the provided schema. List consumers MUST NOT connect to RPC providers present only in an invalid list.

Lists MUST conform to the following JSON Schema:

```json
{
  &quot;$schema&quot;: &quot;https://json-schema.org/draft/2020-12/schema&quot;,

  &quot;title&quot;: &quot;Ethereum RPC Provider List&quot;,
  &quot;description&quot;: &quot;Schema for lists of RPC providers compatible with Ethereum wallets.&quot;,

  &quot;$defs&quot;: {
    &quot;VersionBase&quot;: {
      &quot;type&quot;: &quot;object&quot;,
      &quot;description&quot;: &quot;Version of a list, used to communicate changes.&quot;,

      &quot;required&quot;: [
        &quot;major&quot;,
        &quot;minor&quot;,
        &quot;patch&quot;
      ],

      &quot;properties&quot;: {
        &quot;major&quot;: {
          &quot;type&quot;: &quot;integer&quot;,
          &quot;description&quot;: &quot;Major version of a list. Incremented when providers are removed from the list or when their chain ids change.&quot;,
          &quot;minimum&quot;: 0
        },

        &quot;minor&quot;: {
          &quot;type&quot;: &quot;integer&quot;,
          &quot;description&quot;: &quot;Minor version of a list. Incremented when providers are added to the list.&quot;,
          &quot;minimum&quot;: 0
        },

        &quot;patch&quot;: {
          &quot;type&quot;: &quot;integer&quot;,
          &quot;description&quot;: &quot;Patch version of a list. Incremented for any change not covered by major or minor versions, like bug fixes.&quot;,
          &quot;minimum&quot;: 0
        },

        &quot;preRelease&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;Pre-release version of a list. Indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its major, minor, and patch versions.&quot;,
          &quot;pattern&quot;: &quot;^[1-9A-Za-z][0-9A-Za-z]*(\\.[1-9A-Za-z][0-9A-Za-z]*)*$&quot;
        }
      }
    },

    &quot;Version&quot;: {
      &quot;type&quot;: &quot;object&quot;,
      &quot;additionalProperties&quot;: false,

      &quot;allOf&quot;: [
      {
        &quot;$ref&quot;: &quot;#/$defs/VersionBase&quot;
      }
      ],

      &quot;properties&quot;: {
        &quot;major&quot;: true,
        &quot;minor&quot;: true,
        &quot;patch&quot;: true,
        &quot;preRelease&quot;: true,
        &quot;build&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;Build metadata associated with a list.&quot;,
          &quot;pattern&quot;: &quot;^[0-9A-Za-z-]+(\\.[0-9A-Za-z-])*$&quot;
        }
      }
    },

    &quot;VersionRange&quot;: {
      &quot;type&quot;: &quot;object&quot;,
      &quot;additionalProperties&quot;: false,

      &quot;properties&quot;: {
        &quot;major&quot;: true,
        &quot;minor&quot;: true,
        &quot;patch&quot;: true,
        &quot;preRelease&quot;: true,
        &quot;mode&quot;: true
      },

      &quot;allOf&quot;: [
        {
          &quot;$ref&quot;: &quot;#/$defs/VersionBase&quot;
        }
      ],

      &quot;oneOf&quot;: [
        {
          &quot;properties&quot;: {
            &quot;mode&quot;: {
              &quot;type&quot;: &quot;string&quot;,
              &quot;enum&quot;: [&quot;^&quot;, &quot;=&quot;]
            },
            &quot;preRelease&quot;: false
          }
        },
      {
        &quot;required&quot;: [
          &quot;preRelease&quot;,
          &quot;mode&quot;
        ],

        &quot;properties&quot;: {
          &quot;mode&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;enum&quot;: [&quot;=&quot;]
          }
        }
      }
      ]
    },

    &quot;Logo&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;A URI to a logo; suggest SVG or PNG of size 64x64&quot;,
      &quot;format&quot;: &quot;uri&quot;
    },

    &quot;ProviderChain&quot;: {
      &quot;type&quot;: &quot;object&quot;,
      &quot;description&quot;: &quot;A single chain supported by a provider&quot;,
      &quot;additionalProperties&quot;: false,
      &quot;required&quot;: [
        &quot;chainId&quot;,
        &quot;endpoints&quot;
      ],
      &quot;properties&quot;: {
        &quot;chainId&quot;: {
          &quot;type&quot;: &quot;integer&quot;,
          &quot;description&quot;: &quot;Chain ID of an Ethereum-compatible network&quot;,
          &quot;minimum&quot;: 1
        },
        &quot;endpoints&quot;: {
          &quot;type&quot;: &quot;array&quot;,
          &quot;minItems&quot;: 1,
          &quot;uniqueItems&quot;: true,
          &quot;items&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;format&quot;: &quot;uri&quot;
          }
        }
      }
    },

    &quot;Provider&quot;: {
      &quot;type&quot;: &quot;object&quot;,
      &quot;description&quot;: &quot;Description of an RPC provider.&quot;,
      &quot;additionalProperties&quot;: false,

      &quot;required&quot;: [
        &quot;chains&quot;,
        &quot;name&quot;
      ],

      &quot;properties&quot;: {
        &quot;name&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;Name of the provider.&quot;,
          &quot;minLength&quot;: 1,
          &quot;maxLength&quot;: 40,
          &quot;pattern&quot;: &quot;^[ \\w.&apos;+\\-%/À-ÖØ-öø-ÿ:&amp;\\[\\]\\(\\)]+$&quot;
        },
        &quot;logo&quot;: {
          &quot;$ref&quot;: &quot;#/$defs/Logo&quot;
        },
        &quot;priority&quot;: {
          &quot;type&quot;: &quot;integer&quot;,
          &quot;description&quot;: &quot;Priority of this provider (where zero is the highest priority.)&quot;,
          &quot;minimum&quot;: 0
        },
        &quot;chains&quot;: {
          &quot;type&quot;: &quot;array&quot;,
          &quot;items&quot;: {
            &quot;$ref&quot;: &quot;#/$defs/ProviderChain&quot;
          }
        }
      }
    },

    &quot;Path&quot;: {
      &quot;description&quot;: &quot;A JSON Pointer path.&quot;,
      &quot;type&quot;: &quot;string&quot;
    },

    &quot;Patch&quot;: {
      &quot;items&quot;: {
        &quot;oneOf&quot;: [
          {
            &quot;additionalProperties&quot;: false,
            &quot;required&quot;: [&quot;value&quot;, &quot;op&quot;, &quot;path&quot;],
            &quot;properties&quot;: {
              &quot;path&quot;: {
                &quot;$ref&quot;: &quot;#/$defs/Path&quot;
              },
              &quot;op&quot;: {
                &quot;description&quot;: &quot;The operation to perform.&quot;,
                &quot;type&quot;: &quot;string&quot;,
                &quot;enum&quot;: [&quot;add&quot;, &quot;replace&quot;, &quot;test&quot;]
              },
              &quot;value&quot;: {
                &quot;description&quot;: &quot;The value to add, replace or test.&quot;
              }
            }
          },
          {
            &quot;additionalProperties&quot;: false,
            &quot;required&quot;: [&quot;op&quot;, &quot;path&quot;],
            &quot;properties&quot;: {
              &quot;path&quot;: {
                &quot;$ref&quot;: &quot;#/$defs/Path&quot;
              },
              &quot;op&quot;: {
                &quot;description&quot;: &quot;The operation to perform.&quot;,
                &quot;type&quot;: &quot;string&quot;,
                &quot;enum&quot;: [&quot;remove&quot;]
              }
            }
          },
          {
            &quot;additionalProperties&quot;: false,
            &quot;required&quot;: [&quot;from&quot;, &quot;op&quot;, &quot;path&quot;],
            &quot;properties&quot;: {
              &quot;path&quot;: {
                &quot;$ref&quot;: &quot;#/$defs/Path&quot;
              },

              &quot;op&quot;: {
                &quot;description&quot;: &quot;The operation to perform.&quot;,
                &quot;type&quot;: &quot;string&quot;,
                &quot;enum&quot;: [&quot;move&quot;, &quot;copy&quot;]
              },
              &quot;from&quot;: {
                &quot;$ref&quot;: &quot;#/$defs/Path&quot;,
                &quot;description&quot;: &quot;A JSON Pointer path pointing to the location to move/copy from.&quot;
              }
            }
          }
        ]
      },
      &quot;type&quot;: &quot;array&quot;
    }
  },

  &quot;type&quot;: &quot;object&quot;,
  &quot;additionalProperties&quot;: false,

  &quot;required&quot;: [
    &quot;name&quot;,
    &quot;version&quot;,
    &quot;timestamp&quot;
  ],

  &quot;properties&quot;: {
    &quot;name&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Name of the provider list&quot;,
      &quot;minLength&quot;: 1,
      &quot;maxLength&quot;: 40,
      &quot;pattern&quot;: &quot;^[\\w ]+$&quot;
    },
    &quot;logo&quot;: {
      &quot;$ref&quot;: &quot;#/$defs/Logo&quot;
    },
    &quot;version&quot;: {
      &quot;$ref&quot;: &quot;#/$defs/Version&quot;
    },
    &quot;timestamp&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;format&quot;: &quot;date-time&quot;,
      &quot;description&quot;: &quot;The timestamp of this list version; i.e. when this immutable version of the list was created&quot;
    },
    &quot;extends&quot;: true,
    &quot;changes&quot;: true,
    &quot;providers&quot;: true
  },

  &quot;oneOf&quot;: [
    {
      &quot;type&quot;: &quot;object&quot;,

      &quot;required&quot;: [
        &quot;extends&quot;,
        &quot;changes&quot;
      ],

      &quot;properties&quot;: {
        &quot;providers&quot;: false,

        &quot;extends&quot;: {
          &quot;type&quot;: &quot;object&quot;,
          &quot;additionalProperties&quot;: false,

          &quot;required&quot;: [
            &quot;version&quot;
          ],

          &quot;properties&quot;: {
            &quot;uri&quot;: {
              &quot;type&quot;: &quot;string&quot;,
              &quot;format&quot;: &quot;uri&quot;,
              &quot;description&quot;: &quot;Location of the list to extend, as a URI.&quot;
            },
            &quot;ens&quot;: {
              &quot;type&quot;: &quot;string&quot;,
              &quot;description&quot;: &quot;Location of the list to extend using EIP-1577.&quot;
            },
            &quot;version&quot;: {
              &quot;$ref&quot;: &quot;#/$defs/VersionRange&quot;
            }
          },

          &quot;oneOf&quot;: [
            {
              &quot;properties&quot;: {
                &quot;uri&quot;: false,
                &quot;ens&quot;: true
              }
            },
            {
              &quot;properties&quot;: {
                &quot;ens&quot;: false,
                &quot;uri&quot;: true
              }
            }
          ]
        },
        &quot;changes&quot;: {
          &quot;$ref&quot;: &quot;#/$defs/Patch&quot;
        }
      }
    },
    {
      &quot;type&quot;: &quot;object&quot;,

      &quot;required&quot;: [
        &quot;providers&quot;
      ],

      &quot;properties&quot;: {
        &quot;changes&quot;: false,
        &quot;extends&quot;: false,
        &quot;providers&quot;: {
          &quot;type&quot;: &quot;object&quot;,
          &quot;additionalProperties&quot;: {
            &quot;$ref&quot;: &quot;#/$defs/Provider&quot;
          }
        }
      }
    }
  ]
}
```

For illustrative purposes, the following is an example list following the schema:

```json
{
  &quot;name&quot;: &quot;Example Provider List&quot;,
  &quot;version&quot;: {
    &quot;major&quot;: 0,
    &quot;minor&quot;: 1,
    &quot;patch&quot;: 0,
    &quot;build&quot;: &quot;XPSr.p.I.g.l&quot;
  },
  &quot;timestamp&quot;: &quot;2004-08-08T00:00:00.0Z&quot;,
  &quot;logo&quot;: &quot;https://mylist.invalid/logo.png&quot;,
  &quot;providers&quot;: {
    &quot;some-key&quot;: {
      &quot;name&quot;: &quot;Frustrata&quot;,
      &quot;chains&quot;: [
        {
          &quot;chainId&quot;: 1,
          &quot;endpoints&quot;: [
            &quot;https://mainnet1.frustrata.invalid/&quot;,
            &quot;https://mainnet2.frustrana.invalid/&quot;
          ]
        },
        {
          &quot;chainId&quot;: 3,
          &quot;endpoints&quot;: [
            &quot;https://ropsten.frustrana.invalid/&quot;
          ]
        }
      ]
    },
    &quot;other-key&quot;: {
      &quot;name&quot;: &quot;Sourceri&quot;,
      &quot;priority&quot;: 3,
      &quot;chains&quot;: [
        {
          &quot;chainId&quot;: 1,
          &quot;endpoints&quot;: [
            &quot;https://mainnet.sourceri.invalid/&quot;
          ]
        },
        {
          &quot;chainId&quot;: 42,
          &quot;endpoints&quot;: [
            &quot;https://kovan.sourceri.invalid&quot;
          ]
        }
      ]
    }
  }
}
```

### Versioning

List versioning MUST follow the [Semantic Versioning 2.0.0](/EIPs/assets/eip-5139/semver) (SemVer) specification.

The major version MUST be incremented for the following modifications:

 - Removing a provider.
 - Changing a provider&apos;s key in the `providers` object.
 - Removing the last `ProviderChain` for a chain id.

The major version MAY be incremented for other modifications, as permitted by SemVer.

If the major version is not incremented, the minor version MUST be incremented if any of the following modifications are made:

 - Adding a provider.
 - Adding the first `ProviderChain` of a chain id.

The minor version MAY be incremented for other modifications, as permitted by SemVer.

If the major and minor versions are unchanged, the patch version MUST be incremented for any change.

### Publishing

Provider lists SHOULD be published to an Ethereum Name Service (ENS) name using [EIP-1577](/EIPs/EIPS/eip-1577)&apos;s `contenthash` mechanism on mainnet.

Provider lists MAY instead be published using HTTPS. Provider lists published in this way MUST allow reasonable access from other origins (generally by setting the header `Access-Control-Allow-Origin: *`.)

### Priority

Provider entries MAY contain a `priority` field. A `priority` value of zero SHALL indicate the highest priority, with increasing `priority` values indicating decreasing priority. Multiple providers MAY be assigned the same priority. All providers without a `priority` field SHALL have equal priority. Providers without a `priority` field SHALL always have a lower priority than any provider with a `priority` field.

List consumers MAY use `priority` fields to choose when to connect to a provider, but MAY ignore it entirely. List consumers SHOULD explain to users how their implementation interprets `priority`.

### List Subtypes

Provider lists are subdivided into two categories: root lists, and extension lists. A root list contains a list of providers, while an extension list contains a set of modifications to apply to another list.

#### Root Lists

A root list has a top-level `providers` key.

#### Extension Lists

An extension list has top-level `extends` and `changes` keys.

##### Specifying a Parent (`extends`)

The `uri` and `ens` fields SHALL point to a source for the parent list.

If present, the `uri` field MUST use a scheme specified in [Publishing](#publishing).

If present, the `ens` field MUST specify an ENS name to be resolved using EIP-1577.

The `version` field SHALL specify a range of compatible versions. List consumers MUST reject extension lists specifying an incompatible parent version.

In the event of an incompatible version, list consumers MAY continue to use a previously saved parent list, but list consumers choosing to do so MUST display a prominent warning that the provider list is out of date.

###### Default Mode

If the `mode` field is omitted, a parent version SHALL be compatible if and only if the parent&apos;s version number matches the left-most non-zero portion in the major, minor, patch grouping.

For example:

```javascript
{
  &quot;major&quot;: &quot;1&quot;,
  &quot;minor&quot;: &quot;2&quot;,
  &quot;patch&quot;: &quot;3&quot;
}
```

Is equivalent to:

```
&gt;=1.2.3, &lt;2.0.0
```

And:

```javascript
{
  &quot;major&quot;: &quot;0&quot;,
  &quot;minor&quot;: &quot;2&quot;,
  &quot;patch&quot;: &quot;3&quot;
}
```

Is equivalent to:

```
&gt;=0.2.3, &lt;0.3.0
```

###### Caret Mode (`^`)

The `^` mode SHALL behave exactly as the default mode above.

###### Exact Mode (`=`)

In `=` mode, a parent version SHALL be compatible if and only if the parent&apos;s version number exactly matches the specified version.

##### Specifying Changes (`changes`)

The `changes` field SHALL be a JavaScript Object Notation (JSON) Patch document as specified in RFC 6902.

JSON pointers within the `changes` field MUST be resolved relative to the `providers` field of the parent list. For example, see the following lists for a correctly formatted extension.

###### Root List

```json
TODO
```

###### Extension List

```json
TODO
```

##### Applying Extension Lists

List consumers MUST follow this algorithm to apply extension lists:

 1. Is the current list an extension list?
    * Yes:
       1. Ensure that this `from` has not been seen before.
       1. Retrieve the parent list.
       1. Verify that the parent list is valid according to the JSON schema.
       1. Ensure that the parent list is version compatible.
       1. Set the current list to the parent list and go to step 1.
    * No:
       1. Go to step 2.
 1. Copy the current list into a variable `$output`.
 1. Does the current list have a child:
    * Yes:
       1. Apply the child&apos;s `changes` to `providers` in `$output`.
       1. Verify that `$output` is valid according to the JSON schema.
       1. Set the current list to the child.
       1. Go to step 3.
    * No:
       1. Replace the current list&apos;s `providers` with `providers` from `$output`.
       1. The current list is now the resolved list; return it.


List consumers SHOULD limit the number of extension lists to a reasonable number.

## Rationale

This specification has two layers (provider, then chain id) instead of a flatter structure so that wallets can choose to query multiple independent providers for the same query and compare the results.

Each provider may specify multiple endpoints to implement load balancing or redundancy.

List version identifiers conform to SemVer to roughly communicate the kinds of changes that each new version brings. If a new version adds functionality (eg. a new chain id), then users can expect the minor version to be incremented. Similarly, if the major version is not incremented, list subscribers can assume dapps that work in the current version will continue to work in the next one.

## Security Considerations

Ultimately it is up to the end user to decide on what list to subscribe to. Most users will not change from the default list maintained by their wallet. Since wallets already have access to private keys, giving them additional control over RPC providers seems like a small increase in risk.

While list maintainers may be incentivized (possibly financially) to include or exclude particular providers, actually doing so may jeopardize the legitimacy of their lists. This standard facilitates swapping lists, so if such manipulation is revealed, users are free to swap to a new list with little effort.

If the list chosen by the user is published using EIP-1577, the list consumer has to have access to ENS in some way. This creates a paradox: how do you query Ethereum without an RPC provider? This paradox creates an attack vector: whatever method the list consumer uses to fetch the list can track the user, and even more seriously, **can lie about the contents of the list**.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 06 Jun 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5139</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5139</guid>
      </item>
    
      <item>
        <title>Slippage Protection for Tokenized Vault</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5143-slippage-protection-for-tokenized-vaults/9554</comments>
        
        <description>## Abstract

The following standard extends the [EIP-4626](/EIPs/EIPS/eip-4626) Tokenized Vault standard with functions dedicated to the safe interaction between EOAs and the vault when price is subject to slippage.

## Motivation

[EIP-4626](/EIPs/EIPS/eip-4626) security considerations section states that:
&gt; &quot;If implementors intend to support EOA account access directly, they should consider adding an additional function call for deposit/mint/withdraw/redeem with the means to accommodate slippage loss or unexpected deposit/withdrawal limits, since they have no other means to revert the transaction if the exact output amount is not achieved.&quot;

Yet, EIP-4626 does not standardize the corresponding function signatures and behaviors. For improved interroperability, and better support by wallets, it is essential that this optional functions are also standardized.

## Specification

This ERC is an extension of EIP-4626. Any contract implementing it MUST also implement EIP-4626.

### Methods

#### deposit

Overloaded version of ERC-4626&apos;s `deposit`.

Mints `shares` Vault shares to `receiver` by depositing exactly `assets` of underlying tokens.

MUST emit the `Deposit` event.

MUST support [EIP-20](/EIPs/EIPS/eip-20) `approve` / `transferFrom` on `asset` as a deposit flow.
MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the `deposit` execution, and are accounted for during `deposit`.

MUST revert if all of `assets` cannot be deposited (due to deposit limit being reached, slippage, the user not approving enough underlying tokens to the Vault contract, etc).
MUST revert if depositing `assets` underlying asset mints less then `minShares` shares.

Note that most implementations will require pre-approval of the Vault with the Vault&apos;s underlying `asset` token.

```yaml
- name: deposit
  type: function
  stateMutability: nonpayable

  inputs:
    - name: assets
      type: uint256
    - name: receiver
      type: address
    - name: minShares
      type: uint256

  outputs:
    - name: shares
      type: uint256
```

#### mint

Overloaded version of ERC-4626&apos;s `mint`.

Mints exactly `shares` Vault shares to `receiver` by depositing `assets` of underlying tokens.

MUST emit the `Deposit` event.

MUST support ERC-20 `approve` / `transferFrom` on `asset` as a mint flow.
MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the `mint` execution, and are accounted for during `mint`.

MUST revert if all of `shares` cannot be minted (due to deposit limit being reached, slippage, the user not approving enough underlying tokens to the Vault contract, etc).
MUST revert if minting `shares` shares cost more then `maxAssets` underlying tokens.

Note that most implementations will require pre-approval of the Vault with the Vault&apos;s underlying `asset` token.

```yaml
- name: mint
  type: function
  stateMutability: nonpayable

  inputs:
    - name: shares
      type: uint256
    - name: receiver
      type: address
    - name: maxAssets
      type: uint256

  outputs:
    - name: assets
      type: uint256
```

#### withdraw

Overloaded version of ERC-4626&apos;s `withdraw`.

Burns `shares` from `owner` and sends exactly `assets` of underlying tokens to `receiver`.

MUST emit the `Withdraw` event.

MUST support a withdraw flow where the shares are burned from `owner` directly where `owner` is `msg.sender` or `msg.sender` has ERC-20 approval over the shares of `owner`.
MAY support an additional flow in which the shares are transferred to the Vault contract before the `withdraw` execution, and are accounted for during `withdraw`.

MUST revert if all of `assets` cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner not having enough shares, etc).
MUST revert if withdrawing `assets` underlying tokens requires burning more then `maxShares` shares.

Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed. Those methods should be performed separately.

```yaml
- name: withdraw
  type: function
  stateMutability: nonpayable

  inputs:
    - name: assets
      type: uint256
    - name: receiver
      type: address
    - name: owner
      type: address
    - name: maxShares
      type: uint256

  outputs:
    - name: shares
      type: uint256
```

#### redeem

Overloaded version of ERC-4626&apos;s `redeem`.

Burns exactly `shares` from `owner` and sends `assets` of underlying tokens to `receiver`.

MUST emit the `Withdraw` event.

MUST support a redeem flow where the shares are burned from `owner` directly where `owner` is `msg.sender` or `msg.sender` has ERC-20 approval over the shares of `owner`.
MAY support an additional flow in which the shares are transferred to the Vault contract before the `redeem` execution, and are accounted for during `redeem`.

MUST revert if all of `shares` cannot be redeemed (due to withdrawal limit being reached, slippage, the owner not having enough shares, etc).
MUST revert if redeeming `shares` shares sends less than `minAssets` underlying tokens to `receiver`.

Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed. Those methods should be performed separately.

```yaml
- name: redeem
  type: function
  stateMutability: nonpayable

  inputs:
    - name: shares
      type: uint256
    - name: receiver
      type: address
    - name: owner
      type: address
    - name: minAssets
      type: uint256

  outputs:
    - name: assets
      type: uint256
```

## Rationale

This ERC&apos;s functions do not replace ERC-4626 equivalent mechanisms. They are additional (overloaded) methods designed to protect EOAs interacting with the vault.

When smart contracts interact with an ERC-4626 vault, they can preview any operation using the dedicated functions before executing the operation. This can be done
atomically, with no risk of price change. This is not true of EOA, which will preview their operations on a UI, sign a transaction, and have it mined later.
Between the preview and the transaction being executed, the blockchain state might change, resulting in unexpected outcomes. In particular, frontrunning
make EOA&apos;s interractons with an ERC-4626 vault possibly risky.

Other projects in the DeFi spaces, such as decentralized exchanges, already include similar mechanisms so a user can request its transaction reverts if the
resulting exchange rate is not considered good enough.

Implementing This ERC on top of an ERC-4626 contract can be done very easily. It just requires calling the corresponding ERC-4626 function and adding a revert
check on the returned value.

### Alternative approaches

This ERC aims at solving the security concerns (describes in the motivation section) at the vault level. For completeness, we have to mention that these issues can also be addressed using a generic ERC-4626 router, similar to how Uniswap V2 &amp; V3 use a router to provide good user workflows on top of the Uniswap pairs. The router approach is possibly more versatile and leaves more room for evolutions (the router can be replaced at any point) but it also leads to more expensive operations because the router needs to take temporary custody of the tokens going into the vault.

## Reference Implementation

Given an existing ERC-4626 implementation

``` solidity
contract ERC5143 is ERC4626 {
    function deposit(uint256 assets, address receiver, uint256 minShares) public virtual returns (uint256) {
        uint256 shares = deposit(assets, receiver);
        require(shares &gt;= minShares, &quot;ERC5143: deposit slippage protection&quot;);
        return shares;
    }
    function mint(uint256 shares, address receiver, uint256 maxAssets) public virtual returns (uint256) {
        uint256 assets = mint(shares, receiver);
        require(assets &lt;= maxAssets, &quot;ERC5143: mint slippage protection&quot;);
        return assets;
    }
    function withdraw(uint256 assets, address receiver, address owner, uint256 maxShares) public virtual returns (uint256) {
        uint256 shares = withdraw(assets, receiver, owner);
        require(shares &lt;= maxShares, &quot;ERC5143: withdraw slippage protection&quot;);
        return shares;
    }
    function redeem(uint256 shares, address receiver, address owner, uint256 minAssets) public virtual returns (uint256) {
        uint256 assets = redeem(shares, receiver, owner);
        require(assets &gt;= minAssets, &quot;ERC5143: redeem slippage protection&quot;);
        return assets;
    }
}
```
## Security Considerations

This ERC addresses one of the security consideration raised by ERC-4626. Other considerations still apply.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 09 Jun 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5143</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5143</guid>
      </item>
    
      <item>
        <title>Cross-Chain Execution</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5164-cross-chain-execution/9658</comments>
        
        <description>## Abstract

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.

The specification defines two components: the &quot;Message Dispatcher&quot; and the &quot;Message Executor&quot;. 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.

## Motivation

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.

## Specification

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.

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:

- `MessageDispatcher`
- `MessageExecutor`

The `MessageDispatcher` lives on the origin chain and dispatches messages to the `MessageExecutor` for execution. The `MessageExecutor` lives on the destination chain and executes dispatched messages.

### MessageDispatcher

The `MessageDispatcher` lives on the chain from which messages are sent. The Dispatcher&apos;s job is to broadcast messages through a transport layer to one or more `MessageExecutor` contracts.

A unique `messageId` 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 `chainId, dispatcherAddress, messageNonce` where messageNonce is a monotonically increasing integer per message.

#### MessageDispatcher Methods

**dispatchMessage**

Will dispatch a message to be executed by the `MessageExecutor` on the destination chain specified by `toChainId`.

`MessageDispatcher`s MUST emit the `MessageDispatched` event when a message is dispatched.

`MessageDispatcher`s MUST revert if `toChainId` is not supported.

`MessageDispatcher`s MUST forward the message to a `MessageExecutor` on the `toChainId`.

`MessageDispatcher`s MUST use a unique `messageId` for each message.

`MessageDispatcher`s MUST return the `messageId` to allow the message sender to track the message.

`MessageDispatcher`s MAY require payment.

```solidity
interface MessageDispatcher {
  function dispatchMessage(uint256 toChainId, address to, bytes calldata data) external payable returns (bytes32 messageId);
}
```

```yaml
- name: dispatchMessage
  type: function
  stateMutability: payable
  inputs:
    - name: toChainId
      type: uint256
    - name: to
      type: address
    - name: data
      type: bytes
  outputs:
    - name: messageId
      type: bytes32
```

#### MessageDispatcher Events

**MessageDispatched**

The `MessageDispatched` event MUST be emitted by the `MessageDispatcher` when an individual message is dispatched.

```solidity
interface MessageDispatcher {
  event MessageDispatched(
    bytes32 indexed messageId,
    address indexed from,
    uint256 indexed toChainId,
    address to,
    bytes data,
  );
}
```

```yaml
- name: MessageDispatched
  type: event
  inputs:
    - name: messageId
      indexed: true
      type: bytes32
    - name: from
      indexed: true
      type: address
    - name: toChainId
      indexed: true
      type: uint256
    - name: to
      type: address
    - name: data
      type: bytes
```

### MessageExecutor

The `MessageExecutor` executes dispatched messages and message batches. Developers must implement a `MessageExecutor` in order to execute messages on the receiving chain.

The `MessageExecutor` 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.

#### Execution

`MessageExecutor`s SHOULD verify all message data with the bridge transport layer.

`MessageExecutor`s MUST NOT successfully execute a message more than once.

`MessageExecutor`s MUST revert the transaction when a message fails to be executed allowing the message to be retried at a later time.

**Calldata**

`MessageExecutor`s MUST append the ABI-packed (`messageId`, `fromChainId`, `from`) 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.

```solidity
to.call(abi.encodePacked(data, messageId, fromChainId, from));
```

```yaml
- name: calldata
  type: bytes
  inputs:
    - name: data
      type: bytes
    - name: messageId
      type: bytes32
    - name: fromChainId
      type: uint256
    - name: from
      type: address
```

#### MessageExecutor Events

**MessageIdExecuted**

`MessageIdExecuted` MUST be emitted once a message or message batch has been executed.

```solidity
interface MessageExecutor {
  event MessageIdExecuted(
    uint256 indexed fromChainId,
    bytes32 indexed messageId
  );
}
```

```yaml
- name: MessageIdExecuted
  type: event
  inputs:
    - name: fromChainId
      indexed: true
      type: uint256
    - name: messageId
      indexed: true
      type: bytes32
```

#### MessageExecutor Errors

**MessageAlreadyExecuted**

`MessageExecutor`s MUST revert if a messageId has already been executed and SHOULD emit a `MessageIdAlreadyExecuted` custom error.

```solidity
interface MessageExecutor {
  error MessageIdAlreadyExecuted(
    bytes32 messageId
  );
}
```

**MessageFailure**

`MessageExecutor`s MUST revert if an individual message fails and SHOULD emit a `MessageFailure` custom error.

```solidity
interface MessageExecutor {
  error MessageFailure(
    bytes32 messageId,
    bytes errorData
  );
}
```

## Rationale

The `MessageDispatcher` can be coupled to one or more `MessageExecutor`. It is up to bridges to decide how to couple the two. Users can easily bridge a message by calling `dispatchMessage` without being aware of the `MessageExecutor` address. Messages can also be traced by a client using the data logged by the `MessageIdExecuted` event.

Some bridges may require payment in the native currency, so the `dispatchMessage` function is payable.

## Backwards Compatibility

This specification is compatible with existing governance systems as it offers simple cross-chain execution.

## Security Considerations

Bridge trust profiles are variable, so users must understand that bridge security depends on the implementation.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Client Script URI for Token Contracts</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5169-client-script-uri-for-token-contracts/9674</comments>
        
        <description>## Abstract

This EIP provides a contract interface adding a `scriptURI()` function for locating executable scripts associated with the token.

## Motivation

Often, smart contract authors want to provide some user functionality to their tokens through client scripts. The idea is made popular with function-rich NFTs. It&apos;s important that a token&apos;s contract is linked to its client script, since the client script may carry out trusted tasks such as creating transactions for the user.

This EIP allows users to be sure they are using the correct script through the contract by providing a URI to an official script, made available with a call to the token contract itself (`scriptURI`). This URI can be any RFC 3986-compliant URI, such as a link to an IPFS multihash, GitHub gist, or a cloud storage provider. Each contract implementing this EIP  implements a `scriptURI` function which returns the download URI to a client script. The script provides a client-side executable to the hosting token. Examples of such a script could be:

- A &apos;miniDapp&apos;, which is a cut-down DApp tailored for a single token.
- A &apos;TokenScript&apos; which provides TIPS from a browser wallet.
- A &apos;TokenScript&apos; that allows users to interact with contract functions not normally provided by a wallet, eg &apos;mint&apos; function.
- An extension that is downloadable to the hardware wallet with an extension framework, such as Ledger.
- JavaScript instructions to operate a smartlock, after owner receives authorization token in their wallet.

### Overview

With the discussion above in mind, we outline the solution proposed by this EIP. For this purpose, we consider the following variables:

- `SCPrivKey`: The private signing key to administrate a smart contract implementing this EIP. Note that this doesn&apos;t have to be a new key especially added for this EIP. Most smart contracts made today already have an administration key to manage the tokens issued. It can be used to update the `scriptURI`.

- `newScriptURI`: an array of URIs for different ways to find the client script.

We can describe the life cycle of the `scriptURI` functionality:

- Issuance

1. The token issuer issues the tokens and a smart contract implementing this EIP, with the admin key for the smart contract being `SCPrivKey`.
2. The token issuer calls `setScriptURI` with the `scriptURI`.

- Update `scriptURI`

1. The token issuer stores the desired `script` at all the new URI locations and constructs a new `scriptURI` structure based on this. 
2. The token issuer calls `setScriptURI` with the new `scriptURI` structure.

## Specification

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.

We define a scriptURI element using the `string[]`.
Based on this, we define the smart contract interface below:

```solidity
interface IERC5169 {
    /// @dev This event emits when the scriptURI is updated, 
    /// so wallets implementing this interface can update a cached script
    event ScriptUpdate(string[] newScriptURI);

    /// @notice Get the scriptURI for the contract
    /// @return The scriptURI
    function scriptURI() external view returns(string[] memory);

    /// @notice Update the scriptURI 
    /// emits event ScriptUpdate(scriptURI memory newScriptURI);
    function setScriptURI(string[] memory newScriptURI) external;
}
```

The interface MUST be implemented under the following constraints:

- The smart contract implementing `IERC5169` MUST store variables `address owner` in its state.

- The smart contract implementing `IERC5169` MUST set `owner=msg.sender` in its constructor.

- The `ScriptUpdate(...)` event MUST be emitted when the ```setScriptURI``` function updates the `scriptURI`.

- The `setScriptURI(...)` function MUST validate that `owner == msg.sender` *before* executing its logic and updating any state.

- The `setScriptURI(...)` function MUST update its internal state such that `currentScriptURI = newScriptURI`.

- The `scriptURI()` function MUST return the `currentScriptURI` state.

- The `scriptURI()` function MAY be implemented as pure or view.

- Any user of the script learned from `scriptURI` MUST validate the script is either at an immutable location, its URI contains its hash digest, or it implements the separate `Authenticity for Client Script` EIP, which asserts authenticity using signatures instead of a digest.

## Rationale

This method avoids the need for building secure and certified centralized hosting and allows scripts to be hosted anywhere: IPFS, GitHub or cloud storage.

## Backwards Compatibility

This standard is backwards-compatible with most existing token standards, including the following commonly-used ones:

- [ERC-20](/EIPs/EIPS/eip-20)
- [ERC-721](/EIPs/EIPS/eip-721)
- [ERC-777](/EIPs/EIPS/eip-777)
- [ERC-1155](/EIPs/EIPS/eip-1155)

## Test Cases

### Test Contract

```solidity

import &quot;@openzeppelin/contracts/access/Ownable.sol&quot;;
import &quot;./IERC5169.sol&quot;;
contract ERC5169 is IERC5169, Ownable {
    string[] private _scriptURI;
    function scriptURI() external view override returns(string[] memory) {
        return _scriptURI;
    }

    function setScriptURI(string[] memory newScriptURI) external onlyOwner override {
        _scriptURI = newScriptURI;

        emit ScriptUpdate(newScriptURI);
    }
}

```

### Test Cases

```ts

const { expect } = require(&apos;chai&apos;);
const { BigNumber, Wallet } = require(&apos;ethers&apos;);
const { ethers, network, getChainId } = require(&apos;hardhat&apos;);

describe(&apos;ERC5169&apos;, function () {
  before(async function () {
    this.ERC5169 = await ethers.getContractFactory(&apos;ERC5169&apos;);
  });

  beforeEach(async function () {
    // targetNFT
    this.erc5169 = await this.ERC5169.deploy();
  });

  it(&apos;Should set script URI&apos;, async function () {
    const scriptURI = [
      &apos;uri1&apos;, &apos;uri2&apos;, &apos;uri3&apos;
    ];

    await expect(this.erc5169.setScriptURI(scriptURI))
      .emit(this.erc5169, &apos;ScriptUpdate&apos;)
      .withArgs(scriptURI);
    
    const currentScriptURI = await this.erc5169.scriptURI();

    expect(currentScriptURI.toString()).to.be.equal(scriptURI.toString());
  });
  
```

## Reference Implementation

An intuitive implementation is the STL office door token. This NFT is minted and transferred to STL employees. The TokenScript attached to the token contract via the `scriptURI()` function contains instructions on how to operate the door interface. This takes the form of:

1. Query for challenge string (random message from IoT interface eg &apos;Apples-5E3FA1&apos;).

2. Receive and display challenge string on Token View, and request &apos;Sign Personal&apos;.

3. On obtaining the signature of the challenge string, send back to IoT device.

4. IoT device will unlock door if ec-recovered address holds the NFT.

With `scriptURI()` the experience is greatly enhanced as the flow for the user is:

1. Receive NFT.

2. Use authenticated NFT functionality in the wallet immediately.

The project with contract, TokenScript and IoT firmware is in use by Smart Token Labs office door and numerous other installations. An example implementation contract: [ERC-5169 Contract Example](/EIPs/assets/eip-5169/contract/ExampleContract.sol) and TokenScript:  [ERC-5169 TokenScript Example](/EIPs/assets/eip-5169/tokenscript/ExampleScript.xml). Links to the firmware and full sample can be found in the associated discussion linked in the header.
The associated TokenScript can be read from the contract using `scriptURI()`.

### Script location

While the most straightforward solution to facilitate specific script usage associated with NFTs, is clearly to store such a script on the smart contract. However, this has several disadvantages: 

1. The smart contract signing key is needed to make updates, causing the key to become more exposed, as it is used more often. 

2. Updates require smart contract interaction. If frequent updates are needed, smart contract calls can become an expensive hurdle.

3. Storage fee. If the script is large, updates to the script will be costly. A client script is typically much larger than a smart contract.

For these reasons, storing volatile data, such as token enhancing functionality, on an external resource makes sense. Such an external resource can be either be  hosted centrally, such as through a cloud provider, or privately hosted through a private server, or decentralized hosted, such as the interplanetary filesystem.

While centralized storage for a decentralized functionality goes against the ethos of web3, fully decentralized solutions may come with speed, price or space penalties. This EIP handles this by allowing the function `ScriptURI` to return multiple URIs, which could be a mix of centralized, individually hosted and decentralized locations.

While this EIP does not dictate the format of the stored script, the script itself could contain pointers to multiple other scripts and data sources, allowing for advanced ways to expand token scripts, such as lazy loading. 
The handling of integrity of such secondary data sources is left dependent on the format of the script.

## Security Considerations

**When a server is involved**

When the client script does not purely rely on connection to a blockchain node, but also calls server APIs,  the trustworthiness of the server API is called into question. This EIP does not provide any mechanism to assert the authenticity of the API access point. Instead, as long as the client script is trusted, it&apos;s assumed that it can call any server API in order to carry out token functions. This means the client script can mistrust a server API access point.

**When the scriptURI doesn&apos;t contain integrity (hash) information**

We separately authored `Authenticity for Client Script` EIP to guide on how to use digital signatures efficiently and concisely to ensure authenticity and integrity of scripts not stored at a URI which is a digest of the script itself. 

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 03 May 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5169</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5169</guid>
      </item>
    
      <item>
        <title>NFT Future Rewards (nFR)</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/non-fungible-future-rewards-token-standard/9203</comments>
        
        <description>## Abstract

This proposal introduces the Non-Fungible Future Rewards (nFR) framework, extending [ERC-721](/EIPs/EIPS/eip-721) tokens (NFTs) features to let token holders benefit from value appreciation after transferring ownership. By integrating cooperative game theory, it aligns stakeholder incentives, addressing inefficiencies in asset transactions. The framework fosters collaboration, transparency, and equitable profit sharing. It improves equity and efficiency, recognizes all ownership stages, and establishes a cooperative asset transaction model.

## Motivation

Traditional financial markets are often characterized by inefficiencies, opaque practices, and systemic imbalances, resulting in significant disadvantages for the majority of participants. Although blockchain technology offers transaction transparency, current implementations do not adequately facilitate equitable value sharing or participant alignment. This proposal addresses these gaps by introducing structured collaboration and a fair compensation system, ensuring equitable rewards for contributions to asset value.

### Framework Components

#### The Flow mechanism

Each [ERC-5173](/EIPs/EIPS/eip-5173) token maintains an immutable record of ownership and price transitions, creating a dedicated network of historical token owners. This unique community collaborates to generate additional value and maintains vested interest in the project or token even after selling, ensuring contributors benefit from the asset&apos;s appreciation. This mechanism promotes collaborative value creation, equitable profit sharing, and a connected financial ecosystem, distinct from traditional financial market systems.

#### Cooperative Value (Future Rewards) Distribution 

The nFR framework transforms the zero-sum financial equation:

```
P(A) + P(B) + F ≤ 0
```
Where:

- P(A): Profit of trader A
- P(B): Profit of trader B
- F: Transaction fees, friction costs, and operational expenses

into a collaborative model:

```
P(A) + P(B) + F + FR &gt; 0
```
Where:

- FR: Shared value creation through cooperative mechanisms

This model incentivizes fairness and rewards contributions throughout the asset lifecycle.

## Specification

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.

The following is an extension of the [ERC-721](/EIPs/EIPS/eip-721) standard.

[ERC-721](/EIPs/EIPS/eip-721)-compliant contracts MAY implement this EIP for rewards to provide a standard method of rewarding future buyers and previous owners with realized profits in the future.

Implementers of this standard MUST have all of the following functions:

```solidity

pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/utils/introspection/IERC165.sol&quot;;

/*
 *
 * @dev Interface for the Future Rewards Token Standard.
 *
 * A standardized way to receive future rewards for non-fungible tokens (NFTs.)
 *
 */
interface IERC5173 is IERC165 {

    event FRClaimed(address indexed account, uint256 indexed amount);

    event FRDistributed(uint256 indexed tokenId, uint256 indexed soldPrice, uint256 indexed allocatedFR);

    event Listed(uint256 indexed tokenId, uint256 indexed salePrice);

    event Unlisted(uint256 indexed tokenId);

    event Bought(uint256 indexed tokenId, uint256 indexed salePrice);

    function list(uint256 tokenId, uint256 salePrice) external;

    function unlist(uint256 tokenId) external;

    function buy(uint256 tokenId) payable external;

    function releaseFR(address payable account) external;

    function retrieveFRInfo(uint256 tokenId) external returns(uint8, uint256, uint256, uint256, uint256, address[] memory);

    function retrieveAllottedFR(address account) external returns(uint256);

    function retrieveListInfo(uint256 tokenId) external returns(uint256, address, bool);
    
}

```

An nFR contract MUST implement and update for each Token ID. The data in the `FRInfo` struct MAY either be stored wholly in a single mapping, or MAY be broken down into several mappings. The struct MUST either be exposed in a public mapping or mappings, or MUST have public functions that access the private data. This is for client-side data fetching and verification.

```solidity

struct FRInfo {
        uint8 numGenerations; //  Number of generations corresponding to that Token ID
        uint256 percentOfProfit; // Percent of profit allocated for FR, scaled by 1e18
        uint256 successiveRatio; // The common ratio of successive in the geometric sequence, used for distribution calculation
        uint256 lastSoldPrice; // Last sale price in ETH mantissa
        uint256 ownerAmount; // Amount of owners the Token ID has seen
        address[] addressesInFR; // The addresses currently in the FR cycle
}

struct ListInfo {
        uint256 salePrice; // ETH mantissa of the listed selling price
        address lister; // Owner/Lister of the Token
        bool isListed; // Boolean indicating whether the Token is listed or not
}

```
 
Additionally, an nFR smart contract MUST store the corresponding `ListInfo` for each Token ID in a mapping. A method to retrieve a Token ID’s corresponding `ListInfo` MUST also be accessible publicly.

An nFR smart contract MUST also store and update the amount of Ether allocated to a specific address using the `_allotedFR` mapping. The `_allottedFR` mapping MUST either be public or have a function to fetch the FR payment allotted to a specific address.

### Percent Fixed Point

The `allocatedFR` MUST be calculated using a percentage fixed point with a scaling factor of 1e18 (X/1e18) - such as &quot;5e16&quot; - for 5%. This is REQUIRED to maintain uniformity across the standard. The max and min values would be - 1e18 - 1.

### Default FR Info

A default `FRInfo` MUST be stored in order to be backward compatible with [ERC-721](/EIPs/EIPS/eip-721) mint functions. It MAY also have a function to update the `FRInfo`, assuming it has not been hard-coded.

### ERC-721 Overrides

An nFR-compliant smart contract MUST override the [ERC-721](/EIPs/EIPS/eip-721) `_mint`, `_transfer`, and `_burn` functions. When overriding the `_mint` function, a default FR model is REQUIRED to be established if the mint is to succeed when calling the [ERC-721](/EIPs/EIPS/eip-721) `_mint` function and not the nFR `_mint` function. It is also to update the owner amount and directly add the recipient address to the FR cycle. When overriding the `_transfer` function, the smart contract SHALL consider the NFT as sold for 0 ETH, and update the state accordingly after a successful transfer. This is to prevent FR circumvention. Additionally, the `_transfer` function SHALL prevent the caller from transferring the token to themselves or an address that is already in the FR sliding window, this can be done through a require statement that ensures that the sender or an address in the FR sliding window is not the recipient, otherwise, it’d be possible to fill up the FR sequence with one’s own address or duplicate addresses. Finally, when overriding the `_burn` function, the smart contract SHALL delete the `FRInfo` and `ListInfo` corresponding to that Token ID after a successful burn.

Additionally, the [ERC-721](/EIPs/EIPS/eip-721) `_checkOnERC721Received` function MAY be explicitly called after mints and transfers if the smart contract aims to have safe transfers and mints.

### Safe Transfers

If the wallet/broker/auction application will accept safe transfers, then it MUST implement the [ERC-721](/EIPs/EIPS/eip-721) wallet interface.

### Listing, Unlisting, and Buying

The `list`, `unlist`, and `buy` functions MUST be implemented, as they provide the capability to sell a token.

```solidity
function list(uint256 tokenId, uint256 salePrice) public virtual override {
   //...
}


function unlist(uint256 tokenId) public virtual override {
   //...
}

function buy(uint256 tokenId) public virtual override payable {
   //...
}

```

The `list` function accepts a `tokenId` and a `salePrice` and updates the corresponding `ListInfo` for that given `tokenId` after ensuring that the `msg.sender` is either approved or the owner of the token. The `list` function SHOULD emit the `Listed` event. The function signifies that the token is listed and at what price it is listed for. 

The `unlist` function accepts a `tokenId` and it deletes the corresponding `ListInfo` after the owner verifications have been met. The `unlist` function SHOULD emit the `Unlisted` event.

The `buy` function accepts a `tokenId` and MUST be payable. It MUST verify that the `msg.value` matches the token’s `salePrice` and that the token is listed, before proceeding and calling the FR `_transferFrom` function. The function MUST also verify that the buyer is not already in the FR sliding window. This is to ensure the values are valid and will also allow for the necessary FR to be held in the contract. The `buy` function SHOULD emit the `Bought` event.


### Future Rewards `_transferFrom` Function

The FR `_transferFrom` function MUST be called by all nFR-supporting smart contracts, though the accommodations for non-nFR-supporting contracts MAY also be implemented to ensure backwards compatibility.

```solidity

function transferFrom(address from, address to, uint256 tokenId, uint256 soldPrice) public virtual override payable {
       //...
}

```

Based on the stored `lastSoldPrice`, the smart contract will determine whether the sale was profitable after calling the [ERC-721](/EIPs/EIPS/eip-721) transfer function and transferring the NFT. If it was not profitable, the smart contract SHALL update the last sold price for the corresponding Token ID, increment the owner amount, shift the generations, and transfer all of the `msg.value` to the `lister` depending on the implementation. Otherwise, if the transaction was profitable, the smart contract SHALL call the `_distributeFR` function, then update the `lastSoldPrice`, increment the owner amount, and finally shift generations. The `_distributeFR` function or the FR `_transferFrom` MUST return the difference between the allocated FR that is to be distributed amongst the `_addressesInFR` and the `msg.value` to the `lister`. Once the operations have completed, the function MUST clear the corresponding `ListInfo`. Similarly to the `_transfer` override, the FR `_transferFrom` SHALL ensure that the recipient is not the sender of the token or an address in the FR sliding window.

### Future Rewards Calculation

Marketplaces that support this standard MAY implement various methods of calculating or transferring Future Rewards to the previous owners.

```solidity

function _calculateFR(uint256 totalProfit, uint256 buyerReward, uint256 successiveRatio, uint256 ownerAmount, uint256 windowSize) pure internal virtual returns(uint256[] memory) {
    //...        
}

```

In this example (*Figure 1*), a seller is REQUIRED to share a portion of their net profit with 10 previous holders of the token. Future Rewards will also be paid to the same seller as the value of the token increases from up to 10 subsequent owners. 

When an owner loses money during their holding period, they MUST NOT be obligated to share Future Rewards distributions, since there is no profit to share. However, he SHALL still receive a share of Future Rewards distributions from future generations of owners, if they are profitable.

![Figure 1: Geometric sequence distribution](/EIPs/assets/eip-5173/Total_FR_Payout_Distribution-geo.png) 

*Figure 1: Geometric sequence distribution*

The buyers/owners receive a portion ( r ) of the realized profit  (P ) from an NFT transaction. The remaining proceeds go to the seller.

As a result of defining a sliding window mechanism ( n ), we can determine which previous owners will receive distributions. The owners are arranged in a queue, starting with the earliest owner and ending with the owner immediately before the current owner (the Last Generation). The First Generation is the last of the next n generations. There is a fixed-size profit distribution window from the First Generation to the Last Generation. 

The profit distribution SHALL be only available to previous owners who fall within the window. 

In this example, there SHALL be a portion of the proceeds awarded to the Last Generation owner (the owner immediately prior to the current seller) based on the geometric sequence in which profits are distributed. The larger portion of the proceeds SHALL go to the Mid-Gen owners, the earlier the greater, until the last eligible owner is determined by the sliding window, the First Generation. Owners who purchase earlier SHALL receive a greater reward, with first-generation owners receiving the greatest reward.

### Future Rewards Distribution

![Figure 2: NFT Owners&apos; Future Rewards (nFR)](/EIPs/assets/eip-5173/nFR_Standard_Outline.jpeg) 

*Figure 2: NFT Owners&apos; Future Rewards (nFR)*

*Figure 2* illustrates an example of a five-generation Future Rewards Distribution program based on an owner&apos;s realized profit.

```solidity

function _distributeFR(uint256 tokenId, uint256 soldPrice) internal virtual {
       //...

        emit FRDistributed(tokenId, soldPrice, allocatedFR);
 }
 
```

The `_distributeFR` function MUST be called in the FR `_transferFrom` function if there is a profitable sale. The function SHALL determine the addresses eligible for FR, which would essentially be, excluding the last address in `addressesInFR` in order to prevent any address from paying itself. If the function determines there are no addresses eligible, i.e., it is the first sale, then it SHALL either `return 0` if `_transferFrom` is handling FR payment or send `msg.value` to the `lister`. The function SHALL calculate the difference between the current sale price and the `lastSoldPrice`, then it SHALL call the `_calculateFR` function to receive the proper distribution of FR. Then it SHALL distribute the FR accordingly, making order adjustments as necessary. Then, the contract SHALL calculate the total amount of FR that was distributed (`allocatedFR`), in order to return the difference of the `soldPrice` and `allocatedFR` to the `lister`. Finally, it SHALL emit the `FRDistributed` event. Additionally, the function MAY return the allocated FR, which would be received by the FR `_transferFrom` function, if the `_transferFrom` function is sending the `allocatedFR` to the `lister`.

### Future Rewards Claiming

The future Rewards payments SHOULD utilize a pull-payment model, similar to that demonstrated by OpenZeppelin with their PaymentSplitter contract. The event  FRClaimed would be triggered after a successful claim has been made. 

```solidity

function releaseFR(address payable account) public virtual override {
        //...
}

```

### Owner Generation Shifting

The `_shiftGenerations` function MUST be called regardless of whether the sale was profitable or not. As a result, it will be called in the `_transfer` [ERC-721](/EIPs/EIPS/eip-721) override function and the FR `transferFrom` function. The function SHALL remove the oldest account from the corresponding `_addressesInFR` array. This calculation will take into account the current length of the array versus the total number of generations for a given token ID.

## Rationale

### Fixed Percentage to 10^18

Considering Fixed-Point Arithmetic is to be enforced, it is logical to have 1e18 represent 100% and 1e16 represent 1% for Fixed-Point operations. This method of handling percents is also commonly seen in many Solidity libraries for Fixed-Point operations.

### Emitting Event for Payment

Since each NFT contract is independent, and while a marketplace contract can emit events when an item is sold, choosing to emit an event for payment is important. As the royalty and FR recipient may not be aware of/watching for a secondary sale of their NFT, they would never know that they received a payment except that their ETH wallet has been increased randomly. 

The recipient of the secondary sale will therefore be able to verify that the payment has been received by calling the parent contract of the NFT being sold, as implemented in [ERC-2981](/EIPs/EIPS/eip-2981).

### Number of Generations of All Owners ( n ) vs Number of Generations of Only Profitable Owners

It is the number of generations of all owners, not just those who are profitable, that determines the number of owners from which the subsequent owners&apos; profits will be shared, see *Figure 3*. As part of the effort to discourage &quot;ownership hoarding,&quot; Future Rewards distributions will not be made to the current owner/purchaser if all the owners lose money holding the NFT. Further information can be found under Security Considerations.

![Figure 3: Losing owners](/EIPs/assets/eip-5173/Losing_owners.jpeg)

*Figure 3: Losing owners*

### Single vs Multigenerations

In a single generation reward, the new buyer/owner receives a share of the next single generation&apos;s realized profit only. In a multigenerational reward system, buyers will have future rewards years after their purchase. The NFT should have a long-term growth potential and a substantial dividend payout would be possible in this case. 

We propose that the marketplace operator can choose between a single generational distribution system and a multigenerational distribution system.

### Direct FR Payout by the Seller vs Smart Contract-managed Payout

FR payouts directly derived from the sale proceeds are immediate and final. As part of the fraud detection detailed later in the Security Considerations section, we selected a method in which the smart contract calculates all the FR amounts for each generation of previous owners, and handles payout according to other criteria set by the marketplace, such as reduced or delayed payments for wallet addresses with low scores, or a series of consecutive orders detected using a time-heuristic analysis. 

### Equal vs Linear Reward Distributions

#### Equal FR Payout

![Figure 4: Equal, linear reward distribution](../assets/eip-5173/Total_FR_Payout_Distribution-flat.png?raw=true)

*Figure 4: Equal, linear reward distribution*

FR distributions from the realization of profits by later owners are distributed equally to all eligible owners (*Figure 4*). The exponential reward curve, however, may be more desirable, as it gives a slightly larger share to the newest buyer. Additionally, this distribution gives the earliest generations the largest portions as their FR distributions near the end, so they receive higher rewards for their early involvement, but the distribution is not nearly as extreme as one based on arithmetic sequences (*Figure 5*). 

This system does not discriminate against any buyer because each buyer will go through the same distribution curve.

#### Straight line arithmetic sequence FR payout

![Figure 5: Arithmetic sequence distribution](../assets/eip-5173/Arithmetic_Sequence_FR_Payout_Distribution.png?raw=true)

*Figure 5: Arithmetic sequence distribution*

The profit is distributed according to the arithmetic sequence, which is 1, 2, 3, ... and so on. The first owner will receive 1 portion, the second owner will receive 2 portions, the third owner will receive 3 portions, etc. 

## Backwards Compatibility

This proposal is fully compatible with current [ERC-721](/EIPs/EIPS/eip-721) standards and [ERC-2981](/EIPs/EIPS/eip-2981). It can also be easily adapted to work with [ERC-1155](/EIPs/EIPS/eip-1155).

## Test Cases

[This contract](/EIPs/assets/eip-5173/Implementation/nFRImplementation.sol) contains the reference implementation for this proposal.

[Here is a visualization of the test case](../assets/eip-5173/animate-1920x1080-1750-frames.gif?raw=true). 

As a result of implementing ERC-5173, a new project has been launched called untrading.org.

## Reference Implementation

This implementation uses OpenZeppelin contracts and the PRB Math library created by Paul R Berg for fixed-point arithmetic. It demonstrates the interface for the nFR standard, an nFR standard-compliant extension, and an [ERC-721](/EIPs/EIPS/eip-721) implementation using the extension.

The code for the reference implementation is [here](/EIPs/assets/eip-5173/Implementation/nFRImplementation.sol).

### Distribution of NFT Royalties to Artists and Creators

We agree that artists’ royalties should be uniform and on-chain. We support [ERC-2981](/EIPs/EIPS/eip-2981) NFT royalty Standard proposal.

All platforms can support royalty rewards for the same NFT based on on-chain parameters and functions:

- No profit, no profit sharing, no cost;
- The question of &quot;who owned it&quot; is often crucial to the provenance and value of a collectible;
- The previous owner should be re-compensated for their ownership;
- And the buyer/owner incentive in FR eliminates any motive to circumvent the royalty payout schemes;

### Distribution of NFT Owners’ Future Rewards (FRs)

#### Future Rewards calculation

Any realized profits (P) when an NFT is sold are distributed among the buyers/owners. The previous owners will take a fixed portion of the profit (P), and this portion is called Future Rewards (FRs). The seller takes the rest of the profits.

We define a sliding window mechanism to decide which previous owners will be involved in the profit distribution. Let&apos;s imagine the owners as a queue starting from the first hand owner to the current owner. The profit distribution window starts from the previous owner immediately to the current owner and extends towards the first owner, and the size of the windows is fixed. Only previous owners located inside the window will join the profit distribution.  

![Future Rewards calculation formula](../assets/eip-5173/nFR_distribution_formula.jpg?raw=true)

In this equation:

- P is the total profit, the difference between the selling price minus the buying price;
- _R_ is buyer reward ratio of the total P;
- _g_ is the common ratio of successive in the geometric sequence;
- _n_ is the actual number of owners eligible and participating in the future rewards sharing. To calculate _n_, we have _n_ = min(_m_, _w_), where _m_ is the current number of owners for a token, and _w_ is the window size of the profit distribution sliding window algorithm

#### Converting into Code

```solidity

pragma solidity ^0.8.0;
//...

/* Assumes usage of a Fixed Point Arithmetic library (prb-math) for both int256 and uint256, and OpenZeppelin Math utils for Math.min. */
function _calculateFR(uint256 p, uint256 r, uint256 g, uint256 m, uint256 w) pure internal virtual returns(uint256[] memory) {
        uint256 n = Math.min(m, w);
        uint256[] memory FR = new uint256[](n);

        for (uint256 i = 1; i &lt; n + 1; i++) {
            uint256 pi = 0;

            if (successiveRatio != 1e18) {
                int256 v1 = 1e18 - int256(g).powu(n);
                int256 v2 = int256(g).powu(i - 1);
                int256 v3 = int256(p).mul(int256(r));
                int256 v4 = v3.mul(1e18 - int256(g));
                pi = uint256(v4 * v2 / v1);
            } else {
                pi = p.mul(r).div(n);
            }

            FR[i - 1] = pi;
        }

        return FR;
}

```

The complete implementation code can be found [here](/EIPs/assets/eip-5173/Implementation/nFRImplementation.sol).

## Security Considerations

### Payment Attacks

As this ERC introduces royalty and realized profit rewards collection, distribution, and payouts to the ERC-721 standard, the attack vectors increase. As discussed by Andreas Freund regarding mitigations to phishing attacks, we recommend reentrancy protection for all payment functions to reduce the most significant attack vectors for payments and payouts.

### Royalty Circumventing

Many methods are being used to avoid paying royalties to creators under the current [ERC-721](/EIPs/EIPS/eip-721) standard. Through an under-the-table transaction, the new buyer&apos;s cost basis will be reduced to zero, increasing their FR liability to the full selling price. Everyone, either the buyer or seller, would pay a portion of the previous owner&apos;s net realized profits ( P x r ). Acting in his or her own interests, the buyer rejects any loyalty circumventing proposal.

### FR Hoarding through Wash Sales

Quantexa blog and beincrypto articles have reported widespread wash trading on all unregulated cryptocurrency trading platforms and NFT marketplaces. The use of wash trading by dishonest actors can lead to an unfair advantage, as well as inflated prices and money laundering. When a single entity becomes multiple generations of owners to accumulate more rewards in the future, the validity of the system is undermined.

#### Wash trading by users

Using a different wallet address, an attacker can &quot;sell&quot; the NFT to themselves at a loss. It is possible to repeat this process n times in order to maximize their share of the subsequent FR distributions (*Figure 6*). A wallet ranking score can partially alleviate this problem. It is evident that a brand new wallet is a red flag, and the marketplace may withhold FR distribution from it if it has a short transaction history (i.e. fewer than a certain number of transactions).

We do not want a large portion of future rewards to go to a small number of wash traders. Making such practices less profitable is one way to discourage wash trading and award hoarding. It can be partially mitigated, for example, by implementing a wallet-score and holding period-based incentive system. The rewards for both parties are reduced if a new wallet is used or if a holding period is less than a certain period. 

![Figure 6: Same owner using different wallets](/EIPs/assets/eip-5173/Same_owner_using_different_wallets.jpeg)

*Figure 6: Same owner using different wallets*

#### Wash trading by the marketplace operator

However, the biggest offender appears to be the marketplace, which engages heavily in wash trading, or simply does not care about it, according to Decrypt. The authors have personally experienced this phenomenon. A senior executive of a top-5 cryptocurrency exchange boasted during a mid-night drinking session in 2018, that they had &quot;brushed&quot; (wash-traded) certain newly listed tokens, which they called &quot;marketmaking.&quot; The exchange is still ranked among the top five crypto exchanges today.

Many of these companies engage in wash trading on their own or collude with certain users, and royalties and FR payments are reimbursed under the table. It is crucial that all exchanges have robust features to prevent self-trading. Users should be able to observe watchers transparently. Marketplaces should provide their customers with free access to an on-chain transaction monitoring service like Chainalysis Reactor.

### Long/Cyclical FR-Entitled Owner Generations

In most cases, malicious actors will create excessively long or cyclical Future Rewards Owner Generations that will result in applications that attempt to distribute FR or shift generations running out of gas and not functioning. Therefore, clients are responsible for verifying that the contract with which they interact has an appropriate number of generations, so that looping over will not deplete the gas.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 08 May 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5173</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5173</guid>
      </item>
    
      <item>
        <title>NFT Updatable Metadata Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-721-erc-1155-updatable-metadata-extension/9077</comments>
        
        <description>## Abstract

This specification defines a standard way to allow controlled NFTs&apos; metadata updates along predefined formulas. Updates of the original metadata are restricted and defined by a set of recipes and the sequence and results of these recipes are deterministic and fully verifiable with on-chain metadata updates event. The proposal depends on and extends the [EIP-721](/EIPs/EIPS/eip-721) and [EIP-1155](/EIPs/EIPS/eip-1155).

## Motivation

Storing voluminous NFT metadata on-chain is often neither practical nor cost-efficient.

Storing NFT metadata off-chain on distributed file systems like IPFS can answer some needs of verifiable correlation and permanence between an NFT tokenId and its metadata but updates come at the cost of being all or nothing (aka changing the `tokenURI`). Bespoke solutions can be easily developed for a specific NFT smart contract but a common specification is necessary for NFT marketplaces and third parties tools to understand and verify these metadata updates.

This ERC allows the original JSON metadata to be modified step by step along a set of predefined JSON transformation formulas. Depending on NFT use-cases, the transformation formulas can be more or less restrictive. 

As examples, an NFT representing a house could only allow append-only updates to the list of successive owners, and a game using NFT characters could let some attributes change from time to time (e.g. health, experience, level, etc) while some other would be guaranteed to never change (e.g. physicals traits etc).

This standard extension is compatible with NFTs bridged between Ethereum and L2 networks and allows efficient caching solutions.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot; and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

The **metadata updates extension** is OPTIONAL for [EIP-721](/EIPs/EIPS/eip-721) and [EIP-1155](/EIPs/EIPS/eip-1155) contracts.

```solidity
/// @title ERC-721/ERC-1155 Updatable Metadata Extension
interface IERC5185UpdatableMetadata {
    /// @notice A distinct Uniform Resource Identifier (URI) for a set of updates
    /// @dev This event emits an URI (defined in RFC 3986) of a set of metadata updates.
    /// The URI should point to a JSON file that conforms to the &quot;NFT Metadata Updates JSON Schema&quot;
    /// Third-party platforms such as NFT marketplace can deterministically calculate the latest
    /// metadata for all tokens using these events by applying them in sequence for each token.
    event MetadataUpdates(string URI);
}
```

The original metadata SHOULD conform to the &quot;ERC-5185 Updatable Metadata JSON Schema&quot; which is a compatible extension of the &quot;ERC-721 Metadata JSON Schema&quot; defined in ERC-721.

&quot;ERC-5185 Updatable Metadata JSON Schema&quot; :

```json
{
    &quot;title&quot;: &quot;Asset Updatable Metadata&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;name&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Identifies the asset to which this NFT represents&quot;
        },
        &quot;description&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Describes the asset to which this NFT represents&quot;
        },
        &quot;image&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive.&quot;
        },
        &quot;updatable&quot;: {
            &quot;type&quot;: &quot;object&quot;,
            &quot;required&quot;: [&quot;engine&quot;, &quot;recipes&quot;],
            &quot;properties&quot;: {
                &quot;engine&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;Non ambiguous transformation method/language (with version) to process updates along recipes defined below&quot;
                },
                &quot;schema&quot;: {
                    &quot;type&quot;: &quot;object&quot;,
                    &quot;description&quot;: &quot;if present, a JSON Schema that all sequential post transformation updated metadata need to conform. If a transformed JSON does not conform, the update should be considered voided.&quot;
                },
                &quot;recipes&quot;: {
                    &quot;type&quot;: &quot;object&quot;,
                    &quot;description&quot;: &quot;A catalog of all possibles recipes identified by their keys&quot;,
                    &quot;patternProperties&quot;: {
                        &quot;.*&quot;: {
                            &quot;type&quot;: &quot;object&quot;,
                            &quot;description&quot;: &quot;The key of this object is used to select which recipe to apply for each update&quot;,
                            &quot;required&quot;: [&quot;eval&quot;],
                            &quot;properties&quot;: {
                                &quot;eval&quot;: {
                                    &quot;type&quot;: &quot;string&quot;,
                                    &quot;description&quot;: &quot;The evaluation formula to transform the last JSON metadata using the engine above (can take arguments)&quot;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```

&quot;NFT Metadata Updates JSON Schema&quot; : 

```json
{
    &quot;title&quot;: &quot;Metadata Updates JSON Schema&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;updates&quot;: {
            &quot;type&quot;: &quot;array&quot;,
            &quot;description&quot;: &quot;A list of updates to apply sequentially to calculate updated metadata&quot;,
            &quot;items&quot;: { &quot;$ref&quot;: &quot;#/$defs/update&quot; },
            &quot;$defs&quot;: {
                &quot;update&quot;: {
                    &quot;type&quot;: &quot;object&quot;,
                    &quot;required&quot;: [&quot;tokenId&quot;, &quot;recipeKey&quot;],
                    &quot;properties&quot;: {
                        &quot;tokenId&quot;: {
                            &quot;type&quot;: &quot;string&quot;,
                            &quot;description&quot;: &quot;The tokenId for which the update recipe should apply&quot;
                         },
                        &quot;recipeKey&quot;: {
                            &quot;type&quot;: &quot;string&quot;,
                            &quot;description&quot;: &quot;recipeKey to use to get the JSON transformation expression in current metadata&quot;
                        },
                        &quot;args&quot;: {
                            &quot;type&quot;: &quot;string&quot;,
                            &quot;description&quot;: &quot;arguments to pass to the JSON transformation&quot;
                        }
                    }
                 }
            }
        }
    }
}
```

### Engines

Only one engine is currently defined in this extension proposal.

If the engine in the original metadata is &quot;jsonata@1.8.*&quot;, updated metadata is calculated starting from original metadata and applying each update sequentially (all updates which are present in all the URIs emitted by the event `MetadataUpdates` for which tokenId matches).

For each step, the next metadata is obtained by the javascript calculation (or compatible jsonata implementation in other language) :

```js
const nextMetadata = jsonata(evalString).evaluate(previousMetadata, args)
```

With `evalString` is found with `recipeKey` in the original metadata recipes list.

If the key is not present in the original metadata list, `previousMetadata` is kept as the valid updated metadata.

If the evaluation throws any errors, `previousMetadata` is kept as the valid updated metadata.

If a validation Schema JSON has been defined and the result JSON `nextMetadata` does not conform, that update is not valid and `previousMetadata` is kept as the valid updated metadata.

## Rationale

There have been numerous interesting uses of [EIP-721](/EIPs/EIPS/eip-721) and [EIP-1155](/EIPs/EIPS/eip-1155) smart contracts that associate for each token essential and significant metadata. While some projects (e.g. EtherOrcs) have experimented successfully to manage these metadata on-chain, that experimental solution will always be limited by the cost and speed of generating and storing JSON on-chain. Symmetrically, while storing the JSON metadata at URI endpoint controlled by traditional servers permit limitless updates the metadata for each NFT, it is somehow defeating in many uses cases, the whole purpose of using a trustless blockchain to manage NFT: indeed users may want or demand more permanence and immutability from the metadata associated with their NFT.

Most use cases have chosen intermediate solutions like IPFS or arweave to provide some permanence or partial/full immutability of metadata. This is a good solution when an NFT represents a static asset whose characteristics are by nature permanent and immutable (like in the art world) but less so with other use cases like gaming or NFT representing a deed or title. Distinguishable assets in a game often should be allowed to evolve and change over time in a controlled way and titles need to record real life changes.

The advantages of this standard is precisely to allow these types of controlled transformations over time of each NFT metadata by applying sequential transformations starting with the original metadata and using formulas themselves defined in the original metadata.

The original metadata for a given NFT is always defined as the JSON pointed by the result of `tokenURI` for [EIP-721](/EIPs/EIPS/eip-721) and function `uri` for [EIP-1155](/EIPs/EIPS/eip-1155).

The on-chain log trace of updates guarantee that anyone can recalculate and verify independently the current updated metadata starting from the original metadata. The fact that the calculation is deterministic allows easy caching of intermediate transformations and the efficient processing of new updates using these caches.

The number of updates defined by each event is to be determined by the smart contract logic and use case, but it can easily scale to thousands or millions of updates per event. The function(s) that should emit `MetadataUpdates` and the frequency of these on-chain updates is left at the discretion of this standard implementation.

The proposal is extremely gas efficient, since gas costs are only proportional to the frequency of committing changes. Many changes for many tokens can be batched in one transaction for the cost of only one `emit`.

## Reference Implementation

### Transformation engines

We have been experimenting with this generic Metadata update proposal using the JSONata transformation language. 

Here is a very simple example of a NFT metadata for an imaginary &apos;little monster&apos; game :

```json
{
    &quot;name&quot;: &quot;Monster 1&quot;,
    &quot;description&quot;: &quot;Little monsters you can play with.&quot;,
    &quot;attributes&quot;: [
      { &quot;trait_type&quot;: &quot;Level&quot;, &quot;value&quot;: 0 },
      { &quot;trait_type&quot;: &quot;Stamina&quot;, &quot;value&quot;: 100 }
    ],
    &quot;updatable&quot;: {
      &quot;engine&quot;: &quot;jsonata@1.8.*&quot;,
      &quot;recipes&quot;: {
        &quot;levelUp&quot;: {
          &quot;eval&quot;: &quot;$ ~&gt; | attributes[trait_type=&apos;Level&apos;] | {&apos;value&apos;: value + 1} |&quot;
        },
        &quot;updateDescription&quot;: {
          &quot;eval&quot;: &quot;$ ~&gt; | $ | {&apos;description&apos;: $newDescription} |&quot;
        }
      }
    }
}
 ```

This updatable metadata can only be updated to increment by one the trait attribute &quot;Level&quot;.

An example JSON updates metadata would be :
```json
{
    &quot;updates&quot;: [
      {&quot;tokenId&quot;:&quot;1&quot;,&quot;action&quot;:&quot;levelUp&quot;},
      {&quot;tokenId&quot;:&quot;2&quot;,&quot;action&quot;:&quot;levelUp&quot;},
      {&quot;tokenId&quot;:&quot;1&quot;,&quot;action&quot;:&quot;updateDescription&quot;,&quot;args&quot;:{&quot;newDescription&quot;:&quot;Now I&apos;m a big monster&quot;}},
      {&quot;tokenId&quot;:&quot;1&quot;,&quot;action&quot;:&quot;levelUp&quot;},
      {&quot;tokenId&quot;:&quot;3&quot;,&quot;action&quot;:&quot;levelUp&quot;}
    ]
}
 ```

## Security Considerations

A malicious recipe in the original metadata might be constructed as a DDoS vector for third parties marketplaces and tools that calculate NFT updated JSON metadata. They are encouraged to properly encapsulate software in charge of these calculations and put limits for the engine updates processing.

Smart contracts should be careful and conscious of using this extension and still allow the metadata URI to be updated in some contexts (by not having the same URI returned by `tokenURI` or `uri` for a given tokenId over time). They need to take into account if previous changes could have been already broadcasted for that NFT by the contract, if these changes are compatible with the new &quot;original metadata&quot; and what semantic they decide to associate by combining these two kinds of &quot;updates&quot;. 

## Backwards Compatibility

The proposal is fully compatible with both [EIP-721](/EIPs/EIPS/eip-721) and [EIP-1155](/EIPs/EIPS/eip-1155). Third-party applications that don&apos;t support this EIP will still be able to use the original metadata for each NFT.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 27 Jun 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5185</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5185</guid>
      </item>
    
      <item>
        <title>Extend EIP-1155 with rentable usage rights</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-draft-extending-erc1155-with-rentable-usage-rights/9553/4</comments>
        
        <description>## Abstract

This standard is an extension of [EIP-1155](/EIPs/EIPS/eip-1155). It proposes to introduce separable, rentable, and transferable usage rights (in the form of NFT-IDs), enabling the property owner (the only NFT holder) to rent out the NFT to multiple users (ID holders) at the same time for different terms, and be withdrawn by smart contract upon expiration.

The property owner always retains ownership and is able to transfer the NFT to others during the lease.

The proposal also supports the sublease and renewal of the rental so that users can freely transfer the usage rights among each other and extend the lease term. Early return of NFTs can also be achieved by subletting the usage rights back to the property owners.

## Motivation

The well-accepted [EIP-721](/EIPs/EIPS/eip-721) and EIP-1155 standards focused on the ownership of unique assets, quite sensible in the time of NFTs being used primarily as arts and collectibles, or, you can say, as private property rights.
### First Step: &quot;Expirable&quot; NFTs
The advent of private ownership in the real world has promoted the vigorous development of the modern economy, and we believe that the usage right will be the first detachable right widely applied in the blockchain ecosystem. As NFTs are increasingly applied in rights, finance, games, and the Metaverse, the value of NFT is no longer simply the proof of ownership, but with limitless practice use scenarios. For example, artists may wish to rent out their artworks to media or audiences within specific periods, and game guilds may wish to rent out game items to new players to reduce their entry costs.

The lease/rental of NFTs in the crypto space is not a new topic, but the implementation of leasing has long relied on over-collateralization, centralized custody, or pure trust, which significantly limits the boom of the leasing market. Therefore, a new type of &quot;expirable&quot; NFTs that can be automatically withdrawn upon expiration through smart contract is proposed, at the technical level, to eliminate those bottlenecks. Based on that, a new leasing model that is decentralized, collateral-free, and operated purely &quot;on-chain&quot; may disrupt the way people trade and use NFTs. Thus, this EIP proposal is here to create &quot;expirable&quot; NFTs compatible with EIP-1155.
### Then, Make Everything Transferable
The way we achieve leasing is to separate ownership and usage rights, and beyond that, we focus more on making them freely priced and traded after separation, which is impossible to happen in the traditional financial field. Imagine the below scenarios: i) as a landlord, you can sell your house in rental to others without affecting the tenancy, and your tenants will then pay rent to the new landlord; ii) as a tenant, you can sublet the house to others without the consent of the landlord, and even the one sublets can continue subletting the house until the lease term is close the last tenant can apply for a renewal of the lease. All of this can happen in the blockchain world, and that&apos;s the beauty of blockchain. Without permission, without trust, code is the law.

Making ownership and usage rights transferable may further revolutionize the game rules in NFT&apos;s field, both in capital allocation and NFT development. Buying NFT ownership is more like investing in stocks, and the price is determined by market expectations of the project; renting the usage right is less speculative, so the price is easier to determine based on supply and demand. The ownership market and the usage-right market will function to meet the needs of target participants and achieve a balance that is conducive to the long-term and stable development of NFT projects.
Based on the above, we propose this EIP standard to complement the current EIP scopes and introduce those functions as new standards.


## Specification

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.

```solidity
pragma solidity ^0.8.0;

///  Note: the ERC-165 identifier for this interface is 0x6938e358.
 interface IRental /* is IERC165,IERC1155 */ {
    /**
     * @notice This emits when user rent NFT
     * - `id` The id of the current token
     * - `user` The address to rent the NFT usage rights
     * - `amount` The amount of usage rights
     * - `expire` The specified period of time to rent
     **/
    event Rented(uint256 indexed id,address indexed user,uint256 amount,uint256 expire);

    /**
    * MUST trigger on any successful call to `renew(address user,uint256 id)`
    *  - `id` The id of the current token
    *  - `user` The user of the NFT
    *  - `expire` The new specified period of time to rent
    **/
    event Renew(uint256 indexed id,address indexed user,uint256 expire);

    /**
    *  MUST trigger on any successful call to `renew(address user,uint256 id,uint256 expire)`
    *  - `id` The id of the current token
    *  - `from` The current user of the NFT
    *  - `to` The new user
    **/
    event Sublet(uint256 indexed id,address indexed from,address to);

    /**
     * @notice This emits when the NFT owner takes back the usage rights from the tenant (the `user`)
     * - id The id of the current token
     * - user The address to rent the NFT&apos;s usage rights
     * - amount Amount of usage rights
     **/
    event TakeBack(uint256 indexed id, address indexed user, uint256 amount);

    /**
     * @notice Function to rent out usage rights
     * - from The address to approve
     * - to The address to rent the NFT usage rights
     * - id The id of the current token
     * - amount The amount of usage rights
     * - expire The specified period of time to rent
     **/
    function safeRent(address from,address to,uint256 id,uint256 amount,uint256 expire) external;

    /**
     * @notice Function to take back usage rights after the end of the tenancy
     * - user The address to rent the NFT&apos;s usage rights
     * - tokenId The id of the current token
     **/
    function takeBack(address user,uint256 tokenId) external;

    /**
    * @notice Return the NFT to the address of the NFT property right owner.
    **/
    function propertyRightOf(uint256 id) external view returns (address);

    /**
    * @notice Return the total supply amount of the current token
    **/
    function totalSupply(uint256 id) external view returns (uint256);

    /**
    * @notice Return expire The specified period of time to rent
    **/
    function expireAt(uint256 id,address user) external view returns(uint256);

    /**
    *   extended rental period
    *  - `id` The id of the current token
    *  - `user` The user of the NFT
    *  - `expire` The new specified period of time to rent
    **/
    function renew(address user,uint256 id,uint256 expire)  external;

    /**
    *  transfer of usage right
    *  - `id` The id of the current token
    *  - `user` The user of the NFT
    *  - `expire` The new specified period of time to rent
    **/
    function sublet(address to,uint256 id) external;
}


```

## Rationale

Implementing the proposal to create rentable NFTs has two main benefits.

One is that NFTs with multiple usage rights allow NFT property owners to perform the safeRent function and rent out usage rights to multiple users at the same time. For each usage right leased and expires, the property owner can perform the takeBack function to retrieve the usage right.

Another benefit is that the transfer of usage rights can be quite flexible. The user can transfer the usage rights to other users by calling the Sublet function during the lease period, and can also extend the lease period of the usage rights by asking the property owner to perform the Renewal function. It is worth mentioning that if the user sublet the NFT to the property owner, it will realize the early return of NFT before the end of the lease period.

## Backwards Compatibility

As mentioned at the beginning, this is an extension of EIP-1155. Therefore, it is fully backward compatible with EIP-1155.

## Security Considerations

Needs discussion.

## Copyright

Disclaimer of copyright and related rights through [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 17 Apr 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5187</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5187</guid>
      </item>
    
      <item>
        <title>Account Abstraction via Endorsed Operations</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-account-abstraction-via-endorsed-operations/9799</comments>
        
        <description>## Abstract

This ERC proposes a form of account abstraction (AA) that ensures compatibility with existing smart contract wallets and provides flexibility for alternative designs while avoiding introducing changes to the consensus layer. Instead of defining a strict structure for AA transactions, this proposal introduces the figure of `endorser` contracts. These smart contract instances are tasked with determining the quality of the submitted AA transactions, thus safely helping bundlers determine if a transaction should be kept in the mempool or not. Developers that intend to make their smart contract wallet compatible with this ERC must create and deploy an instance of an `endorser` or use an existing one compatible with their wallet.

## Motivation

This account abstraction proposal aims to implement a generalized system for executing AA transactions while maintaining the following goals:

* **Achieve the primary goal of account abstraction:** allow users to use smart contract wallets containing arbitrary verification and execution logic instead of EOAs as their primary account.
* **Decentralization:**
  * Allow any bundler to participate in the process of including AA transactions.
  * Work with all activity happening over a public mempool without having to concentrate transactions on centralized relayers.
  * Define structures that help maintain a healthy mempool without risking its participants from getting flooded with invalid or malicious payloads.
  * Avoid trust assumptions between bundlers, developers, and wallets.
* **Support existing smart contract wallet implementations:** Work with all the smart contract wallets already deployed and active while avoiding forcing each wallet instance to be manually upgraded.
* **Provide an unrestrictive framework:** Smart contract wallets are very different in design, limitations, and capabilities from one another; the proposal is designed to accommodate almost all possible variations.
* **No overhead:** Smart contract wallets already have a cost overhead compared to EOA alternatives, the proposal does not worsen the current situation.
* **Support other use cases:**
  * Privacy-preserving applications.
  * Atomic multi-operations (similar to [EIP-3074](/EIPs/EIPS/eip-3074)).
  * Payment of transaction fees using tokens. (E.g. [ERC-20](/EIPs/EIPS/eip-20), [ERC-777](/EIPs/EIPS/eip-777), etc.)
  * Scheduled execution of smart contracts without any user input.
  * Applications that require a generalistic relayer.

## Specification

To avoid Ethereum consensus changes, we do not attempt to create new transaction types for account-abstracted transactions. Instead, AA transactions are packed up in a struct called `Operation`, operations are structs composed by the following fields:

| Field                      | Type    | Description                                                                                                                                                 |
| -------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| entrypoint                 | address | Contract address that must be called with `callData` to execute the `operation`.                                                                            |
| callData                   | bytes   | Data that must be passed to the `entrypoint` call to execute the `operation`.                                                                               |
| fixedGas                   | uint64  | Amount of gas that the operation will pay for, regardless execution costs, and independent from `gasLimit`.                                                 |
| gasLimit                   | uint64  | Minimum gasLimit that must be passed when executing the `operation`.                                                                                        |
| feeToken                   | address | Contract address of the token used to repay the bundler. _(`address(0)` for the native token)_.                                                             |
| endorser                   | address | Address of the endorser contract that should be used to validate the `operation`.                                                                           |
| endorserCallData           | bytes   | Additional data that must be passed to the `endorser` when calling `isOperationReady()`.                                                                    |
| endorserGasLimit           | uint64  | Amount of gas that should be passed to the endorser when validating the `operation`.                                                                        |
| maxFeePerGas               | uint256 | Max amount of basefee that the `operation` execution is expected to pay. _(Similar to [EIP-1559](/EIPs/EIPS/eip-1559) `max_fee_per_gas`)_.                        |
| priorityFeePerGas          | uint256 | Fixed amount of fees that the `operation` execution is expected to pay to the bundler. _(Similar to [EIP-1559](/EIPs/EIPS/eip-1559) `max_priority_fee_per_gas`)_. |
| feeScalingFactor           | uint256 | Scaling factor to convert the computed fee into the `feeToken` unit.                                                                                        |
| feeNormalizationFactor     | uint256 | Normalization factor to convert the computed fee into the `feeToken` unit.                                                                                  |
| hasUntrustedContext        | bool    | If `true`, the operation _may_ have untrusted code paths. These should be treated differently by the bundler (see untrusted environment).                   |
| chainId                    | uint256 | Chain ID of the network where the `operation` is intended to be executed.                                                                                   |

These `Operation` objects can be sent to a dedicated operations mempool. A specialized class of actors called bundlers (either block producers running special-purpose code, or just users that can relay transactions to block producers) listen for operations on the mempool and execute these transactions.

Transactions are executed by calling the `entrypoint` with the provided `callData`. The `entrypoint` can be any contract, but most commonly it will be the wallet contract itself. Alternatively it can be an intermediary utility that deploys the wallet and then performs the transaction.

### Endorser functionality

Mempool participants need to be able to able to filter &quot;good operations&quot; (operations that pay the bundler the defined fee) from &quot;bad operations&quot; (operations that either miss payment or revert altogether).

This categorization is facilitated by the `endorser`; the endorser must be a deployed smart contract that implements the following interface:

```solidity
interface Endorser {
  struct Operation {
    address entrypoint;
    bytes callData;
    uint256 fixedGas;
    uint256 gasLimit;
    address endorser;
    bytes endorserCallData;
    uint256 endorserGasLimit;
    uint256 maxFeePerGas;
    uint256 priorityFeePerGas;
    address feeToken;
    uint256 feeScalingFactor;
    uint256 feeNormalizationFactor;
    bool hasUntrustedContext;
  }

  struct GlobalDependency {
    bool baseFee;
    bool blobBaseFee;
    bool chainId;
    bool coinBase;
    bool difficulty;
    bool gasLimit;
    bool number;
    bool timestamp;
    bool txOrigin;
    bool txGasPrice;
    uint256 maxBlockNumber;
    uint256 maxBlockTimestamp;
  }

  struct Constraint {
    bytes32 slot;
    bytes32 minValue;
    bytes32 maxValue;
  }

  struct Dependency {
    address addr;
    bool balance;
    bool code;
    bool nonce;
    bool allSlots;
    bytes32[] slots;
    Constraint[] constraints;
  }

  struct Replacement {
    address oldAddr;
    address newAddr;
    SlotReplacement[] slots;
  }

  struct SlotReplacement {
    bytes32 slot;
    bytes32 value;
  }

  function simulationSettings(
    Operation calldata _operation
  ) external view returns (
    Replacement[] memory replacements
  );

  function isOperationReady(
    Operation calldata _operation
  ) external returns (
    bool readiness,
    GlobalDependency memory globalDependency,
    Dependency[] memory dependencies
  );
}
```

Endorsers SHOULD be registered in the `EndorserRegistry` with an amount of burned ETH.
The amount of ETH to be burned is not specified in this proposal as mempool operators are free to set their own minimum thresholds.
Mempool operators MAY accept operations from endorsers without any burned ETH, but they would increase their risk exposing themselves to denial of service attacks.
Mempool operators MAY publish the minimum amount of burned ETH required for each endorser.

To check for operation status, the caller must first call `simulationSettings` to retrieve a list of on chain alterations.
Then call when the `isOperationReady` method is called, the endorser must return this information:

* **readiness:** when returning `true`, it means the transaction MUST be executed correctly and the bundler MUST be paid the offered gas fees (even if the underlying intent of the operation fails).
* **globalDependency:** a list of possible dependencies that don&apos;t belong to a given address, defines if the execution of the transaction MAY be invalidated by a change on one of these global variables. `maxBlockNumber` and `maxBlockTimestamp` are used as global constraints.
* **dependencies:** a comprehensive list of addresses and storage slots that must be monitored; any state change in these dependencies MUST trigger a re-evaluation of the operation&apos;s readiness.

The information provided by the endorser helps the mempool operator maintain a pool of &quot;good&quot; AA transactions that behave correctly; but it only provides a soft guarantee that the transaction will be executed correctly. Bundlers must always simulate the result of the execution before including a transaction in a block.

If the result of a simulation fails and the endorser still returns `readiness == true` with the same dependencies, then the endorser can not be trusted and it MUST be banned by the mempool operator.

The dependency list serves as a shortcut for the bundler to know which operations are fully independent from each other. This shortcut is useful for (a) clearing the mempool from operations that are no longer valid, and (b) for bundlers to know which operations can be included in the same block.

For efficiency, additional information MAY be provided to the endorser with `endorserCallData`.
If used, the endorser MUST validate that the provided `endorserCallData` is valid and relevant to the other values provided.

While the endorser is deployed on chain, calls to the endorser MUST NOT be submitted on chain. The bundler MUST read the results of `simulationSettings`, perform chain alterations and simulate the execution off chain.

### Global Dependencies

| Field             | Type    | Description                                                           |
| ----------------- | ------- | --------------------------------------------------------------------- |
| baseFee           | bool    | `true` if the `block.basefee` should be considered a dependency.      |
| blobBaseFee       | bool    | `true` if the `block.blockbasefee` should be considered a dependency. |
| chainId           | bool    | `true` if the `block.chainid` should be considered a dependency.      |
| coinbase          | bool    | `true` if the `block.coinbase` should be considered a dependency.     |
| difficulty        | bool    | `true` if the `block.difficulty` should be considered a dependency.   |
| gasLimit          | bool    | `true` if the `block.gaslimit` should be considered a dependency.     |
| number            | bool    | `true` if the `block.number` should be considered a dependency.       |
| timestamp         | bool    | `true` if the `block.timestamp` should be considered a dependency.    |
| txOrigin          | bool    | `true` if the `tx.origin` should be considered a dependency.          |
| txGasPrice        | bool    | `true` if the `tx.gasprice` should be considered a dependency.        |
| maxBlockNumber    | uint256 | The maximum value of `block.number` that `readiness` applies to.      |
| maxBlockTimestamp | uint256 | The maximum value of `block.timestamp` that `readiness` applies to.   |

The `endorser` MUST use the `maxBlockNumber` and `maxBlockTimestamp` fields to limit the validity of the `readiness` result. This is useful for operations that are only valid for a certain period of time.

Note that all values are **inclusive**. If the `endorser` determines the validity of the `operation` is indefinite, the `maxBlockNumber` and `maxBlockTimestamp` fields MUST be set to `type(uint256).max`.

### Dependencies

| Field       | Type         | Description                                                                                 |
| ----------- | ------------ | ------------------------------------------------------------------------------------------- |
| addr        | address      | Contract address of the dependencies entry. _(Only one entry per address is allowed)_.      |
| balance     | bool         | `true` if the balance of `addr` should be considered a dependency of the `operation`.       |
| code        | bool         | `true` if the code of `addr` should be considered a dependency of the `operation`.          |
| nonce       | bool         | `true` if the nonce of `addr` should be considered a dependency of the `operation`.         |
| allSlots    | bool         | `true` if all storage slots of `addr` should be considered a dependency of the `operation`. |
| slots       | bytes32[]    | List of all storage slots of `addr` that should be considered dependencies of `operation`.  |
| constraints | Constraint[] | List of storage slots of `addr` that have a range of specific values as dependencies.       |

The `endorser` does not need to include all accessed storage slots on the dependencies list, it only needs to include storage slots that after a change may also result in a change of readiness.

Note that `allSlots`, `constraints` and `slots` are mutually exclusive. If `allSlots` is set to `true`, then `constraints` and `slots` MUST be empty arrays.
If a slot is listed in `constraints`, it MUST NOT be listed in `slots`.
The `endorser` should prefer to use `constraints` over `slots`, and `slots` over `allSlots` whenever possible to limit reevaluation requirements of the bundler.

&gt; E.g. A wallet may pay fees using funds stored as WETH. During `isOperationReady()`, the endorser contract may call the `balanceOf` method of the `WETH` contract to determine if the wallet has enough `WETH` balance. Even though the ETH balance of the WETH contract and the code of the WETH contract are being accessed, the endorser only cares about the user&apos;s WETH balance for this operation and hence does not include these as dependencies.

#### Constraints

| Field    | Type    | Description                                                                 |
| -------- | ------- | --------------------------------------------------------------------------- |
| slot     | bytes32 | Storage slot of `addr` that has a range of specific values as dependencies. |
| minValue | bytes32 | Minimum value (inclusive) of `slot` that `readiness` applies to.            |
| maxValue | bytes32 | Maximum value (inclusive) of `slot` that `readiness` applies to.            |

The `endorser` can use the `minValue` and `maxValue` fields to limit the validity of the `readiness` result. This allows the endorser to fully validate an operation, even when this operation depends on storage values that are not directly accessible by the endorser.

Note that all values are **inclusive**. When an exact value is required, `minValue` and `maxValue` should be set to the same value.

### Simulation settings

The `simulationSettings` method returns a list of replacements that the bundler should apply to the operation before simulating the `isOperationReady`. Note that these replacements are only used for `isOperationReady` simulation and are not applied when simulating the operation itself.

| Field       | Type    | Description                                                                 |
| ----------- | ------- | --------------------------------------------------------------------------- |
| oldAddr     | address | The on chain address where contract code is currently located.              |
| newAddr     | address | The address the contract code should be located when performing simulation. |
| slots.slot  | bytes32 | The slot location to be changed.                                            |
| slots.value | bytes32 | The value of the slot to be set before performing simulation.               |

The `endorser` MAY use the `simulationSettings` method to provide a list of replacements that the bundler should apply to the network before simulating `isOperationReady`. This is useful for operations that must be called from specific contract addresses or that depend on specific storage values (e.g. [ERC-4337](/EIPs/EIPS/eip-4337)&apos;s EntryPoint).

The `endorser` MAY provide it&apos;s own address for replacement. In this event, the bundler should update the `endorser` address used when calling `isOperationReady`.

### Misbehavior detection

It is possible for `endorser` contracts to behave maliciously or erratically in the following ways:

* (1) It considers an operation &quot;ready&quot;, but when the operation is executed it transfers less than the agreed-upon fees to the bundler.
* (2) It considers an operation &quot;ready&quot;, but when the operation is executed the top-level call fails.
* (3) It changes the readiness from `true` to `false` while none of the dependencies register any change.

The bundler MUST discard and re-evaluate the readiness status after a change on any of the dependencies of the `operation`, meaning that only operations considered `ready` are candidates for constructing the next block.

If, when simulating the final inclusion of the operation, the bundler discovers that it does not result in correct payment (either because the transaction fails, or transferred amount is below the defined fee), then it MUST ban the `endorser`.

When an `endorser` is banned, the mempool operator MUST drop all `operations` related to the endorser.

### Untrusted environment

In some scenarios, the `endorser` may not be able to fully validate the `operation` but may be able to infer that a given code path *should* be safe. In these cases, the endorser can mark a section of the operation as `untrusted`. Any storage slots (balance, code, nonce, or specific slots) accessed in this untrusted context should be automatically considered as dependencies.

```sol
interface Endorser {
  event UntrustedStarted();
  event UntrustedEnded();
}
```

The endorser can use the `UntrustedStarted` and `UntrustedEnded` events to signal the start and end of an untrusted context. The bundler should listen to these events and extend the dependencies list accordingly.

Only the top-level `endorser` can signal an untrusted context; any other events with the same signature but emitted by a different contract should be ignored.

Untrusted contexts can be opened and closed multiple times and can be nested. If multiple events are emitted, the bundler MUST count the number of `UntrustedStarted` and `UntrustedEnded` events and only consider the untrusted context as ended when the number of `UntrustedEnded` events is equal to the number of `UntrustedStarted` events.

If `hasUntrustedContext` is set to `false`, the bundler should ignore any `UntrustedStarted` and `UntrustedEnded` events.

#### Automatic dependency graph construction

All code executed within the untrusted context must be monitored. If the code executes any of the following opcodes, the dependency graph must be extended accordingly.

| Opcode      | Dependency                              |
|-------------|-----------------------------------------|
| BALANCE     | `dependencies[addr].balance = true`     |
| ORIGIN      | `global.txOrigin = true`                |
| CODESIZE    | None                                    |
| CODECOPY    | None                                    |
| GASPRICE    | `global.txGasPrice = true`              |
| EXTCODESIZE | `dependencies[addr].code = true`        |
| EXTCODECOPY | `dependencies[addr].code = true`        |
| EXTCODEHASH | `dependencies[addr].code = true`        |
| COINBASE    | `global.coinbase = true`                |
| TIMESTAMP   | `global.timestamp = true`               |
| NUMBER      | `global.number = true`                  |
| DIFFICULTY  | `global.difficulty = true`              |
| PREVRANDAO  | `global.difficulty = true`              |
| CHAINID     | `global.chainId = true`                 |
| SELFBALANCE | `dependencies[self].balance = true`     |
| BASEFEE     | `global.baseFee = true`                 |
| SLOAD       | `dependencies[addr].slots[slot] = true` |
| CREATE      | `dependencies[addr].nonce = true`       |
| CREATE2     | `dependencies[contract].code = true`    |

Notice that untrusted contexts generate a lot of dependencies and may generate many false positives. This may lead to numerous re-evaluations and thus to the operation being dropped from the mempool. A bundler MAY choose to drop operations if the number of dependencies exceeds a certain threshold.

Block-level dependencies are specially sensitive as they will be shared with a large number of operations.

It is recommended to use untrusted contexts only when necessary, like when an `endorser` needs to validate a nested signature to a wallet that is not under its control.

### Fee payment

The `endorser` MUST guarantee that the operation will repay at least the spent gas to `tx.origin`.

The payment is always made in the `feeToken`, which can be any token standard (E.g. [ERC-20](/EIPs/EIPS/eip-20)). If `feeToken` is `address(0)`, then payment is made in the native currency. When `feeToken` is `address(0)`, `feeScalingFactor` and `feeNormalizationFactor` MUST be equal to `1`.

All units are expressed in the native token unit. The result of the fee calculation is then converted to the `feeToken` unit using the `feeScalingFactor` and `feeNormalizationFactor`.

The gas units consider a fixed amount of gas (`fixedGas`) and a variable amount of gas (`gasLimit`). Allowing fixed costs caters for gas overheads which may be outside the scope of the on chain execution, such as calldata fees. This also allows repayment to be reduced when execution is cheaper than expected (such as when an inner call fails without reverting the top-level transaction), while still repaying the bundler.

The expected gas repayment is calculated as follows:

```
gasUnits = op.fixedGas + Min(gasUsed, op.gasLimit)
feePerGas = Min(op.maxFeePerGas, block.baseFee + op.priorityFeePerGas)
expectedRepayment = (gasUnits * feePerGas * op.feeScalingFactor) / op.feeNormalizationFactor
```

While the `endorser` MUST guarantee the repayment of `expectedRepayment`, the actual repayment amount MAY exceed this fee. E.g. For ease of development, a bundler MAY choose to only endorse operations that repay the maximum values provided by the operation.

### Operation identification

Operations can be identified by their operation hash, which is calculated as a CIDv1 multihash of a `raw` file, containing the canonical JSON representation of the operation. This hash is never used on-chain, but it serves as a unique pointer to the operation that can be shared across systems.

The operation MAY be pinned on the IPFS network; this would allow other participants to retrieve the content of the operation after the operation has been removed from the mempool. This pinning is not mandatory, and it may be performed by the mempool operator or by the wallet itself if visibility of the operation is desired.

### Bundler behavior upon receiving an operation

Bundlers can add their own rules for how to ensure the successful relaying of AA transactions and for getting paid for relaying these transactions. However, we propose here a baseline specification that should be sufficient.

When a bundler receives an `operation`, it SHOULD perform these sanity checks:

* The `endorserGasLimit` is sufficiently low (&lt;= `MAX_ENDORSER_GAS`).
* The endorser (i) is registered and has enough burn (&gt;= `MIN_ENDORSER_BURN`), and (ii) it has not been internally flagged as banned.
* The `fixedGas` is large enough to cover the cost associated with submitting the transaction (i.e. calldata gas costs).
* The `gasLimit` is at least the cost of a `CALL` with a non-zero value.
* The `feeToken` is `address(0)` or a known token address that the bundler is willing to accept.
* The `feeScalingFactor` and `feeNormalizationFactor` are `1` for a `feeToken` value of `address(0)` or values the bundler is willing to accept.
* The `maxFeePerGas` and `priorityPerGas` are above a configurable minimum value the bundler is willing to accept.
* If another operation exists in the mempool with the exact same dependency set AND the same endorser address, the `maxFeePerGas` and `priorityFeePerGas` of the newly received operation MUST be 12% higher than the one on the mempool to replace it. (Similar with how EOA with same nonce work)

The bundler should then perform evaluation of the operation.

### Evaluation

To evaluate the `operation`, the bundler MUST call `simulationSettings()` on the `endorser` to obtain simulation setting values. The bundler MUST apply the settings and **simulate** a call to `isOperationReady()` on the `endorser`. If the endorser considers the operation ready, and the constraints are within bounds, then the client MUST add the operation to the mempool. Otherwise, the operation MUST be dropped.

The `endorser` result SHOULD be invalidated and its readiness SHOULD be re-evaluated if any of the values of the provided dependencies change. If the operation readiness changes to `false`, the operation MUST be discarded.

Before including the operation in a block, a last simulation MUST be performed, this time by constructing the block and probing the result. All transactions in the block listed **before** the operation must be simulated and then the `endorser` must be queried for readiness in-case some dependencies changed. Then constraints MUST be re-evaluated for correctness. Finally, the **operation** MUST be simulated.

If the **operation** fails during the final simulation, the `endorser` MUST be banned because (i) it returned a bad readiness state or (ii) it changed the operation readiness independently from the dependencies.

### Optional rules

Mempool clients MAY implement additional rules to further protect against maliciously constructed transactions.

* Limit the size of accepted dependencies to `MAX_OPERATION_DEPENDENCIES`, dropping operations that cross the boundary.
* Limit the number of times an operation may trigger a re-evaluation to `MAX_OPERATION_REEVALS`, dropping operations that cross the boundary.
* Limit the number of operations in the mempool that depend on the same dependency slots.

If these rules are widely adopted, wallet developers should keep usage of dependencies to the lowest possible levels and avoid shared dependency slots that are frequently updated.

### After operation inclusion

There is no limit in-place that defines that an operation can only be executed once.

The bundler SHOULD NOT drop an `operation` after successfully including such operation in a block, the bundler MAY perform evaluation.

If the `endorser` still returns `readiness == true` (after inclusion) then the operation SHOULD be treated as any other healthy operation, and thus it MAY be kept in the mempool.

### Endorser registry

The endorser registry serves as a place to register the burn of each endorser, anyone can increase the burn of any endorser by calling the `addBurn()` function.

All burn is effectively locked forever; slashing can&apos;t be reliably proved on-chain without protocol alterations, so it remains a virtual event on which mempool operators will ignore the deposited ETH.

#### Implementation

(EXAMPLE)

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.15;

contract EndorserRegistry {
  event Burned(
      address indexed _endorser,
      address indexed _sender,
      uint256 _new,
      uint256 _total
  );

  mapping(address =&gt; uint256) public burn;

  function addBurn(address _endorser) external payable returns (uint256) {
    uint256 total = burn[_endorser] + msg.value;
    burn[_endorser] = total;

    emit Burned(_endorser, msg.sender, msg.value, total);

    return total;
  }
}
```

## Rationale

### Griefing protection

The main challenge with a purely smart contract wallet-based account abstraction system is DoS safety: how can a bundler that includes an operation make sure it will be paid without executing the entire operation?

Bundlers could execute the entire operation to determine if it is healthy or not, but this operation may be expensive and complex for the following reasons:

* The bundler does not have a way to simulate the transaction with a reduced amount of gas; it has to use the whole `gasLimit`, exposing itself to a higher level of griefing.
* The bundler does not have a way to know if a change to the state will affect the operation or not, and thus it has to re-evaluate the operation after every single change.
* The bundler does not have a way to know if a change to the state will invalidate a large portion of the mempool.

In this proposal, we add the `endorser` as a tool for the bundlers to validate arbitrary operations in a controlled manner, without the bundler having to know any of the inner workings of such operation.

In effect, we move the responsibility from the wallet to the wallet developer; the developer must code, deploy and burn ETH for the `endorser`; this is a nearly ideal scenario because developers know how their wallet operations work, and thus they can build tools to evaluate these operations efficiently.

Additionally, the specification is kept as simple as possible as enforcing a highly structured behavior and schema for smart contract wallet transactions may stagnate the adoption of more innovative types of wallets and the adoption of a shared standard among them.

### Burned ETH

Anyone can deploy a endorser contract and wallet clients are the one providing which endorser contract should be used for the given transaction. Instead of having each bundler rely on an off-chain registry that they need to maintain, the endorser registry can be called to see if the requested endorser contract is present and how much ETH was burned for it. Bundlers can then decide a minimum treshshold for how much ETH burnt is required for an endorser contract to be accepted. Bundlers are also free to support endorsers contract that are not part of the registry or are part of it but have no ETH burned associated.

### Minimum overhead

Since the validation of an AA transactions is done off-chain by the bundler rather than at execution time, there is no additional gas fee overhead for executing transactions. The bundler bears the risk rather than all users having to pay for that security.

### Differences with alternative proposals

1. This proposal does not require monitoring for forbidden opcodes or storage access boundaries. Wallets have complete freedom to use any EVM capabilities during validation and execution.
2. This proposal does not specify any replay protection logic since all existing smart contract wallets already have their own, and designs can vary among them. Nonces can be communicated to the bundler using a `dependency`.
3. This proposal does not specify a pre-deployment logic because it can be handled directly by the entrypoint.
4. This proposal does not require wallets to accept `execution` transactions from a trusted entrypoint contract, reducing overhead and allowing existing wallets to be compatible with the proposal.
5. This proposal does not distinguish between `execution` and `signature` payloads, this distinction remains implementation-specific.

## Backwards Compatibility

This ERC does not change he consensus layer, nor does impose changes on existing smart contract wallets, so there are no backwards compatibility issues.

## Security Considerations

This ERC does not make changes to on-chain interactions. Endorsers are explicitly for off-chain validations.

Bundlers are responsible for managing their own security and for ensuring that they are paid for the transactions they include in blocks.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 29 Jun 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5189</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5189</guid>
      </item>
    
      <item>
        <title>Minimal Soulbound NFTs</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5192-minimal-soulbound-nfts/9814</comments>
        
        <description>## Abstract

This standard is an extension of [EIP-721](/EIPs/EIPS/eip-721). It proposes a minimal interface to make tokens soulbound using the feature detection functionality of [EIP-165](/EIPs/EIPS/eip-165). A soulbound token is a non-fungible token bound to a single account.

## Motivation

The Ethereum community has expressed a need for non-transferrable, non-fungible, and socially-priced tokens similar to World of Warcraft’s soulbound items. But the lack of a token standard leads many developers to simply throw errors upon a user&apos;s invocation of transfer functionalities. Over the long term, this will lead to fragmentation and less composability.

In this document, we outline a minimal addition to [EIP-721](/EIPs/EIPS/eip-721) that allows wallet implementers to check for a token contract&apos;s permanent (non-)transferability using [EIP-165](/EIPs/EIPS/eip-165).

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot; and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### Contract Interface

A token with a `uint256 tokenId` may be bound to a receiving account with `function locked(...)` returning `true`. In this case, all [EIP-721](/EIPs/EIPS/eip-721) functions of the contract that transfer the token from one account to another must throw.

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

interface IERC5192 {
  /// @notice Emitted when the locking status is changed to locked.
  /// @dev If a token is minted and the status is locked, this event should be emitted.
  /// @param tokenId The identifier for a token.
  event Locked(uint256 tokenId);

  /// @notice Emitted when the locking status is changed to unlocked.
  /// @dev If a token is minted and the status is unlocked, this event should be emitted.
  /// @param tokenId The identifier for a token.
  event Unlocked(uint256 tokenId);

  /// @notice Returns the locking status of an Soulbound Token
  /// @dev SBTs assigned to zero address are considered invalid, and queries
  /// about them do throw.
  /// @param tokenId The identifier for an SBT.
  function locked(uint256 tokenId) external view returns (bool);
}
```

To aid recognition that an [EIP-721](/EIPs/EIPS/eip-721) token implements &quot;soulbinding&quot; via this EIP upon calling [EIP-721](/EIPs/EIPS/eip-721)&apos;s `function supportsInterface(bytes4 interfaceID) external view returns (bool)` with `interfaceID=0xb45a3c0e`, a contract implementing this EIP must return `true`.

## Rationale

The above model is the simplest possible path towards a canonical interface for Soulbound tokens. It reflects upon the numerous Soulbound token implementations that simply revert upon transfers.

## Backwards Compatibility

This proposal is fully backward compatible with [EIP-721](/EIPs/EIPS/eip-721).

## Security Considerations

There are no security considerations related directly to the implementation of this standard.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 01 Jul 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5192</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5192</guid>
      </item>
    
      <item>
        <title>Blueprint contract format</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-5202-standard-factory-contract-format/9851</comments>
        
        <description>## Abstract

Define a standard for &quot;blueprint&quot; contracts, or contracts which represent initcode that is stored on-chain.

## Motivation

To decrease deployer contract size, a useful pattern is to store initcode on chain as a &quot;blueprint&quot; contract, and then use `EXTCODECOPY` to copy the initcode into memory, followed by a call to `CREATE` or `CREATE2`. However, this comes with the following problems:

- It is hard for external tools and indexers to detect if a contract is a &quot;regular&quot; runtime contract or a &quot;blueprint&quot; contract. Heuristically searching for patterns in bytecode to determine if it is initcode poses maintenance and correctness problems.
- Storing initcode byte-for-byte on-chain is a correctness and security problem. Since the EVM does not have a native way to distinguish between executable code and other types of code, unless the initcode explicitly implements ACL rules, *anybody* can call such a &quot;blueprint&quot; contract and execute the initcode directly as ordinary runtime code. This is particularly problematic if the initcode stored by the blueprint contract has side effects such as writing to storage or calling external contracts. If the initcode stored by the blueprint contract executes a `SELFDESTRUCT` opcode, the blueprint contract could even be removed, preventing the correct operation of downstream deployer contracts that rely on the blueprint existing. For this reason, it would be good to prefix blueprint contracts with a special preamble to prevent execution.

## Specification

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.

A blueprint contract MUST use the preamble `0xFE71&lt;version bits&gt;&lt;length encoding bits&gt;`. 6 bits are allocated to the version, and 2 bits to the length encoding. The first version begins at 0 (`0b000000`), and versions increment by 1. The value `0b11` for `&lt;length encoding bits&gt;` is reserved. In the case that the length bits are `0b11`, the third byte is considered a continuation byte (that is, the version requires multiple bytes to encode). The exact encoding of a multi-byte version is left to a future ERC.

A blueprint contract MUST contain at least one byte of initcode.

A blueprint contract MAY insert any bytes (data or code) between the version byte(s) and the initcode. If such variable length data is used, the preamble must be `0xFE71&lt;version bits&gt;&lt;length encoding bits&gt;&lt;length bytes&gt;&lt;data&gt;`. The `&lt;length encoding bits&gt;` represent a number between 0 and 2 (inclusive) describing how many bytes `&lt;length bytes&gt;` takes, and `&lt;length bytes&gt;` is the big-endian encoding of the number of bytes that `&lt;data&gt;` takes.

## Rationale

- To save gas and storage space, the preamble should be as minimal as possible.

- It is considered &quot;bad&quot; behavior to try to CALL a blueprint contract directly, therefore the preamble starts with `INVALID (0xfe)` to end execution with an exceptional halting condition (rather than a &quot;gentler&quot; opcode like `STOP (0x00)`).

- To help distinguish a blueprint contract from other contracts that may start with `0xFE`, a &quot;magic&quot; byte is used. The value `0x71` was arbitrarily chosen by taking the last byte of the keccak256 hash of the bytestring &quot;blueprint&quot; (i.e.: `keccak256(b&quot;blueprint&quot;)[-1]`).

- An empty initcode is disallowed by the spec to prevent what might be a common mistake.

- Users may want to include arbitrary data or code in their preamble. To allow indexers to ignore these bytes, a variable length encoding is proposed. To allow the length to be only zero or one bytes (in the presumably common case that `len(data bytes)` is smaller than 256), two bits of the third byte are reserved to specify how many bytes the encoded length takes.

- In case we need an upgrade path, version bits are included. While we do not expect to exhaust the version bits, in case we do, a continuation sequence is reserved. Since only two bytes are required for `&lt;length bytes&gt;` (as [EIP-170](/EIPs/EIPS/eip-170) restricts contract length to 24KB), a `&lt;length encoding bits&gt;` value of 3 would never be required to describe `&lt;length bytes&gt;`. For that reason, the special `&lt;length encoding bits&gt;` value of `0b11` is reserved as a continuation sequence marker.

- The length of the initcode itself is not included by default in the preamble because it takes space, and it can be trivially determined using `EXTCODESIZE`.

- The Ethereum Object Format (EOF) could provide another way of specifying blueprint contracts, by adding another section kind (3 - initcode). However, it is not yet in the EVM, and we would like to be able to standardize blueprint contracts today, without relying on EVM changes. If, at some future point, section kind 3 becomes part of the EOF spec, and the EOF becomes part of the EVM, this ERC will be considered to be obsolesced since the EOF validation spec provides much stronger guarantees than this ERC.


## Backwards Compatibility

No known issues

## Test Cases

- An example (and trivial!) blueprint contract with no data section, whose initcode is just the `STOP` instruction:

```
0xFE710000
```

- An example blueprint contract whose initcode is the trivial `STOP` instruction and whose data section contains the byte `0xFF` repeated seven times:

```
0xFE710107FFFFFFFFFFFFFF00
```

Here, 0xFE71 is the magic header, `0x01` means version 0 + 1 length bit, `0x07` encodes the length in bytes of the data section. These are followed by the data section, and then the initcode. For illustration, the above code with delimiters would be `0xFE71|01|07|FFFFFFFFFFFFFF|00`.

- An example blueprint whose initcode is the trivial `STOP` instruction and whose data section contains the byte `0xFF` repeated 256 times:

```
0xFE71020100FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00
```

Delimited, that would be `0xFE71|02|0100|FF...FF|00`.

## Reference Implementation

```python
from typing import Optional, Tuple

def parse_blueprint_preamble(bytecode: bytes) -&gt; Tuple[int, Optional[bytes], bytes]:
    &quot;&quot;&quot;
    Given bytecode as a sequence of bytes, parse the blueprint preamble and
    deconstruct the bytecode into:
        the ERC version, preamble data and initcode.
    Raises an exception if the bytecode is not a valid blueprint contract
    according to this ERC.
    arguments:
        bytecode: a `bytes` object representing the bytecode
    returns:
        (version,
         None if &lt;length encoding bits&gt; is 0, otherwise the bytes of the data section,
         the bytes of the initcode,
        )
    &quot;&quot;&quot;
    if bytecode[:2] != b&quot;\xFE\x71&quot;:
        raise Exception(&quot;Not a blueprint!&quot;)

    erc_version = (bytecode[2] &amp; 0b11111100) &gt;&gt; 2

    n_length_bytes = bytecode[2] &amp; 0b11
    if n_length_bytes == 0b11:
        raise Exception(&quot;Reserved bits are set&quot;)

    data_length = int.from_bytes(bytecode[3:3 + n_length_bytes], byteorder=&quot;big&quot;)

    if n_length_bytes == 0:
        preamble_data = None
    else:
        data_start = 3 + n_length_bytes
        preamble_data = bytecode[data_start:data_start + data_length]

    initcode = bytecode[3 + n_length_bytes + data_length:]

    if len(initcode) == 0:
        raise Exception(&quot;Empty initcode!&quot;)

    return erc_version, preamble_data, initcode
```

The following reference function takes the desired initcode for a blueprint as a parameter, and returns EVM code which will deploy a corresponding blueprint contract (with no data section):

```python
def blueprint_deployer_bytecode(initcode: bytes) -&gt; bytes:
    blueprint_preamble = b&quot;\xFE\x71\x00&quot;  # ERC5202 preamble
    blueprint_bytecode = blueprint_preamble + initcode

    # the length of the deployed code in bytes
    len_bytes = len(blueprint_bytecode).to_bytes(2, &quot;big&quot;)

    # copy &lt;blueprint_bytecode&gt; to memory and `RETURN` it per EVM creation semantics
    # PUSH2 &lt;len&gt; RETURNDATASIZE DUP2 PUSH1 10 RETURNDATASIZE CODECOPY RETURN
    deploy_bytecode = b&quot;\x61&quot; + len_bytes + b&quot;\x3d\x81\x60\x0a\x3d\x39\xf3&quot;

    return deploy_bytecode + blueprint_bytecode
```

## Security Considerations

There could be contracts on-chain already which happen to start with the same prefix as proposed in this ERC. However, this is not considered a serious risk, because the way it is envisioned that indexers will use this is to verify source code by compiling it and prepending the preamble.

As of 2022-07-08, no contracts deployed on the Ethereum mainnet have a bytecode starting with `0xFE71`.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 23 Jun 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5202</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5202</guid>
      </item>
    
      <item>
        <title>ERC-1155 Allowance Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-erc1155-approval-by-amount/9898</comments>
        
        <description>## Abstract

This ERC defines standard functions for granular approval of [ERC-1155](/EIPs/EIPS/eip-1155) tokens by both `id` and `amount`. This ERC extends [ERC-1155](/EIPs/EIPS/eip-1155).

## Motivation

[ERC-1155](/EIPs/EIPS/eip-1155)&apos;s popularity means that multi-token management transactions occur on a daily basis. Although it can be used as a more comprehensive alternative to [ERC-721](/EIPs/EIPS/eip-721), ERC-1155 is most commonly used as intended: creating multiple `id`s, each with multiple tokens. While many projects interface with these semi-fungible tokens, by far the most common interactions are with NFT marketplaces.

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 `setApprovalForAll` function, which approves ALL tokens with a specific `id`. This system has obvious minimum required trust flaws. This ERC combines ideas from [ERC-20](/EIPs/EIPS/eip-20) and [ERC-721](/EIPs/EIPS/eip-721) 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 `id`.

## Specification

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.

Contracts using this ERC MUST implement the `IERC5216` interface.

### Interface implementation

```solidity
/**
 * @title ERC-1155 Allowance Extension
 * Note: the ERC-165 identifier for this interface is 0x1be07d74
 */
interface IERC5216 is IERC1155 {

    /**
     * @notice Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
     * `id` and with an amount: `amount`.
     */
    event Approval(address indexed account, address indexed operator, uint256 id, uint256 amount);

    /**
     * @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.
     */
    function approve(address operator, uint256 id, uint256 amount) external;

    /**
     * @notice Returns the amount allocated to `operator` approved to transfer `account`&apos;s tokens, according to `id`.
     */
    function allowance(address account, address operator, uint256 id) external view returns (uint256);
}
```

The `approve(address operator, uint256 id, uint256 amount)` function MUST be either `public` or `external`.

The `allowance(address account, address operator, uint256 id)` function MUST be either `public` or `external` and MUST be `view`.

The `safeTrasferFrom` function (as defined by ERC-1155) MUST:

- Not revert if the user has approved `msg.sender` with a sufficient `amount`
- Subtract the transferred amount of tokens from the approved amount if `msg.sender` is not approved with `setApprovalForAll`

In addition, the `safeBatchTransferFrom` MUST:

- Add an extra condition that checks if the `allowance` of all `ids` have the approved `amounts` (See `_checkApprovalForBatch` function reference implementation)

The `Approval` event MUST be emitted when a certain number of tokens are approved.

The `supportsInterface` method MUST return `true` when called with `0x1be07d74`.

## Rationale

The name &quot;ERC-1155 Allowance Extension&quot; was chosen because it is a succinct description of this ERC. Users can approve their tokens by `id` and `amount` to `operator`s.

By having a way to approve and revoke in a manner similar to [ERC-20](/EIPs/EIPS/eip-20), the trust level can be more directly managed by users:

- Using the `approve` function, users can approve an operator to spend an `amount` of tokens for each `id`.
- Using the `allowance` function, users can see the approval that an operator has for each `id`.

The [ERC-20](/EIPs/EIPS/eip-20) name patterns were used due to similarities with [ERC-20](/EIPs/EIPS/eip-20) approvals.

## Backwards Compatibility

This standard is compatible with [ERC-1155](/EIPs/EIPS/eip-1155).

## Reference Implementation

The reference implementation can be found [here](/EIPs/assets/eip-5216/ERC5216.sol).

## Security Considerations

Users of this ERC must thoroughly consider the amount of tokens they give permission to `operators`, and should revoke unused authorizations.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>NFT Rights Management</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5218-nft-rights-management/9911</comments>
        
        <description>## Abstract

The following standard defines an API for managing NFT licenses. This standard provides basic functionality to create, transfer, and revoke licenses, and to determine the current licensing state of an NFT. The standard does not define the legal details of the license. Instead, it provides a structured framework for recording licensing details.

We consider use cases of NFT creators who wish to give the NFT holder a copyright license to use a work associated with the NFT. The holder of an active license can issue sublicenses to others to carry out the rights granted under the license. The license can be transferred with the NFT, so do all the sublicenses. The license can optionally be revoked under conditions specified by the creator. 


## Motivation

The [ERC-721](/EIPs/EIPS/eip-721) standard defines an API to track and transfer ownership of an NFT. When an NFT is to represent some off-chain asset, however, we would need some legally effective mechanism to *tether* the on-chain asset (NFT) to the off-chain property. One important case of off-chain property is creative work such as an image or music file. Recently, most NFT projects involving creative works have used licenses to clarify what legal rights are granted to the NFT owner. But these licenses are almost always off-chain and the NFTs themselves do not indicate what licenses apply to them, leading to uncertainty about rights to use the work associated with the NFT. It is not a trivial task to avoid all the copyright vulnerabilities in NFTs, nor have existing EIPs addressed rights management of NFTs beyond the simple cases of direct ownership (see [ERC-721](/EIPs/EIPS/eip-721)) or rental (see [ERC-4907](/EIPs/EIPS/eip-4907)).

This EIP attempts to provide a standard to facilitate rights management of NFTs in the world of Web3. In particular, [ERC-5218](/EIPs/EIPS/eip-5218) smart contracts allow all licenses to an NFT, including the *root license* issued to the NFT owner and *sublicenses* granted by a license holder, to be recorded and easily tracked with on-chain data. These licenses can consist of human-readable legal code, machine-readable summaries such as those written in CC REL, or both. An ERC-5218 smart contract points to a license by recording a URI, providing a reliable reference for users to learn what legal rights they are granted and for NFT creators and auditors to detect unauthorized infringing uses.



## Specification

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.

**Every ERC-5218 compliant contract *must* implement the `IERC5218` interface**:

```solidity
pragma solidity ^0.8.0;

/// @title ERC-5218: NFT Rights Management
interface IERC5218 is IERC721 {

  /// @dev This emits when a new license is created by any mechanism.
  event CreateLicense(uint256 _licenseId, uint256 _tokenId, uint256 _parentLicenseId, address _licenseHolder, string _uri, address _revoker);
 
  /// @dev This emits when a license is revoked. Note that under some
  ///  license terms, the sublicenses may be `implicitly` revoked following the
  ///  revocation of some ancestral license. In that case, your smart contract
  ///  may only emit this event once for the ancestral license, and the revocation
  ///  of all its sublicenses can be implied without consuming additional gas.
  event RevokeLicense(uint256 _licenseId);
 
  /// @dev This emits when the a license is transferred to a new holder. The
  ///  root license of an NFT should be transferred with the NFT in an ERC721
  ///  `transfer` function call. 
  event TransferLicense(uint256 _licenseId, address _licenseHolder);
  
  /// @notice Check if a license is active.
  /// @dev A non-existing or revoked license is inactive and this function must
  ///  return `false` upon it. Under some license terms, a license may become
  ///  inactive because some ancestral license has been revoked. In that case,
  ///  this function should return `false`.
  /// @param _licenseId The identifier for the queried license
  /// @return Whether the queried license is active
  function isLicenseActive(uint256 _licenseId) external view returns (bool);

  /// @notice Retrieve the token identifier a license was issued upon.
  /// @dev Throws unless the license is active.
  /// @param _licenseId The identifier for the queried license
  /// @return The token identifier the queried license was issued upon
  function getLicenseTokenId(uint256 _licenseId) external view returns (uint256);

  /// @notice Retrieve the parent license identifier of a license.
  /// @dev Throws unless the license is active. If a license doesn&apos;t have a
  ///  parent license, return a special identifier not referring to any license
  ///  (such as 0).
  /// @param _licenseId The identifier for the queried license
  /// @return The parent license identifier of the queried license
  function getParentLicenseId(uint256 _licenseId) external view returns (uint256);

  /// @notice Retrieve the holder of a license.
  /// @dev Throws unless the license is active.   
  /// @param _licenseId The identifier for the queried license
  /// @return The holder address of the queried license
  function getLicenseHolder(uint256 _licenseId) external view returns (address);

  /// @notice Retrieve the URI of a license.
  /// @dev Throws unless the license is active.   
  /// @param _licenseId The identifier for the queried license
  /// @return The URI of the queried license
  function getLicenseURI(uint256 _licenseId) external view returns (string memory);

  /// @notice Retrieve the revoker address of a license.
  /// @dev Throws unless the license is active.   
  /// @param _licenseId The identifier for the queried license
  /// @return The revoker address of the queried license
  function getLicenseRevoker(uint256 _licenseId) external view returns (address);

  /// @notice Retrieve the root license identifier of an NFT.
  /// @dev Throws unless the queried NFT exists. If the NFT doesn&apos;t have a root
  ///  license tethered to it, return a special identifier not referring to any
  ///  license (such as 0).   
  /// @param _tokenId The identifier for the queried NFT
  /// @return The root license identifier of the queried NFT
  function getLicenseIdByTokenId(uint256 _tokenId) external view returns (uint256);
  
  /// @notice Create a new license.
  /// @dev Throws unless the NFT `_tokenId` exists. Throws unless the parent
  ///  license `_parentLicenseId` is active, or `_parentLicenseId` is a special
  ///  identifier not referring to any license (such as 0) and the NFT
  ///  `_tokenId` doesn&apos;t have a root license tethered to it. Throws unless the
  ///  message sender is eligible to create the license, i.e., either the
  ///  license to be created is a root license and `msg.sender` is the NFT owner,
  ///  or the license to be created is a sublicense and `msg.sender` is the holder
  ///  of the parent license. 
  /// @param _tokenId The identifier for the NFT the license is issued upon
  /// @param _parentLicenseId The identifier for the parent license
  /// @param _licenseHolder The address of the license holder
  /// @param _uri The URI of the license terms
  /// @param _revoker The revoker address
  /// @return The identifier of the created license
  function createLicense(uint256 _tokenId, uint256 _parentLicenseId, address _licenseHolder, string memory _uri, address _revoker) external returns (uint256);

  /// @notice Revoke a license.
  /// @dev Throws unless the license is active and the message sender is the
  ///  eligible revoker. This function should be used for revoking both root
  ///  licenses and sublicenses. Note that if a root license is revoked, the
  ///  NFT should be transferred back to its creator.
  /// @param _licenseId The identifier for the queried license
  function revokeLicense(uint256 _licenseId) external;
  
  /// @notice Transfer a sublicense.
  /// @dev Throws unless the sublicense is active and `msg.sender` is the license
  ///  holder. Note that the root license of an NFT should be tethered to and
  ///  transferred with the NFT. Whenever an NFT is transferred by calling the
  ///  ERC721 `transfer` function, the holder of the root license should be
  ///  changed to the new NFT owner.
  /// @param _licenseId The identifier for the queried license
  /// @param _licenseHolder The new license holder
  function transferSublicense(uint256 _licenseId, address _licenseHolder) external;
}
```

Licenses to an NFT in general have a tree structure as below:

![The license tree](/EIPs/assets/eip-5218/license-tree.png)

There is one root license to the NFT itself, granting the NFT owner some rights to the linked work. The NFT owner (i.e., the root license holder) may create sublicenses, holders of which may also create sublicenses recursively.

The full log of license creation, transfer, and revocation *must* be traceable via event logs. Therefore, all license creations and transfers *must* emit a corresponding log event. Revocation may differ a bit. An implementation of this EIP may emit a `Revoke` event only when a license is revoked in a function call, or for every revoked license, both are sufficient to trace the status of all licenses. The former costs less gas if revoking a license automatically revokes all sublicenses under it, while the latter is efficient in terms of interrogation of a license status. Implementers should make the tradeoffs depending on their license terms.

The `revoker` of a license may be the licensor, the license holder, or a smart contract address which calls the `revokeLicense` function when some conditions are met. Implementers should be careful with the authorization, and may make the `revoker` smart contract forward compatible with transfers by not hardcoding the addresses of `licensor` or `licenseHolder`.

The license `URI` may point to a JSON file that conforms to the &quot;ERC-5218 Metadata JSON Schema&quot; as below, which adopts the &quot;three-layer&quot; design of the Creative Commons Licenses:

```json
{
    &quot;title&quot;: &quot;License Metadata&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;legal-code&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;The legal code of the license.&quot;
        },
        &quot;human-readable&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;The human readable license deed.&quot;
        },
        &quot;machine-readable&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;The machine readable code of the license that can be recognized by software, such as CC REL.&quot;
        }
    }
}
```

Note that this EIP doesn&apos;t include a function to update license URI so the license terms should be persistent by default. It is recommended to store the license metadata on a decentralized storage service such as IPFS or adopt the IPFS-style URI which encodes the hash of the metadata for integrity verification. On the other hand, license updatability, if necessary in certain scenarios, can be realized by revoking the original license and creating a new license, or adding a updating function, the eligibile caller of which must be carefully specified in the license and securely implemented in the smart contract.

The `supportsInterface` method MUST return `true` when called with `0xac7b5ca9`.

## Rationale

This EIP aims to allow tracing all licenses to an NFT to facilitate right management. The ERC-721 standard only logs the property but not the legal rights tethered to NFTs. Even when logging the license via the optional ERC-721 Metadata extension, sublicenses are not traceable, which doesn&apos;t comply with the transparency goals of Web3. Some implementations attempt to get around this limitation by minting NFTs to represent a particular license, such as the BAYC #6068 Royalty-Free Usage License. This is not an ideal solution because the linking between different licenses to an NFT is ambiguous. An auditor has to investigate all NFTs in the blockchain and inspect the metadata which hasn&apos;t been standardized in terms of sublicense relationship. To avoid these problems, this EIP logs all licenses to an NFT in a tree data structure, which is compatible with ERC-721 and allows efficient traceability.

This EIP attempts to tether NFTs with copyright licenses to the creative work by default and is not subject to the high legal threshold for copyright ownership transfers which require an explicit signature from the copyright owner. To transfer and track copyright ownership, one may possibly integrate ERC-5218 and [ERC-5289](/EIPs/EIPS/eip-5289) after careful scrutinizing and implement a smart contract that atomically (1) signs the legal contract via ERC-5289, and (2) transfers the NFT together with the copyright ownership via ERC-5218. Either both take place or both revert.

## Backwards Compatibility

This standard is compatible with the current ERC-721 standards: a contract can inherit from both ERC-721 and ERC-5218 at the same time.

## Test Cases

Test cases are available [here](/EIPs/assets/eip-5218/contracts/test/Contract.t.sol).

## Reference Implementation

A reference implementation maintains the following data structures:

```solidity
  struct License {
    bool active; // whether the license is active
    uint256 tokenId; // the identifier of the NFT the license is tethered to
    uint256 parentLicenseId; // the identifier of the parent license
    address licenseHolder; // the license holder
    string uri; // the license URI
    address revoker; // the license revoker
  }
  mapping(uint256 =&gt; License) private _licenses; // maps from a license identifier to a license object
  mapping(uint256 =&gt; uint256) private _licenseIds; // maps from an NFT to its root license identifier
```

Each NFT has a license tree and starting from each license, one can trace back to the root license via `parentLicenseId` along the path. 

In the reference implementation, once a license is revoked, all sublicenses under it are revoked. This is realized in a *lazy* manner for lower gas cost, i.e., assign `active=false` only for licenses that are explicitly revoked in a `revokeLicense` function call. Therefore, `isLicenseActive` returns `true` only if all its ancestral licenses haven&apos;t been revoked.

For non-root licenses, the creation, transfer and revocation are straightforward:

1. Only the holder of an active license can create sublicenses.
2. Only the holder of an active license can transfer it to a different license holder. 
3. Only the revoker of an active license can revoke it.

The root license must be compatible with `ERC-721`: 

1. When an NFT is minted, a license is granted to the NFT owner.
2. When an NFT is transferred, the license holder is changed to the new owner of the NFT.
3. When a root license is revoked, the NFT is returned to the NFT creator, and the NFT creator may later transfer it to a new owner with a new license.

The complete implementation can be found [here](/EIPs/assets/eip-5218/contracts/src/RightsManagement.sol). 

In addition, the [Token-Bound NFT License](/EIPs/assets/eip-5218/ic3license/ic3license.pdf) is specifically designed to work with this interface and provides a reference to the language of NFT licenses.

## Security Considerations

Implementors of the `IERC5218` standard must consider thoroughly the permissions they give to `licenseHolder` and `revoker`. If the license is ever to be transferred to a different license holder, the `revoker` smart contract should not hardcode the `licenseHolder` address to avoid undesirable scenarios.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Mon, 11 Jul 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5218</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5218</guid>
      </item>
    
      <item>
        <title>Contract Resource Requests</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/pr-5219-discussion-contract-rest/9907</comments>
        
        <description>## Abstract

This EIP standardizes an interface to make resource requests to smart contracts and to receive HTTP-like responses.

## Motivation

Ethereum is the most-established blockchain for building decentralized applications (referred to as `DApp`s). Due to this, the Ethereum DApp ecosystem is very diverse. However, one issue that plagues DApps is the fact that they are not fully decentralized. Specifically, to interface a &quot;decentralized&quot; application, one first needs to access a *centralized* website containing the DApp&apos;s front-end code, presenting a few issues. The following are some risks associated with using centralized websites to interface with decentralized applications:

- Trust Minimization: An unnecessarily large number of entities need to be trusted
- Censorship: A centralized website is not resistant to being censored
- Permanence: The interface may not have a mechanism that permits it to be permanently stored
- Interoperability: Smart Contracts cannot directly interact with DApp interfaces
  
## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### Name Resolution

EIPs that propose a name resolution mechanism MAY reference this EIP and MAY recommend that clients support their mechanism. Clients MAY also support regular DNS, as defined in RFC 1034 and RFC 1035.

### Separation of Concerns

It is RECOMMENDED to separate the application logic from the front-end logic (the contract implementing the interface defined in [Contract Interface](#contract-interface)).

### Contract Interface

DApp contracts MUST implement the interface defined in the following file: [Contract Interface](/EIPs/assets/eip-5219/IDecentralizedApp.sol).

### Note to Implementers

To save gas costs, it is recommended to use the `message/external-body` MIME-type, which allows you to point to data that the smart contract might not have access to. For example, the following response would tell a client to fetch the data off of IPFS:

```yaml
statusCode: 200
body: THIS IS NOT REALLY THE BODY!
headers:
  - key: Content-type
    value: message/external-body; access-type=URL; URL=&quot;ipfs://11148a173fd3e32c0fa78b90fe42d305f202244e2739&quot;
```

## Rationale

The `request` method was chosen to be readonly because all data should be sent to the contract from the parsed DApp. Here are some reasons why:

- Submitting a transaction to send a request would be costly and would require waiting for the transaction to be mined, resulting in bad user experience.
- Complicated front-end logic should not be stored in the smart contract, as it would be costly to deploy and would be better run on the end-user&apos;s machine.
- Separation of Concerns: the front-end contract shouldn&apos;t have to worry about interacting with the back-end smart contract.
- Other EIPs can be used to request state changing operations in conjunction with a `307 Temporary Redirect` status code.

Instead of mimicking a full HTTP request, a highly slimmed version was chosen for the following reasons:

- The only particularly relevant HTTP method is `GET`
- Query parameters can be encoded in the resource.
- Request headers are, for the most part, unnecessary for `GET` requests.

## Backwards Compatibility

This EIP is backwards compatible with all standards listed in the [Name Resolution](#name-resolution) section.

## Security Considerations

The normal security considerations of accessing normal URLs apply here, such as potential privacy leakage by following `3XX` redirects.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 10 Jul 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5219</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5219</guid>
      </item>
    
      <item>
        <title>Smart Contract Executable Proposal Interface</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-5247-executable-proposal-standard/9938</comments>
        
        <description>## Abstract

This EIP presents an interface for &quot;smart contract executable proposals&quot;: proposals that are submitted to, recorded on, and possibly executed on-chain. Such proposals include a series of information about
function calls including the target contract address, ether value to be transmitted, gas limits and calldatas.

## Motivation

It is oftentimes necessary to separate the code that is to be executed from the actual execution of the code.

A typical use case for this EIP is in a Decentralized Autonomous Organization (DAO). A proposer will create a smart proposal and advocate for it. Members will then choose whether or not to endorse the proposal and vote accordingly (see [ERC-1202](/EIPs/EIPS/eip-1202)). Finally, when consensus has been formed, the proposal is executed.

A second typical use-case is that one could have someone who they trust, such as a delegator, trustee, or an attorney-in-fact, or any bilateral collaboration format, where a smart proposal will be first composed, discussed, approved in some way, and then put into execution.

A third use-case is that a person could make an &quot;offer&quot; to a second person, potentially with conditions. The smart proposal can be presented as an offer and the second person can execute it if they choose to accept this proposal.

## Specification

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.

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

interface IERC5247 {
    event ProposalCreated(
        address indexed proposer,
        uint256 indexed proposalId,
        address[] targets,
        uint256[] values,
        uint256[] gasLimits,
        bytes[] calldatas,
        bytes extraParams
    );

    event ProposalExecuted(
        address indexed executor,
        uint256 indexed proposalId,
        bytes extraParams
    );

    function createProposal(
        uint256 proposalId,
        address[] calldata targets,
        uint256[] calldata values,
        uint256[] calldata gasLimits,
        bytes[] calldata calldatas,
        bytes calldata extraParams
    ) external returns (uint256 registeredProposalId);

    function executeProposal(uint256 proposalId, bytes calldata extraParams) external;
}
```

## Rationale

* Originally, this interface was part of [ERC-1202](/EIPs/EIPS/eip-1202). However, the proposal itself can potentially have many use cases outside of voting. It is possible that voting may not need to be upon a proposal in any particular format. Hence, we decided to *decouple the voting interface and proposal interface*.
* Arrays were used for `target`s, `value`s, `calldata`s instead of single variables, allowing a proposal to carry arbitrarily many function calls.
* `registeredProposalId` is returned in `createProposal` so the standard can support implementation to decide their own format of proposal id.

## Test Cases

A simple test case can be found as

```ts
        it(&quot;Should work for a simple case&quot;, async function () {
            const { contract, erc721, owner } = await loadFixture(deployFixture);
            const callData1 = erc721.interface.encodeFunctionData(&quot;mint&quot;, [owner.address, 1]);
            const callData2 = erc721.interface.encodeFunctionData(&quot;mint&quot;, [owner.address, 2]);
            await contract.connect(owner)
                .createProposal(
                    0,
                    [erc721.address, erc721.address],
                    [0,0],
                    [0,0],
                    [callData1, callData2],
                    []);
            expect(await erc721.balanceOf(owner.address)).to.equal(0);
            await contract.connect(owner).executeProposal(0, []);
            expect(await erc721.balanceOf(owner.address)).to.equal(2);
        });
```

See [testProposalRegistry.ts](/EIPs/assets/eip-5247/testProposalRegistry.ts) for the whole test set.

## Reference Implementation

A simple reference implementation can be found.

```solidity
    function createProposal(
        uint256 proposalId,
        address[] calldata targets,
        uint256[] calldata values,
        uint256[] calldata gasLimits,
        bytes[] calldata calldatas,
        bytes calldata extraParams
    ) external returns (uint256 registeredProposalId) {
        require(targets.length == values.length, &quot;GeneralForwarder: targets and values length mismatch&quot;);
        require(targets.length == gasLimits.length, &quot;GeneralForwarder: targets and gasLimits length mismatch&quot;);
        require(targets.length == calldatas.length, &quot;GeneralForwarder: targets and calldatas length mismatch&quot;);
        registeredProposalId = proposalCount;
        proposalCount++;

        proposals[registeredProposalId] = Proposal({
            by: msg.sender,
            proposalId: proposalId,
            targets: targets,
            values: values,
            calldatas: calldatas,
            gasLimits: gasLimits
        });
        emit ProposalCreated(msg.sender, proposalId, targets, values, gasLimits, calldatas, extraParams);
        return registeredProposalId;
    }
    function executeProposal(uint256 proposalId, bytes calldata extraParams) external {
        Proposal storage proposal = proposals[proposalId];
        address[] memory targets = proposal.targets;
        string memory errorMessage = &quot;Governor: call reverted without message&quot;;
        for (uint256 i = 0; i &lt; targets.length; ++i) {
            (bool success, bytes memory returndata) = proposal.targets[i].call{value: proposal.values[i]}(proposal.calldatas[i]);
            Address.verifyCallResult(success, returndata, errorMessage);
        }
        emit ProposalExecuted(msg.sender, proposalId, extraParams);
    }
```

See [ProposalRegistry.sol](/EIPs/assets/eip-5247/ProposalRegistry.sol) for more information.

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 13 Jul 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5247</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5247</guid>
      </item>
    
      <item>
        <title>Account-bound Finance</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/pr-5252-discussion-account-bound-finance/10027</comments>
        
        <description>## Abstract

This EIP proposes a form of smart contract design pattern and a new type of account abstraction on how one&apos;s finance should be managed, ensuring transparency of managing investments and protection with self-sovereignty even from its financial operators. This EIP enables greater self-sovereignty of one&apos;s assets using a personal finance contract for each individual. The separation between an investor&apos;s funds and the operation fee is clearly specified in the personal smart contract, so investors can ensure safety from arbitrary loss of funds by the operating team&apos;s control.

This EIP extends [ERC-5114](/EIPs/EIPS/eip-5114) to further enable transferring fund to other accounts for mobility between managing multiple wallets.

## Motivation

Decentralized finance (DeFi) faces a trust issue. Smart contracts are often proxies, with the actual logic of the contract hidden away in a separate logic contract. Many projects include a multi-signature &quot;wallet&quot; with unnecessarily-powerful permissions. And it is not possible to independently verify that stablecoins have enough real-world assets to continue maintaining their peg, creating a large loss of funds (such as happened in the official bankruptcy announcement of Celsius and UST de-pegging and anchor protocol failure). One should not trust exchanges or other third parties with one&apos;s own investments with the operators&apos; clout in Web3.0.

Smart contracts are best implemented as a promise between two parties written in code, but current DeFi contracts are often formed using less than 7 smart contracts to manage their whole investors&apos; funds, and often have a trusted key that has full control. This is evidently an issue, as investors have to trust contract operators with their funds, meaning that users do not actually own their funds.

The pattern with personal finance contract also offers more transparency than storing mixed fund financial data in the operating team&apos;s contract. With a personal finance contract, an account&apos;s activity is easier to track than one global smart contract&apos;s activity. The pattern introduces a Non-Fungiible Account-Bound Token (ABT) to store credentials from the personal finance contract.

### Offchain-identity vs Soul-bound token on credentials

This EIP provides a better alternative to off-chain identity solutions which take over the whole system because their backends eventually rely on the trust of the operator, not cryptographic proof (e.g. Proof-of-work, Proof-of-stake, etc). Off-chain identity as credentials are in direct opposition to the whole premise of crypto. Soulbound tokens are a better, verifiable credential, and data stored off-chain is only to store token metadata.

## Specification

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.

The specification consists of two patterns for **Interaction** and **Governance**.

### Interaction

#### Interfaces

The interaction pattern consists of 4 components for interaction; manager, factory, finance, account-bound token, and extension.

Interaction contract pattern is defined with these contracts:

- A soul-bound or account bound token contract to give access to interact with a financial contract with credentials
- A manager contract that interacts first contact with an investor
- A factory contract that creates a financial contract for each user
- A finance contract that can interact with the investor

#### Requirements

A soul-bound or account bound token contract is defined with these properties:

1. It SHALL be non-fungible and MUST satisfy [ERC-721](/EIPs/EIPS/eip-721).
2. Credentials SHOULD be represented with its metadata with `tokenURI()` function.
3. It MUST only reference factory to verify its minting.
4. If it is transferrable, it is account-bound. If not, it is soul-bound.

A manager contract is defined with these properties:

1. It MUST be the only kind of contract which calls factory to create.
2. It SHOULD store all related configurations for financial parameters.

A factory contract is defined with these properties:

1. It SHALL clone the finance contract with uniform implementation.
2. It MUST be the only contract that can mint account-bound token.
3. It MUST keep an recent id of account bound token.

A finance contract is defined with these properties:

1. A finance contract MUST only be initialized once from factory contract in constructor.
2. Funds in the contract SHALL NOT be transferred to other contracts nor accounts unless sender who owns soul-bound or account bound token signs to do so.
3. Every state-changing function of the smart contract MUST only accept sender who owns soul-bound or account bound-token except global function(e.g. liquidation).
4. Global function SHOULD be commented as `/* global */` to clarify the function is can be accessed with anyone.
5. Each finance contract SHOULD be able to represent transaction that has happened only with those who had account-bound token.
6. If soul-bound token is used for access, the finance contract MUST be able to represent transaction that has happened only between whom had the private key and the finance contract.

#### Contracts

![Diagram](/EIPs/assets/eip-5252/media/media.svg)

&lt;center&gt;
Contract Diagram of [ERC-5252](/EIPs/EIPS/eip-5252)
&lt;/center&gt;

**`Manager`**: **`Manager`** contract acts as an entry point to interact with the investor. The contract also stores parameters for **`Finance`** contract.

**`Factory`**: **`Factory`** contract manages contract bytecode to create for managing investor&apos;s fund and clones **`Finance`** contract on **`Manager`** contract&apos;s approval. It also mints account-bound tokens to interact with the `Finance` contract.

**`Finance`**: **`Finance`** contract specifies all rules on managing an investor&apos;s fund. The contract is only accessible with an account that has an Account-bound token. When an investor deposits a fund to **`Manager`** contract, the contract sends the fund to **`Finance`** contract account after separating fees for operation.

**`Account-bound token`**: **`Account-bound token`** contract in this EIP can bring the **`Finance`** contract&apos;s data and add metadata. For example, if there is a money market lending
**`Finance`** contract, its **`Account-bound token`** can show how much balance is in agreement using SVG.

**`Extension`**: **`Extension`** contract is another contract that can utilize locked funds in **`Finance`** contract. The contract can access with **`Finance`** contract on operator&apos;s approval managed in **`Manager`** contract. Example use case of `Extension` can be a membership.

**`Metadata`**: **`Metadata`** contract is the contract where it stores metadata related to account credentials. Credential related data are stored with specific key. Images are usually displayed as SVG, but offchain image is possible.

---

### Governance

The governance pattern consists of 2 components; influencer and governor.

#### Interfaces

#### Requirements

An influencer contract is defined with these properties:

1. The contract SHALL manage multiplier for votes.
2. The contract SHALL set a decimal to calculated normalized scores.
3. The contract SHALL set a function where governance can decide factor parameters.

A governor contract is defined with these properties:

1. The contract MUST satisfy Governor contract from OpenZeppelin.
2. The contract SHALL refer influencer contract for multiplier
3. The contract MUST limit transfer of account bound token once claimed for double vote prevention.

#### From Token Governance To Contribution Based Governance

|             | Token Governance             | Credential-based Governance        |
| ----------- | ---------------------------- | ---------------------------------- |
| Enforcement | More tokens, more power      | More contribution, More power      |
| Incentives  | More tokens, more incentives | More contribution, more incentives |
| Penalty     | No penalty                   | Loss of power                      |
| Assignment  | One who holds the token      | One who has the most influence     |

&lt;center&gt;
Token Governance vs Credential Based Governance
&lt;/center&gt;

Token governance is not sustainable in that it gives **more** power to &quot;those who most want to rule&quot;. Any individual who gets more than 51% of the token supply can forcefully take control.

New governance that considers contributions to the protocol is needed because:

- **Rulers can be penalized on breaking the protocol**
- **Rulers can be more effectively incentivized on maintaining the protocol**

The power should be given to &quot;those who are most responsible&quot;. Instead of locked or owned tokens, voting power is determined with contributions marked in Account Bound Tokens (ABT). This EIP defines this form of voting power as **`Influence`**.

#### Calculating Influence

**`Influence`** is a multiplier on staked tokens that brings more voting power of a DAO to its contributors. To get **`Influence`**, a score is calculated on weighted contribution matrix. Then, the score is normalized to give a member&apos;s position in whole distribution. Finally, the multiplier is determined on the position in every community members.

#### Calculating score

The weights represent relative importance on each factor. The total importance is the total sum of the factors. More factors that can be normalized at the time of submitting proposal can be added by community.

|     | Description                                                                               |
| --- | ----------------------------------------------------------------------------------------- |
| α   | Contribution value per each **`Finance`** contract from current proposal                  |
| β   | Time they maintained **`Finance`** per each contract from current timestamp of a proposal |

```math
(score per each ABT) = α * (contribution value) + β * (time that abt was maintained from now)
```

#### Normalization

Normalization is applied for data integrity on user&apos;s contribution in a DAO.
Normalized score can be calculated from the state of submitting a proposal

```math
(Normalized score per each ABT) = α * (contribution value)/(total contribution value at submitting tx) + β * (time that abt was maintained)/(time passed from genesis to proposal creation)
```

and have a value between 0 and 1 (since α + β = 1).

#### Multiplier

The multiplier is determined linearly from base factor (b) and multiplier(m).

The equation for influence is :

```math
(influence) = m * (sum(normalized_score))
```

#### Example

For example, if a user has 3 **`Account-bound tokens`** with normalized score of each 1.0, 0.5, 0.3 and the locked token is 100, and multiplier is 0.5 and base factor is 1.5. Then the total influence is

````math
0.5 * {(1.0 + 0.5 + 0.3) / 3} + 1.5 = 1.8

 The total voting power would be

```math
(voting power) = 1.8 * sqrt(100)  = 18
````

#### Stakers vs Enforcers

|              | Stakers                           | Enforcers                                                                               |
| ------------ | --------------------------------- | --------------------------------------------------------------------------------------- |
| Role         | stake governance token for voting | Contributed on the system, can make proposal to change rule, more voting power like 1.5 |
| Populations  | many                              | small                                                                                   |
| Contribution | Less effect                       | More effect                                                                             |
| Influence    | sqrt(locked token)                | Influence \* sqrt(locked token)                                                         |

&lt;center&gt;
Stakers vs Enforcers
&lt;/center&gt;

**Stakers**: Stakers are people who vote to enforcers&apos; proposals and get dividend for staked tokens

**Enforcers**: Enforcers are people who takes risk on managing protocol and contributes to the protocol by making a proposal and change to it.

#### Contracts

**`Influencer`**: An **`Influencer`** contract stores influence configurations and measures the contribution of a user from his activities done in a registered Account Bound Token contract. The contract puts a lock on that Account Bound Token until the proposal is finalized.

**`Governor`**: **`Governor`** contract is compatible with the current governor contract in OpenZeppelin. For its special use case, it configures factors where the influencer manages and has access to changing parameters of **`Manager`** configs. Only the `Enforcer` can propose new parameters.

## Rationale

### Gas saving for end user

The gas cost of using multiple contracts (as opposed to a single one) actually saves gas long-run if the clone factory pattern is applied. One contract storing users&apos; states globally means each user is actually paying for the storage cost of other users after interacting with the contract. This, for example, means that MakerDAO&apos;s contract operating cost is sometimes over 0.1 ETH, limitimg users&apos; minimum deposit for CDP in order to save gas costs. To solve inefficient n-times charging gas cost interaction for future users, one contract per user is used.

#### Separation between investor&apos;s and operation fund

The separation between an investor&apos;s funds and operation fee is clearly specified in the smart contract, so investors can ensure safety from arbitrary loss of funds by the operating team&apos;s control.

## Backwards Compatibility

This EIP has no known backward compatibility issues.

## Reference Implementation

[Reference implementation](/EIPs/assets/eip-5252/) is a simple deposit account contract as `Finance` contract and its contribution value α is measured with deposit amount with ETH.

## Security Considerations

- **`Factory`** contracts must ensure that each **`Finance`** contract is registered in the factory and check that **`Finance`** contracts are sending transactions related to their bounded owner.

- Reentrancy attack guard should be applied or change state before delegatecall in each user function in **`Manager`** contract or **`Finance`** contract. Otherwise, **`Finance`** can be generated as double and ruin whole indices.

- Once a user locks influence on a proposal&apos;s vote, an **`Account Bound Token`** cannot be transferred to another wallet. Otherwise, double influence can happen.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 29 Jun 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5252</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5252</guid>
      </item>
    
      <item>
        <title>Retrieval of EIP-712 domain</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5267-retrieval-of-eip-712-domain/9951</comments>
        
        <description>## Abstract

This EIP complements [EIP-712](/EIPs/EIPS/eip-712) by standardizing how contracts should publish the fields and values that describe their domain. This enables applications to retrieve this description and generate appropriate domain separators in a general way, and thus integrate EIP-712 signatures securely and scalably.

## Motivation

EIP-712 is a signature scheme for complex structured messages. In order to avoid replay attacks and mitigate phishing, the scheme includes a &quot;domain separator&quot; that makes the resulting signature unique to a specific domain (e.g., a specific contract) and allows user-agents to inform end users the details of what is being signed and how it may be used. A domain is defined by a data structure with fields from a predefined set, all of which are optional, or from extensions. Notably, EIP-712 does not specify any way for contracts to publish which of these fields they use or with what values. This has likely limited adoption of EIP-712, as it is not possible to develop general integrations, and instead applications find that they need to build custom support for each EIP-712 domain. A prime example of this is [EIP-2612](/EIPs/EIPS/eip-2612) (permit), which has not been widely adopted by applications even though it is understood to be a valuable improvement to the user experience. The present EIP defines an interface that can be used by applications to retrieve a definition of the domain that a contract uses to verify EIP-712 signatures.

## Specification

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.

Compliant contracts MUST define `eip712Domain` exactly as declared below. All specified values MUST be returned even if they are not used, to ensure proper decoding on the client side.

```solidity
function eip712Domain() external view returns (
    bytes1 fields,
    string name,
    string version,
    uint256 chainId,
    address verifyingContract,
    bytes32 salt,
    uint256[] extensions
);
```

The return values of this function MUST describe the domain separator that is used for verification of EIP-712 signatures in the contract. They describe both the form of the `EIP712Domain` struct (i.e., which of the optional fields and extensions are present) and the value of each field, as follows.

- `fields`: A bit map where bit `i` is set to 1 if and only if domain field `i` is present (`0 ≤ i ≤ 4`). Bits are read from least significant to most significant, and fields are indexed in the order that is specified by EIP-712, identical to the order in which they are listed in the function type.
- `name`, `version`, `chainId`, `verifyingContract`, `salt`: The value of the corresponding field in `EIP712Domain`, if present according to `fields`. If the field is not present, the value is unspecified. The semantics of each field is defined in EIP-712.
- `extensions`: A list of EIP numbers, each of which MUST refer to an EIP that extends EIP-712 with new domain fields, along with a method to obtain the value for those fields, and potentially conditions for inclusion. The value of `fields` does not affect their inclusion.

The return values of this function (equivalently, its EIP-712 domain) MAY change throughout the lifetime of a contract, but changes SHOULD NOT be frequent. The `chainId` field, if used, SHOULD change to mirror the [EIP-155](/EIPs/EIPS/eip-155) id of the underlying chain. Contracts MAY emit the event `EIP712DomainChanged` defined below to signal that the domain could have changed.

```solidity
event EIP712DomainChanged();
```

## Rationale

A notable application of EIP-712 signatures is found in EIP-2612 (permit), which specifies a `DOMAIN_SEPARATOR` function that returns a `bytes32` value (the actual domain separator, i.e., the result of `hashStruct(eip712Domain)`). This value does not suffice for the purposes of integrating with EIP-712, as the RPC methods defined there receive an object describing the domain and not just the separator in hash form. Note that this is not a flaw of the RPC methods, it is indeed part of the security proposition that the domain should be validated and informed to the user as part of the signing process. On its own, a hash does not allow this to be implemented, given it is opaque. The present EIP fills this gap in both EIP-712 and EIP-2612.

Extensions are described by their EIP numbers because EIP-712 states: &quot;Future extensions to this standard can add new fields [...] new fields should be proposed through the EIP process.&quot;

## Backwards Compatibility

This is an optional extension to EIP-712 that does not introduce backwards compatibility issues.

Upgradeable contracts that make use of EIP-712 signatures MAY be upgraded to implement this EIP.

User-agents or applications that use this EIP SHOULD additionally support those contracts that due to their immutability cannot be upgraded to implement it. The simplest way to achieve this is to hardcode common domains based on contract address and chain id. However, it is also possible to implement a more general solution by guessing possible domains based on a few common patterns using the available information, and selecting the one whose hash matches a `DOMAIN_SEPARATOR` or `domainSeparator` function in the contract.

## Reference Implementation

### Solidity Example

```solidity
pragma solidity 0.8.0;

contract EIP712VerifyingContract {
  function eip712Domain() external view returns (
      bytes1 fields,
      string memory name,
      string memory version,
      uint256 chainId,
      address verifyingContract,
      bytes32 salt,
      uint256[] memory extensions
  ) {
      return (
          hex&quot;0d&quot;, // 01101
          &quot;Example&quot;,
          &quot;&quot;,
          block.chainid,
          address(this),
          bytes32(0),
          new uint256[](0)
      );
  }
}
```

This contract&apos;s domain only uses the fields `name`, `chainId`, and `verifyingContract`, therefore the `fields` value is `01101`, or `0d` in hexadecimal.

Assuming this contract is on Ethereum mainnet and its address is 0x0000000000000000000000000000000000000001, the domain it describes is:

```json5
{
  name: &quot;Example&quot;,
  chainId: 1,
  verifyingContract: &quot;0x0000000000000000000000000000000000000001&quot;
}
```

### JavaScript

A domain object can be constructed based on the return values of an `eip712Domain()` invocation.

```javascript
/** Retrieves the EIP-712 domain of a contract using EIP-5267 without extensions. */
async function getDomain(contract) {
  const { fields, name, version, chainId, verifyingContract, salt, extensions } =
    await contract.eip712Domain();

  if (extensions.length &gt; 0) {
    throw Error(&quot;Extensions not implemented&quot;);
  }

  return buildBasicDomain(fields, name, version, chainId, verifyingContract, salt);
}

const fieldNames = [&apos;name&apos;, &apos;version&apos;, &apos;chainId&apos;, &apos;verifyingContract&apos;, &apos;salt&apos;];

/** Builds a domain object without extensions based on the return values of `eip712Domain()`. */
function buildBasicDomain(fields, name, version, chainId, verifyingContract, salt) {
  const domain = { name, version, chainId, verifyingContract, salt };

  for (const [i, field] of fieldNames.entries()) {
    if (!(fields &amp; (1 &lt;&lt; i))) {
      delete domain[field];
    }
  }

  return domain;
}
```

#### Extensions

Suppose EIP-XYZ defines a new field `subdomain` of type `bytes32` and a function `getSubdomain()` to retrieve its value.

The function `getDomain` from above would be extended as follows.

```javascript
/** Retrieves the EIP-712 domain of a contract using EIP-5267 with support for EIP-XYZ. */
async function getDomain(contract) {
  const { fields, name, version, chainId, verifyingContract, salt, extensions } =
    await contract.eip712Domain();

  const domain = buildBasicDomain(fields, name, version, chainId, verifyingContract, salt);

  for (const n of extensions) {
    if (n === XYZ) {
      domain.subdomain = await contract.getSubdomain();
    } else {
      throw Error(`EIP-${n} extension not implemented`);
    }
  }

  return domain;
}
```

Additionally, the type of the `EIP712Domain` struct needs to be extended with the `subdomain` field. This is left out of scope of this reference implementation.

## Security Considerations

While this EIP allows a contract to specify a `verifyingContract` other than itself, as well as a `chainId` other than that of the current chain, user-agents and applications should in general validate that these do match the contract and chain before requesting any user signatures for the domain. This may not always be a valid assumption.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 14 Jul 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5267</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5267</guid>
      </item>
    
      <item>
        <title>ERC Detection and Discovery</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc5269-human-readable-interface-detection/9957</comments>
        
        <description>## Abstract

An interface for better identification and detection of ERCs by number.
It designates a field called `majorERCIdentifier` which is normally known or referred to as &quot;ERC number&quot;. For example, [ERC-721](/EIPs/EIPS/eip-721) has a `majorERCIdentifier = 721`. This ERC has a `majorERCIdentifier = 5269`.

Calling it a `majorERCIdentifier` instead of `ERCNumber` makes it future-proof: anticipating there is a possibility where future ERCs are not numbered or if we want to incorporate other types of standards.

It also proposes a new concept of `minorERCIdentifier` which is left for authors of
individual ERC to define. For example, ERC-721&apos;s author may define `ERC721Metadata`
interface as `minorERCIdentifier= keccak256(&quot;ERC721Metadata&quot;)`.

It also proposes an event to allow smart contracts to optionally declare the ERCs they support.

## Motivation

This ERC is created as a competing standard for [ERC-165](/EIPs/EIPS/eip-165).

Here are the major differences between this ERC and [ERC-165](/EIPs/EIPS/eip-165).

1. [ERC-165](/EIPs/EIPS/eip-165) uses the hash of a method&apos;s signature which declares the existence of one method or multiple methods,
therefore it requires at least one method to *exist* in the first place. In some cases, some ERC interfaces do not have a method, such as some ERCs related to data format and signature schemes or the &quot;Soul-Bound-ness&quot; aka SBT which could just revert a transfer call without needing any specific method.
1. [ERC-165](/EIPs/EIPS/eip-165) doesn&apos;t provide query ability based on the caller.
The compliant contract of this ERC will respond to whether it supports certain ERC *based on* a given caller.

Here is the motivation for this ERC given ERC-165 already exists:

1. Using ERC numbers improves human readability as well as make it easier to work with named contracts such as ENS.

2. Instead of using an ERC-165 identifier, we have seen an increasing interest to use ERC numbers as the way to identify or specify an ERC. For example

- [ERC-5267](/EIPs/EIPS/eip-5267) specifies `extensions` to be a list of ERC numbers.
- [ERC-600](/EIPs/EIPS/eip-600), and [ERC-601](/EIPs/EIPS/eip-601) specify an `ERC` number in the `m / purpose&apos; / subpurpose&apos; / ERC&apos; / wallet&apos;` path.
- [ERC-5568](/EIPs/EIPS/eip-5568) specifies `The instruction_id of an instruction defined by an ERC MUST be its ERC number unless there are exceptional circumstances (be reasonable)`
- [ERC-6120](/EIPs/EIPS/eip-6120) specifies `struct Token { uint eip; ..., }` where `uint eip` is an ERC number to identify ERCs.
- [ERC-867](/EIPs/EIPS/eip-867) (Stagnant) proposes creating an `erpId`, described as a string identifier for that ERP, likely based on the associated ERC number.

3. Having an ERC/ERC number detection interface reduces the need for a lookup table in smart contract to
convert a function method or whole interface in any ERC in the bytes4 ERC-165 identifier into its respective ERC number and massively simplifies the way to specify ERC for behavior expansion.

4. We also recognize a smart contract might have different behavior given different caller accounts. One of the most notable use cases is that when using Transparent Upgradable Pattern, a proxy contract gives an Admin account and Non-Admin account different treatment when they call.

## Specification

In the following description, we use ERC and ERC interchangeably. This was because while most of the time the description applies to an ERC category of the Standards Track of ERC, the ERC number space is a subspace of ERC number space and we might sometimes encounter ERCs that aren&apos;t recognized as ERCs but has behavior that&apos;s worthy of a query.

1. Any compliant smart contract MUST implement the following interface

```solidity
// DRAFTv1
pragma solidity ^0.8.9;

interface IERC5269 {
  event OnSupportERC(
      address indexed caller, // when emitted with `address(0x0)` means all callers.
      uint256 indexed majorERCIdentifier,
      bytes32 indexed minorERCIdentifier, // 0 means the entire ERC
      bytes32 ercStatus,
      bytes extraData
  );

  /// @dev The core method of ERC Interface Detection
  /// @param caller, a `address` value of the address of a caller being queried whether the given ERC is supported.
  /// @param majorERCIdentifier, a `uint256` value and SHOULD BE the ERC number being queried. Unless superseded by future ERC, such ERC number SHOULD BE less or equal to (0, 2^32-1]. For a function call to `supportERC`, any value outside of this range is deemed unspecified and open to implementation&apos;s choice or for future ERCs to specify.
  /// @param minorERCIdentifier, a `bytes32` value reserved for authors of individual ERC to specify. For example the author of [ERC-721](/ERCS/eip-721) MAY specify `keccak256(&quot;ERC721Metadata&quot;)` or `keccak256(&quot;ERC721Metadata.tokenURI&quot;)` as `minorERCIdentifier` to be queried for support. Author could also use this minorERCIdentifier to specify different versions, such as ERC-712 has its V1-V4 with different behavior.
  /// @param extraData, a `bytes` for [ERC-5750](/ERCS/eip-5750) for future extensions.
  /// @return ercStatus, a `bytes32` indicating the status of ERC the contract supports.
  ///                    - For FINAL ERCs, it MUST return `keccak256(&quot;FINAL&quot;)`.
  ///                    - For non-FINAL ERCs, it SHOULD return `keccak256(&quot;DRAFT&quot;)`.
  ///                      During ERC procedure, ERC authors are allowed to specify their own
  ///                      ercStatus other than `FINAL` or `DRAFT` at their discretion such as `keccak256(&quot;DRAFTv1&quot;)`
  ///                      or `keccak256(&quot;DRAFT-option1&quot;)`and such value of ercStatus MUST be documented in the ERC body
  function supportERC(
    address caller,
    uint256 majorERCIdentifier,
    bytes32 minorERCIdentifier,
    bytes calldata extraData)
  external view returns (bytes32 ercStatus);
}
```

In the following description, `ERC_5269_STATUS` is set to be `keccak256(&quot;DRAFTv1&quot;)`.

In addition to the behavior specified in the comments of `IERC5269`:

1. Any `minorERCIdentifier=0` is reserved to be referring to the main behavior of the ERC being queried.
2. The Author of compliant ERC is RECOMMENDED to declare a list of `minorERCIdentifier` for their optional interfaces, behaviors and value range for future extension.
3. When this ERC is FINAL, any compliant contract MUST return an `ERC_5269_STATUS` for the call of `supportERC((any caller), 5269, 0, [])`

*Note*: at the current snapshot, the `supportERC((any caller), 5269, 0, [])` MUST return `ERC_5269_STATUS`.

4. Any complying contract SHOULD emit an `OnSupportERC(address(0), 5269, 0, ERC_5269_STATUS, [])` event upon construction or upgrade.
5. Any complying contract MAY declare for easy discovery any ERC main behavior or sub-behaviors by emitting an event of `OnSupportERC` with relevant values and when the compliant contract changes whether the support an ERC or certain behavior for a certain caller or all callers.
6. For any `ERC-XXX` that is NOT in `Final` status, when querying the `supportERC((any caller), xxx, (any minor identifier), [])`, it MUST NOT return `keccak256(&quot;FINAL&quot;)`. It is RECOMMENDED to return `0` in this case but other values of `ercStatus` is allowed. Caller MUST treat any returned value other than `keccak256(&quot;FINAL&quot;)` as non-final, and MUST treat 0 as strictly &quot;not supported&quot;.
7. The function `supportERC` MUST be mutability `view`, i.e. it MUST NOT mutate any global state of EVM.

## Rationale

1. When data type `uint256 majorERCIdentifier`, there are other alternative options such as:

- (1) using a hashed version of the ERC number,
- (2) use a raw number, or
- (3) use an ERC-165 identifier.

The pros for (1) are that it automatically supports any evolvement of future ERC numbering/naming conventions.
But the cons are it&apos;s not backward readable: seeing a `hash(ERC-number)` one usually can&apos;t easily guess what their ERC number is.

We choose the (2) in the rationale laid out in motivation.

2. We have a `bytes32 minorERCIdentifier` in our design decision. Alternatively, it could be (1) a number, forcing all ERC authors to define its numbering for sub-behaviors so we go with a `bytes32` and ask the ERC authors to use a hash for a string name for their sub-behaviors which they are already doing by coming up with interface name or method name in their specification.

3. Alternatively, it&apos;s possible we add extra data as a return value or an array of all ERC being supported but we are unsure how much value this complexity brings and whether the extra overhead is justified.

4. Compared to [ERC-165](/EIPs/EIPS/eip-165), we also add an additional input of `address caller`, given the increasing popularity of proxy patterns such as those enabled by [ERC-1967](/EIPs/EIPS/eip-1967). One may ask: why not simply use `msg.sender`? This is because we want to allow query them without transaction or a proxy contract to query whether interface ERC-`number` will be available to that particular sender.

1. We reserve the input `majorERCIdentifier` greater than or equals `2^32` in case we need to support other collections of standards which is not an ERC/ERC.

## Test Cases

```typescript

describe(&quot;ERC5269&quot;, function () {
  async function deployFixture() {
    // ...
  }

  describe(&quot;Deployment&quot;, function () {
    // ...
    it(&quot;Should emit proper OnSupportERC events&quot;, async function () {
      let { txDeployErc721 } = await loadFixture(deployFixture);
      let events = txDeployErc721.events?.filter(event =&gt; event.event === &apos;OnSupportERC&apos;);
      expect(events).to.have.lengthOf(4);

      let ev5269 = events!.filter(
        (event) =&gt; event.args!.majorERCIdentifier.eq(5269));
      expect(ev5269).to.have.lengthOf(1);
      expect(ev5269[0].args!.caller).to.equal(BigNumber.from(0));
      expect(ev5269[0].args!.minorERCIdentifier).to.equal(BigNumber.from(0));
      expect(ev5269[0].args!.ercStatus).to.equal(ethers.utils.id(&quot;DRAFTv1&quot;));

      let ev721 = events!.filter(
        (event) =&gt; event.args!.majorERCIdentifier.eq(721));
      expect(ev721).to.have.lengthOf(3);
      expect(ev721[0].args!.caller).to.equal(BigNumber.from(0));
      expect(ev721[0].args!.minorERCIdentifier).to.equal(BigNumber.from(0));
      expect(ev721[0].args!.ercStatus).to.equal(ethers.utils.id(&quot;FINAL&quot;));

      expect(ev721[1].args!.caller).to.equal(BigNumber.from(0));
      expect(ev721[1].args!.minorERCIdentifier).to.equal(ethers.utils.id(&quot;ERC721Metadata&quot;));
      expect(ev721[1].args!.ercStatus).to.equal(ethers.utils.id(&quot;FINAL&quot;));

      // ...
    });

    it(&quot;Should return proper ercStatus value when called supportERC() for declared supported ERC/features&quot;, async function () {
      let { erc721ForTesting, owner } = await loadFixture(deployFixture);
      expect(await erc721ForTesting.supportERC(owner.address, 5269, ethers.utils.hexZeroPad(&quot;0x00&quot;, 32), [])).to.equal(ethers.utils.id(&quot;DRAFTv1&quot;));
      expect(await erc721ForTesting.supportERC(owner.address, 721, ethers.utils.hexZeroPad(&quot;0x00&quot;, 32), [])).to.equal(ethers.utils.id(&quot;FINAL&quot;));
      expect(await erc721ForTesting.supportERC(owner.address, 721, ethers.utils.id(&quot;ERC721Metadata&quot;), [])).to.equal(ethers.utils.id(&quot;FINAL&quot;));
      // ...

      expect(await erc721ForTesting.supportERC(owner.address, 721, ethers.utils.id(&quot;WRONG FEATURE&quot;), [])).to.equal(BigNumber.from(0));
      expect(await erc721ForTesting.supportERC(owner.address, 9999, ethers.utils.hexZeroPad(&quot;0x00&quot;, 32), [])).to.equal(BigNumber.from(0));
    });

    it(&quot;Should return zero as ercStatus value when called supportERC() for non declared ERC/features&quot;, async function () {
      let { erc721ForTesting, owner } = await loadFixture(deployFixture);
      expect(await erc721ForTesting.supportERC(owner.address, 721, ethers.utils.id(&quot;WRONG FEATURE&quot;), [])).to.equal(BigNumber.from(0));
      expect(await erc721ForTesting.supportERC(owner.address, 9999, ethers.utils.hexZeroPad(&quot;0x00&quot;, 32), [])).to.equal(BigNumber.from(0));
    });
  });
});
```

See [`TestERC5269.ts`](/EIPs/assets/eip-5269/test/TestERC5269.ts).

## Reference Implementation

Here is a reference implementation for this ERC:

```solidity
contract ERC5269 is IERC5269 {
    bytes32 constant public ERC_STATUS = keccak256(&quot;DRAFTv1&quot;);
    constructor () {
        emit OnSupportERC(address(0x0), 5269, bytes32(0), ERC_STATUS, &quot;&quot;);
    }

    function _supportERC(
        address /*caller*/,
        uint256 majorERCIdentifier,
        bytes32 minorERCIdentifier,
        bytes calldata /*extraData*/)
    internal virtual view returns (bytes32 ercStatus) {
        if (majorERCIdentifier == 5269) {
            if (minorERCIdentifier == bytes32(0)) {
                return ERC_STATUS;
            }
        }
        return bytes32(0);
    }

    function supportERC(
        address caller,
        uint256 majorERCIdentifier,
        bytes32 minorERCIdentifier,
        bytes calldata extraData)
    external virtual view returns (bytes32 ercStatus) {
        return _supportERC(caller, majorERCIdentifier, minorERCIdentifier, extraData);
    }
}
```

See [`ERC5269.sol`](/EIPs/assets/eip-5269/contracts/ERC5269.sol).

Here is an example where a contract of [ERC-721](/EIPs/EIPS/eip-721) also implements this ERC to make it easier
to detect and discover:

```solidity
import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;
import &quot;../ERC5269.sol&quot;;
contract ERC721ForTesting is ERC721, ERC5269 {

    bytes32 constant public ERC_FINAL = keccak256(&quot;FINAL&quot;);
    constructor() ERC721(&quot;ERC721ForTesting&quot;, &quot;E721FT&quot;) ERC5269() {
        _mint(msg.sender, 0);
        emit OnSupportERC(address(0x0), 721, bytes32(0), ERC_FINAL, &quot;&quot;);
        emit OnSupportERC(address(0x0), 721, keccak256(&quot;ERC721Metadata&quot;), ERC_FINAL, &quot;&quot;);
        emit OnSupportERC(address(0x0), 721, keccak256(&quot;ERC721Enumerable&quot;), ERC_FINAL, &quot;&quot;);
    }

  function supportERC(
    address caller,
    uint256 majorERCIdentifier,
    bytes32 minorERCIdentifier,
    bytes calldata extraData)
  external
  override
  view
  returns (bytes32 ercStatus) {
    if (majorERCIdentifier == 721) {
      if (minorERCIdentifier == 0) {
        return keccak256(&quot;FINAL&quot;);
      } else if (minorERCIdentifier == keccak256(&quot;ERC721Metadata&quot;)) {
        return keccak256(&quot;FINAL&quot;);
      } else if (minorERCIdentifier == keccak256(&quot;ERC721Enumerable&quot;)) {
        return keccak256(&quot;FINAL&quot;);
      }
    }
    return super._supportERC(caller, majorERCIdentifier, minorERCIdentifier, extraData);
  }
}

```

See [`ERC721ForTesting.sol`](/EIPs/assets/eip-5269/contracts/testing/ERC721ForTesting.sol).

## Security Considerations

Similar to [ERC-165](/EIPs/EIPS/eip-165) callers of the interface MUST assume the smart contract
declaring they support such ERC interfaces doesn&apos;t necessarily correctly support them.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 15 Jul 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5269</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5269</guid>
      </item>
    
      <item>
        <title>Semaphore for Reentrancy Protection</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5283-a-semaphore-for-parallelizable-reentrancy-protection/10236</comments>
        
        <description>## Abstract

This EIP proposes adding a precompiled contract that provides a semaphore function for creating a new type of reentrancy protection guard (RPG). This function aims to replace the typical RPG based on modifying a contract storage cell. The benefit is that the precompile-based RPG does not write to storage, and therefore it enables contracts to be forward-compatible with all designs that provide fine-grained (i.e. cell level) parallelization for the multi-threaded execution of EVM transactions. 

## Motivation

The typical smart contract RPG uses a contract storage cell. The algorithm is simple: the code checks that a storage cell is 0 (or any other predefined constant) on entry, aborting if not, and then sets it to 1. After executing the required code, it resets the cell back to 0 before exiting. This is the algorithm implemented in OpenZeppelin&apos;s ReentrancyGuard. The algorithm results in a read-write pattern on the RPG&apos;s storage cell. This pattern prevents the parallelization of the execution of the smart contract for all known designs that try to provide fine-grained parallelization (detecting conflicts at the storage cell level). 

Several EVM-based blockchains have successfully tested designs for the parallelization of the EVM. The best results have been obtained with fine-grained parallelization where conflicts are detected by tracking writes and reads of individual storage cells. The designs based on tracking the use of accounts or contracts provide only minor benefits because most transactions use the same [EIP-20](/EIPs/EIPS/eip-20) contracts.

To summarize, the only available RPG construction today is based on using a contract storage cell. This construction is clean but it is not forward-compatible with transaction execution parallelization.

## Specification

Starting from an activation block (TBD) a new precompiled contract `Semaphore` is created at address `0x0A`. When `Semaphore` is called, if the caller address is present more than once in the call stack, the contract behaves as if the first instruction had been a `REVERT`, therefore the CALL returns 0. Otherwise, it executes no code and returns 1. The gas cost of the contract execution is set to 100, which is consumed independently of the call result.

## Rationale

The address `0x0A` is the next one available within the range defined by [EIP-1352](./eip-1352).

### Sample usage

```solidity
pragma solidity ^0.8.0;

abstract contract ReentrancyGuard2 {

    uint8 constant SemaphoreAddress = 0x0A;
    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is supported.      
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
    }

    function _nonReentrantBefore() private {
    	assembly {
            if iszero(staticcall(1000,SemaphoreAddress,  0, 0, 0, 0)) {
                revert(0, 0)
            }
        }
    }
}
```

### Parallelizable storage-based RPGs
 
The only way to parallelize preexistent contracts that are using the storage RPG construction is that the VM automatically detects that a storage variable is used for the RPG, and proves that it works as required. This requires static code analysis. This is difficult to implement in consensus for two reasons. First, the CPU cost of detection and/or proving may be high. Second, some contract functions may not be protected by the RPG, meaning that some execution paths do not alter the RPG, which may complicate proving. Therefore this proposal aims to protect future contracts and let them be parallelizable, rather than to parallelize already deployed ones.

### Alternatives

There are alternative designs to implement RPGs on the EVM:

1. Transient storage opcodes (`TLOAD`/`TSTORE`) provide contract state that is kept between calls in the same transaction but it is not committed to the world state afterward. These opcodes also enable fine-grained parallelization. 
2. An opcode `SSTORE_COUNT` that retrieves the number of `SSTORE` instructions executed. It enables also fine-grained execution parallelization, but `SSTORE_COUNT` is much more complex to use correctly as it returns the number `SSTORE` opcodes executed, not the number of reentrant calls. Reentrancy must be deducted from this value.
3. A new `LOCKCALL` opcode that works similar to `STATICALL` but only blocks storage writes in the caller contract. This results in cheaper RPG, but it doesn&apos;t allow some contract functions to be free of the RPG.

All these alternative proposals have the downside that they create new opcodes, and this is discouraged if the same functionality can be implemented with the same gas cost using precompiles. A new opcode requires modifying compilers, debuggers and static analysis tools.

### Gas cost

A gas cost of 100 represents a worst-case resource consumption, which occurs when the stack is almost full (approximately 400 addresses) and it is fully scanned. As the stack is always present in RAM, the scanning is fast.

Note: Once code is implemented in geth, it can be benchmarked and the cost can be re-evaluated, as it may result to be lower in practice. As a precompile call currently costs 700 gas, the cost of stack scanning has a low impact on the total cost of the precompile call (800 gas in total).

The storage-based RPG currently costs 200 gas (because of the savings introduced in [EIP-1283](/EIPs/EIPS/eip-1283). Using the `Semaphore` precompile as a reentrancy check would currently cost 800 gas (a single call from one of the function modifiers). While this cost is higher than the traditional RPG cost and therefore discourages its use, it is still much lower than the pre-EIP-1283 cost. If a reduction in precompile call cost is implemented, then the cost of using the `Semaphore` precompile will be reduced to approximately 140 gas, below the current 200 gas consumed by a storage-based RPG. To encourage to use of the precompile-based RPG, it is suggested that this EIP is implemented together with a reduction in precompile calls cost.

## Backwards Compatibility

This change requires a hard fork and therefore all full nodes must be updated.

## Test Cases

```solidity
contract Test is ReentrancyGuard2 {
    function second() external nonReentrant {
    }
    function first() external nonReentrant {
        this.second();
    }
}
```

A call to `second()` directly from a transaction does not revert, but a call to `first()` does revert.

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 17 Jul 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5283</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5283</guid>
      </item>
    
      <item>
        <title>Ethereum Notary Interface</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/pr-5289-discussion-notary-interface/9980</comments>
        
        <description>## Abstract

Currently, the real-world applications of smart contracts are limited by the fact that they aren&apos;t legally binding. This EIP proposes a standard that allows smart contracts to be legally binding by providing IPFS links to legal documents and ensuring that the users of the smart contract have privity with the relevant legal documents.

Please note that the authors are not lawyers, and that this EIP is not legal advice.

## Motivation

NFTs have oftentimes been branded as a way to hold and prove copyright of a specific work. However, this, in practice, has almost never been the case. Most of the time, NFTs have no legally-binding meaning, and in the rare cases that do, the NFT simply provides a limited license for the initial holder to use the work (but cannot provide any license for any future holders).

## Specification

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.

### Legal Contract Library Interface

```solidity
/// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

import &quot;./IERC165.sol&quot;;

interface IERC5289Library is IERC165 {
    /// @notice Emitted when signDocument is called
    event DocumentSigned(address indexed signer, uint16 indexed documentId);
    
    /// @notice An immutable link to the legal document (RECOMMENDED to be hosted on IPFS). This MUST use a common file format, such as PDF, HTML, TeX, or Markdown.
    function legalDocument(uint16 documentId) external view returns (string memory);
    
    /// @notice Returns whether or not the given user signed the document.
    function documentSigned(address user, uint16 documentId) external view returns (bool signed);

    /// @notice Returns when the given user signed the document.
    /// @dev If the user has not signed the document, the timestamp may be anything.
    function documentSignedAt(address user, uint16 documentId) external view returns (uint64 timestamp);

    /// @notice Sign a document
    /// @dev This MUST be validated by the smart contract. This MUST emit DocumentSigned or throw.
    function signDocument(address signer, uint16 documentId) external;
}
```

### Requesting a Signature

To request that certain documents be signed, revert with an [ERC-5568](/EIPs/EIPS/eip-5568) signal. The format of the `instruction_data` is an ABI-encoded `(address, uint16)` pair, where the address is the address of the library, and the `uint16` is the `documentId` of the document:

```solidity
throw WalletSignal24(0, 5289, abi.encode(0xcbd99eb81b2d8ca256bb6a5b0ef7db86489778a7, 12345));
```

### Signing a Document

When a signature is requested, wallets MUST call `legalDocument`, display the resulting document to the user, and prompt them to either sign the document or cancel:

![image](/EIPs/assets/eip-5289/example-popup.png)

If the user agrees, the wallet MUST call `signDocument`.

## Rationale

- `uint64` was chosen for the timestamp return type as 64-bit time registers are standard.
- `uint16` was chosen for the document ID as 65536 documents are likely sufficient for any use case, and the contract can always be re-deployed.
- `signDocument` doesn&apos;t take an ECDSA signature for future compatibility with account abstraction. In addition, future extensions can supply this functionality.
- IPFS is mandatory because the authenticity of the signed document can be proven.

## Backwards Compatibility

No backwards compatibility issues found.

## Reference Implementation

### Legal Contract Library

See [`IERC5289Library`](/EIPs/assets/eip-5289/interfaces/IERC5289Library.sol), [`ERC5289Library`](/EIPs/assets/eip-5289/ERC5289Library.sol).

## Security Considerations

Users can claim that their private key was stolen and used to fraudulently &quot;sign&quot; contracts. As such, **documents must only be permissive in nature, not restrictive.** For example, a document granting a license to use the image attached to an NFT would be acceptable, as there is no reason for the signer to plausibly deny signing the document.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 16 Jul 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5289</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5289</guid>
      </item>
    
      <item>
        <title>ENS Trust to hold NFTs under ENS name</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-eip-5198-ens-as-token-holder/10374</comments>
        
        <description>## Abstract

This EIP standardizes an interface for smart contracts to hold [EIP-721](/EIPs/EIPS/eip-721) and [EIP-1155](/EIPs/EIPS/eip-1155) tokens on behalf of ENS domains.

## Motivation

Currently, if someone wants to receive a token, they have to set up a wallet address. This EIP decouples NFT ownership from wallet addresses.

## Specification

1. Compliant contracts MUST implement `ERC721TokenReceiver`, as defined in [EIP-721](/EIPs/EIPS/eip-721).
2. Compliant contracts implement the following interface:

```solidity
interface IERC_ENS_TRUST is ERC721Receiver, ERC1155Receiver {
    function claimTo(address to, bytes32 ensNode, address operator, uint256 tokenId) payable external;
}
```

3. `claimTo` MUST check if `msg.sender` is the owner of the ENS node identified by `bytes32 ensNode` (and/or approved by the domain in implementation-specific ways). The compliant contract then MUST make a call to the `safeTransferFrom` function of [EIP-721](/EIPs/EIPS/eip-712) or [EIP-1155](/EIPs/EIPS/eip-1155).

4. Any `ensNode` is allowed.

## Rationale

1. ENS was chosen because it is a well-established scoped ownership namespace.
This is nonetheless compatible with other scoped ownership namespaces.

2. We didn&apos;t expose getters or setters for ensRoot because it is outside the scope of this EIP.

## Backwards Compatibility

No backward compatibility issues were found.

## Test Cases

```ts
import { loadFixture } from &quot;@nomicfoundation/hardhat-network-helpers&quot;;
import { expect } from &quot;chai&quot;;
import { ethers } from &quot;hardhat&quot;;

describe(&quot;FirstENSBankAndTrust&quot;, function () {

    describe(&quot;Receive and Claim Token&quot;, function () {

        it(&quot;Should ACCEPT/REJECT claimTo based on if ENS owner is msg.sender&quot;, async function () {
            ...
            // Steps of testing:
            // mint to charlie
            // charlie send to ENSTrust and recorded under bob.xinbenlvethsf.eth
            // bob tries to claimTo alice, first time it should be rejected
            // bob then set the ENS record
            // bob claim to alice, second time it should be accepted

            // mint to charlie
            await erc721ForTesting.mint(charlie.address, fakeTokenId);

            // charlie send to ENSTrust and recorded under bob.xinbenlvethsf.eth
            await erc721ForTesting.connect(charlie)[&quot;safeTransferFrom(address,address,uint256,bytes)&quot;](
                charlie.address, firstENSBankAndTrust.address,
                fakeTokenId,
                fakeReceiverENSNamehash
            );

            // bob tries to claimTo alice, first time it should be rejected
            await expect(firstENSBankAndTrust.connect(bob).claimTo(
                alice.address,
                fakeReceiverENSNamehash,
                firstENSBankAndTrust.address,
                fakeTokenId
                ))
                .to.be.rejectedWith(&quot;ENSTokenHolder: node not owned by sender&quot;);

            // bob then set the ENS record
            await ensForTesting.setOwner(
                fakeReceiverENSNamehash, bob.address
            );

            // bob claim to alice, second time it should be accepted
            await expect(firstENSBankAndTrust.connect(bob).claimTo(
                alice.address,
                fakeReceiverENSNamehash,
                erc721ForTesting.address,
                fakeTokenId
            ));
        });
    });
});
```

## Reference Implementation

```solidity
pragma solidity ^0.8.9;

contract FirstENSBankAndTrust is IERC721Receiver, Ownable {
    function getENS() public view returns (ENS) {
        return ENS(ensAddress);
    }

    function setENS(address newENSAddress) public onlyOwner {
        ensAddress = newENSAddress;
    }

    // @dev This function is called by the owner of the token to approve the transfer of the token
    // @param data MUST BE the ENS node of the intended token receiver this ENSHoldingServiceForNFT is holding on behalf of.
    function onERC721Received(
        address operator,
        address /*from*/,
        uint256 tokenId,
        bytes calldata data
    ) external override returns (bytes4) {
        require(data.length == 32, &quot;ENSTokenHolder: last data field must be ENS node.&quot;);
        // --- START WARNING ---
        // DO NOT USE THIS IN PROD
        // this is only a demonstration of using extraData for node information
        // In prod, you should use a struct to store the data. struct should clearly identify the data is for ENS
        // rather than anything else.
        bytes32 ensNode = bytes32(data[0:32]);
        // --- END OF WARNING ---

        addToHolding(ensNode, operator, tokenId); // conduct the book keeping
        return ERC721_RECEIVER_MAGICWORD;
    }

    function claimTo(address to, bytes32 ensNode, address tokenContract uint256 tokenId) public {
        require(getENS().owner(ensNode) == msg.sender, &quot;ENSTokenHolder: node not owned by sender&quot;);
        removeFromHolding(ensNode, tokenContract, tokenId);
        IERC721(tokenContract).safeTransferFrom(address(this), to, tokenId);
    }
}
```

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 12 Jul 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5298</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5298</guid>
      </item>
    
      <item>
        <title>Light Contract Ownership</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5313-light-contract-ownership/10052</comments>
        
        <description>## Abstract

This specification defines the minimum interface required to identify an account that controls a contract.

## Motivation

This is a slimmed-down alternative to [EIP-173](/EIPs/EIPS/eip-173).

## Specification

The key word “MUST” in this document is to be interpreted as described in RFC 2119.

Every contract compliant with this EIP MUST implement the `EIP5313` interface.

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.15;

/// @title EIP-5313 Light Contract Ownership Standard
interface EIP5313 {
    /// @notice Get the address of the owner    
    /// @return The address of the owner
    function owner() view external returns(address);
}
```

## Rationale

Key factors influencing the standard: 

- Minimize the number of functions in the interface
- Backwards compatibility with existing contracts

This standard can be (and has been) extended by other standards to add additional ownership functionality. The smaller scope of this specification allows more and more straightforward ownership implementations, see limitations explained in EIP-173 under &quot;other schemes that were considered&quot;.

Implementing [EIP-165](/EIPs/EIPS/eip-165) could be a valuable addition to this interface specification. However, this EIP is being written to codify existing protocols that connect contracts (often NFTs), with third-party websites (often a well-known NFT marketplace).

## Backwards Compatibility

Every contract that implements EIP-173 already implements this specification.

## Security Considerations

Because this specification does not extend EIP-165, calling this EIP&apos;s `owner` function cannot result in complete certainty that the result is indeed the owner. For example, another function with the same function signature may return some value that is then interpreted to be the true owner. If this EIP is used solely to identify if an account is the owner of a contract, then the impact of this risk is minimized. But if the interrogator is, for example, sending a valuable NFT to the identified owner of any contract on the network, then the risk is heightened.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 22 Jul 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5313</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5313</guid>
      </item>
    
      <item>
        <title>EIP-721 User And Expires And Level Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-721-user-and-expires-and-level-extension/10097</comments>
        
        <description>## Abstract

An [EIP-721](/EIPs/EIPS/eip-721) extension that adds an additional role (`user`) which can be granted to addresses, and a time where the role is automatically revoked (`expires`) and (`level`) . The `user` role represents permission to &quot;use&quot; the NFT, but not the ability to transfer it or set users.

## Motivation

Some NFTs have certain utilities. For example, virtual land can be &quot;used&quot; to build scenes, and NFTs representing game assets can be &quot;used&quot; in-game. In some cases, the owner and user may not always be the same. There may be an owner of the NFT that rents it out to a “user”. The actions that a “user” should be able to take with an NFT would be different from the “owner” (for instance, “users” usually shouldn’t be able to sell ownership of the NFT).  In these situations, it makes sense to have separate roles that identify whether an address represents an “owner” or a “user” and manage permissions to perform actions accordingly.

Some projects already use this design scheme under different names such as “operator” or “controller” but as it becomes more and more prevalent, we need a unified standard to facilitate collaboration amongst all applications.

Furthermore, applications of this model (such as renting) often demand that user addresses have only temporary access to using the NFT. Normally, this means the owner needs to submit two on-chain transactions, one to list a new address as the new user role at the start of the duration and one to reclaim the user role at the end. This is inefficient in both labor and gas and so an “expires” and “level” function is introduced that would facilitate the automatic end of a usage term without the need of a second transaction.

Here are some of the problems that are solved by this standard:

### Clear Rights Assignment

With Dual “owner” and “user” roles, it becomes significantly easier to manage what lenders and borrowers can and cannot do with the NFT (in other words, their rights). Additionally, owners can control who the user is and it’s easy for other projects to assign their own rights to either the owners or the users.

### Simple On-chain Time Management

Once a rental period is over, the user role needs to be reset and the “user” has to lose access to the right to use the NFT. This is usually accomplished with a second on-chain transaction but that is gas inefficient and can lead to complications because it’s imprecise. With the `expires` function, there is no need for another transaction because the “user” is invalidated automatically after the duration is over.

### Easy Third-Party Integration

In the spirit of permission less interoperability, this standard makes it easier for third-party protocols to manage NFT usage rights without permission from the NFT issuer or the NFT application. Once a project has adopted the additional `user` role and `expires` and `level`, any other project can directly interact with these features and implement their own type of transaction. For example, a PFP NFT using this standard can be integrated into both a rental platform where users can rent the NFT for 30 days AND, at the same time, a mortgage platform where users can use the NFT while eventually buying ownership of the NFT with installment payments. This would all be done without needing the permission of the original PFP project.

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot; and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### Contract Interface
Solidity Interface with NatSpec &amp; OpenZeppelin v4 Interfaces (also available at [`IERC5334.sol`](/EIPs/assets/eip-5334/IERC5334.sol)):

```solidity
interface IERC5334 {

    // Logged when the user of a NFT, expires, or level is changed
    /// @notice Emitted when the `user` of an NFT or the `expires` of the `user` is changed or the user `level` is changed
    /// The zero address for user indicates that there is no user address
    event UpdateUser(uint256 indexed tokenId, address indexed user, uint64 expires, uint8 level);

    /// @notice set the user and expires and level of a NFT
    /// @dev The zero address indicates there is no user
    /// Throws if `tokenId` is not valid NFT
    /// @param user  The new user of the NFT
    /// @param expires  UNIX timestamp, The new user could use the NFT before expires
    /// @param level user level
    function setUser(uint256 tokenId, address user, uint64 expires, uint8 level) external;

    /// @notice Get the user address of an NFT
    /// @dev The zero address indicates that there is no user or the user is expired
    /// @param tokenId The NFT to get the user address for
    /// @return The user address for this NFT
    function userOf(uint256 tokenId) external view returns(address);

    /// @notice Get the user expires of an NFT
    /// @dev The zero value indicates that there is no user
    /// @param tokenId The NFT to get the user expires for
    /// @return The user expires for this NFT
    function userExpires(uint256 tokenId) external view returns(uint256);

    /// @notice Get the user level of an NFT
    /// @dev The zero value indicates that there is no user
    /// @param tokenId The NFT to get the user level for
    /// @return The user level for this NFT
    function userLevel(uint256 tokenId) external view returns(uint256);
}
```

The `userOf(uint256 tokenId)` function MAY be implemented as `pure` or `view`.

The `userExpires(uint256 tokenId)` function MAY be implemented as `pure` or `view`.

The `userLevel(uint256 tokenId)` function MAY be implemented as `pure` or `view`.

The `setUser(uint256 tokenId, address user, uint64 expires)` function MAY be implemented as `public` or `external`.

The `UpdateUser` event MUST be emitted when a user address is changed or the user expires is changed or the user level is changed.

&lt;!-- The `supportsInterface` method MUST return `true` when called with `0xTODO`. --&gt;

## Rationale

TBD

## Backwards Compatibility

As mentioned in the specifications section, this standard can be fully EIP-721 compatible by adding an extension function set.

In addition, new functions introduced in this standard have many similarities with the existing functions in EIP-721. This allows developers to easily adopt the standard quickly.

## Reference Implementation
A reference implementation of this standard can be found in the assets folder.
&lt;!-- [../assets/EIP-5334/ERC5334.sol](../assets/EIP-5334/ERC5334.sol). --&gt;

## Security Considerations

This EIP standard can completely protect the rights of the owner, the owner can change the NFT user and expires and level at any time.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Mon, 25 Jul 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5334</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5334</guid>
      </item>
    
      <item>
        <title>Silent Signing Extension for JSON-RPC</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/walletconnect-silent-signing-extension/10137</comments>
        
        <description>## Abstract

Mobile applications supporting lots of transactions might become a source of bad user experience due to uncontrolled switching between the wallet&apos;s and application&apos;s UI. By this proposal, we would like to introduce the means to sign and send wallet transactions without the need for user participation. This feature can be implemented by providing user consent for a specific time duration. We call the feature Silent Signing.

## Motivation

Some blockchain applications interact with a blockchain much more frequently than others. It is especially true for gaming applications having their own sidechains. Interrupting the gaming process and switching to the wallet to perform a transaction drastically affect the user experience.

## Specification

To remedy the situation, we&apos;d like to introduce new RPC methods for the ethereum JSON-RPC. Those methods help enable wallets to implement the Silent Signing feature.

### Silent Signing User Flow

The Silent Signing process has the following structure:

1. First, the application requests the wallet to use Silent Signing via the RPC&apos;s `wallet_requestSilentSign` method.
2. Second, the wallet prompts the user to confirm enabling the Silent Singing functionality for a specific time duration.
3. If the user does not confirm Silent Signing or the RPC method is not allowed, the application will continue using the regular methods.
4. If the user confirms Silent Signing, then each subsequent transaction will be sent using the `wallet_silentSendTransaction` method for the time duration specified.

### Implementation

The implementation introduces new RPC methods and flow for application and wallet side.

### New RPC Methods

#### `wallet_requestSilentSign`

This RPC method opens the wallet and prompts the user to enable automatic signing for a specific time duration. This function grants the application to call the following methods until the timestamp expires. Standard methods like `eth_signTrancaction` remain untouched.

```shell
Parameters
  Object: request object
    until: NUMBER - unix timesptamp, the end time the permission will be valid
    chainId: NUMBER - the chain id that the contract located in
    contractAddress: ADDRESS - address of the contract to be allowed
    allowedFunctions: STRING ARRAY - allowed function signatures
          Ex: [&quot;equip(address,uint256)&quot;, &quot;unequip(address,uint256)&quot;]
    description: STRING - extra description that can be shown to user by the wallet

Returns
  DATA, 20 Bytes: permissionSecret - a secret key for silent-signing requests (randomly generated)
```

#### `wallet_silentSignTransaction`

This RPC method creates a transaction and sends its data to the wallet for signing. The wallet signs the data in the background, interfering with no processes the user is involved in. Afterward, the application sends the signed transaction to the blockchain using Nethereum&apos;s or other libraries&apos; `sendRawTransaction` method.

```shell
Parameters
  DATA, 20 Bytes: permissionSecret - secret key obtained from `wallet_requestSilentSign` method
  Object - The transaction object
    from: DATA, 20 Bytes - The address the transaction is sent from.
    to: DATA, 20 Bytes - (optional when creating new contract) The address the transaction is directed to.
    gas: QUANTITY - (optional, default: 90000) Integer of the gas provided for the transaction execution. It will return unused gas.
    gasPrice: QUANTITY - (optional, default: To-Be-Determined) Integer of the gasPrice used for each paid gas, in Wei.
    value: QUANTITY - (optional) Integer of the value sent with this transaction, in Wei.
    data: DATA - The compiled code of a contract OR the hash of the invoked method signature and encoded parameters.
    nonce: QUANTITY - (optional) Integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce.
  
Returns
  DATA, The signed transaction object.
```

#### `wallet_silentSendTransaction`

This RPC method creates a transaction and sends it to the blockchain without interfering with the process the user is involved in.

```shell
Parameters
  DATA, 20 Bytes: permissionSecret - secret key obtained from `wallet_requestSilentSign` method
  Object - The transaction object
    from: DATA, 20 Bytes - The address the transaction is sent from.
    to: DATA, 20 Bytes - (optional when creating new contract) The address the transaction is directed to.
    gas: QUANTITY - (optional, default: 90000) Integer of the gas provided for the transaction execution. It will return unused gas.
    gasPrice: QUANTITY - (optional, default: To-Be-Determined) Integer of the gasPrice used for each paid gas.
    value: QUANTITY - (optional) Integer of the value sent with this transaction.
    data: DATA - The compiled code of a contract OR the hash of the invoked method signature and encoded parameters.
    nonce: QUANTITY - (optional) Integer of a nonce. This allows to overwrite your own pending transactions that use the same nonce.

Returns
  DATA, 32 Bytes - the transaction hash, or the zero hash if the transaction is not yet available.
```

### Application and Wallet Communication

Sending RPC requests between application and wallet can be as usual. For example browser extension wallets can use these new methods easily. Even hardware wallets can implement this too. But for mobile wallets extra communication techniques should be considered. Because mobile wallets can be inactive when it is not in use.

Mobile wallets mostly use Walletconnect protocol. The application closed or active in the background can&apos;t connect to the Bridge server via WebSocket. Therefore, we have to trigger the wallet to connect to the Bridge and to start waiting for requests. For this purpose, push notifications are to be used. That means that only the wallets supporting push notifications can implement the feature.

![](/EIPs/assets/eip-5345/walletconnect-flow.png)

Whenever the wallet receives a push notification, it connects to the Bridge server and gets access to the pending requests. If there are `wallet_silenSignTransaction` or `wallet_silentSendTransaction` silent signing requests pending and the interaction with the requesting client has been confirmed for this particular time duration, then the wallet executes the request without interfering with the ongoing user activity.

## Rationale

Games and Metaverse applications imply lots of cases when the user interacts with the wallet, switching to it and approving transactions. This switching aspect might interfere with gaming per se and create a bad user experience. That is why such applications can benefit if the wallets can support the Silent Signing functionality allowing transactions to be signed with no user interaction.

## Backwards Compatibility

These new RPC methods don&apos;t interfere with the current ones, and for mobile wallets the push notifications API is currently a part of the `WalletConnect` specification. Implementing the proposal&apos;s functionality changes nothing for other applications and wallets.

## Security Considerations

The proposed feature aims to improve the user experience and can only be enabled with user consent. Users might freely choose to use the application as usual.

Silent Signing permission has restrictions that makes it more secure. 
* Permission granted only for a specified time duration
* Permission granted only for specific contract in a specific chain and restricted to specified functions.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 26 Jul 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5345</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5345</guid>
      </item>
    
      <item>
        <title>NFT Author Information and Consent</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5375-nft-authorship/10182</comments>
        
        <description>## Abstract

This EIP standardizes a JSON format for storing off-chain information about NFT authors. Specifically, it adds a new field which provides a list of author names, addresses, and proofs of _authorship consent_: proofs that the authors have agreed to be named as authors. Note that a proof of authorship _consent_ is not a proof of authorship: an address can consent without having authored the NFT.

## Motivation

There is currently no standard to identify authors of an NFT, and existing techniques have issues:

- Using the mint `tx.origin` or `msg.sender`
  - Assumes that the minter and the author are the same
  - Does not support multiple authors
- Using the first Transfer event for a given ID
  - Contract/minter can claim that someone else is the author without their consent
  - Does not support multiple authors
- Using a custom method/custom JSON field
  - Requires per-contract support by NFT platforms
  - Contract/minter can claim that someone else is the author without their consent

The first practice is the most common. However, there are several situations where the minter and the author might not be the same, such as:

- NFTs minted by a contract
- Lazy minting
- NFTs minted by an intermediary (which can be particularly useful when the author is not tech-savvy and/or the minting process is convoluted)

This document thus defines a standard which allows the minter to provide authorship information, while also preventing authorship claims without the author&apos;s consent.

## Specification

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.

All addresses used in this standard MUST follow the casing rules described in [EIP-55](/EIPs/EIPS/eip-55).

### Definitions

- **Authors**: creators of an NFT
- **Minter**: entity responsible for the actual minting transaction; the minter and the authors MAY be the same
- **Verifier**: entity that wants to verify the authorship of an NFT (e.g. a user or an NFT marketplace)
- **Author Consent Proof (ACP)**: a signed message that proves that the signer agrees to be considered the author of the NFT

### Authorship Support

The standard introduces a new JSON field, named `authorInfo`. It provides a REQUIRED interface for authorship claiming, as well as an OPTIONAL interface for author consent proofs.

`authorInfo` is a top-level field of the NFT metadata. Specifically:

- If a contract supports the metadata extension for [EIP-721](/EIPs/EIPS/eip-721), the JSON document pointed by `tokenURI(uint256 _tokenId)` MUST include the top-level field `authorInfo`
- If a contract supports the metadata extension for [EIP-1155](/EIPs/EIPS/eip-1155), the JSON document pointed by `uri(uint256 _id)` MUST include a top-level field `authorInfo`

The JSON schema of `authorInfo` (named `ERC5375AuthorInfoSchema`) is defined as follows:

```json
{
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;consentInfo&quot;: {
            &quot;type&quot;: &quot;object&quot;,
            &quot;description&quot;: &quot;Helper fields for consent verification&quot;,
            &quot;properties&quot;: {
                &quot;chainId&quot;: {
                    &quot;type&quot;: &quot;integer&quot;,
                    &quot;description&quot;: &quot;EIP-155 chain id&quot;
                },
                &quot;id&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;NFT id&quot;
                },
                &quot;contractAddress&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;0x-prefixed address of the smart contract&quot;
                }
            }
        },
        &quot;authors&quot;: {
            &quot;type&quot;: &quot;array&quot;,
            &quot;items&quot;: &quot;ERC5375AuthorSchema&quot;
        }
    },
    &quot;required&quot;: [ &quot;authors&quot; ]
}
```

Note that `authors` MAY be an empty array.

`ERC5375AuthorSchema` is defined as follows:

```json
{
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;address&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;0x-prefixed address of the author&quot;
        },
        &quot;consent&quot;: {
            &quot;type&quot;: &quot;ERC5375AuthorConsentSchema&quot;,
            &quot;description&quot;: &quot;Author consent information&quot;
        }
    },
    &quot;required&quot;: [ &quot;address&quot; ]
}
```

Moreover, if the `consent` field is present, the `consentInfo` field of `authorInfo` MUST be present.

`ERC5375AuthorConsentSchema` is defined as follows:

```json
{
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;consentData&quot;: {
            &quot;type&quot;: &quot;object&quot;,
            &quot;properties&quot;: {
                &quot;version&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;NFT authorship consent schema version&quot;
                },
                &quot;issuer&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;0x-prefixed address of the author&quot;
                },
                &quot;metadataFields&quot;: {
                    &quot;type&quot;: &quot;object&quot;
                }
            },
            &quot;required&quot;: [&quot;version&quot;, &quot;issuer&quot;, &quot;metadataFields&quot;]
        },
        &quot;publicKey&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;EVM public key of the author&quot;
        },
        &quot;signature&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;EIP-712 signature of the consent message&quot;
        }
    },
    &quot;required&quot;: [&quot;consentData&quot;, &quot;publicKey&quot;, &quot;signature&quot;]
}
```

where `metadataFields` is an object containing the JSON top-level fields (excluding `authorInfo`) that the author will certify. Note that the keys of `metadataFields` MAY be a (potentially empty) subset of the set of fields.

`consentData` MAY support additional fields as defined by other EIPs. `consentData` MUST contain all the information (which is not already present in other fields) required to verify the validity of an authorship consent proof.

### Author Consent

Consent is obtained by signing an [EIP-712](/EIPs/EIPS/eip-712) compatible message. Specifically, the structure is defined as follows:

```solidity
struct Author {
    address subject;
    uint256 tokenId;
    string metadata;
}
```

where `subject` is the address of the NFT contract, `tokenId` is the id of the NFT and `metadata` is the JSON encoding of the fields listed in `metadataFields`. `metadata`:

- MUST contain exactly the same fields as the ones listed in `metadataFields`, in the same order
- MUST escape all non-ASCII characters. If the escaped character contains hexadecimal letters, they MUST be uppercase
- MUST not contain any whitespace that is not part of a field name or value

For example, if the top-level JSON fields are:

```json
{
    &quot;name&quot;: &quot;The Holy Hand Grenade of Antioch&quot;,
    &quot;description&quot;: &quot;Throw in the general direction of your favorite rabbit, et voilà&quot;,
    &quot;damage&quot;: 500,
    &quot;authors&quot;: [...],
    ...
}
```

and the content of `metadataFields` is `[&quot;name&quot;, &quot;description&quot;]`, the content of `metadata` is:

```json
{
    &quot;name&quot;: &quot;The Holy Hand Grenade of Antioch&quot;,
    &quot;description&quot;: &quot;Throw in the general direction of your favorite rabbit, et voil\u00E0&quot;
}
```

Similarly to `consentData`, this structure MAY support additional fields as defined by other EIPs.

The domain separator structure is

```solidity
struct EIP712Domain {
    string name;
    string version;
    uint256 chainId;
}
```

where `name` and `version` are the same fields described in `consentData`

This structure MAY support additional fields as defined by other EIPs.

### Author Consent Verification

Verification is performed using EIP-712 on an author-by-author basis. Specifically, given a JSON document D1, a consent proof is valid if all of the following statements are true:

- D1 has a top-level `authorInfo` field that matches `ERC5375AuthorInfoSchema`
- `consent` exists and matches `ERC5375AuthorConsentSchema`;
- If calling `tokenURI` (for EIP-721) or `uri` (for EIP-1155) returns the URI of a JSON document D2, all the top-level fields listed in `metadataFields` MUST exist and have the same value;
- The EIP-712 signature in `signature` (computed using the fields specified in the JSON document) is valid;

Verifiers MUST NOT assume that an NFT with a valid consent proof from address X means that X is the actual author. On the other hand, verifiers MAY assume that if an NFT does not provide a valid consent proof for address X, then X is not the actual author.

## Rationale

### Why provide only an author consent proof?

Adding support for full authorship proofs (i.e. Alice is the author and no one else is the author) requires a protocol to prove that someone is the only author of an NFT.
In other words, we need to answer the question: &quot;Given an NFT Y and a user X claiming to be the author, is X the original author of Y?&quot;.

For the sake of the argument, assume that there exists a protocol that, given an NFT Y, can determine the original author of Y. Even if such method existed, an attacker could slightly modify Y, thus obtaining a new NFT Y&apos;, and rightfully claim to be the author of Y&apos;, despite the fact that it is not an original work. Real-world examples include changing some pixels of an image or replacing some words of a text with synonyms.
Preventing this behavior would require a general formal definition of when two NFTs are semantically equivalent. Even if defining such a concept were possible, it would still be beyond the scope of this EIP.

Note that this issue is also present when using the minter&apos;s address as a proxy for the author.

### Why off-chain?

There are three reasons:

- Adding off-chain support does not require modifications to existing smart contracts;
- Off-chain storage is usually much cheaper than on-chain storage, thus reducing the implementation barrier;
- While there may be some use cases for full on-chain authorship proofs (e.g. a marketplace providing special features for authors), there are limited applications for on-chain author consent, due to the fact that it is mostly used by users to determine the subjective value of an NFT.

### Why repeat id, chainId and contractAddress?

In many cases, this data can be derived from contextual information. However, requiring their inclusion in the JSON document ensures that author consent can be verified using only the JSON document.

### Why not implement a revocation system?

Authorship is usually final: either someone created an NFT or they didn&apos;t. Moreover, a revocation system would impose additional implementation requirements on smart contracts and increase the complexity of verification. Smart contracts MAY implement a revocation system, such as the one defined in other EIPs.

#### Why escape non-ASCII characters in the signature message?

EIP-712 is designed with the possibility of on-chain verification in mind; while on-chain verification is not a priority for this EIP, non-ASCII characters are escaped due to the high complexity of dealing with non-ASCII strings in smart contracts.

### Usability Improvements for Authors

Since the author only needs to sign an EIP-712 message, this protocol allows minters to handle the technical aspects of minting while still preserving the secrecy of the author&apos;s wallet. Specifically, the author only needs to:

- Obtain an EVM wallet;
- Learn how to read and sign a EIP-712 message (which can often be simplified by using a Dapp)

without needing to:

- Obtain the chain&apos;s native token (e.g. through trading or bridging);
- Sign a transaction;
- Understand the pricing mechanism of transactions;
- Verify if a transaction has been included in a block

This reduces the technical barrier for authors, thus increasing the usability of NFTs, without requiring authors to hand over their keys to a tech-savvy intermediary.

### Limitations of Address-Based Consent

The standard defines a protocol to verify that a certain _address_ provided consent. However, it does not guarantee that the address corresponds to the expected author (such as the one provided in the `name` field). Proving a link between an address and the entity behind it is beyond the scope of this document.

## Backwards Compatibility

No backward compatibility issues were found.

## Security Considerations

### Attacks

A potential attack that exploits this EIP involves tricking authors into signing authorship consent messages against their wishes. For this reason, authors MUST verify that all signature fields match the required ones.

A more subtle approach involves not adding important fields to `metadataFields`. By doing so, the author signature might be valid even if the minter changes critical information.

### Deprecated Features

`ERC5375AuthorInfoSchema` also originally included a field to specify a human-readable name for the author (without any kind of verification). This was scrapped due to the high risk of author spoofing, i.e.:

- Alice mints an NFT using Bob&apos;s name and Alice&apos;s address
- Charlie does not check the address and instead relies on the provided name
- Charlie buys Alice&apos;s NFT while believing that it was created by Bob

For this reason, smart contract developers SHOULD NOT add support for unverifiable information to the JSON document. We believe that the most secure way to provide complex authorship information (e.g. the name of the author) is to prove that the information is associated with the _author&apos;s address_, instead of with the NFT itself.

### Replay Attack Resistance

The chain id, the contract address and the token id uniquely identify an NFT; for this reason, there is no need to implement additional replay attack countermeasures (e.g. a nonce system).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 30 Jul 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5375</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5375</guid>
      </item>
    
      <item>
        <title>ERC-721 Entitlement Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/pr-5380-eip-4907-alternative-design/10190</comments>
        
        <description>## Abstract

This EIP proposes a new interface that allows [ERC-721](/EIPs/EIPS/eip-721) token owners to grant limited usage of those tokens to other addresses.

## Motivation

There are many scenarios in which it makes sense for the owner of a token to grant certain properties to another address. One use case is renting tokens. If the token in question represents a trading card in an on-chain TCG (trading card game), one might want to be able to use that card in the game without having to actually buy it. Therefore, the owner might grant the renter the &quot;property&quot; of it being able to be played in the TCG. However, this property should only be able to be assigned to one person at a time, otherwise a contract could simply &quot;rent&quot; the card to everybody. If the token represents usage rights instead, the property of being allowed to use the associated media does not need such a restriction, and there is no reason that the property should be as scarce as the token. 

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot; and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### Base

Compliant entitlement contracts MUST implement the following Solidity interface:

```solidity
/// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

interface ERC5380Entitlement is ERC165 {
    /// @notice Emitted when the amount of entitlement a user has changes. If user is the zero address, then the user is the owner
    event EntitlementChanged(address indexed user, address indexed contract, uint256 indexed tokenId);

    /// @notice             Set the user associated with the given ERC-721 token as long as the owner is msg.sender.
    /// @dev                SHOULD NOT revert if the owner is not msg.sender.
    /// @param  user        The user to grant the entitlement to
    /// @param  contract    The property to grant
    /// @param  tokenId     The tokenId to grant the properties of
    function entitle(address user, address contract, uint256 tokenId) external;

    /// @notice             Get the maximum number of users that can receive this entitlement
    /// @param  contract    The contract to query
    /// @param  tokenId     The tokenId to query
    function maxEntitlements(address contract, uint256 tokenId) external view (uint256 max);

    /// @notice             Get the user associated with the given contract and tokenId.
    /// @dev                Defaults to maxEntitlements(contract, tokenId) assigned to contract.ownerOf(tokenId)
    /// @param  user        The user to query
    /// @param  contract    The contract to query
    /// @param  tokenId     The tokenId to query
    function entitlementOf(address user, address contract, uint256 tokenId) external view returns (uint256 amt);
}
```

`supportsInterface` MUST return true when called with `ERC5380Entitlement`&apos;s interface ID.

### Enumerable Extension

This OPTIONAL Solidity interface is RECOMMENDED.

```solidity
/// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

interface ERC5380EntitlementEnumerable is ERC5380Entitlement { // Also implicitly supports ERC-165
    /// @notice         Enumerate tokens with nonzero entitlement assigned to a user
    /// @dev            Throws if the index is out of bounds or if user == address(0)
    /// @param  user    The user to query
    /// @param  index   A counter
    function entitlementOfUserByIndex(address user, uint256 index) external view returns (address contract, uint256 tokenId);
}
```

`supportsInterface` MUST return true when called with `ERC5380EntitlementEnumerable`&apos;s interface ID.

### Metadata Extension

This OPTIONAL Solidity interface is RECOMMENDED.

This extension uses [ERC-1046](/EIPs/EIPS/eip-1046) for `tokenURI` compatibility.

```solidity
/// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

interface ERC5380EntitlementMetadata is ERC5380Entitlement { // Also implicitly supports ERC-165
    /// @notice             ERC-1046 token URI
    /// @dev                See ERC-1046 and the metadata schema below
    function tokenURI() external view returns (string);
}
```

`supportsInterface` MUST return true when called with `ERC5380EntitlementMetadata`&apos;s interface ID.

#### Interoperability Metadata Extension

ERC-1046&apos;s `InteroperabilityMetadata` is extended with the following TypeScript interface:

```typescript
/**
 * ERC-5380&apos;s extension to ERC-1046&apos;s Interoperability metadata.
 */
interface ERC5380InteroperabilityMetadata is InteroperabilityMetadata {
    /**
     * This MUST be true if this is ERC-5380 Token Metadata, otherwise, this MUST be omitted.
     * Setting this to true indicates to wallets that the address should be treated as an ERC-5380 entitlement.
     **/
    erc5380?: boolean | undefined;
}
```

#### `tokenURI` Metadata Schema

The resolved `tokenURI` data MUST conform to the following TypeScript interface:

```typescript
/**
 * ERC-5380 Asset Metadata
 * Can be extended
 */
interface ERC5380TokenMetadata {
    /**
     * Interoperabiliy, to differentiate between different types of tokens and their corresponding URIs.
     **/
    interop: ERC5380InteroperabilityMetadata;
    
    /**
     * The name of the ERC-5380 token. 
     */
    name?: string;
    
    /**
     * The symbol of the ERC-5380 token. 
     */
    symbol?: string;
    
    /**
     * Provides a short one-paragraph description of the ERC-5380 token, without any markup or newlines.
     */
    description?: string;
    
    /**
     * One or more URIs each pointing to a resource with mime type `image/*` that represents this token.
     * If an image is a bitmap, it SHOULD have a width between 320 and 1080 pixels
     * Images SHOULD have an aspect ratio between 1.91:1 and 4:5 inclusive.
     */
    images?: string[];
    
    /**
     * One or more URIs each pointing to a resource with mime type `image/*` that represent an icon for this token.
     * If an image is a bitmap, it SHOULD have a width between 320 and 1080 pixels, and MUST have a height equal to its width
     * Images MUST have an aspect ratio of 1:1, and use a transparent background
     */
    icons?: string[];
}
```

## Rationale

[ERC-20](/EIPs/EIPS/eip-20) and [ERC-1155](/EIPs/EIPS/eip-1155) are unsupported as partial ownership is much more complex to track than boolean ownership.

## Backwards Compatibility

No backward compatibility issues were found.

## Security Considerations

The security considerations of [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1046](/EIPs/EIPS/eip-1046) apply.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 11 Mar 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5380</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5380</guid>
      </item>
    
      <item>
        <title>EIP-1155 Non-Fungible Token extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5409-non-fungible-token-extension-for-eip-1155/10240</comments>
        
        <description>## Abstract

This standard is an extension of [EIP-1155](/EIPs/EIPS/eip-1155). It proposes an additional function, `ownerOf`, which allows EIP-1155 tokens to support Non-Fungibility (unique owners). By implementing this extra function, EIP-1155 tokens can benefit from [EIP-721](/EIPs/EIPS/eip-721)&apos;s core functionality without implementing the (less efficient) EIP-721 specification in the same contract.

## Motivation

Currently, EIP-1155 does not allow an external caller to detect whether a token is truly unique (can have only one owner) or fungible. This is because EIP-1155 do not expose a mechanism to detect whether a token will have its supply remain to be &quot;1&quot;. Furthermore, it does not let an external caller retrieve the owner directly on-chain.

The EIP-1155 specification does mention the use of split id to represent non-fungible tokens, but this requires a pre-established convention that is not part of the standard, and is not as simple as EIP-721&apos;s `ownerOf`.

The ability to get the owner of a token enables novel use-cases, including the ability for the owner to associate data with it.

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot; and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### Contract Interface

```solidity
interface IERC1155OwnerOf {

    /// @notice Find the owner of an NFT
    /// @dev The zero address indicates that there is no owner: either the token does not exist or it is not an NFT (supply potentially bigger than 1)
    /// @param tokenId The identifier for an NFT
    /// @return The address of the owner of the NFT
    function ownerOf(uint256 tokenId) external view returns (address);
}
```

The `ownerOf(uint256 tokenId)` function MAY be implemented as `pure` or `view`.

The `supportsInterface` method MUST return `true` when called with `0x6352211e`.

## Rationale

`ownerOf` does not throw when a token does not exist (or does not have an owner). This simplifies the handling of such a case. Since it would be a security risk to assume all EIP-721 implementation would throw, it should not break compatibility with contract handling EIP-721 when dealing with this EIP-1155 extension.

## Backwards Compatibility

This EIP is fully backward compatible with EIP-1155.

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 23 Jul 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5409</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5409</guid>
      </item>
    
      <item>
        <title>Security Contact Interface</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-interface-for-security-contract/10303</comments>
        
        <description>## Abstract
An interface for security notice using asymmetric encryption. The interface exposes an asymmetric encryption key and a destination of delivery.

## Motivation
Currently there is no consistent way to specify an official channel for security researchers to report security issues to smart contract maintainers.

## Specification
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.

```solidity
interface IEIP5437 {

    /// REQUIRED
    function getSecurityContact(uint8 type, bytes memory data) public view
    returns (
        uint8 type,
        bytes memory publicKey,
        bytes memory extraData
    );

    /// OPTIONAL
    // TODO consider remove if not needed before finalized
    function setSecurityContact(
        uint8 type,
        bytes memory publicKey,
        bytes memory extraData) public;
    event SecurityContactChanged(uint8 type, bytes memory publicKeyForEncryption, bytes memory extraData);

    /// OPTIONAL
    function securityNotify(uint8 type, bytes memory data) public payable;
    /// OPTIONAL
    event OnSecurityNotification(uint8 type, bytes memory sourceData, uint256 value);

    /// OPTIONAL
    // TODO consider to make it a separate EIP
    function bountyPolicy(uint256 id) public view returns(string, bytes memory extraData);
}
```

1. Compliant interfaces MUST implement the `getSecurityContact` method.

`type` is a one byte data with valid range of `[0x10, 0x7f]`. The ranges of `[0x00, 0x0f]` and `[0x80, 0xff]` are reserved for future extension.

The `type` indicates the format of the `publicKey` and `extraData` in the following way

------------------------------------------------------------------------------------------------
| Type | Encryption scheme                   | extraData                                       |
-------|-------------------------------------|--------------------------------------------------
| 0x10 | GnuPG - RSA/3072                    | Email address(es) encoded in format of RFC 2822 |
------------------------------------------------------------------------------------------------

A new version of this table can be proposed by future EIPs by specifying a new `type` number.

2. The `publicKey` returned from `getSecurityContact` MUST follow the encryption scheme specified
in the table above.

The following is an example of a `publicKey` using `RSA/3072` generated via GnuPG in an RFC 20 ASCII-encoding of the public key string:

```text
-----BEGIN PGP PUBLIC KEY BLOCK-----

mQGNBGLzM2YBDADnCxAW/A0idvKNeQ6s/iYUeIIE+2mWmHcBGqLi0zrfz7pKWI+D
m6Hek51sg2c7ZlswPEp8KqANrj/CV1stXHF+KAZtYeFiAqpIZl1wtB6QgKYWGsJf
sXjBU3duLzLut2yvTfbEZsWAvrEaDjlXywdpboorHvfTE2vOvI6iGcjdh7PW7W7g
IGzlL6ukLGG7y9FUO2dSMjCR/tWMLCupnDDLN2cUHnfEnHZ34FMd61NxcHLC7cIk
P8xkFt8GCxURniTjqI5HAB8bGfR34kflVpr2+iKD5e+vQxcWK7vB443nruVf8osn
udDF8Z6mgl7bKBbGyYH58QsVlmZ8g3E4YaMKjpwOzEK3V2R8Yh4ETdr670ZCRrIz
QWVkibGgmQ3J/9RYps5Hfqpj4wV60Bsh1xUIJEIAs3ubMt7Z5JYFeze7VlXGlwot
P+SnAfKzlZT4CDEl2LEEDrbpnpOEdp0x9hYsEaXTxBGSpTDaxP2MyhW3u6pYeehG
oD0UVTLjWgU+6akAEQEAAbQjc29tZXJlYWxuYW1lIDxncGcubG9jYWwuZ2VuQHp6
bi5pbT6JAdQEEwEIAD4WIQTDk/9jzRZ+lU2cY8rSVJNbud1lrQUCYvMzZgIbAwUJ
EswDAAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRDSVJNbud1lraulDACqFbQg
e9hfoK17UcPVz/u4ZnwmFd9zFAWSYkGqrK9XMvz0R8pr7Y3Dp5hfvaptqID/lHhA
2oPEZ1ViIYDBcqG9WoWjCOYNoIosEAczrvf8YtUC2MHI+5DdYHtST74jDLuWMw3U
AbBXHds3KcRY5/j01kqqi4uwsMBCYyH3Jl3IwjKgy0KDBbuQakvaHPmNnt81ayvZ
ucdsNB9n/JMDxUWNCcySR+cllW4mk68pdiuK5qw0JMaoUjHFoWsgMTbFSlAV/lre
qu8MnrLSs5iPvvaJ3uDOuYROB2FsbvWxayfAAVS1iZf2vQFBJPnDwDdYoPNYMjLp
s2SfU02MVRGp3wanbtvM52uP42SLLNjBqUvJV03/QwfxCRejgAJOBn+iaOxP9NOe
qfQdKzYPbA9FohdkL9991n21XBZcZzAgF9RyU9IZAPAnwZyex1zfzJsUp/HrjhP8
Ljs8MIcjIlmpLk66TmJte4dN5eML1bpohmfMX8k0ILESLSUhxEg1JBNYIDK5AY0E
YvMzZgEMALnIkONpqCkV+yaP8Tb8TBjmM+3TioJQROViINUQZh6lZM3/M+DPxAWZ
r0MIh1a3+o+ThlZ70tlS67w3Sjd62sWAFzALzW4F+gTqjBTh6LURDqDV8OXUrggA
SKK222aDP+Fr21h/TtPLeyDvcgm8Xvi4Cy7Jmf5CfT5jDio7a+FyFBNlTFSVqzLM
TgFOkUFBg8kJKvDjWIrS2fcTkELwZ8+IlQ52YbrXwbDar843x1fRmsY+x9nnuGuP
RYn1U4Jbptu2pEkG5q94jzUzTkGZHCzBJY7a8mtvS0mLqIE0Se1p+HFLY76Rma/F
HB6J4JNOTzBZ0/1FVvUOcMkjuZ2dX81qoCZ8NP6eafzKvNYZrGa5NJnjWO1ag5jQ
D8qHuOwxs8Fy9evmkwAVl51evLFNT532I4LK0zHSbF8MccZjpEFMSKwalKJn02Ml
yTd+ljYLf8SKMOLVps8kc4VyMR1lz0PwSpKDFOmkC1LRURpM7UTtCK+/RFg1OLyQ
SKBmdI37KQARAQABiQG8BBgBCAAmFiEEw5P/Y80WfpVNnGPK0lSTW7ndZa0FAmLz
M2YCGwwFCRLMAwAACgkQ0lSTW7ndZa2oFgv8DAxHtRZchTvjxtdLhQEUSHt80JCQ
zgHd7OUI9EU3K+oDj9AKtKZF1fqMlQoOskgBsLy/xpWwyhatv2ONLtHSjYDkZ7qs
jsXshqpuvJ3X00Yn9PXG1Z1jKl7rzy2/0DnQ8aFP+gktfu2Oat4uIu4YSqRsVW/Z
sbdTsW3T4E6Uf0qUKDf49mK3Y2nhTwY0YZqJnuQkSuUvpuM5a/4zSoaIRz+vSNjX
MoXUIK/f8UnWABPm90OCptTMTzXCC1UXEHTNm6iBJThFiq3GeLZH+GnIola5KLO1
+YbsFEchLfLZ27pWGfIbyppvsuQmrHef+J3g6sXybOWDHVYr3Za1fzxQVIbwoIEe
ndKG0bu7ZAi2b/c8uH/wHT5IvtfzHLeSTjDqG8UyLTnaDxHQZIE9JIzWSQ1DSoNC
YrU7CQtL+/HRpiGFHfClaXln8VWkjnUvp+Fg1ZPtE1t/SKddZ7m29Hd9nzUc0OQW
MOA+HDqgA3a9kWbQKSloORq4unft1eu/FCra
=O6Bf
-----END PGP PUBLIC KEY BLOCK-----
```

3. IF `setSecurityContact` is implemented and a call to it has succeeded in setting a new security contact, an event `SecurityContactChanged` MUST be emitted with the identical passed-in-parameters of `setSecurityContact`

4. It&apos;s also RECOMMENDED that an on-chain security notify method `securityNotify`
be implemented to receive security notice onchain. If it&apos;s implemented and a call
has succeeded, it MUST emit an `OnSecurityNotification` with identical passed-in parameter data.

5. Compliant interfaces MUST implement [EIP-165](/EIPs/EIPS/eip-165).
&lt;!-- TODO: add EIP-165 interfaces. --&gt;
&lt;!-- TODO also consider requiring/recommending implementing EIP-5629 ERC-interface detection. --&gt;

6. It&apos;s recommended to set a bounty policy via the `bountyPolicy` method. The `id = 0` is preserved for a full overview, while other digits are used for different individual bounty policies. The returned
string will be URI to content of bounty policies.
No particular format of bounty policy is specified.

## Rationale
1. For simplicity, this EIP specifies a simple GPG scheme with a given encryption scheme and uses email addresses as a contact method. It&apos;s possible that future EIPs will specify new encryption schemes or delivery methods.
2. This EIP adds an optional method, `setSecurityContact`, to set the security contact, because it might change due to circumstances such as the expiration of the cryptographic keys.
3. This EIP explicitly marks `securityNotify` as `payable`, in order to allow implementers to set a staking amount to report a security vulnerability.
4. This EIP allows for future expansion by adding the `bountyPolicy` and `extraData` fields. Additional values of these fields may be added in future EIPs.

## Backwards Compatibility
Currently, existing solutions such as OpenZeppelin use plaintext in source code

```solidity
/// @custom:security-contact some-user@some-domain.com
```

It&apos;s recommended that new versions of smart contracts adopt this EIP in addition to the legacy `@custom:security-contact` approach.

## Security Considerations

Implementors should properly follow security practices required by the encryption scheme to ensure the security of the chosen communication channel. Some best practices are as follows:

1. Keep security contact information up-to-date;
2. Rotate encryption keys in the period recommended by best practice;
3. Regularly monitor the channel to receive notices in a timely manner.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 09 Aug 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5437</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5437</guid>
      </item>
    
      <item>
        <title>EOF - Stack Validation</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5450-eof-stack-validation/10410</comments>
        
        <description>## Abstract

Introduce extended validation of EOF code sections to guarantee that neither stack underflow nor overflow can happen during execution of validated contracts.

## Motivation

The current EVM performs a number of validity checks for each executed instruction, such as checking
for instruction being defined, stack overflow and underflow, and enough amount of gas remaining.

This EIP minimizes the number of such checks required at run-time
by verifying that no exceptional conditions can happen
and preventing the execution and deployment of any invalid code.

The operand stack validation provides several benefits:

- removes the run-time stack underflow check for all instructions,
- removes the run-time stack overflow check for all instructions except `CALLF` and `JUMPF` (`JUMPF` introduced in a separate EIP) ,
- ensures that execution terminates with one of the terminating instructions,
- prevents deployment of code with unreachable instructions, thereby discouraging the use of code sections for data storage.

It also has some disadvantages:

- adds constraints to the code structure (similar to JVM, CPython bytecode, WebAssembly, SPIR-V and others); however, these constraints can be lifted in a backward-compatible manner if they are shown to be user-unfriendly,
- it is natural to implement stack validation as a second validation pass; however, it is not strictly required and validation&apos;s computational and space complexity remains linear in any implementation variant.

The guarantees created by these validation rules also improve the feasibility of Ahead-Of-Time and Just-In-Time compilation of EVM code. Single pass transpilation passes can be safely executed with the code validation and advanced stack/register handling can be applied with the stack height validations. While not as impactful to a Mainnet validator node that is bound mostly by storage state sizes, these can significantly speed up witness validation and other non-Mainnet use cases.

## Specification

### Code validation

*Remark:* We rely on the notions of *operand stack* and *type section* as defined by [EIP-4750](/EIPs/EIPS/eip-4750).

Each code section is validated independently.

#### Instructions validation

In the first validation phase defined in [EIP-3670](/EIPs/EIPS/eip-3670) (and extended by [EIP-4200](/EIPs/EIPS/eip-4200) and [EIP-4750](/EIPs/EIPS/eip-4750)) instructions are inspected independently to check if their opcodes and immediate values are valid.

#### Operand stack validation

In the second validation phase control-flow analysis is performed on the code.

*Operand stack height* here refers to the number of stack values accessible by this function, i.e. it does not take into account values of caller functions&apos; frames (but does include this function&apos;s inputs). Note that validation procedure does not require actual operand stack implementation, but only to keep track of its height.

*Terminating instructions* refers to the instructions either:

- ending function execution: `RETF`, `JUMPF`, or
- ending call frame execution: `STOP`, `RETURN`, `RETURNCODE`, `REVERT`, `INVALID`.

*note: `JUMPF` and `RETURNCODE` are introduced in separate EIPs.*

*Forward jump* refers to any of `RJUMP`/`RJUMPI`/`RJUMPV` instruction with relative offset greater than or equal to 0. *Backwards jump* refers to any of `RJUMP`/`RJUMPI`/`RJUMPV` instruction with relative offset less than 0, including jumps to the same jump instruction.

Instructions in the code are scanned in a single linear pass over the code. For each instruction the operand stack height bounds are recorded as `stack_height_min` and `stack_height_max`.

The first instruction&apos;s recorded stack height bounds are initialized to be equal to the number of inputs to the function type matching the code (`stack_height_min = stack_height_max = type[code_section_index].inputs`).

For each instruction:

1. **Check** if this instruction has recorded stack height bounds. If it does not, it means it was neither referenced by previous forward jump, nor is part of sequential instruction flow, and this code fails validation.
   - It is a prerequisite to validation algorithm, and code generators are required to order code basic blocks in a way that no block is referenced only by backwards jump. Any program can satisfy this requirement by ordering code basic blocks by the reverse postorder.
2. Determine the effect the instruction has on the operand stack:
   1. **Check** if the recorded stack height bounds satisfy the instruction requirements. Specifically:
      - for `CALLF` instruction the recorded stack height lower bound must be at least the number of inputs of the called function according to its type defined in the type section,
      - for `RETF` instruction both the recorded lower and upper bound must be equal and must be exactly the number of outputs of the function matching the code,
      - for `JUMPF` into returning function both the recorded lower and upper bound must equal exactly `type[current_section_index].outputs + type[target_section_index].inputs - type[target_section_index].outputs`,
      - for `JUMPF` into non-returning function the recorded stack height lower bound must be at least the number of inputs of the target function according to its type defined in the type section,
      - for any other instruction the recorded stack height lower bound must be at least the number of inputs required by instruction,
      - there is no additional check for terminating instructions other than `RETF` and `JUMPF`, this implies that extra items left on stack at instruction ending EVM execution are allowed.
   2. For `CALLF` and `JUMPF` **check** for possible stack overflow: if recorded stack height upper bound is greater than `1024 - types[target_section_index].max_stack_increase`, validation fails.
   3. Compute new stack height bounds after the instruction execution. Upper and lower bound are updated by the same value:
      - after `CALLF` stack height bounds are adjusted by adding `types[target_section_index].outputs - types[target_section_index].inputs`,
      - after any other non-terminating instruction stack height bounds are adjusted by subtracting the number of instruction inputs and adding the number of instruction outputs,
      - terminating instructions do not need to update stack height bounds.
3. Determine the list of successor instructions that can follow the current instructions:
   1. The next instruction if the current instruction is not a terminating instruction nor unconditional jump (`RJUMP`).
   2. All the current instruction targets if the current instruction is a conditional (`RJUMPI` or `RJUMPV`) or unconditional jump (`RJUMP`).
4. For each successor instruction:
   1. **Check** if the instruction is present in the code (i.e. execution must not &quot;fall off&quot; the code).
   2. If the successor is reached via forwards jump or sequential flow from previous instruction:
      1. If the instruction does not have stack height bounds recorded (being visited for the first time), record the instruction stack height bound as the value computed in 2.3.
      2. Otherwise, instruction has been already visited (by previously seen forward jump). Update this instruction&apos;s recorded stack height bounds so that they contain the bounds computed in 2.3, i.e. `target_stack_min = min(target_stack_min, current_stack_min)` and `target_stack_max = max(target_stack_max, current_stack_max)`, where `(target_stack_min, target_stack_max)` are successor bounds and `(current_stack_min, current_stack_max)` are bounds computed in 2.3.
   3. If the successor is reached via backwards jump, **check** if the recorded stack height bounds equal the value computed in 2.3. Validation fails if they are not equal, i.e. we see backwards jump to a different stack height.

After all instructions are visited, determine the function maximum operand stack height increase:

1. Compute the maximum stack height `max_stack_height` as the maximum of all recorded stack height upper bounds.
2. Compute the maximum stack height increase `max_stack_increase` as `max_stack_height - type[current_section_index].inputs`.
3. **Check** if the maximum stack height increase `max_stack_increase` matches the value corresponding code section&apos;s within the type section: `types[current_section_index].max_stack_increase`.

*Note: Although we check only that `max_stack_increase` matches the type section definition, which guarantees that it does not exceed 1023 by EOF header definition, it is also guaranteed that `max_stack_height` does not exceed 1024, because otherwise validation of `CALLF` and `JUMPF` into this section would fail at operand stack overflow check. Every section is required to have `CALLF` or `JUMPF` targeting it, except 0th section (non-reachable sections are not allowed). 0th section is required to have 0 inputs, which implies `max_stack_increase` equals `max_stack_height`.*

The computational and space complexity of this pass is *O(len(code))*. Each instruction is visited at most once.

### Execution

Given the deploy-time validation guarantees, an EVM implementation is not required anymore to have run-time stack underflow nor overflow checks for each executed instruction. The exception is the `CALLF` and `JUMPF` performing operand stack overflow check for the entire called function.

## Rationale

### Properties of validated code

Any code section validated according to operand stack validation has the following properties:

1. There are no unreachable instructions
2. There are no instructions reachable only via backwards jump
3. Operand stack underflow cannot happen.
4. Operand stack overflow can only happen at `CALLF` or `JUMPF` instruction.
5. Multiple forward jump instructions executing at different stack heights may target the same instruction; the stack of target basic block is validated for all possible heights.
6. Any backwards jump instruction can only target an instruction that is executed with equal stack height; this prevents deployment of the loops with unbounded stack pushing or popping.
7. Final instruction in the code section is either terminating instruction or `RJUMP`.

### Stack overflow check only in CALLF/JUMPF

In this EIP, we provide a more efficient variant of the EVM where stack overflow check is performed only in `CALLF` and `JUMPF` instructions using the called function&apos;s `max_stack_height` information. This decreases flexibility of an EVM program because `max_stack_height` corresponds to the worst-case control-flow path in the function.

### Unreachable code

The operand stack validation algorithm rejects any code having any unreachable instructions. This check can be performed very cheaply. It prevents deploying degenerated code. Moreover, it enables combining instruction validation and operand stack validation into single pass.

### Clean stack upon termination

It is currently required that the operand stack is empty (in the current function context) after the `RETF` instruction.
Otherwise, the `RETF` semantic would be more complicated. For `n` function outputs and `s` the stack height at `RETF` the EVM would have to erase `s-n` non-top stack items and move the `n` stack items to the place of erased ones. Cost of such operation may be relatively cheap but is not constant.
However, lifting the requirement and modifying the `RETF` semantic as described above is backward
compatible and can be easily introduced in the future.

### More restrictive stack validation

Originally another variant of stack validation was proposed, where instead of linear scan of the code section, all code paths were examined by following the target(s) of every jump instruction in a breadth-first-search manner, tracking stack height for each visited instruction and checking that for every possible code path to a particular instruction its stack height remains constant.

The advantage of this variant would be somewhat simpler algorithm (we would not need to track stack height bounds, but only a single stack height value for each instruction) and no extra requirement for ordering of code basic blocks (see below).

However, compiler teams opposed to such restrictive stack height requirements. One prominent pattern used by compilers which wouldn&apos;t be possible is jumping to terminating helpers (code blocks ending with `RETURN` or `REVERT`) from different stack heights. This is common for example for a series of `assert` statements, each one compiled to a `RJUMPI` into a shared terminating helper. Enforcing constant stack requirement would mean that before jumping to such helper, extra items on the stack have to be popped, and this noticeably increases code size and consumed gas, and would defeat the purpose of extracting these common terminating sequences into a helper.

### Ordering of basic blocks

The prerequisite to stack validation algorithm is ordering of code basic blocks in a way that no block is referenced only by backwards jump.

This is required to make it possible to examine each instruction in one linear pass over the code section. Forward pass over the code section allows for the algorithm to &quot;expand&quot; each forward jump target&apos;s stack height bounds and still keep the complexity linear. Trying to do jump target stack bounds expansion while scanning the code in the breadth-first-search manner would require to re-examine entire code path after its stack height bounds are expanded, which would result in quadratic complexity.

This requirement is not unique to EOF but also present is some low-level IRs like SPIR-V and LLVM MIR.

## Backwards Compatibility

This change requires a &quot;network upgrade,&quot; since it modifies consensus rules.

It poses no risk to backwards compatibility, as it is introduced only for EOF1 contracts, for which deploying undefined instructions is not allowed, therefore there are no existing contracts using these instructions. The new instructions are not introduced for legacy bytecode (code which is not EOF formatted).

## Security Considerations

As mentioned above, the proposed validation algorithm has linear computational and space complexity and its cost is covered by the transaction data costs [EIP-2028](./eip-2028).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 12 Aug 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5450</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5450</guid>
      </item>
    
      <item>
        <title>Endorsement - Permit for Any Functions</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-5453-endorsement-standard/10355</comments>
        
        <description>## Abstract

This EIP establishes a general protocol for permitting and approving function calls in the same transaction relying on [ERC-5750](/EIPs/EIPS/eip-5750).
Unlike a few prior art ([ERC-2612](/EIPs/EIPS/eip-2612) for [ERC-20](/EIPs/EIPS/eip-20), [ERC-4494](/EIPs/EIPS/eip-4494) for [ERC-721](/EIPs/EIPS/eip-721) that
usually only permit for a single behavior (`transfer` for ERC-20 and `safeTransferFrom` for ERC-721) and a single approver in two transactions (first a `permit(...)` TX, then a `transfer`-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.

## Motivation

1. Support permit(approval) alongside a function call.
2. Support a second approval from another user.
3. Support pay-for-by another user
4. Support multi-sig
5. Support persons acting in concert by endorsements
6. Support accumulated voting
7. Support off-line signatures

## Specification

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

### Interfaces

The interfaces and structures referenced here are as follows

```solidity
pragma solidity ^0.8.9;

struct ValidityBound {
    bytes32 functionParamStructHash;
    uint256 validSince;
    uint256 validBy;
    uint256 nonce;
}

struct SingleEndorsementData {
    address endorserAddress; // 32
    bytes sig; // dynamic = 65
}

struct GeneralExtensionDataStruct {
    bytes32 erc5453MagicWord;
    uint256 erc5453Type;
    uint256 nonce;
    uint256 validSince;
    uint256 validBy;
    bytes endorsementPayload;
}

interface IERC5453EndorsementCore {
    function eip5453Nonce(address endorser) external view returns (uint256);
    function isEligibleEndorser(address endorser) external view returns (bool);
}

interface IERC5453EndorsementDigest {
    function computeValidityDigest(
        bytes32 _functionParamStructHash,
        uint256 _validSince,
        uint256 _validBy,
        uint256 _nonce
    ) external view returns (bytes32);

    function computeFunctionParamHash(
        string memory _functionName,
        bytes memory _functionParamPacked
    ) external view returns (bytes32);
}

interface IERC5453EndorsementDataTypeA {
    function computeExtensionDataTypeA(
        uint256 nonce,
        uint256 validSince,
        uint256 validBy,
        address endorserAddress,
        bytes calldata sig
    ) external view returns (bytes memory);
}


interface IERC5453EndorsementDataTypeB {
    function computeExtensionDataTypeB(
        uint256 nonce,
        uint256 validSince,
        uint256 validBy,
        address[] calldata endorserAddress,
        bytes[] calldata sigs
    ) external view returns (bytes memory);
}
```

See [`IERC5453.sol`](/EIPs/assets/eip-5453/IERC5453.sol).

### Behavior specification

As specified in [ERC-5750 General Extensibility for Method Behaviors](/EIPs/EIPS/eip-5750), any compliant method that has a `bytes extraData` parameter as its
last designated parameter for extending behaviors can conform to [ERC-5453](/EIPs/EIPS/eip-5453) as the way to indicate a permit from a certain user.

1. Any compliant method of this EIP MUST be a [ERC-5750](/EIPs/EIPS/eip-5750) compliant method.
2. Caller MUST pass in the last parameter `bytes extraData` conforming to Solidity memory-encoded bytes of `GeneralExtensionDataStruct` specified in _Section Interfaces_. The following descriptions are based on when decoding `bytes extraData` into a `GeneralExtensionDataStruct`
3. In the `GeneralExtensionDataStruct`-decoded `extraData`, caller MUST set the value of `GeneralExtensionDataStruct.erc5453MagicWord` to be the `keccak256(&quot;ERC5453-ENDORSEMENT&quot;)`.
4. Caller MUST set the value of `GeneralExtensionDataStruct.erc5453Type` to be one of the supported values.

```solidity
uint256 constant ERC5453_TYPE_A = 1;
uint256 constant ERC5453_TYPE_B = 2;
```

5. When the value of `GeneralExtensionDataStruct.erc5453Type` is set to be `ERC5453_TYPE_A`, `GeneralExtensionDataStruct.endorsementPayload` MUST be abi encoded bytes of a `SingleEndorsementData`.
6. When the value of `GeneralExtensionDataStruct.erc5453Type` is set to be `ERC5453_TYPE_B`, `GeneralExtensionDataStruct.endorsementPayload` MUST be abi encoded bytes of `SingleEndorsementData[]` (a dynamic array).

7. Each `SingleEndorsementData` MUST have a `address endorserAddress;` and a 65-bytes `bytes sig` signature.

8. Each `bytes sig` MUST be an ECDSA (secp256k1) signature using private key of signer whose corresponding address is `endorserAddress` signing `validityDigest` which is the hashTypeDataV4 of [EIP-712](/EIPs/EIPS/eip-712) of hashStruct of `ValidityBound` data structure as follows:

```solidity
bytes32 validityDigest =
    eip712HashTypedDataV4(
        keccak256(
            abi.encode(
                keccak256(
                    &quot;ValidityBound(bytes32 functionParamStructHash,uint256 validSince,uint256 validBy,uint256 nonce)&quot;
                ),
                functionParamStructHash,
                _validSince,
                _validBy,
                _nonce
            )
        )
    );
```

9. The `functionParamStructHash` MUST be computed as follows

```solidity
        bytes32 functionParamStructHash = keccak256(
            abi.encodePacked(
                keccak256(bytes(_functionStructure)),
                _functionParamPacked
            )
        );
        return functionParamStructHash;
```

whereas

- `_functionStructure` MUST be computed as `function methodName(type1 param1, type2 param2, ...)`.
- `_functionParamPacked` MUST be computed as `enc(param1) || enco(param2) ...`

10. Upon validating that `endorserAddress == ecrecover(validityDigest, signature)` or `EIP1271(endorserAddress).isValidSignature(validityDigest, signature) == ERC1271.MAGICVALUE`, the single endorsement MUST be deemed valid.
11. Compliant method MAY choose to impose a threshold for a number of endorsements needs to be valid in the same `ERC5453_TYPE_B` kind of `endorsementPayload`.

12. The `validSince` and `validBy` are both inclusive. Implementer MAY choose to use blocknumber or timestamp. Implementors SHOULD find a way to indicate whether `validSince` and `validBy` is blocknumber or timestamp.

## Rationale

1. We chose to have both `ERC5453_TYPE_A`(single-endorsement) and `ERC5453_TYPE_B`(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 [ERC-4494](/EIPs/EIPS/eip-4494) can be supported by `ERC5453_TYPE_A`. And threshold approvals can be done via `ERC5453_TYPE_B`. More complicated approval types can also be extended by defining new `ERC5453_TYPE_?`

2. We chose to include both `validSince` and `validBy` to allow maximum flexibility in expiration. This can also be supported natively by the EVM if [ERC-5081](/EIPs/EIPS/eip-5081) is adopted, but [ERC-5081](/EIPs/EIPS/eip-5081) will not be adopted anytime soon, so we choose to add these two numbers in our protocol to allow
smart contract level support.

## Backwards Compatibility

The design assumes a `bytes calldata extraData` to maximize the flexibility of future extensions. This assumption is compatible with [ERC-721](/EIPs/EIPS/eip-721), [ERC-1155](/EIPs/EIPS/eip-1155) and many other ERC-track EIPs. Those that aren&apos;t, such as [ERC-20](/EIPs/EIPS/eip-20), can also be updated to support it, such as using a wrapper contract or proxy upgrade.

## Reference Implementation

In addition to the specified algorithm for validating endorser signatures, we also present the following reference implementations.

```solidity
pragma solidity ^0.8.9;

import &quot;@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol&quot;;
import &quot;@openzeppelin/contracts/utils/cryptography/EIP712.sol&quot;;

import &quot;./IERC5453.sol&quot;;

abstract contract AERC5453Endorsible is EIP712,
    IERC5453EndorsementCore, IERC5453EndorsementDigest, IERC5453EndorsementDataTypeA, IERC5453EndorsementDataTypeB {
    // ...

    function _validate(
        bytes32 msgDigest,
        SingleEndorsementData memory endersement
    ) internal virtual {
        require(
            endersement.sig.length == 65,
            &quot;AERC5453Endorsible: wrong signature length&quot;
        );
        require(
            SignatureChecker.isValidSignatureNow(
                endersement.endorserAddress,
                msgDigest,
                endersement.sig
            ),
            &quot;AERC5453Endorsible: invalid signature&quot;
        );
    }
    // ...

    modifier onlyEndorsed(
        bytes32 _functionParamStructHash,
        bytes calldata _extensionData
    ) {
        require(_isEndorsed(_functionParamStructHash, _extensionData));
        _;
    }

    function computeExtensionDataTypeB(
        uint256 nonce,
        uint256 validSince,
        uint256 validBy,
        address[] calldata endorserAddress,
        bytes[] calldata sigs
    ) external pure override returns (bytes memory) {
        require(endorserAddress.length == sigs.length);
        SingleEndorsementData[]
            memory endorsements = new SingleEndorsementData[](
                endorserAddress.length
            );
        for (uint256 i = 0; i &lt; endorserAddress.length; ++i) {
            endorsements[i] = SingleEndorsementData(
                endorserAddress[i],
                sigs[i]
            );
        }
        return
            abi.encode(
                GeneralExtensionDataStruct(
                    MAGIC_WORLD,
                    ERC5453_TYPE_B,
                    nonce,
                    validSince,
                    validBy,
                    abi.encode(endorsements)
                )
            );
    }
}

```

See [`AERC5453.sol`](/EIPs/assets/eip-5453/AERC5453.sol)

### Reference Implementation of `EndorsableERC721`

Here is a reference implementation of `EndorsableERC721` that achieves similar behavior to [ERC-4494](/EIPs/EIPS/eip-4494).

```solidity
pragma solidity ^0.8.9;

contract EndorsableERC721 is ERC721, AERC5453Endorsible {
    //...

    function mint(
        address _to,
        uint256 _tokenId,
        bytes calldata _extraData
    )
        external
        onlyEndorsed(
            _computeFunctionParamHash(
                &quot;function mint(address _to,uint256 _tokenId)&quot;,
                abi.encode(_to, _tokenId)
            ),
            _extraData
        )
    {
        _mint(_to, _tokenId);
    }
}
```

See [`EndorsableERC721.sol`](/EIPs/assets/eip-5453/EndorsableERC721.sol)

### Reference Implementation of `ThresholdMultiSigForwarder`

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

```solidity
pragma solidity ^0.8.9;

contract ThresholdMultiSigForwarder is AERC5453Endorsible {
    //...
    function forward(
        address _dest,
        uint256 _value,
        uint256 _gasLimit,
        bytes calldata _calldata,
        bytes calldata _extraData
    )
        external
        onlyEndorsed(
            _computeFunctionParamHash(
                &quot;function forward(address _dest,uint256 _value,uint256 _gasLimit,bytes calldata _calldata)&quot;,
                abi.encode(_dest, _value, _gasLimit, keccak256(_calldata))
            ),
            _extraData
        )
    {
        string memory errorMessage = &quot;Fail to call remote contract&quot;;
        (bool success, bytes memory returndata) = _dest.call{value: _value}(
            _calldata
        );
        Address.verifyCallResult(success, returndata, errorMessage);
    }

}

```

See [`ThresholdMultiSigForwarder.sol`](/EIPs/assets/eip-5453/ThresholdMultiSigForwarder.sol)

## Security Considerations

### Replay Attacks

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 _public_ 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 `chainId`, or any other similar attack surfaces. The `nonce`, `validSince`, and `validBy` fields are meant to restrict the surface of attack but might not fully eliminate the risk of all such attacks, e.g. see the [Phishing](#phishing) section.

### Phishing

It&apos;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

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>CREATE2COPY Opcode</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5478-reducing-the-gas-cost-of-contract-creation-with-existing-code/10419</comments>
        
        <description>## Abstract

Adding a new opcode, `CREATE2COPY`, that is identical to `CREATE2` but with potentially much lower gas cost by accepting an additional argument `existing_contract_address` that already stored the code of the new contract.

## Motivation

This EIP aims to reduce the smart contract creation cost of account abstraction (AA) contracts that have identical code.

The major cost of creating an AA contract is the contract creation cost, especially data gas. For example, creating an AA contract with 10,000 bytes will consume 2,000,000 data gas. Considering the code for each user&apos;s AA contract is the same, `CREATE2COPY` can reduce the data gas cost to 2600 (cold account) or even 100 (warm account) if the contract code already exists in the local storage.

## Specification

### Parameters

| Constant                     | Value            |
| ---------------------------- | ---------------- |
| `FORK_BLKNUM`                | TBD              |
| `CREATE_DATA_GAS_PER_BYTE`   | 200              |
| `COLD_ACCOUNT_ACCESS_COST`   | 2600             |
| `WARM_ACCOUNT_ACCESS_COST`   | 100              |

If `block.number &gt;= FORK_BLKNUM`, a new opcode is added (`CREATE2COPY`) at `0xf6`, which takes 5 stack arguments: `endowment`, `memory_start`, `memory_length`, `salt`, `existing_contract_address`. `CREATE2COPY` behaves identically to `CREATE2` (`0xf5` as defined in [EIP-1014](/EIPs/EIPS/eip-1014)), except that the code hash of the creating contract MUST be the same as that of `existing_contract_address`.

`CREATE2COPY` has the same `gas` schema as `CREATE2`, but replacing the data gas from `CREATE_DATA_GAS_PER_BYTE * CONTRACT_BYTES` to the gas cost of `EXTCODEHASH` opcode, which is `COLD_ACCOUNT_ACCESS_COST` if the `existing_contract_address` is first-time accessed in the transaction or `WARM_ACCOUNT_ACCESS_COST` if `existing_contract_address` is already in the access list according to [EIP-2929](/EIPs/EIPS/eip-2929).

If the code of the contract returned from the init code differs from that of `existing_contract_address`, the creation fails with the error &quot;mismatched contract creation code with existing code&quot;, and will burn all gas for the contract creation.
## Rationale

TBD
## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 17 Aug 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5478</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5478</guid>
      </item>
    
      <item>
        <title>Consensual Soulbound Tokens</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5484-consensual-soulbound-tokens/10424</comments>
        
        <description>## Abstract

This EIP defines an interface extending [EIP-721](/EIPs/EIPS/eip-721) to create soulbound tokens. Before issuance, both parties (the issuer and the receiver), have to agree on who has the authorization to burn this token. Burn authorization is immutable after declaration. After its issuance, a soulbound token can&apos;t be transferred, but can be burned based on a predetermined immutable burn authorization.

## Motivation

The idea of soulbound tokens has gathered significant attention since its publishing. Without a standard interface, however, soulbound tokens are incompatible. It is hard to develop universal services targeting at soulbound tokens without minimal consensus on the implementation of the tokens.

This EIP envisions soulbound tokens as specialized NFTs that will play the roles of credentials, credit records, loan histories, memberships, and many more. In order to provide the flexibility in these scenarios, soulbound tokens must have an application-specific burn authorization and a way to distinguish themselves from regular EIP-721 tokens.

## Specification

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.

- The token MUST implement the following interfaces:

  1. [EIP-165](/EIPs/EIPS/eip-165)’s `ERC165` (`0x01ffc9a7`)
  1. [EIP-721](/EIPs/EIPS/eip-721)’s `ERC721` (`0x80ac58cd`)

- `burnAuth` SHALL be presented to receiver before issuance.
- `burnAuth` SHALL be Immutable after issuance.
- `burnAuth` SHALL be the sole factor that determines which party has the rights to burn token.
- The issuer SHALL present token metadata to the receiver and acquire receiver&apos;s signature before issuance.
- The issuer SHALL NOT change metadata after issuance.

/// Note: the EIP-165 identifier for this interface is 0x0489b56f

### Contract Interface

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

interface IERC5484 {
    /// A guideline to standardlize burn-authorization&apos;s number coding
    enum BurnAuth {
        IssuerOnly,
        OwnerOnly,
        Both,
        Neither
    }

    /// @notice Emitted when a soulbound token is issued.
    /// @dev This emit is an add-on to nft&apos;s transfer emit in order to distinguish sbt 
    /// from vanilla nft while providing backward compatibility.
    /// @param from The issuer
    /// @param to The receiver
    /// @param tokenId The id of the issued token
    event Issued (
        address indexed from,
        address indexed to,
        uint256 indexed tokenId,
        BurnAuth burnAuth
    );

    /// @notice provides burn authorization of the token id.
    /// @dev unassigned tokenIds are invalid, and queries do throw
    /// @param tokenId The identifier for a token.
    function burnAuth(uint256 tokenId) external view returns (BurnAuth);
}
```

## Rationale

### Soulbound Token (SBTs) as an extension to EIP-721

We believe that soulbound token serves as a specialized subset of the existing EIP-721 tokens. The advantage of such design is seamless compatibility of soulbound token with existing NFT services. Service providers can treat SBTs like NFTs and do not need to make drastic changes to their existing codebase.

### Non-Transferable

One problem with current soulbound token implementations that extend from [EIP-721](/EIPs/EIPS/eip-721) is that all transfer implementations throw errors. A much cleaner approach would be for transfer functions to still throw, but also enable third parties to check beforehand if the contract implements the soulbound interface to avoid calling transfer.

### Burn Authorization

We want maximum freedom when it comes to interface usage. A flexible and predetermined rule to burn is crucial. Here are some sample scenarios for different burn authorizations:

- `IssuerOnly`: Loan record
- `ReceiverOnly`: Paid membership
- `Both`: Credentials
- `Neither`: Credit history

Burn authorization is tied to specific tokens and immutable after issuance. It is therefore important to inform the receiver and gain receiver&apos;s consent before the token is issued.

### Issued Event

On issuing, an `Issued` event will be emitted alongside [EIP-721](/EIPs/EIPS/eip-721)&apos;s `Transfer` event. This design keeps backward compatibility while giving clear signals to thrid-parties that this is a soulBound token issuance event.

### Key Rotations

A concern Ethereum users have is that soulbound tokens having immutable ownership discourage key rotations. This is a valid concern. Having a burnable soulbound token, however, makes key rotations achievable. The owner of the soulbound token, when in need of key rotations, can inform the issuer of the token. Then the party with burn authorization can burn the token while the issuer can issue a replica to the new address.

## Backwards Compatibility

This proposal is fully backward compatible with [EIP-721](/EIPs/EIPS/eip-721)

## Security Considerations

There are no security considerations related directly to the implementation of this standard.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 17 Aug 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5484</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5484</guid>
      </item>
    
      <item>
        <title>Jurisdiction, Accreditation, and Enforcement</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-5485-interface-for-legitimacy-jurisdiction-and-sovereignty/10425</comments>
        
        <description>## Abstract

Defines a standard interface for smart contracts to declare their sovereignty status, observed jurisdiction, accreditation within that jurisdiction, and the mechanisms by which they may receive, and record enforcement actions.

## Motivation

Smart contracts are, in essence, digital agreements whose execution is enforced by network consensus. As their use increasingly expands into domains that mirror real-world legal or institutional relationships, one critical component present in traditional systems is missing on-chain: a structured way to express sovereignty, jurisdiction, accreditation, and enforcement.

Historically, much of the smart-contract ecosystem has emphasized decentralization and self-sovereignty, implicitly assuming that contracts do not rely on any external legal or institutional framework. However, many practical use cases—especially those that interface with real-world regulations, property rights, or compliance regimes—require an explicit identification of the jurisdiction(s) a contract observes, the authority that has accredited it as a valid actor within that jurisdiction, and the mechanisms by which binding decisions may be communicated to it.

This ERC proposes a standardized interface for representing four foundational concepts:

- **Sovereignty** — whether a contract is self-sovereign or claims allegiance to a higher-order system;
- **Jurisdiction** — which external authority it chooses to observe;
- **Accreditation** — whether that authority formally recognizes the contract as a valid participant within its system; and
- **Enforcement** — how decisions, rulings, or binding actions issued by that authority can be delivered to and acknowledged by the contract.

In many real-world and institutional settings, an entity becomes an actionable participant only after receiving formal accreditation by the relevant authority—whether this is a state chartering a corporation, a school recognizing a student club, a platform onboarding a developer, or a DAO admitting a module into its governance structure. Conversely, some entities explicitly declare their absence of external jurisdictional alignment, operating instead as sovereign actors such as declaration of independence as newly established countries gain their sovereignty, or joining a jurisdictional system as a newly established entity. Representing both modes—subordination and self-sovereignty—is essential for accurately modeling institutional relationships on-chain.

By standardizing how smart contracts declare sovereignty, jurisdiction, accreditation, and enforcement pathways, this ERC enables interoperability between legal systems, regulatory frameworks, institutional hierarchies, and on-chain governance models—bridging a structural gap between real-world systems and their digital counterparts.

### Use Cases (Primary)

The primary use cases address questions related to the status of a contract itself.

- **Stablecoins (e.g., USDC):** Require jurisdiction because reserve custody, redemptions, freezes, and regulatory compliance depend on a specific legal authority.
- **Tokenized Stocks / RWAs:** Require jurisdiction because securities laws, transfer restrictions, investor rights, and enforcement vary entirely by legal venue.
- **Regulated Lending Protocols:** Require jurisdiction to define collateral rights, default resolution, licensing requirements, and enforceability of loan agreements.
- **Private Company Equity for Qualified Investors:** Require jurisdiction to enforce accreditation rules, transfer limits, corporate law, and cap-table validity.

### Use Cases (Secondary)

The secondary use cases address the questions related to the interactions between contracts.

- **Jurisdiction Compatibility Checks:** Ensuring that interacting contracts operate under compatible or acceptable jurisdictions.
- **Regulatory Boundary Enforcement:** Gateways, bridges, or marketplaces can restrict integration to contracts meeting specific jurisdictional or accreditation requirements.
- **Good-Standing Verification:** Validating whether a contract is accredited and in compliance under its declared jurisdiction.
- **Jurisdiction-Based Access Control:** Allowing or restricting participation based on jurisdiction or accreditation metadata.
- **Cross-Contract Legal Cohesion:** Ensuring coherent jurisdictional alignment across multi-contract systems, federated DAOs, or hierarchical governance structures.
- **Automated Dispute-Path Selection:** Determining which arbitration venue, legal process, or enforcement route applies when disputes arise

## Specification

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.

A contract compliant with this ERC MUST implement the interface defined below.
The interface provides standardized primitives for declaring a contract’s accreditation source, its observed jurisdiction, and a mechanism for receiving structured enforcement proposals. When the jurisdiction is absent, a contract is self-sovereign.

### 1. Data Structures

For backward compatibility with existing contracts that implement
[ERC-5247](/EIPs/EIPS/eip-5247), the interface extends
the `IERC5247Executable` and `IERC5247Executables` data structures.

#### `IERC5247Executable`

Represents a single action that MAY be proposed as part of an enforcement submission.
This structure follows a generic “executable call” pattern: a target address, an optional ETH value, a gas limit, and calldata for invocation.
No guarantees are made regarding execution; implementations MAY ignore or reinterpret these fields.

```solidity
/// @notice A single executable action that MAY be proposed as part of an enforcement.
struct IERC5247Executable {
    /// @notice The target address to be called if this executable is processed.
    address target;

    /// @notice The amount of ETH (in wei) to send along with the call to `target`.
    uint256 value;

    /// @notice The gas limit for the call. Implementations MAY ignore this field.
    uint256 gasLimit;

    /// @notice The calldata to send to `target`.
    bytes data;
}
```

#### `IERC5247Executables`

A batch of `IERC5247Executable` items representing an ordered enforcement proposal.

```solidity
/// @notice A batch of executable actions forming an enforcement proposal.
struct IERC5247Executables {
    /// @notice Ordered list of executable actions included in this proposal.
    IERC5247Executable[] executables;
}
```

### 2. Interface

#### `sourceOfAccreditation()`

Returns the address that accredited this contract as a valid participant within some jurisdiction or governance system.

* MUST return the accrediting authority’s address if one exists.
* MUST return `address(0)` if the contract does not recognize any external accreditation source (e.g., self-sovereign behavior).
* SHOULD remain stable over the contract’s lifetime or change only through a defined governance or upgrade mechanism.

#### `jurisdiction()`

Returns the primary jurisdiction or system whose rules this contract claims to observe.

* MAY return the same address as `sourceOfAccreditation()` when a single contract performs both roles.
* MUST return `address(0)` if the contract claims no external jurisdiction.
* Represents the higher-order system the contract aligns with, independently of accreditation.

#### `imposeEnforcement(IERC5247Executables _proposal)`

A standardized entry point for submitting an enforcement proposal to the contract.

* Implementations MUST define and document the access control for this function (e.g., restricted to `jurisdiction()`, `sourceOfAccreditation()`, or a curated authority list).
* Implementations MAY:

  * immediately execute some or all proposed actions,
  * record the proposal for later deliberation,
  * partially honor or completely ignore the proposal based on policy.
* Implementations SHOULD emit events or persist state enabling verifiable on-chain acknowledgment that an enforcement attempt occurred.
* The function is payable to allow ETH to accompany proposals when executables specify non-zero `value` or when processing fees apply.

### Full Interface

```solidity
interface IERC5485 {
    /// @notice Returns the address that accredited this contract, if any.
    /// @dev MUST return address(0) if the contract does not recognize
    ///      an external accreditation source. SHOULD remain stable or change
    ///      only via defined governance.
    function sourceOfAccreditation() external view returns (address);

    /// @notice Returns the jurisdiction or higher-order system this contract
    ///      observes.
    /// @dev MAY be the same as `sourceOfAccreditation()`. MUST return address(0)
    ///      when the contract claims no external jurisdiction (self-sovereign
    ///      behavior). SHOULD remain stable or change only via defined governance.
    function jurisdiction() external view returns (address);

    /// @notice Submits an enforcement proposal to this contract.
    /// @dev Implementations MUST define access control. Implementations MAY execute,
    ///      schedule, partially honor, reject, or only record `_proposal`.
    /// @dev Implementations SHOULD emit events or store state acknowledging receipt of
    ///      enforcement proposals. Payable to allow ETH forwarding for executables that
    ///      specify non-zero value.
    function imposeEnforcement(IERC5247Executables _proposal) external payable;
}
```

## Rationale

### Separation of Jurisdiction and Accreditation

This ERC separates **jurisdiction** from **accreditation** because
they represent fundamentally different relationships:

- **Jurisdiction is voluntary.**
  A contract may unilaterally declare that it observes the rules or
  norms of a particular system.

- **Accreditation requires external approval.**
  Only the authority itself can grant formal recognition that a contract
  is an accepted participant within its system.

- **Jurisdiction expresses alignment; accreditation expresses acceptance.**
  Declaring jurisdiction does not imply the authority recognizes the contract.
  Accreditation establishes the reciprocal relationship.

- **Accreditation enables enforcement.**
  Authorities typically issue enforcement only to contracts they have
  accredited. Jurisdiction alone does not create this binding pathway.

Keeping these concepts distinct reflects how real-world institutions work:
observing a system’s rules is self-declared, but gaining formal standing
within that system requires an explicit action by the authority. This
 distinction ensures more accurate modeling of institutional relationships
 on-chain.


## Backwards Compatibility

1. The absence of accreditation and jurisdiction is backward compatible with
existing contracts, as it is a superset of the existing behavior. More
explicitly, a contract that does not implement this interface observes no
jurisdiction, by default showing no accreditation and is considered
self-sovereign.

2. Using [ERC-5247](/EIPs/EIPS/eip-5247) as a base interface for enforcement proposals is backward
compatible with existing contracts that implement [ERC-5247](/EIPs/EIPS/eip-5247), such as Multi-Sig
wallets such as the treasury of a DAO.

## Security Considerations

Similar to a real-world scenario, when observing a jurisdiction
practically gives the contract the ability to enforce rules on the
contract&apos;s behavior. Similar to &quot;Ownable&quot; ([ERC-173](/EIPs/EIPS/eip-173)) or &quot;AccessControl&quot;,
implementations MUST be aware of the security implications of this: the
security of a contract is compromised if the jurisdiction is compromised.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 17 Aug 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5485</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5485</guid>
      </item>
    
      <item>
        <title>NFT Hyperlink Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5489-nft-hyperlink-extension/10431</comments>
        
        <description>## Abstract

This EIP proposes a new extension for NFTs (non-fungible token, aka [EIP-721](/EIPs/EIPS/eip-721)): nft-hyperlink-extention (hNFT), embedding NFTs with hyperlinks, referred to as “hNFTs”. As owners of hNFTs, users may authorize a URL slot to a specific address which can be either an externally-owned account (EOA) or a contract address and hNFT owners are entitled to revoke that authorization at any time. The address which has slot authorization can manage the URL of that slot.


## Motivation

As NFTs attract more attention, they have the potential to become the primary medium of Web3. Currently, end users can’t attach rich texts, videos, or images to NFTs, and there’s no way to render these rich-content attachments. Many industries eagerly look forward to this kind of rich-content attachment ability. Attaching, editing, and displaying highly customized information can usefully be standardized.

This EIP uses hyperlinks as the aforementioned form of “highly customized attachment on NFT”, and also specifies how to attach, edit, and display these attachments on NFTs.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### Interface

#### `IERC5489`

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

interface IERC5489 {
    /**
     * @dev this event emits when the slot on `tokenId` is authorzized to `slotManagerAddr`
     */
    event SlotAuthorizationCreated(uint256 indexed tokenId, address indexed slotManagerAddr);

    /**
     * @dev this event emits when the authorization on slot `slotManagerAddr` of token `tokenId` is revoked.
     * So, the corresponding DApp can handle this to stop on-going incentives or rights
     */
    event SlotAuthorizationRevoked(uint256 indexed tokenId, address indexed slotManagerAddr);

    /**
     * @dev this event emits when the uri on slot `slotManagerAddr` of token `tokenId` has been updated to `uri`.
     */
    event SlotUriUpdated(uint256 indexed tokenId, address indexed slotManagerAddr, string uri);

    /**
     * @dev
     * Authorize a hyperlink slot on `tokenId` to address `slotManagerAddr`.
     * Indeed slot is an entry in a map whose key is address `slotManagerAddr`.
     * Only the address `slotManagerAddr` can manage the specific slot.
     * This method will emit SlotAuthorizationCreated event
     */
    function authorizeSlotTo(uint256 tokenId, address slotManagerAddr) external;

    /**
     * @dev
     * Revoke the authorization of the slot indicated by `slotManagerAddr` on token `tokenId`
     * This method will emit SlotAuthorizationRevoked event
     */
    function revokeAuthorization(uint256 tokenId, address slotManagerAddr) external;

    /**
     * @dev
     * Revoke all authorizations of slot on token `tokenId`
     * This method will emit SlotAuthorizationRevoked event for each slot
     */
    function revokeAllAuthorizations(uint256 tokenId) external;

    /**
     * @dev
     * Set uri for a slot on a token, which is indicated by `tokenId` and `slotManagerAddr`
     * Only the address with authorization through {authorizeSlotTo} can manipulate this slot.
     * This method will emit SlotUriUpdated event
     */
    function setSlotUri(
        uint256 tokenId,
        string calldata newUri
    ) external;

    /**
     * @dev Throws if `tokenId` is not a valid NFT. URIs are defined in RFC 3986.
     * The URI MUST point to a JSON file that conforms to the &quot;EIP5489 Metadata JSON schema&quot;.
     * 
     * returns the latest uri of an slot on a token, which is indicated by `tokenId`, `slotManagerAddr`
     */
    function getSlotUri(uint256 tokenId, address slotManagerAddr)
        external
        view
        returns (string memory);
}
```

The `authorizeSlotTo(uint256 tokenId, address slotManagerAddr)` function MAY be implemented as public or external.

The `revokeAuthorization(uint256 tokenId, address slotManagerAddr)` function MAY be implemented as public or external.

The `revokeAllAuthorizations(uint256 tokenId)` function MAY be implemented as public or external.

The `setSlotUri(uint256 tokenId, string calldata newUri)` function MAY be implemented as public or external.

The `getSlotUri(uint256 tokenId, address slotManagerAddr)` function MAY be implemented as pure or view.

The `SlotAuthorizationCreated` event MUST be emitted when a slot is authorized to an address.

The `SlotAuthorizationRevoked` event MUST be emitted when a slot authorization is revoked.

The `SlotUriUpdated` event MUSt be emitted when a slot&apos;s URI is changed.

The `supportInterface` method MUST return true when called with `0x8f65987b`.

### Authentication

The `authorizeSlotTo`, `revokeAuthorization`, and `revokeAllAuthorizations` functions are authenticated if and only if the message sender is the owner of the token.

### Metadata JSON schema

```json
{
    &quot;title&quot;: &quot;AD Metadata&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;icon&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;A URI pointing to a resource with mime type image/* representing the slot&apos;s occupier. Consider making any images at a width between 48 and 1080 pixels and aspect ration between 1.91:1 and 4:5 inclusive. Suggest to show this as an thumbnail of the target resource&quot;
        },
        &quot;description&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;A paragraph which briefly introduce what is the target resource&quot;
        },
        &quot;target&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;A URI pointing to target resource, sugguest to follow 30X status code to support more redirections, the mime type and content rely on user&apos;s setting&quot;
        } 
    }
}
```

## Rationale

### Extends NFT with hyperlinks

URIs are used to represent the value of slots to ensure enough flexibility to deal with different use cases.

### Authorize slot to address

We use addresses to represent the key of slots to ensure enough flexibility to deal with all use cases.

## Backwards Compatibility

As mentioned in the specifications section, this standard can be fully EIP-721 compatible by adding an extension function set.

In addition, new functions introduced in this standard have many similarities with the existing functions in EIP-721. This allows developers to easily adopt the standard quickly.

## Reference Implementation

You can find an implementation of this standard in [`ERC5489.sol`](/EIPs/assets/eip-5489/contracts/ERC5489.sol).

## Security Considerations

No security considerations were found.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 16 Aug 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5489</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5489</guid>
      </item>
    
      <item>
        <title>Multi-privilege Management NFT Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5496-multi-privilege-management-extension-for-erc-721/10427</comments>
        
        <description>## Abstract

This EIP defines an interface extending [EIP-721](/EIPs/EIPS/eip-721) 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.

## Motivation

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.

[EIP-721](/EIPs/EIPS/eip-721) 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.

For example, an airline company issues a series of [EIP-721](/EIPs/EIPS/eip-721)/[EIP-1155](/EIPs/EIPS/eip-1155) 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.

## Specification

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.

Every contract complying with this standard MUST implement the `IERC5496` interface. The **shareable multi-privilege extension** is OPTIONAL for EIP-721 contracts.

```solidity
/// @title multi-privilege extension for EIP-721
///  Note: the EIP-165 identifier for this interface is 0x076e1bbb
interface IERC5496{
    /// @notice Emitted when `owner` changes the `privilege holder` of a NFT.
    event PrivilegeAssigned(uint256 tokenId, uint256 privilegeId, address user, uint256 expires);
    /// @notice Emitted when `contract owner` changes the `total privilege` of the collection
    event PrivilegeTotalChanged(uint256 newTotal, uint256 oldTotal);

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

    /// @notice Return the expiry timestamp of a privilege
    /// @param tokenId The identifier of the queried NFT
    /// @param privilegeId The identifier of the queried privilege
    /// @return Whether a user has a certain privilege
    function privilegeExpires(uint256 tokenId, uint256 privilegeId) external view returns(uint256);

    /// @notice Check if a user has a certain privilege
    /// @param tokenId The identifier of the queried NFT
    /// @param privilegeId The identifier of the queried privilege
    /// @param user The address of the queried user
    /// @return Whether a user has a certain privilege
    function hasPrivilege(uint256 tokenId, uint256 privilegeId, address user) external view returns(bool);
}
```

Every contract implementing this standard SHOULD set a maximum privilege number before setting any privilege, the `privilegeId` MUST NOT be greater than the maximum privilege number.

The `PrivilegeAssigned` event MUST be emitted when `setPrivilege` is called.

The `PrivilegeTotalChanged` event MUST be emitted when the `total privilege` of the collection is changed.

The `supportsInterface` method MUST return `true` when called with `0x076e1bbb`.

```solidity
/// @title Cloneable extension - Optional for EIP-721
interface IERC721Cloneable {
    /// @notice Emitted when set the `privilege ` of a NFT cloneable.
    event PrivilegeCloned(uint tokenId, uint privId, address from, address to);

    /// @notice set a certain privilege cloneable
    /// @param tokenId The identifier of the queried NFT
    /// @param privilegeId The identifier of the queried privilege
    /// @param referrer The address of the referrer
    /// @return Whether the operation is successful or not
    function clonePrivilege(uint tokenId, uint privId, address referrer) external returns (bool);
}
```

The `PrivilegeCloned` event MUST be emitted when `clonePrivilege` is called.

For Compliant contract, it is RECOMMENDED to use [EIP-1271](/EIPs/EIPS/eip-1271) to validate the signatures.

## Rationale

### Shareable Privileges

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.

### Expire Date Type

The expiry timestamp of a privilege is a timestamp and stored in `uint256` typed variables.

### Beneficiary of Referrer

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&apos;s say Tom gets 30% off Coupon from the shop and he shares the coupon with Alice. Alice gets the coupon too and Alice&apos;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.

### Proposal: NFT Transfer

If the owner of the NFT transfers ownership to another user, there is no impact on &quot;privileges&quot;. But errors may occur if the owner tries to withdraw the original [EIP-721](/EIPs/EIPS/eip-721) token from the wrapped NFT through `unwrap()` 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.

```solidity
function unwrap(uint256 tokenId, address to) external {
    require(getBlockTimestamp() &gt;= privilegeBook[tokenId].lastExpiresAt, &quot;privilege not yet expired&quot;);

    require(ownerOf(tokenId) == msg.sender, &quot;not owner&quot;);

    _burn(tokenId);

    IERC721(nft).transferFrom(address(this), to, tokenId);

    emit Unwrap(nft, tokenId, msg.sender, to);
}
```

## Backwards Compatibility

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 [EIP-721](/EIPs/EIPS/eip-721) standard.

## Test Cases

Test cases are implemented with the reference implementation.

### Test Code

[test.js](/EIPs/assets/eip-5496/test/test.js)

Run in terminal:

```shell
truffle test ./test/test.js
```

[testCloneable.js](/EIPs/assets/eip-5496/test/testCloneable.js)

Run in terminal:

```shell
truffle test ./test/testCloneable.js
```

## Reference Implementation

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0; 

import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;
import &quot;@openzeppelin/contracts/utils/introspection/IERC165.sol&quot;;
import &quot;./IERC5496.sol&quot;;

contract ERC5496 is ERC721, IERC5496 {
    struct PrivilegeRecord {
        address user;
        uint256 expiresAt;
    }
    struct PrivilegeStorage {
        uint lastExpiresAt;
        // privId =&gt; PrivilegeRecord
        mapping(uint =&gt; PrivilegeRecord) privilegeEntry;
    }

    uint public privilegeTotal;
    // tokenId =&gt; PrivilegeStorage
    mapping(uint =&gt; PrivilegeStorage) public privilegeBook;
    mapping(address =&gt; mapping(address =&gt; bool)) private privilegeDelegator;

    constructor(string memory name_, string memory symbol_)
    ERC721(name_,symbol_)
    {
    
    }

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

    function hasPrivilege(
        uint256 tokenId,
        uint256 privId,
        address user
    ) public virtual view returns(bool) {
        if (privilegeBook[tokenId].privilegeEntry[privId].expiresAt &gt;= block.timestamp){
            return privilegeBook[tokenId].privilegeEntry[privId].user == user;
        }
        return ownerOf(tokenId) == user;
    }

    function privilegeExpires(
        uint256 tokenId,
        uint256 privId
    ) public virtual view returns(uint256){
        return privilegeBook[tokenId].privilegeEntry[privId].expiresAt;
    }

    function _setPrivilegeTotal(
        uint total
    ) internal {
        emit PrivilegeTotalChanged(total, privilegeTotal);
        privilegeTotal = total;
    }

    function getPrivilegeInfo(uint tokenId, uint privId) external view returns(address user, uint256 expiresAt) {
        return (privilegeBook[tokenId].privilegeEntry[privId].user, privilegeBook[tokenId].privilegeEntry[privId].expiresAt);
    }

    function setDelegator(address delegator, bool enabled) external {
        privilegeDelegator[msg.sender][delegator] = enabled;
    }

    function _isDelegatorOrHolder(address delegator, uint256 tokenId, uint privId) internal virtual view returns (bool) {
        address holder = privilegeBook[tokenId].privilegeEntry[privId].user;
         return (delegator == holder || isApprovedForAll(holder, delegator) || privilegeDelegator[holder][delegator]);
    }

    function supportsInterface(bytes4 interfaceId) public override virtual view returns (bool) {
        return interfaceId == type(IERC5496).interfaceId || super.supportsInterface(interfaceId);
    }
}
```

## Security Considerations

Implementations must thoroughly consider who has the permission to set or clone privileges.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Rental &amp; Delegation NFT - EIP-721 Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-tbd-rental-delegation-nft-erc-721-extension/10441</comments>
        
        <description>## Abstract
The following standard proposes an additional `user` role for [EIP-721](/EIPs/EIPS/eip-721). This role grants the permission to use the NFT with no ability to transfer or set users. It has an expiry and a flag if the token is borrowed or not. `Owner` can delegate the NFT for usage to hot wallets or lend the NFT. If the token is borrowed, not even the owner can change the user until the status expires or both parties agree to terminate. This way, it is possible to keep both roles active at the same time.

## Motivation
Collectibles, gaming assets, metaverse, event tickets, music, video, domains, real item representation are several among many NFT use cases. With [EIP-721](/EIPs/EIPS/eip-721) only the owner can reap the benefits. However, with most of the utilities it would be beneficial to distinguish between the token owner and its user. For instance music or movies could be rented. Metaverse lands could be delegated for usage. 

The two reasons why to set the user are: 

* **delegation** - Assign user to your hot wallet to interact with applications securely. In this case, the owner can change the user at any time.
* **renting** - This use case comes with additional requirements. It is needed to terminate the loan once the established lending period is over. This is provided by `expires` of the user. It is also necessary to protect the borrower against resetting their status by the owner. Thus, `isBorrowed` check must be implemented to disable the option to set the user before the contract expires.

The most common use cases for having an additional user role are: 

* **delegation** - For security reasons.
* **gaming** - Would you like to try a game (or particular gaming assets) but are you unsure whether or not you will like it? Rent assets first.
* **guilds** - Keep the owner of the NFTs as the multisig wallet and set the user to a hot wallet with shared private keys among your guild members.
* **events** - Distinguish between `ownerOf` and `userOf`. Each role has a different access.
* **social** - Differentiate between roles for different rooms. For example owner has read + write access while userOf has read access only.

This proposal is a follow up on [EIP-4400](/EIPs/EIPS/eip-4400) and [EIP-4907](/EIPs/EIPS/eip-4907) and introduces additional upgrades for lending and borrowing which include: 

* **NFT stays in owner&apos;s wallet during rental period** 
* **Listing and sale of NFT without termination of the rent**
* **Claiming owner benefits during rental period**

Building the standard with additional isBorrowed check now allows to create rental marketplaces which can set the user of NFT without the necessary staking mechanism. With current standards if a token is not staked during the rental period, the owner can simply terminate the loan by setting the user repeatedly. This is taken care of by disabling the function if the token is borrowed which in turn is providing the owner additional benefits. They can keep the token tied to their wallet, meaning they can still receive airdrops, claim free mints based on token ownership or otherwise use the NFT provided by third-party services for owners. They can also keep the NFT listed for sale. Receiving airdrops or free mints was previously possible but the owner was completely reliant on the implementation of rental marketplaces and their discretion.

Decentralized applications can now differentiate between ownerOf and userOf while both statuses can coexist.
  
## Specification
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.

**Every compliant contract MUST implement the `IERC5501` interface. This extension is OPTIONAL for [EIP-721](/EIPs/EIPS/eip-721) contracts.** 

```solidity
/**
 * @title IERC5501: Rental &amp; Delegation NFT - EIP-721 Extension
 * @notice the EIP-165 identifier for this interface is 0xf808ec37.
 */
interface IERC5501 /* is IERC721 */ {
    /**
     * @dev Emitted when the user of an NFT is modified.
     */
    event UpdateUser(uint256 indexed _tokenId, address indexed _user, uint64 _expires, bool _isBorrowed);

    /**
     * @notice Set the user info of an NFT.
     * @dev User address cannot be zero address.
     * Only approved operator or NFT owner can set the user.
     * If NFT is borrowed, the user info cannot be changed until user status expires.
     * @param _tokenId uint256 ID of the token to set user info for
     * @param _user address of the new user
     * @param _expires Unix timestamp when user info expires
     * @param _isBorrowed flag whether or not the NFT is borrowed
     */
    function setUser(uint256 _tokenId, address _user, uint64 _expires, bool _isBorrowed) external;

    /**
     * @notice Get the user address of an NFT.
     * @dev Reverts if user is not set.
     * @param _tokenId uint256 ID of the token to get the user address for
     * @return address user address for this NFT
     */
    function userOf(uint256 _tokenId) external view returns (address);

    /**
     * @notice Get the user expires of an NFT.
     * @param _tokenId uint256 ID of the token to get the user expires for
     * @return uint64 user expires for this NFT
     */
    function userExpires(uint256 _tokenId) external view returns (uint64);

    /**
     * @notice Get the user isBorrowed of an NFT.
     * @param _tokenId uint256 ID of the token to get the user isBorrowed for
     * @return bool user isBorrowed for this NFT
     */
    function userIsBorrowed(uint256 _tokenId) external view returns (bool);
}
``` 

Every contract implementing the `IERC5501` interface is free to define the permissions of a `user`. However, user MUST NOT be considered an `owner`. They MUST NOT be able to execute transfers and approvals. Furthermore, `setUser` MUST be blocked from executing if `userIsBorrowed` returns `true` and `userExpires` is larger than or equal to `block.timestamp`. 

The `UpdateUser` event MUST be emitted when a `user` is changed.   
The `setUser(uint256 _tokenId, address _user, uint64 _expires, bool _isBorrowed)` function SHOULD `revert` unless the `msg.sender` is the `owner` or an approved operator. It MUST revert if a token is borrowed and status has not expired yet. It MAY be `public` or `external`.   
The `userOf(uint256 _tokenId)` function SHOULD revert if `user` is not set or expired.   
The `userExpires(uint256 _tokenId)` function returns a timestamp when user status expires.   
The `userIsBorrowed(uint256 _tokenId)` function returns whether NFT is borrowed or not.   
The `supportsInterface` function MUST return `true` when called with `0xf808ec37`.   
On every `transfer`, the `user` MUST be reset if the token is not borrowed. If the token is borrowed the `user` MUST stay the same.   

**The Balance extension is OPTIONAL. This gives the option to query the number of tokens a `user` has.** 

```solidity
/**
 * @title IERC5501Balance
 * Extension for ERC5501 which adds userBalanceOf to query how many tokens address is userOf.
 * @notice the EIP-165 identifier for this interface is 0x0cb22289.
 */
interface IERC5501Balance /* is IERC5501 */{
    /**
     * @notice Count of all NFTs assigned to a user.
     * @dev Reverts if user is zero address.
     * @param _user an address for which to query the balance
     * @return uint256 the number of NFTs the user has
     */
    function userBalanceOf(address _user) external view returns (uint256);
}
``` 

The `userBalanceOf(address _user)` function SHOULD `revert` for zero address. 

**The Enumerable extension is OPTIONAL. This allows to iterate over user balance.** 

```solidity
/**
 * @title IERC5501Enumerable
 * This extension for ERC5501 adds the option to iterate over user tokens.
 * @notice the EIP-165 identifier for this interface is 0x1d350ef8.
 */
interface IERC5501Enumerable /* is IERC5501Balance, IERC5501 */ {
    /**
     * @notice Enumerate NFTs assigned to a user.
     * @dev Reverts if user is zero address or _index &gt;= userBalanceOf(_owner).
     * @param _user an address to iterate over its tokens
     * @return uint256 the token ID for given index assigned to _user
     */
    function tokenOfUserByIndex(address _user, uint256 _index) external view returns (uint256);
}
``` 

The `tokenOfUserByIndex(address _user, uint256 _index)` function SHOULD `revert` for zero address and `throw` if the index is larger than or equal to `user` balance. 

**The Terminable extension is OPTIONAL. This allows terminating the rent early if both parties agree.**

```solidity
/**
 * @title IERC5501Terminable
 * This extension for ERC5501 adds the option to terminate borrowing if both parties agree.
 * @notice the EIP-165 identifier for this interface is 0x6a26417e.
 */
interface IERC5501Terminable /* is IERC5501 */ {
    /**
     * @dev Emitted when one party from borrowing contract approves termination of agreement.
     * @param _isLender true for lender, false for borrower
     */
    event AgreeToTerminateBorrow(uint256 indexed _tokenId, address indexed _party, bool _isLender);

    /**
     * @dev Emitted when agreements to terminate borrow are reset.
     */
    event ResetTerminationAgreements(uint256 indexed _tokenId);

    /**
     * @dev Emitted when borrow of token ID is terminated.
     */
    event TerminateBorrow(uint256 indexed _tokenId, address indexed _lender, address indexed _borrower, address _caller);

    /**
     * @notice Agree to terminate a borrowing.
     * @dev Lender must be ownerOf token ID. Borrower must be userOf token ID.
     * If lender and borrower are the same, set termination agreement for both at once.
     * @param _tokenId uint256 ID of the token to set termination info for
     */
    function setBorrowTermination(uint256 _tokenId) external;

    /**
     * @notice Get if it is possible to terminate a borrow agreement.
     * @param _tokenId uint256 ID of the token to get termination info for
     * @return bool, bool first indicates lender agrees, second indicates borrower agrees
     */
    function getBorrowTermination(uint256 _tokenId) external view returns (bool, bool);

    /**
     * @notice Terminate a borrow if both parties agreed.
     * @dev Both parties must have agreed, otherwise revert.
     * @param _tokenId uint256 ID of the token to terminate borrow of
     */
    function terminateBorrow(uint256 _tokenId) external;
}
``` 

The `AgreeToTerminateBorrow` event MUST be emitted when either the lender or borrower agrees to terminate the rent.   
The `ResetTerminationAgreements` event MUST be emitted when a token is borrowed and transferred or `setUser` and `terminateBorrow` functions are called.   
The `TerminateBorrow` event MUST be emitted when the rent is terminated.   
The `setBorrowTermination(uint256 _tokenId)`. It MUST set an agreement from either party whichever calls the function. If the lender and borrower are the same address, it MUST assign an agreement for both parties at once.   
The `getBorrowTermination(uint256 _tokenId)` returns if agreements from both parties are `true` or `false`.   
The `terminateBorrow(uint256 _tokenId)` function MAY be called by anyone. It MUST `revert` if both agreements to terminate are not `true`. This function SHOULD change the `isBorrowed` flag from `true` to `false`.   
On every `transfer`, the termination agreements from either party MUST be reset if the token is borrowed.

## Rationale
The main factors influencing this standard are: 

* **[EIP-4400](/EIPs/EIPS/eip-4400) and [EIP-4907](/EIPs/EIPS/eip-4907)**
* **Allow lending and borrowing without the necessary stake or overcollateralization while owner retains ownership**
* **Leave the delegation option available**
* **Keep the number of functions in the interfaces to a minimum while achieving desired functionality**
* **Modularize additional extensions to let developers choose what they need for their project**

### Name
The name for the additional role has been chosen to fit the purpose and to keep compatibility with EIP-4907.

### Ownership retention
Many collections offer their owners airdrops or free minting of various tokens. This is essentially broken if the owner is lending a token by staking it into a contract (unless the contract is implementing a way to claim at least airdropped tokens). Applications can also provide different access and benefits to owner and user roles in their ecosystem.

### Balance and Enumerable extensions
These have been chosen as OPTIONAL extensions due to the complexity of implementation based on the fact that balance is less once user status expires and there is no immediate on-chain transaction to evaluate that. In both `userBalanceOf` and `tokenOfUserByIndex` functions there must be a way to determine whether or not user status has expired. 

### Terminable extension
If the owner mistakenly sets a user with borrow status and expires to a large value they would essentially be blocked from setting the user ever again. The problem is addressed by this extension if both parties agree to terminate the user status.
 
### Security
Once applications adopt the user role, it is possible to delegate ownership to hot wallet and interact with them with no fear of connecting to malicious websites.

## Backwards Compatibility
This standard is compatible with current [EIP-721](/EIPs/EIPS/eip-721) by adding an extension function set. The new functions introduced are similar to existing functions in EIP-721 which guarantees easy adoption by developers and applications. This standard also shares similarities to [EIP-4907](/EIPs/EIPS/eip-4907) considering user role and its expiry which means applications will be able to determine the user if either of the standards is used.

## Test Cases
Test cases can be found in the reference implementation:
* [Main contract](/EIPs/assets/eip-5501/test/ERC5501Test.ts)
* [Balance extension](/EIPs/assets/eip-5501/test/ERC5501BalanceTest.ts)
* [Enumerable extension](/EIPs/assets/eip-5501/test/ERC5501EnumerableTest.ts)
* [Terminable extension](/EIPs/assets/eip-5501/test/ERC5501TerminableTest.ts)
* [Scenario combined of all extensions](/EIPs/assets/eip-5501/test/ERC5501CombinedTest.ts)

## Reference Implementation
The reference implementation is available here:
* [Main contract](/EIPs/assets/eip-5501/contracts/ERC5501.sol)
* [Balance extension](/EIPs/assets/eip-5501/contracts/ERC5501Balance.sol)
* [Enumerable extension](/EIPs/assets/eip-5501/contracts/ERC5501Enumerable.sol)
* [Terminable extension](/EIPs/assets/eip-5501/contracts/ERC5501Terminable.sol)
* [Solution combined of all extensions](/EIPs/assets/eip-5501/contracts/ERC5501Combined.sol)

## Security Considerations
Developers implementing this standard and applications must consider all the permissions they give to users and owners. Since owner and user are both active roles at the same time, double-spending problem must be avoided. Balance extension must be implemented in such a way which will not cause any gas problems. Marketplaces should let users know if a token listed for sale is borrowed or not.
  
## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 18 Aug 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5501</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5501</guid>
      </item>
    
      <item>
        <title>EIP-1155 asset backed NFT extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-draft-erc1155-asset-backed-nft-extension/10437</comments>
        
        <description>## Abstract
To propose an extension of smart contract interfaces for asset-backed, fractionalized projects using the [EIP-1155](/EIPs/EIPS/eip-1155) standard such that total acquisition will become possible. This proposal focuses on physical asset, where total acquisition should be able to happen.

## Motivation
Fractionalized, asset backed NFTs face difficulty when someone wants to acquire the whole asset. For example, if someone wants to bring home a fractionalized asset, he needs to buy all NFT pieces so he will become the 100% owner. However he could not do so as it is publicly visible that someone is trying to perform a total acquisition in an open environment like Ethereum. Sellers will take advantage to set unreasonable high prices which hinders the acquisition. Or in other cases, NFTs are owned by wallets with lost keys, such that the ownership will never be a complete one. We need a way to enable potential total acquisition.

## Specification
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.

[EIP-1155](/EIPs/EIPS/eip-1155) compliant contracts MAY implement this EIP for adding functionalities to support total acquisition.

```solidity
//set the percentage required for any acquirer to trigger a forced sale
//set also the payment token to settle for the acquisition

function setForcedSaleRequirement(
	uint128 requiredBP,
	address erc20Token
) public onlyOwner

//set the unit price to acquire the remaining NFTs (100% - requiredBP)
//suggest to use a Time Weighted Average Price for a certain period before reaching the requiredBP
//emit ForcedSaleSet

function setForcedSaleTWAP(
	uint256 amount
) public onlyOwner

//acquirer deposit remainingQTY*TWAP
//emit ForcedSaleFinished
//after this point, the acquirer is the new owner of the whole asset

function execForcedSale (
	uint256 amount
) public external payable

//burn ALL NFTs and collect funds
//emit ForcedSaleClaimed

function claimForcedSale()
public

event ForcedSaleSet(
	bool isSet
)
event ForceSaleClaimed(
	uint256 qtyBurned,
	uint256 amountClaimed,
	address claimer
)
```


## Rationale
Native ETH is supported by via Wrapped Ether [EIP-20](/EIPs/EIPS/eip-20).
After forcedSale is set, the remaining NFTs metadata should be updated to reflect the NFTs are at most valued at the previously set TWAP price.

## Security Considerations
The major security risks considered include
- The execution of the forcedSale is only executed by the contract owner, after a governance proposal. If there is any governance attack, the forcedSale TWAP price might be manipulated on a specific timing. The governance structure for using this extension should consider adding a **council** to safeguard the fairness of the forcedSale. 
- Payment tokens are deposited into the contract account when forcedSale is executed. These tokens will then await the minority holders to withdraw on burning the NFT. There might be a potential security risk.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 18 Aug 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5505</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5505</guid>
      </item>
    
      <item>
        <title>Refundable Tokens</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5507-refundable-nfts/10451</comments>
        
        <description>## Abstract

This ERC adds refund functionality for initial token offerings to [ERC-20](/EIPs/EIPS/eip-20), [ERC-721](/EIPs/EIPS/eip-721), and [ERC-1155](/EIPs/EIPS/eip-1155). Funds are held in escrow until a predetermined time before they are claimable. Until that predetermined time passes, users can receive a refund for tokens they have purchased.

## Motivation

The NFT and token spaces lack accountability. For the health of the ecosystem as a whole, better mechanisms to prevent rugpulls from happening are needed. Offering refunds provides greater protection for buyers and increases legitimacy for creators.

A standard interface for this particular use case allows for certain benefits:

- Greater Compliance with EU &quot;Distance Selling Regulations,&quot; which require a 14-day refund period for goods (such as tokens) purchased online
- Interoperability with various NFT-related applications, such as portfolio browsers, and marketplaces
  - NFT marketplaces could place a badge indicating that the NFT is still refundable on listings, and offer to refund NFTs instead of listing them on the marketplace
  - DExes could offer to refund tokens if doing so would give a higher yield
- Better wallet confirmation dialogs
  - Wallets can better inform the user of the action that is being taken (tokens being refunded), similar to how transfers often have their own unique dialog
  - DAOs can better display the functionality of smart proposals that include refunding tokens

## Specification

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.

All implementations MUST use and follow the directions of [ERC-165](/EIPs/EIPS/eip-165).

### ERC-20 Refund Extension
  
```solidity
// SPDX-License-Identifier: CC0-1.0

pragma solidity ^0.8.17;

import &quot;ERC20.sol&quot;;
import &quot;ERC165.sol&quot;;

/// @notice Refundable ERC-20 tokens
/// @dev    The ERC-165 identifier of this interface is `0xf0ca2917`
interface ERC20Refund is ERC20, ERC165 {
    /// @notice           Emitted when a token is refunded
    /// @dev              Emitted by `refund`
    /// @param  _from     The account whose assets are refunded
    /// @param  _amount   The amount of token (in terms of the indivisible unit) that was refunded
    event Refund(
        address indexed _from,
        uint256 indexed _amount
    );

    /// @notice           Emitted when a token is refunded
    /// @dev              Emitted by `refundFrom`
    /// @param  _sender   The account that sent the refund
    /// @param  _from     The account whose assets are refunded
    /// @param  _amount   The amount of token (in terms of the indivisible unit) that was refunded
    event RefundFrom(
        address indexed _sender,
        address indexed _from,
        uint256 indexed _amount
    );

    /// @notice         As long as the refund is active, refunds the user
    /// @dev            Make sure to check that the user has the token, and be aware of potential re-entrancy vectors
    /// @param  amount  The `amount` to refund
    function refund(uint256 amount) external;

    /// @notice         As long as the refund is active and the sender has sufficient approval, refund the tokens and send the ether to the sender
    /// @dev            Make sure to check that the user has the token, and be aware of potential re-entrancy vectors
    ///                 The ether goes to msg.sender.
    /// @param  from    The user from which to refund the assets
    /// @param  amount  The `amount` to refund
    function refundFrom(address from, uint256 amount) external;

    /// @notice         Gets the refund price
    /// @return _wei    The amount of ether (in wei) that would be refunded for a single token unit (10**decimals indivisible units)
    function refundOf() external view returns (uint256 _wei);
 
    /// @notice         Gets the first block for which the refund is not active
    /// @return block   The first block where the token cannot be refunded
    function refundDeadlineOf() external view returns (uint256 block);
}
```

### ERC-721 Refund Extension
  
```solidity
// SPDX-License-Identifier: CC0-1.0

pragma solidity ^0.8.17;

import &quot;ERC721.sol&quot;;
import &quot;ERC165.sol&quot;;

/// @notice Refundable ERC-721 tokens
/// @dev    The ERC-165 identifier of this interface is `0xe97f3c83`
interface ERC721Refund is ERC721 /* , ERC165 */ {
    /// @notice           Emitted when a token is refunded
    /// @dev              Emitted by `refund`
    /// @param  _from     The account whose assets are refunded
    /// @param  _tokenId  The `tokenId` that was refunded
    event Refund(
        address indexed _from,
        uint256 indexed _tokenId
    );

    /// @notice           Emitted when a token is refunded
    /// @dev              Emitted by `refundFrom`
    /// @param  _sender   The account that sent the refund
    /// @param  _from     The account whose assets are refunded
    /// @param  _tokenId  The `tokenId` that was refunded
    event RefundFrom(
        address indexed _sender,
        address indexed _from,
        uint256 indexed _tokenId
    );

    /// @notice         As long as the refund is active for the given `tokenId`, refunds the user
    /// @dev            Make sure to check that the user has the token, and be aware of potential re-entrancy vectors
    /// @param  tokenId The `tokenId` to refund
    function refund(uint256 tokenId) external;

    /// @notice         As long as the refund is active and the sender has sufficient approval, refund the token and send the ether to the sender
    /// @dev            Make sure to check that the user has the token, and be aware of potential re-entrancy vectors
    ///                 The ether goes to msg.sender.
    /// @param  from    The user from which to refund the token
    /// @param  tokenId The `tokenId` to refund
    function refundFrom(address from, uint256 tokenId) external;

    /// @notice         Gets the refund price of the specific `tokenId`
    /// @param  tokenId The `tokenId` to query
    /// @return _wei    The amount of ether (in wei) that would be refunded
    function refundOf(uint256 tokenId) external view returns (uint256 _wei);
 
    /// @notice         Gets the first block for which the refund is not active for a given `tokenId`
    /// @param  tokenId The `tokenId` to query
    /// @return block   The first block where token cannot be refunded
    function refundDeadlineOf(uint256 tokenId) external view returns (uint256 block);
}
```

#### Optional ERC-721 Batch Refund Extension

```solidity
// SPDX-License-Identifier: CC0-1.0;

import &quot;ERC721Refund.sol&quot;;

/// @notice Batch Refundable ERC-721 tokens
/// @dev    The ERC-165 identifier of this interface is ``
contract ERC721BatchRefund is ERC721Refund {
    /// @notice           Emitted when one or more tokens are batch refunded
    /// @dev              Emitted by `refundBatch`
    /// @param  _from     The account whose assets are refunded
    /// @param  _tokenId  The `tokenIds` that were refunded
    event RefundBatch(
        address indexed _from,
        uint256[] _tokenIds // This may or may not be indexed
    );

    /// @notice           Emitted when one or more tokens are batch refunded
    /// @dev              Emitted by `refundFromBatch`
    /// @param  _sender   The account that sent the refund
    /// @param  _from     The account whose assets are refunded
    /// @param  _tokenId  The `tokenId` that was refunded
    event RefundFromBatch(
        address indexed _sender,
        address indexed _from,
        uint256 indexed _tokenId
    );
    
    /// @notice           As long as the refund is active for the given `tokenIds`, refunds the user
    /// @dev              Make sure to check that the user has the tokens, and be aware of potential re-entrancy vectors
    ///                   These must either succeed or fail together; there are no partial refunds.
    /// @param  tokenIds  The `tokenId`s to refund
    function refundBatch(uint256[] tokenIds) external;

    /// @notice           As long as the refund is active for the given `tokenIds` and the sender has sufficient approval, refund the tokens and send the ether to the sender
    /// @dev              Make sure to check that the user has the tokens, and be aware of potential re-entrancy vectors
    ///                   The ether goes to msg.sender.
    ///                   These must either succeed or fail together; there are no partial refunds.
    /// @param  from      The user from which to refund the token
    /// @param  tokenIds  The `tokenId`s to refund
    function refundFromBatch(address from, uint256[] tokenIds) external;
}
```

### ERC-1155 Refund Extension
  
```solidity
// SPDX-License-Identifier: CC0-1.0

pragma solidity ^0.8.17;

import &quot;ERC1155.sol&quot;;
import &quot;ERC165.sol&quot;;

/// @notice Refundable ERC-1155 tokens
/// @dev    The ERC-165 identifier of this interface is `0x94029f5c`
interface ERC1155Refund is ERC1155 /* , ERC165 */ {
    /// @notice           Emitted when a token is refunded
    /// @dev              Emitted by `refund`
    /// @param  _from     The account that requested a refund
    /// @param  _tokenId  The `tokenId` that was refunded
    /// @param  _amount   The amount of `tokenId` that was refunded
    event Refund(
        address indexed _from,
        uint256 indexed _tokenId,
        uint256 _amount
    );

    /// @notice           Emitted when a token is refunded
    /// @dev              Emitted by `refundFrom`
    /// @param  _sender   The account that sent the refund
    /// @param  _from     The account whose assets are refunded
    /// @param  _tokenId  The `tokenId` that was refunded
    /// @param  _amount   The amount of `tokenId` that was refunded
    event RefundFrom(
        address indexed _sender,
        address indexed _from,
        uint256 indexed _tokenId
    );

    /// @notice         As long as the refund is active for the given `tokenId`, refunds the user
    /// @dev            Make sure to check that the user has enough tokens, and be aware of potential re-entrancy vectors
    /// @param  tokenId The `tokenId` to refund
    /// @param  amount  The amount of `tokenId` to refund
    function refund(uint256 tokenId, uint256 amount) external;

    /// @notice         As long as the refund is active and the sender has sufficient approval, refund the tokens and send the ether to the sender
    /// @dev            Make sure to check that the user has enough tokens, and be aware of potential re-entrancy vectors
    ///                 The ether goes to msg.sender.
    /// @param  from    The user from which to refund the token
    /// @param  tokenId The `tokenId` to refund
    /// @param  amount  The amount of `tokenId` to refund
    function refundFrom(address from, uint256 tokenId, uint256 amount) external;

    /// @notice         Gets the refund price of the specific `tokenId`
    /// @param  tokenId The `tokenId` to query
    /// @return _wei    The amount of ether (in wei) that would be refunded for a single token
    function refundOf(uint256 tokenId) external view returns (uint256 _wei);

    /// @notice         Gets the first block for which the refund is not active for a given `tokenId`
    /// @param  tokenId The `tokenId` to query
    /// @return block   The first block where the token cannot be refunded
    function refundDeadlineOf(uint256 tokenId) external view returns (uint256 block);
}
```

#### Optional ERC-1155 Batch Refund Extension

```solidity
// SPDX-License-Identifier: CC0-1.0;

import &quot;ERC1155Refund.sol&quot;;

/// @notice Batch Refundable ERC-1155 tokens
/// @dev    The ERC-165 identifier of this interface is ``
contract ERC1155BatchRefund is ERC1155Refund {
    /// @notice           Emitted when one or more tokens are batch refunded
    /// @dev              Emitted by `refundBatch`
    /// @param  _from     The account that requested a refund
    /// @param  _tokenIds The `tokenIds` that were refunded
    /// @param  _amounts  The amount of each `tokenId` that was refunded
    event RefundBatch(
        address indexed _from,
        uint256[] _tokenIds, // This may or may not be indexed
        uint256[] _amounts
    );

    /// @notice           Emitted when one or more tokens are batch refunded
    /// @dev              Emitted by `refundFromBatch`
    /// @param  _sender   The account that sent the refund
    /// @param  _from     The account whose assets are refunded
    /// @param  _tokenIds The `tokenIds` that was refunded
    /// @param  _amounts  The amount of each `tokenId` that was refunded
    event RefundFromBatch(
        address indexed _sender,
        address indexed _from,
        uint256[] _tokenId, // This may or may not be indexed
        uint256[] _amounts
    );
    
    /// @notice           As long as the refund is active for the given `tokenIds`, refunds the user
    /// @dev              Make sure to check that the user has enough tokens, and be aware of potential re-entrancy vectors
    ///                   These must either succeed or fail together; there are no partial refunds.
    /// @param  tokenIds  The `tokenId`s to refund
    /// @param  amounts   The amount of each `tokenId` to refund
    function refundBatch(uint256[] tokenIds, uint256[] amounts) external;

    /// @notice           As long as the refund is active for the given `tokenIds` and the sender has sufficient approval, refund the tokens and send the ether to the sender
    /// @dev              Make sure to check that the user has the tokens, and be aware of potential re-entrancy vectors
    ///                   The ether goes to msg.sender.
    ///                   These must either succeed or fail together; there are no partial refunds.
    /// @param  from      The user from which to refund the token
    /// @param  tokenIds  The `tokenId`s to refund
    /// @param  amounts   The amount of each `tokenId` to refund
    function refundFromBatch(address from, uint256[] tokenIds, uint256[] amounts external;
}
```

## Rationale

`refundDeadlineOf` uses blocks instead of timestamps, as timestamps are less reliable than block numbers.

The function names of `refund`, `refundOf`, and `refundDeadlineOf` were chosen to fit the naming style of ERC-20, ERC-721, and ERC-1155.

[ERC-165](/EIPs/EIPS/eip-165) is required as introspection by DApps would be made significantly harder if it were not.

Custom ERC-20 tokens are not supported, as it needlessly increases complexity, and the `refundFrom` function allows for this functionality when combined with a DEx.

Batch refunds are optional, as account abstraction would make atomic operations like these significantly easier. However, they might still reduce gas costs if properly implemented.

## Backwards Compatibility

No backward compatibility issues were found.

## Security Considerations

There is a potential re-entrancy risk with the `refund` function. Make sure to perform the ether transfer **after** the tokens are destroyed (i.e. obey the checks, effects, interactions pattern).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 19 Aug 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5507</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5507</guid>
      </item>
    
      <item>
        <title>Soulbound Multi-owner Tokens</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/EIP-5516-soulbound-multi-token-standard/10485</comments>
        
        <description>## Abstract

This EIP proposes a standard interface for non-transferable, multi-owner Soulbound tokens.
Previous account-bound token standards face the issue of users losing their account keys or having them rotated, thereby losing their tokens in the process. This EIP provides a solution to this issue that allows for the recycling of SBTs.

## Motivation

This EIP was inspired by the main characteristics of the [ERC-1155](/EIPs/EIPS/eip-1155) token standard and by articles in which benefits and potential use cases of Soulbound/Accountbound Tokens (SBTs) were presented.
This design also allows for batch token transfers, saving on transaction costs. Trading of multiple tokens can be built on top of this standard and it removes the need to approve individual token contracts separately. It is also easy to describe and mix multiple fungible or non-fungible token types in a single contract.

### Characteristics

- The NFT will be non-transferable after the initial transfer
- Multi-Token
- Multi-Owner
- Semi-Fungible

### Applications

- Academic Degrees
- Code audits
- POAPs (Proof of Attendance Protocol NFTs)

## Specification

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.

**Smart contracts implementing this EIP MUST implement all of the functions in the [ERC-5516](/EIPs/EIPS/eip-5516) interface.**

**Smart contracts implementing this EIP MUST implement the [EIP-165](/EIPs/EIPS/eip-165) `supportsInterface` function and MUST return the constant value `true` if `0x45b253ba` is passed through the `interfaceID` argument.**

```solidity
// SPDX-License-Identifier: CC0-1.0

pragma solidity ^0.8.4;

/**
    @title Soulbound, Multi-Token standard.
    @notice Interface of the EIP-5516
    Note: The ERC-165 identifier for this interface is 0x45b253ba.
 */

interface IERC5516 {
    /**
     * @dev Emitted when `issuer` creates a new soulbound token and distributes it to `recipients[]`.
     *
     * @param tokenId The unique identifier of the newly created token.
     * @param issuer The address of the entity that issued the credential.
     * @param recipients Array of addresses that received the soulbound token.
     * @param metadataURI URI pointing to the token metadata (e.g., IPFS hash).
     */
    event Issued(
        uint256 indexed tokenId,
        address indexed issuer,
        address[] recipients,
        string metadataURI
    );

    /**
     * @dev Emitted when `who` voluntarily renounces their soulbound token under `tokenId`.
     *
     * @param tokenId The unique identifier of the renounced token.
     * @param who The address that renounced ownership of the token.
     */
    event Renounced(uint256 indexed tokenId, address indexed who);

    /**
     * @dev Issues a new soulbound token to multiple recipients.
     *
     * Creates a unique token identifier and distributes it to all addresses in `recipients[]`.
     * The token is non-transferable after issuance.
     *
     * Requirements:
     * - `recipients[]` MUST NOT be empty.
     * - All addresses in `recipients[]` MUST be non-zero.
     * - All addresses in `recipients[]` MUST NOT already own a token under the generated `tokenId`.
     * - Caller MUST be an authorized issuer.
     *
     * Emits an {Issued} event.
     *
     * @param recipients Array of addresses that will receive the soulbound token.
     * @param metadataURI URI pointing to the token metadata (IPFS, Arweave, HTTP, etc.).
     * @return tokenId The unique identifier of the newly created token.
     */
    function issue(
        address[] memory recipients,
        string calldata metadataURI
    ) external returns (uint256 tokenId);

    /**
     * @dev Allows the token holder to voluntarily renounce their soulbound token.
     *
     * Once renounced, the holder no longer owns the token and cannot reclaim it.
     * This action is irreversible.
     *
     * Requirements:
     * - Caller MUST own the token under `tokenId`.
     * - `tokenId` MUST exist.
     *
     * Emits a {Renounced} event.
     *
     * @param tokenId The unique identifier of the token to renounce.
     */
    function renounce(uint256 tokenId) external;

    /**
     * @dev Checks if a given address owns a specific soulbound token.
     *
     * @param who The address to check ownership for.
     * @param tokenId The unique identifier of the token.
     * @return True if `who` owns the token under `tokenId`, false otherwise.
     */
    function has(address who, uint256 tokenId) external view returns (bool);

    /**
     * @dev Returns the URI for a given token ID.
     *
     * The URI typically points to a JSON file containing token metadata.
     * This may be an IPFS hash, Arweave transaction ID, or HTTP URL.
     *
     * Requirements:
     * - `tokenId` MUST exist.
     *
     * @param tokenId The unique identifier of the token.
     * @return The complete URI string for the token metadata.
     */
    function uri(uint256 tokenId) external view returns (string memory);
}
```

## Rationale

### [ERC-5516](/EIPs/EIPS/eip-5516) as certificates

The original idea for this proposal aroused from a neccesity of emitting on-chain certificates to multiple people. We thought that having to emit one token per account has redundant, and we originally developed a [ERC-1155](/EIPs/EIPS/eip-1155) partial-compatible implementation.

After revisiting our proposal, we thought that it would be cleaner to have a more minimal interface that just serves this purpose only, so we decided to drop the partial backwards compatibility with [ERC-1155](/EIPs/EIPS/eip-1155).

### SBT as a _spinoff_ of [EIP-1155](/EIPs/EIPS/eip-1155)

We saw the vision of the [ERC-1155](/EIPs/EIPS/eip-1155#metadata) and tried to apply it to Soulbound/Accountbound tokens: We think that having the ability to prove that you own a token, not a particular identifier is valuable, and that it has real world use cases.

### Metadata.

We implement a standard method of obtaining metadata (`uri`) similar to the one defined in [ERC-1155](/EIPs/EIPS/eip-1155#metadata):

The URI value allows for ID substitution by clients. If the string `{id}` exists in any URI, clients MUST replace this with the actual token ID in hexadecimal form. This allows for a large number of tokens to use the same on-chain string by defining a URI once, for that large number of tokens.

- The string format of the substituted hexadecimal ID MUST be lowercase alphanumeric: `[0-9a-f]` with no 0x prefix.
- The string format of the substituted hexadecimal ID MUST be leading zero padded to 64 hex characters length if necessary.
  Example of such a URI: `https://token-cdn-domain/{id}.json` would be replaced with `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json` if the client is referring to token ID 314592/0x4CCE0.

### Guaranteed log trace

The [ERC-5516](/EIPs/EIPS/eip-5516) standard guarantees that event logs emitted by the smart contract will provide enough data to create an accurate record of all current token balances. A database or explorer may listen to events and be able to provide indexed and categorized searches of every [ERC-5516](/EIPs/EIPS/eip-5516) token in the contract.

### Exception handling

Given the non-transferability property of SBTs, if a user&apos;s keys to an account get compromised or rotated, such user may lose the ability to associate themselves with the token.

**Given the multi-owner characteristic of this EIP, SBTs will be able to bind to multiple accounts, providing a potential solution to the issue.**

Multi-owner SBTs can also be issued to a contract account that implements a multi-signature functionality (As recommended in [EIP-4973](/EIPs/EIPS/eip-4973#exception-handling)).

### Multi-token

The multi-token functionality permits the implementation of multiple token types in the same contract. Furthermore, all emitted tokens are stored in the same contract, preventing redundant bytecode from being deployed to the blockchain. It also facilitates transfer to token issuers, since all issued tokens are stored and can be accessed under the same contract address.

## Backwards Compatibility

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 `[address,id]`).

## Reference Implementation

You can find an implementation of this standard [here](/EIPs/assets/eip-5516/ERC5516.sol).

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 19 Aug 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5516</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5516</guid>
      </item>
    
      <item>
        <title>Referable NFT</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-x-erc-721-referable-nft/10310</comments>
        
        <description>## Abstract

This standard is an extension of [ERC-721](/EIPs/EIPS/eip-721). It proposes two referable indicators, referring and referred, and a time-based indicator `createdTimestamp`. The relationship between each NFT forms a directed acyclic graph (DAG). The standard allows users to query, track and analyze their relationships.


![System Architecture](/EIPs/assets/eip-5521/system-arch.png)


## Motivation

Many scenarios require the inheritance, reference, and extension of NFTs. For instance, an artist may develop his NFT work based on a previous NFT, or a DJ may remix his record by referring to two pop songs, etc. A gap in existing NFT standards is the absence of established relationships between an NFT and its original creator. This void isolates NFTs, rendering the sale of each one a one-off transaction, thereby obstructing creators from accruing the full value of their intellectual property over time.

In this sense, proposing a referable solution for existing NFTs that enables efficient queries on cross-references is necessary. By introducing a reference relationship between NFTs, a sustainable economic model can be established to incentivize continued engagement in creating, using, and promoting NFTs.

This standard accordingly introduces a new concept, referable NFT (rNFT), which can transform static NFTs into a dynamically extensible network. We embed reference information, including `referring` and `referred` relationships, aiding in the formation of a Direct Acyclic Graph (DAG)-based NFT network. This structure provides a transparent graphical historical record and allows users to query, trace, and analyze relationships. It can enable NFT creators to build upon existing works without the need to start anew. 

An intuitive example: users can create new NFTs (C, D, E) by referencing existing ones (A, B), while the `referred` function informs the original NFTs (A, B) about their citations (e.g., A &amp;#8592; D; C &amp;#8592; E; B &amp;#8592; E, and A &amp;#8592; E). Here, the `createdTimestamp` (block-level) serves as an indicator for the creation time of NFTs (A, B, C, D, E).

### Key Takeaways

This standard provides several advantages:

*Clear ownership inheritance*: This standard extends the static NFT into a virtually extensible NFT network. Artists do not have to create work isolated from others. The ownership inheritance avoids reinventing the same wheel.

*Incentive Compatibility*: This standard clarifies the referable relationship across different NFTs, helping to integrate multiple up-layer incentive models for both original NFT owners and new creators.

*Easy Integration*: This standard makes it easier for the existing token standards or third-party protocols. For instance, the rNFT can be applied to rentable scenarios (cf. [ERC-5006](/EIPs/EIPS/eip-5006) to build a hierarchical rental market, where multiple users can rent the same NFT during the same time or one user can rent multiple NFTs during the same duration). 

*Scalable Interoperability*: This standard enables cross-contract references, giving a scalable adoption for the broader public with stronger interoperability.


## Specification

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.

- `UpdateNode`: event emitted when `setNode` is invoked;
- `safeMint`: mint a new rNFT;
- `setNode`: set the referring list of an rNFT and update the referred list of each one in the referring list;
    - `setNodeReferring`: set the referring list of an rNFT;
    - `setNodeReferred`: set the referred list of the given rNFTs sourced from different contracts;
        - `setNodeReferredExternal`: set the referred list of the given rNFTs sourced from external contracts;
- `referringOf`: get the referring list of an rNFT;
- `referredOf`: get the referred list of an rNFT;
- `createdTimestampOf`: get the timestamp of an rNFT when it is being created.

Implementers of this standard **MUST** have all of the following functions:

```solidity

pragma solidity ^0.8.4;

import &quot;@openzeppelin/contracts/utils/introspection/IERC165.sol&quot;;

interface IERC_5521 is IERC165 {

    /// Logged when a node in the rNFT gets referred and changed.
    /// @notice Emitted when the `node` (i.e., an rNFT) is changed.
    event UpdateNode(uint256 indexed tokenId, 
                     address indexed owner, 
                     address[] _address_referringList,
                     uint256[][] _tokenIds_referringList,
                     address[] _address_referredList,
                     uint256[][] _tokenIds_referredList
    );

    /// @notice set the referred list of an rNFT associated with different contract addresses and update the referring list of each one in the referred list. Checking the duplication of `addresses` and `tokenIds` is **RECOMMENDED**.
    /// @param `tokenId` of rNFT being set. `addresses` of the contracts in which rNFTs with `tokenIds` being referred accordingly. 
    /// @requirement 
    /// - the size of `addresses` **MUST** be the same as that of `tokenIds`;
    /// - once the size of `tokenIds` is non-zero, the inner size **MUST** also be non-zero;
    /// - the `tokenId` **MUST** be unique within the same contract;
    /// - the `tokenId` **MUST NOT** be the same as `tokenIds[i][j]` if `addresses[i]` is essentially `address(this)`.
    function setNode(uint256 tokenId, address[] memory addresses, uint256[][] memory tokenIds) external;

    /// @notice get the referring list of an rNFT.
    /// @param `tokenId` of the rNFT being focused, `_address` of contract address associated with the focused rNFT.
    /// @return the referring mapping of the rNFT.
    function referringOf(address _address, uint256 tokenId) external view returns(address[] memory, uint256[][] memory);

    /// @notice get the referred list of an rNFT.
    /// @param `tokenId` of the rNFT being focused, `_address` of contract address associated with the focused rNFT.
    /// @return the referred mapping of the rNFT.
    function referredOf(address _address, uint256 tokenId) external view returns(address[] memory, uint256[][] memory);

    /// @notice get the timestamp of an rNFT when is being created.
    /// @param `tokenId` of the rNFT being focused, `_address` of contract address associated with the focused rNFT.
    /// @return the timestamp of the rNFT when is being created with uint256 format.
    function createdTimestampOf(address _address, uint256 tokenId) external view returns(uint256);
    
    /// @notice check supported interfaces, adhereing to ERC165.
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

interface TargetContract is IERC165 {
    /// @notice set the referred list of an rNFT associated with external contract addresses. 
    /// @param `_tokenIds` of rNFTs associated with the contract address `_address` being referred by the rNFT with `tokenId`.
    /// @requirement
    /// - `_address` **MUST NOT** be the same as `address(this)` where `this` is executed by an external contract where `TargetContract` interface is implemented.
    function setNodeReferredExternal(address _address, uint256 tokenId, uint256[] memory _tokenIds) external;

    function referringOf(address _address, uint256 tokenId) external view returns(address[] memory, uint256[][] memory);

    function referredOf(address _address, uint256 tokenId) external view returns(address[] memory, uint256[][] memory);

    function createdTimestampOf(address _address, uint256 tokenId) external view returns(uint256);
    
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

```

## Rationale

### Is this event informative enough? 
`UpdateNode`: This event disseminates crucial information, including the rNFT ID, its owner, and lists of contract addresses/IDs with rNFTs referring to or referred by the subject rNFT. This data set enables stakeholders to efficiently manage and navigate the complex web of relationships inherent in the rNFT ecosystem.

Implementers are free to choose to use a struct (a recommended struct is given in the Reference Implementation), or several separate mappings, or whatever other storage mechanism. Whichever mechanism chosen has no observable effect on the behaviour of the contract, as long as its output can fulfill the `UpdateNode` event.

### Why `createdTimestampOf`?
`createdTimestamp`: A key principle of this standard is that an rNFT should reference content already accepted by the community (a time-based sequence known by participants). Global timestamps for rNFTs are thus essential, serving to prevent conflicting states (akin to concurrency issues in transaction processing and block organization). We define a block-level timestamp where `createdTimestamp = block.timestamp` Note that, given that the granularity of references is tied to the block timestamp, it is impractical to discern the order of two rNFTs within the same block.


### How is cross-contract reference performed?
`setNodeReferredExternal`: This function operates conditionally, dependent on successful interface verification in external contracts. Such selective invocation ensures backward compatibility and integration with existing contracts, provided they adhere to specified interfaces.



## Backwards Compatibility

This standard can be fully [ERC-721](/EIPs/EIPS/eip-721) compatible by adding an extension function set.

## Test Cases

Test cases are included in [ERC_5521.test.js](/EIPs/assets/eip-5521/ERC_5521.test.js)

## Reference Implementation

The recommended implementation is demonstrated as follows:

- `Relationship`: a structure that contains `referring`, `referred`, `referringKeys`, `referredKeys`, `createdTimestamp`, and other customized and optional attributes (i.e., not necessarily included in the standard) such as `privityOfAgreement` recording the ownerships of referred NFTs at the time the Referable NFTs (rNFTs) were being created or `profitSharing` recording the profit sharing of `referring`.
- `referring`: an out-degree indicator, used to show the users this NFT refers to;
- `referred`: an in-degree indicator, used to show the users who have refereed this NFT;
- `referringKeys`: a helper for mapping conversion of out-degree indicators, used for events;
- `referredKeys`: a helper for mapping conversion of in-degree indicators, used for events;
- `createdTimestamp`: a time-based indicator, used to compare the timestamp of mint, which should not be editable anyhow by callers.
- `referringOf` and `referredOf`: First, the current `referringOf` and `referredOf` allow cross-contract looking up, while this cannot be done by directly accessing `_relationship`. Secondly, only if privacy is not a concern, making `_relationship` public simplifies the contract by relying on Solidity’s automatically generated getters. However, if you need to control the visibility of the data, keeping the state variable private and providing specific getter functions would be the best approach.  For example, if `_relationship` includes details about specific users’ interactions or transactions or some private extensible parameters (in the updated version, we specifically highlight the `Relationship` can be extended to meet different requirements), always making this data public could reveal users’ behavior patterns or preferences, leading to potential privacy breaches.
- `convertMap`: This function is essential for retrieving the full mapping contents within a struct. Even if `_relationship` is public, The getters only allow retrieval of individual values for specific keys. Since we need comprehensive access to all stored addresses, `convertMap` is necessary to fulfill our event emission requirements.

```solidity

pragma solidity ^0.8.4;

import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;
import &quot;./IERC_5521.sol&quot;;

contract ERC_5521 is ERC721, IERC_5521, TargetContract {

    struct Relationship {
        mapping (address =&gt; uint256[]) referring;
        mapping (address =&gt; uint256[]) referred;
        address[] referringKeys;
        address[] referredKeys;
        uint256 createdTimestamp; // unix timestamp when the rNFT is being created

        // extensible parameters
        // ...
    }

    mapping (uint256 =&gt; Relationship) internal _relationship;
    address contractOwner = address(0);

    constructor(string memory name_, string memory symbol_) ERC721(name_, symbol_) {
        contractOwner = msg.sender;
    }

    function safeMint(uint256 tokenId, address[] memory addresses, uint256[][] memory _tokenIds) public {
        // require(msg.sender == contractOwner, &quot;ERC_rNFT: Only contract owner can mint&quot;);
        _safeMint(msg.sender, tokenId);
        setNode(tokenId, addresses, _tokenIds);
    }

    /// @notice set the referred list of an rNFT associated with different contract addresses and update the referring list of each one in the referred list
    /// @param tokenIds array of rNFTs, recommended to check duplication at the caller&apos;s end
    function setNode(uint256 tokenId, address[] memory addresses, uint256[][] memory tokenIds) public virtual override {
        require(
            addresses.length == tokenIds.length,
            &quot;Addresses and TokenID arrays must have the same length&quot;
        );
        for (uint i = 0; i &lt; tokenIds.length; i++) {
            if (tokenIds[i].length == 0) { revert(&quot;ERC_5521: the referring list cannot be empty&quot;); }
        }
        setNodeReferring(addresses, tokenId, tokenIds);
        setNodeReferred(addresses, tokenId, tokenIds);
    }

    /// @notice set the referring list of an rNFT associated with different contract addresses 
    /// @param _tokenIds array of rNFTs associated with addresses, recommended to check duplication at the caller&apos;s end
    function setNodeReferring(address[] memory addresses, uint256 tokenId, uint256[][] memory _tokenIds) private {
        require(_isApprovedOrOwner(msg.sender, tokenId), &quot;ERC_5521: transfer caller is not owner nor approved&quot;);

        Relationship storage relationship = _relationship[tokenId];

        for (uint i = 0; i &lt; addresses.length; i++) {
            if (relationship.referring[addresses[i]].length == 0) { relationship.referringKeys.push(addresses[i]); } // Add the address if it&apos;s a new entry
            relationship.referring[addresses[i]] = _tokenIds[i];
        }

        relationship.createdTimestamp = block.timestamp;
        emitEvents(tokenId, msg.sender);
    }

    /// @notice set the referred list of an rNFT associated with different contract addresses 
    /// @param _tokenIds array of rNFTs associated with addresses, recommended to check duplication at the caller&apos;s end
    function setNodeReferred(address[] memory addresses, uint256 tokenId, uint256[][] memory _tokenIds) private {
        for (uint i = 0; i &lt; addresses.length; i++) {
            if (addresses[i] == address(this)) {
                for (uint j = 0; j &lt; _tokenIds[i].length; j++) {
                    Relationship storage relationship = _relationship[_tokenIds[i][j]];
                    if (relationship.referred[addresses[i]].length == 0) { relationship.referredKeys.push(addresses[i]); } // Add the address if it&apos;s a new entry
                    
                    require(tokenId != _tokenIds[i][j], &quot;ERC_5521: self-reference not allowed&quot;);
                    if (relationship.createdTimestamp &gt;= block.timestamp) { revert(&quot;ERC_5521: the referred rNFT needs to be a predecessor&quot;); } // Make sure the reference complies with the timing sequence

                    relationship.referred[address(this)].push(tokenId);
                    emitEvents(_tokenIds[i][j], ownerOf(_tokenIds[i][j]));
                }
            } else {
                TargetContract targetContractInstance = TargetContract(addresses[i]);
                bool isSupports = targetContractInstance.supportsInterface(type(TargetContract).interfaceId);
                if (isSupports) {
                    // The target contract supports the interface, safe to call functions of the interface.
                    targetContractInstance.setNodeReferredExternal(address(this), tokenId, _tokenIds[i]);
                }
            }
        }
    }

    /// @notice set the referred list of an rNFT associated with different contract addresses 
    /// @param _tokenIds array of rNFTs associated with addresses, recommended to check duplication at the caller&apos;s end
    function setNodeReferredExternal(address _address, uint256 tokenId, uint256[] memory _tokenIds) external {
        for (uint i = 0; i &lt; _tokenIds.length; i++) {
            Relationship storage relationship = _relationship[_tokenIds[i]];
            if (relationship.referred[_address].length == 0) { relationship.referredKeys.push(_address); } // Add the address if it&apos;s a new entry

            require(_address != address(this), &quot;ERC_5521: this must be an external contract address&quot;);
            if (relationship.createdTimestamp &gt;= block.timestamp) { revert(&quot;ERC_5521: the referred rNFT needs to be a predecessor&quot;); } // Make sure the reference complies with the timing sequence

            relationship.referred[_address].push(tokenId);
            emitEvents(_tokenIds[i], ownerOf(_tokenIds[i]));
        }
    }

    /// @notice Get the referring list of an rNFT
    /// @param tokenId The considered rNFT, _address The corresponding contract address
    /// @return The referring mapping of an rNFT
    function referringOf(address _address, uint256 tokenId) external view virtual override(IERC_5521, TargetContract) returns (address[] memory, uint256[][] memory) {
        address[] memory _referringKeys;
        uint256[][] memory _referringValues;

        if (_address == address(this)) {
            require(_exists(tokenId), &quot;ERC_5521: token ID not existed&quot;);
            (_referringKeys, _referringValues) = convertMap(tokenId, true);
        } else {
            TargetContract targetContractInstance = TargetContract(_address);
            require(targetContractInstance.supportsInterface(type(TargetContract).interfaceId), &quot;ERC_5521: target contract not supported&quot;);
            (_referringKeys, _referringValues) = targetContractInstance.referringOf(_address, tokenId);     
        }      
        return (_referringKeys, _referringValues);
    }

    /// @notice Get the referred list of an rNFT
    /// @param tokenId The considered rNFT, _address The corresponding contract address
    /// @return The referred mapping of an rNFT
    function referredOf(address _address, uint256 tokenId) external view virtual override(IERC_5521, TargetContract) returns (address[] memory, uint256[][] memory) {
        address[] memory _referredKeys;
        uint256[][] memory _referredValues;

        if (_address == address(this)) {
            require(_exists(tokenId), &quot;ERC_5521: token ID not existed&quot;);
            (_referredKeys, _referredValues) = convertMap(tokenId, false);
        } else {
            TargetContract targetContractInstance = TargetContract(_address);
            require(targetContractInstance.supportsInterface(type(TargetContract).interfaceId), &quot;ERC_5521: target contract not supported&quot;);
            (_referredKeys, _referredValues) = targetContractInstance.referredOf(_address, tokenId);           
        }
        return (_referredKeys, _referredValues);
    }

    /// @notice Get the timestamp of an rNFT when is being created.
    /// @param `tokenId` of the rNFT being focused, `_address` of contract address associated with the focused rNFT.
    /// @return The timestamp of the rNFT when is being created with uint256 format.
    function createdTimestampOf(address _address, uint256 tokenId) external view returns(uint256) {
        uint256 memory createdTimestamp;

        if (_address == address(this)) {
            require(_exists(tokenId), &quot;ERC_5521: token ID not existed&quot;);
            Relationship storage relationship = _relationship[tokenId];
            createdTimestamp = relationship.createdTimestamp;
        } else {
            TargetContract targetContractInstance = TargetContract(_address);
            require(targetContractInstance.supportsInterface(type(TargetContract).interfaceId), &quot;ERC_5521: target contract not supported&quot;);
            createdTimestamp = targetContractInstance.createdTimestampOf(_address, tokenId);            
        }
        return createdTimestamp;
    }

    /// @dev See {IERC165-supportsInterface}.
    function supportsInterface(bytes4 interfaceId) public view virtual override (ERC721, IERC_5521, TargetContract) returns (bool) {
        return interfaceId == type(IERC_5521).interfaceId
            || interfaceId == type(TargetContract).interfaceId
            || super.supportsInterface(interfaceId);    
    }

    // @notice Emit an event of UpdateNode
    function emitEvents(uint256 tokenId, address sender) private {
        (address[] memory _referringKeys, uint256[][] memory _referringValues) = convertMap(tokenId, true);
        (address[] memory _referredKeys, uint256[][] memory _referredValues) = convertMap(tokenId, false);
        
        emit UpdateNode(tokenId, sender, _referringKeys, _referringValues, _referredKeys, _referredValues);
    }

    // @notice Convert a specific `local` token mapping to a key array and a value array
    function convertMap(uint256 tokenId, bool isReferring) private view returns (address[] memory, uint256[][] memory) {
        Relationship storage relationship = _relationship[tokenId];

        address[] memory returnKeys;
        uint256[][] memory returnValues;

        if (isReferring) {
            returnKeys = relationship.referringKeys;
            returnValues = new uint256[][](returnKeys.length);
            for (uint i = 0; i &lt; returnKeys.length; i++) {
                returnValues[i] = relationship.referring[returnKeys[i]];
            }            
        } else {
            returnKeys = relationship.referredKeys;
            returnValues = new uint256[][](returnKeys.length);
            for (uint i = 0; i &lt; returnKeys.length; i++) {
                returnValues[i] = relationship.referred[returnKeys[i]];
            }
        }
        return (returnKeys, returnValues);
    }
}

```


## Security Considerations

### Timestamp

The `createdTimestamp` only covers the block-level timestamp (based on block headers), which does not support fine-grained comparisons such as transaction-level.

### Ownership and Reference

The change of ownership has nothing to do with the reference relationship. Normally, the distribution of profits complies with the agreement when the NFT was being created regardless of the change of ownership unless specified in the agreement.

Referring a token will not refer to its descendants by default. In the case that only a specific child token gets referred, it means the privity of the contract will involve nobody other than the owner of this specific child token. Alternatively, a chain-of-reference all the way from the root token to a specific very bottom child token (from root to leaf) can be constructed and recorded in the `referring` to explicitly define the distribution of profits.

### Open Minting and Relationship Risks

The `safeMint` function has been deliberately designed to allow unrestricted minting and relationship setting, akin to the open referencing system seen in platforms such as Google Scholar. This decision facilitates strong flexibility, enabling any user to create and define relationships between NFTs without centralized control. While this design aligns with the intended openness of the system, it inherently carries certain risks. Unauthorized or incorrect references can be created, mirroring the challenges faced in traditional scholarly referencing, where erroneous citations may occur. Additionally, the open nature may expose the system to potential abuse by malicious actors, who might manipulate relationships or inflate the token supply. It is important to recognize that these risks are not considered design flaws but intentional trade-offs, which balance the system&apos;s flexibility against potential reliability concerns. 

Stakeholders should be aware that the on-chain data integrity guarantees extend only to what has been recorded on the blockchain and do not preclude the possibility of off-chain errors or manipulations. Thus, users and integrators should exercise caution and judgment in interpreting and using the relationships and other data provided by this system.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 10 Aug 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5521</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5521</guid>
      </item>
    
      <item>
        <title>Refundable Fungible Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5528-refundable-token-standard/10494</comments>
        
        <description>## Abstract

This standard is an extension of [EIP-20](/EIPs/EIPS/eip-20). This specification defines a type of escrow service with the following flow:

- The seller issues tokens.
- The seller creates an escrow smart contract with detailed escrow information like contract addresses, lock period, exchange rate, additional escrow success conditions, etc.
- The seller funds seller tokens to the *Escrow Contract*.
- Buyers fund buyer tokens which are pre-defined in the *Escrow Contract*.
- When the escrow status meets success, the seller can withdraw buyer tokens, and buyers can withdraw seller tokens based on exchange rates.
- Buyers can withdraw (or refund) their funded token if the escrow process is failed or is in the middle of the escrow process.

## Motivation

Because of the pseudonymous nature of cryptocurrencies, there is no automatic recourse to recover funds that have already been paid.

In traditional finance, trusted escrow services solve this problem. In the world of decentralized cryptocurrency, however, it is possible to implement an escrow service without a third-party arbitrator. This standard defines an interface for smart contracts to act as an escrow service with a function where tokens are sent back to the original wallet if the escrow is not completed.

## Specification

There are two types of contract for the escrow process:

- *Payable Contract*: The sellers and buyers use this token to fund the *Escrow Contract*. This contract MUST override [EIP-20](/EIPs/EIPS/eip-20) interfaces.
- *Escrow Contract*: Defines the escrow policies and holds *Payable Contract*&apos;s token for a certain period. This contract does not requires override [EIP-20](/EIPs/EIPS/eip-20) interfaces.

### Methods

#### `constructor`

The *Escrow Contract* demonstrates details of escrow policies as none-mutable matter in constructor implementation.

The *Escrow Contract* MUST define the following policies:

- Seller token contract address
- Buyer token contract address

The *Escrow Contract* MAY define the following policies:

- Escrow period
- Maximum (or minimum) number of investors
- Maximum (or minimum) number of tokens to fund
- Exchange rates of seller/buyer token
- KYC verification of users

#### `escrowFund`

Funds `_value` amount of tokens to address `_to`.

In the case of *Escrow Contract*:

 - `_to` MUST be the user address.
 - `msg.sender` MUST be the *Payable Contract* address.
 - MUST check policy validations.

In the case of *Payable Contract*:

  - The address `_to` MUST be the *Escrow Contract* address.
  - MUST call the same function of the *Escrow Contract* interface. The parameter `_to` MUST be `msg.sender` to recognize the user address in the *Escrow Contract*.

```solidity
function escrowFund(address _to, uint256 _value) public returns (bool)
```

#### `escrowRefund`

Refunds `_value` amount of tokens from address `_from`.

In the case of *Escrow Contract*:

 - `_from` MUST be the user address.
 - `msg.sender` MUST be the *Payable Contract* address.
 - MUST check policy validations.

In the case of *Payable Contract*:

  - The address `_from` MUST be the *Escrow Contract* address.
  - MUST call the same function of the *Escrow Contract* interface. The parameter `_from` MUST be `msg.sender` to recognize the user address in the *Escrow Contract*.

```solidity
function escrowRefund(address _from, uint256 _value) public returns (bool)
```

#### `escrowWithdraw`

Withdraws funds from the escrow account.

In the case of *Escrow Contract*:

 - MUST check the escrow process is completed.
 - MUST send the remaining balance of seller and buyer tokens to `msg.sender`&apos;s seller and buyer contract wallets.

In the case of *Payable Contract*, it is optional.

```solidity
function escrowWithdraw() public returns (bool)
```

### Example of interface

This example demonstrates simple exchange of one seller and one buyer in one-to-one exchange rates.

```solidity
pragma solidity ^0.4.20;

interface IERC5528 {

    function escrowFund(address _to, uint256 _value) public returns (bool);

    function escrowRefund(address _from, uint256 _value) public returns (bool);

    function escrowWithdraw() public returns (bool);

}

contract PayableContract is IERC5528, IERC20 {
    /*
      General ERC20 implementations
    */

    function _transfer(address from, address to, uint256 amount) internal {
        uint256 fromBalance = _balances[from];
        require(fromBalance &gt;= amount, &quot;ERC20: transfer amount exceeds balance&quot;);
        _balances[from] = fromBalance - amount;
        _balances[to] += amount;
    }

    function transfer(address to, uint256 amount) public returns (bool) {
        address owner = msg.sender;
        _transfer(owner, to, amount);
        return true;
    }

    function escrowFund(address _to, uint256 _value) public returns (bool){
        bool res = IERC5528(to).escrowFund(msg.sender, amount);
        require(res, &quot;Fund Failed&quot;);
        _transfer(msg.sender, to, amount);
        return true;
    }

    function escrowRefund(address _from, uint256 _value) public returns (bool){
        bool res = IERC5528(_from).escrowRefund(msg.sender, _value);
        require(res, &quot;Refund Failed&quot;);
        _transfer(_from, msg.sender, _value);
        return true;
    }
}

contract EscrowContract is IERC5528 {

    enum State { Inited, Running, Success, Closed }
    struct BalanceData {
        address addr;
        uint256 amount;
    }

    address _addrSeller;
    address _addrBuyer;
    BalanceData _fundSeller;
    BalanceData _fundBuyer;
    EscrowStatus _status;

    constructor(address sellerContract, address buyerContract){
        _addrSeller = sellerContract;
        _addrBuyer = buyerContract;
        _status = State.Inited;
    }

    function escrowFund(address _to, uint256 _value) public returns (bool){
        if(msg.sender == _addrSeller){
            require(_status.state == State.Running, &quot;must be running state&quot;);
            _fundSeller.addr = _to;
            _fundSeller.amount = _value;
            _status = State.Success;
        }else if(msg.sender == _addrBuyer){
            require(_status.state == State.Inited, &quot;must be init state&quot;);
            _fundBuyer.addr = _to;
            _fundBuyer.amount = _value;
            _status = State.Running;
        }else{
            require(false, &quot;Invalid to address&quot;);
        }
        return true;
    }

    function escrowRefund(address _from, uint256 amount) public returns (bool){
        require(_status.state == State.Running, &quot;refund is only available on running state&quot;);
        require(msg.sender == _addrBuyer, &quot;invalid caller for refund&quot;);
        require(_fundBuyer.addr == _from, &quot;only buyer can refund&quot;);
        require(_fundBuyer.amount &gt;= amount, &quot;buyer fund is not enough to refund&quot;);
        _fundBuyer.amount = _fundBuyer.amount - amount
        return true;
    }

    function escrowWithdraw() public returns (bool){
        require(_status.state == State.Success, &quot;withdraw is only available on success state&quot;);
        uint256 common = MIN(_fundBuyer.amount, _fundSeller.amount);

        if(common &gt; 0){
            _fundBuyer.amount = _fundBuyer.amount - common;
            _fundSeller.amount = _fundSeller.amount - common;

            // Exchange
            IERC5528(_addrSeller).transfer(_fundBuyer.addr, common);
            IERC5528(_addrBuyer).transfer(_fundSeller.addr, common);

            // send back the remaining balances
            if(_fundBuyer.amount &gt; 0){
                IERC5528(_addrBuyer).transfer(_fundBuyer.addr, _fundBuyer.amount);
            }
            if(_fundSeller.amount &gt; 0){
                IERC5528(_addrSeller).transfer(_fundSeller.addr, _fundSeller.amount);
            }
        }

        _status = State.Closed;
    }

}

```

## Rationale

The interfaces cover the escrow operation&apos;s refundable issue.

The suggested 3 functions (`escrowFund`, `escrowRefund` and `escrowWithdraw`) are based on `transfer` function in EIP-20.

`escrowFund` send tokens to the *Escrow Contract*. The *Escrow Contract* can hold the contract in the escrow process or reject tokens if the policy does not meet.

`escrowRefund` can be invoked in the middle of the escrow process or when the escrow process fails.

`escrowWithdraw` allows users (sellers and buyers) to transfer tokens from the escrow account. When the escrow process completes, the seller can get the buyer&apos;s token, and the buyers can get the seller&apos;s token.

## Backwards Compatibility

The *Payable Contract* which implements this EIP is fully backward compatible with the [EIP-20](/EIPs/EIPS/eip-20) specification.

## Test Cases

[Unit test example by truffle](/EIPs/assets/eip-5528/truffule-test.js).

This test case demonstrates the following conditions for exchanging seller/buyer tokens.

- The exchange rate is one-to-one.
- If the number of buyers reaches 2, the escrow process will be terminated(success).
- Otherwise (not meeting success condition yet), buyers can refund (or withdraw) their funded tokens.

## Security Considerations

Since the *Escrow Contract* controls seller and buyer rights, flaws within the *Escrow Contract* will directly lead to unexpected behavior and potential loss of funds.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 16 Aug 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5528</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5528</guid>
      </item>
    
      <item>
        <title>Revocation List Registry</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5539-revocation-list-registry/10573</comments>
        
        <description>## Abstract
This EIP proposes a set of methods and standards for a role-based registry of indicators aimed for usage in revocations.

## Motivation
Revocation is a universally needed construct both in the traditional centralized and decentralized credential attestation. This EIP aims to provide an interface to standardize a decentralized approach to managing and resolving revocation states in a contract registry.

The largest problem with traditional revocation lists is the centralized aspect of them. Most of the world&apos;s CRLs rely on HTTP servers as well as caching and are therefore vulnerable to known attack vectors in the traditional web space. This aspect severely weakens the underlying strong asymmetric key architecture in current PKI systems.

In addition, issuers in existing CRL approaches are required to host an own instance of their public revocation list, as shared or centralized instances run the risk of misusage by the controlling entity. 
This incentivizes issuers to shift this responsibility to a third party, imposing the risk of even more centralization of the ecosystem (see Cloudflare, AWS). 
Ideally, issuers should be able to focus on their area of expertise, including ownership of their revocable material, instead of worrying about infrastructure.

We see value in a future of the Internet where anyone can be an issuer of verifiable information. This proposal lays the groundwork for anyone to also own the lifecycle of this information to build trust in ecosystems.

## Specification
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.

This EIP specifies a contract called `EthereumRevocationRegistry` that is deployed once and may then be commonly used by everyone. By default, an Ethereum address **MAY** own and manage a multitude of revocation lists in a namespace that **MUST** contain the revocation states for a set of revocation keys. 

An owner of a namespace **MAY** allow delegates to manage one or more of its revocation lists. Delegates **MUST** be removable by the respective list&apos;s owner. In certain situations, an owner **MAY** also want to transfer a revocation list in a namespace and its management rights to a new owner.

### Definitions
- `namespace`: A namespace is a representation of an Ethereum address inside the registry that corresponds to its owners address. All revocation lists within a namespace are initially owned by the namespace&apos;s owner address.
- `revocation list`: A namespace can contain a number of revocation lists. Each revocation list is identified by a unique key of the type bytes32 that can be used to address it in combination with the namespace address.
- `revocation key`: A revocation list can contain a number of revocation keys of the type bytes32. In combination with the namespace address and the revocation list key, it resolves to a boolean value that indicates whether the revocation key is revoked or not.
- `owner`: An Ethereum address that has modifying rights to revocation lists within its own and possibly foreign namespaces. An owner can give up modifying rights of revocation lists within its namespace by transferring ownership to another address.
- `delegate`: An Ethereum address that received temporary access to a revocation list in a namespace. It has to be granted by the current owner of the revocation list in question.

### Revocation Management

#### isRevoked
**MUST** implement a function that returns the revocation status of a particular revocation key in a namespace&apos;s revocation list. It **MAY** also respect the revocation lists revocation status.
```solidity
function isRevoked(address namespace, bytes32 list, bytes32 key) public view returns (bool);
```

#### changeStatus
**MUST** implement a function to change the revocation status of a particular revocation key in a namespace&apos;s revocation list
```solidity
function changeStatus(bool revoked, address namespace, bytes32 revocationList, bytes32 revocationKey) public;
```

#### changeStatusSigned ([see Meta Transactions](#MetaTransactions))
**OPTIONAL** implements a function to change the revocation status of a particular revocation key in a namespace&apos;s revocation list with a raw signature.
```solidity
function changeStatusSigned(bool revoked, address namespace, bytes32 revocationList, bytes32 revocationKey, address signer, bytes calldata signature) public;
```

#### changeStatusDelegated
**OPTIONAL** implements a function to change the revocation status of a particular revocation key in a namespace&apos;s revocation list by a revocation list&apos;s delegate.
```solidity
function changeStatusDelegated(bool revoked, address namespace, bytes32 revocationList, bytes32 revocationKey) public;
```

#### changeStatusDelegatedSigned ([see Meta Transactions](#MetaTransactions))
**OPTIONAL** implements a function to change the revocation status of a particular revocation key in a namespace&apos;s revocation list with a raw signature.
```solidity
function changeStatusDelegatedSigned(bool revoked, address namespace, bytes32 revocationList, bytes32 revocationKey, address signer, bytes calldata signature) public;
```

#### changeStatusesInList
**OPTIONAL** implements a function to change multiple revocation statuses in a namespace&apos;s revocation list at once.
```solidity
function changeStatusesInList(bool[] memory revoked, address namespace, bytes32 revocationList, bytes32[] memory revocationKeys) public;
```

#### changeStatusesInListSigned ([see Meta Transactions](#MetaTransactions))
**OPTIONAL** implements a function to change multiple revocation statuses in a namespace&apos;s revocation list at once with a raw signature.
```solidity
function changeStatusesInListSigned(bool[] memory revoked, address namespace, bytes32 revocationList, bytes32[] memory revocationKeys, address signer, bytes calldata signature) public;
```

#### changeStatusesInListDelegated
**OPTIONAL** implements a function to change multiple revocation statuses in a namespace&apos;s revocation list at once by a revocation list&apos;s delegate.
```solidity
function changeStatusesInListDelegated(bool[] memory revoked, address namespace, bytes32 revocationList, bytes32[] memory revocationKeys) public;
```

#### changeStatusesInListDelegatedSigned ([see Meta Transactions](#MetaTransactions))
**OPTIONAL** implements a function to change multiple revocation statuses in a namespace&apos;s revocation list at once with a raw signature generated by a revocation list&apos;s delegate.
```solidity
function changeStatusesInListDelegatedSigned(bool[] memory revoked, address namespace, bytes32 revocationList, bytes32[] memory revocationKeys, address signer, bytes calldata signature) public;
```

### Revocation List Management

####
**OPTIONAL** implements a function that returns the revocation status of a particular revocation list in a namespace.
```solidity
function listIsRevoked(address namespace, bytes32 revocationList) view public returns (bool);
```

#### changeListStatus
**OPTIONAL** implements a function to change the revocation of a revocation list itself. If a revocation list is revoked, all its keys are considered revoked as well.
```solidity
function changeListStatus(bool revoked, address namespace, bytes32 revocationList) public;
```

#### changeListStatusSigned ([see Meta Transactions](#MetaTransactions))
**OPTIONAL** implements a function to change the revocation of a revocation list itself with a raw signature. If a revocation list is revoked, all its keys are considered revoked as well.
```solidity
function changeListStatusSigned(bool revoked, address namespace, bytes32 revocationList, address signer, bytes calldata signature) public;
```

### Owner management

#### changeListOwner
**OPTIONAL** implement a function to change the revocation status of a revocation list. If a revocation list is revoked, all keys in it are considered revoked.
```solidity
function changeListOwner(address newOwner, address namespace, bytes32 revocationList) public;
```

#### changeListOwnerSigned ([see Meta Transactions](#MetaTransactions))
**OPTIONAL** implement a function to change the revocation status of a revocation list with a raw signature. If a revocation list is revoked, all keys in it are considered revoked.
```solidity
function changeListOwnerSigned(address newOwner, address namespace, bytes32 revocationList, address signer, bytes calldata signature) public;
```

### Delegation management

#### addListDelegate
**OPTIONAL** implements a function to add a delegate to an owner&apos;s revocation list in a namespace.
```solidity
function addListDelegate(address delegate, address namespace, bytes32 revocationList) public;
```

#### addListDelegateSigned ([see Meta Transactions](#MetaTransactions))
**OPTIONAL** implements a function to add a delegate to an owner&apos;s revocation list in a namespace with a raw signature.
```solidity
function addListDelegateSigned(address delegate, address namespace, bytes32 revocationList, address signer, bytes calldata signature) public;
```

#### removeListDelegate
**OPTIONAL** implements a function to remove a delegate from an owner&apos;s revocation list in a namespace.
```solidity
function removeListDelegate(address delegate, address owner, bytes32 revocationList) public;
```

#### removeListDelegateSigned ([see Meta Transactions](#MetaTransactions))
**OPTIONAL** implements a function to remove a delegate from an owner&apos;s revocation list in a namespace with a raw signature.
```solidity
function removeListDelegateSigned(address delegate, address namespace, bytes32 revocationList, address signer, bytes calldata signature) public;
```

### Events

#### RevocationStatusChanged
**MUST** be emitted when `changeStatus`, `changeStatusSigned`, `changeStatusDelegated`, `changeStatusDelegatedSigned`, `changeStatusesInList`, `changeStatusesInListSigned`, `changeStatusesInListDelegated`, or `changeStatusesInListDelegatedSigned` was successfully executed.

```solidity
event RevocationStatusChanged(
    address indexed namespace,
    bytes32 indexed revocationList,
    bytes32 indexed revocationKey,
    bool revoked
);
```

#### RevocationListOwnerChanged
**MUST** be emitted when `changeListOwner` or `changeListOwnerSigned` was successfully executed.

```solidity
event RevocationListOwnerChanged(
    address indexed namespace,
    bytes32 indexed revocationList,
    address indexed newOwner
);
```

#### RevocationListDelegateAdded
**MUST** be emitted when `addListDelegate` or `addListDelegateSigned` was successfully executed.

```solidity
event RevocationListDelegateAdded(
    address indexed namespace,
    bytes32 indexed revocationList,
    address indexed delegate
);
```

#### RevocationListDelegateRemoved
**MUST** be emitted when `removeListDelegate` or `removeListDelegateSigned` was successfully executed.

```solidity
event RevocationListDelegateRemoved(
    address indexed namespace,
    bytes32 indexed revocationList,
    address indexed delegate
);
```

#### RevocationListStatusChanged
**MUST** be emitted when `changeListStatus` or `changeListStatusSigned` was successfully executed.

```solidity
event RevocationListStatusChanged(
    address indexed namespace,
    bytes32 indexed revocationlist,
    bool revoked
);
```

### Meta Transactions &lt;span id=&quot;MetaTransactions&quot;&gt;&lt;/span&gt;

This section uses the following terms:
- **`transaction signer`**: An Ethereum address that signs arbitrary data for the contract to execute **BUT** does not commit the transaction.
- **`transaction sender`**: An Ethereum address that takes signed data from a **transaction signer** and commits it wrapped with its own signature to the smart contract.

An address (**transaction signer**) **MAY** be able to deliver a signed payload off-band to another address (**transaction sender**) that initiates the Ethereum interaction with the smart contract. The signed payload **MUST** be limited to be used only once ([Signed Hash](#SignedHash) + [nonces](#Nonce)).

#### Signed Hash &lt;span id=&quot;SignedHash&quot;&gt;&lt;/span&gt;

The signature of the **transaction signer** **MUST** conform [EIP-712](/EIPs/EIPS/eip-712). This helps users understand what the payload they&apos;re signing consists of &amp; it improves the protection against replay attacks.

#### Nonce &lt;span id=&quot;Nonce&quot;&gt;&lt;/span&gt;

This EIP **RECOMMENDS** the use of a **dedicated nonce mapping** for meta transactions. If the signature of the **transaction sender** and its meta contents are verified, the contract increases a nonce for this **transaction signer**. This effectively removes the possibility for any other sender to execute the same transaction again with another wallet. 

## Rationale

### Why the concept of namespaces?
This provides every Ethereum address a reserved space, without the need to actively claim it in the contract. Initially addresses only have owner access in their own namespace.

### Why does a namespace always represent the initial owner address? 
The change of an owner of a list shouldn&apos;t break the link to a revocation key in it, as already existing off-chain data may depend on it. 

## Backwards Compatibility
No backward compatibility issues were found.

## Security Considerations

### Meta Transactions
The signature of signed transactions could potentially be replayed on different chains or deployed versions of the registry implementing this ERC. This security consideration is addressed by the usage of [EIP-712](/EIPs/EIPS/eip-712)

### Rights Management
The different roles and their inherent permissions are meant to prevent changes from unauthorized entities. The revocation list owner should always be in complete control over its revocation list and who has writing access to it.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 26 Aug 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5539</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5539</guid>
      </item>
    
      <item>
        <title>Representing IP and its Royalty Structure</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5553-representing-intellectual-property-on-chain-with-royalty-rights/10551</comments>
        
        <description>## Abstract
This proposal introduces a generic way to represent intellectual property on chain, along with a refined royalty representation mechanism and associated metadata link. This standard is not associated with a specific type of IP and could represent many types of IP, such as musical IP, videos, books, images, and more.
The standard is kept very generic to allow the industry to evolve new ecosystems that can all rely on the same basic standard at their core.

This standard allows market participants to:
1) Observe the canonical on-chain representation of an intellectual property
2) Discover its attached metadata
3) Discover its related royalty structure
4) This will enable building registration, licensing, and payout mechanisms for intellectual property assets in the future.

## Motivation

There is no accepted standard mechanism to license intellectual property or to represent it, except using traditional NFTs. However, regular NFTs only represent a collectible item use case and cannot easily represent more complicated use cases of licensing IP for different types of uses.
We can enable such licensing mechanisms if we can:

1) Declare that IP exists, SEPARATELY from its purchase ability
2) Declare possibly multiple interested parties to be paid for such IP 

For 1, no standard exists today.

For 2, traditional split standards exist based on NFT purchases or through mechanisms like 0xsplits. While these solve the main problem, they do not contain the ability to name multiple types of collaboration participants.



## Specification 

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

**contracts that want to represent IP on chain MUST implement [EIP-721](/EIPs/EIPS/eip-721) AND this Proposal**

This standard extends [EIP-721](/EIPs/EIPS/eip-721) with the following `IIPRepresentation` (IPR for short) interface.
Implementers of this standard **MUST** have all of the following functions:

### royaltyPortionTokens() function
This function MUST return an array of addresses related to [EIP-20](/EIPs/EIPS/eip-20) tokens that MUST represent royalty portions to different types of interested parties. These royalty portion tokens represent a more granular and streamlined way to declare royalty splits for multiple collaboration participants for the creation of the IP. 

For example, for a musical IP, we might have two tokens representing the composition/writing/publishing royalty portion side and the recording/master side. These royalty portion tokens are distributed to the collaboration participants and can later be queried by the various holders to distribute royalties. I.e., if one holds 10% of a royalty portion token, that holder will get 10% of the financial distribution related to that type of royalty.

### metadataURI() function
This function MUST return the URI to a metadata file containing any required metadata for the IP or an empty string. Each IP type MAY implement its metadata standard, defined separately. The file MUST be hosted in IPFS, Arweave, or other decentralized content-addressable systems in which the file&apos;s contents are not changeable without changing the URI.

### changeMetadataURI() function
This function allows changing the metadata URI to point to a new version of the metadata file. Calling this function MUST trigger the event `MetadataChanged` in case of success.

### ledger() function
This function MUST return the registry or registrar contract address or an EOA account that initialized the IP and associated royalty tokens. An IP representation MAY be registered in multiple places by different actors for different purposes. This function enables market participants to discover which registry mechanism is the parent of the IP and might have special access rights to manage the IP.

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.9;
import &apos;@openzeppelin/contracts/interfaces/IERC165.sol&apos;;


///
/// @dev Interface for Intellectual Property Representation
///
interface IIPRepresentation is IERC165 {
    
    /// @notice Called with the new URI to an updated metadata file
    /// @param _newUri - the URI pointing to a metadata file (file standard is up to the implementer)
    /// @param _newFileHash - The hash of the new metadata file for future reference and verification
    function changeMetadataURI(string memory _newUri, string memory _newFileHash) external ;

    /// @return array of addresses of ERC20 tokens representing royalty portion in the IP
    /// @dev i.e implementing ERC5501 (IRoyaltyInterestToken interface)
    function royaltyPortionTokens() external view returns (address[] memory) ;

    /// @return the address of the contract or EOA that initialized the IP registration
    /// @dev i.e., a registry or registrar, to be implemented in the future
    function ledger() external view returns (address) ;

    /// @return the URI of the current metadata file for the II P
    function metadataURI() external view returns (string memory) ;

    /// @dev event to be triggered whenever metadata URI is changed
    /// @param byAddress the addresses that triggered this operation
    /// @param oldURI the URI to the old metadata file before the change
    /// @param oldFileHash the hash of the old metadata file before the change
    /// @param newURI the URI to the new metadata file 
    /// @param newFileHash the hash of the new metadata file 
    event MetadaDataChanged(address byAddress, string oldURI, string oldFileHash, string newURI, string newFileHash);
}
```


## Rationale

### Returning an array of EIP-20 tokens presents a more robust royalty portions structure/

Current royalty implementations deal only with a single type of royalty payment: NFT sales. They also only allow a single type of royalty - i.e., Music NFTs cannot pay different people in different scenarios.
In other words, currently, a royalty split works the same way no matter what type of purchase or license deal has happened for all parties involved.

With this proposal, multiple **types** of royalty scenarios are allowed. A classic case is the music industry, in which we have writing/composition royalties and recording/master royalties. Different licensing types will pay different percentages to different parties based on context.

In the case of a song cover, a license payment formula can be created so that that 
a) Original IP&apos;s writers get paid for using the lyrics or composition of the song
b) recording artists of the original song do not get paid since their recording is not used
c) recording artists of the new IP will get paid
d) there are no writing royalties for the creators of the cover.

Moreover, this EIP has a single structure that connects to all types of royalty types and allows finding them more easily.
Lastly, moving EIP-20 tokens around is much easier than managing an 0xsplits contract.

### Separating the IP contract from the collectible and licensing NFTs enables scaling licensing types
By separating the canonical version of the IP from its various licensed uses (NFT purchase, streaming, usage of art and more.), this EIP introduces a path for an ecosystem of various license types and payment distributions to evolve.
In other words, when people use this scheme, they will not start by creating a music NFT or art NFT; they start by creating the IP Representation and then create types of licenses or collectibles for it, each as its own sellable NFT.

### A single pointer to the IP&apos;s metadata
The IPR points to metadata housed in IPFS or Arweave and allows changing it and keeping track of the changes in a simple and standard way. Today the only metadata standard is NFT metadata extension, but it is impossible to know to which standard the document adheres. With different IP types, different metadata standards for different IP types can be formulated and have a simple, easy place to discover attached metadata.

## Reference Implementation 

#### Implementing a Musical IP Representation (MIPR for short) based on IIPRepresentation
```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.9;
import &apos;@openzeppelin/contracts/token/ERC721/ERC721.sol&apos;;
import &quot;./interfaces/IIPRepresentation.sol&quot;;
import &quot;./interfaces/Structs.sol&quot;;


contract MusicalIP is ERC721, IIPRepresentation {
    address public songLedger;
    address public compToken;
    address public recToken;
    string public metadataURI;
    string public fileHash;
    uint256 public tokenId;
    bool public activated =false;

    function supportsInterface(bytes4 interfaceId) public view virtual override( ERC721, IERC165) returns (bool) {
        return
            interfaceId == type(IIPRepresentation).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    function getInterfaceId() public pure returns (bytes4){
        return type(IIPRepresentation).interfaceId;
    }

    constructor (
        uint256 _tokenId,
        address _songLedger,
        SongMintingParams memory _params,
        address _compAddress,
        address _recAddress
        )
    ERC721(_params.shortName, _params.symbol){

        songLedger = _songLedger;
        compToken = _compAddress;
        recToken = _recAddress;
        metadataURI = _params.metadataUri;
        fileHash = _params.fileHash;
        tokenId = _tokenId;
        
        _safeMint(_songLedger, _tokenId);
        emit Minted(_params.shortName,_songLedger,_compAddress,_recAddress,_msgSender(),tokenId,_params.metadataUri);
    }

    function changeMetadataURI(string memory _newURI,string memory _newFileHash) public 
     {
        string memory oldURI = metadataURI;
        string memory oldHash = fileHash;
        metadataURI = _newURI; 
        fileHash = _newFileHash;
        
        emit MetadataChanged(oldURI, oldHash,_newURI,_newFileHash);
    }
    
    function royaltyPortionTokens() external view returns (address[] memory) {
        address[] memory items = new address[](2); 
        items[0] = compToken;
        items[1] = recToken;
        return items;
    }
    function ledger() external view returns (address) {
         return songLedger;
    }

    event MetadataChanged(
        string  oldUri, string oldFileHash,
        string  newUri, string newFileHash
        );
    event Minted(
        string  abbvName,
        address ledger,
        address compToken,
        address recToken,
        address creator,
        uint256 tokenId,
        string metadataUri
        );
}



```

#### Deploying a new Musical IP using a simple song registry contract

```solidity  
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.9;
import &quot;@openzeppelin/contracts/utils/Counters.sol&quot;;
import &quot;./MusicalIP.sol&quot;;
import &quot;./CompositionRoyaltyToken.sol&quot;;
import &quot;./RecordingRoyaltyToken.sol&quot;;


contract SimpleSongLedger is IERC721Receiver {
    using Counters for Counters.Counter;
    Counters.Counter private mipIds;
      function onERC721Received(address, address, uint256, bytes calldata) external pure returns (bytes4) {
        return IERC721Receiver.onERC721Received.selector;
    }

    function mintSong(SongMintingParams memory _params) public {
        CompositionRoyaltyToken comp = new CompositionRoyaltyToken(address(this),&quot;SONGCOMP&quot;,&quot;COMP&quot;);
        RecordingRoyaltyToken rec = new RecordingRoyaltyToken(address(this),&quot;SONGREC&quot;,&quot;REC&quot;);
        mipIds.increment();

        MusicalIP mip = new MusicalIP(
                                        mipIds.current(),
                                        address(this),
                                        _params,
                                        address(comp),
                                        address(rec)
                                    );
    }
}


```
## Security Considerations

There might be potential security challenges of attackers persuading holders of royalty portion tokens to send them those tokens and gaining royalty portion in various IPRs. However, these are not specific to royalties and are a common issue with EIP-20 tokens.

In the case of the IP registration ownership, it will be recommended that registry contracts own the IP registration, which will be non-transferrable (account bound to the registry that created it).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 17 Aug 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5553</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5553</guid>
      </item>
    
      <item>
        <title>NFT Legal Use, Repurposing, and Remixing</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5999-legal-use-sharing-repurposing-and-remixing-standard-compatible-with-creative-commons/10553</comments>
        
        <description>## Abstract

This EIP extends any other token standard to provide:

* Explicit rights for the token holder related to commercial exploitation, derivative works, and reproduction;
* [EIP-5218](/EIPs/EIPS/eip-5218) interface for creating, viewing, and checking the status of licenses
* Standard format for extended license information in the token metadata;
* Standard events to track off chain creation of derivative works, commercial exploitation, and reproduction;
* On chain tracking of derivative works and reproductions
* Additional required fields in the smart contract to reference the copyright owner
* Function calls for commercial exploitation, derivative works and reproduction.

## Motivation
NFTs still face legal uncertainty, and many now realize that the rights associated with an NFT are just as important as the NFT itself. Our goal is to help the ecosystem reach clear consensus and broad understanding of what purchasers of NFTs are acquiring in terms of copyright or other rights. 

Today, purchasing the NFT of a digital work is not the same as purchasing the copyright in that work. In most cases, the NFT does not even incorporate the digital work; it only references it via a hash. Hence, the NFT holder owns a unique digital copy of the work, but does not necessarily enjoy the right to reproduce, redistribute, or otherwise exploit that work—unless explicitly provided for by the copyright owner. It typically only includes the right to privately enjoy the work and display it publicly on social media or in virtual galleries. 

We aim to create a new set of licenses with modular terms and conditions—à la Creative Commons—in order to enable artists to increase the value of their NFT by associating additional rights to them (e.g. the right to create derivative works, or to allow for the commercial usage of the underlying works). Our solution will allow for any licensed rights to be granted, only and exclusively, to the current holders of an NFT, and to be transferred automatically to the new token holders every time the NFT is being transferred. 

An on chain registry of copyrighted material will help in discovery of the rights associated with the NFTs that have been created with this protocol.

Our current work is drafting the legalese and technical specifications.

## Specification
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.

Every contract compliant with this EIP must implement the `IERC5554` interface:

```solidity
pragma solidity ^0.8.0;

interface IERC5554 is IERC5218 {

    event CommercialExploitation(uint256 _tokenId, uint256 _licenseId, string _externalUri);
    event ReproductionCreated(uint256 _tokenId, uint256 _licenseId, uint256 _reproductionId, address _reproduction, uint256 _reproductionTokenId);
    event DerivativeCreated(uint256 _tokenId, uint256 _licenseId, uint256 _derivativeId, address _derivative, uint256 _derivativeTokenId);

    /// @notice Retrieve the copyright owner address
    /// @dev Throws unless the token exists
    /// @param tokenId The identifier for the queried token
    /// @return address of the copyright owner
    function getCopyrightOwner(uint256 tokenId)
        external
        virtual
        returns (address);
    
    /// @notice Requests to log an execution of a license
    /// @dev Throws unless the token issuance conditions are met
    /// @param tokenId The identifier for the queried token
    /// @return uint256 tracking reproduction ID
    function logReproduction(uint256 tokenId, address reproduction, uint256 reproductionTokenId)
        external
        virtual
        returns (uint256);

    /// @notice Requests to log an executions of a license
    /// @dev Throws unless the token issuance conditions are met
    /// @param tokenId The identifier for the queried token
    /// @return uint256 tracking derivative ID
    function logDerivative(uint256 tokenId, address derivative, uint256 derivativeTokenId)
        external
        virtual
        returns (uint256);

    /// @notice Requests to log an execution of a license
    /// @dev Throws unless the commercial exploitation conditions are met
    /// @param tokenId The identifier for the queried token
    function logCommercialExploitation(uint256 tokenId, string calldata uri)
        external;

    /// @notice Retrieve the token associated with a reproduction
    /// @dev Throws unless the reproduction exists
    /// @param _reproductionId The identifier for the reproduction
    /// @return uint256 The identifier for the token used to generate the reproduction
    function getReproductionTokenId(uint256 _reproductionId)
        external
        view
        returns (uint256);

    /// @notice Retrieve the token associated with a reproduction
    /// @dev Throws unless the reproduction exists
    /// @param _reproductionId The identifier for the reproduction
    /// @return uint256 The identifier for the license used to generate the reproduction
    function getReproductionLicenseId(uint256 _reproductionId)
        external
        view
        returns (uint256);

    /// @notice Retrieve the token associated with a reproduction
    /// @dev Throws unless the reproduction exists
    /// @param _reproductionId The identifier for the derivative work
    /// @return address The address of the reproduction collection
    function getReproductionCollection(uint256 _reproductionId)
        external
        view
        returns (address);

    /// @notice Retrieve the token associated with a derivative
    /// @dev Throws unless the derivative exists
    /// @param _derivativeId The identifier for the derivative work
    /// @return uint256 The identifier for the token used to generate the derivative work
    function getDerivativeTokenId(uint256 _derivativeId)
        external
        view
        returns (uint256);

    /// @notice Retrieve the token associated with a derivative
    /// @dev Throws unless the derivative exists
    /// @param _derivativeId The identifier for the derivative work
    /// @return uint256 The identifier for the license used to generate the derivative work
    function getDerivativeLicenseId(uint256 _derivativeId)
        external
        view
        returns (uint256);

    /// @notice Retrieve the token associated with a derivative
    /// @dev Throws unless the derivative exists
    /// @param _derivativeId The identifier for the derivative work
    /// @return address The address of the derivative collection
    function getDerivativeCollection(uint256 _derivativeId)
        external
        view
        returns (address);

}
```



### Token based Attribution/ Remix
On chain derivative works and reproductions
* Reproductions and derivative works are tracked in the contract.


### Event based attribution
For commercial exploitation or other off-chain uses of a creative work, this EIP defines events to be emitted to track the use of the work.

```solidity
event CommercialExploitation(uint256 tokenID, string uri)

function logCommercialExploitation(uint256 tokenId, string calldata uri) external returns bool;
```

#### Example:
When a token holder uses an NFT for off-chain merchandise, log a reference to the off-chain work in the event uri

### Required fields

```solifity
function copyrightOwner(uint256 tokenId) external returns address;
```

Copyright owner per tokenID. Could just be the tokenID owner in a simple use case, or something else if desired by the creator.

## Rationale
We expand here upon the Motivation section to justify every decision made with regard to the specs of the standard:

The `getLicenseId()` function takes a tokenID as a parameter, making it possible for different tokenID to be associated with different licensing terms.

LicenseURI links to a content-addressed file that stipulates the terms and conditions of the license in actual legal language, so that the license can be read and understood by those who want to understand which rights are associated with the work of authorship, and which additional rights are granted through the acquisition of the NFT.

When the license allows for the reproduction and/or for the creation of a derivative work only to the token holders, there needs to be a way to verify that the new NFT or the derivative NFT was created legitimately. The standard ensures this by enabling the current token holder to call a function, e.g. logDerivative which checks that the caller has a valid license to execute

For commercial exploitation or other off-chain uses of a creative work, the standard implements the `logCommercialExploitation()` that makes it possible to keep track of which commercial exploitations have been made, and when. This makes it possible to verify that all commercial exploitation were legitimately done.

The standard introduces a new field, `copyrightOwner`, which indicates the address of the current holder of the copyright in the work. If multiple copyright owners exist, a multisig address (or DAO) can be used. 

The artist address is not registered as an on-chain variable, but rather as part of the metadata, because it is an immutable field. 

If any, the parents of the work (i.e. the works that it is derived upon) must be part of the metadata information, so that people can verify that the NFT has obtained a DerivativeWork for each one of its parents.

This licensing framework is intended to create a system to facilitate the licensing of rights that “follow the token” through a public licensing framework. This is not meant to be used for cases in which an exclusive right is licensed through a personal license to a specific actor (e.g. the copyright owner providing a third-party with the right to commercially exploit the work, regardless of whether they hold the token). This also is not designed to account for the sub-licensing case (e.g. licensing the right to one party to license third parties to engage in commercial exploitation), since this should rather be done via a personal copyright licensing scheme. 


### Examples

#### Bored Koalas merchandising

Vigdís creates a PFP collection of Bored Koalas, which is subject to standard copyright restrictions: no one has the right to reproduce, distribute, communicate, commercialize or remix these works. However, she wants to give specific permissions to those who hold a NFT from the collection. She mints the collection with this EIP, introducing a conditional license that allows for the current token holder to display the Bored Koala associated with each NFT and commercialize it for the purpose of merchandising only.

Neža has purchased one of these Bored Koalas. She wants to produce merchandising to be distributed at his blockchain conference. She goes to a print shop and asks them to make t-shirts with the Bored Koala image of the NFT she has purchased. The print shop can verify that she has the right to commercially exploit the work by verifying that they are the holder of the Bored Koala NFT, and verifying the terms of the license associated with it. (NB: this does not require a sub-license to be granted to the print shop, because the commercial exploitation implies the right to commission third parties to engage in such commercial exploitation). Neža brings the t-shirts to her conference and puts them for sale. When doing so, she calls the `logCommercialExploitation()` function from the NFT smart contract in order to track that the commercial exploitation was done at a time while she was the token holder.

#### Musical Remix

Matti is an up and coming songwriter in the emerging web3 music ecosystem. For the upcoming crypto conference, he creates a hit song called “Degens in the Night”. Instead of listing the song on a web2 platform, Matti mints the song as an NFT using this EIP, with a dual licensing scheme: a general public licenses that allows for the free reproduction and redistribution of the work, given proper attribution (e.g. Creative Commons BY-NC-ND) and a conditional license which allows for the token holder to remix the song, in exchange of a particular lump sum (e.g. 1ETH) and under the condition that the derivative work is released under the same licensing terms as the original work Lyyli wants to create a cover of that song, which she calls “Degens in the Parisian Night”. She purchases the NFT and mints a new derivative NFT under a new smart contract using this EIP standard. She then calls the `requestDerivativeToken()` function and send 1ETH to the original NFT smart contract, in order to request that a DerivativeToken be assigned to the new smart contract she has created. The smart contract automatically approves the request to assign a Derivative Token to the new smart contract of Lyyli. This can be used as a proof that the derivative work is indeed a legitimate work, which has been approved by the copyright owner of the original work. During the conference hundreds of other web3 music creators host a side event with Degens in the Night remixes playing until 4am. 

#### Royalties Remix

Alice created a 3D model of a motorcycle, which she wants everyone to remix, under the condition that she gets royalty from the commercial exploitation of all derivative works. She release her work as an NFT with this EIP, with a dual licensing scheme: a general public licenses that allows for the free reproduction and redistribution of the work, given proper attribution (e.g. Creative Commons BY-NC-ND) and a conditional license which allows for the token holder to remix the song, under the condition that the derivative work is released under the same licensing terms as the original work, and that there is a split of the royalties between himself and the remixer. 

Jane wants to create a derivative work of the motorcycle. She purchases the NFT and mints a new derivative NFT under a new smart contract that uses this EIP, which includes a royalty split for Alice. She then calls the `requestDerivativeToken()` function from the original NFT smart contract in order to request that a DerivativeToken be assigned to the new smart contract she has created. Alice decided that the smart contract shall not automate the approval or rejection of the request, but rather wait for her to validate or invalidate the request, after she has verified that the design and provisions of the new smart contract, namely that it does indeed replicate the same terms and conditions as the original work and that it incorporates the proper amount of royalties. She approves the request to assign a Derivative Token to the new smart contract of Jane. When people purchase Jane’s NFT, the royalties are split to ensure the proper redistribution of the generated profit to Alice. 

## Backwards Compatibility
The interface defined in this standard is backward compatible with most NFT standards used in the Ethereum ecosystem as of this writing.

## Security Considerations
Needs discussion.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 07 Jul 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5554</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5554</guid>
      </item>
    
      <item>
        <title>Cross Chain Write Deferral Protocol</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-cross-chain-write-deferral-protocol/10576</comments>
        
        <description>## Abstract
The following standard provides a mechanism in which smart contracts can request various tasks to be resolved by an external handler. This provides a mechanism in which protocols can reduce the gas fees associated with storing data on mainnet by deferring the handling of it to another system/network. These external handlers act as an extension to the core L1 contract.

This standard outlines a set of handler types that can be used for managing the execution and storage of mutations (tasks), as well as their corresponding tradeoffs. Each handler type has associated operational costs, finality guarantees, and levels of decentralization. By further specifying the type of handler that the mutation is deferred to, the protocol can better define how to permission and secure their system. 

This standard can be implemented in conjunction with [EIP-3668](./eip-3668) to provide a mechanism in which protocols can reside on and be interfaced through an L1 contract on mainnet, while being able to resolve and mutate data stored in external systems.

## Motivation
[EIP-3668](./eip-3668) provides a mechanism by which off-chain lookups can be defined inside smart contracts in a transparent manner. In addition, it provides a scheme in which the resolved data can be verified on-chain. However, there lacks a standard by which mutations can be requested through the native contract, to be performed on the off-chain data. Furthermore, with the increase in L2 solutions, smart contract engineers have additional tools that can be used to reduce the storage and transaction costs of performing mutations on the Ethereum mainnet. 

A specification that allows smart contracts to defer the storage and resolution of data to external handlers facilitates writing clients agnostic to the storage solution being used, enabling new applications that can operate without knowledge of the underlying handlers associated with the contracts they interact with.

Examples of this include:
 - Allowing the management of ENS domains externally resolved on an L2 solution or off-chain database as if they were native L1 tokens.
 - Allowing the management of digital identities stored on external handlers as if they were in the stored in the native L1 smart contract. 

## Specification
### Overview
There are two main handler classifications: L2 Contract and Off-Chain Database. These are determined based off of where the handler is deployed. The handler classifications are used to better define the different security guarantees and requirements associated with its deployment. 

From a high level:
- Handlers hosted on an L2 solution are EVM compatible and can use attributes native to the Ethereum ecosystem (such as address) to permission access. 
- Handlers hosted on an Off-Chain Database require additional parameters and signatures to correctly enforce the authenticity and check the validity of a request.  

A deferred mutation can be handled in as little as two steps. However, in some cases the mutation might be deferred multiple times.

1. Querying or sending a transaction to the contract
2. Querying or sending a transaction to the handler using the parameters provided in step 1

In step 1, a standard blockchain call operation is made to the contract. The contract either performs the operation as intended or reverts with an error that specifies the type of handler that the mutation is being deferred to and the corresponding parameters required to perform the subsequent mutation. There are two types of errors that the contract can revert with, but more may be defined in other EIPs:

- `StorageHandledByL2(chainId, contractAddress)`
- `StorageHandledByOffChainDatabase(sender, url, data)`

In step 2, the client builds and performs a new request based off of the type of error received in (1). These handshakes are outlined in the sections below:

- [StorageHandledByL2](#data-stored-in-an-l2)
- [StorageHandledByOffChainDatabase](#data-stored-in-an-off-chain-database) 

In some cases, the mutation may be deferred multiple times
- [Storage Deferred Twice L1 &gt; L2 &gt; Off-Chain](#data-stored-in-an-l2--an-off-chain-database) 

### Data Stored in an L1
```
┌──────┐                ┌───────────┐ 
│Client│                │L1 Contract│ 
└──┬───┘                └─────┬─────┘ 
   │                          │       
   │ somefunc(...)            │       
   ├─────────────────────────►│       
   │                          │       
   │ response                 │       
   │◄─────────────────────────┤       
   │                          │       
```

In the case in which no reversion occurs, data is stored in the L1 contract when the transaction is executed.

### Data Stored in an L2

```
┌──────┐                                           ┌───────────┐  ┌─────────────┐
│Client│                                           │L1 Contract│  │ L2 Contract │
└──┬───┘                                           └─────┬─────┘  └──────┬──────┘
   │                                                     │               │       
   │ somefunc(...)                                       │               │       
   ├────────────────────────────────────────────────────►│               │       
   │                                                     │               │       
   │ revert StorageHandledByL2(chainId, contractAddress) │               │       
   │◄────────────────────────────────────────────────────┤               │       
   │                                                     │               │       
   │ Execute Tx [chainId] [contractAddress] [callData]   │               │       
   ├─────────────────────────────────────────────────────┼──────────────►│       
   │                                                     │               │       
   │ response                                            │               │       
   │◄────────────────────────────────────────────────────┼───────────────┤       
   │                                                     │               │       
```

The call or transaction to the L1 contract reverts with the `StorageHandledByL2(chainId, contractAddress)` error.

In this case, the client builds a new transaction for `contractAddress` with the original `callData` and sends it to a RPC of their choice for the corresponding `chainId`. The `chainId` parameter corresponds to an L2 Solution that is EVM compatible.

#### Example

Suppose a contract has the following method:

```solidity
function setAddr(bytes32 node, address a) external;
```

Data for this mutations is stored and tracked on an EVM compatible L2. The contract author wants to reduce the gas fees associated with the contract, while maintaining the interoperability and decentralization of the protocol. Therefore, the mutation is deferred to a off-chain handler by reverting with the `StorageHandledByL2(chainId, contractAddress)` error.

One example of a valid implementation of `setAddr` would be:

```solidity
function setAddr(bytes32 node, address a) external {
   revert StorageHandledByL2(
      10,
      _l2HandlerContractAddress
   ); 
}
```

For example, if a contract returns the following data in an `StorageHandledByL2`:

```text
chainId = 10
contractAddress = 0x0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff
```

The user, receiving this error, creates a new transaction for the corresponding `chainId`, and builds a transaction with the original `callData` to send to `contractAddress`. The user will have to choose an RPC of their choice to send the transaction to for the corresponding `chainId`.

### Data Stored in an Off-Chain Database
```
┌──────┐                                           ┌───────────┐  ┌────────────────────┐
│Client│                                           │L1 Contract│  │ Off-Chain Database │
└──┬───┘                                           └─────┬─────┘  └──────────┬─────────┘
   │                                                     │                   │ 
   │ somefunc(...)                                       │                   │ 
   ├────────────────────────────────────────────────────►│                   │ 
   │                                                     │                   │ 
   │ revert StorageHandledByOffChainDatabase(sender,     |                   │ 
   │                               urls, requestParams)  │                   │ 
   │◄────────────────────────────────────────────────────┤                   │ 
   │                                                     │                   │ 
   │ HTTP Request [requestParams, signature]             │                   │ 
   ├─────────────────────────────────────────────────────┼──────────────────►│ 
   │                                                     │                   │ 
   │ response                                            │                   │ 
   │◄────────────────────────────────────────────────────┼───────────────────┤ 
   │                                                     │                   │ 
```

The call or transaction to the L1 contract reverts with the `StorageHandledByOffChainDatabase(sender, url, data)` error.

In this case, the client performs a HTTP POST request to the gateway service. The gateway service is defined by `url`. The body attached to the request is a JSON object that includes `sender`, `data`, and a signed copy of `data` denoted `signature`. The signature is generated according to a [EIP-712](./eip-712), in which a typed data signature is generated using domain definition, `sender`, and the message context, `data`.

`sender` ia an ABI-encoded struct defined as:

```solidity
/**
* @notice Struct used to define the domain of the typed data signature, defined in EIP-712.
* @param name The user friendly name of the contract that the signature corresponds to.
* @param version The version of domain object being used.
* @param chainId The ID of the chain that the signature corresponds to (ie Ethereum mainnet: 1, Goerli testnet: 5, ...). 
* @param verifyingContract The address of the contract that the signature pertains to.
*/
struct domainData {
    string name;
    string version;
    uint64 chainId;
    address verifyingContract;
}    
```

`data` ia an abi encoded struct defined as:

```solidity
/**
* @notice Struct used to define the message context used to construct a typed data signature, defined in EIP-712, 
* to authorize and define the deferred mutation being performed.
* @param functionSelector The function selector of the corresponding mutation.
* @param sender The address of the user performing the mutation (msg.sender).
* @param parameter[] A list of &lt;key, value&gt; pairs defining the inputs used to perform the deferred mutation.
*/
struct messageData {
    bytes4 functionSelector;
    address sender;
    parameter[] parameters;
    uint256 expirationTimestamp;
}

/**
* @notice Struct used to define a parameter for Off-Chain Database Handler deferral.
* @param name The variable name of the parameter.
* @param value The string encoded value representation of the parameter.
*/
struct parameter {
    string name;
    string value;
}
```

`signature` is generated by using the `sender` &amp; `data` parameters to construct an [EIP-712](./eip-712) typed data signature.

The body used in the HTTP POST request is defined as:

```json
{
    &quot;sender&quot;: &quot;&lt;abi encoded domainData (sender)&gt;&quot;,
    &quot;data&quot;: &quot;&lt;abi encoded messageData (data)&gt;&quot;,
    &quot;signature&quot;: &quot;&lt;EIP-712 typed data signature of corresponding message data &amp; domain definition&gt;&quot;
}
```

#### Example

Suppose a contract has the following method:

```solidity
function setAddr(bytes32 node, address a) external;
```

Data for this mutations is stored and tracked in some kind of off-chain database. The contract author wants the user to be able to authorize and make modifications to their `Addr` without having to pay a gas fee. Therefore, the mutation is deferred to a off-chain handler by reverting with the `StorageHandledByOffChainDatabase(sender, url, data)` error.

One example of a valid implementation of `setAddr` would be:

```solidity
function setAddr(bytes32 node, address a) external {
    IWriteDeferral.parameter[] memory params = new IWriteDeferral.parameter[](3);

    params[0].name = &quot;node&quot;;
    params[0].value = BytesToString.bytes32ToString(node);

    params[1].name = &quot;coin_type&quot;;
    params[1].value = Strings.toString(coinType);

    params[2].name = &quot;address&quot;;
    params[2].value = BytesToString.bytesToString(a);

    revert StorageHandledByOffChainDatabase(
        IWriteDeferral.domainData(
            {
                name: WRITE_DEFERRAL_DOMAIN_NAME,
                version: WRITE_DEFERRAL_DOMAIN_VERSION,
                chainId: 1,
                verifyingContract: address(this)
            }
        ),
        _offChainDatabaseUrl,
        IWriteDeferral.messageData(
            {
                functionSelector: msg.sig,
                sender: msg.sender,
                parameters: params,
                expirationTimestamp: block.timestamp + _offChainDatabaseTimeoutDuration
            }
        )
    );
}
```

For example, if a contract reverts with the following:

```text
StorageHandledByOffChainDatabase(
    (
        &quot;CoinbaseResolver&quot;, 
        &quot;1&quot;, 
        1, 
        0x32f94e75cde5fa48b6469323742e6004d701409b
    ), 
    &quot;https://example.com/r/{sender}&quot;, 
    (
        0xd5fa2b00, 
        0x727f366727d3c9cc87f05d549ee2068f254b267c, 
        [
            (&quot;node&quot;, &quot;0x418ae76a9d04818c7a8001095ad01a78b9cd173ee66fe33af2d289b5dc5f4cba&quot;), 
            (&quot;coin_type&quot;, &quot;60&quot;), 
            (&quot;address&quot;, &quot;0x727f366727d3c9cc87f05d549ee2068f254b267c&quot;)
        ], 
        181
    )
)
```

The user, receiving this error, constructs the typed data signature, signs it, and performs that request via a HTTP POST to `url`. 

Example HTTP POST request body including `requestParams` and `signature`:

```json
{
    &quot;sender&quot;: &quot;&lt;abi encoded domainData (sender)&gt;&quot;,
    &quot;data&quot;: &quot;&lt;abi encoded messageData (data)&gt;&quot;,
    &quot;signature&quot;: &quot;&lt;EIP-712 typed data signature of corresponding message data &amp; domain definition&gt;&quot;
}
```

Note that the message could be altered could be altered in any way, shape, or form prior to signature and request. It is the backend&apos;s responsibility to correctly permission and process these mutations. From a security standpoint, this is no different then a user being able to call a smart contract with any params they want, as it is the smart contract&apos;s responsibility to permission and handle those requests.


### Data Stored in an L2 &amp; an Off-Chain Database

```text
┌──────┐                                           ┌───────────┐  ┌─────────────┐  ┌────────────────────┐
│Client│                                           │L1 Contract│  │ L2 Contract │  │ Off-Chain Database │
└──┬───┘                                           └─────┬─────┘  └──────┬──────┘  └──────────┬─────────┘
   │                                                     │               │                    │
   │ somefunc(...)                                       │               │                    │
   ├────────────────────────────────────────────────────►│               │                    │
   │                                                     │               │                    │
   │ revert StorageHandledByL2(chainId, contractAddress) │               │                    │
   │◄────────────────────────────────────────────────────┤               │                    │
   │                                                     │               │                    │
   │ Execute Tx [chainId] [contractAddress] [callData]   │               │                    │
   ├─────────────────────────────────────────────────────┼──────────────►│                    │
   │                                                     │               │                    │
   │ revert StorageHandledByOffChainDatabase(sender, url, data)          │                    │
   │◄────────────────────────────────────────────────────┼───────────────┤                    │
   │                                                     │               │                    │
   │ HTTP Request {requestParams, signature}             │               │                    │
   ├─────────────────────────────────────────────────────┼───────────────┼───────────────────►│
   │                                                     │               │                    │
   │ response                                            │               │                    │
   │◄────────────────────────────────────────────────────┼───────────────┼────────────────────┤
   │                                                     │               │                    │
```

The call or transaction to the L1 contract reverts with the `StorageHandledByL2(chainId, contractAddress)` error.

In this case, the client builds a new transaction for `contractAddress` with the original `callData` and sends it to a RPC of their choice for the corresponding `chainId`. 

That call or transaction to the L2 contract then reverts with the `StorageHandledByOffChainDatabase(sender, url, data)` error.

In this case, the client then performs a HTTP POST request against the gateway service. The gateway service is defined by `url`. The body attached to the request is a JSON object that includes `sender`, `data`, and `signature` -- a typed data signature corresponding to [EIP-712](./eip-712). 

### Events

When making changes to core variables of the handler, the corresponding event MUST be emitted. This increases the transparency associated with different managerial actions. Core variables include `chainId` and `contractAddress` for L2 solutions and `url` for Off-Chain Database solutions. The events are outlined below in the WriteDeferral Interface.

### Write Deferral Interface

Below is a basic interface that defines and describes all of the reversion types and their corresponding parameters.

```solidity
pragma solidity ^0.8.13;

interface IWriteDeferral {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    /// @notice Event raised when the default chainId is changed for the corresponding L2 handler.
    event L2HandlerDefaultChainIdChanged(uint256 indexed previousChainId, uint256 indexed newChainId);
    /// @notice Event raised when the contractAddress is changed for the L2 handler corresponding to chainId.
    event L2HandlerContractAddressChanged(uint256 indexed chainId, address indexed previousContractAddress, address indexed newContractAddress);

    /// @notice Event raised when the url is changed for the corresponding Off-Chain Database handler.
    event OffChainDatabaseHandlerURLChanged(string indexed previousUrl, string indexed newUrl);

    /*//////////////////////////////////////////////////////////////
                                 STRUCTS
    //////////////////////////////////////////////////////////////*/

    /**
     * @notice Struct used to define the domain of the typed data signature, defined in EIP-712.
     * @param name The user friendly name of the contract that the signature corresponds to.
     * @param version The version of domain object being used.
     * @param chainId The ID of the chain that the signature corresponds to (ie Ethereum mainnet: 1, Goerli testnet: 5, ...). 
     * @param verifyingContract The address of the contract that the signature pertains to.
     */
    struct domainData {
        string name;
        string version;
        uint64 chainId;
        address verifyingContract;
    }    

    /**
     * @notice Struct used to define the message context used to construct a typed data signature, defined in EIP-712, 
     * to authorize and define the deferred mutation being performed.
     * @param functionSelector The function selector of the corresponding mutation.
     * @param sender The address of the user performing the mutation (msg.sender).
     * @param parameter[] A list of &lt;key, value&gt; pairs defining the inputs used to perform the deferred mutation.
     */
    struct messageData {
        bytes4 functionSelector;
        address sender;
        parameter[] parameters;
        uint256 expirationTimestamp;
    }

    /**
     * @notice Struct used to define a parameter for off-chain Database Handler deferral.
     * @param name The variable name of the parameter.
     * @param value The string encoded value representation of the parameter.
     */
    struct parameter {
        string name;
        string value;
    }


    /*//////////////////////////////////////////////////////////////
                                 ERRORS
    //////////////////////////////////////////////////////////////*/

    /**
     * @dev Error to raise when mutations are being deferred to an L2.
     * @param chainId Chain ID to perform the deferred mutation to.
     * @param contractAddress Contract Address at which the deferred mutation should transact with.
     */
    error StorageHandledByL2(
        uint256 chainId, 
        address contractAddress
    );

    /**
     * @dev Error to raise when mutations are being deferred to an Off-Chain Database.
     * @param sender the EIP-712 domain definition of the corresponding contract performing the off-chain database, write 
     * deferral reversion.
     * @param url URL to request to perform the off-chain mutation.
     * @param data the EIP-712 message signing data context used to authorize and instruct the mutation deferred to the 
     * off-chain database handler. 
     * In order to authorize the deferred mutation to be performed, the user must use the domain definition (sender) and message data 
     * (data) to construct a type data signature request defined in EIP-712. This signature, message data (data), and domainData (sender) 
     * are then included in the HTTP POST request, denoted sender, data, and signature.
     * 
     * Example HTTP POST request:
     *  {
     *      &quot;sender&quot;: &lt;abi encoded domainData (sender)&gt;,
     *      &quot;data&quot;: &lt;abi encoded message data (data)&gt;,
     *      &quot;signature&quot;: &lt;EIP-712 typed data signature of corresponding message data &amp; domain definition&gt;
     *  }
     * 
     */
    error StorageHandledByOffChainDatabase(
        domainData sender, 
        string url, 
        messageData data
    );     
}
```

### Use of transactions with storage-deferral reversions
In some cases the contract might conditionally defer and handle mutations, in which case a transaction may be required. It is simple to use this method for sending transactions that may result in deferral reversions, as a client should receive the corresponding reversion while `preflighting` the transaction.

This functionality is ideal for applications that want to allow their users to define the security guarantees and costs associated with their actions. For example, in the case of a decentralized identity profile, a user might not care if their data is decentralized and chooses to defer the handling of their records to the off-chain handler to reduce gas fees and on-chain transactions. 

## Rationale
### Use of `revert` to convey call information
[EIP-3668](./eip-3668) adopted the idea of using a `revert` to convey call information. It was proposed as a simple mechanism in which any pre-existing interface or function signature could be satisfied while maintain a mechanism to instruct and trigger an off-chain lookup. 

This is very similar for the write deferral protocol, defined in this EIP; without any modifications to the ABI or underlying EVM, `revert` provides a clean mechanism in which we can &quot;return&quot; a typed instruction - and the corresponding elements to complete that action - without modifying the signature of the corresponding function. This makes it easy to comply with pre-existing interfaces and infrastructure. 

### Use of multiple reversion &amp; handler types to better define security guarantees 
By further defining the class of the handler, it gives the developer increased granularity to define the characteristics and different guarantees associated storing the data off-chain. In addition, different handlers require different parameters and verification mechanisms. This is very important for the transparency of the protocol, as they store data outside of the native ethereum ecosystem. Common implementations of this protocol could include storing non-operational data in L2 solutions and off-chain databases to reduce gas fees, while maintaining open interoperability.   


## Backwards Compatibility
Existing contracts that do not wish to use this specification are unaffected. Clients can add support for Cross Chain Write Deferrals to all contract calls without introducing any new overhead or incompatibilities.

Contracts that require Cross Chain Write Deferrals will not function in conjunction with clients that do not implement this specification. Attempts to call these contracts from non-compliant clients will result in the contract throwing an exception that is propagated to the user.

## Security Considerations
Deferred mutations should never resolve to mainnet ethereum. Such attempts to defer the mutation back to ETH could include hijacking attempts in which the contract developer is trying to get the user to sign and send a malicious transaction. Furthermore, when a transaction is deferred to an L2 system, it must use the original `calldata`, this prevents against potentially malicious contextual changes in the transaction.

### Fingerprinting attacks
As all deferred mutations will include the `msg.sender` parameter in `data`, it is possible that `StorageHandledByOffChainDatabase` reversions could fingerprint wallet addresses and the corresponding IP address used to make the HTTP request. The impact of this is application-specific and something the user should understand is a risk associated with off-chain handlers. To minimize the security impact of this, we make the following recommendations:

1. Smart contract developers should provide users with the option to resolve data directly on the network. Allowing them to enable on-chain storage provides the user with a simple cost-benefit analysis of where they would like their data to resolve and different guarantees / risks associated with the resolution location.
2. Client libraries should provide clients with a hook to override Cross Chain Write Deferral `StorageHandledByOffChainDatabase` calls - either by rewriting them to use a proxy service, or by denying them entirely. This mechanism or another should be written so as to easily facilitate adding domains to allowlists or blocklists.

We encourage applications to be as transparent as possible with their setup and different precautions put in place.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 23 Jun 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5559</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5559</guid>
      </item>
    
      <item>
        <title>Redeemable NFTs</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-redeemable-nft-extension/10589</comments>
        
        <description>## Abstract

The EIP is a Redeemable NFT extension which adds a `redeem` function to [EIP-721](/EIPs/EIPS/eip-721). It can be implemented when an NFT issuer wants his/her NFT to be redeemed for a physical object.

## Motivation

An increasing amount of NFT issuers such as artists, fine art galeries, auction houses, brands and others want to offer a physical object to the holder of a given NFT. This standard allows EIP-721 NFTs to signal reedemability.

## Specification

_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._

`EIP-721` compliant contracts MAY implement this EIP to provide a standard method of receiving information on redeemability.

The NFT issuer **MUST** decide who is allowed to redeem the NFT, and restrict access to the `redeem()` function accordingly.

Anyone **MAY** access the `isRedeemable()` function to check the redeemability status: it returns `true` when the NFT redeemable, and `false` when already redeemed.

Third-party services that support this standard **MAY** use the `Redeem` event to listen to changes on the redeemable status of the NFT.

Implementers of this standard **MUST** have all of the following functions:

```solidity
import &apos;@openzeppelin/contracts/utils/introspection/ERC165.sol&apos;;

/**
 * @dev Implementation of Redeemable for ERC-721s
 *
 */

interface IRedeemable is ERC165 {
	/*
	 * ERC165 bytes to add to interface array - set in parent contract implementing this standard
	 *
	 * bytes4 private constant _INTERFACE_ID_ERC721REDEEM = 0x2f8ca953;
	 */
	 
	/// @dev This event emits when a token is redeemed.
	event Redeem(address indexed from, uint256 indexed tokenId);
	 
	/// @notice Returns the redeem status of a token
	/// @param tokenId Identifier of the token.
	function isRedeemable(uint256 _tokenId) external view returns (bool);

	/// @notice Redeeem a token
	/// @param tokenId Identifier of the token to redeeem
	function redeem(uint256 _tokenId) external;
}
```

The `Redeem` event is emitted when the `redeem()` function is called.

The `supportsInterface` method **MUST** return `true` when called with `0x2f8ca953`.

## Rationale

When the NFT contract is deployed, the `isRedeemable()` function returns `true` by default.

By default, the `redeem()` function visibility is public, so anyone can trigger it. It is **RECOMMENDED** to add a `require` to restrict the access:

```solidity
require(ownerOf(tokenId) == msg.sender, &quot;ERC721Redeemable: You are not the owner of this token&quot;);
```

After the `redeem()` function is triggered, `isRedeemable()` function returns `false`.

### `Redeem` event

When the `redeem()` function is triggered, the following event **MUST** be emitted:

```solidity
event Redeem(address indexed from, uint256 indexed tokenId);
```

## Backwards Compatibility

This standard is compatible with EIP-721.

## Reference Implementation

Here&apos;s an example of an EIP-721 that includes the Redeemable extension:

```solidity
contract ERC721Redeemable is ERC721, Redeemable {

	constructor(string memory name, string memory symbol) ERC721(name, symbol) {
	}

	function isRedeemable(uint256 tokenId) public view virtual override returns (bool) {
		require(_exists(tokenId), &quot;ERC721Redeemable: Redeem query for nonexistent token&quot;);
		return super.isRedeemable(tokenId);
	}

	function redeem(uint256 tokenId) public virtual override {
		require(_exists(tokenId), &quot;ERC721Redeemable: Redeem query for nonexistent token&quot;);
		require(ownerOf(tokenId) == msg.sender, &quot;ERC721Redeemable: You are not the owner of this token&quot;);
		super.redeem(tokenId);
	}

	function supportsInterface(bytes4 interfaceId) public view override(ERC721, Redeemable) returns (bool) {
		return super.supportsInterface(interfaceId);
	}
}
```

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 30 Aug 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5560</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5560</guid>
      </item>
    
      <item>
        <title>Stealth Addresses</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5566-stealth-addresses-for-smart-contract-wallets/10614</comments>
        
        <description>## Abstract

This specification establishes a standardized method for interacting with stealth addresses, which allow senders of transactions or transfers to non-interactively generate private accounts exclusively accessible by their recipients. Moreover, this specification enables developers to create stealth address protocols based on the foundational implementation outlined in this ERC, utilizing a singleton contract deployed at `0x55649E01B5Df198D18D95b5cc5051630cfD45564` to emit the necessary information for recipients. In addition to the base implementation, this ERC also outlines the first implementation of a cryptographic scheme, specifically the SECP256k1 curve.

## Motivation

The standardization of non-interactive stealth address generation presents the potential to significantly improve the privacy capabilities of the Ethereum network and other EVM-compatible chains by allowing recipients to remain private when receiving assets. This is accomplished through the sender generating a stealth address based on a shared secret known exclusively to the sender and recipient. The recipients alone can access the funds stored at their stealth addresses, as they are the sole possessors of the necessary private key. As a result, observers are unable to associate the recipient&apos;s stealth address with their identity, thereby preserving the recipient&apos;s privacy and leaving the sender as the only party privy to this information. By offering a foundational implementation in the form of a single contract that is compatible with multiple cryptographic schemes, recipients are granted a centralized location to monitor, ensuring they do not overlook any incoming transactions.

## Specification

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.

Definitions:

- A &quot;stealth meta-address&quot; is a set of one or two public keys that can be used to compute a stealth address for a given recipient.
- A &quot;spending key&quot; is a private key that can be used to spend funds sent to a stealth address. A &quot;spending public key&quot; is the corresponding public key.
- A &quot;viewing key&quot; is a private key that can be used to determine if funds sent to a stealth address belong to the recipient who controls the corresponding spending key. A &quot;viewing public key&quot; is the corresponding public key.

Different stealth address schemes will have different expected stealth meta-address lengths. A scheme that uses public keys of length `n` bytes MUST define stealth meta-addresses as follows:

- A stealth meta-address of length `n` uses the same stealth meta-address for the spending public key and viewing public key.
- A stealth meta-address of length `2n` uses the first `n` bytes as the spending public key and the last `n` bytes as the viewing public key.

Given a recipient&apos;s stealth meta-address, a sender MUST be able generate a stealth address for the recipient by calling a method with the following signature:

```solidity
/// @notice Generates a stealth address from a stealth meta address.
/// @param stealthMetaAddress The recipient&apos;s stealth meta-address.
/// @return stealthAddress The recipient&apos;s stealth address.
/// @return ephemeralPubKey The ephemeral public key used to generate the stealth address.
/// @return viewTag The view tag derived from the shared secret.
function generateStealthAddress(bytes memory stealthMetaAddress)
  external
  view
  returns (address stealthAddress, bytes memory ephemeralPubKey, bytes1 viewTag);
```

A recipient MUST be able to check if a stealth address belongs to them by calling a method with the following signature:

```solidity
/// @notice Returns true if funds sent to a stealth address belong to the recipient who controls
/// the corresponding spending key.
/// @param stealthAddress The recipient&apos;s stealth address.
/// @param ephemeralPubKey The ephemeral public key used to generate the stealth address.
/// @param viewingKey The recipient&apos;s viewing private key.
/// @param spendingPubKey The recipient&apos;s spending public key.
/// @return True if funds sent to the stealth address belong to the recipient.
function checkStealthAddress(
  address stealthAddress,
  bytes memory ephemeralPubKey,
  bytes memory viewingKey,
  bytes memory spendingPubKey
) external view returns (bool);
```

A recipient MUST be able to compute the private key for a stealth address by calling a method with the following signature:

```solidity
/// @notice Computes the stealth private key for a stealth address.
/// @param stealthAddress The expected stealth address.
/// @param ephemeralPubKey The ephemeral public key used to generate the stealth address.
/// @param viewingKey The recipient&apos;s viewing private key.
/// @param spendingKey The recipient&apos;s spending private key.
/// @return stealthKey The stealth private key corresponding to the stealth address.
/// @dev The stealth address input is not strictly necessary, but it is included so the method
/// can validate that the stealth private key was generated correctly.
function computeStealthKey(
  address stealthAddress,
  bytes memory ephemeralPubKey,
  bytes memory viewingKey,
  bytes memory spendingKey
) external view returns (bytes memory);
```

The implementation of these methods is scheme-specific. The specification of a new stealth address scheme MUST specify the implementation for each of these methods. Additionally, although these function interfaces are specified in Solidity, they do not necessarily ever need to be implemented in Solidity, but any library or SDK conforming to this specification MUST implement these methods with compatible function interfaces.

A 256 bit integer (`schemeId`) is used to identify stealth address schemes. A mapping from the schemeId to its specification MUST be declared in the ERC that proposes to standardize a new stealth address scheme. It is RECOMMENDED that `schemeId`s are chosen to be monotonically incrementing integers for simplicity, but arbitrary or meaningful `schemeId`s may be chosen. This ERC introduces a `schemeId` of `1` with the following extensions:

- `1` is the integer identifier for the scheme,
- `viewTags` MUST be included in the announcement event and is used to reduce the parsing time for the recipients.
- SECP256k1 is the algorithm for encoding a stealth meta-address (i.e. the spending public key and viewing public key) into a `bytes` array, and decoding it from `bytes` to the native key types of that scheme.
- SECP256k1 with view tags will be used in `generateStealthAddress`, `checkStealthAddress`, and `computeStealthKey` methods.

This specification additionally defines a singleton `ERC5564Announcer` contract that emits events to announce when something is sent to a stealth address. This MUST be a singleton contract, with one instance per chain. The contract is specified as follows:

```solidity
/// @notice Interface for announcing when something is sent to a stealth address.
contract IERC5564Announcer {
  /// @dev Emitted when sending something to a stealth address.
  /// @dev See the `announce` method for documentation on the parameters.
  event Announcement (
    uint256 indexed schemeId,
    address indexed stealthAddress,
    address indexed caller,
    bytes ephemeralPubKey,
    bytes metadata
  );

  /// @dev Called by integrators to emit an `Announcement` event.
  /// @param schemeId The integer specifying the applied stealth address scheme.
  /// @param stealthAddress The computed stealth address for the recipient.
  /// @param ephemeralPubKey Ephemeral public key used by the sender.
  /// @param metadata An arbitrary field MUST include the view tag in the first byte.
  /// Besides the view tag, the metadata can be used by the senders however they like,
  /// but the below guidelines are recommended:
  /// The first byte of the metadata MUST be the view tag.
  /// - When sending/interacting with the native token of the blockchain (cf. ETH), the metadata SHOULD be structured as follows:
  ///     - Byte 1 MUST be the view tag, as specified above.
  ///     - Bytes 2-5 are `0xeeeeeeee`
  ///     - Bytes 6-25 are the address 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE.
  ///     - Bytes 26-57 are the amount of ETH being sent.
  /// - When interacting with ERC-20/ERC-721/etc. tokens, the metadata SHOULD be structured as follows:
  ///   - Byte 1 MUST be the view tag, as specified above.
  ///   - Bytes 2-5 are a function identifier. When a function selector (e.g.
  ///     the first (left, high-order in big-endian) four bytes of the Keccak-256
  ///     hash of the signature of the function, like Solidity and Vyper use) is
  ///     available, it MUST be used.
  ///   - Bytes 6-25 are the token contract address.
  ///   - Bytes 26-57 are the amount of tokens being sent/interacted with for fungible tokens, or
  ///     the token ID for non-fungible tokens.
  function announce (
    uint256 schemeId,
    address stealthAddress,
    bytes memory ephemeralPubKey,
    bytes memory metadata
  )
    external
  {
    emit Announcement(schemeId, stealthAddress, msg.sender, ephemeralPubKey, metadata);
  }
}
```

### Stealth meta-address format

The new address format for the stealth meta-address extends the chain specific address format by adding a `st:` (_stealth_) prefix.
Thus, a stealth meta-address on Ethereum has the following format:

```
st:eth:0x&lt;spendingPubKey&gt;&lt;viewingPubKey&gt;
```

Stealth meta-addresses may be managed by the user and/or registered within a publicly available `Registry` contract, as delineated in [ERC-6538](/EIPs/EIPS/eip-6538). This provides users with a centralized location for identifying stealth meta-addresses associated with other individuals while simultaneously enabling recipients to express their openness to engage via stealth addresses.

_Notably, the address format is used only to differentiate stealth addresses from standard addresses, as the prefix is removed before performing any computations on the stealth meta-address._

---

### Initial Implementation of SECP256k1 with View Tags

This ERC provides a foundation that is not tied to any specific cryptographic system through the `IERC5564Announcer` contract. In addition, it introduces the first implementation of a stealth address scheme that utilizes the SECP256k1 elliptic curve and view tags. The SECP256k1 elliptic curve is defined with the equation $y^2 = x^3 + 7 \pmod{p}$, where $p = 2^{256} - 2^{32} - 977$.

The following reference is divided into three sections:

1. Stealth address generation

2. Parsing announcements

3. Stealth private key derivation

Definitions:

- $G$ represents the generator point of the curve.

#### Generation - Generate stealth address from stealth meta-address:

- Recipient has access to the private keys $p_{spend}$, $p_{view}$ from which public keys $P_{spend}$ and $P_{view}$ are derived.

- Recipient has published a stealth meta-address that consists of the public keys $P_{spend}$ and $P_{view}$.

- Sender passes the stealth meta-address to the `generateStealthAddress` function.

- The `generateStealthAddress` function performs the following computations:
  - Generate a random 32-byte entropy ephemeral private key $p_{ephemeral}$.
  - Derive the ephemeral public key $P_{ephemeral}$ from $p_{ephemeral}$.
  - Parse the spending and viewing public keys, $P_{spend}$ and $P_{view}$, from the stealth meta-address.
  - A shared secret $s$ is computed as $s = p_{ephemeral} \cdot P_{view}$.
  - The secret is hashed $s_{h} = \textrm{h}(s)$.
  - The view tag $v$ is extracted by taking the most significant byte $s_{h}[0]$,
  - Multiply the hashed shared secret with the generator point $S_h = s_h \cdot G$.
  - The recipient&apos;s stealth public key is computed as $P_{stealth} = P_{spend} + S_h$.
  - The recipient&apos;s stealth address $a_{stealth}$ is computed as $\textrm{pubkeyToAddress}(P_{stealth})$.
  - The function returns the stealth address $a_{stealth}$, the ephemeral public key $P_{ephemeral}$ and the view tag $v$.

#### Parsing - Locate one&apos;s own stealth address(es):

- User has access to the viewing private key $p_{view}$ and the spending public key $P_{spend}$.

- User has access to a set of `Announcement` events and applies the `checkStealthAddress` function to each of them.

- The `checkStealthAddress` function performs the following computations:
  - Shared secret $s$ is computed by multiplying the viewing private key with the ephemeral public key of the announcement $s = p_{view}$ * $P_{ephemeral}$.
  - The secret is hashed $s_{h} = h(s)$.
  - The view tag $v$ is extracted by taking the most significant byte $s_{h}[0]$ and can be compared to the given view tag. If the view tags do not match, this `Announcement` is not for the user and the remaining steps can be skipped. If the view tags match, continue on.
  - Multiply the hashed shared secret with the generator point $S_h = s_h \cdot G$.
  - The stealth public key is computed as $P_{stealth} = P_{spend} + S_h$.
  - The derived stealth address $a_{stealth}$ is computed as $\textrm{pubkeyToAddress}(P_{stealth})$.
  - Return `true` if the stealth address of the announcement matches the derived stealth address, else return `false`.

#### Private key derivation - Generate the stealth address private key from the hashed shared secret and the spending private key.

- User has access to the viewing private key $p_{view}$ and spending private key $p_{spend}$.

- User has access to a set of `Announcement` events for which the `checkStealthAddress` function returns `true`.

- The `computeStealthKey` function performs the following computations:
  - Shared secret $s$ is computed by multiplying the viewing private key with the ephemeral public key of the announcement $s = p_{view}$ * $P_{ephemeral}$.
  - The secret is hashed $s_{h} = h(s)$.
  - The stealth private key is computed as $p_{stealth} = p_{spend} + s_h$.

### Parsing considerations

Usually, the recipient of a stealth address transaction has to perform the following operations to check whether he was the recipient of a certain transaction:

- 2x ecMUL,

- 2x HASH,

- 1x ecADD,

The view tags approach is introduced to reduce the parsing time by around 6x. Users only need to perform 1x ecMUL and 1x HASH (skipping 1x ecMUL, 1x ecADD and 1x HASH) for every parsed announcement. The 1-byte view tag length is based on the maximum required space to reliably filter non-matching announcements. With a 1-byte `viewTag`, the probability for users to skip the remaining computations after hashing the shared secret $h(s)$ is $255/256$. This means that users can almost certainly skip the above three operations for any announcements that do not involve them. Since the view tag reveals one byte of the shared secret, the security margin is reduced from 128 bits to 124 bits. Notably, this only affects the privacy and not the secure generation of a stealth address.

---

## Rationale

This ERC emerged from the need for privacy-preserving ways to transfer ownership without disclosing any information about the recipients&apos; identities. Token ownership can expose sensitive personal information. While individuals may wish to donate to a specific organization or country, they might prefer not to disclose a link between themselves and the recipient simultaneously. Standardizing stealth address generation represents a significant step towards unlinkable interactions, since such privacy-enhancing solutions require standards to achieve widespread adoption. Consequently, it is crucial to focus on developing generalizable approaches for implementing related solutions.

The stealth address specification standardizes a protocol for generating and locating stealth addresses, facilitating the transfer of assets without requiring prior interaction with the recipient. This enables recipients to verify the receipt of a transfer without the need to interact with the blockchain and query account balances. Importantly, stealth addresses enable token transfer recipients to verify receipt while maintaining their privacy, as only the recipient can recognize themselves as the recipient of the transfer.

The authors recognize the trade-off between on- and off-chain efficiency. Although incorporating a Monero-like view tags mechanism enables recipients to parse announcements more efficiently, it adds complexity to the announcement event.

The recipient&apos;s address and the `viewTag` must be included in the announcement event, allowing users to quickly verify ownership without querying the chain for positive account balances.

## Backwards Compatibility

This ERC is fully backward compatible.

### Deployment Method

The `ERC5564Announcer` contract is deployed at `0x55649E01B5Df198D18D95b5cc5051630cfD45564` using `CREATE2` via the deterministic deployer at `0x4e59b44847b379578588920ca78fbf26c0b4956c` with a salt of `0xd0103a290d760f027c9ca72675f5121d725397fb2f618f05b6c44958b25b4447`.

## Reference Implementation

You can find the implementation of the `ERC5564Announcer` contract [here](/EIPs/assets/eip-5564/contracts/ERC5564Announcer.sol) and the interface `IERC5564Announcer.sol` [here](/EIPs/assets/eip-5564/contracts/interfaces/IERC5564Announcer.sol).

## Security Considerations

### DoS Countermeasures

There are potential denial of service (DoS) attack vectors that are not mitigated by network transaction fees. Stealth transfer senders cause an externality for recipients, as parsing announcement events consumes computational resources that are not compensated with gas. Therefore, spamming announcement events _can_ be a detriment to the user experience, as it _can_ lead to longer parsing times.
We consider the incentives to carry out such an attack to be low because **no monetary benefit can be obtained**
However, to tackle potential spam, parsing providers may adopt their own anti-DoS attack methods. These may include ignoring the spamming users when serving announcements to users or, less harsh, de-prioritizing them when ordering the announcements. The indexed `caller` keyword may help parsing providers to effectively filter known spammers.

Furthermore, parsing providers have a few options to counter spam, such as introducing staking mechanisms or requiring senders to pay a `toll` before including their `Announcement`. Moreover, a Staking mechanism may allow users to stake an unslashable amount of ETH (similarly to [ERC-4337](./eip-4337)), to help mitigate potential spam through _sybil attacks_ and enable parsing providers filtering spam more effectively.
Introducing a `toll`, paid by sending users, would simply put a cost on each stealth address transaction, making spamming economically unattractive.

### Recipients&apos; transaction costs

The funding of the stealth address wallet represents a known issue that might breach privacy. The wallet that funds the stealth address MUST NOT have any physical connection to the stealth address owner in order to fully leverage the privacy improvements.

Thus, the sender may attach a small amount of ETH to each stealth address transaction, thereby sponsoring subsequent transactions of the recipient.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 13 Aug 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5564</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5564</guid>
      </item>
    
      <item>
        <title>Well-Known Format for Required Actions</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5568-revert-signals/10622</comments>
        
        <description>## Abstract

This ERC introduces a minimalistic machine-readable (binary) format to signal to wallets that an action needs to be taken by the user using a well-known function and revert reason. It provides just enough data to be extendable by future ERCs and to take in arbitrary parameters (up to 64 kB of data). Example use cases could include approving a token for an exchange, sending an HTTP request, or requesting the user to rotate their keys after a certain period of time to enforce good hygiene.

## Motivation

Oftentimes, a smart contract needs to signal to a wallet that an action needs to be taken, such as to sign a transaction or send an HTTP request to a URL. Traditionally, this has been done by hard-coding the logic into the frontend, but this ERC allows the smart contract itself to request the action.

This means that, for example, an exchange or a market can directly tell the wallet to approve the smart contract to spend the token, vastly simplifying front-end code.

## Specification

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.

### Action Detection

```solidity
interface IERC5568 {
    function walletSignal24(bytes32 selector, bytes function_data) view returns (uint24 instruction_id, bytes instruction_data);
}
```

The `instruction_id` of an instruction defined by an ERC MUST be its ERC number unless there are exceptional circumstances (be reasonable). An ERC MUST define exactly zero or one `instruction_id`. The structure of the instruction data for any `instruction_id` MUST be defined by the ERC that defines the `instruction_id`.

To indicate that an action needs to be taken, return the `instruction_id` and `instruction_data`. To indicate no actions need to be taken, set `instruction_id` to be `0` and `instruction_data` to any value.

### Custom Revert Reason

To signal an action was not taken, a compliant smart contract MUST revert with the following error:

```solidity
error WalletSignal24(uint24 instruction_id, bytes instruction_data)
```

The `instruction_id` of an instruction defined by an ERC MUST be its ERC number unless there are exceptional circumstances (be reasonable). An ERC MUST define exactly zero or one `instruction_id`. The structure of the instruction data for any `instruction_id` MUST be defined by the ERC that defines the `instruction_id`.

### Responding to a Revert

Before submitting a transaction to the mempool, the `walletSignal24` function MUST be simulated locally. It MUST be treated as if it were a non-`view` function capable of making state changes (e.g. `CALLS` to non-`view` functions are allowed). If the resulting `instruction_id` is nonzero, an action needs to be taken.

The `instruction_id`, and `instruction_data` MUST be taken from the `walletSignal24` simulation. The instruction SHOULD be evaluated as per the relevant ERC. If the instruction is not supported by the wallet, it MUST display an error to the user indicating that is the case. The wallet MUST then re-evaluate the transaction, except if an instruction explicitly states that the transaction MUST NOT be re-evaluated.

If an instruction is invalid, or the `instruction_id`, and `instruction_data` cannot be parsed, then an error MUST be displayed to the user indicating that is the case. The transaction MUST NOT be re-evaluated.

## Rationale

This ERC was explicitly optimized for deployment gas cost and simplicity. It is expected that libraries will eventually be developed that makes this more developer-friendly.

[ERC-165](/EIPs/EIPS/eip-165) is not used, since the interface is simple enough that it can be detected simply by calling the function.

## Backwards Compatibility

### Human-Readable Revert Messages

See [Revert Reason Collisions](#revert-reason-collisions).

### [ERC-3668](/EIPs/EIPS/eip-3668)

ERC-3668 can be used alongside this ERC, but it uses a different mechanism than this ERC.

## Security Considerations

### Revert Reason Collisions

It is unlikely that the signature of the custom error matches any custom errors in the wild. In the case that it does, no harm is caused unless the data happen to be a valid instruction, which is even more unlikely.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 31 Aug 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5568</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5568</guid>
      </item>
    
      <item>
        <title>Digital Receipt Non-Fungible Tokens</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/idea-standard-digital-receipts-using-erc-721/9908</comments>
        
        <description>## Abstract

This ERC proposes a standard schema for digital receipts of transactions. Digital Receipt Non-Fungible Tokens are issued by a vendor when a customer makes a purchase from their store and contains transaction details necessary for record keeping. Digital Receipt Non-Fungible Tokens extend [ERC-721](/EIPs/EIPS/eip-721) which allows for the management and ownership of unique tokens.

## Motivation

Purchases from online retailers include a receipt that is emailed and/or physically provided to the customer. These receipts are critical for many reasons but are provided in an analogue form which is difficult to parse by financial systems. Digital receipts have never gained traction dispite the fact that point of sales systems are already digital and the customers often want this information in their own digital systems. So we are left with a redundant Digital -&gt; Analogue -&gt; Digital process which requires unnecessary data entry or the use of clunky receipt-scanning applications.

Digital receipts are relatively simple and can be specified with a schema that can be parsed into JSON or other structured formats. In addition we can prove the receipts validity by digitally signing the receipt using the vendors private keys. 

As Ethereum scales tooling will need to be developed to provide end users with features (such as receipts) already available to fiat transactions. NFTs provide a unique opportunity to link an on chain purchase with its transaction details directly through the transaction state update. If we conceptually think of a transaction as funds provided to one participant and goods provided to another, then our real life state includes two sides of a transaction, 1) Funds changing ownership and 2) goods changing ownership. NFT receipts are first class citizens of a transaction reflecting the goods changing ownership as part of the transaction state. They will bring our on chain transaction state in line with the changes happening in the real world.

The convenience of a direct link to the transaction receipt via the transaction state is significant, other methods of distributing receipts either off chain or through smart contracts separate to the initial transaction lose this link and force the end user to manually locate the transaction details when needed. 
The benefit can be demonstrated by comparing a wallet that allows a user to click through a transaction to its receipt (available immediately after purchase without any further action) verses a user needing to search through a datastore to locate a receipt for a transaction that they can see in their wallet history.

Digital receipt as NFTs can also conceptually include other important information such as item serial numbers and delivery tracking etc.

One of the major roadblocks to fully automating our finance world has been the difficulty in tracking transaction details. Human beings physically tracking paper receipts is archaic and NFTs on the blockchain provide a pathway for these systems to be significantly improved.

## Specification

Transaction Flow:

 - A customer purchases an item from an online retailer, checking out leads the customer to an option to mint a NFT.
 - The smart contract provides the user with a Digital Receipt Non-Fungible Token.
 - When fulfilling the order, the retailer will upload the digital receipt specified in in the JSON schema below as the metadata to the previously minted NFT.

### Digital Receipt JSON Schema

The JSON schema is composed of 2 parts. The root schema contains high level details of the receipt (for example Date and Vendor) and another schema for the optionally recurring line items contained in the receipt.

#### Root Schema

```json
{
  &quot;id&quot;: &quot;receipt.json#&quot;,
  &quot;description&quot;: &quot;Receipt Schema for Digital Receipt Non-Fungible Tokens&quot;,
  &quot;type&quot;: &quot;object&quot;,
  &quot;required&quot;: [&quot;name&quot;, &quot;description&quot;, &quot;image&quot;, &quot;receipt&quot;],
  &quot;properties&quot;: {
    &quot;name&quot;: {
      &quot;title&quot;: &quot;Name&quot;,
      &quot;description&quot;: &quot;Identifies the token as a digital receipt&quot;,
      &quot;type&quot;: &quot;string&quot;
    },
    &quot;description&quot;: {
      &quot;title&quot;: &quot;Description&quot;,
      &quot;description&quot;: &quot;Brief description of a digital receipt&quot;,
      &quot;type&quot;: &quot;string&quot;
    },
    &quot;receipt&quot;: {
      &quot;title&quot;: &quot;Receipt&quot;,
      &quot;description&quot;: &quot;Details of the receipt&quot;,
      &quot;type&quot;: &quot;object&quot;,
      &quot;required&quot;: [&quot;id&quot;, &quot;date&quot;, &quot;vendor&quot;, &quot;items&quot;],
      &quot;properties&quot;: {
        &quot;id&quot;: {
          &quot;title&quot;: &quot;ID&quot;,
          &quot;description&quot;: &quot;Unique ID for the receipt generated by the vendor&quot;,
          &quot;type&quot;: &quot;string&quot;
        },
        &quot;date&quot;: {
          &quot;title&quot;: &quot;Date&quot;,
          &quot;description&quot;: &quot;Date Receipt Issued&quot;,
          &quot;type&quot;: &quot;string&quot;,
          &quot;format&quot;: &quot;date&quot;
        },
        &quot;vendor&quot;: {
          &quot;title&quot;: &quot;Vendor&quot;,
          &quot;description&quot;: &quot;Details of the entity issuing the receipt&quot;,
          &quot;type&quot;: &quot;object&quot;,
          &quot;required&quot;: [&quot;name&quot;, &quot;website&quot;],
          &quot;properties&quot;: {
            &quot;name&quot;: {
              &quot;title&quot;: &quot;Name&quot;,
              &quot;description&quot;: &quot;Name of the vendor. E.g. Acme Corp&quot;,
              &quot;type&quot;: &quot;string&quot;
            },
            &quot;logo&quot;: {
              &quot;title&quot;: &quot;Logo&quot;,
              &quot;description&quot;: &quot;URL of the issuer&apos;s logo&quot;,
              &quot;type&quot;: &quot;string&quot;,
              &quot;format&quot;: &quot;uri&quot;
            },
            &quot;address&quot;: {
              &quot;title&quot;: &quot;Address&quot;,
              &quot;description&quot;: &quot;List of strings comprising the address of the issuer&quot;,
              &quot;type&quot;: &quot;array&quot;,
              &quot;items&quot;: { &quot;type&quot;: &quot;string&quot; },
              &quot;minItems&quot;: 2,
              &quot;maxItems&quot;: 6
            },
            &quot;website&quot;: {
              &quot;title&quot;: &quot;Website&quot;,
              &quot;description&quot;: &quot;URL of the issuer&apos;s website&quot;,
              &quot;type&quot;: &quot;string&quot;,
              &quot;format&quot;: &quot;uri&quot;
            },
            &quot;contact&quot;: {
              &quot;title&quot;: &quot;Contact Details&quot;,
              &quot;description&quot;: &quot;Details of the person to contact&quot;,
              &quot;type&quot;: &quot;object&quot;,
              &quot;required&quot;: [],
              &quot;properties&quot;: {
                &quot;name&quot;: {
                  &quot;title&quot;: &quot;Name&quot;,
                  &quot;description&quot;: &quot;Name of the contact person&quot;,
                  &quot;type&quot;: &quot;string&quot;
                },
                &quot;position&quot;: {
                  &quot;title&quot;: &quot;Position&quot;,
                  &quot;description&quot;: &quot;Position / Role of the contact person&quot;,
                  &quot;type&quot;: &quot;string&quot;
                },
                &quot;tel&quot;: {
                  &quot;title&quot;: &quot;Telephone Number&quot;,
                  &quot;description&quot;: &quot;Telephone number of the contact person&quot;,
                  &quot;type&quot;: &quot;string&quot;
                },
                &quot;email&quot;: {
                  &quot;title&quot;: &quot;Email&quot;,
                  &quot;description&quot;: &quot;Email of the contact person&quot;,
                  &quot;type&quot;: &quot;string&quot;,
                  &quot;format&quot;: &quot;email&quot;
                },
                &quot;address&quot;: {
                  &quot;title&quot;: &quot;Address&quot;,
                  &quot;description&quot;: &quot;List of strings comprising the address of the contact person&quot;,
                  &quot;type&quot;: &quot;array&quot;,
                  &quot;items&quot;: { &quot;type&quot;: &quot;string&quot; },
                  &quot;minItems&quot;: 2,
                  &quot;maxItems&quot;: 6
                }
              }
            }
          }
        },
        &quot;items&quot;: {
          &quot;title&quot;: &quot;Items&quot;,
          &quot;description&quot;: &quot;Items included into the receipt&quot;,
          &quot;type&quot;: &quot;array&quot;,
          &quot;minItems&quot;: 1,
          &quot;uniqueItems&quot;: true,
          &quot;items&quot;: {
            &quot;$ref&quot;: &quot;item.json#&quot;
          }
        },
        &quot;comments&quot;: {
          &quot;title&quot;: &quot;Comments&quot;,
          &quot;description&quot;: &quot;Any messages/comments the issuer wishes to convey to the customer&quot;,
          &quot;type&quot;: &quot;string&quot;
        }
      }
    },
    &quot;image&quot;: {
      &quot;title&quot;: &quot;Image&quot;,
      &quot;description&quot;: &quot;Viewable/Printable Image of the Digital Receipt&quot;,
      &quot;type&quot;: &quot;string&quot;
    },
    &quot;signature&quot;: {
      &quot;title&quot;: &quot;Signature&quot;,
      &quot;description&quot;: &quot;Digital signature by the vendor of receipts data&quot;,
      &quot;type&quot;: &quot;string&quot;
    },
    &quot;extra&quot;: {
      &quot;title&quot;: &quot;Extra&quot;,
      &quot;description&quot;: &quot;Extra information about the business/receipt as needed&quot;,
      &quot;type&quot;: &quot;string&quot;
    }
  }
}
```

#### Line Items Schema

```json
{
  &quot;type&quot;: &quot;object&quot;,
  &quot;id&quot;: &quot;item.json#&quot;,
  &quot;required&quot;: [&quot;id&quot;, &quot;title&quot;, &quot;date&quot;, &quot;amount&quot;, &quot;tax&quot;, &quot;quantity&quot;],
  &quot;properties&quot;: {
    &quot;id&quot;: {
      &quot;title&quot;: &quot;ID&quot;,
      &quot;description&quot;: &quot;Unique identifier of the goods or service&quot;,
      &quot;type&quot;: &quot;string&quot;
    },
    &quot;title&quot;: {
      &quot;title&quot;: &quot;Title&quot;,
      &quot;description&quot;: &quot;Title of the goods or service&quot;,
      &quot;type&quot;: &quot;string&quot;
    },
    &quot;description&quot;: {
      &quot;title&quot;: &quot;Description&quot;,
      &quot;description&quot;: &quot;Description of the goods or service&quot;,
      &quot;type&quot;: &quot;string&quot;
    },
    &quot;link&quot;: {
      &quot;title&quot;: &quot;Link&quot;,
      &quot;description&quot;: &quot;URL link to the web page for the product or sevice&quot;,
      &quot;type&quot;: &quot;string&quot;,
      &quot;format&quot;: &quot;uri&quot;
    },
    &quot;contract&quot;: {
      &quot;title&quot;: &quot;Contract&quot;,
      &quot;description&quot;: &quot;URL link or hash to an external contract for this product or service&quot;,
      &quot;type&quot;: &quot;string&quot;
    },
    &quot;serial_number&quot;: {
      &quot;title&quot;: &quot;Serial Number&quot;,
      &quot;description&quot;: &quot;Serial number of the item&quot;,
      &quot;type&quot;: &quot;string&quot;
    },
    &quot;date&quot;: {
      &quot;title&quot;: &quot;Supply Date&quot;,
      &quot;description&quot;: &quot;The date the goods or service were provided&quot;,
      &quot;type&quot;: &quot;string&quot;,
      &quot;format&quot;: &quot;date&quot;
    },
    &quot;amount&quot;: {
      &quot;title&quot;: &quot;Unit Price&quot;,
      &quot;description&quot;: &quot;Unit Price per item (excluding tax)&quot;,
      &quot;type&quot;: &quot;number&quot;
    },
    &quot;tax&quot;: {
      &quot;title&quot;: &quot;Tax&quot;,
      &quot;description&quot;: &quot;Amount of tax charged for unit&quot;,
      &quot;type&quot;: &quot;array&quot;,
      &quot;items&quot;: {
        &quot;type&quot;: &quot;object&quot;,
        &quot;required&quot;: [&quot;name&quot;, &quot;rate&quot;, &quot;amount&quot;],
        &quot;properties&quot;: {
          &quot;name&quot;: {
            &quot;title&quot;: &quot;Name of Tax&quot;,
            &quot;description&quot;: &quot;GST/PST etc&quot;,
            &quot;type&quot;: &quot;string&quot;
          },
          &quot;rate&quot;: {
            &quot;title&quot;: &quot;Tax Rate&quot;,
            &quot;description&quot;: &quot;Tax rate as a percentage&quot;,
            &quot;type&quot;: &quot;number&quot;
          },
          &quot;amount&quot;: {
            &quot;title&quot;: &quot;Tax Amount&quot;,
            &quot;description&quot;: &quot;Total amount of tax charged&quot;,
            &quot;type&quot;: &quot;number&quot;
          }
        }
      }
    },
    &quot;quantity&quot;: {
      &quot;title&quot;: &quot;Quantity&quot;,
      &quot;description&quot;: &quot;Number of units&quot;,
      &quot;type&quot;: &quot;integer&quot;
    }
  }
}
```

## Rationale

The schema introduced complies with ERC-721&apos;s metadata extension, conveniently allowing previous tools for viewing NFTs to show our receipts. The new property &quot;receipt&quot; contains our newly provided receipt structure and the signature property optionally allows the vendor to digitally sign the receipt structure.

## Backwards Compatibility

This standard is an extension of ERC-721. It is compatible with both optional extensions, Metadata and Enumerable, mentioned in ERC-721.

## Security Considerations

The data stored in the digital receipt includes various types of personally identifying information (PII), such as the vendor&apos;s name, contact details, and the items purchased. PII is sensitive information that can be used to identify, locate, or contact an individual. Protecting the privacy of the customer is of utmost importance, as unauthorized access to PII can lead to identity theft, fraud, or other malicious activities.

To ensure the privacy of the customer, it is crucial to encrypt the PII contained within the digital receipt. By encrypting the PII, only authorized parties with the appropriate decryption keys can access and read the information stored in the digital receipt. This ensures that the customer&apos;s privacy is maintained, and their data is protected from potential misuse.

While encrypting PII is essential, it is important to note that defining a specific encryption standard is beyond the scope of this ERC. 

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Thu, 01 Sep 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5570</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5570</guid>
      </item>
    
      <item>
        <title>Sign-In with Ethereum Capabilities, ReCaps</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5573-siwe-recap/10627</comments>
        
        <description>## Abstract

[ERC-4361](/EIPs/EIPS/eip-4361), or Sign-In with Ethereum (SIWE), describes how Ethereum accounts authenticate with off-chain services. This proposal, known as ReCaps, describes a mechanism on top of SIWE to give informed consent to authorize a Relying Party to exercise certain scoped capabilities. How a Relying Party authenticates against the target resource is out of scope for this specification and depends on the implementation of the target resource.

## Motivation

SIWE ReCaps unlock integration of protocols and/or APIs for developers by reducing user friction, onchain state and increasing security by introducing informed consent and deterministic capability objects on top of Sign-In With Ethereum (ERC-4361).

While SIWE focuses on authenticating the Ethereum account against the service (relying party or SIWE client) initiating the SIWE flow, there is no canonical way for the authenticated Ethereum account to authorize a relying party to interact with a third-party service (resource service) on behalf of the Ethereum account. A relying party may want to interact with another service on behalf of the Ethereum account, for example a service that provides data storage for the Ethereum account. This specification introduces a mechanism that allows the service (or more generally a Relying Party) to combine authentication and authorization of such while preserving security and optimizing UX.

Note, this approach is a similar mechanism to combining OpenID Connect (SIWE auth) and OAuth2 (SIWE ReCap) where SIWE ReCap implements capabilities-based authorization on top of the authentication provided by SIWE.

## Specification

This specification has three different audiences:

- Web3 application developers that want to integrate ReCaps to authenticate with any protocols and APIs that support object capabilities.
- Protocol or API developers that want to learn how to define their own ReCaps.
- Wallet implementers that want to improve the UI for ReCaps.

### Terms and Definitions

- ReCap - A SIWE Message complying with this specification, i.e. containing at least one ReCap URI in the `Resources` section and the corresponding human-readable ReCap Statement appended to the SIWE `statement`.
- ReCap URI - A type of URI that resolves to a ReCap Details Object.
- ReCap Details Object - A JSON object describing the actions and optionally the resources associated with a ReCap Capability.
- Resource Service (RS) - The entity that is providing third-party services for the Ethereum account.
- SIWE Client (SC) - The entity initiating the authorization (SIWE authentication and ReCap flow).
- Relying Party (RP) - same as SC in the context of authorization.

### Overview

This specification defines the following:

- ReCap SIWE Extension
- ReCap Capability
  - ReCap URI Scheme
  - ReCap Details Object Schema
- ReCap Translation Algorithm
- ReCap Verification

### ReCap SIWE Extension

A ReCap is an ERC-4361 message following a specific format that allows an Ethereum account to delegate a set of ReCap Capabilities to a Relying Party through informed consent. ReCap Capabilities MUST be represented by the final entry in the `Resources` array of the SIWE message that MUST deterministically translate the ReCap Capability in human-readable form to the `statement` field in the SIWE message using the ReCap Translation Algorithm.

The following SIWE message fields are used to further define (or limit) the scope of all ReCap Capabilities:

- The `URI` field MUST specify the intended Relying Party, e.g., `https://example.com`, `did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK`. It is expected that the RS authenticates the Relying Party before invoking an action for the ReCap Capability.
- The `Issued At` field MUST be used to specify the issuance date of the ReCap Capabilities.
- If present, the `Expiration Time` field MUST be used as the expiration time of the ReCap Capabilities, i.e. the time at which the RS will no longer accept an invocation of the capabilities expressed in this form.
- If present, the `Not Before` field MUST be used as the time that has to expire before the RS starts accepting invocations of the capabilities expressed in the message.

The following is a non-normative example of a SIWE message with the SIWE ReCap Extension:

```text
example.com wants you to sign in with your Ethereum account:
0x0000000000000000000000000000000000000000

I further authorize the stated URI to perform the following actions on my behalf: (1) &apos;example&apos;: &apos;append&apos;, &apos;read&apos; for &apos;https://example.com&apos;. (2) &apos;other&apos;: &apos;action&apos; for &apos;https://example.com&apos;. (3) &apos;example&apos;: &apos;append&apos;, &apos;delete&apos; for &apos;my:resource:uri.1&apos;. (4) &apos;example&apos;: &apos;append&apos; for &apos;my:resource:uri.2&apos;. (5) &apos;example&apos;: &apos;append&apos; for &apos;my:resource:uri.3&apos;.

URI: did:key:example
Version: 1
Chain ID: 1
Nonce: mynonce1
Issued At: 2022-06-21T12:00:00.000Z
Resources:
- urn:recap:eyJhdHQiOnsiaHR0cHM6Ly9leGFtcGxlLmNvbSI6eyJleGFtcGxlL2FwcGVuZCI6W10sImV4YW1wbGUvcmVhZCI6W10sIm90aGVyL2FjdGlvbiI6W119LCJteTpyZXNvdXJjZTp1cmkuMSI6eyJleGFtcGxlL2FwcGVuZCI6W10sImV4YW1wbGUvZGVsZXRlIjpbXX0sIm15OnJlc291cmNlOnVyaS4yIjp7ImV4YW1wbGUvYXBwZW5kIjpbXX0sIm15OnJlc291cmNlOnVyaS4zIjp7ImV4YW1wbGUvYXBwZW5kIjpbXX19LCJwcmYiOltdfQ
```

#### ReCap Capability

A ReCap Capability is identified by their ReCap URI that resolves to a ReCap Details Object which defines the associated actions and optional target resources. The scope of each ReCap Capability is attenuated by common fields in the SIWE message as described in the previous chapter, e.g., `URI`, `Issued At`, `Expiration Time`, `Not Before`.

##### ReCap URI Scheme

A ReCap URI starts with `urn:recap:` followed by the unpadded base64url-encoded payload of the ReCap Details Object. Note, the term base64url is defined in RFC4648 - Base 64 Encoding with URL and Filename Safe Alphabet. If present, a Recap URI MUST occupy the final entry of the SIWE resource list.

The following is a non-normative example of a ReCap Capability:

```text
urn:recap:eyJhdHQiOnsiaHR0cHM6Ly9leGFtcGxlLmNvbS9waWN0dXJlcy8iOnsiY3J1ZC9kZWxldGUiOlt7fV0sImNydWQvdXBkYXRlIjpbe31dLCJvdGhlci9hY3Rpb24iOlt7fV19LCJtYWlsdG86dXNlcm5hbWVAZXhhbXBsZS5jb20iOnsibXNnL3JlY2VpdmUiOlt7Im1heF9jb3VudCI6NSwidGVtcGxhdGVzIjpbIm5ld3NsZXR0ZXIiLCJtYXJrZXRpbmciXX1dLCJtc2cvc2VuZCI6W3sidG8iOiJzb21lb25lQGVtYWlsLmNvbSJ9LHsidG8iOiJqb2VAZW1haWwuY29tIn1dfX0sInByZiI6WyJ6ZGo3V2o2Rk5TNHJVVWJzaUp2amp4Y3NOcVpkRENTaVlSOHNLUVhmb1BmcFNadUF3Il19
```

##### Ability Strings

Ability Strings identify an action or Ability within a Namespace. They are serialized as `&lt;namespace&gt;/&lt;ability&gt;`. Namespaces and Abilities MUST contain only alphanumeric characters as well as the characters `.`, `*`, `_`, `+`, `-`, conforming to the regex `^[a-zA-Z0-9.*_+-]$`. The ability string as a whole MUST conform to `^[a-zA-Z0-9.*_+-]+\/[a-zA-z0-9.*_+-]+$`. For example, `crud/update` has an ability-namespace of `crud` and an ability-name of `update`.

##### ReCap Details Object Schema

The ReCap Details Object denotes which actions on which resources the Relying Party is authorized to invoke on behalf of the Ethereum account for the validity period defined in the SIWE message. It can also contain additional information that the RS may require to verify a capability invocation. A ReCap Details Object MUST follow the following JSON Schema:

```jsonc
{
  &quot;$schema&quot;: &quot;http://json-schema.org/draft-04/schema#&quot;,
  &quot;type&quot;: &quot;object&quot;,
  &quot;properties&quot;: {
    &quot;att&quot;: {
      &quot;type&quot;: &quot;object&quot;,
      &quot;propertyNames&quot;: {
        &quot;format&quot;: &quot;uri&quot;
      },
      &quot;patternProperties&quot;: {
        &quot;^.+:.*$&quot;: {
          &quot;type&quot;: &quot;object&quot;,
          &quot;patternProperties&quot;: {
            &quot;^[a-zA-Z0-9.*_+-]+\/[a-zA-z0-9.*_+-]+$&quot;: {
              &quot;type&quot;: &quot;array&quot;,
              &quot;items&quot;: {
                &quot;type&quot;: &quot;object&quot;
              }
            }
          },
          &quot;additionalProperties&quot;: false,
          &quot;minProperties&quot;: 1
        }
      },
      &quot;additionalProperties&quot;: false,
      &quot;minProperties&quot;: 1
    },
    &quot;prf&quot;: {
      &quot;type&quot;: &quot;array&quot;,
      &quot;items&quot;: {
        &quot;type&quot;: &quot;string&quot;,
        &quot;format&quot;: &quot;CID&quot;
      },
      &quot;minItems&quot;: 1
    }
  }
}
```

A ReCap Details Object defines the following properties:

- `att`: (CONDITIONAL) If present, `att` MUST be a JSON object where each key is a URI and each value is an object containing Ability Strings as keys and a corresponding value which is an array of qualifications to the action (i.e. a restriction or requirement). The keys of the object MUST be ordered lexicographically.
- `prf`: (CONDITIONAL) If present, `prf` MUST be a JSON array of string values with at least one entry where each value is a valid Base58-encoded CID which identifies a parent capability, authorizing the Ethereum account for one or more of the entries in `att` if the SIWE `address` does not identify the controller of the `att` entries.

Objects in the `att` field (including nested objects) MUST NOT contain duplicate keys and MUST have their keys ordered lexicographically with two steps:

1. Sort by byte value.
2. If a string starts with another, the shorter string comes first (e.g. `msg/send` comes before `msg/send-to`)

This is the same as the `Array.sort()` method in JavaScript. In the example below, `crud/delete` must appear before `crud/update` and `other/action`, similarly `msg/receive` must appear before `msg/send`.

The following is a non-normative example of a ReCap Capability Object with `att` and `prf`:

```jsonc
{
   &quot;att&quot;:{
      &quot;https://example.com/pictures/&quot;:{
         &quot;crud/delete&quot;: [{}],
         &quot;crud/update&quot;: [{}],
         &quot;other/action&quot;: [{}]
      },
      &quot;mailto:username@example.com&quot;:{
          &quot;msg/receive&quot;: [{
              &quot;max_count&quot;: 5,
              &quot;templates&quot;: [&quot;newsletter&quot;, &quot;marketing&quot;]
          }],
          &quot;msg/send&quot;: [{ &quot;to&quot;: &quot;someone@email.com&quot; }, { &quot;to&quot;: &quot;joe@email.com&quot; }]
      }
   },
   &quot;prf&quot;:[&quot;bafybeigk7ly3pog6uupxku3b6bubirr434ib6tfaymvox6gotaaaaaaaaa&quot;]
}
```

In the example above, the Relying Party is authorized to perform the actions `crud/update`, `crud/delete` and `other/action` on resource `https://example.com/pictures/` without limitations for any. Additionally the Relying Party is authorized to perform actions `msg/send` and `msg/recieve` on resource `mailto:username@example.com`, where `msg/send` is limited to sending to `someone@email.com` or `joe@email.com` and `msg/recieve` is limited to a maximum of 5 and templates `newsletter` or `marketing`. Note, the Relying Party can invoke each action individually and independently from each other in the RS. Additionally the ReCap Capability Object contains some additional information that the RS will need during verification. The responsibility for defining the structure and semantics of this data lies with the RS. These action and restriction semantics are examples not intended to be universally understood. The Nota Bene objects appearing in the array associated with ability strings represent restrictions on use of an ability. An empty object implies that the action can be performed with no restrictions, but an empty array with no objects implies that there is no way to use this ability in a valid way.

It is expected that RS implementers define which resources they want to expose through ReCap Details Objects and which actions they want to allow users to invoke on them.

This example is expected to transform into the following `recap-transformed-statement` (for `URI` of `https://example.com`):

```text
I further authorize the stated URI to perform the following actions on my behalf: (1) &apos;crud&apos;: &apos;delete&apos;, &apos;update&apos; for &apos;https://example.com/pictures/&apos;. (2) &apos;other&apos;: &apos;action&apos; for &apos;https://example.com/pictures/&apos;. (3) &apos;msg&apos;: &apos;receive&apos;, &apos;send&apos; for &apos;mailto:username@example.com&apos;.
```

This example is also expected to transform into the following `recap-uri`:

```text
urn:recap:eyJhdHQiOnsiaHR0cHM6Ly9leGFtcGxlLmNvbS9waWN0dXJlcy8iOnsiY3J1ZC9kZWxldGUiOlt7fV0sImNydWQvdXBkYXRlIjpbe31dLCJvdGhlci9hY3Rpb24iOlt7fV19LCJtYWlsdG86dXNlcm5hbWVAZXhhbXBsZS5jb20iOnsibXNnL3JlY2VpdmUiOlt7Im1heF9jb3VudCI6NSwidGVtcGxhdGVzIjpbIm5ld3NsZXR0ZXIiLCJtYXJrZXRpbmciXX1dLCJtc2cvc2VuZCI6W3sidG8iOiJzb21lb25lQGVtYWlsLmNvbSJ9LHsidG8iOiJqb2VAZW1haWwuY29tIn1dfX0sInByZiI6WyJ6ZGo3V2o2Rk5TNHJVVWJzaUp2amp4Y3NOcVpkRENTaVlSOHNLUVhmb1BmcFNadUF3Il19
```

##### Merging Capability Objects

Any two Recap objects can be merged together by recursive concatenation of their field elements as long as the ordering rules of the field contents is followed. For example, two recap objects:

```jsonc
{
  &quot;att&quot;: {
    &quot;https://example1.com&quot;: {
      &quot;crud/read&quot;: [{}]
    }
  },
  &quot;prf&quot;: [&quot;bafyexample1&quot;]
}

{
  &quot;att&quot;: {
    &quot;https://example1.com&quot;: {
      &quot;crud/update&quot;: [{
        &quot;max_times&quot;: 1
      }]
    },
    &quot;https://example2.com&quot;: {
      &quot;crud/delete&quot;: [{}]
    }
  },
  &quot;prf&quot;: [&quot;bafyexample2&quot;]
}
```

combine into:

```jsonc
{
  &quot;att&quot;: {
    &quot;https://example1.com&quot;: {
      &quot;crud/read&quot;: [{}],
      &quot;crud/update&quot;: [{
        &quot;max_times&quot;: 1
      }]
    },
    &quot;https://example2.com&quot;: {
      &quot;crud/delete&quot;: [{}]
    }
  },
  &quot;prf&quot;: [&quot;bafyexample1&quot;, &quot;bafyexample2&quot;]
}
```

#### ReCap Translation Algorithm

After applying the ReCap Translation Algorithm on a given SIWE message that MAY include a pre-defined `statement`, the `recap-transformed-statement` in a ReCap SIWE message MUST conform to the following ABNF:

```text
recap-transformed-statement = statement recap-preamble 1*(&quot; &quot; recap-statement-entry &quot;.&quot;)
   ; see ERC-4361 for definition of input-statement
recap-preamble = &quot;I further authorize the stated URI to perform the following actions on my behalf:&quot;
recap-statement-entry = &quot;(&quot; number &quot;) &quot; action-namespace &quot;: &quot; 
                          action-name *(&quot;,&quot; action-name) &quot;for&quot;
                          recap-resource
   ; see RFC8259 for definition of number
ability-namespace = string
   ; see RFC8259 for definition of string
ability-name = string
   ; see RFC8259 for definition of string
recap-resource = string
   ; see RFC8259 for definition of string
```

The following algorithm or an algorithm that produces the same output MUST be performed to generate the SIWE ReCap Transformed Statement.

Inputs:

- Let `recap-uri` be a ReCap URI, which represents the ReCap Capabilities that are to be encoded in the SIWE message, and which contains a ReCap Details Object which conforms to the ReCap Details Object Schema.
- [Optional] Let `statement` be the statement field of the input SIWE message conforming to ERC-4361.
Algorithm:
- Let `recap-transformed-statement` be an empty string value.
- If `statement` is present, do the following:
  - Append the value of the `statement` field of `siwe` to `recap-transformed-statement`.
  - Append a single space character `&quot; &quot;` to `recap-transformed-statement`.
- Append the following string to `recap-transformed-statement`: `&quot;I further authorize the stated URI to perform the following actions on my behalf:&quot;`.
- Let `numbering` be an integer starting with 1.
- Let `attenuations` be the `att` field of the ReCap Details Object
- For each key and value pair in `attenuations` (starting with the first entry), perform the following:
  - Let `resource` be the key and `abilities` be the value
  - Group the keys of the `abilities` object by their `ability-namespace`
  - For each `ability-namespace`, perform the following:
    - Append the string concatenation of `&quot; (&quot;`, `numbering`, `&quot;)&quot;` to `recap-transformed-statement`.
    - Append the string concatenation of `&apos;`, `ability-namespace`, `&apos;:` to `recap-transformed-statement`.
    - For each `ability-name` in the `ability-namespace` group, perform the following:
      - Append the string concatenation of `&apos;`, `ability-name`, `&apos;` to `recap-transformed-statement`
      - If not the final `ability-name`, append `,` to `recap-transformed-statement`
    - Append `for &apos;`, `resource`, `&apos;.` to `recap-transformed-statement`
    - Increase `numbering` by 1
- Return `recap-transformed-statement`.

#### ReCap Verification Algorithm

The following algorithm or an algorithm that produces the same output MUST be performed to verify a SIWE ReCap.

Inputs:

- Let `recap-siwe` be the input SIWE message conforming to ERC-4361 and this EIP.
- Let `siwe-signature` be the output of signing `recap-siwe`, as defined in ERC-4361.
Algorithm:
- Perform ERC-4361 signature verification with `recap-siwe` and `siwe-signature` as inputs.
- Let `uri` be the uri field of `recap-siwe`.
- Let `recap-uri` be a recap URI taken from the last entry of the resources field of `recap-siwe`.
- Let `recap-transformed-statement` be the result of performing the above `ReCap Translation Algorithm` with `uri` and `recap-uri` as input.
- Assert that the statement field of `recap-siwe` ends with `recap-transformed-statement`.

### Implementer&apos;s Guide

TBD

#### Web3 Application Implementers

TBD

#### Wallet Implementers

TBD

#### Protocol or API Implementers

TBD

## Rationale

TBD

## Security Considerations

Resource service implementer&apos;s should not consider ReCaps as bearer tokens but instead require to authenticate the Relying Party in addition. The process of authenticating the Relying Party against the resource service is out of scope of this specification and can be done in various different ways.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 20 Jul 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5573</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5573</guid>
      </item>
    
      <item>
        <title>ERC-721 NFT Authorization</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/nft-authorization-erc721-extension/10661</comments>
        
        <description>## Abstract

This EIP separates the [ERC-721](/EIPs/EIPS/eip-721) NFT&apos;s commercial usage rights from its ownership to allow for the independent management of those rights.

## Motivation

Most NFTs have a simplified ownership verification mechanism, with a sole owner of an NFT. Under this model, other rights, such as display, or creating derivative works or distribution, are not possible to grant, limiting the value and commercialization of NFTs. Therefore, the separation of an NFT&apos;s ownership and user rights can enhance its commercial value.

Commercial right is a broad concept based on the copyright, including the rights of copy, display, distribution, renting, commercial use, modify, reproduce and sublicense etc.  With the development of the Metaverse, NFTs are becoming more diverse, with new use cases such as digital collections, virtual real estate, music, art, social media, and digital asset of all kinds. The copyright and authorization based on NFTs are becoming a potential business form.

## Specification

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.

### Contract Interface

```solidity
interface IERC5585 {

    struct UserRecord {
        address user;
        string[] rights;
        uint256 expires;
    }

    /// @notice Get all available rights of this NFT project
    /// @return All the rights that can be authorized to the user
    function getRights() external view returns(string[]);

    /// @notice NFT holder authorizes all the rights of the NFT to a user for a specified period of time
    /// @dev The zero address indicates there is no user
    /// @param tokenId The NFT which is authorized
    /// @param user The user to whom the NFT is authorized
    /// @param duration The period of time the authorization lasts
    function authorizeUser(uint256 tokenId, address user, uint duration) external;

    /// @notice NFT holder authorizes specific rights to a user for a specified period of time
    /// @dev The zero address indicates there is no user. It will throw exception when the rights are not defined by this NFT project
    /// @param tokenId The NFT which is authorized
    /// @param user The user to whom the NFT is authorized
    /// @param rights Rights authorized to the user, such as renting, distribution or display etc
    /// @param duration The period of time the authorization lasts
    function authorizeUser(uint256 tokenId, address user, string[] rights, uint duration) external;
    
    /// @notice The user of the NFT transfers his rights to the new user
    /// @dev The zero address indicates there is no user
    /// @param tokenId The rights of this NFT is transferred to the new user
    /// @param newUser The new user
    function transferUserRights(uint256 tokenId, address newUser) external;

    /// @notice NFT holder extends the duration of authorization
    /// @dev The zero address indicates there is no user. It will throw exception when the rights are not defined by this NFT project
    /// @param tokenId The NFT which has been authorized
    /// @param user The user to whom the NFT has been authorized
    /// @param duration The new duration of the authorization
    function extendDuration(uint256 tokenId, address user, uint duration) external;

    /// @notice NFT holder updates the rights of authorization
    /// @dev The zero address indicates there is no user
    /// @param tokenId The NFT which has been authorized
    /// @param user The user to whom the NFT has been authorized
    /// @param rights New rights authorized to the user
    function updateUserRights(uint256 tokenId, address user, string[] rights) external;

    /// @notice Get the authorization expired time of the specified NFT and user
    /// @dev The zero address indicates there is no user
    /// @param tokenId The NFT to get the user expires for
    /// @param user The user who has been authorized
    /// @return The authorization expired time
    function getExpires(uint256 tokenId, address user) external view returns(uint);

    /// @notice Get the rights of the specified NFT and user
    /// @dev The zero address indicates there is no user
    /// @param tokenId The NFT to get the rights
    /// @param user The user who has been authorized
    /// @return The rights has been authorized
    function getUserRights(uint256 tokenId, address user) external view returns(string[]);

    /// @notice The contract owner can update the number of users that can be authorized per NFT
    /// @param userLimit The number of users set by operators only
    function updateUserLimit(uint256 userLimit) external onlyOwner;

    /// @notice resetAllowed flag can be updated by contract owner to control whether the authorization can be revoked or not 
    /// @param resetAllowed It is the boolean flag
    function updateResetAllowed(bool resetAllowed) external onlyOwner;

    /// @notice Check if the token is available for authorization
    /// @dev Throws if tokenId is not a valid NFT
    /// @param tokenId The NFT to be checked the availability
    /// @return true or false whether the NFT is available for authorization or not
    function checkAuthorizationAvailability(uint256 tokenId) public view returns(bool);

    /// @notice Clear authorization of a specified user
    /// @dev The zero address indicates there is no user. The function  works when resetAllowed is true and it will throw exception when false  
    /// @param tokenId The NFT on which the authorization based
    /// @param user The user whose authorization will be cleared
    function resetUser(uint256 tokenId, address user) external;


    /// @notice Emitted when the user of a NFT is changed or the authorization expires time is updated
    /// param tokenId The NFT on which the authorization based
    /// param indexed user The user to whom the NFT authorized
    /// @param rights Rights authorized to the user
    /// @param expires The expires time of the authorization
    event authorizeUser(uint256 indexed tokenId, address indexed user, string[] rights, uint expires);

    /// @notice Emitted when the number of users that can be authorized per NFT is updated
    /// @param userLimit The number of users set by operators only
    event updateUserLimit(uint256 userLimit);
}
```

The `getRights()` function MAY be implemented as pure and view.

The `authorizeUser(uint256 tokenId, address user, uint duration)` function MAY be implemented as `public` or `external`.

The `authorizeUser(uint256 tokenId, address user, string[] rights; uint duration)` function MAY be implemented as `public` or `external`.

The `transferUserRights(uint256 tokenId, address newUser)` function MAY be implemented as `public` or `external`.

The `extendDuration(uint256 tokenId, address user, uint duration)` function MAY be implemented as `public` or `external`.

The `updateUserRights(uint256 tokenId, address user, string[] rights)` function MAY be implemented as `public` or `external`.

The `getExpires(uint256 tokenId, address user)` function MAY be implemented as `pure` or `view`.

The `getUserRights(uint256 tokenId, address user)` function MAY be implemented as pure and view.

The `updateUserLimit(unit256 userLimit)` function MAY be implemented as `public` or `external`.

The `updateResetAllowed(bool resetAllowed)` function MAY be implemented as `public` or `external`.

The `checkAuthorizationAvailability(uint256 tokenId)` function MAY be implemented as `pure` or `view`.

The `resetUser(uint256 tokenId, address user)` function MAY be implemented as `public` or `external`.

The `authorizeUser` event MUST be emitted when the user of a NFT is changed or the authorization expires time is updated.

The `updateUserLimit` event MUST be emitted when the number of users that can be authorized per NFT is updated.

## Rationale

First of all, NFT contract owner can set the maximum number of authorized users to each NFT and whether the NFT owner can cancel the authorization at any time to protect the interests of the parties involved.

Secondly, there is a `resetAllowed` flag to control the rights between the NFT owner and the users for the contract owner. If the flag is set to true, then the NFT owner can disable usage rights of all authorized users at any time.

Thirdly, the rights within the user record struct is used to store what rights has been authorized to a user by the NFT owner, in other words, the NFT owner can authorize a user with specific rights and update it when necessary.

Finally, this design can be seamlessly integrated with third parties. It is an extension of ERC-721, therefore it can be easily integrated into a new NFT project. Other projects can directly interact with these interfaces and functions to implement their own types of transactions. For example, an announcement platform could use this EIP to allow all NFT owners to make authorization or deauthorization at any time.

## Backwards Compatibility

This standard is compatible with [ERC-721](/EIPs/EIPS/eip-721) since it is an extension of it.

## Security Considerations

When the `resetAllowed` flag is false, which means the authorization can not be revoked by NFT owner during the period of authorization, users of the EIP need to make sure the authorization fee can be fairly assigned if the NFT was sold to a new holder.

Here is a solution for taking reference: the authorization fee paid by the users can be held in an escrow contract for a period of time depending on the duration of the authorization. For example, if the authorization duration is 12 months and the fee in total is 10 ETH, then if the NFT is transferred after 3 months, then only 2.5 ETH would be sent and the remaining 7.5 ETH would be refunded.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 15 Aug 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5585</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5585</guid>
      </item>
    
      <item>
        <title>Restrict Ethereum Provider API Injection</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/rfc-limiting-provider-object-injection-to-secure-contexts/10670</comments>
        
        <description>## Abstract

Historically the web platform has had a notion of “powerful” APIs like those defined in W3C&apos;s Geolocation specification and W3C&apos;s Mediastreams specification, which are subject to additional security restrictions such as those defined by W3C&apos;s secure contexts specification. Since the Ethereum Provider APIs allow dApp websites to request access to sensitive user data and to request use of user funds, new Ethereum Provider APIs generally should align to the security considerations defined by W3C&apos;s Secure Context specification in order to better protect the users data and users funds managed via the web.

### Author&apos;s Note

Unfortunately, because of a difference in interpretations by EIP editors of RFC 2119 terminology around linking in [EIP-1](/EIPs/EIPS/eip-1), the authors cannot directly link to other W3C specifications which this EIP builds upon. The author&apos;s attempted to provide as much context as possible within the text while complying with the editor bot in order to get this merged. If this policy is updated or further clarified before this EIP reaches final call in the future this EIP will be updated with links.

## Motivation

Wallets are oftentimes maintaining security and safety of users&apos; funds that can be equivalent to large portions of money. For this reason, it&apos;s a good idea to restrict access to the Ethereum Provider APIs to align it with other powerful APIs on the web platform. This will assist in reducing the surface area that attacks can be conducted to access users funds or data. Additionally, by adding in restrictions we&apos;re reducing the surface area that malicious web pages could fingerprint the user via the Ethereum Provider APIs providing some additional privacy benefits. An example of a specific attack that&apos;s avoided by this is one where a malicious advertisement is loaded on a legitimate dApp that attempts to interact with a users wallet to maliciously request the user to access funds. With this EIP implemented the advertisement frame would be considered a third-party iframe and therefore would not have the Ethereum Provider API injected into it&apos;s sub frame because it&apos;s not a secure context.

## Specification

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.

### Restrictions for providers

The provider objects, e.g. `window.ethereum`, are expected to only inject the Ethereum Provider APIs in secure context when conforming with this specification. The following restrictions are REQUIRED for conformant wallets:

- Provider objects MAY be accessible in private (incognito) windows.
- The origin MUST be a &quot;potentially trustworthy origin&quot; (defined in W3C&apos;s Secure Contexts specification in section 3.1) to have access to `window.ethereum`. This can be checked using `window.isSecureContext`, including inside iframes.
    - Secure contexts include sites that are served from HTTPS but also HTTP `localhost`.
    - The User Agent implementation MAY also support configured [potentially trustworthy origins] that would normally not be considered trustworthy if the user configures their User Agent to do so. See section 7.2 titled &quot;Development Environments&quot; of W3C&apos;s Secure Contexts specification for additional details. For example, in Chromium based User Agents this is done via the `chrome://flags/#unsafely-treat-insecure-origin-as-secure` flag.
- By default the Ethereum Provider APIs MUST NOT be exposed to third-party iframes.
- `window.ethereum` MUST be `undefined` in an iframe where `window.isSecureContext` returns `false` in that iframe.
- If the iframe is a third party to the top-level secure origin, it SHOULD be blocked. Some implementations MAY provide a mechanism (e.g., via the `allow` attribute and Permissions API) for pages to request access, subject to user approval.
- If the iframe is first-party to the top-level origin AND the `sandbox` attribute is set on the iframe, the provider object MUST be blocked. If the `sandbox` attribute is set to `sandbox=&quot;allow-same-origin&quot;` it MUST be injected for a first party frame.
    - Note `&quot;allow-same-origin&quot;` does nothing if the iframe is third-party. Third-party iframes SHOULD be blocked by default, but implementations MAY allow access through user-approved mechanisms such as the Permissions API.

## Rationale

By limiting the capabilities of where the Ethereum Provider APIs are being injected we can reduce the surface area of where attacks can be executed. Given the sensitivity of data that&apos;s passed to the Ethereum Provider APIs some basic levels of authentication and confidentiality should be met in order to ensure that request data is not being intercepted or tampered with. While there have been attempts to [limit request access via the wallet](/EIPs/EIPS/eip-2255) interface itself, there have not been limitations that have been set to where these Ethereum Provider APIs are expected to be or not be injected. Since the secure contexts web platform API is a well developed boundary that&apos;s been recommended by W3C and the fact that the Ethereum Provider APIs are extending the traditional web platform APIs, no other alternative solutions have been considered in order to extend current established prior art.


## Backwards Compatibility

Wallet extensions SHOULD consider adding a &quot;developer mode&quot; toggle via a UX so that dApp developers have the capability to disable the insecure context (http) check for the `http://localhost:&lt;any-port&gt;` origin only in the event that localhost does not return `true` for secure context. See section 5.2 of W3C&apos;s Secure Context specification for more details. This will allow dApp developers to be able to continue to host dApps on the localhost origin if a User Agent has chosen to not already consider localhost a secure context. All major User Agent implementations tested do consider localhost a secure context already. This toggle MUST be set to disabled by default.

## Test Cases

### Required Test Cases

- Top level `http://a.com` -&gt; blocked (insecure/top level)
- Top level `https://a.com` -&gt; allowed
- Top level `https://a.com` with `&lt;iframe src=&quot;http://a.com/&quot;&gt;` -&gt; blocked (insecure first party iframe)
- Top level `http://a.com` with `&lt;iframe src=&quot;https://a.com/&quot;&gt;` -&gt; blocked (insecure top level window)
- Top level `https://a.com` with `&lt;iframe src=&quot;https://a.com&quot;&gt;` -&gt; allowed
- Top level `https://a.com` with `&lt;iframe src=&quot;https://b.com&quot;&gt;` -&gt; blocked (third-party iframe without sufficient privileges)
- Top level `https://b.com` with `&lt;iframe src=&quot;http://a.com/&quot;&gt;` with `&lt;iframe src=&quot;https://b.com&quot;&gt;` -&gt; blocked (insecure iframe)
- Top level `https://b.com` with `&lt;iframe src=&quot;https://a.com&quot;&gt;` with `&lt;iframe src=&quot;https://b.com&quot;&gt;` -&gt; blocked (third-party iframe without sufficient privileges)
- Top level `https://a.com` with `&lt;iframe src=&quot;https://sub.a.com&quot;&gt;` -&gt; blocked (third-party iframe without sufficient privileges)
- Top level `https://a.com` with `&lt;iframe src=&quot;https://a.com&quot; sandbox&gt;` -&gt; blocked (sandbox attribute without &quot;allow-same-origin&quot;)
- Top level `https://a.com` with `&lt;iframe src=&quot;https://a.com&quot; sandbox=&quot;allow-same-origin allow-scripts&quot;&gt;` -&gt; allowed (Note this case is discouraged by User Agent implementer&apos;s such as Mozilla&apos;s MDN documents because it’d allow the iframe to remove its own `sandbox` attribute. See the `sandbox` attribute section of the iframes document in MDN for more details.)
- Top level `data://foo with &lt;iframe src=&quot;data://bar&quot;&gt;` -&gt; blocked (insecure top level scheme)
- Top level `file://foo with &lt;iframe src=&quot;file://bar&quot;&gt;` -&gt; blocked (third-party iframe)
- Top level `https://a.com` with `&lt;iframe src=&quot;https://b.com&quot; sandbox=&quot;allow-same-origin allow-scripts&quot;&gt;` -&gt; blocked (third-party iframe without sufficient privileges)


## Security Considerations

### User Enables Developer Mode

Oftentimes developers require the ability to develop dApps locally in order to test their website and develop while hosting their dApp on `http://localhost`. In this case localhost would be blocked and compatibility issues would arise when developing a dApp locally. In order to increase compatibility for dApp developers a toggle to disable the check for the localhost can be considered. If this were to be extended beyond the localhost origin it could be used as a means to convince users to enable developer mode in order to subvert the guards put in place by this EIP. Therefore, implementations should be cautious when extending this developer toggle beyond the scope of the localhost origin.

### Privacy Considerations

#### Web3 Provider Fingerprinting

Due to the nature of how the provider object is injected by default into most webpages, there&apos;s a risk that a malicious web page could utilize the provider object to fingerprint the user more precisely as a Web3 user. Implementers of this EIP are expected to consider the risks of injecting the Ethereum provider APIs into pages by default in order to consider what privacy characteristics they wish to enable for their users.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 05 Sep 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5593</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5593</guid>
      </item>
    
      <item>
        <title>NFT Lien</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/creating-a-new-erc-proposal-for-nft-lien/10683</comments>
        
        <description>## Abstract

This ERC introduces NFT liens, a form of security interest over an item of property to secure the recovery of liability or performance of some other obligation. It introduces an interface to place and remove a lien, plus an event.

## Motivation

Liens are widely used in financial use cases, such as car and property liens. An example use case for an NFT lien is for a deed.
This ERC provides an interface to implement an interface that performs the lien holding relationships.

## Specification

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.

1. Any compliant contract MUST implement [ERC-721](/EIPs/EIPS/eip-721) and [ERC-165](/EIPs/EIPS/eip-165).

2. Any compliant contract MUST implement the following interface:

```solidity
interface IERC_LIEN is ERC721, ERC165 {

    /// === Events ===

    /// @notice MUST be emitted when new lien is successfully placed.
    /// @param tokenId the token a lien is placed on.
    /// @param holder the holder of the lien.
    /// @param extraParams of the original request to add the lien.
    event OnLienPlaced(uint256 tokenId, address holder, bytes calldata extraParams);

    /// @notice MUST be emitted when an existing lien is successfully removed.
    /// @param tokenId the token a lien was removed from.
    /// @param holder the holder of the lien.
    /// @param extraParams of the original request to remove the lien.
    event OnLienRemoved(uint256 tokenId, address holder, bytes calldata extraParams);

    /// === CRUD ===

    /// @notice The method to place a lien on a token
    ///         it MUST throw an error if the same holder already has a lien on the same token.
    /// @param tokenId the token a lien is placed on.
    /// @param holder the holder of the lien
    /// @param extraParams extra data for future extension.
    function addLienHolder(uint256 tokenId, address holder, bytes calldata extraParams) public;

    /// @notice The method to remove a lien on a token
    ///         it MUST throw an error if the holder already has a lien.
    /// @param tokenId the token a lien is being removed from.
    /// @param holder the holder of the lien
    /// @param extraParams extra data for future extension.
    function removeLienHolder(uint256 tokenId, address holder, bytes calldata extraParams) public;

    /// @notice The method to query if an active lien exists on a token.
    ///         it MUST throw an error if the tokenId doesn&apos;t exist or is not owned.
    /// @param tokenId the token a lien is being queried for
    /// @param holder the holder about whom the method is querying about lien holding.
    /// @param extraParams extra data for future extension.
    function hasLien(uint256 tokenId, address holder, bytes calldata extraParams) public view returns (bool);
}
```

## Rationale

1. We only support [ERC-721](/EIPs/EIPS/eip-721) NFTs for simplicity and gas efficiency. We have not considered other ERCs, which can be left for future extensions. For example, [ERC-20](/EIPs/EIPS/eip-20) and [ERC-1155](/EIPs/EIPS/eip-1155) were not considered.

2. We choose separate &quot;addLienHolder&quot; and &quot;removeLienHolder&quot; instead of using a single `changeLienholder` with amount because we believe
the add and remove actions are significantly different and usually require different Access Control,
for example, the token holder shall be able to add someone else as a lien holder but the lien holder of that token.

3. We have not specified the &quot;amount of debt&quot; in this interface. We believe this is complex enough and worthy of an individual ERC by itself.

4. We have not specified how endorsement can be applied to allow holders to signal their approval for transfer or swapping. We believe this is complex enough and worthy of an individual ERC by itself.

## Backwards Compatibility

The ERC is designed as an extension of [ERC-721](/EIPs/EIPS/eip-721), and therefore compliant contracts need to fully comply with [ERC-721](/EIPs/EIPS/eip-721).

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 05 Sep 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5604</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5604</guid>
      </item>
    
      <item>
        <title>Multiverse NFTs</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5606-multiverse-nfts-for-digital-asset-interoperability/10698</comments>
        
        <description>## Abstract

This specification defines a minimal interface to create a multiverse NFT standard for digital assets such as wearables and in-game items that, in turn, index the delegate NFTs on each platform where this asset exists. These platforms could be metaverses, play-to-earn games or NFT marketplaces. This proposal depends on and extends [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155). The standard also allows for the ‘bundling’ and ‘unbundling’ of these delegate NFTs within the multiverse NFT so holders can trade them individually or as a bundle.

## Motivation

Several metaverses and blockchain games (&quot;platforms&quot;) exist that use NFT standards such as ERC-721 and ERC-1155 for creating in-universe assets like avatar wearables, in-game items including weapons, shields, potions and much more. The biggest shortcoming while using these standards is that there is no interoperability between these platforms. As a publisher, you must publish the same digital asset (for example, a shirt) on various platforms as separate ERC-721 or ERC-1155 tokens. Moreover, there is no relationship between these, although they represent the same digital asset in reality. Hence, it is very difficult to prove the scarcity of these items on-chain.

Since their inception, NFTs were meant to be interoperable and prove the scarcity of digital assets. Although NFTs can arguably prove the scarcity of items, the interoperability aspect hasn’t been addressed yet. Creating a multiverse NFT standard that allows for indexing and ownership of a digital asset across various platforms would be the first step towards interoperability and true ownership across platforms.

In the web3 ecosystem, NFTs have evolved to represent multiple types of unique and non-fungible assets. One type of asset includes a set of NFTs related to one another. For instance, if a brand releases a new sneaker across various metaverses, it would be minted as a separate NFT on each platform. However, it is, in reality, the same sneaker.
There is a need to represent the relationship and transferability of these types of NFTs as metaverses and blockchain games gain more mainstream adoption. The ecosystem needs a better framework to address this issue rather than relying on the application level. This framework should define the relationship between these assets and the nature of their association. There is more value in the combined recognition, use and transferability of these individual NFTs as a bundle rather than their selves.

## Specification

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.

A multiverse NFT contract represents a digital asset across multiple platforms. This contract can own one or more delegate NFT tokens of the digital asset on the various platforms through bundling or unbundling.

```
/**
* @dev Interface of the Multiverse NFT standard as defined in the EIP.
*/
interface IMultiverseNFT {

   /**
    * @dev struct to store delegate token details
    *
    */
   struct DelegateData {
       address contractAddress;
       uint256 tokenId;
       uint256 quantity;
   }

   /**
    * @dev Emitted when one or more new delegate NFTs are added to a Multiverse NFT
    */
   event Bundled(uint256 multiverseTokenID, DelegateData[] delegateData, address ownerAddress);


   /**
    * @dev Emitted when one or more delegate NFTs are removed from a Multiverse NFT
    */
   event Unbundled(uint256 multiverseTokenID, DelegateData[] delegateData);

   /**
    * @dev Accepts the tokenId of the Multiverse NFT and returns an array of delegate token data
    */
   function delegateTokens(uint256 multiverseTokenID) external view returns (DelegateData[] memory);

   /**
    * @dev Removes one or more delegate NFTs from a Multiverse NFT
    * This function accepts the delegate NFT details and transfers those NFTs out of the Multiverse NFT contract to the owner&apos;s wallet
    */
   function unbundle(DelegateData[] memory delegateData, uint256 multiverseTokenID) external;

   /**
    * @dev Adds one or more delegate NFTs to a Multiverse NFT
    * This function accepts the delegate NFT details and transfers those NFTs to the Multiverse NFT contract
    * Need to ensure that approval is given to this Multiverse NFT contract for the delegate NFTs so that they can be transferred programmatically
    */
   function bundle(DelegateData[] memory delegateData, uint256 multiverseTokenID) external;

   /**
    * @dev Initialises a new bundle, mints a Multiverse NFT and assigns it to msg.sender
    * Returns the token ID of a new Multiverse NFT
    * Note - When a new Multiverse NFT is initialised, it is empty; it does not contain any delegate NFTs
    */
   function initBundle(DelegateData[] memory delegateData) external;
}
```

Any dapp implementing this standard would initialise a bundle by calling the function `initBundle`. This mints a new multiverse NFT and assigns it to msg.sender. While creating a bundle, the delegate token contract addresses and the token IDs are set during the initialisation and cannot be changed after that. This avoids unintended edge cases where non-related NFTs could be bundled together by mistake.

Once a bundle is initialised, the delegate NFT tokens can then be transferred to this Multiverse NFT contract by calling the function `bundle` and passing the token ID of the multiverse NFT. It is essential for a dapp to get the delegate NFTs ‘approved’ from the owner to this Multiverse NFT contract before calling the bundle function. After that, the Multiverse NFT owns one or more versions of this digital asset across the various platforms.

If the owner of the multiverse NFT wants to sell or use the individual delegate NFTs across any of the platforms, they can do so by calling the function `unbundle`. This function transfers the particular delegate NFT token(s) to msg.sender (only if `msg.sender` is the owner of the multiverse NFT).

## Rationale

The `delegateData` struct contains information about the delegate NFT tokens on each platform. It contains variables such as `contractAddress`, `tokenId`, `quantity` to differentiate the NFTs. These NFTs could be following either the ERC-721 standard or the ERC-1155 standard.

The `bundle` and `unbundle` functions accept an array of DelegateData struct because of the need to cater to partial bundling and unbundling. For instance, a user could initialise a bundle with three delegate NFTs, but they should be able to bundle and unbundle less than three at any time. They can never bundle or unbundle more than three. They also need the individual token IDs of the delegate NFTs to bundle and unbundle selectively.

## Backwards Compatibility

This standard is fully compatible with ERC-721 and ERC-1155. Third-party applications that don’t support this EIP will still be able to use the original NFT standards without any problems.

## Reference Implementation

[MultiverseNFT.sol](/EIPs/assets/eip-5606/contracts/MultiverseNFT.sol)

## Security Considerations

The bundle function involves calling an external contract(s). So reentrancy prevention measures should be applied while implementing this function.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 06 Sep 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5606</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5606</guid>
      </item>
    
      <item>
        <title>ERC-1155 Supply Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5615-eip-1155-supply-extension/10732</comments>
        
        <description>## Abstract

This ERC standardizes an existing mechanism to fetch token supply data from [ERC-1155](/EIPs/EIPS/eip-1155) tokens. It adds a `totalSupply` function, which fetches the number of tokens with a given `id`, and an `exists` function, which checks for the existence of a given `id`.

## Specification

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.

```solidity
interface ERC1155Supply is ERC1155 {
  // @notice      This function MUST return whether the given token id exists, previously existed, or may exist
  // @param   id  The token id of which to check the existence
  // @return      Whether the given token id exists, previously existed, or may exist
  function exists(uint256 id) external view returns (bool);

  // @notice      This function MUST return the number of tokens with a given id. If the token id does not exist, it MUST return 0.
  // @param   id  The token id of which fetch the total supply
  // @return      The total supply of the given token id
  function totalSupply(uint256 id) external view returns (uint256);
}
```

Implementations MAY support [ERC-165](/EIPs/EIPS/eip-165) interface discovery, but consumers MUST NOT rely on it.

## Rationale

This ERC does not implement [ERC-165](/EIPs/EIPS/eip-165), as this interface is simple enough that the extra complexity is unnecessary and would cause incompatibilities with pre-existing implementations.

The `totalSupply` and `exists` functions were modeled after [ERC-721](/EIPs/EIPS/eip-721) and [ERC-20](/EIPs/EIPS/eip-20).

`totalSupply` does not revert if the token ID does not exist, since contracts that care about that case should use `exists` instead (which might return false even if `totalSupply` is zero).

`exists` is included to differentiate between the two ways that `totalSupply` could equal zero (either no tokens with the given ID have been minted yet, or no tokens with the given ID will ever be minted).

## Backwards Compatibility

This ERC is designed to be backward compatible with the OpenZeppelin `ERC1155Supply`.

## Security Considerations

None.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 25 May 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5615</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5615</guid>
      </item>
    
      <item>
        <title>NFT Metadata JSON Schema dStorage Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5625-nft-metadata-json-schema-dstorage-extension/10754</comments>
        
        <description>## Abstract

This EIP extends the NFT metadata JSON schema defined in [EIP-721](/EIPs/EIPS/eip-721) and [EIP-1155](/EIPs/EIPS/eip-1155), adding a `dStorage` key that provides information about how the NFT data is stored. 

## Motivation

As highly valuable crypto properties, NFT assets intrinsically demand guaranteed storage to assure their **immutability**, **reliability**, and **durability**. NFT ownership is tracked by [EIP-721](/EIPs/EIPS/eip-721) or [EIP-1155](/EIPs/EIPS/eip-1155) smart contracts, hence persisted in blockchain, which is not a problem. But how about the mime-type assets that NFT tokens represent? Ideally, they should also be stored in some reliable and verifiable decentralized storage system that is designed to store larger amounts of data than the blockchain itself. As an effort to promote **decentralized storage** adoption in NFT world, we propose to add additional **dStorage** information into NFT metadata JSON schema.

As a refresher, let&apos;s review existing NFT metadata JSON schema standards. [EIP-721](/EIPs/EIPS/eip-721) defines a standard contract method `tokenURI` to return a given NFT&apos;s metadata JSON file, conforming to the *[EIP-721](/EIPs/EIPS/eip-721) Metadata JSON Schema*, which defines three properties: `name`, `description` and `image`.

Similarly, [EIP-1155](/EIPs/EIPS/eip-1155) also defines a standard contract method `uri` to return NFT metadata JSON files conforming to the *[EIP-1155](/EIPs/EIPS/eip-1155) Metadata JSON Schema*, which defines properties like `name`, `decimals`, `description`, `image`, `properties`, `localization`, etc.

Besides, as the world&apos;s largest NFT marketplace nowadays, OpenSea defines their own *Metadata Standards*, including a few more properties like `image_data`, `external_url`, `attributes`, `background_color`, `animation_url`, `youtube_url`, etc. This standard is de facto respected and followed by other NFT marketplaces like LooksRare.

None of these standards conveys storage information about the mime-type asset that the NFT token represents. This proposal is an effort to fill the missing part.


## Specification

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.

In addition to the existing properties, the Metadata JSON file returned by [EIP-721](/EIPs/EIPS/eip-721) and [EIP-1155](/EIPs/EIPS/eip-1155) smart contracts (via `tokenURI` and `uri` methods, respectively), should OPTIONALLY contains one more `dStorage` property.

For [EIP-721](/EIPs/EIPS/eip-721) smart contracts, the Metadata JSON file schema is:

```json
{
    &quot;title&quot;: &quot;Asset Metadata&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;name&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Identifies the asset to which this NFT represents&quot;
        },
        &quot;description&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Describes the asset to which this NFT represents&quot;
        },
        &quot;image&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive.&quot;
        },
        &quot;dStorage&quot;: {
            &quot;type&quot;: &quot;object&quot;,
            &quot;required&quot;: [&quot;platform&quot;, &quot;description&quot;, &quot;persistence_mechanism&quot;, &quot;challenge_mechanism&quot;, &quot;consensus&quot;, &quot;dstorage_note&quot;],
            &quot;properties&quot;: {
                &quot;platform&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;dStorage platform name like Swarm, Arweave, Filecoin, Crust, etc&quot;
                },
                &quot;description&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;A brief description of the dStorage platform&quot;
                },
                &quot;persistence_mechanism&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;Persistence mechanism or incentive structure of the dStorage platform, like &apos;blockchain-based&apos;, &apos;contract-based&apos;, etc&quot;
                },
                &quot;challenge_mechanism&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;Challenge mechanism of the dStorage platform, like Arweave&apos;s proof-of-access, etc&quot;
                },
                &quot;consensus&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;Consensus mechanism of the dStorage platform, like PoW, PoS, etc&quot;
                },
                &quot;dstorage_note&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;A note to prove the storage of the NFT asset on the dStorage platform, like a Filecoin deal id, a Crust place_storage_order transaction hash, etc&quot;
                }
            }
        }
    }
}
```

For [EIP-1155](/EIPs/EIPS/eip-1155) smart contracts, the Metadata JSON file schema is:

```json
{
    &quot;title&quot;: &quot;Token Metadata&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;name&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Identifies the asset to which this token represents&quot;,
        },
        &quot;decimals&quot;: {
            &quot;type&quot;: &quot;integer&quot;,
            &quot;description&quot;: &quot;The number of decimal places that the token amount should display - e.g. 18, means to divide the token amount by 1000000000000000000 to get its user representation.&quot;
        },
        &quot;description&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Describes the asset to which this token represents&quot;
        },
        &quot;image&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;A URI pointing to a resource with mime type image/* representing the asset to which this token represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive.&quot;
        },
        &quot;properties&quot;: {
            &quot;type&quot;: &quot;object&quot;,
            &quot;description&quot;: &quot;Arbitrary properties. Values may be strings, numbers, object or arrays.&quot;,
        },
        &quot;localization&quot;: {
            &quot;type&quot;: &quot;object&quot;,
            &quot;required&quot;: [&quot;uri&quot;, &quot;default&quot;, &quot;locales&quot;],
            &quot;properties&quot;: {
                &quot;uri&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;The URI pattern to fetch localized data from. This URI should contain the substring `{locale}` which will be replaced with the appropriate locale value before sending the request.&quot;
                },
                &quot;default&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;The locale of the default data within the base JSON&quot;
                },
                &quot;locales&quot;: {
                    &quot;type&quot;: &quot;array&quot;,
                    &quot;description&quot;: &quot;The list of locales for which data is available. These locales should conform to those defined in the Unicode Common Locale Data Repository (http://cldr.unicode.org/).&quot;
                }
            }
        },
        &quot;dStorage&quot;: {
            &quot;type&quot;: &quot;object&quot;,
            &quot;required&quot;: [&quot;platform&quot;, &quot;description&quot;, &quot;persistence_mechanism&quot;, &quot;challenge_mechanism&quot;, &quot;consensus&quot;, &quot;dstorage_note&quot;],
            &quot;properties&quot;: {
                &quot;platform&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;dStorage platform name like Swarm, Arweave, Filecoin, Crust, etc&quot;
                },
                &quot;description&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;A brief description of the dStorage platform&quot;
                },
                &quot;persistence_mechanism&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;Persistence mechanism or incentive structure of the dStorage platform, like &apos;blockchain-based&apos;, &apos;contract-based&apos;, etc&quot;
                },
                &quot;challenge_mechanism&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;Challenge mechanism of the dStorage platform, like Arweave&apos;s proof-of-access, etc&quot;
                },
                &quot;consensus&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;Consensus mechanism of the dStorage platform, like PoW, PoS, etc&quot;
                },
                &quot;dstorage_note&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;A note to prove the storage of the NFT asset on the dStorage platform, like a Filecoin deal id, a Crust place_storage_order transaction hash, etc&quot;
                }
            }
        }
    }
}
```

## Rationale

### Choice between Interface and JSON Schema Extension

An extension of the EIP-721 or EIP-1155 contract interfaces would unnecessarily require additional code to implement, and would not be available for use by NFT projects that already have their NFT smart contracts finalized and deployed. An optional JSON schema extension is noninvasive, and more easily adopted.

# Backwards Compatibility

This EIP is backward compatible with [EIP-721](/EIPs/EIPS/eip-721)  and [EIP-1155](/EIPs/EIPS/eip-1155).

## Security Considerations

This EIP does not introduce any new security risks or vulnerabilities, as the `dStorage` property is only an informational field of the Metadata JSON file returned by [EIP-721](/EIPs/EIPS/eip-721) and [EIP-1155](/EIPs/EIPS/eip-1155) smart contracts. It does not affect the execution or validity of NFT transactions.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 08 Sep 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5625</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5625</guid>
      </item>
    
      <item>
        <title>New approach for encryption / decryption</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5630-encryption-and-decryption/10761</comments>
        
        <description>## Abstract

This EIP proposes a new way to encrypt and decrypt using Ethereum keys. This EIP uses _only_ the `secp256k1` curve, and proposes two new RPC methods: `eth_getEncryptionPublicKey` and `eth_performECDH`. These two methods, in conjunction, allow users to receive encryptions and perform decryptions (respectively). We require that the wallet _only_ perform the core ECDH operation, leaving the ECIES operations up to implementers (we do suggest a standardized version of ECIES, however). In contrast, a previous EIPs used the same secret key, in both signing and encryption, on two _different_ curves (namely, `secp256k1` and `ec25519`), and hardcoded a particular version of ECIES.

## Motivation

We discuss a few motivating examples. One key motivation is direct-to-address encryption on Ethereum. Using our EIP, one can directly send encrypted messages to some desired recipient on-chain, without having a prior direct channel to that recipient. (Note that in this EIP, we standardize _only_ the encryption procedure—that is, the generation of the ciphertext—and _not_ how exactly the on-chain message should be sent. In practice, ideally, smart-contract infrastructure will be set up for this purpose; barring this, encryptors could make use of the raw `data` field available in each standard transfer.)

We discuss a second sort of example. In a certain common design pattern, a dApp generates a fresh secret on behalf of a user. It is of interest if, instead of forcing this user to independently store, safeguard, and back up this latter secret, the dApp may instead encrypt this secret to a public key which the user controls—and whose secret key, crucially, resides within the user&apos;s HD wallet hierarchy—and then post the resulting ciphertext to secure storage (e.g., on-chain).  This design pattern allows the dApp/user to bootstrap the security of the _fresh_ secret onto the security of the user&apos;s existing HD wallet seed phrase, which the user has already gone through the trouble of safeguarding and storing. This represents a far lower UX burden than forcing the user to store and manage fresh keys directly (which can, and often does, lead to loss of funds). We note that this design pattern described above is used today by, various dApps (e.g., Tornado Cash).

## Specification

We describe our approach here; we compare our approach to prior EIPs in the **Rationale** section below. Throughout, we make reference to SEC 1: Elliptic Curve Cryptography, by Daniel R. L. Brown.

We use the `secp256k1` curve for both signing and encryption.
For encryption, we use ECIES. We specify that the wallet _only_ perform the sensitive ECDH operation. This lets implementers select their own ECIES variants at will.

We propose that all binary data be serialized to and from `0x`-prefixed hex strings. We moreover use `0x`-prefixed hex strings to specify private keys and public keys, and represent public keys in compressed form. We represent Ethereum accounts in the usual way (`0x`-prefixed, 20-byte hex strings). Specifically, to serialize and deserialize elliptic curve points, implementers MUST use the following standard:

- to serialize a point: use [SEC 1, §2.3.3], with point compression.
- to deserialize a point: use [SEC 1, §2.3.3], while _requiring_ point compression; that is:

  - the input byte string MUST have length ⌈log₂q / 8⌉ + 1 = `33`.
  - the first byte MUST be `0x02` or `0x03`.
  - the integer represented by the remaining 32 bytes (as in [SEC 1, §2.3.8]) MUST reside in {0, ..., _p_ - 1}, and moreover MUST yield a quadratic residue modulo _p_ under the Weierstrass expression X^3 + 7 (modulo _p_).

For application-level implementers actually implementing ECIES, we propose the following variant. Unless they have a reason to do otherwise, implementers SHOULD use the following standardized choices:

- the KDF `ANSI-X9.63-KDF`, where the hash function `SHA-512` is used,
- the HMAC `HMAC–SHA-256–256 with 32 octet or 256 bit keys`,
- the symmetric encryption scheme `AES–256 in CBC mode`.

We propose that the binary, _concatenated_ serialization mode for ECIES ciphertexts be used, both for encryption and decryption, where moreover elliptic curve points are _compressed_.

Thus, on the request:

```javascript
request({
  method: &apos;eth_getEncryptionPublicKey&apos;,
  params: [account]
})
```

where `account` is a standard 20-byte, `0x`-prefixed, hex-encoded Ethereum account, the client should operate as follows:

- find the secret signing key `sk` corresponding to the Ethereum account `account`, or else return an error if none exists.
- compute the `secp256k1` public key corresponding to `sk`.
- return this public key in compressed, `0x`-prefixed, hex-encoded form, following [SEC 1, §2.3.3].

On the request

```javascript
request({
  method: &apos;eth_performECDH&apos;,
  params: [account, ephemeralKey]
})
```

where `account` is as above, and `ephemeralKey` is an elliptic curve point encoded as above:

- find the secret key `sk` corresponding to the Ethereum account `account`, or else return an error if none exists.
- deserialize `ephemeralKey` to an elliptic curve point using [SEC 1, §2.3.3] (where compression is required), throwing an error if deserialization fails.
- compute the elliptic curve Diffie–Hellman secret, following [SEC 1, §3.3.1].
- return the resulting field element as an 0x-prefixed, hex-encoded, 32-byte string, using [SEC 1, §2.3.5].

Test vectors are given below.

### Encrypting to a smart contract

In light of account abstraction, [EIP-4337](/EIPs/EIPS/eip-4337), and the advent of smart-contract wallets, we moreover specify a way to encrypt to a contract.
More precisely, we specify a way for a contract to _advertise_ how it would like encryptions to it to be constructed. This should be viewed as an analogue of [EIP-1271](/EIPs/EIPS/eip-1271), but for encryption, as opposed to signing.

Our specification is as follows.

```solidity
pragma solidity ^0.8.0;

contract ERC5630 {
  /**
   * @dev Should return an encryption of the provided plaintext, using the provided randomness.
   * @param plaintext      Plaintext to be encrypted
   * @param randomness     Entropy to be used during encryption
   */
  function encryptTo(bytes memory plaintext, bytes32 randomness)
    public
    view
    returns (bytes memory ciphertext);
}
```

Each contract MAY implement `encryptTo` as it desires. Unless it has a good reason to do otherwise, it SHOULD use the ECIES variant we propose above.

## Rationale

There is _no security proof_ for a scheme which simultaneously invokes signing on the `secp256k1` curve and encryption on the `ec25519` curve, and where _the same secret key is moreover used in both cases_. Though no attacks are known, it is not desirable to use a scheme which lacks a proof in this way.
We, instead, propose the reuse of the same key in signing and encryption, but where _the same curve is used in both_. This very setting has been studied in prior work; see, e.g., Degabriele, Lehmann, Paterson, Smart and Strefler, _On the Joint Security of Encryption and Signature in EMV_, 2011. That work found this joint scheme to be secure in the generic group model.
We note that this very joint scheme (i.e., using ECDSA and ECIES on the same curve) is used live in production in EMV payments.

We now discuss a few further aspects of our approach.

**On-chain public key discovery.** Our proposal has an important feature whereby an encryption _to_ some account can be constructed whenever that account has signed at least one transaction.
Indeed, it is possible to recover an account&apos;s `secp256k1` public key directly from any signature on behalf of that account.

**ECDH vs. ECIES.** We specify that the wallet _only_ perform the sensitive ECDH operation, and let application-level implementers perform the remaining steps of ECIES. This has two distinct advantages:

- **Flexibility.** It allows implementers to select arbitrary variants of ECIES, without having to update what the wallet does.
- **Bandwidth.** Our approach requires that only small messages (on the order of 32 bytes) be exchanged between the client and the wallet. This could be material in settings in which the plaintexts and ciphertexts at play are large, and when the client and the wallet are separated by an internet connection. 

**Twist attacks.** A certain GitHub post by Christian Lundkvist warns against &quot;twist attacks&quot; on the `secp256k1` curve. These attacks are not applicable to this EIP, for multiple _distinct_ reasons, which we itemize:

- **Only applies to classical ECDH, not ECIES.** This attack only applies to classical ECDH (i.e., in which both parties use persistent, authenticated public keys), and not to ECIES (in which one party, the encryptor, uses an ephemeral key). Indeed, it only applies to a scenario in which an attacker can induce a victim to exponentiate an attacker-supplied point by a sensitive scalar, and then moreover send the result back to the attacker. But this pattern only happens in classical Diffie–Hellman, and never in ECIES. Indeed, in ECIES, we recall that the only sensitive Diffie–Hellman operation happens during decryption, but in this case, the victim (who would be the decryptor) never sends the resulting DH point back to the attacker (rather, the victim merely uses it locally to attempt an AES decryption). During _encryption_, the exponentiation is done by the encryptor, who has no secret at all (sure enough, the exponentiation is by an ephemeral scalar), so here there would be nothing for the attacker to learn.
- **Only applies to uncompressed points.** Indeed, we use compressed points in this EIP. When compressed points are used, each 33-byte string _necessarily_ either resolves to a point on the correct curve, or else has no reasonable interpretation. There is no such thing as &quot;a point not on the curve&quot; (which, in particular, can pass undetectedly as such).
- **Only applies when you fail to check a point is on the curve.** But this is inapplicable for us anyway, since we use compressed points (see above). We also require that all validations be performed.

## Backwards Compatibility

Our `eth_performECDH` method is new, and so doesn&apos;t raise any backwards compatibility issues.

A previous proposal proposed an `eth_getEncryptionPublicKey` method (together with an `eth_decrypt` method unrelated to this EIP). Our proposal overwrites the previous behavior of `eth_getEncryptionPublicKey`.
It is unlikely that this will be an issue, since encryption keys need be newly retrieved _only_ upon the time of encryption; on the other hand, _new_ ciphertexts will be generated using our new approach.
(In particular, our modification will not affect the ability of ciphertexts generated using the old EIP to be `eth_decrypt`ed.)

In any case, the previous EIP was never standardized, and is _not_ (to our knowledge) implemented in a non-deprecated manner in _any_ production code today.

### Test Cases

The secret _signing key_

```
    0x439047a312c8502d7dd276540e89fe6639d39da1d8466f79be390579d7eaa3b2
```

with Ethereum address `0x72682F2A3c160947696ac3c9CC48d290aa89549c`, has `secp256k1` public key

```
    0x03ff5763a2d3113229f2eda8305fae5cc1729e89037532a42df357437532770010
```

Thus, the request:

```javascript
request({
  method: &apos;eth_getEncryptionPublicKey&apos;,
  params: [&quot;0x72682F2A3c160947696ac3c9CC48d290aa89549c&quot;]
})
```

should return:

```javascript
&quot;0x03ff5763a2d3113229f2eda8305fae5cc1729e89037532a42df357437532770010&quot;
```

If an encryptor were to encrypt a message—say, `I use Firn Protocol to gain privacy on Ethereum.`—under the above public key, using the above ECIES variant, he could obtain, for example:

```javascript
&quot;0x036f06f9355b0e3f7d2971da61834513d5870413d28a16d7d68ce05dc78744daf850e6c2af8fb38e3e31d679deac82bd12148332fa0e34aecb31981bd4fe8f7ac1b74866ce65cbe848ee7a9d39093e0de0bd8523a615af8d6a83bbd8541bf174f47b1ea2bd57396b4a950a0a2eb77af09e36bd5832b8841848a8b302bd816c41ce&quot;
```

Upon obtaining this ciphertext, the decryptor would extract the relevant ephemeral public key, namely:

```javascript
&quot;0x036f06f9355b0e3f7d2971da61834513d5870413d28a16d7d68ce05dc78744daf8&quot;
```

And submit the request:

```javascript
request({
  method: &apos;eth_performECDH&apos;,
  params: [
    &quot;0x72682F2A3c160947696ac3c9CC48d290aa89549c&quot;,
    &quot;0x036f06f9355b0e3f7d2971da61834513d5870413d28a16d7d68ce05dc78744daf8&quot;
  ]
})
```

which in turn would return the Diffie–Hellman secret:

```javascript
&quot;0x4ad782e7409702101abe6d0279f242a2c545c46dd50a6704a4b9e3ae2730522e&quot;
```

Upon proceeding with the above ECIES variant, the decryptor would then obtain the string `I use Firn Protocol to gain privacy on Ethereum.`.

## Security Considerations

Our proposal uses heavily standardized algorithms and follows all best practices.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 07 Sep 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5630</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5630</guid>
      </item>
    
      <item>
        <title>Composable Soulbound NFT, EIP-1155 Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/composable-soulbound-nft-eip-1155-extension/10773</comments>
        
        <description>## Abstract

This standard is an extension of [EIP-1155](/EIPs/EIPS/eip-1155). It proposes a smart contract interface that can represent any number of soulbound and non-soulbound NFT types. Soulbound is the property of a token that prevents it from being transferred between accounts. This standard allows for each token ID to have its own soulbound property. 

## Motivation

The soulbound NFTs similar to World of Warcraft’s soulbound items are attracting more and more attention in the Ethereum community. In a real world game like World of Warcraft, there are thousands of items, and each item has its own soulbound property. For example, the amulate Necklace of Calisea is of soulbound property, but another low level amulate is not. This proposal provides a standard way to represent soulbound NFTs that can coexist with non-soulbound ones. It is easy to design a composable NFTs for an entire collection in a single contract. 

This standard outline a interface to EIP-1155 that allows wallet implementers and developers to check for soulbound property of token ID using [EIP-165](/EIPs/EIPS/eip-165). the soulbound property can be checked in advance, and the transfer function can be called only when the token is not soulbound.

## Specification
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.

A token type with a `uint256 id`  is soulbound if function `isSoulbound(uint256 id)` returning true. In this case, all EIP-1155 functions of the contract that transfer the token from one account to another MUST throw, except for mint and burn. 

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

interface IERC5633 {
  /**
   * @dev Emitted when a token type `id` is set or cancel to soulbound, according to `bounded`.
   */
  event Soulbound(uint256 indexed id, bool bounded);

  /**
   * @dev Returns true if a token type `id` is soulbound.
   */
  function isSoulbound(uint256 id) external view returns (bool);
}
```
Smart contracts implementing this standard MUST implement the EIP-165 supportsInterface function and MUST return the constant value true if 0x911ec470 is passed through the interfaceID argument.

## Rationale

If all tokens in a contract are soulbound by default, `isSoulbound(uint256 id)` should return true by default during implementation.

## Backwards Compatibility

This standard is fully EIP-1155 compatible.

## Test Cases

Test cases are included in [test.js](/EIPs/assets/eip-5633/test/test.js). 

Run in terminal:

```shell
cd ../assets/eip-5633
npm install
npx hardhat test
```

Test contract are included in [`ERC5633Demo.sol`](/EIPs/assets/eip-5633/contracts/ERC5633Demo.sol). 

## Reference Implementation

See [`ERC5633.sol`](/EIPs/assets/eip-5633/contracts/ERC5633.sol).

## Security Considerations

There are no security considerations related directly to the implementation of this standard.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 09 Sep 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5633</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5633</guid>
      </item>
    
      <item>
        <title>NFT Licensing Agreements</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5635-discussion-nft-licensing-agreement-standard/10779</comments>
        
        <description>## Abstract

This EIP standardizes an NFT licensing oracle to store (register) and retrieve (discover) granted licensing agreements for non-fungible token (NFT) derivative works, which are also NFTs but are created using properties of some other underlying NFTs.

In this standard, an NFT derivative work is referred to as a **dNFT**, while the original underlying NFT is referred to as an **oNFT**.

The NFT owner, known as the `licensor`, may authorize another creator, known as the `licensee`, to create a derivative works (dNFTs), in exchange for an agreed payment, known as a `Royalty`. A licensing agreement outlines terms and conditions related to the deal between the licensor and licensee.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

In general, there are three important roles in this standard:

- oNFT: An original underlying NFT. The holder of an oNFT is a licensor. An oNFT can be any NFT.
- dNFT: A derivative work based on one or more oNFTs. The holder of a dNFT is a licensee.
- Registry: A trusted smart contract able to verify whether a credential is signed or released by the holder of oNFT.

Every **dNFT** contract must implement the `IERC5635NFT` and `IERC165` inferfaces.

```solidity
pragma solidity ^0.6.0;
import &quot;./IERC165.sol&quot;;

///
/// @notice Interface of NFT derivatives (dNFT) for the NFT Licensing Standard
/// @dev The ERC-165 identifier for this interface is 0xd584841c.
interface IERC5635DNFT is IERC165 {

    /// ERC165 bytes to add to interface array - set in parent contract
    /// implementing this standard
    ///
    /// bytes4(keccak256(&quot;IERC5635DNFT{}&quot;)) == 0xd584841c
    /// bytes4 private constant _INTERFACE_ID_IERC5635DNFT = 0xd584841c;
    /// _registerInterface(_INTERFACE_ID_IERC5635XDNFT);
    
    /// @notice Get the number of credentials.
    /// @param _tokenId - ID of the dNFT asset queried
    /// @return _number - the number of credentials 
    function numberOfCredentials(
		uint256 _tokenId
    ) external view returns (
        uint256 _number
    );

    /// @notice Called with the sale price to determine how much royalty is owed and to whom.
    /// @param _tokenId - ID of the dNFT asset queried
    /// @param _credentialId - ID of the licensing agreement credential, the max id is numberOfCredentials(_tokenId)-1
    /// @return _oNFT - the oNFT address where the licensing from
    /// @return _tokenID - the oNFT ID where the licensing from
    /// @return _registry - the address of registry which can verify this credential
    function authorizedBy(
        uint256 _tokenId,
        uint256 _credentialId
    ) external view returns (
        address _oNFT,
        uint256 _tokenId,
        address _registry
    );
    
}

interface IERC165 {
    /// @notice Query if a contract implements an interface
    /// @param interfaceID The interface identifier, as specified in ERC-165
    /// @dev Interface identification is specified in ERC-165. This function
    ///  uses less than 30,000 gas.
    /// @return `true` if the contract implements `interfaceID` and
    ///  `interfaceID` is not 0xffffffff, `false` otherwise
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
```

Every **Registry** contract must implement the `IERC5635Registry` and `IERC165` inferfaces.

```solidity
pragma solidity ^0.6.0;
import &quot;./IERC165.sol&quot;;

///
/// @dev Interface of NFT derivatives (dNFT) for the NFT Licensing Standard
///  Note: the ERC-165 identifier for this interface is 0xb5065e9f
interface IERC5635Registry is IERC165 {

    /// ERC165 bytes to add to interface array - set in parent contract
    /// implementing this standard
    ///
    /// bytes4(keccak256(&quot;IERC5635Registry{}&quot;)) == 0xb5065e9f
    /// bytes4 private constant _INTERFACE_ID_IERC5635Registry = 0xb5065e9f;
    /// _registerInterface(_INTERFACE_ID_IERC5635Registry);

    // TODO: Is the syntax correct?
    enum LicensingAgreementType {
      NonExclusive,
      Exclusive,
      Sole
    } 


    /// @notice 
    /// @param _dNFT - 
    /// @param _dNFT_Id - 
    /// @param _oNFT - 
    /// @param _oNFT_Id - 
    /// @return _licensed - 
    /// @return _tokenID - the oNFT ID where the licensing from
    /// @return _registry - the address of registry which can verify this credential
    function isLicensed(
        address _dNFT,
        uint256 _dNFT_Id,
        address _oNFT,
        uint256 _oNFT_Id
    ) external view returns (
        bool _licensed
    );
    
    /// @return _licenseIdentifier - the identifier, e.g. `MIT` or `Apache`, similar to `SPDX-License-Identifier: MIT` in SPDX.
    function licensingInfo(
        address _dNFT,
        uint256 _dNFT_Id,
        address _oNFT,
        uint256 _oNFT_Id
    ) external view returns (
        bool _licensed,
        address _licensor,
        uint64 _timeOfSignature,
        uint64 _expiryTime,
        LicensingAgreementType _type,
        string _licenseName,
        string _licenseUri //
    );
    
    function royaltyRate(
        address _dNFT,
        uint256 _dNFT_Id,
        address _oNFT,
        uint256 _oNFT_Id
    ) external view returns (
        address beneficiary, 
        uint256 rate // The decimals is 9, means to divide the rate by 1,000,000,000
    );
}
```

The **Registry** contract MAY implement the `IERC5635Licensing` and `IERC165` inferfaces.

```solidity
pragma solidity ^0.6.0;
import &quot;./IERC165.sol&quot;;

///
///
interface IERC5635Licensing is IERC165, IERC5635Registry {

    event Licence(address indexed _oNFT, uint256 indexed _oNFT_Id, address indexed _dNFT, uint256 indexed _dNFT_Id, uint64 _expiryTime, LicensingAgreementType _type, string _licenseName, string _licenseUri);

    event Approval(address indexed _oNFT, address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
    
    event ApprovalForAll(address indexed _oNFT, address indexed _owner, address indexed _operator, bool _approved);

    function licence(address indexed _oNFT, uint256 indexed _oNFT_Id, address indexed _dNFT, uint256 indexed _dNFT_Id, uint64 _expiryTime, LicensingAgreementType _type, string _licenseName, string _licenseUri) external payable; //TODO: mortgages or not?
    
    function approve(address indexed _oNFT, address _approved, uint256 _tokenId) external payable; //TODO: why payable?
    
    function setApprovalForAll(address indexed _oNFT, address _operator, bool _approved) external;
    
    function getApproved(address indexed _oNFT, uint256 _tokenId) external view returns (address);
    
    function isApprovedForAll(address indexed _oNFT, address _owner, address _operator) external view returns (bool);

}
```

## Rationale

Licensing credentials from a dNFT&apos;s contract can be retrieved with `authorizedBy`, which specifies the details of a licensing agreement, which may include the oNFT. Those credentials may be verified with a `registry` service.

Anyone can retrieve licensing royalty information with `licensingRoyalty` via the registry. While it is not possible to enforce the rules set out in this EIP on-chain, just like [EIP-2981](/EIPs/EIPS/eip-2981), we encourages NFT marketplaces to follow this EIP.

### Two stages: Licensing and Discovery

Taking the moment when the dNFT is minted as the cut-off point, the stage before is called the **Licensing** stage, and the subsequent stage is called the **Discovery** stage. The interface `IERC5635Licensing` is for the **Licensing** stage, and the interfaces `IERC5635DNFT` and `IERC5635Registry` are for the **Discovery** stage. 

### Design decision: beneficiary of licensing agreement 

As soon as someone sells their NFT, the full licensed rights are passed along to the new owner without any encumbrances, so that the beneficiary should be the new owner.

### Difference between CantBeEvil Licenses and Licensing Agreements.

CantBeEvil licenses are creator-holder licenses which indicate what rights the NFTs&apos; holder are granted from the creator. Meanwhile, licensing agreements is a contract between a licensor and licensee. So, CantBeEvil licenses cannot be used as a licensing agreement.

### Design decision: Relationship between different approval levels

The approved address can `license()` the licensing agreement to **dNFT** on behalf of the holder of an **oNFT**. We define two levels of approval like that: 

1. `approve` will lead to approval for one NFT related to an id.
2. `setApprovalForAll` will lead to approval of all NFTs owned by `msg.sender`.

## Backwards Compatibility

This standard is compatible with [EIP-721](/EIPs/EIPS/eip-721), [EIP-1155](/EIPs/EIPS/eip-1155), and [EIP-2981](/EIPs/EIPS/eip-2981).

## Reference Implementation

### Examples

#### Deploying an [EIP-721](/EIPs/EIPS/eip-721) NFT and signaling support for dNFT

```solidity
constructor (string memory name, string memory symbol, string memory baseURI) {
        _name = name;
        _symbol = symbol;
        _setBaseURI(baseURI);
        // register the supported interfaces to conform to ERC721 via ERC165
        _registerInterface(_INTERFACE_ID_ERC721);
        _registerInterface(_INTERFACE_ID_ERC721_METADATA);
        _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);
        // dNFT interface
        _registerInterface(_INTERFACE_ID_IERC5635DNFT);
}
```

#### Checking if the NFT being sold on your marketplace is a dNFT

```solidity
bytes4 private constant _INTERFACE_ID_IERC5635DNFT = 0xd584841c;

function checkDNFT(address _contract) internal returns (bool) {
    (bool success) = IERC165(_contract).supportsInterface(_INTERFACE_ID_IERC5635DNFT);
    return success;
}
```

#### Checking if an address is a Registry

```solidity
bytes4 private constant _INTERFACE_ID_IERC5635Registry = 0xb5065e9f;

function checkLARegistry(address _contract) internal returns (bool) {
    (bool success) = IERC165(_contract).supportsInterface(_INTERFACE_ID_IERC5635Registry);
    return success;
}
```

## Security Considerations

Needs discussion.


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 10 Aug 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5635</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5635</guid>
      </item>
    
      <item>
        <title>Delegation Registry</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5639-delegation-registry/10949</comments>
        
        <description>## Abstract

This EIP describes the details of the Delegation Registry, a proposed protocol and ABI definition that provides the ability to link one or more delegate wallets to a vault wallet in a manner which allows the linked delegate wallets to prove control and asset ownership of the vault wallet.

## Motivation

Proving ownership of an asset to a third party application in the Ethereum ecosystem is common. Users frequently sign payloads of data to authenticate themselves before gaining access to perform some operation. However, this method--akin to giving the third party root access to one&apos;s main wallet--is both insecure and inconvenient.

***Examples:***

 1. In order for you to edit your profile on OpenSea, you must sign a message with your wallet.
 2. In order to access NFT gated content, you must sign a message with the wallet containing the NFT in order to prove ownership.
 3. In order to gain access to an event, you must sign a message with the wallet containing a required NFT in order to prove ownership.
 4. In order to claim an airdrop, you must interact with the smart contract with the qualifying wallet.
 5. In order to prove ownership of an NFT, you must sign a payload with the wallet that owns that NFT.

In all the above examples, one interacts with the dApp or smart contract using the wallet itself, which may be

 - inconvenient (if it is controlled via a hardware wallet or a multi-sig)
 - insecure (since the above operations are read-only, but you are signing/interacting via a wallet that has write access)

Instead, one should be able to approve multiple wallets to authenticate on behalf of a given wallet.

### Problems with existing methods and solutions

Unfortunately, we&apos;ve seen many cases where users have accidentally signed a malicious payload. The result is almost always a significant loss of assets associated with the delegate address.

In addition to this, many users keep significant portions of their assets in &apos;cold storage&apos;. With the increased security from &apos;cold storage&apos; solutions, we usually see decreased accessibility because users naturally increase the barriers required to access these wallets.

### Proposal: Use of a Delegation Registry

This proposal aims to provide a mechanism which allows a vault wallet to grant wallet, contract or token level permissions to a delegate wallet. This would achieve a safer and more convenient way to sign and authenticate, and provide &apos;read only&apos; access to a vault wallet via one or more secondary wallets.

From there, the benefits are twofold. This EIP gives users increased security via outsourcing potentially malicious signing operations to wallets that are more accessible (hot wallets), while being able to maintain the intended security assumptions of wallets that are not frequently used for signing operations.

#### Improving dApp Interaction Security

Many dApps requires one to prove control of a wallet to gain access. At the moment, this means that you must interact with the dApp using the wallet itself. This is a security issue, as malicious dApps or phishing sites can lead to the assets of the wallet being compromised by having them sign malicious payloads.

However, this risk would be mitigated if one were to use a secondary wallet for these interactions. Malicious interactions would be isolated to the assets held in the secondary wallet, which can be set up to contain little to nothing of value.

#### Improving Multiple Device Access Security

In order for a non-hardware wallet to be used on multiple devices, you must import the seed phrase to each device. Each time a seed phrase is entered on a new device, the risk of the wallet being compromised increases as you are increasing the surface area of devices that have knowledge of the seed phrase.

Instead, each device can have its own unique wallet that is an authorized secondary wallet of the main wallet. If a device specific wallet was ever compromised or lost, you could simply remove the authorization to authenticate.

Further, wallet authentication can be chained so that a secondary wallet could itself authorize one or many tertiary wallets, which then have signing rights for both the secondary address as well as the root main address. This, can allow teams to each have their own signer while the main wallet can easily invalidate an entire tree, just by revoking rights from the root stem.

#### Improving Convenience

Many invididuals use hardware wallets for maximum security. However, this is often inconvenient, since many do not want to carry their hardware wallet with them at all times.

Instead, if you approve a non-hardware wallet for authentication activities (such as a mobile device), you would be able to use most dApps without the need to have your hardware wallet on hand.

## Specification

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.

Let:

 - `vault` represent the vault address we are trying to authenticate or prove asset ownership for.
 - `delegate` represent the address we want to use for signing in lieu of `vault`.

**A Delegation Registry must implement IDelegationRegistry**

```solidity
/**
 * @title An immutable registry contract to be deployed as a standalone primitive
 * @dev New project launches can read previous cold wallet -&gt; hot wallet delegations
 * from here and integrate those permissions into their flow
 */
interface IDelegationRegistry {
    /// @notice Delegation type
    enum DelegationType {
        NONE,
        ALL,
        CONTRACT,
        TOKEN
    }

    /// @notice Info about a single delegation, used for onchain enumeration
    struct DelegationInfo {
        DelegationType type_;
        address vault;
        address delegate;
        address contract_;
        uint256 tokenId;
    }

    /// @notice Info about a single contract-level delegation
    struct ContractDelegation {
        address contract_;
        address delegate;
    }

    /// @notice Info about a single token-level delegation
    struct TokenDelegation {
        address contract_;
        uint256 tokenId;
        address delegate;
    }

    /// @notice Emitted when a user delegates their entire wallet
    event DelegateForAll(address vault, address delegate, bool value);

    /// @notice Emitted when a user delegates a specific contract
    event DelegateForContract(address vault, address delegate, address contract_, bool value);

    /// @notice Emitted when a user delegates a specific token
    event DelegateForToken(address vault, address delegate, address contract_, uint256 tokenId, bool value);

    /// @notice Emitted when a user revokes all delegations
    event RevokeAllDelegates(address vault);

    /// @notice Emitted when a user revoes all delegations for a given delegate
    event RevokeDelegate(address vault, address delegate);

    /**
     * -----------  WRITE -----------
     */

    /**
     * @notice Allow the delegate to act on your behalf for all contracts
     * @param delegate The hotwallet to act on your behalf
     * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking
     */
    function delegateForAll(address delegate, bool value) external;

    /**
     * @notice Allow the delegate to act on your behalf for a specific contract
     * @param delegate The hotwallet to act on your behalf
     * @param contract_ The address for the contract you&apos;re delegating
     * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking
     */
    function delegateForContract(address delegate, address contract_, bool value) external;

    /**
     * @notice Allow the delegate to act on your behalf for a specific token
     * @param delegate The hotwallet to act on your behalf
     * @param contract_ The address for the contract you&apos;re delegating
     * @param tokenId The token id for the token you&apos;re delegating
     * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking
     */
    function delegateForToken(address delegate, address contract_, uint256 tokenId, bool value) external;

    /**
     * @notice Revoke all delegates
     */
    function revokeAllDelegates() external;

    /**
     * @notice Revoke a specific delegate for all their permissions
     * @param delegate The hotwallet to revoke
     */
    function revokeDelegate(address delegate) external;

    /**
     * @notice Remove yourself as a delegate for a specific vault
     * @param vault The vault which delegated to the msg.sender, and should be removed
     */
    function revokeSelf(address vault) external;

    /**
     * -----------  READ -----------
     */

    /**
     * @notice Returns all active delegations a given delegate is able to claim on behalf of
     * @param delegate The delegate that you would like to retrieve delegations for
     * @return info Array of DelegationInfo structs
     */
    function getDelegationsByDelegate(address delegate) external view returns (DelegationInfo[] memory);

    /**
     * @notice Returns an array of wallet-level delegates for a given vault
     * @param vault The cold wallet who issued the delegation
     * @return addresses Array of wallet-level delegates for a given vault
     */
    function getDelegatesForAll(address vault) external view returns (address[] memory);

    /**
     * @notice Returns an array of contract-level delegates for a given vault and contract
     * @param vault The cold wallet who issued the delegation
     * @param contract_ The address for the contract you&apos;re delegating
     * @return addresses Array of contract-level delegates for a given vault and contract
     */
    function getDelegatesForContract(address vault, address contract_) external view returns (address[] memory);

    /**
     * @notice Returns an array of contract-level delegates for a given vault&apos;s token
     * @param vault The cold wallet who issued the delegation
     * @param contract_ The address for the contract holding the token
     * @param tokenId The token id for the token you&apos;re delegating
     * @return addresses Array of contract-level delegates for a given vault&apos;s token
     */
    function getDelegatesForToken(address vault, address contract_, uint256 tokenId)
        external
        view
        returns (address[] memory);

    /**
     * @notice Returns all contract-level delegations for a given vault
     * @param vault The cold wallet who issued the delegations
     * @return delegations Array of ContractDelegation structs
     */
    function getContractLevelDelegations(address vault)
        external
        view
        returns (ContractDelegation[] memory delegations);

    /**
     * @notice Returns all token-level delegations for a given vault
     * @param vault The cold wallet who issued the delegations
     * @return delegations Array of TokenDelegation structs
     */
    function getTokenLevelDelegations(address vault) external view returns (TokenDelegation[] memory delegations);

    /**
     * @notice Returns true if the address is delegated to act on the entire vault
     * @param delegate The hotwallet to act on your behalf
     * @param vault The cold wallet who issued the delegation
     */
    function checkDelegateForAll(address delegate, address vault) external view returns (bool);

    /**
     * @notice Returns true if the address is delegated to act on your behalf for a token contract or an entire vault
     * @param delegate The hotwallet to act on your behalf
     * @param contract_ The address for the contract you&apos;re delegating
     * @param vault The cold wallet who issued the delegation
     */
    function checkDelegateForContract(address delegate, address vault, address contract_)
        external
        view
        returns (bool);

    /**
     * @notice Returns true if the address is delegated to act on your behalf for a specific token, the token&apos;s contract or an entire vault
     * @param delegate The hotwallet to act on your behalf
     * @param contract_ The address for the contract you&apos;re delegating
     * @param tokenId The token id for the token you&apos;re delegating
     * @param vault The cold wallet who issued the delegation
     */
    function checkDelegateForToken(address delegate, address vault, address contract_, uint256 tokenId)
        external
        view
        returns (bool);
}
```

### Checking Delegation

A dApp or smart contract would check whether or not a delegate is authenticated for a vault by checking the return value of checkDelegateForAll.

A dApp or smart contract would check whether or not a delegate can authenticated for a contract associated with a by checking the return value of checkDelegateForContract.

A dApp or smart contract would check whether or not a delegate can authenticated for a specific token owned by a vault by checking the return value of checkDelegateForToken.

A delegate can act on a token if they have a token level delegation, contract level delegation (for that token&apos;s contract) or vault level delegation.

A delegate can act on a contract if they have contract level delegation or vault level delegation.

For the purposes of saving gas, it is expected if delegation checks are performed at a smart contract level, the dApp would provide a hint to the smart contract which level of delegation the delegate has so that the smart contract can verify with the Delegation Registry using the most gas efficient check method.

## Rationale

### Allowing for vault, contract or token level delegation

In order to support a wide range of delegation use cases, the proposed specification allows a vault to delegate all assets it controls, assets of a specific contract, or a specific token. This ensures that a vault has fine grained control over the security of their assets, and allows for emergent behavior around granting third party wallets limited access only to assets relevant to them.

### On-chain enumeration

In order to support ease of integration and adoption, this specification has chosen to include on-chain enumeration of delegations and incur the additional gas cost associated with supporting enumeration. On-chain enumeration allows for dApp frontends to identify the delegations that any connected wallet has access to, and can provide UI selectors.

Without on-chain enumeration, a dApp would require the user to manually input the vault, or would need a way to index all delegate events.


## Security Considerations

The core purpose of this EIP is to enhance security and promote a safer way to authenticate wallet control and asset ownership when the main wallet is not needed and assets held by the main wallet do not need to be moved. Consider it a way to do &apos;read only&apos; authentication.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 09 Sep 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5639</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5639</guid>
      </item>
    
      <item>
        <title>Subscription NFTs</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5643-subscription-nfts/10802</comments>
        
        <description>## Abstract

This standard is an extension of [EIP-721](/EIPs/EIPS/eip-721). It proposes an additional interface for NFTs to be used as recurring, expirable subscriptions. The interface includes functions to renew and cancel the subscription.

## Motivation

NFTs are commonly used as accounts on decentralized apps or membership passes to communities, events, and more. However, it is currently rare to see NFTs like these that have a finite expiration date. The &quot;permanence&quot; of the blockchain often leads to memberships that have no expiration dates and thus no required recurring payments. However, for many real-world applications, a paid subscription is needed to keep an account or membership valid.

The most prevalent on-chain application that makes use of the renewable subscription model is the Ethereum Name Service (ENS), which utilizes a similar interface to the one proposed below. Each domain can be renewed for a certain period of time, and expires if payments are no longer made. A common interface will make it easier for future projects to develop subscription-based NFTs. In the current Web2 world, it&apos;s hard for a user to see or manage all of their subscriptions in one place. With a common standard for subscriptions, it will be easy for a single application to determine the number of subscriptions a user has, see when they expire, and renew/cancel them as requested.

Additionally, as the prevalence of secondary royalties from NFT trading disappears, creators will need new models for generating recurring income. For NFTs that act as membership or access passes, pivoting to a subscription-based model is one way to provide income and also force issuers to keep providing value.

## Specification

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.

```solidity
interface IERC5643 {
    /// @notice Emitted when a subscription expiration changes
    /// @dev When a subscription is canceled, the expiration value should also be 0.
    event SubscriptionUpdate(uint256 indexed tokenId, uint64 expiration);

    /// @notice Renews the subscription to an NFT
    /// Throws if `tokenId` is not a valid NFT
    /// @param tokenId The NFT to renew the subscription for
    /// @param duration The number of seconds to extend a subscription for
    function renewSubscription(uint256 tokenId, uint64 duration) external payable;

    /// @notice Cancels the subscription of an NFT
    /// @dev Throws if `tokenId` is not a valid NFT
    /// @param tokenId The NFT to cancel the subscription for
    function cancelSubscription(uint256 tokenId) external payable;

    /// @notice Gets the expiration date of a subscription
    /// @dev Throws if `tokenId` is not a valid NFT
    /// @param tokenId The NFT to get the expiration date of
    /// @return The expiration date of the subscription
    function expiresAt(uint256 tokenId) external view returns(uint64);

    /// @notice Determines whether a subscription can be renewed
    /// @dev Throws if `tokenId` is not a valid NFT
    /// @param tokenId The NFT to get the expiration date of
    /// @return The renewability of a the subscription
    function isRenewable(uint256 tokenId) external view returns(bool);
}
```

The `expiresAt(uint256 tokenId)` function MAY be implemented as `pure` or `view`.

The `isRenewable(uint256 tokenId)` function MAY be implemented as `pure` or `view`.

The `renewSubscription(uint256 tokenId, uint64 duration)` function MAY be implemented as `external` or `public`.

The `cancelSubscription(uint256 tokenId)` function MAY be implemented as `external` or `public`.

The `SubscriptionUpdate` event MUST be emitted whenever the expiration date of a subscription is changed.

The `supportsInterface` method MUST return `true` when called with `0x8c65f84d`.

## Rationale

This standard aims to make on-chain subscriptions as simple as possible by adding the minimal required functions and events for implementing on-chain subscriptions. It is important to note that in this interface, the NFT itself represents ownership of a subscription, there is no facilitation of any other fungible or non-fungible tokens.

### Subscription Management

Subscriptions represent agreements to make advanced payments in order to receive or participate in something. In order to facilitate these agreements, a user must be able to renew or cancel their subscriptions hence the `renewSubscription` and `cancelSubscription` functions. It also important to know when a subscription expires - users will need this information to know when to renew, and applications need this information to determine the validity of a subscription NFT. The `expiresAt` function provides this functionality. Finally, it is possible that a subscription may not be renewed once expired. The `isRenewable` function gives users and applications that information.

### Easy Integration

Because this standard is fully EIP-721 compliant, existing protocols will be able to facilitate the transfer of subscription NFTs out of the box. With only a few functions to add, protocols will be able to fully manage a subscription&apos;s expiration, determine whether a subscription is expired, and see whether it can be renewed.

## Backwards Compatibility

This standard can be fully EIP-721 compatible by adding an extension function set.

The new functions introduced in this standard add minimal overhead to the existing EIP-721 interface, which should make adoption straightforward and quick for developers.

## Test Cases

The following tests require Foundry.

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.13;

import &quot;forge-std/Test.sol&quot;;
import &quot;../src/ERC5643.sol&quot;;

contract ERC5643Mock is ERC5643 {
    constructor(string memory name_, string memory symbol_) ERC5643(name_, symbol_) {}

    function mint(address to, uint256 tokenId) public {
        _mint(to, tokenId);
    }
}

contract ERC5643Test is Test {
    event SubscriptionUpdate(uint256 indexed tokenId, uint64 expiration);

    address user1;
    uint256 tokenId;
    ERC5643Mock erc5643;

    function setUp() public {
        tokenId = 1;
        user1 = address(0x1);

        erc5643 = new ERC5643Mock(&quot;erc5369&quot;, &quot;ERC5643&quot;);
        erc5643.mint(user1, tokenId);
    }

    function testRenewalValid() public {
        vm.warp(1000);
        vm.prank(user1);
        vm.expectEmit(true, true, false, true);
        emit SubscriptionUpdate(tokenId, 3000);
        erc5643.renewSubscription(tokenId, 2000);
    }

    function testRenewalNotOwner() public {
        vm.expectRevert(&quot;Caller is not owner nor approved&quot;);
        erc5643.renewSubscription(tokenId, 2000);
    }

    function testCancelValid() public {
        vm.prank(user1);
        vm.expectEmit(true, true, false, true);
        emit SubscriptionUpdate(tokenId, 0);
        erc5643.cancelSubscription(tokenId);
    }

    function testCancelNotOwner() public {
        vm.expectRevert(&quot;Caller is not owner nor approved&quot;);
        erc5643.cancelSubscription(tokenId);
    }

    function testExpiresAt() public {
        vm.warp(1000);

        assertEq(erc5643.expiresAt(tokenId), 0);
        vm.startPrank(user1);
        erc5643.renewSubscription(tokenId, 2000);
        assertEq(erc5643.expiresAt(tokenId), 3000);

        erc5643.cancelSubscription(tokenId);
        assertEq(erc5643.expiresAt(tokenId), 0);
    }
}
```

## Reference Implementation

Implementation: `ERC5643.sol`

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.13;

import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;
import &quot;./IERC5643.sol&quot;;

contract ERC5643 is ERC721, IERC5643 {
    mapping(uint256 =&gt; uint64) private _expirations;

    constructor(string memory name_, string memory symbol_) ERC721(name_, symbol_) {}

    function renewSubscription(uint256 tokenId, uint64 duration) external payable {
        require(_isApprovedOrOwner(msg.sender, tokenId), &quot;Caller is not owner nor approved&quot;);

        uint64 currentExpiration = _expirations[tokenId];
        uint64 newExpiration;
        if (currentExpiration == 0) {
            newExpiration = uint64(block.timestamp) + duration;
        } else {
            if (!_isRenewable(tokenId)) {
                revert SubscriptionNotRenewable();
            }
            newExpiration = currentExpiration + duration;
        }

        _expirations[tokenId] = newExpiration;

        emit SubscriptionUpdate(tokenId, newExpiration);
    }

    function cancelSubscription(uint256 tokenId) external payable {
        require(_isApprovedOrOwner(msg.sender, tokenId), &quot;Caller is not owner nor approved&quot;);
        delete _expirations[tokenId];
        emit SubscriptionUpdate(tokenId, 0);
    }

    function expiresAt(uint256 tokenId) external view returns(uint64) {
        return _expirations[tokenId];
    }

    function isRenewable(uint256 tokenId) external pure returns(bool) {
        return true;
    }

    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC5643).interfaceId || super.supportsInterface(interfaceId);
    }
}
```

## Security Considerations

This EIP standard does not affect ownership of an NFT and thus can be considered secure.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 10 Sep 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5643</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5643</guid>
      </item>
    
      <item>
        <title>Token State Fingerprint</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5646-discussion-token-state-fingerprint/10808</comments>
        
        <description>## Abstract

This specification defines the minimum interface required to unambiguously identify the state of a mutable token without knowledge of implementation details.

## Motivation

Currently, protocols need to know about tokens&apos; state properties to create the unambiguous identifier. Unfortunately, this leads to an obvious bottleneck in which protocols need to support every new token specifically.

![](/EIPs/assets/eip-5646/support-per-abi.png)

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, and &quot;MAY&quot; in this document are to be interpreted as described in RFC 2119.

```solidity
pragma solidity ^0.8.0;

interface ERC5646 is ERC165 {

    /// @notice Function to return current token state fingerprint.
    /// @param tokenId Id of a token state in question.
    /// @return Current token state fingerprint.
    function getStateFingerprint(uint256 tokenId) external view returns (bytes32);

}
```

- `getStateFingerprint` MUST return a different value when the token state changes.
- `getStateFingerprint` MUST NOT return a different value when the token state remains the same.
- `getStateFingerprint` MUST include all state properties that might change during the token lifecycle (are not immutable).
- `getStateFingerprint` MAY include computed values, such as values based on a current timestamp (e.g., expiration, maturity).
- `getStateFingerprint` MAY include token metadata URI.
- `supportsInterface(0xf5112315)` MUST return `true`.

## Rationale

Protocols can use state fingerprints as a part of a token identifier and support mutable tokens without knowing any state implementation details.

![](/EIPs/assets/eip-5646/support-per-eip.png)

State fingerprints don&apos;t have to factor in state properties that are immutable, because they can be safely identified by a token id. 

This standard is not for use cases where token state property knowledge is required, as these cases cannot escape the bottleneck problem described earlier.

## Backwards Compatibility

This EIP is not introducing any backward incompatibilities.

## Reference Implementation

```solidity
pragma solidity ^0.8.0;

/// @title Example of a mutable token implementing state fingerprint.
contract LPToken is ERC721, ERC5646 {

    /// @dev Stored token states (token id =&gt; state).
    mapping (uint256 =&gt; State) internal states;

    struct State {
        address asset1;
        address asset2;
        uint256 amount1;
        uint256 amount2;
        uint256 fee; // Immutable
        address operator; // Immutable
        uint256 expiration; // Parameter dependent on a block.timestamp
    }


    /// @dev State fingerprint getter.
    /// @param tokenId Id of a token state in question.
    /// @return Current token state fingerprint.
    function getStateFingerprint(uint256 tokenId) override public view returns (bytes32) {
        State storage state = states[tokenId];

        return keccak256(
            abi.encode(
                state.asset1,
                state.asset2,
                state.amount1,
                state.amount2,
                // state.fee don&apos;t need to be part of the fingerprint computation as it is immutable
                // state.operator don&apos;t need to be part of the fingerprint computation as it is immutable
                block.timestamp &gt;= state.expiration
            )
        );
    }

    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return super.supportsInterface(interfaceId) ||
            interfaceId == type(ERC5646).interfaceId;
    }

}
```

## Security Considerations

Token state fingerprints from two different contracts may collide. Because of that, they should be compared only in the context of one token contract.

If the `getStateFingerprint` implementation does not include all parameters that could change the token state, a token owner would be able to change the token state without changing the token fingerprint. It could break the trustless assumptions of several protocols, which create, e.g., buy offers for tokens. The token owner would be able to change the state of the token before accepting an offer.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 11 Sep 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5646</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5646</guid>
      </item>
    
      <item>
        <title>MCOPY - Memory copying instruction</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5656-mcopy-instruction/10890</comments>
        
        <description>## Abstract

Provide an efficient EVM instruction for copying memory areas.

## Motivation

Memory copying is a basic operation, yet implementing it on the EVM comes with overhead.

This was recognised and alleviated early on with the introduction of the &quot;identity&quot; precompile, which accomplishes
memory copying by the use of `CALL`&apos;s input and output memory offsets. Its cost is `15 + 3 * (length / 32)` gas, plus
the call overhead. The identity precompile was rendered ineffective by the raise of the cost of `CALL` to 700, but subsequently
the reduction by [EIP-2929](/EIPs/EIPS/eip-2929) made it slightly more economical.

Copying exact words can be accomplished with `&lt;offset&gt; MLOAD &lt;offset&gt; MSTORE` or `&lt;offset&gt; DUP1 MLOAD DUP2 MSTORE`,
at a cost of at least 12 gas per word. This is fairly efficient if the offsets are known upfront and the copying can be unrolled.
In case copying is implemented at runtime with arbitrary starting offsets, besides the control flow overhead, the offset
will need to be incremented using `32 ADD`, adding at least 6 gas per word.

Copying non-exact words is more tricky, as for the last partial word, both the source and destination needs to be loaded,
masked, or&apos;d, and stored again. This overhead is significant. One edge case is if the last &quot;partial word&quot; is a single byte,
it can be efficiently stored using `MSTORE8`.

As example use case, copying 256 bytes costs:

- at least 757 gas pre-EIP-2929 using the identity precompile
- at least 157 gas post-EIP-2929 using the identity precompile
- at least 96 gas using unrolled `MLOAD`/`MSTORE` instructions
- 27 gas using this EIP

According to an analysis of blocks 10537502 to 10538702, roughly 10.5% of memory copies would have had improved performance with the
availability of an `MCOPY` instruction.

Memory copying is used by languages like Solidity and Vyper, where we expect this improvement to provide efficient means of building
data structures, including efficient sliced access and copies of memory objects. Having a dedicated `MCOPY` instruction would also add
forward protection against future gas cost changes to `CALL` instructions in general.

Having a special `MCOPY` instruction makes the job of static analyzers and optimizers easier, since the effects of a `CALL` in general
have to be fenced, whereas an `MCOPY` instruction would be known to only have memory effects. Even if special cases are added
for precompiles, a future hard fork could change `CALL` effects, and so any analysis of code using the identity precompile would only
be valid for a certain range of blocks.

Finally, we expect memory copying to be immensely useful for various computationally heavy operations, such as EVM384,
where it is identified as a significant overhead.

## Specification

The instruction `MCOPY` is introduced at `0x5E`.

### Input stack

| Stack | Value |
|-------|-------|
| top - 0 | `dst` |
| top - 1 | `src` |
| top - 2 | `length` |

This ordering matches the other copying instructions, i.e. `CALLDATACOPY`, `RETURNDATACOPY`.

### Gas costs

Per yellow paper terminology, it should be considered part of the `W_copy` group of opcodes, and follow the gas calculation for `W_copy` in the yellow paper. While the calculation in the yellow paper should be considered the final word, for reference, as of time of this writing, that currently means its gas cost is:

```
words_copied = (length + 31) // 32
g_verylow    = 3
g_copy       = 3 * words_copied + memory_expansion_cost
gas_cost     = g_verylow + g_copy
```

### Output stack

This instruction returns no stack items.

### Semantics

It copies `length` bytes from the offset pointed at `src` to the offset pointed at `dst` in memory.
Copying takes place as if an intermediate buffer was used, allowing the destination and source to overlap.

If `length &gt; 0` and (`src + length` or `dst + length`) is beyond the current memory length, the memory is extended with respective gas cost applied.

The gas cost of this instruction mirrors that of other `Wcopy` instructions and is `Gverylow + Gcopy * ceil(length / 32)`.

## Rationale

Production implementation of exact-word memory copying and partial-word memory copying can be found in the Solidity, Vyper and Fe compilers.

With [EIP-2929](/EIPs/EIPS/eip-2929) the call overhead using the identity precompile was reduced from 700 to 100 gas.
This is still prohibitive for making the precompile a reasonable alternative again.

## Backwards Compatibility

This EIP introduces a new instruction which did not exist previously. Already deployed contracts using this instruction could change their behaviour after this EIP.

## Test Cases

`MCOPY 0 32 32` - copy 32 bytes from offset 32 to offset 0.

pre (spaces included for readability):

```
0000000000000000000000000000000000000000000000000000000000000000 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
```

post:

```
000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
```

gas used: 6

`MCOPY 0 0 32` - copy 32 bytes from offset 0 to offset 0.

pre:

```
0101010101010101010101010101010101010101010101010101010101010101
```

post:

```
0101010101010101010101010101010101010101010101010101010101010101
```

gas used: 6

`MCOPY 0 1 8` - copy 8 bytes from offset 1 to offset 0 (overlapping).

pre (space at byte 8):

```
0001020304050607 080000000000000000000000000000000000000000000000
```

post:

```
0102030405060708 080000000000000000000000000000000000000000000000
```

gas used: 6

`MCOPY 1 0 8` - copy 8 bytes from offset 0 to offset 1 (overlapping).

pre (space at byte 8):

```
0001020304050607 080000000000000000000000000000000000000000000000
```

post:

```
0000010203040506 070000000000000000000000000000000000000000000000
```

gas used: 6

### Full test suite

A full suite of tests can be found in the execution spec tests: [MCOPY suite](https://github.com/ethereum/execution-spec-tests/tree/c0065176a79f89d93f4c326186fc257ec5b8d5f1/tests/cancun/eip5656_mcopy).

## Security Considerations

Clients should take care that their implementation does not use an intermediate buffer (see for instance that the C stdlib `memmove` function does not use an intermediate buffer), as this is a potential Denial of Service (DoS) vector. Most language builtins / standard library functions for moving bytes have the correct performance characteristics here.

This aside, the analysis for Denial of Service (DoS) and memory exhaustion attacks is identical to other opcodes which touch memory, as the memory expansion follows the same pricing rules.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 01 Feb 2021 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5656</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5656</guid>
      </item>
    
      <item>
        <title>Token Minting and Burning</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-5679-mint-and-burn-tokens/10913</comments>
        
        <description>## Abstract

This EIP introduces a consistent way to extend token standards for minting and burning.

## Motivation

Minting and Burning are typical actions for creating and destroying tokens.
By establishing a consistent way to mint and burn a token, we complete the basic lifecycle.

Some implementations of [EIP-721](/EIPs/EIPS/eip-721) and [EIP-1155](/EIPs/EIPS/eip-1155)
have been able to use `transfer` methods or the-like
to mint and burn tokens. However, minting and burning change token supply. The access controls
of minting and burning also usually follow different rules than transfer.
Therefore, creating separate methods for burning and minting simplifies implementations
and reduces security error.

## Specification

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.

1. Any contract complying with [EIP-20](/EIPs/EIPS/eip-20) when extended with this EIP,
**MUST** implement the following interface:

```solidity
// The EIP-165 identifier of this interface is 0xd0017968
interface IERC5679Ext20 {
   function mint(address _to, uint256 _amount, bytes calldata _data) external;
   function burn(address _from, uint256 _amount, bytes calldata _data) external;
}
```

2. Any contract complying with [EIP-721](/EIPs/EIPS/eip-721) when extended with this EIP,
**MUST** implement the following interface:

```solidity
// The EIP-165 identifier of this interface is 0xcce39764
interface IERC5679Ext721 {
   function safeMint(address _to, uint256 _id, bytes calldata _data) external;
   function burn(address _from, uint256 _id, bytes calldata _data) external;
}
```

3. Any contract complying with [EIP-1155](/EIPs/EIPS/eip-1155) when extended with this EIP,
**MUST** implement the following interface:

```solidity
// The EIP-165 identifier of this interface is 0xf4cedd5a
interface IERC5679Ext1155 {
   function safeMint(address _to, uint256 _id, uint256 _amount, bytes calldata _data) external;
   function safeMintBatch(address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;
   function burn(address _from, uint256 _id, uint256 _amount, bytes[] calldata _data) external;
   function burnBatch(address _from, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata _data) external;
}
```

4. When the token is being minted, the transfer events **MUST** be emitted as if
the token in the `_amount` for EIP-20 and EIP-1155 and token id being `_id` for EIP-721 and EIP-1155
were transferred from address `0x0` to the recipient address identified by `_to`.
The total supply **MUST** increase accordingly.

5. When the token is being burned, the transfer events **MUST** be emitted as if
the token in the `_amount` for EIP-20 and EIP-1155 and token id being `_id` for EIP-721 and EIP-1155
were transferred from the recipient address identified by `_to` to the address of `0x0`.
The total supply **MUST** decrease accordingly.

6. `safeMint` MUST implement the same receiver restrictions as `safeTransferFrom` as defined in
[EIP-721](/EIPs/EIPS/eip-721) and [EIP-1155](/EIPs/EIPS/eip-1155).

7. It&apos;s RECOMMENDED for the client to implement [EIP-165](/EIPs/EIPS/eip-165) identifiers as specified above.

## Rationale

1. It&apos;s possible that the interface be consolidated to the same as EIP-1155 which is always bearing `_amount` field,
regardless of whether it&apos;s a EIP-20, EIP-721 or EIP-1155. But we choose that each ERC token should have their own
standard way of representing the amount of token to follow the same way of `_id` and `_amount` in their original
token standard.

2. We have chosen to identify the interface with [EIP-165](/EIPs/EIPS/eip-165) identifiers each individually,
instead of having a single identifier because the signatures of interface are different.

3. We have chosen NOT to create new events but to require the usage of existing transfer event as required by EIP-20
EIP-721 and EIP-1155 for maximum compatibility.

4. We have chosen to add `safeMintBatch` and `burnBatch` methods for EIP-1155 but not for EIP-721 to follow the
convention of EIP-721 and EIP-1155 respectively.

5. We have not add extension for [EIP-777](/EIPs/EIPS/eip-777) because it already handles Minting and Burning.

## Backwards Compatibility

This EIP is designed to be compatible for EIP-20, EIP-721 and EIP-1155 respectively.

## Security Considerations

This EIP depends on the security soundness of the underlying book keeping behavior of the token implementation.
In particular, a token contract should carefully design the access control for which role is granted permission
to mint a new token. Failing to safe guard such behavior can cause fraudulent issuance and an elevation of total supply.

The burning should also carefully design the access control. Typically only the following two roles are entitled to burn a token:

- Role 1. The current token holder
- Role 2. An role with special privilege.

Either Role 1 OR Role 2 or a consensus between the two are entitled to conduct the burning action.
However as author of this EIP we do recognize there are potentially other use case where a third type of role shall be entitled
to burning. We keep this EIP less opinionated in such restriction but implementors should be cautious about designing
the restriction.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 17 Sep 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5679</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5679</guid>
      </item>
    
      <item>
        <title>Bindable Token Interface</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5700-bindable-token-standard/11077</comments>
        
        <description>## Abstract

This standard defines an interface for [ERC-721](/EIPs/EIPS/eip-721) or [ERC-1155](/EIPs/EIPS/eip-155) tokens, known as &quot;bindables&quot;, to &quot;bind&quot; to [ERC-721](/EIPs/EIPS/eip-721) NFTs.

When bindable tokens &quot;bind&quot; to an NFT, even though their ownership is transferred to the NFT, the NFT owner may &quot;unbind&quot; the tokens and claim their ownership. This enables bindable tokens to transfer with their bound NFTs without extra cost, offering a more effective way to create and transfer N:1 token-to-NFT bundles. Until an NFT owner decides to unbind them, bound tokens stay locked and resume their base token functionalities after unbinding. 

This standard supports various use-cases such as:

- NFT-bundled physical assets like microchipped streetwear, digitized car collections, and digitally twinned real estate.
- NFT-bundled digital assets such as accessorizable virtual wardrobes, composable music tracks, and customizable metaverse land.

## Motivation

A standard interface for NFT binding offers a seamless and efficient way to bundle and transfer tokens with NFTs, ensuring compatibility with wallets, marketplaces, and other NFT applications. It eliminates the need for rigid, implementation-specific strategies for token ownership.

In contrast with other standards that deal with token ownership at the account level, this standard aims to address token ownership at the NFT level. Its objective is to build a universal interface for token bundling, compatible with existing [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155) standards.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### ERC-721 Bindable

**Smart contracts implementing the ERC-721 bindable standard MUST implement the `IERC721Bindable` interface.**

**Implementers of the `IER721Bindable` interface MUST return `true` if `0x82a34a7d` is passed as the identifier to the `supportsInterface` function.**

```solidity
/// @title ERC-721 Bindable Token Standard
/// @dev See https://eips.ethereum.org/ERCS/eip-5700
///  Note: the ERC-165 identifier for this interface is 0x82a34a7d.
interface IERC721Bindable /* is IERC721 */ {

    /// @notice This event emits when an unbound token is bound to an NFT.
    /// @param operator The address approved to perform the binding.
    /// @param from The address of the unbound token owner.
    /// @param bindAddress The contract address of the NFT being bound to.
    /// @param bindId The identifier of the NFT being bound to.
    /// @param tokenId The identifier of binding token.
    event Bind(
        address indexed operator,
        address indexed from,
        address indexed bindAddress,
        uint256 bindId,
        uint256 tokenId
    );

    /// @notice This event emits when an NFT-bound token is unbound.
    /// @param operator The address approved to perform the unbinding.
    /// @param from The owner of the NFT the token is bound to.
    /// @param to The address of the new unbound token owner.
    /// @param bindAddress The contract address of the NFT being unbound from.
    /// @param bindId The identifier of the NFT being unbound from.
    /// @param tokenId The identifier of the unbinding token.
    event Unbind(
        address indexed operator,
        address indexed from,
        address to,
        address indexed bindAddress,
        uint256 bindId,
        uint256 tokenId
    );

    /// @notice Binds token `tokenId` to NFT `bindId` at address `bindAddress`.
    /// @dev The function MUST throw unless `msg.sender` is the current owner, 
    ///  an authorized operator, or the approved address for the token. It also
    ///  MUST throw if the token is already bound or if `from` is not the token
    ///  owner. Finally, it MUST throw if the NFT contract does not support the
    ///  ERC-721 interface or if the NFT being bound to does not exist. Before 
    ///  binding, token ownership MUST be transferred to the contract address of
    ///  the NFT. On bind completion, the function MUST emit `Transfer` &amp; `Bind` 
    ///  events to reflect the implicit token transfer and subsequent bind.
    /// @param from The address of the unbound token owner.
    /// @param bindAddress The contract address of the NFT being bound to.
    /// @param bindId The identifier of the NFT being bound to.
    /// @param tokenId The identifier of the binding token.
    function bind(
        address from,
        address bindAddress,
        uint256 bindId,
        uint256 tokenId
    ) external;

    /// @notice Unbinds token `tokenId` from NFT `bindId` at address `bindAddress`.
    /// @dev The function MUST throw unless `msg.sender` is the current owner, 
    ///  an authorized operator, or the approved address for the NFT the token
    ///  is bound to. It also MUST throw if the token is unbound, if `from` is
    ///  not the owner of the bound NFT, or if `to` is the zero address. After
    ///  unbinding, token ownership MUST be transferred to `to`, during which
    ///  the function MUST check if `to` is a valid contract (code size &gt; 0),
    ///  and if so, call `onERC721Received`, throwing if the wrong identifier is
    ///  returned. On unbind completion, the function MUST emit `Unbind` &amp;
    ///  `Transfer` events to reflect the unbind and subsequent transfer.
    /// @param from The address of the owner of the NFT the token is bound to.
    /// @param to The address of the unbound token new owner.
    /// @param bindAddress The contract address of the NFT being unbound from.
    /// @param bindId The identifier of the NFT being unbound from.
    /// @param tokenId The identifier of the unbinding token.
    function unbind(
        address from,
        address to,
        address bindAddress,
        uint256 bindId,
        uint256 tokenId
    ) external;

    /// @notice Gets the NFT address and identifier token `tokenId` is bound to.
    /// @dev When the token is unbound, this function MUST return the zero
    ///  address for the address portion to indicate no binding exists.
    /// @param tokenId The identifier of the token being queried.
    /// @return The token-bound NFT contract address and numerical identifier.
    function binderOf(uint256 tokenId) external view returns (address, uint256);

    /// @notice Gets total tokens bound to NFT `bindId` at address `bindAddress`.
    /// @param bindAddress The contract address of the NFT being queried.
    /// @param bindId The identifier of the NFT being queried.
    /// @return The total number of tokens bound to the queried NFT.
    function boundBalanceOf(address bindAddress, uint256 bindId) external view returns (uint256);

```

### ERC-1155 Bindable

**Smart contracts implementing the ERC-1155 Bindable standard MUST implement the `IERC1155Bindable` interface.**

**Implementers of the `IER1155Bindable` interface MUST return `true` if `0xd0d55c6` is passed as the identifier to the `supportsInterface` function.**

```solidity
/// @title ERC-1155 Bindable Token Standard
/// @dev See https://eips.ethereum.org/ERCS/eip-5700
///  Note: the ERC-165 identifier for this interface is 0xd0d555c6.
interface IERC1155Bindable /* is IERC1155 */ {

    /// @notice This event emits when token(s) are bound to an NFT.
    /// @param operator The address approved to perform the binding.
    /// @param from The owner address of the unbound tokens.
    /// @param bindAddress The contract address of the NFT being bound to.
    /// @param bindId The identifier of the NFT being bound to.
    /// @param tokenId The identifier of the binding token type.
    /// @param amount The number of tokens binding to the NFT.
    event Bind(
        address indexed operator,
        address indexed from,
        address indexed bindAddress,
        uint256 bindId,
        uint256 tokenId,
        uint256 amount
    );

    /// @notice This event emits when token(s) of different types are bound to an NFT.
    /// @param operator The address approved to perform the batch binding.
    /// @param from The owner address of the unbound tokens.
    /// @param bindAddress The contract address of the NFTs being bound to.
    /// @param bindId The identifier of the NFT being bound to.
    /// @param tokenIds The identifiers of the binding token types.
    /// @param amounts The number of tokens per type binding to the NFTs.
    event BindBatch(
        address indexed operator,
        address indexed from,
        address indexed bindAddress,
        uint256 bindId,
        uint256[] tokenIds,
        uint256[] amounts
    );

    /// @notice This event emits when token(s) are unbound from an NFT.
    /// @param operator The address approved to perform the unbinding.
    /// @param from The owner address of the NFT the tokens are bound to.
    /// @param to The address of the unbound tokens&apos; new owner.
    /// @param bindAddress The contract address of the NFT being unbound from.
    /// @param bindId The identifier of the NFT being unbound from.
    /// @param tokenId The identifier of the unbinding token type.
    /// @param amount The number of tokens unbinding from the NFT.
    event Unbind(
        address indexed operator,
        address indexed from,
        address to,
        address indexed bindAddress,
        uint256 bindId,
        uint256 tokenId,
        uint256 amount
    );

    /// @notice This event emits when token(s) of different types are unbound from an NFT.
    /// @param operator The address approved to perform the batch binding.
    /// @param from The owner address of the unbound tokens.
    /// @param to The address of the unbound tokens&apos; new owner.
    /// @param bindAddress The contract address of the NFTs being unbound from.
    /// @param bindId The identifier of the NFT being unbound from.
    /// @param tokenIds The identifiers of the unbinding token types.
    /// @param amounts The number of tokens per type unbinding from the NFTs.
    event UnbindBatch(
        address indexed operator,
        address indexed from,
        address to,
        address indexed bindAddress,
        uint256 bindId,
        uint256[] tokenIds,
        uint256[] amounts
    );

    /// @notice Binds `amount` tokens of `tokenId` to NFT `bindId` at address `bindAddress`.
    /// @dev The function MUST throw unless `msg.sender` is an approved operator
    ///  for `from`. It also MUST throw if the `from` owns fewer than `amount`
    ///  tokens. Finally, it MUST throw if the NFT contract does not support the
    ///  ERC-721 interface or if the NFT being bound to does not exist. Before 
    ///  binding, tokens MUST be transferred to the contract address of the NFT. 
    ///  On bind completion, the function MUST emit `Transfer` &amp; `Bind` events 
    ///  to reflect the implicit token transfers and subsequent bind.
    /// @param from The owner address of the unbound tokens.
    /// @param bindAddress The contract address of the NFT being bound to.
    /// @param bindId The identifier of the NFT being bound to.
    /// @param tokenId The identifier of the binding token type.
    /// @param amount The number of tokens binding to the NFT.
    function bind(
        address from,
        address bindAddress,
        uint256 bindId,
        uint256 tokenId,
        uint256 amount
    ) external;

    /// @notice Binds `amounts` tokens of `tokenIds` to NFT `bindId` at address `bindAddress`.
    /// @dev The function MUST throw unless `msg.sender` is an approved operator
    ///  for `from`. It also MUST throw if the length of `amounts` is not the 
    ///  same as `tokenIds`, or if any balances of `tokenIds` for `from` is less
    ///  than that of `amounts`. Finally, it MUST throw if the NFT contract does 
    ///  not support the ERC-721 interface or if the bound NFT does not exist. 
    ///  Before binding, tokens MUST be transferred to the contract address of 
    ///  the NFT. On bind completion, the function MUST emit `TransferBatch` and
    ///  `BindBatch` events to reflect the batch token transfers and bind.
    /// @param from The owner address of the unbound tokens.
    /// @param bindAddress The contract address of the NFTs being bound to.
    /// @param bindId The identifier of the NFT being bound to.
    /// @param tokenIds The identifiers of the binding token types.
    /// @param amounts The number of tokens per type binding to the NFTs.
    function batchBind(
        address from,
        address bindAddress,
        uint256 bindId,
        uint256[] calldata tokenIds,
        uint256[] calldata amounts
    ) external;

    /// @notice Unbinds `amount` tokens of `tokenId` from NFT `bindId` at address `bindAddress`.
    /// @dev The function MUST throw unless `msg.sender` is an approved operator
    ///  for `from`. It also MUST throw if `from` is not the owner of the bound
    ///  NFT, if the NFT&apos;s token balance is fewer than `amount`, or if `to` is 
    ///  the zero address. After unbinding, tokens MUST be transferred to `to`,
    ///  during which the function MUST check if `to` is a valid contract (code 
    ///  size &gt; 0), and if so, call `onERC1155Received`, throwing if the wrong \
    ///  identifier is returned. On unbind completion, the function MUST emit 
    ///  `Unbind` &amp; `Transfer` events to reflect the unbind and transfers.
    /// @param from The owner address of the NFT the tokens are bound to.
    /// @param to The address of the unbound tokens&apos; new owner.
    /// @param bindAddress The contract address of the NFT being unbound from.
    /// @param bindId The identifier of the NFT being unbound from.
    /// @param tokenId The identifier of the unbinding token type.
    /// @param amount The number of tokens unbinding from the NFT.
    function unbind(
        address from,
        address to,
        address bindAddress,
        uint256 bindId,
        uint256 tokenId,
        uint256 amount
    ) external;

    /// @notice Unbinds `amount` tokens of `tokenId` from NFT `bindId` at address `bindAddress`.
    /// @dev The function MUST throw unless `msg.sender` is an approved operator
    ///  for `from`. It also MUST throw if the length of `amounts` is not the
    ///  same as `tokenIds`, if any balances of `tokenIds` for the NFT is less 
    ///  than that of `amounts`, or if `to` is the zero addresss. After 
    ///  unbinding, tokens MUST be transferred to `to`, during which the 
    ///  function MUST check if `to` is a valid contract (code size &gt; 0), and if 
    ///  so, call `onERC1155BatchReceived`, throwing if the wrong identifier is 
    ///  returned. On unbind completion, the function MUST emit `UnbindBatch` &amp; 
    ///  `TransferBatch` events to reflect the batch unbind and transfers.
    /// @param from The owner address of the unbound tokens.
    /// @param to The address of the unbound tokens&apos; new owner.
    /// @param bindAddress The contract address of the NFTs being unbound from.
    /// @param bindId The identifier of the NFT being unbound from.
    /// @param tokenIds The identifiers of the unbinding token types.
    /// @param amounts The number of tokens per type unbinding from the NFTs.
    function batchUnbind(
        address from,
        address to,
        address bindAddress,
        uint256 bindId,
        uint256[] calldata tokenIds,
        uint256[] calldata amounts
    ) external;

    /// @notice Gets the number of tokens of type `tokenId` bound to NFT `bindId` at address `bindAddress`.
    /// @param bindAddress The contract address of the bound NFT.
    /// @param bindId The identifier of the bound NFT.
    /// @param tokenId The identifier of the token type bound to the NFT.
    /// @return The number of tokens of type `tokenId` bound to the NFT.
    function boundBalanceOf(
        address bindAddress,
        uint256 bindId,
        uint256 tokenId
    ) external view returns (uint256);

    /// @notice Gets the number of tokens of types `bindIds` bound to NFTs `bindIds` at address `bindAddress`.
    /// @param bindAddress The contract address of the bound NFTs.
    /// @param bindIds The identifiers of the bound NFTs.
    /// @param tokenIds The identifiers of the token types bound to the NFTs.
    /// @return balances The bound balances for each token type / NFT pair.
    function boundBalanceOfBatch(
        address bindAddress,
        uint256[] calldata bindIds,
        uint256[] calldata tokenIds
    ) external view returns (uint256[] memory balances);

}
```

## Rationale

A standard for token binding unlocks a new layer of composability for allowing wallets, applications, and protocols to interact with, trade, and display bundled NFTs. One example use-case of this is at Dopamine, where streetwear garments may be bundled with digital assets such as music, avatars, or digital-twins of the garments, by representing these assets as bindable tokens and binding them to microchips represented as NFTs.

### Binding Mechanism

During binding, a bindable token&apos;s technical ownership is conferred to its bound NFT, while allowing the NFT owner to unbind at any time. A caveat of this lightweight design is that applications that have yet to adopt this standard will not show the bundled tokens as owned by the NFT owner.

## Backwards Compatibility

The bindable token interface is designed to be compatible with existing ERC-721 and ERC-1155 standards.

## Reference Implementation

- [ERC-721 Bindable](/EIPs/assets/eip-5700/erc721/ERC721Bindable.sol).
- [ERC-1155 Bindable](/EIPs/assets/eip-5700/erc1155/ERC1155Bindable.sol).

## Security Considerations

During binding, because ownership is conferred to the bound NFT contract, implementations should take caution in ensuring unbinding may only be performed by the designated NFT owner.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 22 Sep 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5700</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5700</guid>
      </item>
    
      <item>
        <title>Signature replacement interface</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-signature-replacing-for-smart-contract-wallets/11059</comments>
        
        <description>## Abstract

Smart contract wallet signed messages can become stale, meaning a signature that once was valid could become invalid at any point.

Signatures MAY become stale for reasons like:

* The internal set of signers changed
* The wallet makes signatures expirable
* The contract was updated to a new implementation

The following standard allows smart contract wallets to expose a URI that clients can use to replace a stale signature with a valid one.

## Motivation

In contrast to EOA signatures, [EIP-1271](/EIPs/EIPS/eip-1271) signatures are not necessarily idempotent; they can become invalid at any point in time. This poses a challenge to protocols that rely on signatures remaining valid for extended periods of time.

A signature MAY need to be mutated due to one of the following scenarios:

1. The wallet removes a signer that contributed to signing the initial message.
2. The wallet uses a Merkle tree to store signers, adding a new signer.
3. The wallet uses a Merkle tree to store signatures, adding new signatures.
4. The wallet is updated to a new implementation, and the signature schema changes.

Non-interactive signature replacement SHOULD be possible, since the wallet that originally signed the message MAY NOT be available when the signature needs to be validated. An example use-case is the settlement of a trade in an exchange that uses an off-chain order book.

## Specification

The wallet contract MUST implement the following function:

```solidity
function getAlternativeSignature(bytes32 _digest) external view returns (string);
```

The returned string MUST be a URI pointing to a JSON object with the following schema:

```json
{
    &quot;title&quot;: &quot;Signature alternative&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;blockHash&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;A block.hash on which the signature should be valid.&quot;
        },
        &quot;signature&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;The alternative signature for the given digest.&quot;
        }
    }
}
```

### Client process for replacing a signature

A client is an entity that holds a signature and intends to validate it, either for off-chain or on-chain use. To use the smart contract wallet signature, the client MUST perform the following actions:

1) Try validating the signature using [EIP-1271](/EIPs/EIPS/eip-1271); if the signature is valid, then the signature can be used as-is.
2) If the signature is not valid, call `getAlternativeSignature(_digest)`, passing the `digest` corresponding to the old signature.
3) If the call fails, no URI is returned, or the content of the URI is not valid, then the signature MUST be considered invalid.
4) Try validating the new signature using [EIP-1271](/EIPs/EIPS/eip-1271); if the signature is valid, it can be used as a drop-in replacement of the original signature.
5) If the validation fails, repeat the process from step (2) (notice: if the URI returns the same signature, the signature MUST be considered invalid).

Clients MUST implement a retry limit when fetching alternative signatures. This limit is up to the client to define.

## Rationale

A URI is chosen because it can accommodate centralized and decentralized solutions. For example, a server can implement live re-encoding for Merkle proofs, or an IPFS link could point to a directory with all the pre-computed signature mutations.

The `getAlternativeSignature` method points to an off-chain source because it&apos;s expected that the smart contract wallet doesn&apos;t contain on-chain records for all signed digests, if that were the case then such contract wouldn&apos;t need to use this EIP since it could directly validate the `digest` on`isValidSignature` ignoring the stale signature.

## Backwards Compatibility

Existing wallets that do not implement the `getAlternativeSignature` method can still sign messages without any changes; if any signatures become invalidated, clients will drop them on step (3).

## Security Considerations

Some applications use signatures as secrets; these applications would risk leaking such secrets if the EIP exposes the signatures.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 26 Sep 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5719</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5719</guid>
      </item>
    
      <item>
        <title>Transferable Vesting NFT</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5725-transferable-vesting-nft/11099</comments>
        
        <description>## Abstract

A **Non-Fungible Token** (NFT) standard used to vest tokens ([ERC-20](/EIPs/EIPS/eip-20) or otherwise) over a vesting release curve.

The following standard allows for the implementation of a standard API for NFT based contracts that hold and represent the vested and locked properties of any underlying token ([ERC-20](/EIPs/EIPS/eip-20) or otherwise) that is emitted to the NFT holder. This standard is an extension of the [ERC-721](/EIPs/EIPS/eip-721) token that provides basic functionality for creating vesting NFTs, claiming the tokens and reading vesting curve properties.

## Motivation

Vesting contracts, including timelock contracts, lack a standard and unified interface, which results in diverse implementations of such contracts. Standardizing such contracts into a single interface would allow for the creation of an ecosystem of on- and off-chain tooling around these contracts. In addition, liquid vesting in the form of non-fungible assets can prove to be a huge improvement over traditional **Simple Agreement for Future Tokens** (SAFTs) or **Externally Owned Account** (EOA)-based vesting as it enables transferability and the ability to attach metadata similar to the existing functionality offered by with traditional NFTs.

Such a standard will not only provide a much-needed [ERC-20](/EIPs/EIPS/eip-20) token lock standard, but will also enable the creation of secondary marketplaces tailored for semi-liquid SAFTs.

This standard also allows for a variety of different vesting curves to be implement easily.

These curves could represent:

- linear vesting
- cliff vesting
- exponential vesting
- custom deterministic vesting

### Use Cases

1. A framework to release tokens over a set period of time that can be used to build many kinds of NFT financial products such as bonds, treasury bills, and many others.
2. Replicating SAFT contracts in a standardized form of semi-liquid vesting NFT assets.
   - SAFTs are generally off-chain, while today&apos;s on-chain versions are mainly address-based, which makes distributing vesting shares to many representatives difficult. Standardization simplifies this convoluted process.
3. Providing a path for the standardization of vesting and token timelock contracts.
   - There are many such contracts in the wild and most of them differ in both interface and implementation.
4. NFT marketplaces dedicated to vesting NFTs.
   - Whole new sets of interfaces and analytics could be created from a common standard for token vesting NFTs.
5. Integrating vesting NFTs into services like Safe Wallet.
   - A standard would mean services like Safe Wallet could more easily and uniformly support interactions with these types of contracts inside of a multisig contract.
6. Enable standardized fundraising implementations and general fundraising that sell vesting tokens (eg. SAFTs) in a more transparent manner.
7. Allows tools, front-end apps, aggregators, etc. to show a more holistic view of the vesting tokens and the properties available to users.
   - Currently, every project needs to write their own visualization of the vesting schedule of their vesting assets. If this is standardized, third-party tools could be developed to aggregate all vesting NFTs from all projects for the user, display their schedules and allow the user to take aggregated vesting actions.
   - Such tooling can easily discover compliance through the [ERC-165](/EIPs/EIPS/eip-165) `supportsInterface(InterfaceID)` check.
8. Makes it easier for a single wrapping implementation to be used across all vesting standards that defines multiple recipients, periodic renting of vesting tokens etc.

## Specification

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.

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;
import &quot;@openzeppelin/contracts/token/ERC721/IERC721.sol&quot;;

/**
 * @title Non-Fungible Vesting Token Standard.
 * @notice A non-fungible token standard used to vest ERC-20 tokens over a vesting release curve 
 *  scheduled using timestamps.
 * @dev Because this standard relies on timestamps for the vesting schedule, it&apos;s important to keep track of the 
 *  tokens claimed per Vesting NFT so that a user cannot withdraw more tokens than allotted for a specific Vesting NFT.
 * @custom:interface-id 0xbd3a202b
 */
interface IERC5725 is IERC721 {
    /**
     *  This event is emitted when the payout is claimed through the claim function.
     *  @param tokenId the NFT tokenId of the assets being claimed.
     *  @param recipient The address which is receiving the payout.
     *  @param claimAmount The amount of tokens being claimed.
     */
    event PayoutClaimed(uint256 indexed tokenId, address indexed recipient, uint256 claimAmount);

    /**
     *  This event is emitted when an `owner` sets an address to manage token claims for all tokens.
     *  @param owner The address setting a manager to manage all tokens.
     *  @param spender The address being permitted to manage all tokens.
     *  @param approved A boolean indicating whether the spender is approved to claim for all tokens.
     */
    event ClaimApprovalForAll(address indexed owner, address indexed spender, bool approved);

    /**
     *  This event is emitted when an `owner` sets an address to manage token claims for a `tokenId`.
     *  @param owner The `owner` of `tokenId`.
     *  @param spender The address being permitted to manage a tokenId.
     *  @param tokenId The unique identifier of the token being managed.
     *  @param approved A boolean indicating whether the spender is approved to claim for `tokenId`.
     */
    event ClaimApproval(address indexed owner, address indexed spender, uint256 indexed tokenId, bool approved);

    /**
     * @notice Claim the pending payout for the NFT.
     * @dev MUST grant the claimablePayout value at the time of claim being called to `msg.sender`. 
     *  MUST revert if not called by the token owner or approved users. 
     *  MUST emit PayoutClaimed. 
     *  SHOULD revert if there is nothing to claim.
     * @param tokenId The NFT token id.
     */
    function claim(uint256 tokenId) external;

    /**
     * @notice Number of tokens for the NFT which have been claimed at the current timestamp.
     * @param tokenId The NFT token id.
     * @return payout The total amount of payout tokens claimed for this NFT.
     */
    function claimedPayout(uint256 tokenId) external view returns (uint256 payout);

    /**
     * @notice Number of tokens for the NFT which can be claimed at the current timestamp.
     * @dev It is RECOMMENDED that this is calculated as the `vestedPayout()` subtracted from `payoutClaimed()`.
     * @param tokenId The NFT token id.
     * @return payout The amount of unlocked payout tokens for the NFT which have not yet been claimed.
     */
    function claimablePayout(uint256 tokenId) external view returns (uint256 payout);

    /**
     * @notice Total amount of tokens which have been vested at the current timestamp. 
     *  This number also includes vested tokens which have been claimed.
     * @dev It is RECOMMENDED that this function calls `vestedPayoutAtTime` 
     *  with `block.timestamp` as the `timestamp` parameter.
     * @param tokenId The NFT token id.
     * @return payout Total amount of tokens which have been vested at the current timestamp.
     */
    function vestedPayout(uint256 tokenId) external view returns (uint256 payout);

    /**
     * @notice Total amount of vested tokens at the provided timestamp. 
     *  This number also includes vested tokens which have been claimed.
     * @dev `timestamp` MAY be both in the future and in the past. 
     *  Zero MUST be returned if the timestamp is before the token was minted.
     * @param tokenId The NFT token id.
     * @param timestamp The timestamp to check on, can be both in the past and the future.
     * @return payout Total amount of tokens which have been vested at the provided timestamp.
     */
    function vestedPayoutAtTime(uint256 tokenId, uint256 timestamp) external view returns (uint256 payout);

    /**
     * @notice Number of tokens for an NFT which are currently vesting.
     * @dev The sum of vestedPayout and vestingPayout SHOULD always be the total payout.
     * @param tokenId The NFT token id.
     * @return payout The number of tokens for the NFT which are vesting until a future date.
     */
    function vestingPayout(uint256 tokenId) external view returns (uint256 payout);

    /**
     * @notice The start and end timestamps for the vesting of the provided NFT. 
     *  MUST return the timestamp where no further increase in vestedPayout occurs for `vestingEnd`.
     * @param tokenId The NFT token id.
     * @return vestingStart The beginning of the vesting as a unix timestamp.
     * @return vestingEnd The ending of the vesting as a unix timestamp.
     */
    function vestingPeriod(uint256 tokenId) external view returns (uint256 vestingStart, uint256 vestingEnd);

    /**
     * @notice Token which is used to pay out the vesting claims.
     * @param tokenId The NFT token id.
     * @return token The token which is used to pay out the vesting claims.
     */
    function payoutToken(uint256 tokenId) external view returns (address token);

    /**
     * @notice Sets a global `operator` with permission to manage all tokens owned by the current `msg.sender`.
     * @param operator The address to let manage all tokens.
     * @param approved A boolean indicating whether the spender is approved to claim for all tokens.
     */
    function setClaimApprovalForAll(address operator, bool approved) external;

    /**
     * @notice Sets a tokenId `operator` with permission to manage a single `tokenId` owned by the `msg.sender`.
     * @param operator The address to let manage a single `tokenId`.
     * @param tokenId the `tokenId` to be managed.
     * @param approved A boolean indicating whether the spender is approved to claim for all tokens.
     */
    function setClaimApproval(address operator, bool approved, uint256 tokenId) external;

    /**
     * @notice Returns true if `owner` has set `operator` to manage all `tokenId`s.
     * @param owner The owner allowing `operator` to manage all `tokenId`s.
     * @param operator The address who is given permission to spend tokens on behalf of the `owner`.
     */
    function isClaimApprovedForAll(address owner, address operator) external view returns (bool isClaimApproved);

    /**
     * @notice Returns the operating address for a `tokenId`. 
     *  If `tokenId` is not managed, then returns the zero address.
     * @param tokenId The NFT `tokenId` to query for a `tokenId` manager.
     */
    function getClaimApproved(uint256 tokenId) external view returns (address operator);
}

```

## Rationale

### Terms

These are base terms used around the specification which function names and definitions are based on.

- _vesting_: Tokens which a vesting NFT is vesting until a future date.
- _vested_: Total amount of tokens a vesting NFT has vested.
- _claimable_: Amount of vested tokens which can be unlocked.
- _claimed_: Total amount of tokens unlocked from a vesting NFT.
- _timestamp_: The unix `timestamp` (seconds) representation of dates used for vesting.

### Vesting Functions

**`vestingPayout` + `vestedPayout`**

`vestingPayout(uint256 tokenId)` and `vestedPayout(uint256 tokenId)` add up to the total number of tokens which can be claimed by the end of the vesting schedule. This is also equal to `vestedPayoutAtTime(uint256 tokenId, uint256 timestamp)` with `type(uint256).max` as the `timestamp`.

The rationale for this is to guarantee that the tokens `vested` and tokens `vesting` are always in sync. The intent is that the vesting curves created are deterministic across the `vestingPeriod`. This creates useful opportunities for integration with these NFTs. For example: A vesting schedule can be iterated through and a vesting curve could be visualized, either on-chain or off-chain.

**`vestedPayout` vs `claimedPayout` &amp; `claimablePayout`**

```solidity
vestedPayout - claimedPayout - claimablePayout = lockedPayout
```

- `vestedPayout(uint256 tokenId)` provides the total amount of payout tokens which have **vested** _including `claimedPayout(uint256 tokenId)`_.
- `claimedPayout(uint256 tokenId)` provides the total amount of payout tokens which have been unlocked at the current `timestamp`.
- `claimablePayout(uint256 tokenId)` provides the amount of payout tokens which can be unlocked at the current `timestamp`.

The rationale for providing three functions is to support a number of features:

1. The return of `vestedPayout(uint256 tokenId)` will always match the return of `vestedPayoutAtTime(uint256 tokenId, uint256 timestamp)` with `block.timestamp` as the `timestamp`.
2. `claimablePayout(uint256 tokenId)` can be used to easily see the current payout unlock amount and allow for unlock cliffs by returning zero until a `timestamp` has been passed.
3. `claimedPayout(uint256 tokenId)` is helpful to see tokens unlocked from an NFT and it is also necessary for the calculation of vested-but-locked payout tokens: `vestedPayout - claimedPayout - claimablePayout = lockedPayout`. This would depend on how the vesting curves are configured by the an implementation of this standard.

`vestedPayoutAtTime(uint256 tokenId, uint256 timestamp)` provides functionality to iterate through the `vestingPeriod(uint256 tokenId)` and provide a visual of the release curve. The intent is that release curves are created which makes `vestedPayoutAtTime(uint256 tokenId, uint256 timestamp)` deterministic.

### Timestamps

Generally in Solidity development it is advised against using `block.timestamp` as a state dependent variable as the timestamp of a block can be manipulated by a miner. The choice to use a `timestamp` over a `block` is to allow the interface to work across multiple **Ethereum Virtual Machine** (EVM) compatible networks which generally have different block times. Block proposal with a significantly fabricated timestamp will generally be dropped by all node implementations which makes the window for abuse negligible.

The `timestamp` makes cross chain integration easy, but internally, the reference implementation keeps track of the token payout per Vesting NFT to ensure that excess tokens allotted by the vesting terms cannot be claimed.

### Limitation of Scope

- **Historical claims**: While historical vesting schedules can be determined on-chain with `vestedPayoutAtTime(uint256 tokenId, uint256 timestamp)`, historical claims would need to be calculated through historical transaction data. Most likely querying for `PayoutClaimed` events to build a historical graph.

### Extension Possibilities

These feature are not supported by the standard as is, but the standard could be extended to support these more advanced features.

- **Custom Vesting Curves**: This standard intends on returning deterministic `vesting` values given NFT `tokenId` and a **timestamp** as inputs. This is intentional as it provides for flexibility in how the vesting curves work under the hood which doesn&apos;t constrain projects who intend on building a complex smart contract vesting architecture.
- **NFT Rentals**: Further complex DeFi tools can be created if vesting NFTs could be rented.

This is done intentionally to keep the base standard simple. These features can and likely will be added through extensions of this standard.

## Backwards Compatibility

- The Vesting NFT standard is meant to be fully backwards compatible with any current [ERC-721](/EIPs/EIPS/eip-721) integrations and marketplaces.
- The Vesting NFT standard also supports [ERC-165](/EIPs/EIPS/eip-165) interface detection for detecting `EIP-721` compatibility, as well as Vesting NFT compatibility.

## Test Cases

The reference vesting NFT repository includes tests written in Hardhat.

## Reference Implementation

A reference implementation of this EIP can be found in [ERC-5725 assets](/EIPs/assets/eip-5725/).

## Security Considerations

**timestamps**

- Vesting schedules are based on timestamps. As such, it&apos;s important to keep track of the number of tokens which have been claimed and to not give out more tokens than allotted for a specific Vesting NFT.
  - `vestedPayoutAtTime(tokenId, type(uint256).max)`, for example, must return the total payout for a given `tokenId`

**approvals**

- When an [ERC-721](/EIPs/EIPS/eip-721) approval is made on a Vesting NFT, the operator would have the rights to transfer the Vesting NFT to themselves and then claim the vested tokens.
- When a ERC-5725 approval is made on a Vesting NFT, the operator would have the rights to claim the vested tokens, but not transfer the NFT away from the owner.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 08 Sep 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5725</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5725</guid>
      </item>
    
      <item>
        <title>Semi-Fungible Soulbound Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5727-semi-fungible-soulbound-token/11086</comments>
        
        <description>## Abstract

An interface for soulbound tokens (SBT), which are non-transferable tokens representing a person&apos;s identity, credentials, affiliations, and reputation.

Our interface can handle a combination of fungible and non-fungible tokens in an organized way. It provides a set of core methods that can be used to manage the lifecycle of soulbound tokens, as well as a rich set of extensions that enables DAO governance, delegation, token expiration, and account recovery.

This interface aims to provide a flexible and extensible framework for the development of soulbound token systems.

## Motivation

The current Web3 ecosystem is heavily focused on financialized, transferable tokens. However, there&apos;s a growing need for non-transferable tokens to represent unique personal attributes and rights. Existing attempts within the Ethereum community to create such tokens lack the necessary flexibility and extensibility. Our interface addresses this gap, offering a versatile and comprehensive solution for SBTs.

Our interface can be used to represent non-transferable ownerships, and provides features for common use cases including but not limited to:

- Lifecycle Management: Robust tools for minting, revocation, and managing the subscription and expiration of SBTs.
- DAO Governance and Delegation: Empower community-driven decisions and operational delegation for SBT management.
- Account Recovery: Advanced mechanisms for account recovery and key rotation, ensuring security and continuity.
- Versatility in Tokens: Support for both fungible and non-fungible SBTs, catering to a wide range of use cases like membership cards and loyalty programs.
- Token Grouping: Innovative slot-based system for organizing SBTs, ideal for complex reward structures including vouchers, points, and badges.
- Claimable SBTs: Streamlined distribution of SBTs for airdrops, giveaways, and referral programs.

This interface not only enriches the Web3 landscape but also paves the way for a more decentralized and personalized digital society.

## Specification

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.

A token is identified by its `tokenId`, which is a 256-bit unsigned integer. A token can also have a value denoting its denomination.

A slot is identified by its `slotId`, which is a 256-bit unsigned integer. Slots are used to group fungible and non-fungible tokens together, thus make tokens semi-fungible. A token can only belong to one slot at a time.

### Core

The core methods are used to manage the lifecycle of SBTs. They MUST be supported by all semi-fungible SBT implementations.

```solidity
/**
 * @title ERC5727 Soulbound Token Interface
 * @dev The core interface of the ERC5727 standard.
 */
interface IERC5727 is IERC3525, IERC5192, IERC5484, IERC4906 {
    /**
     * @dev MUST emit when a token is revoked.
     * @param from The address of the owner
     * @param tokenId The token id
     */
    event Revoked(address indexed from, uint256 indexed tokenId);

    /**
     * @dev MUST emit when a token is verified.
     * @param by The address that initiated the verification
     * @param tokenId The token id
     * @param result The result of the verification
     */
    event Verified(address indexed by, uint256 indexed tokenId, bool result);

    /**
     * @notice Get the verifier of a token.
     * @dev MUST revert if the `tokenId` does not exist
     * @param tokenId the token for which to query the verifier
     * @return The address of the verifier of `tokenId`
     */
    function verifierOf(uint256 tokenId) external view returns (address);

    /**
     * @notice Get the issuer of a token.
     * @dev MUST revert if the `tokenId` does not exist
     * @param tokenId the token for which to query the issuer
     * @return The address of the issuer of `tokenId`
     */
    function issuerOf(uint256 tokenId) external view returns (address);

    /**
     * @notice Issue a token in a specified slot to an address.
     * @dev MUST revert if the `to` address is the zero address.
     *      MUST revert if the `verifier` address is the zero address.
     * @param to The address to issue the token to
     * @param tokenId The token id
     * @param slot The slot to issue the token in
     * @param burnAuth The burn authorization of the token
     * @param verifier The address of the verifier
     * @param data Additional data used to issue the token
     */
    function issue(
        address to,
        uint256 tokenId,
        uint256 slot,
        BurnAuth burnAuth,
        address verifier,
        bytes calldata data
    ) external payable;

    /**
     * @notice Issue credit to a token.
     * @dev MUST revert if the `tokenId` does not exist.
     * @param tokenId The token id
     * @param amount The amount of the credit
     * @param data The additional data used to issue the credit
     */
    function issue(
        uint256 tokenId,
        uint256 amount,
        bytes calldata data
    ) external payable;

    /**
     * @notice Revoke a token from an address.
     * @dev MUST revert if the `tokenId` does not exist.
     * @param tokenId The token id
     * @param data The additional data used to revoke the token
     */
    function revoke(uint256 tokenId, bytes calldata data) external payable;

    /**
     * @notice Revoke credit from a token.
     * @dev MUST revert if the `tokenId` does not exist.
     * @param tokenId The token id
     * @param amount The amount of the credit
     * @param data The additional data used to revoke the credit
     */
    function revoke(
        uint256 tokenId,
        uint256 amount,
        bytes calldata data
    ) external payable;

    /**
     * @notice Verify if a token is valid.
     * @dev MUST revert if the `tokenId` does not exist.
     * @param tokenId The token id
     * @param data The additional data used to verify the token
     * @return A boolean indicating whether the token is successfully verified
     */
    function verify(
        uint256 tokenId,
        bytes calldata data
    ) external returns (bool);
}
```

### Extensions

All extensions below are OPTIONAL for [ERC-5727](/EIPs/EIPS/eip-5727) implementations. An implementation MAY choose to implement some, none, or all of them.

#### Enumerable

This extension provides methods to enumerate the tokens of a owner. It is recommended to be implemented together with the core interface.

```solidity
/**
 * @title ERC5727 Soulbound Token Enumerable Interface
 * @dev This extension allows querying the tokens of a owner.
 */
interface IERC5727Enumerable is IERC3525SlotEnumerable, IERC5727 {
    /**
     * @notice Get the number of slots of a owner.
     * @param owner The owner whose number of slots is queried for
     * @return The number of slots of the `owner`
     */
    function slotCountOfOwner(address owner) external view returns (uint256);

    /**
     * @notice Get the slot with `index` of the `owner`.
     * @dev MUST revert if the `index` exceed the number of slots of the `owner`.
     * @param owner The owner whose slot is queried for.
     * @param index The index of the slot queried for
     * @return The slot is queried for
     */
    function slotOfOwnerByIndex(
        address owner,
        uint256 index
    ) external view returns (uint256);

    /**
     * @notice Get the balance of a owner in a slot.
     * @dev MUST revert if the slot does not exist.
     * @param owner The owner whose balance is queried for
     * @param slot The slot whose balance is queried for
     * @return The balance of the `owner` in the `slot`
     */
    function ownerBalanceInSlot(
        address owner,
        uint256 slot
    ) external view returns (uint256);
}
```

#### Metadata

This extension provides methods to fetch the metadata of a token, a slot and the contract itself. It is recommended to be implemented if you need to specify the appearance and properties of tokens, slots and the contract (i.e. the SBT collection).

```solidity
/**
 * @title ERC5727 Soulbound Token Metadata Interface
 * @dev This extension allows querying the metadata of soulbound tokens.
 */
interface IERC5727Metadata is IERC3525Metadata, IERC5727 {

}
```

#### Governance

This extension provides methods to manage the mint and revocation permissions through voting. It is useful if you want to rely on a group of voters to decide the issuance a particular SBT.

```solidity
/**
 * @title ERC5727 Soulbound Token Governance Interface
 * @dev This extension allows issuing of tokens by community voting.
 */
interface IERC5727Governance is IERC5727 {
    enum ApprovalStatus {
        Pending,
        Approved,
        Rejected,
        Removed
    }

    /**
     * @notice Emitted when a token issuance approval is changed.
     * @param approvalId The id of the approval
     * @param creator The creator of the approval, zero address if the approval is removed
     * @param status The status of the approval
     */
    event ApprovalUpdate(
        uint256 indexed approvalId,
        address indexed creator,
        ApprovalStatus status
    );

    /**
     * @notice Emitted when a voter approves an approval.
     * @param voter The voter who approves the approval
     * @param approvalId The id of the approval
     */
    event Approve(
        address indexed voter,
        uint256 indexed approvalId,
        bool approve
    );

    /**
     * @notice Create an approval of issuing a token.
     * @dev MUST revert if the caller is not a voter.
     *      MUST revert if the `to` address is the zero address.
     * @param to The owner which the token to mint to
     * @param tokenId The id of the token to mint
     * @param amount The amount of the token to mint
     * @param slot The slot of the token to mint
     * @param burnAuth The burn authorization of the token to mint
     * @param data The additional data used to mint the token
     */
    function requestApproval(
        address to,
        uint256 tokenId,
        uint256 amount,
        uint256 slot,
        BurnAuth burnAuth,
        address verifier,
        bytes calldata data
    ) external;

    /**
     * @notice Remove `approvalId` approval request.
     * @dev MUST revert if the caller is not the creator of the approval request.
     *      MUST revert if the approval request is already approved or rejected or non-existent.
     * @param approvalId The approval to remove
     */
    function removeApprovalRequest(uint256 approvalId) external;

    /**
     * @notice Approve `approvalId` approval request.
     * @dev MUST revert if the caller is not a voter.
     *     MUST revert if the approval request is already approved or rejected or non-existent.
     * @param approvalId The approval to approve
     * @param approve True if the approval is approved, false if the approval is rejected
     * @param data The additional data used to approve the approval (e.g. the signature, voting power)
     */
    function voteApproval(
        uint256 approvalId,
        bool approve,
        bytes calldata data
    ) external;

    /**
     * @notice Get the URI of the approval.
     * @dev MUST revert if the `approvalId` does not exist.
     * @param approvalId The approval whose URI is queried for
     * @return The URI of the approval
     */
    function approvalURI(
        uint256 approvalId
    ) external view returns (string memory);
}
```

#### Delegate

This extension provides methods to delegate (undelegate) mint right in a slot to (from) an operator. It is useful if you want to allow an operator to mint tokens in a specific slot on your behalf.

```solidity
/**
 * @title ERC5727 Soulbound Token Delegate Interface
 * @dev This extension allows delegation of issuing and revocation of tokens to an operator.
 */
interface IERC5727Delegate is IERC5727 {
    /**
     * @notice Emitted when a token issuance is delegated to an operator.
     * @param operator The owner to which the issuing right is delegated
     * @param slot The slot to issue the token in
     */
    event Delegate(address indexed operator, uint256 indexed slot);

    /**
     * @notice Emitted when a token issuance is revoked from an operator.
     * @param operator The owner to which the issuing right is delegated
     * @param slot The slot to issue the token in
     */
    event UnDelegate(address indexed operator, uint256 indexed slot);

    /**
     * @notice Delegate rights to `operator` for a slot.
     * @dev MUST revert if the caller does not have the right to delegate.
     *      MUST revert if the `operator` address is the zero address.
     *      MUST revert if the `slot` is not a valid slot.
     * @param operator The owner to which the issuing right is delegated
     * @param slot The slot to issue the token in
     */
    function delegate(address operator, uint256 slot) external;

    /**
     * @notice Revoke rights from `operator` for a slot.
     * @dev MUST revert if the caller does not have the right to delegate.
     *      MUST revert if the `operator` address is the zero address.
     *      MUST revert if the `slot` is not a valid slot.
     * @param operator The owner to which the issuing right is delegated
     * @param slot The slot to issue the token in
     */

    function undelegate(address operator, uint256 slot) external;

    /**
     * @notice Check if an operator has the permission to issue or revoke tokens in a slot.
     * @param operator The operator to check
     * @param slot The slot to check
     */
    function isOperatorFor(
        address operator,
        uint256 slot
    ) external view returns (bool);
}

```

#### Recovery

This extension provides methods to recover tokens from a stale owner. It is recommended to use this extension so that users are able to retrieve their tokens from a compromised or old wallet in certain situations. The signing scheme SHALL be compatible with [EIP-712](/EIPs/EIPS/eip-712) for readability and usability.

```solidity
/**
 * @title ERC5727 Soulbound Token Recovery Interface
 * @dev This extension allows recovering soulbound tokens from an address provided its signature.
 */
interface IERC5727Recovery is IERC5727 {
    /**
     * @notice Emitted when the tokens of `owner` are recovered.
     * @param from The owner whose tokens are recovered
     * @param to The new owner of the tokens
     */
    event Recovered(address indexed from, address indexed to);

    /**
     * @notice Recover the tokens of `owner` with `signature`.
     * @dev MUST revert if the signature is invalid.
     * @param owner The owner whose tokens are recovered
     * @param signature The signature signed by the `owner`
     */
    function recover(address owner, bytes memory signature) external;
}
```

#### Expirable

This extension provides methods to manage the expiration of tokens. It is useful if you want to expire/invalidate tokens after a certain period of time.

```solidity
/**
 * @title ERC5727 Soulbound Token Expirable Interface
 * @dev This extension allows soulbound tokens to be expirable and renewable.
 */
interface IERC5727Expirable is IERC5727, IERC5643 {
    /**
     * @notice Set the expiry date of a token.
     * @dev MUST revert if the `tokenId` token does not exist.
     *      MUST revert if the `date` is in the past.
     * @param tokenId The token whose expiry date is set
     * @param expiration The expire date to set
     * @param isRenewable Whether the token is renewable
     */
    function setExpiration(
        uint256 tokenId,
        uint64 expiration,
        bool isRenewable
    ) external;
}
```

## Rationale

### Token storage model

We adopt semi-fungible token storage models designed to support both fungible and non-fungible tokens, inspired by the semi-fungible token standard. We found that such a model is better suited to the representation of SBT than the model used in [ERC-1155](/EIPs/EIPS/eip-1155).

Firstly, each slot can be used to represent different categories of SBTs. For instance, a DAO can have membership SBTs, role badges, reputations, etc. in one SBT collection.

Secondly, unlike [ERC-1155](/EIPs/EIPS/eip-1155), in which each unit of fungible tokens is exactly the same, our interface can help differentiate between similar tokens. This is justified by that credential scores obtained from different entities differ not only in value but also in their effects, validity periods, origins, etc. However, they still share the same slot as they all contribute to a person&apos;s credibility, membership, etc.

### Recovery mechanism

To prevent the loss of SBTs, we propose a recovery mechanism that allows users to recover their tokens by providing a signature signed by their owner address. This mechanism is inspired by [ERC-1271](/EIPs/EIPS/eip-1271).

Since SBTs are bound to an address and are meant to represent the identity of the address, which cannot be split into fractions. Therefore, each recovery should be considered as a transfer of all the tokens of the owner. This is why we use the `recover` function instead of `transferFrom` or `safeTransferFrom`.

## Backwards Compatibility

This EIP proposes a new token interface which is compatible with [ERC-721](/EIPs/EIPS/eip-721), [ERC-3525](/EIPs/EIPS/eip-3525), [ERC-4906](/EIPs/EIPS/eip-4906), [ERC-5192](/EIPs/EIPS/eip-5192), [ERC-5484](/EIPs/EIPS/eip-5484).

This EIP is also compatible with [ERC-165](/EIPs/EIPS/eip-165).

## Test Cases

Our sample implementation includes test cases written using Hardhat.

## Reference Implementation

You can find our reference implementation [here](/EIPs/assets/eip-5727/ERC5727.sol).

## Security Considerations

This EIP does not involve the general transfer of tokens, and thus there will be no security issues related to token transfer generally.

However, users should be aware of the security risks of using the recovery mechanism. If a user loses his/her private key, all his/her soulbound tokens will be exposed to potential theft. The attacker can create a signature and restore all SBTs of the victim. Therefore, users should always keep their private keys safe. We recommend developers implement a recovery mechanism that requires multiple signatures to restore SBTs.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 28 Sep 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5727</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5727</guid>
      </item>
    
      <item>
        <title>Commit Interface</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-5732-simple-commit-interface-to-support-commit-reveal-schemes/11115</comments>
        
        <description>## Abstract

A simple commit interface to support commit-reveal scheme which provides **only** a commit
method but no reveal method, allowing implementations to integrate this interface
with arbitrary reveal methods such as `vote` or `transfer`.

## Motivation

1. support commit-reveal privacy for applications such as voting.
2. make it harder for attackers for front-running, back-running or sandwich attacks.

## Specification

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.

Interfaces referenced in this specification are as follows:

```solidity
pragma solidity &gt;=0.7.0 &lt;0.9.0;

// The EIP-165 identifier of this interface is 0xf14fcbc8
interface IERC_COMMIT_CORE {
    function commit(bytes32 _commitment) payable external;
}

pragma solidity &gt;=0.7.0 &lt;0.9.0;

// The EIP-165 identifier of this interface is 0x67b2ec2c
interface IERC_COMMIT_GENERAL {
    event Commit(
        uint256 indexed _timePoint,
        address indexed _from,
        bytes32 indexed _commitment,
        bytes _extraData);
    function commitFrom(
        address _from,
        bytes32 _commitment,
        bytes calldata _extraData)
    payable external returns(uint256 timePoint);
}
```

1. A compliant contract MUST implement the `IERC_COMMIT_CORE` interface.
2. A compliant contract SHOULD implement the `IERC_COMMIT_GENERAL` interface.
3. A compliant contract that implements the `IERC_COMMIT_GENERAL` interface MUST accept `commit(_commitment)` as equivalent to `commitFrom(msg.sender, _commitment, [/*empty array*/])`.
4. The `timePoint` return value of `commitFrom` is RECOMMENDED to use `block.timestamp` or `block.number` or a number that indicates the ordering of different commitments. When `commitFrom` is being called.
5. A compliant contract that implements `IERC_COMMIT_GENERAL` MUST emit event `Commit` when a commitment is accepted and recorded. In the parameter of both `Commit` and the `commitFrom` method, the `_timePoint` is a time-point-representing value that represents ordering of commitments in which a latter commitment will always have a _greater or equal value_ than a former commitment, such as `block.timestamp` or `block.number` or other time scale chosen by implementing contracts.

6. The `extraData` is reserved for future behavior extension. If the `_from` is different from the TX signer, it is RECOMMENDED that compliant contract SHOULD validate signature for `_from`. For EOAs this will be validating its ECDSA signatures on chain. For smart contract accounts, it is RECOMMENDED to use [EIP-1271](/EIPs/EIPS/eip-1271) to validate the signatures.

7. One or more methods of a compliant contract MAY be used for reveal.

But there MUST be a way to supply an extra field of `secret_salt`, so that committer can later open the `secret_salt` in the reveal TX that exposes the `secret_salt`. The size and location of `secret_salt` is intentionally unspecified in this EIP to maximize flexibility for integration.

8. It is RECOMMENDED for compliant contracts to implement [EIP-165](/EIPs/EIPS/eip-165).

## Rationale

1. One design options is that we can attach a Commit Interface to any individual ERCs such as voting standards or token standards. We choose to have a simple and generalize commit interface so all ERCs can be extended to support commit-reveal without changing their basic method signatures.

2. The key derived design decision we made is we will have  a standardized `commit` method without a standardized `reveal` method, making room for customized reveal method or using `commit` with existing standard.

3. We chose to have a simple one parameter method of `commit` in our Core interface to make it fully backward compatible with a few prior-adoptions e.g. ENS

4. We also add a `commitFrom` to easy commitment being generated off-chain and submitted by some account on behalf by another account.

## Backwards Compatibility

This EIP is backward compatible with all existing ERCs method signature that has extraData. New EIPs can be designed with an extra field of &quot;salt&quot; to make it easier to support this EIP, but not required.

The `IERC_COMMIT_CORE` is backward compatible with ENS implementations and other existing prior-art.

## Reference Implementation

### Commit with ENS Register as Reveal

In ENS registering process, currently inside of `ETHRegistrarController` contract a commit function is being used to allow registerer fairly register a desire domain to avoid being front-run.

Here is how ENS uses commitment in its registration logic:

```solidity
function commit(bytes32 commitment) public {
    require(commitments[commitment] + maxCommitmentAge &lt; now);
    commitments[commitment] = now;
}
```

With this EIP it can be updated to

```solidity
function commit(bytes32 commitment, bytes calldata data) public {
    require(commitments[commitment] + maxCommitmentAge &lt; now);
    commitments[commitment] = now;
    emit Commit(...);
}
```

## Security Considerations

1. Do not use the reference implementation in production. It is just for demonstration purposes.
2. The reveal transactions and parameters, especially `secret_salt`, MUST be kept secret before they are revealed.
3. The length of `secret_salt` must be cryptographically long enough and the random values used to generate `secret_salt` must be cryptographically safe.
4. Users must NEVER reuse a used `secret_salt`. It&apos;s recommended for client applications to warn users who attempt to do so.
5. Contract implementations should consider deleting the commitment of a given sender immediately to reduce the chances of a replay attack or re-entry attack.
6. Contract implementations may consider including the ordering of commitment received to add restrictions on the order of reveal transactions.
7. There is potential for replay attacks across different chainIds or chains resulting from forks. In these cases, the chainId must be included in the generation of commitment. For applications with a higher risk of replay attacks, implementors should consider battle-tested and cryptographically-secure solutions such as [EIP-712](/EIPs/EIPS/eip-712) to compose commitments before creating their own new solution.
8. Proper time gaps are suggested if the purpose is to avoid frontrunning attacks.
9. For compliant contract that requires the `_timePoint` from the next transaction to be _strictly greater_ than that of any previous transaction, `block.timestamp` and `block.number` are not reliable as two transactions could co-exist in the same block resulting in the same `_timePoint` value. In such case, extra measures to enforce this strict monotonicity are required, such as the use of a separate sate variable in the contract to keep track of number of commits it receives, or to reject any second/other TX that shares the same `block.timestamp` or `block.number`.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 29 Sep 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5732</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5732</guid>
      </item>
    
      <item>
        <title>Latent Fungible Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5744-latent-fungible-token/11111</comments>
        
        <description>## Abstract

The following standard is an extension of [EIP-20](/EIPs/EIPS/eip-20) that enables tokens to become fungible after some initial non-fungible period.
Once minted, tokens are non-fungible until they reach maturity.
At maturity, they become fungible and can be transferred, traded, and used in any way that a standard EIP-20 token can be used.

## Motivation

Example use cases include:

- Receipt tokens that do not become active until a certain date or condition is met. For example, this can be used to enforce minimum deposit durations in lending protocols.
- Vesting tokens that cannot be transferred or used until the vesting period has elapsed.

## Specification

All latent fungible tokens MUST implement EIP-20 to represent the token.
The `balanceOf` and `totalSupply` return quantities for all tokens, not just the matured, fungible tokens.
A new method called `balanceOfMatured` MUST be added to the ABI.
This method returns the balance of matured tokens for a given address:

```solidity
function balanceOfMatured(address user) external view returns (uint256);
```

An additional method called `getMints` MUST be added, which returns an array of all mint metadata for a given address:

```solidity
struct MintMetadata {
  // Amount of tokens minted.
  uint256 amount;
  // Timestamp of the mint, in seconds.
  uint256 time;
  // Delay in seconds until these tokens mature and become fungible. When the
  // delay is not known (e.g. if it&apos;s dependent on other factors aside from
  // simply elapsed time), this value must be `type(uint256).max`.
  uint256 delay;
}

function getMints(address user) external view returns (MintMetadata[] memory);
```

Note that the implementation does not require that each of the above metadata parameters are stored as a `uint256`, just that they are returned as `uint256`.

An additional method called `mints` MAY be added.
This method returns the metadata for a mint based on its ID:

```solidity
function mints(address user, uint256 id) external view returns (MintMetadata memory);
```

The ID is not prescriptive—it may be an index in an array, or may be generated by other means.

The `transfer` and `transferFrom` methods MAY be modified to revert when transferring tokens that have not matured.
Similarly, any methods that burn tokens MAY be modified to revert when burning tokens that have not matured.

All latent fungible tokens MUST implement EIP-20’s optional metadata extensions.
The `name` and `symbol` functions MUST reflect the underlying token’s `name` and `symbol` in some way.

## Rationale

The `mints` method is optional because the ID is optional. In some use cases such as vesting where a user may have a maximum of one mint, an ID is not required.

Similarly, vesting use cases may want to enforce non-transferrable tokens until maturity, whereas lending receipt tokens with a minimum deposit duration may want to support transfers at all times.

It is possible that the number of mints held by a user is so large that it is impractical to return all of them in a single `eth_call`.
This is unlikely so it was not included in the spec.
If this is likely for a given use case, the implementer may choose to implement an alternative method that returns a subset of the mints, such as `getMints(address user, uint256 startId, uint256 endId)`.
However, if IDs are not sequential, a different signature may be required, and therefore this was not included in the specification.

## Backwards Compatibility

This proposal is fully backward compatible with the EIP-20 standard and has no known compatibility issues with other standards.

## Security Considerations

Iterating over large arrays of mints is not recommended, as this is very expensive and may cause the protocol, or just a user&apos;s interactions with it, to be stuck if this exceeds the block gas limit and reverts. There are some ways to mitigate this, with specifics dependent on the implementation.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 29 Sep 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5744</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5744</guid>
      </item>
    
      <item>
        <title>The &apos;window.evmproviders&apos; object</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5749-deprecate-window-ethereum/11195</comments>
        
        <description>## Abstract

A Javascript Ethereum Provider interface injection that will allow for the interoperability of multiple browser wallets at the same time. Replacing `window.ethereum` with `window.evmproviders` is a simple solution that will provide multiple benefits including: improving user experience, encouraging innovation in the space, removing race conditions and a &apos;winner-takes-most&apos; environment as well as lowering barriers for user adoption.

## Motivation

At present, `window.ethereum` is the prevailing method by which Ethereum-compatible applications interact with injected wallets. This originated with Mist Wallet in 2015 to interact with other applications. With the proliferation of both applications and wallets, `window.ethereum` has unintended negative consequences:

- `window.ethereum` only permits one wallet to be injected at a time, resulting in a race condition between two or more wallets. This creates an inconsistent connection behavior that makes having and using more than one browser wallet unpredictable and impractical. The current solution is for wallets to inject their own namespaces, but this is not feasible as every application would need to be made aware of any wallet that might be used.
- The aforementioned race condition means users are disincentivized to experiment with new wallets. This creates a &apos;winner-takes-most&apos; wallet market across EVM chains which forces application developers to optimize for a particular wallet experience.
- The &apos;winner-takes-most&apos; wallet environment that results from the `window.ethereum` standard hinders innovation because it creates a barrier to adoption. New entrants into the space have difficulty gaining traction against legacy players because users can have no more than one injected wallet. With new entrants crowded out, legacy wallet providers are put under little pressure to innovate.
- Wallets continue to be the most fundamental tool for interacting with blockchains. A homogeneous wallet experience in Ethereum and EVM chains risks stunting UX improvement across the ecosystem and will allow other ecosystems that are more encouraging of competition and innovation to move ahead.
- Some wallets that currently use `window.ethereum` as of August, 2022. Currently a user will have inconsistent behavior if they use multiple of these wallets in a single browser.
	- Metamask
	- Coinbase wallet
	- Enkrypt
	- Trust wallet
	- Rainbow
  

Replacing `window.ethereum` with `window.evmproviders` will allow solutions such as web3modal and web3onboard to display all injected wallets the user has installed. This will simplify the UX and remove race conditions between wallet providers in case multiple wallets are installed. Over time, as `window.evmproviders` supplants the current standard and removes barriers to choice, we can hope to see a wallet landscape more reflective of user preference.

## Specification

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.

### `window.evmproviders={}`

```typescript
/**
 * Represents the assets needed to display a wallet
 */
interface ProviderInfo {
   /**
    * A UUIDv4 unique to the wallet provider.
    *
    * This must remain the same across versions but must be different across channels. For example, MetaMask, Trust wallet and Enkrypt should each have different UUIDs, but MetaMask 10.22.2 and MetaMask 9.8.1 should have the same UUID.
    *
    * @readonly
    */
    uuid: string;
    /**
     * The name of the wallet provider (e.g. `MetaMask` or `Enkrypt`)
     *
     * @readonly
     */
    name: string;
    /**
     * A base64 encoded SVG image.
     *
     * Base64 is defined in RFC 4648.
     *
     * @readonly
     */
    icon: `data:image/svg+xml;base64,${string}`;
    /**
     * A description of the wallet provider.
     *
     * @readonly
     */
    description: string;
}
```

```typescript
/**
 * Represents the new Provider with info type that extends the EIP1193 provider
 */
interface ProviderWithInfo extends EIP1193Provider {
  	info: ProviderInfo;
}
```

Type `EIP1193Provider` is documented at [EIP-1193](/EIPs/EIPS/eip-1193)

```typescript
/**
 * The type of `window.evmproviders`
 */
interface EVMProviders {
  /**
   * The key is RECOMMENDED to be the name of the extension in snake_case. It MUST contain only lowercase letters, numbers, and underscores.
   */
  [index: string]: ProviderWithInfo;
}
```

## Rationale

Standardizing a `ProviderInfo` type allows determining the necessary information to populate a wallet selection popup. This is particularly useful for web3 onboarding libraries such as Web3Modal, Web3React, and Web3Onboard.

The name `evmproviders` was chosen to include other EVM-compliant chains.

The SVG image format was chosen for its flexibility, lightweight nature, and dynamic resizing capabilities.

## Backwards Compatibility

This EIP doesn&apos;t require supplanting `window.ethereum`, so it doesn&apos;t directly break existing applications. However, the recommended behavior of eventually supplanting `window.ethereum` would break existing applications that rely on it.

## Reference Implementation

### Injection

```typescript
const provider: ProviderWithInfo = [your wallet]
window.evmproviders = window.evmproviders || {};
window.evmproviders[name] = provider
```

### Retrieving all EVM providers

```typescript
const allproviders = Object.values(window.evmproviders)
```

## Security Considerations

The security considerations of EIP-1193 apply to this EIP.

The use of SVG images introduces a cross-site scripting risk as they can include JavaScript code. Applications and libraries must render SVG images using the `&lt;img&gt;` tag to ensure no JS executions can happen.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 04 Oct 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5749</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5749</guid>
      </item>
    
      <item>
        <title>General Extensibility for Method Behaviors</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-5750-method-with-extra-data/11176</comments>
        
        <description>## Abstract

This EIP standardizes the passing of unstructured call data to functions to enable future extensibility.

## Motivation

The purpose of having extra data in a method is to allow further extensions to existing method interfaces.

It is it useful to make methods extendable. Any methods complying with this EIP, such as overloaded `transfer` and `vote` could use string reasons as the extra data. Existing EIPs that have exported methods compliant with this EIP can be extended for behaviors such as using the extra data to prove endorsement, as a salt, as a nonce, or as a commitment for a reveal/commit scheme. Finally, data can be passed forward to callbacks.

There are two ways to achieve extensibility for existing functions. Each comes with their set of challenges:

1. Add a new method

  * What will the method name be?
  * What will the parameters be?
  * How many use-cases does a given method signature support?
  * Does this support off-chain signatures?

2. Use one or more existing parameters, or add one or more new ones

  * Should existing parameters be repurposed, or should more be added?
  * How many parameters should be used?
  * What are their sizes and types?

Standardizing how methods can be extended helps to answer these questions.

Finally, this EIP aims to achieve maximum backward and future compatibility. Many EIPs already partially support this EIP, such as [EIP-721](/EIPs/EIPS/eip-721) and [EIP-1155](/EIPs/EIPS/eip-1155). This EIP supports many use cases, from commit-reveal schemes ([EIP-5732](/EIPs/EIPS/eip-5732)), to adding digital signatures alongside with a method call. Other implementers and EIPs should be able to depend on the compatibility granted by this EIP so that all compliant method interfaces are eligible for future new behaviors.

## Specification

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 and RFC 8174.

When used in this EIP, the term `bytes` MUST be interpreted as the dynamically-sized byte array in Solidity data types.

1. Unlike many other ERCs which is compliant at the `contract` level, this ERC&apos;s specification specify compliance at `method` level.

2. Any method with a bytes as this method&apos;s last parameter is an _eligible_ method. It looks like this `function methodName(type1 value1, type2 value2, ... bytes data)`.

3. A _compliant_ method MUST be an _eligible_ method and MUST also designate that last `bytes` field in its method parameter for behaviors extensions.

4. If an _eligible_ method has an overloaded sibling method that
has the exact same method name and exact same preceding parameters
except for not having the last `bytes` parameter, the behavior
of the compliant method MUST be identical to
its overloaded sibling method when last `bytes` is an empty array.

### Examples of compliant and non-compliant methods

1. Here is a compliant method `methodName1` in a `Foo` contract

```solidity
contract Foo {
  // @dev This method allows extension behavior via `_data` field;
  function methodName1(uint256 _param1, address _param2, bytes calldata _data);
  function firstNonRelatedMethod(uint256 someValue);
  function secondNonRelatedMethod(uint256 someValue);
}
```

2. Here is a compliant method `methodName2` in a `Bar` contract which is an overloaded method for another `methodName2`.


```solidity
contract Foo {
  // @dev This is a sibling method to `methodName2(uint256 _param1, address _param2, bytes calldata _data);`
  function methodName2(uint256 _param1, address _param2);

  // @dev This method allows extension behavior via `_data` field;
  //      When passed in an empty array for `_data` field, this method
  //      MUST behave IDENTICAL to
  //      its overloaded sibling `methodName2(uint256 _param1, address _param2);`
  function methodName2(uint256 _param1, address _param2, bytes calldata _data);

  function firstNonRelatedMethod(uint256 someValue);
  function secondNonRelatedMethod(uint256 someValue);
}
```

3. Here is a non-compliant method `methodName1` because it do not allow extending behavior

```solidity
contract Foo {
  // @dev This method DO NOT allow extension behavior via `_data` field;
  function methodName1(uint256 _param1, address _param2, bytes calldata _data);
  function firstNonRelatedMethod(uint256 someValue);
  function secondNonRelatedMethod(uint256 someValue);
}
```

4. Here is a non-compliant method
`methodName2(uint256 _param1, address _param2, bytes calldata _data);`
because it behaves differently
to its overloaded sibling method
`methodName2(uint256 _param1, address _param2);` when `_data` is empty array.

```solidity
contract Foo {
  // @dev This is a sibling method to `methodName2(uint256 _param1, address _param2, bytes calldata _data);`
  function methodName2(uint256 _param1, address _param2);

  // @dev This method allows extension behavior via `_data` field;
  //      When passed in an empty array for `_data` field, this method
  //      behave DIFFERENTLY to
  //      its overloaded sibling `methodName2(uint256 _param1, address _param2);`
  function methodName2(uint256 _param1, address _param2, bytes calldata _data);

  function firstNonRelatedMethod(uint256 someValue);
  function secondNonRelatedMethod(uint256 someValue);
}
```

## Rationale

1. Using the dynamically-sized `bytes` type allows for maximum flexibility by enabling payloads of arbitrary types.
2. Having the bytes specified as the last parameter makes this EIP compatible with the calldata layout of solidity.

## Backwards Compatibility

Many existing EIPs already have compliant methods as part of their specification. All contracts compliant with those EIPs are either fully or partially compliant with this EIP.

Here is an incomplete list:

* In [EIP-721](/EIPs/EIPS/eip-721), the following method is already compliant:
  * `function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;` is already compliant
* In [EIP-1155](/EIPs/EIPS/eip-1155), the following methods are already compliant
  * `function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) external;`
  * `function safeBatchTransferFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external;`
* In [EIP-777](/EIPs/EIPS/eip-777), the following methods are already compliant
  * `function burn(uint256 amount, bytes calldata data) external;`
  * `function send(address to, uint256 amount, bytes calldata data) external;`

However, not all functions that have a `bytes` as the last parameter are compliant. The following functions are not compliant without an overload since their last parameter is involved in functionality:

* In [EIP-2535](/EIPs/EIPS/eip-2535), the following methods is not compliant:
  * `function diamondCut(FacetCut[] calldata _diamondCut, address _init, bytes calldata _calldata) external;`
  * **Either** of the following can be done to create a compliance.
    1. An overload MUST be created: `function diamondCut(FacetCut[] calldata _diamondCut, address _init, bytes calldata _calldata, bytes calldata _data) external;` which adds a new `_data` after all parameters of original method.
    2. The use of `bytes memory _calldata` MUST be relaxed to allow for extending behaviors.
* In [EIP-1271](/EIPs/EIPS/eip-1271), the following method is not compliant:
  * `function isValidSignature(bytes32 _hash, bytes memory _signature) public view returns (bytes4 magicValue);`
  * **Either** of the following can be done to create a compliance:
    1. An new overload MUST be created: `function isValidSignature(bytes32 _hash, bytes memory _signature, bytes calldata _data) public view returns (bytes4 magicValue);` which adds a new `_data` after all parameters of original method.
    2. The use of `bytes memory _signature` MUST be relaxed to allow for extending behaviors.

## Security Considerations

1. If using the extra data for extended behavior, such as supplying signature for onchain verification, or supplying commitments in a commit-reveal scheme, best practices should be followed for those particular extended behaviors.
2. Compliant contracts must also take into consideration that the data parameter will be publicly revealed when submitted into the mempool or included in a block, so one must consider the risk of replay and transaction ordering attacks. **Unencrypted personally identifiable information must never be included in the data parameter.**

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 04 Oct 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5750</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5750</guid>
      </item>
    
      <item>
        <title>Lockable Extension for EIP-721</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/lockable-nfts-extension/8800</comments>
        
        <description>## Abstract

This standard is an extension of [EIP-721](/EIPs/EIPS/eip-721). It introduces lockable NFTs. The locked asset can be used in any way except by selling and/or transferring it. The owner or operator can lock the token. When a token is locked, the unlocker address (an EOA or a contract) is set. Only the unlocker is able to `unlock` the token.

## Motivation

With NFTs, digital objects become digital goods, which are verifiably ownable, easily tradable, and immutably stored on the blockchain. That&apos;s why it&apos;s very important to continuously improve UX for non-fungible tokens, not just inherit it from one of the fungible tokens.

In DeFi there is an UX pattern when you lock your tokens on a service smart contract. For example, if you want to borrow some $DAI, you have to provide some $ETH as collateral for a loan. During the loan period this $ETH is being locked into the lending service contract. Such a pattern works for $ETH and other fungible tokens.

However, it should be different for NFTs because NFTs have plenty of use cases that require the NFT to stay in the holder&apos;s wallet even when it is used as collateral for a loan. You may want to keep using your NFT as a verified PFP on Twitter, or use it to authorize a Discord server through collab.land. You may want to use your NFT in a P2E game. And you should be able to do all of this even during the lending period, just like you are able to live in your house even if it is mortgaged.

The following use cases are enabled for lockable NFTs:

- **NFT-collateralised loans** Use your NFT as collateral for a loan without locking it on the lending protocol contract. Lock it on your wallet instead and continue enjoying all the utility of your NFT.
- **No collateral rentals of NFTs** Borrow NFT for a fee, without a need for huge collateral. You can use NFT, but not transfer it, so the lender is safe. The borrowing service contract automatically transfers NFT back to the lender as soon as the borrowing period expires.
- **Primary sales** Mint NFT for only the part of the price and pay the rest when you are satisfied with how the collection evolves.
- **Secondary sales** Buy and sell your NFT by installments. Buyer gets locked NFT and immediately starts using it. At the same time he/she is not able to sell the NFT until all the installments are paid. If full payment is not received, NFT goes back to the seller together with a fee.
- **S is for Safety** Use your exclusive blue chip NFTs safely and conveniently. The most convenient way to use NFT is together with MetaMask. However, MetaMask is vulnerable to various bugs and attacks. With `Lockable` extension you can lock your NFT and declare your safe cold wallet as an unlocker. Thus, you can still keep your NFT on MetaMask and use it conveniently. Even if a hacker gets access to your MetaMask, they won’t be able to transfer your NFT without access to the cold wallet. That’s what makes `Lockable` NFTs safe.
- **Metaverse ready** Locking NFT tickets can be useful during huge Metaverse events. That will prevent users, who already logged in with an NFT, from selling it or transferring it to another user. Thus we avoid double usage of one ticket.
- **Non-custodial staking** There are different approaches to non-custodial staking proposed by communities like CyberKongz, Moonbirds and other. Approach suggested in this impementation supposes that the token can only be staked in one place, not several palces at a time (it is like you can not deposit money in two bank accounts simultaneously). Also it doesn&apos;t require any additional code and is available with just locking feature.
Another approach to the same concept is using locking to provide proof of HODL. You can lock your NFTs from selling as a manifestation of loyalty to the community and start earning rewards for that. It is better version of the rewards mechanism, that was originally introduced by The Hashmasks and their $NCT token.
- **Safe and convenient co-ownership and co-usage** Extension of safe co-ownership and co-usage. For example, you want to purchase an expensive NFT asset together with friends, but it is not handy to use it with multisig, so you can safely rotate and use it between wallets. The NFT will be stored on one of the co-owners&apos; wallet and he will be able to use it in any way (except transfers) without requiring multi-approval. Transfers will require multi-approval.


## Specification

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.

EIP-721 compliant contracts MAY implement this EIP to provide standard methods of locking and unlocking the token at its current owner address.
If the token is locked, the `getLocked` function MUST return an address that is able to unlock the token.
For tokens that are not locked, the `getLocked` function MUST return `address(0)`.
The user MAY permanently lock the token by calling `lock(address(1), tokenId)`.

When the token is locked, all the [EIP-721](/EIPs/EIPS/eip-721) transfer functions MUST revert, except if the transaction has been initiated by an unlocker.
When the token is locked, the [EIP-721](/EIPs/EIPS/eip-721) `approve` method MUST revert for this token.
When the token is locked, the [EIP-721](/EIPs/EIPS/eip-721) `getApproved` method SHOULD return `unlocker` address for this token so the unlocker is able to transfer this token.
When the token is locked, the `lock` method MUST revert for this token, even when it is called with the same `unlocker` as argument.
When the locked token is transferred by an unlocker, the token MUST be unlocked after the transfer.

Marketplaces should call `getLocked` method of an EIP-721 Lockable token contract to learn whether a token with a specified tokenId is locked or not. Locked tokens SHOULD NOT be available for listings. Locked tokens can not be sold. Thus, marketplaces SHOULD hide the listing for the tokens that has been locked, because such orders can not be fulfilled.  

### Contract Interface

```solidity
pragma solidity &gt;=0.8.0;

/// @dev Interface for the Lockable extension

interface ILockable {

    /**
     * @dev Emitted when `id` token is locked, and `unlocker` is stated as unlocking wallet.
     */
    event Lock (address indexed unlocker, uint256 indexed id);

    /**
     * @dev Emitted when `id` token is unlocked.
     */
    event Unlock (uint256 indexed id);

    /**
     * @dev Locks the `id` token and gives the `unlocker` address permission to unlock.
     */
    function lock(address unlocker, uint256 id) external;

    /**
     * @dev Unlocks the `id` token.
     */
    function unlock(uint256 id) external;

    /**
     * @dev Returns the wallet, that is stated as unlocking wallet for the `tokenId` token.
     * If address(0) returned, that means token is not locked. Any other result means token is locked.
     */
    function getLocked(uint256 tokenId) external view returns (address);

}
```

The `supportsInterface` method MUST return `true` when called with `0x72b68110`.

## Rationale

This approach proposes a solution that is designed to be as minimal as possible. It only allows to lock the item (stating who will be able to unlock it) and unlock it when needed if a user has permission to do it.

At the same time, it is a generalized implementation. It allows for a lot of extensibility and any of the potential use cases (or all of them), mentioned in the Motivation section.

When there is a need to grant temporary and/or redeemable rights for the token (rentals, purchase with instalments) this EIP involves the real transfer of the token to the temporary user&apos;s wallet, not just assigning a role.
This choice was made to increase compatibility with all the existing NFT eco-system tools and dApps, such as Collab.land. Otherwise, it would require from all of such dApps implementing additional interfaces and logic.

Naming and reference implementation for the functions and storage entities mimics that of Approval flow for [EIP-721] in order to be intuitive.

## Backwards Compatibility

This standard is compatible with current [EIP-721](/EIPs/EIPS/eip-721) standards.

## Reference Implementation

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity &gt;=0.8.0;

import &apos;../ILockable.sol&apos;;
import &apos;@openzeppelin/contracts/token/ERC721/ERC721.sol&apos;;

/// @title Lockable Extension for ERC721

abstract contract ERC721Lockable is ERC721, ILockable {

    /*///////////////////////////////////////////////////////////////
                            LOCKABLE EXTENSION STORAGE                        
    //////////////////////////////////////////////////////////////*/

    mapping(uint256 =&gt; address) internal unlockers;

    /*///////////////////////////////////////////////////////////////
                              LOCKABLE LOGIC
    //////////////////////////////////////////////////////////////*/

    /**
     * @dev Public function to lock the token. Verifies if the msg.sender is the owner
     *      or approved party.
     */

    function lock(address unlocker, uint256 id) public virtual {
        address tokenOwner = ownerOf(id);
        require(msg.sender == tokenOwner || isApprovedForAll(tokenOwner, msg.sender)
        , &quot;NOT_AUTHORIZED&quot;);
        require(unlockers[id] == address(0), &quot;ALREADY_LOCKED&quot;); 
        unlockers[id] = unlocker;
        _approve(unlocker, id);
    }

    /**
     * @dev Public function to unlock the token. Only the unlocker (stated at the time of locking) can unlock
     */
    function unlock(uint256 id) public virtual {
        require(msg.sender == unlockers[id], &quot;NOT_UNLOCKER&quot;);
        unlockers[id] = address(0);
    }

    /**
     * @dev Returns the unlocker for the tokenId
     *      address(0) means token is not locked
     *      reverts if token does not exist
     */
    function getLocked(uint256 tokenId) public virtual view returns (address) {
        require(_exists(tokenId), &quot;Lockable: locking query for nonexistent token&quot;);
        return unlockers[tokenId];
    }

    /**
     * @dev Locks the token
     */
    function _lock(address unlocker, uint256 id) internal virtual {
        unlockers[id] = unlocker;
    }

    /**
     * @dev Unlocks the token
     */
    function _unlock(uint256 id) internal virtual {
        unlockers[id] = address(0);
    }

    /*///////////////////////////////////////////////////////////////
                              OVERRIDES
    //////////////////////////////////////////////////////////////*/

    function approve(address to, uint256 tokenId) public virtual override {
        require (getLocked(tokenId) == address(0), &quot;Can not approve locked token&quot;);
        super.approve(to, tokenId);
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual override {
        // if it is a Transfer or Burn
        if (from != address(0)) { 
            // token should not be locked or msg.sender should be unlocker to do that
            require(getLocked(tokenId) == address(0) || msg.sender == getLocked(tokenId), &quot;LOCKED&quot;);
        }
    }

    function _afterTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual override {
        // if it is a Transfer or Burn, we always deal with one token, that is startTokenId
        if (from != address(0)) { 
            // clear locks
            delete unlockers[tokenId];
        }
    }

    /**
     * @dev Optional override, if to clear approvals while the tken is locked
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        if (getLocked(tokenId) != address(0)) {
            return address(0);
        }
        return super.getApproved(tokenId);
    }

    /*///////////////////////////////////////////////////////////////
                              ERC165 LOGIC
    //////////////////////////////////////////////////////////////*/

    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override
        returns (bool)
    {
        return
            interfaceId == type(IERC721Lockable).interfaceId ||
            super.supportsInterface(interfaceId);
    }

}
```

## Security Considerations

There are no security considerations related directly to the implementation of this standard for the contract that manages [EIP-721](/EIPs/EIPS/eip-721) tokens.

### Considerations for the contracts that work with lockable tokens

- Make sure that every contract that is stated as `unlocker` can actually unlock the token in all cases.
- There are use cases, that involve transferring the token to a temporary owner and then lock it. For example, NFT rentals. Smart contracts that manage such services should always use `transferFrom` instead of `safeTransferFrom` to avoid re-entrancies.
- There are no MEV considerations regarding lockable tokens as only authorized parties are allowed to lock and unlock.


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE)
</description>
        <pubDate>Wed, 05 Oct 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5753</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5753</guid>
      </item>
    
      <item>
        <title>Process for Approving External Resources</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5757-process-for-approving-external-resources/11215</comments>
        
        <description>## Abstract

Ethereum improvement proposals (EIPs) occasionally link to resources external to this repository. This document sets out the requirements for origins that may be linked to, and the process for approving a new origin.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### Definitions

 - **Link**: Any method of referring to a resource, including: markdown links, anchor tags (`&lt;a&gt;`), images, citations of books/journals, and any other method of referencing content not in the current resource.
 - **Resource**: A web page, document, article, file, book, or other media that contains content.
 - **Origin**: A publisher/chronicler of resources, like a standards body (eg. w3c) or a system of referring to documents (eg. Digital Object Identifier System).

### Requirements for Origins

Permissible origins **MUST** provide a method of uniquely identifying a particular revision of a resource. Examples of such methods may include git commit hashes, version numbers, or publication dates.

Permissible origins **MUST** have a proven history of availability. A origin existing for at least ten years and reliably serving resources would be sufficient—but not necessary—to satisfy this requirement.

Permissible origins **MUST NOT** charge a fee for accessing resources.

### Origin Removal

Any approved origin that ceases to satisfy the above requirements **MUST** be removed from [EIP-1](/EIPs/EIPS/eip-1). If a removed origin later satisfies the requirements again, it MAY be re-approved by following the process described in [Origin Approval](#origin-approval).

Finalized EIPs (eg. those in the `Final` or `Withdrawn` statuses) **SHOULD NOT** be updated to remove links to these origins.

Non-Finalized EIPs **MUST** remove links to these origins before changing statuses.

### Origin Approval

Should the editors determine that an origin meets the requirements above, EIP-1 **MUST** be updated to include:

 * The name of the allowed origin;
 * The permitted markup and formatting required when referring to resources from the origin; and
 * A fully rendered example of what a link should look like.

## Rationale

### Unique Identifiers

If it is impossible to uniquely identify a version of a resource, it becomes impractical to track changes, which makes it difficult to ensure immutability.

### Availability

If it is possible to implement a standard without a linked resource, then the linked resource is unnecessary. If it is impossible to implement a standard without a linked resource, then that resource must be available for implementers.

### Free Access

The Ethereum ecosystem is built on openness and free access, and the EIP process should follow those principles.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 30 Sep 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5757</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5757</guid>
      </item>
    
      <item>
        <title>Context-Dependent Multi-Asset Tokens</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/multiresource-tokens/11326</comments>
        
        <description>## Abstract

The Multi-Asset NFT standard allows for the construction of a new primitive: context-dependent output of information per single NFT.

The context-dependent output of information means that the asset in an appropriate format is displayed based on how the token is being accessed. I.e. if the token is being opened in an e-book reader, the PDF asset is displayed, if the token is opened in the marketplace, the PNG or the SVG asset is displayed, if the token is accessed from within a game, the 3D model asset is accessed and if the token is accessed by the (Internet of Things) IoT hub, the asset providing the necessary addressing and specification information is accessed.

An NFT can have multiple assets (outputs), which can be any kind of file to be served to the consumer, and orders them by priority. They do not have to match in mimetype or tokenURI, nor do they depend on one another. Assets are not standalone entities, but should be thought of as “namespaced tokenURIs” that can be ordered at will by the NFT owner, but only modified, updated, added, or removed if agreed on by both the owner of the token and the issuer of the token.

## Motivation

With NFTs being a widespread form of tokens in the Ethereum ecosystem and being used for a variety of use cases, it is time to standardize additional utility for them. Having multiple assets associated with a single NFT allows for greater utility, usability and forward compatibility.

In the four years since [ERC-721](/EIPs/EIPS/eip-721) was published, the need for additional functionality has resulted in countless extensions. This EIP improves upon ERC-721 in the following areas:

- [Cross-metaverse compatibility](#cross-metaverse-compatibility)
- [Multi-media output](#multi-media-output)
- [Media redundancy](#media-redundancy)
- [NFT evolution](#nft-evolution)

### Cross-metaverse compatibility

At the time of writing this proposal, the metaverse is still a fledgling, not full defined, term. No matter how the definition of metaverse evolves, the proposal can support any number of different implementations.

Cross-metaverse compatibility could also be referred to as cross-engine compatibility. An example of this is where a cosmetic item for game A is not available in game B because the frameworks are incompatible.

Such NFT can be given further utility by means of new additional assets: more games, more cosmetic items, appended to the same NFT. Thus, a game cosmetic item as an NFT becomes an ever-evolving NFT of infinite utility.

The following is a more concrete example. One asset is a cosmetic item for game A, a file containing the cosmetic assets. Another is a cosmetic asset file for game B. A third is a generic asset intended to be shown in catalogs, marketplaces, portfolio trackers, or other generalized NFT viewers, containing a representation, stylized thumbnail, and animated demo/trailer of the cosmetic item.

This EIP adds a layer of abstraction, allowing game developers to directly pull asset data from a user&apos;s NFTs instead of hard-coding it.

### Multi-media output

An NFT of an eBook can be represented as a PDF, MP3, or some other format, depending on what software loads it. If loaded into an eBook reader, a PDF should be displayed, and if loaded into an audiobook application, the MP3 representation should be used. Other metadata could be present in the NFT (perhaps the book&apos;s cover image) for identification on various marketplaces, Search Engine Result Pages (SERPs), or portfolio trackers.

### Media redundancy

Many NFTs are minted hastily without best practices in mind - specifically, many NFTs are minted with metadata centralized on a server somewhere or, in some cases, a hardcoded IPFS gateway which can also go down, instead of just an IPFS hash.

By adding the same metadata file as different assets, e.g., one asset of a metadata and its linked image on Arweave, one asset of this same combination on Sia, another of the same combination on IPFS, etc., the resilience of the metadata and its referenced information increases exponentially as the chances of all the protocols going down at once become less likely.

### NFT evolution

Many NFTs, particularly game related ones, require evolution. This is especially the case in modern metaverses where no metaverse is actually a metaverse - it is just a multiplayer game hosted on someone&apos;s server which replaces username/password logins with reading an account&apos;s NFT balance.

When the server goes down or the game shuts down, the player ends up with nothing (loss of experience) or something unrelated (assets or accessories unrelated to the game experience, spamming the wallet, incompatible with other “verses” - see [cross-metaverse](#cross-metaverse-compatibility) compatibility above).

With Multi-Asset NFTs, a minter or another pre-approved entity is allowed to suggest a new asset to the NFT owner who can then accept it or reject it. The asset can even target an existing asset which is to be replaced.

Replacing an asset could, to some extent, be similar to replacing an ERC-721 token&apos;s URI. When an asset is replaced a clear line of traceability remains; the old asset is still reachable and verifiable. Replacing an asset&apos;s metadata URI obscures this lineage. It also gives more trust to the token owner if the issuer cannot replace the asset of the NFT at will. The propose-accept asset replacement mechanic of this proposal provides this assurance.

This allows level-up mechanics where, once enough experience has been collected, a user can accept the level-up. The level-up consists of a new asset being added to the NFT, and once accepted, this new asset replaces the old one.

As a concrete example, think of Pokemon™️ evolving - once enough experience has been attained, a trainer can choose to evolve their monster. With Multi-Asset NFTs, it is not necessary to have centralized control over metadata to replace it, nor is it necessary to airdrop another NFT into the user&apos;s wallet - instead, a new Raichu asset is minted onto Pikachu, and if accepted, the Pikachu asset is gone, replaced by Raichu, which now has its own attributes, values, etc.

Alternative example of this, could be version control of an IoT device&apos;s firmware. An asset could represent its current firmware and once an update becomes available, the current asset could be replaced with the one containing the updated firmware.

## Specification

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.

```solidity
/// @title ERC-5773 Context-Dependent Multi-Asset Tokens
/// @dev See https://eips.ethereum.org/EIPS/eip-5773
/// @dev Note: the ERC-165 identifier for this interface is 0x06b4329a.

pragma solidity ^0.8.16;

interface IERC5773 /* is ERC165 */ {
    /**
     * @notice Used to notify listeners that an asset object is initialised at `assetId`.
     * @param assetId ID of the asset that was initialised
     */
    event AssetSet(uint64 assetId);

    /**
     * @notice Used to notify listeners that an asset object at `assetId` is added to token&apos;s pending asset
     *  array.
     * @param tokenIds An array of IDs of the tokens that received a new pending asset
     * @param assetId ID of the asset that has been added to the token&apos;s pending assets array
     * @param replacesId ID of the asset that would be replaced
     */
    event AssetAddedToTokens(
        uint256[] tokenIds,
        uint64 indexed assetId,
        uint64 indexed replacesId
    );

    /**
     * @notice Used to notify listeners that an asset object at `assetId` is accepted by the token and migrated
     *  from token&apos;s pending assets array to active assets array of the token.
     * @param tokenId ID of the token that had a new asset accepted
     * @param assetId ID of the asset that was accepted
     * @param replacesId ID of the asset that was replaced
     */
    event AssetAccepted(
        uint256 indexed tokenId,
        uint64 indexed assetId,
        uint64 indexed replacesId
    );

    /**
     * @notice Used to notify listeners that an asset object at `assetId` is rejected from token and is dropped
     *  from the pending assets array of the token.
     * @param tokenId ID of the token that had an asset rejected
     * @param assetId ID of the asset that was rejected
     */
    event AssetRejected(uint256 indexed tokenId, uint64 indexed assetId);

    /**
     * @notice Used to notify listeners that token&apos;s priority array is reordered.
     * @param tokenId ID of the token that had the asset priority array updated
     */
    event AssetPrioritySet(uint256 indexed tokenId);

    /**
     * @notice Used to notify listeners that owner has granted an approval to the user to manage the assets of a
     *  given token.
     * @dev Approvals must be cleared on transfer
     * @param owner Address of the account that has granted the approval for all token&apos;s assets
     * @param approved Address of the account that has been granted approval to manage the token&apos;s assets
     * @param tokenId ID of the token on which the approval was granted
     */
    event ApprovalForAssets(
        address indexed owner,
        address indexed approved,
        uint256 indexed tokenId
    );

    /**
     * @notice Used to notify listeners that owner has granted approval to the user to manage assets of all of their
     *  tokens.
     * @param owner Address of the account that has granted the approval for all assets on all of their tokens
     * @param operator Address of the account that has been granted the approval to manage the token&apos;s assets on all of the
     *  tokens
     * @param approved Boolean value signifying whether the permission has been granted (`true`) or revoked (`false`)
     */
    event ApprovalForAllForAssets(
        address indexed owner,
        address indexed operator,
        bool approved
    );

    /**
     * @notice Accepts an asset at from the pending array of given token.
     * @dev Migrates the asset from the token&apos;s pending asset array to the token&apos;s active asset array.
     * @dev Active assets cannot be removed by anyone, but can be replaced by a new asset.
     * @dev Requirements:
     *
     *  - The caller must own the token or be approved to manage the token&apos;s assets
     *  - `tokenId` must exist.
     *  - `index` must be in range of the length of the pending asset array.
     * @dev Emits an {AssetAccepted} event.
     * @param tokenId ID of the token for which to accept the pending asset
     * @param index Index of the asset in the pending array to accept
     * @param assetId Id of the asset expected to be in the index
     */
    function acceptAsset(
        uint256 tokenId,
        uint256 index,
        uint64 assetId
    ) external;

    /**
     * @notice Rejects an asset from the pending array of given token.
     * @dev Removes the asset from the token&apos;s pending asset array.
     * @dev Requirements:
     *
     *  - The caller must own the token or be approved to manage the token&apos;s assets
     *  - `tokenId` must exist.
     *  - `index` must be in range of the length of the pending asset array.
     * @dev Emits a {AssetRejected} event.
     * @param tokenId ID of the token that the asset is being rejected from
     * @param index Index of the asset in the pending array to be rejected
     * @param assetId Id of the asset expected to be in the index
     */
    function rejectAsset(
        uint256 tokenId,
        uint256 index,
        uint64 assetId
    ) external;

    /**
     * @notice Rejects all assets from the pending array of a given token.
     * @dev Effectively deletes the pending array.
     * @dev Requirements:
     *
     *  - The caller must own the token or be approved to manage the token&apos;s assets
     *  - `tokenId` must exist.
     * @dev Emits a {AssetRejected} event with assetId = 0.
     * @param tokenId ID of the token of which to clear the pending array
     * @param maxRejections to prevent from rejecting assets which arrive just before this operation.
     */
    function rejectAllAssets(uint256 tokenId, uint256 maxRejections) external;

    /**
     * @notice Sets a new priority array for a given token.
     * @dev The priority array is a non-sequential list of `uint16`s, where the lowest value is considered highest
     *  priority.
     * @dev Value `0` of a priority is a special case equivalent to uninitialised.
     * @dev Requirements:
     *
     *  - The caller must own the token or be approved to manage the token&apos;s assets
     *  - `tokenId` must exist.
     *  - The length of `priorities` must be equal the length of the active assets array.
     * @dev Emits a {AssetPrioritySet} event.
     * @param tokenId ID of the token to set the priorities for
     * @param priorities An array of priorities of active assets. The succession of items in the priorities array
     *  matches that of the succession of items in the active array
     */
    function setPriority(uint256 tokenId, uint64[] calldata priorities)
        external;

    /**
     * @notice Used to retrieve IDs of the active assets of given token.
     * @dev Asset data is stored by reference, in order to access the data corresponding to the ID, call
     *  `getAssetMetadata(tokenId, assetId)`.
     * @dev You can safely get 10k
     * @param tokenId ID of the token to retrieve the IDs of the active assets
     * @return uint64[] An array of active asset IDs of the given token
     */
    function getActiveAssets(uint256 tokenId)
        external
        view
        returns (uint64[] memory);

    /**
     * @notice Used to retrieve IDs of the pending assets of given token.
     * @dev Asset data is stored by reference, in order to access the data corresponding to the ID, call
     *  `getAssetMetadata(tokenId, assetId)`.
     * @param tokenId ID of the token to retrieve the IDs of the pending assets
     * @return uint64[] An array of pending asset IDs of the given token
     */
    function getPendingAssets(uint256 tokenId)
        external
        view
        returns (uint64[] memory);

    /**
     * @notice Used to retrieve the priorities of the active assets of a given token.
     * @dev Asset priorities are a non-sequential array of uint16 values with an array size equal to active asset
     *  priorites.
     * @param tokenId ID of the token for which to retrieve the priorities of the active assets
     * @return uint16[] An array of priorities of the active assets of the given token
     */
    function getActiveAssetPriorities(uint256 tokenId)
        external
        view
        returns (uint64[] memory);

    /**
     * @notice Used to retrieve the asset that will be replaced if a given asset from the token&apos;s pending array
     *  is accepted.
     * @dev Asset data is stored by reference, in order to access the data corresponding to the ID, call
     *  `getAssetMetadata(tokenId, assetId)`.
     * @param tokenId ID of the token to check
     * @param newAssetId ID of the pending asset which will be accepted
     * @return uint64 ID of the asset which will be replaced
     */
    function getAssetReplacements(uint256 tokenId, uint64 newAssetId)
        external
        view
        returns (uint64);

    /**
     * @notice Used to fetch the asset metadata of the specified token&apos;s active asset with the given index.
     * @dev Can be overridden to implement enumerate, fallback or other custom logic.
     * @param tokenId ID of the token from which to retrieve the asset metadata
     * @param assetId Asset Id, must be in the active assets array
     * @return string The metadata of the asset belonging to the specified index in the token&apos;s active assets
     *  array
     */
    function getAssetMetadata(uint256 tokenId, uint64 assetId)
        external
        view
        returns (string memory);

    /**
     * @notice Used to grant permission to the user to manage token&apos;s assets.
     * @dev This differs from transfer approvals, as approvals are not cleared when the approved party accepts or
     *  rejects an asset, or sets asset priorities. This approval is cleared on token transfer.
     * @dev Only a single account can be approved at a time, so approving the `0x0` address clears previous approvals.
     * @dev Requirements:
     *
     *  - The caller must own the token or be an approved operator.
     *  - `tokenId` must exist.
     * @dev Emits an {ApprovalForAssets} event.
     * @param to Address of the account to grant the approval to
     * @param tokenId ID of the token for which the approval to manage the assets is granted
     */
    function approveForAssets(address to, uint256 tokenId) external;

    /**
     * @notice Used to retrieve the address of the account approved to manage assets of a given token.
     * @dev Requirements:
     *
     *  - `tokenId` must exist.
     * @param tokenId ID of the token for which to retrieve the approved address
     * @return address Address of the account that is approved to manage the specified token&apos;s assets
     */
    function getApprovedForAssets(uint256 tokenId)
        external
        view
        returns (address);

    /**
     * @notice Used to add or remove an operator of assets for the caller.
     * @dev Operators can call {acceptAsset}, {rejectAsset}, {rejectAllAssets} or {setPriority} for any token
     *  owned by the caller.
     * @dev Requirements:
     *
     *  - The `operator` cannot be the caller.
     * @dev Emits an {ApprovalForAllForAssets} event.
     * @param operator Address of the account to which the operator role is granted or revoked from
     * @param approved The boolean value indicating whether the operator role is being granted (`true`) or revoked
     *  (`false`)
     */
    function setApprovalForAllForAssets(address operator, bool approved)
        external;

    /**
     * @notice Used to check whether the address has been granted the operator role by a given address or not.
     * @dev See {setApprovalForAllForAssets}.
     * @param owner Address of the account that we are checking for whether it has granted the operator role
     * @param operator Address of the account that we are checking whether it has the operator role or not
     * @return bool The boolean value indicating whether the account we are checking has been granted the operator role
     */
    function isApprovedForAllForAssets(address owner, address operator)
        external
        view
        returns (bool);
}
```

The `getAssetMetadata` function returns the asset&apos;s metadata URI. The metadata, to which the metadata URI of the asset points, MAY contain a JSON response with the following fields:

```json
{
  &quot;name&quot;: &quot;Asset Name&quot;,
  &quot;description&quot;: &quot;The description of the token or asset&quot;,
  &quot;mediaUri&quot;: &quot;ipfs://mediaOfTheAssetOrToken&quot;,
  &quot;thumbnailUri&quot;: &quot;ipfs://thumbnailOfTheAssetOrToken&quot;,
  &quot;externalUri&quot;: &quot;https://uriToTheProjectWebsite&quot;,
  &quot;license&quot;: &quot;License name&quot;,
  &quot;licenseUri&quot;: &quot;https://uriToTheLicense&quot;,
  &quot;tags&quot;: [&quot;tags&quot;, &quot;used&quot;, &quot;to&quot;, &quot;help&quot;, &quot;marketplaces&quot;, &quot;categorize&quot;, &quot;the&quot;, &quot;asset&quot;, &quot;or&quot;, &quot;token&quot;],
  &quot;preferThumb&quot;: false, // A boolean flag indicating to UIs to prefer thumbnailUri instead of mediaUri wherever applicable
  &quot;attributes&quot;: [
    {
      &quot;label&quot;: &quot;rarity&quot;,
      &quot;type&quot;: &quot;string&quot;,
      &quot;value&quot;: &quot;epic&quot;,
      // For backward compatibility
      &quot;trait_type&quot;: &quot;rarity&quot;
    },
    {
      &quot;label&quot;: &quot;color&quot;,
      &quot;type&quot;: &quot;string&quot;,
      &quot;value&quot;: &quot;red&quot;,
      // For backward compatibility
      &quot;trait_type&quot;: &quot;color&quot;
    },
    {
      &quot;label&quot;: &quot;height&quot;,
      &quot;type&quot;: &quot;float&quot;,
      &quot;value&quot;: 192.4,
      // For backward compatibility
      &quot;trait_type&quot;: &quot;height&quot;,
      &quot;display_type&quot;: &quot;number&quot;
    }
  ]
}
```

While this is the suggested JSON schema for the asset metadata, it is not enforced and MAY be structured completely differently based on implementer&apos;s preference.

## Rationale

Designing the proposal, we considered the following questions:

1. **Should we use Asset or Resource when referring to the structure that comprises the token?**\
The original idea was to call the proposal Multi-Resource, but while this denoted the broadness of the structures that could be held by a single token, the term *asset* represents it better.\
An asset is defined as something that is owned by a person, company, or organization, such as money, property, or land. This is the best representation of what an asset of this proposal can be. An asset in this proposal can be a multimedia file, technical information, a land deed, or anything that the implementer has decided to be an asset of the token they are implementing.
2. **Why are [EIP-712](/EIPs/EIPS/eip-712) permit-style signatures to manage approvals not used?**\
For consistency. This proposal extends ERC-721 which already uses 1 transaction for approving operations with tokens. It would be inconsistent to have this and also support signing messages for operations with assets.
3. **Why use indexes?**\
To reduce the gas consumption. If the asset ID was used to find which asset to accept or reject, iteration over arrays would be required and the cost of the operation would depend on the size of the active or pending assets arrays. With the index, the cost is fixed. A list of active and pending assets arrays per token need to be maintained, since methods to get them are part of the proposed interface.\
To avoid race conditions in which the index of an asset changes, the expected asset ID is included in operations requiring asset index, to verify that the asset being accessed using the index is the expected asset.\
Implementation that would internally keep track of indices using mapping was attempted. The average cost of adding an asset to a token increased by over 25%, costs of accepting and rejecting assets also increased 4.6% and 7.1% respectively. We concluded that it is not necessary for this proposal and can be implemented as an extension for use cases willing to accept this cost. In the sample implementation provided, there are several hooks which make this possible.
4. **Why is a method to get all the assets not included?**\
Getting all assets might not be an operation necessary for all implementers. Additionally, it can be added either as an extension, doable with hooks, or can be emulated using an indexer.
5. **Why is pagination not included?**\
Asset IDs use `uint64`, testing has confirmed that the limit of IDs you can read before reaching the gas limit is around 30.000. This is not expected to be a common use case so it is not a part of the interface. However, an implementer can create an extension for this use case if needed.
6. **How does this proposal differ from the other proposals trying to address a similar problem?**\
After reviewing them, we concluded that each contains at least one of these limitations:
   - Using a single URI which is replaced as new assets are needed, this introduces a trust issue for the token owner.
   - Focusing only on a type of asset, while this proposal is asset type agnostic.
   - Having a different token for each new use case, this means that the token is not forward-compatible.

### Multi-Asset Storage Schema

Assets are stored within a token as an array of `uint64` identifiers.

In order to reduce redundant on-chain string storage, multi asset tokens store assets by reference via inner storage. An asset entry on the storage is stored via a `uint64` mapping to asset data.

An asset array is an array of these `uint64` asset ID references.

Such a structure allows that, a generic asset can be added to the storage one time, and a reference to it can be added to the token contract as many times as we desire. Implementers can then use string concatenation to procedurally generate a link to a content-addressed archive based on the base *SRC* in the asset and the *token ID*. Storing the asset in a new token will only take 16 bytes of storage in the asset array per token for recurrent as well as `tokenId` dependent assets.

Structuring token&apos;s assets in such a way allows for URIs to be derived programmatically through concatenation, especially when they differ only by `tokenId`.

### Propose-Commit pattern for asset addition

Adding assets to an existing token MUST be done in the form of a propose-commit pattern to allow for limited mutability by a 3rd party. When adding an asset to a token, it is first placed in the *&quot;Pending&quot;* array, and MUST be migrated to the *&quot;Active&quot;* array by the token&apos;s owner. The *&quot;Pending&quot;* assets array SHOULD be limited to 128 slots to prevent spam and griefing.

### Asset management

Several functions for asset management are included. In addition to permissioned migration from &quot;Pending&quot; to &quot;Active&quot;, the owner of a token MAY also drop assets from both the active and the pending array -- an emergency function to clear all entries from the pending array MUST also be included.

## Backwards Compatibility

The MultiAsset token standard has been made compatible with [ERC-721](/EIPs/EIPS/eip-721) in order to take advantage of the robust tooling available for implementations of ERC-721 and to ensure compatibility with existing ERC-721 infrastructure.

## Test Cases

Tests are included in [`multiasset.ts`](/EIPs/assets/eip-5773/test/multiasset.ts).

To run them in terminal, you can use the following commands:

```
cd ../assets/eip-5773
npm install
npx hardhat test
```

## Reference Implementation

See [`MultiAssetToken.sol`](/EIPs/assets/eip-5773/contracts/MultiAssetToken.sol).

## Security Considerations

The same security considerations as with [ERC-721](/EIPs/EIPS/eip-721) apply: hidden logic may be present in any of the functions, including burn, add asset, accept asset, and more.

Caution is advised when dealing with non-audited contracts.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 10 Oct 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5773</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5773</guid>
      </item>
    
      <item>
        <title>Physical Backed Tokens</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/physical-backed-tokens/11350</comments>
        
        <description>## Abstract

This standard is an extension of [ERC-721](/EIPs/EIPS/eip-721). It proposes a minimal interface for a [ERC-721](/EIPs/EIPS/eip-721) NFT to be &quot;physically backed&quot; and owned by whoever owns the NFT&apos;s physical counterpart.

## Motivation

NFT collectors enjoy collecting digital assets and sharing them with others online. However, there is currently no such standard for showcasing physical assets as NFTs with verified authenticity and ownership. Existing solutions are fragmented and tend to be susceptible to at least one of the following:

- The ownership of the physical item and the ownership of the NFT are decoupled.

- Verifying the authenticity of the physical item requires action from a trusted 3rd party (e.g. StockX).

## Specification

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.

### Requirements

This approach requires that the physical item must have a chip attached to it that should be secure and signal authenticity:

- The chip can securely generate and store an asymmetric key pair;
- The chip can sign messages using the private key of the previously-generated asymmetric key pair;
- The chip exposes the public key; and
- The private key cannot be extracted or duplicated by design

The approach also requires that the contract uses an account-bound implementation of [ERC-721](/EIPs/EIPS/eip-721) (where all [ERC-721](/EIPs/EIPS/eip-721) functions that transfer must throw, e.g. the &quot;read only NFT registry&quot; implementation referenced in [ERC-721](/EIPs/EIPS/eip-721)). This ensures that ownership of the physical item is required to initiate transfers and manage ownership of the NFT, through a new function introduced in this interface described below.

### Approach

Each NFT is conceptually linked to a physical chip.

When the chipId is paired to a tokenId, an event will be emitted. This lets downstream indexers know which chip addresses are mapped to which tokens for the NFT collection. The NFT cannot be minted without its token id being linked to a specific chip.

The interface includes a function called `transferToken` that transfers the NFT to the function caller if a valid signature signed by the chip is passed in. A valid signature must follow the schemes set forth in [ERC-191](/EIPs/EIPS/eip-191) and [EIP-2](/EIPs/EIPS/eip-2) (s-value restrictions), where the data to sign consists of the target recipient address (the function caller), the chip address, a block timestamp, and any extra params used for additional custom logic in the implementation.

The interface also includes other functions that let anyone validate whether the chip in the physical item is backing an existing NFT in the collection.

### Interface

```solidity

interface IERC5791 {
    /// @dev Returns the ERC-721 `tokenId` for a given chip address.
    ///      Reverts if `chipId` has not been paired to a `tokenId`.
    ///      For minimalism, this will NOT revert if the `tokenId` does not exist.
    ///      If there is a need to check for token existence, external contracts can
    ///      call `ERC721.ownerOf(uint256 tokenId)` and check if it passes or reverts.
    /// @param chipId The address for the chip embedded in the physical item
    ///               (computed from the chip&apos;s public key).
    function tokenIdFor(address chipId) external view returns (uint256 tokenId);

    /// @dev Returns true if `signature` is signed by the chip assigned to `tokenId`, else false.
    ///      Reverts if `tokenId` has not been paired to a chip.
    ///      For minimalism, this will NOT revert if the `tokenId` does not exist.
    ///      If there is a need to check for token existence, external contracts can
    ///      call `ERC721.ownerOf(uint256 tokenId)` and check if it passes or reverts.
    /// @param tokenId ERC-721 `tokenId`.
    /// @param data      Arbitrary bytes string that is signed by the chip to produce `signature`.
    /// @param signature EIP-191 signature by the chip to check.
    function isChipSignatureForToken(uint256 tokenId, bytes calldata data, bytes calldata signature)
        external
        view
        returns (bool);

    /// @dev Transfers the token into the address.
    ///      Returns the `tokenId` transferred.
    /// @param to                  The recipient. Dynamic to allow easier transfers to vaults.
    /// @param chipId              Chip ID (address) of chip being transferred.
    /// @param chipSignature       EIP-191 signature by the chip to authorize the transfer.
    /// @param signatureTimestamp  Timestamp used in `chipSignature`.
    /// @param useSafeTransferFrom Whether ERC-721&apos;s `safeTransferFrom` should be used,
    ///                            instead of `transferFrom`.
    /// @param extras              Additional data that can be used for additional logic/context
    ///                            when the PBT is transferred.
    function transferToken(
        address to,
        address chipId,
        bytes calldata chipSignature,
        uint256 signatureTimestamp,
        bool useSafeTransferFrom,
        bytes calldata extras
    ) external returns (uint256 tokenId);

    /// @dev Emitted when `chipId` is paired to `tokenId`.
    /// `tokenId` may not necessarily exist during assignment.
    /// Indexers can combine this event with the {ERC721.Transfer} event to
    /// infer which tokens exists and are paired with a chip ID.
    event ChipSet(uint256 indexed tokenId, address indexed chipId);
}

```

To aid recognition that an [ERC-721](/EIPs/EIPS/eip-721) token implements physical binding via this EIP: upon calling [ERC-165](/EIPs/EIPS/eip-165)’s `function supportsInterface(bytes4 interfaceID) external view returns (bool)` with `interfaceID=0x4901df9f`, a contract implementing this EIP must return true.

The mint interface is up to the implementation. The minted NFT&apos;s owner should be the owner of the physical chip (this authentication could be implemented using the signature scheme defined for `transferToken`).

## Rationale

This solution&apos;s intent is to be the simplest possible path towards linking physical items to digital NFTs without a centralized authority.

The interface includes a `transferToken` function that&apos;s opinionated with respect to the signature scheme, in order to enable a downstream aggregator-like product that supports transfers of any NFTs that implement this EIP in the future.

The chip address is included in `transferToken` to allow signature verification by a smart contract. This ensures that chips in physically backed tokens are not strictly tied to implementing secp256k1 signatures, but instead may use a variety of signature schemes such as P256 or BabyJubJub.

### Out of Scope

The following are some peripheral problems that are intentionally not within the scope of this EIP:

- trusting that a specific NFT collection&apos;s chip addresses actually map to physical chips embedded in items, instead of arbitrary EOAs that purport to be chips
- ensuring that the chip does not deteriorate or get damaged
- ensuring that the chip stays attached to the physical item
- etc.

Work is being done on these challenges in parallel.

Mapping token ids to chip addresses is also out of scope. This can be done in multiple ways, e.g. by having the contract owner preset this mapping pre-mint, or by having a `(tokenId, chipId)` tuple passed into a mint function that&apos;s pre-signed by an address trusted by the contract, or by doing a lookup in a trusted registry, or by assigning token ids at mint time first come first served, etc.

Additionally, it&apos;s possible for the owner of the physical item to transfer the NFT to a wallet owned by somebody else (by sending a chip signature to that other person for use). We still consider the NFT physical backed, as ownership management is tied to the physical item. This can be interpreted as the item&apos;s owner temporarily lending the item to somebody else, since (1) the item&apos;s owner must be involved for this to happen as the one signing with the chip, and (2) the item&apos;s owner can reclaim ownership of the NFT at any time.

## Backwards Compatibility

This proposal is backward compatible with [ERC-721](/EIPs/EIPS/eip-721) on an API level. As mentioned above, for the token to be physical-backed, the contract must use a account-bound implementation of [ERC-721](/EIPs/EIPS/eip-721) (all [ERC-721](/EIPs/EIPS/eip-721) functions that transfer must throw) so that transfers go through the new function introduced here, which requires a chip signature.

## Reference Implementation

The following is a snippet on how to validate a chip signature in a transfer event.

```solidity
import &apos;@openzeppelin/contracts/utils/cryptography/ECDSA.sol&apos;;

/// @dev Transfers the `tokenId` assigned to `chipId` to `to`.
function transferToken(
    address to,
    address chipId,
    bytes memory chipSignature,
    uint256 signatureTimestamp,
    bool useSafeTransfer,
    bytes memory extras
) public virtual returns (uint256 tokenId) {
    tokenId = tokenIdFor(chipId);
    _validateSigAndUpdateNonce(to, chipId, chipSignature, signatureTimestamp, extras);
    if (useSafeTransfer) {
        _safeTransfer(ownerOf(tokenId), to, tokenId, &quot;&quot;);
    } else {
        _transfer(ownerOf(tokenId), to, tokenId);
    }
}

/// @dev Validates the `chipSignature` and update the nonce for the future signature of `chipId`.
function _validateSigAndUpdateNonce(
    address to,
    address chipId,
    bytes memory chipSignature,
    uint256 signatureTimestamp,
    bytes memory extras
) internal virtual {
    bytes32 hash = _getSignatureHash(signatureTimestamp, chipId, to, extras);
    if (!SignatureCheckerLib.isValidSignatureNow(chipId, hash, chipSignature)) {
        revert InvalidSignature();
    }
    chipNonce[chipId] = bytes32(uint256(hash) ^ uint256(blockhash(block.number - 1)));
}

/// @dev Returns the digest to be signed by the `chipId`.
function _getSignatureHash(uint256 signatureTimestamp, address chipId, address to, bytes memory extras)
    internal
    virtual
    returns (bytes32)
{
    if (signatureTimestamp &gt; block.timestamp) revert SignatureTimestampInFuture();
    if (signatureTimestamp + maxDurationWindow &lt; block.timestamp) revert SignatureTimestampTooOld();
    bytes32 hash = keccak256(
        abi.encode(address(this), block.chainid, chipNonce[chipId], to, signatureTimestamp, keccak256(extras))
    );
    return ECDSA.toEthSignedMessageHash(hash);
}

```

## Security Considerations

The [ERC-191](/EIPs/EIPS/eip-191) signature passed to `transferToken` requires the function caller&apos;s address in its signed data so that the signature cannot be used in a replay attack. It also requires a recent block timestamp so that a malicious chip owner cannot pre-generate signatures to use after a short time window (e.g. after the owner of the physical item changes). It&apos;s recommended to use a non-deterministic `chipNonce` when generating signatures.

Additionally, the level of trust that one has for whether the token is physically-backed is dependent on the security of the physical chip, which is out of scope for this EIP as mentioned above.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 17 Oct 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5791</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5791</guid>
      </item>
    
      <item>
        <title>Wallet Call API</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5792-wallet-abstract-transaction-send-api/11374</comments>
        
        <description>## Abstract

Defines new JSON-RPC methods which enable apps to ask a wallet to process a batch of onchain write calls and to check on the status of those calls.
Applications can specify that these onchain calls be executed taking advantage of specific capabilities previously expressed by the wallet; an additional, novel wallet RPC is defined to enable apps to query the wallet for those capabilities.

## Motivation

The current methods used to send transactions from the user wallet and check their status are `eth_sendTransaction` and `eth_getTransactionReceipt`.

The current methods used to send transactions from the user wallet and check their status do not meet modern developer demands and cannot accommodate new transaction formats. Even the name–- `eth_sendTransaction`-– is an artifact of a time when nodes served as wallets.

Today, developers want to send multiple calls batched together in a single RPC call, which many smart accounts can, in turn, execute atomically in a single transaction. Developers also want to make use of features afforded by new transaction formats, like paymasters in [ERC-4337](/EIPs/EIPS/eip-4337) transactions. `eth_sendTransaction` offers no way to do these things.

In updating to a new set of `wallet_` RPCs, our main goals are to enforce a clean separation of wallet and app concerns, enable developers to make use of things like paymasters and batch transactions, and to create a clear way for more safely discoverable features to be added over time with minimal coordination.

## Specification

Four new JSON-RPC methods are added: three are for handling batches of onchain calls, and one is for querying support for wallet capabilities, such as to make better use of the three batching methods.
Apps may begin using these first three methods immediately, falling back to `eth_sendTransaction` and `eth_getTransactionReceipt` when they are not available.

### `wallet_sendCalls`

Requests that a wallet submits a batch of calls. `from` and `chainId` are identified by [EIP-155](/EIPs/EIPS/eip-155) integers expressed in hexadecimal notation,
with `0x` prefix and no leading zeroes for the `chainId` value.
The items in the `calls` field are simple `{to, data, value}` tuples.

The capabilities field is how an app can communicate with a wallet about capabilities a wallet supports. For example, this is where an app can specify a paymaster service URL from which an [ERC-4337](/EIPs/EIPS/eip-4337) wallet can request a `paymasterAndData` input for a user operation.

Each capability defined in the &quot;capabilities&quot; member can define global or call specific fields.
These fields are set inside this capability&apos;s entry in the `capabilities` object.
Each entity in the `calls` field may contain an optional `capabilities` object.
This object allows the applications to attach a capability-specific metadata to individual calls.

The `atomicRequired` field specifies if a wallet is required to handle the batch of calls atomically or not. The wallet capacity to execute batch calls atomically is exposed through the built in `atomic` capability and can be sourced via `wallet_getCapabilities`..

Unless these requirements are explicitly overridden by a certain `capability`, the wallet must adhere to the following rules.
Note that such a `capability` is not in the scope of this EIP and should be defined in its own ERC.

The wallet:

* MUST send the calls in the order specified in the request
* MUST send the calls on the same chain identified by the request&apos;s `chainId` property
* MUST send the calls from the address specified in the request&apos;s `from` property, if provided
  * If `from` is not provided the wallet SHOULD present the user with an opportunity to view and select the `from` address during confirmation
* MUST NOT await for any calls to be finalized to complete the batch
* MUST NOT send any calls from the request if the user rejects the request
* When `atomicRequired` is set to `true`:
  * MUST execute all calls atomically, meaning that either all calls execute successfully or no material effects appear on chain.
  * MUST execute all calls contiguously, meaning no other transactions/calls may be interleaved with the calls from this batch.
  * If a wallet is able to upgrade its atomicity guarantees from `ready` to `supported` but has not yet done so, it MUST upgrade before proceeding to submit the calls with the above guarantees.
* When `atomicRequired` is set to `false`:
  * MAY execute all calls sequentially without any atomicity/contiguity guarantees.
  * If a wallet is capable of providing atomicity guarantees, it MAY execute the batch atomically.
  * If a wallet is able to upgrade its atomicity guarantees to `supported` (see `atomic` capability definition below), it MAY do so and then execute the batch atomically.

* MAY reject the request if the from address does not match the enabled account
* MAY reject the request if one or more calls in the batch is expected to fail, when simulated sequentially
* MUST reject the request if it contains a `capability` (either top-level or call-level) that is not supported by the wallet and the `capability` is not explicitly marked as optional.
  * Applications may mark a capability as optional by setting `optional` to `true`. See the RPC Specification section below for details.

If provided, the wallet MUST respect the `id` field and return it in the response.

Identifiers, whether provided by the app or generated by the wallet, MUST be a unique string up to 4096 bytes (8194 characters including leading `0x`).

App-provided `id`s MUST be unique per sender per app, where each &quot;app&quot; SHOULD be identified by their domain.

Wallets MUST reject requests with duplicate `id`s.

Within 24 hours from the corresponding `wallet_sendCalls`, wallets SHOULD return a call-batch status when `wallet_getCallsStatus` is called with the same `id`.

The `capabilities` response object allows the wallets to attach a capability-specific metadata to the response.


#### `wallet_sendCalls` RPC Specification

```typescript
type Capability = {
  [key: string]: unknown;
  optional?: boolean;
}

type SendCallsParams = {
  version: string;
  id?: string;
  from?: `0x${string}`;
  chainId: `0x${string}`; // Hex chain id
  atomicRequired: boolean;
  calls: {
    to?: `0x${string}`;
    data?: `0x${string}`;
    value?: `0x${string}`; // Hex value
    capabilities?: Record&lt;string, Capability&gt;;
  }[];
  capabilities?: Record&lt;string, Capability&gt;;
};

type SendCallsResult = {
  id: string;
  capabilities?: Record&lt;string, any&gt;;
};
```

##### `wallet_sendCalls` Example Parameters

```json
[
  {
    &quot;version&quot;: &quot;2.0.0&quot;,
    &quot;from&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
    &quot;chainId&quot;: &quot;0x01&quot;,
    &quot;atomicRequired&quot;: true,
    &quot;calls&quot;: [
      {
        &quot;to&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
        &quot;value&quot;: &quot;0x9184e72a&quot;,
        &quot;data&quot;: &quot;0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675&quot;
      },
      {
        &quot;to&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
        &quot;value&quot;: &quot;0x182183&quot;,
        &quot;data&quot;: &quot;0xfbadbaf01&quot;
      }
    ],
    &quot;capabilities&quot;: {
      &quot;paymasterService&quot;: {
        &quot;url&quot;: &quot;https://...&quot;,
        &quot;optional&quot;: true
      }
    }
  }
]
```

Note that since the `paymasterService` `capability` is marked as optional, wallets that do not support it will still process and handle the request as if the capability had not been present. If this `optional` field were set to `false` or absent from the request, wallets that do not support the `capability` MUST reject the request.

##### `wallet_sendCalls` Example Return Value

```json
{
  &quot;id&quot;: &quot;0x00000000000000000000000000000000000000000000000000000000000000000e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;,
}
```

### `wallet_getCallsStatus`

Returns the status of a call batch that was sent via `wallet_sendCalls`.
The identifier of the batch is the value returned from the `wallet_sendCalls` RPC.
Note that the `receipts` objects of this method&apos;s response is a strict subset of the object returned by `eth_getTransactionReceipt`.

The `capabilities` object allows the wallets to attach a capability-specific metadata to the response.

The `atomic` field specifies how the wallet handled the batch of calls, which influences the structure of the `receipts` field.

* The receipts in the `receipts` field MUST be in the order that they are included onchain.
* If a wallet executes multiple calls **atomically**, `wallet_getCallsStatus` MAY return an object with a `receipts` field that contains a single transaction receipt or an array of receipts, corresponding to how the batch of transactions were included onchain. It also MUST be explicit and return an `atomic` field set to `true`.
* If a wallet executes multiple calls **non-atomically**, `wallet_getCallsStatus` MUST return an object with a `receipts` field that contains **an array of receipts** for all transactions containing batch calls that were included onchain. This includes the batch calls that were included on-chain but eventually reverted. It also MUST be explicit and return a `atomic` field set to `false`.
* The `logs` in the receipt objects MUST only include logs relevant to the calls submitted using `wallet_sendCalls`. For example, in the case of a transaction submitted onchain by an [ERC-4337](/EIPs/EIPS/eip-4337) bundler, the logs must only include those relevant to the user operation constructed using the calls submitted via `wallet_sendCalls`. I.e. the logs should not include those from other unrelated user operations submitted in the same bundle.
  * Similarly, if a user upgrades their wallet to support atomicity before submitting a batch of calls from an app, the logs MUST NOT include those emitted as part of the upgrade process.

#### `wallet_getCallsStatus` RPC Specification

```typescript
type GetCallsParams = [string];

type GetCallsResult = {
  version: string;
  id: `0x${string}`;
  chainId: `0x${string}`;
  status: number; // See &quot;Status Codes&quot;
  atomic: boolean;
  receipts?: {
    logs: {
      address: `0x${string}`;
      data: `0x${string}`;
      topics: `0x${string}`[];
    }[];
    status: `0x${string}`; // Hex 1 or 0 for success or failure, respectively
    blockHash: `0x${string}`;
    blockNumber: `0x${string}`;
    gasUsed: `0x${string}`;
    transactionHash: `0x${string}`;
  }[];
  capabilities?: Record&lt;string, any&gt;;
};
```

##### Status Codes for `status` field

The purpose of the `status` field is to provide a short summary of the current status of the batch.
It provides some off-chain context to the array of inner transaction `receipts`.

Status codes follow these categories:

* 1xx: Pending states
* 2xx: Confirmed states
* 4xx: Offchain failures
* 5xx: Chain rules failures

| Code | Description                                                                                                                       |
|------|-----------------------------------------------------------------------------------------------------------------------------------|
| 100  | Batch has been received by the wallet but has not completed execution onchain (pending)                                           |
| 200  | Batch has been included onchain without reverts, receipts array contains info of all calls (confirmed)                            |
| 400  | Batch has not been included onchain and wallet will not retry (offchain failure)                                                  |
| 500  | Batch reverted **completely** and only changes related to gas charge may have been included onchain (chain rules failure)         |
| 600  | Batch reverted **partially** and some changes related to batch calls may have been included onchain (partial chain rules failure) |

More specific status codes within these categories should be proposed and agreed upon in separate ERCs.

##### `wallet_getCallsStatus` Example Parameters

The `id` batch identifier is a unique 64 bytes represented as a hex encoded string returned from `wallet_sendCalls`.

```json
[
  &quot;0x00000000000000000000000000000000000000000000000000000000000000000e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;
]
```

##### `wallet_getCallsStatus` Example Return Value

```json
{
  &quot;version&quot;: &quot;2.0.0&quot;,
  &quot;chainId&quot;: &quot;0x01&quot;,
  &quot;id&quot;: &quot;0x00000000000000000000000000000000000000000000000000000000000000000e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;,
  &quot;status&quot;: 200,
  &quot;atomic&quot;: true,
  &quot;receipts&quot;: [
    {
      &quot;logs&quot;: [
        {
          &quot;address&quot;: &quot;0xa922b54716264130634d6ff183747a8ead91a40b&quot;,
          &quot;topics&quot;: [
            &quot;0x5a2a90727cc9d000dd060b1132a5c977c9702bb3a52afe360c9c22f0e9451a68&quot;
          ],
          &quot;data&quot;: &quot;0xabcd&quot;
        }
      ],
      &quot;status&quot;: &quot;0x1&quot;,
      &quot;blockHash&quot;: &quot;0xf19bbafd9fd0124ec110b848e8de4ab4f62bf60c189524e54213285e7f540d4a&quot;,
      &quot;blockNumber&quot;: &quot;0xabcd&quot;,
      &quot;gasUsed&quot;: &quot;0xdef&quot;,
      &quot;transactionHash&quot;: &quot;0x9b7bb827c2e5e3c1a0a44dc53e573aa0b3af3bd1f9f5ed03071b100bb039eaff&quot;
    }
  ]
}
```

### `wallet_showCallsStatus`

Requests that a wallet shows information about a given call bundle that was sent with `wallet_sendCalls`. Note that this method does not return anything for a known `id` batch identifier. If the identifier is not known, or in case of any other failure to execute `wallet_showCallsStatus` returns an RPC call error.

#### `wallet_showCallsStatus` RPC Specification

```typescript
type ShowCallsParams = string; // Call bundle identifier returned by wallet_sendCalls
```

##### `wallet_showCallsStatus` Example Parameters

This method accepts a call bundle identifier returned by a `wallet_sendCalls` call.

```json
[&quot;0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;]
```

### `wallet_getCapabilities`

This RPC allows an application to request capabilities from a wallet (e.g. batch transactions, paymaster communication), without distinct discovery and permission requests. For more on the difference between requesting capabilities and discovering features, see the [&quot;Privacy Considerations&quot; section](#privacy-considerations).

This method SHOULD return an `4100 Unauthorized` error if the user has not already authorized a connection between the application and the requested address.

We expect the community to align on the definition of additional capabilities in separate ERCs over time.

Note that in addition to, or instead of, querying the wallet directly for capabilities, the same capability objects MAY be exposed out-of-band, such as in a `sessionProperties` and/or `scopedProperties` collections persisted in a [CAIP-25](https://github.com/ChainAgnostic/CAIPs/blob/c599f7601d0ce83e6dd9f350c6c21d158d56fd6d/CAIPs/caip-25.md)-conformant wallet provider interface (see the ethereum usage profile for CAIP-25 for an example request and response), or in some other a well-known location (such as a URL derived from an [EIP-6963](/EIPs/EIPS/eip-6963) `rdns` identifier).
Provider abstractions MAY also cache capabilities from previous requests or otherwise inject them from out-of-band to facilitate better user experience.
If any of these supplemental expressions of capabilities are contradicted by capabilities expressed in live wallet RPC responses, these latter values SHOULD be taken as the canonical and current expression of capabilities.

#### `wallet_getCapabilities` RPC Specification

Capabilities are returned in key/value pairs, with the key naming a capability and a value conforming to a shape defined for that name, in an object keyed to the relevant [EIP-155](/EIPs/EIPS/eip-155) `chainId` expressed in hexadecimal notation.
Capabilities are nested in per-chain objects because wallets may support different capabilities across multiple chains authorized in a given session.
Capabilities that the wallet supports on all the chains SHOULD be included only once, using a special `chainID` value `&quot;0x0&quot;`, and SHOULD NOT be repeated in nested per-chain objects.
If a wallet does not support a chain that is requested in the `wallet_getCapabilities` method, the wallet MUST NOT respond with an error, and MUST instead not include a key for the unsupported chain(s) in the response.

```typescript
type GetCapabilitiesParams = [`0x${string}`, [`0x${string}`]]; // Wallet address, array of queried chain ids (optional)

type GetCapabilitiesResult = Record&lt;`0x${string}`, &lt;Record&lt;string, any&gt;&gt;; // Hex chain id
```

##### `wallet_getCapabilities` Example Parameters

```json
[&quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;, [&quot;0x2105&quot;, &quot;0x14A34&quot;]]
```

##### `wallet_getCapabilities` Example Return Value

The capabilities below are for illustrative purposes.

```json
{
  &quot;0x0&quot;: {
    &quot;flow-control&quot;: {
      &quot;supported&quot;: true
    }
  },
  &quot;0x2105&quot;: {
    &quot;paymasterService&quot;: {
      &quot;supported&quot;: true
    },
    &quot;sessionKeys&quot;: {
      &quot;supported&quot;: true
    }
  },
  &quot;0x14A34&quot;: {
    &quot;auxiliaryFunds&quot;: {
      &quot;supported&quot;: true
    }
  }
}
```

### `atomic` Capability

Like the illustrative examples given above and other capabilities to be defined in future EIPs, the `atomic` capability specifies how the wallet will execute the batches of transactions requested through `wallet_sendCalls` method.

The valid JSON-RPC values for this `atomic` capability&apos;s only property, `status`, are `supported`, `ready`, and `unsupported`:

* `supported` means that the wallet will execute the calls atomically and contiguously.
* `ready` means that the wallet is able to upgrade to `supported` pending user approval.
* `unsupported` means that the wallet does not provide any atomicity or contiguity guarantees, nor will it suggest an upgrade to the user.

This capability is expressed separately on each chain and should be interpreted as a guarantee only for batches of transactions on that chain.

If the `atomic` capability is not present for a given chain, and unless it is explicitly overridden by another `capability` (not in scope of this EIP), it means that the wallet does not support batching for that given chain.

#### `atomic` Capability Specification

```typescript
type AtomicCapability = {
  status: &apos;supported&apos; | &apos;ready&apos; | &apos;unsupported&apos;;
};
```


#### `wallet_getCapabilities` Example Return Value including `atomic`

```json
{
  &quot;0x2105&quot;: {
    &quot;atomic&quot;: {
      &quot;status&quot;: &quot;supported&quot;
    }
  },
  &quot;0x14A34&quot;: {
    &quot;atomic&quot;: {
      &quot;status&quot;: &quot;unsupported&quot;
    }
  }
}
```

### Error Codes

The following error codes are defined for the methods specified in this EIP. These errors follow the JSON-RPC 2.0 specification for error objects, which require a `code` and `message` field.

| Code | Message | Description | Related RPCs |
|------|---------|-------------|--------------|
| -32602 | Invalid params | The wallet cannot parse this request (e.g., missing 0x prefix, leading zeros in chain id, request fails schema validation) | `wallet_sendCalls`, `wallet_getCallsStatus`, `wallet_showCallsStatus`, `wallet_getCapabilities` |
| 4001 | User Rejected Request | The user rejected submitting the batch of calls (from [EIP-1193](/EIPs/EIPS/eip-1193)) | `wallet_sendCalls` |
| 4100 | Unauthorized | The specified address is not connected or not in the wallet (from [EIP-1193](/EIPs/EIPS/eip-1193)) | `wallet_sendCalls`, `wallet_getCapabilities` |
| 5700 | Unsupported non-optional capability | This wallet does not support a capability that was not marked as optional | `wallet_sendCalls` |
| 5710 | Unsupported chain id | This wallet does not support the specified chain id | `wallet_sendCalls` |
| 5720 | Duplicate ID | There is already a bundle submitted with this id | `wallet_sendCalls` |
| 5730 | Unknown bundle id | This bundle id is unknown / has not been submitted | `wallet_getCallsStatus`, `wallet_showCallsStatus` |
| 5740 | Bundle too large | The call bundle is too large for the wallet to process | `wallet_sendCalls` |
| 5750 | Atomic-ready wallet rejected upgrade | The wallet can support atomicity after an upgrade, but the user rejected the upgrade | `wallet_sendCalls` |
| 5760 | Atomicity not supported | The wallet does not support atomic execution but the request requires it | `wallet_sendCalls` |

## Rationale

### On Naming

We considered modifying `eth_sendTransaction` to add support for these new capabilities, but the method is ultimately an artifact of when nodes were used to sign transactions. We decided it is better to move forward with `wallet_`-namespaced methods that better describe what they are used for.

We also debated whether the methods should be called `wallet_sendTransaction`, `wallet_sendCalls`, or something else. We ultimately landed on `wallet_sendCalls` because in the case of EOA wallets the `wallet_send*` method might send more than one transaction. Similarly, we decided against `wallet_sendTransactions` because in the case of other wallet implementations (e.g. [ERC-4337](/EIPs/EIPS/eip-4337)) multiple calls could result in a single transaction.

### Call Execution Atomicity

The `wallet_sendCalls` method accepts an array of `calls`. However, this proposal does not require that these calls be executed as part of a single transaction. It enables EOA wallets to express their ability to execute calls as part of a single transaction or as part of multiple transactions. It also enables Apps to express their minimum atomicity requirements for how calls must be executed.

The `atomic` special capability was made an integral part of this specification in order promote expressiveness and facilitate adoption (from both wallets and apps). And due to its importance to reduce ambiguity between the App and the Wallet, the capability is expressed as a top-level field in the `wallet_sendCalls` request (through the `atomicRequired` parameter) and the `wallet_getCallsStatus` response (through the `atomic` field).

We initially proposed that multiple calls must be executed atomically, but after some debate we ultimately decided this was too opinionated. Instead, we are including a specification for an `atomic` capability. This allows for EOA wallets to accept multiple calls and still gives developers the option to only submit batched calls if they are executed atomically.

### Call Gas Limit

Our initial proposal included an optional `gas` field for each call in the `calls` field accepted by the `walletSendCalls` method. However, we realized this could be misleading because in the case of [ERC-4337](/EIPs/EIPS/eip-4337) wallets you cannot specify a gas limit per call, only a single gas limit for all calls in the user operation. We then proposed a single `gas` value that would apply to all of the calls. This works for [ERC-4337](/EIPs/EIPS/eip-4337) wallets, but not for EOA wallets. When we decided that EOA wallets should be able to handle multiple calls, the common `gas` field became untenable across use cases and we removed it altogether.

## Backwards Compatibility

Wallets that do not support the methods defined here SHOULD return error responses when these new JSON-RPC methods are called. Apps MAY attempt to send the same batch of calls serially via `eth_sendTransaction` when a call to these methods fails for lack of wallet support, or they MAY indicate to the user that their wallet is not supported and the request was not processed.

## Security Considerations

Regardless of the `atomic` value specified, App developers MUST NOT assume that all calls will be sent in a single transaction. An example could be an L2 resistant to reorgs that implements a sendBundle or similar functionality.

Wallets MUST ensure that batch identifiers returned by `wallet_sendCalls` are unpredictable to prevent malicious apps from inferring information about other users&apos; transactions.

Wallets MUST NOT leak sensitive information in `wallet_getCallsStatus` `capabilities` responses.

### Privacy Considerations

Progressive authorization and progressive consent paradigms are important to modern user experience, as well as to preserving the anonymity of user agents. To protect these patterns from the cross-incentives of feature-discovery that enables better user experiences, capability semantics are used and the difference between lack of feature support and lack of feature permission explicitly occluded in the design of the `wallet_` RPC for querying capabilities.

Furthermore, wallets are recommended to avoid exposing capabilities to untrusted callers or to more callers than necessary, as this may allow their &quot;user-agent&quot; (i.e. client software) to be &quot;fingerprinted&quot; or probabilistically identified, which combined with other deanonymization vectors inherent to the web platform could contribute to the deanonymization of the individual user or to the deanonymization of all users of a given client in aggregate. Similarly, applications over-querying capabilities or incentivizing capability oversharing (including third-party capability oversharing) is an anti-pattern to be avoided in the implementation of capability exchanges serving to discover features.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 17 Oct 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5792</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5792</guid>
      </item>
    
      <item>
        <title>eth/68 - Add tx type to tx announcement</title>
        <category>Standards Track/Networking</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5793-eth-68-add-transaction-type-to-tx-announcement/11364</comments>
        
        <description>## Abstract

The Ethereum Wire Protocol defines request and response messages for exchanging data between clients. The `NewPooledTransactionHashes` message announces transactions available in the node. This EIP extends this announcement message such that beside the transaction hashes, the node sends the transaction types and their sizes (as defined in [EIP-2718](/EIPs/EIPS/eip-2718)) as well.

## Motivation

The `NewPooledTransactionHashes` message announces transaction hashes, allowing the peer to selectively fetch transactions it does not yet have.

[EIP-4844](/EIPs/EIPS/eip-4844) introduces a new transaction type for blob transactions. Since these blob transactions are large, naively broadcasting them to `sqrt(peers)` could significantly increase bandwidth requirements. Adding the transaction type and the size to the announcement message will allow nodes to select which transactions they want to fetch and also allow them to load balance or throttle peers based on past behavior.

The added metadata fields will also enable future - upgradeless - protocol tweaks to prevent certain transaction type (e.g. blob transactions) or certain transaction sizes (e.g. 128KB+) from being blindly broadcast to many peers. Enforcing announcements only and retrieval on demand would ensure a much more predictable networking behavior, limiting the amplification effect of transaction propagation DoS attack.

## Specification

Modify the `NewPooledTransactionHashes (0x08)` message:

* **(eth/67)**: `[hash_0: B_32, hash_1: B_32, ...]`
* **(eth/68)**: `[types: B, [size_0: P, size_1: P, ...], [hash_0: B_32, hash_1: B_32, ...]]`

The new `types` element refers to the transaction types of the announced hashes. Note the
transaction types are packed as a &apos;byte array&apos; instead of a list.

The `size_0`, `size_1` etc. elements refer to the transaction sizes of the announced hashes.

## Rationale

This change will make the `eth` protocol future-proof for new transaction types that might not be relevant for all nodes. It gives the receiving node better control over the data it fetches from the peer as well as allow throttling the download of specific types.

The `types` message element is a byte array because early implementations of this EIP
erroneously implemented it that way. It was later decided to keep this behavior in order
to minimize work.

## Backwards Compatibility

This EIP changes the `eth` protocol and requires rolling out a new version, `eth/68`. 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 `eth/67`.

This EIP does not change consensus rules of the EVM and does not require a hard fork.

## Security Considerations

None

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).


</description>
        <pubDate>Tue, 18 Oct 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5793</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5793</guid>
      </item>
    
      <item>
        <title>Voting with delegation</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5805-voting-with-delegation/11407</comments>
        
        <description>## Abstract

Many DAOs (decentralized autonomous organizations) rely on tokens to represent one&apos;s voting power. In order to perform this task effectively, the token contracts need to include specific mechanisms such as checkpoints and delegation. The existing implementations are not standardized. This ERC proposes to standardize the way votes are delegated from one account to another, and the way current and past votes are tracked and queried. The corresponding behavior is compatible with many token types, including but not limited to [ERC-20](/EIPs/EIPS/eip-20) and [ERC-721](/EIPs/EIPS/eip-721). This ERC also considers the diversity of time tracking functions, allowing the voting tokens (and any contract associated with it) to track the votes based on `block.number`, `block.timestamp`, or any other non-decreasing function.

## Motivation

Beyond simple monetary transactions, decentralized autonomous organizations are arguably one of the most important use cases of blockchain and smart contract technologies. Today, many communities are organized around a governance contract that allows users to vote. Among these communities, some represent voting power using transferable tokens ([ERC-20](/EIPs/EIPS/eip-20), [ERC-721](/EIPs/EIPS/eip-721), other). In this context, the more tokens one owns, the more voting power one has. Governor contracts, such as Compound&apos;s `GovernorBravo`, read from these &quot;voting token&quot; contracts to get the voting power of the users.

Unfortunately, simply using the `balanceOf(address)` function present in most token standards is not good enough:

- The values are not checkpointed, so a user can vote, transfer its tokens to a new account, and vote again with the same tokens.
- A user cannot delegate their voting power to someone else without transferring full ownership of the tokens.

These constraints have led to the emergence of voting tokens with delegation that contain the following logic:

- Users can delegate the voting power of their tokens to themselves or a third party. This creates a distinction between balance and voting weight.
- The voting weights of accounts are checkpointed, allowing lookups for past values at different points in time.
- The balances are not checkpointed.

This ERC is proposing to standardize the interface and behavior of these voting tokens.

Additionally, the existing (non-standardized) implementations are limited to `block.number` based checkpoints. This choice causes many issues in a multichain environment, where some chains (particularly L2s) have an inconsistent or unpredictable time between blocks. This ERC also addresses this issue by allowing the voting token to use any time tracking function it wants, and exposing it so that other contracts (such as a Governor) can stay consistent with the token checkpoints.

## Specification

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.

Following pre-existing (but not-standardized) implementation, the EIP proposes the following mechanism.

Each user account (address) can delegate to an account of its choice. This can be itself, someone else, or no one (represented by `address(0)`). Assets held by the user cannot express their voting power unless they are delegated.

When a &quot;delegator&quot; delegates its tokens voting power to a &quot;delegatee&quot;, its balance is added to the voting power of the delegatee. If the delegator changes its delegation, the voting power is subtracted from the old delegatee&apos;s voting power and added to the new delegate&apos;s voting power. The voting power of each account is tracked through time so that it is possible to query its value in the past. With tokens being delegated to at most one delegate at a given point in time, double voting is prevented.

Whenever tokens are transferred from one account to another, the associated voting power should be deducted from the sender&apos;s delegate and added to the receiver&apos;s delegate.

Tokens that are delegated to `address(0)` should not be tracked. This allows users to optimize the gas cost of their token transfers by skipping the checkpoint update for their delegate.

To accommodate different types of chains, we want the voting checkpoint system to support different forms of time tracking. On the Ethereum mainnet, using block numbers provides backward compatibility with applications that historically use it. On the other hand, using timestamps provides better semantics for end users, and accommodates use cases where the duration is expressed in seconds. Other monotonic functions could also be deemed relevant by developers based on the characteristics of future applications and blockchains.

Both timestamps, block numbers, and other possible modes use the same external interfaces. This allows transparent binding of third-party contracts, such as governor systems, to the vote tracking built into the voting contracts. For this to be effective, the voting contracts must, in addition to all the vote-tracking functions, expose the current value used for time-tracking.

### Methods

#### [ERC-6372](/EIPs/EIPS/eip-6372): clock and CLOCK_MODE

Compliant contracts SHOULD implement ERC-6372 (Contract clock) to announce the clock that is used for vote tracking.

If the contract does not implement ERC-6372, it MUST operate according to a block number clock, exactly as if ERC-6372&apos;s `CLOCK_MODE` returned `mode=blocknumber&amp;from=default`.

In the following specification, &quot;the current clock&quot; refers to either the result of ERC-6372&apos;s `clock()`, or the default of `block.number` in its absence.

#### getVotes

This function returns the current voting weight of an account. This corresponds to all the voting power delegated to it at the moment this function is called.

As tokens delegated to `address(0)` should not be counted/snapshotted, `getVotes(0)` SHOULD always return `0`.

This function MUST be implemented

```yaml
- name: getVotes
  type: function
  stateMutability: view
  inputs:
    - name: account
      type: address
  outputs:
    - name: votingWeight
      type: uint256
```

#### getPastVotes

This function returns the historical voting weight of an account. This corresponds to all the voting power delegated to it at a specific timepoint. The timepoint parameter MUST match the operating mode of the contract. This function SHOULD only serve past checkpoints, which SHOULD be immutable.

- Calling this function with a timepoint that is greater or equal to the current clock SHOULD revert.
- Calling this function with a timepoint strictly smaller than the current clock SHOULD NOT revert.
- For any integer that is strictly smaller than the current clock, the value returned by `getPastVotes` SHOULD be constant. This means that for any call to this function that returns a value, re-executing the same call (at any time in the future) SHOULD return the same value.

As tokens delegated to `address(0)` should not be counted/snapshotted, `getPastVotes(0,x)` SHOULD always return `0` (for all values of `x`).

This function MUST be implemented

```yaml
- name: getPastVotes
  type: function
  stateMutability: view
  inputs:
    - name: account
      type: address
    - name: timepoint
      type: uint256
  outputs:
    - name: votingWeight
      type: uint256
```

#### delegates

This function returns the address to which the voting power of an account is currently delegated.

Note that if the delegate is `address(0)` then the voting power SHOULD NOT be checkpointed, and it should not be possible to vote with it.

This function MUST be implemented

```yaml
- name: delegates
  type: function
  stateMutability: view
  inputs:
    - name: account
      type: address
  outputs:
    - name: delegatee
      type: address
```

#### delegate

This function changes the caller&apos;s delegate, updating the vote delegation in the meantime.

This function MUST be implemented

```yaml
- name: delegate
  type: function
  stateMutability: nonpayable
  inputs:
    - name: delegatee
      type: address
  outputs: []
```

#### delegateBySig

This function changes an account&apos;s delegate using a signature, updating the vote delegation in the meantime.

This function MUST be implemented

```yaml
- name: delegateBySig
  type: function
  stateMutability: nonpayable
  inputs:
    - name: delegatee
      type: address
    - name: nonce
      type: uint256
    - name: expiry
      type: uint256
    - name: v
      type: uint8
    - name: r
      type: bytes32
    - name: s
      type: bytes32
  outputs: []
```

This signature should follow the [EIP-712](/EIPs/EIPS/eip-712) format:

A call to `delegateBySig(delegatee, nonce, expiry, v, r, s)` changes the signer&apos;s delegate to `delegatee`, increment the signer&apos;s nonce by 1, and emits a corresponding `DelegateChanged` event, and possibly `DelegateVotesChanged` events for the old and the new delegate accounts, if and only if the following conditions are met:


- The current timestamp is less than or equal to `expiry`.
- `nonces(signer)` (before the state update) is equal to `nonce`.

If any of these conditions are not met, the `delegateBySig` call must revert. This translates to the following solidity code:

```sol
require(expiry &lt;= block.timestamp)
bytes signer = ecrecover(
  keccak256(abi.encodePacked(
    hex&quot;1901&quot;,
    DOMAIN_SEPARATOR,
    keccak256(abi.encode(
      keccak256(&quot;Delegation(address delegatee,uint256 nonce,uint256 expiry)&quot;),
      delegatee,
      nonce,
      expiry)),
  v, r, s)
require(signer != address(0));
require(nounces[signer] == nonce);
// increment nonce
// set delegation of `signer` to `delegatee`
```

where `DOMAIN_SEPARATOR` is defined according to [EIP-712](/EIPs/EIPS/eip-712). The `DOMAIN_SEPARATOR` should be unique to the contract and chain to prevent replay attacks from other domains,
and satisfy the requirements of EIP-712, but is otherwise unconstrained.

A common choice for `DOMAIN_SEPARATOR` is:

```solidity
DOMAIN_SEPARATOR = keccak256(
    abi.encode(
        keccak256(&apos;EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)&apos;),
        keccak256(bytes(name)),
        keccak256(bytes(version)),
        chainid,
        address(this)
));
```

In other words, the message is the EIP-712 typed structure:

```js
{
  &quot;types&quot;: {
    &quot;EIP712Domain&quot;: [
      {
        &quot;name&quot;: &quot;name&quot;,
        &quot;type&quot;: &quot;string&quot;
      },
      {
        &quot;name&quot;: &quot;version&quot;,
        &quot;type&quot;: &quot;string&quot;
      },
      {
        &quot;name&quot;: &quot;chainId&quot;,
        &quot;type&quot;: &quot;uint256&quot;
      },
      {
        &quot;name&quot;: &quot;verifyingContract&quot;,
        &quot;type&quot;: &quot;address&quot;
      }
    ],
    &quot;Delegation&quot;: [{
      &quot;name&quot;: &quot;delegatee&quot;,
      &quot;type&quot;: &quot;address&quot;
      },
      {
        &quot;name&quot;: &quot;nonce&quot;,
        &quot;type&quot;: &quot;uint256&quot;
      },
      {
        &quot;name&quot;: &quot;expiry&quot;,
        &quot;type&quot;: &quot;uint256&quot;
      }
    ],
    &quot;primaryType&quot;: &quot;Permit&quot;,
    &quot;domain&quot;: {
      &quot;name&quot;: contractName,
      &quot;version&quot;: version,
      &quot;chainId&quot;: chainid,
      &quot;verifyingContract&quot;: contractAddress
  },
  &quot;message&quot;: {
    &quot;delegatee&quot;: delegatee,
    &quot;nonce&quot;: nonce,
    &quot;expiry&quot;: expiry
  }
}}
```

Note that nowhere in this definition do we refer to `msg.sender`. The caller of the `delegateBySig` function can be any address.

When this function is successfully executed, the delegator&apos;s nonce MUST be incremented to prevent replay attacks.

#### nonces

This function returns the current nonce for a given account.

Signed delegations (see `delegateBySig`) are only accepted if the nonce used in the EIP-712 signature matches the return of this function. This value of `nonce(delegator)` should be incremented whenever a call to `delegateBySig` is performed on behalf of `delegator`.

This function MUST be implemented

```yaml
- name: nonces
  type: function
  stateMutability: view
  inputs:
    - name: account
      type: delegator
  outputs:
    - name: nonce
      type: uint256
```

### Events

#### DelegateChanged

`delegator` changes the delegation of its assets from `fromDelegate` to `toDelegate`.

MUST be emitted when the delegate for an account is modified by `delegate(address)` or `delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)`.

```yaml
- name: DelegateChanged
  type: event
  inputs:
    - name: delegator
      indexed: true
      type: address
    - name: fromDelegate
      indexed: true
      type: address
    - name: toDelegate
      indexed: true
      type: address
```

#### DelegateVotesChanged

`delegate` available voting power changes from `previousBalance` to `newBalance`.

This MUST be emitted when:

- an account (that holds more than 0 assets) updates its delegation from or to `delegate`,
- an asset transfer from or to an account that is delegated to `delegate`.

```yaml
- name: DelegateVotesChanged
  type: event
  inputs:
    - name: delegate
      indexed: true
      type: address
    - name: previousBalance
      indexed: false
      type: uint256
    - name: newBalance
      indexed: false
      type: uint256
```

### Solidity interface

```sol
interface IERC5805 is IERC6372 /* (optional) */ {
  event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);
  event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);

  function getVotes(address account) external view returns (uint256);
  function getPastVotes(address account, uint256 timepoint) external view returns (uint256);
  function delegates(address account) external view returns (address);
  function nonces(address owner) public view virtual returns (uint256)

  function delegate(address delegatee) external;
  function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;
}
```

### Expected properties

Let `clock` be the current clock.

- For all timepoints `t &lt; clock`, `getVotes(address(0))` and `getPastVotes(address(0), t)` SHOULD return 0.
- For all accounts `a != 0`, `getVotes(a)` SHOULD be the sum of the &quot;balances&quot; of all the accounts that delegate to `a`.
- For all accounts `a != 0` and all timestamp `t &lt; clock`, `getPastVotes(a, t)` SHOULD be the sum of the &quot;balances&quot; of all the accounts that delegated to `a` when `clock` overtook `t`.
- For all accounts `a`, `getPastVotes(a, t)` MUST be constant after `t &lt; clock` is reached.
- For all accounts `a`, the action of changing the delegate from `b` to `c` MUST not increase the current voting power of `b` (`getVotes(b)`) and MUST not decrease the current voting power of `c` (`getVotes(c)`).

## Rationale

Delegation allows token holders to trust a delegate with their vote while keeping full custody of their token. This means that only a small-ish number of delegates need to pay gas for voting. This leads to better representation of small token holders by allowing their votes to be cast without requiring them to pay expensive gas fees. Users can take over their voting power at any point, and delegate it to someone else, or to themselves.

The use of checkpoints prevents double voting. Votes, for example in the context of a governance proposal, should rely on a snapshot defined by a timepoint. Only tokens delegated at that timepoint can be used for voting. This means any token transfer performed after the snapshot will not affect the voting power of the sender/receiver&apos;s delegate. This also means that in order to vote, someone must acquire tokens and delegate them before the snapshot is taken. Governors can, and do, include a delay between the proposal is submitted and the snapshot is taken so that users can take the necessary actions (change their delegation, buy more tokens, ...).

While timestamps produced by ERC-6372&apos;s `clock` are represented as `uint48`, `getPastVotes`&apos;s timepoint argument is `uint256` for backward compatibility. Any timepoint `&gt;=2**48` passed to `getPastVotes` SHOULD cause the function to revert, as it would be a lookup in the future.

`delegateBySig` is necessary to offer a gasless workflow to token holders that do not want to pay gas for voting.

The `nonces` mapping is given for replay protection.

EIP-712 typed messages are included because of their widespread adoption in many wallet providers.

## Backwards Compatibility

Compound and OpenZeppelin already provide implementations of voting tokens. The delegation-related methods are shared between the two implementations and this ERC. For the vote lookup, this ERC uses OpenZeppelin&apos;s implementation (with return type uint256) as Compound&apos;s implementation causes significant restrictions of the acceptable values (return type is uint96).

Both implementations use `block.number` for their checkpoints and do not implement ERC-6372, which is compatible with this ERC.

Existing governors, that are currently compatible with OpenZeppelin&apos;s implementation will be compatible with the &quot;block number mode&quot; of this ERC.

## Security Considerations

Before doing a lookup, one should check the return value of `clock()` and make sure that the parameters of the lookup are consistent. Performing a lookup using a timestamp argument on a contract that uses block numbers will very likely cause a revert. On the other end, performing a lookup using a block number argument on a contract that uses timestamps will likely return 0.

Though the signer of a `Delegation` may have a certain party in mind to submit their transaction, another party can always front-run this transaction and call `delegateBySig` before the intended party. The result is the same for the `Delegation` signer, however.

Since the ecrecover precompile fails silently and just returns the zero address as `signer` when given malformed messages, it is important to ensure `signer != address(0)` to avoid `delegateBySig` from delegating &quot;zombie funds&quot; belonging to the zero address.

Signed `Delegation` messages are censorable. The relaying party can always choose to not submit the `Delegation` after having received it, withholding the option to submit it. The `expiry` parameter is one mitigation to this. If the signing party holds ETH they can also just submit the `Delegation` themselves, which can render previously signed `Delegation`s invalid.

If the `DOMAIN_SEPARATOR` contains the `chainId` and is defined at contract deployment instead of reconstructed for every signature, there is a risk of possible replay attacks between chains in the event of a future chain split.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 04 Jul 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5805</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5805</guid>
      </item>
    
      <item>
        <title>Delegate transaction</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5806-delegate-transaction/11409</comments>
        
        <description>## Abstract

This EIP adds a new transaction type that allows EOAs to execute arbitrary code using a delegate-call-like mechanism.

## Motivation

EOA are the most widely used type of account, yet their ability to perform operations is limited to deploying contracts and sending &quot;call&quot; transactions. It is currently not possible for an EOA to execute arbitrary code, which greatly limits the interactions users can have with the blockchain. Account abstraction has been extensively discussed but the path toward mainstream adoption is still unclear. Some approaches, such as [ERC-4337](/EIPs/EIPS/eip-4337) hope to improve the usability of smart wallets, without addressing the issue of smart wallet support by applications.

While smart contract wallets have a lot to offer in terms of UX, it is unlikely that all users will migrate any time soon because of the associated cost and the fact that some EOAs have custody of non-transferable assets.

This EIP proposes an approach to allow the execution of arbitrary code by EOAs, with minimal change over the EVM, and using the same security model users are used to. By allowing EOAs to perform delegate calls to a contract (similarly to how contracts can delegate calls to other contracts using [EIP-7](/EIPs/EIPS/eip-7)), EOAs will be able to have more control over what operations they want to execute. This proposal&apos;s goal is NOT to provide an account abstraction primitive.

By performing a delegate call to a multicall contract (such as the one deployed to `0xcA11bde05977b3631167028862bE2a173976CA11`), EOAs would be able to batch multiple transactions into a single one (being the `msg.sender` of all the sub calls). This would provide a better UX for users that want to interact with protocols (no need for multiple transactions, with variable gas prices and 21k gas overhead) and increase the security of such interactions (by avoiding unsafe token approvals being exploited between an `approval` and the following `transferFrom`).

Other unforeseen logic could be implemented in smart contracts and used by EOA. This includes emitting events.

This EIP doesn&apos;t aim to replace other account abstraction proposals. It hopes to be an easy-to-implement alternative that would significantly improve the user experience of EOA owners in the near future.

## Specification

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.

### Parameters

- `FORK_BLKNUM` = `TBD`
- `TX_TYPE` = TBD, &gt; 0x03 ([EIP-4844](/EIPs/EIPS/eip-4844))

As of `FORK_BLOCK_NUMBER`, a new [EIP-2718](/EIPs/EIPS/eip-2718) transaction is introduced with `TransactionType` = `TX_TYPE(TBD)`.

The intrinsic cost of the new transaction is inherited from [EIP-2930](/EIPs/EIPS/eip-2930), specifically `21000 + 16 * non-zero calldata bytes + 4 * zero calldata bytes + 1900 * access list storage key count + 2400 * access list address count`.

The [EIP-2718](/EIPs/EIPS/eip-2718) `TransactionPayload` for this transaction is

```
rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, data, access_list, signature_y_parity, signature_r, signature_s])
```

The definitions of all fields follow the same semantics as [EIP-1559](/EIPs/EIPS/eip-1559). Note the absence of `amount` field in this transaction!

The `to` field deviates slightly from the semantics with the exception that it MUST NOT be nil and therefore must always represent a 20-byte address. This means that delegate transactions cannot have the form of a create transaction.

The `signature_y_parity, signature_r, signature_s` elements of this transaction represent a secp256k1 signature over `keccak256(TX_TYPE || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, data, access_list]))`.

The [EIP-2718](/EIPs/EIPS/eip-2718) `ReceiptPayload` for this transaction is `rlp([status, cumulative_transaction_gas_used, logs_bloom, logs])`.

The execution of this new transaction type is equivalent to the delegate call mechanism introduced in [EIP-7](/EIPs/EIPS/eip-7), but performed by an EOA (the transaction sender). This implies that the code present at `destination`, if any, should be executed in the context of the sender. As a consequence, such a transaction emit an event from the EOA or use `Create2` with the address of the EOA as the creator. This transaction includes some restrictions though.

### Opcode restriction

For security reasons, some opcodes should not be executed in the context of an EOA:

- `SSTORE` (0x55): Setting storage under an EOA breaks many assumptions. In particular storage set through a delegate transaction could cause issues if the accounts later &quot;migrates&quot; using [EIP-7377](/EIPs/EIPS/eip-7377) or similar. Additionally, storage may be a source of conflicts if a single EOA uses delegate transactions to target codes that interpret the storage layout under this account differently. For all these reasons, EOA should be forbidden from performing `SSTORE` in the context of a delegate transaction. If a delegate transaction performs a CALL, the target of the call is free to manipulate storage normally.

- `CREATE` (0xF0), `CREATE2` (0xF5) and `SELFDESTRUCT` (0xFF): There may be an expectation that transactions from a given sender should have consecutive nonces. This assumption would be broken if an EOA was able to execute one or multiple operations that alter the sender account&apos;s nonce. Consequently, EOA performing a delegate transaction should not be able to use the `CREATE`, `CREATE2` or `SELFDESTRUCT` opcodes. If a delegate transaction performs a CALL, the target of the call is free to create contracts normally.

Any attempts to make execute one of these restricted operations will instead throw an exception.

## Rationale

EOAs are the most widely used type of wallet.

This EIP would drastically expand the ability of EOAs to interact with smart contracts by using the pre-existing and well-understood delegation mechanism introduced in [EIP-7](/EIPs/EIPS/eip-7) and without adding new complexity to the EVM.

## Backwards Compatibility

No known backward compatibility issues thanks to the transaction envelope ([EIP-2718](/EIPs/EIPS/eip-2718)).

Due to the inclusion logic and the gas cost being similar to type 2 transactions, it should be possible to include this new transaction type in the same mempool.

## Security Considerations

The nonce mechanism, already used in other transaction types, prevents replay attacks. Similar to existing transaction types, a delegate transaction can be cancelled by replacing it with a dummy transaction that pays more fees.

Since the object signed by the wallet is a transaction and not a signature that could potentially be processed in many ways (as is the case for [EIP-3074](/EIPs/EIPS/eip-3074)), the risks associated with the miss-use of the signature are reduced. A wallet could simulate the execution of this delegate transaction and provide good guarantees that the operation that the user signs won&apos;t be manipulated.

Contracts being called through this mechanism can execute any operation on behalf of the signer. As with other transaction types, signers should be extremely careful when signing a delegate transaction.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 20 Oct 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5806</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5806</guid>
      </item>
    
      <item>
        <title>Auto-renewable allowance extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5827-auto-renewable-allowance-extension/10392</comments>
        
        <description>## Abstract

This extension adds a renewable allowance mechanism to [ERC-20](/EIPs/EIPS/eip-20) allowances, in which a `recoveryRate` defines the amount of token per second that the allowance regains towards the initial maximum approval `amount`.

## Motivation

Currently, ERC-20 tokens support allowances, with which token owners can allow a spender to spend a certain amount of tokens on their behalf. However, this is not ideal in circumstances involving recurring payments (e.g. subscriptions, salaries, recurring direct-cost-averaging purchases).

Many existing DApps circumvent this limitation by requesting that users grant a large or unlimited allowance. This presents a security risk as malicious DApps can drain users&apos; accounts up to the allowance granted, and users may not be aware of the implications of granting allowances.

An auto-renewable allowance enables many traditional financial concepts like credit and debit limits. An account owner can specify a spending limit, and limit the amount charged to the account based on an allowance that recovers over time.


## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

```solidity
pragma solidity ^0.8.0;

interface IERC5827 /* is ERC20, ERC165 */ {
    /*
     * Note: the ERC-165 identifier for this interface is 0x93cd7af6.
     * 0x93cd7af6 ===
     *   bytes4(keccak256(&apos;approveRenewable(address,uint256,uint256)&apos;)) ^
     *   bytes4(keccak256(&apos;renewableAllowance(address,address)&apos;)) ^
     *   bytes4(keccak256(&apos;approve(address,uint256)&apos;) ^
     *   bytes4(keccak256(&apos;transferFrom(address,address,uint256)&apos;) ^
     *   bytes4(keccak256(&apos;allowance(address,address)&apos;) ^
     */

    /**
     * @notice  Thrown when the available allowance is less than the transfer amount.
     * @param   available       allowance available; 0 if unset
     */
    error InsufficientRenewableAllowance(uint256 available);

    /**
     * @notice  Emitted when any allowance is set.
     * @dev     MUST be emitted even if a non-renewable allowance is set; if so, the
     * @dev     `_recoveryRate` MUST be 0.
     * @param   _owner          owner of token
     * @param   _spender        allowed spender of token
     * @param   _value          initial and maximum allowance granted to spender
     * @param   _recoveryRate   recovery amount per second
     */
    event RenewableApproval(
        address indexed _owner,
        address indexed _spender,
        uint256 _value,
        uint256 _recoveryRate
    );

    /**
     * @notice  Grants an allowance of `_value` to `_spender` initially, which recovers over time 
     * @notice  at a rate of `_recoveryRate` up to a limit of `_value`.
     * @dev     SHOULD cause `allowance(address _owner, address _spender)` to return `_value`, 
     * @dev     SHOULD throw when `_recoveryRate` is larger than `_value`, and MUST emit a 
     * @dev     `RenewableApproval` event.
     * @param   _spender        allowed spender of token
     * @param   _value          initial and maximum allowance granted to spender
     * @param   _recoveryRate   recovery amount per second
     */
    function approveRenewable(
        address _spender,
        uint256 _value,
        uint256 _recoveryRate
    ) external returns (bool success);

    /**
     * @notice  Returns approved max amount and recovery rate of allowance granted to `_spender` 
     * @notice  by `_owner`.
     * @dev     `amount` MUST also be the initial approval amount when a non-renewable allowance 
     * @dev     has been granted, e.g. with `approve(address _spender, uint256 _value)`.
     * @param    _owner         owner of token
     * @param   _spender        allowed spender of token
     * @return  amount initial and maximum allowance granted to spender
     * @return  recoveryRate recovery amount per second
     */
    function renewableAllowance(address _owner, address _spender)
        external
        view
        returns (uint256 amount, uint256 recoveryRate);

    /// Overridden ERC-20 functions

    /**
     * @notice  Grants a (non-increasing) allowance of _value to _spender and clears any existing 
     * @notice  renewable allowance.
     * @dev     MUST clear set `_recoveryRate` to 0 on the corresponding renewable allowance, if 
     * @dev     any.
     * @param   _spender        allowed spender of token
     * @param   _value          allowance granted to spender
     */
    function approve(address _spender, uint256 _value)
        external
        returns (bool success);

    /**
    * @notice   Moves `amount` tokens from `from` to `to` using the caller&apos;s allowance.
    * @dev      When deducting `amount` from the caller&apos;s allowance, the allowance amount used 
    * @dev      SHOULD include the amount recovered since the last transfer, but MUST NOT exceed 
    * @dev      the maximum allowed amount returned by `renewableAllowance(address _owner, address 
    * @dev      _spender)`. 
    * @dev      SHOULD also throw `InsufficientRenewableAllowance` when the allowance is 
    * @dev      insufficient.
    * @param    from            token owner address
    * @param    to              token recipient
    * @param    amount          amount of token to transfer
    */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);

    /**
     * @notice  Returns amount currently spendable by `_spender`.
     * @dev     The amount returned MUST be as of `block.timestamp`, if a renewable allowance 
     * @dev     for the `_owner` and `_spender` is present.
     * @param   _owner         owner of token
     * @param   _spender       allowed spender of token
     * @return  remaining allowance at the current point in time
     */
    function allowance(address _owner, address _spender)
        external
        view
        returns (uint256 remaining);
}
```

Base method `approve(address _spender, uint256 _value)` MUST set `recoveryRate` to 0.

Both `allowance()` and `transferFrom()` MUST be updated to include allowance recovery logic.

`approveRenewable(address _spender, uint256 _value, uint256 _recoveryRate)` MUST set both the initial allowance amount and the maximum allowance limit (to which the allowance can recover) to `_value`.

`supportsInterface(0x93cd7af6)` MUST return `true`.

### Additional interfaces

**Token Proxy**

Existing ERC-20 tokens can delegate allowance enforcement to a proxy contract that implements this specification. An additional query function exists to get the underlying ERC-20 token.

```solidity
interface IERC5827Proxy /* is IERC5827 */ {

    /*
     * Note: the ERC-165 identifier for this interface is 0xc55dae63.
     * 0xc55dae63 ===
     *   bytes4(keccak256(&apos;baseToken()&apos;)
     */

    /**
     * @notice   Get the underlying base token being proxied.
     * @return   baseToken address of the base token
     */
    function baseToken() external view returns (address);
}
```

The `transfer()` function on the proxy MUST NOT emit the `Transfer` event (as the underlying token already does so).

**Automatic Expiration**

```solidity
interface IERC5827Expirable /* is IERC5827 */ {
    /*
     * Note: the ERC-165 identifier for this interface is 0x46c5b619.
     * 0x46c5b619 ===
     *   bytes4(keccak256(&apos;approveRenewable(address,uint256,uint256,uint64)&apos;)) ^
     *   bytes4(keccak256(&apos;renewableAllowance(address,address)&apos;)) ^
     */

    /**
     * @notice  Grants an allowance of `_value` to `_spender` initially, which recovers over time 
     * @notice  at a rate of `_recoveryRate` up to a limit of `_value` and expires at 
     * @notice  `_expiration`.
     * @dev     SHOULD throw when `_recoveryRate` is larger than `_value`, and MUST emit 
     * @dev     `RenewableApproval` event.
     * @param   _spender        allowed spender of token
     * @param   _value          initial allowance granted to spender
     * @param   _recoveryRate   recovery amount per second
     * @param   _expiration     Unix time (in seconds) at which the allowance expires
     */
    function approveRenewable(
        address _spender,
        uint256 _value,
        uint256 _recoveryRate,
        uint64 _expiration
    ) external returns (bool success);

    /**
     * @notice  Returns approved max amount, recovery rate, and expiration timestamp.
     * @return  amount initial and maximum allowance granted to spender
     * @return  recoveryRate recovery amount per second
     * @return  expiration Unix time (in seconds) at which the allowance expires
     */
    function renewableAllowance(address _owner, address _spender)
        external
        view
        returns (uint256 amount, uint256 recoveryRate, uint64 expiration);
}
```

## Rationale

Renewable allowances can be implemented with discrete resets per time cycle. However, a continuous `recoveryRate` allows for more flexible use cases not bound by reset cycles and can be implemented with simpler logic.

## Backwards Compatibility

Existing ERC-20 token contracts can delegate allowance enforcement to a proxy contract that implements this specification.

## Reference Implementation

An minimal implementation is included [here](/EIPs/assets/eip-5827/ERC5827.sol)

An audited, open source implemention of this standard as a `IERC5827Proxy` can be found at `https://github.com/suberra/funnel-contracts`

## Security Considerations

This EIP introduces a stricter set of constraints compared to ERC-20 with unlimited allowances. However, when `_recoveryRate` is set to a large value, large amounts can still be transferred over multiple transactions.

Applications that are not [ERC-5827](/EIPs/EIPS/eip-5827)-aware may erroneously infer that the value returned by `allowance(address _owner, address _spender)` or included in `Approval` events is the maximum amount of tokens that `_spender` can spend from `_owner`. This may not be the case, such as when a renewable allowance is granted to `_spender` by `_owner`.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 22 Oct 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5827</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5827</guid>
      </item>
    
      <item>
        <title>Complex Numbers stored in `bytes32` types</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5850-store-real-and-imaginary-parts-of-complex-numbers-in-the-least-significant-and-most-significant-16-bytes-respectively-of-a-bytes32-type/11532</comments>
        
        <description>## Abstract

This EIP proposes a natural way for complex numbers to be stored in and retrieved from the `bytes32` data-type.  It splits the storage space exactly in half and, most importantly, assigns the real number part to the least significant 16 bytes and the imaginary number part to the most significant 16 bytes.

## Motivation

Complex numbers are an essential tool for many mathematical and scientific calculations.  For example, Fourier Transforms, Characteristic functions, AC Circuits and Navier-Stokes equations all require the concept.

Complex numbers can be represented in many different forms (polynomial, cartesian, polar, exponential).  The EIP creates a standard that can accommodate cartesian, polar and exponential formats with example code given for the Cartesian representation, where a complex number is just the pair of real numbers which gives the real and imaginary co-ordinates of the complex number. Equal storage capacity is assigned to both components and the order they appear is explicitly defined.  

Packing complex numbers into a single `bytes32` data object halves storage costs and creates a more natural code object that can be passed around the solidity ecosystem.  Existing code may not need to be rewritten for complex numbers.  For example, mappings by `bytes32` are common and indexing in the 2D complex plane may improve code legibility.  

Decimal numbers, either fix or floating, are not yet fully supported by Solidity so enforcing similar standards for complex versions is premature.  It can be suggested that fixed point methods such as prb-math be used with 18 decimal places, or floating point methods like abdk.  However, it should be noted that this EIP supports any decimal number representation so long as it fits inside the 16 bytes space.

## Specification

A complex number would be defined as `bytes32` and a cartesian representation would be initialized with the `cnNew` function and converted back with `RealIm`, both given below.

To create the complex number one would use

```solidity
function cnNew(int128 _Real, int128 _Imag) public pure returns (bytes32){
    bytes32 Imag32 = bytes16(uint128(_Imag));
    bytes32 Real32 = bytes16(uint128(_Real));
    return (Real32&gt;&gt; 128) | Imag32;
}
```

and to convert back

```solidity
function RealIm(bytes32 _cn)  public pure returns (int128 Real, int128 Imag){
    bytes16[2] memory tmp = [bytes16(0), 0];
    assembly {
        mstore(tmp, _cn)
        mstore(add(tmp, 16), _cn)
    }
    Imag=int128(uint128(tmp[0]));
    Real=int128(uint128(tmp[1]));
}
```

## Rationale

An EIP is required as this proposal defines a complex numbers storage/type standard for multiple apps to use.

This EIP proposes to package both the real and imaginary within one existing data type, `bytes32`.  This allows compact storage without the need for structures and facilitates easy library implementations.  The `bytes32` would remain available for existing, non-complex number uses.
Only the split and position of the real &amp; imaginary parts is defined in this EIP.  Manipulation of complex numbers (addition, multiplication etc.), number of decimal places and other such topics are left for other EIP discussions.  This keeps this EIP more focused and therefore more likely to succeed.

Defining real numbers in the 16 least-significant bytes allows direct conversion from `uint128` to `bytes32` for positive integers less than 2**127.  
Direct conversion back from `bytes32` -&gt; `uint` -&gt; `int` are not recommended as the complex number may contain imaginary parts and/or the real part may be negative. It is better to always use `RealIm` for separating the complex part.  

Libraries for complex number manipulation can be implemented with the `Using Complex for bytes32` syntax where `Complex` would be the name of the library.  

## Backwards Compatibility

There is no impact on other uses of the `bytes32` datatype.  

## Security Considerations

If complex numbers are manipulated in `bytes32` form then overflow checks must be performed manually during the manipulation.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 29 Oct 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5850</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5850</guid>
      </item>
    
      <item>
        <title>On-Chain Verifiable Credentials</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5815-kyc-certification-issuer-and-verifier-standard/11513</comments>
        
        <description>## Abstract

This proposal introduces a method of certifying that a particular address meets a claim, and a method of verifying those certifications using on-chain metadata. Claims are assertions or statements made about a subject having certain properties that may be met conditions (for example: `age &gt;= 18`), and are certified by issuers using a Soundbound Token (SBT).

## Motivation

On-chain issuance of verifiable attestations are essential for use-case like:

- Avoiding Sybil attacks with one person one vote
- Participation in certain events with credentials
- Compliance to government financial regulations etc.

We are proposing a standard claims structure for Decentralized Identity (DID) issuers and verifier entities to create smart contracts in order to provide on-chain commitment of the off-chain verification process, and once the given address is associated with the given attestation of the identity verification off-chain, the issuers can then onboard other verifiers (i.e. governance, financial institution, non-profit organization, web3 related cooperation) to define the condition of the ownership of the user in order to reduce the technical barriers and overhead of current implementations.

The motivation behind this proposal is to create a standard for verifier and issuer smart contracts to communicate with each other in a more efficient way. This will reduce the cost of KYC processes, and provide the possibility for on-chain KYC checks.  By creating a standard for communication between verifiers and issuers, it will create an ecosystem in which users can be sure their data is secure and private. This will ultimately lead to more efficient KYC processes and help create a more trustful environment for users. It will also help to ensure that all verifier and issuer smart contracts are up-to-date with the most recent KYC regulations.

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119 and RFC 8174.

### Definitions

- Zero-Knowledge Proof (ZKP): a cryptographic device that can convince a verifier that an assertion is correct without revealing all of the inputs to the assertion.

- Soulbound Token (SBT): A non-fungible and non-transferrable token that is used for defining the identity of the users.

- SBT Certificate: An SBT that represents the ownership of ID signatures corresponding to the claims defined in `function standardClaim()`.

- Verifiable Credential (VC): A collection of claims made by an issuer. These are temper evident credentials that allow the holders to prove that they posses certain characteristics (for example, passport verification, constraints like value of tokens in your wallet, etc) as demanded by the verifier entity.

- Claim: An assertion that the DID Holder must fulfill to be verified.

- Holder: The entity that stores the claim, such as a digital identity provider or a DID registry. The holder is responsible for validating the claim and providing verifiable evidence of the claim.

- Claimer: The party making a claim, such as in an identity verification process.

- Issuer: The entity that creates a verifiable credential from claims about one or more subjects to a holder. Example issuers include governments, corporations, non-profit organizations, trade associations, and individuals.

- Verifier: An entity that validates data provided by an issuer of verifiable credentials, determining its accuracy, origin, currency and trustworthiness.



### Metadata Standard

Claims MUST be exposed in the following structures:

#### 1. Metadata information

Each claim requirement MUST be exposed using the following structure:

```solidity
    /** Metadata
    * 
    * @param title defines the name of the claim field
    * @param _type is the type of the data (bool,string,address,bytes,..)
    * @param description additional information about claim details.
     */
    struct Metadata {
        string title;
        string _type;
        string description;
    }
```

#### 2. Values Information

This following structure will be used to define the actual claim information, based on the description of the `Metadata` structure, the structure is the same as `Values` structure of [EIP-3475](/EIPs/EIPS/eip-3475).

```solidity
   struct Values{
       string stringValue;
       uint uintValue;
       address addressValue;
       bool boolValue;
  }
```

#### 3. Claim structure

Claims (eg. `age &gt;= 18`, jurisdiction in allowlist, etc.) are represented by one or many instances of the `Claim` structure below:

```solidity
    /** Claims
    * 
    * Claims structure consist of the conditions and value that holder claims to associate and verifier has to validate them.
    * @notice the below given parameters are for reference purposes only, developers can optimize the fields that are needed to be represented on-chain by using schemes like TLV, encoding into base64 etc.
    * @dev structure that defines the parameters for specific claims of the SBT certificate
    * @notice this structure is used for the verification process, it contains the metadata, logic and expectation
    * @notice logic can represent either the enum format for defining the different operations, or they can be logic operators (stored in form of ASCII figure based on unicode standard). like  e.g: 
(&quot;⊄&quot; = U+2284, &quot;⊂&quot; = U+2282,  &quot;&lt;&quot; = U+003C , &quot;&lt;=&quot; = U + 2265,&quot;==&quot; = U + 003D, &quot;!=&quot;U + 2260, &quot;&gt;=&quot; = U + 2265,&quot;&gt;&quot; =  U + 2262).
    */
    struct Claim {
        Metadata metadata;
        string logic;
        Values expectation;
   
    }
```

description of some logic functions that can be used are as follows: 

| Symbol | Description |
|--------|--------------|
| ⊄ | does not belong to the set of values (or range) defined by the corresponding `Values`  |
| ⊂ | condition that the parameter belongs to one of values defined by the `Values`  |
| &lt; | condition that the parameter is greater than  value defined by the `Values`  |
| == | condition that the parameter is strictly equal to the value defined by the `Values` structure |

#### Claim Example

```json
{
   &quot;title&quot;:&quot;age&quot;,
   &quot;type&quot;:&quot;unit&quot;,
   &quot;description&quot;:&quot;age of the person based on the birth date on the legal document&quot;,
   &quot;logic&quot;:&quot;&gt;=&quot;,
   &quot;value&quot;:&quot;18&quot;
}
```

Defines the condition encoded for the index 1 (i.e the holder must be equal or more than 18 years old).

### Interface specification

#### Verifier

```solidity

    /// @notice getter function to validate if the address `claimer` is the holder of the claim defined by the tokenId `SBTID`
    /// @dev it MUST be defining the conditional operator (logic explained below) to allow the application to convert it into code logic 
    /// @dev logic given here MUST be the conditiaonl operator, MUST be one of (&quot;⊄&quot;, &quot;⊂&quot;, &quot;&lt;&quot;, &quot;&lt;=&quot;, &quot;==&quot;, &quot;!=&quot;, &quot;&gt;=&quot;, &quot;&gt;&quot;)
    /// @param claimer is the EOA address that wants to validate the SBT issued to it by the issuer. 
    /// @param SBTID is the Id of the SBT that user is the claimer.
    /// @return true if the assertion is valid, else false
    /**
    example ifVerified(0xfoo, 1) =&gt; true will mean that 0xfoo is the holder of the SBT identity token defined by tokenId of the given collection. 
    */
    function ifVerified(address claimer, uint256 SBTID) external view returns (bool);
```

#### Issuer  

```solidity
  
    /// @notice getter function to fetch the on-chain identification logic for the given identity holder.
    /// @dev it MUST not be defined for address(0). 
    /// @param SBTID is the Id of the SBT that the user is the claimer.
    /// @return the struct array of all the descriptions of condition metadata that is defined by the administrator for the given KYC provider.
    /**
    ex: standardClaim(1) --&gt; {
    { &quot;title&quot;:&quot;age&quot;,
        &quot;type&quot;: &quot;uint&quot;,
        &quot;description&quot;: &quot;age of the person based on the birth date on the legal document&quot;,
        },
       &quot;logic&quot;: &quot;&gt;=&quot;,
    &quot;value&quot;:&quot;18&quot;  
    }
    Defines the condition encoded for the identity index 1, defining the identity condition that holder must be equal or more than 18 years old.
    **/

    function standardClaim(uint256 SBTID) external view returns (Claim[] memory);

    /// @notice function for setting the claim requirement logic (defined by Claims metadata) details for the given identity token defined by SBTID.
    /// @dev it should only be called by the admin address.
    /// @param SBTID is the Id of the SBT-based identity certificate for which the admin wants to define the Claims.
    /// @param `claims` is the struct array of all the descriptions of condition metadata that is defined by the administrator. check metadata section for more information.
    /**
    example: changeStandardClaim(1, { &quot;title&quot;:&quot;age&quot;,
            &quot;type&quot;: &quot;uint&quot;,
            &quot;description&quot;: &quot;age of the person based on the birth date on the legal document&quot;,
            },
        &quot;logic&quot;: &quot;&gt;=&quot;,
        &quot;value&quot;:&quot;18&quot;  
    }); 
    will correspond to the functionality that admin needs to adjust the standard claim for the identification SBT with tokenId = 1, based on the conditions described in the Claims array struct details.
    **/

    function changeStandardClaim(uint256 SBTID, Claim[] memory _claims) external returns (bool);

    /// @notice function which uses the ZKProof protocol to validate the identity based on the given 
    /// @dev it should only be called by the admin address.
    /// @param SBTID is the Id of the SBT-based identity certificate for which admin wants to define the Claims.
    /// @param claimer is the address that needs to be proven as the owner of the SBT defined by the tokenID.
    /**
    example: certify(0xA....., 10) means that admin assigns the DID badge with id 10 to the address defined by the `0xA....` wallet.
    */
    function certify(address claimer, uint256 SBTID) external returns (bool);

    /// @notice function which uses the ZKProof protocol to validate the identity based on the given 
    /// @dev it should only be called by the admin address.
    /// @param SBTID is the Id of the SBT-based identity certificate for which the admin wants to define the Claims.
    /// @param claimer is the address that needs to be proven as the owner of the SBT defined by the tokenID.
    /* eg: revoke(0xfoo,1): means that KYC admin revokes the SBT certificate number 1 for the address &apos;0xfoo&apos;. */
    function revoke(address certifying, uint256 SBTID) external returns (bool);

```

#### Events

```solidity
    /** 
    * standardChanged
    * @notice standardChanged MUST be triggered when claims are changed by the admin. 
    * @dev standardChanged MUST also be triggered for the creation of a new SBTID.
    e.g : emit StandardChanged(1, Claims(Metadata(&apos;age&apos;, &apos;uint&apos;, &apos;age of the person based on the birth date on the legal document&apos; ), &quot;&gt;=&quot;, &quot;18&quot;);
    is emitted when the Claim condition is changed which allows the certificate holder to call the functions with the modifier, claims that the holder must be equal or more than 18 years old.
    */
    event StandardChanged(uint256 SBTID, Claim[] _claims);
    
    /** 
    * certified
    * @notice certified MUST be triggered when the SBT certificate is given to the certifying address. 
    * eg: Certified(0xfoo,2); means that wallet holder address `0xfoo` is certified to hold a certificate issued with id 2, and thus can satisfy all the conditions defined by the required interface.
    */
    event Certified(address claimer, uint256 SBTID);
    
    /** 
    * revoked
    * @notice revoked MUST be triggered when the SBT certificate is revoked. 
    * eg: Revoked( 0xfoo,1); means that entity user 0xfoo has been revoked to all the function access defined by the SBT ID 1.
    */
    event Revoked(address claimer, uint256 SBTID);
}
```

## Rationale

TBD

## Backwards Compatibility

- This EIP is backward compliant for the contracts that keep intact the metadata structure of previous issued SBT&apos;s with their ID and claim requirement details.
  - For e.g if the DeFI provider (using the modifiers to validate the ownership of required SBT by owner) wants the admin to change the logic of verification or remove certain claim structure, the previous holders of the certificates will be affected by these changes.

## Test Cases

Test cases for the minimal reference implementation can be found [here](/EIPs/assets/eip-5851/contracts/test.sol) for using transaction verification regarding whether the users hold the tokens or not. Use Remix IDE to compile and test the contracts.

## Reference Implementation

The [interface](/EIPs/assets/eip-5851/contracts/interfaces/IERC5851.sol) is divided into two separate implementations:

- [EIP-5851 Verifier](/EIPs/assets/eip-5851/contracts/ERC5851Verifier.sol) is a simple modifier that needs to be imported by functions that are to be only called by holders of the SBT certificates. Then the modifier will call the issuer contract to verifiy if the claimer has the SBT certifcate in question.

- [EIP-5851 Issuer](/EIPs/assets/eip-5851/contracts/ERC5851Issuer.sol) is an example of an identity certificate that can be assigned by a KYC controller contract. This is a full implementation of the standard interface.

## Security Considerations

1. Implementation of functional interfaces for creating KYC on SBT (i.e `changeStandardClaim()`, `certify()` and `revoke()`) are dependent on the admin role. Thus the developer must insure security of admin role and rotation of this role to the entity entrusted by the KYC attestation service provider and DeFI protocols that are using this attestation service.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 18 Oct 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5851</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5851</guid>
      </item>
    
      <item>
        <title>Token Transfer by Social Recovery</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5806-delegate-transaction/11409</comments>
        
        <description>## Abstract

This EIP standardizes a mechanism of a social recovery where a token may be transferred from an inaccessible account to a new account, given enough approvals from other identities. This approval is not purely technical, but rather needs human intervention. These humans are - based on the Soul Bound Token proposal - called Souls. When enough Souls give their approval (which is a Yes/No decision) and a threshold is reached, a token is transferred from an old to a new identity.

## Motivation

It is a known problem that the private key of an account can be lost. If that key is lost it&apos;s not possible to recover the tokens owned by that account. The holder loses those tokens forever. In addition to directly harming the token holder, the entire  ecosystem of the token itself is affected: the more tokens that are lost the less tokens are available for the natural growth and planned evolution of that ecosystem.


## Specification

```solidity

pragma solidity ^0.8.7;

interface ISocialRecovery {
    /// @dev Related but independent identity approves the transfer
    function approveTransfer(address from_, address to_) external;

    /// @dev User wants to move their onchain identity to another wallet which needs to be approved by n-nearest neighbour identities
    function requestTransfer(address from_, address to_) external payable;

    function addNeighbour(address neighbour_) external;

    function removeNeighbour(address neighbour_) external;
}
```

**The math behind it**:

A compliant contract SHOULD calculate the score of a node n with the following formula:

$$ score(n) = tanh({ { {\displaystyle\sum_{i = 1}^{|N|} } {log{(n_i^{r} {1 \over t - n_i^{t} + 1})}} \over{|N| + 1}} + n^{r}}) $$

where:

$t$ is the current time (can be any time-identifying value such as `block.timestamp`, `block.number`, etc.)

$n^{r}$ is the reward count of the node n

$N$ is the list of neighbours of n

$n_i^{r}$ is the reward count of neighbour node i from n

$n_i^{t}$ is the last timestamp (where a reward was booked on that account) of neighbour node i from n


**Flows**:

```mermaid
%% Approval of asset movement
 sequenceDiagram
  AnyWallet-&gt;SmartContract: Requests transfer
  SmartContract-&gt;All neighbours: Centralized notification via Websocket, EPNS, etc.
  Neighbour-&gt;SmartContract: Approve Transfer
  alt Threshold amount of approvers reached
  alt Cumulative Score of approvers above threshold
  SmartContract-&gt;NewAssetOwner: Transfer asset (e.g. identity token)
  end
  end
  SmartContract-&gt;Neighbour: Add Reward to approver
```


## Rationale

The formula proposed was deemed very resilient and provides a coherent incentivation structure to actually see value in the on-chain score. The formula adds weights based on scores based on time which further contributes to the fairness of the metric. 


## Security Considerations


1) We currently do not see any mechanism of preventing a user of getting a lot of rewards. Sure, a high reward is bound to a lot of investment but the person who wants to get that reward amount and has a enough money will reach it. The only thing which could be improved is that we somehow find a mechanism really identify users bound to an address. We thought about having a kind of a hashing mechanism which hashes a real world object which could be fuzzy (for sure!) and generates a hash out of it which is the same based on the fuzzy set.

2) We implemented a threshold which must be reached to make a social token transfer possible. Currently there is no experience which defines a &quot;good&quot; or &quot;bad&quot; threshold hence we tried to find a first value. This can or must be adjusted based on future experience.

3) Another problem we see is that the network of the neighbours is not active anymore to reach the necessary minimum threshold. Which means that due to not being able to reach the minimum amount of approvals a user gets stuck with the e.g. social token transfer he/she wants to perform. Hence the contract lives from its usage and if it tends to be not used anymore it will get useless.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 19 Jul 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5883</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5883</guid>
      </item>
    
      <item>
        <title>Smart Contract Event Hooks</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/idea-smart-contract-event-hooks-standard/11503</comments>
        
        <description>## Abstract

This EIP proposes a standard for creating &quot;hooks&quot; that allow a smart contract function to be called automatically in response to a trigger fired by another contract, by using a public relayer network as a messaging bus.

While there are many similar solutions in existence already, this proposal describes a simple yet powerful primitive that can be employed by many applications in an open, permissionless and decentralized manner.

It relies on two interfaces, one for a publisher contract and one for a subscriber contract.  The publisher contract emits events that are picked up by &quot;relayers&quot;, who are independent entities that subscribe to &quot;hook&quot; events on publisher contracts, and call a function on the respective subscriber contracts, whenever a hook event is fired by the publisher contracts.  Whenever a relayer calls the respective subscriber&apos;s contract with the details of the hook event emitted by the publisher contract, they are paid a fee by the subscriber.  Both the publisher and subscriber contracts are registered in a central registry smart contract that relayers can use to discover hooks.

## Motivation

There exists a number of use cases that require some off-chain party to monitor the chain and respond to on-chain events by broadcasting a transaction.  Such cases usually require some off-chain process to run alongside an Ethereum node in order to subscribe to events emitted by smart contract, and then execute some logic in response and subsequently broadcast a transaction to the network.  This requires an Ethereum node and an open websocket connection to some long-running process that may only be used infrequently, resulting in a sub-optimal use of resources.

This proposal would allow for a smart contract to contain the logic it needs to respond to events without having to store that logic in some off-chain process.  The smart contract can subscribe to events fired by other smart contracts and would only execute the required logic when it is needed. This method would suit any contract logic that does not require off-chain computation, but usually requires an off-chain process to monitor the chain state. With this approach, subscribers do not need their own dedicated off-chain processes for monitoring and responding to contract events.  Instead, a single incentivized relayer can subscribe to many different events on behalf of multiple different subscriber contracts.

Examples of use cases that would benefit from this scheme include:

### Collateralised Lending Protocols

Collateralised lending protocols or stablecoins can emit events whenever they receive price oracle updates, which would allow borrowers to automatically &quot;top-up&quot; their open positions to avoid liquidation.

For example, Maker uses the &quot;medianizer&quot; smart contract which maintains a whitelist of price feed contracts which are allowed to post price updates. Every time a new price update is received, the median of all feed prices is re-computed and the medianized value is updated.  In this case, the medianizer smart contract could fire a hook event that would allow subscriber contracts to decide to re-collateralize their CDPs.

### Automated Market Makers

AMM liquidity pools could fire a hook event whenever liquidity is added or removed.  This could allow a subscriber smart contracts to add or remove liquidity once the total pool liquidity reaches a certain point.

AMMs can fire a hook whenever there is a trade within a trading pair, emitting the time-weighted-price-oracle update via an hook event.  Subscribers can use this to create an automated Limit-Order-Book type contract to buy/sell tokens once an asset&apos;s spot price breaches a pre-specified threshold.

### DAO Voting

Hook events can be emitted by a DAO governance contract to signal that a proposal has been published, voted on, carried or vetoed, and would allow any subscriber contract to automatically respond accordingly. For example, to execute some smart contract function whenever a specific proposal has passed, such as an approval for payment of funds.

### Scheduled Function Calls

A scheduler service can be created whereby a subscriber can register for a scheduled funtion call, this could be done using unix cron format and the service can fire events from a smart contract on separate threads.  Subscriber contracts can subscriber to the respective threads in order to subscribe to certain schedules (e.g. daily, weekly, hourly etc.), and could even register customer cron schedules.

### Recurring Payments

A service provider can fire Hook events that will allow subscriber contracts to automatically pay their service fees on a regular schedule.  Once the subscriber contracts receive a hook event, they can call a function on the service provider&apos;s contract to transfer funds due.

### Coordination via Delegation

Hook event payloads can contain any arbitrary data, this means you can use things like the Delegatable framework to sign off-chain delegations which can faciliate a chain of authorized entities to publish valid Hook events.  You can also use things like BLS threshold signatures, to facilitate multiple off-chain publishers to authorize the firing of a Hook.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### Registering a Publisher

Both the publisher and subscriber contracts **MUST** register in a specific register contract, similarly to how smart contracts register an interface in the [ERC-1820](/EIPs/EIPS/eip-1820) contract.  The registry contract **MUST** must use a deterministic deployment mechanism, i.e. using a factory contract and a specific salt.

To register a publisher contract&apos;s hook, the `registerHook` function **MUST** be called on the registry contract.  The parameters that need to be supplied are:

 - (address) The publisher contract address
 - (uint256) The thread id that the hooks events will reference (a single contract can fire hook events with any number of threads, subscribers can choose which threads to subscribe to)
 - (bytes) The public key associated with the hook events (optional)

When the `registerHook` function is called on the registry contract, the registry contract **MUST** make a downstream call to the publisher contract address, by calling the publisher contract&apos;s `verifyEventHookRegistration` function, with the same arguments as passed to the `registerHook` function on the registry contract.  The `verifyEventHookRegistration` function in the publisher contract **MUST** return true in order to indicate that the contract will allow itself to be added to the registry as a publisher.  The registry contract **MUST** emit a `HookRegistered` event to indicate that a new publisher contract has been added.

### Updating a Hook

Publishers may want to update the details associated with a Hook event, or indeed remove support for a Hook event completely.  The registry contract **MUST** implement the `updatePublisher` function to allow for an existing publisher contract to be updated in the registry.  The registry contract **MUST** emit a `PublisherUpdated` event to indicate that the publisher contract was updated.

### Removing a Hook

To remove a previously registered Hook, the function `removeHook` function must be called on the Registry contract, with the same parameters as the `updateHook` function. The registry contract **MUST** emit a `HookRemoved` event with the same parameters as passed to the &apos;removeHook&apos; function and the `msg.sender` value.

### Registering a Subscriber

To register a subscriber to a hook, the `registerSubscriber` function **MUST** be called on the registry contract with the following parameters:

 - (address) The publisher contract address
 - (bytes32) The subscriber contract address
 - (uint256) The thread id to subscribe to
 - (uint256) The fee that the subscriber is willing to pay to get updates
 - (uint256) The maximum gas that the subscriber will allow for updates, to prevent griefing attacks, or 0 to indicate no maximum
 - (uint256) The maximum gas price that the subscriber is willing to repay the relayer on top of the fee, or 0 to indicate no rebates
 - (uint256) The chain id that the subscriber wants updates from
 - (address) The address of the token that the fee will be paid in or 0x0 for the chain&apos;s native asset (e.g. ETH, MATIC etc.)

The subscriber contract **MAY** implement gas refunds on top of the fixed fee per update. Where a subscriber chooses to do this, then they **SHOULD** specify the `maximum gas` and `maximum gas price` parameters in order to protect themselves from griefing attacks. This is so that a malicious or careless relay doesn&apos;t set an exorbitantly high gas price and ends up draining the subscriber contracts. Subscriber contracts can otherwise choose to set a fee that is estimated to be sufficiently high to cover gas fees.

Note that while the chain id and the token address were not included in the original version of the spec, the simple addition of these two parameters allows for leveraging the relayers for cross chain messages, should the subscriber wish to do this, and also allows for paying relayer fees in various tokens.

### Updating a Subscription

To update a subscription, the `updateSubscriber` function **MUST** be called with the same set of parameters as the `registerSubscriber` function.  This might be done in order to cancel a subscription, or to change the subscription fee. Note that the `updateSubscriber` function **MUST** maintain the same `msg.sender` that the `registerSubscriber` function was called with.

### Removing a Subscription

To remove a previously registered subscription, the function `removeSubscriber` **MUST** be called on the Registry contract, with the same parameters as the `updateSubscriber` function, but without the `fee` parameter (i.e. publisher and subscriber contract addresses and thread id). The fee will be subsequently set to 0 to indicate that the subscriber no longer wants updates for this subscription.  The registry contract **MUST** emit a `SubscriptionRemoved` event with publisher contract address, subscriber contract address and the thread id as topics.

### Publishing an Event

A publisher contract **SHOULD** emit a hook event from at least one function. The emitted event **MUST** be called `Hook` and **MUST** contain the following parameters:

 - uint256 (indexed) - threadId
 - uint256 (indexed) - nonce
 - bytes32 digest
 - bytes payload
 - bytes32 checksum

The `nonce` value **MUST** be incremented every time a Hook event is fired by a publisher contract.  Every Hook event **MUST** have a unique `nonce` value.  The `nonce` property is initiated to 1, but the first Hook event ever fired **MUST** be set to 2.  This is to prevent ambiguity between an uninitiated nonce variable and a nonce variable that is explicitly initiated to zero.

The `digest` parameter of the event **MUST** be the keccak256 hash of the payload, and the `checksum` **MUST** be the keccak256 hash of the concatenation of the digest with the current blockheight, e.g.:

`bytes32 checksum = keccak256(abi.encodePacked(digest, block.number));`

The `Hook` event can be triggered by a function call from any EOA or external contract. This allows the payload to be created dynamically within the publisher contract.  The subscriber contract **SHOULD** call the `verifyEventHook` function on the publisher contract to verify that the received Hook payload is valid.

The payload **MAY** be passed to the function firing the Hook event instead of being generated within the publisher contract itself, but if a signature is provided it **MUST** sign a hash of the payload, and it is strongly recommended to use the [EIP-712](/EIPs/EIPS/eip-712) standard, and to follow the data structure outlined at the end of this proposal.  This signature **SHOULD** be verified by the subscribers to ensure they are getting authentic events. The signature **MUST** correspond to the public key that was registered with the event.  With this approach, the signature **SHOULD** be placed at the start of the payload (e.g. bytes 0 to 65 for an ECDSA signature with r, s, v properties).  This method of verification can be used for cross-chain Hook events, where subscribers will not be able to call the `verifyHookEvent` of the publisher contract on another chain.

The payload **MUST** be passed to subscribers as a byte array in calldata.  The subscriber smart contract **SHOULD** convert the byte array into the required data type.  For example, if the payload is a snark proof, the publisher would need to serialize the variables into a byte array, and the subscriber smart contract would need to deserialize it on the other end, e.g.:

```
struct SnarkProof {
    uint256[2] a;
    uint256[2][2] b;
    uint256[2] c;
    uint256[1] input;
}

SnarkProof memory zkproof = abi.decode(payload, SnarkProof);
```

### Relayers

Relayers are independent parties that listen to `Hook` events on publisher smart contracts.  Relayers retrieve a list of subscribers for different hooks from the registry, and listen for hook events being fired on the publisher contracts.  Once a hook event has been fired by a publisher smart contract, relayers can decide to relay the hook event&apos;s payload to the subscriber contracts by broadcasting a transaction that executes the subscriber contract&apos;s `verifyHook` function.  Relayers are incentivised to do this because it is expected that the subscriber contract will remunerate them with ETH, or some other asset.

Relayers **SHOULD** simulate the transaction locally before broadcasting it to make sure that the subscriber contract has sufficient balance for payment of the fee.  This requires subscriber contracts to maintain a balance of ETH (or some asset) in order to provision payment of relayer fees.  A subscriber contract **MAY** decide to revert a transaction based on some logic, which subsequently allows the subscriber contract to conditionally respond to events, depending on the data in the payload. In this case the relayer will simulate the transaction locally and determine not to relay the Hook event to the subscriber contract.

### Verifying a Hook Event

The `verifyHook` function of the subscriber contracts **SHOULD** include logic to ensure that they are retrieving authentic events. In the case where the Hook event contains a signature, then subscriber contracts **SHOULD** create a hash of the required parameters, and **SHOULD** verify that the signature in the hook event is valid against the derived hash and the publisher&apos;s public key (see the reference implemenetation for an example).  The hook function **SHOULD** also verify the nonce of the hook event and record it internally, in order to prevent replay attacks.

For Hook events without signatures, the subscriber contract **SHOULD** call the `verifyHookEvent` on the publisher contract in order to verify that the hook event is valid.  The publisher smart contract **MUST** implement the `verifyHookEvent`, which accepts the hash of the payload, the thread id, the nonce, and the block height associated with the Hook event, and returns a boolean value to indicate the Hook event&apos;s authenticity.

### Interfaces

IRegistry.sol

```js
/// @title IRegistry
/// @dev Implements the registry contract
interface IRegistry {
    /// @dev Registers a new hook event by a publisher
    /// @param publisherContract The address of the publisher contract
    /// @param threadId The id of the thread these hook events will be fired on
    /// @param signingKey The public key that corresponds to the signature of externally generated payloads (optional)
    /// @return Returns true if the hook is successfully registered
    function registerHook(
        address publisherContract,
        uint256 threadId,
        bytes calldata signingKey
    ) external returns (bool);

    /// @dev Verifies a hook with the publisher smart contract before adding it to the registry
    /// @param publisherAddress The address of the publisher contract
    /// @param threadId The id of the thread these hook events will be fired on
    /// @param signingKey The public key used to verify the hook signatures
    /// @return Returns true if the hook is successfully verified
    function verifyHook(
        address publisherAddress,
        uint256 threadId,
        bytes calldata signingKey
    ) external returns (bool);

    /// @dev Update a previously registered hook event
    /// @dev Can be used to transfer hook authorization to a new address
    /// @dev To remove a hook, transfer it to the burn address
    /// @param publisherContract The address of the publisher contract
    /// @param threadId The id of the thread these hook events will be fired on
    /// @param signingKey The public key used to verify the hook signatures
    /// @return Returns true if the hook is successfully updated
    function updateHook(
        address publisherContract,
        uint256 threadId,
        bytes calldata signingKey
    ) external returns (bool);

    /// @dev Remove a previously registered hook event
    /// @param publisherContract The address of the publisher contract
    /// @param threadId The id of the thread these hook events will be fired on
    /// @param signingKey The public key used to verify the hook signatures
    /// @return Returns true if the hook is successfully updated
    function removeHook(
        address publisherContract,
        uint256 threadId,
        bytes calldata signingKey
    ) external returns (bool);

    /// @dev Registers a subscriber to a hook event
    /// @param publisherContract The address of the publisher contract
    /// @param subscriberContract The address of the contract subscribing to the event hooks
    /// @param threadId The id of the thread these hook events will be fired on
    /// @param fee The fee that the subscriber contract will pay the relayer
    /// @param maxGas The maximum gas that the subscriber allow to spend, to prevent griefing attacks
    /// @param maxGasPrice The maximum gas price that the subscriber is willing to rebate
    /// @param chainId The chain id that the subscriber wants updates on
    /// @param feeToken The address of the token that the fee will be paid in or 0x0 for the chain&apos;s native asset (e.g. ETH)
    /// @return Returns true if the subscriber is successfully registered
    function registerSubscriber(
        address publisherContract,
        address subscriberContract,
        uint256 threadId,
        uint256 fee,
        uint256 maxGas,
        uint256 maxGasPrice,
        uint256 chainId,
        address feeToken
    ) external returns (bool);

    /// @dev Registers a subscriber to a hook event
    /// @param publisherContract The address of the publisher contract
    /// @param subscriberContract The address of the contract subscribing to the event hooks
    /// @param threadId The id of the thread these hook events will be fired on
    /// @param fee The fee that the subscriber contract will pay the relayer
    /// @return Returns true if the subscriber is successfully updated
    function updateSubscriber(
        address publisherContract,
        address subscriberContract,
        uint256 threadId,
        uint256 fee
    ) external returns (bool);

    /// @dev Removes a subscription to a hook event
    /// @param publisherContract The address of the publisher contract
    /// @param subscriberContract The address of the contract subscribing to the event hooks
    /// @param threadId The id of the thread these hook events will be fired on
    /// @return Returns true if the subscriber is subscription removed
    function removeSubscription(
        address publisherContract,
        address subscriberContract,
        uint256 threadId
    ) external returns (bool);
}
```

IPublisher.sol

```js
/// @title IPublisher
/// @dev Implements a publisher contract
interface IPublisher {
    /// @dev Example of a function that fires a hook event when it is called
    /// @param payload The actual payload of the hook event
    /// @param digest Hash of the hook event payload that was signed
    /// @param threadId The thread number to fire the hook event on
    function fireHook(
        bytes calldata payload,
        bytes32 digest,
        uint256 threadId
    ) external;

    /// @dev Adds / updates a new hook event internally
    /// @param threadId The thread id of the hook
    /// @param signingKey The public key associated with the private key that signs the hook events
    function addHook(uint256 threadId, bytes calldata signingKey) external;

    /// @dev Called by the registry contract when registering a hook, used to verify the hook is valid before adding
    /// @param threadId The thread id of the hook
    /// @param signingKey The public key associated with the private key that signs the hook events
    /// @return Returns true if the hook is valid and is ok to add to the registry
    function verifyEventHookRegistration(
        uint256 threadId,
        bytes calldata signingKey
    ) external view returns (bool);

    /// @dev Returns true if the specified hook is valid
    /// @param payloadhash The hash of the hook&apos;s data payload
    /// @param threadId The thread id of the hook
    /// @param nonce The nonce of the current thread
    /// @param blockheight The blockheight that the hook was fired at
    /// @return Returns true if the specified hook is valid
    function verifyEventHook(
        bytes32 payloadhash,
        uint256 threadId,
        uint256 nonce,
        uint256 blockheight
    ) external view returns (bool);
}
```

ISubscriber.sol

```js
/// @title ISubscriber
/// @dev Implements a subscriber contract
interface ISubscriber {
    /// @dev Example of a function that is called when a hook is fired by a publisher
    /// @param publisher The address of the publisher contract in order to verify hook event with
    /// @param payload Hash of the hook event payload that was signed
    /// @param threadId The id of the thread this hook was fired on
    /// @param nonce Unique nonce of this hook
    /// @param blockheight The block height at which the hook event was fired
    function verifyHook(
        address publisher,
        bytes calldata payload,
        uint256 threadId,
        uint256 nonce,
        uint256 blockheight
    ) external;
}

```

## Rationale

The rationale for this design is that it allows smart contract developers to write contract logic that listens and responds to events fired in other smart contracts, without requiring them to run some dedicated off-chain process to achieve this.  This best suits any simple smart contract logic that runs relatively infrequently in response to events in other contracts.

This improves on the existing solutions to achieve a pub/sub design pattern. To elaborate: a number of service providers currently offer &quot;webhooks&quot; as a way to subscribe to events emitted by smart contracts, by having some API endpoint called when the events are emitted, or alternatively offer some serverless feature that can be triggered by some smart contract event.  This approach works very well, but it does require that some API endpoint or serverless function be always available, which may require some dedicated server / process, which in turn will need to have some private key, and some amount of ETH in order to re-broadcast transactions, no to mention the requirement to maintain an account with some third party provider.

This approach offers a more suitable alternative for when an &quot;always-on&quot; server instance is not desirable, e.g. in the case that it will be called infrequently.

This proposal incorporates a decentralized market-driven relay network, and this decision is based on the fact that this is a highly scalable approach.  Conversely, it is possible to implement this functionality without resorting to a market-driven approach, by simply defining a standard for contracts to allow other contracts to subscribe directly.  That approach is conceptually simpler, but has its drawbacks, in so far as it requires a publisher contract to record subscribers in its own state, creating an overhead for data management, upgradeability etc.  That approach would also require the publisher to call the `verifyHook` function on each subscriber contract, which will incur potentially significant gas costs for the publisher contract.

## Security Considerations

### Griefing Attacks

It is imperative that subscriber contracts trust the publisher contracts not to fire events that hold no intrinsic interest or value for them, as it is possible that malicious publisher contracts can publish a large number of events that will in turn drain the ETH from the subscriber contracts.

### Front-running Attacks

It is advised not to rely on signatures alone to validate Hook events. It is important for publishers and subscribers of hooks to be aware that it is possible for a relayer to relay hook events before they are published, by examining the publisher&apos;s transaction in the mempool before it actually executes in the publisher&apos;s smart contract.  The normal flow is for a &quot;trigger&quot; transaction to call a function in the publisher smart contract, which in turn fires an event which is then picked up by relayers.  Competitive relayers will observe that it is possible to pluck the signature and payload from the trigger transaction in the public mempool and simply relay it to subscriber contracts before the trigger transaction has been actually included in a block.  In fact, it is possible that the subscriber contracts process the event before the trigger transaction is processed, based purely on gas fee dynamics.  This can mitigated against by subscriber contracts calling the `verifyEventHook` function on the publisher contract when they receive a Hook event.

Another risk from front-running affects relayers, whereby the relayer&apos;s transactions to the subscriber contracts can be front-run by generalized MEV searchers in the mempool.  It is likely that this sort of MEV capture will occur in the public mempool, and therefore it is advised that relayers use private channels to block builders to mitigate against this issue.

### Relayer Competition

By broadcasting transactions to a segregated mempool, relayers protect themselves from front-running by generalized MEV bots, but their transactions can still fail due to competition from other relayers.  If two or more relayers decide to start relaying hook events from the same publisher to the same subscribers, then the relay transactions with the highest gas price will be executed before the others.  This will result in the other relayer&apos;s transactions potentially failing on-chain, by being included later in the same block.  For now, there are certain transaction optimization services that will prevent transactions from failing on-chain, which will offer a solution to this problem, though this is out-of-scope for this document.

### Optimal Fees

The fees that are paid to relayers are at the discretion of the subscribers, but it can be non-trivial to set fees to their optimal level, especially when considering volatile gas fees and competition between relayers.  This will result in subscribers setting fees to a perceived &quot;safe&quot; level, which they are confident will incentivize relayers to relay Hook events.  This will inevitably lead to poor price discovery and subscribers over-paying for updates.

The best way to solve this problem is through an auction mechanism that would allow relayers to bid against each other for the right to relay a transaction, which would guarantee that subscribers are paying the optimal price for their updates.  Describing an auction mechanism that would satisfy this requirements is out of scope for this proposal, but there exists proposals for general purpose auction mechanisms that can faciliate this without introducing undue latency.  One exampe of such as proposal is SUAVE from Flashbots, and there will likely be several others in time.

### Without an Auction

In order to cultivate and maintain a reliable relayer market without the use of an auction mechanism, subscriber contracts would need to implement logic to either rebate any gas fees up to a specified limit, (while still allowing for execution of hook updates under normal conditions).

Another approach would be to implement a logical condition that checks the gas price of the transaction that is calling the `verifyHook` function, to ensure that the gas price does not effectively reduce the fee to zero.  This would require that the subscriber smart contract has some knowledge of the approximate gas used by it&apos;s `verifyHook` function, and to check that the condition `minFee &gt;= fee - (gasPrice * gasUsed)` is true.  This will mitigate against competitive bidding that would drive the _effective_ relayer fee to zero, by ensuring that there is some minimum fee below which the effective fee is not allowed to drop.  This would mean that the highest gas price that can be paid before the transaction reverts is `fee - minFee + ε` where `ε ~= 1 gwei`.  This will require careful estimation of the gas cost of the `verifyHook` function and an awareness that the gas used may change over time as the contract&apos;s state changes. The key insight with this approach is that competition between relayers will result in the fee that the subscribers pay always being the maximum, which is why the use of an auction mechanism is preferable.

### Relayer Transaction Batching

Another important consideration is with batching of Hook events. Relayers are logically incentivized to batch Hook updates to save on gas, seeing as gas savings amount to 21,000 * n where n is the number of hooks being processed in a block by a single relayer.  If a relayer decides to batch multiple Hook event updates to various subscriber contracts into a single transaction, via a multi-call proxy contract, then they increase the risk of the entire batch failing on-chain if even one of the transactions in the batch fails on-chain.  For example, if relayer A batches x number of Hook updates, and relayer B batches y number of Hook updates, it is possible that relayer A&apos;s batch is included in the same block in front of relayer B&apos;s batch, and if both batches contain at least one duplicate, (i.e. the same Hook event to the same subscriber), then this will cause relayer B&apos;s batch transaction to revert on-chain.  This is an important consideration for relayers, and suggests that relayers should have access to some sort of bundle simulation service to identify conflicting transactions before they occur.

### Replay Attacks

When using signature verification, it is advised to use the [EIP-712](/EIPs/EIPS/eip-712) standard in order to prevent cross network replay attacks, where the same contract deployed on more than one network can have its hook events pushed to subscribers on other networks, e.g. a publisher contract on Polygon can fire a hook event that could be relayed to a subscriber contract on Gnosis Chain.  Whereas the keys used to sign the hook events should ideally be unique, in reality this may not always be the case.

For this reason, it is recommended to use [ERC-721](/EIPs/EIPS/eip-712) Typed Data Signatures.  In this case the process that initiates the hook should create the signature according to the following data structure:

```js
const domain = [
  { name: &quot;name&quot;, type: &quot;string&quot;  },
  { name: &quot;version&quot;, type: &quot;string&quot; },
  { name: &quot;chainId&quot;, type: &quot;uint256&quot; },
  { name: &quot;verifyingContract&quot;, type: &quot;address&quot; },
  { name: &quot;salt&quot;, type: &quot;bytes32&quot; }
]
 
const hook = [
  { name: &quot;payload&quot;, type: &quot;string&quot; },
  { type: &quot;uint256&quot;, name: &quot;nonce&quot; },
  { type: &quot;uint256&quot;, name: &quot;blockheight&quot; },
  { type: &quot;uint256&quot;, name: &quot;threadId&quot; },
]
 
const domainData = {
  name: &quot;Name of Publisher Dapp&quot;,
  version: &quot;1&quot;,
  chainId: parseInt(web3.version.network, 10),
  verifyingContract: &quot;0x123456789abcedf....publisher contract address&quot;,
  salt: &quot;0x123456789abcedf....random hash unique to publisher contract&quot;
}
 
const message = {
  payload: &quot;bytes array serialized payload&quot;
  nonce: 1,
  blockheight: 999999,
  threadId: 1,
}
 
const eip712TypedData = {
  types: {
    EIP712Domain: domain,
    Hook: hook
  },
  domain: domainData,
  primaryType: &quot;Hook&quot;,
  message: message
}
```

Note: please refer to the unit tests in the reference implmenetation for an example of how a hook event should be constructed properly by the publisher.

Replay attacks can also occur on the same network that the event hook was fired, by simply re-broadcasting an event hook that was already broadcast previously.  For this reason, subscriber contracts should check that a nonce is included in the event hook being received, and record the nonce in the contract&apos;s state.  If the hook nonce is not valid, or has already been recorded, the transaction should revert.

### Cross-chain Messaging

There is also the possibility to leverage the `chainId` for more than preventing replay attacks, but also for accepting messages from other chains.  In this use-case the subscriber contracts should register on the same chain that the subscriber contract is deployed on, and should set the `chainId` to the chain it wants to receive hook events from.

## Copyright

Copyright and related rights waived via CC0.
</description>
        <pubDate>Wed, 09 Nov 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5902</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5902</guid>
      </item>
    
      <item>
        <title>PAY opcode</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5920-pay-opcode/11717</comments>
        
        <description>## Abstract

This EIP introduces a new opcode, `PAY`, taking two stack parameters, `addr` and `val`, that transfers `val` wei to the address `addr` without calling any of its functions.

## Motivation

Currently, to send ether to an address requires you to call into that address, which transfers execution context to that address, which creates several issues:

- First of all, it opens a reentrancy attack vector, as the recipient can call back into the sender. More generally, the recipient can unilaterally execute arbitrary state changes, limited only by the gas forwarded, which is not desirable from the point of view of the sender.
  - In practice, when calling into another account and sending ether, 2300 gas (the &quot;gas stipend&quot;) is always available &quot;for free&quot; in the newly created call frame. Although it is currently not possible to make storage state changes with the 2300 gas stipend (see the last minute rejection of [EIP-1283](/EIPs/EIPS/eip-1283) from Constantinople to be replaced with the &quot;gas stipend safe&quot; [EIP-2200](/EIPs/EIPS/eip-2200) version in Istanbul), it is possible to do this with transient storage ([EIP-1153](/EIPs/EIPS/eip-1153)). This is a security risk where potentially the transient storage gets changed unintentionally. The goal is to send ether, and not have to consider these potential unintuitive security problems.
- Secondly, it opens a DoS vector. Contracts wanting to send ether must be cognizant of the possibility that the recipient will run out of gas or revert.
- Future potential call-like opcodes may not provide a way to restrict the amount of gas being forwarded to the recipient, so the meager mitigation against unintended side effects in use today (gas limit) is not guaranteed to be available.
- The `CALL` and `EXTCALL` opcodes will execute code on the recipient, which is unintended when wanting to send ether and which could lead to unintentional operations. The code execution also has to be paid for in gas, even when the intention is to only send ether, which is thus an unnecessary waste of gas.
- Finally, [EIP-7702](/EIPs/EIPS/eip-7702) allows to delegate externally owned accounts (EOAs) to other accounts, which breaks the invariant that EOAs cannot contain code. Therefore, calling such EOA with the intention to send ether will thus also execute code and cost unnecessary gas.

Having a dedicated opcode for ether transfers solves all of these issues, and would be a useful addition to the EVM.

## Specification

### Constants

| Constant                   | Definition                |
| -------------------------- | ------------------------- |
| `WARM_STORAGE_READ_COST`   | [EIP-2929](/EIPs/EIPS/eip-2929) |
| `COLD_ACCOUNT_ACCESS_COST` | [EIP-2929](/EIPs/EIPS/eip-2929) |
| `GAS_NEW_ACCOUNT`          | [EELS][gna]               |
| `GAS_CALL_VALUE`           | [EELS][gcv]               |

[gna]: https://github.com/ethereum/execution-specs/blob/4d953035fb0cceda7cf21d71b2ab7a9a6f4632f0/src/ethereum/frontier/vm/gas.py#L52
[gcv]: https://github.com/ethereum/execution-specs/blob/4d953035fb0cceda7cf21d71b2ab7a9a6f4632f0/src/ethereum/frontier/vm/gas.py#L53

### Behavior

A new opcode is introduced: `PAY` (`0xfc`), which:

- Halt with exceptional failure if the current frame is static, as defined in [EIP-214](/EIPs/EIPS/eip-214).
- Pops two values from the stack: `addr` then `val`.
- Exceptionally halts if `addr` has any of the high 12 bytes set to a non-zero value (i.e. it does not contain a 20-byte address).
- Charges the gas cost detailed below.
- Marks `addr` as warm (adding `addr` to `accessed_addresses`).
- Transfers `val` wei from the current address to the address `addr`, only if the current address has a balance greater than or equal to `val`.
- Push `1` on the stack if the `PAY` operation was successful, or `0` if it failed.
  - Currently only insufficient balance would produce a `0` return value.

### Gas Cost

The gas cost for `PAY` is the sum of the following:

- Is `addr` in `accessed_addresses`?
    - If yes, `WARM_STORAGE_READ_COST`;
    - Otherwise, `COLD_ACCOUNT_ACCESS_COST`.
- Does `addr` exist or is `val` zero?
    - If yes to either, zero;
    - Otherwise, `GAS_NEW_ACCOUNT`.
- Is `val` zero?
    - If yes, zero;
    - Otherwise, `GAS_CALL_VALUE`.

`PAY` cannot be implemented on networks with empty accounts (see [EIP-7523](/EIPs/EIPS/eip-7523)).

## Rationale

### Argument order

The order of arguments mimics that of `CALL`, which pops `addr` before `val`. Beyond consistency, though, this ordering aids validators pattern-matching MEV opportunities, so `PAY` always appears immediately after `COINBASE`.

### Halting for invalid address

The halting behavior is designed to allow for Address Space Extension.
If the high bytes were truncated, as in `CALL`, contracts could depend on the truncating behavior.
If the address space were extended beyond 20 bytes, `PAY` would either not be able to target those accounts, or code expecting truncation could send ether to the wrong address.

Because this behavior may be changed, contracts should not rely on this halting behavior and use methods designated to intentionally halt (such as the [`INVALID`](/EIPs/EIPS/eip-141) opcode).

## Backwards Compatibility

This change requires a hard fork.

## Security Considerations

Existing contracts should not rely on their balance being under their control, since it is already possible to send ether to an address without calling it, by using the `SELFDESTRUCT` opcode (somewhat restricted in [EIP-6780](/EIPs/EIPS/eip-6780)).
It is also possible to involuntarily fund an account with priority fees sent to a `block.coinbase`.
However, this opcode does make this process cheaper and easier. It thus does not break an invariant.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 14 Mar 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5920</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5920</guid>
      </item>
    
      <item>
        <title>Role-based Access Control</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5982-role-based-access-control/11759</comments>
        
        <description>## Abstract

This EIP defines an interface for role-based access control for smart contracts. Roles are defined as `byte32`. The interface specifies how to read, grant, create, and destroy roles. It specifies the meaning of role power in terms of the ability to call a given method
identified by a `bytes4` method selector. It also specifies how metadata of roles are represented.

## Motivation

There are many ways to establish access control for privileged actions. One common pattern is &quot;role-based&quot; access control, where one or more users are assigned to one or more &quot;roles,&quot; which grant access to privileged actions. This pattern is more secure and flexible than ownership-based access control since it allows for many people to be granted permissions according to the principle of least privilege.

## Specification

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

The reference interfaces are described as follows:

```solidity
interface IERC_ACL_CORE {
    function hasRole(bytes32 role, address account) external view returns (bool);
    function grantRole(bytes32 role, address account) external;
    function revokeRole(bytes32 role, address account) external;
}
```

```solidity
interface IERC_ACL_GENERAL {
    event RoleGranted(address indexed grantor, bytes32 indexed role, address indexed grantee, bytes _data);
    event RoleRevoked(address indexed revoker, bytes32 indexed role, address indexed revokee, bytes _data);

    event RoleCreated(address indexed roleGrantor, bytes32 role, bytes32 adminOfRole, string name, string desc, string uri, bytes32 calldata _data);
    event RoleDestroyed(address indexed roleDestroyer, bytes32 role, bytes32 calldata _data);
    event RolePowerSet(address indexed rolePowerSetter, bytes32 role, bytes4 methods, bytes calldata _data);

    function grantRole(bytes32 role, address account, bytes calldata _data) external;
    function revokeRole(bytes32 role, address account, bytes calldata _data) external;

    function createRole(bytes32 role, bytes32 adminOfRole, string name, string desc, string uri, bytes32 calldata _data) external;
    function destroyRole(bytes32 role, bytes32 calldata _data) external;
    function setRolePower(bytes32 role, bytes4 methods, bytes calldata _data) view external returns(bool);

    function hasRole(bytes32 role, address account, bytes calldata _data) external view returns (bool);
    function canGrantRole(bytes32 grantor, bytes32 grantee, bytes calldata _data) view external returns(bool);
    function canRevokeRole(bytes32 revoker, bytes32 revokee, address account, bytes calldata _data) view external returns(bool);
    function canExecute(bytes32 executor, bytes4 methods, bytes32 calldata payload, bytes calldata _data) view external returns(bool);
}
```

```solidity
interface IERC_ACL_METADATA {
    function roleName(bytes32) external view returns(string);
    function roleDescription(bytes32) external view returns(string);
    function roleURI(bytes32) external view returns(string);
}
```

1. Compliant contracts MUST implement `IERC_ACL_CORE`
2. It is RECOMMENDED for compliant contracts to implement the optional extension `IERC_ACL_GENERAL`.
3. Compliant contracts MAY implement the optional extension `IERC_ACL_METADATA`.
4. A role in a compliant smart contract is represented in the format of `bytes32`. It is RECOMMENDED that the value of such a role be computed as a
`keccak256` hash of the role name, in this format: `bytes32 role = keccak256(&quot;&lt;role_name&gt;&quot;)`, such as `bytes32 role = keccak256(&quot;MINTER&quot;)`.
5. Compliant contracts SHOULD implement [ERC-165](/EIPs/EIPS/eip-165) identifier.

## Rationale

1. The names and parameters of methods in `IERC_ACL_CORE` are chosen to allow backward compatibility with OpenZeppelin&apos;s implementation.
2. The methods in `IERC_ACL_GENERAL` conform to [ERC-5750](/EIPs/EIPS/eip-5750) to allow extension.
3. The `renounceRole` method was not adopted, and was consolidated into `revokeRole` to simplify the interface.


## Backwards Compatibility

Needs discussion.

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 15 Nov 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5982</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5982</guid>
      </item>
    
      <item>
        <title>Add Poseidon hash function precompile</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-5988-add-poseidon-hash-function-precompile/11772</comments>
        
        <description>## Abstract

This EIP introduces a new precompiled contract which implements the hash function used in the Poseidon cryptographic hashing algorithm, for the purpose of allowing interoperability between the EVM and ZK / Validity rollups, as well as introducing more flexible cryptographic hash primitives to the EVM.

## Motivation

[Poseidon](/EIPs/assets/eip-5988/papers/poseidon_paper.pdf) is an arithmetic hash function that is designed to be efficient for Zero-Knowledge Proof Systems.
Ethereum adopts a rollup centric roadmap and hence must adopt facilities for L2s to be able to communicate with the EVM in an optimal manner.

ZK-Rollups have particular needs for cryptographic hash functions that can allow for efficient verification of proofs.

The Poseidon hash function is a set of permutations over a prime field, which makes it particularly well-suited for the purpose of building efficient ZK / Validity rollups on Ethereum.

Poseidon is one of the most efficient hashing algorithms that can be used in this context.
Moreover it is compatible with all major proof systems (SNARKs, STARKs, Bulletproofs, etc...).
This makes it a good candidate for a precompile that can be used by many different ZK-Rollups.

An important point to note is that ZK rollups using Poseidon have chosen different sets of parameters, which makes it harder to build a single precompile for all of them.

However, we can still build a generic precompile that supports arbitrary parameters, and allow the ZK rollups to choose the parameters they want to use.

This is the approach that we have taken in this EIP.

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### Parameters

| Constant                      | Value |
| ----------------------------- | ----- |
| `FORK_BLKNUM`                 | `TBD` |
| `GAS_COST`                    | `TBD` |
| `POSEIDON_PRECOMPILE_ADDRESS` | `0xA` |

Here are the Poseidon parameters that the precompile will support:

| Parameter name   | Description                                                        | Encoding size (in bytes) | Comments |
| ---------------- | ------------------------------------------------------------------ | ------------------------ | -------- |
| `p`              | Prime field modulus                                                | 32                       |          |
| `security_level` | Security level measured in bits. Denoted `M` in the Poseidon paper | 2                        |          |
| `alpha`          | Power of S-box                                                     | 1                        |          |
| `input_rate`     | Size of input                                                      | 2                        |          |
| `t`              | Size of the state                                                  | 1                        |          |
| `full_round`     | Number of full rounds. Denoted as `R_F` in the Poseidon paper.     | 1                        |          |
| `partial_round`  | Number of partial rounds. Denoted as `R_P` in the Poseidon paper.  | 1                        |          |
| `input`          | Input to the hash function                                         | `input_rate` * 32        |          |

The encoding of the precompile input is the following:

```text
[32 bytes for p][2 bytes for security_level][1 byte for alpha][2 bytes for input_rate][1 byte for t][1 byte for full_round][1 byte for partial_round][input_rate * 32 bytes for input]
```

The precompile should compute the hash function as [specified in the Poseidon paper](/EIPs/assets/eip-5988/papers/poseidon_paper.pdf) and return hash output.

&lt;!--### Example Usage in Solidity

The precompile can be wrapped easily in Solidity to provide a more development-friendly interface to `poseidon_hash` function.

```solidity
// TODO: Add solidity example
```--&gt;

&lt;!--### Gas Costs

```text
TODO: Fill gas costs section
```--&gt;

## Rationale

TODO: Add rationale

TODO: Add rationale for gas cost e.g. benchmark and computation cost estimation.

## Backwards Compatibility

There is very little risk of breaking backwards-compatibility with this EIP, the sole issue being if someone were to build a contract relying on the address at `0xPOSEIDON_PRECOMPILE_ADDRESS` being empty. The likelihood of this is low, and should specific instances arise, the address could be chosen to be any arbitrary value with negligible risk of collision.

## Test Cases

The Poseidon reference implementation contains test vectors that can be used to test the precompile.
Those tests are available [here](/EIPs/assets/eip-5988/test/poseidon/test_vectors.txt).

&lt;!--## Reference Implementation

TODO: Add initial Geth implementation--&gt;

## Security Considerations

Quoting Vitalik Buterin from `Arithmetic hash based alternatives to KZG for proto-danksharding` thread on EthResearch:

&gt; The Poseidon hash function was officially introduced in 2019. Since then it has seen considerable attempts at cryptanalysis and optimization. However, it is still very young compared to popular “traditional” hash functions (eg. SHA256 and Keccak), and its general approach of accepting a high level of algebraic structure to minimize constraint count is relatively untested.
&gt; There are layer-2 systems live on the Ethereum network and other systems that already rely on these hashes for their security, and so far they have seen no bugs for this reason. Use of Poseidon in production is still somewhat “brave” compared to decades-old tried-and-tested hash functions, but this risk should be weighed against the risks of proposed alternatives (eg. pairings with trusted setups) and the risks associated with centralization that might come as a result of dependence on powerful provers that can prove SHA256.

It is true that arithmetic hash functions are relatively untested compared to traditional hash functions.
However, Poseidon has been thoroughly tested and is considered secure by multiple independent research groups and layers 2 systems are already using it in production (StarkWare, Polygon, Loopring) and also by other projects (e.g. Filecoin).

Moreover, the impact of a potential vulnerability in the Poseidon hash function would be limited to the rollups that use it.

We can see the same rationale for the KZG ceremony in the [EIP-4844](/EIPs/EIPS/eip-4844), arguing that the risk of a vulnerability in the KZG ceremony is limited to the rollups that use it.

List of projects (non exhaustive) using Poseidon:

- StarkWare plans to use Poseidon as the main hash function for StarkNet, and to add a Poseidon built-in in Cairo.
- Filecoin employs POSEIDON for Merkle tree proofs with different arities and for two-value commitments.
- Dusk Network uses POSEIDON to build a Zcash-like protocol for securities trading.11 It also uses POSEIDON
  for encryption as described above.
- Sovrin uses POSEIDON for Merkle-tree based revocation.
- Loopring uses POSEIDON for private trading on Ethereum.
- Polygon uses Poseidon for Hermez ZK-EVM.

In terms of security, the choice of parameters is important.

### Security of the Poseidon parameters

#### Choice of the MDS matrix

The MDS matrix is a square matrix of size `t` \* `t` that is used to mix the state.

This matrix is used during the `MixLayer` phase of the Poseidon hash function.

The matrix must be chosen s.t. no subspace trail with inactive/active S-boxes can be set up for more than `t -1` rounds.

There are some efficient algorithms to detect weak MDS matrices.

Those algorithms are described in the [Proving Resistance Against Infinitely Long Subspace Trails: How to Choose the Linear Layer](/EIPs/assets/eip-5988/papers/proving_resistance_linear_layer.pdf) paper.

The process of the generation of the matrix should look like this, as recommended in the Poseidon paper:

1. Generate a random matrix.
2. Check if the matrix is secure using Algorithm 1, Algorithm 2, and Algorithm 3 provided [Proving Resistance Against Infinitely Long Subspace Trails: How to Choose the Linear Layer](/EIPs/assets/eip-5988/papers/proving_resistance_linear_layer.pdf) paper.
3. If the matrix is not secure, go back to step 1.

### Papers and research related to Poseidon security

- [Poseidon: A New Hash Function for Zero-Knowledge Proof Systems](/EIPs/assets/eip-5988/papers/poseidon_paper.pdf)
- [Security of the Poseidon Hash Function Against Non-Binary Differential and Linear Attacks](/EIPs/assets/eip-5988/papers/security_poseidon_non_binary_differential_attacks.pdf)
- [Report on the Security of STARK-friendly Hash Functions](/EIPs/assets/eip-5988/papers/report_security_stark_friendly_hash.pdf)
- [Practical Algebraic Attacks against some Arithmetization-oriented Hash Functions](/EIPs/assets/eip-5988/papers/practical_algebraic_attacks.pdf)

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 15 Nov 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-5988</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-5988</guid>
      </item>
    
      <item>
        <title>Replace SELFDESTRUCT with DEACTIVATE</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/almost-self-destructing-selfdestruct-deactivate/11886</comments>
        
        <description>## Abstract

Change `SELFDESTRUCT` to not delete all storage keys, and to use a special value in the account nonce to signal *deactivated* accounts. Because the semantics of revival change (storage keys may exists), we also rename the instruction to `DEACTIVATE`.

## Motivation

The `SELFDESTRUCT` instruction currently has a fixed price, but is unbounded in terms of how many storage/account changes it performs (it needs to delete all keys). This has been an outstanding concern for some time.

Furthermore, with *Verkle trees*, accounts will be organised differently: account properties, including storage, will have individual keys. It will not be possible to traverse and find all used keys. This makes `SELFDESTRUCT` very challenging to support in Verkle trees.

## Specification

1. Change the rules introduced by [EIP-2681](/EIPs/EIPS/eip-2681) such that regular nonce increase is bound by `2^64-2` instead of `2^64-1`. This applies from genesis.

2. The behaviour of `SELFDESTRUCT` is changed such that:

  - Does not delete any storage keys and also leave the account in place.
  - Transfer the account balance to the target **and** set account balance to `0.`
  - Set the account nonce to `2^64-1`.
  - Note that no refund is given since [EIP-3529](/EIPs/EIPS/eip-3529).
  - Note that the rules of [EIP-2929](/EIPs/EIPS/eip-2929) regarding `SELFDESTRUCT` remain unchanged.

2. Modify account execution (triggered both via external transactions or CALL* instructions), such that execution succeeds and returns an empty buffer if the nonce equals `2^64-1`.

  - Note that the account can still receive non-executable value transfers (such as coinbase transactions or other `SELFDESTRUCT`s).

3. Modify `CREATE2` such that it allows account creation if the nonce equals `2^64-1`.

  - Note that the account (especially code and storage) might not be empty prior to `CREATE2`.
  - Note that a successful `CREATE2` will change the account code, nonce and potentially balance.

4. Rename the `SELFDESTRUCT` instruction to `DEACTIVATE`, because the semantics of &quot;account revival&quot; are changed: the old storage items will remain, and newly deployed code must be aware of this.

## Rationale

There have been various proposals of removing `SELFDESTRUCT` and many would just outright remove the deletion capability. This breaks certain usage patterns, which the *deactivation* option leaves intact, albeit with minor changes. This only affects *newly* deployed code, and not existing one.

All the proposals would leave data in the state, but this proposal provides the flexibility to reuse or remove storage slots one-by-one should the revived contract choose to do so.

## Backwards Compatibility

This EIP requires a protocol upgrade, since it modifies consensus rules. The further restriction of nonce should not have an effect on accounts, as `2^64-2` is an unfeasibly high limit.

Contracts using the revival pattern will still work, but the code deployed during revival may need to be made aware that storage keys can already exist in the account.

## Security Considerations

The new behaviour of preserving storage has a potential effect on security. Contract authors must be aware and design contracts accordingly. There may be an effect on existing deployed code performing autonomous destruction and revival.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 25 Nov 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6046</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6046</guid>
      </item>
    
      <item>
        <title>ERC-721 Balance indexing via Transfer event</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-xxx-require-erc721-to-always-emit-transfer/11894</comments>
        
        <description>## Abstract

This EIP extends [ERC-721](/EIPs/EIPS/eip-721) to allow the tracking and indexing of NFTs by mandating that a pre-existing event be emitted during contract creation.

ERC-721 requires a `Transfer` event to be emitted whenever a transfer or mint (i.e. transfer from `0x0`) or burn (i.e. transfer to `0x0`) occurs, **except during contract creation**. This EIP mandates that compliant contracts emit a `Transfer` event **regardless of whether it occurs during or after contract creation.**

## Motivation

[ERC-721](/EIPs/EIPS/eip-721) requires a `Transfer` event to be emitted whenever a transfer or mint (i.e. transfer from `0x0`) or burn (i.e. transfer to `0x0`) occurs, EXCEPT for during contract creation. Due to this exception, contracts can mint NFTs during contract creation without the event being emitted. Unlike ERC-721, the [ERC-1155](/EIPs/EIPS/eip-1155) standard mandates events to be emitted regardless of whether such minting occurs during or outside of contract creation. This allows an indexing service or any off-chain service to reliably capture and account for token creation.

This EIP removes this exception granted by ERC-721 and mandates emitting the `Transfer` event for ERC-721 during contract creation. In this manner, indexers and off-chain applications can track token minting, burning, and transferring while relying only on ERC-721&apos;s `Transfer` event log.

## Specification

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

1. Compliant contracts MUST implement [ERC-721](/EIPs/EIPS/eip-721)
2. Compliant contracts MUST emit a `Transfer` event whenever a token is transferred, minted (i.e. transferred from `0x0`), or burned (i.e. transferred to `0x0`), **including during contract creation.**

## Rationale

Using the existing `Transfer` event instead of creating a new event (e.g. `Creation`) allows this EIP to be backward compatible with existing indexers.

## Backwards Compatibility

All contracts compliant with this EIP are compliant with ERC-721. However, not all contracts compliant with ERC-721 are compliant with this EIP.

## Security Considerations

No new security concerns.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 26 Nov 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6047</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6047</guid>
      </item>
    
      <item>
        <title>Deprecate SELFDESTRUCT</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/deprecate-selfdestruct/11907</comments>
        
        <description>## Abstract

This EIP deprecates the `SELFDESTRUCT` opcode and warns against its use. A breaking change to this functionality is likely to come in the future.

## Motivation

Discussions about how to change `SELFDESTRUCT` are ongoing. But there is a strong consensus that *something* will change.

## Specification

Documentation of the `SELFDESTRUCT` opcode is updated to warn against its use and to note that a breaking change may be forthcoming.

## Rationale

As time goes on, the cost of doing something increases, because any change to `SELFDESTRUCT` will be a breaking change.

The Ethereum Blog and other official sources have not provided any warning to developers about a potential forthcoming change.

## Backwards Compatibility

This EIP updates non-normative text in the Yellow Paper. No changes to clients is applicable.

## Security Considerations

None.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 27 Nov 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6049</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6049</guid>
      </item>
    
      <item>
        <title>Private Key Encapsulation</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/private-key-encapsulation-to-move-around-securely-without-entering-seed/11604</comments>
        
        <description>## Abstract

This EIP proposes a mechanism to encapsulate a private key so that it could be securely relocated to another application without providing the seed. This EIP combines `ECIES` (Elliptic Curve Integrated Encryption Scheme) and optional signature verification under various choices to ensure that the private key is encapsulated for a known or trusted party.

## Motivation

There are various cases in which we might want to export one of many private keys from a much more secure but less convenient wallet, which is controlled with a seed or passphrase.

1. We might dedicate one of many private keys for messaging purposes, and that private key is probably managed in a not-so-secure manner;
2. We might want to export one of many private keys from a hardware wallet, and split it with MPC technology so that a 3rd party service could help us identify potential frauds or known bad addresses, enforce 2FA, etc., meanwhile we can initiate transactions from a mobile device with much better UX and without carrying a hardware wallet.

In both cases, it is safer not to provide the seed which controls the whole wallet and might contains many addresses in multiple chains.

This EIP aims to enable such use cases.

## Specification

### Sender and Recipient

We hereby define:

- *Sender* as the party who holds in custody the private key to be encapsulated; *Sender Application* as the client-side application that said *Sender* uses to send the encapsulated private key.

- *Recipient* as the party who accepts the encapsulated private key, unwraps, and then uses it; *Recipient Application* as the client-side application that *Recipient* uses to receive the encapsulated private key.

### Core Algorithms

The basic idea is to encapsulate the private key with ECIES. To ensure that the ephemeral public key to encapsulate the private key is indeed generated from a trusted party and has not been tampered with, we also provided an option to sign that ephemeral public key in this standard.

There should be a mandatory  `version`  parameter. This allows various kinds of Key Encapsulation Mechanisms to be adopted depending on security considerations or preferences. The list shall be short to minimize compatibility issues among different vendors.

In addition to a `version` parameter, the following keys and functions are involved:

1. The Sender&apos;s private key  `sk`, which is to be encapsulated to the Recipient, and the corresponding address `account`.
2. The ephemeral Recipient key pair  `(r, R)`  such that `R = [r]G`. `G` denotes the base point of the elliptic curve, and `[r]G` denotes scalar multiplication. Optionally, `R` could be signed, and `signerPubKey` and `signature` are then provided for Sender to verify if `R`  could be trusted or not.
3. The ephemeral Sender key pair  `(s, S)`  such that `S = [s]G`.
4. The share secret  `ss := [s]R = [r]S` according to ECDH. Note that for secp256k1 this EIP follows RFC5903 and uses compact representation, which means to use *only* the `x` coordinate as the shared secret. For Curve25519 this EIP follows RFC7748.
5. The out-of-band data `oob`, optional. This could be digits or an alpha-numeric string entered by the user.
6. Let  `derivedKey  :=  HKDF(hash=SHA256, ikm=ss, info=oob,  salt,  length)`. HKDF is defined in RFC5869. The  `length`  should be determined by  `skey`  and  `IV`  requirements such that the symmetric key  `skey  = derivedKey[0:keySize]`, and  `IV  = derivedKey[keySize:length]`.  `keySize`  denotes the key size of the underlying symmetric algorithm, for example, 16 (bytes) for AES-128, and 32 (bytes) for Chacha20. See **Security Considerations** for the use of  `salt`.
7. Let `cipher  := authenticated_encryption(symAlg,  skey,  IV, data=sk)`. The symmetric cipher algorithm `symAlg` and authentication scheme are decided by the version parameter. No additional authentication data `aad` is used.

A much-simplified example flow without signature and verification is:

1. *Recipient Application* generates  `(r, R)`.
2. User inputs  `R`  to *Sender Application*, along with a six-digit code “123456” as  `oob`.
3. *Sender Application* generates  `(s, S)`, and computes  `cipher`, then returns `S || cipher`.
4. *Recipient Application* scans to read  `S`  and  `cipher`. The user enters “123456” as  `oob`  to *Recipient Application*.
5. *Recipient Application* decrypts  `cipher`  to get  `sk`.
6. *Recipient Application* derives the address corresponding to  `sk`  so that the user can confirm the correctness.

With signature and verification, the signature to `R` by `singerPubKey` is appended to `R`. `signerPubKey` itself could have been already signed by `trustedPubKey`, and that signature is appended to `signerPubKey`. Note that the signature is applied to the byte array data instead of its string representation, which might lead to confusion and interoperability issues (such as hex or base64, lower case v.s. upper case, etc.). See [Requests](#requests) and [Test Cases](#test-cases) for further clarification and examples.

### Requests

#### Encoding of data and messages

- Raw bytes are encoded in hex and prefixed with &apos;0x&apos;.
- Unless specified otherwise, all parameters and return values are hex-encoded bytes.
- `cipher`  is encoded into a single byte buffer as: `[IV  || encrypted_sk || tag]`.
- `R`, `S`, `signerPubKey`, and `trustedPubKey` are compressed if applicable.
- `R` or `signerPubKey` could be followed by a signature to it: `[pub || sig]`. Note that for the secp256k1 curve, the signature is just 64 bytes without the `v` indicator as found in a typical Ethereum signature.

#### R1. Request for Recipient to generate ephemeral key pair

```javascript
request({
	method: &apos;eth_generateEphemeralKeyPair&apos;,
	params: [version, signerPubKey],
})
// expected return value: R
```

`signerPubKey`  is optional. If provided, it is assumed that the implementation has the corresponding private key and the implementation MUST sign the ephemeral public key (in the form of what is to be returned). The signature algorithm is determined by the curve part of the  `version`  parameter, that is, ECDSA for secp256k1, and Ed25519 for Curve25519. And in this situation, it should be the case that *Sender* trusts  `signerPubKey`, no matter how this trust is maintained. If not, the next request WILL be rejected by *Sender Application*. Also, see [Security Considerations](#security-considerations).

The implementation then MUST generate random private key `r` with a cryptographic secure random number generator (CSRNG), and derive ephemeral public key `R = [r]G`. The implementation SHOULD keep the generated key pair `(r, R)` in a secure manner in accordance with the circumstances, and SHOULD keep it only for a limited duration, but the specific duration is left to individual implementations. The implementation SHOULD be able to retrieve `r` when given back the corresponding public key `R` if within the said duration.

The return value is `R`, compressed if applicable. If  `signerPubKey`  is provided, then the `signature` is appended to `R`, also hex-encoded.

Alternatively, `signature` could be calculated separately, and then appended to the returned data.

#### R2. Request for Sender to encapsulate the private key

```javascript
request({
	method: &apos;eth_encapsulatePrivateKey&apos;,
	params: [
		version,
		recipient, // public key, may be followed by its signature, see signerPubKey
		signerPubKey,
		oob,
		salt,
		account
	],
})
// expected return value: S || cipher
```

`recipient`  is the return value from the call to generate ephemeral key pair, with the optional `signature` appended either as returned or separately.

`oob`  and  `salt`  are just byte arrays.

`account`  is used to identify which private key to be encapsulated. With Ethereum, it is an address. Also, see [Encoding of data and messages](#encoding-of-data-and-messages).

If  `signerPubKey`  is provided or  `recipient`  contains `signature` data, the implementation MUST perform signature verification. Missing data or incorrect format MUST either fail the call or result in an empty return and optional error logs.

`signerPubKey` could have been further signed by another key pair `(trusted, trustedPubKey)`, which is trusted by *Sender Application*. In that case, `signerPubKey` is appended with the corresponding signature data, which SHOULD be verified against `trustedPubKey`. See [Test Cases](#test-cases) for further clarification.

The implementation shall then proceed to retrieve the private key `sk` corresponding to  `account`, and follow the [Core Algorithms](#core-algorithms) to encrypt it.

The return data is a byte array that contains first *Sender*&apos;s ephemeral public key `S` (compressed if applicable), then `cipher` including any authentication tag, that is, `S || cipher`.

#### R3. Request for Recipient to unwrap and intake the private key

```javascript
request({
	method: &apos;eth_intakePrivateKey&apos;,
	params: [
		version,
		recipientPublicKey, //  no signature this time
		oob,
		salt,
		data
	],
})
// expected return value: account
```

This time  `recipientPublicKey`  is only the ephemeral public key `R` generated earlier in the Recipient side, just for the implementation to retrieve the corresponding private key `r`.  `data`  is the return value from the call to encapsulate private key, which is `S || cipher`.

When the encapsulated private key `sk` is decrypted successfully, the implementation can process it further according to the designated purposes. Some general security guidelines SHALL be followed, for example, do  *not*  log the value, do securely wipe it after use, etc.

The return value is the corresponding Ethereum address for `sk`, or empty if any error.

### Options and Parameters

Available elliptic curves are:

- secp256k1 (mandatory)
- Curve25519

Available authenticated encryption schemes are:

- AES-128-GCM (mandatory)
- AES-256-GCM
- Chacha20-Poly1305

The version string is simply the concatenation of the elliptic curve and AE scheme, for example, secp256k1-AES-128-GCM. The above lists allow a combination of six different concrete schemes. Implementations are encouraged to implement curve-related logic separately from authenticated encryption schemes to avoid duplication and to promote interoperability.

Signature algorithms for each curve are:

- secp256k1 --&gt; ECDSA
- Curve25519 --&gt; Ed25519

## Rationale

A critical difference between this [EIP-6051](/EIPs/EIPS/eip-6051) with [EIP-5630](/EIPs/EIPS/eip-5630) is that, as the purpose of key encapsulation is to transport a private key securely, the public key from the key recipient should be ephemeral, and mostly used only one-time. While in EIP-5630 settings, the public key of the message recipient shall be stable for a while so that message senders can encrypt messages without key discovery every time.

There is security implication to this difference, including perfect forward secrecy. We aim to achieve perfect forward secrecy by generating ephemeral key pairs on both sides every time:

1) first *Recipient* shall generate an ephemeral key pair, retain the private key securely, and export the public key;
2) then *Sender* can securely wrap the private key in ECIES, with another ephemeral key pair, then destroy the ephemeral key securely;
3) finally *Recipient* can unwrap the private key, then destroy its ephemeral key pair securely. After these steps, the cipher text in transport intercepted by a malicious 3rd party is no longer decryptable.

## Backwards Compatibility

No backward compatibility issues for this new proposal.

### Interoperability

To minimize potential compatibility issues among applications (including hardware wallets), this EIP requires that version secp256k1-AES-128-GCM MUST be supported.

The version could be decided by the user or negotiated by both sides. When there is no user input or negotiation, secp256k1-AES-128-GCM is assumed.

It is expected that implementations cover curve supports separately from encryption support, that is, all the versions that could be derived from the supported curve and supported encryption scheme should work.

Signatures to `R` and `signerPubKey` are applied to byte array values instead of the encoded string.

### UX Recommendations

`salt` and/or `oob` data: both are inputs to the HKDF function (`oob` as “info” parameter). For better user experiences we suggest to require from users only one of them but this is up to the implementation.

*Recipient Application* is assumed to be powerful enough. *Sender Application* could have very limited computing power and user interaction capabilities.

## Test Cases

For review purposes, the program to generate the test vectors is open-sourced and provided in the corresponding discussion thread.

### Data Fixation

Throughout the test cases, we fix values for the below data:

- `sk`, the private key to be encapsulated, fixed to: `0xf8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315`. The corresponding address is `0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9`, called `account`. Note that these values come from the book *Mastering Ethereum* by Andreas M. Antonopoulos and Gavin Wood.
- `r`, the Recipient private key, fixed to `0x6f2dd2a7804705d2d536bee92221051865a639efa23f5ca7c810e77048253a79`
- `s`, the Sender private key, fixed to `0x28fa2db9f916e44fcc88370bedaf5eb3ec45632f040f4c1450c0f101e1e8bac8`
- `signer`, the private key to sign the ephemeral public key, fixed to `0xac304db075d1685284ba5e10c343f2324ee32df3394fc093c98932517d36e344`. When used for Ed25519 signing, however, this value acts as `seed`, while the actual private key is calculated as `SHA512(seed)[:32]`. Or put another way, the public key is the scalar multiplication of hashed private key to the base point. Same for `trusted`.
- `trusted`, the private key to sign `signerPubKey`, fixed to `0xda6649d68fc03b807e444e0034b3b59ec60716212007d72c9ddbfd33e25d38d1`
- `oob`, fixed to `0x313233343536` (string value: `123456`)
- `salt`, fixed to `0x6569703a2070726976617465206b657920656e63617073756c6174696f6e` (string value: `eip: private key encapsulation`)

### Case 1

Use `version` as `secp256k1-AES-128-GCM`. **R1** is provided as:

```javascript
request({
	method: &apos;eth_generateEphemeralKeyPair&apos;,
	params: [
		version: &apos;secp256k1-AES-128-GCM&apos;,
		signerPubKey: &apos;0x035a5ca16997f9b9ead9572c9bde36c5dab584b17bc965cdd7c2945c776e981b0b&apos;
	],
})
```

Suppose the implementation generates an ephemeral key pair `(r, R)`:

```
r: &apos;0x6f2dd2a7804705d2d536bee92221051865a639efa23f5ca7c810e77048253a79&apos;,
R: &apos;0x039ef98feddb39664450c3876878093c70652caba7e3fd04333c0558ffdf798d09&apos;
```

The return value could be:

```
&apos;0x039ef98feddb39664450c3876878093c70652caba7e3fd04333c0558ffdf798d09536da06b8d9207040ada179dc2c38f701a1a21c9ab5a7d52f5da50ea438e8ccf47dac77547fbdde194f71db52860b9e10ca2b089646f133d172124504ac1996a&apos;
```

Note that `R` is compressed and `R` leads the return value: `R || sig`.

Therefore **R2** could be provided as:

```javascript
request({
	method: &apos;eth_encapsulatePrivateKey&apos;,
	params: [
		version: &apos;secp256k1-AES-128-GCM&apos;,
		recipient: &apos;0x039ef98feddb39664450c3876878093c70652caba7e3fd04333c0558ffdf798d09536da06b8d9207040ada179dc2c38f701a1a21c9ab5a7d52f5da50ea438e8ccf47dac77547fbdde194f71db52860b9e10ca2b089646f133d172124504ac1996a&apos;,
		signerPubKey: &apos;0x035a5ca16997f9b9ead9572c9bde36c5dab584b17bc965cdd7c2945c776e981b0b5bd427c527b7f1012b8edfd179b9002a7f2d7fc326bb6ae9aaf38b44eb93c397631fd8bb05fd78fa16ecca1eb19652b200f9048611265bc81f485cf60f29d6de&apos;,
		oob: &apos;0x313233343536&apos;,
		salt: &apos;0x6569703a2070726976617465206b657920656e63617073756c6174696f6e&apos;,
		account: &apos;0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9&apos;
	],
})
```

*Sender Application* first verifies first layer signature as ECDSA over secp256k1:

```
// actual message to be signed should be the decoded byte array
msg: &apos;0x039ef98feddb39664450c3876878093c70652caba7e3fd04333c0558ffdf798d09&apos;,
sig: &apos;0x536da06b8d9207040ada179dc2c38f701a1a21c9ab5a7d52f5da50ea438e8ccf47dac77547fbdde194f71db52860b9e10ca2b089646f133d172124504ac1996aaf4a811661741a43587dd458858b75c582ca7db82fa77b&apos;,
//signerPubKey
pub: &apos;0x035a5ca16997f9b9ead9572c9bde36c5dab584b17bc965cdd7c2945c776e981b0b&apos;
```

Then it proceeds to verify the second layer signature, also as ECDSA over secp256k1:

```
// actual message to be signed should be the decoded byte array
msg: &apos;0x035a5ca16997f9b9ead9572c9bde36c5dab584b17bc965cdd7c2945c776e981b0b&apos;,
sig: &apos;0x5bd427c527b7f1012b8edfd179b9002a7f2d7fc326bb6ae9aaf38b44eb93c397631fd8bb05fd78fa16ecca1eb19652b200f9048611265bc81f485cf60f29d6de&apos;,
//trustedPubKey
pub: &apos;0x027fb72176f1f9852ce7dd9dc3aa4711675d3d8dc5102b86d758d853002137e839&apos;
```

Since *Sender Application* trusts `trustedPubKey`, the signature verification succeeds.

Suppose the implementation generates an ephemeral key pair `(s, S)` as:

```
s: &apos;0x28fa2db9f916e44fcc88370bedaf5eb3ec45632f040f4c1450c0f101e1e8bac8&apos;,
S: &apos;0x02ced2278d9ebb193f166d4ee5bbbc5ab8ca4b9ddf23c4172ad11185c079944c02&apos;
```

The shared secret, symmetric key, and IV should be:

```
ss: &apos;0x8e83bc5a9c77b11afc12c9a8262b16e899678d1720459e3b73ca2abcfed1fca3&apos;,
skey: &apos;0x6ccc02a61aa16d6c66a1277e5e2434b8&apos;,
IV: &apos;0x9c7a0f870d17ced2d2c3d1cf&apos;
```

Then the return value should be:

```
&apos;0x02ced2278d9ebb193f166d4ee5bbbc5ab8ca4b9ddf23c4172ad11185c079944c02abff407e8901bb37d13d724a2e3a8a1a5af300adc286aa2ec65ef2a38c10c5cec68a949d0a20dbad2a8e5dfd7a14bbcb&apos;
```

With compressed public key `S` leading `cipher`, which in turn is (added prefix &apos;0x&apos;):

```
&apos;0xabff407e8901bb37d13d724a2e3a8a1a5af300adc286aa2ec65ef2a38c10c5cec68a949d0a20dbad2a8e5dfd7a14bbcb&apos;
```

Then **R3** is provided as:

```javascript
request({
	method: &apos;eth_intakePrivateKey&apos;,
	params: [
		version: &apos;secp256k1-AES-128-GCM&apos;,
		recipientPublicKey: &apos;0x039ef98feddb39664450c3876878093c70652caba7e3fd04333c0558ffdf798d09&apos;,
		oob: &apos;0x313233343536&apos;,
		salt: &apos;0x6569703a2070726976617465206b657920656e63617073756c6174696f6e&apos;,
		data: &apos;0x02ced2278d9ebb193f166d4ee5bbbc5ab8ca4b9ddf23c4172ad11185c079944c02abff407e8901bb37d13d724a2e3a8a1a5af300adc286aa2ec65ef2a38c10c5cec68a949d0a20dbad2a8e5dfd7a14bbcb&apos;
	],
})
```

The return value should be `0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9`. This matches the `account` parameter in **R2**.

### Case 2

Use `version` as `secp256k1-AES-256-GCM`. The calculated symmetric key `skey`, `IV`, and `cipher` will be different. **R1** is provided as:

```javascript
request({
	method: &apos;eth_generateEphemeralKeyPair&apos;,
	params: [
		version: &apos;secp256k1-AES-256-GCM&apos;,
		signerPubKey: &apos;0x035a5ca16997f9b9ead9572c9bde36c5dab584b17bc965cdd7c2945c776e981b0b&apos;
	],
})
```

Note that only the `version` is different (AES key size). We keep using the same `(r, R)` (this is just a test vector).

Therefore **R2** is provided as:

```javascript
request({
	method: &apos;eth_encapsulatePrivateKey&apos;,
	params: [
		version: &apos;secp256k1-AES-256-GCM&apos;,
		recipient: &apos;0x039ef98feddb39664450c3876878093c70652caba7e3fd04333c0558ffdf798d09536da06b8d9207040ada179dc2c38f701a1a21c9ab5a7d52f5da50ea438e8ccf47dac77547fbdde194f71db52860b9e10ca2b089646f133d172124504ac1996a&apos;,
		signerPubKey: &apos;0x035a5ca16997f9b9ead9572c9bde36c5dab584b17bc965cdd7c2945c776e981b0b5bd427c527b7f1012b8edfd179b9002a7f2d7fc326bb6ae9aaf38b44eb93c397631fd8bb05fd78fa16ecca1eb19652b200f9048611265bc81f485cf60f29d6de&apos;,
		oob: &apos;0x313233343536&apos;,
		salt: &apos;0x6569703a2070726976617465206b657920656e63617073756c6174696f6e&apos;,
		account: &apos;0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9&apos;
	],
})
```

Suppose the implementation generates the same `(s, S)` as [Case 1](#case-1). The shared secret, symmetric key, and IV should be:

```
ss: &apos;0x8e83bc5a9c77b11afc12c9a8262b16e899678d1720459e3b73ca2abcfed1fca3&apos;,
skey: &apos;0x6ccc02a61aa16d6c66a1277e5e2434b89c7a0f870d17ced2d2c3d1cfd0e6f199&apos;,
IV: &apos;0x3369b9570b9d207a0a8ebe27&apos;
```

With shared secret `ss` remaining the same as [Case 1](#case-1), symmetric key `skey` contains both the `skey` and `IV` from [Case 1](#case-1). IV is changed.

Then the return value should be the following, with the `S` part the same as [Case 1](#case-1) and the `cipher` part different:

```
&apos;0x02ced2278d9ebb193f166d4ee5bbbc5ab8ca4b9ddf23c4172ad11185c079944c0293910a91270b5deb0a645cc33604ed91668daf72328739d52a5af5a4760c4f3a9592b8f6d9b3ebe25127e7bf1c43b839&apos;
```

Then **R3** is provided as:

```javascript
request({
	method: &apos;eth_intakePrivateKey&apos;,
	params: [
		version: &apos;secp256k1-AES-256-GCM&apos;,
		recipientPublicKey: &apos;0x039ef98feddb39664450c3876878093c70652caba7e3fd04333c0558ffdf798d09&apos;,
		oob: &apos;0x313233343536&apos;,
		salt: &apos;0x6569703a2070726976617465206b657920656e63617073756c6174696f6e&apos;,
		data: &apos;0x02ced2278d9ebb193f166d4ee5bbbc5ab8ca4b9ddf23c4172ad11185c079944c0293910a91270b5deb0a645cc33604ed91668daf72328739d52a5af5a4760c4f3a9592b8f6d9b3ebe25127e7bf1c43b839&apos;
	],
})
```

The return value should be `0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9`. This matches the `account` parameter in **R2**.

### Case 3

Use `version` as: `Curve-25519-Chacha20-Poly1305`. **R1** is provided as:

```javascript
request({
	method: &apos;eth_generateEphemeralKeyPair&apos;,
	params: [
		version: &apos;Curve25519-Chacha20-Poly1305&apos;,
		signerPubKey: &apos;0xe509fb840f6d5a69333ef68d69b86de55b9b905e45b16e3591912c097ba69938&apos;
	],
})
```

Note that with Curve25519 the size is 32 (bytes) for both the public key and private key. And there is no compression for the public key. `signerPubKey` is calculated as:

```
//signer is &apos;0xac304db075d1685284ba5e10c343f2324ee32df3394fc093c98932517d36e344&apos;
s := SHA512(signer)[:32]
signerPubKey := Curve25519.ScalarBaseMult(s).ToHex()
```

The same technique applies to `trustedPubKey`. With `r` the same as in [Case 1](#case-1) and [Case 2](#case-2) and the curve being changed, the return value is `R = [r]G || sig`:

```
R = &apos;0xc0ea3514b0ab83b2fe4f4ef96159cda8fa836ce549ef09569b901eef0723bf79cac06de279ec7f65f6b75f6bee740496df0650a6de61da5e691d7c5da1c7cb1ece61c669dd588a1029c38f11ad1714c1c9742232f9562ca6bbc7bad57882da04&apos;
```

**R2** is provided as:

```javascript
request({
	method: &apos;eth_encapsulatePrivateKey&apos;,
	params: [
		version: &apos;Curve25519-Chacha20-Poly1305&apos;,
		recipient: &apos;0xc0ea3514b0ab83b2fe4f4ef96159cda8fa836ce549ef09569b901eef0723bf79879d900f04a955078ff6ae86f1d1b69b3e1265370e64bf064adaecb895c51effa3bdae7964bf8f9a6bfaef3b66306c1bc36afa5607a51b9768aa42ac2c961f02&apos;,
		signerPubKey: &apos;0xe509fb840f6d5a69333ef68d69b86de55b9b905e45b16e3591912c097ba69938d43e06a0f32c9e5ddb39fce34fac2b6f5314a1b1583134f27426d50af7094b0c101e848737e7f717da8c8497be06bab2a9536856c56eee194e89e94fd1bba509&apos;,
		oob: &apos;0x313233343536&apos;,
		salt: &apos;0x6569703a2070726976617465206b657920656e63617073756c6174696f6e&apos;,
		account: &apos;0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9&apos;
	],
})
```

Both `recipient` and `signerPubKey` have been signed in Ed25519. Verifying signature to `R` is carried out as:

```
// actual message to be signed should be the decoded byte array
msg: &apos;0xc0ea3514b0ab83b2fe4f4ef96159cda8fa836ce549ef09569b901eef0723bf79&apos;,
sig: &apos;0x879d900f04a955078ff6ae86f1d1b69b3e1265370e64bf064adaecb895c51effa3bdae7964bf8f9a6bfaef3b66306c1bc36afa5607a51b9768aa42ac2c961f02&apos;,
//signerPubKey
pub: &apos;0xe509fb840f6d5a69333ef68d69b86de55b9b905e45b16e3591912c097ba69938&apos;
```

After successfully verifying the signature (and the one by `trustedPubKey`), the implementation then generates ephemeral key pair `(s, S)` in Curve25519:

```
// s same as Case 1 and Case 2
s = &apos;0x28fa2db9f916e44fcc88370bedaf5eb3ec45632f040f4c1450c0f101e1e8bac8&apos;,
S = &apos;0xd2fd6fcaac231d08363e736e61edb7e7696b13a727e3d2a239415cb8dc6ee278&apos;
```

The shared secret, symmetric key, and IV should be:

```
ss: &apos;0xe0b36f56cdb63c27e933a5a67a5e97db4b566c9276a36aeee5dc6e87da118867&apos;,
skey: &apos;0x7c6fa749e6df13c8578dc44cb24cdf46a44cb163e1e570c2e590c720aed5783f&apos;,
IV: &apos;0x3c98ef6fc34b0d6e7e16bd78&apos;
```

Then the return value should be `S || cipher`:

```
&apos;0xd2fd6fcaac231d08363e736e61edb7e7696b13a727e3d2a239415cb8dc6ee2786a7e2e40efb86dc68f44f3e032bbedb1259fa820e548ac5adbf191784c568d4f642ca5b60c0b2142189dff6ee464b95c&apos;
```

Then **R3** is provided as:

```javascript
request({
	method: &apos;eth_intakePrivateKey&apos;,
	params: [
		version: &apos;Curve25519-Chacha20-Poly1305&apos;,
		recipientPublicKey: &apos;0xc0ea3514b0ab83b2fe4f4ef96159cda8fa836ce549ef09569b901eef0723bf79&apos;,
		oob: &apos;0x313233343536&apos;,
		salt: &apos;0x6569703a2070726976617465206b657920656e63617073756c6174696f6e&apos;,
		data: &apos;0xd2fd6fcaac231d08363e736e61edb7e7696b13a727e3d2a239415cb8dc6ee2786a7e2e40efb86dc68f44f3e032bbedb1259fa820e548ac5adbf191784c568d4f642ca5b60c0b2142189dff6ee464b95c&apos;
	],
})
```

The return value should be `0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9`. This matches the `account` parameter in **R2**.

## Security Considerations

### Perfect Forward Secrecy

PFS is achieved by using ephemeral key pairs on both sides.

### Optional Signature and Trusted Public Keys

`R` could be signed so that *Sender Application* can verify if `R` could be trusted or not. This involves both signature verification and if the signer could be trusted or not. While signature verification is quite straightforward in itself, the latter should be managed with care. To facilitate this trust management issue, `signerPubKey` could be further signed, creating a dual-layer trust structure:

```
R &lt;-- signerPubKey &lt;-- trustedPubKey
```

This allows various strategies to manage trust. For example:

- A hardware wallet vendor which takes it very seriously about the brand reputation and the fund safety for its customers, could choose to trust only its own public keys, all instances of `trustedPubKey`. These public keys only sign `signerPubKey` from selected partners.
- A MPC service could publish its `signerPubKey` online so that *Sender Application* won&apos;t verify the signature against a wrong or fake public key.

Note that it is advised that a separate key pair should be used for signing on each curve.

### Security Level

1. We are not considering post-quantum security. If the quantum computer becomes a materialized threat, the underlying cipher of Ethereum and other L1 chains would have been replaced, and this EIP will be outdated then (as the EC part of ECIES is also broken).
2. The security level shall match that of the elliptic curve used by the underlying chains. It does not make much sense to use AES-256 to safeguard a secp256k1 private key but implementations could choose freely.
3. That being said, a key might be used in multiple chains. So the security level shall cover the most demanding requirement and potential future developments.

AES-128, AES-256, and ChaCha20 are provided.

### Randomness

`r` and `s` must be generated with a cryptographic secure random number generator (CSRNG).

`salt`  could be random bytes generated the same way as  `r`  or  `s`.  `salt`  could be in any length but the general suggestion is 12 or 16, which could be displayed as a QR code by the screen of some hardware wallet (so that another application could scan to read). If  `salt`  is not provided, this EIP uses the default value as `EIP-6051`.

### Out of Band Data

`oob`  data is optional. When non-empty, its content is digits or an alpha-numeric string from the user. *Sender Application* may mandate  `oob`  from the user.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 21 Nov 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6051</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6051</guid>
      </item>
    
      <item>
        <title>Parent-Governed Nestable Non-Fungible Tokens</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6059-parent-governed-nestable-non-fungible-tokens/11914</comments>
        
        <description>## Abstract

The Parent-Governed Nestable NFT standard extends [ERC-721](/EIPs/EIPS/eip-721) by allowing for a new inter-NFT relationship and interaction.

At its core, the idea behind the proposal is simple: the owner of an NFT does not have to be an Externally Owned Account (EOA) or a smart contract, it can also be an NFT.

The process of nesting an NFT into another is functionally identical to sending it to another user. The process of sending a token out of another one involves issuing a transaction from the account owning the parent token.

An NFT can be owned by a single other NFT, but can in turn have a number of NFTs that it owns. This proposal establishes the framework for the parent-child relationships of NFTs. A parent token is the one that owns another token. A child token is a token that is owned by another token. A token can be both a parent and child at the same time. Child tokens of a given token can be fully managed by the parent token&apos;s owner, but can be proposed by anyone.

![Nestable tokens](/EIPs/assets/eip-6059/img/eip-6059-nestable-tokens.png)

The graph illustrates how a child token can also be a parent token, but both are still administered by the root parent token&apos;s owner.

## Motivation

With NFTs being a widespread form of tokens in the Ethereum ecosystem and being used for a variety of use cases, it is time to standardize additional utility for them. Having the ability for tokens to own other tokens allows for greater utility, usability and forward compatibility.

In the four years since [ERC-721](/EIPs/EIPS/eip-721) was published, the need for additional functionality has resulted in countless extensions. This ERC improves upon ERC-721 in the following areas:

- [Bundling](#bundling)
- [Collecting](#collecting)
- [Membership](#membership)
- [Delegation](#delegation)

### Bundling

One of the most frequent uses of [ERC-721](/EIPs/EIPS/eip-721) is to disseminate the multimedia content that is tied to the tokens. In the event that someone wants to offer a bundle of NFTs from various collections, there is currently no easy way of bundling all of these together and handle their sale as a single transaction. This proposal introduces a standardized way of doing so. Nesting all of the tokens into a simple bundle and selling that bundle would transfer the control of all of the tokens to the buyer in a single transaction.

### Collecting

A lot of NFT consumers collect them based on countless criteria. Some aim for utility of the tokens, some for the uniqueness, some for the visual appeal, etc. There is no standardized way to group the NFTs tied to a specific account. By nesting NFTs based on their owner&apos;s preference, this proposal introduces the ability to do it. The root parent token could represent a certain group of tokens and all of the children nested into it would belong to it.

The rise of soulbound, non-transferable, tokens, introduces another need for this proposal. Having a token with multiple soulbound traits (child tokens), allows for numerous use cases. One concrete example of this can be drawn from supply chains use case. A shipping container, represented by an NFT with its own traits, could have multiple child tokens denoting each leg of its journey.

### Membership

A common utility attached to NFTs is a membership to a Decentralised Autonomous Organization (DAO) or to some other closed-access group. Some of these organizations and groups occasionally mint NFTs to the current holders of the membership NFTs. With the ability to nest mint a token into a token, such minting could be simplified, by simply minting the bonus NFT directly into the membership one.

### Delegation

One of the core features of DAOs is voting and there are various approaches to it. One such mechanic is using fungible voting tokens where members can delegate their votes by sending these tokens to another member. Using this proposal, delegated voting could be handled by nesting your voting NFT into the one you are delegating your votes to and transferring it when the member no longer wishes to delegate their votes.

## Specification

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.

```solidity
/// @title EIP-6059 Parent-Governed Nestable Non-Fungible Tokens
/// @dev See https://eips.ethereum.org/EIPS/eip-6059
/// @dev Note: the ERC-165 identifier for this interface is 0x42b0e56f.

pragma solidity ^0.8.16;

interface IERC6059 /* is ERC165 */ {
    /**
     * @notice The core struct of ownership.
     * @dev The `DirectOwner` struct is used to store information of the next immediate owner, be it the parent token,
     * an `ERC721Receiver` contract or an externally owned account.
     * @dev If the token is not owned by an NFT, the `tokenId` MUST equal `0`.
     * @param tokenId ID of the parent token
     * @param ownerAddress Address of the owner of the token. If the owner is another token, then the address MUST be
     *  the one of the parent token&apos;s collection smart contract. If the owner is externally owned account, the address
     *  MUST be the address of this account
     */
    struct DirectOwner {
        uint256 tokenId;
        address ownerAddress;
    }

    /**
     * @notice Used to notify listeners that the token is being transferred.
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     * @param from Address of the previous immediate owner, which is a smart contract if the token was nested.
     * @param to Address of the new immediate owner, which is a smart contract if the token is being nested.
     * @param fromTokenId ID of the previous parent token. If the token was not nested before, the value MUST be `0`
     * @param toTokenId ID of the new parent token. If the token is not being nested, the value MUST be `0`
     * @param tokenId ID of the token being transferred
     */
    event NestTransfer(
        address indexed from,
        address indexed to,
        uint256 fromTokenId,
        uint256 toTokenId,
        uint256 indexed tokenId
    );

    /**
     * @notice Used to notify listeners that a new token has been added to a given token&apos;s pending children array.
     * @dev Emitted when a child NFT is added to a token&apos;s pending array.
     * @param tokenId ID of the token that received a new pending child token
     * @param childIndex Index of the proposed child token in the parent token&apos;s pending children array
     * @param childAddress Address of the proposed child token&apos;s collection smart contract
     * @param childId ID of the child token in the child token&apos;s collection smart contract
     */
    event ChildProposed(
        uint256 indexed tokenId,
        uint256 childIndex,
        address indexed childAddress,
        uint256 indexed childId
    );

    /**
     * @notice Used to notify listeners that a new child token was accepted by the parent token.
     * @dev Emitted when a parent token accepts a token from its pending array, migrating it to the active array.
     * @param tokenId ID of the token that accepted a new child token
     * @param childIndex Index of the newly accepted child token in the parent token&apos;s active children array
     * @param childAddress Address of the child token&apos;s collection smart contract
     * @param childId ID of the child token in the child token&apos;s collection smart contract
     */
    event ChildAccepted(
        uint256 indexed tokenId,
        uint256 childIndex,
        address indexed childAddress,
        uint256 indexed childId
    );

    /**
     * @notice Used to notify listeners that all pending child tokens of a given token have been rejected.
     * @dev Emitted when a token removes all a child tokens from its pending array.
     * @param tokenId ID of the token that rejected all of the pending children
     */
    event AllChildrenRejected(uint256 indexed tokenId);

    /**
     * @notice Used to notify listeners a child token has been transferred from parent token.
     * @dev Emitted when a token transfers a child from itself, transferring ownership.
     * @param tokenId ID of the token that transferred a child token
     * @param childIndex Index of a child in the array from which it is being transferred
     * @param childAddress Address of the child token&apos;s collection smart contract
     * @param childId ID of the child token in the child token&apos;s collection smart contract
     * @param fromPending A boolean value signifying whether the token was in the pending child tokens array (`true`) or
     *  in the active child tokens array (`false`)
     */
    event ChildTransferred(
        uint256 indexed tokenId,
        uint256 childIndex,
        address indexed childAddress,
        uint256 indexed childId,
        bool fromPending
    );

    /**
     * @notice The core child token struct, holding the information about the child tokens.
     * @return tokenId ID of the child token in the child token&apos;s collection smart contract
     * @return contractAddress Address of the child token&apos;s smart contract
     */
    struct Child {
        uint256 tokenId;
        address contractAddress;
    }

    /**
     * @notice Used to retrieve the *root* owner of a given token.
     * @dev The *root* owner of the token is the top-level owner in the hierarchy which is not an NFT.
     * @dev If the token is owned by another NFT, it MUST recursively look up the parent&apos;s root owner.
     * @param tokenId ID of the token for which the *root* owner has been retrieved
     * @return owner The *root* owner of the token
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @notice Used to retrieve the immediate owner of the given token.
     * @dev If the immediate owner is another token, the address returned, MUST be the one of the parent token&apos;s
     *  collection smart contract.
     * @param tokenId ID of the token for which the direct owner is being retrieved
     * @return address Address of the given token&apos;s owner
     * @return uint256 The ID of the parent token. MUST be `0` if the owner is not an NFT
     * @return bool The boolean value signifying whether the owner is an NFT or not
     */
    function directOwnerOf(uint256 tokenId)
        external
        view
        returns (
            address,
            uint256,
            bool
        );

    /**
     * @notice Used to burn a given token.
     * @dev When a token is burned, all of its child tokens are recursively burned as well.
     * @dev When specifying the maximum recursive burns, the execution MUST be reverted if there are more children to be
     *  burned.
     * @dev Setting the `maxRecursiveBurn` value to 0 SHOULD only attempt to burn the specified token and MUST revert if
     *  there are any child tokens present.
     * @param tokenId ID of the token to burn
     * @param maxRecursiveBurns Maximum number of tokens to recursively burn
     * @return uint256 Number of recursively burned children
     */
    function burn(uint256 tokenId, uint256 maxRecursiveBurns)
        external
        returns (uint256);

    /**
     * @notice Used to add a child token to a given parent token.
     * @dev This adds the child token into the given parent token&apos;s pending child tokens array.
     * @dev The destination token MUST NOT be a child token of the token being transferred or one of its downstream
     *  child tokens.
     * @dev This method MUST NOT be called directly. It MUST only be called from an instance of `IERC6059` as part of a 
        `nestTransfer` or `transferChild` to an NFT.
     * @dev Requirements:
     *
     *  - `directOwnerOf` on the child contract MUST resolve to the called contract.
     *  - the pending array of the parent contract MUST not be full.
     * @param parentId ID of the parent token to receive the new child token
     * @param childId ID of the new proposed child token
     */
    function addChild(uint256 parentId, uint256 childId) external;

    /**
     * @notice Used to accept a pending child token for a given parent token.
     * @dev This moves the child token from parent token&apos;s pending child tokens array into the active child tokens
     *  array.
     * @param parentId ID of the parent token for which the child token is being accepted
     * @param childIndex Index of the child token to accept in the pending children array of a given token
     * @param childAddress Address of the collection smart contract of the child token expected to be at the specified
     *  index
     * @param childId ID of the child token expected to be located at the specified index
     */
    function acceptChild(
        uint256 parentId,
        uint256 childIndex,
        address childAddress,
        uint256 childId
    ) external;

    /**
     * @notice Used to reject all pending children of a given parent token.
     * @dev Removes the children from the pending array mapping.
     * @dev The children&apos;s ownership structures are not updated.
     * @dev Requirements:
     *
     * - `parentId` MUST exist
     * @param parentId ID of the parent token for which to reject all of the pending tokens
     * @param maxRejections Maximum number of expected children to reject, used to prevent from
     *  rejecting children which arrive just before this operation.
     */
    function rejectAllChildren(uint256 parentId, uint256 maxRejections) external;

    /**
     * @notice Used to transfer a child token from a given parent token.
     * @dev MUST remove the child from the parent&apos;s active or pending children.
     * @dev When transferring a child token, the owner of the token MUST be set to `to`, or not updated in the event of `to`
     *  being the `0x0` address.
     * @param tokenId ID of the parent token from which the child token is being transferred
     * @param to Address to which to transfer the token to
     * @param destinationId ID of the token to receive this child token (MUST be 0 if the destination is not a token)
     * @param childIndex Index of a token we are transferring, in the array it belongs to (can be either active array or
     *  pending array)
     * @param childAddress Address of the child token&apos;s collection smart contract
     * @param childId ID of the child token in its own collection smart contract
     * @param isPending A boolean value indicating whether the child token being transferred is in the pending array of the
     *  parent token (`true`) or in the active array (`false`)
     * @param data Additional data with no specified format, sent in call to `to`
     */
    function transferChild(
        uint256 tokenId,
        address to,
        uint256 destinationId,
        uint256 childIndex,
        address childAddress,
        uint256 childId,
        bool isPending,
        bytes data
    ) external;

    /**
     * @notice Used to retrieve the active child tokens of a given parent token.
     * @dev Returns array of Child structs existing for parent token.
     * @dev The Child struct consists of the following values:
     *  [
     *      tokenId,
     *      contractAddress
     *  ]
     * @param parentId ID of the parent token for which to retrieve the active child tokens
     * @return struct[] An array of Child structs containing the parent token&apos;s active child tokens
     */
    function childrenOf(uint256 parentId)
        external
        view
        returns (Child[] memory);

    /**
     * @notice Used to retrieve the pending child tokens of a given parent token.
     * @dev Returns array of pending Child structs existing for given parent.
     * @dev The Child struct consists of the following values:
     *  [
     *      tokenId,
     *      contractAddress
     *  ]
     * @param parentId ID of the parent token for which to retrieve the pending child tokens
     * @return struct[] An array of Child structs containing the parent token&apos;s pending child tokens
     */
    function pendingChildrenOf(uint256 parentId)
        external
        view
        returns (Child[] memory);

    /**
     * @notice Used to retrieve a specific active child token for a given parent token.
     * @dev Returns a single Child struct locating at `index` of parent token&apos;s active child tokens array.
     * @dev The Child struct consists of the following values:
     *  [
     *      tokenId,
     *      contractAddress
     *  ]
     * @param parentId ID of the parent token for which the child is being retrieved
     * @param index Index of the child token in the parent token&apos;s active child tokens array
     * @return struct A Child struct containing data about the specified child
     */
    function childOf(uint256 parentId, uint256 index)
        external
        view
        returns (Child memory);

    /**
     * @notice Used to retrieve a specific pending child token from a given parent token.
     * @dev Returns a single Child struct locating at `index` of parent token&apos;s active child tokens array.
     * @dev The Child struct consists of the following values:
     *  [
     *      tokenId,
     *      contractAddress
     *  ]
     * @param parentId ID of the parent token for which the pending child token is being retrieved
     * @param index Index of the child token in the parent token&apos;s pending child tokens array
     * @return struct A Child struct containing data about the specified child
     */
    function pendingChildOf(uint256 parentId, uint256 index)
        external
        view
        returns (Child memory);

    /**
     * @notice Used to transfer the token into another token.
     * @dev The destination token MUST NOT be a child token of the token being transferred or one of its downstream
     *  child tokens.
     * @param from Address of the direct owner of the token to be transferred
     * @param to Address of the receiving token&apos;s collection smart contract
     * @param tokenId ID of the token being transferred
     * @param destinationId ID of the token to receive the token being transferred
     */
    function nestTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        uint256 destinationId
    ) external;
}
```

ID MUST never be a `0` value, as this proposal uses `0` values do signify that the token/destination is not an NFT.

## Rationale

Designing the proposal, we considered the following questions:

1. **How to name the proposal?**\
In an effort to provide as much information about the proposal we identified the most important aspect of the proposal; the parent centered control over nesting. The child token&apos;s role is only to be able to be `Nestable` and support a token owning it. This is how we landed on the `Parent-Centered` part of the title.
2. **Why is automatically accepting a child using [EIP-712](/EIPs/EIPS/eip-712) permit-style signatures not a part of this proposal?**\
For consistency. This proposal extends ERC-721 which already uses 1 transaction for approving operations with tokens. It would be inconsistent to have this and also support signing messages for operations with assets.
3. **Why use indexes?**\
To reduce the gas consumption. If the token ID was used to find which token to accept or reject, iteration over arrays would be required and the cost of the operation would depend on the size of the active or pending children arrays. With the index, the cost is fixed. Lists of active and pending children per token need to be maintained, since methods to get them are part of the proposed interface.\
To avoid race conditions in which the index of a token changes, the expected token ID as well as the expected token&apos;s collection smart contract is included in operations requiring token index, to verify that the token being accessed using the index is the expected one.\
Implementation that would internally keep track of indices using mapping was attempted. The minimum cost of accepting a child token was increased by over 20% and the cost of minting has increased by over 15%. We concluded that it is not necessary for this proposal and can be implemented as an extension for use cases willing to accept the increased transaction cost this incurs. In the sample implementation provided, there are several hooks which make this possible.
4. **Why is the pending children array limited instead of supporting pagination?**\
The pending child tokens array is not meant to be a buffer to collect the tokens that the root owner of the parent token wants to keep, but not enough to promote them to active children. It is meant to be an easily traversable list of child token candidates and should be regularly maintained; by either accepting or rejecting proposed child tokens. There is also no need for the pending child tokens array to be unbounded, because active child tokens array is.\
Another benefit of having bounded child tokens array is to guard against spam and griefing. As minting malicious or spam tokens could be relatively easy and low-cost, the bounded pending array assures that all of the tokens in it are easy to identify and that legitimate tokens are not lost in a flood of spam tokens, if one occurs.\
A consideration tied to this issue was also how to make sure, that a legitimate token is not accidentally rejected when clearing the pending child tokens array. We added the maximum pending children to reject argument to the clear pending child tokens array call. This assures that only the intended number of pending child tokens is rejected and if a new token is added to the pending child tokens array during the course of preparing such call and executing it, the clearing of this array SHOULD result in a reverted transaction.
5. **Should we allow tokens to be nested into one of its children?**\
The proposal enforces that a parent token can&apos;t be nested into one of its child token, or downstream child tokens for that matter. A parent token and its children are all managed by the parent token&apos;s root owner. This means that if a token would be nested into one of its children, this would create the ownership loop and none of the tokens within the loop could be managed anymore.
6. **Why is there not a &quot;safe&quot; nest transfer method?**\
`nestTransfer` is always &quot;safe&quot; since it MUST check for `IERC6059` compatibility on the destination.
7. **How does this proposal differ from the other proposals trying to address a similar problem?**\
This interface allows for tokens to both be sent to and receive other tokens. The propose-accept and parent governed patterns allow for a more secure use. The backward compatibility is only added for ERC-721, allowing for a simpler interface. The proposal also allows for different collections to inter-operate, meaning that nesting is not locked to a single smart contract, but can be executed between completely separate NFT collections.

### Propose-Commit pattern for child token management

Adding child tokens to a parent token MUST be done in the form of propose-commit pattern to allow for limited mutability by a 3rd party. When adding a child token to a parent token, it is first placed in a *&quot;Pending&quot;* array, and MUST be migrated to the *&quot;Active&quot;* array by the parent token&apos;s root owner. The *&quot;Pending&quot;* child tokens array SHOULD be limited to 128 slots to prevent spam and griefing.

The limitation that only the root owner can accept the child tokens also introduces a trust inherent to the proposal. This ensures that the root owner of the token has full control over the token. No one can force the user to accept a child if they don&apos;t want to.

### Parent Governed pattern

The parent NFT of a nested token and the parent&apos;s root owner are in all aspects the true owners of it. Once you send a token to another one you give up ownership.

We continue to use ERC-721&apos;s `ownerOf` functionality which will now recursively look up through parents until it finds an address which is not an NFT, this is referred to as the *root owner*. Additionally we provide the `directOwnerOf` which returns the most immediate owner of a token using 3 values: the owner address, the tokenId which MUST be 0 if the direct owner is not an NFT, and a flag indicating whether or not the parent is an NFT.

The root owner or an approved party MUST be able do the following operations on children: `acceptChild`, `rejectAllChildren` and `transferChild`.

The root owner or an approved party MUST also be allowed to do these operations only when token is not owned by an NFT: `transferFrom`, `safeTransferFrom`, `nestTransferFrom`, `burn`.

If the token is owned by an NFT, only the parent NFT itself MUST be allowed to execute the operations listed above. Transfers MUST be done from the parent token, using `transferChild`, this method in turn SHOULD call `nestTransferFrom` or `safeTransferFrom` in the child token&apos;s smart contract, according to whether the destination is an NFT or not. For burning, tokens must first be transferred to an EOA and then burned.

We add this restriction to prevent inconsistencies on parent contracts, since only the `transferChild` method takes care of removing the child from the parent when it is being transferred out of it.

### Child token management

This proposal introduces a number of child token management functions. In addition to the permissioned migration from *&quot;Pending&quot;* to *&quot;Active&quot;* child tokens array, the main token management function from this proposal is the `tranferChild` function. The following state transitions of a child token are available with it:

1. Reject child token
2. Abandon child token
3. Unnest child token
4. Transfer the child token to an EOA or an `ERC721Receiver`
5. Transfer the child token into a new parent token

To better understand how these state transitions are achieved, we have to look at the available parameters passed to `transferChild`:

```solidity
    function transferChild(
        uint256 tokenId,
        address to,
        uint256 destinationId,
        uint256 childIndex,
        address childAddress,
        uint256 childId,
        bool isPending,
        bytes data
    ) external;
```

Based on the desired state transitions, the values of these parameters have to be set accordingly (any parameters not set in the following examples depend on the child token being managed):

1. **Reject child token**\
![Reject child token](/EIPs/assets/eip-6059/img/eip-6059-reject-child.png)
2. **Abandon child token**\
![Abandon child token](/EIPs/assets/eip-6059/img/eip-6059-abandon-child.png)
3. **Unnest child token**\
![Unnest child token](/EIPs/assets/eip-6059/img/eip-6059-unnest-child.png)
4. **Transfer the child token to an EOA or an `ERC721Receiver`**\
![Transfer child token to EOA](/EIPs/assets/eip-6059/img/eip-6059-transfer-child-to-eoa.png)
5. **Transfer the child token into a new parent token**\
![Transfer child token to parent token](/EIPs/assets/eip-6059/img/eip-6059-transfer-child-to-token.png)\
This state change places the token in the pending array of the new parent token. The child token still needs to be accepted by the new parent token&apos;s root owner in order to be placed into the active array of that token.

## Backwards Compatibility

The Nestable token standard has been made compatible with [ERC-721](/EIPs/EIPS/eip-721) in order to take advantage of the robust tooling available for implementations of ERC-721 and to ensure compatibility with existing ERC-721 infrastructure.

## Test Cases

Tests are included in [`nestable.ts`](/EIPs/assets/eip-6059/test/nestable.ts).

To run them in terminal, you can use the following commands:

```
cd ../assets/eip-6059
npm install
npx hardhat test
```

## Reference Implementation

See [`NestableToken.sol`](/EIPs/assets/eip-6059/contracts/NestableToken.sol).


## Security Considerations

The same security considerations as with [ERC-721](/EIPs/EIPS/eip-721) apply: hidden logic may be present in any of the functions, including burn, add child, accept child, and more.

Since the current owner of the token is allowed to manage the token, there is a possibility that after the parent token is listed for sale, the seller might remove a child token just before before the sale and thus the buyer would not receive the expected child token. This is a risk that is inherent to the design of this standard. Marketplaces should take this into account and provide a way to verify the expected child tokens are present when the parent token is being sold or to guard against such a malicious behaviour in another way.

Caution is advised when dealing with non-audited contracts.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 15 Nov 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6059</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6059</guid>
      </item>
    
      <item>
        <title>Real Estate Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/updated-eip-6065-real-estate-token/11936</comments>
        
        <description>## Abstract

This proposal introduces an open structure for physical real estate and property to exist on the blockchain. This standard builds off of [ERC-721](/EIPs/EIPS/eip-721), adding important functionality necessary for representing real world assets such as real estate. The three objectives this standard aims to meet are: universal transferability of the NFT, private property rights attached to the NFT, and atomic transfer of property rights with the transfer of the NFT. The token contains a hash of the operating agreement detailing the NFT holder’s legal right to the property, unique identifiers for the property, a debt value and foreclosure status, and a manager address.

## Motivation

Real estate is the largest asset class in the world. By tokenizing real estate, barriers to entry are lowered, transaction costs are minimized, information asymmetry is reduced, ownership structures become more malleable, and a new building block for innovation is formed. However, in order to tokenize this asset class, a common standard is needed that accounts for its real world particularities while remaining flexible enough to adapt to various jurisdictions and regulatory environments.

Ethereum tokens involving real world assets (RWAs) are notoriously tricky. This is because Ethereum tokens exist on-chain, while real estate exists off-chain. As such, the two are subject to entirely different consensus environments. For Ethereum tokens, consensus is reached through a formalized process of distributed validators. When a purely-digital NFT is transferred, the new owner has a cryptographic guarantee of ownership. For real estate, consensus is supported by legal contracts, property law, and enforced by the court system. With existing asset-backed ERC-721 tokens, a transfer of the token to another individual does not necessarily have any impact on the legal ownership of the physical asset.

This standard attempts to solve the real world reconciliation issue, enabling real estate NFTs to function seamlessly on-chain, just like their purely-digital counterparts.

## Specification

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.

In order to meet the above objectives and create an open standard for on-chain property ownership we have created a token structure that builds on the widely-used ERC-721 standard.

### Token Components:

1. Inherits ERC-721 - Allows for backwards compatibility with the most widely accepted NFT token standard.
2. operatingAgreementHashOf - immutable hash of the legal agreement detailing the right to ownership and conditions of use with regard to the property
3. Property Unique Identifiers - legal description (from physical deed), street address, GIS coordinates, parcel/tax ID, legal owning entity (on deed)
4. debtOf - readable debt value, currency, and foreclosure status of the NFT
5. managerOf - readable Ethereum address with managing control of property

### Interfaces

This EIP inherits the ERC-721 NFT token standard for all transfer and approval logic. All transfer and approval functions are inherited from this token standard without changes. Additionally, this EIP also inherits the ERC-721 Metadata standards for name, symbol, and metadata URI lookup. This allows an NFT under this EIP to become interoperable with preexisting NFT exchanges and services, however, some care must be taken. Please refer to [Backwards Compatibility](#backwards-compatibility) and [Security Considerations](#security-considerations).


#### Solidity Interface

```
pragma solidity ^0.8.13;

import &quot;forge-std/interfaces/IERC721.sol&quot;;

interface IERC6065 is IERC721 {

	// This event MUST emit if the asset is ever foreclosed.
	event Foreclosed(uint256 id);

	/* 
	Next getter functions return immutable data for NFT.
	*/
	function legalDescriptionOf(uint256 _id) external view returns (string memory);
	function addressOf(uint256 _id) external view returns (string memory);
	function geoJsonOf(uint256 _id) external view returns (string memory);
	function parcelIdOf(uint256 _id) external view returns (string memory);
	function legalOwnerOf(uint256 _id) external view returns (string memory);
	function operatingAgreementHashOf(uint256 _id) external view returns (bytes32);

	/*
	Next getter function returns the debt denomination token of the NFT, the amount of debt (negative debt == credit), and if the underlying 
	asset backing the NFT has been foreclosed on. This should be utilized specifically for off-chain debt and required payments on the RWA asset.
	It&apos;s recommended that administrators only use a single token type to denominate the debt. It&apos;s unrealistic to require integrating smart
	contracts to implement possibly unbounded tokens denominating the off-chain debt of an asset.

	If the foreclosed status == true, then the RWA can be seen as severed from the NFT. The NFT is now &quot;unbacked&quot; by the RWA.
	*/
	function debtOf(uint256 _id) external view returns (address debtToken, int256 debtAmt, bool foreclosed);

	// Get the managerOf an NFT. The manager can have additional rights to the NFT or RWA on or off-chain.
	function managerOf(uint256 _id) external view returns (address);
}
```

## Rationale

### Introduction

Real world assets operate in messy, non-deterministic environments. Because of this, validating the true state of an asset can be murky, expensive, or time-consuming. For example, in the U.S., change of property ownership is usually recorded at the County Recorder’s office, sometimes using pen and paper. It would be infeasible to continuously update this manual record every time an NFT transaction occurs on the blockchain. Additionally, since real world property rights are enforced by the court of law, it is essential that property ownership be documented in such a way that courts are able to interpret and enforce ownership if necessary.

For these reasons, it is necessary to have a trusted party tasked with the responsibility of ensuring the state of the on-chain property NFT accurately mirrors its physical counterpart. By having an Administrator for the property who issues a legally-binding digital representation of the physical property, we are able to solve for both the atomic transfer of the property rights with the transfer of the NFT, as well as institute a seamless process for making the necessary payments and filings associated with property ownership. This is made possible by eliminating the change in legal ownership each time the NFT changes hands. An example Administrator legal structure implemented for property tokenization in the U.S. is provided in the [Reference Implementation](#reference-implementation). While a token that implements this standard must have a legal entity to conduct the off-chain dealings for the property, this implementation is not mandatory.

### Guiding Objectives

We have designed this EIP to achieve three primary objectives necessary for creating an NFT representation of physical real estate:

#### 1. Real Estate NFTs are universally transferable

A key aspect to private property is the right to transfer ownership to any legal person or entity that has the capacity to own that property. Therefore, an NFT representation of physical property should maintain that universal freedom of transfer.

#### 2. All rights associated with property ownership are able to be maintained and guaranteed by the NFT

The rights associated with private property ownership are the right to hold, occupy, rent, alter, resell, or transfer the property. It is essential that these same rights are able to be maintained and enforced with an NFT representation of real estate.

#### 3. Property rights are transferred atomically with the transfer of the NFT

Token ownership on any blockchain is atomic with the transfer of the digital token. To ensure the digital representation of a physical property is able to fully integrate the benefits of blockchain technology, it is essential the rights associated with the property are passed atomically with the transfer of the digital token. 

The following section specifies the technological components required to meet these three objectives. 

### operatingAgreementHashOf

An immutable hash of the legal document issued by the legal entity that owns the property. The agreement is unique and contains the rights, terms, and conditions for the specific property represented by the NFT. The hash of the agreement attached to the NFT must be immutable to ensure the legitimacy and enforceability of these rights in the future for integrators or transferees. Upon transfer of the NFT, these legal rights are immediately enforceable by the new owner. For changes to the legal structure or rights and conditions with regard to the property the original token must be burned and a new token with the new hash must be minted. 

### Property Unique Identifiers

The following unique identifiers of the property are contained within the NFT and are immutable:

`legalDescriptionOf`: written description of the property taken from the physical property deed
`addressOf`: street address of the property
`geoJsonOf`: the GeoJSON format of the property’s geospatial coordinates
`parcelIdOf`: ID number used to identify the property by the local authority
`legalOwnerOf`: the legal entity that is named on the verifiable physical deed

These unique identifiers ensure the physical property in question is clear and identifiable. These strings must be immutable to make certain that the identity of the property can not be changed in the future. This is necessary to provide confidence in the NFT holder in the event a dispute about the property arises. 

These identifiers, especially `legalOwnerOf`, allow for individuals to verify off-chain ownership and legitimacy of the legal agreement. These verification checks could be integrated with something like Chainlink functions in the future to be simplified and automatic. 

### debtOf

A readable value of debt and denoted currency that is accrued to the property. A positive balance signifies a debt against the property, while a negative balance signifies a credit which can be claimed by the NFT owner. This is a way for the property administrator to charge the NFT holder for any necessary payments towards the property, like property tax, or other critical repairs or maintenance in the &quot;real world&quot;. A credit might be given to the NFT holder via this same function, perhaps the administrator and the NFT holder had worked out a property management or tenancy revenue-sharing agreement.

The `debtOf` function also returns the boolean foreclosure status of the asset represented by the NFT. A true result indicates the associated property is no longer backing the NFT, a false result indicates the associated property is still backing the NFT. An administrator can foreclose an asset for any reason as specified in the `Operating Agreement`, an example would be excessive unpaid debts. Smart contracts can check the foreclosure state by calling this function. If the asset is foreclosed, it should be understood that the RWA backing the NFT has been removed, and smart contracts should take this into account when doing any valuations or other calculations.

There are no standard requirements for how these values are updated as those details will be decided by the implementor. This EIP does however standardize how these values are indicated and read for simplicity of integration. 

### managerOf 

A readable Ethereum address that can be granted a right to action on the property without being the underlying owner of the NFT. 

This function allows the token to be owned by one Ethereum address while granting particular rights to another. This enables protocols and smart contracts to own the underlying asset, such as a lending protocol, but still allow another Ethereum address, such as a depositor, to action on the NFT via other integrations, for example the Administrator management portal. The standard does not require a specific implementation of the manager role, only the value is required. In many instances the managerOf value will be the same as the owning address of the NFT. 

## Backwards Compatibility

This EIP is backwards compatible with ERC-721. However, it is important to note that there are potential implementation considerations to take into account before any smart contract integration. See [Security Considerations](#security-considerations) for more details.

## Reference Implementation

Klasma Labs offers a work in progress [reference implementation](/EIPs/assets/eip-6065/Implementation.sol). The technical implementation includes the following additional components for reference, this implementation is not required.

Summary of this implementation:

* NFT burn and mint function
* Immutable NFT data (unique identifiers and operating agreement hash)
* Simple debt tracking by Administrator
* Blocklist function to freeze asset held by fraudulent addresses (NOTE: to be implemented in the future)
* Simple foreclosure logic initiated by Administrator
* `managerOf` function implementation to chain this call to other supported smart contracts

### Legal Structure Implementation

This section explains the legal structure and implementation a company may employ as an Administrator of this token. The structure detailed below is specific to property tokenization in the U.S. in the 2023 regulatory environment.

This section details an implementation of the legal standard that could be used by a company specifically for property tokenization in the U.S. in the 2022 regulatory environment.

![Corporate Structure Image](/EIPs/assets/eip-6065/corporate-structure.png)


The legal structure for this token is as follows:

* A parent company and property Administrator, owns a bankruptcy remote LLC for each individual property they act as Administrator for.
* The bankruptcy remote LLC is the owner and manager of a DAO LLC. The DAO LLC is on the title and deed and issues the corresponding NFT and operating agreement for the property.
* This structure enables the following three outcomes:

    1. Homeowners are shielded from any financial stress or bankruptcy their physical asset Administrator encounters. In the event of an Administrator bankruptcy or dissolution the owner of the NFT is entitled to transfer of the DAO LLC, or the sale and distribution of proceeds from the property.
    2. Transfer of the rights to the property are atomic with the transfer of the NFT. The NFT represents a right to claim the asset and have the title transferred to the NFT owner, as well as the right to use the asset. This ensures the rights to the physical property are passed digitally with the transfer of the NFT, without having to update the legal owner of the property after each transfer.

Security note: In the event of a private key hack the company will likely not be able to reissue a Home NFT. Home NFT owners who are not confident in their ability to safely store their home NFT will have varying levels of security options (multi-sigs, custodians, etc.). For public, large protocol hacks, the company may freeze the assets using the Blocklist function and reissue the home NFTs to the original owners. Blocklist functionality is to-be-implemented in the reference implementation above.

## Security Considerations

The following are checks and recommendations for protocols integrating NFTs under this standard. These are of particular relevance to applications which lend against any asset utilizing this standard.

* Protocol integrators are recommended to check that the unique identifiers for the property and the hash of the operating agreement are immutable for the specific NFTs they wish to integrate. For correct implementation of this standard these values must be immutable to ensure legitimacy for future transferees. 
* Protocol integrators are recommended to check the debtOf value for an accurate representation of the value of this token.
* Protocol integrators are recommended to check the foreclose status to ensure this token is still backed by the asset it was originally tied to.
* For extra risk mitigation protocol integrators can implement a time-delay before performing irreversible actions. This is to protect against potential asset freezes if a hacked NFT is deposited into the protocol. Asset freezes are non-mandatory and subject to the implementation of the asset Administrator. 

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 29 Nov 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6065</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6065</guid>
      </item>
    
      <item>
        <title>Signature Validation Method for NFTs</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6066-signature-validation-method-for-nfts/11943</comments>
        
        <description>## Abstract

While **E**xternally **O**wned **A**ccounts can validate signed messages with `ecrecover()` and smart contracts can validate signatures using specifications outlined in [ERC-1271](/EIPs/EIPS/eip-1271), currently there is no standard method to create or validate signatures made by NFTs. We propose a standard way for anyone to validate whether a signature made by an NFT is valid. This is possible via a modified signature validation function originally found in [ERC-1271](/EIPs/EIPS/eip-1271): `isValidSignature(tokenId, hash, data)`.

## Motivation

With billions of ETH in trading volume, the **N**on-**F**ungible **T**oken standard has exploded into tremendous popularity in recent years. Despite the far-reaching implications of having unique tokenized items on-chain, NFTs have mainly been used to represent artwork in the form of avatars or profile pictures. While this is certainly not a trivial use case for the [ERC-721](/EIPs/EIPS/eip-721) &amp; [ERC-1155](/EIPs/EIPS/eip-1155) token standards, we reckon more can be done to aid the community in discovering alternative uses for NFTs.

One of the alternative use cases for NFTs is using them to represent offices in an organization. In this case, tying signatures to transferrable NFTs instead of EOAs or smart contracts becomes crucial. Suppose there exists a DAO that utilizes NFTs as badges that represent certain administrative offices (i.e., CEO, COO, CFO, etc.) with a quarterly democratic election that potentially replaces those who currently occupy said offices. If the sitting COO has previously signed agreements or authorized certain actions, their past signatures would stay with the EOA who used to be the COO instead of the COO&apos;s office itself once they are replaced with another EOA as the new COO-elect. Although a multisig wallet for the entire DAO is one way to mitigate this problem, often it is helpful to generate signatures on a more intricate level so detailed separation of responsibilities are established and maintained. It is also feasible to appoint a smart contract instead of an EOA as the COO, but the complexities this solution brings are unnecessary. If a DAO uses ENS to establish their organizational hierarchy, this proposal would allow wrapped ENS subdomains (which are NFTs) to generate signatures.

## Specification

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.

```
pragma solidity ^0.8.0;

interface IERC6066 {
    /**
     * @dev MUST return if the signature provided is valid for the provided tokenId and hash
     * @param tokenId   Token ID of the signing NFT
     * @param hash      Hash of the data to be signed
     * @param data      OPTIONAL arbitrary data that may aid verification
     *
     * MUST return the bytes4 magic value 0x12edb34f when function passes.
     * MUST NOT modify state (using STATICCALL for solc &lt; 0.5, view modifier for solc &gt; 0.5)
     * MUST allow external calls
     *
     */
    function isValidSignature(
        uint256 tokenId,
        bytes32 hash,
        bytes calldata data
    ) external view returns (bytes4 magicValue);
}
```

`isValidSignature` can call arbitrary methods to validate a given signature.

This function MAY be implemented by [ERC-721](/EIPs/EIPS/eip-721) or [ERC-1155](/EIPs/EIPS/eip-1155) compliant contracts that desire to enable its token holders to sign messages using their NFTs. Compliant callers wanting to support contract signatures MUST call this method if the signer is the holder of an NFT ([ERC-721](/EIPs/EIPS/eip-721) or [ERC-1155](/EIPs/EIPS/eip-1155)).

## Rationale

We have purposefully decided to not include a signature generation standard in this proposal as it would restrict flexibility of such mechanism, just as [ERC-1271](/EIPs/EIPS/eip-1271) does not enforce a signing standard for smart contracts. We also decided to reference Gnosis Safe&apos;s contract signing approach as it is both simplistic and proven to be adequate. The `bytes calldata data` parameter is considered optional if extra data is needed for signature verification, also conforming this EIP to [ERC-5750](/EIPs/EIPS/eip-5750) for future-proofing purposes.

## Backwards Compatibility

This EIP is incompatible with previous work on signature validation as it does not validate any cryptographically generated signatures. Instead, signature is merely a boolean flag indicating consent. This is consistent with Gnosis Safe&apos;s contract signature implementation.

## Reference Implementation

Example implementation of an [ERC-721](/EIPs/EIPS/eip-721) compliant contract that conforms to [ERC-6066](/EIPs/EIPS/eip-6066) with a custom signing function:

```
pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;
import &quot;./interfaces/IERC6066.sol&quot;;

contract ERC6066Reference is ERC721, IERC6066 {
    // type(IERC6066).interfaceId
    bytes4 public constant MAGICVALUE = 0x12edb34f;
    bytes4 public constant BADVALUE = 0xffffffff;

    mapping(uint256 =&gt; mapping(bytes32 =&gt; bool)) internal _signatures;

    error ENotTokenOwner();

    /**
     * @dev Checks if the sender owns NFT with ID tokenId
     * @param tokenId   Token ID of the signing NFT
     */
    modifier onlyTokenOwner(uint256 tokenId) {
        if (ownerOf(tokenId) != _msgSender()) revert ENotTokenOwner();
        _;
    }

    constructor(string memory name_, string memory symbol_)
        ERC721(name_, symbol_)
    {}

    /**
     * @dev SHOULD sign the provided hash with NFT of tokenId given sender owns said NFT
     * @param tokenId   Token ID of the signing NFT
     * @param hash      Hash of the data to be signed
     */
    function sign(uint256 tokenId, bytes32 hash)
        external
        onlyTokenOwner(tokenId)
    {
        _signatures[tokenId][hash] = true;
    }

    /**
     * @dev MUST return if the signature provided is valid for the provided tokenId, hash, and optionally data
     */
    function isValidSignature(uint256 tokenId, bytes32 hash, bytes calldata data)
        external
        view
        override
        returns (bytes4 magicValue)
    {
        // The data parameter is unused in this example
        return _signatures[tokenId][hash] ? MAGICVALUE : BADVALUE;
    }

    /**
     * @dev ERC-165 support
     */
    function supportsInterface(
        bytes4 interfaceId
    ) public view virtual override returns (bool) {
        return
            interfaceId == type(IERC6066).interfaceId ||
            super.supportsInterface(interfaceId);
    }
}
```

## Security Considerations

The revokable nature of contract-based signatures carries over to this EIP. Developers and users alike should take it into consideration.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 29 Nov 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6066</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6066</guid>
      </item>
    
      <item>
        <title>Custom errors for commonly-used tokens</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6093-custom-errors-for-erc-tokens/12043</comments>
        
        <description>## Abstract

This EIP defines a standard set of custom errors for commonly-used tokens, which are defined as [ERC-20](/EIPs/EIPS/eip-20), [ERC-721](/EIPs/EIPS/eip-721), and [ERC-1155](/EIPs/EIPS/eip-1155) tokens.

Ethereum applications and wallets have historically relied on revert reason strings to display the cause of transaction errors to users. Recent Solidity versions offer rich revert reasons with error-specific decoding (sometimes called &quot;custom errors&quot;). This EIP defines a standard set of errors designed to give at least the same relevant information as revert reason strings, but in a structured and expected way that clients can implement decoding for.

## Motivation

Since the introduction of Solidity custom errors in v0.8.4, these have provided a way to show failures in a more expressive and gas efficient manner with dynamic arguments, while reducing deployment costs.

However, [ERC-20](/EIPs/EIPS/eip-20), [ERC-721](/EIPs/EIPS/eip-721), [ERC-1155](/EIPs/EIPS/eip-1155) were already finalized when custom errors were released, so no errors are included in their specification.

Standardized errors allow users to expect more consistent error messages across applications or testing environments, while exposing pertinent arguments and overall reducing the need of writing expensive revert strings in the deployment bytecode.

## Specification

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

The following errors were designed according to the criteria described in [Rationale](#rationale).

This EIP defines standard errors that may be used by implementations in certain scenarios but it does not specify whether implementations should revert in those scenarios, which remains up to the implementers unless a revert is mandated by the corresponding EIPs.

The names of the error arguments are defined in the [Parameter Glossary](#parameter-glossary) and MUST be used according to those definitions.

### [ERC-20](/EIPs/EIPS/eip-20)

#### `ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed)`

Indicates an error related to the current `balance` of a `sender`.
Used in transfers.

Usage guidelines:

- `balance` MUST be less than `needed`.

#### `ERC20InvalidSender(address sender)`

Indicates a failure with the token `sender`.
Used in transfers.

Usage guidelines:

- RECOMMENDED for disallowed transfers from the zero address.
- MUST NOT be used for approval operations.
- MUST NOT be used for balance or allowance requirements.
  - Use `ERC20InsufficientBalance` or `ERC20InsufficientAllowance` instead.

#### `ERC20InvalidReceiver(address receiver)`

Indicates a failure with the token `receiver`.
Used in transfers.

Usage guidelines:

- RECOMMENDED for disallowed transfers to the zero address.
- RECOMMENDED for disallowed transfers to non-compatible addresses (eg. contract addresses).
- MUST NOT be used for approval operations.

#### `ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed)`

Indicates a failure with the `spender`&apos;s `allowance`.
Used in transfers.

Usage guidelines:

- `allowance` MUST be less than `needed`.

#### `ERC20InvalidApprover(address approver)`

Indicates a failure with the `approver` of a token to be approved.
Used in approvals.

Usage guidelines:

- RECOMMENDED for disallowed approvals from the zero address.
- MUST NOT be used for transfer operations.

#### `ERC20InvalidSpender(address spender)`

Indicates a failure with the `spender` to be approved.
Used in approvals.

Usage guidelines:

- RECOMMENDED for disallowed approvals to the zero address.
- RECOMMENDED for disallowed approvals to the owner itself.
- MUST NOT be used for transfer operations.
  - Use `ERC20InsufficientAllowance` instead.

### [ERC-721](/EIPs/EIPS/eip-721)

#### `ERC721InvalidOwner(address owner)`

Indicates that an address can&apos;t be an owner.
Used in balance queries.

Usage guidelines:

- RECOMMENDED for addresses whose ownership is disallowed (eg. ERC-721 explicitly disallows `address(0)` to be an owner).
- MUST NOT be used for transfers.
  - Use `ERC721IncorrectOwner` instead.

#### `ERC721NonexistentToken(uint256 tokenId)`

Indicates a `tokenId` whose `owner` is the zero address.

Usage guidelines:

- The `tokenId` MUST BE a non-minted or burned token.

#### `ERC721IncorrectOwner(address sender, uint256 tokenId, address owner)`

Indicates an error related to the ownership over a particular token.
Used in transfers.

Usage guidelines:

- `sender` MUST NOT be `owner`.
- MUST NOT be used for approval operations.

#### `ERC721InvalidSender(address sender)`

Indicates a failure with the token `sender`.
Used in transfers.

Usage guidelines:

- RECOMMENDED for disallowed transfers from the zero address.
- MUST NOT be used for approval operations.
- MUST NOT be used for ownership or approval requirements.
  - Use `ERC721IncorrectOwner` or `ERC721InsufficientApproval` instead.

#### `ERC721InvalidReceiver(address receiver)`

Indicates a failure with the token `receiver`.
Used in transfers.

Usage guidelines:

- RECOMMENDED for disallowed transfers to the zero address.
- RECOMMENDED for disallowed transfers to non-`ERC721TokenReceiver` contracts or those that reject a transfer. (eg. returning an invalid response in `onERC721Received`).
- MUST NOT be used for approval operations.

#### `ERC721InsufficientApproval(address operator, uint256 tokenId)`

Indicates a failure with the `operator`&apos;s approval.
Used in transfers.

Usage guidelines:

- `isApprovedForAll(owner, operator)` MUST be false for the `tokenId`&apos;s owner and `operator`.
- `getApproved(tokenId)` MUST not be `operator`.

#### `ERC721InvalidApprover(address approver)`

Indicates a failure with the `owner` of a token to be approved.
Used in approvals.

Usage guidelines:

- RECOMMENDED for disallowed approvals from the zero address.
- MUST NOT be used for transfer operations.

#### `ERC721InvalidOperator(address operator)`

Indicates a failure with the `operator` to be approved.
Used in approvals.

Usage guidelines:

- RECOMMENDED for disallowed approvals to the zero address.
- The `operator` MUST NOT be the owner of the approved token.
- MUST NOT be used for transfer operations.
  - Use `ERC721InsufficientApproval` instead.

### [ERC-1155](/EIPs/EIPS/eip-1155)

#### `ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId)`

Indicates an error related to the current `balance` of a `sender`.
Used in transfers.

Usage guidelines:

- `balance` MUST be less than `needed` for a `tokenId`.

#### `ERC1155InvalidSender(address sender)`

Indicates a failure with the token `sender`.
Used in transfers.

Usage guidelines:

- RECOMMENDED for disallowed transfers from the zero address.
- MUST NOT be used for approval operations.
- MUST NOT be used for balance or allowance requirements.
  - Use `ERC1155InsufficientBalance` or `ERC1155MissingApprovalForAll` instead.

#### `ERC1155InvalidReceiver(address receiver)`

Indicates a failure with the token `receiver`.
Used in transfers.

Usage guidelines:

- RECOMMENDED for disallowed transfers to the zero address.
- RECOMMENDED for disallowed transfers to non-`ERC1155TokenReceiver` contracts or those that reject a transfer. (eg. returning an invalid response in `onERC1155Received`).
- MUST NOT be used for approval operations.

#### `ERC1155MissingApprovalForAll(address operator, address owner)`

Indicates a failure with the `operator`&apos;s approval in a transfer.
Used in transfers.

Usage guidelines:

- `isApprovedForAll(owner, operator)` MUST be false for the `tokenId`&apos;s owner and `operator`.

#### `ERC1155InvalidApprover(address approver)`

Indicates a failure with the `approver` of a token to be approved.
Used in approvals.

Usage guidelines:

- RECOMMENDED for disallowed approvals from the zero address.
- MUST NOT be used for transfer operations.

#### `ERC1155InvalidOperator(address operator)`

Indicates a failure with the `operator` to be approved.
Used in approvals.

Usage guidelines:

- RECOMMENDED for disallowed approvals to the zero address.
- MUST be used for disallowed approvals to the owner itself.
- MUST NOT be used for transfer operations.
  - Use `ERC1155InsufficientApproval` instead.

#### `ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength)`

Indicates an array length mismatch between `ids` and `values` in a `safeBatchTransferFrom` operation.
Used in batch transfers.

Usage guidelines:

- `idsLength` MUST NOT be `valuesLength`.

### Parameter Glossary

| Name        | Description                                                                 |
| ----------- | --------------------------------------------------------------------------- |
| `sender`    | Address whose tokens are being transferred.                                 |
| `balance`   | Current balance for the interacting account.                                |
| `needed`    | Minimum amount required to perform an action.                               |
| `receiver`  | Address to which tokens are being transferred.                              |
| `spender`   | Address that may be allowed to operate on tokens without being their owner. |
| `allowance` | Amount of tokens a `spender` is allowed to operate with.                    |
| `approver`  | Address initiating an approval operation.                                   |
| `tokenId`   | Identifier number of a token.                                               |
| `owner`     | Address of the current owner of a token.                                    |
| `operator`  | Same as `spender`.                                                          |
| `*Length`   | Array length for the prefixed parameter.                                    |

### Error additions

Any addition to this EIP or implementation-specific errors (such as extensions) SHOULD follow the guidelines presented in the [rationale](#rationale) section to keep consistency.

## Rationale

The chosen objectives for a standard for token errors are to provide context about the error, and to make moderate use of meaningful arguments (to maintain the code size benefits with respect to strings).

Considering this, the error names are designed following a basic grammatical structure based on the standard actions that can be performed on each token and the [subjects](#actions-and-subjects) involved.

### Actions and subjects

An error is defined based on the following **actions** that can be performed on a token and its involved _subjects_:

- **Transfer**: An operation in which a _sender_ moves to a _receiver_ any number of tokens (fungible _balance_ and/or non-fungible _token ids_).
- **Approval**: An operation in which an _approver_ grants any form of _approval_ to an _operator_.

These attempt to exhaustively represent what can go wrong in a token operation. Therefore, the errors can be constructed by specifying which _subject_ failed during an **action** execution, and prefixing with an [error prefix](#error-prefixes).

Note that the action is never seen as the subject of an error.

If a subject is called different on a particular token standard, the error should be consistent with the standard&apos;s naming convention.

### Error prefixes

An error prefix is added to a subject to derive a concrete error condition.
Developers can think about an error prefix as the _why_ an error happened.

A prefix can be `Invalid` for general incorrectness, or more specific like `Insufficient` for amounts.

### Domain

Each error&apos;s arguments may vary depending on the token domain. If there are errors with the same name and different arguments, the Solidity compiler currently fails with a `DeclarationError`.

An example of this is:

```solidity
InsufficientApproval(address spender, uint256 allowance, uint256 needed);
InsufficientApproval(address operator, uint256 tokenId);
```

For that reason, a domain prefix is proposed to avoid declaration clashing, which is the name of the ERC and its corresponding number appended at the beginning.

Example:

```solidity
ERC20InsufficientApproval(address spender, uint256 allowance, uint256 needed);
ERC721InsufficientApproval(address operator, uint256 tokenId);
```

### Arguments

The selection of arguments depends on the subject involved, and it should follow the order presented below:

1. _Who_ is involved with the error (eg. `address sender`)
2. _What_ failed (eg. `uint256 allowance`)
3. _Why_ it failed, expressed in additional arguments (eg. `uint256 needed`)

A particular argument may fall into overlapping categories (eg. _Who_ may also be _What_), so not all of these will be present but the order shouldn&apos;t be broken.

Some tokens may need a `tokenId`. This is suggested to include at the end as additional information instead of as a subject.

### Error grammar rules

Given the above, we can summarize the construction of error names with a grammar that errors will follow:

```
&lt;Domain&gt;&lt;ErrorPrefix&gt;&lt;Subject&gt;(&lt;Arguments&gt;);
```

Where:

- _Domain_: `ERC20`, `ERC721` or `ERC1155`. Although other token standards may be suggested if not considered in this EIP.
- _ErrorPrefix_: `Invalid`, `Insufficient`, or another if it&apos;s more appropriate.
- _Subject_: `Sender`, `Receiver`, `Balance`, `Approver`, `Operator`, `Approval` or another if it&apos;s more appropriate, and must make adjustments based on the domain&apos;s naming convention.
- _Arguments_: Follow the [_who_, _what_ and _why_ order](#arguments).

## Backwards Compatibility

Tokens already deployed rely mostly on revert strings and make use of `require` instead of custom errors. Even most of the newly deployed tokens since Solidity&apos;s v0.8.4 release inherit from implementations using revert strings.

This EIP can not be enforced on non-upgradeable already deployed tokens, however, these tokens generally use similar conventions with small variations such as:

- including/removing the [domain](#domain).
- using different [error prefixes](#error-prefixes).
- including similar [subjects](#actions-and-subjects).
- changing the grammar order.

Upgradeable contracts MAY be upgraded to implement this EIP.

Implementers and DApp developers that implement special support for tokens that are compliant with this EIP, SHOULD tolerate different errors emitted by non-compliant contracts, as well as classic revert strings.

## Reference Implementation

### Solidity

```solidity
pragma solidity ^0.8.4;

/// @title Standard ERC20 Errors
/// @dev See https://eips.ethereum.org/EIPS/eip-20
///  https://eips.ethereum.org/EIPS/eip-6093
interface ERC20Errors {
    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
    error ERC20InvalidSender(address sender);
    error ERC20InvalidReceiver(address receiver);
    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
    error ERC20InvalidApprover(address approver);
    error ERC20InvalidSpender(address spender);
}

/// @title Standard ERC721 Errors
/// @dev See https://eips.ethereum.org/EIPS/eip-721
///  https://eips.ethereum.org/EIPS/eip-6093
interface ERC721Errors {
    error ERC721InvalidOwner(address owner);
    error ERC721NonexistentToken(uint256 tokenId);
    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
    error ERC721InvalidSender(address sender);
    error ERC721InvalidReceiver(address receiver);
    error ERC721InsufficientApproval(address operator, uint256 tokenId);
    error ERC721InvalidApprover(address approver);
    error ERC721InvalidOperator(address operator);
}

/// @title Standard ERC1155 Errors
/// @dev See https://eips.ethereum.org/EIPS/eip-1155
///  https://eips.ethereum.org/EIPS/eip-6093
interface ERC1155Errors {
    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
    error ERC1155InvalidSender(address sender);
    error ERC1155InvalidReceiver(address receiver);
    error ERC1155MissingApprovalForAll(address operator, address owner)
    error ERC1155InvalidApprover(address approver);
    error ERC1155InvalidOperator(address operator);
    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}
```

## Security Considerations

There are no known signature hash collisions for the specified errors.

Tokens upgraded to implement this EIP may break assumptions in other systems relying on revert strings.

Offchain applications should be cautious when dealing with untrusted contracts that may revert using these custom errors. For instance, if a user interface prompts actions based on error decoding, malicious contracts could exploit this to encourage untrusted and potentially harmful operations.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 06 Dec 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6093</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6093</guid>
      </item>
    
      <item>
        <title>No Intermediary NFT Trading Protocol</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip6105-no-intermediary-nft-trading-protocol/12171</comments>
        
        <description>## Abstract

This ERC adds a marketplace functionality to [ERC-721](/EIPs/EIPS/eip-721) to enable non-fungible token trading without relying on an intermediary trading platform. At the same time, creators may implement more diverse royalty schemes.

## Motivation

Most current NFT trading relies on an NFT trading platform acting as an intermediary, which has the following problems:

1. Security concerns arise from authorization via the `setApprovalForAll` function. The permissions granted to NFT trading platforms expose unnecessary risks. Should a problem occur with the trading platform contract, it would result in significant losses to the industry as a whole. Additionally, if a user has authorized the trading platform to handle their NFTs, it allows a phishing scam to trick the user into signing a message that allows the scammer to place an order at a low price on the NFT trading platform and designate themselves as the recipient. This can be difficult for ordinary users to guard against.
2. High trading costs are a significant issue. On one hand, as the number of trading platforms increases, the liquidity of NFTs becomes dispersed. If a user needs to make a deal quickly, they must authorize and place orders on multiple platforms, which increases the risk exposure and requires additional gas expenditures for each authorization. For example, taking BAYC as an example, with a total supply of 10,000 and over 6,000 current holders, the average number of BAYC held by each holder is less than 2. While `setApprovalForAll` saves on gas expenditure for pending orders on a single platform, authorizing multiple platforms results in an overall increase in gas expenditures for users. On the other hand, trading service fees charged by trading platforms must also be considered as a cost of trading, which are often much higher than the required gas expenditures for authorization.
3. Aggregators provide a solution by aggregating liquidity, but the decision-making process is centralized. Furthermore, as order information on trading platforms is off-chain, the aggregator&apos;s efficiency in obtaining data is affected by the frequency of the trading platform&apos;s API and, at times, trading platforms may suspend the distribution of APIs and limit their frequency.
4. The project parties&apos; royalty income is dependent on centralized decision-making by NFT trading platforms. Some trading platforms implement optional royalty without the consent of project parties, which is a violation of their interests.
5. NFT trading platforms are not resistant to censorship. Some platforms have delisted a number of NFTs and the formulation and implementation of delisting rules are centralized and not transparent enough. In the past, some NFT trading platforms have failed and wrongly delisted certain NFTs, leading to market panic.

## Specification

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

Compliant contracts MUST implement the following interface:

```solidity
interface IERC6105 {

  /// @notice Emitted when a token is listed for sale or delisted
  /// @dev The zero `salePrice` indicates that the token is not for sale
  ///      The zero `expires` indicates that the token is not for sale
  /// @param tokenId - identifier of the token being listed
  /// @param from - address of who is selling the token
  /// @param salePrice - the price the token is being sold for
  /// @param expires - UNIX timestamp, the buyer could buy the token before expires
  /// @param supportedToken - contract addresses of supported token or zero address
  ///                         The zero address indicates that the supported token is ETH
  ///                         Buyer needs to purchase item with supported token
  /// @param benchmarkPrice - Additional price parameter, may be used when calculating royalties
  event UpdateListing(
    uint256 indexed tokenId,
    address indexed from,
    uint256 salePrice,
    uint64 expires,
    address supportedToken,
    uint256 benchmarkPrice
    );

  /// @notice Emitted when a token is being purchased
  /// @param tokenId - identifier of the token being purchased
  /// @param from - address of who is selling the token
  /// @param to - address of who is buying the token 
  /// @param salePrice - the price the token is being sold for
  /// @param supportedToken - contract addresses of supported token or zero address
  ///                         The zero address indicates that the supported token is ETH
  ///                         Buyer needs to purchase item with supported token
  /// @param royalties - The amount of royalties paid on this purchase
  event Purchased(
    uint256 indexed tokenId,
    address indexed from,
    address indexed to,
    uint256 salePrice,
    address supportedToken,
    uint256 royalties
    );

  /// @notice Create or update a listing for `tokenId`
  /// @dev `salePrice` MUST NOT be set to zero
  /// @param tokenId - identifier of the token being listed
  /// @param salePrice - the price the token is being sold for
  /// @param expires - UNIX timestamp, the buyer could buy the token before expires
  /// @param supportedToken - contract addresses of supported token or zero address
  ///                         The zero address indicates that the supported token is ETH
  ///                         Buyer needs to purchase item with supported token
  /// Requirements:
  /// - `tokenId` must exist
  /// - Caller must be owner, authorised operators or approved address of the token
  /// - `salePrice` must not be zero
  /// - `expires` must be valid
  /// - Must emit an {UpdateListing} event.
  function listItem(
    uint256 tokenId,
    uint256 salePrice,
    uint64 expires,
    address supportedToken
    ) external;

  /// @notice Create or update a listing for `tokenId` with `benchmarkPrice`
  /// @dev `salePrice` MUST NOT be set to zero
  /// @param tokenId - identifier of the token being listed
  /// @param salePrice - the price the token is being sold for
  /// @param expires - UNIX timestamp, the buyer could buy the token before expires
  /// @param supportedToken - contract addresses of supported token or zero address
  ///                         The zero address indicates that the supported token is ETH
  ///                         Buyer needs to purchase item with supported token
  /// @param benchmarkPrice - Additional price parameter, may be used when calculating royalties
  /// Requirements:
  /// - `tokenId` must exist
  /// - Caller must be owner, authorised operators or approved address of the token
  /// - `salePrice` must not be zero
  /// - `expires` must be valid
  /// - Must emit an {UpdateListing} event.
  function listItem(
    uint256 tokenId,
    uint256 salePrice,
    uint64 expires,
    address supportedToken,
    uint256 benchmarkPrice
    ) external;
 
  /// @notice Remove the listing for `tokenId`
  /// @param tokenId - identifier of the token being delisted
  /// Requirements:
  /// - `tokenId` must exist and be listed for sale
  /// - Caller must be owner, authorised operators or approved address of the token
  /// - Must emit an {UpdateListing} event
  function delistItem(uint256 tokenId) external;
 
  /// @notice Buy a token and transfer it to the caller
  /// @dev `salePrice` and `supportedToken` must match the expected purchase price and token to prevent front-running attacks
  /// @param tokenId - identifier of the token being purchased
  /// @param salePrice - the price the token is being sold for
  /// @param supportedToken - contract addresses of supported token or zero address
  /// Requirements:
  /// - `tokenId` must exist and be listed for sale
  /// - `salePrice` must matches the expected purchase price to prevent front-running attacks
  /// - `supportedToken` must matches the expected purchase token to prevent front-running attacks
  /// - Caller must be able to pay the listed price for `tokenId`
  /// - Must emit a {Purchased} event
  function buyItem(uint256 tokenId, uint256 salePrice, address supportedToken) external payable;

  /// @notice Return the listing for `tokenId`
  /// @dev The zero sale price indicates that the token is not for sale
  ///      The zero expires indicates that the token is not for sale
  ///      The zero supported token address indicates that the supported token is ETH
  /// @param tokenId identifier of the token being queried
  /// @return the specified listing (sale price, expires, supported token, benchmark price)
  function getListing(uint256 tokenId) external view returns (uint256, uint64, address, uint256);
}
```

### Optional collection offer extension

```solidity
/// The collection offer extension is OPTIONAL for ERC-6105 smart contracts. This allows smart contract to support collection offer functionality.
interface IERC6105CollectionOffer {

  /// @notice Emitted when the collection receives an offer or an offer is canceled
  /// @dev The zero `salePrice` indicates that the collection offer of the token is canceled
  ///      The zero `expires` indicates that the collection offer of the token is canceled
  /// @param from - address of who make collection offer
  /// @param amount - the amount the offerer wants to buy at `salePrice` per token
  /// @param salePrice - the price of each token is being offered for the collection
  /// @param expires - UNIX timestamp, the offer could be accepted before expires
  /// @param supportedToken - contract addresses of supported ERC20 token
  ///                          Buyer wants to purchase items with supported token
  event UpdateCollectionOffer(address indexed from, uint256 amount, uint256 salePrice ,uint64 expires, address supportedToken);

  /// @notice Create or update an offer for the collection
  /// @dev `salePrice` MUST NOT be set to zero
  /// @param amount - the amount the offerer wants to buy at `salePrice` per token
  /// @param salePrice - the price of each token is being offered for the collection
  /// @param expires - UNIX timestamp, the offer could be accepted before expires
  /// @param supportedToken - contract addresses of supported token
  ///                         Buyer wants to purchase items with supported token
  /// Requirements:
  /// - The caller must have enough supported tokens, and has approved the contract a sufficient amount
  /// - `salePrice` must not be zero
  /// - `amount` must not be zero
  /// - `expires` must be valid
  /// - Must emit an {UpdateCollectionOffer} event
  function makeCollectionOffer(uint256 amount, uint256 salePrice, uint64 expires, address supportedToken) external;

  /// @notice Accepts collection offer and transfers the token to the buyer
  /// @dev `salePrice` and `supportedToken` must match the expected purchase price and token to prevent front-running attacks
  ///      When the trading is completed, the `amount` of NFTs the buyer wants to purchase needs to be reduced by 1
  /// @param tokenId - identifier of the token being offered
  /// @param salePrice - the price the token is being offered for
  /// @param supportedToken - contract addresses of supported token
  /// @param buyer - address of who wants to buy the token
  /// Requirements:
  /// - `tokenId` must exist and be offered for
  /// - Caller must be owner, authorised operators or approved address of the token
  /// - Must emit a {Purchased} event
  function acceptCollectionOffer(uint256 tokenId, uint256 salePrice, address supportedToken, address buyer) external;

  /// @notice Accepts collection offer and transfers the token to the buyer
  /// @dev `salePrice` and `supportedToken` must match the expected purchase price and token to prevent front-running attacks
  ///      When the trading is completed, the `amount` of NFTs the buyer wants to purchase needs to be reduced by 1
  /// @param tokenId - identifier of the token being offered
  /// @param salePrice - the price the token is being offered for
  /// @param supportedToken - contract addresses of supported token
  /// @param buyer - address of who wants to buy the token
  /// @param benchmarkPrice - additional price parameter, may be used when calculating royalties
  /// Requirements:
  /// - `tokenId` must exist and be offered for
  /// - Caller must be owner, authorised operators or approved address of the token
  /// - Must emit a {Purchased} event
  function acceptCollectionOffer(uint256 tokenId, uint256 salePrice, address supportedToken, address buyer, uint256 benchmarkPrice) external;

  /// @notice Removes the offer for the collection
  /// Requirements:
  /// - Caller must be the offerer
  /// - Must emit an {UpdateCollectionOffer} event
  function cancelCollectionOffer() external;

  /// @notice Returns the offer for `tokenId` maked by `buyer`
  /// @dev The zero amount indicates there is no offer
  ///      The zero sale price indicates there is no offer
  ///      The zero expires indicates that there is no offer
  /// @param buyer address of who wants to buy the token
  /// @return the specified offer (amount, sale price, expires, supported token)
  function getCollectionOffer(address buyer) external view returns (uint256, uint256, uint64, address);
}
```

### Optional item offer extension

```solidity
/// The item offer extension is OPTIONAL for ERC-6105 smart contracts. This allows smart contract to support item offer functionality.
interface IERC6105ItemOffer {

  /// @notice Emitted when a token receives an offer or an offer is canceled
  /// @dev The zero `salePrice` indicates that the offer of the token is canceled
  ///      The zero `expires` indicates that the offer of the token is canceled
  /// @param tokenId - identifier of the token being offered
  /// @param from - address of who wants to buy the token
  /// @param salePrice - the price the token is being offered for
  /// @param expires - UNIX timestamp, the offer could be accepted before expires
  /// @param supportedToken - contract addresses of supported token
  ///                          Buyer wants to purchase item with supported token
  event UpdateItemOffer(
    uint256 indexed tokenId,
    address indexed from,
    uint256 salePrice,
    uint64 expires,
    address supportedToken
    );

  /// @notice Create or update an offer for `tokenId`
  /// @dev `salePrice` MUST NOT be set to zero
  /// @param tokenId - identifier of the token being offered
  /// @param salePrice - the price the token is being offered for
  /// @param expires - UNIX timestamp, the offer could be accepted before expires
  /// @param supportedToken - contract addresses of supported token
  ///                         Buyer wants to purchase item with supported token
  /// Requirements:
  /// - `tokenId` must exist
  /// - The caller must have enough supported tokens, and has approved the contract a sufficient amount
  /// - `salePrice` must not be zero
  /// - `expires` must be valid
  /// - Must emit an {UpdateItemOffer} event.
  function makeItemOffer(uint256 tokenId, uint256 salePrice, uint64 expires, address supportedToken) external;

  /// @notice Remove the offer for `tokenId`
  /// @param tokenId - identifier of the token being canceled offer
  /// Requirements:
  /// - `tokenId` must exist and be offered for
  /// - Caller must be the offerer
  /// - Must emit an {UpdateItemOffer} event
  function cancelItemOffer(uint256 tokenId) external;

  /// @notice Accept offer and transfer the token to the buyer
  /// @dev `salePrice` and `supportedToken` must match the expected purchase price and token to prevent front-running attacks
  ///      When the trading is completed, the offer infomation needs to be removed
  /// @param tokenId - identifier of the token being offered
  /// @param salePrice - the price the token is being offered for
  /// @param supportedToken - contract addresses of supported token
  /// @param buyer - address of who wants to buy the token
  /// Requirements:
  /// - `tokenId` must exist and be offered for
  /// - Caller must be owner, authorised operators or approved address of the token
  /// - Must emit a {Purchased} event
  function acceptItemOffer(uint256 tokenId, uint256 salePrice, address supportedToken, address buyer) external;

  /// @notice Accepts offer and transfers the token to the buyer
  /// @dev `salePrice` and `supportedToken` must match the expected purchase price and token to prevent front-running attacks
  ///      When the trading is completed, the offer infomation needs to be removed
  /// @param tokenId - identifier of the token being offered
  /// @param salePrice - the price the token is being offered for
  /// @param supportedToken - contract addresses of supported token
  /// @param buyer - address of who wants to buy the token
  /// @param benchmarkPrice - additional price parameter, may be used when calculating royalties
  /// Requirements:
  /// - `tokenId` must exist and be offered for
  /// - Caller must be owner, authorised operators or approved address of the token
  /// - Must emit a {Purchased} event
  function acceptItemOffer(uint256 tokenId, uint256 salePrice, address supportedToken, address buyer, uint256 benchmarkPrice) external;

  /// @notice Return the offer for `tokenId` maked by `buyer`
  /// @dev The zero sale price indicates there is no offer
  ///      The zero expires indicates that there is no offer
  /// @param tokenId identifier of the token being queried
  /// @param buyer address of who wants to buy the token
  /// @return the specified offer (sale price, expires, supported token)
  function getItemOffer(uint256 tokenId, address buyer) external view returns (uint256, uint64, address);
}
```

## Rationale

### Considerations for some local variables

The `salePrice` in the `listItem` function cannot be set to zero. Firstly, it is a rare occurrence for a caller to set the price to 0, and when it happens, it is often due to an operational error which can result in loss of assets. Secondly, a caller needs to spend gas to call this function, so if he can set the token price to 0, his income would be actually negative at this time, which does not conform to the concept of &apos;economic man&apos; in economics. Additionally, a token price of 0 indicates that the item is not for sale, making the reference implementation more concise.

Setting `expires` in the `listItem` function allows callers to better manage their listings. If a listing expires automatically, the token owner will no longer need to manually `delistItem`, thus saving gas.

Setting `supportedToken` in the `listItem` function allows the caller or contract owner to choose which tokens they want to accept, rather than being limited to a single token.

The rationales of variable setting in the `acceptCollectionOffer` and `acceptItemOffer` functions are the same as described above.

### More diverse royalty schemes

By introducing the parameter `benchmarkPrice` in the `listItem`, `acceptCollectionOffer` and `acceptItemOffer` functions, the `_salePrice` in the `royaltyInfo(uint256 _tokenId, uint256 _salePrice)` function in the [ERC-2981](/EIPs/EIPS/eip-2981) interface can be changed to `taxablePrice`, making the ERC-2981 royalty scheme more diverse. Here are several examples of royalty schemes:

`(address royaltyRecipient, uint256 royalties) = royaltyInfo(tokenId, taxablePrice)`

1. Value-added Royalty (VAR, royalties are only charged on the part of the seller&apos;s profit）: `taxablePrice=max(salePrice- historicalPrice, 0)`
2. Sale Royalty (SR): `taxablePrice=salePrice`
3. Capped Royalty(CR): `taxablePrice=min(salePrice, constant)`
4. Quantitative Royalty(QR, each token trading pays a fixed royalties): `taxablePrice= constant`

### Optional Blocklist

Some viewpoints suggest that tokens should be prevented from trading on intermediary markets that do not comply with royalty schemes, but this standard only provides a functionality for non-intermediary NFT trading and does not offer a standardized interface to prevent tokens from trading on these markets. If deemed necessary to better protect the interests of the project team and community, they may consider adding a blocklist to their implementation contracts to prevent NFTs from being traded on platforms that do not comply with the project’s royalty scheme.

## Backwards Compatibility

This standard is compatible with [ERC-721](/EIPs/EIPS/eip-721) and [ERC-2981](/EIPs/EIPS/eip-2981).

## Reference Implementation

```solidity
 // SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.8;
import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;
import &quot;@openzeppelin/contracts/token/common/ERC2981.sol&quot;;
import &quot;@openzeppelin/contracts/token/ERC20/IERC20.sol&quot;;
import &quot;@openzeppelin/contracts/security/ReentrancyGuard.sol&quot;;
import &quot;./IERC6105.sol&quot;;

/// @title No Intermediary NFT Trading Protocol with Value-added Royalty
/// @dev The royalty scheme used by this reference implementation is Value-Added Royalty
contract ERC6105 is ERC721, ERC2981, IERC6105, ReentrancyGuard{

  /// @dev A structure representing a listed token
  ///      The zero `salePrice` indicates that the token is not for sale
  ///      The zero `expires` indicates that the token is not for sale
  /// @param salePrice - the price the token is being sold for
  /// @param expires - UNIX timestamp, the buyer could buy the token before expires
  /// @param supportedToken - contract addresses of supported ERC20 token or zero address
  ///                         The zero address indicates that the supported token is ETH
  ///                         Buyer needs to purchase item with supported token
  /// @param historicalPrice - The price at which the seller last bought this token
  struct Listing {
    uint256 salePrice;
    uint64 expires;
    address supportedToken;
    uint256 historicalPrice;
  }

  // Mapping from token Id to listing index
  mapping(uint256 =&gt; Listing) private _listings;

  constructor(string memory name_, string memory symbol_)
    ERC721(name_, symbol_)
    {
    }

  /// @notice Create or update a listing for `tokenId`
  /// @dev `salePrice` MUST NOT be set to zero
  /// @param tokenId - identifier of the token being listed
  /// @param salePrice - the price the token is being sold for
  /// @param expires - UNIX timestamp, the buyer could buy the token before expires
  /// @param supportedToken - contract addresses of supported ERC20 token or zero address
  ///                         The zero address indicates that the supported token is ETH
  ///                         Buyer needs to purchase item with supported token
  function listItem (
    uint256 tokenId,
    uint256 salePrice,
    uint64 expires,
    address supportedToken
    ) external virtual{
        listItem(tokenId, salePrice, expires, supportedToken, 0);
    }

  /// @notice Create or update a listing for `tokenId` with `historicalPrice`
  /// @dev `price` MUST NOT be set to zero
  /// @param tokenId - identifier of the token being listed
  /// @param salePrice - the price the token is being sold for
  /// @param expires - UNIX timestamp, the buyer could buy the token before expires
  /// @param supportedToken - contract addresses of supported ERC20 token or zero address
  ///                         The zero address indicates that the supported token is ETH
  ///                         Buyer needs to purchase item with supported token
  /// @param historicalPrice - The price at which the seller last bought this token
  function listItem (
    uint256 tokenId,
    uint256 salePrice,
    uint64 expires,
    address supportedToken,
    uint256 historicalPrice
    ) public virtual{

    address tokenOwner = ownerOf(tokenId);
    require(salePrice &gt; 0, &quot;ERC6105: token sale price MUST NOT be set to zero&quot;);
    require(expires &gt; block.timestamp, &quot;ERC6105: invalid expires&quot;);
    require(_isApprovedOrOwner(_msgSender(), tokenId), &quot;ERC6105: caller is not owner nor approved&quot;);

    _listings[tokenId] = Listing(salePrice, expires, supportedToken, historicalPrice);
    emit UpdateListing(tokenId, tokenOwner, salePrice, expires, supportedToken, historicalPrice);
  }

  /// @notice Remove the listing for `tokenId`
  /// @param tokenId - identifier of the token being listed
  function delistItem(uint256 tokenId) external virtual{
    require(_isApprovedOrOwner(_msgSender(), tokenId), &quot;ERC6105: caller is not owner nor approved&quot;);
    require(_isForSale(tokenId), &quot;ERC6105: invalid listing&quot; );

    _removeListing(tokenId);
  }

  /// @notice Buy a token and transfers it to the caller
  /// @dev `salePrice` and `supportedToken` must match the expected purchase price and token to prevent front-running attacks
  /// @param tokenId - identifier of the token being purchased
  /// @param salePrice - the price the token is being sold for
  /// @param supportedToken - contract addresses of supported token or zero address
  function buyItem(uint256 tokenId, uint256 salePrice, address supportedToken) external nonReentrant payable virtual{
    address tokenOwner = ownerOf(tokenId);
    address buyer = msg.sender;
    uint256 historicalPrice = _listings[tokenId].historicalPrice;

    require(salePrice == _listings[tokenId].salePrice, &quot;ERC6105: inconsistent prices&quot;);
    require(supportedToken ==  _listings[tokenId].supportedToken,&quot;ERC6105: inconsistent tokens&quot;);
    require(_isForSale(tokenId), &quot;ERC6105: invalid listing&quot;);

    /// @dev Handle royalties
    (address royaltyRecipient, uint256 royalties) = _calculateRoyalties(tokenId, salePrice, historicalPrice);

    uint256 payment = salePrice - royalties;
    if(supportedToken == address(0)){
        require(msg.value == salePrice, &quot;ERC6105: incorrect value&quot;);
        _processSupportedTokenPayment(royalties, buyer, royaltyRecipient, address(0));
        _processSupportedTokenPayment(payment, buyer, tokenOwner, address(0));
    }
    else{
        uint256 num = IERC20(supportedToken).allowance(buyer, address(this));
        require (num &gt;= salePrice, &quot;ERC6105: insufficient allowance&quot;);
        _processSupportedTokenPayment(royalties, buyer, royaltyRecipient, supportedToken);
        _processSupportedTokenPayment(payment, buyer, tokenOwner, supportedToken);
    }

    _transfer(tokenOwner, buyer, tokenId);
    emit Purchased(tokenId, tokenOwner, buyer, salePrice, supportedToken, royalties);
  }

  /// @notice Return the listing for `tokenId`
  /// @dev The zero sale price indicates that the token is not for sale
  ///      The zero expires indicates that the token is not for sale
  ///      The zero supported token address indicates that the supported token is ETH
  /// @param tokenId identifier of the token being queried
  /// @return the specified listing (sale price, expires, supported token, benchmark price)
  function getListing(uint256 tokenId) external view virtual returns (uint256, uint64, address, uint256) {
    if(_listings[tokenId].salePrice &gt; 0 &amp;&amp; _listings[tokenId].expires &gt;=  block.timestamp){
    uint256 salePrice = _listings[tokenId].salePrice;
    uint64 expires = _listings[tokenId].expires;
    address supportedToken =  _listings[tokenId].supportedToken;
    uint256 historicalPrice = _listings[tokenId].historicalPrice;
    return (salePrice, expires, supportedToken, historicalPrice);
    }
    else{
      return (0, 0, address(0), 0);
    }
  }

  /// @dev Remove the listing for `tokenId`
  /// @param tokenId - identifier of the token being delisted
  function _removeListing(uint256 tokenId) internal virtual{
    address tokenOwner = ownerOf(tokenId);
    delete _listings[tokenId];
    emit UpdateListing(tokenId, tokenOwner, 0, 0, address(0), 0);
  }

  /// @dev Check if the token is for sale
  function _isForSale(uint256 tokenId) internal virtual returns(bool){
    if(_listings[tokenId].salePrice &gt; 0 &amp;&amp; _listings[tokenId].expires &gt;= block.timestamp){
        return true;
    }
    else{
        return false;
    }    
  }
  
  /// @dev Handle Value Added Royalty
  function _calculateRoyalties(
    uint256 tokenId,
    uint256 price,
    uint256 historicalPrice
    ) internal virtual returns(address, uint256){
    uint256 taxablePrice;
    if(price &gt; historicalPrice){
      taxablePrice = price - historicalPrice;
    }
    else{
      taxablePrice = 0 ;
    }

    (address royaltyRecipient, uint256 royalties) = royaltyInfo(tokenId, taxablePrice);
    return(royaltyRecipient, royalties);
  }

  /// @dev Process a `supportedToken` of `amount` payment to `recipient`.
  /// @param amount - the amount to send
  /// @param from - the payment payer
  /// @param recipient - the payment recipient
  /// @param supportedToken - contract addresses of supported ERC20 token or zero address
  ///                         The zero address indicates that the supported token is ETH
  function _processSupportedTokenPayment(
    uint256 amount,
    address from,
    address recipient,
    address supportedToken
    ) internal virtual{
    if(supportedToken == address(0))
    {
      (bool success,) = payable(recipient).call{value: amount}(&quot;&quot;);
      require(success, &quot;Ether Transfer Fail&quot;); 
    }
    else{
    (bool success) = IERC20(supportedToken).transferFrom(from, recipient, amount);
    require(success, &quot;Supported Token Transfer Fail&quot;);
    }
  }
  
  /// @dev See {IERC165-supportsInterface}.
  function supportsInterface(bytes4 interfaceId) public view virtual override (ERC721, ERC2981) returns (bool) {
     return interfaceId == type(IERC6105).interfaceId || super.supportsInterface(interfaceId);
  }

  /// @dev Before transferring the NFT, need to delete listing
  function _beforeTokenTransfer(address from, address to, uint256 tokenId, uint256 batchSize) internal virtual override{
      super._beforeTokenTransfer(from, to, tokenId, batchSize);
      if(_isForSale(tokenId)){
          _removeListing(tokenId);
      }
  }
}
```

## Security Considerations

The `buyItem` function, as well as the `acceptCollectionOffer` and `acceptItemOffer` functions, has a potential front-running risk.  Must check that `salePrice` and `supportedToken` match the expected price and token to prevent front-running attacks

There is a potential re-entrancy risk with the `acceptCollectionOffer` and `acceptItemOffer` functions. Make sure to obey the checks, effects, interactions pattern or use a reentrancy guard.

If a buyer uses [ERC-20](/EIPs/EIPS/eip-20) tokens to purchase an NFT, the buyer needs to first call the `approve(address spender, uint256 amount)` function of the ERC-20 token to grant the NFT contract access to a certain `amount` of tokens. Please make sure to authorize an appropriate `amount`. Furthermore, caution is advised when dealing with non-audited contracts.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 02 Dec 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6105</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6105</guid>
      </item>
    
      <item>
        <title>Supply validator deposits on chain</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6110-supply-validator-deposits-on-chain/12072</comments>
        
        <description>## Abstract

Appends validator deposits to the Execution Layer block structure. This shifts responsibility of deposit inclusion and validation to the Execution Layer and removes the need for deposit (or `eth1data`) voting from the Consensus Layer.

Validator deposits list supplied in a block is obtained by parsing deposit contract log events emitted by each deposit transaction included in a given block.

## Motivation

Validator deposits are a core component of the proof-of-stake consensus mechanism. This EIP allows for an in-protocol mechanism of deposit processing on the Consensus Layer and eliminates the proposer voting mechanism utilized currently. This proposed mechanism relaxes safety assumptions and reduces complexity of client software design, contributing to the security of the deposits flow. It also improves validator UX.

Advantages of in-protocol deposit processing consist of, but are not limited to, the following:

* Significant increase of deposits security by supplanting proposer voting. With the proposed in-protocol mechanism, an honest online node can&apos;t be convinced to process fake deposits even when more than 2/3 portion of stake is adversarial.
* Decrease of delay between submitting deposit transaction on Execution Layer and its processing on Consensus Layer. That is, ~13 minutes with in-protocol deposit processing compared to ~12 hours with the existing mechanism.
* Eliminate beacon block proposal dependency on JSON-RPC API data polling that suffers from failures caused by inconsistencies between JSON-RPC API implementations and dependency of API calls processing on the inner state (e.g. syncing) of client software.
* Eliminate requirement to maintain and distribute deposit contract snapshots ([EIP-4881](/EIPs/EIPS/eip-4881)).
* Reduction of design and engineering complexity of Consensus Layer client software on a component that has proven to be brittle.

## Specification

### Execution Layer

#### Constants

| Name | Value | Comment |
| - | - | - |
|`DEPOSIT_REQUEST_TYPE` | `b&apos;0&apos;` | The [EIP-7685](/EIPs/EIPS/eip-7685) request type byte for deposit operation |

#### Configuration

| Name | Value | Comment |
| - | - | - |
|`DEPOSIT_CONTRACT_ADDRESS` | `0x00000000219ab540356cbb839cbe05303d7705fa` | Mainnet |
|`DEPOSIT_EVENT_SIGNATURE_HASH` | `0x649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5` | |

`DEPOSIT_CONTRACT_ADDRESS`, `DEPOSIT_EVENT_SIGNATURE_HASH` parameters **MUST** be included into client software binary distribution.

#### Definitions

* **`FORK_BLOCK`** -- the first block in a blockchain after this EIP has been activated.

#### Deposit request

The structure denoting the new deposit request consists of the following fields:

1. `pubkey: Bytes48`
2. `withdrawal_credentials: Bytes32`
3. `amount: uint64`
4. `signature: Bytes96`
5. `index: uint64`

Deposits are a type of [EIP-7685](/EIPs/EIPS/eip-7685) request, with the following encoding:

```python
request_type = DEPOSIT_REQUEST_TYPE
request_data = get_deposit_request_data(block.receipts)
```

#### Block validity

Beginning with the `FORK_BLOCK`, each deposit accumulated in the block **MUST** appear in the EIP-7685 requests list
in the order they appear in the logs. To illustrate:

```python
def parse_deposit_data(deposit_event_data) -&gt; bytes[]:
  &quot;&quot;&quot;
  Parses deposit data from DepositContract.DepositEvent data
  &quot;&quot;&quot;
  pass

def is_valid_deposit_event_data(deposit_event_data: bytes) -&gt; bool:
    &quot;&quot;&quot;
    Verifies the layout of the DepositEvent. Returns `False` if the layout is unsupported,
    `True` if the layout is of the expected format.
    &quot;&quot;&quot;
    if len(deposit_event_data) != 576:
        return False

    pubkey_offset = int.from_bytes(deposit_event_data[0:32], byteorder=&apos;big&apos;, signed=False)
    withdrawal_credentials_offset = int.from_bytes(deposit_event_data[32:64], byteorder=&apos;big&apos;, signed=False)
    amount_offset = int.from_bytes(deposit_event_data[64:96], byteorder=&apos;big&apos;, signed=False)
    signature_offset = int.from_bytes(deposit_event_data[96:128], byteorder=&apos;big&apos;, signed=False)
    index_offset = int.from_bytes(deposit_event_data[128:160], byteorder=&apos;big&apos;, signed=False)

    if (
        pubkey_offset != 160
        or withdrawal_credentials_offset != 256
        or amount_offset != 320
        or signature_offset != 384
        or index_offset != 512
    ):
        return False

    # These sizes are the sizes of the relevant data
    pubkey_size = int.from_bytes(deposit_event_data[pubkey_offset:pubkey_offset+32], byteorder=&apos;big&apos;, signed=False)
    withdrawal_credentials_size = int.from_bytes(deposit_event_data[withdrawal_credentials_offset:withdrawal_credentials_offset+32], byteorder=&apos;big&apos;, signed=False)
    amount_size = int.from_bytes(deposit_event_data[amount_offset:amount_offset+32], byteorder=&apos;big&apos;, signed=False)
    signature_size = int.from_bytes(deposit_event_data[signature_offset:signature_offset+32], byteorder=&apos;big&apos;, signed=False)
    index_size = int.from_bytes(deposit_event_data[index_offset:index_offset+32], byteorder=&apos;big&apos;, signed=False)

    return (
        pubkey_size == 48
        and withdrawal_credentials_size == 32
        and amount_size == 8
        and signature_size == 96
        and index_size == 8
    )

def event_data_to_deposit_request(deposit_event_data) -&gt; bytes:
    deposit_data = parse_deposit_data(deposit_event_data)
    pubkey = Bytes48(deposit_data[0])
    withdrawal_credentials = Bytes32(deposit_data[1])
    amount = deposit_data[2]   # 8 bytes uint64 LE
    signature = Bytes96(deposit_data[3])
    index = deposit_data[4]    # 8 bytes uint64 LE

    return pubkey + withdrawal_credentials + amount + signature + index

def get_deposit_request_data(receipts)
    # Retrieve all deposits made in the block
    deposit_requests = []
    for receipt in receipts:
        for log in receipt.logs:
            if log.address == DEPOSIT_CONTRACT_ADDRESS:
                if len(log.topics) &gt; 0 and log.topics[0] == DEPOSIT_EVENT_SIGNATURE_HASH:
                    assert is_valid_deposit_event_data(log.data), &apos;invalid deposit log: unsupported data layout&apos;
                    deposit_request = event_data_to_deposit_request(log.data)
                    deposit_requests.append(deposit_request)

    # Concatenate list of deposit request data
    return b&apos;&apos;.join(deposit_requests)
```

### Consensus layer

Consensus layer changes can be summarized into the following list:

1. `ExecutionRequests` is extended with a new `deposit_requests` field to accommodate deposit requests list.
2. `BeaconState` is appended with `deposit_requests_start_index` used to switch from the former deposit mechanism to the new one.
3. As a part of transition logic a new beacon block validity condition is added to constrain the usage of `Eth1Data` poll.
4. A new `process_deposit_request` function is added to the block processing routine to handle `deposit_requests` processing.
5. Validator guide provides a logic switching off `Eth1Data` poll once transition is completed.

Detailed consensus layer specification can be found in following documents:

* [`electra/beacon-chain.md`](https://github.com/ethereum/consensus-specs/blob/eba62dbf00132dfdc97fbfab663a99cb23b9e8f1/specs/electra/beacon-chain.md) -- state transition.
* [`electra/validator.md`](https://github.com/ethereum/consensus-specs/blob/eba62dbf00132dfdc97fbfab663a99cb23b9e8f1/specs/electra/validator.md) -- validator guide.
* [`electra/fork.md`](https://github.com/ethereum/consensus-specs/blob/eba62dbf00132dfdc97fbfab663a99cb23b9e8f1/specs/electra/fork.md) -- EIP activation.

#### Validator index invariant

Due to the large follow distance of `Eth1Data` poll an index of a new validator assigned during deposit processing remains the same across different branches of a block tree, i.e. with existing mechanism `(pubkey, index)` cache utilized by consensus layer clients is re-org resilient. The new deposit machinery breaks this invariant and consensus layer clients will have to deal with a fact that a validator index becomes fork dependent, i.e. a validator with the same `pubkey` can have different indexes in different block tree branches.

Detailed [analysis](/EIPs/assets/eip-6110/pubkey_to_index_cache_analysis) shows that `process_deposit` function is *the only* place requiring a fork dependent `(pubkey, index)` cache.

#### `Eth1Data` poll deprecation

Consensus layer clients will be able to remove `Eth1Data` poll mechanism in an uncoordinated fashion once transition period is finished. The transition period is considered as finished when a network reaches the point where `state.eth1_deposit_index == state.deposit_requests_start_index`.

## Rationale

### `index` field

Deposit `index` is used to deterministically initialize `deposit_requests_start_index` in the `BeaconState`, this prevents same deposit from being applied twice during `Eth1Data` poll deprecation.

### Not limiting the size of deposit operations list

The list is unbounded because of negligible data complexity and absence of potential DoS vectors. See [Security Considerations](#security-considerations) for more details.

### Filtering events by `DEPOSIT_CONTRACT_ADDRESS` and `DEPOSIT_EVENT_SIGNATURE_HASH`

Depending on the design, Deposit smart contract can emit different type of events when deposit is being processed. For instance, Deposit smart contract on Sepolia emits `Transfer` in addition to `DepositEvent`. Thus it is important to filter out irrelevant events.

## Backwards Compatibility

This EIP introduces backwards incompatible changes to the block structure and block validation rule set. But neither of these changes break anything related to user activity and experience.

## Security Considerations

### Data complexity

At the time of the latest update of this document, the total number of submitted deposits is 1,899,120 which is 348MB of deposit data. Assuming frequency of deposit transactions remains the same, historic chain data complexity induced by this EIP can be estimated as 84MB per year which is negligible in comparison to other historical data.

After the beacon chain launch in December 2020, the biggest observed spike in a number of submitted deposits was on June 1, 2023. More than 12,000 deposit transactions were submitted during 24 hours which on average is less than 2 deposit, or 384 bytes of data, per block.

Considering the above, we conclude that data complexity introduced by this proposal is negligible.

### DoS vectors

The code in the deposit contract costs 15,650 gas to run in the cheapest case (when all storage slots are hot and only a single leaf has to be modified). Some deposits in a batch deposit are more expensive, but those costs, when amortized over a large number of deposits, are small at around ~1,000 gas per deposit. Under current gas pricing rules an extra 6,900 gas is charged to make a `CALL` that transfers ETH, this is a case of inefficient gas pricing and may be reduced in the future. For future robustness the beacon chain needs to be able to withstand 1,916 deposits in a 30M gas block (15,650 gas per deposit). The limit under current rules is less than 1,271 deposits in a 30M gas block.

#### Execution layer

With 1 ETH as a minimum deposit amount, the lowest cost of a byte of deposit data is 1 ETH/192 ~ 5,208,333 Gwei. This is several orders of magnitude higher than the cost of a byte of transaction&apos;s calldata, thus adding deposit operations to a block does not increase DoS attack surface of the execution layer.

#### Consensus layer

The most consuming computation of deposit processing is signature verification. Its complexity is bounded by a maximum number of deposits per block which is around 1,271 with 30M gas block at the moment. So, it is ~1,271 signature verifications which is roughly ~1.2 seconds of processing (without optimisations like batched signatures verification). An attacker would need to spend 1,000 ETH to slow down block processing by a second which isn&apos;t sustainable and viable attack long term.

An optimistically syncing node may be susceptible to a more severe attack scenario. Such a node can&apos;t validate a list of deposits provided in a payload which makes it possible for attacker to include as many deposits as the limitation allows to. Currently, it is 8,192 deposits (1.5MB of data) with rough processing time of 8s. Considering an attacker would need to sign off on this block with its crypto economically viable signature (which requires building an alternative chain and feeding it to a syncing node), this attack vector is not considered as viable as it can&apos;t result in a significant slow down of a sync process.

### Optimistic sync

An optimistically syncing node has to rely on the honest majority assumption. That is, if adversary is powerful enough to finalize a deposit sequence, a syncing node will have to apply these deposits disregarding the validity of deposit requests with respect to the execution of a given block. Thus, an adversary that can finalize an invalid chain can also convince an honest node to accept fake deposits. The same is applicable to the validity of execution layer world state today and a new deposit processing design is within boundaries of the existing security model in that regard.

Online nodes can&apos;t be tricked into this situation because their execution layer validates supplied deposits with respect to the block execution.

### Weak subjectivity period

This EIP removes a hard limit on a number of deposits per epoch and makes a block gas limit the only limitation on this number. That is, the limit on deposits per epoch shifts from `MAX_DEPOSITS * SLOTS_PER_EPOCH = 512` to `max_deposits_per_30m_gas_block * SLOTS_PER_EPOCH ~ 32,768` at 30M gas block (we consider `max_deposits_per_30m_gas_block = 1,024` for simplicity).

This change affects a number of top ups per epoch which is one of the inputs to the weak subjectivity period computation. One can top up own validators to instantly increase a portion of stake it owns with respect to those validators that are leaking. [The analysis](/EIPs/assets/eip-6110/ws_period_analysis) does not demonstrate significant reduction of a weak subjectivity period sizes. Moreover, such an attack is not considered as viable because it requires a decent portion of stake to be burned as one of preliminaries.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 09 Dec 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6110</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6110</guid>
      </item>
    
      <item>
        <title>Universal Token Router</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6120-universal-token-router/12142</comments>
        
        <description>## Abstract

The default transaction behavior of ETH is *transfer-and-call*, but the widely used [ERC-20](/EIPs/EIPS/eip-20) standard isn&apos;t compatible with this pattern. This incompatibility forces applications to use an inefficient and risky two-step *approve-then-call* process. This approach is costly, creates a poor user experience, and introduces significant security vulnerabilities, as users must approve unaudited and often upgradable contracts. This has led to numerous allowance-related bugs and exploits.

The **Universal Token Router** (**UTR**) addresses this issue by separating the token allowance from the application logic. This allows any token to be spent in a single contract call, similar to how ETH is handled, without needing to approve individual application contracts. When tokens are approved to the **UTR**, they can only be spent in transactions signed directly by the token owner. The **UTR**&apos;s transaction data clearly shows key details like token types, amounts, and the recipient.

The **UTR** promotes the **security-by-result** model over the **security-by-process** model. By allowing applications to verify the output of a transaction (e.g., checking token balance changes), users&apos; funds can be secure even when interacting with potentially flawed or malicious contracts.

The **UTR** contract is deployed at `0x69c4620b62D99f524c5B4dE45442FE2D7dD59576` on all EVM-compatible networks using the [EIP-1014](/EIPs/EIPS/eip-1014) SingletonFactory. This allows new token contracts to pre-configure it as a trusted spender, eliminating the need for approval transactions entirely for their interactive usage.

## Motivation

When users approve their tokens to a contract, they expect that:

* it only spends the tokens with their permission (from `msg.sender` or `ecrecover`)
* it does not use `delegatecall` (e.g. upgradable proxies)

The **UTR** ensures these same security conditions, allowing all interactive applications to share a single, secure token allowance. This saves most approval transactions for existing tokens and **all** approval transactions for new ones.

Before the **UTR**, users had to blindly trust the front-end code of applications to construct transactions honestly. This made them highly vulnerable to phishing. The **UTR**&apos;s function arguments act as a manifest that wallets can display to users, allowing them to review the expected token behavior before signing, making phishing attacks much easier to detect.

Most existing application contracts are already compatible with the **UTR** and can integrate it to gain several benefits:

* Securely share a user&apos;s token allowance across all applications.
* Update their own peripheral contracts as often as needed without requiring new user approvals.
* Save development and security audit costs on their own router contracts.


## Specification

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.

The main interface of the UTR contract:

```solidity
interface IUniversalTokenRouter {
    function exec(
        Output[] memory outputs,
        Action[] memory actions
    ) payable;
}
```

### Output Verification

`Output` defines the expected token balance change for verification.

```solidity
struct Output {
    address recipient;
    uint eip;           // token standard: 0 for ETH or EIP number
    address token;      // token contract address
    uint id;            // token id for ERC-721 and ERC-1155
    uint amountOutMin;
}
```

Token balances of the `recipient` address are recorded at the beginning and the end of the `exec` function for each item in `outputs`. Transaction will revert with `INSUFFICIENT_OUTPUT_AMOUNT` if any of the balance changes are less than its `amountOutMin`.

A special id `ERC_721_BALANCE` is reserved for [ERC-721](/EIPs/EIPS/eip-721), which can be used in output actions to verify the total amount of all ids owned by the `recipient` address.

```solidity
ERC_721_BALANCE = keccak256(&apos;UniversalTokenRouter.ERC_721_BALANCE&apos;)
```

### Action

`Action` defines the token inputs and the contract call.

```solidity
struct Action {
    Input[] inputs;
    address code;       // contract code address
    bytes data;         // contract input data
}
```

The action code contract MUST implement the `NotToken` contract or the [ERC-165](/EIPs/EIPS/eip-165) interface with the ID `0x61206120` in order to be called by the UTR. This interface check prevents the direct invocation of token *allowance-spending* functions (e.g., `transferFrom`) by the UTR. Therefore, new token contracts MUST NOT implement this interface ID.

```solidity
/**
 * This contract will conflict with the ERC20, ERC721, and ERC1155 standards,
 * preventing token contracts from accidentally implementing it.
 */
abstract contract NotToken  {
    function allowance(address, address) external pure returns (string memory) {
        return &quot;THIS IS NOT A TOKEN&quot;;
    }
    function isApprovedForAll(address, address) external pure returns (string memory) {
        return &quot;THIS IS NOT A TOKEN&quot;;
    }
}

contract Application is NotToken {
    // this contract can be used with the UTR
}
```

### Input

`Input` defines the input token to transfer or prepare before the action contract is executed.

```solidity
struct Input {
    uint mode;
    address recipient;
    uint eip;           // token standard: 0 for ETH or EIP number
    address token;      // token contract address
    uint id;            // token id for ERC-721 and ERC-1155
    uint amountIn;
}
```

`mode` takes one of the following values:

* `PAYMENT = 0`: pend a payment for the token to be transferred from `msg.sender` to the `recipient` by calling `UTR.pay` from anywhere in the same transaction.
* `TRANSFER = 1`: transfer the token directly from `msg.sender` to the `recipient`.
* `CALL_VALUE = 2`: record the `ETH` amount to pass to the action as the call `value`.

Each input in the `inputs` argument is processed sequentially. For simplicity, duplicated `PAYMENT` and `CALL_VALUE` inputs are valid, but only the last `amountIn` value is used.

#### Payment Input

`PAYMENT` is the recommended mode for application contracts that use the *transfer-in-callback* pattern. E.g., flashloan contracts, Uniswap/v3-core, Derion, etc.

For each `Input` with `PAYMENT` mode, at most `amountIn` of the token can be transferred from `msg.sender` to the `recipient` by calling `UTR.pay` from anywhere in the same transaction.

```
UTR
 |
 | PAYMENT
 | (payments pended for UTR.pay)
 |
 |                                  Application Contracts
action.code.call ---------------------&gt; |
                                        |
UTR.pay &lt;----------------------- (call) |
                                        |
 | &lt;-------------------------- (return) |
 |
 | (clear all pending payments)
 |
END
```

Token&apos;s allowance and `PAYMENT` are essentially different as:

* allowance: allow a specific `spender` to transfer the token to anyone at any time.
* `PAYMENT`: allow anyone to transfer the token to a specific `recipient` only in that transaction.

##### Spend Payment

```solidity
interface IUniversalTokenRouter {
    function pay(bytes memory payment, uint amount);
}
```

To call `pay`, the `payment` param must be encoded as follows:

```solidity
payment = abi.encode(
    payer,      // address
    recipient,  // address
    eip,        // uint256
    token,      // address
    id          // uint256
);
```

The `payment` bytes can also be used by adapter UTR contracts to pass contexts and payloads for performing custom payment logic.

##### Discard Payment

Sometimes, it&apos;s useful to discard the payment instead of performing the transfer, for example, when the application contract wants to burn its own token from `payment.payer`. The following function can be used to verify the payment to the caller&apos;s address and discard a portion of it.

```solidity
interface IUniversalTokenRouter {
    function discard(bytes memory payment, uint amount);
}
```

Please refer to the [Discard Payment](#discard-payment-1) section in the **Security Considerations** for an important security note.

##### Sender Authentication

Discarding payment also makes sender authentication possible with a router, which is never achievable with regular routers. By inputting a pseudo payment (not a token payment), the UTR allows the target contract to verify the sender&apos;s address for authentication, along with normal token transfers and payments.

```solidity
contract AuthChecker is NotToken {
    // must be trusted with a proper implementation of discard function
    address immutable UTR;

    function actionMustSentBySender(address sender) external {
        bytes memory payment = abi.encode(sender, address(this), 0, address(0), 0);
        IUniversalTokenRouter(UTR).discard(payment, 1);
    }
}
```

```javascript
await utr.exec([], [{
    inputs: [{
        mode: PAYMENT,
        eip: 0,
        token: AddressZero,
        id: 0,
        amountIn: 1,
        recipient: paymentTest.address,
    }],
    code: authChecker.address,
    data: (await authChecker.populateTransaction.actionMustSentBySender(owner.address)).data,
}])
```

Please refer to the [Discard Payment](#discard-payment-1) section in the **Security Considerations** for an important security note.

##### Payment Lifetime

Payments are recorded in the UTR storage and intended to be spent by `input.action` external calls only within that transaction. All payment storages will be cleared before the `UTR.exec` ends.

### Native Token Tranfer

The `UTR` SHOULD have a `receive()` function for user execution logic that requires transferring ETH in. The `msg.value` transferred into the router can be spent in multiple inputs across different actions. While the caller takes full responsibility for the movement of `ETH` in and out of the router, the `exec` function SHOULD refund any remaining `ETH` before the function ends.

Please refer to the [Reentrancy](#reentrancy) section in the **Security Considerations** for information on reentrancy risks and mitigation.

### Usage Examples

#### Uniswap V2 Router

Legacy function:

```solidity
UniswapV2Router01.swapExactTokensForTokens(
    uint amountIn,
    uint amountOutMin,
    address[] calldata path,
    address to,
    uint deadline
)
```

`UniswapV2Helper01.swapExactTokensForTokens` is a modified version of it without the token transfer part.

This transaction is signed by users to execute the swap instead of the legacy function:

```javascript
UniversalTokenRouter.exec([{
    recipient: to,
    eip: 20,
    token: path[path.length-1],
    id: 0,
    amountOutMin,
}], [{
    inputs: [{
        mode: TRANSFER,
        recipient: UniswapV2Library.pairFor(factory, path[0], path[1]),
        eip: 20,
        token: path[0],
        id: 0,
        amountIn: amountIn,
    }],
    code: UniswapV2Helper01.address,
    data: encodeFunctionData(&quot;swapExactTokensForTokens&quot;, [
        amountIn,
        amountOutMin,
        path,
        to,
        deadline,
    ]),
}])
```

#### Uniswap V3 Router

Legacy router contract:

```solidity
contract SwapRouter {
    // this function is called by pool to pay the input tokens
    function pay(
        address token,
        address payer,
        address recipient,
        uint256 value
    ) internal {
        ...
        // pull payment
        TransferHelper.safeTransferFrom(token, payer, recipient, value);
    }
}
```

The helper contract to use with the `UTR`:

```solidity
contract SwapHelper {
    // this function is called by pool to pay the input tokens
    function pay(
        address token,
        address payer,
        address recipient,
        uint256 value
    ) internal {
        ...
        // pull payment
        bytes memory payment = abi.encode(payer, recipient, 20, token, 0);
        UTR.pay(payment, value);
    }
}
```

This transaction is signed by users to execute the `exactInput` functionality using `PAYMENT` mode:

```javascript
UniversalTokenRouter.exec([{
    eip: 20,
    token: tokenOut,
    id: 0,
    amountOutMin: 1,
    recipient: to,
}], [{
    inputs: [{
        mode: PAYMENT,
        eip: 20,
        token: tokenIn,
        id: 0,
        amountIn: amountIn,
        recipient: pool.address,
    }],
    code: SwapHelper.address,
    data: encodeFunctionData(&quot;exactInput&quot;, [...]),
}])
```

#### Allowance Adapter

A simple non-reentrancy ERC-20 adapter for aplication and router contracts that use direct allowance.

```solidity
contract AllowanceAdapter is ReentrancyGuard {
    struct Input {
        address token;
        uint amountIn;
    }

    function approveAndCall(
        Input[] memory inputs,
        address spender,
        bytes memory data,
        address leftOverRecipient
    ) external payable nonReentrant {
        for (uint i = 0; i &lt; inputs.length; ++i) {
            Input memory input = inputs[i];
            IERC20(input.token).approve(spender, input.amountIn);
        }

        (bool success, bytes memory result) = spender.call{value: msg.value}(data);
        if (!success) {
            assembly {
                revert(add(result, 32), mload(result))
            }
        }

        for (uint i = 0; i &lt; inputs.length; ++i) {
            Input memory input = inputs[i];
            // clear all allowance
            IERC20(input.token).approve(spender, 0);
            uint leftOver = IERC20(input.token).balanceOf(address(this));
            if (leftOver &gt; 0) {
                TransferHelper.safeTransfer(input.token, leftOverRecipient, leftOver);
            }
        }
    }
}
```

This transaction is constructed to utilize the `UTR` to interact with Uniswap V2 Router without approving any token to it:

```javascript
const { data: routerData } = await uniswapRouter.populateTransaction.swapExactTokensForTokens(
    amountIn,
    amountOutMin,
    path,
    to,
    deadline,
)

const { data: adapterData } = await adapter.populateTransaction.approveAndCall(
    [{
        token: path[0],
        amountIn,
    }],
    uniswapRouter.address,
    routerData,
    leftOverRecipient,
)

await utr.exec([], [{
    inputs: [{
        mode: TRANSFER,
        recipient: adapter.address,
        eip: 20,
        token: path[0],
        id: 0,
        amountIn,
    }],
    code: adapter.address,
    data: adapterData,
}])
```

## Rationale

The `Permit` type signature is not supported since the purpose of the Universal Token Router is to eliminate all interactive `approve` signatures for new tokens, and *most* for old tokens.

## Backwards Compatibility

### Tokens

Old token contracts (ERC-20, ERC-721 and [ERC-1155](/EIPs/EIPS/eip-1155)) require approval for the Universal Token Router once for each account.

New token contracts can pre-configure the Universal Token Router as a trusted spender, and no approval transaction is required for interactive usage.

```solidity
import &quot;@openzeppelin/contracts/token/ERC20/ERC20.sol&quot;;

/**
 * @dev Implementation of the {ERC20} token standard that support a trusted ERC6120 contract as an unlimited spender.
 */
contract ERC20WithUTR is ERC20 {
    address immutable UTR;

    /**
     * @dev Sets the values for {name}, {symbol} and ERC6120&apos;s {utr} address.
     *
     * All three of these values are immutable: they can only be set once during
     * construction.
     *
     * @param utr can be zero to disable trusted ERC6120 support.
     */
    constructor(string memory name, string memory symbol, address utr) ERC20(name, symbol) {
        UTR = utr;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        if (spender == UTR &amp;&amp; spender != address(0)) {
            return type(uint256).max;
        }
        return super.allowance(owner, spender);
    }

    /**
     * Does not check or update the allowance if `spender` is the UTR.
     */
    function _spendAllowance(address owner, address spender, uint256 amount) internal virtual override {
        if (spender == UTR &amp;&amp; spender != address(0)) {
            return;
        }
        super._spendAllowance(owner, spender, amount);
    }
}
```

### Applications

The only application contracts **INCOMPATIBLE** with the UTR are contracts that use `msg.sender` as the beneficiary address in their internal storage without any function for ownership transfer.

All application contracts that accept `recipient` (or `to`) argument as the beneficiary address are compatible with the UTR out of the box.

Application contracts that transfer tokens (ERC-20, ERC-721, and ERC-1155) to `msg.sender` need additional adapters to add a `recipient` to their functions.

```solidity
// sample adapter contract for WETH
contract WethAdapter {
    function deposit(address recipient) external payable {
        IWETH(WETH).deposit(){value: msg.value};
        TransferHelper.safeTransfer(WETH, recipient, msg.value);
    }
}
```

Additional helper and adapter contracts might be needed, but they&apos;re mostly peripheral and non-intrusive. They don&apos;t hold any tokens or allowances, so they can be frequently updated and have little to no security impact on the core application contracts.

## Reference Implementation

A reference implementation by Derion Labs and audited by Hacken.

```solidity
/// @title The implementation of the EIP-6120.
/// @author Derion Labs
contract UniversalTokenRouter is ERC165, IUniversalTokenRouter {
    uint256 constant PAYMENT       = 0;
    uint256 constant TRANSFER      = 1;
    uint256 constant CALL_VALUE    = 2;

    uint256 constant EIP_ETH       = 0;

    uint256 constant ERC_721_BALANCE = uint256(keccak256(&apos;UniversalTokenRouter.ERC_721_BALANCE&apos;));

    /// The main entry point of the router
    /// @param outputs token behavior for output verification
    /// @param actions router actions and inputs for execution
    function exec(
        Output[] memory outputs,
        Action[] memory actions
    ) external payable virtual override {
    unchecked {
        // track the expected balances before any action is executed
        for (uint256 i = 0; i &lt; outputs.length; ++i) {
            Output memory output = outputs[i];
            uint256 balance = _balanceOf(output);
            uint256 expected = output.amountOutMin + balance;
            require(expected &gt;= balance, &apos;UTR: OUTPUT_BALANCE_OVERFLOW&apos;);
            output.amountOutMin = expected;
        }

        for (uint256 i = 0; i &lt; actions.length; ++i) {
            Action memory action = actions[i];
            uint256 value;
            for (uint256 j = 0; j &lt; action.inputs.length; ++j) {
                Input memory input = action.inputs[j];
                uint256 mode = input.mode;
                if (mode == CALL_VALUE) {
                    // eip and id are ignored
                    value = input.amountIn;
                } else {
                    if (mode == PAYMENT) {
                        bytes32 key = keccak256(abi.encode(
                            msg.sender, input.recipient, input.eip, input.token, input.id
                        ));
                        uint amountIn = input.amountIn;
                        assembly {
                            tstore(key, amountIn)
                        }
                    } else if (mode == TRANSFER) {
                        _transferToken(msg.sender, input.recipient, input.eip, input.token, input.id, input.amountIn);
                    } else {
                        revert(&apos;UTR: INVALID_MODE&apos;);
                    }
                }
            }
            if (action.code != address(0) || action.data.length &gt; 0 || value &gt; 0) {
                require(
                    TokenChecker.isNotToken(action.code) ||
                    ERC165Checker.supportsInterface(action.code, 0x61206120),
                    &quot;UTR: NOT_CALLABLE&quot;
                );
                (bool success, bytes memory result) = action.code.call{value: value}(action.data);
                if (!success) {
                    assembly {
                        revert(add(result,32),mload(result))
                    }
                }
            }
            // clear all transient storages
            for (uint256 j = 0; j &lt; action.inputs.length; ++j) {
                Input memory input = action.inputs[j];
                if (input.mode == PAYMENT) {
                    // transient storages
                    bytes32 key = keccak256(abi.encode(
                        msg.sender, input.recipient, input.eip, input.token, input.id
                    ));
                    assembly {
                        tstore(key, 0)
                    }
                }
            }
        }

        // refund any left-over ETH
        uint256 leftOver = address(this).balance;
        if (leftOver &gt; 0) {
            TransferHelper.safeTransferETH(msg.sender, leftOver);
        }

        // verify balance changes
        for (uint256 i = 0; i &lt; outputs.length; ++i) {
            Output memory output = outputs[i];
            uint256 balance = _balanceOf(output);
            // NOTE: output.amountOutMin is reused as `expected`
            require(balance &gt;= output.amountOutMin, &apos;UTR: INSUFFICIENT_OUTPUT_AMOUNT&apos;);
        }
    } }
    
    /// Spend the pending payment. Intended to be called from the input.action.
    /// @param payment encoded payment data
    /// @param amount token amount to pay with payment
    function pay(bytes memory payment, uint256 amount) external virtual override {
        discard(payment, amount);
        (
            address sender,
            address recipient,
            uint256 eip,
            address token,
            uint256 id
        ) = abi.decode(payment, (address, address, uint256, address, uint256));
        _transferToken(sender, recipient, eip, token, id, amount);
    }

    /// Discard a part of a pending payment. Can be called from the input.action
    /// to verify the payment without transferring any token.
    /// @param payment encoded payment data
    /// @param amount token amount to pay with payment
    function discard(bytes memory payment, uint256 amount) public virtual override {
        bytes32 key = keccak256(payment);
        uint256 remain;
        assembly {
            remain := tload(key)
        }
        require(remain &gt;= amount, &apos;UTR: INSUFFICIENT_PAYMENT&apos;);
        assembly {
            tstore(key, sub(remain, amount))
        }
    }

    // IERC165-supportsInterface
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return
            interfaceId == type(IUniversalTokenRouter).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    function _transferToken(
        address sender,
        address recipient,
        uint256 eip,
        address token,
        uint256 id,
        uint256 amount
    ) internal virtual {
        if (eip == 20) {
            TransferHelper.safeTransferFrom(token, sender, recipient, amount);
        } else if (eip == 1155) {
            IERC1155(token).safeTransferFrom(sender, recipient, id, amount, &quot;&quot;);
        } else if (eip == 721) {
            IERC721(token).safeTransferFrom(sender, recipient, id);
        } else {
            revert(&quot;UTR: INVALID_EIP&quot;);
        }
    }

    function _balanceOf(
        Output memory output
    ) internal view virtual returns (uint256 balance) {
        uint256 eip = output.eip;
        if (eip == 20) {
            return IERC20(output.token).balanceOf(output.recipient);
        }
        if (eip == 1155) {
            return IERC1155(output.token).balanceOf(output.recipient, output.id);
        }
        if (eip == 721) {
            if (output.id == ERC_721_BALANCE) {
                return IERC721(output.token).balanceOf(output.recipient);
            }
            try IERC721(output.token).ownerOf(output.id) returns (address currentOwner) {
                return currentOwner == output.recipient ? 1 : 0;
            } catch {
                return 0;
            }
        }
        if (eip == EIP_ETH) {
            return output.recipient.balance;
        }
        revert(&quot;UTR: INVALID_EIP&quot;);
    }
}
```

## Security Considerations

### ERC-165 Tokens

Token contracts must **NEVER** support the ERC-165 interface with the ID `0x61206120`, as it is reserved for non-token contracts to be called with the UTR. Any token with the interface ID `0x61206120` approved to the UTR can be spent by anyone, without any restrictions.

### Reentrancy

Tokens transferred to the UTR contract will be permanently lost, as there is no way to transfer them out. Applications that require an intermediate address to hold tokens should use their own Helper contract with a reentrancy guard for secure execution.

ETH must be transferred to the UTR contracts before the value is spent in an action call (using `CALL_VALUE`). This ETH value can be siphoned out of the UTR using a re-entrant call inside an action code or rogue token functions. This exploit will not be possible if users don&apos;t transfer more ETH than they will spend in that transaction.

```solidity
// transfer 100 in, but spend only 60,
// so at most 40 wei can be exploited in this transaction
UniversalTokenRouter.exec([
    ...
], [{
    inputs: [{
        mode: CALL_VALUE,
        eip: 20,
        token: 0,
        id: 0,
        amountIn: 60,   // spend 60
        recipient: AddressZero,
    }],
    ...
}], {
    value: 100,   // transfer 100 in
})
```

### Discard Payment

The result of the `pay` function can be checked by querying the balance after the call, allowing the UTR contract to be called in a trustless manner. However, due to the inability to verify the execution of the `discard` function, it should only be used with a trusted UTR contract.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 12 Dec 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6120</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6120</guid>
      </item>
    
      <item>
        <title>Forkid checks based on timestamps</title>
        <category>Standards Track/Networking</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6122-forkid-checks-based-on-timestamps/12130</comments>
        
        <description>## Abstract

[EIP-2124](/EIPs/EIPS/eip-2124) proposed a way of identifying nodes on the p2p network based on their chain configuration via the forkid parameter. 
It allows nodes to cut incompatible nodes off quickly which makes the P2P network more reliable.
After the merge, forks are scheduled by block time instead of block number. This EIP updates the forkid calculation with block time.

## Motivation

While in proof-of-work forks were scheduled by block number, the proof-of-stake consensus layer schedules forks by slot number. The slot number is a time based measurement. In order to schedule forks at the same time on the consensus and execution layer, the execution layer is forced to also schedule forks by timestamp after the merge.

The forkid calculation allows peers to quickly determine the configuration of peers and disconnect peers that are misconfigured or configured for other networks.

## Specification

Each node maintains the following values:

- **`FORK_HASH`**: IEEE CRC32 checksum (`[4]byte`) of the genesis hash and fork blocks numbers or timestamps that already passed.
  - The fork block numbers or timestamps are fed into the CRC32 checksum in ascending order.
  - If multiple forks are applied at the same block or time, the block number or timestamp is checksummed only once.
  - Block numbers are regarded as `uint64` integers, encoded in big endian format when checksumming.
  - Block timestamps are regarded as `uint64` integers, encoded in big endian format when checksumming.
  - If a chain is configured to start with a non-Frontier ruleset already in its genesis, that is NOT considered a fork.
- **`FORK_NEXT`**: Block number or timestamp (`uint64`) of the next upcoming fork, or `0` if no next fork is known.
  - Note that it is not important to distinguish between a timestamp or a block for `FORK_NEXT`.

A `FORK_HASH` for a timestamp based fork at `1668000000` on top of homestead would be:

- forkhash₁ = `0xcb37b2ee` (homestead+fictional fork) = `CRC32(&lt;genesis-hash&gt; || uint64(1150000) || uint64(1668000000))`

### Additional rules

The following additional rules are applied:

- Forks by timestamp MUST be scheduled at or after the forks by block (on mainnet as well as on private networks).
- An implementation of forkid verification of remote peer needs to filter the incoming forkids first by block then by timestamp.

## Rationale

Shanghai will be scheduled by timestamp thus the forkid calculations need to be updated to work with timestamps and blocks.
Since all block number based forks are before time based forks, nodes need to check the block based forks before the time based forks.

## Backwards Compatibility

This change modifies the forkid calculation slightly. 
As a consequence nodes applying this change will drop peers who are not applying this change as soon as timestamp-scheduled fork occurs.
This is not only expected, but actually the purpose of the forkid in the first place.

## Test Cases

Here&apos;s a suite of tests with mainnet config and withdrawals enabled at time `1668000000` and merge netsplit block at block `18000000`

```go
type testcase struct {
	head uint64
	want ID
}
tests := []struct {
	config  *params.ChainConfig
	genesis common.Hash
	cases   []testcase
}{
	// Withdrawal test cases
	&amp;withdrawalConfig,
	params.MainnetGenesisHash,
	[]testcase{
		{0, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}},           // Unsynced
		{1149999, 0, ID{Hash: checksumToBytes(0xfc64ec04), Next: 1150000}},     // Last Frontier block
		{1150000, 0, ID{Hash: checksumToBytes(0x97c2c34c), Next: 1920000}},     // First Homestead block
		{1919999, 0, ID{Hash: checksumToBytes(0x97c2c34c), Next: 1920000}},     // Last Homestead block
		{1920000, 0, ID{Hash: checksumToBytes(0x91d1f948), Next: 2463000}},     // First DAO block
		{2462999, 0, ID{Hash: checksumToBytes(0x91d1f948), Next: 2463000}},     // Last DAO block
		{2463000, 0, ID{Hash: checksumToBytes(0x7a64da13), Next: 2675000}},     // First Tangerine block
		{2674999, 0, ID{Hash: checksumToBytes(0x7a64da13), Next: 2675000}},     // Last Tangerine block
		{2675000, 0, ID{Hash: checksumToBytes(0x3edd5b10), Next: 4370000}},     // First Spurious block
		{4369999, 0, ID{Hash: checksumToBytes(0x3edd5b10), Next: 4370000}},     // Last Spurious block
		{4370000, 0, ID{Hash: checksumToBytes(0xa00bc324), Next: 7280000}},     // First Byzantium block
		{7279999, 0, ID{Hash: checksumToBytes(0xa00bc324), Next: 7280000}},     // Last Byzantium block
		{7280000, 0, ID{Hash: checksumToBytes(0x668db0af), Next: 9069000}},     // First and last Constantinople, first Petersburg block
		{9068999, 0, ID{Hash: checksumToBytes(0x668db0af), Next: 9069000}},     // Last Petersburg block
		{9069000, 0, ID{Hash: checksumToBytes(0x879d6e30), Next: 9200000}},     // First Istanbul and first Muir Glacier block
		{9199999, 0, ID{Hash: checksumToBytes(0x879d6e30), Next: 9200000}},     // Last Istanbul and first Muir Glacier block
		{9200000, 0, ID{Hash: checksumToBytes(0xe029e991), Next: 12244000}},    // First Muir Glacier block
		{12243999, 0, ID{Hash: checksumToBytes(0xe029e991), Next: 12244000}},   // Last Muir Glacier block
		{12244000, 0, ID{Hash: checksumToBytes(0x0eb440f6), Next: 12965000}},   // First Berlin block
		{12964999, 0, ID{Hash: checksumToBytes(0x0eb440f6), Next: 12965000}},   // Last Berlin block
		{12965000, 0, ID{Hash: checksumToBytes(0xb715077d), Next: 13773000}},   // First London block
		{13772999, 0, ID{Hash: checksumToBytes(0xb715077d), Next: 13773000}},   // Last London block
		{13773000, 0, ID{Hash: checksumToBytes(0x20c327fc), Next: 15050000}},   // First Arrow Glacier block
		{15049999, 0, ID{Hash: checksumToBytes(0x20c327fc), Next: 15050000}},   // Last Arrow Glacier block
		{15050000, 0, ID{Hash: checksumToBytes(0xf0afd0e3), Next: 18000000}},   // First Gray Glacier block
		{18000000, 0, ID{Hash: checksumToBytes(0x4fb8a872), Next: 1668000000}}, // First Merge Start block
		{20000000, 0, ID{Hash: checksumToBytes(0x4fb8a872), Next: 1668000000}}, // Last Merge Start block
		{20000000, 1668000000, ID{Hash: checksumToBytes(0xc1fdf181), Next: 0}}, // First Shanghai block
		{20100000, 2669000000, ID{Hash: checksumToBytes(0xc1fdf181), Next: 0}}, // Future Shanghai block
	},
}
```

 Here&apos;s a suite of tests of the different states a Mainnet node might be in and the different remote fork identifiers it might be required to validate and decide to accept or reject:

```go
tests := []struct {
	head uint64
	id   ID
	err  error
}{
	/// Local is mainnet Withdrawals, remote announces the same. No future fork is announced.
	{20000000, 1668000001, ID{Hash: checksumToBytes(0xc1fdf181), Next: 0}, nil},

	// Local is mainnet Withdrawals, remote announces the same also announces a next fork
	// at block/time 0xffffffff, but that is uncertain.
	{20000000, 1668000001, ID{Hash: checksumToBytes(0xc1fdf181), Next: math.MaxUint64}, nil},

	// Local is mainnet currently in Byzantium only (so it&apos;s aware of Petersburg &amp; Withdrawals), remote announces
	// also Byzantium, but it&apos;s not yet aware of Petersburg (e.g. non updated node before the fork).
	// In this case we don&apos;t know if Petersburg passed yet or not.
	{7279999, 1667999999, ID{Hash: checksumToBytes(0xa00bc324), Next: 0}, nil},

	// Local is mainnet currently in Byzantium only (so it&apos;s aware of Petersburg &amp; Withdrawals), remote announces
	// also Byzantium, and it&apos;s also aware of Petersburg (e.g. updated node before the fork). We
	// don&apos;t know if Petersburg passed yet (will pass) or not.
	{7279999, 1667999999, ID{Hash: checksumToBytes(0xa00bc324), Next: 7280000}, nil},

	// Local is mainnet currently in Byzantium only (so it&apos;s aware of Petersburg &amp; Withdrawals), remote announces
	// also Byzantium, and it&apos;s also aware of some random fork (e.g. misconfigured Petersburg). As
	// neither forks passed at neither nodes, they may mismatch, but we still connect for now.
	{7279999, 1667999999, ID{Hash: checksumToBytes(0xa00bc324), Next: math.MaxUint64}, nil},

	// Local is mainnet exactly on Withdrawals, remote announces Byzantium + knowledge about Petersburg. Remote
	// is simply out of sync, accept.
	{20000000, 1668000000, ID{Hash: checksumToBytes(0xa00bc324), Next: 7280000}, nil},

	// Local is mainnet Withdrawals, remote announces Byzantium + knowledge about Petersburg. Remote
	// is simply out of sync, accept.
	{20000000, 1668000001, ID{Hash: checksumToBytes(0xa00bc324), Next: 7280000}, nil},

	// Local is mainnet Withdrawals, remote announces Spurious + knowledge about Byzantium. Remote
	// is definitely out of sync. It may or may not need the Petersburg update, we don&apos;t know yet.
	{20000000, 1668000001, ID{Hash: checksumToBytes(0x3edd5b10), Next: 4370000}, nil},

	// Local is mainnet Byzantium &amp; pre-withdrawals, remote announces Petersburg. Local is out of sync, accept.
	{7279999, 1667999999, ID{Hash: checksumToBytes(0x668db0af), Next: 0}, nil},

	// Local is mainnet Spurious, remote announces Byzantium, but is not aware of Petersburg. Local
	// out of sync. Local also knows about a future fork, but that is uncertain yet.
	{4369999, 1667999999, ID{Hash: checksumToBytes(0xa00bc324), Next: 0}, nil},

	// Local is mainnet Withdrawals. remote announces Byzantium but is not aware of further forks.
	// Remote needs software update.
	{20000000, 1668000001, ID{Hash: checksumToBytes(0xa00bc324), Next: 0}, ErrRemoteStale},

	// Local is mainnet Withdrawals, and isn&apos;t aware of more forks. Remote announces Petersburg +
	// 0xffffffff. Local needs software update, reject.
	{20000000, 1668000001, ID{Hash: checksumToBytes(0x5cddc0e1), Next: 0}, ErrLocalIncompatibleOrStale},

	// Local is mainnet Withdrawals, and is aware of Petersburg. Remote announces Petersburg +
	// 0xffffffff. Local needs software update, reject.
	{20000000, 1668000001, ID{Hash: checksumToBytes(0x5cddc0e1), Next: 0}, ErrLocalIncompatibleOrStale},

	// Local is mainnet Withdrawals, remote is Rinkeby Petersburg.
	{20000000, 1668000001, ID{Hash: checksumToBytes(0xafec6b27), Next: 0}, ErrLocalIncompatibleOrStale},

	// Local is mainnet Withdrawals, far in the future. Remote announces Gopherium (non existing fork)
	// at some future block 88888888, for itself, but past block for local. Local is incompatible.
	//
	// This case detects non-upgraded nodes with majority hash power (typical Ropsten mess).
	{88888888, 1668000001, ID{Hash: checksumToBytes(0xf0afd0e3), Next: 88888888}, ErrRemoteStale},

	// Local is mainnet Withdrawals. Remote is in Byzantium, but announces Gopherium (non existing
	// fork) at block 7279999, before Petersburg. Local is incompatible.
	{20000000, 1668000001, ID{Hash: checksumToBytes(0xa00bc324), Next: 7279999}, ErrRemoteStale},
```

## Security Considerations 

No known security risks

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 13 Dec 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6122</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6122</guid>
      </item>
    
      <item>
        <title>Smart Derivative Contract</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6123-smart-derivative-contract-frictionless-processing-of-financial-derivatives/12134</comments>
        
        <description>## Abstract

The Smart Derivative Contract (SDC) allows fully automizing and securing a financial product&apos;s - e.g. a financial derivative or bond - complete trade life cycle.[^1]
The SDC leverages the advantages of smart contracts to remove many of the frictions associated with the classical derivative life cycle. Most notably, the protocol allows the removal of counterpart risk essentially.
The SDC can be implemented using a pre-agreed valuation oracle and valuation model, removing ambiguity in the settlement amounts. The SDC provides methods and callbacks to enable fully automated and fully transactional settlements (delivery-versus-payment, payment-vs-payment).
Token-based settlement can be realized by any contract implementation implementing an [ERC-20](/EIPs/EIPS/eip-20) token.
Proof of concepts in terms of two legally binding digital Interest Rate Swaps were conducted in 2021 and 2022.

## Motivation

### Rethinking Financial Derivatives

By their very nature, so-called &quot;over-the-counter (OTC)&quot; financial contracts are bilateral contractual agreements on exchanging long-dated cash flow schedules.
Since these contracts change their intrinsic market value due to changing market environments, they are subject to counterparty credit risk when one counterparty is subject to default.
The initial white paper describes the concept of a Smart Derivative Contract (SDC) with the central aim to detach bilateral financial transactions from counterparty credit risk and to remove complexities
in bilateral post-trade processing by a complete redesign.

### Concept of a Smart Derivative Contract

A Smart Derivative Contract is a deterministic settlement protocol with the same economic behaviour as a Financial Contract - e.g. an OTC-Derivative or a Bond.
Every process state is specified; therefore, the trade and post-trade process is known in advance and is deterministic over the trade&apos;s life cycle. An [ERC-20](/EIPs/EIPS/eip-20) token can be used for frictionless decentralized settlement, see reference implementation. We do provide a separate interface and implementation for a specific &quot;Settlement Token&quot; derived from [ERC-20](/EIPs/EIPS/eip-20).
These features enable two or multiple trade parties to process their financial contracts fully decentralized without relying on a third central intermediary agent.
The process logic of SDC can be implemented as a finite state machine on solidity.

### Applications

The interface&apos;s life cycle functionality applies to several use cases.

#### Settle-to-Market OTC Derivative

In the case of a settle-to-market OTC derivative, an SDC settles the outstanding net present value of the underlying financial contract on a frequent (e.g. daily) basis. With each settlement cycle, the net present value of the underlying contract is exchanged, and the value of the contract is reset to zero. Pre-agreed margin buffers are locked at the beginning of each settlement cycle so that settlement will be guaranteed up to a certain amount.
If a counterparty fails to obey contract rules, e.g. not providing sufficient pre-funding, SDC will terminate automatically with the guaranteed transfer of a termination fee by the causing party.
We provide a reference implementation for this case.

#### Callateralized OTC Derivative

An implementation variante of the protocol can be used to realize a collateralized OTC derivative.[^2]
Here the contract manages separate collateral and cash tokens.
The constructions allows to eliminate the risk of under-collateralization.
Thus, a separate initial margin is not required.

#### Defaultable OTC Derivative

A defaultable OTC Derivative has no Collateral Process in place. In that case, a smart derivative will settle the according cash flows as determined in the derivative contract specification. A defaultable OTC derivative might end in
a state &apos;Failure to Pay&apos; if a settlement cannot be conducted.

#### Smart Bond Contract

The life cycle of a bond can also make use of the function catalogue below. The interface enables the issuer to allocate and redeem the bond as well as settle coupon payments. On the other hand, it allows bondholders to interact with each other, conducting secondary market trades. It all boils down to a settlement phase, which needs to be pre-agreed by both parties or triggered by the issuer
which can be processed in a completely frictionless way.

## Specification

The methods and event are separated into different interfaces:

- `ISDCTrade` - events and functions related to trade inception, confirmation and termination.
- `ISDCSettlement` - events and functions related to the settlement life-cycle of a trade.
- `IAsyncTransferCallback` - events and the callback function `afterTransfer` for settlements that utilize and external payment system.
- `IAsyncTransfer` - events and functions related to async transfer (e.g., for external payment systems).

The `ISDC` interface is the aggregation of `ISDCTrade`, `ISDCSettlement` and `IAsyncTransferCallback`.

### Methods of `ISDCTrade`

The following methods specify a Smart Derivative Contract&apos;s trade initiation, trade termination and settlement life cycle. For further information, please also look at the interface documentation `ISDC.sol`.

#### Trade Initiation Phase: `inceptTrade`

A party can initiate a trade by providing the party address to trade with, trade data, trade position, payment amount for the trade and initial settlement data. Only registered counterparties are allowed to use that function.

```solidity
function inceptTrade(address withParty, string memory tradeData, int position, int256 paymentAmount, string memory initialSettlementData) external returns (string memory);
```

The position and the paymentAmount are viewed from the incepter.
The function will return a generated unique `tradeId`. The trade id will also be emitted by an event.

#### Trade Initiation Phase: `confirmTrade`

A counterparty can confirm a trade by providing its trade specification data, which then gets matched against the data stored from `inceptTrade` call.

```solidity
function confirmTrade(address withParty, string memory tradeData, int position, int256 paymentAmount, string memory initialSettlementData) external;
```

Here, the position and the paymentAmount is viewed from the confimer (opposite sign compared to the call to `inceptTrade`).

#### Trade Initiation Phase: `cancelTrade`

The counterparty that called `inceptTrade` has the option to cancel the trade, e.g., in the case where the trade is not confirmed in a timely manner.

```solidity
function cancelTrade(address withParty, string memory tradeData, int position, int256 paymentAmount, string memory initialSettlementData) external;
```

#### Trade Termination: `requestTermination`

Allows an eligible party to request a mutual termination of the trade with the corresponding `tradeId` with a termination amount she is willing to pay and provide further termination terms (e.g. an XML)

```solidity
function requestTradeTermination(string memory tradeId, int256 terminationPayment, string memory terminationTerms) external;
```

#### Trade Termination: `confirmTradeTermination`

Allows an eligible party to confirm a previously requested (mutual) trade termination, including termination payment value and termination terms

```solidity
function confirmTradeTermination(string memory tradeId, int256 terminationPayment, string memory terminationTerms) external;
```

#### Trade Termination: `cancelTradeTermination`

The party that initiated `requestTradeTermination` has the option to withdraw the request, e.g., in the case where the termination is not confirmed in a timely manner.

```solidity
function cancelTradeTermination(string memory tradeId, int256 terminationPayment, string memory terminationTerms) external;
```

### Methods of `ISDCSettlement`

#### Settlement Phase: `initiateSettlement`

Allows eligible participants (such as counterparties or a delegated agent) to trigger a settlement phase.

```solidity
function initiateSettlement() external;
```

#### Settlement Phase: `performSettlement`

Valuation may be provided on-chain or off-chain via an external oracle service that calculates the settlement or coupon amounts and uses external market data.
This method serves as a callback called from an external oracle providing settlement amount and used settlement data, which also get stored.
The settlement amount will be checked according to contract terms, resulting in either a regular settlement or a termination of the trade.

The method may perform a synchonous transfer of the settlement or make use of an `IAsyncTransfer`, which will finalize the
transfer though the callback `afterTransfer`.

The transactionData is emitted as part of the corresponding event: `SettlementTransferred` or `SettlementFailed`
This might result in a termination or start of the next settlement phase, depending on the provided success flag.

The parameter `settlementData` will be ussed as `lastSettlementData` as part of the `SettlementRequested` event (see there)
and may contain updates to the determination of the next settlement, e.g., data to determine the reference value for margining or
the specification of updated margin buffer values.

```solidity
function performSettlement(int256 settlementAmount, string memory settlementData) external;
```

#### Settlement Phase: `afterSettlement`

The method is called to verify and prepare the next settlement and move to that phase.
The method may trigger optional checks (e.g. pre-funding check).

Depending on the implementation, this method may be called automatically at the end of performSettlement
or called externally (e.g. from a time-oracle to allow for a time-period to prepare the next settlement).

- An implementation that uses adjusting of pre-funding can check the pre-funding within this method.
- An implementation that checked a static pre-funding upon confirmation of the trade might not require this step. 

In any case, the method may trigger termination if the settlement failed.

Emits a `SettlementTransferred` or a `SettlementFailed` event. May emit a `TradeTerminated` event.

```solidity
function afterSettlement() external;
```

### Methods of `IAsyncTransferCallback`

#### Settlement Phase: `afterTransfer`

This method is called back from a settlement token or from an eligible address if the transfer of the settlement
amount was successful. - completes the settlement transfer.
The transactionData is emitted as part of the corresponding event: `SettlementTransferred` or `SettlementFailed`
This might result in a termination or start of the next settlement phase, depending on the provided success flag.

```solidity
function afterTransfer(bool success, uint256 transactionID, string memory transactionData) external;
```

### Trade Events

The following events are emitted during an SDC Trade life-cycle.

#### TradeIncepted

Emitted on trade inception - method &apos;inceptTrade&apos;

```solidity
event TradeIncepted(address initiator, string tradeId, string tradeData);
```

#### TradeConfirmed

Emitted on trade confirmation - method &apos;confirmTrade&apos;

```solidity
event TradeConfirmed(address confirmer, string tradeId);
```

#### TradeCanceled

Emitted on trade cancellation - method &apos;cancelTrade&apos;

```solidity
event TradeCanceled(address initiator, string tradeId);
```

#### TradeActivated

Emitted when a Trade is activated

```solidity
event TradeActivated(string tradeId);
```

#### TradeTerminationRequest

Emitted when termination request is initiated by a counterparty

```solidity
event TradeTerminationRequest(address initiator, string tradeId, int256 terminationPayment, string terminationTerms);
```

#### TradeTerminationConfirmed

Emitted when termination request is confirmed by a counterparty

```solidity
event TradeTerminationConfirmed(address confirmer, string tradeId, int256 terminationPayment, string terminationTerms);
```

#### TradeTerminationCanceled

Emitted when termination request is canceled by the requesting counterparty

```solidity
event TradeTerminationCanceled(address initiator, string tradeId, string terminationTerms);
```

#### TradeTerminated

Emitted when trade is terminated

```solidity
event TradeTerminated(string cause);
```


### Settlement Events

The following events are emitted during the settlement phases.

#### SettlementRequested

Emitted when a settlement is requested (via `initiateSettlement`). May trigger the settlement phase.

The argument `lastSettlementData` is the one that was passed upon a previous settlement
in `performSettlement` (under the name `settlementData`). It may be used to pass updated settlement
specific information calculated during the previous settlement, e.g., when margin buffer amounts are a function
of market parameters. In case of an external oracle it can pass the `settlementData` via `performSettlement`
and pick it up in the `SettlementRequested` event (allows for stateless external oracles).

```solidity
event SettlementRequested(address initiator, string tradeData, string lastSettlementData);
```

#### SettlementDetermined

Emitted when the settlement phase is started (via `performSettlement`).

```solidity
event SettlementDetermined(address initiator, int256 settlementAmount, string settlementData);
```

#### SettlementTransferred

Emitted when the settlement succeeded.

```solidity
event SettlementTransferred(string transactionData);
```

#### SettlementFailed

Emitted when the settlement failed.

```solidity
event SettlementFailed(string transactionData);
```


## Rationale

The interface design and reference implementation are based on the following considerations:

- An SDC protocol enables interacting parties to initiate and process a financial transaction in a bilateral and deterministic manner. Settlement and Counterparty Risk is managed by the contract.
- The provided interface specification is supposed to completely reflect the entire trade life cycle.
- The interface specification is generic enough to handle the case that parties process one or even multiple financial transactions (on a netted base)
- Usually, the valuation of financial trades (e.g. OTC Derivatives) will require advanced valuation methodology to determine the market value. This is why the concept might rely on an external market data source and hosted valuation algorithms
- A pull-based valuation-based oracle pattern can be implemented by using the provided callback pattern (methods: `initiateSettlement`, `performSettlement`)
- The reference implementation `SDCSingleTrade.sol` considers a single trade and is based on a state-machine pattern where the states also serve as guards (via modifiers) to check which method is allowed to be called at a particular given process and trade state
- The interface allows the extension to multiple trades with common (netted) settlement.

### State diagram of trade and process states

![image info](/EIPs/assets/eip-6123/doc/sdc_trade_states.svg)

The diagram shows the trade states of a single trade SDC as in `SDCSingleTrade.sol`.

### Sequence diagram of reference implementation &apos;SDCPledgedBalance.sol&apos;

The following sequence diagram shows the function calls that create the trade and stellement state transitions
and the emitted events.  Shown is the implementation variante that

- utilizes an asynchronous settlement through a settlement token (see the interface `IAsyncTransfer`, `IAsyncTransferCallback`)
- receives the trigger `afterSettlement` to perfrom checks of settlement pre-conditions (see the corresponding method description `afterSettlement`)

![image info](/EIPs/assets/eip-6123/doc/sequence.svg)

### Sequence diagram of an implementation variant with a separate collateral account

The following sequence diagram shows the implementation variant with a separate collateral account.
This diagram show the settlement phase.

![image info](/EIPs/assets/eip-6123/doc/sequence-sdc-collateral-settlement.svg)

## Test Cases

Life-cycle unit tests based on the sample implementation and usage of [ERC-20](/EIPs/EIPS/eip-20) token is provided. See file [test/SDCTests.js](/EIPs/assets/eip-6123/test/SDCTests.js)
).

## Reference Implementation

An abstract contract class `SDCSingleTrade.sol` for single trade SDCs as well as a full reference implementation SDCPledgedBalance.sol for an OTC-Derivative is provided and is based on the [ERC-20](/EIPs/EIPS/eip-20) token standard.
See folder `/assets/contracts`, more explanation on the implementation is provided inline.

### Trade Data Specification (suggestion)

Please take a look at the provided xml file as a suggestion on how trade parameters could be stored.

## Security Considerations

No known security issues up to now.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[^1]:
```csl-json
    {
        &quot;type&quot;: &quot;article-journal&quot;,
        &quot;id&quot;: &quot;ssrn-3163074&quot;,
        &quot;title&quot;: &quot;Smart Derivative Contracts (Detaching Transactions from Counterparty Credit Risk: Specification, Parametrisation, Valuation)&quot;,
        &quot;author&quot;: [
        { &quot;family&quot;: &quot;Fries&quot;, &quot;given&quot;: &quot;Christian P.&quot; },
        { &quot;family&quot;: &quot;Kohl-Landgraf&quot;, &quot;given&quot;: &quot;Peter&quot; }
        ],
        &quot;container-title&quot;: &quot;SSRN Electronic Journal&quot;,
        &quot;DOI&quot;: &quot;10.2139/ssrn.3163074&quot;,
        &quot;ISSN&quot;: &quot;1556-5068&quot;,
        &quot;URL&quot;: &quot;https://ssrn.com/abstract=3163074&quot;,
        &quot;issued&quot;: { &quot;date-parts&quot;: [[2018, 4, 24]] },
        &quot;original-date&quot;: { &quot;date-parts&quot;: [[2018, 4, 15]] },
        &quot;note&quot;: &quot;Last revised: 2019-01-09&quot;,
        &quot;number-of-pages&quot;: &quot;22&quot;,
        &quot;keyword&quot;: &quot;Collateralization, CCP, Initial Margin, Smart Contract, Settlement Risk, Gap Risk&quot;,
        &quot;language&quot;: &quot;en&quot;,
        &quot;source&quot;: &quot;SSRN&quot;
    }
```

[^2]:
```csl-json
    {
        &quot;type&quot;: &quot;article-journal&quot;,
        &quot;id&quot;: &quot;ssrn-5454714&quot;,
        &quot;title&quot;: &quot;A Smart Derivative Contract with Collateral&quot;,
        &quot;author&quot;: [
        { &quot;family&quot;: &quot;Fries&quot;, &quot;given&quot;: &quot;Christian P.&quot; },
        { &quot;family&quot;: &quot;Kohl-Landgraf&quot;, &quot;given&quot;: &quot;Peter&quot; },
        { &quot;family&quot;: &quot;Prandtl&quot;, &quot;given&quot;: &quot;Raphael&quot; },
        { &quot;family&quot;: &quot;Schütte&quot;, &quot;given&quot;: &quot;Wilfried&quot; }
        ],
        &quot;container-title&quot;: &quot;SSRN Electronic Journal&quot;,
        &quot;DOI&quot;: &quot;10.2139/ssrn.5454714&quot;,
        &quot;ISSN&quot;: &quot;1556-5068&quot;,
        &quot;URL&quot;: &quot;https://ssrn.com/abstract=5454714&quot;,
        &quot;issued&quot;: { &quot;date-parts&quot;: [[2025, 9, 8]] },
        &quot;original-date&quot;: { &quot;date-parts&quot;: [[2025, 8, 24]] },
        &quot;note&quot;: &quot;Last revised: 2025-09-25&quot;,
        &quot;number-of-pages&quot;: &quot;19&quot;,
        &quot;keyword&quot;: &quot;Smart Contract, Settlement, Collateralisation, ERC-6123, Counterparty Credit Risk, Repo&quot;,
        &quot;language&quot;: &quot;en&quot;,
        &quot;source&quot;: &quot;SSRN&quot;
    }
```
</description>
        <pubDate>Tue, 13 Dec 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6123</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6123</guid>
      </item>
    
      <item>
        <title>Guard of NFT/SBT, an Extension of ERC-721</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/guard-of-nft-sbt-an-extension-of-eip-721/12052</comments>
        
        <description>## Abstract

This standard is an extension of [ERC-721](/EIPs/EIPS/eip-721). It separates the holding right and transfer right of non-fungible tokens (NFTs) and Soulbound Tokens (SBTs) and defines a new role, `guard` with `expires`. The flexibility of the `guard` setting enables the design of NFT anti-theft, NFT lending, NFT leasing, SBT, etc.

## Motivation

NFTs are assets that possess both use and financial value.

Many cases of NFT theft currently exist, and current NFT anti-theft schemes, such as transferring NFTs to cold wallets, make NFTs inconvenient to be used.

In current NFT lending, the NFT owner needs to transfer the NFT to the NFT lending contract, and the NFT owner no longer has the right to use the NFT while he has obtained the loan. In the real world, for example, if a person takes out a mortgage on his own house, he still has the right to use that house.

For SBT, the current mainstream view is that an SBT is not transferable, which makes an SBT bound to an Ether address. However, when the private key of the user address is leaked or lost, retrieving SBT will become a complicated task and there is no corresponding standard. The SBTs essentially realizes the separation of NFT holding right and transfer right. When the wallet where SBT is located is stolen or unavailable, SBT should be able to be recoverable. 

In addition, SBTs still need to be managed in use. For example, if a university issues diploma-based SBTs to its graduates, and if the university later finds that a graduate has committed academic misconduct or jeopardized the reputation of the university, it should have the ability to retrieve the diploma-based SBTs.

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot; and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

ERC-721 compliant contracts MAY implement this EIP.

A guard Must be valid only before expires.

When a token has no guard or the guard is expired, `guardInfo` MUST return `(address(0), 0)`.

When a token has no guard or the guard is expired, owner, authorised operators and approved address of the token MUST have permission to set guard and expires.
  
When a token has a valid guard, owner, authorised operators and approved address of the token MUST NOT be able to change guard and expires, and they MUST NOT be able to transfer the token.
  
When a token has a valid guard, `guardInfo` MUST return the address and expires of the guard.
  
When a token has a valid guard, the guard MUST be able to remove guard and expires, change guard and expires, and transfer the token.

When a token has a valid guard, if the token burns, the guard MUST be deleted.

If issuing or minting SBTs, the guard MAY be uniformly set to the designated address to facilitate management. 

### Contract Interface
  
```solidity
 interface IERC6147 {

    /// Logged when the guard of an NFT is changed or expires is changed
    /// @notice Emitted when the `guard` is changed or the `expires` is changed
    ///         The zero address for `newGuard` indicates that there currently is no guard address
    event UpdateGuardLog(uint256 indexed tokenId, address indexed newGuard, address oldGuard, uint64 expires);
    
    /// @notice Owner, authorised operators and approved address of the NFT can set guard and expires of the NFT and
    ///         valid guard can modifiy guard and expires of the NFT
    ///         If the NFT has a valid guard role, the owner, authorised operators and approved address of the NFT
    ///         cannot modify guard and expires
    /// @dev The `newGuard` can not be zero address
    ///      The `expires` need to be valid
    ///      Throws if `tokenId` is not valid NFT
    /// @param tokenId The NFT to get the guard address for
    /// @param newGuard The new guard address of the NFT
    /// @param expires UNIX timestamp, the guard could manage the token before expires
    function changeGuard(uint256 tokenId, address newGuard, uint64 expires) external;

    /// @notice Remove the guard and expires of the NFT
    ///         Only guard can remove its own guard role and expires
    /// @dev The guard address is set to 0 address
    ///      The expires is set to 0
    ///      Throws if `tokenId` is not valid NFT
    /// @param tokenId The NFT to remove the guard and expires for
    function removeGuard(uint256 tokenId) external;
    
    /// @notice Transfer the NFT and remove its guard and expires
    /// @dev The NFT is transferred to `to` and the guard address is set to 0 address
    ///      Throws if `tokenId` is not valid NFT
    /// @param from The address of the previous owner of the NFT
    /// @param to The address of NFT recipient 
    /// @param tokenId The NFT to get transferred for
    function transferAndRemove(address from, address to, uint256 tokenId) external;

    /// @notice Get the guard address and expires of the NFT
    /// @dev The zero address indicates that there is no guard
    /// @param tokenId The NFT to get the guard address and expires for
    /// @return The guard address and expires for the NFT
   function guardInfo(uint256 tokenId) external view returns (address, uint64);   
}
  ```

The `changeGuard(uint256 tokenId, address newGuard, uint64 expires)` function MAY be implemented as `public` or `external`.

The `removeGuard(uint256 tokenId)` function MAY be implemented as `public` or `external`.

The `transferAndRemove(address from,address to,uint256 tokenId)` function MAY be implemented as `public` or `external`.

The `guardInfo(uint256 tokenId)` function MAY be implemented as `pure` or `view`.

The `UpdateGuardLog` event MUST be emitted when a guard is changed.

The `supportsInterface` method MUST return `true` when called with `0xb61d1057`.

## Rationale 

### Universality

There are many application scenarios for NFT/SBT, and there is no need to propose a dedicated EIP for each one, which would make the overall number of EIPS inevitably increase and add to the burden of developers. The standard is based on the analysis of the right attached to assets in the real world, and abstracts the right attached to NFT/SBT into holding right and transfer right making the standard more universal.

For example, the standard has more than the following use cases:

SBTs. The SBTs issuer can assign a uniform role of `guard` to the SBTs before they are minted, so that the SBTs cannot be transferred by the corresponding holders and can be managed by the SBTs issuer through the `guard`.

NFT anti-theft. If an NFT holder sets a `guard` address of an NFT as his or her own cold wallet address, the NFT can still be used by the NFT holder, but the risk of theft is greatly reduced.

NFT lending. The borrower sets the `guard` of his or her own NFT as the lender&apos;s address, the borrower still has the right to use the NFT while obtaining the loan, but at the same time cannot transfer or sell the NFT. If the borrower defaults on the loan, the lender can transfer and sell the NFT.

Additionally, by setting an `expires` for the `guard`, the scalability of the protocol is further enhanced, as demonstrated in the following examples:

More flexible NFT issuance. During NFT minting, discounts can be offered for NFTs that are locked for a certain period of time, without affecting the NFTs&apos; usability.

More secure NFT management. Even if the `guard` address becomes inaccessible due to lost private keys, the `owner` can still retrieve the NFT after the `guard` has expired.

Valid SBTs. Some SBTs have a period of use. More effective management can be achieved through `guard` and `expires`.

### Extensibility
  
This standard only defines a `guard` and its `expires`. For complex functions needed by NFTs and SBTs, such as social recovery and multi-signature, the `guard` can be set as a third-party protocol address. Through the third-party protocol, more flexible and diverse functions can be achieved based on specific application scenarios. 

### Naming

The alternative names are `guardian` and `guard`, both of which basically match the permissions corresponding to the role: protection of NFT or necessary management according to its application scenarios. The `guard` has fewer characters than the `guardian` and is more concise.

## Backwards Compatibility

This standard can be fully ERC-721 compatible by adding an extension function set.

If an NFT issued based on the above standard does not set a `guard`, then it is no different in the existing functions from the current NFT issued based on the ERC-721 standard.

## Reference Implementation
  
```solidity

// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.8;

import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;
import &quot;./IERC6147.sol&quot;;

abstract contract ERC6147 is ERC721, IERC6147 {

    /// @dev A structure representing a token of guard address and expires
    /// @param guard address of guard role
    /// @param expirs UNIX timestamp, the guard could manage the token before expires
    struct GuardInfo{
        address guard;
        uint64 expires;
    }
    
    mapping(uint256 =&gt; GuardInfo) internal _guardInfo;

    /// @notice Owner, authorised operators and approved address of the NFT can set guard and expires of the NFT and
    ///         valid guard can modifiy guard and expires of the NFT
    ///         If the NFT has a valid guard role, the owner, authorised operators and approved address of the NFT
    ///         cannot modify guard and expires
    /// @dev The `newGuard` can not be zero address
    ///      The `expires` need to be valid
    ///      Throws if `tokenId` is not valid NFT
    /// @param tokenId The NFT to get the guard address for
    /// @param newGuard The new guard address of the NFT
    /// @param expires UNIX timestamp, the guard could manage the token before expires
    function changeGuard(uint256 tokenId, address newGuard, uint64 expires) public virtual{
        require(expires &gt; block.timestamp, &quot;ERC6147: invalid expires&quot;);
        _updateGuard(tokenId, newGuard, expires, false);
    }

    /// @notice Remove the guard and expires of the NFT
    ///         Only guard can remove its own guard role and expires
    /// @dev The guard address is set to 0 address
    ///      The expires is set to 0
    ///      Throws if `tokenId` is not valid NFT
    /// @param tokenId The NFT to remove the guard and expires for
    function removeGuard(uint256 tokenId) public virtual  {
        _updateGuard(tokenId, address(0), 0, true);
    }
    
    /// @notice Transfer the NFT and remove its guard and expires
    /// @dev The NFT is transferred to `to` and the guard address is set to 0 address
    ///      Throws if `tokenId` is not valid NFT
    /// @param from The address of the previous owner of the NFT
    /// @param to The address of NFT recipient 
    /// @param tokenId The NFT to get transferred for
    function transferAndRemove(address from, address to, uint256 tokenId) public virtual {
        safeTransferFrom(from, to, tokenId);
        removeGuard(tokenId);
    }
    
    /// @notice Get the guard address and expires of the NFT
    /// @dev The zero address indicates that there is no guard
    /// @param tokenId The NFT to get the guard address and expires for
    /// @return The guard address and expires for the NFT
    function guardInfo(uint256 tokenId) public view virtual returns (address, uint64) {
        if(_guardInfo[tokenId].expires &gt;= block.timestamp){
            return (_guardInfo[tokenId].guard, _guardInfo[tokenId].expires);
        }
        else{
            return (address(0), 0);
        }
    }

    /// @notice Update the guard of the NFT
    /// @dev Delete function: set guard to 0 address and set expires to 0; 
    ///      and update function: set guard to new address and set expires
    ///      Throws if `tokenId` is not valid NFT
    /// @param tokenId The NFT to update the guard address for
    /// @param newGuard The newGuard address
    /// @param expires UNIX timestamp, the guard could manage the token before expires
    /// @param allowNull Allow 0 address
    function _updateGuard(uint256 tokenId, address newGuard, uint64 expires, bool allowNull) internal {
        (address guard,) = guardInfo(tokenId);
        if (!allowNull) {
            require(newGuard != address(0), &quot;ERC6147: new guard can not be null&quot;);
        }
        if (guard != address(0)) { 
            require(guard == _msgSender(), &quot;ERC6147: only guard can change it self&quot;); 
        } else { 
            require(_isApprovedOrOwner(_msgSender(), tokenId), &quot;ERC6147: caller is not owner nor approved&quot;);
        } 

        if (guard != address(0) || newGuard != address(0)) {
            _guardInfo[tokenId] = GuardInfo(newGuard,expires);
            emit UpdateGuardLog(tokenId, newGuard, guard, expires);
        }
    }
    
    /// @notice Check the guard address
    /// @dev The zero address indicates there is no guard
    /// @param tokenId The NFT to check the guard address for
    /// @return The guard address
    function _checkGuard(uint256 tokenId) internal view returns (address) {
        (address guard, ) = guardInfo(tokenId);
        address sender = _msgSender();
        if (guard != address(0)) {
            require(guard == sender, &quot;ERC6147: sender is not guard of the token&quot;);
            return guard;
        }else{
            return address(0);
        }
    }
 
    /// @dev Before transferring the NFT, need to check the gurard address
    function transferFrom(address from, address to, uint256 tokenId) public virtual override {
        address guard;
        address new_from = from;
        if (from != address(0)) {
            guard = _checkGuard(tokenId);
            new_from = ownerOf(tokenId);
        }
        if (guard == address(0)) {
            require(
                _isApprovedOrOwner(_msgSender(), tokenId),
                &quot;ERC721: transfer caller is not owner nor approved&quot;
            );
        }
        _transfer(new_from, to, tokenId);
    }

    /// @dev Before safe transferring the NFT, need to check the gurard address
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {
        address guard;
        address new_from = from;
        if (from != address(0)) {
            guard = _checkGuard(tokenId);
            new_from = ownerOf(tokenId);
        }
        if (guard == address(0)) {
            require(
                _isApprovedOrOwner(_msgSender(), tokenId),
                &quot;ERC721: transfer caller is not owner nor approved&quot;
            );
        }
        _safeTransfer(from, to, tokenId, _data);
    }

    /// @dev When burning, delete `token_guard_map[tokenId]`
    /// This is an internal function that does not check if the sender is authorized to operate on the token.
    function _burn(uint256 tokenId) internal virtual override {
        (address guard, )=guardInfo(tokenId);
        super._burn(tokenId);
        delete _guardInfo[tokenId];
        emit UpdateGuardLog(tokenId, address(0), guard, 0);
    }

    /// @dev See {IERC165-supportsInterface}.
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC6147).interfaceId || super.supportsInterface(interfaceId);
    }
}

```

## Security Considerations

Make sure to set an appropriate `expires` for the `guard`, based on the specific application scenario.

When an NFT has a valid guard, even if an address is authorized as an operator through `approve` or `setApprovalForAll`, the operator still has no right to transfer the NFT.

When an NFT has a valid guard, the `owner` cannot sell the NFT. Some trading platforms list NFTs through `setApprovalForAll` and owners&apos; signature. It is recommended to prevent listing these NFTs by checking `guardInfo`.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 07 Dec 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6147</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6147</guid>
      </item>
    
      <item>
        <title>Hierarchical NFTs</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6150-hierarchical-nfts-an-extension-to-erc-721/12173</comments>
        
        <description>## Abstract

This standard is an extension to [EIP-721](/EIPs/EIPS/eip-721). It proposes a multi-layer filesystem-like hierarchical NFTs. This standard provides interfaces to get parent NFT or children NFTs and whether NFT is a leaf node or root node, maintaining the hierarchical relationship among them.

## Motivation

This EIP standardizes the interface of filesystem-like hierarchical NFTs and provides a reference implementation.

Hierarchy structure is commonly implemented for file systems by operating systems such as Linux Filesystem Hierarchy (FHS).

![Linux Hierarchical File Structure](/EIPs/assets/eip-6150/linux-hierarchy.png)

Websites often use a directory and category hierarchy structure, such as eBay (Home -&gt; Electronics -&gt; Video Games -&gt; Xbox -&gt; Products), and Twitter (Home -&gt; Lists -&gt; List -&gt; Tweets), and Reddit (Home -&gt; r/ethereum -&gt; Posts -&gt; Hot).

![Website Hierarchical Structure](/EIPs/assets/eip-6150/website-hierarchy.png)

A single smart contract can be the `root`, managing every directory/category as individual NFT and hierarchy relations of NFTs. Each NFT&apos;s `tokenURI` may be another contract address, a website link, or any form of metadata.

The advantages and the advancement of the Ethereum ecosystem of using this standard include:

- Complete on-chain storage of hierarchy, which can also be governed on-chain by additional DAO contract
- Only need a single contract to manage and operate the hierarchical relations
- Transferrable directory/category ownership as NFT, which is great for use cases such as on-chain forums
- Easy and permissionless data access to the hierarchical structure by front-end
- Ideal structure for traditional applications such as e-commerce, or forums
- Easy-to-understand interfaces for developers, which are similar to Linux filesystem commands in concept

The use cases can include:

- On-chain forum, like Reddit
- On-chain social media, like Twitter
- On-chain corporation, for managing organizational structures
- On-chain e-commerce platforms, like eBay or individual stores
- Any application with tree-like structures

In the future, with the development of the data availability solutions of Ethereum and an external permissionless data retention network, the content (posts, listed items, or tweets) of these platforms can also be entirely stored on-chain, thus realizing fully decentralized applications.

## Specification

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

Every compliant contract must implement this proposal, [EIP-721](/EIPs/EIPS/eip-721) and [EIP-165](/EIPs/EIPS/eip-165) interfaces.

```solidity
pragma solidity ^0.8.0;

// Note: the ERC-165 identifier for this interface is 0x897e2c73.
interface IERC6150 /* is IERC721, IERC165 */ {
    /**
     * @notice Emitted when `tokenId` token under `parentId` is minted.
     * @param minter The address of minter
     * @param to The address received token
     * @param parentId The id of parent token, if it&apos;s zero, it means minted `tokenId` is a root token.
     * @param tokenId The id of minted token, required to be greater than zero
     */
    event Minted(
        address indexed minter,
        address indexed to,
        uint256 parentId,
        uint256 tokenId
    );

    /**
     * @notice Get the parent token of `tokenId` token.
     * @param tokenId The child token
     * @return parentId The Parent token found
     */
    function parentOf(uint256 tokenId) external view returns (uint256 parentId);

    /**
     * @notice Get the children tokens of `tokenId` token.
     * @param tokenId The parent token
     * @return childrenIds The array of children tokens
     */
    function childrenOf(
        uint256 tokenId
    ) external view returns (uint256[] memory childrenIds);

    /**
     * @notice Check the `tokenId` token if it is a root token.
     * @param tokenId The token want to be checked
     * @return Return `true` if it is a root token; if not, return `false`
     */
    function isRoot(uint256 tokenId) external view returns (bool);

    /**
     * @notice Check the `tokenId` token if it is a leaf token.
     * @param tokenId The token want to be checked
     * @return Return `true` if it is a leaf token; if not, return `false`
     */
    function isLeaf(uint256 tokenId) external view returns (bool);
}
```

Optional Extension: Enumerable

```solidity
// Note: the ERC-165 identifier for this interface is 0xba541a2e.
interface IERC6150Enumerable is IERC6150 /* IERC721Enumerable */ {
    /**
     * @notice Get total amount of children tokens under `parentId` token.
     * @dev If `parentId` is zero, it means get total amount of root tokens.
     * @return The total amount of children tokens under `parentId` token.
     */
    function childrenCountOf(uint256 parentId) external view returns (uint256);

    /**
     * @notice Get the token at the specified index of all children tokens under `parentId` token.
     * @dev If `parentId` is zero, it means get root token.
     * @return The token ID at `index` of all chlidren tokens under `parentId` token.
     */
    function childOfParentByIndex(
        uint256 parentId,
        uint256 index
    ) external view returns (uint256);

    /**
     * @notice Get the index position of specified token in the children enumeration under specified parent token.
     * @dev Throws if the `tokenId` is not found in the children enumeration.
     * If `parentId` is zero, means get root token index.
     * @param parentId The parent token
     * @param tokenId The specified token to be found
     * @return The index position of `tokenId` found in the children enumeration
     */
    function indexInChildrenEnumeration(
        uint256 parentId,
        uint256 tokenId
    ) external view returns (uint256);
}
```

Optional Extension: Burnable

```solidity
// Note: the ERC-165 identifier for this interface is 0x4ac0aa46.
interface IERC6150Burnable is IERC6150 {
    /**
     * @notice Burn the `tokenId` token.
     * @dev Throws if `tokenId` is not a leaf token.
     * Throws if `tokenId` is not a valid NFT.
     * Throws if `owner` is not the owner of `tokenId` token.
     * Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for this token.
     * @param tokenId The token to be burnt
     */
    function safeBurn(uint256 tokenId) external;

    /**
     * @notice Batch burn tokens.
     * @dev Throws if one of `tokenIds` is not a leaf token.
     * Throws if one of `tokenIds` is not a valid NFT.
     * Throws if `owner` is not the owner of all `tokenIds` tokens.
     * Throws unless `msg.sender` is the current owner, an authorized operator, or the approved address for all `tokenIds`.
     * @param tokenIds The tokens to be burnt
     */
    function safeBatchBurn(uint256[] memory tokenIds) external;
}
```

Optional Extension: ParentTransferable

```solidity
// Note: the ERC-165 identifier for this interface is 0xfa574808.
interface IERC6150ParentTransferable is IERC6150 {
    /**
     * @notice Emitted when the parent of `tokenId` token changed.
     * @param tokenId The token changed
     * @param oldParentId Previous parent token
     * @param newParentId New parent token
     */
    event ParentTransferred(
        uint256 tokenId,
        uint256 oldParentId,
        uint256 newParentId
    );

    /**
     * @notice Transfer parentship of `tokenId` token to a new parent token
     * @param newParentId New parent token id
     * @param tokenId The token to be changed
     */
    function transferParent(uint256 newParentId, uint256 tokenId) external;

    /**
     * @notice Batch transfer parentship of `tokenIds` to a new parent token
     * @param newParentId New parent token id
     * @param tokenIds Array of token ids to be changed
     */
    function batchTransferParent(
        uint256 newParentId,
        uint256[] memory tokenIds
    ) external;
}
```

Optional Extension: Access Control

```solidity
// Note: the ERC-165 identifier for this interface is 0x1d04f0b3.
interface IERC6150AccessControl is IERC6150 {
    /**
     * @notice Check the account whether a admin of `tokenId` token.
     * @dev Each token can be set more than one admin. Admin have permission to do something to the token, like mint child token,
     * or burn token, or transfer parentship.
     * @param tokenId The specified token
     * @param account The account to be checked
     * @return If the account has admin permission, return true; otherwise, return false.
     */
    function isAdminOf(uint256 tokenId, address account)
        external
        view
        returns (bool);

    /**
     * @notice Check whether the specified parent token and account can mint children tokens
     * @dev If the `parentId` is zero, check whether account can mint root nodes
     * @param parentId The specified parent token to be checked
     * @param account The specified account to be checked
     * @return If the token and account has mint permission, return true; otherwise, return false.
     */
    function canMintChildren(
        uint256 parentId,
        address account
    ) external view returns (bool);

    /**
     * @notice Check whether the specified token can be burnt by specified account
     * @param tokenId The specified token to be checked
     * @param account The specified account to be checked
     * @return If the tokenId can be burnt by account, return true; otherwise, return false.
     */
    function canBurnTokenByAccount(uint256 tokenId, address account)
        external
        view
        returns (bool);
}
```

## Rationale

As mentioned in the abstract, this EIP&apos;s goal is to have a simple interface for supporting Hierarchical NFTs. Here are a few design decisions and why they were made:

### Relationship between NFTs

All NFTs will make up a hierarchical relationship tree. Each NFT is a node of the tree, maybe as a root node or a leaf node, as a parent node or a child node.

This proposal standardizes the event `Minted` to indicate the parent and child relationship when minting a new node. When a root node is minted, parentId should be zero. That means a token id of zero could not be a real node. So a real node token id must be greater than zero.

In a hierarchical tree, it&apos;s common to query upper and lower nodes. So this proposal standardizes function `parentOf` to get the parent node of the specified node and standardizes function `childrenOf` to get all children nodes.

Functions `isRoot` and `isLeaf` can check if one node is a root node or a leaf node, which would be very useful for many cases.

### Enumerable Extension

This proposal standardizes three functions as an extension to support enumerable queries involving children nodes. Each function all have param `parentId`, for compatibility, when the `parentId` specified zero means query root nodes.

### ParentTransferable Extension

In some cases, such as filesystem, a directory or a file could be moved from one directory to another. So this proposal adds ParentTransferable Extension to support this situation.

### Access Control

In a hierarchical structure, usually, there is more than one account has permission to operate a node, like mint children nodes, transfer node, burn node. This proposal adds a few functions as standard to check access control permissions.

## Backwards Compatibility

This proposal is fully backward compatible with [EIP-721](/EIPs/EIPS/eip-721).

## Reference Implementation

Implementation: [EIP-6150](/EIPs/assets/eip-6150/contracts/ERC6150.sol)

## Security Considerations

No security considerations were found.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 15 Dec 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6150</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6150</guid>
      </item>
    
      <item>
        <title>Cross-Chain Messaging Interface</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/cross-chain-messaging-standard/12197</comments>
        
        <description>## Abstract

This EIP introduces a common interface for cross-chain arbitrary message bridges (AMBs) to send and receive a cross-chain message (state).

## Motivation

Currently, cross-chain arbitrary message bridges lack standardization, resulting in complex competing implementations: Layerzero, Hyperlane, Axelar, Wormhole, Matic State Tunnel and others. Either chain native (or) seperate message bridge, the problem prevails. Adding a common standardized interface to the arbitrary message bridges provides these benefits:

- **Ease Of Development:** A common standard interface would help developers build scalable cross-chain applications with ease.

- **Improved Scalability:** Cross-chain applications can efficiently use multiple message bridges.

- **Improved Security:** Confronting security to specific parameters. At present, every message bridge has its diverse security variable. E.g., In Layerzero, the nonce is used to prevent a replay attack, whereas Hyperlane uses the Merkle root hash. 

- **Improved Robustness:** Message bridges involving off-chain components are not censorship-resistant and are prone to downtimes. Hence, apps built on top of them have no choice but to migrate their entire state (which is highly impossible for large complex applications).

## Specification

The keywords &quot;MUST,&quot; &quot;MUST NOT,&quot; &quot;REQUIRED,&quot; &quot;SHALL,&quot; &quot;SHALL NOT,&quot; &quot;SHOULD,&quot; &quot;SHOULD NOT,&quot; &quot;RECOMMENDED,&quot; &quot;MAY,&quot; and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

Every compliant cross-chain arbitrary message bridge must implement the following interface.

``` solidity
// SPDX-License-Identifier: Apache-3.0

pragma solidity &gt;=0.8.0;

/// @title Cross-Chain Messaging interface
/// @dev Allows seamless interchain messaging.
/// @author Sujith Somraaj
/// Note: Bytes are used throughout the implementation to support non-evm chains.

interface IEIP6170 {
    /// @dev This emits when a cross-chain message is sent.
    /// Note: MessageSent MUST trigger when a message is sent, including zero bytes transfers.
    event MessageSent(
        bytes to,
        bytes toChainId,
        bytes message,
        bytes extraData
    );

    /// @dev This emits when a cross-chain message is received.
    /// MessageReceived MUST trigger on any successful call to receiveMessage(bytes chainId, bytes sender, bytes message) function.
    event MessageReceived(bytes from, bytes fromChainId, bytes message);

    /// @dev Sends a message to a receiving address on a different blockchain.
    /// @param chainId_ is the unique identifier of receiving blockchain.
    /// @param receiver_ is the address of the receiver.
    /// @param message_ is the arbitrary message to be delivered.
    /// @param data_ is a bridge-specific encoded data for off-chain relayer infrastructure.
    /// @return the status of the process on the sending chain.
    /// Note: this function is designed to support both evm and non-evm chains
    /// Note: proposing chain-ids be the bytes encoding their native token name string. For eg., abi.encode(&quot;ETH&quot;), abi.encode(&quot;SOL&quot;) imagining they cannot override.
    function sendMessage(
        bytes memory chainId_,
        bytes memory receiver_,
        bytes memory message_,
        bytes memory data_
    ) external payable returns (bool);

    /// @dev Receives a message from a sender on a different blockchain.
    /// @param chainId_ is the unique identifier of the sending blockchain.
    /// @param sender_ is the address of the sender.
    /// @param message_ is the arbitrary message sent by the sender.
    /// @param data_ is an additional parameter to be used for security purposes. E.g, can send nonce in layerzero.
    /// @return the status of message processing/storage.
    /// Note: sender validation (or) message validation should happen before processing the message.
    function receiveMessage(
        bytes memory chainId_,
        bytes memory sender_,
        bytes memory message_,
        bytes memory data_
    ) external payable returns (bool);
}
```

## Rationale

The cross-chain arbitrary messaging interface will optimize the interoperability layer between blockchains with a feature-complete yet minimal interface. The light-weighted approach also provides arbitrary message bridges, and the freedom of innovating at the relayer level, to show their technical might.

The EIP will make blockchains more usable and scalable. It opens up the possibilities for building cross-chain applications by leveraging any two blockchains, not just those limited to Ethereum and compatible L2s. To put this into perspective, an easy-to-communicate mechanism will allow developers to build cross-chain applications across Ethereum and Solana, leveraging their unique advantages.

The interface also aims to reduce the risks of a single point of failure (SPOF) for applications/protocols, as they can continue operating by updating their AMB address.

## Security Considerations

Fully permissionless messaging could be a security threat to the protocol. It is recommended that all the integrators review the implementation of messaging tunnels before integrating.

Without sender authentication, anyone could write arbitrary messages into the receiving smart contract.

This EIP focuses only on how the messages should be sent and received with a specific standard. But integrators can implement any authentication (or) message tunnel-specific operations inside the receive function leveraging `data_` parameter.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE)
</description>
        <pubDate>Mon, 19 Dec 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6170</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6170</guid>
      </item>
    
      <item>
        <title>Nonce Cap</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6190-functional-selfdestruct/12232</comments>
        
        <description>## Abstract

This EIP caps the nonce at `2^64-2`, reserving it for contracts with unusual behavior, as defined in other EIPs.

## Motivation

This EIP is not terribly useful on its own, as it adds additional computation without any useful side effects. However, it can be used by other EIPs.

## Specification

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 and RFC 8174.

### EOA Transactions

The nonce of a transaction originating from an EOA MUST be less than `2^64-2`. If the nonce is either `2^64-1` or `2^64-2`, the transaction MUST be invalid.

### `CREATE` and `CREATE2`

If a nonce would be incremented to `2^64-1` by `CREATE` or `CREATE2`, it is instead set to `2^64-2`. `2^64-1` is reserved for alias or other special contracts.

## Rationale

Capping a nonce allows for contracts with special properties to be created, with their functionality based on their contract code. As such, only one nonce needs to be reserved.

## Backwards Compatibility

This EIP requires a protocol upgrade, since it modifies consensus rules. The further restriction of nonce should not have an effect on accounts, as reaching a nonce of `2^64-2` is difficult.

## Security Considerations

As it is not feasible for contract accounts to get to the nonce limit, any potential problems with opcodes that depend on the value of an account&apos;s nonce can be safely ignored.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 20 Dec 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6188</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6188</guid>
      </item>
    
      <item>
        <title>Alias Contracts</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6190-functional-selfdestruct/12232</comments>
        
        <description>## Abstract

This EIP allows contracts to be turned into &quot;alias contracts&quot; using a magic nonce. Alias contracts automatically forward calls to other contracts.

## Motivation

This EIP is not terribly useful on its own, as it adds additional computation and gas costs without any useful side effects. However, in conjunction with [EIP-6190](/EIPs/EIPS/eip-6190), it can be used to make SELFDESTRUCT compatible with Verkle trees.

## Specification

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 and RFC 8174.

### Definitions

A contract is an alias contract if its nonce is `2^64-1`, and its contract code is equal to `0x1`.

### Prerequisites

[EIP-6188](/EIPs/EIPS/eip-6188) MUST be used to protect the magic nonce value of `2^64-1`.

### Opcode Changes

#### `CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL`, `PAY`, and EOA Transactions

The &quot;callee&quot; refers to the account that is being called or being paid.

If the nonce of the callee is `2^64-1`, the call MUST be forwarded to the address stored in the `0`th storage slot of the callee (as if the callee was the address stored in the `0`th storage slot of the callee). This MUST repeat until a non-alias contract is reached. The `CALLER` MUST remain unchanged.

If there is more than one alias contract in the chain, the original callee and all subsequent callees (except the last one) MUST have their `0`th storage slot set to the address of the final non-alias contract. Then, the call MUST be forwarded as usual. **This MUST occur, even in a read-only context like `STATICCALL`.**

For example, if `A` is an alias contract that forwards calls to `B`, which is an alias contract that forwards calls to `C`, then `A`&apos;s `0`th storage slot is set to `C`&apos;s address. Then, the call is forwarded to `C`.

Finally, the opcode MUST proceed as usual, using the final non-alias contract.

The `CALL`, `CALLCODE`, `DELEGATECALL`, and `STATICCALL` opcodes and EOA Transactions MUST cost an `25` gas per account accessed in this manner (including the final one, and including if no aliased accounts were used), in addition to all the regular costs incurred by accessing accounts (see [EIP-2929](/EIPs/EIPS/eip-2929)). For every account whose `0`th storage slot is updated, those opcodes MUST also cost an additional `5000` gas.

If an infinite loop occurs, the transaction MUST run out of gas and revert.

#### `EXTCODEHASH`, `EXTCODECOPY`, `EXTCODESIZE`, and `BALANCE`

The &quot;accessed account&quot; refers to the account that is being accessed (i.e. the account whose code is being accessed, or the account whose balance is being accessed).

Similar to the `CALL` family of opcodes, if the nonce of the accessed account is `2^64-1`, the accessed account&apos;s address MUST be replaced with the address stored in the `0`th storage slot of the accessed account. This MUST repeat until a non-alias contract is reached.

If there is more than one alias contract in the chain, the original accessed account and all subsequent accessed accounts (except the last one) MUST have their `0`th storage slot set to the address of the final non-alias contract. Then, the accessed account MUST be replaced as usual. **This MUST occur, even in a read-only context like `STATICCALL`.**

Finally, the opcode MUST proceed as usual, using the final non-alias contract.

The `EXTCODEHASH`, `EXTCODECOPY`, `EXTCODESIZE`, and `BALANCE` opcodes MUST cost an `25` gas per account accessed in this manner (including the final one, and including if no aliased accounts were used), in addition to all the regular costs incurred by accessing accounts (see [EIP-2929](/EIPs/EIPS/eip-2929)). For every account whose `0`th storage slot is updated, those opcodes MUST also cost an additional `5000` gas.

If an infinite loop occurs, the transaction MUST run out of gas and revert.

#### `CREATE` and `CREATE2`

If `CREATE` or `CREATE2` would create (or fail to create, depending on which EIPs are used) an account at an address, and that account&apos;s code is `0x1`, and its nonce is `2^64-1`, then instead of reverting, an attempt MUST be made to create a contract at the address stored in the `0`th storage slot of the existing account. This MUST repeat until a non-alias contract is reached.

If there is more than one alias contract in the chain, the original accessed account and all subsequent accessed accounts (except the last one) MUST have their `0`th storage slot set to the address of the final non-alias contract.

Finally, the opcode MUST proceed as usual, returning the address of the newly-created contract.

The `CREATE` and `CREATE2` opcodes MUST cost an `25` gas per account accessed in this manner (including the final one, and including if no aliased accounts were used), in addition to all the regular costs incurred by accessing accounts (see [EIP-2929](/EIPs/EIPS/eip-2929)). For every account whose `0`th storage slot is updated, those opcodes must also cost an additional `5000` gas.

If an infinite loop occurs, the transaction runs out of gas and reverts.

#### `ADDRESS`

This opcode remains unchanged; `ADDRESS` points to the address that doesn&apos;t have a nonce of `2^64-1`.33

### Transfers to the zero address

Transfers to the zero address continue to have the same effect as the `CREATE` opcode, and will cost extra gas as discussed in the [`CREATE` and `CREATE2`](#create-and-create2) section.

### Transaction Validity

The &quot;origin&quot; refers to the account that sent the transaction to be validated.

If the nonce of the origin is `2^64-1`, the origin MUST be updated to the address stored in the `0`th storage slot of the current origin (as if the origin was the address stored in the `0`th storage slot of the current origin). This MUST repeat until a non-alias contract is reached.

If there is more than one alias contract in the chain, the original origin and all subsequent origins (except the last one) MUST have their `0`th storage slot set to the address of the final non-alias contract. Then, the call MUST be forwarded as usual.

An additional `25` gas per account accessed in this manner (including the final one, and including if no aliased accounts were used), in addition to all the regular costs incurred by accessing accounts (see [EIP-2929](/EIPs/EIPS/eip-2929)) is added to the validation costs. For every account whose `0`th storage slot is updated, it also costs an additional `5000` gas.

Finally, validation proceeds as normal.

### RPC Endpoint Changes

#### `eth_getStorageAt`

The `eth_getStorageAt` RPC endpoint must error if the target contract has a contract code of `0x1` and a nonce of `2^64-1`.

## Rationale

The additional gas cost of `25` represents the cost of fetching the nonce and comparing it to the given value.

`eth_getStorageAt` was modified to throw an error because of alias contracts&apos; special behavior.

The nonce of `2^64-1` was chosen since it is the nonce protected by [EIP-6188](/EIPs/EIPS/eip-6188).

The contract code of `0x1` was chosen arbitrarily. A nonzero code was chosen just in case a non-alias contract with nonce `2^64-1` somehow had its code set to `0x0`, or an EOA had its nonce set to `2^64-1`.

## Backwards Compatibility

This EIP requires a protocol upgrade, since it modifies consensus rules. No existing contracts should be affected, as they will not have a nonce of `2^64-1`, nor will they have the contract code `0x1`.

## Security Considerations

The additional gas costs may cause potential DoS attacks if they access an arbitrary contract&apos;s data or make frequent contract deactivations. Contract authors must be aware and design contracts accordingly. There may be an effect on existing deployed code performing autonomous destruction and revival.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 20 Dec 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6189</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6189</guid>
      </item>
    
      <item>
        <title>Verkle-compatible SELFDESTRUCT</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6190-functional-selfdestruct/12232</comments>
        
        <description>## Abstract

Changes `SELFDESTRUCT` to only cause a finite number of state changes.

## Motivation

The `SELFDESTRUCT` instruction has a fixed price, but is unbounded in storage/account changes (it needs to delete all keys). This has been an outstanding concern for some time.

Furthermore, with *Verkle trees* accounts will be organised differently. Account properties, including storage, would have individual keys. It would not be possible to traverse and find all used keys. This makes `SELFDESTRUCT` very challenging to support in Verkle trees. This EIP is a step towards supporting `SELFDESTRUCT` in Verkle trees.

## Specification

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 and RFC 8174.

### Prerequisites

[EIP-6188](/EIPs/EIPS/eip-6188) and [EIP-6189](/EIPs/EIPS/eip-6189) must be used for this EIP to function correctly.

### `SELFDESTRUCT` Behaviour

Instead of destroying the contract at the end of the transaction, instead, the following will occur at the end of the transaction in which it is invoked:

1. The contract&apos;s code is set to `0x1`, and its nonce is set to `2^64-1`.
2. The contract&apos;s `0`th storage slot is set to the address that would be issued if the contract used the `CREATE` opcode (`keccak256(contractAddress, nonce)`). Note that the nonce is always `2^64-1`.
3. If the contract was self-destructed after the call being forwarded by one or more alias contracts, the alias contract&apos;s `0`th storage slot is set to the address calculated in step 2.
4. The contract&apos;s balance is transferred, in its entirety, to the address on the top of the stack.
5. The top of the stack is popped.

### Gas Cost of `SELFDESTRUCT`

The base gas cost of `SELFDESTRUCT` is set to `5000`. The gas cost of `SELFDESTRUCT` is increased by `5000` for each alias contract that forwarded to the contract being self-destructed. Finally, the [EIP-2929](/EIPs/EIPS/eip-2929) gas cost increase is applied.

## Rationale

This EIP is designed to be a step towards supporting `SELFDESTRUCT` in Verkle trees while making the minimum amount of changes.

The `5000` base gas cost and additional alias contracts represents the cost of setting the account nonce and first storage slot. The [EIP-2929](/EIPs/EIPS/eip-2929) gas cost increase is preserved for the reasons mentioned in said EIP&apos;s Rationale.

The nonce of `2^64-1` was chosen since it is the nonce protected by [EIP-6188](/EIPs/EIPS/eip-6188). The account code of `0x1` was chosen since it was the code specified in [EIP-6189](/EIPs/EIPS/eip-6189).

The address being the same as the one created by `CREATE` is designed to reduce possible attack vectors by not introducing a new mechanism by which accounts can be created at specific addresses.

## Backwards Compatibility

This EIP requires a protocol upgrade, since it modifies consensus rules.

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 20 Dec 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6190</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6190</guid>
      </item>
    
      <item>
        <title>EOF - JUMPF and non-returning functions</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4750-eof-functions/8195</comments>
        
        <description>## Abstract

This EIP allows for tail call optimizations in EOF functions ([EIP-4750](/EIPs/EIPS/eip-4750)) by introducing a new instruction `JUMPF`, which jumps to a code section without adding a new return stack frame.

Additionally the format of the type sections is extended to allow declaring sections as non-returning, with simplified stack validation for `JUMPF` to such section.

## Motivation

It is common for functions to make a call at the end of the routine only to then return. `JUMPF` optimizes this behavior by changing code sections without needing to update the return stack.

Knowing at validation time that a function will never return control allows for `JUMPF` to such function to be treated similar to terminating instructions, where extra items may be left on the operand stack at execution termination. This provides opportunities for compilers to generate more optimal code, both in code size and in spent gas. It is particularly beneficial for small error handling helpers, that end execution with `REVERT`: they are commonly reused in multiple branches and extracting them into a helper function is efficient, when there is no need to pop extra stack items before `JUMPF` to such helper.

## Specification

### Type section changes

We define a non-returning section as one that cannot return control to its caller section.

Type section `outputs` field contains a special value `0x80` when corresponding code section is non-returning. See [Non-returning status validation](#non-returning-status-validation) below for validation details.

The first code section MUST have 0 inputs and be non-returning.

### Execution Semantics

A new instruction, `JUMPF (0xe5)`, is introduced.

1. `JUMPF` has one immediate argument, `target_section_index`, encoded as a 16-bit unsigned big-endian value.
2. If the operand stack size exceeds `1024 - type[target_section_index].max_stack_increase` (i.e. if the called function may exceed the global stack height limit), execution results in an exceptional halt. This guarantees that the target function does not exceed global stack height limit.
3. `JUMPF` sets `current_section_index` to `target_section_index` and `PC` to `0`, but does not change the return stack. Execution continues in the target section. 
4. `JUMPF` costs 5 gas.
5. `JUMPF` neither pops nor pushes anything to the operand stack.

If the code is legacy bytecode, `JUMPF` instruction results in an *exceptional halt*. (*Note: This means no change to behaviour.*)

### Code Validation

Let the definition of `type[i]` be inherited from [EIP-4750](/EIPs/EIPS/eip-4750) and define `stack_height_min` and `stack_height_max` to be the stack height bounds at a certain instruction during the instruction flow traversal.

* The immediate argument of `JUMPF` MUST be less than the total number of code sections.
* For each `JUMPF` instruction:
  * either `type[current_section_index].outputs` MUST be greater or equal `type[target_section_index].outputs`,
  * or `type[target_section_index].outputs` MUST be `0x80`
* The stack height validation at `JUMPF` depends on whether the target section is non-returning:
  * `JUMPF` into returning section (`type[target_section_index].outputs` does not equal `0x80`):  `stack_height_min` and `stack_height_max` MUST be equal to `type[current_section_index].outputs - type[target_section_index].outputs + type[target_section_index].inputs`. This means that target section can output less stack elements than the original code section called by the top element on the return stack, if the current code section leaves the delta `type[current_section_index].outputs - type[target_section_index].outputs` element(s) on the stack.
  * `JUMPF` into non-returning section (`type[target_section_index].outputs` equals `0x80`): `stack_height_min` MUST be greater than or equal to `type[target_section_index].inputs`.
* Stack overflow check at `JUMPF`: `stack_height_max` MUST be less than or equal to `1024 - types[target_section_index].max_stack_increase`.
* `JUMPF` is considered terminating instruction, i.e. does not have successor instructions in code validation and MAY be final instruction in the section. 
* The code validation defined in [EIP-4200](/EIPs/EIPS/eip-4200) also fails if any `RJUMP*` offset points to one of the two bytes directly following a `JUMPF` instruction.

`CALLF` instruction validation is extended to include the rule:

* Code section is invalid in case an immediate argument `target_section_index` of any `CALLF` targets a non-returning section, i.e. `type[target_section_index].outputs` equals `0x80`.

#### Non-returning status validation

Section type MUST be non-returning if and only if the section contains no `RETF` instructions and no `JUMPF` instructions targeting returning sections (target section&apos;s status is checked via its output value in type section.)
*Note: This implies that section containing only `JUMPF`s into non-returning sections is non-returning itself.*

## Rationale

### Allowing `JUMPF` to section with less outputs

An alternative rule for `JUMPF` stack validation could require the target section&apos;s outputs to be exactly equal to the current section&apos;s outputs. Under such rule, a particular target section (a shared &quot;helper&quot; piece of code) would only &quot;match&quot; sections (requiring some shared &quot;helper&quot; code to execute before returning) *with the same number of outputs*.

Instead, we allow a given `JUMPF` target section to be called from sections with more outputs, as long as these sections provide these extra stack elements (the &quot;delta&quot;) themselves. This will reduce duplicated code as it will allow compilers more flexibility during code generation such that certain helpers can be used generically by functions, regardless of their output values.

## Backwards Compatibility

This change is backward compatible as EOF does not allow undefined instructions to be used or deployed, meaning no contracts will be affected.

## Security Considerations

This new instruction needs to be carefully considered during implementation of the EOF container validation algorithm.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 21 Dec 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6206</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6206</guid>
      </item>
    
      <item>
        <title>Composable NFTs utilizing Equippable Parts</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6220-composable-nfts-utilizing-equippable-parts/12289</comments>
        
        <description>## Abstract

The Composable NFTs utilizing equippable parts standard extends [ERC-721](/EIPs/EIPS/eip-721) by allowing the NFTs to selectively add parts to themselves via equipping.

Tokens can be composed by cherry picking the list of parts from a Catalog for each NFT instance, and are able to equip other NFTs into slots, which are also defined within the Catalog. Catalogs contain parts from which NFTs can be composed.

This proposal introduces two types of parts; slot type of parts and fixed type of parts. The slot type of parts allow for other NFT collections to be equipped into them, while fixed parts are full components with their own metadata.

Equipping a part into an NFT doesn&apos;t generate a new token, but rather adds another component to be rendered when retrieving the token.

## Motivation

With NFTs being a widespread form of tokens in the Ethereum ecosystem and being used for a variety of use cases, it is time to standardize additional utility for them. Having the ability for tokens to equip other tokens and be composed from a set of available parts allows for greater utility, usability and forward compatibility.

In the four years since [ERC-721](/EIPs/EIPS/eip-721) was published, the need for additional functionality has resulted in countless extensions. This EIP improves upon ERC-721 in the following areas:

- [Composing](#composing)
- [Token progression](#token-progression)
- [Merit tracking](#merit-tracking)
- [Provable Digital Scarcity](#provable-digital-scarcity)

### Composing

NFTs can work together to create a greater construct. Prior to this proposal, multiple NFTs could be composed into a single construct either by checking all of the compatible NFTs associated with a given account and used indiscriminately (which could result in unexpected result if there was more than one NFT intended to be used in the same slot), or by keeping a custom ledger of parts to compose together (either in a smart contract or an off-chain database). This proposal establishes a standardized framework for composable NFTs, where a single NFT can select which parts should be a part of the whole, with the information being on chain. Composing NFTs in such a way allows for virtually unbounded customization of the base NFT. An example of this could be a movie NFT. Some parts, like credits, should be fixed. Other parts, like scenes, should be interchangeable, so that various releases (base version, extended cuts, anniversary editions,...) can be replaced.

### Token progression

As the token progresses through various stages of its existence, it can attain or be awarded various parts. This can be explained in terms of gaming. A character could be represented by an NFT utilizing this proposal and would be able to equip gear acquired through the gameplay activities and as it progresses further in the game, better items would be available. In stead of having numerous NFTs representing the items collected through its progression, equippable parts can be unlocked and the NFT owner would be able to decide which items to equip and which to keep in the inventory (not equipped) without need of a centralized party.

### Merit tracking

An equippable NFT can also be used to track merit. An example of this is academic merit. The equippable NFT in this case would represent a sort of digital portfolio of academic achievements, where the owner would be able to equip their diplomas, published articles and awards for all to see.

### Provable Digital Scarcity

The majority of current NFT projects are only mock-scarce. Even with a limited supply of tokens, the utility of these (if any) is uncapped. As an example, you can log into 500 different instances of the same game using the same wallet and the same NFT. You can then equip the same hat onto 500 different in-game avatars at the same time, because its visual representation is just a client-side mechanic. 

This proposal adds the ability to enforce that, if a hat is equipped on one avatar (by being sent into it and then equipped), it cannot be equipped on another. This provides real digital scarcity.

## Specification

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.

### Equippable tokens

The interface of the core smart contract of the equippable tokens.

```solidity
/// @title EIP-6220 Composable NFTs utilizing Equippable Parts
/// @dev See https://eips.ethereum.org/EIPS/eip-6220
/// @dev Note: the ERC-165 identifier for this interface is 0x28bc9ae4.

pragma solidity ^0.8.16;

import &quot;./IERC5773.sol&quot;;

interface IERC6220 is IERC5773 /*, ERC165 */ {
    /**
     * @notice Used to store the core structure of the `Equippable` component.
     * @return assetId The ID of the asset equipping a child
     * @return childAssetId The ID of the asset used as equipment
     * @return childId The ID of token that is equipped
     * @return childEquippableAddress Address of the collection to which the child asset belongs to
     */
    struct Equipment {
        uint64 assetId;
        uint64 childAssetId;
        uint256 childId;
        address childEquippableAddress;
    }

    /**
     * @notice Used to provide a struct for inputing equip data.
     * @dev Only used for input and not storage of data.
     * @return tokenId ID of the token we are managing
     * @return childIndex Index of a child in the list of token&apos;s active children
     * @return assetId ID of the asset that we are equipping into
     * @return slotPartId ID of the slot part that we are using to equip
     * @return childAssetId ID of the asset that we are equipping
     */
    struct IntakeEquip {
        uint256 tokenId;
        uint256 childIndex;
        uint64 assetId;
        uint64 slotPartId;
        uint64 childAssetId;
    }

    /**
     * @notice Used to notify listeners that a child&apos;s asset has been equipped into one of its parent assets.
     * @param tokenId ID of the token that had an asset equipped
     * @param assetId ID of the asset associated with the token we are equipping into
     * @param slotPartId ID of the slot we are using to equip
     * @param childId ID of the child token we are equipping into the slot
     * @param childAddress Address of the child token&apos;s collection
     * @param childAssetId ID of the asset associated with the token we are equipping
     */
    event ChildAssetEquipped(
        uint256 indexed tokenId,
        uint64 indexed assetId,
        uint64 indexed slotPartId,
        uint256 childId,
        address childAddress,
        uint64 childAssetId
    );

    /**
     * @notice Used to notify listeners that a child&apos;s asset has been unequipped from one of its parent assets.
     * @param tokenId ID of the token that had an asset unequipped
     * @param assetId ID of the asset associated with the token we are unequipping out of
     * @param slotPartId ID of the slot we are unequipping from
     * @param childId ID of the token being unequipped
     * @param childAddress Address of the collection that a token that is being unequipped belongs to
     * @param childAssetId ID of the asset associated with the token we are unequipping
     */
    event ChildAssetUnequipped(
        uint256 indexed tokenId,
        uint64 indexed assetId,
        uint64 indexed slotPartId,
        uint256 childId,
        address childAddress,
        uint64 childAssetId
    );

    /**
     * @notice Used to notify listeners that the assets belonging to a `equippableGroupId` have been marked as
     *  equippable into a given slot and parent
     * @param equippableGroupId ID of the equippable group being marked as equippable into the slot associated with
     *  `slotPartId` of the `parentAddress` collection
     * @param slotPartId ID of the slot part of the catalog into which the parts belonging to the equippable group
     *  associated with `equippableGroupId` can be equipped
     * @param parentAddress Address of the collection into which the parts belonging to `equippableGroupId` can be
     *  equipped
     */
    event ValidParentEquippableGroupIdSet(
        uint64 indexed equippableGroupId,
        uint64 indexed slotPartId,
        address parentAddress
    );

    /**
     * @notice Used to equip a child into a token.
     * @dev The `IntakeEquip` struct contains the following data:
     *  [
     *      tokenId,
     *      childIndex,
     *      assetId,
     *      slotPartId,
     *      childAssetId
     *  ]
     * @param data An `IntakeEquip` struct specifying the equip data
     */
    function equip(
        IntakeEquip memory data
    ) external;

    /**
     * @notice Used to unequip child from parent token.
     * @dev This can only be called by the owner of the token or by an account that has been granted permission to
     *  manage the given token by the current owner.
     * @param tokenId ID of the parent from which the child is being unequipped
     * @param assetId ID of the parent&apos;s asset that contains the `Slot` into which the child is equipped
     * @param slotPartId ID of the `Slot` from which to unequip the child
     */
    function unequip(
        uint256 tokenId,
        uint64 assetId,
        uint64 slotPartId
    ) external;

    /**
     * @notice Used to check whether the token has a given child equipped.
     * @dev This is used to prevent from transferring a child that is equipped.
     * @param tokenId ID of the parent token for which we are querying for
     * @param childAddress Address of the child token&apos;s smart contract
     * @param childId ID of the child token
     * @return bool The boolean value indicating whether the child token is equipped into the given token or not
     */
    function isChildEquipped(
        uint256 tokenId,
        address childAddress,
        uint256 childId
    ) external view returns (bool);

    /**
     * @notice Used to verify whether a token can be equipped into a given parent&apos;s slot.
     * @param parent Address of the parent token&apos;s smart contract
     * @param tokenId ID of the token we want to equip
     * @param assetId ID of the asset associated with the token we want to equip
     * @param slotId ID of the slot that we want to equip the token into
     * @return bool The boolean indicating whether the token with the given asset can be equipped into the desired
     *  slot
     */
    function canTokenBeEquippedWithAssetIntoSlot(
        address parent,
        uint256 tokenId,
        uint64 assetId,
        uint64 slotId
    ) external view returns (bool);

    /**
     * @notice Used to get the Equipment object equipped into the specified slot of the desired token.
     * @dev The `Equipment` struct consists of the following data:
     *  [
     *      assetId,
     *      childAssetId,
     *      childId,
     *      childEquippableAddress
     *  ]
     * @param tokenId ID of the token for which we are retrieving the equipped object
     * @param targetCatalogAddress Address of the `Catalog` associated with the `Slot` part of the token
     * @param slotPartId ID of the `Slot` part that we are checking for equipped objects
     * @return struct The `Equipment` struct containing data about the equipped object
     */
    function getEquipment(
        uint256 tokenId,
        address targetCatalogAddress,
        uint64 slotPartId
    ) external view returns (Equipment memory);

    /**
     * @notice Used to get the asset and equippable data associated with given `assetId`.
     * @param tokenId ID of the token for which to retrieve the asset
     * @param assetId ID of the asset of which we are retrieving
     * @return metadataURI The metadata URI of the asset
     * @return equippableGroupId ID of the equippable group this asset belongs to
     * @return catalogAddress The address of the catalog the part belongs to
     * @return partIds An array of IDs of parts included in the asset
     */
    function getAssetAndEquippableData(uint256 tokenId, uint64 assetId)
        external
        view
        returns (
            string memory metadataURI,
            uint64 equippableGroupId,
            address catalogAddress,
            uint64[] calldata partIds
        );
}
```

### Catalog

The interface of the Catalog containing the equippable parts. Catalogs are collections of equippable fixed and slot parts and are not restricted to a single collection, but can support any number of NFT collections.

```solidity
/**
 * @title ICatalog
 * @notice An interface Catalog for equippable module.
 * @dev Note: the ERC-165 identifier for this interface is 0xd912401f.
 */

pragma solidity ^0.8.16;

interface ICatalog /* is IERC165 */ {
    /**
     * @notice Event to announce addition of a new part.
     * @dev It is emitted when a new part is added.
     * @param partId ID of the part that was added
     * @param itemType Enum value specifying whether the part is `None`, `Slot` and `Fixed`
     * @param zIndex An uint specifying the z value of the part. It is used to specify the depth which the part should
     *  be rendered at
     * @param equippableAddresses An array of addresses that can equip this part
     * @param metadataURI The metadata URI of the part
     */
    event AddedPart(
        uint64 indexed partId,
        ItemType indexed itemType,
        uint8 zIndex,
        address[] equippableAddresses,
        string metadataURI
    );

    /**
     * @notice Event to announce new equippables to the part.
     * @dev It is emitted when new addresses are marked as equippable for `partId`.
     * @param partId ID of the part that had new equippable addresses added
     * @param equippableAddresses An array of the new addresses that can equip this part
     */
    event AddedEquippables(
        uint64 indexed partId,
        address[] equippableAddresses
    );

    /**
     * @notice Event to announce the overriding of equippable addresses of the part.
     * @dev It is emitted when the existing list of addresses marked as equippable for `partId` is overwritten by a new
     *  one.
     * @param partId ID of the part whose list of equippable addresses was overwritten
     * @param equippableAddresses The new, full, list of addresses that can equip this part
     */
    event SetEquippables(uint64 indexed partId, address[] equippableAddresses);

    /**
     * @notice Event to announce that a given part can be equipped by any address.
     * @dev It is emitted when a given part is marked as equippable by any.
     * @param partId ID of the part marked as equippable by any address
     */
    event SetEquippableToAll(uint64 indexed partId);

    /**
     * @notice Used to define a type of the item. Possible values are `None`, `Slot` or `Fixed`.
     * @dev Used for fixed and slot parts.
     */
    enum ItemType {
        None,
        Slot,
        Fixed
    }

    /**
     * @notice The integral structure of a standard RMRK catalog item defining it.
     * @dev Requires a minimum of 3 storage slots per catalog item, equivalent to roughly 60,000 gas as of Berlin hard fork
     *  (April 14, 2021), though 5-7 storage slots is more realistic, given the standard length of an IPFS URI. This
     *  will result in between 25,000,000 and 35,000,000 gas per 250 assets--the maximum block size of Ethereum
     *  mainnet is 30M at peak usage.
     * @return itemType The item type of the part
     * @return z The z value of the part defining how it should be rendered when presenting the full NFT
     * @return equippable The array of addresses allowed to be equipped in this part
     * @return metadataURI The metadata URI of the part
     */
    struct Part {
        ItemType itemType; //1 byte
        uint8 z; //1 byte
        address[] equippable; //n Collections that can be equipped into this slot
        string metadataURI; //n bytes 32+
    }

    /**
     * @notice The structure used to add a new `Part`.
     * @dev The part is added with specified ID, so you have to make sure that you are using an unused `partId`,
     *  otherwise the addition of the part vill be reverted.
     * @dev The full `IntakeStruct` looks like this:
     *  [
     *          partID,
     *      [
     *          itemType,
     *          z,
     *          [
     *               permittedCollectionAddress0,
     *               permittedCollectionAddress1,
     *               permittedCollectionAddress2
     *           ],
     *           metadataURI
     *       ]
     *   ]
     * @return partId ID to be assigned to the `Part`
     * @return part A `Part` to be added
     */
    struct IntakeStruct {
        uint64 partId;
        Part part;
    }

    /**
     * @notice Used to return the metadata URI of the associated catalog.
     * @return string Base metadata URI
     */
    function getMetadataURI() external view returns (string memory);

    /**
     * @notice Used to return the `itemType` of the associated catalog
     * @return string `itemType` of the associated catalog
     */
    function getType() external view returns (string memory);

    /**
     * @notice Used to check whether the given address is allowed to equip the desired `Part`.
     * @dev Returns true if a collection may equip asset with `partId`.
     * @param partId The ID of the part that we are checking
     * @param targetAddress The address that we are checking for whether the part can be equipped into it or not
     * @return bool The status indicating whether the `targetAddress` can be equipped into `Part` with `partId` or not
     */
    function checkIsEquippable(uint64 partId, address targetAddress)
        external
        view
        returns (bool);

    /**
     * @notice Used to check if the part is equippable by all addresses.
     * @dev Returns true if part is equippable to all.
     * @param partId ID of the part that we are checking
     * @return bool The status indicating whether the part with `partId` can be equipped by any address or not
     */
    function checkIsEquippableToAll(uint64 partId) external view returns (bool);

    /**
     * @notice Used to retrieve a `Part` with id `partId`
     * @param partId ID of the part that we are retrieving
     * @return struct The `Part` struct associated with given `partId`
     */
    function getPart(uint64 partId) external view returns (Part memory);

    /**
     * @notice Used to retrieve multiple parts at the same time.
     * @param partIds An array of part IDs that we want to retrieve
     * @return struct An array of `Part` structs associated with given `partIds`
     */
    function getParts(uint64[] calldata partIds)
        external
        view
        returns (Part[] memory);
}
```

## Rationale

Designing the proposal, we considered the following questions:

1. **Why are we using a Catalog in stead of supporting direct NFT equipping?**\
If NFTs could be directly equipped into other NFTs without any oversight, the resulting composite would be unpredictable. Catalog allows for parts to be pre-verified in order to result in a composite that composes as expected. Another benefit of Catalog is the ability of defining reusable fixed parts.
2. **Why do we propose two types of parts?**\
Some parts, that are the same for all of the tokens, don&apos;t make sense to be represented by individual NFTs, so they can be represented by fixed parts. This reduces the clutter of the owner&apos;s wallet as well as introduces an efficient way of disseminating repetitive assets tied to NFTs.\
The slot parts allow for equipping NFTs into them. This provides the ability to equip unrelated NFT collections into the base NFT after the unrelated collection has been verified to compose properly.\
Having two parts allows for support of numerous use cases and, since the proposal doesn&apos;t enforce the use of both it can be applied in any configuration needed.
3. **Why is a method to get all of the equipped parts not included?**\
Getting all parts might not be an operation necessary for all implementers. Additionally, it can be added either as an extension, doable with hooks, or can be emulated using an indexer.
4. **Should Catalog be limited to support one NFT collection at a time or be able to support any nunmber of collections?**\
As the Catalog is designed in a way that is agnostic to the use case using it. It makes sense to support as wide reusability as possible. Having one Catalog supporting multiple collections allows for optimized operation and reduced gas prices when deploying it and setting fixed as well as slot parts.

### Fixed parts

Fixed parts are defined and contained in the Catalog. They have their own metadata and are not meant to change through the lifecycle of the NFT. 

A fixed part cannot be replaced.

The benefit of fixed parts is that they represent equippable parts that can be equipped by any number of tokens in any number of collections and only need to be defined once.

### Slot parts

Slot parts are defined and contained in the Catalog. They don&apos;t have their own metadata, but rather support equipping of selected NFT collections into them. The tokens equipped into the slots however, contain their own metadata. This allows for an equippable modifialbe content of the base NFT controlled by its owner. As they can be equipped into any number of tokens of any number of collections, they allow for reliable composing of the final tokens by vetting which NFTs can be equipped by a given slot once and then reused any number of times.

## Backwards Compatibility

The Equippable token standard has been made compatible with [ERC-721](/EIPs/EIPS/eip-721) in order to take advantage of the robust tooling available for implementations of ERC-721 and to ensure compatibility with existing ERC-721 infrastructure.

## Test Cases

Tests are included in [`equippableFixedParts.ts`](/EIPs/assets/eip-6220/test/equippableFixedParts.ts) and [`equippableSlotParts.ts`](/EIPs/assets/eip-6220/test/equippableSlotParts.ts).

To run them in terminal, you can use the following commands:

```
cd ../assets/eip-6220
npm install
npx hardhat test
```

## Reference Implementation

See [`EquippableToken.sol`](/EIPs/assets/eip-6220/contracts/EquippableToken.sol).


## Security Considerations

The same security considerations as with [ERC-721](/EIPs/EIPS/eip-721) apply: hidden logic may be present in any of the functions, including burn, add resource, accept resource, and more.

Caution is advised when dealing with non-audited contracts.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 20 Dec 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6220</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6220</guid>
      </item>
    
      <item>
        <title>Contracts Dependencies Registry</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6224-contracts-dependencies-registry/12316</comments>
        
        <description>## Abstract

This EIP introduces an on-chain registry system that a decentralized protocol may use to manage its smart contracts.

The proposed system consists of two components: `ContractsRegistry` and `Dependant`. The `ContractsRegistry` 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 `Dependant` contracts query to fetch their required dependencies from.

## Motivation

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.

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 `ContractsRegistry` and the `Dependant`.

The advantages of using the provided system might be:

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

## Specification

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

### Overview

The system consists of two smart contracts:

- `ContractsRegistry` that is a singleton registry to manage and upgrade a protocol&apos;s smart contracts.
- `Dependant` that is a mix-in which enables a dependency injection mechanism.

The following diagram depicts the relationship between the registry and its dependants:

![](/EIPs/assets/eip-6224/diagram.svg)

### ContractsRegistry

The `ContractsRegistry` is the main contract of the proposed system. It MUST store the references to every standalone contract used within a protocol. The `ContractRegistry` MAY be configured to deploy a proxy contract of choice on top of the registered contracts. 

Additionally, the `ContractsRegistry` MUST reject the registration of zero addresses.

The `ContractsRegistry` MUST implement the following interface:

```solidity
pragma solidity ^0.8.0;

interface IContractsRegistry {
    /**
     * @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
     */
    event ContractAdded(string name, address contractAddress);
 
    /**
     * @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
     */
    event ProxyContractAdded(string name, address contractAddress, address implementation);
 
    /**
     * @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
     */
    event ProxyContractUpgraded(string name, address newImplementation);
 
    /**
     * @notice The event that is emitted when the contract gets removed from the registry
     * @param name the name of the removed contract
     */
    event ContractRemoved(string name);
 
    /**
     * @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
     */
    function getContract(string memory name) external view returns (address);
 
    /**
     * @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
     */
    function hasContract(string memory name) external view returns (bool);
 
    /**
     * @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
     */
    function injectDependencies(string memory name) external;
 
    /**
     * @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
     */
    function injectDependenciesWithData(
        string memory name,
        bytes memory data
    ) external;
 
    /**
     * @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
     */
    function upgradeContract(string memory name, address newImplementation) external;
 
    /**
     * @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
     */
    function upgradeContractAndCall(
        string memory name,
        address newImplementation,
        bytes memory data
    ) external;
 
    /**
     * @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
     */
    function addContract(string memory name, address contractAddress) external;
 
    /**
     * @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
     */
    function addProxyContract(string memory name, address contractAddress) external;
 
    /**
     * @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
     */
    function addProxyContractAndCall(
        string memory name,
        address contractAddress,
        bytes memory data
    ) external;
 
    /**
     * @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
     */
    function justAddProxyContract(string memory name, address contractAddress) external;
 
    /**
     * @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
     */
    function removeContract(string memory name) external;
}
```

### Dependant

The `ContractsRegistry` works together with the `Dependant` contract. Every standalone contract of a protocol MUST inherit `Dependant` in order to support the dependency injection mechanism. 

The required dependencies MUST be set in the overridden `setDependencies` method, not in the `constructor` or `initializer` methods.

Only the injector MUST be able to call the `setDependencies` and `setInjector` methods. The initial injector will be a zero address, in that case, the call MUST NOT revert on access control checks.

The `Dependant` contract MUST implement the following interface:

```solidity
pragma solidity ^0.8.0;

interface IDependant {
    /**
     * @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
     */
    function setDependencies(address contractsRegistry, bytes memory data) external;
 
    /**
     * @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
     */
    function setInjector(address injector) external;
 
    /**
     * @notice The function that gets the current dependency injector
     * @return the current dependency injector
     */
    function getInjector() external view returns (address);
}
```

- The `Dependant` contract MAY store the dependency injector (usually `ContractsRegistry`) address in the special slot `0x3d1f25f1ac447e55e7fec744471c4dab1c6a2b6ffb897825f9ea3d2e8c9be583` (obtained as `bytes32(uint256(keccak256(&quot;eip6224.dependant.slot&quot;)) - 1)`).

## Rationale

There are a few design decisions that have to be explicitly specified:

### ContractsRegistry Rationale

#### Contracts Identifier

The `string` contracts identifier is chosen over the `uint256` and `bytes32` to maintain code readability and reduce the human error chances when interacting with the `ContractsRegistry`. 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.

Due to the `string` identifier, the event parameters are not indexed. The `string indexed` parameter will become the `keccak256` hash of the contract name if it is larger than 32 bytes. This fact reduces readability, which was prioritized.

#### Reverts

The `getContract` view function reverts if the requested contract is `address(0)`. 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.

The `addContract`, `addProxyContract`, `addProxyContractAndCall`, and `justAddProxyContract` methods revert if the provided address is `address(0)` for the same risk minimization reason.

### Dependant Rationale

#### Dependencies

The `data` parameter is provided to carry additional application-specific context. It MAY be used to extend the method&apos;s behavior.

#### Injector

The `setInjector` function is made `external` to support the dependency injection mechanism for factory-made contracts. However, the method SHOULD be used with extra care.

## Reference Implementation

&gt; Note that the reference implementation depends on OpenZeppelin contracts `4.9.2`.

### ContractsRegistry Implementation

```solidity
pragma solidity ^0.8.0;

import {Address} from &quot;@openzeppelin/contracts/utils/Address.sol&quot;;
import {TransparentUpgradeableProxy} from &quot;@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol&quot;;
import {OwnableUpgradeable} from &quot;@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol&quot;;

import {Dependant} from &quot;./Dependant.sol&quot;;

interface IContractsRegistry {
    event ContractAdded(string name, address contractAddress);
    event ProxyContractAdded(
        string name,
        address contractAddress,
        address implementation
    );
    event ProxyContractUpgraded(string name, address newImplementation);
    event ContractRemoved(string name);

    function getContract(string memory name) external view returns (address);

    function hasContract(string memory name) external view returns (bool);

    function injectDependencies(string memory name) external;

    function injectDependenciesWithData(string memory name, bytes memory data)
        external;

    function upgradeContract(string memory name, address newImplementation)
        external;

    function upgradeContractAndCall(
        string memory name,
        address newImplementation,
        bytes memory data
    ) external;

    function addContract(string memory name, address contractAddress) external;

    function addProxyContract(string memory name, address contractAddress)
        external;

    function addProxyContractAndCall(
        string memory name,
        address contractAddress,
        bytes memory data
    ) external;

    function justAddProxyContract(string memory name, address contractAddress)
        external;

    function removeContract(string memory name) external;
}

contract ProxyUpgrader {
    using Address for address;

    address private immutable _OWNER;

    modifier onlyOwner() {
        _onlyOwner();
        _;
    }

    constructor() {
        _OWNER = msg.sender;
    }

    function upgrade(address what_, address to_, bytes calldata data_) external onlyOwner {
        if (data_.length &gt; 0) {
            TransparentUpgradeableProxy(payable(what_)).upgradeToAndCall(to_, data_);
        } else {
            TransparentUpgradeableProxy(payable(what_)).upgradeTo(to_);
        }
    }

    function getImplementation(address what_) external view onlyOwner returns (address) {
        // bytes4(keccak256(&quot;implementation()&quot;)) == 0x5c60da1b
        (bool success_, bytes memory returndata_) = address(what_).staticcall(hex&quot;5c60da1b&quot;);

        require(success_, &quot;ProxyUpgrader: not a proxy&quot;);

        return abi.decode(returndata_, (address));
    }

    function _onlyOwner() internal view {
        require(_OWNER == msg.sender, &quot;ProxyUpgrader: not an owner&quot;);
    }
}

contract ContractsRegistry is IContractsRegistry, OwnableUpgradeable {
    ProxyUpgrader private _proxyUpgrader;

    mapping(string =&gt; address) private _contracts;
    mapping(address =&gt; bool) private _isProxy;

    function __ContractsRegistry_init() public initializer {
        _proxyUpgrader = new ProxyUpgrader();

        __Ownable_init();
    }

    function getContract(string memory name_) public view returns (address) {
        address contractAddress_ = _contracts[name_];

        require(
            contractAddress_ != address(0),
            &quot;ContractsRegistry: this mapping doesn&apos;t exist&quot;
        );

        return contractAddress_;
    }

    function hasContract(string memory name_) public view returns (bool) {
        return _contracts[name_] != address(0);
    }

    function getProxyUpgrader() external view returns (address) {
        return address(_proxyUpgrader);
    }

    function injectDependencies(string memory name_) public virtual onlyOwner {
        injectDependenciesWithData(name_, bytes(&quot;&quot;));
    }

    function injectDependenciesWithData(string memory name_, bytes memory data_)
        public
        virtual
        onlyOwner
    {
        address contractAddress_ = _contracts[name_];

        require(
            contractAddress_ != address(0),
            &quot;ContractsRegistry: this mapping doesn&apos;t exist&quot;
        );

        Dependant dependant_ = Dependant(contractAddress_);
        dependant_.setDependencies(address(this), data_);
    }

    function upgradeContract(string memory name_, address newImplementation_)
        public
        virtual
        onlyOwner
    {
        upgradeContractAndCall(name_, newImplementation_, bytes(&quot;&quot;));
    }

    function upgradeContractAndCall(
        string memory name_,
        address newImplementation_,
        bytes memory data_
    ) public virtual onlyOwner {
        address contractToUpgrade_ = _contracts[name_];

        require(
            contractToUpgrade_ != address(0),
            &quot;ContractsRegistry: this mapping doesn&apos;t exist&quot;
        );
        require(
            _isProxy[contractToUpgrade_],
            &quot;ContractsRegistry: not a proxy contract&quot;
        );

        _proxyUpgrader.upgrade(contractToUpgrade_, newImplementation_, data_);

        emit ProxyContractUpgraded(name_, newImplementation_);
    }

    function addContract(string memory name_, address contractAddress_)
        public
        virtual
        onlyOwner
    {
        require(
            contractAddress_ != address(0),
            &quot;ContractsRegistry: zero address is forbidden&quot;
        );

        _contracts[name_] = contractAddress_;

        emit ContractAdded(name_, contractAddress_);
    }

    function addProxyContract(string memory name_, address contractAddress_)
        public
        virtual
        onlyOwner
    {
        addProxyContractAndCall(name_, contractAddress_, bytes(&quot;&quot;));
    }

    function addProxyContractAndCall(
        string memory name_,
        address contractAddress_,
        bytes memory data_
    ) public virtual onlyOwner {
        require(
            contractAddress_ != address(0),
            &quot;ContractsRegistry: zero address is forbidden&quot;
        );

        address proxyAddr_ = _deployProxy(
            contractAddress_,
            address(_proxyUpgrader),
            data_
        );

        _contracts[name_] = proxyAddr_;
        _isProxy[proxyAddr_] = true;

        emit ProxyContractAdded(name_, proxyAddr_, contractAddress_);
    }

    function justAddProxyContract(string memory name_, address contractAddress_)
        public
        virtual
        onlyOwner
    {
        require(
            contractAddress_ != address(0),
            &quot;ContractsRegistry: zero address is forbidden&quot;
        );

        _contracts[name_] = contractAddress_;
        _isProxy[contractAddress_] = true;

        emit ProxyContractAdded(
            name_,
            contractAddress_,
            _proxyUpgrader.getImplementation(contractAddress_)
        );
    }

    function removeContract(string memory name_) public virtual onlyOwner {
        address contractAddress_ = _contracts[name_];

        require(
            contractAddress_ != address(0),
            &quot;ContractsRegistry: this mapping doesn&apos;t exist&quot;
        );

        delete _isProxy[contractAddress_];
        delete _contracts[name_];

        emit ContractRemoved(name_);
    }

    function _deployProxy(
        address contractAddress_,
        address admin_,
        bytes memory data_
    ) internal virtual returns (address) {
        return
            address(
                new TransparentUpgradeableProxy(contractAddress_, admin_, data_)
            );
    }
}
```

### Dependant Implementation

```solidity
pragma solidity ^0.8.0;

interface IDependant {
    function setDependencies(address contractsRegistry, bytes memory data) external;
 
    function setInjector(address injector) external;
 
    function getInjector() external view returns (address);
}

abstract contract Dependant is IDependant {
    /**
     * @dev bytes32(uint256(keccak256(&quot;eip6224.dependant.slot&quot;)) - 1)
     */
    bytes32 private constant _INJECTOR_SLOT =
        0x3d1f25f1ac447e55e7fec744471c4dab1c6a2b6ffb897825f9ea3d2e8c9be583;

    modifier dependant() {
        _checkInjector();
        _;
        _setInjector(msg.sender);
    }

    function setDependencies(address contractsRegistry_, bytes memory data_) public virtual;

    function setInjector(address injector_) external {
        _checkInjector();
        _setInjector(injector_);
    }

    function getInjector() public view returns (address injector_) {
        bytes32 slot_ = _INJECTOR_SLOT;

        assembly {
            injector_ := sload(slot_)
        }
    }

    function _setInjector(address injector_) internal {
        bytes32 slot_ = _INJECTOR_SLOT;

        assembly {
            sstore(slot_, injector_)
        }
    }

    function _checkInjector() internal view {
        address injector_ = getInjector();

        require(injector_ == address(0) || injector_ == msg.sender, &quot;Dependant: not an injector&quot;);
    }
}
```

## Security Considerations

It is crucial for the owner of `ContractsRegistry` to keep their keys in a safe place. The loss/leakage of credentials to the `ContractsRegistry` will lead to the application&apos;s point of no return. The `ContractRegistry` is a cornerstone of a protocol, access must be granted to the trusted parties only.

### ContractsRegistry Security

- The `ContractsRegistry` does not perform any upgradeability checks between the proxy upgrades. It is the user&apos;s responsibility to make sure that the new implementation is compatible with the old one.

### Dependant Security

- The `Dependant` contract MUST set its dependency injector no later than the first call to the `setDependencies` function is made. That being said, it is possible to front-run the first dependency injection.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Tokenized Vaults with Lock-in Period</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-tokenized-vaults-with-lock-in-period/12298</comments>
        
        <description>## Abstract

This standard extends [EIP-4626](/EIPs/EIPS/eip-4626) to support lock-in periods.

## Motivation

The [EIP-4626](/EIPs/EIPS/eip-4626) standard defines a tokenized vault allowing users (contracts or EOAs) to deposit and withdraw underlying tokens at any time. However, there exist cases where the vault needs to lock the underlying tokens (perhaps to execute certain strategies). During the lock-in period, neither withdrawals nor deposits should be allowed. This standard extends the EIP-4626 to support lock-in periods and handle scheduled deposits and withdrawals during them.

## Specification

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

All vaults that follow this EIP MUST implement [EIP-4626](/EIPs/EIPS/eip-4626) to provide basic vault functions and [EIP-20](/EIPs/EIPS/eip-20) to represent shares.

### Definitions

- asset: The underlying [EIP-20](/EIPs/EIPS/eip-20) token that the vault accepts and manages.
- share: The EIP-20 token that the vault issued.
- locked: A status of the vault. When the vault is locked, user can’t withdraw or deposit assets from the vault.
- unlocked: A status of the vault. When the vault is unlocked, user can withdraw or deposit assets from the vault.
- round: The period that the vault is locked.

### View Methods

#### isLocked

The current state of the vault.

`true` represents a vault is in the locked state, and `false` represents a vault is in the unlocked state.

```yaml
- name: isLocked
  type: bool
  stateMutability: view

  inputs: []

  outputs:
    - name: isLocked
      type: bool

```

#### vaultRound

The current round of the vault.

MUST start with `0`.

MUST add `1` each time a new round starts, that is, when the `isLocked` becomes true. MUST NOT be modified in any other circumstances.

```yaml
- name: vaultRound
  type: uint256
  stateMutability: view

  inputs: []

  outputs:
    - name: vaultRound
      type: uint256
```

### Methods

#### scheduleDeposit

Schedule the intent to deposit `assets` when the `isLocked` is true.

MUST only be callable when the `isLocked` is true.

MUST transfer the `assets` from the caller to the vault. MUST not issue new shares.

MUST revert if `assets` cannot be deposited.

MUST revert if the `isLocked` is false.

```yaml
- name: scheduleDeposit
  type: function
  stateMutability: nonpayable

  inputs:
    - name: assets
      type: uint256
```

#### scheduleRedeem

Schedule the intent to redeem `shares` from the vault when the `isLocked` is true.

MUST only be callable when the `isLocked` is true.

MUST transfer the `shares` from the caller to the vault. MUST not transfer assets to caller.

MUST revert if `shares` cannot be redeemed.

MUST revert if the `isLocked` is false.

```yaml
- name: scheduleRedeem
  type: function
  stateMutability: nonpayable

  inputs:
    - name: shares
      type: uint256
```

#### settleDeposits

Process all scheduled deposits for `depositor` and minting `newShares`.

MUST only be callable when the `isLocked` is false.

MUST issue `newShares` according to the current share price for the scheduled `depositor`.

MUST revert if there is no scheduled deposit for `depositor`.

```yaml
- name: settleDeposits
  type: function
  stateMutability: nonpayable

  inputs:
    - name: depositor
    - type: address

  outputs:
    - name: newShares
    - type: uint256
```

#### settleRedemptions

Process all scheduled redemptions for `redeemer` by burning `burnShares` and transferring `redeemAssets` to the `redeemer`.

MUST only be callable when the `isLocked` is false.

MUST burn the `burnShares` and transfer `redeemAssets` back to the `redeemer` according to the current share price.

MUST revert if no scheduled redemption for `redeemer`.

```yaml
- name: settleRedemptions
  type: function
  stateMutability: nonpayable

  inputs:
    - name: redeemer
    - type: address

  outputs:
    - name: burnShares
    - type: uint256
    - name: redeemAssets
    - type: uint256
```

#### getScheduledDeposits

Get the `totalAssets` of scheduled deposits for `depositor`.

MUST NOT revert.

```yaml
- name: getScheduledDeposits
  type: function
  stateMutability: view

  inputs:
    - name: depositor
    - type: address

  outputs:
    - name: totalAssets
    - type: uint256
```

#### getScheduledRedemptions

Get the `totalShares` of scheduled redemptions for `redeemer`.

MUST NOT revert.

```yaml
- name: getScheduledRedemptions
  type: function
  stateMutability: view

  inputs:
    - name: redeemer
    - type: address

  outputs:
    - name: totalShares
    - type: uint256
```

### Events

#### ScheduleDeposit

`sender` schedules a deposit with `assets` in this `round`.

MUST be emitted via `scheduleDeposit` method.

```yaml
- name: ScheduleDeposit
  type: event

  inputs:
    - name: sender
      indexed: true
      type: address
    - name: assets
      indexed: false
      type: uint256
    - name: round
      indexed: false
      type: uint256
```

#### ScheduleRedeem

`sender` schedules a redemption with `shares` in this `round`.

MUST be emitted via `scheduleRedeem` method.

```yaml
- name: ScheduleRedeem
  type: event

  inputs:
    - name: sender
      indexed: true
      type: address
    - name: shares
      indexed: false
      type: uint256
    - name: round
      indexed: false
      type: uint2
```

#### SettleDeposits

Settle scheduled deposits for `depositor` in this `round`. Issue `newShares` and transfer them to the `depositor`.

MUST be emitted via `settleDeposits` method.

```yaml
- name: SettleDeposits
  type: event

  inputs:
    - name: depositor
      indexed: true
      type: address
    - name: newShares
      type: uint256
    - name: round
      type: uint256
```

#### SettleRedemptions

Settle scheduled redemptions for `redeemer` in this `round`. Burn `burnShares` and transfer `redeemAssets` back to the `redeemer`.

MUST be emitted via `settleRedemptions` method.

```yaml
- name: SettleRedemptions
  type: event

  inputs:
    - name: redeemer
      indexed: true
      type: address
    - name: burnShares
      type: uint256
    - name: redeemAssets
      type: uint256
    - name: round
      type: uint256
```

## Rationale

The standard is designed to be a minimal interface. Details such as the start and end of a lock-in period, and how the underlying tokens are being used during the lock-in period are not specified.

There is no function for scheduling a withdrawal, since during the lock-in period, the share price is undetermined, so it is impossible to determine how many underlying tokens can be withdrawn.

## Backwards Compatibility

The `deposit`, `mint`, `withdraw`, `redeem` methods for [EIP-4626](/EIPs/EIPS/eip-4626) should revert when the `isLocked` is true to prevent issuing or burning shares with an undefined share price.

## Security Considerations

Implementors need to be aware of unsettled scheduled deposits and redemptions. If a user has scheduled a deposit or redemption but does not settle when the `isLocked` is false, and then settles it after several rounds, the vault will process it with an incorrect share price. We didn’t specify the solution in the standard since there are many possible ways to solve this issue and we think implementors should decide the solution according to their use cases. For example:

- Not allow the `isLocked` to become true if there is any unsettled scheduled deposit or redemption
- Force settling the scheduled deposits or redemptions when the `isLocked` becomes true
- Memorize the ending share price for each round and let the users settle according to the share prices

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 21 Dec 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6229</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6229</guid>
      </item>
    
      <item>
        <title>Semantic Soulbound Tokens</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6239-semantic-soulbound-tokens/12334</comments>
        
        <description>## Abstract

This proposal extends [ERC-721](/EIPs/EIPS/eip-721) and [ERC-5192](/EIPs/EIPS/eip-5192) by introducing Resource Description Framework (RDF) triples to Soulbound Tokens&apos; (‘SBTs‘) metadata.



## Motivation

A Soulbound Token represents the commitments, credentials, and affiliations of accounts. RDF is a standard data model developed by the World Wide Web Consortium (‘W3C’) and is used to represent information in a structured format. Semantic SBTs are built on existing [ERC-721](/EIPs/EIPS/eip-721) and [ERC-5192](/EIPs/EIPS/eip-5192) standards to include RDF triples in metadata to capture and store the meaning of social metadata as a network of accounts and attributes.

Semantic SBT provides a foundation for publishing, linking, and integrating data from multiple sources, and enables the ability to query and retrieve information across these sources, using inference to uncover new insights from existing social relations. For example, form the on-chain united social graph, assign trusted contacts for social recovery, and supports fair governance.

While the existence of SBTs can create a decentralized social framework, there still needs to specify a common data model to manage the social metadata on-chain in a trustless manner, describing social metadata in an interconnected way, make it easy to be exchanged, integrated and discovered. And to further fuel the boom of the SBTs ecosystem, we need a bottom-up and decentralized way to maintain people’s social identity related information.

Semantic SBTs address this by storing social metadata, attestations, and access permissions on-chain to bootstrap the social identity layer and a linked data layer natively on Ethereum, and bring semantic meanings to the tons of bits of on-chain data.

### Connectedness

Semantic SBTs store social data as RDF triples in the Subject-Predicate-Object format, making it easy to create relationships between accounts and attributes.  RDF is a standard for data interchange used to represent highly interconnected data. Representing data in RDF triples makes it simpler for automated systems to identify, clarify, and connect information.

### Linked Data

Semantic SBTs allow the huge amount of social data on-chain to be available in a standard format (RDF) and be reachable and manageable. The interrelated datasets on-chain can create the linked data layer that allows social data to be mixed, exposed, and shared across different applications, providing a convenient, cheap, and reliable way to retrieve data, regardless of the number of users.

### Social Identity

Semantic SBTs allow people to publish or attest their own identity-related data in a bottom-up and decentralized way, without reliance on any centralized intermediaries while setting every party free. The data is fragmentary in each Semantic SBT and socially interrelated. RDF triples enable various community detection algorithms to be built on top.

This proposal outlines the semantic data modeling of SBTs that allows implementers to model the social relations among Semantic SBTs, especially in the social sector.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

- The token **MUST** implement the following interfaces:
    1. [ERC-165](/EIPs/EIPS/eip-165)’s `ERC165` (`0x01ffc9a7`)
    1. [ERC-721](/EIPs/EIPS/eip-721)’s `ERC721` (`0x80ac58cd`)
    1. [ERC-721](/EIPs/EIPS/eip-721)’s `ERC721Metadata` (`0x5b5e139f`)
    1. [ERC-5192](/EIPs/EIPS/eip-5192)’s `ERC5192` (`0xb45a3c0e`)

### RDF Statement

RDF statements come in various formats, we have selected the six most commonly used formats: `nt(N-Triples)`,`ttl(Turtle)`,`rdf(RDF/XML)`,`rj(RDF/JSON)`,`nq(N-Quads)` and `trig(TriG)`.

The complete format of an RDF statement:

```text
rdfStatements = {[format]}&lt;statements&gt;
```

In the following section, fragments surrounded by `{}` characters are OPTIONAL.

In the following section, fragments surrounded by `&lt;&gt;` characters are REQUIRED.

format: nt/ttl/rdf/rj/nq/trig

When no format is selected: statements = [ttl]statements

- `nt(n-triples)`

`nt` uses space to separate the subject, predicate, object of a triple, and a period . to indicate the end of a triple.

The basic structure is:

```text
subject predicate object .
```

In this format, the subject is in the format of IRIREF or BLANK_NODE_LABEL, the predicate is in the format of IRIREF, and the object is in the format of IRIREF, BLANK_NODE_LABEL, or STRING_LITERAL_QUOTE.

For example:

```text
&lt;http://example.org/entity/user1&gt; &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&gt; &lt;http://example.org/entity/User&gt; .
&lt;http://example.org/entity/user1&gt; &lt;http://example.org/property/name&gt; &quot;Alice&quot; .
```

- `ttl(Turtle)`

Compared to `nt`, `ttl` uses prefixes to simplify the IRIREF format, and the same predicate under the same subject can be merged without repeating it. &quot;a&quot; can be used to represent `&lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&gt;`.


For example:

```text
@prefix : &lt;http://example.org/entity/&gt; .
@prefix p: &lt;http://example.org/property/&gt; .

:user1 a :User;
       p:name ”Alice” .
```

- `rdf(RDF/XML)`

`rdf` describes RDF in XML format, using rdf:RDF as the top-level element, and xmlns to describe prefixes. rdf:Description begins describing a node, rdf:about defines the node to be described, and rdf:resource fills in the property value in the format of IRI. If the property value is a string, the property value can be directly written as the text of the property node.

The basic structure is:

```xml
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;rdf:RDF xmlns:rdf=&quot;http://www.w3.org/1999/ 02/22-rdf-syntax-ns#&quot;&gt;

 &lt;rdf:Description rdf:about=&quot;subject&quot; &gt;
  &lt;predicate rdf:resource=&quot;object&quot;/&gt;
   &lt;predicate &gt;object&lt;/predicate&gt;
 &lt;/rdf:Description&gt;
&lt;/rdf:RDF&gt;
```

For example:

```xml
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;rdf:RDF xmlns:rdf=&quot;http://www.w3.org/1999/ 02/22-rdf-syntax-ns#&quot;
           xmlns:p=&quot;http://example.org/property/&quot;&gt;

 &lt;rdf:Description rdf:about=&quot;http://example.org/entity/user1&quot; &gt;
   &lt;rdf:type rdf:resource=&quot;http://example.org/entity/&quot;/&gt;
  &lt;p:name &gt;Alice&lt;/p:name&gt;
 &lt;/rdf:Description&gt;
&lt;/rdf:RDF&gt;
```

- `rj(RDF/JSON)`


`rj` describes RDF in JSON format. A triple is described as:


```text
  {&quot;subject&quot;:{&quot;predicate&quot;:[object]}}
```

Note that each root object is a unique primary key and duplicates are not allowed. There will be no duplicate subjects as keys, and there will be no duplicate predicates under a single subject.

For example:

```json
   {
 &quot;http://example.org/entity/user1&quot;: {
   &quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&quot;: [
     &quot;http://example.org/entity/User&quot;
   ],
   &quot;http://example.org/property/name&quot;: [
     &quot;Alice&quot;
   ]
 }
}

```

- `nq(N-Quads)`

`nq` is based on `nt` but includes a graph label that describes the dataset to which an RDF triple belongs. The graph label can be in the format of IRIREF or BLANK_NODE_LABEL.

The basic structure is:

```text
subject predicate object graphLabel.
```

For example:

```text
&lt;http://example.org/entity/user1&gt; &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#type&gt; &lt;http://example.org/entity/User&gt; &lt;http://example.org/graphs/example&gt; .
&lt;http://example.org/entity/user1&gt; &lt;http://example.org/property/name&gt; &quot;Alice&quot; &lt;http://example.org/graphs/example&gt; .
```

- `trig(TriG)`


`trig` is an extension of `ttl` that includes a graph label to describe the dataset to which an RDF triple belongs. The triple statements are enclosed in curly braces {}.

For example:

```text
@prefix : &lt;http://example.org/entity/&gt; .
@prefix p: &lt;http://example.org/property/&gt; .

&lt;http://example.org/graphs/example&gt;
  {
       :user1 a :User;
              p:name ”Alice” .

   }
```

In the contract events: `CreateRDF`, `UpdateRDF`, `RemoveRDF`, and the `rdfOf method`, the  `rdfStatements` is used in `ttl` format by default. If other formats listed above are used, a format identifier needs to be added for identification.

The format identifier starts with `[` and ends with `]` with the format in the middle, i.e., `[format]`.

For example, the `rdfStatements` in `nt` format should include the prefix `[nt]`.

```text
[nt]subject predicate object .
```


### Contract Interface

```solidity
/**
 * @title Semantic Soulbound Token
 * Note: the ERC-165 identifier for this interface is 0xfbafb698
 */
interface ISemanticSBT{
    /**
     * @dev This emits when minting a Semantic Soulbound Token.
     * @param tokenId The identifier for the Semantic Soulbound Token.
     * @param rdfStatements The RDF statements for the Semantic Soulbound Token. 
     */
    event CreateRDF (
        uint256 indexed tokenId,
        string  rdfStatements
    );
    /**
     * @dev This emits when updating the RDF data of Semantic Soulbound Token. RDF data is a collection of RDF statements that are used to represent information about resources.
     * @param tokenId The identifier for the Semantic Soulbound Token.
     * @param rdfStatements The RDF statements for the semantic soulbound token. 
     */
    event UpdateRDF (
        uint256 indexed tokenId,
        string  rdfStatements
    );
    /**
     * @dev This emits when burning or revoking Semantic Soulbound Token.
     * @param tokenId The identifier for the Semantic Soulbound Token.
     * @param rdfStatements The RDF statements for the Semantic Soulbound Token. 
     */
    event RemoveRDF (
        uint256 indexed tokenId,
        string  rdfStatements
    );
    /**
     * @dev Returns the RDF statements of the Semantic Soulbound Token. 
     * @param tokenId The identifier for the Semantic Soulbound Token.
     * @return rdfStatements The RDF statements for the Semantic Soulbound Token. 
     */
    function rdfOf(uint256 tokenId) external view returns (string memory rdfStatements);
}
```

`ISemanticRDFSchema`, an extension of ERC-721 Metadata, is **OPTIONAL** for this standard, it is used to get the Schema URI for the RDF data.

```solidity
interface ISemanticRDFSchema{
    /**
     * @notice Get the URI of schema for this contract.
     * @return The URI of the contract which point to a configuration profile.
     */
    function schemaURI() external view returns (string memory);
}
```


### Method Specification

`rdfOf (uint256 tokenId)`: Query the RDF data for the Semantic Soulbound Token by `tokenId`. The returned RDF data format conforms to the W3C RDF standard. RDF data is a collection of RDF statements that are used to represent information about resources. An RDF statement, also known as a triple, is a unit of information in the RDF data model. It consists of three parts: a subject, a predicate, and an object.

`schemaURI()`: This **OPTIONAL** method is used to query the URIs of the schema for the RDF data. RDF Schema is an extension of the basic RDF vocabulary and provides a data-modelling vocabulary for RDF data. It is **RECOMMENDED** to store the RDF Schema in decentralized storage such as Arweave or IPFS. The URIs are then stored in the contract and can be queried by this method.

### Event Specification

`CreateRDF`: When minting a Semantic Soulbound Token, this event **MUST** be triggered to notify the listener to perform operations with the created RDF data. When calling the event, the input RDF data **MUST** be RDF statements, which are units of information consisting of three parts: a subject, a predicate, and an object.

`UpdateRDF`: When updating RDF data for a Semantic Soulbound Token, this event **MUST** be triggered to notify the listener to perform update operations accordingly with the updated RDF data. When calling the event, the input RDF data **MUST** be RDF statements, which are units of information consisting of three parts: a subject, a predicate, and an object.

`RemoveRDF`: When burning or revoking a Semantic Soulbound Token, this event **MUST** be triggered to notify the listener to perform operations with the removed RDF data for the Semantic SBT. When calling the event, the input RDF data **MUST** be RDF statements, which are units of information consisting of three parts: a subject, a predicate, and an object.

## Rationale


RDF is a flexible and extensible data model based on creating subject-predicate-object relationships, often used to model graph data due to its semantic web standards, Linked Data concept, flexibility, and query capabilities. RDF allows graph data to be easily integrated with other data sources on the web, making it possible to create more comprehensive and interoperable models. The advantage of using RDF for semantic description is that it can describe richer information, including terms, categories, properties, and relationships. RDF uses standard formats and languages to describe metadata, making the expression of semantic information more standardized and unified. This helps to establish more accurate and reliable semantic networks, promoting interoperability between different systems. Additionally, RDF supports semantic reasoning, which allows the system to automatically infer additional relationships and connections between nodes in the social graph based on the existing data.


There are multiple formats for RDF statements. We list six most widely adopted RDF statement formats in the EIP: `Turtle`, `N-Triples`, `RDF/XML`, `RDF/JSON`,`N-Quads`, and `TriG`. These formats have different advantages and applicability in expressing, storing, and parsing RDF statements. Among these, `Turtle` is a popular format in RDF statements, due to its good human-readability and concision. It is typically used as the default format in this EIP for RDF statements. Using the Turtle format can make RDF statements easier to understand and maintain, while reducing the need for storage, suitable for representing complex RDF graphs.


## Backwards Compatibility

This proposal is fully backward compatible with [ERC-721](/EIPs/EIPS/eip-721) and [ERC-5192](/EIPs/EIPS/eip-5192).

## Security Considerations

There are no security considerations related directly to the implementation of this standard.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE). 
</description>
        <pubDate>Fri, 30 Dec 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6239</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6239</guid>
      </item>
    
      <item>
        <title>Untransferability Indicator for EIP-1155</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/sbt-implemented-in-erc1155/12182</comments>
        
        <description>## Abstract

This EIP standardizes an interface indicating [EIP-1155](/EIPs/EIPS/eip-1155)-compatible token non-transferability using [EIP-165](/EIPs/EIPS/eip-165) feature detection.

## Motivation

Soulbound Tokens (SBT) are non-transferable tokens. While [EIP-5192](/EIPs/EIPS/eip-5192) standardizes non-fungible SBTs, a standard for Soulbound semi-fungible or fungible tokens does not yet exist. The introduction of a standard non-transferability indicator that is agnostic to fungibility promotes the usage of Souldbound semi-fungible or fungible tokens.

## Specification

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

Smart contracts implementing this standard MUST comform to the [EIP-1155](/EIPs/EIPS/eip-1155) specification.

Smart contracts implementing this standard MUST implement all of the functions in the `IERC6268` interface.

Smart contracts implementing this standard MUST implement the [EIP-165](/EIPs/EIPS/eip-165) supportsInterface function and MUST return the constant value true if `0xd87116f3` is passed through the interfaceID argument.

For the token identifier `_id` that is marked as `locked`, `locked(_id)` MUST return the constant value true and any functions that try transferring the token, including `safeTransferFrom` and `safeBatchTransferFrom` function MUST throw.

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

interface IERC6268 {
  /// @notice Either `LockedSingle` or `LockedBatch` MUST emit when the locking status is changed to locked.
  /// @dev If a token is minted and the status is locked, this event should be emitted.
  /// @param _id The identifier for a token.
  event LockedSingle(uint256 _id);

  /// @notice Either `LockedSingle` or `LockedBatch` MUST emit when the locking status is changed to locked.
  /// @dev If a token is minted and the status is locked, this event should be emitted.
  /// @param _ids The list of identifiers for tokens.
  event LockedBatch(uint256[] _ids);

  /// @notice Either `UnlockedSingle` or `UnlockedBatch` MUST emit when the locking status is changed to unlocked.
  /// @dev If a token is minted and the status is unlocked, this event should be emitted.
  /// @param _id The identifier for a token.
  event UnlockedSingle(uint256 _id);

  /// @notice Either `UnlockedSingle` or `UnlockedBatch` MUST emit when the locking status is changed to unlocked.
  /// @dev If a token is minted and the status is unlocked, this event should be emitted.
  /// @param _ids The list of identifiers for tokens.
  event UnlockedBatch(uint256[] _ids);


  /// @notice Returns the locking status of the token.
  /// @dev SBTs assigned to zero address are considered invalid, and queries
  /// about them do throw.
  /// @param _id The identifier for a token.
  function locked(uint256 _id) external view returns (bool);

  /// @notice Returns the locking statuses of the multiple tokens.
  /// @dev SBTs assigned to zero address are considered invalid, and queries
  /// about them do throw.
  /// @param _ids The list of identifiers for tokens
  function lockedBatch(uint256[] _ids) external view returns (bool);
}
```

## Rationale

Needs discussion.

## Backwards Compatibility

This proposal is fully backward compatible with [EIP-1155](/EIPs/EIPS/eip-1155).

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 06 Jan 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6268</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6268</guid>
      </item>
    
      <item>
        <title>ERC-2771 Namespaced Account Abstraction</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/trustless-eip-2771/12497</comments>
        
        <description>## Abstract

[ERC-2771](/EIPs/EIPS/eip-2771) is a prevalent standard for handling meta-transactions via trusted forwarders. This EIP proposes an extension to [ERC-2771](/EIPs/EIPS/eip-2771) to introduce a namespacing mechanism, facilitating trustless account abstraction through per-forwarder namespaced addresses.

## Specification

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

The key words &quot;Forwarder&quot; and &quot;Recipient&quot; in this document are to be interpreted as described in [ERC-2771](/EIPs/EIPS/eip-2771).

### Namespaced Forwarder Interface

```solidity
pragma solidity ^0.8.0;

interface INamespacedForwarder {
    function isNamespacedTransaction() external view returns (bool);
}
```

### Determining the Sender and Forwarder

Upon function invocation on a Recipient, the Recipient MUST execute a `STATICCALL` to the `isNamespacedTransaction()` method of the caller. If this operation reverts or returns the boolean value `false`, the transaction MUST proceed normally, identifying the caller as the sender, and the Forwarder as the zero address. However, if the boolean value `true` is returned, the transaction is acknowledged as a namespaced transaction, with the sender identified using the procedure outlined in [ERC-2771](/EIPs/EIPS/eip-2771#extracting-the-transaction-signer-address), and the Forwarder identified as the caller.

### Recipient Extensions

Whenever a Recipient contract has a function with one or more function parameters of type address, it MUST also provide a new function, mirroring the name of the original function but appending `Namespaced` at the end, which accepts two addresses instead. The initial address denotes the Forwarder, while the latter represents the address managed by that Forwarder. If a function accepts multiple address parameters (e.g., [ERC-20](/EIPs/EIPS/eip-20)&apos;s `transferFrom`), a version of the function accepting two addresses per original address parameter MUST be provided. The original function MUST exhibit identical behavior to the new function when Forwarder addresses are the zero address.

For instance, [ERC-20](/EIPs/EIPS/eip-20) would be extended with these functions:

```solidity
function transferNamespaced(address toForwarder, address toAddress, uint256 amount);
function approveNamespaced(address spenderForwarder, address spenderAddress, uint256 amount);
function transferFromNamespaced(address fromForwarder, address fromAddress, address toForwarder, address toAddress, uint256 amount);
```

#### [ERC-165](/EIPs/EIPS/eip-165)

Recipient contracts MUST implement ERC-165. When an ERC-165 interface ID is registered, a second interface ID corresponding to the XOR of the Namespaced function selectors of the original interface must also be registered.

## Rationale

The approach of simply augmenting existing EIP functions with new `address` parameters, rather than crafting new interfaces for the most commonly used EIPs, is employed to ensure broader applicability of this namespacing proposal.

## Backwards Compatibility

Contracts already deployed cannot not benefit from this namespacing proposal. This limitation also extends to ERC-2771.

### Using this EIP in standards

When using this EIP in another standard, both the original and the Namespaced interface IDs SHOULD be provided. Interfaces MUST NOT include namespaced versions of functions in their interfaces.

## Security Considerations

This proposal alters trust dynamics: Forwarders no longer require Recipient trust, but instead require the trust of their users.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 11 Jan 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6315</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6315</guid>
      </item>
    
      <item>
        <title>Elastic Signature</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6327-elastic-signature-es/12554</comments>
        
        <description>## Abstract

Elastic signature (ES) aims to sign data with a human friendly secret. The secret will be verified fully on-chain and is not stored anywhere. A user can change the secret as often as they need to. The secret does not have a fixed length. The secret will be like a password, which is a better understood concept than private key. This is specifically true for non-technical users. This EIP defines a smart contract interface to verify and authorize operations with ES.


## Motivation

What would a changeable &quot;private key&quot; enable us? For years, we have been looking for ways to lower on-boarding barrier for users, especially those with less technical experiences. Private key custody solutions seem to provide an user friendly on-boarding experience, but it is vendor dependent and is not decentralized. ES makes a breakthrough with Zero-knowledge technology. Users generate proof of knowing the secret and a smart contract will verify the proof. 

### Use case

ES is an alternative signing algorithm. It is not an either-or solution to the private key. It is designed to serve as an additional signing mechanism on top of the private key signature.

- A DeFi app can utilize ES into their transfer fund process. Users will be required to provide their passwords to complete the transaction. This gives an extra protection even if the private key is compromised.
- ES can also be used as a plugin to a smart contract wallet, like Account Abstraction [ERC-4337](/EIPs/EIPS/eip-4337). A decentralized password is picked instead of the private key. This could lead to a smooth onboarding experiences for new Ethereum Dapp users.


## Specification

Let:

- `pwdhash` represents the hash of the private secret (password).
- `datahash` represents the hash of an intended transaction data.
- `fullhash` represents the hash of `datahash` and all the well-known variables.
- `expiration` is the timestamp after which the intended transaction expires. 
- `allhash` represents the hash of `fullhash` and `pwdhash`.


There are three parties involved, Verifier, Requester and Prover.

- A verifier, 
  - SHOULD compute `fullhash` from a `datahash`, which is provided by the requester.
  - SHOULD derive `pwdhash` for a given address. The address can be an EOA or a smart contract wallet.
  - SHOULD verify the proof with the derived `pwdhash`, the computed `fullhash` and a `allhash`, which is submitted by the requester.
- A requester
  - SHOULD generate `datahash` and decide an `expiration`.
  - SHALL request a verification from the verifier with, 
    - `proof` and `allhash` which are provided by the prover;
    - `datahash`;
    - `expiration`.
- A prover
  - SHOULD generate the `proof` and `allhash` from, 
    - `datahash` and `expiration` which are agreed with the requester;
    - `nonce` and other well-known variables. 

There are also some requirements.

- well-known variable SHOULD be available to all parties.
  - SHOULD include a `nonce`.
  - SHOULD include a `chainid`.
  - MAY include any variable that is specific to the verifier.
- public statements SHOULD include, 
  - one reflecting the `pwdhash`;
  - one reflecting the `fullhash`;
  - one reflecting the `allhash`.
- The computation of `fullhash` SHOULD be agreed by both the verifier and the prover.
- The computation of `datahash`

### `IElasticSignature` Interface 

This is the verifier interface.

```solidity
pragma solidity ^0.8.0;

interface IElasticSignature {
    /**
     * Event emitted after user set/reset their password
     * @param user - an user&apos;s address, for whom the password hash is set. It could be a smart contract wallet address
     *  or an EOA wallet address.
     * @param pwdhash - a password hash
     */
    event SetPassword(address indexed user, uint indexed pwdhash);

    /**
     * Event emitted after a successful verification performed for an user
     * @param user - an user&apos;s address, for whom the submitted `proof` is verified. It could be a smart contract wallet
     *  address or an EOA wallet address.
     * @param nonce - a new nonce, which is newly generated to replace the last used nonce. 
     */
    event Verified(address indexed user, uint indexed nonce);

    /**
     * Get `pwdhash` for a user
     * @param user - a user&apos;s address 
     * @return - the `pwdhash` for the given address
     */
    function pwdhashOf(address user) external view returns (uint);

    /**
     * Update an user&apos;s `pwdhash`
     * @param proof1 - proof generated by the old password
     * @param expiration1 - old password signing expiry seconds
     * @param allhash1 - allhash generated with the old password
     * @param proof2 - proof generated by the new password
     * @param pwdhash2 - hash of the new password
     * @param expiration2 - new password signing expiry seconds
     * @param allhash2 - allhash generated with the new password
     */
    function resetPassword(
        uint[8] memory proof1,
        uint expiration1,
        uint allhash1,
        uint[8] memory proof2,
        uint pwdhash2,
        uint expiration2,
        uint allhash2
    ) external;

    /**
     * Verify a proof for a given user
     * It should be invoked by other contracts. The other contracts provide the `datahash`. The `proof` is generated by
     *  the user. 
     * @param user -  a user&apos;s address, for whom the verification will be carried out.
     * @param proof - a proof generated by the password
     * @param datahash - the data what user signing, this is the hash of the data
     * @param expiration - number of seconds from now, after which the proof is expired 
     * @param allhash - public statement, generated along with the `proof`
     */
    function verify(
        address user,
        uint[8] memory proof,
        uint datahash,
        uint expiration,
        uint allhash
    ) external;
}
```

`verify` function SHOULD be called by another contract. The other contract SHOULD generate the `datahash` to call this. The function SHOULD verify if the `allhash` is computed correctly and honestly with the password.


## Rationale

The contract will store everyone&apos;s `pwdhash`.

![verifier-contract](/EIPs/assets/eip-6327/zkpass-1.png)

The chart below shows ZK circuit logic.

![circuit-logic](/EIPs/assets/eip-6327/zkpass-2.png)

To verify the signature, it needs `proof`, `allhash`, `pwdhash` and `fullhash`.

![workflow](/EIPs/assets/eip-6327/zkpass-3.png)

The prover generates `proof` along with the public outputs. They will send all of them to a third-party requester contract. The requester will generate the `datahash`. It sends `datahash`, `proof`, `allhash`, `expiration` and prover&apos;s address to the verifier contract. The contract verifies that the `datahash` is from the prover, which means the withdrawal operation is signed by the prover&apos;s password.


## Backwards Compatibility

This EIP is backward compatible with previous work on signature validation since this method is specific to password based signatures and not EOA signatures. 


## Reference Implementation

Example implementation of a signing contract:

```solidity
pragma solidity ^0.8.0;

import &quot;../interfaces/IElasticSignature.sol&quot;;
import &quot;./verifier.sol&quot;;

contract ZKPass is IElasticSignature {
    Verifier verifier = new Verifier();

    mapping(address =&gt; uint) public pwdhashOf;

    mapping(address =&gt; uint) public nonceOf;

    constructor() {
    }

    function resetPassword(
        uint[8] memory proof1,
        uint expiration1,
        uint allhash1,
        uint[8] memory proof2,
        uint pwdhash2,
        uint expiration2,
        uint allhash2
    ) public override {
        uint nonce = nonceOf[msg.sender];

        if (nonce == 0) {
            //init password

            pwdhashOf[msg.sender] = pwdhash2;
            nonceOf[msg.sender] = 1;
            verify(msg.sender, proof2, 0, expiration2, allhash2);
        } else {
            //reset password

            // check old pwdhash
            verify(msg.sender, proof1, 0, expiration1, allhash1);

            // check new pwdhash
            pwdhashOf[msg.sender] = pwdhash2;
            verify(msg.sender, proof2, 0, expiration2, allhash2);
        }

        emit SetPassword(msg.sender, pwdhash2);
    }

    function verify(
        address user,
        uint[8] memory proof,
        uint datahash,
        uint expiration,
        uint allhash
    ) public override {
        require(
            block.timestamp &lt; expiration,
            &quot;ZKPass::verify: expired&quot;
        );

        uint pwdhash = pwdhashOf[user];
        require(
            pwdhash != 0,
            &quot;ZKPass::verify: user not exist&quot;
        );

        uint nonce = nonceOf[user];
        uint fullhash = uint(keccak256(abi.encodePacked(expiration, block.chainid, nonce, datahash))) / 8; // 256b-&gt;254b
        require(
            verifyProof(proof, pwdhash, fullhash, allhash),
            &quot;ZKPass::verify: verify proof fail&quot;
        );

        nonceOf[user] = nonce + 1;

        emit Verified(user, nonce);
    }

    /////////// util ////////////

    function verifyProof(
        uint[8] memory proof,
        uint pwdhash,
        uint fullhash, //254b
        uint allhash
    ) internal view returns (bool) {
        return
            verifier.verifyProof(
                [proof[0], proof[1]],
                [[proof[2], proof[3]], [proof[4], proof[5]]],
                [proof[6], proof[7]],
                [pwdhash, fullhash, allhash]
            );
    }
}
```

verifier.sol is auto generated by snarkjs, the source code circuit.circom is below

```javascript
pragma circom 2.0.0;

include &quot;../../node_modules/circomlib/circuits/poseidon.circom&quot;;

template Main() {
    signal input in[3];
    signal output out[3];

    component poseidon1 = Poseidon(2);
    component poseidon2 = Poseidon(2);

    poseidon1.inputs[0] &lt;== in[0];  //pwd
    poseidon1.inputs[1] &lt;== in[1];  //address
    out[0] &lt;== poseidon1.out; //pwdhash

    poseidon2.inputs[0] &lt;== poseidon1.out;
    poseidon2.inputs[1] &lt;== in[2]; //fullhash
    out[1] &lt;== in[2]; //fullhash
    out[2] &lt;== poseidon2.out; //allhash
}

component main = Main();
```


## Security Considerations

Since the pwdhash is public, it is possible to be crack the password. We estimate the Poseidon hash rate of RTX3090 would be 100Mhash/s, this is the estimate of crack time:

8 chars (number) : 1 secs

8 chars (number + english) : 25 days

8 chars (number + english + symbol) : 594 days

12 chars (number) : 10000 secs

12 chars (number + english) : 1023042 years

12 chars (number + english + symbol) : 116586246 years

The crack difficulty of private key is 2^256, the crack difficulty of 40 chars (number + english + symbol) is 92^40, 92^40 &gt; 2^256, so when password is 40 chars , it is more difficult to be crack than private key.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 13 Jan 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6327</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6327</guid>
      </item>
    
      <item>
        <title>Charity token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc20-charity-token/12617</comments>
        
        <description>## Abstract

An extension to [EIP-20](/EIPs/EIPS/eip-20) that can automatically send an additional percentage of each transfer to a third party, and that provides an interface for retrieving this information. This can allow token owners to make donations to a charity with every transfer. This can also be used to allow automated savings programs.

## Motivation

There are charity organizations with addresses on-chain, and there are token holders who want to make automated donations. Having a standardized way of collecting and managing these donations helps users and user interface developers. Users can make an impact with their token and can contribute to achieving sustainable blockchain development. Projects can easily retrieve charity donations addresses and rate for a given [EIP-20](/EIPs/EIPS/eip-20) token, token holders can compare minimum rate donation offers allowed by token contract owners. This standard provides functionality that allows token holders to donate easily.

## Specification

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.

Owner of the contract **MAY**, after review, register charity address in `whitelistedRate` and set globally a default rate of donation. To register the address, the rate **MUST** not be null.

Token holders **MAY** choose and specify a default charity address from `_defaultAddress`, this address **SHOULD** be different from the null address for the donation to be activated.

The donation is a percentage-based rate model, but the calculation can be done differently. Applications and individuals can implement this standard by retrieving information with `charityInfo()` , which specifies an assigned rate for a given address.

This standard provides functionality that allows token holders to donate easily. The donation when activated is done directly in the overridden `transfer`, `transferFrom`, and `approve` functions.

When `transfer`, `transferFrom` are called the sender&apos;s balance is reduced by the initial amount and a donation amount is deduced. The initial transferred amount is transferred to the recipient&apos;s balance and an additional donation amount is transferred to a third party (charity). The two transfer are done at the same time and emit two `Transfer` events.
Also, if the account has an insufficient balance to cover the transfer and the donation the whole transfer would revert.

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.4;

///
/// @dev Required interface of an ERC20 Charity compliant contract.
///
interface IERC20charity is IERC165 {
    /// The EIP-165 identifier for this interface is 0x557512b6

    
    /**
     * @dev Emitted when `toAdd` charity address is added to `whitelistedRate`.
     */
    event AddedToWhitelist (address toAdd);

    /**
     * @dev Emitted when `toRemove` charity address is deleted from `whitelistedRate`.
     */
    event RemovedFromWhitelist (address toRemove);

    /**
     * @dev Emitted when `_defaultAddress` charity address is modified and set to `whitelistedAddr`.
     */
    event DonnationAddressChanged (address whitelistedAddr);

    /**
     * @dev Emitted when `_defaultAddress` charity address is modified and set to `whitelistedAddr` 
    * and _donation is set to `rate`.
     */
    event DonnationAddressAndRateChanged (address whitelistedAddr,uint256 rate);

    /**
     * @dev Emitted when `whitelistedRate` for `whitelistedAddr` is modified and set to `rate`.
     */
    event ModifiedCharityRate(address whitelistedAddr,uint256 rate);
    
    /**
    *@notice Called with the charity address to determine if the contract whitelisted the address
    *and if it is the rate assigned.
    *@param addr - the Charity address queried for donnation information.
    *@return whitelisted - true if the contract whitelisted the address to receive donnation
    *@return defaultRate - the rate defined by the contract owner by default , the minimum rate allowed different from 0
    */
    function charityInfo(
        address addr
    ) external view returns (
        bool whitelisted,
        uint256 defaultRate
    );

    /**
    *@notice Add address to whitelist and set rate to the default rate.
    * @dev Requirements:
     *
     * - `toAdd` cannot be the zero address.
     *
     * @param toAdd The address to whitelist.
     */
    function addToWhitelist(address toAdd) external;

    /**
    *@notice Remove the address from the whitelist and set rate to the default rate.
    * @dev Requirements:
     *
     * - `toRemove` cannot be the zero address.
     *
     * @param toRemove The address to remove from whitelist.
     */
    function deleteFromWhitelist(address toRemove) external;

    /**
    *@notice Get all registered charity addresses.
     */
    function getAllWhitelistedAddresses() external ;

    /**
    *@notice Display for a user the rate of the default charity address that will receive donation.
     */
    function getRate() external view returns (uint256);

    /**
    *@notice Set personlised rate for charity address in {whitelistedRate}.
    * @dev Requirements:
     *
     * - `whitelistedAddr` cannot be the zero address.
     * - `rate` cannot be inferior to the default rate.
     *
     * @param whitelistedAddr The address to set as default.
     * @param rate The personalised rate for donation.
     */
    function setSpecificRate(address whitelistedAddr , uint256 rate) external;

    /**
    *@notice Set for a user a default charity address that will receive donation. 
    * The default rate specified in {whitelistedRate} will be applied.
    * @dev Requirements:
     *
     * - `whitelistedAddr` cannot be the zero address.
     *
     * @param whitelistedAddr The address to set as default.
     */
    function setSpecificDefaultAddress(address whitelistedAddr) external;

    /**
    *@notice Set for a user a default charity address that will receive donation. 
    * The rate is specified by the user.
    * @dev Requirements:
     *
     * - `whitelistedAddr` cannot be the zero address.
     * - `rate` cannot be less than to the default rate 
     * or to the rate specified by the owner of this contract in {whitelistedRate}.
     *
     * @param whitelistedAddr The address to set as default.
     * @param rate The personalised rate for donation.
     */
    function setSpecificDefaultAddressAndRate(address whitelistedAddr , uint256 rate) external;

    /**
    *@notice Display for a user the default charity address that will receive donation. 
    * The default rate specified in {whitelistedRate} will be applied.
     */
    function specificDefaultAddress() external view returns (
        address defaultAddress
    );

    /**
    *@notice Delete The Default Address and so deactivate donnations .
     */
    function deleteDefaultAddress() external;
}

```

### Functions

#### **addToWhitelist**

Add address to whitelist and set the rate to the default rate.

| Parameter | Description |
| ---------|-------------|
| toAdd | The address to the whitelist.

#### **deleteFromWhitelist**

Remove the address from the whitelist and set rate to the default rate.

| Parameter | Description |
| ---------|-------------|
| toRemove | The address to remove from whitelist.

#### **getAllWhitelistedAddresses**

Get all registered charity addresses.

#### **getRate**

Display for a user the rate of the default charity address that will receive donation.

#### **setSpecificRate**

Set personalized rate for charity address in {whitelistedRate}.

| Parameter | Description |
| ---------|-------------|
| whitelistedAddr | The address to set as default. |
| rate  | The personalised rate for donation. |

#### **setSpecificDefaultAddress**

Set for a user a default charity address that will receive donations. The default rate specified in {whitelistedRate} will be applied.

| Parameter | Description |
| ---------|-------------|
| whitelistedAddr | The address to set as default.

#### **setSpecificDefaultAddressAndRate**

Set for a user a default charity address that will receive donations. The rate is specified by the user.

| Parameter | Description |
| ---------|-------------|
| whitelistedAddr | The address to set as default. |
| rate  | The personalized rate for donation.

#### **specificDefaultAddress**

Display for a user the default charity address that will receive donations. The default rate specified in {whitelistedRate} will be applied.

#### **deleteDefaultAddress**

Delete The Default Address and so deactivate donations.

#### **charityInfo**

Called with the charity address to determine if the contract whitelisted the address and if it is, the rate assigned.

| Parameter | Description |
| ---------|-------------|
| addr | The Charity address queried for donnation information.

## Rationale

 This EIP chooses to whitelist charity addresses by using an array and keeping track of the &quot;active&quot; status with a mapping `whitelistedRate` to allow multiple choice of recipient and for transparence. The donation address can also be a single address chosen by the owner of the contract and modified by period.

 If the sender balance is insuficent i.e total amount of token (initial transfer + donation) is insuficent the transfer would revert. Donation are done in the `transfer` function to simplify the usage and to not add an additional function, but the implementation could be donne differently, and for example allow a transfer to go through without the donation amount when donation is activated. The token implementer can also choose to store the donation in the contract or in another one and add a withdrawal or claimable function, so the charity can claim the allocated amount of token themselves, the additional transfer will be triggered by the charity and not the token holder.

 Also, donations amount are calculated here as a percentage of the amount of token transferred to allow different case scenario, but the token implementer can decide to opt for another approach instead like rounding up the transaction value.

## Backwards Compatibility

This implementation is an extension of the functionality of [EIP-20](/EIPs/EIPS/eip-20), it introduces new functionality retaining the core interfaces and functionality of the [EIP-20](/EIPs/EIPS/eip-20) standard. There is a small backwards compatibility issue, indeed if an account has insufficient balance, it&apos;s possible for the transfer to fail.

## Test Cases

Tests can be found in [`charity.js`](/EIPs/assets/eip-6353/test/charity.js).

## Reference Implementation

The reference implementation of the standard can be found under [`contracts/`](/EIPs/assets/eip-6353/contracts/ERC20Charity.sol) folder.

## Security Considerations

There are no additional security considerations compared to EIP-20.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 13 May 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6353</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6353</guid>
      </item>
    
      <item>
        <title>Single-contract Multi-delegatecall</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6357-single-contract-multicall/12621</comments>
        
        <description>## Abstract

This EIP standardizes an interface containing a single function, `multicall`, allowing EOAs to call multiple functions of a smart contract in a single transaction, and revert all calls if any call fails. 

## Motivation

Currently, in order to transfer several [ERC-721](/EIPs/EIPS/eip-721) NFTs, one needs to submit a number of transactions equal to the number of NFTs being tranferred. This wastes users&apos; funds by requiring them to pay 21000 gas fee for every NFT they transfer.

## Specification

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

Contracts implementing this EIP must implement the following interface:
  
```solidity
pragma solidity ^0.8.0;

interface IMulticall {
    /// @notice           Takes an array of abi-encoded call data, delegatecalls itself with each calldata, and returns the abi-encoded result
    /// @dev              Reverts if any delegatecall reverts
    /// @param    data    The abi-encoded data
    /// @returns  results The abi-encoded return values
    function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results);

    /// @notice           OPTIONAL. Takes an array of abi-encoded call data, delegatecalls itself with each calldata, and returns the abi-encoded result
    /// @dev              Reverts if any delegatecall reverts
    /// @param    data    The abi-encoded data
    /// @param    values  The effective msg.values. These must add up to at most msg.value
    /// @returns  results The abi-encoded return values
    function multicallPayable(bytes[] calldata data, uint256[] values) external payable virtual returns (bytes[] memory results);
}
```

## Rationale

`multicallPayable` is optional because it isn&apos;t always feasible to implement, due to the `msg.value` splitting.

## Backwards Compatibility

This is compatible with most existing multicall functions.

## Test Cases

The following JavaScript code, using the Ethers library, should atomically transfer `amt` units of an [ERC-20](/EIPs/EIPS/eip-20) token to both `addressA` and `addressB`.

```js
await token.multicall(await Promise.all([
    token.interface.encodeFunctionData(&apos;transfer&apos;, [ addressA, amt ]),
    token.interface.encodeFunctionData(&apos;transfer&apos;, [ addressB, amt ]),
]));
```

## Reference Implementation

```solidity
pragma solidity ^0.8.0;

/// Derived from OpenZeppelin&apos;s implementation
abstract contract Multicall is IMulticall {
    function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results) {
        results = new bytes[](data.length);
        for (uint256 i = 0; i &lt; data.length; i++) {
            (bool success, bytes memory returndata) = address(this).delegatecall(data);
            require(success);
            results[i] = returndata;
        }
        return results;
    }
}
```

## Security Considerations

`multicallPayable` 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.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Cross-Chain Token States Synchronization</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/add-eip-6358-omniverse-distributed-ledger-technology/12625</comments>
        
        <description>## Abstract

This ERC standardizes an interface for contract-layer consensus-agnostic verifiable cross-chain bridging, through which we can define a new global token inherited from [ERC-20](/EIPs/EIPS/eip-20)/[ERC-721](/EIPs/EIPS/eip-721) over multi-chains.  

### Figure.1 Architecture

![img](/EIPs/assets/eip-6358/img/o-dlt.png)    

With this ERC, we can create a global token protocol, that leverages smart contracts or similar mechanisms on existing blockchains to record the token states synchronously. The synchronization could be made by trustless off-chain synchronizers.

## Motivation

- The current paradigm of token bridges makes assets fragment.  
- If ETH was transferred to another chain through the current token bridge, if the chain broke down, ETH will be lost for users.  

The core of this ERC is synchronization instead of transferring, even if all the other chains break down, as long as Ethereum is still running, user’s assets will not be lost. 

- The fragment problem will be solved.
- The security of users&apos; multi-chain assets can be greatly enhanced.

## Specification

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

### Omniverse Account

There SHOULD be a global user identifier of this ERC, which is RECOMMENDED to be referred to as Omniverse Account (`o-account` for short) in this article.  
The `o-account` is RECOMMENDED to be expressed as a public key created by the elliptic curve `secp256k1`. A [mapping mechanism](#mapping-mechanism-for-different-environments) is RECOMMENDED for different environments.  

### Data Structure

An Omniverse Transaction (`o-transaction` for short) MUST be described with the following data structure:

```solidity
/**
 * @notice Omniverse transaction data structure
 * @member nonce: The number of the o-transactions. If the current nonce of an omniverse account is `k`, the valid nonce of this o-account in the next o-transaction is `k+1`. 
 * @member chainId: The chain where the o-transaction is initiated
 * @member initiateSC: The contract address from which the o-transaction is first initiated
 * @member from: The Omniverse account which signs the o-transaction
 * @member payload: The encoded business logic data, which is maintained by the developer
 * @member signature: The signature of the above informations. 
 */
struct ERC6358TransactionData {
    uint128 nonce;
    uint32 chainId;
    bytes initiateSC;
    bytes from;
    bytes payload;
    bytes signature;
}
```

- The data structure `ERC6358TransactionData` MUST be defined as above.
- The member `nonce` MUST be defined as `uint128` due to better compatibility for more tech stacks of blockchains.
- The member `chainId` MUST be defined as `uint32`.
- The member `initiateSC` MUST be defined as `bytes`.
- The member `from` MUST be defined as `bytes`.
- The member `payload` MUST be defined as `bytes`. It is encoded from a user-defined data related to the o-transaction. For example:  
    - For fungible tokens it is RECOMMENDED as follows:  

        ```solidity
        /**
        * @notice Fungible token data structure, from which the field `payload` in `ERC6358TransactionData` will be encoded
        *
        * @member op: The operation type
        * NOTE op: 0-31 are reserved values, 32-255 are custom values
        *           op: 0 - omniverse account `from` transfers `amount` tokens to omniverse account `exData`, `from` have at least `amount` tokens
        *           op: 1 - omniverse account `from` mints `amount` tokens to omniverse account `exData`
        *           op: 2 - omniverse account `from` burns `amount` tokens from his own, `from` have at least `amount` tokens
        * @member exData: The operation data. This sector could be empty and is determined by `op`. For example: 
                    when `op` is 0 and 1, `exData` stores the omniverse account that receives.
                    when `op` is 2, `exData` is empty.
        * @member amount: The amount of tokens being operated
        */
        struct Fungible {
            uint8 op;
            bytes exData;
            uint256 amount;
        }
        ```

        - The related raw data for `signature` in `o-transaction` is RECOMMENDED to be the concatenation of the raw bytes of `op`, `exData`, and `amount`.  

    - For non-fungible tokens it is RECOMMENDED as follows:  

        ```solidity
        /**
        * @notice Non-Fungible token data structure, from which the field `payload` in `ERC6358TransactionData` will be encoded
        *
        * @member op: The operation type
        * NOTE op: 0-31 are reserved values, 32-255 are custom values
        *           op: 0 omniverse account `from` transfers token `tokenId` to omniverse account `exData`, `from` have the token with `tokenId`
        *           op: 1 omniverse account `from` mints token `tokenId` to omniverse account `exData`
        *           op: 2 omniverse account `from` burns token `tokenId`, `from` have the token with `tokenId`
        * @member exData: The operation data. This sector could be empty and is determined by `op`
        *           when `op` is 0 and 1, `exData` stores the omniverse account that receives.
                    when `op` is 2, `exData` is empty.
        * @member tokenId: The tokenId of the non-fungible token being operated
        */
        struct NonFungible {
            uint8 op;
            bytes exData;
            uint256 tokenId;
        }
        ```

        - The related raw data for `signature` in `o-transaction` is RECOMMENDED to be the concatenation of the raw bytes of `op`, `exData`, and `tokenId`. 

- The member `signature` MUST be defined as `bytes`. It is RECOMMENDED to be created as follows.  
    - It is OPTIONAL that concating the sectors in `ERC6358TransactionData` as below (take Fungible token for example) and calculate the hash with `keccak256`: 

        ```solidity
        /**
        * @notice Decode `_data` from bytes to Fungible
        * @return A `Fungible` instance
        */
        function decodeData(bytes memory _data) internal pure returns (Fungible memory) {
            (uint8 op, bytes memory exData, uint256 amount) = abi.decode(_data, (uint8, bytes, uint256));
            return Fungible(op, exData, amount);
        }
        
        /**
        * @notice Get the hash of a transaction
        * @return Hash value of the raw data of an `ERC6358TransactionData` instance
        */
        function getTransactionHash(ERC6358TransactionData memory _data) public pure returns (bytes32) {
            Fungible memory fungible = decodeData(_data.payload);
            bytes memory payload = abi.encodePacked(fungible.op, fungible.exData, fungible.amount);
            bytes memory rawData = abi.encodePacked(_data.nonce, _data.chainId, _data.initiateSC, _data.from, payload);
            return keccak256(rawData);
        }
        ```

    - It is OPTIONAL that encapsulating the sectors in `ERC6358TransactionData` according to `EIP-712`.
    - Sign the hash value.

### Smart Contract Interface

- Every [ERC-6358](/EIPs/EIPS/eip-6358) compliant contract MUST implement the `IERC6358`  

    ```solidity
    /**
    * @notice Interface of the ERC-6358
    */
    interface IERC6358 {
        /**
        * @notice Emitted when a o-transaction which has nonce `nonce` and was signed by user `pk` is sent by calling {sendOmniverseTransaction}
        */
        event TransactionSent(bytes pk, uint256 nonce);

        /**
        * @notice Sends an `o-transaction` 
        * @dev 
        * Note: MUST implement the validation of the `_data.signature`
        * Note: A map maintaining the  `o-account` and the related transaction nonce is RECOMMENDED  
        * Note: MUST implement the validation of the `_data.nonce` according to the current account nonce
        * Note: MUST implement the validation of the `_data. payload`
        * Note: This interface is just for sending an `o-transaction`, and the execution MUST NOT be within this interface 
        * Note: The actual execution of an `o-transaction` is RECOMMENDED to be in another function and MAY be delayed for a time
        * @param _data: the `o-transaction` data with type {ERC6358TransactionData}
        * See more information in the definition of {ERC6358TransactionData}
        *
        * Emit a {TransactionSent} event
        */
        function sendOmniverseTransaction(ERC6358TransactionData calldata _data) external;

        /**
        * @notice Get the number of omniverse transactions sent by user `_pk`, 
        * which is also the valid `nonce` of a new omniverse transactions of user `_pk` 
        * @param _pk: Omniverse account to be queried
        * @return The number of omniverse transactions sent by user `_pk`
        */
        function getTransactionCount(bytes memory _pk) external view returns (uint256);

        /**
        * @notice Get the transaction data `txData` and timestamp `timestamp` of the user `_use` at a specified nonce `_nonce`
        * @param _user Omniverse account to be queried
        * @param _nonce The nonce to be queried
        * @return Returns the transaction data `txData` and timestamp `timestamp` of the user `_use` at a specified nonce `_nonce`
        */
        function getTransactionData(bytes calldata _user, uint256 _nonce) external view returns (ERC6358TransactionData memory, uint256);

        /**
        * @notice Get the chain ID
        * @return Returns the chain ID
        */
        function getChainId() external view returns (uint32);
    }
    ```

    - The `sendOmniverseTransaction` function MAY be implemented as `public` or `external`
    - The `getTransactionCount` function MAY be implemented as `public` or `external`
    - The `getTransactionData` function MAY be implemented as `public` or `external`
    - The `getChainId` function MAY be implemented as `pure` or `view`
    - The `TransactionSent` event MUST be emitted when `sendOmniverseTransaction` function is called
- Optional Extension: Fungible Token  

    ```solidity
    // import &quot;{IERC6358.sol}&quot;;

    /**
    * @notice Interface of the ERC-6358 fungible token, which inherits {IERC6358}
    */
    interface IERC6358Fungible is IERC6358 {
        /**
        * @notice Get the omniverse balance of a user `_pk`
        * @param _pk `o-account` to be queried
        * @return Returns the omniverse balance of a user `_pk`
        */
        function omniverseBalanceOf(bytes calldata _pk) external view returns (uint256);
    }
    ```

    - The `omniverseBalanceOf` function MAY be implemented as `public` or `external`

- Optional Extension: NonFungible Token  

    ```solidity
    import &quot;{IERC6358.sol}&quot;;

    /**
    * @notice Interface of the ERC-6358 non fungible token, which inherits {IERC6358}
    */
    interface IERC6358NonFungible is IERC6358 {
        /**
        * @notice Get the number of omniverse NFTs in account `_pk`
        * @param _pk `o-account` to be queried
        * @return Returns the number of omniverse NFTs in account `_pk`
        */
        function omniverseBalanceOf(bytes calldata _pk) external view returns (uint256);

        /**
        * @notice Get the owner of an omniverse NFT with `tokenId`
        * @param _tokenId Omniverse NFT id to be queried
        * @return Returns the owner of an omniverse NFT with `tokenId`
        */
        function omniverseOwnerOf(uint256 _tokenId) external view returns (bytes memory);
    }
    ```

    - The `omniverseBalanceOf` function MAY be implemented as `public` or `external`
    - The `omniverseOwnerOf` function MAY be implemented as `public` or `external`

## Rationale

### Architecture

As shown in [Figure.1](#figure1-architecture), smart contracts deployed on multi-chains execute `o-transactions` of ERC-6358 tokens synchronously through the trustless off-chain synchronizers.   

- The ERC-6358 smart contracts are referred to as **Abstract Nodes**. The states recorded by the Abstract Nodes that are deployed on different blockchains respectively could be considered as copies of the global state, and they are ultimately consistent.  
- **Synchronizer** is an off-chain execution program responsible for carrying published  `o-transactions` from the ERC-6358 smart contracts on one blockchain to the others. The synchronizers work trustless as they just deliver `o-transactions` with others&apos; signatures, and details could be found in the [workflow](#workflow).

### Principle

- The `o-account` has been mentioned [above](#omniverse-account).
- The synchronization of the `o-transactions` guarantees the ultimate consistency of token states across all chains. The related data structure is [here](#data-structure).

    - A `nonce` mechanism is brought in to make the states consistent globally.
    - The `nonce` appears in two places, the one is `nonce in o-transaction` data structure, and the other is `account nonce` maintained by on-chain ERC-6358 smart contracts. 
    - When synchronizing, the `nonce in o-transaction` data will be checked by comparing it to the `account nonce`.

#### Workflow

- Suppose a common user `A` and her related operation `account nonce` is $k$.
- `A` initiates an `o-transaction` on Ethereum by calling `IERC6358::sendOmniverseTransaction`. The current `account nonce` of `A` in the ERC-6358 smart contracts deployed on Ethereum is $k$ so the valid value of `nonce in o-transaction` needs to be $k+1$.  
- The ERC-6358 smart contracts on Ethereum verify the signature of the `o-transaction` data. If the verification succeeds, the `o-transaction` data will be published by the smart contracts on the Ethereum side. The verification includes:
    - whether the balance (FT) or the ownership (NFT) is valid
    - and whether the `nonce in o-transaction` is $k+1$
- The `o-transaction` SHOULD NOT be executed on Ethereum immediately, but wait for a time.  
- Now, `A`&apos;s latest submitted `nonce in o-transaction` on Ethereum is $k+1$, but still $k$ on other chains.
- The off-chain synchronizers will find a newly published `o-transaction` on Ethereum but not on other chains.  
- Next synchronizers will rush to deliver this message because of a rewarding mechanism. (The strategy of the reward could be determined by the deployers of ERC-6358 tokens. For example, the reward could come from the service fee or a mining mechanism.) 
- Finally, the ERC-6358 smart contracts deployed on other chains will all receive the `o-transaction` data, verify the signature and execute it when the **waiting time is up**. 
- After execution, the `account nonce` on all chains will add 1. Now all the `account nonce` of account `A` will be $k+1$, and the state of the balances of the related account will be the same too.  

## Reference Implementation

### Omniverse Account

- An Omniverse Account example: `3092860212ceb90a13e4a288e444b685ae86c63232bcb50a064cb3d25aa2c88a24cd710ea2d553a20b4f2f18d2706b8cc5a9d4ae4a50d475980c2ba83414a796`
    - The Omniverse Account is a public key of the elliptic curve `secp256k1`
    - The related private key of the example is:  `cdfa0e50d672eb73bc5de00cc0799c70f15c5be6b6fca4a1c82c35c7471125b6`

#### Mapping Mechanism for Different Environments

In the simplest implementation, we can just build two mappings to get it. One is like `pk based on sece256k1 =&gt; account address in the special environment`, and the other is the reverse mapping. 

The `Account System` on `Flow` is a typical example.  

- `Flow` has a built-in mechanism for `account address =&gt; pk`. The public key can be bound to an account (a special built-in data structure) and the public key can be got from the `account address` directly.  
- A mapping from `pk` to the `account address` on Flow can be built by creating a mapping `{String: Address}`, in which `String` denotes the data type to express the public key and the `Address` is the data type of the `account address` on Flow.  

### ERC-6358 Token

The ERC-6358 Token could be implemented with the [interfaces mentioned above](#smart-contract-interface). It can also be used with the combination of [ERC-20](/EIPs/EIPS/eip-20)/[ERC-721](/EIPs/EIPS/eip-721).  

- The implementation examples of the interfaces can be found at:

    - [Interface `IERC6358`](/EIPs/assets/eip-6358/src/contracts/interfaces/IERC6358.sol), the basic ERC-6358 interface mentioned [above](#smart-contract-interface)
    - [Interface `IERC6358Fungible`](/EIPs/assets/eip-6358/src/contracts/interfaces/IERC6358Fungible.sol), the interface for ERC-6358 fungible token
    - [Interface `IERC6358NonFungible`](/EIPs/assets/eip-6358/src/contracts/interfaces/IERC6358NonFungible.sol), the interface for ERC-6358 non-fungible token

- The implementation example of some common tools to operate ERC-6358 can be found at:

    - [Common Tools](/EIPs/assets/eip-6358/src/contracts/libraries/OmniverseProtocolHelper.sol).  

- The implementation examples of ERC-6358 Fungible Token and ERC-6358 Non-Fungible Token can be found at:  

    - [ERC-6358 Fungible Token Example](/EIPs/assets/eip-6358/src/contracts/ERC6358FungibleExample.sol)
    - [ERC-6358 Non-Fungible Token Example](/EIPs/assets/eip-6358/src/contracts/ERC6358NonFungibleExample.sol)  

## Security Considerations

### Attack Vector Analysis

According to the above, there are two roles:

- **common users** are who initiate an `o-transaction`
- **synchronizers** are who just carry the `o-transaction` data if they find differences between different chains.  

The two roles might be where the attack happens:  

#### **Will the *synchronizers* cheat?**  

- Simply speaking, it&apos;s none of the **synchronizer**&apos;s business as **they cannot create other users&apos; signatures** unless some **common users** tell him, but at this point, we think it&apos;s a problem with the role **common user**.  
- The **synchronizer** has no will and cannot do evil because the `o-transaction` data that they deliver is verified by the related **signature** of other **common users**.  
- The **synchronizers** would be rewarded as long as they submit valid `o-transaction` data, and *valid* only means that the signature and the amount are both valid. This will be detailed and explained later when analyzing the role of **common user**.  
- The **synchronizers** will do the delivery once they find differences between different chains:
    - If the current `account nonce` on one chain is smaller than a published `nonce in o-transaction` on another chain
    - If the transaction data related to a specific `nonce in o-transaction` on one chain is different from another published `o-transaction` data with the same `nonce in o-transaction` on another chain

- **Conclusion: The *synchronizers* won&apos;t cheat because there are no benefits and no way for them to do so.**

#### **Will the *common user* cheat?**

- Simply speaking, **maybe they will**, but fortunately, **they can&apos;t succeed**.    
- Suppose the current `account nonce` of a **common user** `A` is $k$ on all chains. `A` has 100 token `X`, which is an instance of the ERC-6358 token.    
- Common user `A` initiates an `o-transaction` on a Parachain of Polkadot first, in which `A` transfers `10` `X`s to an `o-account` of a **common user** `B`. The `nonce in o-transaction` needs to be $k+1$. After signature and data verification, the `o-transaction` data(`ot-P-ab` for short) will be published on Polkadot.
- At the same time, `A` initiates an `o-transaction` with the **same nonce** $k+1$ but **different data**(transfer `10` `X`s to another `o-account` `C` for example) on Ethereum. This `o-transaction` (named `ot-E-ac` for short) will pass the verification on Ethereum first, and be published.  
- At this point, it seems `A` finished a ***double spend attack*** and the states on Polkadot and Ethereum are different.  
- **Response strategy**:
    - As we mentioned above, the synchronizers will deliver `ot-P-ab` to Ethereum and deliver `ot-E-ac` to Polkadot because they are different although with the same nonce. The synchronizer who submits the `o-transaction` first will be rewarded as the signature is valid.
    - Both the ERC-6358 smart contracts or similar mechanisms on Polkadot and Ethereum will find that `A` did cheating after they received both `ot-E-ac` and `ot-P-ab` respectively as the signature of `A` is non-deniable.  
    - We have mentioned that the execution of an `o-transaction` will not be done immediately and instead there needs to be a fixed waiting time. So the `double spend attack` caused by `A` won&apos;t succeed.
    - There will be many synchronizers waiting for delivering o-transactions to get rewards. So although it&apos;s almost impossible that a **common user** can submit two `o-transactions` to two chains, but none of the synchronizers deliver the `o-transactions` successfully because of a network problem or something else, we still provide a solution:  
        - The synchronizers will connect to several native nodes of every public chain to avoid the malicious native nodes.
        - If it indeed happened that all synchronizers&apos; network break, the `o-transactions` will be synchronized when the network recovered. If the waiting time is up and the cheating `o-transaction` has been executed, we are still able to revert it from where the cheating happens according to the `nonce in o-transaction` and `account nonce`.
- `A` couldn&apos;t escape punishment in the end (For example, lock his account or something else, and this is about the certain tokenomics determined by developers according to their own situation).  

- **Conclusion: The *common user* maybe cheat but won&apos;t succeed.**

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 17 Jan 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6358</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6358</guid>
      </item>
    
      <item>
        <title>Permission Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6366-a-standard-for-permission-token/9105</comments>
        
        <description>## Abstract

This EIP offers an alternative to Access Control Lists (ACLs) for granting authorization and enhancing security. A `uint256` is used to store permission of given address in a ecosystem. Each permission is represented by a single bit in a `uint256` as described in [ERC-6617](/EIPs/EIPS/eip-6617). Bitwise operators and bitmasks are used to determine the access right which is much more efficient and flexible than `string` or `keccak256` comparison.

## Motivation

Special roles like `Owner`, `Operator`, `Manager`, `Validator` are common for many smart contracts because permissioned addresses are used to administer and manage them. It is difficult to audit and maintain these system since these permissions are not managed in a single smart contract.

Since permissions and roles are reflected by the permission token balance of the relevant account in the given ecosystem, cross-interactivity between many ecosystems will be made simpler.

## Specification

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

_Note_ The following specifications use syntax from Solidity `0.8.7` (or above)

### Core Interface

Compliant contracts MUST implement `IEIP6366Core`.

It is RECOMMENDED to define each permission as a power of `2` so that we can check for the relationship between sets of permissions using [ERC-6617](/EIPs/EIPS/eip-6617).

```solidity
interface IEIP6366Core {
  /**
   * MUST trigger when `_permission` are transferred, including `zero` permission transfers.
   * @param _from           Permission owner
   * @param _to             Permission receiver
   * @param _permission     Transferred subset permission of permission owner
   */
  event Transfer(address indexed _from, address indexed _to, uint256 indexed _permission);

  /**
   * MUST trigger on any successful call to `approve(address _delegatee, uint256 _permission)`.
   * @param _owner          Permission owner
   * @param _delegatee      Delegatee
   * @param _permission     Approved subset permission of permission owner
   */
  event Approval(address indexed _owner, address indexed _delegatee, uint256 indexed _permission);

  /**
   * Transfers a subset `_permission` of permission to address `_to`.
   * The function SHOULD revert if the message caller’s account permission does not have the subset
   * of the transferring permissions. The function SHOULD revert if any of transferring permissions are
   * existing on target `_to` address.
   * @param _to             Permission receiver
   * @param _permission     Subset permission of permission owner
   */
  function transfer(address _to, uint256 _permission) external returns (bool success);

  /**
   * Allows `_delegatee` to act for the permission owner&apos;s behalf, up to the `_permission`.
   * If this function is called again it overwrites the current granted with `_permission`.
   * `approve()` method SHOULD `revert` if granting `_permission` permission is not
   * a subset of all available permissions of permission owner.
   * @param _delegatee      Delegatee
   * @param _permission     Subset permission of permission owner
   */
  function approve(address _delegatee, uint256 _permission) external returns (bool success);

  /**
   * Returns the permissions of the given `_owner` address.
   */
  function permissionOf(address _owner) external view returns (uint256 permission);

  /**
   * Returns `true` if `_required` is a subset of `_permission` otherwise return `false`.
   * @param _permission     Checking permission set
   * @param _required       Required set of permission
   */
  function permissionRequire(uint256 _permission, uint256 _required) external view returns (bool isPermissioned);

  /**
   * Returns `true` if `_required` permission is a subset of `_actor`&apos;s permissions or a subset of his delegated
   * permission granted by the `_owner`.
   * @param _owner          Permission owner
   * @param _actor          Actor who acts on behalf of the owner
   * @param _required       Required set of permission
   */
  function hasPermission(address _owner, address _actor, uint256 _required) external view returns (bool isPermissioned);

  /**
   * Returns the subset permission of the `_owner` address were granted to `_delegatee` address.
   * @param _owner          Permission owner
   * @param _delegatee      Delegatee
   */
  function delegated(address _owner, address _delegatee) external view returns (uint256 permission);
}
```

### Metadata Interface

It is RECOMMENDED for compliant contracts to implement the optional extension `IEIP6617Meta`.

SHOULD define a description for the base permissions and main combinaison.

SHOULD NOT define a description for every subcombinaison of permissions possible.

### Error Interface

Compatible tokens MAY implement `IEIP6366Error` as defined below:

```solidity
interface IEIP6366Error {
  /**
   * The owner or actor does not have the required permission
   */
  error AccessDenied(address _owner, address _actor, uint256 _permission);

  /**
   * Conflict between permission set
   */
  error DuplicatedPermission(uint256 _permission);

  /**
   * Data out of range
   */
  error OutOfRange();
}
```

## Rationale

Needs discussion.

## Reference Implementation

First implementation could be found here:

- [ERC-6366 Core implementation](/EIPs/assets/eip-6366/contracts/EIP6366Core.sol)

## Security Considerations

Need more discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 19 Jan 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6366</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6366</guid>
      </item>
    
      <item>
        <title>Contract clock</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6372-contract-clock/12689</comments>
        
        <description>## Abstract

Many contracts rely on some clock for enforcing delays and storing historical data. While some contracts rely on block numbers, others use timestamps. There is currently no easy way to discover which time-tracking function a contract internally uses. This EIP proposes to standardize an interface for contracts to expose their internal clock and thus improve composability and interoperability.

## Motivation

Many contracts check or store time-related information. For example, timelock contracts enforce a delay before an operation can be executed. Similarly, DAOs enforce a voting period during which stakeholders can approve or reject a proposal. Last but not least, voting tokens often store the history of voting power using timed snapshots.

Some contracts do time tracking using timestamps while others use block numbers. In some cases, more exotic functions might be used to track time.

There is currently no interface for an external observer to detect which clock a contract uses. This seriously limits interoperability and forces devs to make risky assumptions.

## Specification

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.

Compliant contracts MUST implement the `clock` and `CLOCK_MODE` functions as specified below.

```solidity
interface IERC6372 {
  function clock() external view returns (uint48);
  function CLOCK_MODE() external view returns (string);
}
```

### Methods

#### clock

This function returns the current timepoint according to the mode the contract is operating on. It MUST be a **non-decreasing** function of the chain, such as `block.timestamp` or `block.number`.

```yaml
- name: clock
  type: function
  stateMutability: view
  inputs: []
  outputs:
    - name: timepoint
      type: uint48
```

#### CLOCK_MODE

This function returns a machine-readable string description of the clock the contract is operating on.

This string MUST be formatted like a URL query string (a.k.a. `application/x-www-form-urlencoded`), decodable in standard JavaScript with `new URLSearchParams(CLOCK_MODE)`.

- If operating using **block number**:
  - If the block number is that of the `NUMBER` opcode (`0x43`), then this function MUST return `mode=blocknumber&amp;from=default`.
  - If it is any other block number, then this function MUST return `mode=blocknumber&amp;from=&lt;CAIP-2-ID&gt;`, where `&lt;CAIP-2-ID&gt;` is a CAIP-2 Blockchain ID such as `eip155:1`.
- If operating using **timestamp**, then this function MUST return `mode=timestamp`.
- If operating using any other mode, then this function SHOULD return a unique identifier for the encoded `mode` field.

```yaml
- name: CLOCK_MODE
  type: function
  stateMutability: view
  inputs: []
  outputs:
    - name: descriptor
      type: string
```

### Expected properties

- The `clock()` function MUST be non-decreasing.

## Rationale

`clock` returns `uint48` as it is largely sufficient for storing realistic values. In timestamp mode, `uint48` will be enough until the year 8921556. Even in block number mode, with 10,000 blocks per second, it would be enough until the year 2861. Using a type smaller than `uint256` allows storage packing of timepoints with other associated values, greatly reducing the cost of writing and reading from storage.

Depending on the evolution of the blockchain (particularly layer twos), using a smaller type, such as `uint32` might cause issues fairly quickly. On the other hand, anything bigger than `uint48` appears wasteful.

In addition to timestamps, it is sometimes necessary to define durations or delays, which are a difference between timestamps. In the general case, we would expect these values to be represented with the same type than timepoints (`uint48`). However, we believe that in most cases `uint32` is a good alternative, as it represents over 136 years if the clock operates using seconds. In most cases, we recommend using `uint48` for storing timepoints and using `uint32` for storing durations. That recommendation applies to &quot;reasonable&quot; durations (delay for a timelock, voting or vesting duration, ...) when operating with timestamps or block numbers that are more than 1 second apart.

## Security Considerations

No known security issues.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 25 Jan 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6372</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6372</guid>
      </item>
    
      <item>
        <title>Public Non-Fungible Token Emote Repository</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6381-emotable-extension-for-non-fungible-tokens/12710</comments>
        
        <description>## Abstract

The Public Non-Fungible Token Emote Repository standard provides an enhanced interactive utility for [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155) by allowing NFTs to be emoted at.

This proposal introduces the ability to react to NFTs using Unicode standardized emoji in a public non-gated repository smart contract that is accessible at the same address in all of the networks.

## Motivation

With NFTs being a widespread form of tokens in the Ethereum ecosystem and being used for a variety of use cases, it is time to standardize additional utility for them. Having the ability for anyone to interact with an NFT introduces an interactive aspect to owning an NFT and unlocks feedback-based NFT mechanics.

This ERC introduces new utilities for [ERC-721](/EIPs/EIPS/eip-721) based tokens in the following areas:

- [Interactivity](#interactivity)
- [Feedback based evolution](#feedback-based-evolution)
- [Valuation](#valuation)

### Interactivity

The ability to emote on an NFT introduces the aspect of interactivity to owning an NFT. This can either reflect the admiration for the emoter (person emoting to an NFT) or can be a result of a certain action performed by the token&apos;s owner. Accumulating emotes on a token can increase its uniqueness and/or value.

### Feedback based evolution

Standardized on-chain reactions to NFTs allow for feedback based evolution.

Current solutions are either proprietary or off-chain and therefore subject to manipulation and distrust. Having the ability to track the interaction on-chain allows for trust and objective evaluation of a given token. Designing the tokens to evolve when certain emote thresholds are met incentivizes interaction with the token collection.

### Valuation

Current NFT market heavily relies on previous values the token has been sold for, the lowest price of the listed token and the scarcity data provided by the marketplace. There is no real time indication of admiration or desirability of a specific token. Having the ability for users to emote to the tokens adds the possibility of potential buyers and sellers gauging the value of the token based on the impressions the token has collected.

## Specification

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.

```solidity
/// @title ERC-6381 Emotable Extension for Non-Fungible Tokens
/// @dev See https://eips.ethereum.org/EIPS/eip-6381
/// @dev Note: the ERC-165 identifier for this interface is 0xd9fac55a.

pragma solidity ^0.8.16;

interface IERC6381 /*is IERC165*/ {
    /**
     * @notice Used to notify listeners that the token with the specified ID has been emoted to or that the reaction has been revoked.
     * @dev The event MUST only be emitted if the state of the emote is changed.
     * @param emoter Address of the account that emoted or revoked the reaction to the token
     * @param collection Address of the collection smart contract containing the token being emoted to or having the reaction revoked
     * @param tokenId ID of the token
     * @param emoji Unicode identifier of the emoji
     * @param on Boolean value signifying whether the token was emoted to (`true`) or if the reaction has been revoked (`false`)
     */
    event Emoted(
        address indexed emoter,
        address indexed collection,
        uint256 indexed tokenId,
        bytes4 emoji,
        bool on
    );

    /**
     * @notice Used to get the number of emotes for a specific emoji on a token.
     * @param collection Address of the collection containing the token being checked for emoji count
     * @param tokenId ID of the token to check for emoji count
     * @param emoji Unicode identifier of the emoji
     * @return Number of emotes with the emoji on the token
     */
    function emoteCountOf(
        address collection,
        uint256 tokenId,
        bytes4 emoji
    ) external view returns (uint256);

    /**
     * @notice Used to get the number of emotes for a specific emoji on a set of tokens.
     * @param collections An array of addresses of the collections containing the tokens being checked for emoji count
     * @param tokenIds An array of IDs of the tokens to check for emoji count
     * @param emojis An array of unicode identifiers of the emojis
     * @return An array of numbers of emotes with the emoji on the tokens
     */
    function bulkEmoteCountOf(
        address[] memory collections,
        uint256[] memory tokenIds,
        bytes4[] memory emojis
    ) external view returns (uint256[] memory);

    /**
     * @notice Used to get the information on whether the specified address has used a specific emoji on a specific
     *  token.
     * @param emoter Address of the account we are checking for a reaction to a token
     * @param collection Address of the collection smart contract containing the token being checked for emoji reaction
     * @param tokenId ID of the token being checked for emoji reaction
     * @param emoji The ASCII emoji code being checked for reaction
     * @return A boolean value indicating whether the `emoter` has used the `emoji` on the token (`true`) or not
     *  (`false`)
     */
    function hasEmoterUsedEmote(
        address emoter,
        address collection,
        uint256 tokenId,
        bytes4 emoji
    ) external view returns (bool);

    /**
     * @notice Used to get the information on whether the specified addresses have used specific emojis on specific
     *  tokens.
     * @param emoters An array of addresses of the accounts we are checking for reactions to tokens
     * @param collections An array of addresses of the collection smart contracts containing the tokens being checked
     *  for emoji reactions
     * @param tokenIds An array of IDs of the tokens being checked for emoji reactions
     * @param emojis An array of the ASCII emoji codes being checked for reactions
     * @return An array of boolean values indicating whether the `emoter`s has used the `emoji`s on the tokens (`true`)
     *  or not (`false`)
     */
    function haveEmotersUsedEmotes(
        address[] memory emoters,
        address[] memory collections,
        uint256[] memory tokenIds,
        bytes4[] memory emojis
    ) external view returns (bool[] memory);

    /**
     * @notice Used to get the message to be signed by the `emoter` in order for the reaction to be submitted by someone
     *  else.
     * @param collection The address of the collection smart contract containing the token being emoted at
     * @param tokenId ID of the token being emoted
     * @param emoji Unicode identifier of the emoji
     * @param state Boolean value signifying whether to emote (`true`) or undo (`false`) emote
     * @param deadline UNIX timestamp of the deadline for the signature to be submitted
     * @return The message to be signed by the `emoter` in order for the reaction to be submitted by someone else
     */
    function prepareMessageToPresignEmote(
        address collection,
        uint256 tokenId,
        bytes4 emoji,
        bool state,
        uint256 deadline
    ) external view returns (bytes32);

    /**
     * @notice Used to get multiple messages to be signed by the `emoter` in order for the reaction to be submitted by someone
     *  else.
     * @param collections An array of addresses of the collection smart contracts containing the tokens being emoted at
     * @param tokenIds An array of IDs of the tokens being emoted
     * @param emojis An arrau of unicode identifiers of the emojis
     * @param states An array of boolean values signifying whether to emote (`true`) or undo (`false`) emote
     * @param deadlines An array of UNIX timestamps of the deadlines for the signatures to be submitted
     * @return The array of messages to be signed by the `emoter` in order for the reaction to be submitted by someone else
     */
    function bulkPrepareMessagesToPresignEmote(
        address[] memory collections,
        uint256[] memory tokenIds,
        bytes4[] memory emojis,
        bool[] memory states,
        uint256[] memory deadlines
    ) external view returns (bytes32[] memory);

    /**
     * @notice Used to emote or undo an emote on a token.
     * @dev Does nothing if attempting to set a pre-existent state.
     * @dev MUST emit the `Emoted` event is the state of the emote is changed.
     * @param collection Address of the collection containing the token being emoted at
     * @param tokenId ID of the token being emoted
     * @param emoji Unicode identifier of the emoji
     * @param state Boolean value signifying whether to emote (`true`) or undo (`false`) emote
     */
    function emote(
        address collection,
        uint256 tokenId,
        bytes4 emoji,
        bool state
    ) external;

    /**
     * @notice Used to emote or undo an emote on multiple tokens.
     * @dev Does nothing if attempting to set a pre-existent state.
     * @dev MUST emit the `Emoted` event is the state of the emote is changed.
     * @dev MUST revert if the lengths of the `collections`, `tokenIds`, `emojis` and `states` arrays are not equal.
     * @param collections An array of addresses of the collections containing the tokens being emoted at
     * @param tokenIds An array of IDs of the tokens being emoted
     * @param emojis An array of unicode identifiers of the emojis
     * @param states An array of boolean values signifying whether to emote (`true`) or undo (`false`) emote
     */
    function bulkEmote(
        address[] memory collections,
        uint256[] memory tokenIds,
        bytes4[] memory emojis,
        bool[] memory states
    ) external;

    /**
     * @notice Used to emote or undo an emote on someone else&apos;s behalf.
     * @dev Does nothing if attempting to set a pre-existent state.
     * @dev MUST emit the `Emoted` event is the state of the emote is changed.
     * @dev MUST revert if the lengths of the `collections`, `tokenIds`, `emojis` and `states` arrays are not equal.
     * @dev MUST revert if the `deadline` has passed.
     * @dev MUST revert if the recovered address is the zero address.
     * @param emoter The address that presigned the emote
     * @param collection The address of the collection smart contract containing the token being emoted at
     * @param tokenId IDs of the token being emoted
     * @param emoji Unicode identifier of the emoji
     * @param state Boolean value signifying whether to emote (`true`) or undo (`false`) emote
     * @param deadline UNIX timestamp of the deadline for the signature to be submitted
     * @param v `v` value of an ECDSA signature of the message obtained via `prepareMessageToPresignEmote`
     * @param r `r` value of an ECDSA signature of the message obtained via `prepareMessageToPresignEmote`
     * @param s `s` value of an ECDSA signature of the message obtained via `prepareMessageToPresignEmote`
     */
    function presignedEmote(
        address emoter,
        address collection,
        uint256 tokenId,
        bytes4 emoji,
        bool state,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @notice Used to bulk emote or undo an emote on someone else&apos;s behalf.
     * @dev Does nothing if attempting to set a pre-existent state.
     * @dev MUST emit the `Emoted` event is the state of the emote is changed.
     * @dev MUST revert if the lengths of the `collections`, `tokenIds`, `emojis` and `states` arrays are not equal.
     * @dev MUST revert if the `deadline` has passed.
     * @dev MUST revert if the recovered address is the zero address.
     * @param emoters An array of addresses of the accounts that presigned the emotes
     * @param collections An array of addresses of the collections containing the tokens being emoted at
     * @param tokenIds An array of IDs of the tokens being emoted
     * @param emojis An array of unicode identifiers of the emojis
     * @param states An array of boolean values signifying whether to emote (`true`) or undo (`false`) emote
     * @param deadlines UNIX timestamp of the deadline for the signature to be submitted
     * @param v An array of `v` values of an ECDSA signatures of the messages obtained via `prepareMessageToPresignEmote`
     * @param r An array of `r` values of an ECDSA signatures of the messages obtained via `prepareMessageToPresignEmote`
     * @param s An array of `s` values of an ECDSA signatures of the messages obtained via `prepareMessageToPresignEmote`
     */
    function bulkPresignedEmote(
        address[] memory emoters,
        address[] memory collections,
        uint256[] memory tokenIds,
        bytes4[] memory emojis,
        bool[] memory states,
        uint256[] memory deadlines,
        uint8[] memory v,
        bytes32[] memory r,
        bytes32[] memory s
    ) external;
}
```

### Message format for presigned emotes

The message to be signed by the `emoter` in order for the reaction to be submitted by someone else is formatted as follows:

```solidity
keccak256(
        abi.encode(
            DOMAIN_SEPARATOR,
            collection,
            tokenId,
            emoji,
            state,
            deadline
        )
    );
```

The values passed when generating the message to be signed are:

- `DOMAIN_SEPARATOR` - The domain separator of the Emotable repository smart contract
- `collection` - Address of the collection containing the token being emoted at
- `tokenId` - ID of the token being emoted
- `emoji` - Unicode identifier of the emoji
- `state` - Boolean value signifying whether to emote (`true`) or undo (`false`) emote
- `deadline` - UNIX timestamp of the deadline for the signature to be submitted

The `DOMAIN_SEPARATOR` is generated as follows:

```solidity
keccak256(
        abi.encode(
            &quot;ERC-6381: Public Non-Fungible Token Emote Repository&quot;,
            &quot;1&quot;,
            block.chainid,
            address(this)
        )
    );
```

Each chain, that the Emotable repository smart contract is deployed on, will have a different `DOMAIN_SEPARATOR` value due to chain IDs being different.

### Pre-determined address of the Emotable repository

The address of the Emotable repository smart contract is designed to resemble the function it serves. It starts with `0x311073` which is the abstract representation of `EMOTE`. The address is:

```
0x31107354b61A0412E722455A771bC462901668eA
```

## Rationale

Designing the proposal, we considered the following questions:

1. **Does the proposal support custom emotes or only the Unicode specified ones?**\
The proposal only accepts the Unicode identifier which is a `bytes4` value. This means that while we encourage implementers to add the reactions using standardized emojis, the values not covered by the Unicode standard can be used for custom emotes. The only drawback being that the interface displaying the reactions will have to know what kind of image to render and such additions will probably be limited to the interface or marketplace in which they were made.
2. **Should the proposal use emojis to relay the impressions of NFTs or some other method?**\
The impressions could have been done using user-supplied strings or numeric values, yet we decided to use emojis since they are a well established mean of relaying impressions and emotions.
3. **Should the proposal establish an emotable extension or a common-good repository?**\
Initially we set out to create an emotable extension to be used with any ERC-721 compliant tokens. However, we realized that the proposal would be more useful if it was a common-good repository of emotable tokens. This way, the tokens that can be reacted to are not only the new ones but also the old ones that have been around since before the proposal.\
In line with this decision, we decided to calculate a deterministic address for the repository smart contract. This way, the repository can be used by any NFT collection without the need to search for the address on the given chain.
4. **Should we include only single-action operations, only multi-action operations, or both?**\
We&apos;ve considered including only single-action operations, where the user is only able to react with a single emoji to a single token, but we decided to include both single-action and multi-action operations. This way, the users can choose whether they want to emote or undo emote on a single token or on multiple tokens at once.\
This decision was made for the long-term viability of the proposal. Based on the gas cost of the network and the number of tokens in the collection, the user can choose the most cost-effective way of emoting.
5. **Should we add the ability to emote on someone else&apos;s behalf?**\
While we did not intend to add this as part of the proposal when drafting it, we realized that it would be a useful feature for it. This way, the users can emote on behalf of someone else, for example, if they are not able to do it themselves or if the emote is earned through an off-chain activity.
6. **How do we ensure that emoting on someone else&apos;s behalf is legitimate?**\
We could add delegates to the proposal; when a user delegates their right to emote to someone else, the delegate can emote on their behalf. However, this would add a lot of complexity and additional logic to the proposal.\
Using ECDSA signatures, we can ensure that the user has given their consent to emote on their behalf. This way, the user can sign a message with the parameters of the emote and the signature can be submitted by someone else.
7. **Should we add chain ID as a parameter when reacting to a token?**\
During the course of discussion of the proposal, a suggestion arose that we could add chain ID as a parameter when reacting to a token. This would allow the users to emote on the token of one chain on another chain.\
We decided against this as we feel that additional parameter would rarely be used and would add additional cost to the reaction transactions. If the collection smart contract wants to utilize on-chain emotes to tokens they contain, they require the reactions to be recorded on the same chain. Marketplaces and wallets integrating this proposal will rely on reactions to reside in the same chain as well, because if chain ID parameter was supported this would mean that they would need to query the repository smart contract on all of the chains the repository is deployed in order to get the reactions for a given token.\
Additionally, if the collection creator wants users to record their reactions on a different chain, they can still direct the users to do just that. The repository does not validate the existence of the token being reacted to, which in theory means that you can react to non-existent token or to a token that does not exist yet. The likelihood of a different collection existing at the same address on another chain is significantly low, so the users can react using the collection&apos;s address on another chain and it is very unlikely that they will unintentionally react to another collection&apos;s token.

## Backwards Compatibility

The Emote repository standard is fully compatible with [ERC-721](/EIPs/EIPS/eip-721) and with the robust tooling available for implementations of ERC-721 as well as with the existing ERC-721 infrastructure.

## Test Cases

Tests are included in [`emotableRepository.ts`](/EIPs/assets/eip-6381/test/emotableRepository.ts).

To run them in terminal, you can use the following commands:

```
cd ../assets/eip-6381
npm install
npx hardhat test
```

## Reference Implementation

See [`EmotableRepository.sol`](/EIPs/assets/eip-6381/contracts/EmotableRepository.sol).

## Security Considerations

The proposal does not envision handling any form of assets from the user, so the assets should not be at risk when interacting with an Emote repository.

The ability to use ECDSA signatures to emote on someone else&apos;s behalf introduces the risk of a replay attack, which the format of the message to be signed guards against. The `DOMAIN_SEPARATOR` used in the message to be signed is unique to the repository smart contract of the chain it is deployed on. This means that the signature is invalid on any other chain and the Emote repositories deployed on them should revert the operation if a replay attack is attempted.

Another thing to consider is the ability of presigned message reuse. Since the message includes the signature validity deadline, the message can be reused any number of times before the deadline is reached. The proposal only allows for a single reaction with a given emoji to a specific token to be active, so the presigned message can not be abused to increase the reaction count on the token. However, if the service using the repository relies on the ability to revoke the reaction after certain actions, a valid presigned message can be used to re-react to the token. We suggest that the services using the repository in cnjunction with presigned messages use deadlines that invalidate presigned messages after a reasonalby short period of time.

Caution is advised when dealing with non-audited contracts.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 22 Jan 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6381</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6381</guid>
      </item>
    
      <item>
        <title>Human-readable offline signatures</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6384-readable-eip-712-signatures/12752</comments>
        
        <description>## Abstract

This EIP introduces the `evalEIP712Buffer` function, which takes an [EIP-712](/EIPs/EIPS/eip-712) buffer and returns a human-readable text description.

## Motivation

The use case of Web3 off-chain signatures intended to be used within on-chain transaction is gaining traction and being used in multiple leading protocols (e.g. OpenSea) and standards [EIP-2612](/EIPs/EIPS/eip-2612), mainly as it offers a fee-less experience.
Attackers are known to actively and successfully abuse such off-chain signatures, leveraging the fact that users are blindly signing off-chain messages, since they are not humanly readable.
While [EIP-712](/EIPs/EIPS/eip-712) originally declared in its title that being ”humanly readable” is one of its goals, it did not live up to its promise eventually and EIP-712 messages are not understandable by an average user.

In one example, victims browse a malicious phishing website. It requests the victim to sign a message that will put their NFT token for sale on OpenSea platform, virtually for free.

The user interface for some popular wallet implementations is not conveying the actual meaning of signing such transactions.

In this proposal we offer a secure and scalable method to bring true human readability to EIP-712 messages by leveraging their bound smart contracts.
As a result, once implemented this EIP wallets can upgrade their user experience from current state:

![](/EIPs/assets/eip-6384/media/MiceyMask-non-compliant.png)

to a much clearer user experience:

![](/EIPs/assets/eip-6384/media/ZenGo-EIP-compliant-warning.png)

The proposed solution solves the readability issues by allowing the wallet to query the `verifyingContract`. The incentives for keeping the EIP-712 message description as accurate as possible are aligned, as the responsibility for the description is now owned by the contract, that:

- Knows the message meaning exactly (and probably can reuse the code that handles this message when received on chain)
- Natively incentivized to provide the best explanation to prevent a possible fraud
- Not involving a third party that needs to be trusted
- Maintains the fee-less customer experience as the added function is in “view” mode and does not require an on-chain execution and fees.
- Maintains Web3’s composability property

## Specification

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.

EIP-712 already formally binds an off-chain signature to a contract, with the `verifyingContract` parameter. We suggest adding a “view” function (`&quot;stateMutability&quot;:&quot;view&quot;`) to such contracts, that returns a human readable description of the meaning of this specific off-chain buffer.

```solidity
/**
 * @dev Returns the expected result of the offchain message.
*/

     function evalEIP712Buffer(bytes32 domainHash, string memory primaryType, bytes memory typedDataBuffer)
     external
     view
     returns (string[] memory) {
   ...

}
```

**Every compliant contract MUST implement this function.**

Using this function, wallets can submit the proposed off-chain signature to the contract and present the results to the user, allowing them to enjoy an “on-chain simulation equivalent” experience to their off-chain message.

This function will have a well known name and signature, such that there is no need for updates in the EIP-712 structure.

### Function&apos;s inputs

The inputs of the function:

- `domainHash` is the EIP-712&apos;s domainSeparator, a hashed `eip712Domain` struct.
- `primaryType`is the EIP-712&apos;s `primaryType`.
- `typedDataBuffer` is an ABI encoded message part of the EIP-712 full message.

### Function&apos;s output(s)

The output of the function is an array of strings. The wallet SHOULD display them to its end-users. The wallet MAY choose to augment the returned strings with additional data. (e.g. resolve contract addresses to their name)

The strings SHOULD NOT be formatted (e.g. should not contain HTML code) and wallets SHOULD treat this string as an untrusted input and handle its rendering as such.

### Support for EIP-712 messages that are not meant to be used on-chain

If `verifyingContract` is not included in the EIP-712 domain separator, wallets MUST NOT retrieve a human-readable description using this EIP. In this case, wallets SHOULD fallback to their original EIP-712 display.

## Rationale

- We chose to implement the `typeDataBuffer` parameter as abi encoded as it is a generic way to pass the data to the contract. The alternative was to pass the `typedData` struct, which is not generic as it requires the contract to specify the message data.
- We chose to return an array of strings and not a single string as there are potential cases where the message is composed of multiple parts. For example, in the case of a multiple assets transfers in the same `typedDataBuffer`, the contract is advised to describe each transfer in a separate string to allow the wallet to display each transfer separately.

### Alternative solutions

#### Third party services:

Currently, the best choice for users is to rely on some 3rd party solutions that get the proposed message as input and explain its intended meaning to the user. This approach is:

- Not scalable: 3rd party provider needs to learn all such proprietary messages
- Not necessarily correct: the explanation is based on 3rd party interpretation of the original message author
- Introduces an unnecessary dependency of a third party which may have some operational, security, and privacy implications.

#### Domain name binding

Alternatively, wallets can bind domain name to a signature. i.e. only accept EIP-712 message if it comes from a web2 domain that its `name` as defined by EIP-712 is included in `eip712Domain`. However this approach has the following disadvantages:

- It breaks Web3’s composability, as now other dapps cannot interact with such messages
- Does not protect against bad messages coming from the specified web2 domain, e.g. when web2 domain is hacked
- Some current connector, such as WalletConnect do not allow wallets to verify the web2 domain authenticity

## Backwards Compatibility

For non-supporting contracts the wallets will default to showing whatever they are showing today.
Non-supporting wallets will not call this function and will default to showing whatever they are showing today.

## Reference Implementation

A reference implementation can be found [here](/EIPs/assets/eip-6384/implementation/src/MyToken/MyToken.sol).
This toy example shows how an [EIP-20](/EIPs/EIPS/eip-20) contract supporting this EIP implements an EIP-712 support for &quot;transferWithSig&quot; functionality (a non-standard variation on Permit, as the point of this EIP is to allow readability to non-standard EIP-712 buffers).
To illustrate the usability of this EIP to some real world use case, a helper function for the actual OpenSea&apos;s SeaPort EIP-712 is implemented too in [here](/EIPs/assets/eip-6384/implementation/src/SeaPort/SeaPort712ParserHelper.sol).

## Security Considerations

### The threat model:

The attack is facilitated by a rogue web2 interface (“dapp”) that provides bad parameters for an EIP-712 formatted message that is intended to be consumed by a legitimate contract. Therefore, the message is controlled by attackers and cannot be trusted, however the contract is controlled by a legitimate party and can be trusted.

The attacker intends to use that signed EIP-712 message on-chain later on, with a transaction crafted by the attackers. If the subsequent on-chain transaction was to be sent by the victim, then a regular transaction simulation would have sufficed.

The case of a rogue contract is irrelevant, as such a rogue contract can already facilitate the attack regardless of the existence of the EIP-712 formatted message.

Having said that, a rogue contract may try to abuse this functionality in order to send some maliciously crafted string in order to exploit vulnerabilities in wallet rendering of the string. Therefore wallets should treat this string as an untrusted input and handle its renderring it as such.

### Analysis of the proposed solution

The explanation is controlled by the relevant contract which is controlled by a legitimate party. The attacker must specify the relevant contract address, as otherwise it will not be accepted by it. Therefore, the attacker cannot create false explanations using this method.
Please note that if the explanation was part of the message to sign it would have been under the control of the attacker and hence irrelevant for security purposes.

Since the added functionality to the contract has the “view” modifier, it cannot change the on-chain state and harm the existing functionalities of the contract.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 08 Jan 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6384</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6384</guid>
      </item>
    
      <item>
        <title>SSZ transactions</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6404-ssz-transactions/12783</comments>
        
        <description>## Abstract

This EIP defines a migration process of [EIP-2718](/EIPs/EIPS/eip-2718) Recursive-Length Prefix (RLP) transactions to [Simple Serialize (SSZ)](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/ssz/simple-serialize.md).

## Motivation

RLP transactions have a number of shortcomings:

1. **Linear hashing:** The signing hash (`sig_hash`) and unique identifier (`tx_hash`) of an RLP transaction are computed by linear keccak256 hashes across its serialization. Even if only partial data is of interest, linear hashes require the full transaction data to be present, including potentially large calldata or access lists. This also applies when computing the `from` address of a transaction based on the `sig_hash`.

2. **Inefficient inclusion proofs:** The Merkle-Patricia Trie (MPT) backing the execution block header&apos;s `transactions_root` is constructed from the serialized transactions, internally prepending a prefix to the transaction data before it is keccak256 hashed into the MPT. Due to this prefix, there is no on-chain commitment to the `tx_hash` and inclusion proofs require the full transaction data to be present.

3. **Incompatible representation:** As part of the consensus `ExecutionPayload`, the RLP serialization of transactions is hashed using SSZ merkleization. These SSZ hashes are incompatible with both the `tx_hash` and the MPT `transactions_root`.

4. **Technical debt:** All client applications and smart contracts handling RLP transactions have to correctly deal with caveats such as `LegacyTransaction` lacking a prefix byte, the inconsistent `chain_id` and `v` / `y_parity` semantics, and the introduction of `max_priority_fee_per_gas` between other fields instead of at the end. As existing transaction types tend to remain valid perpetually, this technical debt builds up over time.

5. **Inappropriate opaqueness:** The Consensus Layer treats RLP transaction data as opaque, but requires validation of consensus `blob_kzg_commitments` against transaction `blob_versioned_hashes`, resulting in a more complex than necessary engine API.

This EIP addresses these by defining a lossless conversion mechanism to normalize transaction representation across both Consensus Layer and Execution Layer while retaining support for processing RLP transaction types.

## Specification

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

### Existing definitions

Definitions from existing specifications that are used throughout this document are replicated here for reference.

| Name | Value |
| - | - |
| [`BYTES_PER_FIELD_ELEMENT`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/deneb/polynomial-commitments.md#constants) | `uint64(32)` |
| [`FIELD_ELEMENTS_PER_BLOB`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/deneb/polynomial-commitments.md#blob) | `uint64(4096)` |

| Name | SSZ equivalent |
| - | - |
| [`Hash32`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/phase0/beacon-chain.md#custom-types) | `Bytes32` |
| [`ExecutionAddress`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/bellatrix/beacon-chain.md#custom-types) | `Bytes20` |
| [`VersionedHash`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/deneb/beacon-chain.md#custom-types) | `Bytes32` |
| [`KZGCommitment`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/deneb/polynomial-commitments.md#custom-types) | `Bytes48` |
| [`KZGProof`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/deneb/polynomial-commitments.md#custom-types) | `Bytes48` |
| [`Blob`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/deneb/polynomial-commitments.md#custom-types) | `ByteVector[BYTES_PER_FIELD_ELEMENT * FIELD_ELEMENTS_PER_BLOB]` |

### Signatures

Transaction signatures are represented by their native, opaque representation, prefixed by a value indicating their algorithm.

| Name | SSZ equivalent |
| - | - |
| `ExecutionSignature` | `ProgressiveByteList` |
| `ExecutionSignatureAlgorithm` | `uint8` |

#### Secp256k1

| Name | Value | Description |
| - | - | - |
| `SECP256K1_ALGORITHM` | `uint8(0xFF)` | Defined from [EIP-7932](/EIPs/EIPS/eip-7932) |

#### Verification

The following functions are imported from [EIP-7932](/EIPs/EIPS/eip-7932):

- `calculate_penalty`
- `validate_signature`
- `verify_signature`
- `pubkey_to_address`


```python
def get_signature_gas_cost(
    signature: ExecutionSignature,
    sig_hash: Hash32,
    expected_algorithm: Optional[ExecutionSignatureAlgorithm]=None
) -&gt; uint:
    assert len(signature) &gt; 0

    if expected_algorithm is not None:
        assert signature[0] == expected_algorithm

    return calculate_penalty(signature[0], sig_hash)


def validate_execution_signature(
    signature: ExecutionSignature,
    expected_algorithm: Optional[ExecutionSignatureAlgorithm]=None,
):
    assert len(signature) &gt; 0

    if expected_algorithm is not None:
        assert signature[0] == expected_algorithm

    validate_signature(signature)

def recover_execution_signer(signature: ExecutionSignature, sig_hash: Hash32) -&gt; ExecutionAddress:
    public_key = verify_signature(sig_hash, signature)

    return pubkey_to_address(public_key, signature[0])
```

### Gas fees

The different kinds of gas fees are combined into a single structure.

| Name | SSZ equivalent | Description |
| - | - | - |
| `FeePerGas` | `uint256` | Fee per unit of gas |

```python
class BasicFeesPerGas(ProgressiveContainer(active_fields=[1])):
    regular: FeePerGas

class BlobFeesPerGas(ProgressiveContainer(active_fields=[1, 1])):
    regular: FeePerGas
    blob: FeePerGas
```

### Normalized transactions

RLP transactions are converted to a normalized SSZ representation. Their original RLP `TransactionType` is retained to enable recovery of their original RLP representation and associated `sig_hash` and historical `tx_hash` values.

| Name | SSZ equivalent | Description |
| - | - | - |
| `TransactionType` | `uint8` | [EIP-2718](/EIPs/EIPS/eip-2718) transaction type, range `[0x00, 0x7F]` |
| `ChainId` | `uint256` | [EIP-155](/EIPs/EIPS/eip-155) chain ID |
| `GasAmount` | `uint64` | Amount in units of gas |

#### Replayable legacy transactions

The original RLP representation of these transactions is replayable across networks with different chain ID.

```python
class RlpLegacyReplayableBasicTransactionPayload(
    ProgressiveContainer(active_fields=[1, 0, 1, 1, 1, 1, 1, 1])
):
    type_: TransactionType  # 0x00
    nonce: uint64
    max_fees_per_gas: BasicFeesPerGas
    gas: GasAmount
    to: ExecutionAddress
    value: uint256
    input_: ProgressiveByteList

class RlpLegacyReplayableCreateTransactionPayload(
    ProgressiveContainer(active_fields=[1, 0, 1, 1, 1, 0, 1, 1])
):
    type_: TransactionType  # 0x00
    nonce: uint64
    max_fees_per_gas: BasicFeesPerGas
    gas: GasAmount
    value: uint256
    input_: ProgressiveByteList
```

#### EIP-155 legacy transactions

These transactions are locked to a single [EIP-155](/EIPs/EIPS/eip-155) chain ID.

```python
class RlpLegacyBasicTransactionPayload(
    ProgressiveContainer(active_fields=[1, 1, 1, 1, 1, 1, 1, 1])
):
    type_: TransactionType  # 0x00
    chain_id: ChainId
    nonce: uint64
    max_fees_per_gas: BasicFeesPerGas
    gas: GasAmount
    to: ExecutionAddress
    value: uint256
    input_: ProgressiveByteList

class RlpLegacyCreateTransactionPayload(
    ProgressiveContainer(active_fields=[1, 1, 1, 1, 1, 0, 1, 1])
):
    type_: TransactionType  # 0x00
    chain_id: ChainId
    nonce: uint64
    max_fees_per_gas: BasicFeesPerGas
    gas: GasAmount
    value: uint256
    input_: ProgressiveByteList
```

#### Legacy transactions

```python
RlpLegacyTransactionPayload = (
    RlpLegacyReplayableBasicTransactionPayload |
    RlpLegacyReplayableCreateTransactionPayload |
    RlpLegacyBasicTransactionPayload |
    RlpLegacyCreateTransactionPayload
)
```

#### EIP-2930 access list transactions

These transactions support specifying an [EIP-2930](/EIPs/EIPS/eip-2930) access list.

```python
class AccessTuple(Container):
    address: ExecutionAddress
    storage_keys: ProgressiveList[Hash32]

class RlpAccessListBasicTransactionPayload(
    ProgressiveContainer(active_fields=[1, 1, 1, 1, 1, 1, 1, 1, 1])
):
    type_: TransactionType  # 0x01
    chain_id: ChainId
    nonce: uint64
    max_fees_per_gas: BasicFeesPerGas
    gas: GasAmount
    to: ExecutionAddress
    value: uint256
    input_: ProgressiveByteList
    access_list: ProgressiveList[AccessTuple]

class RlpAccessListCreateTransactionPayload(
    ProgressiveContainer(active_fields=[1, 1, 1, 1, 1, 0, 1, 1, 1])
):
    type_: TransactionType  # 0x01
    chain_id: ChainId
    nonce: uint64
    max_fees_per_gas: BasicFeesPerGas
    gas: GasAmount
    value: uint256
    input_: ProgressiveByteList
    access_list: ProgressiveList[AccessTuple]

RlpAccessListTransactionPayload = (
    RlpAccessListBasicTransactionPayload |
    RlpAccessListCreateTransactionPayload
)
```

#### EIP-1559 fee market transactions

These transactions support specifying [EIP-1559](/EIPs/EIPS/eip-1559) priority fees.

```python
class RlpBasicTransactionPayload(
    ProgressiveContainer(active_fields=[1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
):
    type_: TransactionType  # 0x02
    chain_id: ChainId
    nonce: uint64
    max_fees_per_gas: BasicFeesPerGas
    gas: GasAmount
    to: ExecutionAddress
    value: uint256
    input_: ProgressiveByteList
    access_list: ProgressiveList[AccessTuple]
    max_priority_fees_per_gas: BasicFeesPerGas

class RlpCreateTransactionPayload(
    ProgressiveContainer(active_fields=[1, 1, 1, 1, 1, 0, 1, 1, 1, 1])
):
    type_: TransactionType  # 0x02
    chain_id: ChainId
    nonce: uint64
    max_fees_per_gas: BasicFeesPerGas
    gas: GasAmount
    value: uint256
    input_: ProgressiveByteList
    access_list: ProgressiveList[AccessTuple]
    max_priority_fees_per_gas: BasicFeesPerGas

RlpFeeMarketTransactionPayload = (
    RlpBasicTransactionPayload |
    RlpCreateTransactionPayload
)
```

#### EIP-4844 blob transactions

These transactions support specifying [EIP-4844](/EIPs/EIPS/eip-4844) blobs.

```python
class RlpBlobTransactionPayload(
    ProgressiveContainer(active_fields=[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
):
    type_: TransactionType  # 0x03
    chain_id: ChainId
    nonce: uint64
    max_fees_per_gas: BlobFeesPerGas
    gas: GasAmount
    to: ExecutionAddress
    value: uint256
    input_: ProgressiveByteList
    access_list: ProgressiveList[AccessTuple]
    max_priority_fees_per_gas: BasicFeesPerGas
    blob_versioned_hashes: ProgressiveList[VersionedHash]
```

#### EIP-7702 set code transactions

These transactions support specifying an [EIP-7702](/EIPs/EIPS/eip-7702) authorization list.

```python
class RlpReplayableBasicAuthorizationPayload(ProgressiveContainer(active_fields=[1, 0, 1, 1])):
    magic: TransactionType  # 0x05
    address: ExecutionAddress
    nonce: uint64

class RlpBasicAuthorizationPayload(ProgressiveContainer(active_fields=[1, 1, 1, 1])):
    magic: TransactionType  # 0x05
    chain_id: ChainId
    address: ExecutionAddress
    nonce: uint64

class RlpSetCodeAuthorizationPayload(CompatibleUnion({
    0x01: RlpReplayableBasicAuthorizationPayload,
    0x02: RlpBasicAuthorizationPayload,
})):
    pass

class RlpSetCodeAuthorization(Container):
    payload: RlpSetCodeAuthorizationPayload
    signature: ExecutionSignature

class RlpSetCodeTransactionPayload(
    ProgressiveContainer(active_fields=[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1])
):
    type_: TransactionType  # 0x04
    chain_id: ChainId
    nonce: uint64
    max_fees_per_gas: BasicFeesPerGas
    gas: GasAmount
    to: ExecutionAddress
    value: uint256
    input_: ProgressiveByteList
    access_list: ProgressiveList[AccessTuple]
    max_priority_fees_per_gas: BasicFeesPerGas
    authorization_list: ProgressiveList[RlpSetCodeAuthorization]
```

#### Transaction helpers

```python
class TransactionPayload(CompatibleUnion({
    0x01: RlpLegacyReplayableBasicTransactionPayload,
    0x02: RlpLegacyReplayableCreateTransactionPayload,
    0x03: RlpLegacyBasicTransactionPayload,
    0x04: RlpLegacyCreateTransactionPayload,
    0x05: RlpAccessListBasicTransactionPayload,
    0x06: RlpAccessListCreateTransactionPayload,
    0x07: RlpBasicTransactionPayload,
    0x08: RlpCreateTransactionPayload,
    0x09: RlpBlobTransactionPayload,
    0x0a: RlpSetCodeTransactionPayload,
})):
    pass

class Transaction(Container):
    payload: TransactionPayload
    signature: ExecutionSignature

class RlpTxType(IntEnum):
    LEGACY = 0x00
    ACCESS_LIST = 0x01
    FEE_MARKET = 0x02
    BLOB = 0x03
    SET_CODE = 0x04
    SET_CODE_MAGIC = 0x05

def calculate_transaction_intrinsic_gas(tx: Transaction) -&gt; uint:
    tx_data = tx.payload.data()
    gas_cost = TX_BASE_COST # FIXME: Should this be defined from another EIP?

    if hasattr(tx_data, &quot;authorization_list&quot;):
        for auth in tx_data.authorization_list:
            gas_cost += get_signature_gas_cost(auth.signature, expected_algorithm=expected_signature_algorithm)

    gas_cost += get_signature_gas_cost(tx.signature, expected_algorithm=expected_signature_algorithm)

    return gas_cost

def validate_transaction(tx: Transaction):
    tx_data = tx.payload.data()

    expected_signature_algorithm = None

    if hasattr(tx_data, &quot;type_&quot;):
        expected_signature_algorithm = SECP256K1_ALGORITHM
        match tx_data.type_:
            case RlpTxType.LEGACY:
                assert isinstance(tx_data, RlpLegacyTransactionPayload)
            case RlpTxType.ACCESS_LIST:
                assert isinstance(tx_data, RlpAccessListTransactionPayload)
            case RlpTxType.FEE_MARKET:
                assert isinstance(tx_data, RlpFeeMarketTransactionPayload)
            case RlpTxType.BLOB:
                assert isinstance(tx_data, RlpBlobTransactionPayload)
            case RlpTxType.SET_CODE:
                assert isinstance(tx_data, RlpSetCodeTransactionPayload)
            case _:
                assert False

    if hasattr(tx_data, &quot;authorization_list&quot;):
        for auth in tx_data.authorization_list:
            auth_data = auth.payload.data()

            if hasattr(auth_data, &quot;magic&quot;):
                assert auth_data.magic == RlpTxType.SET_CODE_MAGIC
            if hasattr(auth_data, &quot;chain_id&quot;):
                assert auth_data.chain_id != 0

            validate_execution_signature(auth.signature, compute_auth_hash(auth), expected_algorithm=expected_signature_algorithm)
    
    validate_execution_signature(tx.signature, compute_sig_hash(tx), expected_algorithm=expected_signature_algorithm)

```

### Execution block header changes

The [execution block header&apos;s `txs-root`](https://github.com/ethereum/devp2p/blob/bc76b9809a30e6dc5c8dcda996273f0f9bcf7108/caps/eth.md#block-encoding-and-validity) is transitioned from MPT to SSZ.

```python
transactions = ProgressiveList[Transaction](
    tx_0, tx_1, tx_2, ...)

block_header.transactions_root = transactions.hash_tree_root()
```

### Engine API

In the engine API, the semantics of the `transactions` field in `ExecutionPayload` versions adopting this EIP are changed to emit transactions using SSZ serialization.

- `transactions` - `Array` of `DATA` - Array of transaction objects, each object is a byte list (`DATA`) representing `ssz.serialize(tx)`

### Consensus `ExecutionPayload` changes

When building a consensus `ExecutionPayload`, the [`transactions`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/deneb/beacon-chain.md#executionpayload) list is no longer opaque and uses the new `Transaction` type, aligning the `transactions_root` across execution blocks and execution payloads.

```python
class ExecutionPayload(...):
    ...
    transactions: ProgressiveList[Transaction]
    ...
```

### Unique transaction identifier

For each transaction, an additional identifier `tx_root` SHALL be assigned:

```python
def compute_tx_root(tx: Transaction) -&gt; Hash32:
    return Hash32(tx.hash_tree_root())
```

Note that this `tx_root` differs from the existing `tx_hash`. Existing APIs based on `tx_hash` remain available.

## Rationale

### Forward compatibility

The proposed transaction design is extensible with new fee types, new signature types, and entirely new transaction features (e.g., CREATE2), while retaining compatibility with the proposed transactions.

### Verifier improvements

The `transactions_root` is effectively constructed from the list of `tx_root`, enabling transaction inclusion proofs. Further, partial data becomes provable, such as destination / amount without requiring the full calldata. This can reduce gas cost or zk proving cost when verifying L2 chain data in an L1 smart contract.

### Consensus client improvements

Consensus Layer implementations may drop invalid blocks early if consensus `blob_kzg_commitments` do not validate against transaction `blob_versioned_hashes` and no longer need to query the Execution Layer for that validation. Future versions of the engine API could be simplified to drop the transfers of `blob_kzg_commitments` to the EL.

## Backwards Compatibility

Applications that rely on the replaced MPT `transactions_root` in the block header require migration to the SSZ `transactions_root`.

While there is no on-chain commitment of the `tx_hash`, it is widely used in JSON-RPC and the [Ethereum Wire Protocol](https://github.com/ethereum/devp2p/blob/bc76b9809a30e6dc5c8dcda996273f0f9bcf7108/caps/eth.md) to uniquely identify transactions. The conversion from RLP transactions to SSZ is lossless. The original RLP `sig_hash` and `tx_hash` can be recovered from the SSZ representation.

RLP and SSZ transactions may clash when encoded. It is essential to use only a single format within one channel.

## Security Considerations

None

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 30 Jan 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6404</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6404</guid>
      </item>
    
      <item>
        <title>Minimal Transferable NFT detection interface</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/minimalistic-transferable-interface/12517</comments>
        
        <description>## Abstract

The Minimalistic Transferable interface for Non-Fungible Tokens standard extends [ERC-721](/EIPs/EIPS/eip-721) by introducing the ability to identify whether an NFT can be transferred or not.

This proposal introduces the ability to prevent a token from being transferred from their owner, making them bound to the externally owned account, abstracted account, smart contract or token that owns it.

## Motivation

With NFTs being a widespread form of tokens in the Ethereum ecosystem and being used for a variety of use cases, it is time to standardize additional utility for them. Having the ability to prevent the tokens from being transferred introduces new possibilities of NFT utility and evolution.

This proposal is designed in a way to be as minimal as possible in order to be compatible with any usecases that wish to utilize this proposal.

This EIP introduces new utilities for [ERC-721](/EIPs/EIPS/eip-721) based tokens in the following areas:

- [Verifiable attribution](#verifiable-attribution)
- [Immutable properties](#immutable-properties)

### Verifiable attribution

Personal achievements can be represented by non-fungible tokens. These tokens can be used to represent a wide range of accomplishments, including scientific advancements, philanthropic endeavors, athletic achievements, and more. However, if these achievement-indicating NFTs can be easily transferred, their authenticity and trustworthiness can be called into question. By binding the NFT to a specific account, it can be ensured that the account owning the NFT is the one that actually achieved the corresponding accomplishment. This creates a secure and verifiable record of personal achievements that can be easily accessed and recognized by others in the network. The ability to verify attribution helps to establish the credibility and value of the achievement-indicating NFT, making it a valuable asset that can be used as a recognition of the holder&apos;s accomplishments.

### Immutable properties

NFT properties are a critical aspect of non-fungible tokens, serving to differentiate them from one another and establish their scarcity. Centralized control of NFT properties by the issuer, however, can undermine the uniqueness of these properties.

By tying NFTs to specific properties, the original owner is ensured that the NFT will always retain these properties and its uniqueness.

In a blockchain game that employs non-transferable NFTs to represent skills or abilities, each skill would be a unique and permanent asset tied to a specific player or token. This would ensure that players retain ownership of the skills they have earned and prevent them from being traded or sold to other players. This can increase the perceived value of these skills, enhancing the player experience by allowing for greater customization and personalization of characters.

## Specification

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.

```solidity
/// @title EIP-6454 Minimalistic Non-Transferable interface for NFTs
/// @dev See https://eips.ethereum.org/EIPS/eip-6454
/// @dev Note: the ERC-165 identifier for this interface is 0x91a6262f.

pragma solidity ^0.8.16;

interface IERC6454 /* is IERC165 */ {
    /**
     * @notice Used to check whether the given token is transferable or not.
     * @dev If this function returns `false`, the transfer of the token MUST revert execution.
     * @dev If the tokenId does not exist, this method MUST revert execution, unless the token is being checked for
     *  minting.
     * @dev The `from` parameter MAY be used to also validate the approval of the token for transfer, but anyone
     *  interacting with this function SHOULD NOT rely on it as it is not mandated by the proposal.
     * @param tokenId ID of the token being checked
     * @param from Address from which the token is being transferred
     * @param to Address to which the token is being transferred
     * @return Boolean value indicating whether the given token is transferable
     */
    function isTransferable(uint256 tokenId, address from, address to) external view returns (bool);
}
```

In order to determine whether a token is transferable or not in general, the function SHOULD return the appropriate boolean value when passing the `0x0000000000000000000000000000000000000000` address as the `to` and `from` parameter.

The general transferability of a token should not be affected by the ability to mint the token (value of `from` parameter is `0x0000000000000000000000000000000000000000`) and the ability to burn the token (value of `to` parameter is `0x0000000000000000000000000000000000000000`).

If the general transferability of token is `false`, any kind of transfer of the token, save minting and burning, MUST revert execution.

In order to determine whether a token is mintable, the exception SHOULD be made to allow the `tokenId` parameter for a token that does not exist. Additionally the `from` parameter SHOULD be `0x0000000000000000000000000000000000000000` and the `to` parameter SHOULD NOT be `0x0000000000000000000000000000000000000000`.

In order to determine whether a token is burnable, the `from` parameter SHOULD NOT be `0x0000000000000000000000000000000000000000` and the `to` parameter SHOULD be `0x0000000000000000000000000000000000000000`.

Implementers MAY choose to validate the approval of the token for transfer by the `from` parameter, but anyone interacting with this function SHOULD NOT rely on it as it is not mandated by the proposal. This means that the `from` parameter in such implementations validates the initiator of the transaction rather than the owner from which the token is being transferred (which can either be the owner of the token or the operator allowed to transfer the token).

## Rationale

Designing the proposal, we considered the following questions:

1. **Should we propose another (Non-)Transferable NFT proposal given the existence of existing ones, some even final, and how does this proposal compare to them?**\
   This proposal aims to provide the minimum necessary specification for the implementation of non-transferable NFTs, we feel none of the existing proposals have presented the minimal required interface. Unlike other proposals that address the same issue, this proposal requires fewer methods in its specification, providing a more streamlined solution.
2. **Why is there no event marking the token as Non-Transferable in this interface?**\
   The token can become non-transferable either at its creation, after being marked as non-transferable, or after a certain condition is met. This means that some cases of tokens becoming non-transferable cannot emit an event, such as if the token becoming non-transferable is determined by a block number. Requiring an event to be emitted upon the token becoming non-transferable is not feasible in such cases.
3. **Should the transferability state management function be included in this proposal?**\
   A function that marks a token as non-transferable or releases the binding is referred to as the transferability management function. To maintain the objective of designing an agnostic minimal transferable proposal, we have decided not to specify the transferability management function. This allows for a variety of custom implementations that require the tokens to be non-transferable.
4. **Why should this be an EIP if it only contains one method?**\
   One could argue that since the core of this proposal is to only prevent ERC-721 tokens to be transferred, this could be done by overriding the transfer function. While this is true, the only way to assure that the token is non-transferable before the smart contract execution, is for it to have the transferable interface.\
   This also allows for smart contract to validate whether the token is not transferable and not attempt transferring it as this would result in failed transactions and wasted gas.
5. **Should we include the most straightforward method possible that only accepts a `tokenId` parameter?**\
   The initial version of the proposal contained a method that only accepted a `tokenId` parameter. This method would return a boolean value indicating whether the token is transferable. However, the fact that the token can be non-transferable for different reasons was brought up throughout the discussion. This is why the method was changed to accept additional parameters, allowing for a more flexible implementation. Additionally, we kept the original method’s functionality by specifying the methodology on how to achieve the same result (by passing the `0x0000000000000000000000000000000000000000` address as the `to` and `from` parameters).
6. **What is the best user experience for frontend?**\
   The best user experience for the front end is having a single method that checks whether the token is transferable. This method should handle both cases of transferability, general and conditional.\
   The front end should also be able to handle the case where the token is not transferable and the transfer is attempted. This can be done by checking the return value of the transfer function, which will be false if the token is not transferable. If the token would just be set as non-transferable, without a standardized interface to check whether the token is transferable, the only way to validate transferability would be to attempt a gas calculation and check whether the transaction would revert. This is a bad user experience and should be avoided.
7. **Should we mandate that the `isTransferable` validates approvals as well?**\
   We considered specifying that the `from` parameter represents the initiator of the token transfer. This would mean that the `from` would validate whether the address is the owner of the token or approved to transfer it. While this might be beneficial, we ultimately decided to make it optional.\
   As this proposal aims to be the minimal possible implementation and the approvals are already standardized, we feel that `isTransferable` can be used in conjunction with the approvals to validate whether the given address can initiate the transfer or not.\
   Additionally, mandating the validation of approvals would incur higher gas consumption as additional checks would be required to validate the transferability.

## Backwards Compatibility

The Minimalistic Non-Transferable token standard is fully compatible with [ERC-721](/EIPs/EIPS/eip-721) and with the robust tooling available for implementations of ERC-721 as well as with the existing ERC-721 infrastructure.

## Test Cases

Tests are included in [`transferable.ts`](/EIPs/assets/eip-6454/test/transferable.ts).

To run them in terminal, you can use the following commands:

```
cd ../assets/eip-6454
npm install
npx hardhat test
```

## Reference Implementation

See [`ERC721TransferableMock.sol`](/EIPs/assets/eip-6454/contracts/mocks/ERC721TransferableMock.sol).

## Security Considerations

The same security considerations as with [ERC-721](/EIPs/EIPS/eip-721) apply: hidden logic may be present in any of the functions, including burn, add asset, accept asset, and more.

A smart contract can implement the proposal interface but returns fraudulent values, i.e., returning `false` for `isTransferable` when the token is transferable. Such a contract would trick other contracts into thinking that the token is non-transferable when it is transferable. If such a contract exists, we suggest not interacting with it. Much like fraudulent [ERC-20](/EIPs/EIPS/eip-20) or [ERC-721](/EIPs/EIPS/eip-721) smart contracts, it is not possible to prevent such contracts from existing. We suggest that you verify all of the external smart contracts you interact with and not interact with contracts you do not trust.

Since the transferability state can change over time, verifying that the state of the token is transferable before interacting with it is essential. Therefore, a dApp, marketplace, or wallet implementing this interface should verify the state of the token every time the token is displayed.

Caution is advised when dealing with non-audited contracts.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 31 Jan 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6454</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6454</guid>
      </item>
    
      <item>
        <title>Multi-operator, per-token ERC-721 approvals.</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/fine-grained-erc721-approval-for-multiple-operators/12796</comments>
        
        <description>## Abstract

[ERC-721](/EIPs/EIPS/eip-721) did not foresee the approval of multiple operators to manage a specific token on behalf of its owner. This lead to the establishment of `setApprovalForAll()` as the predominant way to authorise operators, which affords the approved address control over all assets and creates an unnecessarily broad security risk that has already been exploited in a multitude of phishing attacks. The presented EIP extends ERC-721 by introducing a fine-grained, on-chain approval mechanism that allows owners to authorise multiple, specific operators on a per-token basis; this removes unnecessary access permissions and shrinks the surface for exploits to a minimum. The provided reference implementation further enables cheap revocation of all approvals on a per-owner or per-token basis.

## Motivation

The NFT standard defined in ERC-721 allows token owners to &quot;approve&quot; arbitrary addresses to control their tokens—the approved addresses are known as &quot;operators&quot;. Two types of approval were defined:

1. `approve(address,uint256)` provides a mechanism for only a single operator to be approved for a given `tokenId`; and
2. `setApprovalForAll(address,bool)` toggles whether an operator is approved for *every* token owned by `msg.sender`.

With the introduction of multiple NFT marketplaces, the ability to approve multiple operators for a particular token is necessary if sellers wish to allow each marketplace to transfer a token upon sale. There is, however, no mechanism for achieving this without using `setApprovalForAll()`. This is in conflict with the principle of least privilege and creates an attack vector that is exploited by phishing for malicious (i.e. zero-cost) sell-side signatures that are executed by legitimate marketplace contracts.

This EIP therefore defines a fine-grained approach for approving multiple operators but scoped to specific token(s).

### Goals

1. Ease of adoption for marketplaces; requires minimal changes to existing workflows.
2. Ease of adoption for off-chain approval-indexing services.
3. Simple revocation of approvals; i.e. not requiring one per grant.

### Non-goals

1. Security measures for protecting NFTs other than through limiting the scope of operator approvals.
2. Compatibility with [ERC-1155](/EIPs/EIPS/eip-1155) semi-fungible tokens. However we note that the mechanisms described herein are also applicable to ERC-1155 token *types* without requiring approval for all other types.

## Specification

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

To comply with this EIP, a contract MUST implement `IERC6464` (defined herein) and the `ERC165` and `ERC721` interfaces; see [ERC-165](/EIPs/EIPS/eip-165) and ERC-721 respectively.

```solidity
/**
 * @notice Extends ERC-721 to include per-token approval for multiple operators.
 * @dev Off-chain indexers of approvals SHOULD assume that an operator is approved if either of `ERC721.Approval(…)` or
 * `ERC721.ApprovalForAll(…, true)` events are witnessed without the corresponding revocation(s), even if an
 * `ExplicitApprovalFor(…, false)` is emitted.
 * @dev TODO: the ERC-165 identifier for this interface is TBD.
 */
interface IERC6464 is ERC721 {
    /**
     * @notice Emitted when approval is explicitly granted or revoked for a token.
     */
    event ExplicitApprovalFor(
        address indexed operator,
        uint256 indexed tokenId,
        bool approved
    );

    /**
     * @notice Emitted when all explicit approvals, as granted by either `setExplicitApprovalFor()` function, are
     * revoked for all tokens.
     * @dev MUST be emitted upon calls to `revokeAllExplicitApprovals()`.
     */
    event AllExplicitApprovalsRevoked(address indexed owner);

    /**
     * @notice Emitted when all explicit approvals, as granted by either `setExplicitApprovalFor()` function, are
     * revoked for the specific token.
     * @param owner MUST be `ownerOf(tokenId)` as per ERC721; in the case of revocation due to transfer, this MUST be
     * the `from` address expected to be emitted in the respective `ERC721.Transfer()` event.
     */
    event AllExplicitApprovalsRevoked(
        address indexed owner,
        uint256 indexed tokenId
    );

    /**
     * @notice Approves the operator to manage the asset on behalf of its owner.
     * @dev Throws if `msg.sender` is not the current NFT owner, or an authorised operator of the current owner.
     * @dev Approvals set via this method MUST be revoked upon transfer of the token to a new owner; equivalent to
     * calling `revokeAllExplicitApprovals(tokenId)`, including associated events.
     * @dev MUST emit `ApprovalFor(operator, tokenId, approved)`.
     * @dev MUST NOT have an effect on any standard ERC721 approval setters / getters.
     */
    function setExplicitApproval(
        address operator,
        uint256 tokenId,
        bool approved
    ) external;

    /**
     * @notice Approves the operator to manage the token(s) on behalf of their owner.
     * @dev MUST be equivalent to calling `setExplicitApprovalFor(operator, tokenId, approved)` for each `tokenId` in
     * the array.
     */
    function setExplicitApproval(
        address operator,
        uint256[] memory tokenIds,
        bool approved
    ) external;

    /**
     * @notice Revokes all explicit approvals granted by `msg.sender`.
     * @dev MUST emit `AllExplicitApprovalsRevoked(msg.sender)`.
     */
    function revokeAllExplicitApprovals() external;

    /**
     * @notice Revokes all excplicit approvals granted for the specified token.
     * @dev Throws if `msg.sender` is not the current NFT owner, or an authorised operator of the current owner.
     * @dev MUST emit `AllExplicitApprovalsRevoked(msg.sender, tokenId)`.
     */
    function revokeAllExplicitApprovals(uint256 tokenId) external;

    /**
     * @notice Query whether an address is an approved operator for a token.
     */
    function isExplicitlyApprovedFor(address operator, uint256 tokenId)
        external
        view
        returns (bool);
}

interface IERC6464AnyApproval is ERC721 {
    /**
     * @notice Returns true if any of the following criteria are met:
     * 1. `isExplicitlyApprovedFor(operator, tokenId) == true`; OR
     * 2. `isApprovedForAll(ownerOf(tokenId), operator) == true`; OR
     * 3. `getApproved(tokenId) == operator`.
     * @dev The criteria MUST be extended if other mechanism(s) for approving operators are introduced. The criteria
     * MUST include all approval approaches.
     */
    function isApprovedFor(address operator, uint256 tokenId)
        external
        view
        returns (bool);
}
```

## Rationale

### Draft notes to be expanded upon

1. Approvals granted via the newly introduced methods are called *explicit* as a means of easily distinguishing them from those granted via the standard `ERC721.approve()` and `ERC721.setApprovalForAll()` functions. However they follow the same intent: authorising operators to act on the owner&apos;s behalf.
2. Abstracting `isApprovedFor()` into `IERC6464AnyApproval` interface, as against keeping it in `IERC6464` allows for modularity of plain `IERC6464` implementations while also standardising the interface for checking approvals when interfacing with specific implementations and any future approval EIPs.
3. Inclusion of an indexed owner address in `AllExplicitApprovalsRevoked(address,uint256)` assists off-chain indexing of existing approvals.
4. Re `IERC6464AnyApproval`: With an increasing number of approval mechanisms it becomes cumbersome for marketplaces to integrate with them since they have to query multiple interfaces to check if they are approved to manage tokens. This provides a streamlined interface, intended to simplify data ingestion for them.

&lt;!--
  The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages.

  The current placeholder is acceptable for a draft.

  TODO: Remove this comment before submitting
--&gt;

## Backwards Compatibility

This extension was written to allow for the smallest change possible to the original ERC-721 spec while still providing a mechanism to grant, revoke and track approvals of multiple operators on a per-token basis.

Extended contracts remain fully compatible with all existing platforms.

**Note** the `Security Considerations` sub-section on `Other risks` regarding interplay of approval types.

## Reference Implementation

TODO: add internal link to assets directory when the implementation is in place.

An efficient mechanism for broad revocation of approvals via incrementing nonces is included.

## Security Considerations

### Threat model

### Mitigations

### Other risks

TODO: Interplay with `setApprovalForAll()`.

&lt;!--
  All EIPs must contain a section that discusses the security implications/considerations relevant to the proposed change. Include information that might be important for security discussions, surfaces risks and can be used throughout the life cycle of the proposal. For example, include security-relevant design decisions, concerns, important discussions, implementation-specific guidance and pitfalls, an outline of threats and risks and how they are being addressed. EIP submissions missing the &quot;Security Considerations&quot; section will be rejected. An EIP cannot proceed to status &quot;Final&quot; without a Security Considerations discussion deemed sufficient by the reviewers.

  The current placeholder is acceptable for a draft.

  TODO: Remove this comment before submitting
--&gt;

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 02 Feb 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6464</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6464</guid>
      </item>
    
      <item>
        <title>SSZ withdrawals root</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6465-ssz-withdrawals-root/12883</comments>
        
        <description>## Abstract

This EIP defines a migration process of the existing Merkle Patricia Trie (MPT) commitment for withdrawals to [Simple Serialize (SSZ)](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/ssz/simple-serialize.md).

## Motivation

While the consensus `ExecutionPayloadHeader` and the execution block header map to each other conceptually, they are encoded differently. This EIP aims to align the encoding of the `withdrawals_root`, taking advantage of the more modern SSZ format. This brings several advantages:

1. **Reducing complexity:** The proposed design reduces the number of use cases that require support for Merkle Patricia Trie (MPT).

2. **Reducing ambiguity:** The name `withdrawals_root` is currently used to refer to different roots. While the execution block header refers to a Merkle Patricia Trie (MPT) root, the consensus `ExecutionPayloadHeader` instead refers to an SSZ root. With these changes, `withdrawals_root` consistently refers to the same SSZ root.

## Specification

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

### Existing definitions

Definitions from existing specifications that are used throughout this document are replicated here for reference.

| Name | SSZ equivalent |
| - | - |
| [`ValidatorIndex`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/phase0/beacon-chain.md#custom-types) | `uint64` |
| [`Gwei`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/phase0/beacon-chain.md#custom-types) | `uint64` |
| [`ExecutionAddress`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/bellatrix/beacon-chain.md#custom-types) | `Bytes20`
| [`WithdrawalIndex`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/capella/beacon-chain.md#custom-types) | `uint64` |

### Withdrawals

New withdrawals use a normalized SSZ representation. The existing consensus [`Withdrawal`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/capella/beacon-chain.md#withdrawal) SSZ container is migrated to [EIP-7495 `ProgressiveContainer`](/EIPs/EIPS/eip-7495).

```python
class Withdrawal(ProgressiveContainer(active_fields=[1, 1, 1, 1])):
    index: WithdrawalIndex
    validator_index: ValidatorIndex
    address: ExecutionAddress
    amount: Gwei
```

### Execution block header changes

The [execution block header&apos;s `withdrawals-root`](https://github.com/ethereum/devp2p/blob/bc76b9809a30e6dc5c8dcda996273f0f9bcf7108/caps/eth.md#block-encoding-and-validity) is transitioned from MPT to SSZ.

```python
withdrawals = ProgressiveList[Withdrawal](
    withdrawal_0, withdrawal_1, withdrawal_2, ...)

block_header.withdrawals_root = withdrawals.hash_tree_root()
```

### Consensus `ExecutionPayload` changes

When building a consensus `ExecutionPayload`, the [`withdrawals`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/deneb/beacon-chain.md#executionpayload) list is based on the new progressive container type.

```python
class ExecutionPayload(...):
    ...
    withdrawals: ProgressiveList[Withdrawal]
    ...
```

The state transition function is updated to limit withdrawals to [`MAX_WITHDRAWALS_PER_PAYLOAD`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/capella/beacon-chain.md#execution).

## Rationale

This change was originally a candidate for inclusion in Shanghai, but was postponed to accelerate the rollout of withdrawals.

## Backwards Compatibility

Applications that rely on the replaced MPT `withdrawals_root` in the block header require migration to the SSZ `withdrawals_root`.

RLP and SSZ withdrawals may clash when encoded. It is essential to use only a single format within one channel. The block header corresponding to the withdrawals can be consulted to identify the underlying fork.

## Security Considerations

None

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 08 Feb 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6465</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6465</guid>
      </item>
    
      <item>
        <title>SSZ receipts</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6466-ssz-receipts/12884</comments>
        
        <description>## Abstract

This EIP defines a migration process of [EIP-2718](/EIPs/EIPS/eip-2718) Recursive-Length Prefix (RLP) receipts to [Simple Serialize (SSZ)](https://github.com/ethereum/consensus-specs/blob/b3e83f6691c61e5b35136000146015653b22ed38/ssz/simple-serialize.md)

## Motivation

RLP receipts have a number of shortcomings:

1. **Limited proving support:** Due to receipt data being linearly hashed as part of the `receipts_root` Merkle-Patricia Trie (MPT), it is not possible to efficiently proof individual parts of receipts, such as logs. Requiring the full receipt data to be present can be prohibitive for smart contract based applications such as L2 fraud proofs or client applications verifying log data.

2. **Incomplete data:** JSON-RPC provides `from`, `gasUsed`, and `contractAddress` fields for receipts, but the on-chain receipt does not contain the required information to verify them.

This EIP defines a universal receipt format based on SSZ to address these concerns.

## Specification

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

### Existing definitions

Definitions from existing specifications that are used throughout this document are replicated here for reference.

| Name | SSZ equivalent |
| - | - |
| [`Root`](https://github.com/ethereum/consensus-specs/blob/b3e83f6691c61e5b35136000146015653b22ed38/specs/phase0/beacon-chain.md#custom-types) | `Bytes32` |
| [`ExecutionAddress`](https://github.com/ethereum/consensus-specs/blob/b3e83f6691c61e5b35136000146015653b22ed38/specs/bellatrix/beacon-chain.md#custom-types) | `Bytes20` |
| [`GasAmount`](/EIPs/EIPS/eip-6404#normalized-transactions) | `uint64` |

### Logs

Logs are represented as an SSZ `Container`.

| Name | Value | Description |
| - | - | - |
| `MAX_TOPICS_PER_LOG` | `4` | `LOG0` through `LOG4` opcodes allow 0-4 topics per log |

```python
class Log(Container):
    address: ExecutionAddress
    topics: List[Bytes32, MAX_TOPICS_PER_LOG]
    data: ProgressiveByteList
```

### Receipts

New receipts use a normalized SSZ representation.

```python
class Receipt(CompatibleUnion({
    0x01: BasicReceipt,
    0x02: CreateReceipt,
    0x03: SetCodeReceipt,
})):
    pass
```

#### Basic receipts

This receipt is emitted for these transactions:

- [`RlpLegacyReplayableBasicTransaction`](/EIPs/EIPS/eip-6404#normalized-transactions)
- [`RlpLegacyBasicTransaction`](/EIPs/EIPS/eip-6404#normalized-transactions)
- [`RlpAccessListBasicTransaction`](/EIPs/EIPS/eip-6404#normalized-transactions)
- [`RlpBasicTransaction`](/EIPs/EIPS/eip-6404#normalized-transactions)
- [`RlpBlobTransaction`](/EIPs/EIPS/eip-6404#normalized-transactions)

```python
class BasicReceipt(
    ProgressiveContainer(active_fields=[1, 1, 0, 1, 1])
):
    from_: ExecutionAddress
    gas_used: GasAmount
    logs: ProgressiveList[Log]
    status: boolean
```

#### Create receipts

This receipt is emitted for these transactions:

- [`RlpLegacyReplayableCreateTransaction`](/EIPs/EIPS/eip-6404#normalized-transactions)
- [`RlpLegacyCreateTransaction`](/EIPs/EIPS/eip-6404#normalized-transactions)
- [`RlpAccessListCreateTransaction`](/EIPs/EIPS/eip-6404#normalized-transactions)
- [`RlpCreateTransaction`](/EIPs/EIPS/eip-6404#normalized-transactions)

```python
class CreateReceipt(
    ProgressiveContainer(active_fields=[1, 1, 1, 1, 1])
):
    from_: ExecutionAddress
    gas_used: GasAmount
    contract_address: ExecutionAddress
    logs: ProgressiveList[Log]
    status: boolean
```

#### EIP-7702 set code receipts

This receipt is emitted for these transactions:

- [`RlpSetCodeTransaction`](/EIPs/EIPS/eip-6404#normalized-transactions)

```python
class SetCodeReceipt(
    ProgressiveContainer(active_fields=[1, 1, 0, 1, 1, 1])
):
    from_: ExecutionAddress
    gas_used: GasAmount
    logs: ProgressiveList[Log]
    status: boolean
    authorities: ProgressiveList[ExecutionAddress]
```

### `Receipt` construction

Receipts are constructed as follows.

| Field | Description |
| - | - |
| `from` | The transaction sender&apos;s address |
| `gas_used` | How much gas this individual transaction used |
| `contract_address` | For transactions deploying a contract, the new contract address. Present only in `CreateReceipt` |
| `logs` | Logs emitted during transaction execution |
| `status` | [EIP-658](/EIPs/EIPS/eip-658) transaction status code |
| `authorities` | For transactions with an authorization list, the list of [EIP-7702](/EIPs/EIPS/eip-7702) `authority` addresses. Non-successful authorizations are represented with an all-zero address |

The `logs_bloom`, intermediate state `root` (Homestead scheme), and `cumulative_gas_used` (pre [EIP-8116](/EIPs/EIPS/eip-8116)) fields are not present in SSZ receipts.

### Execution block header changes

The [execution block header&apos;s `receipts-root`](https://github.com/ethereum/devp2p/blob/bc76b9809a30e6dc5c8dcda996273f0f9bcf7108/caps/eth.md#block-encoding-and-validity) is transitioned from MPT to SSZ.

```python
receipts = ProgressiveList[Receipt](
    receipt_0, receipt_1, receipt_2, ...)

block_header.receipts_root = receipts.hash_tree_root()
```

### JSON-RPC API

Transaction receipt objects in the context of the JSON-RPC API are extended to include:

- `authorities`: `Array of DATA|null` - Array of `DATA` entries each containing 20 Bytes, corresponding to the receipt&apos;s `authorities` field

The `logsBloom` field is no longer returned for new receipts. It continues to be returned for historical receipts conforming to earlier schemes.

`from`, `gasUsed`, and `contractAddress` are already provided via JSON-RPC and are left unchanged. For `BasicReceipt` and `SetCodeReceipt`, `contractAddress` will be `null` as these receipt types do not contain the `contract_address` field. `logIndex` indicates the log index position in the individual receipt (rather than the entire block), as defined in [EIP-8116](/EIPs/EIPS/eip-8116).

### Consensus `ExecutionPayload` changes

When building a consensus `ExecutionPayload`, the [`receipts_root`](https://github.com/ethereum/consensus-specs/blob/b3e83f6691c61e5b35136000146015653b22ed38/specs/deneb/beacon-chain.md#executionpayload) is now based on the `Receipt` type, changing the type of `receipts_root` from an MPT [`Hash32`](https://github.com/ethereum/consensus-specs/blob/b3e83f6691c61e5b35136000146015653b22ed38/specs/phase0/beacon-chain.md#custom-types) to an SSZ [`Root`](https://github.com/ethereum/consensus-specs/blob/b3e83f6691c61e5b35136000146015653b22ed38/specs/phase0/beacon-chain.md#custom-types).

```python
class ExecutionPayload(...):
    ...
    receipts_root: Root
    ...

class ExecutionPayloadHeader(...):
    ...
    receipts_root: Root
    ...
```

```python
payload_header.receipts_root = payload.receipts_root
```

## Rationale

### Forward compatibility

All receipts share the same Merkle tree shape with a stable [generalized index (gindex)](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/ssz/merkle-proofs.md#generalized-merkle-tree-index) assigned to each field. Future transaction features can introduce additional receipt fields or drop existing fields without breaking verifiers.

### Verifier improvements

Committing to `from`, `contract_address` and `authorities` in the receipt allows efficient verification without the expensive `ecrecover` mechanism. This allows future EIPs to change how these addresses are computed without breaking verifiers, e.g., when future signature schemes are introduced.

### Execution client improvements

Execution Layer implementations no longer need access to the transaction and additional indices when serving receipts based on SSZ.

## Backwards Compatibility

Applications that rely on the replaced MPT `receipts_root` in the block header require migration to the SSZ `receipts_root`.

RLP and SSZ receipts may clash when encoded. It is essential to use only a single format within one channel. When requesting receipts by hash over the network, the block header corresponding to the containing receipts root can be consulted to identify the underlying fork.

## Security Considerations

None

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 08 Feb 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6466</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6466</guid>
      </item>
    
      <item>
        <title>SSZ Optional</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6475-ssz-optional/12891</comments>
        
        <description>## Abstract

This EIP introduces a new [Simple Serialize (SSZ) type](https://github.com/ethereum/consensus-specs/blob/67c2f9ee9eb562f7cc02b2ff90d92c56137944e1/ssz/simple-serialize.md) to represent `Optional[T]` values.

## Motivation

Optional values are currently only representable in SSZ using workarounds. Adding proper support provides these benefits:

1. **Better readability:** SSZ structures with optional values can be represented with idiomatic types of the underlying programming language, e.g., `Optional[T]` in Python, making them easier to interact with.

2. **Compact serialization:** SSZ serialization can rely on the binary nature of optional values; they either exist or they don&apos;t. This allows more compact serialization than using alternative approaches based on workarounds.

## Specification

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

### Type definition

`Optional[T]` is defined as a type that can represent:

- A value of SSZ type `T`
- Absence of a value, indicated by `None`

### Default value

The default value of `Optional[T]` is `None`.

### Serialization

```python
if value is None:
    return b&quot;&quot;
else:
    return b&quot;\x01&quot; + serialize(value)
```

### Deserialization

The deserialization of an `Optional[T]` depends on the input length:

- If the input length is 0, the value is `None`.
- Otherwise, the first byte of the deserialization scope must be checked to be `0x01`, the remainder of the scope is deserialized same as `T`.

### Merkleization

An `Optional[T]` is merkleized as a `List[T, 1]`.

- If the value is `None`, the list length is `0`.
- Otherwise, the list length is `1`, and the first list element contains the underlying value.

## Rationale

### Why not `Union[None, T]`?

`Union[None, T]` leaves ambiguity about the intention whether the type may be extended in the future, i.e., `Union[None, T, U]`.

Furthermore, SSZ Union types are currently not used in any final Ethereum specification and do not have a finalized design themselves. If the only use case is a workaround for lack of `Optional[T]`, the simpler `Optional[T]` type is sufficient, and support for general unions could be delayed until really needed. Note that the design of `Optional[T]` could be used as basis for a more general `Union`.

### Why not `List[T, 1]`?

The serialization is less compact for variable-length `T`, due to the extra offset table at the beginning of the list to indicate the list length.

## Backwards Compatibility

`Union[None, T]` and `List[T, 1]` workarounds are not used at this time to represent `Optional[T]`.

## Test Cases

See [EIP assets](/EIPs/assets/eip-6475/tests.py).

## Reference Implementation

- **Python:** See [EIP assets](/EIPs/assets/eip-6475/optional.py), based on `protolambda/remerkleable`
- **Nim:** `status-im/nim-ssz-serialization`

## Security Considerations

None

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 09 Feb 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6475</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6475</guid>
      </item>
    
      <item>
        <title>Signature Validation for Predeploy Contracts</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6492-signature-validation-for-pre-deploy-contracts/12903</comments>
        
        <description>## Abstract

Contracts can sign verifiable messages via [ERC-1271](/EIPs/EIPS/eip-1271).

However, if the contract is not deployed yet, [ERC-1271](/EIPs/EIPS/eip-1271) verification is impossible, as you can&apos;t call the `isValidSignature` function on said contract.

We propose a standard way for any contract or off-chain actor to verify whether a signature on behalf of a given counterfactual contract (that is not deployed yet) is valid. This standard way extends [ERC-1271](/EIPs/EIPS/eip-1271).

## Motivation

With the rising popularity of account abstraction, we often find that the best user experience for contract wallets is to defer contract deployment until the first user transaction, therefore not burdening the user with an additional deploy step before they can use their account. However, at the same time, many dApps expect signatures, not only for interactions, but also just for logging in.

As such, contract wallets have been limited in their ability to sign messages before their de-facto deployment, which is often done on the first transaction.

Furthermore, not being able to sign messages from counterfactual contracts has always been a limitation of [ERC-1271](/EIPs/EIPS/eip-1271).

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

The words &quot;validation&quot; and &quot;verification&quot; are used interchangeably.

Quoting [ERC-1271](/EIPs/EIPS/eip-1271),
&gt; `isValidSignature` can call arbitrary methods to validate a given signature, which could be context dependent (e.g. time based or state based), EOA dependent (e.g. signers authorization level within smart wallet), signature scheme Dependent (e.g. ECDSA, multisig, BLS), etc. 
&gt;
&gt; This function should be implemented by contracts which desire to sign messages (e.g. smart contract wallets, DAOs, multisignature wallets, etc.) Applications wanting to support contract signatures should call this method if the signer is a contract.


We use the same `isValidSignature` function, but we add a new wrapper signature format, that signing contracts MAY use before they&apos;re deployed, in order to allow support for verification.

The signature verifier MUST perform a contract deployment before attempting to call `isValidSignature` if the wrapper signature format is detected.

The wrapper format is detected by checking if the signature ends in `magicBytes`, which MUST be defined as `0x6492649264926492649264926492649264926492649264926492649264926492`.

It is RECOMMENDED to use this ERC with CREATE2 contracts, as their deploy address is always predictable.

### Signer side

The signing contract will normally be a contract wallet, but it could be any contract that implements [ERC-1271](/EIPs/EIPS/eip-1271) and is deployed counterfactually.

- If the contract is deployed, produce a normal [ERC-1271](/EIPs/EIPS/eip-1271) signature
- If the contract is not deployed yet, wrap the signature as follows: `concat(abi.encode((create2Factory, factoryCalldata, originalERC1271Signature), (address, bytes, bytes)), magicBytes)`
- If the contract is deployed but not ready to verify using [ERC-1271](/EIPs/EIPS/eip-1271), wrap the signature as follows: `concat(abi.encode((prepareTo, prepareData, originalERC1271Signature), (address, bytes, bytes)), magicBytes)`; `prepareTo` and `prepareData` must contain the necessary transaction that will make the contract ready to verify using [ERC-1271](/EIPs/EIPS/eip-1271) (e.g. a call to `migrate` or `update`)

Note that we&apos;re passing `factoryCalldata` instead of `salt` and `bytecode`. We do this in order to make verification compliant with any factory interface. We do not need to calculate the address based on  `create2Factory`/`salt`/`bytecode`, because [ERC-1271](/EIPs/EIPS/eip-1271) verification presumes we already know the account address we&apos;re verifying the signature for.

### Verifier side

Full signature verification MUST be performed in the following order:

- check if the signature ends with magic bytes, in which case do an `eth_call` to a multicall contract that will call the factory first with the `factoryCalldata` and deploy the contract if it isn&apos;t already deployed; Then, call `contract.isValidSignature` as usual with the unwrapped signature
- check if there&apos;s contract code at the address. If so perform [ERC-1271](/EIPs/EIPS/eip-1271) verification as usual by invoking `isValidSignature`
- if the [ERC-1271](/EIPs/EIPS/eip-1271) verification fails, and the deploy call to the `factory` was skipped due to the wallet already having code, execute the `factoryCalldata` transaction and try `isValidSignature` again
- if there is no contract code at the address, try `ecrecover` verification

## Rationale

We believe that wrapping the signature in a way that allows to pass the deploy data is the only clean way to implement this, as it&apos;s completely contract agnostic, but also easy to verify.

The wrapper format ends in `magicBytes`, which ends with a `0x92`, which makes it is impossible for it to collide with a valid `ecrecover` signature if packed in the `r,s,v` format, as `0x92` is not a valid value for `v`. To avoid collisions with normal [ERC-1271](/EIPs/EIPS/eip-1271), `magicBytes` itself is also quite long (`bytes32`).

The order to ensure correct verification is based on the following rules:

- checking for `magicBytes` MUST happen before the usual [ERC-1271](/EIPs/EIPS/eip-1271) check in order to allow counterfactual signatures to be valid even after contract deployment
- checking for `magicBytes` MUST happen before `ecrecover` in order to avoid trying to verify a counterfactual contract signature via `ecrecover` if such is clearly identifiable
- checking `ecrecover` MUST NOT happen before [ERC-1271](/EIPs/EIPS/eip-1271) verification, because a contract may use a signature format that also happens to be a valid `ecrecover` signature for an EOA with a different address. One such example is a contract that&apos;s a wallet controlled by said EOA.

We can&apos;t determine the reason why a signature was encoded with a &quot;deploy prefix&quot; when the corresponding wallet already has code. It could be due to the signature being created before the contract was deployed, or it could be because the contract was deployed but not ready to verify signatures yet. As such, we need to try both options.

## Backwards Compatibility

This ERC is backward compatible with previous work on signature validation, including [ERC-1271](/EIPs/EIPS/eip-1271) and allows for easy verification of all signature types, including EOA signatures and typed data ([EIP-712](/EIPs/EIPS/eip-712)). 

### Using [ERC-6492](/EIPs/EIPS/eip-6492) for regular contract signatures

The wrapper format described in this ERC can be used for all contract signatures, instead of plain [ERC-1271](/EIPs/EIPS/eip-1271). This provides several advantages:

- allows quick recognition of the signature type: thanks to the magic bytes, you can immediately know whether the signature is a contract signature without checking the blockchain
- allows recovery of address: you can get the address only from the signature using `create2Factory` and `factoryCalldata`, just like `ecrecover`

## Reference Implementation

Below you can find an implementation of a universal verification contract that can be used both on-chain and off-chain, intended to be deployed as a singleton. It can validate signatures signed with this ERC, [ERC-1271](/EIPs/EIPS/eip-1271) and traditional `ecrecover`. [EIP-712](/EIPs/EIPS/eip-712) is also supported by extension, as we validate the final digest (`_hash`).

```solidity
// As per ERC-1271
interface IERC1271Wallet {
  function isValidSignature(bytes32 hash, bytes calldata signature) external view returns (bytes4 magicValue);
}

error ERC1271Revert(bytes error);
error ERC6492DeployFailed(bytes error);

contract UniversalSigValidator {
  bytes32 private constant ERC6492_DETECTION_SUFFIX = 0x6492649264926492649264926492649264926492649264926492649264926492;
  bytes4 private constant ERC1271_SUCCESS = 0x1626ba7e;

  function isValidSigImpl(
    address _signer,
    bytes32 _hash,
    bytes calldata _signature,
    bool allowSideEffects,
    bool tryPrepare
  ) public returns (bool) {
    uint contractCodeLen = address(_signer).code.length;
    bytes memory sigToValidate;
    // The order here is strictly defined in https://eips.ethereum.org/EIPS/eip-6492
    // - ERC-6492 suffix check and verification first, while being permissive in case the contract is already deployed; if the contract is deployed we will check the sig against the deployed version, this allows 6492 signatures to still be validated while taking into account potential key rotation
    // - ERC-1271 verification if there&apos;s contract code
    // - finally, ecrecover
    bool isCounterfactual = bytes32(_signature[_signature.length-32:_signature.length]) == ERC6492_DETECTION_SUFFIX;
    if (isCounterfactual) {
      address create2Factory;
      bytes memory factoryCalldata;
      (create2Factory, factoryCalldata, sigToValidate) = abi.decode(_signature[0:_signature.length-32], (address, bytes, bytes));

      if (contractCodeLen == 0 || tryPrepare) {
        (bool success, bytes memory err) = create2Factory.call(factoryCalldata);
        if (!success) revert ERC6492DeployFailed(err);
      }
    } else {
      sigToValidate = _signature;
    }

    // Try ERC-1271 verification
    if (isCounterfactual || contractCodeLen &gt; 0) {
      try IERC1271Wallet(_signer).isValidSignature(_hash, sigToValidate) returns (bytes4 magicValue) {
        bool isValid = magicValue == ERC1271_SUCCESS;

        // retry, but this time assume the prefix is a prepare call
        if (!isValid &amp;&amp; !tryPrepare &amp;&amp; contractCodeLen &gt; 0) {
          return isValidSigImpl(_signer, _hash, _signature, allowSideEffects, true);
        }

        if (contractCodeLen == 0 &amp;&amp; isCounterfactual &amp;&amp; !allowSideEffects) {
          // if the call had side effects we need to return the
          // result using a `revert` (to undo the state changes)
          assembly {
           mstore(0, isValid)
           revert(31, 1)
          }
        }

        return isValid;
      } catch (bytes memory err) {
        // retry, but this time assume the prefix is a prepare call
        if (!tryPrepare &amp;&amp; contractCodeLen &gt; 0) {
          return isValidSigImpl(_signer, _hash, _signature, allowSideEffects, true);
        }

        revert ERC1271Revert(err);
      }
    }

    // ecrecover verification
    require(_signature.length == 65, &apos;SignatureValidator#recoverSigner: invalid signature length&apos;);
    bytes32 r = bytes32(_signature[0:32]);
    bytes32 s = bytes32(_signature[32:64]);
    uint8 v = uint8(_signature[64]);
    if (v != 27 &amp;&amp; v != 28) {
      revert(&apos;SignatureValidator: invalid signature v value&apos;);
    }
    return ecrecover(_hash, v, r, s) == _signer;
  }

  function isValidSigWithSideEffects(address _signer, bytes32 _hash, bytes calldata _signature)
    external returns (bool)
  {
    return this.isValidSigImpl(_signer, _hash, _signature, true, false);
  }

  function isValidSig(address _signer, bytes32 _hash, bytes calldata _signature)
    external returns (bool)
  {
    try this.isValidSigImpl(_signer, _hash, _signature, false, false) returns (bool isValid) { return isValid; }
    catch (bytes memory error) {
      // in order to avoid side effects from the contract getting deployed, the entire call will revert with a single byte result
      uint len = error.length;
      if (len == 1) return error[0] == 0x01;
      // all other errors are simply forwarded, but in custom formats so that nothing else can revert with a single byte in the call
      else assembly { revert(error, len) }
    }
  }
}

// this is a helper so we can perform validation in a single eth_call without pre-deploying a singleton
contract ValidateSigOffchain {
  constructor (address _signer, bytes32 _hash, bytes memory _signature) {
    UniversalSigValidator validator = new UniversalSigValidator();
    bool isValidSig = validator.isValidSigWithSideEffects(_signer, _hash, _signature);
    assembly {
      mstore(0, isValidSig)
      return(31, 1)
    }
  }
}
```

### On-chain validation

For on-chain validation, you could use two separate methods:

- `UniversalSigValidator.isValidSig(_signer, _hash, _signature)`: returns a bool of whether the signature is valid or not; this is reentrancy-safe
- `UniversalSigValidator.isValidSigWithSideEffects(_signer, _hash, _signature)`: this is equivalent to the former - it is not reentrancy-safe but it is more gas-efficient in certain cases

Both methods may revert if the underlying calls revert.

### Off-chain validation

The `ValidateSigOffchain` helper allows you to perform the universal validation in one `eth_call`, without any pre-deployed contracts.

Here&apos;s example of how to do this with the `ethers` library:

```javascript
const isValidSignature = &apos;0x01&apos; === await provider.call({
  data: ethers.utils.concat([
    validateSigOffchainBytecode,
    (new ethers.utils.AbiCoder()).encode([&apos;address&apos;, &apos;bytes32&apos;, &apos;bytes&apos;], [signer, hash, signature])
  ])
})
```

You may also use a library to perform the universal signature validation, such as Ambire&apos;s `signature-validator`.

## Security Considerations

The same considerations as [ERC-1271](/EIPs/EIPS/eip-1271) apply.

However, deploying a contract requires a `CALL` rather than a `STATICCALL`, which introduces reentrancy concerns. This is mitigated in the reference implementation by having the validation method always revert if there are side-effects, and capturing its actual result from the revert data. For use cases where reentrancy is not a concern, we have provided the `isValidSigWithSideEffects` method.

Furthermore, it is likely that this ERC will be more frequently used for off-chain validation, as in many cases, validating a signature on-chain presumes the wallet has been already deployed.

One out-of-scope security consideration worth mentioning is whether the contract is going to be set-up with the correct permissions at deploy time, in order to allow for meaningful signature verification. By design, this is up to the implementation, but it&apos;s worth noting that thanks to how CREATE2 works, changing the bytecode or contructor callcode in the signature will not allow you to escalate permissions as it will change the deploy address and therefore make verification fail.

It must be noted that contract accounts can dynamically change their methods of authentication. This issue is mitigated by design in this EIP - even when validating counterfactual signatures, if the contract is already deployed, we will still call it, checking against the current live version of the contract.

As per usual with signatures, replay protection should be implemented in most use cases. This proposal adds an extra dimension to this, because it may be possible to validate a signature that has been rendered invalid (by changing the authorized keys) on a different network as long as 1) the signature was valid at the time of deployment 2) the wallet can be deployed with the same factory address/bytecode on this different network.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 10 Feb 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6492</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6492</guid>
      </item>
    
      <item>
        <title>SSZ transaction signature scheme</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6493-ssz-transaction-signature-scheme/13050</comments>
        
        <description>## Abstract

This EIP defines a signature scheme for native [Simple Serialize (SSZ)](https://github.com/ethereum/consensus-specs/blob/b3e83f6691c61e5b35136000146015653b22ed38/ssz/simple-serialize.md) encoded transactions.

## Motivation

[EIP-6404](/EIPs/EIPS/eip-6404) introduces SSZ transactions by converting from RLP transactions. Defining a signature scheme for native SSZ transactions further reduces required conversions and unlocks the forward compatibility benefits of SSZ [`ProgressiveContainer`](/EIPs/EIPS/eip-7495).

## Specification

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

### Transaction signature scheme

Native SSZ transactions are based on the `TransactionPayload` defined in [EIP-6404](/EIPs/EIPS/eip-6404) and emit an [EIP-6466](/EIPs/EIPS/eip-6466) `Receipt`. To distinguish native SSZ transactions from those converted from RLP, native SSZ transactions do not contain the RLP `TransactionType` field in their `TransactionPayload`.

All native SSZ transactions follow a scheme based on [`hash_tree_root`](https://github.com/ethereum/consensus-specs/blob/b3e83f6691c61e5b35136000146015653b22ed38/ssz/simple-serialize.md#merkleization) to compute their signing hash (`sig_hash`). Likewise, native SSZ authorizations use such a scheme to derive their signing hash (`auth_hash`).

Additional information is mixed into `sig_hash` and `auth_hash` to uniquely identify the underlying specification and avoid hash collisions across different signature kinds. Vendor-defined networks MUST use a different `DomainType` for signing custom transaction or authorization types.

| Name | Value | Description |
| - | - | - |
| `DOMAIN_TX_SSZ` | `DomainType(&apos;0x01000008&apos;)` | [`DomainType`](https://github.com/ethereum/consensus-specs/blob/b3e83f6691c61e5b35136000146015653b22ed38/specs/phase0/beacon-chain.md#custom-types) for signing native SSZ transactions compatible with this EIP |
| `DOMAIN_AUTH_SSZ` | `DomainType(&apos;0x02000008&apos;)` | [`DomainType`](https://github.com/ethereum/consensus-specs/blob/b3e83f6691c61e5b35136000146015653b22ed38/specs/phase0/beacon-chain.md#custom-types) for signing native SSZ authorizations compatible with this EIP |

```python
class ExecutionSigningData(Container):
    object_root: Root
    domain_type: DomainType

def compute_ssz_sig_hash(payload: SszTransactionPayload) -&gt; Hash32:
    return Hash32(ExecutionSigningData(
        object_root=payload.hash_tree_root(),
        domain_type=DOMAIN_TX_SSZ,
    ).hash_tree_root())

def compute_ssz_auth_hash(payload: SszAuthorizationPayload) -&gt; Hash32:
    return Hash32(ExecutionSigningData(
        object_root=payload.hash_tree_root(),
        domain_type=DOMAIN_AUTH_SSZ,
    ).hash_tree_root())
```

### Native transactions

New [EIP-6404](/EIPs/EIPS/eip-7495) `TransactionPayload` definitions are introduced to represent native SSZ transactions:

- `BasicTransactionPayload` and `CreateTransactionPayload` share the functionality of [EIP-1559](/EIPs/EIPS/eip-1559#specification) fee market transactions
- `BlobTransactionPayload` shares the functionality of [EIP-4844](/EIPs/EIPS/eip-4844#parameters) blob transactions
- `SetCodeTransactionPayload` shares the functionality of [EIP-7702](/EIPs/EIPS/eip-7702#parameters) set code transactions; native SSZ types are introduced for authorizations

```python
class BasicTransactionPayload(
    ProgressiveContainer(active_fields=[0, 1, 1, 1, 1, 1, 1, 1, 1, 1])
):
    chain_id: ChainId
    nonce: uint64
    max_fees_per_gas: BasicFeesPerGas
    gas: GasAmount
    to: ExecutionAddress
    value: uint256
    input_: ProgressiveByteList
    access_list: ProgressiveList[AccessTuple]
    max_priority_fees_per_gas: BasicFeesPerGas

class CreateTransactionPayload(
    ProgressiveContainer(active_fields=[0, 1, 1, 1, 1, 0, 1, 1, 1, 1])
):
    chain_id: ChainId
    nonce: uint64
    max_fees_per_gas: BasicFeesPerGas
    gas: GasAmount
    value: uint256
    input_: ProgressiveByteList
    access_list: ProgressiveList[AccessTuple]
    max_priority_fees_per_gas: BasicFeesPerGas

class BlobTransactionPayload(
    ProgressiveContainer(active_fields=[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
):
    chain_id: ChainId
    nonce: uint64
    max_fees_per_gas: BlobFeesPerGas
    gas: GasAmount
    to: ExecutionAddress
    value: uint256
    input_: ProgressiveByteList
    access_list: ProgressiveList[AccessTuple]
    max_priority_fees_per_gas: BasicFeesPerGas
    blob_versioned_hashes: ProgressiveList[VersionedHash]

class ReplayableBasicAuthorizationPayload(ProgressiveContainer(active_fields=[0, 0, 1, 1])):
    address: ExecutionAddress
    nonce: uint64

class BasicAuthorizationPayload(ProgressiveContainer(active_fields=[0, 1, 1, 1])):
    chain_id: ChainId
    address: ExecutionAddress
    nonce: uint64

class SetCodeAuthorizationPayload(CompatibleUnion({
    0x01: RlpReplayableBasicAuthorizationPayload,
    0x02: RlpBasicAuthorizationPayload,

    # [New in EIP-6493]
    0x11: ReplayableBasicAuthorizationPayload,
    0x12: BasicAuthorizationPayload,
})):
    pass

class SetCodeAuthorization(Container):
    payload: SetCodeAuthorizationPayload
    signature: ExecutionSignature

class SetCodeTransactionPayload(
    ProgressiveContainer(active_fields=[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1])
):
    chain_id: ChainId
    nonce: uint64
    max_fees_per_gas: BasicFeesPerGas
    gas: GasAmount
    to: ExecutionAddress
    value: uint256
    input_: ProgressiveByteList
    access_list: ProgressiveList[AccessTuple]
    max_priority_fees_per_gas: BasicFeesPerGas
    authorization_list: ProgressiveList[SetCodeAuthorization]

SszTransactionPayload = (
    BasicTransactionPayload |
    CreateTransactionPayload |
    BlobTransactionPayload |
    SetCodeTransactionPayload
)

SszAuthorizationPayload = (
    ReplayableBasicAuthorizationPayload |
    BasicAuthorizationPayload
)
```

#### Transaction helpers

The helpers from [EIP-6404](/EIPs/EIPS/eip-6404) are updated to support native SSZ transactions.

```python
class TransactionPayload(CompatibleUnion({
    0x01: RlpLegacyReplayableBasicTransactionPayload,
    0x02: RlpLegacyReplayableCreateTransactionPayload,
    0x03: RlpLegacyBasicTransactionPayload,
    0x04: RlpLegacyCreateTransactionPayload,
    0x05: RlpAccessListBasicTransactionPayload,
    0x06: RlpAccessListCreateTransactionPayload,
    0x07: RlpBasicTransactionPayload,
    0x08: RlpCreateTransactionPayload,
    0x09: RlpBlobTransactionPayload,
    0x0a: RlpSetCodeTransactionPayload,

    # [New in EIP-6493]
    0x11: BasicTransactionPayload,
    0x12: CreateTransactionPayload,
    0x13: BlobTransactionPayload,
    0x14: SetCodeTransactionPayload,
})):
    pass
```

### JSON-RPC

| Name | Value | Description |
| - | - | - |
| `SSZ_TX_TYPE` | `TransactionType(0x1f)` | Endpoint specific SSZ object |

Certain JSON-RPC endpoints such as `eth_getTransactionByHash` indicate the corresponding [EIP-2718](/EIPs/EIPS/eip-2718) envelope type prefix in a `type` field.

When representing native SSZ transactions on such endpoints, `SSZ_TX_TYPE` SHOULD be indicated as their `type`. Omitting the `type` is NOT RECOMMENDED as certain client applications could confuse the omission with untyped `LegacyTransaction`.

### Unique transaction identifier

The unique RPC transaction identifier `tx_hash` for native SSZ transactions is defined to match the [EIP-6404](/EIPs/EIPS/eip-6404#unique-transaction-identifier) `tx_root` value.

## Rationale

The SSZ signature scheme reduces hashing overhead and ensures that `tx_hash` commitments are available on-chain. It also provides a flexible basis for future transaction functionality.

## Backwards Compatibility

The new transaction signature scheme is solely used for native SSZ transactions and is representable using a unique [EIP-2718](/EIPs/EIPS/eip-2718) envelope type prefix (`SSZ_TX_TYPE`) different from existing RLP transactions.

## Security Considerations

SSZ signatures MUST NOT collide with RLP transaction and message hashes.

As RLP messages are hashed using keccak256, and all SSZ objects are hashed using SHA256. These two hashing algorithms are both considered cryptographically secure and are based on fundamentally different approaches, minimizing the risk of hash collision between those two hashing algorithms.

Furthermore, RLP messages are hashed linearly across their serialization, while SSZ objects are hashed using a recursive Merkle tree. Having a different mechanism further reduces the risk of hash collisions.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 24 Feb 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6493</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6493</guid>
      </item>
    
      <item>
        <title>P2P Escrowed Governance Incentives</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/escrowed-and-private-bribes-for-generalized-dao-voting/12694</comments>
        
        <description>## Abstract

The following EIP defines the interface for a contract that facilitates the exchange of a governance-incentive for users to vote in a designated direction on a DAO-proposal while escrowing funds until the vote can be verified. 

## Motivation

While a ton of effort has gone into building bribe systems for DAOs like Curve, Frax, Convex, etc., not a lot of focus has been put on how bribes on other, more general DAO votes, may affect outcomes. Bribes are a lucrative market on many popular DAO’s, and it stands to reason that people are willing to accept them for voting on other proposals, especially if they have no personal stake in the outcome. There are however, problems with current systems:

1. Current bribe schemes for votes based on pro-rata distribution are economically inefficient and result in worse outcomes for voters. For systems like Votium or Hidden-Hand, If Alice votes on a proposal with the expectation of receiving $10 in bribes, they can just be backrun by a larger voter, diluting their share of the pool. It may no longer be economical to make the decision they did. Using an OTC mechanisms is more efficient because the amount is “locked in” when the bribe is made and the recipient has much more concrete assurances on which to base their decision. These protocols are also centralized, relying on a central authority to accept and redistribute rewards fairly. Whenever possible, centralization should be avoided.

2. The lack of an existing standard means that parties are relying entirely on trust in one-another to obey. Bob has to trust Alice to pay out and Alice has to trust Bob to vote. Even if the two of them were to use an escrow contract, it may have flaws like relying on a trusted third-party, or simply that it is outside the technical reach of both parties.

3. There are no mechanisms for creating transparency into the collusion of actors. Users colluding off-chain to sway the vote of a large token-holder creates opaque outcomes with no accountability since everything happens off-chain.

4. For actors that wish to solicit incentives for their vote, this may require either active management, or the doxxing of their identity/pseudonymous identifier. A user who wishes to negotiate would need to provide a way for incentivizers to contact them, engage in a negotiation process, write and deploy escrow contracts, vote, and then claim their reward. This is a lengthy and involved process that requires active management and communication. This creates a limit on who is able to solicit these incentives, and leads to the centralization of profit towards the few who can sustain this process at length.

5. Bribe Revenue as subsidies. As Vitalik wrote in a 2019 article, *On Collusion*, a potential solution would be a token that requires voters for a proposal to purchase the governance-token if the proposal-passes, subsidizing the cost of a bad decision for everyone else. If the revenue generated from these incentives is used (at least partly) to directly buy back those tokens by the treasury, then you get a similar outcome. The impact of a bad proposal being passed via-bribing is subsidized for everyone who didn&apos;t vote for it by having some value returned to token-holders. This not only makes malicious bribes more costly, as it has to offset the value accrued via buyback, but also means higher profits for recipients.

## Specification

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

The key words &quot;BRIBE&quot; and &quot;INCENTIVE&quot; are to be interpreted as the transfer of a digital-asset(s) from user A to user B in exchange for an assurance that user B will vote in a specific-direction, on a specific proposal, for a specified-DAO. If user B does not honor the arrangement, the digital-asset(s) will be returned to user A. 

The key words &quot;BRIBER&quot;, &quot;INCENTIVIZER&quot;, and &quot;SENDER&quot; shall refer to the user A offering monetary compensation to user B. &quot;RECIPIENT&quot;, &quot;VOTER&quot;, and &quot;INCENTIVIZEE&quot; herein refer to user B whom shall formally receive their compensation upon the termination of the agreement.

The key word &quot;VOTE&quot; shall be interpreted as the casting of a ballot in any kind of governance system which uses accounts as a form of permissions.

Contracts wishing to implement such a standard must implement the following interface

```solidity
interface IEscrowedGovIncentive {

  struct incentive {
    address incentiveToken;
    address incentivizer;
    address recipient;
    uint amount;
    uint256 proposalId;
    bytes32 direction; //the keccak256 of the vote direction
    uint96 deadline;
    uint96 timestamp;
    bool claimed;
  }

  event incentiveSent(address indexed incentivizer, address indexed token, uint256 indexed amount, address recipient, bytes data);

  event incentiveReclaimed(address incentivizer, address indexed recipient, address indexed token, uint256 indexed amount, bytes data);

  event modifiedClaimer(address recipient, address claimer, bool direction);

  event incentiveClaimed(address indexed incentivizer, address voter, bytes32 incentiveId, bytes proofData);

  event disputeInitiated(bytes32 indexed incentiveId, address indexed plaintiff, address indexed defendant);

  event disputeResolved(bytes32 indexed incentive, address indexed plaintiff, address indexed defendant, bool dismissed);


  //Core mechanism
  function incentivize(bytes32 incentiveId, bytes memory incentiveInfo) external payable;

  function claimIncentive(bytes32 incentiveId, bytes memory reveal, address payable recipient) external;
  
  function reclaimIncentive(bytes32 incentiveId, bytes memory reveal) external;
  
  function verifyVote(bytes32 incentive, bytes memory voteInfo) external view returns (bool isVerifiable, bytes proofData);

  function modifyClaimer(address claimer, bool designation) external;

  //Dispute Mechanism
  function beginDispute(bytes32 incentiveId, bytes memory disputeInfo) external payable;

  function resolveDispute(bytes32 incentiveId, bytes memory disputeResolutionInfo) external returns (bool isDismissed);

}
```

### Optional Implementation Details

Below are three potential implementation examples of the above system for different aspects.

#### *Complete Transparency*

In this version all information about the vote direction, the amount, and the recipient are public at all times. Information is passed as calldata in plaintext and stored/emitted as such.

#### *Opacity until Completion (OUC)*

In this model, the recipient, the direction, and the amount are kept secret until the incentive is claimed. In this model, the data is committed to, and an encrypted version is passed as calldata. This data can be encrypted with the recipient&apos;s public-key. It should be emitted as such which can then be decrypted off-chain by the recipient and used to make a determination on whether to oblige. In this model to ensure the privacy of transferring funds into escrow, the incentivizer could use methods such as deterministic-address-generation with the create2 opcode.

Upon the claiming of the bribe the recipient would simply open the commitment, which would then be checked on-chain and funds released.

#### *Compatibility with Off-Chain Voting*

Many DAO&apos;s operate off-chain, typically through voting platforms like snapshot. This system does allow for such compatibility using known signature data. Consider the following example

1. User A commits an incentive to user B to vote on snapshot. User B votes.
2. Once the deadline has passed, a challenge window is initiated. The incentivizer has a predetermined window to demonstrate that the bribe was not honored. This can be done by simply passing to the contract a signature signed by User B voting in the opposite direction of the bribe. If the signature can be verified, then the arrangement was not honored and funds can be safely released back to user A. 
3. If the challenge window concludes without A being able produce proof of noncompliance, then B is able to claim the reward. If B voted inline with the incentive, A will not be able to produce a valid signature of noncompliance. The challenge window with A demonstrating noncompliance is necesarry, because otherwise B could simply sign a message and not broadcast it, allowing them to claim the reward without voting.
4. In the event that B does NOT vote at all, then a special challenge period may be entered. Since B did not vote at all, A would not be able to produce the requisite proof, but B would still be able to claim the reward without complying. In this event, user A would have the option to enter a special dispute period. The details of this are determined by the contract implementation. This can include resolution by a trusted third-party, or other methods. An example includes using a merkle-root to show that B was not in the list of voters at the conclusion of the proposal. It should be considered making A present a  


### Methods

While this EIP defines a struct *incentive*, `bytes memory` should be used whenever possible. Given as each DAO will have its own implementation details, interfaces, and signature data, this should then be decoded using `abi.decode()` and interpreted according to those known specifications.

#### `incentivize`

The function where an incentivizer should commit to the details of their incentive. The commitment value can be calculated off-chain or calculated on-chain in a full transparency system. The function should take the input data from `incentiveInfo` and create store a new `incentive` object in the mapping incentives. If OUC is enabled, then only incentivizer and timestamp information need be public, everything else should be left as zero.

Function should account for fees taken from user at deposit. If fees are present, then `incentivize` should take them up front. This is to ensure that the amount quoted to a recipient is *at least* as much as they would receive.

MUST emit the `incentiveSent` event

```yaml
- name: incentivize
  type: function
  stateMutability: payable

  inputs:
    - name: incentiveId
      type: bytes32
    - name: incentiveInfo
      type: bytes memory
```

#### `claimIncentive`

Should be used by the intended recipient of a previously-committed incentive. 

MUST revert if `msg.sender != original_recipient` and `!allowedClaimer[original_recipient][msg.sender]`

MUST revert if the data provided in `reveal` does not match the data committed to by `incentiveId`.

MUST revert if all funds committed to cannot be properly sent to `recipient` at conclusion of the function. If fees are present, then additional funds should be present at deposit to ensure that *at least* the amount committed to is sent to the user. This however, **DOES NOT** apply to any fees which may be taken by an approved claimer.

Ex: Alice commits to Bob an incentive 100 USDC. Bob has approved Eve to claim on his behalf in exchange for 5% of net value. Function should check that amount paid to Bob and Eve is `&gt;=100 USDC` but **NOT** that Bob himself receives `&gt;=100 USDC` 

MUST revert if the voting direction of the original recipient cannot be verified as being in line with the intended direction of `incentiveId`, and no dispute resolution process is defined.

MUST revert if the specified incentive has a pending dispute.

If verification is successful then funds should be sent to `recipient`.

MUST emit the `incentiveClaimed` event if function does not revert.

```yaml
- name: claimIncentive
  type: function
  stateMutability: nonpayable

  inputs:
    - name: incentiveId
      type: bytes32
    - name: reveal
      type: bytes memory
    - name: recipient
      type: address payable
```

#### `reclaimIncentive`

  Function that should be invoked by the initial sender of `incentiveId` in the event that `recipient` did not vote in accordance with the incentive&apos;s `direction`. Function should return the funds initially committed to by `incentiveId` to `incentivizer`

  MUST revert if all of the funds committed to cannot be returned to the incentivizer. 

  MUST revert if the function cannot successfully verify the validity of `msg.sender` claim of non-compliance.

  MUST emit the event `incentiveReclaimed` if verification is successful. If proof can be retrieved on-chain, then the `proof` parameter may be left empty.

  MUST revert if the specified incentive has a pending dispute.

  If fees are taken, then all funds including any prepaid fees committed to should be returned to the `incentivizer`.
  
  ```yaml
- name: reclaimIncentive
    type: function
    stateMutability: nonpayable
  
    inputs:
      - name: incentiveId
        type: bytes32
      - name: reveal
        type: bytes memory
  ```

#### `verifyVote`

 `function verifyVote(bytes32 incentive, bytes memory voteInfo) public view returns (bool isVerifiable);`

 Function used to determine if the voter for `incentive` should receive the incentive originally committed to. 

 Functions may use whatever scheme they like to determine this information. Necessary data should be encoded and passed through `voteInfo`. 

 MUST return `false` if `voteInfo` indicates that `recipient` did not vote in the direction committed to by `incentive`, and true otherwise.

```yaml
- name: verifyVote
  type: function
  stateMutability: view

  inputs:
    - name: incentiveId
      type: bytes32
    - name: voteInfo
      type: bytes memory

  outputs: 
    - name: isVerified
      type: bool
    - name: proofData
      type: bytes memory
```

#### `modifyClaimer`

Function changing the designation of an address as being approved to claim a bribe on behalf of another user. Only an approved claimer should be able to claim the incentive on behalf of the user which approved them. 

```yaml
- name: modifyClaimer
  type: function
  stateMutability: nonpayable

  inputs:
    - name: claimer
      type: address
    - name: designation
      type: bool

```

#### `beginDispute`

A function used to initiate the resolution of an incentive through an optional dispute-mechanism. At the discretion of the developers, and based on the specifics of the vote-verification mechanism in which a voting direction cannot be conclusively decided, the developers may opt for an additional mechanism to resolve dispute between parties. This may include third-party intervention, additional cryptographic evidence, etc. needed to determine whether to pay out rewards to `recipient` or return them to the `incentivizer`

Potential Examples requiring additional dispute mechanisms:

  1. Requiring a trusted third-party to resolve disputes.
  2. The recipient did not vote in an off-chain proposal, and additional off-chain information is needed to confirm.
  3. An additional unlocking mechanism is required to access previously deposited funds.


Dispute mechanisms may optionally choose to require a bond from the filer to prevent frivolous filings, to be returned to them on successful resolution of the dispute in their favor.

Must emit the event `disputeInitiated`

Once a dispute for a given incentive has been filed, neither the `incentivizer` nor `recipient` should be able to withdraw funds until completed.


```yaml
- name: beginDispute
  type: function
  stateMutability: payable

  inputs:
    - name: incentiveId
      type: bytes32
    - name: disputeInfo
      type: bytes memory
```

#### `resolveDispute`

A function which is used to resolve pending disputes over `incentiveId`. The exact mechanism shall be specified by the developers.

MUST return false, and be *&quot;dismissed&quot;*, if the mechanisms resolves the dispute in favor of the defendant `(recipient)`, by showing they did honor the incentive of `incentiveId`. If the dispute is *&quot;confirmed&quot;*, then the function should return true. 

MUST transfer funds committed to by `incentivizer` to `recipient` if dispute is `dismissed` and return `funds + fee + bond` to the `plaintiff`. If dismissed, the distribution of the bond shall be at the discretion of the developers. This may including burning, awarding to the defendant, or donating to a community treasury.

MUST emit the event `disputeResolved` on successful resolution.

```yaml
- name: resolveDispute
  type: function
  stateMutability: nonPayable

  inputs:
    - name: incentiveId
      type: bytes32
    - name: disputeResolutionInfo
      type: bytes memory
  
  outputs: 
    - name isDismissed
      type: bool
```

### Events

#### `incentiveSent`

`incentivizer` has bribed `recipient` `amount` of `token` for some information. 

If system is private then recipient, amount, and `token` may be left as zero.

```yaml
- name: incentiveSent
  type: event

  inputs: 
    - name incentivizer
      indexed: true
      type: address
    - name: token
      indexed: true
      type: address
    - name: amount
      indexed: true
      type: uint256
    - name: recipient
      indexed: true
      type: address
```


#### `incentiveClaimed`

  `recipient` claimed an incentive `amount` of `token` and any other data relevant.
  
```yaml
- name: incentiveClaimed
  - type: event

  inputs:
    - name: recipient
      indexed: true
      type: address
    - name: token
      indexed: true
      type: address
    - name: amount
      indexed: true
      type: uint256
    - name: data
      indexed: false
      type: bytes
```

#### `modifiedClaimer`

  A new `claimer` was either whitelisted by `recipient` or blacklisted.

```yaml
- name: modifiedClaimer
  type: event

  inputs:
    - name: recipient
      indexed: false
      type: address
    - name: claimer
      indexed: false
      type: address
    - name: direction
      indexed: false
      type: bool
```

#### `incentiveReclaimed`

  An `incentivizer` is reclaiming `incentiveId`, and outing the noncompliance of `voter`

```yaml
- name: incentiveReclaimed
  type: event

  inputs: 
    - name: incentivizer
      indexed: true
      type: address
    - name: voter
      indexed: true
      type: address
    - name: incentiveId
      indexed: false
      type: bytes32
    - name: proofData
      indexed: false
      type: bytes
```

#### `disputeInitiated`

  `incentivizer` has initiated a dispute with `plaintiff` over `incentiveId`

```yaml
- name: disputeInitiated
  type: event

  inputs: 
    - name: incentiveId
      indexed: true
      type: bytes32
    - name: plaintiff
      indexed: true
      type: address
    - name: defendant
      indexed: true
      type: address
```

#### `disputeResolved`

  The dispute over `incentiveId` has been resolved, either `dismissed` in favor of `defendant` or resolved in favor of the `plaintiff`

```yaml
- name: disputeResolved
  type: event

  inputs:
    - name: incentiveId
      indexed: false
      type: bytes32
    - name: plaintiff
      indexed: true
      type: address
    - name: defendant
      indexed: true
      type: address
    - name: dismissed
      indexed: true
      type: bool
      
```

## Rationale

This design was motivated by a few factors:

1. The issue of offering incentives for votes is an inevitability. There is no mechanism that can prevent users from colluding off-chain to vote a certain direction, and with enough obfuscation, can be completely hidden from the community&apos;s view. The solution is therefore to realign the incentives of these actors in a way that both creates transparency, while allowing for the decentralization of bribe-revenue. Flashbots is a relevant example. Since MEV could not be prevented, the solution was to make it more fairly distributed by incentivizing miners to use Flashbots-Geth with profits. Using an OTC market structure would have the same effect, allowing anyone to reap the benefits of a potential incentive while also creating a more efficient marketplace. 

2. Injecting transparency about whom is bribing whom for what increases both fairness and profitability. This makes it possible for the community to organize around potential solutions. Ex: Alice pays Bob $10 for his 1k votes in the DAO. This is now known on-chain and next time someone who cares about the outcome can offer Bob $11 for the votes. This maximizes profit to the recipient.

**Implementations should operate similar to the following example:**

1. Alice wants to give bob $10 to vote YES on DAO proposal #420. She wants an assurance he will do it and gets the money back if he doesn’t

2. It should work as an escrow service for both on-chain and snapshot based voting, releasing funds only after the vote has concluded, and it can be verified the recipient voted in line with the vote. It should be done without requiring a trusted third-party to escrow and release the funds themselves.

3. This EIP makes no discernment about the nature in which this information is relayed to the recipient. Implementation details are at the discretion of the protocol. This includes the optional decisions to enable privacy for both the recipient and the amount. Information on how this can be implemented is below. Once the vote has occurred, then the contents of the bribe can be claimed, pending verification. This verification should satisfy both soundness and completeness, that only after the user can show they did vote in line with the incentive do they receive the funds, and that such proof cannot be forged or misleading in any way.


**Factors to consider**

1. To remedy the problem of diluted rewards, the system uses a simple hash-based commitment scheme. When an incentive is sent, its data is committed to, and revealed when withdrawn.

2. Once a bribe is committed to, it cannot be withdrawn until after the voting period for the proposal has concluded. This is to ensure the legitimacy of the escrow, so that user A cannot withdraw the bribe after B has voted, but before they can claim the reward.


### Potential Ethical Issues

Potential ethical issues have been raised about the prospect of potentially encouraging users to accept monetary payment for their vote. This is the wrong frame of reference. The question is not whether it is ethical to encourage users to send/solicit, but rather the consequences of doing nothing. Returning to the flashbots example, the question is not whether MEV is ethical, but repercussions of allowing it to flourish without pushback. 

If nothing is done, the following outcomes are possible:

1. Flywheel Effect - Only dedicated and financially endowed holders will solicit incentives with impunity. This centralization of profit allows them to purchase more voting-rights, increasing power and so on until they have accumulated a critical mass, exerting potentially harmful influence over operations. This can range anywhere from minor operational decisions, to votes over treasury resolution. 

2. Lack of transparency - Decisionmaking will occur behind closed doors as the true intentions of voters is unclear, and votes that should pass may fail, or vice-versa. The will of the community will not be honored.

## Backwards Compatibility

No backward compatibility issues found.

## Security Considerations

This standard is intended to work with existing governance systems. Any potential issue with existing governance may represent a potential attack on this as well. This includes voting-weight manipulation, vote forgery, verification discrepancies etc. All systems in which this EIP is integrated with should be properly audited for maximum security, as any issues may result in improper distribution of these governance incentives.

Potential implementations of this system may rely on complex cryptographic operations as well. This may include proper implementation of digital-signatures to prevent replay attacks, or correctness requirements of SNARK proofs. These features may be **non-trivial** and thus require special care to ensure they are implemented and configured securely, otherwise features like confidentiality may be violated. 


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 15 Feb 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6506</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6506</guid>
      </item>
    
      <item>
        <title>Stealth Meta-Address Registry</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/stealth-meta-address-registry/12888</comments>
        
        <description>## Abstract

This specification defines a standardized way of storing and retrieving an entity&apos;s stealth meta-address, by extending [ERC-5564](/EIPs/EIPS/eip-5564). An entity may register their stealth meta-address directly. A third party can also register on behalf of an entity using a valid [EIP-712](/EIPs/EIPS/eip-712) or [EIP-1271](/EIPs/EIPS/eip-1271) signature. Once registered, the stealth meta-address for the entity can be retrieved by any smart contract or user. One can use the stealth meta-address with `generateStealthAddress` specified in [ERC-5564](/EIPs/EIPS/eip-5564) to send assets to the generated stealth address without revealing the entity&apos;s address.

## Motivation

The standardization of stealth address generation holds the potential to greatly enhance the privacy capabilities of Ethereum by enabling the recipient of a transfer to remain anonymous when receiving an asset. By introducing a central smart contract for users to store their stealth meta-addresses, EOAs and contracts can programmatically engage in stealth interactions using a variety of stealth address schemes.

## Specification

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.

This contract defines an `ERC6538Registry` that stores the stealth meta-address for entities. These entities may be identified by an address, ENS name, or other identifier. This MUST be a singleton contract, with one instance per chain.

The contract is specified below. A one byte integer is used to identify the stealth address scheme. This integer is used to differentiate between different stealth address schemes. This ERC outlines schemeId `1` as the SECP256k1 curve cryptographic scheme with view tags, as specified in [ERC-5564](/EIPs/EIPS/eip-5564).

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity 0.8.23;

/// @notice `ERC6538Registry` contract to map accounts to their stealth meta-address. See
/// [ERC-6538](https://eips.ethereum.org/EIPS/eip-6538) to learn more.
contract ERC6538Registry {
  /// @notice Emitted when an invalid signature is provided to `registerKeysOnBehalf`.
  error ERC6538Registry__InvalidSignature();

  /// @notice Next nonce expected from `user` to use when signing for `registerKeysOnBehalf`.
  /// @dev `registrant` may be a standard 160-bit address or any other identifier.
  /// @dev `schemeId` is an integer identifier for the stealth address scheme.
  mapping(address registrant =&gt; mapping(uint256 schemeId =&gt; bytes)) public stealthMetaAddressOf;

  /// @notice A nonce used to ensure a signature can only be used once.
  /// @dev `registrant` is the user address.
  /// @dev `nonce` will be incremented after each valid `registerKeysOnBehalf` call.
  mapping(address registrant =&gt; uint256) public nonceOf;

  /// @notice The EIP-712 type hash used in `registerKeysOnBehalf`.
  bytes32 public constant ERC6538REGISTRY_ENTRY_TYPE_HASH =
    keccak256(&quot;Erc6538RegistryEntry(uint256 schemeId,bytes stealthMetaAddress,uint256 nonce)&quot;);

  /// @notice The chain ID where this contract is initially deployed.
  uint256 internal immutable INITIAL_CHAIN_ID;

  /// @notice The domain separator used in this contract.
  bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;

  /// @notice Emitted when a registrant updates their stealth meta-address.
  /// @param registrant The account that registered the stealth meta-address.
  /// @param schemeId Identifier corresponding to the applied stealth address scheme, e.g. 1 for
  /// secp256k1, as specified in ERC-5564.
  /// @param stealthMetaAddress The stealth meta-address.
  /// [ERC-5564](https://eips.ethereum.org/EIPS/eip-5564) bases the format for stealth
  /// meta-addresses on [ERC-3770](https://eips.ethereum.org/EIPS/eip-3770) and specifies them as:
  ///   st:&lt;shortName&gt;:0x&lt;spendingPubKey&gt;:&lt;viewingPubKey&gt;
  /// The chain (`shortName`) is implicit based on the chain the `ERC6538Registry` is deployed on,
  /// therefore this `stealthMetaAddress` is just the compressed `spendingPubKey` and
  /// `viewingPubKey` concatenated.
  event StealthMetaAddressSet(
    address indexed registrant, uint256 indexed schemeId, bytes stealthMetaAddress
  );

  /// @notice Emitted when a registrant increments their nonce.
  /// @param registrant The account that incremented the nonce.
  /// @param newNonce The new nonce value.
  event NonceIncremented(address indexed registrant, uint256 newNonce);

  constructor() {
    INITIAL_CHAIN_ID = block.chainid;
    INITIAL_DOMAIN_SEPARATOR = _computeDomainSeparator();
  }

  /// @notice Sets the caller&apos;s stealth meta-address for the given scheme ID.
  /// @param schemeId Identifier corresponding to the applied stealth address scheme, e.g. 1 for
  /// secp256k1, as specified in ERC-5564.
  /// @param stealthMetaAddress The stealth meta-address to register.
  function registerKeys(uint256 schemeId, bytes calldata stealthMetaAddress) external {
    stealthMetaAddressOf[msg.sender][schemeId] = stealthMetaAddress;
    emit StealthMetaAddressSet(msg.sender, schemeId, stealthMetaAddress);
  }

  /// @notice Sets the `registrant`&apos;s stealth meta-address for the given scheme ID.
  /// @param registrant Address of the registrant.
  /// @param schemeId Identifier corresponding to the applied stealth address scheme, e.g. 1 for
  /// secp256k1, as specified in ERC-5564.
  /// @param signature A signature from the `registrant` authorizing the registration.
  /// @param stealthMetaAddress The stealth meta-address to register.
  /// @dev Supports both EOA signatures and EIP-1271 signatures.
  /// @dev Reverts if the signature is invalid.
  function registerKeysOnBehalf(
    address registrant,
    uint256 schemeId,
    bytes memory signature,
    bytes calldata stealthMetaAddress
  ) external {
    bytes32 dataHash;
    address recoveredAddress;

    unchecked {
      dataHash = keccak256(
        abi.encodePacked(
          &quot;\x19\x01&quot;,
          DOMAIN_SEPARATOR(),
          keccak256(
            abi.encode(
              ERC6538REGISTRY_ENTRY_TYPE_HASH,
              schemeId,
              keccak256(stealthMetaAddress),
              nonceOf[registrant]++
            )
          )
        )
      );
    }

    if (signature.length == 65) {
      bytes32 r;
      bytes32 s;
      uint8 v;
      assembly (&quot;memory-safe&quot;) {
        r := mload(add(signature, 0x20))
        s := mload(add(signature, 0x40))
        v := byte(0, mload(add(signature, 0x60)))
      }
      recoveredAddress = ecrecover(dataHash, v, r, s);
    }

    if (
      (
        (recoveredAddress == address(0) || recoveredAddress != registrant)
          &amp;&amp; (
            IERC1271(registrant).isValidSignature(dataHash, signature)
              != IERC1271.isValidSignature.selector
          )
      )
    ) revert ERC6538Registry__InvalidSignature();

    stealthMetaAddressOf[registrant][schemeId] = stealthMetaAddress;
    emit StealthMetaAddressSet(registrant, schemeId, stealthMetaAddress);
  }

  /// @notice Increments the nonce of the sender to invalidate existing signatures.
  function incrementNonce() external {
    unchecked {
      nonceOf[msg.sender]++;
    }
    emit NonceIncremented(msg.sender, nonceOf[msg.sender]);
  }

  /// @notice Returns the domain separator used in this contract.
  /// @dev The domain separator is re-computed if there&apos;s a chain fork.
  function DOMAIN_SEPARATOR() public view returns (bytes32) {
    return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : _computeDomainSeparator();
  }

  /// @notice Computes the domain separator for this contract.
  function _computeDomainSeparator() internal view returns (bytes32) {
    return keccak256(
      abi.encode(
        keccak256(
          &quot;EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)&quot;
        ),
        keccak256(&quot;ERC6538Registry&quot;),
        keccak256(&quot;1.0&quot;),
        block.chainid,
        address(this)
      )
    );
  }
}

/// @notice Interface of the ERC1271 standard signature validation method for contracts as defined
/// in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
interface IERC1271 {
  /// @notice Should return whether the signature provided is valid for the provided data
  /// @param hash Hash of the data to be signed
  /// @param signature Signature byte array associated with _data
  function isValidSignature(bytes32 hash, bytes memory signature)
    external
    view
    returns (bytes4 magicValue);
}

```

The interface for this contract is defined below:

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity 0.8.23;

/// @dev Interface for calling the `ERC6538Registry` contract to map accounts to their stealth
/// meta-address. See [ERC-6538](https://eips.ethereum.org/EIPS/eip-6538) to learn more.
interface IERC6538Registry {
  /// @notice Emitted when an invalid signature is provided to `registerKeysOnBehalf`.
  error ERC6538Registry__InvalidSignature();

  /// @dev Emitted when a registrant updates their stealth meta-address.
  /// @param registrant The account that registered the stealth meta-address.
  /// @param schemeId Identifier corresponding to the applied stealth address scheme, e.g. 1 for
  /// secp256k1, as specified in ERC-5564.
  /// @param stealthMetaAddress The stealth meta-address.
  /// [ERC-5564](https://eips.ethereum.org/EIPS/eip-5564) bases the format for stealth
  /// meta-addresses on [ERC-3770](https://eips.ethereum.org/EIPS/eip-3770) and specifies them as:
  ///   st:&lt;shortName&gt;:0x&lt;spendingPubKey&gt;:&lt;viewingPubKey&gt;
  /// The chain (`shortName`) is implicit based on the chain the `ERC6538Registry` is deployed on,
  /// therefore this `stealthMetaAddress` is just the `spendingPubKey` and `viewingPubKey`
  /// concatenated.
  event StealthMetaAddressSet(
    address indexed registrant, uint256 indexed schemeId, bytes stealthMetaAddress
  );

  /// @notice Emitted when a registrant increments their nonce.
  /// @param registrant The account that incremented the nonce.
  /// @param newNonce The new nonce value.
  event NonceIncremented(address indexed registrant, uint256 newNonce);

  /// @notice Sets the caller&apos;s stealth meta-address for the given scheme ID.
  /// @param schemeId Identifier corresponding to the applied stealth address scheme, e.g. 1 for
  /// secp256k1, as specified in ERC-5564.
  /// @param stealthMetaAddress The stealth meta-address to register.
  function registerKeys(uint256 schemeId, bytes calldata stealthMetaAddress) external;

  /// @notice Sets the `registrant`&apos;s stealth meta-address for the given scheme ID.
  /// @param registrant Address of the registrant.
  /// @param schemeId Identifier corresponding to the applied stealth address scheme, e.g. 1 for
  /// secp256k1, as specified in ERC-5564.
  /// @param signature A signature from the `registrant` authorizing the registration.
  /// @param stealthMetaAddress The stealth meta-address to register.
  /// @dev Supports both EOA signatures and EIP-1271 signatures.
  /// @dev Reverts if the signature is invalid.
  function registerKeysOnBehalf(
    address registrant,
    uint256 schemeId,
    bytes memory signature,
    bytes calldata stealthMetaAddress
  ) external;

  /// @notice Increments the nonce of the sender to invalidate existing signatures.
  function incrementNonce() external;

  /// @notice Returns the domain separator used in this contract.
  function DOMAIN_SEPARATOR() external view returns (bytes32);

  /// @notice Returns the stealth meta-address for the given `registrant` and `schemeId`.
  function stealthMetaAddressOf(address registrant, uint256 schemeId)
    external
    view
    returns (bytes memory);

  /// @notice Returns the EIP-712 type hash used in `registerKeysOnBehalf`.
  function ERC6538REGISTRY_ENTRY_TYPE_HASH() external view returns (bytes32);

  /// @notice Returns the nonce of the given `registrant`.
  function nonceOf(address registrant) external view returns (uint256);
}

```

### Deployment Method

The `ERC6538Registry` contract is deployed at `0x6538E6bf4B0eBd30A8Ea093027Ac2422ce5d6538` using `CREATE2` via the deterministic deployer at `0x4e59b44847b379578588920ca78fbf26c0b4956c` with a salt of `0x7cac4e512b1768c627c9e711c7a013f1ad0766ef5125c59fb7161dade58da078`.

## Rationale

Having a central smart contract for registering stealth meta-addresses has several benefits:

1. It guarantees interoperability with other smart contracts, as they can easily retrieve and utilize the registered stealth meta-addresses. This enables applications such as ENS or Gnosis Safe to use that information and integrate stealth addresses into their services.

2. It ensures that users are not dependent on off-chain sources to retrieve a user&apos;s stealth meta-address.

3. Registration of a stealth meta-address in this contract provides a standard way for users to communicate that they&apos;re ready to participate in stealth interactions.

4. By deploying the registry as a singleton contract, multiple projects can access the same set of stealth meta-addresses, contributing to improved standardization.

## Backwards Compatibility

This EIP is fully backward compatible.

## Reference Implementation

You can find an implementation of the `ERC6538Registry` contract [here](/EIPs/assets/eip-6538/contracts/ERC6538Registry.sol) and the interface `IERC6538Registry.sol` [here](/EIPs/assets/eip-6538/contracts/interfaces/IERC6538Registry.sol).

## Security Considerations

In the event of a compromised private key, the registrant should promptly un-register from the stealth key registry to prevent loss of future funds sent to the compromised account.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 24 Jan 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6538</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6538</guid>
      </item>
    
      <item>
        <title>Non-fungible Token Bound Accounts</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/non-fungible-token-bound-accounts/13030</comments>
        
        <description>## Abstract

This proposal defines a system which assigns Ethereum accounts to all non-fungible tokens. These token bound accounts allow NFTs to own assets and interact with applications, without requiring changes to existing smart contracts or infrastructure.

## Motivation

The [ERC-721](/EIPs/EIPS/eip-721) standard enabled an explosion of non-fungible token applications. Some notable use cases have included breedable cats, generative artwork, and exchange liquidity positions.

However, NFTs cannot act as agents or associate with other on-chain assets. This limitation makes it difficult to represent many real-world non-fungible assets as NFTs. For example:

- A character in a role-playing game that accumulates assets and abilities over time based on actions they have taken
- An automobile composed of many fungible and non-fungible components
- An investment portfolio composed of multiple fungible assets
- A punch pass membership card granting access to an establishment and recording a history of past interactions

This proposal aims to give every NFT the same rights as an Ethereum user. This includes the ability to self-custody assets, execute arbitrary operations, control multiple independent accounts, and use accounts across multiple chains. By doing so, this proposal allows complex real-world assets to be represented as NFTs using a common pattern that mirrors Etherem&apos;s existing ownership model.

This is accomplished by defining a singleton registry which assigns unique, deterministic smart contract account addresses to all existing and future NFTs. Each account is permanently bound to a single NFT, with control of the account granted to the holder of that NFT.

The pattern defined in this proposal does not require any changes to existing NFT smart contracts. It is also compatible out of the box with nearly all existing infrastructure that supports Ethereum accounts, from on-chain protocols to off-chain indexers. Token bound accounts are compatible with every existing on-chain asset standard, and can be extended to support new asset standards created in the future.

By giving every NFT the full capabilities of an Ethereum account, this proposal enables many novel use cases for existing and future NFTs.

## Specification

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

### Overview

The system outlined in this proposal has two main components:

- A singleton registry for token bound accounts
- A common interface for token bound account implementations

The following diagram illustrates the relationship between NFTs, NFT holders, token bound accounts, and the Registry:
![](/EIPs/assets/eip-6551/diagram.png)

### Registry

The registry is a singleton contract that serves as the entry point for all token bound account address queries. It has two functions:

- `createAccount` - creates the token bound account for an NFT given an `implementation` address
- `account` - computes the token bound account address for an NFT given an `implementation` address

The registry is permissionless, immutable, and has no owner. The complete source code for the registry can be found in the [Registry Implementation](#registry-implementation) section. The registry MUST be deployed at address `0x000000006551c19487814612e58FE06813775758` using Nick&apos;s Factory (`0x4e59b44847b379578588920cA78FbF26c0B4956C`) with salt `0x0000000000000000000000000000000000000000fd8eb4e1dca713016c518e31`.

The registry can be deployed to any EVM-compatible chain using the following transaction:

```
{
        &quot;to&quot;: &quot;0x4e59b44847b379578588920ca78fbf26c0b4956c&quot;,
        &quot;value&quot;: &quot;0x0&quot;,
        &quot;data&quot;: &quot;0x0000000000000000000000000000000000000000fd8eb4e1dca713016c518e31608060405234801561001057600080fd5b5061023b806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063246a00211461003b5780638a54c52f1461006a575b600080fd5b61004e6100493660046101b7565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b61004e6100783660046101b7565b6100e1565b600060806024608c376e5af43d82803e903d91602b57fd5bf3606c5285605d52733d60ad80600a3d3981f3363d3d373d3d3d363d7360495260ff60005360b76055206035523060601b60015284601552605560002060601b60601c60005260206000f35b600060806024608c376e5af43d82803e903d91602b57fd5bf3606c5285605d52733d60ad80600a3d3981f3363d3d373d3d3d363d7360495260ff60005360b76055206035523060601b600152846015526055600020803b61018b578560b760556000f580610157576320188a596000526004601cfd5b80606c52508284887f79f19b3655ee38b1ce526556b7731a20c8f218fbda4a3990b6cc4172fdf887226060606ca46020606cf35b8060601b60601c60005260206000f35b80356001600160a01b03811681146101b257600080fd5b919050565b600080600080600060a086880312156101cf57600080fd5b6101d88661019b565b945060208601359350604086013592506101f46060870161019b565b94979396509194608001359291505056fea2646970667358221220ea2fe53af507453c64dd7c1db05549fa47a298dfb825d6d11e1689856135f16764736f6c63430008110033&quot;,
}
```

The registry MUST deploy each token bound account as an [ERC-1167](/EIPs/EIPS/eip-1167) minimal proxy with immutable constant data appended to the bytecode.

The deployed bytecode of each token bound account MUST have the following structure:

```
ERC-1167 Header               (10 bytes)
&lt;implementation (address)&gt;    (20 bytes)
ERC-1167 Footer               (15 bytes)
&lt;salt (bytes32)&gt;              (32 bytes)
&lt;chainId (uint256)&gt;           (32 bytes)
&lt;tokenContract (address)&gt;     (32 bytes)
&lt;tokenId (uint256)&gt;           (32 bytes)
```

For example, the token bound account with implementation address `0xbebebebebebebebebebebebebebebebebebebebe`, salt `0`, chain ID `1`, token contract `0xcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcf` and token ID `123` would have the following deployed bytecode:

```
363d3d373d3d3d363d73bebebebebebebebebebebebebebebebebebebebe5af43d82803e903d91602b57fd5bf300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000cfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcfcf000000000000000000000000000000000000000000000000000000000000007b
```

Each token bound account proxy MUST delegate execution to a contract that implements the `IERC6551Account` interface.

The registry MUST deploy all token bound accounts using the `create2` opcode so that each account address is deterministic. Each token bound account address SHALL be derived from the unique combination of its implementation address, token contract address, token ID, chain ID, and salt.

The registry MUST implement the following interface:

```solidity
interface IERC6551Registry {
    /**
     * @dev The registry MUST emit the ERC6551AccountCreated event upon successful account creation.
     */
    event ERC6551AccountCreated(
        address account,
        address indexed implementation,
        bytes32 salt,
        uint256 chainId,
        address indexed tokenContract,
        uint256 indexed tokenId
    );

    /**
     * @dev The registry MUST revert with AccountCreationFailed error if the create2 operation fails.
     */
    error AccountCreationFailed();

    /**
     * @dev Creates a token bound account for a non-fungible token.
     *
     * If account has already been created, returns the account address without calling create2.
     *
     * Emits ERC6551AccountCreated event.
     *
     * @return account The address of the token bound account
     */
    function createAccount(
        address implementation,
        bytes32 salt,
        uint256 chainId,
        address tokenContract,
        uint256 tokenId
    ) external returns (address account);

    /**
     * @dev Returns the computed token bound account address for a non-fungible token.
     *
     * @return account The address of the token bound account
     */
    function account(
        address implementation,
        bytes32 salt,
        uint256 chainId,
        address tokenContract,
        uint256 tokenId
    ) external view returns (address account);
}
```

### Account Interface

All token bound accounts SHOULD be created via the singleton registry.

All token bound account implementations MUST implement [ERC-165](/EIPs/EIPS/eip-165) interface detection.

All token bound account implementations MUST implement [ERC-1271](/EIPs/EIPS/eip-1271) signature validation.

All token bound account implementations MUST implement the following interface:

```solidity
/// @dev the ERC-165 identifier for this interface is `0x6faff5f1`
interface IERC6551Account {
    /**
     * @dev Allows the account to receive Ether.
     *
     * Accounts MUST implement a `receive` function.
     *
     * Accounts MAY perform arbitrary logic to restrict conditions
     * under which Ether can be received.
     */
    receive() external payable;

    /**
     * @dev Returns the identifier of the non-fungible token which owns the account.
     *
     * The return value of this function MUST be constant - it MUST NOT change over time.
     *
     * @return chainId       The chain ID of the chain the token exists on
     * @return tokenContract The contract address of the token
     * @return tokenId       The ID of the token
     */
    function token()
        external
        view
        returns (uint256 chainId, address tokenContract, uint256 tokenId);

    /**
     * @dev Returns a value that SHOULD be modified each time the account changes state.
     *
     * @return The current account state
     */
    function state() external view returns (uint256);

    /**
     * @dev Returns a magic value indicating whether a given signer is authorized to act on behalf
     * of the account.
     *
     * MUST return the bytes4 magic value 0x523e3260 if the given signer is valid.
     *
     * By default, the holder of the non-fungible token the account is bound to MUST be considered
     * a valid signer.
     *
     * Accounts MAY implement additional authorization logic which invalidates the holder as a
     * signer or grants signing permissions to other non-holder accounts.
     *
     * @param  signer     The address to check signing authorization for
     * @param  context    Additional data used to determine whether the signer is valid
     * @return magicValue Magic value indicating whether the signer is valid
     */
    function isValidSigner(address signer, bytes calldata context)
        external
        view
        returns (bytes4 magicValue);
}

```

### Execution Interface

All token bound accounts MUST implement an execution interface which allows valid signers to execute arbitrary operations on behalf of the account. Support for an execution interface MUST be signaled by the account using ERC-165 interface detection.

Token bound accounts MAY support the following execution interface:

```solidity
/// @dev the ERC-165 identifier for this interface is `0x51945447`
interface IERC6551Executable {
    /**
     * @dev Executes a low-level operation if the caller is a valid signer on the account.
     *
     * Reverts and bubbles up error if operation fails.
     *
     * Accounts implementing this interface MUST accept the following operation parameter values:
     * - 0 = CALL
     * - 1 = DELEGATECALL
     * - 2 = CREATE
     * - 3 = CREATE2
     *
     * Accounts implementing this interface MAY support additional operations or restrict a signer&apos;s
     * ability to execute certain operations.
     *
     * @param to        The target address of the operation
     * @param value     The Ether value to be sent to the target
     * @param data      The encoded operation calldata
     * @param operation A value indicating the type of operation to perform
     * @return The result of the operation
     */
    function execute(address to, uint256 value, bytes calldata data, uint8 operation)
        external
        payable
        returns (bytes memory);
}
```

## Rationale

### Singleton Registry

This proposal specifies a single, canonical registry that can be permissionlessly deployed to any chain at a known address. It purposefully does not specify a common interface that can be implemented by multiple registry contracts. This approach enables several critical properties.

#### Counterfactual Accounts

All token bound accounts are created using the create2 opcode, enabling accounts to exist in a counterfactual state prior to their creation. This allows token bound accounts to receive assets prior to contract creation. A singleton account registry ensures a common addressing scheme is used for all token bound account addresses.

#### Trustless Deployments

A single ownerless registry ensures that the only trusted contract for any token bound account is the implementation. This guarantees the holder of a token access to all assets stored within a counterfactual account using a trusted implementation.

Without a canonical registry, some token bound accounts may be deployed using an owned or upgradable registry. This may lead to loss of assets stored in counterfactual accounts, and increases the scope of the security model that applications supporting this proposal must consider.

#### Cross-chain Compatibility

A singleton registry with a known address enables each token bound account to exist on multiple chains. The inclusion of `chainId` as a parameter to `createAccount` allows the contract for a token bound account to be deployed at the same address on any supported chain. Account implementations are therefore able to support cross-chain account execution, where an NFT on one chain can control its token bound account on another chain.

#### Single Entry Point

A single entry point for querying account addresses and `AccountCreated` events simplifies the complex task of indexing token bound accounts in applications which support this proposal.

#### Implementation Diversity

A singleton registry allows diverse account implementations to share a common addressing scheme. This gives developers significant freedom to implement both account-specific features (e.g. delegation) as well as alternative account models (e.g. ephemeral accounts) in a way that can be easily supported by client applications.

### Registry vs Factory

The term &quot;registry&quot; was chosen instead of &quot;factory&quot; to highlight the canonical nature of the contract and emphasize the act of querying account addresses (which occurs regularly) over the creation of accounts (which occurs only once per account).

### Variable Execution Interface

This proposal does not require accounts to implement a specific execution interface in order to be compatible, so long as they signal support for at least one execution interface via ERC-165 interface detection. Allowing account developers to choose their own execution interface allows this proposal to support the wide variety of existing execution interfaces and maintain forward compatibility with likely future standardized interfaces.

### Account Ambiguity

The specification proposed above allows NFTs to have multiple token bound accounts. During the development of this proposal, alternative architectures were considered which would have assigned a single token bound account to each NFT, making each token bound account address an unambiguous identifier.

However, these alternatives present several trade offs.

First, due to the permissionless nature of smart contracts, it is impossible to enforce a limit of one token bound account per NFT. Anyone wishing to utilize multiple token bound accounts per NFT could do so by deploying an additional registry contract.

Second, limiting each NFT to a single token bound account would require a static, trusted account implementation to be included in this proposal. This implementation would inevitably impose specific constraints on the capabilities of token bound accounts. Given the number of unexplored use cases this proposal enables and the benefit that diverse account implementations could bring to the non-fungible token ecosystem, it is the authors&apos; opinion that defining a canonical and constrained implementation in this proposal is premature.

Finally, this proposal seeks to grant NFTs the ability to act as agents on-chain. In current practice, on-chain agents often utilize multiple accounts. A common example is individuals who use a &quot;hot&quot; account for daily use and a &quot;cold&quot; account for storing valuables. If on-chain agents commonly use multiple accounts, it stands to reason that NFTs ought to inherit the same ability.

### Proxy Implementation

ERC-1167 minimal proxies are well supported by existing infrastructure and are a common smart contract pattern. This proposal deploys each token bound account using a custom ERC-1167 proxy implementation that stores the salt, chain id, token contract address, and token ID as ABI-encoded constant data appended to the contract bytecode. This allows token bound account implementations to easily query this data while ensuring it remains constant. This approach was taken to maximize compatibility with existing infrastructure while also giving smart contract developers full flexibility when creating custom token bound account implementations.

### Chain Identifier

This proposal uses the chain ID to identify each NFT along with its contract address and token ID. Token identifiers are globally unique on a single Ethereum chain, but may not be unique across multiple Ethereum chains.

## Backwards Compatibility

This proposal seeks to be maximally backwards compatible with existing non-fungible token contracts. As such, it does not extend the ERC-721 standard.

Additionally, this proposal does not require the registry to perform an ERC-165 interface check for ERC-721 compatibility prior to account creation. This maximizes compatibility with non-fungible token contracts that pre-date the ERC-721 standard (such as CryptoKitties) or only implement a subset of the ERC-721 interface (such as ENS NameWrapper names). It also allows the system described in this proposal to be used with semi-fungible or fungible tokens, although these use cases are outside the scope of the proposal.

Smart contract authors may optionally choose to enforce interface detection for ERC-721 in their account implementations.

## Reference Implementation

### Example Account Implementation

```solidity
pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/utils/introspection/IERC165.sol&quot;;
import &quot;@openzeppelin/contracts/token/ERC721/IERC721.sol&quot;;
import &quot;@openzeppelin/contracts/interfaces/IERC1271.sol&quot;;
import &quot;@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol&quot;;

interface IERC6551Account {
    receive() external payable;

    function token()
        external
        view
        returns (uint256 chainId, address tokenContract, uint256 tokenId);

    function state() external view returns (uint256);

    function isValidSigner(address signer, bytes calldata context)
        external
        view
        returns (bytes4 magicValue);
}

interface IERC6551Executable {
    function execute(address to, uint256 value, bytes calldata data, uint8 operation)
        external
        payable
        returns (bytes memory);
}

contract ERC6551Account is IERC165, IERC1271, IERC6551Account, IERC6551Executable {
    uint256 immutable deploymentChainId = block.chainid;

    uint256 public state;

    receive() external payable {}

    function execute(address to, uint256 value, bytes calldata data, uint8 operation)
        external
        payable
        virtual
        returns (bytes memory result)
    {
        require(_isValidSigner(msg.sender), &quot;Invalid signer&quot;);
        require(operation == 0, &quot;Only call operations are supported&quot;);

        ++state;

        bool success;
        (success, result) = to.call{value: value}(data);

        if (!success) {
            assembly {
                revert(add(result, 32), mload(result))
            }
        }
    }

    function isValidSigner(address signer, bytes calldata) external view virtual returns (bytes4) {
        if (_isValidSigner(signer)) {
            return IERC6551Account.isValidSigner.selector;
        }

        return bytes4(0);
    }

    function isValidSignature(bytes32 hash, bytes memory signature)
        external
        view
        virtual
        returns (bytes4 magicValue)
    {
        bool isValid = SignatureChecker.isValidSignatureNow(owner(), hash, signature);

        if (isValid) {
            return IERC1271.isValidSignature.selector;
        }

        return bytes4(0);
    }

    function supportsInterface(bytes4 interfaceId) external pure virtual returns (bool) {
        return interfaceId == type(IERC165).interfaceId
            || interfaceId == type(IERC6551Account).interfaceId
            || interfaceId == type(IERC6551Executable).interfaceId;
    }

    function token() public view virtual returns (uint256, address, uint256) {
        bytes memory footer = new bytes(0x60);

        assembly {
            extcodecopy(address(), add(footer, 0x20), 0x4d, 0x60)
        }

        return abi.decode(footer, (uint256, address, uint256));
    }

    function owner() public view virtual returns (address) {
        (uint256 chainId, address tokenContract, uint256 tokenId) = token();
        if (chainId != deploymentChainId) return address(0);

        return IERC721(tokenContract).ownerOf(tokenId);
    }

    function _isValidSigner(address signer) internal view virtual returns (bool) {
        return signer == owner();
    }
}
```

### Registry Implementation

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

interface IERC6551Registry {
    /**
     * @dev The registry MUST emit the ERC6551AccountCreated event upon successful account creation.
     */
    event ERC6551AccountCreated(
        address account,
        address indexed implementation,
        bytes32 salt,
        uint256 chainId,
        address indexed tokenContract,
        uint256 indexed tokenId
    );

    /**
     * @dev The registry MUST revert with AccountCreationFailed error if the create2 operation fails.
     */
    error AccountCreationFailed();

    /**
     * @dev Creates a token bound account for a non-fungible token.
     *
     * If account has already been created, returns the account address without calling create2.
     *
     * Emits ERC6551AccountCreated event.
     *
     * @return account The address of the token bound account
     */
    function createAccount(
        address implementation,
        bytes32 salt,
        uint256 chainId,
        address tokenContract,
        uint256 tokenId
    ) external returns (address account);

    /**
     * @dev Returns the computed token bound account address for a non-fungible token.
     *
     * @return account The address of the token bound account
     */
    function account(
        address implementation,
        bytes32 salt,
        uint256 chainId,
        address tokenContract,
        uint256 tokenId
    ) external view returns (address account);
}

contract ERC6551Registry is IERC6551Registry {
    function createAccount(
        address implementation,
        bytes32 salt,
        uint256 chainId,
        address tokenContract,
        uint256 tokenId
    ) external returns (address) {
        assembly {
            // Memory Layout:
            // ----
            // 0x00   0xff                           (1 byte)
            // 0x01   registry (address)             (20 bytes)
            // 0x15   salt (bytes32)                 (32 bytes)
            // 0x35   Bytecode Hash (bytes32)        (32 bytes)
            // ----
            // 0x55   ERC-1167 Constructor + Header  (20 bytes)
            // 0x69   implementation (address)       (20 bytes)
            // 0x5D   ERC-1167 Footer                (15 bytes)
            // 0x8C   salt (uint256)                 (32 bytes)
            // 0xAC   chainId (uint256)              (32 bytes)
            // 0xCC   tokenContract (address)        (32 bytes)
            // 0xEC   tokenId (uint256)              (32 bytes)

            // Silence unused variable warnings
            pop(chainId)

            // Copy bytecode + constant data to memory
            calldatacopy(0x8c, 0x24, 0x80) // salt, chainId, tokenContract, tokenId
            mstore(0x6c, 0x5af43d82803e903d91602b57fd5bf3) // ERC-1167 footer
            mstore(0x5d, implementation) // implementation
            mstore(0x49, 0x3d60ad80600a3d3981f3363d3d373d3d3d363d73) // ERC-1167 constructor + header

            // Copy create2 computation data to memory
            mstore(0x35, keccak256(0x55, 0xb7)) // keccak256(bytecode)
            mstore(0x15, salt) // salt
            mstore(0x01, shl(96, address())) // registry address
            mstore8(0x00, 0xff) // 0xFF

            // Compute account address
            let computed := keccak256(0x00, 0x55)

            // If the account has not yet been deployed
            if iszero(extcodesize(computed)) {
                // Deploy account contract
                let deployed := create2(0, 0x55, 0xb7, salt)

                // Revert if the deployment fails
                if iszero(deployed) {
                    mstore(0x00, 0x20188a59) // `AccountCreationFailed()`
                    revert(0x1c, 0x04)
                }

                // Store account address in memory before salt and chainId
                mstore(0x6c, deployed)

                // Emit the ERC6551AccountCreated event
                log4(
                    0x6c,
                    0x60,
                    // `ERC6551AccountCreated(address,address,bytes32,uint256,address,uint256)`
                    0x79f19b3655ee38b1ce526556b7731a20c8f218fbda4a3990b6cc4172fdf88722,
                    implementation,
                    tokenContract,
                    tokenId
                )

                // Return the account address
                return(0x6c, 0x20)
            }

            // Otherwise, return the computed account address
            mstore(0x00, shr(96, shl(96, computed)))
            return(0x00, 0x20)
        }
    }

    function account(
        address implementation,
        bytes32 salt,
        uint256 chainId,
        address tokenContract,
        uint256 tokenId
    ) external view returns (address) {
        assembly {
            // Silence unused variable warnings
            pop(chainId)
            pop(tokenContract)
            pop(tokenId)

            // Copy bytecode + constant data to memory
            calldatacopy(0x8c, 0x24, 0x80) // salt, chainId, tokenContract, tokenId
            mstore(0x6c, 0x5af43d82803e903d91602b57fd5bf3) // ERC-1167 footer
            mstore(0x5d, implementation) // implementation
            mstore(0x49, 0x3d60ad80600a3d3981f3363d3d373d3d3d363d73) // ERC-1167 constructor + header

            // Copy create2 computation data to memory
            mstore(0x35, keccak256(0x55, 0xb7)) // keccak256(bytecode)
            mstore(0x15, salt) // salt
            mstore(0x01, shl(96, address())) // registry address
            mstore8(0x00, 0xff) // 0xFF

            // Store computed account address in memory
            mstore(0x00, shr(96, shl(96, keccak256(0x00, 0x55))))

            // Return computed account address
            return(0x00, 0x20)
        }
    }
}
```

## Security Considerations

### Fraud Prevention

In order to enable trustless sales of token bound accounts, decentralized marketplaces will need to implement safeguards against fraudulent behavior by malicious account owners.

Consider the following potential scam:

- Alice owns an ERC-721 token X, which owns token bound account Y.
- Alice deposits 10ETH into account Y
- Bob offers to purchase token X for 11ETH via a decentralized marketplace, assuming he will receive the 10ETH stored in account Y along with the token
- Alice withdraws 10ETH from the token bound account, and immediately accepts Bob&apos;s offer
- Bob receives token X, but account Y is empty

To mitigate fraudulent behavior by malicious account owners, decentralized marketplaces SHOULD implement protection against these sorts of scams at the marketplace level. Contracts which implement this EIP MAY also implement certain protections against fraudulent behavior.

Here are a few mitigations strategies to be considered:

- Attach the current token bound account state to the marketplace order. If the state of the account has changed since the order was placed, consider the offer void. This functionality would need to be supported at the marketplace level.
- Attach a list of asset commitments to the marketplace order that are expected to remain in the token bound account when the order is fulfilled. If any of the committed assets have been removed from the account since the order was placed, consider the offer void. This would also need to be implemented by the marketplace.
- Submit the order to the decentralized market via an external smart contract which performs the above logic before validating the order signature. This allows for safe transfers to be implemented without marketplace support.
- Implement a locking mechanism on the token bound account implementation that prevents malicious owners from extracting assets from the account while locked

Preventing fraud is outside the scope of this proposal.

### Ownership Cycles

All assets held in a token bound account may be rendered inaccessible if an ownership cycle is created. The simplest example is the case of an ERC-721 token being transferred to its own token bound account. If this occurs, both the ERC-721 token and all of the assets stored in the token bound account would be permanently inaccessible, since the token bound account is incapable of executing a transaction which transfers the ERC-721 token.

Ownership cycles can be introduced in any graph of n&gt;0 token bound accounts. On-chain prevention of cycles with depth&gt;1 is difficult to enforce given the infinite search space required, and as such is outside the scope of this proposal. Application clients and account implementations wishing to adopt this proposal are encouraged to implement measures that limit the possibility of ownership cycles.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 23 Feb 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6551</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6551</guid>
      </item>
    
      <item>
        <title>Cultural and Historical Asset Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6596-historical-asset-metadata-json-schema/13090</comments>
        
        <description>## Abstract

This EIP proposes the establishment of a comprehensive metadata standard for Cultural and Historical Asset Tokens
(CHATs) on the Ethereum platform. These tokens represent cultural and historical assets such as artwork, artifacts,
collectibles, and rare items, providing crucial context and provenance to substantiate their significance and value.

While existing NFT standards ensure the immutability and decentralized ownership of assets on the blockchain, based on
our research they do not adequately capture the cultural and historical importance and value of such assets needed for
widespread adoption by institutions such as museums. The CHAT standard aims to overcome these limitations by preserving
the provenance, history, and evolving context of cultural and historical assets, thus substantiating their value.
Furthermore, it incentivises museums, institutions, and asset owners to create tamper-proof records on the blockchain,
ensuring transparency and accountability and accelerating adoption of web3 protocols. Additionally, the CHAT standard
promotes interoperability with existing metadata standards in the arts and cultural sector, facilitating the search,
discovery, and connection of distributed assets.

## Motivation

**Preserving context and significance** - Provenance and context are crucial for cultural and historical assets. The
CHAT standard captures and preserves the provenance and history of these assets, as well as the changing contexts that
emerge from new knowledge and information. This context and provenance substantiate the significance and value of
cultural and historical assets.

**Proof-based preservation** - The recent incidents of lost artifacts and data breaches at a number of significant
international museums points to a need in reassessing our current record keeping mechanisms. While existing systems
mostly operate on trust, blockchain technology offers opportunities to establish permanent and verifiable records in a
proof-based environment. Introducing the CHAT standard on the Ethereum platform enables museums, institutions, and
owners of significant collections to create tamper-proof records on the blockchain. By representing these valuable
cultural and historical assets as tokens on the blockchain, permanent and tamper-proof records can be established
whenever amendments are made, ensuring greater transparency and accountability.

**Interoperability** - The proposed standard addresses the multitude of existing metadata standards used in the arts and
cultural sector. The vision is to create a metadata structure specifically built for preservation on the blockchain that
is interoperable with these existing standards and compliant with the Open Archives Initiative (OAI) as well as the
International Image Interoperability Framework protocol (IIIF).

**Search and Discovery** - Ownership and history of artworks, artifacts, and historical intellectual properties are
often distributed. Although there may never be a fully consolidated archive, a formalized blockchain-based metadata
structure enables consolidation for search and discovery of the assets, without consolidating the ownership. For
example, an artifact from an archaeological site of the Silk Road can be connected with Buddhist paintings, statues, and
texts about the ancient trade route across museum and institutional collections internationally. The proposed CHAT
metadata structure will facilitate easy access to these connections for the general public, researchers, scholars, other
cultural professionals, brands, media, and any other interested parties.

Currently, the [ERC-721](/EIPs/EIPS/eip-721) standard includes a basic metadata extension, which optionally provides functions
for identifying NFT collections (&quot;name&quot; and &quot;symbol&quot;) and attributes for representing assets (&quot;name,&quot; &quot;description,&quot;
and &quot;image&quot;). However, to provide comprehensive context and substantiate the value of tokenized assets, NFT issuers
often create their own metadata structures. We believe that the basic extension alone is insufficient to capture the
context and significance of cultural and historical assets. The lack of interoperable and consistent rich metadata
hinders users&apos; ability to search, discover, and connect tokenized assets on the blockchain. While connectivity among
collections may not be crucial for NFTs designed for games and memberships, it is of utmost importance for cultural and
historical assets. As the number and diversity of tokenized assets on the blockchain increase, it becomes essential to
establish a consistent and comprehensive metadata structure that provides context, substantiates value, and enables
connected search and discovery at scale.

## Specification

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

This EIP extends [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155) with 48 additional properties to capture the
cultural and historical significance of the underlying asset.

Compatible contracts, besides implementing the relevant metadata schemas (&quot;Metadata JSON Schema&quot; for
[ERC-721](/EIPs/EIPS/eip-721) contracts or &quot;Metadata URI JSON Schema&quot; for [ERC-1155](/EIPs/EIPS/eip-1155) contracts), must implement
the following metadata interface.

### Cultural and Historical Asset Metadata Extension TypeScript Interface

The following TypeScript interface defines the Metadata JSON Schema compatible tokens must conform to:

```typescript
interface HistoricalAssetMetadata {
    name?: string;                              // Name of the CHAT
    description?: string;                       // Full description of the CHAT to provide the cultural and historical
                                                // context
    image?: string;                             // A URI pointing to a resource with mime type image/* to serve as the
                                                // cover image of the CHAT
    attributes?: CHATAttribute[];               // A list of attributes to describe the CHAT. Attribute object may be
                                                // repeated if a field has multiple values
    attributesExt?: ExtendedCHATAttribute[];    // A list of extended attributes to describe the CHAT, not to be
                                                // displayed. Attribute object may be repeated if a field has
                                                // multiple values
}

type CHATAttribute =
    { trait_type: &quot;Catalogue Level&quot;, value: string }
    | { trait_type: &quot;Publication / Creation Date&quot;, value: string }
    | { trait_type: &quot;Creator Name&quot;, value: string }
    | { trait_type: &quot;Creator Bio&quot;, value: string }
    | { trait_type: &quot;Asset Type&quot;, value: string }
    | { trait_type: &quot;Classification&quot;, value: string }
    | { trait_type: &quot;Materials and Technology&quot;, value: string }
    | { trait_type: &quot;Subject Matter&quot;, value: string }
    | { trait_type: &quot;Edition&quot;, value: string }
    | { trait_type: &quot;Series name&quot;, value: string }
    | { trait_type: &quot;Dimensions Unit&quot;, value: string }
    | { trait_type: &quot;Dimensions (height)&quot;, value: number }
    | { trait_type: &quot;Dimensions (width)&quot;, value: number }
    | { trait_type: &quot;Dimensions (depth)&quot;, value: number }
    | { trait_type: &quot;Inscriptions / Marks&quot;, value: string }
    | { trait_type: &quot;Credit Line&quot;, value: string }
    | { trait_type: &quot;Current Owner&quot;, value: string }
    | { trait_type: &quot;Provenance&quot;, value: string }
    | { trait_type: &quot;Acquisition Date&quot;, value: string }
    | { trait_type: &quot;Citation&quot;, value: string }
    | { trait_type: &quot;Keyword&quot;, value: string }
    | { trait_type: &quot;Copyright Holder&quot;, value: string }
    | { trait_type: &quot;Bibliography&quot;, value: string }
    | { trait_type: &quot;Issuer&quot;, value: string }
    | { trait_type: &quot;Issue Timestamp&quot;, value: string }
    | { trait_type: &quot;Issuer Description&quot;, value: string }
    | { trait_type: &quot;Asset File Size&quot;, value: number }
    | { trait_type: &quot;Asset File Format&quot;, value: string }
    | { trait_type: &quot;Copyright / Restrictions&quot;, value: string }
    | { trait_type: &quot;Asset Creation Geo&quot;, value: string }
    | { trait_type: &quot;Asset Creation Location&quot;, value: string }
    | { trait_type: &quot;Asset Creation Coordinates&quot;, value: string }
    | { trait_type: &quot;Relevant Date&quot;, value: string }
    | { trait_type: &quot;Relevant Geo&quot;, value: string }
    | { trait_type: &quot;Relevant Location&quot;, value: string }
    | { trait_type: &quot;Relevant Person&quot;, value: string }
    | { trait_type: &quot;Relevant Entity&quot;, value: string }
    | { trait_type: &quot;Asset Language&quot;, value: string }
    | { trait_type: &quot;Is Physical Asset&quot;, value: boolean }

type ExtendedCHATAttribute =
    { trait_type: &quot;Asset Full Text&quot;, value: string }
    | { trait_type: &quot;Exhibition / Loan History&quot;, value: string }
    | { trait_type: &quot;Copyright Document&quot;, value: string }
    | { trait_type: &quot;Provenance Document&quot;, value: string }
    | { trait_type: &quot;Asset URL&quot;, value: string }
    | { trait_type: &quot;Copyright Document of Underlying Asset&quot;, value: string }
```

#### CHATAttribute Description

| trait_type                  | description                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
|-----------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Catalogue Level             | An indication of the level of cataloging represented by the record, based on the physical form or intellectual content of the material                                                                                                                                                                                                                                                                                                                              |
| Publication / Creation Date | Earliest possible creation date of the underlying asset in ISO 8601 date format                                                                                                                                                                                                                                                                                                                                                                                     |
| Creator Name                | The name, brief biographical information, and roles (if necessary) of the named or anonymous individuals or corporate bodies responsible for the design, production, manufacture, or alteration of the work, presented in a syntax suitable for display to the end-user and including any necessary indications of uncertainty, ambiguity, and nuance. If there is no known creator, make a reference to the presumed culture or nationality of the unknown creator |
| Creator Bio                 | The brief biography or description of creator                                                                                                                                                                                                                                                                                                                                                                                                                       |
| Asset Type                  | The type of the underlying asset                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| Classification              | Classification terms or codes are used to place a work of art or architecture in a useful organizational scheme that has been devised by a repository, collector, or other person or entity. Formal classification systems are used to relate a work of art or architecture to broader, narrower, and related objects. Classification terms group similar works together according to varying criteria                                                              |
| Materials and Technology    | The materials and/or techniques used to create the physical underlying asset                                                                                                                                                                                                                                                                                                                                                                                        |
| Subject Matter              | Indexing terms that characterize in general terms what the work depicts or what is depicted in it. This subject analysis is the minimum required. It is recommended to also list specific subjects, if possible                                                                                                                                                                                                                                                     |
| Edition                     | Edition of the original work                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| Series Name                 | The name of the series the asset is a part of                                                                                                                                                                                                                                                                                                                                                                                                                       |
| Dimensions Unit             | Unit of the measurement of the dimension of the asset                                                                                                                                                                                                                                                                                                                                                                                                               |
| Dimensions (height)         | Height of the underlying asset                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| Dimensions (width)          | Width of the underlying asset                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| Dimensions (depth)          | Depth of the underlying asset                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| Credit Line                 | Crediting details of the source or origin of an image or content being used publicly. The credit line typically includes important details such as the name of the museum, the title or description of the artwork or object, the artist&apos;s name (if applicable), the date of creation, and any other relevant information that helps identify and contextualize the work                                                                                            |
| Inscriptions / Marks        | A description of distinguishing or identifying physical markings, lettering, annotations, texts, or labels that are a part of a work or are affixed, applied, stamped, written, inscribed, or attached to the work, excluding any mark or text inherent in materials (record watermarks in MATERIALS AND TECHNIQUES)                                                                                                                                                |
| Current Owner               | Name of the current owner                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| Provenance                  | Provenance provides crucial information about the artwork&apos;s authenticity, legitimacy, and historical significance. It includes details such as the names of previous owners, dates of acquisition, locations where the artwork or artifact resided, and any significant events or transactions related to its ownership                                                                                                                                             |
| Acquisition Date            | The date on which the acquirer obtained the asset                                                                                                                                                                                                                                                                                                                                                                                                                   |
| Citation                    | Citations of the asset in publications, journals, and any other medium                                                                                                                                                                                                                                                                                                                                                                                              |
| Keyword                     | Keywords that are relevant for researchers                                                                                                                                                                                                                                                                                                                                                                                                                          |
| Copyright Holder            | Copyright holder of the underlying asset                                                                                                                                                                                                                                                                                                                                                                                                                            |
| Bibliography                | Information on where this asset has been referenced, cited, consulted, and for what purpose                                                                                                                                                                                                                                                                                                                                                                         |
| Issuer                      | Issuer of the token                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| Issue Timestamp             | Date of token creation                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| Issuer Description          | Brief description of the issuing party                                                                                                                                                                                                                                                                                                                                                                                                                              |
| Asset File Size             | Size of the digital file of the underlying asset in bytes                                                                                                                                                                                                                                                                                                                                                                                                           |
| Asset File Format           | The physical form or the digital format of the underlying asset. For digital format, a MIME type should be specified                                                                                                                                                                                                                                                                                                                                                |
| Copyright / Restrictions    | The copyright status the work is under                                                                                                                                                                                                                                                                                                                                                                                                                              |
| Asset Creation Geo          | Country, subdivision, and city where the underlying asset was created. Reference to ISO 3166-2 standard for the short name of the country and subdivision. Utilize the official name for the city if it is not covered in the ISO subdivision                                                                                                                                                                                                                       |
| Asset Creation Location     | Specific cities and named locations where the underlying asset was created                                                                                                                                                                                                                                                                                                                                                                                          |
| Asset Creation Coordinates  | Coordinates of the location where the underlying asset was created                                                                                                                                                                                                                                                                                                                                                                                                  |
| Relevant Date               | Dates, in ISO 8601 date format, referenced in, and important to the significance of the CHAT                                                                                                                                                                                                                                                                                                                                                                        |
| Relevant Geo                | Country, subdivision, and city CHATs are referenced and important to the significance of the CHAT. Reference to ISO 3166-2 standard for the short name of the country and subdivision. Utilize the official name for the city if it is not covered in the ISO subdivision                                                                                                                                                                                           |
| Relevant Location           | Specific cities and named locations referenced in, and important to the significance of the CHAT                                                                                                                                                                                                                                                                                                                                                                    |
| Relevant Person             | Individuals referenced in, and important to the significance of the CHAT                                                                                                                                                                                                                                                                                                                                                                                            |
| Relevant Entity             | Entities referenced in, and important to the significance of the CHAT                                                                                                                                                                                                                                                                                                                                                                                               |
| Asset Language              | Languages used in the underlying asset. Reference to ISO 639 for code or macrolanguage names                                                                                                                                                                                                                                                                                                                                                                        |
| Is Physical Asset           | Flags whether the asset is tied to a physical asset                                                                                                                                                                                                                                                                                                                                                                                                                 |

#### ExtendedCHATAttribute Description

| trait_type                             | description                                                                                                                                                                                                                                                                                |
|----------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Asset Full Text                        | The full text in the underlying asset of the CHAT                                                                                                                                                                                                                                          |
| Exhibition / Loan History              | Including exhibition/loan description, dates, title, type, curator, organizer, sponsor, venue                                                                                                                                                                                              |
| Copyright Document                     | A URI pointing to the legal contract CHATs outlines the copyright of the underlying asset                                                                                                                                                                                                  |
| Provenance Document                    | A URI pointing to the existing provenance record documents of the underlying asset                                                                                                                                                                                                         |
| Asset URL                              | A URI pointing to a high-quality file of the underlying asset                                                                                                                                                                                                                              |
| Copyright Document of Underlying Asset | A URI pointing to legal document outlining the rights of the token owner. Specific dimensions include the right to display a work via digital and physical mediums, present the work publicly, create or sell copies of the work, and create or sell derivations from the underlying asset |

#### Example

To illustrate the use of the CHAT metadata extension, we provide an example of a CHAT metadata JSON file for the famous
Japanese woodblock print &quot;Under the Wave off Kanagawa&quot; by Katsushika Hokusai, which is currently held by the  Art
Institute of Chicago.

The metadata format is compatible with the [ERC-721](/EIPs/EIPS/eip-721) and OpenSea style metadata format.

```json
{
  &quot;name&quot;: &quot;Under the Wave off Kanagawa (Kanagawa oki nami ura), also known as The Great Wave, from the series “Thirty-Six Views of Mount Fuji (Fugaku sanjūrokkei)&quot;,
  &quot;description&quot;: &quot;Katsushika Hokusai’s much celebrated series, Thirty-Six Views of Mount Fuji (Fugaku sanjûrokkei), was begun in 1830, when the artist was 70 years old. This tour-de-force series established the popularity of landscape prints, which continues to this day. Perhaps most striking about the series is Hokusai’s copious use of the newly affordable Berlin blue pigment, featured in many of the compositions in the color for the sky and water. Mount Fuji is the protagonist in each scene, viewed from afar or up close, during various weather conditions and seasons, and from all directions.\n\nThe most famous image from the set is the “Great Wave” (Kanagawa oki nami ura), in which a diminutive Mount Fuji can be seen in the distance under the crest of a giant wave. The three impressions of Hokusai’s Great Wave in the Art Institute are all later impressions than the first state of the design.&quot;,
  &quot;image&quot;: &quot;ipfs://bafybeiav6sqcgzxk5h5afnmb3iisgma2kpnyj5fa5gnhozwaqwzlayx6se&quot;,
  &quot;attributes&quot;: [
    { &quot;trait_type&quot;: &quot;Publication / Creation Date&quot;, &quot;value&quot;: &quot;1826/1836&quot; },
    { &quot;trait_type&quot;: &quot;Creator Name&quot;, &quot;value&quot;: &quot;Katsushika Hokusai&quot; },
    { &quot;trait_type&quot;: &quot;Creator Bio&quot;, &quot;value&quot;: &quot;Katsushika Hokusai’s woodblock print The Great Wave is one of the most famous and recognizable works of art in the world. Hokusai spent the majority of his life in the capital of Edo, now Tokyo, and lived in a staggering 93 separate residences. Despite this frenetic movement, he produced tens of thousands of sketches, prints, illustrated books, and paintings. He also frequently changed the name he used to sign works of art, and each change signaled a shift in artistic style and intended audience.&quot; },
    { &quot;trait_type&quot;: &quot;Asset Type&quot;, &quot;value&quot;: &quot;Painting&quot; },
    { &quot;trait_type&quot;: &quot;Classification&quot;, &quot;value&quot;: &quot;Arts of Asia&quot; },
    { &quot;trait_type&quot;: &quot;Materials and Technology&quot;, &quot;value&quot;: &quot;Color woodblock print, oban&quot; },
    { &quot;trait_type&quot;: &quot;Subject Matter&quot;, &quot;value&quot;: &quot;Asian Art&quot; },
    { &quot;trait_type&quot;: &quot;Subject Matter&quot;, &quot;value&quot;: &quot;Edo Period (1615-1868)&quot; },
    { &quot;trait_type&quot;: &quot;Subject Matter&quot;, &quot;value&quot;: &quot;Ukiyo-e Style&quot; },
    { &quot;trait_type&quot;: &quot;Subject Matter&quot;, &quot;value&quot;: &quot;Woodblock Prints&quot; },
    { &quot;trait_type&quot;: &quot;Subject Matter&quot;, &quot;value&quot;: &quot;Japan 1800-1900 A.D.&quot; },
    { &quot;trait_type&quot;: &quot;Edition&quot;, &quot;value&quot;: &quot;1&quot; },
    { &quot;trait_type&quot;: &quot;Series name&quot;, &quot;value&quot;: &quot;Thirty-Six Views of Mount Fuji (Fugaku sanjûrokkei)&quot; },
    { &quot;trait_type&quot;: &quot;Dimensions Unit&quot;, &quot;value&quot;: &quot;cm&quot; },
    { &quot;trait_type&quot;: &quot;Dimensions (height)&quot;, &quot;value&quot;: 25.4 },
    { &quot;trait_type&quot;: &quot;Dimensions (width)&quot;, &quot;value&quot;: 37.6 },
    { &quot;trait_type&quot;: &quot;Inscriptions / Marks&quot;, &quot;value&quot;: &quot;Signature: Hokusai aratame Iitsu fude&quot; },
    { &quot;trait_type&quot;: &quot;Inscriptions / Marks&quot;, &quot;value&quot;: &quot;Publisher: Nishimura-ya Yohachi&quot; },
    { &quot;trait_type&quot;: &quot;Credit Line&quot;, &quot;value&quot;: &quot;Clarence Buckingham Collection&quot; },
    { &quot;trait_type&quot;: &quot;Current Owner&quot;, &quot;value&quot;: &quot;Art Institute of Chicago&quot; },
    { &quot;trait_type&quot;: &quot;Provenance&quot;, &quot;value&quot;: &quot;Yamanaka, New York by 1905&quot; },
    { &quot;trait_type&quot;: &quot;Provenance&quot;, &quot;value&quot;: &quot;Sold to Clarence Buckingham, Chicago by 1925&quot; },
    { &quot;trait_type&quot;: &quot;Provenance&quot;, &quot;value&quot;: &quot;Kate S. Buckingham, Chicago, given to the Art Institute of Chicago, 1925.&quot; },
    { &quot;trait_type&quot;: &quot;Acquisition Date&quot;, &quot;value&quot;: &quot;1925&quot; },
    { &quot;trait_type&quot;: &quot;Citation&quot;, &quot;value&quot;: &quot;James Cuno, The Art Institute of Chicago: The Essential Guide, rev. ed. (Art Institute of Chicago, 2009) p. 100.&quot; },
    { &quot;trait_type&quot;: &quot;Citation&quot;, &quot;value&quot;: &quot;James N. Wood, The Art Institute of Chicago: The Essential Guide, rev. ed. (Art Institute of Chicago, 2003), p. 86.&quot; },
    { &quot;trait_type&quot;: &quot;Citation&quot;, &quot;value&quot;: &quot;Jim Ulak, Japanese Prints (Art Institute of Chicago, 1995), p. 268.&quot; },
    { &quot;trait_type&quot;: &quot;Citation&quot;, &quot;value&quot;: &quot;Ukiyo-e Taikei (Tokyo, 1975), vol. 8, 29; XIII, I.&quot; },
    { &quot;trait_type&quot;: &quot;Citation&quot;, &quot;value&quot;: &quot;Matthi Forrer, Hokusai (Royal Academy of Arts, London 1988), p. 264.&quot; },
    { &quot;trait_type&quot;: &quot;Citation&quot;, &quot;value&quot;: &quot;Richard Lane, Hokusai: Life and Work (London, 1989), pp. 189, 192.&quot; },
    { &quot;trait_type&quot;: &quot;Copyright Holder&quot;, &quot;value&quot;: &quot;Public domain&quot; },
    { &quot;trait_type&quot;: &quot;Copyright / Restrictions&quot;, &quot;value&quot;: &quot;CC0&quot; },
    { &quot;trait_type&quot;: &quot;Asset Creation Geo&quot;, &quot;value&quot;: &quot;Japan&quot; },
    { &quot;trait_type&quot;: &quot;Asset Creation Location&quot;, &quot;value&quot;: &quot;Tokyo (Edo)&quot; },
    { &quot;trait_type&quot;: &quot;Asset Creation Coordinates&quot;, &quot;value&quot;: &quot;36.2048° N, 138.2529° E&quot; },
    { &quot;trait_type&quot;: &quot;Relevant Date&quot;, &quot;value&quot;: &quot;18th Century&quot; },
    { &quot;trait_type&quot;: &quot;Relevant Geo&quot;, &quot;value&quot;: &quot;Japan, Chicago&quot; },
    { &quot;trait_type&quot;: &quot;Relevant Location&quot;, &quot;value&quot;: &quot;Art Institute of Chicago&quot; },
    { &quot;trait_type&quot;: &quot;Relevant Person&quot;, &quot;value&quot;: &quot;Katsushika Hokusai&quot; },
    { &quot;trait_type&quot;: &quot;Relevant Person&quot;, &quot;value&quot;: &quot;Yamanaka&quot; },
    { &quot;trait_type&quot;: &quot;Relevant Person&quot;, &quot;value&quot;: &quot;Clarence Buckingham&quot; },
    { &quot;trait_type&quot;: &quot;Relevant Person&quot;, &quot;value&quot;: &quot;Kate S. Buckingham&quot; },
    { &quot;trait_type&quot;: &quot;Relevant Entity&quot;, &quot;value&quot;: &quot;Art Institute of Chicago, Clarence Buckingham Collection&quot; },
    { &quot;trait_type&quot;: &quot;Asset Language&quot;, &quot;value&quot;: &quot;Japanese&quot; },
    { &quot;trait_type&quot;: &quot;Is Physical Asset&quot;, &quot;value&quot;: true }
  ]
}
```

## Rationale

### Choosing to Extend Off-Chain Metadata JSON Schema over On-Chain Interface

Both the [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155) provide natural extension points in the metadata JSON
file associated with NFTs to supply enriched datasets about the underlying assets.

Providing enriched datasets through off-chain metadata JSON files allows existing NFT contracts to adopt the new
metadata structure proposed in this EIP without upgrading or migrating. The off-chain design enables flexible and
progressive enhancement of any NFT collections to adopt this standard gradually. This approach allows NFT collections to
be deployed using already-audited and battle-tested smart contract code without creating or adapting new smart
contracts, reducing the risk associated with adopting and implementing a new standard.

### Capturing Attributes Extensions in `attributes` and `attributesExt` properties

In the design of the Cultural and Historical Asset Token (CHAT) metadata extension, we have made a deliberate choice to
capture the metadata attributes between two main properties: `attributes` and `attributesExt`. This division serves
two distinct purposes while ensuring maximum compatibility with existing NFT galleries and marketplaces.

**1. `attributes` Property**

The `attributes` property contains core metadata attributes that are integral to the identity and categorization of
CHATs. These attributes are meant to be readily accessible, displayed, and searchable by NFT galleries and marketplaces.
By placing fundamental details such as the CHAT&apos;s name, description, image, and other key characteristics
in `attributes`, we ensure that these essential elements can be easily presented to users, collectors, and researchers.
This approach allows CHATs to seamlessly integrate with existing NFT platforms and marketplaces without requiring major
modifications.

**2. `attributesExt` Property**

The `attributesExt` property, on the other hand, is dedicated to extended attributes that provide valuable, in-depth
information about a CHAT but are not typically intended for display or search within NFT galleries and marketplaces.
These extended attributes serve purposes such as archival documentation, provenance records, and additional context that
may not be immediately relevant to a casual observer or collector. By isolating these extended attributes
in `attributesExt`, we strike a balance between comprehensiveness and user-friendliness. This approach allows CHAT
creators to include rich historical and contextual data without overwhelming the typical user interface, making the
extended information available for scholarly or specialized use cases.

This division of attributes into `attributes` and `attributesExt` ensures that the CHAT standard remains highly
compatible with existing NFT ecosystems, while still accommodating the specific needs of cultural and historical assets.
Users can enjoy a seamless experience in browsing and collecting CHATs, while researchers and historians have access to
comprehensive information when required, all within a framework that respects the practicalities of both user interfaces
and extended data documentation.

## Backwards Compatibility

This EIP is fully backward compatible with [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155).

## Security Considerations

NFT platforms and systems working with Cultural and Historical Asset Metadata JSON files are recommended to treat the
files as client-supplied data and follow the appropriate best practices for processing such data.

Specifically, when processing the URI fields, backend systems should take extra care to prevent a malicious issuer from
exploiting these fields to perform Server-Side Request Forgery (SSRF).

Frontend or client-side systems are recommended to escape all control characters that may be exploited to perform
Cross-Site Scripting (XSS).

Processing systems should manage resource allocation to prevent the systems from being vulnerable to Denial of Service (
DOS) attacks or circumventing security protection through arbitrary code exceptions. Improper processing of variable
data, such as strings, arrays, and JSON objects, may result in a buffer overflow. Therefore, it is crucial to allocate
resources carefully to avoid such vulnerabilities.

The metadata JSON files and the digital resources representing both the token and underlying assets should be stored in
a decentralized storage network to preserve the integrity and to ensure the availability of data for long-term
preservation.

Establishing the authenticity of the claims made in the Metadata JSON file is beyond the scope of this EIP, and is left
to future EIPs to propose an appropriate protocol.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 28 Feb 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6596</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6596</guid>
      </item>
    
      <item>
        <title>Abstract Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/draft-eip-abstract-token-standard/13152</comments>
        
        <description>## Abstract

Abstract tokens provide a standard interface to:

* Mint tokens off-chain as messages
* Reify tokens on-chain via smart contract
* Dereify tokens back into messages

Abstract tokens can comply with existing standards like [ERC-20](/EIPs/EIPS/eip-20), [ERC-721](/EIPs/EIPS/eip-721), and [ERC-1155](/EIPs/EIPS/eip-1155). The standard allows wallets and other applications to better handle *potential* tokens before any consensus-dependent events occur on-chain.

## Motivation

Abstract tokens enable zero-cost token minting, facilitating high-volume applications by allowing token holders to reify tokens (place the tokens on-chain) as desired. Example use cases:

* airdrops
* POAPs / receipts
* identity / access credentials

Merkle trees are often used for large token distributions to spread mint/claim costs to participants, but they require participants to provide a markle proof when claiming tokens. This standard aims to improve the claims proces for similar distributions:

* Generic: compatible with merkle trees, digital signatures, or other eligibility proofs
* Legible: users can query an abstract token contract to understand their potential tokens (e.g. token id, quantity, or uri)
* Contained: users do not need to understand the proof mechanism used by the particular token implementation contract

## Specification

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

### Data Types

#### Token Messages

A token message defines one or more tokens along with the context needed to reify the token(s) using a smart contract.

`chainId` &amp; `implementation`: set the domain of the token message to a specific chain and contract: this is where the token can be reified
`owner`: the address that owns the tokens defined in the messages when reified
`meta`: implementation-specific context necessary to reify the defined token(s), such as id, amount, or uri.
`proof`: implementation-specific authorization to reify the defined token(s).
`nonce`: counter that may be incremented when multiple otherwise-identical abstract token messages are needed

```solidity
struct AbstractTokenMessage {
  uint256 chainId;
  address implementation;
  address owner;
  bytes meta;
  uint256 nonce;
  bytes proof;
}
```

#### Message Status

A message status may be defined for every (abstract token contract, abstract token message) pair.
`invalid`: the contract cannot interact with the message
`valid`: the contract can interact with the message
`used`: the contract has already interacted with the message

```solidity
enum AbstractTokenMessageStatus {
  invalid,
  valid,
  used
}
```

### Methods

#### reify

Moves token(s) from a message to a contract
`function reify(AbstractTokenMessage calldata message) external;`

The token contract MUST reify a valid token message.

Reification MUST be idempotent: a particular token message may be used to reify tokens at most once. Calling `reify` with an already used token message MAY succeed or revert.

#### status

Returns the status of a particular message
`function status(AbstractTokenMessage calldata message) external view returns (AbstractTokenMessageStatus status);`

#### dereify

Moves token(s) from a contract to a message intended for another contract and/or chain.
`function dereify(AbstractTokenMessage calldata message) external;`

OPTIONAL - allows tokens to be moved between contracts and/or chains by dereifying them from one context and reifying them in another.
Dereification MUST be idempotent: a particular token message must be used to dereify tokens at most once.

If implemented, dereification:

* MUST burn the exact tokens from the holder as defined in the token message
* MUST NOT dereify token messages scoped to the same contract and chain.
* MAY succeed or revert if the token message is already used.
* MUST emit the `Reify` event on only the first `reify` call with a specific token message

#### id

Return the id of token(s) defined in a token message.
`function id(AbstractTokenMessage calldata message) external view returns (uint256);`

OPTIONAL - abstract token contracts without a well-defined token ID (e.g. ERC-20) MAY return `0` or not implement this method.

#### amount

Return the amount of token(s) defined in a token message.
`function amount(AbstractTokenMessage calldata message) external view returns (uint256);`

OPTIONAL - abstract token contracts without a well-defined token amount (e.g. ERC-721) MAY return `0` or not implement this method.

#### uri

Return the amount of token(s) defined in a token message.
`function uri(AbstractTokenMessage calldata message) external view returns (string memory);`

OPTIONAL - abstract token contracts without a well-defined uri (e.g. ERC-20) MAY return `&quot;&quot;` or not implement this method.

#### supportsInterface

All abstract token contracts must support [ERC-165](/EIPs/EIPS/eip-165) and include the Abstract Token interface ID in their supported interfaces.

### Events

#### Reify

The Reify event MUST be emitted when a token message is reified into tokens
`event Reify(AbstractTokenMessage);`

#### Dereify

The Dereify event MUST be emitted when tokens are dereified into a message
`event Dereify(AbstractTokenMessage);`

### Application to existing token standards

Abstract tokens compatible with existing token standards MUST overload existing token transfer functions to allow transfers from abstract token messages.

### Abstract ERC-20

```solidity
interface IAbstractERC20 is IAbstractToken, IERC20, IERC165 {
  // reify the message and then transfer tokens
  function transfer(
    address to,
    uint256 amount,
    AbstractTokenMessage calldata message
  ) external returns (bool);

  // reify the message and then transferFrom tokens
  function transferFrom(
    address from,
    address to,
    uint256 amount,
    AbstractTokenMessage calldata message
  ) external returns (bool);
}
```

### Abstract ERC-721

```solidity
interface IAbstractERC721 is IAbstractToken, IERC721 {
  function safeTransferFrom(
    address from,
    address to,
    uint256 tokenId,
    bytes calldata _data,
    AbstractTokenMessage calldata message
  ) external;

  function transferFrom(
    address from,
    address to,
    uint256 tokenId,
    AbstractTokenMessage calldata message
  ) external;
}
```

### Abstract ERC-1155

```
interface IAbstractERC1155 is IAbstractToken, IERC1155 {
  function safeTransferFrom(
    address from,
    address to,
    uint256 id,
    uint256 amount,
    bytes calldata data,
    AbstractTokenMessage calldata message
  ) external;

  function safeBatchTransferFrom(
    address from,
    address to,
    uint256[] calldata ids,
    uint256[] calldata amounts,
    bytes calldata data,
    AbstractTokenMessage[] calldata messages
  ) external;
}
```

## Rationale

### Meta format

The abstract token message `meta` field is simply a byte array to preserve the widest possible accesibility.

* Applications handling abstract tokens can interact with the implementation contract for token metadata rather than parsing this field, so legibility is of secondary importance
* A byte array can be decoded as a struct and checked for errors within the implementation contract
* Future token standards will include unpredictable metadata

### Proof format

Similar considerations went into defining the `proof` field as a plain byte array:

* The contents of this field may vary, e.g. an array of `bytes32` merkle tree nodes or a 65 byte signature.
* a byte array handles all potential use cases at the expense of increased message size.

## Backwards Compatibility

No backward compatibility issues found.

## Reference Implementation

See [here](/EIPs/assets/eip-6604/).

## Security Considerations

Several concerns are highlighted.

### Message Loss

Because token messages are not held on-chain, loss of the message may result in loss of the token. Applications that issue abstract tokens to their users can store the messages themselves, but ideally users would be able to store and interact with abstract token messages within their crypto wallets.

### Authorizing Reification

Token messages may only be reified if they include a validity proof. While the proof mechanism itself is out of scope for this standard, those designing proof mechanisms should consider:

* Does total supply need to audited on-chain and/or off-chain?
* Does the mechanism require ongoing access to a secret (e.g. digital signature) or is it immutable (e.g. merkle proof)?
* Is there any way for an attacker to prevent the reification of an otherwise valid token message?

### Non-owner (De)Reification

Can non-owners (de)reify a token message on behalf of the owner?

Pro: supporting apps should be able to handle this because once a valid message exists, the owner could (de)reify the message at any time
Con: if the token contract reverts upon (de)reification of a used message, an attacker could grief the owner by front-running the transaction

### Abstract Token Bridge Double Spend

Abstract tokens could be used for a token-specific bridge:

* Dereify the token from chain A to with message M
* Reify the token on chain B with message M

Because the abstract token standard does not specify any cross-chain message passing, the abstract token contracts on chains A and B cannot know whether a (de)reification of message M has occurred on the other chain.

A naive bridge would be subject to double spend attacks:

* An attacker requests bridging tokens they hold on chain A to chain B
* A bridging mechanism creates an abstract token message M
* The attacker reifies message M on chain B but *does not* dereify message M on chain A
* The attacker continues to use tokens

Some oracle mechanism is necessary to prevent the reification of message M on chain B until the corresponding tokens on chain A are dereified.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 03 Mar 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6604</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6604</guid>
      </item>
    
      <item>
        <title>Bit Based Permission</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/bit-based-permission/13065</comments>
        
        <description>## Abstract

This EIP offers a standard for building a bit-based permission and role system. Each permission is represented by a single bit. By using an `uint256`, up to $256$ permissions and $2^{256}$ roles can be defined. We are able to specify the importance of each permission based on the order of the bits.

## Specification

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

_Note_ The following specifications use syntax from Solidity `0.8.7` (or above)

Interface of reference is described as followed:

```solidity
pragma solidity ^0.8.7;

/**
    @title EIP-6617 Bit Based Permission
    @dev See https://eips.ethereum.org/EIPS/eip-6617
*/
interface IEIP6617 {

    /**
        MUST trigger when a permission is granted.
        @param _grantor        Grantor of the permission
        @param _permission     Permission that is granted
        @param _user           User who received the permission
    */
    event PermissionGranted(address indexed _grantor, uint256 indexed _permission, address indexed _user);

    /**
        MUST trigger when a permission is revoked.
        @param _revoker        Revoker of the permission
        @param _permission     Permission that is revoked
        @param _user           User who lost the permission
    */
    event PermissionRevoked(address indexed _revoker, uint256 indexed _permission, address indexed _user);

    /**
        @notice Check if user has permission
        @param _user                Address of the user whose permission we need to check
        @param _requiredPermission  The required permission
        @return                     True if the _permission is a superset of the _requiredPermission else False
    */
    function hasPermission(address _user, uint256 _requiredPermission)
        external
        view
        returns (bool);

    /**
        @notice Add permission to user
        @param _user                Address of the user to whom we are going to add a permission
        @param _permissionToAdd     The permission that will be added
        @return                     The new permission with the _permissionToAdd
    */
    function grantPermission(address _user, uint256 _permissionToAdd)
        external
        returns (bool);

    /**
        @notice Revoke permission from user
        @param _user                Address of the user to whom we are going to revoke a permission
        @param _permissionToRevoke  The permission that will be revoked
        @return                     The new permission without the _permissionToRevoke
    */
    function revokePermission(address _user, uint256 _permissionToRevoke)
        external
        returns (bool);
}
```

- Compliant contracts MUST implement `IEIP6617`
- A permission in a compliant contract is represented as an `uint256`. A permission MUST take only one bit of an `uint256` and therefore MUST be a power of 2. Each permission MUST be unique and the `0` MUST be used for none permission.

### Metadata Interface

It is RECOMMENDED for compliant contracts to implement the optional extension `IEIP6617Meta`.

- They SHOULD define a name and description for the base permissions and main combinaison.

- They SHOULD NOT define a description for every subcombinaison of permissions possible.

```solidity
/**
 * @dev Defined the interface of the metadata of EIP6617, MAY NOT be implemented
 */
interface IEIP6617Meta {
    
    /**
        Structure of permission description
        @param _permission     Permission
        @param _name           Name of the permission
        @param _description    Description of the permission
    */
    struct PermissionDescription {
        uint256 permission;
        string name;
        string description;
    }

    /**
        MUST trigger when the description is updated.
        @param _permission     Permission
        @param _name           Name of the permission
        @param _description    Description of the permission
    */
    event UpdatePermissionDescription(uint256 indexed _permission, string indexed _name, string indexed _description);

    /**
        Returns the description of a given `_permission`.
        @param _permission     Permission
    */
    function getPermissionDescription(uint256 _permission) external view returns (PermissionDescription memory description);

    /**
        Return `true` if the description was set otherwise return `false`. It MUST emit `UpdatePermissionDescription` event.
        @param _permission     Permission
        @param _name           Name of the permission
        @param _description    Description of the permission
    */
    function setPermissionDescription(uint256 _permission, string memory _name, string memory _description)
        external
        returns (bool success);
}
```

## Rationale

Currently permission and access control is performed using a single owner ([ERC-173](/EIPs/EIPS/eip-173)) or with `bytes32` roles ([ERC-5982](/EIPs/EIPS/eip-5982)).
However, using bitwise and bitmask operations allows for greater gas-efficiency and flexibility.

### Gas cost efficiency

Bitwise operations are very cheap and fast. For example, doing an `AND` bitwise operation on a permission bitmask is significantly cheaper than calling any number of `LOAD` opcodes.

### Flexibility

With the 256 bits of the `uint256`, we can create up to 256 different permissions which leads to $2^{256}$ unique combinations (a.k.a. roles).
_(A role is a combination of multiple permissions)._ Not all roles have to be predefined.

Since permissions are defined as unsigned integers, we can use the binary OR operator to create new role based on multiple permissions.

### Ordering permissions by importance

We can use the most significant bit to represent the most important permission, the comparison between permissions can then be done easily since they all are `uint256`s.

### Associate a meaning

Compared with access control managed via ERC-5982, this EIP does not provide a direct and simple understanding of the meaning of a permission or role.

To deal with this problem, you can set up the metadata interface, which associates a name and description to each permission or role. 

## Reference Implementation

First implementation could be found here:

- [Basic ERC-6617 implementation](/EIPs/assets/eip-6617/contracts/EIP6617.sol)

## Security Considerations

No security considerations.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 27 Feb 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6617</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6617</guid>
      </item>
    
      <item>
        <title>AA Account Metadata For Authentication</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6662-account-metadata-for-aa-account-authentication/13232</comments>
        
        <description>## Abstract

This ERC proposes a new **IAccountMetadata** interface as an extension for [ERC-4337](/EIPs/EIPS/eip-4337) to store authentication data on-chain to support a more user-friendly authentication model.

## Motivation

In this proposal, we propose a new **IAccountMetadata** interface as an extension for ERC-4337 **IAccount** interface. With this new interface, users can store authentication data on-chain through one-time publishing, allowing dApps to proactively fetch it from the chain to support a more flexible and user-friendly authentication model. This will serve as an alternative to the current authentication model where users need to log in with a wallet every time and push account-related information to dApps by connecting the wallet in advance.

## Specification

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.

### Authentication Flow

![Authentication Flow](/EIPs/assets/eip-6662/auth-flow.png)

In the new authentication workflow, users use AA compatible smart contract accounts as their wallet addresses. **Authenticator** could be anything but holding the private key to sign users&apos; operations. For example, it can be an offline authenticator mobile app or an online cloud service. **Relay** is an online service responsible for forwarding requests from dApps to the Authenticator. If the authenticator is online, it can play the role of Relay service and listen to dApps directly.

### Interface

To support the new authentication workflow, this ERC proposes a new **IAccountMetadata** interface as an extension of **IAccount** interface defined by ERC-4337.

```
interface IAccountMetadata {
  struct AuthenticatorInfo {
    // a list of service URIs to relay message from dApps to authenticators
    string[] relayURI;
    // a JSON string or URI pointing to a JSON file describing the
    // schema of AuthenticationRequest. The URI should follow ERC-4804
    // if the schema file is stored on-chain
    string schema;
  }

  function getAuthenticationInfo() external view returns(AuthenticatorInfo[] memory);
}
```

The relay endpoint should accept an AuthenticationRequest object as input. The format of the AuthenticationRequest object is defined by the schema field at AuthenticationInfo.

Following is a schema example which supports end to end encryption, where we pack all encrypted fields into an encryptedData field. Here we only list basic fields but there may be more fields per schema definition. A special symbol, such as &quot;$e2ee&quot;, could be used to indicate the field is encrypted.

```json
{
    &quot;title&quot;: &quot;AuthenticationRequest&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;entrypoint&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;the entrypoint contract address&quot;,
        },
        &quot;chainId&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;the chain id represented as hex string, e.g. 0x5 for goerli testnet&quot;,
        },
        &quot;userOp&quot;: {
            &quot;type&quot;: &quot;object&quot;,
            &quot;description&quot;: &quot;UserOp struct defined by ERC-4337 without signature&quot;,
        },
        &quot;encryptedData&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;contains all encrypted fields&quot;
        },
    }
}
```

## Rationale

To enable the new authentication workflow we described above, dApp needs to know two things:

1. **Where is the authenticator?** This is solved by the **relayURI** field in struct **AuthenticationInfo**. Users can publish the uri as the account metadata which will be pulled by dApp to do service discovery.

2. **What’s the format of AuthenticationRequest?** This is solved by the **schema** field in struct **AuthenticationInfo**. The schema defines the structure of the AuthenticationRequest object which is consumed by the authenticator. It can also be used to define extra fields for the relay service to enable flexible access control.

### Relay Service Selection

Each authenticator can provide a list of relay services. dApp should pull through the list of relay services in order to find the first workable one. All relay services under each authenticator must follow the same schema.

### Signature Aggregation

Multisig authentication could be enabled if multiple AuthenticatorInfos are provided under each smart contract account. Each authenticator can sign and submit signed user operations to bundler independently. These signatures will be aggregated by the Aggregator defined in ERC-4337.

### Future Extension

The **IAccountMetadata** interface could be extended per different requirements. For example, a new alias or avatar field could be defined for profile displaying.

## Backwards Compatibility

The new interface is fully backward compatible with ERC-4337.

## Security Considerations

### End to End Encryption

To protect the user’s privacy and prevent front-running attacks, it&apos;s better to keep the data from dApps to authenticators encrypted during transmission. This could be done by adopting the JWE (JSON Web Encryption, RFC-7516) method. Before sending out AuthenticationRequest, a symmetric CEK(Content Encryption Key) is generated to encrypt fields with end to end encryption enabled, then the CEK is encrypted with the signer&apos;s public key. dApp will pack the request into a JWE object and send it to the authenticator through the relay service. Relay service has no access to the end to end encrypted data since only the authenticator has the key to decrypt the CEK.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 09 Mar 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6662</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6662</guid>
      </item>
    
      <item>
        <title>Multi-redeemable NFTs</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6672-multi-redeemable-nfts/13276</comments>
        
        <description>## Abstract

This EIP proposes an extension to the [ERC-721](/EIPs/EIPS/eip-721) standard for Non-Fungible Tokens (NFTs) to enable multi-redeemable NFTs. Redemption provides a means for NFT holders to demonstrate ownership and eligibility of their NFT, which in turn enables them to receive a physical or digital item. This extension would allow an NFT to be redeemed in multiple scenarios and maintain a record of its redemption status on the blockchain.

## Motivation

The motivation behind our proposed NFT standard is to provide a more versatile and flexible solution compared to existing standards, allowing for multi-redeemable NFTs. Our proposed NFT standard enables multi-redeemable NFTs, allowing them to be redeemed in multiple scenarios for different campaigns or events, thus unlocking new possibilities for commerce use cases and breaking the limitation of one-time redemption per NFT.

One use case for an NFT that can be redeemed multiple times in various scenarios is a digital concert ticket. The NFT could be redeemed for access to the online concert and then again for exclusive merchandise, a meet and greet with the artist, or any exclusive commerce status that is bound to the NFT. Each redemption could represent a unique experience or benefit for the NFT holder.

## Specification

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

### Redeem and Cancel Functions

An operator SHALL only make an update to the redemption created by itself. Therefore, the `redeem()` and `cancel()` functions do not have an `_operator` parameter, and the `msg.sender` address MUST be used as the `_operator`.

### Redemption Flag Key-Value Pairs

The combination of `_operator`, `_tokenId`, and `_redemptionId` MUST be used as the key in the redemption flag key-value pairs, whose value can be accessed from the `isRedeemed()` function.

**Every contract compliant with this EIP MUST implement `ERC6672` and `ERC721` interfaces.**

```solidity
pragma solidity ^0.8.16;

/// @title ERC-6672 Multi-Redeemable NFT Standard
/// @dev See https://eips.ethereum.org/EIPS/eip-6672
/// Note: the ERC-165 identifier for this interface is 0x4dddf83f.
interface IERC6672 /* is IERC721 */ {
    /// @dev This event emits when an NFT is redeemed.
    event Redeem(
        address indexed _operator,
        uint256 indexed _tokenId,
        address redeemer,
        bytes32 _redemptionId,
        string _memo
    );

    /// @dev This event emits when a redemption is canceled.
    event Cancel(
      address indexed _operator,
      uint256 indexed _tokenId,
      bytes32 _redemptionId,
      string _memo
    );

    /// @notice Check whether an NFT is already used for redemption or not.
    /// @dev 
    /// @param _operator The address of the operator of the redemption platform.
    /// @param _redemptionId The identifier for a redemption.
    /// @param _tokenId The identifier for an NFT.
    /// @return Whether an NFT is already redeemed or not.
    function isRedeemed(address _operator, bytes32 _redemptionId, uint256 _tokenId) external view returns (bool);

    /// @notice List the redemptions created by the given operator for the given NFT.
    /// @dev
    /// @param _operator The address of the operator of the redemption platform.
    /// @param _tokenId The identifier for an NFT.
    /// @return List of redemptions of speficic `_operator` and `_tokenId`.
    function getRedemptionIds(address _operator, uint256 _tokenId) external view returns (bytes32[]);
    
    /// @notice Redeem an NFT
    /// @dev
    /// @param _redemptionId The identifier created by the operator for a redemption.
    /// @param _tokenId The NFT to redeem.
    /// @param _memo
    function redeem(bytes32 _redemptionId, uint256 _tokenId, string _memo) external;

    /// @notice Cancel a redemption
    /// @dev
    /// @param _redemptionId The redemption to cancel.
    /// @param _tokenId The NFT to cancel the redemption.
    /// @param _memo
    function cancel(bytes32 _redemptionId, uint256 _tokenId, string _memo) external;
}
```

### Metadata Extension

The key format for the `redemptions` key-value pairs MUST be standardized as `operator-tokenId-redemptionId`, where `operator` is the operator wallet address, `tokenId` is  the identifier of the token that has been redeemed, and `redemptionId` is the redemption identifier. The value of the key `operator-tokenId-redemptionId` is an object that contains the `status` and `description` of the redemption.

- Redemption status, i.e. `status`

    The redemption status can have a more granular level, rather than just being a flag with a `true` or `false` value. For instance, in cases of physical goods redemption, we may require the redemption status to be either `redeemed`, `paid`, or `shipping`. It is RECOMMENDED to use a string enum that is comprehensible by both the operator and the marketplace or any other parties that want to exhibit the status of the redemption.

- Description of the redemption, i.e. `description`

    The `description` SHOULD be used to provide more details about the redemption, such as information about the concert ticket, a detailed description of the action figures, and more.
    
The **metadata extension** is OPTIONAL for [ERC-6672](/EIPs/EIPS/eip-6672) smart contracts (see &quot;caveats&quot;, below). This allows your smart contract to be interrogated for its name and for details about the assets which your NFTs represent.

```solidity
/// @title ERC-6672 Multi-Redeemable Token Standard, optional metadata extension
/// @dev See https://eips.ethereum.org/EIPS/eip-6672
interface IERC6672Metadata /* is IERC721Metadata */ {
    /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
    /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC
    ///  3986. The URI may point to a JSON file that conforms to the &quot;ERC-6672
    ///  Metadata JSON Schema&quot;.
    function tokenURI(uint256 _tokenId) external view returns (string);
}
```

This is the &quot;[ERC-6672](/EIPs/EIPS/eip-6672) Metadata JSON Schema&quot; referenced above.

```json
{
    &quot;title&quot;: &quot;Asset Metadata&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;name&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Identifies the asset to which this NFT represents&quot;
        },
        &quot;description&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Describes the asset to which this NFT represents&quot;
        },
        &quot;image&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive.&quot;
        }
    },
    &quot;redemptions&quot;: {
        &quot;operator-tokenId-redemptionId&quot;: {
            &quot;status&quot;: {
                &quot;type&quot;: &quot;string&quot;,
                &quot;description&quot;: &quot;The status of a redemption. Enum type can be used to represent the redemption status, such as redeemed, shipping, paid.&quot;
            },
            &quot;description&quot;: {
                &quot;type&quot;: &quot;string&quot;,
                &quot;description&quot;: &quot;Describes the object that has been redeemed for an NFT, such as the name of an action figure series name or the color of the product.&quot;
            }
        }
    }
}
```

## Rationale

### Key Choices for Redemption Flag and Status

The combination of `_operator`, `_tokenId`, and `_redemptionId` is chosen as the key because it provides a clear and unique identifier for each redemption transaction.

- Operator wallet address, i.e. `_operator`

    It&apos;s possible that there are more than one party who would like to use the same NFT for redemption. For example, MisterPunks NFTs are eligible to be redeemed for both Event-X and Event-Y tickets, and each event&apos;s ticket redemption is handled by a different operator.

- Token identifier, i.e. `_tokenId`

    Each NFT holder will have different redemption records created by the same operator. Therefore, it&apos;s important to use token identifier as one of the keys.

- Redemption identifier, i.e. `_redemptionId`

    Using `_redemptionId` as one of the keys enables NFT holders to redeem the same NFT to the same operator in multiple campaigns. For example, Operator-X has 2 campaigns, i.e. campaign A and campaign B, and both campaigns allow for MisterPunks NFTs to be redeemed for physical action figures. Holder of MisterPunk #7 is eligible for redemption in both campaigns and each redemption is recorded with the same `_operator` and `_tokenId`, but with different `_redemptionId`.

## Backwards Compatibility

This standard is compatible with [ERC-721](/EIPs/EIPS/eip-721).

## Reference Implementation

The reference implementation of Multi-Redeemable NFT can be found [here](/EIPs/assets/eip-6672/contracts/ERC6672.sol).


## Security Considerations

An incorrect implementation of [ERC-6672](/EIPs/EIPS/eip-6672) could potentially allow an unauthorized operator to access redemption flags owned by other operators, creating a security risk. As a result, an unauthorized operator could cancel the redemption process managed by other operators. Therefore, it is crucial for [ERC-6672](/EIPs/EIPS/eip-6672) implementations to ensure that only the operator who created the redemption, identified using `msg.sender`, can update the redemption flag using the `redeem()` and `cancel()` functions. It is also recommended to isolate the `redeem()` and `cancel()` functions from [ERC-721](/EIPs/EIPS/eip-721) approval models.

This [ERC-6672](/EIPs/EIPS/eip-6672) token is compatible with [ERC-721](/EIPs/EIPS/eip-721), so wallets and smart contracts capable of storing and handling standard [ERC-721](/EIPs/EIPS/eip-721) tokens will not face the risk of asset loss caused by incompatible standard implementations.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 21 Feb 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6672</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6672</guid>
      </item>
    
      <item>
        <title>NFT Flashloans</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6682-nft-flashloans/13294</comments>
        
        <description>## Abstract

This standard is an extension of the existing flashloan standard ([ERC-3156](/EIPs/EIPS/eip-3156)) to support [ERC-721](/EIPs/EIPS/eip-721) NFT flashloans. It proposes a way for flashloan providers to lend NFTs to contracts, with the condition that the loan is repaid in the same transaction along with some fee.

## Motivation

The current flashloan standard, [ERC-3156](/EIPs/EIPS/eip-3156), only supports [ERC-20](/EIPs/EIPS/eip-20) tokens. ERC-721 tokens are sufficiently different from ERC-20 tokens that they require an extension of this existing standard to support them. 

An NFT flash loan could be useful in any action where NFT ownership is checked. For example, claiming airdrops, claiming staking rewards, or taking an in-game action such as claiming farmed resources.

## Specification

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

### Contract Interface

```solidity
pragma solidity ^0.8.19;

interface IERC6682 {
    /// @dev The address of the token used to pay flash loan fees.
    function flashFeeToken() external view returns (address);

    /// @dev Whether or not the NFT is available for a flash loan.
    /// @param token The address of the NFT contract.
    /// @param tokenId The ID of the NFT.
    function availableForFlashLoan(address token, uint256 tokenId) external view returns (bool);
}
```

The `flashFeeToken` function MUST return the address of the token used to pay flash loan fees.

If the token used to pay the flash loan fees is ETH then `flashFeeToken` MUST return `address(0)`.

The `availableForFlashLoan` function MUST return whether or not the `tokenId` of `token` is available for a flashloan. If the `tokenId` is not currently available for a flashloan `availableForFlashLoan` MUST return `false` instead of reverting.

Implementers `MUST` also implement `IERC3156FlashLender`.

## Rationale

The above modifications are the simplest possible additions to the existing flashloan standard to support NFTs.

We choose to extend as much of the existing flashloan standard ([ERC-3156](/EIPs/EIPS/eip-3156)) as possible instead of creating a wholly new standard because the flashloan standard is already widely adopted and few changes are required to support NFTs.

In most cases, the handling of fee payments will be desired to be paid in a separate currency to the loaned NFTs because NFTs themselves cannot always be fractionalized. Consider the following example where the flashloan provider charges a 0.1 ETH fee on each NFT that is flashloaned; The interface must provide methods that allow the borrower to determine the fee rate on each NFT and also the currency that the fee should be paid in.

## Backwards Compatibility

This EIP is fully backwards compatible with [ERC-3156](/EIPs/EIPS/eip-3156) with the exception of the `maxFlashLoan` method. This method does not make sense within the context of NFTs because NFTs are not fungible. However it is part of the existing flashloan standard and so it is not possible to remove it without breaking backwards compatibility. It is RECOMMENDED that any contract implementing this EIP without the intention of supporting ERC-20 flashloans should always return `1` from `maxFlashLoan`. The `1` reflects the fact that only one NFT can be flashloaned per `flashLoan` call. For example:

```solidity
function maxFlashLoan(address token) public pure override returns (uint256) {
    // if a contract also supports flash loans for ERC20 tokens then it can
    // return some value here instead of 1
    return 1;
}
```

## Reference Implementation

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.19;

import &quot;../interfaces/IERC20.sol&quot;;
import &quot;../interfaces/IERC721.sol&quot;;
import &quot;../interfaces/IERC3156FlashBorrower.sol&quot;;
import &quot;../interfaces/IERC3156FlashLender.sol&quot;;
import &quot;../interfaces/IERC6682.sol&quot;;

contract ExampleFlashLender is IERC6682, IERC3156FlashLender {
    uint256 internal _feePerNFT;
    address internal _flashFeeToken;

    constructor(uint256 feePerNFT_, address flashFeeToken_) {
        _feePerNFT = feePerNFT_;
        _flashFeeToken = flashFeeToken_;
    }

    function flashFeeToken() public view returns (address) {
        return _flashFeeToken;
    }

    function availableForFlashLoan(address token, uint256 tokenId) public view returns (bool) {
        // return if the NFT is owned by this contract
        try IERC721(token).ownerOf(tokenId) returns (address result) {
            return result == address(this);
        } catch {
            return false;
        }
    }

    function flashFee(address token, uint256 tokenId) public view returns (uint256) {
        return _feePerNFT;
    }

    function flashLoan(IERC3156FlashBorrower receiver, address token, uint256 tokenId, bytes calldata data)
        public
        returns (bool)
    {
        // check that the NFT is available for a flash loan
        require(availableForFlashLoan(token, tokenId), &quot;IERC6682: NFT not available for flash loan&quot;);

        // transfer the NFT to the borrower
        IERC721(token).safeTransferFrom(address(this), address(receiver), tokenId);

        // calculate the fee
        uint256 fee = flashFee(token, tokenId);

        // call the borrower
        bool success =
            receiver.onFlashLoan(msg.sender, token, tokenId, fee, data) == keccak256(&quot;ERC3156FlashBorrower.onFlashLoan&quot;);

        // check that flashloan was successful
        require(success, &quot;IERC6682: Flash loan failed&quot;);
        
        // check that the NFT was returned by the borrower
        require(IERC721(token).ownerOf(tokenId) == address(this), &quot;IERC6682: NFT not returned by borrower&quot;);

        // transfer the fee from the borrower
        IERC20(flashFeeToken()).transferFrom(msg.sender, address(this), fee);

        return success;
    }

    function maxFlashLoan(address token) public pure override returns (uint256) {
        // if a contract also supports flash loans for ERC20 tokens then it can
        // return some value here instead of 1
        return 1;
    }

    function onERC721Received(address, address, uint256, bytes memory) public returns (bytes4) {
        return this.onERC721Received.selector;
    }
}
```

## Security Considerations

It&apos;s possible that the `flashFeeToken` method could return a malicious contract. Borrowers who intend to call the address that is returned from the `flashFeeToken` method should take care to ensure that the contract is not malicious. One way they could do this is by verifying that the returned address from `flashFeeToken` matches that of a user input.

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 12 Mar 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6682</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6682</guid>
      </item>
    
      <item>
        <title>EVM Modular Arithmetic Extensions</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6690-evm-modular-arithmetic-extensions/13322</comments>
        
        <description>## Abstract

This EIP proposes new EVM modular arithmetic opcodes which support operations on odd or power-of-two moduli between 3 and 2**768-1

## Motivation

Current opcodes for modular arithmetic only support values up to 256 bits wide.  In addition, they are permissive and accept any representable value for the inputs.

Many cryptographic operations are heavily-bottlenecked by modular arithmetic.  To expand the range of cryptographic primitives that can be implemented efficiently as EVM contracts, we propose new modular arithmetic opcodes designed for efficiency.

## Specification

### Constants

| Name | Value | Description |
| ---- | ---- | ---- |
| `COST_SETMODX_BASE` | 1 | static cost component for the `SETMODX` opcode |
| `COST_STOREX_BASE` | 1 | static cost for the `STOREX` opcode |
| `COST_LOADX_BASE` | 1 | static cost for the `LOADX` opcode |


### Conventions

1. The use of `assert` implies that if the assertion fails, the current call frame will consume all call gas and terminate call execution in an exceptional state.
2. Unless otherwise stated, the implied unit for size is bytes.

### Overview

The execution state of an EVM call frame is modified to include a mapping of `id` (a number 0-256) to a field context.  A field context comprises a modulus and an allocated space of virtual registers to perform modular arithmetic operations on.

An executing contract uses a new instruction `SETMODX` to set the active field context, allocating a new one in the mapping if it does not already exist for `id`.

New arithmetic opcodes perform modular addition, subtraction and multiplication with inputs/outputs from virtual registers of the active field context.

New load/store opcodes copy values to and from EVM memory and the virtual registers allocated by the active field context.

### New Opcodes

#### `SETMODX(0xc0)`

**Input**: `&lt;top of stack&gt; id modulus_offset modulus_size alloc_count`.

**Output**: none

##### Execution

Charge `COST_SETMODX_BASE`.

Assert `0 &lt;= id &lt;= 256`.

If a field context for `id` exists in this call scope:

* Set it as the active one.

Otherwise:

* Assert `modulus_size &lt;= 96`.
* Assert that the byte range`[modulus_offset, modulus_offset+modulus_size]` falls within EVM memory.
* Load the byte range from EVM memory, interpreting it as a big endian `modulus`.
* Assert `modulus` is odd or is a power of two.
* Assert `3 &lt;= modulus &lt;= 2**768 - 1`.
* Assert `0 &lt; alloc_count &lt;= 256`.
* Define the size of elements stored in virtual registers: `element_size` as the size needed to represent the modulus padded to be a multiple of 64 bits.  Implementations will align virtual register values along system-word lines.
* assert that the new size of all virtual registers allocated in the current call-context does not exceed 24576 bytes.
* Charge EVM memory expansion cost to expand memory by `alloc_count * element_size` bytes:.
* if the modulus is odd, charge the dynamic cost component (defined below)
* Allocate the new field context with `alloc_count` initially-zeroed registers. Associate it with `id` in the mapping.
* The new field context is now set as the active one.

##### Dynamic Cost Component for Odd Moduli

| Modulus size (padded to nearest 64 bits) | cost |
| --- | --- |
| 64 bits | 23 |
| 128 bits | 26 |
| 192 bits | 29 |
| 256 bits | 32 |
| 320 bits | 36 |
| 384 bits | 39 |
| 448 bits | 42 |
| 512 bits | 45 |
| 576 bits | 48 |
| 640 bits | 51 |
| 704 bits | 54 |
| 768 bits | 58 |

The values in this table are based on the following linear cost model:

```
def cost_setmodx_dynamic(modulus_size: int) -&gt; int:
    limb_count = (modulus_size + 7) / 8
    return round(limb_count * 3.13 + 19.94)
```

#### Arithmetic Opcodes

Opcodes `ADDMODX(0xc3)`, `SUBMODX(0xc4)`, `MULMODX(0xc5)` take a 7 byte immediate interpreted as byte values `out_idx`, `out_stride`, `x_idx`, `x_stride`, `y_idx`, `y_stride`, `count`.

Define cost tables for each arithmetic operation based on the modulus:

| Modulus size (padded to nearest 64 bits) | cost per add/sub | cost per mul |
| --- | --- | --- |
| 64 | 1 | 1 |
| 128 | 1 | 1 |
| 192 | 1 | 1 |
| 256 | 1 | 2 |
| 320 | 1 | 2 |
| 384 | 1 | 3 |
| 448 | 1 | 4 |
| 512 | 2 | 5 |
| 576 | 2 | 7 |
| 640 | 2 | 8 |
| 704 | 2 | 10 |
| 768 | 2 | 12 |

The values in this table correspond to the following cost models:

```
def cost_add_or_sub(modulus_size: int) -&gt; int:
    limb_count = (modulus_size + 7) // 8
    return round(limb_count * 0.12 + 0.58)
    
def cost_mul(modulus_size: int) -&gt; int:
    limb_count = (modulus_size + 7) // 8
    return round((0.08 * limb_count**2) + (-0.06 * limb_count) + 0.75)
```

Execution asserts:

* all accessed values fall within bounds: `max([out_idx + (out_stride * count), x_idx + (x_stride * count), y_idx + (y_stride * count)]) &lt; len(field_context.registers)`
* `out_stride != 0`
* `count != 0`
* an active field context `active_ctx` is set.

Then, charge `count * operation_cost` where `operation_cost` is drawn from the cost table. Compute:

```
for i in range(count):
    active_ctx.registers[out_idx+i*out_stride] = operation(active_ctx.registers[x_idx+i*x_stride], active_ctx.registers[y_idx+i*y_stride])
```

Where `operation` computes modular addition, subtraction or multiplication depending on the opcode.

Note: Inputs/outputs can overlap. `active_ctx.registers` is not modified until all operations in the loop have completed.

#### Data Transfer Opcodes

Note: serialization format for values in EVM memory: big-endian padded to `active_ctx.element_size` bytes.

##### `LOADX(0xc1)`

**Stack in**: `(top of stack) dest source count`

**Stack out**: none

**Description**: copies values from registers in the currently-active field context to EVM memory.

###### Execution

* Assert that a field context is set as active in the current call frame.
* Assert that the range `[source, source + count]` falls within the active field context&apos;s zero-indexed value space.
* Assert that the range `[dest, dest + count * active_ctx.element_size]` falls entirely within EVM memory.
* If modulus is a power of two:
    * charge `(active_ctxt.element_size + 31) // 32 * 3` gas (the same as the memory copying component for the `MCOPY` opcode)
* If modulus is odd:
    * charge `count * operation_cost` gas, where `operation_cost` is looked up from the multiplication cost table, given `active_ctxt.element_size`.
* copy virtual register values `[source, source + count]` to memory `[dest, dest + count * active_ctx.element_size]`.

##### `STOREX(0xc2)`

**Stack in**: `dest source count`

**Stack out**: none

**Description**: copies values from EVM memory into registers of the currently-active field context.

###### Execution

* Assert that a field context is set as active in the current call frame.
* Assert `dest + count` is less than or equal to the number of the active field context&apos;s virtual registers.
* If modulus of the active context is a power of two:
    * charge `cost_mem_copy(count * active_ctx.element_size)` (TBD: deliberately didn&apos;t choose `mcopy` gas model to see if this can consider a cheaper one).
* Else if modulus of the active context is odd:
    * charge `count * operation_cost` gas, where `operation_cost` is looked up from the multiplication cost table, given `active_ctxt.element_size`.
* Assert that `[source, source + count * active_context.element_size]` falls entirely within EVM memory.  Interpret it as `count` number of values, asserting that each is less than the modulus and storing them in the registers `[dest, dest + count]`.

### EVM Memory Expansion Cost Modification

When expanding EVM memory or allocating a new field context via `SETMODX`, expansion cost will now consider the size of all allocated virtual registers in the current call frame.

## Rationale

### Separation of EVM Memory and EVMMAX Virtual Register Space

It is assumed that optimized implementations will not store values in EVM-compatible big-endian serialization format, but instead convert them to an internal working representation.  The costs in the spec explicitly reflect the choice of Montgomery form as an optimal internal representation.

Values represented in Montgomery form can make use of optimized modular reduction for multiplication.  See the dedicated section on Montgomery multiplication in the rationale for more details.

### Total Virtual Register Allocation Cap

24576 bytes is chosen as the per-call-context allocation limit with the goal of ensuring that the virtual register space can be contained in the L1 CPU data cache of most machines (with room to spare), in order that arithmetic operation costs do not have to account for memory access latency.

### SETMODX cost

For odd moduli, `SETMODX` precomputes two values used for optimized modular multiplication via Montgomery reduction.  This is dominated by a modular reduction by the modulus, so the cost model is assumed to be linear.

Power-of-two moduli require no precomputation for optimized modular arithmetic.

### LOADX/STOREX costs

For power-of-two moduli, `LOADX`/`STOREX` are assumed to copy values directly between EVM/EVMMAX memories without measurable conversion cost to convert between EVM big-endian serialization and whatever internal representation is used.

For odd moduli, the spec assumes that the internal representation is Montgomery form.  Conversion between canonical/Montgomery form requires one modular multiplication per value per direction.  The cost of memory copying is baked in to the multiplication price model.

### Arithmetic Costs

Addition/subtraction/multiplication are assumed to have constant-time implementations.  Addition/subtraction can be implemented with linear complexity, while multiplication is quadratic in the size of the modulus.

The costs for power-of-two modular multiplication are provisional, and likely be brought down when an optimized arithmetic implementation is rolled out and benchmarked.

### Montgomery Modular Multiplication

For a value `A`, an odd modulus `M` and a value `R` (must be coprime and greater than `M`, chosen as a power of two for efficient performance), the Montgomery representation is `A * R % M`.

Define the Montgomery modular multiplication of two values `A` and `B`: `mulmont(A, B, M): A * B * R**-1 % M` where `R**-1 % M` is the modular inverse of `R` with respect to `M`.  There is various literature and algorithms for computing `mulmont` which have been published since 1985, and the operation is used ubiquitously where execution is bottlenecked by operations over odd moduli.

Note that normal modular addition and subtraction algorithms work for Montgomery form values.

#### Conversion of Canonical to Montgomery Representation

`mulmont(canon_val, R**2 % M, M) = mont_val`

#### Conversion from Montgomery to Canonical representation

`mulmont(mont_val, 1, M) = canon_val`

#### Implementation

```
# Basic Montgomery Multiplication
#   x, y, mod (int) - x &lt; mod and y &lt; mod
#   mod (int) - an odd modulus
#   R (int) -  a power of two, and greater than mod
#   mont_const (int) - pow(-mod, -1, R), precomputed
# output:
#  (x * y * pow(R, -1, mod)) % mod
#
def mulmont(x: int, y: int, mod: int, mont_const: int, R: int) -&gt; int:
    t = x * y
    m = ((t % R) * mont_const) % R
    t = t + m * mod
    t /= R
    if t &gt;= mod:
        t -= mod
    return t
```

There are various optimized algorithms for computing Montgomery Multiplication of bigint numbers expressed as arrays of system words.

These all use a different precomputed constant `mont_const = pow(-mod, -1, 2**SYSTEM_WORD_SIZE_BITS)`.


## Test Cases

There are tests contained in the Geth implementation.  However, no cross-client tests exist yet.

## Reference Implementation

There is an implementation of this EIP in an open PR to Go Ethereum.

## Security Considerations


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Wed, 15 Mar 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6690</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6690</guid>
      </item>
    
      <item>
        <title>L2 Token List</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/canonical-token-list-standard-from-the-eea-oasis-community-projects-l2-standards-working-group/13091</comments>
        
        <description>## Abstract

The document describes a JSON token list that ensures that two or more Layer 1, Layer 2, or Sidechains can identify tokens from a different Layer 1, Layer 2, or Sidechain.

## Motivation

This particular work by the L2 WG of the EEA Communities Projects managed by OASIS, an open-source initiative, is motivated by a significant challenge around the definition and listing of tokens on Layer 1 (L1), Layer 2 (L2), and Sidechain systems. Note that for simplicity, this document we will collectively refer to L1, L2 and Sidechain systems as chains below since the challenge described below is valid across all such systems:

* Consensus on the &quot;canonical&quot; token on chain B that corresponds to some token on chain A. When one wants to bridge token X from chain A to chain B, one must create some new representation of the token on chain B. It is worth noting that this problem is not limited to L2s -- every chain connected via bridges must deal with the same issue.

Related to the above challenge is the standardization around lists of bridges and their routes across different chains. This will be addressed in a separate document. 

Note that both of these issues are fundamental problems for the current multi-chain world.

Therefore, the goal of this document is to help token users to operationalize and disambiguate the usage of a token in their systems.

For lists of canonical tokens, L2s currently maintain their own customized versions of the Uniswap token list. For example, Arbitrum maintains a token list with various custom extensions. Optimism also maintains a custom token list, but with different extensions. It should be noted that both of these custom extensions refer to the bridge that these tokens can be carried through. However, these are not the only bridges that the tokens can be carried through, which means that bridges and token lists should be separated. Also note that currently, both Optimism and Arbitrum base &quot;canonicity&quot; on the token name + symbol pair.

An example of an Arbitrum token entry is given below:

```
{
logoURI: &quot;https://assets.coingecko.com/coins/images/13469/thumb/1inch-token.png?1608803028&quot;,
chainId: 42161,
address: &quot;0x6314C31A7a1652cE482cffe247E9CB7c3f4BB9aF&quot;,
name: &quot;1INCH Token&quot;,
symbol: &quot;1INCH&quot;,
decimals: 18,
extensions: {
  bridgeInfo: {
    1: {
    tokenAddress: &quot;0x111111111117dc0aa78b770fa6a738034120c302&quot;,
    originBridgeAddress: &quot;0x09e9222e96e7b4ae2a407b98d48e330053351eee&quot;,
    destBridgeAddress: &quot;0xa3A7B6F88361F48403514059F1F16C8E78d60EeC&quot;
     }
   }
  }
}
```

This standard will build upon the current framework and augment it with concepts from [Decentralized Identifiers (DIDs)](https://www.w3.org/TR/2022/REC-did-core-20220719/) based on the JSON linked data model [JSON-LD](https://www.w3.org/TR/2020/REC-json-ld11-20200716/) such as resolvable unique resource identifiers (URIs) and JSON-LD schemas which enable easier schema verification using existing tools.

Note that a standard for defining tokens is beyond the scope of this document.

## Specification

### Keywords:

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [[RFC2119](https://www.rfc-editor.org/rfc/rfc2119)] when, and only when, they appear in all capitals, as shown here.

### Typographical Convention: Requirement Ids

A requirement is uniquely identified by a unique ID composed of its requirement level followed by a requirement number, as per convention **[RequirementLevelRequirementNumber]**. 
There are four requirement levels that are coded in requirement ids as per below convention: 

**[R]** - The requirement level for requirements which IDs start with the letter _R_ is to be interpreted as **MUST** as described in [RFC2119](https://www.rfc-editor.org/rfc/rfc2119). \
**[D]** - The requirement level for requirements which IDs start with the letter _D_ is to be interpreted as **SHOULD** as described in [RFC2119](https://www.rfc-editor.org/rfc/rfc2119). \
**[O]** - The requirement level for requirements which IDs start with the letter _O_ is to be interpreted as **MAY** as described in [RFC2119](https://www.rfc-editor.org/rfc/rfc2119). 

Note that requirements are uniquely numbered in ascending order within each requirement level.

Example : It should be read that [R1] is an absolute requirement of the specification whereas [D1] is a recommendation and [O1] is truly optional. 

&lt;a name=&quot;r1&quot;&gt; **[R1]** &lt;/a&gt;
The following data elements MUST be present in a canonical token list:

* type
* tokenListId
* name
* createdAt
* updatedAt
* versions
* tokens

Note, that the detailed definition of the data elements in [[R1]](#r1) along with descriptions and examples are given in the schema itself below.

[[R1]](#r1) testability: See suggested test fixtures for the data schema below. 

&lt;a name=&quot;r2&quot;&gt; **[R2]** &lt;/a&gt;
The tokens data element is a composite which MUST minimally contain the following data elements:

* chainId
* chainURI
* tokenId
* tokenType
* address
* name
* symbol
* decimals
* createdAt
* updatedAt

Note, that the detailed definition of the data elements in [[R2]](#r2) along with descriptions and examples are given in the schema itself below.

[[R2]](#r2) testability: See suggested test fixtures for this documents&apos; data schema below.

&lt;a name=&quot;d1&quot;&gt; **[D1]** &lt;/a&gt;
All other data elements of the schema SHOULD be included in a representation of a canonical token list.

[[D1]](#d1) testability: See suggested test fixtures for this documents&apos; data schema below.

&lt;a name=&quot;cr1d1&quot;&gt; **[CR1]&gt;[D1]** &lt;/a&gt; 
If the extension data elements is used, the following data elements MUST be present in the schema representation:

* rootChainId
* rootChainURI
* rootAddress

Note, that the detailed definition of the data elements in [[D1]](#d1) and [[CR1]&gt;[D1]](#cr1d1) along with descriptions and examples are given in the schema itself below.

[[CR1]&gt;[D1]](#cr1d1) testability: See suggested test fixtures for this documents&apos; data schema below.

&lt;a name=&quot;r3&quot;&gt; **[R3]** &lt;/a&gt;
All properties in the schema identified in the description to be a Universal Resource Identifier (URI) MUST follow in their semantics [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986).

[[R3]](#r3) testability: All requirements for [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986) are testable.

&lt;a name=&quot;r4&quot;&gt; **[R4]** &lt;/a&gt;
The chainId property utilized MUST allow for the requirements of the [EIP-155](/EIPs/EIPS/eip-155) standard to be met.

Namely, transaction replay protection on the network that is identified by the chainId property value. Note, that for replay protection to be guaranteed, the chainId should be unique. Ensuring a unique chainId is beyond the scope of this document.

[[R4]](#r4) testability: EIP-155 requires that a transaction hash is derived from the keccak256 hash of the following nine RLP encoded elements `(nonce, gasprice, startgas, to, value, data, chainid, 0, 0)` which can be tested easily with existing cryptographic libraries. EIP-155 further requires that the `v` value of the secp256k1 signature must be set to `{0,1} + CHAIN_ID * 2 + 35` where `{0,1}` is the parity of the `y` value of the curve point for which the signature `r`-value is the `x`-value in the secp256k1 signing process. This requirement is testable with available open-source secp256k1 digital signature suites. Therefore, [[R4]](#r4) is testable.

&lt;a name=&quot;o1&quot;&gt; **[O1]** &lt;/a&gt;
The `humanReadableTokenSymbol` property MAY be used.

[[O1]](#o1) testability: A data property is always implementable in a schema.

&lt;a name=&quot;cr2o1&quot;&gt; **[CR2]&gt;[O1]** &lt;/a&gt;
The `humanReadableTokenSymbol` property MUST be constructed as the hyphenated concatenation of first the `tokenSymbol` and then the `chainId`.

An example would be:

```
&quot;tokenSymbol&quot; = ETH;
&quot;chainId&quot; = 1;
&quot;humanReadableTokenSymbol&quot; = ETH-1;
```

[[CR2]&gt;[O1]](#cr2o1) testability: `humanReadableTokenSymbol` can be parsed and split based on existing open source packages and the result compared to the `tokenSymbol` and `chainId` used in the data schema.


The schema for a canonical token list is given below as follows and can be utilized as a JSON-LD schema if a JSON-LD context file is utilized (see [[W3C-DID]](https://www.w3.org/TR/2022/REC-did-core-20220719/) for a concrete example in the context of a standard):

```
{
    &quot;$id&quot;: &quot;https://github.com/eea-oasis/l2/schemas/CanonicalTokenList.json&quot;,
    &quot;$schema&quot;: &quot;https://json-schema.org/draft-07/schema#&quot;,
    &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;CanonicalTokenList\&quot;, \&quot;@id\&quot;: \&quot;https://github.com/eea-oasis/l2#CanonicalTokenList\&quot;}&quot;,
    &quot;title&quot;: &quot;CanonicalTokenList&quot;,
    &quot;description&quot;: &quot;Canonical Token List&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;required&quot;: [
        &quot;type&quot;,
        &quot;tokenListId&quot;,
        &quot;name&quot;,
        &quot;createdAt&quot;,
        &quot;updatedAt&quot;,
        &quot;versions&quot;,
        &quot;tokens&quot;
        ],
        &quot;properties&quot;: {
            &quot;@context&quot;: {
                &quot;type&quot;: &quot;array&quot;
            },
            &quot;type&quot;: {
                &quot;oneOf&quot;: [
                    {
                        &quot;type&quot;: &quot;string&quot;
                    },
                    {
                        &quot;type&quot;: &quot;array&quot;
                    }
                ],
                &quot;examples&quot;: [&quot;CanonicalTokenList&quot;]
            },
            &quot;tokenListId&quot;: {
                &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;tokenListId\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/identifier\&quot;}&quot;,
                &quot;title&quot;: &quot;tokenListId&quot;,
                &quot;description&quot;: &quot;A resolvable URI to the publicly accessible place where this list can be found following the RFC 3986 standard.&quot;,
                &quot;type&quot;: &quot;string&quot;,
                &quot;examples&quot;: [&quot;https://ipfs.io/ipns/k51qzi5uqu5dkkciu33khkzbcmxtyhn376i1e83tya8kuy7z9euedzyr5nhoew&quot;]
            },
            &quot;name&quot;: {
                &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;name\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/name\&quot;}&quot;,
                &quot;title&quot;: &quot;name&quot;,
                &quot;description&quot;: &quot;Token List name&quot;,
                &quot;type&quot;: &quot;string&quot;,
                &quot;examples&quot;: [&quot;Aggregate Canonical Token List&quot;]
            },
            &quot;logoURI&quot;: {
                &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;logoURI\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/identifier\&quot;}&quot;,
                &quot;title&quot;: &quot;logoURI&quot;,
                &quot;description&quot;: &quot;URI or URL of the token list logo following the RFC 3986 standard&quot;,
                &quot;type&quot;: &quot;string&quot;,
                &quot;examples&quot;: [&quot;https://ipfs.io/ipns/k51qzi5uqu5dh5kbbff1ucw3ksphpy3vxx4en4dbtfh90pvw4mzd8nfm5r5fnl&quot;]
            },
            &quot;keywords&quot;: {
                &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;keywords\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/DefinedTerm\&quot;}&quot;,
                &quot;title&quot;: &quot;keywords&quot;,
                &quot;description&quot;: &quot;List of key words for the token list&quot;,
                &quot;type&quot;: &quot;array&quot;,
                &quot;examples&quot;: [Aggregate Token List]
            },
            &quot;createdAt&quot;: {
                &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;createdAt\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/datePublished\&quot;}&quot;,
                &quot;title&quot;: &quot;createdAt&quot;,
                &quot;description&quot;: &quot;Date and time token list was created&quot;,
                &quot;type&quot;: &quot;string&quot;,
                &quot;examples&quot;: [&quot;2022-05-08&quot;]
            },
            &quot;updatedAt&quot;: {
                &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;updatedAt\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/dateModified\&quot;}&quot;,
                &quot;title&quot;: &quot;updatedAt&quot;,
                &quot;description&quot;: &quot;Date and time token list was updated&quot;,
                &quot;type&quot;: &quot;string&quot;,
                 &quot;examples&quot;: [&quot;2022-05-09&quot;]
            },
            &quot;versions&quot;: {
                &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;versions\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/version\&quot;}&quot;,
                &quot;title&quot;: &quot;versions&quot;,
                &quot;description&quot;: &quot;Versions of the canonical token list&quot;,
                &quot;type&quot;: &quot;array&quot;,
                 &quot;items&quot;: {
                    &quot;type&quot;:&quot;object&quot;,
                    &quot;required&quot;:[
                        &quot;major&quot;,
                        &quot;minor&quot;,
                        &quot;patch&quot;
                    ],
                    &quot;properties&quot;: {
                        &quot;major&quot;: {
                            &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;major\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/Number\&quot;}&quot;,
                            &quot;title&quot;: &quot;major&quot;,
                            &quot;description&quot;: &quot;Major Version Number of the Token List&quot;,
                            &quot;type&quot;: &quot;integer&quot;,
                             &quot;examples&quot;: [1]
                        },
                        &quot;minor&quot;: {
                            &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;minor\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/Number\&quot;}&quot;,
                            &quot;title&quot;: &quot;minor&quot;,
                            &quot;description&quot;: &quot;Minor Version Number of the Token List&quot;,
                            &quot;type&quot;: &quot;integer&quot;,
                             &quot;examples&quot;: [1]
                        },
                        &quot;patch&quot;: {
                            &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;patch\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/Number\&quot;}&quot;,
                            &quot;title&quot;: &quot;patch&quot;,
                            &quot;description&quot;: &quot;Patch Number of the Token List&quot;,
                            &quot;type&quot;: &quot;integer&quot;,
                             &quot;examples&quot;: [1]
                        },
                    }
                }
            },
            &quot;tokens&quot;: {
                &quot;title&quot;: &quot;Listed Token Entry&quot;,
                &quot;description&quot;: &quot;Listed Token Entry&quot;,
                &quot;type&quot;: &quot;array&quot;,
                 &quot;items&quot;: {
                    &quot;type&quot;:&quot;object&quot;,
                    &quot;required&quot;: [
                        &quot;chainId&quot;,
                        &quot;chainURI&quot;,
                        &quot;tokenId&quot;,
                        &quot;tokenType&quot;,
                        &quot;address&quot;,
                        &quot;name&quot;,
                        &quot;symbol&quot;,
                        &quot;decimals&quot;,
                        &quot;createdAt&quot;,
                        &quot;updatedAt&quot;
                    ],
                    &quot;properties&quot;: {
                        &quot;chainId&quot;: {
                            &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;chainId\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/identifier\&quot;}&quot;,
                            &quot;title&quot;: &quot;chainId&quot;,
                            &quot;description&quot;: &quot;The typically used number identifier for the chain on which the token was issued.&quot;,
                            &quot;type&quot;: &quot;number&quot;,
                            &quot;examples&quot;: [137]
                        },
                        &quot;chainURI&quot;: {
                            &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;chainURI\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/identifier\&quot;}&quot;,
                            &quot;title&quot;: &quot;chainURI&quot;,
                            &quot;description&quot;: &quot;A resolvable URI to the genesis block of the chain on which the token was issued following the RFC 3986 standard.&quot;,
                            &quot;type&quot;: &quot;string&quot;
                             &quot;examples&quot;: [&quot;https://polygonscan.com/block/0&quot;]
                        },
                        &quot;genesisBlockHash&quot;: {
                            &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;genesisBlockHash\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/sha256\&quot;}&quot;,
                            &quot;title&quot;: &quot;genesisBlockHash&quot;,
                            &quot;description&quot;: &quot;The hash of the genesis block of the chain on which the token was issued.&quot;,
                            &quot;type&quot;: &quot;string&quot;,
                            &quot;examples&quot;: [&quot;0xa9c28ce2141b56c474f1dc504bee9b01eb1bd7d1a507580d5519d4437a97de1b&quot;]
                        },
                        &quot;tokenIssuerId&quot;: {
                            &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;tokenIssuerId\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/identifier\&quot;}&quot;,
                            &quot;title&quot;: &quot;tokenIssuerId&quot;,
                            &quot;description&quot;: &quot;A resolvable URI identifying the token issuer following the RFC 3986 standard.&quot;,
                            &quot;type&quot;: &quot;string&quot;,
                            &quot;examples&quot;: [&quot;https://polygonscan.com/address/0xa9c28ce2141b56c474f1dc504bee9b01eb1bd7d1a507580d5519d4437a97de1b&quot;]
                        },
                        &quot;tokenIssuerName&quot;: {
                            &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;tokenIssuerName\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/name\&quot;}&quot;,
                            &quot;title&quot;: &quot;tokenIssuerName&quot;,
                            &quot;description&quot;: &quot;The name oof the token issuer.&quot;,
                            &quot;type&quot;: &quot;string&quot;
                            &quot;examples&quot;: [&quot;Matic&quot;]
                        },
                        &quot;tokenId&quot;: {
                            &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;tokenId\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/identifier\&quot;}&quot;,
                            &quot;title&quot;: &quot;tokenId&quot;,
                            &quot;description&quot;: &quot;A resolvable URI of the token following the RFC 3986 standard to for example the deployment transaction of the token, or a DID identifying the token and its issuer.&quot;,
                            &quot;type&quot;: &quot;string&quot;,
                            &quot;example&quot;: [&quot;https://polygonscan.com/address/0x0000000000000000000000000000000000001010&quot;]
                        },
                        &quot;tokenType&quot;: {
                            &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;tokenType\&quot;, \&quot;@id\&quot;: \https://schema.org/StructuredValue\&quot;}&quot;,
                            &quot;title&quot;: &quot;tokenType&quot;,
                            &quot;description&quot;: &quot;Describes the type of token.&quot;,
                            &quot;type&quot;: &quot;array&quot;
                            &quot;examples&quot;[[&quot;fungible&quot;,&quot;transferable&quot;]]
                        },
                        &quot;tokenDesc&quot;: {
                            &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;tokenDesc\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/description\&quot;}&quot;,
                            &quot;title&quot;: &quot;tokenDesc&quot;,
                            &quot;description&quot;: &quot;Brief description of the token and its functionality.&quot;,
                            &quot;type&quot;: &quot;string&quot;,
                            &quot;examples&quot;: [&quot;Protocol Token for the Matic Network&quot;]
                        },
                        &quot;standard&quot;: {
                            &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;standard\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/citation\&quot;}&quot;,
                            &quot;title&quot;: &quot;standard&quot;,
                            &quot;description&quot;: &quot;A resolvable URI to the description of the token standard.&quot;,
                            &quot;type&quot;: &quot;string&quot;,
                            &quot;examples&quot;: [&quot;https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md&quot;]
                        },
                        &quot;address&quot;: {
                            &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;address\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/identifier\&quot;}&quot;,
                            &quot;title&quot;: &quot;address&quot;,
                            &quot;description&quot;: &quot;Address of the token smart contract.&quot;,
                            &quot;type&quot;: &quot;string&quot;,
                            &quot;examples&quot;: [&quot;0x0000000000000000000000000000000000001010&quot;]
                        },
                        &quot;addressType&quot;: {
                            &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;address\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/Intangible\&quot;}&quot;,
                            &quot;title&quot;: &quot;addressType&quot;,
                            &quot;description&quot;: &quot;AddressType of the token smart contract.&quot;,
                            &quot;type&quot;: &quot;string&quot;,
                            &quot;examples&quot;: [&quot;MaticNameSpace&quot;]
                        },
                        &quot;addressAlg&quot;: {
                            &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;addressAlg\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/algorithm\&quot;}&quot;,
                            &quot;title&quot;: &quot;addressAlg&quot;,
                            &quot;description&quot;: &quot;Algorithm used to create the address e.g. CREATE2 or the standard ethereum address construction which is the last 40 characters/20 bytes of the Keccak-256 hash of a secp256k1 public key.&quot;,
                            &quot;type&quot;: &quot;string&quot;,
                            &quot;examples&quot;: [&quot;CREATE2&quot;]
                        },
                        &quot;name&quot;: {
                            &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;name\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/name\&quot;}&quot;,
                            &quot;title&quot;: &quot;name&quot;,
                            &quot;description&quot;: &quot;Token name.&quot;,
                            &quot;type&quot;: &quot;string&quot;,
                            &quot;examples&quot;: [&quot;Matic&quot;]
                        },
                        &quot;symbol&quot;: {
                            &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;symbol\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/currency\&quot;}&quot;,
                            &quot;title&quot;: &quot;symbol&quot;,
                            &quot;description&quot;: &quot;Token symbol e.g. ETH.&quot;,
                            &quot;type&quot;: &quot;string&quot;,
                            &quot;examples&quot;: [&quot;MATIC&quot;]
                        },
                        &quot;humanReadableTokenSymbol&quot;: {
                            &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;humanReadableTokenSymbol\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/currency\&quot;}&quot;,
                            &quot;title&quot;: &quot;humanReadableTokenSymbol&quot;,
                            &quot;description&quot;: &quot;A Token symbol e.g. ETH, concatenated with the `chainId` the token was issued on or bridged to, e.g. ETH-1&quot;,
                            &quot;type&quot;: &quot;string&quot;,
                            &quot;examples&quot;: [&quot;MATIC-137&quot;]
                        },
                        &quot;decimals&quot;: {
                            &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;decimals\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/Number\&quot;}&quot;,
                            &quot;title&quot;: &quot;decimals&quot;,
                            &quot;description&quot;: &quot;Allowed number of decimals for the listed token. This property may be named differently by token standards e.g. granularity for ERC-777&quot;,
                            &quot;type&quot;: &quot;integer&quot;,
                            &quot;examples&quot;: [18]
                        },
                        &quot;logoURI&quot;: {
                            &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;logoURI\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/identifier\&quot;}&quot;,
                            &quot;title&quot;: &quot;logoURI&quot;,
                            &quot;description&quot;: &quot;URI or URL of the token logo following the RFC 3986 standard.&quot;,
                            &quot;type&quot;: &quot;string&quot;
                            &quot;examples&quot;: [&quot;https://polygonscan.com/token/images/matic_32.png&quot;]
                        },
                        &quot;createdAt&quot;: {
                            &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;createdAt\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/datePublished\&quot;}&quot;,
                            &quot;title&quot;: &quot;createdAt&quot;,
                            &quot;description&quot;: &quot;Date and time token was created&quot;,
                            &quot;type&quot;: &quot;string&quot;,
                            &quot;examples&quot;: [&quot;2020-05-31&quot;]
                        },
                        &quot;updatedAt&quot;: {
                            &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;updatedAt\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/dateModified\&quot;}&quot;,
                            &quot;title&quot;: &quot;updatedAt&quot;,
                            &quot;description&quot;: &quot;Date and time token was updated&quot;,
                            &quot;type&quot;: &quot;string&quot;
                            &quot;examples&quot;: [&quot;2020-05-31&quot;]
                        },
                        &quot;extensions&quot;: {
                            &quot;title&quot;: &quot;extensions&quot;,
                            &quot;description&quot;: &quot;Extension to the token list entry to specify an origin chain if the token entry refers to another chain other than the origin chain of the token&quot;,
                            &quot;type&quot;: &quot;array&quot;,
                            &quot;items&quot;: {
                                &quot;type&quot;:&quot;object&quot;,
                                &quot;required&quot;: [
                                    &quot;rootChainId&quot;,
                                    &quot;rootChainURI&quot;,
                                    &quot;rootAddress&quot;,
                                ],
                                &quot;properties&quot;: {
                                    &quot;rootChainId&quot;: {
                                        &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;rootChainId\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/identifier\&quot;}&quot;,
                                        &quot;title&quot;: &quot;rootChainId&quot;,
                                        &quot;description&quot;: &quot;The typically used number identifier for the root chain on which the token was originally issued.&quot;,
                                        &quot;type&quot;: &quot;number&quot;,
                                        &quot;examples&quot;: [137]
                                    },
                                    &quot;rootChainURI&quot;: {
                                        &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;rootChainURI\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/identifier\&quot;}&quot;,
                                        &quot;title&quot;: &quot;rootChainURI&quot;,
                                        &quot;description&quot;: &quot;A resolvable URI to the genesis block of the root chain on which the token was originally issued following the RFC 3986 standard.&quot;,
                                        &quot;type&quot;: &quot;string&quot;,
                                        &quot;examples&quot;: [&quot;https://polygonscan.com/block/0&quot;]
                                    },
                                    &quot;rootAddress&quot;: {
                                        &quot;$comment&quot;: &quot;{\&quot;term\&quot;: \&quot;rootAddress\&quot;, \&quot;@id\&quot;: \&quot;https://schema.org/identifier\&quot;}&quot;,
                                        &quot;title&quot;: &quot;rootAddress&quot;,
                                        &quot;description&quot;: &quot;Root address of the token smart contract.&quot;,
                                        &quot;type&quot;: &quot;string&quot;,
                                        &quot;examples&quot;: [&quot;0x0000000000000000000000000000000000001010&quot;]
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
    &quot;additionalProperties&quot;: false,
}
```

Data Schema Testability: As the above data schema follows a JSON/JSON-LD schema format, and since such formats are known to be testable for schema conformance (see for example the W3C CCG Traceability Work Item), the above data schema is testable.


### Conformance

This section describes the conformance clauses and tests required to achieve an implementation that is provably conformant with the requirements in this document.

#### Conformance Targets

This document does not yet define a standardized set of test-fixtures with test inputs for all MUST, SHOULD, and MAY requirements with conditional MUST or SHOULD requirements. 

A standardized set of test-fixtures with test inputs for all MUST, SHOULD, and MAY requirements with conditional MUST or SHOULD requirements is intended to be published with the next version of the standard.

#### Conformance Levels

This section specifies the conformance levels of this standard. The conformance levels offer implementers several levels of conformance. These can be used to establish competitive differentiation.

This document defines the conformance levels of a canonical token list as follows:

* **Level 1:** All MUST requirements are fulfilled by a specific implementation as proven by a test report that proves in an easily understandable manner the implementation&apos;s conformance with each requirement based on implementation-specific test-fixtures with implementation-specific test-fixture inputs.
* **Level 2:** All MUST and SHOULD requirements are fulfilled by a specific implementation as proven by a test report that proves in an easily understandable manner the implementation&apos;s conformance with each requirement based on implementation-specific test-fixtures with implementation-specific test-fixture inputs.
* **Level 3:** All MUST, SHOULD, and MAY requirements with conditional MUST or SHOULD requirements are fulfilled by a specific implementation as proven by a test report that proves in an easily understandable manner the implementation&apos;s conformance with each requirement based on implementation-specific test-fixtures with implementation-specific test-fixture inputs.

&lt;a name=&quot;d2&quot;&gt; **[D2]** &lt;/a&gt; 
A claim that a canonical token list implementation conforms to this specification SHOULD describe a testing procedure carried out for each requirement to which conformance is claimed, that justifies the claim with respect to that requirement.

[[D2]](#d2) testability: Since each of the non-conformance-target requirements in this documents is testable, so must be the totality of the requirements in this document. Therefore, conformance tests for all requirements can exist, and can be described as required in [[D2]](#d2).

&lt;a name=&quot;r5&quot;&gt; **[R5]** &lt;/a&gt; 
A claim that a canonical token list implementation conforms to this specification at **Level 2** or higher MUST describe the testing procedure carried out for each requirement at **Level 2** or higher, that justifies the claim to that requirement.

[[R5]](#r5) testability: Since each of the non-conformance-target requirements in this documents is testable, so must be the totality of the requirements in this document. Therefore, conformance tests for all requirements can exist, be described, be built and implemented and results can be recorded as required in [[R5]](#r5).


## Rationale

This specification is extending and clarifying current custom lists such as from Arbitrum and Optimism as referenced in the [Motivation](#motivation) or the Uniswap Tokenlist Project to improve clarity, security and encourage adoption by non-Web3 native entities.

The specification is utilizing the current JSON-LD standard to describe a token list to allow for easy integrations with Self-Sovereign-Identity frameworks such as W3C DID and W3C Verifiable Credential standards that allow for interoperability across L2s, Sidechains and L1s when identifying token list relevant entities such as Token Issuers. In addition, being compatible to W3C utilized frameworks allows implementers to use existing tooling around JSON-LD, W3C DIDs and W3C Verifiable Credentials. The choice of referencing known data property definitions from schema.org further disambiguates the meaning and usage of terms.

## Security Considerations

There are no additional security requirements apart from the warnings that URIs utilized in implementations of this standard might be direct to malicious resources such as websites, and that implementers should ensure that data utilized for a canonical token list is secure and correct. Since this standard is focused on a data schema and its data properties there are no additional security considerations from for example homoglyph attacks (see [CVE-2021-42574 (2021-10-25T12:38:28)](https://nvd.nist.gov/vuln/detail/CVE-2021-42574)).

### Security Considerations: Data Privacy

The standard does not set any requirements for compliance to jurisdiction legislation/regulations. It is the responsibility of the implementer to comply with applicable data privacy laws.

### Security Considerations: Production Readiness 

The standard does not set any requirements for the use of specific applications/tools/libraries etc. The implementer should perform due diligence when selecting specific applications/tools/libraries.

### Security Considerations: Internationalization and Localization

The standard encourages implementers to follow the [W3C &quot;Strings on the Web: Language and Direction Metadata&quot; best practices guide](https://www.w3.org/TR/2022/DNOTE-string-meta-20220804/) for identifying language and base direction for strings used on the Web wherever appropriate.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 20 Mar 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6734</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6734</guid>
      </item>
    
      <item>
        <title>L2 Aliasing of EVM-based Addresses</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/l2-aliasing-of-evm-based-addresses-from-the-eea-oasis-community-projects-l2-standards-working-group/13093</comments>
        
        <description>## Abstract

The document describes the minimal set of business and technical prerequisites, functional and non-functional requirements for Aliasing of EVM based Addresses that when implemented ensures that two or more Layer 1, Layer 2, or Sidechains can identify and translate EVM based addresses from different Layer 1, Layer 2, or Sidechains.

## Motivation

The members of the L2 WG of the EEA Communities Project managed by OASIS have recognized that the ability to deterministically derive addresses of a digital asset or an externally owned account (EOA) in EVM based execution frameworks for L1s, L2s, Sidechains based on an origin chain of an asset or EOA, known as address aliasing, simplifies interoperability between EVM based L1s, L2s, and Sidechains because: 

 * It allows messages from chain A (source chain) to unambiguously address asset A (smart contract) or EOA on chain Y (target chain), if asset A or EOA exists on Chain X and on Chain Y. 
 * It allows a user to deterministically verify the source chain of a message, and, if required, directly verify the origin chain of asset A or EOA and its state on its origin chain utilizing a canonical token list of the (message) source chain.

The ability to unambiguously, and deterministically, relate an address for a digital asset (smart contract) or an externally owned account (EOA) between EVM based L1s, L2s, and Sidechains where this digital asset or EOA exists, also known as address aliasing, is critical prerequisite for interoperability between EVM based L1s, L2s, and Sidechains. However, there is currently no way to do so in a standardized way -- imagine every internet service provider were to define its own IP addresses.

Hence, the L2 WG of the EEA Communities Project managed by OASIS, an open-source initiative, intends for this document to establish an unambiguous and deterministic standard for EVM based address aliasing based on the concept of root &amp;rarr; leaf where an address alias is derived based on the address on the origin chain and an offset which is an immutable characteristic of the origin chain.

See Figure 1 for the conceptual root &amp;rarr; leaf design with offset.

![Fig1](/EIPs/assets/eip-6735/address-aliasing-root-leaf-design.png)

Figure 1: Root &amp;rarr; Leaf address aliasing concept using an chain immanent characteristics from L1 to L2 and L3 and back.

Alternative Figure 1 Description: The figure describes conceptually how (interoperability) messages from source to target chain utilize address aliasing. At the bottom an EVM based L1 is uni-directionally connected to three EVM based L2s -- A, B, and C -- each with an alias of L1 address + L1 Offset. In addition, A is uni-directionally connected to B with an alias of L1 address + L1 offset + A offset. B is uni-directionally connected to an EVM-based Layer 3 or L3 with an alias of L1 address + L1 offset + B offset signaling that the address is anchored on L1 via the L2 B. And finally D is uni-directionally connected to C via the alias L1 address + L1 offset + B offset plus D offset indicating the asset chain of custody from L1 to B to D to C.

To further clarify the connections between the different possible paths an asset can take from an L1 to different L2/L3s and the `relativeAddress` of that asset, we visually highlight in red the path from the EVM based L1 to the B L2, to the D L3, and finally to the C L2.

![Fig2](/EIPs/assets/eip-6735/visual-Highlight-Path-Red-evm-based-aliasing..png)

Figure 2: Visually highlighted path in red from the EVM based L1 to the B L2, to the D L3, and finally to the C L2.

Alternative Figure 1 Description: The figure is the same as Figure 1. However, the uni-directional connections between the EVM based L1 to the L2 B, to the L3 D, and finally to the L2 C are highlighted in red.

Note, that address aliasing between non-EVM and EVM-based L1s, L2s, and Sidechains, and between non-EVM-based L1s, L2s, and Sidechains is out of scope of this document.

## Specification

### Typographical Convention: Requirement Ids

A requirement is uniquely identified by a unique ID composed of its requirement level followed by a requirement number, as per convention **[RequirementLevelRequirementNumber]**. 
There are four requirement levels that are coded in requirement ids as per below convention: 

**[R]** - The requirement level for requirements which IDs start with the letter _R_ is to be interpreted as **MUST** as described in [RFC2119](https://www.rfc-editor.org/rfc/rfc2119). \
**[D]** - The requirement level for requirements which IDs start with the letter _D_ is to be interpreted as **SHOULD** as described in [RFC2119](https://www.rfc-editor.org/rfc/rfc2119). \
**[O]** - The requirement level for requirements which IDs start with the letter _O_ is to be interpreted as **MAY** as described in [RFC2119](https://www.rfc-editor.org/rfc/rfc2119). 

Note that requirements are uniquely numbered in ascending order within each requirement level.

Example : It should be read that [R1] is an absolute requirement of the specification whereas [D1] is a recommendation and [O1] is truly optional.

The requirements below are only valid for EVM based L1s, L2, or Sidechains. Address aliasing for non-EVM systems is out of scope of this document.

&lt;a name=&quot;r1&quot;&gt; **[R1]** &lt;/a&gt;
An address alias -- `addressAlias` -- to be used between Chain A and Chain B MUST be constructed as follows:
`addressAlias (Chain A) = offsetAlias (for Chain A) relativeAddress (on Chain A) offsetAlias (for Chain A)`

[[R1]](#r1) testability: `addressAlias` can be parsed and split using existing open source packages and the result compared to known `addressAlias` and `relativeAddress` used in the construction.

&lt;a name=&quot;r2&quot;&gt; **[R2]** &lt;/a&gt;
The `offsetAlias` of a chain MUST be `0xchainId00000000000000000000000000000000chainId`

[[R2]](#r2) testability: `offsetAlias` can be parsed and split using existing open source packages and the result compared to known `chainId` used in the construction.

&lt;a name=&quot;r3&quot;&gt; **[R3]** &lt;/a&gt;
The `chainId` used in the `offsetAlias` MUST NOT be zero (0)

[[R3]](#r3) testability: A `chainId` is a numerical value and can be compared to `0`.

&lt;a name=&quot;r4&quot;&gt; **[R4]** &lt;/a&gt;
The `chainId` used in the `offsetAlias` MUST be 8 bytes.

[[R4]](#r4) testability: The length of the `chainId` string can be converted to bytes and then compared to `8`.

&lt;a name=&quot;r5&quot;&gt; **[R5]** &lt;/a&gt;
In case the `chainId` has less than 16 digits the `chainId` MUST be padded with zeros to 16 digits.

For example the `chainId` of Polygon PoS is `137`, with the current list of EVM based `chainId`s to be found at chainlist.org, and its `offsetAlias` is `0x0000000000000137000000000000000000000000000000000000000000000137`.

[[R5]](#r5) testability: `chainId` can be parsed and split using existing open source packages and the result compared to known `chainId` used in the construction. Subsequently the number of zeros used in the padding can be computed and compared to the expected number of zeros for the padding.

&lt;a name=&quot;r6&quot;&gt; **[R6]** &lt;/a&gt;
The `offsetAlias`for Ethereum Mainnet as the primary anchor of EVM based chains MUST be `0x1111000000000000000000000000000000001111` due to current adoption of this offset by existing L2 solutions.

An example of address alias for the USDC asset would be `addressAlias = 0x1111A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB481111` 

[[R6]](#r6) testability: This requirement is a special case of [[R1]](#r1). Hence, it is testable. 

&lt;a name=&quot;r7&quot;&gt; **[R7]** &lt;/a&gt;
The `relativeAddress` of an Externally Owned Account (EOA) or Smart Contract on a chain MUST either be the smart contract or EOA address of the origin chain or a `relativeAddress` of an EOA or Smart Contract from another chain.  

An example of the former instance would be the relative address of wrapped USDC, `relativeAddress = 0x1111A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB481111`, and an example of the latter would be the relative address of wrapped USDC on Polygon, `relativeAddress = 0x00000000000001371111A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB4811110000000000000137`.

Finally, an example of an address alias for a message to another L1, L2, or Sidechain for wrapped USDC from Ethereum on Arbitrum would be:

```
addressAlias = 0x00000000000421611111A0b86991c6218b36c1d19D4a2e9Eb0cE3606eB4811110000000000042161
```

[[R7]](#r7) testability: Since this document is dealing with EVM-based systems with multiple live implementations, there are multiple known methods of how to verify if an address belongs to an EOA or a smart contract.

&lt;a name=&quot;r8&quot;&gt; **[R8]** &lt;/a&gt;
The order of the `offsetAlias`es in an `addressAlias` MUST be ordered from the `offSetAlias` of the root chain bracketing the `relativeAddress` on the root chain through the ordered sequence of `offsetAlias`es of the chains on which the digital asset exists.

For example, a valid `addressAlias` of an asset on chain A bridged to chain B and subsequently to chain C and that is to be bridged to yet another chain from chain C would be:

```
addressAlias = chainId(C) chainId(B) chainId(A) relativeAddress chainId(A) chainId(B) chainId(C)
```   

However, the reverse order is invalid:

```
addressAlias = chainId(A) chainId(B) chainId(C) relativeAddress chainId(C) chainId(B) chainId(A)
```  

[[R8]](#r8) testability: Since [[R1]](#r1) is testable and since [[R8]](#r8) is an order rule for the construction in [[R1]](#r1), which can be tested by applying logic operations on the output of [[R1]](#r1) tests, [[R8]](#r8) is testable. 

Note, that a proof that a given order is provably correct is beyond the scope of this document.

### Conformance

This section describes the conformance clauses and tests required to achieve an implementation that is provably conformant with the requirements in this document.

#### Conformance Targets

This document does not yet define a standardized set of test-fixtures with test inputs for all MUST, SHOULD, and MAY requirements with conditional MUST or SHOULD requirements. 

A standardized set of test-fixtures with test inputs for all MUST, SHOULD, and MAY requirements with conditional MUST or SHOULD requirements is intended to be published with the next version of the standard.

#### Conformance Levels

This section specifies the conformance levels of this standard. The conformance levels offer implementers several levels of conformance. These can be used to establish competitive differentiation.

This document defines the conformance levels of EVM based Address Aliasing as follows:

* **Level 1:** All MUST requirements are fulfilled by a specific implementation as proven by a test report that proves in an easily understandable manner the implementation&apos;s conformance with each requirement based on implementation-specific test-fixtures with implementation-specific test-fixture inputs.
* **Level 2:** All MUST and SHOULD requirements are fulfilled by a specific implementation as proven by a test report that proves in an easily understandable manner the implementation&apos;s conformance with each requirement based on implementation-specific test-fixtures with implementation-specific test-fixture inputs.
* **Level 3:** All MUST, SHOULD, and MAY requirements with conditional MUST or SHOULD requirements are fulfilled by a specific implementation as proven by a test report that proves in an easily understandable manner the implementation&apos;s conformance with each requirement based on implementation-specific test-fixtures with implementation-specific test-fixture inputs.

&lt;a name=&quot;d1&quot;&gt; **[D1]** &lt;/a&gt;
A claim that a canonical token list implementation conforms to this specification SHOULD describe a testing procedure carried out for each requirement to which conformance is claimed, that justifies the claim with respect to that requirement.

[[D1]](#d1) testability: Since each of the non-conformance-target requirements in this documents is testable, so must be the totality of the requirements in this document. Therefore, conformance tests for all requirements can exist, and can be described as required in [[D1]](#d1).

&lt;a name=&quot;r9&quot;&gt; **[R9]** &lt;/a&gt;
A claim that a canonical token list implementation conforms to this specification at **Level 2** or higher MUST describe the testing procedure carried out for each requirement at **Level 2** or higher, that justifies the claim to that requirement.

[[R9]](#r9) testability: Since each of the non-conformance-target requirements in this documents is testable, so must be the totality of the requirements in this document. Therefore, conformance tests for all requirements can exist, be described, be built and implemented and results can be recorded as required in [[R9]](#r9).

## Rationale

The standard follows an already existing approach for address aliasing from Ethereum (L1) to EVM-based L2s such as Arbitrum and Optimism and between L2s, and extends and generalizes it to allow aliasing across any type of EVM-based network irrespective of the network type -- L1, L2 or higher layer networks.

## Security Considerations

### Data Privacy

The standard does not set any requirements for compliance to jurisdiction legislation/regulations. It is the responsibility of the implementer to comply with applicable data privacy laws.

### Production Readiness 

The standard does not set any requirements for the use of specific applications/tools/libraries etc. The implementer should perform due diligence when selecting specific applications/tools/libraries.

There are security considerations as to the Ethereum-type addresses used in the construction of the `relativeAddress`.

If the Ethereum-type address used in the `relativeAddress` is supposed to be an EOA, the target system/recipient should validate that the `codehash` of the source account is `NULL` such that no malicious code can be executed surreptitiously in an asset transfer.

If the Ethereum-type address used in the `relativeAddress` is supposed to be a smart contract account representing an asset, the target system/recipient should validate that the `codehash` of the source account matches the `codehash` of the published smart contract solidity code to ensure that the source smart contract behaves as expected.

Lastly, it is recommended that as part of the `relativeAddress` validation the target system performs an address checksum validation as defined in [ERC-55](/EIPs/EIPS/eip-55).

### Internationalization and Localization

Given the non-language specific features of EVM-based address aliasing, there are no internationalization/localization considerations.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 20 Mar 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6735</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6735</guid>
      </item>
    
      <item>
        <title>SELFDESTRUCT only in same transaction</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/deactivate-selfdestruct-except-where-it-occurs-in-the-same-transaction-in-which-a-contract-was-created/13539</comments>
        
        <description>## Abstract

This EIP changes the functionality of the `SELFDESTRUCT` opcode. The new functionality will be only to send all Ether in the account to the target, except that the current behaviour is preserved when `SELFDESTRUCT` is called in the same transaction a contract was created.

## Motivation

The `SELFDESTRUCT` opcode requires large changes to the state of an account, in particular removing all code and storage. This will not be possible in the future with Verkle trees: Each account will be stored in many different account keys, which will not be obviously connected to the root account.

This EIP implements this change. Applications that only use `SELFDESTRUCT` to retrieve funds will still work. Applications that only use `SELFDESTRUCT` in the same transaction as they created a contract will also continue to work without any changes.

## Specification

The behaviour of `SELFDESTRUCT` is changed in the following way:

1. When `SELFDESTRUCT` is executed in a transaction that is not the same as the contract calling `SELFDESTRUCT` was created:

   - The current execution frame halts.
   - `SELFDESTRUCT` does not delete any data (including storage keys, code, or the account itself).
   - `SELFDESTRUCT` transfers the entire account balance to the target.
   - Note that if the target is the same as the contract calling `SELFDESTRUCT` there is no net change in balances.  Unlike the prior specification, Ether will not be burnt in this case.
   - Note that no refund is given since [EIP-3529](/EIPs/EIPS/eip-3529).
   - Note that the rules of [EIP-2929](/EIPs/EIPS/eip-2929) regarding `SELFDESTRUCT` remain unchanged.
  
2. When `SELFDESTRUCT` is executed in the same transaction as the contract was created: 

   - `SELFDESTRUCT` continues to behave as it did prior to this EIP, this includes the following actions
     - The current execution frame halts.
     - `SELFDESTRUCT` deletes data as previously specified.
     - `SELFDESTRUCT` transfers the entire account balance to the target
     - The account balance of the contact calling `SELFDESTRUCT` is set to `0`.
   - Note that if the target is the same as the contract calling `SELFDESTRUCT` that Ether will be burnt.
   - Note that no refund is given since [EIP-3529](/EIPs/EIPS/eip-3529).
   - Note that the rules of [EIP-2929](/EIPs/EIPS/eip-2929) regarding `SELFDESTRUCT` remain unchanged.

A contract is considered created at the beginning of a create transaction or when a CREATE series operation begins execution (CREATE, CREATE2, and other operations that deploy contracts in the future).  If a balance exists at the contract&apos;s new address it is still considered to be a contract creation. 

The `SELFDESTRUCT` opcode remains deprecated as specified in [EIP-6049](/EIPs/EIPS/eip-6049). Any use in newly deployed contracts is strongly discouraged even if this new behaviour is taken into account, and future changes to the EVM might further reduce the functionality of the opcode.

## Rationale

Getting rid of the `SELFDESTRUCT` opcode has been considered in the past, and there are currently no strong reasons to use it. This EIP implements a behavior that will attempt to leave some common uses of `SELFDESTRUCT` working, while reducing the complexity of the change on EVM implementations that would come from contract versioning.

Handling the account creation and contract creation as two distinct and possibly separate events is needed for use cases such as counterfactual accounts.  By allowing the `SELFDESTRUCT` to delete the account at contract creation time it will not result in stubs of counterfactually instantiated contracts that never had any on-chain state other than a balance prior to the contract creation. These accounts would never have any storage and thus the trie updates to delete the account would be limited to the account node, which is the same impact a regular transfer of ether would have.

## Backwards Compatibility

This EIP requires a hard fork, since it modifies consensus rules.

Contracts that depended on re-deploying contracts at the same address using `CREATE2` (after a `SELFDESTRUCT`) will no longer function properly if the created contract does not call `SELFDESTRUCT` within the same transaction.

Previously it was possible to burn ether by calling `SELFDESTRUCT` targeting the executing contract as the beneficiary.  If the contract existed prior to the transaction the ether will not be burned.  If the contract was newly created in the transaction the ether will be burned, as before.

## Test Cases 

Test cases for this EIP can be found in the Execution Spec Tests suite [`eip6780_selfdestruct`](https://github.com/ethereum/execution-spec-tests/tree/1983444bbe1a471886ef7c0e82253ffe2a4053e1/tests/cancun/eip6780_selfdestruct).

## Security Considerations

The following applications of `SELFDESTRUCT` will be broken and applications that use it in this way are not safe anymore:

1. Where `CREATE2` is used to redeploy a contract in the same place in order to make a contract upgradable. This is not supported anymore and [ERC-2535](/EIPs/EIPS/eip-2535) or other types of proxy contracts should be used instead.

2. Where a contract depended on burning Ether via a `SELFDESTRUCT` with the contract as beneficiary, in a contract not created within the same transaction.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 25 Mar 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6780</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6780</guid>
      </item>
    
      <item>
        <title>ERC-721 Utilities Information Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6785-erc-721-utilities-extension/13568</comments>
        
        <description>## Abstract

This specification defines standard functions and an extension of the metadata schema that outlines what a 
token&apos;s utility entails and how the utility may be used and/or accessed.
This specification is an optional extension of [ERC-721](/EIPs/EIPS/eip-721).

## Motivation

This specification aims to clarify what the utility associated with an NFT is and how to access this utility.
Relying on third-party platforms to obtain information regarding the utility of the NFT that one owns can lead to scams,
phishing or other forms of fraud.

Currently, utilities that are offered with NFTs are not captured on-chain. We want the utility of an NFT to be part of
the metadata of an NFT. The metadata information would include: a) type of utility, b) description
of utility, c) frequency and duration of utility, and d) expiration of utility. This will provide transparency as to the
utility terms, and greater accountability on the creator to honor these utilities.

As the instructions on how to access a given utility may change over time, there should be a historical record of these
changes for transparency.

## Specification

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.

Every contract compliant with [ERC-6785](/EIPs/EIPS/eip-6785) MUST implement the interface defined as follows:

### Contract Interface

```solidity
// @title NFT Utility description
///  Note: the EIP-165 identifier for this interface is ed231d73

interface IERC6785 {

    // Logged when the utility description URL of an NFT is changed
    /// @notice Emitted when the utilityURL of an NFT is changed
    /// The empty string for `utilityUri` indicates that there is no utility associated
    event UpdateUtility(uint256 indexed tokenId, string utilityUri);

    /// @notice set the new utilityUri - remember the date it was set on
    /// @dev The empty string indicates there is no utility
    /// Throws if `tokenId` is not valid NFT
    /// @param utilityUri  The new utility description of the NFT
    /// 4a048176
    function setUtilityUri(uint256 tokenId, string utilityUri) external;

    /// @notice Get the utilityUri of an NFT
    /// @dev The empty string for `utilityUri` indicates that there is no utility associated
    /// @param tokenId The NFT to get the user address for
    /// @return The utility uri for this NFT
    /// 5e470cbc
    function utilityUriOf(uint256 tokenId) external view returns (string memory);

    /// @notice Get the changes made to utilityUri
    /// @param tokenId The NFT to get the user address for
    /// @return The history of changes to `utilityUri` for this NFT
    /// f96090b9
    function utilityHistoryOf(uint256 tokenId) external view returns (string[] memory);
}
```

All functions defined as view MAY be implemented as pure or view

Function `setUtilityUri` MAY be implemented as public or external. Also, the ability to set the `utilityUri` SHOULD be
restricted to the one who&apos;s offering the utility, whether that&apos;s the NFT creator or someone else.

The event `UpdateUtility` MUST be emitted when the `setUtilityUri` function is called or any other time that the utility
of the token is changed, like in batch updates. 

The method `utilityHistoryOf` MUST reflect all changes made to the `utilityUri` of a tokenId, whether that&apos;s done 
through `setUtilityUri` or by any other means, such as bulk updates

The `supportsInterface` method MUST return true when called with `ed231d73`

The original metadata SHOULD conform to the “ERC-6785 Metadata with utilities JSON Schema” which is a compatible
extension of the “ERC-721 Metadata JSON Schema” defined in ERC-721.

“ERC-6785 Metadata with utilities JSON Schema” :

```json
{
  &quot;title&quot;: &quot;Asset Metadata&quot;,
  &quot;type&quot;: &quot;object&quot;,
  &quot;properties&quot;: {
    &quot;name&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Identifies the asset to which this NFT represents&quot;
    },
    &quot;description&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Describes the asset to which this NFT represents&quot;
    },
    &quot;image&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive.&quot;
    },
    &quot;utilities&quot;: {
      &quot;type&quot;: &quot;object&quot;,
      &quot;required&quot;: [
        &quot;type&quot;,
        &quot;description&quot;,
        &quot;t&amp;c&quot;
      ],
      &quot;properties&quot;: {
        &quot;type&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;Describes what type of utility this is&quot;
        },
        &quot;description&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;A brief description of the utility&quot;
        },
        &quot;properties&quot;: {
          &quot;type&quot;: &quot;array&quot;,
          &quot;description&quot;: &quot;An array of possible properties describing the utility, defined as key-value pairs&quot;,
          &quot;items&quot;: {
            &quot;type&quot;: &quot;object&quot;
          }
        },
        &quot;expiry&quot;: {
          &quot;type&quot;: &quot;number&quot;,
          &quot;description&quot;: &quot;The period of time for the validity of the utility, since the minting of the NFT. Expressed in seconds&quot;
        },
        &quot;t&amp;c&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;&quot;
        }
      }
    }
  }
}
```

## Rationale

Since the `utilityUri` could contain information that has to be restricted to some level and could be dependent on an
off-chain tool for displaying said information, the creator needs the ability to modify it in the event the off-chain
tool or platform becomes unavailable or inaccessible. 

For transparency purposes, having a `utilityHistoryOf` method will make it clear how the `utilityUri` has changed over 
time.

For example, if a creator sells an NFT that gives holders a right to a video call with the creator, the metadata for
this utility NFT would read as follows:

```json
{
  &quot;name&quot;: &quot;...&quot;,
  &quot;description&quot;: &quot;...&quot;,
  &quot;image&quot;: &quot;...&quot;,
  &quot;utilities&quot;: {
    &quot;type&quot;: &quot;Video call&quot;,
    &quot;description&quot;: &quot;I will enter a private video call with whoever owns the NFT&quot;,
    &quot;properties&quot;: [
      {
        &quot;sessions&quot;: 2
      },
      {
        &quot;duration&quot;: 30
      },
      {
        &quot;time_unit&quot;: &quot;minutes&quot;
      }
    ],
    &quot;expiry&quot;: 1.577e+7,
    &quot;t&amp;c&quot;: &quot;https://....&quot;
  }
}
```

In order to get access to the details needed to enter the video call, the owner would access the URI returned by
the `getUtilityUri` method for the NFT that they own. Additionally, access to the details could be conditioned by the
authentication with the wallet that owns the NFT.

The current status of the utility would also be included in the URI (eg: how many sessions are still available, etc.)

## Backwards Compatibility

This standard is compatible with current ERC-721 standard. There are no other standards that define similar methods for
NFTs and the method names are not used by other ERC-721 related standards.

## Test Cases

Test cases are available [here](/EIPs/assets/eip-6785/test/ERC6785.test.js)

## Reference Implementation

The reference implementation can be found [here](/EIPs/assets/eip-6785/contracts/ERC6785.sol).

## Security Considerations

There are no security considerations related directly to the implementation of this standard.

## Copyright

Copyright and related rights waived via [CC0-1.0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 27 Mar 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6785</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6785</guid>
      </item>
    
      <item>
        <title>Registry for royalties payment for NFTs</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6786-royalty-debt-registry/13569</comments>
        
        <description>## Abstract

This standard allows anyone to pay royalties for a certain NFT and also to keep track of the royalties amount paid. It will cumulate the value each time a payment is executed through it and make the information public.

## Motivation

There are many marketplaces which do not enforce any royalty payment to the NFT creator every time the NFT is sold or re-sold and/or providing a way for doing it. There are some marketplaces which use specific system of royalties, however that system is applicable for the NFTs creates on their platform.

In this context, there is a need of a way for paying royalties, as it is a strong incentive for creators to keep contributing to the NFTs ecosystem.

Additionally, this standard will provide a way of computing the amount of royalties paid to a creator for a certain NFT. This could be useful in the context of categorising NFTs in terms of royalties. The term “debt“ is used because the standard aims to provide a way of knowing if there are any royalties left unpaid for the NFTs trades that took place in a marketplace that does not support them and, in that case, expose a way of paying them.

With a lot of places made for trading NFTs dropping down the royalty payment or having a centralised approach, we want to provide a way for anyone to pay royalties to the creators.

Not only the owner of it, but anyone could pay royalties for a certain NFT. This could be a way of supporting a creator for his work.

## Specification

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.

Every contract compliant with [ERC-6786](/EIPs/EIPS/eip-6786) MUST implement the interface defined as follows:

### Contract Interface

```solidity
// @title Royalty Debt Registry
/// Note: the ERC-165 identifier for this interface is 0x253b27b0

interface IERC6786 {

    // Logged when royalties were paid for a NFT
    /// @notice Emitted when royalties are paid for the NFT with address tokenAddress and id tokenId
    event RoyaltiesPaid(address indexed tokenAddress, uint256 indexed tokenId, uint256 amount);

    /// @notice sends msg.value to the creator of a NFT
    /// @dev Reverts if there are no on-chain informations about the creator
    /// @param tokenAddress The address of NFT contract
    /// @param tokenId The NFT id
    function payRoyalties(address tokenAddress, uint256 tokenId) external payable;

    /// @notice Get the amount of royalties which was paid for a NFT
    /// @dev 
    /// @param tokenAddress The address of NFT contract
    /// @param tokenId The NFT id
    /// @return The amount of royalties paid for the NFT
    function getPaidRoyalties(address tokenAddress, uint256 tokenId) external view returns (uint256);
}
```

All functions defined as view MAY be implemented as pure or view

Function `payRoyalties`  MAY be implemented as public or external

The event `RoyaltiesPaid` MUST be emitted when the payRoyalties function is called

The `supportsInterface` function MUST return true when called with `0x253b27b0`

## Rationale

The payment can be made in native coins, so it is easy to aggregate the amount of paid royalties. We want this information to be public, so anyone could tell if a creator received royalties in case of under the table trading or in case of marketplaces which don’t support royalties.

The function used for payment can be called by anyone (not only the NFTs owner) to support the creator at any time. There is a way of seeing the amount of paid royalties in any token, also available for anyone.

For fetching creator on-chain data we will use [ERC-2981](/EIPs/EIPS/eip-2981), but any other on-chain method of getting the creator address is accepted.

## Backwards Compatibility

This ERC is not introducing any backward incompatibilities.

## Test Cases

Tests are included in [`ERC6786.test.js`](/EIPs/assets/eip-6786/test/ERC6786.test.js).

To run them in terminal, you can use the following commands:

```
cd ../assets/eip-6786
npm install
npx hardhat test
```

## Reference Implementation

See [`ERC6786.sol`](/EIPs/assets/eip-6786/contracts/ERC6786.sol).

## Security Considerations

There are no security considerations related directly to the implementation of this standard.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 27 Mar 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6786</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6786</guid>
      </item>
    
      <item>
        <title>Order Book DEX with Two Phase Withdrawal</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/order-book-dex-standard/13573</comments>
        
        <description>## Abstract

The Order Book DEX Standard is a proposed set of interface specifications that define a decentralized exchange (DEX) protocol for trading assets using order books. This standard provides a set of functions that allow users to deposit, withdraw, and trade assets on a decentralized exchange. Additionally, it proposes a novel two-phase withdrawal scheme to ensure the asset security of both users and the exchange, addressing users&apos; trust issues with the exchange.

## Motivation

Decentralized exchanges (DEXs) have become increasingly popular in recent years due to their ability to provide users with greater control over their assets and reduce reliance on centralized intermediaries. However, many existing DEX protocols suffer from issues such as low liquidity and inefficient price discovery. Order book-based DEXs based Layer2 have emerged as a popular alternative, but there is currently no standardized interface for implementing such exchanges.

The Order Book DEX Standard aims to provide developers with a common interface for building interoperable order book-based DEXs that can benefit from network effects. By establishing a standard set of functions for depositing, withdrawing, and forced withdrawals, the Order Book DEX Standard can fully ensure the security of user assets. At the same time, the two-phase forced withdrawal mechanism can also prevent malicious withdrawals from users targeting the exchange.

The two phase commit protocol is an important distributed consistency protocol, aiming to ensure data security and consistency in distributed systems. In the Layer2 order book DEX system, to enhance user experience and ensure financial security, we adopt a 1:1 reserve strategy, combined with a decentralized clearing and settlement interface, and a forced withdrawal function to fully guarantee users&apos; funds.

However, such design also faces potential risks. When users engage in perpetual contract transactions, they may incur losses. In this situation, malicious users might exploit the forced withdrawal function to evade losses. To prevent this kind of attack, we propose a two-phase forced withdrawal mechanism.

By introducing the two phase forced withdrawal function, we can protect users&apos; financial security while ensuring the security of the exchange&apos;s assets. In the first phase, the system will conduct a preliminary review of the user&apos;s withdrawal request to confirm the user&apos;s account status. In the second phase, after the forced withdrawal inspection period, users can directly submit the forced withdrawal request to complete the forced withdrawal process. In this way, we can not only prevent users from exploiting the forced withdrawal function to evade losses but also ensure the asset security for both the exchange and the users.

In conclusion, by adopting the two phase commit protocol and the two phase forced withdrawal function, we can effectively guard against malicious behaviors and ensure data consistency and security in distributed systems while ensuring user experience and financial security.

## Specification

### Interfaces

The Order Book DEX Standard defines the following Interfaces:

#### `deposit`

`function deposit(address token, uint256 amount) external;`

The **deposit** function allows a user to deposit a specified amount of a particular token to the exchange. The *token* parameter specifies the address of the token contract, and the *amount* parameter specifies the amount of the token to be deposited.

#### `withdraw`

`function withdraw(address token, uint256 amount) external;`

The **withdraw** function allows a user to withdraw a specified amount of a particular token from the exchange. The *token* parameter specifies the address of the token contract, and the *amount* parameter specifies the amount of the token to be withdrawn.

#### `prepareForceWithdraw`

`function prepareForceWithdraw(address token, uint256 amount) external returns (uint256 requestID);`

The assets deposited by users will be stored in the exchange contract&apos;s account, and the exchange can achieve real-time 1:1 reserve proof. The **prepareForceWithdraw** function is used for users to initiate a forced withdrawal of a certain amount of a specified token. This function indicates that the user wants to perform a forced withdrawal and can submit the withdrawal after the default timeout period. Within the timeout period, the exchange needs to confirm that the user&apos;s order status meets the expected criteria, and forcibly cancel the user&apos;s order and settle the trade to avoid malicious attacks by the user. This function takes the following parameters:

1. *token*: the address of the token to be withdrawn
2. *amount*: the amount of the token to be withdrawn

Since an account may initiate multiple two phase forced withdrawals in parallel, each forced withdrawal needs to return a unique *requestID*. The function returns a unique *requestID* that can be used to submit the forced withdrawal using the commitForceWithdraw function.

#### `commitForceWithdraw`

`function commitForceWithdraw(uint256 requestID) external;`

1. *requestID*: the request ID of the two phase Withdraw

The **commitForceWithdraw** function is used to execute a forced withdrawal operation after the conditions are met. The function takes a *requestID* parameter, which specifies the ID of the forced withdrawal request to be executed. The request must have been previously initiated using the prepareForceWithdraw function.

### Events

#### `PrepareForceWithdraw`

MUST trigger when user successful call to PrepareForceWithdraw.

`event PrepareForceWithdraw(address indexed user, address indexed tokenAddress, uint256 amount);`

## Rationale

The flow charts for two-phase withdrawal are shown below:

![](/EIPs/assets/eip-6787/image1.png)

## Backwards Compatibility

No backward compatibility issues found.

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 27 Mar 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6787</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6787</guid>
      </item>
    
      <item>
        <title>Rename gas to mana</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6789-rename-gas-to-mana/13570</comments>
        
        <description>## Abstract

This EIP suggests renaming `gas` to `mana`, as proposed by Vitalik Buterin in 2015.

## Motivation

The underlying motivation for reviving Vitalik&apos;s original proposal from 2015 is that we have finally arrived at the age of Proof-of-Stake, and given the roadmap ahead (i.e. &quot;The Surge&quot;, &quot;The Scourge&quot;, &quot;The Verge&quot;, &quot;The Purge&quot;, and &quot;The Splurge&quot;), I consider this moment as the last opportunity to make such a far-reaching semantic change.

## Specification

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

The core term `gas` MUST be renamed to `mana`.

The following opcodes MUST be renamed:

- `GASPRICE` to `MANAPRICE`;
- `GASLIMIT` to `MANALIMIT`; and
- `GAS` to `MANA`.

Additionally, the input parameters or outputs of the following opcodes MUST be renamed:

- `CALL`&apos;s `gas` input parameter to `mana`;
- `CALLCODE`&apos;s `gas` input parameter to `mana`;
- `DELEGATECALL`&apos;s `gas` input parameter to `mana`;
- `STATICCALL`&apos;s `gas` input parameter to `mana`;
- `GASLIMIT`&apos;s `gasLimit` output to `manaLimit`; and
- `GAS`&apos;s `gas` output to `mana`.

Finally, the following RPC endpoints MUST be renamed:

- `eth_estimateGas` to `eth_estimateMana`;
- `eth_gasPrice` to `eth_manaPrice`; and
- `eth_maxPriorityFeePerGas` to `eth_maxPriorityFeePerMana`.

The description of the RPC endpoints MUST be renamed accordingly:

- `eth_estimateMana`: Generates and returns an estimate of how much `mana` is necessary to allow the transaction to complete;
- `eth_manaPrice`: Returns the current price per `mana` in wei; and
- `eth_maxPriorityFeePerMana`: Returns the current `maxPriorityFeePerMana` per `mana` in wei.

## Rationale

- `mana` reflects the increased environmental friendliness of Proof-of-Stake;
- `mana` is generally understood to be ephemeral and non-transferable, which better represents the concept of `gas`; and
- `mana` is generally portrayed as renewable, while (natural) `gas` is non-renewable.

## Backwards Compatibility

This proposal is not backward compatible as it renames the core term `gas`.

## Test Cases

### Example 1

If a transaction requires more `mana` than allowed by the `manaLimit`, it is reverted as an _out-of-mana_ transaction.

### Example 2

A Solidity contract to estimate the used `mana` via the new `manaleft()` syntax (replacing `gasleft()`) for dedicated function calls.

```solidity
// SPDX-License-Identifier: AGPL-3.0
pragma solidity 0.8.19;

contract ManaMetering {
    function oldWay() external view returns (string memory, uint256 manaUsed) {
        string memory hiMom = &quot;Hi Mom, &quot;;
        string memory missYou = &quot;miss you.&quot;;
        uint256 startMana = manaleft();
        string memory concat = string(abi.encodePacked(hiMom, missYou));
        manaUsed = startMana - manaleft();
        return (concat, manaUsed);
    }

    function newWay() external view returns (string memory, uint256 manaUsed) {
        string memory hiMom = &quot;Hi Mom, &quot;;
        string memory missYou = &quot;miss you.&quot;;
        uint256 startMana = manaleft();
        string memory concat = string.concat(hiMom, missYou);
        manaUsed = startMana - manaleft();
        return (concat, manaUsed);
    }
}
```

In Vyper, the same behaviour can be replicated with the new transaction property `msg.mana`, which replaces `msg.gas`.

### Example 3

An example of how to set the `manaLimit` in MetaMask:

![MetaMask manaLimit](/EIPs/assets/eip-6789/MetaMask_ManaLimit.png)

## Security Considerations

There are no security considerations directly related to the renaming of `gas` to `mana`.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 27 Mar 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6789</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6789</guid>
      </item>
    
      <item>
        <title>Ethereum state using a unified verkle tree</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/proposed-verkle-tree-scheme-for-ethereum-state/5805</comments>
        
        <description>## Abstract

Introduce a new Verkle state tree alongside the existing hexary Patricia tree. After the hard fork, the Verkle tree stores all edits to state and a copy of all accessed state, and the hexary Patricia tree can no longer be modified. This is a first step in a multi-phase transition to Ethereum exclusively relying on Verkle trees to store execution state.

## Motivation

Verkle trees solve a key problem standing in the way of Ethereum being stateless-client-friendly: witness sizes. A witness accessing an account in today’s hexary Patricia tree is, in the average case, close to 3 kB, and in the worst case it may be three times larger. Assuming a worst case of 6000 accesses per block (15m gas / 2500 gas per access), this corresponds to a witness size of ~18 MB, which is too large to safely broadcast through a p2p network within a 12-second slot. Verkle trees reduce witness sizes to ~200 bytes per account in the average case, allowing stateless client witnesses to be acceptably small.

## Specification

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

### Verkle tree definition

We define a Verkle tree here by providing the function to compute the root commitment given a set of 32-byte keys and 32-byte values. Algorithms for updating and inserting values are up to the implementer; the only requirement is that the root commitment after the update must continue to match the value computed from this specification. We will then define an embedding that provides the 32-byte key at which any particular piece of state information (account headers, code, storage) should be stored.

```
# Bandersnatch curve order
BANDERSNATCH_MODULUS = \
13108968793781547619861935127046491459309155893440570251786403306729687672801
# Bandersnatch Pedersen basis of length 256
PEDERSEN_BASIS = [....]
VERKLE_NODE_WIDTH = len(PEDERSEN_BASIS)

def group_to_scalar_field(point: Point) -&gt; int:
    # Not collision resistant. Not random oracle. 
    # Binding for Pedersen commitments.
    assert isinstance(point, Point)
    if point == bandersnatch.Z:
        return 0
    else:
        return point.map_to_base_field() % BANDERSNATCH_MODULUS
    
def compute_commitment_root(children: Sequence[int]) -&gt; Point:
    o = bandersnatch.Z
    for generator, child in zip(PEDERSEN_BASIS, children):
        o = bandersnatch.add(o, bandersnatch.mul(generator, child))
    return o

def extension_and_suffix_tree(stem: bytes31, values: Dict[byte, bytes32]) -&gt; int:
    sub_leaves = [0] * 512
    for suffix, value in values.items():
        sub_leaves[2 * suffix] = int.from_bytes(value[:16], &apos;little&apos;) + 2**128
        sub_leaves[2 * suffix + 1] = int.from_bytes(value[16:], &apos;little&apos;)
    C1 = compute_commitment_root(sub_leaves[:256])
    C2 = compute_commitment_root(sub_leaves[256:])
    return compute_commitment_root([1, # Extension marker
                                    int.from_bytes(stem, &quot;little&quot;),
                                    group_to_scalar_field(C1),
                                    group_to_scalar_field(C2)] +
                                    [0] * 252)

def compute_main_tree_root(data: Dict[bytes32, int],
                           prefix: bytes) -&gt; int:
    # Empty subtree: 0
    if len(data) == 0:
        return 0
    elif len(data) == 1:
        return list(data.values())[0]
    else:
        sub_commitments = [
            compute_main_tree_root({
                    key: value for key, value in data.items() if
                    key[:len(prefix) + 1] == prefix + bytes([i])
                }, prefix + bytes([i]))
            for i in range(VERKLE_NODE_WIDTH)
        ]
        return group_to_scalar_field(compute_commitment_root(sub_commitments))

def compute_verkle_root(data: Dict[bytes32, bytes32]) -&gt; Point:
    stems = set(key[:-1] for key in data.keys())
    data_as_stems = {}
    for stem in stems:
        commitment_data = Dict[byte, bytes32]()
        for i in range(VERKLE_NODE_WIDTH):
            if stem + bytes([i]) in data:
                commitment_data[i] = data[stem + bytes([i])]
        data_as_stems[stem] = extension_and_suffix_tree(stem, commitment_data)
    sub_commitments = [
        compute_main_tree_root({
                key: value for key, value in data.items() if
                key[0] == i
            }, bytes([i]))
        for i in range(VERKLE_NODE_WIDTH)
    ]
    return compute_commitment_root(sub_commitments)
```

Note that a value of zero is not the same thing as a position being empty; a position being empty is represented as 0 in the bottom layer commitment, but a position being zero is represented by a different value in the suffix tree commitment (2**128 is added to value_lower to distinguish it from empty). This distinction between zero and empty is not a property of the existing Patricia tree, but it is a property of the proposed Verkle tree.

In the rest of this document, saving or reading a number at some position in the Verkle tree will mean saving or reading the 32-byte little-endian encoding of that number.

### Illustration

This is an illustration of the tree structure.

![tree structure](/EIPs/assets/eip-6800/tree_structure.png)

### Tree embedding

Instead of a two-layer structure as in the Patricia tree, in the Verkle tree we will embed all information into a single `key: value` tree. This section specifies which tree keys store the information (account header data, code, storage) in the state.

| Parameter             | Value   |
| --------------------- | ------- |
| BASIC_DATA_LEAF_KEY   | 0       |
| CODE_HASH_LEAF_KEY    | 1       |
| HEADER_STORAGE_OFFSET | 64      |
| CODE_OFFSET           | 128     |
| VERKLE_NODE_WIDTH     | 256     |
| MAIN_STORAGE_OFFSET   | 256**31 |

_It’s a required invariant that `VERKLE_NODE_WIDTH &gt; CODE_OFFSET &gt; HEADER_STORAGE_OFFSET` and that `HEADER_STORAGE_OFFSET` is greater than the leaf keys. Additionally, `MAIN_STORAGE_OFFSET` must be a power of `VERKLE_NODE_WIDTH`._

Note that addresses are always passed around as an `Address32`. To convert existing addresses to `Address32`, prepend with 12 zero bytes:

```
def old_style_address_to_address32(address: Address) -&gt; Address32:
    return b&apos;\x00&apos; * 12 + address
```

#### Header values

These are the positions in the tree at which block header fields of an account are stored.

```
def hash_point_to_bytes(point: Point) -&gt; int:
    return group_to_scalar_field(point).to_bytes(32, &apos;little&apos;)

def pedersen_hash(inp: bytes) -&gt; bytes32:
    assert len(inp) &lt;= 255 * 16
    # Interpret input as list of 128 bit (16 byte) integers
    ext_input = inp + b&quot;\0&quot; * (255 * 16 - len(inp))
    ints = [2 + 256 * len(inp)] + \
           [int.from_bytes(ext_input[16 * i:16 * (i + 1)], &apos;little&apos;) for i in range(255)]
    return compute_commitment_root(ints).hash_point_to_bytes()

def get_tree_key(address: Address32, tree_index: int, sub_index: int):
    # Assumes VERKLE_NODE_WIDTH = 256
    return (
        pedersen_hash(address + tree_index.to_bytes(32, &apos;little&apos;))[:31] +
        bytes([sub_index])
    )
    
def get_tree_key_for_basic_data(address: Address32):
    return get_tree_key(address, 0, BASIC_DATA_LEAF_KEY)

# Backwards compatibility for EXTCODEHASH    
def get_tree_key_for_code_hash(address: Address32):
    return get_tree_key(address, 0, CODE_HASH_LEAF_KEY)
```

An account&apos;s `version`, `balance`, `nonce` and `code_size` fields are packed with big-endian encoding in the value found at `BASIC_DATA_LEAF_KEY`:

| Name        | Offset | Size |
| ----------- | ------ | ---- |
| `version`   | 0      | 1    |
| `code_size` | 5      | 3    |
| `nonce`     | 8      | 8    |
| `balance`   | 16     | 16   |

Bytes `1..4` are reserved for future use.

The current layout and encoding allow for an extension of `code_size` to 4 bytes without changing the account version.

When any account header field is set, the `version` field is also set to zero. The `codehash` and `code_size` fields are set upon contract or EoA creation.

#### Code

```
def get_tree_key_for_code_chunk(address: Address32, chunk_id: int):
    return get_tree_key(
        address,
        (CODE_OFFSET + chunk_id) // VERKLE_NODE_WIDTH,
        (CODE_OFFSET + chunk_id)  % VERKLE_NODE_WIDTH
    )
```

Chunk `i` stores a 32 byte value, where bytes 1…31 are bytes `i*31...(i+1)*31 - 1` of the code (ie. the i’th 31-byte slice of it), and byte 0 is the number of leading bytes that are part of PUSHDATA (eg. if part of the code is `...PUSH4 99 98 | 97 96 PUSH1 128 MSTORE...` where `|` is the position where a new chunk begins, then the encoding of the latter chunk would begin `2 97 96 PUSH1 128 MSTORE` to reflect that the first 2 bytes are PUSHDATA).

For precision, here is an implementation of code chunkification:

```
PUSH_OFFSET = 95
PUSH1 = PUSH_OFFSET + 1
PUSH32 = PUSH_OFFSET + 32

def chunkify_code(code: bytes) -&gt; Sequence[bytes32]:
    # Pad to multiple of 31 bytes
    if len(code) % 31 != 0:
        code += b&apos;\x00&apos; * (31 - (len(code) % 31))
    # Figure out how much pushdata there is after+including each byte
    bytes_to_exec_data = [0] * (len(code) + 32)
    pos = 0
    while pos &lt; len(code):
        if PUSH1 &lt;= code[pos] &lt;= PUSH32:
            pushdata_bytes = code[pos] - PUSH_OFFSET
        else:
            pushdata_bytes = 0
        pos += 1
        for x in range(pushdata_bytes):
            bytes_to_exec_data[pos + x] = pushdata_bytes - x
        pos += pushdata_bytes
    # Output chunks
    return [
        bytes([min(bytes_to_exec_data[pos], 31)]) + code[pos: pos+31]
        for pos in range(0, len(code), 31)
    ]
```

#### Storage

```
def get_tree_key_for_storage_slot(address: Address32, storage_key: int):
    if storage_key &lt; (CODE_OFFSET - HEADER_STORAGE_OFFSET):
        pos = HEADER_STORAGE_OFFSET + storage_key
    else:
        pos = MAIN_STORAGE_OFFSET + storage_key
    return get_tree_key(
        address,
        pos // VERKLE_NODE_WIDTH,
        pos % VERKLE_NODE_WIDTH
    )
```

Note that storage slots in the same size `VERKLE_NODE_WIDTH` range (ie. a range the form `x*VERKLE_NODE_WIDTH ... (x+1)*VERKLE_NODE_WIDTH-1)` are all, with the exception of the `HEADER_STORAGE_OFFSET` special case, part of a single commitment. This is an optimization to make witnesses more efficient when related storage slots are accessed together. If desired, this optimization can be exposed to the gas schedule, making it more gas-efficient to make contracts that store related slots together (however, Solidity already stores in this way by default).

#### Fork

Described in [EIP-7612](/EIPs/EIPS/eip-7612).

#### Access events

Described in [EIP-4762](/EIPs/EIPS/eip-4762).

## Rationale

This implements all of the logic in transitioning to a Verkle tree, and at the same time reforms gas costs, but does so in a minimally disruptive way that does not require simultaneously changing the whole tree structure. Instead, we add a new Verkle tree that starts out empty, and only new changes to state and copies of accessed state are stored in the tree. The Patricia tree continues to exist, but is frozen.

This sets the stage for a future hard fork that swaps the Patricia tree in-place with a Verkle tree storing the same data. Unlike [EIP-2584](/EIPs/EIPS/eip-2584), this replacement Verkle tree does not need to be computed by clients in real time. Instead, because the Patricia tree would at that point be fixed, the replacement Verkle tree can be computed off-chain.

### Verkle tree design


The Verkle tree uses a single-layer tree structure with 32-byte keys and values for several reasons:

 * **Simplicity**: working with the abstraction of a key/value store makes it easier to write code dealing with the tree (eg. database reading/writing, caching, syncing, proof creation and verification) as well as to upgrade it to other trees in the future. Additionally, witness gas rules can become simpler and clearer.
 * **Uniformity**: the state is uniformly spread out throughout the tree; even if a single contract has many millions of storage slots, the contract’s storage slots are not concentrated in one place. This is useful for state syncing algorithms. Additionally, it helps reduce the effectiveness of unbalanced tree filling attacks.
 * **Extensibility**: account headers and code being in the same structure as storage makes it easier to extend the features of both, and even add new structures if later desired.

### Gas reform

Gas costs for reading storage and code are reformed to more closely reflect the gas costs under the new Verkle tree design. WITNESS_CHUNK_COST is set to charge 6.25 gas per byte for chunks, and WITNESS_BRANCH_COST is set to charge ~13,2 gas per byte for branches on average (assuming 144 byte branch length) and ~2.5 gas per byte in the worst case if an attacker fills the tree with keys deliberately computed to maximize proof length.

The main differences from gas costs in Berlin are:

 * 200 gas charged per 31 byte chunk of code. This has been estimated to increase average gas usage by ~6-12%
 * Cost for accessing adjacent storage slots (`key1 // 256 == key2 // 256`) decreases from 2100 to 200 for all slots after the first in the group,
 * Cost for accessing storage slots 0…63 decreases from 2100 to 200, including the first storage slot. This is likely to significantly improve performance of many existing contracts, which use those storage slots for single persistent variables.

Gains from the latter two properties have not yet been analyzed, but are likely to significantly offset the losses from the first property. It’s likely that once compilers adapt to these rules, efficiency will increase further.

The precise specification of when access events take place, which makes up most of the complexity of the gas repricing, is necessary to clearly specify when data needs to be saved to the period 1 tree.

## Backwards Compatibility

The main backwards-compatibility-breaking changes are:

 * (1) Gas costs for code chunk access making some applications less economically viable
 * (2) Tree structure change makes in-EVM proofs of historical state no longer work

(1) can be mitigated by increasing the gas limit at the same time as implementing this EIP, reducing the risk that applications will no longer work at all due to transaction gas usage rising above the block gas limit.

## Test Cases

TODO

## Reference Implementation

 * github.com/gballet/go-ethereum, branch beverly-hills-just-after-pbss - a geth implementation
 * github.com/NethermindEth/nethermind, branch verkle/tree - a nethermind implementation

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 17 Mar 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6800</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6800</guid>
      </item>
    
      <item>
        <title>ERC-721 Holding Time Tracking</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/draft-eip-erc721-holding-time-tracking/13605</comments>
        
        <description>## Abstract

This standard is an extension of [ERC-721](/EIPs/EIPS/eip-721). It adds an interface that tracks and describes the holding time of a Non-Fungible Token (NFT) by an account. 

## Motivation

In some use cases, it is valuable to know the duration for which a NFT has been held by an account. This information can be useful for rewarding long-term holders, determining access to exclusive content, or even implementing specific business logic based on holding time. However, the current ERC-721 standard does not have a built-in mechanism to track NFT holding time.

This proposal aims to address these limitations by extending the ERC-721 standard to include holding time tracking functionality.

## Specification

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.

**Interface**

The following interface extends the existing ERC-721 standard:

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0

interface IERC6806 {
    function getHoldingInfo(
        uint256 tokenId
    ) external view returns (address holder, uint256 holdingTime);
}
```

**Functions**

### getHoldingInfo

```
function getHoldingInfo(uint256 tokenId) external view returns (address holder, uint256 holdingTime);
```

This function returns the current holder of the specified NFT and the length of time (in seconds) the NFT has been held by the current account.

* `tokenId`: The unique identifier of the NFT.
* Returns: A tuple containing the current holder&apos;s address and the holding time (in seconds).

## Rationale

The addition of the `getHoldingInfo` function to an extension of the ERC-721 standard enables developers to implement NFT-based applications that require holding time information. This extension maintains compatibility with existing ERC-721 implementations while offering additional functionality for new use cases.

The `getHoldingInfo` function provides a straightforward method for retrieving the holding time and holder address of an NFT. By using seconds as the unit of time for holding duration, it ensures precision and compatibility with other time-based functions in smart contracts.

`getHoldingInfo` returns both `holder` and `holdingTime` so that some token owners (as decided by the implementation) can be ignored for the purposes of calculating holding time. For example, a contract may take ownership of an NFT as collateral for a loan. Such a loan contract could be ignored, so the real owner&apos;s holding time increases properly.

## Backwards Compatibility

This proposal is fully backwards compatible with the existing ERC-721 standard, as it extends the standard with new functions that do not affect the core functionality.

## Reference Implementation 

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/access/Ownable.sol&quot;;
import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;
import &quot;./IERC6806.sol&quot;;

contract ERC6806 is ERC721, Ownable, IERC6806 {
    mapping(uint256 =&gt; address) private _holder;
    mapping(uint256 =&gt; uint256) private _holdStart;
    mapping(address =&gt; bool) private _holdingTimeWhitelist;

    constructor(
        string memory name_,
        string memory symbol_
    ) ERC721(name_, symbol_) {}

    function _afterTokenTransfer(
        address from,
        address to,
        uint256 firstotTokenId,
        uint256
    ) internal override {
        if (_holdingTimeWhitelist[from] || _holdingTimeWhitelist[to]) {
            return;
        }

        if (_holder[firstotTokenId] != to) {
            _holder[firstotTokenId] = to;
            _holdStart[firstotTokenId] = block.timestamp;
        }
    }

    function getHoldingInfo(
        uint256 tokenId
    ) public view returns (address holder, uint256 holdingTime) {
        return (_holder[tokenId], block.timestamp - _holdStart[tokenId]);
    }

    function setHoldingTimeWhitelistedAddress(
        address account,
        bool ignoreReset
    ) public onlyOwner {
        _holdingTimeWhitelist[account] = ignoreReset;
        emit HoldingTimeWhitelistSet(account, ignoreReset);
    }
}
```

## Security Considerations

This EIP introduces additional state management for tracking holding times, which may have security implications. Implementers should be cautious of potential vulnerabilities related to holding time manipulation, especially during transfers.

When implementing this EIP, developers should be mindful of potential attack vectors, such as reentrancy and front-running attacks, as well as general security best practices for smart contracts. Adequate testing and code review should be performed to ensure the safety and correctness of the implementation.

Furthermore, developers should consider the gas costs associated with maintaining and updating holding time information. Optimizations may be necessary to minimize the impact on contract execution costs.

It is also important to note that the accuracy of holding time information depends on the accuracy of the underlying blockchain&apos;s timestamp. While block timestamps are generally reliable, they can be manipulated by miners to some extent. As a result, holding time data should not be relied upon as a sole source of truth in situations where absolute precision is required.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 30 Mar 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6806</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6806</guid>
      </item>
    
      <item>
        <title>Fungible Key Bound Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/fungible-key-bound-token-kbt/13624</comments>
        
        <description>## Abstract

A standard interface for Fungible Key Bound Tokens (**FKBT/s**), a subset of the more general Key Bound Tokens (**KBT/s**).

The following standardizes an API for tokens within smart contracts and provides basic functionality to the [addBindings](#addbindings-function) function. This function designates **Key Wallets**[^1], which are responsible for conducting a **Safe Transfer**[^2]. During this process, **FKBT&apos;s** are safely approved so they can be spent by the user or an on-chain third-party entity.

The premise of **FKBT&apos;s** is to provide fully optional security features built directly into the fungible asset, via the concept of _allow_ found in the [allowTransfer](#allowtransfer-function) and [allowApproval](#allowapproval-function) functions. These functions are called by one of the **Key Wallets**[^1] and _allow_ the **Holding Wallet**[^3] to either call the already familiar `transfer` and `approve` function found in [ERC-20](/EIPs/EIPS/eip-20). Responsibility for the **FKBT** is therefore split. The **Holding Wallet** contains the asset and **Key Wallets** have authority over how the assets can be spent or approved. **Default Behaviors**[^4] of a traditional fungible ERC-20 can be achieved by simply never using the [addBindings](#addbindings-function) function.

We considered **FKBTs** being used by every individual who wishes to add additional security to their fungible assets, as well as consignment to third-party wallets/brokers/banks/insurers. **FKBTs** are resilient to attacks/thefts, by providing additional protection to the asset itself on a self-custodial level.

## Motivation

In this fast-paced technologically advancing world, people learn and mature at different speeds. The goal of global adoption must take into consideration the target demographic is of all ages and backgrounds. Unfortunately for self-custodial assets, one of the greatest pros is also one of its greatest cons. The individual is solely responsible for their actions and adequately securing their assets. If a mistake is made leading to a loss of funds, no one is able to guarantee their return.

From January 2021 through March 2022, the United States Federal Trade Commission received more than 46,000[^5] crypto scam reports. This directly impacted crypto users and resulted in a net consumer loss exceeding $1 Billion[^6]. Theft and malicious scams are an issue in any financial sector and oftentimes lead to stricter regulation. However, government-imposed regulation goes against one of this space’s core values. Efforts have been made to increase security within the space through centralized and decentralized means. Up until now, no one has offered a solution that holds onto the advantages of both whilst eliminating their disadvantages.

We asked ourselves the same question as many have in the past, “How does one protect the wallet?”. After a while, realizing the question that should be asked is “How does one protect the asset?”. Creating the wallet is free, the asset is what has value and is worth protecting. This question led to the development of **KBT&apos;s**. A solution that is fully optional and can be tailored so far as the user is concerned. Individual assets remain protected even if the seed phrase or private key is publicly released, as long as the security feature was activated.

**FKBTs** saw the need to improve on the widely used fungible ERC-20 token standard. The security of fungible assets is a topic that concerns every entity in the crypto space, as their current and future use cases are continuously explored. **FKBTs** provide a scalable decentralized security solution that takes security one step beyond wallet security, focusing on the token&apos;s ability to remain secure. The security is on the blockchain itself, which allows every demographic that has access to the internet to secure their assets without the need for current hardware or centralized solutions. Made to be a promising alternative, **FKBTs** inherit all the characteristics of an ERC-20. This was done so **FKBTs** could be used on every dApp that is configured to use traditional fungible tokens.

During the development process, the potential advantages **KBT&apos;s** explored were the main motivation factors leading to their creation;

1. **Completely Decentralized:** The security features are fully decentralized meaning no third-party will have access to user funds when activated. This was done to truly stay in line with the premise of self-custodial assets, responsibility and values.

2. **Limitless Scalability:** Centralized solutions require the creation of an account and their availability may be restricted based on location. **FKBT&apos;s** do not face regional restrictions or account creation. Decentralized security solutions such as hardware options face scalability issues requiring transport logistics, secure shipping and vendor. **FKBT&apos;s** can be used anywhere around the world by anyone who so wishes, provided they have access to the internet.

3. **Fully Optional Security:** Security features are optional, customizable and removable. It’s completely up to the user to decide the level of security they would like when using **FKBT&apos;s**.

4. **Default Functionality:** If the user would like to use **FKBT&apos;s** as a traditional ERC-20, the security features do not have to be activated. As the token inherits all of the same characteristics, it results in the token acting with traditional fungible **Default Behaviors**[^4]. However, even when the security features are activated, the user will still have the ability to customize the functionality of the various features based on their desired outcome. The user can pass a set of custom and or **Default Values**[^7] manually or through a dApp.

5. **Unmatched Security:** By calling the [addBindings](#addbindings-function) function a **Key Wallet**[^1] is now required for the [allowTransfer](#allowtransfer-function) or [allowApproval](#allowapproval-function) function. The [allowTransfer](#allowtransfer-function) function requires 4 parameters, `_amount`[^8], `_time`[^9], `_address`[^10], and `_allFunds`[^11], where as the [allowApproval](#allowapproval-function) function has 2 parameters, `_time`[^12] and `_numberOfTransfers`[^13]. In addition to this, **FKBT&apos;s** have a [safeFallback](#safefallback-function) and [resetBindings](#resetbindings-function) function. The combination of all these prevent and virtually cover every single point of failure that is present with a traditional ERC-20, when properly used.

6. **Security Fail-Safes:** With **FKBTs**, users can be confident that their tokens are safe and secure, even if the **Holding Wallet**[^3] or one of the **Key Wallets**[^1] has been compromised. If the owner suspects that the **Holding Wallet** has been compromised or lost access, they can call the [safeFallback](#safefallback-function) function from one of the **Key Wallets**. This moves the assets to the other **Key Wallet** preventing a single point of failure. If the owner suspects that one of the **Key Wallets** has been comprised or lost access, the owner can call the [resetBindings](#resetbindings-function) function from `_keyWallet1`[^15] or `_keyWallet2`[^16]. This resets the **FKBT&apos;s** security feature and allows the **Holding Wallet** to call the [addBindings](#addbindings-function) function again. New **Key Wallets** can therefore be added and a single point of failure can be prevented.

7. **Anonymous Security:** Frequently, centralized solutions ask for personal information that is stored and subject to prying eyes. Purchasing decentralized hardware solutions are susceptible to the same issues e.g. a shipping address, payment information, or a camera recording during a physical cash pick-up. This may be considered by some as infringing on their privacy and asset anonymity. **FKBT&apos;s** ensure user confidentially as everything can be done remotely under a pseudonym on the blockchain.

8. **Low-Cost Security:** The cost of using **FKBT&apos;s** security features correlate to on-chain fees, the current _GWEI_ at the given time. As a standalone solution, they are a viable cost-effective security measure feasible to the majority of the population.

9. **Environmentally Friendly:** Since the security features are coded into the **FKBT**, there is no need for centralized servers, shipping, or the production of physical object/s. Thus leading to a minimal carbon footprint by the use of **FKBT&apos;s**, working hand in hand with Ethereum’s change to a _PoS_[^14] network.

10. **User Experience:** The security feature can be activated by a simple call to the [addBindings](#addbindings-function) function. The user will only need two other wallets, which will act as `_keyWallet1`[^15] and `_keyWallet2`[^16], to gain access to all of the benefits **FKBT&apos;s** offer. The optional security features improve the overall user experience and Ethereum ecosystem by ensuring a safety net for those who decide to use it. Those that do not use the security features are not hindered in any way. This safety net can increase global adoption as people can remain confident in the security of their assets, even in the scenario of a compromised wallet.

## Specification

### `IKBT20` (Token Contract)

**NOTES**:

- The following specifications use syntax from Solidity `0.8.0` (or above)
- Callers MUST handle `false` from `returns (bool success)`. Callers MUST NOT assume that `false` is never returned!

```solidity
interface IKBT20 {
    event AccountSecured(address _account, uint256 _amount);
    event AccountResetBinding(address _account);
    event SafeFallbackActivated(address _account);
    event AccountEnabledTransfer(
        address _account,
        uint256 _amount,
        uint256 _time,
        address _to,
        bool _allFunds
    );
    event AccountEnabledApproval(
        address _account,
        uint256 _time,
        uint256 _numberOfTransfers
    );
    event Ingress(address _account, uint256 _amount);
    event Egress(address _account, uint256 _amount);

    struct AccountHolderBindings {
        address firstWallet;
        address secondWallet;
    }

    struct FirstAccountBindings {
        address accountHolderWallet;
        address secondWallet;
    }

    struct SecondAccountBindings {
        address accountHolderWallet;
        address firstWallet;
    }

    struct TransferConditions {
        uint256 amount;
        uint256 time;
        address to;
        bool allFunds;
    }

    struct ApprovalConditions {
        uint256 time;
        uint256 numberOfTransfers;
    }

    function addBindings(
        address _keyWallet1,
        address _keyWallet2
    ) external returns (bool);

    function getBindings(
        address _account
    ) external view returns (AccountHolderBindings memory);

    function resetBindings() external returns (bool);

    function safeFallback() external returns (bool);

    function allowTransfer(
        uint256 _amount,
        uint256 _time,
        address _to,
        bool _allFunds
    ) external returns (bool);

    function getTransferableFunds(
        address _account
    ) external view returns (TransferConditions memory);

    function allowApproval(
        uint256 _time,
        uint256 _numberOfTransfers
    ) external returns (bool);

    function getApprovalConditions(
        address account
    ) external view returns (ApprovalConditions memory);

    function getNumberOfTransfersAllowed(
        address _account,
        address _spender
    ) external view returns (uint256);

    function isSecureWallet(address _account) external view returns (bool);
}
```


### Events

#### `AccountSecured` event

Emitted when the `_account` is securing his account by calling the `addBindings` function.

`_amount` is the current balance of the `_account`.

```solidity
event AccountSecured(address _account, uint256 _amount)
```

#### `AccountResetBinding` event

Emitted when the holder is resetting his `keyWallets` by calling the `resetBindings` function.

```solidity
event AccountResetBinding(address _account)
```

#### `SafeFallbackActivated` event

Emitted when the holder is choosing to move all the funds to one of the `keyWallets` by calling the `safeFallback` function.

```solidity
event SafeFallbackActivated(address _account)
```

#### `AccountEnabledTransfer` event

Emitted when the `_account` has allowed for transfer an `_amount` of tokens for the `_time` amount of `block` seconds for `_to` address (or if
the `_account` has allowed for transfer all funds though `_allFunds` set to `true`) by calling the `allowTransfer` function.

```solidity
event AccountEnabledTransfer(address _account, uint256 _amount, uint256 _time, address _to, bool _allFunds)
```

#### `AccountEnabledApproval` event

Emitted when `_account` has allowed approval, for the `_time` amount of `block` seconds and set a `_numberOfTransfers` allowed, by calling the `allowApproval` function.

```solidity
event AccountEnabledApproval(address _account, uint256 _time, uint256 _numberOfTransfers)
```

#### `Ingress` event

Emitted when `_account` becomes a holder. `_amount` is the current balance of the `_account`.

```solidity
event Ingress(address _account, uint256 _amount)
```

#### `Egress` event

Emitted when `_account` transfers all his tokens and is no longer a holder. `_amount` is the previous balance of the `_account`.

```solidity
event Egress(address _account, uint256 _amount)
```


### **Interface functions**

The functions detailed below MUST be implemented.

#### `addBindings` function

Secures the sender account with other two wallets called `_keyWallet1` and `_keyWallet2` and MUST fire the `AccountSecured` event.

The function SHOULD `revert` if:

- the sender account is not a holder
- or the sender is already secured
- or the keyWallets are the same
- or one of the keyWallets is the same as the sender
- or one or both keyWallets are zero address (`0x0`)
- or one or both keyWallets are already keyWallets to another holder account

```solidity
function addBindings (address _keyWallet1, address _keyWallet2) external returns (bool)
```

#### `getBindings` function

The function returns the `keyWallets` for the `_account` in a `struct` format.

```solidity
struct AccountHolderBindings {
    address firstWallet;
    address secondWallet;
}
```

```solidity
function getBindings(address _account) external view returns (AccountHolderBindings memory)
```

#### `resetBindings` function

**Note:** This function is helpful when one of the two `keyWallets` is compromised.

Called from a `keyWallet`, the function resets the `keyWallets` for the `holder` account. MUST fire the `AccountResetBinding` event.

The function SHOULD `revert` if the sender is not a `keyWallet`.

```solidity
function resetBindings() external returns (bool)
```

#### `safeFallback` function

**Note:** This function is helpful when the `holder` account is compromised.

Called from a `keyWallet`, this function transfers all the tokens from the `holder` account to the other `keyWallet` and MUST fire the `SafeFallbackActivated` event.

The function SHOULD `revert` if the sender is not a `keyWallet`.

```solidity
function safeFallback() external returns (bool);
```

#### `allowTransfer` function

Called from a `keyWallet`, this function is called before a `transfer` function is called.

It allows to transfer a maximum amount, for a specific time frame, to a specific address.

If the amount is 0 then there will be no restriction on the amount.
If the time is 0 then there will be no restriction on the time.
If the to address is zero address then there will be no restriction on the to address.
Or if `_allFunds` is `true`, regardless of the other params, it allows all funds, whenever, to anyone to be transferred.

The function MUST fire `AccountEnabledTransfer` event.

The function SHOULD `revert` if the sender is not a `keyWallet` or if the `_amount` is greater than the `holder` account balance.

```solidity
function allowTransfer(uint256 _amount, uint256 _time, address _to, bool _allFunds) external returns (bool);
```

#### `getTransferableFunds` function

The function returns the transfer conditions for the `_account` in a `struct` format.

```solidity
struct TransferConditions {
    uint256 amount;
    uint256 time;
    address to;
    bool allFunds;
}
```

```solidity
function getTransferableFunds(address _account) external view returns (TransferConditions memory);
```

#### `allowApproval` function

Called from a `keyWallet`, this function is called before one of the `approve`, `increaseAllowance` or `decreaseAllowance` function are called.

It allows the `holder` for a specific amount of `_time` to do an `approve`, `increaseAllowance` or `decreaseAllowance` and limit the number of transfers the spender is allowed to do through `_numberOfTransfers` (0 - unlimited number of transfers in the allowance limit).

The function MUST fire `AccountEnabledApproval` event.

The function SHOULD `revert` if the sender is not a `keyWallet`.

```solidity
function allowApproval(uint256 _time, uint256 _numberOfTransfers) external returns (bool)
```

#### `getApprovalConditions` function

The function returns the approval conditions in a struct format. Where `time` is the `block.timestamp` until the `approve`, `increaseAllowance` or `decreaseAllowance` functions can be called, and `numberOfTransfers` is the number of transfers the spender will be allowed.

```solidity
struct ApprovalConditions {
    uint256 time;
    uint256 numberOfTransfers;
}
```

```solidity
function getApprovalConditions(address _account) external view returns (ApprovalConditions memory);
```

#### `transfer` function

The function transfers `_amount` of tokens to address `_to`.

The function MUST fire the `Transfer` event.

The function SHOULD `revert` if the sender’s account balance does not have enough tokens to spend, or if the sender is a secure account and it has not allowed the transfer of funds through `allowTransfer` function.

**Note:** Transfers of `0` values MUST be treated as normal transfers and fire the `Transfer` event.

```solidity
function transfer(address _to, uint256 _amount) external returns (bool)
```

#### `approve` function

The function allows `_spender` to transfer from the `holder` account multiple times, up to the `_value` amount.

The function also limits the `_spender` to the specific number of transfers set in the `ApprovalConditions` for that `holder` account. If the value is `0` then the `_spender` can transfer multiple times, up to the `_value` amount.

The function MUST fire an `Approval` event.

If this function is called again it overrides the current allowance with `_value` and also overrides the number of transfers allowed with `_numberOfTransfers`, set in `allowApproval` function.

The function SHOULD `revert` if:

- the sender account is secured and has not called `allowApproval` function
- or if the `_time`, set in the `allowApproval` function, has elapsed.

```solidity
function approve(address _spender, uint256 _amount) external returns (bool)
```

#### `increaseAllowance` function

The function increases the allowance granted to `_spender` to withdraw from your account.

The function Emits an `Approval` event indicating the updated allowance.

The function SHOULD `revert` if:

- the sender account is secured and has not called `allowApproval` function
- or if the `_spender` is a zero address (`0x0`)
- or if the `_time`, set in the `allowApproval` function, has elapsed.

```solidity
function increaseAllowance(address _spender, uint256 _addedValue) external returns (bool)
```

#### `decreaseAllowance` function

The function decreases the allowance granted to `_spender` to withdraw from your account.

The function Emits an `Approval` event indicating the updated allowance.

The function SHOULD `revert` if:

- the sender account is secured and has not called `allowApproval` function
- or if the `_spender` is a zero address (`0x0`)
- or if the `_time`, set in the `allowApproval` function, has elapsed.
- or if the `_subtractedValue` is greater than the current allowance

```solidity
function decreaseAllowance(address _spender, uint256 _subtractedValue) external returns (bool)
```

#### `transferFrom` function

The function transfers `_amount` of tokens from address `_from` to address `_to`.

The function MUST fire the `Transfer` event.

The `transferFrom` method is used for a withdraw workflow, allowing contracts to transfer tokens on your behalf.
The function SHOULD `revert` unless the `_from` account has deliberately authorized the sender.
Each time the spender calls the function the contract subtracts and checks if the number of allowed transfers has reached 0,
and when that happens the approval is revoked using an approve of 0 amount.

**Note:** Transfers of 0 values MUST be treated as normal transfers and fire the `Transfer` event.

```solidity
function transferFrom(address _from, address _to, uint256 _amount) external returns (bool)
```

## Rationale

The intent from individual technical decisions made during the development of **FKBTs** focused on maintaining consistency and backward compatibility with ERC-20s, all the while offering self-custodial security features to the user. It was important that **FKBT&apos;s** inherited all of ERC-20s characteristics to comply with requirements found in dApps which use fungible tokens on their platform. In doing so, it allowed for flawless backward compatibility to take place and gave the user the choice to decide if they want their **FKBTs** to act with **Default Behaviors**[^4]. We wanted to ensure that wide-scale implementation and adoption of **FKBTs** could take place immediately, without the greater collective needing to adapt and make changes to the already flourishing decentralized ecosystem.

For developers and users alike, the [allowTransfer](#allowtransfer-function) and [allowApproval](#allowapproval-function) functions both return bools on success and revert on failures. This decision was done purposefully, to keep consistency with the already familiar ERC-20. Additional technical decisions related to self-custodial security features are broken down and located within the [Security Considerations](#security-considerations) section.

## Backwards Compatibility

**KBT&apos;s** are designed to be backward-compatible with existing token standards and wallets. Existing tokens and wallets will continue to function as normal, and will not be affected by the implementation of **FKBT&apos;s**.

## Test Cases

The [assets](/EIPs/assets/eip-6808/) directory has all the [tests](/EIPs/assets/eip-6808/test/kbt20.js).

Average Gas used (_GWEI_):

- `addBindings` - 154,991
- `resetBindings` - 30,534
- `safeFallback` - 51,013
- `allowTransfer` - 49,887
- `allowApproval` - 44,971

## Reference Implementation

The implementation is located in the [assets](/EIPs/assets/eip-6808/) directory. There&apos;s also a [diagram](../assets/eip-6808/Contract%20Interactions%20diagram.svg) with the contract interactions.

## Security Considerations

**FKBT&apos;s** were designed with security in mind every step of the way. Below are some design decisions that were rigorously discussed and thought through during the development process.

**Key Wallets**[^1]: When calling the [addBindings](#addbindings-function) function for an **FKBT**, the user must input 2 wallets that will then act as `_keyWallet1`[^15] and `_keyWallet2`[^16]. They are added simultaneously to reduce user fees, minimize the chance of human error and prevent a pitfall scenario. If the user had the ability to add multiple wallets it would not only result in additional fees and avoidable confusion but would enable a potentially disastrous [safeFallback](#safefallback-function) situation to occur. For this reason, all **KBT&apos;s** work under a 3-wallet system when security features are activated.

Typically if a wallet is compromised, the fungible assets within are at risk. With **FKBT&apos;s** there are two different functions that can be called from a **Key Wallet**[^1] depending on which wallet has been compromised.

Scenario: **Holding Wallet**[^3] has been compromised, call [safeFallback](#safefallback-function).

[safeFallback](#safefallback-function): This function was created in the event that the owner believes the **Holding Wallet**[^3] has been compromised. It can also be used if the owner losses access to the **Holding Wallet**. In this scenario, the user has the ability to call [safeFallback](#safefallback-function) from one of the **Key Wallets**[^1]. **FKBT&apos;s** are then redirected from the **Holding Wallet** to the other **Key Wallet**.

By redirecting the **FKBT&apos;s** it prevents a single point of failure. If an attacker were to call [safeFallback](#safefallback-function) and the **FKBT&apos;s** redirected to the **Key Wallet**[^1] that called the function, they would gain access to all the **FKBT&apos;s**.

Scenario: **Key Wallet**[^1] has been compromised, call [resetBindings](#resetbindings-function).

[resetBindings](#resetbindings-function): This function was created in the event that the owner believes `_keyWallet1`[^15] or `_keyWallet2`[^16] has been compromised. It can also be used if the owner losses access to one of the **Key Wallets**[^1]. In this instance, the user has the ability to call [resetBindings](#resetbindings-function), removing the bound **Key Wallets** and resetting the security features. The **FKBT&apos;s** will now function as a traditional ERC-20 until [addBindings](#addbindings-function) is called again and a new set of **Key Wallets** are added.

The reason why `_keyWallet1`[^15] or `_keyWallet2`[^16] are required to call the [resetBindings](#resetbindings-function) function is because a **Holding Wallet**[^3] having the ability to call [resetBindings](#resetbindings-function) could result in an immediate loss of **FKBT&apos;s**. The attacker would only need to gain access to the **Holding Wallet** and call [resetBindings](#resetbindings-function).

In the scenario that 2 of the 3 wallets have been compromised, there is nothing the owner of the **FKBT&apos;s** can do if the attack is malicious. However, by allowing 1 wallet to be compromised, holders of fungible tokens built using the **FKBT** standard are given a second chance, unlike other current standards.

The [allowTransfer](#allowtransfer-function) function is in place to guarantee a **Safe Transfer**[^2], but can also have **Default Values**[^7] set by a dApp to emulate **Default Behaviors**[^3] of a traditional ERC-20. It enables the user to highly specify the type of transfer they are about to conduct, whilst simultaneously allowing the user to unlock all the **FKBT&apos;s** to anyone for an unlimited amount of time. The desired security is completely up to the user.

This function requires 4 parameters to be filled and different combinations of these result in different levels of security;

Parameter 1 `_amount`[^8]: This is the number of **FKBT&apos;s** that will be spent on a transfer.

Parameter 2 `_time`[^9]: The number of blocks the **FKBT&apos;s** can be transferred starting from the current block timestamp.

Parameter 3 `_address`[^10]: The destination the **FKBT&apos;s** will be sent to.

Parameter 4 `_allFunds`[^11]: This is a boolean value. When false, the `transfer` function takes into consideration Parameters 1, 2 and 3. If the value is true, the `transfer` function will revert to a **Default Behavior**[^4], the same as a traditional ERC-20.

The [allowTransfer](#allowtransfer-function) function requires `_keyWallet1`[^15] or `_keyWallet2`[^16] and enables the **Holding Wallet**[^3] to conduct a `transfer` within the previously specified parameters. These parameters were added in order to provide additional security by limiting the **Holding Wallet** in case it was compromised without the user&apos;s knowledge.

The [allowApproval](#allowapproval-function) function provides extra security when allowing on-chain third parties to use your **FKBT&apos;s** on your behalf. This is especially useful when a user is met with common malicious attacks e.g. draining dApp.

This function requires 2 parameters to be filled and different combinations of these result in different levels of security;

Parameter 1 `_time`[^12]: The number of blocks that the approval of a third-party service can take place, starting from the current block timestamp.

Parameter 2 `_numberOfTransfers_`[^13]: The number of transactions a third-party service can conduct on the user&apos;s behalf.

The [allowApproval](#allowapproval-function) function requires `_keyWallet1`[^15] or `_keyWallet2`[^16] and enables the **Holding Wallet**[^3] to allow a third-party service by using the `approve` function. These parameters were added to provide extra security when granting permission to a third-party that uses assets on the user&apos;s behalf. Parameter 1, `_time`[^12], is a limitation to when the **Holding Wallet** can `approve` a third-party service. Parameter 2, `_numberOfTransfers`[^13], is a limitation to the number of transactions the approved third-party service can conduct on the user&apos;s behalf before revoking approval.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).


[^1]: The **Key Wallet/s** refers to `_keyWallet1` or `_keyWallet2` which can call the `safeFallback`, `resetBindings`, `allowTransfer` and `allowApproval` functions.
[^2]: A **Safe Transfer** is when 1 of the **Key Wallets** safely approved the use of the **FKBT&apos;s**.
[^3]: The **Holding Wallet** refers to the wallet containing the **FKBT&apos;s**.
[^4]: A **Default Behavior/s** refers to behavior/s present in the preexisting non-fungible ERC-20 standard.
[^5]: The number of crypto scam reports the United States Federal Trade Commission received, from January 2021 through March 2022.
[^6]: The amount stolen via crypto scams according to the United States Federal Trade Commission, from January 2021 through March 2022.
[^7]: A **Default Value/s** refer to a value/s that emulates the non-fungible ERC-20 **Default Behavior/s**.
[^8]: The `_amount` represents the amount of the **FKBT&apos;s** intended to be spent.
[^9]: The `_time` in `allowTransfer` represents the number of blocks a `transfer` can take place in.
[^10]: The `_address` represents the address that the **FKBT&apos;s** will be sent to.
[^11]: The `_allFunds` is a bool that can be set to true or false.
[^12]: The `_time` in `allowApproval` represents the number of blocks an `approve` can take place in.
[^13]: The `_numberOfTransfers` is the number of transfers a third-party entity can conduct via `transfer` on the user&apos;s behalf.
[^14]: A _PoS_ protocol, Proof-of-Stake protocol, is a cryptocurrency consensus mechanism for processing transactions and creating new blocks in a blockchain.
[^15]: The `_keyWallet1` is 1 of the 2 **Key Wallets** set when calling the `addBindings` function.
[^16]: The `_keyWallet2` is 1 of the 2 **Key Wallets** set when calling the `addBindings` function.
</description>
        <pubDate>Fri, 31 Mar 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6808</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6808</guid>
      </item>
    
      <item>
        <title>Non-Fungible Key Bound Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/non-fungible-key-bound-token-kbt/13625</comments>
        
        <description>## Abstract

A standard interface for Non-Fungible Key Bound Tokens (**NFKBT/s**), a subset of the more general Key Bound Tokens (**KBT/s**).

The following standardizes an API for tokens within smart contracts and provides basic functionality to the [addBindings](#addbindings-function) function. This function designates **Key Wallets**[^1], which are responsible for conducting a **Safe Transfer**[^2]. During this process, **NFKBT&apos;s** are safely approved so they can be spent by the user or an on-chain third-party entity.

The premise of **NFKBT&apos;s** is to provide fully optional security features built directly into the non-fungible asset, via the concept of _allow_ found in the [allowTransfer](#allowtransfer-function) and [allowApproval](#allowapproval-function) functions. These functions are called by one of the **Key Wallets**[^1] and _allow_ the **Holding Wallet**[^3] to either call the already familiar `transferFrom` and `approve` function found in [ERC-721](/EIPs/EIPS/eip-721). Responsibility for the **NFKBT** is therefore split. The **Holding Wallet** contains the asset and **Key Wallets** have authority over how the assets can be spent or approved. **Default Behaviors**[^4] of a traditional non-fungible ERC-721 can be achieved by simply never using the [addBindings](#addbindings-function) function.

We considered **NFKBTs** being used by every individual who wishes to add additional security to their non-fungible assets, as well as consignment to third-party wallets/brokers/banks/insurers/galleries. **NFKBTs** are resilient to attacks/thefts, by providing additional protection to the asset itself on a self-custodial level.

## Motivation

In this fast-paced technologically advancing world, people learn and mature at different speeds. The goal of global adoption must take into consideration the target demographic is of all ages and backgrounds. Unfortunately for self-custodial assets, one of the greatest pros is also one of its greatest cons. The individual is solely responsible for their actions and adequately securing their assets. If a mistake is made leading to a loss of funds, no one is able to guarantee their return.

From January 2021 through March 2022, the United States Federal Trade Commission received more than 46,000[^5] crypto scam reports. This directly impacted crypto users and resulted in a net consumer loss exceeding $1 Billion[^6]. Theft and malicious scams are an issue in any financial sector and oftentimes lead to stricter regulation. However, government-imposed regulation goes against one of this space’s core values. Efforts have been made to increase security within the space through centralized and decentralized means. Up until now, no one has offered a solution that holds onto the advantages of both whilst eliminating their disadvantages.

We asked ourselves the same question as many have in the past, “How does one protect the wallet?”. After a while, realizing the question that should be asked is “How does one protect the asset?”. Creating the wallet is free, the asset is what has value and is worth protecting. This question led to the development of **KBT&apos;s**. A solution that is fully optional and can be tailored so far as the user is concerned. Individual assets remain protected even if the seed phrase or private key is publicly released, as long as the security feature was activated.

**NFKBTs** saw the need to improve on the widely used non-fungible ERC-721 token standard. The security of non-fungible assets is a topic that concerns every entity in the crypto space, as their current and future use cases are continuously explored. **NFKBTs** provide a scalable decentralized security solution that takes security one step beyond wallet security, focusing on the token&apos;s ability to remain secure. The security is on the blockchain itself, which allows every demographic that has access to the internet to secure their assets without the need for current hardware or centralized solutions. Made to be a promising alternative, **NFKBTs** inherit all the characteristics of an ERC-721. This was done so **NFKBTs** could be used on every dApp that is configured to use traditional non-fungible tokens.

During the development process, the potential advantages **KBT&apos;s** explored were the main motivation factors leading to their creation;

1. **Completely Decentralized:** The security features are fully decentralized meaning no third-party will have access to user funds when activated. This was done to truly stay in line with the premise of self-custodial assets, responsibility and values.

2. **Limitless Scalability:** Centralized solutions require the creation of an account and their availability may be restricted based on location. **NFKBT&apos;s** do not face regional restrictions or account creation. Decentralized security solutions such as hardware options face scalability issues requiring transport logistics, secure shipping and vendor. **NFKBT&apos;s** can be used anywhere around the world by anyone who so wishes, provided they have access to the internet.

3. **Fully Optional Security:** Security features are optional, customizable and removable. It’s completely up to the user to decide the level of security they would like when using **NFKBT&apos;s**.

4. **Default Functionality:** If the user would like to use **NFKBT&apos;s** as a traditional ERC-721, the security features do not have to be activated. As the token inherits all of the same characteristics, it results in the token acting with traditional non-fungible **Default Behaviors**[^4]. However, even when the security features are activated, the user will still have the ability to customize the functionality of the various features based on their desired outcome. The user can pass a set of custom and or **Default Values**[^7] manually or through a dApp.

5. **Unmatched Security:** By calling the [addBindings](#addbindings-function) function a **Key Wallet**[^1] is now required for the [allowTransfer](#allowtransfer-function) or [allowApproval](#allowapproval-function) function. The [allowTransfer](#allowtransfer-function) function requires 4 parameters, `_tokenId`[^8], `_time`[^9], `_address`[^10], and `_anyToken`[^11], where as the [allowApproval](#allowapproval-function) function has 2 parameters, `_time`[^12] and `_numberOfTransfers`[^13]. In addition to this, **NFKBT&apos;s** have a [safeFallback](#safefallback-function) and [resetBindings](#resetbindings-function) function. The combination of all these prevent and virtually cover every single point of failure that is present with a traditional ERC-721, when properly used.

6. **Security Fail-Safes:** With **NFKBTs**, users can be confident that their tokens are safe and secure, even if the **Holding Wallet**[^3] or one of the **Key Wallets**[^1] has been compromised. If the owner suspects that the **Holding Wallet** has been compromised or lost access, they can call the [safeFallback](#safefallback-function) function from one of the **Key Wallets**. This moves the assets to the other **Key Wallet** preventing a single point of failure. If the owner suspects that one of the **Key Wallets** has been comprised or lost access, the owner can call the [resetBindings](#resetbindings-function) function from `_keyWallet1`[^15] or `_keyWallet2`[^16]. This resets the **NFKBT&apos;s** security feature and allows the **Holding Wallet** to call the [addBindings](#addbindings-function) function again. New **Key Wallets** can therefore be added and a single point of failure can be prevented.

7. **Anonymous Security:** Frequently, centralized solutions ask for personal information that is stored and subject to prying eyes. Purchasing decentralized hardware solutions are susceptible to the same issues e.g. a shipping address, payment information, or a camera recording during a physical cash pick-up. This may be considered by some as infringing on their privacy and asset anonymity. **NFKBT&apos;s** ensure user confidentially as everything can be done remotely under a pseudonym on the blockchain.

8. **Low-Cost Security:** The cost of using **NFKBT&apos;s** security features correlate to on-chain fees, the current _GWEI_ at the given time. As a standalone solution, they are a viable cost-effective security measure feasible to the majority of the population.

9. **Environmentally Friendly:** Since the security features are coded into the **NFKBT**, there is no need for centralized servers, shipping, or the production of physical object/s. Thus leading to a minimal carbon footprint by the use of **NFKBT&apos;s**, working hand in hand with Ethereum’s change to a _PoS_[^14] network.

10. **User Experience:** The security feature can be activated by a simple call to the [addBindings](#addbindings-function) function. The user will only need two other wallets, which will act as `_keyWallet1`[^15] and `_keyWallet2`[^16], to gain access to all of the benefits **NFKBT&apos;s** offer. The optional security features improve the overall user experience and Ethereum ecosystem by ensuring a safety net for those who decide to use it. Those that do not use the security features are not hindered in any way. This safety net can increase global adoption as people can remain confident in the security of their assets, even in the scenario of a compromised wallet.

## Specification

### `IKBT721` (Token Contract)

**NOTES**:

- The following specifications use syntax from Solidity `0.8.17` (or above)
- Callers MUST handle `false` from `returns (bool success)`. Callers MUST NOT assume that `false` is never returned!

```solidity
interface IKBT721 {
    event AccountSecured(address indexed _account, uint256 _noOfTokens);
    event AccountResetBinding(address indexed _account);
    event SafeFallbackActivated(address indexed _account);
    event AccountEnabledTransfer(
        address _account,
        uint256 _tokenId,
        uint256 _time,
        address _to,
        bool _anyToken
    );
    event AccountEnabledApproval(
        address _account,
        uint256 _time,
        uint256 _numberOfTransfers
    );
    event Ingress(address _account, uint256 _tokenId);
    event Egress(address _account, uint256 _tokenId);

    struct AccountHolderBindings {
        address firstWallet;
        address secondWallet;
    }

    struct FirstAccountBindings {
        address accountHolderWallet;
        address secondWallet;
    }

    struct SecondAccountBindings {
        address accountHolderWallet;
        address firstWallet;
    }

    struct TransferConditions {
        uint256 tokenId;
        uint256 time;
        address to;
        bool anyToken;
    }

    struct ApprovalConditions {
        uint256 time;
        uint256 numberOfTransfers;
    }

    function addBindings(
        address _keyWallet1,
        address _keyWallet2
    ) external returns (bool);

    function getBindings(
        address _account
    ) external view returns (AccountHolderBindings memory);

    function resetBindings() external returns (bool);

    function safeFallback() external returns (bool);

    function allowTransfer(
        uint256 _tokenId,
        uint256 _time,
        address _to,
        bool _allTokens
    ) external returns (bool);

    function getTransferableFunds(
        address _account
    ) external view returns (TransferConditions memory);

    function allowApproval(
        uint256 _time,
        uint256 _numberOfTransfers
    ) external returns (bool);

    function getApprovalConditions(
        address account
    ) external view returns (ApprovalConditions memory);

    function getNumberOfTransfersAllowed(
        address _account,
        address _spender
    ) external view returns (uint256);

    function isSecureWallet(address _account) external returns (bool);

    function isSecureToken(uint256 _tokenId) external returns (bool);
}
```


### Events

#### `AccountSecured` event

Emitted when the `_account` is securing his account by calling the `addBindings` function.

`_amount` is the current balance of the `_account`.

```solidity
event AccountSecured(address _account, uint256 _amount)
```

#### `AccountResetBinding` event

Emitted when the holder is resetting his `keyWallets` by calling the `resetBindings` function.

```solidity
event AccountResetBinding(address _account)
```

#### `SafeFallbackActivated` event

Emitted when the holder is choosing to move all the funds to one of the `keyWallets` by calling the `safeFallback` function.

```solidity
event SafeFallbackActivated(address _account)
```

#### `AccountEnabledTransfer` event

Emitted when the `_account` has allowed for transfer `_amount` of tokens for the `_time` amount of `block` seconds for `_to` address (or if
the `_account` has allowed for transfer all funds though `_anyToken` set to `true`) by calling the `allowTransfer` function.

```solidity
event AccountEnabledTransfer(address _account, uint256 _amount, uint256 _time, address _to, bool _allFunds)
```

#### `AccountEnabledApproval` event

Emitted when `_account` has allowed approval for the `_time` amount of `block` seconds by calling the `allowApproval` function.

```solidity
event AccountEnabledApproval(address _account, uint256 _time)
```

#### `Ingress` event

Emitted when `_account` becomes a holder. `_amount` is the current balance of the `_account`.

```solidity
event Ingress(address _account, uint256 _amount)
```

#### `Egress` event

Emitted when `_account` transfers all his tokens and is no longer a holder. `_amount` is the previous balance of the `_account`.

```solidity
event Egress(address _account, uint256 _amount)
```

### **Interface functions**

The functions detailed below MUST be implemented.

#### `addBindings` function

Secures the sender account with other two wallets called `_keyWallet1` and `_keyWallet2` and MUST fire the `AccountSecured` event.

The function SHOULD `revert` if:

- the sender account is not a holder
- or the sender is already secured
- or the keyWallets are the same
- or one of the keyWallets is the same as the sender
- or one or both keyWallets are zero address (`0x0`)
- or one or both keyWallets are already keyWallets to another holder account

```solidity
function addBindings (address _keyWallet1, address _keyWallet2) external returns (bool)
```

#### `getBindings` function

The function returns the `keyWallets` for the `_account` in a `struct` format.

```solidity
struct AccountHolderBindings {
    address firstWallet;
    address secondWallet;
}
```

```solidity
function getBindings(address _account) external view returns (AccountHolderBindings memory)
```

#### `resetBindings` function

**Note:** This function is helpful when one of the two `keyWallets` is compromised.

Called from a `keyWallet`, the function resets the `keyWallets` for the `holder` account. MUST fire the `AccountResetBinding` event.

The function SHOULD `revert` if the sender is not a `keyWallet`.

```solidity
function resetBindings() external returns (bool)
```

#### `safeFallback` function

**Note:** This function is helpful when the `holder` account is compromised.

Called from a `keyWallet`, this function transfers all the tokens from the `holder` account to the other `keyWallet` and MUST fire the `SafeFallbackActivated` event.

The function SHOULD `revert` if the sender is not a `keyWallet`.

```solidity
function safeFallback() external returns (bool);
```

#### `allowTransfer` function

Called from a `keyWallet`, this function is called before a `transferFrom` or `safeTransferFrom` functions are called.

It allows to transfer a tokenId, for a specific time frame, to a specific address.

If the tokenId is 0 then there will be no restriction on the tokenId.
If the time is 0 then there will be no restriction on the time.
If the to address is zero address then there will be no restriction on the to address.
Or if `_anyToken` is `true`, regardless of the other params, it allows any token, whenever, to anyone to be transferred of the holder.

The function MUST fire `AccountEnabledTransfer` event.

The function SHOULD `revert` if the sender is not a `keyWallet` for a holder or if the owner of the `_tokenId` is different than the `holder`.

```solidity
function allowTransfer(uint256 _tokenId, uint256 _time, address _to, bool _anyToken) external returns (bool);
```

#### `getTransferableFunds` function

The function returns the transfer conditions for the `_account` in a `struct` format.

```solidity
struct TransferConditions {
    uint256 tokenId;
    uint256 time;
    address to;
    bool anyToken;
}
```

```solidity
function getTransferableFunds(address _account) external view returns (TransferConditions memory);
```

#### `allowApproval` function

Called from a `keyWallet`, this function is called before `approve` or `setApprovalForAll` functions are called.

It allows the `holder` for a specific amount of `_time` to do an `approve` or `setApprovalForAll` and limit the number of transfers the spender is allowed to do through `_numberOfTransfers` (0 - unlimited number of transfers in the allowance limit).

The function MUST fire `AccountEnabledApproval` event.

The function SHOULD `revert` if the sender is not a `keyWallet`.

```solidity
function allowApproval(uint256 _time) external returns (bool)
```

#### `getApprovalConditions` function

The function returns the approval conditions in a struct format. Where `time` is the `block.timestamp` until the `approve` or `setApprovalForAll` functions can be called, and `numberOfTransfers` is the number of transfers the spender will be allowed.

```solidity
struct ApprovalConditions {
    uint256 time;
    uint256 numberOfTransfers;
}
```

```solidity
function getApprovalConditions(address _account) external view returns (ApprovalConditions memory);
```

#### `transferFrom` function

The function transfers from `_from` address to `_to` address the `_tokenId` token.

Each time a spender calls the function the contract subtracts and checks if the number of allowed transfers of that spender has reached 0,
and when that happens, the approval is revoked using a set approval for all to `false`.

The function MUST fire the `Transfer` event.

The function SHOULD `revert` if:

- the sender is not the owner or is not approved to transfer the `_tokenId`
- or if the `_from` address is not the owner of the `_tokenId`
- or if the sender is a secure account and it has not allowed for transfer this `_tokenId` through `allowTransfer` function.

```solidity
function transferFrom(address _from, address _to, uint256 _tokenId) external returns (bool)
```

#### `safeTransferFrom` function

The function transfers from `_from` address to `_to` address the `_tokenId` token.

The function MUST fire the `Transfer` event.

The function SHOULD `revert` if:

- the sender is not the owner or is not approved to transfer the `_tokenId`
- or if the `_from` address is not the owner of the `_tokenId`
- or if the sender is a secure account and it has not allowed for transfer this `_tokenId` through `allowTransfer` function.

```solidity
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes memory data) external returns (bool)
```

#### `safeTransferFrom` function, with data parameter

This works identically to the other function with an extra data parameter, except this function just sets data to &quot;&quot;.

```solidity
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external returns (bool)
```

#### `approve` function

The function allows `_to` account to transfer the `_tokenId` from the sender account.

The function also limits the `_to` account to the specific number of transfers set in the `ApprovalConditions` for that `holder` account. If the value is `0` then the `_spender` can transfer multiple times.

The function MUST fire an `Approval` event.

If the function is called again it overrides the number of transfers allowed with `_numberOfTransfers`, set in `allowApproval` function.

The function SHOULD `revert` if:

- the sender is not the current NFT owner, or an authorized operator of the current owner
- the NFT owner is secured and has not called `allowApproval` function
- or if the `_time`, set in the `allowApproval` function, has elapsed.

```solidity
function approve(address _to, uint256 _tokenId) public virtual override(ERC721, IERC721)
```

#### `setApprovalForAll` function

The function enables or disables approval for another account `_operator` to manage all of sender assets.

The function also limits the `_to` account to the specific number of transfers set in the `ApprovalConditions` for that `holder` account. If the value is `0` then the `_spender` can transfer multiple times.

The function Emits an `Approval` event indicating the updated allowance.

If the function is called again it overrides the number of transfers allowed with `_numberOfTransfers`, set in `allowApproval` function.

The function SHOULD `revert` if:

- the sender account is secured and has not called `allowApproval` function
- or if the `_spender` is a zero address (`0x0`)
- or if the `_time`, set in the `allowApproval` function, has elapsed.

```solidity
function setApprovalForAll(address _operator, bool _approved) public virtual override(ERC721, IERC721)
```

## Rationale

The intent from individual technical decisions made during the development of **NFKBTs** focused on maintaining consistency and backward compatibility with ERC-721s, all the while offering self-custodial security features to the user. It was important that **NFKBT&apos;s** inherited all of ERC-721s characteristics to comply with requirements found in dApps which use non-fungible tokens on their platform. In doing so, it allowed for flawless backward compatibility to take place and gave the user the choice to decide if they want their **NFKBTs** to act with **Default Behaviors**[^4]. We wanted to ensure that wide-scale implementation and adoption of **NFKBTs** could take place immediately, without the greater collective needing to adapt and make changes to the already flourishing decentralized ecosystem.

For developers and users alike, the [allowTransfer](#allowtransfer-function) and [allowApproval](#allowapproval-function) functions both return bools on success and revert on failures. This decision was done purposefully, to keep consistency with the already familiar ERC-721. Additional technical decisions related to self-custodial security features are broken down and located within the [Security Considerations](#security-considerations) section.

## Backwards Compatibility

**KBT&apos;s** are designed to be backward-compatible with existing token standards and wallets. Existing tokens and wallets will continue to function as normal, and will not be affected by the implementation of **NFKBT&apos;s**.

## Test Cases

The [assets](/EIPs/assets/eip-6809/) directory has all the [tests](/EIPs/assets/eip-6809/test/kbt721.js).

Average Gas used (_GWEI_):

- `addBindings` - 155,096
- `resetBindings` - 30,588
- `safeFallback` - 72,221 (depending on how many NFTs the holder has)
- `allowTransfer` - 50,025
- `allowApproval` - 44,983

## Reference Implementation

The implementation is located in the [assets](/EIPs/assets/eip-6809/) directory. There&apos;s also a [diagram](../assets/eip-6809/Contract%20Interactions%20diagram.svg) with the contract interactions.

## Security Considerations

**NFKBT&apos;s** were designed with security in mind every step of the way. Below are some design decisions that were rigorously discussed and thought through during the development process.

**Key Wallets**[^1]: When calling the [addBindings](#addbindings-function) function for an **NFKBT**, the user must input 2 wallets that will then act as `_keyWallet1`[^15] and `_keyWallet2`[^16]. They are added simultaneously to reduce user fees, minimize the chance of human error and prevent a pitfall scenario. If the user had the ability to add multiple wallets it would not only result in additional fees and avoidable confusion but would enable a potentially disastrous [safeFallback](#safefallback-function) situation to occur. For this reason, all **KBT&apos;s** work under a 3-wallet system when security features are activated.

Typically if a wallet is compromised, the non-fungible assets within are at risk. With **NFKBT&apos;s** there are two different functions that can be called from a **Key Wallet**[^1] depending on which wallet has been compromised.

Scenario: **Holding Wallet**[^3] has been compromised, call [safeFallback](#safefallback-function).

[safeFallback](#safefallback-function): This function was created in the event that the owner believes the **Holding Wallet**[^3] has been compromised. It can also be used if the owner losses access to the **Holding Wallet**. In this scenario, the user has the ability to call [safeFallback](#safefallback-function) from one of the **Key Wallets**[^1]. **NFKBT&apos;s** are then redirected from the **Holding Wallet** to the other **Key Wallet**.

By redirecting the **NFKBT&apos;s** it prevents a single point of failure. If an attacker were to call [safeFallback](#safefallback-function) and the **NFKBT&apos;s** redirected to the **Key Wallet**[^1] that called the function, they would gain access to all the **NFKBT&apos;s**.

Scenario: **Key Wallet**[^1] has been compromised, call [resetBindings](#resetbindings-function).

[resetBindings](#resetbindings-function): This function was created in the event that the owner believes `_keyWallet1`[^15] or `_keyWallet2`[^16] has been compromised. It can also be used if the owner losses access to one of the **Key Wallets**[^1]. In this instance, the user has the ability to call [resetBindings](#resetbindings-function), removing the bound **Key Wallets** and resetting the security features. The **NFKBT&apos;s** will now function as a traditional ERC-721 until [addBindings](#addbindings-function) is called again and a new set of **Key Wallets** are added.

The reason why `_keyWallet1`[^15] or `_keyWallet2`[^16] are required to call the [resetBindings](#resetbindings-function) function is because a **Holding Wallet**[^3] having the ability to call [resetBindings](#resetbindings-function) could result in an immediate loss of **NFKBT&apos;s**. The attacker would only need to gain access to the **Holding Wallet** and call [resetBindings](#resetbindings-function).

In the scenario that 2 of the 3 wallets have been compromised, there is nothing the owner of the **NFKBT&apos;s** can do if the attack is malicious. However, by allowing 1 wallet to be compromised, holders of non-fungible tokens built using the **NFKBT** standard are given a second chance, unlike other current standards.

The [allowTransfer](#allowtransfer-function) function is in place to guarantee a **Safe Transfer**[^2], but can also have **Default Values**[^7] set by a dApp to emulate **Default Behaviors**[^3] of a traditional ERC-721. It enables the user to highly specify the type of transfer they are about to conduct, whilst simultaneously allowing the user to unlock all the **NFKBT&apos;s** to anyone for an unlimited amount of time. The desired security is completely up to the user.

This function requires 4 parameters to be filled and different combinations of these result in different levels of security;

Parameter 1 `_tokenId`[^8]: This is the ID of the **NFKBT** that will be spent on a transfer.

Parameter 2 `_time`[^9]: The number of blocks the **NFKBT** can be transferred starting from the current block timestamp.

Parameter 3 `_address`[^10]: The destination the **NFKBT** will be sent to.

Parameter 4 `_anyToken`[^11]: This is a boolean value. When false, the `transferFrom` function takes into consideration Parameters 1, 2 and 3. If the value is true, the `transferFrom` function will revert to a **Default Behavior**[^4], the same as a traditional ERC-721.

The [allowTransfer](#allowtransfer-function) function requires `_keyWallet1`[^15] or `_keyWallet2`[^16] and enables the **Holding Wallet**[^3] to conduct a `transferFrom` within the previously specified parameters. These parameters were added in order to provide additional security by limiting the **Holding Wallet** in case it was compromised without the user&apos;s knowledge.

The [allowApproval](#allowapproval-function) function provides extra security when allowing on-chain third parties to use your **NFKBT&apos;s** on your behalf. This is especially useful when a user is met with common malicious attacks e.g. draining dApp.

This function requires 2 parameters to be filled and different combinations of these result in different levels of security;

Parameter 1 `_time`[^12]: The number of blocks that the approval of a third-party service can take place, starting from the current block timestamp.

Parameter 2 `_numberOfTransfers_`[^13]: The number of transactions a third-party service can conduct on the user&apos;s behalf.

The [allowApproval](#allowapproval-function) function requires `_keyWallet1`[^15] or `_keyWallet2`[^16] and enables the **Holding Wallet**[^3] to allow a third-party service by using the `approve` function. These parameters were added to provide extra security when granting permission to a third-party that uses assets on the user&apos;s behalf. Parameter 1, `_time`[^12], is a limitation to when the **Holding Wallet** can `approve` a third-party service. Parameter 2, `_numberOfTransfers`[^13], is a limitation to the number of transactions the approved third-party service can conduct on the user&apos;s behalf before revoking approval.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[^1]: The **Key Wallet/s** refers to `_keyWallet1` or `_keyWallet2` which can call the `safeFallback`, `resetBindings`, `allowTransfer` and `allowApproval` functions.
[^2]: A **Safe Transfer** is when 1 of the **Key Wallets** safely approved the use of the **NFKBT&apos;s**.
[^3]: The **Holding Wallet** refers to the wallet containing the **NFKBT&apos;s**.
[^4]: A **Default Behavior/s** refers to behavior/s present in the preexisting non-fungible ERC-721 standard.
[^5]: The number of crypto scam reports the United States Federal Trade Commission received, from January 2021 through March 2022.
[^6]: The amount stolen via crypto scams according to the United States Federal Trade Commission, from January 2021 through March 2022.
[^7]: A **Default Value/s** refer to a value/s that emulates the non-fungible ERC-721 **Default Behavior/s**.
[^8]: The `_tokenId` represents the ID of the **NFKBT** intended to be spent.
[^9]: The `_time` in `allowTransfer` represents the number of blocks a `transferFrom` can take place in.
[^10]: The `_address` represents the address that the **NFKBT** will be sent to.
[^11]: The `_anyToken` is a bool that can be set to true or false.
[^12]: The `_time` in `allowApproval` represents the number of blocks an `approve` can take place in.
[^13]: The `_numberOfTransfers` is the number of transfers a third-party entity can conduct via `transferFrom` on the user&apos;s behalf.
[^14]: A _PoS_ protocol, Proof-of-Stake protocol, is a cryptocurrency consensus mechanism for processing transactions and creating new blocks in a blockchain.
[^15]: The `_keyWallet1` is 1 of the 2 **Key Wallets** set when calling the `addBindings` function.
[^16]: The `_keyWallet2` is 1 of the 2 **Key Wallets** set when calling the `addBindings` function.
</description>
        <pubDate>Fri, 31 Mar 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6809</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6809</guid>
      </item>
    
      <item>
        <title>Ex Post Facto Cascading Revert</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6810-ex-post-facto-cascading-revert/13630</comments>
        
        <description>## Abstract

A new transaction type reverts one of a sender&apos;s prior transactions, and other transactions dependent on that state, recursively.

## Motivation

While Ethereum has the capability of reversible transactions through smart contracts, instant settlement is the default.
But sometimes users make mistakes.
Most mistakes are discovered quickly.
However, once the transaction is confirmed, it is settled.
There are many use cases for reverting settled transactions.
Some of the most-common mistakes are listed below.

- Wrong recipient
- Unintended consequences
- Got scammed

This feature addresses these issues and more, ending all regret.

## Specification

### Parameters

A new [EIP-2718](/EIPs/EIPS/eip-2718) transaction is introduced with `TransactionType` `0x5a`.
The [EIP-2718](/EIPs/EIPS/eip-2718) `TransactionPayload` for this transaction is `rlp([chainId, nonce, revertNonce, budget, signatureYParity, signatureR, signatureS])`.
The `signatureYParity, signatureR, signatureS` elements of this transaction represent a secp256k1 signature over `keccak256(0x5a || rlp([chainId, nonce, revertNonce, budget]))`.
The [EIP-2718](/EIPs/EIPS/eip-2718) `ReceiptPayload` for this transaction is `rlp([status, budgetUsed, removedLogsBloom, [newReceiptPayloads]])`, where `newReceiptPayloads` is a sequential array of the updated receipts of all reverted transactions.

### Block gas limit

A transaction of type `0x5a` shall be the only transaction in its block.

### Cascading revert operation

A transaction fee budget is initialized to the value specified by `budget`, denominated in ether.
This budget is the transaction fee for this type of transaction.
Reverted transaction fees are refunded from this budget.
Should the budget be insufficient, the Ex Post Facto Cascading Revert transaction fails and the entire budget is paid to the `COINBASE` specified in the block header.
Otherwise, the remainder of the budget after all transactions are reverted is paid to the `COINBASE` account.

The state is rolled back to the start of the transaction specified by `revertNonce`.
An access list is initialized empty.
Any state previously modified by a reverted transaction is added to the access list.
Any subsequent transaction reading or using state included in the access list must also be reverted.
This operation cascades forward until the current block.

State includes:

- ether balance
- contract code
- account nonce
- storage keys

### Snap sync

Due to the large amount of state that may be modified by such a transaction, slower clients should use snap sync to load the new state.

## Rationale

The transaction must fill the entire block to prevent MEV attacks.

While some cascading reverts are highly consequential, others are considerably simpler.
The budget ensures the full network cost of the operation is paid.
For example, reversing a token transfer to the wrong recipient would be relatively cheap.
On the other hand, it would be prohibitively expensive to revert all deposits to a custodial exchange.

Transaction fees must be refunded from this budget rather than the prior block reward in order to protect the security of the consensus protocol.

Snap sync should be safe because if the state root is invalid then the block producer could get slashed.

## Backwards Compatibility

If we find any backwards compatibility issue we can maybe reverse those transactions.
If that doesn&apos;t work idk maybe need another hard fork.

## Test Cases

- Reverting a transaction that ever funded an account reverts all of that account&apos;s subsequent transactions.
- Reverting the transaction that deploys a contract reverts all transactions interacting with that contract.
- Reverting a transfer to a new account does not revert other transactions.

## Reference Implementation

Seems simple enough.
TODO this later; should only take a few hours, tops.

## Security Considerations

This specification has been audited by Illinois Senator Robert Peters.
No exploits were found.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 01 Apr 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6810</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6810</guid>
      </item>
    
      <item>
        <title>To The Moon—10 Minute Blocks</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/ethereum-to-the-moon/13633</comments>
        
        <description>## Abstract

This EIP makes a minimal number of changes to allow Ethereum to be used on the moon and other potentially habitable bodies in Earth&apos;s solar system. It changes the time between blocks, the per-block validator reward, and the number of blocks per epoch.

## Motivation

It is impossible for today&apos;s Ethereum to literally &quot;go to the moon&quot; due to a limitation in the protocol: the block length. Should validators attempt to validate on the surface of the moon, they would find that the ~1.25 second communication delay (caused by the speed of light) might cause issues with synchronization, considering the 12-second timer between blocks. The validators would eventually be ejected on the terrestrial chain after leaking. If however a substantial number of validators are displaced (think 1/3), they might follow their own fork and would eventually eject the terrestrial to finalize their own chain.

## Specification

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

* The time between blocks MUST be changed from 12 seconds to 600 seconds (10 minutes).
* The per-block validator reward MUST be multiplied by 50
* The number of blocks per epoch MUST be reduced from 4 to 2

## Rationale

* The block gas limit is multiplied by fifty to compensate for the time between blocks being multiplied by fifty.
* The per-block validator reward is also multiplied by fifty to compensate for the time between blocks being multiplied by fifty.
* Epochs are changed to be 2 blocks long so that finality can be reached in a reasonable amount of time.

## Backwards Compatibility

Many applications expect mainnet transactions to be included in a short amount of time. This would clearly no longer be the case. Such applications should switch to planetary rollups. Syncing rollups across heavenly bodies is outside the scope of this proposal.

## Test Cases

TODO.

## Security Considerations

Definitely needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 01 Apr 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6811</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6811</guid>
      </item>
    
      <item>
        <title>Support ENS Name for Web3 URL</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6821-support-ens-name-for-web3-url/13654</comments>
        
        <description>## Abstract

This standard defines the mapping from an Ethereum name service (ENS) name to an Ethereum address for [ERC-4804](/EIPs/EIPS/eip-4804).

## Motivation

ERC-4804 defines a `web3://`-scheme RFC 2396 URI to call a smart contract either by its address or a **name** from name service.  If a **name** is specified, the standard specifies a way to resolve the contract address from the name.

## Specification

Given **contractName** and **chainid** from a `web3://` URI defined in ERC-4804, the protocol will find the address of the contract using the following steps:

1. Find the `contentcontract` text record on ENS resolver on chain **chainid**.  Return an error if the chain does not have ENS or the record is an invalid ETH address.
2. If the `contentcontract` text record does not exist, the protocol will use the resolved address of **name** from [ERC-137](/EIPs/EIPS/eip-137#contract-address-interface).
3. If the resolved address of **name** is the zero address, then return an &quot;address not found&quot; error.

Note that `contentcontract` text record may return an Ethereum address in hexadecimal with a `0x` prefix or an [ERC-3770](/EIPs/EIPS/eip-3770) chain-specific address.  If the address is an ERC-3770 chain-specific address, then the **chainid** to call the message will be overridden by the **chainid** specified by the ERC-3770 address.

## Rationale

The standard uses `contentcontract` text record with ERC-3770 chain-specific address instead of `contenthash` so that the record is human-readable - a design principle of ERC-4804.  Further, we can use the text record to add additional fields such as time to live (TTL).

## Security Considerations

No security considerations were found.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 02 Apr 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6821</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6821</guid>
      </item>
    
      <item>
        <title>Token Mapping Slot Retrieval Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6823-token-mapping-slot-retrieval-extension/13666</comments>
        
        <description>## Abstract

The aim of this proposal is to enhance the precision of off-chain simulations for transactions that involve contracts complying with the [ERC-20](/EIPs/EIPS/eip-20), [ERC-721](/EIPs/EIPS/eip-721), or [ERC-1155](/EIPs/EIPS/eip-1155) standards. To achieve this, a method is proposed for obtaining the reserved storage slot of the mapping responsible to track ownership of compliant tokens. The proposed extension offers a standardized entry point that allows for identifying the reserved storage slot of a mapping in a compatible manner. This not only facilitates capturing state changes more precisely but also enables external tools and services to do so without requiring expertise in the particular implementation details.

## Motivation

To understand the rationale behind this proposal, it&apos;s important to remember how values and mapping are stored in the storage layout. This procedure is language-agnostic; it can be applied to multiple programming languages beyond Solidity, including Vyper.

The storage layout is a way to persistently store data in Ethereum smart contracts. In the EVM, storage is organized as a key-value store, where each key is a 32-byte location, and each value is a 32-byte word. When you define a state variable in a contract, it is assigned to a storage location. The location is determined by the variable&apos;s position in the contract&apos;s storage structure. The first variable in the contract is assigned to location 0, the second to location 1, and so on. Multiple values less than 32 bytes can be grouped to fit in a single slot if possible.

Due to their indeterminate size, mappings utilize a specialized storage arrangement. Instead of storing mappings &quot;in between&quot; state variables, they are allocated to occupy 32 bytes only, and their elements are stored in a distinct storage slot computed through a keccak-256 hash. The location of the value corresponding to a mapping key `k` is determined by concatenating `h(k)` and `p` and performing a keccak-256 hash. The value of `p` is the position of the mapping in the storage layout, which depends on the order and the nature of the variables initialized before the mapping. It can&apos;t be determined in a universal way as you have to know how the implementation of the contract is done.

Due to the nature of the mapping type, it is challenging to simulate transactions that involve smart contracts because the storage layout for different contracts is unique to their specific implementation, etched by their variable requirements and the order of their declaration. Since the storage location of a value in a mapping variable depends on this implementation-sensitive storage slot, we cannot guarantee similarity on the off-chain simulation version that an on-chain attempted interaction will result in.

This hurdle prevents external platforms and tools from capturing/validating changes made to the contract&apos;s state with certainty.

That&apos;s why transaction simulation relies heavily on events. However, this approach has limitations, and events should only be informative and not relied upon as the single source of truth. The state is and must be the only source of truth. Furthermore, it is impossible to know the shape of the storage deterministically and universally, which prevents us from verifying the source of truth that is storage, forcing us to rely on information emitted from the application layer.

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119 and RFC 8174.

The proposal suggests an extension to the ERC-20/ERC-721/ERC-1155 standards that allows retrieving the reserved storage slot for the mapping type in any compliant smart-contract implementation in a deterministic manner. This method eliminates the reliance on events and enhances the precision of the data access from storage. The proposed extension therefore enables accurate off-chain simulations. The outcome is greater transparency and predictability at no extra cost for the caller, and a negigleable increase in the deployment cost of the contract.

The proposed extension is a single function that returns the reserved storage slot for the mapping type in any ERC-20/ERC-721/ERC-1155 compliant smart-contract implementation. The function is named `getTokenLocationRoot` and is declared as follows:

```solidity
abstract contract ERC20Extension is ERC20 {
    function getTokenLocationRoot() external pure virtual returns (bytes32 slot) {
        assembly {
            slot := &lt;mapping_name&gt;.slot
        }
    }
}

abstract contract ERC721Extension is ERC721 {
    function getTokenLocationRoot() external pure virtual returns (bytes32 slot) {
        assembly {
            slot := &lt;mapping_name&gt;.slot
        }
    }
}

abstract contract ERC1155Extension is ERC1155 {
    function getTokenLocationRoot() external pure virtual returns (bytes32 slot) {
        assembly {
            slot := &lt;mapping_name&gt;.slot
        }
    }
}
```

For these contracts, off-chain callers can use the `getTokenLocationRoot()` function to find the reserved storage slot for the mapping type. This function returns the reserved storage slot for the mapping type in the contract. This location is used to calculate where all the values of the mapping will be stored. Knowing this value makes it possible to determine precisely where each value of the mapping will be stored, regardless of the contract&apos;s implementation. The caller can use this slot to calculate the storage slot for a specific token ID and compare the value to the expected one to verify the action stated by the event. In the case of a ERC-721 mint, the caller can compare the value of the storage slot to the address of the token&apos;s owner. In the case of a ERC-20 transfer, the caller can compare the value of the storage slot to the address of the token&apos;s new owner. In the case of a ERC-1155 burn, the caller can compare the value of the storage slot to the zero address. The off-chain comparison can be performed with any of the many tools available. In addition, it could perhaps allow storage to be proven atomically by not proving the entire state but only a location -- to track ownership of a specific token, for example.

The name of the function is intentionally generic to allow the same implementation for all the different token standards. Once implemented universally, the selector derived from the signature of this function will be a single, universal entry point that can be used to directly read the slots in the storage responsible of the ownership, of any token contract. This will make off-chain simulations significantly more accurate, and the events will be used for informational purposes only.

Contract implementers MUST implement the `getTokenLocationRoot()` function in their contracts. The function MUST return the reserved storage slot for the mapping type in the contract. The function SHOULD be declared as `external pure`.

## Rationale

The idea behind the implementation was to find an elegant and concise way that avoided any breaking changes with the current standard. Moreover, since gas consumption is crucial, it was inconceivable to find an implementation that would cost gas to the final user. In this case, the addition of a function increases the deployment cost of the contract in a minimal way, but its use is totally free for the external actors.

The implementation is minimalist in order to be as flexible as possible while being directly compatible with the main programming languages used today to develop smart-contracts for the EVM.

## Backwards Compatibility

No backward compatibility issues have been found.

## Reference Implementation

```solidity
abstract contract ERC20Extension is ERC20 {
    function getTokenLocationRoot() external pure virtual returns (bytes32 slot) {
        assembly {
            slot := &lt;mapping_name&gt;.slot
        }
    }
}

abstract contract ERC721Extension is ERC721 {
    function getTokenLocationRoot() external pure virtual returns (bytes32 slot) {
        assembly {
            slot := &lt;mapping_name&gt;.slot
        }
    }
}

abstract contract ERC1155Extension is ERC1155 {
    function getTokenLocationRoot() external pure virtual returns (bytes32 slot) {
        assembly {
            slot := &lt;mapping_name&gt;.slot
        }
    }
```

## Security Considerations

No security issues are raised by the implementation of this extension.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 29 Mar 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6823</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6823</guid>
      </item>
    
      <item>
        <title>Web3 URL to EVM Call Message Translation</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-4804-web3-url-to-evm-call-message-translation/8300</comments>
        
        <description>## Abstract

This standard translates an [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986) URI like `web3://uniswap.eth/` to an EVM message such as:

```
EVMMessage {
   To: 0xaabbccddee.... // where uniswap.eth&apos;s address registered at ENS
   Calldata: 0x
   ...
}
```

⚠️ This proposal updates [ERC-4804](/EIPs/EIPS/eip-4804) with minor corrections, clarifications and modifications.

## Motivation

Currently, reading data from Web3 generally relies on a translation done by a Web2 proxy to Web3 blockchain. The translation is mostly done by the proxies such as dApp websites/node service provider/etherscan, which are out of the control of users. The standard here aims to provide a simple way for Web2 users to directly access the content of Web3, especially on-chain Web contents such as SVG/HTML.  Moreover, this standard enables interoperability with other standards already compatible with URIs, like SVG/HTML.

## Specification

This specification only defines read-only (i.e. Solidity&apos;s `view` functions) semantics. State modifying functions may be defined as a future extension.

This specification uses the Augmented Backus-Naur Form (ABNF) notation of [RFC 2234](https://www.rfc-editor.org/rfc/rfc2234). The complete URI syntax is listed in Appendix A.

A Web3 URL is an ASCII string in the following form :

```
web3URL         = schema &quot;://&quot; [ userinfo &quot;@&quot; ] contractName [ &quot;:&quot; chainid ] pathQuery [ &quot;#&quot; fragment ]
schema          = &quot;w3&quot; / &quot;web3&quot;
userinfo        = address
```

**userinfo** indicates which user is calling the EVM, i.e., &quot;From&quot; field in EVM call message. If not specified, the protocol will use 0x0 as the sender address.

```
contractName    = address 
                / domainName
address         = &quot;0x&quot; 20( HEXDIG HEXDIG )
domainName      = *( unreserved / pct-encoded / sub-delims ) ; As in RFC 3986
```

**contractName** indicates the contract to be called, i.e., the &quot;To&quot; field in the EVM call message. If the **contractName** is an address then it will be used for the &quot;To&quot; field. Otherwise, **contractName** is a domain name from a domain name service, and it must be resolved to an address to use for the &quot;To&quot; field.

The way to resolve the domain name from a domain name service to an address is specified in [ERC-6821](/EIPs/EIPS/eip-6821) for the Ethereum Name service, and will be discussed in later ERCs for other name services. 

```
chainid         = %x31-39 *DIGIT
```

**chainid** indicates which chain to resolve **contractName** and call the message. If not specified, the protocol will use the primary chain of the name service provider used, e.g., 1 for eth. If no name service provider was used, the default chainid is 1.

```
pathQuery       = mPathQuery ; path+query for manual mode
                / aPathQuery ; path+query for auto mode
```

**pathQuery**, made of the path and optional query, will have a different structure whether the resolve mode is &quot;manual&quot; or &quot;auto&quot;.

```
fragment        = *VCHAR
```

**fragment**, like in HTTP URLs, is a string of characters meant to refer to a resource, and is not transmitted to the smart contract.

```
web3UrlRef      = web3URL 
                / relativeWeb3URL
relativeWeb3URL = relPathQuery
relPathQuery    = relMPathQuery ; Relative URL path+query for manual mode
                / relAPathQuery ; Relative URL path+query for auto mode
```

Relative URLs are supported, but the support differs based on the resolve mode.


### Resolve Mode

Once the &quot;To&quot; address and chainid are determined, the protocol will check the resolver mode of contract by calling the `resolveMode` method of the &quot;To&quot; address. The Solidity signature of `resolveMode` is:

```solidity
function resolveMode() external returns (bytes32);
```

The protocol currently supports two resolve modes: auto and manual.

- The manual mode will be used if the `resolveMode` return value is `0x6d616e75616c0000000000000000000000000000000000000000000000000000`, i.e., &quot;manual&quot; in bytes32
- The auto mode will be used if :
    - the `resolveMode` return value is `0x6175746f00000000000000000000000000000000000000000000000000000000`, i.e, &quot;auto&quot; in bytes32, or
    - the `resolveMode` return value is `0x0000000000000000000000000000000000000000000000000000000000000000`, or
    - the call to `resolveMode` throws an error (method not implemented or error thrown from the method)
- Otherwise, the protocol will fail the request with the error &quot;unsupported resolve mode&quot;.

#### Manual Mode

```
mPathQuery      = mPath [ &quot;?&quot; mQuery ]

mPath           = mPathAbempty ; begins with &quot;/&quot; or is empty
mPathAbempty    = [ *( &quot;/&quot; segment ) &quot;/&quot; segment [ &quot;.&quot; fileExtension ] ]
segment         = *pchar ; as in RFC 3986
fileExtension   = 1*( ALPHA / DIGIT )

mQuery = *( pchar / &quot;/&quot; / &quot;?&quot; ) ; as in RFC 3986
```

The manual mode will use the raw **mPathQuery** as calldata of the message directly (no percent-encoding decoding will be done). If **mPathQuery** is empty, the sent calldata will be ``/`` (0x2f).

The returned message data will be treated as ABI-encoded bytes and the decoded bytes will be returned to the frontend.

The MIME type returned to the frontend is ``text/html`` by default, but will be overridden if a **fileExtension**  is present. In this case, the MIME type will be deduced from the filename extension.

```
relMPathQuery   = relMPath [ &quot;?&quot; mQuery ]
relMPath        = mPathAbsolute ; begins with &quot;/&quot; but not &quot;//&quot;
                / mPathNoscheme ; begins with a non-colon segment
                / mPathEmpty    ; zero characters

mPathAbsolute   = &quot;/&quot; [ segmentNz *( &quot;/&quot; segment ) ] [ &quot;.&quot; fileExtension ]
mPathNoscheme   = segmentNzNc *( &quot;/&quot; segment ) [ &quot;.&quot; fileExtension ]
mPathEmpty      = 0&lt;pchar&gt;

segmentNz       = 1*pchar ; as in RFC 3986
segmentNzNc     = 1*( unreserved / pct-encoded / sub-delims / &quot;@&quot; )
                ; as in RFC 3986: non-zero-length segment without any colon &quot;:&quot;
```

Support for manual mode relative URLs is similar to HTTP URLs : URLs relative to the current contract are allowed, both with an absolute path and a relative path.

#### Auto Mode

```
aPathQuery      = aPath [ &quot;?&quot; aQuery ]
aPath           = [ &quot;/&quot; [ method *( &quot;/&quot; argument ) ] ]
```

In the auto mode, if **aPath** is empty or &quot;/&quot;, then the protocol will call the target contract with empty calldata. Otherwise, the calldata of the EVM message will use standard Solidity contract ABI.

```
method          = ( ALPHA / &quot;$&quot; / &quot;_&quot; ) *( ALPHA / DIGIT / &quot;$&quot; / &quot;_&quot; )
```

**method** is a string of the function method to be called

```
argument        = boolArg
                / uintArg
                / intArg
                / addressArg
                / bytesArg
                / stringArg
boolArg         = [ &quot;bool!&quot; ] ( &quot;true&quot; / &quot;false&quot; )
uintArg         = [ &quot;uint&quot; [ intSizes ] &quot;!&quot; ] 1*DIGIT
intArg          = &quot;int&quot; [ intSizes ] &quot;!&quot; 1*DIGIT
intSizes        = &quot;8&quot; / &quot;16&quot; / &quot;24&quot; / &quot;32&quot; / &quot;40&quot; / &quot;48&quot; / &quot;56&quot; / &quot;64&quot; / &quot;72&quot; / &quot;80&quot; / &quot;88&quot; / &quot;96&quot; / &quot;104&quot; / &quot;112&quot; / &quot;120&quot; / &quot;128&quot; / &quot;136&quot; / &quot;144&quot; / &quot;152&quot; / &quot;160&quot; / &quot;168&quot; / &quot;176&quot; / &quot;184&quot; / &quot;192&quot; / &quot;200&quot; / &quot;208&quot; / &quot;216&quot; / &quot;224&quot; / &quot;232&quot; / &quot;240&quot; / &quot;248&quot; / &quot;256&quot;
addressArg      = [ &quot;address!&quot; ] ( address / domainName )
bytesArg        = [ &quot;bytes!&quot; ] bytes
                / &quot;bytes1!0x&quot; 1( HEXDIG HEXDIG )
                / &quot;bytes2!0x&quot; 2( HEXDIG HEXDIG )
                ...
                / &quot;bytes32!0x&quot; 32( HEXDIG HEXDIG )
stringArg       = &quot;string!&quot; *pchar [ &quot;.&quot; fileExtension ]
```

**argument** is an argument of the method with a type-agnostic syntax of ``[ type &quot;!&quot; ] value``. If **type** is specified, the value will be translated to the corresponding type. The protocol currently supports these basic types: bool, int, uint, int&amp;lt;X&amp;gt;, uint&amp;lt;X&amp;gt; (with X ranging from 8 to 256 in steps of 8), address, bytes&amp;lt;X&amp;gt; (with X ranging from 1 to 32), bytes, and string. If **type** is not specified, then the type will be automatically detected using the following rule in a sequential way:

  1. **type**=&quot;uint256&quot;, if **value** is digits; or
  2. **type**=&quot;bytes32&quot;, if **value** is in the form of 0x+32-byte-data hex; or
  3. **type**=&quot;address&quot;, if **value** is in the form of 0x+20-byte-data hex; or
  4. **type**=&quot;bytes&quot;, if **value** is in the form of 0x followed by any number of bytes besides 20 or 32; or
  5. **type**=&quot;bool&quot;, if **value** is either ``true`` or ``false``; or
  6. else **type**=&quot;address&quot; and parse the argument as a domain name. If unable to resolve the domain name, an unsupported name service provider error will be returned. 


```
aQuery          = attribute *( &quot;&amp;&quot; attribute )
attribute       = attrName &quot;=&quot; attrValue
attrName        = &quot;returns&quot;
                / &quot;returnTypes&quot;
attrValue       = [ &quot;(&quot; [ retTypes ] &quot;)&quot; ]
retTypes        = retType *( &quot;,&quot; retType )
retType         = retRawType *( &quot;[&quot; [ %x31-39 *DIGIT ] &quot;]&quot; )
retRawType      = &quot;(&quot; retTypes &quot;)&quot;
                / retBaseType
retBaseType      = &quot;bool&quot; / &quot;uint&quot; [ intSizes ] / &quot;int&quot; [ intSize ] / &quot;address&quot; / &quot;bytes&quot; [ bytesSizes ] / &quot;string&quot;
bytesSizes      = %x31-39              ; 1-9
                / ( &quot;1&quot; / &quot;2&quot; ) DIGIT  ; 10-29
                / &quot;31&quot; / &quot;32&quot;          ; 31-32
```

The &quot;returns&quot; attribute in **aQuery** tells the format of the returned data. It follows the syntax of the arguments part of the ethereum ABI function signature (``uint`` and ``int`` aliases are authorized).

- If the &quot;returns&quot; attribute value is undefined or empty, the returned message data will be treated as ABI-encoded bytes and the decoded bytes will be returned to the frontend. The MIME type returned to the frontend will be undefined by default, but will be overridden if the last argument is of string type and has a **fileExtension**, in which case the MIME type will be deduced from the filename extension. (Note that **fileExtension** is not excluded from the string argument given to the smartcontract)
- If the &quot;returns&quot; attribute value is equal to &quot;()&quot;, the raw bytes of the returned message data will be returned, encoded as a &quot;0x&quot;-prefixed hex string in an array in JSON format: ``[&quot;0xXXXXX&quot;]``
- Otherwise, the returned message data will be ABI-decoded in the data types specified in the **returns** value and encoded in JSON format. The encoding of the data will follow the Ethereum JSON-RPC format:
  - Unformatted data (bytes, address) will be encoded as hex, prefixed with &quot;0x&quot;, two hex digits per byte
  - Quantities (integers) will be encoded as hex, prefix with &quot;0x&quot;, the most compact representation (slight exception: zero should be represented as &quot;0x0&quot;)
  - Boolean and strings will be native JSON boolean and strings
    
If multiple &quot;returns&quot; attributes are present, the value of the last &quot;returns&quot; attribute will be applied. Note that &quot;returnTypes&quot; is the alias of &quot;returns&quot;, but it is not recommended to use and is mainly for [ERC-4804](/EIPs/EIPS/eip-4804) backward-compatible purpose.

```
relAPathQuery   = aPath [ &quot;?&quot; aQuery ]
```

Support for auto mode relative URLs is limited : URLs relative to the current contract are allowed and will either reference itself (empty), the ``/`` path or a full method and its arguments.

### Examples

#### Example 1a

```
web3://w3url.eth/
```

where the contract of **w3url.eth** is in manual mode.

The protocol will find the address of **w3url.eth** from ENS in chainid 1 (Mainnet). Then the protocol will call the address with &quot;Calldata&quot; = `keccak(&quot;resolveMode()&quot;)[0:4]` = &quot;0xDD473FAE&quot;, which returns &quot;manual&quot; in ABI-type &quot;(bytes32)&quot;. After determining the manual mode of the contract, the protocol will call the address with &quot;To&quot; = **contractAddress** and &quot;Calldata&quot; = &quot;0x2F&quot;. The returned data will be treated as ABI-type &quot;(bytes)&quot;, and the decoded bytes will be returned to the frontend, with the information that the MIME type is ``text/html``.

#### Example 1b

```
web3://w3url.eth/
```

where the contract of **w3url.eth** is in auto mode.

The protocol will find the address of **w3url.eth** from ENS in chainid 1 (Mainnet). Then the protocol will call the address with &quot;Calldata&quot; = `keccak(&quot;resolveMode()&quot;)[0:4]` = &quot;0xDD473FAE&quot;, which returns &quot;&quot;, i.e., the contract is in auto mode. After determining the auto mode of the contract, the protocol will call the address with &quot;To&quot; = **contractAddress** and &quot;Calldata&quot; = &quot;&quot;. The returned data will be treated as ABI-type &quot;(bytes)&quot;, and the decoded bytes will be returned to the frontend, with the information that the MIME type is undefined.

#### Example 2

```
web3://cyberbrokers-meta.eth/renderBroker/9999
```

where the contract of **cyberbrokers-meta.eth** is in auto mode.

The protocol will find the address of **cyberbrokers-meta.eth** from ENS on chainid 1 (Mainnet). Then the protocol will call the address with &quot;Calldata&quot; = `keccak(&quot;resolveMode()&quot;)[0:4]` = &quot;0xDD473FAE&quot;, which returns &quot;&quot;, i.e., the contract is in auto mode. After determining the auto mode of the contract, the protocol will call the address with &quot;To&quot; = **contractAddress** and &quot;Calldata&quot; = &quot;0x&quot; + `keccak(&quot;renderBroker(uint256)&quot;)[0:4] + abi.encode(uint256(9999))`. The returned data will be treated as ABI-type &quot;(bytes)&quot;, and the decoded bytes will be returned to the frontend, with the information that the MIME type is undefined.

#### Example 3

```
web3://vitalikblog.eth:5/
```

where the contract of **vitalikblog.eth:5** is in manual mode.

The protocol will find the address of **vitalikblog.eth** from ENS on chainid 5 (Goerli). Then after determining the contract is in manual mode, the protocol will call the address with &quot;To&quot; = **contractAddress** and &quot;Calldata&quot; = &quot;0x2F&quot; with chainid = 5. The returned data will be treated as ABI-type &quot;(bytes)&quot;, and the decoded bytes will be returned to the frontend, with the information that the MIME type is ``text/html``.

#### Example 4

```
web3://0xe4ba0e245436b737468c206ab5c8f4950597ab7f:42170/
```

where the contract &quot;0xe4ba0e245436b737468c206ab5c8f4950597ab7f:42170&quot; is in manual mode.

After determining the contract is in manual mode, the protocol will call the address with &quot;To&quot; = &quot;0xe4ba0e245436b737468c206ab5c8f4950597ab7f&quot; and &quot;Calldata&quot; = &quot;0x2F&quot; with chainid = 42170 (Arbitrum Nova). The returned data will be treated as ABI-type &quot;(bytes)&quot;, and the decoded bytes will be returned to the frontend, with the information that the MIME type is ``text/html``.

#### Example 5

```
web3://0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/balanceOf/vitalik.eth?returns=(uint256)
```

where the contract &quot;0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48&quot; is in auto mode.

The protocol will find the addresses of **vitalik.eth** from ENS on chainid 1 (Mainnet) and then call the method &quot;balanceOf(address)&quot; of the contract with the **vitalik.eth**&apos;s address. The returned data from the call of the contract will be treated as ABI-type &quot;(uint256)&quot;, and the decoded data will be returned to the frontend in JSON format like `[ &quot;0x9184e72a000&quot; ]`, with the information that the MIME type is ``application/json``.

#### Example 6

```
web3://0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/balanceOf/vitalik.eth?returns=()
```

where the contract ”0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48“ is in auto mode.

The protocol will find the address of **vitalik.eth** from ENS on chainid 1 (Mainnet) and then call the method &quot;balanceOf(address)&quot; of the address. The returned data from the call of the contract will be treated as raw bytes and will be encoded in JSON format like `[&quot;0x000000000000000000000000000000000000000000000000000009184e72a000&quot;]` and returned to the frontend, with the information that the MIME type is ``application/json``.

### Appendix A: Complete ABNF for Web3 URLs

```
web3URL         = schema &quot;://&quot; [ userinfo &quot;@&quot; ] contractName [ &quot;:&quot; chainid ] pathQuery [ &quot;#&quot; fragment ]
schema          = &quot;w3&quot; / &quot;web3&quot;
userinfo        = address
contractName    = address 
                / domainName
chainid         = %x31-39 *DIGIT

pathQuery       = mPathQuery ; path+query for manual mode
                / aPathQuery ; path+query for auto mode
fragment        = *VCHAR

web3UrlRef      = web3URL 
                / relativeWeb3URL
relativeWeb3URL = relPathQuery
relPathQuery    = relMPathQuery ; Relative URL path+query for manual mode
                / relAPathQuery ; Relative URL path+query for auto mode

mPathQuery      = mPath [ &quot;?&quot; mQuery ]
mPath           = mPathAbempty ; begins with &quot;/&quot; or is empty

relMPathQuery   = relMPath [ &quot;?&quot; mQuery ]
relMPath        = mPathAbsolute ; begins with &quot;/&quot; but not &quot;//&quot;
                / mPathNoscheme ; begins with a non-colon segment
                / mPathEmpty    ; zero characters

mPathAbempty    = [ *( &quot;/&quot; segment ) &quot;/&quot; segment [ &quot;.&quot; fileExtension ] ]
mPathAbsolute   = &quot;/&quot; [ segmentNz *( &quot;/&quot; segment ) ] [ &quot;.&quot; fileExtension ]
mPathNoscheme   = segmentNzNc *( &quot;/&quot; segment ) [ &quot;.&quot; fileExtension ]
mPathEmpty      = 0&lt;pchar&gt;

segment         = *pchar ; as in RFC 3986
segmentNz       = 1*pchar ; as in RFC 3986
segmentNzNc     = 1*( unreserved / pct-encoded / sub-delims / &quot;@&quot; )
                ; as in RFC 3986: non-zero-length segment without any colon &quot;:&quot;

mQuery          = *( pchar / &quot;/&quot; / &quot;?&quot; ) ; as in RFC 3986

aPathQuery      = aPath [ &quot;?&quot; aQuery ]
aPath           = [ &quot;/&quot; [ method *( &quot;/&quot; argument ) ] ]
relAPathQuery   = aPath [ &quot;?&quot; aQuery ]
method          = ( ALPHA / &quot;$&quot; / &quot;_&quot; ) *( ALPHA / DIGIT / &quot;$&quot; / &quot;_&quot; )
argument        = boolArg
                / uintArg
                / intArg
                / addressArg
                / bytesArg
                / stringArg
boolArg         = [ &quot;bool!&quot; ] ( &quot;true&quot; / &quot;false&quot; )
uintArg         = [ &quot;uint&quot; [ intSizes ] &quot;!&quot; ] 1*DIGIT
intArg          = &quot;int&quot; [ intSizes ] &quot;!&quot; 1*DIGIT
intSizes        = &quot;8&quot; / &quot;16&quot; / &quot;24&quot; / &quot;32&quot; / &quot;40&quot; / &quot;48&quot; / &quot;56&quot; / &quot;64&quot; / &quot;72&quot; / &quot;80&quot; / &quot;88&quot; / &quot;96&quot; / &quot;104&quot; / &quot;112&quot; / &quot;120&quot; / &quot;128&quot; / &quot;136&quot; / &quot;144&quot; / &quot;152&quot; / &quot;160&quot; / &quot;168&quot; / &quot;176&quot; / &quot;184&quot; / &quot;192&quot; / &quot;200&quot; / &quot;208&quot; / &quot;216&quot; / &quot;224&quot; / &quot;232&quot; / &quot;240&quot; / &quot;248&quot; / &quot;256&quot;
addressArg      = [ &quot;address!&quot; ] ( address / domainName )
bytesArg        = [ &quot;bytes!&quot; ] bytes
                / &quot;bytes1!0x&quot; 1( HEXDIG HEXDIG )
                / &quot;bytes2!0x&quot; 2( HEXDIG HEXDIG )
                / &quot;bytes3!0x&quot; 3( HEXDIG HEXDIG )
                / &quot;bytes4!0x&quot; 4( HEXDIG HEXDIG )
                / &quot;bytes5!0x&quot; 5( HEXDIG HEXDIG )
                / &quot;bytes6!0x&quot; 6( HEXDIG HEXDIG )
                / &quot;bytes7!0x&quot; 7( HEXDIG HEXDIG )
                / &quot;bytes8!0x&quot; 8( HEXDIG HEXDIG )
                / &quot;bytes9!0x&quot; 9( HEXDIG HEXDIG )
                / &quot;bytes10!0x&quot; 10( HEXDIG HEXDIG )
                / &quot;bytes11!0x&quot; 11( HEXDIG HEXDIG )
                / &quot;bytes12!0x&quot; 12( HEXDIG HEXDIG )
                / &quot;bytes13!0x&quot; 13( HEXDIG HEXDIG )
                / &quot;bytes14!0x&quot; 14( HEXDIG HEXDIG )
                / &quot;bytes15!0x&quot; 15( HEXDIG HEXDIG )
                / &quot;bytes16!0x&quot; 16( HEXDIG HEXDIG )
                / &quot;bytes17!0x&quot; 17( HEXDIG HEXDIG )
                / &quot;bytes18!0x&quot; 18( HEXDIG HEXDIG )
                / &quot;bytes19!0x&quot; 19( HEXDIG HEXDIG )
                / &quot;bytes20!0x&quot; 20( HEXDIG HEXDIG )
                / &quot;bytes21!0x&quot; 21( HEXDIG HEXDIG )
                / &quot;bytes22!0x&quot; 22( HEXDIG HEXDIG )
                / &quot;bytes23!0x&quot; 23( HEXDIG HEXDIG )
                / &quot;bytes24!0x&quot; 24( HEXDIG HEXDIG )
                / &quot;bytes25!0x&quot; 25( HEXDIG HEXDIG )
                / &quot;bytes26!0x&quot; 26( HEXDIG HEXDIG )
                / &quot;bytes27!0x&quot; 27( HEXDIG HEXDIG )
                / &quot;bytes28!0x&quot; 28( HEXDIG HEXDIG )
                / &quot;bytes29!0x&quot; 29( HEXDIG HEXDIG )
                / &quot;bytes30!0x&quot; 30( HEXDIG HEXDIG )
                / &quot;bytes31!0x&quot; 31( HEXDIG HEXDIG )
                / &quot;bytes32!0x&quot; 32( HEXDIG HEXDIG )
stringArg       = &quot;string!&quot; *pchar [ &quot;.&quot; fileExtension ]

aQuery          = attribute *( &quot;&amp;&quot; attribute )
attribute       = attrName &quot;=&quot; attrValue
attrName        = &quot;returns&quot;
                / &quot;returnTypes&quot;
attrValue       = [ &quot;(&quot; [ retTypes ] &quot;)&quot; ]
retTypes        = retType *( &quot;,&quot; retType )
retType         = retRawType *( &quot;[&quot; [ %x31-39 *DIGIT ] &quot;]&quot; )
retRawType      = &quot;(&quot; retTypes &quot;)&quot;
                / retBaseType
retBaseType      = &quot;bool&quot; / &quot;uint&quot; [ intSizes ] / &quot;int&quot; [ intSize ] / &quot;address&quot; / &quot;bytes&quot; [ bytesSizes ] / &quot;string&quot;
bytesSizes      = %x31-39              ; 1-9
                / ( &quot;1&quot; / &quot;2&quot; ) DIGIT  ; 10-29
                / &quot;31&quot; / &quot;32&quot;          ; 31-32

domainName      = *( unreserved / pct-encoded / sub-delims ) ; As in RFC 3986

fileExtension   = 1*( ALPHA / DIGIT )

address         = &quot;0x&quot; 20( HEXDIG HEXDIG )
bytes           = &quot;0x&quot; *( HEXDIG HEXDIG )

pchar           = unreserved / pct-encoded / sub-delims / &quot;:&quot; / &quot;@&quot; ; As in RFC 3986

pct-encoded     = &quot;%&quot; HEXDIG HEXDIG ; As in RFC 3986

unreserved      = ALPHA / DIGIT / &quot;-&quot; / &quot;.&quot; / &quot;_&quot; / &quot;~&quot; ; As in RFC 3986
sub-delims    = &quot;!&quot; / &quot;$&quot; / &quot;&amp;&quot; / &quot;&apos;&quot; / &quot;(&quot; / &quot;)&quot;
                / &quot;*&quot; / &quot;+&quot; / &quot;,&quot; / &quot;;&quot; / &quot;=&quot; ; As in RFC 3986

```

### Appendix B: Changes versus [ERC-4804](/EIPs/EIPS/eip-4804)

#### Corrections

- Manual mode : [ERC-4804](/EIPs/EIPS/eip-4804) stipulates that there is no interpretation of the path [ &quot;?&quot; query ]. This ERC indicates that there is in fact an interpretation of the path, for MIME type determination purpose.
- Auto mode : If there is no **returns** attribute in **query**, [ERC-4804](/EIPs/EIPS/eip-4804) stipulates that the returned data is treated as ABI-encoded bytes32. This ERC indicates that in fact the returned data is treated as ABI-encoded bytes.

#### Clarifications

- Formal specification: This ERC add a ABNF definition of the URL format.
- Resolve mode: This ERC indicates more details on how the resolve mode is determined.
- Manual mode : This ERC indicates how to deal with URI-percent-encoding, the return data, and how the MIME type is determined.
- Auto mode : This ERC indicates in more details the encoding of the argument values, as well as the format and handling of the **returns** value.
- Examples : This ERC add more details to the examples.

#### Modifications

- Protocol name: [ERC-4804](/EIPs/EIPS/eip-4804) mentionned ``ethereum-web3://`` and ``eth-web3://``, these are removed.
- Auto mode: Supported types: [ERC-4804](/EIPs/EIPS/eip-4804) supported only uint256, bytes32, address, bytes, and string. This ERC add more types.
- Auto mode: Encoding of returned integers when a **returns** attribute is specified: [ERC-4804](/EIPs/EIPS/eip-4804) suggested in example 5 to encode integers as strings. This ERC indicates to follow the Ethereum JSON RPC spec and encode integers as a hex string, prefixed with &quot;0x&quot;.

## Rationale

The purpose of the proposal is to add a decentralized presentation layer for Ethereum.  With the layer, we are able to render any web content (including HTML/CSS/JPG/PNG/SVG, etc) on-chain using human-readable URLs, and thus EVM can be served as a decentralized backend.  The design of the standard is based on the following principles:

- **Human-readable**.  The Web3 URL should be easily recognized by human similar to Web2 URL (`http://`).  As a result, we support names from name services to replace address for better readability.  In addition, instead of using calldata in hex, we use human-readable method + arguments and translate them to calldata for better readability.

- **Maximum-Compatible with HTTP-URL standard**.  The Web3 URL should be compatible with HTTP-URL standard including relative pathing, query, fragment, percent-encoding, etc so that the support of existing HTTP-URL (e.g., by browser) can be easily extended to Web3 URL with minimal modification.  This also means that existing Web2 users can easily migrate to Web3 with minimal extra knowledge of this standard.

- **Simple**.  Instead of providing explicit types in arguments, we use a &quot;maximum likelihood&quot; principle of auto-detecting the types of the arguments such as address, bytes32, and uint256.  This could greatly minimize the length of URL, while avoiding confusion.  In addition, explicit types are also supported to clear the confusion if necessary.

- **Flexible**.  The contract is able to override the encoding rule so that the contract has fine-control of understanding the actual Web resources that the users want to locate.

## Security Considerations

No security considerations were found.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 29 Sep 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6860</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6860</guid>
      </item>
    
      <item>
        <title>Upgradable Fungible Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6864-upgradable-fungible-token-a-simple-extension-to-erc-20/13781</comments>
        
        <description>## Abstract

This proposal outlines a smart contract interface for upgrading/downgrading existing [ERC-20](/EIPs/EIPS/eip-20) smart contracts while maintaining user balances. The interface itself is an extension to the ERC-20 standard so that other smart contracts can continue to interact with the upgraded smart contract without changing anything other than the address.

## Motivation

By design, smart contracts are immutable and token standards like ERC-20 are minimalistic. While these design principles are fundamental in decentalized applications, there are sensible and practical situations where the ability to upgrade an ERC-20 token is desirable, such as:

- to address bugs and remove limitations
- to adopt new features and standards
- to comply w/ changing regulations

Proxy pattern using `delegatecall` opcode offers a reasonable, generalized solution to reconcile the immutability and upgradability features but has its own shortcomings:

- the smart contracts must support proxy pattern from the get go, i.e. it cannot be used on contracts that were not deployed with proxies
- upgrades are silent and irreversible, i.e. users do not have the option to opt-out

In contrast, by reducing the scope to specifically ERC-20 tokens, this proposal standardizes an ERC-20 extension that works with any existing or future ERC-20 smart contracts, is much simpler to implement and to maintain, can be reversed or nested, and offers a double confirmation opportunity for any and all users to explicitly opt-in on the upgrade.

[ERC-4931](/EIPs/EIPS/eip-4931) attepts to address the same problem by introducing a third &quot;bridge&quot; contract to help facilitate the upgrade/downgrade operations. While this design decouples upgrade/downgrade logic from token logic, ERC-4931 would require tokens to be pre-minted at the destination smart contract and owned by the bridge contrtact rather then just-in-time when upgrade is invoked. It also would not be able to support upgrade-while-transfer and see-through functions as described below.

## Specification

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

```solidity
pragma solidity ^0.8.0;

/**
    @title Upgradable Fungible Token
    @dev See https://eips.ethereum.org/EIPS/eip-6864
 */
interface IERC6864 is IERC20 {
    /**
      @dev MUST be emitted when tokens are upgraded
      @param from Previous owner of base ERC-20 tokens
      @param to New owner of ERC-6864 tokens
      @param amount The amount that is upgraded
    */
    event Upgrade(address indexed from, address indexed to, uint256 amount);

    /**
      @dev MUST be emitted when tokens are downgraded
      @param from Previous owner of ERC-6864 tokens
      @param to New owner of base ERC-20 tokens
      @param amount The amount that is downgraded
    */
    event Downgrade(address indexed from, address indexed to, uint256 amount);

    /**
      @notice Upgrade `amount` of base ERC-20 tokens owned by `msg.sender` to ERC-6864 tokens under `to`
      @dev `msg.sender` must directly own sufficient base ERC-20 tokens
      MUST revert if `to` is the zero address
      MUST revert if `msg.sender` does not directly own `amount` or more of base ERC-20 tokens
      @param to The address to receive ERC-6864 tokens
      @param amount The amount of base ERC-20 tokens to upgrade
    */
    function upgrade(address to, uint256 amount) external;

    /**
      @notice Downgrade `amount` of ERC-6864 tokens owned by `from` to base ERC-20 tokens under `to`
      @dev `msg.sender` must either directly own or be approved to spend sufficient ERC-6864 tokens for `from`
      MUST revert if `to` is the zero address
      MUST revert if `from` does not directly own `amount` or more of ERC-6864 tokens
      MUST revret if `msg.sender` is not `from` and is not approved to spend `amount` or more of ERC-6864 tokens for `from`
      @param from The address to release ERC-6864 tokens
      @param to The address to receive base ERC-20 tokens
      @param amount The amount of ERC-6864 tokens to downgrade
    */
    function downgrade(address from, address to, uint256 amount) external;

    /**
      @notice Get the base ERC-20 smart contract address
      @return The address of the base ERC-20 smart contract
    */
    function baseToken() external view returns (address);
}
```

### See-through Extension

The **see-through extension** is OPTIONAL. It allows for easy viewing of combined states between this [ERC-6864](/EIPs/EIPS/eip-6864) and base ERC-20 smart contracts.

```solidity
pragma solidity ^0.8.0;

interface IERC6864SeeThrough is IERC6864 {
  /**
    @notice Get the combined total token supply between this ERC-6864 and base ERC-20 smart contracts
    @return The combined total token supply
  */
  function combinedTotalSupply() external view returns (uint256);

  /**
    @notice Get the combined token balance of `account` between this ERC-6864 and base ERC-20 smart contracts
    @param account The address that owns the tokens
    @return The combined token balance
  */
  function combinedBalanceOf(address account) external view returns (uint256);

  /**
    @notice Get the combined allowance that `spender` is allowed to spend for `owner` between this ERC-6864 and base ERC-20 smart contracts
    @param owner The address that owns the tokens
    @param spender The address that is approve to spend the tokens
    @return The combined spending allowance
  */
  function combinedAllowance(address owner, address spender) external view returns (uint256);
}

```

## Rationale

### Extending ERC-20 standard

The goal of this proposal is to upgrade without affecting user balances, therefore leveraging existing data structure and methods is the path of the least engineering efforts as well as the most interoperability.

### Supporting downgrade

The ability to downgrade makes moving between multiple IERC-6864 implementations on the same base ERC-20 smart contract possible. It also allows a way out should bugs or limitations discovered on ERC-6864 smart contract, or the user simply changes his or her mind.

### Optional see-through extension

While these functions are useful in many situations, they are trivial to implement and results can be calculated via other public functions, hence the decision to include them in an optional extension rather than the core interface.

## Backwards Compatibility

ERC-6864 is generally compatible with the ERC-20 standard. The only caveat is that some smart contracts may opt to implement `transfer` to work with the entire combined balance (this reduces user friction, see reference implementation) rather than the standard `balanceOf` amount. In this case it is RECOMMENDED that such contract to implement `totalSupply` and `balanceOf` to return combined amount between this ERC-6864 and base ERC-20 smart contracts

## Reference Implementation

```solidity
import {IERC20, ERC20} from &quot;@openzeppelin-contracts/token/ERC20/ERC20.sol&quot;;

contract ERC6864 is IERC6864, ERC20 {
  IERC20 private immutable s_baseToken;

    constructor(string memory name, string memory symbol, address baseToken_) ERC20(name, symbol) {
        s_baseToken = IERC20(baseToken_);
    }

    function baseToken() public view virtual override returns (address) {
        return address(s_baseToken);
    }

    function upgrade(address to, uint256 amount) public virtual override {
        address from = _msgSender();

        s_baseToken.transferFrom(from, address(this), amount);
        _mint(to, amount);

        emit Upgrade(from, to, amount);
    }

    function downgrade(address from, address to, uint256 amount) public virtual override {
        address spender = _msgSender();

        if (from != spender) {
            _spendAllowance(from, spender, amount);
        }
        _burn(from, amount);
        s_baseToken.transfer(to, amount);

        emit Downgrade(from, to, amount);
    }

    function transfer(address to, uint256 amount) public virtual override returns (bool) {
        address from = _msgSender();
        uint256 balance = balanceOf(from);

        if (balance &lt; amount) {
            upgrade(from, amount - balance);
        }

        _transfer(from, to, amount);
        return true;
    }

    function totalSupply() public view virtual override returns (uint256) {
        return return super.totalSupply() + s_baseToken.totalSupply() - s_baseToken.balanceOf(address(this));
    }

    function balanceOf(address account) public view virtual override returns (uint256) {
        return super.balanceOf(account) + s_baseToken.balanceOf(account);
    }
}
```

## Security Considerations

- User who opts to upgrade base ERC-20 tokens must first `approve` the ERC-6864 smart contract to spend them. Therefore it&apos;s the user&apos;s responsibility to verify that the ERC-6864 smart contract is sound and secure, and the amount that he or she is approving is approperiate. This represents the same security considerations as with any `approve` operation.
- The ERC-6864 smart contract may implement any conversion function for upgrade/downgrade as approperiate: 1-to-1, linear, non-linear. In the case of a non-linear conversion function, `upgrade` and `downgrade` may be vulnerable for front running or sandwich attacks (whether or not to the attacker&apos;s benefit). This represents the same security considerations as with any automated market maker (AMM) that uses a similar non-linear curve for conversion.
- The ERC-6864 smart contract may ask user to approve unlimited allowance and/or attempt to automatically upgrade during `transfer` (see reference implementation). This removes the chance for user to triple confirm his or her intension to upgrade (`approve` being the double confirmation).
- Multiple IERC-6864 implementations can be applied to the same base ERC-20 token, and ERC-6864 smart contracts can be nested. This would increase token complexity and may cause existing dashboards to report incorrect or inconsistent results.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 05 Apr 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6864</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6864</guid>
      </item>
    
      <item>
        <title>On-Chain EIP-712 Visualization</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6865-on-chain-eip-712-visualization/13800</comments>
        
        <description>## Abstract

Numerous protocols employ distinct [EIP-712](/EIPs/EIPS/eip-712) schemas, leading to unavoidable inconsistencies across the ecosystem. To address this issue, we propose a standardized approach for dApps to implement an on-chain view function called `visualizeEIP712Message`. This function takes an abi encoded EIP-712 payload message as input and returns a universally agreed-upon structured data format that emphasizes the potential impact on users&apos; assets. Wallets can then display this structured data in a user-friendly manner, ensuring a consistent experience for end-users when interacting with various dApps and protocols.

## Motivation

The rapid expansion of the web3.0 ecosystem has unlocked numerous opportunities and innovations. However, this growth has also heightened users&apos; vulnerability to security threats, such as phishing scams. Ensuring that users have a comprehensive understanding of the transactions they sign is crucial for mitigating these risks.

In an attempt to address this issue, we developed an in-house, open-source off-chain SDK for wallets to visualize various protocols. However, we encountered several challenges along the way:

- Scalability: Identifying and understanding all protocols that utilize EIP-712 and their respective business logic is a daunting task, particularly with limited resources. Crafting an off-chain solution for all these protocols is nearly impossible.
- Reliability: Grasping each protocol&apos;s business logic is difficult and may lead to misunderstandings of the actual implementation. This can result in inaccurate visualizations, which could be more detrimental than providing no visualization at all.
- Maintainability: Offering support for protocols with an off-chain solution is insufficient in a rapidly evolving ecosystem. Protocols frequently upgrade their implementations by extending features or fixing bugs, further complicating the maintenance process.

To overcome these challenges, we propose a standardized, on-chain solution that can accommodate the diverse and ever-changing web3.0 ecosystem. This approach would enhance scalability, reliability, and maintainability by shifting the responsibility of visualizing EIP-712 payloads from the wallets to the protocols themselves. Consequently, wallets can use a consistent and effective approach to EIP-712 message visualization.

The adoption of a universal solution will not only streamline the efforts and reduce the maintenance burden for wallet providers, but it will also allow for faster and more extensive coverage across the ecosystem. This will ultimately result in users gaining a clearer understanding of the transactions they&apos;re signing, leading to increased security and an improved overall user experience within the crypto space.

Currently, most of the wallets display something similar to image below

![](/EIPs/assets/eip-6865/current-EIP-712-signature-wallet-interface.png)

With visualization we can achieve something similar to image below where more insightful details are revealed to user thanks to the structured data returned from the EIP

![](/EIPs/assets/eip-6865/vision-EIP-712-signature-wallet-interface.png)

## Specification

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

Contracts implementing this proposal MUST include the `visualizeEIP712Message` function in the  `verifyingContract` implementation so that wallets upon receiving a request to sign an EIP-712 message(`eth_signTypedData`) MAY call the function `visualizeEIP712Message` at the smart contract and chain specified in the EIP-712 message domain separator `verifyingContract` and `chainId` fields, respectively. 

Wallets SHOULD ignore this proposal if the domain separator does not include the `verifyingContract` and `chainId` fields.

```solidity
/**
* @notice This function processes an EIP-712 payload message and returns a structured data format emphasizing the potential impact on users&apos; assets.
* @dev The function returns assetsOut (assets the user is offering), assetsIn (assets the user would receive), and liveness (validity duration of the EIP-712 message).
* @param encodedMessage The ABI-encoded EIP-712 message (abi.encode(types, params)).
* @param domainHash The hash of the EIP-712 domain separator as defined in the EIP-712 proposal; see https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator.
* @return Result struct containing the user&apos;s assets impact and message liveness.
*/
function visualizeEIP712Message(
    bytes memory encodedMessage,
    bytes32 domainHash
) external view returns (Result memory);
```

### Params

`encodedMessage` is bytes that represents the encoded EIP-712  message with `abi.encode` and it can be decoded using `abi.decode`

`domainHash` is the bytes32 hash of the EIP-712 domain separator as defined in the EIP-712 proposal

### Outputs

The function MUST return `Result`, a struct that contains information&apos;s about user’s assets impact and the liveness of such a message if it gets signed.

```solidity
struct Liveness {
  uint256 from;
  uint256 to;
}

struct UserAssetMovement {
  address assetTokenAddress;
  uint256 id;
  uint256[] amounts;
}

struct Result {
  UserAssetMovement[] assetsIn;
  UserAssetMovement[] assetsOut;
  Liveness liveness;
}
```

#### `Liveness`

`Liveness` is a struct that defines the timestamps which the message is valid where:

- `from` is the starting timestamp.
- `to` is the expiry timestamp
- `from` MUST be less than `to`

#### `UserAssetMovement`

`UserAssetMovement` defines the user’s asset where:

- `assetTokenAddress` is the token ([ERC-20](/EIPs/EIPS/eip-20), [ERC-721](/EIPs/EIPS/eip-721), [ERC-1155](/EIPs/EIPS/eip-1155)) smart contract address where the zero address MUST represents the Native coin (Native ETH in the case of Ethereum network).
- `id` is the NFT ID, this item MUST ignored if the asset is not an NFT
    - if token with `id` doesn’t exist in an NFT collection, this SHOULD be considered as any token within that collection
- `amounts` is an Array of `uint256` where items MUST define the amount per time curve, with time defined within liveness boundaries
    - the first amount in `amounts` Array (amounts[0]) MUST be the amount of the asset at `liveness.from` timestamp
    - the last amount in `amounts` Array (amounts[amounts.length-1]) MUST be the amount of the asset at `liveness.to` timestamp
    - in most of the cases, `amounts` will be an Array with a single item which is MUST be the minimum amount of the asset.

#### `assetsIn`

`assetsIn` are the minimum assets which the user MUST get if the message is signed and fulfilled

#### `assetsOut`

`assetsOut` are the maximum assets which the user MUST offer if the message is signed and fulfilled

## Rationale

### on-chain

One might argue that certain processes can be done off-chain, which is true, but our experience building an off-chain TypeScript SDK to solve this matter revealed some issues:

- Reliability: Protocols developers are the ones responsible for developing the protocol itself, thus crafting the visualization is much more accurate when done by them.
- Scalability: Keeping up with the rapidly expanding ecosystem is hard. Wallets or 3rd party entities must keep an eye on each new protocol, understand it carefully (which poses the reliability issues mentioned above), and then only come up with an off-chain implementation.
- Maintainability: Many protocols implement smart contracts in an upgradable manner. This causes the off-chain visualization to differ from the real protocol behaviors (if updated), making the solution itself unreliable and lacking the scalability to handle various protocols.

### `DomainHash`

The `domainHash` is much needed by protocols to revert against unsupported versions of its EIP-712 implementation. It identifies the needed implementation in case the protocol implements various EIP-712 implementations (`name`) or to revert if the `domainHash` belongs to a different protocol.

In the future, if there is a registry that reroutes this EIP implementation for already deployed protocols that can&apos;t upgrade the existing deployed smart contract, `domainHash` can be used to identify protocols.

### Amounts Array

We suggest using an array of amounts (uint256[]) instead of a single uint256 to cover auctions, which are common in NFT protocols.

## Backwards Compatibility

No backward compatibility issues found.

## Reference Implementation

openSea Seaport NFT marketplace implementation example is available [here](/EIPs/assets/eip-6865/contracts/SeaPortEIP712Visualizer.sol)

## Security Considerations

`visualizeEIP712Message` function should be reliable and accurately represent the potential impact of the EIP-712 message on users&apos; assets. Wallet providers and users must trust the protocol&apos;s implementation of this function to provide accurate and up-to-date information.

`visualizeEIP712Message` function results should be treated based on the reputation of its `verifyingContract`, if the `verifyingContract` is trusted it means the `visualizeEIP712Message` function results are trusted as the this proposal implementation lives at the same address of `verifyingContract`.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 10 Apr 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6865</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6865</guid>
      </item>
    
      <item>
        <title>Preimage retention</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6873-preimage-retention-in-the-fork-preceding-the-verge/15830</comments>
        
        <description>## Abstract

Enforce preimage collection by every node on the network from the fork preceding the verge, up to the fork. This is needed in case each node is responsible for their own conversion.

## Specification

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

Let `T_p` be the timestamp of the fork preceding the verge, and `T_v` the timestamp of the verge. 

 * EL clients MUST save the preimage of each address and slot hashes they produce during the execution of all blocks produced between `T_p` and `T_v`

 * EL clients MAY start storing preimages outside of this time range as well

 * Given a hash produced between `T_p` and `T_v`, EL clients SHOULD be able to show they have the preimage for that hash in their database

 * EL clients SHOULD be able to download the preimages of the address and slot hashes that were produced before `T_v` from a publicly-available datastore

## Rationale

Switching to verkle trees require a complete rehashing of all tree keys. Most execution clients store all keys hashed, without their preimages, which as the time of print take up 70GB on mainnet. In order to make these preimages available to everyone, the following course of action are available to each user:

 * Restart a full-sync with preimage retention enabled
 * Download the preimages as a file

The second option is the only acceptable option in practice, as a full-sync requires the syncing machine to be offline for several days, and therefore should not be simultaneously imposed to the entire network. A file download, however, poses a problem of data obsolescence as new preimages will immediately need to be added to the list as the chain progresses and new addresses are accessed. Updating the preimage file is not sufficient, since it takes more than a slot time to download over 70GB.

To guarantee a timely availability of all preimages around the verkle transition time, each node is therefore responsible for updating the list of preimages between the fork preceding the Verge, and the Verge itself.

## Backwards Compatibility

No backward compatibility issues found.

&lt;!--

## Test Cases

TODO

--&gt;

## Reference Implementation

All clients already implement preimage retention, at least as an option.

## Security Considerations

Needs discussion. &lt;!-- TODO --&gt;

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 14 Apr 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6873</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6873</guid>
      </item>
    
      <item>
        <title>Arithmetic verification at EVM level</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-math-checking/13846</comments>
        
        <description>## Abstract

This EIP adds arithmetics checks to EVM arithmetic and a new opcode jump conditionally if there were events. The list of check includes overflows, division by zero.

## Motivation

The importance of math checks in smart contract projects is very clear. It was an OpenZeppelin library and then incorporated in Solidity&apos;s default behavior. Bringing this to EVM level can combine both gas efficiency and safety.

## Specification

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

Starting from `BLOCK_TIMESTAMP &gt;= HARDFORK_TIMESTAMP`

### Constants

|     Constant         | Type      | Value     |
| -------------------- | --------- | --------- |
| `HARDFORK_TIMESTAMP` | `uint64`  | `TBD`     |
| `UINT_MAX`           | `uint256` | `2 ** 256 - 1` |
| `INT_MIN`            | `int256`  | `-(2**255)` |

### Flags

|     Variable        | Type      | Initial Value |
| ------------------- | --------- |:------------- |
| `carry`             | `bool`    | false         |
| `overflow`          | `bool`    | false         |

Two new flags are added to the EVM state: unsigned warning (`carry`) and signed warning (`overflow`). The scope of those flags are the same as the program counter.

### Definitions

From this point forward  `a`, `b` and `c` references the arguments in a math operation and `res` the output. `c` is only used if the operation takes 3 inputs.

The function `sign(x)` is defined in the set of `uint256 -&gt; {NEGATIVE, ZERO, POSITIVE}`

### Conditions

The `carry` flag MUST be set in the following circumstances:

 - When opcode is `ADD` (`0x01`) and `res &lt; a`
 - When opcode is `MUL` (`0x02`) and `a != 0 ∧ res / a != b`
 - When opcode is `SUB` (`0x03`) and `b &gt; a`
 - When opcode is `DIV` (`0x04`) or `MOD` (`0x06`); and `b == 0`
 - When opcode is `ADDMOD` (`0x08`) and `c == 0`
 - When opcode is `MULMOD` (`0x08`) and `c == 0`
 - When opcode is `EXP` (`0x0A`) and `a ** b &gt; UINT_MAX`
 - When opcode is `SHL` (`0x1b`) and `res &gt;&gt; a != b`

The `overflow` flag MUST be set in the following circumstances:

 - When opcode is `ADD` (`0x01`) and `a != 0 ∧ b != 0 ∧ sign(a) == sign(b) ∧ sign(a) != sign(res)`
 - When opcode is `SUB` (`0x03`) and `(a != 0 ∧ b != 0 ∧ sign(a) != sign(b) ∧ sign(a) != sign(res)) ∨ (a == 0 ^ b == INT_MIN)`
 - When opcode is `MUL` (`0x02`) and `(a == -1 ∧ b == INT_MIN) ∨ (a == INT_MIN ∧ b == -1) ∨ (a != 0 ∧ (res / a != b))` (this `/` represents `SDIV`)
 - When opcode is `SDIV` (`0x05`)  or `SMOD` (`0x06`); and `b == 0 ∨ (a == INT_MIN ∧ b == -1)`
 - When opcode is `SHL` (`0x1b`) and `res &gt;&gt; a != b` (this `&gt;&gt;` represents `SAR`)

### Opcodes

#### `JUMPC`

Consumes one argument from the stack, the possible pc dest,
Conditionally alter the program counter depending on the `carry` flag. `J_JUMPC = carry ? µ_s[0] : µ_pc + 1` 
Clears both flags. `carry = overflow = false`


#### `JUMPO`

Consumes one argument from the stack, the possible pc dest,
Conditionally alter the program counter depending on the `overflow` flag. `J_JUMPO = carry ? µ_s[0] : µ_pc + 1` 
Clears both flags. `carry = overflow = false`

### gas

The gas cost for both instructions is `G_high`, the same as `JUMPI`.

## Rationale

EVM uses two&apos;s complement for negative numbers. The opcodes listed above triggers one or two flags depending if they are used for signed and unsigned numbers.

The conditions described for each opcode is made with implementation friendliness in mind. The only exception is EXP as it is hard to give a concise test as most of the others relied on the inverse operation and there is no native `LOG`. Most `EXP` implementations will internally use `MUL` so the flag `carry` can be drawn from that instruction, not the `overflow`.

Both flags are cleaned at the same time because the instructions are expected to be used when transitioning between codes where numbers are treated as signed or unsigned.

## Backwards Compatibility

This EIP introduces a new opcode and changes int EVM behavior.

## Test Cases

TBD

## Reference Implementation

TBD

## Security Considerations

This is a new EVM behavior but each code will decide how to interact with it.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 16 Apr 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6888</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6888</guid>
      </item>
    
      <item>
        <title>Modular Smart Contract Accounts</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-modular-smart-contract-accounts-and-plugins/13885</comments>
        
        <description>## Abstract

This proposal standardizes smart contract accounts and account modules, which are smart contracts that allow for composable logic within smart contract accounts. This proposal is compliant with [ERC-4337](/EIPs/EIPS/eip-4337). This standard emphasizes secure permissioning of modules, and maximal interoperability between all spec-compliant accounts and modules.

This modular approach splits account functionality into three categories, implements them in external contracts, and defines an expected execution flow from accounts.

## Motivation

One of the goals that ERC-4337 accomplishes is abstracting the logic for execution and validation to each smart contract account.

Many new features of accounts can be built by customizing the logic that goes into the validation and execution steps. Examples of such features include session keys, subscriptions, spending limits, and role-based access control. Currently, some of these features are implemented natively by specific smart contract accounts, and others are able to be implemented by proprietary module systems like Safe modules.

However, managing multiple account implementations provides a poor user experience, fragmenting accounts across supported features and security configurations. Additionally, it requires module developers to choose which platforms to support, causing either platform lock-in or duplicated development effort.

We propose a standard that coordinates the implementation work between module developers and account developers. This standard defines a modular smart contract account capable of supporting all standard-conformant modules. This allows users to have greater portability of their data, and for module developers to not have to choose specific account implementations to support.

![diagram showing relationship between accounts and modules with modular functions](/EIPs/assets/eip-6900/MSCA_Shared_Components_Diagram.svg)

These modules can contain execution logic, validation functions, and hooks. Validation functions define the circumstances under which the smart contract account will approve actions taken on its behalf, while hooks allow for pre and post execution controls.

Accounts adopting this standard will support modular, upgradable execution and validation logic. Defining this as a standard for smart contract accounts will make modules easier to develop securely and will allow for greater interoperability.

## Specification

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

### Terms

- An **account** (or **smart contract account, SCA**) is a smart contract that can be used to send transactions and hold digital assets. It implements the `IAccount` interface from ERC-4337.
- A **modular account** (or **modular smart contract account, MSCA**) is an account that supports modular functions. There are three types of modular functions:
  - **Validation functions** validate authorization on behalf of the account.
  - **Execution functions** execute custom logic allowed by the account.
  - **Hooks** execute custom logic and checks before and/or after an execution function or validation function. There are two types of hooks:
    - **Validation hooks** run before a validation function. These can enforce permissions on actions authorized by a validation function.
    - **Execution hooks** can run before and/or after an execution function. Execution hooks can be attached either to a specific execution function or a validation function. A pre execution hook may optionally return data to be consumed by a post execution hook.
- A **native function** refers to a function implemented by the modular account, as opposed to a function added by a module.
- A **module** is a deployed smart contract that hosts any amount of the above three kinds of modular functions.
- A module&apos;s **manifest** describes the execution functions, interface IDs, and hooks that should be installed on the account.

### Overview

A modular account handles two kinds of calls: either from the `EntryPoint` through ERC-4337, or through direct calls from externally owned accounts (EOAs) and other smart contracts. This standard supports both use cases.

A call to the modular account can be broken down into the steps as shown in the diagram below. The validation steps validate if the caller is allowed to perform the call. The pre execution hook step can be used to do any pre execution checks or updates. It can also be used along with the post execution hook step to perform additional actions or verification. The execution step performs a defined task or collection of tasks.

![diagram showing call flow within a modular account](/EIPs/assets/eip-6900/Modular_Account_Call_Flow.svg)

Each step is modular, supporting different implementations, which allows for open-ended programmable accounts.

### Interfaces

Modular accounts MUST implement:

- `IAccount.sol` and `IAccountExecute.sol` from [ERC-4337](/EIPs/EIPS/eip-4337).
- `IERC6900Account.sol` to support module management and usage, and account identification.
- The function `isValidSignature` from [ERC-1271](/EIPs/EIPS/eip-1271)

Modular accounts MAY implement:

- `IERC6900AccountView.sol` to support visibility in account states on-chain.
- [ERC-165](/EIPs/EIPS/eip-165) for interfaces installed from modules.

Modules MUST implement:

- `IERC6900Module.sol` described below and implement ERC-165 for `IERC6900Module`.

Modules MAY implement any of the following module types:

- `IERC6900ValidationModule` to support validation functions for the account.
- `IERC6900ValidationHookModule` to support hooks for validation functions.
- `IERC6900ExecutionModule` to support execution functions and their installations on the account.
- `IERC6900ExecutionHookModule` to support pre &amp; post execution hooks for execution functions.

#### `IERC6900Account.sol`

Module execution and management interface. Modular accounts MUST implement this interface to support installing and uninstalling modules, and open-ended execution.

```solidity
/// @dev A packed representation of a module function.
/// Consists of the following, left-aligned:
/// Module address: 20 bytes
/// Entity ID:      4 bytes
type ModuleEntity is bytes24;

/// @dev A packed representation of a validation function and its associated flags.
/// Consists of the following, left-aligned:
/// Module address:     20 bytes
/// Entity ID:          4 bytes
/// ValidationFlags:    1 byte
type ValidationConfig is bytes25;

// ValidationFlags layout:
// 0b00000___ // unused
// 0b_____A__ // isGlobal
// 0b______B_ // isSignatureValidation
// 0b_______C // isUserOpValidation
type ValidationFlags is uint8;

/// @dev A packed representation of a hook function and its associated flags.
/// Consists of the following, left-aligned:
/// Module address: 20 bytes
/// Entity ID:      4 bytes
/// Flags:          1 byte
///
/// Hook flags layout:
/// 0b00000___ // unused
/// 0b_____A__ // hasPre (exec only)
/// 0b______B_ // hasPost (exec only)
/// 0b_______C // hook type (0 for exec, 1 for validation)
type HookConfig is bytes25;

struct Call {
    // The target address for the account to call.
    address target;
    // The value to send with the call.
    uint256 value;
    // The calldata for the call.
    bytes data;
}

interface IERC6900Account {
    event ExecutionInstalled(address indexed module, ExecutionManifest manifest);
    event ExecutionUninstalled(address indexed module, bool onUninstallSucceeded, ExecutionManifest manifest);
    event ValidationInstalled(address indexed module, uint32 indexed entityId);
    event ValidationUninstalled(address indexed module, uint32 indexed entityId, bool onUninstallSucceeded);

    /// @notice Standard execute method.
    /// @param target The target address for the account to call.
    /// @param value The value to send with the call.
    /// @param data The calldata for the call.
    /// @return The return data from the call.
    function execute(address target, uint256 value, bytes calldata data) external payable returns (bytes memory);

    /// @notice Standard executeBatch method.
    /// @dev If the target is a module, the call SHOULD revert. If any of the calls revert, the entire batch MUST
    /// revert.
    /// @param calls The array of calls.
    /// @return An array containing the return data from the calls.
    function executeBatch(Call[] calldata calls) external payable returns (bytes[] memory);

    /// @notice Execute a call using the specified runtime validation.
    /// @param data The calldata to send to the account.
    /// @param authorization The authorization data to use for the call. The first 24 bytes is a ModuleEntity which
    /// specifies which runtime validation to use, and the rest is sent as a parameter to runtime validation.
    function executeWithRuntimeValidation(bytes calldata data, bytes calldata authorization)
        external
        payable
        returns (bytes memory);

    /// @notice Install a module to the modular account.
    /// @param module The module to install.
    /// @param manifest the manifest describing functions to install.
    /// @param installData Optional data to be used by the account to handle the initial execution setup. Data encoding
    /// is implementation-specific.
    function installExecution(
        address module,
        ExecutionManifest calldata manifest,
        bytes calldata installData
    ) external;

    /// @notice Uninstall a module from the modular account.
    /// @param module The module to uninstall.
    /// @param manifest The manifest describing functions to uninstall.
    /// @param uninstallData Optional data to be used by the account to handle the execution uninstallation. Data
    /// encoding is implementation-specific.
    function uninstallExecution(
        address module,
        ExecutionManifest calldata manifest,
        bytes calldata uninstallData
    ) external;

    /// @notice Installs a validation function across a set of execution selectors, and optionally mark it as a
    /// global validation function.
    /// @param validationConfig The validation function to install, along with configuration flags.
    /// @param selectors The selectors to install the validation function for.
    /// @param installData Optional data to be used by the account to handle the initial validation setup. Data
    /// encoding is implementation-specific.
    /// @param hooks Optional hooks to install and associate with the validation function. Data encoding is
    /// implementation-specific.
    function installValidation(
        ValidationConfig validationConfig,
        bytes4[] calldata selectors,
        bytes calldata installData,
        bytes[] calldata hooks
    ) external;

    /// @notice Uninstall a validation function from a set of execution selectors.
    /// @param validationFunction The validation function to uninstall.
    /// @param uninstallData Optional data to be used by the account to handle the validation uninstallation. Data
    /// encoding is implementation-specific.
    /// @param hookUninstallData Optional data to be used by the account to handle hook uninstallation. Data encoding
    /// is implementation-specific.
    function uninstallValidation(
        ModuleEntity validationFunction,
        bytes calldata uninstallData,
        bytes[] calldata hookUninstallData
    ) external;

    /// @notice Return a unique identifier for the account implementation.
    /// @dev This function MUST return a string in the format &quot;vendor.account.semver&quot;. The vendor and account
    /// names MUST NOT contain a period character.
    /// @return The account ID.
    function accountId() external view returns (string memory);
}
```

#### `IERC6900AccountView.sol`

Module inspection interface. Modular accounts MAY implement this interface to support visibility in module configuration.

```solidity
/// @dev Represents data associated with a specific function selector.
struct ExecutionDataView {
    // The module that implements this execution function.
    // If this is a native function, the address must be the address of the account.
    address module;
    // Whether or not the function needs runtime validation, or can be called by anyone. The function can still be
    // state changing if this flag is set to true.
    // Note that even if this is set to true, user op validation will still be required, otherwise anyone could
    // drain the account of native tokens by wasting gas.
    bool skipRuntimeValidation;
    // Whether or not a global validation function may be used to validate this function.
    bool allowGlobalValidation;
    // The execution hooks for this function selector.
    HookConfig[] executionHooks;
}

struct ValidationDataView {
    // ValidationFlags layout:
    // 0b00000___ // unused
    // 0b_____A__ // isGlobal
    // 0b______B_ // isSignatureValidation
    // 0b_______C // isUserOpValidation
    ValidationFlags validationFlags;
    // The validation hooks for this validation function.
    HookConfig[] validationHooks;
    // Execution hooks to run with this validation function.
    HookConfig[] executionHooks;
    // The set of selectors that may be validated by this validation function.
    bytes4[] selectors;
}

interface IERC6900AccountView {
    /// @notice Get the execution data for a selector.
    /// @dev If the selector is a native function, the module address will be the address of the account.
    /// @param selector The selector to get the data for.
    /// @return The execution data for this selector.
    function getExecutionData(bytes4 selector) external view returns (ExecutionDataView memory);

    /// @notice Get the validation data for a validation function.
    /// @dev If the selector is a native function, the module address will be the address of the account.
    /// @param validationFunction The validation function to get the data for.
    /// @return The validation data for this validation function.
    function getValidationData(ModuleEntity validationFunction)
        external
        view
        returns (ValidationDataView memory);
}
```

#### `IERC6900Module.sol`

Module interface. Modules MUST implement this interface to support module management and interactions with [ERC-6900](/EIPs/EIPS/eip-6900) modular accounts.

```solidity
interface IERC6900Module is IERC165 {
    /// @notice Initialize module data for the modular account.
    /// @dev Called by the modular account during `installExecution`.
    /// @param data Optional bytes array to be decoded and used by the module to setup initial module data for the
    /// modular account.
    function onInstall(bytes calldata data) external;

    /// @notice Clear module data for the modular account.
    /// @dev Called by the modular account during `uninstallExecution`.
    /// @param data Optional bytes array to be decoded and used by the module to clear module data for the modular
    /// account.
    function onUninstall(bytes calldata data) external;

    /// @notice Return a unique identifier for the module.
    /// @dev This function MUST return a string in the format &quot;vendor.module.semver&quot;. The vendor and module
    /// names MUST NOT contain a period character.
    /// @return The module ID.
    function moduleId() external view returns (string memory);
}
```

#### `IERC6900ValidationModule.sol`

Validation module interface. Modules MAY implement this interface to provide validation functions for the account.

```solidity
interface IERC6900ValidationModule is IERC6900Module {
    /// @notice Run the user operation validation function specified by the `entityId`.
    /// @param entityId An identifier that routes the call to different internal implementations, should there
    /// be more than one.
    /// @param userOp The user operation.
    /// @param userOpHash The user operation hash.
    /// @return Packed validation data for validAfter (6 bytes), validUntil (6 bytes), and authorizer (20 bytes).
    function validateUserOp(uint32 entityId, PackedUserOperation calldata userOp, bytes32 userOpHash)
        external
        returns (uint256);

    /// @notice Run the runtime validation function specified by the `entityId`.
    /// @dev To indicate the entire call should revert, the function MUST revert.
    /// @param account The account to validate for.
    /// @param entityId An identifier that routes the call to different internal implementations, should there
    /// be more than one.
    /// @param sender The caller address.
    /// @param value The call value.
    /// @param data The calldata sent.
    /// @param authorization Additional data for the validation function to use.
    function validateRuntime(
        address account,
        uint32 entityId,
        address sender,
        uint256 value,
        bytes calldata data,
        bytes calldata authorization
    ) external;

    /// @notice Validates a signature using ERC-1271.
    /// @dev To indicate the entire call should revert, the function MUST revert.
    /// @param account The account to validate for.
    /// @param entityId An identifier that routes the call to different internal implementations, should there
    /// be more than one.
    /// @param sender The address that sent the ERC-1271 request to the smart account.
    /// @param hash The hash of the ERC-1271 request.
    /// @param signature The signature of the ERC-1271 request.
    /// @return The ERC-1271 `MAGIC_VALUE` if the signature is valid, or 0xFFFFFFFF if invalid.
    function validateSignature(
        address account,
        uint32 entityId,
        address sender,
        bytes32 hash,
        bytes calldata signature
    ) external view returns (bytes4);
}
```

#### `IERC6900ValidationHookModule.sol`

Validation hook module interface. Modules MAY implement this interface to provide hooks for validation functions for the account.

```solidity
interface IERC6900ValidationHookModule is IERC6900Module {
    /// @notice Run the pre user operation validation hook specified by the `entityId`.
    /// @dev Pre user operation validation hooks MUST NOT return an authorizer value other than 0 or 1.
    /// @param entityId An identifier that routes the call to different internal implementations, should there
    /// be more than one.
    /// @param userOp The user operation.
    /// @param userOpHash The user operation hash.
    /// @return Packed validation data for validAfter (6 bytes), validUntil (6 bytes), and authorizer (20 bytes).
    function preUserOpValidationHook(uint32 entityId, PackedUserOperation calldata userOp, bytes32 userOpHash)
        external
        returns (uint256);

    /// @notice Run the pre runtime validation hook specified by the `entityId`.
    /// @dev To indicate the entire call should revert, the function MUST revert.
    /// @param entityId An identifier that routes the call to different internal implementations, should there
    /// be more than one.
    /// @param sender The caller address.
    /// @param value The call value.
    /// @param data The calldata sent.
    /// @param authorization Additional data for the hook to use.
    function preRuntimeValidationHook(
        uint32 entityId,
        address sender,
        uint256 value,
        bytes calldata data,
        bytes calldata authorization
    ) external;

    /// @notice Run the pre signature validation hook specified by the `entityId`.
    /// @dev To indicate the call should revert, the function MUST revert.
    /// @param entityId An identifier that routes the call to different internal implementations, should there
    /// be more than one.
    /// @param sender The caller address.
    /// @param hash The hash of the message being signed.
    /// @param signature The signature of the message.
    function preSignatureValidationHook(uint32 entityId, address sender, bytes32 hash, bytes calldata signature)
        external
        view;
}
```

#### `IERC6900ExecutionModule.sol`

Execution module interface. Modules MAY implement this interface to provide execution functions for the account.

```solidity
struct ManifestExecutionFunction {
    // The selector to install.
    bytes4 executionSelector;
    // If true, the function won&apos;t need runtime validation, and can be called by anyone.
    bool skipRuntimeValidation;
    // If true, the function can be validated by a global validation function.
    bool allowGlobalValidation;
}

struct ManifestExecutionHook {
    bytes4 executionSelector;
    uint32 entityId;
    bool isPreHook;
    bool isPostHook;
}

/// @dev A struct describing how the module should be installed on a modular account.
struct ExecutionManifest {
    // Execution functions defined in this module to be installed on the MSCA.
    ManifestExecutionFunction[] executionFunctions;
    ManifestExecutionHook[] executionHooks;
    // List of ERC-165 interface IDs to add to account to support introspection checks. This MUST NOT include
    // IERC6900Module&apos;s interface ID.
    bytes4[] interfaceIds;
}

interface IERC6900ExecutionModule is IERC6900Module {
    /// @notice Describe the contents and intended configuration of the module.
    /// @dev This manifest MUST stay constant over time.
    /// @return A manifest describing the contents and intended configuration of the module.
    function executionManifest() external pure returns (ExecutionManifest memory);
}
```

#### `IERC6900ExecutionHookModule.sol`

Execution hook module interface. Modules MAY implement this interface to provide hooks for execution functions for the account.

```solidity
interface IERC6900ExecutionHookModule is IERC6900Module {
    /// @notice Run the pre execution hook specified by the `entityId`.
    /// @dev To indicate the entire call should revert, the function MUST revert.
    /// @param entityId An identifier that routes the call to different internal implementations, should there
    /// be more than one.
    /// @param sender The caller address.
    /// @param value The call value.
    /// @param data The calldata sent. For `executeUserOp` calls of validation-associated hooks, hook modules
    /// should receive the full calldata.
    /// @return Context to pass to a post execution hook, if present. An empty bytes array MAY be returned.
    function preExecutionHook(uint32 entityId, address sender, uint256 value, bytes calldata data)
        external
        returns (bytes memory);

    /// @notice Run the post execution hook specified by the `entityId`.
    /// @dev To indicate the entire call should revert, the function MUST revert.
    /// @param entityId An identifier that routes the call to different internal implementations, should there
    /// be more than one.
    /// @param preExecHookData The context returned by its associated pre execution hook.
    function postExecutionHook(uint32 entityId, bytes calldata preExecHookData) external;
}
```

### Validation Functions

#### Installation

- The account MUST install all validation hooks specified by the user and SHOULD call `onInstall` with the user-provided data on the hook module to initialize state if specified by the user.
- The account MUST install all execution hooks specified by the user and SHOULD call `onInstall` with the user-provided data on the hook module to initialize state if specified by the user.
- The account MUST configure the validation function to validate all of the selectors specified by the user.
- The account MUST set all flags as specified, like `isGlobal`, `isSignatureValidation`, and `isUserOpValidation`.
- The account SHOULD call `onInstall` on the validation module to initialize state if specified by the user.
- The account MUST emit `ValidationInstalled` as defined in the interface for all installed validation functions.

#### Uninstallation

During validation uninstallation, the account MUST correctly clear flags and other fields based on the incoming data provided by the user.

- The account MUST clear all flags for the validation function, like `isGlobal`, `isSignatureValidation`, and `isUserOpValidation`.
- The account MUST remove all hooks and SHOULD clear hook module states by calling `onUninstall` with the user-provided data for each hook, including both validation hooks and execution hooks, if specified by the user.
  - The account MAY ignore the revert from `onUninstall` with try/catch depending on the design principle of the account.
- The account MUST clear the configuration for the selectors that the validation function can validate.
- The account SHOULD call `onUninstall` on the validation module to clean up state if specified by the user.
- The account MUST emit `ValidationUninstalled` as defined in the interface for all uninstalled validation functions.

### Execution Functions

#### Installation

- The account MUST install all execution functions and set flags and fields as specified in the manifest.
    - An execution function selector MUST be unique in the account.
    - An execution function selector MUST not conflict with native ERC-4337 and ERC-6900 functions.
- The account MUST add all execution hooks as specified in the manifest.
- The account SHOULD add all supported interfaces as specified in the manifest.
- The account SHOULD call `onInstall` on the execution module to initialize state if specified by the user.
- The account MUST emit `ExecutionInstalled` as defined in the interface for all installed executions.

#### Uninstallation

During execution uninstallation, the account MUST correctly clear flags and other fields based on the incoming data and module manifest provided by the user.

- The account MUST remove all execution functions and clear flags and fields as specified in the manifest.
- The account MUST remove all execution hooks as specified in the manifest.
- The account SHOULD remove all supported interfaces as specified in the manifest.
- The account SHOULD call `onUninstall` on the execution module to clean up state and track call success if specified by the user.
- The account MUST emit `ExecutionUninstalled` as defined in the interface for all uninstalled executions.

### Hooks

#### Execution Hooks Data Format

For accounts that implement execution hooks, accounts MUST conform to these execution hook formats:

1. For `executeUserOp` calls, for execution hooks associated with a validation function, accounts MUST send the full calldata (`msg.data` in solidity), including the `executeUserOp` selector.
2. For `executeUserOp` calls, for execution hooks associated with a selector, accounts MUST send `PackedUserOperation.callData` for `executeUserOp` calls, excluding `executeUserOp.selector` and the rest of the `PackedUserOperation`.
3. For `executeWithRuntimeValidation` calls, for all execution hooks, accounts MUST send the inner `data` field.
4. For all other calls, for execution hooks associated with a selector, accounts MUST send over the full calldata (`msg.data` in solidity).

#### Hook Execution Order

It is RECOMMENDED that an account implementer runs hooks in first installed first executed order. However, an account MAY implement a different execution order.

### Validation Call Flow

Modular accounts support three different calls flows for validation: user op validation, runtime validation, and signature validation. User op validation happens within the account&apos;s implementation of the function `validateUserOp`, defined in the ERC-4337 interface `IAccount`. Runtime validation happens through the dispatcher function `executeWithRuntimeValidation`, or when using [direct call validation](#direct-call-validation). Signature validation happens within the account&apos;s implementation of the function `isValidSignature`, defined in ERC-1271.

For each of these validation types, an account implementation MAY specify its own format for selecting which validation function to use, as well as any per-hook data for validation hooks.

Within the implementation of each type of validation function, the modular account MUST check that the provided validation function applies to the given function selector intended to be run (See [Checking Validation Applicability](#checking-validation-applicability)). Then, the account MUST execute all validation hooks of the corresponding type associated with the validation function in use. After the execution of validation hooks, the account MUST invoke the validation function of the corresponding type. If any of the validation hooks or the validation function reverts, the account MUST revert. It SHOULD include the module&apos;s revert data within its revert data.

The account MUST define a way to pass data separately for each validation hook and the validation function itself. This data SHOULD be sent as the `userOp.signature` field for user op validation, the `authorization` field for runtime validation, and the `signature` field for signature validation.

The result of user op validation MUST be the intersection of time bounds returned by the validation hooks and the validation function. If any validation hooks or the validation functions returns a value of `1` for the authorizer field, indicating a signature verification failure by the ERC-4337 standard, the account MUST return a value of `1` for the authorizer portion of the validation data.

The set of validation hooks run MUST be the hooks specified by account state at the start of validation. In other words, if the set of applicable hooks changes during validation, the original set of hooks MUST still run, and only future invocations of the same validation should reflect the changed set of hooks.

#### Checking Validation Applicability

To enforce module permission isolation, the modular account MUST check validation function applicability as part of each validation function implementation.

User op validation and runtime validation functions have a configurable range of applicability to functions on the account. This can be configured with selectors installed to a validation. Alternatively, a validation installation MAY specify the `isGlobal` flag as true, which means the account MUST consider it applicable to any module execution function with the `allowGlobalValidation` flag set to true, or for any account native function that the account MAY allow for global validation.

If the selector being checked is `execute` or `executeBatch`, the modular account MUST perform additional checking. If the target of `execute` is the modular account&apos;s own address, or if the target of any `Call` within `executeBatch` is the account, validation MUST either revert or check that validation applies to the selector(s) being called.

Installed validation functions have two additional flag variables indicating what they may be used for. If a validation function is attempted to be used for user op validation and the flag `isUserOpValidation` is set to false, validation MUST revert. If the validation function is attempted to be used for signature validation and the flag `isSignatureValidation` is set to false, validation MUST revert.

#### Direct Call Validation

If a validation function is installed with the entity ID of `0xffffffff`, it may be used as direct call validation. This occurs when a module or other address calls a function on the modular account, without wrapping its call in the dispatcher function `executeWithRuntimeValidation` to use as a selection mechanism for a runtime validation function.

To implement direct call validation, the modular account MUST treat direct function calls that are not from the modular account itself or the `EntryPoint` as an attempt to validate using the caller&apos;s address and the entity ID of `0xffffffff`. If such a validation function is installed, and applies to the function intended to be called, the modular account MUST allow it to continue, without performing runtime validation. Any validation hooks and execution hooks installed to this validation function MUST still run.

### Execution Call Flow

For all non-view functions within `IERC6900Account` except `executeWithRuntimeValidation`, all module-defined execution functions, and any additional native functions that the modular account MAY wish to include, the modular account MUST adhere to these steps during execution:

If the caller is not the `EntryPoint` or the account, the account MUST check access control for direct call validation.

Prior to running the target function, the modular account MUST run all pre execution hooks that apply for the current function call. Pre execution hooks apply if they have been installed to the currently running function selector, or if they are installed as an execution hook to the validation function that was used for the current execution. Pre execution hooks MUST run validation-associated hooks first, then selector-associated hooks second.

Next, the modular account MUST run the target function, either an account native function or a module-defined execution function.

After the execution of the target function, the modular account MUST run any post execution hooks. These MUST be run in the reverse order of the pre execution hooks. If a hook is defined to be both a pre and a post execution hook, and the pre execution hook returned a non-empty `bytes` value to the account, the account MUST pass that data to the post execution hook.

The set of hooks run for a given target function MUST be the hooks specified by account state at the start of the execution phase. In other words, if the set of applicable hooks changes during execution, the original set of hooks MUST still run, and only future invocations of the same target function should reflect the changed set of hooks.

Module execution functions where the field `skipRuntimeValidation` is set to true, as well as native functions without access control, SHOULD omit the runtime validation step, including any runtime validation hooks. Native functions without access control MAY also omit running execution hooks.

### Extension

#### Semi-Modular Account

Account implementers MAY choose to design a semi-modular account, where certain features, such as default validation, are integrated into the core account. This approach SHOULD ensure compatibility with fully modular accounts, as defined in this proposal, to maintain interoperability across different implementations.

## Rationale

ERC-4337 compatible accounts must implement the `IAccount` interface, which consists of only one method that bundles validation with execution: `validateUserOp`. A primary design rationale for this proposal is to extend the possible functions for a smart contract account beyond this single method by unbundling these and other functions, while retaining the benefits of account abstraction.

This proposal includes several interfaces that build on ERC-4337. First, we standardize a set of modular functions that allow smart contract developers greater flexibility in bundling validation, execution, and hook logic. We also propose interfaces that provide methods for querying execution functions, validation functions, and hooks on a modular account. The rest of the interfaces describe a module&apos;s methods for exposing its modular functions and desired configuration, and the modular account&apos;s methods for installing and removing modules and allowing execution across modules and external addresses.

### ERC-4337 Dependency

ERC-6900&apos;s main objective is to create a secure and interoperable foundation through modular accounts and modules to increase the velocity and security of the smart account ecosystem, and ultimately the wallet ecosystem. Currently, the standard prescribes ERC-4337 for one of its [modular account call flows](#overview). However, this does not dictate that ERC-6900 will continue to be tied to ERC-4337.
It is likely that smart account builders will want to develop modular accounts that do not use ERC-4337 in the future (e.g., native account abstraction on rollups). Moreover, it is expected that ERC-4337 and its interfaces and contracts will continue to evolve until there is a protocol-level account abstraction.

In the current state of the AA ecosystem, it is tough to predict the direction the builders and industry will take, so ERC-6900 will evolve together with the space&apos;s research, development, and adoption. The standard will do its best to address the objectives and create a secure foundation for modular accounts that may eventually be abstracted away from the infrastructure mechanism used.

### Community Consensus

While this standard has largely been the result of collaboration among the coauthors, there have been noteworthy contributions from others in the community with respect to improvements, education, and experimentation. Thank you to the contributors:

- Gerard Persoon (@gpersoon)
- Harry Jeon (@sm-stack)
- Zhiyu Zhang (@ZhiyuCircle)
- Danilo Neves Cruz (@cruzdanilo)
- Iván Alberquilla (@ialberquilla)

We host community calls and working groups to discuss standard improvements and invite anyone with questions or contributions into our discussion.

## Backwards Compatibility

Existing accounts that are deployed as proxies may have the ability to upgrade account implementations to one that supports this standard for modularity. Depending on implementation logic, existing modules may be wrapped in an adapter contract to adhere to the standard.

The standard also allows for flexibility in account implementations, including accounts that have certain features implemented without modules, so usage of modules may be gradually introduced.

## Reference Implementation

See `https://github.com/erc6900/reference-implementation`

## Security Considerations

### Wallet/SDK Developers

From the wallet side, there are certain checks that the wallet/SDK should perform on the UI/UX side.

The standard introduces a concept of the execution manifest, which describes the execution functions, interface IDs, and hooks that should be installed on the account from an execution manifest. As part of constructing parameters to `installExecution()`, the SDK creates an `executionManifest` parameter that will specify the actions of the execution module being installed. SDKs will process the provided `executionManifest()` function of the underlying module, but the finished parameter will not necessarily be identical to the module’s return value of `executionManifest()`. Furthermore, this parameter is only going through very limited checks on-chain as part of the installation process. Therefore, the `executionManifest` parameter needs to be carefully constructed and verified before being used for installations. Furthermore, the `executionManifest` parameter of uninstallation should ideally be the same used in installation to not leave residual data.

The standard supports a `isGlobalValidation` flag for validation functions, which means that this function is added to a global validation pool and can validate any of the execution functions that expose themselves to global validation via `allowGlobalValidation` flag. Depending on the implementation, some, all or none of the native execution functions could be globally validated. Therefore, the wallets should be careful about what validation functions they allow to be installed with global validation enabled, as that would allow these functions to validate the exposed native functions and hence bypass any restrictions that may have been added to protect these native/execution functions. In a sense, these global validation functions could gain root access to the exposed native execution functions and potentially the whole account.

### Module Developers

The standard does not enforce any rules surrounding what data needs to be installed or uninstalled when a module is added/deleted from the account. Hence the `onUninstall()` function in various modules may leave behind residual state data, especially since the external call may not be performed all. Furthermore, execution hooks linked to an uninstalled function may remain configured. This could pose security risks or lead to unexpected behavior in the case where the module is reinstalled with the same `entityId`. The danger is that previously set permissions or data may be unintentionally reused. Hence it is a good idea to fully uninstall all data linked to the smart module account including execution hooks.

### Users

The modular smart contract accounts themselves are trusted components. Installed modules are trusted to varying degrees, as modules can interact with an arbitrarily large or small set of resources on an account. For example, a wide-reaching malicious module could add reverting hooks to native function selectors, bricking the account, or add execution functions that may drain the funds of the account. However, it is also possible to install a module with a very narrow domain, and depend on the correctness of the account behavior to enforce its limited access. Users should, therefore be careful in what modules to add to their account.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 18 Apr 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6900</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6900</guid>
      </item>
    
      <item>
        <title>Minimal Multi-Token Interface</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-6909-multi-token-standard/13891</comments>
        
        <description>## Abstract

The following specifies a multi-token contract as a simplified alternative to the [ERC-1155](/EIPs/EIPS/eip-1155) Multi-Token Standard. In contrast to ERC-1155, callbacks and batching have been removed from the interface and the permission system is a hybrid operator-approval scheme for granular and scalable permissions. Functionally, the interface has been reduced to the bare minimum required to manage multiple tokens under the same contract.

## Motivation

The ERC-1155 standard includes unnecessary features such as requiring recipient accounts with code to implement callbacks returning specific values and batch-calls in the specification. In addition, the single operator permission scheme grants unlimited allowance on every token ID in the contract. Backwards compatibility is deliberately removed only where necessary. Additional features such as batch calls, increase and decrease allowance methods, and other user experience improvements are deliberately omitted in the specification to minimize the required external interface.

According to ERC-1155, callbacks are required for each transfer and batch transfer to contract accounts. This requires potentially unnecessary external calls to the recipient when the recipient account is a contract account. While this behavior may be desirable in some cases, there is no option to opt-out of this behavior, as is the case for [ERC-721](/EIPs/EIPS/eip-721) having both `transferFrom` and `safeTransferFrom`. In addition to runtime performance of the token contract itself, it also impacts the runtime performance and codesize of recipient contract accounts, requiring multiple callback functions and return values to receive the tokens.

Batching transfers, while useful, are excluded from this standard to allow for opinionated batch transfer operations on different implementations. For example, a different ABI encoding may provide different benefits in different environments such as calldata size optimization for rollups with calldata storage commitments or runtime performance for environments with expensive gas fees.

A hybrid allowance-operator permission scheme enables granular yet scalable controls on token approvals. Allowances enable an external account to transfer tokens of a single token ID on a user&apos;s behalf w by their ID while operators are granted full transfer permission for all token IDs for the user.

## Specification

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

Every [ERC-6909](/EIPs/EIPS/eip-6909) compliant contract must implement the [ERC-165](/EIPs/EIPS/eip-165) interface in addition to the following interface.

### Definitions

- infinite: The maximum value for a uint256 (`2 ** 256 - 1`).
- caller: The caller of the current context (`msg.sender`).
- spender: An account that transfers tokens on behalf of another account.
- operator: An account that has unlimited transfer permissions on all token ids for another account.
- mint: The creation of an amount of tokens. This MAY happen in a mint method or as a transfer from the zero address.
- burn: The removal an amount of tokens. This MAY happen in a burn method or as a transfer to the zero address.

### Methods

#### `balanceOf`

The total `amount` of a token `id` that an `owner` owns.

```yaml
- name: balanceOf
  type: function
  stateMutability: view

  inputs:
    - name: owner
      type: address
    - name: id
      type: uint256

  outputs:
    - name: amount
      type: uint256
```

#### `allowance`

The total `amount` of a token `id` that a `spender` is permitted to transfer on behalf of an `owner`.

```yaml
- name: allowance
  type: function
  stateMutability: view

  inputs:
    - name: owner
      type: address
    - name: spender
      type: address
    - name: id
      type: uint256

  outputs:
    - name: amount
      type: uint256
```

#### `isOperator`

Returns `true` if the `spender` is approved as an operator for an `owner`.

```yaml
- name: isOperator
  type: function
  stateMutability: view

  inputs:
    - name: owner
      type: address
    - name: spender
      type: address

  outputs:
    - name: status
      type: bool
```

#### `transfer`

Transfers an `amount` of a token `id` from the caller to the `receiver`.

MUST revert when the caller&apos;s balance for the token `id` is insufficient.

MUST log the `Transfer` event.

MUST return True.

```yaml
- name: transfer
  type: function
  stateMutability: nonpayable

  inputs:
    - name: receiver
      type: address
    - name: id
      type: uint256
    - name: amount
      type: uint256

  outputs:
    - name: success
      type: bool
```

#### `transferFrom`

Transfers an `amount` of a token `id` from a `sender` to a `receiver` by the caller.

MUST revert when the caller is neither the `sender` nor an operator for the `sender` and the caller&apos;s allowance for the token `id` for the `sender` is insufficient.

MUST revert when the `sender`&apos;s balance for the token id is insufficient.

MUST log the `Transfer` event.

MUST decrease the caller&apos;s `allowance` by the same `amount` of the `sender`&apos;s balance decrease if the caller is not an operator for the `sender` and the caller&apos;s `allowance` is not infinite.

SHOULD NOT decrease the caller&apos;s `allowance` for the token `id` for the `sender` if the `allowance` is infinite.

SHOULD NOT decrease the caller&apos;s `allowance` for the token `id` for the `sender` if the caller is an operator or the `sender`.

MUST return True.

```yaml
- name: transferFrom
  type: function
  stateMutability: nonpayable

  inputs:
    - name: sender
      type: address
    - name: receiver
      type: address
    - name: id
      type: uint256
    - name: amount
      type: uint256

  outputs:
    - name: success
      type: bool
```

#### `approve`

Approves an `amount` of a token `id` that a `spender` is permitted to transfer on behalf of the caller.

MUST set the `allowance` of the `spender` of the token `id` for the caller to the `amount`.

MUST log the `Approval` event.

MUST return True.

```yaml
- name: approve
  type: function
  stateMutability: nonpayable

  inputs:
    - name: spender
      type: address
    - name: id
      type: uint256
    - name: amount
      type: uint256

  outputs:
    - name: success
      type: bool
```

#### `setOperator`

Grants or revokes unlimited transfer permissions for a `spender` for any token `id` on behalf of the caller.

MUST set the operator status to the `approved` value.

MUST log the `OperatorSet` event.

MUST return True.

```yaml
- name: setOperator
  type: function
  stateMutability: nonpayable

  inputs:
    - name: spender
      type: address
    - name: approved
      type: bool

  outputs:
    - name: success
      type: bool
```

### Events

#### `Transfer`

The `caller` initiates a transfer of an `amount` of a token `id` from a `sender` to a `receiver`.

MUST be logged when an `amount` of a token `id` is transferred from one account to another.

MUST be logged with the `sender` address as the zero address when an `amount` of a token `id` is minted.

MUST be logged with the `receiver` address as the zero address when an `amount` of a token `id` is burned.

```yaml
- name: Transfer
  type: event

  inputs:
    - name: caller
      indexed: false
      type: address
    - name: sender
      indexed: true
      type: address
    - name: receiver
      indexed: true
      type: address
    - name: id
      indexed: true
      type: uint256
    - name: amount
      indexed: false
      type: uint256
```

#### `OperatorSet`

The `owner` has set the `approved` status to a `spender`.

MUST be logged when the operator status is set.

MAY be logged when the operator status is set to the same status it was before the current call.

```yaml
- name: OperatorSet
  type: event

  inputs:
    - name: owner
      indexed: true
      type: address
    - name: spender
      indexed: true
      type: address
    - name: approved
      indexed: false
      type: bool
```

#### `Approval`

The `owner` has approved a `spender` to transfer an `amount` of a token `id` to be transferred on the owner&apos;s behalf.

MUST be logged when the `allowance` is set by an `owner`.

```yaml
- name: Approval
  type: event

  inputs:
    - name: owner
      indexed: true
      type: address
    - name: spender
      indexed: true
      type: address
    - name: id
      indexed: true
      type: uint256
    - name: amount
      indexed: false
      type: uint256
```

### Interface ID

The interface ID is `0x0f632fb3`.

### Metadata Extension

#### Methods

##### name

The `name` for a token `id`.

```yaml
- name: name
  type: function
  stateMutability: view

  inputs:
    - name: id
      type: uint256

  outputs:
    - name: name
      type: string
```

##### symbol

The ticker `symbol` for a token `id`.

```yaml
- name: symbol
  type: function
  stateMutability: view

  inputs:
    - name: id
      type: uint256

  outputs:
    - name: symbol
      type: string
```

##### decimals

The `amount` of decimals for a token `id`.

```yaml
- name: decimals
  type: function
  stateMutability: view

  inputs:
    - name: id
      type: uint256

  outputs:
  - name: amount
    type: uint8
```

### Content URI Extension

#### Methods

##### contractURI

The `URI` for the contract.

```yaml
- name: contractURI
  type: function
  stateMutability: view

  inputs: []

  outputs:
    - name: uri
      type: string
```

##### tokenURI

The `URI` for a token `id`.

MAY revert if the token `id` does not exist.

MUST replace occurrences of `{id}` in the returned URI string by the client.

```yaml
- name: tokenURI
  type: function
  stateMutability: view

  inputs:
    - name: id
      type: uint256

  outputs:
    - name: uri
      type: string
```

#### Metadata Structure

##### Contract URI

JSON Schema:

```json
{
  &quot;title&quot;: &quot;Contract Metadata&quot;,
  &quot;type&quot;: &quot;object&quot;,
  &quot;properties&quot;: {
    &quot;name&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;The name of the contract.&quot;
    },
    &quot;description&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;The description of the contract.&quot;
    },
    &quot;image_url&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;format&quot;: &quot;uri&quot;,
      &quot;description&quot;: &quot;The URL of the image representing the contract.&quot;
    },
    &quot;banner_image_url&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;format&quot;: &quot;uri&quot;,
      &quot;description&quot;: &quot;The URL of the banner image of the contract.&quot;
    },
    &quot;external_link&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;format&quot;: &quot;uri&quot;,
      &quot;description&quot;: &quot;The external link of the contract.&quot;
    },
    &quot;editors&quot;: {
      &quot;type&quot;: &quot;array&quot;,
      &quot;items&quot;: {
        &quot;type&quot;: &quot;string&quot;,
        &quot;description&quot;: &quot;An Ethereum address representing an authorized editor of the contract.&quot;
      },
      &quot;description&quot;: &quot;An array of Ethereum addresses representing editors (authorized editors) of the contract.&quot;
    },
    &quot;animation_url&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;An animation URL for the contract.&quot;
    }
  },
  &quot;required&quot;: [&quot;name&quot;]
}
```

JSON Example (Minimal):

```json
{
  &quot;name&quot;: &quot;Example Contract Name&quot;,
}
```

##### Token URI

MUST replace occurrences of `{id}` in the returned URI string by the client.

JSON Schema:

```json
{
  &quot;title&quot;: &quot;Asset Metadata&quot;,
  &quot;type&quot;: &quot;object&quot;,
  &quot;properties&quot;: {
    &quot;name&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Identifies the token&quot;
    },
    &quot;description&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Describes the token&quot;
    },
    &quot;image&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;A URI pointing to an image resource.&quot;
    },
    &quot;animation_url&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;An animation URL for the token.&quot;
    }
  },
  &quot;required&quot;: [&quot;name&quot;, &quot;description&quot;, &quot;image&quot;]
}
```

JSON Example (Minimal):

```json
{
  &quot;name&quot;: &quot;Example Token Name&quot;,
  &quot;description&quot;: &quot;Example Token Description&quot;,
  &quot;image&quot;: &quot;exampleurl/{id}&quot;
}
```

### Token Supply Extension

#### Methods

##### totalSupply

The `totalSupply` for a token `id`.

```yaml
- name: totalSupply
  type: function
  stateMutability: view

  inputs:
    - name: id
      type: uint256

  outputs:
    - name: supply
      type: uint256
```

## Rationale

### Granular Approvals

While the &quot;operator model&quot; from the ERC-1155 standard allows an account to set another account as an operator, giving full permissions to transfer any amount of any token id on behalf of the owner, this may not always be the desired permission scheme. The &quot;allowance model&quot; from [ERC-20](/EIPs/EIPS/eip-20) allows an account to set an explicit amount of the token that another account can spend on the owner&apos;s behalf. This standard requires both be implemented, with the only modification being to the &quot;allowance model&quot; where the token id must be specified as well. This allows an account to grant specific approvals to specific token ids, infinite approvals to specific token ids, or infinite approvals to all token ids.

### Removal of Batching

While batching operations is useful, its place should not be in the standard itself, but rather on a case-by-case basis. This allows for different tradeoffs to be made in terms of calldata layout, which may be especially useful for specific applications such as roll-ups that commit calldata to global storage.

### Removal of Required Callbacks

Requiring callbacks unnecessarily encumbers implementors that either have no particular use case for callbacks or prefer a bespoke callback mechanism. Minimization of such requirements saves contract size, gas efficiency and complexity.

### Removal of &quot;Safe&quot; Naming

The `safeTransfer` and `safeTransferFrom` naming conventions are misleading, especially in the context of the ERC-1155 and ERC-721 standards, as they require external calls to receiver accounts with code, passing the execution flow to an arbitrary contract, provided the receiver contract returns a specific value. The combination of removing mandatory callbacks and removing the word &quot;safe&quot; from all method names improves the safety of the control flow by default.

## Backwards Compatibility

This is not backwards compatible with ERC-1155 as some methods are removed. However, wrappers can be implemented for the ERC-20, ERC-721, and ERC-1155 standards.

## Reference Implementation

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity 0.8.19;

/// @title ERC6909 Multi-Token Reference Implementation
/// @author jtriley.eth
contract ERC6909 {
    /// @dev Thrown when owner balance for id is insufficient.
    /// @param owner The address of the owner.
    /// @param id The id of the token.
    error InsufficientBalance(address owner, uint256 id);

    /// @dev Thrown when spender allowance for id is insufficient.
    /// @param spender The address of the spender.
    /// @param id The id of the token.
    error InsufficientPermission(address spender, uint256 id);

    /// @notice The event emitted when a transfer occurs.
    /// @param sender The address of the sender.
    /// @param receiver The address of the receiver.
    /// @param id The id of the token.
    /// @param amount The amount of the token.
    event Transfer(address caller, address indexed sender, address indexed receiver, uint256 indexed id, uint256 amount);

    /// @notice The event emitted when an operator is set.
    /// @param owner The address of the owner.
    /// @param spender The address of the spender.
    /// @param approved The approval status.
    event OperatorSet(address indexed owner, address indexed spender, bool approved);

    /// @notice The event emitted when an approval occurs.
    /// @param owner The address of the owner.
    /// @param spender The address of the spender.
    /// @param id The id of the token.
    /// @param amount The amount of the token.
    event Approval(address indexed owner, address indexed spender, uint256 indexed id, uint256 amount);

    /// @notice Owner balance of an id.
    mapping(address owner =&gt; mapping(uint256 id =&gt; uint256 amount)) public balanceOf;

    /// @notice Spender allowance of an id.
    mapping(address owner =&gt; mapping(address spender =&gt; mapping(uint256 id =&gt; uint256 amount))) public allowance;

    /// @notice Checks if a spender is approved by an owner as an operator.
    mapping(address owner =&gt; mapping(address spender =&gt; bool)) public isOperator;

    /// @notice Transfers an amount of an id from the caller to a receiver.
    /// @param receiver The address of the receiver.
    /// @param id The id of the token.
    /// @param amount The amount of the token.
    function transfer(address receiver, uint256 id, uint256 amount) public returns (bool) {
        if (balanceOf[msg.sender][id] &lt; amount) revert InsufficientBalance(msg.sender, id);
        balanceOf[msg.sender][id] -= amount;
        balanceOf[receiver][id] += amount;
        emit Transfer(msg.sender, msg.sender, receiver, id, amount);
        return true;
    }

    /// @notice Transfers an amount of an id from a sender to a receiver.
    /// @param sender The address of the sender.
    /// @param receiver The address of the receiver.
    /// @param id The id of the token.
    /// @param amount The amount of the token.
    function transferFrom(address sender, address receiver, uint256 id, uint256 amount) public returns (bool) {
        if (sender != msg.sender &amp;&amp; !isOperator[sender][msg.sender]) {
            uint256 senderAllowance = allowance[sender][msg.sender][id];
            if (senderAllowance &lt; amount) revert InsufficientPermission(msg.sender, id);
            if (senderAllowance != type(uint256).max) {
                allowance[sender][msg.sender][id] = senderAllowance - amount;
            }
        }
        if (balanceOf[sender][id] &lt; amount) revert InsufficientBalance(sender, id);
        balanceOf[sender][id] -= amount;
        balanceOf[receiver][id] += amount;
        emit Transfer(msg.sender, sender, receiver, id, amount);
        return true;
    }

    /// @notice Approves an amount of an id to a spender.
    /// @param spender The address of the spender.
    /// @param id The id of the token.
    /// @param amount The amount of the token.
    function approve(address spender, uint256 id, uint256 amount) public returns (bool) {
        allowance[msg.sender][spender][id] = amount;
        emit Approval(msg.sender, spender, id, amount);
        return true;
    }


    /// @notice Sets or removes a spender as an operator for the caller.
    /// @param spender The address of the spender.
    /// @param approved The approval status.
    function setOperator(address spender, bool approved) public returns (bool) {
        isOperator[msg.sender][spender] = approved;
        emit OperatorSet(msg.sender, spender, approved);
        return true;
    }

    /// @notice Checks if a contract implements an interface.
    /// @param interfaceId The interface identifier, as specified in ERC-165.
    /// @return supported True if the contract implements `interfaceId`.
    function supportsInterface(bytes4 interfaceId) public pure returns (bool supported) {
        return interfaceId == 0x0f632fb3 || interfaceId == 0x01ffc9a7;
    }

    function _mint(address receiver, uint256 id, uint256 amount) internal {
      // WARNING: important safety checks should precede calls to this method.
      balanceOf[receiver][id] += amount;
      emit Transfer(msg.sender, address(0), receiver, id, amount);
    }

    function _burn(address sender, uint256 id, uint256 amount) internal {
      // WARNING: important safety checks should precede calls to this method.
      balanceOf[sender][id] -= amount;
      emit Transfer(msg.sender, sender, address(0), id, amount);
    }
}
```

## Security Considerations

### Approvals and Operators

The specification includes two token transfer permission systems, the &quot;allowance&quot; and &quot;operator&quot;
models. There are two security considerations in regards to delegating permission to transfer.

The first consideration is consistent with all delegated permission models. Any account with an allowance may transfer the full allowance for any reason at any time until the allowance is revoked. Any account with operator permissions may transfer any amount of any token id on behalf of the owner until the operator permission is revoked.

The second consideration is unique to systems with both delegated permission models. If an account has both operator permissions and an insufficient allowance for a given transfer, performing the allowance check before the operator check would result in a revert while performing the operator check before the allowance check would not. The specification intentionally leaves this unconstrained for cases where implementors may track allowances despite the operator status. Nonetheless, this is a notable consideration.

```solidity
contract ERC6909OperatorPrecedence {
  // -- snip --

  function transferFrom(address sender, address receiver, uint256 id, uint256 amount) public {
    // check if `isOperator` first
    if (msg.sender != sender &amp;&amp; !isOperator[sender][msg.sender]) {
      require(allowance[sender][msg.sender][id] &gt;= amount, &quot;insufficient allowance&quot;);
      allowance[sender][msg.sender][id] -= amount;
    }
  
    // -- snip --
  }
}

contract ERC6909AllowancePrecedence {
  // -- snip --

  function transferFrom(address sender, address receiver, uint256 id, uint256 amount) public {
    // check if allowance is sufficient first
    if (msg.sender != sender &amp;&amp; allowance[sender][msg.sender][id] &lt; amount) {
      require(isOperator[sender][msg.sender], &quot;insufficient allowance&quot;);
    }

    // ERROR: when allowance is insufficient, this panics due to arithmetic underflow, regardless of
    // whether the caller has operator permissions.
    allowance[sender][msg.sender][id] -= amount;

    // -- snip
  }
}
```

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 19 Apr 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6909</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6909</guid>
      </item>
    
      <item>
        <title>SETCODE instruction</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6913-setcode-instruction/13898</comments>
        
        <description>## Abstract

Introduce the `SETCODE` (`0xfc`) instruction, which replaces the code of the executing account from memory.

## Motivation

Many contracts are upgradeable in order to facilitate improvement or defer decisions without migrating to a new address.
Contracts presently do this in several ways:

The oldest method uses `CALL`.
The limitation of this method is that internal state must be modifiable by all future implementations.

Second, `DELEGATECALL` can proxy the implementation.
Some proxies are minimal while others branch to many separate implementation accounts.
This method can also bypass account code size limits.

A third method uses `SELFDESTRUCT` and `CREATE2` to replace code in-place.
This method improves upon the prior methods by removing the need to call into external contracts.
One limitation of this method is that any internal state is removed by `SELFDESTRUCT`.
Another limitation is that `SELFDESTRUCT` does not remove code until the end of the transaction, sacrificing availability until `CREATE2` can complete the upgrade.

Given the upcoming deprecation of `SELFDESTRUCT`, `SETCODE` introduces a better method for replacing code in-place.

## Specification

When within a read-only execution scope like the recursive kind created by `STATICCALL`, `SETCODE` causes an exceptional abort.

When the currently executing code does not equal the code of the executing account, such as can happen inside of `DELEGATECALL` or `CREATE`, `SETCODE` causes an exceptional abort.

Otherwise, `SETCODE` consumes two words from the stack: offset and length.
These specify a range of memory containing the new code.
Any validations that would be performed on the result of `CREATE` or `CREATE2` occur immediately, potentially causing failure with exceptional abort.
The operations `EXTCODESIZE` and `EXTCODECOPY` now query the updated code, and message-calls such as `DELEGATECALL`, `CALLCODE`, `CALL`, and `STATICCALL` now execute the updated code.
Any execution scopes already executing replaced code, including the one that `SETCODE`, will continue executing the prior code.
Inside such scopes, `CODESIZE` and `CODECOPY` continue to query the executing code.

Like `SSTORE`, this account modification will be reverted if the current scope or any parent scope reverts or aborts.

Unlike `SELFDESTRUCT`, `SETCODE` does not clear account balance, nonce, or storage.

### Gas

The gas cost of this operation is the sum of `Gselfdestruct` and the product of `Gcodedeposit` and the number of bytes in the new code.

## Rationale

The behavior of `CODECOPY`, `CODESIZE`, `EXTCODESIZE`, and `EXTCODECOPY` match the behavior of `DELEGATECALL` and `CREATE`, where it is also possible for executing code to differ from the code of the executing account.

The gas cost of `SETCODE` is comparable to `CREATE` but excludes `Gcreate` because no execution context is created, nor any new account.
Other account modification costs are accounted for outside of execution gas.

Unlike `SELFDESTRUCT`, execution proceeds normally after `SETCODE` in order to allow validation and return data.
Post-update validation can undo a `SETCODE` operation with `REVERT`, or with a recursive `SETCODE`, but `REVERT` uses less gas.

Preventing `SETCODE` within most `DELEGATECALL` allows static analysis to easily identify mutable code.
Account code not containing the `SETCODE` operation can be safely assumed to be immutable.
Code observed in a non-reverting context to be immutable will remain immutable, allowing on-chain static analysis for immutability.

## Backwards Compatibility

The only prior operation changing code is `SELFDESTRUCT`.
As code modification via `SELFDESTRUCT` is deferred until the end of the transaction, its interactions with `SETCODE` are well-defined.

## Test Cases

| CodeStart            | CallData         | CodeResult           | Gas  |
|----------------------|------------------|----------------------|------|
| 365f5f37365ffc00     | 365f5f37365ffc00 | 365f5f37365ffc00     | 6613 |
| 365f5f37365ffc00     | 00               | 00                   | 5213 |
| 365f5f37365ffc00     |                  |                      | 5013 |
| 365f5f37365ffc595ffd | 365f5f37365ffc00 | 365f5f37365ffc595ffd | 6617 |
| 365f5f37365ffcfe     | 365f5f37365ffc00 | 365f5f37365ffcfe     |  all |

## Security Considerations

Risks related to `SETCODE` similarly apply to other upgrade patterns.

Most contracts should never be replaced and should not be upgradeable.
Any upgrade mechanism can risk permanent failure.
The possibility of upgrade perpetuates such risk.

Access to upgrade operations should be restricted.
Upgrades should never be performed in a hurry or when tired.
Upgrades should be tested under as similar conditions to production as possible; discrepancies are sources of unexpected results.
When possible, multiple engineers should preview and independently verify pending upgrade procedures.

Block explorers, wallets, and other interfaces should flag upgradeable code.
Client software should warn against approving [ERC-20](/EIPs/EIPS/eip-20) or [ERC-721](/EIPs/EIPS/eip-721) tokens for upgradeable accounts.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 20 Apr 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6913</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6913</guid>
      </item>
    
      <item>
        <title>Reuse Withdrawn Validator Indices</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6914-reuse-withdrawn-validator-indices/15253</comments>
        
        <description>## Abstract

Reuse fully withdrawn validator indices after a sufficient safe-to-reuse period has passed to eliminate the unbounded growth of the beacon chain validator list as the validator set churns.

## Motivation

The beacon chain maintains a list of validators and a separate list of balances associated with each validator. When a new deposit for a new validator occurs, the current mechanism only appends, rather than reusing previously fully withdrawn validator indices. As validators fully withdraw and new validators enter, this means the two lists will grow unbounded.

This specification allows for the reuse of validator indices in the event that it is safe to do so, eliminating the concerns around the unbounded validator list growth.

## Specification

### Consensus Layer

The configuration values and mechanics of the specification can be found in the [Consensus Layer specs](https://github.com/ethereum/consensus-specs/blob/1a38b83e5db8638ee01c9461cccf11e7d8a3ebce/specs/_features/eip6914).

Note that validator indices are reused in the event that the validator has been fully withdrawn *and* that the validator has been withdrawable for a sufficient safe period.

### Execution Layer

This specification does not require any changes to the Execution Layer.

## Rationale

The `validators` and `balances` lists are currently appended to each time a new Deposit for a new pubkey comes into the beacon chain. Due to the natural mechanics of stakers entering and leaving consensus over long time spans, these lists, thus the state size, will grow unbounded.

Increased state size represents load and/or complexity in client implementations. This comes in the form of client memory footprint, state root calculations, validator set scans, and more. This is a relatively simple clean-up within the state transition that will prevent the unnecessary load and complexity of the otherwise unbounded lists.

## Backwards Compatibility

This is a backwards incompatible change to the Consensus Layer of Ethereum and must be scheduled with a hard fork.

There are no forwards/backwards compatibility issues with the Execution Layer

## Test Cases

Test cases are work-in-progress within the standard Consensus Layer tests.

## Security Considerations

Validator indices cannot be immediately reused but instead must wait `SAFE_EPOCHS_TO_REUSE_INDEX` epochs to ensure that attestations cannot be &quot;poisoned&quot; with withdrawn validator signatures -- thus non-slashable -- for at least the weak subjectivity period.

The attestation poisoning attack hinges upon two facts:

* The reuse of a validator index overwrites the previous validator&apos;s pubkey from the beacon state.
* `AttesterSlashing`s includes validator indices to reconstruct signature participants.

### Details of the attack

Assume a 1/3 attacker. Attacker exits N validators on the honest chain, where N is a small fraction of the validator set. These validators leave the exit queue and are withdrawable within a few days. Now, N new deposits come in and overwrite the validators and most importantly their pubkeys.

The attacker then constructs an alternative attacker chain from before any of the N voluntary exits, such that the original N validators are not exited and withdrawn. N is large enough such that at least one of the N keys is on average in every committee of the attacker chain. The attacker double-signs in an attempt to finalize the attacker chain but ensures that one of the N keys is mixed into any revealed double-signed aggregate attestation -- the individual attestations are unavailable, only aggregates. These malicious attestations are *not* includable in the honest chain because `AttesterSlashing`s rely upon mapping validator indices to particular pubkeys, thus breaking accountable safety.

### Mitigation

Not overwriting withdrawn validators for `SAFE_EPOCHS_TO_REUSE_INDEX` epochs (3x the max weak subjectivity period) ensures that attestations cannot be poisoned within the accountable safety security window.

### Alternative

Note that if `AttesterSlashing`s included a list of pubkeys instead of validator indices, then this would not be an issue. However, this would require more breaking changes and would increase the data requirement of an `AttesterSlashing`, the largest Consensus Layer data type, by a factor of 6.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Wed, 19 Apr 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6914</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6914</guid>
      </item>
    
      <item>
        <title>Automatically Reset Testnet</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/automatically-reset-testnet/15825</comments>
        
        <description>## Abstract

This EIP proposes a specification for an automatically reset testnet, a novel approach to testnets that can be implemented within Ethereum clients. It enables a single testing infrastructure consisting of ephemeral networks with deterministic parameters. Each network iteration is created by a specified function which deterministically generates genesis states.

## Motivation

A testnet which automatically resets can provide an alternative environment for short-term testing of applications, validators and also breaking changes in client implementations. It avoids issues of long running testnets which suffer from state bloat, lack of testnet funds or consensus issues. Periodically resetting the network back to genesis cleans the validator set and returns funds back to faucets while keeping the network reasonably small for easy bootstrapping.

## Specification

The testnet is set to always reset after a predefined time period. The reset means the generation of the next genesis, discarding the old one and starting a new network. This is possible by introducing functions for the genesis generation and the client reset.

### Genesis

To connect to the current instance of the network, the client must implement the genesis function. This function defines how the client stores information about the testnet and generates the current genesis. With each reset, the network starts from a new genesis which needs to be built based on given parameters and correspond in EL and CL clients.

The network always starts from a genesis which is deterministically created based on the original one - this very first genesis is hardcoded and we can call it `genesis 0`. Terminal time, the expiration of each genesis, is the addition of the start time of that genesis `MIN_GENESIS_TIME` and the testnet lifetime `period`, where `period` is a constant defining the length of time a single ephemeral network runs. Therefore, once the current slot timestamp reaches the terminal time of the ephemeral network, it has to switch to a new genesis. The main changes in each new genesis iteration are chainId, genesis time and the withdrawal credentials of the first validator.

Clients shall include a hardcoded `genesis 0` parameters, much like other networks predefined in clients. However, this genesis shall be used directly, only at the very beginning of the testnet&apos;s existence, in its first iteration where `i` equals `0`. Later on, with iteration `i` equal to `1` and above, the client does not initialize this genesis but uses it to derive the current one. When `i&gt;0`, given a known `period` and current slot timestamp, the client always calculates the number of lifecycle iterations from `genesis 0` and creates a new genesis with the latest parameters.

When the client starts with the option of an ephemeral testnet, it checks whether a genesis for the network is present. If it doesn&apos;t exist or the current slot timestamp is older than `current_genesis.genesis_time + period`, it triggers the generation of a new genesis. This new genesis, derived from `genesis 0`, will be written to the database and used to run the current network.

#### Execution client

The EL client includes the hardcoded `genesis 0` serving as a preimage for generating the current one. Iteration of variables is done as follows:

* Number of iterations:
  * `i` = `int((current_slot_timestamp` - `genesis_0.genesis_time) / period)`
* Genesis time of current genesis:
  * `current_genesis.genesis_time` = `period` * `i` + `genesis_0.genesis_time`
* Current EL ChainId:
  * `chainId` = `genesis_0.chainId` + `i`

#### Consensus client

Genesis generation in the CL client includes config with iterated values, similarly to EL, but also requires the updated genesis state. The state in SSZ format can be either generated by the client or downloaded from an external source. It includes validators with deposits ready to launch a merged network with the validator set created by trusted entities within the community.

`MIN_GENESIS_TIME` is set to the latest genesis time and defines when the current period starts. It is recommended to add a small `GENESIS_DELAY`, for example 15 minutes, to avoid issues while infrastructure is restarting with the new genesis.

To ensure a successful reset, `ForkDigest` needs to be unique for each iteration. In order to keep the `ForkVersions` of the network static for better tooling support, the withdrawal credentials of the first validator in the validator set need to be overridden by a calculated value.

* `genesis.validators[0].withdrawal_credentials` = `0x0100000000000000000000000000000000000000000000000000000000000000` + `i`
* `genesis.genesis_validators_root` =  `hash_tree_root(genesis.validators)`

The update of `genesis.validators[0]` changes the state, therefore, clients have to be able to generate or download the latest genesis state. Generating the genesis ssz is not considered a standard client feature and adding it enables to trustlessly create the latest genesis state at the price of certain complexity. An alternative solution is to obtain it from a third party, either by downloading the ssz file from a server or using the checkpoint sync feature with an endpoint serving the genesis state. This became an accepted practice with Holešky testnet and existing features of checkpoint sync can be used for obtaining genesis states for automatically reset testnets. It also allows maintainers to update the genesis validator set without requiring new client releases. The full implementation of the recommended practice for obtaining the latest CL state should behave as follows:

* When the testnet flag is provided and client supports checkpoint sync of genesis, automatically use the hardcoded checkpoint endpoint to download the latest genesis state using the checkpoint sync feature
  * If user provides a custom checkpoint sync flag, override the default option and use the endpoint provided by user
* Include a backup download option pointing to an url with the latest testnet release, a publicly distributed ssz file, and trigger this option if the checkpoint state sync fails or make it the default if client doesn&apos;t support genesis checkpoint sync
* If the client includes a feature for generating the genesis or some of its parameters, use it to verify parameters in the downloaded state and issue an error if values or checksum don&apos;t correspond

It&apos;s important to note that `genesis_validators_root` is normally predefined in the client but in this case it&apos;s not known in advance which can potentially break certain architectures. For example light clients which are relying on hardcoded `genesis_validators_root` won&apos;t work.

### Reset

The reset function defines an automatic process of throwing away the old data and starting with a new genesis. It depends on the previously defined function for genesis generation which the client must implement in order to be able to automatically follow the latest network iteration.

For the reset function, we can introduce the `terminal_timestamp` value which defines the network expiry time of an iteration. It can be the same as the genesis time of the next iteration (without the genesis delay) or can be calculated simply as `terminal_timestamp = current_genesis.genesis_time + period`.

When the network reaches a slot with a timestamp `&gt;= terminal_timestamp`:

* Client stops accepting/creating new blocks
  * Shutdown client services running the network, e.g. p2p communication, beacon service, execution environment
  * This feature should be implemented alongside Genesis even without further reset functions just to create a basic support which is always safe from forking
* Client calls a function which discards the current genesis, all chain or beacon data
  * Clients already include db tools including for purging the database which could be used here
  * It might be beneficial to include an additional flag, e.g. `--retain-ephemeral-data`, which would first export the existing data in a standard format before removing the database
* Client triggers the Genesis function (as defined above):
  * Behaves like a regular client startup when genesis is not present
  * New genesis is written into db and initialized
* Main network services are started again pointing to the updated genesis
* After the new genesis time is reached, the network starts again from the new genesis

For a full reset implementation, clients should be able to perform the above actions without requiring manual restart, operating the network fully independently and with minimal downtime.

Note that depending on the client architecture, it may not be feasible to fully implement such an internal reset mechanism, e.g. if the client doesn&apos;t support a graceful shutdown. The reset feature is considered an advanced level of support and is mainly needed by infrastructure providers and genesis validators. The assumption is that even if the client doesn&apos;t implement reset, advanced users can achieve similar behavior with external scripts handling the client by system tools.

## Rationale

Ephemeral testnets with deterministic parameters provide a sustainable alternative to traditional testnets, with the same infrastructure. At each reset, the validator set is cleared, faucets are filled again and the database is kept small.

Upon reset the whole state is purged, which, on the one hand keeps the network small and easy to bootstrap but introduces problems for testing longer term / advanced applications. However, basic contract infrastructure can be automatically deployed after each reset by any user. Generally, using the network is recommended for short term testing, deploying `Hello World` kinds of contracts that don&apos;t need to stay forever on a long term testnet. However, there can be an offchain mechanism that automatically deploys standard contract primitives after each reset so application developers can also utilize the network more.

By defining two mechanisms for Genesis and Reset, this EIP enables two levels of how a client implementation can support the testnet;

* Basic support requires the client to determine the current network specs and enables only connecting to the network.
  * This means support of the Genesis mechanism defined above
  * Enough to participate in the network for short term testing
  * To follow the latest iteration, the user has to manually shut down the client and delete the database
  * It&apos;s still recommended to add a feature for terminating the network
* Full support enables the client to follow the reset process and always sync the latest chain iteration
  * This also requires the client to implement an inherent Reset feature
  * Needed for running persistent infrastructure, genesis validators and bootnodes
  * It might be more complex to implement due to client architecture of clients

The design is also compatible with nodes managed by external tooling, i.e. even if the client doesn&apos;t implement these features, it can run on the same network as other nodes which are automatically reset by scripts. Any client supporting a custom network can be used for the testnet.

### Network parameters

Constants and variables defining testnet properties are arbitrary but need to be crafted considering certain limitations and security properties set out below.

#### Reset Period

The `period` is a constant, hardcoded in the client defining the period of time after which the network resets.

It can be defined based on users&apos; needs but for security reasons, it also depends on the number of validators in genesis. Considering the time to activate a validator, the number of trusted validators should be high enough so the network cannot be overtaken by a malicious actor.

```sh
Genesis Validators =&gt; Epochs until &lt; 66% majority
10k  =&gt; 1289 Epochs (5,7 days)
50k  =&gt; 6441 Epochs (28,6 days)
75k  =&gt; 9660 Epochs (42,9 days)
100k =&gt; 12877 Epochs (57,2 days)
150k =&gt; 19323 Epochs (85,9 days)
200k =&gt; 25764 Epochs (114,5 days)
```

#### ChainId

ChainId is a variable because it needs to keep changing with each new genesis to avoid replay attack. The function for the new ChainId value is a simple incrementation (+1). The ChainId in `genesis 0` is a hardcoded constant. This constant is used by the client with each new genesis to derive a new ChainId for that network iteration.

New ChainIds shouldn&apos;t collide with any other existing public EVM chain even after many iterations. Consequently, low ChainId values are discouraged.

## Security Considerations

The network itself is providing a secure environment thanks to regular resets. Even if some sort of vulnerability is exploited, it will be cleared on the next reset. This is also a reason to keep periods relatively short (weeks/months opposed to months/years) with a big enough genesis validator set to keep an honest majority.

Changes in clients caused by the implementation of features for resetting networks need to be reviewed together with standard security procedures. Especially the mechanism for triggering reset which must be separated from other networks that are not configured as ephemeral.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 10 Apr 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6916</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6916</guid>
      </item>
    
      <item>
        <title>Subscription-Based Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-subscription-based-erc20-token/13964</comments>
        
        <description>## Abstract

This subscription-based [ERC-20](/EIPs/EIPS/eip-20) token extends the basic [ERC-20](/EIPs/EIPS/eip-20) token standard with a `subscribe` and `unsubscribe` function, which allow users to subscribe or unsubscribe from the subscription service. The `subscriptionFee` and `subscriptionFrequency` variables define the cost and frequency of the subscription. The `nextPaymentDate` mapping keeps track of the next payment date for each subscriber.

This token standard will enable automatic periodic deductions from user balances as determined by the merchant subscriber. Simplify and streamline subscription-based services on the Ethereum network, offering enhanced convenience and efficiency for users and merchants alike.

A `renewSubscription` method, that will be used by token holders to renew their subscription to a service or product that requires recurring payments in the form of the token.

## Motivation

The rise of subscription-based business models necessitates a standardized approach to handle recurring payments on the Ethereum blockchain. Currently, users often manually initiate subscription payments, resulting in inconvenience and potential disruptions in service delivery. By introducing a Subscription Token, users can seamlessly authorize periodic deductions, enabling uninterrupted access to subscribed services.

The subscription-based [ERC-20](/EIPs/EIPS/eip-20) token provides a more flexible and convenient way to manage recurring payments. It can be used for a wide range of services and products that require regular payments, such as subscription-based content platforms, gaming services, and more.

The Subscription Token ensures consistency and interoperability across different implementations. Key features include:

- Auto Deduction: Merchants, acting as subscribers, can set the subscription interval and associated payment amount for their services. This information is encoded within the Subscription Token contract, enabling automatic deductions from user balances at regular intervals without requiring manual intervention.

- Balance Check: Users can verify the remaining balance of their subscription tokens at any given time. This transparency empowers users to monitor their subscriptions and make informed decisions regarding their ongoing commitment to the service.

- Flexibility: The Subscription Token framework accommodates various subscription models, such as monthly, quarterly, or annual billing cycles. Additionally, merchants have the option to define trial periods, upgrade/downgrade plans, and cancellation policies, providing a versatile foundation for a wide range of subscription-based businesses.

- Security: The Subscription Token employs established security measures, including the use of cryptographic signatures, to ensure the integrity and authenticity of subscription-related transactions. This protects both users and merchants from unauthorized access and potential malicious activities.

## Specification

Below are the implementations required by the standard:


### `SubscriptionToken`

#### `subscribers`

Returns the list of `addresses` subscribed to the subscription token contract.

#### `subscriptionInfo`

Metadata information of the subscription, like - `subscriptionID`, `subscriptionName`, `subscriptionDesc` and `subscriptionTandC`.

#### `subscriptionFee`

The subscription amount specified that will be deducted in `subscriptionFrequency` interval, when an address subscribes to the subscription token contract.

#### `subscriptionFrequency`

Frequency of subscription, interval at which the `subscriptionFee` will be charged. for example, every 1 day, 1 week or 1 month, denoted in seconds.

#### `subscribe`

Method for subscribing an address to the subscription token contract.

#### `unsubscribe`

Revoke subscription from the subscription token contract, by the subscribed address.

```solidity
interface ISubscriptionERC20 {
  /// @dev map subscribers address, returns address(0) if `idx` is not found
  /// @param idx: the key of the map values
  /// @return the address at key `idx` of subscribers map
  function subscribers(uint idx) external view returns (address);

  /// @dev information of the subscription token contract
  /// @return subscriptionID, subscriptionName, subscriptionDesc, subscriptionTandC
  function subscriptionInfo() external view returns ( uint, string memory, string memory, string memory );

  /// @dev subscribes to the subscription, can be payable
  function subscribe() external;

  /// @dev unsubscribe the subscription
  function unsubscribe() external;

  /// @dev view or pure can be used
  /// @return the subscription fee
  function subscriptionFee() external view returns (uint256);

  /// @dev view or pure can be used
  /// @return get the subscription frequency
  function subscriptionFrequency() external view returns (uint);
}
```

## Rationale

The subscription token contract inherits the fundamentals of subscription by deducting payments from subscribed addresses on a regular interval using mathematical formulas.

```
uint256 intervals = ( block.timestamp - info.start ) / info.frequency;
uint256 amount = info.amount * intervals;

uint256 localEffectiveBalance = effectiveBalance[account];

if ( (totalAmount + amount) &gt; localEffectiveBalance ) {
    amount = localEffectiveBalance;
}

totalAmount += ( localEffectiveBalance - amount );
```

Here, the token balance of the address is calculated using, the locked balances from ongoing subscripitons and the effective balance of the address (updates whenever a transfer is made).

## Backwards Compatibility

No backward compatibility issues found.

## Security Considerations

Subscription Tokens may require users to sign transactions or provide cryptographic proofs for subscription-related actions. Proper key management practices should be followed to protect users&apos; private keys and prevent unauthorized access. Encouraging the use of hardware wallets or secure key storage solutions can mitigate the risk of key compromise.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 25 Apr 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6932</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6932</guid>
      </item>
    
      <item>
        <title>ERC-5219 Resolve Mode</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-5219-resolve-mode/14088</comments>
        
        <description>## Abstract

This EIP adds a new [ERC-4804](/EIPs/EIPS/eip-4804) `resolveMode` to resolve [ERC-5219](/EIPs/EIPS/eip-5219) contract resource requests.

## Specification

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

Contracts wishing to use ERC-5219 as their ERC-4804 resolve mode must implement the following interface:

```solidity
/// @dev IDecentralizedApp is the ERC-5219 interface
interface IERC5219Resolver is IDecentralizedApp {
    // @notice The ERC-4804 resolve mode
    // @dev    This MUST return &quot;5219&quot; (0x3532313900000000000000000000000000000000000000000000000000000000) for ERC-5219 resolution (case-insensitive). The other options, as of writing this, are &quot;auto&quot; for automatic resolution, or &quot;manual&quot; for manual resolution.
    function resolveMode() external pure returns (bytes32 mode);
}
```

## Rationale

[ERC-165](/EIPs/EIPS/eip-165) was not used because interoperability can be checked by calling `resolveMode`.

## Backwards Compatibility

No backward compatibility issues found.


## Reference Implementation

```solidity
abstract contract ERC5219Resolver is IDecentralizedApp {
    function resolveMode() public pure returns (bytes32 mode) {
      return &quot;5219&quot;;
    }
}
```


## Security Considerations

The security considerations of [ERC-4804](/EIPs/EIPS/eip-4804#security-considerations) and [ERC-5219](/EIPs/EIPS/eip-5219#security-considerations) apply.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 27 Apr 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6944</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6944</guid>
      </item>
    
      <item>
        <title>Network Upgrade Activation Triggers</title>
        <category>Informational/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6666-network-upgrade-activation-triggers/14047</comments>
        
        <description>## Abstract

This EIP outlines the various network upgrade activation triggers used on Ethereum over time, from the proof-of-work era to the first post-merge network upgrade, Shanghai/Capella, across both the execution and consensus layers.

## Motivation

This EIP aims to provide users and developers with a single source of truth for understanding the various upgrade activation patterns used throughout Ethereum&apos;s history. It does not aim to be a comprehensive, ongoing record, of upgrades and their activations mechanism. Readers should assume that future upgrades use the mechanism described in the [Post Merge Upgrades](#post-merge-upgrades) section, unless this EIP is superseded by another one. 

## Specification

### Proof-of-Work Network Upgrades

During the proof-of-work era, network upgrades on Ethereum were triggered based on specific block numbers. The following upgrades followed this pattern:

| Upgrade Name       | Activation Block Number |
|--------------------|-------------------------|
| Frontier           | `1`                     |
| Frontier Thawing   | `200000`				   |
| Homestead          | `1150000`               |
| DAO Fork           | `1920000`               |
| Tangerine Whistle  | `2463000`               |
| Spurious Dragon    | `2675000`               |
| Byzantium          | `4370000`               |
| Constantinople     | `7280000`               |
| Petersburg         | `7280000`               |
| Istanbul           | `9069000`               |
| Muir Glacier       | `9200000`               |
| Berlin	         | `12244000`              |
| London	         | `12965000`              |
| Arrow Glacier	     | `13773000`              |
| Gray Glacier	     | `15050000`              | 

### Beacon Chain Launch

The Beacon Chain was launched following a set of conditions detailed in [EIP-2982](/EIPs/EIPS/eip-2982). The launch was activated once all the following conditions were met:

1. The Beacon Chain deposit contract received at least `524288` ETH from `16384` validators.
2. The `MIN_GENESIS_TIME` timestamp of `1606824000` (Dec 1, 2020) had been exceeded.
3. A `GENESIS_DELAY` of `604800` seconds had passed since the minimum validator count was exceeded.

### Beacon Chain Upgrades

Beacon Chain upgrades are activated at specific epochs. The following upgrades followed this pattern:

| Upgrade Name | Activation Epoch |
|--------------|------------------|
| Altair       | `74240`          |
| Bellatrix    | `144896`         |

### The Merge: Paris Upgrade

The Paris upgrade, the execution layer portion of &quot;The Merge,&quot; was triggered by a proof-of-work Total Difficulty value of `58750000000000000000000`, as specified in [EIP-3675](/EIPs/EIPS/eip-3675). Note that the activation of the Bellatrix upgrade on the Beacon Chain was a pre-requisite for the Paris upgrade to successfully activate on the proof-of-work chain. 

### Post-Merge Upgrades

After The Merge, network upgrades are triggered at an epoch on the consensus layer (CL), which ideally maps to an historical roots accumulator boundary (i.e., a multiple of 8192 slots). The epoch&apos;s corresponding timestamp, rather than a block number, is then used on the execution layer (EL) as the activation trigger. The following upgrades followed this pattern:

| Upgrade Name     | Activation Epoch | Activation Timestamp |
|------------------|------------------|----------------------|
| Capella  (CL)    | `194048`         |                      |
| Shanghai (EL)    |                  | `1681338455`         |

Note that epoch `194048` happened at timestamp `1681338455`. In other words, the upgrades activated simultaneously on both the execution and consensus layers, even though they each used a different constant to trigger it. 

Additionally, the use of timestamps on the execution layer resulted in changes to how nodes&apos; `FORK_HASH` and `FORK_NEXT` values are calculated. These are described in [EIP-6122](/EIPs/EIPS/eip-6122)

## Rationale

### Blocks and Epochs

Blocks and epochs serve as natural trigger points for upgrades, as they represent the levels at which state transitions occur on Ethereum.

### Terminal Total Difficulty

For the Terminal Total Difficulty mechanism, the rationale can be found in [EIP-3675](/EIPs/EIPS/eip-3675).

### Timestamps

Due to the possibility of missed slots on the Beacon Chain, the execution layer cannot rely solely on block numbers to trigger upgrades in sync with the consensus layer. 

Timestamps are guaranteed to map to a specific epoch, and in their Unix representation, timestamps will always be greater than the block numbers previously used. This allows for a reliable method to trigger upgrades on the execution layer post-merge, while also ensuring that a post-merge upgrade based on a timestamp can never use a value that is considered lower than the last block-triggered upgrade.

## Security Considerations

None. 

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 28 Apr 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6953</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6953</guid>
      </item>
    
      <item>
        <title>Asset-bound Non-Fungible Tokens</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-6956-asset-bound-non-fungible-tokens/14056</comments>
        
        <description>## Abstract

This standard allows integrating physical and digital ASSETS without signing capabilities into dApps/web3 by extending [ERC-721](/EIPs/EIPS/eip-721).

An ASSET, for example a physical object, is marked with a uniquely identifiable ANCHOR. The ANCHOR is bound in a secure and inseparable manner 1:1 to an NFT on-chain - over the complete life cycle of the ASSET. 

Through an ATTESTATION, an ORACLE testifies that a particular ASSET associated with an ANCHOR has been CONTROLLED when defining the `to`-address for certain operations (mint, transfer, burn, approve, ...). The ORACLE signs the ATTESTATION off-chain. The operations are authorized through verifying on-chain that ATTESTATION has been signed by a trusted ORACLE. Note that authorization is solely provided through the ATTESTATION, or in other words, through PROOF-OF-CONTROL over the ASSET. The controller of the ASSET is guaranteed to be the controller of the Asset-Bound NFT.

The proposed ATTESTATION-authorized operations such as `transferAnchor(attestation)` are permissionless, meaning neither the current owner (`from`-address) nor the receiver (`to`-address) need to sign. 

Figure 1 shows the data flow of an ASSET-BOUND NFT transfer. The simplified system is utilizing a smartphone as user-device to interact with a physical ASSET and specify the `to`-address.

![Figure 1: Sample system](/EIPs/assets/eip-6956/img/erc6956_concept.svg)

## Motivation

The well-known [ERC-721](/EIPs/EIPS/eip-721) establishes that NFTs may represent &quot;ownership over physical properties [...] as well as digital collectables and even more abstract things such as responsibilities&quot; - in a broader sense, we will refer to all those things as ASSETS, which typically have value to people.

### The Problem

ERC-721 outlines that &quot;NFTs can represent ownership over digital or physical assets&quot;. ERC-721 excels in this task when used to represent ownership over digital, on-chain assets, that is when the asset is &quot;holding a token of a specific contract&quot; or the asset is an NFT&apos;s metadata. Today, people commonly treat an NFT&apos;s metadata (images, traits, ...) as asset-class, with their rarity often directly defining the value of an individual NFT. 

However, we see integrity issues not solvable with ERC-721, primarily when NFTS are used to represent off-chain ASSETS (&quot;ownership over physical products&quot;, &quot;digital collectables&quot;, &quot;in-game assets&quot;, &quot;responsibilities&quot;, ...). Over an ASSET&apos;s lifecycle, the ASSET&apos;s ownership and possession state changes multiple, sometimes thousands, of times. Each of those state changes may result in shifting obligations and privileges for the involved parties. Therefore tokenization of an ASSET *without* enforcably anchoring the ASSET&apos;s associated obligation and properties to the token is not complete. Nowadays, off-chain ASSETs are often &quot;anchored&quot; through adding an ASSET-identifier to a NFT&apos;s metadata. 

**NFT-ASSET integrity:** Contrary to a popular belief among NFT-investors, metadata is data that is, more often than not, mutable and off-chain. Therefore the link between an ASSET through an asset-identifier stored in mutable metadata, which is only linked to the NFT through tokenURI, can be considered weak at best.

Approaches to ensure integrity between metadata (=reference to ASSET) and a token exist. This is most commonly achieved by storing metadata-hashes onchain. Additional problems arise through hashing; For many applications, metadata (besides the asset-identifier) should be update-able. Therefore making metadata immutable through storing a hash is problematic. Further the offchain metadata-resource specified via tokenURI must be made available until eternity, which has historically been subject to failure (IPFS bucket disappears, central tokenURI-provider has downtimes, ...)

**Off-chain-on-chain-integrity:** There are approaches where off-chain ASSET ownership is enforced or conditioned through having ownership over the on-chain representation. A common approach is to burn tokens in order to get the (physical) ASSET, as the integrity cannot be maintained. However, there are no approaches known, where on-chain ownership is enforced through having off-chain ownership of the ASSET. Especially when the current owner of an NFT is incooperative or incapacitated, integrity typically fail due to lack of signing-power from the current NFT owner.

Metadata is off-chain. The majority of implementations completely neglect that metadata is mutable. More serious implementations strive to preserve integrity by for example hashing metadata and storing the hash mapped to the tokenId on-chain. However, this approach does not allow for use-case, where metadata besides the asset-identifier, for example traits, &quot;hours played&quot;, ... shall be mutable or evolvable.

### ASSET-BOUND NON-FUNGIBLE TOKENS

In this standard we propose to

1. Elevate the concept of representing physical or digital off-chain ASSETS by on-chain ANCHORING the ASSET inseperably into an NFT.
1. Being off-chain in control over the ASSET must mean being on-chain in control over the anchored NFT.
1. (Related) A change in off-chain ownership over the ASSET inevitably should be reflected by a change in on-chain ownership over the anchored NFT, even if the current owner is uncooperative or incapacitated.

As 2. and 3. indicate, the control/ownership/possession of the ASSET should be the single source of truth, *not* the possession of an NFT. Hence, we propose an ASSET-BOUND NFT, where off-chain CONTROL over the ASSET enforces on-chain CONTROL over the anchored NFT.
Also the proposed ASSET-BOUND NFTs allow to anchor digital metadata inseperably to the ASSET. When the ASSET is a physical asset, this allows to design &quot;phygitals&quot; in their purest form, namely creating a &quot;phygital&quot; asset with a physical and digital component that are inseparable. Note that metadata itself can still change, for instance for &quot;Evolvable NFT&quot;.

We propose to complement the existing transfer control mechanisms of a token according to [ERC-721](/EIPs/EIPS/eip-721) by another mechanism; ATTESTATION. An ATTESTATION is signed off-chain by the ORACLE and must only be issued when the ORACLE verified that whoever specifies the `to` address or beneficiary address has simultaneously been in control over the ASSET. The `to` address of an attestation may be used for Transfers as well as for approvals and other authorizations.

Transactions authorized via ATTESTATION shall not require signature or approval from neither the `from` (donor, owner, sender) nor `to` (beneficiary, receiver) account, namely making transfers permissionless. Ideally, transaction are signed independent from the ORACLE as well, allowing different scenarios in terms of gas-fees.

Lastly we want to mention two major side-benefits of using the proposed standard, which drastically lowers hurdles in onboarding web2 users and increase their security;

- New users, e.g `0xaa...aa` (Fig.1), can use gasless wallets, hence participate in Web3/dApps/DeFi and mint+transfer tokens without ever owning crypto currency. Gas-fees may be paid through a third-party account `0x..gasPayer` (Fig.1). The gas is typically covered by the ASSET issuer, who signs `transferAnchor()` transactions
- Users cannot get scammed. Common attacks (for example wallet-drainer scams) are no longer possible or easily reverted, since only the anchored NFT can be stolen, not the ASSET itself. Also mishaps like transferring the NFT to the wrong account, losing access to an account etc can be mitigated by executing another `transferAnchor()` transaction based on proofing control over the ASSET, namely the physical object.

### Related work

We primarily aim to onboard physical or digital ASSETS into dApps, which do not signing-capabilities of their own (contrary to other proposals relying on crypto-chips). Note that we do not see any restrictions preventing to use such solutions in combination with this standard, as the address of the crypto-chip qualifies as an ANCHOR.

## Specification

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

### Definitions (alphabetical)

- **ANCHOR** uniquely identifies the off-chain ASSET, whether it is physical or digital.
- **ANCHOR-TECHNOLOGY** MUST ensure that
  - the ANCHOR is inseparable from the ASSET (physically or otherwise)
  - an ORACLE can establish PROOF-OF-CONTROL over the ASSET beyond reasonable doubt
  - For physical ASSETS, additional [Security considerations for Physical Assets](#security-considerations-for-physical-assets) MUST be taken into account 

- **ASSET** refers to the &quot;thing&quot;, being it physical or digital, which is represented through NFTs according to the proposed standard. Typically, an ASSET does not have signing capabilities.

- **ATTESTATION** is the confirmation that PROOF OF CONTROL was established when specifying the `to` (receiver, beneficiary) address.

- **PROOF-OF-CONTROL** over the ASSET means owning or otherwise controlling an ASSET. How Proof of Control is established depends on the ASSET and may be implemented using technical, legal or other means. For physical ASSETS, CONTROL is typically verified by proofing physical proximity between a physical ASSET and an input device (for example a smartphone) used to specify the `to` address.

- An **ORACLE** has signing capabilities. MUST be able to sign ATTESTATIONS off-chain in a way such that signatures can be verified on-chain.


### Base Interface

Every contract compliant to this standard MUST implement the [the proposed standard interface](/EIPs/assets/eip-6956/contracts/IERC6956.sol), [ERC-721](/EIPs/EIPS/eip-721) and [ERC-165](/EIPs/EIPS/eip-165) interfaces and is subject to [Caveats](#caveats-for-base-interface) below:

```solidity
// SPDX-License-Identifier: MIT OR CC0-1.0
pragma solidity ^0.8.18;

/**
 * @title IERC6956 Asset-Bound Non-Fungible Tokens 
 * @notice Asset-bound Non-Fungible Tokens anchor a token 1:1 to a (physical or digital) asset and token transfers are authorized through attestation of control over the asset
 * @dev See https://eips.ethereum.org/EIPS/eip-6956
 *      Note: The ERC-165 identifier for this interface is 0xa9cf7635
 */
interface IERC6956 {
   
    /** @dev Authorization, typically mapped to authorizationMaps, where each bit indicates whether a particular ERC6956Role is authorized 
     *      Typically used in constructor (hardcoded or params) to set burnAuthorization and approveAuthorization
     *      Also used in optional updateBurnAuthorization, updateApproveAuthorization, I
     */ 
    enum Authorization {
        NONE,               // = 0,      // None of the above
        OWNER,              // = (1&lt;&lt;OWNER), // The owner of the token, i.e. the digital representation
        ISSUER,             // = (1&lt;&lt;ISSUER), // The issuer of the tokens, i.e. this smart contract
        ASSET,              // = (1&lt;&lt;ASSET), // The asset, i.e. via attestation
        OWNER_AND_ISSUER,   // = (1&lt;&lt;OWNER) | (1&lt;&lt;ISSUER),
        OWNER_AND_ASSET,    // = (1&lt;&lt;OWNER) | (1&lt;&lt;ASSET),
        ASSET_AND_ISSUER,   // = (1&lt;&lt;ASSET) | (1&lt;&lt;ISSUER),
        ALL                 // = (1&lt;&lt;OWNER) | (1&lt;&lt;ISSUER) | (1&lt;&lt;ASSET) // Owner + Issuer + Asset
    }
    
    /**
     * @notice This emits when approved address for an anchored tokenId is changed or reaffirmed via attestation
     * @dev This emits when approveAnchor() is called and corresponds to ERC-721 behavior
     * @param owner The owner of the anchored tokenId
     * @param approved The approved address, address(0) indicates there is no approved address
     * @param anchor The anchor, for which approval has been changed
     * @param tokenId ID (&gt;0) of the anchored token
     */
    event AnchorApproval(address indexed owner, address approved, bytes32 indexed anchor, uint256 tokenId);

    /**
     * @notice This emits when the ownership of any anchored NFT changes by any mechanism
     * @dev This emits together with tokenId-based ERC-721.Transfer and provides an anchor-perspective on transfers
     * @param from The previous owner, address(0) indicate there was none.
     * @param to The new owner, address(0) indicates the token is burned
     * @param anchor The anchor which is bound to tokenId
     * @param tokenId ID (&gt;0) of the anchored token
     */
    event AnchorTransfer(address indexed from, address indexed to, bytes32 indexed anchor, uint256 tokenId);
    /**
     * @notice This emits when an attestation has been used indicating no second attestation with the same attestationHash will be accepted
     * @param to The to address specified in the attestation
     * @param anchor The anchor specified in the attestation
     * @param attestationHash The hash of the attestation, see ERC-6956 for details
     * @param totalUsedAttestationsForAnchor The total number of attestations already used for the particular anchor
     */
    event AttestationUse(address indexed to, bytes32 indexed anchor, bytes32 indexed attestationHash, uint256 totalUsedAttestationsForAnchor);

    /**
     * @notice This emits when the trust-status of an oracle changes. 
     * @dev Trusted oracles must explicitly be specified. 
     *      If the last event for a particular oracle-address indicates it&apos;s trusted, attestations from this oracle are valid.
     * @param oracle Address of the oracle signing attestations
     * @param trusted indicating whether this address is trusted (true). Use (false) to no longer trust from an oracle.
     */
    event OracleUpdate(address indexed oracle, bool indexed trusted);

    /**
     * @notice Returns the 1:1 mapped anchor for a tokenId
     * @param tokenId ID (&gt;0) of the anchored token
     * @return anchor The anchor bound to tokenId, 0x0 if tokenId does not represent an anchor
     */
    function anchorByToken(uint256 tokenId) external view returns (bytes32 anchor);
    /**
     * @notice Returns the ID of the 1:1 mapped token of an anchor.
     * @param anchor The anchor (&gt;0x0)
     * @return tokenId ID of the anchored token, 0 if no anchored token exists
     */
    function tokenByAnchor(bytes32 anchor) external view returns (uint256 tokenId);

    /**
     * @notice The number of attestations already used to modify the state of an anchor or its bound tokens
     * @param anchor The anchor(&gt;0)
     * @return attestationUses The number of attestation uses for a particular anchor, 0 if anchor is invalid.
     */
    function attestationsUsedByAnchor(bytes32 anchor) view external returns (uint256 attestationUses);
    /**
     * @notice Decodes and returns to-address, anchor and the attestation hash, if the attestation is valid
     * @dev MUST throw when
     *  - Attestation has already been used (an AttestationUse-Event with matching attestationHash was emitted)
     *  - Attestation is not signed by trusted oracle (the last OracleUpdate-Event for the signer-address does not indicate trust)
     *  - Attestation is not valid yet or expired
     *  - [if IERC6956AttestationLimited is implemented] attestationUsagesLeft(attestation.anchor) &lt;= 0
     *  - [if IERC6956ValidAnchors is implemented] validAnchors(data) does not return true. 
     * @param attestation The attestation subject to the format specified in ERC-6956
     * @param data Optional additional data, may contain proof as the first abi-encoded argument when IERC6956ValidAnchors is implemented
     * @return to Address where the ownership of an anchored token or approval shall be changed to
     * @return anchor The anchor (&gt;0)
     * @return attestationHash The attestation hash computed on-chain as `keccak256(attestation)`
     */
    function decodeAttestationIfValid(bytes memory attestation, bytes memory data) external view returns (address to, bytes32 anchor, bytes32 attestationHash);

    /**
     * @notice Indicates whether any of ASSET, OWNER, ISSUER is authorized to burn
     */
    function burnAuthorization() external view returns(Authorization burnAuth);

    /**
     * @notice Indicates whether any of ASSET, OWNER, ISSUER is authorized to approve
     */
    function approveAuthorization() external view returns(Authorization approveAuth);

    /**
     * @notice Corresponds to transferAnchor(bytes,bytes) without additional data
     * @param attestation Attestation, refer ERC-6956 for details
     */
    function transferAnchor(bytes memory attestation) external;

    /**
     * @notice Changes the ownership of an NFT mapped to attestation.anchor to attestation.to address.
     * @dev Permissionless, i.e. anybody invoke and sign a transaction. The transfer is authorized through the oracle-signed attestation.
     *  - Uses decodeAttestationIfValid()
     *  - When using a centralized &quot;gas-payer&quot; recommended to implement IERC6956AttestationLimited.
     *  - Matches the behavior of ERC-721.safeTransferFrom(ownerOf[tokenByAnchor(attestation.anchor)], attestation.to, tokenByAnchor(attestation.anchor), ..) and mint an NFT if `tokenByAnchor(anchor)==0`.
     *  - Throws when attestation.to == ownerOf(tokenByAnchor(attestation.anchor))
     *  - Emits AnchorTransfer  
     *  
     * @param attestation Attestation, refer ERC-6956 for details
     * @param data Additional data, may be used for additional transfer-conditions, may be sent partly or in full in a call to safeTransferFrom
     * 
     */
    function transferAnchor(bytes memory attestation, bytes memory data) external;

     /**
     * @notice Corresponds to approveAnchor(bytes,bytes) without additional data
     * @param attestation Attestation, refer ERC-6956 for details
     */
    function approveAnchor(bytes memory attestation) external;

     /**
     * @notice Approves attestation.to the token bound to attestation.anchor. .
     * @dev Permissionless, i.e. anybody invoke and sign a transaction. The transfer is authorized through the oracle-signed attestation.
     *  - Uses decodeAttestationIfValid()
     *  - When using a centralized &quot;gas-payer&quot; recommended to implement IERC6956AttestationLimited.
     *  - Matches the behavior of ERC-721.approve(attestation.to, tokenByAnchor(attestation.anchor)).
     *  - Throws when ASSET is not authorized to approve.
     * 
     * @param attestation Attestation, refer ERC-6956 for details 
     */
    function approveAnchor(bytes memory attestation, bytes memory data) external;

    /**
     * @notice Corresponds to burnAnchor(bytes,bytes) without additional data
     * @param attestation Attestation, refer ERC-6956 for details
     */
    function burnAnchor(bytes memory attestation) external;
   
    /**
     * @notice Burns the token mapped to attestation.anchor. Uses ERC-721._burn.
     * @dev Permissionless, i.e. anybody invoke and sign a transaction. The transfer is authorized through the oracle-signed attestation.
     *  - Uses decodeAttestationIfValid()
     *  - When using a centralized &quot;gas-payer&quot; recommended to implement IERC6956AttestationLimited.
     *  - Throws when ASSET is not authorized to burn
     * 
     * @param attestation Attestation, refer ERC-6956 for details
     */
    function burnAnchor(bytes memory attestation, bytes memory data) external;
}
```

#### Caveats for Base Interface

- MUST implement ERC-721 and ERC-165
- MUST have bidirectional mapping `tokenByAnchor(anchor)` and `anchorByToken(tokenId)`. This implies that a maximum of one token per ANCHOR exists.
- MUST have a mechanism to determine whether an ANCHOR is valid for the contract. RECOMMENDED to implement the proposed [ValidAnchors-Interface](#validanchors-interface)
- MUST implement `decodeAttestationIfValid(attestation, data)` to validate and decode ATTESTATIONS as specified in the [ORACLE-Section](#oracle)
  - MUST return `attestation.to`, `attestation.anchor`, `attestation.attestationHash`.
  - MUST not modify state, as this function can be used to check an ATTESTATION&apos;s validity without redeeming it.
  - MUST throw when
    - ATTESTATION is not signed from a trusted ORACLE.
    - ATTESTATION has expired or is not valid yet
    - ATTESTATION has not been redeemed. &quot;Redeemed&quot; being defined in at least one state-changing operation has been authorized through a particular ATTESTATION.
    - If [AttestationLimited-Interface](#attestationlimited-interface) implemented: When `attestationUsagesLeft(attestation.to) &lt;= 0`  
    - If [ValidAnchors-Interface](#validanchors-interface) implemented: When `validAnchor() != true`.
  - If [ValidAnchors-Interface](#validanchors-interface) implemented: MUST call `validAnchor(attestation.to, abi.decode(&apos;bytes32[]&apos;,data))`, meaning the first abi-encoded value in the `data` parameter corresponds to `proof`.
- MUST have a ANCHOR-RELEASED mechanism, indicating whether the anchored NFT is released/transferable. 
  - Any ANCHOR MUST NOT be released by default.
- MUST extend any ERC-721 token transfer mechanism by:
  - MUST throw when `ANCHOR` is not released.
  - MUST throw when batchSize &gt; 1, namely no batch transfers are supported with this contract.
  - MUST emit `AnchorTransfer(from, to, anchorByToken[tokenId], tokenId)`

- MUST implement `attestationsUsedByAnchor(anchor)`, returning how many attestations have already been used for a specific anchor.

- MUST implement the state-changing `transferAnchor(..)`, `burnAnchor(..)`, `approveAnchor(..)` and OPTIONAL MAY implement additional state-changing operations which
  - MUST use the `decodeAttestationIfValid()` to determine `to`, `anchor` and `attestationHash`
  - MUST redeem each ATTESTATION in the same transaction as any authorized state-changing operation. RECOMMENDED by storing each used `attestationHash`
  - MUST increment `attestationsUsedByAnchor[anchor]`
  - MUST emit `AttestationUsed`
  - `transferAnchor(attestation)` MUST behave and emit events like `ERC-721.safeTransferFrom(ownerOf[tokenByAnchor(attestation.anchor)], attestation.to, tokenByAnchor(attestation.anchor), ..)` and mint an NFT if `tokenByAnchor(anchor)==0`.
 
- RECOMMENDED to implement `tokenURI(tokenId)` to return an anchorBased-URI, namely `baseURI/anchor`. This anchoring metadata to ASSET. Before an anchor is not used for the first time, the ANCHOR&apos;s mapping to tokenId is unknown. Hence, using the anchor in instead of the tokenId is preferred.


### ORACLE

- MUST provide an ATTESTATION. Below we define the format how an ORACLE testifies that the `to` address of a transfer has been specified under the pre-condition of PROOF-OF-CONTROL associated with the particular ANCHOR being transferred to `to`.
- The ATTESTATION MUST abi-encode the following:
  - `to`, MUST be address, specifying the beneficiary, for example the to-address, approved account etc.
  - ANCHOR, aka the ASSET identifier, MUST have a 1:1 relation to the ASSET
  - `attestationTime`, UTC seconds, time when attestation was signed by ORACLE,
  - `validStartTime` UTC seconds, start time of the ATTESTATION&apos;s validity timespan
  - `validEndTime`, UTC seconds, end time of the ATTESTATION&apos;s validity timespan
  - `signature`, ETH-signature (65 bytes). Output of an ORACLE signing the `attestationHash = keccak256([to, anchor, attestationTime, validStartTime, validEndTime])`.
- How PROOF-OF-CONTROL is establish in detail through an ANCHOR-TECHNOLOGY is not subject to this standard. Some ORACLE requirements and ANCHOR-TECHNOLOGY requirements when using PHYSICAL ASSETS are outlined in [Security considerations for Physical Assets](#security-considerations-for-physical-assets).

A Minimal Typescript sample to generate an ATTESTATION is available in the [Reference Implementation section](#reference-implementation) of this proposal.

### AttestationLimited-Interface

Every contract compliant to this standard MAY implement the [proposed AttestationLimited interface](/EIPs/assets/eip-6956/contracts/IERC6956AttestationLimited.sol) and is subject to [Caveats](#caveats-for-attestationlimited-interface) below:

```solidity
// SPDX-License-Identifier: MIT OR CC0-1.0
pragma solidity ^0.8.18;
import &quot;./IERC6956.sol&quot;;

/**
 * @title Attestation-limited Asset-Bound NFT
 * @dev See https://eips.ethereum.org/EIPS/eip-6956
 *      Note: The ERC-165 identifier for this interface is 0x75a2e933
 */
interface IERC6956AttestationLimited is IERC6956 {
  enum AttestationLimitPolicy {
    IMMUTABLE,
    INCREASE_ONLY,
    DECREASE_ONLY,
    FLEXIBLE
  }
      
  /// @notice Returns the attestation limit for a particular anchor
  /// @dev MUST return the global attestation limit per default
  ///      and override the global attestation limit in case an anchor-based limit is set
  function attestationLimit(bytes32 anchor) external view returns (uint256 limit);

  /// @notice Returns number of attestations left for a particular anchor
  /// @dev Is computed by comparing the attestationsUsedByAnchor(anchor) and the current attestation limit 
  ///      (current limited emitted via GlobalAttestationLimitUpdate or AttestationLimit events)
  function attestationUsagesLeft(bytes32 anchor) external view returns (uint256 nrTransfersLeft);

  /// @notice Indicates the policy, in which direction attestation limits can be updated (globally or per anchor)
  function attestationLimitPolicy() external view returns (AttestationLimitPolicy policy);

  /// @notice This emits when the global attestation limit is updated
  event GlobalAttestationLimitUpdate(uint256 indexed transferLimit, address updatedBy);

  /// @notice This emits when an anchor-specific attestation limit is updated
  event AttestationLimitUpdate(bytes32 indexed anchor, uint256 indexed tokenId, uint256 indexed transferLimit, address updatedBy);

  /// @dev This emits in the transaction, where attestationUsagesLeft becomes 0
  event AttestationLimitReached(bytes32 indexed anchor, uint256 indexed tokenId, uint256 indexed transferLimit);
}
```

#### Caveats for AttestationLimited-Interface

- MUST extend the proposed standard interface
- MUST define one of the above listed AttestationLimit update policies and expose it via `attestationLimitPolicy()`
  - MUST support different update modes, namely FIXED, INCREASE_ONLY, DECREASE_ONLY, FLEXIBLE (= INCREASABLE and DECREASABLE)
  - RECOMMENDED to have a global transfer limit, which can be overwritten on a token-basis (when `attestationLimitPolicy() != FIXED`)
- MUST implement `attestationLimit(anchor)`, specifying how often an ANCHOR can be transferred in total. Changes in the return value MUST reflect the AttestationLimit-Policy.
- MUST implement `attestationUsagesLeft(anchor)`, returning the number of usages left (namely `attestationLimit(anchor)-attestationsUsedByAnchor[anchor]`) for a particular anchor


### Floatable-Interface

Every contract compliant to this extension MAY implement the proposed [Floatable interface](/EIPs/assets/eip-6956/contracts/IERC6956Floatable.sol) and is subject to [Caveats](#caveats-for-floatable-interface) below:

```solidity
// SPDX-License-Identifier: MIT OR CC0-1.0
pragma solidity ^0.8.18;
import &quot;./IERC6956.sol&quot;;

/**
 * @title Floatable Asset-Bound NFT
 * @notice A floatable Asset-Bound NFT can (temporarily) be transferred without attestation
 * @dev See https://eips.ethereum.org/EIPS/eip-6956
 *      Note: The ERC-165 identifier for this interface is 0xf82773f7
 */
interface IERC6956Floatable is IERC6956 {
  enum FloatState {
    Default, // 0, inherits from floatAll
    Floating, // 1
    Anchored // 2
  }

  /// @notice Indicates that an anchor-specific floating state changed
  event FloatingStateChange(bytes32 indexed anchor, uint256 indexed tokenId, FloatState isFloating, address operator);
  /// @notice Emits when FloatingAuthorization is changed.
  event FloatingAuthorizationChange(Authorization startAuthorization, Authorization stopAuthorization, address maintainer);
  /// @notice Emits, when the default floating state is changed
  event FloatingAllStateChange(bool areFloating, address operator);

  /// @notice Indicates whether an anchored token is floating, namely can be transferred without attestation
  function floating(bytes32 anchor) external view returns (bool);
  
  /// @notice Indicates whether any of OWNER, ISSUER, (ASSET) is allowed to start floating
  function floatStartAuthorization() external view returns (Authorization canStartFloating);
  
  /// @notice Indicates whether any of OWNER, ISSUER, (ASSET) is allowed to stop floating
  function floatStopAuthorization() external view returns (Authorization canStartFloating);

  /**
    * @notice Allows to override or reset to floatAll-behavior per anchor
    * @dev Must throw when newState == Floating and floatStartAuthorization does not authorize msg.sender
    * @dev Must throw when newState == Anchored and floatStopAuthorization does not authorize msg.sender
    * @param anchor The anchor, whose anchored token shall override default behavior
    * @param newState Override-State. If set to Default, the anchor will behave like floatAll
    */
  function float(bytes32 anchor, FloatState newState) external;    
}
```


#### Caveats for Floatable-Interface

If `floating(anchor)` returns true, the token identified by `tokenByAnchor(anchor)` MUST be transferable without attestation, typically authorized via `ERC721.isApprovedOrOwner(msg.sender, tokenId)` 

### ValidAnchors-Interface

Every contract compliant to this extension MAY implement the proposed [ValidAnchors interface](/EIPs/assets/eip-6956/contracts/IERC6956ValidAnchors.sol) and is subject to [Caveats](#caveats-for-validanchors-interface) below:

```solidity
// SPDX-License-Identifier: MIT OR CC0-1.0
pragma solidity ^0.8.18;
import &quot;./IERC6956.sol&quot;;

/**
 * @title Anchor-validating Asset-Bound NFT
 * @dev See https://eips.ethereum.org/EIPS/eip-6956
 *      Note: The ERC-165 identifier for this interface is 0x051c9bd8
 */
interface IERC6956ValidAnchors is IERC6956 {
    /**
     * @notice Emits when the valid anchors for the contract are updated.
     * @param validAnchorHash Hash representing all valid anchors. Typically Root of Merkle-Tree
     * @param maintainer msg.sender when updating the hash
     */
    event ValidAnchorsUpdate(bytes32 indexed validAnchorHash, address indexed maintainer);

    /**
     * @notice Indicates whether an anchor is valid in the present contract
     * @dev Typically implemented via MerkleTrees, where proof is used to verify anchor is part of the MerkleTree 
     *      MUST return false when no ValidAnchorsUpdate-event has been emitted yet
     * @param anchor The anchor in question
     * @param proof Proof that the anchor is valid, typically MerkleProof
     * @return isValid True, when anchor and proof can be verified against validAnchorHash (emitted via ValidAnchorsUpdate-event)
     */
    function anchorValid(bytes32 anchor, bytes32[] memory proof) external view returns (bool isValid);        
}
```

#### Caveats for ValidAnchors-Interface

- MUST implement `validAnchor(anchor, proof)` which returns true when anchor is valid, namely MerkleProof is correct, false otherwise.


## Rationale

**Why do you use an anchor&lt;&gt;tokenId mapping and not simply use tokenIds directly?**
Especially for collectable use-cases, special or sequential tokenIds (for example low numbers), have value. Holders may be proud to have claimed tokenId=1 respectively the off-chain ASSET with tokenId=1 may increase in value, because it was the first ever claimed. Or an Issuer may want to address the first 100 owners who claimed their ASSET-BOUND NFT. While these use-cases technically can certainly be covered by observing the blockchain state-changes, we consider reflecting the order in the tokenIds to be the user-friendly way. Please refer [Security considerations](#security-considerations) on why sequential anchors shall be avoided.

**Why is tokenId=0 and anchor=0x0 invalid?**
For gas efficiency. This allows to omit checks and state-variables for the existence of a token or anchor, since mappings of a non-existent key return 0 and cannot be easily distinguished from anchor=0 or tokenId=0.

**ASSETS are often batch-produced with the goal of identical properties, for example a batch of automotive spare parts. Why should do you extend ERC-721 and not Multi-Token standards?**
Even if a (physical) ASSET is mass produced with fungible characteristics, each ASSET has an individual property/ownership graph and thus shall be represented in a non-fungible way. Hence this EIP follows the design decision that ASSET (represented via a unique asset identifier called ANCHOR) and token are always mapped 1-1 and not 1-N, so that a token represents the individual property graph of the ASSET.

**Why is there a burnAnchor() and approveAnchor()?**
Due to the permissionless nature ASSET-BOUND NFTs can even be transferred to or from any address. This includes arbitrary and randomly generated accounts (where the private key is unknown) and smart-contracts which would traditionally not support ERC-721 NFTs. Following that owning the ASSET must be equivalent to owning the NFT, this means that we also need to support ERC-721 operations like approval and burning in such instances through authorizing the operations with an attestation.

**Implementation alternatives considered** Soulbound burn+mint combination, for example through Consensual Soulbound Tokens ([ERC-5484](/EIPs/EIPS/eip-5484)). Disregarded because appearance is highly dubious, when the same asset is represented through multiple tokens over time. An predecessor of this EIP has used this approach and can be found deployed to Mumbai Testnet under address `0xd04c443913f9ddcfea72c38fed2d128a3ecd719e`.

**When should I implement AttestationLimited-Interface**
Naturally, when your use-case requires each ASSET being transferable only a limited number of times. But also for security reasons, see [Security Considerations](#security-considerations)

**Why is there the `IERC6956Floatable.FloatState` enum?** In order to allow gas-efficient implementation of floatAll(), which can be overruled by anchor-based floatability in all combinations. (See rationale for tokenId=0 above).

**Why is there no `floating(tokenId)` function?**
This would behave identically to an `isTransferable(tokenId,...)` mechanism proposed in many other EIPs (refer e.g. [ERC-6454](/EIPs/EIPS/eip-6454)). Further, the proposed `floating(anchorByToken(tokenId))` can be used.

**Why are there different FloatingAuthorizations for start and stop?**
Depending on the use-case, different roles should be able to start or stop floating. Note that for many applications the ISSUER may want to have control over the floatability of the collection.


### Example Use Cases and recommended combination of interfaces

Possession based use cases are covered by the standard interface `IERC6956`: The holder of ASSET is in possession of ASSET. Possession is an important social and economical tool: In many sports games possession of ASSET, commonly referred to as &quot;the ball&quot;, is of essence. Possession can come with certain obligations and privileges. Ownership over an ASSET can come with rights and benefits as well as being burdened with liens and obligations. For example, an owned ASSET can be used for collateral, can be rented or can even yield a return. Example use-cases are

- **Possession based token gating:** Club guest in possession of limited T-Shirt (ASSET) gets a token which allows him to open the door to the VIP lounge.

- **Possession based digital twin:** A gamer is in possession of a pair of physical sneakers (ASSET), and gets a digital twin (NFT) to wear them in metaverse.

- **Scarce possession based digital twin:** The producer of the sneakers (ASSET) decided that the product includes a limit of 5 digital twins (NFTs), to create scarcity.

- **Lendable digital twin:** The gamer can lend his sneaker-tokens (NFT) to a friend in the metaverse, so that the friend can run faster.

- **Securing ownership from theft:** If ASSET is owned off-chain, the owner wants to secure the anchored NFT, namely not allow transfers to prevent theft or recover the NFT easily through the ASSET.

- **Selling a house with a mortgage:** The owner holds NFT as proof of ownership. The DeFi-Bank finances the house and puts a lock on the transfer of NFT. Allow Transfers of the NFT require the mortgage to be paid off. Selling the ASSET (house) off-chain will be impossible, as it&apos;s no longer possible to finance the house.

- **Selling a house with a lease:** A lease contract puts a lien on an ASSET&apos;s anchored NFT. The old owner removes the lock, the new owner buys and refinances the house. Transfer of NFT will also transfer the obligations and benefits of the lien to the new owner.

- **Buying a brand new car with downpayment:** A buyer configures a car and provides a downpayment, for a car that will have an ANCHOR. As long as the car is not produced, the NFT can float and be traded on NFT market places. The owner of the NFT at time of delivery of the ASSET has the permission to pick up the car and the obligation to pay full price.

- **Buying a barrel of oil by forward transaction:** A buyer buys an oil option on a forward contract for one barrel of oil (ASSET). On maturity date the buyer has the obligation to pick up the oil.

The use case matrix below shows which extensions and settings must (additionally to `IERC6956`!) be implemented for the example use-cases together with relevant configurations.

Note that for `Lockable` listed in the table below, the proposed EIP can be extended with any Lock- or Lien-Mechanism known to extend for ERC-721, for example [ERC-5192](/EIPs/EIPS/eip-5192) or [ERC-6982](/EIPs/EIPS/eip-6982). We recommend to verify whether a token is locked in the `_beforeTokenTransfer()`-hook, as this is called from `safeTransferFrom()` as well as `transferAnchor()`, hence suitable to block &quot;standard&quot; ERC-721 transfers as well as the proposed attestation-based transfers.

| Use Case | approveAuthorization | burnAuthorization | `IERC6956Floatable` | `IERC6956AttestationLimited` | Lockable |
|---------------|---|---|---|---|---|
| **Managing Possession** |
| Token gating  | ASSET | ANY | incompatible | - | - |
| Digital twin  | ASSET | ANY | incompatible | - | - |
| Scarce digital twin | ASSET | ANY | incompatible | required | - |
| Lendable digital twin         | OWNER_AND_ASSET | ASSET | required | - | - |
| **Managing Ownership** |
| Securing ownership from theft   | OWNER or OWNER_AND_ASSET | ANY | optional | - | required |
| Selling an house with a mortgage  | ASSET  or OWNER_AND_ASSET | ANY | optional | optional | required |
| Selling a house with a lease | ASSET or OWNER_AND_ASSET | ANY | optional | optional | required |
| Buying a brand new car with downpayment | ASSET or OWNER_AND_ASSET | ANY | optional | optional | required |
| Buying a barrel of oil by forward transaction | ASSET or OWNER_AND_ASSET | ANY | optional | optional | required |

Legend:

- required ... we don&apos;t see a way how to implement the use-case without it
- incompatible ... this MUSTN&apos;T be implemented, as it is a security risk for the use-case
- optional ... this MAY optionally be implemented

## Backwards Compatibility

No backward compatibility issues found. 

This EIP is fully compatible with ERC-721 and (when extended with the `IERC6956Floatable`-interface) corresponds to the well-known ERC-721 behavior with an additional authorization-mechanism via attestations. Therefore we recommend - especially for physical assets - to use the present EIP instead of ERC-721 and amend it with extensions designed for ERC-721.

However, it is RECOMMENDED to extend implementations of the proposed standard with an interface indicating transferability of NFTs for market places. Examples include [ERC-6454](/EIPs/EIPS/eip-6454) and [ERC-5484](/EIPs/EIPS/eip-5484).

Many ERC-721 extensions suggest to add additional throw-conditions to transfer methods. This standard is fully compatible, as

- The often-used ERC-721 `_beforeTokenTransfer()` hook must be called for all transfers including attestation-authorized transfers.
- A `_beforeAnchorUse()` hook is suggested in the reference implementation, which only is called when using attestation as authorization.

## Test Cases

Test cases are available:

- For only implementing [the proposed standard interface](/EIPs/assets/eip-6956/contracts/IERC6956.sol) can be found [here](/EIPs/assets/eip-6956/test/ERC6956.ts)
- For implementing [the proposed standard interface](/EIPs/assets/eip-6956/contracts/IERC6956.sol), [the Floatable extension](/EIPs/assets/eip-6956/contracts/IERC6956Floatable.sol), [the ValidAnchors extension](/EIPs/assets/eip-6956/contracts/IERC6956ValidAnchors.sol) and [the AttestationLimited extension](/EIPs/assets/eip-6956/contracts/IERC6956AttestationLimited.sol) can be found [here](/EIPs/assets/eip-6956/test/ERC6956Full.ts)

## Reference Implementation

- Minimal implementation, only supporting [the proposed standard interface](/EIPs/assets/eip-6956/contracts/IERC6956.sol) can be found [here](/EIPs/assets/eip-6956/contracts/ERC6956.sol)
- Full implementation, with support for [the proposed standard interface](/EIPs/assets/eip-6956/contracts/IERC6956.sol), [the Floatable extension](/EIPs/assets/eip-6956/contracts/IERC6956Floatable.sol), [the ValidAnchors extension](/EIPs/assets/eip-6956/contracts/IERC6956ValidAnchors.sol) and [the AttestationLimited extension](/EIPs/assets/eip-6956/contracts/IERC6956AttestationLimited.sol) can be found [here](/EIPs/assets/eip-6956/contracts/ERC6956Full.sol)
- A Minimal Typescript sample to generate an ATTESTATION using ethers library is available [here](/EIPs/assets/eip-6956/minimalAttestationSample.ts)

## Security Considerations

**If the asset is stolen, does this mean the thief has control over the NFT?**
Yes.The standard aims to anchor an NFT to the asset inseperably and unconditionally. This includes reflecting theft, as the ORACLE will testify that PROOF-OF-CONTROL over the ASSET is established. The ORACLE does not testify whether the controller is the legitimate owner,
Note that this may even be a benefit. If the thief (or somebody receiving the asset from the thief) should interact with the anchor, an on-chain address of somebody connected to the crime (directly or another victim) becomes known. This can be a valuable starting point for investigation.
Also note that the proposed standard can be combined with any lock-mechanism, which could lock attestation-based action temporarily or permanently (after mint).

**How to use AttestationLimits to avoid fund-draining**
A central security mechanism in blockchain applications are gas fees. Gas fees ensure that executing a high number of transactions get penalized, hence all DoS or other large-scale attacks are discouraged. Due to the permissionless nature of attestation-authorized operations, many use-cases will arise, where the issuer of the ASSET (which normally is also the issuer of the ASSET-BOUND NFT) will pay for all transactions - contrary to the well-known ERC-721 behavior, where either from- or to-address are paying. So a user with malicious intent may just let the ORACLE approve PROOF-OF-CONTROL multiple times with specifying alternating account addresses. These ATTESTATIONS will be handed to the central gas-payer, who will execute them in a permissionless way, paying gas-fees for each transactions. This effectively drains the funds from the gas-payer, making the system unusable as soon as the gas-payer can no longer pay for transactions.

**Why do you recommend hashing serial numbers over using them plain?**
Using any sequential identifier allows to at least conclude of the number between the lowest and highest ever used serial number. This therefore provides good indication over the total number of assets on the market. While a limited number of assets is often desirable for collectables, publishing exact production numbers of assets is undesirable for most industries, as it equals to publishing sales/revenue numbers per product group, which is often considered confidential. Within supply chains, serial numbers are often mandatory due to their range-based processing capability. The simplest approach to allow using physical serial numbers and still obfuscating the actual number of assets is through hashing/encryption of the serial number.

**Why is anchor-validation needed, why not simply trust the oracle to attest only valid anchors?**
The oracle testifies PROOF-OF-CONTROL. As the ORACLE has to know the merkle-tree of valid anchors, it could also modify the merkle-tree with malicious intent. Therefore, having an on-chain verification, whether the original merkle-tree has been used, is needed. Even if the oracle gets compromised, it should not have the power to introduce new anchors. This is achieved by requiring that the oracle knows the merkle-tree, but updateValidAnchors() can only be called by a maintainer. Note that the oracle must not be the maintainer. As a consequence, care shall be taken off-chain, in order to ensure that compromising one system-part not automatically compromises oracle and maintainer accounts. 

**Why do you use merkle-trees for anchor-validation?**
For security- and gas-reasons. Except for limited collections, anchors will typically be added over time, e.g. when a new batch of the asset is produced or issued. While it is already ineffective to store all available anchors on-chain gas-wise, publishing all anchors would also expose the total number of assets. When using the data from anchor-updates one could even deduce the production capabilities of that asset, which is usually considered confidential information. 

**Assume you have N anchors. If all anchored NFTs are minted, what use is a merkle-tree?**
If all anchored NFTs are minted this implies that all anchors have been published and could be gathered on-chain. Consequently, the merkle-tree can be reconstructed. While this may not be an issue for many use cases (all supported anchors are minted anyway), we still recommend to add one &quot;salt-leave&quot; to the merkle-tree, characterized in that the ORACLE will never issue an attestation for an ANCHOR matching that salt-leave. Therefore, even if all N anchors are 

### Security Considerations for PHYSICAL ASSETS

In case the ASSET is a physical object, good or property, the following ADDITIONAL specifications MUST be satisfied:

#### ORACLE for Physical Anchors

- Issuing an ATTESTATION requires that the ORACLE
  - MUST proof physical proximity between an input device (for example smartphone) specifying the `to` address and a particular physical ANCHOR and it&apos;s associated physical object. Typical acceptable proximity is ranges between some millimeters to several meters.
  - The physical presence MUST be verified beyond reasonable doubt, in particular the employed method
    - MUST be robust against duplication or reproduction attempts of the physical ANCHOR,
    - MUST be robust against spoofing (for example presentation attacks) etc.
  - MUST be implemented under the assumption that the party defining the `to` address has malicious intent and to acquire false ATTESTATION, without currently or ever having access to the physical object comprising the physical ANCHOR.

#### Physical ASSET

- MUST comprise an ANCHOR, acting as the unique physical object identifier, typically a serial number (plain (NOT RECOMMENDED) or hashed (RECOMMENDED))
- MUST comprise a physical security device, marking or any other feature that enables proofing physical presence for ATTESTATION through the ORACLE
- Is RECOMMENDED to employ ANCHOR-TECHNOLOGIES featuring irreproducible security features.
- In general it is NOT RECOMMENDED to employ ANCHOR-TECHNOLOGIES that can easily be replicated (for example barcodes, &quot;ordinary&quot; NFC chips, .. ). Replication includes physical and digital replication.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 29 Apr 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6956</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6956</guid>
      </item>
    
      <item>
        <title>Dual Layer Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6960-dual-layer-token/14070</comments>
        
        <description>## Abstract

The dual-layer token combines the functionalities of [ERC-20](/EIPs/EIPS/eip-20), [ERC-721](/EIPs/EIPS/eip-721), and [ERC-1155](/EIPs/EIPS/eip-1155) while adding a classification layer that uses `mainId` as the main asset type identifier and `subId` as the unique attributes or variations of the main asset.
![Dual Layer Token](/EIPs/assets/eip-6960/eip-6960-dual-layer-token-dlt.png)

The proposed token aims to offer more granularity in token management, facilitating a well-organized token ecosystem and simplifying the process of tracking tokens within a contract. This standard is particularly useful for tokenizing and enabling the fractional ownership of Real World Assets (RWAs). It also allows for efficient and flexible management of both fungible and non-fungible assets.

The following are examples of assets that the DLT standard can represent fractional ownership of:

- Invoices
- Company stocks
- Digital collectibles
- Real estate

## Motivation

The [ERC-1155](/EIPs/EIPS/eip-1155) standard has experienced considerable adoption within the Ethereum ecosystem; however, its design exhibits constraints when handling tokens with multiple classifications, particularly in relation to Real World Assets (RWAs) and fractionalization of assets.

This EIP strives to overcome this limitation by proposing a token standard incorporating a dual-layer classification system, allowing for enhanced organization and management of tokens, especially in situations where additional sub-categorization of token types is necessary.

## Specification

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

### DLT Interface

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity 0.8.17;

/**
 * @title DLT token standard interface
 * @dev Interface for any contract that wants to implement the DLT standard
 */
interface IDLT {

    /**
     * @dev MUST emit when `subId` token is transferred from `sender` to `recipient`
     * @param sender is the address of the previous holder whose balance is decreased
     * @param recipient is the address of the new holder whose balance is increased
     * @param mainId is the main token type ID to be transferred
     * @param subId is the token subtype ID to be transferred
     * @param amount is the amount to be transferred of the token subtype
     */
    event Transfer(
        address indexed sender,
        address indexed recipient,
        uint256 indexed mainId,
        uint256 subId,
        uint256 amount
    );

    /**
     * @dev MUST emit when `subIds` token array is transferred from `sender` to `recipient`
     * @param sender is the address of the previous holder whose balance is decreased
     * @param recipient is the address of the new holder whose balance is increased
     * @param mainIds is the main token type ID array to be transferred
     * @param subIds is the token subtype ID array to be transferred
     * @param amounts is the amount array to be transferred of the token subtype                
    */
    event TransferBatch(
        address indexed sender,
        address indexed recipient,
        uint256[] mainIds,
        uint256[] subIds,
        uint256[] amounts
    );

    /**
     * @dev MUST emit when `owner` enables `operator` to manage the `subId` token
     * @param owner is the address of the token owner
     * @param operator is the authorized address to manage the allocated amount for an owner address 
     * @param mainId is the main token type ID to be approved
     * @param subId is the token subtype ID to be approved
     * @param amount is the amount to be approved of the token subtype
     */
    event Approval(
        address indexed owner,
        address indexed operator,
        uint256 mainId,
        uint256 subId,
        uint256 amount
    );

    /**
     * @dev MUST emit when `owner` enables or disables (`approved`) `operator` to manage all of its assets
     * @param owner is the address of the token owner
     * @param operator is the authorized address to manage all tokens for an owner address
     * @param approved true if the operator is approved, false to revoke approval
     */
    event ApprovalForAll(
        address indexed owner,
        address indexed operator,
        bool approved
    );
    
    /**
     * @dev MUST emit when the URI is updated for a main token type ID.
     * URIs are defined in RFC 3986.
     * The URI MUST point to a JSON file that conforms to the &quot;DLT Metadata URI JSON Schema&quot;.
     * @param oldValue is the old URI value
     * @param newValue is the new URI value
     * @param mainId is the main token type ID
     */
    event URI(string oldValue, string newValue, uint256 indexed mainId);

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any subId owned by the caller.
     * The `operator` MUST NOT be the caller.
     * MUST emit an {ApprovalForAll} event.     
     * @param operator is the authorized address to manage all tokens for an owner address
     * @param approved true if the operator is approved, false to revoke approval
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller&apos;s
     * allowance.
     * MUST revert if `sender` or `recipient` is the zero address.
     * MUST revert if balance of holder for token `subId` is lower than the `amount` sent.
     * MUST emit a {Transfer} event.
     * @param sender is the address of the previous holder whose balance is decreased
     * @param recipient is the address of the new holder whose balance is increased
     * @param mainId is the main token type ID to be transferred
     * @param subId is the token subtype ID to be transferred
     * @param amount is the amount to be transferred of the token subtype
     * @param data is additional data with no specified format
     * @return True if the operation succeeded, false if operation failed
     */
    function safeTransferFrom(
        address sender,
        address recipient,
        uint256 mainId,
        uint256 subId,
        uint256 amount,
        bytes calldata data
    ) external returns (bool);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller&apos;s tokens.
     * The `operator` MUST NOT be the caller.
     * MUST revert if `operator` is the zero address.
     * MUST emit an {Approval} event.
     * @param operator is the authorized address to manage tokens for an owner address
     * @param mainId is the main token type ID to be approved
     * @param subId is the token subtype ID to be approved
     * @param amount is the amount to be approved of the token subtype
     * @return True if the operation succeeded, false if operation failed
     */
    function approve(
        address operator,
        uint256 mainId,
        uint256 subId,
        uint256 amount
    ) external returns (bool);

    /**
     * @notice Get the token with a particular subId balance of an `account`
     * @param account is the address of the token holder
     * @param mainId is the main token type ID
     * @param subId is the token subtype ID
     * @return The amount of tokens owned by `account` in subId
     */
    function subBalanceOf(
        address account,
        uint256 mainId,
        uint256 subId
    ) external view returns (uint256);

    /**
     * @notice Get the tokens with a particular subIds balance of an `accounts` array
     * @param accounts is the address array of the token holder
     * @param mainIds is the main token type ID array
     * @param subIds is the token subtype ID array
     * @return The amount of tokens owned by `accounts` in subIds
     */
    function balanceOfBatch(
        address[] calldata accounts,
        uint256[] calldata mainIds,
        uint256[] calldata subIds
    ) external view returns (uint256[] calldata);

    /** 
     * @notice Get the allowance allocated to an `operator`
     * @dev This value changes when {approve} or {transferFrom} are called
     * @param owner is the address of the token owner
     * @param operator is the authorized address to manage assets for an owner address
     * @param mainId is the main token type ID
     * @param subId is the token subtype ID
     * @return The remaining number of tokens that `operator` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     */
    function allowance(
        address owner,
        address operator,
        uint256 mainId,
        uint256 subId
    ) external view returns (uint256);

    /**
     * @notice Get the approval status of an `operator` to manage assets
     * @param owner is the address of the token owner
     * @param operator is the authorized address to manage assets for an owner address
     * @return True if the `operator` is allowed to manage all of the assets of `owner`, false if approval is revoked
     * See {setApprovalForAll}
     */
    function isApprovedForAll(
        address owner,
        address operator
    ) external view returns (bool);
}
```

### `DLTReceiver` Interface

Smart contracts MUST implement all the functions in the `DLTReceiver` interface to accept transfers.

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity 0.8.17;

/**
 * @title DLT token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from DLT asset contracts.
 */
interface IDLTReceiver {
    /**
     * @notice Handle the receipt of a single DLT token type.
     * @dev Whenever an {DLT} `subId` token is transferred to this contract via {IDLT-safeTransferFrom}
     * by `operator` from `sender`, this function is called.
     * MUST return its Solidity selector to confirm the token transfer.
     * MUST revert if any other value is returned or the interface is not implemented by the recipient.
     * The selector can be obtained in Solidity with `IDLTReceiver.onDLTReceived.selector`.
     * @param operator is the address which initiated the transfer
     * @param from is the address which previously owned the token
     * @param mainId is the main token type ID being transferred
     * @param subId subId is the token subtype ID being transferred
     * @param amount is the amount of tokens being transferred
     * @param data is additional data with no specified format
     * @return `IDLTReceiver.onDLTReceived.selector`
     */
    function onDLTReceived(
        address operator,
        address from,
        uint256 mainId,
        uint256 subId,
        uint256 amount,
        bytes calldata data
    ) external returns (bytes4);

    /**
     * @notice Handle the receipts of a DLT token type array.
     * @dev Whenever an {DLT} `subIds` token is transferred to this contract via {IDLT-safeTransferFrom}
     * by `operator` from `sender`, this function is called.
     * MUST return its Solidity selector to confirm the token transfers.
     * MUST revert if any other value is returned or the interface is not implemented by the recipient.
     * The selector can be obtained in Solidity with `IDLTReceiver.onDLTReceived.selector`.
     * @param operator is the address which initiated the transfer
     * @param from is the address which previously owned the token
     * @param mainIds is the main token type ID being transferred
     * @param subIds subId is the token subtype ID being transferred
     * @param amounts is the amount of tokens being transferred
     * @param data is additional data with no specified format
     * @return `IDLTReceiver.onDLTReceived.selector`
     */
    function onDLTBatchReceived(
        address operator,
        address from,
        uint256[] calldata mainIds,
        uint256[] calldata subIds,
        uint256[] calldata amounts,
        bytes calldata data
    ) external returns (bytes4);
}
```

## Rationale

The two-level classification system introduced in this EIP allows for a more organized token ecosystem, enabling users to manage and track tokens with greater granularity. It is particularly useful for projects that require token classifications beyond the capabilities of the current ERC-1155 standard.

As assets can have various properties or variations, our smart contract design reflects this by assigning a mainId to each asset category and a unique subId to each derivative or sub-category. This approach expands the capabilities of ERC-1155 to support a broader range of assets with complex requirements. Additionally, it enables tracking of mainBalance for the main asset and subBalance for its sub-assets individual accounts.

The contract can be extended to support the use of subIds in two ways:

- Shared SubIds: where all mainIds share the same set of subIds.
- Mixed SubIds: where mainIds have unique sets of subIds.

DLT provides a more versatile solution compared to other token standards such as ERC-20, ERC-721, and ERC-1155 by effectively managing both fungible and non-fungible assets within the same contract.

The following are questions that we considered during the design process:

- How to name the proposal?
The standard introduces a two-level classification to tokens where one main asset (layer 1) can be further sub-divided into several sub-assets (layer 2) hence we decided to name it as &quot;Dual-layer&quot; token to reflect the hierarchical structure of the token classification.
- Should we limit the classification to two levels?
The standard’s implementation maintains a mapping to track the total supply of each sub-asset. If we allow sub-assets to have their own children, it would be necessary to introduce additional methods to track each sub-asset, which would be impractical and increases the complexity of the contract.
- Should we extend the ERC-1155 standard?
As the ERC-1155 standard is not designed to support a layered classification and requires significant modifications to do so, we concluded that it would not be appropriate to extend it for the dual-layer token standard. Hence, a standalone implementation would be a more suitable approach.

## Backwards Compatibility

No backward compatibility issues found.

## Test Cases

The test suite covers:

- Minting tokens with specific `mainId` and `subId` combinations and verifying `subBalanceOf` reflects correct amounts
- Batch balance queries via `balanceOfBatch` with array parity validation
- `safeTransferFrom` between EOAs with balance and allowance checks
- `safeTransferFrom` to contract recipients implementing `IDLTReceiver`, verifying `onDLTReceived` callback
- Rejection of transfers to non-receiver contracts and to revertable receiver contracts
- Approval flows: `approve` for specific `(mainId, subId)` pairs and `setApprovalForAll` for operator-level access
- Allowance spending and the `type(uint256).max` infinite approval pattern
- Batch transfers via `safeBatchTransferFrom` with array length validation
- Burning tokens and verifying supply reduction
- Zero address validation on mints, transfers, and approvals

## Reference Implementation

A reference implementation is provided in [DLT.sol](/EIPs/assets/eip-6960/DLT.sol).

The implementation includes:

- `DLT.sol`: Core token contract implementing the `IDLT` interface with dual-layer balance tracking, approval management, safe transfers with receiver callbacks, and batch operations.
- `IDLT.sol`: The interface as specified above.
- `IDLTReceiver.sol`: Receiver interface for safe transfer callbacks.

The reference implementation uses a nested mapping `mapping(uint256 mainId =&gt; mapping(address =&gt; mapping(uint256 subId =&gt; uint256)))` for balance storage, enabling O(1) lookups for any `(account, mainId, subId)` tuple. Allowances follow the same pattern with an additional spender dimension.

## Security Considerations

### Allowance Race Condition

The dual-layer allowance system inherits the same approve/transferFrom race condition present in [ERC-20](/EIPs/EIPS/eip-20). If an owner changes an allowance from N to M, the spender may be able to spend both N and M. Implementers SHOULD provide `increaseAllowance` and `decreaseAllowance` helper functions or use the check-set pattern where the owner first sets allowance to zero before setting the new value.

### Receiver Callback Reentrancy

The `safeTransferFrom` function calls `onDLTReceived` on the recipient contract after updating balances. This follows the checks-effects-interactions pattern, but implementers extending the base contract SHOULD be aware that the recipient callback executes with updated state. Contracts that override `_beforeTokenTransfer` or `_afterTokenTransfer` hooks must not introduce external calls that could create reentrancy paths.

### Batch Operation Gas Limits

`safeBatchTransferFrom` and `balanceOfBatch` iterate over unbounded arrays. Callers MUST ensure the array lengths do not exceed block gas limits. Implementations MAY impose an upper bound on array length to prevent out-of-gas failures in on-chain contexts.

### Integer Overflow in Balance Aggregation

While individual `subBalance` values are tracked per `(mainId, subId)` pair, any aggregation of balances across sub-IDs (e.g., computing a total `mainBalance`) must account for potential overflow when summing multiple `uint256` values. The reference implementation tracks main balances separately to avoid this.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 30 Apr 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6960</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6960</guid>
      </item>
    
      <item>
        <title>Multi Injected Provider Discovery</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6963-multi-injected-provider-interface-aka-mipi/14076</comments>
        
        <description>## Abstract

An alternative discovery mechanism to `window.ethereum` for [EIP-1193](/EIPs/EIPS/eip-1193) providers which supports discovering multiple injected Wallet Providers in a web page using Javascript&apos;s `window` events.

## Motivation

Currently, Wallet Provider that offer browser extensions must inject their Ethereum providers ([EIP-1193](/EIPs/EIPS/eip-1193)) into the same window object `window.ethereum`; however, this creates conflicts for users that may install more than one browser extension.

Browser extensions are loaded in the web page in an unpredictable and unstable order, resulting in a race condition where the user does not have control over which Wallet Provider is selected to expose the Ethereum interface under the `window.ethereum` object. Instead, the last wallet to load usually wins.

This results not only in a degraded user experience but also increases the barrier to entry for new browser extensions as users are forced to only install one browser extension at a time.

Some browser extensions attempt to counteract this problem by delaying their injection to overwrite the same `window.ethereum` object which creates an unfair competition for Wallet Providers and lack of interoperability.

In this proposal, we present a solution that focuses on optimizing the interoperability of multiple Wallet Providers. This solution aims to foster fairer competition by reducing the barriers to entry for new Wallet Providers, along with enhancing the user experience on Ethereum networks.

This is achieved by introducing a set of window events to provide a two-way communication protocol between Ethereum libraries and injected scripts provided by browser extensions thus enabling users to select their wallet of choice.

## Specification

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].

### Definitions

Wallet Provider: A user agent that manages keys and facilitates transactions with Ethereum.

Decentralized Application (DApp): A web page that relies upon one or many Web3 platform APIs which are exposed to the web page via the Wallet.

Provider Discovery Library: A library or piece of software that assists a DApp to interact with the Wallet. 

### Provider Info

Each Wallet Provider will be announced with the following interface `EIP6963ProviderInfo`. The values in the `EIP6963ProviderInfo` MUST be included within the `EIP6963ProviderInfo` object. The `EIP6963ProviderInfo` MAY also include extra extensible properties within the object. If a DApp does not recognize the additional properties, it SHOULD ignore them.

- **`uuid`** - a globally unique identifier the Wallet Provider that MUST be ([UUIDv4][RFC-4122] compliant) to uniquely distinguish different [EIP-1193](/EIPs/EIPS/eip-1193) provider sessions that have matching properties defined below during the lifetime of the page. The cryptographic uniqueness provided by [UUIDv4][RFC-4122] guarantees that two independent `EIP6963ProviderInfo` objects can be separately identified.
- **`name`** - a human-readable local alias of the Wallet Provider to be displayed to the user on the DApp. (e.g. `Example Wallet Extension` or `Awesome Example Wallet`)
- **`icon`** - a [URI][RFC-3986] pointing to an image. The image SHOULD be a square with 96x96px minimum resolution. See the [Images/Icons](#imagesicons) below for further requirements of this property.
- **`rdns`** - The Wallet MUST supply the `rdns` property which is intended to be a domain name from the Domain Name System in reverse syntax ordering such as `com.example.subdomain`. It&apos;s up to the Wallet to determine the domain name they wish to use, but it&apos;s generally expected the identifier will remain the same throughout the development of the Wallet. It&apos;s also worth noting that similar to a user agent string in browsers, there are times where the supplied value could be unknown, invalid, incorrect, or attempt to imitate a different Wallet. Therefore, the DApp SHOULD be able to handle these failure cases with minimal degradation to the functionality of the DApp.

```typescript
/**
 * Represents the assets needed to display a wallet
 */
interface EIP6963ProviderInfo {
  uuid: string;
  name: string;
  icon: string;
  rdns: string;
}
```

#### Images/Icons

A URI-encoded image was chosen to enable flexibility for multiple protocols for fetching and rendering icons, for example:

```sh
# svg (data uri)
data:image/svg+xml,&lt;svg version=&quot;1.1&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;32px&quot; height=&quot;32px&quot; viewBox=&quot;0 0 32 32&quot;&gt;&lt;circle fill=&quot;red&quot; cx=&quot;16&quot; cy=&quot;16&quot; r=&quot;12&quot;/&gt;&lt;/svg&gt;
# png (data uri)
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==
```

The `icon` string MUST be a data URI as defined in [RFC-2397]. The image SHOULD be a square with 96x96px minimum resolution. The image format is RECOMMENDED to be either lossless or vector based such as PNG, WebP or SVG to make the image easy to render on the DApp. Since SVG images can execute Javascript, applications and libraries MUST render SVG images using the `&lt;img&gt;` tag to ensure no untrusted Javascript execution can occur.

#### RDNS

The **`rdns`** (Reverse-DNS) property serves to provide an identifier which DApps can rely on to be stable between sessions. The Reverse Domain Name Notation is chosen to prevent namespace collisions.
The Reverse-DNS convention implies that the value should start with a reversed DNS domain name controlled by the Provider. The domain name should be followed by a subdomain or a product name. Example: `com.example.MyBrowserWallet`.

- The `rdns` value MUST BE a valid [RFC-1034] Domain Name;
- The DNS part of the `rdns` value SHOULD BE an active domain controlled by the Provider;
- DApps MAY reject the Providers which do not follow the Reverse-DNS convention correctly;
- DApps SHOULD NOT use the `rdns` value for feature detection as these are self-attested and prone to impersonation or bad incentives without an additional verification mechanism; feature-discovery and verification are both out of scope of this interface specification.

### Provider Detail

The `EIP6963ProviderDetail` is used as a composition interface to announce a Wallet Provider and related metadata about the Wallet Provider. The `EIP6963ProviderDetail` MUST contain an `info` property of type `EIP6963ProviderInfo` and a `provider` property of type `EIP1193Provider` defined by [EIP-1193](/EIPs/EIPS/eip-1193).

```typescript
interface EIP6963ProviderDetail {
  info: EIP6963ProviderInfo;
  provider: EIP1193Provider;
}
```

### Window Events

In order to prevent provider collisions, the DApp and the Wallet are expected to emit an event and instantiate an eventListener to discover the various Wallets. This forms an Event concurrency loop. 

Since the DApp code and Wallet code aren&apos;t guaranteed to run in a particular order, the events are designed to handle such race conditions.

To emit events, both DApps and Wallets MUST use the `window.dispatchEvent` function to emit events and MUST use the `window.addEventListener` function to observe events. There are two Event interfaces used for the DApp and Wallet to discover each other.

#### Announce and Request Events

The `EIP6963AnnounceProviderEvent` interface MUST be a `CustomEvent` object with a `type` property containing a string value of `eip6963:announceProvider` and a `detail` property with an object value of type `EIP6963ProviderDetail`. The `EIP6963ProviderDetail` object SHOULD be frozen by calling `Object.freeze()` on the value of the `detail` property.

```typescript
// Announce Event dispatched by a Wallet
interface EIP6963AnnounceProviderEvent extends CustomEvent {
  type: &quot;eip6963:announceProvider&quot;;
  detail: EIP6963ProviderDetail;
}
```

The `EIP6963RequestProviderEvent` interface MUST be an `Event` object with a `type` property containing a string value of `eip6963:requestProvider`.

```typescript
// Request Event dispatched by a DApp
interface EIP6963RequestProviderEvent extends Event {
  type: &quot;eip6963:requestProvider&quot;;
}
```

The Wallet MUST announce the `EIP6963AnnounceProviderEvent` to the DApp via a `window.dispatchEvent()` function call. The Wallet MUST add an EventListener to catch an `EIP6963RequestProviderEvent` dispatched from the DApp. This EventListener MUST use a handler that will re-dispatch an `EIP6963AnnounceProviderEvent`. This re-announcement by the Wallet is useful for when a Wallet&apos;s initial Event announcement may have been delayed or fired before the DApp had initialized its EventListener. This allows the various Wallet Providers to react to the DApp without the need to pollute the `window.ethereum` namespace which can produce non-deterministic wallet behavior such as different wallets connecting each time.

The Wallet dispatches the `&quot;eip6963:announceProvider&quot;` event with immutable contents and listens to the `&quot;eip6963:requestProvider&quot;` event:

```typescript
let info: EIP6963ProviderInfo;
let provider: EIP1193Provider;

const announceEvent: EIP6963AnnounceProviderEvent = new CustomEvent(
  &quot;eip6963:announceProvider&quot;,
  { detail: Object.freeze({ info, provider }) }
);

// The Wallet dispatches an announce event which is heard by
// the DApp code that had run earlier
window.dispatchEvent(announceEvent);

// The Wallet listens to the request events which may be
// dispatched later and re-dispatches the `EIP6963AnnounceProviderEvent`
window.addEventListener(&quot;eip6963:requestProvider&quot;, () =&gt; {
  window.dispatchEvent(announceEvent);
});
```

The DApp MUST listen for the `EIP6963AnnounceProviderEvent` dispatched by the Wallet via a `window.addEventListener()` method and MUST NOT remove the Event Listener for the lifetime of the page so that the DApp can continue to handle Events beyond the initial page load interaction. The DApp MUST dispatch the `EIP6963RequestProviderEvent` via a `window.dispatchEvent()` function call after the `EIP6963AnnounceProviderEvent` handler has been initialized.

```typescript
// The DApp listens to announced providers
window.addEventListener(
  &quot;eip6963:announceProvider&quot;,
  (event: EIP6963AnnounceProviderEvent) =&gt; {}
);

// The DApp dispatches a request event which will be heard by 
// Wallets&apos; code that had run earlier
window.dispatchEvent(new Event(&quot;eip6963:requestProvider&quot;));
```

The DApp MAY elect to persist various `EIP6963ProviderDetail` objects contained in the  announcement events sent by multiple wallets. Thus, if the user wishes to utilize a different Wallet over time, the user can express this within the DApp&apos;s interface and the DApp can immediately elect to send transactions to that new Wallet. Otherwise, the DApp MAY re-initiate the wallet discovery flow via dispatching a new `EIP6963RequestProviderEvent`, potentially discovering a different set of wallets.

The described orchestration of events guarantees that the DApp is able to discover the Wallet, regardless of which code executes first, the Wallet code or the DApp code.

## Rationale

The previous proposal introduced mechanisms that relied on a single, mutable window object that could be overwritten by multiple parties. We opted for an event-based approach to avoid the race conditions, the namespace collisions, and the potential for &quot;pollution&quot; attacks on a shared mutable object; the event-based orchestration creates a bidirectional communication channel between wallet and dapp that can be re-orchestrated over time.

To follow the Javascript event name conventions, the names are written in present tense and are prefixed with the number of this document (`EIP6963`). 

### Interfaces

Standardizing an interface for provider information (`EIP6963ProviderInfo`) allows a DApp to determine all information necessary to populate a user-friendly wallet selection modal. This is particularly useful for DApps that rely on libraries such as Web3Modal, RainbowKit, Web3-Onboard, or ConnectKit to programmatically generate such selection modals.

Regarding the announced provider interface (`EIP6963ProviderDetail`), it was important to leave the [EIP-1193](/EIPs/EIPS/eip-1193) provider interface untouched for backwards compatibility; this allows conformant DApps to interface with wallets conforming to either, and for Wallets conformant to this spec to still inject [EIP-1193](/EIPs/EIPS/eip-1193) providers for legacy DApps. Note that a legacy dapp or a DApp conformant with this spec connecting to a legacy wallet cannot guarantee the correct wallet will be selected if multiple are present.

## Backwards Compatibility

This EIP doesn&apos;t require supplanting `window.ethereum`, so it doesn&apos;t directly break existing applications that cannot update to this method of Wallet discovery. However, it is RECOMMENDED DApps implement this EIP to ensure discovery of multiple Wallet Providers and SHOULD disable `window.ethereum` usage except as a fail-over when discovery fails. Similarly, Wallets SHOULD keep compatibility of `window.ethereum` to ensure backwards compatibility for DApps that have not implemented this EIP. In order to prevent the previous issues of namespace collisions, it&apos;s also RECOMMENDED that wallets inject their provider object under a wallet specific namespace then proxy the object into the `window.ethereum` namespace.

## Reference Implementation

### Wallet Provider

Here is a reference implementation for an injected script by a Wallet Provider to support this new interface in parallel with the existing pattern.

```typescript
function onPageLoad() {
  let provider: EIP1193Provider;

  window.ethereum = provider;

  function announceProvider() {
    const info: EIP6963ProviderInfo = {
      uuid: &quot;350670db-19fa-4704-a166-e52e178b59d2&quot;,
      name: &quot;Example Wallet&quot;,
      icon: &quot;data:image/svg+xml,&lt;svg xmlns=&apos;http://www.w3.org/2000/svg&apos;/&gt;&quot;,
      rdns: &quot;com.example.wallet&quot;
};
    window.dispatchEvent(
      new CustomEvent(&quot;eip6963:announceProvider&quot;, {
        detail: Object.freeze({ info, provider }),
      })
    );
  }

  window.addEventListener(
    &quot;eip6963:requestProvider&quot;,
    (event: EIP6963RequestProviderEvent) =&gt; {
      announceProvider();
    }
  );

  announceProvider();
}
```

### DApp implementation

Here is a reference implementation for a DApp to display and track multiple Wallet Providers that are injected by browser extensions. 

```typescript
const providers: EIP6963ProviderDetail[];

function onPageLoad() {

  window.addEventListener(
    &quot;eip6963:announceProvider&quot;,
    (event: EIP6963AnnounceProviderEvent) =&gt; {
      providers.push(event.detail);
    }
  );

  window.dispatchEvent(new Event(&quot;eip6963:requestProvider&quot;));
}
```

## Security Considerations

### EIP-1193 Security considerations

The security considerations of [EIP-1193](/EIPs/EIPS/eip-1193) apply to this EIP. Implementers are expected to consider and follow the guidance of the providers they&apos;re utilizing as well.

### Prototype Pollution of Wallet Provider objects

Browser extensions, and therefore Wallet extensions, are able to modify the contents of the page and the Provider object by design. The provider objects of various Wallets are considered a highly trusted interface to communicate transaction data. In order to prevent the page or various other extensions from modifying the interaction between the DApp and the Wallet in an unexpected way, the best practice is to &quot;freeze&quot; the provider discovery object by utilizing `object.freeze()` on the  `EIP1193Provider` object before the wallet dispatches it in the `eip6963:announceProvider` Event. However, there are difficulties that can occur around web compatibility where pages need to monkey patch the object. In scenarios like this there&apos;s a tradeoff that needs to be made between security and web compatibility that Wallet implementers are expected to consider.

### Wallet Imitation and Manipulation

Similarly so, DApps are expected to actively detect for misbehavior of properties or functions being modified in order to tamper with or modify other wallets. One way this can be easily achieved is to look for when the `uuid` property within two `EIP6963ProviderInfo` objects match. DApps and DApp discovery libraries are expected to consider other potential methods that the `EIP6963ProviderInfo` objects are being tampered with and consider additional mitigation techniques to prevent this as well in order to protect the user.

### Prevent SVG Javascript Execution 

The use of SVG images introduces a cross-site scripting risk as they can include JavaScript code. This Javascript executes within the context of the page and can therefore modify the page or the contents of the page. So when considering the experience of rendering the icons, DApps need to take into consideration how they&apos;ll approach handling these concerns in order to prevent an image being used as an obfuscation technique to hide malicious modifications to the page or to other wallets.

### Prevent Wallet Fingerprinting

One advantage to the concurrency Event loop utilized by this design is that it operates in a manner where either the DApp or the Wallet can initiate the flow to announce a provider. For this reason, Wallet implementers can now consider whether or not they wish to announce themselves to all pages or attempt alternative means in order to reduce the ability for a user to be fingerprinted by the injection of the `window.ethereum` object. Some examples, of alternative flows to consider would be to wait to inject the provider object until the DApp has announced the `eip6963:requestProvider`. At that point, the wallet can initiate a UI consent flow to ask the user if they would like to share their wallet address. This allows for the Wallet to enable the option of a &quot;private connect&quot; feature. However, if this approach is taken, Wallets must also consider how they intend to support backwards compatibility with a DApp that does not support this EIP.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).


[RFC-1034]: https://www.rfc-editor.org/rfc/rfc1034
[RFC-2119]: https://www.rfc-editor.org/rfc/rfc2119
[RFC-2397]: https://www.rfc-editor.org/rfc/rfc2397
[RFC-3986]: https://www.rfc-editor.org/rfc/rfc3986
[RFC-4122]: https://www.rfc-editor.org/rfc/rfc4122
</description>
        <pubDate>Mon, 01 May 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6963</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6963</guid>
      </item>
    
      <item>
        <title>Contract Secured Revenue on an EVM based L2</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6968-generalized-csr-protocol/14178</comments>
        
        <description>## Abstract 
 
Contract Secured Revenue (CSR) allows smart contract developers to claim a percentage of all transaction fees paid by users when interacting with their smart contracts.

This EIP proposes the introduction of CSR on EVM-based L2s which would provide smart contract developers who deploy on L2s access to revenue streams and/or public goods.

## Motivation 
 
Using protocol rewards of an L1 to fund smart contract development would be a big change to the way the current market works.  This EIP *does not* advocate for any changes to the existing Ethereum L1.

This EIP does advocate that L2s could begin to experiment with Contract Secured Revenue as a means of:
 
1. creating a new revenue stream for smart contract developers
2. creating a new way of funding public goods
3. creating incentives for developers to deploy their dapps on your network
 
## Specification  

### Parameters 
 
| Constant | Value  |
|---|---|
| REVENUE_SHARE_QUOTIENT | 5 |

### Fee Mechanism 
 
The current [EIP-1559](/EIPs/EIPS/eip-1559) fee behavior is modified so that `header.base_fee_per_gas * REVENUE_SHARE_QUOTIENT` per gas is reallocated proportionally, based on gas used, to each contract executed during the transaction.

Implicitly, this means that no fees are redistributed to externally owned accounts (EOA).

#### Gas Tracking 
 
In order to fairly distribute the fee revenue, a new transaction-wide gas tracker is defined.

When executing a block, maintain a mapping `gas_used_by_address` of `address` to `uint64`. This will track the amount of gas used by each address. For every EVM instruction that does not instantiate a new execution frame (e.g. `CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL`, `CREATE`, and `CREATE2`), add the cost of the instruction to the address&apos; current sum in the mapping.

For EVM instructions which do instantiate new frames, greater care must be taken to determine the cost of the instruction to the calling frame. For simplicity, this cost is defined to be the total cost of the operation minus the amount of gas passed to the child frame. The gas passed to the child frame is determined via [EIP-150](/EIPs/EIPS/eip-150). The computed cost is added to the address&apos; current sum in the mapping.

Additionally:

- If the address does not exist in the mapping, it&apos;s total gas used is `0`.
- If the instructions throws an out-of-gas (OOG) error, all remaining gas allocated to execution frame is added to the current total gas used by the address.
- No other exceptional halt adds remaining gas to the counter for the address where the halt occurred.

#### Setting Revenue Recipient 
 
Revenue recipients are tracked via a new transaction wide mapping `revenue_recipient` of `address` to `address`. The default value for every key is the key itself. For example, unless set otherwise, the key `0xdead...beef` maps to the value `0xdead...beef`.

To set a different revenue recipient, a new instruction `SETREVENUERECIPIENT` is introduced with the opcode `0x49`. The operation takes `1` stack element as input and outputs `0` stack elements. 

The `20` least significant bytes of the input stack element is the address of the new revenue recipient for the instruction&apos;s caller. The `revenue_recipient` entry is updated to reflect this.

The instruction costs `3` gas.

#### Dispersing Revenue 
 
After a transaction completes, for every element (`addr`, `gas_used`) in `gas_used_by_address`, increase the balance of `revenue_recipient[addr]` by `gas_used * (header.base_fee_per_gas // REVENUE_SHARE_QUOTIENT)`

## Rationale 
 
### Tracking Gas Proportionally 
 
A simpler mechanism would be to send the full transaction revenue to the `to` value of the transaction. This, however, does not accurately reward the composition of many different smart contracts and applications. Additionally, it is not compatible with smart contract wallets which, by definition, are often the first destination of a transaction.

Maintaining a transaction wide tracker of gas uses makes it possible to distribute revenue to contracts which are genuinely the most utilized.

### Ephemeral Revenue Recipient Mapping 
 
Constructing the revenue recipient mapping ephemerally during each transaction appears inefficient on the surface. This value is expected to be relatively static and even if it did need to change, the change could be facilitated by the recipient contract.

Unfortunately such a change is much more invasive for the EVM. The recipient value would need to be stored somewhere. This would require a modification to the account structure in the state trie. Also, the recipient value would need to be set at some point. This would necessitate either a modification to the `CREATE*` opcodes or a new opcode, similar to `SETREVENUERECIPIENT`, that would be called by initcode to &quot;initialize&quot; the recipient value.

## Security Considerations 
 
### Increased Max Block Size/Complexity 
 
Similar to EIP-1559, we must consider the effects this will have on block size. Depending on the method by which this is implemented, it could increase maximum block size in the event that a significant number of contracts opt-in to CSR. 


## Copyright 

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 01 May 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6968</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6968</guid>
      </item>
    
      <item>
        <title>Reserved Ownership Accounts</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-6981-reserved-ownership-accounts/14118</comments>
        
        <description>## Abstract

The following specifies a system for services to link their users to a claimable Ethereum address. Services can provide a signed message and unique salt to their users which can be used to deploy a smart contract wallet to the deterministic address through a registry contract using the `create2` opcode.

## Motivation

It is common for web services to allow their users to hold on-chain assets via custodial wallets. These wallets are typically EOAs, deployed smart contract wallets or omnibus contracts, with private keys or asset ownership information stored on a traditional database. This proposal outlines a solution that avoids the security concerns associated with historical approaches, and rids the need and implications of services controlling user assets

Users on external services that choose to leverage the following specification can be given an Ethereum address to receive assets without the need to do any on-chain transaction. These users can choose to attain control of said addresses at a future point in time. Thus, on-chain assets can be sent to and owned by a user beforehand, therefore enabling the formation of an on-chain identity without requiring the user to interact with the underlying blockchain.

## Specification

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

### Overview

The system for creating reserved ownership accounts consists of:

1. An Account Registry which provides deterministic addresses based on the service users&apos; identifying salts, and implements a signature verified function that enables claiming of Account Instances by the service&apos;s end users.
2. Account Instances created through the Account Registry by end users which allow access to the assets received at the deterministic address prior to Account Instance deployment.

External services wishing to provide their users with reserved ownership accounts MUST maintain a relationship between a user&apos;s identifying credentials and a salt. The external service SHALL refer to an Account Registry Instance to retrieve the deterministic account address for a given salt. Users of a given service MUST be able to create an Account Instance by validating their identifying credentials via the external service, which SHOULD give the user a signed message for their salt. Signatures SHOULD be generated by the external service using an signing address known to the Account Registry Instance. Users SHALL pass this message and signature to the service&apos;s Account Registry Instance in a call to `claimAccount` to deploy and claim an Account Instance at the deterministic address.

### Account Registry

The Account Registry MUST implement the following interface:

```solidity
interface IAccountRegistry {
    /**
     * @dev Registry instances emit the AccountCreated event upon successful account creation
     */
    event AccountCreated(address account, address accountImplementation, uint256 salt);

    /**
     * @dev Registry instances emit the AccountClaimed event upon successful claim of account by owner
     */
    event AccountClaimed(address account, address owner);

    /**
     * @dev Creates a smart contract account.
     *
     * If account has already been created, returns the account address without calling create2.
     *
     * @param salt       - The identifying salt for which the user wishes to deploy an Account Instance
     *
     * Emits AccountCreated event
     * @return the address for which the Account Instance was created
     */
    function createAccount(uint256 salt) external returns (address);

    /**
     * @dev Allows an owner to claim a smart contract account created by this registry.
     *
     * If the account has not already been created, the account will be created first using `createAccount`
     *
     * @param owner      - The initial owner of the new Account Instance
     * @param salt       - The identifying salt for which the user wishes to deploy an Account Instance
     * @param expiration - If expiration &gt; 0, represents expiration time for the signature.  Otherwise
     *                     signature does not expire.
     * @param message    - The keccak256 message which validates the owner, salt, expiration
     * @param signature  - The signature which validates the owner, salt, expiration
     *
     * Emits AccountClaimed event
     * @return the address of the claimed Account Instance
     */
    function claimAccount(
        address owner,
        uint256 salt,
        uint256 expiration,
        bytes32 message,
        bytes calldata signature
    ) external returns (address);

    /**
     * @dev Returns the computed address of a smart contract account for a given identifying salt
     *
     * @return the computed address of the account
     */
    function account(uint256 salt) external view returns (address);

    /**
     * @dev Fallback signature verification for unclaimed accounts
     */
    function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4);
}
```

#### createAccount

`createAccount` is used to deploy the Account Instance for a given salt.

- This function MUST deploy a new Account Instance as a [ERC-1167](/EIPs/EIPS/eip-1167) proxy pointing to the account implementation.
- This function SHOULD set the initial owner of the Account Instance to the Account Registry Instance.
- The account implementation address MUST be immutable, as it is used to compute the deterministic address for the Account Instance.
- Upon successful deployment of the Account Instance, the registry SHOULD emit an `AccountCreated` event.

#### claimAccount

`claimAccount` is used to claim ownership of the Account Instance for a given salt.

- This function MUST create a new Account Instance if one does not already exist for the given salt.
- This function SHOULD verify that the msg.sender has permission to claim ownership over the Account Instance for the identifying salt and initial owner. Verification SHOULD be done by validating the message and signature against the owner, salt and expiration using ECDSA for EOA signers, or [ERC-1271](/EIPs/EIPS/eip-1271) for smart contract signers.
- This function SHOULD verify that the block.timestamp &lt; expiration or that expiration == 0.
- Upon successful signature verification on calls to `claimAccount`, the registry MUST completely relinquish control over the Account Instance, and assign ownership to the initial owner by calling `setOwner` on the Account Instance.
- Upon successful claim of the Account Instance, the registry SHOULD emit an `AccountClaimed` event.

#### isValidSignature

`isValidSignature` is a fallback signature verification function used by unclaimed accounts. Valid signatures SHALL be generated by the registry signer by signing a composite hash of the original message hash, and the Account Instance address (e.g. `bytes32 compositeHash = keccak256(abi.encodePacked(originalHash, accountAddress))`). The function MUST reconstruct the composite hash, where `originalHash` is the hash passed to the function, and `accountAddress` is `msg.sender` (the unclaimed Account Instance). The function MUST verify the signature against the composite hash and registry signer.

### Account Instance

The Account Instance MUST implement the following interface:

```solidity
interface IAccount is IERC1271 {
    /**
     * @dev Sets the owner of the Account Instance.
     *
     * Only callable by the current owner of the instance, or by the registry if the Account
     * Instance has not yet been claimed.
     *
     * @param owner      - The new owner of the Account Instance
     */
    function setOwner(address owner) external;
}
```

- All Account Instances MUST be created using an Account Registry Instance.
- Account Instances SHOULD provide access to assets previously sent to the address at which the Account Instance is deployed to.
- `setOwner` SHOULD update the owner and SHOULD be callable by the current owner of the Account Instance.
- If an Account Instance is deployed, but not claimed, the owner of the Account Instance MUST be initialized to the Account Registry Instance.
- An Account Instance SHALL determine if it has been claimed by checking if the owner is the Account Registry Instance.

#### Account Instance Signatures

Account Instances MUST support [ERC-1271](/EIPs/EIPS/eip-1271) by implementing an `isValidSignature` function. When the owner of an Account Instance wants to sign a message (e.g. to log in to a dApp), the signature MUST be generated in one of the following ways, depending the state of the Account Instance:

1. If the Account instance is deployed and claimed, the owner should generate the signature, and `isValidSignature` SHOULD verify that the message hash and signature are valid for the current owner of the Account Instance.
2. If the Account Instance is deployed, but unclaimed, the registry signer should generate the signature using a composite hash of the original message and address of the Account Instance described [above](#isvalidsignature), and `isValidSignature` SHOULD forward the message hash and signature to the Account Registry Instance&apos;s `isValidSignature` function.
3. If the Account Instance is not deployed, the registry signer should generate a signature on the composite hash as done in situation 2, and wrap the signature according to [ERC-6492](/EIPs/EIPS/eip-6492#signer-side) (e.g. `concat(abi.encode((registryAddress, createAccountCalldata, compositeHashSignature), (address, bytes, bytes)), magicBytes)`).

Signature validation for Account Instances should be done according to [ERC-6492](/EIPs/EIPS/eip-6492#verifier-side).

## Rationale

### Service-Owned Registry Instances

While it might seem more user-friendly to implement and deploy a universal registry for reserved ownership accounts, we believe that it is important for external service providers to have the option to own and control their own Account Registry.  This provides the flexibility of implementing their own permission controls and account deployment authorization frameworks.

We are providing a reference Registry Factory which can deploy Account Registries for an external service, which comes with:

- Immutable Account Instance implementation
- Validation for the `claimAccount` method via ECDSA for EOA signers, or [ERC-1271](/EIPs/EIPS/eip-1271) validation for smart contract signers
- Ability for the Account Registry deployer to change the signing addressed used for `claimAccount` validation

### Account Registry and Account Implementation Coupling

Since Account Instances are deployed as [ERC-1167](/EIPs/EIPS/eip-1167) proxies, the account implementation address affects the addresses of accounts deployed from a given Account Registry. Requiring that registry instances be linked to a single, immutable account implementation ensures consistency between a user&apos;s salt and linked address on a given Account Registry Instance.

This also allows services to gain the trust of users by deploying their registries with a reference to a trusted account implementation address.

Furthermore, account implementations can be designed as upgradeable, so users are not necessarily bound to the implementation specified by the Account Registry Instance used to create their account.

### Separate `createAccount` and `claimAccount` Operations

Operations to create and claim Account Instances are intentionally separate. This allows services to provide users with valid [ERC-6492](/EIPs/EIPS/eip-6492) signatures before their Account Instance has been deployed.

## Reference Implementation

The following is an example of an Account Registry Factory which can be used by external service providers to deploy their own Account Registry Instance.

### Account Registry Factory

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.13;

/// @author: manifold.xyz

import {Create2} from &quot;openzeppelin/utils/Create2.sol&quot;;

import {Address} from &quot;../../lib/Address.sol&quot;;
import {ERC1167ProxyBytecode} from &quot;../../lib/ERC1167ProxyBytecode.sol&quot;;
import {IAccountRegistryFactory} from &quot;./IAccountRegistryFactory.sol&quot;;

contract AccountRegistryFactory is IAccountRegistryFactory {
    using Address for address;

    error InitializationFailed();

    address private immutable registryImplementation = 0x076B08EDE2B28fab0c1886F029cD6d02C8fF0E94;

    function createRegistry(
        uint96 index,
        address accountImplementation,
        bytes calldata accountInitData
    ) external returns (address) {
        bytes32 salt = _getSalt(msg.sender, index);
        bytes memory code = ERC1167ProxyBytecode.createCode(registryImplementation);
        address _registry = Create2.computeAddress(salt, keccak256(code));

        if (_registry.isDeployed()) return _registry;

        _registry = Create2.deploy(0, salt, code);

        (bool success, ) = _registry.call(
            abi.encodeWithSignature(
                &quot;initialize(address,address,bytes)&quot;,
                msg.sender,
                accountImplementation,
                accountInitData
            )
        );
        if (!success) revert InitializationFailed();

        emit AccountRegistryCreated(_registry, accountImplementation, index);

        return _registry;
    }

    function registry(address deployer, uint96 index) external view override returns (address) {
        bytes32 salt = _getSalt(deployer, index);
        bytes memory code = ERC1167ProxyBytecode.createCode(registryImplementation);
        return Create2.computeAddress(salt, keccak256(code));
    }

    function _getSalt(address deployer, uint96 index) private pure returns (bytes32) {
        return bytes32(abi.encodePacked(deployer, index));
    }
}
```

### Account Registry

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.13;

/// @author: manifold.xyz

import {Create2} from &quot;openzeppelin/utils/Create2.sol&quot;;
import {ECDSA} from &quot;openzeppelin/utils/cryptography/ECDSA.sol&quot;;
import {Ownable} from &quot;openzeppelin/access/Ownable.sol&quot;;
import {Initializable} from &quot;openzeppelin/proxy/utils/Initializable.sol&quot;;
import {IERC1271} from &quot;openzeppelin/interfaces/IERC1271.sol&quot;;
import {SignatureChecker} from &quot;openzeppelin/utils/cryptography/SignatureChecker.sol&quot;;

import {Address} from &quot;../../lib/Address.sol&quot;;
import {IAccountRegistry} from &quot;../../interfaces/IAccountRegistry.sol&quot;;
import {ERC1167ProxyBytecode} from &quot;../../lib/ERC1167ProxyBytecode.sol&quot;;

contract AccountRegistryImplementation is Ownable, Initializable, IAccountRegistry {
    using Address for address;
    using ECDSA for bytes32;

    struct Signer {
        address account;
        bool isContract;
    }

    error InitializationFailed();
    error ClaimFailed();
    error Unauthorized();

    address public accountImplementation;
    bytes public accountInitData;
    Signer public signer;

    constructor() {
        _disableInitializers();
    }

    function initialize(
        address owner,
        address accountImplementation_,
        bytes calldata accountInitData_
    ) external initializer {
        _transferOwnership(owner);
        accountImplementation = accountImplementation_;
        accountInitData = accountInitData_;
    }

    /**
     * @dev See {IAccountRegistry-createAccount}
     */
    function createAccount(uint256 salt) external override returns (address) {
        bytes memory code = ERC1167ProxyBytecode.createCode(accountImplementation);
        address _account = Create2.computeAddress(bytes32(salt), keccak256(code));

        if (_account.isDeployed()) return _account;

        _account = Create2.deploy(0, bytes32(salt), code);

        (bool success, ) = _account.call(accountInitData);
        if (!success) revert InitializationFailed();

        emit AccountCreated(_account, accountImplementation, salt);

        return _account;
    }

    /**
     * @dev See {IAccountRegistry-claimAccount}
     */
    function claimAccount(
        address owner,
        uint256 salt,
        uint256 expiration,
        bytes32 message,
        bytes calldata signature
    ) external override returns (address) {
        _verify(owner, salt, expiration, message, signature);
        address _account = this.createAccount(salt);

        (bool success, ) = _account.call(
            abi.encodeWithSignature(&quot;transferOwnership(address)&quot;, owner)
        );
        if (!success) revert ClaimFailed();

        emit AccountClaimed(_account, owner);
        return _account;
    }

    /**
     * @dev See {IAccountRegistry-account}
     */
    function account(uint256 salt) external view override returns (address) {
        bytes memory code = ERC1167ProxyBytecode.createCode(accountImplementation);
        return Create2.computeAddress(bytes32(salt), keccak256(code));
    }

    /**
     * @dev See {IAccountRegistry-isValidSignature}
     */
    function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4) {
        bytes32 expectedHash = keccak256(abi.encodePacked(hash, msg.sender));
        bool isValid = SignatureChecker.isValidSignatureNow(
            signer.account,
            expectedHash,
            signature
        );
        if (isValid) {
            return IERC1271.isValidSignature.selector;
        }

        return &quot;&quot;;
    }

    function updateSigner(address newSigner) external onlyOwner {
        uint32 signerSize;
        assembly {
            signerSize := extcodesize(newSigner)
        }
        signer.account = newSigner;
        signer.isContract = signerSize &gt; 0;
    }

    function _verify(
        address owner,
        uint256 salt,
        uint256 expiration,
        bytes32 message,
        bytes calldata signature
    ) internal view {
        address signatureAccount;

        if (signer.isContract) {
            if (!SignatureChecker.isValidSignatureNow(signer.account, message, signature))
                revert Unauthorized();
        } else {
            signatureAccount = message.recover(signature);
        }

        bytes32 expectedMessage = keccak256(
            abi.encodePacked(&quot;\x19Ethereum Signed Message:\n84&quot;, owner, salt, expiration)
        );

        if (
            message != expectedMessage ||
            (!signer.isContract &amp;&amp; signatureAccount != signer.account) ||
            (expiration != 0 &amp;&amp; expiration &lt; block.timestamp)
        ) revert Unauthorized();
    }
}
```

### Example Account Implementation

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.13;

/// @author: manifold.xyz

import {IERC1271} from &quot;openzeppelin/interfaces/IERC1271.sol&quot;;
import {SignatureChecker} from &quot;openzeppelin/utils/cryptography/SignatureChecker.sol&quot;;
import {IERC165} from &quot;openzeppelin/utils/introspection/IERC165.sol&quot;;
import {ERC165Checker} from &quot;openzeppelin/utils/introspection/ERC165Checker.sol&quot;;
import {IERC721} from &quot;openzeppelin/token/ERC721/IERC721.sol&quot;;
import {IERC721Receiver} from &quot;openzeppelin/token/ERC721/IERC721Receiver.sol&quot;;
import {IERC1155Receiver} from &quot;openzeppelin/token/ERC1155/IERC1155Receiver.sol&quot;;
import {Initializable} from &quot;openzeppelin/proxy/utils/Initializable.sol&quot;;
import {Ownable} from &quot;openzeppelin/access/Ownable.sol&quot;;
import {IERC1967Account} from &quot;./IERC1967Account.sol&quot;;

import {IAccount} from &quot;../../interfaces/IAccount.sol&quot;;

/**
 * @title ERC1967AccountImplementation
 * @notice A lightweight, upgradeable smart contract wallet implementation
 */
contract ERC1967AccountImplementation is
    IAccount,
    IERC165,
    IERC721Receiver,
    IERC1155Receiver,
    IERC1967Account,
    Initializable,
    Ownable
{
    address public registry;

    constructor() {
        _disableInitializers();
    }

    function initialize() external initializer {
        registry = msg.sender;
        _transferOwnership(registry);
    }

    function supportsInterface(bytes4 interfaceId) external pure returns (bool) {
        return (interfaceId == type(IAccount).interfaceId ||
            interfaceId == type(IERC1967Account).interfaceId ||
            interfaceId == type(IERC1155Receiver).interfaceId ||
            interfaceId == type(IERC721Receiver).interfaceId ||
            interfaceId == type(IERC165).interfaceId);
    }

    function onERC721Received(
        address,
        address,
        uint256,
        bytes memory
    ) public pure returns (bytes4) {
        return this.onERC721Received.selector;
    }

    function onERC1155Received(
        address,
        address,
        uint256,
        uint256,
        bytes memory
    ) public pure returns (bytes4) {
        return this.onERC1155Received.selector;
    }

    function onERC1155BatchReceived(
        address,
        address,
        uint256[] memory,
        uint256[] memory,
        bytes memory
    ) public pure returns (bytes4) {
        return this.onERC1155BatchReceived.selector;
    }

    /**
     * @dev {See IERC1967Account-executeCall}
     */
    function executeCall(
        address _target,
        uint256 _value,
        bytes calldata _data
    ) external payable override onlyOwner returns (bytes memory _result) {
        bool success;
        // solhint-disable-next-line avoid-low-level-calls
        (success, _result) = _target.call{value: _value}(_data);
        require(success, string(_result));
        emit TransactionExecuted(_target, _value, _data);
        return _result;
    }

    /**
     * @dev {See IAccount-setOwner}
     */
    function setOwner(address _owner) external override onlyOwner {
        _transferOwnership(_owner);
    }

    receive() external payable {}

    function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4) {
        if (owner() == registry) {
            return IERC1271(registry).isValidSignature(hash, signature);
        }

        bool isValid = SignatureChecker.isValidSignatureNow(owner(), hash, signature);
        if (isValid) {
            return IERC1271.isValidSignature.selector;
        }

        return &quot;&quot;;
    }
}
```

## Security Considerations

### Front-running

Deployment of reserved ownership accounts through an Account Registry Instance through calls to `createAccount` could be front-run by a malicious actor. However, if the malicious actor attempted to alter the `owner` parameter in the calldata, the Account Registry Instance would find the signature to be invalid, and revert the transaction. Thus, any successful front-running transaction would deploy an identical Account Instance to the original transaction, and the original owner would still gain control over the address.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 25 Apr 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6981</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6981</guid>
      </item>
    
      <item>
        <title>Efficient Default Lockable Tokens</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc721-default-lockable-proposal/13366</comments>
        
        <description>## Abstract

This proposal introduces a lockable interface for [ERC-721](/EIPs/EIPS/eip-721) tokens that optimizes gas usage by eliminating unnecessary events. This interface forms the foundation for the creation and management of lockable [ERC-721](/EIPs/EIPS/eip-721) tokens. It provides a gas-efficient approach by emitting a `DefaultLocked(bool locked)` event upon deployment, setting the initial lock status for all tokens, while individual `Locked(uint256 indexed tokenId, bool locked)` events handle subsequent status changes for specific tokens. The interface also includes a view function `locked(uint256 tokenId)` to return the current lock status of a token, and a view function `defaultLocked()` to query the default status of a newly minted token.

## Motivation

Existing lockable token proposals often mandate the emission of an event each time a token is minted. This results in unnecessary gas consumption, especially in cases where tokens are permanently locked from inception to destruction (e.g., soulbounds or non-transferable badges). This proposal offers a more gas-efficient solution that only emits events upon contract deployment and status changes of individual tokens.

## Specification

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

The interface is defined as follows:

```solidity
// ERC165 interfaceId 0x6b61a747
interface IERC6982 {
  /**
   * @dev MUST be emitted when the contract is deployed to establish the default lock status 
   *      for all tokens. Also, MUST be emitted again if the default lock status changes, 
   *      to ensure the default status for all tokens (without a specific `Locked` event) is updated.
   */
  event DefaultLocked(bool locked);

  /**
   * @dev MUST be emitted when the lock status of a specific token changes.
   *      This status overrides the default lock status for that specific token.
   */
  event Locked(uint256 indexed tokenId, bool locked);

  /**
   * @dev Returns the current default lock status for tokens. 
   *      The returned value MUST reflect the status indicated by the most recent `DefaultLocked` event.
   */
  function defaultLocked() external view returns (bool);

  /**
   * @dev Returns the lock status of a specific token. 
   *      If no `Locked` event has been emitted for the token, it MUST return the current default lock status. 
   *      The function MUST revert if the token does not exist.
   */
  function locked(uint256 tokenId) external view returns (bool);
}
```

The [ERC-165](/EIPs/EIPS/eip-165) interfaceId is `0x6b61a747`.

## Rationale

This standard seeks to optimize gas consumption by minimizing the frequency of event emission. The `DefaultLocked` event is designed to establish the lock status for all tokens, thereby circumventing the need to emit an event each time a new token is minted. It&apos;s crucial to note that the `DefaultLocked` event can be emitted at any point in time, and is not restricted to only before the `Locked` events are emitted.

Tokens may alter their behavior under certain circumstances (such as after a reveal), prompting the re-emission of the `DefaultLocked` event to reflect the new default status. The primary objective here is to economize on gas usage by avoiding the need to emit a `Locked` event for each token when the default status changes.

The `Locked` event is utilized to document changes in the lock status of individual tokens.

The `defaultLocked` function returns the prevailing default lock status of a token. This function is beneficial as it fosters interaction with other contracts and averts potential conflicts with [ERC-5192](./eip-5192), which is in its final stage.

The `locked` function gives the current lock status of a particular token, further facilitating interaction with other contracts. If no changes have been made to a specific token ID, this function should return the value provided by the `defaultLocked` function.

Bear in mind that a token being designated as &quot;locked&quot; doesn&apos;t necessarily imply that it is entirely non-transferable. There might be certain conditions under which a token can still be transferred despite its locked status. Primarily, the locked status relates to a token&apos;s transferability on marketplaces and external exchanges.

To illustrate, let&apos;s consider the Cruna protocol. In this system, an NFT owner has the ability to activate what is termed an &apos;protector&apos;. This is essentially a secondary wallet with the unique privilege of initiating key transactions. Upon setting an initiator, the token&apos;s status is rendered &apos;locked&apos;. However, this does not impede the token&apos;s transferability if the initiation for the transfer comes from the designated protector. 

## Backwards Compatibility

This standard is fully backwards compatible with existing [ERC-721](/EIPs/EIPS/eip-721) contracts. It can be easily integrated into existing contracts and will not cause any conflicts or disruptions.

## Reference Implementation

An example implementation is located in the [assets](../assets/eip-6982) directory.

It solves a specific use case: token&apos;s owners losing the ownership when staking the asset in a pool. The implementation allow the pool to lock the asset, leaving the ownership to the owner. In the [README](/EIPs/assets/eip-6982/) you can find more details about how to compile and test the contracts.

## Security Considerations

This EIP does not introduce any known security considerations. However, as with any smart contract standard, it is crucial to employ rigorous security measures in the implementation of this interface.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 02 May 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6982</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6982</guid>
      </item>
    
      <item>
        <title>Elected block proposer has not been slashed</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6988-elected-block-proposer-has-not-been-slashed/14349</comments>
        
        <description>## Abstract

Introduces a modification to the consensus layer specification which ensures that slashed validator cannot be elected as block proposer.

## Motivation

A block proposed by a slashed validator is rejected by the corresponding validity check in the [`phase0/process_block_header`](https://github.com/ethereum/consensus-specs/blob/3115d1140b23dd4c9c23fbd9e2428186cf816bde/specs/phase0/beacon-chain.md#block-header) function as defined in the consensus layer specification.

At the same time the definition of the [`phase0/compute_proposer_index`](https://github.com/ethereum/consensus-specs/blob/3115d1140b23dd4c9c23fbd9e2428186cf816bde/specs/phase0/beacon-chain.md#compute_proposer_index) allows for a slashed validator to be elected as a proposer. This contradiction effectively leads to a missed proposal if it is supposed to be made by a slashed validator.

The impact of the proposed fix in the case of a single slashing on Ethereum Mainnet is negligible but it becomes significant in the case of correlated slashings. For instance, a correlated slashing of `1/10th` of a validator set can lead to `1/10th` of missed proposals in a number of epochs after the slashing.

## Specification

Specification of the proposed change can be found in [`/_features/eip6988/beacon-chain.md`](https://github.com/ethereum/consensus-specs/blob/0ad3972725e7c22e8edf3bab2dd7730acbe3c272/specs/_features/eip6988/beacon-chain.md).

## Rationale

### Modifying `get_beacon_proposer_index`

This function is modified to read a proposer index from a beacon state if a slot of a latest block header is the same as the `state.slot`.

This modification is done to make the function return correct proposer index in the case when the proposer of a given block is being slashed during processing of the block.

## Backwards Compatibility

This fix changes proposer election mechanism in a backwards incompatible way and requires a hard fork to be deployed.

## Test Cases

The following test cases were added to cover this change:

* [`test_slashed_proposer_rewarded_for_sync_aggregate_inclusion`](https://github.com/ethereum/consensus-specs/blob/0ad3972725e7c22e8edf3bab2dd7730acbe3c272/tests/core/pyspec/eth2spec/test/altair/block_processing/sync_aggregate/test_process_sync_aggregate.py#L712)
* [`test_slashed_proposer_rewarded_for_attestation_inclusion`](https://github.com/ethereum/consensus-specs/blob/0ad3972725e7c22e8edf3bab2dd7730acbe3c272/tests/core/pyspec/eth2spec/test/altair/block_processing/test_process_attestation.py#L17)
* [`test_slashed_validator_not_elected_for_proposal`](https://github.com/ethereum/consensus-specs/blob/0ad3972725e7c22e8edf3bab2dd7730acbe3c272/tests/core/pyspec/eth2spec/test/eip6988/unittests/validator/test_validator.py#L9)
* [`test_slashed_validator_elected_for_proposal`](https://github.com/ethereum/consensus-specs/blob/0ad3972725e7c22e8edf3bab2dd7730acbe3c272/tests/core/pyspec/eth2spec/test/phase0/unittests/validator/test_validator_unittest.py#L520)

## Reference Implementation

Reference implementation is in the same place as [Specification](#specification).

## Security Considerations

There are no observed security issues introduced by the proposed change.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 04 May 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6988</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6988</guid>
      </item>
    
      <item>
        <title>ERC-721 with transaction validation step.</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc721-with-a-validation-step/14071</comments>
        
        <description>## Abstract

This standard is an extension of [ERC-721](/EIPs/EIPS/eip-721). It defines new validation functionality to avoid wallet draining: every `transfer` or `approve` will be locked waiting for validation.

## Motivation

The power of the blockchain is at the same time its weakness: giving the user full responsibility for their data.

Many cases of NFT theft currently exist, and current NFT anti-theft schemes, such as transferring NFTs to cold wallets, make NFTs inconvenient to use.

Having a validation step before every `transfer` and `approve` would give Smart Contract developers the opportunity to create secure NFT anti-theft schemes.

An implementation example would be a system where a validator address is responsible for validating all Smart Contract transactions.

This address would be connected to a dApp where the user could see the validation requests of his NFTs and accept the correct ones.

Giving this address only the power to validate transactions would make a much more secure system where to steal an NFT the thief would have to have both the user&apos;s address and the validator address simultaneously.

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot; and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

[ERC-721](/EIPs/EIPS/eip-721) compliant contracts MAY implement this EIP.

All the operations that change the ownership of an NFT, like a `transferFrom`/`safeTransferFrom`, SHALL create a `TransferValidation` pending to be validated and emit a `ValidateTransfer`, and SHALL NOT transfer the ownership of an NFT.

All the operations that enable an approval to manage an NFT, like an `approve`/`setApprovalForAll`, SHALL create an `ApprovalValidation` pending to be validated and emit a `ValidateApproval`, and SHALL NOT enable an approval.

When the transfer is called by an approved account and not the owner, it MUST be executed directly without the need for validation. This is in order to adapt to all current marketplaces that require approve to directly move your NFTs.

When validating a `TransferValidation` or `ApprovalValidation` the valid field MUST be set to true and MUST NOT be validated again.

The operations that validate a `TransferValidation` SHALL change the ownership of the NFT or enable the approval.

The operations that validate an `ApprovalValidation` SHALL enable the approval.

### Contract Interface

```solidity
 interface IERC6997 {

    struct TransferValidation {
        // The address of the owner.
        address from;
        // The address of the receiver.
        address to;
        // The token Id.
        uint256 tokenId;
        // Whether is a valid transfer.
        bool valid;
    }

    struct ApprovalValidation {
        // The address of the owner.
        address owner;
        // The approved address.
        address approve;
        // The token Id.
        uint256 tokenId;
        // Whether it is a total approval.
        bool approveAll;
        // Whether it is a valid approval.
        bool valid;
    }

    /**
     * @dev Emitted when a new transfer validation has been requested.
     */
    event ValidateTransfer(address indexed from, address to, uint256 indexed tokenId, uint256 indexed transferValidationId);

    /**
    * @dev Emitted when a new approval validation has been requested.
    */
    event ValidateApproval(address indexed owner, address approve, uint256 tokenId, bool indexed approveAll, uint256 indexed approvalValidationId);

    /**
     * @dev Returns true if this contract is a validator ERC721.
     */
    function isValidatorContract() external view returns (bool);

    /**
     * @dev Returns the transfer validation struct using the transfer ID.
     *
     */
    function transferValidation(uint256 transferId) external view returns (TransferValidation memory);

    /**
    * @dev Returns the approval validation struct using the approval ID.
    *
    */
    function approvalValidation(uint256 approvalId) external view returns (ApprovalValidation memory);

    /**
     * @dev Return the total amount of transfer validations created.
     *
     */
    function totalTransferValidations() external view returns (uint256);

    /**
     * @dev Return the total amount of transfer validations created.
     *
     */
    function totalApprovalValidations() external view returns (uint256);
}
  ```

The `isValidatorContract()` function MUST be implemented as `public`.

The `transferValidation(uint256 transferId)` function MAY be implemented as `public` or `external`.

The `approvalValidation(uint256 approveId)` function MAY be implemented as `public` or `external`.

The `totalTransferValidations()` function MAY be implemented as `pure` or `view`.

The `totalApprovalValidations()` function MAY be implemented as `pure` or `view`.

## Rationale

### Universality

The standard only defines the validation functions, but not how they should be used. It defines the validations as internal and lets the user decide how to manage them.

An example could be to have an address validator connected to a dApp so that users could manage their validations.

This validator could be used for all NFTs or only for some users.

It could also be used as a wrapped Smart Contract for existing ERC-721, allowing 1/1 conversion with existing NFTs.

### Extensibility

This standard only defines the validation function, but does not define the system with which it has to be validated. A third-party protocol can define how it wants to call these functions as it wishes.

## Backwards Compatibility

This standard is an extension of [ERC-721](/EIPs/EIPS/eip-721), compatible with all the operations except `transferFrom`/`safeTransferFrom`/`approve`/`setApprovalForAll`.

This operations will be overridden to create a validation petition instead of transfer ownership of an NFT or enable an approval.

## Reference Implementation

```solidity
// SPDX-License-Identifier: CC0-1.0

pragma solidity ^0.8.0;

import &quot;./IERC6997.sol&quot;;
import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;

/**
 * @dev Implementation of ERC6997
 */
contract ERC6997 is IERC6997, ERC721 {

    // Mapping from transfer ID to transfer validation
    mapping(uint256 =&gt; TransferValidation) private _transferValidations;

    // Mapping from approval ID to approval validation
    mapping(uint256 =&gt; ApprovalValidation) private _approvalValidations;

    // Total number of transfer validations
    uint256 private _totalTransferValidations;

    // Total number of approval validations
    uint256 private _totalApprovalValidations;

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    constructor(string memory name_, string memory symbol_) ERC721(name_, symbol_){
    }

    /**
    * @dev Returns true if this contract is a validator ERC721.
    */
    function isValidatorContract() public pure returns (bool) {
        return true;
    }

    /**
     * @dev Returns the transfer validation struct using the transfer ID.
     *
     */
    function transferValidation(uint256 transferId) public view override returns (TransferValidation memory) {
        require(transferId &lt; _totalTransferValidations, &quot;ERC6997: invalid transfer ID&quot;);
        TransferValidation memory v = _transferValidation(transferId);

        return v;
    }

    /**
     * @dev Returns the approval validation struct using the approval ID.
     *
     */
    function approvalValidation(uint256 approvalId) public view override returns (ApprovalValidation memory) {
        require(approvalId &lt; _totalApprovalValidations, &quot;ERC6997: invalid approval ID&quot;);
        ApprovalValidation memory v = _approvalValidation(approvalId);

        return v;
    }

    /**
     * @dev Return the total amount of transfer validations created.
     *
     */
    function totalTransferValidations() public view override returns (uint256) {
        return _totalTransferValidations;
    }

    /**
     * @dev Return the total amount of approval validations created.
     *
     */
    function totalApprovalValidations() public view override returns (uint256) {
        return _totalApprovalValidations;
    }

    /**
     * @dev Returns the transfer validation of the `transferId`. Does NOT revert if transfer doesn&apos;t exist
     */
    function _transferValidation(uint256 transferId) internal view virtual returns (TransferValidation memory) {
        return _transferValidations[transferId];
    }

    /**
     * @dev Returns the approval validation of the `approvalId`. Does NOT revert if transfer doesn&apos;t exist
     */
    function _approvalValidation(uint256 approvalId) internal view virtual returns (ApprovalValidation memory) {
        return _approvalValidations[approvalId];
    }

    /**
     * @dev Validate the transfer using the transfer ID.
     *
     */
    function _validateTransfer(uint256 transferId) internal virtual {
        TransferValidation memory v = transferValidation(transferId);
        require(!v.valid, &quot;ERC6997: the transfer is already validated&quot;);

        address from = v.from;
        address to = v.to;
        uint256 tokenId = v.tokenId;

        super._transfer(from, to, tokenId);

        _transferValidations[transferId].valid = true;
    }

    /**
     * @dev Validate the approval using the approval ID.
     *
     */
    function _validateApproval(uint256 approvalId) internal virtual {
        ApprovalValidation memory v = approvalValidation(approvalId);
        require(!v.valid, &quot;ERC6997: the approval is already validated&quot;);

        if(!v.approveAll) {
            require(v.owner == ownerOf(v.tokenId), &quot;ERC6997: The token have a new owner&quot;);
            super._approve(v.approve, v.tokenId);
        }
        else {
            super._setApprovalForAll(v.owner, v.approve, true);
        }

        _approvalValidations[approvalId].valid = true;
    }

    /**
     * @dev Create a transfer petition of `tokenId` from `from` to `to`.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {TransferValidate} event.
     */
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual override {
        require(ERC721.ownerOf(tokenId) == from, &quot;ERC6997: transfer from incorrect owner&quot;);
        require(to != address(0), &quot;ERC6997: transfer to the zero address&quot;);

        if(_msgSender() == from) {
            TransferValidation memory v;

            v.from = from;
            v.to = to;
            v.tokenId = tokenId;

            _transferValidations[_totalTransferValidations] = v;

            emit ValidateTransfer(from, to, tokenId, _totalTransferValidations);

            _totalTransferValidations++;
        } else {
            super._transfer(from, to, tokenId);
        }
    }

    /**
     * @dev Create an approval petition from `to` to operate on `tokenId`
     *
     * Emits an {ValidateApproval} event.
     */
    function _approve(address to, uint256 tokenId) internal override virtual {
        ApprovalValidation memory v;

        v.owner = ownerOf(tokenId);
        v.approve = to;
        v.tokenId = tokenId;

        _approvalValidations[_totalApprovalValidations] = v;

        emit ValidateApproval(v.owner, to, tokenId, false, _totalApprovalValidations);

        _totalApprovalValidations++;
    }

    /**
     * @dev If approved is true create an approval petition from `operator` to operate on
     * all of `owner` tokens, if not remove `operator` from operate on all of `owner` tokens
     *
     * Emits an {ValidateApproval} event.
     */
    function _setApprovalForAll(
        address owner,
        address operator,
        bool approved
    ) internal override virtual {
        require(owner != operator, &quot;ERC6997: approve to caller&quot;);

        if(approved) {
            ApprovalValidation memory v;

            v.owner = owner;
            v.approve = operator;
            v.approveAll = true;

            _approvalValidations[_totalApprovalValidations] = v;

            emit ValidateApproval(v.owner, operator, 0, true, _totalApprovalValidations);

            _totalApprovalValidations++;
        }
        else {
            super._setApprovalForAll(owner, operator, approved);
        }
    }
}
```

## Security Considerations

As is defined in the Specification the operations that change the ownership of an NFT or enable an approval to manage the NFT SHALL create a `TransferValidation` or an `ApprovalValidation` pending to be validated and SHALL NOT transfer the ownership of an NFT or enable an approval.

With this premise in mind, the operations in charge of validating a `TransferValidation` or an `ApprovalValidation` must be protected with the maximum security required by the applied system.

For example, a valid system would be one where there is a validator address in charge of validating the transactions.

To give another example, a system where each user could choose his validator address would also be correct.

In any case, the importance of security resides in the fact that no address can validate a `TransferValidation` or an `ApprovalValidation` without the permission of the chosen system.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 07 May 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-6997</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-6997</guid>
      </item>
    
      <item>
        <title>Execution layer triggerable withdrawals</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7002-execution-layer-triggerable-exits/14195</comments>
        
        <description>## Abstract

Adds a new mechanism to allow validators to trigger withdrawals and exits from their execution layer (0x01) withdrawal credentials.

These new execution layer exit messages are appended to the execution layer block and then processed by the consensus layer.

## Motivation

Validators have two keys -- an active key and a withdrawal credential. The active key takes the form of a BLS key, whereas the withdrawal credential can either be a BLS key (0x00) or an execution layer address (0x01). The active key is &quot;hot&quot;, actively signing and performing validator duties, whereas the withdrawal credential can remain &quot;cold&quot;, only performing limited operations in relation to withdrawing and ownership of the staked ETH. Due to this security relationship, the withdrawal credential ultimately is the key that owns the staked ETH and any rewards.

As currently specified, only the active key can initiate a validator exit. This means that in any non-standard custody relationship (i.e., the active key is a separate entity from the withdrawal credentials), the ultimate owner of the funds -- the possessor of the withdrawal credentials -- cannot independently choose to exit and begin the withdrawal process. This leads to either trust issues (e.g. ETH can be &quot;held hostage&quot; by the active key owner) or insufficient work-arounds such as pre-signed exits. Additionally, in the event that active keys are lost, a user should still be able to recover their funds by using their cold withdrawal credentials.

To ensure that the withdrawal credentials (owned by both EOAs and smart contracts) can trustlessly control the destiny of the staked ETH, this specification enables exits triggerable by 0x01 withdrawal credentials.

Note, 0x00 withdrawal credentials can be changed into 0x01 withdrawal credentials with a one-time signed message. Thus any functionality enabled for 0x01 credentials is defacto enabled for 0x00 credentials.

## Specification

### Configuration

| Name | Value | Comment |
| - | - | - |
| `WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS` | `0x00000961Ef480Eb55e80D19ad83579A64c007002` | Where to call and store relevant details about exit / partial withdrawal mechanism |
| `WITHDRAWAL_REQUEST_TYPE` | `0x01` | The [EIP-7685](/EIPs/EIPS/eip-7685) type prefix for withdrawal request |
| `SYSTEM_ADDRESS` | `0xfffffffffffffffffffffffffffffffffffffffe` | Address used to invoke system operation on contract
| `EXCESS_WITHDRAWAL_REQUESTS_STORAGE_SLOT` | 0 | |
| `WITHDRAWAL_REQUEST_COUNT_STORAGE_SLOT` | 1 | |
| `WITHDRAWAL_REQUEST_QUEUE_HEAD_STORAGE_SLOT` | 2 | Pointer to head of the withdrawal request message queue |
| `WITHDRAWAL_REQUEST_QUEUE_TAIL_STORAGE_SLOT` | 3 | Pointer to the tail of the withdrawal request message queue|
| `WITHDRAWAL_REQUEST_QUEUE_STORAGE_OFFSET` | 4 | The start memory slot of the in-state withdrawal request message queue|
| `MAX_WITHDRAWAL_REQUESTS_PER_BLOCK` | 16 | Maximum number of withdrawal requests that can be dequeued into a block |
| `TARGET_WITHDRAWAL_REQUESTS_PER_BLOCK` | 2 | |
| `MIN_WITHDRAWAL_REQUEST_FEE` | 1 | |
| `WITHDRAWAL_REQUEST_FEE_UPDATE_FRACTION` | 17 | |
| `EXCESS_INHIBITOR` | `2**256-1` | Excess value used to compute the fee before the first system call |

### Execution layer

#### Definitions

* **`FORK_BLOCK`** -- the first block in a blockchain after this EIP has been activated.

#### Withdrawal request operation

The new withdrawal request operation is an [EIP-7685](/EIPs/EIPS/eip-7685) request
with type `0x01` and consists of the following fields:

1. `source_address`: `Bytes20`
2. `validator_pubkey`: `Bytes48`
3. `amount`: `uint64`

The [EIP-7685](/EIPs/EIPS/eip-7685) encoding of a withdrawal request is computed as follows.
Note that `amount` is returned by the contract little-endian, and must be encoded as such.

```python
request_type = WITHDRAWAL_REQUEST_TYPE
request_data = read_withdrawal_requests()
```

#### Withdrawal Request Contract

The contract has three different code paths, which can be summarized at a high level as follows:

1. Add withdrawal request - requires a `56` byte input, the validator&apos;s public
   key concatenated with a big-endian `uint64` amount value.
2. Fee getter - if the input length is zero, return the current fee required to add a withdrawal request.
3. System process - if called by system address, pop off the withdrawal requests for the current block from the queue.

##### Add Withdrawal Request

If call data input to the contract is exactly `56` bytes, perform the following:

* Ensure enough ETH was sent to cover the current withdrawal request fee (`check_fee()`)
* Increase withdrawal request count by 1 for the current block (`increment_count()`)
* Insert a withdrawal request into the queue for the source address and validator pubkey (`insert_withdrawal_request_into_queue()`)

Specifically, the functionality is defined in pseudocode as the function `add_withdrawal_request()`:

```python
def add_withdrawal_request(Bytes48: validator_pubkey, uint64: amount):
    &quot;&quot;&quot;
    Add withdrawal request adds new request to the withdrawal request queue, so long as a sufficient fee is provided.
    &quot;&quot;&quot;

    # Verify sufficient fee was provided.
    fee = get_fee()
    require(msg.value &gt;= fee, &apos;Insufficient value for fee&apos;)

    # Increment withdrawal request count.
    count = sload(WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS, WITHDRAWAL_REQUEST_COUNT_STORAGE_SLOT)
    sstore(WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS, WITHDRAWAL_REQUEST_COUNT_STORAGE_SLOT, count + 1)

    # Insert into queue.
    queue_tail_index = sload(WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS, WITHDRAWAL_REQUEST_QUEUE_TAIL_STORAGE_SLOT)
    queue_storage_slot = WITHDRAWAL_REQUEST_QUEUE_STORAGE_OFFSET + queue_tail_index * 3
    sstore(WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot, msg.sender)
    sstore(WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 1, validator_pubkey[0:32])
    sstore(WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 2, validator_pubkey[32:48] ++ uint64_to_little_endian(amount))
    sstore(WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS, WITHDRAWAL_REQUEST_QUEUE_TAIL_STORAGE_SLOT, queue_tail_index + 1)
```

###### Fee calculation

The following pseudocode can compute the cost of an individual withdrawal request, given a certain number of excess withdrawal requests.

```python
def get_fee() -&gt; int:
    excess = sload(WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS, EXCESS_WITHDRAWAL_REQUESTS_STORAGE_SLOT)
    require(excess != EXCESS_INHIBITOR, &apos;Inhibitor still active&apos;)
    return fake_exponential(
        MIN_WITHDRAWAL_REQUEST_FEE,
        excess,
        WITHDRAWAL_REQUEST_FEE_UPDATE_FRACTION
    )

def fake_exponential(factor: int, numerator: int, denominator: int) -&gt; int:
    i = 1
    output = 0
    numerator_accum = factor * denominator
    while numerator_accum &gt; 0:
        output += numerator_accum
        numerator_accum = (numerator_accum * numerator) // (denominator * i)
        i += 1
    return output // denominator
```

##### Fee Getter

When the input to the contract is length zero, interpret this as a get request for the current fee, i.e. the contract returns the result of `get_fee()`.

##### System Call

At the end of processing any execution block starting from the `FORK_BLOCK` (i.e. after processing all transactions and after performing the block body withdrawal requests validations), call `WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS` as `SYSTEM_ADDRESS` with no calldata. The invocation triggers the following:

* The contract&apos;s queue is updated based on withdrawal requests dequeued and the withdrawal requests queue head/tail are reset if the queue has been cleared (`dequeue_withdrawal_requests()`)
* The contract&apos;s excess withdrawal requests are updated based on usage in the current block (`update_excess_withdrawal_requests()`)
* The contract&apos;s withdrawal requests count is reset to 0 (`reset_withdrawal_requests_count()`)

Each withdrawal request must appear in the EIP-7685 requests list in the exact order returned by `dequeue_withdrawal_requests()`.

Additionally, the system call and the processing of that block must conform to the following:

* The call has a dedicated gas limit of `30_000_000`.
* Gas consumed by this call does not count against the block’s overall gas usage.
* Both the gas limit assigned to the call and the gas consumed are excluded from any checks against the block’s gas limit.
* The call does not follow [EIP-1559](/EIPs/EIPS/eip-1559) fee burn semantics — no value should be transferred as part of this call.
* If there is no code at `WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS`, the corresponding block **MUST** be marked invalid.
* If the call to the contract fails or returns an error, the block **MUST** be invalidated.

The functionality triggered by the system call is defined in pseudocode as the function `read_withdrawal_requests()`:

```python
###################
# Public function #
###################

def read_withdrawal_requests():
    reqs = dequeue_withdrawal_requests()
    update_excess_withdrawal_requests()
    reset_withdrawal_requests_count()
    return ssz.serialize(reqs)

###########
# Helpers #
###########

def little_endian_to_uint64(data: bytes) -&gt; uint64:
    return uint64(int.from_bytes(data, &apos;little&apos;))

def uint64_to_little_endian(num: uint64) -&gt; bytes:
    return num.to_bytes(8, &apos;little&apos;)

class ValidatorWithdrawalRequest(object):
    source_address: Bytes20
    validator_pubkey: Bytes48
    amount: uint64

def dequeue_withdrawal_requests():
    queue_head_index = sload(WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS, WITHDRAWAL_REQUEST_QUEUE_HEAD_STORAGE_SLOT)
    queue_tail_index = sload(WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS, WITHDRAWAL_REQUEST_QUEUE_TAIL_STORAGE_SLOT)
    num_in_queue = queue_tail_index - queue_head_index
    num_dequeued = min(num_in_queue, MAX_WITHDRAWAL_REQUESTS_PER_BLOCK)

    reqs = []
    for i in range(num_dequeued):
        queue_storage_slot = WITHDRAWAL_REQUEST_QUEUE_STORAGE_OFFSET + (queue_head_index + i) * 3
        source_address = address(sload(WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot)[0:20])
        validator_pubkey = (
            sload(WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 1)[0:32] + sload(WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 2)[0:16]
        )
        amount = little_endian_to_uint64(sload(WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 2)[16:24])
        req = ValidatorWithdrawalRequest(
            source_address=Bytes20(source_address),
            validator_pubkey=Bytes48(validator_pubkey),
            amount=uint64(amount)
        )
        reqs.append(req)

    new_queue_head_index = queue_head_index + num_dequeued
    if new_queue_head_index == queue_tail_index:
        # Queue is empty, reset queue pointers
        sstore(WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS, WITHDRAWAL_REQUEST_QUEUE_HEAD_STORAGE_SLOT, 0)
        sstore(WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS, WITHDRAWAL_REQUEST_QUEUE_TAIL_STORAGE_SLOT, 0)
    else:
        sstore(WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS, WITHDRAWAL_REQUEST_QUEUE_HEAD_STORAGE_SLOT, new_queue_head_index)

    return reqs

def update_excess_withdrawal_requests():
    previous_excess = sload(WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS, EXCESS_WITHDRAWAL_REQUESTS_STORAGE_SLOT)
    if previous_excess == EXCESS_INHIBITOR:
        previous_excess = 0

    count = sload(WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS, WITHDRAWAL_REQUEST_COUNT_STORAGE_SLOT)

    new_excess = 0
    if previous_excess + count &gt; TARGET_WITHDRAWAL_REQUESTS_PER_BLOCK:
        new_excess = previous_excess + count - TARGET_WITHDRAWAL_REQUESTS_PER_BLOCK

    sstore(WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS, EXCESS_WITHDRAWAL_REQUESTS_STORAGE_SLOT, new_excess)

def reset_withdrawal_requests_count():
    sstore(WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS, WITHDRAWAL_REQUEST_COUNT_STORAGE_SLOT, 0)
```

##### Bytecode

```asm
caller
push20 0xfffffffffffffffffffffffffffffffffffffffe
eq
push1 0xcb
jumpi

push1 0x11
push0
sload
dup1
push32 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
eq
push2 0x01f4
jumpi

push1 0x01
dup3
mul
push1 0x01
swap1
push0

jumpdest
push0
dup3
gt
iszero
push1 0x68
jumpi

dup2
add
swap1
dup4
mul
dup5
dup4
mul
swap1
div
swap2
push1 0x01
add
swap2
swap1
push1 0x4d
jump

jumpdest
swap1
swap4
swap1
div
swap3
pop
pop
pop
calldatasize
push1 0x38
eq
push1 0x88
jumpi

calldatasize
push2 0x01f4
jumpi

callvalue
push2 0x01f4
jumpi

push0
mstore
push1 0x20
push0
return

jumpdest
callvalue
lt
push2 0x01f4
jumpi

push1 0x01
sload
push1 0x01
add
push1 0x01
sstore
push1 0x03
sload
dup1
push1 0x03
mul
push1 0x04
add
caller
dup2
sstore
push1 0x01
add
push0
calldataload
dup2
sstore
push1 0x01
add
push1 0x20
calldataload
swap1
sstore
caller
push1 0x60
shl
push0
mstore
push1 0x38
push0
push1 0x14
calldatacopy
push1 0x4c
push0
log0
push1 0x01
add
push1 0x03
sstore
stop

jumpdest
push1 0x03
sload
push1 0x02
sload
dup1
dup3
sub
dup1
push1 0x10
gt
push1 0xdf
jumpi

pop
push1 0x10

jumpdest
push0

jumpdest
dup2
dup2
eq
push2 0x0183
jumpi

dup3
dup2
add
push1 0x03
mul
push1 0x04
add
dup2
push1 0x4c
mul
dup2
sload
push1 0x60
shl
dup2
mstore
push1 0x14
add
dup2
push1 0x01
add
sload
dup2
mstore
push1 0x20
add
swap1
push1 0x02
add
sload
dup1
push32 0xffffffffffffffffffffffffffffffff00000000000000000000000000000000
and
dup3
mstore
swap1
push1 0x10
add
swap1
push1 0x40
shr
swap1
dup2
push1 0x38
shr
dup2
push1 0x07
add
mstore8
dup2
push1 0x30
shr
dup2
push1 0x06
add
mstore8
dup2
push1 0x28
shr
dup2
push1 0x05
add
mstore8
dup2
push1 0x20
shr
dup2
push1 0x04
add
mstore8
dup2
push1 0x18
shr
dup2
push1 0x03
add
mstore8
dup2
push1 0x10
shr
dup2
push1 0x02
add
mstore8
dup2
push1 0x08
shr
dup2
push1 0x01
add
mstore8
mstore8
push1 0x01
add
push1 0xe1
jump

jumpdest
swap2
add
dup1
swap3
eq
push2 0x0195
jumpi

swap1
push1 0x02
sstore
push2 0x01a0
jump

jumpdest
swap1
pop
push0
push1 0x02
sstore
push0
push1 0x03
sstore

jumpdest
push0
sload
dup1
push32 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
eq
iszero
push2 0x01cd
jumpi

pop
push0

jumpdest
push1 0x01
sload
push1 0x02
dup3
dup3
add
gt
push2 0x01e2
jumpi

pop
pop
push0
push2 0x01e8
jump

jumpdest
add
push1 0x02
swap1
sub

jumpdest
push0
sstore
push0
push1 0x01
sstore
push1 0x4c
mul
push0
return

jumpdest
push0
push0
revert
```

##### Deployment

The withdrawal requests contract is deployed like any other smart contract. A special synthetic address is generated by working backwards from the desired deployment transaction:

```json
{
  &quot;type&quot;: &quot;0x0&quot;,
  &quot;nonce&quot;: &quot;0x0&quot;,
  &quot;to&quot;: null,
  &quot;gas&quot;: &quot;0x3d090&quot;,
  &quot;gasPrice&quot;: &quot;0xe8d4a51000&quot;,
  &quot;maxPriorityFeePerGas&quot;: null,
  &quot;maxFeePerGas&quot;: null,
  &quot;value&quot;: &quot;0x0&quot;,
  &quot;input&quot;: &quot;0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f556101f880602d5f395ff33373fffffffffffffffffffffffffffffffffffffffe1460cb5760115f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff146101f457600182026001905f5b5f82111560685781019083028483029004916001019190604d565b909390049250505036603814608857366101f457346101f4575f5260205ff35b34106101f457600154600101600155600354806003026004013381556001015f35815560010160203590553360601b5f5260385f601437604c5fa0600101600355005b6003546002548082038060101160df575060105b5f5b8181146101835782810160030260040181604c02815460601b8152601401816001015481526020019060020154807fffffffffffffffffffffffffffffffff00000000000000000000000000000000168252906010019060401c908160381c81600701538160301c81600601538160281c81600501538160201c81600401538160181c81600301538160101c81600201538160081c81600101535360010160e1565b910180921461019557906002556101a0565b90505f6002555f6003555b5f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14156101cd57505f5b6001546002828201116101e25750505f6101e8565b01600290035b5f555f600155604c025ff35b5f5ffd&quot;,
  &quot;v&quot;: &quot;0x1b&quot;,
  &quot;r&quot;: &quot;0x539&quot;,
  &quot;s&quot;: &quot;0x5feeb084551e4e03a3581e269bc2ea2f8d0008&quot;,
  &quot;hash&quot;: &quot;0x8ded54be89448d78d4bc97782c0187b099e45380ab681742f9d3754e405c2572&quot;
}
```

```
Sender: 0x8646861A7cF453dDD086874d622b0696dE5b9674
Address: 0x00000961Ef480Eb55e80D19ad83579A64c007002
```

### Consensus layer

[Full specification](https://github.com/ethereum/consensus-specs/blob/7bf43d1bc4fdb91059f0e6f4f7f0f3349b144950/specs/electra/beacon-chain.md)

Sketch of spec:

* New operation `ExecutionLayerWithdrawalRequest`
* Will show up in `ExecutionPayload` as an SSZ List bound by length `MAX_WITHDRAWAL_REQUESTS_PER_BLOCK`
* New function that has similar functionality to `process_voluntary_exit` but can fail validations (e.g. validator is already exited) without the block failing (similar to deposit coming from EL)
* This function is called in `process_operations` for each `ExecutionLayerWithdrawalRequest` found in the `ExecutionPayload`

## Rationale

### `validator_pubkey` field

Multiple validators can utilize the same execution layer withdrawal credential, thus the `validator_pubkey` field is utilized to disambiguate which validator is being exited.

Note, `validator_index` also disambiguates validators.
The problem is that smart contracts of some staking pools are not aware of the indices, because the index becomes known only after the validator has been created on the beacon chain, while the pubkey is available in advance.

### Message queue

The contract maintains an in-state queue of withdrawal request messages to be dequeued each block into the block and thus into the execution layer.

The number of withdrawal requests that can be passed into the consensus layer are bound by `MAX_WITHDRAWAL_REQUESTS_PER_BLOCK` to bound the load both on the block size as well as on the consensus layer processing. `16` has been chosen for `MAX_WITHDRAWAL_REQUESTS_PER_BLOCK` to be in line with the bounds of similar operations on the beacon chain -- e.g. `VoluntaryExit` and `Deposit`.

Although there is a maximum number of withdrawal requests that can be passed to the consensus layer each block, the execution layer gas limit can provide for far more calls to the withdrawal request predeploy contract at each block. The queue then allows for these calls to successfully be made while still maintaining a system rate limit.

The alternative design considered was to have calls to the contract fail after `MAX_WITHDRAWAL_REQUESTS_PER_BLOCK` successful calls were made within the context of a single block. This would eliminate the need for the message queue, but would come at the cost of a bad UX of contract call failures in times of high exiting. The complexity to mitigate this bad UX is relatively low and is currently favored.

### Rate limiting using a fee

Transactions are naturally rate-limited in the execution layer via the gas limit, but an adversary willing to pay market-rate gas fees (and potentially utilize builder markets to pay for front-of-block transaction inclusion) can fill up the exit operation limits for relatively cheap, thus griefing honest validators that want to make a withdrawal request.

There are two general approaches to combat this griefing -- (a) only allow validators to send such messages and with a limit per time period or (b) utilize an economic method to make such griefing increasingly costly.

Method (a) (not used in this EIP) would require [EIP-4788](/EIPs/EIPS/eip-4788) (the `BEACON_ROOT` opcode) against which to prove withdrawal credentials in relation to validator pubkeys as well as a data-structure to track requests per-unit-time (e.g. 4 months) to ensure that a validator cannot grief the mechanism by submitting many requests. The downsides of this method are that it requires another cross-layer EIP and that it is of higher cross-layer complexity (e.g. care that might need to be taken in future upgrades if, for example, the shape of the merkle tree of `BEACON_ROOT` changes, then the contract and proof structure might need to be updated).

Method (b) has been utilized in this EIP to eliminate additional EIP requirements and to reduce cross-layer complexity to allow for correctness of this EIP (now and in the future) to be easier to analyze. The [EIP-1559](/EIPs/EIPS/eip-1559)-style mechanism with a dynamically adjusting fee mechanism allows for users to pay `MIN_WITHDRAWAL_REQUEST_FEE` for withdrawal requests in the normal case (fewer than 2 per block on average), but scales the fee up exponentially in response to high usage (i.e. potential abuse).

### `TARGET_WITHDRAWAL_REQUESTS_PER_BLOCK` configuration value

`TARGET_WITHDRAWAL_REQUESTS_PER_BLOCK` has been selected as `2` such that the growth of the partial withdrawal queue in the beacon state is negligible under extreme scenarios of the exit churn congestion.

### Fee update rule

The fee update rule is intended to approximate the formula `fee = MIN_WITHDRAWAL_REQUEST_FEE * e**(excess / WITHDRAWAL_REQUEST_FEE_UPDATE_FRACTION)`, where `excess` is the total &quot;extra&quot; amount of withdrawal requests that the chain has processed relative to the &quot;targeted&quot; number (`TARGET_WITHDRAWAL_REQUESTS_PER_BLOCK` per block).

Like EIP-1559, it’s a self-correcting formula: as the excess goes higher, the `fee` increases exponentially, reducing usage and eventually forcing the excess back down.

The block-by-block behavior is roughly as follows. If block `N` processes `X` requests, then at the end of block `N` `excess` increases by `X - TARGET_WITHDRAWAL_REQUESTS_PER_BLOCK`, and so the `fee` in block `N+1` increases by a factor of `e**((X - TARGET_WITHDRAWAL_REQUESTS_PER_BLOCK) / WITHDRAWAL_REQUEST_FEE_UPDATE_FRACTION)`. Hence, it has a similar effect to the existing EIP-1559, but is more &quot;stable&quot; in the sense that it responds in the same way to the same total withdrawal requests regardless of how they are distributed over time.

The parameter `WITHDRAWAL_REQUEST_FEE_UPDATE_FRACTION` controls the maximum downwards rate of change of the blob gas price. It is chosen to target a maximum downwards change rate of `e(TARGET_WITHDRAWAL_REQUESTS_PER_BLOCK / WITHDRAWAL_REQUEST_FEE_UPDATE_FRACTION) ≈ 1.125` per block.

More detailed analysis of the fee mechanism is available [here](/EIPs/assets/eip-7002/fee_analysis).

### Withdrawal requests inside of the block

Withdrawal requests are placed into the actual body of the beacon block.

There is a strong design requirement that the consensus layer and execution layer can execute independently of each other. This means, in this case, that the consensus layer cannot rely upon a synchronous call to the execution layer to get the required withdrawal requests for the current block. Instead, the requests must be embedded in the beacon block such that if the execution layer is offline, the consensus layer still has the requisite data to fully execute the consensus portion of the state transition function.

### Submitting requests via execution layer

Verifying `secp256k1` signatures from the consensus layer via Engine API is one of the alternatives to the proposed requests mechanism which engineering complexity is much lower.
However, this approach would limit usage of withdrawal requests to a large extent by making it impossible for smart contracts owning validator withdrawal credentials to benefit from this functionality.

## Backwards Compatibility

This EIP introduces backwards incompatible changes to the block structure and block validation rule set. But neither of these changes break anything related to current user activity and experience.

## Security Considerations

### Impact on existing custody relationships

There might be existing custody relationships and/or products that rely upon the assumption that the withdrawal credentials *cannot* trigger a withdrawal request. We are currently confident that the additional withdrawal credentials feature does not impact the security of existing validators because:

1. The withdrawal credentials ultimately own the funds so allowing them to exit staking is natural with respect to ownership.
2. We are currently not aware of any such custody relationships and/or products that do rely on the lack of this feature.

In the event that existing validators/custodians rely on this, then the validators can be exited and restaked utilizing 0x01 withdrawal credentials pointing to a smart contract that simulates this behaviour.

### Fee Overpayment

Calls to the system contract require a fee payment defined by the current contract state. Overpaid fees are not returned to the caller. It is not generally possible to compute the exact required fee amount ahead of time. When adding a withdrawal request from a contract, the contract can perform a read operation to check for the current fee and then pay exactly the required amount. Here is an example in Solidity:

```
function addWithdrawal(bytes memory pubkey, uint64 amount, uint64 requestFeeLimit) private {
    assert(pubkey.length == 48);

    // Read current fee from the contract.
    (bool readOK, bytes memory feeData) = WithdrawalsContract.staticcall(&apos;&apos;);
    if (!readOK) {
        revert(&apos;reading fee failed&apos;);
    }
    uint256 fee = uint256(bytes32(feeData));

    // Check the fee is not too high.
    if (fee &gt; requestFeeLimit) {
        revert(&apos;fee is too high&apos;);
    }

    // Add the request.
    bytes memory callData = abi.encodePacked(pubkey, amount);
    (bool writeOK,) = WithdrawalsContract.call{value: fee}(callData);
    if (!writeOK) {
        revert(&apos;adding request failed&apos;);
    }
}
```

Note: the system contract uses the EVM `CALLER` operation (Solidity: `msg.sender`) as the target address for withdrawals, i.e. the address that calls the system contract must match the 0x01 withdrawal credential recorded in the beacon state.

Note: the above code reverts if the fee is too high, the fee can change significantly between creation of a withdrawal request transaction and its inclusion into a block, thus, this check is very important to avoid overpayments.

Using an EOA to request withdrawals will always result in overpayment of fees. There is no way for an EOA to use a wrapper contract to request a withdrawal. And even if a way existed, the gas cost of returning the overage would likely be higher than the overage itself. If requesting withdrawals to an EOA through the system contract is desired, we recommend that users perform transaction simulations to estimate a reasonable fee amount to send.

### System Call failure

Although the likelihood of a failed system call to `WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS` is extremely low, the behavior in such cases is well-defined: the block is marked as invalid. However, if the failure results from processing a transaction within the block, the public mempool may still retain the transaction even after the block is invalidated. This can result in the offending transaction being included again, potentially causing one or more subsequent slots to go without valid blocks. To mitigate this, we recommend that the block producer implementation shuffle their transaction set to increase the chances of producing a valid block, without the offending transaction(s). The block producer implementation and/or the mempool should be aware of system call failure scenarios to enable this behavior.

### Empty Code failure

This EIP should not have been activated if there is no code present at `WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS` (i.e., if the chain is not &quot;ready&quot;). Doing so would cause the first and all subsequent blocks after `FORK_BLOCK` to be marked invalid.

If this situation occurs on a live chain, the following are two potential recovery strategies:

* Deploy the contract code via a transaction and include it in a block. This block would become the first valid block, provided the system call to the contract does not fail. This works because the empty code validation occurs after block-transactions execution.
* Postpone the `FORK_BLOCK` activation point by updating the consensual fork timestamp or block number in the client implementation(s), then deploy the contract before the fork activates.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 09 May 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7002</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7002</guid>
      </item>
    
      <item>
        <title>Verifiable AI-Generated Content Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7007-zkml-aigc-nfts-an-erc-721-extension-interface-for-zkml-based-aigc-nfts/14216</comments>
        
        <description>## Abstract

The verifiable AI-generated content (AIGC) non-fungible token (NFT) standard is an extension of the [ERC-721](/EIPs/EIPS/eip-721) token standard for AIGC. It proposes a set of interfaces for basic interactions and enumerable interactions for AIGC-NFTs. The standard includes an `addAigcData` and `verify` function interface, a new `AigcData` event, optional `Enumerable` and `Updatable` extensions, and a JSON schema for AIGC-NFT metadata. Additionally, it incorporates Zero-Knowledge Machine Learning (zkML) and Optimistic Machine Learning (opML) capabilities to enable verification of AIGC data correctness. In this standard, the `tokenId` is indexed by the `prompt`.

## Motivation

The verifiable AIGC-NFT standard aims to extend the existing [ERC-721](/EIPs/EIPS/eip-721) token standard to accommodate the unique requirements of AI-generated content NFTs representing models in a collection. This standard provides interfaces to use zkML or opML to verify whether or not the AIGC data for an NFT is generated from a certain ML model with a certain input (prompt). The proposed interfaces allow for additional functionality related to adding AIGC data, verifying, and enumerating AIGC-NFTs. Additionally, the metadata schema provides a structured format for storing information related to AIGC-NFTs, such as the prompt used to generate the content and the proof of ownership.

This standard supports two primary types of proofs: validity proofs and fraud proofs. In practice, zkML and opML are commonly employed as the prevailing instances for these types of proofs. Developers can choose their preferred ones.

In the zkML scenario, this standard enables model owners to publish their trained model and its ZKP verifier to Ethereum. Any user can claim an input (prompt) and publish the inference task. Any node that maintains the model and the proving circuit can perform the inference and proving, and submit the output of inference and the ZK proof for the inference trace to the verifier. The user that initiates the inference task will own the output for the inference of that model and input (prompt).

In the opML scenario, this standard enables model owners to publish their trained model to Ethereum. Any user can claim an input (prompt) and publish the inference task. Any node that maintains the model can perform the inference and submit the inference output. Other nodes can challenge this result within a predefined challenge period. At the end of the challenge period, the user can verify that they own the output for the inference of that model and prompt, and update the AIGC data as needed.

This capability is especially beneficial for AI model authors and AI content creators seeking to capitalize on their creations. With this standard, every input prompt and its resulting content can be securely verified on the blockchain. This opens up opportunities for implementing revenue-sharing mechanisms for all AI-generated content (AIGC) NFT sales. AI model authors can now share their models without concerns that open-sourcing will diminish their financial value.

An example workflow of a zkML AIGC NFT project compliant with this proposal is as follows:

![zkML Suggested Workflow](/EIPs/assets/eip-7007/workflow.png)

There are 4 components in this workflow:

- ML model - contains weights of a pre-trained model; given an inference input, generates the output
- zkML prover - given an inference task with input and output, generates a ZK proof
- AIGC-NFT smart contract - contract compliant with this proposal, with full [ERC-721](/EIPs/EIPS/eip-721) functionalities
- Verifier smart contract - implements a `verify` function, given an inference task and its ZK proof, returns the verification result as a boolean

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119 and RFC 8174.

**Every compliant contract must implement the `IERC7007`, [`ERC721`](/EIPs/EIPS/eip-721), and [`ERC165`](/EIPs/EIPS/eip-165) interfaces.**

The verifiable AIGC-NFT standard includes the following interfaces:

`IERC7007`: Defines an `addAigcData` function and an `AigcData` event for adding AIGC data to AIGC-NFTs. Defines a `verify` function to check the validity of the combination of prompt and aigcData using zkML/opML techniques.

```solidity
pragma solidity ^0.8.18;

/**
 * @dev Required interface of an ERC7007 compliant contract.
 * Note: the ERC-165 identifier for this interface is 0x702c55a6.
 */
interface IERC7007 is IERC165, IERC721 {
    /**
     * @dev Emitted when `tokenId` token&apos;s AIGC data is added.
     */
    event AigcData(
        uint256 indexed tokenId,
        bytes indexed prompt,
        bytes indexed aigcData,
        bytes proof
    );

    /**
     * @dev Add AIGC data to token at `tokenId` given `prompt`, `aigcData`, and `proof`.
     */
    function addAigcData(
        uint256 tokenId,
        bytes calldata prompt,
        bytes calldata aigcData,
        bytes calldata proof
    ) external;

    /**
     * @dev Verify the `prompt`, `aigcData`, and `proof`.
     */
    function verify(
        bytes calldata prompt,
        bytes calldata aigcData,
        bytes calldata proof
    ) external view returns (bool success);
}
```

### Optional Extension: Enumerable

The **enumeration extension** is OPTIONAL for [ERC-7007](/EIPs/EIPS/eip-7007) smart contracts. This allows your contract to publish its full list of mapping between `tokenId` and `prompt` and make them discoverable.

```solidity
pragma solidity ^0.8.18;

/**
 * @title ERC7007 Token Standard, optional enumeration extension
 * Note: the ERC-165 identifier for this interface is 0xfa1a557a.
 */
interface IERC7007Enumerable is IERC7007 {
    /**
     * @dev Returns the token ID given `prompt`.
     */
    function tokenId(bytes calldata prompt) external view returns (uint256);

    /**
     * @dev Returns the prompt given `tokenId`.
     */
    function prompt(uint256 tokenId) external view returns (string calldata);
}
```

### Optional Extension: Updatable

The **updatable extension** is OPTIONAL for [ERC-7007](/EIPs/EIPS/eip-7007) smart contracts. This allows your contract to update a token&apos;s `aigcData` in the case of opML, where `aigcData` content might change over the challenge period.

```solidity
pragma solidity ^0.8.18;

/**
 * @title ERC7007 Token Standard, optional updatable extension
 * Note: the ERC-165 identifier for this interface is 0x3f37dce2.
 */
interface IERC7007Updatable is IERC7007 {
    /**
     * @dev Update the `aigcData` of `prompt`.
     */
    function update(
        bytes calldata prompt,
        bytes calldata aigcData
    ) external;

    /**
     * @dev Emitted when `tokenId` token is updated.
     */
    event Update(
        uint256 indexed tokenId,
        bytes indexed prompt,
        bytes indexed aigcData
    );
}
```

### ERC-7007 Metadata JSON Schema for reference

```json
{
  &quot;title&quot;: &quot;AIGC Metadata&quot;,
  &quot;type&quot;: &quot;object&quot;,
  &quot;properties&quot;: {
    &quot;name&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Identifies the asset to which this NFT represents&quot;
    },
    &quot;description&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Describes the asset to which this NFT represents&quot;
    },
    &quot;image&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive.&quot;
    },
    &quot;prompt&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Identifies the prompt from which this AIGC NFT generated&quot;
    },
    &quot;aigc_type&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;image/video/audio...&quot;
    },
    &quot;aigc_data&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;A URI pointing to a resource with mime type image/* representing the asset to which this AIGC NFT represents.&quot;
    },
    &quot;proof_type&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;validity (zkML) or fraud (opML)&quot;
    }
  }
}
```

### ML Model Publication

While this standard does not describe the Machine Learning model publication stage, it is natural and recommended to publish the commitment of the Model to Ethereum separately, before any actual `addAigcData` actions. The model commitment schema choice lies on the AIGC-NFT project issuer party. The commitment should be checked inside the implementation of the `verify` function.

## Rationale

### Unique Token Identification

This specification sets the `tokenId` to be the hash of its corresponding `prompt`, creating a deterministic and collision-resistant way to associate tokens with their unique content generation parameters. This design decision ensures that the same prompt (which corresponds to the same AI-generated content under the same model seed) cannot be minted more than once, thereby preventing duplication and preserving the uniqueness of each NFT within the ecosystem.

### Generalization to Different Proof Types

This specification accommodates two proof types: validity proofs for zkML and fraud proofs for opML. Function arguments in `addAigcData` and `verify` are designed for generality, allowing for compatibility with both proof systems. Moreover, the specification includes an updatable extension that specifically serves the requirements of opML.

### `verify` interface

We specify a `verify` interface to enforce the correctness of `aigcData`. It is defined as a view function to reduce gas cost. `verify` should return true if and only if `aigcData` is finalized in both zkML and opML. In zkML, it must verify the ZK proof, i.e. `proof`; in opML, it must make sure that the challenging period is finalized, and that the `aigcData` is up-to-date, i.e. has been updated after finalization. Additionally, `proof` can be _empty_ in opML.

### `addAigcData` interface

We specify an `addAigcData` interface to bind the prompt and `aigcData` with `tokenId`. This function provides flexibility for different minting implementations. Notably, it acts differently in zkML and opML cases. In zkML, `addAigcData` should make sure `verify` returns `true`. While in opML, it can be called before finalization. The consideration here is that, limited by the proving difficulty, zkML usually targets simple model inference tasks in practice, making it possible to provide a proof within an acceptable time frame. On the other hand, opML enables large model inference tasks, with a cost of longer confirmation time to achieve the approximate same security level. Mint until opML finalization may not be the best practice considering the existing optimistic protocols.

### Naming Choice on `update`

We adopt &quot;update&quot; over &quot;finalize&quot; because a successful challenge happens rarely in practice. Using `update` could avoid calling it for every `tokenId` and save gas.

## Backwards Compatibility

This standard is backward compatible with the [ERC-721](/EIPs/EIPS/eip-721) as it extends the existing functionality with new interfaces.

## Test Cases

The reference implementation includes sample implementations of the [ERC-7007](/EIPs/EIPS/eip-7007) interfaces under `contracts/` and corresponding unit tests under `test/`. This repo can be used to test the functionality of the proposed interfaces and metadata schema.

## Reference Implementation

- ERC-7007 for [zkML](/EIPs/assets/eip-7007/contracts/ERC7007Zkml.sol) and [opML](/EIPs/assets/eip-7007/contracts/ERC7007Opml.sol)
- [ERC-7007 Enumerable Extension](/EIPs/assets/eip-7007/contracts/ERC7007Enumerable.sol)

## Security Considerations

### Frontrunning Risk

To address the risk of frontrunning, where an actor could potentially observe and preemptively claim a prompt during the minting process, implementers of this proposal must incorporate a secure prompt-claiming mechanism. Implementations could include time-locks, commit-reveal schemes, or other anti-frontrunning techniques to ensure equitable and secured claim processes for AIGC-NFTs.

### AIGC Data Change During Challenge Period

In the opML scenario, it is important to consider that the `aigcData` might change during the challenge period due to disputes or updates. The updatable extension defined here provides a way to handle these updates. Implementations must ensure that updates to `aigcData` are treated as critical state changes that require adherence to the same security and validation protocols as the initial minting process. Indexers should always check for any `Update` event emission.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 10 May 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7007</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7007</guid>
      </item>
    
      <item>
        <title>NFT Creator Attribution</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-authorship-attribution-for-erc721/14244</comments>
        
        <description>## Abstract

This Ethereum Improvement Proposal aims to solve the issue of creator attribution for Non-Fungible Token (NFT) standards ([ERC-721](/EIPs/EIPS/eip-721), [ERC-1155](/EIPs/EIPS/eip-1155)). To achieve this, this EIP proposes a mechanism where the NFT creator signs the required parameters for the NFT creation, including the NFT metadata in a hash along with any other relevant information. The signed parameters and the signature are then validated and emitted during the deployment transaction, which allows the NFT to validate the creator and NFT platforms to attribute creatorship correctly. This method ensures that even if a different wallet sends the deployment transaction, the correct account is attributed as the creator.

## Motivation

Current NFT platforms assume that the wallet deploying the smart contract is the creator of the NFT, leading to a misattribution in cases where a different wallet sends the deployment transaction. This happens often when working with smart wallet accounts, and new contract deployment strategies such as the first collector deploying the NFT contract. This proposal aims to solve the problem by allowing creators to sign the parameters required for NFT creation so that any wallet can send the deployment transaction with an signal in a verifiable way who is the creator.

## Specification

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.

ERC-721 and ERC-1155 compliant contracts MAY implement this NFT Creator Attribution extension to provide a standard event to be emitted that defines the NFT creator at the time of contract creation.

This EIP takes advantage of the fact that contract addresses can be precomputed before a contract is deployed. Whether the NFT contract is deployed through another contract (a factory) or through an EOA, the creator can be correctly attributed using this specification.

**Signing Mechanism**

Creator consent is given by signing an [EIP-712](/EIPs/EIPS/eip-712) compatible message; all signatures compliant with this EIP MUST include all fields defined. The struct signed can be any arbitrary data that defines how to create the token; it must hashed in an EIP-712 compatible format with a proper EIP-712 domain.

The following shows some examples of structs that could be encoded into `structHash` (defined below):

```solidity
// example struct that can be encoded in `structHash`; defines that a token can be created with a metadataUri and price:

struct TokenCreation {
  string metadataUri;
  uint256 price;
  uint256 nonce;
}
```

**Signature Validation**

Creator attribution is given through a signature verification that MUST be verified by the NFT contract being deployed and an event that MUST be emitted by the NFT contract during the deployment transaction. The event includes all the necessary fields for reconstructing the signed digest and validating the signature to ensure it matches the specified creator. The event name is `CreatorAttribution` and includes the following fields:

- `structHash`: hashed information for deploying the NFT contract (e.g. name, symbol, admins etc). This corresponds to the value `hashStruct` as defined in the [EIP-712 definition of hashStruct](/EIPs/EIPS/eip-712#definition-of-hashstruct) standard.
- `domainName`: the domain name of the contract verifying the signature (for EIP-712 signature validation).
- `version`: the version of the contract verifying the signature (for EIP-712 signature validation)
- `creator`: the creator&apos;s account
- `signature`: the creator’s signature

The event is defined as follows:

```solidity
event CreatorAttribution(
  bytes32 structHash,
  string domainName,
  string version,
  address creator,
  bytes signature
);
```

Note that although the `chainId` parameters is necessary for [EIP-712](/EIPs/EIPS/eip-712) signatures, we omit the parameter from the event as it can be inferred through the transaction data. Similarly, the `verifyingContract` parameter for signature verification is omitted since it MUST be the same as the `emitter` field in the transaction. `emitter` MUST be the token.

A platform can verify the validity of the creator attribution by reconstructing the signature digest with the parameters emitted and recovering the signer from the `signature` parameter. The recovered signer MUST match the `creator` emitted in the event. If `CreatorAttribution` event is present creator and the signature is validated correctly, attribution MUST be given to the `creator` instead of the account that submitted the transaction.

### Reference Implementation

#### Example signature validator

```solidity
pragma solidity 0.8.20;
import &quot;@openzeppelin/contracts/utils/cryptography/EIP712.sol&quot;;
import &quot;@openzeppelin/contracts/utils/cryptography/ECDSA.sol&quot;;
import &quot;@openzeppelin/contracts/interfaces/IERC1271.sol&quot;;

abstract contract ERC7015 is EIP712 {
  error Invalid_Signature();
  event CreatorAttribution(
    bytes32 structHash,
    string domainName,
    string version,
    address creator,
    bytes signature
  );

  /// @notice Define magic value to verify smart contract signatures (ERC1271).
  bytes4 internal constant MAGIC_VALUE =
    bytes4(keccak256(&quot;isValidSignature(bytes32,bytes)&quot;));

  function _validateSignature(
    bytes32 structHash,
    address creator,
    bytes memory signature
  ) internal {
    if (!_isValid(structHash, creator, signature)) revert Invalid_Signature();
    emit CreatorAttribution(structHash, &quot;ERC7015&quot;, &quot;1&quot;, creator, signature);
  }

  function _isValid(
    bytes32 structHash,
    address signer,
    bytes memory signature
  ) internal view returns (bool) {
    require(signer != address(0), &quot;cannot validate&quot;);

    bytes32 digest = _hashTypedDataV4(structHash);

    // if smart contract is the signer, verify using ERC-1271 smart-contract
    /// signature verification method
    if (signer.code.length != 0) {
      try IERC1271(signer).isValidSignature(digest, signature) returns (
        bytes4 magicValue
      ) {
        return MAGIC_VALUE == magicValue;
      } catch {
        return false;
      }
    }

    // otherwise, recover signer and validate that it matches the expected
    // signer
    address recoveredSigner = ECDSA.recover(digest, signature);
    return recoveredSigner == signer;
  }
}
```

## Rationale

By standardizing the `CreatorAttribution` event, this EIP enables platforms to ascertain creator attribution without relying on implicit assumptions. Establishing a standard for creator attribution empowers platforms to manage the complex aspects of deploying contracts while preserving accurate onchain creator information. This approach ensures a more reliable and transparent method for identifying NFT creators, fostering trust among participants in the NFT ecosystem.

[ERC-5375](/EIPs/EIPS/eip-5375) attempts to solve the same issue and although offchain data offers improved backward compatibility, ensuring accurate and immutable creator attribution is vital for NFTs. A standardized onchain method for creator attribution is inherently more reliable and secure.

In contrast to this proposal, ERC-5375 does not facilitate specifying creators for all tokens within an NFT collection, which is a prevalent practice, particularly in emerging use cases.

Both this proposal and ERC-5375 share similar limitations regarding address-based creator attribution:

&gt; The standard defines a protocol to verify that a certain *address* provided consent. However, it does not guarantee that the address corresponds to the expected creator […]. Proving a link between an address and the entity behind it is beyond the scope of this document.

## Backwards Compatibility

Since the standard requires an event to be emitted during the NFTs deployment transaction, existing NFTs cannot implement this standard.

## Security Considerations

A potential attack exploiting this proposal could involve deceiving creators into signing creator attribution consent messages unintentionally. Consequently, creators MUST ensure that all signature fields correspond to the necessary ones before signing.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 11 May 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7015</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7015</guid>
      </item>
    
      <item>
        <title>Scheme-Handler Discovery Option for Wallets</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/shadow-a-scheme-handler-discovery-option-for-wallets/14330</comments>
        
        <description>## Abstract

This proposal (affectionately known as SHADOW) is an alternative to [EIP-1193](/EIPs/EIPS/eip-1193) for wallet discovery in web browsers that requires no special permissions. Web pages intending to open a connection to a wallet inject an `iframe` tag pointing at a well-known scheme. Communication between the page and the wallet uses the `postMessage` API.

## Motivation

Current wallet discovery methods (eg. `window.ethereum`) only support one active wallet at a time, and require browser extensions to request broad permissions to modify web pages.

Ideally users should be able to have multiple wallets active, and choose between them at runtime. This not only results in an improved user experience but also reduces the barrier to entry for new browser extensions as users are no longer forced to only install one browser extension at a time.

With SHADOW, and unlike other recent proposals, browser extensions do not need blanket `content_scripts` or any `permissions` at all. Furthermore, any web page (and not just browser extensions) can register a handler for a protocol. That means better support for pure web wallets, native executable wallets, and hardware wallets. As long as a wallet can serve a page securely, it can register itself as a handler.

## Specification

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

### Initiating a Connection

To initiate a connection to a provider, a web page SHOULD:

1. Add an event listener to `window` for the `&quot;message&quot;` event (or set `window.onmessage`.)
2. Create an `iframe` tag with a `src` attribute value of `web+evm://`; then
3. Attach the `iframe` to the DOM.
4. Wait for a `&quot;message&quot;` event with a non-nullish `source` equal to the `iframe`&apos;s `contentWindow`.
5. Save the first port from the message event for further communication. This is referred to as the &quot;primary port.&quot;

The event received in step 4 MAY contain additional information about the provider. If present, the event data SHALL satisfy the following TypeScript interface:

```typescript
interface ProviderInfo {
    name: string;
    icon: string;
}
```

Where:

 - **`name`** is the human-readable name of the provider; and
 - **`icon`** is a URI pointing at an image. See [Icon Images](#icon-images).

### Communicating on an Established Connection

The web page and wallet MAY make requests of the other. The party making the request is known as the requester, and the replying party is known as the responder.

A requester MAY make requests of the responder by sending a message (using `postMessage`) on the primary port. The message MAY include a `MessagePort` as the first item of the message&apos;s transfer list to receive a reply. This port is known as a &quot;reply port.&quot; The message&apos;s data MUST satisfy [EIP-1193](/EIPs/EIPS/eip-1193)&apos;s `RequestArguments` interface, and SHALL be interpreted as described there.

The responder SHALL respond by posting a single message to the reply port, if a reply port was transferred. The message&apos;s data SHALL satisfy the following TypeScript interface, where `ProviderRpcError` is defined in EIP-1193:

```typescript
interface Response {
    result?: unknown;
    error?: ProviderRpcError;
}
```

Exactly one of `result` or `error` SHALL be present on the response.

If present, `result` SHALL be equivalent to the `result` field of the named JSON-RPC method&apos;s response.

Error objects SHOULD follow the recommendations set out in EIP-1193.

A request without a transferred reply port SHALL NOT be considered an error, even if a reply would have been sent.

### Icon Images

&lt;!-- TODO --&gt;

## Rationale

Instead of directly using the `iframe.contentWindow`&apos;s message port, SHADOW transfers a message port in the first message. This allows the `iframe`, in some specific scenarios, to completely hand off communication, so the web page and the provider communicate directly, without any proxying in the `iframe`.

## Backwards Compatibility

While not backwards compatible with EIP-1193, this proposal uses extremely similar data structures to make the transition as painless as possible.

It is possible to implement an EIP-1193 compatible provider using this proposal like so:

&lt;!-- TODO: Show example of implementing EIP-1193 provider on top of this proposal. --&gt;

## Security Considerations

&lt;!-- TODO: Needs more discussion. --&gt;

Both providers and web pages MUST verify the origin of messages before trusting them.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 15 May 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7039</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7039</guid>
      </item>
    
      <item>
        <title>Perpetually Valid Signed Voluntary Exits</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7044-perpetually-valid-signed-voluntary-exits/14348</comments>
        
        <description>## Abstract

Lock validator voluntary exit signature domain on Capella for perpetual validity. Currently, signed voluntary exits are only valid for two upgrades.

## Motivation

Currently, signed voluntary exits are valid up-to only two upgrades for block inclusion due to the Beacon Chain state considering only the current and previous fork version. This limitation increases the complexity of some staking operations, specifically those in which the staking operator (holder of active key) is distinct from the owner of the funds (holder of the withdrawal credential). Because voluntary exits can only be signed by the active key, such a relationship requires the exchange of signed exits ahead of time for an unbounded number of forks.

The limited validity of voluntary exits was originally motivated to isolate them in the event of a hard fork that results in two maintained chains. If fork A and B exist and a validator operates on both, if they send an exit, it will be replayable on both. However, this possibility is not sufficient to justify the UX degradation exposed above, as no funds are at risk and the staker can re-stake on one or both of the chains.

## Specification

### Consensus Layer

Specification changes are built into the Consensus Specs Deneb upgrade.

The specific makes one change to the state transition function:

- Modify [`process_voluntary_exit`](https://github.com/ethereum/consensus-specs/blob/75971a8c218b1d76d605dd8b88a08d39c42de221/specs/deneb/beacon-chain.md#modified-process_voluntary_exit) to compute the signing domain and root fixed on `CAPELLA_FORK_VERSION`.

Additionally, the `voluntary_exit` gossip conditions are implicitly modified to support this change.

To make the change backwards compatible the signature domain is locked on the Capella fork

### Execution Layer

This specification does not require any changes to the Execution Layer.

## Rationale

Perpetually valid signed voluntary exits allow simpler staking operation designs. It also aligns the UX of such objects to `BLSToExecutionChanges` and deposits, such that downstream tooling does not need to be updated with fork version information.

## Backwards Compatibility

This change is backwards compatible to the Consensus Layer of Ethereum block processing logic.

The expectation of future validity of exits is not forward compatible. Specifically, users who have already pre-signed exits utilizing the Deneb fork domain with an expectation of their validity should be aware that these pre-signed exits will no longer be recognized as valid. Consequently, users should adjust their approach moving forward. For continued validity across forks, including Deneb and subsequent forks, users should ensure that their exits are signed using the Capella fork domain.

There are no forwards/backwards compatibility issues with the Execution Layer.

## Test Cases

Test cases for this EIP can be found in the [`deneb`](https://github.com/ethereum/consensus-specs/tree/2297c09b7e457a13f7b2261a28cb45777be82f83/tests/core/pyspec/eth2spec/test/deneb) test suite of the `consensus-specs` repository. 

## Security Considerations

The divergent signature domains across forked networks would previously have prevented the replay of VoluntaryExits after two hard forks. This specification change causes the replay protection to no longer exist. These potential replays could impact individual stakers on both sides of a fork, but does not put funds at risk and does not impact the security of the chain.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 18 May 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7044</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7044</guid>
      </item>
    
      <item>
        <title>Increase max attestation inclusion slot</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7045-increase-attestation-slot-inclusion-range/14342</comments>
        
        <description>## Abstract

Increases max attestation inclusion slot from `attestation.slot + SLOTS_PER_EPOCH` to the last slot of epoch `N+1` where `N` is the epoch containing the attestation slot.

This increase is critical to the current LMD-GHOST security analysis as well as the confirmation rule.

## Motivation

Attestations can currently be included after some minimum delay (`1` slot on mainnet) up until `SLOTS_PER_EPOCH` slots after the slot the attestation was created in. This rolling window of one epoch was decided upon during Phase 0 because the equal inclusion window for any attestation was assessed as &quot;fair&quot;. The alternative considered path was to allow inclusion during the current and next epoch which means attestations created during the start of an epoch have more potential slots of inclusion than those at the end of the epoch.

Since this decision, it has become apparent that the alternative design is critical for current LMD-GHOST security proofs as well as a new confirmation rule (which will allow for block confirmations in approximately 3-4 slots in normal mainnet conditions).

This specification thus increases the max inclusion slot for attestations in accordance with the learned security proof and confirmation rule needs.

## Specification

### Constants

| Name | Value | Comment |
| - | - | - |
|`FORK_TIMESTAMP` | `1710338135` | Mainnet |

### Execution layer

This requires no changes to the Execution Layer.

### Consensus layer

Specification changes are built into the Consensus Specs Deneb upgrade.

The specification makes two minor changes to the state transition function:

* Modify [`process_attestation`](https://github.com/ethereum/consensus-specs/blob/95f36d99cf4aa59974da06af24ef9a7c12d3c301/specs/deneb/beacon-chain.md#modified-process_attestation) to not have an upper bound on the slot check and instead define the inclusion range via the minimum slot as well as the target epoch being in either current or previous epoch.
* Modify [`get_attestation_participation_flag_indices`](https://github.com/ethereum/consensus-specs/blob/95f36d99cf4aa59974da06af24ef9a7c12d3c301/specs/deneb/beacon-chain.md#modified-get_attestation_participation_flag_indices) to set the `TIMELY_TARGET_FLAG` without consideration of `inclusion_delay` to ensure that the extended inclusion attestations have a non-zero reward.

Additionally, the specification modifies the [attestation](https://github.com/ethereum/consensus-specs/blob/95f36d99cf4aa59974da06af24ef9a7c12d3c301/specs/deneb/p2p-interface.md#beacon_attestation_subnet_id) and [aggregate attestation](https://github.com/ethereum/consensus-specs/blob/95f36d99cf4aa59974da06af24ef9a7c12d3c301/specs/deneb/p2p-interface.md#beacon_aggregate_and_proof) gossip conditions to allow for gossip during this extended range.

## Rationale

### Extended max inclusion slot

As discussed in the Motivation, extending this max inclusion slot to the end of the next epoch is critical for LMD-GHOST security proofs and confirmation rule.

### Removal of `inclusion_delay` consideration for target reward

Previously, `get_attestation_participation_flag_indices` would only set the `TIMELY_TARGET_FLAG` (and thus reward for an attestation with correct target vote) if the attestation was included within a `SLOTS_PER_EPOCH` window.

The `inclusion_delay` consideration for this flag is removed to ensure that whatever the valid inclusion window is for an attestation, it can receive a baseline non-zero reward for correct target. This ensures that clients will still attempt to pack such attestations into blocks which is important for the security analysis.

Note, this was the intended behavior with the previously defined range which was equivalent to the max.

## Backwards Compatibility

This EIP introduces backwards incompatible changes to the block validation rule set on the consensus layer and must be accompanied by a hard fork.

## Test Cases 

Test cases for this EIP can be found in the [`deneb`](https://github.com/ethereum/consensus-specs/tree/2297c09b7e457a13f7b2261a28cb45777be82f83/tests/core/pyspec/eth2spec/test/deneb) test suite of the `consensus-specs` repository. 

## Security Considerations

This improves LMD-GHOST security as well as enables a fast confirmation rule.

There are no known negative impacts to security.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Thu, 18 May 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7045</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7045</guid>
      </item>
    
      <item>
        <title>Interoperable Digital Media Indexing</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7053-interoperable-digital-media-indexing/14394</comments>
        
        <description>## Abstract

This EIP proposes an interoperable indexing strategy designed to enhance the organization and retrieval of digital media information across multiple smart contracts and EVM-compatible blockchains. This system enhances the traceability and verification of cross-contract and cross-chain data, facilitating a more efficient discovery of storage locations and crucial information related to media assets. The major purpose is to foster an integrated digital media environment on the blockchain.

## Motivation

Given the significant role digital media files play on the Internet, it&apos;s crucial to have a robust and efficient method for indexing immutable information. Existing systems encounter challenges due to the absence of a universal, interoperable identifier for digital media content. This leads to fragmentation and complications in retrieving metadata, storage information, or the provenance of specific media assets. The issues become increasingly critical as the volume of digital media continues to expand.

The motivation behind this EIP is to establish a standardized, decentralized, and interoperable approach to index digital media across EVM-compatible networks. By integrating Decentralized Content Identifiers (CIDs) and Commit events, this EIP puts forward a mechanism enabling unique identification and indexing of each digital media file. Moreover, this system suggests a way for users to access a complete history of data associated with digital media assets, from creation to the current status. This full view enhances transparency, thereby providing users with the necessary information for future interactions with digital media.

This method creates a common interface that any digital media system can use to provide a standard way of indexing and searching their content.

||
|:--:|
| ![](/EIPs/assets/eip-7053/digital-media-indexing-system-and-metadata-lookup.jpg) |
| Figure 1: Digital Media Indexing Relationships and Lookup |

This EIP aims to create an interoperable indexing system to associate all data of the same digital content together (Figure 1). This will make it easier for users to find and trust digital media content, and it will also make it easier for systems to share and exchange information about this digital media content.

## Specification

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

### Content Identifier

Content Identifier in this EIP is the content address generated by passing the content of a digital media through a cryptographic hash function. Before the indexing process for digital media can begin, it is REQUIRED to generate unique Content Identifiers for each file. This identifier should the same as the Content Identifiers on the decentralized storage, ensuring each identifier provides access to the metadata, media information, and the content file itself.

### Commit Function

To index digital media, we shall call the commit function and generate Commit event:

```solidity
/**
 * @notice Emitted when a new commit is made.
 * @param recorder The address of the account making the commit.
 * @param assetCid The content identifier of the asset being committed.
 * @param commitData The data associated with the commit.
 */
event Commit(address indexed recorder, string indexed assetCid, string commitData);

/**
 * @notice Registers a commit for an asset.
 * Emits a Commit event and records the block number of the commit in the recordLogs mapping for the provided assetCid.
 * @dev Emits a Commit event and logs the block number of the commit event.
 * @param assetCid The content identifier of the asset being committed.
 * @param commitData The data associated with the commit.
 * @return The block number at which the commit was made.
 */
function commit(string memory assetCid, string memory commitData) public returns (uint256 blockNumber);
```

## Rationale

The design decisions in this EIP prioritize the effectiveness and efficiency of the indexing method. To achieve this, Decentralized Content Identifiers (CIDs) are utilized to uniquely identify digital media content across all systems. This approach offers accurate and precise searching of media, along with the following benefits:

1. Strengthened data integrity: CIDs serve as cryptographic hashes of the content, ensuring their uniqueness and preventing forgery. With the content in hand, obtaining the CID allows for searching relevant information associated with that content.

2. Streamlined data portability: CIDs enable the seamless transfer of digital media content across different systems, eliminating the need for re-encoding or reconfiguration of protocols. This promotes a more interoperable and open indexing system. For example, in cases where Non-Fungible Tokens (NFTs) are created prior to Commit events, the digital media content can still be indexed by converting the file referenced by the tokenURI using the same mechanism. This conversion process ensures that the digital media content associated with NFT tokens can be indexed with a consistent identification approach.

## Reference Implementation

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.4;

import &quot;@openzeppelin/contracts/utils/cryptography/ECDSA.sol&quot;;
import &quot;@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol&quot;;

contract CommitRegister is Initializable {
    using ECDSA for bytes32;

    mapping(string =&gt; uint[]) public commitLogs;

    event Commit(address indexed recorder, string indexed assetCid, string commitData);

    function initialize() public initializer {}

    function commit(string memory assetCid, string memory commitData) public returns (uint256 blockNumber) {
        emit Commit(msg.sender, assetCid, commitData);
        commitLogs[assetCid].push(block.number);
        return block.number;
    }

    function getCommits(string memory assetCid) public view returns (uint[] memory) {
        return commitLogs[assetCid];
    }
}
```

## Security Considerations

When implementing this EIP, it&apos;s essential to address several security aspects to ensure the safety and integrity of the digital media index:

1. Input Validation: Given that commit function accepts string parameters, it&apos;s important to validate these inputs to avoid potential injection attacks. Although such attacks are less common in smart contracts than traditional web development, caution should be exercised.

2. Data Integrity: The commit function relies on CIDs, which are assumed to be correct and point to the right data. It&apos;s important to note that this EIP doesn&apos;t validate the content behind the CIDs and the commit data, which remains a responsibility of the users or implementing applications.

3. Event Listening: Systems relying on listening to the Commit events for changes need to be aware of potential missed events or incorrect ordering, especially during periods of network congestion or reorganizations.

Implementers should consider these security aspects in the context of their specific use case and deployment scenario. It is strongly recommended to perform a comprehensive security audit before deploying any implementation of this EIP to a live network.


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 22 May 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7053</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7053</guid>
      </item>
    
      <item>
        <title>Lockable Extension for ERC-721</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7066-lockable-extension-for-erc721/14425</comments>
        
        <description>## Abstract

An extension of [ERC-721](/EIPs/EIPS/eip-721), this standard incorporates `locking` features into NFTs, allowing for various uses while preventing sale or transfer. The token&apos;s `owner` can `lock` it, setting up locker address (either an EOA or a contract) that exclusively holds the power to unlock the token. Owner can also provide approval for `tokenId`, enabling ability to lock asset while address holds the token approval. Token can also be locked by `approved`, assigning locker to itself. Upon token transfer, these rights get purged.

## Motivation

[ERC-721](/EIPs/EIPS/eip-721) has sparked an unprecedented surge in demand for NFTs. However, despite this tremendous success, the NFT economy suffers from secondary liquidity where it remains illiquid in owner’s wallet. There are projects which aim to address the liquidity challenge, but they entail the below mentioned inconveniences and risks for owners as they necessitate transferring the participating NFTs to the projects&apos; contracts.

- Loss of utility: The utility value of NFTs diminishes when they are transferred to an escrow account, no longer remaining under the direct custody of the owners.
- Lack of composability: The market could benefit from increased liquidity if NFT owners had access to multiple financial tools, such as leveraging loans and renting out their assets for maximum returns. Composability serves as the missing piece in creating a more efficient market.
- Smart contract vulnerabilities: NFTs are susceptible to loss or theft due to potential bugs or vulnerabilities present in the smart contracts they rely on.

The aforementioned issues contribute to a poor user experience (UX), and we propose enhancing the [ERC-721](/EIPs/EIPS/eip-721) standard by implementing a native locking mechanism: 
Rather than being transferred to a smart contract, an NFT remains securely stored in self-custody but is locked. 
During the lock period, the NFT&apos;s transfer is restricted while its other properties remain unchanged. 
NFT Owner retains the ability to use or distribute it’s utility.

NFTs have numerous use cases where the NFT must remain within the owner&apos;s wallet, even when it serves as collateral for a loan. Whether it&apos;s authorizing access to a Discord server, or utilizing NFT within a play-to-earn (P2E) game, owner should have the freedom to do so throughout the lending period. Just as real estate owner can continue living in their mortgaged house, take personal loan or keep tenants to generate passive income, these functionalities should be available to NFT owners to bring more investors in NFT economy.


Lockable NFTs enable the following use cases :

- NFT-collateralized loans: Utilize NFT as collateral for a loan without locking it on the lending protocol contract. Instead, lock it within owner’s wallet while still enjoying all the utility of NFT.
- No collateral rentals of NFTs: Borrow an NFT for a fee without the need for significant collateral. Renter can use the NFT but not transfer it, ensuring the lender&apos;s safety. The borrowing service contract automatically returns the NFT to the lender once the borrowing period expires.
- Buy Now Pay Later (BNPL): The buyer receives the locked NFT and can immediately begin using it. However, they are unable to sell the NFT until all installments are paid. Failure to complete the full payment results in the NFT returning to the seller, along with a fee.
- Composability: Maximize liquidity by having access to multiple financial tools. Imagine taking a loan against NFT and putting it on rentals to generate passive income.
- Primary sales: Mint an NFT for a partial payment and settle the remaining amount once owner is satisfied with the collection&apos;s progress.
- Soulbound: Organization can mint and self-assign `locker`, send token to user and lock the asset.
- Safety: Safely and conveniently use exclusive blue chip NFTs. Lockable extension allows owner to lock NFT and designate secure cold wallet as the unlocker. This way, owner can keep NFT on MetaMask and easily use it, even if a hacker gains access to MetaMask account. Without access to the cold wallet, the hacker cannot transfer NFT, ensuring its safety.

This proposal is different from other locking proposals in number of ways: 

- This implementation provides a minimal implementation of `lock` and `unlock` and believes other conditions like time-bound are great ideas but can be achieved without creating a specific implementation. Locking and Unlocking can be based on any conditions (e.g. repayment, expiry). Therefore time-bound unlocks a relatively specific use case that can be achieved via smart-contracts themselves without that being a part of the token contract.
- This implementation proposes a separation of rights between locker and approver. Token can be locked with approval and approved can unlock and withdraw tokens (opening up opportunities like renting, lending, BNPL etc), and token can be locked lacking the rights to revoke token, yet can unlock if required (opening up opportunities like account-bound NFTs).
- Our proposal implement ability to `transferAndLock` which can be used to transfer, lock and optionally approve token. Enabling the possibility of revocation after transfer.

By extending the [ERC-721](/EIPs/EIPS/eip-721) standard, the proposed standard enables secure and convenient management of underlying NFT assets. It natively supports prevalent NFTFi use cases such as staking, lending, and renting. We anticipate that this proposed standard will foster increased engagement of NFT owners in NFTFi projects, thereby enhancing the overall vitality of the NFT ecosystem.

## Specification

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

### Overview

[ERC-721](/EIPs/EIPS/eip-721) compliant contracts MAY implement this EIP to provide standard methods of locking and unlocking the token at its current owner address. 

Token owner MAY `lock` the token and assign `locker` to some `address` using `lock(uint256 tokenId, address _locker)` function, this MUST set `locker` to `_locker`. Token owner or approved MAY `lock` the token using `lock(uint256 tokenId)` function, this MUST set `locker` to `msg.sender`. Token MAY be `unlocked` by `locker` using `unlock` function. `unlock` function MUST delete `locker` mapping and default to `address(0)`.

If the token is `locked`, the `lockerOf` function MUST return an address that is `locker` and can `unlock` the token. For tokens that are not `locked`, the `lockerOf` function MUST return `address(0)`.

`lock` function MUST revert if token is already `locked`. `unlock` function MUST revert if token is not `locked`. ERC-721 `approve` function MUST revert if token is `locked`. ERC-721 functions that transfer ownership of a token MUST revert if token is `locked`, unless `msg.sender` is `approved` and `locker` both. After ERC-721 token transfer function call, values of `locker` and `approved` MUST be purged.

Token MAY be transferred and `locked`, also assign `approval` to `locker` using `transferAndLock` function. This is RECOMMENDED for use-cases where Token transfer and subsequent revocation is REQUIRED.

### Interface

```
// SPDX-License-Identifier: CC0-1.0

pragma solidity &gt;=0.7.0 &lt;0.9.0;

/// @title Lockable Extension for ERC721
/// @dev Interface for the Lockable extension
/// @author StreamNFT 

interface IERC7066{

    /**
     * @dev Emitted when tokenId is locked
     */
    event Lock (uint256 indexed tokenId, address _locker);

    /**
     * @dev Emitted when tokenId is unlocked
     */
    event Unlock (uint256 indexed tokenId);

    /**
     * @dev Lock the tokenId if msg.sender is owner or approved and set locker to msg.sender
     */
    function lock(uint256 tokenId) external;

    /**
     * @dev Lock the tokenId if msg.sender is owner and set locker to _locker
     */
    function lock(uint256 tokenId, address _locker) external;

    /**
     * @dev Unlocks the tokenId if msg.sender is locker
     */
    function unlock(uint256 tokenId) external;

    /**
     * @dev Tranfer and lock the token if the msg.sender is owner or approved. 
     *      Lock the token and set locker to caller
     *      Optionally approve caller if bool setApprove flag is true
     */
    function transferAndLock(uint256 tokenId, address from, address to, bool setApprove) external;

    /**
     * @dev Returns the wallet, that is stated as unlocking wallet for the tokenId.
     *      If address(0) returned, that means token is not locked. Any other result means token is locked.
     */
    function lockerOf(uint256 tokenId) external view returns (address);
}
```

## Rationale

This proposal set `locker[tokenId]` to `address(0)` when token is `unlocked` because we delete mapping on `locker[tokenId]` freeing up space. Also, this assertion helps our contract to validate if token is `locked` or `unlocked` for internal function calls.

This proposal exposes `transferAndLock(uint256 tokenId, address from, address to, bool setApprove)` which can be used to transfer token and lock at the receiver&apos;s address. This additionally accepts input `bool setApprove` which on `true` assign `approval` to `locker`, hence enabling `locker` to revoke the token (revocation conditions can be defined in contracts and `approval` provided to contract). This provides conditional ownership to receiver, without the privilege to `transfer` token.

## Backwards Compatibility

This standard is compatible with [ERC-721](/EIPs/EIPS/eip-721) standards.

Existing Upgradedable [ERC-721](/EIPs/EIPS/eip-721) can upgrade to this standard, enabling locking capability inherently and unlock underlying liquidity features.

## Test Cases

Test cases can be found [here](/EIPs/assets/eip-7066/test/test.js).

## Reference Implementation

Reference Interface can be found [here](/EIPs/assets/eip-7066/IERC7066.sol).

Reference Implementation can be found [here](/EIPs/assets/eip-7066/ERC7066.sol).

## Security Considerations

There are no security considerations related directly to the implementation of this standard for the contract that manages [ERC-721](/EIPs/EIPS/eip-721).

### Considerations for the contracts that work with lockable tokens

- Once `locked`, token can not be further `approved` or `transfered`.
- If token is `locked` and caller is `locker` and `approved` both, caller can transfer the token.
- `locked` token with `locker` as in-accesible account or un-verified contract address can lead to permanent lock of the token.
- There are no MEV considerations regarding lockable tokens as only authorized parties are allowed to lock and unlock.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 25 May 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7066</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7066</guid>
      </item>
    
      <item>
        <title>Revamped CALL instructions</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-revamped-call-instructions/14432</comments>
        
        <description>## Abstract

Introduce three new call instructions, `EXTCALL`, `EXTDELEGATECALL` and `EXTSTATICCALL`, with simplified semantics. Introduce another instruction, `RETURNDATALOAD` for loading a word from return data into stack. Modify the behavior of `RETURNDATACOPY` instruction executed within EOF formatted code (as defined by [EIP-3540](/EIPs/EIPS/eip-3540)). The existing `*CALL` instructions are rejected by EOF validation.

The new instructions do not allow specifying a gas limit, but rather rely on the &quot;63/64th rule&quot; ([EIP-150](/EIPs/EIPS/eip-150)) to limit gas. An important improvement is the rules around the &quot;stipend&quot; are simplified, and callers do not need to perform special calculation whether the value is sent or not. 

Furthermore, the obsolete functionality of specifying output buffer address is removed in favor of using `RETURNDATACOPY` instead. For cases which would previously `*CALL` output into a buffer and then `MLOAD` from the buffer, `RETURNDATALOAD` is provided instead.

Lastly, instead of returning a boolean for execution status, an extensible list of status codes is returned: `0` for success, `1` for revert, `2` for failure.

## Motivation

Observability of gas has been a problem for very long. The system of gas has been (and likely must be) flexible in adapting to changes to both how Ethereum is used as well as changes in underlying hardware.

Unfortunately, in many cases compromises or workarounds had to be made to avoid affecting call instructions negatively, mostly due to the complex semantics and expectations of them.

This change removes gas observability from the new instructions and opens the door for new classes of contracts that are not affected by repricings. Furthermore, the legacy call instructions are rejected within EOF contracts, making sure they are mostly unaffected by changes in gas fees. Because these operations are required for removing gas observability they are required for EOF in lieu of the existing legacy instructions.

It is important to note that starting Solidity 0.4.21, the compiler already passes all remaining gas to calls (using `call(gas(), ...`), unless the developer uses the explicit override (`{gas: ...}`) in the language. This suggests most contracts don&apos;t rely on controlling gas.

Besides the above, this change introduces a convenience feature of returning more detailed status codes: `success (0)`, `revert (1)`, `failure (2)`. This moves from the boolean option to codes, which are extensible in the future.

Lastly, the introduction of the `RETURNDATA*` instructions ([EIP-211](/EIPs/EIPS/eip-211)) has obsoleted the output parameters of calls, in a large number of cases rendering them unused. Using the output buffers have caused &quot;bugs&quot; in the past: in the case of [ERC-20](/EIPs/EIPS/eip-20), conflicting implementations caused a lot of trouble, where some would return something, while others would not. With relying on `RETURNDATA*` instructions this is implicitly clarified. This proposal also adds the &quot;missing&quot; `RETURNDATALOAD` instruction to round out returndata buffer access instructions.

## Specification

| Name | Value | Comment |
|------|-------|---------|
| WARM_STORAGE_READ_COST | 100 | From [EIP-2929](/EIPs/EIPS/eip-2929) |
| COLD_ACCOUNT_ACCESS | 2600 | From [EIP-2929](/EIPs/EIPS/eip-2929) |
| CALL_VALUE_COST | 9000 | |
| ACCOUNT_CREATION_COST | 25000 | |
| MIN_RETAINED_GAS | 5000 | |
| MIN_CALLEE_GAS | 2300 | |

We introduce four new instructions:

- `EXTCALL` (`0xf8`) with arguments `(target_address, input_offset, input_size, value)` 
- `EXTDELEGATECALL` (`0xf9`) with arguments `(target_address, input_offset, input_size)`
- `EXTSTATICCALL` (`0xfb`) with arguments `(target_address, input_offset, input_size)`
- `RETURNDATALOAD` (`0xf7`) with argument `offset`

These four new instructions are undefined in legacy code and only available in EOF code.

Execution semantics of `EXT*CALL`:

1. Charge `WARM_STORAGE_READ_COST` gas.
2. Pop required arguments from stack, halt with exceptional failure on stack underflow.
    - **NOTE**: When implemented in EOF, stack underflow check is done during stack validation and runtime check is omitted.
3. If `value` is non-zero (only `EXTCALL`):
    - Halt with exceptional failure if the current frame is in `static-mode`.
    - Charge `CALL_VALUE_COST` gas.
4. If `target_address` has any of the high 12 bytes set to a non-zero value (i.e. it does not contain a 20-byte address) then halt with an exceptional failure. 
5. Perform (and charge for) memory expansion using `[input_offset, input_size]`.
6. If `target_address` is not in the `warm_account_list`, charge `COLD_ACCOUNT_ACCESS - WARM_STORAGE_READ_COST` gas.
7. If `target_address` is not in the state and the call configuration would result in account creation, charge `ACCOUNT_CREATION_COST` gas.
    - The only such case in this EIP is if `value` is non-zero (only `EXTCALL`).
8. Calculate the gas available to callee as caller&apos;s remaining gas reduced by `max(floor(gas/64), MIN_RETAINED_GAS)`.
9. Clear the returndata buffer.
10. Fail with status code `1` returned on stack if any of the following is true (only gas charged until this point is consumed):
    - Gas available to callee at this point is less than `MIN_CALLEE_GAS`.
    - Balance of the current account is less than `value` (only `EXTCALL`).
    - Current call stack depth equals `1024`.
    - (only `EXTDELEGATECALL`) `target_address` account in the state doesn&apos;t have EOF code to execute (in particular, [EIP-7702](/EIPs/EIPS/eip-7702) delegations should be resolved, as if `EXTCALL` was used)
11. Perform the call with the available gas and configuration.
12. Push a status code on the stack:
    - `0` if the call was successful.
    - `1` if the call has reverted (also can be pushed earlier in a light failure scenario described in step 10).
    - `2` if the call has failed (in case of general OOG failure or any scenario where all gas passed to the callee is burnt in case of an error).
13. Gas not used by the callee is returned to the caller.

Execution semantics of `RETURNDATALOAD`:

1. Charge `3` gas
2. Pop 1 item from the stack, to be referred to as `offset`
3. Push 1 item onto the stack, the 32-byte word read from the returndata buffer starting at `offset`.
4. If `offset + 32 &gt; len(returndata buffer)`, the result is zero-padded.

Execution semantics of `RETURNDATACOPY` in EOF formatted code ([EIP-3540](/EIPs/EIPS/eip-3540)) is modified as follows:

1. Assume the 3 arguments popped from stack are `destOffset`, `offset` and `size`. _(no change)_
2. Performs memory expansion to `destOffset + size` and deducts memory expansion cost. _(no change)_
3. If `offset + size &gt; len(returndata buffer)` **do not** halt with exceptional failure, but instead set the `offset + size - len(returndata buffer)` memory bytes after the copied ones to zero.
4. Gas charged for memory copying remains `3 * num_words(size)`, regardless of the number of bytes actually copied or set to zero.
    
Execution of `RETURNDATACOPY` which is not in EOF formatted code (i.e. is in legacy code) is not changed.

## Rationale

### Removing gas selectability

One major change from the original `CALL` series of instructions is that the caller has no control over the amount of gas passed in as part of the call. The number of cases where such a feature is essential are probably better served by direct protocol integration.

Removing gas selectability also introduces a valuable property that future revisions to the gas schedule will benefit from: you can always overcome Out of Gas (OOG) errors by sending more gas as part of the transaction (subject to the block gas limit). Previously when raising storage costs ([EIP-1884](/EIPs/EIPS/eip-1884)) some contracts that sent only a limited amount of gas to their calls were broken by the new costing.

Hence some contracts had a gas ceiling they were sending to their next call, permanently limiting the amount of gas they could spend. No amount of extra gas could fix the issue as the call would limit the amount sent.  The notion of a stipend floor is retained in this spec. This floor can be changed independent of the smart contracts and still preserve the feature that OOG halts can be fixed by sending more gas as part of the transaction.

### Stipend and 63/64th rule

The purpose of the stipend is to have enough gas to emit logs (i.e. perform non-state-changing operations) when a &quot;contract wallet&quot; is called. The stipend is only added when the `CALL` instruction is used and the value is non-zero.

The 63/64th rule has multiple purposes:

a. to limit call depth,
b. to ensure the caller has gas left to make state changes after a callee returns.

Additionally, there is a call depth counter, and calls fail if the depth would exceed 1024.

Before the 63/64th rule was introduced, it was required to calculate available gas semi-accurately on caller side. Solidity has a complicated ruleset where it tries to estimate how much it will cost on the caller side to perform the call itself, in order to set a reasonable gas value.

We have changed the ruleset:

The 63/64th rule is still applied, but
    - At least `MIN_RETAINED_GAS` gas is retained prior to executing the callee,
    - At least `MIN_CALLEE_GAS` gas is available to the callee.

The `MIN_CALLEE_GAS` rule is a replacement for stipend: it simplifies the reasoning about the gas costs and is applied uniformly for all introduced `EXT*CALL` instructions.
The following table visualizes the differences (note the discrepancy between _caller required gas_ and _caller cost_ for `CALL`).

|                 | Caller required gas | Caller cost (burned gas) | Caller min retained gas | Callee min gas |   
|-----------------|---------------------|--------------------------|-------------------------|----------------|
| CALL V=0        | 100                 | 100                      | 0                       | 0              |
| CALL V≠0        | 100+9000            | 100+6700                 | 0                       | 2300           |
| DELEGATECALL    | 100                 | 100                      | 0                       | 0              |
| STATICCALL      | 100                 | 100                      | 0                       | 0              |
| EXTCALL V=0     | 100                 | 100                      | 5000                    | 2300           |
| EXTCALL V≠0     | 100+9000            | 100+9000                 | 5000                    | 2300           |
| EXTDELEGATECALL | 100                 | 100                      | 5000                    | 2300           |
| EXTSTATICCALL   | 100                 | 100                      | 5000                    | 2300           |

- **Caller required gas**: the minimum amount of gas a caller is required to have to execute a call instruction, lower value causes caller&apos;s OOG,
- **Caller cost (burned gas)**: the amount of gas deducted from the caller to execute the instruction, this amount is not available to the callee,
- **Caller min retained gas**: the minimum amount of gas the caller is guaranteed to have after the call, if this cannot be guaranteed the call fails without even reaching the callee,
- **Callee min gas**: the minimum gas limit for the callee&apos;s execution.

Removing the call stack depth check was initially considered, but this would be incompatible with the original `*CALL` instructions, as well as `CREATE*` instructions, which can be intertwined with the new `EXT*CALL` instructions in the call stack. As such, keeping the call stack depth check involves no change affecting legacy code.

Also, we find the simple (as opposed to the complex 63/64th rule) hard cap reassuring, that the call stack depth is limited, in case the gas rules can be bypassed. Lastly, the amount of gas to reach depth of 1024 is huge, but not absurdly huge, and we want to avoid constraining ourselves by dependency of this check on current gas limits.

### Output buffers

The functionality of specifying output buffer address is removed, because it is added complexity and in a large number of cases implementers prefer to use `RETURNDATACOPY` instead. Even if they rely on the output buffer (like in the case of Vyper), they would still check the length with `RETURNDATASIZE`. In Solidity one exception is the case when the expected return size is known (i.e. non-dynamic return values), in this case Solidity still uses the output buffer. For these cases, `RETURNDATALOAD` is introduced, which simplifies the workflow of copying returndata into a (known) output buffer and using `MLOAD` from there; instead, `RETURNDATALOAD` can be used directly.

### Status codes

Current call instructions return a boolean value to signal success: 0 means failure, 1 means success. The Solidity compiler assumed this value is a boolean and thus uses the value as branch condition to status (`if iszero(status) { /* failure */ }`). This prevents us from introducing new status codes without breaking existing contracts. At the time of the design of [EIP-211](/EIPs/EIPS/eip-211) the idea of return a specific code for revert was discussed, but ultimately abandoned for the above reason.

We change the value from boolean to a status code, where `0` signals success and thus it will be possible to introduce more non-success codes in the future, if desired.

Status code `1` is used for both reverts coming from the callee frame and light failures encountered (see step 10. of Execution Semantics) in the execution of the instructions. The reason for combining them is keeping the semantics similar to the original CALLs - both scenarios preserve unused gas and continue being indistinguishable to the caller.

Status code `2` signals an exceptional failure in the callee execution, meaning an error occurred that consumed all remaining gas in the callee frame.

### Parameter order

The order of parameters has been changed to move the `value` field to be the last. This allows the instructions to have identical encoding with the exception of the last parameter, and simplifies EVM and compiler implementations slightly.

### Opcode encoding

Instead of introducing three new `EXT*CALL` opcodes we have discussed a version with an immediate configuration byte (flags). There are two main disadvantages to this:

1. Some combination of flags may not be useful/be invalid, and this increases the testing/implementation surface.
2. The instruction could take variable number of stack items (i.e. `value` for `EXTCALL`) would be a brand new concept no other instruction has.

It is also useful to have these as new opcodes instead of modifying the existing CALL series inside of EOF. This creates an &quot;escape hatch&quot; in case gas observability needs to be restored to EOF contracts. This is done by adding the GAS and original CALL series opcodes to the valid EOF opcode list.

### `CALLCODE`

Since `CALLCODE` is deprecated, we do not introduce a counterpart here.

### Halting when `target_address` is not a 20-byte ethereum addresses  

When existing `CALL` series operations encounter an address that does not fit into 20 bytes the current behavior is to mask the address so that it fits into 20 bytes, ignoring all high bytes. For the `EXT*CALL` operations a halt was chosen over treating the contract as empty for two reasons. First, it handles the case of sending value to an address that doesn&apos;t exist without having to create a special case. Second, it keeps the `warm_access_list` from needing to track anything that is not a 20-byte ethereum address.

Smart contract developers should not rely on the operation reverting when such addresses are passed in. When a suitable proposal for the use of Address Space Extension is adopted it is expected that the `EXT*CALL` series of operations will adopt those changes.

### New instructions undefined in legacy (this EIP is part of EOF only)

Initially an alternative scenario was considered to introduce these new instructions separately in the legacy EVM first to limit the scope of EOF change, but it was decided to include it as a part of the EOF upgrade and keep them undefined in the legacy EVM.

### `RETURNDATALOAD` and `RETURNDATACOPY` padding behavior

This EIP initially proposed keeping the halt-on-OOB behavior of legacy `RETURNDATACOPY`. This makes compilers optimizations harder, because unnecessary `RETURNDATA*` instructions cannot be optimized out without change to code semantics.

It could be that only `RETURNDATALOAD` is given the padding behavior, but that would make it confusingly inconsistent with the closely related `RETURNDATACOPY` instruction.

There also was the alternative to have `RETURNDATACOPY2` introduced with the padding behavior, available in EOF only, at the same time banning `RETURNDATACOPY` in EOF. This has been rejected in order to avoid multiplying opcodes, and also as suboptimal from the point of view of compiler implementation.

### EOF1 contracts can `EXTDELEGATECALL` only EOF1 contracts

Legacy contracts can selfdestruct in three different ways (directly through `SELFDESTRUCT`, indirectly through `CALLCODE` and indirectly through `DELEGATECALL`). [EIP-3670](/EIPs/EIPS/eip-3670) disables the first two possibilities, however the third possibility remains. Allowing EOF1 contracts to `EXTDELEGATECALL` only other EOF1 contracts allows the following strong statement: EOF1 contract can never be destructed. Attacks based on `SELFDESTRUCT` completely disappear for EOF1 contracts. These include destructed library contracts (e.g. Parity Multisig).

## Backwards Compatibility

No existing instructions are changed and so we do not think any backwards compatibility issues can occur.

## Security Considerations

It is expected that the attack surface will not grow. All of these operations can be modeled by existing operations with fixed gas (all available) and output range (zero length at zero memory).

When implemented in EOF (where the GAS opcode and the original CALL operations are removed) existing out of gas attacks will be slightly more difficult, but not entirely prevented. Transactions can still pass in arbitrary gas values and clever contract construction can still result in specific gas values being passed to specific calls. It is expected the same surface will remain in EOF, but the ease of exploitation will be reduced.

The legacy `*CALL` instructions allow to pass gas available for the callee. This ability is used to prevent reentrancy attack but in case of potential future gas repricing proposal this pattern does not give this guarantee any longer. Protecting against reentrancy should be resolved by using `TSTORE/TLOAD` instructions introduced in [EIP-1153](/EIPs/EIPS/eip-1153) or other solutions which do not rely on current gas schedule.       

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 05 May 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7069</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7069</guid>
      </item>
    
      <item>
        <title>NFT Relationship Enhancement</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/introducing-new-eip-nft-relationship-standard/14468</comments>
        
        <description>## Abstract

This proposal builds on [ERC-1155](/EIPs/EIPS/eip-1155) and creates a standard for referring relationships and quantifiable attributes between non-isolated [ERC-721](/EIPs/EIPS/eip-721) or [ERC-1155](/EIPs/EIPS/eip-1155) non-fungible tokens (NFTs). It enables users to build a graph of NFTs and set quantifiable attributes for each NFT, facilitating more complex NFT ecosystems. While a similar proposal exists for [ERC-721](/EIPs/EIPS/eip-721) tokens, it does not provide a way to establish quantifiable relationships or object attributes.

## Motivation

The current standard for NFTs lacks the ability to establish relationships and attributes between tokens. This limitation makes it difficult for users to build more complex NFT ecosystems that require referring relationships and quantifiable attributes between tokens. For example, a user may create a derivative NFT that refers to the original NFT and sets a quantifiable attribute for the relationship between the two NFTs, but without a standardized way to establish relationships and attributes between NFTs, managing these ecosystems becomes increasingly difficult and inefficient.

This proposal aims to address this issue by extending the [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155) standards to include the ability to establish referring relationships and quantifiable attributes between NFTs.

By enabling users to build more complex NFT ecosystems, this proposal will enhance the NFT ecosystem and open up new possibilities for NFT use cases. However, it&apos;s important to consider potential drawbacks such as increased complexity and gas cost, and carefully design rules to mitigate these issues.

## Specification

This EIP proposes the addition of five new functions to the [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155) standards: `setRelationship`, `setAttribute`, `getRelationship`, `getAttribute`, and `getAttributeNames`. These functions allow users to establish referring relationships and set quantifiable attributes between NFTs.

### `setRelationship`

The `setRelationship` function establishes a referring relationship between two NFTs. It takes the following parameters:

```solidity
function setRelationship(uint256 _originalID, uint256 _derivativeID, uint256 _attribute) external;
```

- `_originalID`: the ID of the original NFT
- `_derivativeID`: the ID of the derivative NFT that refers to the original NFT
- `_attribute`: the quantifiable attribute for this relationship, which defaults to 1 if not specified

When called, this function establishes a referring relationship between the two NFTs.

### `setAttribute`

The `setAttribute` function sets a quantifiable attribute for an NFT. It takes the following parameters:

```solidity
function setAttribute(uint256 _id, string calldata _name, uint256 _value) external;
```

- `_id`: the ID of the NFT
- `_name`: the name of the attribute to be set
- `_value`: the value of the attribute to be set

When called, this function sets a quantifiable attribute for the NFT.

### `getAttribute`

The `getAttribute` function allows anyone to retrieve the value of a specific attribute associated with an NFT. It takes the following parameters:

```solidity
function getAttribute(uint256 _id, string calldata _name) external view returns (bytes32);
```

- `_id`: The ID of the NFT for which you want to retrieve the attribute.
- `_name`: The name of the attribute you wish to retrieve.

This function returns the value of the specified attribute as a bytes32 data type.

### `getAttributeNames`

The getAttributeNames function allows anyone to retrieve the names of all attributes associated with an NFT. It takes the following parameter:

```solidity
function getAttributeNames(uint256 _id) external view returns (bytes32[] memory);
```

- `_id`: The ID of the NFT for which you want to retrieve the attribute names.

This function returns an array of bytes32 values representing the names of all attributes associated with the specified NFT.

### `getRelationship`

The `getRelationship` function allows anyone to retrieve the value of a referring relationship between two NFTs. It takes the following parameters:

```solidity
function getRelationship(uint256 _originalID, uint256 _derivativeID) external view returns (uint256);
```

- `_originalID`: The ID of the original NFT.
- `_derivativeID`: The ID of the derivative NFT that refers to the original NFT.

This function returns the value of the referring relationship between the two NFTs as a uint256 data type.

### Example Usage

```solidity
NFTGraph nftContract = NFTGraph(addressOfContract);

// Retrieve the value of an attribute named &quot;Color&quot; for NFT with ID 123
bytes32 colorValue = nftContract.getAttribute(123, &quot;Color&quot;);

// Retrieve the names of all attributes associated with NFT with ID 456
bytes32[] memory attributeNames = nftContract.getAttributeNames(456);
```

By including these functions and methods in the specification, you establish a clear and standardized way for users and developers to read attributes associated with NFTs.

## Rationale

In developing this EIP, some key design decisions were made. For example, we limited the complexity of the relationship graph that can be created by only allowing for one referring relationship between two NFTs. This helps to ensure that the graph remains manageable and does not become too complex to be useful. Additionally, we kept the gas cost of setting attributes to a minimum by only allowing for one attribute to be set at a time.

While there are currently no similar features in other blockchain languages or standards, we drew inspiration from the concept of Graph Theory, which is a branch of mathematics that studies the relationships between objects. By adding the ability to establish relationships between NFTs and set quantifiable attributes for those relationships, we believe that the extended NFT standard will become even more useful and versatile for NFT creators and users.

## Backwards Compatibility

This EIP is designed to be fully backward-compatible with existing [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155) contracts and tokens. Existing NFT contracts and tokens will continue to function as they did before, and the new `setRelationship` and `setAttribute` functions will only be available to contracts that explicitly implement this EIP.

## Reference Implementation

To assist in understanding and implementing this proposal, we provide a reference Solidity interface and contract that define the functions for establishing relationships and reading attributes. Developers can use this interface as a foundation for integrating the NFT Relationship Enhancement into their own contracts.

### [ERC-165](/EIPs/EIPS/eip-165) Interface Support

The NFT Relationship Enhancement contract implements the ERC-165 standard interface to allow for interface detection. This enables smart contracts and applications to check if a given contract supports the functions defined in this proposal before interacting with it.

### INFTGraph Interface

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/token/ERC165/IERC165.sol&quot;;  // Import IERC165 for interface detection

interface INFTGraph is IERC165 {
    // setRelationship: Establishes relationships between NFTs.
    function setRelationship(uint256 _originalID, uint256 _derivativeID, uint256 _attribute) external;
    // setAttribute: Sets quantifiable attributes for NFTs.
    function setAttribute(uint256 _id, string calldata _name, uint256 _value) external;
    // getRelationship: Retrieves relationship values between NFTs.
    function getRelationship(uint256 _originalID, uint256 _derivativeID) external view returns (uint256);
    // getAttribute: Retrieves the value of specific attributes associated with NFTs.
    function getAttribute(uint256 _id, string calldata _name) external view returns (bytes32);
    // getAttributeNames: Retrieves all attribute names associated with an NFT.
    function getAttributeNames(uint256 _id) external view returns (bytes32[] memory);
}
```

The INFTGraph interface specifies the functions for setting relationships and attributes, as well as retrieving attribute information and relationship values.

### NFTGraph Contract

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/introspection/ERC165.sol&quot;;  // Import ERC165 for interface detection

import &quot;./INFTGraph.sol&quot;;  // Import INFTGraph interface

contract NFTGraph is INFTGraph{
    mapping(uint256 =&gt; mapping(uint256 =&gt; uint256)) public relationship;
    mapping(uint256 =&gt; mapping(bytes32 =&gt; bytes32)) public attributes;

    // Implement the setRelationship and setAttribute functions as described in the EIP specification.


    // Implement the supportsInterface function for ERC-165.
    function supportsInterface(bytes4 interfaceID) public view override returns (bool) {
        return interfaceID == type(INFTGraph).interfaceId || super.supportsInterface(interfaceID);
    }

    // Additional implementation details...
    function getRelationship(uint256 _originalID, uint256 _derivativeID) external view returns (uint256) {
        return relationship[_originalID][_derivativeID];
    }

    function getAttribute(uint256 _id, string calldata _name) external view returns (bytes32) {
        return bytes32(attributes[_id][_name]);
    }

    function getAttributeNames(uint256 _id) external view returns (bytes32[] memory) {
        bytes32[] memory names = new bytes32[](attributes[_id].length);
        for (uint256 i = 0; i &lt; attributes[_id].length; i++) {
            names[i] = bytes32(attributes[_id][i]);
        }
        return names;
    }

    function setRelationship(uint256 originalNFT, uint256 derivativeNFT, uint256 relationshipValue) public {
        require(originalNFT != derivativeNFT, &quot;Original and derivative NFTs must be different&quot;);
        relationship[originalNFT][derivativeNFT] = relationshipValue;
    }
    
    function setAttribute(uint256 nft, bytes32 attributeName, bytes32 attributeValue) public {
        attributes[nft][attributeName] = attributeValue;
    }

}
```

The NFTGraph contract implements the functions specified in the INFTGraph interface and provides storage for relationships and attributes.

Developers can use this reference interface and contract as a starting point for integrating the NFT Relationship Enhancement functionality into their own projects.
The interface provides a clear and standardized way to interact with the contract, promoting consistency and ease of integration.

## Security Considerations

When implementing this proposal, contract developers should consider the following security aspects:

1. **Validation of Relationships**: Contracts utilizing the setRelationship function must ensure that the relationships being established are valid and authorized by the relevant parties. Unauthorized or malicious relationships could lead to unintended consequences.
2. **Attribute Validation**: Contracts implementing the setAttribute function should carefully validate attributes to prevent malicious or harmful values. Invalid or unvalidated attributes could disrupt the functionality of the NFT ecosystem.
3. **Access Control**: Contracts should implement appropriate access control mechanisms to restrict who can call critical functions, especially those that modify relationships or attributes. Unauthorized access can lead to misuse or exploitation.
4. **Reentrancy Protection**: Consider adding reentrancy protection mechanisms to functions that modify relationships or attributes. Reentrancy attacks could otherwise be exploited to manipulate contract behavior.

By addressing these considerations, developers can enhance the security of their contracts and protect the integrity of the NFT ecosystem.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 02 May 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7085</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7085</guid>
      </item>
    
      <item>
        <title>MIME type for Web3 URL in Auto Mode</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7087-mime-type-for-web3-url-in-auto-mode/14471</comments>
        
        <description>## Abstract

This standard extends the [ERC-6860](/EIPs/EIPS/eip-6860) `web3://` standard: in smart contracts not designed for `web3://` (thus using auto mode), the MIME type of the returned data is either implicit (not advertised by the smart contract) or included within the returned data ([RFC 2397](https://www.rfc-editor.org/rfc/rfc2397) data URLs). This standard defines additional query parameters so that a MIME type can be returned when fetching a `web3://` URL in these scenarios.


## Motivation

When returning data to the web browser, a `Content-Type` header indicating the MIME type of the data is strongly recommended, or the data may be incorrectly interpreted and displayed by the web browser.

The `web3://` protocol has 2 modes: manual and auto. 

- The manual mode is used on smart contracts explicitly requesting this mode (via an interface), so they are expected to signal the MIME type of the returned data, with the mechanism described in [ERC-6860](/EIPs/EIPS/eip-6860). 
- On the other hand, the auto mode is used on both smart contracts specifically requesting the mode, and for all the others not signalling anything. While we can expect smart contracts explicitly requesting auto mode to signal the MIME type of the returned data, we cannot expect it for the others contracts.

This standard aims at filling this gap: with the introduction of additional query parameters, it will allow the URL to specify the MIME type of the returned data. Additionally, when the returned data is a [RFC 2397](https://www.rfc-editor.org/rfc/rfc2397) data URL, it will allow the URL to flag the returned data as data URL, so that the protocol can return the decoded data, and accompany it with the MIME type advertised in the data URL.

## Specification

The standard introduces three query parameters to determine the MIME type.

- `mime.content=&lt;contentType&gt;`, where `&lt;contentType&gt;` is a MIME type defined in [RFC 6838](https://www.rfc-editor.org/rfc/rfc6838). If the `&lt;contentType&gt;` does not follow the structure of a MIME type, the URL is not fetched and an error message is displayed to the user. After URL decoding, `&lt;contentType&gt;` is set as the value of the `Content-Type` header of the response; or
- `mime.type=&lt;fileType&gt;`, where `&lt;fileType&gt;` is a filename extension from which a MIME type is determined. If the filename extension is not recognized, the URL is not fetched and an error message is displayed to the user. The MIME type is then set as the value of the `Content-Type` header of the response; or
- `mime.dataurl`, which indicates to decode the returned bytes as a [RFC 2397](https://www.rfc-editor.org/rfc/rfc2397) data URL. After decoding, the decoded body will be returned as the main output, and the MIME type specified in the data URL will be used. If the data cannot be parsed as data URL, an error will be returned.


  
If multiple query parameters are present, the last query parameter will be applied.  If none of the query parameter is specified, `Content-Type` is defined by [ERC-6860](/EIPs/EIPS/eip-6860).  If the `returns` query parameter is specified, the `mime.xxx` parameters will be ignored and the `Content-Type` will be defined by [ERC-6860](/EIPs/EIPS/eip-6860).

In [RFC 2234](https://www.rfc-editor.org/rfc/rfc2234) ABNF notation, the [ERC-6860](/EIPs/EIPS/eip-6860) syntax is :

```
attribute       = attrName &quot;=&quot; attrValue
attrName        = &quot;returns&quot;
                / &quot;returnTypes&quot;
attrValue       = [ &quot;(&quot; [ retTypes ] &quot;)&quot; ]
```

This standard evolves it into: 

```
attribute       = retAttr / mimeCAttr / mimeTAttr / mimeDAttr
retAttr         = retAttrName &quot;=&quot; retAttrValue
retAttrName     = &quot;returns&quot;
                / &quot;returnTypes&quot;
retAttrValue    = [ &quot;(&quot; [ retTypes ] &quot;)&quot; ]

mimeCAttr       = &quot;mime.content=&quot; mimeCAttrVal
mimeCAttrVal    = # ABNF of MIME type as in RFC 6838 
mimeTAttr       = &quot;mime.type=&quot; 1*( ALPHA / DIGIT )
mimeDAttr       = &quot;mime.dataurl&quot;
```

### Examples

#### Example 1

```
web3://0x91cf36c92feb5c11d3f5fe3e8b9e212f7472ec14/accessorizedImageOf/1289?mime.content=image/svg%2Bxml
```

where the contract is in auto mode.

The protocol will call the contract `0x91cf36c92feb5c11d3f5fe3e8b9e212f7472ec14` with the message defined in [ERC-6860](/EIPs/EIPS/eip-6860) and the returned `Content-Type` header will be set to `image/svg+xml`.

#### Example 2

```
web3://0x91cf36c92feb5c11d3f5fe3e8b9e212f7472ec14/accessorizedImageOf/1289?mime.type=svg
```

where the contract is in auto mode.

The protocol will call the contract `0x91cf36c92feb5c11d3f5fe3e8b9e212f7472ec14` with the message defined in [ERC-6860](/EIPs/EIPS/eip-6860) and the returned `Content-Type` header will be set to `image/svg+xml`.

#### Example 3

```
web3://0xff9c1b15b16263c61d017ee9f65c50e4ae0113d7/tokenURI/100?mime.dataurl
```

where the contract is in auto mode, and the returned data is `data:application/json,[&quot;xx&quot;]`.

The protocol will call the contract `0xff9c1b15b16263c61d017ee9f65c50e4ae0113d7` with the message defined in [ERC-6860](/EIPs/EIPS/eip-6860) and decode the data according to the [RFC 2397](https://www.rfc-editor.org/rfc/rfc2397) data URL standard. The returned output will be ``[&quot;xx&quot;]`` and the returned `Content-Type` header will be set to `application/json`.


## Rationale

The standard uses three different query parameters rather than a single query parameter to avoid confusion - an implementer or a user can easily tell the expected returned MIME of a link.  Further, in auto mode, the query parameters are not used to form the EVM message (e.g., calldata) and thus it is safe to introduce new query parameters.

## Security Considerations

These new query parameters introduce Cross Site Scripting attack vectors : an attacker could exploit string or bytes returning methods he can influence by making them return unfiltered data injected by him, and then craft a URL to make the returned data interpreted as HTML, and then send the URL to victims. If the web3 hostname is well known, the victim may get a false sense of security.

Malicious actions using javascript are broad and can include : 

- Extraction of data of web storage APIs (cookies, localStorage, sessionStorage, indexedDB), sent to the attacker
- Triggering a signature request or transaction confirmation request (via a wallet javascript interface)

Cross Site Scripting is a classical attack vector in HTTP websites, we expect developers to be wary of this. Nonetheless; the ability to specify the MIME type is unusual. `auto` mode websites should be discouraged and the attack vectors well documented.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 28 May 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7087</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7087</guid>
      </item>
    
      <item>
        <title>Financial Bonds</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/financial-bonds/14461</comments>
        
        <description>## Abstract

This proposal introduces fixed-income financial bonds with key characteristics defined to facilitate bond issuance in the primary market and enable buying or selling bonds in the secondary market. The standard also provides cross-chain functionalities for bonds operations and management across multiple blockchains.

## Motivation

Fixed-income instruments are a widely utilized asset class for corporations and other entities raising funds. However, transitioning to tokenized bonds is challenging due to existing standards like [ERC-3475](/EIPs/EIPS/eip-3475), which introduces unfamiliar concepts and leads to unnecessary gas consumption. Additionally, the lack of named variables like coupon, maturity date, and principal, makes it difficult to implement ERC-3475 since developers need to remember which metadata is assigned to each parameter.

## Specification

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

**Every contract compliant with this ERC MUST implement the following Token Interface as well as the [ERC-165](/EIPs/EIPS/eip-165) interface:**

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

/**
* @title ERC-7092 Financial Bonds Standard
*/
interface IERC7092 /** is ERC165 */ {
    // events
    /**
    * @notice MUST be emitted when bond tokens are transferred, issued or redeemed, except during contract creation
    * @param _from the account that owns bonds
    * @param _to the account that receives the bond
    * @param _amount amount of bond tokens to be transferred
    */
    event Transfer(address indexed _from, address indexed _to, uint256 _amount);

    /**
    * @notice MUST be emitted when an account is approved or when the allowance is decreased
    * @param _owner bond token&apos;s owner
    * @param _spender the account to be allowed to spend bonds
    * @param _amount amount of bond tokens allowed by _owner to be spent by `_spender`
    *        Or amount of bond tokens to decrease allowance from `_spender`
    */
    event Approval(address indexed _owner, address indexed _spender, uint256 _amount);

    /**
    * @notice MUST be emitted when multiple bond tokens are transferred, issued or redeemed, with the exception being during contract creation
    * @param _from array of bondholders accounts
    * @param _to array of accounts to transfer bonds to
    * @param _amount array of amounts of bond tokens to be transferred
    *
    ** OPTIONAL - interfaces and other contracts MUST NOT expect this function to be present. MUST be emitted in `batchTransfer` and `batchTransferFrom` functions
    */
    event TransferBatch(address[] _from, address[] _to, uint256[] _amount);

    /**
    * @notice MUST be emitted when multiple accounts are approved or when the allowance is decreased from multiple accounts
    * @param _owner bondholder account
    * @param _spender array of accounts to be allowed to spend bonds, or to decrase the allowance from
    * @param _amount array of amounts of bond tokens allowed by `_owner` to be spent by multiple accounts in `_spender`.
    *
    ** OPTIONAL - interfaces and other contracts MUST NOT expect this function to be present. MUST be emitted in `batchApprove` and `batchDecreaseAllowance` functions
    */
    event ApprovalBatch(address indexed _owner, address[] _spender, uint256[] _amount);

    // getter functions
    /**
    *  @notice Returns the bond isin
    */
    function isin() external view returns(string memory);

    /**
    * @notice Returns the bond name
    */
    function name() external view returns(string memory);

    /**
    * @notice Returns the bond symbol
    *         It is RECOMMENDED to represent the symbol as a combination of the issuer Issuer&apos;shorter name and the maturity date
    *         Ex: If a company named Green Energy issues bonds that will mature on october 25, 2030, the bond symbol could be `GE30` or `GE2030` or `GE102530`
    */
    function symbol() external view returns(string memory);

    /**
    * @notice Returns the bond currency. This is the contract address of the token used to pay and return the bond principal
    */
    function currency() external view returns(address);

    /**
    * @notice Returns the bond denominiation. This is the minimum amount in which the Bonds may be issued. It must be expressend in unit of the principal currency
    *         ex: If the denomination is equal to 1,000 and the currency is USDC, then the bond denomination is equal to 1,000 USDC
    */
    function denomination() external view returns(uint256);

    /**
    * @notice Returns the issue volume (total debt amount). It is RECOMMENDED to express the issue volume in denomination unit.
    */
    function issueVolume() external view returns(uint256);

    /**
    * @notice Returns the bond interest rate. It is RECOMMENDED to express the interest rate in basis point unit.
    *         1 basis point = 0.01% = 0.0001
    *         ex: if interest rate = 5%, then coupon() =&gt; 500 basis points
    */
    function couponRate() external view returns(uint256);

    /**
    * @notice Returns the date when bonds were issued to investors. This is a Unix Timestamp like the one returned by block.timestamp
    */
    function issueDate() external view returns(uint256);

    /**
    * @notice Returns the bond maturity date, i.e, the date when the principal is repaid. This is a Unix Timestamp like the one returned by block.timestamp
    *         The maturity date MUST be greater than the issue date
    */
    function maturityDate() external view returns(uint256);

    /**
    * @notice Returns the principal of an account. It is RECOMMENDED to express the principal in the bond currency unit (USDC, DAI, etc...)
    * @param _account account address
    */
    function principalOf(address _account) external view returns(uint256);

    /**
    * @notice Returns the amount of tokens the `_spender` account has been authorized by the `_owner``
    *         account to manage their bonds
    * @param _owner the bondholder address
    * @param _spender the address that has been authorized by the bondholder
    */
    function allowance(address _owner, address _spender) external view returns(uint256);

    // setter functions
    /**
    * @notice Authorizes `_spender` account to manage `_amount`of their bond tokens
    * @param _spender the address to be authorized by the bondholder
    * @param _amount amount of bond tokens to approve
    */
    function approve(address _spender, uint256 _amount) external returns(bool);

    /**
    * @notice Lowers the allowance of `_spender` by `_amount`
    * @param _spender the address to be authorized by the bondholder
    * @param _amount amount of bond tokens to remove from allowance
    */
    function decreaseAllowance(address _spender, uint256 _amount) external returns(bool);

    /**
    * @notice Moves `_amount` bonds to address `_to`. This methods also allows to attach data to the token that is being transferred
    * @param _to the address to send the bonds to
    * @param _amount amount of bond tokens to transfer
    * @param _data additional information provided by the token holder
    */
    function transfer(address _to, uint256 _amount, bytes calldata _data) external returns(bool);

    /**
    * @notice Moves `_amount` bonds from an account that has authorized the caller through the approve function
    *         This methods also allows to attach data to the token that is being transferred
    * @param _from the bondholder address
    * @param _to the address to transfer bonds to
    * @param _amount amount of bond tokens to transfer.
    * @param _data additional information provided by the token holder
    */
    function transferFrom(address _from, address _to, uint256 _amount, bytes calldata _data) external returns(bool);

    // batch functions
    /**
    * @notice Authorizes multiple spender accounts to manage a specified `_amount` of the bondholder tokens
    * @param _spender array of accounts to be authorized by the bondholder
    * @param _amount array of amounts of bond tokens to approve
    *
    * OPTIONAL - interfaces and other contracts MUST NOT expect these values to be present. The method is used to improve usability.
    */
    function batchApprove(address[] calldata _spender, uint256[] calldata _amount) external returns(bool);

    /**
    * @notice Decreases the allowance of multiple spenders by corresponding amounts in `_amount`
    * @param _spender array of accounts to be authorized by the bondholder
    * @param _amount array of amounts of bond tokens to decrease the allowance from
    *
    * OPTIONAL - interfaces and other contracts MUST NOT expect this function to be present. The method is used to decrease token allowance.
    */
    function batchDecreaseAllowance(address[] calldata _spender, uint256[] calldata _amount) external returns(bool);

    /**
    * @notice Transfers multiple bonds with amounts specified in the array `_amount` to the corresponding accounts in the array `_to`, with the option to attach additional data
    * @param _to array of accounts to send the bonds to
    * @param _amount array of amounts of bond tokens to transfer
    * @param _data array of additional information provided by the token holder
    *
    * OPTIONAL - interfaces and other contracts MUST NOT expect this function to be present.
    */
    function batchTransfer(address[] calldata _to, uint256[] calldata _amount, bytes[] calldata _data) external returns(bool);

    /**
    * @notice Transfers multiple bonds with amounts specified in the array `_amount` to the corresponding accounts in the array `_to` from an account that have been authorized by the `_from` account
    *         This method also allows to attach data to tokens that are being transferred
    * @param _from array of bondholder accounts
    * @param _to array of accounts to transfer bond tokens to
    * @param _amount array of amounts of bond tokens to transfer.
    * @param _data array of additional information provided by the token holder
    *
    ** OPTIONAL - interfaces and other contracts MUST NOT expect this function to be present.
    */
    function batchTransferFrom(address[] calldata _from, address[] calldata _to, uint256[] calldata _amount, bytes[] calldata _data) external returns(bool);
}
```

### Additional bond parameters Interface

The `IERC7092ESG` interface is OPTIONAL for contracts implementing this proposal. This interface MAY be used to improve the standard usability.

- The `currencyOfCoupon` The currency used for coupon payment may be different from the currency used to repay the principal
- The `couponType` MAY be employed to signify the interest rate that the issuer has committed to paying to investors, which may take various forms such as zero coupon, fixed rate, floating rate, and more.
- The `couponFrequency` refers to how often the bond pays interest to its bondholders, and is typically expressed in terms of time periods, such as: Annual, Semi-Annual, Quarterly, or Monthly.
- The `dayCountBasis` is used to calculate the accrued interest on a bond between two coupon payment dates or other specific periods. Some of the day count basis are: Actual/Actual, 30/360, Actual/360, Actual/365, or 30/365

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

interface IERC7092ESG /** is ERC165 */ {
    /**
    * @notice Returns the number of decimals used by the bond. For example, if it returns `10`, it means that the token amount MUST be multiplied by 10000000000 to get the standard representation.
    */
    function decimals() external view returns(uint8);

    /**
    * @notice Rreturns the coupon currency, which is represented by the contract address of the token used to pay coupons. It can be the same as the one used for the principal
    */
    function currencyOfCoupon() external view returns(address);

    /**
    * @notice Returns the coupon type
    *         For example, 0 can denote Zero coupon, 1 can denote Fixed Rate, 2 can denote Floating Rate, and so on
    */
    function couponType() external view returns(uint8);

    /**
    * @notice Returns the coupon frequency, i.e. the number of times coupons are paid in a year.
    */
    function couponFrequency() external view returns(uint256);

    /**
    * @notice Returns the day count basis
    *         For example, 0 can denote actual/actual, 1 can denote actual/360, and so on
    */
    function dayCountBasis() external view returns(uint8);
}
```

### Cross-chain Interface

The standard permits the implementation of the `IERC7092CrossChain` interface for cross-chain management of bond tokens. This interface is OPTIONAL and may be used by applications to allow cross-chain transactions. Any function initiating a cross-chain transaction MUST explicitly define the destination chain identifier `destinationChainID` and specify the target smart contract `destinationContract`.

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

interface IERC7092CrossChain /** is ERC165 */ {
    // events
    /**
    * @notice MUST be emitted when bond tokens are transferred or redeemed in a cross-chain transaction
    * @param _from bondholder account
    * @param _to account the transfer bond tokens to
    * @param _amount amount of bond tokens to be transferred
    * @param _destinationChainID The unique ID that identifies the destination Chain
    */
    event CrossChainTransfer(address indexed _from, address indexed _to, uint256 _amount, bytes32 _destinationChainID);

    /**
    * @notice MUST be emitted when several bond tokens are transferred or redeemed in a cross-chain transaction
    * @param _from array of bondholders accounts
    * @param _to array of accounts that receive the bond
    * @param _amount array of amount of bond tokens to be transferred
    * @param _destinationChainID array of unique IDs that identify the destination Chain
    */
    event CrossChainTransferBatch(address[] _from, address[] _to, uint256[] _amount, bytes32[] _destinationChainID);

    /**
    * @notice MUST be emitted when an account is approved to spend the bondholder&apos;s tokens in a different chain than the current chain
    * @param _owner the bondholder account
    * @param _spender the account to be allowed to spend bonds
    * @param _amount amount of bond tokens allowed by `_owner` to be spent by `_spender`
    * @param _destinationChainID The unique ID that identifies the destination Chain
    */
    event CrossChainApproval(address indexed _owner, address indexed _spender, uint256 _amount, bytes32 _destinationChainID);

    /**
    * @notice MUST be emitted when multiple accounts in the array `_spender` are approved or when the allowances of multiple accounts in the array `_spender` are reduced on the destination chain which MUST be different than the current chain
    * @param _owner bond token&apos;s owner
    * @param _spender array of accounts to be allowed to spend bonds
    * @param _amount array of amount of bond tokens allowed by _owner to be spent by _spender
    * @param _destinationChainID array of unique IDs that identify the destination Chain
    */
    event CrossChainApprovalBatch(address indexed _owner, address[] _spender, uint256[] _amount, bytes32[] _destinationChainID);

    // functions
    /**
    * @notice Authorizes the `_spender` account to manage a specified `_amount`of the bondholder bond tokens on the destination Chain
    * @param _spender account to be authorized by the bondholder
    * @param _amount amount of bond tokens to approve
    * @param _destinationChainID The unique ID that identifies the destination Chain.
    * @param _destinationContract The smart contract to interact with in the destination Chain
    */
    function crossChainApprove(address _spender, uint256 _amount, bytes32 _destinationChainID, address _destinationContract) external returns(bool);

    /**
    * @notice Authorizes multiple spender accounts in `_spender` to manage specified amounts in `_amount` of the bondholder tokens on the destination chain
    * @param _spender array of accounts to be authorized by the bondholder
    * @param _amount array of amounts of bond tokens to approve
    * @param _destinationChainID array of unique IDs that identifies the destination Chain.
    * @param _destinationContract array of smart contracts to interact with in the destination Chain in order to Deposit or Mint tokens that are transferred.
    */
    function crossChainBatchApprove(address[] calldata _spender, uint256[] calldata _amount, bytes32[] calldata _destinationChainID, address[] calldata _destinationContract) external returns(bool);

    /**
    * @notice Decreases the allowance of `_spender` by a specified `_amount` on the destination Chain
    * @param _spender the address to be authorized by the bondholder
    * @param _amount amount of bond tokens to remove from allowance
    * @param _destinationChainID The unique ID that identifies the destination Chain.
    * @param _destinationContract The smart contract to interact with in the destination Chain in order to Deposit or Mint tokens that are transferred.
    */
    function crossChainDecreaseAllowance(address _spender, uint256 _amount, bytes32 _destinationChainID, address _destinationContract) external returns(bool);

    /**
    * @notice Decreases the allowance of multiple spenders in `_spender` by corresponding amounts specified in the array `_amount` on the destination chain
    * @param _spender array of accounts to be authorized by the bondholder
    * @param _amount array of amounts of bond tokens to decrease the allowance from
    * @param _destinationChainID array of unique IDs that identifies the destination Chain.
    * @param _destinationContract array of smart contracts to interact with in the destination Chain in order to Deposit or Mint tokens that are transferred.
    */
    function crossChainBatchDecreaseAllowance(address[] calldata _spender, uint256[] calldata _amount, bytes32[] calldata _destinationChainID, address[] calldata _destinationContract) external returns(bool);

    /**
    * @notice Moves `_amount` bond tokens to the address `_to` from the current chain to another chain (e.g., moving tokens from Ethereum to Polygon).
    *         This methods also allows to attach data to the token that is being transferred
    * @param _to account to send bond tokens to
    * @param _amount amount of bond tokens to transfer
    * @param _data additional information provided by the bondholder
    * @param _destinationChainID The unique ID that identifies the destination Chain.
    * @param _destinationContract The smart contract to interact with in the destination Chain in order to Deposit or Mint bond tokens that are transferred.
    */
    function crossChainTransfer(address _to, uint256 _amount, bytes calldata _data, bytes32 _destinationChainID, address _destinationContract) external returns(bool);

    /**
    * @notice Transfers multiple bond tokens with amounts specified in the array `_amount` to the corresponding accounts in the array `_to` from the current chain to another chain (e.g., moving tokens from Ethereum to Polygon).
    *         This methods also allows to attach data to the token that is being transferred
    * @param _to array of accounts to send the bonds to
    * @param _amount array of amounts of bond tokens to transfer
    * @param _data array of additional information provided by the bondholder
    * @param _destinationChainID array of unique IDs that identify the destination Chains.
    * @param _destinationContract array of smart contracts to interact with in the destination Chains in order to Deposit or Mint bond tokens that are transferred.
    */
    function crossChainBatchTransfer(address[] calldata _to, uint256[] calldata _amount, bytes[] calldata _data, bytes32[] calldata _destinationChainID, address[] calldata _destinationContract) external returns(bool);

    /**
    * @notice Transfers `_amount` bond tokens from the `_from`account to the `_to` account from the current chain to another chain. The caller must be approved by the `_from` address.
    *         This methods also allows to attach data to the token that is being transferred
    * @param _from the bondholder address
    * @param _to the account to transfer bonds to
    * @param _amount amount of bond tokens to transfer
    * @param _data additional information provided by the token holder
    * @param _destinationChainID The unique ID that identifies the destination Chain.
    * @param _destinationContract The smart contract to interact with in the destination Chain in order to Deposit or Mint tokens that are transferred.
    */
    function crossChainTransferFrom(address _from, address _to, uint256 _amount, bytes calldata _data, bytes32 _destinationChainID, address _destinationContract) external returns(bool);

    /**
    * @notice Transfers several bond tokens with amounts specified in the array `_amount` from accounts in the array `_from` to accounts in the array `_to` from the current chain to another chain.
    *         The caller must be approved by the `_from` accounts to spend the corresponding amounts specified in the array `_amount`
    *         This methods also allows to attach data to the token that is being transferred
    * @param _from array of bondholder addresses
    * @param _to array of accounts to transfer bonds to
    * @param _amount array of amounts of bond tokens to transfer
    * @param _data array of additional information provided by the token holder
    * @param _destinationChainID array of unique IDs that identifies the destination Chain.
    * @param _destinationContract array of smart contracts to interact with in the destination Chain in order to Deposit or Mint tokens that are transferred.
    */
    function crossChainBatchTransferFrom(address[] calldata _from, address[] calldata _to, uint256[] calldata _amount, bytes[] calldata _data, bytes32[] calldata _destinationChainID, address[] calldata _destinationContract) external returns(bool);
}
```

## Rationale

The design of this ERC aims to simplify the migration to tokenized bonds by maintaining consistency with traditional bond standards. This approach allows fixed-income instruments to be represented as on-chain tokens, manageable through wallets, and utilized by applications like decentralized exchanges, while avoiding the complexities and inefficiencies associated with other standards. This ERC facilitates the creation of new bond tokens with characteristics akin to traditional bonds, enhancing accessibility, liquidity, and cost-efficiency in bond trading and management.

The use of traditional finance terminology, like `issueVolume` and `principalOf`, is aimed at maintaining consistency with traditional bond language, which eases the adaptation for traditional entities.

### Total Supply and Account Balance

The `totalSupply` and `balanceOf` functions are not defined as they can be derived from `issueVolume` and `principalOf`, and `denomination`. However, these functions can be be added in any contract implementing this standard, ensuring the proper relationship between these values.

```solidity
    function totalSupply() external view returns(uint256) {
        return issueVolume() / denomination();
    }

    function balance0f(account) external view returns(uint256) {
        return principal(account) / denomination();
    }
```

## Backwards Compatibility

This ERC is not backwards compatible with existing standards like [ERC-20](/EIPs/EIPS/eip-20) or [ERC-1155](/EIPs/EIPS/eip-1155) due to the absence of certain functions like `totalSupply` or `balanceOf`. A pure implementation of this standard is RECOMMENDED for issuing tokenized bonds, as any hybrid solution with other mentioned standards SHOULD fail.


## Reference Implementation

The complete Reference Implementation can be found [here](/EIPs/assets/eip-7092/ERC7092.sol).

Bonds with embedded options like callable, puttable, or convertible bonds can be created by inheriting from the reference [`ERC7092.sol`](/EIPs/assets/eip-7092/ERC7092.sol) that integrates the proposed interface.

### CALLABLE BONDS:

```solidity
pragma solidity ^0.8.0;

import &apos;ERC7092.sol&apos;;

contract ERC7092Callable is ERC7092 {
    // WRITE THE LOGIC TO ALLOW THE ISSUER TO CALL BONDS
    // STATE VARIABLES AND FUNCTIONS NEEDED
    
    /**
    * @notice call bonds owned by `_investor`
    *         MUST be called by the issuer only
    */
    function call(address _investor) public {
        require(msg.sender == _issuer[bondISIN].issuerAddress, &quot;ERC7092Callable: ONLY_ISSUER&quot;);
        require(_principals[_investor] &gt; 0, &quot;ERC7092Callable: NO_BONDS&quot;);
        require(block.timestamp &lt; _bond[bondISIN].maturityDate, &quot;ERC7092Callable: BOND_MATURED&quot;);
        
        uint256 principal =  _principals[_investor];
        _principals[_investor] = 0;
        
        // ADD LOGIC HERE
    }
}
```

### PUTTABLE BONDS:

```solidity
pragma solidity ^0.8.0;

import &apos;ERC7092.sol&apos;;

contract ERC7092Puttable is ERC7092 {
    // WRITE THE LOGIC TO ALLOW INVESTORS TO PUT BONDS
    // STATE VARIABLES AND FUNCTIONS NEEDED
    
    /**
    * @notice put bonds
    *         MUST be called by investors who own bonds
    */
    function put() public {
        require(_principals[msg.sender] &gt; 0, &quot;ERC7092Puttable: ONLY_INVESTORS&quot;);
        require(block.timestamp &lt; _bond[bondISIN].maturityDate, &quot;ERC7092Puttable: BOND_MATURED&quot;);
        
        uint256 principal =  _principals[msg.sender];
        _principals[msg.sender] = 0;
        
        // ADD LOGIC
    }
}
```

### CONVERTIBLE BONDS:

```solidity
pragma solidity ^0.8.0;

import &apos;ERC7092.sol&apos;;

contract ERC7092Convertible is ERC7092 {
    // WRITE THE LOGIC TO ALLOW INVESTOR OR ISSUER TO CONVERT BONDS TO EQUITY
    // STATE VARIABLES AND FUNCTIONS NEEDED
    
    /**
    * @notice convert bonds to equity. Here we assumed that the investors must convert their bonds to equity
    *         Issuer can also convert invetsors bonds to equity.
    */
    function convert() public {
        require(_principals[msg.sender] &gt; 0, &quot;ERC7092Convertible: ONLY_INVESTORS&quot;);
        require(block.timestamp &lt; _bond[bondISIN].maturityDate, &quot;ERC7092Convertible: BOND_MATURED&quot;);
        
        uint256 principal =  _principals[msg.sender];
        _principals[msg.sender] = 0;
        
        // ADD LOGIC HERE
    }
}
```

### Identity Registry

This standard is designed specifically for tokenizing bonds. It does not inherently manage information pertaining to bondholders&apos; identities. However, to enhance compliance with regulatory requirements and improve transparency, an identity registry can be added  on top of this standard to store the identity of all authorized investors.

By maintaining an identity registry, issuers can ensure that bond tokens issued under the `ERC7092` standard are transferred only to registered and authorized entities. This practice aligns with regulatory compliance measures and provides a structured way to manage and verify the identity of bondholders. It also helps prevent unauthorized or non-compliant transfers of bond tokens.

## Security Considerations

Implementing this ERC requires careful consideration of security risks related to functions approving operators to manage owner&apos;s bonds and functions allowing bond transfers. The use of these functions necessitates robust validation to ensure only the bond owner or approved accounts can call them.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 28 May 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7092</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7092</guid>
      </item>
    
      <item>
        <title>Social Recovery Interface</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-social-recovery-interface/14494</comments>
        
        <description>## Abstract

This ERC proposes a standard interface for social recovery of smart contract accounts. It separates identity and policy verification from the recovery process, allowing more ways to authenticate (known as Guardians) than just on-chain accounts. It also lets users customize recovery policies without changing the account’s smart contract.

## Motivation

Vitalik Buterin has long advocated for social recovery as an essential tool for user protection within the crypto space. He posits that the value of this system rests in its ability to offer users, especially those less acquainted with the technicalities of cryptography, a robust safety net when access credentials are lost. By entrusting account recovery to a network of selected individuals or entities, dubbed &quot;Guardians,&quot; users gain a safeguard against the risk of losing access to their digital assets.

In essence, social recovery operates by verifying the identity of the user and the chosen Guardians, and then considering a set of their signatures. Should the validated signatures reach a specified threshold, account access is reestablished. This system is equipped to enforce complex policies, such as necessitating signatures from particular Guardians or reaching signature thresholds from different Guardian categories.

To overcome these limitations, this Ethereum Improvement Proposal (EIP) introduces a novel, customizable social recovery interface standard. This standard decouples identity and recovery policy verification from the recovery procedure itself, thereby enabling an independent, versatile definition and extension of both. This strategy accommodates a wider range of Guardian types and recovery policies, thereby offering users the following benefits:

1. Appoint friends or family members, who do not have blockchain accounts, as Guardians for social recovery.
2. Use NFTs/SBTs as Guardians for their accounts.
3. Personalize and implement adaptable recovery policies.
4. Support novel types of Guardians and recovery policies without needing to upgrade their account contracts.
5. Enable multiple recovery mechanism support, thereby eliminating single points of failure.

This approach enables users to customize recovery policies without the need to change the smart contract of the account itself.

## Specification

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



This EIP consists of four key concepts:

- **Identity**: This denotes the representation of a Guardian&apos;s identity on the blockchain. It encapsulates traditional on-chain account types such as Externally Owned Accounts (EOA) and Smart Contract Accounts (SCA). More importantly, it extends to include any identity construct capable of producing construct able to be verified on-chain, like signatures and proofs. This could range from [Webauthn](https://www.w3.org/TR/2021/REC-webauthn-2-20210408/)/Passkey R1 keys to Email DomainKeys Identified Mail (DKIM) signatures [RFC 6376](https://www.rfc-editor.org/rfc/rfc6376), OpenID tokens, Zero-Knowledge Proofs (ZKP), Non-Fungible Tokens (NFTs), SoulBound Tokens (SBTs), and even types yet to be developed. This comprehensive approach ensures a broad, forward-compatible support for various identity types.
- **PermissionVerifier**: This component defines how to verify the signature or proof provided by the Guardian. Regardless of whether the Guardian&apos;s account is on-chain or off-chain, the PermissionVerifier is invoked during the recovery process of smart contract accounts that incorporate a social recovery system. Its primary role is to confirm the validity of the Guardian&apos;s signature or proof, thereby ensuring the authenticity of the Guardian during the recovery process.
- **RecoveryPolicyVerifier**: This component offers a flexible interface for validating recovery policies. The flexibility stems from allowing account holders or authorized parties to define and store their recovery policies. During the recovery process, the verification logic is implemented by invoking the specific function of the contract instance adopting this interface. Thus, a wide array of customizable social recovery scenarios can be catered to through different contract instances and policy configurations. This contract is optional, because sometimes the contract designer may not need the policy abstraction.
- **RecoveryAccount**: This component encapsulates the core of the social recovery functionality. It is designed to be flexible, composable, and extensible to adapt to various recovery needs. Each RecoveryAccount is defined by an instance contract, crafted by smart contract developers, which embeds the essential logic for the recovery process.
- **RecoveryModule**: In some contract designs, many functions are not directly added to the account contract, but are implemented in the form of Module, which is a contract outside the account contract. This component encapsulates the core of the social recovery functionality. It is designed to be flexible, composable, and extensible to adapt to various recovery needs. 

![social_recovery_flow](/EIPs/assets/eip-7093/social-recovery-flow.svg)

### DataTypes

### `TypesAndDecoders`

This defines the necessary data types required by this interface standard.

```solidity
/**
 * @dev Structure representing an identity with its signature/proof verification logic.
 * Represents an EOA/CA account when signer is empty, use `guardianVerifier`as the actual signer for signature verification.
 * OtherWise execute IPermissionVerifier(guardianVerifier).isValidPermission(hash, signer, signature).
 */
struct Identity {
    address guardianVerifier;
    bytes signer;
}

/**
 * @dev Structure representing a guardian with a property
 * The property of Guardian are defined by the associated RecoveryPolicyVerifier contract.
 */
struct GuardianInfo {
    Identity guardian;
    uint64 property; //eg.,Weight,Percentage,Role with weight,etc.
}

/**
 * @dev Structure representing a threshold configuration
 */
struct ThresholdConfig {
    uint64 threshold; // Threshold value
    int48 lockPeriod; // Lock period for the threshold
}

/**
 * @dev Structure representing a recovery configuration
 * A RecoveryConfig can have multiple threshold configurations for different threshold values and their lock periods, and the policyVerifier is optional.
 */
struct RecoveryConfigArg {
    address policyVerifier;
    GuardianInfo[] guardianInfos;
    ThresholdConfig[] thresholdConfigs;
}

struct Permission {
    Identity guardian;
    bytes signature;
}

```

The `Identity` structure represents various types of guardians. The process of identity verification is as follows:

- When the `signer` value in the declared entity is empty, this implies that the `Identity` entity is of EOA/SCA account type. In this case, `guardianVerifier` address should be the address of EOA/SCA (the actual signer). For permission verification of this `Identity` entity, it is recommended to utilize a secure library or built-in function capable of validating both ECDSA and [ERC-1271](/EIPs/EIPS/eip-1271) signatures. This helps in preventing potential security vulnerabilities, such as signature malleability attacks. 
- When the `signer` value in the declared entity is non-empty, this suggests that the `Identity` entity is of non-account type. In this case, permission verification can be accomplished by calling `guardianVerifier` address contract instance through `IPermissionVerifier` interface.



### Interfaces

### `IPermissionVerifier`

The Guardian Permission Verification Interface. Implementations MUST conform to this interface to enable identity verification of non-account type guardians.

```solidity
/**
 * @dev Interface for no-account type identity signature/proof verification
 */
interface IPermissionVerifier {
    /**
     * @dev Check if the signer key format is correct
     */
    function isValidSigners(bytes[] signers) external returns (bool);

    /**
     * @dev Validate permission
     */
    function isValidPermission(
        bytes32 hash,
        bytes signer,
        bytes signature
    ) external returns (bool);

    /**
     * @dev Validate permissions
     */
    function isValidPermissions(
        bytes32 hash,
        bytes[] signers,
        bytes[] signatures
    ) external returns (bool);

    /**
     * @dev Return supported signer key information, format, signature format, hash algorithm, etc.
     * MAY TODO:using ERC-3668: ccip-read
     */
    function getGuardianVerifierInfo() public view returns (bytes memory);
}

```



### `IRecoveryPolicyVerifier`

The Recovery Policy Verification Interface. Implementations MAY conform to this interface to support verification of varying recovery policies. RecoveryPolicyVerifier is optional for SocialRecoveryInterface.

```solidity
/**
 * @dev Interface for recovery policy verification
 */
interface IRecoveryPolicyVerifier {
    /**
     * @dev Verify recovery policy and return verification success and lock period
     * Verification includes checking if guardians exist in the Guardians List
     */
    function verifyRecoveryPolicy( Permission[] memory permissions, uint64[] memory properties)
        external
        view
        returns (bool succ, uint64 weight);

    /**
     * @dev Returns supported policy settings and accompanying property definitions for Guardian.
     */
    function getPolicyVerifierInfo() public view returns (bytes memory);
}

```

The `verifyRecoveryPolicy()` function is designed to validate whether the provided list of `Permissions` abides by the specified recovery properties (`properties`). This function has the following constraints and effects: For each matched `guardian`, calculations are made according to the corresponding `property` in the `properties` list (e.g., accumulating weight, distinguishing role while accumulating, etc.). 

These constraints ensure that the provided `guardians` and `properties` comply with the requirements of the recovery policy, maintaining the security and integrity of the recovery process.



### `IRecoveryAccount`

The Smart Contract Account MAY implement the `IRecoveryAccount` interface to support social recovery functionality, enabling users to customize configurations of different types of Guardians and recovery policies. In the contract design based on Module, the implementation of `RecoveryModule` is very similar to `RecoveryAccount`, except that different accounts need to be distinguished and isolated.

```solidity
interface IRecoveryAccount {
    modifier onlySelf() {
        require(msg.sender == address(this), &quot;onlySelf: NOT_AUTHORIZED&quot;);
        _;
    }

    modifier InRecovering(address policyVerifyAddress) {
        (bool isRecovering, ) = getRecoveryStatus(policyVerifierAddress);
        require(isRecovering, &quot;InRecovering: no ongoing recovery&quot;);
        _;
    }

    /**
     * @dev Events for updating guardians, starting for recovery, executing recovery, and canceling recovery
     */
    event RecoveryStarted(bytes newOwners, uint256 nonce, uint48 expiryTime);
    event RecoveryExecuted(bytes newOwners, uint256 nonce);
    event RecoveryCanceled(uint256 nonce);

    /**
     * @dev Return the domain separator name and version for signatures
     * Also return the domainSeparator for EIP-712 signature
     */

    /// @notice             Domain separator name for signatures
    function DOMAIN_SEPARATOR_NAME() external view returns (string memory);

    /// @notice             Domain separator version for signatures
    function DOMAIN_SEPARATOR_VERSION() external view returns (string memory);

    /// @notice             returns the domainSeparator for EIP-712 signature
    /// @return             the bytes32 domainSeparator for EIP-712 signature
    function domainSeparatorV4() external view returns (bytes32);

    /**
     * @dev Update /replace guardians and recovery policies
     * Multiple recovery policies can be set using an array of RecoveryConfigArg
     */
    function updateGuardians(RecoveryConfigArg[] recoveryConfigArgs) external onlySelf;

    // Generate EIP-712 message hash,
    // Iterate over signatures for verification,
    // Verify recovery policy,
    // Store temporary state or recover immediately based on the result returned by verifyRecoveryPolicy.
    function startRecovery(
        uint256 configIndex,
        bytes newOwner,
        Permission[] permissions
    ) external;

    /**
     * @dev Execute recovery
     * temporary state -&gt; ownerKey rotation
     */
    function executeRecovery(uint256 configIndex) external;

    function cancelRecovery(uint256 configIndex) external onlySelf InRecovering(policyVerifier);

    function cancelRecoveryByGuardians(uint256 configIndex, Permission[] permissions)
        external
        InRecovering(policyVerifier);

    /**
     * @dev Get wallet recovery config, check if an identity is a guardian, get the nonce of social recovery, and get the recovery status of the wallet
     */
    function isGuardian(uint256 configIndex, identity guardian) public view returns (bool);

    function getRecoveryConfigs() public view returns (RecoveryConfigArg[] recoveryConfigArgs);

    function getRecoveryNonce() public view returns (uint256 nonce);

    function getRecoveryStatus(address policyVerifier) public view returns (bool isRecovering, uint48 expiryTime);
}

```

- For the `Guardian`&apos;s signable message, it SHOULD employ [EIP-712](/EIPs/EIPS/eip-712) type signature to ensure the content of the signature is readable and can be confirmed accurately during the Guardian signing process.
- `getRecoveryNonce()` SHOULD be separated from nonces associated with account asset operations, as social recovery is a function at the account layer.



### **Recovery Account Workflow**

Note: This workflow is presented as an illustrative example to clarify the coordinated usage of the associated interface components. It does not imply a mandatory adherence to this exact process.

1. A user sets up a `recoveryPolicyConfigA` within his `RecoveryAccount`:

   ```json
    {
    &quot;recoveryConfigA&quot;: {
        &quot;type&quot;: &quot;RecoveryConfig&quot;,
        &quot;policyVerifier&quot;: &quot;0xA&quot;,
        &quot;guardians&quot;: [
            {
                &quot;type&quot;: &quot;Identity&quot;,
                &quot;name&quot;: &quot;A&quot;,
                &quot;data&quot;: {
                    &quot;guardianVerifier&quot;: &quot;guardianVerifier1&quot;,
                    &quot;signer&quot;: &quot;signerA&quot;
                },
                &quot;property&quot;: 30
            },
            {
                &quot;type&quot;: &quot;Identity&quot;,
                &quot;name&quot;: &quot;B&quot;,
                &quot;data&quot;: {
                    &quot;guardianVerifier&quot;: &quot;guardianVerifier2&quot;,
                    &quot;signer&quot;: &quot;&quot;
                },
                &quot;property&quot;: 30
            },
            {
                &quot;type&quot;: &quot;Identity&quot;,
                &quot;name&quot;: &quot;C&quot;,
                &quot;data&quot;: {
                    &quot;guardianVerifier&quot;: &quot;guardianVerifier3&quot;,
                    &quot;signer&quot;: &quot;signerC&quot;
                },
                &quot;property&quot;: 40
            }
        ],
        &quot;thresholdConfigs&quot;: [
            { &quot;threshold&quot;: 50, &quot;lockPeriod&quot;: &quot;24hours&quot;},
            { &quot;threshold&quot;: 100,&quot;lockPeriod&quot;: &quot;0&quot;}
        ]
      }
    }
   ```

2. When GuardianA and GuardianB assist the user in performing account recovery, they are to confirm the [EIP-712](/EIPs/EIPS/eip-712) structured data for signing, which might look like this:

   ```json
   {
     &quot;types&quot;: {
       &quot;EIP712Domain&quot;: [
         { &quot;name&quot;: &quot;name&quot;, &quot;type&quot;: &quot;string&quot; },
         { &quot;name&quot;: &quot;version&quot;, &quot;type&quot;: &quot;string&quot; },
         { &quot;name&quot;: &quot;chainId&quot;, &quot;type&quot;: &quot;uint256&quot; },
         { &quot;name&quot;: &quot;verifyingContract&quot;, &quot;type&quot;: &quot;address&quot; }
       ],
       &quot;StartRecovery&quot;: [
         { &quot;name&quot;: &quot;configIndex&quot;, &quot;type&quot;: &quot;uint256&quot; },
         { &quot;name&quot;: &quot;newOwners&quot;, &quot;type&quot;: &quot;bytes&quot; },
         { &quot;name&quot;: &quot;nonce&quot;, &quot;type&quot;: &quot;uint256&quot; }
       ]
     },
     &quot;primaryType&quot;: &quot;StartRecovery&quot;,
     &quot;domain&quot;: {
       &quot;name&quot;: &quot;Recovery Account Contract&quot;,
       &quot;version&quot;: &quot;1&quot;,
       &quot;chainId&quot;: 1,
       &quot;verifyingContract&quot;: &quot;0xCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC&quot;
     },
     &quot;message&quot;: {
       &quot;policyVerifier&quot;: &quot;0xA&quot;,
       &quot;newOwners&quot;: &quot;0xabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd&quot;,
       &quot;nonce&quot;: 10
     }
   }
   ```

   In this step, the guardians need to confirm that the domain separator&apos;s `verifyingContract` is the correct `RecoveryAccount` address for the user, the contract name, version, and chainId are correct, and the `policyVerifier` and `newOwners` fields in the `message` part match the user&apos;s provided data.

   The `msgHash` is then composed of:

   - `msgHash` = `keccak256(&quot;\\x19\\x01&quot; + domainSeparatorV4() + dataHash)`

   Where,

   - `dataHash` = `keccak256(EXECUTE_RECOVERY_TYPEHASH + configIndex + keccak256(bytes(newOwners)) + getRecoveryNonce())`
   - `EXECUTE_RECOVERY_TYPEHASH` = `keccak256(&quot;StartRecovery(address configIndex, bytes newOwners, uint256 nonce)&quot;)`

   The guardians sign this hash to obtain the signature:

   - `signature` = `sign(msgHash)`

   The `permission` is then constructed as:

   - `permission` = `guardian + signature`

   Once each Guardian has generated their unique `permission`, all these individual permissions are collected to form `permissions`:

   `permissions`= [`guardianA+signature`, `guardianB+signature`, ...]

   The `permissions` is an array that consists of all the permissions of the Guardians who are participating in the recovery process.

3. A bundler or another relayer service calls the `RecoveryAccount.startRecovery(0xA, newOwners, permissions)` function.

4. `startRecovery()` function&apos;s processing logic is as follows:

   - Generate a message hash (`msgHash`) from the input parameters `0xA`, `newOwners` and internally generated [EIP-712](/EIPs/EIPS/eip-712) signature parameters and `RecoveryNonce`.
   - Extract `guardian` and corresponding `signature` from the input parameters `permissions` and process them as follows:
     - If `guardianA.signer` is non-empty (Identity A), call `IPermissionVerifier(guardianVerifier1).isValidPermissions(signerA, msgHash, permissionA.signature)` to validate the signature.
     - If `guardianA.signer` is empty (Identity B), call the internal function `SignatureChecker.isValidSignatureNow(guardianVerifier2, msgHash, permissionB.signature)` to validate the signature.

5. After successful verification of all `guardians` signatures, fetch the associated `config` data for policyVerifier address `0xA` and call `IRecoveryPolicyVerifier(0xA).verifyRecoveryPolicy(permissions, properties)`. The function `verifyRecoveryPolicy()` performs the following checks:

   Note that the `guardians` parameter in the function refers to the guardians whose signatures have been successfully verified.

   - Verify that `guardians` (Identity A and B) are present in `config.guardianInfos` list and are unique.
   - Accumulate the `property` values of `guardians` (30 + 30 = 60).
   - Compare the calculated result (60) with the `config.thresholdConfigs.threshold` ,the result is more than the first element (`threshold: 50, lockPeriod: 24 hours`) but less than the second element (`threshold: 100, lockPeriod: &quot;&quot;`), the validation is successful, and the lock period of 24 hours is returned.

6. The `RecoveryAccount` saves a temporary state `{newOwners, block.timestamp + 24 hours}` and increments `RecoveryNonce`. A `RecoveryStarted` event is emitted.

7. After the expiry time, anyone (usually a relayer) can call `RecoveryAccount.executeRecovery()` to replace `newOwners`, remove the temporary state, complete the recovery, and emit a `RecoveryExecuteed` event.



## Rationale

A primary design rationale for this proposal is to extend a greater diversity of Guardian types and more flexible, customizable recovery policies for a RecoveryAccount. This is achieved by separating the verification logic from the social recovery process, ensuring that the basic logic of the account contract remains unaltered.

The necessity of incorporating `Verifiers` from external contracts arises from the importance of maintaining the inherent recovery logic of the `RecoveryAccount`. The `Verifiers`&apos;s logic is designed to be simple and clear, and its fixed invocation format means that any security risks posed by integrating external contracts can be effectively managed.

The `recoveryConfigs` are critical to the `RecoveryAccount` and should be securely and effectively stored. The access and modification permissions associated with these configurations must be carefully managed and isolated to maintain security. The storage and quantity of `recoveryConfigs` are not limited to ensure the maximum flexibility of the `RecoveryAccount`&apos;s implementation.

The introduction of `recoveryNonce` into the `RecoveryAccount` serves to prevent potential replay attacks arising from the malicious use of Guardian&apos;s `permissions`. The `recoveryNonce` ensures each recovery process is unique, reducing the likelihood of past successful recovery attempts being maliciously reused.

## Backwards Compatibility

No backward compatibility issues are introduced by this standard.

## Reference Implementation

TBD.

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 29 May 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7093</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7093</guid>
      </item>
    
      <item>
        <title>ERC-20 with transaction validation step.</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc721-with-a-validation-step/14071</comments>
        
        <description>## Abstract

This standard is an extension of [ERC-20](/EIPs/EIPS/eip-20). It defines new validation functionality to avoid wallet draining: every `transfer` or `approve` will be locked waiting for validation.

## Motivation

The power of the blockchain is at the same time its weakness: giving the user full responsibility for their data.

Many cases of Token theft currently exist, and current Token anti-theft schemes, such as transferring Tokens to cold wallets, make Tokens inconvenient to use.

Having a validation step before every `transfer` and `approve` would give Smart Contract developers the opportunity to create secure Token anti-theft schemes.

An implementation example would be a system where a validator address is responsible for validating all Smart Contract transactions.

This address would be connected to a dApp where the user could see the validation requests of his Tokens and accept the correct ones.

Giving this address only the power to validate transactions would make a much more secure system where to steal a Token the thief would have to have both the user&apos;s address and the validator address simultaneously.

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot; and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

[ERC-20](/EIPs/EIPS/eip-20) compliant contracts MAY implement this EIP.

All the operations that change the ownership of Tokens, like a `transfer`/`transferFrom`, SHALL create a `TransferValidation` pending to be validated and emit a `ValidateTransfer`, and SHALL NOT transfer the Tokens.

All the operations that enable an approval to manage a Token, like an `approve`, SHALL create an `ApprovalValidation` pending to be validated and emit a `ValidateApproval`, and SHALL NOT enable an approval.

When the transfer is called by an approved account and not the owner, it MUST be executed directly without the need for validation. This is in order to adapt to all current projects that require approve to directly move your Tokens.

When validating a `TransferValidation` or `ApprovalValidation` the valid field MUST be set to true and MUST NOT be validated again.

The operations that validate a `TransferValidation` SHALL change the ownership of the Tokens.

The operations that validate an `ApprovalValidation` SHALL enable the approval.

### Contract Interface

```solidity
interface IERC7144 {

    struct TransferValidation {
        // The address of the owner.
        address from;
        // The address of the receiver.
        address to;
        // The token amount.
        uint256 amount;
        // Whether is a valid transfer.
        bool valid;
    }

    struct ApprovalValidation {
        // The address of the owner.
        address owner;
        // The spender address.
        address spender;
        // The token amount approved.
        uint256 amount;
        // Whether is a valid approval.
        bool valid;
    }

    /**
     * @dev Emitted when a new transfer validation has been requested.
     */
    event ValidateTransfer(address indexed from, address indexed to, uint256 amount, uint256 indexed transferValidationId);

    /**
    * @dev Emitted when a new approval validation has been requested.
    */
    event ValidateApproval(address indexed owner, address indexed spender, uint256 amount, uint256 indexed approvalValidationId);

    /**
     * @dev Returns true if this contract is a validator ERC20.
     */
    function isValidatorContract() external view returns (bool);

    /**
     * @dev Returns the transfer validation struct using the transfer ID.
     *
     */
    function transferValidation(uint256 transferId) external view returns (TransferValidation memory);

    /**
    * @dev Returns the approval validation struct using the approval ID.
    *
    */
    function approvalValidation(uint256 approvalId) external view returns (ApprovalValidation memory);

    /**
     * @dev Return the total amount of transfer validations created.
     *
     */
    function totalTransferValidations() external view returns (uint256);

    /**
     * @dev Return the total amount of transfer validations created.
     *
     */
    function totalApprovalValidations() external view returns (uint256);
}
  ```

The `isValidatorContract()` function MUST be implemented as `public`.

The `transferValidation(uint256 transferId)` function MAY be implemented as `public` or `external`.

The `approvalValidation(uint256 approveId)` function MAY be implemented as `public` or `external`.

The `totalTransferValidations()` function MAY be implemented as `pure` or `view`.

The `totalApprovalValidations()` function MAY be implemented as `pure` or `view`.

## Rationale

### Universality

The standard only defines the validation functions, but not how they should be used. It defines the validations as internal and lets the user decide how to manage them.

An example could be to have an address validator connected to a dApp so that users could manage their validations.

This validator could be used for all Tokens or only for some users.

It could also be used as a wrapped Smart Contract for existing ERC-20, allowing 1/1 conversion with existing Tokens.

### Extensibility

This standard only defines the validation function, but does not define the system with which it has to be validated. A third-party protocol can define how it wants to call these functions as it wishes.

## Backwards Compatibility

This standard is an extension of [ERC-20](/EIPs/EIPS/eip-20), compatible with all the operations except `transfer`/`transferFrom`/`approve`.

This operations will be overridden to create a validation petition instead of transfer the Tokens or enable an approval.

## Reference Implementation

```solidity
// SPDX-License-Identifier: CC0-1.0

pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/token/ERC20/ERC20.sol&quot;;
import &quot;./IERC7144.sol&quot;;

/**
 * @dev Implementation of ERC7144
 */
contract ERC7144 is IERC7144, ERC20 {

    // Mapping from transfer ID to transfer validation
    mapping(uint256 =&gt; TransferValidation) private _transferValidations;

    // Mapping from approval ID to approval validation
    mapping(uint256 =&gt; ApprovalValidation) private _approvalValidations;

    // Total number of transfer validations
    uint256 private _totalTransferValidations;

    // Total number of approval validations
    uint256 private _totalApprovalValidations;

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    constructor(string memory name_, string memory symbol_) ERC20(name_, symbol_){
    }

    /**
    * @dev Returns true if this contract is a validator ERC721.
    */
    function isValidatorContract() public pure returns (bool) {
        return true;
    }

    /**
     * @dev Returns the transfer validation struct using the transfer ID.
     *
     */
    function transferValidation(uint256 transferId) public view override returns (TransferValidation memory) {
        require(transferId &lt; _totalTransferValidations, &quot;ERC7144: invalid transfer ID&quot;);
        TransferValidation memory v = _transferValidation(transferId);

        return v;
    }

    /**
     * @dev Returns the approval validation struct using the approval ID.
     *
     */
    function approvalValidation(uint256 approvalId) public view override returns (ApprovalValidation memory) {
        require(approvalId &lt; _totalApprovalValidations, &quot;ERC7144: invalid approval ID&quot;);
        ApprovalValidation memory v = _approvalValidation(approvalId);

        return v;
    }

    /**
     * @dev Return the total amount of transfer validations created.
     *
     */
    function totalTransferValidations() public view override returns (uint256) {
        return _totalTransferValidations;
    }

    /**
     * @dev Return the total amount of approval validations created.
     *
     */
    function totalApprovalValidations() public view override returns (uint256) {
        return _totalApprovalValidations;
    }

    /**
     * @dev Returns the transfer validation of the `transferId`. Does NOT revert if transfer doesn&apos;t exist
     */
    function _transferValidation(uint256 transferId) internal view virtual returns (TransferValidation memory) {
        return _transferValidations[transferId];
    }

    /**
     * @dev Returns the approval validation of the `approvalId`. Does NOT revert if transfer doesn&apos;t exist
     */
    function _approvalValidation(uint256 approvalId) internal view virtual returns (ApprovalValidation memory) {
        return _approvalValidations[approvalId];
    }

    /**
     * @dev Validate the transfer using the transfer ID.
     *
     */
    function _validateTransfer(uint256 transferId) internal virtual {
        TransferValidation memory v = transferValidation(transferId);
        require(!v.valid, &quot;ERC721V: the transfer is already validated&quot;);

        super._transfer(v.from, v.to, v.amount);

        _transferValidations[transferId].valid = true;
    }

    /**
     * @dev Validate the approval using the approval ID.
     *
     */
    function _validateApproval(uint256 approvalId) internal virtual {
        ApprovalValidation memory v = approvalValidation(approvalId);
        require(!v.valid, &quot;ERC7144: the approval is already validated&quot;);

        super._approve(v.owner, v.spender, v.amount);

        _approvalValidations[approvalId].valid = true;
    }

    /**
     * @dev Create a transfer petition of `tokenId` from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     *
     * Emits a {ValidateTransfer} event.
     */
    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual override {
        require(from != address(0), &quot;ERC7144: transfer from the zero address&quot;);
        require(to != address(0), &quot;ERC7144: transfer to the zero address&quot;);

        if(_msgSender() == from) {
            TransferValidation memory v;

            v.from = from;
            v.to = to;
            v.amount = amount;

            _transferValidations[_totalTransferValidations] = v;

            emit ValidateTransfer(from, to, amount, _totalTransferValidations);

            _totalTransferValidations++;
        } else {
            super._transfer(from, to, amount);
        }
    }

    /**
     * @dev Create an approval petition from `owner` to operate the `amount`
     *
     * Emits an {ValidateApproval} event.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual override {
        require(owner != address(0), &quot;ERC7144: approve from the zero address&quot;);
        require(spender != address(0), &quot;ERC7144: approve to the zero address&quot;);

        ApprovalValidation memory v;

        v.owner = owner;
        v.spender = spender;
        v.amount = amount;

        _approvalValidations[_totalApprovalValidations] = v;

        emit ValidateApproval(v.owner, spender, amount, _totalApprovalValidations);

        _totalApprovalValidations++;
    }
}
```

## Security Considerations

As is defined in the Specification the operations that change the ownership of Tokens or enable an approval to manage the Tokens SHALL create a `TransferValidation` or an `ApprovalValidation` pending to be validated and SHALL NOT transfer the Tokens or enable an approval.

With this premise in mind, the operations in charge of validating a `TransferValidation` or an `ApprovalValidation` must be protected with the maximum security required by the applied system.

For example, a valid system would be one where there is a validator address in charge of validating the transactions.

To give another example, a system where each user could choose his validator address would also be correct.

In any case, the importance of security resides in the fact that no address can validate a `TransferValidation` or an `ApprovalValidation` without the permission of the chosen system.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 07 May 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7144</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7144</guid>
      </item>
    
      <item>
        <title>ERC-721 Multi-Metadata Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc721-multi-metadata-extension/14629</comments>
        
        <description>## Abstract

This EIP proposes an extension to the [ERC-721](/EIPs/EIPS/eip-721) standard to support multiple metadata URIs per token. It introduces a new interface, `IERC721MultiMetadata`, which provides methods for accessing the metadata URIs associated with a token, including a pinned URI index and a list of all metadata URIs. The extension is designed to be backward compatible with existing `ERC721Metadata` implementations.

## Motivation

The current [ERC-721](/EIPs/EIPS/eip-721) standard allows for a single metadata URI per token with the `ERC721Metadata` implementation. However, there are use cases where multiple metadata URIs are desirable. Some example use cases are listed below:

- A token represents a collection of (cycling) assets with individual metadata
- An on-chain history of revisions to token metadata
- Appending metadata with different aspect ratios so that it can be displayed properly on all screens
- Dynamic and evolving metadata
- Collaborative and multi-artist tokens

This extension enables such use cases by introducing the concept of multi-metadata support.

The primary reason for having a multi-metadata standard in addition to the existing `ERC721Metadata` standard is that dapps and marketplaces don&apos;t have a mechanism to infer and display all the token URIs. Giving a standard way for marketplaces to offer collectors a way to pin/unpin one of the metadata choices also enables quick and easy adoption of this functionality.

## Specification

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.

**The multi-metadata extension is OPTIONAL for [ERC-721](/EIPs/EIPS/eip-721) contracts and it is RECOMMENDED to be used in conjunction with the [ERC-4906](/EIPs/EIPS/eip-4906) standard if implemented**.

```solidity
/// @title EIP-721 Multi-Metdata Extension
/// @dev The ERC-165 identifier for this interface is 0x06e1bc5b.
interface IERC7160 {

  /// @dev This event emits when a token uri is pinned and is
  ///  useful for indexing purposes.
  event TokenUriPinned(uint256 indexed tokenId, uint256 indexed index);

  /// @dev This event emits when a token uri is unpinned and is
  ///  useful for indexing purposes.
  event TokenUriUnpinned(uint256 indexed tokenId);

  /// @notice Get all token uris associated with a particular token
  /// @dev If a token uri is pinned, the index returned SHOULD be the index in the string array
  /// @dev This call MUST revert if the token does not exist
  /// @param tokenId The identifier for the nft
  /// @return index An unisgned integer that specifies which uri is pinned for a token (or the default uri if unpinned)
  /// @return uris A string array of all uris associated with a token
  /// @return pinned A boolean showing if the token has pinned metadata or not
  function tokenURIs(uint256 tokenId) external view returns (uint256 index, string[] memory uris, bool pinned);

  /// @notice Pin a specific token uri for a particular token
  /// @dev This call MUST revert if the token does not exist
  /// @dev This call MUST emit a `TokenUriPinned` event
  /// @dev This call MAY emit a `MetadataUpdate` event from ERC-4096
  /// @param tokenId The identifier of the nft
  /// @param index The index in the string array returned from the `tokenURIs` function that should be pinned for the token
  function pinTokenURI(uint256 tokenId, uint256 index) external;

  /// @notice Unpin metadata for a particular token
  /// @dev This call MUST revert if the token does not exist
  /// @dev This call MUST emit a `TokenUriUnpinned` event
  /// @dev This call MAY emit a `MetadataUpdate` event from ERC-4096
  /// @dev It is up to the developer to define what this function does and is intentionally left open-ended
  /// @param tokenId The identifier of the nft
  function unpinTokenURI(uint256 tokenId) external;

  /// @notice Check on-chain if a token id has a pinned uri or not
  /// @dev This call MUST revert if the token does not exist
  /// @dev Useful for on-chain mechanics that don&apos;t require the tokenURIs themselves
  /// @param tokenId The identifier of the nft
  /// @return pinned A bool specifying if a token has metadata pinned or not
  function hasPinnedTokenURI(uint256 tokenId) external view returns (bool pinned);
}
```

The `TokenUriPinned` event MUST be emitted when pinning a token uri with the `pinTokenUri` function.

The `TokenUriUnpinned` event MUST be emitted when unpinning a token uri with the `unpinTokenUri` function.

The `tokenURI` function defined in the ERC-721 Metadata extension MUST return the pinned URI when a token has a pinned uri.

The `tokenURI` function defined in the ERC-721 Metadata extension MUST return a default uri when a token has an unpinned uri.

The `supportsInterface` method MUST return `true` when called with `0x06e1bc5b`.

Implementing functionality to add or remove uris to a token MUST be implemented separately from this standard. It is RECOMMENDED that one of the event defined in [ERC-4906](/EIPs/EIPS/eip-4906) are emitted whenever uris are added or removed.

See the [Implementation](#reference-implementation) section for an example.

## Rationale

Similar terminology to [ERC-721](/EIPs/EIPS/eip-721) was used in order to keep fetching metadata familiar. The concept of pinning and unpinning metadata is introduced as it is clear that NFT owners might want to choose which piece of metadata to display. At first, we considered leaving the pinning and unpinning actions up to each developer, but realized that a standard interface for pinning and unpinning allows for dApps to easily implement universal support for multi-metadata tokens.

We first considered whether the `tokenURIs` function should return just a string array, but added the extra information so that you could get all info desired in one call instead of potentially three calls. The pinned URI should be used as the primary URI for the token, while the list of metadata URIs can be used to access individual assets&apos; metadata within the token. dApps could present these as a gallery or media carousels.

The `TokenUriPinned` and `TokenUriUnpinned` events included in this specification can be used by dApps to index what metadata to show. This can eliminate on-chain calls and event driven architecture can be used instead.

The reason why this standard recommends the use of [ERC-4906](/EIPs/EIPS/eip-4906) when adding or removing uris from a token is that there is already wide dApp support for this event and it already is what is needed - an alert to dApps that metadata for a token has been updated. We did not want to potentially cause dApp issues with duplicate events. A third party listening to this event could then call the `tokenURIs` function to get the updated metadata.

## Backwards Compatibility

This extension is designed to be backward compatible with existing [ERC-721](/EIPs/EIPS/eip-721) contracts. The implementation of the `tokenURI` method must either return the pinned token uri (if pinned) or some default uri (if unpinned).

## Reference Implementation

An open-source reference implementation of the `IERC721MultiMetadata` interface can be provided, demonstrating how to extend an existing [ERC-721](/EIPs/EIPS/eip-721) contract to support multi-metadata functionality. This reference implementation can serve as a guide for developers looking to implement the extension in their own contracts.

```solidity
// SPDX-License-Identifier: CC0-1.0

pragma solidity ^0.8.19;

import {ERC721} from &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;
import {Ownable} from &quot;@openzeppelin/contracts/access/Ownable.sol&quot;;
import {IERC4906} from &quot;@openzeppelin/contracts/interfaces/IERC4906.sol&quot;;
import {IERC7160} from &quot;./IERC7160.sol&quot;;

contract MultiMetadata is ERC721, Ownable, IERC7160, IERC4906 {
  mapping(uint256 =&gt; string[]) private _tokenURIs;
  mapping(uint256 =&gt; uint256) private _pinnedURIIndices;
  mapping(uint256 =&gt; bool) private _hasPinnedTokenURI;

  constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) Ownable() {
    _mint(msg.sender, 1);
  }

  // @notice Returns the pinned URI index or the last token URI index (length - 1).
  function _getTokenURIIndex(uint256 tokenId) internal view returns (uint256) {
    return _hasPinnedTokenURI[tokenId] ? _pinnedURIIndices[tokenId] : _tokenURIs[tokenId].length - 1;
  }

  // @notice Implementation of ERC721.tokenURI for backwards compatibility.
  // @inheritdoc ERC721.tokenURI
  function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
    _requireMinted(tokenId);

    uint256 index = _getTokenURIIndex(tokenId);
    string[] memory uris = _tokenURIs[tokenId];
    string memory uri = uris[index];

    // Revert if no URI is found for the token.
    require(bytes(uri).length &gt; 0, &quot;ERC721: not URI found&quot;);
    return uri;
  }

  /// @inheritdoc IERC721MultiMetadata.tokenURIs
  function tokenURIs(uint256 tokenId) external view returns (uint256 index, string[] memory uris, bool pinned) {
    _requireMinted(tokenId);
    return (_getTokenURIIndex(tokenId), _tokenURIs[tokenId], _hasPinnedTokenURI[tokenId]);
  }

  /// @inheritdoc IERC721MultiMetadata.pinTokenURI
  function pinTokenURI(uint256 tokenId, uint256 index) external {
    require(msg.sender == ownerOf(tokenId), &quot;Unauthorized&quot;);
    _pinnedURIIndices[tokenId] = index;
    _hasPinnedTokenURI[tokenId] = true;
    emit TokenUriPinned(tokenId, index);
  }

  /// @inheritdoc IERC721MultiMetadata.unpinTokenURI
  function unpinTokenURI(uint256 tokenId) external {
    require(msg.sender == ownerOf(tokenId), &quot;Unauthorized&quot;);
    _pinnedURIIndices[tokenId] = 0;
    _hasPinnedTokenURI[tokenId] = false;
    emit TokenUriUnpinned(tokenId);
  }

  /// @inheritdoc IERC721MultiMetadata.hasPinnedTokenURI
  function hasPinnedTokenURI(uint256 tokenId) external view returns (bool pinned) {
    return _hasPinnedTokenURI[tokenId];
  }

  /// @notice Sets a specific metadata URI for a token at the given index.
  function setUri(uint256 tokenId, uint256 index, string calldata uri) external onlyOwner {
    if (_tokenURIs[tokenId].length &gt; index) {
      _tokenURIs[tokenId][index] = uri;
    } else {
      _tokenURIs[tokenId].push(uri);
    }

    emit MetadataUpdate(tokenId);
  }

  // Overrides supportsInterface to include IERC721MultiMetadata interface support.
  function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
    return (
      interfaceId == type(IERC7160).interfaceId ||
      super.supportsInterface(interfaceId)
    );
  }
}
```

## Security Considerations

Care should be taken when specifying access controls for state changing events, such as those that allow uris to be added to tokens
and those specified in this standard: the `pinTokenUri` and `unpinTokenUri` functions. This is up to the developers to specify
as each application may have different requirements to allow for pinning and unpinning.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 09 Jun 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7160</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7160</guid>
      </item>
    
      <item>
        <title>Simple token, Simplified ERC-20</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/simple-token-designed-for-smart-contract-wallet-aa/14757</comments>
        
        <description>## Abstract

This ERC is a new asset designed based on the user contract wallet (including account abstraction), and is forward compatible with [ERC-20](/EIPs/EIPS/eip-20). To keep token assets simple, this ERC removes the `transferFrom`, `approve` and `allowance` functions of ERC-20.


## Motivation

[ERC-20](/EIPs/EIPS/eip-20) defines Ethereum-based standard tokens that can be traded and transferred, but the essence of ERC-20 is based on the externally-owned account (EOA) wallet design. An EOA wallet has no state and code storage, and the smart contract wallet is different.

Almost all ERCs related to tokens add functions, but our opinion is the opposite. We think the token contract should be simpler, with more functions taken care of by the smart contract wallet.

Our proposal is to design a simpler token asset based on the smart contract wallet.

It aims to achieve the following goals:

1. Keep the asset contract simple: only responsible for the `transfer` functions.
2. `approve` and `allowance` functions are not managed by the token contract, Instead, these permissions are managed at the user level, offering greater flexibility and control to users. This change not only enhances user autonomy but also mitigates certain risks associated with the ERC-20 contract&apos;s implementation of these functions.
3. Remove the `transferFrom` function. A better way to call the other party&apos;s token assets is to access the other party&apos;s own contract instead of directly accessing the token asset contract.
4. Forward compatibility with ERC-20 means that all fungible tokens can be compatible with this proposal.

## Specification

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

Compliant contracts MUST implement the following interface:

```solidity
pragma solidity ^0.8.20;

/**
 * @title ERC7196 Simple token interface 
 * @dev See https://ercs.ethereum.org/ERCS/erc-7196
 */
interface IERC7196 {
    /**
     * @notice Used to notify transfer tokens.
     * @param from Address of the from
     * @param to Address of the receive
     * @param value The transaction amount 
     */
    event Transfer(
        address indexed from,
        address indexed to,
        uint256 value
    );
	
    /**
     * @notice Get the total supply
     * @return total The total supply amount
     */
    function totalSupply() 
        external  
        view
        returns (uint256 total);
	  
    /**
     * @notice get the balance of owenr address
     * @param owner Address of the owner
     * @return balance The balance of the owenr address
     */
    function balanceOf(address owner) 
        external
        view
        returns (uint256 balance);

    /**
     * @notice Transfer token
     * @param to Address of the to
     * @param value The transaction amount 
     * @return success The bool value returns whether the transfer is successful
     */
    function transfer(address to, uint256 value)
        external
        returns (bool success);

}
```

## Rationale

The proposal is to simplify token standards by removing `transferFrom`, `approve` and `allowance` functions. This simplification aims to enhance security, reduce complexity, and improve efficiency, making the standard more suitable for smart contract wallet environments while maintaining essential functionalities.

## Backwards Compatibility

As mentioned in the beginning, this ERC is forward compatible with [ERC-20](/EIPs/EIPS/eip-20), ERC-20 is backward compatible with this ERC.

## Reference Implementation

**forward compatible with [ERC-20](/EIPs/EIPS/eip-20)**

```solidity
pragma solidity ^0.8.20;

import &quot;./IERC7196.sol&quot;;
import &quot;../../math/SafeMath.sol&quot;;

/**
 * @title Standard ERC7196 token
 * @dev Note: the ERC-165 identifier for this interface is 0xc1b31357
 * @dev Implementation of the basic standard token.
 */
contract ERC7196 is IERC7196 {
    using SafeMath for uint256;

    mapping (address =&gt; uint256) private _balances;

    uint256 private _totalSupply;

    function totalSupply() external view returns (uint256) {
        return _totalSupply;
    }

    function balanceOf(address owner) external view returns (uint256) {
        return _balances[owner];
    }

    function transfer(address to, uint256 value) external returns (bool) {
        require(value &lt;= _balances[msg.sender]);
        require(to != address(0));

        _balances[msg.sender] = _balances[msg.sender].sub(value);
        _balances[to] = _balances[to].add(value);
        emit Transfer(msg.sender, to, value);
        return true;
    }

}
```


## Security Considerations

It should be noted that this ERC is not backward compatible with [ERC-20](/EIPs/EIPS/eip-20), so there will be incompatibility with existing dapps.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 21 Jun 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7196</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7196</guid>
      </item>
    
      <item>
        <title>Linter Scope</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/proposal-eipw-should-only-complain-about-changing-lines/14762</comments>
        
        <description>## Abstract

Currently in practice EIP linter tools (EIPW, for example) will block a Pull Request for lint errors even if that lint errors was not introduced in that Pull Request.
This EIP make it explicit that lint errors for untouched lines shall be considered ignorable except for status change.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

In an update to an EIP, A Pull Request SHOULD NOT be required to fix linter errors in untouched lines unless it&apos;s changing the Status of the EIP.

## Rationale

This policy allows micro contributions for anyone who just want to fix a typo or change a section of a section in a large EIP.

## Security Considerations

None 

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 20 Jun 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7199</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7199</guid>
      </item>
    
      <item>
        <title>Namespaced Storage Layout</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7201-namespaced-storage-layout/14796</comments>
        
        <description>## Abstract

We define the NatSpec annotation `@custom:storage-location` to document storage namespaces and their location in storage in Solidity or Vyper source code. Additionally, we define a formula to derive a location from an arbitrary identifier. The formula is chosen to be safe against collisions with the storage layouts used by Solidity and Vyper.

## Motivation

Smart contract languages such as Solidity and Vyper rely on tree-shaped storage layout. This tree starts at slot 0 and is composed of sequential chunks for consecutive variables. Hashes are used to ensure the chunks containing values of mappings and dynamic arrays do not collide. This is sufficient for most contracts. However, it presents a challenge for various design patterns used in smart contract development. One example is a modular design where using `DELEGATECALL` a contract executes code from multiple contracts, all of which share the same storage space, and which have to carefully coordinate on how to use it. Another example is upgradeable contracts, where it can be difficult to add state variables in an upgrade given that they may affect the assigned storage location for the preexisting variables.

Rather than using this default storage layout, these patterns can benefit from laying out state variables across the storage space, usually at pseudorandom locations obtained by hashing. Each value may be placed in an entirely different location, but more frequently values that are used together are put in a Solidity struct and co-located in storage. These pseudorandom locations can be the root of new storage trees that follow the same rules as the default one. Provided that this pseudorandom root is constructed so that it is not part of the default tree, this should result in the definition of independent spaces that do not collide with one another or with the default one.

These storage usage patterns are invisible to the Solidity and Vyper compilers because they are not represented as Solidity state variables. Smart contract tools like static analyzers or blockchain explorers often need to know the storage location of contract data. Standardizing the location for storage layouts will allow these tools to correctly interpret contracts where these design patterns are used.

## Specification

### Preliminaries

A _namespace_ consists of a set of ordered variables, some of which may be dynamic arrays or mappings, with its values laid out following the same rules as the default storage layout but rooted in some location that is not necessarily slot 0. A contract using namespaces to organize storage is said to use _namespaced storage_.

A _namespace id_ is a string that identifies a namespace in a contract. It should not contain any whitespace characters.

### `@custom:storage-location`

A namespace in a contract should be implemented as a struct type. These structs should be annotated with the NatSpec tag `@custom:storage-location &lt;FORMULA_ID&gt;:&lt;NAMESPACE_ID&gt;`, where `&lt;FORMULA_ID&gt;` identifies a formula used to compute the storage location where the namespace is rooted, based on the namespace id. _(Note: The Solidity compiler includes this annotation in the AST since v0.8.20, so this is recommended as the minimum compiler version when using this pattern.)_ Structs with this annotation found outside of contracts are not considered to be namespaces for any contract in the source code.

### Formula

The formula identified by `erc7201` is defined as `erc7201(id: string) = keccak256(keccak256(id) - 1) &amp; ~0xff`. In Solidity, this corresponds to the expression `keccak256(abi.encode(uint256(keccak256(bytes(id))) - 1)) &amp; ~bytes32(uint256(0xff))`. When using this formula the annotation becomes `@custom:storage-location erc7201:&lt;NAMESPACE_ID&gt;`. For example, `@custom:storage-location erc7201:foobar` annotates a namespace with id `&quot;foobar&quot;` rooted at `erc7201(&quot;foobar&quot;)`.

Future EIPs may define new formulas with unique formula identifiers. It is recommended to follow the convention set in this EIP and use an identifier of the format `erc1234`.

## Rationale

The tree-shaped storage layout used by Solidity and Vyper follows the following grammar (with root=0):

$L_{root} := \mathit{root} \mid L_{root} + n \mid \texttt{keccak256}(L_{root}) \mid \texttt{keccak256}(H(k) \oplus L_{root}) \mid \texttt{keccak256}(L_{root} \oplus H(k))$

A requirement for the root is that it shouldn&apos;t overlap with any storage location that would be part of the standard storage tree used by Solidity and Vyper (root = 0), nor should it be part of the storage tree derived from any other namespace (another root). This is so that multiple namespaces may be used alongside each other and alongside the standard storage layout, either deliberately or accidentally, without colliding. The term `keccak256(id) - 1` in the formula is chosen as a location that is unused by Solidity, but this is not used as the final location because namespaces can be larger than 1 slot and would extend into `keccak256(id) + n`, which is potentially used by Solidity. A second hash is added to prevent this and guarantee that namespaces are completely disjoint from standard storage, assuming keccak256 collision resistance and that arrays are not unreasonably large.

Additionally, namespace locations are aligned to 256 as a potential optimization, in anticipation of gas schedule changes after the Verkle state tree migration, which may cause groups of 256 storage slots to become warm all at once.

### Naming

This pattern has sometimes been referred to as &quot;diamond storage&quot;. This causes it to be conflated with the &quot;diamond proxy pattern&quot;, even though they can be used independently of each other. This EIP has chosen to use a different name to clearly differentiate it from the proxy pattern.

## Backwards Compatibility

No backward compatibility issues found.

## Reference Implementation

```solidity
pragma solidity ^0.8.20;

contract Example {
    /// @custom:storage-location erc7201:example.main
    struct MainStorage {
        uint256 x;
        uint256 y;
    }

    // keccak256(abi.encode(uint256(keccak256(&quot;example.main&quot;)) - 1)) &amp; ~bytes32(uint256(0xff));
    bytes32 private constant MAIN_STORAGE_LOCATION =
        0x183a6125c38840424c4a85fa12bab2ab606c4b6d0e7cc73c0c06ba5300eab500;

    function _getMainStorage() private pure returns (MainStorage storage $) {
        assembly {
            $.slot := MAIN_STORAGE_LOCATION
        }
    }

    function _getXTimesY() internal view returns (uint256) {
        MainStorage storage $ = _getMainStorage();
        return $.x * $.y;
    }
}
```


## Security Considerations

Namespaces should avoid collisions with other namespaces or with standard Solidity or Vyper storage layout. The formula defined in this ERC guarantees this property for arbitrary namespace ids under the assumption of keccak256 collision resistance, as discussed in Rationale.

`@custom:storage-location` is a NatSpec annotation that current compilers don&apos;t enforce any rules for or ascribe any meaning to. The contract developer is responsible for implementing the pattern and using the namespace as claimed in the annotation.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 20 Jun 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7201</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7201</guid>
      </item>
    
      <item>
        <title>Contract wallet management token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/token-asset-management-interface-with-smart-contract-wallet/14759</comments>
        
        <description>## Abstract

This proposal introduces a smart contract wallet-based approach for managing tokens, focusing on utilizing the programmable features of smart contract wallets for asset management. 
Additionally, it introduces functions such as `tokenTransfer`, `tokenApprove`, `tokenApproveForAll`, `tokenIsApproveForAll` and `tokenAllowance`, which provide enhanced control over token transactions. This approach seeks to enhance token management by utilizing the built-in features of smart contract wallets, thus offering a more adaptable, secure, and efficient method for managing token transactions.


## Motivation

An externally-owned account (EOA) wallet has no state and code storage, while the smart contract wallet does.

Account abstraction (AA) is a direction of the smart contract wallet, which works around abstract accounts. This ERC can also be an extension based on [ERC-4337](/EIPs/EIPS/eip-4337) or as a plug-in for wallets.

The smart contract wallet allows the user&apos;s own account to have state and code, bringing programmability to the wallet. We think there are more directions to expand. For example, token asset management, functional expansion of token transactions, etc.

The smart contract wallet interface of this ERC is for asset management and asset approval. It supports the simpletoken &lt;!-- TODO --&gt; ERC-X, and [ERC-20](/EIPs/EIPS/eip-20) is backward compatible with &lt;!-- TODO --&gt; ERC-X, so it can be compatible with the management of all fungible tokens in the existing market.

The proposal aims to achieve the following goals:

1. Assets are allocated and managed by the wallet itself, such as `approve` and `allowance`, which are configured by the user’s contract wallet, rather than controlled by the token asset contract, to avoid some existing ERC-20 contract risks.
2. Add the `tokenTransfer` function, the transaction initiated by the non-smart wallet itself or will verify the allowance amount.
3. Add `tokenApprove`, `tokenAllowance`, `tokenApproveForAll`, `tokenIsApproveForAll` functions. The user wallet itself supports approve and provides approve.
 for single token assets and all token assets.
4. user wallet can choose batch approve and batch transfer. 
5. Users can choose to add hook function before and after their `tokenTransfer` to increase the user&apos;s more playability.
6. The user can choose to implement the `tokenReceive` function.


## Specification

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

** Compliant contract must implement the [ERC-165](/EIPs/EIPS/eip-165) interfaces**

```solidity
/// @title ERC-7204 
/// @dev See https://eips.ethereum.org/EIPS/eip-7204
/// @dev Note: the ERC-165 identifier for this interface is 0xf73edcda
pragma solidity ^0.8.20;

interface IERC7204 /* is ERC165 */ {

    /**
     * @notice Used to notify listeners that owner has granted approval to the user to manage assets tokens.
     * @param asset Address of the token
     * @param owner Address of the account that has granted the approval for token‘s assets
     * @param spender Address of the spender
     * @param value The amount allowed to spend
     */
    event TokenApproval(
        address indexed asset,
        address indexed owner, 
        address indexed spender, 
        uint256 value
    );

    /**
     * @notice Used to notify listeners that owner has granted approval to the spender to manage all token .
     * @param asset Address of the token
     * @param owner Address of the account that has granted the approval for token‘s assets
     * @param approved approve all token
     */
    event TokenApprovalForAll(
        address indexed owner, 
        address indexed spender,
        bool approved
    );

    /**
     * @notice Approve token
     * @dev Allows spender address to withdraw from your account multiple times, up to the value amount.
     * @dev If this function is called again it overwrites the current allowance with value.
     * @dev Emits an {TokenApproval} event.
     * @param asset Address of the token
     * @param spender Address of the spender
     * @param value The amount allowed to spend
     * @return success The bool value returns whether the approve is successful
     */
    function tokenApprove(address asset, address spender, uint256 value) 
        external 
        returns (bool success);

    /**
     * @notice read token allowance value
     * @param asset Address of the token
     * @param spender Address of the spender
     * @return remaining The asset amount which spender is still allowed to withdraw from owner.
     */
    function tokenAllowance(address asset, address spender) 
        external
        view
        returns (uint256 remaining);

    /**
     * @notice Approve all token
     * @dev Allows spender address to withdraw from your wallet all token.
     * @dev Emits an {TokenApprovalForAll} event.
     * @param spender Address of the spender
     * @param approved Approved all tokens
     * @return success The bool value returns whether the approve is successful
     */
    function tokenApproveForAll(address spender, bool approved) 
        external 
        returns (bool success);

    /**
     * @notice read spender approved value
     * @param spender Address of the spender
     * @return approved Whether to approved spender all tokens
     */
    function tokenIsApproveForAll(address spender) 
        external
        view
        returns (bool approved);

    /**
     * @notice Transfer token
     * @dev must call asset.transfer() inside the function
     * @dev If the caller is not wallet self, must verify the allowance and update the allowance value
     * @param asset Address of the token
     * @param to Address of the receive
     * @param value The transaction amount
     * @return success The bool value returns whether the transfer is successful
     */
    function tokenTransfer(address asset, address to, uint256 value) 
        external 
        returns (bool success); 
}
```


## Rationale

the key technical decisions in this proposal are:

**Improved Approve Mechanism**
- **Current vs. Proposed**: In the existing ERC-20 system, an externally-owned account (EOA) directly interacts with token contracts to `approve`. The new `tokenApprove` and `tokenApproveForAll` functions in this proposed enable more precise control over token usage within a wallet contract, a significant improvement over the traditional method.
- **Enhanced Security**: This mechanism mitigates risks like token over-approval by shifting approval control to the user&apos;s smart contract wallet.
- **Programmability**: Users gain the ability to set advanced approval strategies, such as conditional or time-limited approvals, the `tokenApproveForAll` function specifically allows for a universal setting  all tokens. these were not possible with traditional ERC-20 tokens.

**Optimized Transfer Process**
- **Efficiency and Security**: The `tokenTransfer` function streamlines the token transfer process, making transactions both more efficient and secure.
- **Flexibility**: Allows the integration of custom logic (hooks) before and after transfers, enabling additional security checks or specific actions tailored to the user’s needs.

**Support for Batch Operations**
- **Increased Efficiency**: Users can simultaneously handle multiple `approve` or `transfer` operations, significantly boosting transaction efficiency.
- **Enhanced User Experience**: Simplifies the management of numerous assets, improving the overall experience for users with large portfolios.



## Backwards Compatibility

This ERC can be used as an extension of [ERC-4337](/EIPs/EIPS/eip-4337) and is backward compatible with ERC-4337.

## Security Considerations

No security considerations were found.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 21 Jun 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7204</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7204</guid>
      </item>
    
      <item>
        <title>On-Chain Data Containers</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7208-on-chain-data-container/14778</comments>
        
        <description>## Abstract


This ERC defines a series of interfaces for the abstraction of storage of on-chain data by implementing the logic functions that govern such data on independent smart contracts. &quot;On-chain Data Containers&quot; (ODCs) refer to the separation and indexing of data storage away from data management. We propose that on-chain data can be abstracted and stored in smart contracts called &quot;Data Objects&quot; (DO), which answer to external data indexing mechanisms named &quot;Data Points&quot; (DP). This data can be accessed and modified by implementing (one or many) separate smart contracts identified as &quot;Data Managers&quot; (DM). We introduce two mechanisms for access management: first, through a &quot;Data Index&quot; (DI) implementation, the &quot;Data Managers&quot; (DM) can be gated from accessing &quot;Data Objects&quot; (DO); second, a &quot;Data Point Registry&quot; (DPR) implementation manages the issuance of &quot;Data Points&quot; (DP). Lastly, we introduce the concept of data portability (horizontal data mobility) between implementations of &quot;Data Index&quot; (DI), enabling massive updates to the logic without affecting the underlying data storage.


## Motivation

As the Ethereum ecosystem grows, so does the demand for on-chain functionalities. The market encourages a desire for broader adoption through more complex systems and there is a constant need for improved efficiency. We have seen times when an explosion of new standard token proposals was solely driven by market hype. While ultimately each standard serves its purpose, most of them require more flexibility to manage interoperability with other standards. A standard adapter mechanism is needed to enhance interoperability by driving the interactions between assets issued under different ERCs.


Without such mechanisms, most projects have implemented bespoke solutions for interoperability. This is an inefficient approach and leads to a fragmented ecosystem. We recognize there is no “one size fits all” solution to solve the standardization and interoperability challenges. Most assets - Fungible, Non-Fungible, Digital Twins, Real-world Assets, DePin, etc - have multiple mechanisms for representing them as on-chain tokens through the use of different standard interfaces and the diversity of standards spurs innovation.

However, for these assets to be exchanged, traded, or otherwise interacted with, protocols must implement compatibility with the relevant interfaces to access and modify on-chain data. This is especially challenging when considering the previously mentioned bespoke solutions for interoperability. Additionally, the immutability of smart contracts complicates the ability of already deployed protocols to adapt to new tokenization standards, which is critical for future-proofing implementations. A collaborative effort must be made to enable interaction between assets tokenized under different standards. The current ERC provides the tools for developing such on-chain adapters.

We aim to abstract the on-chain data handling from the logical implementation, exposing the underlying data independently of the ERC interface. We propose a series of interfaces for storing and accessing data on-chain in contracts called &quot;Data Objects&quot; (DO), grouping the underlying assets as generic &quot;Data Points&quot; (DP) that may be associated with multiple interoperable and even concurrent &quot;Data Manager&quot; (DM) contracts. This proposal is designed to work by coexisting with previous and future token standards, providing a flexible, efficient, and coherent mechanism to manage asset interoperability.

- **Data Abstraction**: We propose a standardized interface for enabling developers to separate the data storage code from the underlying token utility logic, reducing the need for supporting and implementing multiple inherited -and often clashing- interfaces to achieve asset compatibility. The data (and therefore the assets) can be stored independently of the logic that governs such data.

- **Standard Neutrality**: A neutral approach must enable the underlying data of any tokenized asset to transition seamlessly between different token standards. This will significantly improve interoperability among other standards, reducing fragmentation in the landscape. Our proposal aims to separate the storage of data representing an underlying asset from the standard interface used for representing the token.

- **Consistent Interface**: A uniform interface of primitive functions abstracts the data storage from the use case, irrespective of the underlying token&apos;s standard or the interface exposing such data. Data and metadata can be stored on-chain, and exposed through the same primitives.

- **Data Portability**: We provide a mechanism for the Horizontal Mobility of data between implementations of this standard, incentivizing the implementation of interoperable solutions and standard adapters.



## Specification

### Terms

**Data Point**: A uniquely identifiable reference to an on-chain data structure stored within one or many **Data Objects** and managed by one or many **Data Managers**. **Data Points** are issued by a **Data Point Registry**.

**Data Object**: A Smart Contract implementing the low-level storage management of information indexed through **Data Points**.

**Data Manager**: One or many Smart Contracts implementing the high-level logic and end-user interfaces for managing Data Objects.

**Data Point Registry**: One or many Smart Contracts used for managing the issuance of **Data Points**. Additionally, a **Data Point Registry** defines a space of compatible or interoperable **Data Points**.

**Data Index**: One or many Smart Contracts used for managing the access of **Data Managers** to **Data Objects**.

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119 and RFC 8174.


### Data Point Structure

 * Data Point MUST be `bytes32` storage units.
 * Data Point SHOULD NOT be used for storing asset data.
 * Data Point SHOULD be used for indexing data.
 * Data Point SHOULD use a 4 bytes prefix for storing information relevant to the compatibility with other Data Points.
 * Data Point MUST use 4 bytes for storing the Chain ID
 * Data Point SHOULD use the last 20 bytes for identifying which Registry allocated them.
 * The RECOMMENDED internal structure of the Data Point is as follows:

```solidity
/**
 * RECOMMENDED internal DataPoint structure on the Reference Implementation:
 * 0xPPPPVVRRIIIIIIIIHHHHHHHHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 * - Prefix (bytes4)
 * -- PPPP - Type prefix (i.e. 0x4450 - ASCII representation of letters &quot;DP&quot;)
 * -- VV   - Version of DataPoint specification (i.e. 0x00 for the reference implementation)
 * -- RR   - Reserved
 * - Registry-local identifier
 * -- IIIIIIII - 32 bit implementation-specific id of the DataPoint
 * - Chain ID (bytes4)
 * -- HHHHHHHH - 32 bit of chain identifier
 * - REGISTRY Address (bytes20)
 * -- AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - Address of Registry which allocated the DataPoint
**/
```

**Data Points** are a low-level structure abstracting and indexing information. **Data Points** act as pointers to information stored within data structures in **Data Objects**.
**Data Points** are allocated by a **Data Point Registry**. The **Data Point** SHOULD store which **Data Point Registry** initialized it within its internal structure. Each **Data Point** SHOULD have a unique identifier provided by the **Data Point Registry** when instantiated.



### Data Object Interface

 * Data Object SHOULD be used for storing asset data.
 * Data Object SHOULD use **Data Points** for indexing the structure storing the data.
 * Data Object SHOULD implement the logic directly related to handling the data structure.
 * Data Object SHOULD implement the logic for transferring management of its **Data Points** to a different **Data Index** implementation.
 * Data Object MUST use the IDataObject interface:

```solidity
interface IDataObject {
    /**
     * @notice Reads stored data
     * @param dp Identifier of the DataPoint
     * @param operation Read operation to run on the data
     * @param data Operation-specific data
     * @return Operation-specific data
     */
    function read(bytes32 dp, bytes4 operation, bytes calldata data) external view returns(bytes memory);

    /**
     * @notice Store data
     * @param dp Identifier of the DataPoint
     * @param operation Write operation to execute on the data
     * @param data Operation-specific data
     * @return Operation-specific data (can be empty)
     */
    function write(bytes32 dp, bytes4 operation, bytes calldata data) external returns(bytes memory);

    /**
     * @notice Sets DataIndex Implementation
     * @param dp Identifier of the DataPoint
     * @param newImpl address of the new DataIndex implementation
     */
    function setDIImplementation(bytes32 dp, address newImpl) external;
}
```
**Data Objects** are entrusted with the storage and management of data. **Data Objects** SHOULD implement the logic for managing the storage of on-chain data. **Data Object** internal data structure SHOULD use **Data Points** for indexing information.

**Data Objects** CAN receive `read()`, `write()`, or any other custom requests from a **Data Manager** requesting access to a storage structure indexed by a **Data Point**.

As such, **Data Objects** respond to a gating mechanism given by a single **Data Index**. The function `setDIImplementation()` SHOULD enable the delegation of the management function to an `IDataIndex` implementation.



### Data Manager Contract

 * Data Manager SHOULD use `IDataIndex.read()` or `IDataObject.read()` to read data from **Data Objects**
 * Data Manager MUST use `IDataIndex.write()` to write data to **Data Objects**
 * Data Manager MAY share **Data Point** with other **Data Managers**
 * Data Manager MAY use multiple **Data Points**
 * Data Manager SHOULD implement the logic for requesting **Data Points** from a **Data Point Registry**.

**Data Managers** are independent smart contracts that implement the business logic or &quot;high-level&quot; data management. They can `read()` from a **Data Object** address and `write()` through a **Data Index** implementation managing the delegated storage of the **Data Points**.



### Data Point Registry Interface


 * Data Point Registry SHOULD define functions to manage the creation, transfer, and access control of **Data Points**
 * Data Point Registry SHOULD manage **Data Point** access management for **Data Managers**
 * Data Point Registry MUST use the IDataPointRegistry interface:

```solidity
interface IDataPointRegistry {

  /**
     * @notice Verifies if an address has an Admin role for a DataPoint
     * @param dp DataPoint
     * @param account Account to verify
     */
    function isAdmin(bytes32 dp, address account) external view returns (bool);

    /**
     * @notice Allocates a DataPoint to an owner
     * @param owner Owner of the new DataPoint
     * @dev Owner should be granted Admin role during allocation
     */
    function allocate(address owner) external payable returns (DataPoint);

    /**
     * @notice Transfers a DataPoint to an owner
     * @param dp Data Point to be transferred
     * @param owner Owner of the new DataPoint
     */
    function transferOwnership(bytes32 dp, address newOwner) external;

    /**
     * @notice Grant permission to grant/revoke other roles on the DataPoint inside a Data Index Implementation
     * This is useful if DataManagers are deployed during lifecycle of the application.
     * @param dp DataPoint
     * @param account New admin
     * @return If the role was granted (otherwise account already had the role)
     */
    function grantAdminRole(bytes32 dp, address account) external returns (bool);

    /**
     * @notice Revoke permission to grant/revoke other roles on the DataPoint inside a Data Index Implementation
     * @param dp DataPoint
     * @param account Old admin
     * @dev If an owner revokes Admin role from himself, he can add it again
     * @return If the role was revoked (otherwise account didn&apos;t have the role)
     */
    function revokeAdminRole(bytes32 dp, address account) external returns (bool);
}
```
The **Data Point Registry** is a smart contract entrusted with **Data Point** access control. **Data Managers** may request the allocation of **Data Points** to the **Data Point Registry**.




### Data Index Interface

 * DataIndex SHOULD manage the access of **Data Managers** to **Data Objects**.
 * DataIndex SHOULD manage internal IDs for each user.
 * DataIndex MUST use the IDataIndex interface:

```solidity
interface IDataIndex {
    /**
     * @notice Verifies if DataManager is allowed to write specific DataPoint on specific DataObject
     * @param dp Identifier of the DataPoint
     * @param dm Address of DataManager
     * @return if write access is allowed
     */
    function isApprovedDataManager(bytes32 dp, address dm) external view returns(bool);

    /**
     * @notice Defines if DataManager is allowed to write specific DataPoint
     * @param dp Identifier of the DataPoint
     * @param dm Address of DataManager
     * @param approved if DataManager should be approved for the DataPoint
     * @dev Function should be restricted to DataPoint maintainer only
     */
    function allowDataManager(bytes32 dp, address dm, bool approved) external;

    /**
     * @notice Reads stored data
     * @param dobj Identifier of DataObject
     * @param dp Identifier of the datapoint
     * @param operation Read operation to execute on the data
     * @param data Operation-specific data
     * @return Operation-specific data
     */
    function read(address dobj, bytes32 dp, bytes4 operation, bytes calldata data) external view returns(bytes memory);

    /**
     * @notice Store data
     * @param dobj Identifier of DataObject
     * @param dp Identifier of the datapoint
     * @param operation Read operation to execute on the data
     * @param data Operation-specific data
     * @return Operation-specific data (can be empty)
     * @dev Function should be restricted to allowed DMs only
     */
    function write(address dobj, bytes32 dp, bytes4 operation, bytes calldata data) external returns(bytes memory);
}
```
The **Data Index** is a smart contract entrusted with access control. It is a gating mechanism for **Data Managers** to access **Data Objects**. If a **Data Manager** intends to access a **Data Point** (either by `read()`, `write()`, or any other method), the **Data Index** SHOULD be used for validating access to the data.

The mechanism for ID management determines a space of compatibility between implementations.


## Rationale


The decision to encode **Data Points** as `bytes32` data pointers is primarily driven by flexibility and future-proofing. The use `bytes32` allows for a wide range of data encodings. This provides the developer with many options to accommodate diverse use cases. Furthermore, as Ethereum and its standards continue to evolve, encoding as `bytes32` ensures that the Standard Adapters built with the current ERC can reference future data types or structures without requiring significant changes to the adapter itself. The **Data Point** encoding should have a prefix so that the **Data Object** can efficiently identify compatibility issues when accessing the data storage. Additionally, the prefix should be used to find the **Data Point Registry** and verify admin access to the **Data Point**. The use of a suffix for identifying the **Data Point Registry** is also required, for the **Data Object** to quickly discard badly formed transactions that aim to use a **Data Point** from an unmatching **Data Point Registry**.


**Data Manager** implementations decide which **Data Points** they will be using. Their allocation is managed through a **Data Point Registry**, and the `write()` access to the **Data Point** is managed by passing through the **Data Index** implementation.

**Data Objects** are independent separate Smart Contracts that implement the same `read`/`write` interface for communicating with **Data Managers**. This is a decision mainly driven by the scalability of the system. Offering a simple interface for this layered structure enables different applications to have their addresses for storage of data independently from the asset&apos;s interface. It is up to each implementation to manage access to their **Data Point** storage space. This enables a wide array of complex, dynamic, and interactive use cases to be implemented with multiple ERCs as well as other smart contracts, including the embedding of cross-chain and rollup logic for asset management.

**Data Objects** offer flexibility in storing mutable on-chain data that can be modified as per the requirements of each specific use case. This enables the **Data Managers** to hold mutable states in delegated storage and reflect changes over time, providing a dynamic layer to the otherwise static nature of storage through most other standardized interfaces.

**Data Managers** can decide to migrate the complete storage management of a **Data Object** from one **Data Index** implementation to another. As the **Data Index** implements user ID management, this mechanism enables a **Data Manager** to upgrade its internal access control mechanisms without affecting the underlying storage of value, as it is located elsewere (in the **Data Object**). We call this mechanism &quot;Horizontal Data Mobility/Portability&quot;.


## Backwards Compatibility

This ERC is intended to augment the functionality of existing token standards without introducing breaking changes. As such, it does not present any backward compatibility issues. Already deployed tokens under other ERCs can be wrapped and indexed as **Data Points** and managed by **Data Objects**, and later exposed through any implementation of **Data Managers**. All interoperability integrations will require a compatibility analysis, depending on the use case. However, the interfaces defined in this ERC define a framework for adapting one standard to another through storage abstraction.

## Reference Implementation

We present an *educational example* implementation of a Standard Adapter showcasing two types of tokens (Fungible and Semi-Fungible) with shared data storage. The end user can interact with this implementation through one of two types of interfaces: The semi-fungible one (represented through a single **Data Manager**), and the fungible interface (represented by many **Data Managers**). The abstraction of the storage from the logic is achieved through the use of a single *Fungible Fractions* **Data Object**. A factory is used for deploying the Fungible token interfaces that share storage with each semi-fungible collection. Note that if a `transfer()` is called by either interface (Fungible or Semi-Fungible), both interfaces are emitting an event.


**This example has not been audited and should not be used in production environments.**


See [contracts](/EIPs/assets/eip-7208/contracts/)


## Security Considerations

The access control is separated into three layers:

* **Layer 1**: The **Data Point Registry** allocates for **Data Managers** and manages ownership (admin/write rights) of **Data Points**.
* **Layer 2**: The **Data Index** smart contract implements Access Control by managing Approvals of **Data Managers** to **Data Points**. It uses the **Data Point Registry** to verify who can grant/revoke this access.
* **Layer 3**: The **DataObject** manages trust relationship between the **DataPoint** and a **DataIndex**  implementation and allows a trusted **DataIndex** to execute `write` operations.

A common task for a **Data Object** is to store user-related data, while the **Data Manager** implements the logic for managing such data. Both **Data Objects** and **Data Managers** often require the management of user IDs. A **Data Index** can offer logic for user management (i.e. IDs based on `address`) that are independent of any particular implementation, but care must be taken in selecting these identifiers. If chosen improperly, they could hinder a **Data Manager**&apos;s ability to migrate between different **Data Indexes**.

No further security considerations are derived specifically from this ERC.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Fri, 09 Jun 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7208</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7208</guid>
      </item>
    
      <item>
        <title>Identity-aggregated NFT</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc7231-identity-aggregated-nft/15062</comments>
        
        <description>## Abstract

This standard extends [ERC-721](/EIPs/EIPS/eip-721) by binding individuals&apos; Web2 and Web3 identities to non-fungible tokens (NFTs) and soulbound tokens (SBTs). By binding multiple identities, aggregated and composible identity infomation can be verified, resulting in more beneficial onchain scenarios for individuals, such as self-authentication, social overlapping, commercial value generation from user targetting, etc. By adding a custom schema in the metadata, and updating and verifying the schema hash in the contract, the binding of NFT and identity information is completed.

## Motivation

One of the most interesting aspects of Web3 is the ability to bring an individual&apos;s own identity to different applications. Even more powerful is the fact that individuals truly own their accounts without relying on centralized gatekeepers, disclosing to different apps components necessary for authentication and approved by individuals. 
Exisiting solutions such as ENS, although open, decentralized, and more convenient for Ethereum-based applications, suffer from a lack of data standardization and authentication of identity due to inherent anominity. Other solutions such as SBTs rely on centralized attestors, can not prevent data tampering, and do not inscribe data into the ledger itself in a privacy enabling way.  
The proposed pushes the boundaries of solving identity problems with Identity Aggregated NFT, i.e., the individual-authenticated aggregation of web2 and web3 identities to NFTs (SBTs included). 

## Specification

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.

### Every compliant contract must implement the Interface

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.15;

interface IERC7231 {

    /**
     * @notice emit the use binding information
     * @param id nft id 
     * @param identitiesRoot new identity root
     */
    event SetIdentitiesRoot(
        uint256 id,
        bytes32 identitiesRoot
    );

    /**
     * @notice 
     * @dev set the user ID binding information of NFT with identitiesRoot
     * @param id nft id 
     * @param identitiesRoot multi UserID Root data hash
     * MUST allow external calls
     */
    function setIdentitiesRoot(
        uint256 id,
        bytes32 identitiesRoot
    ) external;

    /**
     * @notice 
     * @dev get the multi-userID root by  NFTID
     * @param id nft id 
     * MUST return the bytes32 multiUserIDsRoot
     * MUST NOT modify the state
     * MUST allow external calls
     */
    function getIdentitiesRoot(
        uint256 id
    ) external returns(bytes32);

    /**
     * @notice 
     * @dev verify the userIDs binding 
    * @param id nft id 
     * @param userIDs userIDs for check
     * @param identitiesRoot msg hash to verify
     * @param signature ECDSA signature 
     * MUST If the verification is passed, return true, otherwise return false
     * MUST NOT modify the state
     * MUST allow external calls
     */
    function verifyIdentitiesBinding(
        uint256 id,address nftOwnerAddress,string[] memory userIDs,bytes32 identitiesRoot, bytes calldata signature
    ) external returns (bool);
}
```

This is the “Metadata JSON Schema” referenced above.

```json
{
  &quot;title&quot;: &quot;Asset Metadata&quot;,
  &quot;type&quot;: &quot;object&quot;,
  &quot;properties&quot;: {
    &quot;name&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Identifies the asset to which this NFT represents&quot;
    },
    &quot;description&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Describes the asset to which this NFT represents&quot;
    },
    &quot;image&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;A URI pointing to a resource with mime type image&quot;
    },
    &quot;MultiIdentities&quot;: [
      {
        &quot;userID&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;User ID of Web2 and web3(DID)&quot;
        },
        &quot;verifierUri&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;Verifier Uri of the userID&quot;
        },
        &quot;memo&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;description&quot;: &quot;Memo of the userID&quot;
        },
        &quot;properties&quot;: {
          &quot;type&quot;: &quot;object&quot;,
          &quot;description&quot;: &quot;properties of the user ID information&quot;
        }
      }
    ]
  }
}
```

## Rationale

Designing the proposal, we considered the following problems that are solved by this standard:
![EIP Flow Diagram](/EIPs/assets/eip-7231/img/Identity-aggregated-NFT-flow.png)

1. Resolve the issue of multiple ID bindings for web2 and web3.
By incorporating the MultiIdentities schema into the metadata file, an authorized bond is established between user identity information and NFTs. This schema encompasses a userID field that can be sourced from a variety of web2 platforms or a decentralized identity (DID) created on blockchain. By binding the NFT ID with the UserIDInfo array, it becomes possible to aggregate multiple identities seamlessly.
1. Users have full ownership and control of their data
Once the user has set the metadata, they can utilize the setIdentitiesRoot function to establish a secure binding between hashed userIDs objects and NFT ID. As only the user holds the authority to carry out this binding, it can be assured that the data belongs solely to the user.
1. Verify the binding relationship between data on-chain and off-chain data through signature based on [ERC-1271](/EIPs/EIPS/eip-1271)
Through the signature method based on the [ERC-1271](/EIPs/EIPS/eip-1271) protocol, the verifyIdentiesBinding function of this EIP realizes the binding of the userID and NFT owner address between on-chain and off-chain.
   1. NFT ownership validation
   2. UserID format validation
   3. IdentitiesRoot Consistency verification
   4. Signature validation from nft owner

As for how to verify the authenticity of the individuals&apos; identities, wallets, accounts, there are various methods, such as zk-based DID authentication onchain, and offchain authentication algorithms, such as auth2, openID2, etc.

## Backwards Compatibility

As mentioned in the specifications section, this standard can be fully [ERC-721](/EIPs/EIPS/eip-721) compatible by adding an extension function set.
In addition, new functions introduced in this standard have many similarities with the existing functions in [ERC-721](/EIPs/EIPS/eip-721). This allows developers to easily adopt the standard quickly.

## Test Cases

Tests are included in [`erc7231.ts`](/EIPs/assets/eip-7231/test/erc7231.ts).

To run them in terminal, you can use the following commands:

```
cd ../assets/eip-7231
npm install
npx hardhat test
```

## Reference Implementation

`ERC7231.sol` Implementation: [`ERC7231.sol`](/EIPs/assets/eip-7231/contracts/ERC7231.sol)

## Security Considerations

This EIP standard can comprehensively empower individuals to have ownership and control of their identities, wallets, and relevant data by themselves adding or removing the NFTs and identity bound information. 

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 25 Jun 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7231</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7231</guid>
      </item>
    
      <item>
        <title>Encumber - Splitting Ownership &amp; Guarantees</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/encumber-extending-the-erc-20-token-standard-to-allow-pledging-tokens-without-giving-up-ownership/14849</comments>
        
        <description>## Abstract

This ERC proposes an extension to the [ERC-20](/EIPs/EIPS/eip-20) token standard by adding Encumber—the ability for an account to grant another account exclusive right to move some portion of their balance. Encumber is a stronger version of [ERC-20](/EIPs/EIPS/eip-20) allowances. While [ERC-20](/EIPs/EIPS/eip-20) approve grants another account the permission to transfer a specified token amount, encumber grants the same permission while ensuring that the tokens will be available when needed.

## Motivation

This extension adds flexibility to the [ERC-20](/EIPs/EIPS/eip-20) token standard and caters to use cases where token locking is required, but it is preferential to maintain actual ownership of tokens. This interface can also be adapted to other token standards, such as [ERC-721](/EIPs/EIPS/eip-721), in a straightforward manner

Token holders commonly transfer their tokens to smart contracts which will return the tokens under specific conditions. In some cases, smart contracts do not actually need to hold the tokens, but need to guarantee they will be available if necessary. Since allowances do not provide a strong enough guarantee, the only way to do guarantee token availability presently is to transfer the token to the smart contract. Locking tokens without moving them gives more clear indication of the rights and ownership of the tokens. This allows for airdrops and other ancillary benefits of ownership to reach the true owner. It also adds another layer of safety, where draining a pool of [ERC-20](/EIPs/EIPS/eip-20) tokens can be done in a single transfer, iterating accounts to transfer encumbered tokens would be significantly more prohibitive in gas usage.

## Specification

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

A compliant token MUST implement the following interface

```solidity
/**
 * @dev Interface of the ERC-7246 standard.
 */
interface IERC7246{
    /**
     * @dev Emitted when `amount` tokens are encumbered from `owner` to `taker`.
     */
    event Encumber(address indexed owner, address indexed taker, uint amount);

    /**
     * @dev Emitted when the encumbrance of a `taker` to an `owner` is reduced by `amount`.
     */
    event Release(address indexed owner, address indexed taker, uint amount);

    /**
     * @dev Returns the total amount of tokens owned by `owner` that are currently encumbered.
     * MUST never exceed `balanceOf(owner)`
     *
     * Any function which would reduce balanceOf(owner) below encumberedBalanceOf(owner) MUST revert
     */
    function encumberedBalanceOf(address owner) external returns (uint);

    /**
     * @dev Returns the number of tokens that `owner` has encumbered to `taker`.
     *
     * This value increases when {encumber} or {encumberFrom} are called by the `owner` or by another permitted account.
     * This value decreases when {release} and {transferFrom} are called by `taker`.
     */
    function encumbrances(address owner, address taker) external returns (uint);

    /**
     * @dev Increases the amount of tokens that the caller has encumbered to `taker` by `amount`.
     * Grants to `taker` a guaranteed right to transfer `amount` from the caller&apos;s balance by using `transferFrom`.
     *
     * MUST revert if caller does not have `amount` tokens available
     * (e.g. if `balanceOf(caller) - encumberedBalanceOf(caller) &lt; amount`).
     *
     * Emits an {Encumber} event.
     */
    function encumber(address taker, uint amount) external;

    /**
     * @dev Increases the amount of tokens that `owner` has encumbered to `taker` by `amount`.
     * Grants to `taker` a guaranteed right to transfer `amount` from `owner` using transferFrom
     *
     * The function SHOULD revert unless the owner account has deliberately authorized the sender of the message via some mechanism.
     *
     * MUST revert if `owner` does not have `amount` tokens available
     * (e.g. if `balanceOf(owner) - encumberedBalanceOf(owner) &lt; amount`).
     *
     * Emits an {Encumber} event.
     */
    function encumberFrom(address owner, address taker, uint amount) external;

    /**
     * @dev Reduces amount of tokens encumbered from `owner` to caller by `amount`
     *
     * Emits a {Release} event.
     */
    function release(address owner, uint amount) external;


    /**
     * @dev Convenience function for reading the unencumbered balance of an address.
     * Trivially implemented as `balanceOf(owner) - encumberedBalanceOf(owner)`
     */
    function availableBalanceOf(address owner) public view returns (uint);
}
```

## Rationale
The specification was designed to complement and mirror the ERC-20 specification to ease adoption and understanding. The specification is intentionally minimally proscriptive of this joining, where the only true requirement is that an owner cannot transfer encumbered tokens. However, the example implementation includes some decisions about where to connect with ERC-20 functions worth noting. It was designed for minimal invasiveness of standard ERC-20 definitions.
    - The example has a dependency on `approve` to facilitate `encumberFrom`. This proposal allows for an implementer to define another mechanism, such as an `approveEncumber` which would mirror ERC-20 allowances, if desired.
    - `transferFrom(src, dst, amount)` is written to first reduce the `encumbrances(src, amount)`, and then subsequently spend from `allowance(src, msg.sender)`. Alternatively, `transferFrom` could be implemented to spend from allowance simultaneously to spending encumbrances. This would require `approve` to check that the approved balance does not decrease beneath the amount required by encumbered balances, and also make creating the approval a prerequisite to calling `encumber`.

It is possible to stretch the Encumber interface to cover ERC-721 tokens by using the `tokenId` in place of `amount` param since they are both `uint`. The interface opts for clarity with the most likely use case (ERC-20), even if it is compatible with other formats.



## Backwards Compatibility

This EIP is backwards compatible with the existing [ERC-20](/EIPs/EIPS/eip-20) standard. Implementations must add the functionality to block transfer of tokens that are encumbered to another account.


## Reference Implementation

This can be implemented as an extension of any base [ERC-20](/EIPs/EIPS/eip-20) contract by modifying the transfer function to block the transfer of encumbered tokens and to release encumbrances when spent via transferFrom.


``` solidity
// An erc-20 token that implements the encumber interface by blocking transfers.

pragma solidity ^0.8.0;
import {ERC20} from &quot;../lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol&quot;;
import { IERC7246 } from &quot;./IERC7246.sol&quot;;

contract EncumberableERC20 is ERC20, IERC7246 {
    // Owner -&gt; Taker -&gt; Amount that can be taken
    mapping (address =&gt; mapping (address =&gt; uint)) public encumbrances;

    // The encumbered balance of the token owner. encumberedBalance must not exceed balanceOf for a user
    // Note this means rebasing tokens pose a risk of diminishing and violating this prototocol
    mapping (address =&gt; uint) public encumberedBalanceOf;

    address public minter;

    constructor(string memory name, string memory symbol) ERC20(name, symbol) {
        minter = msg.sender;
    }

    function mint(address recipient, uint amount) public {
        require(msg.sender == minter, &quot;only minter&quot;);
        _mint(recipient, amount);
    }

    function encumber(address taker, uint amount) external {
        _encumber(msg.sender, taker, amount);
    }

    function encumberFrom(address owner, address taker, uint amount) external {
        require(allowance(owner, msg.sender) &gt;= amount);
       _encumber(owner, taker, amount);
    }

    function release(address owner, uint amount) external {
        _release(owner, msg.sender, amount);
    }

    // If bringing balance and encumbrances closer to equal, must check
    function availableBalanceOf(address a) public view returns (uint) {
        return (balanceOf(a) - encumberedBalanceOf[a]);
    }

    function _encumber(address owner, address taker, uint amount) private {
        require(availableBalanceOf(owner) &gt;= amount, &quot;insufficient balance&quot;);
        encumbrances[owner][taker] += amount;
        encumberedBalanceOf[owner] += amount;
        emit Encumber(owner, taker, amount);
    }

    function _release(address owner, address taker, uint amount) private {
        if (encumbrances[owner][taker] &lt; amount) {
          amount = encumbrances[owner][taker];
        }
        encumbrances[owner][taker] -= amount;
        encumberedBalanceOf[owner] -= amount;
        emit Release(owner, taker, amount);
    }

    function transfer(address dst, uint amount) public override returns (bool) {
        // check but dont spend encumbrance
        require(availableBalanceOf(msg.sender) &gt;= amount, &quot;insufficient balance&quot;);
        _transfer(msg.sender, dst, amount);
        return true;
    }

    function transferFrom(address src, address dst, uint amount) public override returns (bool) {
        uint encumberedToTaker = encumbrances[src][msg.sender];
        bool exceedsEncumbrance = amount &gt; encumberedToTaker;
        if (exceedsEncumbrance)  {
            uint excessAmount = amount - encumberedToTaker;

            // check that enough unencumbered tokens exist to spend from allowance
           require(availableBalanceOf(src) &gt;= excessAmount, &quot;insufficient balance&quot;);

           // Exceeds Encumbrance , so spend all of it
            _spendEncumbrance(src, msg.sender, encumberedToTaker);

            _spendAllowance(src, dst, excessAmount);
        } else {
            _spendEncumbrance(src, msg.sender, amount);
        }

        _transfer(src, dst, amount);
        return true;
    }

    function _spendEncumbrance(address owner, address taker, uint256 amount) internal virtual {
        uint256 currentEncumbrance = encumbrances[owner][taker];
        require(currentEncumbrance &gt;= amount, &quot;insufficient encumbrance&quot;);
        uint newEncumbrance = currentEncumbrance - amount;
        encumbrances[owner][taker] = newEncumbrance;
        encumberedBalanceOf[owner] -= amount;

        emit Release(owner, taker, amount);
    }
}
```


## Security Considerations

Parties relying on `balanceOf` to determine the amount of tokens available for transfer should instead rely on `balanceOf(account) - encumberedBalance(account)`, or, if implemented, `availableBalanceOf(account)`.

The property that encumbered balances are always backed by a token balance can be accomplished in a straightforward manner by altering `transfer` and `transferFrom` to block . If there are other functions that can alter user balances, such as a rebasing token or an admin burn function, additional guards must be added by the implementer to likewise ensure those functions prevent reducing `balanceOf(account)` below `encumberedBalanceOf(account)` for any given account.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 27 Jun 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7246</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7246</guid>
      </item>
    
      <item>
        <title>Increase the MAX_EFFECTIVE_BALANCE</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7251-increase-the-max-effective-balance/15982</comments>
        
        <description>## Abstract

Increases the constant `MAX_EFFECTIVE_BALANCE`, while keeping the minimum staking balance `32 ETH`. This permits large node operators to consolidate into fewer validators while also allowing solo-stakers to earn compounding rewards and stake in more flexible increments.

## Motivation

As of October 3, 2023, there are currently over 830,000 validators participating in the consensus layer. The size of this set continues to grow due, in part, to the `MAX_EFFECTIVE_BALANCE`, which limits the stake of a single validator to `32 ETH`. This leads to large amounts of &quot;redundant validators&quot;, which are controlled by a single entity, possibly running on the same beacon node, but with distinct BLS signing keys. The limit on the `MAX_EFFECTIVE_BALANCE` is technical debt from the original sharding design, in which subcommittees (not the attesting committee but the committee calculated in `is_aggregator`) needed to be majority honest. As a result, keeping the weights of subcommittee members approximately equal reduced the risk of a single large validator containing too much influence. Under the current design, these subcommittees are only used for attestation aggregation, and thus only have a `1/N` honesty assumption.

With the security model of the protocol no longer dependent on a low value for `MAX_EFFECTIVE_BALANCE`, we propose raising this value while keeping the minimum validator threshold of `32 ETH`. This increase aims to reduce the validator set size, thereby reducing the number of P2P messages over the network, the number of BLS signatures that need to be aggregated each epoch, and the `BeaconState` memory footprint. This change adds value for both small and large validators. Large validators can consolidate to run fewer validators and thus fewer beacon nodes. Small validators now benefit from compounding rewards and the ability to stake in more flexible increments (e.g., the ability to stake `40 ETH` instead of needing to accumulate `64 ETH` to run two validators today).

## Specification

### Constants

#### Execution layer

| Name | Value | Comment |
| - | - | - |
| `CONSOLIDATION_REQUEST_TYPE` | `0x02` | The [EIP-7685](/EIPs/EIPS/eip-7685) type prefix for consolidation request |
| `CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS` | `0x0000BBdDc7CE488642fb579F8B00f3a590007251` | Where to call and store relevant details about consolidation request mechanism |
| `SYSTEM_ADDRESS` | `0xfffffffffffffffffffffffffffffffffffffffe` | Address used to invoke system operation on contract |
| `EXCESS_CONSOLIDATION_REQUESTS_STORAGE_SLOT` | `0` | |
| `CONSOLIDATION_REQUEST_COUNT_STORAGE_SLOT` | `1` | |
| `CONSOLIDATION_REQUEST_QUEUE_HEAD_STORAGE_SLOT` | `2` | Pointer to the head of the consolidation request message queue |
| `CONSOLIDATION_REQUEST_QUEUE_TAIL_STORAGE_SLOT` | `3` | Pointer to the tail of the consolidation request message queue |
| `CONSOLIDATION_REQUEST_QUEUE_STORAGE_OFFSET` | `4` | The start memory slot of the in-state consolidation request message queue |
| `MAX_CONSOLIDATION_REQUESTS_PER_BLOCK` | `2` | Maximum number of consolidation requests that can be dequeued into a block |
| `TARGET_CONSOLIDATION_REQUESTS_PER_BLOCK` | `1` | |
| `MIN_CONSOLIDATION_REQUEST_FEE` | `1` | |
| `CONSOLIDATION_REQUEST_FEE_UPDATE_FRACTION` | `17` | |
| `EXCESS_INHIBITOR` | `2**256-1` | Excess value used to compute the fee before the first system call |

#### Consensus layer

| Name | Value |
| - | - |
| `COMPOUNDING_WITHDRAWAL_PREFIX` | `Bytes1(&apos;0x02&apos;)` |
| `MIN_ACTIVATION_BALANCE` | `Gwei(2**5 * 10**9)`  (32 ETH) |
| `MAX_EFFECTIVE_BALANCE_ELECTRA` | `Gwei(2**11 * 10**9)` (2048 ETH) |

### Execution layer

#### Consolidation request

The new consolidation request is an [EIP-7685](/EIPs/EIPS/eip-7685) request with type `0x02` consisting of the following fields:

1. `source_address`: `Bytes20`
2. `source_pubkey`: `Bytes48`
3. `target_pubkey`: `Bytes48`

The [EIP-7685](/EIPs/EIPS/eip-7685) encoding of a consolidation request is as follows. Note we simply return the encoded request value as returned by the contract.

```python
request_type = CONSOLIDATION_REQUEST_TYPE
request_data = dequeue_consolidation_requests()
```

#### Consolidation request contract

The contract has three different code paths, which can be summarized at a high level as follows:

1. Add consolidation request - requires a `96` byte input, concatenated public keys of the source and the target validators.
2. Fee getter - if the input length is zero, return the current fee required to add a consolidation request.
3. System process - if called by system address, pop off the consolidation requests for the current block from the queue.

##### Add Consolidation Request

If call data input to the contract is exactly `96` bytes, perform the following:

1. Ensure enough ETH was sent to cover the current consolidation request fee (`msg.value &gt;= get_fee()`)
2. Increase consolidation request count by `1` for the current block (`increment_count()`)
3. Insert a consolidation request into the queue for the source address and pubkeys of the source and the target (`insert_consolidation_request_into_queue()`)

Specifically, the functionality is defined in pseudocode as the function `add_consolidation_request()`:

```python
def add_consolidation_request(Bytes48: source_pubkey, Bytes48: target_pubkey):
    &quot;&quot;&quot;
    Add consolidation request adds new request to the consolidation request queue, so long as a sufficient fee is provided.
    &quot;&quot;&quot;

    # Verify sufficient fee was provided.
    fee = get_fee()
    require(msg.value &gt;= fee, &apos;Insufficient value for fee&apos;)

    # Increment consolidation request count.
    count = sload(CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS, CONSOLIDATION_REQUEST_COUNT_STORAGE_SLOT)
    sstore(CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS, CONSOLIDATION_REQUEST_COUNT_STORAGE_SLOT, count + 1)

    # Insert into queue.
    queue_tail_index = sload(CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS, CONSOLIDATION_REQUEST_QUEUE_TAIL_STORAGE_SLOT)
    queue_storage_slot = CONSOLIDATION_REQUEST_QUEUE_STORAGE_OFFSET + queue_tail_index * 4
    sstore(CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot, msg.sender)
    sstore(CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 1, source_pubkey[0:32])
    sstore(CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 2, source_pubkey[32:48] ++ target_pubkey[0:16])
    sstore(CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 3, target_pubkey[16:48])
    sstore(CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS, CONSOLIDATION_REQUEST_QUEUE_TAIL_STORAGE_SLOT, queue_tail_index + 1)
```

###### Fee calculation

The following pseudocode can compute the cost of an individual consolidation request, given a certain number of excess consolidation requests.

```python
def get_fee() -&gt; int:
    excess = sload(CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS, EXCESS_CONSOLIDATION_REQUESTS_STORAGE_SLOT)
    require(excess != EXCESS_INHIBITOR, &apos;Inhibitor still active&apos;)
    return fake_exponential(
        MIN_CONSOLIDATION_REQUEST_FEE,
        excess,
        CONSOLIDATION_REQUEST_FEE_UPDATE_FRACTION
    )

def fake_exponential(factor: int, numerator: int, denominator: int) -&gt; int:
    i = 1
    output = 0
    numerator_accum = factor * denominator
    while numerator_accum &gt; 0:
        output += numerator_accum
        numerator_accum = (numerator_accum * numerator) // (denominator * i)
        i += 1
    return output // denominator
```

##### Fee Getter

When the input to the contract is length zero, interpret this as a get request for the current fee, i.e. the contract returns the result of `get_fee()`.

##### System Call

At the end of processing any execution block where this EIP is active (i.e. after processing all transactions and after performing the block body consolidation requests validations), call the contract at `CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS` as `SYSTEM_ADDRESS` with no calldata. The invocation triggers the following:

* The contract&apos;s queue is updated based on consolidation requests dequeued and the consolidation requests queue head/tail are reset if the queue has been cleared (`dequeue_consolidation_requests()`)
* The contract&apos;s excess consolidation requests are updated based on usage in the current block (`update_excess_consolidation_requests()`)
* The contract&apos;s consolidation requests count is reset to `0` (`reset_consolidation_requests_count()`)

Each consolidation request must appear in the EIP-7685 requests list in the exact order returned by `dequeue_consolidation_requests()`.

Additionally, the system call and the processing of that block must conform to the following:

* The call has a dedicated gas limit of `30_000_000`.
* Gas consumed by this call does not count against the block’s overall gas usage.
* Both the gas limit assigned to the call and the gas consumed are excluded from any checks against the block’s gas limit.
* The call does not follow [EIP-1559](/EIPs/EIPS/eip-1559) fee burn semantics — no value should be transferred as part of this call.
* If there is no code at `CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS`, the corresponding block **MUST** be marked invalid.
* If the call to the contract fails or returns an error, the block **MUST** be invalidated.

The functionality triggered by the system call is defined in pseudocode as the function `process_consolidation_requests()`:

```python
###################
# Public function #
###################

def process_consolidation_requests():
    reqs = dequeue_consolidation_requests()
    update_excess_consolidation_requests()
    reset_consolidation_requests_count()
    return ssz.serialize(reqs)

###########
# Helpers #
###########

class ConsolidationRequest(object):
    source_address: Bytes20
    source_pubkey: Bytes48
    target_pubkey: Bytes48

def dequeue_consolidation_requests():
    queue_head_index = sload(CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS, CONSOLIDATION_REQUEST_QUEUE_HEAD_STORAGE_SLOT)
    queue_tail_index = sload(CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS, CONSOLIDATION_REQUEST_QUEUE_TAIL_STORAGE_SLOT)
    num_in_queue = queue_tail_index - queue_head_index
    num_dequeued = min(num_in_queue, MAX_CONSOLIDATION_REQUESTS_PER_BLOCK)

    reqs = []
    for i in range(num_dequeued):
        queue_storage_slot = CONSOLIDATION_REQUEST_QUEUE_STORAGE_OFFSET + (queue_head_index + i) * 4
        source_address = address(sload(CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot)[0:20])
        source_pubkey = (
            sload(CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 1)[0:32] + sload(CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 2)[0:16]
        )
        target_pubkey = (
            sload(CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 2)[16:32] + sload(CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 3)[0:32]
        )
        req = ConsolidationRequest(
            source_address=Bytes20(source_address),
            source_pubkey=Bytes48(source_pubkey),
            target_pubkey=Bytes48(target_pubkey)
        )
        reqs.append(req)

    new_queue_head_index = queue_head_index + num_dequeued
    if new_queue_head_index == queue_tail_index:
        # Queue is empty, reset queue pointers
        sstore(CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS, CONSOLIDATION_REQUEST_QUEUE_HEAD_STORAGE_SLOT, 0)
        sstore(CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS, CONSOLIDATION_REQUEST_QUEUE_TAIL_STORAGE_SLOT, 0)
    else:
        sstore(CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS, CONSOLIDATION_REQUEST_QUEUE_HEAD_STORAGE_SLOT, new_queue_head_index)

    return reqs

def update_excess_consolidation_requests():
    previous_excess = sload(CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS, EXCESS_CONSOLIDATION_REQUESTS_STORAGE_SLOT)
    # Check if excess needs to be reset to 0 for first iteration after activation
    if previous_excess == EXCESS_INHIBITOR:
        previous_excess = 0

    count = sload(CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS, CONSOLIDATION_REQUEST_COUNT_STORAGE_SLOT)

    new_excess = 0
    if previous_excess + count &gt; TARGET_CONSOLIDATION_REQUESTS_PER_BLOCK:
        new_excess = previous_excess + count - TARGET_CONSOLIDATION_REQUESTS_PER_BLOCK

    sstore(CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS, EXCESS_CONSOLIDATION_REQUESTS_STORAGE_SLOT, new_excess)

def reset_consolidation_requests_count():
    sstore(CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS, CONSOLIDATION_REQUEST_COUNT_STORAGE_SLOT, 0)
```

##### Bytecode

```asm
caller
push20 0xfffffffffffffffffffffffffffffffffffffffe
eq
push1 0xd3
jumpi

push1 0x11
push0
sload
dup1
push32 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
eq
push2 0x019a
jumpi

push1 0x01
dup3
mul
push1 0x01
swap1
push0

jumpdest
push0
dup3
gt
iszero
push1 0x68
jumpi

dup2
add
swap1
dup4
mul
dup5
dup4
mul
swap1
div
swap2
push1 0x01
add
swap2
swap1
push1 0x4d
jump

jumpdest
swap1
swap4
swap1
div
swap3
pop
pop
pop
calldatasize
push1 0x60
eq
push1 0x88
jumpi

calldatasize
push2 0x019a
jumpi

callvalue
push2 0x019a
jumpi

push0
mstore
push1 0x20
push0
return

jumpdest
callvalue
lt
push2 0x019a
jumpi

push1 0x01
sload
push1 0x01
add
push1 0x01
sstore
push1 0x03
sload
dup1
push1 0x04
mul
push1 0x04
add
caller
dup2
sstore
push1 0x01
add
push0
calldataload
dup2
sstore
push1 0x01
add
push1 0x20
calldataload
dup2
sstore
push1 0x01
add
push1 0x40
calldataload
swap1
sstore
caller
push1 0x60
shl
push0
mstore
push1 0x60
push0
push1 0x14
calldatacopy
push1 0x74
push0
log0
push1 0x01
add
push1 0x03
sstore
stop

jumpdest
push1 0x03
sload
push1 0x02
sload
dup1
dup3
sub
dup1
push1 0x02
gt
push1 0xe7
jumpi

pop
push1 0x02

jumpdest
push0

jumpdest
dup2
dup2
eq
push2 0x0129
jumpi

dup3
dup2
add
push1 0x04
mul
push1 0x04
add
dup2
push1 0x74
mul
dup2
sload
push1 0x60
shl
dup2
mstore
push1 0x14
add
dup2
push1 0x01
add
sload
dup2
mstore
push1 0x20
add
dup2
push1 0x02
add
sload
dup2
mstore
push1 0x20
add
swap1
push1 0x03
add
sload
swap1
mstore
push1 0x01
add
push1 0xe9
jump

jumpdest
swap2
add
dup1
swap3
eq
push2 0x013b
jumpi

swap1
push1 0x02
sstore
push2 0x0146
jump

jumpdest
swap1
pop
push0
push1 0x02
sstore
push0
push1 0x03
sstore

jumpdest
push0
sload
dup1
push32 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
eq
iszero
push2 0x0173
jumpi

pop
push0

jumpdest
push1 0x01
sload
push1 0x01
dup3
dup3
add
gt
push2 0x0188
jumpi

pop
pop
push0
push2 0x018e
jump

jumpdest
add
push1 0x01
swap1
sub

jumpdest
push0
sstore
push0
push1 0x01
sstore
push1 0x74
mul
push0
return

jumpdest
push0
push0
revert
```

##### Deployment

The consolidation requests contract is deployed like any other smart contract. A special synthetic address is generated by working backwards from the desired deployment transaction:

```json
{
  &quot;type&quot;: &quot;0x0&quot;,
  &quot;nonce&quot;: &quot;0x0&quot;,
  &quot;to&quot;: null,
  &quot;gas&quot;: &quot;0x3d090&quot;,
  &quot;gasPrice&quot;: &quot;0xe8d4a51000&quot;,
  &quot;maxPriorityFeePerGas&quot;: null,
  &quot;maxFeePerGas&quot;: null,
  &quot;value&quot;: &quot;0x0&quot;,
  &quot;input&quot;: &quot;0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f5561019e80602d5f395ff33373fffffffffffffffffffffffffffffffffffffffe1460d35760115f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1461019a57600182026001905f5b5f82111560685781019083028483029004916001019190604d565b9093900492505050366060146088573661019a573461019a575f5260205ff35b341061019a57600154600101600155600354806004026004013381556001015f358155600101602035815560010160403590553360601b5f5260605f60143760745fa0600101600355005b6003546002548082038060021160e7575060025b5f5b8181146101295782810160040260040181607402815460601b815260140181600101548152602001816002015481526020019060030154905260010160e9565b910180921461013b5790600255610146565b90505f6002555f6003555b5f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff141561017357505f5b6001546001828201116101885750505f61018e565b01600190035b5f555f6001556074025ff35b5f5ffd&quot;,
  &quot;v&quot;: &quot;0x1b&quot;,
  &quot;r&quot;: &quot;0x539&quot;,
  &quot;s&quot;: &quot;0xc0730f92dc275b663d377a7cbb141b6600052&quot;,
  &quot;hash&quot;: &quot;0x379269d571beff3ed1d8eba3abb24076a7267b0eaf0cc66d728fb0544f5a690d&quot;
}
```

```
Sender: 0x13d1913d623E6a9D8811736359E50fD31Fe54fCA
Address: 0x0000BBdDc7CE488642fb579F8B00f3a590007251
```

### Consensus layer

The defining features of this EIP are:

1. ***Increasing the `MAX_EFFECTIVE_BALANCE`, while creating a `MIN_ACTIVATION_BALANCE`.*** The core feature of allowing variable size validators.
2. ***Allowing for multiple validator indices to be combined through the protocol.*** A mechanism by which large node operators can combine validators without cycling through the exit and activation queues.
3. ***Adding execution layer partial withdrawals (part of [EIP-7002](/EIPs/EIPS/eip-7002)).*** Allowing Execution Layer messages to trigger partial withdrawals in addition to full exits (e.g., a `100 ETH` validator can remove up to `68 ETH` without exiting the validator).
4. ***Making the initial slashing penalty negligible.*** This reduces the risk of consolidation for large validators.

The [Rationale](#rationale) section contains an explanation for each of these proposed core features. A sketch of the resulting changes to the consensus layer is included below.

1. Add `COMPOUNDING_WITHDRAWAL_PREFIX` and `MIN_ACTIVATION_BALANCE` constants, while introducing the updated value of `MAX_EFFECTIVE_BALANCE` (`MAX_EFFECTIVE_BALANCE_ELECTRA`).
2. Create the `PendingDeposit` container, which is used to track incoming deposits in the weight-based rate limiting mechanism.
3. Update the `BeaconState` with deposit and partial withdrawal queues, fields needed for deposit, and exit queue weight-based rate limiting.
4. Modify `is_eligible_for_activation_queue` to check against `MIN_ACTIVATION_BALANCE` rather than `MAX_EFFECTIVE_BALANCE`.
5. Modify `get_validator_churn_limit` to depend on the validator weight rather than the validator count.
6. Create a helper `compute_exit_epoch_and_update_churn` to calculate the exit epoch based on the current pending withdrawals.
6. Modify `initiate_validator_exit` to rate limit the exit queue by balance rather than the number of validators.
7. Modify `initialize_beacon_state_from_eth1` to use `MIN_ACTIVATION_BALANCE`.
9. Modify `process_registry_updates` to activate all eligible validators.
10. Add a per-epoch helper, `process_pending_deposits`, to consume some of the pending deposits.
10. Modify `get_validator_from_deposit` to initialize the effective balance to zero (it&apos;s updated by the pending deposit flow).
11. Modify `process_deposit` to store incoming deposits in `state.pending_deposits`.
12. Modify `compute_weak_subjectivity_period` to use the new churn limit function.
13. Add `has_compounding_withdrawal_credential` to check for the `0x02` credential.
14. Modify `is_fully_withdrawable_validator` to check for compounding credentials.
15. Add `get_validator_excess_balance` to calculate the excess balance of validators.
16. Modify `is_partially_withdrawable_validator` to check for excess balance.
17. Modify `get_expected_withdrawals` to use excess balance and process pending partial withdrawals.
18. Add `process_consolidation` to initiate in-protocol validator consolidation and switch a validator to compounding withdrawal credentials.
19. Limits the usage of exit churn to 256 ETH (equivalent to 8 validators with 32 ETH effective balance), and defers the surplus of the churn to process consolidations.

Full consensus layer specification can be found in [`./electra/beacon-chain.md`](https://github.com/ethereum/consensus-specs/blob/834e40604ae4411e565bd6540da50b008b2496dc/specs/electra/beacon-chain.md)

## Rationale

This EIP aims to reduce the total number of validators without changing anything about the economic security of the protocol. It provides a mechanism by which large node operators who control significant amounts of stake can consolidate into fewer validators. We analyze the reasoning behind each of the core features.

### Increasing the `MAX_EFFECTIVE_BALANCE`, while creating a `MIN_ACTIVATION_BALANCE`

While increasing the `MAX_EFFECTIVE_BALANCE` to allow larger-stake validators, it is important to keep the lower bound of `32 ETH` (by introducing a new constant – `MIN_ACTIVATION_BALANCE`) to encourage solo-staking.

### Allowing for multiple validator indices to be combined through the protocol

For large staking pools that already control thousands of validators, exiting and re-entering would be extremely slow and costly. The adoption of the EIP will be much higher by allowing in-protocol consolidation.

### Adding execution layer partial withdrawals (part of [EIP-7002](/EIPs/EIPS/eip-7002))

For validators that choose to raise their effective balance ceiling, allowing for custom partial withdrawals triggered from the execution layer increases the flexibility of the staking configurations. Validators can choose when and how much they withdraw but will have to pay gas for the EL transaction.

### Making the initial slashing penalty negligible

To encourage consolidation, we could modify the slashing penalties. The biggest hit comes from the initial penalty of `1/32` of the validator&apos;s effective balance. Since this scales linearly on the effective balance, the higher-stake validators directly incur higher risk. By changing the scaling properties, we could make consolidation more attractive.

### Consolidation contract parameter values

The consolidation smart contract uses a fee mechanism to rate limit the number of requests per block. Details of the fee mechanism are available in [EIP-7002](/EIPs/EIPS/eip-7002#fee-update-rule).

`TARGET_CONSOLIDATION_REQUESTS_PER_BLOCK` is chosen to be `1` to rate limit consolidation requests as much as possible.
`MAX_CONSOLIDATION_REQUESTS_PER_BLOCK` is chosen to be `2` to allow for switching a validator to compounding credentials and requesting a consolidation in the same block.

One consolidation per block is still higher than the size of consolidation churn which can lead to unbounded growth of the consolidation queue.
Thus, there is a hard limit on the consolidation queue size equal to 262,144 requests which is `4 MB` of data in the beacon state.

## Backwards Compatibility

This EIP introduces backward incompatible changes to the block validation rule set and must be accompanied by a hard fork. These changes do not break anything related to current user activity and experience.

## Security Considerations

This change modifies committees and churn, but doesn&apos;t significantly impact the security properties.

### Security of attestation committees

Given full consolidation as the worst case, the probability of an adversarial takeover of a committee remains low. Even in a high consolidation scenario, the required share of honest validators remains well below the 2/3 supermajority needed for finality.

### Aggregator selection

In the original sharding roadmap, subcommittees were required to be secure with extremely high probability. Now with the sole responsibility of attestation aggregation, we only require each committee to have at least one honest aggregator. Currently, aggregators are selected through a VRF lottery, targeting several validator units that can be biased by non-consolidated attackers. This proposal changes the VRF lottery to consider weight, so the probability of having at least one honest aggregator is not worse.

### Proposer selection probability

Proposer selection is already weighted by the ratio of their effective balance to `MAX_EFFECTIVE_BALANCE`. Due to the lower probabilities, this change will slightly increase the time it takes to calculate the next proposer index.

### Sync committee selection probability

Sync committee selection is also already weighted by effective balance, so this proposal does not require modifications to the sync protocol. Light clients can still check that a super-majority of participants have signed an update irrespective of their weights since we maintain a weight-based selection probability.

### Churn invariants

This proposal maintains the activation and exit churn invariants limiting active weight instead of validator count. Balance top-ups are now handled explicitly, being subject to the same activation queue as full deposits.

### Fee Overpayment

Calls to the system contract require a fee payment defined by the current contract state. Overpaid fees are not returned to the caller. It is not generally possible to compute the exact required fee amount ahead of time. When adding a consolidation request from a contract, the contract can perform a read operation to check for the current fee and then pay exactly the required amount. Here is an example in Solidity:

```
function addConsolidation(bytes memory srcPubkey, bytes memory targetPubkey, uint64 requestFeeLimit) private {
    assert(srcPubkey.length == 48);
    assert(targetPubkey.length == 48);

    // Read current fee from the contract.
    (bool readOK, bytes memory feeData) = ConsolidationsContract.staticcall(&apos;&apos;);
    if (!readOK) {
        revert(&apos;reading fee failed&apos;);
    }
    uint256 fee = uint256(bytes32(feeData));

    // Check the fee is not too high.
    if (fee &gt; requestFeeLimit) {
        revert(&apos;fee is too high&apos;);
    }

    // Add the request.
    bytes memory callData = bytes.concat(srcPubkey, targetPubkey);
    (bool writeOK,) = ConsolidationsContract.call{value: fee}(callData);
    if (!writeOK) {
        revert(&apos;adding request failed&apos;);
    }
}
```

Note: the system contract uses the EVM `CALLER` operation (Solidity: `msg.sender`) to get the address used in the consolidation request, i.e. the address that calls the system contract must match the 0x01 withdrawal credential recorded in the beacon state.

Note: the above code reverts if the fee is too high, the fee can change significantly between the creation of a consolidation request transaction and its inclusion into a block, thus, this check is very important to avoid overpayments.

Using an EOA to request consolidations will always result in overpayment of fees. There is no way for an EOA to use a wrapper contract to request a consolidation. And even if a way existed, the gas cost of returning the overage would likely be higher than the overage itself. If requesting consolidations from an EOA to the system contract is desired, we recommend that users perform transaction simulations to estimate a reasonable fee amount to send.

### Consolidation queue hard limit

Consolidations exceeding the hard limit of the consolidation queue (262,144 requests) will be discarded by the consensus layer and will need to be re-submitted,
note that the fee is not refunded in this case.


### System Call failure

Although the likelihood of a failed system call to `CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS` is extremely low, the behavior in such cases is well-defined: the block is marked as invalid. This consideration directly follows from [EIP-7002](/EIPs/EIPS/eip-7002#system-call-failure) 

### Empty Code failure

This EIP should not have been activated if there is no code present at `CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS` (i.e., if the chain is not &quot;ready&quot;). This is also similar to the consideration in [EIP-7002](/EIPs/EIPS/eip-7002#empty-code-failure) 

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 28 Jun 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7251</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7251</guid>
      </item>
    
      <item>
        <title>Token Revenue Sharing</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/token-revenue-sharing/14872</comments>
        
        <description>## Abstract

With the aspiration of bringing forth unique functionality and enhancing value for holders of [ERC-20](/EIPs/EIPS/eip-20) tokens, our project aims to effortlessly reward token holders without necessitating users to lock, stake, or farm their tokens. Whenever the project generates profits, these profits can be distributed to the token holders.

Revenue Sharing is an extended version of [ERC-20](/EIPs/EIPS/eip-20). It proposes an additional payment method for token holders. 

This standard includes updating rewards for holders and allowing token holders to withdraw rewards.

Potential use cases encompass:

* Companies distributing dividends to token holders.
* Direct sharing of revenue derived from business activities, such as marketplaces, Automated Market Makers (AMMs), and games.


## Specification

### Methods

#### maxTokenReward

Returns  max token reward.

``` js
function maxTokenReward() public view returns (uint256)
```

#### informationOf

Returns the account information of another account with the address `token` and `account`, including: inReward, outReward and withdraw.

``` js
function informationOf(address token, address account) public view returns (UserInformation memory)
```

#### informationOfBatch

Returns the list account information of another account with the `account`, including: inReward, outReward and withdraw.

``` js
function informationOfBatch(address account) public view returns (UserInformation[] memory)
```

#### UserInformation

`inReward`: when user&apos;s balance decreases, inReward will be updated
`outReward`: when user&apos;s balance increases, outReward will be updated
`withdraw`: total amount of reward tokens withdrawn

```solidity
struct UserInformation {
    uint256 inReward;
    uint256 outReward;
    uint256 withdraw;
}
```

#### tokenReward

Returns the list token reward address of the token.

``` js
function tokenReward() public view returns (address[] memory)
```

#### updateReward

Updates rewardPerShare of token reward.
rewardPerShare = rewardPerShare + amount / totalSupply()

``` js
function updateReward(address[] memory token, uint256[] memory amount) public
```

#### viewReward

Returns the list amount of reward for an account

``` js
function viewReward(address account) public view returns (uint256[] memory)
```

#### getReward

Gets and returns reward with list token reward.

``` js
function getReward(address[] memory token) public
```

#### getRewardPerShare

Returns the reward per share of token reward.

``` js
function getRewardPerShare(address token) public view returns (uint256)
```

#### existsTokenReward

Returns the status of token reward.

``` js
function existsTokenReward(address token) public view returns (bool)
```

## Rationale

TBD

## Reference Implementation

* [ERC-7254](/EIPs/assets/eip-7254/ERC7254.sol)
* [IERC-7254](/EIPs/assets/eip-7254/IERC7254.sol)

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 29 Jun 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7254</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7254</guid>
      </item>
    
      <item>
        <title>Remove BLAKE2 compression precompile</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/discussion-removal-of-ripemd-160-and-blake2f-precompiles/14857</comments>
        
        <description>## Abstract

This EIP removes the [`blake2f`](/EIPs/EIPS/eip-152) (`0x09`) precompile by changing the precompile behaviour to result in an exceptional abort.

## Motivation

[EIP-152](/EIPs/EIPS/eip-152) has never capitalised on a real-world use case. This fact is clearly reflected in the number of times the address `0x09` has been invoked (numbers from the date this EIP was created):

- The most recent call took place on 6 October 2022.
- Since its gone live as part of the Istanbul network upgrade on December 7 2019 (block number 9,069,000), `0x09` has been called only 22,131 times.

One of the reasons why [EIP-152](/EIPs/EIPS/eip-152) has failed is that the envisioned use cases were not validated before inclusion.

## Specification

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

All `CALL`, `CALLCODE`, `DELEGATECALL`, and `STATICCALL` invocations to the `blake2f` precompile address `0x09` MUST result in an exceptional halting state that consumes all supplied gas and returns no data.

## Rationale

The EVM should be optimised for simplicity and future-proofness. The original Yellow Paper states: _these are so-called &apos;precompiled&apos; contracts, meant as a preliminary piece of architecture that may later become native extensions_. Considering that no use cases have been realised in the last 3.5 years, we can conclude that the precompile `blake2f` (`0x09`) will never transition into a native opcode. In that sense, the precompile `blake2f` (`0x09`) is an obsolete carry-along with no real-world traction and thus should be removed. This removal will simplify the EVM to the extent that it only consists of clear instructions with real-world use cases. Eventually, the precompile `blake2f` (`0x09`) can be safely used as a test run for the phase-out and removal of EVM functions.

## Backwards Compatibility

This EIP requires a hard fork as it modifies the consensus rules. Note that very few applications are affected by this change and a lead time of 6-12 months can be considered sufficient.

## Security Considerations

There are no known additional security considerations introduced by this change.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 03 Jul 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7266</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7266</guid>
      </item>
    
      <item>
        <title>Ethereum Access Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7272-ethereum-access-token/14945</comments>
        
        <description>## Abstract

An Ethereum Access Token (EAT) is an [EIP-712](/EIPs/EIPS/eip-712) conformant, signed message, used by off-chain services to grant Ethereum accounts access to specific on-chain resources. EATs share similarities with JSON Web Tokens (JWTs); both are used for short-lived authorizations. However Ethereum Access Tokens are specifically designed to be verified on-chain and tailored to authorize smart contract function calls.

## Motivation

While other proposals tackle authentication or authorization in a more narrow way, this specification allows developers to add a layer of access control to any function they create with minimal changes. It is best suited for use cases where end users should only be able to access specific on-chain resources themselves directly, by way of sending a transaction, provided they have been granted authorization by an off-chain service first. Examples of such scenarios include an off-chain verifier assessing eligibility requirements (e.g by verifying verifiable credentials) to mint a token or to interact with a smart contract that requires a certain compliance status.
Therefore, this proposal enables off-chain systems to authenticate the controller of an Ethereum account in any way they want, before granting an authorization bound to said account.

This specification is intended to improve interoperability in the Ethereum ecosystem, by providing a consistent machine-readable message format to achieve improved user experiences.

EATs fill a void where access control requirements differ from current standard access control mechanisms (role-based access modifiers or checking that an address owns an NFT):

- Desired acccess is short-lived
- Criteria needs to be flexible/dynamic: updating the requirements for granting access doesn&apos;t require any update on chain
- When Soulbound or other on-chain token semantics are not desired. Using any kind of &quot;on-chain registry&quot; to grant authorization places a burden on the owner of such registry to keep it up-to-date at all time. Otherwise, someone might be wrongly granted access in the lapse of time where their on-chain status is incorrect. With EATs, on the contrary, users come to ask for an authorization which gives EAT issuers the opportunity to perform some checks and update their records before granting authorization. Additionally, relying purely on on-chain data comes with privacy concerns due to the public nature of most of current chains. When authorization needs to be granted based on sensitive or personally identifiable information, it is not recommended to store that information on-chain and perform a lookup. Ethereum Access Tokens provide an alternative which doesn&apos;t leak any PII on-chain.

## Specification

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

### Overview

An example flow integrated in a DeFi application is the following:

1. A user interacts with the DeFi&apos;s off-chain service, providing sufficient input for the off-chain service to ensure the user meets its criteria (for example, authenticates the user and/or make sure they possess valid credentials)
2. If authorization is granted, an EAT is issued to the user
3. The user then interacts with the gated smart contract function within the specified period of time passing the EAT as part of the transaction
4. The EAT is verified on-chain

![Transaction authorization flow using an EAT](/EIPs/assets/eip-7272/EAT_transaction_auth_flow.png)

An Ethereum Access Token MUST guarantee granular access control by binding it to specific parameters upon issuance. Then, on-chain EAT verification ensures that:

- The function being called is the expected one
- The function parameters are the expected ones
- The function caller is the expected one
- The function is being called in the authorized timeframe (i.e checking that the EAT is not expired)
- The smart contract being called is the expected one
- The authorization has been given by a valid issuer, i.e the EAT has been signed by one of the expected issuers

### Structure of an Ethereum Access Token

An Ethereum Access Token is composed of a signature and expiry.

```
{
 uint8 v,
 bytes32 r,
 bytes32 s,
 uint256 expiry
}
```

The signature is obtained using the typed structured data hashing and signing standard (EIP-712), signing over the following EAT payload:

```
struct AccessToken {
    uint256 expiry;
    FunctionCall functionCall;
}

struct FunctionCall {
    bytes4 functionSignature;
    address target;
    address caller;
    bytes parameters;
}
```

- **expiry**: unix timestamp, expected to be before `block.timestamp`

`FunctionCall` parameters correspond to the following:

- **functionSignature**: identifier for the function being called, expected to match `msg.sig`
- **target**: address of the target contract being called
- **caller**: address of the current caller - expected to match `msg.sender`
- **parameters**: `calldata` after stripping off the first parameters, namely `v`,`r`, `s` and `expiry`

### EAT Verification

On chain, the reference implementation uses two contracts: an `AccessTokenConsumer` which is inherited by contracts needing to permission some of its functions and an `AccessTokenVerifier` which is responsible for verifying EATs.

The `AccessTokenConsumer` contract calls the `AccessTokenVerifier` to verify the integrity of an EAT.

The `verify()` function of the `AccessTokenVerifier` takes a signature and an `AccessToken` as input, verifies that the token is not expired, attempts to recover the signer from the signature and the reconstructed EIP-712 digest, and verifies that the signer is a valid, expected signer.

Please see the [reference implementation](/EIPs/assets/eip-7272/AccessTokenVerifier.sol) for an example of how this can be performed.

## Rationale

- Single-use. The reference implementation guarantees non-replayability of EATs. But other implementations might favor a different approach.

- Use of EIP-712. By conforming to EIP-712, EATs are interoperable with existing Ethereum infrastructure, and developers can use them to create access controls with minimal modifications to their existing code. It also ensures that EATs issued are bound to a specific chain.

- Zero-knowledge proofs. Using ZKPs comes at a cost, including added complexity. EATs are not much more than signed messages which are simpler to reason around. While `ecrecover` is available in any Ethereum smart contract out of the box, ZKPs come in different flavors which hinders interoperability.

## Backwards Compatibility

Any function can be gated with an EAT, apart from the special `receive` and `fallback` functions.

## Reference Implementation

Here&apos;s a reference implementation of the different smart contracts making up the EAT system onchain:

- [IAccessTokenVerifier.sol](/EIPs/assets/eip-7272/IAccessTokenVerifier.sol)
- [AccessTokenVerifier.sol](/EIPs/assets/eip-7272/AccessTokenVerifier.sol)
- [AccessTokenConsumer.sol](/EIPs/assets/eip-7272/AccessTokenConsumer.sol)

## Security Considerations

The security of the Ethereum Access Token (EAT) proposal depends on several factors:

### Replay Attacks

The implementation MAY ensure that an EAT cannot be reused after it has been consumed. This is achieved by marking the EAT as consumed in the `_consumeAccessToken` function.

### Off-Chain Issuance

The security of the off-chain service issuing EATs is critical since the security of EAT-gated functions depends on it.
If this service is compromised, malicious actors could be granted EATs giving them access to on-chain resources that they should not have access to.

### Expiry Time Considerations

The expiry time of the EAT must be set judiciously to balance usability and security. If the expiry time is set too long, it might increase the risk of EAT misuse. If it&apos;s too short, it might compromise the usability of the application.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 03 Jul 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7272</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7272</guid>
      </item>
    
      <item>
        <title>NFT Metadata Extension like JSON-LD</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7280-nft-metadata-extension-like-json-ld/14935</comments>
        
        <description>## Abstract

This proposal expands the metadata format for Non-Fungible Tokens ([ERC-721](/EIPs/EIPS/eip-721), [ERC-1155](/EIPs/EIPS/eip-1155), [ERC-3525](/EIPs/EIPS/eip-3525), and others), adding support for linked data like JSON-LD format. The additional data is stored under the linked_data key in the metadata JSON.

## Motivation

The existing metadata format for Non-Fungible Tokens is limited and doesn&apos;t support the inclusion of structured and semantically meaningful data. By integrating JSON-LD (Linked Data), we can enhance the richness and interoperability of the metadata associated with NFTs.

This allows for complex metadata structures that can link to external schemas and data, improving the contextual relevance and usability of NFTs across various applications.

## Specification

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

The JSON-LD based metadata is stored under a new `linked_data` key in the metadata JSON. The `linked_data` key is an array of objects, where each object contains two keys: `schema` and `data`.

| name   | compliance level | type   | description                    |
| ------ | ---------------- | ------ | ------------------------------ |
| schema | MUST             | object | The schema of the linked data. |
| data   | MUST             | object | The data of the linked data.   |

### Schema

| name        | compliance level | type   | description                    |
| ----------- | ---------------- | ------ | ------------------------------ |
| uri         | MUST             | string | The URI of the schema.         |
| name        | MUST             | string | The name of the schema.        |
| description | OPTIONAL         | string | The description of the schema. |

### Data

| name        | compliance level | type   | description                                               |
| ----------- | ---------------- | ------ | --------------------------------------------------------- |
| uri         | MUST             | string | The URI of the data.                                      |
| lang        | OPTIONAL         | string | The language of the data. IETF language tag like `en-US`. |
| name        | OPTIONAL         | string | The name of the data.                                     |
| description | OPTIONAL         | string | The description of the data.                              |

## Rationale

For providing typical webpage for an NFT, it&apos;s much simple to include JSON-LD in HTML header tag with this extension. Just looking for JSON-LD compliant value&apos;s uri from `linked_data` array, fetch it and embed its content in HTML header tag.
This means the minter of NFT can control the appearance in the search result of Google, for example.
In more common case for interoperability, the NFT metadata can include any schema and data with this extension. This means the NFT metadata can be used as a data source for any application. With the schema, the implementation is much easier.

## Backwards Compatibility

The proposed expansion to the NFT metadata format is backward compatible with existing implementations. NFTs that do not include the `linked_data` key will continue to function as before, and existing applications consuming NFT metadata will not be affected.

## Reference Implementation

Here is an example metadata JSON demonstrating the new linked_data structure:

```json
{
  &quot;name&quot;: &quot;NFT Name&quot;,
  &quot;description&quot;: &quot;This NFT represents...&quot;,
  &quot;image&quot;: &quot;https://example.org/images/nft.png&quot;,
  &quot;linked_data&quot;: [
    {
      &quot;schema&quot;: {
        &quot;name&quot;: &quot;VideoObject&quot;,
        &quot;uri&quot;: &quot;https://example.org/schemas/VideoObject.json&quot;
      },
      &quot;data&quot;: {
        &quot;uri&quot;: &quot;https://example.org/data/video1.json&quot;
      }
    },
    {
      &quot;schema&quot;: {
        &quot;name&quot;: &quot;MusicRecording&quot;,
        &quot;uri&quot;: &quot;https://example.org/schemas/MusicRecording.json&quot;
      },
      &quot;data&quot;: {
        &quot;uri&quot;: &quot;https://example.org/data/music1.json&quot;
      }
    },
    {
      &quot;schema&quot;: {
        &quot;name&quot;: &quot;GoogleTravelImpactModel&quot;,
        &quot;uri&quot;: &quot;https://example.org/schemas/GoogleTravelImpactModel.json&quot;
      },
      &quot;data&quot;: {
        &quot;uri&quot;: &quot;https://example.org/data/gtim1.json&quot;
      }
    }
  ]
}
```

In the example above, the NFT metadata contains three linked data objects, each with a different schema and data:
First one. VideoObject data can be used as JSON-LD in HTML header tag and realize rich snippet in Google search result.
Second one. MusicRecording data is based on a schema from `schema.org`. However this one cannot realize rich snippet.
Third one. GoogleTravelImpactModel data is a dedicated schema for Google Travel Impact Model.
The most important point is that any schema and data can be included with this standard like above.

### Sample files

- [VideoObject.json](/EIPs/assets/eip-7280/samples/schemas/VideoObject.json)
- [MusicRecording.json](/EIPs/assets/eip-7280/samples/schemas/MusicRecording.json)
- [GoogleTravelImpactModel.json](/EIPs/assets/eip-7280/samples/schemas/GoogleTravelImpactModel.json)
- [video1.json](/EIPs/assets/eip-7280/samples/data/video1.json)
- [music1.json](/EIPs/assets/eip-7280/samples/data/music1.json)
- [gtim1.json](/EIPs/assets/eip-7280/samples/data/gtim1.json)

## Security Considerations

The proposed expansion does not introduce any additional security considerations beyond those already associated with NFTs and linked data. Implementations should adhere to best practices for secure handling and validation of metadata from external sources.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 04 Jul 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7280</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7280</guid>
      </item>
    
      <item>
        <title>Purpose bound money</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7291-purpose-bound-money/14973</comments>
        
        <description>## Abstract

A Purpose Bound Money (PBM) token is a wrapper around an [ERC-1155](/EIPs/EIPS/eip-1155) token that can be used for a limited activity. This proposal outlines a smart contract interface that builds upon the ERC-1155 standard to implement the purpose bound money (PBM) concept:

- A PBM consists of a PBM wrapper and the digital money token it wraps. A digital money token (e.g., stablecoins, central bank digital currencies, tokenized bank deposits, and similar instruments) serves as a store of value (abbreviated as &quot;sov&quot;). Thus, a digital money token (also referred to as &quot;sovToken&quot;) **SHOULD** be:
  - a good store of value;
  - a suitable unit of account; and
  - a medium of exchange.
- PBMs are bearer instruments, with self-contained programming logic, and can be transferred between two parties without involving intermediaries. It combines the concept of:
  - programmable payment - automatic execution of payments once a pre-defined set of conditions are met; and
  - programmable money - the possibility of embedding rules within the medium of exchange itself that define or constrain its usage.
- Once the conditions are met, sovToken is released, and it becomes unbounded once again. A PBM can be thought of as a digital cash voucher, because it places constraints on how a payer can use the PBM but does not impose any constraints on the merchant/redeemer because the PBM unwraps and releases the underlying digital money upon payment to the merchant/redeemer. This is akin to a physical cash voucher: the payer is restricted to purchases from the merchants specified by the issuer but the merchants accepting the vouchers can exchange the physical vouchers with the issuer for fiat money.

In this EIP, we propose a modular structure consisting of a sovToken compatible with [ERC-20](/EIPs/EIPS/eip-20) as the digital money, an ERC-1155 compatible smart contract as the PBM wrapper, a compliance guard smart contract as a component of the PBM Wrapper logic, and a PBM token manager smart contract to manage token registration and retrieval.

## Motivation

Purpose Bound Money (PBM) enables digital currencies to carry conditions on how they can be spent, making them especially useful in real-world scenarios such as:

- **Government vouchers** (e.g. CDC vouchers in Singapore), where funds should only be redeemable at approved heartland merchants;
- **Conditional disbursements**, such as SkillsFuture learning accounts, where funds are released only after course participation is verified;
- **Escrow-style payments**, like homebuyer milestones, where payouts to developers are tied to the completion of specific construction stages;

This proposal intends to forestall technology fragmentation and consequently a lack of interoperability. By making the PBM specification open, it gives new participants easy and free access to the pre-existing market standards, enabling interoperability across different platforms, wallets, payment systems and rails. This would lower cost of entry for new participants, foster a vibrant payment landscape and prevent the development of walled gardens and monopolies, ultimately leading to more efficient, affordable services and better user experiences.

## Specification

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

### Definitions

- **sovToken** - an ERC-20 or ERC-20 compatible digital currency (e.g. [ERC-777](/EIPs/EIPS/eip-777), [ERC-1363](/EIPs/EIPS/eip-1363)) serving as the store of value token (i.e. collateral backing the PBM Token).

- **PBM Wrapper** - an ERC-1155 compliant smart contract, which wraps the sovToken by specifying one or more conditions that have to be met (referred to as PBM business logic in subsequent section of this proposal). The PBM wrapper can be designed to be modular in nature, with core, plug-ins and hooks components (see section on PBM Architecture for elaboration). The PBM wrapper smart contract, together with adopted hooks smart contracts verifies that condition(s) has/have been met before unwrapping the underlying sovToken.

- **PBM Token** - the sovToken and its PBM wrapper are collectively referred to as a PBM Token. PBM Tokens are represented as ERC-1155 tokens.

- **PBM Creator** defines the conditions of the PBM Wrapper to create PBM Tokens.

- **Merchant / Redeemer** - In the context of this proposal, a Merchant or a Redeemer is broadly defined as the ultimate recipient, or endpoint, for PBM tokens, to which these tokens are intrinsically directed or purpose-bound to. The identity of merchant/redeemer will be one of the validations performed by the compliance guard, which may be implemented as part of the PBM Wrapper smart contract or as a standalone compliance guard contract registered as a PBM hook.

### Overview

- PBM **SHALL** adhere to the definition of &quot;wrap&quot; or &quot;wrapping&quot; to mean binding a token in accordance with PBM business logic throughout its lifecycle.

- PBM **SHALL** adhere to the definition of &quot;unwrap&quot; or &quot;unwrapping&quot; to mean the release of a token in accordance with the PBM business logic during its lifecycle stage.

- A valid PBM Token **MUST** consist of an underlying sovToken and a PBM Wrapper.

  - The sovToken can be wrapped either upon the creation of the PBM Token or at a later date.

  - A sovToken can be implemented as any widely accepted ERC-20 compatible token, such as ERC-20, ERC-777, or ERC-1363.

- PBM Wrapper **MUST** provide a mechanism for all transacting parties to verify that all necessary condition(s) have been met before allowing the PBM Token to be unwrapped. Refer to Auditability section for elaborations. The necessary conditions can be implemented within the PBM wrapper, or in a separate PBM hook(s) smart contract(s).

- PBM Wrapper **MUST** ensure the destination address for unwrapped sovToken is in a whitelist of Merchant/Redeemer addresses and not in a blacklist of banned addresses prior to unwrapping the underlying sovToken.

- The PBM Token **MUST** be burnt upon being fully unwrapped and used.

- A PBM Token **SHOULD** have an expiry time that is decided by the PBM Creator.

  - For cases where an expiry time is not needed, the expiry time **SHOULD** be set to infinity (typically represented as the maximum value of uint256 or type(uint256).max).

- This proposal defines a base specification of what a PBM should entail. Extensions to this base specification can be implemented as separate specifications.

### PBM Architecture

In this EIP, we propose a modular PBM architecture that has three distinct components (the core, the plugins and the hooks):

- The **core components** contains basic functionalities and validation checks that all PBMs should have. Core components includes sovToken and PBM wrapper containing the core logic (e.g. logic to whitelist the merchant/redeemer address, logic to unwrap upon transfer to a whitelisted address, logic for minting and burning the PBM) and a token manager which allows for token registration, retrieval. In addition, the PBM wrapper **MAY** include logic to interface with plugins and hooks.
- The **plugin components** implement additional functionality that only specific PBMs may require (e.g. logic to call external application programming interfaces to verify specific PBM condition was met, logic to track PBM usage patterns).
- The **hook components** implement additional validation checks that some PBMs may need (e.g. checks for expiration, daily spending limit, goods &amp; services limit etc).

For example, a PBM creator may want to ensure that only 50% of PBM Series A can be spent in supermarkets, while there are no restrictions on the proportion of PBM Series B that can be spent in supermarkets. The creator can implement a plugin smart contract to keep track of supermarket spending by PBM users and a hook to validate that less than 50% of the PBM Series A issued to a user is spent in a supermarket. This approach allows the same generic PBM wrapper and sovToken to be used for both PBM Series A and B. In addition, PBM Series A will register the plugin module and hook module for additional data tracking and validations.

### Auditability

PBM Wrapper **SHOULD** provide the public easily accessible mechanism(s) to verify the smart contract logic for unwrapping a PBM. Such mechanisms could be leveraged by automated validation or asynchronous user verifications from transacting parties and/or whitelisted third parties attestations.

As the fulfilment of PBM conditions is likely to be subjected to audits to ensure trust amongst all transacting parties, the following evidence shall be documented to support audits:

- The interface/events emitted **SHOULD** allow a fine-grained recreation of the transaction history, token types and token balances
- The source code **SHOULD** be verified and formally published on a blockchain explorer.

### Fungibility

A PBM Wrapper **SHOULD** be able to wrap multiple types of compatible sovTokens (e.g. the same PBM Wrapper should be able to wrap USDC and XSGD). sovTokens wrapped by the same PBM wrapper may or may not be fungible to one another. The standard does NOT mandate how an implementation must do this.

### PBM token details

The ERC-1155 Multi Token Standard enables each token ID to correspond to a unique, configurable token type. All essential details facilitating the business or display logic for a PBM **MUST** be defined for each token type. The mandatory fields for this purpose are outlined in the `struct PBMToken` (below). Future proposals may define additional, optional state variables as needed. Once a token detail has been defined, it **MUST** be immutable.

Example of token details:

```solidity
pragma solidity ^0.8.0;

interface IPBMRC1_TokenManager {
    /// @notice A PBM token MUST include compulsory state variables (name, faceValue, expiry, and uri) to adhere to this standard.
    /// @dev Represents all the details corresponding to a PBM tokenId.
    struct PBMToken {
        // Name of the token.
        string name;

        // Value of the underlying wrapped ERC20-compatible sovToken. Additional information on the `faceValue` can be specified by
        // adding the optional variables: `currencySymbol` or `tokenSymbol` as indicated below
        uint256 faceValue;

        // Time after which the token will be rendered useless (expressed in Unix Epoch time).
        uint256 expiry;

        // Metadata URI for ERC-1155 display purposes.
        string uri;
    }
}
```

An implementer of the standard can enhance their PBM tokens with additional functionality by implementing the `IPBMRC1_TokenManagerExt` interface. This extension provides optional properties that can be used to support a variety of use cases beyond the core requirements.

```solidity
pragma solidity ^0.8.0;

interface IPBMRC1_TokenManagerExt {
    /// @notice Optional properties that a PBM token MAY include for extended functionality.
    /// @dev Represents additional optional fields that can be implemented for a PBM tokenId.
    struct PBMTokenExt {
        // Indicates if the PBM token can be transferred to a non merchant/redeemer wallet.
        bool isTransferable;

        // Determines whether the PBM will be burned or revoked upon expiry, under certain predefined conditions, or at the owner&apos;s discretion.
        bool burnable;

        // Number of decimal places for the token.
        uint8 decimals;

        // The address of the creator of this PBM type on this smart contract. This field is optional because the creator is msg.sender by default.
        address creator;

        // The smart contract address of the sovToken.
        address tokenAddress;

        // The running balance of the PBM Token type that has been minted.
        uint256 totalSupply;

        // An ISO4217 three-character alphabetic code may be needed for the faceValue in multicurrency PBM use cases.
        string currencySymbol;

        // An abbreviation for the PBM token name may be assigned.
        string tokenSymbol;

        // Add other optional state variables below...
    }
}
```

An implementer has the option to define all token types upon PBM contract deployment. If needed, they can also expose an external function to create new PBM tokens at a later time.
All token types created **SHOULD** emit a `NewPBMTypeCreated` event.

```solidity
    /// @notice Creates a new PBM Token type with the provided data.
    /// @dev The caller of createPBMTokenType shall be responsible for setting the creator address.
    /// Example of uri can be found in [`sample-uri`](/EIPs/assets/eip-7291/sample-uri/stx-10-static)
    /// MUST Emit the {NewPBMTypeCreated} event
    /// @param _name Name of the token.
    /// @param _faceValue Value of the underlying wrapped ERC20-compatible sovToken.
    /// @param _tokenExpiry Time after which the token will be rendered useless (expressed in Unix Epoch time).
    /// @param _tokenURI Metadata URI for ERC-1155 display purposes
    function createPBMTokenType(
        string memory _name,
        uint256 _faceValue,
        uint256 _tokenExpiry,
        string memory _tokenURI
    ) external returns (uint256 tokenId_);

    /// @notice Emitted when a new Purpose-Bound Token (PBM) type is created within the contract.
    /// @param tokenId The unique identifier for the newly created PBM token type.
    /// @param tokenName A human-readable string representing the name of the newly created PBM token type.
    /// @param amount The initial supply of the newly created PBM token type.
    /// @param expiry The timestamp at which the newly created PBM token type will expire.
    /// @param creator The address of the account that created the new PBM token type.
    event NewPBMTypeCreated(uint256 tokenId, string tokenName, uint256 amount, uint256 expiry, address creator);

```

Implementors of the standard **MUST** define a method to retrieve a PBM token detail

```solidity
    /// @notice Retrieves the details of a PBM Token type given its tokenId.
    /// @dev This function fetches the PBMToken struct associated with the tokenId and returns it.
    /// @param tokenId The identifier of the PBM token type.
    /// @return pbmToken_ A PBMToken struct containing all the details of the specified PBM token type.
    function getTokenDetails(uint256 tokenId) external view returns(PBMToken memory pbmToken_);
```

### Compliance Guard

A compliance guard should have logic to store and retrieve whitelisted merchants/redeemers and blacklisted addresses to fulfill the basic premise of a PBM. Additional logic can be added to fulfill other compliance goals.

```solidity
pragma solidity ^0.8.0;

/// @title Compliance Guard Interface.
/// @notice The compliance guard stores and manages whitelisted merchants/redeemers and blacklisted addresses for the PBMs
interface IComplianceGuard {
    /// @notice Checks if the address is one of the blacklisted addresses
    /// @param _address The address to query
    /// @return bool_ True if address is blacklisted, else false
    function isBlacklisted(address _address) external returns (bool bool_) ;

    /// @notice Checks if the address is one of the whitelisted merchant/redeemer addresses
    /// @param _address The address to query
    /// @return bool_ True if the address is in merchant/redeemer whitelist and is NOT a blacklisted address, otherwise false.
    function isMerchant(address _address) external returns (bool bool_) ;

    /// @notice Event emitted when the Merchant/Redeemer List is edited
    /// @param action Tags &quot;add&quot; or &quot;remove&quot; for action type
    /// @param addresses An array of merchant wallet addresses that was just added or removed from Merchant/Redeemer whitelist
    /// @param metadata Optional comments or notes about the added or removed addresses.
    event MerchantList(string action, address[] addresses, string metadata);

    /// @notice Event emitted when the Blacklist is edited
    /// @param action Tags &quot;add&quot; or &quot;remove&quot; for action type
    /// @param addresses An array of wallet addresses that was just added or removed from address blacklist
    /// @param metadata Optional comments or notes about the added or removed addresses.
    event Blacklist(string action, address[] addresses, string metadata);
}

```

### PBMRC1 - Base Interface

This interface contains the essential functions required to implement a pre-loaded PBM.

```solidity
pragma solidity ^0.8.0;

/// LIST OF EVENTS TO BE EMITTED
/// A database or explorer may listen to events and be able to provide indexed and categorized searches
/// @title PBM Specification interface
/// @notice The PBM (purpose bound money) allows us to add logical requirements on the use of sovTokens.
/// The PBM acts as wrapper around the sovTokens and implements the necessary business logic.
/// @dev PBM deployer must assign an overall owner to the smart contract. If fine grain access controls are required, EIP-5982 can be used on top of ERC173
interface IPBMRC1 is IERC173, IERC5679Ext1155 {

    /// @notice Initialise the contract by specifying an underlying ERC20-compatible token address,
    /// contract expiry and PBM Wrapper Logic smart contract&apos;s address.
    /// @param _sovToken The address of the underlying sovToken.
    /// @param _expiry The contract-wide expiry timestamp (in Unix epoch time).
    /// @param _pbmWrapperLogic This address should point to a smart contract that contains conditions governing a PBM;
    /// such as purpose-bound conditions (e.g., a compliance guard determining whether a PBM is permitted to be transferred or to be unwrapped)
    /// and other relevant business logic, effectively implementing an inversion of control.
    function initialise(address _sovToken, uint256 _expiry, address _pbmWrapperLogic) external;

    /// @notice Returns the Uniform Resource Identifier (URI) metadata information for the PBM with the corresponding tokenId.
    /// @dev URIs are defined in RFC 3986.
    /// The URI MUST point to a JSON file that conforms to the &quot;ERC-1155 Metadata URI JSON Schema&quot;.
    /// Developers may choose to adhere to the ERC1155Metadata_URI extension interface if necessary.
    /// The URI is not expected to be immutable.
    /// @param tokenId The id for the PBM in query
    /// @return Returns the metadata URI string for the PBM
    function uri(uint256 tokenId) external  view returns (string memory);

    /**
        @notice Creates a PBM copy ( ERC1155 NFT ) of an existing PBM token type.
        @dev See {IERC5679Ext1155} for further implementation notes
        @param receiver The wallet address to which the created PBMs need to be transferred to
        @param tokenId The identifier of the PBM token type to be copied.
        @param amount The number of the PBMs that are to be created
        @param data Additional data with no specified format, based on EIP-5750

        This function transfers the underlying token from the caller into the PBM smart contract.
        IMPT: Before minting, the caller should approve the contract address to spend sovTokens on behalf of the caller.
            This can be done by calling the `approve` or `increaseMinterAllowance` functions of the ERC-20 contract and specifying `_spender` to be the PBM contract address.
            Ref : https://eips.ethereum.org/EIPS/eip-20

        WARNING: Any contracts that externally call these safeMint() and safeMintBatch() functions should implement some sort of reentrancy guard procedure
        (such as OpenZeppelin&apos;s ReentrancyGuard) or a Checks-effects-interactions pattern.

        As per ERC-5679 standard: When the token is being minted, the transfer events MUST be emitted as if the token in the `amount` for EIP-1155
        and `tokenId` being _id for EIP-1155 were transferred from address 0x0 to the recipient address identified by receiver.
        The total supply MUST increase accordingly.

        MUST Emit the {TokenWrap} event as the underlying sovToken is wrapped by the PBM wrapper smart contract during minting.

        Requirements:
        - contract must not be paused
        - tokens must not be expired
        - `tokenId` should be a valid id that has already been created
        - caller should have the necessary amount of the sovTokens required to mint
        - caller should have approved the PBM contract to spend the sovTokens
        - receiver should not be blacklisted
     */
    function safeMint(address receiver, uint256 tokenId, uint256 amount, bytes calldata data) external;

    /**
        @notice Creates multiple PBM copies (ERC1155 NFT) of an existing PBM token type.
        @dev See {IERC5679Ext1155}.
        @param receiver The wallet address to which the created PBMs need to be transferred to
        @param tokenIds The identifier of the PBM token type
        @param amounts The number of the PBMs that are to be created
        @param data Additional data with no specified format, based on eip-5750

        This function will transfer the underlying token from the caller into the PBM smart contract.
        IMPT: Before minting, the caller should approve the contract address to spend sovTokens on behalf of the caller.
            This can be done by calling the `approve` or `increaseMinterAllowance` functions of the ERC-20 contract and specifying `_spender` to be the PBM contract address.
            Ref : https://eips.ethereum.org/EIPS/eip-20

        WARNING: Any contracts that externally call these safeMint() and safeMintBatch() functions should implement some sort of reentrancy guard procedure
        (such as OpenZeppelin&apos;s ReentrancyGuard) or a Checks-effects-interactions pattern.

        As per ERC-5679 standard: When the token is being minted, the transfer events MUST be emitted as if the token in the `amount` for EIP-1155
        and `tokenId` being _id for EIP-1155 were transferred from address 0x0 to the recipient address identified by receiver.
        The total supply MUST increase accordingly.

        MUST Emit the {TokenWrap} event as the underlying sovToken is wrapped by PBM wrapper smart contract during minting.

        Requirements:
        - contract must not be paused
        - tokens must not be expired
        - `tokenIds` should all be valid ids that have already been created
        - `tokenIds` and `amounts` list need to have the same number of values
        - caller should have the necessary amount of the sovTokens required to mint
        - caller should have approved the PBM contract to spend the sovTokens
        - receiver should not be blacklisted
     */
    function safeMintBatch(address receiver, uint256[] calldata tokenIds, uint256[] calldata amounts, bytes calldata data) external;

    /**
        @notice Burns a PBM token. Upon burning of the tokens, the underlying wrapped token (if any) should be handled.
        @dev Destroys `amount` tokens of token type `tokenId` from `from`
        @dev See {IERC5679Ext1155}

        @param from The originating wallet address of the PBMs to be burned
        @param tokenId The identifier of the PBM token type
        @param amount The amount of the PBMs that are to be burned
        @param data Additional data with no specified format, based on EIP-5750

        MUST Emit the {TransferSingle} event.
        MUST Emit the {TokenUnwrapForPBMBurn} event if the underlying wrapped token is moved out of the PBM smart contract.

        Requirements:
        - `from` cannot be the zero address.
        - `from` must have at least `amount` tokens of token type `tokenId`.

     */
    function burn(address from, uint256 tokenId, uint256 amount, bytes calldata data) external;

    /**
        @notice Burns multiple PBM token. Upon burning of the tokens, the underlying wrapped token (if any) should be handled.
        @dev Destroys `amount` tokens of token type `tokenId` from `from`
        @dev See {IERC5679Ext1155}

        @param from The originating wallet address of the PBMs to be burned
        @param tokenIds The identifier of the PBM token types
        @param amounts The amount of the PBMs that are to be burned for each tokenId in _tokenIds
        @param data Additional data with no specified format, based on eip-5750

        MUST Emit the {TransferSingle} event.
        MUST Emit the {TokenUnwrapForPBMBurn} event if the underlying wrapped token is moved out of the PBM smart contract.

        Requirements:
        - `from` cannot be the zero address.
        - `from` must have at least amount specified in `_amounts` of the corresponding token type tokenId in `_tokenIds` array.
     */
    function burnBatch(address from, uint256[] calldata tokenIds, uint256[] calldata amounts, bytes calldata data) external;

    /// @notice Transfers the PBM(NFT) from one wallet to another.
    /// @dev This function extends the ERC-1155 standard in order to allow the PBM token to be freely transferred between wallet addresses due to
    /// widespread support across wallet providers. Specific conditions and restrictions on whether a pbm can be moved across addresses can be incorporated in this function.
    /// Unwrap logic MAY also be placed within this function to be called.
    /// @param from The account from which the PBM (NFT) is moving from
    /// @param to The account which is receiving the PBM (NFT)
    /// @param id The identifier of the PBM token type
    /// @param amount The number of (quantity) the PBM type that are to be transferred of the PBM type
    /// @param data To record any data associated with the transaction, can be left blank if none
    function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes memory data) external;

    /// @notice Transfers the PBM(NFT)(s) from one wallet to another.
    /// @dev This function extends the ERC-1155 standard in order to allow the PBM token to be freely transferred between wallet addresses due to
    /// widespread support across wallet providers.  Specific conditions and restrictions on whether a pbm can be moved across addresses can be incorporated in this function.
    /// Unwrap logic MAY also be placed within this function to be called.
    /// If the receiving wallet is a whitelisted /redeemer wallet address, the PBM(NFT)(s) will be burnt and the underlying sovTokens will be transferred to the merchant/redeemer wallet instead.
    /// @param from The account from which the PBM (NFT)(s) is moving from
    /// @param to The account which is receiving the PBM (NFT)(s)
    /// @param ids The identifiers of the different PBM token type
    /// @param amounts The number of (quantity) the different PBM types that are to be created
    /// @param data To record any data associated with the transaction, can be left blank if none.
    function safeBatchTransferFrom(address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) external;

    /// @notice Unwraps the underlying ERC-20 compatible tokens to an intended end point (ie: merchant/redeemer) upon fulfilling the required PBM conditions.
    /// @dev Add implementation specific logic for the conditions under which a PBM processes and transfers the underlying tokens here.
    /// e.g. If the receiving wallet is a whitelisted merchant/redeemer wallet address, the PBM (NFT) MUST be burnt and the underlying sovTokens
    /// will unwrapped to be transferred to the merchant/redeemer wallet.
    /// MUST Emit the {TokenUnwrapForTarget} event on success
    /// @param from The account currently holding the PBM
    /// @param to The account receiving the PBM (NFT)
    /// @param tokenId The identifier of the PBM token type
    /// @param amount The quantity of the PBM type involved in this transaction
    /// @param data Additional data without a specified format, based on EIP-5750
    function unwrap(address from, address to, uint256 tokenId, uint256 amount, bytes memory data) internal;

    /// @notice Allows the creator of a PBM token type to retrieve all locked-up underlying sovTokens within that PBM.
    /// @dev Ensure that only the creator of the PBM token type or the contract owner can call this function.
    /// Validate the token state and existence, handle PBM token burning if necessary, safely transfer the remaining sovTokens to the originator,
    /// MUST Emit the {PBMrevokeWithdraw} event upon a successful revoke.
    /// @param tokenId The identifier of the PBM token type
    /// Requirements:
    /// - `tokenId` should be a valid identifier for an existing PBM token type.
    /// - The caller must be either the creator of the token type or the smart contract owner.
    function revokePBM(uint256 tokenId) external;

    /// @notice Emitted when a PBM type creator withdraws the underlying sovTokens from all the remaining expired PBMs
    /// @param beneficiary the address ( PBM type creator ) which receives the sovToken
    /// @param PBMTokenId The identifiers of the different PBM token type
    /// @param sovToken The address of the underlying sovToken
    /// @param sovTokenValue The number of underlying sovTokens transferred
    event PBMrevokeWithdraw(address beneficiary, uint256 PBMTokenId, address sovToken, uint256 sovTokenValue);

    /// @notice Emitted when the underlying tokens are unwrapped and transferred to a specific purpose-bound address.
    /// This event signifies the end of the PBM lifecycle, as all necessary conditions have been met to release the underlying tokens to the recipient (whitelisted merchant/redeemer with non-blacklisted wallet address).
    /// If there are multiple different underlying tokens involved in a single unwrap operation, this event should be emitted for each underlying token.
    /// @param from The address from which the PBM tokens are being unwrapped.
    /// @param to The purpose-bound address receiving the unwrapped underlying tokens.
    /// @param tokenIds An array containing the identifiers of the unwrapped PBM token types.
    /// @param amounts An array containing the quantities of the corresponding unwrapped PBM tokens.
    /// @param sovToken The address of the underlying sovToken.
    /// @param sovTokenValue The amount of unwrapped underlying sovTokens transferred.
    event TokenUnwrapForTarget(address from, address to, uint256[] tokenIds, uint256[] amounts, address sovToken, uint256 sovTokenValue);

    /// @notice Emitted when PBM tokens are burned, resulting in the unwrapping of the underlying tokens for the designated recipient.
    /// This event is required if there is an unwrapping of the underlying tokens during the PBM (NFT) burning process.
    /// If there are multiple different underlying tokens involved in a single unwrap operation, this event should be emitted for each underlying token.
    /// @param from The address from which the PBM tokens are being burned.
    /// @param to The address receiving the unwrapped underlying tokens.
    /// @param tokenIds An array containing the identifiers of the burned PBM token types.
    /// @param amounts An array containing the quantities of the corresponding burned PBM tokens.
    /// @param sovToken The address of the underlying sovToken.
    /// @param sovTokenValue The amount of unwrapped underlying sovTokens transferred.
    event TokenUnwrapForPBMBurn(address from, address to, uint256[] tokenIds, uint256[] amounts, address sovToken, uint256 sovTokenValue);

    /// Indicates the wrapping of a token into the PBM smart contract.
    /// @notice Emitted when underlying tokens are wrapped within the PBM smart contract.
    /// If there are multiple different underlying tokens involved in a single wrap operation, this event should be emitted for each underlying token.
    /// This event signifies the beginning of the PBM lifecycle, as tokens are now managed by the conditions within the PBM contract.
    /// @param from The address initiating the token wrapping process, and
    /// @param tokenIds An array containing the identifiers of the token types being wrapped.
    /// @param amounts An array containing the quantities of the corresponding wrapped tokens.
    /// @param sovToken The address of the underlying sovToken.
    /// @param sovTokenValue The amount of wrapped underlying sovTokens transferred.
    event TokenWrap(address from, uint256[] tokenIds, uint256[] amounts,address sovToken, uint256 sovTokenValue);
}

```

### Extensions

#### PBMRC1 - Token Receiver

Smart contracts MUST implement all of the functions in the PBMRC1_TokenReceiver interface to subscribe to PBM unwrap callbacks.

```solidity
pragma solidity ^0.8.0;

/// @notice Smart contracts MUST implement the ERC-165 `supportsInterface` function and signify support for the `PBMRC1_TokenReceiver` interface to accept callbacks.
/// It is optional for a receiving smart contract to implement the `PBMRC1_TokenReceiver` interface
/// @dev WARNING: Reentrancy guard procedure, Non delegate call, or the check-effects-interaction pattern must be adhere to when calling an external smart contract.
/// The interface functions MUST only be called at the end of the `unwrap` function.
interface PBMRC1_TokenReceiver {
    /**
        @notice Handles the callback from a PBM smart contract upon unwrapping
        @dev An PBM smart contract MUST call this function on the token recipient contract, at the end of a `unwrap` if the
        receiver smart contract supports type(PBMRC1_TokenReceiver).interfaceId
        @param _operator  The address which initiated the transfer (either the address which previously owned the token or the address authorised to make transfers on the owner&apos;s behalf) (i.e. msg.sender)
        @param _from      The address which previously owned the token
        @param _id        The ID of the token being unwrapped
        @param _value     The amount of tokens being transferred
        @param _data      Additional data with no specified format
        @return           `bytes4(keccak256(&quot;onPBMRC1Unwrap(address,address,uint256,uint256,bytes)&quot;))`
    */
    function onPBMRC1Unwrap(address _operator, address _from, uint256 _id, uint256 _value, bytes calldata _data) external returns(bytes4);

    /**
        @notice Handles the callback from a PBM smart contract upon unwrapping a batch of tokens
        @dev A PBM smart contract MUST call this function on the token recipient contract at the end of an `unwrap` if the
        receiver smart contract supports type(PBMRC1_TokenReceiver).interfaceId

        @param _operator  The address which initiated the transfer (either the address which previously owned the token or the address authorised to make transfers on the owner&apos;s behalf) (i.e. msg.sender)
        @param _from      The address which previously owned the token
        @param _id        The ID of the token being unwrapped
        @param _value     The amount of tokens being transferred
        @param _data      Additional data with no specified format
        @return           `bytes4(keccak256(&quot;onPBMRC1BatchUnwrap(address,address,uint256,uint256,bytes)&quot;))`
    */
    function onPBMRC1BatchUnwrap(address _operator, address _from, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external returns(bytes4);
}

```

#### PBMRC2 - Non preloaded PBM Interface

The **Non Preloaded** PBM extension is OPTIONAL for compliant smart contracts. This allows contracts to bind an underlying sovToken to the PBM at a later date instead of during a minting process.

Compliant contract **MUST** implement the following interface:

```solidity
pragma solidity ^0.8.0;

/**
 *  @dev This interface extends IPBMRC1, adding functions for working with non-preloaded PBMs.
 *  Non-preloaded PBMs are minted as empty containers without any underlying tokens of value,
 *  allowing the loading of the underlying token to happen at a later stage.
 */
interface PBMRC2_NonPreloadedPBM is IPBMRC1 {

  /// @notice This function extends IPBMRC1 to mint PBM tokens as empty containers without underlying tokens of value.
  /// @dev The loading of the underlying token of value can be done by calling the `load` function. The function parameters should be identical to IPBMRC1
  function safeMint(address receiver, uint256 tokenId, uint256 amount, bytes calldata data) external;

  /// @notice This function extends IPBMRC1 to mint PBM tokens as empty containers without underlying tokens of value.
  /// @dev The loading of the underlying token of value can be done by calling the `load` function. The function parameters should be identical to IPBMRC1
  function safeMintBatch(address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;

  /// @notice Wrap an amount of sovTokens into the PBM
  /// @dev function will pull sovTokens from msg.sender
  /// Approval must be given to the PBM smart contract in order to for the pbm to pull money from msg.sender
  /// underlying data structure must record how much the msg.sender has been loaded into the PBM.
  /// Emits {TokenLoad} event.
  /// @param amount    The amount of sovTokens to be loaded
  function load(uint256 amount) external;

  /// @notice Retrieves the balance of the underlying sovToken associated with a specific PBM token type and user address.
  /// This function provides a way to check the amount of the underlying token that a user has loaded into a particular PBM token.
  /// @param user The address of the user whose underlying token balance is being queried.
  /// @return The balance of the underlying sovToken associated with the specified PBM token type and user address.
  function underlyingBalanceOf(address user) external view returns (uint256);

  /// @notice Unloads all of the underlying token belonging to the caller from the PBM smart contract.
  /// @dev The underlying token that belongs to the caller (msg.sender) will be removed and transferred
  /// back to the caller.
  /// Emits {TokenUnload} event.
  /// @param amount The quantity of the corresponding tokens to be unloaded.
  /// Amount should not exceed the amount that the caller has originally loaded into the PBM smart contract.
  function unload(uint256 amount) external;

  /// @notice Emitted when an underlying token is loaded into a PBM
  /// @param caller Address by which sovToken is taken from.
  /// @param to Address by which the token is loaded and assigned to
  /// @param amount The quantity of tokens to be loaded
  /// @param sovToken The address of the underlying sovToken.
  /// @param sovTokenValue The amount of underlying sovTokens loaded
  event TokenLoad(address caller, address to, uint256 amount, address sovToken, uint256 sovTokenValue);

  /// @notice Emitted when an underlying token is unloaded from a PBM.
  /// This event indicates the process of releasing the underlying token from the PBM smart contract.
  /// @param caller The address initiating the token unloading process.
  /// @param from The address from which the token is being unloaded and removed from.
  /// @param amount The quantity of the corresponding unloaded tokens.
  /// @param sovToken The address of the underlying sovToken.
  /// @param sovTokenValue The amount of unloaded underlying sovTokens transferred.
  event TokenUnload(address caller, address from, uint256 amount, address sovToken, uint256 sovTokenValue);
}

```

## Rationale

### Why sovToken **MUST** be ERC-20 compatible?

As PBM is envisioned to have functionality of money, it has to be a fungible token with stable value. Currently, the major stablecoins in the market are mainly based on the ERC-20 interface. ERC-20 or ERC-20 compatible tokens are the most widely supported by existing wallets, defi apps, and used also by protocol design such as [ERC-4337](/EIPs/EIPS/eip-4337) and more importantly they are the de facto standard for fungible tokens.

With regards to [ERC-721](/EIPs/EIPS/eip-721) and ERC-1155 compatible tokens:

- ERC-721 is not suitable given that it is a standard for non-fungible tokens, which cannot fulfill the functions of money.
- While ERC-1155 tokens could be used for fungible tokens, we decided not to include it because there is a lack of ERC-1155 stablecoins in the market. Requiring the PBM interface to support both ERC-20 compatible and ERC-1155 compatible sovToken would complicate PBM interface without adding much practical utility. Furthermore, the base ERC-1155 does not support decimals, but this is not a dealbreaker as there can be workarounds. However, should there be changes in the stablecoin market in future, a revision can be considered.

### Why PBM Wrapper **MUST** be ERC-1155 compatible?

This paper extends the ERC-1155 standards in order to enable easy adoption by existing wallet providers. Currently, most wallet providers are able to support and display ERC-20, ERC-1155 and ERC-721 standards. An implementation which doesn&apos;t extend these standards will require the wallet provider to build a custom user interface and interfacing logic which increases the implementation cost and lengthen the time-to-market.

The core aim of our proposal is to standardize the implementation of PBM. Hence, we have surveyed existing interface standards and decided to build upon ERC-1155 standard for the PBM tokens for the following reasons:

- ERC-1155 allows a single contract to support multiple tokens. This is very useful for the PBM use cases as a single contract can support issuance of tokens with different denominations, expiry dates, business logics.
- ERC-1155 also has batch transfer support, which is absent in ERC-20, which could lead to gas savings when tokens have to be airdropped to a large number of recipients.
- ERC-1155 is able to support semi-fungible tokens which could be very useful for PBM use cases as a PBM can be converted into a collectible after its expiry.
- ERC-1155 allows for a visualisation of a PBM token on the UI of a wallet issuer.

### Why PBM **MUST** ensure the destination address for unwrapped sovToken is in a whitelist of Merchant/Redeemer addresses and not in a blacklist of banned addresses prior to unwrapping the underlying sovToken?

Why do we need a whitelist?

- The whitelist is a compulsory requirement because a PBM is purpose-bound, i.e., it should be unwrapped only if all conditions are fulfilled and it is transferred to someone in the predefined whitelist.
- In some implementations, developers can define a whitelisted address dynamically at runtime, such as requiring the presence of an NFT in a wallet address or relying on an oracle, etc.

Why do we need a blacklist?

- The blacklist is a compulsory requirement to ensure that accounts which were banned for various reasons (e.g., address owner has re-registered a new account, address owner suspended, withdrawn, or expelled due to complaints or law enforcement reasons, etc.) are excluded.

Why we can&apos;t have either a whitelist or a blacklist?

- While the same effect can be obtained by only having a whitelist, repeatedly redeploying the whitelist to the blockchain to ban one person is not gas efficient.
- Using only a blacklist to implement purpose-bound money is not practical as it would require maintaining a list of all addresses to be excluded and updating it whenever a new account is created.

Why is there a need for destination?

- This forms the core of our proposal: a PBM can be unwrapped when only it is transferred to pre-approved destinations.
- PBMs can be transferred freely, but only the target is allowed to unwrap the PBM and take delivery of the underlying sovToken must be limited to differentiate it from plain vanilla stablecoins that are wrapped by smart contracts.

### What does business logic encompass?

- In general, business logic can be categorized into core, plugin, and hook logic:
  - Core logic contains essential functionalities and validation checks and should be included in the PBM Wrapper contract.
  - Plugin and hook logic can be implemented as standalone smart contract modules and are registered by the PBM Wrapper contract. Plugin logic extends the core logic by adding functionality, e.g., custom data collection, additional administrative functions, etc.
  - Hook logic implements additional validation checks which are only applicable for a subset of PBMs.
- &quot;PBM business logic&quot; can contain access control logic, PBM unwrapping logic, API logic to integrate with non-blockchain IT systems.
- As PBM can be used for a wide variety of use cases, ranging from government disbursement tokens, shopping vouchers, prepaid tokens, rewards points tokens, purpose-bound donation tokens, school allowance tokens, etc., with each use case having separate business logic, it was intentionally left undefined so that implementation authors can have maximum flexibility.

### Why was a push transaction model chosen?

- This standard sticks to the push transaction model where the transfer of PBM is initiated on the sender&apos;s side. Modern wallets can support the required PBM logic by embedding the unwrapping logic within the ERC-1155 `safeTransfer` function.

### Customisability

Each ERC-1155 PBM Token would map to an underlying `PBMToken` data structure that implementers are free to customize in accordance to the business logic.

By mapping the underlying ERC-1155 token model with an additional data structure, implementers gain flexibility in the management of multiple token types within the same smart contract with multiple conditional unwrapping logic attached to each token type, reducing gas costs as there is no need to deploy multiple smart contracts for each token type.

1. To keep it simple, this standard _intentionally_ omits functions or events that doesn&apos;t add to definition and concept of a PBM.

2. This EIP makes no assumptions about access control or the conditions under which a function can be executed. It is the responsibility of the PBM creator to determine the various roles involved in each specific PBM business flow.

3. The proposed PBM Architecture _intentionally_ modular to enable greater customisability and reusability of smart contracts.

4. Metadata associated to the PBM standard is not included the standard. If necessary, related metadata can be created with a separate metadata extension interface, e.g. `ERC721Metadata` from ERC-721. Refer to Opensea&apos;s metadata-standards for an implementation example.

5. To allow for future extensibility, it is **RECOMMENDED** that developers read and adopt the specifications for building general extensibility for method behaviours ([ERC-5750](/EIPs/EIPS/eip-5750)).

## Backwards Compatibility

This interface is designed to be compatible with ERC-1155.

## Reference Implementation

Reference implementations can be found in [`README.md`](/EIPs/assets/eip-7291/).

## Security Considerations

- Malicious users may attempt to:

  - Double spend through reentrancy.
  - clone existing PBM Tokens to perform double-spending;
  - create invalid PBM Token with no underlying sovToken; or
  - falsifying the face value of PBM token through wrapping of fraudulent/invalid/worthless sovTokens.

- For consistency, when the contract is suspended or a user&apos;s token transfer is restricted due to suspected fraudulent activity or erroneous transfers, corresponding restrictions **MUST** be applied to the user&apos;s unwrap requests for the PBM Token.

- Security audits and tests should be performed to verify that unwrap logic behaves as expected or if any complex business logic is being implemented that involves calling an external smart contract to prevent re-entrancy attacks and other forms of call chain attacks.

- This EIP relies on the secure and accurate bookkeeping behavior of the token implementation.

  - Contracts adhering to this standard should closely monitor balance changes for each user during token consumption or minting.

  - The PBM Wrapper must be meticulously designed to ensure effective control over the permission to mint new tokens. Failure to secure the minting permission can lead to fraudulent issuance and unauthorized inflation of the total token supply.

  - The mapping of each PBM Token to the corresponding amount of underlying sovToken held by the smart contract requires careful accounting and auditing.

  - The access control over permission to burn tokens should be carefully designed. Typically, only the following two roles are entitled to burn a token:

    - Role 1. Prior to a PBM&apos;s expiry, only whitelisted merchants/redeemers with non-blacklisted wallet addresses are allowed to unwrap and burn tokens that they hold.
    - Role 2. After a PBM has expired:
      - whitelisted merchants/redeemers with non-blacklisted wallet addresses are allowed to unwrap and burn tokens that they hold; and
      - PBM owners are allowed to burn unused PBM Tokens remaining in the hands of non-whitelisted merchants/redeemers to retrieve underlying sovTokens.

  - Nevertheless, we do recognize there are potentially other use cases where a third type of role may be entitled to burning. Implementors should be cautious when designing access control over burning of PBM Tokens.

- It is recommended to adopt a sovToken standard that is compatible with ERC-20. Examples of such compatible tokens include those implementing ERC-777 or ERC-1363. However, ERC-20 remains the most widely accepted due to its simplicity and there is a high degree of confidence in its security.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 24 Jun 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7291</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7291</guid>
      </item>
    
      <item>
        <title>Token-Controlled Token Circulation</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7303-token-controlled-token-circulation/15020</comments>
        
        <description>## Abstract

This ERC introduces an access control scheme termed Token-Controlled Token Circulation (TCTC). By representing the privileges associated with a role as an [ERC-721](/EIPs/EIPS/eip-721) or [ERC-1155](/EIPs/EIPS/eip-1155) token (referred to as a `control token`), the processes of granting or revoking a role can be facilitated through the minting or burning of the corresponding `control token`. 

## Motivation

There are numerous methods to implement access control for privileged actions. A commonly utilized pattern is &quot;role-based&quot; access control as specified in [ERC-5982](/EIPs/EIPS/eip-5982). This method, however, necessitates the use of an off-chain management tool to grant or revoke required roles through its interface. Additionally, as many wallets lack a user interface that displays the privileges granted by a role, users are often unable to comprehend the status of their privileges through the wallet.

### Use Cases

This ERC is applicable in many scenarios where role-based access control as described in [ERC-5982](/EIPs/EIPS/eip-5982) is used. Specific use cases include:

**Mint/Burn Permission:**
In applications that circulate items such as tickets, coupons, membership cards, and site access rights as tokens, it is necessary to provide the system administrator with the authority to mint or burn these tokens. These permissions can be realized as `control tokens` in this scheme.

**Transfer Permission:**
In some situations within these applications, it may be desirable to limit the ability to transfer tokens to specific agencies. In these cases, an agency certificate is issued as a `control token`. The ownership of this `control token` then provides the means to regulate token transfers.

**Address Verification:**
Many applications require address verification to prevent errors in the recipient&apos;s address when minting or transferring target tokens. A `control token` is issued as proof of address verification to users, which is required by the recipient when a mint or transfer transaction is executed, thus preventing misdeliveries. In some instances, this `control token` for address verification may be issued by a government agency or specific company after an identity verification process.

## Specification

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

1. Smart contracts implementing the [ERC-7303](/EIPs/EIPS/eip-7303) standard MUST represent the privilege required by the role as an ERC-721 token or ERC-1155 token. The tokens that represent privileges are called `control tokens` in this ERC. The `control token` can be any type of token, and its transactions may be recursively controlled by another `control token`.
2. To associate the required `control token` with the role, the address of the previously deployed contract for the `control token` MUST be used.
3. To ascertain whether an account possesses the necessary role, it SHOULD be confirmed that the balance of the `control token` exceeds 0, utilizing the `balanceOf` method defined in ERC-721 or ERC-1155. Note that the `typeId` must be specified if an ERC-1155 token is used for the `balanceOf` method.
4. To grant a role to an account, a `control token` representing the privilege SHOULD be minted to the account using `safeMint` method defined in [ERC-5679](/EIPs/EIPS/eip-5679).
5. To revoke a role from an account, the `control token` representing the privilege SHOULD be burned using the `burn` method defined in ERC-5679.
6. A role in a compliant smart contract is represented in the format of `bytes32`. It&apos;s RECOMMENDED the value of such role is computed as a `keccak256` hash of a string of the role name, in this format: `bytes32 role = keccak256(&quot;&lt;role_name&gt;&quot;)` such as `bytes32 role = keccak256(&quot;MINTER&quot;)`.

## Rationale

The choice to utilize ERC-721 or ERC-1155 token as the control token for privileges enhances visibility of such privileges within wallets, thus simplifying privilege management for users.

Generally, when realizing privileges as tokens, specifications like Soulbound Token (e.g., [ERC-5192](/EIPs/EIPS/eip-5192)) are used. Given that ERC-5192 inherits from ERC-721, this ERC has choiced ERC-721 as the requirement for the control token.

Employing a transferable control token can cater to scenarios where role delegation is necessary. For example, when an authority within an organization is replaced or on vacation, the ability to transfer their privileges to another member becomes possible. The decision to designate the control token as transferable will depend on the specific needs of the application.

## Backwards Compatibility

This ERC is designed to be compatible for [ERC-721](./eip-721), [ERC-1155](./eip-1155), and [ERC-5679](./eip-5679) respectively.

## Reference Implementation

ERC-7303 provides a modifier to facilitate the implementation of TCTC access control in applications.　This modifier checks if an account possesses the necessary role. ERC-7303 also includes a function that grants a specific role to a designated account.

```solidity
// SPDX-License-Identifier: Apache-2.0

pragma solidity ^0.8.9;

import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;
import &quot;@openzeppelin/contracts/token/ERC1155/ERC1155.sol&quot;;

abstract contract ERC7303 {
    struct ERC721Token {
        address contractId;
    }

    struct ERC1155Token {
        address contractId;
        uint256 typeId;
    }

    mapping (bytes32 =&gt; ERC721Token[]) private _ERC721_Contracts;
    mapping (bytes32 =&gt; ERC1155Token[]) private _ERC1155_Contracts;

    modifier onlyHasToken(bytes32 role, address account) {
        require(_checkHasToken(role, account), &quot;ERC7303: not has a required token&quot;);
        _;
    }

    /**
     * @notice Grant a role to user who owns a control token specified by the ERC-721 contractId. 
     * Multiple calls are allowed, in this case the user must own at least one of the specified token.
     * @param role byte32 The role which you want to grant.
     * @param contractId address The address of contractId of which token the user required to own.
     */
    function _grantRoleByERC721(bytes32 role, address contractId) internal {
        require(
            IERC165(contractId).supportsInterface(type(IERC721).interfaceId),
            &quot;ERC7303: provided contract does not support ERC721 interface&quot;
        );
        _ERC721_Contracts[role].push(ERC721Token(contractId));
    }

    /**
     * @notice Grant a role to user who owns a control token specified by the ERC-1155 contractId. 
     * Multiple calls are allowed, in this case the user must own at least one of the specified token.
     * @param role byte32 The role which you want to grant.
     * @param contractId address The address of contractId of which token the user required to own.
     * @param typeId uint256 The token type id that the user required to own.
     */
    function _grantRoleByERC1155(bytes32 role, address contractId, uint256 typeId) internal {
        require(
            IERC165(contractId).supportsInterface(type(IERC1155).interfaceId),
            &quot;ERC7303: provided contract does not support ERC1155 interface&quot;
        );
        _ERC1155_Contracts[role].push(ERC1155Token(contractId, typeId));
    }

    function _checkHasToken(bytes32 role, address account) internal view returns (bool) {
        ERC721Token[] memory ERC721Tokens = _ERC721_Contracts[role];
        for (uint i = 0; i &lt; ERC721Tokens.length; i++) {
            if (IERC721(ERC721Tokens[i].contractId).balanceOf(account) &gt; 0) return true;
        }

        ERC1155Token[] memory ERC1155Tokens = _ERC1155_Contracts[role];
        for (uint i = 0; i &lt; ERC1155Tokens.length; i++) {
            if (IERC1155(ERC1155Tokens[i].contractId).balanceOf(account, ERC1155Tokens[i].typeId) &gt; 0) return true;
        }

        return false;
    }
}
```

The following is a simple example of utilizing `ERC7303` within an ERC-721 token to define &quot;minter&quot; and &quot;burner&quot; roles. Accounts possessing these roles are allowed to create new tokens and destroy existing tokens, facilitated by specifying ERC-721 or ERC-1155 control tokens: 

```solidity
// SPDX-License-Identifier: Apache-2.0

pragma solidity ^0.8.9;

import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;
import &quot;@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol&quot;;
import &quot;./ERC7303.sol&quot;;

contract MyToken is ERC721, ERC7303 {
    bytes32 public constant MINTER_ROLE = keccak256(&quot;MINTER_ROLE&quot;);
    bytes32 public constant BURNER_ROLE = keccak256(&quot;BURNER_ROLE&quot;);

    constructor() ERC721(&quot;MyToken&quot;, &quot;MTK&quot;) {
        // Specifies the deployed contractId of ERC721 control token.
        _grantRoleByERC721(MINTER_ROLE, 0x...);
        _grantRoleByERC721(BURNER_ROLE, 0x...);

        // Specifies the deployed contractId and typeId of ERC1155 control token.
        _grantRoleByERC1155(MINTER_ROLE, 0x..., ...);
        _grantRoleByERC1155(BURNER_ROLE, 0x..., ...);
    }

    function safeMint(address to, uint256 tokenId)
        public onlyHasToken(MINTER_ROLE, msg.sender)
    {
        _safeMint(to, tokenId);
    }

    function burn(uint256 tokenId) 
        public onlyHasToken(BURNER_ROLE, msg.sender) 
    {
        _burn(tokenId);
    }
}
```

## Security Considerations

The security of tokens subject to circulation depends significantly on the security of the control tokens. Careful consideration must be given to the settings regarding the administrative privileges, mint/transfer/burn permissions, and the possibility of contract updates of control tokens.

In particular, making control tokens transferable allows for flexible operations, such as the temporary delegation of administrative rights. However, it also raises the possibility that the rights to circulate tokens could fall into the hands of inappropriate third parties. Therefore, control tokens should generally be made non-transferable. If control tokens are to be made transferable, at the very least, the authority to burn these tokens should be retained by a trusted administrator.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 09 Jul 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7303</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7303</guid>
      </item>
    
      <item>
        <title>ERC/EIP Repository split</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/proposal-forking-ercs-from-eips-repository/12804</comments>
        
        <description>## Abstract

Describes the motivation and rational for splitting the EIP repositories into an
EIP repository, targeting core ethereum changes and an ERC repository, targeting
application layer specifications.

## Motivation

Long ago when the EIPs repository was created, there was a vision of a single
home for all standards related to Ethereum. The community was small and most
people were interacting at every level of the ecosystem. It made sense to
combine application standards with core consensus changes.

Since then, the ecosystem has grown. Today, the chasm between application
development and core development is wide. Fewer people are involved across the
ecosystem (for better or worse); yet the repository remains unified.

For years, we&apos;ve considered separating the repository. This would allow ERC and
EIP specifications to evolve more naturally due to the independence. But it&apos;s
always difficult to reach critical threshold to make a change like this happen.
Each time we get lost in the details of the migration and the debate grinds
progress to a halt.

Now that the Consensus Layer is also utilizing the EIP process, the cracks are
becoming more visible. There are changes we could make to the process that might
benefit them more, but because we also need to ensure the quality of ERCs, we
are restricted.

There are also many more efforts to catalyze applications around the ERC
process. Attempts have been made to develop working groups and review groups for
certain ERC &quot;categories&quot; (a distinction that doesn&apos;t even technically exist
because of the unified repo).

## Specification

This specification only details with the initial mechanism of the split. The
particulars of how each repository will govern itself is out of scope for this
EIP, as it is the motivating point of this EIP that the divergent needs of the
community will require highly divergent methods.

1. All ERCs and Interface-category EIPs are removed from this repository and
   migrated to a new repo. The history should be intact so that repo should be
   forked of this one with the non-ERCs removed. 
2. The new ERCs repository goes live and includes the changes from the script.
3. Setup ercs.ethereum.org subdomain and update the CI to point to the ERCs
   repo.
4. Set up a redirect for ERCs on eips.ethereum.org to go to the new website.
5. Create a unified document for editors to assign EIP/ERC numbers. EIPs and
   ERCs will no longer be based on an initial PR number but on a number
   incremented by the EIP editors of their respective repositories. EIPs will be
   assigned even numbers and ERCs will be assigned odd numbers. The exact timing
   of this migration is a policy decision of the editors.

The EIP repository will be associated with core protocol changes, specifically
the kind that would be discussed in one of the AllCoreDevs calls; whereas the
ERC repository will be affiliated with all remaining areas such as smart
contract application interfaces, wallet standards, DeFi protocol standards, and
all other such improvements that do not require core protocol changes.

This association is to persist across any other process changes the EIP editors
may introduce such as working groups, topic groups, expert groups, special
interest groups, splitting of the process, or other such changes. Any
sub-groupings that includes core protocol changes would be associated with the
EIP repository and other sub-groupings are associated with the ERC repository.
Any such process change are out of scope of this EIP and are independent of the
structural changes to the repositories specified in this EIP.

There may be further structural changes to repository layouts to accommodate
more sub-groupings. Such proposals are out of scope of this EIP.

## Rationale

There are two major communities served by the EIP process that are highly
divergent and very differentiated in their needs.

Let&apos;s consider the impact of specification ambiguity, the impacts are different
based on the community. The core protocol community has a low tolerance for
difference of implementation and a high penalty for specification ambiguity. An
improperly implemented part of a new spec could cause the ethereum mainnet to
split, possibly costing millions to billions of value lost to node operators as
well as community members using the services offered by the Ethereum protocols.
A poorly specified solidity interface, however, can be adapted and implemented
in multiple compatible ways across any smart choosing to implement it. A missing
RPC API (such as a configuration option specifying the number of decimals in the
chains native currency) can have limited to zero impact on the rest of the
community not choosing to use that wallet.

Timeframe for delivery of a feature is also similarly differentiated. A Core
protocol EIP adjusting the gas cost for transaction data needs to be rolled out
at a specific time uniformly across the network. Whereas a new RPC to support
new semantics to gas estimation would not need uniform rollout across the
Ethereum clients, and in fact would also need to be rolled out by service
provides that provide RPC services for Ethereum networks. Wallets can use early
support as a differentiating factor in their appeal to community members.

To address this divergence the AllCoreDevs call has adopted a lifecycle for EIPs
different from the Draft -&gt; Review -&gt; Last Call -&gt; Final lifecycle of the EIP
repository. It would best be described as Draft -&gt; Eligible for Inclusion -&gt;
Considered for Inclusion -&gt; Testnet -&gt; Mainnet. The EIPs also get slotted for a
fork in the third step, a consideration that simply does not apply to a smart
contract or wallet standard.

Several alternatives have been proposed, but the actual implementation only
further underscores the specialization that each side of the split encounters.

### Alternative: Working Groups

One repeated concern of editors is that they often lack the technical experience
to adequately judge if an EIP is complete and sound. Considering that EIPs
covers wide variety of topics such as elliptic curve cryptography, VM
performance, DeFi market dynamics, compression protocols, NFT Royalties, and
consensus protocols it is impossible for a single editor to provide sensible
feedback on every one of those topics.

When examining how the core protocol and ERC communities would approach the
working group process, however, it underscores how different they would handle
it. For core protocol change the working group would be one of the two
AllCoreDevs meetings, either AllCoreDevs-Execution or AllCoreDevs-Consensus. And
sometimes both. There is no EIP that would be shipped in mainnet that would not
first be extensively considered by one of these two groups.

ERC proposals have no such standing groups. Wallet impacting changes may go
through the AllWalletDevs group, but it is entirely possible for a wallet or
group of wallets to collaborate on a protocol outside AllWalletDevs. Smart
contract APIs have no such standing meeting.

The Working Group model, however, would be a critical social signal for the ERC
community. It would signal a critical mass for a particular proposal issue if
enough experts could get together to agree to review a set of changes.

While working groups are excellent for the ERC community, it is overhead for the
core protocol community that would only add friction to an already established
process with know governance checkpoints.

### Alternative: Specialized Editors

This alternative has already been implemented with the introduction of the
`eip-editors.yml` file. This allows for different groups of editors to review
different types of EIPs.

There has been no measurable impact on the divergence of the community. Most
categories have a significant overlap with other categories.

This alternative does not address the governance and workflow issues that the
Core Protocol Developers would want to implement. All subgroups would still be
subject to the same workflow as other groups.

### Alternative: Pain unrelated to process divergences

This is a catch-all for a number of proposals, from allowing discord links in
discussion-to to allowing more freedom in external links.

While the theory that this may reduce the total amount of pain felt by users and
editors, bringing the pain level down to a more acceptable level, this does not
address the core divergence issue. Many of these pain relief proposals should
probably be done anyway, weather or not the EIP repository splits.

### Alternative: Replace EIP Editors with AI Chatbots

Nobody wins in this proposal. We would instead end up debating training sets,
competing implementations, and whether to use commercial providers. And
that&apos;s if things go well.

AI chatbots, however, would not be able to compartmentalize the divergent needs
of the multiple groups if all adjudication were to be handled with one model or
one chat session. Higher quality output would be received if separate training
repositories were used for each major functional area.

### Alternatives are not Mutually Exclusive

It is critical to note that most of the discussed alternatives all have merits
and address important pain points. The adoption of a split should not be viewed
as a rejection of those alternatives. To quote a famous internet meme &quot;Why Not
Both?&quot;

### Objection: This splits the ethereum community

One objection is that splitting the repository would result in the community no
longer being able to say &quot;we are all of us Ethereum Magicians.&quot;

First it is important to note that such splits are already occurring. The
AllCoreDevs call has split into a Consensus and Execution layer call. ACD calls
no longer discuss client issues like wallet apis, the AllWalletDevs call has
adopted those issues and has grown into user experience issues. Cross chain
issues have been adopted by the Chain Agnostic Improvement Process (CAIP) group.

Rather than splitting this should be viewed as &quot;sharding&quot;, where a sub-community
of interest rallies around a shared sub issue, and by gathering are able to
increase the total scope of the community. CAIP is a perfect example where
operating separate from EIPs have allowed them to strengthen the ethereum
community.

Is a single cell organism weakened when it grows large and then splits into two?
Is an animal weakened when cells split and specialize into different tasks? It
is this very act of division and specialization that allows it to accomplish the
things that would be impossible as a single uniform cell.

### Objection: This should be an  [EIP-1](/EIPs/EIPS/eip-1) proposal

Since this is directly impacting the ERC process it should be documented
in  [EIP-1](/EIPs/EIPS/eip-1) first.

As the old programming adage goes: &quot;Refactor first before adding any new
features.&quot;  Adding new processes specific to the post-split governing docs would
only confuse the existing process, adding special cases for one class of EIPs
that don&apos;t apply to another. It is precisely this kind of problem the proposed
split is aiming to change.

This is also valid grounds for a Meta category EIP, as how many and which
repository to put a proposal in is core to the &quot;procedures, guidelines, \[and\]
changes to the decision-making process&quot;.

Some process changes that can be expected in a Core Protocol EIP may include:

* Changing the work flow to add the Eligible for Inclusion/Considered for
  Inclusion stages to a pre-last-call EIP.
* Adding test net and mainnet steps to the lifecycle
* Adding a &quot;fork&quot; header to the RFCs section, for EIPs that are (or will be)
  implemented in a specific fork
* Changing the testing section to a header link to reference tests

Some process change ERC may want to adopt:

* A strong working group model and adding an optional &quot;forming working group&quot;
  step editors may require.
* Add an &quot;outdated&quot; or &quot;replaced&quot; lifecycle step for EIPs that are abrogated by
  future specs.
* Deputize single-eip reviewers for specific EIPs

### Objection: Structural changes to a repository and process changes do not need to be bundled.

It is possible to split the structure of the repositories separately from any
EIP process changes related to this. Bundling the changes is unnecessary and
such structure and process changes should be handled independently.

To accommodate this objection this EIP has been revised to only address
structural changes in the repository and can be adapted to any other,
independent, process changes and mapped onto those outcomes.

## Backwards Compatibility

### Old Links

Old ERC links pointing to the old url `https://eips.ethereum.org/` will continue
to work. Redirect instructions will be put into place to redirect to the new ERC
repos for their corresponding location.

### Stray Proposals

ERC community members may continue to post new ERCs in the EIP proposal. Editors
will be able to redirect them to the new repository. ERCs that do not respond to
editor requests would not be merged anyway.

## Security Considerations

This proposal only addresses the EIP and ERC proposal process and is not
expected to expose any new attack surfaces by virtue of its adoption.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 13 Jul 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7329</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7329</guid>
      </item>
    
      <item>
        <title>Migration Transaction</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-xxxx-migration-transaction/15144</comments>
        
        <description>## Abstract

Introduce a new [EIP-2718](/EIPs/EIPS/eip-2718) transaction type with the format `0x04 || rlp([chainId, nonce, maxFeePerGas, maxPriorityFeePerGas, gasLimit, codeAddr, storage, data, value, accessList, yParity, r, s])` which sets the sending account&apos;s `code` field in the state trie to the `code` value at `codeAddr` and applies the storage tuples to the sender&apos;s storage trie.

## Motivation

Smart contract wallets have long been touted as the solution to Ethereum&apos;s user experience woes. As early as 2015, there were proposals for allowing smart contracts to originate transactions in hopes that new users would flock to smart contract wallets to store their assets. So far, only a fraction of users have elected to do so.

Today, account abstraction is still an important goal in Ethereum and there are many efforts attempting to realize it. We&apos;re getting closer to succeeding at this, but unfortunately the years of failure have caused many users to simply rely on EOA.

After a user has accumulated enough assets in an EOA, it is not tenable to migrate each individual asset to a new address. This is due both to the cost and to needing to manually sign and verify potentially hundreds of transactions.

This is an overlooked piece of the problem. Converting *existing* users to smart contract wallets efficiently will expedite adoption and push forward better support and integrations for smart contract wallets. They will no longer be dismissed as a niche use case.

Therefore, we must provide a mechanism, embedded in the protocol, to migrate EOAs to smart contracts. This EIP proposes such mechanism.

## Specification

At the fork block `X`, introduce the migration transaction type.

### Migration Transaction

#### Definition

| field                  | type      |
|------------------------|-----------|
| `chainId`              | `uint256` |
| `nonce`                | `uint64`  |
| `maxFeePerGas`         | `uint256` |
| `maxPriorityFeePerGas` | `uint256` |
| `gasLimit`             | `uint64`  |
| `codeAddr`             | `address` |
| `storage`              | `List[Tuple[uint256, uint256]]` |
| `data`                 | `bytes`   |
| `value`                | `uint256` |
| `accessList`           | `List[Tuple[address, List[uint256]]]` |
| `yParity`              | `uint8`   |
| `r`                    | `uint256` |
| `s`                    | `uint256` |

The EIP-2718 `TransactionType` is `0x04` and the `TransactionPayload` is `rlp([chainId, nonce, maxFeePerGas, maxPriorityFeePerGas, gasLimit, codeAddr, storage, data, value, accessList, yParity, r, s])`.

The transaction&apos;s signature hash is `keccak256(0x04 || rlp([chainId, nonce, maxFeePerGas, maxPriorityFeePerGas, gasLimit, codeAddr, storage, data, value, accessList])`

#### Validation

A migration transaction is considered valid if the follow properties hold:

* all [EIP-1559](/EIPs/EIPS/eip-1559) properties, unless specified otherwise
* the code at `codeAddr` is less than the [EIP-170](/EIPs/EIPS/eip-170) limit of `24576`
* the code at `codeAddr` must not have size `0`

The intrinsic gas calculation modified from [EIP-1559](/EIPs/EIPS/eip-1559) to be `21000 + 16 * non-zero calldata bytes + 4 * zero calldata bytes + 1900 * access list storage key count + 2400 * access list address count + 20000 * length of storage`.

#### Processing

Executing a migration transaction has two parts.

##### Contract Deployment

Unlike standard contract deployment, a migration transaction directly specifies what `code` value the sender&apos;s account should be set to.

As the first step of processing the transaction, set the sender&apos;s `code` to `state[tx.codeAddr].code`. Next, for each tuple in `tx.storage` and the sender&apos;s storage trie, set `storage[t.first] = t.second`.

##### Transaction Execution

Now instantiate an EVM call into the sender&apos;s account using the same rules as [EIP-1559](/EIPs/EIPS/eip-1559) and set the transaction&apos;s origin to be `keccak256(sender)[0..20]`.

## Rationale

### No `to` address field

This transaction is only good for one-time use to migrate an EOA to a smart contract. It is designed to immediately call the deployed contract, which is at the sender&apos;s address, after deployment to allow the sender to do any kind of further processing.

### Code pointer for deployment

Naively, one could design the migration transaction to have a field `code` of type `bytes`. However, there would be substantial duplication of code calldata, since many users will want to deploy the exact same thing (often a wallet). Using a pointer instead acknowledges this overwhelming use case for the transaction type, and exploits it as an optimization.

### Cheaper storage

Since the storage is guaranteed to be empty, there is no need to read before write. This means only 20,000 gas is needed to pay for the [EIP-2200](/EIPs/EIPS/eip-2200) `SSTORE_SET_GAS` value. This is a small discount to the normal cost of `22,100`, which is `SSTORE_SET_GAS` plus the [EIP-2929](/EIPs/EIPS/eip-2929) `COLD_SLOAD_COST` of `2100`, because no load occurs.

### Intrinsic does not account for contract deployment

This takes advantage of the fact that clients tend to store a single, unique copy of code; no matter the number of deployments. Therefore, the only operation here is changing a pointer in the state trie to the desired code.

Additionally, the EOA already exists because it has enough balance for the migration transaction to be considered valid. Therefore, we don&apos;t need to pay a premium for adding a new account into the state trie.

### Manipulating transaction origin

Many applications have a security check `caller == origin` to verify the caller is an EOA. This is done to &quot;protect&quot; assets. While it is usually more of a bandage than an actual fix, we attempt to placate these projects by modifying the origin of the transaction so the check will continue performing its duty.

### One-time migration

There is no technical reason we couldn&apos;t allow EOAs to change their code at any time with this transaction type. The only inhibitor at the moment is [EIP-3607](/EIPs/EIPS/eip-3607) which will cause migration transactions to be considered invalid if they come from an account with code already deployed. A functional reason for retaining this behavior though is that it makes it simpler to reason about contracts and their upgradability.

## Backwards Compatibility

No backward compatibility issues found.

## Security Considerations

### Blind Signing

As with all sufficiently sophisticated account designs, if a user can be convinced to sign an arbitrary message, that message could be a migration transaction which is owned by a malicious actor instead of the user. This can generally be avoided if wallets treat these transactions with *extreme* care and create as much friction and verification as possible before completing the signature.

### On `ecrecover`

Applications standards such as [ERC-2612: Permit Extension](/EIPs/EIPS/eip-2612) have exploited the cryptographic relationship between EOA addresses and their private keys. Many tokens today support this extension, allowing EOAs to approve the transfer of fund from their account using only a signature. Although collisions between EOAs and contract accounts are considered unlikely and [maybe impossible](/EIPs/EIPS/eip-3607) given today&apos;s computing power, this EIP would make it common place for private keys to exist for contract accounts. There are some considerations here regarding security:

* The obvious attack is a defi protocol deploys some their contract using this EIP and later sign an [ERC-2612](/EIPs/EIPS/eip-2612) message to steal the funds accrued in the contract. This can be avoided by wallets simply not allowing users to interact with protocols deployed in this manner.
* It&apos;s also worth mentioning that there are concerns around how this EIP will affect the cross chain experience. Ultimately a users private key may still have some control over the account&apos;s assets, depending on the exact protocols used on Ethereum and on other chains. It isn&apos;t really possible perfectly migrate the EOA at the same time, on all chains. The best thing that can be done is to educate the user that just because their account has been migrated doesn&apos;t mean that they are safe to now publicly reveal their private key. This seems like a reasonable request, especially since they&apos;ll want to retain the private key in case they want to use the address on any other EVM-like chain.

Something that may alleviate these issues to some degree would be to add an `EXTCODEHASH` check in `ecrecover`. If the recovered account has code, the precompile will revert. This would disallow migrated EOAs from using standards like [ERC-2612](/EIPs/EIPS/eip-2612).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Fri, 21 Jul 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7377</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7377</guid>
      </item>
    
      <item>
        <title>Add time-weighted averaging to the base fee</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/add-time-weighted-averaging-to-the-base-fee-mechanism/15142</comments>
        
        <description>## Abstract

This EIP proposes a new formula to update the base fee, derived from [EIP-1559](/EIPs/EIPS/eip-1559). The existing base fee update formula,

$$b[i+1]\triangleq  b[i] \cdot \left( 1+\frac{1}{8} \cdot \frac{s[i]-s^* }{s^* }\right)$$

only considers the last block size $s[i]$. This mechanism incentivizes proposers to collude with users to manipulate the base fee.

We propose that even previous block sizes be considered by replacing the last block size with an exponential moving average. In particular, we suggest the following base fee update formula:

$$b[i+1]\triangleq  b[i] \cdot \left( 1+\frac{1}{8} \cdot \frac{s_{\textit{avg}}[i]-s^* }{s^* }\right)$$

where $s_{\textit{avg}}[i]$ is defined by:

$$s_{\textit{avg}}[i] \triangleq \alpha\sum_{k=1}^{\infty} (1-\alpha)^k\cdot s[i-k+1]$$ 

and $\alpha\in(0,1)$ is a smoothing factor.

## Motivation

To reduce bribe motivation when the demand for blockspace is high (see Incentive Considerations section) and to reduce oscillations, thus, having a more stable fee setting mechanism.

Proposers use a mechanism described in EIP-1559 to determine which messages to include in a block. This mechanism includes a &quot;base fee&quot;: a portion of the transaction fee that is burned. The base fee varies according to the fill rate of blocks. A target block size is defined. If a block exceeds the target size, the base fee increases, and if it is smaller, the base fee lowers.

Research on the subject have revealed issues with this transaction fee mechanism. It has been shown to be [unstable in cases](/EIPs/assets/eip-7378/LMRSP.pdf). Moreover, it has been shown that the dynamic nature of the base fee, which is influenced by the fill rate of blocks, opens the door for [manipulation by miners (proposers) and users](/EIPs/assets/eip-7378/AGHH.pdf). The desired behavior of the system under a stable high demand, is for it to reach an equilibrium where the base fee -- $b$ -- is the significant part of the gas fee, and the tip is relatively small -- denoted $\varepsilon$ (for reference, Ethereum&apos;s base fee often has $\frac{b}{\varepsilon}\approx 20$). According to [Roughgarden](/EIPs/assets/eip-7378/TR1559.pdf) this is a rational equilibrium under the assumption that proposers do not think ahead. However, we expect a proposer to optimize its behavior by also considering its future payoffs. In essence, since neither the proposer nor the user are getting the burnt fee, by colluding they can both tap into the burnt fee for a win-win situation for them both.

A [theoretical work](/EIPs/assets/eip-7378/AGHH.pdf) describes how both proposers and users can initiate such an attack. For example, we can imagine that users who wish to pay lower costs will coordinate the attack. Roughly, a user (or group of users) that has transactions with a total $g$ amount of gas bribes the proposer of the current block (no matter the proposer&apos;s power) to propose an empty block instead. The cost of such a bribe is only $\varepsilon \times {s^* }$ -- the tip times the target block size. Consequently, the base fee reduces in the next block. If we accept that EIP-1559 reaches its goals, e.g., users would typically use a simple and honest bidding strategy of reporting their maximal willingness to pay plus adding a small tip ($\varepsilon$), then in the honest users&apos; steady state, gas proposals leave the proposers with an $\varepsilon$ tip. Given that other users are naive (or slow to react), our bribing user will include its transactions with any tip larger than $\varepsilon$ -- making the attack profitable whenever $g \frac{b^* }{8} &gt;s^* \varepsilon$.


## Specification

$s[i]$ is replaced by $s_{\textit{avg}}[i]$, where:

$$s_{\textit{avg}}[i] \triangleq \alpha\sum_{k=1}^{\infty} (1-\alpha)^k\cdot s[i-k+1]$$ 

which simplifies to the recursive form

$$s_{\textit{avg}}[i] = \alpha\cdot s[i] + (1-\alpha)\cdot s_{\textit{avg}}[i-1]$$

where $\alpha\in(0, 1)$ is the smoothing factor. A higher smoothing factor means that the average responds more quickly to changes in block size (e.g., if $\alpha = 1$ the proposed formula degenerates to the existing rule).

## Rationale

An intuitive option for the Transaction Fee Mechanism (TFM) that adjusts supply and demand economically is *First price auction*, which is well known and studied. Nevertheless, the Ethereum network choice was to use EIP-1559 for the TFM (one stated reason was to try and simplify the fee estimation for users, and reduce the advantage of sophisticated users). In this proposal, our design goal is to improve the TFM (of EIP-1559) by mitigating known problems that it raises. It is important to note that these problems severity are in direct relation to the demand for block space, and currently only mildly impact the Ethereum network. If demand to use Ethereum increases, however, these problems are expected to exacerbate. We may want to prepare for this beforehand.

The change is based on [this work](/EIPs/assets/eip-7378/AGHH.pdf) that described a rational strategy in which bribes are profitable. Choosing to average based on a geometric series weights results in two desired properties: (i) the computation and space complexity are both in O(1), and (ii) the average gradually phases out the impact of a single outlier block without causing significant future fluctuations in the base fee.
Moreover, the theoretical analysis does not consider the income from classic MEV strategies. (Actually, the described strategy may be seen as another form of MEV.) The fact that classic MEV (sandwich, front running, etc.) are not included in the analysis, means that the proposed solutions to classic MEV (obscuring transactions etc.) will also not help against the described strategy. The problem that we tackle in this EIP is at the core of the base fee mechanism, with no further assumptions (such as MEV or predictability of randomness).

Remark: An additional alternative strategy that is not fully discussed [here](/EIPs/assets/eip-7378/AGHH.pdf) but one may consider is to reduce the &apos;max change denominator&apos; (the learning rate) from 1/8 to something smaller. However, this is problematic since it significantly affects the responsiveness of the base fee, making it slow to respond to actual persistent changes. The reason for using geometric series weights is precisely to achieve the favorable tradeoff of still responding quickly while mitigating incentive misalignments.

### Incentive Considerations

The proposal is designed to improve the incentive compatibility of the TFM. A [game theoretic analysis](/EIPs/assets/eip-7378/AGHH.pdf) shows that the current TFM, which is based on EIP-1559, encourages bribes. 

One of the main goals of EIP-1559 was to simplify the bidding for users. It was articulated [theoretically by Roughgarden](/EIPs/assets/eip-7378/TR1559.pdf) as users bidding their honest valuations being an optimal strategy. In contrast, when using first price auctions for the TFM (as done by Bitcoin and previously in Ethereum), it is typically sub-optimal for a user to bid its honest valuation. In other words, a TFM that encourages users to not fully reveal their preferences is considered less good. However, one may argue that a TFM that encourages bribes is worse than a TFM that encourages not revealing one&apos;s full preferences.

Although a first price auction is a safe bet regarding TFMs, the Ethereum network chose to use EIP-1559 and burn transaction fees (perhaps for reasons other than game-theoretic ones). We therefore suggest to mitigate the current incentives for bribes using the above proposal.

## Backwards Compatibility

This change requires a hard fork since the base fee is enforced (for blocks to be considered valid).

## Test Cases

TBD

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 22 Jul 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7378</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7378</guid>
      </item>
    
      <item>
        <title>Vanilla Options for ERC-20 Tokens</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7390-vanilla-option-standard/15206</comments>
        
        <description>## Abstract

This standard defines a comprehensive set of functions and events facilitating seamless interactions (creation, management, exercising, etc.) for vanilla options.

Vanilla options grant the right, without obligation, to buy or sell an asset at a set price within a specified timeframe.

This standard doesn&apos;t represent a simple option that would be useless after the expiration date. Instead, it can store as many issuance as needed. Each issuance is identified by an id, and can be bought, exercised, cancelled, etc., independently of the other issuances.\
Every issuance is collateralized, meaning that the writer has to provide the collateral to the contract before the buyer can buy the option. The writer can retrieve the collateral if the buyer hasn&apos;t exercised in the exercise window.\
A buyer can decide to buy only a fraction of the issuance (meaning multiple buyers is possible), and will receive accordingly tokens ([ERC-1155](/EIPs/EIPS/eip-1155)) that represent the fraction of the issuance. From now, we will call these tokens *redeem tokens*. These tokens can be exchanged between users, and are used for exercising the option. With this mechanism, a buyer can decide to exercise only a fraction of what he bought.\
Also, the writer can decide to cancel the issuance if no option has been bought yet. He also has the right to update the premium price at any time. This doesn&apos;t affect the already bought options.\
The underlying token, strike token and premium token are [ERC-20](/EIPs/EIPS/eip-20) tokens.

In the following, the plural term option**s** will sometimes be used. This can refer to the amount of redeem tokens a buyer purchased and can exercise.

## Motivation

Options are widely used financial instruments, and have a true usefulness for investors and traders. It offers versatile risk management tools and speculative opportunities.\
In the decentralized finance, many options-selling platform emerged, but each of these protocols implements their own definition of an option. This leads to incompatibilities, which is a pity because options should be interoperable like fungible/non-fungible tokens are.\
By introducing a standard interface for vanilla options contracts, we aim to foster a more inclusive and interoperable derivatives ecosystem. This standard will enhance the user experience and facilitate the development of decentralized options platforms, enabling users to seamlessly trade options across different applications. Moreover, this standard is designed to represent vanilla options, which are the most common type of options. This standard can be used as a base for more complex options, such as exotic options.

## Specification

Implementations of this proposal MUST also implement ERC-1155 to give the possibility to buy only a fraction of the issuance.

### Interface

```solidity
interface IERC7390 {
    enum Side {
        Call,
        Put
    }

    struct VanillaOptionData {
        Side side;
        address underlyingToken;
        uint256 amount;
        address strikeToken;
        uint256 strike;
        address premiumToken;
        uint256 premium;
        uint256 exerciseWindowStart;
        uint256 exerciseWindowEnd;
        address[] allowed;
    }

    struct OptionIssuance {
        VanillaOptionData data;
        address writer;
        uint256 exercisedAmount;
        uint256 soldAmount;
    }

    error Forbidden();
    error TransferFailed();
    error TimeForbidden();
    error AmountForbidden();
    error InsufficientBalance();

    event Created(uint256 indexed id);
    event Bought(uint256 indexed id, uint256 amount, address indexed buyer);
    event Exercised(uint256 indexed id, uint256 amount);
    event Expired(uint256 indexed id);
    event Canceled(uint256 indexed id);
    event PremiumUpdated(uint256 indexed id, uint256 amount);
    event AllowedUpdated(uint256 indexed id, address[] allowed);

    function create(VanillaOptionData calldata optionData) external returns (uint256);

    function buy(uint256 id, uint256 amount) external;

    function exercise(uint256 id, uint256 amount) external;

    function retrieveExpiredTokens(uint256 id, address receiver) external;

    function cancel(uint256 id, address receiver) external;

    function updatePremium(uint256 id, uint256 amount) external;

    function updateAllowed(uint256 id, address[] memory allowed) external;

    function issuance(uint256 id) external view returns (OptionIssuance memory);
}
```

### State Variable Descriptions

At creation time, user must provide filled instance of `VanillaOptionData` structure that contains all the key information for initializing the option issuance.

#### `side`

**Type: `enum`**

Side of the option. Can take the value `Call` or `Put`. `Call` option gives the option buyer right to exercise any acquired option tokens to buy the `underlying` token at given `strike` price using `strikeToken` from option writer. Similarly, `Put` option gives the option buyer right to sell the `underlying` token to the option writer at `strike` price.

#### `underlyingToken`

**Type: `address` ([ERC-20](/EIPs/EIPS/eip-20) contract)**

Underlying token.

#### `amount`

**Type: `uint256`**

Maximum amount of the underlying tokens that can be exercised.

&gt; Be aware of token decimals!

#### `strikeToken`

**Type: `address` (ERC-20 contract)**

Token used as a reference to determine the strike price.

#### `strike`

**Type: `uint256`**

Strike price. The option buyer MAY be able to exercise only fraction of the issuance and the paid strike price must be adjusted by the contract to reflect it.

Note that `strike` is meant to represent the price in `strikeToken` for a single `underlyingToken`.

&gt; Be aware of token decimals!

#### `premiumToken`

**Type: `address` (ERC-20 contract)**

Premium token.

#### `premium`

**Type: `uint256`**

Premium price is the price that option buyer has to pay to option writer to compensate for the risk that the writer takes for issuing the option. Option premium changes depending on various factors, most important ones being the volatility of the underlying token, strike price and the time left for exercising the option.

**Note that the premium price is set for exercising the total `amount` of the issuance. The buyer MAY be able to buy only fraction of the option tokens and the paid premium price must be adjusted by the contract to reflect it.**

&gt; Be aware of token decimals!

#### `exerciseWindowStart`

**Type: `uint256`**\
**Format: *timestamp as seconds since unix epoch***

Option exercising window start time. When current time is greater or equal to `exerciseWindowStart` and below or equal to `exerciseWindowEnd`, owner of option(s) can exercise them.

#### `exerciseWindowEnd`

**Type: `uint256`**\
**Format: *timestamp as seconds since unix epoch***

Option exercising window end time. When current time is greater or equal to `exerciseWindowStart` and below or equal to `exerciseWindowEnd`, owner of option(s) can exercise them. When current time is greater than `exerciseWindowEnd`, buyers can&apos;t exercise and writer can retrieve remaining underlying (call) or strike (put) tokens.

#### `allowed`

**Type: `address[]`**

Addresses that are allowed to buy the issuance. If the array is empty, all addresses are allowed to buy the issuance.

`VanillaOptionData` is stored in the `OptionIssuance` struct, which is used to store the option issuance data. It contains other information.

#### `writer`

**Type: `address`**

Address of the writer meaning the address that created the option.

#### `exercisedAmount`

**Type: `uint256`**

Amount of underlying tokens that have been exercised.

#### `soldAmount`

**Type: `uint256`**

Amount of underlying tokens that have been bought for this issuance.

#### `transferredExerciseCost`

**Type: `uint256`**

Amount of `strikeToken` tokens that have been transferred to the writer (call) or buyers (put) of the option issuance.\
This is an utility variable used to not always have to calculate the total exercise cost transferred. It&apos;s updated at the same time `exercisedAmount` is updated. The calculation is `(amount * selectedIssuance.data.strike) / (10**underlyingToken.decimals())`.

#### `exerciseCost`

**Type: `uint256`**

Exercise cost. It represents the collateral the writer has to deposit to the contract (put), or the amount of `strikeToken` tokens a writer can receive if all buyers decide to exercise (call).\
This is an utility variable used to not always have to calculate the exercise cost. We compute it at the creation of the option. The calculation is `(strike * amount) / (10 ** underlyingToken.decimals())`.

### Function Descriptions

#### `constructor`

No constructor is needed for this standard, but the contract MUST implement the ERC-1155 interface. So, the contract MUST call the ERC-1155 constructor.

#### `create`

```solidity
function create(VanillaOptionData calldata optionData) external returns (uint256);
```

Option writer creates new option tokens and defines the option parameters using `create()`. As an argument, option writer needs to fill `VanillaOptionData` data structure instance and pass it to the method. As a part of creating the option tokens, the function transfers the collateral from option writer to the contract.

It is highly preferred that as a part of calling `create()` the option issuance becomes fully collateralized to prevent increased counterparty risk. For creating a call (put) option issuance, writer needs to allow the amount of `amount` (`strike`) tokens of `underlyingToken` (`strikeToken`) to be transferred to the option contract before calling `create()`.

Note that this standard does not define functionality for option writer to &quot;re-up&quot; the collateral in case the option contract allows under-collateralization. The contract needs to then adjust its API and implementation accordingly.

MUST revert if `underlyingToken` or `strikeToken` is the zero address.\
MUST revert if `premium` is not 0 and `premiumToken` is the zero address.\
MUST revert if `amount` or `strike` is 0.\
MUST revert if `exerciseWindowStart` is less than the current time or if `exerciseWindowEnd` is less than `exerciseWindowStart`.

*Returns an id value that refers to the created option issuance in option contract if option issuance was successful.*
*Emits `Created` event if option issuance was successful.*

#### `buy`

```solidity
function buy(uint256 id, uint256 amount) external;
```

Allows the buyer to buy `amount` of option tokens from option issuance with the defined `id`.

The buyer has to allow the token contract to transfer the (fraction of total) `premium` in the specified `premiumToken` to option writer. During the call of the function, the premium is be directly transferred to the writer.

If `allowed` array is not empty, the buyer&apos;s address MUST be included in this list.\
MUST revert if `amount` is 0 or greater than the remaining options available for purchase.\
MUST revert if the current time is greater than `exerciseWindowEnd`.

*Mints `amount` redeem tokens to the buyer&apos;s address if buying was successful.*
*Emits `Bought` event if buying was successful.*

#### `exercise`

```solidity
function exercise(uint256 id, uint256 amount) external;
```

Allows the buyer to exercise `amount` of option tokens from option issuance with the defined `id`.

- If the option is a call, buyer pays writer at the specified strike price and gets the specified underlying tokens.
- If the option is a put, buyer transfers to writer the underlying tokens and gets paid at the specified strike price.

The buyer has to allow the spend of either `strikeToken` or `underlyingToken` before calling `exercise()`.

Exercise MUST only take place when `exerciseWindowStart` &lt;= current time &lt;= `exerciseWindowEnd`.\
MUST revert if `amount` is 0 or buyer hasn&apos;t the necessary redeem tokens to exercise the option.

*Burns `amount` redeem tokens from the buyer&apos;s address if the exercising was successful.*
*Emits `Exercised` event if the option exercising was successful.*

#### `retrieveExpiredTokens`

```solidity
function retrieveExpiredTokens(uint256 id, address receiver) external;
```

Allows writer to retrieve the collateral tokens that were not exercised. These tokens are transferred to `receiver`.\
If the option is a call, `receiver` retrieves the underlying tokens. If the option is a put, `receiver` retrieves the strike tokens.

MUST revert if the address calling the function is not the writer of the option issuance.\
MUST revert if `exerciseWindowEnd` is greater or equals than the current time.\
If equals to the zero address, MUST set `receiver` to caller&apos;s address.

*Transfers the un-exercised collateral to the writer&apos;s address.*
*MAY delete the option issuance from the contract if the retrieval was successful.*
*Emits `Expired` event if the retrieval was successful.*

#### `cancel`

```solidity
function cancel(uint256 id, address receiver) external;
```

Allows writer to cancel the option and retrieve tokens used as collateral. These tokens are transferred to `receiver`.\
If the option is a call, `receiver` retrieves the underlying tokens. If the option is a put, `receiver` retrieves the strike tokens.

MUST revert if the address calling the function is not the writer of the option issuance.\
MUST revert if at least one option&apos;s fraction has been bought.\
If equals to the zero address, MUST set `receiver` to caller&apos;s address.

*Transfers the un-exercised collateral to the writer&apos;s address.*
*MAY delete the option issuance from the contract if the cancelation was successful.*
*Emits `Canceled` event if the cancelation was successful.*

#### `updatePremium`

```solidity
function updatePremium(uint256 id, uint256 amount) external;
```

Allows the writer to update the premium that buyers will need to provide for buying the options.

**Note that the `amount` will be for the whole underlying amount, not only for the options that might still be available for purchase.**

MUST revert if the address calling the function is not the writer of the option issuance.\
MUST revert if the current time is greater than `exerciseWindowEnd`.

*Emits `PremiumUpdated` event when the function call was handled successfully.*

#### `updateAllowed`

```solidity
function updateAllowed(uint256 id, address[] memory allowed) external;
```

Allows the writer to update the list of allowed addresses that can buy the option issuance.\
If a buyer already bought an option and his address is not in the new list, he will still be able to exercise his purchased options.

MUST revert if the address calling the function is not the writer of the option issuance.\
MUST revert if the current time is greater than `exerciseWindowEnd`.

*Emits `AllowedUpdated` event when the function call was handled successfully.*

#### `issuance`

```solidity
function issuance(uint256 id) external view returns (OptionIssuance memory);
```

Returns all the key information for the option issuance with the given `id`.

### Events

#### `Created`

```solidity
event Created(uint256 id);
```

Emitted when the writer has provided option issuance data successfully (and locked down the collateral to the contract). The given `id` identifies the particular option issuance.

#### `Bought`

```solidity
event Bought(uint256 indexed id, uint256 amount, address indexed buyer);
```

Emitted when options have been bought. Provides information about the option issuance `id`, the address of `buyer` and the `amount` of options bought.

#### `Exercised`

```solidity
event Exercised(uint256 indexed id, uint256 amount);
```

Emitted when the option has been exercised from the option issuance with given `id` and the given `amount`.

#### `Expired`

```solidity
event Expired(uint256 indexed id);
```

Emitted when the writer of the option issuance with `id` has retrieved the un-exercised collateral.

#### `Canceled`

```solidity
event Canceled(uint256 indexed id);
```

Emitted when the option issuance with given `id` has been cancelled by the writer.

#### `PremiumUpdated`

```solidity
event PremiumUpdated(uint256 indexed id, uint256 amount);
```

Emitted when writer updates the premium to `amount` for option issuance with given `id`. Note that the updated premium is for the total issuance.

#### `AllowedUpdated`

```solidity
event AllowedUpdated(uint256 indexed id, address[] allowed);
```

Emitted when writer updates the list of allowed addresses for option issuance with given `id`.

### Errors

#### `Forbidden`

Reverts when the caller is not allowed to perform some actions (general purpose).

#### `TransferFailed`

Reverts when the transfer of tokens failed.

#### `TimeForbidden`

Reverts when the current time of the execution is invalid.

#### `AmountForbidden`

Reverts when the amount is invalid.

#### `InsufficientBalance`

Reverts when the caller has insufficient balance to perform the action.

### Concrete Examples

#### Call Option

Let&apos;s say Bob sells a **call** option.\
He gives the right to anyone to buy **8 TokenA** at **25 TokenB** each between **14th of July 2023** and **16th of July 2023 (at midnight)**.\
For such a contract, he wants to receive a premium of **10 TokenC**.

Before creating the option, Bob has to transfer the collateral to the contract. This collateral corresponds to the tokens he will have to give if the option if fully exercised (`amount`). For this option, he has to give as collateral 8 TokenA. He does that by calling the function `approve(address spender, uint256 amount)` on the TokenA&apos;s contract and as parameters the contract&apos;s address (`spender`) and for `amount`: **8 \* 10^(TokenA&apos;s decimals)**. Then Bob can execute `create()` on the contract for issuing the option, giving the following parameters:

- `side`: **Call**
- `underlyingToken`: **TokenA&apos;s address**
- `amount`: **8 \* 10^(TokenA&apos;s decimals)**
- `strikeToken`: **TokenB&apos;s address**
- `strike`: **25 \* 10^(TokenB&apos;s decimals)**
- `premiumToken`: **TokenC&apos;s address**
- `premium`: **10 \* 10^(TokenC&apos;s decimals)**
- `exerciseWindowStart`: **1689292800** *(2023-07-14 timestamp)*
- `exerciseWindowEnd`: **1689465600** *(2023-07-16 timestamp)*
- `allowed`: `[]` (open to anyone)

The issuance has ID 88.

Alice wants to be able to buy only **4** TokenA. She will first have to pay the premium (that is proportional to its share) by allowing the spending of his 10 TokenC by calling `approve(address spender, uint256 amount)` on the TokenC&apos;s contract and give as parameters the contract&apos;s address (`spender`) and for `amount`: **4\*10^(TokenA&apos;s decimals) \* 10\*10^(TokenC&apos;s decimals) / 8\*10^(TokenA&apos;s decimals)** (amountToBuy \* `premium` / `amount`). She can then execute `buy(88, 4 * 10^(TokenA&apos;s decimals))` on the contract, and will receive 4\*10^(TokenA&apos;s decimals) redeem tokens.

John, for his part, wants to buy **2** TokenA. He does the same thing and receives **2\*10^(TokensA&apos;s decimals)** redeem tokens.

We&apos;re on the 15th of July and Alice wants to exercise his option because 1 TokenA is traded at 50 TokenB! She needs to allow the contract to transfer **4\*10^(TokenA&apos;s decimals) \* 25\*10^(TokenB&apos;s decimals) / 10^(TokenA&apos;s decimals)** (amountToExercise \* `strike` / 10^(`TokenA`&apos;s decimals)) TokenBs from her account to be able to exercise. When she calls `exercise(88, 4 * 10^(TokenA&apos;s decimals))` on the contract, it will transfer 4 TokenA to Alice, and 4\*25 TokenB to Bob.

John decided to give his right to exercise to his friend Jimmy. He did that simply by transferring his **2\*10^(TokensA&apos;s decimals)** redeem tokens to Jimmy&apos;s address.\
Jimmy decides to only buy **1** TokenA with the option. So he will give to Bob (through the contract) **1\*10^(TokenA&apos;s decimals) \* 25\*10^(TokenB&apos;s decimals) / 10^(TokenA&apos;s decimals)**.

#### Put Option

Let&apos;s say Bob sells a **put** option.\
He gives the right to anyone to sell to him **8 TokenA** at **25 TokenB** each between **14th of July 2023** and **16th of July 2023 (at midnight)**.\
For such a contract, he wants to receive a premium of **10 TokenC**.

Before creating the option, Bob has to transfer the collateral to the contract. This collateral corresponds to the tokens he will have to give if the option if fully exercised (`exerciseCost`). For this option, he has to give as collateral 200 TokenB (8 \* 25). He does that by calling the function `approve(address spender, uint256 amount)` on the TokenB&apos;s contract and as parameters the contract&apos;s address (`spender`) and for `amount`: **25\*10^(Token B&apos;s decimals) \* 8\*10^(TokenB&apos;s decimals) / 10^(TokenA&apos;s decimals)** (`strike` \* `amount` / 10^(`underlyingToken`&apos;s decimals)). Then Bob can execute `create()` on the contract for issuing the option, giving the following parameters:

- `side`: **Put**
- `underlyingToken`: **TokenA&apos;s address**
- `amount`: **8 \* 10^(TokenA&apos;s decimals)**
- `strikeToken`: **TokenB&apos;s address**
- `strike`: **25 \* 10^(TokenB&apos;s decimals)**
- `premiumToken`: **TokenC&apos;s address**
- `premium`: **10 \* 10^(TokenC&apos;s decimals)**
- `exerciseWindowStart`: **1689292800** *(2023-07-14 timestamp)*
- `exerciseWindowEnd`: **1689465600** *(2023-07-16 timestamp)*
- `allowed`: `[]` (open to anyone)

The issuance has ID 88.

Alice wants to be able to sell only **4** TokenA. She will first have to pay the premium (that is proportional to its share) by allowing the spending of his 10 TokenC by calling `approve(address spender, uint256 amount)` on the TokenC&apos;s contract and give as parameters the contract&apos;s address (`spender`) and for `amount`: **4\*10^(TokenA&apos;s decimals) \* 10\*10^(TokenC&apos;s decimals) / 8\*10^(TokenA&apos;s decimals)** (amountToSell \* `premium` / `amount`). She can then execute `buy(88, 4 * 10^(TokenA&apos;s decimals))` on the contract, and will receive 4\*10^(TokenA&apos;s decimals) redeem tokens.

John, for his part, wants to sell **2** TokenA. He does the same thing and receives **2\*10^(TokensA&apos;s decimals)** redeem tokens.

We&apos;re on the 15th of July and Alice wants to exercise his option because 1 TokenA is traded at only 10 TokenB! She needs to allow the contract to transfer **4 \* 10^(TokenA&apos;s decimals)** TokenAs from her account to be able to exercise. When she calls `exercise(88, 4 * 10^(TokenA&apos;s decimals))` on the contract, it will transfer 4\*25 TokenB to Alice and 4 TokenA to Bob.

John decided to give his right to exercise to his friend Jimmy. He did that simply by transferring his **2\*10^(TokensA&apos;s decimals)** redeem tokens to Jimmy&apos;s address.\
Jimmy decides to only sell **1** TokenA with the option. So he will give to Bob (through the contract) **1\*10^(TokenA&apos;s decimals)**.

#### Retrieve collateral

Let&apos;s say Alice never exercised his option because it wasn&apos;t profitable enough for her. To retrieve his collateral, Bob would have to wait for the current time to be greater than `exerciseWindowEnd`. In the examples, this characteristic is set to 2 days, so he would be able to get back his collateral from the 16th of July by simply calling `retrieveExpiredTokens()`.

## Rationale

This contract&apos;s concept is oracle-free, because we assume that a rational buyer will exercise his option only if it&apos;s profitable for him.

The premium is to be determined by the option writer. writer is free to choose how to calculate the premium, e.g. by using *Black-Scholes model* or something else. writer can update the premium price at will in order to adjust it according to changes on the underlying&apos;s price, volatility, time to option expiry and other such factors. Computing the premium off-chain is better for gas costs purposes.

This ERC is intended to represent vanilla options. However, exotic options can be built on top of this ERC.\
Instead of representing a single option that would be useless after the expiration date, this contract can store as many issuances as needed. Each issuance is identified by an id, and can be bought, exercised, cancelled, etc., independently of the other issuances. This is a better approach for gas costs purposes.

It&apos;s designed so that the option can be either European or American, by introduction of the `exerciseWindowStart` and `exerciseWindowEnd` data points. A buyer can only exercise between `exerciseWindowStart` and `exerciseWindowEnd`.

- If the option writer considers the option to be European, he can set the `exerciseWindowStart` in line with the expiration date, and `exerciseWindowEnd` to the expiration date + a determined time range so that buyers have a period of time to exercise.
- If the option writer considers the option to be American, he can set the `exerciseWindowStart` to the current time, and the buyer will be able to exercise the option immediately.

The contract inherently supports multiple buyers for a single option issuance. This is achieved by using ERC-1155 tokens for representing the options. When a buyer buys a fraction of the option issuance, he receives ERC-1155 tokens that represent the fraction of the option issuance. These tokens can be exchanged between users, and are used for exercising the option. With this mechanism, a buyer can decide to exercise only a fraction of what he bought.

The contract implements `allowed` array, which can be used to restrict the addresses that can buy the option issuance. This can be useful if two users agreed for an option off-chain and they want to create it on-chain. This prevents the risk that between the creation of the contract and the purchase by the second user, an on-chain user has already bought the contract.

This ERC is designed to handle ERC-20 tokens. However, this standard can be used as a good base for handling other types of tokens, such as [ERC-721](/EIPs/EIPS/eip-721) tokens. Some attributes and functions signatures (to provide an id instead of an amount for instance) would have to be changed, but the general idea would remain the same.

## Security Considerations

Contract contains `exerciseWindowStart` and `exerciseWindowEnd` data points. These define the determined time range for the buyer to exercise options. When the current time is greater than `exerciseWindowEnd`, the buyer won&apos;t be able to exercise and the writer will be able to retrieve any remaining collateral.

For preventing clear arbitrage cases when option writer considers the issuance to be of European options, we would strongly advice the option writer to call `updatePremium` to considerably increase the premium price when exercise window opens. This will make sure that the bots won&apos;t be able to buy any remaining options and immediately exercise them for quick profit. Of course, this standard can be customized and maybe users will find more convenient to update the premium automatically using available tools, instead of doing it manually (especially if the premium is based on specific dynamic metrics like the *Black-Scholes model*). If the option issuance is considered to be American, such adjustment is of course not needed.

This standard implements the `updatePremium` function, which allows the writer to update the premium price at any time. This function can lead to security issues for the buyer: a buyer could buy an option, and the writer could front-run buyer&apos;s transaction by updating the premium price to a very high value. To prevent this, we advise the buyer to only allow for the agreed amount of premium to be spent by the contract, not more.

The contract supports multiple buyers for a single option issuance, meaning fractions of the option issuance can be bought. The ecosystem doesn&apos;t really support non-integers, so fractions can sometimes lead to rounding errors. This can lead to unexpected results, especially in the `buy` function: if the premium is set, the buyer has to pay for only a fraction proportional to the amount of options he wants to buy. If that fraction is not an integer, this will truncate and therefore round to floor. This means that writer will receive less than the expected premium. We consider this risk pretty negligible given that most tokens have a high number of decimals, but it&apos;s important to be aware of it. Some buyer could exploit this by buying repeatedly small fraction, and therefore paying less than the expected premium. However, this probably wouldn&apos;t be profitable given the gas costs.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 02 Sep 2022 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7390</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7390</guid>
      </item>
    
      <item>
        <title>⚡ Flash Loans ⚡</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc7400-flash-loans/15211</comments>
        
        <description>## Abstract

A flash loan is a loan between lender and borrower smart contracts that must be repaid, plus an optional fee, before the end of the transaction. This ERC specifies interfaces for lenders to accept flash loan requests, and for borrowers to take temporary control of the transaction within the lender execution. The process for the safe execution of flash loans is also specified.

## Motivation

The current state of the flash loan ecosystem is fragmented and lacks standardization, leading to several challenges for both lenders and borrowers. The absence of a common interface results in increased integration efforts, as each flash loan provider implements its own unique approach. This lack of standardization is expected to become more problematic as the ecosystem grows, requiring more resources to maintain compatibility.

A comprehensive analysis of the existing flash loan protocols reveals significant differences in their implementations, including:

- Inconsistent syntax for initiating flash loans across different platforms.
- Variations in the relationship between the loan receiver and the callback receiver, with some protocols allowing different addresses for each role while others do not.
- Divergent repayment mechanisms, with some lenders pulling the principal and fee from the loan receiver and others requiring the loan receiver to manually return the funds.
- Disparities in the treatment of flash minting, where some lenders allow the creation of any amount of their native asset without charging a fee, effectively permitting flash loans bounded by computational constraints rather than asset ownership limitations.

To address these inconsistencies and promote a more efficient and accessible flash loan ecosystem, this ERC specifies a standardized interface that encompasses the maximum flexibility required by both lenders and borrowers. By consolidating the various approaches into a unified standard, this proposal aims to streamline the integration process, enabling borrowers to seamlessly switch between flash lenders without the need for code modifications.

## Specification

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

Under this standard a flash loan is a loan of an `amount` of an [ERC-20](/EIPs/EIPS/eip-20) `asset` from a `lender`. This loan can remain open for the span of a single `flash` call in the `lender`.

This `amount` plus a `fee` defined by the `lender` in the same `asset` must be repaid before the end of `flash` call at a _repayment receiver_ address defined by the `lender`.

The `flash` function is called by the `initiator`, who defines the _loan receiver_, the _callback receiver_, the _callback function_, the `asset` and the `amount`.

When the `initiator` calls `flash` in a `lender`. The `lender` will then transfer the `amount` of `asset` to the _loan receiver_.

The `lender`, after transferring `amount` of `asset` to the _loan receiver_, will execute the _callback function_ on the _callback receiver_. The `lender` will include in this _callback function_ call a number of parameters related to the loan as defined in this standard.

The `amount` and `fee` need to be transferred to a `repayment receiver` before the end of the `flash` call. The `fee` can be set to zero `asset`.

The _callback function_ can return any arbitrary data which will be received by the `initiator` as the return value of the `flash` call.

The lender decides which `assets` to support. The lender can decide to support all possible assets.

### Lender Specification

A `lender` MUST implement the [ERC-7399](/EIPs/EIPS/eip-7399) interface.

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity &gt;=0.6.0 &lt;0.9.0;

import { IERC20 } from &quot;./IERC20.sol&quot;;

interface IERC7399 {
    /// @dev The amount of currency available to be lent.
    /// @param asset The loan currency.
    /// @return The amount of `asset` that can be borrowed.
    function maxFlashLoan(
        address asset
    ) external view returns (uint256);

    /// @dev The fee to be charged for a given loan. Returns type(uint256).max if the loan is not possible.
    /// @param asset The loan currency.
    /// @param amount The amount of assets lent.
    /// @return The amount of `asset` to be charged for the loan, on top of the returned principal.
    function flashFee(
        IERC20 asset,
        uint256 amount
    ) external view returns (uint256);

    /// @dev Initiate a flash loan.
    /// @param loanReceiver The address receiving the flash loan
    /// @param asset The asset to be loaned
    /// @param amount The amount to loaned
    /// @param data The ABI encoded user data
    /// @param callback The address and signature of the callback function
    /// @return result ABI encoded result of the callback
    function flash(
        address loanReceiver,
        ERC20 asset,
        uint256 amount,
        bytes calldata data,
        /// @dev callback. This is a combination of the callback receiver address, and the signature of callback
        /// function. It is encoded packed as 20 bytes + 4 bytes.
        /// @dev the return of the callback function is not encoded in the parameter, but must be `returns (bytes
        /// memory)` for compliance with the standard.
        /// @param initiator The address that called this function
        /// @param paymentReceiver The address that needs to receive the amount plus fee at the end of the callback
        /// @param asset The asset to be loaned
        /// @param amount The amount to loaned
        /// @param fee The fee to be paid
        /// @param data The ABI encoded data to be passed to the callback
        /// @return result ABI encoded result of the callback
        function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory) callback
    )
        external
        returns (bytes memory);
}

```

The `maxFlashLoan` function MUST return the maximum available loan for `asset`. The `maxFlashLoan` function MUST NOT revert. If no flash loans for the specified `asset` are possible, the value returned MUST be zero.

The `flashFee` function MUST return the fee charged for a loan of `amount` `asset`. The `flashFee` function MUST NOT revert. If a flash loan for the specified `asset` and `amount` is not possible, the value returned MUST be `type(uint256).max`.

The `flash` function MUST execute the callback passed on as an argument.

```solidity
bytes memory result = callback(msg.sender, address(this), asset, amount, _fee, data);
```

The `flash` function MUST transfer `amount` of `asset` to _loan receiver_ before executing the callback.

The `flash` function MUST include `msg.sender` as the `initiator` in the callback.

The `flash` function MUST NOT modify the `asset`, `amount` and `data` parameter received, and MUST pass them on to the callback.

The `flash` function MUST include a `fee` argument in the callback with the fee to pay for the loan on top of the principal, ensuring that `fee == flashFee(asset, amount)`.

Before the end of the callback, the `asset` balance of `payment receiver` MUST have increased by `amount + fee` from the amount at the beginning of the callback, or revert if this is not true.

The return of the `flash` function MUST be the same as the return from the callback.

### Receiver Specification

A _callback receiver_ of flash loans MUST implement one or more external functions with the following arguments and return value:

```solidity
/// @dev This function can have any name and be overloaded.
/// @param initiator The address that called this function
/// @param paymentReceiver The address that needs to receive the amount plus fee at the end of the callback
/// @param asset The asset to be loaned
/// @param amount The amount to loaned
/// @param fee The fee to be paid
/// @param data The ABI encoded data to be passed to the callback
/// @return result ABI encoded result of the callback
function(address, address, IERC20, uint256, uint256, bytes memory) external returns (bytes memory) callback;
```

## Rationale

The interfaces described in this ERC have been chosen as to cover the known flash lending use cases, while allowing for safe and gas efficient implementations.

`maxFlashLoan` and `flashFee` return numerical values on impossible loans to allow sorting lenders without having to deal with reverts.

`maxFlashLoan` returns a value that is consistent with an impossible loan when the `lender` is not able to serve the loan.

`flashFee` returns a value that is consistent with an impossible loan when the `lender` is not able to serve the loan.

`flash` has been chosen as a function name as a verb which is descriptive enough, unlikely to clash with other functions in the `lender`, and including both the use cases in which the assets lent are held or minted by the `lender`.

Existing flash lenders all provide flash loans of several asset types from the same contract. Providing a `asset` parameter in both the `flash` and callback functions matches closely the observed functionality.

A `bytes calldata data` parameter is included for the `initiator` to pass arbitrary information to the `receiver`. The `receiver` can pass arbitrary information back to the `initiator` using the `bytes memory` return value.

A `initiator` will often be required in the callback function, which the `lender` knows as `msg.sender`. An alternative implementation which would embed the `initiator` in the `data` parameter by the caller would require an additional mechanism for the receiver to verify its accuracy, and is not advisable.

A _loan receiver_ is taken as a parameter to allow flexibility on the implementation of separate loan initiators, loan receivers, and callback receivers. This parameter is not passed on to the _callback receiver_ on the grounds that it will be often the same as _callback receiver_ and when not, it can be encoded in the `data` by the `initiator`.

A `payment receiver` allows for the same flexibility on repayments as in borrows. Control flow and asset flow are independent.

The `amount` will be required in the callback function, which the `lender` took as a parameter. An alternative implementation which would embed the `amount` in the `data` parameter by the caller would require an additional mechanism for the receiver to verify its accuracy, and is not advisable.

A `fee` will often be calculated in the callback function, which the callback receiver must be aware of for repayment. Passing the `fee` as a parameter instead of appended to `data` is simple and effective.

Arbitrary callback functions on callback receivers allows to implement different behaviours to flash loans on callback receivers without the need for encoding a function router using the `data` argument. A function call type is 24 bytes of which the first 20 bytes are the target address and the last 4 bytes are the function signature.

The `amount + fee` are pushed to the `payment receiver` to allow for the segregation of asset and control flows. While a &quot;pull&quot; architecture is more prevalent, &quot;push&quot; architectures are also common. For those cases where the `lender` can&apos;t implement a &quot;push&quot; architecture, a simple wrapper contract can offer this proposal&apos;s external interface, while using liquidity from the `lender` using a &quot;pull&quot; architecture.

## Backwards Compatibility

This EIP is a successor of [ERC-3156](/EIPs/EIPS/eip-3156). While not directly backwards compatible, a wrapper contract offering this proposal&apos;s external interface with liquidity obtained from an ERC-3156 flash `lender` is trivial to implement.

## Security Considerations

### Verification of callback arguments

The arguments of the flash loan callbacks are expected to reflect the conditions of the flash loan, but cannot be trusted unconditionally. They can be divided in two groups, that require different checks before they can be trusted to be genuine.

1. No arguments can be assumed to be genuine without some kind of verification. `initiator`, `asset` and `amount` refer to a past transaction that might not have happened if the caller of the callback decides to lie. `fee` might be false or calculated incorrectly. `data` might have been manipulated by the caller.
2. To trust that the value of `initiator`, `asset`, `amount` and `fee` are genuine a reasonable pattern is to verify that the callback caller is in a whitelist of verified flash lenders. Since often the caller of `flash` will also be receiving the callback this will be trivial. In all other cases flash lenders will need to be approved if the arguments in the callback are to be trusted.
3. To trust that the value of `data` is genuine, in addition to the check in point 1, it is recommended to verify that the `initiator` belongs to a group of trusted addresses. Trusting the `lender` and the `initiator` is enough to trust that the contents of `data` are genuine.

### Flash lending security considerations

#### Automatic approvals

Any `receiver` that repays the `amount` and `fee` received as arguments needs to include in the callback a mechanism to verify that the initiator and `lender` are trusted.

Alternatively, the callback receiver can implement permissioned functions that set state variables indicating that a flash loan has been initiated and what to expect as `amount` and `fee`.

Alternatively, the callback receiver can verify that `amount` was received by the `loanReceiver` and use its own heuristics to determine if a `fee` is fair and the loan repaid, or the transaction reverted.

### Flash minting external security considerations

The typical quantum of assets involved in flash mint transactions will give rise to new innovative attack vectors.

#### Spot Oracle Manipulation

The supply of a flash-mintable asset can be easily manipulated, so oracles that take the supply of the flash-mintable asset into account must either discount amounts that were flash-minted, produce data that is averaged over time, or find some other solution to the varying supply.

#### Arithmetic Overflow and Underflow

If the flash mint provider does not place any limits on the amount of flash mintable assets in a transaction, then anyone can flash mint $2^256-1$ amount of assets.

The protocols on the receiving end of the flash mints will need to ensure their contracts can handle this, either by using a compiler that embeds overflow protection in the smart contract bytecode, or by setting explicit checks.

### Flash minting internal security considerations

The coupling of flash minting with business specific features in the same platform can easily lead to unintended consequences.

#### Treasury Draining

Assume a smart contract that flash lends its native asset. The same smart contract borrows from a third party when users burn the native asset. This pattern would be used to aggregate in the smart contract the collateralized debt of several users into a single account in the third party. The flash mint could be used to cause the `lender` to borrow to its limit, and then pushing interest rates in the underlying `lender`, liquidate the flash `lender`:

1. Flash mint from `lender` a very large amount of FOO.
2. Redeem FOO for BAR, causing `lender` to borrow from `underwriter` all the way to its borrowing limit.
3. Trigger a debt rate increase in `underwriter`, making `lender` undercollateralized.
4. Liquidate the `lender` for profit.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 25 Jul 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7399</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7399</guid>
      </item>
    
      <item>
        <title>Parent-Governed Non-Fungible Tokens Nesting</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6059-parent-governed-nestable-non-fungible-tokens/11914</comments>
        
        <description>## Abstract

❗️ **[ERC-7401](/EIPs/EIPS/eip-7401) supersedes [ERC-6059](/EIPs/EIPS/eip-6059).** ❗️

The Parent-Governed NFT Nesting standard extends [ERC-721](/EIPs/EIPS/eip-721) by allowing for a new inter-NFT relationship and interaction.

At its core, the idea behind the proposal is simple: the owner of an NFT does not have to be an Externally Owned Account (EOA) or a smart contract, it can also be an NFT.

The process of nesting an NFT into another is functionally identical to sending it to another user. The process of sending a token out of another one involves issuing a transaction from the account owning the parent token.

An NFT can be owned by a single other NFT, but can in turn have a number of NFTs that it owns. This proposal establishes the framework for the parent-child relationships of NFTs. A parent token is the one that owns another token. A child token is a token that is owned by another token. A token can be both a parent and child at the same time. Child tokens of a given token can be fully managed by the parent token&apos;s owner, but can be proposed by anyone.

![Nestable tokens](/EIPs/assets/eip-7401/img/eip-7401-nestable-tokens.png)

The graph illustrates how a child token can also be a parent token, but both are still administered by the root parent token&apos;s owner.

## Motivation

With NFTs being a widespread form of tokens in the Ethereum ecosystem and being used for a variety of use cases, it is time to standardize additional utility for them. Having the ability for tokens to own other tokens allows for greater utility, usability and forward compatibility.

In the four years since [ERC-721](/EIPs/EIPS/eip-721) was published, the need for additional functionality has resulted in countless extensions. This ERC improves upon ERC-721 in the following areas:

- [Bundling](#bundling)
- [Collecting](#collecting)
- [Membership](#membership)
- [Delegation](#delegation)

This proposal fixes the inconsistency in the [ERC-6059](/EIPs/EIPS/eip-6059) interface specification, where interface ID doesn&apos;t match the interface specified as the interface evolved during the proposal&apos;s lifecycle, but one of the parameters was not added to it. The missing parameter is, however, present in the interface ID. Apart from this fix, this proposal is functionally equivalent to [ERC-6059](/EIPs/EIPS/eip-6059).

### Bundling

One of the most frequent uses of [ERC-721](/EIPs/EIPS/eip-721) is to disseminate the multimedia content that is tied to the tokens. In the event that someone wants to offer a bundle of NFTs from various collections, there is currently no easy way of bundling all of these together and handle their sale as a single transaction. This proposal introduces a standardized way of doing so. Nesting all of the tokens into a simple bundle and selling that bundle would transfer the control of all of the tokens to the buyer in a single transaction.

### Collecting

A lot of NFT consumers collect them based on countless criteria. Some aim for utility of the tokens, some for the uniqueness, some for the visual appeal, etc. There is no standardized way to group the NFTs tied to a specific account. By nesting NFTs based on their owner&apos;s preference, this proposal introduces the ability to do it. The root parent token could represent a certain group of tokens and all of the children nested into it would belong to it.

The rise of soulbound, non-transferable, tokens, introduces another need for this proposal. Having a token with multiple soulbound traits (child tokens), allows for numerous use cases. One concrete example of this can be drawn from supply chains use case. A shipping container, represented by an NFT with its own traits, could have multiple child tokens denoting each leg of its journey.

### Membership

A common utility attached to NFTs is a membership to a Decentralised Autonomous Organization (DAO) or to some other closed-access group. Some of these organizations and groups occasionally mint NFTs to the current holders of the membership NFTs. With the ability to nest mint a token into a token, such minting could be simplified, by simply minting the bonus NFT directly into the membership one.

### Delegation

One of the core features of DAOs is voting and there are various approaches to it. One such mechanic is using fungible voting tokens where members can delegate their votes by sending these tokens to another member. Using this proposal, delegated voting could be handled by nesting your voting NFT into the one you are delegating your votes to and transferring it when the member no longer wishes to delegate their votes.

## Specification

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.

```solidity
/// @title EIP-7401 Parent-Governed Nestable Non-Fungible Tokens
/// @dev See https://eips.ethereum.org/EIPS/eip-7401
/// @dev Note: the ERC-165 identifier for this interface is 0x42b0e56f.

pragma solidity ^0.8.16;

interface IERC7059 /* is ERC165 */ {
    /**
     * @notice The core struct of ownership.
     * @dev The `DirectOwner` struct is used to store information of the next immediate owner, be it the parent token,
     * an `ERC721Receiver` contract or an externally owned account.
     * @dev If the token is not owned by an NFT, the `tokenId` MUST equal `0`.
     * @param tokenId ID of the parent token
     * @param ownerAddress Address of the owner of the token. If the owner is another token, then the address MUST be
     *  the one of the parent token&apos;s collection smart contract. If the owner is externally owned account, the address
     *  MUST be the address of this account
     */
    struct DirectOwner {
        uint256 tokenId;
        address ownerAddress;
    }

    /**
     * @notice The core child token struct, holding the information about the child tokens.
     * @return tokenId ID of the child token in the child token&apos;s collection smart contract
     * @return contractAddress Address of the child token&apos;s smart contract
     */
    struct Child {
        uint256 tokenId;
        address contractAddress;
    }

    /**
     * @notice Used to notify listeners that the token is being transferred.
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     * @param from Address of the previous immediate owner, which is a smart contract if the token was nested.
     * @param to Address of the new immediate owner, which is a smart contract if the token is being nested.
     * @param fromTokenId ID of the previous parent token. If the token was not nested before, the value MUST be `0`
     * @param toTokenId ID of the new parent token. If the token is not being nested, the value MUST be `0`
     * @param tokenId ID of the token being transferred
     */
    event NestTransfer(
        address indexed from,
        address indexed to,
        uint256 fromTokenId,
        uint256 toTokenId,
        uint256 indexed tokenId
    );

    /**
     * @notice Used to notify listeners that a new token has been added to a given token&apos;s pending children array.
     * @dev Emitted when a child NFT is added to a token&apos;s pending array.
     * @param tokenId ID of the token that received a new pending child token
     * @param childIndex Index of the proposed child token in the parent token&apos;s pending children array
     * @param childAddress Address of the proposed child token&apos;s collection smart contract
     * @param childId ID of the child token in the child token&apos;s collection smart contract
     */
    event ChildProposed(
        uint256 indexed tokenId,
        uint256 childIndex,
        address indexed childAddress,
        uint256 indexed childId
    );

    /**
     * @notice Used to notify listeners that a new child token was accepted by the parent token.
     * @dev Emitted when a parent token accepts a token from its pending array, migrating it to the active array.
     * @param tokenId ID of the token that accepted a new child token
     * @param childIndex Index of the newly accepted child token in the parent token&apos;s active children array
     * @param childAddress Address of the child token&apos;s collection smart contract
     * @param childId ID of the child token in the child token&apos;s collection smart contract
     */
    event ChildAccepted(
        uint256 indexed tokenId,
        uint256 childIndex,
        address indexed childAddress,
        uint256 indexed childId
    );

    /**
     * @notice Used to notify listeners that all pending child tokens of a given token have been rejected.
     * @dev Emitted when a token removes all child tokens from its pending array.
     * @param tokenId ID of the token that rejected all of the pending children
     */
    event AllChildrenRejected(uint256 indexed tokenId);

    /**
     * @notice Used to notify listeners a child token has been transferred from parent token.
     * @dev Emitted when a token transfers a child from itself, transferring ownership.
     * @param tokenId ID of the token that transferred a child token
     * @param childIndex Index of a child in the array from which it is being transferred
     * @param childAddress Address of the child token&apos;s collection smart contract
     * @param childId ID of the child token in the child token&apos;s collection smart contract
     * @param fromPending A boolean value signifying whether the token was in the pending child tokens array (`true`) or
     *  in the active child tokens array (`false`)
     * @param toZero A boolean value signifying whether the token is being transferred to the `0x0` address (`true`) or
     *  not (`false`)
     */
    event ChildTransferred(
        uint256 indexed tokenId,
        uint256 childIndex,
        address indexed childAddress,
        uint256 indexed childId,
        bool fromPending,
        bool toZero
    );

    /**
     * @notice Used to retrieve the *root* owner of a given token.
     * @dev The *root* owner of the token is the top-level owner in the hierarchy which is not an NFT.
     * @dev If the token is owned by another NFT, it MUST recursively look up the parent&apos;s root owner.
     * @param tokenId ID of the token for which the *root* owner has been retrieved
     * @return owner The *root* owner of the token
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @notice Used to retrieve the immediate owner of the given token.
     * @dev If the immediate owner is another token, the address returned, MUST be the one of the parent token&apos;s
     *  collection smart contract.
     * @param tokenId ID of the token for which the direct owner is being retrieved
     * @return address Address of the given token&apos;s owner
     * @return uint256 The ID of the parent token. MUST be `0` if the owner is not an NFT
     * @return bool The boolean value signifying whether the owner is an NFT or not
     */
    function directOwnerOf(uint256 tokenId)
        external
        view
        returns (
            address,
            uint256,
            bool
        );

    /**
     * @notice Used to burn a given token.
     * @dev When a token is burned, all of its child tokens are recursively burned as well.
     * @dev When specifying the maximum recursive burns, the execution MUST be reverted if there are more children to be
     *  burned.
     * @dev Setting the `maxRecursiveBurn` value to 0 SHOULD only attempt to burn the specified token and MUST revert if
     *  there are any child tokens present.
     * @param tokenId ID of the token to burn
     * @param maxRecursiveBurns Maximum number of tokens to recursively burn
     * @return uint256 Number of recursively burned children
     */
    function burn(uint256 tokenId, uint256 maxRecursiveBurns)
        external
        returns (uint256);

    /**
     * @notice Used to add a child token to a given parent token.
     * @dev This adds the child token into the given parent token&apos;s pending child tokens array.
     * @dev The destination token MUST NOT be a child token of the token being transferred or one of its downstream
     *  child tokens.
     * @dev This method MUST NOT be called directly. It MUST only be called from an instance of `IERC7059` as part of a 
        `nestTransfer` or `transferChild` to an NFT.
     * @dev Requirements:
     *
     *  - `directOwnerOf` on the child contract MUST resolve to the called contract.
     *  - the pending array of the parent contract MUST not be full.
     * @param parentId ID of the parent token to receive the new child token
     * @param childId ID of the new proposed child token
     */
    function addChild(uint256 parentId, uint256 childId) external;

    /**
     * @notice Used to accept a pending child token for a given parent token.
     * @dev This moves the child token from parent token&apos;s pending child tokens array into the active child tokens
     *  array.
     * @param parentId ID of the parent token for which the child token is being accepted
     * @param childIndex Index of the child token to accept in the pending children array of a given token
     * @param childAddress Address of the collection smart contract of the child token expected to be at the specified
     *  index
     * @param childId ID of the child token expected to be located at the specified index
     */
    function acceptChild(
        uint256 parentId,
        uint256 childIndex,
        address childAddress,
        uint256 childId
    ) external;

    /**
     * @notice Used to reject all pending children of a given parent token.
     * @dev Removes the children from the pending array mapping.
     * @dev The children&apos;s ownership structures are not updated.
     * @dev Requirements:
     *
     * - `parentId` MUST exist
     * @param parentId ID of the parent token for which to reject all of the pending tokens
     * @param maxRejections Maximum number of expected children to reject, used to prevent from
     *  rejecting children which arrive just before this operation.
     */
    function rejectAllChildren(uint256 parentId, uint256 maxRejections) external;

    /**
     * @notice Used to transfer a child token from a given parent token.
     * @dev MUST remove the child from the parent&apos;s active or pending children.
     * @dev When transferring a child token, the owner of the token MUST be set to `to`, or not updated in the event of `to`
     *  being the `0x0` address.
     * @param tokenId ID of the parent token from which the child token is being transferred
     * @param to Address to which to transfer the token to
     * @param destinationId ID of the token to receive this child token (MUST be 0 if the destination is not a token)
     * @param childIndex Index of a token we are transferring, in the array it belongs to (can be either active array or
     *  pending array)
     * @param childAddress Address of the child token&apos;s collection smart contract
     * @param childId ID of the child token in its own collection smart contract
     * @param isPending A boolean value indicating whether the child token being transferred is in the pending array of the
     *  parent token (`true`) or in the active array (`false`)
     * @param data Additional data with no specified format, sent in call to `to`
     */
    function transferChild(
        uint256 tokenId,
        address to,
        uint256 destinationId,
        uint256 childIndex,
        address childAddress,
        uint256 childId,
        bool isPending,
        bytes data
    ) external;

    /**
     * @notice Used to retrieve the active child tokens of a given parent token.
     * @dev Returns array of Child structs existing for parent token.
     * @dev The Child struct consists of the following values:
     *  [
     *      tokenId,
     *      contractAddress
     *  ]
     * @param parentId ID of the parent token for which to retrieve the active child tokens
     * @return struct[] An array of Child structs containing the parent token&apos;s active child tokens
     */
    function childrenOf(uint256 parentId)
        external
        view
        returns (Child[] memory);

    /**
     * @notice Used to retrieve the pending child tokens of a given parent token.
     * @dev Returns array of pending Child structs existing for given parent.
     * @dev The Child struct consists of the following values:
     *  [
     *      tokenId,
     *      contractAddress
     *  ]
     * @param parentId ID of the parent token for which to retrieve the pending child tokens
     * @return struct[] An array of Child structs containing the parent token&apos;s pending child tokens
     */
    function pendingChildrenOf(uint256 parentId)
        external
        view
        returns (Child[] memory);

    /**
     * @notice Used to retrieve a specific active child token for a given parent token.
     * @dev Returns a single Child struct locating at `index` of parent token&apos;s active child tokens array.
     * @dev The Child struct consists of the following values:
     *  [
     *      tokenId,
     *      contractAddress
     *  ]
     * @param parentId ID of the parent token for which the child is being retrieved
     * @param index Index of the child token in the parent token&apos;s active child tokens array
     * @return struct A Child struct containing data about the specified child
     */
    function childOf(uint256 parentId, uint256 index)
        external
        view
        returns (Child memory);

    /**
     * @notice Used to retrieve a specific pending child token from a given parent token.
     * @dev Returns a single Child struct locating at `index` of parent token&apos;s active child tokens array.
     * @dev The Child struct consists of the following values:
     *  [
     *      tokenId,
     *      contractAddress
     *  ]
     * @param parentId ID of the parent token for which the pending child token is being retrieved
     * @param index Index of the child token in the parent token&apos;s pending child tokens array
     * @return struct A Child struct containing data about the specified child
     */
    function pendingChildOf(uint256 parentId, uint256 index)
        external
        view
        returns (Child memory);

    /**
     * @notice Used to transfer the token into another token.
     * @dev The destination token MUST NOT be a child token of the token being transferred or one of its downstream
     *  child tokens.
     * @param from Address of the direct owner of the token to be transferred
     * @param to Address of the receiving token&apos;s collection smart contract
     * @param tokenId ID of the token being transferred
     * @param destinationId ID of the token to receive the token being transferred
     * @param data Additional data with no specified format
     */
    function nestTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        uint256 destinationId,
        bytes memory data
    ) external;
}
```

ID MUST never be a `0` value, as this proposal uses `0` values do signify that the token/destination is not an NFT.

## Rationale

Designing the proposal, we considered the following questions:

1. **How to name the proposal?**\
In an effort to provide as much information about the proposal we identified the most important aspect of the proposal; the parent centered control over nesting. The child token&apos;s role is only to be able to be `Nestable` and support a token owning it. This is how we landed on the `Parent-Centered` part of the title.
2. **Why is automatically accepting a child using [EIP-712](/EIPs/EIPS/eip-712) permit-style signatures not a part of this proposal?**\
For consistency. This proposal extends ERC-721 which already uses 1 transaction for approving operations with tokens. It would be inconsistent to have this and also support signing messages for operations with assets.
3. **Why use indexes?**\
To reduce the gas consumption. If the token ID was used to find which token to accept or reject, iteration over arrays would be required and the cost of the operation would depend on the size of the active or pending children arrays. With the index, the cost is fixed. Lists of active and pending children per token need to be maintained, since methods to get them are part of the proposed interface.\
To avoid race conditions in which the index of a token changes, the expected token ID as well as the expected token&apos;s collection smart contract is included in operations requiring token index, to verify that the token being accessed using the index is the expected one.\
Implementation that would internally keep track of indices using mapping was attempted. The minimum cost of accepting a child token was increased by over 20% and the cost of minting has increased by over 15%. We concluded that it is not necessary for this proposal and can be implemented as an extension for use cases willing to accept the increased transaction cost this incurs. In the sample implementation provided, there are several hooks which make this possible.
4. **Why is the pending children array limited instead of supporting pagination?**\
The pending child tokens array is not meant to be a buffer to collect the tokens that the root owner of the parent token wants to keep, but not enough to promote them to active children. It is meant to be an easily traversable list of child token candidates and should be regularly maintained; by either accepting or rejecting proposed child tokens. There is also no need for the pending child tokens array to be unbounded, because active child tokens array is.\
Another benefit of having bounded child tokens array is to guard against spam and griefing. As minting malicious or spam tokens could be relatively easy and low-cost, the bounded pending array assures that all of the tokens in it are easy to identify and that legitimate tokens are not lost in a flood of spam tokens, if one occurs.\
A consideration tied to this issue was also how to make sure, that a legitimate token is not accidentally rejected when clearing the pending child tokens array. We added the maximum pending children to reject argument to the clear pending child tokens array call. This assures that only the intended number of pending child tokens is rejected and if a new token is added to the pending child tokens array during the course of preparing such call and executing it, the clearing of this array SHOULD result in a reverted transaction.
5. **Should we allow tokens to be nested into one of its children?**\
The proposal enforces that a parent token can&apos;t be nested into one of its child token, or downstream child tokens for that matter. A parent token and its children are all managed by the parent token&apos;s root owner. This means that if a token would be nested into one of its children, this would create the ownership loop and none of the tokens within the loop could be managed anymore.
6. **Why is there not a &quot;safe&quot; nest transfer method?**\
`nestTransfer` is always &quot;safe&quot; since it MUST check for `IERC7059` compatibility on the destination.
7. **How does this proposal differ from the other proposals trying to address a similar problem?**\
This interface allows for tokens to both be sent to and receive other tokens. The propose-accept and parent governed patterns allow for a more secure use. The backward compatibility is only added for ERC-721, allowing for a simpler interface. The proposal also allows for different collections to inter-operate, meaning that nesting is not locked to a single smart contract, but can be executed between completely separate NFT collections.\
Additionally this proposal addresses the inconsistencies between `interfaceId`, interface specification and example implementation of [ERC-6059](/EIPs/EIPS/eip-6059).

### Propose-Commit pattern for child token management

Adding child tokens to a parent token MUST be done in the form of propose-commit pattern to allow for limited mutability by a 3rd party. When adding a child token to a parent token, it is first placed in a *&quot;Pending&quot;* array, and MUST be migrated to the *&quot;Active&quot;* array by the parent token&apos;s root owner. The *&quot;Pending&quot;* child tokens array SHOULD be limited to 128 slots to prevent spam and griefing.

The limitation that only the root owner can accept the child tokens also introduces a trust inherent to the proposal. This ensures that the root owner of the token has full control over the token. No one can force the user to accept a child if they don&apos;t want to.

### Parent Governed pattern

The parent NFT of a nested token and the parent&apos;s root owner are in all aspects the true owners of it. Once you send a token to another one you give up ownership.

We continue to use ERC-721&apos;s `ownerOf` functionality which will now recursively look up through parents until it finds an address which is not an NFT, this is referred to as the *root owner*. Additionally we provide the `directOwnerOf` which returns the most immediate owner of a token using 3 values: the owner address, the tokenId which MUST be 0 if the direct owner is not an NFT, and a flag indicating whether or not the parent is an NFT.

The root owner or an approved party MUST be able to do the following operations on children: `acceptChild`, `rejectAllChildren` and `transferChild`.

The root owner or an approved party MUST also be allowed to do these operations only when token is not owned by an NFT: `transferFrom`, `safeTransferFrom`, `nestTransferFrom`, `burn`.

If the token is owned by an NFT, only the parent NFT itself MUST be allowed to execute the operations listed above. Transfers MUST be done from the parent token, using `transferChild`, this method in turn SHOULD call `nestTransferFrom` or `safeTransferFrom` in the child token&apos;s smart contract, according to whether the destination is an NFT or not. For burning, tokens must first be transferred to an EOA and then burned.

We add this restriction to prevent inconsistencies on parent contracts, since only the `transferChild` method takes care of removing the child from the parent when it is being transferred out of it.

### Child token management

This proposal introduces a number of child token management functions. In addition to the permissioned migration from *&quot;Pending&quot;* to *&quot;Active&quot;* child tokens array, the main token management function from this proposal is the `transferChild` function. The following state transitions of a child token are available with it:

1. Reject child token
2. Abandon child token
3. Unnest child token
4. Transfer the child token to an EOA or an `ERC721Receiver`
5. Transfer the child token into a new parent token

To better understand how these state transitions are achieved, we have to look at the available parameters passed to `transferChild`:

```solidity
    function transferChild(
        uint256 tokenId,
        address to,
        uint256 destinationId,
        uint256 childIndex,
        address childAddress,
        uint256 childId,
        bool isPending,
        bytes data
    ) external;
```

Based on the desired state transitions, the values of these parameters have to be set accordingly (any parameters not set in the following examples depend on the child token being managed):

1. **Reject child token**\
![Reject child token](/EIPs/assets/eip-7401/img/eip-7401-reject-child.png)
2. **Abandon child token**\
![Abandon child token](/EIPs/assets/eip-7401/img/eip-7401-abandon-child.png)
3. **Unnest child token**\
![Unnest child token](/EIPs/assets/eip-7401/img/eip-7401-unnest-child.png)
4. **Transfer the child token to an EOA or an `ERC721Receiver`**\
![Transfer child token to EOA](/EIPs/assets/eip-7401/img/eip-7401-transfer-child-to-eoa.png)
5. **Transfer the child token into a new parent token**\
![Transfer child token to parent token](/EIPs/assets/eip-7401/img/eip-7401-transfer-child-to-token.png)\
This state change places the token in the pending array of the new parent token. The child token still needs to be accepted by the new parent token&apos;s root owner in order to be placed into the active array of that token.

## Backwards Compatibility

The Nestable token standard has been made compatible with [ERC-721](/EIPs/EIPS/eip-721) in order to take advantage of the robust tooling available for implementations of ERC-721 and to ensure compatibility with existing ERC-721 infrastructure.

The only incompatibility with ERC-721 is that Nestable tokens cannot use a token ID of 0.

There is some differentiation of how the `ownerOf` method behaves compared to ERC-721. The `ownerOf` method will now recursively look up through parent tokens until it finds an address that is not an NFT; this is referred to as the *root owner*. Additionally, we provide the `directOwnerOf`, which returns the most immediate owner of a token using 3 values: the owner address, the `tokenId`, which MUST be 0 if the direct owner is not an NFT, and a flag indicating whether or not the parent is an NFT. In case the token is owned by an EoA or an ERC-721 Receiver, the `ownerOf` method will behave the same as in ERC-721.

## Test Cases

Tests are included in [`nestable.ts`](/EIPs/assets/eip-7401/test/nestable.ts).

To run them in terminal, you can use the following commands:

```
cd ../assets/eip-7401
npm install
npx hardhat test
```

## Reference Implementation

See [`NestableToken.sol`](/EIPs/assets/eip-7401/contracts/NestableToken.sol).


## Security Considerations

The same security considerations as with [ERC-721](/EIPs/EIPS/eip-721) apply: hidden logic may be present in any of the functions, including burn, add child, accept child, and more.

Since the current owner of the token is allowed to manage the token, there is a possibility that after the parent token is listed for sale, the seller might remove a child token just before before the sale and thus the buyer would not receive the expected child token. This is a risk that is inherent to the design of this standard. Marketplaces should take this into account and provide a way to verify the expected child tokens are present when the parent token is being sold or to guard against such a malicious behaviour in another way.

It is worth noting that `balanceOf` method only accounts for immediate tokens owned by the address; the tokens that are nested into a token owned by this address will not be reflected in this value as the recursive lookup needed in order to calculate this value is potentially too deep and might break the method.

Caution is advised when dealing with non-audited contracts.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 26 Jul 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7401</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7401</guid>
      </item>
    
      <item>
        <title>Portable Smart Contract Accounts</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7405-portable-smart-contract-accounts/15236</comments>
        
        <description>## Abstract

Portable Smart Contract Accounts (PSCA) address the lack of portability and compatibility faced by Smart Contract Accounts (SCA) across different wallet providers. Based on [ERC-1967](/EIPs/EIPS/eip-1967), the PSCA system allows users to easily migrate their SCAs between different wallets using new, randomly generated migration keys. This provides a similar experience to exporting an externally owned account (EOA) with a private key or mnemonic. The system ensures security by employing signatures and time locks, allowing users to verify and cancel migration operations during the lock period, thereby preventing potential malicious actions. PSCA offers a non-intrusive and cost-effective approach, enhancing the interoperability and composability within the Account Abstraction (AA) ecosystem.

## Motivation

With the introduction of the [ERC-4337](/EIPs/EIPS/eip-4337) standard, AA related infrastructure and SCAs have been widely adopted in the community. However, unlike EOAs, SCAs have a more diverse code space, leading to varying contract implementations across different wallet providers. Consequently, the lack of portability for SCAs has become a significant issue, making it challenging for users to migrate their accounts between different wallet providers. While some proposed a modular approach for SCA accounts, it comes with higher implementation costs and specific prerequisites for wallet implementations.

Considering that different wallet providers tend to prefer their own implementations or may expect their contract systems to be concise and robust, a modular system may not be universally applicable. The community currently lacks a more general SCA migration standard.

This proposal describes a solution working at the Proxy (ERC-1967) layer, providing a user experience similar to exporting an EOA account (using private keys or mnemonics). A universal SCA migration mechanism is shown in the following diagram:

![Overview Diagram](/EIPs/assets/eip-7405/overview-diagram.jpg)

Considering that different wallet providers may have their own implementations, this solution imposes almost no requirements on the SCA implementation, making it more universally applicable and less intrusive with lower operational costs. Unlike a modular system operating at the &quot;implementation&quot; layer, both approaches can complement each other to further improve the interoperability and composability of the AA ecosystem.

## Specification

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.

### Terms

- Wallet Provider: A service provider that offers wallet services. SCA implementations among wallet providers are typically different, lacking compatibility with each other.
- Random Operator: A new, randomly generated migration mnemonic or private key used for each migration. The corresponding address of its public key is the random operator&apos;s address.
    - If using a mnemonic, the derived migration private key follows the [BIP 44](https://github.com/bitcoin/bips/blob/55566a73f9ddf77b4512aca8e628650c913067bf/bip-0044.mediawiki) specification with the path **`m/44&apos;/60&apos;/0&apos;/0/0&apos;`**.

### Interfaces

A Portable Smart Contract Account **MUST** implement the **`IERC7405`** interface:

```solidity
interface IERC7405 {
    /**
     * @dev emitted when the account finishes the migration
     * @param oldImplementation old implementation address
     * @param newImplementation new implementation address
     */
    event AccountMigrated(
        address oldImplementation,
        address newImplementation
    );
    
    /**
     * @dev prepare the account for migration
     * @param randomOperator public key (in address format) of the random operator
     * @param signature signature signed by the random operator
     *
     * **MUST** check the authenticity of the account
     */
    function prepareAccountMigration(
        address randomOperator,
        bytes calldata signature
    ) external;

    /**
     * @dev cancel the account migration
     *
     * **MUST** check the authenticity of the account
     */
    function cancelAccountMigration() external;

    /**
     * @dev handle the account migration
     * @param newImplementation new implementation address
     * @param initData init data for the new implementation
     * @param signature signature signed by the random operator
     *
     * **MUST NOT** check the authenticity to make it accessible by the new implementation
     */
    function handleAccountMigration(
        address newImplementation,
        bytes calldata initData,
        bytes calldata signature
    ) external;
}
```

### Signatures

The execution of migration operations **MUST** use the migration private key to sign the `MigrationOp`.

```solidity
struct MigrationOp {
    uint256 chainID;
    bytes4 selector;
    bytes data;
}
```

When the **`selector`** corresponds to **`prepareAccountMigration(address,bytes)`** (i.e., **`0x50fe70bd`**), the **`data`** is **`abi.encode(randomOperator)`**. When the **`selector`** corresponds to **`handleAccountMigration(address,bytes,bytes)`** (i.e., **`0xae2828ba`**), the **`data`** is **`abi.encode(randomOperator, setupCalldata)`**.

The signature is created using **[ERC-191](/EIPs/EIPS/eip-191)**, signing the **`MigrateOpHash`** (calculated as **`abi.encode(chainID, selector, data)`**).

### Registry

To simplify migration credentials and enable direct addressing of the SCA account with only the migration mnemonic or private key, this proposal requires a shared registry deployed at the protocol layer.

```solidity
interface IERC7405Registry {
    struct MigrationData {
        address account;
        uint48 createTime;
        uint48 lockUntil;
    }

    /**
     * @dev check if the migration data for the random operator exists
     * @param randomOperator public key (in address format) of the random operator
     */
    function migrationDataExists(
        address randomOperator
    ) external returns (bool);

    /**
     * @dev get the migration data for the random operator
     * @param randomOperator public key (in address format) of the random operator
     */
    function getMigrationData(
        address randomOperator
    ) external returns (MigrationData memory);

    /**
     * @dev set the migration data for the random operator
     * @param randomOperator public key (in address format) of the random operator
     * @param lockUntil the timestamp until which the account is locked for migration
     *
     * **MUST** validate `migrationDataMap[randomOperator]` is empty
     */
    function setMigrationData(
        address randomOperator,
        uint48 lockUntil
    ) external;

    /**
     * @dev delete the migration data for the random operator
     * @param randomOperator public key (in address format) of the random operator
     *
     * **MUST** validate `migrationDataMap[randomOperator].account` is `msg.sender`
     */
    function deleteMigrationData(address randomOperator) external;
}
```

### Expected behavior

When performing account migration (i.e., migrating an SCA from Wallet A to Wallet B), the following steps **MUST** be followed:

1. Wallet A generates a new migration mnemonic or private key (**MUST** be new and random) and provides it to the user. The address corresponding to its public key is used as the **`randomOperator`**.
2. Wallet A signs the **`MigrateOpHash`** using the migration private key and calls the **`prepareAccountMigration`** method, which **MUST** performs the following operations:
    - Calls the internal method **`_requireAccountAuth()`** to verify the authenticity of the SCA account. For example, in ERC-4337 account implementation, it may require **`msg.sender == address(entryPoint)`**.
    - Performs signature checks to confirm the validity of the **`randomOperator`**.
    - Calls **`IERC7405Registry.migrationDataExists(randomOperator)`** to ensure that the **`randomOperator`** does not already exist.
    - Sets the SCA account&apos;s lock status to true and adds a record by calling **`IERC7405Registry.setMigrationData(randomOperator, lockUntil)`**.
    - After calling **`prepareAccountMigration`**, the account remains locked until a successful call to either **`cancelAccountMigration`** or **`handleAccountMigration`**.
3. To continue the migration, Wallet B initializes authentication data and imports the migration mnemonic or private key. Wallet B then signs the **`MigrateOpHash`** using the migration private key and calls the **`handleWalletMigration`** method, which **MUST** performs the following operations:
    - **MUST NOT** perform SCA account authentication checks to ensure public accessibility.
    - Performs signature checks to confirm the validity of the **`randomOperator`**.
    - Calls **`IERC7405Registry.getMigrationData(randomOperator)`** to retrieve **`migrationData`**, and requires **`require(migrationData.account == address(this) &amp;&amp; block.timestamp &gt; migrationData.lockUntil)`**.
    - Calls the internal method **`_beforeWalletMigration()`** to execute pre-migration logic from Wallet A (e.g., data cleanup).
    - Modifies the Proxy (ERC-1967) implementation to the implementation contract of Wallet B.
    - Calls **`address(this).call(initData)`** to initialize the Wallet B contract.
    - Calls **`IERC7405Registry.deleteMigrationData(randomOperator)`** to remove the record.
    - Emits the **`AccountMigrated`** event.
4. If the migration needs to be canceled, Wallet A can call the **`cancelAccountMigration`** method, which **MUST** performs the following operations:
    - Calls the internal method **`_requireAccountAuth()`** to verify the authenticity of the SCA account.
    - Sets the SCA account&apos;s lock status to false and deletes the record by calling **`IERC7405Registry.deleteMigrationData(randomOperator)`**.

### Storage Layout

To prevent conflicts in storage layout during migration across different wallet implementations, a Portable Smart Contract Account implementation contract:

- **MUST NOT** directly define state variables in the contract header.
- **MUST** encapsulate all state variables within a struct and store that struct in a specific slot. The slot index **SHOULD** be unique across different wallet implementations.

For slot index, we recommend calculating it based on the namespace and slot ID:

- The namespace **MUST** contain only [A-Za-z0-9_].
- Wallet providers&apos; namespaces are **RECOMMENDED** to use snake_case, incorporating the wallet name and major version number, such as **`foo_wallet_v1`**.
- The slot ID for slot index **SHOULD** follow the format **`{namespace}.{customDomain}`**, for example, **`foo_wallet_v1.config`**.
- The calculation of the slot index is performed as **`bytes32(uint256(keccak256(slotID) - 1))`**.

## Rationale

The main challenge addressed by this EIP is the lack of portability in Smart Contract Accounts (SCAs). Currently, due to variations in SCA implementations across wallet providers, moving between wallets is a hassle. Proposing a modular approach, though beneficial in some respects, comes with its own costs and compatibility concerns.

The PSCA system, rooted in ERC-1967, introduces a migration mechanism reminiscent of exporting an EOA with a private key or mnemonic. This approach is chosen for its familiarity to users, ensuring a smoother user experience.

Employing random, migration-specific keys further fortifies security. By mimicking the EOA exportation process, we aim to keep the process recognizable, while addressing the unique challenges of SCA portability.

The decision to integrate with a shared registry at the protocol layer simplifies migration credentials. This system enables direct addressing of the SCA account using only the migration key, enhancing efficiency.

Storage layout considerations were paramount to avoid conflicts during migrations. Encapsulating state variables within a struct, stored in a unique slot, ensures that migrations don&apos;t lead to storage overlaps or overwrites.

## Backwards Compatibility

This proposal is backward compatible with all SCA based on ERC-1967 Proxy, including non-ERC-4337 SCAs. Furthermore, this proposal does not have specific prerequisites for SCA implementation contracts, making it broadly applicable to various SCAs.

&lt;!--
## Reference Implementation

[WIP]
--&gt;

## Security Considerations

- Each migration must generate a new, randomly generated migration mnemonic or private key and its corresponding random operator address to prevent replay attacks or malicious signing.
- Different wallet implementations must consider the independence of storage layout to avoid conflicts in storage after migration.
- To prevent immediate loss of access for the account owner due to malicious migration, we introduce a &quot;time lock&quot; to make migrations detectable and reversible. When a malicious operation attempts an immediate migration of an SCA, the account enters a lock state and waits for a lock period. During this time, users can use the original account authentication to cancel the migration and prevent asset loss. Accounts in the lock state **SHOULD NOT** allow the following operations:
    - Any form of asset transfer operations
    - Any form of external contract call operations
    - Any attempts to modify account authentication factors
    - Any operations that could potentially impact the above three
- When performing migration operations, the wallet provider **SHOULD** attempt to notify the account owner of the migration details through all available messaging channels.

## Copyright

Copyright and related rights waived via **[CC0](/EIPs/LICENSE)**.
</description>
        <pubDate>Wed, 26 Jul 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7405</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7405</guid>
      </item>
    
      <item>
        <title>Multi-Namespace Onchain Registry</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7406-multi-namespace-onchain-registry/15216</comments>
        
        <description>## Abstract

This EIP proposes a universally accepted description for onchain registry entries with support for multi-namespaces, where each entry is structured as a mapping type. The multi-namespace registry enables the storage of a collection of key-value mappings within the blockchain, serving as a definitive source of information with a traceable history of changes. These mapping records act as pointers combined with onchain assets, offering enhanced versatility in various use cases by encapsulating extensive details. The proposed solution introduces a general mapping data structure that is flexible enough to support and be compatible with different situations, providing a more scalable and powerful alternative to current ENS-like registries.

## Motivation

Blockchain-based registries are fundamental components for decentralized applications, enabling the storage and retrieval of essential information. Existing solutions, like the ENS registry, serve specific use cases but may lack the necessary flexibility to accommodate more complex scenarios. The need for a more general mapping data structure with multi-namespace support arises to empower developers with a single registry capable of handling diverse use cases efficiently.

The proposed multi-namespace registry offers several key advantages:

- **Versatility**: Developers can define and manage multiple namespaces, each with its distinct set of keys, allowing for more granular control and organization of data. For instance, single same key can derive as different pointers to various values based on difference namespaces, which a namespace can be specified as a session type, if this registry stores sessions, or short URL -&gt; full URL mapping is registry stores such type of data.
- **Traceable History**: By leveraging multi-namespace capabilities, the registry can support entry versioning by using multi-namespace distinct as version number, enabling tracking of data change history, reverting data, or data tombstoning. This facilitates data management and governance within a single contract.
- **Enhanced Compatibility**: The proposed structure is designed to be compatible with various use cases beyond the scope of traditional ENS-like registries, promoting its adoption in diverse decentralized applications.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### **Registry specification**

The multi namespace registry contract exposes the following functions:

```solidity
function owner(bytes32 namespace, bytes32 key) external view returns (address);
```

- Returns the owner of the specified **key** under the given **namespace**.

```solidity
function resolver(bytes32 namespace, bytes32 key) external view returns (address);
```

- Returns the resolver address for the specified **key** under the given **namespace**.

```solidity
function setOwner(bytes32 namespace, bytes32 key, address newOwner) external;
```

- Transfers ownership of the **key** under the specified **namespace** to another owner. This function may only be called by the current owner of the **key** under a specific **namespace**. The same **key** under different **namespaces** may have different owners. A successful call to this function logs the event **Transfer(bytes32 namespace, bytes32 key, address newOwner)**.

```solidity
function createNamespace(bytes32 namespace) external;
```

- Create a new **namespace** such as a new version or a new type of protocol in current registry. A successful call to this function logs the event **NewNamespace(bytes32 namespace)**.

```solidity
function setResolver(bytes32 namespace, bytes32 key, address newResolver) external;
```

- Sets the resolver address for the **key** under the given **namespace**. This function may only be called by the owner of the key under a specific **namespace**. The same key under different namespaces may have different resolvers. A successful call to this function logs the event **NewResolver(bytes32 namespace, bytes32 key, address newResolver)**.

### **Resolver specification**

The multi-namespace resolver contract can utilize the same specification as defined in [ERC-137](/EIPs/EIPS/eip-137).

## Rationale

By supporting multiple namespaces, the registry caters to various use cases, including but not limited to identity management, session management, record tracking, and decentralized content publishing. This flexibility enables developers to design and implement more complex decentralized applications with ease.

## Backwards Compatibility

As this EIP introduces a new feature and does not modify any existing behaviors, there are no backwards compatibility issues.

## Reference Implementation

### *Appendix A: Registry Implementation*

```solidity
pragma solidity ^0.8.12;

import &quot;./IERC7406Interface.sol&quot;;

contract ERC7406 {
    struct Record {
        address owner;
        address resolver;
    }


    // A map is used to record namespace existence
    mapping(byte32=&gt;uint) namespaces;
    mapping(bytes32=&gt;mapping(bytes32=&gt;Record)) records;

    event NewOwner(bytes32 indexed namespace, bytes32 indexed key, address owner);
    event Transfer(bytes32 indexed namespace, bytes32 indexed key, address owner);
    event NewResolver(bytes32 indexed namespace, bytes32 indexed key, address resolver);
    event NewNamespace(bytes32 namespace)

    modifier only_owner(bytes32 namespace, bytes32 key) {
        if(records[namespace][key].owner != msg.sender) throw;
        _
    }

    modifier only_approver() {
        if(records[0][0].owner != msg.sender) throw;
        _
    }

    function ERC7406(address approver) {
        records[0][0].owner = approver;
    }

    function owner(bytes32 namespace, bytes32 key) constant returns (address) {
        return records[namespace][key].owner;
    }
  
    function createNamespace(bytes32 namespace) only_approver() {
       if (status == 0) throw;
       NewNamespace(namespace);
       if (namespaces[namespace] != 0) {
           return;
       }
       namespaces[namespace] = 1;
    }

    function resolver(bytes32 namespace, bytes32 key) constant returns (address) {
        if (namespaces[namespace] == 0) throw;
        return records[namespace][key].resolver;
    }

    function setOwner(bytes32 namespace, bytes32 key, address owner) only_owner(namespace, key) {
        Transfer(key, namespace, owner);
        records[namespace][key].owner = owner;
    }

    function setResolver(bytes32 namespace, bytes32 key, address resolver) only_approver() {
        if (namespaces[namespace] == 0) {
            this.createNamespace(namespace, 1);
        }
        NewResolver(key, namespace, resolver);
        records[namespace][key].resolver = resolver;
    }
}
```

## Security Considerations

The proposed multi-namespace registry introduces several security considerations due to its ability to manage various namespaces and access controls. Thorough testing, auditing, and peer reviews will be conducted to identify and mitigate potential attack vectors and vulnerabilities. Security-conscious developers are encouraged to contribute to the audit process.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 23 Jul 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7406</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7406</guid>
      </item>
    
      <item>
        <title>Public Non-Fungible Tokens Emote Repository</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-6381-emotable-extension-for-non-fungible-tokens/12710</comments>
        
        <description>## Abstract

❗️ **[ERC-7409](/EIPs/EIPS/eip-7409) supersedes [ERC-6381](/EIPs/EIPS/eip-6381).** ❗️

The Public Non-Fungible Tokens Emote Repository standard provides an enhanced interactive utility for [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155) by allowing NFTs to be emoted at.

This proposal introduces the ability to react to NFTs using Unicode standardized emoji in a public non-gated repository smart contract that is accessible at the same address in all of the networks.

## Motivation

With NFTs being a widespread form of tokens in the Ethereum ecosystem and being used for a variety of use cases, it is time to standardize additional utility for them. Having the ability for anyone to interact with an NFT introduces an interactive aspect to owning an NFT and unlocks feedback-based NFT mechanics.

This ERC introduces new utilities for [ERC-721](/EIPs/EIPS/eip-721) based tokens in the following areas:

- [Interactivity](#interactivity)
- [Feedback based evolution](#feedback-based-evolution)
- [Valuation](#valuation)

This proposal fixes the compatibility issue in the [ERC-6381](/EIPs/EIPS/eip-6381) interface specification, where emojis are represented using `bytes4` values. The introduction of variation flags and emoji skin tones has rendered the `bytes4` namespace insufficient for representing all possible emojis, so the new standard used `string` instead. Apart from this fix, this proposal is functionally equivalent to [ERC-6381](/EIPs/EIPS/eip-6381).

### Interactivity

The ability to emote on an NFT introduces the aspect of interactivity to owning an NFT. This can either reflect the admiration for the emoter (person emoting to an NFT) or can be a result of a certain action performed by the token&apos;s owner. Accumulating emotes on a token can increase its uniqueness and/or value.

### Feedback based evolution

Standardized on-chain reactions to NFTs allow for feedback based evolution.

Current solutions are either proprietary or off-chain and therefore subject to manipulation and distrust. Having the ability to track the interaction on-chain allows for trust and objective evaluation of a given token. Designing the tokens to evolve when certain emote thresholds are met incentivizes interaction with the token collection.

### Valuation

Current NFT market heavily relies on previous values the token has been sold for, the lowest price of the listed token and the scarcity data provided by the marketplace. There is no real time indication of admiration or desirability of a specific token. Having the ability for users to emote to the tokens adds the possibility of potential buyers and sellers gauging the value of the token based on the impressions the token has collected.

## Specification

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.

```solidity
/// @title ERC-7409 Emotable Extension for Non-Fungible Tokens
/// @dev See https://eips.ethereum.org/EIPS/eip-7409
/// @dev Note: the ERC-165 identifier for this interface is 0x1b3327ab.

pragma solidity ^0.8.16;

interface IERC7409 /*is IERC165*/ {
    /**
     * @notice Used to notify listeners that the token with the specified ID has been emoted to or that the reaction has been revoked.
     * @dev The event MUST only be emitted if the state of the emote is changed.
     * @param emoter Address of the account that emoted or revoked the reaction to the token
     * @param collection Address of the collection smart contract containing the token being emoted to or having the reaction revoked
     * @param tokenId ID of the token
     * @param emoji Unicode identifier of the emoji
     * @param on Boolean value signifying whether the token was emoted to (`true`) or if the reaction has been revoked (`false`)
     */
    event Emoted(
        address indexed emoter,
        address indexed collection,
        uint256 indexed tokenId,
        string emoji,
        bool on
    );

    /**
     * @notice Used to get the number of emotes for a specific emoji on a token.
     * @param collection Address of the collection containing the token being checked for emoji count
     * @param tokenId ID of the token to check for emoji count
     * @param emoji Unicode identifier of the emoji
     * @return Number of emotes with the emoji on the token
     */
    function emoteCountOf(
        address collection,
        uint256 tokenId,
        string memory emoji
    ) external view returns (uint256);

    /**
     * @notice Used to get the number of emotes for a specific emoji on a set of tokens.
     * @param collections An array of addresses of the collections containing the tokens being checked for emoji count
     * @param tokenIds An array of IDs of the tokens to check for emoji count
     * @param emojis An array of unicode identifiers of the emojis
     * @return An array of numbers of emotes with the emoji on the tokens
     */
    function bulkEmoteCountOf(
        address[] memory collections,
        uint256[] memory tokenIds,
        string[] memory emojis
    ) external view returns (uint256[] memory);

    /**
     * @notice Used to get the information on whether the specified address has used a specific emoji on a specific
     *  token.
     * @param emoter Address of the account we are checking for a reaction to a token
     * @param collection Address of the collection smart contract containing the token being checked for emoji reaction
     * @param tokenId ID of the token being checked for emoji reaction
     * @param emoji The ASCII emoji code being checked for reaction
     * @return A boolean value indicating whether the `emoter` has used the `emoji` on the token (`true`) or not
     *  (`false`)
     */
    function hasEmoterUsedEmote(
        address emoter,
        address collection,
        uint256 tokenId,
        string memory emoji
    ) external view returns (bool);

    /**
     * @notice Used to get the information on whether the specified addresses have used specific emojis on specific
     *  tokens.
     * @param emoters An array of addresses of the accounts we are checking for reactions to tokens
     * @param collections An array of addresses of the collection smart contracts containing the tokens being checked
     *  for emoji reactions
     * @param tokenIds An array of IDs of the tokens being checked for emoji reactions
     * @param emojis An array of the ASCII emoji codes being checked for reactions
     * @return An array of boolean values indicating whether the `emoter`s has used the `emoji`s on the tokens (`true`)
     *  or not (`false`)
     */
    function haveEmotersUsedEmotes(
        address[] memory emoters,
        address[] memory collections,
        uint256[] memory tokenIds,
        string[] memory emojis
    ) external view returns (bool[] memory);

    /**
     * @notice Used to get the message to be signed by the `emoter` in order for the reaction to be submitted by someone
     *  else.
     * @param collection The address of the collection smart contract containing the token being emoted at
     * @param tokenId ID of the token being emoted
     * @param emoji Unicode identifier of the emoji
     * @param state Boolean value signifying whether to emote (`true`) or undo (`false`) emote
     * @param deadline UNIX timestamp of the deadline for the signature to be submitted
     * @return The message to be signed by the `emoter` in order for the reaction to be submitted by someone else
     */
    function prepareMessageToPresignEmote(
        address collection,
        uint256 tokenId,
        string memory emoji,
        bool state,
        uint256 deadline
    ) external view returns (bytes32);

    /**
     * @notice Used to get multiple messages to be signed by the `emoter` in order for the reaction to be submitted by someone
     *  else.
     * @param collections An array of addresses of the collection smart contracts containing the tokens being emoted at
     * @param tokenIds An array of IDs of the tokens being emoted
     * @param emojis An array of unicode identifiers of the emojis
     * @param states An array of boolean values signifying whether to emote (`true`) or undo (`false`) emote
     * @param deadlines An array of UNIX timestamps of the deadlines for the signatures to be submitted
     * @return The array of messages to be signed by the `emoter` in order for the reaction to be submitted by someone else
     */
    function bulkPrepareMessagesToPresignEmote(
        address[] memory collections,
        uint256[] memory tokenIds,
        string[] memory emojis,
        bool[] memory states,
        uint256[] memory deadlines
    ) external view returns (bytes32[] memory);

    /**
     * @notice Used to emote or undo an emote on a token.
     * @dev Does nothing if attempting to set a pre-existent state.
     * @dev MUST emit the `Emoted` event is the state of the emote is changed.
     * @param collection Address of the collection containing the token being emoted at
     * @param tokenId ID of the token being emoted
     * @param emoji Unicode identifier of the emoji
     * @param state Boolean value signifying whether to emote (`true`) or undo (`false`) emote
     */
    function emote(
        address collection,
        uint256 tokenId,
        string memory emoji,
        bool state
    ) external;

    /**
     * @notice Used to emote or undo an emote on multiple tokens.
     * @dev Does nothing if attempting to set a pre-existent state.
     * @dev MUST emit the `Emoted` event is the state of the emote is changed.
     * @dev MUST revert if the lengths of the `collections`, `tokenIds`, `emojis` and `states` arrays are not equal.
     * @param collections An array of addresses of the collections containing the tokens being emoted at
     * @param tokenIds An array of IDs of the tokens being emoted
     * @param emojis An array of unicode identifiers of the emojis
     * @param states An array of boolean values signifying whether to emote (`true`) or undo (`false`) emote
     */
    function bulkEmote(
        address[] memory collections,
        uint256[] memory tokenIds,
        string[] memory emojis,
        bool[] memory states
    ) external;

    /**
     * @notice Used to emote or undo an emote on someone else&apos;s behalf.
     * @dev Does nothing if attempting to set a pre-existent state.
     * @dev MUST emit the `Emoted` event is the state of the emote is changed.
     * @dev MUST revert if the lengths of the `collections`, `tokenIds`, `emojis` and `states` arrays are not equal.
     * @dev MUST revert if the `deadline` has passed.
     * @dev MUST revert if the recovered address is the zero address.
     * @param emoter The address that presigned the emote
     * @param collection The address of the collection smart contract containing the token being emoted at
     * @param tokenId IDs of the token being emoted
     * @param emoji Unicode identifier of the emoji
     * @param state Boolean value signifying whether to emote (`true`) or undo (`false`) emote
     * @param deadline UNIX timestamp of the deadline for the signature to be submitted
     * @param v `v` value of an ECDSA signature of the message obtained via `prepareMessageToPresignEmote`
     * @param r `r` value of an ECDSA signature of the message obtained via `prepareMessageToPresignEmote`
     * @param s `s` value of an ECDSA signature of the message obtained via `prepareMessageToPresignEmote`
     */
    function presignedEmote(
        address emoter,
        address collection,
        uint256 tokenId,
        string memory emoji,
        bool state,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @notice Used to bulk emote or undo an emote on someone else&apos;s behalf.
     * @dev Does nothing if attempting to set a pre-existent state.
     * @dev MUST emit the `Emoted` event is the state of the emote is changed.
     * @dev MUST revert if the lengths of the `collections`, `tokenIds`, `emojis` and `states` arrays are not equal.
     * @dev MUST revert if the `deadline` has passed.
     * @dev MUST revert if the recovered address is the zero address.
     * @param emoters An array of addresses of the accounts that presigned the emotes
     * @param collections An array of addresses of the collections containing the tokens being emoted at
     * @param tokenIds An array of IDs of the tokens being emoted
     * @param emojis An array of unicode identifiers of the emojis
     * @param states An array of boolean values signifying whether to emote (`true`) or undo (`false`) emote
     * @param deadlines UNIX timestamp of the deadline for the signature to be submitted
     * @param v An array of `v` values of an ECDSA signatures of the messages obtained via `prepareMessageToPresignEmote`
     * @param r An array of `r` values of an ECDSA signatures of the messages obtained via `prepareMessageToPresignEmote`
     * @param s An array of `s` values of an ECDSA signatures of the messages obtained via `prepareMessageToPresignEmote`
     */
    function bulkPresignedEmote(
        address[] memory emoters,
        address[] memory collections,
        uint256[] memory tokenIds,
        string[] memory emojis,
        bool[] memory states,
        uint256[] memory deadlines,
        uint8[] memory v,
        bytes32[] memory r,
        bytes32[] memory s
    ) external;
}
```

### Message format for presigned emotes

The message to be signed by the `emoter` in order for the reaction to be submitted by someone else is formatted as follows:

```solidity
keccak256(
        abi.encode(
            DOMAIN_SEPARATOR,
            collection,
            tokenId,
            emoji,
            state,
            deadline
        )
    );
```

The values passed when generating the message to be signed are:

- `DOMAIN_SEPARATOR` - The domain separator of the Emotable repository smart contract
- `collection` - Address of the collection containing the token being emoted at
- `tokenId` - ID of the token being emoted
- `emoji` - Unicode identifier of the emoji
- `state` - Boolean value signifying whether to emote (`true`) or undo (`false`) emote
- `deadline` - UNIX timestamp of the deadline for the signature to be submitted

The `DOMAIN_SEPARATOR` is generated as follows:

```solidity
keccak256(
        abi.encode(
            &quot;ERC-7409: Public Non-Fungible Token Emote Repository&quot;,
            &quot;1&quot;,
            block.chainid,
            address(this)
        )
    );
```

Each chain, that the Emotable repository smart contract is deployed on, will have a different `DOMAIN_SEPARATOR` value due to chain IDs being different.

### Pre-determined address of the Emotable repository

The address of the Emotable repository smart contract is designed to resemble the function it serves. It starts with `0x3110735` which is the abstract representation of `EMOTES`. The address is:

```
0x3110735F0b8e71455bAe1356a33e428843bCb9A1
```

## Rationale

Designing the proposal, we considered the following questions:

1. **Does the proposal support custom emotes or only the Unicode specified ones?**\
The proposal only accepts the Unicode identifier which is a `string` value. This means that while we encourage implementers to add the reactions using standardized emojis, the values not covered by the Unicode standard can be used for custom emotes. The only drawback being that the interface displaying the reactions will have to know what kind of image to render and such additions will probably be limited to the interface or marketplace in which they were made.
2. **Should the proposal use emojis to relay the impressions of NFTs or some other method?**\
The impressions could have been done using user-supplied strings or numeric values, yet we decided to use emojis since they are a well established mean of relaying impressions and emotions.
3. **Should the proposal establish an emotable extension or a common-good repository?**\
Initially we set out to create an emotable extension to be used with any ERC-721 compliant tokens. However, we realized that the proposal would be more useful if it was a common-good repository of emotable tokens. This way, the tokens that can be reacted to are not only the new ones but also the old ones that have been around since before the proposal.\
In line with this decision, we decided to calculate a deterministic address for the repository smart contract. This way, the repository can be used by any NFT collection without the need to search for the address on the given chain.
4. **Should we include only single-action operations, only multi-action operations, or both?**\
We&apos;ve considered including only single-action operations, where the user is only able to react with a single emoji to a single token, but we decided to include both single-action and multi-action operations. This way, the users can choose whether they want to emote or undo emote on a single token or on multiple tokens at once.\
This decision was made for the long-term viability of the proposal. Based on the gas cost of the network and the number of tokens in the collection, the user can choose the most cost-effective way of emoting.
5. **Should we add the ability to emote on someone else&apos;s behalf?**\
While we did not intend to add this as part of the proposal when drafting it, we realized that it would be a useful feature for it. This way, the users can emote on behalf of someone else, for example, if they are not able to do it themselves or if the emote is earned through an off-chain activity.
6. **How do we ensure that emoting on someone else&apos;s behalf is legitimate?**\
We could add delegates to the proposal; when a user delegates their right to emote to someone else, the delegate can emote on their behalf. However, this would add a lot of complexity and additional logic to the proposal.\
Using ECDSA signatures, we can ensure that the user has given their consent to emote on their behalf. This way, the user can sign a message with the parameters of the emote and the signature can be submitted by someone else.
7. **Should we add chain ID as a parameter when reacting to a token?**\
During the course of discussion of the proposal, a suggestion arose that we could add chain ID as a parameter when reacting to a token. This would allow the users to emote on the token of one chain on another chain.\
We decided against this as we feel that additional parameter would rarely be used and would add additional cost to the reaction transactions. If the collection smart contract wants to utilize on-chain emotes to tokens they contain, they require the reactions to be recorded on the same chain. Marketplaces and wallets integrating this proposal will rely on reactions to reside in the same chain as well, because if chain ID parameter was supported this would mean that they would need to query the repository smart contract on all of the chains the repository is deployed in order to get the reactions for a given token.\
Additionally, if the collection creator wants users to record their reactions on a different chain, they can still direct the users to do just that. The repository does not validate the existence of the token being reacted to, which in theory means that you can react to non-existent token or to a token that does not exist yet. The likelihood of a different collection existing at the same address on another chain is significantly low, so the users can react using the collection&apos;s address on another chain and it is very unlikely that they will unintentionally react to another collection&apos;s token.
8. **Should we use `bytes4` or `strings` to represent emotes?**\
Initially the proposal used `bytes4`. This was due to the assumption that all of the emojis use UTF-4 encoding, which is not the case.\
The emojis usually use up to 8 bytes, but the personalized emojis with skin tones use much more. This is why we decided to use `strings` to represent the emotes. This allows the repository to be forward compatible with any future emojis that might be added to the Unicode standard.\
This is how this proposal fixes the forward compatibility issue of the [ERC-6381](/EIPs/EIPS/eip-6381).

## Backwards Compatibility

The Emote repository standard is fully compatible with [ERC-721](/EIPs/EIPS/eip-721) and with the robust tooling available for implementations of ERC-721 as well as with the existing ERC-721 infrastructure.

## Test Cases

Tests are included in [`emotableRepository.ts`](/EIPs/assets/eip-7409/test/emotableRepository.ts).

To run them in terminal, you can use the following commands:

```
cd ../assets/eip-7409
npm install
npx hardhat test
```

## Reference Implementation

See [`EmotableRepository.sol`](/EIPs/assets/eip-7409/contracts/EmotableRepository.sol).

## Security Considerations

The proposal does not envision handling any form of assets from the user, so the assets should not be at risk when interacting with an Emote repository.

The ability to use ECDSA signatures to emote on someone else&apos;s behalf introduces the risk of a replay attack, which the format of the message to be signed guards against. The `DOMAIN_SEPARATOR` used in the message to be signed is unique to the repository smart contract of the chain it is deployed on. This means that the signature is invalid on any other chain and the Emote repositories deployed on them should revert the operation if a replay attack is attempted.

Another thing to consider is the ability of presigned message reuse. Since the message includes the signature validity deadline, the message can be reused any number of times before the deadline is reached. The proposal only allows for a single reaction with a given emoji to a specific token to be active, so the presigned message can not be abused to increase the reaction count on the token. However, if the service using the repository relies on the ability to revoke the reaction after certain actions, a valid presigned message can be used to re-react to the token. We suggest that the services using the repository in conjunction with presigned messages use deadlines that invalidate presigned messages after a reasonably short period of time.

Caution is advised when dealing with non-audited contracts.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 26 Jul 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7409</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7409</guid>
      </item>
    
      <item>
        <title>ERC-20 Update Allowance By Spender</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7410-decrease-allowance-by-spender/15222</comments>
        
        <description>## Abstract

This extension adds a `decreaseAllowanceBySpender` function to decrease [ERC-20](/EIPs/EIPS/eip-20) allowances, in which a spender can revoke or decrease a given allowance by a specific address. This ERC extends [ERC-20](/EIPs/EIPS/eip-20).

## Motivation

Currently, [ERC-20](/EIPs/EIPS/eip-20) tokens offer allowances, enabling token owners to authorize spenders to use a designated amount of tokens on their behalf. However, the process of decreasing an allowance is limited to the owner&apos;s side, which can be problematic if the token owner is a treasury wallet or a multi-signature wallet that has granted an excessive allowance to a spender. In such cases, reducing the allowance from the owner&apos;s perspective can be time-consuming and challenging.

To address this issue and enhance security measures, this ERC proposes allowing spenders to decrease or revoke the granted allowance from their end. This feature provides an additional layer of security in the event of a potential hack in the future. It also eliminates the need for a consensus or complex procedures to decrease the allowance from the token owner&apos;s side.

## Specification

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.

Contracts using this ERC MUST implement the `IERC7410` interface.

### Interface implementation

```solidity
pragma solidity ^0.8.0;

/**
 * @title IERC-7410 Update Allowance By Spender Extension
 * Note: the ERC-165 identifier for this interface is 0x12860fba
 */
interface IERC7410 is IERC20 {

    /**
     * @notice Decreases any allowance by `owner` address for caller.
     * Emits an {IERC20-Approval} event.
     *
     * Requirements:
     * - when `subtractedValue` is equal or higher than current allowance of spender the new allowance is set to 0.
     * Nullification also MUST be reflected for current allowance being type(uint256).max.
     */
    function decreaseAllowanceBySpender(address owner, uint256 subtractedValue) external;

}
```

The `decreaseAllowanceBySpender(address owner, uint256 subtractedValue)` function MUST be either `public` or `external`.

The `Approval` event MUST be emitted when `decreaseAllowanceBySpender` is called.

The `supportsInterface` method MUST return `true` when called with `0x12860fba`.

## Rationale

The technical design choices within this ERC are driven by the following considerations:

- The introduction of the `decreaseAllowanceBySpender` function empowers spenders by allowing them to autonomously revoke or decrease allowances. This design choice aligns with the goal of providing more direct control to spenders over their authorization levels.
- The requirement for the `subtractedValue` to be lower than the current allowance ensures a secure implementation. Additionally, nullification is achieved by setting the new allowance to 0 when `subtractedValue` is equal to or exceeds the current allowance. This approach adds an extra layer of security and simplifies the process of decreasing allowances.
- The decision to maintain naming patterns similar to [ERC-20](/EIPs/EIPS/eip-20)&apos;s approvals is rooted in promoting consistency and ease of understanding for developers familiar with [ERC-20](/EIPs/EIPS/eip-20) standard.

## Backwards Compatibility

This standard is compatible with [ERC-20](/EIPs/EIPS/eip-20).

## Test Cases

Test cases for the reference implementation cover the following scenarios:

- Spender calls `decreaseAllowanceBySpender` with a value less than current allowance, verifying the allowance is reduced by exactly `subtractedValue` and an `Approval` event is emitted with the new allowance
- Spender calls `decreaseAllowanceBySpender` with a value equal to current allowance, verifying the new allowance is set to 0
- Spender calls `decreaseAllowanceBySpender` with a value greater than current allowance, verifying the new allowance is set to 0 (nullification)
- Spender calls `decreaseAllowanceBySpender` when current allowance is `type(uint256).max`, verifying the allowance is set to 0 regardless of `subtractedValue`
- Spender calls `decreaseAllowanceBySpender` when no allowance exists (allowance is 0), verifying the call succeeds with allowance remaining at 0
- Verifying `supportsInterface` returns `true` for `0x12860fba`
- Verifying `supportsInterface` returns `false` for unsupported interface IDs

## Reference Implementation

A minimal implementation is included [here](/EIPs/assets/eip-7410/ERC7410.sol).

## Security Considerations

Users of this ERC must thoroughly consider the amount of tokens they decrease from their allowance for an `owner`.

### Spender Griefing

A malicious spender could call `decreaseAllowanceBySpender` to nullify an allowance that the owner intentionally granted. This is by design - the spender already has the ability to spend the tokens, so revoking that ability is strictly less harmful. However, integrators relying on stable allowances for scheduled operations (e.g., recurring payments) should be aware that the spender can unilaterally cancel future transfers.

### Interaction with Infinite Approvals

When an owner sets allowance to `type(uint256).max` (infinite approval), calling `decreaseAllowanceBySpender` with any value MUST set the allowance to 0. Spenders should be aware that partial decreases are not possible on infinite approvals - any call results in full revocation.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 26 Jul 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7410</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7410</guid>
      </item>
    
      <item>
        <title>On-Demand Off-Chain Data Retrieval</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7412-on-demand-off-chain-data-retrieval/15346</comments>
        
        <description>## Abstract

Contracts may require off-chain data during execution. A smart contract function could implement the standard proposed here by reverting with `error OracleDataRequired(address oracleContract, bytes oracleQuery, uint256 feeRequired)`. Clients supporting this standard would recognize this error message during a simulation of the request, query the specified decentralized oracle network for signed data, and instead stage a transaction with a multicall that prepends the verification of the required off-chain data. The data would be written on-chain during verification to a smart contract for the subsequent call to read, avoiding the error.

## Motivation

Ethereum&apos;s scaling roadmap involves a series of separate execution contexts for smart contract code (including layer two and layer three scaling solutions). This makes the ability to read data across multiple chains crucial to the construction of scalable applications. Also, for decentralized finance protocols that rely on price data, it is not reasonable to expect oracle networks will be able to continuously push fresh data to every layer two and layer three network for an arbitrary number of price feeds.

Cross-chain bridges are being developed where smart contract functions can write data to other chains. There is a need for a similar standard that enables reading data from other chains. This standard can be generalized for reading any off-chain data from a decentralized oracle network, including price feeds.

With standards for both writing and reading cross-chain data, protocol developers will be able to create abstractions for asynchronicity (a topic thoroughly explored in other software engineering contexts). This will enable the development of highly sophisticated protocols that do not suffer from scaling constraints.

[ERC-3668](/EIPs/EIPS/eip-3668) introduced the use of reverts for requiring off-chain data, but there are various challenges introduced by the specifics of that standard which are outlined in the _Rationale_ section below. By leveraging multicalls rather than callback functions, the standard proposed here is able to overcome some of these constraints.

## Specification

A contract implementing this standard MUST revert with the following error whenever off-chain data is required:

```solidity
error OracleDataRequired(address oracleContract, bytes oracleQuery, uint256 feeRequired)
```

`oracleQuery` specifies the off-chain data that is being required. Valid data formats for this parameter are specific to the oracle ID specified by the oracle contract. This might include chain id, contract address, function signature, payload, and timestamp/&quot;latest&quot; for cross-chain reads. For price feeds, it could include a ticker symbol and timestamp/&quot;latest&quot;.

`oracleContract` is the address of the contract which can verify the off-chain data and provide it to the contract to avoid the `OracleDataRequired` error. This contract MUST implement the following interface:

```solidity
interface IERC7412 {
  function oracleId() view external returns (bytes32 oracleId);
  function fulfillOracleQuery(bytes signedOffchainData) payable external;
}
```

`oracleId` is a unique identifier that references the decentralized oracle network that generates the desired signed off-chain data. Oracle IDs would be analogous to Chain IDs in the Ethereum ecosystem. Clients are expected to resolve a gateway that corresponds to an Oracle ID, similar to how clients are expected to resolve an RPC endpoint based on a Chain ID.

It should be possible to derive the `oracleQuery` from the `signedOffchainData`, such that the oracle contract is able to provide the verified offchain data based on the `oracleQuery`.

The contract implementing the `IERC7412` interface MUST revert with the following error message if it requires payment to fulfill the oracle data query:

```solidity
error FeeRequired(uint amount)
```

`amount` specifies the amount of native gas tokens required to execute the `fulfillOracleQuery` function, denominated in wei. This error MUST be resolved if the caller provides sufficient `msg.value` such that the fee amount can be collected by the oracle contract. The contract MAY NOT return gas tokens if they are provided in excess of the `amount`. In practice, we would expect the fee amount to remain relatively stable, if not constant.

Additionally, to optimize for scenarios where multiple oracle data requests are needed (such as protocols requiring many price feeds simultaneously), the interface MAY include an error for batching multiple errors:

```solidity
error Errors(bytes[] errors);
```

This allows clients to efficiently handle multiple `OracleDataRequired` errors in a single transaction simulation, reducing the number of separate requests needed. When encountering this error, clients should parse each error in the array and handle them accordingly, potentially using recursion for nested error objects.

It is the responsibility of the client to decide how to construct the multicall, where necessary the `fulfillOracleQuery` functions are being called before the intended function call in an atomic transaction. Wallets that support account abstraction (per [ERC-4337](/EIPs/EIPS/eip-4337)) should already have the ability to generate atomic multi-operations. For EOA support, protocols could implement [ERC-2771](/EIPs/EIPS/eip-2771). A standard multicall contract can only be used to construct multicalls including functions which do not reference `msg.sender` or `msg.data`.

Note that `URI` could be used as the `oracleId` with a URI specified as the `oracleQuery`. This would allow this standard to be compliant with arbitrary on-chain URIs without requiring updates to a client library, similar to [ERC-3668](/EIPs/EIPS/eip-3668).

## Rationale

This proposal is essentially an alternative to [ERC-3668](/EIPs/EIPS/eip-3668) with a couple notable distinctions:

- The error is very simple to construct. Developers implementing this standard only need to have awareness of the oracle network they choose to rely on, the form of the query accepted by this network, and the contract from which they expect to retrieve the data.
- By relying on a multicall rather than callbacks, it is much simpler to handle situations in which nested calls require different off-chain data. By the standard proposed here, end users (including those using clients that implement account abstraction) always need to simply sign a transaction, regardless of the complexity of the internal structure of the call being executed. The client can automatically prepend any necessary off-chain data to the transaction for the call to succeed.

With this standard, not only can oracle providers scalably support an unlimited number of networks but they can also be compatible with local/forked networks for protocol development.

Another major advantage of this standard is that oracles can charge fees in the form of native gas tokens during the on-chain verification of the data. This creates an economic incentive where fees can be collected from data consumers and provided to node operators in the decentralized oracle network.

## Reference Implementation

The following pseudocode illustrates an oversimplified version of the client SDK. Ideally, this could be implemented in wallets, but it could also be built into the application layer. This function takes a desired transaction and converts it into a multicall with the required data verification transactions prepended such that the `OracleDataRequired` errors would be avoided:

```javascript
function prepareTransaction(originalTx) {
  let multicallTx = [originalTx];
  while (true) {
    try {
      const simulationResult = simulateTx(multicallTx);
      return multicallTx;
    } catch (error) {
      if (error instanceof OracleDataRequired) {
        const signedRequiredData = fetchOffchainData(
          error.oracleContract,
          error.oracleQuery
        );
        const dataVerificationTx = generateDataVerificationTx(
          error.oracleContract,
          signedRequiredData
        );
        multicallTx.unshift(dataVerificationTx);
      }
    }
  }
}
```

An oracle provider could create a contract (that might also perform some pre-processing) that would automatically trigger a request for off-chain data as follows:

```solidity
contract OracleContract is IERC7412 {
  address public constant VERIFIER_CONTRACT = 0x0000;
  uint public constant STALENESS_TOLERANCE = 86400; // One day
  mapping(bytes32 =&gt; bytes) public latestVerifiedData;

  function oracleId() external pure returns (bytes32){
    return bytes32(abi.encodePacked(&quot;MY_ORACLE_ID&quot;));
  }

  function fulfillOracleQuery(bytes calldata signedOffchainData) payable external {
    bytes memory oracleQuery = _verify(signedOffchainData);
    latestVerifiedData[keccak256(oracleQuery)] = signedOffchainData;
  }

  function retrieveCrossChainData(uint chainId, address contractAddress, bytes payload) internal returns (bytes) {
    bytes memory oracleQuery = abi.encode(chainId, contractAddress, payload);
    (uint timestamp, bytes response) = abi.decode(latestVerifiedData[oracleQuery], (uint, bytes));

    if(timestamp &lt; block.timestamp - STALENESS_TOLERANCE){
      revert OracleDataRequired(address(this), oracleQuery, 0);
    }

    return response;
  }

  function _verify(bytes memory signedOffchainData) payable internal returns (bytes oracleQuery) {
    // Insert verification code here
    // This may revert with error FeeRequired(uint amount)
  }

}
```

Now a top-level protocol smart contract could implement a cross-chain function like so:

```solidity
interface ICrosschainContract {
  function functionA(uint x) external returns (uint y);
  function functionB(uint x) external returns (uint y);
}

contract CrosschainAdder {
  IERC7412 oracleContract = 0x0000;

  function add(uint chainIdA, address contractAddressA, uint chainIdB, address contractAddressB) external returns (uint sum){
    sum = abi.decode(oracleContract.retrieveCrossChainData(chainIdA, contractAddressA, abi.encodeWithSelector(ICrosschainContract.functionA.selector,1)), (uint)) + abi.decode(oracleContract.retrieveCrossChainData(chainIdB, contractAddressB, abi.encodeWithSelector(ICrosschainContract.functionB.selector,2)),(uint));
  }
}
```

Note that the developer of the `CrosschainAdder` function does not need to be concerned with the implementation of this standard. The `add` function can simply call the function on the oracle contract as if it were retrieving on-chain data normally.

Cross-chain functions like this could also be leveraged to avoid O(n) (and greater) loops on-chain. For example, `chainIdA` and `chainIdB` could reference the same chain that the `CrosschainAdder` contract is deployed on with `functionA` and `functionB` as view functions with computationally intensive loops.

## Security Considerations

One potential risk introduced by this standard is that its reliance on multicalls could obfuscate transaction data in wallet applications that do not have more sophisticated transaction decoding functionality. This is an existing challenge being addressed by wallet application developers, as multicalls are increasingly common in protocol development outside of this standard.

Note that it is the responsibility of the verifier contract to confirm the validity of the data provided from the oracle network. This standard does not create any new opportunities for invalid data to be provided to a smart contract.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 26 Jul 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7412</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7412</guid>
      </item>
    
      <item>
        <title>Token Converter</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/token-standard-converter/15252</comments>
        
        <description>## Abstract

There are multiple token standards on Ethereum chain currently. This EIP introduces a concept of cross-standard interoperability by creating a service that allows [ERC-20](/EIPs/EIPS/eip-20) tokens to be upgraded to [ERC-223](/EIPs/EIPS/eip-223) tokens anytime. [ERC-223](/EIPs/EIPS/eip-223) tokens can be converted back to [ERC-20](/EIPs/EIPS/eip-20) version without any restrictions to avoid any problems with backwards compatibility and allow different standards to co-exist and become interoperable and interchangeable.

In order to perform the conversion, a user must deposit tokens of one standard to the Converter contract and it will automatically send tokens of another standard back.

## Motivation

This proposal introduces a concept of a token standard upgrading procedure driven by a specialized smart-contract which can convert tokens of one standard to another at any time.

Currently some tokens are available on different chains in different standards, for example most exchanges support [ERC-20](/EIPs/EIPS/eip-20) USDT, TRX USDT, BEP-20 USDT and all this tokens are in fact the same USDT token. This proposal is intended to introduce a concept where there can be a [ERC-20](/EIPs/EIPS/eip-20) USDT and [ERC-223](/EIPs/EIPS/eip-223) USDT available on Ethereum mainnet at the same time and these would be freely interchangeable.

The address of the deployed Token Converter must be described here as to solve the trust issues for the token developers and help them figure out a proper way of interacting with the Converter.

As Ethereum already has an established ecosystem of tokens and [ERC-20](/EIPs/EIPS/eip-20) is the most adopted standard at the moment the lack of defined migration processes can be a bottleneck for newer standards adoption. This proposal addresses the problem of coordinating the upgrading process and addresses the backwards compatibility problems for [ERC-20](/EIPs/EIPS/eip-20) and [ERC-223](/EIPs/EIPS/eip-223) tokens.

The Token Converter is supposed to allow anyone to create an alternative version of an existing token implemented in a different standard. This proposal focuses on [ERC-20](/EIPs/EIPS/eip-20) and [ERC-223](/EIPs/EIPS/eip-223) standards and takes into account the specifics of this particular token standards. It is assumed that the most common case would be creation of [ERC-223](/EIPs/EIPS/eip-223) version for an existing [ERC-20](/EIPs/EIPS/eip-20) token.

The implementation of this service is an alternative to convincing each token developer to choose an alternative standard at the moment of the token deployment or during the development stage of their project. With this service there will be no need to choose one standard and stick with it as every token can be available in both concurrently.

The implementation of this Token Converter service is supposed to be a contract deployed on Ethereum mainnet once and forever. It&apos;s address will be provided in the text of this proposal as to avoid any potential trust issues and assure the developers that the service they are interacting with is exactly the one which drives the conversion process of existing tokens.

All the [ERC-223](/EIPs/EIPS/eip-223) tokens created by the Token Converter will be identical in a way that they all implement the same functions, which return the same values and there is no ambiguity there. This helps to avoid problems where a token deployed during the early stage of a token standard adoption may implement it improperly or there can be an ambiguity in the standard itself that would allow developers to implement tokens of one standard in different ways. 

For example it was a common case with [ERC-20](/EIPs/EIPS/eip-20) where developers could implement custom logic of the `transfer` function and mess the return values. The [ERC-20](/EIPs/EIPS/eip-20) specification declares that a `transfer` function MUST return a `bool` value, however in practice we have three different types of [ERC-20](/EIPs/EIPS/eip-20) tokens which are not compatible with each other:

1. [ERC-20](/EIPs/EIPS/eip-20) tokens that return `true` on success and revert on an error.
2. [ERC-20](/EIPs/EIPS/eip-20) tokens that return `true` on success and `false` on an error without reverting the transaction.
3. [ERC-20](/EIPs/EIPS/eip-20) tokens that don&apos;t have return values and revert on an error.

Technically the third category of tokens is not compatible with [ERC-20](/EIPs/EIPS/eip-20) standard. However, USDT token deployed on Ethereum mainnet at `0xdac17f958d2ee523a2206206994597c13d831ec7` address does not implement return values and it is one of the most used tokens and it is not an option to deny supporting USDT due to it&apos;s improper implementation of the standard.

The Token Converter eliminates the issue where different development teams may implement the standard with slight modifications and result in a situation where we would have different versions of the same standard on the mainnet.

At the same time the Converter enables the concurrent token support in other smart-contracts, such as decentralized exchanges. The Converter can guarantee that a pair of two tokens one of which is a wrapper for another is in fact the same token that can be converted from one standard to another at any time. This enables the creation of liquidity pools where two different tokens are dealt with as if they were one token.

## Specification

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

The Token Converter system comprises two main components:

- Converter contract.

- Wrapper contracts. Each original token can have exactly one wrapper of each standard.

Converter contract can deploy new [ERC-223](/EIPs/EIPS/eip-223) wrapper contracts for any [ERC-20](/EIPs/EIPS/eip-20) token that does not have a [ERC-223](/EIPs/EIPS/eip-223) wrapper currently. There MUST be exactly one [ERC-223](/EIPs/EIPS/eip-223) wrapper for each [ERC-20](/EIPs/EIPS/eip-20) token.

Converter contract MUST accept deposits of [ERC-20](/EIPs/EIPS/eip-20) tokens and send [ERC-223](/EIPs/EIPS/eip-223) tokens to the depositor at 1:1 ratio. Upon depositing 1234 units of `ERC20 token_A` the depositor MUST receive exactly 1234 units of `ERC223 token_A`. This is done by issuing new [ERC-223](/EIPs/EIPS/eip-223) tokens at the moment of [ERC-20](/EIPs/EIPS/eip-20) deposit. The original [ERC-20](/EIPs/EIPS/eip-20) tokens MUST be frozen in the Converter contract and available for claiming back.

Converter contract MUST accept deposits of [ERC-223](/EIPs/EIPS/eip-223) tokens and send [ERC-20](/EIPs/EIPS/eip-20) tokens to the depositor at 1:1 ratio. This is done by releasing the original [ERC-20](/EIPs/EIPS/eip-20) tokens at the moment of [ERC-223](/EIPs/EIPS/eip-223) deposit. The deposited [ERC-223](/EIPs/EIPS/eip-223) tokens must be burned.

### Token Converter

#### Conver contract methods

##### `getERC20WrapperFor`

```solidity
function getERC20WrapperFor(address _token) public view returns (address)
```

Returns the address of the [ERC-20](/EIPs/EIPS/eip-20) wrapper for a given token address. Returns `0x0` if there is no [ERC-20](/EIPs/EIPS/eip-20) version for the provided token address. There can be exactly one wrapper for any given [ERC-223](/EIPs/EIPS/eip-223) token address created by the Token Converter contract.

##### `getERC223WrapperFor`

```solidity
function getERC223WrapperFor(address _token) public view returns (address)
```

Returns the address of the [ERC-223](/EIPs/EIPS/eip-223) wrapper for a given token address. Returns `0x0` if there is no [ERC-223](/EIPs/EIPS/eip-223) version for the provided token address. There can be exactly one [ERC-223](/EIPs/EIPS/eip-223) wrapper for any given [ERC-20](/EIPs/EIPS/eip-20) token address created by the Token Converter contract.

##### `getERC20OriginFor`

```solidity
function getERC20OriginFor(address _erc223Token) public view returns (address)
```

Returns the address of the original [ERC-20](/EIPs/EIPS/eip-20) token for the provided [ERC-223](/EIPs/EIPS/eip-223) wrapper. Returns `0x0` if the provided `_erc223Token` is not an address of any [ERC-223](/EIPs/EIPS/eip-223) wrapper created by the Token Converter contract.

##### `getERC223OriginFor`

```solidity
function getERC223OriginFor(address _erc20Token) public view returns (address)
```

Returns the address of the original [ERC-223](/EIPs/EIPS/eip-223) token for the provided [ERC-20](/EIPs/EIPS/eip-20) wrapper. Returns `0x0` if the provided `_erc20Token` is not an address of any wrapper created by the Token Converter contract.

##### `predictWrapperAddress`

```solidity
function predictWrapperAddress(address _token,
                                   bool    _isERC20 // Is the provided _token a ERC-20 or not?
                                                    // If it is set as ERC-20 then we will predict the address of a 
                                                    // ERC-223 wrapper for that token.
                                                    // Otherwise we will predict ERC-20 wrapper address.
                                  ) view external returns (address)
```

Wrapper contracts are deployed via `CREATE2` opcode and it is possible to predict the address of a wrapper which is not yet deployed. The address of a wrapper contract depends on the bytecode therefore it is necessary to specify if the address of wrapper [ERC-20](/EIPs/EIPS/eip-20) or wrapper [ERC-223](/EIPs/EIPS/eip-223) must be predicted.

Providing `_token` address and `_isERC20 = false` will result in [ERC-20](/EIPs/EIPS/eip-20) wrapper address being predicted.

Providing `_token` address and `_isERC20 = true` will result in [ERC-223](/EIPs/EIPS/eip-223) wrapper address being predicted.

##### `createERC223Wrapper`

```solidity
function createERC223Wrapper(address _erc20Token) public returns (address)
```

Creates a new [ERC-223](/EIPs/EIPS/eip-223) wrapper for a given `_erc20Token` if it does not exist yet. Reverts the transaction if the wrapper already exist. Returns the address of the new wrapper token contract on success.  Reverts if `_erc223Token` is a wrapper created by the Converter.

The deployed contract will be a standard [ERC-223](/EIPs/EIPS/eip-223) token with `approve` and `transferFrom` functions implemented for backwards compatibility.

All [ERC-223](/EIPs/EIPS/eip-223) wrappers deployed by the Converter will have `standard() pure returns (bytes32)` function implemented which returns `223`. This serves further token standard introspection as [ERC-165](/EIPs/EIPS/eip-165) may not be reliable when dealing with identifying the internal logic implemented within `transfer` function of a token.

NOTE: This function does not verify the standard of `_erc20Token` because there is no reliable method of introspection available which could guarantee that the provided token implements a particular standard. As the result it is possible to create a [ERC-223](/EIPs/EIPS/eip-223) wrapper for an original [ERC-223](/EIPs/EIPS/eip-223) token.

##### `createERC20Wrapper`

```solidity
function createERC20Wrapper(address _erc223Token) public returns (address)
```

Creates a new [ERC-20](/EIPs/EIPS/eip-20) wrapper for a given `_erc223Token` if it does not exist yet. Reverts the transaction if the wrapper already exist. Returns the address of the new wrapper token contract on success. Reverts if `_erc223Token` is a wrapper created by the Converter.

NOTE: This function does not verify the standard of `_erc223Token` because there is no reliable method of introspection available which could guarantee that the provided token implements a particular standard. As the result it is possible to create a [ERC-20](/EIPs/EIPS/eip-20) wrapper for an original [ERC-20](/EIPs/EIPS/eip-20) token.

##### `wrapERC20toERC223`

```solidity
function wrapERC20toERC223(address _ERC20token, uint256 _amount) public returns (bool)
```

Withdraws `_amount` of [ERC-20](/EIPs/EIPS/eip-20) tokens from the transaction sender with `transferFrom` function. Delivers the `_amount` of [ERC-223](/EIPs/EIPS/eip-223) wrapper tokens to the sender of the transaction. Stores the original tokens at the balance of the Token Converter contract for future claims. Returns `true` on success. The Token Converter must keep record of the amount of [ERC-20](/EIPs/EIPS/eip-20) tokens that were deposited with `wrapERC20toERC223` function because it is possible to deposit [ERC-20](/EIPs/EIPS/eip-20) tokens to any contract by directly sending them with `transfer` function.

If there is no [ERC-223](/EIPs/EIPS/eip-223) wrapper for the `_ERC20token` then creates it by calling a `createERC223Wrapper(_erc20toke)` function.

There is no special function to unwrap [ERC-223](/EIPs/EIPS/eip-223) wrappers to [ERC-20](/EIPs/EIPS/eip-20) origin as this logic is implemented in the `tokenReceived` function of the Converter.

##### `unwrapERC20toERC223`

```solidity
function unwrapERC20toERC223(address _ERC20token, uint256 _amount) public returns (bool)
```

Withdraws `_amount` of [ERC-20](/EIPs/EIPS/eip-20) tokens from the transaction sender with `transferFrom` function. Delivers the `_amount` of [ERC-223](/EIPs/EIPS/eip-223) wrapper tokens to the sender of the transaction. Stores the original tokens at the balance of the Token Converter contract for future claims. Returns `true` on success. The Token Converter must keep record of the amount of [ERC-20](/EIPs/EIPS/eip-20) tokens that were deposited with `wrapERC20toERC223` function because it is possible to deposit [ERC-20](/EIPs/EIPS/eip-20) tokens to any contract by directly sending them with `transfer` function.

If there is no [ERC-223](/EIPs/EIPS/eip-223) wrapper for the `_ERC20token` then creates it by calling a `createERC223Wrapper(_erc20toke)` function.


##### `convertERC20`

```solidity
function convertERC20(address _token, uint256 _amount) public returns (bool)
```

Automatically determines if the provided [ERC-20](/EIPs/EIPS/eip-20) token is a wrapper or not. If it is a wrapper then executes `unwrapERC20toERC223` function. If the provided token is an origin then executes `wrapERC20toERC223` function.

This function is implemented to significantly simplify the workflow of services that integrate both versions of one token in the same contract and need to automatically convert tokens through the Converter.

##### `isWrapper`

```solidity
function isWrapper(address _token) public view returns (bool)
```

Returns `true` if the provided `_token` address is an address of a wrapper created by the Converter.

NOTE: This function does not identify the standard of a `_token`. There can be exactly one origin for any wrapper created by the Converter. However an original token can have two wrappers, one of each standard.

##### `tokenReceived`

```solidity
function tokenReceived(address _from, uint _value, bytes memory _data) public override returns (bytes4)
```

This is a standard [ERC-223](/EIPs/EIPS/eip-223) transaction handler function and it is called by the [ERC-223](/EIPs/EIPS/eip-223) token contract when `_from` is sending `_value` of [ERC-223](/EIPs/EIPS/eip-223) tokens to `address(this)` address. In the scope of this function `msg.sender` is the address of the [ERC-223](/EIPs/EIPS/eip-223) token contract and `_from` is the sender of the token transfer.

Automatically determines 

If `msg.sender` is an address of [ERC-223](/EIPs/EIPS/eip-223) wrapper created by the Token Converter then `_value` of [ERC-20](/EIPs/EIPS/eip-20) original token must be sent to the `_from` address.

If `msg.sender` is not an address of any [ERC-223](/EIPs/EIPS/eip-223) wrapper known to the Token Converter then it is considered a [ERC-223](/EIPs/EIPS/eip-223) origin and `_value` amount of [ERC-20](/EIPs/EIPS/eip-20) wrapper tokens must be sent to the `_from` address. If the [ERC-20](/EIPs/EIPS/eip-20) wrapper for the `msg.sender` token does not exist then create it first.

Returns `0x8943ec02`.

##### `extractStuckERC20`

```solidity
function extractStuckERC20(address _token)
```

This function allows to extract the [ERC-20](/EIPs/EIPS/eip-20) tokens that were directly deposited to the contract with `transfer` function to prevent users who may send tokens by mistake from permanently losing their tokens. Since the Token Converter calculates the amount of tokens that were deposited legitimately with `convertERC20toERC223` function it is always possible to calculate the amount of &quot;accidentally deposited tokens&quot; by subtracting the recorded amount from the returned value of the `balanceOf( address(this) )` function called on the [ERC-20](/EIPs/EIPS/eip-20) token contract.

### Converting [ERC-20](/EIPs/EIPS/eip-20) tokens to [ERC-223](/EIPs/EIPS/eip-223)

In order to convert [ERC-20](/EIPs/EIPS/eip-20) tokens to [ERC-223](/EIPs/EIPS/eip-223) the token holder should:

1. Call the `approve` function of the [ERC-20](/EIPs/EIPS/eip-20) token and allow Token Converter to withdraw tokens from the token holders address via `transferFrom` function.
2. Wait for the transaction with `approve` to be submitted to the blockchain.
3. Call the `convertERC20toERC223` function of the Token Converter contract.

### Converting [ERC-223](/EIPs/EIPS/eip-223) wrapper tokens back to [ERC-20](/EIPs/EIPS/eip-20)

In order to convert [ERC-20](/EIPs/EIPS/eip-20) tokens to [ERC-223](/EIPs/EIPS/eip-223) the token holder should:

1. Send [ERC-223](/EIPs/EIPS/eip-223) tokens to the address of the Token Converter contract via `transfer` function of the [ERC-223](/EIPs/EIPS/eip-223) token contract.

## Rationale

### Support of [ERC-223](/EIPs/EIPS/eip-223) original tokens

Two methods of implementing a Token Converter service were considered: (1) a converter that can only create [ERC-223](/EIPs/EIPS/eip-223) versions of the existing [ERC-20](/EIPs/EIPS/eip-20) tokens, and (2) a converter that can create both versions ([ERC-20](/EIPs/EIPS/eip-20) and [ERC-223](/EIPs/EIPS/eip-223)) of any original token.

The first approach would encourage developers to always deploy an original token as [ERC-20](/EIPs/EIPS/eip-20) and then create it&apos;s [ERC-223](/EIPs/EIPS/eip-223) version in the converter. If it would happen that some developers may consider [ERC-223](/EIPs/EIPS/eip-223) as their original standard then they would be left with the problem of creating their custom [ERC-20](/EIPs/EIPS/eip-20) version of the token. In addition, if any third party contracts like liquidity pools are using the proposed Token Converter to ensure that a token can be listed on a DEX with two versions and both can be combined within one pool - then such contract would not be able to recognize any original [ERC-223](/EIPs/EIPS/eip-223) token and it&apos;s [ERC-20](/EIPs/EIPS/eip-20) version as a valid pair of contracts that represent one token available in two standards.

For that reason it was decided to go with the second approach where the Converter can create [ERC-20](/EIPs/EIPS/eip-20) wrappers for original [ERC-223](/EIPs/EIPS/eip-223) tokens.

### Support of `approve` &amp; `transferFrom` functions in the [ERC-223](/EIPs/EIPS/eip-223) wrapper tokens

This functions are superfluous for a [ERC-223](/EIPs/EIPS/eip-223) token since the `transfer` function can be used to deposit tokens of this standard to contracts. The current ecosystem is built for [ERC-20](/EIPs/EIPS/eip-20) tokens however and there are plenty of multisig contracts that rely on accepting tokens deposited without any callback with an assumption that it is not necessary for a multisig to count the amount of tokens it stores.

There can be any other contracts and scenarios where it would be necessary to deposit a token to a contract which is relying on an assumption that tokens are deposited without invoking a callback in the recipient. As the result we can expect that any original deployed [ERC-223](/EIPs/EIPS/eip-223) tokens will support this functions, as token developers strive for backward compatibility with the existing ecosystem. In order to make tokens deployed by the converter a reference implementation for developers that can be used without any modifications it was decided to support this functions in the [ERC-223](/EIPs/EIPS/eip-223) wrapper contracts.

`transferFrom` function does not support error handling and this needs to be taken into account. It is possible to deposit tokens to a contract which is not designed to receive them by approving X tokens to your own address and then calling a `transferFrom(self, contract, X)`. The tokens will be deposited regardless of whether the recipient contract is designed to hold/receive tokens or not. The tokens may get permanently stuck if the recipient contract did not implement the extraction functions. The `approve` &amp; `transferFrom` function is not the default method of token transferring however and it is not directly used by any wallets and any other software that manages tokens. The `transfer` function (which is safe) is used instead. The `transferFrom` function is supposed to be invoked by a contract to pull tokens from the approver.

As the result, the `approve` &amp; `transferFrom` transferring method must be avoided with [ERC-223](/EIPs/EIPS/eip-223) tokens whenever possible.

### Modified transfer events of the [ERC-223](/EIPs/EIPS/eip-223) token

The pure [ERC-223](/EIPs/EIPS/eip-223) token implementation has the following event emitted on a token transfer: `event Transfer(address indexed _from, address indexed _to, uint256 _value, bytes _data)`. This events are different from ones emitted by [ERC-20](/EIPs/EIPS/eip-20) tokens and may not be properly recognized by existing blockchain explorers, wallets and other services that browse token transfers history.

It was considered that events are not an important part of the standard as these do not affect the logic of the token, it&apos;s workflow and it&apos;s security. When developing the Converter it was decided to prioritize compatibility with existing ecosystem.

### `standard()` function usage for the introspection

The main existing method of introspection is currently [ERC-165](/EIPs/EIPS/eip-165) which inspects the signatures of functions implemented in a contract. It is not possible to differentiate an [ERC-20](/EIPs/EIPS/eip-20) token from an [ERC-223](/EIPs/EIPS/eip-223) token by just browsing functions that they implement without digging their internal logic.

Here is a token and it is not possible to identify if it should be dealt with as [ERC-20](/EIPs/EIPS/eip-20) or [ERC-223](/EIPs/EIPS/eip-223) because it depends on the actual implementation of it&apos;s `transfer` function logic.

```solidity
abstract contract Token {
    function name() external virtual returns (string memory);
    function symbol() external virtual returns (string memory);
    function decimals() external virtual returns (uint8);

    function transfer(address, uint256) external virtual returns (bool);
    function approve(address, uint256) external virtual returns (bool);
    function transferFrom(address, address, uint256) external virtual returns (bool);
}
```

In case of this implementation the token will behave as [ERC-20](/EIPs/EIPS/eip-20):

```solidity
    function transfer(address _to, uint256 _amount) external virtual returns (bool)
    {
        balances[msg.sender] -= _amount;
        balances[_to] += _amount;
    }
}
```

In case of this implementation the token will behave as [ERC-223](/EIPs/EIPS/eip-223):

```solidity
    function transfer(address _to, uint256 _amount) external virtual returns (bool)
    {
        balances[msg.sender] -= _amount;
        balances[_to] += _amount;
        if(_to.isContract())
        {
            IERC223Recipient(_to).tokenReceived(msg.sender, _amount, hex&quot;000000&quot;);
        }
    }
}
```

Also, there are plenty of tokens that do not implement [ERC-165](/EIPs/EIPS/eip-165) introspection at all. As the result it was decided to implement a special `standard() returns (uint32)` function in all [ERC-223](/EIPs/EIPS/eip-223) wrappers created by the Converter and assume that original [ERC-223](/EIPs/EIPS/eip-223) tokens may explicitly declare themselves as [ERC-223](/EIPs/EIPS/eip-223) by implementing the same function too. It is assumed that if a token does not implement this function then it is [ERC-20](/EIPs/EIPS/eip-20).

This method of token standard introspection is more precise than [ERC-165](/EIPs/EIPS/eip-165).

## Backwards Compatibility

This proposal is supposed to eliminate the backwards compatibility concerns for different token standards making them interchangeable and interoperable.

This service is the first of its kind and therefore does not have any backwards compatibility issues as it does not have any predecessors.

## Reference Implementation

```solidity


pragma solidity =0.8.19;

library Address {
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size &gt; 0;
    }
}

interface IERC20 {
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address recipient, uint256 amount) external returns (bool);
    function allowance(address owner, address spender) external view returns (uint256);
    function approve(address spender, uint256 amount) external returns (bool);
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

interface IERC20Metadata is IERC20 {
    /// @return The name of the token
    function name() external view returns (string memory);

    /// @return The symbol of the token
    function symbol() external view returns (string memory);

    /// @return The number of decimal places the token has
    function decimals() external view returns (uint8);
}

abstract contract IERC223Recipient {
    function tokenReceived(address _from, uint _value, bytes memory _data) public virtual returns (bytes4)
    {
        return 0x8943ec02;
    }
}

abstract contract ERC165 {
    /*
     * bytes4(keccak256(&apos;supportsInterface(bytes4)&apos;)) == 0x01ffc9a7
     */
    bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
    mapping(bytes4 =&gt; bool) private _supportedInterfaces;

    constructor () {
        // Derived contracts need only register support for their own interfaces,
        // we register support for ERC165 itself here
        _registerInterface(_INTERFACE_ID_ERC165);
    }
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return _supportedInterfaces[interfaceId];
    }
    function _registerInterface(bytes4 interfaceId) internal virtual {
        require(interfaceId != 0xffffffff, &quot;ERC165: invalid interface id&quot;);
        _supportedInterfaces[interfaceId] = true;
    }
}

abstract contract IERC223 {
    function name()        public view virtual returns (string memory);
    function symbol()      public view virtual returns (string memory);
    function decimals()    public view virtual returns (uint8);
    function totalSupply() public view virtual returns (uint256);
    function balanceOf(address who) public virtual view returns (uint);
    function transfer(address to, uint value) public virtual returns (bool success);
    function transfer(address to, uint value, bytes calldata data) public payable virtual returns (bool success);
    event Transfer(address indexed from, address indexed to, uint value, bytes data);
}

interface standardERC20
{
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address to, uint256 value) external returns (bool);
    function allowance(address owner, address spender) external view returns (uint256);
    function approve(address spender, uint256 value) external returns (bool);
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

/**
 * @dev Interface of the ERC20 standard.
 */
interface IERC223WrapperToken {
    function name()     external view returns (string memory);
    function symbol()   external view returns (string memory);
    function decimals() external view returns (uint8);
    function standard() external view returns (string memory);
    function origin()   external  view returns (address);

    function totalSupply()                                            external view returns (uint256);
    function balanceOf(address account)                               external view returns (uint256);
    function transfer(address to, uint256 value)                      external payable returns (bool);
    function transfer(address to, uint256 value, bytes calldata data) external payable returns (bool);
    function allowance(address owner, address spender)                external view returns (uint256);
    function approve(address spender, uint256 value)                  external returns (bool);
    function transferFrom(address from, address to, uint256 value)    external returns (bool);

    function mint(address _recipient, uint256 _quantity) external;
    function burn(address _recipient, uint256 _quantity) external;
}

interface IERC20WrapperToken {
    function name()     external view returns (string memory);
    function symbol()   external view returns (string memory);
    function decimals() external view returns (uint8);
    function standard() external view returns (string memory);
    function origin()   external  view returns (address);

    function totalSupply()                                         external view returns (uint256);
    function balanceOf(address account)                            external view returns (uint256);
    function transfer(address to, uint256 value)                   external returns (bool);
    function allowance(address owner, address spender)             external view returns (uint256);
    function approve(address spender, uint256 value)               external returns (bool);
    function transferFrom(address from, address to, uint256 value) external returns (bool);

    function mint(address _recipient, uint256 _quantity) external;
    function burn(address _recipient, uint256 _quantity) external;
}

contract ERC20Rescue
{
    // ERC20 tokens can get stuck on a contracts balance due to lack of error handling.
    //
    // The author of the ERC7417 can extract ERC20 tokens if they are mistakenly sent
    // to the wrapper-contracts balance.
    // Contact dexaran@ethereumclassic.org
    address public extractor = 0x01000B5fE61411C466b70631d7fF070187179Bbf;
    
    function safeTransfer(address token, address to, uint value) internal {
        // bytes4(keccak256(bytes(&apos;transfer(address,uint256)&apos;)));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
        require(success &amp;&amp; (data.length == 0 || abi.decode(data, (bool))), &apos;TransferHelper: TRANSFER_FAILED&apos;);
    }

    function rescueERC20(address _token, uint256 _amount) external 
    {
        safeTransfer(_token, extractor, _amount);
    }
}

contract ERC223WrapperToken is IERC223, ERC165, ERC20Rescue
{
    address public creator = msg.sender;
    address private wrapper_for;

    mapping(address account =&gt; mapping(address spender =&gt; uint256)) private allowances;

    event Transfer(address indexed from, address indexed to, uint256 amount);
    event TransferData(bytes data);
    event Approval(address indexed owner, address indexed spender, uint256 amount);

    function set(address _wrapper_for) external
    {
        require(msg.sender == creator);
        wrapper_for = _wrapper_for;
    }

    uint256 private _totalSupply;

    mapping(address =&gt; uint256) private balances; // List of user balances.

    function totalSupply() public view override returns (uint256)             { return _totalSupply; }
    function balanceOf(address _owner) public view override returns (uint256) { return balances[_owner]; }


    /**
     * @dev The ERC165 introspection function.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return
            interfaceId == type(IERC20).interfaceId ||
            interfaceId == type(standardERC20).interfaceId ||
            interfaceId == type(IERC223WrapperToken).interfaceId ||
            interfaceId == type(IERC223).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /**
     * @dev Standard ERC223 transfer function.
     *      Calls _to if it is a contract. Does not transfer tokens to contracts
     *      which do not explicitly declare the tokenReceived function.
     * @param _to    - transfer recipient. Can be contract or EOA.
     * @param _value - the quantity of tokens to transfer.
     * @param _data  - metadata to send alongside the transaction. Can be used to encode subsequent calls in the recipient.
     */
    function transfer(address _to, uint _value, bytes calldata _data) public payable override returns (bool success)
    {
        balances[msg.sender] = balances[msg.sender] - _value;
        balances[_to] = balances[_to] + _value;
        if (msg.value &gt; 0) 
        {
            (bool sent, bytes memory data) = _to.call{value: msg.value}(&quot;&quot;);
            require(sent);
        }
        if(Address.isContract(_to)) {
            IERC223Recipient(_to).tokenReceived(msg.sender, _value, _data);
        }
        emit Transfer(msg.sender, _to, _value, _data);
        emit Transfer(msg.sender, _to, _value); // Old ERC20 compatible event. Added for backwards compatibility reasons.

        return true;
    }

    /**
     * @dev Standard ERC223 transfer function without _data parameter. It is supported for 
     *      backwards compatibility with ERC20 services.
     *      Calls _to if it is a contract. Does not transfer tokens to contracts
     *      which do not explicitly declare the tokenReceived function.
     * @param _to    - transfer recipient. Can be contract or EOA.
     * @param _value - the quantity of tokens to transfer.
     */
    function transfer(address _to, uint _value) public override returns (bool success)
    {
        bytes memory _empty = hex&quot;00000000&quot;;
        balances[msg.sender] = balances[msg.sender] - _value;
        balances[_to] = balances[_to] + _value;
        if(Address.isContract(_to)) {
            IERC223Recipient(_to).tokenReceived(msg.sender, _value, _empty);
        }
        emit Transfer(msg.sender, _to, _value, _empty);
        emit Transfer(msg.sender, _to, _value); // Old ERC20 compatible event. Added for backwards compatibility reasons.

        return true;
    }

    function name() public view override returns (string memory)   { return IERC20Metadata(wrapper_for).name(); }
    function symbol() public view override returns (string memory) { return string.concat(IERC20Metadata(wrapper_for).symbol(), &quot;223&quot;); }
    function decimals() public view override returns (uint8)       { return IERC20Metadata(wrapper_for).decimals(); }
    function standard() public pure returns (uint32)               { return 223; }
    function origin() public view returns (address)                { return wrapper_for; }


    /**
     * @dev Minting function which will only be called by the converter contract.
     * @param _recipient - the address which will receive tokens.
     * @param _quantity  - the number of tokens to create.
     */
    function mint(address _recipient, uint256 _quantity) external
    {
        require(msg.sender == creator, &quot;Wrapper Token: Only the creator contract can mint wrapper tokens.&quot;);
        balances[_recipient] += _quantity;
        _totalSupply += _quantity;
    }

    /**
     * @dev Burning function which will only be called by the converter contract.
     * @param _quantity  - the number of tokens to destroy. TokenConverter can only destroy tokens on it&apos;s own address.
     *                     Only the token converter is allowed to burn wrapper-tokens.
     */
    function burn(uint256 _quantity) external
    {
        require(msg.sender == creator, &quot;Wrapper Token: Only the creator contract can destroy wrapper tokens.&quot;);
        balances[msg.sender] -= _quantity;
        _totalSupply -= _quantity;
    }

    // ERC20 functions for backwards compatibility.

    function allowance(address owner, address spender) public view virtual returns (uint256) {
        return allowances[owner][spender];
    }

    function approve(address _spender, uint _value) public returns (bool) {
        require(_spender != address(0), &quot;ERC223: Spender error.&quot;);

        allowances[msg.sender][_spender] = _value;
        emit Approval(msg.sender, _spender, _value);

        return true;
    }

    function transferFrom(address _from, address _to, uint _value) public returns (bool) {

        require(allowances[_from][msg.sender] &gt;= _value, &quot;ERC223: Insufficient allowance.&quot;);

        balances[_from] -= _value;
        allowances[_from][msg.sender] -= _value;
        balances[_to] += _value;

        emit Transfer(_from, _to, _value);

        return true;
    }
}

contract ERC20WrapperToken is IERC20, ERC165, ERC20Rescue
{
    address public creator = msg.sender;
    address public wrapper_for;

    mapping(address account =&gt; mapping(address spender =&gt; uint256)) private allowances;

    function set(address _wrapper_for) external
    {
        require(msg.sender == creator);
        wrapper_for = _wrapper_for;
    }

    uint256 private _totalSupply;
    mapping(address =&gt; uint256) private balances; // List of user balances.


    function balanceOf(address _owner) public view override returns (uint256) { return balances[_owner]; }

    function name()        public view  returns (string memory) { return IERC20Metadata(wrapper_for).name(); }
    function symbol()      public view  returns (string memory) { return string.concat(IERC223(wrapper_for).symbol(), &quot;20&quot;); }
    function decimals()    public view  returns (uint8)         { return IERC20Metadata(wrapper_for).decimals(); }
    function totalSupply() public view override returns (uint256)       { return _totalSupply; }
    function origin()      public view returns (address)                { return wrapper_for; }

    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return
            interfaceId == type(IERC20).interfaceId ||
            interfaceId == type(IERC20WrapperToken).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    function transfer(address _to, uint _value) public override returns (bool success)
    {
        balances[msg.sender] = balances[msg.sender] - _value;
        balances[_to] = balances[_to] + _value;
        emit Transfer(msg.sender, _to, _value);
        return true;
    }

    function mint(address _recipient, uint256 _quantity) external
    {
        require(msg.sender == creator, &quot;Wrapper Token: Only the creator contract can mint wrapper tokens.&quot;);
        balances[_recipient] += _quantity;
        _totalSupply += _quantity;
    }

    function burn(address _from, uint256 _quantity) external
    {
        require(msg.sender == creator, &quot;Wrapper Token: Only the creator contract can destroy wrapper tokens.&quot;);
        balances[_from] -= _quantity;
        _totalSupply    -= _quantity;
    }

    function allowance(address owner, address spender) public view virtual returns (uint256) {
        return allowances[owner][spender];
    }

    function approve(address _spender, uint _value) public returns (bool) {

        // Safety checks.

        require(_spender != address(0), &quot;ERC20: Spender error.&quot;);

        allowances[msg.sender][_spender] = _value;
        emit Approval(msg.sender, _spender, _value);

        return true;
    }

    function transferFrom(address _from, address _to, uint _value) public returns (bool) {

        require(allowances[_from][msg.sender] &gt;= _value, &quot;ERC20: Insufficient allowance.&quot;);

        balances[_from] -= _value;
        allowances[_from][msg.sender] -= _value;
        balances[_to] += _value;

        emit Transfer(_from, _to, _value);

        return true;
    }
}

contract TokenStandardConverter is IERC223Recipient
{
    event ERC223WrapperCreated(address indexed _token, address indexed _ERC223Wrapper);
    event ERC20WrapperCreated(address indexed _token, address indexed _ERC20Wrapper);

    mapping (address =&gt; ERC223WrapperToken) public erc223Wrappers; // A list of token wrappers. First one is ERC20 origin, second one is ERC223 version.
    mapping (address =&gt; ERC20WrapperToken)  public erc20Wrappers;

    mapping (address =&gt; address)            public erc223Origins;
    mapping (address =&gt; address)            public erc20Origins;
    mapping (address =&gt; uint256)            public erc20Supply; // Token =&gt; how much was deposited.

    function getERC20WrapperFor(address _token) public view returns (address)
    {
        return address(erc20Wrappers[_token]);
    }

    function getERC223WrapperFor(address _token) public view returns (address)
    {
        return address(erc223Wrappers[_token]);
    }

    function getERC20OriginFor(address _token) public view returns (address)
    {
        return (address(erc20Origins[_token]));
    }

    function getERC223OriginFor(address _token) public view returns (address)
    {
        return (address(erc223Origins[_token]));
    }

    function predictWrapperAddress(address _token,
                                   bool    _isERC20 // Is the provided _token a ERC20 or not?
                                                    // If it is set as ERC20 then we will predict the address of a 
                                                    // ERC223 wrapper for that token.
                                                    // Otherwise we will predict ERC20 wrapper address.
                                  ) view external returns (address)
    {
        bytes memory _bytecode;
        if(_isERC20)
        {
            _bytecode = type(ERC223WrapperToken).creationCode;
        }
        else
        {
            _bytecode = type(ERC20WrapperToken).creationCode;
        }

        bytes32 hash = keccak256(
            abi.encodePacked(
                bytes1(0xff), address(this), keccak256(abi.encode(_token)), keccak256(_bytecode)
          )
        );

        return address(uint160(uint(hash)));
    }

    function tokenReceived(address _from, uint _value, bytes memory /* _data */) public override returns (bytes4)
    {
        require(erc223Origins[msg.sender] == address(0), &quot;Error: creating wrapper for a wrapper token.&quot;);
        // There are two possible cases:
        // 1. A user deposited ERC223 origin token to convert it to ERC20 wrapper
        // 2. A user deposited ERC223 wrapper token to unwrap it to ERC20 origin.

        if(erc20Origins[msg.sender] != address(0))
        {
            // Origin for deposited token exists.
            // Unwrap ERC-223 wrapper.

            erc20Supply[erc20Origins[msg.sender]] -= _value;
            safeTransfer(erc20Origins[msg.sender], _from, _value);

            ERC223WrapperToken(msg.sender).burn(_value);

            return this.tokenReceived.selector;
        }
        // Otherwise origin for the sender token doesn&apos;t exist
        // There are two possible cases:
        // 1. ERC20 wrapper for the deposited token exists
        // 2. ERC20 wrapper for the deposited token doesn&apos;t exist and must be created.
        else if(address(erc20Wrappers[msg.sender]) == address(0))
        {
            // Create ERC-20 wrapper if it doesn&apos;t exist.
            createERC20Wrapper(msg.sender);
        }

        // Mint ERC-20 wrapper tokens for the deposited ERC-223 token
        // if the ERC-20 wrapper didn&apos;t exist then it was just created in the above statement.
        erc20Wrappers[msg.sender].mint(_from, _value);
        return this.tokenReceived.selector;
    }

    function createERC223Wrapper(address _token) public returns (address)
    {
        require(address(erc223Wrappers[_token]) == address(0), &quot;ERROR: Wrapper exists&quot;);
        require(!isWrapper(_token), &quot;Error: Creating wrapper for a wrapper token&quot;);
        
        ERC223WrapperToken _newERC223Wrapper     = new ERC223WrapperToken{salt: keccak256(abi.encode(_token))}();
        _newERC223Wrapper.set(_token);
        erc223Wrappers[_token]                   = _newERC223Wrapper;
        erc20Origins[address(_newERC223Wrapper)] = _token;

        emit ERC223WrapperCreated(_token, address(_newERC223Wrapper));
        return address(_newERC223Wrapper);
    }

    function createERC20Wrapper(address _token) public returns (address)
    {
        require(address(erc20Wrappers[_token]) == address(0), &quot;ERROR: Wrapper already exists.&quot;);
        require(!isWrapper(_token), &quot;Error: Creating wrapper for a wrapper token&quot;);

        ERC20WrapperToken _newERC20Wrapper       = new ERC20WrapperToken{salt: keccak256(abi.encode(_token))}();
        _newERC20Wrapper.set(_token);
        erc20Wrappers[_token]                    = _newERC20Wrapper;
        erc223Origins[address(_newERC20Wrapper)] = _token;

        emit ERC20WrapperCreated(_token, address(_newERC20Wrapper));
        return address(_newERC20Wrapper);
    }

    function wrapERC20toERC223(address _ERC20token, uint256 _amount) public returns (bool)
    {
        // If there is no active wrapper for a token that user wants to wrap
        // then create it.
        if(address(erc223Wrappers[_ERC20token]) == address(0))
        {
            createERC223Wrapper(_ERC20token);
        }
        uint256 _converterBalance = IERC20(_ERC20token).balanceOf(address(this)); // Safety variable.
        safeTransferFrom(_ERC20token, msg.sender, address(this), _amount);

        _amount = IERC20(_ERC20token).balanceOf(address(this)) - _converterBalance;
        erc20Supply[_ERC20token] += _amount;

        erc223Wrappers[_ERC20token].mint(msg.sender, _amount);

        return true;
    }

    function unwrapERC20toERC223(address _ERC20token, uint256 _amount) public returns (bool)
    {
        require(IERC20(_ERC20token).balanceOf(msg.sender) &gt;= _amount, &quot;Error: Insufficient balance.&quot;);
        require(erc223Origins[_ERC20token] != address(0), &quot;Error: provided token is not a ERC-20 wrapper.&quot;);

        ERC20WrapperToken(_ERC20token).burn(msg.sender, _amount);

        safeTransfer(erc223Origins[_ERC20token], msg.sender, _amount);

        return true;
    }

    function convertERC20(address _token, uint256 _amount) public returns (bool)
    {
        if(isWrapper(_token)) return unwrapERC20toERC223(_token, _amount);
        else return wrapERC20toERC223(_token, _amount);
    }

    function isWrapper(address _token) public view returns (bool)
    {
        return erc20Origins[_token] != address(0) || erc223Origins[_token] != address(0);
    }

    function extractStuckERC20(address _token) external 
    {
        require(msg.sender == address(0x01000B5fE61411C466b70631d7fF070187179Bbf));

        safeTransfer(_token, address(0x01000B5fE61411C466b70631d7fF070187179Bbf), IERC20(_token).balanceOf(address(this)) - erc20Supply[_token]);
    }
    
    function safeTransfer(address token, address to, uint value) internal {
        // bytes4(keccak256(bytes(&apos;transfer(address,uint256)&apos;)));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
        require(success &amp;&amp; (data.length == 0 || abi.decode(data, (bool))), &apos;TransferHelper: TRANSFER_FAILED&apos;);
    }

    function safeTransferFrom(address token, address from, address to, uint value) internal {
        // bytes4(keccak256(bytes(&apos;transferFrom(address,address,uint256)&apos;)));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
        require(success &amp;&amp; (data.length == 0 || abi.decode(data, (bool))), &apos;TransferHelper: TRANSFER_FROM_FAILED&apos;);
    }
}
```

## Security Considerations

1. While it is possible to implement a service that converts any token standard to any other standard - it is better to keep different standard convertors separate from one another as different standards may contain specific logic and therefore require different conversion approach. This proposal focuses on [ERC-20](/EIPs/EIPS/eip-20) and [ERC-223](/EIPs/EIPS/eip-223) upgradeability.
2. [ERC-20](/EIPs/EIPS/eip-20) tokens can be deposited to any contract directly with `transfer` function. This may result in a permanent loss of tokens because it is not possible to recognize this transaction on the recipients side. Therefore wrapper-ERC-20 tokens are prone to this problem as they are compatible with the [ERC-20](/EIPs/EIPS/eip-20) standard. `rescueERC20` function is implemented to address this problem.
3. Token Converter relies on [ERC-20](/EIPs/EIPS/eip-20) `approve` &amp; `transferFrom` method of depositing assets. Any related issues must be taken into account. `approve` and `transferFrom` are two separate transactions so it is required to make sure `approval` was successful before relying on `transferFrom`.
4. This is a common practice for UI services to prompt a user to issue unlimited `approval` on any contract that may withdraw tokens from the user. This puts users funds at risk and therefore is not recommended.
5. There is no reliable token standard introspection method available that could guarantee that a token implements a particular token standard. It is possible to artificially construct a token that will pretend it is a [ERC-20](/EIPs/EIPS/eip-20) token that implements `approve &amp; transferFrom` but at the same time implements [ERC-223](/EIPs/EIPS/eip-223) logic of transferring via `transfer` function. It can be possible to create a [ERC-223](/EIPs/EIPS/eip-223) wrapper for this [ERC-20](/EIPs/EIPS/eip-20)-[ERC-223](/EIPs/EIPS/eip-223) hybrid implementation in the Token Converter. This doesn&apos;t pose any threat for the workflow of the Token Converter itself but it must be taken into account that if a token has [ERC-223](/EIPs/EIPS/eip-223) wrapper in the Token Converter it does not automatically mean the origin is fully compatible with the [ERC-20](/EIPs/EIPS/eip-20) standard and methods of introspection must be used to determine the origins compatibility with any existing standard.
6. Token Converter does not verify the standard of a provided token when it is asked to create a wrapper for it due to the lack of reliable standard introspection method. It is possible to call `createERC20Wrapper` function and provide an address of an existing [ERC-20](/EIPs/EIPS/eip-20) token. The Token Converter will successfully create a [ERC-20](/EIPs/EIPS/eip-20) wrapper for that [ERC-20](/EIPs/EIPS/eip-20) original token. It is also possible to create a [ERC-223](/EIPs/EIPS/eip-223) wrapper for that exact original [ERC-20](/EIPs/EIPS/eip-20) token. This doesn&apos;t pose any threat to the workflow of the Converter but it must be taken into account that any token regardless of it&apos;s original standard may have up to two wrappers created by the Converter, one for each standard. Any wrapper token must have exactly one origin. It is not possible to create a wrapper for a wrapper.
7. The Token Converter only holds the original tokens that were deposited during the conversion process and it assumes that tokens do not decay over time and the token balance of the Converter does not decrease on its own. If some token implements burning logic or decaying supply and it may impact the balance of the Converter then the Converter must not be used to deploy an alternative version of that token as it will not be able to guarantee that there is enough tokens for the conversion at any time.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 27 Jul 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7417</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7417</guid>
      </item>
    
      <item>
        <title>Tokenized Reserve</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7425-tokenized-reserve/15297</comments>
        
        <description>## Abstract

This document describes a tokenized reserve mechanism. This includes functionality that allow stakeholders to participate in goverance stategies wthin the reserve.

## Motivation

Tokenized vaults store [ERC-20](/EIPs/EIPS/eip-20) tokens that are represented by shares within vault smart contracts. Implementations can follow the [ERC-4626](/EIPs/EIPS/eip-4626) standard to provide basic functionality for depositing, withdrawing, and reading balances for a vault. As tokenization becomes increasingly popular, there is a need for standard for how these vaults holding tokenized assets are audited. Applications could use tokenized vaults to store assets while allowing other interseted parties to purpose, restrict and track the events of the vault. 

This specification introduces a standard for an on-chain reserve that uses utilizes active stakeholders. Core functionality, which is an extension of [ERC-4626](/EIPs/EIPS/eip-4626), will allow stakehoolder representation in the form of depositing and withdrawing. The record of asset activity, represented by the underlying [ERC-20](/EIPs/EIPS/eip-20) token, wiil be easily accessible by party.

In a tokenized reserve, stakeholders mint shares from the vault when depositing the underlying token. The goal is to create a reserve similar to a real-world reserve fund used as a contingency for an entity. In the real world an entity agrees on some condition that would justify the use of funds, like when running low on regular funds. In a decentralized environment, an entity could incorporate stakeholders and replicate this mechanism. Assets associated with the reserve, including its origin and destination will vary in decentralized environments, so transparent auditing is needed.

## Specification

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


### Definitions:

	- owner: The creator of the reserve
	- user: Stakeholders participating in proposals
	- reserve: The assets held on the contract excluding the ERC4626 underlying token
	- proposal: Created by reserve owners or stakeholder to request withdrawals
 
### Constructor:
 
 	- name: ERC-20 token name
  	- ticker: ERC-20 ticker
   	- asset: ERC-4626 underlying ERC-20 address
	- rAuth: Authorized user, for cases utilizing more than one owner/ limiting owner withdrawals
	- rOwner: Owner of the Reserve

### Reserve Actions

The reserve will account for activity by all participants. 
Some criteria created by the owner is REQUIRED to onboard new stakeholders with the underlying `asset` of the [ERC-4626](/EIPs/EIPS/eip-4626) vault.
Each new proposal is recorded and its information SHOULD be retrievable by a call function.
The REQUIRED information includes the amount and address for a proposal.

A proposal MUST be open before the transfer of any tokens out of the reserve.
A `proposalOpen` MAY be requested by stakeholders or the owner.
Once opened a stakeholder MUST use `proposalDeposit` to represent support for the proposal.
 
### Interface
    
```solidity
import &quot;./ERC4626.sol&quot;;
    
interface TokenizedReserve is ERC4626{

	/**
	* @dev Event emitted after a new policy is created
	*/
	event policies(
	    	address indexed token,
	    	uint256 indexed policyNum,
	    	uint256 indexed amount,
			address recipient
	);

	/**
	* @dev Event emitted after a new deposit is made by the owner
	*/
	event depositR(
		address indexed token,
		uint256 indexed amount,
		uint256 indexed time,
		uint256 count
	);

	/** 
	* @dev Get time a deposit/withdrawal was made by the owner
	* @param count Number for deposit count
	* @return block.timestamp format
	*/
	function ownerTime(uint256 count) external view returns (uint256);

	/** 
	* @dev Get amount deposited to reserve by owner
	* @param count Number for deposit count
	* @param proposal The proposal number to deposit to
	* @return uint256 Amount of an asset that was deposited
	*/
	function ownerDeposit(uint256 count, uint256 proposal) external view returns(uint256);

	/**
	* @dev Amount withdrawn for a opened proposal by the owner
	* @param propoal The proposal number
	* @return Amount of ERC20
	*/
	function ownerWithdrawals(uint256 proposal) external view returns(uint256);

	/**
	* @dev Token type deposited to reserve by the owner
	* - MUST be an address of ERC20 token
	* @param count Number of deposit count
	* @return address Address of ERC20 token
	*/
	function tokenDeposit(uint256 count) external view returns(address);

	/**
	* @dev Token type withdrawn for an opened proposal by the owner
	* - MUST be ERC20 address
	* @param proposal The proposal number for the token used
	* @return Token ERC20 address
	*/
	function tokenWithdrawal(uint256 proposal) external view returns(address);

	/**
	* @dev User amount deposited to a proposal for shares
	* - MUST be an ERC20 token
	* @param user Address of user
	* @param proposal The proposal number the user deposited to
	* @return uint256 Amount of ERC20 deposited
	*/
	function userDeposit(address user, uint256 proposal) external view returns(uint256);

	/**
	* @dev Amount withdrawn from a proposal by the user
	* @param user The address of user
	* @param proposal The proposal number for user withdrawal
	* @param uint256 Amount of ERC20
	*/
	function userWithdrawals(address user, uint256 proposal) public view returns(uint256);


	/**
	* @dev Make a deposit to a proposal creating new shares using deposit() function from ERC4626
	* - MUST be opened proposal
	* - MUST NOT be opened proposal that was closed
	* - SHOULD be only method to deposit to ERC4626 vault
	* NOTE: using the deposit() will cause assets to not be accounted for in a proposal (see Security Considerations section)
	* @param assets Amount being deposited
	* @param receiver Address of depositor
	* @param proposal The number associated proposal
	* @return Amount of shares minted 
	*/
	function proposalDeposit(uint256 assets, address receiver, uint256 proposal) external returns(uint256);

	/**
	* @dev Burn shares, receive 1 to 1 value of shares using withdraw() function from ERC4626
	* - MUST have userDeposit greater than or equal to userWithdrawal
	* - SHOULD be only method for withdrawing underlying token from ERC4626 vault
	* @param assets Amount being deposited
	* @param receiver Address of receiver
	* @param owner Address of token owner
	* @param proposal Number associated proposal
	* @return Amount of the asset
	*/
	function proposalWithdraw(uint256 assets, address receiver, address owner, uint256 proposal)external returns(uint256);

	/**
	* @dev Issue new policy
	* - MUST create new policy number
	* - MUST account for amount withdrawn
	* - MUST be only method to withdraw ERC20 tokens owned by the reserve (excluding share tokens deposited in a proposal )
	* - MUST be owner
	* - SHOULD emit proposals event
	* @param token Address of ERC-20 token
	* @param amount Token amount being withdrawn
	* @param receiver Address of token recipient
	* @return The proposal number
	*/
	function openProposal(address token, uint256 amount, address receiver) external returns (uint256);

	/**
	* @dev Make a deposit and/or close an opened proposal
	* - MUST be owner
	* - MUST account for amount received
	* - SHOULD emit proposals event
	* @param token Address of ERC-20 token
	* @param proposal Number of the desired proposals
	* @param amount Token amount being deposited to the reserve
	* @param close Choose to close the proposal
	* @return true for closed proposal 
	*/
	function closeProposal(address token, uint256 proposal, uint256 amount, bool close) external returns (bool);

	/**
	* @dev Accounting for tokens deposited in the reserve
	* - MUST be reserve owner
	* - SHOULD emit depositR event
	* NOTE: No shares are issued, funds can not be redeemed and no proposal is opened. Withdrawnal made with openProposal function.
	* @param token Address of ERC-20 token being deposited
	* @param sender Address of token sender
	* @param amount Token amount being deposited 
	*/
	function depositReserve(address token, address sender, uint256 amount) external;
}
    
```

## Rationale

This proposed standard is designed to be a core implementation of a tokenized reserve interface. Other non-specified conditions should be addressed on a case-by-case basis. Each reserve uses [ERC-20](/EIPs/EIPS/eip-20) standard for shares, and [ERC-4626](/EIPs/EIPS/eip-4626) for the creation of shares. The underlying token MAY be considered to be termed as the reserve token and share token is minted by the [ERC-4626](/EIPs/EIPS/eip-4626) vault.
The [ERC-4626](/EIPs/EIPS/eip-4626) standard is used to create shares that represent stakeholder paticitapting in a proposal, thus within the reserve. There MUST be a representation of interested parties in the reserve. The implementer can decide how to treat representation based on users entering and leaving the vault. For example, a stakeholder could not ba able to use the same reserve token for multiple proposals, which could allow shares to be distributed fairly.  

## Backwards Compatibility

Tokenized reserves are made compatible with [ERC-20](/EIPs/EIPS/eip-20) and [ERC-4626](/EIPs/EIPS/eip-4626).

## Security Considerations

Tokenized reserves share the same security considerations as [ERC-20](/EIPs/EIPS/eip-20) and [ERC-4626](/EIPs/EIPS/eip-4626).
Including:

1. Assests withdrawn by owner are not secured by vaults.
- Stakeholders SHOULD be aware that the underlying `asset` stored on a contract can be withdrawn by the owner with no restrictions or authorizing party, like requiring an `rAuth`. Depending on the authorizing implementation, the `asset` could still be withdrawn by the owner.

A RECOMMENDED implementation:
- The `openProposal` MUST explictly restrict the transfer of the underlying `asset`.
- If the underlying asset is owned by the reserve and not the vault(within a proposal),
the reserve MUST account for the difference to avoid user `asset` loss.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 30 Jun 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7425</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7425</guid>
      </item>
    
      <item>
        <title>Non-Fungible Token Roles</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7432-non-fungible-token-roles/15298</comments>
        
        <description>## Abstract

This standard introduces role management for NFTs. Each role assignment is associated with a single NFT and expires
automatically at a given timestamp. Roles are defined as `bytes32` and feature a custom `data` field of arbitrary size
to allow customization.

## Motivation

The NFT Roles interface aims to establish a standard for role management in NFTs. Tracking on-chain roles enables
decentralized applications (dApps) to implement access control for privileged actions, e.g., minting tokens with a role
(airdrop claim rights).

NFT roles can be deeply integrated with dApps to create a utility-sharing mechanism. A good example is in digital real
estate. A user can create a digital property NFT and grant a `keccak256(&quot;PropertyManager()&quot;)` role to another user,
allowing them to delegate specific utility without compromising ownership. The same user could also grant a
`keccak256(&quot;PropertyTenant(uint256)&quot;)` role to other users, allowing the recipient to access and interact with the
digital property.

There are also interesting use cases in decentralized finance (DeFi). Insurance policies could be issued as NFTs, and 
the beneficiaries, insured, and insurer could all be on-chain roles tracked using this standard.

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;,
&quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC-2119 and RFC-8174.

Compliant contracts MUST implement the following interface:

```solidity
/// @title ERC-7432 Non-Fungible Token Roles
/// @dev See https://eips.ethereum.org/EIPS/eip-7432
/// Note: the ERC-165 identifier for this interface is 0xd00ca5cf.
interface IERC7432 /* is ERC165 */ {
  struct Role {
    bytes32 roleId;
    address tokenAddress;
    uint256 tokenId;
    address recipient;
    uint64 expirationDate;
    bool revocable;
    bytes data;
  }

  /** Events **/

  /// @notice Emitted when an NFT is locked (deposited or frozen).
  /// @param _owner The owner of the NFT.
  /// @param _tokenAddress The token address.
  /// @param _tokenId The token identifier.
  event TokenLocked(address indexed _owner, address indexed _tokenAddress, uint256 _tokenId);

  /// @notice Emitted when a role is granted.
  /// @param _tokenAddress The token address.
  /// @param _tokenId The token identifier.
  /// @param _roleId The role identifier.
  /// @param _owner The user assigning the role.
  /// @param _recipient The user receiving the role.
  /// @param _expirationDate The expiration date of the role.
  /// @param _revocable Whether the role is revocable or not.
  /// @param _data Any additional data about the role.
  event RoleGranted(
    address indexed _tokenAddress,
    uint256 indexed _tokenId,
    bytes32 indexed _roleId,
    address _owner,
    address _recipient,
    uint64 _expirationDate,
    bool _revocable,
    bytes _data
  );

  /// @notice Emitted when a role is revoked.
  /// @param _tokenAddress The token address.
  /// @param _tokenId The token identifier.
  /// @param _roleId The role identifier.
  event RoleRevoked(address indexed _tokenAddress, uint256 indexed _tokenId, bytes32 indexed _roleId);

  /// @notice Emitted when an NFT is unlocked (withdrawn or unfrozen).
  /// @param _owner The original owner of the NFT.
  /// @param _tokenAddress The token address.
  /// @param _tokenId The token identifier.
  event TokenUnlocked(address indexed _owner, address indexed _tokenAddress, uint256 indexed _tokenId);

  /// @notice Emitted when a user is approved to manage roles on behalf of another user.
  /// @param _tokenAddress The token address.
  /// @param _operator The user approved to grant and revoke roles.
  /// @param _isApproved The approval status.
  event RoleApprovalForAll(address indexed _tokenAddress, address indexed _operator, bool indexed _isApproved);

  /** External Functions **/

  /// @notice Grants a role to a user.
  /// @dev Reverts if sender is not approved or the NFT owner.
  /// @param _role The role attributes.
  function grantRole(Role calldata _role) external;

  /// @notice Revokes a role from a user.
  /// @dev Reverts if sender is not approved or the original owner.
  /// @param _tokenAddress The token address.
  /// @param _tokenId The token identifier.
  /// @param _roleId The role identifier.
  function revokeRole(address _tokenAddress, uint256 _tokenId, bytes32 _roleId) external;

  /// @notice Unlocks NFT (transfer back to original owner or unfreeze it).
  /// @dev Reverts if sender is not approved or the original owner.
  /// @param _tokenAddress The token address.
  /// @param _tokenId The token identifier.
  function unlockToken(address _tokenAddress, uint256 _tokenId) external;

  /// @notice Approves operator to grant and revoke roles on behalf of another user.
  /// @param _tokenAddress The token address.
  /// @param _operator The user approved to grant and revoke roles.
  /// @param _approved The approval status.
  function setRoleApprovalForAll(address _tokenAddress, address _operator, bool _approved) external;

  /** View Functions **/

  /// @notice Retrieves the original owner of the NFT.
  /// @param _tokenAddress The token address.
  /// @param _tokenId The token identifier.
  /// @return owner_ The owner of the token.
  function ownerOf(address _tokenAddress, uint256 _tokenId) external view returns (address owner_);

  /// @notice Retrieves the recipient of an NFT role.
  /// @param _tokenAddress The token address.
  /// @param _tokenId The token identifier.
  /// @param _roleId The role identifier.
  /// @return recipient_ The user that received the role.
  function recipientOf(
    address _tokenAddress,
    uint256 _tokenId,
    bytes32 _roleId
  ) external view returns (address recipient_);

  /// @notice Retrieves the custom data of a role assignment.
  /// @param _tokenAddress The token address.
  /// @param _tokenId The token identifier.
  /// @param _roleId The role identifier.
  /// @return data_ The custom data of the role.
  function roleData(
    address _tokenAddress,
    uint256 _tokenId,
    bytes32 _roleId
  ) external view returns (bytes memory data_);

  /// @notice Retrieves the expiration date of a role assignment.
  /// @param _tokenAddress The token address.
  /// @param _tokenId The token identifier.
  /// @param _roleId The role identifier.
  /// @return expirationDate_ The expiration date of the role.
  function roleExpirationDate(
    address _tokenAddress,
    uint256 _tokenId,
    bytes32 _roleId
  ) external view returns (uint64 expirationDate_);

  /// @notice Verifies whether the role is revocable.
  /// @param _tokenAddress The token address.
  /// @param _tokenId The token identifier.
  /// @param _roleId The role identifier.
  /// @return revocable_ Whether the role is revocable.
  function isRoleRevocable(
    address _tokenAddress,
    uint256 _tokenId,
    bytes32 _roleId
  ) external view returns (bool revocable_);

  /// @notice Verifies if the owner approved the operator.
  /// @param _tokenAddress The token address.
  /// @param _owner The user that approved the operator.
  /// @param _operator The user that can grant and revoke roles.
  /// @return Whether the operator is approved.
  function isRoleApprovedForAll(
    address _tokenAddress,
    address _owner,
    address _operator
  ) external view returns (bool);
}
```

### Metadata Extension

The Roles Metadata extension extends the traditional JSON-based metadata schema of NFTs. Therefore, DApps supporting
this feature MUST also implement the metadata extension of [ERC-721](/EIPs/EIPS/eip-721). This extension is **optional** and allows
developers to provide additional information for roles.

Updated Metadata Schema:

```js
{
  
  /** Existing NFT Metadata **/

  &quot;title&quot;: &quot;Asset Metadata&quot;,
  &quot;type&quot;: &quot;object&quot;,
  &quot;properties&quot;: {
    &quot;name&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Identifies the asset to which this NFT represents&quot;
    },
    &quot;description&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Describes the asset to which this NFT represents&quot;
    },
    &quot;image&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive&quot;
    }
  },
  
  /** Additional fields for Roles **/

  &quot;roles&quot;: [
    {
      &quot;id&quot;: {
        &quot;type&quot;: &quot;bytes32&quot;,
        &quot;description&quot;: &quot;Identifies the role&quot;
      },
      &quot;name&quot;: {
        &quot;type&quot;: &quot;string&quot;,
        &quot;description&quot;: &quot;Human-readable name of the role&quot;
      },
      &quot;description&quot;: {
        &quot;type&quot;: &quot;string&quot;,
        &quot;description&quot;: &quot;Describes the role&quot;
      },
      &quot;inputs&quot;: [
        {
          &quot;name&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Human-readable name of the argument&quot;
          },
          &quot;type&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Solidity type, e.g., uint256 or address&quot;
          }
        }
      ]
    }
  ]
  
}
```

The following JSON is an example of [ERC-7432](/EIPs/EIPS/eip-7432) Metadata:

```js
{
  // ... Existing NFT Metadata
  
  &quot;roles&quot;: [
    {
      // keccak256(&quot;PropertyManager()&quot;)
      &quot;id&quot;: &quot;0x76be0ffb73d8cd9e8fa76c28632ebbc3865a8ec7a0b6acab6ac589a1c88dd301&quot;,
      &quot;name&quot;: &quot;Property Manager&quot;,
      &quot;description&quot;: &quot;The manager of the property is responsible for furnishing it and ensuring its good condition.&quot;,
      &quot;inputs&quot;: []
    },
    {
      // keccak256(&quot;PropertyTenant(uint256)&quot;)
      &quot;id&quot;: &quot;0x17dfc8ea82661b71bd62ce0bd9db3858dd8f3e8ab9799d6ab468ec64f1be21a5&quot;,
      &quot;name&quot;: &quot;Property Tenant&quot;,
      &quot;description&quot;: &quot;The tenant of the property is responsible for paying the rent and keeping the property in good condition.&quot;,
      &quot;inputs&quot;: [
        {
          &quot;name&quot;: &quot;rent&quot;,
          &quot;type&quot;: &quot;uint256&quot;
        }
      ]
    }
  ]
  
}
```

The `roles` array properties are SUGGESTED, and developers should add any other relevant information as necessary (e.g.,
an image for the role). It&apos;s also important to highlight the importance of the `inputs` property. This field describes
the parameters that should be encoded and passed to the `grantRole` function. It&apos;s RECOMMENDED to use the properties
`type` and `components` defined on the Solidity ABI Specification, where `type` is the canonical type of the parameter,
and `components` is used for complex tuple types.

### Caveats

* Compliant contracts MUST implement the `IERC7432` interface.
* A role is represented by a `bytes32`, and it&apos;s RECOMMENDED to use the `keccak256` of the role&apos;s name with its inputs:
  `bytes32 roleId = keccak256(&quot;RoleName(input_type)&quot;)`.
* The `grantRole` function MUST revert if the `expirationDate` is in the past or if the `msg.sender` is not approved to
  grant roles on behalf of the NFT owner. It MAY be implemented as `public` or `external`.
* In addition to emitting the `RoleGranted` event, the `grantRole` function MUST emit a `TokenLocked` event if the token
  is frozen or transferred to an escrow account.
* The `revokeRole` function MUST revert if the `msg.sender` is not approved to revoke roles on behalf of the original
  NFT owner or the `recipient`. It MAY be implemented as `public` or `external`.
* If `revocable` is false, only the `recipient` can revoke the role. If `revocable` is true, both the `recipient` and
  the original NFT owner can revoke the role.
* The `unlockToken` function MUST revert if the `msg.sender` is not approved, or if there is at least one non-revocable
  role not expired. It MAY be implemented as `public` or `external`.
* The `setRoleApprovalForAll` function MAY be implemented as `public` or `external`.
* The `ownerOf` function MAY be implemented as `pure` or `view`, and MUST return the address of the original owner of
  the NFT.
* The `recipientOf` function MAY be implemented as `pure` or `view`, and MUST return the address of the account that
  received the role.
* The `roleData` function MAY be implemented as `pure` or `view`, and MUST return the encoded data passed to the
  `grantRole` function.
* The `roleExpirationDate` function MAY be implemented as `pure` or `view`, and MUST return the expiration date of a
  given role.
* The `isRoleRevocable` function MAY be implemented as `pure` or `view`, and MUST return whether the role is revocable.
* The `isRoleApprovedForAll` function MAY be implemented as `pure` or `view`, and SHOULD only return `true` if the
  `_operator` is approved to grant and revoke roles on behalf of the original NFT owner.
* Compliant contracts SHOULD implement [ERC-165](/EIPs/EIPS/eip-165).

## Rationale

[ERC-7432](/EIPs/EIPS/eip-7432) IS NOT an extension of [ERC-721](/EIPs/EIPS/eip-721). The main reason behind this decision is to
enable it to be implemented externally or on the same contract as the NFT, allowing dApps to implement roles with
immutable assets. This standard covers many crucial features, such as automatic expiration and custom data, but perhaps
the most important one is its flexibility in implementation. ERC-7432 can be implemented in many ways, and for this
reason, the neutral term &quot;lock&quot; is employed. This term can refer to an NFT being frozen (preventing transfers until
roles expire) or deposited in an escrow contract. Developers should decide which implementation to use based on their
use cases.

### Automatic Expiration

Automatic expiration is implemented via the `grantRole` and `roleExpirationDate` functions. `grantRole` is responsible
for setting the expiration date, and `roleExpirationDate` allow developers to check whether the role is expired. Since
`uint256` is not natively supported by most programming languages, dates are represented as `uint64` on this standard.
The maximum UNIX timestamp represented by a `uint64` is about the year `584,942,417,355`, which should be enough to be
considered &quot;permanent&quot;. For this reason, it&apos;s recommended using `type(uint64).max` to support use cases that require a
role never to expire.

### Revocable Roles

In certain scenarios, the original owner of the NFT may need to revoke a role before its expiration date, while in
others, the recipient may require assurance that the role cannot be revoked. The `revocable` parameter was introduced
to the `grantRole` function to specify whether a role can be revoked prematurely, enabling the standard to
support both use cases.

Regardless of the value of `revocable`, it&apos;s recommended always to enable the `recipient` to revoke roles, allowing them
to eliminate undesirable assignments.

### Custom Data

DApps can customize roles using the `data` parameter of the `grantRole` function. `data` is implemented using the
generic type `bytes` to enable dApps to encode any role-specific information when granting a role. The custom
data is retrievable using the `roleData` function and is emitted with the `RoleGranted` event. With this approach, 
developers can integrate this information into their applications, both on-chain and off-chain.

### Role Approval

Similar to [ERC-721](/EIPs/EIPS/eip-721), this standard enable other accounts to manage roles on behalf of the NFT owner. This
functionality was introduced to allow third-parties to interact with ERC-7432 without requiring NFT ownership. Compliant
contracts MUST implement the functions `setRoleApprovalForAll` and `isRoleApprovedForAll` to deliver this feature. 

## Backwards Compatibility

On all functions and events, the standard requires both the `tokenAddress` and `tokenId` to be provided. This 
requirement enables dApps to use a standalone [ERC-7432](/EIPs/EIPS/eip-7432) contract as the authoritative source for the
roles of immutable NFTs.

## Reference Implementation

See [ERC-7432.sol](/EIPs/assets/eip-7432/ERC7432.sol).

## Security Considerations

Developers integrating the Non-Fungible Token Roles interface should consider the following on their implementations:

* Ensure proper access controls are in place to prevent unauthorized role assignments or revocations.
* Take into account potential attack vectors such as reentrancy and ensure appropriate safeguards are in place.
* Approved accounts should be able to manage roles on behalf of another user. However, ensure that the NFT can
  only be transferred to an escrow contract, and back to its original owner (not to the approved account).
* Always check the expiration date before allowing users to access the utility of an NFT. 

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 14 Jul 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7432</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7432</guid>
      </item>
    
      <item>
        <title>Prevent ticket touting</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/prevent-ticket-touting/15269</comments>
        
        <description>## Abstract

This standard is an extension of  [ERC-721](/EIPs/EIPS/eip-721) and defines standard functions outlining a scope for ticketing agents or event organizers to take preventative actions to stop audiences being exploited in the ticket scalping market and allow customers to resell their tickets via authorized ticket resellers.

## Motivation

Industrial-scale ticket touting has been a longstanding issue, with its associated fraud and criminal problems leading to unfortunate incidents and waste of social resources. It is also hugely damaging to artists at all levels of their careers and to related businesses across the board. Although the governments of various countries have begun to legislate to restrict the behavior of scalpers, the effect is limited. They still sold tickets for events at which resale was banned or did not yet own then obtained substantial illegal profits from speculative selling. We consulted many opinions to provide a consumer-friendly resale interface, enabling buyers to resell or reallocate a ticket at the price they initially paid or less is the efficient way to rip off “secondary ticketing”.that enables ticketing agents to utilize

The typical ticket may be a &quot;piece of paper&quot; or even a voucher in your email inbox, making it easy to counterfeit or circulate. To restrict the transferability of these tickets, we have designed a mechanism that prohibits ticket transfers for all parties, including the ticket owner, except for specific accounts that are authorized to transfer tickets. The specific accounts may be ticketing agents, managers, promoters and authorized resale platforms. Therefore, the ticket touts are unable to transfer tickets as they wish. Furthermore, to enhance functionality, we have implemented a token info schema to each ticket,  allowing only authorized accounts(excluding the owner) to modify these records.

This standard defines a framework that enables ticketing agents to utilize [ERC-721](/EIPs/EIPS/eip-721) tokens as event tickets and restricts token transferability to prevent ticket touting. By implementing this standard, we aim to protect customers from scams and fraudulent activities.

## Specification

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

### Interface

The interface and structure referenced here are as follows:

* TokenInfo
    * `signature`: Recommend that the adapter self-defines what to sign using the user&apos;s private key or agent&apos;s private key to prove the token validity.
    * `status`: Represent token current status.
    * `expireTime`: Recommend set to the event due time.
* TokenStatus
    * `Sold`: When a token is sold, it MUST change to `Sold`. The token is valid in this status.
    * `Resell`: When a token is in the secondary market, it MUST be changed to Resell. The token is valid in this status.
    * `Void`: When the token owner engages in an illegal transaction, the token status MUST be set to Void, and the token is invalid in this status.
    * `Redeemed`:  When the token is used, it is RECOMMENDED to change the token status to `Redeemed`.

```solidity
/// @title IERC7439 Prevent Ticket Touting Interface
interface IERC7439 /* is ERC721 */ {
    /// @dev TokenStatus represent the token current status, only specific role can change status
    enum TokenStatus {
        Sold,    // 0
        Resell,  // 1
        Void,    // 2
        Redeemed // 3
    }

    /// @param signature Data signed by user&apos;s private key or agent&apos;s private key
    /// @param tokenStatus Token status changing to
    /// @param expireTime Event due time
    struct TokenInfo {
        bytes signature;
        TokenStatus tokenStatus;
        uint256 expireTime;
    }

    /// @notice Used to notify listeners that the token with the specified ID has been changed status
    /// @param tokenId The token has been changed status
    /// @param tokenStatus Token status has been changed to
    /// @param signature Data signed by user&apos;s private key or agent&apos;s private key
    event TokenStatusChanged(
        uint256 indexed tokenId,
        TokenStatus indexed tokenStatus,
        bytes signature
    );

    /// @notice Used to mint token with token status
    /// @dev MUST emit the `TokenStatusChanged` event if the token status is changed.
    /// @param to The receiptent of token
    /// @param signature Data signed by user&apos;s private key or agent&apos;s private key
    function safeMint(address to, bytes memory signature) external;

    /// @notice Used to change token status and can only be invoked by a specific role
    /// @dev MUST emit the `TokenStatusChanged` event if the token status is changed.
    /// @param tokenId The token need to change status
    /// @param signature Data signed by user&apos;s private key or agent&apos;s private key
    /// @param tokenStatus Token status changing to
    /// @param newExpireTime New event due time
    function changeState(
        uint256 tokenId,
        bytes memory signature,
        TokenStatus tokenStatus,
        uint256 newExpireTime
    ) external;
}
```
The `supportsInterface` method MUST return `true` when called with `0x15fbb306`.

## Rationale

Designing the proposal, we considered the following questions:
1. What is the most crucial for ticketing agents, performers, and audiences?
   * For ticketing companies, selling out all tickets is crucial. Sometimes, to create a vibrant sales environment, ticketing companies may even collaborate with scalpers. This practice can be detrimental to both the audience and performers. To prevent such situations, there must be an open and transparent primary sales channel, as well as a fair secondary sales mechanism. In the `safeMint` function, which is a public function, we hope that everyone can mint tickets transparently at a listed price by themselves. At that time, `TokenInfo` adds a signature that only the buyer account or agent can resolve depending on the mechanism, to prove the ticket validity. And the token `status` is `Sold`. Despite this, we must also consider the pressures on ticketing companies. They aim to maximize the utility of every valid ticket, meaning selling out each one. In the traditional mechanism, ticketing companies only benefit from the initial sale, implying that they do not enjoy the excess profits from secondary sales. Therefore, we have designed a secondary sales process that is manageable for ticketing companies. In the `_beforeTokenTransfer()` function, you can see that it is an accessControl function, and only the `PARTNER_ROLE` `mint` or `burn` situation can transfer the ticket. The `PARTNER_ROLE` can be the ticket agency or a legal secondary ticket selling platform, which may be a state supervision or the ticket agency designated platform. To sustain the fair ticketing market, we cannot allow them to transfer tickets themselves, because we can’t distinguish whether the buyer is a scalper. 
  
   * For performers or event holder, they aren&apos;t willing to see bad news during ticket selling. A smooth ticketing process or no news that may damage their performers’ reputation is what they want. Other than that, what really matters is all the audience true fans who come. Tickets ending up in the hands of scalpers or entering a chaotic secondary market doesn&apos;t really appeal to genuine fans. We believe performers wouldn&apos;t be pleased with such a situation. Through the transparant mechanism, performers or event holder can control the real sales status at all times form cross-comparison of token mint amount and `TokenInfo`-`TokenStatus`.
        ```
        enum TokenStatus {
            Sold,    // 0
            Resell,  // 1
            Void,    // 2
            Redeemed // 3
        }
        ```
   * For audiences, the only thing they need is to get a valid ticket. In the traditional mechanism,fans encounter many obstacles. At hot concerts, fans who try to snag tickets can run into some foes, like scalpers and ticketing companies. These scalpers are like pros, all organized and strategic in grabbing up tickets. Surprisingly, ticketing companies might actually team up with these scalpers. Or, they might just keep a bunch of freebies or VIP tickets to themselves. A transparent mechanism is equally important for the audiences.

2. How to establish a healthy ticketing ecosystem?
   * Clear ticketing rules are key to making sure the supply and demand stay in balance.

   * An open pricing system is a must to make sure consumers are protected.
 
   * Excellent liquidity. In the initial market, users can mint tickets themselves. If needed, purchased tickets can also be transferred in a transparent and open secondary market. Audiences who didn’t buy tickets during the initial sale can also confidently purchase tickets in a legal secondary market. The `changeState` function is to help the ticket have good liquidity. Only `PARTNER_ROLE` can change the ticket status. Once the sold ticket needs to be sold in the secondary market, it needs to ask the secondary market to help it change to resell status. The process of changing status is a kind of official verification of the secondary sale ticket. It is a protection mechanism to the second hand buyer.

3. How to design a smooth ticketing process？
   * Easy to buy/sell. Audiences can buy ticket as mint NFT. This is a well-known practice.
   
   * Easy to refund. When something extreme happens and you need to cancel the show. Handling ticket refunds can be a straightforward process.
 
   * Easy to redeem. Before the show, the ticket agency can verify the ticket by the signature to confirm if the audience is genuine. `TokenStatus` needs to be equal to `sold`, and `expireTime` can distinguish whether the audience has arrived at the correct session. After verification is passed, the ticket agency can change the `TokenStatus` to `Redeemed`.
   
   * Normal Flow
        ![Alt text](/EIPs/assets/eip-7439/normal.png)

   * Void Flow
        ![Alt text](/EIPs/assets/eip-7439/void.png)

   * Resell Flow
        ![Alt text](/EIPs/assets/eip-7439/resell.png)

## Backwards Compatibility

This standard is compatible with [ERC-721](/EIPs/EIPS/eip-721).

## Test Cases

```javascript
const { expectRevert } = require(&quot;@openzeppelin/test-helpers&quot;);
const { expect } = require(&quot;chai&quot;);
const ERC7439 = artifacts.require(&quot;ERC7439&quot;);

contract(&quot;ERC7439&quot;, (accounts) =&gt; {
  const [deployer, partner, userA, userB] = accounts;
  const expireTime = 19999999;
  const tokenId = 0;
  const signature = &quot;0x993dab3dd91f5c6dc28e17439be475478f5635c92a56e17e82349d3fb2f166196f466c0b4e0c146f285204f0dcb13e5ae67bc33f4b888ec32dfe0a063e8f3f781b&quot;
  const zeroHash = &quot;0x&quot;;

  beforeEach(async () =&gt; {
    this.erc7439 = await ERC7439.new({
      from: deployer,
    });
    await this.erc7439.mint(userA, signature, { from: deployer });
  });

  it(&quot;Should mint a token&quot;, async () =&gt; {
    const tokenInfo = await this.erc7439.tokenInfo(tokenId);

    expect(await this.erc7439.ownerOf(tokenId)).to.equal(userA);
    expect(tokenInfo.signature).equal(signature);
    expect(tokenInfo.status).equal(&quot;0&quot;); // Sold
    expect(tokenInfo.expireTime).equal(expireTime);
  });

  it(&quot;should ordinary users cannot transfer successfully&quot;, async () =&gt; {
    expectRevert(await this.erc7439.transferFrom(userA, userB, tokenId, { from: userA }), &quot;ERC7439: You cannot transfer this NFT!&quot;);
  });

  it(&quot;should partner can transfer successfully and chage the token info to resell status&quot;, async () =&gt; {
    const tokenStatus = 1; // Resell

    await this.erc7439.changeState(tokenId, zeroHash, tokenStatus, { from: partner });
    await this.erc7439.transferFrom(userA, partner, tokenId, { from: partner });

    expect(tokenInfo.tokenHash).equal(zeroHash);
    expect(tokenInfo.status).equal(tokenStatus); // Resell
    expect(await this.erc7439.ownerOf(tokenId)).to.equal(partner);
  });

  it(&quot;should partner can change the token status to void&quot;, async () =&gt; {
    const tokenStatus = 2; // Void

    await this.erc7439.changeState(tokenId, zeroHash, tokenStatus, { from: partner });

    expect(tokenInfo.tokenHash).equal(zeroHash);
    expect(tokenInfo.status).equal(tokenStatus); // Void
  });

  it(&quot;should partner can change the token status to redeemed&quot;, async () =&gt; {
    const tokenStatus = 3; // Redeemed

    await this.erc7439.changeState(tokenId, zeroHash, tokenStatus, { from: partner });

    expect(tokenInfo.tokenHash).equal(zeroHash);
    expect(tokenInfo.status).equal(tokenStatus); // Redeemed
  });

  it(&quot;should partner can resell the token and change status from resell to sold&quot;, async () =&gt; {    
    let tokenStatus = 1; // Resell
    await this.erc7439.changeState(tokenId, zeroHash, tokenStatus, { from: partner });
    await this.erc7439.transferFrom(userA, partner, tokenId, { from: partner });
    
    expect(tokenInfo.status).equal(tokenStatus); // Resell
    expect(tokenInfo.tokenHash).equal(zeroHash);

    tokenStatus = 0; // Sold
    const newSignature = &quot;0x113hqb3ff45f5c6ec28e17439be475478f5635c92a56e17e82349d3fb2f166196f466c0b4e0c146f285204f0dcb13e5ae67bc33f4b888ec32dfe0a063w7h2f742f&quot;;
    await this.erc7439.changeState(tokenId, newSignature, tokenStatus, { from: partner });
    await this.erc7439.transferFrom(partner, userB, tokenId, { from: partner });

    expect(tokenInfo.status).equal(tokenStatus); // Sold
    expect(tokenInfo.tokenHash).equal(newSignature);
  });
});
```

## Reference Implementation

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity 0.8.19;

import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;
// If you need additional metadata, you can import ERC721URIStorage
// import &quot;@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol&quot;;
import &quot;@openzeppelin/contracts/access/AccessControl.sol&quot;;
import &quot;@openzeppelin/contracts/utils/Counters.sol&quot;;
import &quot;./IERC7439.sol&quot;;

contract ERC7439 is ERC721, AccessControl, IERC7439 {
    using Counters for Counters.Counter;

    bytes32 public constant PARTNER_ROLE = keccak256(&quot;PARTNER_ROLE&quot;);
    Counters.Counter private _tokenIdCounter;

    uint256 public expireTime;

    mapping(uint256 =&gt; TokenInfo) public tokenInfo;

    constructor(uint256 _expireTime) ERC721(&quot;MyToken&quot;, &quot;MTK&quot;) {
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _grantRole(PARTNER_ROLE, msg.sender);
        expireTime = _expireTime;
    }

    function safeMint(address to, bytes memory signature) public {
        uint256 tokenId = _tokenIdCounter.current();
        _tokenIdCounter.increment();
        _safeMint(to, tokenId);
        tokenInfo[tokenId] = TokenInfo(signature, TokenStatus.Sold, expireTime);
        emit TokenStatusChanged(tokenId, TokenStatus.Sold, signature);
    }

    function changeState(
        uint256 tokenId,
        bytes memory signature,
        TokenStatus tokenStatus,
        uint256 newExpireTime
    ) public onlyRole(PARTNER_ROLE) {
        tokenInfo[tokenId] = TokenInfo(signature, tokenStatus, newExpireTime);
        emit TokenStatusChanged(tokenId, tokenStatus, signature);
    }
    
    function _burn(uint256 tokenId) internal virtual override(ERC721) {
        super._burn(tokenId);

        if (_exists(tokenId)) {
            delete tokenInfo[tokenId];
            // If you import ERC721URIStorage
            // delete _tokenURIs[tokenId];
        }
    }

    function supportsInterface(
        bytes4 interfaceId
    ) public view virtual override(AccessControl, ERC721) returns (bool) {
        return
            interfaceId == type(IERC7439).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual override(ERC721) {
        if (!hasRole(PARTNER_ROLE, _msgSender())) {
            require(
                from == address(0) || to == address(0),
                &quot;ERC7439: You cannot transfer this NFT!&quot;
            );
        }

        super._beforeTokenTransfer(from, to, tokenId);
    }
}
```

## Security Considerations

There are no security considerations related directly to the implementation of this standard.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 28 Jul 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7439</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7439</guid>
      </item>
    
      <item>
        <title>Upgrade block proposer election to Whisk</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7441-upgrade-block-proposer-election-to-whisk-ssle/15316</comments>
        
        <description>## Abstract

Upgrades the block proposer election mechanism to Whisk, a single secret leader election (SSLE) protocol. Currently, block proposers are publicly known in advance, sufficiently to allow sequential DoS attacks that could disable Ethereum. This upgrade allows the next block proposer to remain secret until its block is published.

## Motivation

The beacon chain currently elects the next 32 block proposers at the beginning of each epoch. The results of this election are public and everyone gets to learn the identity of those future block proposers.

This information leak enables attackers to launch DoS attacks against each proposer sequentially in an attempt to disable Ethereum.

## Specification

### Execution layer

This requires no changes to the Execution Layer.

### Consensus layer

The protocol can be summarized in the following concurrent steps:

- Validators register a tracker and unique commitment on their first proposal after the fork
- At the start of a shuffling phase a list of candidate trackers is selected using public randomness from RANDAO
- During each shuffling phase each proposer shuffles a subset of the candidate trackers using private randomness
- After each shuffling phase an ordered list of proposer trackers is selected from the candidate set using RANDAO

The full specification of the proposed change can be found in [`/_features/whisk/beacon-chain.md`](https://github.com/ethereum/consensus-specs/blob/a39abe388bc2d1abd5b4fd62fd18aed497956b30/specs/_features/whisk/beacon-chain.md). In summary:

- Update `BeaconState` with fields needed to track validator trackers, commitments, and the two rounds of candidate election.
- Add `select_whisk_candidate_trackers` to compute the next vector of candidates from the validator set.
- Add `select_whisk_proposer_trackers` to compute the next vector of proposers from current candidates.
- Add `process_whisk_updates` to epoch processing logic.
- Add `process_whisk_opening_proof` to validate block proposer has knowledge of this slot&apos;s elected tracker.
- Modify `process_block_header` to not assert proposer election with `get_beacon_proposer_index`, instead assert valid opening proof.
- Update `BeaconBlockBody` with fields to submit opening proof, shuffled trackers with proof, and tracker registration with proof.
- Add `get_shuffle_indices` to compute pre-shuffle candidate selection
- Add `process_shuffled_trackers` to submit shuffled candidate trackers.
- Add `process_whisk` to block processing logic.
- Modify `apply_deposit` to register an initial unique tracker and commitment without entropy.

## Rationale

### Fields per validator

Whisk requires having one tracker `(rG,krG)` and one unique commitment `kG` per validator. Both are updated only once on a validator&apos;s first proposal after the fork.

Trackers are registered with a randomized base `(rG,krG)` to make it harder for adversaries to track them through shuffling gates. It can become an issue if the set of honest shufflers is small.

### Identity binding

Each tracker must be bound to a validator&apos;s identity to prevent multiple parties to claim the same proposer slot. Otherwise, it would allow proposers to sell their proposer slot, and cause fork-choice issues if two competing blocks appear.

Whisk does identity binding by storing a commitment to the tracker&apos;s secret `kG` in the validator record. Storing the commitment also ensures the uniqueness of `k`.

Alternatively, identity binding can be achieved by forcing the hash prefix of `hash(kG)` to match its validator index. However, validators would have to brute force `k` making bootstrap of the system harder for participants with fewer computational resources.

Identity binding can also be achieved by setting `k = hash(nonce + pubkey)`. However, proposers will need to reveal `k` and be de-anonymized for repeated proposals on adjacent shuffling phases.

### Alternative: non-single secret election

Secret non-single leader election could be based on protocol engineering rather than cryptography, thus much simpler and cheaper than Whisk. However, it complicates the fork-choice and opens it up to potential MEV time-buying attacks, making it an unsuitable option at the time of writing.

### Alternative: network anonymity

Privacy-preserving networking protocols like Dandelion or Dandelion++ increase the privacy of network participants but not sufficiently for Ethereum&apos;s use case.

SASSAFRAS is a simpler alternative SSLE protocol consensus-wise, but it relies on a network anonymity layer. Its specific trade-offs do not fit Ethereum&apos;s overall threat model better than Whisk.

## Backwards Compatibility

This EIP introduces backward incompatible changes to the block validation rule set on the consensus layer and must be accompanied by a hard fork.

PBS participants (e.g. builders) will not know the next proposer validator index to use a specific pre-registered fee recipient; unless the proposer chooses to reveal itself ahead of time. Block explorers and tooling will not be able to attribute missing slots to a specific validator index.

## Security Considerations

The shuffling strategy is analyzed in a companion paper and considered sufficiently safe for Whisk&apos;s use case. The data and computational complexity of this EIP are significant but constant, thus does not open new DoS vectors. 

### Anonymity set

The anonymity set in Whisk is the set of 8,192 candidates that did not get selected as proposers. That count of validators corresponds to a smaller number of p2p nodes. Assuming a Pareto principle where &quot;20% of the nodes run 80% of the validators&quot; the anonymity corresponds to 2,108 nodes on average. A bigger candidate pool could make the shuffling strategy unsafe while shuffling more trackers per round would increase the cost of the ZK proofs.

### RANDAO biasing

Whisk uses RANDAO in the candidate selection and proposer selection events, and is susceptible to potential RANDAO biasing attacks by malicious proposers. Whisk security could be made identical to the status quo by spreading the selection events over an entire shuffling period. However, status quo security is not ideal either and it would complicate the protocol further.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Fri, 01 Sep 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7441</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7441</guid>
      </item>
    
      <item>
        <title>Time Locks Maturity</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-idea-timelock-maturity/15321</comments>
        
        <description>## Abstract

This EIP defines a standardized method to communicate the date on which a time-locked system will become unlocked. This allows for the determination of maturities for a wide variety of asset classes and increases the ease with which these assets may be valued.

## Motivation

Time-locks are ubiquitous, yet no standard on how to determine the date upon which they unlock exists. Time-locked assets experience theta-decay, where the time remaining until they become unlocked dictates their value. Providing a universal standard to view what date they mature on allows for improved on-chain valuations of the rights to these illiquid assets, particularly useful in cases where the rights to these illiquid assets may be passed between owners through semi-liquid assets such as [ERC-721](/EIPs/EIPS/eip-721) or [ERC-1155](/EIPs/EIPS/eip-1155).  

## Specification

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

**Every [ERC-7444](/EIPs/EIPS/eip-7444) compliant contract must implement [ERC-165](/EIPs/EIPS/eip-165) interface detection**

```solidity
// SPDX-License-Identifier: CC0-1.0

pragma solidity ^0.8.0;

interface ERC-7444 {
    /
     * @notice      This function returns the timestamp that the time lock specified by `id` unlocks at
     * @param       id The identifier which describes a specific time lock
     * @return      maturity The timestamp of the time lock when it unlocks
     */
    function getMaturity(bytes32 id)
        external
        view
        returns (uint256 maturity);

}
```

The maturity return parameter should be implemented in the Unix timestamp standard, which has been used widely in solidity. For example, `block.timestamp` represents the Unix timestamp when a block is mined in 256-bit value. 

For singleton implementations on fungible assets, values passed to `id` SHOULD be ignored, and queries to such implementations should pass in `0x0` 

## Rationale

### Universal Maturities on Locked Assets

Locked Assets have become increasingly popular and used in different parts of defi, such as yield farming and vested escrow concept. This has increased the need to formalize and define an universal interface for all these timelocked assets.

### Valuation of Locked Assets via the Black-Scholes Model

 Locked Assets cannot be valued normally since the value of these assets can be varied through time and many other different factors throughout the locking time. For instance, The Black-Scholes Model or Black-Scholes-Merton model is an example of a suitable model to estimate the theoretical value of asset with the consideration of impact of time and other potential risks. 

![Black-Sholes Model](/EIPs/assets/eip-7444/equation.png)

- $C=\text{call option price}$
- $N=\text{CDF of the normal distribution}$
- $S_t=\text{spot price of an asset}$
- $K=\text{strike price}$
- $r=\text{risk-free interest rate}$
- $t=\text{time to maturity}$
- $\sigma=\text{volatility of the asset}$

Time to maturity plays an important role in evaluating the price of timelocked assets, thus the demand to have a common interface for retrieving the data is inevitable. 

## Backwards Compatibility

This standard can be implemented as an extension to [ERC-721](/EIPs/EIPS/eip-721) and/or [ERC-1155](/EIPs/EIPS/eip-1155) tokens with time-locked functionality, many of which can be retrofitted with a designated contract to determine the point at which their time locks release. 

## Reference Implementation

### Locked [ERC-20](/EIPs/EIPS/eip-20) implementation

```solidity
// SPDX-License-Identifier: CC0-1.0

pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/token/ERC20/ERC20.sol&quot;;

contract LockedERC20ExampleContract implements ERC-7444{
    ERC20 public immutable token;
    uint256 public totalLocked;

    //Timelock struct
    struct TimeLock {
        address owner;
        uint256 amount;
        uint256 maturity;
        bytes32 lockId;
    }

    //maps lockId to balance of the lock
    mapping(bytes32 =&gt; TimeLock) public idToLock;    

    function constructor(
        address _token,
    ) public {
        token = ERC20(_token);
    }

    //Maturity is not appropriate
    error LockPeriodOngoing();
    error InvalidReceiver();
    error TransferFailed();

    /// @dev Deposit tokens to be locked in the requested locking period
    /// @param amount The amount of tokens to deposit
    /// @param lockingPeriod length of locking period for the tokens to be locked
    function deposit(uint256 amount, uint256 lockingPeriod) external returns (bytes32 lockId) {
        uint256 maturity = block.timestamp + lockingPeriod;
        lockId = keccack256(abi.encode(msg.sender, amount, maturity));

        require(idToLock[lockId].maturity == 0, &quot;lock already exists&quot;);

        if (!token.transferFrom(msg.sender, address(this), amount)) {
            revert TransferFailed();
        }

        TimeLock memory newLock = TimeLock(msg.sender, amount, maturity, lockedId);

        totalLocked += amount;

        idToLock[lockId] = newLock;
        
    }

    /// @dev Withdraw tokens in the lock after the end of the locking period
    /// @param lockId id of the lock that user have deposited in
    function withdraw(bytes32 lockId) external {
        TimeLock memory lock = idToLock[lockId];

        if (msg.sender != lock.owner) {
            revert InvalidReceiver();
        }

        if (block.timestamp &gt; lock.maturity) {
            revert LockPeriodOngoing();
        }

        totalLocked -= lock.amount;

        //State cleanup
        delete idToLock[lockId];

        if (!token.transfer(msg.sender, lock.amount)) {
            revert TransferFailed();
        }

    }

    function getMaturity(bytes32 id) external view returns (uint256 maturity) {
        return idToLock[id].maturity;
    }
}

```

## Security Considerations

### Extendable Time Locks

Users or developers should be aware of potential extendable timelocks, where the returned timestamp can be modified through protocols. Users or protocols should check the timestamp carefully before trading or lending with others.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 05 Jun 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7444</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7444</guid>
      </item>
    
      <item>
        <title>EOF - Data section access instructions</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7480-eof-data-instructions/15414</comments>
        
        <description>## Abstract

Four new instructions are introduced, that allow to read EOF container&apos;s data section: `DATALOAD` loads 32-byte word to stack, `DATALOADN` loads 32-byte word to stack where the word is addressed by a static immediate argument, `DATASIZE` loads data section size and `DATACOPY` copies a segment of data section to memory. 

## Motivation

Clear separation between code and data is one of the main features of EOF1. Data section may contain anything, e.g. compiler&apos;s metadata, but to make it useful for smart contracts, EVM has to have instructions that allow to read from data section. Previously existing instructions for bytecode inspection (`CODECOPY`, `CODESIZE` etc.) are deprecated in EOF1 and cannot be used for this purpose.

The `DATALOAD`, `DATASIZE`, `DATACOPY` instruction pattern follows the design of existing instructions for reading other kinds of data (i.e. returndata and calldata).

`DATALOADN` is an optimized version of `DATALOAD`, where data offset to read is set at compilation time, and therefore need not be validated at run-time, which makes the instruction cheaper.

## Specification

We introduce four new instructions on the same block number [EIP-3540](/EIPs/EIPS/eip-3540) is activated on:

1. `DATALOAD` (0xd0)
2. `DATALOADN` (0xd1)
3. `DATASIZE` (0xd2)
4. `DATACOPY` (0xd3)

If the code is legacy bytecode, all of these instructions result in an *exceptional halt*. (*Note: This means no change to behaviour.*)

If the code is valid EOF1, the following execution rules apply:

### `DATALOAD`

1. Pops one value, `offset`, from the stack.
2. Reads `[offset:offset+32]` segment from the data section and pushes it as 32-byte value to the stack.
3. If `offset + 32` is greater than the data section size, bytes after the end of data section are set to 0.
4. Deducts 4 gas.

### `DATALOADN`

1. Has one immediate argument,`offset`, encoded as a 16-bit unsigned big-endian value.
2. Pops nothing from the stack.
3. Reads `[offset:offset+32]` segment from the data section and pushes it as 32-byte value to the stack.
4. Deducts 3 gas.

`[offset:offset+32]` is guaranteed to be within data bounds by [code validation](#code-validation).

### `DATASIZE`

1. Pops nothing from the stack.
2. Pushes the size of the data section of the active container to the stack.
3. Deducts 2 gas.

### `DATACOPY`

1. Pops three values from the stack: `mem_offset`, `offset`, `size`.
2. Performs memory expansion to `mem_offset + size` and deducts memory expansion cost.
3. Deducts `3 + 3 * ((size + 31) // 32)` gas for copying.
4. Reads `[offset:offset+size]` segment from the data section and writes it to memory starting at offset `mem_offset`.
5. If `offset + size` is greater than data section size, 0 bytes will be copied for bytes after the end of the data section.


### Code Validation

We extend code section validation rules (as defined in [EIP-3670](/EIPs/EIPS/eip-3670)).

1. Code section is invalid in case an immediate argument `offset` of any `DATALOADN` is such that `offset + 32` is greater than data section size, as indicated in the container header *before deployment*.
2. `RJUMP`, `RJUMPI` and `RJUMPV` immediate argument value (jump destination relative offset) validation: code section is invalid in case offset points to one of two bytes directly following `DATALOADN` instruction.


## Rationale

### Zero-padding on out of bounds access

Existing instructions for reading other kinds of data implicitly pad with zeroes on out of bounds access, with the only exception of return data copying.

It is beneficial to avoid exceptional failures, because compilers can employ optimizations like removing a code that copies data, but never accesses this copy afterwards, but such optimization is possible only if instruction never has other side effects like exceptional abort.

### Lack of `EXTDATACOPY`

`EXTCODECOPY` instruction is deprecated and rejected in EOF contracts and does not copy contract code when being called in legacy with an EOF contract as target. A replacement instruction `EXTDATACOPY` has been considered, but decided against in order to reduce the scope of changes.

Data-only contracts which previously relied on `EXTCODECOPY` are thereby discouraged, but if there is a strong need, support for them can be easily brought back by introducing `EXTDATACOPY` in a future upgrade.

## Backwards Compatibility

This change poses no risk to backwards compatibility, as it is introduced only for EOF1 contracts, for which deploying undefined instructions is not allowed, therefore there are no existing contracts using these instructions. The new instructions are not introduced for legacy bytecode (code which is not EOF formatted).

## Security Considerations

Gas cost of these new opcodes is comparable to the legacy `CODECOPY` instruction. They must be carefully considered during the implementation of the EOF container validation algorithm.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 11 Aug 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7480</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7480</guid>
      </item>
    
      <item>
        <title>Registry Extension for ERC-7579</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7484-registry-adapters-for-smart-accounts/15434</comments>
        
        <description>## Abstract

This proposal standardizes the interface and functionality of Module Registries, allowing modular smart accounts to verify the security of modules using a Registry Adapter. It also provides a reference implementation of a Singleton Module Registry.

## Motivation

[ERC-4337](/EIPs/EIPS/eip-4337) standardizes the execution flow of contract accounts and [ERC-7579](/EIPs/EIPS/eip-7579) standardizes the modular implementation of these accounts, allowing any developer to build modules for these modular accounts (hereafter Smart Accounts). However, adding third-party modules into Smart Accounts unchecked opens up a wide range of attack vectors.

One solution to this security issue is to create a Module Registry that stores security attestations on Modules and allows Smart Accounts to query these attestations before using a module. This standard aims to achieve two things:

1. Standardize the interface and required functionality of Module Registries.
2. Standardize the functionality of Adapters that allow Smart Accounts to query Module Registries.

This ensures that Smart Accounts can securely query Module Registries and handle the Registry behavior correctly, irrespective of their architecture, execution flows and security assumptions. This standard also provides a reference implementation of a Singleton Module Registry that is ownerless and can be used by any Smart Account. While we see many benefits of the entire ecosystem using this single Module Registry (see `Rationale`), we acknowledge that there are tradeoffs to using a singleton and thus this standard does not require Smart Accounts to use the reference implementation. Hence, this standard ensures that Smart Accounts can query any Module Registry that implements the required interface and functionality, reducing integration overhead and ensuring interoperability for Smart Accounts.

## Specification

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

### Definitions

- **Smart account** - An ERC-7579 modular smart account.
- **Module** - Self-contained smart account functionality.
- **Attestation** - Onchain assertions made about the security of a module.
- **Attester** - The entity that makes an attestation about a module.
- **(Module) Registry** - A contract that stores an onchain list of attestations about modules.
- **Adapter** - Smart account functionality that handles the fetching and validation of attestations from the Registry.

### Required Registry functionality

The core interface for a Registry is as follows:

```solidity
interface IERC7484Registry {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*               Check with internal attester(s)              */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
    function check(address module) external view;

    function checkForAccount(address smartAccount, address module) external view;

    function check(address module, uint256 moduleType) external view;

    function checkForAccount(
        address smartAccount,
        address module,
        uint256 moduleType
    )
        external
        view;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   Set internal attester(s)                 */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    function trustAttesters(uint8 threshold, address[] calldata attesters) external;


    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*              Check with external attester(s)               */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    function check(
        address module,
        address[] calldata attesters,
        uint256 threshold
    )
        external
        view;

    function check(
        address module,
        uint256 moduleType,
        address[] calldata attesters,
        uint256 threshold
    )
        external
        view;
}
```

The Registry MUST also implement the following functionality:

- Verify that an attester is the creator of an attestation, for example by checking `msg.sender` or by using signatures, before storing it.
- Allow attesters to revoke attestations that they have made.
- Store either the attestation data or a reference to the attestation data.

The Registry SHOULD also implement the following additional functionality:

- Allow attesters to specify an expiry date for their attestations and revert during a check if an attestation is expired.
- Implement a view function that allows an adapter or offchain client to read the data for a specific attestation.

#### `check` functions

- The Registry MUST revert if the number of `attesters` that have made an attestation on the `module` is smaller than the `threshold`.
- The Registry MUST revert if any `attester` has revoked their attestation on the `module`.
- The `attesters` provided MUST be unique and sorted and the Registry MUST revert if they are not.

#### `check` functions with moduleType

- The Registry MUST revert if the module type of the `module` stored is not the provided `moduleType`.

#### Functions with internal attester(s)

- The Registry MUST use the stored attester(s) for the `smartAccount` or `msg.sender` (if the former is not an argument).
- The Registry MUST revert if no attester(s) are stored for the `smartAccount` or `msg.sender` (if the former is not an argument).

#### `trustAttesters`

- The Registry MUST store the `threshold` and `attesters` for the `msg.sender`.
- The `attesters` provided MUST be unique and sorted and the Registry MUST revert if they are not.

### Adapter behavior

A Smart Account MUST implement the following Adapter functionality either natively in the account or as a module. This Adapter functionality MUST ensure that:

- The Registry is queried about module `A` at least once before or during the transaction in which `A` is called for the first time.
- The Registry reverting is treated as a security risk.

Additionally, the Adapter SHOULD implement the following functionality:

- Revert the transaction flow when the Registry reverts.
- Query the Registry about module `A` on installation of `A`.
- Query the Registry about module `A` on execution of `A`.

Example: Adapter flow using `check`
![Adapter flow using check()](/EIPs/assets/eip-7484/check-sequence.jpg)

## Rationale

### Attestations

Attestations are onchain assertions made about a module. These assertions could pertain to the security of a module (similar to a regular smart contract audit), whether a module adheres to a certain standard or any other kinds of statements about these modules. While some of these assertions can feasibly be verified onchain, the majority of them cannot be.

One example of this would be determining what storage slots a specific module can write to, which might be useful if a smart account uses DELEGATECALL to invoke the module. This assertion is practically infeasible to verify onchain, but can easily be verified off-chain. Thus, an attester could perform this check off-chain and publish an attestation onchain that attests to the fact that a given module can only write to its designated storage slots.

While attestations are always certain kinds of assertions made about a module, this proposal purposefully allows the attestation data to be any kind of data or pointer to data. This ensures that any kind of data can be used as an assertion, from a simple boolean flag specifying that a module is secure to a complex proof of runtime module behaviour.

### Singleton Registry

In order for attestations to be queryable onchain, they need to be stored in some sort of list in a smart contract. This proposal includes the reference implementation of an ownerless Singleton Registry that functions as the source of truth for attestations.

The reasons for proposing a Singleton Registry are the following:

**Security**: A Singleton Registry creates greater security by focusing account integrations into a single source of truth where a maximum number of security entities are attesting. This has a number of benefits: a) it increases the maximum potential quantity and type of attestations per module and b) removes the need for accounts to verify the authenticity and security of different registries, focusing trust delegation to the onchain entities making attestations. The result is that accounts are able to query multiple attesters with lower gas overhead in order to increase security guarantees and there is no additional work required by accounts to verify the security of different registries.

**Interoperability**: A Singleton Registry not only creates a greater level of “attestation liquidity”, but it also increases module liquidity and ensures a greater level of module interoperability. Developers need only deploy their module to one place to receive attestations and maximise module distribution to all integrated accounts. Attesters can also benefit from previous auditing work by chaining attestations and deriving ongoing security from these chains of dependencies. This allows for benefits such as traversing through the history of attestations or version control by the developer.

However, there are obviously tradeoffs for using a singleton. A Singleton Registry creates a single point of failure that, if exploited, could lead to serious consequences for smart accounts. The most serious attack vector of these would be the ability for an attacker to attest to a malicious module on behalf of a trusted attester. One tradeoff here is that using multiple registries, changes in security attestations (for example a vulnerability is found and an attestation is revoked) are slower to propagate across the ecosystem, giving attackers an opportunity to exploit vulnerabilities for longer or even find and exploit them after seeing an issue pointed out in a specific Registry but not in others.

Due to being a singleton, the Registry needs to be very flexible and thus likely less computationally efficient in comparison to a narrow, optimised Registry. This means that querying a Singleton Registry is likely to be more computationally (and by extension gas) intensive than querying a more narrow Registry. The tradeoff here is that a singleton makes it cheaper to query attestations from multiple parties simultaneously. So, depending on the Registry architectures, there is an amount of attestations to query (N) after which using a flexible singleton is actually computationally cheaper than querying N narrow registries. However, the reference implementation has also been designed with gas usage in mind and it is unlikely that specialised registries will be able to significantly decrease gas beyond the reference implementations benchmarks.

### Module Types

Modules can be of different types and it can be important for an account to ensure that a module is of a certain type. For example, if an account wants to install a module that handles the validation logic of the account, then it might want to ensure that attesters have confirmed that the module is indeed capable of performing this validation logic. Otherwise, the account might be at risk of installing a module that is not capable of performing the validation logic, which could lead to an account being rendered unusable.

Nonetheless, the Registry itself does not need to care what specific module types mean. Instead, attesters can provide these types and the Registry can store them.

### Related work

The reference implementation of the Registry is heavily inspired by the Ethereum Attestation Service. The specific use-case of this proposal, however, required some custom modifications and additions to EAS, meaning that using the existing EAS contracts as the Module Registry was sub-optimal. However, it would be possible to use EAS as a Module Registry with some modifications.

## Backwards Compatibility

No backward compatibility issues found.

## Reference Implementation

### Adapter.sol

```solidity
contract Adapter {
    IRegistry registry;

    function checkModule(address module) internal {
        // Check module attestation on Registry
        registry.check(module);
    }

    function checkModuleWithModuleTypeAndAttesters(address module, address[] memory attesters, uint256 threshold,  uint16 moduleType) internal {
        // Check list of module attestations on Registry
        registry.check(module, attesters, threshold, moduleType);
    }

}
```

### Account.sol

**Note**: This is a specific example that complies to the `Specification` above, but this implementation is not binding.

```solidity
contract Account is Adapter {
    ...

    // installs a module
    function installModule(
        uint256 moduleTypeId,
        address module,
        bytes calldata initData
    )
        external
        payable
    {
        checkModule(module);
        ...
    }

    // executes a module
    function executeFromExecutor(
        ModeCode mode,
        bytes calldata executionCalldata
    )
        external
        payable
        returns (bytes[] memory returnData)
    {
        checkModule(module);
        ...
    }

    ...
}
```

### Registry

```solidity
/**
* @dev this implementation is unoptimized in order to make the reference implementation shorter to read
* @dev some function implementations are missing for brevity
*/
contract Registry is IERC7484Registry {
    ...

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*               Check with internal attester(s)              */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
    function check(address module) external view {
        (address[] calldata attesters, uint256 threshold) = _getAttesters(msg.sender);

        uint256 validCount = 0;
        for (uint256 i = 0; i &lt; attesters.length; i++) {
            bool isValid = _check(module, attesters[i]);
            if (isValid) validCount++;
        }
        if (validCount &lt; threshold) revert AttestationThresholdNotMet();
    }

    function checkForAccount(address smartAccount, address module) external view {
        (address[] calldata attesters, uint256 threshold) = _getAttesters(smartAccount);

        ...
    }

    function check(address module, uint256 moduleType) external view {
        (address[] calldata attesters, uint256 threshold) = _getAttesters(msg.sender);

        uint256 validCount = 0;
        for (uint256 i = 0; i &lt; attesters.length; i++) {
            bool isValid = _check(module, attesters[i]);
            if (isValid) validCount++;

            AttestationRecord storage attestation = _getAttestation(module, attester);
            if (attestation.moduleType != moduleType) revert ModuleTypeMismatch();
        }
        if (validCount &lt; threshold) revert AttestationThresholdNotMet();
    }

    function checkForAccount(
        address smartAccount,
        address module,
        uint256 moduleType
    )
        external
        view {
        (address[] calldata attesters, uint256 threshold) = _getAttesters(smartAccount);

        ...
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   Set internal attester(s)                 */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    function trustAttesters(uint8 threshold, address[] calldata attesters) external {
        ...
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*              Check with external attester(s)               */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    function check(
        address module,
        address[] calldata attesters,
        uint256 threshold
    )
        external
        view
    {
        uint256 validCount = 0;
        for (uint256 i = 0; i &lt; attesters.length; i++) {
            bool isValid = _check(module, attesters[i]);
            if (isValid) validCount++;
        }
        if (validCount &lt; threshold) revert AttestationThresholdNotMet();
    }

    function check(
        address module,
        uint256 moduleType,
        address[] calldata attesters,
        uint256 threshold
    )
        external
        view
    {
        uint256 validCount = 0;
        for (uint256 i = 0; i &lt; attesters.length; i++) {
            bool isValid = _check(module, attesters[i]);
            if (isValid) validCount++;

            AttestationRecord storage attestation = _getAttestation(module, attester);
            if (attestation.moduleType != moduleType) revert ModuleTypeMismatch();
        }
        if (validCount &lt; threshold) revert AttestationThresholdNotMet();
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         Internal                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    function _check(address module, address attester) external view returns (bool isValid){
        AttestationRecord storage attestation = _getAttestation(module, attester);

        uint48 expirationTime = attestation.expirationTime;
        uint48 attestedAt =
            expirationTime != 0 &amp;&amp; expirationTime &lt; block.timestamp ? 0 : attestation.time;
        if (attestedAt == 0) return;

        uint48 revokedAt = attestation.revocationTime;
        if (revokedAt != 0) return;

        isValid = true;
    }

    function _getAttestation(
        address module,
        address attester
    )
        internal
        view
        virtual
        returns (AttestationRecord storage)
    {
        return _moduleToAttesterToAttestations[module][attester];
    }

    function _getAttesters(
        address account
    )
        internal
        view
        virtual
        returns (address[] calldata attesters, uint256 threshold)
    {
        ...
    }

    ...
}
```

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 14 Aug 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7484</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7484</guid>
      </item>
    
      <item>
        <title>SSZ ProgressiveContainer</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7495-ssz-progressivecontainer/15476</comments>
        
        <description>## Abstract

This EIP introduces a new [Simple Serialize (SSZ)](https://github.com/ethereum/consensus-specs/blob/ad36024441cf910d428d03f87f331fbbd2b3e5f1/ssz/simple-serialize.md) type to represent containers with forward-compatible Merkleization: A given field is always assigned the same stable [generalized index (gindex)](https://github.com/ethereum/consensus-specs/blob/ad36024441cf910d428d03f87f331fbbd2b3e5f1/ssz/merkle-proofs.md#generalized-merkle-tree-index) even when different container versions append new fields or drop existing fields.

## Motivation

SSZ containers are frequently versioned, for example across fork boundaries. When the number of fields reaches a new power of two, or a field is removed or replaced with one of a different type, the shape of the underlying Merkle tree changes, breaking verifiers of Merkle proofs for these containers. Deploying a new verifier may involve security councils to upgrade smart contract logic, or require firmware updates for embedded devices. This effort is needed even when no semantic changes apply to the fields that the verifier is interested in.

Progressive containers address these shortcomings by:

- Using the [progressive Merkle tree](/EIPs/EIPS/eip-7916) structure to progressively grow to the actual field count with minimal overhead, ensuring provers remain valid as the field count changes.
- Assigning stable gindices for each field across all versions by allowing gaps in the Merkle tree where a field is absent.
- Serializing in a compact form where absent fields do not consume space.

## Specification

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

### `ProgressiveContainer(active_fields)`

A new [SSZ composite types](https://github.com/ethereum/consensus-specs/blob/ad36024441cf910d428d03f87f331fbbd2b3e5f1/ssz/simple-serialize.md#composite-types) is defined:

- **progressive container**: ordered heterogeneous collection of values with stable Merkleization
  - python dataclass notation with key-type pairs, e.g.

  ```python
  class Square(ProgressiveContainer(active_fields=[1, 0, 1])):
      side: uint16  # Merkleized at field index #0 (location of first 1 in `active_fields`)
      color: uint8  # Merkleized at field index #2 (location of second 1 in `active_fields`)

  class Circle(ProgressiveContainer(active_fields=[0, 1, 1])):
      radius: uint16  # Merkleized at field index #1 (location of first 1 in `active_fields`)
      color: uint8  # Merkleized at field index #2 (location of second 1 in `active_fields`)
  ```

The [default value](https://github.com/ethereum/consensus-specs/blob/ad36024441cf910d428d03f87f331fbbd2b3e5f1/ssz/simple-serialize.md#default-values) is defined as:

| Type                                   | Default Value                                       |
| -------------------------------------- | --------------------------------------------------- |
| `ProgressiveContainer(active_fields)`  | `[default(type) for type in progressive_container]` |

The following types are considered [illegal](https://github.com/ethereum/consensus-specs/blob/ad36024441cf910d428d03f87f331fbbd2b3e5f1/ssz/simple-serialize.md#illegal-types):

- `ProgressiveContainer` with no fields are illegal.
- `ProgressiveContainer` with an `active_fields` configuration of more than 256 entries are illegal.
- `ProgressiveContainer` with an `active_fields` configuration ending in `0` are illegal.
- `ProgressiveContainer` with an `active_fields` configuration with a different count of `1` than fields are illegal.

#### Serialization

Serialization of `ProgressiveContainer(active_fields)` is identical to [`Container`](https://github.com/ethereum/consensus-specs/blob/ad36024441cf910d428d03f87f331fbbd2b3e5f1/ssz/simple-serialize.md#vectors-containers-lists).

#### Deserialization

Deserialization of `ProgressiveContainer(active_fields)` is identical to [`Container`](https://github.com/ethereum/consensus-specs/blob/ad36024441cf910d428d03f87f331fbbd2b3e5f1/ssz/simple-serialize.md#deserialization).

#### JSON mapping

The canonical [JSON mapping](https://github.com/ethereum/consensus-specs/blob/ad36024441cf910d428d03f87f331fbbd2b3e5f1/ssz/simple-serialize.md#json-mapping) is updated:

| SSZ                                   | JSON   | Example            |
| ------------------------------------- | ------ | ------------------ |
| `ProgressiveContainer(active_fields)` | object | `{ &quot;field&quot;: ... }` |

#### Merkleization

The [SSZ Merkleization specification](https://github.com/ethereum/consensus-specs/blob/ad36024441cf910d428d03f87f331fbbd2b3e5f1/ssz/simple-serialize.md#merkleization) is extended with two helper functions:

- `get_active_fields(value)`, where `value` is of type `ProgressiveContainer(active_fields)`: return `active_fields`.
- `mix_in_active_fields`: Given a Merkle root `root` and an `active_fields` configuration return `hash(root, pack_bits(active_fields))`. Note that `active_fields` is restricted to ≤ 256 bits.

The Merkleization definitions are extended.

- `mix_in_active_fields(merkleize_progressive([hash_tree_root(element) for element in value]), get_active_fields(value))` if `value` is a progressive container.

## Rationale

### Why is `active_fields` limited to 256 bits?

256 bits (1 word) allows the mix-in to be simple, consistent with the length mix-in for lists, and is practically sufficient. An alternate design with a `ProgressiveBitlist` mix-in was explored, however deemed too over-engineered as it would effectively require introducing caches to pre-compute the mix-in&apos;s `hash_tree_root` to avoid repeated computations, and also makes verifier logic more complex than necessary.

Even though the 256 field limit includes all fields (including deprecated ones), it is unlikely that many progressive containers come close to reach 256 fields (`BeaconState` currently reaches around 40 fields). If that happens, one can add a `more` field with a nested `ProgressiveContainer`.

### Why is empty `ProgressiveContainer` an illegal type?

It would result in 0-length serialization, meaning that the length of a list of such a container cannot be determined from the serialization.

### `Optional[type]`?

Introducing `Optional` is not required by any current functionality and is deferred to a future EIP.

The `active_fields` bitvector can be updated to also indicate optionality. Further, serialization for sparse lists should be explored.

## Backwards Compatibility

`ProgressiveContainer(active_fields)` is a new SSZ type and does not conflict with existing types.

## Test Cases

- `ethereum/remerkleable` contains static tests in `test_impl.py` and `test_typing.py`.
- `ethereum/consensus-specs` releases contain random tests in `tests/general/phase0/ssz_generic`, generated according to a format defined in `tests/format/ssz_generic`.

## Reference Implementation

See `ethereum/remerkleable`.

## Security Considerations

Light client based verifiers and smart contracts (e.g., based on [EIP-4788](/EIPs/EIPS/eip-4788)) do not update at the same cadence as Ethereum. If a future fork removes a field from a `ProgressiveContainer(active_fields)`, the `active_fields` mix-in enables such verifiers to distinguish absent fields from `0` values. Without `active_fields`, the `hash_tree_root` for these cases would collide.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 18 Aug 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7495</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7495</guid>
      </item>
    
      <item>
        <title>NFT Dynamic Traits</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7496-nft-dynamic-traits/15484</comments>
        
        <description>## Abstract

This specification introduces a new interface that extends [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155) that defines methods for setting and getting dynamic onchain traits associated with non-fungible tokens. These dynamic traits can be used to represent properties, characteristics, redeemable entitlements, or other attributes that can change over time. By defining these traits onchain, they can be used and modified by other onchain contracts.

## Motivation

Trait values for non-fungible tokens are often stored offchain. This makes it difficult to query and mutate these values in contract code. Specifying the ability to set and get traits onchain allows for new use cases like redeeming onchain entitlements and transacting based on a token&apos;s traits.

Onchain traits can be used by contracts in a variety of different scenarios. For example, a contract that wants to entitle a token to a consumable benefit (e.g. a redeemable) can robustly reflect that onchain. Marketplaces can allow bidding on these tokens based on the trait value without having to rely on offchain state and exposing users to frontrunning attacks. The motivating use case behind this proposal is to protect users from frontrunning attacks on marketplaces where users can list NFTs with certain traits where they are expected to be upheld during fulfillment.

## Specification

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

Contracts implementing this EIP MUST include the events, getters, and setters as defined below, and MUST return `true` for [ERC-165](/EIPs/EIPS/eip-165) `supportsInterface` for `0xaf332f3e`, the 4 byte `interfaceId` for this ERC.

```solidity
interface IERC7496 {
    /* Errors */
    /// @notice Thrown when trying to set a trait that does not exist.
    error TraitDoesNotExist(bytes32 traitKey);
    /// @notice Thrown when the token does not exist.
    error TokenDoesNotExist(uint256 tokenId);

    /* Events */
    event TraitUpdated(bytes32 indexed traitKey, uint256 tokenId, bytes32 traitValue);
    event TraitUpdatedRange(bytes32 indexed traitKey, uint256 fromTokenId, uint256 toTokenId);
    event TraitUpdatedRangeUniformValue(bytes32 indexed traitKey, uint256 fromTokenId, uint256 toTokenId, bytes32 traitValue);
    event TraitUpdatedList(bytes32 indexed traitKey, uint256[] tokenIds);
    event TraitUpdatedListUniformValue(bytes32 indexed traitKey, uint256[] tokenIds, bytes32 traitValue);
    event TraitMetadataURIUpdated();

    /* Getters */
    function getTraitValue(uint256 tokenId, bytes32 traitKey) external view returns (bytes32 traitValue);
    function getTraitValues(uint256 tokenId, bytes32[] calldata traitKeys) external view returns (bytes32[] traitValues);
    function getTraitMetadataURI() external view returns (string memory uri);

    /* Setters */
    function setTrait(uint256 tokenId, bytes32 traitKey, bytes32 newValue) external;
}
```

### Keys &amp; Names

The `traitKey` is used to identify a trait. The `traitKey` MUST be a unique `bytes32` value identifying a single trait.

The `traitKey` SHOULD be a `keccak256` hash of a human readable trait name.

### Errors

If a `traitKey` is not defined in the contract (i.e., not present in the trait metadata schema), the contract MUST revert with `TraitDoesNotExist(traitKey)`. This allows applications to detect when they have queried an invalid or unsupported trait key.

If a `traitKey` is defined in the contract but a specific token does not have a value set for that trait, the contract MUST return `bytes32(0)` as the default value instead of reverting. This enables batch querying of all defined trait keys across multiple tokens without failures due to unset values.

If a `tokenId` does not exist, the contract MUST revert with `TokenDoesNotExist(tokenId)`. If the token contract already defines a custom error for non-existent tokens (e.g. from [ERC-721](/EIPs/EIPS/eip-721) or [ERC-1155](/EIPs/EIPS/eip-1155)), that error MAY be used instead.

### Metadata

Trait metadata is necessary to provide information about which traits are present in a contract, how to display trait names and values, and other optional features.

The trait metadata must be compliant with the [specified schema](/EIPs/assets/eip-7496/DynamicTraitsSchema.json).

The trait metadata URI MAY be a data URI or point to an offchain resource.

The keys in the `traits` object MUST be unique trait names. If the trait name is 32 byte hex string starting with `0x` then it is interpreted as a literal `traitKey`. Otherwise, the `traitKey` is defined as the `keccak256` hash of the trait name. A literal `traitKey` MUST NOT collide with the `keccak256` hash of any other traits defined in the metadata.

The `displayName` values MUST be unique and MUST NOT collide with the `displayName` of any other traits defined in the metadata.

The `validateOnSale` value provides a signal to marketplaces on how to validate the trait value when a token is being sold. If the validation criteria is not met, the sale MUST not be permitted by the marketplace contract. If specified, the value of `validateOnSale` MUST be one of the following (or it is assumed to be `none`):

- `none`: No validation is necessary.
- `requireEq`: The `bytes32` `traitValue` MUST be equal to the value at the time the offer to purchase was made.
- `requireNeq`: The `bytes32` `traitValue` MUST NOT be equal to the value at the time the offer to purchase was made.
- `requireUintLt`: The `bytes32` `traitValue` MUST be less than the value at the time the offer to purchase was made. This comparison is made using the `uint256` representation of the `bytes32` value.
- `requireUintLte`: The `bytes32` `traitValue` MUST be less than or equal to the value at the time the offer to purchase was made. This comparison is made using the `uint256` representation of the `bytes32` value.
- `requireUintGt`: The `bytes32` `traitValue` MUST be greater than the value at the time the offer to purchase was made. This comparison is made using the `uint256` representation of the `bytes32` value.
- `requireUintGte`: The `bytes32` `traitValue` MUST be greater than or equal to the value at the time the offer to purchase was made. This comparison is made using the `uint256` representation of the `bytes32` value.

Note that even though this specification requires marketplaces to validate the required trait values, buyers and sellers cannot fully rely on marketplaces to do this and must also take their own precautions to research the current trait values prior to initiating the transaction.

Here is an example of the specified schema:

```json
{
  &quot;traits&quot;: {
    &quot;color&quot;: {
      &quot;displayName&quot;: &quot;Color&quot;,
      &quot;dataType&quot;: {
        &quot;type&quot;: &quot;string&quot;
      }
    },
    &quot;points&quot;: {
      &quot;displayName&quot;: &quot;Total Score&quot;,
      &quot;dataType&quot;: {
        &quot;type&quot;: &quot;decimal&quot;,
        &quot;signed&quot;: false,
        &quot;decimals&quot;: 0
      },
      &quot;validateOnSale&quot;: &quot;requireUintGte&quot;
    },
    &quot;name&quot;: {
      &quot;displayName&quot;: &quot;Name&quot;,
      &quot;dataType&quot;: {
        &quot;type&quot;: &quot;string&quot;,
        &quot;minLength&quot;: 1,
        &quot;maxLength&quot;: 32,
        &quot;valueMappings&quot;: {
          &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;: &quot;Unnamed&quot;,
          &quot;0x92e75d5e42b80de937d204558acf69c8ea586a244fe88bc0181323fe3b9e3ebf&quot;: &quot;🙂&quot;
        }
      },
      &quot;tokenOwnerCanUpdateValue&quot;: true
    },
    &quot;birthday&quot;: {
      &quot;displayName&quot;: &quot;Birthday&quot;,
      &quot;dataType&quot;: {
        &quot;type&quot;: &quot;epochSeconds&quot;,
        &quot;valueMappings&quot;: {
          &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;: null
        }
      }
    },
    &quot;0x77c2fd45bd8bdef5b5bc773f46759bb8d169f3468caab64d7d5f2db16bb867a8&quot;: {
      &quot;displayName&quot;: &quot;🚢 📅&quot;,
      &quot;dataType&quot;: {
        &quot;type&quot;: &quot;epochSeconds&quot;,
        &quot;valueMappings&quot;: {
          &quot;0x0000000000000000000000000000000000000000000000000000000000000000&quot;: 1696702201
        }
      }
    }
  }
}
```

#### `string` Metadata Type

The `string` metadata type allows for a string value to be set for a trait.

The `dataType` object MAY have a `minLength` and `maxLength` value defined. If `minLength` is not specified, it is assumed to be 0. If `maxLength` is not specified, it is assumed to be a reasonable length.

The `dataType` object MAY have a `valueMappings` object defined. If the `valueMappings` object is defined, the `valueMappings` object MUST be a mapping of `bytes32` values to `string` or unset `null` values. The `bytes32` values SHOULD be the `keccak256` hash of the `string` value. The `string` values MUST be unique. If the trait for a token is updated to `null`, it is expected that offchain indexers will delete the trait for the token.

#### `decimal` Metadata Type

The `decimal` metadata type allows for a numeric value to be set for a trait in decimal form.

The `dataType` object MAY have a `signed` value defined. If `signed` is not specified, it is assumed to be `false`. This determines whether the `traitValue` returned is interpreted as a signed or unsigned integer.

The `dataType` object MAY have `minValue` and `maxValue` values defined. These should be formatted with the decimals specified. If `minValue` is not specified, it is assumed to be the minimum value of `signed` and `decimals`. If `maxValue` is not specified, it is assumed to be the maximum value of the `signed` and `decimals`.

The `dataType` object MAY have a `decimals` value defined. The `decimals` value MUST be a non-negative integer. The `decimals` value determines the number of decimal places included in the `traitValue` returned onchain. If `decimals` is not specified, it is assumed to be 0.

The `dataType` object MAY have a `valueMappings` object defined. If the `valueMappings` object is defined, the `valueMappings` object MUST be a mapping of `bytes32` values to numeric or unset `null` values.

#### `boolean` Metadata Type

The `boolean` metadata type allows for a boolean value to be set for a trait.

The `dataType` object MAY have a `valueMappings` object defined. If the `valueMappings` object is defined, the `valueMappings` object MUST be a mapping of `bytes32` values to `boolean` or unset `null` values. The `boolean` values MUST be unique.

If `valueMappings` is not used, the default trait values for `boolean` should be `bytes32(0)` for `false` and `bytes32(uint256(1))` (`0x0000000000000000000000000000000000000000000000000000000000000001`) for `true`.

#### `epochSeconds` Metadata Type

The `epochSeconds` metadata type allows for a numeric value to be set for a trait in seconds since the Unix epoch.

The `dataType` object MAY have a `valueMappings` object defined. If the `valueMappings` object is defined, the `valueMappings` object MUST be a mapping of `bytes32` values to integer or unset `null` values.

### Events

Updating traits MUST emit one of:

- `TraitUpdated`
- `TraitUpdatedRange`
- `TraitUpdatedRangeUniformValue`
- `TraitUpdatedList`
- `TraitUpdatedListUniformValue`

For the `Range` events, the `fromTokenId` and `toTokenId` MUST be a consecutive range of tokens IDs and MUST be treated as an inclusive range.

For the `List` events, the `tokenIds` MAY be in any order.

It is RECOMMENDED to use the `UniformValue` events when the trait value is uniform across all token ids, so offchain indexers can more quickly process bulk updates rather than fetching each trait value individually.

Updating the trait metadata MUST emit the event `TraitMetadataURIUpdated` so offchain indexers can be notified to query the contract for the latest changes via `getTraitMetadataURI()`.

Note that dynamic trait values MUST NOT be based on time-dependent factors (e.g. block timestamp) or other implicit state changes. All trait changes MUST be the result of an explicit onchain action that emits a corresponding `TraitUpdated` event. This requirement ensures that offchain indexers can remain synchronized with the current trait values by processing emitted events, rather than needing to continuously poll or re-evaluate trait values.

### `setTrait`

If a trait defines `tokenOwnerCanUpdateValue` as `true`, then the trait value MUST be updatable by the token owner by calling `setTrait`.

If the value the token owner is attempting to set is not valid, the transaction MUST revert. If the value is valid, the trait value MUST be updated and one of the `TraitUpdated` events MUST be emitted.

If the trait has a `valueMappings` entry defined for the desired value being set, `setTrait` MUST be called with the corresponding `traitValue`.

## Rationale

The design of this specification is primarily a key-value mapping for maximum flexibility. This interface for traits was chosen instead of relying on using regular `getFoo()` and `setFoo()` style functions to allow for brevity in defining, setting, and getting traits. Otherwise, contracts would need to know both the getter and setter function selectors including the parameters that go along with it. In defining general but explicit get and set functions, the function signatures are known and only the trait key and values are needed to query and set the values. Contracts can also add new traits in the future without needing to modify contract code.

The traits metadata allows for customizability of both display and behavior. The `valueMappings` property can define human-readable values to enhance the traits, for example, the default label of the `0` value (e.g. if the key was &quot;redeemed&quot;, &quot;0&quot; could be mapped to &quot;No&quot;, and &quot;1&quot; to &quot;Yes&quot;). The `validateOnSale` property lets the token creator define which traits should be protected on order creation and fulfillment, to protect end users against frontrunning.

## Backwards Compatibility

As a new EIP, no backwards compatibility issues are present, except for the point in the specification above that it is explicitly required that the onchain traits MUST override any conflicting values specified by the ERC-721 or ERC-1155 metadata URIs.

## Test Cases

Authors have included Foundry tests covering functionality of the specification in the [assets folder](/EIPs/assets/eip-7496/ERC721DynamicTraits.t.sol).

## Reference Implementation

Authors have included reference implementations of the specification in the [assets folder](/EIPs/assets/eip-7496/DynamicTraits.sol).

## Security Considerations

The set\* methods exposed externally MUST be permissioned so they are not callable by everyone but only by select roles or addresses.

Marketplaces SHOULD NOT trust offchain state of traits as they can be frontrunned. Marketplaces SHOULD check the current state of onchain traits at the time of transfer. Marketplaces MAY check certain traits that change the value of the NFT (e.g. redemption status, defined by metadata values with `validateOnSale` property) or they MAY hash all the trait values to guarantee the same state at the time of order creation.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 28 Jul 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7496</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7496</guid>
      </item>
    
      <item>
        <title>NFT Redeemables</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7498-nft-redeemables/15485</comments>
        
        <description>## Abstract

This specification introduces a new interface that extends [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155) to enable the discovery and use of onchain and offchain redeemables for NFTs. Onchain getters and events facilitate discovery of redeemable campaigns and their requirements. New onchain mints use an interface that gives context to the minting contract of what was redeemed. For redeeming physical products and goods (offchain redeemables) a `redemptionHash` and `signer` can tie onchain redemptions with offchain order identifiers that contain chosen product and shipping information.

## Motivation

Creators frequently use NFTs to create redeemable entitlements for digital and physical goods. However, without a standard interface, it is challenging for users and apps to discover and interact with these NFTs in a predictable and standard way. This standard aims to encompass enabling broad functionality for:

- discovery: events and getters that provide information about the requirements of a redemption campaign
- onchain: token mints with context of items spent
- offchain: the ability to associate with ecommerce orders (through `redemptionHash`)
- trait redemptions: improving the burn-to-redeem experience with [ERC-7496](/EIPs/EIPS/eip-7496) Dynamic Traits.

## Specification

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

The token MUST have the following interface and MUST return `true` for [ERC-165](/EIPs/EIPS/eip-165) supportsInterface for `0x1ac61e13`, the 4 byte interfaceId of the below.

```solidity
interface IERC7498 {
  /* Events */
  event CampaignUpdated(uint256 indexed campaignId, Campaign campaign, string metadataURI);
  event Redemption(uint256 indexed campaignId, uint256 requirementsIndex, bytes32 redemptionHash, uint256[] considerationTokenIds, uint256[] traitRedemptionTokenIds, address redeemedBy);

  /* Structs */
  struct Campaign {
    CampaignParams params;
    CampaignRequirements[] requirements; // one requirement must be fully satisfied for a successful redemption
  }
  struct CampaignParams {
    uint32 startTime;
    uint32 endTime;
    uint32 maxCampaignRedemptions;
    address manager; // the address that can modify the campaign
    address signer; // null address means no EIP-712 signature required
  }
  struct CampaignRequirements {
    OfferItem[] offer;
    ConsiderationItem[] consideration;
    TraitRedemption[] traitRedemptions;
  }
  struct TraitRedemption {
    uint8 substandard;
    address token;
    bytes32 traitKey;
    bytes32 traitValue;
    bytes32 substandardValue;
  }

  /* Getters */
  function getCampaign(uint256 campaignId) external view returns (Campaign memory campaign, string memory metadataURI, uint256 totalRedemptions);

  /* Setters */
  function createCampaign(Campaign calldata campaign, string calldata metadataURI) external returns (uint256 campaignId);
  function updateCampaign(uint256 campaignId, Campaign calldata campaign, string calldata metadataURI) external;
  function redeem(uint256[] calldata considerationTokenIds, address recipient, bytes calldata extraData) external payable;
}

---

/* Seaport structs, for reference, used in offer/consideration above */
enum ItemType {
    NATIVE,
    ERC20,
    ERC721,
    ERC1155
}
struct OfferItem {
    ItemType itemType;
    address token;
    uint256 identifierOrCriteria;
    uint256 startAmount;
    uint256 endAmount;
}
struct ConsiderationItem extends OfferItem {
    address payable recipient;
    // (note: psuedocode above, as of this writing can&apos;t extend structs in solidity)
}
struct SpentItem {
    ItemType itemType;
    address token;
    uint256 identifier;
    uint256 amount;
}
```

### Creating campaigns

When creating a new campaign, `createCampaign` MUST be used and MUST return the newly created `campaignId` along with the `CampaignUpdated` event. The `campaignId` MUST be a counter incremented with each new campaign. The first campaign MUST have an id of `1`.

### Updating campaigns

Updates to campaigns MAY use `updateCampaign` and MUST emit the `CampaignUpdated` event. If an address other than the `manager` tries to update the campaign, it MUST revert with `NotManager()`. If the manager wishes to make the campaign immutable, the `manager` MAY be set to the null address.

### Offer

If tokens are set in the params `offer`, the tokens MUST implement the `IRedemptionMintable` interface in order to support minting new items. The implementation SHOULD be however the token mechanics are desired. The implementing token MUST return true for ERC-165 `supportsInterface` for the interfaceId of `IRedemptionMintable`, `0x81fe13c2`.

```solidity
interface IRedemptionMintable {
    function mintRedemption(
        uint256 campaignId,
        address recipient,
        OfferItem calldata offer,
        ConsiderationItem[] calldata consideration,
        TraitRedemption[] calldata traitRedemptions
    ) external;
}
```

When `mintRedemption` is called, it is RECOMMENDED to replace the token identifiers in the consideration items and trait redemptions with the items actually being redeemed.

### Consideration

Any token may be specified in the campaign requirement `consideration`. This will ensure the token is transferred to the `recipient`. If the token is meant to be burned, the recipient SHOULD be `0x000000000000000000000000000000000000dEaD`. If the token can internally handle burning its own tokens and reducing totalSupply, the token MAY burn the token instead of transferring to the recipient `0x000000000000000000000000000000000000dEaD`.

### Dynamic traits

Including trait redemptions is optional, but if the token would like to enable trait redemptions the token MUST include [ERC-7496](/EIPs/EIPS/eip-7496) Dynamic Traits.

### Signer

A signer MAY be specified to provide a signature to process the redemption. If the signer is not the null address, the signature MUST recover to the signer address via [EIP-712](/EIPs/EIPS/eip-712) or [ERC-1271](/EIPs/EIPS/eip-1271).

The EIP-712 struct for signing MUST be as follows: `SignedRedeem(address owner,uint256[] considerationTokenIds,uint256[] traitRedemptionTokenIds,uint256 campaignId,uint256 requirementsIndex, bytes32 redemptionHash, uint256 salt)&quot;`

### Redeem function

The `redeem` function MUST use the `consideration`, `offer`, and `traitRedemptions` specified by the `requirements` determined by the `campaignId` and `requirementsIndex`:

- Execute the transfers in the `consideration`
- Mutate the traits specified by `traitRedemptions` according to ERC-7496 Dynamic Traits
- Call `mintRedemption()` on every `offer` item

The `Redemption` event MUST be emitted for every valid redemption that occurs.

#### Redemption extraData

The extraData layout MUST conform to the below:

| bytes    | value                             | description / notes                                                                  |
| -------- | --------------------------------- | ------------------------------------------------------------------------------------ |
| 0-32     | campaignId                        |                                                                                      |
| 32-64    | requirementsIndex                 | index of the campaign requirements met                                               |
| 64-96    | redemptionHash                    | hash of offchain order ids                                                           |
| 96-\*    | uint256[] traitRedemptionTokenIds | token ids for trait redemptions, MUST be in same order of campaign TraitRedemption[] |
| \*-(+32) | salt                              | if signer != address(0)                                                              |
| \*-(+\*) | signature                         | if signer != address(0). can be for EIP-712 or ERC-1271                              |

The `requirementsIndex` MUST be the index in the `requirements` array that satisfies the redemption. This helps reduce gas to find the requirement met.

The `traitRedemptionTokenIds` specifies the token IDs required for the trait redemptions in the requirements array. The order MUST be the same order of the token addresses expected in the array of `TraitRedemption` structs in the campaign requirement used.

If the campaign `signer` is the null address the `salt` and `signature` MUST be omitted.

The `redemptionHash` is designated for offchain redemptions to reference offchain order identifiers to track the redemption to.

The function MUST check that the campaign is active (using the same boundary check as Seaport, `startTime &lt;= block.timestamp &lt; endTime`). If it is not active, it MUST revert with `NotActive()`.

### Trait redemptions

The token MUST respect the TraitRedemption substandards as follows:

| substandard ID | description                     | substandard value                                                  |
| -------------- | ------------------------------- | ------------------------------------------------------------------ |
| 1              | set value to `traitValue`       | prior required value. if blank, cannot be the `traitValue` already |
| 2              | increment trait by `traitValue` | max value                                                          |
| 3              | decrement trait by `traitValue` | min value                                                          |
| 4              | check value is `traitValue`     | n/a                                                                |

### Max campaign redemptions

The token MUST check that the `maxCampaignRedemptions` is not exceeded. If the redemption does exceed `maxCampaignRedemptions`, it MUST revert with `MaxCampaignRedemptionsReached(uint256 total, uint256 max)`

### Metadata URI

The metadata URI MUST conform to the below JSON schema:

```json
{
  &quot;$schema&quot;: &quot;https://json-schema.org/draft/2020-12/schema&quot;,
  &quot;type&quot;: &quot;object&quot;,
  &quot;properties&quot;: {
    &quot;campaigns&quot;: {
      &quot;type&quot;: &quot;array&quot;,
      &quot;items&quot;: {
        &quot;type&quot;: &quot;object&quot;,
        &quot;properties&quot;: {
          &quot;campaignId&quot;: {
            &quot;type&quot;: &quot;number&quot;
          },
          &quot;name&quot;: {
            &quot;type&quot;: &quot;string&quot;
          },
          &quot;description&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;A one-line summary of the redeemable. Markdown is not supported.&quot;
          },
          &quot;details&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;A multi-line or multi-paragraph description of the details of the redeemable. Markdown is supported.&quot;
          },
          &quot;imageUrls&quot;: {
            &quot;type&quot;: &quot;array&quot;,
            &quot;items&quot;: {
              &quot;type&quot;: &quot;string&quot;
            },
            &quot;description&quot;: &quot;A list of image URLs for the redeemable. The first image will be used as the thumbnail. Will rotate in a carousel if multiple images are provided. Maximum 5 images.&quot;
          },
          &quot;bannerUrl&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;The banner image for the redeemable.&quot;
          },
          &quot;faq&quot;: {
            &quot;type&quot;: &quot;array&quot;,
            &quot;items&quot;: {
              &quot;type&quot;: &quot;object&quot;,
              &quot;properties&quot;: {
                &quot;question&quot;: {
                  &quot;type&quot;: &quot;string&quot;
                },
                &quot;answer&quot;: {
                  &quot;type&quot;: &quot;string&quot;
                },
                &quot;required&quot;: [&quot;question&quot;, &quot;answer&quot;]
              }
            }
          },
          &quot;contentLocale&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;The language tag for the content provided by this metadata. https://www.rfc-editor.org/rfc/rfc9110.html#name-language-tags&quot;
          },
          &quot;maxRedemptionsPerToken&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;The maximum number of redemptions per token. When isBurn is true should be 1, else can be a number based on the trait redemptions limit.&quot;
          },
          &quot;isBurn&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;If the redemption burns the token.&quot;
          },
          &quot;uuid&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;An optional unique identifier for the campaign, for backends to identify when draft campaigns are published onchain.&quot;
          },
          &quot;productLimitForRedemption&quot;: {
            &quot;type&quot;: &quot;number&quot;,
            &quot;description&quot;: &quot;The number of products which are able to be chosen from the products array for a single redemption.&quot;
          },
          &quot;products&quot;: {
            &quot;type&quot;: &quot;object&quot;,
            &quot;properties&quot;: &quot;https://schema.org/Product&quot;,
            &quot;required&quot;: [&quot;name&quot;, &quot;url&quot;, &quot;description&quot;]
          }
        },
        &quot;required&quot;: [&quot;campaignId&quot;, &quot;name&quot;, &quot;description&quot;, &quot;imageUrls&quot;, &quot;isBurn&quot;]
      }
    }
  }
}
```

Future EIPs MAY inherit this one and add to the above metadata to add more features and functionality.

### ERC-1155 (Semi-fungibles)

This standard MAY be applied to ERC-1155 but the redemptions would apply to all token amounts for specific token identifiers. If the ERC-1155 contract only has tokens with amount of 1, then this specification MAY be used as written.

## Rationale

The &quot;offer&quot; and &quot;consideration&quot; structs from Seaport were used to create a similar language for redeemable campaigns. The &quot;offer&quot; is what is being offered, e.g. a new onchain token, and the &quot;consideration&quot; is what must be satisfied to complete the redemption. The &quot;consideration&quot; field has a &quot;recipient&quot;, who the token should be transferred to. For trait updates that do not require moving of a token, `traitRedemptionTokenIds` is specified instead.

The &quot;salt&quot; and &quot;signature&quot; fields are provided primarily for offchain redemptions where a provider would want to sign approval for a redemption before it is conducted onchain, to prevent the need for irregular state changes. For example, if a user lives outside a region supported by the shipping of an offchain redeemable, during the offchain order creation process the signature would not be provided for the onchain redemption when seeing that the user&apos;s shipping country is unsupported. This prevents the user from redeeming the NFT, then later finding out the shipping isn&apos;t supported after their NFT is already burned or trait is mutated.

[ERC-7496](/EIPs/EIPS/eip-7496) Dynamic Traits is used for trait redemptions to support onchain enforcement of trait values for secondary market orders.

## Backwards Compatibility

As a new EIP, no backwards compatibility issues are present.

## Test Cases

Authors have included Foundry tests covering functionality of the specification in the [assets folder](/EIPs/assets/eip-7498/ERC721ShipyardRedeemable.t.sol).

## Reference Implementation

Authors have included reference implementations of the specification in the [assets folder](/EIPs/assets/eip-7498/ERC7498NFTRedeemables.sol).

## Security Considerations

If trait redemptions are desired, tokens implementing this EIP must properly implement [ERC-7496](/EIPs/EIPS/eip-7496) Dynamic Traits.

For tokens to be minted as part of the params `offer`, the `mintRedemption` function contained as part of `IRedemptionMintable` MUST be permissioned and ONLY allowed to be called by specified addresses.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 28 Jul 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7498</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7498</guid>
      </item>
    
      <item>
        <title>Zero-Knowledge Wormholes</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7503-zero-knowledge-wormholes-private-proof-of-burn-ppob/15456</comments>
        
        <description>## Abstract

While researching on privacy solutions and applications of ZKP, we discovered a technique, 
by which people can burn their digital asset (E.g ETH) by sending it to an unspendable address, 
and later build a ZK proof showing that some amount of tokens reside in an account that are 
unspendable, without revealing the account.

The EIP proposes to add a minting functionality to Ethereum, so that people can re-mint 
Ethers they have purposefully burnt. The mentioned privacy solution will bring strong levels of
***plausible deniability*** for the sender, since there is no way one can prove that the sender 
has been participating in a privacy protocol. This will also make an anonymity pool that includes 
all of the Ethereum accounts with zero outgoing transactions by default.

## Specification

### Parameters

* `MAGIC_ADDRESS`: `0xfe` (one byte)
* `MAGIC_NULLIFIER`: `0x01` (one byte)
* `MAGIC_POW`: `0x02` (one byte)
* `MAGIC_CHANGE`: `0x0404040404040404040404040404040404040404040404040404040404040404`
* `POW_LOG_DIFFICULTY`: `24`
* `MAX_DEPOSIT`: `32 * 10**18` wei
* `WormholeTxType`: `TBD`
* `WORMHOLE_NULLIFIER_ADDRESS`: `TBD`
* `RECEIPT_PREFIX`: `TBD` (datatype `List[bool]`)

- - - 

We define a new [EIP-2718](/EIPs/EIPS/eip-2718) transaction type, where `TransactionType` is `WormholeTxType` and the `TransactionPayload` format is as follows:

`[chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to, data, access_list, root_beacon_block_number, proof]`

Verifying this type of transaction requires confirming that:

1. The proof is a zero-knowledge proof:
    * Private inputs: `secret`, `main_index`, `main_branch`, `privacy_pool_index`, `privacy_pool_branch`, `deposit_value`, `deposit_sender`, `change_value_salt`, `change_value`
    * Public inputs: `beacon_block_root`, `nullifier`, `privacy_pool_root`, `withdraw_value`, `change_value_hash`
    * Function: verify all of the following conditions
        * `verify_merkle_branch(root=beacon_block_root, index=RECEIPT_PREFIX + main_index, leaf=make_receipt_hash(deposit_sender, deposit_value, change_value_salt, secret), branch=main_branch)`
        * `verify_merkle_branch(root=privacy_pool_root, index=privacy_pool_index, leaf=make_receipt_hash(deposit_sender, deposit_value, change_value_salt, secret), branch=privacy_pool_branch)`
        * `nullifier == sha256(MAGIC_NULLIFIER + secret)`
        * `sha256(MAGIC_POW + secret) % 2**POW_LOG_DIFFICULTY == 0`
        * `change_value_hash == sha256(change_value_salt, change_value)`
        * `change_value + withdraw_value == deposit_value` (all values are unsigned int, also need to confirm that there is no overflow)
        * `deposit_value &lt;= MAX_DEPOSIT`
2. `SLOAD(WORMHOLE_NULLIFIER_ADDRESS, proof.nullifier) == 0`
3. `get_beacon_block_root(root_beacon_block_number) == proof.beacon_block_root`

We define `make_receipt_hash` as follows:

```
def make_receipt_hash(deposit_sender: Address, value: uint256, change_value_salt: bytes32, secret: bytes32):
    if deposit_sender != 0:
        to_address = sha256(MAGIC_ADDRESS + secret)[12:]
        topics = [MAGIC_EIP_7708, deposit_sender, to_address]
        logdata = int_to_bytes32(value)
    else:
        topics = [MAGIC_CHANGE, hash(change_value_salt, value)]
        logdata = bytes([])
    return get_ssz_root_hash(Log(topics=topics, data=logdata))
```

The hash of the transaction (excluding proof) should be included in the randomness for generating the zero-knowledge proof. This ensures the proof serves as a signature.

If the transaction is confirmed, generate `proof.withdraw_value` ether at address `WORMHOLE_NULLIFIER_ADDRESS`. Then proceed with a normal call from this address using that value. Before the call, set `SSTORE(WORMHOLE_NULLIFIER_ADDRESS, proof.nullifier, 1)`, and emit a log event where `topics = [MAGIC_CHANGE, proof.change_value_hash]` and `logdata = bytes([])`.

## Rationale 

In Elliptic-Curve based digital signatures, normally there is a secret scalar $s$, from which 
a public-key is calculated (By multiplying the generator point with the scalar: $s \times G$). An 
Ethereum EOA-address is the keccak hash of a public-key.

Also, the funds in an Ethereum address might be spendable by a smart-contract, if the keccak hash
of the smart-contract&apos;s parameters is equal with that address.

Therefore, an Ethereum address $A$ is spendable if and only if:

 1. A private-key $s$ exists. such that $A = keccak(s \times G)$.
 2. There exists a smart-contract $c$, such that $A = keccak(c_{params})$.

The preimage resistance property of hash functions implies that, you can&apos;t find $x$ where $keccak(x)=r$,
in case $r$ is a random value. So the funds sent to a random Ethereum address $r$ is unspendable, but 
how can other people be sure that $r$ is indeed random and not the result of calculating $s \times G$?

A great source of randomness is a hash function. If the address is equal with the hash of a secret preimage 
$s$, we can conclude that the address is unspendable, since there isn&apos;t a polynomially bounded algorithm 
to find $x$ where $keccak(x)=h(s)$. This is only true if the second hash function is a different hash 
function, and it assumes it is impossible to find $x_1$ and $x_2$ such that $h_1(x_1)=h_2(x_2)$ in case
$h_1$ and $h_2$ are different hash functions.

Using the help of Zero-Knowledge proofs, we can hide the value of $s$! We just need to prove that 
we know a secret value $s$ where the address is $h(s)$. We can go even further. We can prove 
that an Ethereum accounts exists in the state-root, which holds some amount of ETH and is unspendable.

By revealing this to the Ethereum blockchain and providing something like a nullifier 
(E.g. $h(s | 123)$ so that double minting of same burnt tokens are not possible), we can add a new 
***minting*** functionality for ETH so that people can migrate their secretly burnt tokens to a 
completely new address, without any trace on the blockchain. 

Cryptocurrency mixers like TornadoCash can successfully obfuscate Ethereum transactions, but it&apos;s
easy for the governments to ban usage of them. Anybody who has interactions with a mixer contract,
whether the sender or receiver, can get marked. However this EIP tries to minimize the privacy leakage 
of the senders, by requiring zero smart-contract interactions in order to send money, so 
we only use plain EOA-to-EOA transfers. In order to have a &quot;teleportation&quot; mechanism we divide
the set of all Secp256k1 points $E(K)$ into two subsets/address-spaces:

 - The spendable address-space: $\\{p \in \\{0,1\\}^{160} | \exists s : keccak(s \times G)=p \lor \exists c : keccak(c_{params})=p \\}$
 - The unspendable address-space: $\\{p \in \\{0,1\\}^{160} | \nexists s : keccak(s \times G)=p \land \nexists c : keccak(c_{params})=p \\}$

The spendable/unspendable addresses are not distinguishable, so we can exploit this fact and define
a spendability rule for the money sent to addresses that can&apos;t be spent using regular elliptic-curve
signatures. 

Deposits are made by sending ether to an address `sha256(MAGIC_ADDRESS + secret)[12:]`, where you know the `secret`. This ensures that no one knows about the deposit unless you reveal it: a deposit onchain is not distinguishable from sending ether to a friend. Withdrawals use a zero-knowledge proof to prove knowledge of a previous deposit&apos;s `secret`.

A deposit can come from two places: a standard deposit by sending ether, or a change deposit. A change deposit is automatically generated when withdrawing funds from another deposit (standard or change). The entire deposited amount does not have to be withdrawn; for example, if 20 ether was deposited and only 12 is withdrawn, the system will make a new change deposit of 8 ether. The value of this change deposit is hashed, so someone looking at the chain cannot calculate `change deposit value + withdrawal value = old deposit value` and use the value to expose the original deposit.

This EIP requires that [EIP-7708](/EIPs/EIPS/eip-7708) be in place along with an EIP to change receipts to SSZ format. This simplifies the proof as it only needs to verify a regular SHA256 Merkle branch verifying a log, there is no need to do verkle or RLP or other complex logic inside the proof. The log can be of two types: an EIP-7708 ETH transfer log, or a log generated by this EIP itself through the change mechanism.

The EIP also includes a privacy pool [^1] mechanism where you must provide a privacy pool root, which corresponds to a list of deposits, so you prove that your deposit is one of the deposits in that list. Since this second Merkle branch mechanism is integrated into the proof, the marginal cost for a user to use it is zero, ensuring maximum adoption and maximizing the chance that privacy will be used responsibly. The privacy pools paper explains in much more detail the value of this privacy pools mechanism, and the benefits of an ecosystem where almost all legitimate users use it.

The built-in PoW and 32 ETH limit prevent hash collision attacks: if an attacker can find collision `(x1, x2)` such that `create2_address(..., x1) == sha256(MAGIC_ADDRESS + x2)`, the attacker could extract their ether twice (but only twice). Such an attack requires approximately `2**80` hashes. Adding 24 bits of PoW increases the difficulty to `2**92`. This many hashes can be computed but is very difficult; currently, mining a Bitcoin block takes around `2**79` hashes, so those with the capabilities to attack this mechanism have a much more lucrative opportunity in Bitcoin mining.

### Scalability Implications

In case the circuits are able to simultaneously re-mint the sum of multiple burns in a single-proof, 
merchants and CEXs will be able to accept their payments in burn-addresses and accumulate their funds
in a single address by storing a single proof (And a bunch of nullifiers) on the blockchain, which
significantly reduces the transaction count on the blockchain. The people who will use this EIP as a
scalability solution, will also increase the privacy guarantees of the protocol.

## Backwards Compatibility

The Ethers generated using the mint function should not have any difference with original Ethers.
People should be able to use those minted Ethers for paying the gas fees.

## Reference Implementation

To be determined (TBD).

### ZK-SNARK Implementation

Also TBD, but the implementation must meet the following conditions:

* Use a transparent setup; ideally reuse the [EIP-4844](/EIPs/EIPS/eip-4844) setup. Do not use Groth16 or other application-specific setups.
* The circuit should be directly verifiable without blindly trusting compilers like Circom. SHA256 is not too complicated and can be implemented using PLOOKUP with an 8-bit lookup table for arithmetic operations, which should suffice. There is no need to over-focus on prover efficiency.
* Elliptic curves must still be used; Stark is too large.

## Security Considerations

In case of faulty implementation of this EIP, people may mint infinite amount of ETH, collapsing the price of Ethereum.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[^1]:
    ```csl-json
    {
      &quot;type&quot;: &quot;article&quot;,
      &quot;id&quot;: 1,
      &quot;author&quot;: [
        {
          &quot;family&quot;: &quot;Buterin&quot;,
          &quot;given&quot;: &quot;Vitalik&quot;
        },
        {
          &quot;family&quot;: &quot;Illum&quot;,
          &quot;given&quot;: &quot;Jacob&quot;
        },
        {
          &quot;family&quot;: &quot;Nadler&quot;,
          &quot;given&quot;: &quot;Matthias&quot;
        },
        {
          &quot;family&quot;: &quot;Schär&quot;,
          &quot;given&quot;: &quot;Fabian&quot;
        },
        {
          &quot;family&quot;: &quot;Soleimani&quot;,
          &quot;given&quot;: &quot;Ameen&quot;
        }
      ],
      &quot;DOI&quot;: &quot;10.2139/ssrn.4563364&quot;,
      &quot;title&quot;: &quot;Blockchain Privacy and Regulatory Compliance: Towards a Practical Equilibrium&quot;,
      &quot;original-date&quot;: {
        &quot;date-parts&quot;: [
          [2023, 9, 6]
        ]
      },
      &quot;URL&quot;: &quot;https://ssrn.com/abstract=4563364&quot;,
      &quot;custom&quot;: {
        &quot;additional-urls&quot;: [
          &quot;http://dx.doi.org/10.2139/ssrn.4563364&quot;
        ]
      }
    }
    ```
</description>
        <pubDate>Mon, 14 Aug 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7503</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7503</guid>
      </item>
    
      <item>
        <title>Trusted Hint Registry</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-trusted-hint-registry/15615</comments>
        
        <description>## Abstract

This EIP standardizes a system for managing on-chain metadata (hints), enabling claim interpretation, reliability, 
and verification. It structures these hints within defined namespaces and lists, enabling structured organization and 
retrieval, as well as permissioned write access. The system permits namespace owners to delegate hint management tasks, 
enhancing operational flexibility. It incorporates secure meta transactions via [EIP-712](/EIPs/EIPS/eip-712)-enabled 
signatures and offers optional ENS integration for trust verification and discoverability. The interface is equipped to
emit specific events for activities like hint modifications, facilitating easy traceability of changes to hints. This 
setup aims to provide a robust, standardized framework for managing claim- and ecosystem-related metadata, essential for 
maintaining integrity and trustworthiness in decentralized environments.

## Motivation

In an increasingly interconnected and decentralized landscape, the formation of trust among entities remains a critical
concern. Ecosystems, both on-chain and off-chain—spanning across businesses, social initiatives, and other organized
frameworks—frequently issue claims for or about entities within their networks. These claims serve as the foundational
elements of trust, facilitating interactions and transactions in environments that are essentially untrustworthy by
nature. While the decentralization movement has brought about significant improvements around trustless technologies,
many ecosystems building on top of these are in need of technologies that build trust in their realm. Real-world
applications have shown that verifiable claims alone are not enough for this purpose. Moreover, a supporting layer of
on-chain metadata is needed to support a reliable exchange and verification of those claims.

The absence of a structured mechanism to manage claim metadata on-chain poses a significant hurdle to the formation and 
maintenance of trust among participating entities in an ecosystem. This necessitates the introduction of a layer of 
on-chain metadata, which can assist in the reliable verification and interpretation of these claims. Termed &quot;hints&quot; in 
this specification, this metadata can be used in numerous ways, each serving to bolster the integrity and reliability 
of the ecosystem&apos;s claims. Hints can perform various tasks, such as providing revocation details, identifying trusted 
issuers, or offering timestamping hashes. These are just a few examples that enable ecosystems to validate and 
authenticate claims, as well as verify data integrity over time.

The proposed &quot;Trusted Hint Registry&quot; aims to provide a robust, flexible, and standardized interface for managing such
hints. The registry allows any address to manage multiple lists of hints, with a set of features that not only make it
easier to create and manage these hints but also offer the flexibility of delegating these capabilities to trusted
entities. In practice, this turns the hint lists into dynamic tools adaptable to varying requirements and use cases.
Moreover, an interface has been designed with a keen focus on interoperability, taking into consideration existing W3C
specifications around Decentralized Identifiers and Verifiable Credentials, as well as aligning with on-chain projects
like the Ethereum Attestation Service.

By providing a standardized smart contract interface for hint management, this specification plays an integral role in
enabling and scaling trust in decentralized ecosystems. It offers a foundational layer upon which claims — both on-chain
and off-chain — can be reliably issued, verified, and interpreted, thus serving as an essential building block for the
credible operation of any decentralized ecosystem. Therefore, the Trusted Hint Registry is not just an addition to the
ecosystem but a necessary evolution in the complex topology of decentralized trust.

## Specification

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.

This EIP specifies a contract called `TrustedHintRegistry` and standardizes a set of **REQUIRED** core hint functions,
while also providing a common set of **OPTIONAL** management functions, enabling various ways for collaborative hint 
management. Ecosystems **MAY** use this specification to build their own hint registry contracts with ecosystem-specific, 
non-standardized features. Governance is deliberately excluded from this ERC and **MAY** be implemented according to an
ecosystem&apos;s need.

### Definitions

- `claim`: A claim is a statement about an entity made by another entity.
- `hint`: A &quot;hint&quot; refers to a small piece of information that provides insights, aiding in the interpretation, 
   reliability, or verifiability of decentralized ecosystem data.
- `namespace`: A namespace is a representation of an Ethereum address inside the registry that corresponds to its
  owner’s address. A namespace contains hint lists for different use cases.
- `hint list`: A hint list is identified by a unique value that contains a number of hint keys that resolve to hint
  values. An example of this is a revocation key that resolves to a revocation state.
- `hint key`: A hint key is a unique value that resolves to a hint value. An example of this is a trusted issuer
  identifier, which resolves to the trust status of that identifier.
- `hint value`: A hint value expresses data about an entity in an ecosystem.
- `delegate`: An Ethereum address that has been granted writing permissions to a hint list by its owner.

### Interface

#### Hint Management

##### getHint

A method with the following signature **MUST** be implemented that returns the hint value in a hint list of a namespace.

```solidity
function getHint(address _namespace, bytes32 _list, bytes32 _key) external view returns (bytes32);
```

##### setHint

A method with the following signature **MUST** be implemented that changes the hint value in a hint list of a namespace.
An overloaded method with an additional `bytes calldata _metadata` parameter **MAY** be implemented to set metadata 
together with the hint value.

```solidity
function setHint(address _namespace, bytes32 _list, bytes32 _key, bytes32 _value) public;
```

##### setHintSigned

A method with the following signature **MAY** be implemented that changes the hint value in a hint list of a namespace
with a raw signature. The raw signature **MUST** be generated following the Meta Transactions section. An overloaded
method with an additional `bytes calldata _metadata` parameter **MAY** be implemented to set metadata together with the
hint value.

```solidity
function setHintSigned(address _namespace, bytes32 _list, bytes32 _key, bytes32 _value, address _signer, bytes calldata _signature) public;
```

The type hash **MUST** be the keccak256 hash of `SetHintSigned(address namespace,bytes32 list,bytes32 key,bytes32 value,address signer,uint256 nonce)`
or `SetHintSigned(address namespace,bytes32 list,bytes32 key,bytes32 value,bytes metadata,address signer,uint256 nonce)`
when calling the metadata variant.

##### setHints

A method with the following signature **MUST** be implemented that changes multiple hint values in a hint list of a
namespace. An overloaded method with an additional `bytes[] calldata _metadata` parameter **MAY** be implemented to set
metadata together with the hint value.

```solidity
function setHints(address _namespace, bytes32 _list, bytes32[] calldata _keys, bytes32[] calldata _values) public;
```

##### setHintsSigned

A method with the following signature **MUST** be implemented that multiple hint values in a hint list of a namespace
with a raw signature. The raw signature **MUST** be generated following the Meta Transactions section. An overloaded
method with an additional `bytes[] calldata _metadata` parameter **MAY** be implemented to set metadata together with the
hint value.

```solidity
function setHintsSigned(address _namespace, bytes32 _list, bytes32[] calldata _keys, bytes32[] calldata _values, address _signer, bytes calldata _signature) public;
```

The type hash **MUST** be the keccak256 hash of `SetHintsSigned(address namespace,bytes32 list,bytes32[] keys,bytes32[] values,address signer,uint256 nonce)`
or `SetHintsSigned(address namespace,bytes32 list,bytes32[] keys,bytes32[] values,bytes[] metadata,address signer,uint256 nonce)`
when calling the metadata variant.

#### Delegated Hint Management

A namespace owner can add delegate addresses to specific hint lists in their namespace. These delegates **SHALL** have
write access to the specific lists via a specific set of methods.

##### setHintDelegated

A method with the following signature **MAY** be implemented that changes the hint value in a hint list of a namespace
for pre-approved delegates. An overloaded method with an additional `bytes calldata _metadata` parameter **MAY** be
implemented to set metadata together with the hint value.

```solidity
function setHintDelegated(address _namespace, bytes32 _list, bytes32 _key, bytes32 _value) public;
```

##### setHintDelegatedSigned

A method with the following signature **MAY** be implemented that changes the hint value in a hint list of a namespace
for pre-approved delegates with a raw signature. The raw signature **MUST** be generated following the Meta Transactions
section. An overloaded method with an additional `bytes calldata _metadata` parameter **MAY** be implemented to set
metadata together with the hint value.

```solidity
function setHintDelegatedSigned(address _namespace, bytes32 _list, bytes32 _key, bytes32 _value, address _signer, bytes calldata _signature) public;
```

The type hash **MUST** be the keccak256 hash of `SetHintDelegatedSigned(address namespace,bytes32 list,bytes32 key,bytes32 value,address signer,uint256 nonce)`
or `SetHintDelegatedSigned(address namespace,bytes32 list,bytes32 key,bytes32 value,bytes metadata,address signer,uint256 nonce)`
when calling the metadata variant.

##### setHintsDelegated

A method with the following signature **MAY** be implemented that changes multiple hint values in a hint list of a
namespace for pre-approved delegates. An overloaded method with an additional `bytes[] calldata _metadata` parameter
**MAY** be implemented to set metadata together with the hint value.

```solidity
function setHintsDelegated(address _namespace, bytes32 _list, bytes32[] calldata _keys, bytes32[] calldata _values) public;
```

##### setHintsDelegatedSigned

A method with the following signature **MAY** be implemented that has multiple hint values in a hint list of a namespace
for pre-approved delegates with a raw signature. The raw signature **MUST** be generated following the Meta Transactions
section. An overloaded method with an additional `bytes[] calldata _metadata` parameter **MAY** be implemented to set
metadata together with the hint value.

```solidity
function setHintsDelegatedSigned(address _namespace, bytes32 _list, bytes32[] calldata _keys, bytes32[] calldata _values, address _signer, bytes calldata _signature) public;
```

The type hash **MUST** be the keccak256 hash of `SetHintsDelegatedSigned(address namespace,bytes32 list,bytes32[] keys,bytes32[] values,address signer,uint256 nonce)`
or `SetHintsDelegatedSigned(address namespace,bytes32 list,bytes32[] keys,bytes32[] values,bytes[] metadata,address signer,uint256 nonce)`
when calling the metadata variant.

#### Hint List Management

##### setListStatus

A method with the following signature **MAY** be implemented that changes the validity state of a hint list. Revoking a
list **CAN** be used to invalidate all hint values in a list.

```solidity
function setListStatus(address _namespace, bytes32 _list, bool _revoked) public;
```

##### setListStatusSigned

A method with the following signature **MAY** be implemented that changes the validity state of a hint list with a raw
signature. Revoking a list **CAN** be used to invalidate all hint values in a list.

```solidity
function setListStatusSigned(address _namespace, bytes32 _list, bool _revoked, address _signer, bytes calldata _signature) public;
```

The type hash **MUST** be the keccak256 hash of `SetListStatusSigned(address namespace,bytes32 list,bool revoked,address signer,uint256 nonce)`
when generating the signature.

##### setListOwner

A method with the following signature **MAY** be implemented that transfers the ownership of a trust list to another
address. Changing the owner of a list **SHALL NOT** change the namespace the hint list resides in, to retain references
of paths to a hint value.

```solidity
function setListOwner(address _namespace, bytes32 _list, address _newOwner) public;
```

##### setListOwnerSigned

A method with the following signature **MAY** be implemented that transfers the ownership of a trust list to another
address with a raw signature. The raw signature **MUST** be generated following the Meta Transactions section. Changing
the owner of a list **SHALL NOT** change the namespace the hint list resides in, to retain references to paths to a hint
value.

```solidity
function setListOwnerSigned(address _namespace, bytes32 _list, address _newOwner, address _signer, bytes calldata _signature) public;
```

The type hash **MUST** be the keccak256 hash of `SetListOwnerSigned(address namespace,bytes32 list,address newOwner,address signer,uint256 nonce)`
when generating the signature.

##### addListDelegate

A method with the following signature **MAY** be implemented to add a delegate to an owner’s hint list in a namespace.

```solidity
function addListDelegate(address _namespace, bytes32 _list, address _delegate, uint256 _untilTimestamp) public;
```

##### addListDelegateSigned

A method with the following signature **MAY** be implemented to add a delegate to an owner’s hint list in a namespace
with a raw signature. The raw signature **MUST** be generated following the Meta Transactions section.

```solidity
function addListDelegateSigned(address _namespace, bytes32 _list, address _delegate, uint256 _untilTimestamp, address _signer, bytes calldata _signature) public;
```

The type hash **MUST** be the keccak256 hash of `AddListDelegateSigned(address namespace,bytes32 list,address delegate,uint256 untilTimestamp,address signer,uint256 nonce)`
when generating the signature.

##### removeListDelegate

A method with the following signature **MAY** be implemented to remove a delegate from an owner’s hint list in a namespace.

```solidity
function removeListDelegate(address _namespace, bytes32 _list, address _delegate) public;
```

##### removeListDelegateSigned

A method with the following signature **MAY** be implemented to remove a delegate from an owner’s hint list in a namespace 
with a raw signature. The raw signature **MUST** be generated following the Meta Transactions section.

```solidity
function removeListDelegateSigned(address _namespace, bytes32 _list, address _delegate, address _signer, bytes calldata _signature) public;
```

The type hash **MUST** be the keccak256 hash of `RemoveListDelegateSigned(address namespace,bytes32 list,address delegate,address signer,uint256 nonce)`
when generating the signature.

#### Metadata Management

##### getMetadata

A method with the following signature **MAY** be implemented to retrieve metadata for a hint.

```solidity
function getMetadata(address _namespace, bytes32 _list, bytes32 _key, bytes32 _value) external view returns (bytes memory);
```

##### setMetadata

A method with the following signature **MAY** be implemented to set metadata for a hint.

```solidity
function setMetadata(address _namespace, bytes32 _list, bytes32 _key, bytes32 _value, bytes calldata _metadata) public;
```

##### setMetadataSigned

A method with the following signature **MAY** be implemented to set metadata for a hint with a raw signature. The raw
signature **MUST** be generated following the Meta Transactions section.

```solidity
function setMetadataSigned(address _namespace, bytes32 _list, bytes32 _key, bytes32 _value, bytes calldata _metadata, address _signer, bytes calldata _signature) public;
```

The type hash **MUST** be the keccak256 hash of `SetMetadataSigned(address namespace,bytes32 list,bytes32 key,bytes32 value,bytes metadata,address signer,uint256 nonce)`
when generating the signature.

#### setMetadataDelegated

A method with the following signature **MAY** be implemented to set metadata for a hint as a pre-approved delegate of
the hint list.

```solidity
function setMetadataDelegated(address _namespace, bytes32 _list, bytes32 _key, bytes32 _value, bytes calldata _metadata) public;
```

##### setMetadataDelegatedSigned

A method with the following signature **MAY** be implemented to set metadata for a hint as a pre-approved delegate of
the hint list with a raw signature. The raw signature **MUST** be generated following the Meta Transactions section.

```solidity
function setMetadataDelegatedSigned(address _namespace, bytes32 _list, bytes32 _key, bytes32 _value, bytes calldata _metadata, address _signer, bytes calldata _signature) public;
```

The type hash **MUST** be the keccak256 hash of `SetMetadataDelegatedSigned(address namespace,bytes32 list,bytes32 key,bytes32 value,bytes metadata,address signer,uint256 nonce)`
when generating the signature.

#### Events

##### HintValueChanged

**MUST** be emitted when a hint value has changed.

```solidity
event HintValueChanged(
  address indexed namespace,
  bytes32 indexed list,
  bytes32 indexed key,
  bytes32 value
);
```

##### HintListOwnerChanged

**MUST** be emitted when the owner of a list has changed.

```solidity
event HintListOwnerChanged(
  address indexed namespace,
  bytes32 indexed list,
  address indexed newOwner
);
```

##### HintListDelegateAdded

**MUST** be emitted when a delegate has been added to a hint list.

```solidity
event HintListDelegateAdded(
  address indexed namespace,
  bytes32 indexed list,
  address indexed newDelegate
);
```

##### HintListDelegateRemoved

**MUST** be emitted when a delegate has been removed from a hint list.

```solidity
event HintListDelegateRemoved(
  address indexed namespace,
  bytes32 indexed list,
  address indexed oldDelegate
);
```

##### HintListStatusChanged

**MUST** be emitted when the validity status of the hint list has been changed.

```solidity
event HintListStatusChanged(
  address indexed namespace,
  bytes32 indexed list,
  bool indexed revoked
);
```

### Meta Transactions

This section uses the following terms:

- **`transaction signer`**: An Ethereum address that signs arbitrary data for the contract to execute **BUT** does not
  commit the transaction.
- **`transaction sender`**: An Ethereum address that takes signed data from a **transaction signer** and commits it
  as part of the method call in a transaction to the smart contract.

A **transaction signer** **MAY** be able to deliver a signed payload off-band to a **transaction sender** that initiates
the Ethereum interaction with the smart contract. The signed payload **MUST** be limited to being used only
once (see Signed Hash and Nonce).

#### Signed Hash

The signature of the **transaction signer** **MUST** conform to [EIP-712](/EIPs/EIPS/eip-712). This helps users understand
what the payload they are signing consists of, and it provides protection against replay attacks.

#### Nonce

This EIP **RECOMMENDS** the use of a **dedicated nonce mapping** for meta transactions. If the signature of the 
**transaction sender** and its meta-contents are verified, the contract increases a nonce for the 
**transaction signer**. This effectively removes the possibility for any other sender to execute the same transaction 
again with another wallet.

### Trust Anchor via ENS

Ecosystems that use an Ethereum Name Service (ENS) domain can increase trust by using ENS entries to share information
about a hint list registry. This method takes advantage of the ENS domain&apos;s established credibility to make it easier to
find a hint registry contract of the domain&apos;s entity, as well as the appropriate namespace and hint list customized for 
particular ecosystem needs. Implementing a trust anchor through ENS is **OPTIONAL**.

For each use case, a specific or set of ENS subdomain **SHALL** be created. Each subdomain should be treated as an 
atomic entity for a singular set of namespace-list-key-value TEXT records. The following records **SHALL** be set:

- ADDRESS ETH - address of the trusted hint registry contract
- TEXT - key: “hint.namespace”; value: owner address of namespace

The following records **MAY** be set:

- TEXT - key: “hint.list”; value: bytes32 key of hint list
- TEXT - key: “hint.key”; value: bytes32 key of hint key
- TEXT - key: “hint.value”; value: bytes32 key of hint value
- ABI - ABI of trusted hint registry contract

To create a two-way connection, a namespace owner **SHALL** set metadata referencing the complete ENS subdomain hash. 
Metadata **SHALL** be set in the owners namespace with a hint list and hint key value of `0x0` where the hint value is 
the ENS subdomain keccak256 hash.

By establishing this connection, a robust foundation for trust and discovery within an ecosystem is created.

## Rationale

Examining the method signatures reveals a deliberate architecture and data hierarchy within this ERC: A namespace
address maps to a hint list, which in turn maps to a hint key, which then reveals the hint value.

```solidity
//     namespace          hint list          hint key    hint value
mapping(address =&gt; mapping(bytes32 =&gt; mapping(bytes32 =&gt; bytes32))) hints;
```

This structure is designed to implicitly establish the initial ownership of all lists under a given namespace,
eliminating the need for subsequent claiming actions. As a result, it simplifies the process of verifying and enforcing
write permissions, thereby reducing potential attack surfaces. Additional data structures must be established and
validated for features like delegate management and ownership transfer of hint lists. These structures won&apos;t affect the
main namespace layout; rather, they serve as a secondary mechanism for permission checks.

One of the primary objectives of this ERC is to include management features, as these significantly influence the ease
of collaboration and maintainability of hint lists. These features also enable platforms to hide complexities while
offering user-friendly interfaces. Specifically, the use of meta-transactions allows users to maintain control over
their private keys while outsourcing the technical heavy lifting to platforms, which is achieved simply by signing an
[EIP-712](/EIPs/EIPS/eip-712) payload.

## Backwards Compatibility

No backward compatibility issues found.

## Security Considerations

### Meta Transactions

The signature of signed transactions could potentially be replayed on different chains or deployed versions of the
registry implementing this ERC. This security consideration is addressed by the usage
of [EIP-712](/EIPs/EIPS/eip-712).

### Rights Management

The different roles and their inherent permissions are meant to prevent changes from unauthorized entities. The hint
list owner should always be in complete control over its hint list and who has writing access to it.

### Governance

It is recognized that ecosystems might have processes in place that might also apply to changes in hint lists. This ERC
explicitly leaves room for implementers or users of the registry to apply a process that fits the requirements of their
ecosystem. Possible solutions can be an extension of the contract with governance features around specific methods, the
usage of multi-sig wallets, or off-chain processes enforced by an entity.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 31 Aug 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7506</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7506</guid>
      </item>
    
      <item>
        <title>Multi-User NFT Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7507-multi-user-nft-extension/15660</comments>
        
        <description>## Abstract

This standard is an extension of [ERC-721](/EIPs/EIPS/eip-721). It proposes a new role `user` in addition to `owner` for a token. A token can have multiple users under separate expiration time. It allows the subscription model where an NFT can be subscribed non-exclusively by different users.

## Motivation

Some NFTs represent IP assets, and IP assets have the need to be licensed for access without transferring ownership. The subscription model is a very common practice for IP licensing where multiple users can subscribe to an NFT to obtain access. Each subscription is usually time limited and will thus be recorded with an expiration time.

Existing [ERC-4907](/EIPs/EIPS/eip-4907) introduces a similar feature, but does not allow for more than one user. It is more suitable in the rental scenario where a user gains an exclusive right of use to an NFT before the next user. This rental model is common for NFTs representing physical assets like in games, but not very useful for shareable IP assets.

## Specification

Solidity interface available at [`IERC7507.sol`](/EIPs/assets/eip-7507/contracts/IERC7507.sol):

```solidity
interface IERC7507 {

    /// @notice Emitted when the expires of a user for an NFT is changed
    event UpdateUser(uint256 indexed tokenId, address indexed user, uint64 expires);

    /// @notice Get the user expires of an NFT
    /// @param tokenId The NFT to get the user expires for
    /// @param user The user to get the expires for
    /// @return The user expires for this NFT
    function userExpires(uint256 tokenId, address user) external view returns(uint256);

    /// @notice Set the user expires of an NFT
    /// @param tokenId The NFT to set the user expires for
    /// @param user The user to set the expires for
    /// @param expires The user could use the NFT before expires in UNIX timestamp
    function setUser(uint256 tokenId, address user, uint64 expires) external;

}
```

## Rationale

This standard complements [ERC-4907](/EIPs/EIPS/eip-4907) to support multi-user feature. Therefore the proposed interface tries to keep consistent using the same naming for functions and parameters.

However, we didn&apos;t include the corresponding `usersOf(uint256 tokenId)` function as that would imply the implemention has to support enumerability over multiple users. It is not always necessary, for example, in the case of open subscription. So we decide not to add it to the interface and leave the choice up to the implementers.

## Backwards Compatibility

No backwards compatibility issues found.

## Test Cases

Test cases available at: [`ERC7507.test.ts`](/EIPs/assets/eip-7507/test/ERC7507.test.ts):

```typescript
import { loadFixture } from &quot;@nomicfoundation/hardhat-toolbox/network-helpers&quot;;
import { expect } from &quot;chai&quot;;
import { ethers } from &quot;hardhat&quot;;

const NAME = &quot;NAME&quot;;
const SYMBOL = &quot;SYMBOL&quot;;
const TOKEN_ID = 1234;
const EXPIRATION = 2000000000;
const YEAR = 31536000;

describe(&quot;ERC7507&quot;, function () {

  async function deployContractFixture() {
    const [deployer, owner, user1, user2] = await ethers.getSigners();

    const contract = await ethers.deployContract(&quot;ERC7507&quot;, [NAME, SYMBOL], deployer);
    await contract.mint(owner, TOKEN_ID);

    return { contract, owner, user1, user2 };
  }

  describe(&quot;Functions&quot;, function () {
    it(&quot;Should not set user if not owner or approved&quot;, async function () {
      const { contract, user1 } = await loadFixture(deployContractFixture);

      await expect(contract.setUser(TOKEN_ID, user1, EXPIRATION))
        .to.be.revertedWith(&quot;ERC7507: caller is not owner or approved&quot;);
    });

    it(&quot;Should return zero expiration for nonexistent user&quot;, async function () {
      const { contract, user1 } = await loadFixture(deployContractFixture);

      expect(await contract.userExpires(TOKEN_ID, user1)).to.equal(0);
    });

    it(&quot;Should set users and then update&quot;, async function () {
      const { contract, owner, user1, user2 } = await loadFixture(deployContractFixture);

      await contract.connect(owner).setUser(TOKEN_ID, user1, EXPIRATION);
      await contract.connect(owner).setUser(TOKEN_ID, user2, EXPIRATION);

      expect(await contract.userExpires(TOKEN_ID, user1)).to.equal(EXPIRATION);
      expect(await contract.userExpires(TOKEN_ID, user2)).to.equal(EXPIRATION);

      await contract.connect(owner).setUser(TOKEN_ID, user1, EXPIRATION + YEAR);
      await contract.connect(owner).setUser(TOKEN_ID, user2, 0);

      expect(await contract.userExpires(TOKEN_ID, user1)).to.equal(EXPIRATION + YEAR);
      expect(await contract.userExpires(TOKEN_ID, user2)).to.equal(0);
    });
  });

  describe(&quot;Events&quot;, function () {
    it(&quot;Should emit event when set user&quot;, async function () {
      const { contract, owner, user1 } = await loadFixture(deployContractFixture);

      await expect(contract.connect(owner).setUser(TOKEN_ID, user1, EXPIRATION))
        .to.emit(contract, &quot;UpdateUser&quot;).withArgs(TOKEN_ID, user1.address, EXPIRATION);
    });
  });

});
```

## Reference Implementation

Reference implementation available at: [`ERC7507.sol`](/EIPs/assets/eip-7507/contracts/ERC7507.sol):

```solidity
// SPDX-License-Identifier: CC0-1.0

pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;

import &quot;./IERC7507.sol&quot;;

contract ERC7507 is ERC721, IERC7507 {

    mapping(uint256 =&gt; mapping(address =&gt; uint64)) private _expires;

    constructor(
        string memory name, string memory symbol
    ) ERC721(name, symbol) {}

    function supportsInterface(
        bytes4 interfaceId
    ) public view virtual override returns (bool) {
        return interfaceId == type(IERC7507).interfaceId || super.supportsInterface(interfaceId);
    }

    function userExpires(
        uint256 tokenId, address user
    ) public view virtual override returns(uint256) {
        require(_exists(tokenId), &quot;ERC7507: query for nonexistent token&quot;);
        return _expires[tokenId][user];
    }

    function setUser(
        uint256 tokenId, address user, uint64 expires
    ) public virtual override {
        require(_isApprovedOrOwner(_msgSender(), tokenId), &quot;ERC7507: caller is not owner or approved&quot;);
        _expires[tokenId][user] = expires;
        emit UpdateUser(tokenId, user, expires);
    }

}
```

## Security Considerations

No security considerations found.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 24 Aug 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7507</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7507</guid>
      </item>
    
      <item>
        <title>Dynamic On-Chain Token Attributes Repository</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/dynamic-on-chain-token-attributes-repository/15667</comments>
        
        <description>## Abstract

The Public On-Chain Non-Fungible Token Attributes Repository standard provides the ability for [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155) compatible tokens to store their attributes on-chain available to any external smart contract interacting with them.

This proposal introduces the ability to assign attributes to NFTs in a public non-gated repository smart contract that is accessible at the same address in all of the networks. The repository smart contract is designed to be a common-good repository, meaning that it can be used by any ERC-721 or ERC-1155 compatible token.

## Motivation

With NFTs being a widespread form of tokens in the Ethereum ecosystem and being used for a variety of use cases, it is time to standardize additional utility for them. Having the ability to store token&apos;s attributes on chain allows for greater utility of tokens as it fosters cross-collection interactivity and provides perpetual store of attributes.

This ERC introduces new utilities for [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155) based tokens in the following areas:

- [Cross-Collection interactivity](#cross-collection-interactivity)
- [Perpetual Store of Attributes](#perpetual-store-of-attributes)
- [Token Evolution](#token-evolution)
- [Dynamic State Tracking](#dynamic-state-tracking)

### Cross-Collection Interactivity

Storing attributes on-chain in a predictable format allows for cross-collection interactivity. This means that the attributes of a token can be used by any external smart contract without the need for the token to be aware of the external smart contract.

For example, a token can represent a game character with its set of attributes and can be used in an unrelated game with the same stats without the need for retrieving these attributes from an off-chain source. This ensures that the data the game is using is legitimate and not tampered with in order to gain an advantage.

### Perpetual Store of Attributes

Standardized on-chain token attributes allow for their perpetual storage.

With off-chain attributes storage, the attributes are only available as long as the off-chain storage is available. If the storage is taken down, the attributes are lost. With on-chain attributes storage, the attributes are available as long as the blockchain is available. This increases the value of the token as it ensures that the attributes are available for as long as the token exists.

### Token Evolution

On-Chain storage of token attributes allows for the token to evolve over time. Owner&apos;s actions can impact the attributes of the token. Since the attributes are stored on chain, the smart contract has the ability to modify the attribute once certain thresholds are met. This allows for token to become more interactive and reflect owner&apos;s dedication and effort.

### Dynamic State Tracking

On-Chain storage of token attributes allows for dynamic state tracking. The attributes can be used to track the state of the token and its owner. This allows for the token to be used in a variety of use cases. One such use case is supply chains; the token can represent a product and its attributes can be used to track the state of the product as it transitions from pending, shipped, delivered, etc.

## Specification

### Interface 

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.

```solidity
/// @title ERC-7508 Public On-Chain NFT Attributes Repository
/// @dev See https://eips.ethereum.org/EIPS/eip-7508
/// @dev Note: the ERC-165 identifier for this interface is 0x212206a8.

pragma solidity ^0.8.21;

interface IERC7508 is IERC165 {
    /**
     * @notice A list of supported access types.
     * @return The `Owner` type, where only the owner can manage the parameter.
     * @return The `Collaborator` type, where only the collaborators can manage the parameter.
     * @return The `OwnerOrCollaborator` type, where only the owner or collaborators can manage the parameter.
     * @return The `TokenOwner` type, where only the token owner can manage the parameters of their tokens.
     * @return The `SpecificAddress` type, where only specific addresses can manage the parameter.
     */
    enum AccessType {
        Owner,
        Collaborator,
        OwnerOrCollaborator,
        TokenOwner,
        SpecificAddress
    }

    /**
     * @notice Structure used to represent an address attribute.
     * @return key The key of the attribute
     * @return value The value of the attribute
     */
    struct AddressAttribute {
        string key;
        address value;
    }

    /**
     * @notice Structure used to represent a boolean attribute.
     * @return key The key of the attribute
     * @return value The value of the attribute
     */
    struct BoolAttribute {
        string key;
        bool value;
    }

    /**
     * @notice Structure used to represent a bytes attribute.
     * @return key The key of the attribute
     * @return value The value of the attribute
     */
    struct BytesAttribute {
        string key;
        bytes value;
    }

    /**
     * @notice Structure used to represent an int attribute.
     * @return key The key of the attribute
     * @return value The value of the attribute
     */
    struct IntAttribute {
        string key;
        int256 value;
    }

    /**
     * @notice Structure used to represent a string attribute.
     * @return key The key of the attribute
     * @return value The value of the attribute
     */
    struct StringAttribute {
        string key;
        string value;
    }

    /**
     * @notice Structure used to represent an uint attribute.
     * @return key The key of the attribute
     * @return value The value of the attribute
     */
    struct UintAttribute {
        string key;
        uint256 value;
    }

    /**
     * @notice Used to notify listeners that a new collection has been registered to use the repository.
     * @param collection Address of the collection
     * @param owner Address of the owner of the collection; the addess authorized to manage the access control
     * @param registeringAddress Address that registered the collection
     * @param useOwnable A boolean value indicating whether the collection uses the Ownable extension to verify the
     *  owner (`true`) or not (`false`)
     */
    event AccessControlRegistration(
        address indexed collection,
        address indexed owner,
        address indexed registeringAddress,
        bool useOwnable
    );

    /**
     * @notice Used to notify listeners that the access control settings for a specific parameter have been updated.
     * @param collection Address of the collection
     * @param key The name of the parameter for which the access control settings have been updated
     * @param accessType The AccessType of the parameter for which the access control settings have been updated
     * @param specificAddress The specific addresses that has been updated
     */
    event AccessControlUpdate(
        address indexed collection,
        string key,
        AccessType accessType,
        address specificAddress
    );

    /**
     * @notice Used to notify listeners that the metadata URI for a collection has been updated.
     * @param collection Address of the collection
     * @param attributesMetadataURI The new attributes metadata URI
     */
    event MetadataURIUpdated(
        address indexed collection,
        string attributesMetadataURI
    );

    /**
     * @notice Used to notify listeners that a new collaborator has been added or removed.
     * @param collection Address of the collection
     * @param collaborator Address of the collaborator
     * @param isCollaborator A boolean value indicating whether the collaborator has been added (`true`) or removed
     *  (`false`)
     */
    event CollaboratorUpdate(
        address indexed collection,
        address indexed collaborator,
        bool isCollaborator
    );

    /**
     * @notice Used to notify listeners that an address attribute has been updated.
     * @param collection The collection address
     * @param tokenId The token ID
     * @param key The key of the attribute
     * @param value The new value of the attribute
     */
    event AddressAttributeUpdated(
        address indexed collection,
        uint256 indexed tokenId,
        string key,
        address value
    );

    /**
     * @notice Used to notify listeners that a boolean attribute has been updated.
     * @param collection The collection address
     * @param tokenId The token ID
     * @param key The key of the attribute
     * @param value The new value of the attribute
     */
    event BoolAttributeUpdated(
        address indexed collection,
        uint256 indexed tokenId,
        string key,
        bool value
    );

    /**
     * @notice Used to notify listeners that a bytes attribute has been updated.
     * @param collection The collection address
     * @param tokenId The token ID
     * @param key The key of the attribute
     * @param value The new value of the attribute
     */
    event BytesAttributeUpdated(
        address indexed collection,
        uint256 indexed tokenId,
        string key,
        bytes value
    );

    /**
     * @notice Used to notify listeners that an int attribute has been updated.
     * @param collection The collection address
     * @param tokenId The token ID
     * @param key The key of the attribute
     * @param value The new value of the attribute
     */
    event IntAttributeUpdated(
        address indexed collection,
        uint256 indexed tokenId,
        string key,
        int256 value
    );

    /**
     * @notice Used to notify listeners that a string attribute has been updated.
     * @param collection The collection address
     * @param tokenId The token ID
     * @param key The key of the attribute
     * @param value The new value of the attribute
     */
    event StringAttributeUpdated(
        address indexed collection,
        uint256 indexed tokenId,
        string key,
        string value
    );

    /**
     * @notice Used to notify listeners that an uint attribute has been updated.
     * @param collection The collection address
     * @param tokenId The token ID
     * @param key The key of the attribute
     * @param value The new value of the attribute
     */
    event UintAttributeUpdated(
        address indexed collection,
        uint256 indexed tokenId,
        string key,
        uint256 value
    );

    // ------------------- ACCESS CONTROL -------------------

    /**
     * @notice Used to check if the specified address is listed as a collaborator of the given collection&apos;s parameter.
     * @param collaborator Address to be checked.
     * @param collection Address of the collection.
     * @return isCollaborator_ Boolean value indicating if the address is a collaborator of the given collection&apos;s (`true`) or not
     *  (`false`).
     */
    function isCollaborator(
        address collaborator,
        address collection
    ) external view returns (bool isCollaborator_);

    /**
     * @notice Used to check if the specified address is listed as a specific address of the given collection&apos;s
     *  parameter.
     * @param specificAddress Address to be checked.
     * @param collection Address of the collection.
     * @param key The key of the attribute
     * @return isSpecificAddress_ Boolean value indicating if the address is a specific address of the given collection&apos;s parameter
     *  (`true`) or not (`false`).
     */
    function isSpecificAddress(
        address specificAddress,
        address collection,
        string memory key
    ) external view returns (bool isSpecificAddress_);

    /**
     * @notice Used to register a collection to use the RMRK token attributes repository.
     * @dev  If the collection does not implement the Ownable interface, the `useOwnable` value must be set to `false`.
     * @dev Emits an {AccessControlRegistration} event.
     * @param collection The address of the collection that will use the RMRK token attributes repository.
     * @param owner The address of the owner of the collection.
     * @param useOwnable The boolean value to indicate if the collection implements the Ownable interface and whether it
     *  should be used to validate that the caller is the owner (`true`) or to use the manually set owner address
     *  (`false`).
     */
    function registerAccessControl(
        address collection,
        address owner,
        bool useOwnable
    ) external;

    /**
     * @notice Used to manage the access control settings for a specific parameter.
     * @dev Only the `owner` of the collection can call this function.
     * @dev The possible `accessType` values are:
     *  [
     *      Owner,
     *      Collaborator,
     *      OwnerOrCollaborator,
     *      TokenOwner,
     *      SpecificAddress,
     *  ]
     * @dev Emits an {AccessControlUpdated} event.
     * @param collection The address of the collection being managed.
     * @param key The key of the attribute
     * @param accessType The type of access control to be applied to the parameter.
     * @param specificAddress The address to be added as a specific addresses allowed to manage the given
     *  parameter.
     */
    function manageAccessControl(
        address collection,
        string memory key,
        AccessType accessType,
        address specificAddress
    ) external;

    /**
     * @notice Used to manage the collaborators of a collection.
     * @dev The `collaboratorAddresses` and `collaboratorAddressAccess` arrays must be of the same length.
     * @dev Emits a {CollaboratorUpdate} event.
     * @param collection The address of the collection
     * @param collaboratorAddresses The array of collaborator addresses being managed
     * @param collaboratorAddressAccess The array of boolean values indicating if the collaborator address should
     *  receive the permission (`true`) or not (`false`).
     */
    function manageCollaborators(
        address collection,
        address[] memory collaboratorAddresses,
        bool[] memory collaboratorAddressAccess
    ) external;

    // ------------------- METADATA URI -------------------

    /**
     * @notice Used to retrieve the attributes metadata URI for a collection, which contains all the information about the collection attributes.
     * @param collection Address of the collection
     * @return attributesMetadataURI The URI of the attributes metadata
     */
    function getAttributesMetadataURIForCollection(
        address collection
    ) external view returns (string memory attributesMetadataURI);

    /**
     * @notice Used to set the metadata URI for a collection, which contains all the information about the collection attributes.
     * @dev Emits a {MetadataURIUpdated} event.
     * @param collection Address of the collection
     * @param attributesMetadataURI The URI of the attributes metadata
     */
    function setAttributesMetadataURIForCollection(
        address collection,
        string memory attributesMetadataURI
    ) external;

    // ------------------- GETTERS -------------------

    /**
     * @notice Used to retrieve the address type token attributes.
     * @param collection The collection address
     * @param tokenId The token ID
     * @param key The key of the attribute
     * @return attribute The value of the address attribute
     */
    function getAddressAttribute(
        address collection,
        uint256 tokenId,
        string memory key
    ) external view returns (address attribute);

    /**
     * @notice Used to retrieve the bool type token attributes.
     * @param collection The collection address
     * @param tokenId The token ID
     * @param key The key of the attribute
     * @return attribute The value of the bool attribute
     */
    function getBoolAttribute(
        address collection,
        uint256 tokenId,
        string memory key
    ) external view returns (bool attribute);

    /**
     * @notice Used to retrieve the bytes type token attributes.
     * @param collection The collection address
     * @param tokenId The token ID
     * @param key The key of the attribute
     * @return attribute The value of the bytes attribute
     */
    function getBytesAttribute(
        address collection,
        uint256 tokenId,
        string memory key
    ) external view returns (bytes memory attribute);

    /**
     * @notice Used to retrieve the uint type token attributes.
     * @param collection The collection address
     * @param tokenId The token ID
     * @param key The key of the attribute
     * @return attribute The value of the uint attribute
     */
    function getUintAttribute(
        address collection,
        uint256 tokenId,
        string memory key
    ) external view returns (uint256 attribute);
    /**
     * @notice Used to retrieve the string type token attributes.
     * @param collection The collection address
     * @param tokenId The token ID
     * @param key The key of the attribute
     * @return attribute The value of the string attribute
     */
    function getStringAttribute(
        address collection,
        uint256 tokenId,
        string memory key
    ) external view returns (string memory attribute);

    /**
     * @notice Used to retrieve the int type token attributes.
     * @param collection The collection address
     * @param tokenId The token ID
     * @param key The key of the attribute
     * @return attribute The value of the uint attribute
     */
    function getIntAttribute(
        address collection,
        uint256 tokenId,
        string memory key
    ) external view returns (int256 attribute);

    // ------------------- BATCH GETTERS -------------------

    /**
     * @notice Used to get multiple address parameter values for a token.
     * @dev The `AddressAttribute` struct contains the following fields:
     *  [
     *     string key,
     *     address value
     *  ]
     * @param collections Addresses of the collections, in the same order as the attribute keys. If all tokens are from the same collection the array can contain a single element with the collection address.
     * @param tokenIds IDs of the tokens, in the same order as the attribute keys. If all attributes are for the same token the array can contain a single element with the token ID.
     * @param attributeKeys An array of address keys to retrieve
     * @return attributes An array of addresses, in the same order as the attribute keys
     */
    function getAddressAttributes(
        address[] memory collections,
        uint256[] memory tokenIds,
        string[] memory attributeKeys
    ) external view returns (address[] memory attributes);

    /**
     * @notice Used to get multiple bool parameter values for a token.
     * @dev The `BoolAttribute` struct contains the following fields:
     *  [
     *     string key,
     *     bool value
     *  ]
     * @param collections Addresses of the collections, in the same order as the attribute keys. If all tokens are from the same collection the array can contain a single element with the collection address.
     * @param tokenIds IDs of the tokens, in the same order as the attribute keys. If all attributes are for the same token the array can contain a single element with the token ID.
     * @param attributeKeys An array of bool keys to retrieve
     * @return attributes An array of bools, in the same order as the attribute keys
     */
    function getBoolAttributes(
        address[] memory collections,
        uint256[] memory tokenIds,
        string[] memory attributeKeys
    ) external view returns (bool[] memory attributes);

    /**
     * @notice Used to get multiple bytes parameter values for a token.
     * @dev The `BytesAttribute` struct contains the following fields:
     *  [
     *     string key,
     *     bytes value
     *  ]
     * @param collections Addresses of the collections, in the same order as the attribute keys. If all tokens are from the same collection the array can contain a single element with the collection address.
     * @param tokenIds IDs of the tokens, in the same order as the attribute keys. If all attributes are for the same token the array can contain a single element with the token ID.
     * @param attributeKeys An array of bytes keys to retrieve
     * @return attributes An array of bytes, in the same order as the attribute keys
     */
    function getBytesAttributes(
        address[] memory collections,
        uint256[] memory tokenIds,
        string[] memory attributeKeys
    ) external view returns (bytes[] memory attributes);

    /**
     * @notice Used to get multiple int parameter values for a token.
     * @param collections Addresses of the collections, in the same order as the attribute keys. If all tokens are from the same collection the array can contain a single element with the collection address.
     * @param tokenIds IDs of the tokens, in the same order as the attribute keys. If all attributes are for the same token the array can contain a single element with the token ID.
     * @param attributeKeys An array of int keys to retrieve
     * @return attributes An array of ints, in the same order as the attribute keys
     */
    function getIntAttributes(
        address[] memory collections,
        uint256[] memory tokenIds,
        string[] memory attributeKeys
    ) external view returns (int256[] memory attributes);

    /**
     * @notice Used to get multiple sting parameter values for a token.
     * @param collections Addresses of the collections, in the same order as the attribute keys. If all tokens are from the same collection the array can contain a single element with the collection address.
     * @param tokenIds IDs of the tokens, in the same order as the attribute keys. If all attributes are for the same token the array can contain a single element with the token ID.
     * @param attributeKeys An array of string keys to retrieve
     * @return attributes An array of strings, in the same order as the attribute keys
     */
    function getStringAttributes(
        address[] memory collections,
        uint256[] memory tokenIds,
        string[] memory attributeKeys
    ) external view returns (string[] memory attributes);

    /**
     * @notice Used to get multiple uint parameter values for a token.
     * @param collections Addresses of the collections, in the same order as the attribute keys. If all tokens are from the same collection the array can contain a single element with the collection address.
     * @param tokenIds IDs of the tokens, in the same order as the attribute keys. If all attributes are for the same token the array can contain a single element with the token ID.
     * @param attributeKeys An array of uint keys to retrieve
     * @return attributes An array of uints, in the same order as the attribute keys
     */
    function getUintAttributes(
        address[] memory collections,
        uint256[] memory tokenIds,
        string[] memory attributeKeys
    ) external view returns (uint256[] memory attributes);

    /**
     * @notice Used to retrieve multiple token attributes of any type at once.
     * @dev The `StringAttribute`, `UintAttribute`, `IntAttribute`, `BoolAttribute`, `AddressAttribute` and `BytesAttribute` structs consists
     *  to the following fields (where `value` is of the appropriate type):
     *  [
     *      key,
     *      value,
     *  ]
     * @param collection The collection address
     * @param tokenId The token ID
     * @param addressKeys An array of address type attribute keys to retrieve
     * @param boolKeys An array of bool type attribute keys to retrieve
     * @param bytesKeys An array of bytes type attribute keys to retrieve
     * @param intKeys An array of int type attribute keys to retrieve
     * @param stringKeys An array of string type attribute keys to retrieve
     * @param uintKeys An array of uint type attribute keys to retrieve
     * @return addressAttributes An array of addresses, in the same order as the addressKeys
     * @return boolAttributes An array of bools, in the same order as the boolKeys
     * @return bytesAttributes An array of bytes, in the same order as the bytesKeys
     * @return intAttributes An array of ints, in the same order as the intKeys
     * @return stringAttributes An array of strings, in the same order as the stringKeys
     * @return uintAttributes An array of uints, in the same order as the uintKeys
     */
    function getAttributes(
        address collection,
        uint256 tokenId,
        string[] memory addressKeys,
        string[] memory boolKeys,
        string[] memory bytesKeys,
        string[] memory intKeys,
        string[] memory stringKeys,
        string[] memory uintKeys
    )
        external
        view
        returns (
            address[] memory addressAttributes,
            bool[] memory boolAttributes,
            bytes[] memory bytesAttributes,
            int256[] memory intAttributes,
            string[] memory stringAttributes,
            uint256[] memory uintAttributes
        );

    // ------------------- PREPARE PRESIGNED MESSAGES -------------------

    /**
     * @notice Used to retrieve the message to be signed for submitting a presigned address attribute change.
     * @param collection The address of the collection smart contract of the token receiving the attribute
     * @param tokenId The ID of the token receiving the attribute
     * @param key The attribute key
     * @param value The attribute value
     * @param deadline The deadline timestamp for the presigned transaction after which the message is invalid
     * @return message Raw message to be signed by the authorized account
     */
    function prepareMessageToPresignAddressAttribute(
        address collection,
        uint256 tokenId,
        string memory key,
        address value,
        uint256 deadline
    ) external view returns (bytes32 message);

    /**
     * @notice Used to retrieve the message to be signed for submitting a presigned bool attribute change.
     * @param collection The address of the collection smart contract of the token receiving the attribute
     * @param tokenId The ID of the token receiving the attribute
     * @param key The attribute key
     * @param value The attribute value
     * @param deadline The deadline timestamp for the presigned transaction after which the message is invalid
     * @return message Raw message to be signed by the authorized account
     */
    function prepareMessageToPresignBoolAttribute(
        address collection,
        uint256 tokenId,
        string memory key,
        bool value,
        uint256 deadline
    ) external view returns (bytes32 message);

    /**
     * @notice Used to retrieve the message to be signed for submitting a presigned bytes attribute change.
     * @param collection The address of the collection smart contract of the token receiving the attribute
     * @param tokenId The ID of the token receiving the attribute
     * @param key The attribute key
     * @param value The attribute value
     * @param deadline The deadline timestamp for the presigned transaction after which the message is invalid
     * @return message Raw message to be signed by the authorized account
     */
    function prepareMessageToPresignBytesAttribute(
        address collection,
        uint256 tokenId,
        string memory key,
        bytes memory value,
        uint256 deadline
    ) external view returns (bytes32 message);

    /**
     * @notice Used to retrieve the message to be signed for submitting a presigned int attribute change.
     * @param collection The address of the collection smart contract of the token receiving the attribute
     * @param tokenId The ID of the token receiving the attribute
     * @param key The attribute key
     * @param value The attribute value
     * @param deadline The deadline timestamp for the presigned transaction after which the message is invalid
     * @return message Raw message to be signed by the authorized account
     */
    function prepareMessageToPresignIntAttribute(
        address collection,
        uint256 tokenId,
        string memory key,
        int256 value,
        uint256 deadline
    ) external view returns (bytes32 message);

    /**
     * @notice Used to retrieve the message to be signed for submitting a presigned string attribute change.
     * @param collection The address of the collection smart contract of the token receiving the attribute
     * @param tokenId The ID of the token receiving the attribute
     * @param key The attribute key
     * @param value The attribute value
     * @param deadline The deadline timestamp for the presigned transaction after which the message is invalid
     * @return message Raw message to be signed by the authorized account
     */
    function prepareMessageToPresignStringAttribute(
        address collection,
        uint256 tokenId,
        string memory key,
        string memory value,
        uint256 deadline
    ) external view returns (bytes32 message);

    /**
     * @notice Used to retrieve the message to be signed for submitting a presigned uint attribute change.
     * @param collection The address of the collection smart contract of the token receiving the attribute
     * @param tokenId The ID of the token receiving the attribute
     * @param key The attribute key
     * @param value The attribute value
     * @param deadline The deadline timestamp for the presigned transaction after which the message is invalid
     * @return message Raw message to be signed by the authorized account
     */
    function prepareMessageToPresignUintAttribute(
        address collection,
        uint256 tokenId,
        string memory key,
        uint256 value,
        uint256 deadline
    ) external view returns (bytes32 message);

    // ------------------- SETTERS -------------------

    /**
     * @notice Used to set an address attribute.
     * @dev Emits a {AddressAttributeUpdated} event.
     * @param collection Address of the collection receiving the attribute
     * @param tokenId The token ID
     * @param key The attribute key
     * @param value The attribute value
     */
    function setAddressAttribute(
        address collection,
        uint256 tokenId,
        string memory key,
        address value
    ) external;

    /**
     * @notice Used to set a boolean attribute.
     * @dev Emits a {BoolAttributeUpdated} event.
     * @param collection Address of the collection receiving the attribute
     * @param tokenId The token ID
     * @param key The attribute key
     * @param value The attribute value
     */
    function setBoolAttribute(
        address collection,
        uint256 tokenId,
        string memory key,
        bool value
    ) external;

    /**
     * @notice Used to set an bytes attribute.
     * @dev Emits a {BytesAttributeUpdated} event.
     * @param collection Address of the collection receiving the attribute
     * @param tokenId The token ID
     * @param key The attribute key
     * @param value The attribute value
     */
    function setBytesAttribute(
        address collection,
        uint256 tokenId,
        string memory key,
        bytes memory value
    ) external;

    /**
     * @notice Used to set a signed number attribute.
     * @dev Emits a {IntAttributeUpdated} event.
     * @param collection Address of the collection receiving the attribute
     * @param tokenId The token ID
     * @param key The attribute key
     * @param value The attribute value
     */
    function setIntAttribute(
        address collection,
        uint256 tokenId,
        string memory key,
        int256 value
    ) external;

    /**
     * @notice Used to set a string attribute.
     * @dev Emits a {StringAttributeUpdated} event.
     * @param collection Address of the collection receiving the attribute
     * @param tokenId The token ID
     * @param key The attribute key
     * @param value The attribute value
     */
    function setStringAttribute(
        address collection,
        uint256 tokenId,
        string memory key,
        string memory value
    ) external;

    /**
     * @notice Used to set an unsigned number attribute.
     * @dev Emits a {UintAttributeUpdated} event.
     * @param collection Address of the collection receiving the attribute
     * @param tokenId The token ID
     * @param key The attribute key
     * @param value The attribute value
     */
    function setUintAttribute(
        address collection,
        uint256 tokenId,
        string memory key,
        uint256 value
    ) external;

    // ------------------- BATCH SETTERS -------------------

    /**
     * @notice Sets multiple address attributes for a token at once.
     * @dev The `AddressAttribute` struct contains the following fields:
     *  [
     *      string key,
     *      address value
     *  ]
     * @param collections Addresses of the collections, in the same order as the attributes. If all tokens are from the same collection the array can contain a single element with the collection address.
     * @param tokenIds IDs of the tokens, in the same order as the attributes. If all attributes are for the same token the array can contain a single element with the token ID.
     * @param attributes An array of `AddressAttribute` structs to be assigned to the given token
     */
    function setAddressAttributes(
        address[] memory collections,
        uint256[] memory tokenIds,
        AddressAttribute[] memory attributes
    ) external;

    /**
     * @notice Sets multiple bool attributes for a token at once.
     * @dev The `BoolAttribute` struct contains the following fields:
     *  [
     *      string key,
     *      bool value
     *  ]
     * @param collections Addresses of the collections, in the same order as the attributes. If all tokens are from the same collection the array can contain a single element with the collection address.
     * @param tokenIds IDs of the tokens, in the same order as the attributes. If all attributes are for the same token the array can contain a single element with the token ID.
     * @param attributes An array of `BoolAttribute` structs to be assigned to the given token
     */
    function setBoolAttributes(
        address[] memory collections,
        uint256[] memory tokenIds,
        BoolAttribute[] memory attributes
    ) external;

    /**
     * @notice Sets multiple bytes attributes for a token at once.
     * @dev The `BytesAttribute` struct contains the following fields:
     *  [
     *      string key,
     *      bytes value
     *  ]
     * @param collections Addresses of the collections, in the same order as the attributes. If all tokens are from the same collection the array can contain a single element with the collection address.
     * @param tokenIds IDs of the tokens, in the same order as the attributes. If all attributes are for the same token the array can contain a single element with the token ID.
     * @param attributes An array of `BytesAttribute` structs to be assigned to the given token
     */
    function setBytesAttributes(
        address[] memory collections,
        uint256[] memory tokenIds,
        BytesAttribute[] memory attributes
    ) external;

    /**
     * @notice Sets multiple int attributes for a token at once.
     * @dev The `UintAttribute` struct contains the following fields:
     *  [
     *      string key,
     *      int value
     *  ]
     * @param collections Addresses of the collections, in the same order as the attributes. If all tokens are from the same collection the array can contain a single element with the collection address.
     * @param tokenIds IDs of the tokens, in the same order as the attributes. If all attributes are for the same token the array can contain a single element with the token ID.
     * @param attributes An array of `IntAttribute` structs to be assigned to the given token
     */
    function setIntAttributes(
        address[] memory collections,
        uint256[] memory tokenIds,
        IntAttribute[] memory attributes
    ) external;

    /**
     * @notice Sets multiple string attributes for a token at once.
     * @dev The `StringAttribute` struct contains the following fields:
     *  [
     *      string key,
     *      string value
     *  ]
     * @param collections Addresses of the collections, in the same order as the attributes. If all tokens are from the same collection the array can contain a single element with the collection address.
     * @param tokenIds IDs of the tokens, in the same order as the attributes. If all attributes are for the same token the array can contain a single element with the token ID.
     * @param attributes An array of `StringAttribute` structs to be assigned to the given token
     */
    function setStringAttributes(
        address[] memory collections,
        uint256[] memory tokenIds,
        StringAttribute[] memory attributes
    ) external;

    /**
     * @notice Sets multiple uint attributes for a token at once.
     * @dev The `UintAttribute` struct contains the following fields:
     *  [
     *      string key,
     *      uint value
     *  ]
     * @param collections Addresses of the collections, in the same order as the attributes. If all tokens are from the same collection the array can contain a single element with the collection address.
     * @param tokenIds IDs of the tokens, in the same order as the attributes. If all attributes are for the same token the array can contain a single element with the token ID.
     * @param attributes An array of `UintAttribute` structs to be assigned to the given token
     */
    function setUintAttributes(
        address[] memory collections,
        uint256[] memory tokenIds,
        UintAttribute[] memory attributes
    ) external;

    /**
     * @notice Sets multiple attributes of multiple types for a token at the same time.
     * @dev Emits a separate event for each attribute set.
     * @dev The `StringAttribute`, `UintAttribute`, `BoolAttribute`, `AddressAttribute` and `BytesAttribute` structs consists
     *  to the following fields (where `value` is of the appropriate type):
     *  [
     *      key,
     *      value,
     *  ]
     * @param collection The address of the collection
     * @param tokenId The token ID
     * @param addressAttributes An array of `AddressAttribute` structs containing address attributes to set
     * @param boolAttributes An array of `BoolAttribute` structs containing bool attributes to set
     * @param bytesAttributes An array of `BytesAttribute` structs containing bytes attributes to set
     * @param intAttributes An array of `IntAttribute` structs containing int attributes to set
     * @param stringAttributes An array of `StringAttribute` structs containing string attributes to set
     * @param uintAttributes An array of `UintAttribute` structs containing uint attributes to set
     */
    function setAttributes(
        address collection,
        uint256 tokenId,
        AddressAttribute[] memory addressAttributes,
        BoolAttribute[] memory boolAttributes,
        BytesAttribute[] memory bytesAttributes,
        IntAttribute[] memory intAttributes,
        StringAttribute[] memory stringAttributes,
        UintAttribute[] memory uintAttributes
    ) external;

    // ------------------- PRESIGNED SETTERS -------------------

    /**
     * @notice Used to set the address attribute on behalf of an authorized account.
     * @dev Emits a {AddressAttributeUpdated} event.
     * @param setter Address of the account that presigned the attribute change
     * @param collection Address of the collection receiving the attribute
     * @param tokenId The ID of the token receiving the attribute
     * @param key The attribute key
     * @param value The attribute value
     * @param deadline The deadline timestamp for the presigned transaction
     * @param v `v` value of an ECDSA signature of the presigned message
     * @param r `r` value of an ECDSA signature of the presigned message
     * @param s `s` value of an ECDSA signature of the presigned message
     */
    function presignedSetAddressAttribute(
        address setter,
        address collection,
        uint256 tokenId,
        string memory key,
        address value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @notice Used to set the bool attribute on behalf of an authorized account.
     * @dev Emits a {BoolAttributeUpdated} event.
     * @param setter Address of the account that presigned the attribute change
     * @param collection Address of the collection receiving the attribute
     * @param tokenId The ID of the token receiving the attribute
     * @param key The attribute key
     * @param value The attribute value
     * @param deadline The deadline timestamp for the presigned transaction
     * @param v `v` value of an ECDSA signature of the presigned message
     * @param r `r` value of an ECDSA signature of the presigned message
     * @param s `s` value of an ECDSA signature of the presigned message
     */
    function presignedSetBoolAttribute(
        address setter,
        address collection,
        uint256 tokenId,
        string memory key,
        bool value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @notice Used to set the bytes attribute on behalf of an authorized account.
     * @dev Emits a {BytesAttributeUpdated} event.
     * @param setter Address of the account that presigned the attribute change
     * @param collection Address of the collection receiving the attribute
     * @param tokenId The ID of the token receiving the attribute
     * @param key The attribute key
     * @param value The attribute value
     * @param deadline The deadline timestamp for the presigned transaction
     * @param v `v` value of an ECDSA signature of the presigned message
     * @param r `r` value of an ECDSA signature of the presigned message
     * @param s `s` value of an ECDSA signature of the presigned message
     */
    function presignedSetBytesAttribute(
        address setter,
        address collection,
        uint256 tokenId,
        string memory key,
        bytes memory value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @notice Used to set the int attribute on behalf of an authorized account.
     * @dev Emits a {IntAttributeUpdated} event.
     * @param setter Address of the account that presigned the attribute change
     * @param collection Address of the collection receiving the attribute
     * @param tokenId The ID of the token receiving the attribute
     * @param key The attribute key
     * @param value The attribute value
     * @param deadline The deadline timestamp for the presigned transaction
     * @param v `v` value of an ECDSA signature of the presigned message
     * @param r `r` value of an ECDSA signature of the presigned message
     * @param s `s` value of an ECDSA signature of the presigned message
     */
    function presignedSetIntAttribute(
        address setter,
        address collection,
        uint256 tokenId,
        string memory key,
        int256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @notice Used to set the string attribute on behalf of an authorized account.
     * @dev Emits a {StringAttributeUpdated} event.
     * @param setter Address of the account that presigned the attribute change
     * @param collection Address of the collection receiving the attribute
     * @param tokenId The ID of the token receiving the attribute
     * @param key The attribute key
     * @param value The attribute value
     * @param deadline The deadline timestamp for the presigned transaction
     * @param v `v` value of an ECDSA signature of the presigned message
     * @param r `r` value of an ECDSA signature of the presigned message
     * @param s `s` value of an ECDSA signature of the presigned message
     */
    function presignedSetStringAttribute(
        address setter,
        address collection,
        uint256 tokenId,
        string memory key,
        string memory value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @notice Used to set the uint attribute on behalf of an authorized account.
     * @dev Emits a {UintAttributeUpdated} event.
     * @param setter Address of the account that presigned the attribute change
     * @param collection Address of the collection receiving the attribute
     * @param tokenId The ID of the token receiving the attribute
     * @param key The attribute key
     * @param value The attribute value
     * @param deadline The deadline timestamp for the presigned transaction
     * @param v `v` value of an ECDSA signature of the presigned message
     * @param r `r` value of an ECDSA signature of the presigned message
     * @param s `s` value of an ECDSA signature of the presigned message
     */
    function presignedSetUintAttribute(
        address setter,
        address collection,
        uint256 tokenId,
        string memory key,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;
}
```

### Schema

In addition to the interface we propose that collection owers SHOULD be able to set the schema for the attributes of their collection. We distinguish between 2 types: token attributes and collection attributes. The latter are the attributes that are shared by all tokens in the collection, they can be retrieved and set by using the max uint256 value as tokenId.

For each attribute we specify the following fields: name, description, type, display_name, display_type, decimals, min_value, max_value, conditional_value, modifiers and multi_storage. Only name and type are required. For more details on the fields, please refer to the [JSON schema] available [`collection-metadata-schema.json`](/EIPs/assets/eip-7508/collection-metadata-schema.json), with an example available at [`collection-metadata-example.json`](/EIPs/assets/eip-7508/collection-metadata-example.json).

The reasoning for conditional_value, modifiers and multi_storage will be discussed in the rationale section.

### Message format for presigned attribute

The message to be signed by the `setter` in order for the attribute setting to be submitted by someone else is formatted as follows:

```solidity
keccak256(
        abi.encode(
            DOMAIN_SEPARATOR,
            METHOD_TYPEHASH,
            collection,
            tokenId,
            key,
            value,
            deadline
        )
    );
```

The values passed when generating the message to be signed are:

- `DOMAIN_SEPARATOR` - The domain separator of the Attribute repository smart contract
- `METHOD_TYPEHASH` - The typehash of the method being called. The supported values, depending on the method are:
  - `SET_UINT_ATTRIBUTE_TYPEHASH` - Used for setting uint attributes
  - `SET_STRING_ATTRIBUTE_TYPEHASH` - Used for setting string attributes
  - `SET_BOOL_ATTRIBUTE_TYPEHASH` - Used for setting bool attributes
  - `SET_BYTES_ATTRIBUTE_TYPEHASH` - Used for setting bytes attributes
  - `SET_ADDRESS_ATTRIBUTE_TYPEHASH` - Used for setting address attributes
- `collection` - Address of the collection containing the token receiving the attribute
- `tokenId` - ID of the token receiving the attribute
- `key` - The attribute key
- `value` - The attribute value of the appropriate type
- `deadline` - UNIX timestamp of the deadline for the signature to be submitted. The signed message submitted after the deadline MUST be rejected

The `DOMAIN_SEPARATOR` is generated as follows:

```solidity
keccak256(
    abi.encode(
        &quot;ERC-7508: Public Non-Fungible Token Attributes Repository&quot;,
        &quot;1&quot;,
        block.chainid,
        address(this)
    )
);
```

The `SET_UINT_ATTRIBUTE_TYPEHASH` is generated as follows:

```solidity
keccak256(
    &quot;setUintAttribute(address collection,uint256 tokenId,string memory key,uint256 value)&quot;
);
```

The `SET_STRING_ATTRIBUTE_TYPEHASH` is generated as follows:

```solidity
keccak256(
    &quot;setStringAttribute(address collection,uint256 tokenId,string memory key,string memory value)&quot;
);
```

The `SET_BOOL_ATTRIBUTE_TYPEHASH` is generated as follows:

```solidity
keccak256(
    &quot;setBoolAttribute(address collection,uint256 tokenId,string memory key,bool value)&quot;
);
```

The `SET_BYTES_ATTRIBUTE_TYPEHASH` is generated as follows:

```solidity
keccak256(
    &quot;setBytesAttribute(address collection,uint256 tokenId,string memory key,bytes memory value)&quot;
);
```

The `SET_ADDRESS_ATTRIBUTE_TYPEHASH` is generated as follows:

```solidity
keccak256(
    &quot;setAddressAttribute(address collection,uint256 tokenId,string memory key,address value)&quot;
);
```

Each chain, that the Attributes repository smart contract is deployed in, will have a different `DOMAIN_SEPARATOR` value due to chain IDs being different.

### Pre-determined address of the Attributes repository

The address of the Emotable repository smart contract is designed to resemble the function it serves. It starts with `0xA77B75` which is the abstract representation of `ATTBTS`. The address is TBD.

## Rationale

Designing the proposal, we considered the following questions:

1. **Should we refer to the values stored by the repository as propertiers or attributes?**\
Historically values defining characteristics of tokens have been called properties, but have evolved in to being called attributes. Referring to the dictionary, the property is defined as a quality or characteristic that something has, and the attribute is defined as a quality or feature of somebody/something. We felt that using the term attribute fits better and decided to use it.
2. **Should the proposal specify access control?**\
Designing the proposal, we had two options: either to include the access control within the specification of the proposal or to leave the access control up to the implementers that desire to use the attributes repository. While considering this we also had to consider the usability and compatibility aspects of the repository.\
On one hand, including access control narrows down the freedom of implementation and requires the implementers to configure it before being able to use the repository. On the other hand, leaving access control up to implementers requires dedicated design of attributes access control within their smart contracts, increasing their size, complexity and deployment costs.\
Another important thing to note is that including access control in the proposal makes it compatible with collections existing prior to the deployment of the repository and thus powers backwards-compatibility.
3. **Should the proposal establish an attributes extension or a common-good repository?**\
Initially we set out to create an attributes extension to be used with any ERC-721 compliant tokens. However, we realized that the proposal would be more useful if it was a common-good repository of token attributes. This way, the tokens that can utilize it are not only the new ones but also the old ones that have been around since before the proposal.\
An additional benefit of this course-correction is the compatibility with ERC-1155 tokens.
4. **Should we include only single-action operations, only multi-action operations, or both?**\
We&apos;ve considered including only single-action operations, where the user is only able to assign a single attribute to a single token, but we decided to include both single-action and multi-action operations. This way, the users can choose whether they want to assign an attribute to a single token or on multiple tokens at once.\
This decision was made for the long-term viability of the proposal. Based on the gas cost of the network and the number of tokens in the collection, the user can choose the most cost-effective way of attribute assigning.
5. **Should we add the ability to assign attributes on someone else&apos;s behalf?**\
While we did not intend to add this as part of the proposal when drafting it, we realized that it would be a useful feature for it. This way, the users can assign attributes on behalf of someone else, for example, if they are not able to do it themselves or if the attribute is earned through an off-chain activity.
6. **How do we ensure that attribute assignment on someone else&apos;s behalf is legitimate?**\
We could add delegates to the proposal; when a user delegates their right to assign attributes to someone else, but having the ability to do so opens up the possibility for abuse and improper setting of attributes.\
Using ECDSA signatures, we can ensure that the user has given their consent to assign attribute on their behalf. This way, the user can sign a message with the parameters of the attribute and the signature can be submitted by someone else.
7. **Should we add chain ID as a parameter when assigning attribute to a token?**\
We decided against this as we feel that additional parameter would rarely be used and would add additional cost to the attribute assignment transactions. If the collection smart contract wants to utilize on-chain token attributes, it requires the reactions to be recorded on the same chain. Marketplaces and wallets integrating this proposal will rely on attributes to reside in the same chain as well, because if chain ID parameter was supported this would mean that they would need to query the repository smart contract on all of the chains the repository is deployed in order to get the attributes of a given token.\
Additionally, if the collection creator wants users to record their reactions on a different chain, they can still direct the users to do just that. The repository does not validate the existence of the token being reacted to (except in an instance where the attribute can be modified by the token&apos;s owner), which in theory means that you can assign an attribute to non-existent token or to a token that does not exist yet. 
8. **How should we reduce the cost of string usage in the repository?**
One fo the main issues we were dealing with while designing the proposal is the cost of string usage. We considered using bytes instead of strings, but decided against it as it would require the users to encode and decode the strings themselves.\
The solution for reducing the cost was to use a string indices. This means that the cost of setting a new string attribute or key will only be paid by the first user to do so. The subsequent users will only pay the cost of setting the index of the string attribute or key.\
We also extended this gas-saving approach to be applicable across the entire repository. This means that if the string was already set by one collection, any other collection using the same string will not have to pay the cost of setting the string again.

## Backwards Compatibility

The Attributes repository standard is fully compatible with [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155) and with the robust tooling available for implementations of ERC-721 as well as with the existing ERC-721 infrastructure.

## Test Cases

Tests are included in [`attributesRepository.ts`](/EIPs/assets/eip-7508/test/attributesRepository.ts).

To run them in terminal, you can use the following commands:

```
cd ../assets/eip-7508
pnpm i
pnpm hardhat test
```

## Reference Implementation

See [`AttributesRepository.sol`](/EIPs/assets/eip-7508/contracts/AttributesRepository.sol).

## Security Considerations

The proposal does not envision handling any form of assets from the user, so the assets should not be at risk when interacting with an Attributes repository.

The ability to use ECDSA signatures to set attributes on someone else&apos;s behalf introduces the risk of a replay attack, which the format of the message to be signed guards against. The `DOMAIN_SEPARATOR` used in the message to be signed is unique to the repository smart contract of the chain it is deployed on. This means that the signature is invalid on any other chain and the attributes repositories deployed on them should revert the operation if a replay attack is attempted.

Another thing to consider is the ability of presigned message reuse. Since the message includes the signature validity deadline, the message can be reused any number of times before the deadline is reached. The proposal only allows for a single value for a given key to be set, so the presigned message can not be abused to further modify the attribute value. However, if the service using the repository relies on the ability to revert or modify the attribute after certain actions, a valid presigned message can be used to re-assign the attribute of the token. We suggest that the services using the repository in cnjunction with presigned messages use deadlines that invalidate presigned messages after a reasonalby short period of time.

Caution is advised when dealing with non-audited contracts.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 15 Aug 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7508</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7508</guid>
      </item>
    
      <item>
        <title>Entity Component System</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/a-new-proposal-of-entity-component-system/15665</comments>
        
        <description>## Abstract

This proposal defines a minimal Entity Component System (ECS). Entities are unique identities that are assigned to multiple components (data) and then processed using the system (logic).
This proposal standardizes the interface specification for using ECS in smart contracts, providing a set of basic functions that allow users to freely combine and manage multi-contract applications.

## Motivation   

ECS is a design pattern that improves code reusability by separating data from behavior. It is often used in game development. A minimal ECS consists of   
**Entity**: a unique identifier.   
**Component**: a reusable data container attached to an entity.   
**System**: the logic for operating entity components.   
**World**: a container for an entity component system.   
This proposal uses smart contracts to implement an easy-to-use minimal ECS, eliminates unnecessary complexity, and makes some functional improvements that are consistent with contract interaction behavior. You can combine components and systems easily and freely.
As a smart contract developer, the benefits of adopting ECS include:

- It adopts a simple design of decoupling, encapsulation, and modularization, which makes the architecture design of your game or application easier.
- It has flexible composition ability, each entity can combine different components. You can also define different systems for manipulating the data of these new entities.
- It is conducive to expansion, and two games or applications can interact by defining new components and systems.
- It can help your application add new features or upgrades, because data and behavior are separated, new features will not affect your old data.
- It is easy to manage. When your application consists of multiple contracts, it will help you effectively manage the status of each contract.
- Its components are reusable, and you can share your components with the community to help others improve development efficiency.

## Specification

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

World contracts are containers for entities, component contracts, and system contracts. Its core principle is to establish the relationship between entities and component contracts, where different entities will attach different components, and use system contracts to dynamically change the data of the entity in the component.

Usual workflow when building ECS-based programs:

1. Implement the `IWorld` interface to create a world contract.
2. Call `createEntity()` of the world contract to create an entity.
3. Implement the `IComponent` interface to create a Component contract.
4. Call `registerComponent()` of the world contract to register the component contract.
5. Call `addComponent()` of the world contract to attach the component to the entity.
6. Create a system contract, which is a contract without interface restrictions, and you can define any function in the system contract.
7. Call `registerSystem()` of the world contract to register the system contract.
8. Run the system.

### Interfaces

#### `IWorld.sol`

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity &gt;=0.8.0;

interface IWorld {
    /**
     * Create a new entity.
     * @dev The entity MUST be assigned a unique Id.
     * If the state of the entity is true, it means it is available, and if it is false, it means it is not available.
     * When the state of the entity is false, you cannot add or remove components for the entity.
     * @return New entity id.
     */
    function createEntity() external returns (uint256);

    /**
     * Does the entity exist in the world.
     * @param _entityId is the Id of the entity.
     * @return true exists, false does not exist.
     */
    function entityExists(uint256 _entityId) external view returns (bool);

    /**
     * Get the total number of entities in the world.
     * @return The total number of entities.
     */
    function getEntityCount() external view returns (uint256);

    /**
     * Set the state of an entity.
     * @dev Entity MUST exist.
     * @param _entityId is the Id of the entity.
     * @param _entityState is the state of the entity, true means available, false means unavailable.
     */
    function setEntityState(uint256 _entityId, bool _entityState) external;

    /**
     * Get the state of an entity.
     * @param _entityId Id of the entity.
     * @return The current state of the entity.
     */
    function getEntityState(uint256 _entityId) external view returns (bool);

    /**
     * Register a component to the world.
     * @dev A component MUST be registered with the world before it can be attached to an entity.
     * MUST NOT register the same component to the world repeatedly.
     * It SHOULD be checked that the contract address returned by world() of the component contract is the same as the current world contract.
     * The state of the component is true means it is available, and false means it is not available. When the component state is set to false, it cannot be attached to the entity.
     * @param _componentAddress is the contract address of the component.
     */
    function registerComponent(address _componentAddress) external;

    /**
     * Does the component exist in the world.
     * @param _componentAddress is the contract address of the component.
     * @return true exists, false does not exist.
     */
    function componentExists(address _componentAddress)
        external
        view
        returns (bool);

    /**
     * Get the contract addresses of all components registered in the world.
     * @return Array of contract addresses.
     */
    function getComponents() external view returns (address[] memory);

    /**
     * Set component state.
     * @dev Component MUST exist.
     * @param _componentAddress is the contract address of the component.
     * @param _componentState is the state of the component, true means available, false means unavailable.
     */
    function setComponentState(address _componentAddress, bool _componentState)
        external;

    /**
     * Get the state of a component.
     * @param _componentAddress is the contract address of the component.
     * @return true means available, false means unavailable.
     */
    function getComponentState(address _componentAddress)
        external
        view
        returns (bool);

    /**
     * Attach a component to the entity.
     * @dev Entity MUST be available.Component MUST be available.A component MUST NOT be added to an entity repeatedly.
     * @param _entityId is the Id of the entity.
     * @param _componentAddress is the address of the component to be attached.
     */
    function addComponent(uint256 _entityId, address _componentAddress)
        external;

    /**
     * Whether the entity has a component attached,
     * @dev Entity MUST exist.Component MUST be registered.
     * @param _entityId is the Id of the entity.
     * @param _componentAddress is the component address.
     * @return true is attached, false is not attached
     */
    function hasComponent(uint256 _entityId, address _componentAddress)
        external
        view
        returns (bool);

    /**
     * Remove a component from the entity.
     * @dev Entity MUST be available.The component MUST have been added to the entity before.
     * @param _entityId is the Id of the entity.
     * @param _componentAddress is the address of the component to be removed.
     */
    function removeComponent(uint256 _entityId, address _componentAddress)
        external;

    /**
     * Get the contract addresses of all components attached to the entity.
     * @dev Entity MUST exist.
     * @param _entityId is the Id of the entity.
     * @return An array of contract addresses of the components owned by this entity.
     */
    function getEntityComponents(uint256 _entityId)
        external
        view
        returns (address[] memory);

    /**
     * Register a system to the world.
     * @dev MUST NOT register the same system to the world repeatedly.The system state is true means available, false means unavailable.
     * @param _systemAddress is the contract address of the system.
     */
    function registerSystem(address _systemAddress) external;

    /**
     * Does the system exist in the world.
     * @param _systemAddress is the contract address of the system.
     * @return true exists, false does not exist.
     */
    function systemExists(address _systemAddress) external view returns (bool);

    /**
     * Get the contract addresses of all systems registered in the world.
     * @return Array of contract addresses.
     */
    function getSystems() external view returns (address[] memory);

    /**
     * Set the system State.
     * @dev System MUST exist.
     * @param _systemAddress is the contract address of the system.
     * @param _systemState is the state of the system.
     */
    function setSystemState(address _systemAddress, bool _systemState) external;

    /**
     * Get the state of a system.
     * @param _systemAddress is the contract address of the system.
     * @return The state of the system.
     */
    function getSystemState(address _systemAddress)
        external
        view
        returns (bool);
}
```

#### `IComponent.sol`

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity &gt;=0.8.0;
import &quot;./Types.sol&quot;;

interface IComponent {
    /**
     * The world contract address registered by the component.
     * @return world contract address.
     */
    function world() external view returns (address);

    /**
     *Get the data type and get() parameter type of the component
     * @dev SHOULD Import Types Library, which is an enumeration Library containing all data types.
     * Entity data can be stored according to the data type.
     * The get() parameter data type can be used to get entity data.
     * @return the data type array of the entity
     * @return get parameter data type array
     */
    function types()
        external
        view
        returns (Types.Type[] memory, Types.Type[] memory);

    /**
     *Store entity data.
     * @dev entity MUST be available. The system that operates on it MUST be available.
     * The entity has the component attached.
     * @param _entityId is the Id of the entity.
     * @param _data is the data to be stored.
     */
    function set(uint256 _entityId, bytes memory _data) external;

    /**
     *Get the data of the entity according to the entity Id.
     * @param _entityId is the Id of the entity.
     * @return Entity data.
     */
    function get(uint256 _entityId) external view returns (bytes memory);

    /** Get the data of the entity according to the entity Id and parameters.
     * @param _entityId is the Id of the entity.
     * @param _params is an extra parameter, it SHOULD depend on whether you need it.
     * @return Entity data.
     */
    function get(uint256 _entityId, bytes memory _params)
        external
        view
        returns (bytes memory);
}
```

### Library

The library [`Types.sol`](/EIPs/assets/eip-7509/Types.sol) contains an enumeration of Solidity types used in the above interfaces.

## Rationale

### Why include type information instead of simple byte arrays?

This is to ensure the correctness of types when using components, in order to avoid potential errors and inconsistencies. External developers can clearly set and get based on the type.

### Why differentiate between a non-existent entity and an entity with false state?

We cannot judge whether an entity actually exists based on its state alone. External contributors can create components based on entities. If the entities he uses don&apos;t exist, the components he creates may not make sense. Component creators should first check if the entity exists, and if the entity does exist, it makes sense even if the entity&apos;s state is false. Because he can wait for the entity state to be true before attaching the component to the entity.

### Why `getEntityComponents` function returns all addresses of components instead of all component ids?

There are two designs for `getEntityComponents`. The other design is to add an additional mapping for the storage of component id and component address. Every time we call `addComponent`, the parameters of the function are the entity id and component id. When the user calls `getEntityComponents`, it will returning an array of component ids, they query the component address with each component id, and then query the data based on each component address. Because a entity may contain many component ids, this will cause the user to request the component address multiple times. In the end, we chose to use `getEntityComponents` directly for all addresses owned by the entity.

### Can `registerComponent` and `registerSystem` provide external permissions?

It depends on the openness of your application or game. If you encourage developers to participate, the state of the component and system they submit for registration should be `false`, and you need to check whether they have submitted malicious code before using `setComponentState` and `setSystemState` to enable them .

### When to use `get` with extra parameters in component?

The component provides two `get` functions. One `get` function only needs to pass in the entity id, and the other has more `_params` parameters, which will be used as additional parameters for obtaining data. For example, you define a component that stores the HP corresponding to the level of an entity. If you want to get the HP of an entity that matches its level, then you call the `get` function with the entity level as `_params`.

## Reference Implementation

See [Ethereum ECS Example](/EIPs/assets/eip-7509/)

## Security Considerations

Unless you want to implement special functions, do not provide the following methods directly to ordinary users, they should be set by the contract owner.   
`createEntity()`,
`setEntityState()`,
`addComponent()`,
`removeComponent()`,
`registerComponent()`,
`setComponentState()`,
`registerSystem()`,
`setSystemState()`

Do not provide functions that modify entities other than set() in the component contract. And add a check in `set()` to check whether the entity is available and whether the operating system is available.   

After the system is registered in the world, it will be able to operate the component data of all entities in the world. It is necessary to check and audit the code security of all system contracts before registering it in the world.

If the new version has deprecated some entities, component contracts and system contracts. They need to be disabled in time using `setEntityState()`, `setComponentState()`, and `setSystemState()`.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Tue, 05 Sep 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7509</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7509</guid>
      </item>
    
      <item>
        <title>Cross-Contract Hierarchical NFT</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7510-cross-contract-hierarchical-nft/15687</comments>
        
        <description>## Abstract

This standard is an extension of [ERC-721](/EIPs/EIPS/eip-721). It proposes a way to maintain hierarchical relationship between tokens from different contracts. This standard provides an interface to query the parent tokens of an NFT or whether the parent relation exists between two NFTs.

## Motivation

Some NFTs want to generate derivative assets as new NFTs. For example, a 2D NFT image would like to publish its 3D model as a new derivative NFT. An NFT may also be derived from multiple parent NFTs. Such cases include a movie NFT featuring multiple characters from other NFTs. This standard is proposed to record such hierarchical relationship between derivative NFTs.

Existing [ERC-6150](/EIPs/EIPS/eip-6150) introduces a similar feature, but it only builds hierarchy between tokens within the same contract. More than often we need to create a new NFT collection with the derivative tokens, which requires cross-contract relationship establishment. In addition, deriving from multiple parents is very common in the scenario of IP licensing, but the existing standard doesn&apos;t support that either.

## Specification

Solidity interface available at [`IERC7510.sol`](/EIPs/assets/eip-7510/contracts/IERC7510.sol):

```solidity
/// @notice The struct used to reference a token in an NFT contract
struct Token {
    address collection;
    uint256 id;
}

interface IERC7510 {

    /// @notice Emitted when the parent tokens for an NFT is updated
    event UpdateParentTokens(uint256 indexed tokenId);

    /// @notice Get the parent tokens of an NFT
    /// @param tokenId The NFT to get the parent tokens for
    /// @return An array of parent tokens for this NFT
    function parentTokensOf(uint256 tokenId) external view returns (Token[] memory);

    /// @notice Check if another token is a parent of an NFT
    /// @param tokenId The NFT to check its parent for
    /// @param otherToken Another token to check as a parent or not
    /// @return Whether `otherToken` is a parent of `tokenId`
    function isParentToken(uint256 tokenId, Token memory otherToken) external view returns (bool);

    /// @notice Set the parent tokens for an NFT
    /// @param tokenId The NFT to set the parent tokens for
    /// @param parentTokens The parent tokens to set
    function setParentTokens(uint256 tokenId, Token[] memory parentTokens) external;

}
```

## Rationale

This standard differs from [ERC-6150](/EIPs/EIPS/eip-6150) in mainly two aspects: supporting cross-contract token reference, and allowing multiple parents. But we try to keep the naming consistent overall.

In addition, we didn&apos;t include `child` relation in the interface. An original NFT exists before its derivative NFTs. Therefore we know what parent tokens to include when minting derivative NFTs, but we wouldn&apos;t know the children tokens when minting the original NFT. If we have to record the children, that means whenever we mint a derivative NFT, we need to call on its original NFT to add it as a child. However, those two NFTs may belong to different contracts and thus require different write permissions, making it impossible to combine the two operations into a single transaction in practice. As a result, we decide to only record the `parent` relation from the derivative NFTs.

## Backwards Compatibility

No backwards compatibility issues found.

## Test Cases

Test cases available at: [`ERC7510.test.ts`](/EIPs/assets/eip-7510/test/ERC7510.test.ts):

```typescript
import { loadFixture } from &quot;@nomicfoundation/hardhat-toolbox/network-helpers&quot;;
import { expect } from &quot;chai&quot;;
import { ethers } from &quot;hardhat&quot;;

const NAME = &quot;NAME&quot;;
const SYMBOL = &quot;SYMBOL&quot;;
const TOKEN_ID = 1234;

const PARENT_1_COLLECTION = &quot;0xDEAdBEEf00000000000000000123456789ABCdeF&quot;;
const PARENT_1_ID = 8888;
const PARENT_1_TOKEN = { collection: PARENT_1_COLLECTION, id: PARENT_1_ID };

const PARENT_2_COLLECTION = &quot;0xBaDc0ffEe0000000000000000123456789aBCDef&quot;;
const PARENT_2_ID = 9999;
const PARENT_2_TOKEN = { collection: PARENT_2_COLLECTION, id: PARENT_2_ID };

describe(&quot;ERC7510&quot;, function () {

  async function deployContractFixture() {
    const [deployer, owner] = await ethers.getSigners();

    const contract = await ethers.deployContract(&quot;ERC7510&quot;, [NAME, SYMBOL], deployer);
    await contract.mint(owner, TOKEN_ID);

    return { contract, owner };
  }

  describe(&quot;Functions&quot;, function () {
    it(&quot;Should not set parent tokens if not owner or approved&quot;, async function () {
      const { contract } = await loadFixture(deployContractFixture);

      await expect(contract.setParentTokens(TOKEN_ID, [PARENT_1_TOKEN]))
        .to.be.revertedWith(&quot;ERC7510: caller is not owner or approved&quot;);
    });

    it(&quot;Should correctly query token without parents&quot;, async function () {
      const { contract } = await loadFixture(deployContractFixture);

      expect(await contract.parentTokensOf(TOKEN_ID)).to.have.lengthOf(0);

      expect(await contract.isParentToken(TOKEN_ID, PARENT_1_TOKEN)).to.equal(false);
    });

    it(&quot;Should set parent tokens and then update&quot;, async function () {
      const { contract, owner } = await loadFixture(deployContractFixture);

      await contract.connect(owner).setParentTokens(TOKEN_ID, [PARENT_1_TOKEN]);

      let parentTokens = await contract.parentTokensOf(TOKEN_ID);
      expect(parentTokens).to.have.lengthOf(1);
      expect(parentTokens[0].collection).to.equal(PARENT_1_COLLECTION);
      expect(parentTokens[0].id).to.equal(PARENT_1_ID);

      expect(await contract.isParentToken(TOKEN_ID, PARENT_1_TOKEN)).to.equal(true);
      expect(await contract.isParentToken(TOKEN_ID, PARENT_2_TOKEN)).to.equal(false);

      await contract.connect(owner).setParentTokens(TOKEN_ID, [PARENT_2_TOKEN]);

      parentTokens = await contract.parentTokensOf(TOKEN_ID);
      expect(parentTokens).to.have.lengthOf(1);
      expect(parentTokens[0].collection).to.equal(PARENT_2_COLLECTION);
      expect(parentTokens[0].id).to.equal(PARENT_2_ID);

      expect(await contract.isParentToken(TOKEN_ID, PARENT_1_TOKEN)).to.equal(false);
      expect(await contract.isParentToken(TOKEN_ID, PARENT_2_TOKEN)).to.equal(true);
    });

    it(&quot;Should burn and clear parent tokens&quot;, async function () {
      const { contract, owner } = await loadFixture(deployContractFixture);

      await contract.connect(owner).setParentTokens(TOKEN_ID, [PARENT_1_TOKEN, PARENT_2_TOKEN]);
      await contract.burn(TOKEN_ID);

      await expect(contract.parentTokensOf(TOKEN_ID)).to.be.revertedWith(&quot;ERC7510: query for nonexistent token&quot;);
      await expect(contract.isParentToken(TOKEN_ID, PARENT_1_TOKEN)).to.be.revertedWith(&quot;ERC7510: query for nonexistent token&quot;);
      await expect(contract.isParentToken(TOKEN_ID, PARENT_2_TOKEN)).to.be.revertedWith(&quot;ERC7510: query for nonexistent token&quot;);

      await contract.mint(owner, TOKEN_ID);

      expect(await contract.parentTokensOf(TOKEN_ID)).to.have.lengthOf(0);
      expect(await contract.isParentToken(TOKEN_ID, PARENT_1_TOKEN)).to.equal(false);
      expect(await contract.isParentToken(TOKEN_ID, PARENT_2_TOKEN)).to.equal(false);
    });
  });

  describe(&quot;Events&quot;, function () {
    it(&quot;Should emit event when set parent tokens&quot;, async function () {
      const { contract, owner } = await loadFixture(deployContractFixture);

      await expect(contract.connect(owner).setParentTokens(TOKEN_ID, [PARENT_1_TOKEN, PARENT_2_TOKEN]))
        .to.emit(contract, &quot;UpdateParentTokens&quot;).withArgs(TOKEN_ID);
    });
  });

});
```

## Reference Implementation

Reference implementation available at: [`ERC7510.sol`](/EIPs/assets/eip-7510/contracts/ERC7510.sol):

```solidity
// SPDX-License-Identifier: CC0-1.0

pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;

import &quot;./IERC7510.sol&quot;;

contract ERC7510 is ERC721, IERC7510 {

    mapping(uint256 =&gt; Token[]) private _parentTokens;
    mapping(uint256 =&gt; mapping(address =&gt; mapping(uint256 =&gt; bool))) private _isParentToken;

    constructor(
        string memory name, string memory symbol
    ) ERC721(name, symbol) {}

    function supportsInterface(
        bytes4 interfaceId
    ) public view virtual override returns (bool) {
        return interfaceId == type(IERC7510).interfaceId || super.supportsInterface(interfaceId);
    }

    function parentTokensOf(
        uint256 tokenId
    ) public view virtual override returns (Token[] memory) {
        require(_exists(tokenId), &quot;ERC7510: query for nonexistent token&quot;);
        return _parentTokens[tokenId];
    }

    function isParentToken(
        uint256 tokenId, Token memory otherToken
    ) public view virtual override returns (bool) {
        require(_exists(tokenId), &quot;ERC7510: query for nonexistent token&quot;);
        return _isParentToken[tokenId][otherToken.collection][otherToken.id];
    }

    function setParentTokens(
        uint256 tokenId, Token[] memory parentTokens
    ) public virtual override {
        require(_isApprovedOrOwner(_msgSender(), tokenId), &quot;ERC7510: caller is not owner or approved&quot;);
        _clear(tokenId);
        for (uint256 i = 0; i &lt; parentTokens.length; i++) {
            _parentTokens[tokenId].push(parentTokens[i]);
            _isParentToken[tokenId][parentTokens[i].collection][parentTokens[i].id] = true;
        }
        emit UpdateParentTokens(tokenId);
    }

    function _burn(
        uint256 tokenId
    ) internal virtual override {
        super._burn(tokenId);
        _clear(tokenId);
    }

    function _clear(
        uint256 tokenId
    ) private {
        Token[] storage parentTokens = _parentTokens[tokenId];
        for (uint256 i = 0; i &lt; parentTokens.length; i++) {
            delete _isParentToken[tokenId][parentTokens[i].collection][parentTokens[i].id];
        }
        delete _parentTokens[tokenId];
    }

}
```

## Security Considerations

Parent tokens of an NFT may point to invalid data for two reasons. First, parent tokens could be burned later. Second, a contract implementing `setParentTokens` might not check the validity of `parentTokens` arguments. For security consideration, applications that retrieve parent tokens of an NFT need to verify they exist as valid tokens.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 24 Aug 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7510</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7510</guid>
      </item>
    
      <item>
        <title>Minimal Proxy Contract with PUSH0</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7511-minimal-proxy-contract-with-push0/15662</comments>
        
        <description>## Abstract

With the `PUSH0` opcode ([EIP-3855](/EIPs/EIPS/eip-3855)), introduced with the Shanghai upgrade, we optimized the previous Minimal Proxy Contract ([ERC-1167](/EIPs/EIPS/eip-1167)) by 200 gas at deployment and 5 gas at runtime, while retaining the same functionality.

## Motivation


1. Reduce the contract bytecode size by `1` byte by removing a redundant `SWAP` opcode.
2. Reduce the runtime gas by replacing two `DUP` (cost `3` gas each) with two `PUSH0` (cost `2` gas each).
3. Increase the readability of the proxy contract by redesigning it from first principles with `PUSH0`.

## Specification

### Standard Proxy Contract

The exact runtime code for the minimal proxy contract with `PUSH0` is: 

```
365f5f375f5f365f73bebebebebebebebebebebebebebebebebebebebe5af43d5f5f3e5f3d91602a57fd5bf3
```

where the bytes at indices 9 - 28 (inclusive) are replaced with the 20-byte address of the master implementation contract. The length of the runtime code is `44` bytes.

The disassembly of the new minimal proxy contract code is:

| pc   | op     | opcode         | stack              |
|------|--------|----------------|--------------------|
| [00] | 36     | CALLDATASIZE   | cds                |
| [01] | 5f     | PUSH0          | 0 cds              |
| [02] | 5f     | PUSH0          | 0 0 cds            |
| [03] | 37     | CALLDATACOPY   |                    |
| [04] | 5f     | PUSH0          | 0                  |
| [05] | 5f     | PUSH0          | 0 0                |
| [06] | 36     | CALLDATASIZE   | cds 0 0            |
| [07] | 5f     | PUSH0          | 0 cds 0 0          |
| [08] | 73bebe.| PUSH20 0xbebe. | 0xbebe. 0 cds 0 0  |
| [1d] | 5a     | GAS            | gas 0xbebe. 0 cds 0 0|
| [1e] | f4     | DELEGATECALL   | suc                |
| [1f] | 3d     | RETURNDATASIZE | rds suc            |
| [20] | 5f     | PUSH0          | 0 rds suc          |
| [21] | 5f     | PUSH0          | 0 0 rds suc        |
| [22] | 3e     | RETURNDATACOPY | suc                |
| [23] | 5f     | PUSH0          | 0 suc              |
| [24] | 3d     | RETURNDATASIZE | rds 0 suc          |
| [25] | 91     | SWAP2          | suc 0 rds          |
| [26] | 602a   | PUSH1 0x2a     | 0x2a suc 0 rds     |
| [27] | 57     | JUMPI          | 0 rds              |
| [29] | fd     | REVERT         |                    |
| [2a] | 5b     | JUMPDEST       | 0 rds              |
| [2b] | f3     | RETURN         |                    |

### Minimal Creation Code

The minimal creation code of the minimal proxy contract is:

```
602c8060095f395ff3365f5f375f5f365f73bebebebebebebebebebebebebebebebebebebebe5af43d5f5f3e5f3d91602a57fd5bf3
```

where the first 9 bytes are the initcode: 

```
602c8060095f395ff3
```

And the rest are runtime/contract code of the proxy. The length of the creation code is `53` bytes.

### Deploy with Solidity

The minimal proxy contract can be deployed with Solidity using the following contract:

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.20;

// Note: this contract requires `PUSH0`, which is available in solidity &gt; 0.8.20 and EVM version &gt; Shanghai
contract Clone0Factory {
    error FailedCreateClone();

    receive() external payable {}

    /**
     * @dev Deploys and returns the address of a clone0 (Minimal Proxy Contract with `PUSH0`) that mimics the behaviour of `implementation`.
     *
     * This function uses the create opcode, which should never revert.
     */
    function clone0(address impl) public payable returns (address addr) {
        // first 18 bytes of the creation code 
        bytes memory data1 = hex&quot;602c8060095f395ff3365f5f375f5f365f73&quot;;
        // last 15 bytes of the creation code
        bytes memory data2 = hex&quot;5af43d5f5f3e5f3d91602a57fd5bf3&quot;;
        // complete the creation code of Clone0
        bytes memory _code = abi.encodePacked(data1, impl, data2);

        // deploy with create op
        assembly {
            // create(v, p, n)
            addr := create(callvalue(), add(_code, 0x20), mload(_code))
        }

        if (addr == address(0)) {
            revert FailedCreateClone();
        }
    }
}
```

## Rationale

The optimized contract is constructed with essential components of the proxy contract and incorporates the recently added `PUSH0` opcode. The core elements of the minimal proxy include:

1. Copy the calldata with `CALLDATACOPY`.
2. Forward the calldata to the implementation contract using `DELEGATECALL`.
3. Copy the returned data from the `DELEGATECALL`.
4. Return the results or revert the transaction based on whether the `DELEGATECALL` is successful.

### Step 1: Copy the Calldata

To copy the calldata, we need to provide the arguments for the `CALLDATACOPY` opcodes, which are `[0, 0, cds]`, where `cds` represents calldata size.

| pc   | op     | opcode         | stack              |
|------|--------|----------------|--------------------|
| [00] | 36     | CALLDATASIZE   | cds                |
| [01] | 5f     | PUSH0          | 0 cds              |
| [02] | 5f     | PUSH0          | 0 0 cds            |
| [03] | 37     | CALLDATACOPY   |                    |

### Step 2: Delegatecall

To forward the calldata to the delegate call, we need to prepare arguments for the `DELEGATECALL` opcodes, which are `[gas 0xbebe. 0 cds 0 0]`, where `gas` represents the remaining gas, `0xbebe.` represents the address of the implementation contract, and `suc` represents whether the delegatecall is successful. 

| pc   | op     | opcode         | stack              |
|------|--------|----------------|--------------------|
| [04] | 5f     | PUSH0          | 0                  |
| [05] | 5f     | PUSH0          | 0 0                |
| [06] | 36     | CALLDATASIZE   | cds 0 0            |
| [07] | 5f     | PUSH0          | 0 cds 0 0          |
| [08] | 73bebe.| PUSH20 0xbebe. | 0xbebe. 0 cds 0 0  |
| [1d] | 5a     | GAS            | gas 0xbebe. 0 cds 0 0|
| [1e] | f4     | DELEGATECALL   | suc                |

### Step 3: Copy the Returned Data from the `DELEGATECALL`

To copy the returndata, we need to provide the arguments for the `RETURNDATACOPY` opcodes, which are `[0, 0, red]`, where `rds` represents size of returndata from the `DELEGATECALL`.

| pc   | op     | opcode         | stack              |
|------|--------|----------------|--------------------|
| [1f] | 3d     | RETURNDATASIZE | rds suc            |
| [20] | 5f     | PUSH0          | 0 rds suc          |
| [21] | 5f     | PUSH0          | 0 0 rds suc        |
| [22] | 3e     | RETURNDATACOPY | suc                |

### Step 4: Return or Revert

Lastly, we need to return the data or revert the transaction based on whether the `DELEGATECALL` is successful. There is no `if/else` in opcodes, so we need to use `JUMPI` and `JUMPDEST` instead. The arguments for `JUMPI` is `[0x2a, suc]`, where `0x2a` is the destination of the conditional jump.

 We also need to prepare the argument `[0, rds]` for `REVERT` and `RETURN` opcodes before the `JUMPI`, otherwise we have to prepare them twice. We cannot avoid the `SWAP` operation, because we can only get `rds` after the `DELEGATECALL`.

| pc   | op     | opcode         | stack              |
|------|--------|----------------|--------------------|
| [23] | 5f     | PUSH0          | 0 suc              |
| [24] | 3d     | RETURNDATASIZE | rds 0 suc          |
| [25] | 91     | SWAP2          | suc 0 rds          |
| [26] | 602a   | PUSH1 0x2a     | 0x2a suc 0 rds     |
| [27] | 57     | JUMPI          | 0 rds              |
| [29] | fd     | REVERT         |                    |
| [2a] | 5b     | JUMPDEST       | 0 rds              |
| [2b] | f3     | RETURN         |                    |

In the end, we arrived at the runtime code for Minimal Proxy Contract with `PUSH0`: 

```
365f5f375f5f365f73bebebebebebebebebebebebebebebebebebebebe5af43d5f5f3e5f3d91602a57fd5bf3
```

The length of the runtime code is `44` bytes, which reduced `1` byte from the previous Minimal Proxy Contract. Moreover, it replaced the `RETURNDATASIZE` and `DUP` operations with `PUSH0`, which saves gas and increases the readability of the code. In summary, the new Minimal Proxy Contract reduces `200` gas at deployment and `5` gas at runtime, while remaining the same functionalities as the old one.

## Backwards Compatibility

Because the new minimal proxy contract uses `PUSH0` opcode, it can only be deployed after the Shanghai Upgrade. It behaves the same as the previous Minimal Proxy Contract.

## Security Considerations

The new proxy contract standard is identical to the previous one (ERC-1167). Here are the security considerations when using minimal proxy contracts:

1. **Non-Upgradability**: Minimal Proxy Contracts delegate their logic to another contract (often termed the &quot;implementation&quot; or &quot;logic&quot; contract). This delegation is fixed upon deployment, meaning you can&apos;t change which implementation contract the proxy delegates to after its creation.
   
2. **Initialization Concerns**: Proxy contracts lack constructors, so you need to use an initialization function after deployment. Skipping this step could leave the contract unsafe.

3. **Safety of Logic Contract**: Vulnerabilities in the logic contract affect all associated proxy contracts.

4. **Transparency Issues**: Because of its complexity, users might see the proxy as an empty contract, making it challenging to trace back to the actual logic contract.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 04 Sep 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7511</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7511</guid>
      </item>
    
      <item>
        <title>Onchain Representation for Audits</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7512-onchain-audit-representation/15683</comments>
        
        <description>## Abstract

The proposal aims to create a standard for an onchain representation of audit reports that can be parsed by contracts to extract relevant information about the audits, such as who performed the audits and what standards have been verified.

## Motivation

Audits are an integral part of the smart contract security framework. They are commonly used to increase the security of smart contracts and ensure that they follow best practices as well as correctly implement standards such [ERC-20](/EIPs/EIPS/eip-20), [ERC-721](/EIPs/EIPS/eip-721), and similar ERCs. Many essential parts of the blockchain ecosystem are facilitated by the usage of smart contracts. Some examples of this are:

- Bridges: Most bridges consist of a bridgehead or a lockbox that secures the tokens that should be bridged. If any of these contracts are faulty it might be possible to bring the operation of the bridge to a halt or, in extreme circumstances, cause uncollateralized assets to be minted on satellite chains.
- Token Contracts: Every token in the Ethereum ecosystem is a smart contract. Apps that interact with these tokens rely on them adhering to known token standards, most commonly [ERC-20](/EIPs/EIPS/eip-20) and [ERC-721](/EIPs/EIPS/eip-721). Tokens that behave differently can cause unexpected behavior and might even lead to loss of funds.
- Smart Contract Accounts (SCAs): With [ERC-4337](/EIPs/EIPS/eip-4337) more visibility has been created for smart-contract-based accounts. They provide extreme flexibility and can cater to many different use cases whilst retaining a greater degree of control and security over each account. A concept that has been experimented with is the idea of modules that allow the extension of a smart contract account&apos;s functionality. [ERC-6900](/EIPs/EIPS/eip-6900)) is a recent standard that defines how to register and design plugins that can be registered on an account.
- Interoperability (Hooks &amp; Callbacks): With more protocols supporting external-facing functions to interact with them and different token standards triggering callbacks on a transfer (i.e. [ERC-1155](/EIPs/EIPS/eip-1155)), it is important to make sure that these interactions are well vetted to minimize the security risks they are associated with as much as possible.

The usage and impact smart contracts will have on the day-to-day operations of decentralized applications will steadily increase. To provide tangible guarantees about security and allow better composability it is imperative that an onchain verification method exists to validate that a contract has been audited. Creating a system that can verify that an audit has been made for a specific contract will strengthen the security guarantees of the whole smart contract ecosystem.

While this information alone is no guarantee that there are no bugs or flaws in a contract, it can provide an important building block to create innovative security systems for smart contracts in an onchain way.

### Example

Imagine a hypothetical [ERC-1155](/EIPs/EIPS/eip-1155) token bridge. The goal is to create a scalable system where it is possible to easily register new tokens that can be bridged. To minimize the risk of malicious or faulty tokens being registered, audits will be used and verified onchain.

![Onchain Audit Example Use Case](/EIPs/assets/eip-7512/example_use_case.png)

To illustrate the flow within the diagram clearly, it separates the Bridge and the Verifier roles into distinct actors. Theoretically, both can live in the same contract. 

There are four parties:

- User: The end user that wants to bridge their token
- Bridge Operator: The operator that maintains the bridge
- Bridge: The contract the user will interact with to trigger the bridge operation
- Validator: The contract that validates that a token can be bridged

As a first (1) step, the bridge operator should define the keys/accounts for the auditors from which audits are accepted for the token registration process. 

With this, the user (or token owner) can trigger the registration flow (2). There are two steps (3 and 6) that will be performed: verify that the provided audit is valid and has been signed by a trusted auditor (4), and check that the token contract implements the bridge&apos;s supported token standard ([ERC-1155](/EIPs/EIPS/eip-1155)) (7).

After the audit and token standard validations have been performed, it is still advisable to have some form of manual intervention in place by the operator to activate a token for bridging (10). &lt;!-- This step could be omitted if there is strong trust in the auditor or if an ERC provides strong compatibility guarantees. --&gt;

Once the token has been activated on the bridge, Users can start bridging it (11). 

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119 and RFC 8174.

### Audit Properties

- Auditor
    - `name`: Name of the auditor (i.e. for displaying to the user)
    - `uri`: URI to retrieve more information about the auditor
    - `authors`: A list of authors that contributed to this audit. This SHOULD be the persons who audited the contracts and created the audit
- Audit
    - `auditor`: Information on the auditor
    - `auditedContract`: MUST be the `chainId` as well as `deployment` of the contract the audit is related to
    - `issuedAt`: MUST contain the information when the original audit (identified by the `auditHash`) was issued
    - `ercs`: A list of ERCs that are implemented by the target contract. The ERCs listed MUST be fully implemented. This list MAY be empty
    - `auditHash`: MUST be the hash of the original audit. This allows onchain verification of information that may belong to a specific audit
    - `auditUri`: SHOULD point to a source where the audit can be retrieved
- Contract
    - `chainId`: MUST be a `bytes32` representation of the [EIP-155](/EIPs/EIPS/eip-155) chain ID of the blockchain that the contract has been deployed in
    - `deployment`: MUST be an `address` representation of a contract&apos;s deployment address

### Auditor Verification

- Signature
    - Type
        - `SECP256K1`
            - Data is the encoded representation of `r`, `s`, and `v`
        - `BLS`
            - TBD
        - `ERC1271`
            - Data is the ABI-encoded representation of `chainId`, `address`, `blocknumber`, and the `signature bytes`
        - `SECP256R1`
            - Data is the encoded representation of `r`, `s`, and `v`
    - Data

### Data types

```solidity
struct Auditor {
    string name;
    string uri;
    string[] authors;
}

struct Contract {
    bytes32 chainId;
    address deployment;
}

struct AuditSummary {
    Auditor auditor;
    uint256 issuedAt;
    uint256[] ercs;
    Contract auditedContract;
    bytes32 auditHash;
    string auditUri;
}
```

### Signing

For signing [EIP-712](/EIPs/EIPS/eip-712) will be used. For this the main type is the `AuditSummary` and as the `EIP712Domain` the following definition applies:

```solidity
struct EIP712Domain {
    string name;
    string version;
}

EIP712Domain auditDomain = EIP712Domain(&quot;ERC-7652: Onchain Audit Representation&quot;, &quot;1.0&quot;);
```

The generated signature can then be attached to the `AuditSummary` to generate a new `SignedAuditSummary` object:

```solidity
enum SignatureType {
    SECP256K1,
    BLS,
    ERC1271,
    SECP256R1
}

struct Signature {
    SignatureType type;
    bytes data;
}

struct SignedAuditSummary extends AuditSummary {
    uint256 signedAt;
    Signature auditorSignature;
}
```

## Rationale

The current ERC deliberately does not define the `findings` of an audit. Such a definition would require alignment on the definition of what severities are supported, what data of a finding should be stored onchain vs off-chain, and other similar finding-related attributes that are hard to strictly describe. Given the complexity of this task, we consider it to be outside the scope of this EIP. It is important to note that this ERC proposes that a signed audit summary indicates that a specific contract instance (specified by its `chainId` and `deployment`) has undergone a security audit. 

Furthermore, it indicates that this contract instance correctly implements the listed ERCs. This normally corresponds to the final audit revision for a contract which is then connected to the deployment. As specified above, this ERC MUST NOT be considered an attestation of a contract&apos;s security but rather a methodology via which data relevant to a smart contract can be extracted; evaluation of the quality, coverage, and guarantees of the data is left up to the integrators of the ERC.

### Further Considerations

- `standards` vs `ercs`
    - Limiting the scope to audits related to EVM-based smart contract accounts allows a better definition of parameters.
- `chainId` and `deployment`
    - As a contract&apos;s behavior depends on the blockchain it is deployed in, we have opted to associate a `chainId` as well as `deployment` address per contract that corresponds to an audit
- `contract` vs `contracts`
    - Many audits are related to multiple contracts that make up a protocol. To ensure simplicity in the initial version of this ERC, we chose to only reference one contract per audit summary. If multiple contracts have been audited in the same audit engagement, the same audit summary can be associated with different contract instances. An additional benefit of this is the ability to properly associate contract instances with the `ercs` they support. The main drawback of this approach is that it requires multiple signing passes by the auditors.
- Why [EIP-712](/EIPs/EIPS/eip-712)?
    - [EIP-712](/EIPs/EIPS/eip-712) was chosen as a base due to its tooling compatibility (i.e. for signing)
- How to assign a specific Signing Key to an Auditor?
    - Auditors should publicly share the public part of the signature, which can be done via their website, professional page, and any such social medium
    - As an extension to this ERC it would be possible to build a public repository, however, this falls out-of-scope of the ERC
- Polymorphic Contracts and Proxies
    - This ERC explicitly does **not** mention polymorphic contracts and proxies. These are important to be considered, however, their proper management is delegated to auditors as well as implementors of this ERC

### Future Extensions

- Potential expansion of ERC to accommodate non-EVM chains
- Better support for polymorphic/upgradeable contracts and multi-contract audits
- Management of signing keys for auditors
- Definition of findings of an audit

## Backwards Compatibility

No backward compatibility issues have been identified in relation to current ERC standards.

## Reference Implementation

TBD.

The following features will be implemented in a reference implementation:

- Script to trigger signing based on a JSON representing the audit summary
- Contract to verify signed audit summary

## Security Considerations

### Auditor Key Management

The premise of this ERC relies on proper key management by the auditors who partake in the system. If an auditor&apos;s key is compromised, they may be associated with seemingly audited or ERC-compliant contracts that ultimately could not comply with the standards. As a potential protection measure, the ERC may define an &quot;association&quot; of auditors (f.e. auditing companies) that would permit a secondary key to revoke existing signatures of auditors as a secondary security measure in case of an auditor&apos;s key compromise.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 05 Sep 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7512</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7512</guid>
      </item>
    
      <item>
        <title>Smart NFT - A Component for Intent-Centric</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/nft-bound-modularized-contract/15696</comments>
        
        <description>## Abstract

Smart NFT is the fusion of Smart Contract and NFT. An NFT with the logic of a Smart Contract can be executed, enabling on-chain interactions. Transitioning from an NFT to a Smart NFT is akin to going from a regular landline telephone to a smartphone, opening up broader and more intelligent possibilities for NFTs.

## Motivation

Ethereum introduces smart contracts revolutionized the blockchain and paved the way for the flourishing ecosystem of decentralized applications (dApps). Also, the concept of non-fungible tokens (NFTs) was introduced through [ERC-721](/EIPs/EIPS/eip-721), offering a paradigm for ownership verification.

However, smart contracts still present significant barriers for most users, and NFTs have largely been limited to repetitive explorations within Art, Gaming, and Real-World Assets realm.

The widespread adoption of smart contracts and the functional applications of NFTs still face substantial challenges. Here are some facts that emerges from this contradiction:

1. The strong desire for both intelligence and usability has led users to sacrifice security (sharing their private key with BOTs)
2. For individual developers, the process of turning functionalities into market-ready products is hindered by a lack of sufficient resources.
3. In the context of a &quot;Code is Law&quot; philosophy, there is a lack of on-chain infrastructure for securely transferring ownership of smart contracts/code.

### Usability with Security

IA-NFT acts as a key of a smart contract. With no private key, no risk of private key leakage.

### IA-NFT as Native On-chain Asset

For years, NFT stands for the ownership of a picture, a piece of artwork, a game item, a real-world asset. All these backed assets are in fact not crypto native. IA-NFT verify the ownership of a piece of code or a smart contract.

### Interaction Abstraction for the Intent Abstraction

The on-chain interaction can be abstract to many functional module IA-NFTs and thus make the Interaction process more effective. Users can focus more on their intent rather than how to operate cross different dApps.

## Specification

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.

### Overview

The following section will define the interface specifications for three main objects: Smart-NFT, Smart-Manager, Intent-Proxy, and establish the interaction relationships between three primary roles (developer, verifier, user) and these objects.

![](/EIPs/assets/eip-7513/workflow.png)

### Smart-NFT Interface

Before sending a registration request to Smart-Manager, developers should implement the following two core interfaces in Smart-NFT.

- `execute`: This function **MUST** contain only one parameter of the &quot;bytes&quot; type, which encapsulates the required parameters for a specific Smart-NFT. Additionally, **MUST** call validatePermission during the implementation to determine if this call is legitimate.

- `validatePermission`: This function is used to query the Smart-Manager to determine whether the Smart-NFT has been successfully verified and is callable by the caller.

```solidity
interface ISmartNFT {
  function execute(bytes memory data) external payable returns (bool);

  function validatePermission() external view returns (bool);
}
```

### Smart-Manager Interface

The Smart-Manager interface defines 5 possible states for Smart-NFTs:：

- **UNREGISTERED**: Refers to Smart-NFTs that have not been registered with the Smart-Manager.
- **DEREGISTERED**: Denotes Smart-NFTs that were previously registered but have been removed or deregistered from the Smart-Manager.
- **UNVERIFIED**: Signifies Smart-NFTs that have been registered with the Smart-Manager but have not yet undergone the verification process.
- **VERIFIED**: Represents Smart-NFTs that have been registered with the Smart-Manager and have successfully passed the verification process, indicating they are safe to use.
- **DENIED**: Refers to Smart-NFTs that have been registered but failed the verification process, indicating they should not be used as they may pose security risks.

Smart-Manager should be implemented with the following thress core interfaces.

- `register`: Developers can initiate a registration request for a Smart-NFT through this interface and provide the Smart-NFT&apos;s creation code. Upon successful request, the Smart-NFT **MUST** be marked as _UNVERIFIED_.

- `auditTo`: **Should** only let trusted verifiers use this interface to audit a Smart-NFT to change its status to _Verified_ or _Denied_.

- `isAccessible`: This interface is used to ascertain whether a user can use a specific Smart-NFT. The determination **MUST** involves considering both the ownership of the corresponding tokenId NFT and whether the Smart-NFT has been successfully verified.

- `verificationStatusOf`: The function **MUST** returns the current verification stage of the specified Smart-NFT.

Additionally, the implementation of Smart-Manager **SHOULD** inherit from [ERC-1155](/EIPs/EIPS/eip-1155).

```solidity
interface ISmartManager {
  enum VerificationStatus {
      UNREGISTERED,
      DEREGISTERED,
      UNVERIFIED,
      VERIFIED,
      DENIED
  }

  function register(
      bytes calldata creationCode,
      uint256 totalSupply
  ) external returns (uint256 tokenId, address implAddr);

  function auditTo(uint256 tokenId, bool isValid) external returns (bool);

  function isAccessible(
      address caller,
      uint256 tokenId
  ) external view returns (bool);

  function verificationStatusOf(
      uint256 tokenId
  ) external view returns (VerificationStatus);
}
```

### Intent-Proxy Interface

Intent-Proxy interface defines an Action struct:

| name         | type    | defination                                                              |
| ------------ | ------- | ----------------------------------------------------------------------- |
| tokenId      | uint256 | The nft id of the target Smart-NFT to call                              |
| executeParam | bytes   | The param defined by the target Smart-NFT&apos;s execute encode packed input |

Intent-Proxy should be implemented with `executeIntent`.

- executeIntent: Users can achieve batch use of specified Smart-NFTs by calling this interface and providing an array of desired actions.

```solidity
interface IIntentProxy {
  struct Action {
      uint256 tokenId;
      bytes executeParam;
  }

  function executeIntent(
      Action[] calldata actions
  ) external payable returns (bool);
}
```

## Rationale

### Why using ERC-1155

In the technical implementation aspect, we chose to use [ERC-1155](/EIPs/EIPS/eip-1155) as the main contract for NFTs due to the consideration of increasing the reusability of Smart-NFTs. The reason for this choice is that both [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155) are based on the concept of &quot;token IDs&quot; that point to NFTs. The key difference is that [ERC-1155](/EIPs/EIPS/eip-1155) introduces the concept of &quot;shares,&quot; meaning that having at least one share gives you the right to use the functionality of that Smart-NFT. This concept can be likened to owning multiple smartphones of the same model, where owning several smartphones doesn&apos;t grant you additional features; you can only use the features of each individual device.

Another reason for directly using [ERC-1155](/EIPs/EIPS/eip-1155) instead of defining a new NFT standard is the seamless integration of Smart-NFT transaction behavior into the existing market. This approach benefits both developers and users, as it simplifies the adoption of Smart-NFTs into the current ecosystem.

### Verifier

In this protocol, Verifiers play a crucial role, responsible for auditing and verifying Smart-NFT code. However, decentralized Verifiers face some highly challenging issues, with one of the primary concerns being the specialized expertise required for their role, which is not easily accessible to the general population.

First, let&apos;s clarify the responsibilities of Verifiers, which include assessing the security, functionality, and compliance of smart contract code. This work demands professional programming skills, blockchain technology knowledge, and contract expertise. Verifiers must ensure the absence of vulnerabilities in the code.

Secondly, decentralized Verifiers encounter challenges related to authority and credibility. In a centralized model, we can trust a specific auditing organization or expert to perform this task. However, in a decentralized environment, it becomes difficult to determine the expertise and integrity of Verifiers. This could potentially lead to incorrect audits and might even be abused to undermine overall stability and reliability.

Lastly, achieving decentralized Verifiers also requires addressing coordination and management issues. In a centralized model, the responsibilities of managing and supervising Verifiers are relatively straightforward. However, in a decentralized environment, coordinating the work of various Verifiers and ensuring consistency in their audits across different contracts and code become significant challenges.

### Copyright infringement issue

Code plagiarism has always been a topic of concern, but often, such discussions seem unnecessary. We present two key points: first, overly simple code has no value, making discussions about plagiarism irrelevant. Secondly, when code is complex enough or creative, legal protection can be obtained through open-source licenses (OSI).

The first point is that for overly simple code, plagiarism is almost meaningless. For example, consider a very basic &quot;Hello World&quot; program. Such code is so simple that almost anyone can independently create it. Discussing plagiarism of such code is a waste of time and resources because it lacks sufficient innovation or value and does not require legal protection.

The second point is that when code is complex enough or creative, open-source licenses (OSI) provide legal protection for software developers. Open-source licenses are a way for developers to share their code and specify terms of use. For example, the GNU General Public License (GPL) and the Massachusetts Institute of Technology (MIT) license are common open-source licenses that ensure the original code&apos;s creators can retain their intellectual property rights while allowing others to use and modify the code. This approach protects complex and valuable code while promoting innovation and sharing.

## Backwards Compatibility

This proposal aims to ensure the highest possible compatibility with the existing [ERC-1155](/EIPs/EIPS/eip-1155) protocol. All functionalities present in [ERC-1155](/EIPs/EIPS/eip-1155), including [ERC-165](/EIPs/EIPS/eip-165) detection and Smart-NFT support, are retained. This encompasses compatibility with current NFT trading platforms.

For all Smart-NFTs, this proposla only mandates the provision of the `execute` function. This means that existing proxy contracts need to focus solely on this interface, making integration of Smart-NFTs more straightforward and streamlined.

## Reference Implementation

See `https://github.com/TsengMJ/EIP-7513_Example`

## Security Considerations

### Malicious Validator

All activities involving human intervention inherently carry the risk of malicious behavior. In this protocol, during the verification phase of Smart-NFTs, external validators provide guarantees. However, this structure raises concerns about the possibility of malicious validators intentionally endorsing Malicious Smart-NFTs. To mitigate this risk, it&apos;s necessary to implement stricter validation mechanisms, filtering of validators, punitive measures, or even more stringent consensus standards.

### Unexpected Verification Error

Apart from the issue of Malicious Validators, there&apos;s the possibility of missed detection during the verification phase due to factors like overly complex Smart-NFT implementations or vulnerabilities in the Solidity compiler. This issue can only be addressed by employing additional tools to assist in contract auditing or by implementing multiple validator audits for the auditTo interface to reduce the likelihood of its occurrence.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 06 Sep 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7513</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7513</guid>
      </item>
    
      <item>
        <title>Add Max Epoch Churn Limit</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7514-add-max-epoch-churn-limit/15709</comments>
        
        <description>## Abstract

Update the maximum validator growth rate from an exponential to a linear increase by capping the epoch churn limit.

## Motivation

This proposal aims to mitigate the negative externalities of very high level of total ETH supply staked before a proper solution is implemented. In other words, this proposal accepts the complexities of changing the rewards curve and is meant only to slow down growth. 

In the event that the deposit queue stays 100% full, the share of ETH supply staked will reach 50% by May 2024, 75% by September 2024, and 100% by December 2024. While rewards decrease as the validator set size increases, at 100% of ETH supply staked, yearly consensus rewards alone (excluding MEV/transaction fees) for validators still represent ~1.6% of their stake. This small yield does not necessarily dissuade additional capital staking due to the often much higher and unpredictable yields from MEV. As such, the equilibrium point of the validator set size can be close to its maximum possible. Liquid staking tokens (LSTs) also contribute to this, given stakers can use them as they use unstaked ETH. 

As the levels of ETH staked increase, more strain is put on the consensus layer. A larger number of validators leads to an increase in gossip messages, as well as a growing Beacon state size. Additionally, as the amount of stake grows, it&apos;s unclear how much marginal security benefits come from additional economic weight. 

The Beacon Chain validator reward function was chosen before its launch in 2020. PoS research and reward curve design were performed in a pre-MEV world. Much has changed since then, including the Beacon chain achieving unprecedented success, beyond the original intended targets of stake rate. In light of this, it is worth discussing whether Beacon chain validator rewards should be adjusted to better match today&apos;s reality, potentially to discourage staking past a certain point. 

This EIP does not attempt to do this, but to allow more time for the community to have these discussions. By limiting the epoch churn limit now, the time to reach critical milestones of total ETH supply staked are significantly delayed. This allows more time for research into more comprehensive solutions, and for community consensus around them to emerge.

## Specification

### Constants

| Name | Value |
| ---- | ----- |
| `MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT` | 8 |

### Execution layer

This requires no changes to the Execution Layer.

### Consensus layer

- Add `get_validator_activation_churn_limit` with upper bound `MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT`
- Modify `process_registry_updates` to use bounded activation churn limit

The full specification of the proposed change can be found in [`/specs/deneb/beacon-chain.md`](https://github.com/ethereum/consensus-specs/blob/69d34dc4ee3d026ca437d1b6875b218e8aaf3a5c/specs/deneb/beacon-chain.md).

## Rationale

### `MAX_PER_EPOCH_CHURN_LIMIT` value

Depending on the specific constant selection the churn can _decrease_ at the activation fork epoch. The Beacon chain spec can handle this without issues. During 2023 Q4 (projected Dencun activation) the churn value will range 14-16. The table below compares the projected validator set assuming a continuous full deposit queue.

#### `MAX_PER_EPOCH_CHURN_LIMIT` activation date: Dec 01, 2023

|   Max Churn Limit | 50% ETH staked   | 75% ETH staked   | 100% ETH staked   |
|------------------:|:-----------------|:-----------------|:------------------|
|               inf | May 28, 2024     | Sep 25, 2024     | Dec 18, 2024      |
|                16 | Jul 23, 2024     | Apr 10, 2025     | Dec 26, 2025      |
|                12 | Oct 09, 2024     | Sep 21, 2025     | Sep 04, 2026      |
|                 8 | Mar 15, 2025     | Aug 18, 2026     | Jan 21, 2028      |
|                 6 | Aug 19, 2025     | Jul 14, 2027     | Jun 08, 2029      |
|                 4 | Jun 29, 2026     | May 05, 2029     | Mar 12, 2032      |

#### `MAX_PER_EPOCH_CHURN_LIMIT` activation date: Apr 01, 2024

|   Max Churn Limit | 50% ETH staked   | 75% ETH staked   | 100% ETH staked   |
|------------------:|:-----------------|:-----------------|:------------------|
|               inf | May 28, 2024     | Sep 25, 2024     | Dec 18, 2024      |
|                16 | Jul 01, 2024     | Mar 18, 2025     | Dec 04, 2025      |
|                12 | Aug 01, 2024     | Jul 14, 2025     | Jun 26, 2026      |
|                 8 | Oct 01, 2024     | Mar 05, 2026     | Aug 08, 2027      |
|                 6 | Dec 01, 2024     | Oct 26, 2026     | Sep 20, 2028      |
|                 4 | Apr 02, 2025     | Feb 07, 2028     | Dec 15, 2030      |

Assuming that the earliest the next fork can happen is at the start of 2024 Q3, a value of 8 provides a significant reduction in projected size without causing a big drop in churn at a projected Dencun fork date. A value of 8 prevents reaching a level of 50% ETH staked for at least 1 full year even with a delayed dencun fork.

## Backwards Compatibility

This EIP introduces backward incompatible changes to the block validation rule set on the consensus layer and must be accompanied by a hard fork.

## Test Cases 

Test cases for this EIP can be found in the [`deneb`](https://github.com/ethereum/consensus-specs/tree/2297c09b7e457a13f7b2261a28cb45777be82f83/tests/core/pyspec/eth2spec/test/deneb) test suite of the `consensus-specs` repository. 

## Security Considerations

This EIP breaks the symmetry between the validator entry and exit queues, where the former is bound by `MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT` while the latter isn&apos;t. 

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Thu, 07 Sep 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7514</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7514</guid>
      </item>
    
      <item>
        <title>BLOBBASEFEE instruction</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7516-blobbasefee-opcode/15761</comments>
        
        <description>## Abstract

Add a `BLOBBASEFEE (0x4a)` instruction that returns the value of the blob base-fee of the current block it is executing in. It is the identical to [EIP-3198](/EIPs/EIPS/eip-3198) (`BASEFEE` opcode) except that it returns the blob base-fee as per [EIP-4844](/EIPs/EIPS/eip-4844).

## Motivation

The intended use case would be for contracts to get the value of the blob base-fee. This feature enables blob-data users to programmatically account for the blob gas price, eg:

- Allow rollup contracts to trustlessly account for blob data usage costs.
- Blob gas futures can be implemented based on it which allows for blob users to smooth out data blob costs.

## Specification

Add a `BLOBBASEFEE` instruction with opcode `0x4a`, with gas cost `2`.

| Op   | Input | Output | Cost |
|------|-------|--------|------|
| 0x4a | 0     | 1      | 2    |

`BLOBBASEFEE` returns the result of the `get_blob_gasprice(header) -&gt; int` function as defined in [EIP-4844 §Gas accounting](/EIPs/EIPS/eip-4844#gas-accounting).

## Rationale

### Gas cost

The value of the blob base-fee is needed to process data-blob transactions. That means its value is already available before running the EVM code.
The instruction does not add extra complexity and additional read/write operations, hence the choice of `2` gas cost. This is also identical to [EIP-3198](/EIPs/EIPS/eip-3198) (`BASEFEE` opcode)&apos;s cost as it just makes available data that is in the header.

## Backwards Compatibility

There are no known backward compatibility issues with this instruction.

## Test Cases

### Nominal Case

Assume calling `get_blob_gasprice(header)` (as defined in [EIP-4844 §Gas accounting](/EIPs/EIPS/eip-4844#gas-accounting)) on the current block&apos;s header returns `7 wei`:
`BLOBBASEFEE` should push the value `7` (left padded byte32) to the stack.

Bytecode: `0x4a00` (`BLOBBASEFEE, STOP`)

| Pc | Op          | Cost | Stack | RStack |
|----|-------------|------|-------|--------|
| 0  | BLOBBASEFEE | 2    | []    | []     |
| 1  | STOP        | 0    | [7]   | []     |

Output: 0x
Consumed gas: `2`

### Comprehensive Test Suite

A complete suite of tests can be found [here](https://github.com/ethereum/execution-spec-tests/blob/1983444bbe1a471886ef7c0e82253ffe2a4053e1/tests/cancun/eip7516_blobgasfee/test_blobgasfee_opcode.py).

## Security Considerations

The value of the blob base-fee is not sensitive and is publicly accessible in the block header. There are no known security implications with this instruction.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 11 Sep 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7516</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7516</guid>
      </item>
    
      <item>
        <title>Content Consent for AI/ML Data Mining</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7517-content-consent-for-ai-ml-data-mining/15755</comments>
        
        <description>## Abstract

This EIP proposes a standardized approach to declaring mining preferences for digital media content on the EVM-compatible blockchains. This extends digital media metadata standards like [ERC-7053](/EIPs/EIPS/eip-7053) and NFT metadata standards like [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155), allowing asset creators to specify how their assets are used in data mining, AI training, and machine learning workflows.

## Motivation

As digital assets become increasingly utilized in AI and machine learning workflows, it is critical that the rights and preferences of asset creators and license owners are respected, and the AI/ML creators can check and collect data easily and safely. Similar to robot.txt to websites, content owners and creators are looking for more direct control over how their creativities are used.

This proposal standardizes a method of declaring these preferences. Adding `dataMiningPreference` in the content metadata allows creators to include the information about whether the asset may be used as part of a data mining or AI/ML training workflow. This ensures the original intent of the content is maintained.

For AI-focused applications, this information serves as a guideline, facilitating the ethical and efficient use of content while respecting the creator&apos;s rights and building a sustainable data mining and AI/ML environment.

The introduction of the `dataMiningPreference` property in digital asset metadata covers the considerations including:

* Accessibility: A clear and easily accessible method with human-readibility and machine-readibility for digital asset creators and license owners to express their preferences for how their assets are used in data mining and AI/ML training workflows. The AI/ML creators can check and collect data systematically.
* Adoption: As Coalition for Content Provenance and Authenticity (C2PA) already outlines guidelines for indicating whether an asset may be used in data mining or AI/ML training, it&apos;s crucial that onchain metadata aligns with these standards. This ensures compatibility between in-media metadata and onchain records.

## Specification

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

This EIP introduces a new property, `dataMiningPreference`, to the metadata standards which signify the choices made by the asset creators or license owners regarding the suitability of their asset for inclusion in data mining or AI/ML training workflows. `dataMiningPreference` is an object that can include one or more specific conditions.

* `dataMining`: Allow the asset to be used in data mining for determining &quot;patterns, trends, and correlations&quot;.
* `aiInference`: Allow the asset to be used as input to a trained AI/ML model for inferring a result.
* `aiGenerativeTraining`: Allow the asset to be used as training data for an AI/ML model that could produce derivative assets.
* `aiGenerativeTrainingWithAuthorship`: Same as `aiGenerativeTraining`, but requires that the authorship is disclosed.
* `aiTraining`: Allow the asset to be used as training data for generative and non-generative AI/ML models.
* `aiTrainingWithAuthorship`: Same as `aiTraining`, but requires that the authorship is disclosed.

Each category is defined by a set of permissions that can take on one of three values: `allowed`, `notAllowed`, and `constraint`.

* `allowed` indicates that the asset can be freely used for the specific purpose without any limitations or restrictions.
* `notAllowed` means that the use of the asset for that particular purpose is strictly prohibited.
* `constrained` suggests that the use of the asset is permitted, but with certain conditions or restrictions that must be adhered to.

For instance, the `aiInference` property indicates whether the asset can be used as input for an AI/ML model to derive results. If set to `allowed`, the asset can be utilized without restrictions. If `notAllowed`, the asset is prohibited from AI inference.

If marked as `constrained`, certain conditions, detailed in the license document, must be met. When `constraint` is selected, parties intending to use the media files should respect the rules specified in the license. To avoid discrepancies with the content license, the specifics of these constraints are not detailed within the schema, but the license reference should be included in the content metadata.

### Schema

The JSON schema of `dataMiningPreference` is defined as follows:

```json
{
  &quot;type&quot;: &quot;object&quot;,
  &quot;properties&quot;: {
    &quot;dataMining&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;enum&quot;: [&quot;allowed&quot;, &quot;notAllowed&quot;, &quot;constrained&quot;]
    },
    &quot;aiInference&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;enum&quot;: [&quot;allowed&quot;, &quot;notAllowed&quot;, &quot;constrained&quot;]
    },
    &quot;aiTraining&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;enum&quot;: [&quot;allowed&quot;, &quot;notAllowed&quot;, &quot;constrained&quot;]
    },
    &quot;aiGenerativeTraining&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;enum&quot;: [&quot;allowed&quot;, &quot;notAllowed&quot;, &quot;constrained&quot;]
    },
    &quot;aiTrainingWithAuthorship&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;enum&quot;: [&quot;allowed&quot;, &quot;notAllowed&quot;, &quot;constrained&quot;]
    },
    &quot;aiGenerativeTrainingWithAuthorship&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;enum&quot;: [&quot;allowed&quot;, &quot;notAllowed&quot;, &quot;constrained&quot;]
    }
  },
  &quot;additionalProperties&quot;: true
}
```

### Examples

The mining preference example for not allowing generative AI training:

```json
{
  &quot;dataMiningPreference&quot;: {
    &quot;dataMining&quot;: &quot;allowed&quot;,
    &quot;aiInference&quot;: &quot;allowed&quot;,
    &quot;aiTrainingWithAuthorship&quot;: &quot;allowed&quot;,
    &quot;aiGenerativeTraining&quot;: &quot;notAllowed&quot;
  }
}
```

The mining preference example for only allowing for AI inference:

```json
{
  &quot;dataMiningPreference&quot;: {
    &quot;aiInference&quot;: &quot;allowed&quot;,
    &quot;aiTraining&quot;: &quot;notAllowed&quot;,
    &quot;aiGenerativeTraining&quot;: &quot;notAllowed&quot;
  }
}
```

The mining preference example for allowing generative AI training if mentioning authorship and follow license:

```json
{
  &quot;dataMiningPreference&quot;: {
    &quot;dataMining&quot;: &quot;allowed&quot;,
    &quot;aiInference&quot;: &quot;allowed&quot;,
    &quot;aiTrainingWithAuthorship&quot;: &quot;allowed&quot;,
    &quot;aiGenerativeTrainingWithAuthorship&quot;: &quot;constrained&quot;
  }
}
```

### Example Usage with ERC-721

The following is an example of using the `dataMiningPreference` property in [ERC-721](/EIPs/EIPS/eip-721) NFTs.

We can put the `dataMiningPreference` field in the NFT metadata below. The `license` field is only an example for specifying how to use a constrained condition, and is not defined in this proposal. A NFT has its way to describe its license.

```json
{
  &quot;name&quot;: &quot;The Starry Night, revision&quot;,
  &quot;description&quot;: &quot;Recreation of the oil-on-canvas painting by the Dutch Post-Impressionist painter Vincent van Gogh.&quot;,
  &quot;image&quot;: &quot;ipfs://bafyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&quot;,
  &quot;dataMiningPreference&quot;: {
    &quot;dataMining&quot;: &quot;allowed&quot;,
    &quot;aiInference&quot;: &quot;allowed&quot;,
    &quot;aiTrainingWithAuthorship&quot;: &quot;allowed&quot;,
    &quot;aiGenerativeTrainingWithAuthorship&quot;: &quot;constrained&quot;
  },
  &quot;license&quot;: {
    &quot;name&quot;: &quot;CC-BY-4.0&quot;,
    &quot;document&quot;: &quot;https://creativecommons.org/licenses/by/4.0/legalcode&quot;
  }
}
```

### Example Usage with ERC-7053

The example using the `dataMiningPreference` property in onchain media provenance registration defined in [ERC-7053](/EIPs/EIPS/eip-7053).

Assuming the Decentralized Content Identifier (CID) is `bafyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`. We can put the `dataMiningPreference` field in the Commit data directly. After following up the CID, got the Commit data:

```json
{
  &quot;dataMiningPreference&quot;: {
    &quot;dataMining&quot;: &quot;allowed&quot;,
    &quot;aiInference&quot;: &quot;allowed&quot;,
    &quot;aiTrainingWithAuthorship&quot;: &quot;allowed&quot;,
    &quot;aiGenerativeTrainingWithAuthorship&quot;: &quot;constrained&quot;
  },
  &quot;license&quot;: {
    &quot;name&quot;: &quot;CC-BY-4.0&quot;,
    &quot;document&quot;: &quot;https://creativecommons.org/licenses/by/4.0/legalcode&quot;
  }
}
```

We can also put the `dataMiningPreference` field in any custom metadata whose CID is linked in the Commit data. The `assetTreeCid` field is an example for specifying how to link a custom metadata. After following up the CID, got the Commit data:

```json
{
  /* custom metadata CID */
  &quot;assetTreeCid&quot;: &quot;bafybbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb&quot;
}
```

Following up the `assetTreeCid` which describes the custom properties of the registered asset:

```json
{
  &quot;dataMiningPreference&quot;: {
    &quot;dataMining&quot;: &quot;allowed&quot;,
    &quot;aiInference&quot;: &quot;allowed&quot;,
    &quot;aiTrainingWithAuthorship&quot;: &quot;allowed&quot;,
    &quot;aiGenerativeTrainingWithAuthorship&quot;: &quot;constrained&quot;
  },
  &quot;license&quot;: {
    &quot;name&quot;: &quot;CC-BY-4.0&quot;,
    &quot;document&quot;: &quot;https://creativecommons.org/licenses/by/4.0/legalcode&quot;
  }
}
```

## Rationale

The technical decisions behind this EIP have been carefully considered to address specific challenges and requirements in the digital asset landscape. Here are the clarifications for the rationale behind:

1. Adoption of JSON schema: The use of JSON facilitates ease of integration and interaction, both manually and programmatically, with the metadata.
2. Detailed control with training types: The different categories like `aiGenerativeTraining`, `aiTraining`, and `aiInference` let creators control in detail, considering both ethics and computer resource needs.
3. Authorship options included: Options like `aiGenerativeTrainingWithAuthorship` and `aiTrainingWithAuthorship` make sure creators get credit, addressing ethical and legal issues.
4. Introduction of `constrained` category: The introduction of `constrained` category serves as an intermediary between `allowed` and `notAllowed`. It signals that additional permissions or clarifications may be required, defaulting to `notAllowed` in the absence of such information.
5. C2PA alignment for interoperability: The standard aligns with C2PA guidelines, ensuring seamless mapping between onchain metadata and existing offchain standards.

## Security Considerations

When adopting this EIP, it’s essential to address several security aspects to ensure the safety and integrity of adoption:

* Data Integrity: Since this EIP facilitates the declaration of mining preferences for digital media assets, the integrity of the data should be assured. Any tampering with the `dataMiningPreference` property can lead to unauthorized data mining usage. Blockchain&apos;s immutability will play a significant role here, but additional security layers, such as cryptographic signatures, can further ensure data integrity.
* Verifiable Authenticity: Ensure that the individual or entity setting the `dataMiningPreference` is the legitimate owner or authorized representative of the digital asset. Unauthorized changes to preferences can lead to data misuse. Cross-checking asset provenance and ownership becomes paramount. Services or smart contracts should be implemented to verify the authenticity of assets before trusting the `dataMiningPreference`.
* Data Privacy: Ensure that the process of recording preferences doesn&apos;t inadvertently expose sensitive information about the asset creators or owners. Although the Ethereum blockchain is public, careful consideration is required to ensure no unintended data leakage.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 12 Sep 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7517</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7517</guid>
      </item>
    
      <item>
        <title>Dynamic Compliant Interop Security Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7518-dynamic-compliant-interop-security-token-dycist/15822</comments>
        
        <description>## Abstract

This proposal is a security token standard that extends [ERC-1155](/EIPs/EIPS/eip-1155)  to provide a flexible framework for managing compliant real-asset security tokens. It introduces the concept of partitions, where each `tokenId` represents a distinct partition with its own set of rights and privileges. This makes it suitable for various use cases, particularly semi-fungible asset management. The standard also includes features like token locking, forced transfers for recovery, address freezing, payouts, and dynamic compliance management using off-chain vouchers.

## Motivation

The growing demand for tokenized real-world assets necessitates a token standard that can accommodate the unique requirements of security tokens. Existing standards, while powerful, do not fully address the need for flexible partitioning and comprehensive compliance management.

This standard builds upon [ERC-1155](/EIPs/EIPS/eip-1155) by introducing partitions, allowing for the creation of semi-fungible tokens representing fractional ownership, different share classes, or other distinct units within a single token contract. This flexibility is crucial for tokenizing complex real-world assets like real estate or funds.

Furthermore, it includes features essential for security tokens, such as token locking for vesting or holding periods, forced transfers for recovery in case of lost keys, address freezing for regulatory compliance, efficient payout mechanisms, and dynamic compliance management using off-chain vouchers.

By providing a standardized interface for these features, this proposal aims to facilitate the development of interoperable and compliant security token ecosystems.

### Partition-Based Architecture Benefits

The partition paradigm offers significant flexibility and power in managing security tokens:

1. Dynamic Allocation : Partitions allow for dynamic allocation of tokens between different classes or categories. For example, in a real estate tokenization scenario, an issuer can initially allocate tokens to a Reg D partition for accredited U.S. investors and a &quot;Reg S&quot; partition for non-U.S. investors. As the offering progresses and demand shifts, the issuer can dynamically mint tokens into the appropriate partition based on the investor&apos;s eligibility, ensuring optimal distribution and compliance.
2. Temporary Non-Fungibility : Partitions enable temporary non-fungibility of tokens. In some cases, securities may need to be treated as non-fungible for a certain period, such as tokens of the same underlying asset sold at different offerings. By assigning tokens to specific partitions, issuers can enforce these restrictions and maintain the necessary segregation between them, but merge them at a later point to prevent liquidity fragmentation. Merger occurs by creating a new joint partition, a deploying a merger contract where users can deposit old partitioned tokens to receive new joint partition token.
3. Granular Compliance : Each partition can have its own set of compliance rules and transfer restrictions. This allows for more granular control over token transfers based on the specific characteristics of each partition. For instance, a partition representing a particular share class may have different transfer restrictions or payout rights compared to other partitions.
4. Efficient Asset Management : Partitions streamline the management of complex asset structures. Instead of deploying separate contracts for each share class or asset category, issuers can manage multiple partitions within a single proposed contract, reducing deployment costs and simplifying overall asset management.

### Real World Use Cases

![image](/EIPs/assets/eip-7518/exampleUsecase.svg)

#### Use Case 1: Tokenization of Commercial Real Estate

In this use case, a commercial real estate property with 100 floors is being tokenized using this proposal. Each floor is represented as a unique non-fungible token (NFT) partition, allowing for fractional ownership and separate management of individual floors.

1. Property Representation: The entire commercial property is tokenized using the proposed contract, with each floor being  assigned a unique tokenId representing an NFT partition.

2. Fractional Ownership: Each floor&apos;s NFT partition can be divided into multiple fungible tokens, enabling fractional ownership. For instance, if a floor is divided into 100 tokens, multiple investors can own portions of that floor.

3. Dynamic Pricing: Since each floor is a separate partition, the pricing of tokens within a partition can be adjusted dynamically based on factors such as floor level, amenities, or market demand. This flexibility allows for accurate representation of the varying values of different floors.

4. Transfer of Ownership: The ownership of each floor&apos;s NFT partition can be transferred seamlessly to token holders using the safeTransferFrom function. This enables the seamless transfer of ownership rights for specific floors.

5. Compliance Management: Different compliance rules and transfer restrictions can be applied to each partition (floor) based on regulatory requirements or issuer-defined rules. The canTransfer function can be used to enforce these rules before allowing transfers.

6. Payouts: The payout and batchPayout functions can be used to distribute rental income, dividends, or other payouts to token holders of specific floor partitions efficiently.

By leveraging proposal, this use case demonstrates the ability to tokenize complex real estate assets while maintaining granular control over ownership, pricing, compliance, and payouts for individual units within the property.

#### Use Case 2: Tokenization of Securities with Reg S and Reg D Partitions

In this use case, a company is tokenizing its securities and wants to comply with different regulations for U.S. accredited investors (Reg D) and non-U.S. investors (Reg S).

1. Initial Partitions: The company deploys an proposed standard and creates two partitions: one for Reg D investors (accredited U.S. investors) and another for Reg S investors (non-U.S. investors).

2. Dynamic Allocation: As the offering progresses, the company can dynamically mint tokens into the appropriate partition based on investor eligibility. For example, if a U.S. accredited investor wants to participate, tokens can be minted in the Reg D partition, while tokens for non-U.S. investors are minted in the Reg S partition.

3. Compliance Management: Each partition can have its own set of compliance rules and transfer restrictions. The canTransfer function can be integrated with off-chain compliance services to verify the eligibility of a transfer based on the specific rules for each partition.

4. Temporary Non-Fungibility: During the initial offering period, tokens in the Reg D and Reg S partitions may need to be treated as non-fungible due to different regulatory requirements. However, after the holding period, the company can create a new joint partition and allow token holders to deposit their old partitioned tokens to receive the new joint partition tokens, merging the two classes.

5. Payouts: The payout and batchPayout functions can be used to distribute dividends, interest payments, or other payouts to token holders in each partition based on their respective rights and privileges.

By utilizing the proposal, this use case demonstrates the ability to tokenize securities while maintaining compliance with different regulatory regimes, dynamically allocating tokens based on investor eligibility, and efficiently managing payouts and potential mergers of different share classes.

#### Use Case 3: Force Transfer for AML/KYC/Compliance Violations

In the world of tokenized securities, maintaining compliance with regulatory requirements is of utmost importance. This proposal provides a robust mechanism to handle situations where an investor&apos;s tokens need to be forcibly transferred due to violations of Anti-Money Laundering (AML), Know Your Customer (KYC), or other compliance-related regulations.

Let&apos;s consider the scenario of Alice, an investor who holds tokens in the proposed token compliant security token contract. During the regular compliance checks conducted by the token issuer or a designated compliance service, it is discovered that Alice&apos;s wallet address is associated with suspicious activities related to money laundering or other financial crimes.

In such a situation, the regulatory authorities or the contract administrators may decide to freeze Alice&apos;s account and initiate a forced transfer of her tokens to a designated address controlled by the issuer or a recovery agent. The `forceTransfer` function in this proposal enables this process.

## Specification

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

### Interface

```solidity
pragma solidity ^0.8.0;

interface IERC7518 is IERC1155, IERC165{
  event TokensLocked(address indexed account, uint indexed id, uint256 amount, uint256 releaseTime);

  event TokenUnlocked(address indexed account, uint indexed id);

  event TokensForceTransferred(address indexed from, address indexed to, uint indexed id, uint256 amount);

  event AddressFrozen(address indexed account, bytes data);

  event AddressUnfrozen(address indexed account, bytes data);

  // Emitted when the transferability of tokens with a specific ID is restricted.
  event TransferRestricted(uint indexed id);

  // Emitted when the transferability restriction of tokens with a specific ID is removed.
  event TransferRestrictionRemoved(uint indexed id);

  event PayoutDelivered(address indexed from, address indexed to, uint256 amount);

  /**
  * @dev Retrieves the transferable balance of tokens for the specified account and ID.
  * @param account The address of the account.
  * @param id The token ID.
  * @return The transferable balance of tokens.
  */
  function transferableBalance(address account, uint id) external view returns (uint);

  /**
  * @dev Retrieves the locked balance of tokens for the specified account and ID.
  * @param account The address of the account.
  * @param id The token ID.
  * @return The locked balance of tokens.
  */
  function lockedBalanceOf(address account, uint256 id) external view returns (uint256);

  /**
  * @dev Restricts the transferability of tokens with the specified ID.
  * @param id The token ID.
  * @return A boolean value indicating whether the operation was successful.
  */
  function restrictTransfer(uint id) external returns (bool);

  /**
  * @dev Removes the transferability restriction of tokens with the specified ID.
  * @param id The token ID.
  * @return A boolean value indicating whether the operation was successful.
  */
  function removeRestriction(uint id) external returns (bool);

  /**
  * @notice Transfers `_value` amount of an `_id` from the `_from` address to the `_to` address specified (with safety call).
  * @dev Caller must be approved to manage the tokens being transferred out of the `_from` account (see &quot;Approval&quot; section of the standard).

  * After the above conditions are met, this function MUST check if `_to` is a smart contract (e.g. code size &gt; 0). If so, it MUST call `onERC1155Received` on `_to` and act appropriately (see &quot;Safe Transfer Rules&quot; section of the standard).  
  * @param _from    Source address
  * @param _to      Target address
  * @param _id      ID of the token type
  * @param _value   Transfer amount
  * @param _data    Additional data with no specified format, MUST be sent unaltered in call to `onERC1155Received` on `_to`
  */
  function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) override external;

  /**
  * @dev Checks if a transfer is allowed.
  * @param from The address to transfer tokens from.
  * @param to The address to transfer tokens to.
  * @param id The token ID.
  * @param amount The amount of tokens to transfer.
  * @param data Additional data related to the transfer.
  * @return status A boolean value indicating whether the transfer is allowed.
  */
  function canTransfer(address from, address to, uint id, uint amount, bytes calldata data) external view returns (bool status);

  /**
  * @dev lock token till a particular block time.
  * @param account The address of the account for which tokens will be locked.
  * @param id The token ID.
  * @param amount The amount of tokens to be locked for the account.
  * @param releaseTime The timestamp indicating when the locked tokens can be released.
  * @return bool Returns true if the tokens are successfully locked, otherwise false.
  */
  function lockTokens(address account, uint id, uint256 amount, uint256 releaseTime) external returns (bool);

  /**
  * @dev Unlocks tokens that have crossed the release time for a specific account and id.
  * @param account The address of the account to unlock tokens for.
  * @param id The token ID.
  */
  function unlockToken(address account, uint256 id) external;

  /**
  * @dev Force transfer in cases like recovery of tokens.
  * @param from The address to transfer tokens from.
  * @param to The address to transfer tokens to.
  * @param id The token ID.
  * @param amount The amount of tokens to transfer.
  * @param data Additional data related to the transfer.
  * @return A boolean value indicating whether the operation was successful.
  */
  function forceTransfer(address from, address to, uint256 id, uint256 amount, bytes memory data) external returns (bool);

  /**
  * @dev Freezes specified address.
  * @param account The address to be frozen.
  * @param data Additional data related to the freeze operation.
  * @return A boolean value indicating whether the operation was successful.
  */
  function freezeAddress(address account, bytes calldata data) external returns (bool);

  /**
  * @dev Unfreezes specified address.
  * @param account The address to be unfrozen.
  * @param data Additional data related to the unfreeze operation.
  * @return A boolean value indicating whether the operation was successful.
  */
  function unFreeze(address account, bytes memory data) external returns (bool);

  /**
  * @dev Sends payout to single address with corresponding amounts.
  * @param to address to send the payouts to.
  * @param amount amount representing the payouts to be sent.
  * @return A boolean indicating whether the batch payouts were successful.
  */* 
  function payout(address calldata to, uint256 calldata amount) public returns (bool);

  /**
  * @dev Sends batch payouts to multiple addresses with corresponding amounts.
  * @param to An array of addresses to send the payouts to.
  * @param amount An array of amounts representing the payouts to be sent.
  * @return A boolean indicating whether the batch payouts were successful.
  */
  function batchPayout(address[] calldata to, uint256[] calldata amount) public returns (bool);
}
```

### Methods for token

### `transferableBalance`

Retrieves the transferable balance of tokens for the specified account and ID.

```solidity
function transferableBalance(address account,uint id) external view returns (uint)
```

- MUST calculate and return the transferable balance of tokens for the specified account and ID (i.e. current) `balanceOf(account, id) - lockedBalanceOf(account, id)`.

### `lockedBalanceOf`

Retrieves the locked balance of tokens for the specified account and ID.

```solidity
function lockedBalanceOf(address account,uint256 id) external view returns (uint256)
```

- MUST retrieve and return the locked balance of tokens for the specified `account` and `id`.

### `restrictTransfer`

Restricts the transferability of tokens with the specified ID.

```solidity
function restrictTransfer(uint id) external returns (bool)
```

- MUST restrict the transferability of tokens with the specified `id`.
- SHOULD emit `TransferRestricted`.

### `removeRestriction`

Removes the transferability restriction of tokens with the specified ID.

```solidity
function removeRestriction(uint id) external returns (bool)
```

- MUST remove the transferability restriction of tokens with the specified `id`. MUST revert if `id` was not previously restricted.
- SHOULD emit `TransferRestrictionRemoved`.

### `safeTransferFrom`

```solidity
function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) override external;
```

- MUST revert if `_to` is the zero address.
- MUST revert if balance of holder for token `_id` is lower than the `_value` sent.
- MUST revert on any other error.
- MUST emit the `TransferSingle` event to reflect the balance change (see &quot;Safe Transfer Rules&quot; section of the standard).
- MUST call `canTransfer` function to check if the transfer can proceed

### `canTransfer`

Determine transferring a specified amount of a token from one address to another.

```solidity
function canTransfer(address from,address to,uint id,uint amount,bytes calldata data) external view returns (bool status);
```

- Accurately determine whether the transfer of tokens is allowed.
- MUST validate `to` and `from` are not frozen address.
- MUST validate `id` of the transfer should not be restricted
- MUST check if `amount` is a transferable balance.
- MAY call external contract to verify the transfer.
- SHOULD NOT modify any state or perform any side effects.

### `lockTokens`

Locks a specified amount of tokens from an account for a specified duration.

```solidity
function lockTokens(address account,uint id,uint256 amount,uint256 releaseTime) external returns (bool);
```

- MUST enforce time-based restrictions on the transfer or use of tokens.
- MUST revert if balance of holder is less than amount.
- SHOULD use proper access control measures to ensure that only authorized entities can lock tokens.
- MUST perform input validation prevent potential vulnerabilities and unauthorized locking of tokens.
- SHOULD record release time securely and ensure that locked tokens are only released after the designated time has passed.
- SHOULD emit `TokensLocked`.

### `unlockToken`

Unlocks tokens that have crossed the release time for a specific account and id.

```solidity
function unlockToken(address account,uint256 id) external;
```

- MUST unlock the tokens for the specified `account` address and `id`.
- MUST unlock all the token which has release time &lt;= `block.timestamp`
- SHOULD revert if no token are unlocked to save gas.
- SHOULD emit `TokenUnlocked`.

### `forceTransfer`

Force transfer in cases like recovery of tokens

```solidity
function forceTransfer(address from,address to,uint256 id,uint256 amount,bytes memory data) external returns (bool);
```

- MUST bypass normal transfer restrictions and authorization checks.
- MUST revert if the `from` address is not Frozen.
- MUST revert if `to` address is Frozen.
- MUST ensure that only authorized entities have the capability to call this function.
- Additional data related to the freeze operation.
- SHOULD emit `TokensForceTransferred`.

### `freeze`

Freezes specified address. The Freeze function takes in the `account address` to be frozen and additional data, and returns a `boolean` value indicating whether the operation was successful.

```solidity
function freezeAddress(address account,bytes data) external returns (bool);
```

- MUST prevent `account` to transfer and payout.
- SHOULD implement appropriate access control measures to ensure that only authorized addresses can be unfrozen.
- SHOULD emit `AddressFrozen`.

### `unFreeze`

The Unfreeze function takes in the `account address` to be unfrozen and additional data, and returns a `boolean` value indicating whether the operation was successful.

```solidity
function unFreeze(address account,bytes memory data) external returns (bool);
```

- MUST unfreeze the specified `account`
- SHOULD implement appropriate access control measures to ensure that only authorized addresses can be unfrozen.
- SHOULD emit `AddressUnfrozen`.

### `payout`

Send payouts to single address, receiver will be receiving a specific amount of tokens.

```solidity
function payout(address calldata to,uint256 calldata amount) public returns (bool)
```

- MUST revert if `to` address is frozen address.
- SHOULD have sufficient balance to transfer token from issuer address.
- SHOULD emit `PayoutDelivered`.

### `batchPayout`

Send payouts to multiple addresses at once, with each address receiving a specific amount of tokens. It can be used for various purposes such as distributing rewards, dividends, or interest payment.

```solidity
function batchPayout(address[] calldata to,uint256[] calldata amount) public returns (bool)
```

- MUST revert if `to` address is frozen address.
- SHOULD have sufficient balance to transfer token from issuer address.
- SHOULD emit `PayoutDelivered`.

### Interoperability

This proposal facilitates interoperability with non-fungible and fungible tokens through a token wrapping method. The process involves two key components: the token contracts representing the original and the proposed token contract for the wrapped version. Users seeking to wrap their tokens interact with the wrapping contract, which securely locks their original tokens and mints an equivalent amount of the proposed tokens to their address. Conversely, unwrapping is achieved by calling the contract&apos;s withdraw function, resulting in the burning of the proposed tokens and the release of the corresponding original tokens. Events are emitted for transparency, and robust security measures are implemented to safeguard user assets and address any potential vulnerabilities in the contract code. With this design, this proposal ensures the seamless conversion and compatibility with fungible and non-fungible tokens, promoting greater utility and usability across the Ethereum ecosystem.

### Interface for Interoperability

```solidity
interface IERC1155Wrapper is IERC7518 {

/**
@dev Emitted when a new wrapped token address is added to the set.
@param wrappedTokenAddress The address of the wrapped token that was added.
*/
event WrappedTokenAddressSet(address wrappedTokenAddress);

/**
@dev Emitted when tokens are wrapped.
@param The ERC-1155 token ID of the wrapped tokens.
@param amount The amount of tokens that were wrapped.
*/
event TokensWrapped(uint indexed id, uint256 amount);

/**
@dev Emitted when tokens are unwrapped.
@param wrappedTokenId Is the ERC-1155 token ID of the wrapped tokens.
@param amount The amount of tokens that were unwrapped.
*/
event TokensUnwrapped(uint indexed wrappedTokenId, uint256 amount);

/**
* @dev Sets the wrapped token address and logic for deciding partitions.
* @param wrappedTokenAddress The address of the wrapped token contract.
* @return A boolean value indicating whether the operation was successful.
*/
function setWrappedToken(address token) external returns (bool);

/**
* @dev Wraps the specified amount of tokens by depositing the original tokens and receiving new standard tokens.
* @param amount The amount of tokens to wrap.
* @param data Additional data for partition.
* @return A boolean value indicating whether the operation was successful.
*/
function wrapToken(uint256 amount, bytes calldata data) external returns (bool);

/**
* @notice Wraps a specified amount of tokens from a given partition into the main balance.
* @dev This function allows users to convert tokens from a specific partition back to the main balance,making them fungible with tokens from other partitions.
* @param partitionId The unique identifier of the partition from which tokens will be wrapped.
* @param id The unique identifier of the token.
* @param amount The amount of tokens to be wrapped from the specified partition.
* @param data Additional data that may be used to handle the wrap process (optional).
* @return success A boolean indicating whether the wrapping operation was successful or not.
*/

function wrapTokenFromPartition(bytes32 partitionId, uint256 id, uint256 amount, bytes calldata data) external returns (bool);
/**
* @dev Unwraps the specified amount of wrapped tokens by depositing the current tokens and receiving the original tokens.
* @param wrappedTokenId internal partition id.
* @param amount The amount of wrapped tokens to unwrap.
* @param data Additional data for partition.
* @return A boolean value indicating whether the operation was successful.
*/
function unwrapToken(uint256 wrappedTokenId, uint256 amount, bytes calldata data) external returns (bool);

/**
* @dev Retrieves the balance of wrapped tokens for the specified account and ID.
* @param account The address of the account.
* @param id The token ID.
* @param data Additional data for partition.
* @return The balance of wrapped tokens.
*/
function wrappedBalanceOf(address account, uint256 id, bytes calldata data) external view returns (uint256);

/**
* @dev Retrieves the balance of original tokens for the specified account and ID.
* @param account The address of the account.
* @param id The token ID.
* @param data Additional data for partition.
* @return The balance of original tokens.
*/
function originalBalanceOf(address account, uint256 id, bytes calldata data) external view returns (uint256);
}
```

### Methods for Interoperability

### `setWrappedTokenAddress`

```solidity
function setWrappedTokenAddress(address token) external returns (bool);
```

- `token` address could be any security token standard i.e [ERC-3643](/EIPs/EIPS/eip-3643).

### `wrapToken`

```solidity
function wrapToken(uint256 amount, bytes calldata data) external returns (bool);
```

- MUST lock token in an on-chain vault type smart contract.
- MUST mint an equivalent amount of the proposed token.
- MUST verify mapping of [ERC-1155](/EIPs/EIPS/eip-1155)  `id` with the corresponding [ERC-20](/EIPs/EIPS/eip-20)  compatible security token.

### `wrapTokenFromPartition`

```solidity
function wrapTokenFromPartition(bytes32 partitionId, uint256 id, uint256 amount, bytes calldata data) external returns (bool);
```

- MUST lock the token amount from source standard and mint an equivalent amount of the proposed token.
- SHOULD lock token in smart contract to achieve one to one mapping with the investor.
- MUST verify mapping of `id` with the corresponding partially fungible security token `partitionId`.

### `unwrapToken`

```solidity
function unwrapToken(uint256 wrappedTokenId, uint256 amount, bytes calldata data) external returns (bool);
```

- MUST burn the proposed token and release the original token.
- MUST verify that the token is not subject to any of the proposal&apos;s locking functionality.

### Partition Management

The proposal leverages the `tokenId` feature of [ERC-1155](/EIPs/EIPS/eip-1155) to represent distinct partitions within a token contract. Each `tokenId` corresponds to a unique partition with its own set of rights, privileges, and compliance rules. This enables the creation of semi-fungible tokens representing fractional ownership, different share classes, or other granular units.

### Partition as the Fundamental Unit

- Each partition is created by minting tokens under a unique `tokenId` value.  
- All tokens with the same `tokenId` are **fungible within that partition** but **non-fungible across partitions**.  
- The issuer can represent different classes, jurisdictions, or series by minting tokens under different `tokenId`s.

### Compliance Management

![image](/EIPs/assets/eip-7518/sequentialDiagram.svg)

This standard includes functions for managing token transfers in accordance with regulatory requirements and issuer-defined rules. The `canTransfer` function checks whether a transfer is allowed based on factors such as token restrictions, frozen addresses, transferable balances, and token locking.

To facilitate dynamic compliance management, the standard uses a voucher-based pattern. An authorized entity (e.g., the issuer or a designated compliance service) generates a signed off-chain voucher that may encapsulate results from on-chain rule evaluation, oracle responses, or other checks. The `canTransfer` verifies vouchers signature, expiry, and binding of `from`, `to`, `id`, and `amount` together with contract state to determine the eligibility of a transfer.

Here&apos;s an example of how off-chain vouchers can be used with the proposal:

1. The token issuer defines a set of compliance rules and requirements for token transfers.
2. When a user initiates a transfer, they submit a request to a designated compliance service with the necessary details (sender, recipient, amount, etc.).
3. The compliance service evaluates the transfer request against the predefined rules and requirements, considering factors such as investor eligibility, transfer restrictions, and regulatory compliance.
4. If the transfer is deemed compliant, the compliance service generates a signed voucher containing the relevant details and returns it to the user.
5. The user includes the signed voucher as an additional parameter when calling the `safeTransferFrom` function on the proposed contract.
6. The `canTransfer` function verifies the authenticity and validity of the voucher by checking the signature and ensuring that the voucher details match the transfer parameters.
7. If the voucher is valid and the transfer meets all other requirements, the transfer is allowed to proceed.

Implementations MAY accept a cryptographically signed compliance voucher in the `data` argument of `canTransfer`, and state changing transfer functions defined in this standard, for example `safeTransferFrom`. Voucher schema and policy content are application defined. Implementations MAY combine on chain rules, oracle responses, and off chain verification for the voucher.

### Token Recovery

In case of lost or compromised wallets, the proposal includes a `forceTransfer` function that allows authorized entities (e.g., the issuer or a designated recovery agent) to transfer tokens from one address to another. This function bypasses the usual transfer restrictions and can be used as a recovery mechanism.

### Payout Management

Provides functions for efficient payout distribution to token holders. The `payout` function allows sending payouts to a single address, while `batchPayout` enables sending payouts to multiple addresses in a single transaction. These functions streamline the process of distributing dividends, interest, or other payments to token holders.

## Rationale

### Enhancing Compliance Management

The `canTransfer` function facilitates compliance checks during token transfers, offering adaptability through diverse implementation methods such as on-chain storage, oracle utilization, or any off-chain methodologies. This versatility ensures seamless integration with existing compliance frameworks, particularly in enforcing regulatory standards like KYC/AML. Additionally, functionalities like `freezeAddress`, `restrictTransfer`, `lockToken` and `forceTransfer` empower entities to regulate token movements based on specified conditions or regulatory requirements. Complementing these, the `unlockToken` function enhances transparency and accountability by facilitating the release of tokens post-compliance actions.

### Fractionalization

Fractionalization in this standard is realized natively through [ERC-1155](/EIPs/EIPS/eip-1155) balances. For a given partition identified by tokenId, each unit of amount represents a fungible fraction of that partition’s underlying security. Issuers mint and burn units to manage supply. Transfers use `safeTransferFrom` and `safeBatchTransferFrom`, and must pass canTransfer. Locks and freezes reduce the transferable portion of balances, and `forceTransfer` operates proportionally on units. Partitions can be merged by issuing a new tokenId and allowing holders to deposit old partitions for one-to-one or proportional conversion, and can be split by minting new tokenIds with defined conversion rules. All compliance rules and restrictions apply identically to every fractional unit in a partition.

### Interoperability with other standard

This standard builds directly on [ERC-1155](/EIPs/EIPS/eip-1155), which already models fractional supply, batching, and balance-based accounting with broad ecosystem support. [ERC-3525](/EIPs/EIPS/eip-3525) was carefully evaluated but intentionally not adopted as a base. Its slot-and-value abstraction overlaps almost exactly with the partition and `amount` semantics defined here, yet inherits [ERC-721](/EIPs/EIPS/eip-721)’s single-token overhead and per-position statefulness, which are inefficient for large scale issuance and compliance checks. Implementers who require slot-style compatibility may optionally expose [ERC-3525](/EIPs/EIPS/eip-3525) through [ERC-165](/EIPs/EIPS/eip-165) by mapping `slot` to partition and `value` to `amount`. [ERC-6909](/EIPs/EIPS/eip-6909), while a minimal multi-token variant, omits partition metadata and compliance hooks and is therefore unsuitable for regulated assets. [ERC-7518](/EIPs/EIPS/eip-7518) extends this lineage by representing partitions as [ERC-1155](/EIPs/EIPS/eip-1155) `tokenId`s, enabling dynamic minting, merging, and voucher based dynamic compliance that can evolve without redeployment. Overall, [ERC-7518](/EIPs/EIPS/eip-7518) uses [ERC-1155](/EIPs/EIPS/eip-1155) as its canonical substrate because it balances composability, efficiency, and regulatory flexibility, turning fractionalization into a compliance-preserving primitive rather than an auxiliary layer.

The functions `wrapToken` and `wrapTokenFromPartition` are essential for simplifying conversions within the token system. `wrapToken` is specifically designed for wrapping ERC-20-like tokens to this protocol, on the other hand, `wrapTokenFromPartition` is used when we want to convert tokens from non-fungible tokens or any multi-standard token into proposed protocol. It allows for more specialized conversions, ensuring tokens from different standards can work together smoothly.

The `unwrapToken` function is used to reverse the process of wrapping tokens. When tokens are wrapped, they&apos;re usually locked or held in a special way to ensure they&apos;re used correctly. users can unlock or release these tokens, returning them to their original standard, essentially, frees up tokens that were previously locked, giving users more control over their assets in the ecosystem.

### Payment distribution

The `payout` function enables direct payments to individual token holders for one-off or event-triggered distributions, facilitating targeted disbursements. Meanwhile, the `batchPayout` function processes multiple payments in a single transaction, optimizing efficiency for larger-scale or regular payouts on the blockchain

## Backwards Compatibility

The proposal is fully compatible with [ERC-1155](/EIPs/EIPS/eip-1155) , and any [ERC-1155](/EIPs/EIPS/eip-1155) compliant wallet or marketplace can interact with the proposal&apos;s tokens. The additional functions introduced by this proposal do not conflict with the [ERC-1155](/EIPs/EIPS/eip-1155) interface, ensuring seamless integration with existing ecosystem tools and infrastructure.

## Security Considerations

1. Access Control: The proposal includes functions that can significantly impact token transfers and balances, such as `forceTransfer`, `freezeAddress`, and `lockTokens`. It is crucial to implement proper access control mechanisms, such as role-based permissions, to ensure that only authorized entities can execute these functions.
2. Parameter Validation: Functions like `safeTransferFrom`, `lockTokens`, and `forceTransfer` should validate input parameters to prevent unauthorized or unintended actions. This includes checking for valid addresses, sufficient balances, and appropriate permissions.
3. Reentrancy Protection: The contract should implement reentrancy guards to prevent potential vulnerabilities arising from external calls, especially in functions that transfer tokens or update balances.
4. Overflow/Underflow Protection: The contract should use safe math libraries or built-in overflow protection to prevent integer overflow and underflow vulnerabilities.
5. Payout Security: The `payout` and `batchPayout` functions should ensure that only authorized entities can initiate payouts and that the total payout amount does not exceed the available balance. Proper access control and input validation are essential to prevent unauthorized or fraudulent payouts.
6. Off-Chain Voucher Security: When using off-chain vouchers for dynamic compliance management, it is crucial to ensure the security and integrity of the voucher generation process. The compliance service responsible for generating vouchers should have robust security measures in place to prevent unauthorized voucher creation or tampering. Additionally, the proposed contract should thoroughly validate the authenticity and validity of vouchers before allowing transfers to proceed.
7. Operational considerations for unfreezing: Unfreezing restores an account&apos;s ability to transfer and receive payouts. Implementers and operators should evaluate applicable regulatory and contractual obligations before unfreezing an address.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).</description>
        <pubDate>Thu, 14 Sep 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7518</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7518</guid>
      </item>
    
      <item>
        <title>Atomic Storage Operations SCREDIT and SDEBIT</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7519-atomic-storage-operations-scredit-and-sdebit/15818</comments>
        
        <description>## Abstract

Two new opcodes that atomically mutate smart contract storage are proposed:
SCREDIT, which increments a storage slot by a specified value, and SDEBIT, which
decrements a storage slot by a specified value. Overflow and underflow errors
are enforced, reverting when an unsigned 256-bit integer would overflow or
underflow.

## Motivation

There has been a large amount of energy around parallel EVMs across multiple
chains, however there is a lack of parallel primitives within the EVM to support
any model other than optimistic concurrency control (OCC). By adding concurrent
increment and decrement operations more advanced parallel environments can be
introduced in Layer 2 networks.

This also provides the opportunity to serve the principal use case of increment
and decrement: token balances. We can introduce failures on overflow and
underflow conditions and provide an operation that is also useful outside of
parallel use cases.

## Specification

Two operations to atomically increment and decrement a storage will be
introduced
at `0xTBD`. Each operation takes two stack arguments and has no immediate
arguments. Gas schedule will be the same as SSTORE.

| Mnemonic  | Op        | Input | Output |
|-----------|-----------|-------|--------|
| `SCREDIT` | `0xTBD`   | `2`   | `0`    |
| `SDEBIT`  | `0xTBD+1` | `2`   | `0`    |

### SCREDIT

`SCREDIT: slot, value`

#### Description

Adds `value` to the value stored in contract storage `slot.`  If an overflow
would occur the operation halts exceptionally.

#### Gas Charging

Gas charging is identical to SSTORE. including interactions with the warm
storage slot list. Any future modifications to the SSTORE gas charges will also
apply to SCREDIT.

#### Execution

*Not valid python, not suitable for EELS yet*

```
slot = evm_stack.pop()
value = evm_stack.pop()

storage_value = read_contract_storage(slot)
storage_value = storage_value + value

if storage_value &gt;= 2**256 :
  raise Exception(&quot;scredit overflow&quot;)
 
write_contract_storage(storage_value)
```

### SDEBIT

`SDEBIT: slot, value`

#### Description

Subtracts `value` to the value stored in contract storage `slot.`  If an
underflow would occur the operation halts exceptionally.

#### Gas Charging

Gas charging is identical to SSTORE, including interactions with the warm
storage slot list. Any future modifications to the SSTORE gas charges will also
apply to SDEBIT.

#### Execution

*Not valid python, not suitable for EELS yet*

```
slot = evm_stack.pop()
value = evm_stack.pop()

storage_value = read_contract_storage(slot)
storage_value = storage_value - value

if storage_value &lt; 0 :
  raise Exception(&quot;sdebit underflow&quot;)
 
write_contract_storage(storage_value)
```

## Rationale

The primary consideration when choosing between alternatives is that the primary
intended audiences is token contracts and other asset-tracking contracts
combined with a desire to ship the minimum necessary changes to enable that use
case. General concurrency controls is not a goal of this EIP.

### Enforcing Overflow Semantics

When allowing for out-of-order execution there needs to be mechanism to handle
any possible order of execution. OCC handles this by validating pre- and
post-conditions, and re-evaluating the transactions if those invariants did not
hold. This technique breaks down around writing to balances and counters.

Increment/decrement with rollover checking allows for simple handling of
balances and counters while allowing for functional read support ensuring that
sufficient balance or count exists without depending on the exact values. This
allows for evaluation models where the only post-condition checked is to
validate that the storage slots could handle all possible re-ordering of
transactions.

### Gas Schedule

The decision to cost the operations at the exact same value as SSTORE is partly
for ease of implementation and partly as an incentive to compilers and
developers.

These semantics could be implemented in the EVM today, but it would also include
a SLOAD, DUP, LT, JUMPI and REVERT instructions. The EVM, however, can do these
operations much more efficiently than via opcodes. First, each SSTORE always
incurs a slot load in order to apply [EIP-2200](/EIPs/EIPS/eip-2200) gas calculation
rules. This load is essential if there is no paired SLOAD. Math libraries for
256-bit numbers can all easily be made sensitive to overflow and underflow, if
they are not already present. Conditional logic handling is also much faster in
the operation logic as most of the overhead would be operation parsing and stack
management when interpreted.

The net impact of the most relevant operations to the most expensive
evaluation (an ADD and LT operation, above the cost of a plain SSTORE) would be
4 gas, or 0.2% of the current cost of a SSTORE. Finally, database access costs
dominate the real cost of the operation. A 0.2% overhead may disappear in I/O
stalls.

Keeping the cost the same makes implementations of gas charging vert simple.

### Storage Slots Only

This most important use case for this EIP asset balances and not general
concurrency controls. Hence, only enabling credit and debit operations on
storage slots (which persist across transactions). Parallel execution within a
transaction and more generic tools like locks and semaphores have very limited
utility within this scope. The lack of in-transaction parallel execution also
precludes the use of such primitives against transient storage (as defined in
[EIP-1153](/EIPs/EIPS/eip-1153)).

### Opcode Instead of System Contract

One alternative, particularly viable for Layer 2 chains, would be to implement
SCREDIT and SDEBIT as system contracts. The primary objection to system
contracts for other operations is the gas cost overhead of constructing a call.
Because a SSTORE is always greater than the cost of a call it would be possible
to build in a discount. However, there is no such accommodation that can be made
for the code size needed to invoke such a call.

## Backwards Compatibility

These opcodes are not simple replacements for SLOAD-(ADD|SUB)-SSTORE sequence
because there is an overflow/underflow check

There is no EVM functionality removed by this proposal.

## Test Cases

Test for overflow and non-overflow for the following values and values before
and after:

1, 2^8, 2^16, 2^32, 2^64, 2^128 2^255, 2^256-1.

## Reference Implementation

/# TBD

## Security Considerations

The use of revert to handle over/underflow represents a new halt condition that
auditors will need to consider when examining reentrancy concerns.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 16 Sep 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7519</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7519</guid>
      </item>
    
      <item>
        <title>General Intents for Smart Contract Wallets</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7521-generalized-intents-for-smart-contract-wallets/15840</comments>
        
        <description>## Abstract

A generalized intent specification entry point contract which enables support for a multitude of intent standards as they evolve over time. Instead of smart contract wallets having to constantly upgrade to provide support for new intent standards as they pop up, a single entry point contract is trusted to handle signature verification which then passes off the low level intent data handling and defining to other contracts specified by users at intent sign time. These signed messages, called a `UserIntent`, are gossipped around any host of mempool strategies for MEV searchers to look through and combine with their own `UserIntent` into an object called an `IntentSolution`. MEV searchers then package up an `IntentSolution` object they build into a transaction making a `handleIntents` call to the special contract entry point contract. This transaction then goes through the typical MEV channels to eventually be included in a block.

## Motivation

See also [&quot;ERC-4337: Account Abstraction via Entry Point Contract specification&quot;](/EIPs/EIPS/eip-4337) and the links therein for historical work and motivation.

This proposal uses the same entry point contract idea to enable a single interface which smart contract wallets can support now to unlock future-proof access to an evolving intent landscape. It seeks to achieve the following goals:

- **Achieve the key goal of enabling intents for users**: allow users to use smart contract wallets containing arbitrary verification logic to specify intent execution as described and handled by various other intent standard contracts.
- **Decentralization**
  - Allow any MEV searcher to participate in the process of solving signed intents
  - Allow any developer to add their own intent standard definitions for users to opt-in to at sign time
- **Be forward thinking for future intent standard compatibility**: Define an intent standard interface that gives future intent standard defining contracts access to as much information about the current `handleIntents` execution context as possible.
- **Keep gas costs down to a minimum**: Include key intent handling logic, like intent segment execution order, into the entry point contract itself in order to optimize gas efficiency for the most common use cases.
- **Enable good user experience**
  - Avoid the need for smart contract wallet upgrades when a user wants to use a newly developed intent standard.
  - Enable complex intent composition that only needs a single signature.

## Specification

Users package up intents they want their wallet to participate in, in an ABI-encoded struct called a `UserIntent`:

| Field        | Type      | Description                                                   |
| ------------ | --------- | ------------------------------------------------------------- |
| `sender`     | `address` | The wallet making the intent                                  |
| `segments`   | `bytes[]` | Data defined by multiple segments of varying intent standards |
| `signature`  | `bytes`   | Data passed into the wallet during the verification step      |

The `segments` parameter is an array of arbitrary bytes whose use is defined by an intent standard. Each item in this array is referred to as an **intent segment**. The first 32 bytes of each segment is used to specify the **intent standard ID** to which the segment data belongs. Users send `UserIntent` objects to any mempool strategy that works best for the intent standards being used. A specialized class of MEV searchers called **solvers** look for these intents and ways that they can be combined with other intents (including their own) to create an ABI-encoded struct called an `IntentSolution`:

| Field       | Type           | Description                                   |
| ----------- | -------------- | --------------------------------------------- |
| `timestamp` | `uint256`      | The time at which intents should be evaluated |
| `intents`   | `UserIntent[]` | List of intents to execute                    |
| `order`     | `uint256[]`    | Order of execution for the included intents   |

The solver then creates a **solution transaction**, which packages up an `IntentSolution` object into a single `handleIntents` call to a pre-published global **entry point contract**.

The core interface of the entry point contract is as follows:

```solidity
function handleIntents
    (IntentSolution calldata solution)
    external;

function validateIntent
    (UserIntent calldata intent)
    external;

function registerIntentStandard
    (IIntentStandard intentStandard)
    external returns (bytes32);

function verifyExecutingIntentSegmentForStandard
    (IIntentStandard intentStandard)
    external view returns (bool);
```

The core interface required for an intent standard to have is:

```solidity
function validateIntentSegment
    (bytes calldata segmentData)
    external pure;

function executeIntentSegment
    (IntentSolution calldata solution, uint256 executionIndex, uint256 segmentIndex, bytes calldata context)
    external returns (bytes memory);
```

The core interface required for a wallet to have is:

```solidity
function validateUserIntent
    (UserIntent calldata intent, bytes32 intentHash)
    external;

function generalizedIntentDelegateCall
    (bytes memory data)
    external;
```

### Required entry point contract functionality

The entry point&apos;s `handleIntents` function must perform the following steps. It must make two loops, the **verification loop** and the **execution loop**.

In the verification loop, the `handleIntents` call must perform the following steps for each `UserIntent`:

- **Validate `timestamp` value on the `IntentSolution`** by making sure it is within an acceptable range of `block.timestamp` or some time before it.
- **Call `validateUserIntent` on the wallet**, passing in the `UserIntent` and the hash of the intent. The wallet should verify the intent&apos;s signature. If any `validateUserIntent` call fails, `handleIntents` must skip execution of at least that intent, and may revert entirely.

In the execution loop, the `handleIntents` call must perform the following steps for all **segments** on the `segments` bytes array parameter on each `UserIntent`:

- **Call `executeIntentSegment` on the intent standard**, specified by the first 32 bytes of the `segments` (the intent standard ID). This call passes in the entire `IntentSolution` as well as the current `executionIndex` (the number of times this function has already been called for any standard or intent before this), `segmentIndex` (index in the `segments` array to execute for) and `context` data. The `executeIntentSegment` function returns arbitrary bytes per intent which must be remembered and passed into the next `executeIntentSegment` call for the same intent.

It&apos;s up to the intent standard to choose how to parse the `segments` bytes and utilize the `context` data blob that persists across intent execution.

The order of execution for `UserIntent` segments in the `segments` array always follows the same order defined on the `segments` parameter. However, the order of execution for segments between `UserIntent` objects can be specified by the `order` parameter of the `IntentSolution` object. For example, an `order` array of `[1,1,0,1]` would result in the second intent being executed twice (segments 1 and 2 on intent 2), then the first intent would be executed (segment 1 on intent 1), followed by the second intent being executed a third time (segment 3 on intent 2). If no ordering is specified in the solution, or all segments have not been processed for all intents after getting to the end of the order array, a default ordering will be used. This default ordering loops from the first intent to the last as many times as necessary until all intents have had all their segments executed. If the ordering calls for an intent to be executed after it&apos;s already been executed for all its segments, then the `executeIntentSegment` call is simply skipped and execution across all intents continues.

Before accepting a `UserIntent`, solvers must use an RPC method to locally call the `validateIntent` function of the entry point, which verifies that the signature and data formatting is correct; see the [Intent validation section below](#solver-intent-validation) for details.

#### Registering new entry point intent standards

The entry point&apos;s `registerIntentStandard` function must allow for permissionless registration of new intent standard contracts. During the registration process, the entry point gives it a **standard ID** which is unique to the intent standard contract, entry point contract and chain ID.

### Intent standard behavior executing an intent

The intent standard&apos;s `executeIntentSegment` function is given access to a wide set of data, including the entire `IntentSolution` in order to allow it to implement any kind of logic that may be seen as useful in the future. Each intent standard contract is expected to parse the `UserIntent` objects `segments` parameter and use that to validate any constraints or perform any actions relevant to the standard. Intent standards can also take advantage of the `context` data it can return at the end of the `executeIntentSegment` function. This data is kept by the entry point and passed in as a parameter to the `executeIntentSegment` function the next time it is called for an intent. This gives intent standards access to a persistent data store as other intents are executed in between others. One use case for this is an intent standard that is looking for a change in state during intent execution (like releasing tokens and expecting to be given other tokens).

### Smart contract wallet behavior executing an intent

The entry point does not expect anything from the smart contract wallets after validation and during intent execution. However, intent standards may wish for the smart contract wallet to perform some action during execution. The smart contract wallet `generalizedIntentDelegateCall` function must perform a delegate call with the given calldata at the calling intent standard. In order for the wallet to trust making the delegate call it must call the `verifyExecutingIntentSegmentForStandard` function on the entry point contract to verify both of the following:

- The `msg.sender` for `generalizedIntentDelegateCall` on the wallet is the intent standard contract that the entry point is currently calling `executeIntentSegment` on.
- The smart contract wallet is the `sender` on the `UserIntent` that the entry point is currently calling `executeIntentSegment` for.

### Smart contract wallet behavior validating an intent

The entry point calls `validateUserIntent` for each intent on the smart contract wallet specified in the `sender` field of each `UserIntent`. This function provides the entire `UserIntent` object as well as the precomputed hash of the intent. The smart contract wallet is then expected to analyze this data to ensure it was actually sent from the specified `sender`. If the intent is not valid, the smart contract wallet should throw an error in the `validateUserIntent` function. It should be noted that although `validateUserIntent` is not restricted as `view`, updates to state for things like nonce management, should be done in an individual segment on the intent itself. This allows for maximum customization in the way users define their intents while enshrining only the minimum verification within the entry point needed to ensure intents cannot be forged.

### Solver intent validation

To validate a `UserIntent`, the solver makes a view call to `validateIntent` on the entry point. This function checks that the signature passes validation and that the segments on the intent are properly formatted. If the call reverts with any error, the solver should reject the `UserIntent`.

### Simulation

Solvers are expected to handle simulation in typical MEV workflows. This most likely means dry running their solutions at the current block height to determine the outcome is as expected. Successful solutions can then be submitted as a bundle to block builders to be included in the next block.

### Extensions

The entry point contract may enable additional functionality to reduce gas costs for common scenarios.

#### Extension: embedded intent standards

We extend the entry point logic to include the logic of several identified  **common intent standards**. These standards are registered with their own standard ID at entry point contract creation time. The functions `validateUserIntent` and `executeIntentSegment` for these standards are included as part of the entry point contracts code in order to reduce external calls and save gas.

#### Extension: handle multi

We add the additional function `handleIntentsMulti(IntentSolution[] calldata solutions)` to the entry point contract. This allows multiple solutions to be executed in a single transaction to enable gas saving in intents that touch similar areas of storage.

#### Extension: nonce management

We add the functions `getNonce(address sender, uint256 key)` and `setNonce(uint256 key, uint256 nonce)` to the entry point contract. These functions allow nonce data to be stored in the entry point contracts storage. Nonces are stored at a per sender level and are available to be read by anyone. However, the entry point contract enforces that nonces can only be set for a user by a currently executing intent standard and only for the `sender` on the intent currently being executed.

#### Extension: data blobs

We enable the entry point contract to skip the validation of `UserIntent` objects with either a `sender` field of `address(0)` or an empty `segments` field (rather than fail validation). Similarly, they are skipped during execution. The `segments` field or `sender` field is then free to be treated as a way to inject any arbitrary data into intent execution. This data could be useful in solving an intent that has an intent standard which requires some secret to be known and proven to it, or an intent whose behavior can change according to what other intents are around it. For example, an intent standard that signals a smart contract wallet to transfer some tokens to the sender of the intent that is next in line for the execution process.

## Rationale

The main challenge with a generalized intent standard is being able to adapt to the evolving world of intents. Users need to have a way to express their intents in a seamless way without having to make constant updates to their smart contract wallets.

In this proposal, we expect wallets to have a `validateUserIntent` function that takes as input a `UserIntent`, and verifies the signature. A trusted entry point contract uses this function to validate the signature and forwards the intent handling logic to the intent standard contracts specified in the first 32 bytes of each segment in the `segments` array field on the `UserIntent`. The wallet is then expected to have a `generalizedIntentDelegateCall` function that allows it to perform intent related actions from the intent standard contracts, using the `verifyExecutingIntentSegmentForStandard` function on the entry point for security.

The entry point based approach allows for a clean separation between verification and intent execution, and prevents wallets from having to constantly update to support the latest intent standard composition that a user wants to use. The alternative would involve developers of new intent standards having to convince wallet software developers to support their new intent standards. This proposal moves the core definition of an intent into the hands of users at signing time.

### Solvers

Solvers facilitate the fulfillment of a user&apos;s intent in search of their own MEV. They also act as the transaction originator for executing intents on-chain, including having to front any gas fees, removing that burden from the typical user.

Solvers will rely on gossiping networks and solution algorithms that are to be determined by the nature of the intents themselves and the individual intent standards being used.

### Entry point upgrading

Wallets are encouraged to be DELEGATECALL forwarding contracts for gas efficiency and to allow wallet upgradability. The wallet code is expected to hard-code the entry point into their code for gas efficiency. If a new entry point is introduced, whether to add new functionality, improve gas efficiency, or fix a critical security bug, users can self-call to replace their wallet&apos;s code address with a new code address containing code that points to a new entry point. During an upgrade process, it&apos;s expected that intent standard contracts will also have to be re-registered to the new entry point.

Another option would be for wallets to not hard-code the entry point and instead validate signatures from any entry point. When a signature is validated, the wallet can note the entry point in transient storage and then use that to ensure security when accepting `generalizedIntentDelegateCall` function calls. There is an example of this in the [reference implementation](#reference-implementation).

#### Intent standard upgrading

Because intent standards are not hardcoded into the wallet, users do not need to perform any operation to use any newly registered intent standards. A user can simply sign an intent with the new intent standard.

### Signature aggregation

Signature aggregation should be handled by the smart contract wallets directly during the signature validation process. This removes complexity from the entry point and allows developers to be creative with solutions. The [reference implementation](#reference-implementation) includes an example for how to accomplish this through the use of a wallet trusted aggregation contract which uses transient storage to report back to individual wallets that an intent was already validated via an aggregated signature earlier in the transaction call stack.

## Backwards Compatibility

This ERC does not change the consensus layer, so there are no backwards compatibility issues for Ethereum as a whole. There is a little more difficulty when trying to integrate with existing smart contract wallets. If the wallet already has support for [ERC-4337](/EIPs/EIPS/eip-4337), then implementing a `validateUserIntent` function should be very similar to the `validateUserOp` function, but would require an upgrade by the user.

## Reference Implementation

See `https://github.com/essential-contributions/ERC7521`

## Security Considerations

The entry point contract will need to be very heavily audited and formally verified, because it will serve as a central trust point for _all_ [ERC-7521](/EIPs/EIPS/eip-7521) supporting wallets. In total, this architecture reduces auditing and formal verification load for the ecosystem, because the amount of work that individual _wallets_ have to do becomes much smaller (they need only verify the `validateUserIntent` function and its &quot;check signature&quot; logic) and gate any calls to `generalizedIntentDelegateCall` by checking with the entry point using the `verifyExecutingIntentSegmentForStandard` function. The concentrated security risk in the entry point contract, however, needs to be verified to be very robust since it is so highly concentrated.

Verification would need to cover one primary claim (not including claims needed to protect solvers, and intent standard related infrastructure):

- **Safety against arbitrary hijacking**: The entry point only returns true for `verifyExecutingIntentSegmentForStandard` when it has successfully validated the signature of the `UserIntent` and is currently in the middle of calling `executeIntentSegment` on the `standard` specified in the `segments` field of a `UserIntent` which also has the same `sender` as the `msg.sender` wallet calling the function.

Additional heavy auditing and formal verification will also need to be done for any intent standard contracts a user decides to interact with.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 19 Sep 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7521</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7521</guid>
      </item>
    
      <item>
        <title>OIDC ZK Verifier for AA Account</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7522-oidc-zk-verifier/15862</comments>
        
        <description>## Abstract

Account Abstraction facilitates new use cases for smart accounts, empowering users with the ability to tailor authentication and recovery mechanisms to their specific needs. To unlock the potential for more convenient verification methods such as social login, we inevitably need to connect smart accounts and OpenID Connect(OIDC), given its status as the most widely accepted authentication protocol. In this EIP, we proposed a [ERC-4337](/EIPs/EIPS/eip-4337) compatible OIDC ZK verifier. Users can link their ERC-4337 accounts with OIDC identities and authorize an OIDC verifier to validate user operations by verifying the linked OIDC identity on-chain.

## Motivation

Connecting OIDC identity and smart accounts has been a very interesting but challenging problem. Verifying an OIDC issued IdToken is simple. IdToken are usually in the form of JWT and for common JWTs, they usually consist of three parts, a header section, a claim section and a signature section. The user claimed identity shall be included in the claim section and the signature section is usually an RSA signature of a well-known public key from the issuer against the hash of the combination of the header and claim section.

The most common way of tackling the issue is by utilizing Multi-Party Computation(MPC). However, the limitation of the MPC solution is obvious. First, it relies on a third-party service to sign and aggregate the signature which introduces centralization risk such as single point of failure and vendor lock-in. Second, it leads to privacy concerns, since the separation between the users&apos; Web2 identity to their Web3 address can not be cryptographically guaranteed.

All these problems could be solved by ZK verification. Privacy will be guaranteed as the connection between Web2 identity and the Web3 account will be hidden. The ZK proof generation process is completely decentralized since it can be done on the client side without involving any third-party service. ZK proofs aggregation has also proven to be viable and paves the way for cheaper verification cost at scale.

In this EIP, we propose a new model to apply OIDC ZK verification to ERC-4337 account validation. We also define a minimal set of functions of the verifier as well as the input of the ZK proof to unify the interface for different ZK implementations. Now one can link its ERC-4337 account with an OIDC identity and use the OpenID ZK verifier to validate user operations. Due to the high cost of ZK verification, one common use case is to use the verifier as the guardian to recover the account owner if the owner key is lost or stolen. One may set multiple OIDC identities(e.g. Google Account, Facebook Account) as guardians to minimize the centralization risk introduced by the identity provider.

## Specification

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.

### Definitions

**Identity Provider(IDP)**: The service to authenticate users and provide signed ID token

**User**: The client to authenticate users and generate the ZK proof

**ZK Aggregrator**: The offchain service to aggregate ZK proof from multiple users

**OpenIdZkVerifier**: The on-chain contract to verify the ZK proof

The **EntryPoint**, **Aggregator** and **AA Account** are defined at ERC-4337.

### Example Flow

![The example workflow](/EIPs/assets/eip-7522/workflow.png)

### Interface

```
struct OpenIdZkProofPublicInput {
    bytes32 jwtHeaderAndPayloadHash;
    bytes32 userIdHash;
    uint256 expirationTimestamp;
    bytes jwtSignature;
}

interface IOpenIdZkVerifier {
    // @notice get verification key of the open id authenticator
    function getVerificationKeyOfIdp() external view returns(bytes memory);
 
    // @notice get id hash of account
    function getIdHash(address account) external view returns(bytes32);

    // @notice the function verifies the proof and given a user op
    // @params op: the user operation defined by ERC-4337
    //         input: the zk proof input with JWT info to prove
    //         proof: the generated ZK proof for input and op
    function verify(
        UserOp memory op,
        OpenIdZkProofPublicInput input,
        bytes memory proof
    ) external;

    // @notice the function verifies the aggregated proof give a list of user ops
    // @params ops: a list of user operations defined by ERC-4337
    //         inputs: a list of zk proof input with JWT info to prove
    //         aggregatedProof: the aggregated ZK proof for inputs and ops
    function verifyAggregated(
        UserOp[] memory ops,
        OpenIdZkProofPublicInput[] memory inputs,
        bytes memory aggregatedProof
    ) external;
}
```

## Rationale

To verify identity ownership on-chain, **IOpenIdVerifier** needs at least three pieces of information:

1. the user ID to identify the user in the IDP. The **getIdHash** function returns the hash of the user id given smart account address. There may be multiple smart accounts linked to the same user ID.

2. the public key of the key pair used by identity provider to sign ID token. It is provided by the **getVerificationKeyOfIdp** function.

3. the ZK proof to verify the OIDC identity. The verification is done by the **verify** function. Besides the proof, the function takes two extra params: the user operation to execute and the public input to prove. The **verifyAggregated** is similar to the **verify** function but with a list of input and ops as parameters

The **OpenIdZkProofPublicInput** struct must contain the following fields:

| Field      | Description |
| ----------- | ----------- |
| jwtHeaderAndPayloadHash | the hash of the JWT header plus payload |
| userIdHash   | the hash of the user id, the user id should present as value of one claim |
| expirationTimestamp | the expiration time of the JWT, which could be value of &quot;exp&quot; claim |
| jwtSignature | the signature of the JWT |

We didn&apos;t include the verification key and the user operation hash in the struct because we assume the public key could be provided by **getVerificationKeyOfIdp** function and the user operation hash could be calculated from the raw user operation passed in.

## Security Considerations

The proof must verify the *expirationTimestamp* to prevent replay attacks. **expirationTimestamp** should be incremental and could be the **exp** field in JWT payload. The proof must verify the user operation to prevent front running attacks. The proof must verify the **userIdHash**. The verifier must verify that the sender from each user operation is linked to the user ID hash via the **getIdHash** function.

## Copyright

Copyright and related rights waived via CC0.
</description>
        <pubDate>Wed, 20 Sep 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7522</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7522</guid>
      </item>
    
      <item>
        <title>Empty accounts deprecation</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7523-empty-accounts-deprecation/15870</comments>
        
        <description>## Abstract

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.

## Motivation

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 `14049881` (transaction `0xf955834bfa097458a9cf6b719705a443d32e7f43f20b9b0294098c205b4bcc3d`) 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.

Despite empty accounts no longer existing, they still impose a legacy of technical debt. [EIP-161](/EIPs/EIPS/eip-161) imposes complicated rules that require a client to delete an empty account when it is &quot;touched&quot;. As the Ethereum specification continues to evolve new edgecases of the &quot;touch&quot; 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.

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.

## Specification

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

An empty account is an account with has **no code** and **zero nonce** and **zero balance**. This is the same as the definition in [EIP-161](/EIPs/EIPS/eip-161).

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.

Rather than performing a scan of the state, clients MAY assume the following chains have no post-merge empty accounts:

1. The Mainnet chain whose merge block has hash `0x56a9bb0302da44b8c0b3df540781424684c3af04d0b7a38d72842b762076a664`.

2. Any chain which satisfies all of the following:

    - has no empty accounts in the genesis.

    - had a post Spurious Dragon fork at genesis.
  
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.

## Rationale

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.

Alternative approaches include:

- Using an earlier cutoff point, such as block `14049881`.

- Identifying a wider range of edge case behaviour that never happened.

These approaches were rejected as being unnecessarily complicated.

## Backwards Compatibility

As EIP does not change any behaviour that can occur outside the testsuite, it has no backwards compatibility consequences.

## Security Considerations

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.

Any networks artificially created with empty accounts will cause problems with tooling and clients.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>PLUME Signature in Wallets</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7524-plume-signature-in-wallets/15902</comments>
        
        <description>## Abstract

ZK-SNARKs have enabled ideation for new identity applications based on anonymous proof-of-ownership. One of the primary technologies that would enable the jump from existing apps to systems that require anonymous uniqueness is the development of verifiably deterministic signatures. Because Ethereum is based on ECDSA, there is no way right now for someone to verify that a signature is generated deterministically, even with ‘deterministic’ ECDSA signatures: a ZK-SNARK proof would need someone’s private key to do so, and some hardware wallets do not even allow viewing of a private key. Broadly, we don’t want to export/copy-paste the private key into a SNARK to be an intended user behavior, and most hardware wallets will not be able to run SNARK arithmetization inside a secure enclave for existing schemes (and nor do we want to standardize an entire proof system inside a wallet right now when they emerge and evolve almost every year). Thus we are left to select a new algorithm that offers us verifiable, deterministic nullifiers that can be SNARKed outside the enclave.

One specific example of how such a signature can lead to unique pseudonymity is that we prove it was generated correctly in a ZK-SNARK that only reveals publicly the hash(signature), and the SNARK additionally proves some property the public key has (i.e. is in some anonymity set, has executed some set of actions on chain, etc). This proof is the only thing that is ever seen by other people, and so the hash(signature) can be used as a “nullifier”: a public commitment to a specific anonymous account, to forbid actions like double spending, or allow a consistent identity between anonymous actions. We aim to standardize a new verifiably deterministic signature algorithm that both uniquely identifies the keypair, and keeps the account identity secret, where verification does not require a secret key. The specific signature function we found (and will discuss for the rest of the post) is $hash(message, public\ key) ^ {secret\ key}$.

## Motivation

- Existing ZK applications have the advantage that there is no uniqueness constraint on the provers: that is, allowing the same wallet to prove itself as a member more than once is intended. However, many applications require a maximum of one action per user, especially protocols that desire Sybil resistance. Such protocols are not natively possible on Ethereum right now without mapping each address into an opt-in mapping that also maps a user’s private key to a new system, which adds complexity, loses atomicity, and does not benefit from the rich on-chain history of Ethereum accounts.
- Specific applications that require this tech include:
    - zk voting, where each account in some set has one vote
    - pseudonymously claiming an airdrop like Stealthdrop
    - moderating a pseudonymous forum, where people can prove that they are the same identity elsewhere in the forum
    - zk proof of solvency — if you want two exchanges to prove they know a set of private keys that hold some balance, you need a way to ensure that two exchanges aren’t both claiming the same address, while keeping it private
    
As such, a deterministic value based on the Ethereum account’s ECDSA keypair is a necessary component of ensuring one action per user and enables all these applications on Ethereum.
    

## Specification

We propose a new signature standard that offers the following properties, to be implemented for standard ECDSA keys within wallets:

1. It produces signatures that contain a deterministic component and a nondeterministic component. The deterministic component may be used as a *nullifier*.
2. Signers can use existing secpk256k1 keypairs, such as those in hardware wallets that support Ethereum accounts. As a consequence, secret keys can remain in secure enclaves if there is a generator point multiplication API into the enclave (which Ledger for instance has).

### Parameters

This scheme uses the secp256k1 curve, defined in [Standards for Efficient
Cryptography 2 (SEC 2) v2](../assets/eip-7524/sec2-v2.pdf), page 9.

We use the following notation to refer to the parameters of this curve:

- $g$: the base point (also called the generator) of the curve.
- $p$: the order of the curve.
- $F_p$: the finite field whose order is $p$.

Note we use exponential notation to denote elliptic curve scalar multiplications.

### Public key encoding functions

### SEC1

This scheme uses the SEC1 elliptic curve point encoding scheme defined in [Standards for Efficient
Cryptography 1 (SEC 1) v2](../assets/eip-7524/sec1-v2.pdf). Point compression is used. We use the notation $\mathsf{sec1}(pk)$ to denote the compressed encoding of secp256k1 curve point $pk$ as a bytestring of length 33.

### Hash functions

**SHA256**

This scheme uses the SHA256 hash function defined in [IETF RFC 4634](https://www.rfc-editor.org/rfc/rfc4634).

In this document, we use the notation $\mathsf{sha256}(a_1,.. a_n)$ to denote the sha256 digest of the concatenation of $n$ values $a_1, ..., a_n$. The digest should then be interpreted as a big-endian value in the secp256k1 scalar field.

### Hash-to-curve

We use the notation $\mathsf{htc}([a_1, ..., a_n])$ to denote the elliptic curve point which is the result of the [IETF RFC 9380](https://www.rfc-editor.org/rfc/rfc9380) `secp256k1_XMD:SHA-256_SSWU_RO_` in Appendix J.8.1. This hash-to-curve algorithm operates over the concatenation of $n$ values $a_1, ..., a_n$.

### Key generation

A *keypair* comprises of $(sk, pk)$, defined as such:

- $sk$: The user&apos;s secret key, which is a cryptographically secure random scalar in the field $F_p$.
- $pk$: The user&apos;s public key, defined as $g^{sk}$, which is a point on the secp256k1 curve.

### Signature generation

This scheme builds upon the Chaum-Pedersen signature scheme [^1]. Given a 32-byte message $m$ and a keypair $(sk, pk)$, a  user may generate a signature as such:

[^1]:
    ```csl-json
    {
      &quot;DOI&quot;: &quot;10.1007/3-540-48071-4_7&quot;,
      &quot;URL&quot;: &quot;https://link.springer.com/content/pdf/10.1007/3-540-48071-4_7.pdf&quot;,
      &quot;publisher-place&quot;: &quot;Berlin, Heidelberg&quot;,
      &quot;author&quot;: [
        {
          &quot;given&quot;: &quot;David&quot;,
          &quot;family&quot;: &quot;Chaum&quot;
        },
        {
          &quot;given&quot;: &quot;Torben Pryds&quot;,
          &quot;family&quot;: &quot;Pedersen&quot;
        }
      ],
      &quot;container-title&quot;: &quot;Advances in Cryptology — CRYPTO&apos; 92&quot;,
      &quot;editor&quot;: [
        {
          &quot;given&quot;: &quot;Ernest F.&quot;,
          &quot;family&quot;: &quot;Brickell&quot;
        }
      ],
      &quot;type&quot;: &quot;paper-conference&quot;,
      &quot;id&quot;: &quot;10.1007/3-540-48071-4_7&quot;,
      &quot;citation-label&quot;: &quot;10.1007/3-540-48071-4_7&quot;,
      &quot;ISBN&quot;: &quot;978-3-540-48071-6&quot;,
      &quot;issued&quot;: {
        &quot;date-parts&quot;: [
          [
            1993
          ]
        ]
      },
      &quot;page&quot;: &quot;89-105&quot;,
      &quot;publisher&quot;: &quot;Springer Berlin Heidelberg&quot;,
      &quot;title&quot;: &quot;Wallet Databases with Observers&quot;
    }
    ```

1. Pick a random $r$ from $F_p$.
2. Compute $h = \mathsf{htc}([m, \mathsf{sec1}(pk)])$.
3. Compute $z = h ^ r$.
4. Compute the nullifier $\mathsf{nul} = h^{sk}$.
5. Compute $c = \mathsf{sha256}([g, pk, h, \mathsf{nul}, g^r, z]])$.
6. Compute $s = r + sk \cdot c$.

The signature is $(z, s, g^r, c, \mathsf{nul})$.

The length of the input to $\mathsf{htc}$ is always 65 bytes.

Note that in this scheme, we compute $h$ as the hash of the message and $pk$, not the message and $r$. This is to make our scheme deterministic.

### Signature verification (non-ZK)

&gt; 📝 **Note:** This section is non-normative.
&gt;
&gt; Non-ZK signature verification is not part of this proposal but relevant for an intuitive understanding of the ZK signature verification.

In a situation where the verifier knows $g$, $m$, the signer&apos;s public key $pk$, and the signature $(z, s, g^r, c, \mathsf{nul})$, they may perform the following checks to determine if the signature is valid:

1. Compute $h = \mathsf{htc}([m, \mathsf{sec1}(pk)])$.
2. Compute $c&apos; = \mathsf{sha256}([g, pk, h, \mathsf{nul}, g^r, z])$.
3. Reject if any of the following is false:
a. $g^{s} \cdot pk^{-c} \stackrel{?}{=} g^r$
b. $h^s \cdot \mathsf{nul}^{-c} \stackrel{?}{=} z$
c. $c \stackrel{?}{=} c&apos;$
4. Accept if all of the above is true.

Now we move onto the ZK signature verification specs.

### Version 1: Verifier Optimized

In a situation where there is a verifier who must *not* know the signer&apos;s $pk$, but the signer must nevertheless prove that they know $sk$ corresponding to the signature given $m$, a zero-knowledge proof is required.

The following verification function may be described via a circuit as part of a non-interactive zero-knowledge proving system, such as Groth16. To create a proof, the prover supplies the following inputs:

**Public**: $\mathsf{nul}$, $c$
**Private**: $pk$, $r$, $s$, $z$, $g^r$, $hash[m, g^sk]$ (included to save constraints)

The circuit performs the following computations:

1. Compute $h = \mathsf{htc}([m, \mathsf{sec1}(pk)])$.
2. Compute $pk = g^{sk}$.
3. Compute $c&apos; = \mathsf{sha256}([g, pk, h, \mathsf{nul}, g^r, z]])$.
4. Compute $g^{s} \cdot pk^{-c}$.
5. Compute $g^r$.
6. Compute $h^s \cdot \mathsf{nul}^{-c}$.

It also establishes the following constraints:

- $g^{s} \cdot pk^{-c} = g^r$
- $h^s \cdot \mathsf{nul}^{-c} = z$
- $c = c&apos;$

### Version 2: Prover Optimized

Currently, SHA-256 hashing operations are particularly expensive with zk proofs in the browser. In the context of PLUME, the computation of $c$ is a bottleneck for efficient proof times, so one modification suggested by the Poseidon team was to move this hash computation outside the circuit, into the verifier.

To do this, we make $z$ and $g^r$ public signals in the circuit and update the definition of $c$ to $c = \text{sha256}([\text{nul}, g^r, z])$. The updated protocol is as follows.

**Public:** $\mathsf{nul}$, $c$, $g^r$, $z$
**Private:** $pk$, $r$, $s$, $hash[m, g^sk]$

The circuit performs the following computations:

1. Compute $h = \mathsf{htc}([m, \mathsf{sec1}(pk)])$.
2. Compute $pk = g^{sk}$.
3. Compute $g^{s} \cdot pk^{-c}$.
4. Compute $g^r$.
5. Compute $h^s \cdot \mathsf{nul}^{-c}$.

The circuit establishes the following constraints:

- $g^{s} \cdot pk^{-c} = g^r$
- $h^s \cdot \mathsf{nul}^{-c} = z$

In addition to verifying the zk-SNARK, the PLUME verifier performs the following check.

$c == \text{hash}(\text{nul}, g^r, h^r)$

Due to SHA-256 being a native precompile on Ethereum, this operation will still be efficient for smart contract verifiers.

### Version 3:

There may be a more efficient V3 in the future, perhaps via removing indifferentiability from hash_to_curve.

## Rationale

We will define a few specific properties we are looking for in a candidate algorithm, then define a few other intuitive algorithms and explain why they don’t actually work.

- Noninteractivity
    - The importance of noninteractivity in ZK ID systems is that it enables a large anonymity set from the start, making it resistant to sybil attacks and spam, which would be possible if there was an interactive phase. This allows for new use cases such as ZK airdrops.
    - Noninteractivity enables the full set of eligible users to be part of the anonymity set, without requiring any interaction. This is possible if the zk proof can verify the set membership in the Merkle tree, the message via the signature, and the unique nullifier. Interactive nullifiers, such as tornado.cash&apos;s, require updating the anonymity set Merkle tree with each new user,
- Uniqueness
    - If we want to forbid actions like double spending or double claiming, we need them to be verifiably unique per account.
    - For example: Because ECDSA signatures are nondeterministic, signatures don’t suffice; we need a new deterministic function, verifiable with only the public key. We want the nullifier to be non-interactive, to uniquely identify the keypair yet keep the account identity secret.
    - The key insight is that such nullifiers can be used as a public commitment to a specific anonymous account to provide us with a uniqueness guarantee.
- Deterministic
    - We want each account to only generate one such signature, and generate it exactly the same over time into the future.
- Verifiable without a secret key
    - In cases where signatures are nondeterministic (like ECDSA) the signature alone is not sufficient for verification.
    - We want a new, deterministic function verifiable only with the public key
    - We don’t want users copy-pasting secret keys anywhere, and we need to choose a function such that the enclave calculation is simple enough for hardware wallets.
    - Because the nullifier is non-interactive, we are able to uniquely identify the key pair without revealing the account identity.

We based the final design to be as simple as possible, and based off of BLS signatures, Chaum-Pederson EQDL, and Goh-Jarecki’s EDL paper, but to work on secp256k1.

## Security Considerations

There are formal proofs of this specific algorithm’s cryptography in the PLUME paper [^2]. The theory has been published, and implementations have had one internal round of audit, but they have not end-to-end been formally verified or audited yet, although empirically they correctly conform to the spec laid out.

[^2]:
    ```csl-json
    {
        &quot;DOI&quot;: &quot;1721.1/147434&quot;,
        &quot;author&quot;: [
        {
            &quot;given&quot;: &quot;Aayush&quot;,
            &quot;family&quot;: &quot;Gupta&quot;
        },
        {
            &quot;given&quot;: &quot;Kobi&quot;,
            &quot;family&quot;: &quot;Gurkan&quot;
        }
        ],
        &quot;type&quot;: &quot;book&quot;,
        &quot;id&quot;: &quot;Gupta_Gurkan_2022_PLUME&quot;,
        &quot;citation-label&quot;: &quot;Gupta_Gurkan_2022_PLUME&quot;,
        &quot;issued&quot;: {
        &quot;date-parts&quot;: [
            [
            2022,
            9
            ]
        ]
        },
        &quot;keyword&quot;: &quot;zero knowledge,zk proof,nullifier,ddh-vrf,vrf,pseudonymity,ethereum,bitcoin,ecdsa,secp256k1,plume,signature&quot;,
        &quot;note&quot;: &quot;Cryptology ePrint Archive, Paper 2022/1255&quot;,
        &quot;title&quot;: &quot;PLUME: An ECDSA Nullifier Scheme for Unique Pseudonymity within Zero Knowledge Proofs&quot;,
        &quot;URL&quot;: &quot;https://eprint.iacr.org/2022/1255&quot;
    }
    ```

**The Interactivity-Quantum Secrecy Tradeoff**

Note that in the far future, once quantum computers can break ECDSA keypair security, most Ethereum keypairs will be broken, but migration to a quantum-resistant keypair in advance will keep active funds safe. Specifically, people can merely sign messages committing to new quantum-resistant keypairs (or just higher-bit keypairs on similar algorithms), and the canonical chain can fork to make such keypairs valid. ZK-SNARKs become forgeable, but there is still forward-secrecy for zk proofs. In the best case, the chain should be able to continue without a hitch.

However, if people rely on any type of deterministic nullifier like our construction, their anonymity is immediately broken: someone can merely derive the secret keys for the whole anonymity set, calculate all the nullifiers, and see which ones match. This problem will exist for any deterministic nullifier algorithm on ECDSA, since revealing the secret key reveals the only source of “randomness” that guarantees anonymity in a deterministic protocol.

If people want to keep post-quantum secrecy of data, they have to give up at least one of our properties: the easiest one is probably non-interactivity. For example, for the zero-knowledge airdrop, each account in the anonymity set publicly signs a commitment to a new semaphore id commitment (effectively address pk publishes $hash[randomness\ |\ external\ nullifier\ |\ pk]$). Then to claim, they reveal their external nullifier and ZK prove it came from one of the semaphore ids in the anonymity set. This considerably shrinks the anonymity set to everyone who has opted in to a semaphore commitment prior to that account claiming. As a result, there probably needs to be a separate signup phase where people commit to nullifiers in order to seed the anonymity set. This interactivity requirement makes applications such as the zk airdrop or nicer tornado cash construction (in the use cases section) much harder. However, since hashes (as far as we currently know) are still hard with quantum computers, it’s unlikely that people will be able to ever de-anonymize you.

A recent approximation of $2n^2$ qubits needed to solve discrete log via quantum annealing that failed to work on larger than $n$ = 6-bit primes shows that we are likely several decades from this becoming a reality, and the $n^2$ qubits needed to solve RSA having predictions 10-40 years out suggest that it will likely take longer than that to solve discrete log.

We hope that people will choose the appropriate algorithm for their chosen point on the interactivity-quantum secrecy tradeoff for their application, and hope that including this information helps folks make the right choice for themselves. Folks prioritizing shorter-term secrecy, like DAO voting or confessions of the young who will likely no longer care when they’re old, might prioritize this document’s nullifier construction, but whistleblowers or journalists might want to consider the semaphore construction instead.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 24 Sep 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7524</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7524</guid>
      </item>
    
      <item>
        <title>Token Bound Function Oracle AMM</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7527-token-bound-function-oracle-amm-contract/15950</comments>
        
        <description>## Abstract

This proposal outlines interfaces for wrapping [ERC-20](/EIPs/EIPS/eip-20) or ETH to [ERC-721](/EIPs/EIPS/eip-721) and unwrap ERC-721 to ERC-20 or ETH. A function oracle feeds mint/burn prices based on an embedded equation of Function Oracle Automated Market Maker(FOAMM), which executes and clears the mint and burn of NFT. 

## Motivation

Liquidity can be a significant challenge in decentralized systems, especially for unique or less commonly traded tokens like NFTs. To foster a trustless NFT ecosystem, the motivation behind Function Oracle Automated Market Maker(FOAMM) is to provide automated pricing solutions for NFTs with liquidity through transparent, smart contract mechanisms. 

This ERC provides innovative solutions for the following aspects: 

- Automated Price Discovery
- Liquidity Enhancement

### Automated Price Discovery 

Transactions under FOAMM can occur without the need for a matching counterparty. When interacting directly with the pool, FOAMM automatically feeds prices based on the oracle with predefined function. 

### Liquidity Enhancement

In traditional DEX models, liquidity is supplied by external parties, known as Liquidity Providers(LP). These LPs deposit tokens into liquidity pools, facilitating exchanges by providing the liquidity. The removal or withdrawal of these LPs can introduce significant volatility, as it directly impacts the available liquidity in the market. 

In a FOAMM system, the liquidity is added or removed internally through `wrap` or `unwrap`. FOAMM reduces reliance on external LPs and mitigates the risk of volatility caused by their sudden withdrawal, as the liquidity is continuously replenished and maintained through ongoing participant interactions.


## Specification

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

Contract Interfaces: 

Three interfaces are included here: `Agency`, `App`, and `Factory`. 

`Agency` and `App` MAY be implemented by the same contract or MAY be separately implemented. If separately implemented, they SHALL be mutually bounded and not upgradable after initialization.

`Agency` and `App` should implement `iconstructor` interface to initialize the parameters within the contract and validate the configuration parameters. If factory is used to deploy `Agency` and `App`, factory will automatically call the two functions when deploying.

`App` SHALL implement `onlyAgency()` modifier and `mint` and `burn` SHALL apply `onlyAgency()` as a modifier, which restricts calls to `Mint` and `Burn` only have effect if they are called through the corresponding `Agency`.

`Agency` is OPTIONAL to implement `onlyApp()`.

The `Factory` interface is OPTIONAL. It is most useful if `Agency` and `App` need to be deployed repeatedly. 

Function Oracle is implemented through `getWrapOracle` and `getUnwrapOracle`, which feeds prices based on parameters and mathematical equations defined in the functions. 

FOAMM is implemented through `wrap` and `unwrap`, which calls `getWrapOracle` and `getUnwrapOracle` to get the feed and automatically clears. To perform `wrap`, FOAMM receives the premium and initiate `mint` in `App`. To perform `unwrap`, FOAMM transfer the premium and initiate `burn` in `App`.

`Agency` serves as a single entry point for all `mint` and `burn` transfer. 

### Agency Interface

```
pragma solidity ^0.8.20;

/**
 * @dev The settings of the agency.
 * @param currency The address of the currency. If `currency` is 0, the currency is Ether.
 * @param basePremium The base premium of the currency.
 * @param feeRecipient The address of the fee recipient.
 * @param mintFeePercent The fee of minting.
 * @param burnFeePercent The fee of burning.
 */

struct Asset {
    address currency;
    uint256 basePremium;
    address feeRecipient;
    uint16 mintFeePercent;
    uint16 burnFeePercent;
}

interface IERC7527Agency {
    /**
     * @dev Allows the account to receive Ether
     *
     * Accounts MUST implement a `receive` function.
     *
     * Accounts MAY perform arbitrary logic to restrict conditions
     * under which Ether can be received.
     */
    receive() external payable;

    /**
     * @dev Emitted when `tokenId` token is wrapped.
     * @param to The address of the recipient of the newly created non-fungible token.
     * @param tokenId The identifier of the newly created non-fungible token.
     * @param premium The premium of wrapping.
     * @param fee The fee of wrapping.
     */
    event Wrap(address indexed to, uint256 indexed tokenId, uint256 premium, uint256 fee);

    /**
     * @dev Emitted when `tokenId` token is unwrapped.
     * @param to The address of the recipient of the currency.
     * @param tokenId The identifier of the non-fungible token to unwrap.
     * @param premium The premium of unwrapping.
     * @param fee The fee of unwrapping.
     */
    event Unwrap(address indexed to, uint256 indexed tokenId, uint256 premium, uint256 fee);

    /**
     * @dev Constructor of the instance contract.
     */
    function iconstructor() external;

    /**
     * @dev Wrap some amount of currency into a non-fungible token.
     * @param to The address of the recipient of the newly created non-fungible token.
     * @param data The data to encode into ifself and the newly created non-fungible token.
     * @return The identifier of the newly created non-fungible token.
     */
    function wrap(address to, bytes calldata data) external payable returns (uint256);

    /**
     * @dev Unwrap a non-fungible token into some amount of currency.
     *
     * Todo: event
     *
     * @param to The address of the recipient of the currency.
     * @param tokenId The identifier of the non-fungible token to unwrap.
     * @param data The data to encode into ifself and the non-fungible token with identifier `tokenId`.
     */
    function unwrap(address to, uint256 tokenId, bytes calldata data) external payable;

    /**
     * @dev Returns the strategy of the agency.
     * @return app The address of the app.
     * @return asset The asset of the agency.
     * @return attributeData The attributeData of the agency.
     */
    function getStrategy() external view returns (address app, Asset memory asset, bytes memory attributeData);

    /**
     * @dev Returns the premium and fee of wrapping.
     * @param data The data to encode to calculate the premium and fee of wrapping.
     * @return premium The premium of wrapping.
     * @return fee The fee of wrapping.
     */
    function getWrapOracle(bytes memory data) external view returns (uint256 premium, uint256 fee);

    /**
     * @dev Returns the premium and fee of unwrapping.
     * @param data The data to encode to calculate the premium and fee of unwrapping.
     * @return premium The premium of wrapping.
     * @return fee The fee of wrapping.
     */
    function getUnwrapOracle(bytes memory data) external view returns (uint256 premium, uint256 fee);

    /**
     * @dev OPTIONAL - This method can be used to improve usability and clarity of Agency, but interfaces and other contracts MUST NOT expect these values to be present.
     * @return the description of the agency, such as how `getWrapOracle()` and `getUnwrapOracle()` are calculated.
     */
    function description() external view returns (string memory);
}
```

### App Interface

`ERC7527App` SHALL inherit `name` from interface `ERC721Metadata`. 

```
pragma solidity ^0.8.20;

interface IERC7527App {
    /**
     * @dev Returns the maximum supply of the non-fungible token.
     */
    function getMaxSupply() external view returns (uint256);

    /**
     * @dev Returns the name of the non-fungible token with identifier `id`.
     * @param id The identifier of the non-fungible token.
     */
    function getName(uint256 id) external view returns (string memory);

    /**
     * @dev Returns the agency of the non-fungible token.
     */
    function getAgency() external view returns (address payable);

    /**
     * @dev Constructor of the instance contract.
     */
    function iconstructor() external;

    /**
     * @dev Sets the agency of the non-fungible token.
     * @param agency The agency of the non-fungible token.
     */
    function setAgency(address payable agency) external;

    /**
     * @dev Mints a non-fungible token to `to`.
     * @param to The address of the recipient of the newly created non-fungible token.
     * @param data The data to encode into the newly created non-fungible token.
     */
    function mint(address to, bytes calldata data) external returns (uint256);

    /**
     * @dev Burns a non-fungible token with identifier `tokenId`.
     * @param tokenId The identifier of the non-fungible token to burn.
     * @param data The data to encode into the non-fungible token with identifier `tokenId`.
     */
    function burn(uint256 tokenId, bytes calldata data) external;
}
```

Token ID can be specified in `data` parameter of `mint` function. 

### Factory Interface 

OPTIONAL - This interface can be used to deploy App and Agency, but interfaces and other contracts MUST NOT expect this interface to be present.

If a factory is needed to deploy bounded App and Agency, the factory SHALL implement the following interface:

```
pragma solidity ^0.8.20;

import {Asset} from &quot;./IERC7527Agency.sol&quot;;

/**
 * @dev The settings of the agency.
 * @param implementation The address of the agency implementation.
 * @param asset The parameter of asset of the agency.
 * @param immutableData The immutable data are stored in the code region of the created proxy contract of agencyImplementation.
 * @param initData If init data is not empty, calls proxy contract of agencyImplementation with this data.
 */
struct AgencySettings {
    address payable implementation;
    Asset asset;
    bytes immutableData;
    bytes initData;
}

/**
 * @dev The settings of the app.
 * @param implementation The address of the app implementation.
 * @param immutableData The immutable data are stored in the code region of the created proxy contract of appImplementation.
 * @param initData If init data is not empty, calls proxy contract of appImplementation with this data.
 */
struct AppSettings {
    address implementation;
    bytes immutableData;
    bytes initData;
}

interface IERC7527Factory {
    /**
     * @dev Deploys a new agency and app clone and initializes both.
     * @param agencySettings The settings of the agency.
     * @param appSettings The settings of the app.
     * @param data The data is additional data, it has no specified format and it is sent in call to `factory`.
     * @return appInstance The address of the created proxy contract of appImplementation.
     * @return agencyInstance The address of the created proxy contract of agencyImplementation.
     */
    function deployWrap(AgencySettings calldata agencySettings, AppSettings calldata appSettings, bytes calldata data)
        external
        returns (address, address);
}
```

## Rationale

### Prior Interfaces

[ERC-5679](/EIPs/EIPS/eip-5679) proposed `IERC5679Ext721` interface for introducing a consistent way to extend [ERC-721](/EIPs/EIPS/eip-721) token standards for minting and burning. To ensure the backward compatibility, considering some contracts which do not implement `ERC721TokenReceiver`, `IERC7527App` employ `mint` function instead of `safeMint`. To ensure the safety and the uniqueness of mutual bound, the `_from` parameter of the `burn` function in `IERC5679Ext721` must be the contract address of the bounded agency. Thus, `burn` function in `IERC7527App` does not contain the `_from` parameter. 

### Mutual Bound

Implement contracts for `IERC7527App` and `IERC7527Agency` so that they are each other&apos;s only owner. The wrap process is to check the premium amount of the fungible token received and then mint non-fungible token in the App. Only the owner or an approver of the non-fungible token can unwrap it.

### Implementation Diversity 

Users can customize function and fee percentage when implement the Agency and the App interfaces.

Different Agency implementations have distinct wrap, unwrap function logic, and different oracleFunction. Users can customize the currency, initial price, fee receiving address, fee rate, etc., to initialize the Agency contract. 

Different App implementations cater to various use cases. Users can initialize the App contract.

Factory is not required. Factory implementation is need-based. Users can deploy their own contracts by selecting different Agency implementations and different App implementations through the Factory, combining them to create various products.


### Currency types

`currency` in `IERC7527Agency` is the address of fungible token. `Asset` can only define one type of `currency` as the fungible token in the system. `currency` supports various kinds of fungible tokens including ETH and [ERC-20](/EIPs/EIPS/eip-20). 

### Token id

For each wrap process, a unique `tokenId` should be generated. This `tokenId` is essential for verification during the unwrap process. It also serves as the exclusive credential for the token. This mechanism ensures the security of assets in contracts. 

### Wrap and Mint

The `strategy` is set while implementing the Agency interface, and it should be ensured not upgradable once deployed.

When executing the `wrap` function, the predetermined strategy parameters are passed into the `getWrapOracle` function to fetch the current premium and fee. The respective premium is then transferred to the Agency instance; the fee, according to `mintFeePercent` is transferred to `feeRecipient`. Subsequently, the App mints the NFT to the user&apos;s address.

Premium(tokens) transferred into the Agency cannot be moved, except through the unwrap process. The act of executing wrap is the sole trigger for the mint process. 

### Unwrap and Burn

When executing the `unwrap` function, predetermined strategy parameters are passed into the `getUnwrapOracle` function to read the current premium and fee. The App burns the NFT. Then, the corresponding premium, subtracting the fee according to `burnFeePercent`, is then transferred to the user&apos;s address; the fee is transferred to `feeRecipient`. The act of executing &apos;unwrap&apos; is the sole trigger for the &apos;burn&apos; process.

### Two interfaces use together

`IERC7527App` and `IERC7527Agency` can be implemented together for safety, but they can be independently implemented before initialization for flexibiliy.

### Pricing

`getWrapOracle` and `getUnwrapOracle` are used to fetch the current premium and fee. They implement on-chain price fetching through oracle functions. They not only support fetching the premium and fee during the wrap and unwrap processes but also support other contracts calling them to obtain the premium and fee, such as lending contracts.

They can support function oracle based on on-chain and off-chain parameters, but on-chain parameters are suggested only for consensus of on-chain reality.

### `initData` and `iconstructor`

During the deployment of `App` and `Agency` by the Factory, the Factory uses `initData` as Calldata to call the `Agency` and `App` contracts and also invokes the `iconstructor` functions within `App` and `Agency`. 

The initData is mainly used to call the parameterized initialization functions, while `iconstructor` is often used to validate configuration parameters and non-parameterized initialization functions.

## Backwards Compatibility

No backward compatibility issues found.


## Reference Implementation

```
pragma solidity ^0.8.20;

import {
    ERC721Enumerable,
    ERC721,
    IERC721Enumerable
} from &quot;@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol&quot;;
import {IERC20} from &quot;@openzeppelin/contracts/token/ERC20/IERC20.sol&quot;;
import {Address} from &quot;@openzeppelin/contracts/utils/Address.sol&quot;;
import {ClonesWithImmutableArgs} from &quot;clones-with-immutable-args/ClonesWithImmutableArgs.sol&quot;;
import {IERC7527App} from &quot;./interfaces/IERC7527App.sol&quot;;
import {IERC7527Agency, Asset} from &quot;./interfaces/IERC7527Agency.sol&quot;;
import {IERC7527Factory, AgencySettings, AppSettings} from &quot;./interfaces/IERC7527Factory.sol&quot;;

contract ERC7527Agency is IERC7527Agency {
    using Address for address payable;

    receive() external payable {}

    function iconstructor() external override pure {
        (, Asset memory _asset,) = getStrategy();
        require(_asset.basePremium != 0, &quot;LnModule: zero basePremium&quot;);
    }

    function unwrap(address to, uint256 tokenId, bytes calldata data) external payable override {
        (address _app, Asset memory _asset,) = getStrategy();
        require(_isApprovedOrOwner(_app, msg.sender, tokenId), &quot;LnModule: not owner&quot;);
        IERC7527App(_app).burn(tokenId, data);
        uint256 _sold = IERC721Enumerable(_app).totalSupply();
        (uint256 premium, uint256 burnFee) = getUnwrapOracle(abi.encode(_sold));
        _transfer(address(0), payable(to), premium - burnFee);
        _transfer(address(0), _asset.feeRecipient, burnFee);
        emit Unwrap(to, tokenId, premium, burnFee);
    }

    function wrap(address to, bytes calldata data) external payable override returns (uint256) {
        (address _app, Asset memory _asset,) = getStrategy();
        uint256 _sold = IERC721Enumerable(_app).totalSupply();
        (uint256 premium, uint256 mintFee) = getWrapOracle(abi.encode(_sold));
        require(msg.value &gt;= premium + mintFee, &quot;ERC7527Agency: insufficient funds&quot;);
        _transfer(address(0), _asset.feeRecipient, mintFee);
        if (msg.value &gt; premium + mintFee) {
            _transfer(address(0), payable(msg.sender), msg.value - premium - mintFee);
        }
        uint256 id_ = IERC7527App(_app).mint(to, data);
        require(_sold + 1 == IERC721Enumerable(_app).totalSupply(), &quot;ERC7527Agency: Reentrancy&quot;);
        emit Wrap(to, id_, premium, mintFee);
        return id_;
    }

    function getStrategy() public pure override returns (address app, Asset memory asset, bytes memory attributeData) {
        uint256 offset = _getImmutableArgsOffset();
        address currency;
        uint256 basePremium;
        address payable feeRecipient;
        uint16 mintFeePercent;
        uint16 burnFeePercent;
        assembly {
            app := shr(0x60, calldataload(add(offset, 0)))
            currency := shr(0x60, calldataload(add(offset, 20)))
            basePremium := calldataload(add(offset, 40))
            feeRecipient := shr(0x60, calldataload(add(offset, 72)))
            mintFeePercent := shr(0xf0, calldataload(add(offset, 92)))
            burnFeePercent := shr(0xf0, calldataload(add(offset, 94)))
        }
        asset = Asset(currency, basePremium, feeRecipient, mintFeePercent, burnFeePercent);
        attributeData = &quot;&quot;;
    }

    function getUnwrapOracle(bytes memory data) public pure override returns (uint256 premium, uint256 fee) {
        uint256 input = abi.decode(data, (uint256));
        (, Asset memory _asset,) = getStrategy();
        premium = _asset.basePremium + input * _asset.basePremium / 100;
        fee = premium * _asset.burnFeePercent / 10000;
    }

    function getWrapOracle(bytes memory data) public pure override returns (uint256 premium, uint256 fee) {
        uint256 input = abi.decode(data, (uint256));
        (, Asset memory _asset,) = getStrategy();
        premium = _asset.basePremium + input * _asset.basePremium / 100;
        fee = premium * _asset.mintFeePercent / 10000;
    }

    function _transfer(address currency, address recipient, uint256 premium) internal {
        if (currency == address(0)) {
            payable(recipient).sendValue(premium);
        } else {
            IERC20(currency).transfer(recipient, premium);
        }
    }

    function _isApprovedOrOwner(address app, address spender, uint256 tokenId) internal view virtual returns (bool) {
        IERC721Enumerable _app = IERC721Enumerable(app);
        address _owner = _app.ownerOf(tokenId);
        return (spender == _owner || _app.isApprovedForAll(_owner, spender) || _app.getApproved(tokenId) == spender);
    }
    /// @return offset The offset of the packed immutable args in calldata

    function _getImmutableArgsOffset() internal pure returns (uint256 offset) {
        // solhint-disable-next-line no-inline-assembly
        assembly {
            offset := sub(calldatasize(), add(shr(240, calldataload(sub(calldatasize(), 2))), 2))
        }
    }
}

contract ERC7527App is ERC721Enumerable, IERC7527App {
    constructor() ERC721(&quot;ERC7527App&quot;, &quot;EA&quot;) {}

    address payable private _oracle;

    modifier onlyAgency() {
        require(msg.sender == _getAgency(), &quot;only agency&quot;);
        _;
    }

    function iconstructor() external {}

    function getName(uint256) external pure returns (string memory) {
        return &quot;App&quot;;
    }

    function getMaxSupply() public pure override returns (uint256) {
        return 100;
    }

    function getAgency() external view override returns (address payable) {
        return _getAgency();
    }

    function setAgency(address payable oracle) external override {
        require(_getAgency() == address(0), &quot;already set&quot;);
        _oracle = oracle;
    }

    function mint(address to, bytes calldata data) external override onlyAgency returns (uint256 tokenId) {
        require(totalSupply() &lt; getMaxSupply(), &quot;max supply reached&quot;);
        tokenId = abi.decode(data, (uint256));
        _mint(to, tokenId);
    }

    function burn(uint256 tokenId, bytes calldata) external override onlyAgency {
        _burn(tokenId);
    }

    function _getAgency() internal view returns (address payable) {
        return _oracle;
    }
}

contract ERC7527Factory is IERC7527Factory {
    using ClonesWithImmutableArgs for address;

    function deployWrap(AgencySettings calldata agencySettings, AppSettings calldata appSettings, bytes calldata)
        external
        override
        returns (address appInstance, address agencyInstance)
    {
        appInstance = appSettings.implementation.clone(appSettings.immutableData);
        {
            agencyInstance = address(agencySettings.implementation).clone(
                abi.encodePacked(
                    appInstance,
                    agencySettings.asset.currency,
                    agencySettings.asset.basePremium,
                    agencySettings.asset.feeRecipient,
                    agencySettings.asset.mintFeePercent,
                    agencySettings.asset.burnFeePercent,
                    agencySettings.immutableData
                )
            );
        }

        IERC7527App(appInstance).setAgency(payable(agencyInstance));

        IERC7527Agency(payable(agencyInstance)).iconstructor();
        IERC7527App(appInstance).iconstructor();

        if (agencySettings.initData.length != 0) {
            (bool success, bytes memory result) = agencyInstance.call(agencySettings.initData);

            if (!success) {
                assembly {
                    revert(add(result, 32), mload(result))
                }
            }
        }

        if (appSettings.initData.length != 0) {
            (bool success, bytes memory result) = appInstance.call(appSettings.initData);

            if (!success) {
                assembly {
                    revert(add(result, 32), mload(result))
                }
            }
        }
    }
}
```

## Security Considerations

### Fraud Prevention

Consider the following for the safety of the contracts:

* Check whether modifiers `onlyAgency()` and `onlyApp()` are proporly implemented and applied.

* Check the function strategies.

* Check whether the contracts can be subject to re-entrancy attack.

* Check whether all non-fungible tokens can be unwrapped with the premium calculated from FOAMM.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 03 Sep 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7527</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7527</guid>
      </item>
    
      <item>
        <title>ETH (Native Asset) Address Convention</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7808-eth-native-asset-address-convention/15989</comments>
        
        <description>## Abstract

The following standard proposes a convention for using the address `0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee` in all contexts where an address is used to represent ETH in the same capacity as an [ERC-20](/EIPs/EIPS/eip-20) token. This would apply to both events where an address field would denote ETH or an [ERC-20](/EIPs/EIPS/eip-20) token, as well as discriminators such as the `asset` field of an [ERC-4626](/EIPs/EIPS/eip-4626) vault.

This standard generalizes to other EVM chains where the native asset is not ETH.

## Motivation

ETH, being a fungible unit of value, often behaves similarly to [ERC-20](/EIPs/EIPS/eip-20) tokens. Protocols tend to implement a standard interface for ERC-20 tokens, and benefit from having the ETH implementation to closely mirror the [ERC-20](/EIPs/EIPS/eip-20) implementations.

In many cases, protocols opt to use Wrapped ETH (e.g. WETH9 deployed at address 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 on Etherum Mainnet) for [ERC-20](/EIPs/EIPS/eip-20) compliance. In other cases, protocols will use native ETH due to gas considerations, or the requirement of using native ETH such as in the case of a Liquid Staking Token (LST).

In addition, protocols might create separate events for handling ETH native cases and ERC-20 cases. This creates data fragmentation and integration overhead for off-chain infrastructure. By having a strong convention for an ETH address to use for cases where it behaves like an [ERC-20](/EIPs/EIPS/eip-20) token, it becomes beneficial to use one single event format for both cases. 

One intended use case for the standard is [ERC-4626](/EIPs/EIPS/eip-4626) compliant LSTs which use ETH as the `asset`. This extends the benefits and tooling of [ERC-4626](/EIPs/EIPS/eip-4626) to LSTs and integrating protocols.

This standard allows protocols and off-chain data infrastructure to coordinate around a shared understanding that any time `0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee` is used as an address in an [ERC-20](/EIPs/EIPS/eip-20) context, it means ETH.

## Specification

This standard applies for all components of smart contract systems in which an address is used to identify an [ERC-20](/EIPs/EIPS/eip-20) token, and where native ETH is used in certain instances in place of an [ERC-20](/EIPs/EIPS/eip-20) token. The usage of the term Token below means ETH or an [ERC-20](/EIPs/EIPS/eip-20) in this context.

Any fields or events where an [ERC-20](/EIPs/EIPS/eip-20) address is used, yet the underlying Token is ETH, the address field MUST return `0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee`

Any fields or events where the Token is a non-enshrined wrapped ERC-20 version of ETH (i.e WETH9) MUST use that Token&apos;s address and MUST NOT use `0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee`.

Where appropriate, the address should be checksummed. E.g. the [EIP-55](/EIPs/EIPS/eip-55) checksum is `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE`.

## Rationale

### Considered alternative addresses

Many existing implementations of the same use case as this standard use addresses such as 0x0, 0x1, and 0xe for gas efficiency of having leading zero bytes.

Ultimately, all of these addresses collide with potential precompile addresses and are less distinctive as identifiers for ETH.

`0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee` has the most current usage, is distinctive, and would not collide with any precompiles. These benefits outweigh the potential gas benefits of other alternatives.

## Backwards Compatibility

This standard has no known compatibility issues with other standards.

## Security Considerations

Using ETH as a Token instead of WETH exposes smart contract systems to re-entrancy and similar classes of vulnerabilities. Implementers must take care to follow the industry standard development patterns (e.g.  checks-effects-interactions) when the Token is ETH.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 03 Oct 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7528</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7528</guid>
      </item>
    
      <item>
        <title>Contract Discovery and eTLD+1 Association</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/add-eip-dns-over-https-for-contract-discovery-and-etld-1-association/15996</comments>
        
        <description>## Abstract

The introduction of DNS over HTTPS (DoH) in [RFC 8484](https://www.rfc-editor.org/rfc/rfc8484) has enabled tamper-resistant client-side queries of DNS records directly from a web application. This proposal describes a simple standard leveraging DoH to fetch TXT records (from traditional DNS service providers) which are used for discovering and verifying the association of a smart contract with a common DNS domain. This standard can be used as a straightforward technique to mitigate smart contract authorship spoofing and enhance the discoverability of smart contracts through standard web search mechanisms.  

## Motivation

As mainstream businesses begin to adopt public blockchain and digital asset technologies more rapidly, there is a growing need for a discovery/search mechanism (compatible with conventional web technologies) of smart contracts associated with a known business domain as well as reasonable assurance that the smart contract does indeed belong to the business owner of the DNS domain. The relatively recent introduction and widespread support of DoH means it is possible to make direct, tamper-resistant queries of DNS records straight from a web application context and thus leverage a simple TXT record as a pointer to an on-chain smart contract. Prior to the introduction of DoH, web (and mobile) applications *could not* access DNS records directly; instead they would have to relay requests through a trusted, proprietary service provider who could easily manipulate response results. 

According to Cloudflare, the two most common use cases of TXT records today are email spam prevention (via [SPF](https://www.rfc-editor.org/rfc/rfc7208), [DKIM](https://www.rfc-editor.org/rfc/rfc6376), and [DMARC](https://www.rfc-editor.org/rfc/rfc7489) TXT records) and domain name ownership verification. The use case considered here for on-chain smart contract discovery and verification is essentially analogous. 

A TXT pointer coupled with an appropriate smart contract interface (described in this proposal) yields a simple, yet flexible and robust mechanism for the client-side detection and reasonably secure verification of on-chain logic and digital assets associated with the owner of a domain name. For example, a stablecoin issuer might leverage this standard to provide a method for an end user or web-based end user client to ensure that the asset their wallet is interacting with is indeed the contract issued or controlled by the owner or administrator of a well known DNS domain.

**Example 1**:

A user visits merchant.com who accepts payments via paymentprocessor.com. The business behind paymentprocessor.com has previously released a stable coin for easier cross-border payments which adheres to this ERC. On the checkout page, paymentprocessor.com is mounted as an iframe component. If the user has installed a browser-extension wallet compatible with this standard, then the wallet can detect the domain of the iframe in the context of the checkout page, discover and verify the stable coin&apos;s association with paymentprocessor.com, and automatically prompt to complete the purchase in paymentprocessor.com&apos;s stable coin. 

**Example 2**:

A user visits nftmarketplace.io to buy a limited release NFT from theirfavoritebrand.com. The marketplace webapp can leverage this ERC to allow the user to search by domain name and also indicate to the user that an NFT of interest is indeed an authentic asset associated with theirfavoritebrand.com. 

## Specification

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

#### Definition: eTLD+1 

The term TLD stands for *top-level domain* and is always the part of a domain name which follows the final dot in a URL (e.g. `.com` or `.net`). If only domains directly under TLDs where registrable by a single organization, then it would be guaranteed that `myexample.com`, `abc.myexample.com`, and `def.myexample.com` all belonged to the same organization. 

However, this is not the case in general since many DNS registrars allow organizations to register domain names below the top level (examples include `sussex.ac.uk` and `aber.ac.uk` which are controlled by different institutions). These types of domains are referred to as eTLDs (effective top-level domains) and represent a domain under which domain names can be registered by a single organization. For example, the eTLD of `myexample.com` is `.com` and the eTLD of `sussex.ac.uk` is `.ac.uk` since individual organizations can be issued their own domain names under both `.com` and `.ac.uk`. 

Therefore, an eTLD+1 is an eTLD *plus* this next part on the domain name. Since eTLDs are by definition registerable, all domains with the same eTLD+1 are owned by the same organization, which makes them appropriate to utilize in this proposal for associating a smart contract with a single business or organization entity. 


### Contract Pointers in TXT Records 

The owner of an eTLD+1 domain name MUST create a TXT record in their DNS settings that serves as a pointer to all relevant smart contracts they wish to associate with their domain. 

[TXT records](https://www.rfc-editor.org/rfc/rfc1035#section-3.3.14) are not intended (nor permitted by most DNS servers) to store large amounts of data. Every DNS provider has their own vendor-specific character limits. However, an EVM-compatible address string is 42 characters, so most DNS providers will allow for dozens of contract addresses to be stored under a single record. Furthermore, a domain is allowed to have multiple TXT records associated with the same host and the content of all duplicate records can be retrieved in a single DoH query. 

A TXT record pointing to an organization&apos;s smart contracts MUST adhere to the following schema:

- `HOST`: `ERC-7529.&lt;chain_id&gt;._domaincontracts` (where `&lt;chain_id&gt;` is replaced by the decimal representation of the chain id)
- `VALUE`: \&lt;`address 1`\&gt;,\&lt;`address 2`\&gt;,...

It is RECOMMENDED that EVM address strings adhere to [ERC-1191](/EIPs/EIPS/eip-1191) so that the browser client can checksum the validity of the address and its target network before making an RPC call. 

A user&apos;s web application can access TXT records directly from a DNS registrar who supports DoH with `fetch`. An example query of a DoH server that supports JSON format will look like:

```javascript
await fetch(&quot;https://example-doh-provider.com/dns-query?name=ERC-7529.1._domaincontracts.myexample.com&amp;type=TXT&quot;, {
  headers: {
    Accept: &quot;application/dns-json&quot;
  }
})
```

### Smart Contract Association with a Domain 

Any smart contract MAY implement this ERC to provide a verification mechanism of smart contract addresses listed in a compatible TXT record.

A smart contract need only store one new member variable, `domains`, which is a mapping from the keccak256 hash of all eTLD+1 domain strings associated with the business or organization which deployed (or is closely associated with) the contract to a boolean. This member variable can be written to with the external functions `addDomain` and `removeDomain`. The `domains` member variable can be queried by the `checkDomain` function which takes a string representing an eTLD+1 and returns true
if the contract has been associated with the domain and false otherwise. 

Lastly, the contract MAY emit events when eTLD+1 domains are added (`AddDomain`) or removed (`RemoveDomain`) from the `domains` map. This can be useful for 
determining all domains associated with a contract when they are not known ahead of time by the client. 

```solidity
{
  /// @notice Optional event emitted when a domain is added
  /// @param domain eTLD+1 associated with the contract
  event AddDomain(string domain);

  /// @notice Optional event emitted when a domain is removed
  /// @param domain eTLD+1 that is no longer associated with the contract
  event RemoveDomain(string domain);

  /// @dev a mapping from the keccak256 hash of eTLD+1 domains associated with this contract to a boolean
  mapping(bytes32 =&gt; bool) domains;

  /// @notice a getter function that takes an eTLD+1 domain string and returns true if associated with the contract
  /// @param domain a string representing an eTLD+1 domain
  function checkDomain(string calldata domain) external view returns (bool); 

  /// @notice an authenticated method to add an eTLD+1 domain
  /// @param domain a string representing an eTLD+1 domain associated with the contract
  function addDomain(string calldata domain) external;

  /// @notice an authenticated method to remove an eTLD+1 domain
  /// @param domain a string representing an eTLD+1 domain that is no longer associated with the contract
  function removeDomain(string calldata domain) external; 
}
```

### Client-side Verification

When a client detects a compatible TXT record listed on an eTLD+1, it SHOULD loop through each listed contract address and, via an appropriate RPC provider, assert
that each of the smart contracts returns `true` when the eTLD+1 string is passed to the `checkDomain` function. 

Alternatively, if a client is inspecting a contract that implements this ERC, the client SHOULD inspect the `AddDomain` and `RemoveDomain` events to calculate if 
one or more eTLD+1 domains are actively associated with the contract. The user client SHOULD attempt to fetch TXT records from all associated eTLD+1 domains to verify its association or authenticity. The client MUST confirm that each contract address is contained in a TXT record&apos;s `VALUE` field of the eTLD+1 pointed to by the contract&apos;s `domains` mapping. 

## Rationale

In this specification, the TXT record `HOST` naming scheme is designed to mimic the DKIM naming convention. Additionally, this naming scheme makes it simple to programmatically ascertain if any smart contracts are associated with the domain on a given blockchain network. Prepending with `ERC-7529` will prevent naming collisions with other TXT records. The value of `&lt;chain_id&gt;` is simply the decimal representation of the chain id associated with the target blockchain network (i.e. `1` for Ethereum mainnet or `11155111` for Sepolia) where the smart contracts are deployed. So, a typical `HOST` might be: `ERC-7529.1._domainContracts`, `ERC-7529.11155111._domaincontracts`, etc.

A user client working with smart contracts implementing this proposal is protected by cross-checking that two independent sources of information agree with each other (i.e. DNS and a blockchain network). As long as the `addDomain` and `removeDomain` calls on the smart contract are properly authenticated (as shown in the reference implementation), the values in the domains field must have been set by a controller of the contract. The contract addresses in the TXT records can only be set by the owner of the eTLD+1 domain. For these two values to align the same organization must control both resources.

## Backwards Compatibility

No backward compatibility issues found.

## Reference Implementation

The implementation of `checkDomain`, `addDomain` and `removeDomain` is a trivial exercise, but candidate implementations are given here for completeness:

```solidity
function checkDomain(
      string calldata domain
  ) external view returns (bool) {
    return domains[keccak256(abi.encodePacked(domain))];
  }

function addDomain(
      string memory domain
  ) external onlyRole(DEFAULT_ADMIN_ROLE) {
    domains[keccak256(abi.encodePacked(domain))] = true;
    emit AddDomain(domain);
  }

function removeDomain(
    string memory domain
  ) external onlyRole(DEFAULT_ADMIN_ROLE) {
    require(domains[keccak256(abi.encodePacked(domain))] == true, &quot;ERC7529: eTLD+1 currently not associated with this contract&quot;); 
    domains[keccak256(abi.encodePacked(domain))] = false;
    emit RemoveDomain(domain);
  }
```

**NOTE**: Appropriate account authentication MUST be applied to `addDomain` and `removeDomain` so that only authorized users may update the `domains` mapping. In the given reference implementation the `onlyRole` modifier is used to restrict call privileges to accounts with the `DEFAULT_ADMIN_ROLE` which can be added to any contract with the OpenZeppelin access control abstract class. 

## Security Considerations

Due to the reliance on traditional DNS systems, this ERC is susceptible to attacks on this technology, such as domain hijacking. Additionally, it is the responsibility of the smart contract author to ensure that `addDomain` and `removeDomain` are authenticated properly, otherwise an attacker could associate their smart contract with an undesirable domain, which would simply break the ability to verify association with the proper domain. 

It is worth noting that for an attacker to falsy verify a contract against a domain would require them to compromise both the DNS settings **and** the smart contract itself. In this scenario, the attacker has likely also compromised the business&apos; email domains as well. 

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 30 Sep 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7529</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7529</guid>
      </item>
    
      <item>
        <title>Staked ERC-721 Ownership Recognition</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7531-resolving-staked-erc-721-ownership-recognition/15967</comments>
        
        <description>## Abstract

The ownership of [ERC-721](/EIPs/EIPS/eip-721) tokens when staked in a pool presents challenges, particularly when it involves older, non-lockable NFTs like, for example, Crypto Punks or Bored Ape Yacht Club (BAYC) tokens. This proposal introduces an interface to address these challenges by allowing staked NFTs to be recognized by their original owners, even after they&apos;ve been staked.

## Motivation

Recent solutions involve retaining NFT ownership while &quot;locking&quot; an NFT letting the owner keeping its ownership. However, this requires the NFT contract to implement lockable functionality. Early NFTs were not originally designed as lockable and so they must be staked transferring the ownership to the staking contract.

This prevents the original owner from accessing valuable privileges and benefits associated with their NFTs.

For example:

- A BAYC NFT holder would lose access to the BAYC Yacht Club and member events when staked.
- A CryptoPunks holder may miss out on special airdrops or displays only available to verified owners.
- Owners of other early NFTs like EtherRocks would lose the social status of provable ownership when staked.

By maintaining a record of the original owner, the proposed interface allows these original perks to remain accessible even when the NFT is staked elsewhere. This compatibility is critical for vintage NFT projects lacking native locking mechanisms.

Another important right, is the right to use an asset. For example an NFT can be used to play a game. If the NFT is lent to a user, the ownership of the NFT is transferred to the lending contract. In this case, it can be hard to identify the wallet that has the right to us the NFT in the game, which should be the user.

The interface provides a simple, elegant way to extend staking compatibility to legacy NFTs without affecting their core functionality or benefits of ownership.

## Specification

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

The interface is defined as follows:

```solidity
interface IERC7531 {

  /**
   * @notice MUST be emitted when the token&apos;s technical owner (the contract holding the token) is different 
   *      from its actual owner (the entity with rights over the token). 
   * @dev This scenario is common in staking, where a staking contract is the technical owner. The event MUST  
   *      be emitted in the same or any subsequent block as the Transfer event for the token. 
   *      A later Transfer event involving the same token supersedes this RightsHolderChange event.
   *      To ensure authenticity, entities listening to this event MUST verify that the contract emitting
   *      the event matches the token&apos;s current owner as per the related Transfer event.
   *
   * @param tokenAddress The address of the token contract.
   * @param tokenId The ID of the token.
   * @param holder The address of the actual rights holder of the token.
   * @param right The type of right held by the holder. The initial supported rights are:
   *
   *           0x399d2b36   // bytes4(keccak256(&quot;ownership&quot;))
   *           0x230a5961   // bytes4(keccak256(&quot;usage&quot;))
   *
   *        This allows projects to add more rights without breaking compatibility with this interface. See IERC7531Rights for more details.
   */
  event RightsHolderChange(address indexed tokenAddress, uint256 indexed tokenId, address indexed holder, bytes4 right);

  /**
   * @dev Returns the address of the entity with rights over the token, distinct from the current owner.
   *      The function MUST revert if the token does not exist or is not currently held.
   *
   * @param tokenAddress The address of the ERC-721 contract.
   * @param tokenId The ID of the token.
   * @param right The type of right held by the holder.
   * @return The address of the entity with rights over the token.
   */
  function rightsHolderOf(
    address tokenAddress,
    uint256 tokenId,
    bytes4 right
  ) external view returns (address);
}
```

The `RightsHolderChange` event is crucial for accurately identifying the actual owner of a held token. In scenarios where a token is staked in a contract, the [ERC-721](/EIPs/EIPS/eip-721) Transfer event would incorrectly assign ownership to the staking contract itself. The `RightsHolderChange` event addresses this discrepancy by explicitly signaling the real owner of the token rights.

### Timing of Event Emission:

The `RightsHolderChange` event MUST be emitted either in the same block as the corresponding `Transfer` event or in any subsequent block. This approach offers flexibility for existing pools to upgrade their systems without compromising past compatibility. Specifically, staking pools can emit this event for all previously staked tokens, or they can allow users to actively reclaim their ownership. This flexibility ensures that the system can adapt to both current and future states while accurately reflecting the actual ownership of held tokens.

### Invalidation of Previous `RightsHolderChange` Events:

To maintain compatibility with the broader ecosystem and optimize for gas efficiency, any new `Transfer` event involving the same token invalidates any previous `RightsHolderChange` event. This approach ensures that the most recent `Transfer` event reliably reflects the current ownership status, negating the need for additional events upon unstaking.

### NFT extension

The two default rights are:
* 0x399d2b36   // bytes4(keccak256(&quot;ownership&quot;))
* 0x230a5961   // bytes4(keccak256(&quot;usage&quot;))

However, there can ben NFTs that only need to validate the ownership, others may need to validate the usage, and others may need to validate both, some other NFT may need to manage totally different rights.

To give NFTs the necessary flexibility, we also propose the following OPTIONAL extension.

```solidity
interface IERC7531Rights {
  
  /**
   * @dev Returns the list of rights supported by the NFT.
   * @return The list of rights supported by the NFT.
   */
  function supportedERC7531Rights() external view returns (bytes4[] memory);
  
  /**
   * @dev Returns whether the NFT supports a specific right.
   * @param right The right to check.
   * @return Whether the NFT supports the right.
   */
  function supportsERC7531Right(bytes4 right) external view returns (bool);
}
```

It allows NFTs to return the list of rights they support, and projects to verify it an NFT supports a specific right. Since the rights are identified by the bytes4 hash of the right name, when introducing new rights, NFT projects SHOULD make public statements about the string that corresponds to the bytes4 hash and explain the rationale for it.

If the NFT does not support the interface (for example, if an existing NFT), project using NFTs SHOULD consider only the standard rights.

NFT Projects SHOULD adhere to pre-existing rights, when possible, to avoid the proliferation of rights that could make the system less efficient and more complex.

## Rationale

### Addressing Non-Lockable NFT Challenges:

Non-lockable NFTs present a unique challenge in decentralized ecosystems, especially in scenarios involving staking or delegating usage rights. The standard [ERC-721](/EIPs/EIPS/eip-721) `ownerOf` function returns the current owner of the NFT, which, in the case of staking, would be the staking pool contract. This transfer of ownership to the staking pool, even if temporary, can disrupt the utility or privileges tied to the NFT, such as participation in governance, access to exclusive content, or utility within a specific ecosystem.

### The `rightsHolderOf` Method:

The `rightsHolderOf` method provides a solution to this challenge. By maintaining a record of the original owner or the rightful holder of certain privileges associated with the NFT, this method ensures that the underlying utility of the NFT is preserved, even when the NFT itself is held in a pool.

### Technical Advantages:

1. Preservation of Utility: This approach allows NFT owners to leverage their assets in staking pools or other smart contracts without losing access to the benefits associated with the NFT. This is particularly important for NFTs that confer ongoing benefits or rights.

2. Enhanced Flexibility: The method offers greater flexibility for NFT owners, allowing them to participate in staking and other DeFi activities without relinquishing the intrinsic benefits of their NFTs.

3. Compatibility and Interoperability: By introducing a new method instead of altering the existing ownerOf function, this EIP ensures backward compatibility with existing [ERC-721](/EIPs/EIPS/eip-721) contracts. This is crucial for maintaining interoperability across various platforms and applications in the NFT space.

4. Event-Driven Updates: The `RightsHolderChange` event facilitates real-time tracking of the rights-holder of an NFT. This is particularly useful for third-party platforms and services that rely on up-to-date ownership information to provide services or privileges.

### Addressing Potential Misuse:

While this approach introduces a layer of complexity, it also comes with the need for diligent implementation to prevent misuse, such as the wrongful assignment of rights. This EIP outlines security considerations and best practices to mitigate such risks.

## Backwards Compatibility

This standard is fully backwards compatible with existing [ERC-721](/EIPs/EIPS/eip-721) contracts. It can seamlessly integrate with existing upgradeable staking pools, provided they choose to adopt it. It does not require changes to the [ERC-721](/EIPs/EIPS/eip-721) standard but acts as an enhancement for staking pools.

## Security Considerations

A potential risk with this interface is the improper assignment of ownership by a staking pool to a different wallet. This could allow that wallet to access privileges associated with the NFT, which might not be intended by the true owner. However, it is important to note that this risk is lower than transferring full legal ownership of the NFT to the staking pool, as the interface only enables recognizing the staker, not replacing the actual owner on-chain.

### Event Authenticity:

There is a concern regarding the potential emission of fake `RightsHolderChange` events. Since any contract can emit such an event, there&apos;s a risk of misinformation or misrepresentation of ownership. It is crucial for entities listening to the `RightsHolderChange` event to verify that the emitting contract is indeed the current owner of the token. This validation is essential to ensure the accuracy of ownership information and to mitigate the risks associated with deceptive event emissions.

### Reducing the Risk of Inaccurate Ownership Records:

While improper use of this interface poses some risk of inaccurate ownership records, this is an inherent issue with any staking arrangement. The risk is somewhat mitigated by the fact that the owner retains custody rather than transferring ownership.

### Due Diligence:

Consumers of privilege-granting NFTs should exercise due diligence when evaluating staking providers. Signs of mismanagement or fraud should be carefully assessed. The interface itself does not enable new manipulation capabilities, but caution is always prudent when interacting with smart contracts and staking pools.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 01 Oct 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7531</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7531</guid>
      </item>
    
      <item>
        <title>Public Cross Port</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/connect-all-l2s/15534</comments>
        
        <description>## Abstract

The objective of Public Cross Port (PCP) is to securely and efficiently connect various EVM chains. It replaces the method of pushing message to multiple chains with a method of pulling messages from multiple chains, significantly reducing the number of cross-chain bridges and gas cost, as more cross-chain bridge projects are built on PCP, the overall security increases.


## Motivation

Currently, there are official cross-chain bridges between L2 and L1, but not between L2s. If there are 10 L2 chains that need to cross-chain with each other, it would require 10 x 9 = 90 cross-chain bridges. However, if a pull mechanism is used to merge messages from the other 9 chains into one transaction synchronized to its own chain, only 10 cross-chain bridges would be needed. This significantly reduces the number of cross-chain bridges required and minimizes gas cost.

This implementation, with the participation of multiple cross-chain bridge projects, would greatly enhance security. There is currently a considerable amount of redundant construction of cross-chain bridges, which does not contribute to improved security. By using a standardized `SendPort` contract, if the same cross-chain message is being transported by multiple redundant bridges, the validation on the target chain&apos;s `IReceivePort` should yield the same result. This result, confirmed by multiple cross-chain bridge projects, provides much higher security than relying on a single confirmation. The purpose of this EIP is to encourage more cross-chain bridge projects to participate, transforming redundant construction into enhanced security.

To attract cross-chain bridge projects to participate, aside from reducing the number of bridges and gas cost, the use of the Hash MerkleTree data structure in the `SendPort` ensures that adding cross-chain messages does not increase the overhead of the bridges. Only a small-sized root is required for the transportation of cross-chain bridges, further saving gas.


### Use case

This EIP divides the cross-chain ecosystem into 3 layers and defines the `SendPort` contract and `IReceivePort` interface at the foundational layer. The implementation of the other layers is left to ecosystem project participants.

![](/EIPs/assets/eip-7533/0.png)

On top of cross-chain messaging, applications can use bridges as service, such like Token cross.

Cross-chain messaging bridges can be combined with Token cross-chain functionality, as shown in the code example at Reference Implementation. Alternatively, they can be separated. Taking the example of an NFT cross-chain application, it can reuse the messaging bridge of Tokens, and even leverage multiple messaging bridges. Reusing multiple bridges for message verification can significantly enhance security without incurring additional costs for cross-chain and verification services.


## Specification

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

The essence of cross-chain is to inform the target chain about events happening on the source chain. This process can be divided into 3 steps. The following diagram illustrates the overall principle:

![](/EIPs/assets/eip-7533/1.png)

### 1.Add cross-chain message

Under this EIP, a `SendPort` contract is deployed on each chain. It is responsible for collecting cross-chain messages on that chain and packing them. `SendPort` operates as a public, permissionless, administrator-free, and automatic system. Cross-chain bridge operators retrieve cross-chain messages from `SendPort` and transport it to the target chain to complete the cross-chain messaging process.

The `SendPort` contract can serve for multiple bridges and is responsible for collecting events (i.e., cross-chain messages) that occur on that chain and packing them into a MerkleTree. For example, let&apos;s consider a scenario where a Bridge contract receives a user&apos;s USDT deposit. It can send the hash of this event and the ID of the target chain to the `SendPort` contract. `SendPort` adds this information, along with the hash of the sender&apos;s address (i.e., the Bridge contract&apos;s address), as a leaf in an array. After collecting a certain number of leaves for a period of time (e.g., 1 minute), `SendPort` automatically packs them into a MerkleTree and begins the next collection phase. `SendPort`&apos;s role is solely focused on event collection and packing. It operates autonomously without the need for management. So no need to repeat deploy `SendPort` on each chain, **RECOMMENDED** one chain one `SendPort`.

The `SendPort.addMsgHash()` function can be called by different cross-chain bridge projects or any other contract. The function does not require permission, which means that there is a possibility of incorrect or fraudulent messages being sent. To prevent fraud, `SendPort` includes the sender&apos;s address in the packing process. This indicates that the `sender` intends to send the information `msgHash` to the `toChainId` chain. When this information is decoded on the target chain, it can help prevent fraudulent activities.

### 2.Pull roots &amp; Set roots

Upon the completion of packing a new MerkleTree, the package carrier (usually the cross-chain bridge project) pulls the root from multiple chains and stores it in the `IReceivePort` contract of each chain. 

A root contains messages from one source chain to multiple target chains. For the package carrier, the root **MAY** not contain relevant messages or **MAY** not include messages intended for a specific target chain. Therefore, the package carrier has the discretion to decide whether or not to transport the root to a particular target chain, based on its relevance.

Hence, the `IReceivePort` contract is not unique and is implemented by the package carrier based on the `IReceivePort` interface. With multiple package carriers, there will be multiple `IReceivePort` contracts.

### 3.Verify cross-chain message

The `IReceivePort` contract stores the roots of each chain, allowing it to verify the authenticity of messages when provided with the complete message. It is important to note that the root itself cannot be used to decipher the message; it can only be used to validate its authenticity. The complete message can be retrieved from the `SendPort` contract of the source chain.

Since the roots originate from the same `SendPort`, the roots in different `IReceivePort` contracts **SHOULD** be identical. In other words, if a message is authentic, it **SHOULD** be able to be verified as authentic across different `IReceivePort` contracts. This significantly enhances security. It is similar to the principle of multi-signature, where if the majority of `IReceivePort` contracts verify a message as authentic, it is likely to be true. Conversely, any `IReceivePort` contracts that verify the message as false may indicate a potential hacker attack or a failure in the corresponding cross-chain bridge. This decentralized participation model ensures that the security of the system is not compromised by single points of failure. It transforms redundant construction into an improvement in security.

Regarding data integrity:

The `SendPort` retains all roots and continuous index numbers without deletion or modification. The `IReceivePort` contracts of each cross-chain bridge **SHOULD** also follow this approach.

### `ISendPort` Interface

```solidity
pragma solidity ^0.8.0;

interface ISendPort {
    event MsgHashAdded(uint indexed packageIndex, address sender, bytes32 msgHash, uint toChainId, bytes32 leaf);

    event Packed(uint indexed packageIndex, uint indexed packTime, bytes32 root);

    struct Package {
        uint packageIndex;
        bytes32 root;
        bytes32[] leaves;
        uint createTime;
        uint packTime;
    }

    function addMsgHash(bytes32 msgHash, uint toChainId) external;

    function pack() external;

    function getPackage(uint packageIndex) external view returns (Package memory);

    function getPendingPackage() external view returns (Package memory);
}
```

Let:

- `Package`: Collects cross-chain messages within a certain period and packs them into a single package.
  - `packageIndex`: The index of the package, starting from 0.
  - `root`: The root generated by the MerkleTree from the `leaves`, representing the packed package.
  - `leaves`: Each leaf represents a cross-chain message, and it is a hash calculated from `msgHash`, `sender`, and `toChainId`.
    - `msgHash`: The hash of the message, passed in from an external contract.
    - `sender`: The address of the external contract, no need to pass it in explicitly.
    - `toChainId`: The chain ID of the target chain, passed in from an external contract.
  - `createTime`: The timestamp when the package started collecting messages. It is also the timestamp when the previous package was packed.
  - `packTime`: The timestamp when the package was packed. After packing, no more leaves can be added.
- `addMsgHash()`: The external contract sends the hash of cross-chain messages to the SendPort.
- `pack()`: Manually triggers the packing process. Typically, it is automatically triggered when the last submitter submits his message. If waiting for the last submitter takes too long, the packing process can be manually triggered.
- `getPackage()`: Retrieves each package in the SendPort, including both packed and pending packages.
- `getPendingPackage()`: Retrieves the pending package in the SendPort.


### `IReceivePort` Interface

```solidity
pragma solidity ^0.8.0;

interface IReceivePort {
    event PackageReceived(uint indexed fromChainId, uint indexed packageIndex, bytes32 root);

    struct Package {
        uint fromChainId;
        uint packageIndex;
        bytes32 root;
    }

    function receivePackages(Package[] calldata packages) external;

    function getRoot(uint fromChainId, uint packageIndex) external view returns (bytes32);

    function verify(
        uint fromChainId,
        uint packageIndex,
        bytes32[] memory proof,
        bytes32 msgHash,
        address sender
    ) external view returns (bool);
}
```

Let:

- `Package`: Collects cross-chain messages within a certain period and bundles them into a single package.
  - `fromChainId`: The chain from which the package originates.
  - `packageIndex`: The index of the package, starting from 0.
  - `root`: The root generated by the MerkleTree from the `leaves`, representing the packed package.
- `receivePackages()`: Receive multiple roots from different source chains&apos;s SendPort.
- `getRoot()`: Retrieves a specific root from a particular chain.
- `verify()`: Verifies if the message on the source chain was sent by the sender.


## Rationale

The traditional approach involves using a push method, as depicted in the following diagram:

![](/EIPs/assets/eip-7533/2.png)

If there are 6 chains, each chain needs to push to the other 5 chains, resulting in the requirement of 30 cross-chain bridges, as shown in the diagram below:

![](/EIPs/assets/eip-7533/3.png)

When N chains require cross-chain communication with each other, the number of cross-chain bridges needed is calculated as: num = N * (N - 1).

Using the pull approach allows the batch of cross-chain messages from 5 chains into 1 transaction, significantly reducing the number of required cross-chain bridges, as illustrated in the following diagram:

![](/EIPs/assets/eip-7533/4.png)

If each chain pulls messages from the other 5 chains onto its own chain, only 6 cross-chain bridges are necessary. For N chains requiring cross-chain communication, the number of cross-chain bridges needed is: num = N.

Thus, the pull approach can greatly reduce the number of cross-chain bridges.

The MerkleTree data structure efficiently compresses the size of cross-chain messages. Regardless of the number of cross-chain messages, they can be compressed into a single root, represented as a byte32 value. The package carrier only needs to transport the root, resulting in low gas cost.


## Backwards Compatibility

This EIP does not change the consensus layer, so there are no backwards compatibility issues for Ethereum as a whole. 

This EIP does not change other ERC standars, so there are no backwards compatibility issues for Ethereum applications. 


## Reference Implementation

Below is an example contract for a cross-chain bridge:

### `SendPort.sol`

```solidity
pragma solidity ^0.8.0;

import &quot;./ISendPort.sol&quot;;

contract SendPort is ISendPort {
    uint public constant PACK_INTERVAL = 6000;
    uint public constant MAX_PACKAGE_MESSAGES = 100;

    uint public pendingIndex = 0;

    mapping(uint =&gt; Package) public packages;

    constructor() {
        packages[0] = Package(0, bytes32(0), new bytes32[](0), block.timestamp, 0);
    }

    function addMsgHash(bytes32 msgHash, uint toChainId) public {
        bytes32 leaf = keccak256(
            abi.encodePacked(msgHash, msg.sender, toChainId)
        );
        Package storage pendingPackage = packages[pendingIndex];
        pendingPackage.leaves.push(leaf);

        emit MsgHashAdded(pendingPackage.packageIndex, msg.sender, msgHash, toChainId, leaf);

        if (pendingPackage.leaves.length &gt;= MAX_PACKAGE_MESSAGES) {
            console.log(&quot;MAX_PACKAGE_MESSAGES&quot;, pendingPackage.leaves.length);
            _pack();
            return;
        }

        // console.log(&quot;block.timestamp&quot;, block.timestamp);
        if (pendingPackage.createTime + PACK_INTERVAL &lt;= block.timestamp) {
            console.log(&quot;PACK_INTERVAL&quot;, pendingPackage.createTime, block.timestamp);
            _pack();
        }
    }

    function pack() public {
        require(packages[pendingIndex].createTime + PACK_INTERVAL &lt;= block.timestamp, &quot;SendPort::pack: pack interval too short&quot;);

       _pack();
    }

    function getPackage(uint packageIndex) public view returns (Package memory) {
        return packages[packageIndex];
    }

    function getPendingPackage() public view returns (Package memory) {
        return packages[pendingIndex];
    }

    function _pack() internal {
        Package storage pendingPackage = packages[pendingIndex];
        bytes32[] memory _leaves = pendingPackage.leaves;
        while (_leaves.length &gt; 1) {
            _leaves = _computeLeaves(_leaves);
        }
        pendingPackage.root = _leaves[0];
        pendingPackage.packTime = block.timestamp;

        emit Packed(pendingPackage.packageIndex, pendingPackage.packTime, pendingPackage.root);

        pendingIndex = pendingPackage.packageIndex + 1;
        packages[pendingIndex] = Package(pendingIndex, bytes32(0), new bytes32[](0), pendingPackage.packTime, 0);
    }

    function _computeLeaves(bytes32[] memory _leaves) pure internal returns (bytes32[] memory _nextLeaves) {
        if (_leaves.length % 2 == 0) {
            _nextLeaves = new bytes32[](_leaves.length / 2);
            bytes32 computedHash;
            for (uint i = 0; i + 1 &lt; _leaves.length; i += 2) {
                computedHash = _hashPair(_leaves[i], _leaves[i + 1]);
                _nextLeaves[i / 2] = computedHash;
            }

        } else {
            bytes32 lastLeaf = _leaves[_leaves.length - 1];
            _nextLeaves = new bytes32[]((_leaves.length / 2 + 1));
            bytes32 computedHash;
            for (uint i = 0; i + 1 &lt; _leaves.length; i += 2) {
                computedHash = _hashPair(_leaves[i], _leaves[i + 1]);
                _nextLeaves[i / 2] = computedHash;
            }
            _nextLeaves[_nextLeaves.length - 1] = lastLeaf;
        }
    }

    function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
        return a &lt; b ? _efficientHash(a, b) : _efficientHash(b, a);
    }

    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}
```

External featrues:

- `PACK_INTERVAL`: The minimum time interval between two consecutive packing operations. If this interval is exceeded, a new packing operation can be initiated.
- `MAX_PACKAGE_MESSAGES`: Once `MAX_PACKAGE_MESSAGES` messages are collected, a packing operation is triggered immediately. This takes precedence over the `PACK_INTERVAL` setting.

### `ReceivePort.sol`

```solidity
pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/access/Ownable.sol&quot;;
import &quot;./IReceivePort.sol&quot;;

abstract contract ReceivePort is IReceivePort, Ownable {

    //fromChainId =&gt; packageIndex =&gt; root
    mapping(uint =&gt; mapping(uint =&gt; bytes32)) public roots;

    constructor() {}

    function receivePackages(Package[] calldata packages) public onlyOwner {
        for (uint i = 0; i &lt; packages.length; i++) {
            Package calldata p = packages[i];
            require(roots[p.fromChainId][p.packageIndex] == bytes32(0), &quot;ReceivePort::receivePackages: package already exist&quot;);
            roots[p.fromChainId][p.packageIndex] = p.root;

            emit PackageReceived(p.fromChainId, p.packageIndex, p.root);
        }
    }

    function getRoot(uint fromChainId, uint packageIndex) public view returns (bytes32) {
        return roots[fromChainId][packageIndex];
    }

    function verify(
        uint fromChainId,
        uint packageIndex,
        bytes32[] memory proof,
        bytes32 msgHash,
        address sender
    ) public view returns (bool) {
        bytes32 leaf = keccak256(
            abi.encodePacked(msgHash, sender, block.chainid)
        );
        return _processProof(proof, leaf) == roots[fromChainId][packageIndex];
    }

    function _processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i &lt; proof.length; i++) {
            computedHash = _hashPair(computedHash, proof[i]);
        }
        return computedHash;
    }

    function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
        return a &lt; b ? _efficientHash(a, b) : _efficientHash(b, a);
    }

    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}
```

### `BridgeExample.sol`

```solidity
pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/token/ERC20/IERC20.sol&quot;;
import &quot;@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol&quot;;
import &quot;./ISendPort.sol&quot;;
import &quot;./ReceivePort.sol&quot;;

contract BridgeExample is ReceivePort {
    using SafeERC20 for IERC20;

    ISendPort public sendPort;

    mapping(bytes32 =&gt; bool) public usedMsgHashes;

    mapping(uint =&gt; address) public trustBridges;

    mapping(address =&gt; address) public crossPairs;

    constructor(address sendPortAddr) {
        sendPort = ISendPort(sendPortAddr);
    }

    function setTrustBridge(uint chainId, address bridge) public onlyOwner {
        trustBridges[chainId] = bridge;
    }

    function setCrossPair(address fromTokenAddr, address toTokenAddr) public onlyOwner {
        crossPairs[fromTokenAddr] = toTokenAddr;
    }

    function getLeaves(uint packageIndex, uint start, uint num) view public returns(bytes32[] memory) {
        ISendPort.Package memory p = sendPort.getPackage(packageIndex);
        bytes32[] memory result = new bytes32[](num);
        for (uint i = 0; i &lt; p.leaves.length &amp;&amp; i &lt; num; i++) {
            result[i] = p.leaves[i + start];
        }
        return result;
    }

    function transferTo(
        uint toChainId,
        address fromTokenAddr,
        uint amount,
        address receiver
    ) public {
        bytes32 msgHash = keccak256(
            abi.encodePacked(toChainId, fromTokenAddr, amount, receiver)
        );
        sendPort.addMsgHash(msgHash, toChainId);

        IERC20(fromTokenAddr).safeTransferFrom(msg.sender, address(this), amount);
    }

    function transferFrom(
        uint fromChainId,
        uint packageIndex,
        bytes32[] memory proof,
        address fromTokenAddr,
        uint amount,
        address receiver
    ) public {
        bytes32 msgHash = keccak256(
            abi.encodePacked(block.chainid, fromTokenAddr, amount, receiver)
        );

        require(!usedMsgHashes[msgHash], &quot;transferFrom: Used msgHash&quot;);

        require(
            verify(
                fromChainId,
                packageIndex,
                proof,
                msgHash,
                trustBridges[fromChainId]
            ),
            &quot;transferFrom: verify failed&quot;
        );

        usedMsgHashes[msgHash] = true;

        address toTokenAddr = crossPairs[fromTokenAddr];
        require(toTokenAddr != address(0), &quot;transferFrom: fromTokenAddr is not crossPair&quot;);
        IERC20(toTokenAddr).safeTransfer(receiver, amount);
    }
}
```


## Security Considerations

Regarding competition and double spending among cross-chain bridges:

The `SendPort` is responsible for one task: packing the messages to be cross-chain transferred. The transmission and verification of messages are implemented independently by each cross-chain bridge project. The objective is to ensure that the cross-chain messages obtained by different cross-chain bridges on the source chain are consistent. Therefore, there is no need for competition among cross-chain bridges for the right to transport or validate roots. Each bridge operates independently. If a cross-chain bridge has bugs in its implementation, it poses a risk to itself but does not affect other cross-chain bridges.

**Suggestions**:

1. Don&apos;t let `IReceivePort.receivePackages()` be called by anyone.
2. When performing verification, store the verified `msgHash` to avoid double spending during subsequent verifications.
3. Don&apos;t trust all senders in the MerkleTree.

Regarding the forgery of cross-chain messages:

Since the `SendPort` is a public contract without usage restrictions, anyone can send arbitrary cross-chain messages to it. The `SendPort` includes the `msg.sender` in the packing process. If a hacker attempts to forge a cross-chain message, the hacker&apos;s address will be included in the packing along with the forged message. During verification, the hacker&apos;s address can be identified. This is why it is suggested to not trust all senders in the MerkleTree.

Regarding the sequnce of messages:

While the `SendPort` sorts received cross-chain messages by time, there is no guarantee of sequnce during verification. For example, if a user performs a cross-chain transfer of 10 ETH and then 20 USDT, on the target chain, he may withdraw the 20 USDT first and then the 10 ETH, or vice versa. The specific sequnce depends on the implementation of the `IReceivePort`.


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 11 Oct 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7533</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7533</guid>
      </item>
    
      <item>
        <title>Native Asset ERC-4626 Tokenized Vault</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7535-eth-native-asset-tokenized-vault/16068</comments>
        
        <description>## Abstract

This standard is an extension of the [ERC-4626](/EIPs/EIPS/eip-4626) spec with an identical interface and behavioral overrides for handling Ether or any native asset as the underlying.

## Motivation

A standard for tokenized ETH Vaults has the same benefits as [ERC-4626](/EIPs/EIPS/eip-4626), particularly in the case of Liquid Staking Tokens, (i.e. fungible [ERC-20](/EIPs/EIPS/eip-20) wrappers around ETH staking). 

Maintaining the same exact interface as ERC-4626 further amplifies the benefits as the standard will be maximally compatible with existing ERC-4626 tooling and protocols.

## Specification

All [ERC-7535](/EIPs/EIPS/eip-7535) tokenized Vaults MUST implement ERC-4626 (and by extension ERC-20) with behavioral overrides for the methods `asset`, `deposit`, and `mint` specified below.

### ERC-4626 Breaking Changes

* Any `assets` quantity refers to wei of Ether rather than ERC-20 balances.
* Any ERC-20 `transfer` calls are replaced by Ether transfer (`send` or `call`)
* Any ERC-20 `transferFrom` approval flows for `asset` are not implemented
* `deposit` and `mint` have state mutability `payable`
* `deposit` uses `msg.value` as the primary input and MAY ignore `assets`

### Methods

#### asset

MUST return `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` per [ERC-7528](/EIPs/EIPS/eip-7528).

```yaml
- name: asset
  type: function
  stateMutability: view

  inputs: []

  outputs:
    - name: assetTokenAddress
      type: address
```

#### deposit

Mints `shares` Vault shares to `receiver` by depositing exactly `msg.value` of Ether.

MUST have state mutability of `payable`.

MUST use `msg.value` as the primary input parameter for calculating the `shares` output. I.e. MAY ignore `assets` parameter as an input.

MUST emit the `Deposit` event.

MUST revert if all of `msg.value` cannot be deposited (due to deposit limit being reached, slippage, etc).

```yaml
- name: deposit
  type: function
  stateMutability: payable

  inputs:
    - name: assets
      type: uint256
    - name: receiver
      type: address

  outputs:
    - name: shares
      type: uint256
```

#### mint

Mints exactly `shares` Vault shares to `receiver` by depositing `assets` of ETH.

MUST have state mutability of `payable`.

MUST emit the `Deposit` event.

MUST revert if all of `shares` cannot be minted (due to deposit limit being reached, slippage, the user not sending a large enough `msg.value` of Ether to the Vault contract, etc).

```yaml
- name: mint
  type: function
  stateMutability: payable

  inputs:
    - name: shares
      type: uint256
    - name: receiver
      type: address

  outputs:
    - name: assets
      type: uint256
```


### Events

The event usage MUST be identical to ERC-4626.

### Wrapped ETH

Any ERC-4626 Vault that uses a Wrapped ETH ERC-20 as the `asset` MUST NOT implement ERC-7535. ERC-7535 only applies to native ETH.

## Rationale

This standard was designed to maximize compatibility with ERC-4626 while minimizing additional opinionated details on the interface. Examples of this decision rationale are described below:

* maintaining the redundant `assets` input to the `deposit` function while making its usage optional
* not enforcing a relationship between `msg.value` and `assets` in a `mint` call
* not enforcing any behaviors or lack thereof for `fallback`/`__default__` methods, payability on additional vault functions, or handling ETH forcibly sent to the contract

All breaking implementation level changes with ERC-4626 are purely to accomodate for the usage of Ether or any native asset instead of an ERC-20 token.

### Allowing assets Parameter to be Ignored in a Deposit
`msg.value` must always be passed anyway to fund a `deposit`, therefore it may as well be treated as the primary input number. Allowing `assets` to be used either forces a strict equality and extra unnecessary gas overhead for redundancy, or allows different values which could cause footguns and undefined behavior.

The last option which could work is to require that `assets` MUST be 0, but this still requires gas to enforce at the implementation level and can more easily be left unspecified, as the input is functionally ignorable in the spec as written.

### Allowing msg.value to Not Equal assets Output in a Mint
There may be many cases where a user deposits slightly too much Ether in a `mint` call. In these cases, enforcing `msg.value` to equal `assets` would cause unnecessary reversions. It is up to the vault implementer to decide whether to refund or absorb any excess Ether, and up to depositors to deposit as close to the exact amount as possible.

## Backwards Compatibility

ERC-7535 is fully backward compatible with ERC-4626 at the function interface level. Certain implementation behaviors are different due to the fact that ETH is not ERC-20 compliant, such as the priority of `msg.value` over `assets`.

It has no known compatibility issues with other standards.

## Security Considerations

In addition to all security considerations of [ERC-4626](/EIPs/EIPS/eip-4626), there are security implications of having ETH as the Vault asset.

### `call` vs `send`

Contracts should take care when using `call` to transfer ETH, as this allows additional reentrancy vulnerabilities and arbitrary code execution beyond what is possible with trusted ERC-20 tokens.

It is safer to simply `send` ETH with a small gas stipend. 

Implementers should take extra precautions when deciding how to transfer ETH.

### Forceful ETH transfers

ETH can be forced into any Vault through the `SELFDESTRUCT` opcode. Implementers should validate that this does not disrupt Vault accounting in any way.

Similarly, any additional `payable` methods should be checked to ensure they do not disrupt Vault accounting.

### Wrapped ETH

Smart contract systems which implement ERC-4626 should consider only supporting ERC-20 underlying assets, and default to using a Wrapped ETH ERC-20 instead of implementing ERC-7535 for handling ETH.

The subtle differences between ERC-4626 and ERC-7535 can introduce code fragmentation and security concerns.

Cleaner use cases for ERC-7535 are ETH exclusive, such as Wrapped ETH and Liquid Staking Tokens.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 12 Oct 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7535</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7535</guid>
      </item>
    
      <item>
        <title>Multiplicative Tokens</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/multiplicative-tokens/16149</comments>
        
        <description>## Abstract

This EIP extends [ERC-1046](/EIPs/EIPS/eip-1046)-compatible token types (notably, [ERC-20](/EIPs/EIPS/eip-20) and [ERC-1155](/EIPs/EIPS/eip-1155) by introducing a `multiplier` field to the metadata schema, altering how user-facing balances are displayed.

## Motivation

Many projects necessitate the creation of various types of tokens, both fungible and non-fungible. While certain standards are ideal for this purpose, they lack support for fractional tokens. Additionally, some tokens may require built-in inflation or deflation mechanisms, or may wish to allow transfers in unconventional increments, such as `0.5`.

## Specification

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

The `MultiplierMetadata` interface MUST be implemented in the resolved ERC-1046 `tokenURI` of tokens that use a `multiplier`:

```typescript
interface MultiplierMetadata {
    /**
     * The positive multiplier for generating user-facing representation.
     * Defaults to 1 if undefined.
     * This is an EXACT VALUE, base 10. Beware of floating-point error!
     **/
    multiplier: string | undefined;

    /**
     * Decimals are no longer supported
     **/
    decimals: never;
}
```

Token contracts MUST NOT have a method named `decimals` if a `multiplier` is used.

## Rationale

Employing strings for numerical representation offers enhanced precision when needed. The use of a multiplier instead of decimals facilitates increments other than powers of 10, and ensures seamless handling of inflation or deflation. Utilizing ERC-1046 promotes gas efficiency in the majority of cases.

## Backwards Compatibility

This EIP is incompatible with any method named `decimals` in ERC-1046-compatible token standards or the ERC-1046 `decimals` field.

## Security Considerations

Improper handling of the `multiplier` field may lead to rounding errors, potentially exploitable by malicious actors. Contracts MUST process multipliers accurately to avoid such issues. The multiplier MUST be positive (‘0’ is not positive) to avert display issues. Particularly large or small multipliers MAY pose display challenges, yet wallets SHOULD endeavor to display the full number without causing UI/UX or additional security issues.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 18 Oct 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7538</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7538</guid>
      </item>
    
      <item>
        <title>Asynchronous ERC-4626 Tokenized Vaults</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7540-asynchronous-erc-4626-tokenized-vaults/16153</comments>
        
        <description>## Abstract

The following standard extends [ERC-4626](/EIPs/EIPS/eip-4626) by adding support for asynchronous deposit and redemption flows. The async flows are called Requests.

New methods are added to asynchronously Request a deposit or redemption, and view the status of the Request. The existing `deposit`, `mint`, `withdraw`, and `redeem` ERC-4626 methods are used for executing Claimable Requests. 

Implementations can choose whether to add asynchronous flows for deposits, redemptions, or both. 

## Motivation

The ERC-4626 Tokenized Vaults standard has helped to make yield-bearing tokens more composable across decentralized finance. The standard is optimized for atomic deposits and redemptions up to a limit. If the limit is reached, no new deposits or redemptions can be submitted.

This limitation does not work well for any smart contract system with asynchronous actions or delays as a prerequisite for interfacing with the Vault (e.g. real-world asset protocols, undercollateralized lending protocols, cross-chain lending protocols, liquid staking tokens, or insurance safety modules). 

This standard expands the utility of ERC-4626 Vaults for asynchronous use cases. The existing Vault interface (`deposit`/`withdraw`/`mint`/`redeem`) is fully utilized to claim asynchronous Requests.

## Specification

### Definitions:

The existing definitions from [ERC-4626](/EIPs/EIPS/eip-4626) apply. In addition, this spec defines:

- Request: a request to enter (`requestDeposit`) or exit (`requestRedeem`) the Vault
- Pending: the state where a Request has been made but is not yet Claimable
- Claimable: the state where a Request is processed by the Vault enabling the user to claim corresponding `shares` (for async deposit) or `assets` (for async redeem)
- Claimed: the state where a Request is finalized by the user and the user receives the output token (e.g. `shares` for a deposit Request)
- Claim function: the corresponding Vault method to bring a Request to Claimed state (e.g. `deposit` or `mint` claims `shares` from `requestDeposit`). Lowercase claim always describes the verb action of calling a Claim function.
- asynchronous deposit Vault: a Vault that implements asynchronous Requests for deposit flows
- asynchronous redemption Vault: a Vault that implements asynchronous Requests for redemption flows
- fully asynchronous Vault: a Vault that implements asynchronous Requests for both deposit and redemption flows
- controller: owner of the Request, who can manage any actions related to the Request including claiming the `assets` or `shares`
- operator: an account that can manage Requests on behalf of another account.

### Request Flows

[ERC-7540 Vaults](/EIPs/EIPS/eip-7540) MUST implement one or both of asynchronous deposit and redemption Request flows. If either flow is not implemented in a Request pattern, it MUST use the ERC-4626 standard synchronous interaction pattern. 

All ERC-7540 asynchronous tokenized Vaults MUST implement ERC-4626 with overrides for certain behavior described below.

Asynchronous deposit Vaults MUST override the ERC-4626 specification as follows:

1. The `deposit` and `mint` methods do not transfer `assets` to the Vault, because this already happened on `requestDeposit`.
2. `previewDeposit` and `previewMint` MUST revert for all callers and inputs.

Asynchronous redeem Vaults MUST override the ERC-4626 specification as follows:

1. The `redeem` and `withdraw` methods do not transfer `shares` to the Vault, because this already happened on `requestRedeem`. 
2. The `owner` field of `redeem` and `withdraw` SHOULD be renamed to `controller`, and the controller MUST be `msg.sender` unless the `controller` has approved the `msg.sender` as an operator.
3. `previewRedeem` and `previewWithdraw` MUST revert for all callers and inputs.

### Request Lifecycle

After submission, Requests go through Pending, Claimable, and Claimed stages. An example lifecycle for a deposit Request is visualized in the table below.

| **State**   | **User**                         | **Vault** |
|-------------|---------------------------------|-----------|
| Pending     | `requestDeposit(assets, controller, owner)` | `asset.transferFrom(owner, vault, assets)`; `pendingDepositRequest[controller] += assets` |
| Claimable   |                                 | *Internal Request fulfillment*:  `pendingDepositRequest[controller] -= assets`; `claimableDepositRequest[controller] += assets` |
| Claimed     | `deposit(assets, receiver, controller)` | `claimableDepositRequest[controller] -= assets`; `vault.balanceOf[receiver] += shares` |

Note that `maxDeposit` increases and decreases in sync with `claimableDepositRequest`.

Requests MUST NOT skip or otherwise short-circuit the Claim state. In other words, to initiate and claim a Request, a user MUST call both request* and the corresponding Claim function separately, even in the same block. Vaults MUST NOT &quot;push&quot; tokens onto the user after a Request, users MUST &quot;pull&quot; the tokens via the Claim function.

For asynchronous Vaults, the exchange rate between `shares` and `assets` including fees and yield is up to the Vault implementation. In other words, pending redemption Requests MAY NOT be yield-bearing and MAY NOT have a fixed exchange rate.

### Request Ids
The request ID (`requestId`) of a request is returned by the corresponding `requestDeposit` and `requestRedeem` functions.

Multiple requests may have the same `requestId`, so a given Request is discriminated by both the `requestId` and the `controller`. 

Requests of the same `requestId` MUST be fungible with each other (except in the special case `requestId == 0` described below). I.e. all Requests with the same `requestId` MUST transition from Pending to Claimable at the same time and receive the same exchange rate between `assets` and `shares`. If a Request with `requestId != 0` becomes partially claimable, all requests of the same `requestId` MUST become claimable at the same pro-rata rate.

There are no assumptions or requirements of requests with different `requestId`. I.e. they MAY transition to Claimable at different times and exchange rates with no ordering or correlation enforced in any way.

When `requestId==0`, the Vault MUST use purely the `controller` to discriminate the request state. The Pending and Claimable state of multiple requests from the same `controller` would be aggregated. If a Vault returns `0` for the `requestId` of any request, it MUST return `0` for all requests.

### Methods

#### requestDeposit

Transfers `assets` from `owner` into the Vault and submits a Request for asynchronous `deposit`. This places the Request in Pending state, with a corresponding increase in `pendingDepositRequest` for the amount `assets`. 

The output `requestId` is used to partially discriminate the request along with the `controller`. See [Request Ids](#request-ids) section for more info.

When the Request is Claimable, `claimableDepositRequest` will be increased for the `controller`. `deposit` or `mint` can subsequently be called by `controller` to receive `shares`. A Request MAY transition straight to Claimable state but MUST NOT skip the Claimable state.

The `shares` that will be received on `deposit` or `mint` MAY NOT be equivalent to the value of `convertToShares(assets)` at the time of Request, as the price can change between Request and Claim.

MUST support [ERC-20](/EIPs/EIPS/eip-20) `approve` / `transferFrom` on `asset` as a deposit Request flow.

`owner` MUST equal `msg.sender` unless the `owner` has approved the `msg.sender` as an operator.

MUST revert if all of `assets` cannot be requested for `deposit`/`mint` (due to deposit limit being reached, slippage, the user not approving enough underlying tokens to the Vault contract, etc).

Note that most implementations will require pre-approval of the Vault with the Vault&apos;s underlying `asset` token.

MUST emit the `DepositRequest` event.

```yaml
- name: requestDeposit
  type: function
  stateMutability: nonpayable

  inputs:
    - name: assets
      type: uint256
    - name: controller
      type: address
    - name: owner
      type: address
  outputs:
    - name: requestId
      type: uint256
```

#### pendingDepositRequest

The amount of requested `assets` in Pending state for the `controller` with the given `requestId` to `deposit` or `mint`.

MUST NOT include any `assets` in Claimable state for `deposit` or `mint`.

MUST NOT show any variations depending on the caller.

MUST NOT revert unless due to integer overflow caused by an unreasonably large input.

```yaml
- name: pendingDepositRequest
  type: function
  stateMutability: view

  inputs:
    - name: requestId
      type: uint256
    - name: controller
      type: address

  outputs:
    - name: assets
      type: uint256
```

#### claimableDepositRequest

The amount of requested `assets` in Claimable state for the `controller` with the given `requestId` to `deposit` or `mint`.

MUST NOT include any `assets` in Pending state for `deposit` or `mint`.

MUST NOT show any variations depending on the caller.

MUST NOT revert unless due to integer overflow caused by an unreasonably large input.

```yaml
- name: claimableDepositRequest
  type: function
  stateMutability: view

  inputs:
    - name: requestId
      type: uint256
    - name: controller
      type: address

  outputs:
    - name: assets
      type: uint256
```

#### requestRedeem

Assumes control of `shares` from `owner` and submits a Request for asynchronous `redeem`. This places the Request in Pending state, with a corresponding increase in `pendingRedeemRequest` for the amount `shares`. 

The output `requestId` is used to discriminate the request along with the `controller`. See [Request Ids](#request-ids) section for more info.

`shares` MAY be temporarily locked in the Vault until the Claimable or Claimed state for accounting purposes, or they MAY be burned immediately upon `requestRedeem`. 

In either case, the `shares` MUST be removed from the custody of `owner` upon `requestRedeem` and burned by the time the request is Claimed.

Redeem Request approval of `shares` for a `msg.sender` NOT equal to `owner` may come either from ERC-20 approval over the `shares` of `owner` or if the `owner` has approved the `msg.sender` as an operator. This MUST be consistent with similar behaviour pointed out in [ERC-6909](/EIPs/EIPS/eip-6909), within &quot;Approvals and Operators&quot; section: &quot;In accordance with the transferFrom method, spenders with operator permission are not subject to allowance restrictions, spenders with infinite approvals SHOULD NOT have their allowance deducted on delegated transfers, but spenders with non-infinite approvals MUST have their balance deducted on delegated transfers.&quot;

When the Request is Claimable, `claimableRedeemRequest` will be increased for the `controller`. `redeem` or `withdraw` can subsequently be called by `controller` to receive `assets`. A Request MAY transition straight to Claimable state but MUST NOT skip the Claimable state.

The `assets` that will be received on `redeem` or `withdraw` MAY NOT be equivalent to the value of `convertToAssets(shares)` at the time of Request, as the price can change between Pending and Claimed.

MUST revert if all of `shares` cannot be requested for `redeem` / `withdraw` (due to withdrawal limit being reached, slippage, the owner not having enough shares, etc).

MUST emit the `RedeemRequest` event.

```yaml
- name: requestRedeem
  type: function
  stateMutability: nonpayable

  inputs:
    - name: shares
      type: uint256
    - name: controller
      type: address
    - name: owner
      type: address
  outputs:
    - name: requestId
    - type: uint256
```

#### pendingRedeemRequest

The amount of requested `shares` in Pending state for the `controller` with the given `requestId` to `redeem` or `withdraw`.

MUST NOT include any `shares` in Claimable state for `redeem` or `withdraw`.

MUST NOT show any variations depending on the caller.

MUST NOT revert unless due to integer overflow caused by an unreasonably large input.

```yaml
- name: pendingRedeemRequest
  type: function
  stateMutability: view

  inputs:
    - name: requestId
      type: uint256
    - name: controller
      type: address

  outputs:
    - name: shares
      type: uint256
```

#### claimableRedeemRequest

The amount of requested `shares` in Claimable state for the `controller` with the given `requestId` to `redeem` or `withdraw`.

MUST NOT include any `shares` in Pending state for `redeem` or `withdraw`.

MUST NOT show any variations depending on the caller.

MUST NOT revert unless due to integer overflow caused by an unreasonably large input.

```yaml
- name: claimableRedeemRequest
  type: function
  stateMutability: view

  inputs:
    - name: requestId
      type: uint256
    - name: controller
      type: address

  outputs:
    - name: shares
      type: uint256
```

#### `isOperator`

Returns `true` if the `operator` is approved as an operator for a `controller`.

```yaml
- name: isOperator
  type: function
  stateMutability: view

  inputs:
    - name: controller
      type: address
    - name: operator
      type: address

  outputs:
    - name: status
      type: bool
```

#### `setOperator`

Grants or revokes permissions for `operator` to manage Requests on behalf of the `msg.sender`.

MUST set the operator status to the `approved` value.

MUST log the `OperatorSet` event.

MUST return True.

```yaml
- name: setOperator
  type: function
  stateMutability: nonpayable

  inputs:
    - name: operator
      type: address
    - name: approved
      type: bool

  outputs:
    - name: success
      type: bool
```

#### `deposit` and `mint` overloaded methods

Implementations MUST support an additional overloaded `deposit` and `mint` method on the specification from [ERC-4626](/EIPs/EIPS/eip-4626), with an additional `controller` input of type `address`:

- `deposit(uint256 assets, address receiver, address controller)`
- `mint(uint256 shares, address receiver, address controller)`

Calls MUST revert unless `msg.sender` is either equal to `controller` or an operator approved by `controller`.

The `controller` field is used to discriminate the Request for which the `assets` should be claimed in the case where `msg.sender` is NOT `controller`.

When the `Deposit` event is emitted, the first parameter MUST be the `controller`, and the second parameter MUST be the `receiver`.

### Events

#### DepositRequest

`owner` has locked `assets` in the Vault to Request a deposit with request ID `requestId`. `controller` controls this Request. `sender` is the caller of the `requestDeposit` which may not be equal to the `owner`.

MUST be emitted when a deposit Request is submitted using the `requestDeposit` method.

```yaml
- name: DepositRequest
  type: event

  inputs:
    - name: controller
      indexed: true
      type: address
    - name: owner
      indexed: true
      type: address
    - name: requestId
      indexed: true
      type: uint256
    - name: sender
      indexed: false
      type: address
    - name: assets
      indexed: false
      type: uint256
```

#### RedeemRequest

`sender` has locked `shares`, owned by `owner`, in the Vault to Request a redemption. `controller` controls this Request, but is not necessarily the `owner`.

MUST be emitted when a redemption Request is submitted using the `requestRedeem` method.

```yaml
- name: RedeemRequest
  type: event

  inputs:
    - name: controller
      indexed: true
      type: address
    - name: owner
      indexed: true
      type: address
    - name: requestId
      indexed: true
      type: uint256
    - name: sender
      indexed: false
      type: address
    - name: shares
      indexed: false
      type: uint256
```

#### `OperatorSet`

The `controller` has set the `approved` status to an `operator`.

MUST be logged when the operator status is set.

MAY be logged when the operator status is set to the same status it was before the current call.

```yaml
- name: OperatorSet
  type: event

  inputs:
    - name: controller
      indexed: true
      type: address
    - name: operator
      indexed: true
      type: address
    - name: approved
      indexed: false
      type: bool
```

### [ERC-165](/EIPs/EIPS/eip-165) support

Smart contracts implementing this Vault standard MUST implement the [ERC-165](/EIPs/EIPS/eip-165) `supportsInterface` function.

All asynchronous Vaults MUST return the constant value `true` if either `0xe3bc4e65` (representing the operator methods that all ERC-7540 Vaults implement) or `0x2f0a18c5` (representing the [ERC-7575](/EIPs/EIPS/eip-7575) interface) is passed through the `interfaceID` argument.

Asynchronous deposit Vaults MUST return the constant value `true` if `0xce3bbe50` is passed through the `interfaceID` argument.

Asynchronous redemption Vaults MUST return the constant value `true` if `0x620ee8e4` is passed through the `interfaceID` argument.

### [ERC-7575](/EIPs/EIPS/eip-7575) support

Smart contracts implementing this Vault standard MUST implement the [ERC-7575](/EIPs/EIPS/eip-7575) standard (in particular the `share` method). 

## Rationale

### Including Request IDs but not including a Claim by ID method
Requests in an Asynchronous Vault have properties of NFTs or Semi-Fungible tokens due to their asynchronicity. However, trying to pigeonhole all ERC-7540 Vaults into supporting [ERC-721](./eip-721) or [ERC-1155](./eip-1155) for Requests would create too much interface bloat. 

Using both an id and address to discriminate Requests allows for any of these use cases to be developed at an external layer without adding too much complexity to the core interface.

Certain Vaults, especially `requestId==0` cases, benefit from using the underlying [ERC-4626](./eip-4626) methods for claiming because there is no discrimination at the `requestId` level. This standard is written primarily with those use cases in mind. A future standard can optimize for nonzero request ID with support for claiming and transferring requests discriminated also with a `requestId`.

### Symmetry and Non-inclusion of requestWithdraw and requestMint

In ERC-4626, the spec was written to be fully symmetrical with respect to converting `assets` and `shares` by including deposit/withdraw and mint/redeem.

Due to the nature of Requests, asynchronous Vaults can only operate with certainty on the quantity that is fully known at the time of the Request (`assets` for `deposit` and `shares` for `redeem`). Therefore the deposit Request flow cannot work with a `mint` call, because the amount of `assets` for the requested `shares` amount may fluctuate before the fulfillment of the Request. Likewise, the redemption Request flow cannot work with a `withdraw` call.

### Optionality of Flows

Certain use cases are only asynchronous on one side of the deposit or redeem Request flow. A good example of an asynchronous redemption Vault is a liquid staking token. The unstaking period necessitates support for asynchronous withdrawals, however, deposits can be fully synchronous.

### Non-inclusion of a Request Cancelation Flow

In many cases, canceling a Request may not be straightforward or even technically feasible. The state transition of cancelations could be synchronous or asynchronous, and the way to claim a cancelation interfaces with the remaining Vault functionality in complex ways.

A separate EIP should be developed to standardize the behavior of cancelling a pending Request. Defining the cancel flow is still important for certain classes of use cases for which the fulfillment of a Request can take a considerable amount of time.

### Request Implementation Flexibility

The standard is flexible enough to support a wide range of interaction patterns for Request flows. Pending Requests can be handled via internal accounting, globally or on per-user levels, use ERC-20 or [ERC-721](/EIPs/EIPS/eip-721), etc.

Likewise yield on redemption Requests can accrue or not, and the exchange rate of any Request may be fixed or variable depending on the implementation.

### Not Allowing Short-circuiting for Claims

If claims can short-circuit, this creates ambiguity for integrators and complicates the interface with overloaded behavior on Request functions.

An example of a short-circuiting Request flow could be as follows: user triggers a Request which enters Pending state. When the Vault fulfills the Request, the corresponding `assets/shares` are pushed straight to the user. This requires only 1 step on the user&apos;s behalf.

This approach has a few issues:
- cost/lack of scalability: as the number of vault users grows it can become intractably expensive to offload the Claim costs to the Vault operator
- hinders integration potential: Vault integrators would need to handle both the 2-step and 1-step cases, with the 1-step pushing arbitrary tokens in from an unknown Request at an unknown time. This pushes complexity out onto integrators and reduces the standard&apos;s utility.

The 2-step approach used in the standard may be abstracted into a 1-step approach from the user perspective through the use of routers, relayers, message signing, or account abstraction.

In the case where a Request may become Claimable immediately in the same block, there can be router contracts that atomically check for Claimable amounts immediately upon Request. Frontends can dynamically route Requests in this way depending on the state and implementation of the Vault to handle this edge case.

### No Outputs for Request Functions

`requestDeposit` and `requestRedeem` may not have a known exchange rate that will happen when the Request becomes Claimed. Returning the corresponding `assets` or `shares` could not work in this case.

The Requests could also output a timestamp representing the minimum amount of time expected for the Request to become Claimable, however, not all Vaults will be able to return a reliable timestamp.

### No Event for Claimable State

The state transition of a Request from Pending to Claimable happens at the Vault implementation level and is not specified in the standard. Requests may be batched into the Claimable state, or the state may transition automatically after a timestamp has passed. It is impractical to require an event to emit after a Request becomes Claimable at the user or batch level.

### Reversion of Preview Functions in Async Request Flows

The preview functions do not take an address parameter, therefore the only way to discriminate discrepancies in the exchange rate is via the `msg.sender`. However, this could lead to integration/implementation complexities where support contracts cannot determine the output of a claim on behalf of a `controller`.

In addition, there is no on-chain benefit to previewing the Claim step as the only valid state transition is to Claim anyway. If the output of a Claim is undesirable for any reason, the calling contract can revert on the output of that function call.

It reduces code and implementation complexity at little to no cost to simply mandate reversion for the preview functions of an async flow.

### Mandated Support for [ERC-165](/EIPs/EIPS/eip-165)

Implementing support for [ERC-165](/EIPs/EIPS/eip-165) is mandated because of the [optionality of flows](#optionality-of-flows). Integrations can use the `supportsInterface` method to check whether a vault is fully asynchronous, partially asynchronous, or fully synchronous (for which it is just following the [ERC-4626](./eip-4626)), and use a single contract to support all cases.

### Not Allowing Pending Claims to be Fungible
The async pending claims represent a sort of semi-fungible intermediate share class. Vaults can elect to wrap these claims in any token standard they like, for example, ERC-20, [ERC-1155](/EIPs/EIPS/eip-1155), or ERC-721 depending on the use case. This is intentionally left out of the spec to provide flexibility to implementers.

## Backwards Compatibility

The interface is fully backward compatible with [ERC-4626](/EIPs/EIPS/eip-4626). The specification of the `deposit`, `mint`, `redeem`, and `withdraw` methods is different as described in [Specification](#specification).

## Reference Implementation

```solidity
    // This code snippet is incomplete pseudocode used for example only and is no way intended to be used in production or guaranteed to be secure

    mapping(address =&gt; uint256) public pendingDepositRequest;
    
    mapping(address =&gt; uint256) public claimableDepositRequest;

    mapping(address controller =&gt; mapping(address operator =&gt; bool)) public isOperator;

    function requestDeposit(uint256 assets, address controller, address owner) external returns (uint256 requestId) {
        require(assets != 0);
        require(owner == msg.sender || isOperator[owner][msg.sender]);

        requestId = 0; // no requestId associated with this request

        asset.safeTransferFrom(owner, address(this), assets); // asset here is the Vault underlying asset

        pendingDepositRequest[controller] += assets;

        emit DepositRequest(controller, owner, requestId, msg.sender, assets);
        return requestId;
    }

    /**
     * Include some arbitrary transition logic here from Pending to Claimable
     */

    function deposit(uint256 assets, address receiver, address controller) external returns (uint256 shares) {
        require(assets != 0);
        require(controller == msg.sender || isOperator[controller][msg.sender]);

        claimableDepositRequest[controller] -= assets; // underflow would revert if not enough claimable assets

        shares = convertToShares(assets); // this naive example uses the instantaneous exchange rate. It may be more common to use the rate locked in upon Claimable stage.

        balanceOf[receiver] += shares;

        emit Deposit(controller, receiver, assets, shares);
    }

    function setOperator(address operator, bool approved) public returns (bool) {
        isOperator[msg.sender][operator] = approved;
        emit OperatorSet(msg.sender, operator, approved);
        return true;
    }

```

## Security Considerations

In general, asynchronicity concerns make state transitions in the Vault much more complex and vulnerable to security risks. Access control on Vault operations, clear documentation of state transitions, and invariant checks should all be performed to mitigate these risks. For example:

* The view methods for viewing Pending and Claimable request states (e.g. pendingDepositRequest) are estimates useful for display purposes but can be outdated. The inability to know the final exchange rate on any Request requires users to trust the implementation of the asynchronous Vault in the computation of the exchange rate and fulfillment of their Request.
* Shares or assets locked for Requests can be stuck in the Pending state. Vaults may elect to allow for the fungibility of pending claims or implement some cancellation functionality to protect users.

### Operators

An operator has the ability to transfer the `asset` of the vault from the approver to any address, and simultaneously grants control over the `share` of the vault. 

Any user approving an operator must trust that operator with both the `asset` and `share` of the Vault.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 18 Oct 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7540</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7540</guid>
      </item>
    
      <item>
        <title>eth/70 - available-blocks-extended protocol</title>
        <category>Standards Track/Networking</category>
        
          <comments>https://ethereum-magicians.org/t/eip-eth-70-available-blocks-extended-protocol-handshake/16188</comments>
        
        <description>## Abstract

The purpose of this EIP is to introduce a method that allows an Ethereum node to communicate the range of blocks it has available. By knowing the block range a node can serve, peers can make more informed decisions when choosing whom to request blocks from or whom to connect to, especially when looking for specific block ranges. This can lead to more efficient network behavior.

This EIP proposes extending the Ethereum wire protocol (`eth`) handshake, introducing a new version, `eth/70`, which will contain information regarding the block range a node can serve. Furthermore, it extends the protocol with two new message types to share the updated block ranges when requested.

## Motivation

In a first stage of [EIP-4444](/EIPs/EIPS/eip-4444), some nodes will still need to serve the historical data of the chain and others might be interested in starting to prune it. Currently, nodes need to connect to peers and request specific blocks to determine if a peer has the requested data. This can be inefficient, leading to unnecessary data requests and wasting both bandwidth and time. Consequently, this change empowers nodes that still want to retrieve historical data from the network to do so efficiently.

As a bonus, This change enhances the efficiency of synchronization by allowing a node to determine if a peer, potentially still in the process of syncing, has the necessary blocks available, thereby avoiding unnecessary block requests and potential empty responses.

## Specification

- Advertise a new `eth` protocol capability (version) at `eth/70`.
  - The old `eth/69` protocol should still be kept alive side-by-side, until `eth/70` is sufficiently adopted by implementors.
- Modify the `Status (0x00)` message for `eth/70` to add an additional `blockRange` field right after the `forkid`:
  - Current packet for `eth/69`: `[version: P, networkid: P, blockhash: B_32, genesis: B_32, forkid]`
  - New packet for `eth/70`: `[version: P, networkid: P, blockhash: B_32, genesis: B_32, forkid blockRange]`,
  where `blockRange` is `[startBlock: uint64, endBlock: uint64]`.

- Introduce two new message types:
  - `RequestBlockRange (0x0b)` - A message from a node to request the current block range of a peer.
  - `SendBlockRange (0x0c): [startBlock: uint64, endBlock: uint64]` - The response to `RequestBlockRange`, informing the requesting node of the current available block range of the peer.

Upon connecting using `eth/70`, nodes should exchange the `Status` message. Afterwards, they can use the `RequestBlockRange` and `SendBlockRange` messages to keep informed about peer block range changes.

Nodes must retain connections regardless of a peer&apos;s available block range, with an exception, if a node&apos;s peer slots are full and it lacks connections to peers with the necessary block range, it may disconnect to seek such peers.

## Rationale

Including the available block range in the `eth` handshake allows for immediate understanding of peer capabilities. This can lead to more efficient networking as nodes can prioritize connections based on the data they need.
The new message types are introduced to allow nodes to request updated available block range from other nodes since the range can change by the node syncing or pruning blocks.
Maintaining connections with peers that don&apos;t have the desired range ensures network resilience, while the exception facilitates efficient block sync under full peer capacity.

## Backwards Compatibility

This EIP extends the `eth` protocol handshake in a backwards incompatible manner and proposes the introduction of a new version, `eth/70`. However, `devp2p` allows for multiple versions of the same wire protocol to run concurrently. Hence, nodes that have not been updated can continue using older versions like `eth/69`, `eth/68` or `eth/67`.

This EIP doesn&apos;t affect the consensus engine and doesn&apos;t necessitate a hard fork.

## Test Cases

Testing will involve ensuring that nodes can correctly communicate and understand the block range information during the handshake. Additionally, it will involve ensuring nodes can correctly request and share updated block range when requested.

## Security Considerations

This change is not a standardization of not storing and serving historical blocks before the implementation of alternative historical blocks storage solutions.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 21 Oct 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7542</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7542</guid>
      </item>
    
      <item>
        <title>EVM arbitrary precision decimal math</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/decimal-math-on-evm/16194</comments>
        
        <description>## Abstract

This EIP adds *arbitrary precision decimal float* OPCODEs for arithmetic via DECADD, DECNEG, DECMUL, DECINV and expression of all elementary functions via DECEXP, DECLN, DECSIN. All decimal values upto the maximal precision allowed by a int256 coefficient and exponent are represented exactly, as c*10^q. All implemented algorithms converge for all inputs given enough precision, as chosen by the user. All calculations are deterministic and gas is precisely embedded bottom-up. Allowing arbitrary precision decimal elementary functions invites the worlds of mathematical finance, machine learning, science, digital art, games and others to Ethereum. The implementation is functional.

## Motivation

Currently, to take a power, a^b, of non integer values, requires vast amounts of Solidity code.
The simplest task in trading e.g. is to convert volatilities from yearly to daily, which involves taking the 16th root.

Giving users/devs the same ability that scientific calculators have allows for the creation of apps with higher complexity.

The files [BlackScholes.yul](/EIPs/assets/eip-7543/BlackScholes.yul) and [Neuron.yul](/EIPs/assets/eip-7543/Neuron.yul) demonstrate how these OPCODEs simplify numerical smart contract code.

### Why decimal?

To represent a simple value like 0.1 in binary requires infinite many digits and is therefore not exactly represently in a finite binary machine. Decimal types are much closer to the vast majority of numerical calculations run by humans.

### eVm

The EVM is a virtual machine and thereby not restricted by hardware. Usually, assembly languages provide OPCODES that are mimic the ability of hardware. In a virtual machine, we have no such limitations and nothing stops us from adding more complex OPCODEs, as long as fair gas is provided. At the same time, we do not want to clutter the OPCODEs library. EXP, LN and SIN are universal functions that open the path to: powers, trigonometry, integrals, differential equations, machine learning, digital art, etc.

## Specification

### Decimal

A decimal is defined as

c * 10^q

where c and q are int256.

Notationwise:
a = ac * 10^aq
b = bc * 10^bq
etc.

### OPCODE defs

0xd0 DECADD a+b -&gt; c    : (ac, aq, bc, bq, precision) -&gt; (cc, cq)
0xd1 DECNEG  -a -&gt; b    : (ac, aq) -&gt; (bc, bq)
0xd2 DECMUL a*b -&gt; c    : (ac, aq, bc, bq, precision) -&gt; (cc, cq)
0xd3 DECINV 1/a -&gt; b    : (ac, aq, precision) -&gt; (bc, bq)
0xd4 DECEXP exp(a) -&gt; b : (ac, aq, precision, steps) -&gt; (bc, bq)
0xd5 DECLN   ln(a) -&gt; b : (ac, aq, precision, steps) -&gt; (bc, bq)
0xd6 DECSIN sin(a) -&gt; b : (ac, aq, precision, steps) -&gt; (bc, bq)

`precision` is the # of digits kept during all calculations. `steps` for DECEXP and DECSIN are the # of Taylor expansion steps. `steps` for DECLN is the depth of the continued fractions expansion.

### Why these functions?

The proposed functions (+,-,*,/,exp,ln,sin) form a small set that combined enable all calculation of all elementary functions, which includes the sets of sums, products, roots and compositions of finitely many polynomial, rational, trigonometric, hyperbolic, and exponential functions, including their inverse functions.

a^b = exp(b * ln(a)) gives us powers and polynomials.
cos(a) = sin(tau/4-a), tan(a)=sin(a)/cos(a), etc., gives us all of trigonometry.

Together with arithmetic, we get all elementary functions.

### DECNEG instead of DECSUB

Negation is a more general operation vs subtraction. OPCODEs should be as fundamental as possible and as complex as desirable.
For the same reason, we have DECINV instead of DECDIV.

DECSUB(a,b) = DECADD(a,DECNEG(b))
DECDIV(a,b) = DECMUL(a,DECINV(b))

### DECEXP, DECSIN via Taylor series

The Taylor series of exp and sin converge everywhere and fast. The error falls as fast as the factorial of steps.

### DECLN via continued fractions

Ln converges fast using continued fractions within the interval ]0,2]. The implementation scales the input into this interval and scales the result back correctly.


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

## Rationale

### gas

All the above OPCODEs are deterministic, hence the gas cost can be determined. At the same time, the calculations are complex and depend on the input.

It is crucial to have accurate gas costs to avoid energy attacks on nodes.

To this end, the underlying uint256 lib can be wrapped with gas accumulation, as found in the reference implementation in ../assets/eip-EVM+/uint256_wrapped.go. This gives a bottom-up approach to calculating gas, by running the OPCODE.

Because the EVM interprator expects the gas cost before actually running the OPCODE, we are running the OPCODE twice. the first run, identical to the second, is to get the bottom-up gas cost, which is then doubled to account for the actual run plus the gas calculation. On top, we add a fixed emulation cost.

This gives an embedded gas calculation, which works well for complex OPCODEs (see gasEVMPlusEmulate in ../assets/eip-EVM+/gasEVMPlusEmulate.go).

To remove the double gas, we could find an upper bound on gas usage dependent on the function inputs.
Alternatively, a future EIP would suggest the following: allow contract code to run whilst accumulating gas (at runtime) and panicking in case of limit breach, without requiring the cost in advance. This only works for contract code that is pure, defined as code that only depends on the user input and the inner bytecode of the contract. Pure contracts cannot use state from the chain, nor make calls to other contracts. pure mathematical functions would e.g. be pure contracts. pure contracts are fully deterministic given the input, allowing a user to estimate gas costs offline (cheaper) and the EVM to panic at runtime, without knowing gas in advance.

Since the costs depend on the input, a fuzzing would give us close to the worst cases (TODO).

## Backwards Compatibility

No backward compatibility issues found.

Since the EVM allows contracts to deploy with invalid code, there could be previously invalid code that becomes valid when adding a new OPCODE. The EVM could be designed to expect a version tag at the beginning of all bytecode or (not xor) to only deploy valid code. This is an issue for any new OPCODE.

## Test Cases

../assets/eip-EVM+/decimal_float_test.go

## Reference Implementation

The reference implementation is found in ../assets/eip-EVM+/decimal_float.go

## Security Considerations

There are no security considerations, as long as numerical correctness is guaranteed and gas is collected fairly.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 22 Oct 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7543</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7543</guid>
      </item>
    
      <item>
        <title>Verkle proof verification precompile</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/verkle-proof-verification-precompile/16274</comments>
        
        <description>## Abstract

This EIP proposes the addition of a precompiled contract to provide up-to-date state proof verification capabilities to smart contracts in a stateless Ethereum context.

## Motivation

The proposed proof systems for stateless Ethereum require an upgrade to many tools and applications, that need a simple path to keep their proving systems up-to-date, without having to develop and deploy new proving libraries each time another proof format must be supported.

## Specification
    
The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119 and RFC 8174.
    
A precompiled contract is added at address `0x21`, wrapping the stateless ethereum proof verification function.
    
The precompile&apos;s `input` is the tightly packed concatenation of the following fields:

  * `version` (1 byte) specifies which version of the stateless proof verification function should be used. Version 0 is used for an MPT and version 1 is used for the polynomial commitment scheme multiproof used in [EIP-6800](/EIPs/EIPS/eip-6800).
  * `state_root` (32 bytes) specifies the state root that the proof is proving against.
  * `proof_data` (arbitrary long) is the proof data.

Pseudo-code behavior of the precompile:
    
```python
def proof_verification_precompile(input):
    version = input[0]
    state_root = input[1:33]
    proof_data = input[33:33+proof_data_size]

    if version == 0:
        proof = deserialize_proof(state_root, proof_data)
        return verify_mpt_multiproof(proof)

    if version == 1:
        proof = deserialize_proof(state_root, proof_data)
        return verify_pcs_multiproof(proof)
    
    return 0
```

If `version` is `0` then the proof is expected to follow the SSZ format described in &quot;the verge&quot; proposal in the consensus spec.
    
The precompile returns `1` if it was able to verify the proof, and `0` otherwise.

### Gas costs

|Constant name|cost|
|-|-|
|`POINT_COST`|TBD|
|`POLY_EVAL_COST`|TBD|

The precompile cost is:

`cost = (POINT_COST + 1)*len(get_commitments(input)) + POLY_EVAL_COST * [leaf_depth(key, get_tree(input)) for key in get_keys(input))]`

where:

 * `get_commitments` extracts the list of commitments in the proof, as encoded in `input`
 * `get_keys` extracts the list of keys in the proof, as encoded in `input`
 * `leaf_depth` returns the depth of the leaf in the tree
 * `get tree` reconstruct a stateless view of the tree from `input`

## Rationale

Stateless Ethereum relies on proofs using advanced mathematical concepts and tools from a fast-moving area of cryptography. As a result, a soft-fork approach is currently favored in the choice of the proof format: proofs are going to be distributed outside of consensus, and in the future, stateless clients will be able to chose their favorite proof format.
    
This introduces a burden on several application, e.g. bridges, as they will potentially need to support proof formats designed after the release of the bridge contract.
    
Delegating the proof verification burden to a version-aware precompile will ensure that these applications can support newer proving primitives without having to upgrade their contracts.

## Backwards Compatibility

No backward compatibility issues found.

## Test Cases

TODO

## Reference Implementation

WIP

 * First implementation in Optimism, pull request #192 of ethereum-optimism/op-geth by @protolambda

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 13 Oct 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7545</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7545</guid>
      </item>
    
      <item>
        <title>Upgradeable Clone for Scalable Contracts</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7546-upgradeable-clone/16256</comments>
        
        <description>## Abstract
It has been a significant challenge for developers attempting to create cloneable and upgradeable contracts on the Ethereum Virtual Machine (EVM). While [ERC-2535](/EIPs/EIPS/eip-2535) Diamonds and other existing proxy standards offer partial solutions, a comprehensive answer has remained elusive. Our proposal addresses this gap through the introduction of two main features.

### Function-Level Upgradeability
In alignment with [ERC-2535](/EIPs/EIPS/eip-2535), this functionality permits the selective redirection of implementation contracts for individual function calls. This granular control over upgrades allows for modifications on a per-function basis. Moreover, segmenting implementation contracts by function helps mitigate the limitations posed by the contract size cap (24.576kB as of EVM version Shanghai or earlier).

### Factory/Clone-Friendly &amp; Simultaneous Upgradeability
Drawing on the Beacon model from [ERC-1967](/EIPs/EIPS/eip-1967), our method aims to streamline the process of cloning and updating Proxy contracts simultaneously. This approach is designed to maintain consistent functionality across different instances, each with its own state. Typically, proxies are limited to basic upgradeability features or follow the [ERC-1167](/EIPs/EIPS/eip-1167) standard. However, our solution combines both functionalities into a compact proxy.

## Motivation
Smart contract development often encounters hurdles due to the inherent limitations of the Ethereum Virtual Machine (EVM), such as the contract size limit and stack depth. Additionally, addressing vulnerabilities in both the smart contract logic and its compiler are persistent issues. While there is a desire to minimize reliance on trusted third parties for upgradeability, introducing complex governance structures for upgrade management can significantly increase the workload for crypto DevOps, adding to the apprehension developers may feel towards advancing their projects. This apprehension can restrict the complexity and innovation within smart contract development. Our approach seeks to simplify smart contract programming, making it more accessible and enjoyable. It does so by clearly delineating DevOps concerns from business logic, thereby enhancing codebase clarity, facilitating audits, and allowing for more focused analysis through Language Model (LM) techniques, tailored to specific infrastructure and domain needs.

### Use Cases
Over time, various smart contract design patterns have been proposed and utilized. This *Upgradeable Clone Standard (UCS)* is intended for scenarios where these existing patterns may not suffice. To clarify it, we define some key terms:

- **Contract-Level Upgradeability**: One Proxy contract corresponds to one Implementation contract, responsible for all logic of the Proxy.
- **Function-Level Upgradeability**: One Proxy contract corresponds to multiple Implementation contracts, basically each responsible for a specific function.
- **Factory**: A contract that clones Proxies with a common Implementation(s). In the context of upgradeability, it allows for the simultaneous upgrade of these cloned Proxies.

Here are the use cases:

1. For basic needs without Upgradeability or a Factory, *Regular smart contract deployment* suffices.
2. When a Factory is needed without Upgradeability, [ERC-1167](/EIPs/EIPS/eip-1167) is suitable.
3. For Contract-Level Upgradeability without a Factory, [ERC-1822](/EIPs/EIPS/eip-1822) can be used.
4. For Contract-Level Upgradeability with a Factory, the Beacon from [ERC-1967](/EIPs/EIPS/eip-1967) is applicable.
5. For Function-Level Upgradeability without a Factory, [ERC-2535](/EIPs/EIPS/eip-2535) is available.
6. For Function-Level Upgradeability with a Factory, this ***Upgradeable Clone Standard*** is the ideal choice.

![Fig. Use Cases](/EIPs/assets/eip-7546/images/usecases.svg)


## Specification
&gt; The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119 and RFC 8174.

In the EVM, contract accounts are characterized by four primary fields: *nonce*, *balance*, *code*, and *storage*. This ERC&apos;s architecture modularizes these functionalities into three distinct types of contracts, each serving a specific purpose when combined to represent a single account:

1. **Proxy Contract**: Maintains the state of the contract account, such as nonce, balance, and storage. This contract delegatecalls to the _Function Contract_ as registered in the _Dictionary Contract_, ensuring the state and logic are separated but effectively integrated.
2. **Dictionary Contract**: Acts as a dispatcher that routes function calls based on their selectors to the appropriate _Function Contract_. It manages the dynamic aspects of contract behavior, facilitating function upgrades and dynamic addressing. By externalizing this contract from the _Proxy Contract_, it becomes factory/clone-friendly and supports simultaneous upgradeability.
3. **Function (Implementation) Contract**: Implements the executable logic for function calls. When delegatecalled by the _Proxy Contract_, it performs the actual computations or logic as defined in the contract&apos;s code.

This architecture not only aligns with the core attributes of an EVM contract account but also significantly enhances the modularity, upgradeability, and scalability of smart contracts by clarifying account state, function dispatching, and logic implementation.

### Proxy Contract
This contract requests the _Dictionary Contract_ to retrieve the associated _Function Contract_ address based on its function selector, and then delegatecall to it.

#### Storage &amp; Events
This contract SHOULD store the _Dictionary Contract_ address in the storage slot `0x267691be3525af8a813d30db0c9e2bad08f63baecf6dceb85e2cf3676cff56f4`, obtained as `bytes32(uint256(keccak256(&apos;erc7546.proxy.dictionary&apos;)) - 1)`, in accordance with the method defined in [ERC-1967](/EIPs/EIPS/eip-1967). This ensures that the address is stored in a secure and predictable slot.

Changes to the Dictionary address SHOULD emit events. When such an event is emitted, it MUST use the signature:
```solidity
event DictionaryUpgraded(address dictionary);
```

#### Functions
For every invocation made via `CALL` or `STATICCALL`, this contract MUST perform a delegatecall to the corresponding _Function Contract_ address retrieved from the _Dictionary Contract_ using the `getImplementation(bytes4 functionSelector)` function. This contract MUST also process the return value from this delegatecall to ensure the intended functionality is executed correctly. Furthermore, to avoid potential collisions with function selectors registered in the _Dictionary Contract_, the Proxy SHOULD NOT define any external functions.

### Dictionary Contract
This contract manages a mapping of function selectors to corresponding _Function Contract_ addresses. It uses this mapping to handle requests from the _Proxy Contract_.

#### Storage &amp; Events
The Dictionary MUST maintain a mapping of function selectors to _Function Contract_ addresses.

Changes to this mapping SHOULD be communicated through an event (or log).

```solidity
event ImplementationUpgraded(bytes4 functionSelector, address implementation);
```

#### Functions
##### `getImplementation`
This contract MUST implement this function to return _Function Implementation Contract_ address.

```solidity
function getImplementation(bytes4 functionSelector) external view returns(address implementation);
```

##### `setImplementation`
This contract SHOULD implement this function to update or add new function selectors and their corresponding _Function Implementation Contract_ addresses to the mapping.

```solidity
function setImplementation(bytes4 functionSelector, address implementation) external;
```

##### `supportsInterface`
This contract is RECOMMENDED to implement the `supportsInterface(bytes4 interfaceID)` function defined in [ERC-165](/EIPs/EIPS/eip-165) to indicate which interfaces are supported by the contracts referenced in the mapping.

##### `supportsInterfaces`
This contract is RECOMMENDED to implement the `supportsInterfaces()` to return a list of registered interfaceIDs.
```solidity
function supportsInterfaces() public view returns (bytes4[] memory);
```

### Function (Implementation) Contract
This contract acts as the logic implementation contract that the _Proxy Contract_ delegatecalls and it&apos;s address is registered with the function selector in the _Dictionary Contract_.

#### Storage &amp; Events
This contract SHOULD NOT use its storage but SHOULD store to the _Proxy Contract_ through delegatecall.

The _Proxy Contract_ shares storage layout with several _Function Contracts_. For example, using sequential slot allocation starting from slot 0, as is the default compiler option, can lead to storage conflicts.

In order to prevent storage conflict, this contract MUST manage the storage layout properly. The matter of storage management techniques has been a subject of debate for years, both at the ERC level and the language level. However, there is still no definitive standard. Therefore, this ERC does not go into the specifics of storage management techniques.

It is RECOMMENDED to choose the storage management method that is considered most appropriate at the time.

For instance, the storage could be arranged according to useful storage layout patterns, such as ***[ERC-7201](/EIPs/EIPS/eip-7201)***.

#### Functions
This contract MUST have the same function selector registered in the _Dictionary Contract_. If not, the Proxy&apos;s delegatecall will fail. So it is RECOMMENDED for each _Function Contract_ to implement ERC-165&apos;s `supportsInterface(bytes4 interfaceID)` to ensure that it correctly implements the function selector being registered when added to the Dictionary.


## Rationale
### Comparison with [ERC-2535](/EIPs/EIPS/eip-2535)
While both this ERC and ERC-2535 offer [Function-Level Upgradeability](#function-level-upgradeability), there is a key distinction in their approaches. ERC-2535 maintains a mapping of implementation contracts (referred to as Facets in ERC-2535) within the Proxy itself. In contrast, this ERC stores the mapping in an external _Dictionary Contract_. This externalization of the mapping facilitates another significant feature of this standard: [Factory/Clone-Friendly &amp; Simultaneous Upgradeability](#factoryclone-friendly--simultaneous-upgradeability). By separating the mapping from the Proxy, this design allows for easier cloning of contracts and their simultaneous upgrade, which is not as straightforward in the ERC-2535 framework.

![Fig. Comparison with Diamond](/EIPs/assets/eip-7546/images/comparison-with-diamond.svg)

### Separating the Dictionary and Proxy contracts:
The separation of the Dictionary from the Proxy was driven by aligning with [Factory/Clone-Friendly &amp; Simultaneous Upgradeability](#factoryclone-friendly--simultaneous-upgradeability).

To achieve this, the management functionality of _Function Implementation Contract_ addresses were externalized as the _Dictionary Contract_ instead of including them within the _Proxy Contract_, a concept akin to the Beacon Proxy approach.

If the functionality is within the _Proxy Contract_, each proxy requires its implementation to be upgraded.
By externalizing this, a common implementation can be cloned and upgraded simultaneously.

![Fig. Comparison with Beacon](/EIPs/assets/eip-7546/images/comparison-with-beacon.svg)

### Utilizing the mapping of function selectors and implementation addresses:
The utilization of the mapping of function selectors to corresponding _Function Implementation Contract_ addresses of the _Dictionary Contract_ by the _Proxy Contract_, followed by delegatecalling to the returned implementation address, aligns with [Function-Level Upgradeability](#function-level-upgradeability).

By adopting this approach, the Proxy emulates the behavior of possessing a set of _Function Implementation Contracts_ registered within the _Dictionary Contract_. This specification closely resembles the pattern outlined in the Diamond Standard.


## Reference Implementation
There are reference implementations and tests as a foundry project.

It includes the following contents:
- Reference Implementations
  - [Proxy Contract](/EIPs/assets/eip-7546/src/Proxy.sol)
  - [Dictionary Contract](/EIPs/assets/eip-7546/src/Dictionary.sol)
- Tests
  - [Proxy Spec Test](/EIPs/assets/eip-7546/test/Proxy.spec.t.sol)
  - [Dictionary Spec Test](/EIPs/assets/eip-7546/test/Dictionary.spec.t.sol)
  - [UCS Usecase Test](/EIPs/assets/eip-7546/test/UCS.usecase.t.sol)


## Security Considerations
### Delegation of Implementation Management
This pattern of delegating all implementations for every call to the _Dictionary Contract_ relies on the assumption that the _Dictionary Contract_&apos;s admin acts in good faith and does not introduce vulnerabilities through negligence.

You should not connect your proxy with the _Dictionary Contract_ provided by an untrusted admin. Moreover, providing an option to switch to another _Dictionary Contract_ managed by a different (or potentially more trustworthy) admin is recommended.

While it is possible to store the _Dictionary Contract_ address in the code area (e.g., using Solidity&apos;s immutable or constant), it SHOULD be designed with caution, considering the possibility that if the _Dictionary Contract_&apos;s admin is not the same as the _Proxy Contract_&apos;s admin, the ability to manipulate the implementation could be permanently lost.

### Storage Conflict
As mentioned in the above [Storage section](#storage--events-2). This design pattern involves multiple _Function Implementation Contracts_ sharing a single _Proxy Contract_ storage. Therefore, it&apos;s important to take care for preventing storage conflicts by using the storage management method that is considered most appropriate at the time.

### Mismatch Function Selector
The _Dictionary Contract_ returns the _Function Implementation Contract_ address based on the _Proxy Contract_&apos;s invoked function selector.

If there is a mismatch between function selectors registered in the _Dictionary Contract_ and those implemented in the _Function Implementation Contract_, the execution will fail. To prevent unexpected behavior, it&apos;s recommended to check that the _Function Implementation Contract_ includes the function selector (interface) being registered during the process for setting implementation address to the _Dictionary Contract_.

### Handling of CALL and STATICCALL
The _Proxy Contract_ is designed primarily to respond to `CALL` and `STATICCALL` opcodes. Should a `DELEGATECALL` be made to this _Proxy Contract_, it will attempt to request the _Dictionary Contract_ for a corresponding implementation via the `getImplementation(bytes4 functionSelector)` function, using the stored _Dictionary Contract_ address within its own storage. Although this action may not lead to the intended outcome if the calling contract&apos;s storage layout does not align with expectations, it does not constitute a direct threat to the _Proxy Contract_ itself. Developers are cautioned that invoking this _Proxy Contract_ via `DELEGATECALL` could result in unexpected and potentially non-functional outcomes, making it an unsuitable method for interaction.


## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 25 Oct 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7546</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7546</guid>
      </item>
    
      <item>
        <title>Inclusion lists</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7547-inclusion-lists/17474</comments>
        
        <description>## Abstract

Censorship resistance is a core value proposition of blockchains. Inclusion lists aim to provide a mechanism to improve the censorship resistance of Ethereum by allowing proposers to specify a set of transactions that must be promptly included for subsequent blocks to be considered valid. 

## Motivation

Since the merge, validators have started outsourcing almost all block production to a specialized set of builders who compete to extract the most MEV (this is commonly referred to as Proposer-Builder Separation). As of October 2023, nearly 95% of blocks are built by builders rather than the proposer. While it is great that all proposers have access to competitive blocks through the `mev-boost` ecosystem, a major downside of externally built blocks is the fact that the builders ultimately decide what transactions to include or exclude. Without any forced transaction inclusion mechanism, the proposer is faced with a difficult choice: they either have no say on the transactions that get included, or they build the block locally (thus have the final say on transactions) and sacrifice some MEV rewards. 

Inclusion lists aim to allow proposers to retain some authority by providing a mechanism by which transactions can be forcibly included. The simplest design is for the `slot N` proposer to specify a list of transactions that must be included in the block that is produced for their slot. However, this is not incentive-compatible because builders may choose to abstain from building blocks if the proposer sets some constraints on their behavior. This leads to the idea of &quot;forward&quot; inclusion lists, where the transactions specified by the `slot N` proposer are enforced in the `slot N+1` block. The naïve implementation of the forward inclusion lists presents a different issue of potentially exposing free data availability, which could be exploited to bloat the size of the chain without paying the requisite gas costs. The free data availability problem is solved with observations about nonce reuse and allowing multiple inclusion lists to be specified for each slot. With the incentive compatibility and free data availability problems addressed, we can more safely proceed with the implementation of inclusion lists.

## Specification

### Constants

| Name | Value |
| - | - |
| `MAX_TRANSACTIONS_PER_INCLUSION_LIST` | `2**4 = 16` |
| `MAX_GAS_PER_INCLUSION_LIST` | `2**21` |
| `MIN_SLOTS_FOR_INCLUSION_LIST_REQUEST` | `1` |

#### Reference Objects

```
class InclusionListSummaryEntry(Container):
    address: ExecutionAddress
    gas_limit: uint64
```

```
class InclusionListSummary(Container)
    slot: Slot
    proposer_index: ValidatorIndex
    summary: List[InclusionListSummaryEntry, MAX_TRANSACTIONS_PER_INCLUSION_LIST]
```

```
class SignedInclusionListSummary(Container):
    message: InclusionListSummary
    signature: BLSSignature
```

```
class InclusionList(Container)
    summary: SignedInclusionListSummary
    transactions: List[Transaction, MAX_TRANSACTIONS_PER_INCLUSION_LIST]
```

```
class ExecutionPayload(Container):
    ...
    inclusion_list_summary: List[InclusionListSummaryEntry, MAX_TRANSACTIONS_PER_INCLUSION_LIST]
    inclusion_list_exclusions: List[uint64, MAX_TRANSACTIONS_PER_INCLUSION_LIST]
```

```
class ExecutionPayloadHeader(Container):
    ...
    inclusion_list_summary_root: Root
    inclusion_list_exclusions_root: Root
```

```
class BeaconBlockBody(Container):
    ...
    inclusion_list_summary: SignedInclusionListSummary
```

### Consensus layer

#### High-level overview

**`slot N` proposal:**

- Proposer broadcasts a signed block and an inclusion list (summary and transactions objects) for `slot N+1`.
- Transactions will be included in `slot N` or `slot N+1`.
- Summaries include the originating address of the transactions and their respective gas limits.
- Summaries are signed, but transactions are not.

**`slot N` validation:**

- Validators only consider the block for validation and fork-choice if they have seen at least one inclusion list for that slot.
- They consider the block invalid if the inclusion list transactions are not executable at the start of `slot N` or if the transactions&apos; `maxFeePerGas` are not at least 12.5% higher than the current slot (to ensure the transactions will be valid in `slot N+1`).

**`slot N+1` validation:**

- The proposer for `slot N+1` builds their block along with a signed summary from the `slot N` proposer.
- The payload includes a list of transaction indices from the `slot N` payload that satisfy some entry in the signed inclusion list summary.
- The payload is considered valid if: (a) the execution conditions are met, including satisfying the inclusion list summary and being executable from the execution layer perspective, and (b) the consensus conditions are met with a proposer signature of the previous block.

#### Specific Changes

**Beacon chain state transition spec:**

- ***New** `inclusion_list` object:* Introduce a new `inclusion_list` for the proposer to submit and nodes to process.
- ***Modified** `ExecutionPayload` and `ExecutionPayloadHeader` objects:* Update these objects to meet the inclusion list requirements.
- ***Modified** `BeaconBlockBody`:* Modified to cache the inclusion list summary.
- ***Modified** `process_execution_payload` function:* Update this process to include checks for the inclusion list summary satisfaction.

**Beacon chain fork-choice spec:**

- ***New** `is_inclusion_list_available` check:* Introduce a new check to determine if the inclusion list is available within the visibility window.
- ***New** notification action:* Implement a new call to notify the Execution Layer (EL) client about a new inclusion list. The corresponding block is considered invalid if the EL client deems the inclusion list invalid.
 
**Beacon chain P2P spec:**

- ***New** gossipnet and validation rules for inclusion list:* Define new rules for handling the inclusion list in the gossip network and validation.
- ***New** RPC request and response network for inclusion list:* Establish a new network for sending and receiving inclusion lists.


**Validator spec:**

- ***New** duty for `inclusion_list`:* Proposer to prepare and sign the inclusion list.
- ***Modified** duty for `BeaconBlockBody`:* Update the duty to prepare the beacon block body to include the `inclusion_list_summary`.

### Execution layer

- ***New** `get_inclusion_list`:* Introduce a new function for proposers to retrieve inclusion lists.
- ***New** `new_inclusion_list`:* Define a new function for nodes to validate the execution side of the inclusion list.
- ***Modified** `forkchoice_updated`:* Update the function with a `payload_attribute` to include the inclusion list summary as part of the attribute.
- ***Modified** `new_payload`:* Update the function for EL clients to verify that `payload_transactions` satisfy `payload.inclusion_list_summary` and `payload.inclusion_list_exclusions`.
- ***New** validation rules:* Implement new validation rules based on the changes introduced in the Execution-API spec.

## Rationale

We consider a few design decisions present in this EIP. 

1. `ReducedSummary` versus `Summary`
    - The original proposal tries to improve data efficiency by using a `ReducedSummary` and a `Rebuilder`. This allows the full summary to be reconstructed. 
    - This adds a lot of complexity to the spec, so in this initial version, we should consider just using the regular `Summary` and including that in the subsequent block.
3. Gas limit vs no limit. 
    - One consideration is whether the inclusion list should have a gas limit or use the block’s gas limit.
    - Having a separate gas limit simplifies complexity but opens up the possibility for validators to outsource their inclusion list construction for side payments (e.g., if a block is full, the proposer could auction off space in the inclusion list for guaranteed inclusion in the subsequent block).
    - Alternatively, inclusion lists could be part of the block gas limit and only satisfied if the block gas limit is not full. However, this could lead to situations where the next block proposer intentionally fills up the block to ignore the inclusion list, albeit at the potential expense of paying to waste the gas.
4. Inclusion list ordering.
    - We assume that the inclusion list is processed at the top of the `slot N` block. Transactions in the inclusion list are evaluated for the pre-state of `slot N` but are only guaranteed to be included in `slot N+1`.
3. Inclusion list transaction exclusion.
    - Inclusion list transactions proposed at `slot N` may be satisfied in the same slot (e.g., by being included in the `ExecutionPayload`). This is a side effect of validators using `mev-boost` because they don’t know the contents of the block they propose.
    - Due to this, there exists an exclusion field, a node looks at each transaction in the payload’s `inclusion_list_exclusion` field and makes sure it matches with a transaction in the current inclusion list. When there’s a match, we remove that transaction from the inclusion list summary.
4. `mev-boost` compatibility.
    - There are no significant changes to `mev-boost`. Like any other hard fork, `mev-boost`, relays, and builders must adjust their beacon nodes.
    - Builders must know that execution payloads that don’t satisfy the inclusion list summary will be invalid.
    - Relays may have additional duties to verify such constraints before passing them to validators for signing.
    - When receiving the header, validators can check that the `inclusion_list_summary_root` matches their local version and skip building a block if there’s a mismatch, using the local block instead.
5. Syncing using by range or by root.
    - To consider a block valid, a node syncing to the latest head must also have an inclusion list.
    - A block without an inclusion list cannot be processed during syncing.
    - To address this, there is a parameter called `MIN_SLOTS_FOR_INCLUSION_LIST_REQUEST`. A node can skip inclusion list checks if the block’s slot plus this parameter is lower than the current slot.
    - This is similar to [EIP-4844](/EIPs/EIPS/eip-4844), where a node skips blob sidecar data availability checks if it’s outside the retention window.

## Backwards Compatibility

This EIP introduces backward incompatible changes to the block validation rule set on the consensus layer and must be accompanied by a hard fork. These changes do not break anything related to current user activity and experience.

## Security Considerations

The main potential issue is around the incentivization of the inclusion lists. If the `slot N` proposer constructs an inclusion list that negatively impacts the rewards of the `slot N+1` proposer, the `slot N+1` proposer may attempt to bribe the `slot N` proposer to publish an empty list. This isn&apos;t a direct attack on the protocol, but rather a profit-sharing mechanism by which the inclusion list would go unutilized. It seems likely these commitment games could be played no matter the censorship resistance scheme in place, but this remains an active area of research.


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 24 Oct 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7547</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7547</guid>
      </item>
    
      <item>
        <title>Open IP Protocol built on NFTs</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/draft-open-ip-protocol/16373</comments>
        
        <description>## Abstract

This proposal aims to establish a standardized method for creating new intellectual properties (IPs) by remixing multiple existing IPs in a decentralized manner.

The protocol is built on the foundation of NFTs (Non-Fungible Tokens). Within this protocol, each intellectual property is represented as an NFT. It extends the [ERC-721](/EIPs/EIPS/eip-721) standard, enabling users to generate a new NFT by remixing multiple existing NFTs. To ensure transparency and traceability in the creation process, the relationships between the new NFT and the original NFTs are recorded on the blockchain and made publicly accessible.

Furthermore, to enhance the liquidity of IP, users not only have the ability to remix NFTs they own but can also grant permission to others to participate in the creation of new NFTs using their own NFTs.

## Motivation

The internet is flooded with fresh content every day, but with the traditional IP infrastructure, IP registration and licensing is a headache for digital creators. The rapid creation of content has eclipsed the slower pace of IP registration, leaving much of this content unprotected. This means digital creators can&apos;t fairly earn from their work&apos;s spread.  

||Traditional IP Infrastructure|Open IP Infrastructure|
|-|-|-|
|IP Registration|Long waits, heaps of paperwork, and tedious back-and-forths.|An NFT represents intellectual property; the owner of the NFT holds the rights to the IP.|
|IP Licensing|Lengthy discussions, legal jargon, and case-by-case agreements.|A one-stop global IP licensing market that supports various licensing agreements.|  

With this backdrop, we&apos;re passionate about building an Open IP ecosystem tailored for today&apos;s digital creators. Here, with just a few clicks, creators can register, license, and monetize their content globally, without geographical or linguistic barriers. 

## Specification

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.

**Interface**

This protocol standardizes how to remix multiple existing NFTs and create a new NFT derivative work (known as a combo), while their relationships can be traced on the blockchain. It contains three core modules, remix module, network module, and license module.

### Remix Module

This module extends the ERC-721 standard and enables users to create a new NFT by remixing multiple existing NFTs, whether they’re ERC-721 or [ERC-1155](/EIPs/EIPS/eip-1155). 

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.10;

interface IERC721X {
    // Events

    /// @dev Emits when a combo is minted.
    /// @param owner The owner address of the newly minted combo
    /// @param comboId The newly minted combo identifier
    event ComboMinted(address indexed owner, uint256 indexed comboId);

    // Structs

    /// @param tokenAddress The NFT&apos;s collection address
    /// @param tokenId The NFT identifier
    struct Token {
        address tokenAddress;
        uint256 tokenId;
    }

    /// @param amount The number of NFTs used
    /// @param licenseId Which license to be used to verify this component
    struct Component {
        Token token;
        uint256 amount;
        uint256 licenseId;
    }

    // Functions

    /// @dev Mints a NFT by remixing multiple existing NFTs.
    /// @param components The NFTs remixed to mint a combo
    /// @param hash The hash representing the algorithm about how to generate the combo&apos;s metadata when remixing multiple existing NFTs.
    function mint(
        Component[] calldata components,
        string calldata hash
    ) external;

    /// @dev Retrieve a combo&apos;s components.
    function getComponents(
        uint256 comboId
    ) external view returns (Component[] memory);
}
```

### License Module

By default, users can only remix multiple NFTs they own to create new NFT derivative works. This module enables NFT holders to grant others permission to use their NFTs in the remixing process.

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.10;

import &quot;./IERC721X.sol&quot;;

interface ILicense {
    /// @dev Verify the permission when minting a combo
    /// @param user The minter
    /// @param combo The new NFT to be minted by remixing multiple existing NFTs
    /// @return components The multiple existing NFTs used to mint the new combo
    function verify(
        address user,
        IERC721X.Token calldata combo,
        IERC721X.Component[] calldata components
    ) external returns (bool);
}
```

### Network Module

This module follows the singleton pattern and is used to track all relationships between the original NFTs and their NFT derivative works.

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.10;

import &quot;./IERC721X.sol&quot;;

interface INFTNetIndexer {
    /// @dev Verify if the `child` was created by remixing the `parent` with other NFTs.
    /// @param parent Any NFT
    /// @param child Any NFT
    function isParent(
        IERC721X.Token calldata parent,
        IERC721X.Token calldata child
    ) external view returns (bool);

    /// @dev Verify if `a` and `b` have common `parent`s
    /// @param a Any NFT
    /// @param b Any NFT
    function isSibling(
        IERC721X.Token calldata a,
        IERC721X.Token calldata b
    ) external view returns (bool, IERC721X.Token[] memory commonParents);

    /// @dev Return all parents of a `token`
    /// @param token Any NFT
    /// @return parents All NFTs used to mint the `token`
    function getParents(
        IERC721X.Token calldata token
    ) external view returns (IERC721X.Token[] memory parents);
}
```

## Rationale

The Open IP Protocol is built on the &quot;1 premise, 2 extensions, 1 constant&quot; principle.  

The “1 premise” means that for any IP in the Open IP ecosystem, an NFT stands for that IP. So, if you have the NFT, you own the IP. That’s why the Open IP Protocol is designed as an extended protocol compatible with ERC-721.  

The “2 extensions” refer to the diversification of IP licensing and remixing.  

- IP licensing methods are diverse. For example, delegating an NFT to someone else is one type of licensing, setting a price for the number of usage rights is another type of licensing, and even pricing based on auction, AMM, or other pricing mechanisms can develop different licensing methods. Therefore, the license module is designed allowing various custom licensing methods.  

- IP remixing rules are also diverse. When remixing multiple existing NFTs, whether to support ERC-1155, whether to limit the range of NFT selection, and whether the NFT is consumed after remixing, there is no standard. So, the remix module is designed to support custom remixing rules.  

The &quot;1 constant&quot; refers to the fact that the traceability information of IP licensing is always public and unchangeable. Regardless of how users license or remix IPs, the relationship between the original and new IPs remains consistent. Moreover, if all IP relationships are recorded in the same database, it would create a vast IP network. If other social or gaming dApps leverage this network, it can lead to entirely novel user experiences. Hence, this protocol&apos;s network module is designed as a singleton.

## Backwards Compatibility

This proposal is fully backwards compatible with the existing ERC-721 standard, extending the standard with new functions that do not affect the core functionality.

&lt;!-- TODO: add reference implementation --&gt;

## Security Considerations

This standard highlights several security concerns that need attention:  

* **Ownership and Permissions**: Only the NFT owner or those granted by them should be allowed to remix NFTs into NFT derivative works. It&apos;s vital to have strict access controls to prevent unauthorized creations.  

* **Reentrancy Risks**: Creating derivative works might require interacting with multiple external contracts, like the remix, license, and network modules. This could open the door to reentrancy attacks, so protective measures are necessary.  

* **Gas Usage**: Remixing NFTs can be computation-heavy and involve many contract interactions, which might result in high gas fees. It&apos;s important to optimize these processes to keep costs down and maintain user-friendliness.  

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 31 Oct 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7548</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7548</guid>
      </item>
    
      <item>
        <title>Move committee index outside Attestation</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7549-move-committee-index-outside-attestation/16390</comments>
        
        <description>## Abstract

Move the committee&apos;s `index` field outside of the signed Attestation message to allow aggregation of equal consensus votes.

## Motivation

This proposal aims to make Casper FFG clients more efficient by reducing the average number of pairings needed to verify consensus rules. While all types of clients can benefit from this EIP, ZK circuits proving Casper FFG consensus will likely have the most impact.

On a beacon chain network with at least 262144 active indices, it&apos;s necessary to verify a minimum of `ceil(32*64 * 2/3) = 1366` attestations to reach a 2/3 threshold. Participants cast two votes at once: LMD GHOST vote and Casper-FFG vote. However, the Attestation message contains three elements:

1. LMD GHOST vote `(beacon_block_root, slot)`. Note: includes slot in the event (block, slot) voting is adopted.
2. FFG vote `(source, target)`
3. Committee index `(index)`

Signing over the 3rd item causes tuples of equal votes to produce different signing roots. If the committee index is moved outside of the Attestation message, the minimum number of attestations to verify to reach a 2/3 threshold is reduced to `ceil(32 * 2/3) = 22` (a factor of 62).

On-chain attestations can now be packed more space-efficiently into beacon blocks. This proposal allows for up to 8 slots worth of votes in a block, compared to 2 today. In other words, a chain with only 1/8 online proposers can still potentially include all votes on-chain.

## Specification

### Execution layer

This requires no changes to the Execution Layer.

### Consensus layer

- Set `index` field from `AttestationData` to a fixed value of zero
- Move committee indexing data to the outer `Attestation` container with `committee_bits`
- Increase the capacity of `aggregation_bits` to all committees in a slot

The full specification of the proposed change can be found in [`/specs/electra/beacon-chain.md`](https://github.com/ethereum/consensus-specs/blob/2c1f677187e6534aec77057a7d1cc746a40d3630/specs/electra/beacon-chain.md).

## Rationale

### Deprecation strategy

The `index` field in `AttestationData` can be deprecated by:

1. Removing the field 
2. Preserving the field and setting it to zero
3. Changing the field type to Optional (from EIP-7495 StableContainer)

This EIP chooses the second option to not complicate the inclusion of `AttesterSlashing` objects. While the `Attestation` container changes, `AttesterSlashing` includes indexed attestations without committee data.

### `MAX_ATTESTATIONS` value

The maximum size of an attestation increases, with a bitfield 64 times larger on networks with maxed committees. `MAX_ATTESTATIONS` value is reduced to limit the beacon block size while still increasing the total capacity of votes. A value of 8 increases the voting capacity by 4 while having the same attestation space size with a network of 1.2M active indices.
Read the details [here](/EIPs/assets/eip-7549/complexity_analysis).

### `MAX_ATTESTER_SLASHINGS` value

On-chain `AttesterSlashing` includes a list of participants&apos; indices. With this EIP, the worst-case size increases by 64 times, resulting in an uncompressed size of 488 KB per `AttesterSlashing` in a network of 1M validators. Snappy compression reduces it to 320 KB, which is still significant. To bound the maximum size of the block, this proposal reduces `MAX_ATTESTER_SLASHINGS` from 2 to 1, the minimum value.
Read the details [here](/EIPs/assets/eip-7549/complexity_analysis).

### Using `Bitvector` for `committee_bits`

The `committee_bits` sequence has a variable length with the max size `MAX_COMMITTEES_PER_SLOT = 64`. Encoding of the `Bitlist` includes its actual length, which doubles the size of the `committee_bits` compared to the `Bitvector` type. Beacon chain state transition ensures correctness of the `committee_bits` when the effective number of committees in a slot is less than its max value.

## Backwards Compatibility

This EIP introduces backward-incompatible changes to the block validation rule set on the consensus layer and must be accompanied by a hard fork.

## Security Considerations

### First block after the fork

Because the on-chain `Attestation` container changes, attestations from the prior fork can&apos;t be included in post-Electra blocks. Therefore, the first block after the fork may have zero attestations. LMD votes can still be applied to fork-choice via `on_attestation` handler, so there will be only a 1/32 loss of FFG votes. Attesters assigned to the last slot of the fork will incur one epoch worth of offline penalties. One possible mitigation is to change the Electra block body type to allow including attestations from both forks. However, the mitigation increases complexity for little gain, so this proposal chooses not to address the issue.

### Mutation over gossip

Moving the `index` field outside of the signed message allows malicious mutation only on the p2p gossip topic `beacon_attestation_${subnet_id}`. Everywhere else, the `Attestation` message is wrapped with an outer signature that prevents mutation.

Gossip verification rules for the `beacon_attestation_${subnet_id}` topic include:

&gt; - [REJECT] The attester is a member of the committee -- i.e., `attestation.attester_index` in `get_beacon_committee(state, attestation.data.slot, index)`

If an attacker mutates the `index` field, the above rule verification will fail, and the message will be dropped. If implementations run the above check before registering the attestation in a &apos;first-seen&apos; cache, there&apos;s no risk of cache pollution.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Wed, 01 Nov 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7549</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7549</guid>
      </item>
    
      <item>
        <title>Single Sign-On for Account Discovery</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7555-single-sign-on-for-account-discovery/16536</comments>
        
        <description>## Abstract
This proposal establishes a standardized interface and functionality for applications to discover user accounts besides the readily available EOA. Specifically discovering normal accounts and smart accounts that may have been deployed or configured using a signing key that is not the standard Ethereum secp256k1 curve. The objective is to ensure uniformity of address retrieval across applications, and domains.

## Motivation
The recent progress in account abstraction has led to significantly increased flexibility enabling use cases such as multi-signature transactions, social recovery, contract/account whitelisting, session keys and much more. However, with increased flexibility there comes an increased complexity. One area of increased complexity is account fragmentation -both at the EOA and smart account level - following from the inability to correctly identify all existing addresses by a user. In this EIP we present a potential solution that aims to unify the discovery and handling of such accounts.

Prior to [ERC-4337](/EIPs/EIPS/eip-4337), the standard approach to interacting with a smart contract account required a valid signature from a keypair using secp256k1. Since ERC-4337, alternative signing options have become popular, such as passkey, yubikey or ios/android secure enclaves, which do not conform to the secp256k1 curve, and require a paymaster to submit the transaction on the users behalf. Since providers implement additional logic into the key generation process (shamir, mpc, secure enclave, etc) alternative signers have no uniform way for a user to produce the same externally-owned account adresses, or smart account addresses across different applications. 

Secure hardware devices such as native passkeys, or yubikeys generate a unique keypair per domain. The implication is for application developers that natively integrate authentication methods such as those, will never be able to recover a uniform keypair. Practically, if we have the following scenario where there are two applications: a mobile app (App A), and a web based application (App B). If both implement a solution such as passkey, App A and App B would recover two different keys. This poses a hurdle to the user who would expect to have the same address across services (much like they would using a hardware wallet, or other wallets).

With the introduction of 4337, this problem is amplified. An application that wants its users to leverage 4337 (to abstract keys away, and generally improve the onboarding experience) will not be able to detect if a user has an existing smart account deployed. This will lead to the developer (or third party service providing the onboarding experience) to deploy a smart account on behalf of the user at the given address scoped to the apps domain.

Not being able to correctly identify existing accounts owned by a user will lead to account fragmentation. The fragmentation, as described early, exists because applications will identify them as a new user, and not one whom may already have an account. Leading to a single user having many unassociated accounts, with assets scattered amongst them, and no way to unify them.

This standard aims to achieve:
1. Standard way for applications to request a users signing address.
2. Standard way for applications to provide single sign-on (SSO) functionality for alternative signing methods.
3. Standard way for applications to disclose smart accounts that have been created through their own service.

This standard **does not** aim to achieve:
1. How a user can sign messages across domains.
2. How a provider generates a keypair for a user.
3. How an application handles the user interface logic.


## Specification
The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119 and RFC 8174.

### Definitions
- **Smart account** - An ERC-4337 compliant smart contract account that has a modular architecture.
- **Domain** - A string of text acting as an identification to a server or website (eg: `ethereum.org` or `ABCDE12345.com.example.app`).
- **EOA** - Accounts that are controlled by a single private key.
- **Provider** - A third party service provider that is able to authenticate a user and produce a keypair for the user.

### Redirects
An application looking to authenticate a user must navigate the user to a given provider&apos;s URI based on the `URI Request Syntax`. The application must implement a valid redirect URI for the callback in order to receive a valid response.

#### Available Routes
- `/auth/`: The route used to authenticate a user, and request credentials.
- `/sendTransaction/`: The route used to send a transaction payload for a user to sign. This is more of a convenient method to allow applications to do both authentication, and plugin registration within a single redirect, instead of requiring the user to perform two redirects.

### Schema
The `smart_account_address` should be returned in the CAIP-10 format.

#### Auth Route
##### Request Schema
```= swagger
 parameters:
    - in: query
      name: redirect_uri
      schema:
        type: string
      description: The uri that the provider should redirect back to.
   - in: query
      name: chain_id
      schema:
        type: string
      description: The chain_id of a given network.
```
##### Response Schema
```= swagger
 parameters:
  - in: query
      name: smart_account_address
      schema:
        type: string
      description: The on-chain address for a given smart account, formatted using CAIP-10
```

##### Request Syntax
```= swagger
https://&lt;PROVIDER_URI&gt;/auth/?
    redirect_uri=&lt;YOUR_REDIRECT_URI&gt;
    &amp;chain_id=&lt;CHAIN_ID&gt;
```
##### Response Syntax
```= swagger
https://&lt;YOUR_REDIRECT_URI&gt;/auth/?
    smart_account_address=&lt;SMART_ACCOUNT_ADDRESS&gt;
```

#### sendTransaction Route
##### Request Schema
```= swagger
 parameters:
    - in: query
      name: redirect_uri
      schema:
        type: string
      description: The uri that the provider should redirect back to.
   - in: query
      name: chain_id
      schema:
        type: string
      description: The chain_id of a given network.
   - in: query
      name: transaction
      schema:
        type: string
      description: The RLP encoded transaction that needs to be signed
```
##### Response Schema
```= swagger
 parameters:
  - in: query
      name: smart_account_address
      schema:
        type: string
      description: The on-chain address for a given smart account, formatted using CAIP-10
  - in: query
      name: tx_hash
      schema:
        type: string
      description: The hash of the transaction
```

##### Request Syntax
```= swagger
https://&lt;PROVIDER_URI&gt;/sendTransaction/?
    redirect_uri=&lt;YOUR_REDIRECT_URI&gt;
    &amp;chain_id=&lt;CHAIN_ID&gt;
    &amp;transaction=&lt;TRANSACTION_DATA&gt;
```
##### Response Syntax
```= swagger
https://&lt;YOUR_REDIRECT_URI&gt;/sendTransaction/?
    smart_account_address=&lt;SMART_ACCOUNT_ADDRESS&gt;
    &amp;tx_hash=&lt;TX_HASH&gt;
```

## Rationale
### Redirects
Taking inspiration from how SSO functions in the web today. We implement a similar redirect pattern, consisting of a simple request/response.

#### Application
##### Initial Request
An application would redirect a user to a specified provider, only passing along the callback url information. This is to ensure the providers website can remain stateless, and not rely on web requests.
##### Response from provider
When a user is redirected to the application, it can parse the response for a signer address, and associated smart account address.

#### Provider
Upon a user navigating to the provider website, the provider would parse the redirect url and authenticate the user. The authentication method does not matter, such that it can produce a valid public address, and recover any smart accounts that may have been deployed through the provider.

## Backwards Compatibility

No backward compatibility issues found.

## Reference Implementation
Using `location.replace()` vs `location.href` is up to the application to decide how they wish the experience to be handled.

Sample URI Request
```=
https://eth-sso.ethereum.org/auth?redirect_uri=http://myapp.com/eth-sso/callback/&amp;chain_id=1
```
Sample Response
```=
http://myapp.com/callback/?smart_account_address=0xb...c
```

Application logic
```javascript=
// https://myapp.com
// User triggered authentication function
function auth() {
    window.location.replace(&quot;https://eth-sso.ethereum.org/auth?redirect_uri=myapp.com&amp;chain_id=1/eth-sso/callback/&quot;);
};

// App level routing logic (generic router)
route(&quot;/eth-sso/callback/&quot;, function() {
    let params = (new URL(document.location)).searchParams;
    let smartAccountAddress = params.get(&quot;smart_account_address&quot;);
});
```

Provider Logic
```javascript=
// eg: https://eth-sso.ethereum.org/auth
route(&quot;/eth-sso/callback/&quot;, function(&quot;/auth&quot;) {
    let params = (new URL(document.location)).searchParams;
    let redirectUrl = params.get(&quot;redirect_uri&quot;);
    // Authenticate the user (eg: with passkeys)
    let address = &quot;...&quot;;
    // Get smart account if available
    let smartAccountAddress = getSmartAccount(address);
    window.location.replace(`http://${redirectUrl}/?smart_account_address=${smartAccountAddress}`);
});
```

## Security Considerations

&lt;!-- Needs discussion. --&gt;
- Is there a concern that a user can spoof another persons address, and that could be malicious? For example, circumventing the provider, and manually calling the redirect_url with a chosen address. A way around this would be having the user actually sign a challenge message, perhaps leveraging SIWE.

The absence of wildcard support in the redirect URI is intended to protect users from nested open redirect vulnerabilities. Allowing wildcards could enable attackers to redirect users to different pages under the supported wildcard, creating a vulnerability to open redirects.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).</description>
        <pubDate>Fri, 10 Nov 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7555</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7555</guid>
      </item>
    
      <item>
        <title>Block-level Warming with fair cost savings</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7557-block-level-warming/16642</comments>
        
        <description>## Abstract

A mechanism for a fair distribution of the gas costs associated with access to addresses and storage slots
among multiple transactions with shared items in their `accessList`.

## Motivation

[EIP-2929: Gas cost increases for state access opcodes](./eip-2929) introduced a new gas cost model that differentiates
between &quot;cold&quot; and &quot;warm&quot; access to accounts and storage slots.

However, the cost of every cold access is borne by each transaction separately, even though the validator only
needs to fetch the state object once for the entire block.

When multiple transactions access the same state object in the same block the fees charged for these transactions
do not accurately reflect the computations that block builders and validators perform for the blockchain state access
during transaction execution.

[EIP-2930: Optional access lists](./eip-2930) made it possible for transactions to pre-specify and pre-pay for the
accounts and storage slots that the transaction plans to access,
however, the cost is still paid repeatedly by each transaction rather than once at the block level.

With the [EIP-6800: Ethereum state using a unified verkle tree](./eip-6800) on the roadmap for inclusion,
the cost of reading from the Ethereum state and especially the contract code is expected to increase.

Especially affected by this upcoming change will be transactions that involve smart contracts with a high code size.

Each such transaction in the block will be forced to pay the full &quot;retail&quot; price for loading smart contract
bytecode during a transaction.

The validators, however, only have to perform the actual reading from the Ethereum state once per block,
and all subsequent reads of the values that were already referenced are significantly more efficient.

If witnesses are introduced to Ethereum blocks, the same witness can be reused by multiple transactions.
Requiring each transaction to pay regardless of the contents of the block is unfair and inefficient.

Another change that may be on the roadmap for Ethereum is Account Abstraction.
This change will see a large share of transactions being initiated by smart contracts directly.
It is reasonable to expect many of these Smart Contract Accounts to rely on the same core wallet implementations.
If each Account Abstraction transaction is charged a full gas cost of loading the Smart Contract Account code repeatedly,
such transactions would become significantly overpriced.

This difference is especially noticeable when compared to an EOA, which gets its validation logic loaded and executed for free.

In this scenario, the base gas fees would be taken from the senders and burned needlessly while block proposers
would be enjoying an unjustified excessive earning of priority gas fees.

A major distinction between this proposal and alternatives, such as [EIP-7863](./eip-7863), lies in performing a fair
distribution of gas savings between all participants - all transactions senders and the block builder.

## Specification

The [EIP-2930: Optional access lists](./eip-2930) already introduced the first part of the solution.
Each transaction can specify an array of `accessed_addresses` and `accessed_storage_keys` to announce its intention to
read those values during the execution of the transaction.

The sender of the transaction is then pre-charged with the cost of accessing this data but is given a small discount
compared to unannounced access.

The missing component is a mechanism to aggregate the gas costs of the cold access and redistribute the resulting
savings amongst the participating transactions.

### Overview

During the transaction execution, the cost of all storage-related operations is not affected,
and all rules from EIP-2929 and EIP-2930 continue to apply.

There are no changes to the block header or the transaction payload and receipt.

As the last operation of each block, the collected gas costs associated with storage access are redistributed
among the senders of all transactions withing a block.
This affects the balances of all these accounts in a way that only becomes observable in the next block.

This reimbursement&apos;s amount is proportional to the amount paid for the access in the first place.

### Participant transactions mapping

After the block builder finalizes the contents of the block, it iterates over all included transactions to read
the `accessList` component of each supported transaction.

The block builder then constructs an array containing each accessed address and each accessed slot, and an array of
transaction senders&apos; addresses that initiated at least one access to the given address or slot,
as well as the `priorityFeePerGas` that was paid for such access.

A sample JSON representation of the data structure that represents such a structure and is used in the pseudocode below:

```json
[
  {
    &quot;address&quot;: &quot;0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae&quot;,
    &quot;accessors&quot;: [
      {
        &quot;sender&quot;: &quot;0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1&quot;,
        &quot;priorityFeePerGas&quot;: &quot;1000&quot;
      },
      {
        &quot;sender&quot;: &quot;0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1&quot;,
        &quot;priorityFeePerGas&quot;: &quot;2000&quot;
      },
      {
        &quot;sender&quot;: &quot;0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0&quot;,
        &quot;priorityFeePerGas&quot;: &quot;1000&quot;
      },
      {
        &quot;sender&quot;: &quot;0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0&quot;,
        &quot;priorityFeePerGas&quot;: &quot;2000&quot;
      },
      {
        &quot;sender&quot;: &quot;0x22d491Bde2303f2f43325b2108D26f1eAbA1e32b&quot;,
        &quot;priorityFeePerGas&quot;: &quot;2000&quot;
      },
      {
        &quot;sender&quot;: &quot;0x22d491Bde2303f2f43325b2108D26f1eAbA1e32b&quot;,
        &quot;priorityFeePerGas&quot;: &quot;3000&quot;
      }
    ],
    &quot;slots&quot;: [
      {
        &quot;id&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000003&quot;,
        &quot;accessors&quot;: [
          {
            &quot;sender&quot;: &quot;0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1&quot;,
            &quot;priorityFeePerGas&quot;: &quot;1000&quot;
          },
          {
            &quot;sender&quot;: &quot;0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1&quot;,
            &quot;priorityFeePerGas&quot;: &quot;2000&quot;
          },
          {
            &quot;sender&quot;: &quot;0x22d491Bde2303f2f43325b2108D26f1eAbA1e32b&quot;,
            &quot;priorityFeePerGas&quot;: &quot;2000&quot;
          },
          {
            &quot;sender&quot;: &quot;0x22d491Bde2303f2f43325b2108D26f1eAbA1e32b&quot;,
            &quot;priorityFeePerGas&quot;: &quot;3000&quot;
          }
        ]
      },
      {
        &quot;id&quot;: &quot;0x0000000000000000000000000000000000000000000000000000000000000007&quot;,
        &quot;accessors&quot;: [
          {
            &quot;sender&quot;: &quot;0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0&quot;,
            &quot;priorityFeePerGas&quot;: &quot;1000&quot;
          },
          {
            &quot;sender&quot;: &quot;0xFFcf8FDEE72ac11b5c542428B35EEF5769C409f0&quot;,
            &quot;priorityFeePerGas&quot;: &quot;2000&quot;
          }
        ]
      }
    ]
  }
]

```

### Calculating a reimbursement of the burned base fee

Considering that the same amount of computation is needed to access an address or a slot regardless of the number of
transactions using one, it is reasonable for the protocol to only burn the gas cost of the cold access once.
As all transactions in the same block pay exactly the same `baseFeePerGas`, the single cost of accessing a cold item is
divided evenly among all transactions containing such access and the rest of the burned base fee is reimbursed.

### Setting an absolute minimal cost of cold state access

If a large number of transactions all access the same addresses or slots, the cost of each cold access may get
way too low which may represent a potential DoS attack vector.

In order to prevent that, the gas cost of including an entity in the access list cannot be lower
than `MIN_ACCESS_LIST_ENTRY_COST`, which is set to `32 gas`.

This value is equivalent to the calldata cost of including two bytes long identifier of entries in `block_access_list`.

### Calculating a reimbursement of the charged priority fee

Each transaction pays an individual `priorityFeePerGas` value and redistributing this part of the cold access cost
is more complex.

We propose the following approach to a fair reimbursement of the paid `priorityFee`:

1. The validator gets paid the `priorityFee` for each cold access only once, but according to the highest `priorityFee`
   among the transactions containing the said cold access.
2. The rest of the Ether that was charged by the validator as a  `priorityFee` is redistributed back to all the senders
   of transactions containing the same cold access in proportion to their **marginal contribution** to the
   **total gains** of the transaction.
3. The block builder is only paid for access once and the remaining value is reimbursed.
   So the `total reimbursement` value is a difference between the sum of value charged and the block builder&apos;s reward.
4. The `total gains` of the transaction is defined by a sum of the `priorityFee` paid out to the block builder
   and `total reimbursement` made to all participants.
5. Mathematically, the `marginal contribution` of a transaction to the `total gains` is defined as
   the difference between the sum `total gains` value calculated when all transactions in a block are included,
   and when all transactions are included except for this particular transaction.
   In practice this value always amounts to `priorityFee * gasCost`.

   &gt; 𝑀𝐶𝑖 = 𝑣(𝑆 ∪ {𝑖}) − 𝑣(𝑆)

A single transaction accessing an address or a slot that is not shared by other transactions does not trigger a reimbursement,
and therefore has a zero marginal contribution.

### Efficiently storing the access lists in the block history

The contents of the `accessList` parameter are part of the Ethereum history and the potential cost of keeping this
data in the blockchain must be accounted for when implementing this change.
There is currently no additional charge applied to the `accessList` parameter, due to the cost of including
an address or a storage slot in the `accessList` being a constant value that is significantly higher than the
potential cost of storing the `accessList` at the cost of  a
dynamically sized `calldata` field.

With the block-level warming there is a change that makes it possible for a transaction sender to construct
transactions with a large `accessList` that cost very little to be included, and this can be used to bloat the
blockchain size.

This potential bloating of the block size also presents a challenge for the propagation of the block in a P2P network.

In order to minimize the cost of permanently storing access lists, we propose the following changes to
the `execution_payload` structure:

1. Add a new `block_access_list` field.

 The execution clients create a combined block-level &quot;access list&quot; that contains all unique entries from all
 transactions in the block.
2. All individual transaction `accessList` fields replace the full entries with a
 compact 2 bytes long reference to the `block_access_list` in the same order they appeared originally.

With this approach shared entries in the access lists cannot cause sufficient bloating of the block size.

There is no need to introduce any observable changes to the RPC API as this &quot;compression&quot; can be unwrapped by the
clients in real time.

### Pseudocode implementation of the reimbursement calculation algorithm

```typescript
export function calculateBlockColdAccessReimbursement (
  baseFeePerGas: string,
  accessDetailsMap: AddressAccessDetails[]
): Map&lt;string, reimbursement&gt; {
  const reimbursements = new Map&lt;string, Reimbursement&gt;()
  for (const accessDetail of accessDetailsMap) {
    calculateItemColdAccessReimbursement(accessDetail.accessors, baseFeePerGas, COLD_ACCOUNT_ACCESS_COST, reimbursements)
    for (const slot of accessDetail.slots) {
      calculateItemColdAccessReimbursement(slot.accessors, baseFeePerGas, COLD_SLOAD_COST, reimbursements)
    }
  }
  return reimbursements
}

function calculateItemColdAccessReimbursement (
  unsortedAccessors: AccessDetails[],
  baseFeePerGas: string,
  accessGasCost: string,
  reimbursements: Map&lt;string, Reimbursement&gt;
): void {
  const sortedAccessDetails = unsortedAccessors.sort((a, b) =&gt; { return parseInt(b.priorityFeePerGas) - parseInt(a.priorityFeePerGas) })
  const addressAccessN = sortedAccessDetails.length
  const reimbursementPercent = (addressAccessN - 1) / addressAccessN
  const reimbursementsFromCoinbase = calculatePriorityFeeReimbursements(sortedAccessDetails, accessGasCost)
  for (let i = 0; i &lt; sortedAccessDetails.length; i++) {
    const accessor = sortedAccessDetails[i]
    const reimbursement = reimbursements.get(accessor.sender) ?? { reimbursementFromBurn: 0n, reimbursementFromCoinbase: 0n }
    const adjustedAccessGasCost = Math.max(MIN_ACCESS_LIST_ENTRY_COST, parseInt(accessGasCost) * reimbursementPercent)
    reimbursement.reimbursementFromBurn += BigInt(adjustedAccessGasCost * parseInt(baseFeePerGas))
    reimbursement.reimbursementFromCoinbase += BigInt(reimbursementsFromCoinbase[i])
    reimbursements.set(accessor.sender, reimbursement)
  }
}

export function calculatePriorityFeeReimbursements (sortedAccesses: AccessDetails[], accessGasCost: string) {
  // Validator charge is based on the highest paid priority fee per gas
  const validatorFee = parseInt(sortedAccesses[0].priorityFeePerGas) * parseInt(accessGasCost)

  // Accumulate the sum of all &quot;contributions&quot;, at least the top transaction contribution
  let totalContributions = validatorFee
  // Accumulate cost of gas paid to validator for accessing the same address/slot/chunk
  let totalSendersCharged = parseInt(sortedAccesses[0].priorityFeePerGas) * parseInt(accessGasCost)
  // Starting with `1` as element at `0` is explicitly shown here to be used as `validatorFee`
  for (let i = 1; i &lt; sortedAccesses.length; i++) {
    const charge = parseInt(sortedAccesses[i].priorityFeePerGas) * parseInt(accessGasCost)
    totalContributions += charge
    totalSendersCharged += charge
  }

  // Calculate the total amount of ether to be reimbursed for this access
  const totalReimbursement = totalSendersCharged - validatorFee
  if (totalReimbursement == 0) {
    // possible if only single transaction or if all priority fees are 0
    return Array(sortedAccesses.length).fill(0)
  }

  // Calculate actual charges and reimbursements
  const reimbursements = [Math.floor(totalReimbursement * topTransactionContribution / totalContributions)]
  for (let i = 1; i &lt; sortedAccesses.length; i++) {
    const charge = parseInt(sortedAccesses[i].priorityFeePerGas) * parseInt(accessGasCost)
    const calldataCharge = parseInt(sortedAccesses[i].priorityFeePerGas) * MIN_ACCESS_LIST_ENTRY_COST
    const reimbursementToCalldata = charge - calldataCharge
    const reimbursementToContribution = Math.floor(totalReimbursement * charge / totalContributions)
    reimbursements.push(Math.min(reimbursementToCalldata, reimbursementToContribution))
  }
  return reimbursements
}
```

Note that two accumulating values, `reimbursementFromBurn` and `reimbursementFromCoinbase`,
are necessary in light of [EIP-1559: Fee market change for ETH 1.0 chain](./eip-1559) in order to differentiate
between the Ether reimbursement that is originating from a reduced block gas burn,
and from the reduced block proposer priority fee per gas reward.

### Future EIP-6800 gas reform support

Once [EIP-6800](./eip-6800) is active, the cost of accessing a contract code for a cold address is expected to change.

Instead of being a constant value of `COLD_ACCOUNT_ACCESS_COST` (currently 2600 gas),
the total cost will be determined by the number of 31-byte &quot;chunks&quot; the code consists of.
Each &quot;chunk&quot; of code will have a cost of `CODE_CHUNK_ACCESS_COST` (currently 200 gas).

For a maximum contract size of `24576 bytes` defined by [EIP-170](./eip-170) the cost of accessing this contract
surges from `2600` to `158600` gas.

This change will likely require the `accessList` parameter of transactions to be adjusted for transactions
to be able to specify which code chunks will be accessed.

In such case the changes are reflected in the reimbursement function as well, which is updated by adding the following code
in order to redistribute the shared cost of accessing the same code chunk in multiple transactions:

```typescript
const reimbursementsFromCoinbase = calculatePriorityFeeReimbursements(sortedCodeChunkAccessDetails, CHUNK_ACCESS_COST)
for (let i = 0; i &lt; sortedAccessDetails.length; i++) {
  const reimbursement = reimbursements.get(accessor.sender)
  reimbursement.reimbursementFromBurn += CHUNK_ACCESS_COST * block.baseFeePerGas * reimbursementPercent
  reimbursement.reimbursementFromCoinbase += reimbursementsFromCoinbase[i]
}
```

### Cost redistribution system operation

The [EIP-4895: Beacon chain push withdrawals as operations](eip-4895) sets a precedent by introducing a concept of a `system-level withdrawal operation`.

We propose the introduction of yet another system-level operation called `cost redistribution`.
The `redistributions` in an execution payload are processed after any user-level transactions are applied.

The block builder or a validator prepares a list of reimbursement information.

For each `redistribution` in the list, the implementation increases the balance of the address specified by the amount `reimbursementFromBurn + reimbursementFromCoinbase`.

The balance of the `coinbase` is reduced by a sum of all `reimbursementFromCoinbase` values.

## Rationale

### Current cold storage gas cost is unfair

As described in the [Motivation](#motivation) section, the amount of gas that users spend on accessing the contract code does not reflect the actual cost of this access for the block builder or a validator.

The more popular the contract code or a storage slot is, the more transactions in each block should share the cost.
However, the current system multiplies the cost for the users instead of dividing it.

### Issuing a regular gas refund after a transaction is not possible

There exists a list of EVM instructions that trigger both a gas charge and a gas refund.
A notable example of such operations is the `0x55 SSTORE` opcode as defined in [EIP-1283: Net gas metering for SSTORE without dirty maps](./eip-1283).
Intuitively it seems reasonable to issue the gas reimbursements for the shared cold storage access in the same fashion.

However, this approach significantly complicates the block-building process.
In this case, the inclusion or exclusion of a transaction at the end of the block triggers observable effects in transactions included at the beginning of the block, and this makes the job of finding a valid set of transactions for a block potentially computationally unsolvable.

Therefore, we propose performing the reimbursements at the end of the block, where it cannot change the behavior of any transaction in the block.

### Weighting priority fee reimbursement

A common game-theoretical answer to the problem of calculating a fair redistribution of the payoff of the
results of the participants&apos; cooperation is the use of Shapley values.

However, we argue that the proposed distribution of the `priorityFee` reimbursements is sufficiently fair while being
a lot easier to compute or articulate.

## Backwards Compatibility

This proposal does not introduce a change to any behavior that can be observed by a smart contract during its execution.
The only effect this change has is a lower effective gas cost for the transaction senders.

## Security Considerations

The upper limit of storage reads in one block is not affected by this change as the gas charge is done with the
full cost of `COLD_ACCOUNT_ACCESS_COST` or `COLD_SLOAD_COST`.

The maximum amount of memory and computation required to calculate the reimbursements according to the
specified algorithm is insignificant.

It appears that this change does not have any negative security implications.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 01 Oct 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7557</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7557</guid>
      </item>
    
      <item>
        <title>Simple NFT, Simplified ERC-721</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7561-simple-nft/16695</comments>
        
        <description>## Abstract

This ERC is a new NFT asset designed based on the user contract wallet (including account abstraction), and is forward compatible with [ERC-721](/EIPs/EIPS/eip-721). To keep NFT assets simple, this ERC removes the `approve`, `setApprovalForAll`, `getApproved`, `isApprovedForAll` and `safeTransferFrom` functions of ERC-721.

## Motivation

[ERC-721](/EIPs/EIPS/eip-721) defines Ethereum-based standard NFT that can be traded and transferred, but the essence of ERC-721 is based on the externally-owned account (EOA) wallet design. An EOA wallet has no state and code storage, and the smart contract wallet is different.

Almost all ERCs related to NFTs are add functions, but our opinion is the opposite. We think the NFT contract should be simpler, with more functions taken care of by the smart contract wallet.

Our proposal is to design a simpler NFT asset based on the smart contract wallet.

It aims to achieve the following goals:

1. Keep the NFT contract simple, only responsible for the `transferFrom` function.
2. `approve`, `getApproved`, `setApprovalForAll` and `isApprovedForAll` functions are not managed by the NFT contract. Instead, these permissions are managed at the user level, offering greater flexibility and control to users. This change not only enhances user autonomy but also mitigates certain risks  associated with the ERC-721 contract&apos;s implementation of these functions. 
3. Remove the `safeTransferFrom` function. A better way to call the other party&apos;s NFT assets is to access the other party&apos;s own contract instead of directly accessing the NFT asset contract.
4. Forward compatibility with ERC-721 means that all NFT can be compatible with this proposal.

## Specification

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

Compliant contracts MUST implement the following interface:

```solidity
pragma solidity ^0.8.20;

/**
 * @title ERC7561 Simple NFT interface 
 * @dev See https://ercs.ethereum.org/ERCS/erc-7561
 */
interface IERC7561 {
    /**
     * @notice Used to notify transfer NFT.
     * @param from Address of the from
     * @param to Address of the receive
     * @param tokenId The transaction token id 
     */
    event Transfer(
        address indexed from,
        address indexed to,
        uint256 indexed tokenId
    );

    /**
     * @notice  Count all NFTs assigned to an owner
     * @param owner Address of the owner
     * @return The number of NFTs owned by `owner`, possibly zero
     */
    function balanceOf(address owner) 
        external
        view
        returns (uint256);

    /**
     * @notice Find the owner of an NFT
     * @param tokenId The identifier for an NFT
     * @return The address of the owner of the NFT
     */
    function ownerOf(uint256 tokenId) 
        external  
        view
        returns (address);
	  

    /**
     * @notice Transfer ownership of an NFT
     * @param from Address of the from
     * @param to Address of the to
     * @param tokenId The NFT to transfer
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

}
```

## Rationale

The proposal is to simplify NFT standards by removing `approve`, `setApprovalForAll`, `getApproved`, `isApprovedForAll` and `safeTransferFrom` functions. This simplification aims to enhance security, reduce complexity, and improve efficiency, making the standard more suitable for smart contract wallet environments while maintaining essential functionalities.


## Backwards Compatibility

As mentioned in the beginning, this ERC is forward compatible with [ERC-721](/EIPs/EIPS/eip-721), ERC-721 is backward compatible with this ERC.

## Reference Implementation

**forward compatible with [ERC-721](/EIPs/EIPS/eip-721)**

```solidity
pragma solidity ^0.8.20;

import &quot;./IERC7561.sol&quot;;
import &quot;../../math/SafeMath.sol&quot;;

/**
 * @title Standard ERC7561 NFT
 * @dev Note: the ERC-165 identifier for this interface is 0xc1b31357
 * @dev Implementation of the basic standard NFT.
 */
contract ERC7561 is IERC7561 {

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    mapping(uint256 tokenId =&gt; address) private _owners;

    mapping(address owner =&gt; uint256) private _balances;

    uint256 private _totalSupply;

    function totalSupply() external view returns (uint256) {
        return _totalSupply;
    }

    function balanceOf(address owner) public view  returns (uint256) {
        require (owner != address(0));
        
        return _balances[owner];
    }

    function ownerOf(uint256 tokenId) public view  returns (address) {
        return _requireOwned(tokenId);
    }


    function transferFrom(address from, address to, uint256 tokenId) public  {

        require(from == msg.sender);

        require (to != address(0) );

        address previousOwner = _update(to, tokenId);

        require(previousOwner == from);
    }


    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
        return _owners[tokenId];
    }

    function _requireOwned(uint256 tokenId) internal view returns (address) {
        address owner = _ownerOf(tokenId);
        require(owner != address(0));
            
        return owner;
    }

    function _update(address to, uint256 tokenId) internal virtual returns (address) {
        address from = _ownerOf(tokenId);

        
        // Execute the update
        if (from != address(0)) {         

            unchecked {
                _balances[from] -= 1;
            }
        }

        if (to != address(0)) {
            unchecked {
                _balances[to] += 1;
            }
        }

        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        return from;
    }

}
```


## Security Considerations

It should be noted that this ERC is not backward compatible with [ERC-721](/EIPs/EIPS/eip-721), so there will be incompatibility with existing dapps.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 29 Oct 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7561</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7561</guid>
      </item>
    
      <item>
        <title>Account Abstraction Validation Scope Rules</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7562-account-abstraction-validation-scope-rules/16683</comments>
        
        <description>## Abstract

This document describes the rules Account Abstraction protocols should follow, during the validation phase of Account Abstraction transactions,
such as [ERC-4337](./eip-4337) `UserOperation` or RIP-7560 (Native Account Abstraction), which are enforced off-chain by a
block builder or a standalone bundler, and the rationale behind each one of them.

## Motivation

With Account-Abstraction, instead of hard-coded logic for processing a transaction (validation, gas-payment, and execution), this logic is executed by EVM code.
The benefits for the account are countless -
- abstracting the validation allows the contract to use different signature schemes, multisig configuration, custom recovery, and more.
- abstracting gas payments allows easy onboarding by 3rd party payments, paying with tokens, cross-chain gas payments
- abstracting execution allows batch transactions

All of the above are missing from the EOA account model.

However, there is one rule a transaction must follow to preserve the decentralized network: once submitted into the network (the mempool), the transaction is guaranteed to pay. This comes to prevent denial-of-service attacks on the network.

The EOA model implicitly follows the rule: a valid transaction can&apos;t become invalid without payment by the account: e.g. account balance can&apos;t be reduced (except with a higher paying transaction)

This rule makes the network sustainable and DoS-protected: the network can&apos;t be cheaply attacked by a mass of transactions. An attack (sending a mass of transactions) is expensive, and gets more expensive as the network clogs. Legitimate users pay more, and can delay operations to avoid the cost, but the attacker pays a huge (and increasing) amount to keep the network clogged.

To mimic the same incentive structure in any Account Abstraction system, we suggest the following transaction validation rules.
These validation rules only apply to the validation phase of Account Abstraction transactions, not their entire executed code path.

For the actual interfaces of those contract-based accounts see the definitions in ERC-4337 and RIP-7560.

This documentation uses the terminology &quot;UserOperation&quot; for a transaction created by a smart contract account, and closely follows [ERC-4337](./eip-4337) terminology.
However, the rules apply to any Account Abstraction framework that uses EVM code to perform transaction validation and makes a distinction between validation (whether the operation is eligible for inclusion on the protocol level) and execution (on-chain execution and gas payment) in a public mempool.

## Specification

### Validation Rules Types
We define two types of validation rules: **network-wide rules** and **local rules**.

A violation of any validation rule by a UserOperation results in the UserOperation being dropped from the mempool and excluded from a bundle.

**Network-wide rule** is a rule, that its violation by a UserOperation validation should result in a reputation damage for the peer bundler that sent this UserOperation in the p2p mempool.
A peer bundler with a critically low reputation will eventually be marked as a malicious **spammer** peer.

**Local rule** is a rule that is enforced in the context of each bundler&apos;s local state, which may be different for each bundler and different bundlers may not always be in agreement on these rules&apos; violations.
Thus, The bundler that sent the violating UserOperation should not suffer a p2p reputation damage by its peers.

### Constants

| Title                                | Value                       | Comment                                                                                                                 |
|--------------------------------------|-----------------------------|-------------------------------------------------------------------------------------------------------------------------|
| `MIN_UNSTAKE_DELAY`                  | 86400                       | 1 day, which provides a sufficient withdrawal delay to prevent most sybil attacks                                       |
| `MIN_STAKE_VALUE`                    | Adjustable per chain value  | Equivalent to ~$1000 in native tokens, which provides a sufficient capital requirement to prevent most sybil attacks    |
| `SAME_SENDER_MEMPOOL_COUNT`          | 4                           | Maximum number of allowed userops in the mempool from a single sender.                                                  |
| `SAME_UNSTAKED_ENTITY_MEMPOOL_COUNT` | 10                          | Maximum number allowed in the mempool of UserOperations referencing the same unstaked entity                            |
| `THROTTLED_ENTITY_MEMPOOL_COUNT`     | 4                           | Number of `UserOperations` with a throttled entity that can stay in the mempool                                         |
| `THROTTLED_ENTITY_LIVE_BLOCKS`       | 10                          | Number of blocks a `UserOperations` with a throttled entity can stay in mempool                                         |
| `THROTTLED_ENTITY_BUNDLE_COUNT`      | 4                           | Number of `UserOperations` with a throttled entity that can be added in a single bundle                                 |
| `MIN_INCLUSION_RATE_DENOMINATOR`     | 100 (client) \ 10 (bundler) | A denominator of a formula for entity reputation calculation                                                            |
| `THROTTLING_SLACK`                   | 10                          | Part of a reputation formula that allows entities to legitimately reject some transactions without being throttled      |
| `BAN_SLACK`                          | 50                          | Part of a reputation formula that allows throttled entities to reject some transactions without being throttled         |
| `BAN_OPS_SEEN_PENALTY`               | 10000                       | A value to put into the opsSeen counter of entity to declare as banned                                                  |
| `MAX_OPS_ALLOWED_UNSTAKED_ENTITY`    | 10000                       |                                                                                                                         |
| `PRE_VERIFICATION_OVERHEAD_GAS`      | 50000                       | Gas used by the `EntryPoint` per `UserOp` that cannot be tracked on-chain                                               |
| `MAX_VERIFICATION_GAS`               | 500000                      | Maximum gas verification functions may use                                                                              |
| `MAX_USEROP_SIZE`                    | 8192                        | Maximum size of a single packed and ABI-encoded `UserOperation` in bytes                                                |
| `MAX_CONTEXT_SIZE`                   | 2048                        | Maximum size of a `context` byte array returned by a paymaster in a single `UserOperation` in bytes                     |
| `MAX_BUNDLE_SIZE`                    | 262144                      | Maximum size of an ABI-encoded bundle call to the `handleOps` function in bytes                                         |
| `MAX_BUNDLE_CONTEXT_SIZE`            | 65536                       | Maximum total size of all `context` byte arrays returned by all paymasters in all `UserOperations` in a bundle in bytes |
| `VALIDATION_GAS_SLACK`               | 4000                        | An amount of gas that must be added to the estimations of `verificationGasLimit` and `paymasterVerificationGasLimit`    |

### Validation Rules

### **Definitions**:
1. **Validation Phase**: there are up to three frames during the validation phase onchain
    1. `sender` deployment frame (once per account)
    2. `sender` validation (required)
    3. `paymaster` validation frame (optional)

2. **Execution Phase**: there are up to two frames during the execution phase onchain
   1. `sender` execution frame (required)
   2. `paymaster` post-transaction frame (optional)

   The validation rules only apply during the validation phase. Once a UserOperation is validated, it is guaranteed to pay. There are no restrictions on execution, neither account (callData) nor paymaster (postOp)

2. **Entity**: a contract that is explicitly specified by the `UserOperation`.
   Includes the `factory`, `paymaster`, `aggregator`, and staked `account`, as discussed below. \
   Each &quot;validation frame&quot; is attributed to a single entity. \
   Entity contracts must have non-empty code on-chain.
3. **Canonical Mempool**: The rules defined in this document apply to the main mempool shared by all bundlers on the network.
4. **Staked Entity:** an entity that has a locked stake of at least `MIN_STAKE_VALUE`
   and an unstake delay of at least `MIN_UNSTAKE_DELAY`.
5. **Associated storage:** a storage slot of any smart contract is considered to be &quot;associated&quot; with address `A` if:
    1. The slot value is `A`
    2. The slot value was calculated as `keccak(A||x)+n`, where `x` is a `bytes32` value, and `n` is a value in the range 0..128
6. **Using an address**: accessing the code of a given address in any way.
   This can be done by executing `*CALL` or `EXTCODE*` opcodes for a given address.
7. **Spammer** - a P2P peer bundler that attempts a DoS attack on the mempool by sending other peers with a large number of invalid UserOperations.
   Bundlers MUST detect and disconnect from such peers, as described in the [Mempool Validation Rules](#mempool-validation-rules) section.

### Reputation Definitions
1. **opsSeen**: a per-entity counter of how many times a unique valid `UserOperation` referencing this entity
   was received by this bundler.
   This includes `UserOperation` received via incoming RPC calls or through a P2P mempool protocol.

2. **opsIncluded**: a per-entity counter of how many times a unique valid `UserOperation` referencing this entity
   appeared in an actual included `UserOperation`. \
   Calculation of this value is based on UserOperationEvents and is only counted for `UserOperations` that were
   previously counted as `opsSeen` by this bundler.
3. **Refresh rate**: Both of the above values are updated every hour as `value = value * 23 // 24` \
   Effectively, the value is reduced to 1% after 4 days.
4. **inclusionRate**: Ratio of `opsIncluded`  to `opsSeen`


### Reputation Calculation

We define a value `max_seen = opsSeen // MIN_INCLUSION_RATE_DENOMINATOR`.

The reputation state of each entity is determined as follows:

1. **BANNED**: `max_seen &gt; opsIncluded + BAN_SLACK`
2. **THROTTLED**: `max_seen &gt; opsIncluded + THROTTLING_SLACK`
3. **OK**: otherwise

Note that new entities start with an `OK` reputation.

Because of the reputation `refresh rate`, note that a malicious paymaster can at most cause the network (only the p2p network, not the blockchain) to process `BAN_SLACK * MIN_INCLUSION_RATE_DENOMINATOR / 24` non-paying ops per hour.

### Running the Validation Rules

1. A block builder or a bundler should perform a full validation once before accepting a `UserOperation` into its mempool, and again before including it in a bundle/block.
2. The bundler should trace the validation phase of the UserOperation and apply all the rules defined in this document.
3. A bundler should also perform a full validation of the entire bundle before submission.
4. The validation rules prevent an unstaked entity from altering its behavior between simulation and execution of the UserOperation.
   However, a malicious staked entity can detect that it is running in a bundle validation and cause a revert. Thus, a third tracing simulation of the entire bundle should be performed before submission.
5. The failed `UserOperation` should be dropped from the bundle.
6. The bundler should update the reputation of the staked entity that violated the rules, and consider it `THROTTLED`/`BANNED` as described below. 

### Mempool Validation Rules

1. A `UserOperation` is broadcast over the P2P protocol with the following information:
    1. The `UserOperation` itself
    2. The blockhash this `UserOperation` was originally verified against.
2. Once a `UserOperation` is received from another bundler it should be verified locally by a receiving bundler.
3. A received `UserOperation` may fail any of the reasonable static checks, such as:
   invalid format, values below minimum, submitted with a blockhash that isn&apos;t recent, etc.
   In this case, the bundler should drop this particular `UserOperation` but keep the connection.
4. The bundler should check the `UserOperation` against the nonces of last-included bundles and silently drop `UserOperations` with `nonce` that was recently included.
   This invalidation is likely attributable to a network race condition and should not cause a reputation change.
5. If a received `UserOperation` fails against the current block:
    1. Retry the validation against the block the `UserOperation` was originally verified against.
    2. If it succeeds, silently drop the `UserOperation` and keep the connection.
    3. If it fails, mark the sender as a &quot;spammer&quot; (disconnect from that peer and block it permanently).

### Opcode Rules
* Block access from opcodes that access information outside of storage and code (aka &quot;environment&quot;).
    * **[OP-011]** Blocked opcodes:
        * `ORIGIN` (`0x32`)
        * `GASPRICE` (`0x3A`)
        * `BLOCKHASH` (`0x40`)
        * `COINBASE` (`0x41`)
        * `TIMESTAMP` (`0x42`)
        * `NUMBER` (`0x43`)
        * `PREVRANDAO`/`DIFFICULTY` (`0x44`)
        * `GASLIMIT` (`0x45`)
        * `BASEFEE` (`0x48`)
        * `BLOBHASH` (`0x49`)
        * `BLOBBASEFEE` (`0x4A`)
        * `CREATE` (`0xF0`) (except in the &quot;Contract Creation&quot; and &quot;Staked factory creation&quot; sections, below)
        * `INVALID` (`0xFE`)
        * `SELFDESTRUCT` (`0xFF`)
    * **[OP-012]** `GAS` (`0x5A`) opcode is allowed, but only if followed immediately by `*CALL` instructions, else it is blocked.\
      This is a common way to pass all remaining gas to an external call, and it means that the actual value is
      consumed from the stack immediately and cannot be accessed by any other opcode.
    * **[OP-13]** any &quot;unassigned&quot; opcode.
* **[OP-020]** Revert on &quot;out of gas&quot; is forbidden as it can &quot;leak&quot; the gas limit or the current call stack depth.
* Contract creation:
    * **[OP-031]** `CREATE2` is allowed exactly once in the deployment frame and must deploy code for the &quot;sender&quot; address.
      (Either by the factory itself, or by a utility contract it calls)
    * **[OP-032]** If there is a `factory` (even unstaked), the `sender` contract is allowed to use `CREATE` opcode
      (That is, only the sender contract itself, not through utility contract)
* Access to an address without a deployed code is forbidden:
    * **[OP-041]** For `EXTCODE*` and `*CALL` opcodes.
    * **[OP-042]** Exception: access to the &quot;sender&quot; address is allowed.
      This is only possible in `factory` code during the deployment frame.
* Allowed access to the `EntryPoint` address:
    * **[OP-051]** May call `EXTCODESIZE ISZERO`\
      This pattern is used to check destination has a code before the `depositTo` function is called.
    * **[OP-052]** May call `depositTo(sender)` with any value from either the `sender` or `factory`.
    * **[OP-053]** May call the fallback function from the `sender` with any value.
    * **[OP-054]** Any other access to the `EntryPoint` (either of the `*CALL` or `EXT*` opcodes) is forbidden.
    * **[OP-055]** May call `incrementNonce())` from the `sender`
* `*CALL` opcodes:
    * **[OP-061]** `CALL` with `value` is forbidden. The only exception is a call to the `EntryPoint` described above.
    * **[OP-062]** Precompiles:
        * Only allow known accepted precompiles on the network, that do not access anything in the blockchain state or environment.
        * The core precompiles 0x1 .. 0x11
        * The RIP-7212 secp256r1 precompile, on networks that accepted it.
* **[OP-070]** Transient Storage slots defined in [EIP-1153](./eip-1153) and accessed using `TLOAD` (`0x5c`) and `TSTORE` (`0x5d`) opcodes
  are treated exactly like persistent storage (SLOAD/SSTORE).
* **[OP-080]** `BALANCE` (`0x31`) and `SELFBALANCE` (`0x47`) are allowed only from a staked entity, else they are blocked.


### Code Rules

* **[COD-010]** Between the first and the second validations, the `EXTCODEHASH` value of any visited address,
  entity, or referenced library, may not be changed.\
  If the code is modified, the UserOperation is considered invalid.

### Storage Rules

The storage access with `SLOAD` and `SSTORE` (and `TLOAD`, `TSTORE`) instructions within each phase is limited as follows:

* **[STO-010]** Access to the &quot;account&quot; storage is always allowed.
* Access to associated storage of the account in an external (non-entity) contract is allowed if either:
    * **[STO-021]**  The account already exists.
    * **[STO-022]**  There is an `initCode` and the `factory` contract is staked.
* If the entity (`paymaster`, `factory`) is staked, then it is also allowed:
    * **[STO-031]** Access the entity&apos;s own storage.
    * **[STO-032]** Read/Write Access to storage slots that are associated with the entity, in any non-entity contract.
    * **[STO-033]** Read-only access to any storage in non-entity contract.

### Local Rules

Local storage rules protect the bundler against denial of service at the time of bundling. They do not affect mempool propagation and cannot cause a bundler to be marked as a &quot;spammer&quot;.
* **[STO-040]** `UserOperation` may not use an entity address (`factory`/`paymaster`/`aggregator`) that is used as an &quot;account&quot; in another `UserOperation` in the mempool. \
  This means that `Paymaster`, `Factory` or `Aggregator` contracts cannot practically be an &quot;account&quot; contract as well.
* **[STO-041]** `UserOperation` may not use associated storage (of either its account or from staked entity) in a contract that is a &quot;sender&quot; of another UserOperation in the mempool.

### General Reputation Rules

The following reputation rules apply for all staked entities, and for unstaked paymasters. All rules apply to all of these entities unless specified otherwise.

* **[GREP-010]** A `BANNED` address is not allowed into the mempool.\
  Also, all existing `UserOperations` referencing this address are removed from the mempool.
* **[GREP-020]** A `THROTTLED` address is limited to:
    * `THROTTLED_ENTITY_MEMPOOL_COUNT` entries in the mempool.
    * `THROTTLED_ENTITY_BUNDLE_COUNT` `UserOperations` in a bundle.
    * Can remain in the mempool only for `THROTTLED_ENTITY_LIVE_BLOCKS`.
* **[GREP-040]** If an entity fails the bundle creation after passing second validation, its `opsSeen` set to `BAN_OPS_SEEN_PENALTY`, and `opsIncluded` to zero, causing it to be `BANNED`.
* **[GREP-050]** When a UserOperation is replaced (by submitting a new UserOperation, with higher gas fees), and an entity (e.g. a paymaster) is replaced, then the removed entity has its reputation (opsSeen counter) decremented by 1.

### Staked Entities Reputation Rules

* **[SREP-010]** The &quot;canonical mempool&quot; defines a staked entity if it has `MIN_STAKE_VALUE` and unstake delay of `MIN_UNSTAKE_DELAY`
* **[SREP-020]** MOVED TO GREP-010
* **[SREP-030]** MOVED TO GREP-020
* **[SREP-040]** An `OK` staked entity is unlimited by the reputation rule.
    * Allowed in unlimited numbers in the mempool.
    * Allowed in unlimited numbers in a bundle.
* **[SREP-050]** MOVED TO GREP-040

### Entity-specific Rules

* **[EREP-010]** For each `paymaster`, the bundler must track the total gas `UserOperations` using this `paymaster` may consume.
    * Bundler should not accept a new `UserOperation` with a paymaster to the mempool if the maximum total gas cost of all userops in the mempool, including this new `UserOperation`, is above the deposit of that `paymaster` at the current gas price.
* **[EREP-011]** REMOVED
* **[EREP-015]** A `paymaster` should not have its opsSeen incremented in case of a failure of factory or account
  * When running 2nd validation (before inclusion in a bundle), if a UserOperation fails because of factory or account error (either a FailOp revert or validation rule), then the paymaster&apos;s opsSeen valid is decremented by 1.
* **[EREP-016]** An `aggregator` should not have its opsSeen incremented in case of a failure of a factory, an account or a paymaster
  * When running 2nd validation (before inclusion in a bundle), if a UserOperation fails because of a factory, an account or a paymaster error (either a FailOp revert or validation rule), then the aggregator&apos;s opsSeen valid is decremented by 1.
* **[EREP-020]** If a staked factory is used, its reputation is updated for the account violating any of the validation rules accordingly. \
  That is, if the `validateUserOp()` is rejected for any reason in a `UserOperation` that has an `initCode`, it is treated as if the factory caused this failure, and thus this affects its reputation.
* **[EREP-030]** If a staked account is used, its reputation is updated for failures in other entities (`paymaster`, `aggregator`) even if they are staked.
* **[EREP-040]** An `aggregator` must be staked, regardless of storage usage.
* **[EREP-050]** An unstaked `paymaster` may not return a `context`.
* **[EREP-055]** A context size may not change between validation and bundle creation. \
    If a bundle creation reverts, and a paymaster&apos;s context size was modified, that paymaster \
    is BANNED, regardless if the UserOperation that reverted used that paymaster or not.
* Staked factory creation rules:
  * **[EREP-060]** If the factory is staked, either the factory itself or the sender may use the CREATE2 and CREATE opcode
    (the sender is allowed to use the CREATE with unstaked factory, with OP-032)
  * **[EREP-061]** A staked factory may also use a utility contract that calls the `CREATE`
* **[EREP-070]** During bundle creation, if a staked entity reduce its validation gas by more than 10% 
    compared to the second validation, that entity is throttled, even if the UserOperation itself didn&apos;t revert.
    (as it might affect the gas calculation based on [EIP-7623](/EIPs/EIPS/eip-7623) )

### Unstaked Entities Reputation Rules

* Definitions:
    * **`opsSeen`, `opsIncluded`, and reputation calculation** are defined above.
    * `UnstakedReputation` of an entity determines the maximum number of entries using this entity allowed in the mempool.
    * `opsAllowed` is a reputation-based calculation for an unstaked entity, representing how many `UserOperations` it is allowed to have in the mempool.
    * Rules:
        * **[UREP-010]** An unstaked sender (that is not throttled/banned) is only allowed to have `SAME_SENDER_MEMPOOL_COUNT` `UserOperation`s  in the mempool.
        * **[UREP-020]** For an unstaked paymaster only that is not throttled/banned: \
          `opsAllowed = SAME_UNSTAKED_ENTITY_MEMPOOL_COUNT + inclusionRate * min(opsIncluded, MAX_OPS_ALLOWED_UNSTAKED_ENTITY)`.
        * This is a default of `SAME_UNSTAKED_ENTITY_MEMPOOL_COUNT` for new entity
        * **[UREP-030]** REMOVED

### Alt-mempools Rules

Alternate mempool is an agreed-upon rule that the bundlers may opt into, in addition to the canonical mempool
The alt-mempool &quot;topic&quot; is a unique identifier. By convention, this is the IPFS hash of the document describing (in clear test and YAML file) the specifics of this alt mempool.

* **[ALT-010]** The bundler listens to the alt-mempool &quot;topic&quot; over the P2P protocol
* **[ALT-020]** The alt mempool rules MUST be checked only when a canonical rule is violated
    * That is, if validation follows the canonical rules above, it is not considered part of an alt-mempool.
*  **[ALT-021]** Such a `UserOperation` (that violates the canonical rules) is checked against all the &quot;alternate mempools&quot;, and is considered part of all those alt-mempools
* **[ALT-030]** Bundlers SHOULD forward `UserOperations` to other bundlers only once, regardless of how many (shared) alt-mempools they have. \
  The receiving bundler validates the `UserOperations`, and based on the above rules (and subscribed alt-mempools) decides which alt-mempools to propagate it to.
* **[ALT-040]** opsInclude and opsSeen of entities are kept per alt-mempool. That is, an entity can be considered throttled (or banned) in one mempool, while still active on another.

### Alt-mempool Reputation

Alt-mempools are served by the same bundlers participating in the canonical mempool, but change the rules and may introduce denial-of-service attack vectors. To prevent them from taking the canonical mempool or other alt mempools down with them, a reputation is managed for each. An alt mempool that causes too many invalidations gets throttled. This limits the scope of the attack and lets the bundler continue doing its work for other mempools.

* **[AREP-010]** each alt-mempool has &quot;opsSeen&quot; and &quot;opsIncluded&quot;, much like entities. The opsSeen is incremented after `UserOperation` initial validation, where it is considered part of this mempool.
  The &quot;opsIncluded&quot; is incremented after this UserOperation is included on-chain (either by this bundler, or another)
* **[AREP-020]** the alt-mempool becomes `THROTTLED`/`BANNED` based on the [Reputation Calculation](#reputation-calculation)
* **[AREP-030]** REMOVED

### Authorizations

* **[AUTH-010]** A UserOperation may only contain a single [EIP-7702](./eip-7702) authorization tuple.
* **[AUTH-020]** An account with EIP-7702 delegation can only be used as the Sender of the UserOperation.
  Using authorized account as any other kind of UserOperation entity is not allowed.
* **[AUTH-030]** An account with EIP-7702 delegation can only be **accessed** (using `*CALL` or `EXTCODE*` opcodes) if it is the Sender of the current UserOperation.
* **[AUTH-040]** If there are multiple UserOperations by the same sender with an authorization tuple in the mempool, they all MUST have the same delegate address.

### Limitations

The validation rules attempt to guarantee a degree of isolation between individual `UserOperations`&apos; validations.
In order to prevent hitting the memory expansion limitations (imposed by ethereum EVM) when creating a bundle, `UserOperation`s must meet the following limitations:

* **[LIM-010]** Maximum size of a single packed and ABI-encoded `UserOperation` in bytes MUST not exceed `MAX_USEROP_SIZE`
* **[LIM-020]** Maximum size of a `context` byte array returned by a paymaster in a single `UserOperation` in bytes MUST not exceed `MAX_CONTEXT_SIZE`
* **[LIM-030]** The `verificationGasLimit` and `paymasterVerificationGasLimit` parameters MUST exceed the actual usage during validation of the `UserOperation` by `VALIDATION_GAS_SLACK`
* **[LIM-040]** Maximum size of an ABI-encoded bundle call to the `handleOps` function in bytes SHOULD not exceed `MAX_BUNDLE_SIZE`
* **[LIM-050]** Maximum total size of all `context` byte arrays returned by all paymasters in all `UserOperations` in a bundle in bytes SHOULD not exceed `MAX_BUNDLE_CONTEXT_SIZE`

## Rationale

All transactions initiated by EOAs have an implicit validation phase where balance, nonce, and signature are
checked to be valid for the current state of the Ethereum blockchain.
Once the transaction is checked to be valid by a node, only another transaction by the same EOA can modify the Ethereum
state in a way that makes the first transaction invalid.

With Account Abstraction, however, the validation can also include an arbitrary EVM code and rely on storage as well,
which means that unrelated `UserOperations` or transactions may invalidate each other.

If not addressed, this would make the job of maintaining a mempool of valid `UserOperations` and producing valid
bundles computationally infeasible and susceptible to DoS attacks.

This document describes a set of validation rules that if applied by a bundler before accepting a `UserOperation`
into the mempool can prevent such attacks.

### The high-level goal

The purpose of this specification is to define a consensus between nodes (bundlers or block-builders) when processing incoming UserOperations from an external source.
This external source for UserOperations is either an end-user node (via RPC [ERC-7769](./eip-7769)) or another node in the p2p network.

The protocol tries to detect &quot;spam&quot; - which are large bursts of UserOperations that cannot be included on-chain (and thus can&apos;t pay).
The network is protected by throttling down requests from such spammer nodes.

All nodes in the network must have the same definition of &quot;spam&quot;: otherwise, if some nodes accept some type of UserOperations and propagate them while others consider them spam, those &quot;forgiving&quot; nodes will be considered &quot;spammers&quot; by the rest of the nodes, and the network effectively gets split.

### The processing flow of a UserOperation

- First, a UserOperation is received - either via RPC (submitted on behalf of a single application) or via the p2p protocol, from another node in the mempool.
- The node performs validation on the UserOperation, and then adds it to its in-memory mempool, and submits it to its peers.
- Lastly, when building a block, a node collects UserOperations from the mempool, performs a 2nd validation to make sure they are all still valid as a bundle and submits them into the next block.

### The need for 2nd validation before submitting a block

A normal Ethereum transaction in the mempool can be invalidated if another transaction was received with the same nonce. That other transaction had to increase the gas price in order to replace the first one, so it satisfied the rule of &quot;must pay to get included into the mempool&quot;.
With contract-based accounts, since the UserOperation validity may depend on mutable state, other transactions may invalidate a previously valid UserOperation, so we must check it before inclusion.

### Rationale of limiting opcodes:

- the validation is performed off-chain, before creating a block. Some opcodes access information that is known only when creating the block.
- using those opcodes while validating a transaction can easily create a validation rule that will succeed off-chain, but always revert on-chain, and thus cause a DoS attack.
- a simple example is `require block.number==12345`. It can be valid when validating the UserOperation and adding it to the mempool
  but will be invalid when attempting to include it on-chain at a later block.

### Rationale for limiting storage access

- We need UserOperation validations not to overlap so that a single storage change can&apos;t easily invalidate a large number of UserOperations in the mempool. By limiting UserOperations to access storage associated with the account itself, we know that we can for sure include a single UserOperation for each account in a bundle
- (A bundler MAY include multiple UserOperations of the same account in a bundle, but MUST first validate them together)

### Rationale of requiring a stake

We want to be able to allow globally-used contracts (paymasters, factories, aggregators) to use storage not associated with the account, but still prevent them from
spamming the mempool.
If a contract causes too many UserOperations to fail in their second validation after succeeding in their first, we can throttle its use in the mempool.
By requiring such a contract to have a stake, we prevent a &quot;Sybil attack&quot;, by making it expensive to create a large number of such paymasters to continue the spam attack.

By following the validation rules, we can detect contracts that cause spam UserOperations, and throttle them.
The stake comes to prevent the fast re-creation of malicious entities.
The stake is never slashed (since it is only used for off-chain detection) but is locked for a period of time, which makes such an attack much more expensive.


### Definition of the `mass invalidation attack`

A possible set of actions is considered to be a `mass invalidation attack` on the network if a large number of
`UserOperations` that did pass the initial validation and were accepted by nodes and propagated further into the
mempool to other bundlers in the network becomes invalid and not eligible for inclusion in a block.

There are 3 ways to perform such an attack:

1. Submit `UserOperation`s that pass the initial validation, but later fail the re-validation
   that is performed during the bundle creation.
2. Submit `UserOperation`s that are valid in isolation during validation, but when bundled
   together become invalid.
3. Submit valid `UserOperation`s but &quot;front-run&quot; them by executing a state change on the
   network that causes them to become invalid. The &quot;front-run&quot; in question must be economically viable.

To prevent such attacks, we attempt to &quot;sandbox&quot; the validation code.
We isolate the validation code from other `UserOperations`, from external changes to the storage, and
from information about the environment such as a current block timestamp.

### What is not considered a `mass invalidation attack`

A `UserOperation` that fails the initial validation by a receiving node without entering its mempool is not
considered an attack. The node is expected to apply web2 security measures and throttle requests based on API key,
source IP address, etc.
RPC nodes already do that to prevent being spammed with invalid transactions which also have a validation cost.
P2P nodes already have (and should apply) a scoring mechanism to determine spammer nodes.

Also, if the invalidation of `N` UserOperations from the mempool costs `N*X` with a sufficiently large `X`, it is not considered an economically viable attack.

- The minimum change to cause an invalidation is a storage change (5k gas)
- Assuming a Node can sustain processing 2000 invalid UserOps per block, the cost of a DoS attack is 10M gas per block.
- The above value is high, but we take further measures to make such an attack more expensive.

## Security Considerations

This document describes the security considerations bundlers must take to protect themselves (and the entire mempool network)
from denial-of-service attacks.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Fri, 01 Sep 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7562</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7562</guid>
      </item>
    
      <item>
        <title>Contract wallet management NFT</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-draft-contract-wallet-management-nft/16702</comments>
        
        <description>## Abstract

This proposal introduces a smart contract wallet-based approach for managing NFTs, focusing on utilizing the programmable features of smart contract wallets for NFT asset management. Additionally, it introduces functions such as `nftApprove`, `nftSetApprovalForOneAll`, `nftSetApprovalForAllAll`, `nftGetApproved`, `nftIsApprovedForOneAll`, `nftIsApprovedForAllAll` and `nftTransfer`, which provide enhanced control over NFT transactions. This approach seeks to enhance NFT management by utilizing the built-in features of smart contract wallets, thus offering a more adaptable, secure, and efficient method for managing token transactions.


## Motivation

An externally-owned account (EOA) wallet has no state and code storage, while the smart contract wallet does.

Account abstraction (AA) is a direction of the smart contract wallet, which works around abstract accounts. This ERC can also be an extension based on [ERC-4337](./eip-4337) or as a plug-in for wallets.

The smart contract wallet allows the user&apos;s own account to have state and code, bringing programmability to the wallet. We think there are more directions to expand. For example, nft asset management, functional expansion of nft transactions, etc.

The smart contract wallet interface of this ERC is for nft asset management and nft asset approval. It supports the simplenft &lt;!-- TODO --&gt; ERC-X, and [ERC-721](./eip-721) is backward compatible with &lt;!-- TODO --&gt; ERC-X, so it can be compatible with the management of all nfts in the existing market.

The proposal aims to achieve the following goals:

1. NFT assets are allocated and managed by the wallet itself, such as approve function, which are configured by the user’s contract wallet, rather than controlled by the nft asset contract, to avoid some existing ERC-721 contract risks.
2. Add the `nftTransfer` function, the transaction initiated by the non-smart wallet itself.
3. Add `nftApprove`, `nftSetApprovalForOneAll`, `nftSetApprovalForAllAll`, `nftGetApproved`, `nftIsApprovedForOneAll`, `nftIsApprovedForAllAll` functions. The user wallet itself supports approve and provides approve. for One nft, all nft of one nft smart contract, all nft assets.
4. User wallet can choose batch approve and batch transfer.
5. Users can choose to add hook function before and after their `nftTransfer` to increase the user&apos;s more playability.
6. The user can choose to implement the `nftReceive` function.



## Specification

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

**Compliant contract must implement the [ERC-165](./eip-165) interfaces**
```solidity

/// @title ERC-7564
/// @dev See https://eips.ethereum.org/EIPS/eip-7564
/// @dev Note: the ERC-165 identifier for this interface is 
pragma solidity ^0.8.20;

interface IERC7564{

    /**
     * @notice Used to notify listeners that owner has granted approval to the user to manage one nft.
     * @param _asset Address of the nft
     * @param _owner Address of the account that has granted the approval for nft‘s assets
     * @param _operator Address of the operator
     * @param _tokenId The unique identifier of the NFT
     */
    event NftApproval(
        address indexed _asset,
        address indexed _owner, 
        address indexed _operator, 
        uint256 _tokenId
    );

    /**
     * @notice Used to notify listeners that owner has granted approval to the operator to manage all nft of one asset contract.
     * @param _asset Address of the nft
     * @param _owner Address of the account that has granted the approval for nft‘s assets
     * @param _operator Address of the operator
     * @param _approved approve all nft of one asset contract
     */
    event NftApprovalForOneAll(
        address indexed _asset,
        address indexed _owner, 
        address indexed _operator,
        bool _approved
    );

    /**
     * @notice Used to notify listeners that owner has granted approval to the operator to manage all nft .
     * @param _owner Address of the account that has granted the approval for nft‘s assets
     * @param _operator Address of the operator
     * @param _approved approve all nft
     */
    event NftApprovalForAllAll(
        address indexed _owner, 
        address indexed _operator,
        bool _approved
    );

    /**
     * @notice Approve nft
     * @dev Allows operator address to withdraw from your wallet one nft.
     * @dev Emits an {nftApproval} event.
     * @param _asset Address of the nft
     * @param _operator Address of the operator
     * @param _tokenId The unique identifier of the NFT
     */
    function nftApprove(address _asset, address _operator, uint256 _tokenId) external;

   

    /**
     * @notice Approve all nft of one asset
     * @dev Allows operator address to withdraw from your wallet all nft.
     * @dev Emits an {nftApprovalForOneAll} event.
    * @param _asset Address of the nft
     * @param _operator Address of the operator
     * @param _approved Approved all nfts of one asset
     */
    function nftSetApprovalForOneAll(address _asset, address _operator, bool _approved) external;


     /**
     * @notice Approve all nft
     * @dev Allows operator address to withdraw from your wallet all nft.
     * @dev Emits an {nftApprovalForAllAll} event.
     * @param _operator Address of the operator
     * @param _approved Approved all nfts
     */
    function nftSetApprovalForAllAll(address _operator, bool _approved) external;

    /**
     * @notice read operator approved
     * @param _asset Address of the nft
     * @param _operator Address of the operator
     * @param _tokenId The unique identifier of the NFT
     * @return _approved Whether to approved operator one nft
     */
    function nftGetApproved(address _asset, address _operator, uint256 _tokenId) 
        external
        view
        returns (bool _approved);

    /**
     * @notice read operator approved
     * @param _asset Address of the nft
     * @param _operator Address of the operator
     * @return _approved Whether to approved operator all nfts of this one asset
     */
    function nftIsApprovedForOneAll(address _asset, address _operator) 
        external
        view
        returns (bool _approved);

    /**
     * @notice read operator approved
     * @param _operator Address of the operator
     * @return _approved Whether to approved operator all nfts
     */
    function nftIsApprovedForAllAll(address _operator) 
        external
        view
        returns (bool _approved);

    /**
     * @notice Transfer nft
     * @dev must call nft asset transfer() inside the function
     * @dev If the caller is not wallet self, must verify the approve and update
     * @param _asset Address of the nft
     * @param _to Address of the receive
     * @param _tokenId The transaction amount
     * @return _success The bool value returns whether the transfer is successful
     */
    function nftTransfer(address _asset, address _to, uint256 _tokenId) 
        external 
        returns (bool _success); 


}
```


## Rationale

the key technical decisions in this proposal are:

**Improved Approve Mechanism**
- **Current vs. Proposed**: In the existing ERC-721 system, an externally-owned account (EOA) directly interacts with nft contracts to `approve`. The new `nftApprove`, `nftSetApprovalForOneAll`, `nftSetApprovalForAllAll`, `nftGetApproved`, `nftIsApprovedForOneAll`, `nftIsApprovedForAllAll`functions in this proposed enable more precise control over nft usage within a wallet contract, a significant improvement over the traditional method.
- **Enhanced Security**: This mechanism mitigates risks like nft over-approval by shifting approval control to the user&apos;s smart contract wallet.
- **Programmability**: Users gain the ability to set advanced approval strategies, such as conditional or time-limited approvals, the `nftSetApprovalForAllAll` function specifically allows for a universal setting  all nfts. these were not possible with traditional ERC-721 nfts.

**Optimized Transfer Process**
- **Efficiency and Security**: The `nftTransfer` function streamlines the nft transfer process, making transactions both more efficient and secure.
- **Flexibility**: Allows the integration of custom logic (hooks) before and after transfers, enabling additional security checks or specific actions tailored to the user’s needs.

**Support for Batch Operations**
- **Increased Efficiency**: Users can simultaneously handle multiple `approve` or `transfer` operations, significantly boosting transaction efficiency.
- **Enhanced User Experience**: Simplifies the management of numerous assets, improving the overall experience for users with large portfolios.


## Backwards Compatibility

This ERC can be used as an extension of [ERC-4337](/EIPs/EIPS/eip-4337) and is backward compatible with ERC-4337.



## Security Considerations

No security considerations were found.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 21 Nov 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7564</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7564</guid>
      </item>
    
      <item>
        <title>Perpetual Contract NFTs as Collateral</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7565-proposal-perpetual-contract-nft-for-defi-composability/16790</comments>
        
        <description>## Abstract

This ERC proposes a mechanism where a person (referred to as the &quot;Asset Owner&quot;) can collateralize NFTs that represent locked deposits or assets, to borrow funds against them. These NFTs represent the right to claim the underlying assets, along with any accrued benefits, after a predefined maturity period. [^1]

[^1]:
    ```csl-json
    {
        &quot;container-title&quot;: &quot;IEEE Access&quot;,
        &quot;author&quot;: [
            {
                &quot;given&quot;: &quot;Hyoungsung&quot;,
                &quot;family&quot;: &quot;Kim&quot;
            },
            {
                &quot;given&quot;: &quot;Hyun-Sik&quot;,
                &quot;family&quot;: &quot;Kim&quot;
            },
            {
                &quot;given&quot;: &quot;Yong-Suk&quot;,
                &quot;family&quot;: &quot;Park&quot;
            }
        ],
        &quot;DOI&quot;: &quot;10.1109/ACCESS.2022.3225884&quot;,
        &quot;URL&quot;: &quot;https://ieeexplore.ieee.org/document/9967987&quot;,
        &quot;type&quot;: &quot;article-journal&quot;,
        &quot;id&quot;: 9967987,
        &quot;citation-label&quot;: &quot;9967987&quot;,        
        &quot;issued&quot;: {
            &quot;date-parts&quot;: [
                [
                    2022
                ]
            ]
        },
        &quot;keyword&quot;: &quot;Contracts;Nonfungible tokens;Cryptocurrency;Finance;Smart contracts;Blockchains;Financial services;Automated market maker (AMM);blockchain;decentralized exchange (DEX);decentralized finance (DeFi);Ethereum;liquidity pool (LP);non-fungible token (NFT);uniswap&quot;,
        &quot;page&quot;: &quot;126802-126814&quot;,
        &quot;title&quot;: &quot;Perpetual Contract NFT as Collateral for DeFi Composability&quot;,
        &quot;volume&quot;: 10
    }
    ```

## Motivation

The rapidly evolving landscape of DeFi has introduced various mechanisms for asset locking, offering benefits like interest and voting rights. However, one of the significant challenges in this space is maintaining liquidity while these assets are locked. This ERC addresses this challenge by proposing a method to generate profit from locked assets using [ERC-721](/EIPs/EIPS/eip-721) and [ERC-4907](/EIPs/EIPS/eip-4907).

In DeFi services, running Automated Market Maker (AMM), liquidity providers contribute assets to pools and receive NFTs representing their stake. These NFTs denote the rights to the assets and the associated benefits, but they also lock the assets in the pool, often causing liquidity challenges for the providers. The current practice requires providers to withdraw their assets for urgent liquidity needs, adversely affecting the pool&apos;s liquidity and potentially increasing slippage during asset swaps.

Our proposal allows these NFTs, representing locked assets in liquidity pools, to be used as collateral. This approach enables liquidity providers to gain temporary liquidity without withdrawing their assets, maintaining the pool&apos;s liquidity levels. Furthermore, it extends to a broader range of DeFi services, including lending and trading, where asset locking is prevalent. By allowing the collateralization of locked asset representations through NFTs, our approach aims to provide versatile liquidity solutions across DeFi services, benefitting a diverse user base within the ecosystem.

The concept of perpetual contract NFTs, which we introduce, exploits the idea of perpetual futures contracts in the cryptocurrency derivatives market. These NFTs represent the rights to the perpetual contract and its collateral, enabling them to be used effectively as collateral for DeFi composability. The perpetual contract NFT offers a new form of NFT that enhances the utility of locked assets, providing a significant advantage in DeFi applications by offering liquidity while retaining the benefits of asset locking.

## Specification

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

### Contract Interface

Solidity interface.

```solidity
    interface IPerpetualContractNFT {

        // Emitted when an NFT is collateralized for obtaining a loan
        event Collateralized(uint256 indexed tokenId, address indexed owner, uint256 loanAmount, uint256 interestRate, uint256 loanDuration);

        // Emitted when a loan secured by an NFT is fully repaid, releasing the NFT from collateral
        event LoanRepaid(uint256 indexed tokenId, address indexed owner);

        // Emitted when a loan defaults, resulting in the transfer of the NFT to the lender
        event Defaulted(uint256 indexed tokenId, address indexed lender);

        // Enables an NFT owner to collateralize their NFT in exchange for a loan
        // @param tokenId The NFT to be used as collateral
        // @param loanAmount The amount of funds to be borrowed
        // @param interestRate The interest rate for the loan
        // @param loanDuration The duration of the loan
        function collateralize(uint256 tokenId, uint256 loanAmount, uint256 interestRate, uint64 loanDuration) external;

        // Enables a borrower to repay their loan and regain ownership of the collateralized NFT
        // @param tokenId The NFT that was used as collateral
        // @param repayAmount The amount of funds to be repaid
        function repayLoan(uint256 tokenId, uint256 repayAmount) external;

        // Allows querying the loan terms for a given NFT
        // @param tokenId The NFT used as collateral
        // @return loanAmount The amount of funds borrowed
        // @return interestRate The interest rate for the loan
        // @return loanDuration The duration of the loan
        // @return loanDueDate The due date for the loan repayment
        function getLoanTerms(uint256 tokenId) external view returns (uint256 loanAmount, uint256 interestRate, uint256 loanDuration, uint256 loanDueDate);

        // Allows querying the current owner of the NFT
        // @param tokenId The NFT in question
        // @return The address of the current owner
        function currentOwner(uint256 tokenId) external view returns (address);

        // View the total amount required to repay the loan for a given NFT
        // @param tokenId The NFT used as collateral
        // @return The total amount required to repay the loan, including interest
        function viewRepayAmount(uint256 tokenId) external view returns (uint256);
    }
```

#### Event `Collateralized`

- The `Collateralized` event MUST be emitted when the collateralize function is successfully executed.
- Usage: Logs the event of an NFT being used as collateral for a loan, capturing essential details like the loan amount, interest rate, and loan duration.

#### Event `LoanRepaid`

- The `LoanRepaid` event MUST be emitted when the repayLoan function is successfully executed.
- Usage: Logs the event of a loan being repaid and the corresponding NFT being released from collateral.

#### Event `Defaulted`

- The `Defaulted` event MUST be emitted in scenarios where the loan defaults and the NFT is transferred to the lender.
- Usage: Used to log the event of a loan default and the transfer of the NFT to the lender.

#### Function `collateralize`

- The `collateralize` event SHOULD be implemented as `external`.
- Usage: Allows an NFT owner to collateralize their NFT to receive a loan.

#### Function `repayLoan`

- The `repayLoan` function SHOULD be implemented as `external`.
- Usage: Enables an NFT owner to repay their loan and reclaim their NFT.
  
#### Function `getLoanTerms`

- The `getLoanTerms` function MAY be implemented as `external` `view`.
- Usage: Allows querying the loan terms for a given NFT.

#### Function `currentOwner`

- The `currentOwner` function MAY be implemented as `external` `view`.
- Usage: Enables querying the current owner of a specific NFT.

#### Function `viewRepayAmount`

- The `viewRepayAmount` function MAY be implemented as `external` `view`.
- Usage: Enables querying the current repay amount of a specific NFT.
  
## Rationale

### Design Motivation

The design of this standard is driven by the need to address specific challenges in the DeFi sector, particularly concerning the liquidity and management of assets locked as collateral. Traditional mechanisms in DeFi often require asset holders to lock up their assets for participation in activities such as lending, staking, or yield farming, which results in a loss of liquidity. This standard aims to introduce a more flexible approach, allowing asset holders to retain some liquidity while their assets are locked, thereby enhancing the utility and appeal of DeFi products.

### Design Decision

- Dual-Role System (Asset Owner and DeFi Platform/Contract): A clear division is established between the NFT owner (asset holder) and the DeFi platform or contract utilizing the NFT as collateral. This distinction simplifies the management of rights and responsibilities, enhancing clarity and reducing potential conflicts.

- Enhancing Liquidity without Compromising Asset Locking Benefits: A key feature of this standard is enabling asset owners to use their NFTs, which represent locked assets, as collateral to secure loans. This approach allows asset owners to access liquidity without needing to withdraw their assets from pools or staking programs, thus preserving the associated benefits like interest accrual or voting rights.

- Automated Loan and Collateral Management: The integration of automated features for managing the terms and conditions of the collateralized NFT is a deliberate choice to minimize transaction costs and complexity.

- DeFi Composability: The strategic emphasis on DeFi composability, particularly the integration between asset-locking and collateralizing services, is pivotal for this standard. This approach aims to streamline the adoption of the standard across diverse DeFi platforms and services, fostering seamless connections within the DeFi ecosystem.

### Alternate Designs and Related Work

- Comparison with [ERC-4907](/EIPs/EIPS/eip-4907): While [ERC-4907](/EIPs/EIPS/eip-4907) also introduces a dual-role model for NFTs (owner and user), our standard focuses specifically on the use of NFTs for collateralization in financial transactions, diverging from [ERC-4907](/EIPs/EIPS/eip-4907)’s rental-oriented approach.

- Improvement Over Traditional Collateralization Methods: Compared to traditional DeFi collateralization, which often requires complete asset lock-up, this standard proposes a more dynamic and flexible model that allows for continued liquidity access.

## Backwards Compatibility

Fully compatible with [ERC-721](/EIPs/EIPS/eip-721) and integrates with [ERC-4907](/EIPs/EIPS/eip-4907) for renting NFTs.

## Test Cases

```solidity
// SPDX-License-Identifier: CC0-1.0 
pragma solidity ^0.8.0;

import &quot;./PerpetualContractNFT.sol&quot;;

contract PerpetualContractNFTDemo is PerpetualContractNFT {

    constructor(string memory name, string memory symbol)
        PerpetualContractNFT(name, symbol)
    {         
    }

    function mint(uint256 tokenId, address to) public {
        _mint(to, tokenId);
    }
}
```

```solidity
import { expect } from &quot;chai&quot;;
import { ethers } from &quot;hardhat&quot;;

describe(&quot;PerpetualContractNFTDemo&quot;, function () {
    it(&quot;should allow an owner to collateralize an NFT, rent it to a contract, and then have the owner repay the loan&quot;, async function () {
        const [owner] = await ethers.getSigners();

        const PerpetualContractNFTDemo = await ethers.getContractFactory(&quot;PerpetualContractNFTDemo&quot;);
        const demo = await PerpetualContractNFTDemo.deploy(&quot;DemoNFT&quot;, &quot;DNFT&quot;);
        await demo.waitForDeployment();
        expect(demo.target).to.be.properAddress;

        // Mint an NFT to the owner
        await demo.mint(1, owner.address);

        // Owner collateralizes the NFT for a loan
        const loanAmount = ethers.parseUnits(&quot;1&quot;, &quot;ether&quot;); // 1 Ether in Wei. Use Wei to avoid precision error.
        const interest = 5; // 5% interest
        const expiration = Math.floor(new Date().getTime() / 1000) + 3600; // Expire after 60 minutes (3600 seconds), convert it to seconds because `hours` in solidity converted to seconds
        
        await demo.connect(owner).collateralize(1, loanAmount, interest, expiration); // tokenId, loanAmount, interestRate, loanDuration

        // Check current user of the NFT (should be the contract address)
        expect(await demo.userOf(1)).to.equal(demo.target);

        // Borrower repays the loan to release the NFT
        const repayAmountWei = await demo.connect(owner).viewRepayAmount(1);
        await demo.connect(owner).repayLoan(1, repayAmountWei);
        
        // Check if the NFT is returned to the original owner after the loan is repaid
        expect(await demo.userOf(1)).to.equal(&quot;0x0000000000000000000000000000000000000000&quot;);
    });
    });
```

Run in Terminal：

```console
npx hardhat test
```

## Reference Implementation

```solidity
// SPDX-License-Identifier: CC0-1.0 
pragma solidity ^0.8.0;

//import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;
import &quot;./IPerpetualContractNFT.sol&quot;;
import &quot;./ERC4907/ERC4907.sol&quot;;

contract PerpetualContractNFT is ERC4907, IPerpetualContractNFT {
    struct LoanInfo {
        address borrower;   // Address that borrowed against the NFT
        uint256 loanAmount; // Amount of funds borrowed
        uint256 interestRate; // Interest rate for the loan
        uint64 loanDuration; // Duration of the loan
        uint256 loanStartTime; // Timestamp when the loan starts
    }

    mapping(uint256 =&gt; LoanInfo) internal _loans;

    //Constructor to initialize the Perpetual Contract NFT contract with the given name and symbo
    constructor(string memory name_, string memory symbol_)
        ERC4907(name_, symbol_)
    {}

    function collateralize(uint256 tokenId, uint256 loanAmount, uint256 interestRate, uint64 loanDuration) public override {
        require(ownerOf(tokenId) == msg.sender || isApprovedForAll(ownerOf(tokenId), msg.sender) || getApproved(tokenId) == msg.sender, &quot;Not owner nor approved&quot;);

        LoanInfo storage info = _loans[tokenId];
        info.borrower = msg.sender;
        // The loan amount should reflect the asset&apos;s value as represented by the NFT, considering an appropriate loan-to-value (LTV) ratio.
        info.loanAmount = loanAmount;
        info.interestRate = interestRate;
        info.loanDuration = loanDuration;
        info.loanStartTime = block.timestamp;

        setUser(tokenId, address(this), loanDuration);
        emit Collateralized(tokenId, msg.sender, loanAmount, interestRate, loanDuration);

        // Further logic can be implemented here to manage the lending of assets
    }

    function repayLoan(uint256 tokenId, uint256 repayAmount) public override {
        require(_loans[tokenId].borrower == msg.sender, &quot;Not the borrower.&quot;);

        // Calculate the total amount due for repayment
        uint256 totalDue = viewRepayAmount(tokenId);

        // Check if the repayAmount is sufficient to cover at least a part of the total due amount
        require(repayAmount &lt;= totalDue, &quot;Repay amount exceeds total due.&quot;);

        // Calculate the remaining loan amount after repayment
        _loans[tokenId].loanAmount = totalDue - repayAmount;

        // Resets the user of the NFT to the default state if the entire loan amount is fully repaid
        if(_loans[tokenId].loanAmount == 0) {
            setUser(tokenId, address(0), 0);
        }

        emit LoanRepaid(tokenId, msg.sender);
    }


    function getLoanTerms(uint256 tokenId) public view override returns (uint256, uint256, uint256, uint256) {
        LoanInfo storage info = _loans[tokenId];
        return (info.loanAmount, info.interestRate, info.loanDuration, info.loanStartTime);
    }

    function currentOwner(uint256 tokenId) public view override returns (address) {
        return ownerOf(tokenId);
    }

    function viewRepayAmount(uint256 tokenId) public view returns (uint256) {
        if (_loans[tokenId].loanAmount == 0) {
            // If the loan amount is zero, there is nothing to repay
            return 0;
        }

        // The interest is calculated on an hourly basis, prorated based on the actual duration for which the loan was held.
        // If the borrower repays before the loan duration ends, they are charged interest only for the time the loan was held.
        // For example, if the annual interest rate is 5% and the borrower repays in half the loan term, they pay only 2.5% interest.
        uint256 elapsed = block.timestamp &gt; (_loans[tokenId].loanStartTime + _loans[tokenId].loanDuration) 
                        ? _loans[tokenId].loanDuration  / 1 hours
                        : (block.timestamp - _loans[tokenId].loanStartTime) / 1 hours;

        // Round up
        // Example: 15/4 = 3.75
        // round((15 + 4 - 1)/4) = 4, round((15/4) = 3)
        uint256 interest = ((_loans[tokenId].loanAmount * _loans[tokenId].interestRate / 100) * elapsed + (_loans[tokenId].loanDuration / 1 hours) - 1) / 
                    (_loans[tokenId].loanDuration / 1 hours);

        // Calculate the total amount due
        uint256 totalDue = _loans[tokenId].loanAmount + interest;

        return totalDue;
    }

    // Additional functions and logic to handle loan defaults, transfers, and other aspects of the NFT lifecycle
}
```

## Security Considerations

&lt;!-- Needs discussion. --&gt;

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 27 Nov 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7565</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7565</guid>
      </item>
    
      <item>
        <title>Multiplayer Game Communication</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-proposal-multiplayer-onchain-game/16796</comments>
        
        <description>## Abstract

This proposal introduces a multiplayer game communication (MGC) interface, using `room` to match and group players, and using `message` to process actions between players. This allows one smart contract to handle multiple players playing games on the chain, preventing centralized servers from affecting the fairness of the game.

## Motivation   

Common multiplayer games are generally played on centralized servers. Players have no way of knowing whether there are forged data and cheating on the server. The owner of the game server can match players at will, modify scores and levels, and even close and pause the game. If the player&apos;s actions all occur on the chain, every message from the chain is proof of the player&apos;s instructions and actions, which further ensures the fairness of the game. The Multiplayer Game Communication framework scales vertically by adding rooms to handle and accommodate multiple players. Write on-chain game logic with custom messages for horizontal expansion, allowing game developers to build multiplayer and fully on-chain games with smart contracts.   
Advantages of using this standard include:
- All parties can provide comprehensive game data query services based on standard interfaces and verify the fairness of the game.
- It has a basic grouping and messaging architecture, which reduces complexity and allows developers to focus on the development of the core logic of the game.
- It is more composable, and developers can decompose a large game into several contracts that implement the standard.
- Messages have one-to-many and customized capabilities, which is more conducive to developers to expand for different games. 
- The room adopts a hierarchical data structure, and each member will be assigned a new ID in each room to facilitate developers to manage the player&apos;s state.

## Specification

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

The principle of Multiplayer Game Communication is to use the same game logic to change the state of different groups of players. 

It consists of two core parts:

**Room**: A container for players, used to match and view connected players. The game can only be played after players join the room.

**Message**: Actions between players, using messages to perform game behaviors and change the player&apos;s state in the room.

![Multiplayer Game Communication Workflow](/EIPs/assets/eip-7566/MOGFlowChart.png)

### Interfaces

#### `IMOG.sol`

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity &gt;=0.8.0;

import &quot;./Types.sol&quot;;

interface IMOG {
    /**
     * Create a new room.
     * @dev The entity MUST be assigned a unique Id.
     * @return New room id.
     */
    function createRoom() external returns (uint256);

    /**
     * Get the total number of rooms that have been created.
     * @return Total number of rooms.
     */
    function getRoomCount() external view returns (uint256);

    /**
     * Player joins room.
     * @dev The member MUST be assigned a unique Id.
     * @param _roomId is the id of the room.
     * @return Member id.
     */
    function joinRoom(uint256 _roomId) external returns (uint256);

    /**
     * Get the id of a member in a room.
     * @param _roomId is the id of the room.
     * @param _member is the address of a member.
     * @return Member id.
     */
    function getMemberId(uint256 _roomId, address _member)
        external
        view
        returns (uint256);

    /**
     * Check if a member exists in the room.
     * @param _roomId is the id of the room.
     * @param _member is the address of a member.
     * @return true exists, false does not exist.
     */
    function hasMember(uint256 _roomId, address _member)
        external
        view
        returns (bool);

    /**
     * Get all room IDs joined by a member.
     * @param _member is the address of a member.
     * @return An array of room ids.
     */
    function getRoomIds(address _member)
        external
        view
        returns (uint256[] memory);

    /**
     * Get the total number of members in a room.
     * @param _roomId is the id of the room.
     * @return Total members.
     */
    function getMemberCount(uint256 _roomId) external view returns (uint256);

    /**
     * A member sends a message to other members.
     * @dev Define your game logic here and use the content in the message to handle the member&apos;s state. The message MUST be assigned a unique Id
     * @param _roomId is the id of the room.
     * @param _to is an array of other member ids.
     * @param _message is the content of the message, encoded by abi.encode.
     * @param _messageTypes is data type array of message content.
     * @return Message id.
     */
    function sendMessage(
        uint256 _roomId,
        uint256[] memory _to,
        bytes memory _message,
        Types.Type[] memory _messageTypes
    ) external returns (uint256);

    /**
     * Get all messages received by a member in the room.
     * @param _roomId is the id of the room.
     * @param _memberId is the id of the member.
     * @return An array of message ids.
     */
    function getMessageIds(uint256 _roomId, uint256 _memberId)
        external
        view
        returns (uint256[] memory);

    /**
     * Get details of a message.
     * @param _roomId is the id of the room.
     * @param _messageId is the id of the message.
     * @return The content of the message.
     * @return Data type array of message content.
     * @return Sender id.
     * @return An array of receiver ids.
     */
    function getMessage(uint256 _roomId, uint256 _messageId)
        external
        view
        returns (
            bytes memory,
            Types.Type[] memory,
            uint256,
            uint256[] memory
        );
}


```

### Library

The library [`Types.sol`](/EIPs/assets/eip-7566/Types.sol) contains an enumeration of Solidity types used in the above interfaces.

## Rationale

### Why are multiplayer onchain games room-based?

Because the rooms are independent, each player will be assigned a new ID when entering a room. A new game round can be a room, a game task can be a room, and a game activity can be a room.

### The player&apos;s state in the game.

The game state refers to the player&apos;s data changes in the game, and `sendMessage` actually plays the role of a state converter. The proposal is very flexible, you can define some data inside the room (internal) or outside the room (global) according to the game logic.

### How to initialize player data?

You can initialize player data in `createRoom` or `joinRoom`.

### How to check and handle player exits from the game?

You can use `block.timestamp` or `block.number` to record the latest `sendMessage` time of a member. And add a message type to `sendMessage`. Other players can use this message type to complain that a member is offline and punish the member.

### Appropriate game categories.

This is a multiplayer on-chain game rather than a multiplayer real-time game standard. The game category depends on the network your contract is deployed on. Some layer 2 networks process blocks very quickly and can make some more real-time games. Generally, the network is more suitable for strategy, trading card, turn-based, chess, sandbox, and settlement.

## Reference Implementation

See [Multiplayer Game Communication Example](/EIPs/assets/eip-7566/MultiplayerOnchainGame.sol)

## Security Considerations

&lt;!-- TODO: Needs discussion. --&gt;

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Tue, 28 Nov 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7566</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7566</guid>
      </item>
    
      <item>
        <title>Hardfork Meta Backfill - Berlin to Shapella</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/hardfork-meta-backfill/16923</comments>
        
        <description>## Abstract

Following Muir Glacier hard fork, Meta EIPs were abandoned in favor of other ways to track changes included in Ethereum network upgrades. This EIP aggregates the specifications for these upgrades, which themselves list the specific changes included. Specifically, it covers the Beacon Chain launch (Serenity Phase 0), Berlin, London, Altair, Arrow Glacier, Gray Glacier, The Merge (Paris + Bellatrix) and Shapella (Shanghai + Capella). 

## Motivation

For many years, Ethereum used Meta EIPs to document network upgrades. Recently, consensus has formed around using them again. This EIP aggregates the network upgrades who did not have Meta EIPs and links out to their specifications.

## Specification

The network upgrades below are listed in order of activation. Upgrades to Ethereum&apos;s execution layer are marked &quot;[EL]&quot;, and those to Ethereum&apos;s consensus layer are marked &quot;[CL]&quot;. 

### Beacon Chain Launch - Serenity Phase 0 [CL]

The full specifications for the Beacon Chain at launch can be found in the [`v1.0.0` release of the `ethereum/consensus-specs` repository](https://github.com/ethereum/consensus-specs/blob/579da6d2dc734b269dbf67aa1004b54bb9449784/README.md#phase-0). Additionally, [EIP-2982](/EIPs/EIPS/eip-2982) provides context on the Beacon Chain design and rationale for its mainnet parametrization. 

### Berlin [EL]

The set of EIPs included in Berlin were originally specified in [EIP-2070](/EIPs/EIPS/eip-6953), but then moved to the [`berlin.md`](https://github.com/ethereum/execution-specs/blob/8dbde99b132ff8d8fcc9cfb015a9947ccc8b12d6/network-upgrades/mainnet-upgrades/berlin.md) file of the `ethereum/execution-specs` repository. 

### London [EL]

The set of EIPs included in London are specified in the [`london.md`](https://github.com/ethereum/execution-specs/blob/8dbde99b132ff8d8fcc9cfb015a9947ccc8b12d6/network-upgrades/mainnet-upgrades/london.md) file of the `ethereum/execution-specs` repository. 

### Altair [CL]

The full specifications for the Altair network upgrade can be found in the [`v1.1.0` release of the `ethereum/consensus-specs` repository](https://github.com/ethereum/consensus-specs/blob/67fd7979ffd705bd6b0b5c1aaa842a445cc74d9a/README.md#altair).

### Arrow Glacier [EL]

The set of EIPs included in Arrow Glacier are specified in the[`arrow-glacier.md`](https://github.com/ethereum/execution-specs/blob/8dbde99b132ff8d8fcc9cfb015a9947ccc8b12d6/network-upgrades/mainnet-upgrades/arrow-glacier.md) file of the `ethereum/execution-specs` repository. 

### Gray Glacier [EL]

The set of EIPs included in Gray Glacier are specified in the[`gray-glacier.md`](https://github.com/ethereum/execution-specs/blob/8dbde99b132ff8d8fcc9cfb015a9947ccc8b12d6/network-upgrades/mainnet-upgrades/gray-glacier.md) file of the `ethereum/execution-specs` repository. 

### The Merge 

The Merge was the first upgrade to require coordination between the execution and consensus layers. The consensus layer first activated the Bellatrix upgrade, which was followed by the activation of Paris on the execution layer.

#### Bellatrix [CL]

The full specifications for the Bellatrix network upgrade can be found in the [`v1.2.0` release of the `ethereum/consensus-specs` repository](https://github.com/ethereum/consensus-specs/blob/f8ae982c2fc7dbb03a3c95a638da4486310e09e9/README.md#stable-specifications).

#### Paris [EL]

The set of EIPs included in Paris are specified in the [`paris.md`](https://github.com/ethereum/execution-specs/blob/8dbde99b132ff8d8fcc9cfb015a9947ccc8b12d6/network-upgrades/mainnet-upgrades/paris.md) file of the `ethereum/execution-specs` repository. 

### Shapella 

The Shapella upgrade was the first upgrade to activate at the same time on both the execution and consensus layers. To enable this, the upgrade activation mechanism on the execution layer was changed to use timestamps instead of blocks. This is described in [EIP-6953](/EIPs/EIPS/eip-6953) and [EIP-6122](/EIPs/EIPS/eip-6122).

#### Shanghai [EL]

The set of EIPs included in Shanghai are specified in the[`shanghai.md`](https://github.com/ethereum/execution-specs/blob/8dbde99b132ff8d8fcc9cfb015a9947ccc8b12d6/network-upgrades/mainnet-upgrades/shanghai.md) file of the `ethereum/execution-specs` repository. 

#### Capella [CL]

The full specifications for the Capella network upgrade can be found in the [`v1.3.0` release of the `ethereum/consensus-specs` repository](https://github.com/ethereum/consensus-specs/blob/01b53691dcc36d37a5ad8994b3a32d8de69fb1aa/README.md#stable-specifications).


## Rationale

The EIP repository is well known within the Ethereum community, and Meta EIPs have historically been useful to clearly list the EIPs included in a specific network upgrade.

While the specification process for the execution and consensus layers differ, there is value in having a single, harmonized, list of EIPs included in each upgrade, and for the lists for both layers to be part of the same repository.

Re-introducing Hardfork Meta EIPs enables this, and allows for de-duplication in cases where an EIP affects both the execution and consensus layer of Ethereum. This EIP covers the upgrades which did not use a Hardfork Meta EIP. 

## Backwards Compatibility

No backward compatibility issues found.

## Security Considerations

None.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 01 Dec 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7568</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7568</guid>
      </item>
    
      <item>
        <title>Hardfork Meta - Dencun</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/dencun-hardfork-meta/16924</comments>
        
        <description>## Abstract

This Meta EIP lists the EIPs included in the Dencun network upgrade across both Ethereum&apos;s execution and consensus layers. See [EIP-7568](/EIPs/EIPS/eip-7568) for the specifications of past upgrades.

## Specification

### Included EIPs 

* [EIP-1153](/EIPs/EIPS/eip-1153): Transient storage opcodes
* [EIP-4788](/EIPs/EIPS/eip-4788): Beacon block root in the EVM
* [EIP-4844](/EIPs/EIPS/eip-4844): Shard Blob Transactions 
* [EIP-5656](/EIPs/EIPS/eip-5656): MCOPY - Memory copying instruction
* [EIP-6780](/EIPs/EIPS/eip-6780): SELFDESTRUCT only in same transaction
* [EIP-7044](/EIPs/EIPS/eip-7044): Perpetually Valid Signed Voluntary Exits
* [EIP-7045](/EIPs/EIPS/eip-7045): Increase Max Attestation Inclusion Slot
* [EIP-7514](/EIPs/EIPS/eip-7514): Add Max Epoch Churn Limit
* [EIP-7516](/EIPs/EIPS/eip-7516): BLOBBASEFEE opcode

### Full Specifications 

#### Consensus Layer

EIPs 4788, 4844, 7044, 7045 and 7514 require changes to Ethereum&apos;s consensus layer. These are specified in the `deneb` folder of the `ethereum/consensus-specs` repository.

#### Execution Layer

EIPs 1153, 4788, 4844, 5656, 6780 and 7516 require changes to Ethereum&apos;s execution layer. The EIPs fully specify the changes. 

### Activation 

| Network Name     | Activation Epoch | Activation Timestamp |
|------------------|------------------|----------------------|
| Goerli           |    `231680`      |    `1705473120`      |
| Sepolia          |    `132608`      |    `1706655072`      |
| Holešky          |    `29696`       |    `1707305664`      |
| Mainnet          |    `269568`      |    `1710338135`      |

**Note**: rows in the table above will be filled as activation times are decided by client teams. 

## Rationale

This Meta EIP provides a global view of all changes included in the Dencun network upgrade, as well as links to full specification. 

## Security Considerations

None.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 01 Dec 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7569</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7569</guid>
      </item>
    
      <item>
        <title>Contract-level metadata via `contractURI()`</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-contract-level-metadata-via-contracturi/17157</comments>
        
        <description>## Abstract

This specification standardizes `contractURI()` to return contract-level metadata. This is useful for dapps and offchain indexers to show rich information about a contract, such as its name, description and image, without specifying it manually or individually for each dapp.

## Motivation

Dapps have included supported for `contractURI()` for years without an ERC to reference. This standard also introduces the event `ContractURIUpdated()` to signal when to update the metadata.

## Specification

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

The contract MUST implement the below interface:

```solidity
interface IERC7572 {
  function contractURI() external view returns (string memory);

  event ContractURIUpdated();
}
```

The string returned from `contractURI()` MAY be an offchain resource or onchain JSON data string (`data:application/json;utf8,{}`).

The `ContractURIUpdated()` event SHOULD be emitted on updates to the contract metadata for offchain indexers to query the contract.

If the underlying contract provides any methods that conflict with the `contractURI` schema such as `name()` or `symbol()`, the metadata returned by `contractURI()` is RECOMMENDED to take precedence. This enables contract creators to update their contract details with an event that notifies of the update.

### Schema for contractURI

The schema for the JSON returned from `contractURI()` MUST conform to:

```json
{
  &quot;$schema&quot;: &quot;https://json-schema.org/draft/2020-12/schema&quot;,
  &quot;type&quot;: &quot;object&quot;,
  &quot;properties&quot;: {
    &quot;name&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;The name of the contract.&quot;
    },
    &quot;symbol&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;The symbol of the contract.&quot;
    },
    &quot;description&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;The description of the contract.&quot;
    },
    &quot;image&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;format&quot;: &quot;uri&quot;,
      &quot;description&quot;: &quot;A URI pointing to a resource with mime type image/* that represents the contract, typically displayed as a profile picture for the contract.&quot;
    },
    &quot;banner_image&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;format&quot;: &quot;uri&quot;,
      &quot;description&quot;: &quot;A URI pointing to a resource with mime type image/* that represents the contract, displayed as a banner image for the contract.&quot;
    },
    &quot;featured_image&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;format&quot;: &quot;uri&quot;,
      &quot;description&quot;: &quot;A URI pointing to a resource with mime type image/* that represents the featured image for the contract, typically used for a highlight section.&quot;
    },
    &quot;external_link&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;format&quot;: &quot;uri&quot;,
      &quot;description&quot;: &quot;The external link of the contract.&quot;
    },
    &quot;collaborators&quot;: {
      &quot;type&quot;: &quot;array&quot;,
      &quot;items&quot;: {
        &quot;type&quot;: &quot;string&quot;,
        &quot;description&quot;: &quot;An Ethereum address representing an authorized editor of the contract.&quot;
      },
      &quot;description&quot;: &quot;An array of Ethereum addresses representing collaborators (authorized editors) of the contract.&quot;
    }
  },
  &quot;required&quot;: [&quot;name&quot;]
}
```

Example:

```json
{
  &quot;name&quot;: &quot;Example Contract&quot;,
  &quot;symbol&quot;: &quot;EC&quot;,
  &quot;description&quot;: &quot;Your description here&quot;,
  &quot;image&quot;: &quot;ipfs://QmTNgv3jx2HHfBjQX9RnKtxj2xv2xQCtbDXoRi5rJ3a46e&quot;,
  &quot;banner_image&quot;: &quot;ipfs://QmdChMVnMSq4U7oVKhud7wUSEZGnwuMuTY5rUQx57Ayp6H&quot;,
  &quot;featured_image&quot;: &quot;ipfs://QmS9m6e1E1NfioMM8dy1WMZNN2FRh2WDjeqJFWextqXCT8&quot;,
  &quot;external_link&quot;: &quot;https://project-website.com&quot;,
  &quot;collaborators&quot;: [&quot;0x388C818CA8B9251b393131C08a736A67ccB19297&quot;]
}
```

Future ERCs MAY inherit this one to add more properties to the schema for standardization.

## Rationale

The method name `contractURI()` was chosen based on its existing implementation in dapps. The event `ContractURIUpdated()` is specified to help offchain indexers to know when to refetch the metadata.

## Backwards Compatibility

As a new ERC, no backwards compatibility issues are present.

## Reference Implementation

```solidity
contract MyCollectible is ERC721, IERCXXXX {
    string _contractURI = &quot;ipfs://QmTNgv3jx2HHfBjQX9RnKtxj2xv2xQDtbVXoRi5rJ3a46e&quot;
    // or e.g. &quot;https://external-link-url.com/my-contract-metadata.json&quot;;

    function contractURI() external view returns (string memory) {
        return _contractURI;
        // or e.g. for onchain:
        string memory json = &apos;{&quot;name&quot;: &quot;Creatures&quot;,&quot;description&quot;:&quot;...&quot;}&apos;;
        return string.concat(&quot;data:application/json;utf8,&quot;, json);
    }

    /// @dev Suggested setter, not explicitly specified as part of this ERC
    function setContractURI(string memory newURI) external onlyOwner {
        _contractURI = newURI;
        emit ContractURIUpdated();
    }
}
```

## Security Considerations

Addresses specified as `collaborators` should be expected to receive admin-level functionality for updating contract information on dapps that implement this standard.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 06 Dec 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7572</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7572</guid>
      </item>
    
      <item>
        <title>Conditional-upon-Transfer-Decryption for DvP</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7573-conditional-upon-transfer-decryption-for-delivery-versus-payment/17232</comments>
        
        <description>## Abstract

The interfaces in this proposal model a functional transaction scheme to establish a secure *delivery-versus-payment*
across two blockchains, where a) no intermediary is required and b) one of the two chains
can securely interact with a stateless &quot;decryption oracle&quot;. Here, *delivery-versus-payment* refers to the exchange of,
e.g., an asset against a payment; however, the concept is generic to make a transfer of one token on one
chain (e.g., the payment) conditional to the successful transfer of another token on another chain (e.g., the asset).

The scheme is realized by two smart contracts, one on each chain.
One smart contract implements the `ILockingContract` interface on one chain (e.g. the &quot;asset chain&quot;), and another smart contract implements the `IDecryptionContract` interface on the other chain (e.g., the &quot;payment chain&quot;).
The smart contract implementing `ILockingContract` locks a token (e.g., the asset) on its chain until a key is presented to encrypt to one of two given values.
The smart contract implementing `IDecryptionContract`, decrypts one of two keys (via the decryption oracle) conditional to the success or failure of the token transfer (e.g., the payment). A stateless decryption oracle is attached to the chain running `IDecryptionContract` for the decryption.

In addition, there are two interfaces that standardize the communication with external decryption oracle(s):

- `IKeyDecryptionOracle.sol` is implemented by a decryption oracle proxy contract (on-chain router/proxy for an off-chain oracle).
- `IKeyDecryptionOracleCallback.sol` is implemented by a callback receiving the decrypted key (or derived verification material).

**Fulfillment semantics note:** The oracle proxy may implement either
(i) **strict fulfillment** (reverting `fulfill*` when the callback fails) or
(ii) **best-effort fulfillment** (not reverting `fulfill*` on callback failure, but signaling failure via events).
This proposal describes both modes and their operational trade-offs.


## Motivation

Within the domain of financial transactions and distributed ledger technology (DLT), the Hash-Linked Contract (HLC) concept has been recognized as valuable and has been thoroughly investigated.
The concept may help to solve the challenge of delivery-versus-payment (DvP), especially in cases where the asset chain and payment system (which may be a chain, too) are separated.
A prominent application of smart contracts realizing a secure DvP is that of buying an asset, where the asset is managed on one chain (the asset chain), but the payments are executed on another chain (the payment chain).
Proposed solutions are based on an API-based interaction mechanism which bridges the communication between a so-called asset chain and a corresponding
payment system or requires complex and problematic time locks.[^1]

Here, we propose a protocol that facilitates secure delivery-versus-payment with less overhead, especially with a stateless oracle.[^2]


## Specification

### Methods

#### Smart Contract on the chain that performs the locking (e.g. the asset chain)

The following methods specify the functionality of the smart contract implementing
the locking. For further information, please also look at the interface
documentation [`ILockingContract.sol`](/EIPs/assets/eip-7573/contracts/ILockingContract.sol).

##### Initiation of Transfer: `inceptTransfer`

```solidity
function inceptTransfer(uint256 id, int amount, address from, bytes keyHashedSeller, bytes memory keyEncryptedSeller) external;
```

Called from the buyer of the token to initiate token transfer. Emits a `TransferIncepted` event.
The parameter `id` is an identifier of the trade. The parameter `from` is the address of the seller (the address of the buyer is `msg.sender`).
The parameter `keyHashedSeller` is a hash of the key that can be used by the seller to (re-)claim the token.
The parameter `keyEncryptedSeller` is an encryption of the key that can be used by the buyer to claim the token.
It is possible to implement the protocol in a way where the hashing method agrees with the  encryption method. See below on &quot;encryption&quot;.

##### Initiation of Transfer: `confirmTransfer`

```solidity
function confirmTransfer(uint256 id, int amount, address to, bytes keyHashedBuyer, bytes memory keyEncryptedBuyer) external;
```

Called from the seller of the token to confirm token transfer. Emits a `TransferConfirmed` event.
The parameter `id` is an identifier of the trade. The parameter `to` is the address of the buyer (the address of the seller is `msg.sender`).
The parameter `keyHashedBuyer` is a hash of the key that can be used by the buyer to (re-)claim the token.
The parameter `keyEncryptedBuyer` is an encryption of the key that can be used by the buyer to (re-)claim the token.
It is possibly to implement the protocol in a way where the hashing method agrees with the  encryption method. See below on &quot;encryption&quot;.

If the trade specification, that is, the quadruple (`id`, `amount`, `from`, `to`), in a call to `confirmTransfer`
matches that of a previous call to `inceptTransfer`, and the balance is sufficient, the corresponding `amount`
of tokens is locked (transferred from `from` to the smart contract) and `TransferConfirmed` is emitted.

##### Transfer: `transferWithKey`

```solidity
function transferWithKey(uint256 id, bytes memory key) external;
```

Called from either the buyer or the seller of the token
of the trade with id `id`.

If the method is called from the buyer (`to`) *and* the hashing of `key` matches `keyHashedBuyer`,
then the locked tokens are transferred to the buyer (`to`). This emits `TokenClaimed`.

If the method is called from the seller (`from`) *and* the hashing of `key` matches `keyHashedSeller`,
then the locked tokens are transferred (back) to the seller (`to`). This emits `TokenReclaimed`.

##### Summary

The interface `ILockingContract`:

```solidity
interface ILockingContract {
    event TransferIncepted(uint256 id, int amount, address from, address to, bytes keyHashedSeller, bytes keyEncryptedSeller);
    event TransferConfirmed(uint256 id, int amount, address from, address to, bytes keyHashedBuyer, bytes keyEncryptedBuyer);
    event TokenClaimed(uint256 id, bytes key);
    event TokenReclaimed(uint256 id, bytes key);

    function inceptTransfer(uint256 id, int amount, address from, bytes memory keyHashedSeller, bytes memory keyEncryptedSeller) external;
    function confirmTransfer(uint256 id, int amount, address to, bytes memory keyHashedBuyer, bytes memory keyEncryptedBuyer) external;
    function transferWithKey(uint256 id, bytes memory key) external;
}
```

#### Smart Contract on the other chain that performs the conditional decryption (e.g. the payment chain)

The following methods specify the functionality of the smart contract implementing
the conditional decryption. For further information, please also look at the interface
documentation [`IDecryptionContract.sol`](/EIPs/assets/eip-7573/contracts/IDecryptionContract.sol).

##### Initiation of Transfer: `inceptTransfer`

```solidity
function inceptTransfer(uint256 id, int amount, address from, bytes memory keyEncryptedSuccess, bytes memory keyEncryptedFailure) external;
```

Called from the receiver of the amount to initiate payment transfer. Emits a `TransferIncepted`.
The parameter `id` is an identifier of the trade. The parameter `from` is the address of the sender of the payment (the address of the receiver is `msg.sender`).
The parameter `keyEncryptedSuccess` is an encryption of a key and will be decrypted if the transfer is successful in a call to `transferAndDecrypt`.
The parameter `keyEncryptedFailure` is an encryption of a key and will be decrypted if the transfer fails in a call to `transferAndDecrypt` or if `cancelAndDecrypt` is successful.

##### Transfer: `transferAndDecrypt`

```solidity
function transferAndDecrypt(uint256 id, int amount, address to, bytes memory keyEncryptedSuccess, bytes memory keyEncryptedFailure) external;
```

Called from the sender of the amount to initiate completion of the payment transfer. Emits a `TransferKeyRequested` with keys depending on completion success.
The parameter `id` is an identifier of the trade. The parameter `to` is the address of the receiver of the payment (the sender of the payment (from) is implicitly the `msg.sender`).
The parameter `keyEncryptedSuccess` is an encryption of the key and will be decrypted if the transfer is successful.
The parameter `keyEncryptedFailure` is an encryption of the key and will be decrypted if the transfer fails.

The method will not decrypt any key and not perform a transfer of a payment if the values (`id`, `amount`, `from` `to`, `keyEncryptedSuccess`, `keyEncryptedFailure`)
do not match a previous call to `inceptTransfer`.

##### Cancelation of Transfer: `cancelAndDecrypt`

```solidity
function cancelAndDecrypt(uint256 id, address from, bytes memory keyEncryptedSuccess, bytes memory keyEncryptedFailure) external;
```

Called from the receiver of the amount to cancel payment transfer (cancels the incept transfer).

The method must be called from the caller of a previous call to `inceptTransfer`
with the exact same arguments and cancels this specific transfer.
If these preconditions are met and a valid call to `transferAndDecrypt` has not been issued before,
i.e. if `keyEncryptedSuccess` has not been issued in a `TransferKeyRequested` event,
then this method emits a `TransferKeyRequested` with the key `keyEncryptedFailure`.

##### Release of ILockingContract Access Key: `releaseKey`

```solidity
function releaseKey(uint256 id, bytes memory key) external;
```

Called from the (possibly external) decryption oracle.

Emits the event `TransferKeyReleased` with the value of `key` if the call was eligible.

##### Summary

The interface `IDecryptionContract`:

```solidity
interface IDecryptionContract {
    event TransferIncepted(uint256 id, int amount, address from, address to, bytes keyEncryptedSuccess, bytes keyEncryptedFailure);
    event TransferKeyRequested(address sender, uint256 id, bytes encryptedKey);
    event TransferKeyReleased(address sender, uint256 id, bool success, bytes key);

    function inceptTransfer(uint256 id, int amount, address from, bytes memory keyEncryptedSuccess, bytes memory keyEncryptedFailure) external;
    function transferAndDecrypt(uint256 id, int amount, address to, bytes memory keyEncryptedSuccess, bytes memory keyEncryptedFailure) external;
    function cancelAndDecrypt(uint256 id, address from, bytes memory keyEncryptedSuccess, bytes memory keyEncryptedFailure) external;
    function releaseKey(uint256 id, bytes memory key) external;
}
```

### Interfaces to External Decryption Oracles (Oracle Proxy + Callback)

This proposal additionally standardizes the on-chain interaction with external (off-chain) decryption oracles via:

- `IKeyDecryptionOracle` (oracle proxy / router)
- `IKeyDecryptionOracleCallback` (consumer callback)

The general flow is:

1. The consumer calls `request*` on the oracle proxy contract (payable).
2. The oracle proxy emits a request event containing a `requestId` (correlation id).
3. The off-chain oracle observes the request event, performs decryption or verification off-chain, and calls `fulfill*` on the proxy.
4. The oracle proxy calls the consumer callback `on*` with the fulfillment payload.

#### Callback execution semantics: strict vs best-effort

Implementations MAY choose one of the following fulfillment semantics. Both are compatible with this proposal.

##### Strict fulfillment (reverting)

In **strict fulfillment**, the proxy MUST revert `fulfill*` if the callback call fails (including OOG).

Properties:

- The off-chain oracle operator can treat `receipt.status == 1` as “callback succeeded”.
- If `receipt.status == 0`, the request is not fulfilled and can be retried (e.g., with higher tx gas limit).
- The proxy MUST ensure that request state is not lost on revert (e.g., by relying on revert rollback of state changes).

This mode is operationally simple for closed deployments where the off-chain oracle and the consumer are coordinated and where failure handling/retries are primarily managed by the oracle operator.

##### Best-effort fulfillment (non-reverting)

In **best-effort fulfillment**, the proxy MUST NOT revert `fulfill*` solely because the callback call fails (including OOG). Instead, it SHOULD signal callback outcome via events (e.g. `CallbackSucceeded` / `CallbackFailed`).

Properties:

- The off-chain oracle operator MUST NOT interpret `receipt.status == 1` as “callback succeeded”; it must also evaluate the emitted outcome signal.
- Failure handling can be shifted to the callback implementer/operator: a consumer can run an off-chain watcher that subscribes to `CallbackFailed` and reacts accordingly (e.g. pull/consume flow, re-request, alerting).
- The proxy may either keep the request pending for retries or consume it and shift retry responsibility to the consumer. The chosen policy SHOULD be documented by the implementation.

This mode is useful when the proxy wants to provide an on-chain observable audit trail for callback failures and to decouple “oracle fulfillment” from “consumer processing”.

#### Gas budgeting and forwarding

- The off-chain oracle controls the total cost of `fulfill*` by setting the transaction gas limit.
- The proxy MAY cap or budget the gas forwarded to the callback (e.g., by forwarding “all but a reserve”).
- Keeping a small gas reserve in the proxy can help ensure the proxy can finalize `fulfill*` and emit outcome events even if the callback consumes most forwarded gas.

#### Calldata fallback (retrieving fulfillment payload without logging)

In either strict or best-effort mode, the `fulfill*` payload is present in the transaction input calldata of the `fulfill*` call.

Implementations SHOULD document the following operational fallback:

- Off-chain systems that observe an event (e.g., `CallbackFailed`) can use the event’s `transactionHash` to fetch the corresponding transaction and decode the input calldata using the `IKeyDecryptionOracle` ABI to recover the fulfillment arguments.
- Practical caveat: Some RPC providers prune old transaction bodies; indexers SHOULD persist decoded fulfillment payload off-chain if long-term retention is required.

This fallback can be used to support consumer-side “pull/consume” flows, or as a recovery mechanism when callback execution fails.

### Encryption and Decryption

The linkage of the two smart contracts relies on use of a `key`, `encryptedKey` and `hashedKey`.
The implementation is free to support several encryption methods for
as long as the decryption oracle supports it.

The encryption is performed with the public key of  the decryption oracle.
Either the encryption oracle offers a method performing encryption, in which
case the encryption method isn&apos;t even required to be known, or both parties
know the public key of the decryption oracle and can perform the generation
of the key and its encryption.

It is implicitly assumed that the two parties may check that
the strings `keyEncryptedBuyer` and `keyEncryptedSeller` are
in a valid format.

To avoid on-chain encryption in the `ILockingContract`, it is possible to use a
simpler hashing algorithm  on the `ILockingContract`. In that case, the decryption oracle has
to provide a method that allows to obtain the hash *H(K)* (`keyHashed`) for an
encrypted key *E(K)* (`keyEncrypted`) without exposing the key *K* (``key`), cf. [^2].


### Sequence diagram of delivery versus payment

The interplay of the two smart contracts is summarized
in the following sequence diagram:

![sequence diagram dvp](/EIPs/assets/eip-7573/doc/DvP-Seq-Diag.png)

## Rationale

The protocol tries to be parsimonious. The transfer
is associated with a (preferably unique) `id` possibly
generated by some additional interaction of the trading
parties.

The `key` and the `encryptedKey` arguments are strings to
allow the flexible use of different encryption schemes.
The decryption/encryption scheme should be inferable from the contents
of the `encryptedKey`.

### Ensuring Secure Key Decryption - Key Format

It has to be ensured that the decryption oracle decrypts a key only for the eligible contract.

It seems as if this would require us to introduce a concept of eligibility to the description oracle, which would imply a kind of state.

A fully stateless decryption can be realized by introducing a document format for the key and a corresponding eligibility verification protocol. We propose the following elements:

- The (unencrypted) key documents contain the address of the payment contract implementing `IDecryptionContract`.
- The decryption oracle offers a stateless function `verify` that receives an encrypted key and returns the callback address (that will be used for the `releaseKey` call) that is stored inside the decrypted key without returning the decrypted key.
- When an encrypted key is presented to the decryption oracle, the oracle decrypts the document and passes the decrypted key to `releaseKey` of the callback contract address found within the document decrypted key.

We propose the following XML schema for the document of the decrypted key:
```xml
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;xs:schema attributeFormDefault=&quot;unqualified&quot; elementFormDefault=&quot;qualified&quot; targetNamespace=&quot;http://finnmath.net/erc/ILockingContract&quot; xmlns:xs=&quot;http://www.w3.org/2001/XMLSchema&quot;&gt;
    &lt;xs:element name=&quot;releaseKey&quot;&gt;
        &lt;xs:complexType&gt;
            &lt;xs:simpleContent&gt;
                &lt;xs:extension base=&quot;xs:string&quot;&gt;
                    &lt;xs:attribute name=&quot;contract&quot; type=&quot;xs:string&quot; use=&quot;required&quot; /&gt;
                    &lt;xs:attribute name=&quot;transaction&quot; type=&quot;xs:unsignedShort&quot; use=&quot;required&quot; /&gt;
                &lt;/xs:extension&gt;
            &lt;/xs:simpleContent&gt;
        &lt;/xs:complexType&gt;
    &lt;/xs:element&gt;
&lt;/xs:schema&gt;
```

A corresponding XML sample is shown below.
```xml
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;yes&quot;?&gt;
&lt;releaseKey contract=&quot;eip155:1:0x1234567890abcdef1234567890abcdef12345678&quot; transaction=&quot;3141&quot; xmlns=&quot;http://finnmath.net/erc/ILockingContract&quot;&gt;
    &lt;!-- random data --&gt;
    zZsnePj9ZLPkelpSKUUcg93VGNOPC2oBwX1oCcVwa+U=
&lt;/releaseKey&gt;
```

### Multi-Party Delivery versus Payment

#### Locking is a Feature

In Delivery-versus-Payment (DvP) protocols like [ERC-7573](/EIPs/EIPS/eip-7573), at least one token must be locked to ensure atomicity, even if only for a short period during the transaction.

While locking may appear as an inconvenient necessity, it is in fact a feature that becomes valuable in the construction of conditional trades or multi-party DvPs.

If *n* parties wish to perform bilateral transactions atomically, there are *at least* *m := 2 • (n - 1)* transactions, of which *m-1* require locking. The last one can operate directly, and its success or failure decides whether the other locks are released or reverted.

A multi-party delivery versus payment is a valuable trade feature. Consider, for example, the case where counterparty A wishes to buy a token *Y* (e.g., a bond) from counterparty C, but in order to fund this transaction, counterparty A wishes to sell a token *X* (e.g., another bond) to counterparty B. However, A does not want to sell bond *X* if the purchase of *Y* fails. A multi-party DvP allows these two transactions to be bound into a single atomic unit.

While for a two-party DvP with two tokens only one token requires locking—and hence a DvP can be constructed without locking on the cash chain—a three-party DvP with three tokens in general requires the ability to lock all three tokens.

This highlights that locking is not just a constraint, but a required feature to enable advanced and economically meaningful protocols.

#### N-DvP with [ERC-7573](/EIPs/EIPS/eip-7573)

A multi-party DvP can be created elegantly by combining multiple (*n-1*) two-party DvPs, for example based on the [ERC-7573](/EIPs/EIPS/eip-7573) protocol.

The procedure is simple: instead of finalizing the respective two-party DvP by a call to `transferAndDecrypt`, the two-party DvP is first confirmed with a call to `confirm`, leaving the finalization open.

At any time, any party can call `cancelAndDecrypt` to release the failure key and revert all lockings.

Once all parties are linked with their respective two-party DvPs, a single call to `transferAndDecrypt` performs locking of the token implementing the `IDecryptionContract` and releases either the success key on success or the failure key on failure.

##### Initiation and Finalization

The counterparty that initiates the multi-party DvP by making the first call
to the `IDecryptionContract` is the one that is allowed to finalize it via `transferAndDecrypt`, the other may cancel via `cancelAndDecrypt`.

##### Sequence Diagram

Below we depict the corresponding sequence diagram of a multi-party DvP via [ERC-7573](/EIPs/EIPS/eip-7573).
Note that the individual DvP may come in two different flavors depending on which counterparty is the receiver of the token on the `IDecryptionContract`.

The diagram depicts a multi-party dvp with n+1 counterparties trading n+1 tokens out of which
the DvPs are bound by the contract on token 0.

![sequence diagram multi party dvp](/EIPs/assets/eip-7573/doc/multi-party-dvp.svg)

*Note: The more general case of N counterparties trading
M tokens is just a special case where we enumerate all combination as new counterparties and new tokens.*

## Security Considerations

The decryption oracle does not need to be a single trusted entity. Instead, a threshold decryption scheme can be employed, where multiple oracles perform partial decryption, requiring a quorum of them to reconstruct the secret key. This enhances security by mitigating the risk associated with a single point of failure or trust.

In such cases, each participating decryption oracle will observe the decryption request from an emitted `TransferKeyRequested` event, and subsequently call the `releaseKey` method with a partial decryption result. The following sequence diagram illustrates this.

![sequence diagram distributed oracle](/EIPs/assets/eip-7573/doc/Distributed-Oracle.png)

See [^2] for details.

Additional considerations for the oracle proxy + callback pattern:

- Callback implementations SHOULD restrict callers (e.g. `require(msg.sender == oracleProxy)`), otherwise any address could invoke `on*` directly.
- Callback implementations SHOULD be cheap and should avoid unbounded loops or expensive state changes. If heavy work is required, prefer a pull/consume pattern initiated by the consumer.
- Oracle proxy implementations SHOULD document whether they use strict or best-effort fulfillment semantics, and how retries are intended to be handled (oracle-operated retry vs consumer-operated recovery).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).



[^1]:
    ```csl-json
        {
          &quot;type&quot;: &quot;article&quot;,
          &quot;id&quot;: 1,
          &quot;author&quot;: [
            {
              &quot;family&quot;: &quot;La Rocca&quot;,
              &quot;given&quot;: &quot;Rosario&quot;
            },
            {
              &quot;family&quot;: &quot;Mancini&quot;,
              &quot;given&quot;: &quot;Riccardo&quot;
            },
            {
              &quot;family&quot;: &quot;Benedetti&quot;,
              &quot;given&quot;: &quot;Marco&quot;
            },
            {
              &quot;family&quot;: &quot;Caruso&quot;,
              &quot;given&quot;: &quot;Matteo&quot;
            },
            {
              &quot;family&quot;: &quot;Cossu&quot;,
              &quot;given&quot;: &quot;Stefano&quot;
            },
            {
              &quot;family&quot;: &quot;Galano&quot;,
              &quot;given&quot;: &quot;Giuseppe&quot;
            },
            {
              &quot;family&quot;: &quot;Mancini&quot;,
              &quot;given&quot;: &quot;Simone&quot;
            },
            {
              &quot;family&quot;: &quot;Marcelli&quot;,
              &quot;given&quot;: &quot;Gabriele&quot;
            },
            {
              &quot;family&quot;: &quot;Martella&quot;,
              &quot;given&quot;: &quot;Piero&quot;
            },
            {
              &quot;family&quot;: &quot;Nardelli&quot;,
              &quot;given&quot;: &quot;Matteo&quot;
            },
            {
              &quot;family&quot;: &quot;Oliviero&quot;,
              &quot;given&quot;: &quot;Ciro&quot;
            }
          ],
          &quot;DOI&quot;: &quot;10.2139/ssrn.4386904&quot;,
          &quot;title&quot;: &quot;Integrating DLTs with Market Infrastructures: Analysis and Proof-of-Concept for Secure DvP between TIPS and DLT Platforms&quot;,
          &quot;original-date&quot;: {
            &quot;date-parts&quot;: [
              [2022, 7, 19]
            ]
          },
          &quot;URL&quot;: &quot;http://dx.doi.org/10.2139/ssrn.4386904&quot;
        }
    ```

[^2]:
    ```csl-json
        {
          &quot;type&quot;: &quot;article&quot;,
          &quot;id&quot;: 2,
          &quot;author&quot;: [
            {
              &quot;family&quot;: &quot;Fries&quot;,
              &quot;given&quot;: &quot;Christian&quot;
            },
            {
              &quot;family&quot;: &quot;Kohl-Landgraf&quot;,
              &quot;given&quot;: &quot;Peter&quot;
            }
          ],
          &quot;DOI&quot;: &quot;10.2139/ssrn.4628811&quot;,
          &quot;title&quot;: &quot;A Proposal for a Lean and Functional Delivery versus Payment across two Blockchains&quot;,
          &quot;original-date&quot;: {
            &quot;date-parts&quot;: [
              [2023, 11, 9]
            ]
          },
          &quot;URL&quot;: &quot;http://dx.doi.org/10.2139/ssrn.4628811&quot;
        }
    ```
</description>
        <pubDate>Tue, 05 Dec 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7573</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7573</guid>
      </item>
    
      <item>
        <title>Multi-Asset ERC-4626 Vaults</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7575-partial-and-extended-erc-4626-vaults/17274</comments>
        
        <description>## Abstract

The following standard adapts [ERC-4626](/EIPs/EIPS/eip-4626) to support multiple assets or entry points for the same share token. This also enables Vaults which don&apos;t have a true share token but rather convert between two arbitrary external tokens.

It adds a new `share` method to the Vault, to allow the [ERC-20](/EIPs/EIPS/eip-20) dependency to be externalized.

It also adds Vault-to-Share lookup to the share token.

Lastly, it enforces [ERC-165](/EIPs/EIPS/eip-165) support for Vaults and the share token.

## Motivation

One missing use case that is not supported by [ERC-4626](/EIPs/EIPS/eip-4626) is Vaults which have multiple assets or entry points such as liquidity provider (LP) Tokens. These are generally unwieldy or non-compliant due to the requirement of ERC-4626 to itself be an [ERC-20](/EIPs/EIPS/eip-20).

## Specification

### Definitions:

The existing definitions from [ERC-4626](/EIPs/EIPS/eip-4626) apply. In addition, this spec defines:

- Multi-Asset Vaults: A Vault which has multiple assets/entry points. The Multi-Asset Vault refers to the group of [ERC-7575](/EIPs/EIPS/eip-7575) contracts with the entry points for a specific asset, linked to one common `share` token.
- Pipe: A converter from one token to another (unidirectional or bidirectional)

### Methods

All [ERC-7575](/EIPs/EIPS/eip-7575) Vaults MUST implement [ERC-4626](/EIPs/EIPS/eip-4626) excluding the [ERC-20](/EIPs/EIPS/eip-20) methods and events.

#### share

The address of the underlying `share` received on deposit into the Vault. MUST return an address of an [ERC-20](/EIPs/EIPS/eip-20) share representation of the Vault.

`share` MAY return the address of the Vault itself.

If the `share` returns an external token i.e. `share != address(this)`:
* entry functions MUST increase the `share` balance of the `receiver` by the `shares` amount. i.e. `share.balanceOf(receiver) += shares`
* exit functions MUST decrease the `share` balance of the `owner` by the `shares` amount. i.e. `share.balanceOf(owner) -= shares`

MUST _NOT_ revert.

```yaml
- name: share
  type: function
  stateMutability: view

  inputs: []
  outputs:
    - name: shareTokenAddress
      type: address
```

### Multi-Asset Vaults

Multi-Asset Vaults share a single `share` token with multiple entry points denominated in different `asset` tokens.

Multi-Asset Vaults MUST implement the `share` method on each entry point. The entry points SHOULD NOT be [ERC-20](/EIPs/EIPS/eip-20).

### Pipes

Pipes convert between a single `asset` and `share` which are both [ERC-20](/EIPs/EIPS/eip-20) tokens outside the Vault.

A Pipe MAY be either unidirectional or bidirectional.

A unidirectional Pipe SHOULD implement only the entry function(s) `deposit` and/or `mint`, not `redeem` and/or `withdraw`.

The entry points SHOULD lock or burn the `asset` from the `msg.sender` and mint or transfer the `share` to the `receiver`. For bidirectional pipes, the exit points SHOULD lock or burn the `share` from the `owner` and mint or transfer the `asset` to the `receiver`.

### Share-to-Vault lookup

The [ERC-20](/EIPs/EIPS/eip-20) implementation of `share` SHOULD implement a `vault` method, that returns the address of the Vault for a specific `asset`.

SHOULD emit the `VaultUpdate` event when a Vault linked to the share changes.

```yaml
- name: vault
  type: function
  stateMutability: view

  inputs: 
    - name: asset
      type: address
    
  outputs:
    - name: vault
      type: address
```

### [ERC-165](/EIPs/EIPS/eip-165) support

Vaults implementing [ERC-7575](/EIPs/EIPS/eip-7575) MUST implement the [ERC-165](/EIPs/EIPS/eip-165) `supportsInterface` function. The Vault contract MUST return the constant value `true` if `0x2f0a18c5` is passed through the `interfaceID` argument.

The share contract SHOULD implement the [ERC-165](/EIPs/EIPS/eip-165) `supportsInterface` function. The share token MUST return the constant value `true` if `0xf815c03d` is passed through the `interfaceID` argument.

### Events

#### VaultUpdate

The Vault linked to the share has been updated.

```yaml
- name: VaultUpdate
  type: event

  inputs:
    - name: asset
      indexed: true
      type: address
    - name: vault
      indexed: false
      type: address
```


## Rationale

This standard is intentionally flexible to support both existing [ERC-4626](/EIPs/EIPS/eip-4626) Vaults easily by the introduction of a single new method, but also flexible to support new use cases by allowing separate share tokens.

### Ability to externalize [ERC-20](/EIPs/EIPS/eip-20) Dependency

By allowing `share != address(this)`, the Vault can have an external contract managing the [ERC-20](/EIPs/EIPS/eip-20) functionality of the Share. In the case of Multi-Asset, this avoids the confusion that might arise if each Vault itself were required to be an [ERC-20](/EIPs/EIPS/eip-20), which could confuse integrators and front-ends.

This approach also enables the creation of new types of Vaults, such as Pipes, which facilitate the conversion between two external [ERC-20](/EIPs/EIPS/eip-20) tokens. These Pipes could be unidirectional (i.e. only for assets to shares via deposit/mint, or shares to assets via redeem/withdraw) or bidirectional for both entry and exit flows.

### Including Share-to-Vault lookup optionally

The `vault` method is included to look up a Vault for a `share` by its `asset`, combined with the `VaultUpdate` event and [ERC-165](/EIPs/EIPS/eip-165) support. This enables integrations to easily query Multi-Asset Vaults.

This is optional, to maintain backward compatibility with use cases where the `share` is an existing deployed contract.


## Backwards Compatibility

[ERC-7575](/EIPs/EIPS/eip-7575) Vaults are not fully compatible with [ERC-4626](/EIPs/EIPS/eip-4626) because the [ERC-20](/EIPs/EIPS/eip-20) functionality has been removed.

## Reference Implementation

```solidity
    // This code snippet is incomplete pseudocode used for example only and is no way intended to be used in production or guaranteed to be secure

    contract Share is ERC20 {
        mapping (address asset =&gt; address) vault;

        function updateVault(address asset, address vault_) public {
            vault[asset] = vault_;
            emit UpdateVault(asset, vault_);
        }

        function supportsInterface(bytes4 interfaceId) external pure override returns (bool) {
            return interfaceId == 0xf815c03d || interfaceId == 0x01ffc9a7;
        }
    }

    contract TokenAVault is ERC7575 {
        address public share = address(Share);
        address public asset = address(TokenA);

        // ERC4626 implementation

        function supportsInterface(bytes4 interfaceId) external pure override returns (bool) {
            return interfaceId == 0x2f0a18c5 || interfaceId == 0x01ffc9a7;
        }
    }

    contract TokenBVault is ERC7575 {
        address public share = address(Share);
        address public asset = address(TokenB);

        // ERC4626 implementation

        function supportsInterface(bytes4 interfaceId) external pure override returns (bool) {
            return interfaceId == 0x2f0a18c5 || interfaceId == 0x01ffc9a7;
        }
    }

```

## Security Considerations

[ERC-20](/EIPs/EIPS/eip-20) non-compliant Vaults must take care with supporting a redeem flow where `owner` is not `msg.sender`, since the [ERC-20](/EIPs/EIPS/eip-20) approval flow does not by itself work if the Vault and share are separate contracts. It can work by setting up the Vault as a Trusted Forwarder of the share token, using [ERC-2771](/EIPs/EIPS/eip-2771).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 11 Dec 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7575</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7575</guid>
      </item>
    
      <item>
        <title>Versioning Scheme for EIPs</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/add-eip-versioning-scheme-for-eips/17295</comments>
        
        <description>## Abstract

This EIP introduces a versioning scheme for [Standards Track](/EIPs/EIPS/eip-1#eip-types) EIPs by applying [Semantic Versioning 2.0.0](/EIPs/assets/eip-7577/semver) based on changes made to the EIP&apos;s Specification section once its status has changed from `Draft` to `Review`.

## Motivation

EIP specifications often receive increasing modifications as more people review them, which is generally the case as client teams start implementing the specifications and the community gains a better understanding of their interaction with the rest of the protocol. These changes can be difficult to track. In particular, as EVM reference tests are often not maintained (and generally not released) by client teams or the EIP&apos;s authors, it can be difficult to ascertain whether a release of reference tests is sufficient, or even valid, to test the latest version of an EIP&apos;s specifications or the specification as currently implemented by a client.

This EIP proposes a semantic versioning scheme and an addition of a CHANGELOG section for EIPs that enables clearer communication within the community and allows the scope of a change to be ascertained at first glance. Furthermore, client implementation and testing toolchains can query EIP changes and automatically flag incompatibilities between the EIP&apos;s current specification and between client and test implementations.

## Specification

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

Once an EIP has moved out of &quot;Draft&quot; status, it MUST use the EIP versioning scheme outlined below. It MAY already use the versioning scheme in &quot;Draft&quot; status, which could be useful if the specification is actively being implemented. If more than one team is implementing the specification, it is RECOMMENDED to change the EIP&apos;s status to &quot;Review&quot;.

The EIP versioning scheme MUST apply the following semantic versioning scheme of `MAJOR.MINOR.PATCH`, based on [Semantic Versioning 2.0.0](/EIPs/assets/eip-7577/semver):

1. `MAJOR`: A breaking change to the specifications that requires an implementation change and a change to the reference tests.
2. `MINOR`: An addition to the specifications that requires additional implementation and additional test coverage to be added to the reference tests.
3. `PATCH`: Any cosmetic change to, or a reformulation of, the EIP without specification change.

Before the EIP has moved out of Draft status and is being versioned, the version number MUST initially have `MAJOR` version `0`.

For every change made to an EIP via a pull request (PR) made to ethereum/EIPs, a new entry MUST be added to the CHANGELOG section of the EIP that outlines the changes made within the PR. This CHANGELOG entry MUST include the following:

1. A new version number that follows the semantic versioning scheme outlined above.
2. The date when the changes were introduced.
3. The ethereum/EIPs PR number that implements the changes.
4. A line for each change made to the EIP&apos;s specifications that includes a short description of the change.

Additionally, the new version MUST be added to the metadata header of the EIP&apos;s markdown file (to a new &quot;version&quot; field), so that it may be easily parsed.

Tooling MUST be added to the ethereum/EIPs repository to help EIP authors apply the versioning scheme. This tooling SHOULD automatically:

1. Update the EIP version in the metadata header of the EIP&apos;s markdown file. If the EIP&apos;s status is changed from &quot;Draft&quot; to &quot;Review&quot;, the version MUST be updated to `1.0.0`.
2. Add a new CHANGELOG entry based on the EIP Version and the PR&apos;s title.

To allow the tooling to make these changes, the EIP author MUST indicate the scope of change in one of the commit messages pushed to the PR&apos;s branch. The scope is indicated by starting a commit message with (&quot;`[Mm]ajor:`&quot;, &quot;`[Mm]inor:`&quot;, or &quot;`[Pp]atch`&quot;). Multiple commit messages may contain scopes; in this case, the most severe scope change will be applied. If no scope can be detected in any of the commit messages, merging of the PR is blocked until such a commit message is pushed to the PR.

## Rationale

Making the version available in the EIP&apos;s metadata header allows for programmatic parsing of the version number by tooling used in reference tests or by client teams. Currently, the execution-spec-tests repository, which contains consensus tests for Ethereum execution clients, implements a rudimentary EIP version checker: EIP spec tests are required to declare the EIP&apos;s markdown file digest SHA that the test implementation was based on. The current value of the digest SHA is then polled via the Github API to verify that no changes have occurred since the test implementation. While this provides a warning to test implementers that the EIP has changed, it is clearly of limited use.

A richer versioning scheme, as defined by this EIP, can provide a lot of value to the testing toolchain. Client teams can provide an interface that reports the EIP version currently implemented and reference tests can specify the version they implement in generated tests as metadata. This allows a test runner to mark tests to xfail (expectedly fail) and issue a warning if the `MAJOR` or `MINOR` versions don&apos;t match. It would even be possible to automatically select the correct version of the reference tests to run against a client implementation, although given the pace of Ethereum development, it will likely be impractical to maintain and track multiple versions of tests.

### Case Study

This section explores how the versioning scheme would be applied to an existing EIPs recently under active development at the time of writing as an example.

The history of [EIP-4788](/EIPs/EIPS/eip-4788) contains many changes to its specification. EIP-4788 was updated to status &quot;Review&quot; on 2023-11-28. This case study assumes, however, that the EIP moved to status &quot;Review&quot; as of 2023-04-11 and updated to version 1.0.0 due to the start of a client team implementation.

#### Changelog

- 9.0.1 - 2023-09-26: Update ring buffer size rationale for new ring buffer size, #7786.
- 9.0.0 - 2023-09-26: Post audit tweaks, #7672.
  - Verify timestamp is non-zero.
  - Make `HISTORY_BUFFER_LENGTH` prime (8191).
  - Load calldata once.
  - Update `BEACON_ROOTS_ADDRESS`.
- 8.0.1 - 2023-08-28: 4788 cleanups, #7532.
- 8.0.0 - 2023-08-24: Initial stab at v2, #7456.
  - Require timestamp input to be exactly 32 bytes.
  - Revert if timestamp input does not match stored value (instead of returning zeroed word).
  - Remove precompile concept, use regular smart contract with provided bytecode.
- 7.0.3 - 2023-08-01: Mention genesis block with no existing beacon block root case, #7445.
- 7.0.2 - 2023-07-07: Explicitly specify header schema, #7297.
- 7.0.1 - 2023-07-07: Fix typo, #7293.
- 7.0.0 - 2023-07-05: Bound precompile storage, #7178.
- 6.0.1 - 2023-06-13: Clarify header and validity sections, #7179.
- 6.0.0 - 2023-06-12: Update precompile address, #7173.
- 5.0.0 - 2023-05-31: Key beacon roots by root, #7107.
- 4.0.0 - 2023-05-24: Favor stateful precompile over opcode, #7065.
- 3.0.0 - 2023-05-17: Send current slot from CL to avoid timestamp conversions, #7037.
- 2.0.1 - 2023-05-15: Fix typo, #7005.
- 2.0.0 - 2023-05-03: Update opcode to avoid clash, #6980.
- 1.0.1 - 2023-04-13: Minor nits, #6870.
- 1.0.0 - 2023-04-11: Use block roots; update to status &quot;Draft&quot;, #6859.
  - Update to &quot;Draft&quot; due to client implementation (NethermindEth/nethermind#5476).
  - Use block roots instead of state roots.
  - Roots are stored keyed by slot.
  - Use of ring buffer in state.
  - Use header timestamps to derive slot numbers, rather than consume additional header space.
- 0.2.1 - 2023-02-04:  Update to status &quot;Stagnant&quot;, #6432.
- 0.2.0 - 2022-06-29:  Rename &quot;beacon block root&quot; to &quot;beacon state root&quot;, #5090.
- 0.1.1 - 2022-05-06: Force usage of included LICENSE file, #5055.
- 0.1.0 - 2022-02-17: Add EIP-4788: Beacon state root in EVM, #4788.

## Backwards Compatibility

It is not necessary to retroactively add a CHANGELOG or versions for versions of the EIP prior to the introduction of this EIP. Upon the next change to the EIP&apos;s Specification section, the author MUST introduce a CHANGELOG section and a version number that follows the semantic versioning scheme outlined above.

## Security Considerations

None.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 13 Dec 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7577</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7577</guid>
      </item>
    
      <item>
        <title>Physical Asset Redemption</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7578-physical-asset-redemption/17556</comments>
        
        <description>## Abstract

This proposal is an extension of [ERC-721](/EIPs/EIPS/eip-721) and implements additional functionality and information pertaining to the NFT’s underlying physical asset by capturing information that enables the holder of physical asset backed NFTs to verify authenticity and facilitate redemption of the underlying physical assets. This proposal is primarily aimed at providing transparency by disclosing details of involved parties and provides opportunity to define and make readily available relevant legal relationship between NFT holder and the owner/holder of the respective underlying physical asset. This proposal makes the token issuer accountable to embed accurate information on a set of standardized information about the underlying physical asset and the involved key parties.

## Motivation

The first wave of NFT use cases encompass predominately the representation of ownership of digital assets. In view of the anticipated trend to tokenize any real-world asset, it is to be expected that the use cases of NFTs will rapidly grow and expand around physical assets. The absence of an embedded standardized set of information pertaining to the underlying physical asset together with lack of transparency of involved key parties, creates an unnecessary hurdle for NFT holders and potential users which might, as a result, hinder mass adoption of NFTs that are used as ownership representation of a specific physical asset.

Addressing the lack of readily available information and paving the way for mass adoption for a tokenized economy, this proposal requires that each minted token includes a defined number of predefined variables enabling verification of authenticity and facilitating redemption of the underlying physical asset.

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot; and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

When a token is minted, its properties SHOULD be initialized beforehand, with each field being defined as follows:

- **Token issuer**: identification of an individual or entity minting the NFT
  &lt;br&gt; _The token issuer is the key person connecting the physical asset and the digital representation. By identifying and disclosing the token issuer, a reference point is made instantly available to the NFT holder which allows them to conduct a due diligence on the NFT issuer and assessment of the NFT issuer’s trustworthiness. At the same time, it creates accountability for the token issuer which leads to overall improvement and standardisation of the NFT minting process. Token issuers will compete for best practices and recognition to gain advantages over competitors. A reputable NFT issuer will e.g. keep information on the legal owner of the physical asset prior to the minting of the underlying physical asset to satisfy any AML and KYC concerns. Ideally the NFT issuer is identified by a name but may also be identifiable via unique identification number or network ID that is issued by a service provider who stores relevant information on the NFT issuer._

- **Asset holder**: identification of legal owner of underlying physical asset
  &lt;br&gt; _In view of a redemption of the underlying physical asset and enforcing of legal rights, it is (from a legal perspective) essential for the NFT holder to identify the legal owner of the underlying physical asset. It allows the NFT holder to consider the legal counterparty risk. It cannot be assumed that the NFT issuer is the legal owner of the underlying physical asset, therefore it is vital for the NFT holder to have instant access to this additional information. Same as with the NFT issuer’s identity, the legal owner is ideally identified by a name but may also be identifiable via unique identification number or network ID that is issued by a service provider who stores relevant information on the legal owner._

- **Storage location**: identification of storage location of underlying physical asset
  &lt;br&gt; _Certain physical assets require specific storage conditions. A digital representation of an inappropriately stored physical asset may impact the value of the NFT significantly. Disclosing the storage location and making it directly accessible to the NFT holder, allows them to evaluate the storage risk of the underlying physical asset. In addition, it provides the NFT holder with a second point of contact for the enforcement of the redemption of the underlying physical asset._

- **Terms**: identification of legal relationship
  &lt;br&gt; _The disclosure and accessibility of the legal basis of the relationship between NFT holder and legal owner of the underlying physical asset promotes token issuers to stipulate and define the legal rights of the involved key parties. It furthermore allows the NFT Holder to conduct a legal risk and enforcement assessment. Ideally, the information is provided by embedding a link to the actual legal documentation such as an agreement or terms. The more information is accessible via the NFT, the better the NFT holder can assess the legal risks associated with enforcement of the redemption of the underlying physical asset._

- **Jurisdiction**: governing law and jurisdiction
  &lt;br&gt; _The applicable law is an extension of the legal contract disclosure and makes instantly available to the NFT holder or smart contract under what jurisdiction an enforcement would be governed without the need to review the details legal contract. This allows for an instant assessment of jurisdiction risk._

- **Declared value**: value of the underlying asset
  &lt;br&gt; _Certain auxiliary services such as insurance are tied to a value of the NFT and underlying physical asset. By defining a declared value, NFTs are able to be categorised in certain ways while the declared value provides an indication regarding the underlying asset’s value. The declared value of the underlying physical asset does not necessarily represent the market value._

The `terms` parameter SHOULD be an HTTP link to a document that is stored on IPFS. This is to ensure that the document is immutable and can be verified by the NFT holder.

When a token with valid properties is to be burned, the properties MUST be removed.

### Contract Interface

```solidity
pragma solidity ^0.8.21;

/**
 * @notice Struct encapsulating fields required to by the ERC-7578 standard to represent the physical asset
 * @param tokenIssuer The network or entity minting the token
 * @param assetHolder The legal owner of the physical asset
 * @param storageLocation The physical location where the asset is stored
 * @param terms Link to IPFS contract, agreement or terms
 * @param jurisdiction The legal justification set out in the terms
 * @param declaredValue The declared value at time of token minting
 */
struct Properties {
    string tokenIssuer;
    string assetHolder;
    string storageLocation;
    string terms;
    string jurisdiction;
    Amount declaredValue;
}

/**
 * @notice Struct encapsulating fields describing the declared value of the physical asset
 * @param currency The currency of the amount
 * @param value The value of the amount
 */
struct Amount {
    string currency;
    uint256 value;
}

/**
 * @notice Required interface of an ERC-7578 compliant contract
 */
interface IERC7578 {
    /**
     * @notice Emitted when the properties of the `tokenId` token are set
     * @param tokenId The ID of the token
     * @param properties The properties of the token
     */
    event PropertiesSet(uint256 indexed tokenId, Properties properties);

    /**
     * @notice Emitted when the properties of the `tokenId` token are removed
     * @param tokenId The ID of the token
     */
    event PropertiesRemoved(uint256 indexed tokenId);

    /**
     * @notice Retrieves all properties of the `tokenId` token
     * @dev Does NOT revert if token doesn&apos;t exist
     * @param tokenId The token ID of the minted token
     */
    function getPropertiesOf(uint256 tokenId) external view returns (Properties memory properties);
}
```

When `properties` are set, the `PropertiesSet(uint256 indexed tokenId, Properties properties)` event is emitted.

When `properties` are removed, the `PropertiesRemoved(uint256 indexed tokenId)` event is emitted.

The `getPropertiesOf(uint256 tokenId)` function MUST return the unique `properties` of a token. If the ERC-721 token is burned or has no properties set, it SHOULD return an empty `Properties` struct.

## Rationale

By not initializing a token&apos;s properties before minting, one risks that the asset&apos;s provenance represented by the token cannot be established.

Contract level validation is not used on the properties as we believe the accuracy of the data declared is the responsibility of the token issuer. This builds trust on the token issuer and the token itself.

## Backwards Compatibility

This standard is compatible with ERC-721.

## Reference Implementation

An example of an [ERC-721](/EIPs/EIPS/eip-721) that includes this proposal using the OpenZeppelin ERC-721 v5 library:

```solidity
pragma solidity ^0.8.21;

import { ERC721 } from &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;
import { IERC7578, Properties, Amount } from &quot;./interfaces/IERC7578.sol&quot;;

/**
 * @title ERC7578
 * @author DESAT
 * @notice Implementation of the ERC-7578: Physical Asset Redemption standard
 **/
contract ERC7578 is ERC721, IERC7578 {
    /**
     * @notice Thrown when the properties of a token are not initialized
     */
    error PropertiesUninitialized();

    /**
     * @notice Retrieves the properties of the `tokenId` token
     */
    mapping(uint256 tokenId =&gt; Properties) private _properties;

    /**
     * @notice Initializes the name and symbol of the ERC-721 collection
     */
    constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {}

    /**
     * @inheritdoc IERC7578
     */
    function getPropertiesOf(uint256 tokenId) public view override returns (Properties memory properties) {
        properties = _properties[tokenId];
    }

    /**
     * @notice Initializes the ERC-7578 properties of the `tokenId` token
     *
     * WARNING: This method should only be called within a function that has appropriate access control
     * It is recommended to restrict access to trusted Externally Owned Accounts (EOAs),
     * authorized contracts, or implement a Role-Based Access Control (RBAC) mechanism
     * Failure to properly secure this method could lead to unauthorized modification of token properties
     *
     * Emits a {PropertiesSet} event
     */
    function _setPropertiesOf(uint256 tokenId, Properties calldata properties) internal {
        _properties[tokenId] = Properties({
            tokenIssuer: properties.tokenIssuer,
            assetHolder: properties.assetHolder,
            storageLocation: properties.storageLocation,
            terms: properties.terms,
            jurisdiction: properties.jurisdiction,
            declaredValue: Amount({
                currency: properties.declaredValue.currency,
                value: properties.declaredValue.value
            })
        });

        emit PropertiesSet(tokenId, _properties[tokenId]);
    }

    /**
     * @notice Removes the properties of the `tokenId` token
     * @param tokenId The unique identifier of the token whose properties are to be removed
     *
     * Emits a {PropertiesRemoved} event
     */
    function _removePropertiesOf(uint256 tokenId) internal {
        delete _properties[tokenId];
        emit PropertiesRemoved(tokenId);
    }

    /**
     * @notice Override of the {_update} function to remove the properties of the `tokenId` token or
     * to check if they are set before minting
     * @param tokenId The unique identifier of the token being minted or burned
     */
    function _update(address to, uint256 tokenId, address auth) internal virtual override returns (address) {
        address from = _ownerOf(tokenId);
        if (to == address(0)) {
            _removePropertiesOf(tokenId);
        } else if (from == address(0)) {
            if (bytes(_properties[tokenId].tokenIssuer).length == 0) revert PropertiesUninitialized();
        }

        return super._update(to, tokenId, auth);
    }
}
```

## Security Considerations

To ensure authenticity, token properties must be set only via a method that is restricted to a trusted Externally Owned Account (EOA) or contract. This trusted entity must verify that the properties accurately reflect the real physical attributes of the represented asset. Additionally, proper access control mechanisms should be implemented to prevent unauthorized modifications of token properties after they are set.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 01 Aug 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7578</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7578</guid>
      </item>
    
      <item>
        <title>Minimal Modular Smart Accounts</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7579-minimal-modular-smart-accounts/17336</comments>
        
        <description>## Abstract

This proposal outlines the minimally required interfaces and behavior for modular smart accounts and modules to ensure interoperability across implementations. For accounts, the standard specifies execution, config and fallback interfaces as well as compliance to [ERC-165](/EIPs/EIPS/eip-165) and [ERC-1271](/EIPs/EIPS/eip-1271). For modules, the standard specifies a core interface, module types and type-specific interfaces.

## Motivation

Contract accounts are gaining adoption with many accounts being built using a modular architecture. These modular contract accounts (hereafter smart accounts) move functionality into external contracts (modules) in order to increase the speed and potential of innovation, to future-proof themselves and to allow customizability by developers and users. However, currently these smart accounts are built in vastly different ways, creating module fragmentation and vendor lock-in. There are several reasons for why standardizing smart accounts is very beneficial to the ecosystem, including:

- Interoperability for modules to be used across different smart accounts
- Interoperability for smart accounts to be used across different wallet applications and sdks
- Preventing significant vendor lock-in for smart account users

However, it is highly important that this standardization is done with minimal impact on the implementation logic of the accounts, so that smart account vendors can continue to innovate, while also allowing a flourishing, multi-account-compatible module ecosystem. As a result, the goal of this standard is to define the smart account and module interfaces and behavior that is as minimal as possible while ensuring interoperability between accounts and modules.

## Specification

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

### Definitions

- **Smart account** - A smart contract account that has a modular architecture.
- **Module** - A smart contract with self-contained smart account functionality.
  - Validator: A module used during the validation phase to determine if a transaction is valid and should be executed on the account.
  - Executor: A module that can execute transactions on behalf of the smart account via a callback.
  - Fallback Handler: A module that can extend the fallback functionality of a smart account.
- **EntryPoint** - A trusted singleton contract according to [ERC-4337](/EIPs/EIPS/eip-4337) specifications.
- **Validation** - Any functionality used to determine if an execution should be made on the account. When using ERC-4337, this function will be `validateUserOp`.
- **Execution** - Any functionality used to execute an operation from or on the users account. When using ERC-4337, this will be called by the EntryPoint using `userOp.callData`.

### Account

#### Validation

This standard does not dictate how validator selection is implemented. However, should a smart account encode validator selection mechanisms in data fields passed to the validator (e.g. in `userOp.signature` if used with ERC-4337), the smart account MUST sanitize the affected values before invoking the validator.

The smart account&apos;s validation function SHOULD return the return value of the validator.

#### Execution Behavior

To comply with this standard, smart accounts MUST implement the execution interface below:

```solidity
interface IERC7579Execution {
    /**
     * @dev Executes a transaction on behalf of the account. MAY be payable.
     * @param mode The encoded execution mode of the transaction.
     * @param executionCalldata The encoded execution call data.
     *
     * MUST ensure adequate authorization control: e.g. onlyEntryPointOrSelf if used with ERC-4337
     * If a mode is requested that is not supported by the Account, it MUST revert
     */
    function execute(bytes32 mode, bytes calldata executionCalldata) external;

    /**
     * @dev Executes a transaction on behalf of the account. MAY be payable.
     *         This function is intended to be called by Executor Modules
     * @param mode The encoded execution mode of the transaction.
     * @param executionCalldata The encoded execution call data.
     *
     * @return returnData An array with the returned data of each executed subcall
     *
     * MUST ensure adequate authorization control: i.e. onlyExecutorModule
     * If a mode is requested that is not supported by the Account, it MUST revert
     */
    function executeFromExecutor(bytes32 mode, bytes calldata executionCalldata)
        external
        returns (bytes[] memory returnData);
}
```

The account MAY also implement the following function in accordance with ERC-4337:

```solidity
/**
 * @dev ERC-4337 executeUserOp according to ERC-4337 v0.7
 *         This function is intended to be called by ERC-4337 EntryPoint.sol
 * @param userOp PackedUserOperation struct (see ERC-4337 v0.7+)
 * @param userOpHash The hash of the PackedUserOperation struct
 *
 * MUST ensure adequate authorization control: i.e. onlyEntryPoint
 */
function executeUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) external;
```

If an account chooses to implement `executeUserOp`, this method SHOULD ensure the account executes `userOp.calldata` except 4 most significant bytes, which are reserved for `executeUserOp.selector` as per ERC-4337. Thus the `userOp.callData[4:]` should represent the calldata for a valid call to the account. It is RECOMMENDED that the account executes a `delegatecall` in order to preserve the original `msg.sender` to the account.

Example:

```
(bool success, bytes memory innerCallRet) = address(this).delegatecall(userOp.callData[4:]);
```

The execution mode is a `bytes32` value that is structured as follows:

- callType (1 byte): `0x00` for a single `call`, `0x01` for a batch `call`, `0xfe` for `staticcall` and `0xff` for `delegatecall`
- execType (1 byte): `0x00` for executions that revert on failure, `0x01` for executions that do not revert on failure but implement some form of error handling
- unused (4 bytes): this range is reserved for future standardization
- modeSelector (4 bytes): an additional mode selector that can be used to create further execution modes
- modePayload (22 bytes): additional data to be passed

Here is a visual representation of the execution mode:

| CallType | ExecType | Unused  | ModeSelector | ModePayload |
| -------- | -------- | ------- | ------------ | ----------- |
| 1 byte   | 1 byte   | 4 bytes | 4 bytes      | 22 bytes    |

Accounts are NOT REQUIRED to implement all execution modes. The account MUST declare what modes are supported in `supportsExecutionMode` (see below) and if a mode is requested that is not supported by the account, the account MUST revert.

The account MUST encode the execution data the following ways:

- For single calls, the `target`, `value` and `callData` are packed in this order (ie `abi.encodePacked` in Solidity).
- For delegatecalls, the `target` and `callData` are packed in this order (ie `abi.encodePacked` in Solidity).
- For batch calls, the `targets`, `values` and `callDatas` are put into an array of `Execution` structs that includes these fields in this order (ie `Execution(address target, uint256 value, bytes memory callData)`). Then, this array is encoded with padding (ie `abi.encode` in Solidity).

#### Account configurations

To comply with this standard, smart accounts MUST implement the account config interface below:

```solidity
interface IERC7579AccountConfig {
    /**
     * @dev Returns the account id of the smart account
     * @return accountImplementationId the account id of the smart account
     *
     * MUST return a non-empty string
     * The accountId SHOULD be structured like so:
     *        &quot;vendorname.accountname.semver&quot;
     * The id SHOULD be unique across all smart accounts
     */
    function accountId() external view returns (string memory accountImplementationId);

    /**
     * @dev Function to check if the account supports a certain execution mode (see above)
     * @param encodedMode the encoded mode
     *
     * MUST return true if the account supports the mode and false otherwise
     */
    function supportsExecutionMode(bytes32 encodedMode) external view returns (bool);

    /**
     * @dev Function to check if the account supports a certain module typeId
     * @param moduleTypeId the module type ID according to the ERC-7579 spec
     *
     * MUST return true if the account supports the module type and false otherwise
     */
    function supportsModule(uint256 moduleTypeId) external view returns (bool);
}
```

#### Module configurations

To comply with this standard, smart accounts MUST implement the module config interface below.

When storing an installed module, the smart account MUST ensure that there is a way to differentiate between module types. For example, the smart account should be able to implement access control that only allows installed executors, but not other installed modules, to call the `executeFromExecutor` function.

```solidity
interface IERC7579ModuleConfig {
    event ModuleInstalled(uint256 moduleTypeId, address module);
    event ModuleUninstalled(uint256 moduleTypeId, address module);

    /**
     * @dev Installs a Module of a certain type on the smart account
     * @param moduleTypeId the module type ID according to the ERC-7579 spec
     * @param module the module address
     * @param initData arbitrary data that may be required on the module during `onInstall`
     * initialization.
     *
     * MUST implement authorization control
     * MUST call `onInstall` on the module with the `initData` parameter if provided
     * MUST emit ModuleInstalled event
     * MUST revert if the module is already installed or the initialization on the module failed
     */
    function installModule(uint256 moduleTypeId, address module, bytes calldata initData) external;

    /**
     * @dev Uninstalls a Module of a certain type on the smart account
     * @param moduleTypeId the module type ID according the ERC-7579 spec
     * @param module the module address
     * @param deInitData arbitrary data that may be required on the module during `onInstall`
     * initialization.
     *
     * MUST implement authorization control
     * MUST call `onUninstall` on the module with the `deInitData` parameter if provided
     * MUST emit ModuleUninstalled event
     * MUST revert if the module is not installed or the deInitialization on the module failed
     */
    function uninstallModule(uint256 moduleTypeId, address module, bytes calldata deInitData) external;

    /**
     * @dev Returns whether a module is installed on the smart account
     * @param moduleTypeId the module type ID according the ERC-7579 spec
     * @param module the module address
     * @param additionalContext arbitrary data that may be required to determine if the module is installed
     *
     * MUST return true if the module is installed and false otherwise
     */
    function isModuleInstalled(uint256 moduleTypeId, address module, bytes calldata additionalContext) external view returns (bool);
}
```

#### Hooks

Hooks are an OPTIONAL extension of this standard. Smart accounts MAY use hooks to execute custom logic and checks before and/or after the smart accounts performs a single or batched execution. To comply with this OPTIONAL extension, a smart account:

- MUST call the `preCheck` function of one or multiple hooks before any call or batch of calls going through execute or executeFromExecutor
- MUST call the `postCheck` function of one or multiple hooks after any call or batch of calls through execute or executeFromExecutor
- Is RECOMMENDED to call `preCheck` and `postCheck` before and after executing calls to `installModule` or `uninstallModule`
- Is RECOMMENDED to call `preCheck` and `postCheck` before and after executing calls through other (custom) functions called execution

#### ERC-1271 Forwarding

The smart account MUST implement the ERC-1271 interface. The `isValidSignature` function calls MAY be forwarded to a validator. If ERC-1271 forwarding is implemented, the validator MUST be called with `isValidSignatureWithSender(address sender, bytes32 hash, bytes signature)`, where the sender is the `msg.sender` of the call to the smart account. Should the smart account implement any validator selection encoding in the `bytes signature` parameter, the smart account MUST sanitize the parameter, before forwarding it to the validator.

The smart account&apos;s ERC-1271 `isValidSignature` function SHOULD return the return value of the validator that the request was forwarded to.

#### Fallback

Smart accounts MAY implement a fallback function that forwards the call to a fallback handler.

If the smart account has a fallback handler installed, it:

- MUST use `call` or `staticcall` to invoke the fallback handler
- MUST utilize [ERC-2771](/EIPs/EIPS/eip-2771) to add the original `msg.sender` to the `calldata` sent to the fallback handler
- MUST route to fallback handlers based on the function selector of the calldata
- MAY implement authorization control, which SHOULD be done via hooks

If the account adds features via fallback, these should be considered the same as if the account was implementing those features natively.
ERC-165 support (see below) is one example of such an approach. Note, that it is only RECOMMENDED to implement view functions via fallback where this can lead to greater extensibility. It is NOT RECOMMENDED to implement core account logic via a fallback.

#### ERC-165

Smart accounts MAY implement ERC-165. However, for every interface function that reverts instead of implementing the functionality, the smart account MUST return `false` for the corresponding interface id.

### Modules

This standard separates modules into the following different types that each has a unique and incremental identifier, which MUST be used by accounts, modules and other entities to identify the module type:

- Validation (type id: 1)
- Execution (type id: 2)
- Fallback (type id: 3)
- Hooks (type id: 4)

Note: A single module can be of multiple types.

Modules MUST implement the following interface:

```solidity
interface IERC7579Module {
     /**
     * @dev This function is called by the smart account during installation of the module
     * @param data arbitrary data that may be required on the module during `onInstall` initialization
     *
     * MUST revert on error (e.g. if module is already enabled)
     */
    function onInstall(bytes calldata data) external;

    /**
     * @dev This function is called by the smart account during uninstallation of the module
     * @param data arbitrary data that may be required on the module during `onUninstall` de-initialization
     *
     * MUST revert on error
     */
    function onUninstall(bytes calldata data) external;

    /**
     * @dev Returns boolean value if module is a certain type
     * @param moduleTypeId the module type ID according the ERC-7579 spec
     *
     * MUST return true if the module is of the given type and false otherwise
     */
    function isModuleType(uint256 moduleTypeId) external view returns(bool);
}
```

Note: A single module that is of multiple types MAY decide to pass `moduleTypeId` inside `data` to `onInstall` and/or `onUninstall` methods, so those methods are able to properly handle installation/uninstallation for various types.
Example:

```solidity
// Module.sol
function onInstall(bytes calldata data) external {
    // ...
    (uint256 moduleTypeId, bytes memory otherData) = abi.decode(data, (uint256, bytes));
    // ...
}
```

#### Validators

Validators MUST implement the `IERC7579Module` and the `IERC7579Validator` interface and have module type id: `1`.

```solidity
interface IERC7579Validator is IERC7579Module {
    /**
     * @dev Validates a UserOperation
     * @param userOp the ERC-4337 PackedUserOperation
     * @param userOpHash the hash of the ERC-4337 PackedUserOperation
     *
     * MUST validate that the signature is a valid signature of the userOpHash
     * SHOULD return ERC-4337&apos;s SIG_VALIDATION_FAILED (and not revert) on signature mismatch
     */
    function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) external returns (uint256);

    /**
     * @dev Validates a signature using ERC-1271
     * @param sender the address that sent the ERC-1271 request to the smart account
     * @param hash the hash of the ERC-1271 request
     * @param signature the signature of the ERC-1271 request
     *
     * MUST return the ERC-1271 `MAGIC_VALUE` if the signature is valid
     * MUST NOT modify state
     */
    function isValidSignatureWithSender(address sender, bytes32 hash, bytes calldata signature) external view returns (bytes4);
}
```

#### Executors

Executors MUST implement the `IERC7579Module` interface and have module type id: `2`.

#### Fallback Handlers

Fallback handlers MUST implement the `IERC7579Module` interface and have module type id: `3`.

Fallback handlers MAY implement authorization control. Fallback handlers that do implement authorization control, MUST NOT rely on `msg.sender` for authorization control but MUST use ERC-2771 `_msgSender()` instead.

#### Hooks

Hooks MUST implement the `IERC7579Module` and the `IERC7579Hook` interface and have module type id: `4`.

```solidity
interface IERC7579Hook is IERC7579Module {
    /**
     * @dev Called by the smart account before execution
     * @param msgSender the address that called the smart account
     * @param value the value that was sent to the smart account
     * @param msgData the data that was sent to the smart account
     *
     * MAY return arbitrary data in the `hookData` return value
     */
    function preCheck(address msgSender, uint256 value, bytes calldata msgData) external returns (bytes memory hookData);

    /**
     * @dev Called by the smart account after execution
     * @param hookData the data that was returned by the `preCheck` function
     *
     * MAY validate the `hookData` to validate transaction context of the `preCheck` function
     */
    function postCheck(bytes calldata hookData) external;
}
```

## Rationale

### Minimal approach

Smart accounts are a new concept and we are still learning about the best ways to build them. Therefore, we should not be too opinionated about how they are built. Instead, we should define the most minimal interfaces that allow for interoperability between smart accounts and modules to be used across different account implementations.

Our approach has been twofold:

1. Take learnings from existing smart accounts that have been used in production and from building interoperability layers between them
2. Ensure that the interfaces are as minimal and open to alternative architectures as possible

### Extensions

While we want to be minimal, we also want to allow for innovation and opinionated features. Some of these features might also need to be standardized (for similar reasons as the core interfaces) even if not all smart accounts will implement them. To ensure that this is possible, we suggest for future standardization efforts to be done as extensions to this standard. This means that the core interfaces will not change, but that new interfaces can be added as extensions. These should be proposed as separate ERCs, for example with the title &quot;[FEATURE] Extension for [ERC-7579](/EIPs/EIPS/eip-7579)&quot;.

### Specification

#### Execution mode

Accounts need to be able to execute calldata in different ways. Rather than defining a separate function for each combination of execution types, we decided to encode the execution type in a single `bytes32` value. This allows for a more flexible and extensible approach, while also making the code far easier to write, read, maintain and audit. As explained above, the exeuction mode consists of two bytes that encode the call type and the execution type. The call type covers the three different methods of calls, namely single, batched and `delegatecall` (note that you can `delegatecall` to a multicall contract to batch `delegatecalls`). The execution type covers the two different types of executions, namely executions that revert on failure and executions that do not revert on failure but implement some form of error handling. This allows for accounts to batch together uncorrelated executions, such that if one execution fails, the other executions can still be executed. These two bytes are followed by 4 unused bytes that are reserved for futurre standardization, should this be required. This is followed by an item of 4 bytes which is a custom mode selector that accounts can implement. This allows for accounts to implement custom execution modes that are not covered by the standard and do not need to be standardized. This item is 4 bytes long to ensure collision resistance between different account vendors, with the same guarantees as Solidity function selectors. Finally, the last 22 bytes are reserved for custom data that can be passed to the account. This allows for accounts to pass any data up to 22 bytes, such as a 2 byte flag followed by an address, or otherwise a pointer to further data packed into the calldata for the execution. For example, this payload can be used to pass a hook address that should be executed before and/or after the execution.

#### Differentiating module types

Not differentiating between module types could present a security issue when enforcing authorization control. For example, if a smart account treats validators and executors as the same type of module, it could allow a validator to execute arbitrary transactions on behalf of the smart account.

#### Account id

The account config interface includes a function `accountId` which can be used to identify an account. This is especially useful for frontend libraries that need to determine what account type and version is being used in order to implement the correct logic for account behavior that is not standardized. Alternate solutions include using an ERC-165-like interface to declare the exact differences and supported features of accounts or returning a keccak hash of the account id. However, the first solution is not as flexible as the account id and requires agreeing on a well-defined set of features to use, while the second solution is not as human-readable as the account id.

#### Dependence on ERC-4337

This standard has a strict dependency on ERC-4337 for the validation flow. However, it is likely that smart account builders will want to build modular accounts in the future that do not use ERC-4337 but, for example, a native account abstraction implementation on a rollup. Once this starts to happen, the proposed upgrade path for this standard is to move the ERC-4337 dependency into an extension (ie a separate ERC) and to make it optional for smart accounts to implement. If it is required to standardize the validation flow for different account abstraction implementations, then these requirements could also be moved into separate extensions.

The reason this is not done from the start is that currently, the only modular accounts that are being built are using ERC-4337. Therefore, it makes sense to standardize the interfaces for these accounts first and to move the ERC-4337 dependency into an extension once there is a need for it. This is to maximize learnings about how modular accounts would look like when built on different account abstraction implementations.

## Backwards Compatibility

### Already deployed smart accounts

Smart accounts that have already been deployed will most likely be able to implement this standard. If they are deployed as proxies, it is possible to upgrade to a new account implementation that is compliant with this standard. If they are deployed as non-upgradeable contracts, it might still be possible to become compliant, for example by adding a compliant adapter as a fallback handler, if this is supported.

## Reference Implementation

A full interface of a smart account can be found in [`IMSA.sol`](/EIPs/assets/eip-7579/IMSA.sol).

## Security Considerations

Needs more discussion. Some initial considerations:

- Implementing `delegatecall` executions on a smart account must be considered carefully. Note that smart accounts implementing `delegatecall` must ensure that the target contract is safe, otherwise security vulnerabilities are to be expected.
- The `onInstall` and `onUninstall` functions on modules may lead to unexpected callbacks (e.g. reentrancy). Account implementations should consider this by implementing adequate protection routines. Furthermore, modules could maliciously revert on `onUninstall` to stop the account from uninstalling a module and removing it from the account.
- For modules types where only a single module is active at one time (e.g. fallback handlers), calling `installModule` on a new module will not properly uninstall the previous module, unless this is properly implemented. This could lead to unexpected behavior if the old module is then added again with left over state.
- Insufficient authorization control in fallback handlers can lead to unauthorized executions.
- Malicious Hooks may revert on `preCheck` or `postCheck`, adding untrusted hooks may lead to a denial of service of the account.
- Currently account configuration functions (e.g. `installModule`) are designed for single operations. An account could allow these to be called from `address(this)`, creating the possibility to batch configuration operations. However, if an account implements greater authorization control for these functions since they are more sensitive, then these measures can be bypassed by nesting calls to configuration options in calls to self.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 14 Dec 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7579</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7579</guid>
      </item>
    
      <item>
        <title>Advertisement Tracking Interface</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7580-inter-dapp-tracking-inferface/17653</comments>
        
        <description>## Abstract

This ERC proposes a standard interface for advertisement clients to track user actions in contracts and check corresponding rewards from advertisement protocols. Contracts implementing the interface use events to define a region of interest within a transaction. A Dapp could implement this interface to join an advertisement protocol, which enable projects to fund users for specific actions in a contract. While users could benefit from project funds, dapps would also get proportional rewards once they joined the protocol.


## Motivation

Dapps would propsper due to mass adoption and there emerges surging demands for advertisement on chain. Compared with advertisements in web2, web3 has tremendous advantages on delivery and many other fields. We do need a set of standard tracking interfaces to facilitate advertisement related developments, which could create new economic cycles on chain, further boost dapp prosperity and ultimately benefit on chain users.

Tracking interface standard should be designed with essential &amp; universal support for tracking user actions, and minimum restriction, which could leave most innovative space for airdrop (or advertisement) protocol. The general routine would work like this:
1. projects get a seed id (hash) from promotion side
2. before the target promotion action starts, project contracts called the interface `onTrackStart(id, contract_address, function_hash)`
3. after the target promotion action ends, project contracts called the inferface `onTrackEnd(id, contract_address, function_hash)`
4. promotion contract collect the project action info and distribute the rewards back to projects

For example, we have two entities holding their respective contracts: contract A and contract B. Contract A targets on users who did specific key moves(eg. commit specific functions) in contract B and would give bonus/airdrop to these users. Sure B would also get incentives in the meanwhile. To connect all these dots, B needs to identity these users, verify they&apos;re coming for the A&apos;s bonus. Hence, we need a track mechanism to facilitate such business.

## Specification

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.

### Interfaces

This protocol standardizes how to keep track of inter-dapp operations, which initially offers 2 main methods `onTrackStart` and `onTrackEnd`.

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.10;

interface IERCXXX {
    // Events

    /// @dev Emits when track starts.
    /// @param track_id track id
    /// @param contract_address the address of tracking contract
    /// @param function_hash the hash of tracking function with params
    event onTrackStartRecorded(uint256 track_id, address contract_address, bytes32 function_hash);

    /// @dev Emits when track starts.
    /// @param track_id track id
    /// @param contract_address the address of tracking contract
    /// @param function_hash the hash of tracking function with params
    event onTrackEndRecorded(uint256 track_id, address contract_address, bytes32 function_hash);

    // Functions

    /// @dev Track a specified contract function start move.
    /// @param track_id track id
    /// @param contract_address the address of tracking contract
    /// @param function_hash the hash of tracking function with params
    function onTrackStart(uint256 track_id, address contract_address, bytes32 function_hash) external;

    /// @dev Track a specified contract function end move.
    /// @param track_id track id
    /// @param contract_address the address of tracking contract
    /// @param function_hash the hash of tracking function with params
    function onTrackEnd(uint256 track_id, address contract_address, bytes32 function_hash);
}
```


## Rationale

The core mechanism for this proposal is to provide a shared tracking interface for inter-dapp operations, to improve the efficiency and fulfill the required tracking business. We provide two interface functions `onTrackStart` and `onTrackEnd` to fill the basic required info and connect the necessary dots. Sure there&apos;re more demands for more functions and it would be updated later.

## Backwards Compatibility

No backward compatibility issues are introduced by this standard.

## Security Considerations

&lt;!-- TODO: discuss more --&gt;

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).</description>
        <pubDate>Wed, 13 Dec 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7580</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7580</guid>
      </item>
    
      <item>
        <title>Modular Accounts with Delegated Validation</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7582-modular-accounts-with-delegated-validation/17640</comments>
        
        <description>## Abstract

This proposal standardizes a method for adding plugins and composable logic to smart contract accounts built on existing interfaces like [ERC-4337](/EIPs/EIPS/eip-4337) (e.g., ERC-4337&apos;s `IAccount`). Specifically, by formalizing how applications can use the ERC-4337 Entry Point `NonceManager` and the emission of the `IEntryPoint` `UserOperationEvent` to account for plugin interactions, as well, as how to extract designated validators (in this case, by means of `IAccount`&apos;s `validateUserOp`), accounts can specify how they call plugin contracts and grant special executory access for more advanced operations. Furthermore, this minimalist plugin approach is developer-friendly and complimentary to existing account abstraction standards by not requiring any additional functions for contracts that follow the `IAccount` interface (itself minimalist in only specifying one function, `validateUserOp`).

## Motivation

Smart contract accounts (contract accounts) are a powerful tool for managing digital assets and executing transactions by allowing users to program their interactions with blockchains. However, they are often limited in their functionality and flexibility without sufficient consensus around secure abstraction designs (albeit, the adoption of ERC-4337 is the preferred path of this proposal). For example, contract accounts are often unable to support social recovery, payment schedules, and other features that are common in traditional financial systems without efficient and predictable schemes to delegate execution and other access rights to approximate the UX of custodial and more specialized applications.

Account abstraction standards like ERC-4337 have achieved simplification of many core contract account concerns such as transaction fee payments, but to fully leverage the expressive capability of these systems to accomplish user intents, minimalist methods to delegate contract account access and validation to other contracts would aid their UX and extend the benefits of centering operations around the Entry Point.

While the `IAccount` interface from ERC-4337 does not specify a way to add custom validation logic to contract accounts to support plugins and similar extensions without upgrades or migrations, it nevertheless contains sufficient information to do so efficiently. This proposal therefore offers a method for adding plugins and other composable validation logic to smart contract accounts built on existing interfaces with singleton nonce-tracking like ERC-4337&apos;s `IAccount` and `NonceManager`.

## Specification

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

![diagram showing proposed flow](/EIPs/assets/eip-7582/base-flow.svg)

We leverage the key in ERC-4337 semi-abstracted nonce as the pointer to `validator` identifier. If a non-sequential key (`&gt;type(uint64).max`) is used as an ERC-4337 Entry Point `UserOperation` (userOp) `nonce`, the `validateUserOp` function in the `sender` contract account MUST extract the validator identifier, this MAY be the address itself or a pointer to the validator address in storage. Once the validator contract address is extracted, the proposed contract account (henceforth, shall be referred to as MADV account) MUST forward the userOp calldata to the validator. This calldata SHOULD be the entire userOp. In response to this delegated validation, the validator contract MUST return the ERC-4337 `validationData`, and the MADV `sender` account MUST return this as the `validationData` to the Entry Point. 

In all of the above validation steps, the validator contract MUST respect the ERC-4337 Entry Point conventions. Note, that while validator key data might be included elsewhere in a `UserOperation` to achieve similar contract account modularity, for example, by packing this data into the `signature` field, this proposal opts to repurpose `nonce` for this pointer to minimize calldata costs and to benefit from the EntryPoint&apos;s `getNonce` accounting, as well as the discoverability of user plugin interactions in the `UserOperationEvent` which exposes `nonce` but not other userOp data.

### ERC-4337 references:

`PackedUserOperation` interface

```solidity
/**
 * User Operation struct
 * @param sender                - The sender account of this request.
 * @param nonce                 - Unique value the sender uses to verify it is not a replay. In MADV, the validator identifier is encoded in the high 192 bit (`key`) of the nonce value
 * @param initCode              - If set, the account contract will be created by this constructor/
 * @param callData              - The method call to execute on this account.
 * @param accountGasLimits      - Packed gas limits for validateUserOp and gas limit passed to the callData method call.
 * @param preVerificationGas    - Gas not calculated by the handleOps method, but added to the gas paid.
 *                                Covers batch overhead.
 * @param gasFees               - packed gas fields maxPriorityFeePerGas and maxFeePerGas - Same as EIP-1559 gas parameters.
 * @param paymasterAndData      - If set, this field holds the paymaster address, verification gas limit, postOp gas limit and paymaster-specific extra data
 *                                The paymaster will pay for the transaction instead of the sender.
 * @param signature             - Sender-verified signature over the entire request, the EntryPoint address and the chain ID.
 */
struct PackedUserOperation {
    address sender;
    uint256 nonce;
    bytes initCode;
    bytes callData;
    bytes32 accountGasLimits;
    uint256 preVerificationGas;
    bytes32 gasFees;
    bytes paymasterAndData;
    bytes signature;
}
```

`IAccount` interface

```solidity
interface IAccount {
    /**
     * Validate user&apos;s signature and nonce
     * the entryPoint will make the call to the recipient only if this validation call returns successfully.
     * signature failure should be reported by returning SIG_VALIDATION_FAILED (1).
     * This allows making a &quot;simulation call&quot; without a valid signature
     * Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure.
     *
     * @dev Must validate caller is the entryPoint.
     *      Must validate the signature and nonce
     * @param userOp              - The operation that is about to be executed.
     * @param userOpHash          - Hash of the user&apos;s request data. can be used as the basis for signature.
     * @param missingAccountFunds - Missing funds on the account&apos;s deposit in the entrypoint.
     *                              This is the minimum amount to transfer to the sender(entryPoint) to be
     *                              able to make the call. The excess is left as a deposit in the entrypoint
     *                              for future calls. Can be withdrawn anytime using &quot;entryPoint.withdrawTo()&quot;.
     *                              In case there is a paymaster in the request (or the current deposit is high
     *                              enough), this value will be zero.
     * @return validationData       - Packaged ValidationData structure. use `_packValidationData` and
     *                              `_unpackValidationData` to encode and decode.
     *                              &lt;20-byte&gt; sigAuthorizer - 0 for valid signature, 1 to mark signature failure,
     *                                 otherwise, an address of an &quot;authorizer&quot; contract.
     *                              &lt;6-byte&gt; validUntil - Last timestamp this operation is valid. 0 for &quot;indefinite&quot;
     *                              &lt;6-byte&gt; validAfter - First timestamp this operation is valid
     *                                                    If an account doesn&apos;t use time-range, it is enough to
     *                                                    return SIG_VALIDATION_FAILED value (1) for signature failure.
     *                              Note that the validation code cannot use block.timestamp (or block.number) directly.
     */
    function validateUserOp(
        PackedUserOperation calldata userOp,
        bytes32 userOpHash,
        uint256 missingAccountFunds
    ) external returns (uint256 validationData);
}
```

`NonceManager` interface

```solidity
 /**
     * Return the next nonce for this sender.
     * Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop)
     * But UserOp with different keys can come with arbitrary order.
     *
     * @param sender the account address
     * @param key the high 192 bit of the nonce, in MADV the validator identifier is encoded here 
     * @return nonce a full nonce to pass for next UserOp with this sender.
     */
    function getNonce(address sender, uint192 key)
    external view returns (uint256 nonce);
```

`UserOperationEvent` 

```solidity
/***
     * An event emitted after each successful request
     * @param userOpHash - unique identifier for the request (hash its entire content, except signature).
     * @param sender - the account that generates this request.
     * @param paymaster - if non-null, the paymaster that pays for this request.
     * @param nonce - the nonce value from the request.
     * @param success - true if the sender transaction succeeded, false if reverted.
     * @param actualGasCost - actual amount paid (by account or paymaster) for this UserOperation.
     * @param actualGasUsed - total gas used by this UserOperation (including preVerification, creation, validation and execution).
     */
    event UserOperationEvent(bytes32 indexed userOpHash, address indexed sender, address indexed paymaster, uint256 nonce, bool success, uint256 actualGasCost, uint256 actualGasUsed);
```

## Rationale 

This proposal is designed to be a minimalist extension to ERC-4337 that allows for additional functionality without requiring changes to the existing interface. Keeping the proposal&apos;s footprint small. 

Further, by repurposing the nonce field for the validator identifier we minimize calldata costs and leverage existing `getNonce` accounting. The `UserOperationEvent` emits nonce which can be used for tracking validator invocations without additional events. Other options like packing the validator identifier into the `signature` field were considered but were rejected due to potential for conflict with other signatures schemes and increased opaqueness into validator invocation. 

This proposal allows for MADV accounts to specify their own method for extracting the validator address from the `nonce`. This provides flexibility to account developers and supports both &quot;just in time&quot; validators as well as a more predictable storage pattern for plugin reuse.

The requirement is simply to use `nonce` for encoding an identifier and to return the `validationData` from the extracted validator contract to the `EntryPoint` in line with the requirements of the ERC-4337 `validateUserOp` function. 

## Backwards Compatibility

No backward compatibility issues found.

## Reference Implementation

See the [MADV reference implementation](/EIPs/assets/eip-7582/MADVAccount.sol) for a simple example of how to implement this proposal.

## Security Considerations

As this proposal introduces no new functions and leaves implementation of the validator extraction method and approval logic open to developers, the surface for security issues is intentionally kept small. Nevertheless, specific validator use cases require further discussion and consideration of the overall ERC-4337 verification flow and its underlying security.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).</description>
        <pubDate>Mon, 25 Dec 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7582</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7582</guid>
      </item>
    
      <item>
        <title>MixHash and Public Data Storage Proofs</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7585-mixhash-and-public-data-storage-proofs/17707</comments>
        
        <description>## Abstract

This proposal introduces a design for &quot;minimum value selection&quot; storage proofs on Merkle trees. The design consists of two main components:

1. A hashing algorithm termed MixHash, aimed to replace the commonly used Keccak256 and SHA256 algorithms.
2. Public data storage proofs. This enables anyone to present a proof to a public network, verifying their possession of a copy of specific public data marked by MixHash.

Additionally, the proposal discusses the practical implementation of this design in various scenarios and suggests some improvements to the [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155) standards.

## Motivation

The [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155) standards are widely used in the NFT  fields. However, the current standards do not provide a mechanism for verifying the existence of public data. This is a major obstacle to the development of many applications, such as decentralized data markets, decentralized data storage, and decentralized data oracles.

## Specification

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

### MixHash

MixHash is a Merkle tree root hash value that incorporates data length information. Its structure is as follows:

```text
     +-----------256 bits MixHash-----------+
High |-2-|----62----|----------192----------| Low

2   bits: Hash algorithm selection, where 0b00 represents SHA256, and 0b10 represents Keccak256. (0b01, 0b11 are reserved)
62  bits: File size. Hence, MixHash can support file sizes up to 2^62-1.
192 bits: The lower 192 bits of the Merkel root node value constructed by the designated hash algorithm.

```

Given a file, we can construct a MixHash through the following defined steps:

1. File MUST Split into 1KB chunks. MUST Pad zeros to the end of the last chunk if needed.

2. Calculate the hash for each chunk and the low 128bits is the Merkle Tree leaf value.

3. Construct a Merkle tree , root node hash algorithm is 256bits, other node use low 128bits of the 256bits hash result.

4. Return the combination of hash type, the file size, and the low 192 bits of the Merkle tree root node hash.

MixHash retains a length of 256 bits, so replacing the widely used Keccak256 and SHA256 with MixHash incurs no additional cost. Although including the file length in the upper 62 bits compromises security to some extent, the 192-bit hash length is already sufficient for defending against hash collisions.

The following is the pseudo code for generating Mixhash:

```python
def generateMixHash(blockHeight,hashType,file):
    chunk_hash_array = []
    for chunk in file:
        if len(chunk) &lt; 1024:
            chunk = chunk + b&apos;\x00&apos; * (1024-len(chunk))
        chunk_hash_array.append(getChunkHash(chunk,hashType))
    merkle_tree_root = getMerkleTreeRoot(chunk_hash_array,hash_type)
    return mix_hash(hash_type, len(file), merkle_tree_root)
```

### Public Data Storage Proofs

When MixHash is used to identify a piece of public data, anyone can construct a storage proof to demonstrate possession of a copy of that data. Here is a typical process for using a public data storage proof:

0. Users eligible to submit storage proofs for rewards are referred to as Suppliers.
1. A Supplier prepares a storage proof for data D (with MixHash `mix_hash_d`) based on a block at height `h`. A 256-bit `nonce` value for the proof is derived from this block (usually directly using the block&apos;s hash).
2. To generate a correct storage proof, the Supplier needs to traverse every 1KB chunk of D to find the optimal leaf node `m`. This is done by attempting to append the nonce value to the end of each chunk to minimize the new Merkle tree root hash. After determining `m`, the path `m_path` and leaf node value `m_leaf_data` of `m` are extracted.
3. The Supplier constructs the storage proof for data D at block time `h` using `{mix_hash_d, h, m, m_path, m_leaf_data}` and submits it to the public network.
4. The public network can validate the correctness of `m`, `m_path`, and `m_leaf_data` based on `mix_hash_d`: verifying that `m` is indeed a chunk of D. The timeliness of the proof can be verified through `h`. After passing both correctness and timeliness checks, the public network calculates `proof_result_m` based on the nonce value and existing proof information, and saves it.
5. The public network does not have enough information to verify the optimality of the proof, but other Suppliers with the full data set can submit a better `{mix_hash_d, h, better_m, better_m_path, better_m_leaf_data}` to challenge the published storage proof.
6. The public network can determine the success of the challenge by comparing `proof_result_m` and `proof_result_better_m`. A successful challenge indicates the old storage proof was forged. If no one challenges the published storage proof within a certain timeframe, it can be considered correct from a game-theoretic perspective.
7. To support healthy competition, the public network should design an appropriate economic model, rewarding users who provide correct storage proofs and penalizing those who submit false ones.

With an understanding of the above process, let us describe the generation and verification of storage proofs more precisely using `Pseudocode`.

```python
# generate proof off chain
def generateProof(mixHash, blockHeight,file) 
    nonce = getNonce(blockHeight)
    hash_type = getHashType(mixHash)
    chunk_hash_array = buildChunkHashArray(file,hash_type)

    min_index = 0
    min_merkle_tree_root = MAX_UINT256
    min_chunk = None

    m_index = 0
    for chunk in file:
      new_chunk = chunk + nonce
      chunk_hash_array[m_index] = getChunkHash(new_chunk,hash_type)
      merkle_tree_root = getMerkleTreeRoot(chunk_hash_array,hash_type)
      chunk_hash_array[m_index] = getChunkHash(chunk,hash_type)
      if (merkle_tree_root &lt; min_merkle_tree_root):
        min_merkle_tree_root = merkle_tree_root
        min_index = m_index
        min_chunk = chunk
      m_index = m_index + 1
```

```solidity
// verify on chain
function verifyDataProof(mixHash, blockHeight, m_index, m_path, m_leaf_data) {
    if(current_block_height - blockHeight &gt; MAX_BLOCK_DISTANCE) {
       revert(&quot;proof expired&quot;);
    }
    hash_type = getHashType(mixHash);
    merkle_tree_root = getMerkleTreeRootFromPath(m_path,m_leaf_data,hash_type);
    if(low192(merkle_tree_root) != low192(mixHash)) {
       revert(&quot;invalid proof&quot;);
    }

    nonce = getNonce(blockHeight);
    proof_result = getMerkleTreeRootFromPath(m_path,m_leaf_data.append(nonce),hash_type);
    last_proof_result,last_prover = getProofResult(mixHash, blockHeight);
    if(proof_result &lt; last_proof_result) {
      emit ProofPunish(last_prover);
      updateProofResult(mixHash, blockHeight, proof_result, msg.sender);
    } 
}
```

To minimize the size of the storage proof as much as possible, we have optimized the implementation of getMerkleTreeRoot: besides the RootHash, the hash values of other nodes are truncated to the lower 128 bits. This approach effectively compresses the hash value of a complete Merkle tree to half its size. The full implementation details can be found in the subsequent Reference Implementation section.

### Defending Sourcing Attack

As can be seen from the process described above, the core of constructing public data storage proofs is based on a public, non-repeating nonce value generated at a specific moment. It requires traversing the entire content of the file within a designated time to construct a correct proof. Without restrictions, this process is vulnerable to external data source attacks: Suppliers do not store data locally but obtain it through network requests when constructing storage proofs. How does our design prevent such attacks?

1. Time-Limited Response: Suppliers must submit storage proofs within a specified time. On a typical public network like Ethereum, the block time is about 15 seconds. A typical maximum block interval could be 2 (MAX_BLOCK_DISTANCE = 2), meaning Suppliers must complete the construction and submission of the storage proof within 30 seconds. This duration is insufficient for most data sources to complete transmission, thus Suppliers must store data locally to have a chance to construct storage proofs within the allotted time.

2. Economic Game Theory: The economic model based on public data storage proofs usually rewards the first Supplier to submit a correct storage proof. This means that, from a game-theoretic standpoint, the inherent delay in using external data sources to construct storage proofs reduces the likelihood of successful submission. Economically, it&apos;s less profitable than the expected gains from storing data locally. The economic model incentivizes Suppliers to store data locally.

### Success Rate of Defending Sourcing Attack

Using a strategy combining block interval limitations and priority for first-time submissions is often effective in defending against external data source attacks. The effectiveness of this approach primarily relies on the difference in speed between reading files from local storage and retrieving files from the network. We can define the success rate `R`` of defending against external data source attacks using the following formula:

```math
R = (TNetwork - TLocal) / AvgProofTime
```

The larger the AvgProofTime, the lower the success rate of defending against Sourcing Attack. Currently, the most significant factor affecting AvgProofTime is the average time for on-chain transactions. For example, in the BTC network, the time for 2 blocks is approximately 20 minutes. With such a large AvgProofTime, the success rate `R`` decreases rapidly, making sourcing attacks more likely to succeed. We can introduce a dynamically adjustable Proof of Work (PoW) mechanism to further defend against Sourcing Attack. This modification alters the formula as follows:

```math
R = (TNetwork - TLocal) / (AvgProofTime-AvgPoWTime)
```

With the introduction of the Proof of Work (PoW) concept, the strategy for submitting storage proofs becomes: constructing and submitting storage proofs within a specified time while endeavoring to complete as much PoW computation as possible. In the valid proof time window, the storage proof with the greater amount of PoW computation prevails. Such a mechanism can effectively defend against external data source attacks, especially when AvgProofTime is large.

Integrating a PoW mechanism into the design of public data storage proofs is not complex. A simple implementation could modify the second step to:

```text
2. To generate a correct storage proof, the Supplier needs to traverse all 1KB chunks of D to find the optimal leaf node `m`. The method involves attempting to append the nonce and a self-constructed noise value to the end of each chunk to minimize the new Merkle tree root hash and, according to PoW difficulty requirements, ensuring that the last x bits of the constructed `proof_result_m` are zero. After determining `m` and the noise, the path `m_path` and the leaf node value `m_leaf_data` of `m` are extracted.
```

The `Pseudocode` adjusted according to the above modifications is as follows:

```python
# generate proof with PoW off chain
POW_DIFFICULTY = 16
def generateProofWithPow(mixHash, blockHeight,file) 
  nonce = getNonce(blockHeight)
  hash_type = getHashType(mixHash)
  chunk_hash_array = buildChunkHashArray(file,hash_type)

  min_index = 0
  min_merkle_tree_root = MAX_UINT256
  min_chunk = None

  m_index = 0
  noise = 0
  while True:
    for chunk in file:
      new_chunk = chunk + nonce + noise
      chunk_hash_array[m_index] = getChunkHash(new_chunk,hash_type)
      merkle_tree_root = getMerkleTreeRoot(chunk_hash_array,hash_type)
      chunk_hash_array[m_index] = getChunkHash(chunk,hash_type)
      if (merkle_tree_root &lt; min_merkle_tree_root):
        min_merkle_tree_root = merkle_tree_root
        min_index = m_index
        min_chunk = chunk
      m_index = m_index + 1
    if(last_zero_bits(min_merkle_tree_root) &gt;= POW_DIFFICULTY):
      break
    noise = noise + 1
    
  m_path = getMerkleTreePath(chunk_hash_array, min_index)
  return storage_proof(mixHash, blockHeight, min_index, m_path, min_chunk,noise) 
```

Applying this mechanism increases the cost of generating storage proofs, which deviates from our initial intent to reduce the widespread effective storage of public data. Moreover, heavily relying on a PoW-based economic model may allow Suppliers with significant advantages in PoW through specialized hardware to disrupt the basic participatory nature of the game, reducing the widespread distribution of public data. Therefore, it is advised not to enable the PoW mechanism unless absolutely necessary.

### Limitations

1. The storage proofs discussed in this paper are not suitable for storing very small files, as small files inherently struggle to defend against external data source attacks.

2. Public data storage proofs do not address the issue of whether the data is genuinely public. Therefore, it is important to verify the public nature of MixHash in specific scenarios (which is often not easy). Allowing Suppliers to submit storage proofs for any MixHash and receive rewards would lead to a situation where Suppliers create data only they possess and exploit this to gain rewards through constructed attacks, ultimately leading to the collapse of the entire ecosystem.

### ERC Extension Suggestion: Tracking High-Value Public Data by MixHash

We can use the existing Ethereum ecosystem to confirm whether a MixHash is public data and track its value. For any contracts related to unstructured data, the `ERCPublicDataOwner` interface can be implemented. This interface determines whether a specific MixHash is associated with the current contract and attempts to return an Owner address corresponding to a MixHash. Additionally, for the existing and widely recognized NFT ecosystem, we suggest that new [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155) contracts implement a new extension interface `ERC721MixHashVerify`. This interface can explicitly associate an NFT with a MixHash. The specific interface definition is as follows:

```solidity
/// @title ERCPublicDataOwner Standard, query Owner of the specified MixHash
///  Note: the ERC-165 identifier for this interface is &lt;ERC-Number&gt;.
interface ERCPublicDataOwner {
    /**
        @notice Queries Owner of public data determined by Mixhash
        @param  mixHash    Mixhash you want to query
        @return            If it is an identified public data, return the Owner address, otherwise 0x0 will be returned
    */
    function getPublicDataOwner(bytes32 mixHash) external view returns (address);
}
```

The `ERC721MixHashVerfiy` extension is OPTIONAL for [ERC-721](/EIPs/EIPS/eip-721) smart contracts or [ERC-1155](/EIPs/EIPS/eip-1155) smart contracts. This extension can help establish a relationship between specified NFT and MixHash.

```solidity
/// @title ERC721MixHashVerfiy Extension, optional extension
///  Note: the ERC-165 identifier for this interface is &lt;ERC-Number&gt;.
interface ERC721MixHashVerfiy{
    /**
        @notice Is the tokenId of the NFT is the Mixhash?
        @return           True if the tokenId is MixHash, false if not
    */
    function tokenIdIsMixHash() external view returns (bool); 
    
    /**
        @notice Queries NFT&apos;s MixHash
        @param  _tokenId  NFT to be querying
        @return           The target NFT corresponds to MixHash, if it is not Mixhash, it returns 0x0
    */
    function tokenDataHash(uint256 _tokenId) external view returns (bytes32);
}
```

## Rationale

Storage proofs (often referred to as space-time proofs) have long been a subject of interest, with numerous implementations and related projects existing.

1. Compared to existing copy proofs based on zero-knowledge proofs, our storage proof is based on &quot;Nash Consensus,&quot; with its core principles being:
   a. The public network (on-chain) cannot verify the optimality of a proof but relies on economic game theory. This significantly reduces the costs of construction and verification.
   b. Data without value typically lacks game value and is naturally eliminated from the system. There is no commitment to elusive perpetual storage.
2. It can be fully implemented through smart contracts (although the GAS cost of the current reference implementation is somewhat high), separating storage proof from the economic model.
3. For public data, we do not strictly defend against Sybil attacks. A Sybil attack refers to a Supplier using multiple identities to commit to storing multiple copies of data D (e.g., n copies) while actually storing less (like just one copy) but providing n storage proofs, thereby succeeding in the attack. Strictly preventing Sybil attacks essentially means attaching more additional costs to data storage. The core of our storage proof is to increase the probability of the existence of public data copies through a combination of storage proofs and different economic models, rather than needing to strictly define how many copies exist. Therefore, from the perspective of the design of public data storage proofs, we do not need to defend against Sybil attacks.

## Backwards Compatibility

Using HashType allows storage proofs to be compatible with EVM-compatible public blockchain systems, as well as BTC-Like public blockchain systems. In fact, MixHash could become a new cross-chain value anchor: it can track the value of the same data represented by MixHash across different public blockchain networks using different models, achieving the aggregation of cross-chain values. Considering the need for backward compatibility, we have set the default HashType of MixHash to SHA256. Two categories of HashType remain unused, leaving ample room for future expansion.

## Test Cases

PublicDataProofDemo includes test cases written using Hardhat.

## Reference Implementation

PublicDataProof Demo

- A standard reference implementation

DMC public data inscription 

- Based on public data storage certification, a complete economic model and gameplay has been designed on ETH network and BTC inscription network

Learn more background and existing attempts   

- DMC Main Chain 
- CYFS 

## Security Considerations

This storage proof revolves around public data. In demonstrating storage proofs, it often involves sending 1KB segments of the data to the public network. Therefore, please do not use the storage proof design presented in this paper for private data.

The design of MixHash can support storage proofs for private files, but this requires some adjustments in the processing of the original data and the construction of the storage proof. A detailed discussion on the design of storage proofs for private files is beyond the scope of this paper. In fact, some of the projects mentioned in the Reference Implementation section use both public data storage proofs and private data storage proofs.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 27 Dec 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7585</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7585</guid>
      </item>
    
      <item>
        <title>Interest Rate Swaps</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/interest-rate-swaps/17777</comments>
        
        <description>## Abstract

This proposal introduces a standardized framework for on-chain interest rate swaps. The proposed standard aims to facilitate the seamless exchange of fixed and floating interest rate cash flows between parties, providing a foundation for decentralized finance (DeFi) applications. 

## Motivation

Interest Rate Swapping (IRS) denotes a derivative contract wherein two parties mutually consent to exchange a series of forthcoming interest payments based on a specified notional amount. This financial instrument serves as a strategic tool for hedging against interest rate fluctuations. The mechanism entails the utilization of a benchmark index to facilitate the exchange between a variable interest rate and a fixed rate. Despite its widespread use, there is currently an absence of a standardized framework that enables the representation of IRS contracts on blockchain platforms.

This proposal addresses this gap by establishing a consistent and transparent methodology for representing IRS contracts within the blockchain environment. By doing so, it would enhance the interoperability, security, and efficiency of interest rate swap transactions on distributed ledger technology.

## Specification

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

### Example Flow

![alt text](../assets/eip-7586/irs.jpeg &quot;IRS diagram&quot;)

Every contract compliant with this ERC MUST implement the following interface. The contract MUST inherit from [ERC-20](/EIPs/EIPS/eip-20) to tokenize the swap cash flows.

```solidity
pragma solidity ^0.8.0;

/**
* @title ERC-7586 Interest Rate Swaps
*/
interface IERC7586 /** is ERC20, ERC165 */ {
    // events
    /**
    * @notice MUST be emitted when interest rates are swapped
    * @param _amount the interest difference to be transferred
    * @param _account the recipient account to send the interest difference to. MUST be either the `payer` or the `receiver`
    */
    event Swap(uint256 _amount, address _account);

    /**
    * @notice MUST be emitted when the swap contract is terminated
    * @param _payer the swap payer
    * @param _receiver the swap receiver
    */
    event TerminateSwap(address indexed _payer, address indexed _receiver);

    // functions
    /**
    *  @notice Returns the IRS `payer` account address. The party who agreed to pay fixed interest
    */
    function fixedRatePayer() external view returns(address);

    /**
    *  @notice Returns the IRS `receiver` account address. The party who agreed to pay floating interest
    */
    function floatingRatePayer() external view returns(address);

    /**
    * @notice Returns the number of decimals the swap rate and spread use - e.g. `4` means to divide the rates by `10000`
    *         To express the interest rates in basis points unit, the decimal MUST be equal to `2`. This means rates MUST be divided by `100`
    *         1 basis point = 0.01% = 0.0001
    *         ex: if interest rate = 2.5%, then swapRate() =&gt; 250 `basis points`
    */
    function ratesDecimals() external view returns(uint8);

    /**
    *  @notice Returns the fixed interest rate. All rates MUST be multiplied by 10^(ratesDecimals)
    */
    function swapRate() external view returns(uint256);

    /**
    *  @notice Returns the floating rate spread, i.e. the fixed part of the floating interest rate. All rates MUST be multiplied by 10^(ratesDecimals)
    *          floatingRate = benchmark + spread
    */
    function spread() external view returns(uint256);

    /**
    * @notice Returns the day count basis
    *         For example, 0 can denote actual/actual, 1 can denote actual/360, and so on
    */
    function dayCountBasis() external view returns(uint8);

    /**
    *  @notice Returns the contract address of the currency for which the notional amount is denominated (Example: USDC contract address).
    *          Returns the zero address if the notional is expressed in FIAT currency like USD
    */
    function notionalCurrency() external view returns(address);

    /**
    * @notice Returns an array of acceptable contract address of the assets to be transferred when swapping IRS
    *         The two counterparties may wish to get the payment in different currencies.
    *         Ex: if the payer wants to receive the payment in USDC and the receiver in DAI, then the function should return [USDC, DAI] or [DAI, USDC]
    */
    function paymentAssets() external view returns(address[] memory);

    /**
    *  @notice Returns the notional amount in unit of asset to be transferred when swapping IRS. This amount serves as the basis for calculating the interest payments, and may not be exchanged
    *          Example: If the two parties aggreed to swap interest rates in USDC, then the notional amount may be equal to 1,000,000 USDC 
    */
    function notionalAmount() external view returns(uint256);

    /**
    *  @notice Returns the number of times payments must be realized in 1 year
    */
    function paymentFrequency() external view returns(uint256);

    /**
    *  @notice Returns an array of specific dates on which the fix interest payments are exchanged. Each date MUST be a Unix timestamp like the one returned by block.timestamp
    *          The length of the array returned by this function MUST equal the total number of swaps that should be realized
    *
    *  OPTIONAL
    */
    function fixPaymentDates() external view returns(uint256[] memory);

    /**
    *  @notice Returns an array of specific dates on which the floating interest payments are exchanged. Each date MUST be a Unix timestamp like the one returned by block.timestamp
    *          The length of the array returned by this function MUST equal the total number of swaps that should be realized
    *
    *  OPTIONAL
    */
    function floatingPaymentDates() external view returns(uint256[] memory);

    /**
    *  @notice Returns the starting date of the swap contract. This is a Unix Timestamp like the one returned by block.timestamp
    */
    function startingDate() external view returns(uint256);

    /**
    *  @notice Returns the maturity date of the swap contract. This is a Unix Timestamp like the one returned by block.timestamp
    */
    function maturityDate() external view returns(uint256);

    /**
    *  @notice Returns the benchmark (the reference rate). All rates MUST be multiplied by 10^(ratesDecimals)
    *          Example: value of one the following rates: CF BIRC, EURIBOR, HIBOR, SHIBOR, SOFR, SONIA, TONAR, etc.
    *                   Or set manually
    */
    function benchmark() external view returns(uint256);

    /**
    *  @notice Returns the oracle contract address for acceptable reference rates (benchmark), or the zero address when the two parties agreed to set the benchmark manually.
    *          This contract SHOULD be used to fetch real time benchmark rate
    *          Example: Contract address for `CF BIRC`
    *
    *  OPTIONAL. The two parties MAY agree to set the benchmark manually
    */
    function oracleContractsForBenchmark() external view returns(address);

    /**
    *  @notice Makes swap calculation and transfers the payment to counterparties
    */
    function swap() external returns(bool);

    /**
    *  @notice Terminates the swap contract before its maturity date. MUST be called by either the `payer`or the `receiver`.
    */
    function terminateSwap() external;
}
```
### Tokenization of Swap Cash Flows

The interest payments associated with the IRS MUST be tokenized by issuing digital [ERC-20](./eip-20) tokens to the respective parties according to the terms of the swap. Each token SHOULD represent a specific interest payment. Every time a swap happens (the `swap` function is called), one token MUST be burned from each party.

## Rationale

This standard allows parties involved in the IRS contract to define essential parameters such as notional amount, interest rates, payment frequency, and payment dates. This flexibility accommodates a diverse range of financial agreements, catering to the unique needs of different participants.

To accommodate a wide array of use cases, the standard introduces optional features such as payment dates and manual benchmark setting. This allows parties to tailor the contract to specific requirements, while maintaining a core set of functions for essential functionality.

To ensure real-time and accurate benchmark rates, the standard integrates with oracles. Parties have the option to use oracles for fetching benchmark rates, enhancing the reliability and accuracy of interest rate calculations.

## Backwards Compatibility

This standard is backward compatible with ERC-20.

## Reference Implementation

The complete reference implementation can be found [here](/EIPs/assets/eip-7586/ERC7586.sol).

This reference implementation serves as a foundation for the implementation of more advanced types of swaps.

## Security Considerations

Security considerations of various types must be thoroughly evaluated

* Interest Rate Risk: This pertains to the potential impact of fluctuations in interest rates.
* Credit Risk: There exists the possibility that one or both parties may default on their respective responsibilities.
* ERC-20 Risks: All security aspects outlined in the ERC-20 standard must be taken into account.

Both parties must acknowledge their awareness of these security risks before proceeding with the implementation of the standard.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 31 Dec 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7586</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7586</guid>
      </item>
    
      <item>
        <title>Reserve Precompile Address Range for RIPs</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-75xx-reserve-precompile-address-range-for-rips-l2s/17828</comments>
        
        <description>## Abstract

This EIP reserves precompile ranges to ensure there are no conflicts with those used by the Rollup Improvement Proposal (RIP) process.

## Motivation

As L2s begin to deploy RIPs, it is necessary to reserve an address range for use by the RIP process so as to ensure there are no conflicts between precompile addresses used by RIPs and EIPs.

## Specification

The address range between `0x0000000000000000000000000000000000000100` and `0x00000000000000000000000000000000000001ff` is reserved for use by the RIP process.

## Rationale

By reserving an address range for RIPs, it allows the RIP process to maintain its own registry of precompiles that are not (necessarily) deployed on L1 mainnet, the EIP process is freed from having to maintain a registry of RIP precompiles while still having 255 addresses for its own use.

## Backwards Compatibility

No backward compatibility issues found.

## Security Considerations

Nil.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 21 Dec 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7587</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7587</guid>
      </item>
    
      <item>
        <title>Blob Transactions Metadata JSON Schema</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc7588-attaching-metadata-to-blobs-carried-by-blob-transactions/17873</comments>
        
        <description>## Abstract

This EIP introduces a standard for attaching metadata to blobs carried by blob transactions, as outlined in [EIP-4844](/EIPs/EIPS/eip-4844). The metadata is represented as a JSON object adhering to a predefined schema, and its string representation is placed in the data field of the blob transaction.

## Motivation

[EIP-4844](/EIPs/EIPS/eip-4844) defines a new type of transaction known as a “blob transaction.” These transactions contain a list of blobs along with their KZG commitments and proofs. Blob transactions serve as a mechanism for rollups to post their layer 2 transaction data to Ethereum layer 1.

While rollups typically manage their own posted blob transactions, third-party solutions (such as Portal Network and blobscan) may also index all blobs ever posted to Ethereum, and provide querying services for blobs. By attaching metadata to blobs, such as information about the originator, a description, or content type, we can significantly enhance the visibility and auditability of these data structures.

Furthermore, decentralized storage applications may utilize blob transactions to post user data to Ethereum, sync and store the blobs off-chain for future retrieval. The inclusion of metadata opens up possibilities for novel applications, including inscriptions and other creative use cases.


## Specification

### Metadata JSON Schema

The metadata is represented as a JSON object adhering to the following JSON Schema:

```json
{
    &quot;title&quot;: &quot;Blobs Metadata&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;originator&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Identifies the originator of the carried blobs&quot;
        },
        &quot;description&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Describes the contents of the blobs&quot;
        },
        &quot;content_type&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Describes the MIME type of the blobs. The MIME type should be defined in RFC 2046 (https://www.rfc-editor.org/rfc/rfc2046)&quot;
        },
        &quot;extras&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Dynamic extra information related to the blobs&quot;
        },
        &quot;blobs&quot;: {
            &quot;type&quot;: &quot;array&quot;,
            &quot;description&quot;: &quot;Metadata of the i&apos;th blob. This is optional and overlays the upper level properties if provided&quot;,
            &quot;items&quot;: {
                &quot;description&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;Describes the content of the i&apos;th blob&quot;
                },
                &quot;content_type&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;Describes the MIME type of the i&apos;th blob. The MIME type should be defined in RFC 2046 (https://www.rfc-editor.org/rfc/rfc2046)&quot;
                },
                &quot;extras&quot;: {
                    &quot;type&quot;: &quot;string&quot;,
                    &quot;description&quot;: &quot;Dynamic extra information related to the i&apos;th blob&quot;
                },
            }
        }
    }
}
```

For example, suppose Vitalik wants to send a blob transaction carrying two blobs explaining “data availability sampling.” He could include a paragraph of textual explanation in the first blob and an illustration image in the second blob. The corresponding metadata JSON object would look like this:

```json
{
    &quot;originator&quot;: &quot;Vitalik Buterin&quot;,
    &quot;description&quot;: &quot;An illustration of data availability sampling&quot;,
    &quot;blobs&quot;: [
      {
        &quot;content_type&quot;: &quot;text/plain&quot;,
        &quot;description&quot;: &quot;This blob contains a description text of the illustration.&quot;
      },
      {
        &quot;content_type&quot;: &quot;image/png&quot;,
        &quot;description&quot;: &quot;This blob contains the illustration image data in base64 format. It&apos;s a RFC 2397 (https://www.rfc-editor.org/rfc/rfc2397) data URL.&quot;
      },
    ]
  }
```

The complete blob transaction would include this metadata in the data field, along with other relevant fields:

```json
{
  &quot;blobVersionedHashes&quot;: [&quot;0x...&quot;, &quot;0x...&quot;],
  &quot;chainId&quot;: 11155111, // Supposing the blob transaction is posted to Sepolia
  &quot;type&quot;: &quot;eip4844&quot;,
  &quot;to&quot;: &quot;0x0000000000000000000000000000000000000000&quot;,
  &quot;gas&quot;: 28236,
  &quot;data&quot;: &quot;0x..&quot;, // String representation of the above metadata JSON object
  &quot;nonce&quot;: 18,
  &quot;maxFeePerBlobGas&quot;: 1073677089,
  &quot;maxFeePerGas&quot;: 1213388073,
  &quot;maxPriorityFeePerGas&quot;: 1165808679,
  &quot;sidecars&quot;: [
    { &quot;blob&quot;: &quot;0x...&quot;, &quot;commitment&quot;: &quot;0x...&quot;, &quot;proof&quot;: &quot;0x...&quot; },
    { &quot;blob&quot;: &quot;0x...&quot;, &quot;commitment&quot;: &quot;0x...&quot;, &quot;proof&quot;: &quot;0x...&quot; }
  ]
}
```

### Blob Transaction Envelope

The blob transaction&apos;s calldata (i.e., the data field) should be set to the string representation of the metadata JSON object, encoded in UTF-8.

## Rationale

In the Ethereum ecosystem, various types of transactions exist, each serving different purposes. The usage of the data field within these transactions varies:

- **Regular Funds Transfer Transactions**:
In these transactions, the data field is typically not used, and users may optionally include arbitrary data.
- **Smart Contract Deployment Transactions**:
For deploying smart contracts. The data field holds the contract bytecode and any encoded arguments required by the constructor.
- **Smart Contract Function Call Transactions**:
When invoking smart contract functions, the data field contains the function call data, including the function signature and any necessary parameters.

Blob transactions are specifically designed for posting blobs, and normally, the data field remains unused. This EIP proposes a novel approach: utilizing the data field to attach metadata to the carried blobs. By doing so, we can enhance the auditability and usability of blob transactions.

However, it’s essential to note that there are scenarios where blob transactions may also need to call smart contract functions. Consider a decentralized storage application that employs a smart contract to track blob versioned hashes and metadata like MIME types. In such cases, users could submit a blob transaction containing blobs while simultaneously using the data field to invoke smart contract functions to store versioned hashes and MIME types of those blobs. It’s important to recognize that this EIP does not cover such specific use cases.


# Backwards Compatibility

This EIP is backward compatible with [EIP-4844](/EIPs/EIPS/eip-4844), as it does not modify the structure or functionality of blob transactions, but only adds an optional metadata field to them.

## Security Considerations

This EIP does not introduce any new security risks or vulnerabilities, as the metadata is only an informational field that does not affect the execution or validity of blob transactions. However, users and applications should be aware of the following potential issues:

- The metadata is not verified or enforced by the consensus layer, and therefore it may not be accurate or trustworthy. Users and applications should not rely on the metadata for critical or sensitive operations, and should always verify the contents and sources of the blobs themselves.

- The metadata may contain malicious or harmful data, such as spam, phishing, malware, etc. Users and applications should not blindly trust or execute the metadata, and should always scan and sanitize the metadata before using it.

- The metadata may increase the gas cost of blob transactions, as more data is included in the data field. Users and applications should balance the benefits and costs of using the metadata, and should optimize the size and format of the metadata to reduce the gas cost.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7588</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7588</guid>
      </item>
    
      <item>
        <title>Semi-Fungible Token Roles</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7589-semi-fungible-token-roles/17967</comments>
        
        <description>## Abstract

This standard introduces role management for SFTs (Semi-Fungible Tokens). Each role assignment is granted to a single
user (grantee) and expires automatically. Roles are defined as `bytes32` and feature a custom `_data` field of
arbitrary size to allow customization.

## Motivation

[ERC-1155](/EIPs/EIPS/eip-1155) has significantly contributed to the tokenization capabilities of Ethereum by enabling
developers to create fungible and non-fungible tokens with a single contract. While [ERC-1155](/EIPs/EIPS/eip-1155) excels at
tracking ownership, it focuses solely on token balances, overlooking the nuanced aspects of how these tokens can be
utilized.

An essential aspect of token utility is access control, which determines who has permission to spend or use these
tokens. In some cases, the owner has complete control over its balance. Nevertheless, in many others, the utility can be
delegated (or granted) to other users, allowing for more complex use cases to be implemented.

One example is in gaming, in-game assets can be issued with a single [ERC-1155](/EIPs/EIPS/eip-1155) contract and rented out
via a secure role management interface.

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;,
&quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119 and RFC 8174.

Compliant contracts MUST implement the following interface:

```solidity
/// @title ERC-7589 Semi-Fungible Token Roles
/// @dev See https://eips.ethereum.org/EIPS/eip-7589
/// Note: the ERC-165 identifier for this interface is 0xc4c8a71d.
interface IERC7589 /* is IERC165 */ {

    /** Events **/

    /// @notice Emitted when tokens are committed (deposited or frozen).
    /// @param _grantor The owner of the SFTs.
    /// @param _commitmentId The identifier of the commitment created.
    /// @param _tokenAddress The token address.
    /// @param _tokenId The token identifier.
    /// @param _tokenAmount The token amount.
    event TokensCommitted(
        address indexed _grantor,
        uint256 indexed _commitmentId,
        address indexed _tokenAddress,
        uint256 _tokenId,
        uint256 _tokenAmount
    );

    /// @notice Emitted when a role is granted.
    /// @param _commitmentId The commitment identifier.
    /// @param _role The role identifier.
    /// @param _grantee The recipient the role.
    /// @param _expirationDate The expiration date of the role.
    /// @param _revocable Whether the role is revocable or not.
    /// @param _data Any additional data about the role.
    event RoleGranted(
        uint256 indexed _commitmentId,
        bytes32 indexed _role,
        address indexed _grantee,
        uint64 _expirationDate,
        bool _revocable,
        bytes _data
    );

    /// @notice Emitted when a role is revoked.
    /// @param _commitmentId The commitment identifier.
    /// @param _role The role identifier.
    /// @param _grantee The recipient of the role revocation.
    event RoleRevoked(uint256 indexed _commitmentId, bytes32 indexed _role, address indexed _grantee);

    /// @notice Emitted when a user releases tokens from a commitment.
    /// @param _commitmentId The commitment identifier.
    event TokensReleased(uint256 indexed _commitmentId);

    /// @notice Emitted when a user is approved to manage roles on behalf of another user.
    /// @param _tokenAddress The token address.
    /// @param _operator The user approved to grant and revoke roles.
    /// @param _isApproved The approval status.
    event RoleApprovalForAll(address indexed _tokenAddress, address indexed _operator, bool _isApproved);

    /** External Functions **/

    /// @notice Commits tokens (deposits on a contract or freezes balance).
    /// @param _grantor The owner of the SFTs.
    /// @param _tokenAddress The token address.
    /// @param _tokenId The token identifier.
    /// @param _tokenAmount The token amount.
    /// @return commitmentId_ The unique identifier of the commitment created.
    function commitTokens(
        address _grantor,
        address _tokenAddress,
        uint256 _tokenId,
        uint256 _tokenAmount
    ) external returns (uint256 commitmentId_);

    /// @notice Grants a role to `_grantee`.
    /// @param _commitmentId The identifier of the commitment.
    /// @param _role The role identifier.
    /// @param _grantee The recipient the role.
    /// @param _expirationDate The expiration date of the role.
    /// @param _revocable Whether the role is revocable or not.
    /// @param _data Any additional data about the role.
    function grantRole(
        uint256 _commitmentId,
        bytes32 _role,
        address _grantee,
        uint64 _expirationDate,
        bool _revocable,
        bytes calldata _data
    ) external;

    /// @notice Revokes a role.
    /// @param _commitmentId The commitment identifier.
    /// @param _role The role identifier.
    /// @param _grantee The recipient of the role revocation.
    function revokeRole(uint256 _commitmentId, bytes32 _role, address _grantee) external;

    /// @notice Releases tokens back to grantor.
    /// @param _commitmentId The commitment identifier.
    function releaseTokens(uint256 _commitmentId) external;

    /// @notice Approves operator to grant and revoke roles on behalf of another user.
    /// @param _tokenAddress The token address.
    /// @param _operator The user approved to grant and revoke roles.
    /// @param _approved The approval status.
    function setRoleApprovalForAll(address _tokenAddress, address _operator, bool _approved) external;

    /** View Functions **/

    /// @notice Returns the owner of the commitment (grantor).
    /// @param _commitmentId The commitment identifier.
    /// @return grantor_ The commitment owner.
    function grantorOf(uint256 _commitmentId) external view returns (address grantor_);

    /// @notice Returns the address of the token committed.
    /// @param _commitmentId The commitment identifier.
    /// @return tokenAddress_ The token address.
    function tokenAddressOf(uint256 _commitmentId) external view returns (address tokenAddress_);

    /// @notice Returns the identifier of the token committed.
    /// @param _commitmentId The commitment identifier.
    /// @return tokenId_ The token identifier.
    function tokenIdOf(uint256 _commitmentId) external view returns (uint256 tokenId_);

    /// @notice Returns the amount of tokens committed.
    /// @param _commitmentId The commitment identifier.
    /// @return tokenAmount_ The token amount.
    function tokenAmountOf(uint256 _commitmentId) external view returns (uint256 tokenAmount_);

    /// @notice Returns the custom data of a role assignment.
    /// @param _commitmentId The commitment identifier.
    /// @param _role The role identifier.
    /// @param _grantee The recipient the role.
    /// @return data_ The custom data.
    function roleData(
        uint256 _commitmentId,
        bytes32 _role,
        address _grantee
    ) external view returns (bytes memory data_);

    /// @notice Returns the expiration date of a role assignment.
    /// @param _commitmentId The commitment identifier.
    /// @param _role The role identifier.
    /// @param _grantee The recipient the role.
    /// @return expirationDate_ The expiration date.
    function roleExpirationDate(
        uint256 _commitmentId,
        bytes32 _role,
        address _grantee
    ) external view returns (uint64 expirationDate_);

    /// @notice Returns the expiration date of a role assignment.
    /// @param _commitmentId The commitment identifier.
    /// @param _role The role identifier.
    /// @param _grantee The recipient the role.
    /// @return revocable_ Whether the role is revocable or not.
    function isRoleRevocable(
        uint256 _commitmentId,
        bytes32 _role,
        address _grantee
    ) external view returns (bool revocable_);

    /// @notice Checks if the grantor approved the operator for all SFTs.
    /// @param _tokenAddress The token address.
    /// @param _grantor The user that approved the operator.
    /// @param _operator The user that can grant and revoke roles.
    /// @return isApproved_ Whether the operator is approved or not.
    function isRoleApprovedForAll(
        address _tokenAddress,
        address _grantor,
        address _operator
    ) external view returns (bool isApproved_);
}
```

### Single Transaction Extension

Granting roles is a two-step process that requires two transactions. The first is to commit tokens, and the second is to
grant the role. This extension allows users to commit tokens and grant a role in one transaction, which is desirable for
some use cases.

```solidity
/// @title ERC-7589 Semi-Fungible Token Roles, optional single transaction extension
/// @dev See https://eips.ethereum.org/EIPS/eip-7589
/// Note: the ERC-165 identifier for this interface is 0x5c3d7d74.
interface ICommitTokensAndGrantRoleExtension /* is IERC7589 */ {
    /// @notice Commits tokens and grant role in a single transaction.
    /// @param _grantor The owner of the SFTs.
    /// @param _tokenAddress The token address.
    /// @param _tokenId The token identifier.
    /// @param _tokenAmount The token amount.
    /// @param _role The role identifier.
    /// @param _grantee The recipient the role.
    /// @param _expirationDate The expiration date of the role.
    /// @param _revocable Whether the role is revocable or not.
    /// @param _data Any additional data about the role.
    /// @return commitmentId_ The identifier of the commitment created.
    function commitTokensAndGrantRole(
        address _grantor,
        address _tokenAddress,
        uint256 _tokenId,
        uint256 _tokenAmount,
        bytes32 _role,
        address _grantee,
        uint64 _expirationDate,
        bool _revocable,
        bytes calldata _data
    ) external returns (uint256 commitmentId_);
}
```

### Role Balance Extension

The core interface allows for querying a token commitment&apos;s balance but not for a specific user&apos;s balance. To determine
the total amount of tokens granted to a user, the implementation needs to sum up all the roles granted to that user
while filtering out any expired roles.

This function was included in an optional extension because it&apos;s not always necessary and will likely make the
implementation much more complex (increasing smart contract risk).

```solidity
/// @title ERC-7589 Semi-Fungible Token Roles, optional role balance extension
/// @dev See https://eips.ethereum.org/EIPS/eip-7589
/// Note: the ERC-165 identifier for this interface is 0x2f35b73f.
interface IRoleBalanceOfExtension /* is IERC7589 */ {
    /// @notice Returns the sum of all tokenAmounts granted to the grantee for the given role.
    /// @param _role The role identifier.
    /// @param _tokenAddress The token address.
    /// @param _tokenId The token identifier.
    /// @param _grantee The user for which the balance is returned.
    /// @return balance_ The balance of the grantee for the given role.
    function roleBalanceOf(
        bytes32 _role,
        address _tokenAddress,
        uint256 _tokenId,
        address _grantee
    ) external returns (uint256 balance_);
}
```

### Metadata Extension

The Roles Metadata extension extends the traditional JSON-based metadata schema of SFTs. Therefore, DApps supporting
this feature MUST also implement the metadata extension of [ERC-1155](/EIPs/EIPS/eip-1155). This JSON extension is 
**optional** and allows developers to provide additional information on roles.

Updated JSON Schema:
```json
{

  /** Existing ERC-1155 Metadata **/

  &quot;title&quot;: &quot;Token Metadata&quot;,
  &quot;type&quot;: &quot;object&quot;,
  &quot;properties&quot;: {
    &quot;name&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Identifies the asset to which this token represents&quot;
    },
    &quot;decimals&quot;: {
      &quot;type&quot;: &quot;integer&quot;,
      &quot;description&quot;: &quot;The number of decimal places that the token amount should display - e.g. 18, means to divide the token amount by 1000000000000000000 to get its user representation.&quot;
    },
    &quot;description&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Describes the asset to which this token represents&quot;
    },
    &quot;image&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;A URI pointing to a resource with mime type image/* representing the asset to which this token represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive.&quot;
    },
    &quot;properties&quot;: {
      &quot;type&quot;: &quot;object&quot;,
      &quot;description&quot;: &quot;Arbitrary properties. Values may be strings, numbers, object or arrays.&quot;
    }
  },

  /** Additional fields for ERC-7589 **/

  &quot;roles&quot;: [{
    &quot;id&quot;: {
      &quot;type&quot;: &quot;bytes32&quot;,
      &quot;description&quot;: &quot;Identifies the role&quot;
    },
    &quot;name&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Human-readable name of the role&quot;
    },
    &quot;description&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Describes the role&quot;
    },
    &quot;inputs&quot;: [{
      &quot;name&quot;: {
        &quot;type&quot;: &quot;string&quot;,
        &quot;description&quot;: &quot;Human-readable name of the argument&quot;
      },
      &quot;type&quot;: {
        &quot;type&quot;: &quot;string&quot;,
        &quot;description&quot;: &quot;Solidity type, e.g., uint256 or address&quot;
      }
    }]
  }]
}
```

The following code snipped is an example of the additional fields described above:

```json
{

  /** Existing ERC-1155 Metadata **/

  &quot;name&quot;: &quot;Asset Name&quot;,
  &quot;description&quot;: &quot;Lorem ipsum...&quot;,
  &quot;image&quot;: &quot;https:\/\/s3.amazonaws.com\/your-bucket\/images\/{id}.png&quot;,
  &quot;properties&quot;: {
    &quot;simple_property&quot;: &quot;example value&quot;,
    &quot;rich_property&quot;: {
      &quot;name&quot;: &quot;Name&quot;,
      &quot;value&quot;: &quot;123&quot;,
      &quot;display_value&quot;: &quot;123 Example Value&quot;,
      &quot;class&quot;: &quot;emphasis&quot;,
      &quot;css&quot;: {
        &quot;color&quot;: &quot;#ffffff&quot;,
        &quot;font-weight&quot;: &quot;bold&quot;,
        &quot;text-decoration&quot;: &quot;underline&quot;
      }
    },
    &quot;array_property&quot;: {
      &quot;name&quot;: &quot;Name&quot;, 
      &quot;value&quot;: [1,2,3,4],
      &quot;class&quot;: &quot;emphasis&quot;
    }
  },

  /** Additional fields for ERC-7589 **/

  &quot;roles&quot;: [
    {
      // keccak256(&quot;Player(uint256)&quot;)
      &quot;id&quot;: &quot;0x70d2dab8c6ff873dc0b941220825d9271fdad6fdb936f6567ffde77d05491cef&quot;,
      &quot;name&quot;: &quot;Player&quot;,
      &quot;description&quot;: &quot;The user allowed to use this item in-game.&quot;,
      &quot;inputs&quot;: [
        {
          &quot;name&quot;: &quot;ProfitShare&quot;,
          &quot;type&quot;: &quot;uint256&quot;
        }
      ]
    }
  ]
}
```

The properties of the `roles` array are SUGGESTED, and developers should add any other relevant information for their
use case (e.g., an image representing the role).

It&apos;s also important to highlight the significance of the `inputs` property. This field describes the parameters that
should be encoded and passed to the `grantRole` function, and can include the properties `type` and `components` to
represent the format of the data. It&apos;s RECOMMENDED to use the properties `type` and `components` as defined on the
Solidity ABI Specification.

### Caveats

* Compliant contracts MUST implement the `IERC7589` interface.
* Every role is represented by a `bytes32` identifier. It&apos;s RECOMMENDED to use the keccak256 hash of the role name and
  its arguments (if any) as the identifier. E.g., `keccak256(&quot;Player(uint256)&quot;)`.
* The `commitTokens` function MUST revert if the `_tokenAmount` is zero or the `msg.sender` was not approved by the
  `_grantor`. It MAY be implemented as public or external.
* The `grantRole` function MUST revert if the `_expirationDate` is in the past or if the `msg.sender` is not approved to
  grant roles on behalf of the grantor. It MAY be implemented as public or external, and it is RECOMMENDED using 
  `type(uint64).max` for a permanent roles.
* The `revokeRole` function SHOULD always allow the grantee to revoke roles and MAY be implemented as public or 
  external, and MUST revert if:
  * The role assignment is not found (no role was granted).
  * The `msg.sender` was not approved by the grantor or the grantee.
  * The `msg.sender` is the grantor or was approved by the grantor, but the role is not revocable or expired.
* The `releaseTokens` function MAY be implemented as public or external and MUST revert if:
  * The commitment is not found (no tokens were committed).
  * The `msg.sender` is not and was not approved by the grantor.
  * The commitment has at least one non-revocable role that didn&apos;t expire.
* The `setRoleApprovalForAll` function MAY be implemented as public or external.
* The `grantorOf` function MAY be implemented as pure or view and MUST return the owner of the committed tokens.
* The `tokenAddressOf` function MAY be implemented as pure or view and MUST return the address of the committed tokens.
* The `tokenIdOf` function MAY be implemented as pure or view and MUST return the identifier of the committed tokens.
* The `tokenAmountOf` function MAY be implemented as pure or view and MUST return the token amount committed.
* The `roleData` function MAY be implemented as pure or view and MUST return the custom data of the role assignment.
* The `roleExpirationDate` function MAY be implemented as pure or view and MUST return the expiration date of the role 
  assignment.
* The `isRoleRevocable` function MAY be implemented as pure or view and MUST return whether the grantor can end the role
  assignment before its expiration date.
* The `isRoleApprovedForAll` function MAY be implemented as pure or view and MUST return whether the `_operator` is
  allowed to grant and revoke roles on behalf of the `_grantor`.

&gt; Please note that &quot;approval&quot; refers to allowing users to commit tokens and grant/revoke roles on one&apos;s behalf. An
  approved user either received the role approval or is the target user. Role approvals are not to be confused with
  [ERC-1155](/EIPs/EIPS/eip-1155) approvals. More information can be found in the [Role Approvals](#role-approvals) section.

## Rationale

The concept of &quot;token commitments&quot; as an abstraction serves as a powerful tool for users looking to delegate the control
of their SFTs. A token commitment represents either a frozen balance or tokens deposited into a contract, offering a
standardized and secure way for SFT owners to delegate the use of their assets. Through [ERC-7589](/EIPs/EIPS/eip-7589), users
gain a versatile mechanism to abstract the complexities of secure delegation, enhancing the utility and interoperability
of semi-fungible tokens.

[ERC-7589](/EIPs/EIPS/eip-7589) IS NOT an extension of [ERC-1155](/EIPs/EIPS/eip-1155). The main reason behind this decision is to
keep the standard agnostic of any implementation. This approach enables the standard to be implemented externally or on
the same contract as the SFT and allows dApps to use roles with immutable SFTs.

### Role Approvals

Like [ERC-1155](/EIPs/EIPS/eip-1155), [ERC-7589](/EIPs/EIPS/eip-7589) allows users to approve operators to grant and revoke roles on
their behalf. This feature is crucial for interoperability, as it enables third-party applications to manage user roles
without custody-level approvals. Role approvals are part of the core interface, and compliant contracts must implement
the `setRoleApprovalForAll` and `isRoleApprovedForAll` functions.

### Automatic Expiration

Automatic expiration is implemented to save users gas. To end a role assignment, instead of requiring users always to
call `revokeRole`, applications should call the `roleExpirationDate` and compare it to the current timestamp to check if
the role is still valid.

In the context of [ERC-7589](/EIPs/EIPS/eip-7589), dates are represented as `uint64`. The maximum UNIX timestamp represented
by a `uint64` is about the year 584 billion, which should be enough to be considered &quot;permanent&quot;. For this reason, using
`type(uint64).max` in an assignment represents that it never expires.

### Revocable Roles

In certain scenarios, the grantor might need to revoke a role before its expiration. While in others, the grantee
requires assurance that the role can&apos;t be prematurely revoked (e.g. when the grantee pays tokens to utilize them). The
`_revocable` parameter was included in the `grantRole` function for this exact reason, and it specifies whether the
grantor can revoke the role prior to the expiration date. Regardless of the `_revocable` value, the grantee will always 
be able to revoke roles, allowing recipients to eliminate undesirable assignments.

### Custom Data

The `grantRole` function&apos;s `_data` parameter is critical for the standardization of this EIP. SFTs have different use
cases, and it&apos;s impractical to attempt to cover all of them on a solidity-level interface. Therefore, a generic
parameter of type `bytes` was incorporated, allowing users to pass any custom information when granting a role.

For example, it&apos;s common for web3 games to introduce a profit-share when delegating NFTs to players, which is
represented by a `uint256`. Using [ERC-7589](/EIPs/EIPS/eip-7589), one could simply encode the `uint256` as bytes and pass it
to the`grantRole` function. Data validation can happen on-chain or off-chain, and other contracts can query this
information using the `roleData` function.


## Backwards Compatibility

Many SFTs are deployed as immutable contracts, which imposes the following challenge: How can one enable role management
for SFTs that can&apos;t be modified? This proposal solves this problem by requiring the `tokenAddress` parameter
when committing tokens. This requirement ensures that dApps can either implement [ERC-7589](/EIPs/EIPS/eip-7589) inside the
SFT contract or use a standalone external contract as the authoritative source for the roles of immutable SFTs.

## Reference Implementation

See [`ERC7589.sol`](/EIPs/assets/eip-7589/ERC7589.sol).

## Security Considerations

Developers integrating with Semi-Fungible Token Roles should consider the points below on their implementations:
* Ensure proper access control is in place to prevent unauthorized role assignments or revocations. This is especially
  important in `commitTokens` and `releaseTokens`, as they might freeze or transfer balances.
* Consider potential attack vectors such as reentrancy and ensure appropriate safeguards are in place.
* Always check the expiration date before allowing users to utilize a role assignment.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 28 Dec 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7589</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7589</guid>
      </item>
    
      <item>
        <title>ERC-20 Holder Extension for NFTs</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/token-holder-extension-for-nfts/16260</comments>
        
        <description>## Abstract

This proposal suggests an extension to [ERC-721](/EIPs/EIPS/eip-721) to enable easy exchange of [ERC-20](/EIPs/EIPS/eip-20) tokens. By enhancing [ERC-721](/EIPs/EIPS/eip-721), it allows unique tokens to manage and trade [ERC-20](/EIPs/EIPS/eip-20) fungible tokens bundled in a single NFT. This is achieved by including methods to pull [ERC-20](/EIPs/EIPS/eip-20) tokens into the NFT contract to a specific NFT, and transferring them out by the owner of such NFT. A transfer out nonce is included to prevent front-running issues.

## Motivation

In the ever-evolving landscape of blockchain technology and decentralized ecosystems, interoperability between diverse token standards has become a paramount concern. By enhancing [ERC-721](/EIPs/EIPS/eip-721) functionality, this proposal empowers non-fungible tokens (NFTs) to engage in complex transactions, facilitating the exchange of fungible tokens, unique assets, and multi-class assets within a single protocol.

This ERC introduces new utilities in the following areas:
- Expanded use cases
- Facilitating composite transactions
- Market liquidity and value creation

### Expanded Use Cases

Enabling [ERC-721](/EIPs/EIPS/eip-721) tokens to handle various token types opens the door to a wide array of innovative use cases. From gaming and digital collectibles to decentralized finance (DeFi) and supply chain management, this extension enhances the potential of NFTs by allowing them to participate in complex, multi-token transactions.

### Facilitating Composite Transactions

With this extension, composite transactions involving both fungible and non-fungible assets become easier. This functionality is particularly valuable for applications requiring intricate transactions, such as gaming ecosystems where in-game assets may include a combination of fungible and unique tokens.

### Market Liquidity and Value Creation

By allowing [ERC-721](/EIPs/EIPS/eip-721) tokens to hold and trade different types of tokens, it enhances liquidity for markets in all types of tokens.

## Specification

```solidity

interface IERC7590 /*is IERC165, IERC721*/  {
    /**
     * @notice Used to notify listeners that the token received ERC-20 tokens.
     * @param erc20Contract The address of the ERC-20 smart contract
     * @param toTokenId The ID of the token receiving the ERC-20 tokens
     * @param from The address of the account from which the tokens are being transferred
     * @param amount The number of ERC-20 tokens received
     */
    event ReceivedERC20(
        address indexed erc20Contract,
        uint256 indexed toTokenId,
        address indexed from,
        uint256 amount
    );

    /**
     * @notice Used to notify the listeners that the ERC-20 tokens have been transferred.
     * @param erc20Contract The address of the ERC-20 smart contract
     * @param fromTokenId The ID of the token from which the ERC-20 tokens have been transferred
     * @param to The address receiving the ERC-20 tokens
     * @param amount The number of ERC-20 tokens transferred
     */
    event TransferredERC20(
        address indexed erc20Contract,
        uint256 indexed fromTokenId,
        address indexed to,
        uint256 amount
    );

    /**
     * @notice Used to retrieve the given token&apos;s specific ERC-20 balance
     * @param erc20Contract The address of the ERC-20 smart contract
     * @param tokenId The ID of the token being checked for ERC-20 balance
     * @return The amount of the specified ERC-20 tokens owned by a given token
     */
    function balanceOfERC20(
        address erc20Contract,
        uint256 tokenId
    ) external view returns (uint256);

    /**
     * @notice Transfer ERC-20 tokens from a specific token.
     * @dev The balance MUST be transferred from this smart contract.
     * @dev MUST increase the transfer-out-nonce for the tokenId
     * @dev MUST revert if the `msg.sender` is not the owner of the NFT or approved to manage it.
     * @param erc20Contract The address of the ERC-20 smart contract
     * @param tokenId The ID of the token to transfer the ERC-20 tokens from
     * @param amount The number of ERC-20 tokens to transfer
     * @param data Additional data with no specified format, to allow for custom logic
     */
    function transferHeldERC20FromToken(
        address erc20Contract,
        uint256 tokenId,
        address to,
        uint256 amount,
        bytes memory data
    ) external;

    /**
     * @notice Transfer ERC-20 tokens to a specific token.
     * @dev The ERC-20 smart contract must have approval for this contract to transfer the ERC-20 tokens.
     * @dev The balance MUST be transferred from the `msg.sender`.
     * @param erc20Contract The address of the ERC-20 smart contract
     * @param tokenId The ID of the token to transfer ERC-20 tokens to
     * @param amount The number of ERC-20 tokens to transfer
     * @param data Additional data with no specified format, to allow for custom logic
     */
    function transferERC20ToToken(
        address erc20Contract,
        uint256 tokenId,
        uint256 amount,
        bytes memory data
    ) external;

    /**
     * @notice Nonce increased every time an ERC20 token is transferred out of a token
     * @param tokenId The ID of the token to check the nonce for
     * @return The nonce of the token
     */
    function erc20TransferOutNonce(
        uint256 tokenId
    ) external view returns (uint256);
}
```


## Rationale

### Pull Mechanism

We propose using a pull mechanism, where the contract transfers the token to itself, instead of receiving it via &quot;safe transfer&quot; for 2 reasons:

1. Customizability with Hooks. By initiating the process this way, smart contract developers have the flexibility to execute specific actions before and after transferring the tokens.

2. Lack of transfer with callback: [ERC-20](/EIPs/EIPS/eip-20) tokens lack a standardized transfer with callback method, such as the &quot;safeTransfer&quot; on [ERC-721](/EIPs/EIPS/eip-721), which means there is no reliable way to notify the receiver of a successful transfer, nor to know which is the destination token is.

This has the disadvantage of requiring approval of the token to be transferred before actually transferring it into an NFT.

### Granular vs Generic

We considered 2 ways of presenting the proposal:
1. A granular approach where there is an independent interface for each type of held token.
2. A universal token holder which could also hold and transfer [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155).

An implementation of the granular version is slightly cheaper in gas, and if you&apos;re using just one or two types, it&apos;s smaller in contract size. The generic version is smaller and has single methods to send or receive, but it also adds some complexity by always requiring Id and amount on transfer methods. Id not being necessary for [ERC-20](/EIPs/EIPS/eip-20) and amount not being necessary for [ERC-721](/EIPs/EIPS/eip-721).

We also considered that due to the existence of safe transfer methods on both [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155), and the commonly used interfaces of `IERC721Receiver` and `IERC1155Receiver`, there is not much need to declare an additional interface to manage such tokens. However, this is not the case for [ERC-20](/EIPs/EIPS/eip-20), which does not include a method with a callback to notify the receiver of the transfer.

For the aforementioned reasons, we decided to go with a granular approach.


## Backwards Compatibility

No backward compatibility issues found.

## Test Cases

Tests are included in [`erc7590.ts`](/EIPs/assets/eip-7590/test/erc7590.ts).

To run them in terminal, you can use the following commands:

```
cd ../assets/eip-erc7590
npm install
npx hardhat test
```

## Reference Implementation

See [`ERC7590Mock.sol`](/EIPs/assets/eip-7590/contracts/ERC7590Mock.sol).

## Security Considerations

The same security considerations as with [ERC-721](/EIPs/EIPS/eip-721) apply: hidden logic may be present in any of the functions, including burn, add resource, accept resource, and more.

Caution is advised when dealing with non-audited contracts.

Implementations MUST use the message sender as from parameter when they are transferring tokens into an NFT. Otherwise, since the current contract needs approval, it could potentially pull the external tokens into a different NFT.

When transferring [ERC-20](/EIPs/EIPS/eip-20) tokens in or out of an NFT, it could be the case that the amount transferred is not the same as the amount requested. This could happen if the [ERC-20](/EIPs/EIPS/eip-20) contract has a fee on transfer. This could cause a bug on your Token Holder contract if you do not manage it properly. There are 2 ways to do it, both of which are valid:
1. Use the `IERC20` interface to check the balance of the contract before and after the transfer, and revert if the balance is not the expected one, hence not supporting tokens with fees on transfer.
2. Use the `IERC20` interface to check the balance of the contract before and after the transfer, and use the difference to calculate the amount of tokens that were actually transferred. 

To prevent a seller from front running the sale of an NFT holding [ERC-20](/EIPs/EIPS/eip-20) tokens to transfer out such tokens before a sale is executed, marketplaces MUST beware of the `erc20TransferOutNonce` and revert if it has changed since listed.

[ERC-20](/EIPs/EIPS/eip-20) tokens that are transferred directly to the NFT contract will be lost.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 05 Jan 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7590</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7590</guid>
      </item>
    
      <item>
        <title>BLS signed transactions</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7591-bls-signed-transactions/19911</comments>
        
        <description>## Abstract

This EIP introduces a new [EIP-2718](/EIPs/EIPS/eip-2718) transaction type that is signed with BLS signatures.

## Motivation

The BLS signature scheme allows for easy aggregation and verification of aggregated signatures.
If a substantial number of transactions on mainnet were BLS signed transactions, we can aggregate signatures in a block and batch-verify them.
This will reduce growth of the chain history.


## Specification

BLS_TX_TYPE = Bytes1(0x04)

### Transaction Type

The transaction type will have the following format: 

```
[chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to, value, data, access_list, sender, signature]
```

with `sender` being the BLS public key of an account with address `address = [0:20](keccak256(sender))`.

The signature value `signature` is calculated by constructing a BLS signature over the following digest:

`tx_hash = keccak256(BLS_TX_TYPE || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to, value, data, access_list, sender]))`.

### Header changes

The block header will be amended with the `aggregated_sig` field, containing an aggregated signature of all BLS transactions in the block.

The resulting RLP encoding of the header is therefore:

```
rlp([
    parent_hash,
    0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347, # ommers hash
    coinbase,
    state_root,
    txs_root,
    receipts_root,
    logs_bloom,
    0, # difficulty
    number,
    gas_limit,
    gas_used,
    timestamp,
    extradata,
    prev_randao,
    0x0000000000000000, # nonce
    base_fee_per_gas,
    withdrawals_root,
    blob_gas_used,
    excess_blob_gas,
    aggregated_sig,
])
```

### Block changes

The block building algorithm needs to be changed in order to built the aggregated signature of all BLS signed transactions in the block. 
All transactions in the block will be added without the signature field set. 

Blocks with transactions containing the `signature` field MUST be rejected.

On block verification, the `verifyAggregate` algorithm is used as follows:

```
valid = verifyAggregate(sender_1, ... sender_n, tx_hash_1, ... tx_hash_n, aggregated_sig)
```

## Rationale

Removing the ECDSA signature from a transaction saves 65 bytes. The BLS public key is 48 bytes, the aggregated signature is 96 bytes.
Thus we save `-96 + (65-48)* #transactions` bytes per block. With ~7000 blocks per day, 1.000.000 transactions per day, the average block contains roughly 150 transactions.

Thus we would save 2454 bytes or 2.4KB per block. This would equate to ~1.5% saving given an average block size of 160KB. 

In addition to the (admittedly meager) size savings for full nodes, the ability to add a new transaction type to utilize a different signature scheme does have some merit to it. This proposal shows that it would be possible to add for example a quantum safe signature scheme to ethereum.

## Backwards Compatibility

This EIP introduces backward incompatible changes to the block validation rule set on the execution layer and introduces a new transaction type and a new header field. Thus a hardfork is needed.

## Security Considerations

The messages signed via BLS are distinct (no hash collisions on the txhash), thus the aggregation is secure even without a proof-of-possession.
The public keys are not distinct which is not a problem in BLS.

We assume that keccak256 and ECDSA and BLS are working as intended. 
Suppose we have two addresses `address_1 = keccak256(pk_ecdsa)` and `address_2 = keccak256(pk_bls)` with `address_1 == address_2`.
We know that `pk_ecdsa` must be equal to `pk_bls` (follows from keccak256).
This would mean that we would either be able to find `x` with `g_bls^x = y` for a given `y` (violates the security of BLS)
or find `z` with `d_ecdsa^z = y` (violates the security of ECDSA).

Thus it would be impossible (with greater than negligible probability) to find two private keys, one in ECDSA and one in BLS that control the same account.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).


</description>
        <pubDate>Wed, 10 Jan 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7591</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7591</guid>
      </item>
    
      <item>
        <title>PeerDAS - Peer Data Availability Sampling</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7594-peerdas-peer-data-availability-sampling/18215</comments>
        
        <description>## Abstract

PeerDAS (Peer Data Availability Sampling) is a networking protocol that allows nodes to perform data availability sampling (DAS) to ensure that blob data has been made available while downloading only a subset of the data. PeerDAS utilizes gossip for distribution, discovery for finding peers of particular data custody, and peer requests for sampling.

## Motivation

DAS is a method of scaling data availability beyond the levels of [EIP-4844](/EIPs/EIPS/eip-4844) by not requiring all nodes to download all data while still ensuring that all of the data has been made available.

Providing additional data availability helps bring scale to Ethereum users in the context of layer 2 systems called &quot;roll-ups&quot; whose dominant bottleneck is layer 1 data availability.

## Specification

We extend the blobs introduced in EIP-4844 using a one-dimensional erasure coding extension. Each row consists of the blob data combined with its erasure code. It is subdivided into cells, which are the smallest units that can be authenticated with their respective blob&apos;s KZG commitments. Each column, associated with a specific gossip subnet, consists of the cells from all rows for a specific index. Each node is responsible for maintaining a deterministic set of column subnets and custodying their data as a function of their node ID.

Nodes find and maintain a diverse peer set and sample columns from their peers to perform DAS every slot.

A node can reconstruct the entire data matrix if it acquires at least 50% of all the columns. If a node has less than 50%, it can request the necessary columns from its peer nodes.

Additionally, a limit of 6 blobs per transaction is introduced. Clients MUST enforce this limit when validating blob transactions at submission time, when received from the network, and during block production and processing.

The detailed specifications are on [ethereum/consensus-specs](https://github.com/ethereum/consensus-specs/tree/9d377fd53d029536e57cfda1a4d2c700c59f86bf/specs/fulu/).

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

### Networking

This EIP introduces cell KZG proofs, which are used to prove that a KZG commitment opens to a cell at the given index. This allows downloading only specific cells from a blob, while still ensuring data integrity with respect to the corresponding KZG commitment, and is therefore a key component of data availability sampling. However, computing the cell proofs for a blob is an expensive operation, which a block producer would have to repeat for many blobs. Since proof verification is much cheaper than proof computation, and the proof size is negligible compared to cell size, we instead require blob transaction senders to compute the proofs themselves and include them in the EIP-4844 transaction pool wrapper for blob transactions.

To this end, during transaction gossip responses (`PooledTransactions`), the wrapper is modified to:

```
rlp([tx_payload_body, wrapper_version, blobs, commitments, cell_proofs])

cell_proofs = [cell_proof_0, cell_proof_1, ...]
```

The `tx_payload_body`, `blobs` and `commitments` are as in EIP-4844, while the `proofs` field is replaced by `cell_proofs`, and a `wrapper_version` is added. These are defined as follows:

- `wrapper_version` - one byte indicating which version of the wrapper is used. For the current version, it is set to **`1`**.
- `cell_proofs` - list of cell proofs for all `blobs`, including the proofs for the extension indices, for a total of `CELLS_PER_EXT_BLOB` proofs per blob (`CELLS_PER_EXT_BLOB` is the number of cells for an extended blob, defined [in the consensus specs](https://github.com/ethereum/consensus-specs/tree/9d377fd53d029536e57cfda1a4d2c700c59f86bf/specs/fulu/polynomial-commitments-sampling.md#cells))

Note that, while `cell_proofs` contain the proofs for all cells, including the extension cells, the blobs themselves are sent without being extended (`CELLS_PER_EXT_BLOB / 2` cells per blob). This is to avoid sending redundant data, which can quickly be computed by the receiving node.
In other words, `cell_proofs[i * CELLS_PER_EXT_BLOB + j]` is the proof for cell `j` of `compute_cells(blobs[i])`, where `compute_cells(blob)` outputs all cells of `blob`, including the extension cells.

The node MUST validate `tx_payload_body` and verify the wrapped data against it. To do so, ensure that:

- There are an equal number of `tx_payload_body.blob_versioned_hashes`, `blobs` and `commitments`.
- `cell_proofs` contains exactly `CELLS_PER_EXT_BLOB * len(blobs)` cell proofs
- The KZG `commitments` hash to the versioned hashes, i.e. `kzg_to_versioned_hash(commitments[i]) == tx_payload_body.blob_versioned_hashes[i]`
- The KZG `commitments` match the corresponding `blobs` and `cell_proofs`. This requires computing the extension cells for all `blobs` (e.g. via `compute_cells`), and verifying all `cell_proofs`. (Note: all cell proofs can be batch verified at once, e.g. via `verify_cell_kzg_proof_batch`)

## Rationale

### Why use DAS to scale the DA layer?

PeerDAS is a DAS scheme that requires nodes to only download a small constant fraction of the data to satisfy a local availability check. With the current parameters, this is 1/8 of the total data (i.e. blobs in a block), which can in the future be decreased to 1/16 or even 1/32 by reducing the size of samples (increasing the number of columns). In this way, PeerDAS allows for securely scaling the blob throughput of the network without compromising decentralization, i.e., without increasing node&apos;s bandwidth and storage requirements.

### What does peer sampling provide?

PeerDAS takes the set of peers of a node on the network as a primitive to build a DAS scheme around. A focus on peers allows for redundancy in the mechanism (as a node generally has many peers, and peer count can also be cheaply increased) which both helps with theoretical security as detailed in the &quot;Security Considerations&quot; section, but also practical security of the implementation (e.g. if a single peer fails, a node can likely use another peer for the same sampling task).

PeerDAS also has the nice property that any given node may voluntarily custody more of the data than the bare minimum which increases the performance of the mechanism. Alternative schemes do not readily support this &quot;transparent&quot; scaling property.

### Why are these parameters chosen?

The parameters of PeerDAS given in the specs support network security while keeping node requirements sufficiently low. See the security argument below for further details.

### Why do validators have an additional custody requirement beyond full nodes?

Validators are assumed to have marginally higher requirements to participate on the network. PeerDAS introduces a custody requirement that scales with the validator count so that nodes with more resources can contribute to a more stable backbone that makes the global network more robust.

### Column sampling vs row sampling

PeerDAS defines a sample as a &quot;column&quot; which is a cross-section across _all_ blobs, rather than a &quot;row&quot; which would be a full blob.
The sampling scheme could be defined over rows but then any reconstruction strategy would need to work over &quot;extension&quot; blobs that do not a priori exist on the network.
Reconstruction becomes much more tractable by working over columns as nodes can be assumed to have much more of the complete data by default (e.g. because most/all of the blobs are in the public mempool).

Another benefit is that sampling over rows requires _column_ extensions which would have to be done at the time of block construction, i.e. on the &quot;critical path&quot;. Sampling over columns requires row extensions which can be done in advance (not on the critical path), and moreover proof computation can be outsourced to senders of blob transactions.

## Backwards Compatibility

This EIP is fully backwards compatible with [EIP-4844](/EIPs/EIPS/eip-4844).

## Test Cases

Refer to the consensus and execution spec tests for testing of this EIP.

## Security Considerations

The primary failure mode of a DAS scheme is a &quot;data withholding&quot; attack, where a block producer attempts to convince the network some data is available even when the block producer fails to provide the associated data.
PeerDAS resolves withholding attacks by implementing a (pseudo)randomized sampling scheme that decreases the probability of a successful attack as the size of the network grows for a sublinear amount of data that must be downloaded.

This intuition can be formalized as follows:

Letting `n` be the total number of sampling nodes (i.e. the size of the network), `m` be the total number of samples possible (cf. `NUMBER_OF_CUSTODY_GROUPS` in the specs) and `k` be the minimum number of samples that a node must download (cf. `SAMPLES_PER_SLOT` in the specs), we have the following bound for the probability of convincing a fraction $\epsilon$ of the nodes that some data is available when it is withheld:

![withholding-probability](/EIPs/assets/eip-7594/withholding-probability.svg)

The first term is the number of possible ways to choose a subset of $n\epsilon$ nodes whose sampling queries should be satisfied (i.e. the nodes to be tricked).
The second term is the number of ways to choose a maximally large subset of samples to be made available to satisfy the sampling queries of the $n\epsilon$ nodes without allowing reconstruction of the full data.
Finally, for any such choices, the third term is the probability of success, i.e. the probability that the sampling queries of all chosen $n\epsilon$ nodes are satisfied by the chosen subset up to the reconstruction threshold.

For mainnet parameters given in the specs and assuming 10,000 nodes on the network, we can compute upper bounds of attack success for varying $\epsilon$:

| $\epsilon$ | $n\epsilon$ (target nodes) | Upper bound on $\mathbb{P}$ |
|:----------:|:-------------------:|:---------------------------:|
| 0.01        | 100                | $1$                         |
| 0.02        | 200                | $10^{-20.04}$               |
| 0.03        | 300                | $10^{-101.55}$              |
| 0.04        | 400                | $10^{-198.24}$              |
| 0.05        | 500                | $10^{-306.34}$              |

The table shows that the chances of a successful attack quickly drop to a negligible amount and so PeerDAS is considered secure to withholding attacks.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 12 Jan 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7594</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7594</guid>
      </item>
    
      <item>
        <title>Collateralized NFT</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/collateralized-nft-standard/18097</comments>
        
        <description>## Abstract

This proposal recommends an extension of [ERC-721](/EIPs/EIPS/eip-721) to allow for collateralization using a list of [ERC-20](/EIPs/EIPS/eip-20) based tokens. The proprietor of this ERC collection could hold both the native coin and [ERC-20](/EIPs/EIPS/eip-20) based tokens, with the `ownerOf` tokenId being able to unlock the associated portion of the underlying [ERC-20](/EIPs/EIPS/eip-20) balance.

## Motivation

The emerging trend of NFT finance focuses on the NFT floor price to enable the market value of the NFT serve as a collateral in lending protocols. The NFT floor price is susceptible to the supply-demand dynamics of the NFT market, characterized by higher volatility compared to the broader crypto market. Furthermore, potential price manipulation in specific NFT collections can artificially inflate NFT market prices, impacting the floor price considered by lending protocols. Relying solely on the NFT floor price based on market value is both unpredictable and unreliable.

This ERC addresses various challenges encountered by the crypto community with [ERC-721](/EIPs/EIPS/eip-721) based collections and assets. This ERC brings forth advantages such as sustainable NFT royalties supported by tangible assets, an on-chain verifiable floor price, and the introduction of additional monetization avenues for NFT collection creators.

### Presets

* The Basic Preset allows for the evaluation of an on-chain verifiable price floor for a specified NFT asset.

* The Dynamic Preset facilitates on-chain modification of tokenURI based on predefined collateral rules for a specified NFT asset.

* With the Royalty Preset, NFT collection creators can receive royalty payments for each transaction involving asset owners and Externally Owned Accounts (EOA), as well as transactions with smart contracts.

* The VRF Preset enables the distribution of collateral among multiple NFT asset holders using the Verifiable Random Function (VRF) by Chainlink.

### Extension to Existing ERC-721 Based Collections

For numerous [ERC-721](/EIPs/EIPS/eip-721) based collections that cannot be redeployed, we propose the implementation of an abstraction layer embodied by a smart contract. This smart contract would replicate all the functionalities of this ERC standard and grant access to collateral through mapping.

## Specification
### ERC standard for new NFT collections

```solidity

interface IERC721Envious is IERC721 {
	event Collateralized(uint256 indexed tokenId, uint256 amount, address tokenAddress);
	event Uncollateralized(uint256 indexed tokenId, uint256 amount, address tokenAddress);
	event Dispersed(address indexed tokenAddress, uint256 amount);
	event Harvested(address indexed tokenAddress, uint256 amount, uint256 scaledAmount);

	/**
	 * @dev An array with two elements. Each of them represents percentage from collateral
	 * to be taken as a commission. First element represents collateralization commission.
	 * Second element represents uncollateralization commission. There should be 3 
	 * decimal buffer for each of them, e.g. 1000 = 1%.
	 *
	 * @param uint 256 index of value in array.
	 */
	function commissions(uint256 index) external view returns (uint256);

	/**
	 * @dev &apos;Black hole&apos; is any address that guarantees that tokens sent to it will not be 
	 * retrieved from it. Note: some tokens revert on transfer to zero address.
	 *
	 * @return address address of black hole.
	 */
	function blackHole() external view returns (address);

	/**
	 * @dev Token that will be used to harvest collected commissions.
	 *
	 * @return address address of token.
	 */
	function communityToken() external view returns (address);

	/**
	 * @dev Pool of available tokens for harvesting.
	 *
	 * @param uint256 index in array.
	 * @return address address of token.
	 */
	function communityPool(uint256 index) external view returns (address);

	/**
	 * @dev Token balance available for harvesting.
	 *
	 * @param address address of token.
	 * @return uint256 token balance.
	 */
	function communityBalance(address tokenAddress) external view returns (uint256);

	/**
	 * @dev Array of tokens that have been dispersed.
	 *
	 * @param uint256 index in array.
	 * @return address address of dispersed token.
	 */
	function disperseTokens(uint256 index) external view returns (address);

	/**
	 * @dev Amount of tokens that has been dispersed.
	 *
	 * @param address address of token.
	 * @return uint256 token balance.
	 */
	function disperseBalance(address tokenAddress) external view returns (uint256);

	/**
	 * @dev Amount of tokens that was already taken from the disperse.
	 *
	 * @param address address of token.
	 * @return uint256 total amount of tokens already taken.
	 */
	function disperseTotalTaken(address tokenAddress) external view returns (uint256);

	/**
	 * @dev Amount of disperse already taken by each tokenId.
	 *
	 * @param tokenId unique identifier of unit.
	 * @param address address of token.
	 * @return uint256 amount of tokens already taken.
	 */
	function disperseTaken(uint256 tokenId, address tokenAddress) external view returns (uint256);

	/**
	 * @dev Mapping of `tokenId`s to token addresses that have collateralized before.
	 *
	 * @param tokenId unique identifier of unit.
	 * @param index in array.
	 * @return address address of token.
	 */
	function collateralTokens(uint256 tokenId, uint256 index) external view returns (address);

	/**
	 * @dev Token balances that are stored under `tokenId`.
	 *
	 * @param tokenId unique identifier of unit.
	 * @param address address of token.
	 * @return uint256 token balance.
	 */
	function collateralBalances(uint256 tokenId, address tokenAddress) external view returns (uint256);

	/**
	 * @dev Calculator function for harvesting.
	 *
	 * @param amount of `communityToken`s to spend
	 * @param address address of token to be harvested
	 * @return amount to harvest based on inputs
	 */
	function getAmount(uint256 amount, address tokenAddress) external view returns (uint256);

	/**
	 * @dev Collect commission fees gathered in exchange for `communityToken`.
	 *
	 * @param amounts[] array of amounts to collateralize
	 * @param address[] array of token addresses
	 */
	function harvest(uint256[] memory amounts, address[] memory tokenAddresses) external;

	/**
	 * @dev Collateralize NFT with different tokens and amounts.
	 *
	 * @param tokenId unique identifier for specific NFT
	 * @param amounts[] array of amounts to collateralize
	 * @param address[] array of token addresses
	 */
	function collateralize(
		uint256 tokenId,
		uint256[] memory amounts,
		address[] memory tokenAddresses
	) external payable;

	/**
	 * @dev Withdraw underlying collateral.
	 *
	 * Requirements:
	 * - only owner of NFT
	 *
	 * @param tokenId unique identifier for specific NFT
	 * @param amounts[] array of amounts to collateralize
	 * @param address[] array of token addresses
	 */
	function uncollateralize(
		uint256 tokenId, 
		uint256[] memory amounts, 
		address[] memory tokenAddresses
	) external;

	/**
	 * @dev Split collateral among all existent tokens.
	 *
	 * @param amounts[] to be dispersed among all NFT owners
	 * @param address[] address of token to be dispersed
	 */
	function disperse(uint256[] memory amounts, address[] memory tokenAddresses) external payable;
}
```

### Abstraction layer for already deployed NFT collections

```solidity

interface IEnviousHouse {
	event Collateralized(
		address indexed collection,
		uint256 indexed tokenId,
		uint256 amount,
		address tokenAddress
	);
	
	event Uncollateralized(
		address indexed collection,
		uint256 indexed tokenId,
		uint256 amount,
		address tokenAddress
	);
	
	event Dispersed(
		address indexed collection,
		address indexed tokenAddress,
		uint256 amount
	);
	
	event Harvested(
		address indexed collection,
		address indexed tokenAddress,
		uint256 amount,
		uint256 scaledAmount
	);

	/**
	 * @dev totalCollections function returns the total count of registered collections.
	 *
	 * @return uint256 number of registered collections.
	 */
	function totalCollections() external view returns (uint256);

	/**
	 * @dev &apos;Black hole&apos; is any address that guarantees that tokens sent to it will not be 
	 * retrieved from it. Note: some tokens revert on transfer to zero address.
	 *
	 * @param address collection address.
	 * @return address address of black hole.
	 */
	function blackHole(address collection) external view returns (address);

	/**
	 * @dev collections function returns the collection address based on the collection index input.
	 *
	 * @param uint256 index of a registered collection.
	 * @return address address collection.
	 */
	function collections(uint256 index) external view returns (address);

	/**
	 * @dev collectionIds function returns the collection index based on the collection address input.
	 * 
	 * @param address collection address.
	 * @return uint256 collection index.
	 */
	function collectionIds(address collection) external view returns (uint256);
	
	/**
	 * @dev specificCollections function returns whether a particular collection follows the ERC721 standard or not.
	 * 
	 * @param address collection address.
	 * @return bool specific collection or not.
	 */
	function specificCollections(address collection) external view returns (bool);
	
	/**
	 * @dev An array with two elements. Each of them represents percentage from collateral
	 * to be taken as a commission. First element represents collateralization commission.
	 * Second element represents uncollateralization commission. There should be 3 
	 * decimal buffer for each of them, e.g. 1000 = 1%.
	 *
	 * @param address collection address.
	 * @param uint256 index of value in array.
	 * @return uint256 collected commission.
	 */
	function commissions(address collection, uint256 index) external view returns (uint256);
	
	/**
	 * @dev Token that will be used to harvest collected commissions.
	 *
	 * @param address collection address.
	 * @return address address of token.
	 */
	function communityToken(address collection) external view returns (address);

	/**
	 * @dev Pool of available tokens for harvesting.
	 *
	 * @param address collection address.
	 * @param uint256 index in array.
	 * @return address address of token.
	 */
	function communityPool(address collection, uint256 index) external view returns (address);
	
	/**
	 * @dev Token balance available for harvesting.
	 *
	 * @param address collection address.
	 * @param address address of token.
	 * @return uint256 token balance.
	 */
	function communityBalance(address collection, address tokenAddress) external view returns (uint256);

	/**
	 * @dev Array of tokens that have been dispersed.
	 *
	 * @param address collection address.
	 * @param uint256 index in array.
	 * @return address address of dispersed token.
	 */
	function disperseTokens(address collection, uint256 index) external view returns (address);
	
	/**
	 * @dev Amount of tokens that has been dispersed.
	 *
	 * @param address collection address.
	 * @param address address of token.
	 * @return uint256 token balance.
	 */
	function disperseBalance(address collection, address tokenAddress) external view returns (uint256);
	
	/**
	 * @dev Amount of tokens that was already taken from the disperse.
	 *
	 * @param address collection address.
	 * @param address address of token.
	 * @return uint256 total amount of tokens already taken.
	 */
	function disperseTotalTaken(address collection, address tokenAddress) external view returns (uint256);
	
	/**
	 * @dev Amount of disperse already taken by each tokenId.
	 *
	 * @param address collection address.
	 * @param tokenId unique identifier of unit.
	 * @param address address of token.
	 * @return uint256 amount of tokens already taken.
	 */
	function disperseTaken(address collection, uint256 tokenId, address tokenAddress) external view returns (uint256);
	
	/**
	 * @dev Mapping of `tokenId`s to token addresses that have collateralized before.
	 *
	 * @param address collection address.
	 * @param tokenId unique identifier of unit.
	 * @param index in array.
	 * @return address address of token.
	 */
	function collateralTokens(address collection, uint256 tokenId, uint256 index) external view returns (address);

	/**
	 * @dev Token balances that are stored under `tokenId`.
	 *
	 * @param address collection address.
	 * @param tokenId unique identifier of unit.
	 * @param address address of token.
	 * @return uint256 token balance.
	 */
	function collateralBalances(address collection, uint256 tokenId, address tokenAddress) external view returns (uint256);
	
	/**
	 * @dev Calculator function for harvesting.
	 *
	 * @param address collection address.
	 * @param amount of `communityToken`s to spend.
	 * @param address address of token to be harvested.
	 * @return amount to harvest based on inputs.
	 */
	function getAmount(address collection, uint256 amount, address tokenAddress) external view returns (uint256);
	
	/**
	 * @dev setSpecificCollection function enables the addition of any collection that is not compatible with the ERC721 standard to the list of exceptions.
	 *
	 * @param address collection address.
	 */
	function setSpecificCollection(address collection) external;
	
	/**
	 * @dev registerCollection function grants Envious functionality to any ERC721-compatible collection and streamlines
	 * the distribution of an initial minimum disbursement to all NFT holders.
	 *
	 * @param address collection address.
	 * @param address address of `communityToken`.
	 * @param uint256 collateralization fee, incoming / 1e5 * 100%.
	 * @param uint256 uncollateralization fee, incoming / 1e5 * 100%.
	 */
	function registerCollection(
		address collection,
		address token,
		uint256 incoming,
		uint256 outcoming
	) external payable;	

	/**
	 * @dev Collect commission fees gathered in exchange for `communityToken`.
	 *
	 * @param address collection address.
	 * @param amounts[] array of amounts to collateralize.
	 * @param address[] array of token addresses.
	 */
	function harvest(
		address collection,
		uint256[] memory amounts,
		address[] memory tokenAddresses
	) external;
	
	/**
	 * @dev Collateralize NFT with different tokens and amounts.
	 *
	 * @param address collection address.
	 * @param tokenId unique identifier for specific NFT.
	 * @param amounts[] array of amounts to collateralize.
	 * @param address[] array of token addresses.
	 */
	function collateralize(
		address collection,
		uint256 tokenId,
		uint256[] memory amounts,
		address[] memory tokenAddresses
	) external payable;
	
	/**
	 * @dev Withdraw underlying collateral.
	 *
	 * Requirements:
	 * - only owner of NFT
	 *
	 * @param address collection address.
	 * @param tokenId unique identifier for specific NFT.
	 * @param amounts[] array of amounts to collateralize.
	 * @param address[] array of token addresses.
	 */
	function uncollateralize(
		address collection,
		uint256 tokenId,
		uint256[] memory amounts,
		address[] memory tokenAddresses
	) external;
	
	/**
	 * @dev Split collateral among all existent tokens.
	 *
	 * @param address collection address.
	 * @param amounts[] to be dispersed among all NFT owners.
	 * @param address[] address of token to be dispersed.
	 */
	function disperse(
		address collection,
		uint256[] memory amounts,
		address[] memory tokenAddresses
	) external payable;
}
```

## Rationale
### “Envious” Term Choice
We propose adopting the term &quot;Envious&quot; to describe any NFT collection minted using this ERC standard or any [ERC-721](/EIPs/EIPS/eip-721) based NFT collection that utilized the EnviousHouse abstraction layer.

### NFT Collateralization with Multiple Tokens
Some Web3 projects primarily collateralize a specific NFT asset with one [ERC-20](/EIPs/EIPS/eip-20) based token, resulting in increased gas fees and complications in User Experience (UX).

This ERC has been crafted to enable the collateralization of a designated NFT asset with multiple [ERC-20](/EIPs/EIPS/eip-20) based tokens within a single transaction.

### NFT Collateralization with the Native Coin
Each [ERC-20](/EIPs/EIPS/eip-20) based token possesses a distinct address. However, a native coin does not carry an address. To address this, we propose utilizing a null address (`0x0000000000000000000000000000000000000000`) as an identifier for the native coin during collateralization, as it eliminates the possibility of collisions with smart contract addresses.

### Disperse Functionality
We have implemented the capability to collateralize all assets within a particular NFT collection in a single transaction. The complete collateral amount is deposited into a smart contract, enabling each user to claim their respective share of the collateral when they add or redeem collateral for that specific asset.

### Harvest Functionality
Each Envious NFT collection provides an option to incorporate a community [ERC-20](/EIPs/EIPS/eip-20) based token, which can be exchanged for commissions accrued from collateralization and uncollateralization activities.

### BlackHole Instance
Some [ERC-20](/EIPs/EIPS/eip-20) based token implementations forbid transfers to the null address, it is necessary to have a reliable burning mechanism in the harvest transactions. `blackHole` smart contract removes [ERC-20](/EIPs/EIPS/eip-20) communityTokens from the circulating supply in exchange for commission fees withdrawn.

`blackHole` has been designed to prevent the transfer of any tokens from itself and can only perform read operations. It is intended to be used with the Envious extension in implementations related to commission harvesting.

## Backwards Compatibility

EnviousHouse abstraction layer is suggested for already deployed [ERC-721](/EIPs/EIPS/eip-721) based NFT collections.

## Security Considerations

Envious may share security concerns similar to those found in [ERC-721](/EIPs/EIPS/eip-721), such as hidden logic within functions like burn, add resource, accept resource, etc.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 13 Mar 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7595</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7595</guid>
      </item>
    
      <item>
        <title>Signature Validation Extension for Permit</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/add-erc-contract-signature-validation-extension-for-eip-2612-permit/18157</comments>
        
        <description># EIP: Contract signature validation extension for [ERC-2612](/EIPs/EIPS/eip-2612) Permit

## Abstract

This proposal aims to extend the functionality of the existing [ERC-2612](/EIPs/EIPS/eip-2612) Permit to support gasless [ERC-20](/EIPs/EIPS/eip-20) approval operations initiated by smart contract wallets. 

## Motivation

The current signature validation scheme in [ERC-2612](/EIPs/EIPS/eip-2612), based on V, R, S parameters, restricts signature validation to EOA wallets. 

With the growing popularity of smart contract wallets and increased adoption of [ERC-1271](/EIPs/EIPS/eip-1271), it is necessary to allow for flexible signature validation methods and the use of custom logic in each contract&apos;s signature verification. By accepting unstructured signature bytes as input, custom algorithms and signature schemes can be utilized, enabling a wider range of wallet types.

## Specification

Compliant contracts must implement the `permit` using the following spec

```
function permit(address owner, address spender, uint value, uint deadline, bytes memory signature) external
```
as well as two other interfaces previously mandated by [ERC-2612](/EIPs/EIPS/eip-2612):
```
function nonces(address owner) external view returns (uint)
function DOMAIN_SEPARATOR() external view returns (bytes32)
```

A call to `permit(owner, spender, value, deadline, signature)` will set `allowance[owner][spender]` to value, increment `nonces[owner]` by 1, and emit a corresponding `Approval` event, if and only if the following conditions are met:

- The current blocktime is less than or equal to `deadline`.
- `owner` is not the zero address.
- `nonces[owner]` (before the state update) is equal to nonce.
- `signature` validation:
    - If `owner` is an EOA, `signature` is a valid secp256k1 signature in the form of `abi.encodePacked(r, s, v)`.
    - If `owner` is a contract, `signature` is validated by calling `isValidSignature()` on the `owner` contract.

If any of these conditions are not met, the permit call must revert.

## Rationale

By replacing the existing V, R, S signature validation scheme and introducing support for unstructured bytes input, contract developers can use a unified interface to validate signature from both EOAs and SC wallets. This allows for the utilization of different signature schemes and algorithms fitting the wallet type, paving the way for smart contract wallets and advanced wallet types to enhance their signature validation processes, promoting flexibility and innovation.

## Backwards Compatibility

This proposal is fully backward-compatible with the existing ERC-2612 standard. Contracts that currently rely on the V, R, S signature validation scheme will continue to function without any issues.

If both V, R, S signature validation and the new unstructured bytes signature validation need to be supported for backward compatibility reasons, developers can reduce duplicates by adapting the following code block as an example:

```
function permit(
    address owner,
    address spender,
    uint256 value,
    uint256 deadline,
    uint8 v, 
    bytes32 r, 
    bytes32 s
) external {
    _permit(owner, spender, value, deadline, abi.encodePacked(r, s, v));
}
```

## Reference Implementation

Sample `permit` implemented with OZ&apos;s SignatureChecker

```solidity
/**
 * @notice Update allowance with a signed permit
 * @dev Signature bytes can be used for both EOA wallets and contract wallets.
 * @param owner       Token owner&apos;s address (Authorizer)
 * @param spender     Spender&apos;s address
 * @param value       Amount of allowance
 * @param deadline    The time at which the signature expires (unix time)
 * @param signature   Unstructured bytes signature signed by an EOA wallet or a contract wallet
 */
function permit(
    address owner,
    address spender,
    uint256 value,
    uint256 deadline,
    bytes memory signature
) external {
    require(deadline &gt;= now, &quot;Permit is expired&quot;);
    require(owner != address(0), &quot;ERC20: approve from the zero address&quot;);
    require(spender != address(0), &quot;ERC20: approve to the zero address&quot;);

    bytes32 digest = keccak256(abi.encodePacked(
        hex&quot;1901&quot;,
        DOMAIN_SEPARATOR,
        keccak256(abi.encode(
            keccak256(&quot;Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)&quot;),
            owner,
            spender,
            value,
            nonce,
            deadline
        ))
    ));
    
    require(
        // Check for both ECDSA signature and ERC-1271 signature. A sample SignatureChecker is available at
        // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/7bd2b2a/contracts/utils/cryptography/SignatureChecker.sol
        SignatureChecker.isValidSignatureNow(
            owner,
            typedDataHash,
            signature
        ),
        &quot;Invalid signature&quot;
    );
    
    allowed[owner][spender] = value;
    emit Approval(owner, spender, value);
}
```

## Security Considerations

- For contract wallets, the security of `permit` relies on `isValidSignature()` to ensure the signature bytes represent the desired execution from contract wallet owner(s). Contract wallet developers must exercise caution when implementing custom signature validation logic to ensure the security of their contracts. 

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 15 Jan 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7597</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7597</guid>
      </item>
    
      <item>
        <title>Use contract signature for signed transfer</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/add-erc-contract-signature-validation-extension-for-erc-3009-transfer-with-authorization/18158</comments>
        
        <description># EIP: Contract signature validation extension for [ERC-3009](/EIPs/EIPS/eip-3009) Transfer with Authorization

## Abstract

This proposal aims to extend the functionality of the existing [ERC-3009](/EIPs/EIPS/eip-3009) standard, &quot;Transfer With Authorization,&quot; to support transfer operations initiated by smart contract wallets. 

## Motivation

The existing [ERC-3009](/EIPs/EIPS/eip-3009) standard enables asset transfers with ECDSA signatures. However, as smart contract wallets become more prevalent in the ecosystem, the current standard is no longer sufficient. 

This proposal aims to enhance the usability and composeability of the standard by extending ERC-3009 with smart contract wallet signature validation, as defined in [ERC-1271](/EIPs/EIPS/eip-1271). By incorporating this extension, users will have greater flexibility in managing their assets while ensuring a secure authorization process.

## Specification

The following events and interfaces must still be present given the initial spec defined in [ERC-3009](/EIPs/EIPS/eip-3009).
- Event `AuthorizationUsed`.
- Constants `TRANSFER_WITH_AUTHORIZATION_TYPEHASH` and `RECEIVE_WITH_AUTHORIZATION_TYPEHASH`.
- View function interface `authorizationState(address authorizer, bytes32 nonce)`

In addition, the following interfaces must be added to be compliant with the standard:

```
/**
 * @notice Execute a transfer with a signed authorization
 * @param from          Payer&apos;s address (Authorizer)
 * @param to            Payee&apos;s address
 * @param value         Amount to be transferred
 * @param validAfter    The time after which this is valid (unix time)
 * @param validBefore   The time before which this is valid (unix time)
 * @param nonce         Unique nonce
 * @param signature     Unstructured bytes signature signed by an EOA wallet or a contract wallet
 */
function transferWithAuthorization(
    address from,
    address to,
    uint256 value,
    uint256 validAfter,
    uint256 validBefore,
    bytes32 nonce,
    bytes memory signature
) external;

/**
 * @notice Receive a transfer with a signed authorization from the payer
 * @dev This has an additional check to ensure that the payee&apos;s address matches
 * the caller of this function to prevent front-running attacks. (See security
 * considerations)
 * @param from          Payer&apos;s address (Authorizer)
 * @param to            Payee&apos;s address
 * @param value         Amount to be transferred
 * @param validAfter    The time after which this is valid (unix time)
 * @param validBefore   The time before which this is valid (unix time)
 * @param nonce         Unique nonce
 * @param signature     Unstructured bytes signature signed by an EOA wallet or a contract wallet
 */
function receiveWithAuthorization(
    address from,
    address to,
    uint256 value,
    uint256 validAfter,
    uint256 validBefore,
    bytes32 nonce,
    bytes memory signature
) external;
```

Optional:

The `AuthorizationCanceled` event and `CANCEL_AUTHORIZATION_TYPEHASH` constant as defined in the [ERC-3009](/EIPs/EIPS/eip-3009) spec.

```
/**
 * @notice Attempt to cancel an authorization
 * @param authorizer    Authorizer&apos;s address
 * @param nonce         Nonce of the authorization
 * @param signature     Unstructured bytes signature signed by an EOA wallet or a contract wallet
 */
function cancelAuthorization(
    address authorizer,
    bytes32 nonce,
    bytes memory signature
) external;
```

## Rationale

By replacing the existing V, R, S signature validation scheme and introducing support for unstructured bytes input, contract developers can use a unified interface to validate signature from both EOAs and SC wallets. This allows for the utilization of different signature schemes and algorithms fitting the wallet type, paving the way for smart contract wallets and advanced wallet types to enhance their signature validation processes, promoting flexibility and innovation.


## Backwards Compatibility

This proposal is fully backward-compatible with the existing ERC-3009 standard. Contracts that currently rely on the V, R, S signature validation scheme will continue to function without any issues.

In the event that both the existing V, R, S signature validation scheme and the new unstructured bytes signature validation need to be supported for backward compatibility, developers can reduce duplicates by adapting the following code block as an example:

```
function transferWithAuthorization(
    address from,
    address to,
    uint256 value,
    uint256 validAfter,
    uint256 validBefore,
    bytes32 nonce,
    uint8 v,
    bytes32 r,
    bytes32 s
) external {
    transferWithAuthorization(owner, spender, value, deadline, abi.encodePacked(r, s, v));
}
```

## Reference Implementation

```
/**
  * @notice Execute a transfer with a signed authorization
  * @dev EOA wallet signatures should be packed in the order of r, s, v.
  * @param from          Payer&apos;s address (Authorizer)
  * @param to            Payee&apos;s address
  * @param value         Amount to be transferred
  * @param validAfter    The time after which this is valid (unix time)
  * @param validBefore   The time before which this is valid (unix time)
  * @param nonce         Unique nonce
  * @param signature     Signature byte array produced by an EOA wallet or a contract wallet
  */
function _transferWithAuthorization(
    address from,
    address to,
    uint256 value,
    uint256 validAfter,
    uint256 validBefore,
    bytes32 nonce,
    bytes memory signature
) internal {
    require(now &gt; validAfter, &quot;Authorization is not yet valid&quot;);
    require(now &lt; validBefore, &quot;Authorization is expired&quot;);
    require(!_authorizationStates[authorizer][nonce], &quot;Authorization is used or canceled&quot;);

    bytes32 digest = keccak256(abi.encodePacked(
        hex&quot;1901&quot;,
        DOMAIN_SEPARATOR,
        keccak256(abi.encode(
            TRANSFER_WITH_AUTHORIZATION_TYPEHASH,
            from,
            to,
            value,
            validAfter,
            validBefore,
            nonce
        ))
    ));
    require(
        // Check for both ECDSA signature and ERC-1271 signature. A sample SignatureChecker is available at
        // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/7bd2b2a/contracts/utils/cryptography/SignatureChecker.sol
        SignatureChecker.isValidSignatureNow(
            owner,
            typedDataHash,
            signature
        ),
        &quot;Invalid signature&quot;
    );

    _authorizationStates[authorizer][nonce] = true;
    emit AuthorizationUsed(authorizer, nonce);
    
    _transfer(from, to, value);
}
```

## Security Considerations

- For contract wallets, the security of `transferWithAuthorization`, `receiveWithAuthorization`, and `cancelAuthorization` rely on `ContractWallet.isValidSignature()` to ensure the signature bytes represent the desired execution from contract wallet owner(s). Contract wallet developers must exercise caution when implementing custom signature validation logic to ensure the security of their contracts. 

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 15 Jan 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7598</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7598</guid>
      </item>
    
      <item>
        <title>Hardfork Meta - Pectra</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7600-hardfork-meta-prague-electra/18205</comments>
        
        <description>## Abstract

This Meta EIP lists the EIPs Included in the Prague/Electra network upgrade. It follows the Dencun upgrade, documented in [EIP-7569](/EIPs/EIPS/eip-7569).

## Specification

### Included EIPs

#### Core EIPs

* [EIP-2537](/EIPs/EIPS/eip-2537): Precompile for BLS12-381 curve operations
* [EIP-2935](/EIPs/EIPS/eip-2935): Save historical block hashes in state
* [EIP-6110](/EIPs/EIPS/eip-6110): Supply validator deposits on chain
* [EIP-7002](/EIPs/EIPS/eip-7002): Execution layer triggerable exits
* [EIP-7251](/EIPs/EIPS/eip-7251): Increase the MAX_EFFECTIVE_BALANCE  
* [EIP-7549](/EIPs/EIPS/eip-7549): Move committee index outside Attestation
* [EIP-7623](/EIPs/EIPS/eip-7623): Increase calldata cost
* [EIP-7685](/EIPs/EIPS/eip-7685): General purpose execution layer requests 
* [EIP-7691](/EIPs/EIPS/eip-7691): Blob throughput increase
* [EIP-7702](/EIPs/EIPS/eip-7702): Set EOA account code

#### Other EIPs

* [EIP-7840](/EIPs/EIPS/eip-7840): Add blob schedule to EL config files (Informational)
* [EIP-7642](/EIPs/EIPS/eip-7642): eth/69 - Drop pre-merge fields (Networking)
	* While not necessary for the Pectra network upgrade, client teams MAY support EIP-7642 by the upgrade&apos;s activation and MUST support it by the next network upgrade.

### Full Specifications

#### Consensus Layer

EIP-6110, EIP-7002 EIP-7251, EIP-7549, EIP-7685 and EIP-7691 require changes to Ethereum&apos;s consensus layer. While the EIPs present an overview of these changes, the full specifications can be found in the `specs/electra` and `specs/_features` directories of the `ethereum/consensus-specs` repository.

#### Execution Layer

EIP-2537, EIP-2935, EIP-6110, EIP-7002, EIP-7623, EIP-7685, EIP-7702 and EIP-7840 require changes to Ethereum&apos;s execution layer. The EIPs fully specify those changes.

### Activation 

| Network Name     | Activation Epoch | Activation Timestamp |
|------------------|------------------|----------------------|
| Holešky          |   `115968`       |     `1740434112`     |
| Sepolia          |   `222464`       |     `1741159776`     |
| Hoodi            |    `2048`        |     `1742999832`     |
| Mainnet          |   `364032`       |     `1746612311`     |

## Rationale

This Meta EIP provides a global view of all changes included in the Prague/Electra network upgrade, as well as links to the full specification. 

## Security Considerations

None.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 18 Jan 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7600</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7600</guid>
      </item>
    
      <item>
        <title>ERC-1155 Multi-Asset extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-multi-context-dependent-multi-asset-tokens-eip1155-extension/18303</comments>
        
        <description>## Abstract

The Multi-Asset Token standard, compatible with [ERC-1155](/EIPs/EIPS/eip-1155), facilitates the development of a new fundamental component: the context-dependent data output for each collection.

The context-dependent data output means that the asset is displayed in an appropriate format based on how the token is accessed. I.e., if the token is being opened in an e-book reader, the PDF asset is displayed; if the token is opened in the marketplace, the PNG or the SVG asset is displayed; if the token is accessed from within a game, the 3D model asset is accessed, and if the token is accessed by an Internet of Things (IoT) hub, the asset providing the necessary addressing and specification information is accessed.

A Token Collection can have multiple assets (outputs), which can be any file to order them by priority. They do not have to match in mime-type or tokenURI, nor do they depend on one another. Assets are not standalone entities but should be considered “namespaced tokenURIs”.

## Motivation

With ERC-1155 compatible tokens being a widespread form of tokens in the Ethereum ecosystem and being used for various use cases, it is time to standardize additional utility for them. Having multiple assets associated with a single Token Collection allows for greater utility, usability, and forward compatibility. This EIP improves upon ERC-1155 in the following areas:

- [Cross-metaverse compatibility](#cross-metaverse-compatibility)
- [Multi-media output](#multi-media-output)
- [Media redundancy](#media-redundancy)

### Cross-metaverse compatibility

The proposal can support any number of different implementations.

Cross-metaverse compatibility could also be referred to as cross-engine compatibility. An example is where a cosmetic item for game A is unavailable in game B because the frameworks are incompatible.

Such Tokens can be given further utility through new assets: more games, cosmetic items, and more.

The following is a more concrete example. One asset is a cosmetic item for game A, a file containing the cosmetic assets. Another is a cosmetic asset file for game B. A third is a generic asset intended to be shown in catalogs, marketplaces, portfolio trackers, or other generalized Token Collection viewers, containing a representation, stylized thumbnail, and animated demo/trailer of the cosmetic item.

This EIP adds a layer of abstraction, allowing game developers to pull asset data from a user&apos;s Tokens directly instead of hard-coding it.

### Multi-media output

Tokens of an eBook can be represented as a PDF, MP3, or some other format, depending on what software loads it. If loaded into an eBook reader, a PDF should be displayed, and if loaded into an audiobook application, the MP3 representation should be used. Other metadata could be present in the Tokens (perhaps the book&apos;s cover image) for identification on various marketplaces, Search Engine Result Pages (SERPs), or portfolio trackers.

### Media redundancy

Many Tokens are minted hastily without best practices in mind. Specifically, many Tokens are minted with metadata centralized on a server somewhere or, in some cases, a hardcoded IPFS gateway which can also go down, instead of just an IPFS hash.

By adding the same metadata file as different assets, e.g., one asset of metadata and its linked image on Arweave, one asset of this same combination on Sia, another of the same combination on IPFS, etc., the resilience of the metadata and its referenced information increases exponentially as the chances of all the protocols going down at once become less likely.

## Specification

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

```solidity
/// @title ERC-7603 Context-Dependent Multi-Asset Tokens, ERC-1155 Execution
/// @dev See https://eips.ethereum.org/EIPS/erc-7603

pragma solidity ^0.8.23;

interface IERC7603 /* is ERC165 */ {
    /**
     * @notice Used to notify listeners that an asset object is initialised at `assetId`.
     * @param assetId ID of the asset that was initialised
     */
    event AssetSet(uint64 assetId);

    /**
     * @notice Used to notify listeners that an asset object at `assetId` is added to token&apos;s asset
     *  array.
     * @param tokenId An ID of the token that received a new asset
     * @param assetId ID of the asset that has been added to the token&apos;s assets array
     * @param replacesId ID of the asset that would be replaced
     */
    event AssetAddedToToken(
        uint256[] tokenId,
        uint64 indexed assetId,
        uint64 indexed replacesId
    );

    /**
     * @notice Used to notify listeners that token&apos;s priority array is reordered.
     * @param tokenId ID of the token that had the asset priority array updated
     */
    event AssetPrioritySet(uint256 indexed tokenId);

    /**
     * @notice Sets a new priority array for a given token.
     * @dev The priority array is a non-sequential list of `uint16`s, where the lowest value is considered highest
     *  priority.
     * @dev Value `0` of a priority is a special case equivalent to uninitialised.
     * @dev Requirements:
     *
     *  - `tokenId` must exist.
     *  - The length of `priorities` must be equal the length of the assets array.
     * @dev Emits a {AssetPrioritySet} event.
     * @param tokenId ID of the token to set the priorities for
     * @param priorities An array of priorities of assets. The succession of items in the priorities array
     *  matches that of the succession of items in the array
     */
    function setPriority(uint256 tokenId, uint64[] calldata priorities)
        external;

    /**
     * @notice Used to retrieve IDs of assets of given token.
     * @dev Asset data is stored by reference, in order to access the data corresponding to the ID, call
     *  `getAssetMetadata(tokenId, assetId)`.
     * @dev You can safely get 10k
     * @param tokenId ID of the token to retrieve the IDs of the assets
     * @return uint64[] An array of the asset IDs of the given token
     */
    function getAssets(uint256 tokenId)
        external
        view
        returns (uint64[] memory);

    /**
     * @notice Used to retrieve the priorities of the assets of a given token.
     * @dev Asset priorities are a non-sequential array of uint16 values with an array size equal to asset
     *  priorites.
     * @param tokenId ID of the token for which to retrieve the priorities of the assets
     * @return uint16[] An array of priorities of the assets of the given token
     */
    function getAssetPriorities(uint256 tokenId)
        external
        view
        returns (uint64[] memory);

    /**
     * @notice Used to fetch the asset metadata of the specified token&apos;s asset with the given index.
     * @dev Can be overridden to implement enumerate, fallback or other custom logic.
     * @param tokenId ID of the token from which to retrieve the asset metadata
     * @param assetId Asset Id, must be in the assets array
     * @return string The metadata of the asset belonging to the specified index in the token&apos;s assets array
     */
    function getAssetMetadata(uint256 tokenId, uint64 assetId)
        external
        view
        returns (string memory);
}

```

## Rationale

TBD &lt;!-- TODO --&gt;

## Backwards Compatibility

The MultiAsset token standard has been made compatible with ERC-1155 in order to take advantage of the robust tooling available for implementations of ERC-1155 and to ensure compatibility with existing ERC-1155 infrastructure.

## Security Considerations

Needs discussion. &lt;!-- TODO --&gt;

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 25 Jan 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7603</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7603</guid>
      </item>
    
      <item>
        <title>ERC-1155 Permit Approvals</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/proposal-for-a-new-eip-erc-2612-style-permits-for-erc1155-nfts/15504</comments>
        
        <description>## Abstract

The &quot;permit&quot; approval flow for both [ERC-20](/EIPs/EIPS/eip-20) and [ERC-721](/EIPs/EIPS/eip-721) are large improvements for the existing UX of the token underlying each ERC. This ERC extends the &quot;permit&quot; pattern to [ERC-1155](/EIPs/EIPS/eip-20) tokens, borrowing heavily upon both [ERC-4494](/EIPs/EIPS/eip-4494) and [ERC-2612](/EIPs/EIPS/eip-2612).

The structure of [ERC-1155](/EIPs/EIPS/eip-1155) tokens requires a new ERC to account for the token standard&apos;s use of both token IDs and balances (also why this ERC requires [ERC-5216](/EIPs/EIPS/eip-5216)).

## Motivation

The permit structures outlined in both [ERC-4494](./eip-4494) and [ERC-2612](./eip-2612) allows a signed message to create an approval, but are only applicable to their respective underlying tokens ([ERC-721](./eip-721) and [ERC-20](./eip-20)).

## Specification

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

Three new functions must be added to ERC-1155 and ERC-5216.

```solidity
interface IERC1155Permit {
	function permit(address owner, address operator, uint256 tokenId, uint256 value, uint256 deadline, bytes memory sig) external;
	function nonces(address owner, uint256 tokenId) external view returns (uint256);
	function DOMAIN_SEPARATOR() external view returns (bytes32);
}
```

The semantics of which are as follows:

For all addresses `owner`, `spender`, uint256&apos;s `tokenId`, `value`, `deadline`, and `nonce`, bytes `sig`, a call to `permit(owner, spender, tokenId, value, deadline, sig)` MUST set `allowance(owner, spender, tokenId)` to `value`, increment `nonces(owner, tokenId)` by 1, and emit a corresponding `Approval` event defined by [ERC-5216](/EIPs/EIPS/eip-5216), if and only if the following conditions are met:
- The current blocktime is less than or equal to `deadline`
- `owner` is not the zero address
- `nonces[owner][tokenId]` (before state update) is equal to `nonce`
- `sig` is a valid `secp256k1`, [ERC-2098](/EIPs/EIPS/eip-2098), or [ERC-1271](/EIPs/EIPS/eip-1271) signature from `owner` of the message:
```
keccak256(abi.encodePacked(
   hex&quot;1901&quot;,
   DOMAIN_SEPARATOR,
   keccak256(abi.encode(
            keccak256(&quot;Permit(address owner,address spender,uint256 tokenId,uint256 value,uint256 nonce,uint256 deadline)&quot;),
            owner,
            spender,
            tokenId,
            value,
            nonce,
            deadline))
));
```

If any of these conditions are not met the `permit` call MUST revert.

Where `DOMAIN_SEPARATOR` MUST be defined according to [EIP-712](/EIPs/EIPS/eip-712). The `DOMAIN_SEPARATOR` should be unique to the contract and chain to prevent replay attacks from other domains, and satisfy the requirements of EIP-712, but is otherwise unconstrained. A common choice for `DOMAIN_SEPARATOR` is:
```
DOMAIN_SEPARATOR = keccak256(
    abi.encode(
        keccak256(&apos;EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)&apos;),
        keccak256(bytes(name)),
        keccak256(bytes(version)),
        chainid,
        address(this)
));
```

In other words, the message is the following EIP-712 typed structure:
```
{
  &quot;types&quot;: {
    &quot;EIP712Domain&quot;: [
      {
        &quot;name&quot;: &quot;name&quot;,
        &quot;type&quot;: &quot;string&quot;
      },
      {
        &quot;name&quot;: &quot;version&quot;,
        &quot;type&quot;: &quot;string&quot;
      },
      {
        &quot;name&quot;: &quot;chainId&quot;,
        &quot;type&quot;: &quot;uint256&quot;
      },
      {
        &quot;name&quot;: &quot;verifyingContract&quot;,
        &quot;type&quot;: &quot;address&quot;
      }
    ],
    &quot;Permit&quot;: [
	  {
	    &quot;name&quot;: &quot;owner&quot;.
	    &quot;type&quot;: &quot;address&quot;
	  },
      {
        &quot;name&quot;: &quot;spender&quot;,
        &quot;type&quot;: &quot;address&quot;
      },
      {
        &quot;name&quot;: &quot;tokenId&quot;,
        &quot;type&quot;: &quot;uint256&quot;
      },
      {
        &quot;name&quot;: &quot;value&quot;,
        &quot;type&quot;: &quot;uint256&quot;
      },
      {
        &quot;name&quot;: &quot;nonce&quot;,
        &quot;type&quot;: &quot;uint256&quot;
      },
      {
        &quot;name&quot;: &quot;deadline&quot;,
        &quot;type&quot;: &quot;uint256&quot;
      }
    ],
    &quot;primaryType&quot;: &quot;Permit&quot;,
    &quot;domain&quot;: {
      &quot;name&quot;: erc1155name,
      &quot;version&quot;: version,
      &quot;chainId&quot;: chainid,
      &quot;verifyingContract&quot;: tokenAddress
  },
  &quot;message&quot;: {
    &quot;owner&quot;: owner,
    &quot;spender&quot;: spender,
    &quot;tokenId&quot;: tokenId,
    &quot;value&quot;: value,
    &quot;nonce&quot;: nonce,
    &quot;deadline&quot;: deadline
  }
}}
```

The `permit` function MUST check that the signer is not the zero address.

Note that nowhere in this definition do we refer to `msg.sender`. The caller of the `permit` function can be any address.

This EIP requires [ERC-165](/EIPs/EIPS/eip-165). ERC-165 is already required in [ERC-1155](/EIPs/EIPS/eip-1155), but is further necessary here in order to register the interface of this ERC. Doing so will allow easy verification if an NFT contract has implemented this ERC or not, enabling them to interact accordingly. The ERC-165 interface of this ERC is `0x7409106d`. Contracts implementing this ERC MUST have the `supportsInterface` function return `true` when called with `0x7409106d`.

## Rationale

The `permit` function is sufficient for enabling a `safeTransferFrom` transaction to be made without the need for an additional transaction.

The format avoids any calls to unknown code.

The `nonces` mapping is given for replay protection.

A common use case of permit has a relayer submit a Permit on behalf of the owner. In this scenario, the relaying party is essentially given a free option to submit or withhold the Permit. If this is a cause of concern, the owner can limit the time a Permit is valid for by setting deadline to a value in the near future. The `deadline` argument can be set to `uint(-1)` to create Permits that effectively never expire. Likewise, the `value` argument can be set to `uint(-1)` to create Permits with effectively unlimited allowances.

EIP-712 typed messages are included because of its use in [ERC-4494](/EIPs/EIPS/eip-4494) and [ERC-2612](/EIPs/EIPS/eip-2612), which in turn cites widespread adoption in many wallet providers.

This ERC focuses on both the `value` and `tokenId` being approved, ERC-4494 focuses only on the `tokenId`, while ERC-2612 focuses primarily on the `value`. ERC-1155 does not natively support approvals by amount, thus this ERC requires ERC-5216, otherwise a `permit` would grant approval for an account&apos;s entire `tokenId` balance.

Whereas ERC-2612 splits signatures into their `v,r,s` components, this ERC opts to instead take a `bytes` array of variable length in order to support [ERC-2098](/EIPs/EIPS/eip-1271) signatures, which may not be easily separated or reconstructed from `r,s,v` components (65 bytes).

## Backwards Compatibility

No backward compatibility issues found.

## Security Considerations

The below considerations have been copied from ERC-4494.

Extra care should be taken when creating transfer functions in which `permit` and a transfer function can be used in one function to make sure that invalid permits cannot be used in any way. This is especially relevant for automated NFT platforms, in which a careless implementation can result in the compromise of a number of user assets.

The remaining considerations have been copied from [ERC-2612](/EIPs/EIPS/eip-2612) with minor adaptation, and are equally relevant here:

Though the signer of a `Permit` may have a certain party in mind to submit their transaction, another party can always front run this transaction and call `permit` before the intended party. The end result is the same for the `Permit` signer, however.

Since the ecrecover precompile fails silently and just returns the zero address as `signer` when given malformed messages, it is important to ensure `ownerOf(tokenId) != address(0)` to avoid `permit` from creating an approval to any `tokenId` which does not have an approval set.

Signed `Permit` messages are censorable. The relaying party can always choose to not submit the `Permit` after having received it, withholding the option to submit it. The `deadline` parameter is one mitigation to this. If the signing party holds ETH they can also just submit the `Permit` themselves, which can render previously signed `Permit`s invalid.

The standard ERC-20 race condition for approvals applies to `permit` as well.

If the `DOMAIN_SEPARATOR` contains the `chainId` and is defined at contract deployment instead of reconstructed for every signature, there is a risk of possible replay attacks between chains in the event of a future chain split..

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 27 Jan 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7604</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7604</guid>
      </item>
    
      <item>
        <title>Hardfork Meta - Fusaka</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7607-fusaka-meta-eip/18439</comments>
        
        <description>## Abstract

This Meta EIP lists the EIPs included in the Fulu/Osaka network upgrade. It follows the Pectra upgrade, documented in [EIP-7600](/EIPs/EIPS/eip-7600).

## Specification

### Included EIPs

#### Core EIPs

* [EIP-7594](/EIPs/EIPS/eip-7594): PeerDAS - Peer Data Availability Sampling
* [EIP-7823](/EIPs/EIPS/eip-7823): Set upper bounds for MODEXP
* [EIP-7825](/EIPs/EIPS/eip-7825): Transaction Gas Limit Cap
* [EIP-7883](/EIPs/EIPS/eip-7883): ModExp Gas Cost Increase
* [EIP-7917](/EIPs/EIPS/eip-7917): Deterministic proposer lookahead
* [EIP-7918](/EIPs/EIPS/eip-7918): Blob base fee bounded by execution cost
* [EIP-7934](/EIPs/EIPS/eip-7934): RLP Execution Block Size Limit
* [EIP-7939](/EIPs/EIPS/eip-7939): Count leading zeros (CLZ) opcode
* [EIP-7951](/EIPs/EIPS/eip-7951): Precompile for secp256r1 Curve Support

#### Other EIPs

* [EIP-7892](/EIPs/EIPS/eip-7892): Blob Parameter Only Hardforks 
* [EIP-7642](/EIPs/EIPS/eip-7642): eth/69 - Drop pre-merge fields
    * Client teams MUST support this EIP by the activation of the Fusaka network upgrade.
* [EIP-7910](/EIPs/EIPS/eip-7910): eth_config JSON-RPC Method
    * Client teams MUST support this JSON-RPC method by the activation of Fusaka network upgrade. 
* [EIP-7935](/EIPs/EIPS/eip-7935): Set default gas limit to 60M

### Activation

| Network Name     | Activation Epoch | Activation Timestamp | Activation Time (UTC)   | Fork ID     |
|------------------|------------------|----------------------|-------------------------|-------------|
| Holešky          |   `165120`       |     `1759308480`     | 2025-10-01 08:48:00     | `0x783def52`|
| Sepolia          |   `272640`       |     `1760427360`     | 2025-10-14 07:36:00     | `0xe2ae4999`|
| Hoodi            |    `50688`       |     `1761677592`     | 2025-10-28 18:53:12     | `0xe7e0e7ff`|
| Mainnet          |   `411392`       |      `1764798551`    | 2025-12-03 21:49:11     | `0x5167e2a6`|

### Blob Parameter Only Forks

Blob Parameter Only (BPO) forks, defined in [EIP-7892](/EIPs/EIPS/eip-7892), are scheduled alongside Fusaka to raise blob capacity without additional protocol changes.

#### BPO 1

| Network Name | Activation Epoch | Activation Timestamp | Activation Time (UTC)   | Fork ID     |
|--------------|------------------|----------------------|-------------------------|-------------|
| Holešky      |   `166400`       |     `1759800000`     | 2025-10-07 01:20:00     | `0xa280a45c`|
| Sepolia      |   `274176`       |     `1761017184`     | 2025-10-21 03:26:24     | `0x56078a1e`|
| Hoodi        |    `52480`       |     `1762365720`     | 2025-11-05 18:02:00     | `0x3893353e`|
| Mainnet      |   `412672`       |     `1765290071`     | 2025-12-09 14:21:11     | `0xcba2a1c0`|

#### BPO 2

| Network Name | Activation Epoch | Activation Timestamp | Activation Time (UTC)   | Fork ID     |
|--------------|------------------|----------------------|-------------------------|-------------|
| Holešky      |   `167936`       |     `1760389824`     | 2025-10-13 21:10:24     | `0x9bc6cb31`|
| Sepolia      |   `275712`       |     `1761607008`     | 2025-10-27 23:16:48     | `0x268956b6`|
| Hoodi        |    `54016`       |     `1762955544`     | 2025-11-12 13:52:24     | `0x23aa1351`|
| Mainnet      |   `419072`       |     `1767747671`     | 2026-01-07 01:01:11     | `0x07c9462e`|

## Rationale

This Meta EIP provides a global view of all changes included in the Fusaka network upgrade, as well as links to full specification.

## Security Considerations

None.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 01 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7607</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7607</guid>
      </item>
    
      <item>
        <title>Decrease base cost of TLOAD/TSTORE</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7609-reduce-transient-storage-pricing/18435</comments>
        
        <description>## Abstract

Decrease the base cost of TLOAD/TSTORE while introducing a superlinear pricing model. This increases the efficiency of TLOAD/TSTORE for common use cases, while providing a pricing model to prevent DoS vectors.

## Motivation

[EIP-1153](/EIPs/EIPS/eip-1153) introduces a new storage region, termed &quot;transient storage&quot;. It behaves like storage (word-addressed and persists between call frames), but unlike storage it is wiped at the end of each transaction. During development of EIP-1153, the pricing was set to be the same as warm storage loads and stores. This was for two reasons: conceptual simplicity of the EIP, and it also addressed concerns about two related DoS vectors: being able to allocate too much transient storage, and the cost of rolling back state in the case of reverts.

One of the most important use cases that EIP-1153 enables is cheap reentrancy protection. In fact, if transient storage is cheap enough for the first few slots, reentrancy protection can be enabled by default at the language level without too much burden to users, while simultaneously preventing the largest—and most expensive—class of smart contract vulnerabilities.

Furthermore, it seems that transient storage is fundamentally overpriced. Its pricing does not interact with refunds, it only requires a new allocation on contract load (as opposed to memory, which requires a fresh allocation on every call), and has no interaction with the physical database.

This EIP proposes a pricing model which charges additional gas per allocation, which is cheaper for common cases (fewer than ~95 slots are written per contract), while making DoS using transient storage prohibitively expensive.

## Specification

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

The gas cost for `TLOAD` is proposed to be 5 gas. The gas cost for `TSTORE` is proposed to be 8 gas + `expansion_cost`, where `expansion_cost` is calculated as `1 gas * len(transient storage mapping)` if the key is not yet in the transient storage mapping, and otherwise 0 gas.

In pseudo-code:

```python
G_LOW = 5
G_MID = 8

SLOPE = 1

def gas_tload(_key):
    return G_LOW

def gas_tstore(key, transient_mapping):
    cost = G_MID
    if key not in transient_mapping:
        cost += SLOPE * transient_mapping.size()
    return cost
```

## Rationale

### Gas

In benchmarking, `TLOAD` was found to cost a similar amount of CPU time as `MUL`, while `TSTORE` was found to cost about 1.5x that. The values `G_low` and `G_mid` were therefore chosen for `TLOAD` and `TSTORE`, respectively.

## Backwards Compatibility

No backward compatibility issues found.

## Security Considerations

The maximum number of transient slots which can be allocated on a single contract given 30m gas is approximately 7,739 (solution to `x(x-1)/2*1 + 8*x = 30_000_000`), which totals 248KB.

The maximum number of transient slots which can be allocated in a transaction if you use the strategy of calling new contracts (which each are designed to maximize transient storage allocation) once the cost of `TSTORE` is more than the cost of calling a cold contract (2600 gas), can be solved for as follows:

```
solve for SLOPE * &lt;num slots&gt; == 2600, =&gt; num_slots == 2600
gas_used_by_contract = 2600 + SLOPE * num_slots * (num_slots - 1) / 2 + G_MID * num_slots == 3402100
block_gas_limit = 30_000_000
num_calls_per_txn = block_gas_limit // gas_used_by_contract ~= 8.8
max_transient_slots = num_calls_per_txn * num_slots == 22927
```

Thus, the maximum number of transient slots which can be allocated in a single transaction with this method is roughly 23,000, which totals 736KB. Compared to the current gas schedule (which allows allocating approximately `30_000_000 / 100 * 32 == 9.6MB` worth of memory), this is a net *reduction* in the total memory which can be allocated on a client using transient storage, so this EIP presents a stronger bound on the resources which can be used by transient storage. As a comparison point, the total amount of memory which can be allocated on a client by `SSTORE`s in a given transaction is `30_000_000 / 20_000 * 32`, or 48KB.

Note that this cap scales linearly with the gas limit, which is a useful property when considering future block gas limit increases.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 01 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7609</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7609</guid>
      </item>
    
      <item>
        <title>Revert creation in case of non-empty storage</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-revert-creation-in-case-of-non-empty-storage/18452</comments>
        
        <description>## Abstract

This EIP causes contract creation to throw an error when attempted at an address with pre-existing storage.

## Specification

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

If a contract creation is attempted due to a creation transaction, the `CREATE` opcode, the `CREATE2` 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.

This EIP amends [EIP-684](/EIPs/EIPS/eip-684) with one extra condition, requiring empty storage for contract deployment.

This EIP will not affect [EIP-7702](/EIPs/EIPS/eip-7702), since the authority&apos;s nonce is always incremented after an authorization is applied, which conflicts with the condition required for contract deployment.

## Rationale

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 [EIP-161](/EIPs/EIPS/eip-161) 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.

## Backwards Compatibility

This is an execution layer upgrade, and so it requires a hard fork.

## Test Cases

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.

Refilling the existing tests will provide sufficient coverage for this EIP.

## Security Considerations

This EIP is a security upgrade: it enforces the immutability of deployed code.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Verkle state transition via an overlay tree</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/ethereum-state-trie-format-change-using-an-overlay/4165</comments>
        
        <description>## Abstract

This EIP proposes a method to switch the state tree tree format from hexary Merkle Patricia Tree (MPT) to a Verkle Tree (VKT): the MPT tree is frozen, and new writes to the state are stored in a VKT “laid over” the hexary MPT. The historical MPT state is left untouched and its eventual migration is handled at a later time.

## Motivation

The Ethereum state is growing, and VKTs offer a good mitigation strategy to stem this growth and enable weak statelessness. Owing to the difficulty of translating contracts with large storage while they are being accessed, proposals for migrating the current MPT state are complex and will require client teams to undergo a long process of refactoring their code to handle this conversion.

The bigger the state, the longer any conversion process will take. This has an impact both while the conversion is happening, as well as when full-syncing the chain if the conversion is part of consensus. Fullsync is used extensively by core dev teams to test the performance of new code. A conversion longer than a month will impact the release schedule of client teams who typically release at this rate. Nodes that cannot follow the conversion will need to wait longer to rejoin. The conversion will also make reorgs slower, so reducing its duration is desirable.

This current proposal suggests to stop the MPT state growth in its tracks by activating a new “overlay” VKT, that all new state updates are written to. The “base” MPT is frozen in place, until all execution clients are ready to perform the full transition. Data is read first from the overlay tree, and if not found there, from the MPT.

Whenever the block that freeze the MPT is finalized, internal node data can be deleted, in order to free up disk space.

## Specification

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

### Constants

| Parameter   | value | Description                                  |
| ----------- | ----- | -------------------------------------------- |
| `FORK_TIME` | `TBD` | Time at which the overlay tree is activated. |

### Helper functions

```python3
# Determine if `block` is the fork activation block
def is_fork_block(block):
    return block.parent.timestamp &lt; FORK_TIME &amp;&amp; block.timestamp &gt;= FORK_TIME
    
# Write an account in the verkle tree
def verkle_set_account(tree: VerkleTree, key: Bytes32, account: Optional[Account]):
    if account is not None:
        basicdata = bytes(0) # Version
        basicdata += bytes(4) # Reserved
        basicdata += len(account.code).to_bytes(3, &apos;big&apos;)
        basicdata += account.nonce.to_bytes(8, &apos;big&apos;)
        basicdata += account.balance.to_bytes(16, &apos;big&apos;)
        tree.set(key, basicdata)
        ckkey = key
        ckkey[31] = CODEHASH_LEAF_KEY
        tree.set(ckkey, account.code_hash)

# Reads an account from the verkle tree
def verkle_get_account(tree: VerkleTree, key: Bytes32) -&gt; Optional[Account]:
    basicdata_leaf = tree.get(key)
    if basicdata_leaf is not None:
        cs = int.from_bytes(basicdata_leaf[5:8], &apos;big&apos;)
        nonce = int.from_bytes(basicdata_leaf[8:16], &apos;big&apos;)
        balance = int.from_bytes(basicdata_leaf[16:32], &apos;big&apos;)
        ckkey = key
        ckkey[31] = CODEHASH_LEAF_KEY
        ck = tree.get(ckkey)
        cskey = key
        cskey[31] = CODE_SIZE_LEAF_KEY
        cs = tree.get(cskey)
        account = Account(0, balance, nonce, ck, cs)

    return account
```

### Changes to the execution spec

In the execution spec, modify the `State` class as such:

```python3
@dataclass
class State:
    &quot;&quot;&quot;
    Contains all information that is preserved between transactions.
    &quot;&quot;&quot;

    _main_trie: Trie[Address, Optional[Account]] = field(
        default_factory=lambda: Trie(secured=True, default=None)
    )
    _storage_tries: Dict[Address, Trie[Bytes, U256]] = field(
        default_factory=dict
    )
    _snapshots: List[
        Tuple[
            Trie[Address, Optional[Account]], Dict[Address, Trie[Bytes, U256]]
        ]
    ] = field(default_factory=list)
    _created_accounts: Set[Address] = field(default_factory=set)

    # Added in this EIP
    _overlay_tree: VerkleTree[Address, Bytes32]
```

And the state access functions are modified as such:

```python3
def get_account_optional(state: State, address: Address) -&gt; Optional[Account]:
    account = verkle_get_account(state._overlay_tree, get_tree_key_for_version(addr))
    if account is not None:
        return account
    
    return trie_get(state._main_trie, address)

def set_account(state: State, address: Address, account: Optional[Account]) -&gt; None:
    verkle_set_account(state._overlay_tree, get_tree_key_for_nonce(addr), account)

def get_storage(state: State, address: Address, key: Bytes) -&gt; U256:
    value = state._overlay_tree.get(get_tree_key_for_storage_slot(addr, slot))
    if value is not None:
        return value
        
    trie = state._storage_tries.get(address)
    if trie is None:
        return U256(0)

    value = trie_get(trie, key)

    assert isinstance(value, U256)
    return value

def set_storage(
    state: State, address: Address, key: Bytes, value: U256
) -&gt; None:
    state._overlay_tree.set(get_tree_key_for_storage_slot(addr, slot), value)
```

Add the following function which is used when storing a contract in the tree:

```python3
def state_set_codechunk(state: State, addr: Address, chunk_num: int, chunk: Bytes):
    state._overlay_tree.set(get_tree_key_for_code_chunk(addr, chunk_num), chunk)
```

### Changes to the block header

At `FORK_TIME` the block header state root is changed from the MPT root to the VKT root.

## Rationale

This approach doesn&apos;t convert the state, which is left to a subsequent EIP. This is meant as a stopgap in case we decide to push the conversion itself to a later time. It has the advantage of simplicity, which means that the Verge fork could happen at the same time as other, simpler EIPs. It also requires no change at the consensus layer.

## Backwards Compatibility

No backward compatibility issues found.

## Test Cases

&lt;!--
  This section is optional for non-Core EIPs.

  The Test Cases section should include expected input/output pairs, but may include a succinct set of executable tests. It should not include project build files. No new requirements may be introduced here (meaning an implementation following only the Specification section should pass all tests here.)
  If the test suite is too large to reasonably be included inline, then consider adding it as one or more files in `../assets/eip-####/`. External links will not be allowed

  TODO: Remove this comment before submitting
--&gt;

## Reference Implementation

 * `transition-post-genesis` branch in `github.com/gballet/go-ethereum` implements this when setting `--override.overlay-stride=0` on the command line.

## Security Considerations

&lt;!--
  All EIPs must contain a section that discusses the security implications/considerations relevant to the proposed change. Include information that might be important for security discussions, surfaces risks and can be used throughout the life cycle of the proposal. For example, include security-relevant design decisions, concerns, important discussions, implementation-specific guidance and pitfalls, an outline of threats and risks and how they are being addressed. EIP submissions missing the &quot;Security Considerations&quot; section will be rejected. An EIP cannot proceed to status &quot;Final&quot; without a Security Considerations discussion deemed sufficient by the reviewers.

  The current placeholder is acceptable for a draft.

  TODO: Remove this comment before submitting
--&gt;

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 25 Jan 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7612</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7612</guid>
      </item>
    
      <item>
        <title>Puppet Proxy Contract</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7613-puppet-proxy-contract/18482</comments>
        
        <description>## Abstract

A puppet is a contract that, when called, acts like an empty account. It doesn&apos;t do anything and it has no API, except when it is called by the address that deployed it. In that case, it delegates the call to the address passed to it in calldata. This gives the deployer the ability to execute any logic they want in the context of the puppet.

## Motivation

A puppet can be used as an alternative account of its deployer. It has a different address, so it has a separate set of asset balances. This enables sophisticated accounting, e.g. each user of a protocol can get their own address where assets can be sent and stored. The user may call the protocol contract, which in turn will deploy a new puppet and consider it assigned to the user. If the puppet is deployed under a predictable address, e.g. by using the user&apos;s address as the CREATE2 salt, the puppet may not even need to be deployed before funds are sent to its address. From now on the protocol will consider all the assets sent to the puppet as owned by the user. If the protocol needs to move the funds out from the puppet address, it can call the puppet ordering it to delegate to a function transferring the assets to arbitrary addresses, or making arbitrary calls triggering approved transfers to other contracts.

Puppets can be used as an alternative to approved transfers when loading funds into the protocol. Any contract and any wallet can transfer the funds to the puppet address assigned to the user without making any approvals or calling the protocol contracts. Funds can be loaded across multiple transactions and potentially from multiple sources. To funnel funds from another protocol, there&apos;s no need for integration in the 3rd party contracts as long as they are capable of transferring funds to an arbitrary address. Wallets limited to plain [ERC-20](/EIPs/EIPS/eip-20) transfers and stripped of any web3 functionality can be used to load funds into the protocol. The users of the fully featured wallets don&apos;t need to sign opaque calldata blobs that may be harmful or approve the protocol to take their tokens, they only need to make a transfer, which is a simple process with a familiar UX. When the funds are already stored in the puppet assigned to the user, somebody needs to call the protocol so it&apos;s notified that the funds were loaded. Depending on the protocol and its API this call may or may not be permissionless potentially making the UX even more convenient with gasless transactions or 3rd parties covering the gas cost. Some protocols don&apos;t need the users to specify what needs to be done with the loaded funds or they allow the users to configure that in advance. Most of the protocols using approved transfers to load funds may benefit from using the puppets.

The puppet&apos;s logic doesn&apos;t need to be ever upgraded. To change its behavior the deployer needs to change the address it passes to the puppet to delegate to or the calldata it passes for delegation. The entire fleet of puppets deployed by a single contract can be upgraded by upgrading the contract that deployed them, without using beacons. A nice trick is that the deployer can make the puppet delegate to the address holding the deployer&apos;s own logic, so the puppet&apos;s logic is encapsulated in the deployer&apos;s.

A puppet is unable to expose any API to any caller except the deployer. If a 3rd party needs to be able to somehow make the puppet execute some logic, it can&apos;t be requested by directly calling the puppet. Instead, the deployer needs to expose a function that if called by the 3rd parties, will call the puppet, and make it execute the desired logic. Mechanisms expecting contracts to expose some APIs don&apos;t work with puppet, e.g. [ERC-721](/EIPs/EIPS/eip-721)&apos;s `safeTransfer`s.

This standard defines the puppet as a blob of bytes used as creation code, which enables integration with many frameworks and codebases written in variety of languages. The specific tooling is outside of the scope of this standard, but it should be easy to create the libraries and helpers necessary for usage in practice. All the implementations will be interoperable because they will be creating identical puppets and if CREATE2 is used, they will have deterministic addresses predictable by all implementations.

Because the puppet can be deployed under a predictable address despite having no fixed logic, in some cases it can be used as a CREATE3 alternative. It can be also used as a full replacement of the CREATE3 factory by using a puppet deployed using CREATE2 to deploy arbitrary code using plain CREATE.

Deploying a new puppet is almost as cheap as deploying a new clone proxy. Its whole deployed bytecode is 66 bytes, and its creation code is 62 bytes. Just like clone proxy, it can be deployed using just the Solidity scratch space in memory. The cost to deploy a puppet is 45K gas, only 4K more than a clone. Because the bytecode is not compiled, it can be reliably deployed under a predictable CREATE2 address regardless of the compiler version.

## Specification

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

To delegate, the deployer must prepend the calldata with an ABI-encoded address to delegate to.
All the data after the address will be passed verbatim as the delegation calldata.
If the caller isn&apos;t the deployer, the calldata is shorter than 32 bytes, or it doesn&apos;t start with
an address left-padded with zeros, the puppet doesn&apos;t do anything.
This lets the deployer make a plain native tokens transfer to the puppet,
it will have an empty calldata, and the puppet will accept the transfer without delegating.

The puppet is deployed with this creation code:
```
0x604260126D60203D3D3683113D3560A01C17733D3360147F331817604057823603803D943D373D3D355AF43D82803E903D91604057FD5BF36034525252F3
```

The bytecode breakdown:
```
// The creation code.
// [code 1] and [code 2] are parts of the deployed code,
// placed respectively before and after the deployer&apos;s address.
// | Opcode used    | Hex value     | Stack content after executing
// Code size and offset in memory
// | PUSH1          | 60 42         | 66
// | PUSH1          | 60 12         | 18 66
// The code before the deployer&apos;s address and where it&apos;s stored in memory
// | PUSH14         | 6D [code 1]   | [code 1] 18 66
// | RETURNDATASIZE | 3D            | 0 [code 1] 18 66
// The deployer&apos;s address and where it&apos;s stored in memory
// | CALLER         | 33            | [deployer] 0 [code 1] 18 66
// | PUSH1          | 60 14         | 20 [deployer] 0 [code 1] 18 66
// The code after the deployer&apos;s address and where it&apos;s stored in memory
// | PUSH32         | 7F [code 2]   | [code 2] 20 [deployer] 0 [code 1] 18 66
// | PUSH1          | 60 34         | 52 [code 2] 20 [deployer] 0 [code 1] 18 66
// Return the entire code
// | MSTORE         | 52            | 20 [deployer] 0 [code 1] 18 66
// | MSTORE         | 52            | 0 [code 1] 18 66
// | MSTORE         | 52            | 18 66
// | RETURN         | F3            |

// The deployed code.
// `deployer` is the deployer&apos;s address.
// | Opcode used    | Hex value     | Stack content after executing
// Push some constants
// | PUSH1          | 60 20         | 32
// | RETURNDATASIZE | 3D            | 0 32
// | RETURNDATASIZE | 3D            | 0 0 32
// Do not delegate if calldata shorter than 32 bytes
// | CALLDATASIZE   | 36            | [calldata size] 0 0 32
// | DUP4           | 83            | 32 [calldata size] 0 0 32
// | GT             | 11            | [do not delegate] 0 0 32
// Do not delegate if the first word of calldata is not a zero-padded address
// | RETURNDATASIZE | 3D            | 0 [do not delegate] 0 0 32
// | CALLDATALOAD   | 35            | [first word] [do not delegate] 0 0 32
// | PUSH1          | 60 A0         | 160 [first word] [do not delegate] 0 0 32
// | SHR            | 1C            | [first word upper bits] [do not delegate] 0 0 32
// | OR             | 17            | [do not delegate] 0 0 32
// Do not delegate if not called by the deployer
// | PUSH20         | 73 [deployer] | [deployer] [do not delegate] 0 0 32
// | CALLER         | 33            | [sender] [deployer] [do not delegate] 0 0 32
// | XOR            | 18            | [sender not deployer] [do not delegate] 0 0 32
// | OR             | 17            | [do not delegate] 0 0 32
// Skip to the return if should not delegate
// | PUSH1          | 60 40         | [success branch] [do not delegate] 0 0 32
// | JUMPI          | 57            | 0 0 32
// Calculate the payload size
// | DUP3           | 82            | 32 0 0 32
// | CALLDATASIZE   | 36            | [calldata size] 32 0 0 32
// | SUB            | 03            | [payload size] 0 0 32
// Copy the payload from calldata
// | DUP1           | 80            | [payload size] [payload size] 0 0 32
// | RETURNDATASIZE | 3D            | 0 [payload size] [payload size] 0 0 32
// | SWAP5          | 94            | 32 [payload size] [payload size] 0 0 0
// | RETURNDATASIZE | 3D            | 0 32 [payload size] [payload size] 0 0 0
// | CALLDATACOPY   | 37            | [payload size] 0 0 0
// Delegate call
// | RETURNDATASIZE | 3D            | 0 [payload size] 0 0 0
// | RETURNDATASIZE | 3D            | 0 0 [payload size] 0 0 0
// | CALLDATALOAD   | 35            | [delegate to] 0 [payload size] 0 0 0
// | GAS            | 5A            | [gas] [delegate to] 0 [payload size] 0 0 0
// | DELEGATECALL   | F4            | [success] 0
// Copy return data
// | RETURNDATASIZE | 3D            | [return size] [success] 0
// | DUP3           | 82            | 0 [return size] [success] 0
// | DUP1           | 80            | 0 0 [return size] [success] 0
// | RETURNDATACOPY | 3E            | [success] 0
// Return
// | SWAP1          | 90            | 0 [success]
// | RETURNDATASIZE | 3D            | [return size] 0 [success]
// | SWAP2          | 91            | [success] 0 [return size]
// | PUSH1          | 60 40         | [success branch] [success] 0 [return size]
// | JUMPI          | 57            | 0 [return size]
// | REVERT         | FD            |
// | JUMPDEST       | 5B            | 0 [return size]
// | RETURN         | F3            |
```

## Rationale

The main goals of the puppet design are low cost and modularity. It should be cheap to deploy and cheap to interact with. The contract should be self-contained, simple to reason about, and easy to use as an architectural building block.

The puppet behavior could be implemented fairly easily in Solidity with some inline Yul for delegation. This would make the bytecode much larger and more expensive to deploy. It would also be different depending on the compiler version and configuration, so deployments under predictable addresses using CREATE2 would be trickier.

A workaround for the problems with the above solution could be to use the clone proxy pattern to deploy copies of the puppet implementation. It would make the cost to deploy each puppet a little lower than deploying the bytecode proposed in this document, and the addresses of the clones would be predictable when deploying using CREATE2. The downside is that now there would be 1 extra delegation for each call, from the clone proxy to the puppet implementation address, which costs gas. The architecture of such solution is also more complicated with more contracts involved, and it requires the initialization step of deploying the puppet implementation before any clone can be deployed. The initialization step limits the CREATE2 address predictability because the creation code of the clone proxy includes the implementation address, which affects the deployment address.

Another alternative is to use the beacon proxy pattern. Making a Solidity API call safely is a relatively complex procedure that takes up a non-trivial space in the bytecode. To lower the cost of the puppets, the beacon proxy probably should be used with the clone proxy, which would be even more complicated and more expensive to use than the above solutions. Querying a beacon for the delegation address is less flexible than passing it in calldata, it requires updating the state of the beacon to change the address.

## Backwards Compatibility

No backward compatibility issues found.

The puppet bytecode doesn&apos;t use PUSH0, because many chains don&apos;t support it yet.

## Test Cases

Here are the tests verifying that the bytecode and the reference implementation library are working as expected, using the Foundry test tools:

```solidity
pragma solidity ^0.8.0;

import {Test} from &quot;forge-std/Test.sol&quot;;
import {Puppet} from &quot;src/Puppet.sol&quot;;

contract Logic {
    string public constant ERROR = &quot;Failure called&quot;;

    fallback(bytes calldata data) external returns (bytes memory) {
        return abi.encode(data);
    }

    function success(uint256 arg) external payable returns (address, uint256, uint256) {
        return (address(this), arg, msg.value);
    }

    function failure() external pure {
        revert(ERROR);
    }
}

contract PuppetTest is Test {
    address puppet = Puppet.deploy();
    address logic = address(new Logic());

    function logicFailurePayload() internal view returns (bytes memory) {
        return Puppet.delegationCalldata(logic, abi.encodeWithSelector(Logic.failure.selector));
    }

    function call(address target, bytes memory data) internal returns (bytes memory) {
        return call(target, data, 0);
    }

    function call(address target, bytes memory data, uint256 value)
        internal
        returns (bytes memory)
    {
        (bool success, bytes memory returned) = target.call{value: value}(data);
        require(success, &quot;Unexpected revert&quot;);
        return returned;
    }

    function testDeployDeterministic() public {
        bytes32 salt = keccak256(&quot;Puppet&quot;);
        address newPuppet = Puppet.deployDeterministic(salt);
        assertEq(
            newPuppet, Puppet.predictDeterministicAddress(salt, address(this)), &quot;Invalid address&quot;
        );
        assertEq(
            newPuppet, Puppet.predictDeterministicAddress(salt), &quot;Invalid address when no deployer&quot;
        );
        assertEq(newPuppet.code, puppet.code, &quot;Invalid code&quot;);
    }

    function testPuppetDelegates() public {
        uint256 arg = 1234;
        bytes memory data = abi.encodeWithSelector(Logic.success.selector, arg);
        bytes memory payload = Puppet.delegationCalldata(logic, data);
        uint256 value = 5678;

        bytes memory returned = call(puppet, payload, value);

        (address thisAddr, uint256 receivedArg, uint256 receivedValue) =
            abi.decode(returned, (address, uint256, uint256));
        assertEq(thisAddr, puppet, &quot;Invalid delegation context&quot;);
        assertEq(receivedArg, arg, &quot;Invalid argument&quot;);
        assertEq(receivedValue, value, &quot;Invalid value&quot;);
    }

    function testPuppetDelegatesWithEmptyCalldata() public {
        bytes memory payload = Puppet.delegationCalldata(logic, &quot;&quot;);
        bytes memory returned = call(puppet, payload);
        bytes memory data = abi.decode(returned, (bytes));
        assertEq(data.length, 0, &quot;Delegated with non-empty calldata&quot;);
    }

    function testPuppetBubblesRevertPayload() public {
        vm.expectRevert(bytes(Logic(logic).ERROR()));
        call(puppet, logicFailurePayload());
    }

    function testPuppetDoesNothingForNonDeployer() public {
        vm.prank(address(1234));
        call(puppet, logicFailurePayload());
    }

    function testCallingWithCalldataShorterThan32BytesDoesNothing() public {
        address delegateTo = address(uint160(1234) &lt;&lt; 8);
        bytes memory payload = abi.encodePacked(bytes31(bytes32(uint256(uint160(delegateTo)))));
        vm.mockCallRevert(delegateTo, &quot;&quot;, &quot;Logic called&quot;);
        call(puppet, payload);
    }

    function testCallingWithDelegationAddressOver20BytesDoesNothing() public {
        bytes memory payload = logicFailurePayload();
        payload[11] = 0x01;
        call(puppet, payload);
    }

    function testCallingPuppetDoesNothing() public {
        // Forge the calldata, so if puppet uses it to delegate, it will run `Logic.failure`
        uint256 forged = uint256(uint160(address(this))) &lt;&lt; 32;
        forged |= uint32(Logic.failure.selector);
        bytes memory payload = abi.encodeWithSignature(&quot;abc(uint)&quot;, forged);
        call(puppet, payload);
    }

    function testTransferFromDeployerToPuppet() public {
        uint256 amt = 123;
        payable(puppet).transfer(amt);
        assertEq(puppet.balance, amt, &quot;Invalid balance&quot;);
    }

    function testTransferToPuppet() public {
        uint256 amt = 123;
        address sender = address(456);
        payable(sender).transfer(amt);
        vm.prank(sender);
        payable(puppet).transfer(amt);
        assertEq(puppet.balance, amt, &quot;Invalid balance&quot;);
    }
}
```

## Reference Implementation

The puppet bytecode is explained in the specification section. Here&apos;s the example helper library:

```solidity
library Puppet {
    bytes internal constant CREATION_CODE =
        hex&quot;604260126D60203D3D3683113D3560A01C17733D3360147F33181760405782&quot;
        hex&quot;3603803D943D373D3D355AF43D82803E903D91604057FD5BF36034525252F3&quot;;
    bytes32 internal constant CREATION_CODE_HASH = keccak256(CREATION_CODE);

    /// @notice Deploy a new puppet.
    /// @return instance The address of the puppet.
    function deploy() internal returns (address instance) {
        bytes memory creationCode = CREATION_CODE;
        assembly {
            instance := create(0, add(creationCode, 32), mload(creationCode))
        }
        require(instance != address(0), &quot;Failed to deploy the puppet&quot;);
    }

    /// @notice Deploy a new puppet under a deterministic address.
    /// @param salt The salt to use for the deterministic deployment.
    /// @return instance The address of the puppet.
    function deployDeterministic(bytes32 salt) internal returns (address instance) {
        bytes memory creationCode = CREATION_CODE;
        assembly {
            instance := create2(0, add(creationCode, 32), mload(creationCode), salt)
        }
        require(instance != address(0), &quot;Failed to deploy the puppet&quot;);
    }

    /// @notice Calculate the deterministic address for a puppet deployment made by this contract.
    /// @param salt The salt to use for the deterministic deployment.
    /// @return predicted The address of the puppet.
    function predictDeterministicAddress(bytes32 salt) internal view returns (address predicted) {
        return predictDeterministicAddress(salt, address(this));
    }

    /// @notice Calculate the deterministic address for a puppet deployment.
    /// @param salt The salt to use for the deterministic deployment.
    /// @param deployer The address of the deployer of the puppet.
    /// @return predicted The address of the puppet.
    function predictDeterministicAddress(bytes32 salt, address deployer)
        internal
        pure
        returns (address predicted)
    {
        bytes32 hash = keccak256(abi.encodePacked(hex&quot;ff&quot;, deployer, salt, CREATION_CODE_HASH));
        return address(uint160(uint256(hash)));
    }

    function delegationCalldata(address delegateTo, bytes memory data)
        internal
        pure
        returns (bytes memory payload)
    {
        return abi.encodePacked(bytes32(uint256(uint160(delegateTo))), data);
    }
}
```

## Security Considerations

The bytecode is made to resemble clone proxy&apos;s wherever it makes sense to simplify auditing.

ABI-encoding the delegation address protects the deployer from being tricked by a 3rd party into calling the puppet and making it delegate to an arbitrary address. Such scenario would only be possible if the deployer called on the puppet a function with the selector `0x00000000`, which as of now doesn&apos;t come from any reasonably named function.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 04 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7613</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7613</guid>
      </item>
    
      <item>
        <title>Atomic Push-based Data Feed Among Contracts</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7615-smart-contract-data-push-mechanism/18466</comments>
        
        <description>## Abstract
This ERC proposes a push-based mechanism for sending data, allowing publisher contract to automatically push certain data to subscriber contracts during a call. The specific implementation relies on two interfaces: one for publisher contract to push data, and another for the subscriber contract to receive data. When the publisher contract is called, it checks if the called function corresponds to subscriber addresses. If it does, the publisher contract push data to the subscriber contracts.

## Motivation
Currently, there are many keepers rely on off-chain data or seperate data collection process to monitor the events on chain. This proposal aims to establish a system where the publisher contract can atomicly push data to inform subscriber contracts about the updates. The direct on-chain interaction bewteen the publisher and the subscriber allows the system to be more trustless and efficient. 

This proposal will offer significant advantages across a range of applications, such as enabling the boundless and permissionless expansion of DeFi, as well as enhancing DAO governance, among others. 

### Lending Protocol

An example of publisher contract could be an oracle, which can automatically push the price update through initiating a call to the subscriber protocol. The lending protocol, as the subscriber, can automatically liquidate the lending positions based on the received price.

### Automatic Payment

A service provider can use a smart contract as a publisher contract, so that when a user call this contract, it can push the information to the subsriber contracts, such as, the users&apos; wallets like NFT bound accounts that follows [ERC-6551](/EIPs/EIPS/eip-6551) or other smart contract wallets. The user&apos;s smart contract wallet can thus perform corresponding payment operations automatically. Compared to traditional `approve` needed approach, this solution allows more complex logic in implementation, such as limited payment, etc.

### PoS Without Transferring Assets

For some staking scenarios, especially NFT staking, the PoS contract can be set as the subscriber and the NFT contracts can be set as the publisher. Staking can thus achieved through contracts interation, allowing users to earn staking rewards without transferring assets.

When operations like `transfer` of NFT occur, the NFT contract can push this information to the PoS contract, which can then perform unstaking or other functions.

### DAO Voting

The DAO governance contract as a publisher could automatically triggers the push mechanism after the vote is completed, calling relevant subscriber contracts to directly implement the voting results, such as injecting funds into a certain account or pool.

## Specification

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.

### Overview

The push mechanism can be divided into the following four steps:

1. The publisher contract is called.
2. The publisher contract query the subscriber list from the `selector` of the function called. The subscriber contract can put the selected data into `inbox`.
3. The publisher contract push `selector` and data through calling `exec` function of the subscriber contract.
4. The subscriber contract executes based on pushed `selector` and data, or it may request information from the publisher contract&apos;s inbox function as needed.

In the second step, the relationship between a called function and the corresponding subscriber can be configured in the publisher contract. Two configuration schemes are proposed:

1. Unconditional Push: Any call to the configured `selector` triggers a push
2. Conditional Push: Only the conditioned calls to the configured `selector` trigger a push based on the configuration.

It&apos;s allowed to configure multiple, different types of subscriber contracts for a single `selector`. The publisher contract will call the `exec` function of each subscriber contract to push the request. 

When unsubscribing a contract from a `selector`, publisher contract MUST check whether `isLocked` function of the subscriber contract returns `true`. 

It is OPTIONAL for a publisher contract to use the `inbox` mechanism to store data.

In the fourth step, the subscriber contract SHOULD handle all possible `selector` requests and data in the implementation of `exec` function. In some cases, `exec` MAY call `inbox` function of publisher contract to obtain the pushed data in full. 


![Workflow](/EIPs/assets/eip-7615/ERC7615.svg)

### Contract interface

As mentioned above, there are Unconditional Push and Conditional Push two types of implementation. To implement Unconditional Push, the publisher contract SHOULD implement the following interface:

```
interface IPushForce {
    event ForceApprove(bytes4 indexed selector, address indexed target);
    event ForceCancel(bytes4 indexed selector, address indexed target);
    event RenounceForceApprove();
    event RenounceForceCancel();

    error MustRenounce();
    error ForceApproveRenounced();
    error ForceCancelRenounced();

    function isForceApproved(bytes4 selector, address target) external returns (bool);
    function forceApprove(bytes4 selector, address target) external;
    function forceCancel(bytes4 selector, address target) external;
    function isRenounceForceApprove() external returns (bool);
    function isRenounceForceCancel() external returns (bool);
    function renounceForceApprove(bytes memory) external;
    function renounceForceCancel(bytes memory) external;
}
```

`isForceApproved` is to query whether `selector` has already unconditionally bound to the subscriber contract with the address `target`. 
`forceApprove` is to bind `selector` to the subscriber contract `target`. `forceCancel` is to cancel the binding relationship between `selector` and `target`, where `isLocked` function of `target` returns `true` is REQUIRED.

`renounceForceApprove` is used to relinquish the `forceApprove` permission. After calling the `renounceForceApprove` function, `forceApprove` can no longer be called. Similarly, `renounceForceCancel` is used to relinquish the `forceCancel` permission. After calling the `renounceForceCancel` function, `forceCancel` can no longer be called.

To implement Conditional Push, the publisher contract SHOULD implement the following interface:

```
interface IPushFree {
    event Approve(bytes4 indexed selector, address indexed target, bytes data);
    event Cancel(bytes4 indexed selector, address indexed target, bytes data);

    function inbox(bytes4 selector) external returns (bytes memory);
    function isApproved(bytes4 selector, address target, bytes calldata data) external returns (bool);
    function approve(bytes4 selector, address target, bytes calldata data) external;
    function cancel(bytes4 selector, address target, bytes calldata data) external;
}
```

`isApproved`, `approve`, and `cancel` have functionalities similar to the corresponding functions in `IPushForce`. However, an additional `data` parameter is introduced here for checking whether a push is needed. 
The `inbox` here is used to store data in case of being called from the subscriber contract.

The publisher contract SHOULD implement `_push(bytes4 selector, bytes calldata data)` function, which acts as a hook. Any function within the publisher contract that needs to implement push mechanism must call this internal function. The function MUST include querying both unconditional and conditional subscription contracts based on `selector` and `data`, and then calling corresponding `exec` function of the subscribers.

A subscriber need to implement the following interface:

```solidity
interface IExec {
    function isLocked(bytes4 selector, bytes calldata data) external returns (bool);
    function exec(bytes4 selector, bytes calldata data) external;
}
```

`exec` is to receive requests from the publisher contracts and further proceed to execute. 
`isLocked` is to check the status of whether the subscriber contract can unsubscribe the publisher contract based on `selector` and `data`. It is triggered when a request to unsubscribe is received. 

## Rationale

### Unconditional and Conditional Configuration

When the sending contract is called, it is possible to trigger a push, requiring the caller to pay the resulting gas fees. 
In some cases, an Unconditional Push is necessary, such as pushing price changes to a lending protocol. While, Conditional Push will reduce the unwanted gas consumption.

### Check `isLocked` Before Unsubscribing

Before `forceCancel` or `cancel`, the publisher contract MUST call the `isLocked` function of the subscriber contract to avoid unilateral unsubscribing. The subscriber contract may have a significant logical dependence on the publisher contract, and thus unsubscription could lead to severe issues within the subscriber contract. Therefore, the subscriber contract should implement `isLocked` function with thorough consideration.

### `inbox` Mechanism

In certain scenarios, the publisher contract may only push essential data with `selector` to the subscriber contracts, while the full data might be stored within `inbox`. Upon receiving the push from the publisher contract, the subscriber contract is optional to call `inbox`. 
`inbox` mechanism simplifies the push information while still ensuring the availability of complete data, thereby reducing gas consumption.

### Using Function Selectors as Parameters

Using function selectors to retrieve the addresses of subscriber contracts allows 
more detailed configuration. 
For the subscriber contract, having the specific function of the request source based on the push information enables more accurate handling of the push information.

### Renounce Safety Enhancement

Both `forceApprove` and `forceCancel` permissions can be relinquished using their respective renounce functions. When both `renounceForceApprove` and `renounceForceCancel` are called, the registered push targets can longer be changed, greatly enhancing security.

## Reference Implementation

```
pragma solidity ^0.8.24;

import {EnumerableSet} from &quot;@openzeppelin/contracts/utils/structs/EnumerableSet.sol&quot;;
import {IPushFree, IPushForce} from &quot;./interfaces/IPush.sol&quot;;
import {IExec} from &quot;./interfaces/IExec.sol&quot;;

contract Foo is IPushFree, IPushForce {
    using EnumerableSet for EnumerableSet.AddressSet;

    bool public override isRenounceForceApprove;
    bool public override isRenounceForceCancel;

    mapping(bytes4 selector =&gt; mapping(uint256 tokenId =&gt; EnumerableSet.AddressSet targets)) private _registry;
    mapping(bytes4 selector =&gt; EnumerableSet.AddressSet targets) private _registryOfAll;
    // mapping(bytes4 =&gt; bytes) public inbox;

    modifier notLock(bytes4 selector, address target, bytes memory data) {
        require(!IExec(target).isLocked(selector, data), &quot;Foo: lock&quot;);
        _;
    }

    function inbox(bytes4 selector) public view returns (bytes memory data) {
        uint256 loadData;
        assembly {
            loadData := tload(selector)
        }

        data = abi.encode(loadData);
    }

    function isApproved(bytes4 selector, address target, bytes calldata data) external view override returns (bool) {
        uint256 tokenId = abi.decode(data, (uint256));
        return _registry[selector][tokenId].contains(target);
    }

    function isForceApproved(bytes4 selector, address target) external view override returns (bool) {
        return _registryOfAll[selector].contains(target);
    }

    function approve(bytes4 selector, address target, bytes calldata data) external override {
        uint256 tokenId = abi.decode(data, (uint256));
        _registry[selector][tokenId].add(target);
    }

    function cancel(bytes4 selector, address target, bytes calldata data)
        external
        override
        notLock(selector, target, data)
    {
        uint256 tokenId = abi.decode(data, (uint256));
        _registry[selector][tokenId].remove(target);
    }

    function forceApprove(bytes4 selector, address target) external override {
        if (isRenounceForceApprove) revert ForceApproveRenounced();
        _registryOfAll[selector].add(target);
    }

    function forceCancel(bytes4 selector, address target) external override notLock(selector, target, &quot;&quot;) {
        if (isRenounceForceCancel) revert ForceCancelRenounced();
        _registryOfAll[selector].remove(target);
    }

    function renounceForceApprove(bytes memory data) external override {
        (bool burn) = abi.decode(data, (bool));
        if (burn != true) {
            revert MustRenounce();
        }

        isRenounceForceApprove = true;
        emit RenounceForceApprove();
    }

    function renounceForceCancel(bytes memory data) external override {
        (bool burn) = abi.decode(data, (bool));
        if (burn != true) {
            revert MustRenounce();
        }

        isRenounceForceCancel = true;
        emit RenounceForceCancel();
    }

    function send(uint256 message) external {
        _push(this.send.selector, message);
    }

    function _push(bytes4 selector, uint256 message) internal {
        assembly {
            tstore(selector, message)
        }

        address[] memory targets = _registry[selector][message].values();
        for (uint256 i = 0; i &lt; targets.length; i++) {
            IExec(targets[i]).exec(selector, abi.encode(message));
        }

        targets = _registryOfAll[selector].values();
        for (uint256 i = 0; i &lt; targets.length; i++) {
            IExec(targets[i]).exec(selector, abi.encode(message));
        }
    }
}

contract Bar is IExec {
    event Log(bytes4 indexed selector, bytes data, bytes inboxData);

    function isLocked(bytes4, bytes calldata) external pure override returns (bool) {
        return true;
    }

    function exec(bytes4 selector, bytes calldata data) external {
        bytes memory inboxData = IPushFree(msg.sender).inbox(selector);

        emit Log(selector, data, inboxData);
    }
}
```

## Security Considerations

### `exec` Attacks

The `exec` function is `public`, therefore, it is vulnerable to malicious calls where arbitrary push information can be inserted. Implementations of `exec` should carefully consider the arbitrariness of calls and should not directly use data passed by the exec function without verification.

### Reentrancy Attack

The publisher contract&apos;s call to the subscriber contract&apos;s `exec` function could lead to reentrancy attacks. Malicious subscription contracts might construct reentrancy attacks to the publisher contract within `exec`.

### Arbitrary Target Approve

Implementation of `forceApprove` and `approve` should have reasonable access controls; otherwise, unnecessary gas losses could be imposed on callers.

Check the gas usage of the `exec` function.

### isLocked implementation

Subscriber contracts should implement the `isLocked` function to avoid potential loss brought by unsubscription. This is particularly crucial for lending protocols implementing this proposal. Improper unsubscription can lead to abnormal clearing, causing considerable losses. 

Similarly, when subscribing, the publisher contract should consider whether `isLocked` is properly implemented to prevent irrevocable subscriptions. 

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 03 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7615</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7615</guid>
      </item>
    
      <item>
        <title>Chunk support for ERC-5219 mode in Web3 URL</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-5219-resolve-mode/14088</comments>
        
        <description>## Abstract

In the context of the [ERC-6860](/EIPs/EIPS/eip-6860) `web3://` standard, this ERC extends the [ERC-6944](/EIPs/EIPS/eip-6944) resolve mode: This standard defines a new optional ``web3-next-chunk`` HTTP header returned by the `request()` call, that contains a `web3://` URL pointing to the next data chunk of the resource data. Chunks are streamed to the `web3://` client, and it loops until the ``web3-next-chunk`` header is no longer present.

## Motivation

Ethereum RPC endpoints have a gas limit, which can be reached when serving large content. By adding a chunking feature, we add the possibility to serve arbitrary sized content.

## Specification

In the [ERC-6944](/EIPs/EIPS/eip-6944) resolve mode, this standard introduces the new optional ``web3-next-chunk`` HTTP header, to be returned in the `headers` `KeyValue` array of the `request()` method defined in [ERC-6944](/EIPs/EIPS/eip-6944).

The value of the header is either a complete `web3://` URL, or a relative one. The target smart contract must use the [ERC-6944](/EIPs/EIPS/eip-6944) resolve mode.

When processing the result of the initial `request()` call, the protocol return the HTTP status code, HTTP headers and body right away to the `web3://` client. If a ``web3-next-chunk`` header is present, it parse the URL. If the URL is invalid, or the target smart contract is not using the [ERC-6944](/EIPs/EIPS/eip-6944) resolve mode, the HTTP data streaming is ended with an error. Otherwise it call the `request()` method, ignore the returned `statusCode`, send the `body` data as the next chunk of data, and if a ``web3-next-chunk`` header is again present, loops until no more are present.

## Rationale

The use of a header pointing to the next chunk was chosen because it does not require changes to the [ERC-6944](/EIPs/EIPS/eip-6944) `request()` interface, and the use of a `web3://` URL in the header add flexibility to the means to provide the next chunk.

## Security Considerations

No security considerations were found.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 08 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7617</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7617</guid>
      </item>
    
      <item>
        <title>Content encoding in ERC-5219 mode Web3 URL</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-5219-resolve-mode/14088</comments>
        
        <description>## Abstract

In the context of the [ERC-6860](/EIPs/EIPS/eip-6860) `web3://` standard, this ERC extends the [ERC-6944](/EIPs/EIPS/eip-6944) resolve mode: This standard specifies that if a `Content-Encoding` header is returned by the `request()` call, then the returned data is decoded if necessary according to the specified algorithm before being returned to the client.

## Motivation

As storage in blockchains is expensive, it is optimal to try to store and serve compressed assets. Standard HTTP uses the `Accept-Encoding`/`Content-Encoding` mechanism, in which the client specifies their supported compression algorithms, and the server returns the data compressed in one of them. It is not optimal to replicate this mechanism in the `web3://` protocol, due to blockchain storage and computation constraints. Moreover, it is not possible to blindly serve content with a fixed `Content-Encoding` header, because the HTTP client may not implement the compression algorithm.

By specifying a list of supported compression algorithms, optionally doing the decompression at the protocol side and serving the data to the client, we can safely store compressed data and serve it.

## Specification

In the [ERC-6944](/EIPs/EIPS/eip-6944) resolve mode, this standard indicates that if a ``Content-Encoding`` HTTP header (in the returned `headers` `KeyValue` array of the `request()` method) is provided, and if it is not part of the supported algorithms provided by the client in the ``Accept-Encoding`` header, or the client did not provide an ``Accept-Encoding`` header, then the protocol MUST decode the content before forwarding it to the `web3://` client.

The protocol MUST support the following content encodings: `gzip`, `br` (brotli). If the protocol is to decode the content, and if the advertized ``Content-encoding`` is not part of this list, an error indicating an unsupported content encoding MUST be sent to the client. Once decoded, the decompressed data is sent to the client. The ``Content-Encoding`` header MUST NOT be forwarded to the client when the protocol decodes the content.

## Rationale

We add this feature to the [ERC-6944](/EIPs/EIPS/eip-6944) resolve mode because it can be added without changes the interface.
To stay as close as possible to standard HTTP, we don&apos;t introduce a new HTTP header but reuse the known `Content-Encoding` header.

## Security Considerations

No security considerations were found.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 08 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7618</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7618</guid>
      </item>
    
      <item>
        <title>Precompile Falcon512 generic verifier</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/falcon-512-precompiled-generic-signature-verifier/18569</comments>
        
        <description>## Abstract

Include a precompiled signature verification function using Falcon-512. Falcon-512 is a candidate for standardization by the National Institute of Standards and Technology (NIST) and is quantum resistant with security level I.

## Motivation

The advent of quantum computing threatens blockchain protocols and networks because they utilize non-quantum resistant cryptographic algorithms. When quantum computers become robust enough to run Shor’s algorithm (a quantum algorithm to find the prime factors of an integer) on a large scale, the most used asymmetric algorithms, utilized for digital signatures and message encryption, such as RSA, (EC)DSA, and (EC)DH, will be no longer secure. Quantum computers will be able to break them within a short period of time. Today, there are hundreds of billions of dollars denominated in cryptocurrencies and other digital assets that rely on blockchain ledgers as well as thousands of blockchain-based applications storing value in blockchain networks. Cryptocurrencies and blockchain-based applications require solutions that guarantee quantum resistance in order to preserve the integrity of data and assets in these public and immutable ledgers. Most proposals for quantum-resistant blockchain networks are theoretical, require large QKD (quantum key distribution, a secure communication method that implements a cryptographic protocol involving components of quantum mechanics) networks, or propose new quantum-resistant blockchain protocols to be built from scratch. This EIP is pioneer in proposing a solution compatible with current EVM blockchain protocols. It presents a simple mechanism to add a NIST-compliant post-quantum signature to blockchain transactions, making them quantum-resistant even when ECC (elliptic curve cryptography) cryptography becomes vulnerable against attacks by quantum computers. We have developed a Solidity implementation for the on-chain verification of this signatures, which does not scale due to the required high amount of gas. This is why **this EIP is proposing a pre-compiled smart contract** that allows to verify post-quantum signatures in a scalable manner.

## Specification

A clean implementation for Falcon-512 algorithm was brought from the PQClean project.

The precompiled signature verification function runs at address `0x65`. The required inputs are:

- `public key` - Falcon Public key of 897 bytes
- `signature` - 666 bytes (max size)
- `message` - an arbitrary number of bytes representing the message that was signed


Those inputs are encoded according to:

```
[pubkey:897 bytes][signature:666 bytes][message: remainder]
```

Output is:

- `result` -
  A successful signature verification returns `0000000000000000000000000000000000000000000000000000000000000001`, otherwise `0000000000000000000000000000000000000000000000000000000000000000` indicating all other failure cases where sufficient gas has been provided.

The precompile will only revert in the case where insufficient gas has been provided. Data format errors, size errors, and invalid signatures will not cause the precompile to revert.

```
  {
    Input:         &quot;&quot;,
    Gas:           10,
    ExpectedError: &quot;out of gas&quot;,
    Name:          &quot;empty input, too little gas&quot;,
  },
  {
    Input:         &quot;111111110000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000006e0&quot;,
    Gas:           1000000,
    Result:        &quot;000000000000000000000000000000000000000000000000000000000000000000000000&quot;,
    Name:          &quot;garbled input&quot;,
  }
```

### Example Usage in Solidity

The precompile can be wrapped in Solidity to provide a more development-friendly interface to `Falcon-512` signature verification.

```solidity
  function verify(
        bytes calldata publicKey,
        bytes calldata signature,
        bytes calldata message
    ) public returns (bool isValid) {
        (bool success, bytes memory verifies) = address(0x0000000000000000000000000000000000000065)
            .staticcall(
                abi.encodePacked(
                    publicKey,
                    signature,
                    message
                )
            );
        require(success &amp;&amp; verifies.length == 32, &quot;Invalid signature&quot;);
        return verifies[31] == 1;
    }
```

### Gas costs

Since data size is variable, each operation to execute the precompiled call will require:

- 1465 base units of gas for each operation.
- 6 units of gas for each word contained in the payload.
  These values are based on results presented at the [benchmarks](#benchmarks) section.

## Rationale

Falcon-512 is a good candidate for a new signature implementation. Key sizes in Falcon-512 are relatively small compared to other post-quantum signature algorithms.

The following table shows a summary of the typical values for keys and the approximate amount of time taken per second to execute signature verifications as specified by the authors of Falcon algorithm:


| **variant** | **verify/s** | **pub size(bytes)** | **sig size(bytes)** |
| ----------- | ------------ | ------------------- | ------------------- |
| Falcon512   |      27933.0 |                 897 |                 666 |


Falcon uses shake256 under the hood, an implementation made in solidity showed it is not viable to implement this algorithm at that layer, on the other hand the implementation of falcon-512 by using precompiles turned to be the best approach since the gas cost (as shown in the previous section) is relatively low.

Implementing just the signature verification is sufficiently enough to open a wide range of use cases at the smart contract level. To give an example, this method can perfectly work with the Account Abstraction concept, where the authentication process would rely on Falcon and the account is a smart contract.

### benchmarks

Assuming ecRecover precompile is perfectly priced, a set of benchmarks were executed comparing Falcon-512 signature verification function precompile with ecRecover precompile. For benchmarks, it was used 2.6 GHz Intel Core i7 64-bit machine.

```sh
$ cat /proc/cpuinfo | grep &quot;model name&quot;
Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz
```

#### 5 seconds benchmark

Based on [100 test vectors with valid signatures](/EIPs/assets/eip-7619/bench_vectors) a benchmark of 5 seconds, for each test vector, was performed, considering the following:

- the average time per operation (ns/op),
- each vector size increases in 33 bytes
- Ecrecover is well tested

Benchmark results [here](/EIPs/assets/eip-7619/benchmark_results)

Then the 100 BenchmarkPrecompiledFalcon512 results were approximated to a linear equation dependent on the number of bytes in each test vector. From the approximation it was concluded that 1465 units of gas is the base requirement for any falcon-512 signature validation and 6 gas per word is additionally required.

## Backwards Compatibility

There is very little risk of breaking backwards-compatibility with this EIP, the sole issue being if someone were to build a contract relying on the address at `0x65` being empty. The likelihood of this is low, and should specific instances arise, the address could be chosen to be any arbitrary value with negligible risk of collision.

## Test Cases

- A set of test vectors, with valid signatures, for benchmarking on new implementations is located in a separate [file](/EIPs/assets/eip-7619/bench_vectors)

- A set of test vectors, with invalid data, to verify some invalid signature cases is located in a separate [file](/EIPs/assets/eip-7619/invalid_signature_test_vectors)

## Security Considerations

Since the scope of this proposal is encapsulated at the contract level for verifying signatures it doesn&apos;t represent issues in regards to security.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 03 Jul 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7619</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7619</guid>
      </item>
    
      <item>
        <title>EOF Contract Creation</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7620-eof-contract-creation-instructions/18625</comments>
        
        <description>## Abstract

EVM Object Format (EOF) removes the possibility to create contracts using `CREATE` or `CREATE2` instructions. We introduce a new/replacement method in form of pair of instructions : `EOFCREATE` and `RETURNCODE` to provide a way to create contracts using EOF containers.

## Motivation

This EIP uses terminology from the [EIP-3540](/EIPs/EIPS/eip-3540) which introduces the EOF format.

EOF aims to remove code observability, which is a prerequisite to legacy EVM contract creation logic using legacy-style create transactions, `CREATE` or `CREATE2`, because both the initcode and code are available to the EVM and can be manipulated. On the same premise, EOF removes opcodes like `CODECOPY` and `EXTCODECOPY`, introducing EOF subcontainers as a replacement to cater for factory contracts creating other contracts.

The new instructions introduced in this EIP operate on EOF containers enabling factory contract use case that legacy EVM has.

## Specification

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

Wherever not explicitly listed, the rules of EOF contract creation, as well as the `EOFCREATE` instruction, should be identical or analogous to those of `CREATE2` instruction. This includes but is not limited to:

- behavior on `accessed_addresses` and address collision ([EIP-684](/EIPs/EIPS/eip-684) and [EIP-2929](/EIPs/EIPS/eip-2929))
- EVM execution frame created for the `EOFCREATE` initcode - memory, account context etc.
- nonce bumping of the account of newly created contract [EIP-161](/EIPs/EIPS/eip-161)
- balance checking and transfer for the creation endowment (`value` argument)
    
### Parameters

| Constant | Value |
| - | - |
| `TX_CREATE_COST` | Defined as `32000` in the [Ethereum Execution Layer Specs](https://github.com/ethereum/execution-specs/blob/0f9e4345b60d36c23fffaa69f70cf9cdb975f4ba/src/ethereum/shanghai/fork_types.py#L42) |
| `STACK_DEPTH_LIMIT` | Defined as `1024` in the [Ethereum Execution Layer Specs](https://github.com/ethereum/execution-specs/blob/0f9e4345b60d36c23fffaa69f70cf9cdb975f4ba/src/ethereum/shanghai/vm/interpreter.py#L60) |
| `GAS_CODE_DEPOSIT` | Defined as `200` in the [Ethereum Execution Layer Specs](https://github.com/ethereum/execution-specs/blob/0f9e4345b60d36c23fffaa69f70cf9cdb975f4ba/src/ethereum/shanghai/vm/gas.py#L44) |
| `MAX_CODE_SIZE` | Defined as `24576` in [EIP-170](/EIPs/EIPS/eip-170) |

We introduce two new instructions on the same block number [EIP-3540](/EIPs/EIPS/eip-3540) is activated on:

1. `EOFCREATE` (`0xec`)
2. `RETURNCODE` (`0xee`)

If the code is legacy bytecode, any of these instructions result in an *exceptional halt*. (*Note: This means no change to behaviour.*)

### Execution Semantics

- The instructions `CREATE`, `CREATE2` are made obsolete and rejected by validation in EOF contracts. They are only available in legacy contracts.
- If instructions `CREATE` and `CREATE2` have EOF code as initcode (starting with `EF00` magic)
    - deployment fails (returns 0 on the stack)
    - caller&apos;s nonce is not updated and gas for initcode execution is not consumed

In the context of legacy bytecode execution any of these instructions (`EOFCREATE`, `RETURNCODE`) result in an *exceptional halt*. (*Note: This means no change to behaviour.*)

#### Overview of the new contract creation flow

In EOF EVM, new bytecode is introduced to the state by means of `InitcodeTransaction` delivering an EOF container (`initcontainer`). Such a container may include arbitrarily deeply nesting subcontainers. The `initcontainer` and its subcontainers are recursively validated according to all the validation rules applicable for the EOF version in question. Next, the 0th code section of the `initcontainer` is executed and may eventually call a `RETURNCODE` instruction, which will refer to a subcontainer to be finally deployed to an address.

`InitcodeTransactions` are defined in detail in [EIP-7873](/EIPs/EIPS/eip-7873).

`EOFCREATE` instruction is in turn a replacement of the `CREATE` and `CREATE2` legacy instructions allowing factory contracts to create other contracts. The main difference to the `InitcodeTransaction` is that the `initcontainer` is selected to be one of the subcontainers of the EOF container calling `EOFCREATE` (and not one of `transaction.initcodes`). It is worth noting that no validation is performed at this point, as it has already been done when the factory contract containing `EOFCREATE` was deployed.

Details on each instruction follow in the next sections.

#### `EOFCREATE`

- deduct `TX_CREATE_COST` gas
- halt with exceptional failure if the current frame is in `static-mode`.
- read immediate operand `initcontainer_index`, encoded as 8-bit unsigned value
- pop `salt`, `input_offset`, `input_size`, `value` from the operand stack
- perform (and charge for) memory expansion using `[input_offset, input_size]`
- load initcode EOF subcontainer at `initcontainer_index` in the container from which `EOFCREATE` is executed
    - let `initcontainer` be that EOF container
- check that current call depth is below `STACK_DEPTH_LIMIT` and that caller balance is enough to transfer `value`
  - in case of failure return 0 on the stack, caller&apos;s nonce is not updated and gas for initcode execution is not consumed.
- caller&apos;s memory slice `[input_offset:input_size]` is used as calldata
- execute the container and deduct gas for execution. The 63/64th rule from [EIP-150](/EIPs/EIPS/eip-150) applies.
- increment `sender` account&apos;s nonce
- calculate `new_address` as `keccak256(0xff || sender32 || salt)[12:]`, where `sender32` is the sender address left-padded to 32 bytes with zeros
- an unsuccessful execution of initcode results in pushing `0` onto the stack
    - can populate returndata if execution `REVERT`ed
- a successful execution ends with initcode executing `RETURNCODE{deploy_container_index}(aux_data_offset, aux_data_size)` instruction (see below). After that:
    - load deploy EOF subcontainer at `deploy_container_index` in the container from which `RETURNCODE` is executed
    - concatenate data section with `(aux_data_offset, aux_data_offset + aux_data_size)` memory segment and update data size in the header if needed.
    - if updated deploy container size exceeds `MAX_CODE_SIZE` instruction exceptionally aborts
    - set `state[new_address].code` to the updated deploy container
    - push `new_address` onto the stack
- deduct `GAS_CODE_DEPOSIT * deployed_code_size` gas

#### `RETURNCODE`

- read immediate operand `deploy_container_index`, encoded as 8-bit unsigned value
- pop two values from the operand stack: `aux_data_offset`, `aux_data_size` referring to memory section that will be appended to deployed container&apos;s data
- cost 0 gas + possible memory expansion for aux data
- ends initcode frame execution and returns control to EOFCREATE caller frame where `deploy_container_index` and `aux_data` are used to construct deployed contract (see above)
- instruction exceptionally aborts if after the appending, data section size would overflow the maximum data section size or underflow (i.e. be less than data section size declared in the header)

### Code Validation

We extend code section validation rules (as defined in [EIP-3670](/EIPs/EIPS/eip-3670)).

1. `EOFCREATE` `initcontainer_index` must be less than `num_container_sections`
2. `EOFCREATE` the subcontainer pointed to by `initcontainer_index` must have its `len(data_section)` equal `data_size`, i.e. data section content is exactly as the size declared in the header (see [Data section lifecycle](#data-section-lifecycle))
3. `EOFCREATE` the subcontainer pointed to by `initcontainer_index` must not contain either a `RETURN` or `STOP` instruction
4. `RETURNCODE` `deploy_container_index` must be less than `num_container_sections`
5. `RETURNCODE` the subcontainer pointed to `deploy_container_index` must not contain a `RETURNCODE` instruction
6. It is an error for a container to contain both `RETURNCODE` and either of `RETURN` or `STOP`
7. It is an error for a subcontainer to never be referenced in its parent container
8. It is an error for a given subcontainer to be referenced by both `RETURNCODE` and `EOFCREATE`
9. `RJUMP`, `RJUMPI` and `RJUMPV` immediate argument value (jump destination relative offset) validation: code section is invalid in case offset points to the byte directly following either `EOFCREATE` or `RETURNCODE` instruction.

### Data Section Lifecycle

**For an EOF container which has not yet been deployed**, the `data_section` is only a portion of the final `data_section` after deployment.
Let&apos;s define it as `pre_deploy_data_section` and as `pre_deploy_data_size` the `data_size` declared in that container&apos;s header.
`pre_deploy_data_size &gt;= len(pre_deploy_data_section)`, which anticipates more data to be appended to the `pre_deploy_data_section` during the process of deploying.

```
pre_deploy_data_section
|                                      |
\___________pre_deploy_data_size______/
```

**For a deployed EOF container**, the final `data_section` becomes:

```
pre_deploy_data_section | static_aux_data | dynamic_aux_data
|                         |             |                  |
|                          \___________aux_data___________/
|                                       |                  |
\___________pre_deploy_data_size______/                    |
|                                                          |
\________________________data_size_______________________/
```

where:
    
- `aux_data` is the data which is appended to `pre_deploy_data_section` on `RETURNCODE` instruction.
- `static_aux_data` is a subrange of `aux_data`, which size is known before `RETURNCODE` and equals `pre_deploy_data_size - len(pre_deploy_data_section)`.
- `dynamic_aux_data` is the remainder of `aux_data`.

`data_size` in the deployed container header is updated to be equal `len(data_section)`.

Summarizing, there are `pre_deploy_data_size` bytes in the final data section which are guaranteed to exist before the EOF container is deployed and `len(dynamic_aux_data)` bytes which are known to exist only after.
This impacts the validation and behavior of data-section-accessing instructions: `DATALOAD`, `DATALOADN`, and `DATACOPY`, see [EIP-7480](/EIPs/EIPS/eip-7480).

## Rationale

### Data section appending

The data section is appended to during contract creation and also its size needs to be updated in the header. Alternative designs were considered, where:

- additional section kinds for the data were introduced
- additional fields describing a subcontainer were introduced
- data section would be written over as opposed to being appended to, requiring it to be filled with 0 bytes prior to deployment
    
All of these alternatives either complicated the otherwise simple data structures or took away useful features (like the dynamically sized portion of the data section).

### `keccak256(initcontainer)` in the `new_address` hashing scheme

`new_address = keccak256(0xff || sender || salt || keccak256(initcontainer))[12:]` was originally proposed as the way to calculate the address of newly created contract, similar, but not exactly equal, to what `CREATE2` uses.

This alternative however goes against code non-observability, because it locks in the contents of the initcontainer e.g. preventing re-writing it in some future upgrade. It also seems unnecessarily expensive: `EOFCREATE` can only pick up one of its subcontainers, yet the hash value would need to be recalculated on every execution of `EOFCREATE`.

Other ways of removing code observability, yet keeping some form of witness of the code, were considered. However, keeping only `sender` and `salt` allows the implementer of the factory contract (i.e. one containing the `EOFCREATE` instruction) to include the code witness via the `salt` anyway, if that&apos;s necessary for the particular use case. Therefore, keeping the `new_address` formula minimal is the most flexible approach with better separation of concerns.

Leaving the `keccak256(initcontainer)` out of the `new_address` hash has also the benefit of making the `new_address` independent of the metadata section (proposed for the EOF in a separate EIP), which is a desired property. Unfortunately, if a factory wants to opt into committing to a particular `initcontainer`, it needs to include it in the `salt`, and that will include the metadata section.

### `EOFCREATE` stack argument order

`EXT*CALL` instructions from [EIP-7069](/EIPs/EIPS/eip-7069) have had their stack argument order changed, as compared to that of legacy instructions `*CALL`. We follow the same change to have `EOFCREATE` stack arg order match those of `EXTCALL`.

## Backwards Compatibility

This change poses no risk to backwards compatibility, as it is introduced at the same time EIP-3540 is. The new instructions are not introduced for legacy bytecode (code which is not EOF formatted), and the contract creation options do not change for legacy bytecode.

`CREATE` and `CREATE2` calls with `EF00` initcode fail early without executing the initcode. Previously, in both cases the initcode execution would begin and fail on the first undefined instruction `EF`.

## Test Cases

Creation transaction, `CREATE` and `CREATE2` cannot have its *code* starting with `0xEF`, but such cases are covered already in [EIP-3541](/EIPs/EIPS/eip-3541). However, new cases must be added where `CREATE` or `CREATE2` have its *initcode* being (validly or invalidly) EOF formatted:

| Initcode | Expected result |
| - | - |
| `0xEF` | initcode starts execution and fails |
| `0xEF01` | initcode starts execution and fails |
| `0xEF5f` | initcode starts execution and fails |
| `0xEF00` | `CREATE` / `CREATE2` fails early, returns 0 and keeps sender nonce intact |
| `0xEF0001` | as above |
| valid EOFv1 container | as above |

## Security Considerations

It is the EOF `InitcodeTransaction` (specified in [EIP-7873](/EIPs/EIPS/eip-7873)) which needs a detailed review and discussion as that is where external unverified code enters the state. Among others:

1. Is its complexity under control, ruling out any DoS attempts
2. Is it correctly priced and always charged for
3. Is the validation comprehensive and not allowing problematic code to be saved into the state

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 12 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7620</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7620</guid>
      </item>
    
      <item>
        <title>Basket Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7621-basket-token-revised/28050</comments>
        
        <description>## Abstract

This standard defines a multi-asset basket token that extends [ERC-20](/EIPs/EIPS/eip-20). A basket holds a set of [ERC-20](/EIPs/EIPS/eip-20) constituent tokens at configurable target weights. The basket contract itself is the share token: holders of the basket&apos;s [ERC-20](/EIPs/EIPS/eip-20) supply have a proportional claim on its underlying reserves. A designated owner, identified via [ERC-173](/EIPs/EIPS/eip-173), has authority to rebalance the basket&apos;s composition.

## Motivation

[ERC-4626](/EIPs/EIPS/eip-4626) standardized single-asset vaults for yield-bearing tokens. [ERC-7575](/EIPs/EIPS/eip-7575) extended that model to multi-asset vault entry points while preserving ERC-4626 semantics. However, neither standard addresses manager-rebalanced, weighted basket share tokens, where a designated owner actively adjusts the constituent set and target allocations over time.

There is no standard specifically for this use case. Every protocol that implements a weighted basket (tokenized index funds, portfolio products, treasury diversification vehicles) uses a custom interface, which creates additional integration work for wallets, aggregators, and DeFi protocols that support such baskets.

This standard provides a common interface for weighted, manager-rebalanced baskets: contributing assets, withdrawing proportionally, querying composition and target weights, and rebalancing. Unlike vault standards that primarily standardize asset entry and exit, this standard treats portfolio composition itself (constituent membership and target weights) as standardized, queryable state. Because the basket contract is itself an [ERC-20](/EIPs/EIPS/eip-20) token, basket shares are compatible with existing ERC-20 infrastructure.

## Specification

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

### Definitions

- **Basket:** A collection of [ERC-20](/EIPs/EIPS/eip-20) tokens held at specified target weights, managed as a single unit.
- **Constituent:** An [ERC-20](/EIPs/EIPS/eip-20) token held within a basket.
- **Weight:** A constituent&apos;s target allocation in basis points (10000 = 100%). Weights are targets; actual reserves MAY diverge from weights at any time.
- **Reserve:** The quantity of a constituent recognized by the basket for accounting purposes. This is the value returned by `getReserve()` and MAY differ from the raw `balanceOf(address(this))` if the implementation uses internal accounting.
- **Owner:** The address returned by [ERC-173](/EIPs/EIPS/eip-173)&apos;s `owner()`, with management authority over the basket.

### Interface

A conforming contract MUST implement [ERC-20](/EIPs/EIPS/eip-20) and the [ERC-20](/EIPs/EIPS/eip-20) metadata extensions (`name()`, `symbol()`, and `decimals()`), [ERC-165](/EIPs/EIPS/eip-165), [ERC-173](/EIPs/EIPS/eip-173), and the following interface. The contract&apos;s [ERC-20](/EIPs/EIPS/eip-20) supply represents shares, a proportional claim on the basket&apos;s reserves. Each contract manages exactly one basket. Implementations MAY additionally implement [EIP-2612](/EIPs/EIPS/eip-2612) for gasless approvals.

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.20;

/// @title ERC-7621 Basket Token Standard
/// @dev See https://eips.ethereum.org/EIPS/eip-7621
///      Conforming contracts MUST also implement IERC20, IERC165, and IERC173.
interface IERC7621 {

    // --- Errors ---

    /// @dev Array lengths do not match.
    error LengthMismatch(uint256 expected, uint256 actual);

    /// @dev Weights do not sum to 10000.
    error InvalidWeights(uint256 weightSum);

    /// @dev Amount is zero where a non-zero value is required.
    error ZeroAmount();

    /// @dev Token is not a constituent of the basket.
    error NotConstituent(address token);

    /// @dev Slippage tolerance exceeded on share minting.
    error InsufficientShares(uint256 minimum, uint256 actual);

    /// @dev Slippage tolerance exceeded on constituent withdrawal.
    error InsufficientAmount(uint256 index, uint256 minimum, uint256 actual);

    /// @dev Duplicate constituent token address.
    error DuplicateConstituent(address token);

    /// @dev Constituent address is the zero address.
    error ZeroAddress();

    // --- Events ---

    /// @notice MUST be emitted when assets are contributed to the basket.
    /// @param caller The address that called `contribute`.
    /// @param receiver The address that received the minted shares.
    /// @param lpAmount The number of shares minted.
    /// @param amounts The constituent token amounts deposited.
    event Contributed(
        address indexed caller,
        address indexed receiver,
        uint256 lpAmount,
        uint256[] amounts
    );

    /// @notice MUST be emitted when shares are burned and assets withdrawn.
    /// @param caller The address that called `withdraw`.
    /// @param receiver The address that received the constituent tokens.
    /// @param lpAmount The number of shares burned.
    /// @param amounts The constituent token amounts returned.
    event Withdrawn(
        address indexed caller,
        address indexed receiver,
        uint256 lpAmount,
        uint256[] amounts
    );

    /// @notice MUST be emitted when the constituent set or weights change.
    /// @param newTokens The new constituent token addresses.
    /// @param newWeights The new target weights in basis points.
    event Rebalanced(address[] newTokens, uint256[] newWeights);

    // --- View Functions ---

    /// @notice Returns the constituent tokens and their target weights.
    /// @dev The ordering of the returned arrays is stable between calls to
    ///      `rebalance`. The `amounts` arrays in `contribute`, `withdraw`,
    ///      and their preview counterparts MUST follow this same ordering.
    /// @return tokens Constituent addresses.
    /// @return weights Target weights in basis points, summing to 10000.
    function getConstituents()
        external view returns (address[] memory tokens, uint256[] memory weights);

    /// @notice Returns the number of constituents.
    /// @return count The number of constituent tokens.
    function totalConstituents() external view returns (uint256 count);

    /// @notice Returns the accounted reserve balance of a constituent.
    /// @dev Returns the reserve recognized by the basket for share accounting,
    ///      which MAY differ from `IERC20(token).balanceOf(address(this))`.
    /// @param token The constituent token address.
    /// @return balance The accounted reserve of `token`.
    function getReserve(address token) external view returns (uint256 balance);

    /// @notice Returns the target weight of a specific constituent.
    /// @dev MUST revert with `NotConstituent` if `token` is not a constituent.
    /// @param token The constituent token address.
    /// @return weight The target weight in basis points.
    function getWeight(address token) external view returns (uint256 weight);

    /// @notice Returns whether an address is a current constituent.
    /// @param token The token address to check.
    /// @return True if `token` is a constituent.
    function isConstituent(address token) external view returns (bool);

    /// @notice Returns the total basket value in the implementation&apos;s accounting unit.
    /// @dev The accounting unit and valuation method are implementation-defined
    ///      but MUST be deterministic and consistent with `previewContribute`.
    ///      The returned value is only meaningful within this implementation&apos;s
    ///      accounting model and MUST NOT be assumed comparable across
    ///      different basket implementations.
    /// @return value The total basket value in the implementation&apos;s unit.
    function totalBasketValue() external view returns (uint256 value);

    // --- Actions ---

    /// @notice Deposits constituent tokens and mints shares to `receiver`.
    /// @dev The caller MUST have approved this contract to spend the required
    ///      amounts of each constituent prior to calling.
    ///      `amounts` MUST be ordered to match `getConstituents`.
    ///      MUST emit `Contributed`.
    ///      MUST revert with `LengthMismatch` if `amounts.length` does not
    ///      equal `totalConstituents()`.
    ///      MUST revert with `ZeroAmount` if all amounts are zero.
    ///      MUST revert with `InsufficientShares` if shares minted is less
    ///      than `minShares`.
    ///      Shares minted MUST be monotonically non-decreasing with respect
    ///      to amounts contributed — contributing more MUST NOT yield fewer shares.
    ///      When rounding, MUST round shares minted down (favoring the basket).
    /// @param amounts Ordered array of constituent token amounts to deposit.
    /// @param receiver The address that will receive minted shares.
    /// @param minShares Minimum acceptable shares to mint. Reverts if not met.
    /// @return lpAmount Shares minted.
    function contribute(uint256[] calldata amounts, address receiver, uint256 minShares)
        external returns (uint256 lpAmount);

    /// @notice Burns shares and transfers proportional reserves to `receiver`.
    /// @dev MUST emit `Withdrawn`.
    ///      MUST revert with `ZeroAmount` if `lpAmount` is zero.
    ///      MUST revert if the caller holds fewer than `lpAmount` shares.
    ///      MUST revert with `LengthMismatch` if `minAmounts.length` does not
    ///      equal `totalConstituents()`.
    ///      MUST revert with `InsufficientAmount` if any returned amount is
    ///      less than the corresponding entry in `minAmounts`.
    ///      For each constituent: `amount_i = reserve_i * lpAmount / totalSupply`,
    ///      rounding down (favoring the basket).
    ///      Shares MUST be burned before constituent tokens are transferred out.
    /// @param lpAmount The number of shares to burn.
    /// @param receiver The address that will receive constituent tokens.
    /// @param minAmounts Minimum acceptable amounts per constituent. Reverts if not met.
    /// @return amounts Constituent amounts returned, ordered by `getConstituents`.
    function withdraw(uint256 lpAmount, address receiver, uint256[] calldata minAmounts)
        external returns (uint256[] memory amounts);

    /// @notice Updates the constituent set and target weights.
    /// @dev MUST revert if caller is not `owner()` per ERC-173.
    ///      MUST revert with `LengthMismatch` if array lengths differ.
    ///      MUST revert with `InvalidWeights` if weights do not sum to 10000.
    ///      MUST revert with `DuplicateConstituent` if `newTokens` contains duplicates.
    ///      MUST revert with `ZeroAddress` if any entry in `newTokens` is `address(0)`.
    ///      MUST emit `Rebalanced`.
    ///      The standardized effect of this function is updating the constituent
    ///      set and target weights. Any reserve realignment (swaps) is an
    ///      implementation concern and MUST NOT be inferred by integrators
    ///      from this call alone.
    /// @param newTokens The new ordered set of constituent token addresses.
    /// @param newWeights The new ordered set of target weights in basis points.
    function rebalance(address[] calldata newTokens, uint256[] calldata newWeights)
        external;

    // --- Preview Functions ---

    /// @notice Estimates shares that would be minted for given amounts.
    /// @dev MUST return the same value as `contribute` would return if called
    ///      in the same transaction. MUST NOT revert except for invalid inputs.
    ///      MUST NOT vary by caller. MUST round down.
    ///      MUST use the same valuation function as `contribute`.
    /// @param amounts Ordered array of constituent token amounts.
    /// @return lpAmount Estimated shares that would be minted.
    function previewContribute(uint256[] calldata amounts)
        external view returns (uint256 lpAmount);

    /// @notice Estimates constituent amounts returned for burning shares.
    /// @dev MUST return the same value as `withdraw` would return if called
    ///      in the same transaction. MUST NOT revert except for invalid inputs.
    ///      MUST round down.
    /// @param lpAmount The number of shares to simulate burning.
    /// @return amounts Estimated constituent amounts, ordered by `getConstituents`.
    function previewWithdraw(uint256 lpAmount)
        external view returns (uint256[] memory amounts);
}
```

The `IERC7621` interface identifier is `0xc9c80f73`. Implementations MUST return `true` for this identifier via [ERC-165](/EIPs/EIPS/eip-165). Implementations MUST also return `true` for the [ERC-173](/EIPs/EIPS/eip-173) interface identifier (`0x7f5828d0`).

### Ownership

Basket ownership MUST conform to [ERC-173](/EIPs/EIPS/eip-173). The address returned by `owner()` is the only address authorized to call `rebalance`. Transferring ownership via `transferOwnership(address)` MUST emit the [ERC-173](/EIPs/EIPS/eip-173) `OwnershipTransferred` event. Implementations SHOULD also emit `OwnershipTransferred(address(0), initialOwner)` at contract creation, per ERC-173 convention.

The standard does not prescribe how ownership is implemented internally. An [ERC-721](/EIPs/EIPS/eip-721) token backing the `owner()` return value, a multisig, a governance contract, or a simple storage variable are all valid. Implementations MAY use [ERC-721](/EIPs/EIPS/eip-721) to represent ownership when transferability of management rights on NFT marketplaces is desired.

Share holders&apos; claims MUST NOT be affected by ownership changes.

If ownership is renounced via `transferOwnership(address(0))`, `rebalance` becomes permanently unavailable since no caller can satisfy the `owner()` check. Implementations that wish to prevent permanent lockout SHOULD restrict or override renunciation behavior.

### Weight Encoding

Weights MUST be expressed in basis points (10000 = 100%). The sum of all constituent weights MUST equal 10000. Implementations MUST NOT allow constituents with zero weight; remove them instead.

Weights are informational targets and MUST NOT be assumed to reflect current reserve ratios. Actual reserves MAY diverge from targets between rebalances, during contributions, and during withdrawals. `getConstituents()` returns target weights; `getReserve()` returns accounted reserves recognized by the implementation.

### Constituent Constraints

Constituent token addresses MUST be unique within a basket; duplicates are not permitted. Constituent addresses MUST NOT be `address(0)`. These constraints MUST be enforced during `rebalance` and during initialization.

### Constituent Ordering

The order of constituent tokens returned by `getConstituents()` MUST be stable between calls to `rebalance`. The `amounts` arrays passed to `contribute` and returned by `withdraw` (and their preview counterparts) MUST follow this same ordering. After a `rebalance`, the ordering is determined by the `newTokens` array provided.

### Valuation

Implementations MUST define a deterministic function mapping current reserves to a total basket value, reported by `totalBasketValue()`. Shares minted during contribution MUST be proportional to the value contributed relative to this total. The standard does not prescribe the valuation function (summing reserve balances, querying oracles, and using time-weighted prices are all valid approaches), but the function MUST be deterministic and MUST be the same function used by `previewContribute`.

### Contribution Mechanics

Shares minted MUST be monotonically non-decreasing with respect to amounts contributed; contributing more of any constituent MUST NOT result in fewer shares.

When rounding, implementations MUST round shares minted down (favoring the basket over the contributor). This matches [ERC-4626](/EIPs/EIPS/eip-4626)&apos;s rounding convention.

### Withdrawal Mechanics

Constituent amounts returned during withdrawal MUST be proportional to the shares burned relative to total supply. For each constituent:

```
amount_i = reserve_i * lpAmount / totalSupply
```

When rounding, implementations MUST round amounts down (favoring the basket over the withdrawer).

If `totalSupply()` is zero, `withdraw` MUST revert.

### Initialization

When `totalSupply()` is zero (empty basket), the implementation MUST mint shares according to a deterministic initialization rule. That rule MUST be the same rule used by `previewContribute` in the same state, and MUST NOT vary by caller. Implementations SHOULD document their initialization rule and SHOULD mitigate first-depositor inflation attacks using dead shares, virtual shares, or an equivalent mechanism.

### Edge Cases

- `contribute` with all-zero amounts MUST revert with `ZeroAmount`.
- `withdraw` with zero `lpAmount` MUST revert with `ZeroAmount`.
- `previewContribute` and `previewWithdraw` with zero inputs MUST return zero, not revert.
- `getReserve` for a non-constituent token MUST return zero.
- `getWeight` for a non-constituent token MUST revert with `NotConstituent`.

### Scope and Non-Goals

This standard covers:

- An [ERC-20](/EIPs/EIPS/eip-20) share token representing proportional claims on a managed basket of [ERC-20](/EIPs/EIPS/eip-20) constituents.
- First-class target weights as standardized, queryable state.
- Owner-managed constituent set and weight changes via `rebalance`.
- Multi-asset contribution, proportional withdrawal, and slippage protection.
- Preview functions for user interfaces and integrators.

This standard does not cover:

- Swap execution or routing during rebalancing.
- Oracle design or pricing methodology.
- Fee models (management fees, performance fees, entry/exit fees).
- Cross-implementation value comparability (`totalBasketValue()` is meaningful only within a single implementation&apos;s accounting model).
- Multi-vault or multi-basket lookup registries.
- Externalized share-token architectures (the basket contract IS the share token).

## Rationale

### Relationship to [ERC-4626](/EIPs/EIPS/eip-4626) and [ERC-7575](/EIPs/EIPS/eip-7575)

[ERC-4626](/EIPs/EIPS/eip-4626) standardizes single-asset vaults with `deposit(assets, receiver)` and `withdraw(assets, receiver, owner)`. [ERC-7575](/EIPs/EIPS/eip-7575) extends that model to multi-asset vault entry points while preserving ERC-4626 share semantics. We considered extending either, but manager-rebalanced weighted baskets diverge from both:

- Contributions involve multiple tokens at specified ratios, not a single underlying asset or a set of independent entry points.
- Withdrawals return multiple tokens proportionally, not a single asset.
- Rebalancing (changing the constituent set and weights over time) has no analogue in [ERC-4626](/EIPs/EIPS/eip-4626) or [ERC-7575](/EIPs/EIPS/eip-7575).
- Weights as explicit interface elements (target allocations that an owner actively manages) are not part of either standard.
- The `convertToShares` / `convertToAssets` model assumes a single exchange rate. Baskets have N exchange rates, one per constituent.

A separate standard with a dedicated multi-asset, manager-rebalanced model is more appropriate than overloading existing vault semantics.

That said, we follow ERC-4626&apos;s conventions where they apply: the contract is itself the share token ([ERC-20](/EIPs/EIPS/eip-20)), preview functions provide read-only estimates, rounding favors the contract over the user, and `totalBasketValue()` serves a role analogous to `totalAssets()`.

[ERC-7621](/EIPs/EIPS/eip-7621) is not an alternative implementation of [ERC-4626](/EIPs/EIPS/eip-4626) or [ERC-7575](/EIPs/EIPS/eip-7575). Those standards center vault accounting and asset entry points. [ERC-7621](/EIPs/EIPS/eip-7621) centers managed basket composition as a standardized state surface: constituent membership, target weights, and owner-driven rebalancing are explicit interface elements with no equivalent in either vault standard.

**[ERC-4626](/EIPs/EIPS/eip-4626):** Single underlying asset. Deposit and withdrawal operate on that single asset. No composition state, no composition mutation, no management role. Slippage protection was not included (later addressed by [ERC-5143](/EIPs/EIPS/eip-5143)).

**[ERC-7575](/EIPs/EIPS/eip-7575):** Multiple entry points with a single share token. Per-asset deposit and withdrawal. No composition state, no composition mutation, no management role. No built-in slippage protection.

**[ERC-7621](/EIPs/EIPS/eip-7621):** Multiple constituents with target weights. Composition state is queryable via `getConstituents()`, `getWeight()`, `isConstituent()`. Composition mutation via `rebalance()`, restricted to `owner()` per [ERC-173](/EIPs/EIPS/eip-173). Multi-asset `contribute(amounts[], receiver, minShares)` and proportional multi-asset `withdraw(lpAmount, receiver, minAmounts[])`. Built-in slippage protection via `minShares` and `minAmounts`.

### Ownership via [ERC-173](/EIPs/EIPS/eip-173)

Rather than defining a custom ownership accessor, this standard reuses [ERC-173](/EIPs/EIPS/eip-173) which already standardizes `owner()`, `transferOwnership(address)`, and `OwnershipTransferred`. Registries, wallets, and UIs that recognize ERC-173 will work with basket tokens without custom integration.

The standard does not mandate the internal ownership mechanism. An implementation backed by an [ERC-721](/EIPs/EIPS/eip-721) token can implement `owner()` as `IERC721(nftContract).ownerOf(tokenId)` and `transferOwnership` as an NFT transfer. A simple `Ownable` contract works equally well. This flexibility is important because basket governance varies in practice: single EOAs, multisigs, DAOs, and NFT-based ownership are all in production use.

### Slippage Protection

The `minShares` parameter on `contribute` and `minAmounts` parameter on `withdraw` provide on-chain slippage protection. [ERC-4626](/EIPs/EIPS/eip-4626) omitted these, and [ERC-5143](/EIPs/EIPS/eip-5143) was later created specifically to add them. As with [ERC-5143](/EIPs/EIPS/eip-5143)&apos;s extension of [ERC-4626](/EIPs/EIPS/eip-4626), [ERC-7621](/EIPs/EIPS/eip-7621) includes slippage protection in the base interface because baskets are sensitive to execution drift across multiple assets. Including it avoids the need for a follow-on ERC and makes the interface safer for direct EOA interaction.

### Preview Functions

Following [ERC-4626](/EIPs/EIPS/eip-4626)&apos;s convention, `previewContribute` and `previewWithdraw` provide estimates for display and integration logic. They MUST return values matching what the corresponding action function would return if called in the same transaction, but MAY differ from actual results if state changes between the preview call and the action call.

### Weights as Targets

Weights represent the basket&apos;s intended allocation, not a guarantee about current reserves. After a contribution or withdrawal, actual reserve ratios will differ from target weights. After a `rebalance`, reserves may or may not be realigned depending on the implementation. This is intentional. Mandating immediate reserve alignment would require the standard to specify swap execution, which varies too widely across implementations (AMM routing, off-chain signatures, aggregator calls) to standardize.

### Rebalance Semantics

The standardized effect of `rebalance` is updating the constituent set and target weights. Any reserve realignment (executing swaps to match new weights) is an implementation concern. Integrators MUST NOT assume that a `rebalance` call results in reserves matching the new weights; it may only update targets, with reserve alignment deferred to future contributions and withdrawals, or through a separate implementation-specific mechanism. Accordingly, `rebalance` standardizes changes to intended composition, not execution strategy.

## Backwards Compatibility

This standard introduces a new interface and is not backwards compatible with any existing ERC. It extends [ERC-20](/EIPs/EIPS/eip-20) without modifying it and reuses [ERC-173](/EIPs/EIPS/eip-173) for ownership. Basket tokens are standard [ERC-20](/EIPs/EIPS/eip-20) tokens and work with all existing [ERC-20](/EIPs/EIPS/eip-20) infrastructure.

## Test Cases

Test cases are provided in the assets directory. Key scenarios covered:

- Contribution mints shares proportionally and emits `Contributed` with caller, receiver, amounts
- Contribution reverts with `InsufficientShares` when shares minted is below `minShares`
- Withdrawal burns shares, returns proportional constituents, and emits `Withdrawn` with caller, receiver
- Withdrawal reverts with `InsufficientAmount` when any returned amount is below `minAmounts`
- Withdrawal reverts with `LengthMismatch` when `minAmounts` length mismatches constituents
- Rebalance with duplicate constituent addresses reverts with `DuplicateConstituent`
- Rebalance with zero-address constituent reverts with `ZeroAddress`
- Withdrawal with rounding returns amounts that round down
- Rebalance by `owner()` updates constituents and emits `Rebalanced`
- Rebalance by non-owner reverts
- Rebalance with invalid weight sum reverts with `InvalidWeights`
- Contribution with mismatched array length reverts with `LengthMismatch`
- Zero-amount contribution reverts with `ZeroAmount`
- Zero-amount withdrawal reverts with `ZeroAmount`
- Preview functions return values consistent with action functions
- `getReserve` returns zero for non-constituent tokens
- `getWeight` reverts with `NotConstituent` for non-constituent tokens
- `getConstituents` ordering is stable across calls
- `totalBasketValue` is consistent with `previewContribute`
- `owner()` and `transferOwnership()` conform to [ERC-173](/EIPs/EIPS/eip-173)
- First contribution to empty basket mints shares deterministically
- Ownership renunciation makes `rebalance` permanently unavailable
- Contract creation emits `OwnershipTransferred(address(0), initialOwner)` per [ERC-173](/EIPs/EIPS/eip-173) convention

## Reference Implementation

A minimal reference implementation is provided in the assets directory. It includes:

- `BasketToken.sol` — a single-basket implementation using direct [ERC-20](/EIPs/EIPS/eip-20) token deposits
- `BasketFactory.sol` — a factory for deploying baskets

The reference implementation is intentionally minimal. It does not include swap routing, fee collection, oracle integration, or advanced inflation-attack mitigations. These are production concerns, not interface concerns.

## Security Considerations

### Reentrancy

`contribute`, `withdraw`, and `rebalance` make external calls to [ERC-20](/EIPs/EIPS/eip-20) token contracts. Implementations MUST use reentrancy guards or follow checks-effects-interactions. The `withdraw` function is especially sensitive; shares MUST be burned before constituent tokens are transferred out.

### First-Contributor Manipulation

The first contributor to an empty basket controls the initial share-to-reserve exchange rate and can manipulate it to extract value from subsequent contributors. This is the same inflation attack described in [ERC-4626](/EIPs/EIPS/eip-4626). Implementations SHOULD mint a minimum amount of shares to a dead address on first contribution, or use virtual shares.

### Rebalancing Front-Running

Rebalancing transactions are visible in the mempool and reveal the intended weight changes. If the implementation executes swaps during `rebalance`, those trades will be sandwiched. Implementations that execute swaps during `rebalance` SHOULD use private mempools, commit-reveal schemes, or off-chain routing with signature verification. Enforcing slippage limits on rebalancing swaps is also recommended.

### Owner Trust

Share holders trust the basket owner to rebalance responsibly. The owner can change constituents to illiquid or worthless tokens, or trigger rebalancing at unfavorable prices. This trust assumption is inherent to the model. Implementations MAY add timelocks, governance voting, or maximum-slippage constraints to reduce this trust assumption, but these are not required by the standard.

### Donation Attacks

Tokens sent directly to the basket contract (outside of `contribute`) can skew the relationship between tracked reserves and actual balances. Implementations SHOULD track reserves via internal accounting rather than relying on `balanceOf(address(this))`, and SHOULD ignore tokens received outside the standard contribution flow.

### Fee-on-Transfer and Rebasing Tokens

Baskets that track reserves via internal accounting will desync if a constituent charges transfer fees or rebases. Implementations that allow arbitrary constituents SHOULD check actual received balances after each transfer rather than trusting the transfer amount.

### Poisoned Constituents

A constituent token with blacklist, pause, or other transfer-restriction functionality can freeze basket withdrawals entirely. If any single constituent cannot be transferred out, `withdraw` reverts for all holders. Implementations SHOULD consider maintaining an allowlist of acceptable constituent tokens, or implement a partial-withdrawal mechanism that skips non-transferable constituents.

### Preview Function Safety

`previewContribute` and `previewWithdraw` are manipulable by altering on-chain state (e.g., donating tokens to the basket). They SHOULD NOT be used as price oracles. Integrators that need manipulation-resistant pricing SHOULD use external oracles or time-weighted calculations.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 11 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7621</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7621</guid>
      </item>
    
      <item>
        <title>Increase calldata cost</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7623-increase-calldata-cost/18647</comments>
        
        <description>## Abstract

The current calldata pricing permits EL payloads of up to 7.15 MB, while the average size is much smaller at around 100 KB.
This EIP proposes adjusting the calldata cost to reduce the maximum possible block size and its variance without negatively impacting regular users.
This is achieved by increasing calldata costs for transactions that predominantly post data.

## Motivation

The block gas limit has not been increased since [EIP-1559](/EIPs/EIPS/eip-1559), while the average size of blocks has continuously increased due to the growing number of rollups posting data to Ethereum. Moreover, calldata costs have remained unchanged since [EIP-2028](./eip-2028).
[EIP-4844](/EIPs/EIPS/eip-4844) introduces blobs as a preferred method for data availability (DA).
This transition demands a reevaluation of calldata pricing, especially in order to address the disparity between average and maximum block sizes.
By introducing a floor cost dependent on the ratio of gas spent on EVM operations to calldata, this proposal aims to reduce the maximum block size to make room for additional blobs or potential block gas limit increases.

## Specification

| Parameter                    | Value |
| ---------------------------- | ----- |
| `STANDARD_TOKEN_COST`        | `4`   |
| `TOTAL_COST_FLOOR_PER_TOKEN` | `10`  |

Let `tokens_in_calldata = zero_bytes_in_calldata + nonzero_bytes_in_calldata * 4`.

Let `isContractCreation` be a boolean indicating the respective event.

Let `execution_gas_used` be the gas used for EVM execution with the gas refund subtracted.

Let `INITCODE_WORD_COST` be 2 as defined in [EIP-3860](/EIPs/EIPS/eip-3860).

The current formula for determining the total gas used per transaction (`tx.gasUsed`) is equivalent to:

```python
tx.gasUsed = (
    21000
    + STANDARD_TOKEN_COST * tokens_in_calldata
    + execution_gas_used
    + isContractCreation * (32000 + INITCODE_WORD_COST * words(calldata))
)
```

The formula for determining the gas used per transaction changes to:

```python
tx.gasUsed = (
    21000
    +
    max(
        STANDARD_TOKEN_COST * tokens_in_calldata
        + execution_gas_used
        + isContractCreation * (32000 + INITCODE_WORD_COST * words(calldata)),
        TOTAL_COST_FLOOR_PER_TOKEN * tokens_in_calldata
    )
)
```

Any transaction with a gas limit below `21000 + TOTAL_COST_FLOOR_PER_TOKEN * tokens_in_calldata` 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 `gasUsed` will be below this floor price, but the floor price needs to be reserved in the transaction gas limit.

## Rationale

The current maximum EL payload size is approximately 1.79 MB (`30_000_000/16`). It is possible to create payloads filled with zero bytes that expand to 7.15 MB. However, since blocks are typically compressed with Snappy at the P2P layer, zero-byte-heavy EL payloads generally compress to under 1.79 MB. The implementation of [EIP-4844](/EIPs/EIPS/eip-4844) increased the maximum possible compressed block size to approximately 2.54 MB.

This proposal aims to increase the cost of calldata to 10/40 gas for transactions that do not exceed a certain threshold of gas spent on EVM operations relative to gas spent on calldata. This change will significantly reduce the maximum block size by limiting the size of data-heavy transactions that can fit into a single block. By increasing calldata costs from 4/16 to 10/40 gas per byte, for data-heavy transactions this EIP aims to reduce the possible EL payload size to approximately 0.72 MB (`30_000_000/40`) without affecting the majority of users. Other adversarial block constructions can have a non-compressible EL payload size of approximately 1.26MiB.

Notably, regular users (e.g. sending ETH/Tokens/NFTs, engaging in DeFi, social media, restaking, bridging, etc.), who do not use calldata predominantly for DA, may remain unaffected.
The calldata cost for transactions involving significant EVM computation remains at 4/16 gas per byte, so those transactions are unaffected.

## Backwards Compatibility

This is a backwards incompatible gas repricing that requires a scheduled network upgrade.

Wallet developers and node operators MUST update gas estimation handling to accommodate the new calldata cost rules. Specifically:

1. **Wallets**: Wallets using `eth_estimateGas` MUST be updated to ensure that they correctly account for the `TOTAL_COST_FLOOR_PER_TOKEN` parameter. Failure to do so could result in underestimating gas, leading to failed transactions.

2. **Node Software**: RPC methods such as `eth_estimateGas` MUST incorporate the updated formula for gas calculation. Node developers MUST ensure compatibility with the updated calldata pricing logic.

Users can maintain their usual workflows without modification, as wallet and RPC updates will handle these changes.

## Security Considerations

As the maximum possible block size is reduced, no security concerns have been raised.

In some cases, it might seem advantageous to combine two transactions into one to reduce costs. For example, bundling a transaction that relies heavily on calldata but minimally on EVM resources with another that does the opposite. However, this is not a significant concern for several reasons:

1. This type of bundling is already possible today. Merging multiple transactions can save the 21,000 gas cost for each additional transaction beyond the first, a feature explicitly supported in [ERC-4337](/EIPs/EIPS/eip-4337).
2. Such bundling does not compromise the block size reduction objectives of this EIP.
3. In practice, transaction bundling is often impractical due to challenges such as trust and coordination requirements.

These factors ensure that transaction bundling does not pose a significant issue.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 13 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7623</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7623</guid>
      </item>
    
      <item>
        <title>Secure Messaging Protocol</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7627-secure-messaging-protocol/18761</comments>
        
        <description>## Abstract

This proposal implements the capability to securely exchange encrypted messages on-chain. Users can register their public keys and encryption algorithms by registration and subsequently send encrypted messages to other users using their addresses. The interface also includes enumerations for public key algorithms and a structure for user information to support various encryption algorithms and user information management.

## Motivation

With the emergence of Layer 2 chains featuring sub-second block times and the introduction of account abstraction, the use of end-to-end encrypted communication has facilitated the proliferation of real-time communication and online chat dApps. Providing a unified interface enables easy integration of encrypted communication into smart contracts, thereby fostering innovation. Standardization promotes interoperability, facilitating seamless communication across platforms. 

## Specification

### Objectives

- Provide a standardized interface for implementing messaging systems in smart contracts, including user registration and message sending functionalities.
- Enhance flexibility and scalability for messaging systems by defining enumerations for public key algorithms and a structure for user information.
- Define events for tracking message sending to enhance the observability and auditability of the contract.
- Using a custom sessionId allows messages to be organized into a conversation.
- Encrypt message content using the recipient&apos;s public key during message transmission.

### Interface

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

Implementers of this standard **MUST** have all of the following functions:

``` solidity
pragma solidity ^0.8.0;

interface IERC7627 {

    enum PublicKeyAlgorithm { ECDSA, ED25519, X25519 }

    struct PublicKey {
        bytes public_key; 
        uint64 valid_before;
        PublicKeyAlgorithm algorithm; 
    }
    
    // Events
	/**
     * @notice Event emitted when a message is sent between users.
     * @param from The address of the sender
     * @param to The address of the recipient
     * @param keyIndex The index of the public key used to encrypt the message
     * @param sessionId The session ID for the communication
     * @param encryptedMessage The encrypted message in bytes
	*/
    event MessageSent(address indexed from, address indexed to, bytes32 indexed keyIndex, bytes32 sessionId, bytes encryptedMessage);

	/**
     * @notice Event emitted when a user&apos;s public key is updated.
     * @param user The address of the user whose public key is updated
     * @param keyIndex The index of the public key being updated
     * @param newPublicKey The new public key data
	*/
    event PublicKeyUpdated(address indexed user, bytes32 indexed keyIndex, PublicKey newPublicKey);

    // Functions

	/**
     * @notice Updates the public key for the sender.
     * @param _keyIndex The index of the key to be updated
     * @param _publicKey The new public key data
	*/
    function updatePublicKey(bytes32 _keyIndex, PublicKey memory _publicKey) external;

	/**
     * @notice Sends an encrypted message to a specified address.
     * @param _to The recipient&apos;s address
     * @param _keyIndex The index of the public key used to encrypt the message
     * @param _sessionId The session ID for the communication
     * @param _encryptedMessage The encrypted message in bytes
	*/
    function sendMessage(address _to, bytes32 _keyIndex, bytes32 _sessionId, bytes calldata _encryptedMessage) external;

	/**
     * @notice Retrieves a public key for a specific user and key index.
     * @param _user The address of the user
     * @param _keyIndex The index of the key to retrieve
     * @return The public key data associated with the user and key index
	*/
    function getUserPublicKey(address _user, bytes32 _keyIndex) external view returns (PublicKey memory);
}
```

## Rationale

### Event Emission for Off-Chain Integration 
By emitting events when messages are sent or public keys are updated, the implementation facilitates seamless integration with off-chain dApps. This enables these dApps to easily track and display the latest messages and updates, ensuring real-time responsiveness and enhancing user interaction.

### End-to-End Encryption Security
The design ensures that only the owner of an address can update their public key. This restriction preserves the integrity of the end-to-end encryption, making sure that only the intended recipient can decrypt and read the messages, thereby securing communication.

### Session ID for Conversation Organization
The use of session IDs in message transactions allows multiple messages to be grouped under specific conversations. This feature is crucial for organizing and managing discussions within a dApp, providing users with a coherent and structured messaging experience.


## Reference Implementation

```solidity
pragma solidity ^0.8.0;

contract ERC7627 {

    /// @dev Enum to specify the algorithm used for the public key.
    enum PublicKeyAlgorithm { ECDSA, ED25519, X25519 }

    /// @dev Structure to represent a user&apos;s public key.
    struct PublicKey {
        bytes public_key; 
        uint64 valid_before;
        PublicKeyAlgorithm algorithm; 
    }

    /// @dev Mapping to store public keys for each address. The mapping is by user address and a unique key index.
    mapping(address =&gt; mapping(bytes32 =&gt; PublicKey)) public pk;

    event MessageSent(address indexed from, address indexed to, bytes32 indexed keyIndex, bytes32 sessionId, bytes encryptedMessage);

    event PublicKeyUpdated(address indexed user, bytes32 indexed keyIndex, PublicKey newPublicKey);

    function updatePublicKey(bytes32 _keyIndex, PublicKey memory _publicKey) external {
        pk[msg.sender][_keyIndex] = _publicKey;
        emit PublicKeyUpdated(msg.sender, _keyIndex, _publicKey);
    }

    function sendMessage(address _to, bytes32 _keyIndex, bytes32 _sessionId, bytes calldata _encryptedMessage) external {
        emit MessageSent(msg.sender, _to, _keyIndex, _sessionId, _encryptedMessage);
    }

    function getUserPublicKey(address _user, bytes32 _keyIndex) external view returns (PublicKey memory) {
        return pk[_user][_keyIndex];
    }
}
```

## Security Considerations

#### Utilization of Latest Secure Encryption Algorithms
When selecting encryption algorithms, it is essential to stay informed about the latest security news and recommendations. Avoid using asymmetric encryption algorithms with known vulnerabilities or those not recommended to ensure the confidentiality and integrity of messages. Regularly update encryption algorithms to address evolving security threats.

#### Strict Encryption Using Public Keys for Message Content
To maintain message confidentiality, the content of sent messages must be strictly encrypted using the recipient&apos;s public key. Any plaintext information transmitted could lead to information leakage and security risks. Encrypt message content at all times during transmission and storage to prevent unauthorized access to sensitive information.

#### Key Management and Protection
Robust key management and protection measures are necessary for both user public and private keys. Ensure secure storage and transmission of keys to prevent leakage and tampering. Employ multi-factor authentication and key rotation strategies to enhance key security and regularly assess key management processes to mitigate potential security risks.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE)
</description>
        <pubDate>Mon, 19 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7627</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7627</guid>
      </item>
    
      <item>
        <title>ERC-721 Ownership Shares Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7628-erc-721-ownership-shares-extension/18744</comments>
        
        <description>## Abstract

This proposal introduces an attribute of ownership and profit share quantities for each token under an NFT. This attribute signifies a stake in the ownership and profit rights associated with the NFT&apos;s specific privileges, enabling the querying, transferring, and approval of these shares, thereby making the shares represented by each token applicable in a broader range of use cases.

## Motivation

At times, when we wish to distribute dividends or assign rights to tokens of an NFT based on their share of ownership, it becomes necessary to equip each token with an attribute indicating the number of ownership shares. While [ERC-1155](/EIPs/EIPS/eip-1155) allows for the representation of ownership stakes through the balance of a token held by a wallet address, it sacrifices the uniqueness of each token. Conversely, [ERC-721](/EIPs/EIPS/eip-721) maintains the uniqueness of each token but lacks an attribute to signify the share of ownership rights, and its metadata does not allow for the free transfer of these share quantities by the token owner. This extension seeks to merge the features of [ERC-1155](/EIPs/EIPS/eip-1155) and [ERC-721](/EIPs/EIPS/eip-721), enabling holders of each share to possess characteristics akin to those of a token owner, thus bridging the gap between share representation and token uniqueness.

## Specification

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

Implementers of this extension **MUST** have all of the following functions:

```solidity
pragma solidity ^0.8.0;

interface IERC7628 /* is IERC721 */ {
    /// @notice Returns the number of decimal places used for ownership shares.
    /// @return The number of decimal places for ownership shares.
    function shareDecimals() external view returns (uint8);

    /// @notice Returns the total sum of ownership shares in existence for all tokens.
    /// @return The total sum of ownership shares.
    function totalShares() external view returns (uint256);

    /// @notice Returns the ownership share of the specified token.
    /// @param tokenId The identifier of the token.
    /// @return The ownership share of the token.
    function shareOf(uint256 tokenId) external view returns (uint256);

    /// @notice Returns the share allowance granted to the specified spender by the owner for the specified token.
    /// @param tokenId The identifier of the token.
    /// @param spender The address of the spender.
    /// @return The share allowance granted to the spender.
    function shareAllowance(uint256 tokenId, address spender) external view returns (uint256);

    /// @notice Approves the specified address to spend a specified amount of shares on behalf of the caller.
    /// @param tokenId The identifier of the token.
    /// @param spender The address of the spender.
    /// @param shares The amount of shares to approve.
    function approveShare(uint256 tokenId, address spender, uint256 shares) external;

    /// @notice Transfers ownership shares from one token to another.
    /// @param fromTokenId The identifier of the sender token.
    /// @param toTokenId The identifier of the recipient token.
    /// @param shares The amount of shares to transfer.
    function transferShares(uint256 fromTokenId, uint256 toTokenId, uint256 shares) external;

    /// @notice Transfers ownership shares from one token to another address (resulting in a new token or increased shares at the recipient address).
    /// @param fromTokenId The identifier of the sender token.
    /// @param to The address of the recipient.
    /// @param shares The amount of shares to transfer.
    function transferSharesToAddress(uint256 fromTokenId, address to, uint256 shares) external; 

    /// @notice Adds a specified amount of shares to a token, only callable by the contract owner.
    /// @param tokenId The identifier of the token.
    /// @param shares The amount of shares to add.
    function addSharesToToken(uint256 tokenId, uint256 shares) external;

    /// @notice Emitted when ownership shares are transferred from one token to another.
    /// @param fromTokenId The identifier of the sender token.
    /// @param toTokenId The identifier of the recipient token.
    /// @param amount The amount of shares transferred.
    event SharesTransfered(uint256 indexed fromTokenId, uint256 indexed toTokenId, uint256 amount);

    /// @notice Emitted when an approval is granted for a spender to spend shares on behalf of an owner.
    /// @param tokenId The token identifier.
    /// @param spender The address of the spender.
    /// @param amount The amount of shares approved.
    event SharesApproved(uint256 indexed tokenId, address indexed spender, uint256 amount);
}
```

## Rationale

#### Share Issuance to a Token

Issuing additional shares to a token allows for flexible management of ownership stakes in digital assets, catering to the evolving needs of stakeholders. It ensures transparency and security in modifying ownership structures directly on the blockchain, facilitating scenarios like profit sharing or investment adjustments.

#### Transferring Shares to an Address

Enabling shares to be transferred to an address enhances NFT liquidity and accessibility by allowing fractional ownership. This feature supports diverse use cases like fractional sales or collateralization, making NFTs more adaptable and inclusive for a broader audience.

## Backwards Compatibility

This standard is fully [ERC-721](/EIPs/EIPS/eip-721) compatible.

## Reference Implementation

```solidity
pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;
import &quot;@openzeppelin/contracts/access/Ownable.sol&quot;;
import &quot;@openzeppelin/contracts/security/ReentrancyGuard.sol&quot;;

contract ERC7628 is IERC7628, ERC721, Ownable, ReentrancyGuard {
    mapping(uint256 =&gt; uint256) private _shareBalances;
    mapping(uint256 =&gt; mapping(address =&gt; uint256)) private _shareAllowances;
    uint256 private _totalShares;
    uint256 private _nextTokenId;

    constructor(address initialOwner)
        ERC721(&quot;MyToken&quot;, &quot;MTK&quot;)
        Ownable(initialOwner)
    {}

    function addSharesToToken(uint256 tokenId, uint256 shares) public override onlyOwner {
        require(tokenId &gt; 0, &quot;ERC7628: tokenId cannot be zero&quot;);
        _shareBalances[tokenId] += shares;
        _totalShares += shares;
        emit SharesTransfered(0, tokenId, shares);
    }

    function shareDecimals() external pure override returns (uint8) {
        return 18;
    }

    function totalShares() external view override returns (uint256) {
        return _totalShares;
    }

    function shareOf(uint256 tokenId) external view override returns (uint256) {
        return _shareBalances[tokenId];
    }

    function shareAllowance(uint256 tokenId, address spender) external view override returns (uint256) {
        return _shareAllowances[tokenId][spender];
    }

    function approveShare(uint256 tokenId, address spender, uint256 shares) external override {
        require(spender != ownerOf(tokenId), &quot;ERC7628: approval to current owner&quot;);
        require(msg.sender == ownerOf(tokenId), &quot;ERC7628: approve caller is not owner&quot;);

        _shareAllowances[tokenId][spender] = shares;
        emit SharesApproved(tokenId, spender, shares);
    }

    function transferShares(uint256 fromTokenId, uint256 toTokenId, uint256 shares) external override nonReentrant {
        require(_shareBalances[fromTokenId] &gt;= shares, &quot;ERC7628: insufficient shares for transfer&quot;);
        require(_isApprovedOrOwner(msg.sender, fromTokenId), &quot;ERC7628: transfer caller is not owner nor approved&quot;);

        _shareBalances[fromTokenId] -= shares;
        _shareBalances[toTokenId] += shares;
        emit SharesTransfered(fromTokenId, toTokenId, shares);
    }

    function transferSharesToAddress(uint256 fromTokenId, address to, uint256 shares) external override nonReentrant {
        require(_shareBalances[fromTokenId] &gt;= shares, &quot;ERC7628: insufficient shares for transfer&quot;);
        require(_isApprovedOrOwner(msg.sender, fromTokenId), &quot;ERC7628: transfer caller is not owner nor approved&quot;);

        _nextTokenId++;
        _safeMint(to, _nextTokenId);
        _shareBalances[_nextTokenId] = shares;
        emit SharesTransfered(fromTokenId, _nextTokenId, shares);
    }

    // Helper function to check if an address is the owner or approved
    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) {
        return (spender == ownerOf(tokenId) || getApproved(tokenId) == spender || isApprovedForAll(ownerOf(tokenId), spender));
    }
}
```

## Security Considerations

#### Clear Approvals on Transfer
When transferring token ownership, it is crucial to clear all existing approvals. This precaution prevents previously authorized parties from retaining access after the token has changed hands.

#### Prevent Reentrancy
Implementations must guard against reentrancy attacks. This involves ensuring that functions altering balances or ownership are secure against such vulnerabilities, particularly during share transfers.

#### Validate IDs and Addresses
Verifying the legitimacy of token IDs and wallet addresses in all operations is essential. This step helps avoid errors and ensures that tokens and their associated shares are handled correctly.

#### Manage Shares on Ownership Change
Proper management of share quantities is vital during a token ownership transfer. It&apos;s important to ensure that shares are accurately accounted for and transferred alongside the token to maintain the integrity of ownership stakes.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 20 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7628</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7628</guid>
      </item>
    
      <item>
        <title>ERC-20/ERC-721 Unified Token Interface</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7629-unified-token/18793</comments>
        
        <description>## Abstract

This proposal introduces a protocol that establishes a unified interface for managing both [ERC-20](/EIPs/EIPS/eip-20) fungible tokens and [ERC-721](/EIPs/EIPS/eip-721) non-fungible tokens (NFTs) on the Ethereum blockchain. By defining a common set of functions applicable to both token types, developers can seamlessly interact with [ERC-20](/EIPs/EIPS/eip-20) and [ERC-721](/EIPs/EIPS/eip-721) tokens using a single interface. This simplifies integration efforts and enhances interoperability within decentralized applications (DApps).


## Motivation

The proposal aims to address the demand for assets combining the liquidity of [ERC-20](/EIPs/EIPS/eip-20) tokens and the uniqueness of [ERC-721](/EIPs/EIPS/eip-721) tokens. Current standards present a fragmentation, requiring users to choose between these features. This proposal fills that gap by providing a unified token interface, enabling smooth transitions between [ERC-20](/EIPs/EIPS/eip-20) and [ERC-721](/EIPs/EIPS/eip-721) characteristics to accommodate diverse blockchain applications.

## Specification

- Introduces a token contract that combines features from both [ERC-20](/EIPs/EIPS/eip-20) and [ERC-721](/EIPs/EIPS/eip-721) standards.
- Supports state transitions between [ERC-20](/EIPs/EIPS/eip-20) and [ERC-721](/EIPs/EIPS/eip-721) modes, facilitating seamless conversion and utilization of both liquidity and non-fungibility.
- Defines essential functions and events to support token interactions, conversions, and queries.
- Implements low gas consumption [ERC-20](/EIPs/EIPS/eip-20) mode to maintain efficiency comparable to typical [ERC-20](/EIPs/EIPS/eip-20) token transfers.


Compliant contracts MUST implement the following Solidity interface:

```solidity

pragma solidity ^0.8.0;
/**
 * @title ERC-7629 Unify Token Interface
 * @dev This interface defines the ERC-7629 Unify Token, which unifies ERC-721 and ERC-20 assets.
 */
interface IERC7629  is IERC165 {
    // ERC-20 Transfer event
    event ERC20Transfer(
        address indexed from,
        address indexed to,
        uint256 amount
    );

    // ERC-721 Transfer event
    event ERC721Transfer(
        address indexed from,
        address indexed to,
        uint256 indexed tokenId
    );

    // ERC-721 Transfer event
    event Transfer(
        address indexed from,
        address indexed to,
        uint256 indexed tokenId
    );

    // Approval event for ERC-20 and ERC-721
    event Approval(
        address indexed owner,
        address indexed approved,
        uint256 indexed tokenId
    );

    // Approval event for ERC-20 and ERC-721
    event Approval(
        address indexed owner,
        address indexed approved,
        uint256 indexed tokenId
    );

    // Approval event for ERC-20
    event ERC20Approval(
        address indexed owner,
        address indexed approved,
        uint256 indexed tokenId
    );

    // ApprovalForAll event for ERC-721
    event ApprovalForAll(
        address indexed owner,
        address indexed operator,
        bool approved
    );

    // ERC-20 to ERC-721 Conversion event
    event ERC20ToERC721(address indexed to, uint256 amount, uint256 tokenId);

    // ERC-721 to ERC-20 Conversion event
    event ERC20ToERC721(address indexed to, uint256 amount, uint256[] tokenIds);

    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the number of decimals used in the token.
     */
    function decimals() external view returns (uint8);

    /**
     * @dev Returns the total supply of the ERC-20 tokens.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the balance of an address for ERC-20 tokens.
     * @param owner The address to query the balance of.
     */
    function balanceOf(address owner) external view returns (uint256);

    /**
     * @dev Returns the total supply of ERC-20 tokens.
     */
    function erc20TotalSupply() external view returns (uint256);

    /**
     * @dev Returns the balance of an address for ERC-20 tokens.
     * @param owner The address to query the balance of.
     */
    function erc20BalanceOf(address owner) external view returns (uint256);

    /**
     * @dev Returns the total supply of ERC-721 tokens.
     */
    function erc721TotalSupply() external view returns (uint256);

    /**
     * @dev Returns the balance of an address for ERC-721 tokens.
     * @param owner The address to query the balance of.
     */
    function erc721BalanceOf(address owner) external view returns (uint256);

    /**
     * @notice Get the approved address for a single NFT
     * @dev Throws if `tokenId` is not a valid NFT.
     * @param tokenId The NFT to find the approved address for
     * @return The approved address for this NFT, or the zero address if there is none
     */
    function getApproved(uint256 tokenId) external view returns (address);

    /**
     * @dev Checks if an operator is approved for all tokens of a given owner.
     * @param owner The address of the token owner.
     * @param operator The address of the operator to check.
     */
    function isApprovedForAll(
        address owner,
        address operator
    ) external view returns (bool);

    /**
     * @dev Returns the remaining number of tokens that spender will be allowed to spend on behalf of owner.
     * @param owner The address of the token owner.
     * @param spender The address of the spender.
     */
    function allowance(
        address owner,
        address spender
    ) external view returns (uint256);

    /**
     * @dev Returns the array of ERC-721 token IDs owned by a specific address.
     * @param owner The address to query the tokens of.
     */
    function owned(address owner) external view returns (uint256[] memory);

    /**
     * @dev Returns the address that owns a specific ERC-721 token.
     * @param tokenId The token ID.
     */
    function ownerOf(uint256 tokenId) external view returns (address erc721Owner);

    /**
     * @dev Returns the URI for a specific ERC-721 token.
     * @param tokenId The token ID.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);

    /**
     * @dev Approve or disapprove the operator to spend or transfer all of the sender&apos;s tokens.
     * @param spender The address of the spender.
     * @param amountOrId The amount of ERC-20 tokens or ID of ERC-721 tokens.
     */
    function approve(
        address spender,
        uint256 amountOrId
    ) external returns (bool);

    /**
     * @dev Set or unset the approval of an operator for all tokens.
     * @param operator The address of the operator.
     * @param approved The approval status.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Transfer ERC-20 tokens or ERC-721 token from one address to another.
     * @param from The address to transfer ERC-20 tokens or ERC-721 token from.
     * @param to The address to transfer ERC-20 tokens or ERC-721 token to.
     * @param amountOrId The amount of ERC-20 tokens or ID of ERC-721 tokens to transfer.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amountOrId
    ) external returns (bool);
    
    /**
     * @notice Transfers the ownership of an NFT from one address to another address
     * @dev Throws unless `msg.sender` is the current owner, an authorized
     *  operator, or the approved address for this NFT. Throws if `_rom` is
     *  not the current owner. Throws if `_to` is the zero address. Throws if
     *  `tokenId` is not a valid NFT. When transfer is complete, this function
     *  checks if `to` is a smart contract (code size &gt; 0). If so, it calls
     *  `onERC721Received` on `to` and throws if the return value is not
     *  `bytes4(keccak256(&quot;onERC721Received(address,address,uint256,bytes)&quot;))`.
     * @param from The current owner of the NFT
     * @param to The new owner
     * @param tokenId The NFT to transfer
     * @param data Additional data with no specified format, sent in call to `to`
     */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external payable;

    /**
     * @notice Transfers the ownership of an NFT from one address to another address
     * @dev This works identically to the other function with an extra data parameter,
     *  except this function just sets data to &quot;&quot;.
     * @param from The current owner of the NFT
     * @param to The new owner
     * @param tokenId The NFT to transfer
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) external payable;

    /**
     * @dev Transfer ERC-20 tokens to an address.
     * @param to The address to transfer ERC-20 tokens to.
     * @param amount The amount of ERC-20 tokens to transfer.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Retrieves the unit value associated with the token.
     * @return The unit value.
     */
    function getUnit() external view returns (uint256);

    /**
     * @dev Converts ERC-721 token to ERC-20 tokens.
     * @param tokenId The unique identifier of the ERC-721 token.
     */
    function erc721ToERC20(uint256 tokenId) external;

    /**
     * @dev Converts ERC-20 tokens to an ERC-721 token.
     * @param amount The amount of ERC-20 tokens to convert.
     */
    function erc20ToERC721(uint256 amount) external;
}


```
## Rationale

Common Interface for Different Token Types:

- Introduces a unified interface to address the fragmentation caused by separate [ERC-20](/EIPs/EIPS/eip-20) and [ERC-721](/EIPs/EIPS/eip-721) standards.
- Standardizes functions like transferFrom, mint, and burn, enabling developers to interact with both token types without implementing distinct logic.

Transfer Functionality:

- Includes transferFrom function for seamless movement of tokens between addresses, as it&apos;s a core component of both [ERC-20](/EIPs/EIPS/eip-20) and [ERC-721](/EIPs/EIPS/eip-721) standards.

Minting and Burning:

- Incorporates mint and burn functions for creating and destroying tokens, essential for managing token supply and lifecycle.

Balance and Ownership Queries:

- Provides functions like balanceOf and ownerOf for retrieving token balances and ownership information, crucial for both [ERC-20](/EIPs/EIPS/eip-20) and [ERC-721](/EIPs/EIPS/eip-721) tokens.

Compatibility and Extensibility:

- Ensures compatibility with existing [ERC-20](/EIPs/EIPS/eip-20) and [ERC-721](/EIPs/EIPS/eip-721) implementations, minimizing disruption during transition.
- Allows extension with additional functions and events for future enhancements.

Security Considerations:

- Implements mechanisms to prevent common issues like reentrancy attacks and overflows, ensuring the security and robustness of the unified interface.



## Backwards Compatibility


The proposed this proposal introduces a challenge in terms of backward compatibility due to the distinct balance query mechanisms utilized by [ERC-20](/EIPs/EIPS/eip-20) and [ERC-721](/EIPs/EIPS/eip-721) standards. [ERC-20](/EIPs/EIPS/eip-20) employs `balanceOf` to check an account&apos;s token balance, while [ERC-721](/EIPs/EIPS/eip-721) uses `balanceOf` to inquire about the quantity of tokens owned by an account. To reconcile these differences, the ERC must consider providing either two separate functions catering to each standard or adopting a more generalized approach.

### Compatibility Points

The primary compatibility point lies in the discrepancy between [ERC-20](/EIPs/EIPS/eip-20)&apos;s balanceOf and [ERC-721](/EIPs/EIPS/eip-721)&apos;s balanceOf functionalities. Developers accustomed to the specific balance query methods in each standard may face challenges when transitioning to this proposal.

### Proposed Solutions

Dual Balance Query Functions:

Introduce two distinct functions, `erc20BalanceOf` and `erc721TotalSupply`, to align with the conventions of [ERC-20](/EIPs/EIPS/eip-20) and [ERC-721](/EIPs/EIPS/eip-721), respectively. Developers can choose the function based on the token type they are working with.



## Security Considerations

- Due to the dual nature of this proposal, potential differences in protocol interpretation may arise, necessitating careful consideration during development.
- Comprehensive security audits are recommended, especially during mode transitions by users, to ensure the safety of user assets.


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Sun, 18 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7629</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7629</guid>
      </item>
    
      <item>
        <title>Dual Nature Token Pair</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7631-dual-nature-token-pair/18796</comments>
        
        <description>## Abstract

A fungible [ERC-20](/EIPs/EIPS/eip-20) token contract and non-fungible [ERC-721](/EIPs/EIPS/eip-721) token contract can be interlinked, allowing actions performed on one contract to be reflected on the other. This proposal defines how the relationship between the two token contracts can be queried. It also enables accounts to configure whether ERC-721 mints and transfers should be skipped during ERC-20 to ERC-721 synchronization.

## Motivation

The ERC-20 fungible and ERC-721 non-fungible token standards offer sufficient flexibility for a co-joined, dual nature token pair. Transfers on the ERC-20 token can automatically trigger transfers on the ERC-721 token, and vice-versa. This enables applications such as native ERC-721 fractionalization, wherein acquiring ERC-20 tokens leads to the automatic issuance of ERC-721 tokens, proportional to the ERC-20 balance.

Dual nature token pairs maintain full compliance with both ERC-20 and ERC-721 token standards. This proposal aims to enhance the functionality of dual nature token pairs.

To facilitate querying the relationship between the tokens, extension interfaces are proposed for the ERC-20 and ERC-721 tokens respectively. This enables various quality of life improvements such as allowing decentralized exchanges and NFT marketplaces to display the relationship between the tokens.

Additionally, users can configure whether they want to skip ERC-721 mints and transfers during ERC-20 to ERC-721 synchronization.

## Specification

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

### Overview

A dual nature token pair comprises of an ERC-20 contract and an ERC-721 contract.

For convention, the ERC-20 contract is designated as the base contract, and the ERC-721 contract is designated as the mirror contract.

### ERC-20 Extension Interface

The ERC-20 contract MUST implement the following interface.

```solidity
interface IERC7631Base {
    /// @dev Returns the address of the mirror ERC-721 contract.
    ///
    /// This method MAY revert or return the zero address
    /// to denote that a mirror ERC-721 contract has not been linked.
    ///
    /// If a non-zero address is returned, the returned address MUST
    /// implement `IERC7631Mirror` and its `baseERC20()` method MUST
    /// return the address of this contract.
    ///
    /// Once a non-zero address has been returned, this method
    /// MUST NOT revert and the returned value MUST NOT change.
    function mirrorERC721() external view returns (address);
}
```

The ERC-20 contract MAY implement the following interface.

```solidity
interface IERC7631BaseNFTSkippable {
    /// @dev Implementations SHOULD emit this event when the skip NFT status
    /// of `owner` is updated to `status`.
    ///
    /// The purpose of this event is to signal to indexers that the
    /// skip NFT status has been changed.
    ///
    /// For simplicity of implementation,
    /// this event MAY be emitted even if the status is unchanged.
    event SkipNFTSet(address indexed owner, bool status);

    /// @dev Returns true if ERC-721 mints and transfers to `owner` SHOULD be
    /// skipped during ERC-20 to ERC-721 synchronization.
    /// Otherwise, returns false.
    /// 
    /// This method MAY revert
    /// (e.g. contract not initialized, method not supported).
    ///
    /// If this method reverts:
    /// - Interacting code SHOULD interpret `setSkipNFT` functionality as
    ///   unavailable and hide any functionality to call `setSkipNFT`.
    /// - The skip NFT status for `owner` SHOULD be interpreted as undefined.
    ///
    /// Once a true or false value has been returned for a given `owner`,
    /// this method MUST NOT revert for the given `owner`.
    function getSkipNFT(address owner) external view returns (bool);

    /// @dev Sets the caller&apos;s skip NFT status.
    ///
    /// This method MAY revert
    /// (e.g. insufficient permissions, method not supported).
    ///
    /// It is RECOMMENDED to keep this method permissionless.
    ///
    /// Emits a {SkipNFTSet} event.
    function setSkipNFT(bool status) external;
}
```

### ERC-721 Extension Interface

The ERC-721 contract MUST implement the following interface.

```solidity
interface IERC7631Mirror {
    /// @dev Returns the address of the base ERC-20 contract.
    ///
    /// This method MAY revert or return the zero address
    /// to denote that a base ERC-20 contract has not been linked.
    ///
    /// If a non-zero address is returned, the returned address MUST
    /// implement `IERC7631Base` and its `mirrorERC721()` method MUST
    /// return the address of this contract.
    ///
    /// Once a non-zero address has been returned, this method
    /// MUST NOT revert and the returned value MUST NOT change.
    function baseERC20() external view returns (address);
}
```
## Rationale

### Implementation Detection

The `mirrorERC721` and `baseERC20` methods returning non-zero addresses signal that the ERC-20 and ERC-721 contracts implement the required interfaces respectively. As such, [ERC-165](/EIPs/EIPS/eip-165) is not required.

The `getSkipNFT` and `setSkipNFT` methods MAY revert. As contracts compiled with Solidity or Vyper inherently revert on calls to undefined methods, a typical `IERC7631Base` implementation lacking explicit `getSkipNFT` and `setSkipNFT` definitions still complies with `IERC7631BaseNFTSkippable`.

### NFT Skipping

The skip NFT methods allow accounts to avoid having ERC-721 tokens automatically minted to it whenever there is an ERC-20 transfer.

They are helpful in the following situations:

- Loading vesting contracts with large amounts ERC-20 tokens to be vested to many users.
- Loading candy machine contracts with large amounts of ERC-20 tokens to sell ERC-721 tokens to customers.
- Transferring large amounts of ERC-20 tokens in / out of a liquidity pool.
- Transferring large amounts of ERC-20 tokens between admin accounts.

Including the skip NFT methods in the standard will:
- Enable applications to conveniently display the option for users to skip NFTs.
- Enable applications to transfer any amount of ERC-20 tokens without the O(n) gas costs associated with minting multiple ERC-721 tokens, which can surpass the block gas limit.

These methods are recommended even on EVM chains with low gas costs, because bulk automatic ERC-721 transfers can still surpass the block gas limit.

A useful pattern is to make `getSkipNFT` return true by default if `owner` is a smart contract.

The choice of `getSkipNFT` returning a boolean value is for simplicity. If more complex behavior is needed, developers may add in extra methods of their own.

### Implementation Conventions

The ERC-20 contract is designated as the base contract for convention, as a typical implementation can conveniently derive ERC-721 balances from the ERC-20 balances. This does not prohibit one from implementing most of the logic in the ERC-721 contract if required.

This proposal does not cover the token synchronization logic. This is to leave flexibility for various implementation patterns and novel use cases (e.g. automatically rebased tokens).

### Linking Mechanism

The linking process is omitted for flexibility purposes. Developers can use any desired mechanism (e.g. linking in constructor, initializer, or via custom admin-only public methods on the two contracts). The only restriction is that the pairing must be immutable once established (to simplify indexing logic).

## Backwards Compatibility

No backward compatibility issues found.

## Security Considerations

### Synchronization Access Guards

External methods for synchronization logic must be guarded such that only the other contract is authorized to call them.

### Rare NFT Sniping

For dual nature collections that offer ERC-721 tokens with differing rarity levels, the ERC-721 metadata should be revealed in a way that is not easily gameable with metadata scraping and ERC-20 token transfers. A recommendation is to require that an ERC-721 token is held by the same account for some time before revealing its metadata.

### Out-of-gas Denial of Service

Transferring ERC-20 tokens can automatically initiate the minting, transferring, or burning of multiple ERC-721 tokens. This can incur O(n) gas costs instead of the typical O(1) gas costs for ERC-20 tokens transfers. Logic for selecting ERC-721 token IDs can also incur additional gas costs. Synchronization logic must consider ERC-721 related gas costs to prevent out-of-gas denial of service issues.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 21 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7631</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7631</guid>
      </item>
    
      <item>
        <title>Interfaces for Named Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-tbd-named-nfts-extending-erc-721/18550</comments>
        
        <description>## Abstract

Extends tokens using `uint256 tokenId` to support `tokenName` of type `string` and to convert back to `tokenId`.

## Motivation

For Marketplaces, Explorers, Wallets, DeFi and dApps to better display and operate NFTs that come with a name.

## Specification

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

1. Compliant contracts MUST support `tokenName` and
a mapping between `tokenName` and `tokenId` in one of the following ways:
  - 1a all compliant contracts are RECOMMENDED to implement the following
interfaces: `IERC_NamedTokenCore`,
```solidity
interface IERC_NamedTokenCore {
  function idToName(uint256 _tokenId) external view returns (string);
  function nameToId(string memory _tokenName) external returns (uint256);
}
```

and it should satisfy the behavior rules that:
    - 1a.1. when a new name is introduced, it is RECOMMENDED to emit an event `newName(uint256 indexed tokenId, string tokenName)`.
    - 1a.2. tokenId and tokenName MUST be two-way single mapping, meaning if tokenId exists, tokenName MUST exist and vice versa and
      `tokenId = nameToId(idToName(tokenId))` and
      `tokenName = idToName(nameToId(tokenName))` MUST hold true.

  - 1b. if the compliant contract does not implement `IERC_NamedTokenCore`,
it MAY follow the default mapping rule between `tokenId` and `tokenName`
`uint256 tokenId = uint256(keccak256(tokenName))`.

2. All methods involving `tokenId` for a compliant contract are RECOMMENDED to
have a counterpart method ending with `ByName` that substitutes all
parameters of `uint256 tokenId` with `string memory tokenName`,
and the behavior of the counterpart method MUST be consistent
with the original method.

3. A compliant contract MAY implement one or more of the following extra interfaces

```solidity
interface IERC_NamedTokenExtension {
  function isValidTokenName(string memory _tokenName) external view returns (string);
  function normalizeTokenName(string memory _tokenName) external view returns (string memory);
}
```

## Rationale

1. We allow a default way to map `tokenId` and `tokenName` for convenience, but
we also allow contracts to implement their own ways of mapping `tokenId` and
`tokenName` for flexibility.

2. We consider providing an interface for

## Backwards Compatibility

This proposal is fully backwards compatible with token contracts using
`uint256 tokenId` as the unique identifier.

## Security Considerations

This proposal assumes that both `tokenName` and `tokenId` are
unique amongst all tokens.

If token names are not normalized, two distinct token names may confuse users
as they look alike. Contract developers shall declare a normalization mechanism if
non-unique `tokenName` is allowed using `IERC_NamedTokenExtension`.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 08 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7632</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7632</guid>
      </item>
    
      <item>
        <title>Limited Transfer Count NFT</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7634-limited-transferable-nft/18861</comments>
        
        <description>## Abstract

This standard extends [ERC-721](/EIPs/EIPS/eip-721) with a mechanism that lets token owners/minters cap how many times a specific token can be transferred. It specifies functions to set and read a per-token transfer limit, to query a per-token transfer count, and defines transfer-time hooks to enforce the cap. The goal is fine-grained, enforceable transfer restrictions while preserving ERC-721 compatibility.

## Motivation

Once NFTs are sold, they detach from their minters and can be perpetually transferred. Yet many situations require tighter control over secondary movement.

First, limiting the number of transfers can help preserve value (e.g., premium auctions, IP that becomes CC0 after a finite number of transfers, or game items that “wear out” and burn at a threshold).

Second, capping transfer frequency can reduce risks from adversarial arbitrage (e.g., HFT-like behavior) by offering an easy-to-deploy throttle.

Third, bounding re-staking cycles of NFT positions (e.g., proof-of-restake) can dampen recursive leverage and mitigate bubble dynamics.


### Key Takeaways

*Controlled Value Preservation.* Scarcity via a transfer cap can help maintain value over time.

*Ensuring Intended Usage.* Limits keep usage aligned with intent (e.g., limited editions less prone to flip cycles).

*Expanding Use Cases.* Memberships/licenses with bounded transferability become practical.

*Easy Integration.* An extension interface (`IERC7634`) layers on top of [ERC-721](/EIPs/EIPS/eip-721), easing adoption without breaking compatibility.

## Specification

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.

- `setTransferLimit`: establishes the transfer limit for a `tokenId`.
- `transferLimitOf`: returns the transfer limit for a `tokenId`.
- `transferCountOf`: returns the current transfer count for a `tokenId`.

**Counting and enforcement scope.** Implementations **MUST** enforce the cap on native ERC-721 transfers of the underlying token (i.e., transfers where `from != address(0)` and `to != address(0)`). Incrementing the count **SHOULD** occur only after a successful native transfer. Mint and burn operations MUST NOT increment the count.

Implementers **MUST** provide the following interface:

```solidity

pragma solidity ^0.8.4;

/// @title IERC7634 Interface for Transfer-Capped ERC-721 Tokens
/// @dev ERC-7634 is an extension interface intended to be implemented alongside ERC-721
interface IERC7634 {
    /**
     * @dev Emitted after a successful native transfer when the per-token count increases.
     */
    event TransferCountIncreased(uint256 indexed tokenId, uint256 newCount);

    /**
     * @dev Emitted when the per-token transfer limit is set or updated.
     */
    event TransferLimitUpdated(uint256 indexed tokenId, uint256 previousLimit, uint256 newLimit);

    /**
     * @dev Returns the current transfer count for a tokenId.
     */
    function transferCountOf(uint256 tokenId) external view returns (uint256);

    /**
     * @dev Sets the transfer limit for a tokenId. Callable by owner or approved.
     * @param tokenId The token id to set the limit for.
     * @param limit The maximum number of native transfers allowed.
     */
    function setTransferLimit(uint256 tokenId, uint256 limit) external;

    /**
     * @dev Returns the transfer limit for a tokenId.
     */
    function transferLimitOf(uint256 tokenId) external view returns (uint256);
}
    
```

## Rationale

### Tracking and hooks

`transferCountOf` and `transferLimitOf` expose state needed to enforce a cap. The count should only increase after a successful native transfer (not on mint/burn). Separating `TransferLimitUpdated` from `TransferCountIncreased` makes it clear that the former is an administrative change while the latter is derived from runtime transfers.

## Backwards Compatibility

This standard is fully compatible with [ERC-721](/EIPs/EIPS/eip-721). Existing contracts can adopt it by adding the new interface and hooks without changing ERC-721 semantics.

### Extensions

This standard can be enhanced with additional advanced functionalities alongside existing NFT protocols. For example:

- Incorporating a burn function (e.g., [ERC-5679](/EIPs/EIPS/eip-5679)) would enable NFTs to automatically expire after reaching their transfer limits, akin to the ephemeral nature of Snapchat messages that disappear after multiple views.

- Incorporating a non-transferring function, as defined in the SBT standards, would enable NFTs to settle and bond with a single owner after a predetermined number of transactions. This functionality mirrors the scenario where a bidder ultimately secures a treasury after participating in multiple bidding rounds.


## Reference Implementation

Below is a recommended pattern. It enforces the cap pre-transfer, increments the count post-transfer, ignores mint/burn for counting, and emits the clarified events. Implementations commonly override `_beforeTokenTransfer` to enforce `transferCount` &lt; `transferLimit` and `_afterTokenTransfer` to increment the count and emit `TransferCountIncreased`.

```solidity

pragma solidity ^0.8.4;

import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;
import &quot;./IERC7634.sol&quot;;

/// @title Transfer-Capped ERC-721 (ERC-7634)
/// @dev Example implementation of ERC-7634 alongside ERC-721
contract ERC7634 is ERC721, IERC7634 {
    // tokenId =&gt; current transfer count
    mapping(uint256 =&gt; uint256) private _transferCounts;
    // tokenId =&gt; max allowed native transfers
    mapping(uint256 =&gt; uint256) private _transferLimits;

    function transferCountOf(uint256 tokenId) public view override returns (uint256) {
        require(_exists(tokenId), &quot;ERC7634: nonexistent token&quot;);
        return _transferCounts[tokenId];
    }

    function setTransferLimit(uint256 tokenId, uint256 limit) public override {
        require(_isApprovedOrOwner(_msgSender(), tokenId), &quot;ERC7634: not owner/approved&quot;);
        uint256 prev = _transferLimits[tokenId];
        _transferLimits[tokenId] = limit;
        emit TransferLimitUpdated(tokenId, prev, limit);
    }

    function transferLimitOf(uint256 tokenId) public view override returns (uint256) {
        require(_exists(tokenId), &quot;ERC7634: nonexistent token&quot;);
        return _transferLimits[tokenId];
    }

    /// @dev Enforce transfer limit on native transfers (exclude mint/burn).
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual override {
        if (from != address(0) &amp;&amp; to != address(0)) {
            require(
                _transferCounts[tokenId] &lt; _transferLimits[tokenId],
                &quot;ERC7634: transfer limit reached&quot;
            );
        }
        super._beforeTokenTransfer(from, to, tokenId);
    }

    /// @dev Increment count only after successful native transfer and emit event.
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 tokenId,
        uint256 quantity
    ) internal virtual override {
        if (from != address(0) &amp;&amp; to != address(0)) {
            unchecked { _transferCounts[tokenId] += 1; }
            emit TransferCountIncreased(tokenId, _transferCounts[tokenId]);

            if (_transferCounts[tokenId] == _transferLimits[tokenId]) {
                // Optional: perform action exactly when the cap is reached (e.g., _burn(tokenId))
            }
        }
        super._afterTokenTransfer(from, to, tokenId, quantity);
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(ERC721)
        returns (bool)
    {
        return interfaceId == type(IERC7634).interfaceId || super.supportsInterface(interfaceId);
    }
}

```

## Security Considerations

- Scope with wrappers. The cap applies only to native [ERC-721](/EIPs/EIPS/eip-721) transfers of the underlying token. Any owner can cheaply wrap a token and transfer a separate wrapper token; such downstream transfers cannot be prevented without breaking [ERC-721](/EIPs/EIPS/eip-721) composability. As a result, this standard does not provide an unbypassable guarantee that, for example, a game item will always wear out or that secondary trading is globally capped; it standardizes a primitive for budgeting native transfers that ecosystems may choose to coordinate around. Deployments that want stronger effective guarantees **MAY** add optional mitigations such as recipient allowlists/registries or &quot;compliant wrapper&quot; patterns that mirror counts/limits, trading off openness for enforcement.

- Limit mutability. Consider making limits immutable once set (or only decreasing), to prevent tampering.

- Gas. Avoid heavy logic in hooks; extensions (e.g., burn on cap) should remain gas-safe.



## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 22 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7634</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7634</guid>
      </item>
    
      <item>
        <title>Extension of EIP-778 for &quot;client&quot; ENR Entry</title>
        <category>Standards Track/Networking</category>
        
          <comments>https://ethereum-magicians.org/t/eip7636-extension-of-eip-778-for-client-enr-entry/18935</comments>
        
        <description>## Abstract

The Ethereum network consists of nodes running various client implementations. Each client has its own set of features, optimizations, and unique behaviors. Introducing a standardized way to identify client software and its version in the ENR allows for more effective network analysis, compatibility checks, and troubleshooting. This EIP proposes the addition of a &quot;client&quot; field to the ENR.

## Motivation

Understanding the landscape of client software in the Ethereum network is crucial for developers, nodes, and network health assessment. Currently, there is no standardized method for nodes to announce their software identity and version, which can lead to compatibility issues or difficulty in diagnosing network-wide problems. Adding this to the ENR allows clients to audit network health only using discv5, and additionally track discv5 adoption across different services.

## Specification

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

The &quot;client&quot; entry is proposed to be added to the ENR following the specifications in [EIP-778](/EIPs/EIPS/eip-778). This entry is OPTIONAL and can be omitted by clients that choose not to disclose such information. The key for this entry is `&quot;client&quot;`.

All elements MUST be encoded as a string using the ASCII standard as described in [RFC 20](https://www.rfc-editor.org/rfc/rfc20).

The value for this entry MUST be an RLP list:

```
[ClientName, Version, (BuildVersion)]
```

- `ClientName`: A string identifier for the client software. It SHOULD be concise, free of spaces, and representative of the client application.
- `Version`: A string representing the version of the client software in a human-readable format. It is RECOMMENDED to follow semantic versioning.
- `BuildVersion`: An OPTIONAL string representing the build or commit version of the client software. This can be used to identify specific builds or development versions.

## Rationale

One key was chosen over using many keys to make efficient use of space. The use of one string, however, does not align with other EIPs of similar purpose and as such the RLP list was decided as the best encoding.

## Backwards Compatibility

This EIP is fully backwards compatible as it extends the ENR specification by adding an optional entry. Existing implementations that do not recognize the &quot;client&quot; entry will ignore it without any adverse effects on ENR processing or network behavior.

## Test Cases

A node running Geth version 1.10.0 on the mainnet might have an ENR `client` entry like:

```
[&quot;Geth&quot;, &quot;1.10.0&quot;]
```

A node running an experimental build of Nethermind might include:

```
[&quot;Nethermind&quot;, &quot;1.9.53&quot;, &quot;7fcb567&quot;]
```

and an ENR of 

```
enr:-MO4QBn4OF-y-dqULg4WOIlc8gQAt-arldNFe0_YQ4HNX28jDtg41xjDyKfCXGfZaPN97I-MCfogeK91TyqmWTpb0_AChmNsaWVudNqKTmV0aGVybWluZIYxLjkuNTOHN2ZjYjU2N4JpZIJ2NIJpcIR_AAABg2lwNpAAAAAAAAAAAAAAAAAAAAABiXNlY3AyNTZrMaECn-TTdCwfZP4XgJyq8Lxoj-SgEoIFgDLVBEUqQk4HnAqDdWRwgiMshHVkcDaCIyw
```

which can be decoded to yield normal data such as `seq`, `signature`, `id` and `secp256k1`. Additionally, it would yield the client value of `[&quot;0x4e65746865726d696e64&quot;,&quot;0x312e392e3533&quot;,&quot;0x37666362353637&quot;]` or `[&quot;Nethermind&quot;, &quot;1.9.53&quot;, &quot;7fcb567&quot;]`

## Security Considerations

Introducing identifiable client information could potentially be used for targeted attacks against specific versions or builds known to have vulnerabilities. It is crucial for clients implementing this EIP to consider the implications of disclosing their identity and version. Users or operators should have the ability to opt-out or anonymize this information if desired.

Additionally, as this information is self proclaimed, this data ***MUST NOT*** be used for anything that requires it to be reliable.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 25 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7636</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7636</guid>
      </item>
    
      <item>
        <title>Optimize EOA EXTCODEHASH</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7637-extcodehash-optimize/18946</comments>
        
        <description>## Abstract

This proposal is an optimization for [EIP-1052](/EIPs/EIPS/eip-1052),
For addresses with a balance, but without code, the codehash should still be `0x`.

When an address `add.code == 0x` and `add.balance != 0`, `add.codehash==0` is required instead of `add.codehash==keccak256(&quot;&quot;)`

## Motivation

EIP-1052 was proposed to save gas fees. However, due to some flaws in the set specifications, in actual applications, due to safety concerns, they will not actually be used. In order for EIP-1052 to be truly useful, it should be optimized.

If someone uses it based on the proposal of EIP-1052 and does not notice the change when `add.balance != 0`, there may be security issues.


## Specification

The behaviour of `EXTCODEHASH` is changed in the following way:

1. When calling `EXTCODEHASH`, the codehash of the address with balance but no code is still `0x`


## Rationale

EIP-1052 In order to include the function of `BALANCE`, let the `EXTCODEHASH` of the address without balance be `0x`, and the `EXTCODEHASH` of the address with balance be `keccak256(&quot;&quot;)`.

The contract address can be calculated in advance. Whether it is  `CREATE` or `CREATE2`, it is possible that the contract is not created but has a balance. For security, You can actually only use `keccak256(add.code) == keccak256(&quot;&quot;)` or `add.code.length ==0` instead of `add.codehash == 0`,, which makes the original intention of EIP-1052 meaningless.

For example, uniswap V2 uses stored addresses to determine whether a contract exists. If this `EXTCODEHASH` is optimized, can save a huge amount of gas.

If someone uses a `add.codehash==0` to determine whether a contract has been created, due to intuition and the lack of details in many documents, they will not think that the codehash of an address with a balance will change from `0x` to `keccak256(&quot;&quot;)`. If someone maliciously attacks at this time, it will cause some bad effects.


## Backwards Compatibility

Using codehash to determine whether a non-contract address has a balance will not be available


## Reference Implementation

Code reference for execution-specs

After modification

```python
def extcodehash(evm: Evm) -&gt; None:
    address = to_address(pop(evm.stack))
    charge_gas(evm, GAS_CODE_HASH)
    account = get_account(evm.env.state, address)
    if account == EMPTY_ACCOUNT:
        codehash = U256(0)
    else:
	codehash = U256.from_be_bytes(keccak256(account.code))
	if codehash == U256(hexstr=&quot;c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470&quot;):
	    codehash = U256(0)
    push(evm.stack, codehash)
    evm.pc += 1
```


Source code

```python
def extcodehash(evm: Evm) -&gt; None:
    address = to_address(pop(evm.stack))
    charge_gas(evm, GAS_CODE_HASH)
    account = get_account(evm.env.state, address)
    if account == EMPTY_ACCOUNT:
        codehash = U256(0)
    else:
        codehash = U256.from_be_bytes(keccak256(account.code))

    push(evm.stack, codehash)
    evm.pc += 1
```


## Security Considerations

Using codehash to determine whether a non-contract address has a balance will not be available

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
 
</description>
        <pubDate>Mon, 26 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7637</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7637</guid>
      </item>
    
      <item>
        <title>Batch Calls Encoding in SCA</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7638-optimized-calls-encoding/18966</comments>
        
        <description>## Abstract
Batch Calls Encoding (BCE) outlines a solution for Smart Contract Account (SCA) wallets to consolidate multiple calls into a single call, encoding multiple parameters into bytes, compressing on-chain data, and saving gas. It can be used to implement atomic operations as well as non-atomic operations.

## Motivation
Typically, interactions between users and contracts involve a series of coherent operations, such as `approve`-`transferFrom`. While EOA wallets require users to confirm each operation sequentially, SCA wallets can confirm all operations with a single confirmation, completing all operations within a single call, thus achieving atomicity. If `approve` succeeds but `transferFrom` fails, it poses a security risk. The secure approach is to ensure that if one operation fails, all associated operations also fail, thereby ensuring atomicity. Therefore, we propose this encoding method to encode multiple parameters into bytes, compress on-chain data, and save gas. It can be used to implement both atomic and non-atomic operations.

In addition to the atomic operation of `approve`-`transferFrom` mentioned above, gas payment delegation can also be achieved. It involves users and bundlers signing a set of calls, where the content of the calls includes:

1. The user wishes to initiate multiple calls through his SCA.
2. The user transfers 10 USDT to the bundler as fee, included within the calls.
3. The bundler submits the calls, pay ETH gas and get the 10 USDT.

The user encodes the content of the calls, attaches their signature to ensure its integrity, and sends it to the bundler. If the bundler considers the gas payment insufficient, they may choose not to submit it. However, if they approve the content of the calls, the signed transaction can be submitted. After execution, the user obtains the desired operations, and the bundler receives the fee.

[EIP-4337](/EIPs/EIPS/eip-4337) also implements gas payment delegation. BCE and [EIP-4337](/EIPs/EIPS/eip-4337) are not mutually exclusive and can be implemented concurrently within an SCA.

Based on empirical testing, BCE is simpler and more gas-efficient compared to alternative methods.

## Specification
The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119 and RFC 8174.

This ERC **REQUIRED** SCA to be implemented in the contract, where the Dapp communicates with the SCA wallet extension to communicate the user&apos;s intentions to the wallet, which uses Batch Calls Encoding to send multiple calls as bytes to the user&apos;s SCA contract.

_Batch Calls_ comprises multiple `Call` bytes, each defined by the encoding of `to`\`value`\`data` as follows:

```mermaid
graph LR
A[&quot;to (20bytes)&quot;] --- B[&quot;value (32bytes)&quot;] --- C[&quot;data length (32bytes)&quot;] --- D[&quot;data (bytes)&quot;]
```

Let:
- `to`: The address of the called contract, corresponding to the Solidity address type, 20 bytes.
- `value`: The amount of ETH(in wei) sent to the contract, in wei, corresponding to the Solidity uint type, 32 bytes.
- `data length`: The length of the data(in bytes), corresponding to the Solidity uint type, 32 bytes.
- `data`: The encoded functionData sent to the contract, corresponding to the Solidity bytes type, with a length defined by `data length`.

Multiple `Call` units are concatenated to form an _Batch Calls_ sequence.


## Rationale
Each call encapsulates 3 parameters: `to`\`value`\`data`. The conventional approach involves packaging these 3 parameters into a struct and then placing multiple structs into an array. However, using a struct adds overhead as it also packages the types of `to`\`value`\`data`, increasing the size of the encoding. Since `to`\`value`\`data` have fixed types, this additional encoding can be omitted. In Solidity, reading data from `bytes calldata` using slice is a gas-efficient method. Considering these factors, _Batch Calls Encoding_ can compress on-chain data and save gas.

## Backwards Compatibility
This ERC does not change the consensus layer, so there are no backwards compatibility issues for Ethereum as a whole. 

This ERC does not change other ERC standards, so there are no backwards compatibility issues for Ethereum applications. 


## Reference Implementation
This proposal only specifies the encoding of _Batch Calls_, while the specific implementation and naming are left to the discretion of the project. Below is an example of an SCA contract utilizing _Batch Calls_ (referred to as `atomCallbytes`), where the user atomically signs multiple operations, enabling the bundler to pay gas on behalf of the user:

### `SmartWallet.sol`

```solidity
pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/utils/cryptography/ECDSA.sol&quot;;

contract SmartWallet {
    using ECDSA for bytes32;

    uint32 public valid = 1; //to make AtomSign invalid

    address private immutable original;
    address public owner;
    address public bundler;

    mapping(bytes32 =&gt; bool) public usedMsgHashes;

    modifier onlyBundler() {
        require(
            bundler == msg.sender,
            &quot;onlyBundler: caller is not the bundler&quot;
        );
        _;
    }

    modifier onlyOwnerAndOriginal() {
        require(
            owner == msg.sender || original == msg.sender,
            &quot;onlyOwnerAndOriginal: caller is not the owner&quot;
        );
        _;
    }

    constructor(address _bundler) {
        original = address(this);
        owner = msg.sender;
        bundler = _bundler;
    }

    function atomSignCall(
        bytes calldata atomCallbytes,
        uint32 deadline,
        bytes calldata signature
    ) external onlyBundler {
        require(deadline &gt;= block.timestamp, &quot;atomSignCall: Expired&quot;);
        bytes32 msgHash = keccak256(
            bytes.concat(
                msg.data[:msg.data.length - signature.length - 32],
                bytes32(block.chainid),
                bytes20(address(this)),
                bytes4(valid)
            )
        );
        require(!usedMsgHashes[msgHash], &quot;atomSignCall: Used msgHash&quot;);
        require(
            owner == msgHash.toEthSignedMessageHash().recover(signature),
            &quot;atomSignCall: Invalid Signature&quot;
        );

        //do calls
        uint i;
        while(i &lt; atomCallbytes.length) {
            address to = address(uint160(bytes20(atomCallbytes[i:i+20])));
            uint value = uint(bytes32(atomCallbytes[i+20:i+52]));
            uint len = uint(bytes32(atomCallbytes[i+52:i+84]));

            (bool success, bytes memory result) = to.call{value: value}(atomCallbytes[i+84:i+84+len]);
            if (!success) {
                assembly {
                    revert(add(result, 32), mload(result))
                }
            }

            i += 84 + len;
        }

        usedMsgHashes[msgHash] = true;
    }

    /**
     * if you signed something then regretted, make it invalid
     */
    function makeAtomSignInvalid() public onlyOwnerAndOriginal {
        valid = uint32(uint(blockhash(block.number)));
    }
}
```

### `Bundler.sol`

```solidity
pragma solidity ^0.8.0;

contract Bundler {

    address public owner;

    modifier onlyOwner() {
        require(
            owner == msg.sender,
            &quot;onlyOwner: caller is not the owner&quot;
        );
        _;
    }

    constructor() {
        owner = msg.sender;
    }

    function executeOperation(
        address wallet,
        bytes calldata data
    ) public onlyOwner {
        (bool success, bytes memory result) = _callTo.call{value: 0}(data);

        if (!success) {
            assembly {
                revert(add(result, 32), mload(result))
            }
        }
    }
}
```

## Security Considerations
This proposal introduces a data encoding scheme aimed at data compression. It solely concerns data compression and does not lead to data loss or concealment of private data.


## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Mon, 26 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7638</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7638</guid>
      </item>
    
      <item>
        <title>eth/70 - Cease serving history before PoS</title>
        <category>Standards Track/Networking</category>
        
          <comments>https://ethereum-magicians.org/t/cease-serving-history-before-pos/18991</comments>
        
        <description>## Abstract

Execution layer clients will no longer request or respond to p2p queries about
block data before the Paris upgrade.

## Motivation

As of 2024, historical data in clients has grown to around 500 GB. Nearly 400 GB
of that is from block data before PoS was activated in the Paris upgrade. Long
term, Ethereum plans to bound the amount of data nodes must store. This EIP
proposes the first steps to achieve such goal.

## Specification

Add a new `eth` protocol capability with version `70`. 

Clients connected on this version must not make or respond to p2p queries about
block bodies or receipts before block 15537393.

The affected protocol messages are:

- `GetBlockBodies (0x05)`
- `BlockBodies (0x06)`
- `GetReceipts (0x0f)`
- `Receipts (0x10)`

## Rationale

### Only Pre-PoS data

One might ask why the distinction between pre and post PoS data is made in this
EIP. The simple answer is that the at the moment of the merge, the block
structure changed substantially. Although execution layer client software today
continues on with block data on disk which remains similar to per-PoS data, the
beacon chain is now the canonical chain definition. Therefore, a beacon block
can be used to both record historical data for execution layer and beacon layer.

Over the long term, the distinctions of &quot;execution layer&quot; and &quot;consensus layer&quot;
may matter less. This EIP tries to be agnostic to client architecture and
instead focuses on the shape of the data.

## Backwards Compatibility

After this EIP is activated, nodes will no longer be able to full sync from the
devp2p network. To continue doing so, they must retrieve the data out-of-band.

## Security Considerations

TODO

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 13 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7639</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7639</guid>
      </item>
    
      <item>
        <title>Intrinsic RevShare Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7641-intrinsic-revshare-token/18999</comments>
        
        <description>## Abstract

This proposal outlines an extension of the prevailing [ERC-20](/EIPs/EIPS/eip-20) token standard, introducing a seamlessly integrated revenue-sharing mechanism. It incorporates a suite of interfaces designed to foster fair distribution of revenue among token holders while preserving the essential attributes of [ERC-20](/EIPs/EIPS/eip-20). Central to this design is the establishment of a communal revenue pool, aggregating revenues from diverse sources. The token, in essence, embodies shares, affording holders the ability to burn their tokens and redeem a proportionate share from the revenue pool. This innovative burning mechanism guarantees that, when the revenue pool is non-empty, the token&apos;s value remains at least commensurate with the share of the revenue pool. Additionally, in periodic intervals, token holders can claim a portion of the reward, enriching their engagement and further enhancing the token&apos;s utility.

## Motivation

### Revenue Sharing for Token Holders

This proposal standardized an Intrinsic RevShare (revenue-sharing) model, allowing users to claim rewards periodically to ensure the efficiency of liquidity. This standard can inherently offer a clear path to long-term benefits for holders with revenue sharing, achieving a more sustainable token model by rewarding holders.

With the inheritance of [ERC-20](/EIPs/EIPS/eip-20) functionalities, token holders enjoy flexibility in trading tokens on secondary markets, and an optional burning mechanism empowers them to actively contribute to a deflationary economic model while obtaining a proportional share of the revenue pool.

This approach also encourages active participation in open-source initiatives with a sustainable and multifaceted revenue-sharing ecosystem for Intrinsic RevShare token holders.

### Funding for Any Project

This standard enables the tokenizing of all kinds of projects with revenue. This EIP introduces a new model for incentivizing contributions to open-source projects. It proposes the distribution of Intrinsic RevShare tokens to active contributors, creating a tangible asset reflecting project involvement.

Notably, it introduces a use case known as Initial Model Offering (IMO). Many open-sourced AI models face a challenge in monetizing their contributions, leading to a lack of motivation for contributors and organizations alike. This proposal seeks to empower open-sourced AI models and organizations by introducing Intrinsic RevShare token. In leveraging the token for IMO, open-sourced AI organizations can conduct fundraisings for essential funds to incentivize the ongoing development of AI models. Moreover, any project utilizing these open-source models contributes to the sustainability of the ecosystem by paying a designated fee to the revenue pool. This fee forms the basis of a revenue-sharing mechanism, allowing Intrinsic RevShare token holders to claim a proportionate share, thereby establishing a systematic and fair distribution mechanism. Importantly, this revenue-sharing feature serves as a guarantee for token holders, fostering long-term revenue benefits and encouraging sustained engagement in the open-source AI community.


## Specification

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

**Every compliant contract must implement the `IERC7641`, and [ERC-20](/EIPs/EIPS/eip-20) interfaces.**

The Intrinsic RevShare Token standard includes the following interfaces:

`IERC7641`:
- Defines a `claimableRevenue` view function to calculate the amount of ETH claimable by a token holder at a certain snapshot.
- Defines a `claim` function for token holder to claim ETH based on the token balance at certain snapshot.
- Defines a `snapshot` function to snapshot the token balance and the claimable revenue token balance.
- Defines a `redeemableOnBurn` view function to calculate the amount of ETH redeemable by a token holder upon burn.
- Defines a `burn` function for token holder to burn tokens and redeem the corresponding amount of revenue token.

```solidity
pragma solidity ^0.8.24;

/**
 * @dev An interface for ERC-7641, an ERC-20 extension that integrates a revenue-sharing mechanism, ensuring tokens intrinsically represent a share of a communal revenue pool
 */
interface IERC7641 is IERC20 {
    /**
     * @dev A function to calculate the amount of ETH claimable by a token holder at certain snapshot.
     * @param account The address of the token holder
     * @param snapshotId The snapshot id
     * @return The amount of revenue token claimable
     */
    function claimableRevenue(address account, uint256 snapshotId) external view returns (uint256);

    /**
     * @dev A function for token holder to claim ETH based on the token balance at certain snapshot.
     * @param snapshotId The snapshot id
     */
    function claim(uint256 snapshotId) external;

    /**
     * @dev A function to snapshot the token balance and the claimable revenue token balance
     * @return The snapshot id
     * @notice Should have `require` to avoid ddos attack
     */
    function snapshot() external returns (uint256);

    /**
     * @dev A function to calculate the amount of ETH redeemable by a token holder upon burn
     * @param amount The amount of token to burn
     * @return The amount of revenue ETH redeemable
     */
    function redeemableOnBurn(uint256 amount) external view returns (uint256);

    /**
     * @dev A function to burn tokens and redeem the corresponding amount of revenue token
     * @param amount The amount of token to burn
     */
    function burn(uint256 amount) external;
}
```

### Optional Extension: AltRevToken

The **AltRevToken extension** is OPTIONAL for this standard. This allows the contract to accept other [ERC-20](/EIPs/EIPS/eip-20) revenue tokens (more than ETH) into the revenue sharing pool.

The AltRevToken extension
- Defines a `claimableERC20` function to calculate the amount of [ERC-20](/EIPs/EIPS/eip-20) claimable by a token holder at certain snapshot.
- Defines a `redeemableERC20OnBurn` function to calculate the amount of [ERC-20](/EIPs/EIPS/eip-20) redeemable by a token holder upon burn.

```solidity
pragma solidity ^0.8.24;

/**
 * @dev An optional extension of the ERC-7641 standard that accepts other ERC-20 revenue tokens into the contract with corresponding claim function
 */
interface IERC7641AltRevToken is IERC7641 {
    /**
     * @dev A function to calculate the amount of ERC-20 claimable by a token holder at certain snapshot.
     * @param account The address of the token holder
     * @param snapshotId The snapshot id
     * @param token The address of the revenue token
     * @return The amount of revenue token claimable
     */
    function claimableERC20(address account, uint256 snapshotId, address token) external view returns (uint256);

    /**
     * @dev A function to calculate the amount of ERC-20 redeemable by a token holder upon burn
     * @param amount The amount of token to burn
     * @param token The address of the revenue token
     * @return The amount of revenue token redeemable
     */
    function redeemableERC20OnBurn(uint256 amount, address token) external view returns (uint256);
}
```

## Rationale

### Revenue Sharing Mechanism

We implement a revenue sharing mechanism wherein any token holder can claim a proportional share from the revenue pool. To ensure regular and transparent revenue distribution, we have incorporated the snapshot method, capturing both the token balance and the associated claimable revenue token balance. Periodic invocation of the snapshot method, corresponding to distinct revenue-sharing processes, is required. During each snapshot, token holders are empowered to claim a proportionate share from the revenue pool, creating a systematic and equitable distribution mechanism for participants.

### `snapshot` interface

We specify a `snapshot` interface to snapshot the token balance and the claimable revenue token balance. This functionality ensures correctness in tracking token holdings, facilitating a transparent record of each token portfolio. Regular invocation of the snapshot function is essential to maintain up-to-date records. The `snapshot` interface returns a unique `snapshotId`, allowing access to the corresponding token balance and claimable revenue token balance associated with that specific snapshot. This systematic approach enhances the correctness and reliability of historical data retrieval, providing users with comprehensive insights into their token and revenue token balances at different points in time.

### `claimableRevenue` interface

We specify a `claimableRevenue` interface to calculate the amount of ETH claimable by a token holder at a certain snapshot. We will share the revenue between two consecutive snapshots. As an example in our reference implementation, assuming that the revenue between two snapshots is `R`, we specify a revenue sharing ratio `p`, ranging from 0%-100%, and we share the revenue of `pR` to different token holders according to the token ratio. In this example, the amount of ETH claimable by a token holder with `amount` tokens at a certain snapshot is `pR * amount / totalAmount` , where `totalAmount` denotes the total amount of [ERC-7641](/EIPs/EIPS/eip-7641) token. Noted that the remaining revenue of `(1-p)R` will be retained in the revenue pool, and we can take out this part of revenue through burning.

### `claim` interface

We specify a `claim` interface for token holder to claim ETH based on the token balance at certain snapshot. Each token holder can only claim revenue at a certain snapshot once, ensuring a fair and transparent distribution mechanism.

### Burning Mechanism

We implement a burning mechanism wherein any token holder can burn their tokens to redeem a proportional share from the revenue pool. This mechanism serves as a guarantee, ensuring that the value of the token is consistently greater than or equal to the share of the revenue pool, promoting a fair and balanced system.

### `redeemableOnBurn` interface

We specify `redeemableOnBurn` interface to calculate the amount of ETH redeemable by a token holder upon burn. It is defined as a view function to reduce gas cost. As an example in our reference implementation, the amount of ETH redeemable, i.e., `redeemableETH` by a token holder with `amount` of token to burn is

```solidity
redeemableETH = amount / totalSupply * totalRedeemableETH
```

where `totalSupply` denotes the total supply of [ERC-7641](/EIPs/EIPS/eip-7641) token, and `totalRedeemableETH` denotes the total amount of ETH in the burning pool.

### `burn` interface:

We specify `burn` interface for token holder to burn tokens and redeem the corresponding amount of revenue token. A token holder can burn at most all tokens it holds. This burning process leads to a reduction in the total token supply, establishing a deflationary economic model. Furthermore, it is important to note that tokens once burned are excluded from participating in any subsequent revenue sharing.

## Backwards Compatibility

This standard is backward compatible with the [ERC-20](/EIPs/EIPS/eip-20) as it extends the existing functionality with new interfaces.

## Test Cases

The reference implementation includes sample implementations of the interfaces in this standard under `contracts/` and corresponding unit tests under `test/`.

## Reference Implementation

- [ERC-7641](/EIPs/assets/eip-7641/contracts/ERC7641.sol)

## Security Considerations

### Deflationary Economic Model

The introduction of the burning mechanism in this standard signifies a shift towards a deflationary economic model, which introduces unique considerations regarding security. One prominent concern involves the potential impact on token liquidity and market dynamics. The continuous reduction in token supply through burning has the potential to affect liquidity levels, potentially leading to increased volatility and susceptibility to price manipulation. It is essential to conduct thorough stress testing and market simulations to assess the resilience of the system under various scenarios.

### Spam Revenue Tokens

The extension of AltRevToken with the ability to set up different revenue tokens introduces specific security considerations, primarily centered around the prevention of adding numerous, potentially worthless tokens. The addition of too many spam (worthless) tokens may lead to an increase in gas fees associated with burning and claiming processes. This can result in inefficiencies and higher transaction costs for users, potentially discouraging participation in revenue-sharing activities. 

A robust governance model is crucial for the approval and addition of new revenue tokens. Implementing a transparent and community-driven decision-making process ensures that only reputable and valuable tokens are introduced, preventing the inclusion of tokens with little to no utility. This governance process should involve community voting, security audits, and careful consideration of the potential impact on gas fees.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 28 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7641</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7641</guid>
      </item>
    
      <item>
        <title>eth/69 - history expiry and simpler receipts</title>
        <category>Standards Track/Networking</category>
        
          <comments>https://ethereum-magicians.org/t/eth-70-drop-pre-merge-fields-from-eth-protocol/19005</comments>
        
        <description>## Abstract

This EIP modifies the &apos;eth&apos; p2p protocol to announce the historical block range served by
the node. We also simplify the handshake to remove total difficulty information, which
isn&apos;t used anymore after the merge. Additionally we propose to remove the `Bloom` field
from receipts transferred over the protocol.

## Motivation

### Block range in Status message

In the history expiry working group, it was decided that clients may drop pre-merge
history from their storage after May 1, 2025. For clients that want to sync history
through the &apos;eth&apos; protocol, it is essential to know whether a peer still serves old
history. A similar idea was proposed in [EIP-7542](/EIPs/EIPS/eip-7542) but was later withdrawn
because a political decision on history expiry had not been reached at the time.

### Removing Bloom in Receipts

We recently discovered that none of the clients store the `Bloom` field of the receipts as
it can be recomputed on demand. However the networking spec requires the `Bloom` field to
be sent over the network. Thus a syncing node will ask for the Bloom filters for all
receipts. The serving node will regenerate roughly 530GB of bloom filters (2.3B txs * 256
byte). These 530GBs are send over the network to the syncing peer, the syncing peer will
verify them and not store them either. This adds an additional 530GB of unnecessary
bandwidth to every sync.

### BlockRangeUpdate message

We want clients to be aware of the available block range in their peers. The new
notification message can be used to detect sync status of peers, and adjust fetching
behavior accordingly.

## Specification

### Status message changes

Modify the `Status (0x00)` message as follows:

- (eth/68): `[version: P, networkid: P, td: P, blockhash: B_32, genesis: B_32, forkid]`

- (eth/69): `[version: P, networkid: P, genesis: B_32, forkid, earliestBlock: P, latestBlock: P, latestBlockHash: B_32]`

Note `blockhash` has moved to the end to match `BlockRangeUpdate`.

### Receipts message changes

Modify the encoding for receipts in the `Receipts (0x10)` message as follows:

- (eth/68): `receipt = {legacy-receipt, typed-receipt}` with

```
typed-receipt = tx-type || rlp(legacy-receipt)

legacy-receipt = [
    post-state-or-status: {B_32, {0, 1}},
    cumulative-gas: P,
    bloom: B_256,
    logs: [log₁, log₂, ...]
]
```

- (eth/69): `receipt = [tx-type, post-state-or-status, cumulative-gas, logs]`

### BlockRangeUpdate message

Add a new `BlockRangeUpdate (0x11)` message, with the following encoding

`[earliestBlock: P, latestBlock: P, latestBlockHash: B_32]`

The new message should be sent whenever the block range available from this client is
updated. In order to reduce traffic, it is not necessary to send an update for every new
block. Clients should send an update at most once per epoch (32 blocks).

## Rationale

### Status changes

After the merge, the `TD` field of the `Status` message became meaningless since the
difficulty of post-merge blocks are 0. It could in theory be used to distinguish synced
with unsynced nodes, but the same thing can be accomplished with the forkid as well.

The new `earliestBlock` field is technically not required for history expiry, but there
are a couple reasons why adding it can help:

- It improves peer finding for clients that still want to sync history from p2p after the
  agreed-upon removal of pre-merge history has taken place. Without `earliestBlock`, the
  client would have to perform a request for history to check if the earlier range exists,
  and assume that a failed request means it&apos;s not there.
- The new field can be used for census in a specialized crawler. We will be able to see
  how many users/nodes enable history, and in which implementation.
- It prepares us for a future where the history expiry window is dynamic.

### Receipts changes

Removing the bloom filters from the `Receipt` message reduces the CPU load of serving
nodes as well as the bandwidth significantly. The receiving nodes will need to recompute
the bloom filter in order to fully verify the receipt hash. The recomputation is not very
CPU intensive. The bandwidth gains amount to roughly 530GiB per syncing node or (at least)
95GiB snappy compressed.

In Ethereum consensus, the encoding of receipts differs between legacy transactions and
typed transactions. Typed transaction receipts are &apos;opaque&apos; and have the data wrapped in a
byte array. However, all receipt types ultimately contain the same four fields. With the
removal of the bloom filter, the networking protocol now deviates from the encoding used
by consensus, and there is no need to replicate the weird and expensive encoding used
there. The proposed receipt encoding is just a flat list of the required data fields.

## Backwards Compatibility

This EIP changes the eth protocol and requires rolling out a new version, `eth/69`.
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
`eth/68`.

This EIP does not change consensus rules of the EVM and does not require a hard fork.

## Security Considerations

None

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 29 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7642</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7642</guid>
      </item>
    
      <item>
        <title>History accumulator for pre-PoS data</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7643-history-accumulator-for-pre-pos-data/19014</comments>
        
        <description>## Abstract

Defines an SSZ object for accumulating all pre-PoS data and commit to the
historical hashes accumulator&apos;s root
`0xec8e040fd6c557b41ca8ddd38f7e9d58a9281918dc92bdb72342a38fb085e701`.

## Motivation

There are two main uses we consider for the historical hashes accumulator:

* for users who wish to download the pre-PoS data for the execution chain and
  verify it without executing each block, they may simply compute each block
  hash, accumulate the epoch records, and then compare the local accumulator
  root with the expected value.
* additionally, the accumulator root allows for `O(log(n))` sized proofs to any
  pre-PoS block, whereas today to achieve something similar, one must
  recursively verify the header chain.

## Specification

### Historical Hashes Accumulator

The historical hashes accumulator commits to the set of pre-merge headers and their
associated total difficulty. The format for this data is defined as:

```python
EPOCH_SIZE = 8192 # blocks
MAX_HISTORICAL_EPOCHS = 2048

# An individual record for a historical header.
HeaderRecord = Container[block_hash: bytes32, total_difficulty: uint256]

# The records of the headers from within a single epoch
EpochRecord = List[HeaderRecord, max_length=EPOCH_SIZE]

HistoricalHashesAccumulator = Container[
    historical_epochs: List[bytes32, max_length=MAX_HISTORICAL_EPOCHS],
    current_epoch: EpochRecord,
]
```

### Pre-PoS Root

The hash tree root of `HistoricalHashesAccumulator` for data before block 15537394 is
`0xec8e040fd6c557b41ca8ddd38f7e9d58a9281918dc92bdb72342a38fb085e701`.

## Rationale

### Inclusion of total difficulty

The total difficulty allowed so that clients may return the value for specific
JSON-RPC methods which support it. It is also useful for verifying the TTD of
the final proof-of-work block.

## Backwards Compatibility

n/a

## Test Cases

```csv
epoch,root
00000,0x5ec1ffb8c3b146f42606c74ced973dc16ec5a107c0345858c343fc94780b4218
00001,0xa5364e9a9bc513c4601f0d62e6b46dbdedf3200bbfae54d6350f46f2c7a01938
00002,0x98cbd8a95ae7dc9c1ed823156d0eab9aaffa869f6852cab18ff0083063f27d26
00003,0xd8b8a40b8cf6818e1bac871d882e772be0b28d1baaf72374946506d9e6fa7d75
00004,0x6e3baba7e324b99ed72d98f0255d25ce66832736550f8b971c12280eac2a0bb8
00005,0x5cff5a4b7284b1a4a6cebfcc80d876ab0418f71254d03f91d46a9a1fab49fa09
00006,0x678fb79306f84e9d0a4749323dc29934ca59b852fbc7c8d2890eabe8a0cde282
00007,0xd9bc682bc5bc63b20a8344407ae12cb17e2085d448f438efa6aa5d522b913a20
00008,0x12c9605f2d8d4738f9aa04fbecdbbbc8b77135ebfaa9db399135c14e1ef10bee
00009,0xf9e4e8905b214c97bb4ed1f69178d6ecc769e21352885147fce5b671215db2a8
00010,0x5f5d4516b7a38929b47ea7334b62b53829b9665d37f752d96c33fad0f7f78583
00011,0x30f04eb968efe4079356b873e37f1657984717e60af612ecca95c98226528d54
00012,0x5ecb9bf9e193da08c7e7f22abcd50d1b4d3c2b909f980ac1315856cb48ca49cc
00013,0xd0175c1ed6e694180c4c161ac7f06a913784daba14dc1d2e926f72def4f7f65d
00014,0x4f92d78141b7fa8d6fcef45f9dbc611f858447629eeac2d63bb43d07e6bd1aca
00015,0xa47cb8eb7157d56f718a6896c2ee1843a44e3de81b9127e64b78fc38ee382310
00016,0x9344d8b785c0e619d0b1b83e5d7b3849d667f1ec0d0d6390d26fa33dd4cb31af
00017,0x43963724de4a8917d16d8c6a663c38fcdcf3ce5b89a51bc766dcd0ffd1d5aa32
00018,0xefce27b480c92a0e7fec472fe38e87ed9a1c91c3d07324cc2f262de3916a38f6
00019,0xf5434352253a7f35d909fb2c383e7cdad65761c509eec24741197b869ebcc212
00020,0x0c405203cb7b2e54b910e5d953b5378ff4f0c3bcebef92e7e3a1f240dd6703ee
00021,0x20d8f1af038c2777dea9f86fe9e33f14af9e4270ee20adb32e0dddedc4b85236
00022,0xb694d8955851f744e44c68fba193f6bc41d1159036531c5f55fac9ce91883695
00023,0x11beacba76e467dda23253f104d064b00ab75672ab33cff6097be1c3e8ce7053
00024,0xf216a28afb2212269b634b9b44ff327a4a79f261640ff967f7e3283e3a184c70
00025,0x987cb6206e5bae4b68ce0eeb6c05ae090d02b7331e47d1705a2a515ac88475aa
00026,0x3afd50ff0edf3cae577c42bfc39871f0f0ffe7bdd5ee0b96f7b2e879c9b29994
00027,0x28083285c935c0c169ea1406f9830701ff20fde3d0b2a5b83efc1cd13139dccf
00028,0x362fc97cbcfa6ab609f1a3f8ca2f8a6e0ac6061c33e84a285a14713cfd73f203
00029,0xa0cb99e26e896f5d115914910c4c66fc112ae240bc827acdd564785e738ff29c
00030,0x78fc5e8e58e6dd726499295eea1f7f52a31979c6a003d48d4e027d95285e851c
00031,0x52306cf9ed840bea9d8c3466bfbed5ffecdfd51107f33d013a487c3b653b3646
00032,0xcb4d0c3a2384b890a8acd698da6b9ae6267c5365fcc516391829f7adbae838ee
00033,0x0c3781bbc07124e29ff67754bdcf556b20ac4f4ef19ddb004837ec50193ce0bc
00034,0xfac9315aa442073b647e71716a7acf1c170e5a0092b69edc2a5634813716592f
00035,0x737e07578f0dd5eeebd8313e58cdb59ac705c0ba07d842feace53fa2922c6508
00036,0x84c7c1e7c4a8949247953858992012799d323ebcd0fc6cdecf8002f20f2ea7e1
00037,0x34d067652cbea843a01e70ba75566b6f174218969dc453c285e59b4f309faee8
00038,0x38aaf94c653d619b1a08e7cf9fac72ecc57715bc19ba236c942d400742bc3f16
00039,0x4ad4940c51be350c9d8c69f424f01a9e87e42fe6b312afae3f8f7267c62512e5
00040,0x4707f60dffab08b6837078ae91316ebe04a275aa19892462521cb6125913d3d7
00041,0xa6a87a9e797af923887645fc57602d60f7cd684357ae837a6270936eb6e5ebd5
00042,0x5c8dca3c7c7842995372aed15fae7b9bada264b56082bec19c870bd4c7562b97
00043,0xcb513d912a6ee576a33cf3683d596354b57484cfb4d7e382f64326eef5bec32b
00044,0x1c72a3909e56831cea647e4c67faeb91db49b5be8c61832082041c16b2072e87
00045,0xa87afdc1e1d225e6826d8f18c15c0415c7d13ba2a3933dc35816491bbc64501c
00046,0x22b3f78d1437187866a86fc05463d5afa558903def2357a05ffd32663d5b7896
00047,0x92d8437253506251ea652d6242ced9f3941906d4ffaa78edcb396a6c5fcad7d7
00048,0x78ae53ed63f208b18448b40e3c31476eb2cd6627d6c65ba7dbc96d3e1051dcca
00049,0x3934e9608386c1bab748cf80199b6b6341e581a163c64f6c0bfc55d36d41cc64
00050,0x71698ebf74b826ce701bdda7c804c2b9d0aa3616bc1ccfbb62d4455cc2b0bec6
00051,0x2c1c77788b22e42409b9e068fc98a28310af7cb451dbdc2601d29771bb117c47
00052,0x3a047d9aba82db1eac26733dcc652c0aed663250b25781360ba9596db48ebe01
00053,0x161ee1b5102e9c6300c04d4885dda180e50f3e5078ca8d2bc1f3d0af0a9d8287
00054,0x14074ce7acc2ad4e4d60966d9717d8f2e6f7d28cffa1fccede05d4ab7269b772
00055,0xae639ad86664191274136f85177a515b7524be9d089571f5e24c13bff9f91a38
00056,0xd92c394c57df45119161e4ffecf8445e3af06c79c90987db86db649f2cbf7840
00057,0x4bbe776e7229c9583ccc6da7d82451b56ef1fc015c802c27b2d364ffff7c6e7d
00058,0x9ac60ed891eb7490ae1a5fa1d9c14ef66b01bf5fdc6f31a419a28c2946e0c3bc
00059,0x246c1b33d8b91d3fad3c3b88d6aa04cd872bdf0608aafcd1f11a53c437418eec
00060,0x4533d0c5d211593355e4bf1e07564fc04bc158e75437f33eb97ec9066322b3dd
00061,0x122db1c231fee4e86b938a432ae95eae69a3ea733b82b15c2d784c70be3f9b89
00062,0x65505079e3493c2fb572db2d1d9e455ef3e48be78c18f760fa6724fe1326f5ff
00063,0x39b219117b1d306e0e9ac0a8f969d47f1cc375d7593e2c8e0996fbb80822f293
00064,0xdb26a83cc55bf6f8c6ff63525fafd2c8dca1a0cd99828afcdbc5d3146da18dde
00065,0x1df3a40f96ae6291f081fcf9dab9ebe03382d958cde909a4cb7cdc76201fe006
00066,0x07bde22d34d4cd3a29214dd2bd1c35a49190a3df40505ddddde8e3622c6e7cab
00067,0x751bac833356761ab2a1794fed46b04afcbc60d23e608a707db5b897e5d042d2
00068,0x546a10c136f0cb0c85bf58b69e04424ffcf1b00b4afffd3f33c5ee253899367b
00069,0x55c236ed7566681663e88a71b9597a48970297cbc0ee8b23b1d302dfe69f61f6
00070,0x0ac3ebb18ec9ee6c921f36d5053d9343ad81218f797c39376d9e4f4352c768c7
00071,0x2fb03713d78b7fba05408f872267c4877ed8db5e1bd1b9f1e57d872c5cc08adf
00072,0x2f9a4a75044a49046297e71c578329b8326352fd49bd01158f42c73ea6948454
00073,0x32871a4303777114e0f17126567013d94bb2884ea22bf0a103d45fef47c4b005
00074,0x8aacdeeec1021158c05056e5aa2ea4cc4994aa2372f5d37d22272ed065f7493d
00075,0x368ce2b13e74f99ef231825ba5df588d654ccaea62e0ff46d012b879608454d5
00076,0x290a4131608502c9423b9ec4fdbb4cfdfa245ec92a571053702cb431d6d661ab
00077,0x5d736b0aecc493c6160872dbcc216816071483a4c4518a2284bbaad9a9c592c9
00078,0x98ac3e9dfdd27556bf5d5e037d10de525ad1142c1e954de9cc3b7e2287dc9ca9
00079,0x95e0734eb17b4182d2458e6f5268abbc75c44e743b5abeb775d99bfdb1d1f6a2
00080,0xd778ae86ee6b3ed9f3f3dc83a5ece367faa9ea230daa21c07c54e073af83f2fe
00081,0x2089ffc8e635baaf3e1673f9ca3ed6d64b1dd02dd73aa5c2beb692af5363a1a1
00082,0x382ac3bc7f5de4df286366863351ae1d3655fe5df7aa195e3f955e5cb4988bed
00083,0x5ab1cca211eb959107d5541a30d1b9f3e8a6fcf9935643acabd4f2dff8f3d212
00084,0x9ec0497d2130e92ea521793e98774962fe83ebd994fcac4963cede93950efaaf
00085,0xf847bef9c0f4876906d74c0955d362175cc4d9bb83f134d60dad7bf3df6d0b3b
00086,0x0dd5eb92d78e345af8ac60db208207fe3f4621e5ea09f195da8c977418c358fb
00087,0xc0612d68f34fc28c18a095b0062d5762cf56d5c6554d94a0e97315ef262a4dd7
00088,0x3f433e6334fa2b3d05edd615d92926aaec56b355f9375e3ea4b91ca0dd7c654d
00089,0x0432ee13cd0aab4c445219c8edcbf80bd502d11170a2724cabad19f55d8f2ad1
00090,0xcf23b0c8c31f2368dc982efbf1220f64439b107d691450a3eb15dca1180f5854
00091,0x9fbb0197fb4b50008c5feea2810b0336d38dba1958fafdb3482036e6ad269895
00092,0xf88ab15fc925643c8adc5b3485f19240e4afc53dc777f0c9bf9ab5c6c6f3338b
00093,0xb7499b8c5bdb76c9a892b9e0d09cde7813ed0c38740d25743d02910f337c3c6a
00094,0x5c45bbb126771f6277dca461a28239b4efd388b55afe6ef1c6e595ea4ebd9509
00095,0xa3dea11d2eef1db4c8855ae369918a0e12de5b99e0087e3af0105ceb1ed1e0a3
00096,0x91ff33f7ed74652bdd22a154aeec0cf24542b29477122dc02704000ef15dd540
00097,0x8e4ffd2bc8e767d8848b4d001c20a7dbf942fe73b20f6821a2abd586c8462334
00098,0x4c5709afb1a85d25d9131fe5e441ad7f0d5d4608583c07836ff4cc2e3228a30d
00099,0xd55b92c14fec40d8ccf4fee501efecf9f71ced6d787eb3faaa4cd7050f3a3e08
00100,0xbb39d00a031359e390914a91d9c26c1b8dff1b6d8ca4a44ebb64d5946a5451c0
00101,0xe6df19425c17f10ef876e9964f7561bf3f7bc41fdca9151c26797f38e4a064e4
00102,0x2aac9e21e2134958f6ebebe21acaa65142ccab41a0ca386aad4eb4c383b69145
00103,0x3fe56c2aa4b33540147f05427b757a5ecfb57a4301a84022a0a26c57bd1f5b4b
00104,0xf3269b3047cc6b5dd1f38313ff3bcc717b44375148a8637e4ce41ec39a9adc57
00105,0x6f2f86e801b6456e59b5f4c6d2587ca8e5cfd97fbf93dcbd11b7c3cf65b83170
00106,0x621a252741c0cc84c5e7e3b01f90d30d86474348f44cc659ff48000093671bbd
00107,0xc3e8f7cdf2b7fd8a0ac98834d4ab1374e8aec4644fc722a04db5abd57329405c
00108,0xbe1a1635522e1529456595e0615c4d3c53905a0198ad65320c8ec1f7f3ec665b
00109,0x49424c3e48cdef7a00003a3ea76da66ce8f833df83f74580faacfa7cbff5dd28
00110,0xaf29e604357c6c3d6f8a23c69ab648b8b19c0bac3e7e8ffcfe3d23f62c585490
00111,0x1738246f2b0b1ba4a084cbe299233f487f3730d8ebcac38bc6cb43e503992248
00112,0x0074a32e1420b57f8f7c142a61d5d945fa0df577c3007b375dc4412c46e774a0
00113,0x56e191304d05e3370a821bf16ef43a7528b63105a03b425fb2c408ec21807233
00114,0x10c2a569cfef2c20fbce1953dcabaa463cae1daf08e83a38322091fb1da59db0
00115,0x26efb6b7b8a822fcfb126451c09491efa88a986bf3ee4f0bcbc7ff5610f051c1
00116,0xbdf3bc6e520513ff3ca5382abbcfad7f2bc857db708233a07f17149d57d66648
00117,0xe68e5334db9c4e799fdd67843038b909e231e8f5d248af1cb212907554ccc352
00118,0x1c9a243765a53509f7ac091504edfdb27fe9e22f9766a7cfa02e0f87ba6774b5
00119,0x5fc6b689c399c8151792427fa1e9b44c6453f520ea15ca643ec14cf1860b3397
00120,0xcfefc65fab88cf757198c581e272c0e02d6488f4447b87dea8c908cbd8b3fdc6
00121,0x0e29b6cdd3b4816acfbd104ca56b2ed140958c37fd4f7d9dbe5d62e1e7444e61
00122,0xcddbda3fd6f764602c06803ff083dbfc73f2bb396df17a31e5457329b9a0f38d
00123,0x7717d3958ced7ec038af0b4d7daaaf2ab4da56290db865faaf96da59e9babf7b
00124,0x2e66a66a8ff5e15178ee8c9e500475b7badb71cc65d26dd6074e8faad109b427
00125,0x82fdaab150f1a25c78a2a0253018fc5a83c420bfed8ec727f6c98e1571b39b6c
00126,0x427637ff154cc2036316442348c319c019515af54dd5a2c702527b87f6ea4611
00127,0x65e302f1d26bca3ceb600bcc6c19190d2a5e9723a47a99e0710f4ea1fdf9a2f7
00128,0x6fdc1fedc9d9454ed6b7f1067da89f57ee4c4e298767cebcf549b37c38b463e3
00129,0xc8705b6e734dc09bff141a739eddafc9a3016ca7e7078a09439db7785fb4e688
00130,0x650f1d51006a9afa156973b7080774340dbff7334f6d4941729ed1fd39f4bbd2
00131,0x7b4435cab2538749da96316d2068854b40a8cc5eb4810155954acb70ab8eefec
00132,0x23bd760353974c8a41e410bb24b6aee32d19eb703692420d375da68ed5b8b4a9
00133,0xc0faccfc19b41bb694cb86c86b88760dddc771125caff85b33ee5cf935f5106b
00134,0xec9cf3ec39f1bb33d363eda9d803fd63de89a5b4afeed17c9bb5185b784d4cc2
00135,0x66f5486b3e5c79a9d9d10d4ac5581bf89b4068376bf05ced98455b7d50b08844
00136,0xdc4ebb94b5007edaa6be31715620430cab85927af56ff7efcd8e5c4df5b2912d
00137,0x022982006526d25c7ee022373f4832c10fe42c7aa25b26044ee3f317b812c221
00138,0x3d2314001a3de949f8cf44018b245fe6522bfe212ecae7b8e1676505d05c9905
00139,0x5f31661180c2ee22f0f7209e38c1c2aea2fc03384aa0ea1f9d8b98cb0747ca5d
00140,0xf13c9fc08dd8e3fd03250091f66d0cebcad41cfb4330d6e68bf447863d2f8201
00141,0x17dbb0e39329cd8b2bf6839de0722241211c8a602c233f48302e50d7e6aa6361
00142,0xe42539c839845c3033143db80f7bd316ab323114554cca363c2f3ead3ed6a68d
00143,0x5594a813aaa2752040681086954b21e457ddc5a8f1d816b45925eb85ee7528ee
00144,0x5ac2296fd274fd53197c615a25b4fb6f4303b17a977954775f73e036981eb4f0
00145,0x9244d418b8875cb5a463decd0f8cee235755222f2e72ad97810635975f6ffff8
00146,0xaf9e7a53390b2fe7c833e937cdbf627a8ecb39da70260eda50ad0af37b4a2d1f
00147,0x1b6fa332dd5f6b04e3fb1a027b63f2513b4159035d3294b0212899649b61da2a
00148,0x39f0b0575eec3daa97f64b9bc538f841242003a72256fed04e015e78f72bb92d
00149,0x586c4a913ddb47e0cd4847637cccd2b458a09e35e10b29451febc5ce8f19f696
00150,0x3ff89a4a288f9325e315b394c991680a5843acde1412d0539412363b08ee7c4d
00151,0xe322efe1b787fb583eed8d19ef06ac5660c014e566ba2541c160251273f8eaf5
00152,0x4d9d0d1c39a4d03a8e4def8892d713c4c9c84df804bd2da90e20e596c99ff6f1
00153,0x6b5702b39f5bde08d74649594e48ef49faf24a19c5d7ec75d8cf490157f4f201
00154,0x13608c120fd377b160206bd5f9afe2ed660ecd8a121210faeaec26c9b6010975
00155,0xd0bf6ce2d1f149196b41e2379831cd9e07d215a9da2be8a2b772be32a10b3f64
00156,0xb8c3629c89fbf5c93a481688d05e108af37f4ca1152e2c1ce66de366db58e934
00157,0x97351a9d18fe2307ffc128e294f580eb5c9c9f48fba6a5f4f25a0aa98d97fac8
00158,0x5cee8f8c5f208a9d23dc367deb3c47e1b3e186bbdd94f2812ac27b40825de041
00159,0xb92f84e91d955459a2de86bc28544a82ffaf23c6175f657f767303d63cf8b842
00160,0x3e41d9f5b9538accaac888b49abc201aa3d71f5aa6c516a97e69314886989788
00161,0x0736b99a2882a562bfd35db27b128a498711834107fd2c0356063b406ed8c804
00162,0x0a1530daf01f3cddb2af69fc527b5f7635aab2d02adc46e5a21f8344eed9f7b3
00163,0x43212d3b60bfcccb6b12bf765fd072f8785a7d41dca097e37ea14b7c8faf6d85
00164,0x3744a01c5c7968e2230ec9d29de8a370db7f43763ef8f22f58cbbdf13f27eb1e
00165,0x3d14fc84c9f2dafa748275285205ae2b29df613c8f982d1f334d661b1511f8e2
00166,0x97c2592527a83d1c2c514f447e8ae6fdb1481c0dc9c4a3f7212049c5eeae578d
00167,0x1148500252c17babbed0e2df0e3913dc380f7c0a06e680d4ba101748620660b4
00168,0x88a365fabc60615ca56960314ae6006f61df6fe729a40341c12bb3c98045a4dc
00169,0xf18242e71a0c97722f01fbe9c462e0fe857d93a43f1d683fff9e36e4d3ad59df
00170,0xf03ea8ee5343e37601df81cc61173e6276516b1f69225a8c1a94fb079545957f
00171,0xbec8ccd9a6e13443a8e61a931138f3cf6218a2b477d11ef59a082f898796c439
00172,0x34a4c5d21fc33c31b415829b9e46c63588db2327e3ee13682d52233108a2af25
00173,0xe1ae6c812dc2ca1cb0613ab42e6c81721f96e771b13c79d284dacbb30c65e5aa
00174,0x727d10b81b790e7f5f608c35126fafc3523c7e991bfdb8ef018edbdd207b4c24
00175,0x1bf21dcc47b8d4ed6511e49dfc4bc14c1f40f2c21464d52aba8b4a50c60e3b1f
00176,0xecc872aa4aa1c53bdc3c22687ed31f1373db111f1c1219286f857b157f6990b0
00177,0x966bdbf23d2e86326afccf08377aac0067d485c6098d90c1c74a84b34b8eea3a
00178,0xb412f22cecb0219921846638c68908fbc2d73f3d2c7d32d7d86795e9f48c5145
00179,0x09e40d3b668d4808509a521703734da066da50c303525314712713c5dbc6a2f2
00180,0x8ce22357ac0066d519294b9ab476c222a2edf3cbcc4e06a2df0504ad11f5c1ca
00181,0xac1cf418529f5346213890d7f11ccf4a21e24023d40f2eaaa943606f8b7a1e6e
00182,0xf770e12a39d1ebfe34919a211fcedb2098ff562689be021bbfb8636f756c4b95
00183,0x798224ae95fa5281f29cdd3ac9eb753ca8e9ee44b9cb2c5747f97c8d71917b58
00184,0x876fdbe53a7831817a5e123f1b043700f1f3d47f685b772dded35c953d629e5a
00185,0x7b447a76548eb9c28145371f61831a2dc941acd907804808a7ab93f7c171d621
00186,0xf1e11ac5a67e45142b1a1a13663c725f82a84d5e59ddf65f3b740dbd028b3d63
00187,0xce8b009f996254d6df379dd2b3a5aba9dd1d3e0b64de28e5838b43f411f42e4b
00188,0xc7bd816d6d55b71c0f6784b2925ff9e1daf65bfb238fc1bb4980274130b500c9
00189,0x144cc97d4bfc31469fec6de2cc4ab5556af13aa4b00b96081692ea64092c592d
00190,0xcbbcca518e96049a99aad9b53f2e579cf866d6c8fa3a69e407404a3508963394
00191,0x3a7f648499e877f2451d3bb6f1e90e5e48ce653459849d52aef5b1f04bd7a9cb
00192,0x8a4639c3f8df41e06f4af80ecd6227823708c39128cd6a791e9ce390d9bcc7c9
00193,0x52629553fb11ce8b1f53ad71c3ec8fa911ff6e0424b7c0a015922311888079d3
00194,0xc4828a4b7616281c5e82ba47e691de8a9975512f0d9033b098082cf027e90236
00195,0xf50a165e20e68aa37f97ead770fd9710ccb7b4fdc80581b5982f1d7a219feae8
00196,0x5c31919b4d982bee212e5d30e35fc2998d946a0c124e54e3e2c27fbf8d129494
00197,0x9e2a709b9953cd0e76df8b6f36d2cee961b24aa19ed11c6def3f5a1744c1755b
00198,0xc3e781bf3998d0fd70bdbdf8213e066bb31636039606d9763ab9449cf73ad5d1
00199,0x20c05ee3e79b3ab76d806ae93d9cd01340ea68c007816dcedede0635df91850a
00200,0xdc265ad95ef9c500cecb8bf2a5da52b3f29d171aa981c8bd9ccbd6ccb7696e69
00201,0x1356f2dabf963afe35b149a0de796d3e48f87bc41d9a516d4924854af52dd709
00202,0x84e861144a0bfc933935e47097d963e8591a0f321cdb7ad1d75d899ca501df1e
00203,0xf2da7b50b32ed6bc786564ffc8e7b85ab250ec0eaa0096dea3faebfc9e07bdc7
00204,0x7f42b43f0556b03846f18a12da581203682f8d2266fcd686b388970ea6229de5
00205,0xafd08f8ec73d9a83ac8b099ba3202cda132e9e07e3dd18738dc4b5b1f0d98e93
00206,0xcf4a2c657b1cf55f37167bf85a51ed104eac71967a98bd4c02a42dfc057c02a6
00207,0x59a0e883c7a7087b9c330ae4703d0cf263eedd8d20466e313c894519235f5d44
00208,0x3d0bbaf203bdf186daab82974347c617e1210a586751ec6c9818185d0a096e3f
00209,0xc1041285ee311030789717024ad66718f6184a03a0d31a1ce4ccb0948fa17dc5
00210,0x1eb673abfb14d61c67d81d48dad2b7f72080a90fe090b6846779fb78046402ff
00211,0x01e5a4d0cf29ec996c00f168d445f55eb3552f213200a247c4efd60d4fceede4
00212,0x83c3bb0ad1f3784c92a88909ab533c62dd5e7b3dcacbaf624ae95ee12022eb11
00213,0x9a09fe68cd5dcdc15ea76f08eac7e2a679075e772064354c747b75e5ddca8d2f
00214,0x9e78dc12bf0023bdf0c8c1b8e7f7c6e5a92d66b56475594bfa334c129df58735
00215,0xb02bf96a7443e246b6733270453b35a70ff1fcf49375cedc97338614ac65ac51
00216,0x209c8b324d31fd9d8c8c4cf26f6506657608e6816471fe522adb1425b5ebd04d
00217,0x6c84f49aa1ae7943df31f340739b2b63df7476e87cf0ddf82862982456865c95
00218,0xacb60f14bf4bdc96ce579f02f62f8bb35db16f03dde7329363bb50388c3c45b0
00219,0x0a773645ba0627df6df44158e292f2f226ca74bbc90464ec4796ac2e9bf26578
00220,0x76ed2324a565e51cf2a82bd0cdb025f255caf25d61396d4da19d708c40adcf92
00221,0x76ddd2d829c12483b2ffec2c587557bc5972e08dc8866708a2d44a31575483d2
00222,0x71e986b22213ce63d0e3df141581fca8fbfc41569f0bcd62c101c67cb00295b3
00223,0xca2b5c289ff78be184a6cea0f072aa71cfe0977f18bbcca536b48938e5d64276
00224,0xff571e13e54cdc9ca6facd7012051ee787bee1c52a555653fd969751bfaac7f2
00225,0x1cfe32398c41e4ecdde6cff7b2df6f9f2651ee87aae1b52bc35e4d76f136c3a0
00226,0xb0eb8f2f68728e48a4ded02891b9a682f7c925099e899c26143083850b3f2829
00227,0x83556e9f3d0e05c0d4cd809cf1bcad1557bfeae027ac4de16e6956596e8309fc
00228,0x7651e7fbd8326e549f9af9122585f517c4f59ab6e735cd958888fb6f80f29db3
00229,0x238ed7884113c0356cf4e5ef35e05434d3e076428884b93bbb873ac30afef54d
00230,0x3826affaf4ebf5817b453c54c937951770c19ddb7900c9a7742919c24242f6b0
00231,0xb81f93c6179db089673e919d91660274e96f240a699a12a140185c69ac19b674
00232,0x0cda2a75d5dd4059a2e5712ac7cb151f033b700995e93c0819f38cb01b7f005e
00233,0xb183167b3a03238701597a198475ccec1308e2c55babbe5d5acb92fcd694fa21
00234,0x4a88300d556d8a8d66669f2d2b395263ded44d9a86bd45b3b426a55f7da8eb22
00235,0x05ef61436ee159233c382043f0a9e99d34ed88a0bf3c12244f546b7b861b9f5f
00236,0x4164fdf451a7134e2faa3672aa40a0168e2a16895020c0cd5632322793fc96d1
00237,0xd5c9eed4c1796793e8595d155187444376f4b5478ea5ff1804f1ba06bd328506
00238,0xdb0d90c5045dec94b87c81a03fb985a6fb84e1debb372b56c2513f25d4a2d8f8
00239,0xa0c972ed0270d34b19b803a74649470307f138ef0567df85ef53a862b383dbdd
00240,0x9cc1a86a28230bad01981b644067885e0333588976edef464aac674744c9eed9
00241,0x8ab5ad435e4c9a37815b47344d282c90a3f364d516374b4b2158cf16148d79de
00242,0x491f232e15a8a44b1f045dc68552543672c6d3bff361a5fecd7c0a54c1f21d2f
00243,0xf66eb348a6b9dd916baf6bbab3299c57b9d95e5bfb585893f2953209c2c451e8
00244,0x7b141f131b2878edbef5e71682051e3082490e755502c0372e5ace9cb5ea3d5b
00245,0xef5b96a583318ef2d24bde313396aa09dd5d102cbd270b95c036bc6db98349a5
00246,0x32d63aa14065862ce43f33e578625a2892710dd11025a9299f8722421c625874
00247,0x7b033a6c76470c8b7b953161d562fe30c90705672f950a176de70a6aa5f1b130
00248,0x50916052436d167fa83998749a703038ddb08d7cc789c276099235f9af28a613
00249,0x75e0db34d48e90e80705be01c100e3767aa3302d4269a00f4c944069ea451ccf
00250,0x4781ac7f896d2a547f2a973fdd352d5e9efb019939bd10ab31f0f84887968831
00251,0xc0f8b33bf4828ab6578b5312d922b37139bf9c1d0eddd973f5ee84b39af48a28
00252,0xafa72ca222af4feacee96c6a64a4b05a1fe464f9ed48e93e13cdb096d0147d25
00253,0x96c6ccb34878fb040117b6933c7d7f1ca4f534dc63ab86d2cc4914b06786331a
00254,0x7b32050e8240cfbf7ab11e4b06647d363c83aafa32d78cf34460b335d0e55a3c
00255,0x16317cf915089e0c7cc1afb35540a004fa2c79e75f4410dbd89e6d9fdb2b89e1
00256,0xb4ccb50be9c8f0759450e6dd9d05cb16778cc2852c0f8aaaeaa118a45267891b
00257,0x98808d165ea3e628d92a93cfb1081e68254c4e2a48eea8c1cb3771772ee0fa74
00258,0x3cf61b1ca697e63092bcbaafad3cf25608f47a9b6563bf8dc1720eb2a7fbe384
00259,0x051764d24d14c62f71e8df8e9eda01d4edba8a9a52cf50ed50dce0d06f33bbeb
00260,0x3b0545e8512ad0ef40623a237e1461577102fb2d6aa820dc0a9420d62f1a5942
00261,0xa6f4bfcafda2d4cfc8bc900a5f844d60a50822aff332f7aadec3157b12a8d1ba
00262,0x1a75662f7da5af8abe9f73deddfdbc4fa23772f28a2968eb44dab1e413238841
00263,0x21bf7eeeff2979facb0c0a59ebfe07e4f110c9f7417217a341039ae2deb4c6d7
00264,0xd41eb83d2e64d9928f6c18e95060bca40c3226b4982f91dc97a518201aac8fb2
00265,0xe7a1956113e4b4c440a7ca46855ad2d2705ee3c018770e3fa8f8a3b3a6b6d6a9
00266,0x4f172aab43c6bec97adf68392b12e82b4512ebc52df0298ce3253672fe59135b
00267,0x7c0e1bcfc2aaa6ae002a1bc3fe0ed288598013b4c0dbce889d4b41cc8f1c792b
00268,0xc839e6d47fa99f7bab58ca9eea51d6306873f67fd286ddeca8348a09c773cc42
00269,0x9ec52dfb6facec401f848cee38bd6eda4e3429291939754a4985eb8ae969787d
00270,0x4e8bc7277defdbc8c904f780c9b6f82c214816b5379e95490c7f0052a7295465
00271,0x5294c75dc9cdf4c43f683b6c02c9078852607faf9dec990339b74476e0c0108b
00272,0x02a11db25d807b03efafe32a0ee0647b35d47506a7fac186bb51e3c3a77a5655
00273,0xd81a2c4138adf6e8b1af325a9a0b08ce6a0b3b72a79b367118294bafb4b832e9
00274,0x9c4bd87dc1b25b83302973a9c4223cda44c1200ea2a83106463adf6317bdc605
00275,0x85b9c67dc6b5b7c0014824f8b1909633459cd0b8e1584753064f85e1a1243c8a
00276,0x38cc12366c2a7d559e4df0705bb822d8d0db59221de71477dfcab90e317b2e97
00277,0x40c70f952d1ecfafbd064b1367045570b703fdbc7059cc7f9194ed34794d1db6
00278,0xd9e0d7381580a9f3fa81e7a8f582967f09e1e87f0e4c5d08221edf0434053608
00279,0xd20a7b7f9138afec7ab17bcc1fa4d77571d78f12bac193db64cbe046d0bcd1e6
00280,0x54a85faaf00ddd99bf86faab4ddbd028b8d3f4e8f4492d1c7160aad9a03db638
00281,0xf08b974956e8b7c14b335bf82add248bdf06a9626ecd6627ae0cc523359cad9f
00282,0xa5912776593b35ee8dbca404e0c36497dc410062c0e5f4c6b40923232b17a8ab
00283,0x8ee7ec35fab36575d9e5105303fa547ca8a03b6ecf731cbb64b9823250323d25
00284,0x374996f2ff5de9c6262168bc93fe7548bc6cb94d45dd4dcce211a9be677ddcfd
00285,0x9494258571f7dda74ed018ffed536e412f5272028442ce932677668613278035
00286,0x6d47a23492f0ec9831f3536b4b542b1addaa041ab9f9cb6d2f6821a5f9ed6646
00287,0xf9804151a4dbbe0c86e08b2109fc328a287ea4ac10abfbe01a9bcc866e7422b5
00288,0x3724a8c948c728a89eb03af19c3be5e7e26abde6713e6e9ab5559dd21f8e095e
00289,0x60d72bd902aef520fa3a0fd618cc230a50c8cd3951042f5a613b3d45f0b94c6d
00290,0x64cca80b0eb18b315b2213ad5e2b53dfcbb1141ffa422ad46e7cb3586a200aeb
00291,0x0dfa92f2d0ff334ed8306b33e6d3325720cc13aa0f046d53a2de144d89b9af92
00292,0x9490598864a1e3ce2241136637de020cf275921f59545dbc4ecf4cf87f678b84
00293,0x0d6c5812bd1b877d8715198580c66eab1ddaa78e1dc350e70eba0d59e633cf30
00294,0xf6c5c94a2006aa624d007104ed8debbb32ec15423382e4759bc7a16a1357d5ed
00295,0x4efa78d05a58e9b1e633443b058c9f8d447728e0ad64a50332f848199f8a4253
00296,0x81c1446a12d42c3ce40f4a99326cf8e5a306ab72c773ac26f63a63cbe0a58064
00297,0x08d13a3189fb2e18636d6beadbc137a79d03d9278c60f80829443348b8c560a4
00298,0x3d1d6d89bcfb495fccee7bb0bd8f04715d84abe14f94fb36f870e5606c2cdf18
00299,0x23728d43eeafdcff8f761c5a53e3f9373d25d17efb28347a91938484e03d07cf
00300,0xde0332534e50154c9eac98068e56da4508d82ecf24ca3a275aeef3dee99b95e0
00301,0x15a24df990de83affd9aa7cd9e67f4c558e1b3f306a6281385cc2e6409b9793a
00302,0xba653536adb3464fdd46fe741d7daa1514a84f7555bf7ed91cb4d3bddc0a6f1b
00303,0x35fde006dd9552f56250125ce80ad21476daf78f8727b432cdb370372c161a65
00304,0x377bf395fc2a3ef98595766247a1c057a05d5fd3629bfd27d0bede0c6183a7f1
00305,0x340a0b81056d5170e635ef43d952b8ec4ff7f3d5cf4ea1469750448d78f3e501
00306,0x848e3d92711946156cd7c848947d2ba4ee4c0b39087ea30c90eb1e64f8aba773
00307,0xa3ff791642f87c2bffb269a1da3d8e943a1828cafe10ea7a483a508f78ab54e6
00308,0x48c7160cbf3a38ea7299edf971711e9d6875969dd38ce2086763389d9fac048c
00309,0xe7948131b78ed9f05c0e18ff0497a192aaf8c5d3c1a56e1096570b3b45117253
00310,0xdb22eaaf717a1a827a085d3960e2a477a2e9a73584bc4a293377ac50a492350f
00311,0xf9e4fff98d04206dd4004f5ec146e676327dc8399dff7c7eb61d1d80f706d3ea
00312,0xd95903d02e93dc935ce569153d9c88680972dd5e9156dc0a7f4da9a3435ff004
00313,0x73f91876f19025335210705149eac61825673f8698bcf5aae285c00051fd6f6c
00314,0x8e3397949f833d550ca3a268befa4c48c238f488572b2512f8cb5232d78dde24
00315,0xe83123f07d6e146998f885c5c4f71988f472b9769e9c731d421327f3f4add351
00316,0xe49c7af7a328992fb98e65057e28326f3684f84293a6b9825ef8297fb361a186
00317,0xf3ae6a628ac464fc0f14f4654dedf31ab553c9750bbbc801e395ac858bbb619f
00318,0x4bf5c84ae3ef17b5fb6455380d4708dba2da9c9224c4a31a0cb14ed4e8eb17f0
00319,0x391837c44adbebf55ee138d56c65353612b31c66f1cc02663b7f088b80dde22f
00320,0xbfd4677eb2bd0210ee172956700adfcf8b5164982b533a191907f62ac3f6ae1e
00321,0x7189f4963254c00f349ebdb7f507638472c13e083cc525be744de2ce8374e1e9
00322,0x344663aa7240ee9c312f31e5111dcb672451ef971ec1375fb8a298c676738c7f
00323,0xe111bfc2e481e928c91b0d0a5868221c8699e22fbe87852b3bedb3124072659a
00324,0xbe2b4b22f7c8c897ba0731eb6342e075c338b8feb2791c31be1d20c6c47f167d
00325,0x441fdc4402e5b407058b634523f6318e2b6ac078414720bda9466129896e19c4
00326,0x4297936031236c915aed0b391555294f1df7b346889ca02edd1313b8fbd73298
00327,0x820afe74538d0b05b98e1d16604fb60bca79f04c56fa724e6d2af5532a5b45e1
00328,0x08665862041221b6d297f4e7619b1044eadbdb92ec1415e916e9bc78558aafca
00329,0xcc85d0d955b9068c848b56435b53e7eef8d2a1266cfd92c46544594a1b7c06fc
00330,0x8ffabe96ffed7125caf2395331a37eeeaa016c1fbd0af6ddbaaeaa4ce3a75428
00331,0x57c9aa448a060ee1cbe8a7b5236ef301c090d29baa0f644ccb23661b7933b4df
00332,0x3135b7344e51ce37b6f82ad0e1ab5dde01a7cbf154ec76ae394c6e99fa866e68
00333,0xef368f009534af83848b1ad36c874d1cd28cbf792663db122dd8f7f123506966
00334,0x1c3457cf9b7bde27ad51086fb1ea494d78e82217cf2477f79ac8fc4cfa610f25
00335,0xb191a95efc41af23eaf794aea75d4b4c9308a85647f6793201533b30b3d9d368
00336,0xb5318d5c8c6f173084a7d838110e3e3de8739123b4ec387658c0b579cb87fcec
00337,0xa84d51fe94498ad9c2f558ad6fe685d9aa73ef5ab52c794861277e690ff27d65
00338,0xf0b5744f941d4eea8fa255edaa9f7af5028da4900c7fd0b2a1214b00c33f96fb
00339,0x5a637c4c3cebacbb0caf5c8bb9080288270e8f2ad3106e50ce82a65bc27386a5
00340,0x6bd16b95991a8cfb3671511c673093106b4aa7d626edd4558bc58ca67f8054c1
00341,0xe0d9d5cba01b6dc8c430de66d0503e58b9be6195e7a767fc26e15277af7a08fa
00342,0x203bc599777747671b50d1ddcc78edc4a180537d2e6fe14610426772d1caf926
00343,0xa668f92ec27ced688ad1ce7eeb4f437996bdc213ab001f5d548f5e283f243754
00344,0x9cfd6013d6c92d918e19c4b6118dcf5d73e9070af0c7300f8db0ccc7fef5e89a
00345,0x54595ee743dc095ed8c3a82f1c0ae34ab2ef7ebb494286a990be0f6b9e85e6a8
00346,0x2297e35e02ef969b43a787aa88feb7e101a21fb5d73a81af1c4bc06c57a7c3bf
00347,0xdb8912b310472c79894387c19d79d84113709d05057c043380ec4ad8145991fc
00348,0x1dde5ab9d554e74a5635f8042ccee5454b215eb598cfbf696a74a459fc1ec87f
00349,0x7e25d7fe6b0e71c03d401537f46ea1628e91513cc3991171227d6ec165058e2e
00350,0x2bce5715759f8e6f9f17a735408e410f9965ac3cfd27e2c710060f3778d662b2
00351,0x112b61e1ad4e349919eadac971bb9128d385eb3f51668b2895cb978f148a83f2
00352,0x2ffd764d428f87651d62f1a1113874042f1c77dee8b999524e896663e1a0e000
00353,0x8d5ed81a06d6bb19866099c16d80a7dfe3ebf9c642236410a5f3f491fabab7b8
00354,0x78c57cc6fa8c8eaee7bef3b0573faacf9a42783f39c9a307a3cebd4a66a56e37
00355,0x55973475ad5f1404bca12aec3688d80cb5881796a9d0a9a917245f8ed9bed47b
00356,0xc7493a6e7fcfb05ceb9f11b9af843556bea9f87883a2ee21ee76cbbb769204fb
00357,0xe5dd91711b000ce8cd41d02ec760a50625f924fcf7a095353f6965322881fb94
00358,0x60ed8451fe763621afb94803cbec04b48e9ab83c8d05e2ec1524e623dbe0decb
00359,0xeeb9573da28cde717ede462163188da0c184c4aa61e166e9bc4ee047fa0c170b
00360,0x277ba2fed1fae84aa2b23a43872100f00b7699326a22df5679115b1dd88c5206
00361,0xfc97c47f7bf57fce450809d63a32e255db170aa3fbc94c88d9b15a09f22e2f8f
00362,0x77f810e72a7d1aa4a164ba9f7bf0164b6f14842dda65d584508d7f403942c319
00363,0x056ef66ff214f7a777abda23d7c32c1ed17e2d25f3e5e4299e11c22412bfb1df
00364,0x374faafad27fc139a45b9a73cb5957de978227d494de6cbe4d9bb4d48fc26197
00365,0xa959566e36f4790873b779f74d0b31b5c08b4177e844e430fee9c33c190839c2
00366,0x905c4a521e63de87fdd413379e245a1c8c2aafd1cf92e5ed6394892a635e62a9
00367,0xed4e7dab8d5ac5eb9d4e3b711be5a5074eaceee1936455fc145362871d64faae
00368,0xb4a84335f5900e1df9ffd45af119abb6808b69960359257826702a0792dbb9c9
00369,0x1f3be8331532a43391f286dce1908e750c2c1db4f40e04240df8a49b15077ffe
00370,0xccf6672e6da5a00cd8ce25a1dcd7ac9701d10e13db51b249cec8a168fbc1fad3
00371,0x1aa762ac08985e6a081e59742827fdcaa0194f37db5a03574bea395a548c1ae8
00372,0x05d7f23c6cb10f2e5ea143504193e0c18799879225cc7bb9f548c2a7bca406a5
00373,0x9a8322055f128164d9b1ae8be520dabd5aa9a78e6b38887d2d0ef1c29f8fe5fb
00374,0xdab73b8e1681ad78f5948c11596f320dc9e37833a372a4bb75131ae27144789d
00375,0xe97d6f9f8cf09791cfa7d844116e30f30c0c25a010500db0721e1a0794a0f0bd
00376,0x6af73957e98a3366086abd58c1d750803706d7bc3ae2bbbab4eb6030d58cb244
00377,0xfa0bd020aa5cff144e0c34ec5a67a63cd593c607905dfd7a8697796a7641385d
00378,0x85b101eb40a52a559a3bffc4667c2fa220ad9cacca9a34c62c684e87cafa5e56
00379,0xfbe01c0b7b7e3e3434a5a4723c3619f544c6fc91324421172c74b3aceb816f39
00380,0x3e90265a2de6ab0f66324c687364be3c3a4bf46b96fb5dedc4da99c2a59c66f2
00381,0x0b316492b1f48b2a578bf289dbfdcfeccc756410f0260e2b14b8b2bf972ab173
00382,0xa02e585dc76ee230753d64e6f49d31f6c785e03834bba8acc2fe3f97b2b0de67
00383,0x2198573b3c6f4e37218236277eb87d39d60646c6a46b7f516de4ee75f7eb57cd
00384,0x0c367f630c9a45d6320139277a8d2f880118a31a856daea875c5a095986f50fa
00385,0x8893c8da5a5e2df4e794962fd80bf6d4b8785de5ec445115f1851f601d92afc0
00386,0x30637c5e41cbd7671b1b2744d5abde33576904c2fb999de2262dde69d552b4e5
00387,0x069b5e283383b315d1a151162386e05161a9ae0704c2b5d3162d18fe91445c14
00388,0x82890633807a55f66db32bbfbc7eddec26666cf69d927c6ec17d3e52839f3d3e
00389,0xdef916eb755fd6d271775e79079003b9851e520c744dc2fc544599069a2f9a2b
00390,0x00f646779628de768f0a78b66f79310092a7eed1b1f42d871bc14945b31c4dab
00391,0x6055482350dcadf13a115468db04f05b533177f9cb92ce0d1174e80cf72ffe92
00392,0x01eb08ec62a30cb0bc16493c077396adcf2921cf45e7fe07f8ad8a9eb3cb2486
00393,0xa5b5b2ed61c5a22e51f28e7081d3c57657bfe1ee7ca90ba380e21b0c29bb871d
00394,0xc96f2c65a9b708e26fb06146840df2ba2fee86811fc64b8b03cb8da0e864cf21
00395,0xc7c791690e0a24e565ad4325f0916eacd1472c5c67ed9d08007f519ab5ea4751
00396,0x98f01c73bc56a14d597f9a2fc522c1f9ce473d5aebcf9f025bf85e10ab5e69b2
00397,0xece428f5e482195f4fc650d8ba4535cdc50da4bbd6daff83dabf40f0fc1cb264
00398,0x15d52476e016b06a31965a6f867703d8e72de4d75952ea588619e24d16946860
00399,0x07f402789b0a04c5c653605ae4a4d9b538575eb278790ee1fca13e1f47aa85a4
00400,0x837a78da3c31e197110da75373e9161ec3630eac20956d4976bfdfe5a3f76705
00401,0xf319bb85477c7540c8296e257ae3e9887477cc5ce6615e79ff465e67447ef449
00402,0x28918ded462955d7564a1cf7515dcde37e47a0bf649af47ce19c1bd2f42420f2
00403,0x8d3e10d5ddb059e88145c8a640d6f435b50abf014464ef4112bb7153172e8712
00404,0x729d063ef003bc0cd25960f423adc378a96f94bf330e2894980e229c7f792827
00405,0x3857def7fbba5ea6f0330f98e7810ff7efec3dec752c7a72961925ebb55935ab
00406,0x7be7d5cd302192b0891e799f7fd3dc6214225bac396740ca00eab0987afa0e15
00407,0x0a5da5b2bd5353f6dfccb3173ffc30d765f1abae1eb3fe1a2ba70a4c9e69144c
00408,0x4ef48eb40d14a101421b182a44e62e46058b24a968731f9672658c2998359339
00409,0xe4148ff741b9ad3ceebc501e8db8796f923b39918bc4e003164b490a0b61d9a7
00410,0xb195d1d07cd0b541bde741b4086345048fc40eba5c36958db1e84b72f813f9ce
00411,0xab2766df14efa74b0e28bb35708e39d6b1ca1d0bca5a94ef65b5aedfb53bb200
00412,0x4fcf3d8ce7b02562b9f72decca131bda4095b44bff685e901c1a5b5d29ad1bdb
00413,0x371970b092f836d650467a8ce9b049da8e286f73b4ef1063380be6ec1c07622a
00414,0x7525f2eda283e525441c353da10bdc982c0b1ff04dea2c153b3543fdad000b73
00415,0x4820498a2f344d87b28241909d366f5be00766e75b23645c45a09c75ec8dfdb4
00416,0x55dcafa7fd60cb0110e64c6d5cc69db5f031a572e110368f9067151b0890a0f6
00417,0x9a836ceab0f6c37b3523b9df29cd0434d420819221ef1063600765b3ca5f522f
00418,0xc524844779cb06e98494028130b971a762f7e249dd1d79e08acfc33d7927aae8
00419,0xaa00e84454c9ec2852bedc300676f8d20bda558c13442ec8b9a148fbe5d37098
00420,0x1a718263b17245356ffb42bb178e9590283ea2e0a82ff52dab5f904da8951895
00421,0xb7a7719554eabde85fa9f5bac7580c6f352f60a460f9a07fbe87fff47ba7c19d
00422,0x05e01b82ba2d8b2fda2a7e149186ae56e933298b9251269a4e2eab1717f44fda
00423,0x0c5c203528a51dc0cc9a0852cea64ed0debab06b3ac95d012870589a5ae4c0a0
00424,0x7d31cd1ad7743f0c08549c8aba82c3914de61f8637f768725812dae0be1c3cf5
00425,0x737fc2002808f4c81dbad877b69160a9ebdc3f8382b5e1f2f08defce897857ab
00426,0xb042cd22b27a2d46775de19a0fe07ea0187139b69a8a5f9f8ad680b49a50e81c
00427,0xa5f8fadbaf1e1b1c025e9ca7646d214d84afa0d2575026bfd188492553ad2dc9
00428,0x2247adf42e4fabead0c52c18fd8d9c3d378b6a82dc3941e9f2e7c03a3e6a5316
00429,0x1cae28d5c467521d0a2986ae1ab697c0137fb88a2cd57b7b65e1087002f4ca8b
00430,0xab59cee6f8c573ce2e2abac2865d1590cdcc0e4289aa75144582810327d2bffd
00431,0xed24090f25bc8dca7749c25f4d6a81a6c0421251b40e9fefaaf7896a49e1cec8
00432,0xecfb2f473b32475d203492960f9c706024ad7be82ced8dd0f9506c2cedf3b29f
00433,0xea10cb3faf85fe26801f5c5c6f963aa09936d48cc6070abdc86ef7c1ab93eb6b
00434,0xed8823c84177d8ffabf104566f313a2b2a43d05304ba6c74c2f5555bae0ef329
00435,0x1acee0de8d8fa5a692ca7fe4e6e6b6070264bbce1d27bae29aa96794a92fffaf
00436,0xc3510bf4ec6f2561e65ef90ac5f69719835bd88ebc526470a11645a2c743696f
00437,0xf2dcc620fcc9352d6e87c27c30f9dcbc38e05c66d4cc315a6b04b3007234821b
00438,0x00f5e21daa244de11bbc15728bcda77c7c15fd858252459ad7c10c0ac877ae9c
00439,0x5149508dee482fd1927f619b3984641ee6a4cd545e763475d97a759cdd6b9ce4
00440,0x9feb91891bf0aa0981ae9b6d8a71dbec00cc4a2ebf9a94a0aecc1815d621b2c1
00441,0x3f1832caadae9d68b7056679e7e36db138a48754d0bd69f0f7c369ecfff7763c
00442,0x1d30de4aac58ef2504ba7fca3cdc0536a6129314efcf91c713578bebd2182e6f
00443,0xea71b6f9916c2fe3cee071ccbbf4105935e111b40d71ecc3b327ae5a992a6d49
00444,0xc56da958661c206315768f8f855721cce15e24ff1f350b294a1331eb29db56e2
00445,0x02cff3d78ac49a70b6466ab49a54dd2695b8ae3a423b9e52dae2351864ad4e4d
00446,0x2280f1cf6ebfeddf1211be1d8801bb188f0afb1626da2921ee603ede2bbcf926
00447,0x3cff32e3d7dbda7c7efec80b3c9ceaf9c56b9d5d0c03b53cd12897c0ecb8a59a
00448,0x7dd2c4f161ae53d17ee1bce79c6dc3a848fabc81c2ed01d08d768e02c7ae8b19
00449,0x6d1d274b948411de02b87258045266f96be9a450a363da2482a1219aecf586cf
00450,0x2b5e114981c6f32c8a3b78fa35ce6132d9ca9b597dd94ffd91b77657f5e51be2
00451,0x4abe0e076ff522ec7b0eaf0d6751f9dfb7f164b42864e0255f1502a77315178c
00452,0x42606107511944b1c7dc61fd2d3467fc43128e69092df1eef47479dbca67f3e8
00453,0x23cdebe00f8b0071fe04101936e236e3dcb4e58b94a8101a0f449ec38aaf53b2
00454,0xb2b5e5f97f7552d912156e250165b87cf670d32260186a1a41c47bd53e4b7f51
00455,0x54943c8b31b13a4f0cc4f3472967383de372b4ca8f89979f6043d44ae330888b
00456,0xcab079083dd2ddc43386c219d265ed110b97d315943e37e859764ddb5c380a2c
00457,0x82d06ed1ec9bfb436ed64caeb0a1c99efdc719d79167ec9600fed7802c5cb1ba
00458,0x2bff3cd79eed0180444dfcbfb8fb93579be52e5d0eb92fcd3ae6c70702a93254
00459,0x29e03017ed0f32215c0705d87beff1ecde7afc804217ec41c250a0541e71dd67
00460,0x6f2ddb12b11f17f35b123ca3692ac57b18043af935e33eb2f662fa0fe862a866
00461,0x86535bae04792f1724aabb2201189ef0b12ca7624e1e9fd296d129d3ef1f74f7
00462,0x3658342ed3dba9eedabc93cae0d6cc657bedef4d1dc6c631113af874dd65fb64
00463,0x4f586d74db2e09c1ddb553421304a352ae8ca4dfcdd49cb9905c83184cd1050d
00464,0x2da57d6c84f0f2de638453005d496136fac3d1a4957f0e6a8aca32070522c965
00465,0xafdd52d62167b3f4a6e0c88d5bd5fffd1f4fa06a528e52f2cf3a095cf5f84fea
00466,0x21cf05fbe816d55dc025ddc38f55aa7e66bcdb98ccff8abfd031c0832f69dd62
00467,0x27685b9d5efe40fe088b50b9a1ea62e8dadeb0425171ad45e6bcc3c283af2acf
00468,0x610466b6f8c2771439da2e8a7343c8d961a040e3bbc73ca6c661e4a13f977132
00469,0x8c5751e2b93bc6f0ddffd243332a890e3794bb3de71a80ca45c95b971be88167
00470,0x2e445b03b86127fe3149c740429382afdd2d0bd2e1ff0b1f05ece2e23470017c
00471,0x7f37562302193a70baf1096ce39a616be3737721795d7a106ca321593f29af71
00472,0x5f279db60b9c122ef92a239345b84ae0d9d6ab6399ef756e89078c9ded3df15c
00473,0x5ae48eaec56b9a49cbb966ec90af455eaa03ee66604e50195cc6ca4dc3f0e1b6
00474,0x8b70d9c82bf64392306a74b2075f1218f3e25ff143962e2c63d0300437bd9794
00475,0xa8e53747848b2eee9050ce20905f07d99282ae9a35ce825ea1b7faf09677a468
00476,0xdd34a7c17094183961aa4c17d9cd6e2e73daeac22f27af1f0d948772d9727e11
00477,0x488d852ffe678ca5d7fd3b4f04afeb893595b929c6a968c2b8e6ff7204be27bd
00478,0x232a4fc9a0cf3b37008375f24a562c44e25a0f54774e2384db37ea0acc0b599f
00479,0x4b082f2481b4819595dba7d5f02505e200b32e78c59100241de37b51720217e1
00480,0xb54b802e1b7923c298d222ff23b5f0d1c8b76b886c764b517a1e29bd4801ebe0
00481,0x213ae81b453ef36e78b560492832c28c71db8bbb5d12816cf0477c16155ab8d6
00482,0x5d09d6eed5b020f1268016d5117587d519d1aaea97b575c6ab24a85135daab13
00483,0xf3c11c6e063ba5b267f6616529b2495424a633e08f6a78bedaa660496914ca81
00484,0xcdc41b84ddcf6530555d2fd03651ca3fcc29981f4b9df53944efe410442174c4
00485,0xb26f2e53df52942461b1c54800e6eb25858b1d86f9bee68c40b8f13ca1fb44bd
00486,0x82b8c438d8704a976289eb09500c628a3c07ceaca62d081de94e345d14bf58af
00487,0xd834f157ce0cabf68f199cabbda6fe5a47256b25acbfaabd376ee9d28d2366c3
00488,0xfa3989a5ba10e3c27731de69a30136ee3ea9e603cb27d12e2a5f32afa60ddada
00489,0x4db390c5cb4c32c03d7f9cd7b8823b700e9d64da825194b83e3df46ce5751864
00490,0xb9ad2e4d9c6627f63d60befc8778777c829594a044f464f12956c904486f7691
00491,0x6aa98f9f56f6ef66ad09f15071de716f61e203ab7a31a98737fd5c46649a14e2
00492,0xebdcd70d9e477a11b4fc48d3258dd5bcf6c9222db25dfef74dff86487714b798
00493,0x3079f6253e59035a7e4a039275e685c9017d7e1055252fcc7db8c4a5c9bac205
00494,0x33f97b590b8f704670771f738f9df52e2037a876fb185f0cecb89fba754af618
00495,0xee3904aea19ec5886c2f52956576a8e81fa4b2bacc4464257c1dc3190d6694bb
00496,0xcdf13c18466bff16c454c4548995f6d11eb639ebfe71dc793b648066cbb23cb7
00497,0x27f7ad957db315648dae2007f3c0c8d7ee81a6c7c3cba09119091325e7ffbf9b
00498,0xfed48beb69c269ece25dd3b123aae953c66433728e03370df36a76624736b61f
00499,0xd9c9a7333aded4d0f68412484ca0032f348c55ce9ecf21c986d22855625b3ba3
00500,0xb11653db38e95638077c58252fa5695f38b933a229decc1bf3d1dd124c0d5f00
00501,0xb202cc73bfc03b7f9f584614f21533221cbd0acc95409239090ddc52b5f27d9a
00502,0x19ef7cc080401251d654b9529fe8018fb1bc1a58cc6b99e8a5a47a40872c5955
00503,0x45f20620961362cc0f7f6e4f3fe15312150eb015de00fe77f6730383c79b9688
00504,0x21e3a8f27e2686892a5cf54955dbf7509feb97114352d211efa8573dc344245d
00505,0x6dd1ba5667a00e35a95d075c187344e3dd341c0b96e9d7c686b1cf8768e2d4ad
00506,0xc0414076dded3d476fba3387ed8b0eb57402f1017dbd117dfaa64eebeb162f24
00507,0xa7340f2eaab8704157b80028c86a7f0cb1fef4864da34554f08dfcb614cf4955
00508,0xdde4c38d485ca458dcaf7dd54cbd451ee8c9eeae251d59b2f5fa6faa97280a14
00509,0xfa5dc42a17a4f780caf728dfc049b9fd56455f05e2ea06202c763ec143b9fd6f
00510,0xea2b8d47198cfdc653a2136b98df5615aee70388df0c64eb5cfb90cacd50a931
00511,0xd5d2416f6a00df2713ec8fa6cc13ef973d1eb9d900d852903fe1046633599565
00512,0xe2918e5026ffd68825dd25cad6ed824a9ab0a4fa4b85a35c4ecf4ef8e0544d08
00513,0xd39eefadcb758f4e3c4e4b34eef2e976c6a3959432abcebdfc78d06bcc3148d4
00514,0x8bd8f6bdf0226ae2173194ea147c71af760a5c0c661ff1f5ad7cac137b1b6d83
00515,0x66d4642ecbc838dc65765a4fcecd474b20b9ae0637244181a84bb373b13d5601
00516,0xed3b11872cdaf7b8feb4ba80cc6635e2123473ceec8e939eb46471c70872bb97
00517,0x5ef487b21fd4c9f018e1c42787966f14f32ed2e1581fd159ea1e4259a6d73cc8
00518,0x710270293ed9c587e43e725361f93c98be4769eace47c2016e4189ef59c5b7e4
00519,0x218c3b62dc99a297a595e41cca22f5f8535ff99908dc03940c9e4a855104b61f
00520,0x062e17197c2a5da9db37319b5a50917706cbb5b2f94436f231515944f5a533af
00521,0x5b55367f4c641c3f847e97b9507772f3defe8e7a7b7e7ba7485a5350838e1786
00522,0xdbca1ed318fb0b730386df7aa1e3093735b7579852cfc869c4ef4bc80cdd6564
00523,0x297cf9d5925da0389d57e13787de1938ca0efbc4fdf2683d957e86f076191df4
00524,0xf389f3b6336ac065daf31616b7dad80bf6e725ffa95b57da3cea36466c04fa47
00525,0xd851e82289f5aeca6786aab0281c156e6e75cce90fb8689cbbbc6cff69f034bd
00526,0xc69972a185d32c7419238da9577424406252b97d93001e401d8649fe6991809c
00527,0x2c103256a2b901f09cd43ae21da8743d4b7c8e5c925d98a67de5579de1d89630
00528,0x32a674ae21d37007a12f57639d299bd71d378c127c3b5bf80d9b7b72f8a89800
00529,0x1bf711d19f7b6ee55cebb887105666aa7f30c594081b4b9bacca5b42c935d68c
00530,0xaab9d4e3f1f4a07e2dc09ecd78ee8fdd50daf8ec5349ce42d33e93e73452e1c9
00531,0x0f51dbcac068fc62805ec9b43a0b1b83c683b23f255eb63cd81ea3e2562953ca
00532,0xb4c6703d6f10db4d87cfd07d94c45cdf6176fc42656997210ed219af1320df18
00533,0xbb2932ed5e95ea609fc5a252cc60087f857230da2797d62330595e0647430f1f
00534,0xc65d109d82fe28526fe4653452cf09db4db6a254c2c3054b8ce3d6cad489bc3e
00535,0xbb367122e14176555be535edd3085bbffe0cfa73f3754ca9eaa10dcae6f60e82
00536,0xfaadd066133e49dcb1a5fa2c92f376f3d165c3b276ac75e5881fe7012b2734dc
00537,0x576b374c1d32e2db299b04073d838366c4525a766e1c10dd8fe0a79ac2ce45f4
00538,0xd8eab6c1d289e8f853425d63e99768ba364012c21537e9be20e9b8999ed94eb8
00539,0x2c32d06d103d4b1f9d31779131b008f404e149a5bd8a53f6805ad0331e592281
00540,0xf3078a9b01c1741a63baca8c231bb4a482e62d835c4eb3ca3ef752154ef9454b
00541,0x3063ad60f10b704d724c082e97a0145796854d3ce3d1550347309657dd36b8f9
00542,0x90a242f8e1785389d27726dab026c0e30677713f67c4bc2747673358990aa4d9
00543,0xbe9dd353aa0b026bc9363961397d25bb46f26570ea7f90ed982373d6a7115c72
00544,0x1c5c761520401a356ed867ac5172ffcf59b1a9b9c6fda3908a4c9474ea075592
00545,0xe6369239027eb6239ee703f7e9e6dfdb32dd1a94b70094dfcadc9fbe0154e4cd
00546,0x2135141345bcdc69e19b4e3df1ce29a017c07fb80df9b27bc38287c2c5ccd628
00547,0x0fd9e031326788cff66e44315940516bf926d51524e880548d90717d0da9d6c6
00548,0xe318be79b341bdbc93f1900e82a5fff4f52df9b9a113edbe4bfaa512d1411189
00549,0x2dde72e5e61c9eea6351d4ff14794a71685daefea6ed3cf9b62ca9aa99f9313f
00550,0xd89b717d47ffb827b1490a37ffd97547694c6ad3dbdee5cd56a3583717962751
00551,0xa8dfd8606b55c4f54453ccf9e48838bca6accabcb629be668755b0a13867a77c
00552,0xd6a3521a5eaec4c47314a4b123701777fb7ab51af66093ad8c57bde9249bfe8a
00553,0xf702584d8c87da3ca916ab9caac71d0a0922884cb8db05cf513d5b4144bac3a6
00554,0x700d58da768be40c844feeadc5f42385dab83a5b758aafc432172fc150403739
00555,0x41db6d144ada4684a7a61e108131d5d78d250b3e47c8cccc85b447e5b1088a8c
00556,0x3503dd53c35d41dd5df98f30d4a4df5f7c4a456edb598cb5c2ecc91cc81198d3
00557,0x02391085f2bdccf3e4774ffe1e0a7fdf318fdebd564f5015c64d6d1edefb34bb
00558,0xed670fa946019be6e96bd20ec27eb5c92bd6177ae0a32fc9cbe2c179cf7f536c
00559,0x63277435c400bbc4916dcf4d295ab0cb233d68834bcda11cc231e999996628cf
00560,0xe89160d7dc2b0d06408df356eb166aad39c73e6fd51e97f5a64d1f6d57fa1686
00561,0xf95c755f337bd6df5127911e601a763a36070bda95ec63ab8adbd1fbf148a35d
00562,0x97a6fdba7ddb6462d9cae6ecaaf13c2ac670f7db6216547a5c20ef46a9a2af6b
00563,0x8aa6ac0e68888875b0afe306759d787609bd56cbad19a9cdbed484cba64b15b6
00564,0xba8486b8d3fc13f529e72ac00fddca459b530ff9a9ec0948a7838089401efc60
00565,0x7cba894eacdce587e611f2740c3de0d15e3754efe0331e976e1cf0150035fb2b
00566,0x54b3e34b615873aa7def6c73d8d45bab4e5f0ee5a9c8e503340ec9bf42e32cb3
00567,0x40280a8567c1cab76c46ea7666b3f17b06a6b1d845922feb286020e7c3439091
00568,0xad863b1e23e92bc3b1dfd81f66371f01eb200bb178d4c1659b39fecc1d5209e3
00569,0xdcb283eaa11602480e3a38aec7563c48bd939a61149760408704f243062dffe0
00570,0xfb9123623556bc897c2f316008fddb109a20ce6abbb666bf55d9f0e96aff0dc6
00571,0xb65f3342d82ea682030d61222badd0d0032f03a44fb33454fd5965edfb57e9ab
00572,0xdc59179d2daa0417c7f7879eee3d53a08066ad558a36cee1535a9b515b0d0cef
00573,0x21aec308be98ab2777b0030e3b55220901ba3e4c2059a076086ef52e11e15e9c
00574,0x55e72fc99ac693fb34bb00d1ed8611d53d6414693acaaa52fdabfd3099dfc88b
00575,0xf6564eb58e1d7f625d3a634513ab089b913301c69a30faa1bb52730be7908721
00576,0x923096d4ee10bb045085a46459592497f6314b580c75c62cda1e27c637f105df
00577,0x5914605dadf8851cf40c7591ff45b182fc6751a233e8ded429a92df0fca49c5d
00578,0x57d591a81cbbb89601aa972f81d25b61b88f534fa7fdbf207611ebb6aa1cc267
00579,0x705b8e045b05fb96483e3356c8b0e0120cfef7a8e9649476bce35c26a8d25f95
00580,0x5b210184902c591dc9dd3630edbe4d816137515009ff3447144360d49ee26317
00581,0xd3dc3f99fc86600deabcc70f3bd7ef4fa9fe70da3a428b2b4ec622012b115d7e
00582,0xd6b2c7ef628b2a4e0be27bba141b8f45946d18ad5d17255d9230b21555a377cd
00583,0x434001606cc9da452057323ef3d56d1cf3505f9dd19aae59e918617e11e180e9
00584,0x21b2682b8046bd14001c17d9a9feb7feda179d3a56f21a722df82042056dd1c9
00585,0x02f0b1510358fee5dda91e345cfe38e0e0bdb0643d0165ebc51cd382fd0ed6fc
00586,0x60d868cb6169cbec6c74545f6cc362b6b44290d889527a728b1af1f846e9230a
00587,0x59cc91f73e2cb552ff57ac76eeb2de51c49f80f237e5e05302115e2d1500f668
00588,0xefefa87ce3db08c5545fc2bb64021e8112434e06ec3760bed7b6440d852cd576
00589,0x85c8dc20f625a20a8d969f1cd97a54a4c760817067763f9992be2e1e9d2d9e8b
00590,0x2bd79cac465f01ebb1eb59886d2b7d2d1c7b7c1debb19d5cea88470aa13fadd9
00591,0xd9b21bd9fc16529e92da39239593c1021e195231affab0eed3475b79e01d8c65
00592,0x9dd2dc6ad9373a8e5e80ec6ec9eba8b0f2242692bf27a93678270986620a743e
00593,0x0a9de411103269d9df322cc24c80bc49e30b0d0021f0a13c84e784a95c1412c6
00594,0x54bb502669ff807c87513c7ac708c471efaf3782d0ff9b7dba577dbd5024a8d3
00595,0x08fa26596e31b58ac3788844e300b057d53983911166d3848105b53c0b064993
00596,0x5e2423f9905b980f953f2c35daf3385540333d41dddd46c710ab7dab864278f4
00597,0x49b11d141d74f6eff4a99a858413e3ab5f3d3740c6ed5c705cd66070af051a63
00598,0x050d0b97623cdfd0c8d202dc6bf4e0c3a73df861383ed307131163623422e0e0
00599,0xa19b1a209ced8078ab2f240886f68b64cc67bd5806a08d472ba3cccefc5eb9e0
00600,0xa81ae85fb6a0ebae94d8df6f34414ea890a7ec7621ac195c683a6d6c34a594a0
00601,0x9e26205a26df3598d2ec6236069fb7a74c37fa84cf323c4fa09f4bf7412e687c
00602,0x287136148ea36dabb0693ef81fe921e25974d96a2724ff0d86b10e3e78302ffe
00603,0x9a115bef53f5237d03975ba6c2baf4377bf8e15ac54bf2093375681a38cbf19e
00604,0xba62e0022781cddf46d8da27f2c69b7c1dcd33fc184b2329fd59cb187e351d3b
00605,0x0d936f160c2fd830cfc16d6c17e87ca0cf6e6b28ec1f6b7d934100e82d61c59f
00606,0xae859b842f320c06c3899683b50a2d37a32e1b07786c761fa092e10e572793ce
00607,0x62d75fce6440773a1c0e6573ac37e429164c377aa00135c7e1c2e2f7b06a4759
00608,0xd449c48d3ab67d1f1f15eaf0dcd5351f9c463f6aa103e6b4ce6a17a3b69bb523
00609,0x7e60445e276f7e090b8ddc8a36a01bc4b66faa212588130c1175a5797a837bb6
00610,0x2f230cba76af9df75862b04ecf554ad6bb46abd4be7a8e99dc468de6d5905408
00611,0x290b8c2bbdea109cbf5209a39382993c21f9d520ff8fd07e85d273de90c5f587
00612,0xb363f64740a275f7816130024de8ccfdbd67fae7526a015679bee407a5e5f485
00613,0x80a4144c9bb6e7aba587a8a91a1362a5edf92e0fc4dbcd339a717a9200cf391a
00614,0x20913bde281d7f10d729b290f509ab76ed07603f32033cb73071f43cef734092
00615,0x8b6e7a1e1535c08d0457aacae6cc68c0385a62a35282179c726707090c84985f
00616,0xbd35481ad334939158e73a3b0e8214993e9de1202e8a8ff567c5dbf88a3dccc1
00617,0x624ad401fff7fe715ab546b1898e5f3e735f42c134d592d49b4615afd5b6d3e1
00618,0xc70c6f7e13ccb5d9a1e56381ac39cabeb4c2e9f1693134d59599b7260bfd7954
00619,0x1b807cedf382c87a6ee8cf00a7178eba5516948a0318aacb8176f3e577ce0a6a
00620,0x850650230838e76460e4ddca3edc33bd286c3f8d40ad3a1ff89b35280cc6510f
00621,0x385fbb21923e5bbca8952a90a3d861ba963d83ddd01c9730fe177341cdb25260
00622,0x92fb5e57d123f079903c0f55481f913c45d490c7df412a721d38cbc528037875
00623,0x642081dd761497e077b1aab32917656570396000b075f9c182ffeb34e905bf91
00624,0x1d72d6273c3ce96a26a5442357d4bd58b84dad51a2eb39f25ec02929e55290dc
00625,0xf7ca7cb8ad47a85c6dad965e8c89bf7b33af62fc5dbfae0f5e141ae4ae1c280c
00626,0x4f92dd261b9f5a9ed03735dc46722963d949ad3038f66ce380e4a1aaec9997ce
00627,0x06e70723c3b912cfe421cb2126e812684742e304f2b8f6d6eb57b1fa959b19e7
00628,0x313cbe432878645b4d887d961d6ff1dcd3c75b508b9263c05ed385754b7c7709
00629,0xe939c15140cdf455b99492b6259ecf0c93ff858719948940f54dcc0d202988bd
00630,0x1fbd3e9af1082f0e99094876294f6a857d8162f32c1f583eba1618acd2099a17
00631,0x333c0583cffee0f355a1e3ccb6aa6aa16c80ebdc789e698c5f0f17521fc75035
00632,0xbd6027f363c5a6efaf7d6f483653d256c6038a628064927411e970280a7ada9e
00633,0x2fc5d74d149d6b265a5f6ef7b220738da67423b7aa176bd97d8b1c0df694ea47
00634,0x5b3c9d594d6329d06de454698372063fe7c17da6f5dedb0ed68d7220e51af8d0
00635,0x95e4dedec09d095e65d74638d433817b736659254cfbb46483ff449a9a1414b6
00636,0xf8124b1e4bc3e7715dcff4eac8fdfd594f035a5c37ed7e041c85928cb0f32a93
00637,0x12daf758eb702d488f8ae9c61e89b165f4b1e4090dba46713796dd49866585dc
00638,0x75957ec2b9f6cd5f4e74a8f9c7f87432ba90888af7eebd1cb621b4d8b002d113
00639,0x7c4f218a868ac866144c6d3d76ce9418c7674546ed3dc36e8ef313dd58913d6a
00640,0x3cdc61329614d0f9f495f56c7be93a89783786ec23004628348b62819a5db04c
00641,0x471f9e808ae0a317cce604dd035331ef6409ba0c3b0b0bf36ed93946fcd0fe83
00642,0x551764bd61137d2595500f29b441cf8588f4ed1f7e1023182ee72656ad70bae8
00643,0x368d4f6f887c76cd7416b91139d0613952a137d983d7ade47602ea026edf5e04
00644,0x81a7c3da06068fc345f11d7bc65b30d249f3bae56c476ef2c16a2d7a04e19112
00645,0x2582b644739c464536ed4befe7d7bcf77bba70a416a74869934701eba0300a4e
00646,0x7fd3548a22eafe728cfee056c100c5ec3622ee0280a79be7b7fb5cd1af2499b5
00647,0x07e93c81557232d569357182dc05bbbcf7ff3f5b3786163cfb5df756e601d9d9
00648,0x01a981a6bc6a5c30e9e24acbd2610094f612785ee1da40150ef6adf7759418a3
00649,0x05bf160d3f11c285bd8d159e9a675bf04b17615fcadb4390e8f582246d52a263
00650,0x119bef0c67ab4480ee8952c208c75959a4a98db6b646410d4276c650e107354f
00651,0x4d3f0b82017c63839fe95826858a18ac4ae5376c004d04a23aba4d6d7a32b96f
00652,0x730975c7bcbee5e2bc9299e12abb46dfc7f5b94416c94b6b103ae22d4a189049
00653,0x2eb89f05e222461e22e437518949767e25e432862909e07df410c6ca237cb567
00654,0x51b0bde3cc9eaf4d7ababa77e2e06e65b262864cd9894a8f9edf4b3483ee1d28
00655,0x06381406a98b16d278488bbba3f91c0ec10c1ace930d75833f15ba9c73500a2d
00656,0x0c07242390289d92c0deb8bf23da435720a753a07822a0bde0bfddc258c2ae90
00657,0x4b0dfe65c189822fa4cd1648d3fbb1ecf75b8b5538383cde1b3f899caf1d1bb1
00658,0xeafc91b6b61da1feb8af3c78fc9b7d01239962fdbfbd40c920a55f620ff74351
00659,0x49e7399f27b5e26165b5603002b529ab4a974346259ba9aac2128387c0b6516a
00660,0x376add4f0e8ed9e97c43c5e439d90b5742c913908bbd5ff6da3ea59ac381da92
00661,0xa8a70e6e484c3180d23874a903ba032a1377e3bd53fa9818d7c11dae93883fa5
00662,0xdffecb3c77a67ecd4d71ef3d16a47cb27dfeeda34126567620ad4bc0e6ff5961
00663,0x6c4ef261baa1dc41e4e3f559e686ce4e340cb14cebebc5ec6cd2d8d11b4bb550
00664,0x3eb2993dbbfdd451bf6ee204a1aa8363bccdf05442fb2d37283d0e9743c9548f
00665,0x8f4067864f02001aa64082821d09b6fa8bd4f08eb10a97f2b3d725988dec18ef
00666,0x4ed7ee7ff95fba3f7e26f8ba3dedd661c29cc693e39ac180fb1cf51cf06be01e
00667,0xa6b898d4e160d6568325e5178aad53d3b1928eb26c0a6983e2e564787cb59169
00668,0xc4a9d166c6bf0bf68df60ac3841b9dd7643261a1f680ebc4a3eb1e78a2bae263
00669,0xd8d978428ae77afca8ea889e5e315b4840b2c03a2f9cf046e6809ab3cc2bb50b
00670,0xbe3afc5ce9e69625defb1cef154c5ed21bd685b3b444f0bf18eb578438483e84
00671,0xbf138a264139a579902a52806444d5b72e5a7d700b441fb3e48007d1d96badb4
00672,0xbf106779ccffef7ba05420f4d363f699759225b5c63c0570c644684ed02a1a82
00673,0xdefe7756ebd4bbb46d00e6a9ec83e0b448ad30cd07e8140e8d198a762e17bc9d
00674,0xc6dc6388bc26f755dbc33c06ede33976846dc45cf406aaacc275f36bafbeb8a6
00675,0x1e729aa1a7eba72fa1b394e8e02ac0b11ff5b52c45ade0e1dbe6cf94133d3d52
00676,0xa5855d981860b945790cd878ab958c0c8f9d634e19eed4ffb6f2b6fb0bdac0b4
00677,0xf3e17cb0fdfb1b6843f71e8371f3ec7943f3fe8c336f50eec94be6b3d7cc74c0
00678,0x42e737249c54ec77b3e92f6e2ad6cefa998f950a04b6e86467096abe91018de1
00679,0xf0fc97a52d48a5cd63c3a44569661bf5d52b37631aa5de0f9c43bf9fe2ac0e54
00680,0xa6045d364b325ce7f818cda8750a79196c59419e2be015438e097fc8b52dfa0d
00681,0x247222f0af90a8ec543ba8c04c847b648fce30a323ffb4cec28f0c1571f878a4
00682,0xa6b3aedbef826280e9fb8ac59718ab16e5369cd11be51532675fc454d89d533a
00683,0x19fcceed6516cae75fdec68f8d34a12c90b64c4d140c4576e724251e6ee6ebed
00684,0x388b0bdc52a25713bd30615e094a873e633092c199bbe247c96c32a61fc12263
00685,0xa2bcc3ddd6f1ec7a0e90f3faf0eb8418a297538a351f16523bf767951cdf179b
00686,0xdf515337eccd495de4a93cfd27e7cd44bfdaaf7cad84ab831255b232d9c3dbad
00687,0x8977442562e00f0c2d71e621848a4ed4b54dc37900075e31d4e945cc1ff9cd5a
00688,0xa979df6fe13d81c5777eae13b0416a370a2c631c41446e51ffb060a8a6a71452
00689,0x33e5fa30c4826bbd3448bbb05dd7273639f122e9c9cacaad987e1def1daa7c80
00690,0x7c95061fb3cac78558039c1cebd4c7e70831f6f5a7906b9faa1a7554cbb43e28
00691,0x062b4177522f6cbaebe9e708a4717d0f5218b21041f84b7eaa13293477135e10
00692,0x945645ca1e3e1c23eade81c2c8e0a7cd428d3dc875b15fc9bbdbde163bc742a7
00693,0x8c6754fdf4780c58461bb089f7d5cfce43a0c0b527b7044e27eda9852f34a7a0
00694,0x222e02bcbbe7f319c293f0c4da042bf7cd9c3bf8c953f4319a14191e4f005966
00695,0xcebc5a0e235e81bd4488436792b62e736be4cdbcc60f200326cc91b436808baa
00696,0xf73fca1b251055ccf2966f306db54c0201bea107de603c1aac0f7b2914386dd8
00697,0xcc3b18315c91ff81f2f9c76c74c0aec6f4bb76fc6cee9512ee81026de4f687aa
00698,0x062461dfeaa7dc2a5a6e7149f2ba928b78aef2b9958605a31185bcd7f004522c
00699,0x7dcae2e8fbc54bedb91edeb0c02141574a70e0412b2045e311330119491c2129
00700,0x64f029a915ad77e37247bb296e4e3eca49dac180d5b91d5b9e1366cb5d02df74
00701,0xc0ae757bd5b3d4a2a87884cfe45bd3ee2f11239b51f9dd5cfc05401c5c66bb8d
00702,0xabe351f7c2bbfcbe08dc7bcdb0eeb08079046bb9f2c94a80ed7bf8e51bddeff4
00703,0xddee734cacc8d4ef083d67efa4df54519a60e0101c0a43842eaf93af88ab3377
00704,0x2ea464e978346b97200486d8994e77706f83622452eb3850a745b215b6351eab
00705,0x9f0bc9d6161d69f28e3f342553c62fe53e281dee8c05002bd562b964c7abc1a6
00706,0x58568eed1ab113f2d3305f595ff6306f9bd4a20dbc168388afce22679b648ccd
00707,0x6aca18990b84a8ef483d70e93ef95a3fefd969b44162724e8d205b2e44a60e09
00708,0x2478502ca3b5bd3787da2b2702e4ed470abc698594043bd7eefc6b0d200cfae9
00709,0x07426af091dc9d0b455e6c0a6de13abd24f3eb3a8e7763538159bcd1bf141645
00710,0xa70b753c132d447457a4a4c500a03afa9fc5a506cd08966303adf5439a183fd2
00711,0x1146e2f9e5e7d485c0b97ed15f1f6a5d3ce2b829460d37cdb9ac49d7f6b2ee08
00712,0x560a81199fb507f115ab5c06337c8c4dc0fe38d991a0057b88816849e2899ad0
00713,0x54d9396ec97021ae660990c80c6a06075f9e7e2cb7520f242b8c4019f29fe4c3
00714,0x8979cc56b72d0fa09ab853f0c94da9223e371e4e3a76d085a8d5e0ccfa812c9f
00715,0x1a583ca6146142cd35125be61ebecf376f08db4cb907d613d8877b383a961923
00716,0x4850905c37251bdd1612b0948a06170a335831bd753be7c62d0d50a8f10bfb34
00717,0xf510edaada3d10661180eb5af717d93b8c5e39971c0c7b82245958bdc47d4359
00718,0x511c0a35f990cf41f851e42863956b7fa20eb133503b7f5e8b7dcfd42ff57d8e
00719,0x14409e14f0ae0f18d080c8f6bf0ae89e4817e214ac3b2c3e7625266375a502a1
00720,0xcf91e8a7472e27a4172246ac5c5a761575f2f25650a2284ea607f8b607ece639
00721,0xaa8695870b38dbd336c12ca05e61ae474fc3540e3780da64432d6cae23de1ed5
00722,0x96e85fdbaab8e3e96a18a455b6f7c52dfc256146b15b4a17cd5349a1e05dd900
00723,0x78bf01d3000e5bf37d29358748ec99c6e4eb1d6e3203dcb914b0b7009bb475b7
00724,0xd7c27830b175b06d64f2c9e7f6533d396a6527aa8078030d35e2997805031dfe
00725,0x8859c97fca028d013b18ac01644d4070df18cb369a380207c646808ee242d99e
00726,0xa705da9bf450e3f38cbc0916a3430caf7b7c2e5b84b0eed30865c21417a787e9
00727,0x58d8312647f7b4f93bb4e166ebefe27b4031924f7550d9ba1d2ab7fa58fbd547
00728,0x2daec9311d82d342bf0a5f197beda1aa5bec47277d79baccc91d033c2151d583
00729,0xfe141ac786b2e586770563dd5812bab7673e4939e29473e6c4a1a75d5217bf13
00730,0x4ab51ad5fce5b07c3935e88c8a21e911e30fec10a5066b79e0d01df2737bd613
00731,0x11b0f603bc13ce8a712ca6ef749c8c923097c455c6b86386f166b1e47daebfd9
00732,0x3e648126f5543d814037eb55ff7d4079433fb586ec6b3a2bd0ed968f8fed9603
00733,0x87195980bf623a55f7bb30e396648aecd839768429e6dc5ecd3417dc44c6521d
00734,0x1a924a1baf8970146ef21e1ae77cbececbadcb975f4f950314313381d50fa823
00735,0x34d9d6a7333d35e1f16458eb9bcac884e81f93dc421c3ad47b7a46ea6f929c7a
00736,0x1569f88b5514b6f98302427c8ab4b4b6c020b517b290b2c7b1e8b6b9ee2b74f3
00737,0x288181ee87c7c1f4c8052ae1692959d57f9f4b123014deebfeeb6df20dfaa424
00738,0x28dbb0e5bd25ae20d92b68183f093bf002cb40e2d0e7b9597ea6e58478db184b
00739,0x4bd79b88bf29f2048cff7bb28f048b67312009bb49d5c33e0a8df28fb26de7b7
00740,0xc84ee78099163d07ff47d4e2f864338e0fcbdaa1298b6fa71352e6896655b918
00741,0x2aacc622a545af97bb40c4d5decffd5142427c482ca5bb8ef7f29951e1807e4d
00742,0x165aa7d2b8608774366225bc7252056104da64abd35ddbd1db832ae375bb6031
00743,0x4505bedc2d45231f48b90817f82a686da0f8b362a79bb0d774cb396288491461
00744,0x08785ac95582347c80d4321d003a4c31d343effc0cc8e8d4a32f8370996123c1
00745,0x6ea3cb82c7125522aa5fe08d65c4edcd10e1823d312f13288c5ae9b69b2d2935
00746,0x3ec58c854981ed2f44dd8516cf166b12232e5e32d2fbeddf070fa45a1d8cc638
00747,0xaaaebe5b4f04d2085247c7c9855d1add2e8f0d7e545c532cde20b6145ea711fd
00748,0x5ab3b22293636bc4bb517aac1a3c22fd297cdf1c8da5cab2353c7b657208f1d0
00749,0x27aebfb9c574b6b4a90161369be8e3361b887534f6031f35654424c9d50e3efc
00750,0xcc08abf8cae1d37837d395bfd9094e01b70dd66c8cfc9800fe8fecb4b2b09599
00751,0x032ebacd972a00b4cd4fc81ee4e8499468ac379eabf1de2762e98aaa957e4cca
00752,0xf09c12bf003999d4e98769faca1a7c12352abd26bfb290a048b846c669bbfc89
00753,0x876733dd576846ad12f5967b4c131194b19013232b270faa88f816795c403e6b
00754,0xf50f5eb285818911c3fc43b60174f25a9e5b9dcac9a5f3e6914d8b0af439234a
00755,0x4d52bb12e70194eb981ae85c08a02d16b7e899262dc34e7b028eda0a123421a2
00756,0x0af4e42bc526ccc68e29d057456f30076323afdb70a6aaecef47cb316a689c88
00757,0xd1988f793da01c8d63bbd508befde9fe8ccc1f2f5974d9bdf0b2d8afa0b9f997
00758,0xc66fcb070ebb36a3ef93360bb74079d15f8c4cad6fada6a408dc33f982308279
00759,0xa6242a1ccc07f0b240026340ccc6d91d99396732364858d8dab438965f90545d
00760,0x824af748696096e08232cea82a07f15a590908d73e4b72da6733ed3dce3ce648
00761,0x76b41584de30eb80fd613f82c44d7fa70aff42a1760221e3852d8865923ce75f
00762,0xb3ed5869910b3b75a102644af13fb642991e19aa885848ea9099f31091cffe0e
00763,0x713aaaf6faa21e1ace76e89e35cb9cadc04e01a6808e264dc08075a0a4074e09
00764,0x3a6de7d91da79fe7ceb3f9ab4634e88efb40832ef2e776624ffde6b3d37b6443
00765,0x18b5d60216a44d195c8c533a95a82c1cf17184393db431accc269b8f759f6341
00766,0x6b5ade6c06f8ba9ef42f64369a90145db95ee3f84c7ef2f4cc0bbd088d400287
00767,0xa008476355318634f1f429e5921b41860e1f2b84a56f25bfc4d1bb3ad99e339d
00768,0x8dc563b6cdbec477ab54634e7dbe0a986ea6f745e81d1fbe2d9ee2036222f50b
00769,0xefd6696f77b898d126c7df1d9f481853086479c17279d5d138348e5202bce86d
00770,0xd9db47f4de8d5d1c4700ea620d918e8ad0877e06d40183790fe55bf6a334748a
00771,0x2aa70a70c541cd444fd2caf88968d737fa7df568af3e13526cb9efd7d0c340fb
00772,0x44dcb9abd03e34d90516dfcf01de57529d8e5efe899d526fb222840547e98dd8
00773,0xe4dcc8e85df47ef9e3e5ca5d5fa8bf8597cde9c9234f6ee5020260e69e911b2e
00774,0x63f82331a80309f20bd3c9500671446c81923ce5023224f9502343c7db25d83b
00775,0xf24f282ea23a59a5c6451e66987eca682686d8b5df910676b2fcac68e675a3da
00776,0x382525f177efd6e19eb9949fdf8f31802f86c7754d43898dafc36eacdcf72db8
00777,0x2d3a5e7ae6a0aa3498ff29bd9c01bb50be16608071cdc311690b08d54b81ceb4
00778,0x9a24e96613beb77c7482edb95e3bd149f3a95df7fde1e01c23eff75a71f73dd7
00779,0x0be7242c1c73f21c6912fe398bf625f142d4b00f260cd0169b82162c7b215da0
00780,0x0b8c7a94e807b13c8053ee0c97d5f38f263e31d9fa703d9b11de00c7d4c7945d
00781,0x6e9ae0809cf9e38136a64b629b4b58f37bcbf54b6744ef3121403abb14b1582b
00782,0xe888e6c289f0734c57b9c61c1b6798e5d94139252173305a7764c8c4cc9da157
00783,0x03027295eb991e1dd03d652ebc3ac786ee4c263504a78fe31398341844f235f4
00784,0xb6efb516952e014d0e2197320e521f15d58f6eb8c88bae72fed90c570ec3bf85
00785,0x79728b75e2cbcd3ec3a144ad474dd75eac9e1dd898fb3c97023c4edfe7d91890
00786,0x0586eef4843820a247d8f8201c6b77e828096bc02c4c5bc3d2c3b83bf42ce549
00787,0xa0d4c8c20e3a37f678959b563859677050107b0e63d043ca1930dd48a93c0311
00788,0xa55feb48d4922a3189983989333d70c7fc6b18656446bce243eaf77fd21c54bb
00789,0x9b95d3aa1408771b1e1e743db3216bf9e512a1fdaf6035f7a9f40e3019e9134c
00790,0x4a62280eabc47623a8015bbbdb99a64521c554491b9ca4baee28def4c857cfa4
00791,0x064776dafa35a56678a5574157b74c8e5f1433d823f8addfacd972e0d2dfa90b
00792,0xe9a295429a1b3fe4ae05e4444fa3e7939ee234416505e5bb12533e45204ccce8
00793,0x93ac12baf1d3519d2d6db741537a098b5b97e00c7044e96eb2c49900a7d3c3f4
00794,0xb199a3097a3b71bb74286673315795e98805a6951174ec6957b80bcadddffe1b
00795,0x284915ec1b0af683caaf90546c773bdb1e950f8923f9468192e160aa757a4869
00796,0x80b8a59801157a40d10e17c3915a16f78eca8b03998466f59ce4c4f910ac0760
00797,0x40e902aaa84d1fa5c8cfc7ec95846be5b541c785a9514f6886257431d7c7d5e7
00798,0x25bb39c7596cf80eed1af44ca924abd9f738b386cc3604beb0cc0e139b570a5c
00799,0x565a1bf8ee5e84e7e9ff397ee36a656ffa670321bacd7533e77eaf91ea104561
00800,0x6723d6d967dab127477429efceb7f975d2cec28aad8ddb603fef54cc69fdc6b0
00801,0x2c9057ba31e7f3ddad8a3324a066efb9353cbdce8e399ba3061531737b118713
00802,0x75e347ad895b4b6dadad02d048f988ec7298298756d55d924a6605e3ce2bc9e6
00803,0xafb8c20ffd497fd6ed9ce26ae25f7a83c66e30bfbae612cf83dd83972a75d7f3
00804,0x472b0432e2d130803fee6986e35c0decf8989cb0d0645cce4848848a30cc990d
00805,0xa00ad7738c5a78e98095ad2803f5f02736ddf5fc471940d4d01642317be7bafd
00806,0x4fabbfd520862fb8c2a3cef755e30fab50f8e235460924f43eb239e3276738da
00807,0xebadaa845247da44fad909d4bad16b43a5e63c6f48bc3eaffe2b98b27f9e1c3d
00808,0x71a5a039aa5425f801492260210074426cf5deb420cb2ddf9defb3601564f0d5
00809,0x2a78afe865f39dadda88e3d3d493b6be19af8374a62f0b48c3cc8b41e28227aa
00810,0xddc911377e4dd2291f709e0243a6cc7331a49aa27aab1ef211470f4662c8e460
00811,0x47305f69611d5c09e9f302c34c1a491b8166f950f14fa56ed0885c11257f0224
00812,0x6492e81274651a77c064ac8a6cec00c509e58de9a951070770cab002658d662a
00813,0x9ccf4c433a7e66762068756cbde59d2c603e1dc1d64cd0e61bd39bd636ddd877
00814,0x02f878d63294625f5b8e01973359df0621504feeb548141ee1fabd1747bb2f4e
00815,0xe97a4d00ec948995c670a9c30441ca9f510c6369f00ef2fb38624f14d8531eb8
00816,0x13c60a90e71fbfa321264b1dfbcdf76d0b15f3adbed05f31b02848e4fddad79c
00817,0x6f8e5552d9e7982de12d6cca3368f02671fa6b071f0618876d4a1e9a4d79a3ea
00818,0x8143cae1101045cfd98b8202617280228a5b68c0d4f37180b79327d4fd555a61
00819,0x3894e28cbfa568d39fa7db232e4954e9c14f36eccbcc4c1d35cb8562285fbcf2
00820,0x97b69aecc1068e3d89e32195d6b0058b13a2b762cdfbecee7d54256e67bc4b81
00821,0x22732c1861dceac8803885adf29e9c9b7758ee5c2de3660d175aec67e0deb2d8
00822,0x6977fa0d3194c37772fb68df9929cc9974fd9441cd4881adf20e17408465d544
00823,0x0d164934226bdbae6b1a9c2e284a02bfe3e7552ac901576e33aee614f8f4d9e1
00824,0x0de9eb6ca895573dc439ff773e617cec54c9a3e83c8412ae6bed73594f51845c
00825,0x14eaae6399e76bb8c66fbf9cf4333701bfeda482cc347590402ba802332e5610
00826,0xe0848f10dad16982805b6bc7f6151605db509bb228fc49dc647bb472c0fdd83d
00827,0x6846201d042855e80cd3e2a1b2f5f0a6360d499cd803900873c1900264e45448
00828,0xe89c0e11010967dc5ceb97b9ef40a45f36ecd9390c82b58d95592deb04b6e746
00829,0x3096af7600019e93e14000a119faa50fc3c60c4fedfab2b65ef7c5e76c40dd2c
00830,0x55e8b4c2d3dc809690f3276cd43ddb11b907c7a975de41041a1cf47e6fd535b7
00831,0xc501837ee2c215da498b734153628de1acc5d433179078696ce82a4f2fda42c1
00832,0xf7000808e45b53416da880d5a8a6face40cb10a55fd1a9f4c07bc125da165ea6
00833,0x5d73b97ad48b73368898a1e39b0f725c43ca3757b9224dacd2f8db81b90d6807
00834,0xf240decca5d9b9a21a75948716f83b68499f5f260fba9e535320d7ad2b8f654f
00835,0xfbd0a3686d9e771cbe2410e0eaaa2535d140a5b5628d2dc5b79afe2a54da0255
00836,0xfbd2c4fe042a2c0c30942153fd2b2a148fd11275cda67d7e945ea50d8ce9588a
00837,0x8bdc330460491a8d07586f41f6c980500b273533b9a98d0d0d180230a35abe43
00838,0x2a2047ce16869ba58f7aa520202bc2c2345fac6bfca50e06194361165cedc4ad
00839,0x84c88273e2546de530b060ff56c8c9fe3aef02cc968fbeac333fdc4de9c49cde
00840,0xb96ae20a3f7c6cb7890d5f72037ba8a1a8be4e4f758be430f089ba62c9886887
00841,0x5cfe6abdb5b075a8fc721d49e76d0c136de22d165ff61d27a7acf7050d84a31d
00842,0xb7d8f3a61da1cf210b8d80336009634c26f97ec52375533406ac0f0f7e22f5fb
00843,0xc14d7f51eb905c4e662965caae40a537cb7a85d85458a5508e91a2498e479fd4
00844,0xc5eea731a2a18fbbc08066a06515c8f05d8838912d961c32b31ac31736d8e5df
00845,0xaea57615f40fa35e4c73f273cee2b1f077838a18001e8ddb9e87d28286149014
00846,0xbe228f4af7a96d9c1cbbd4e76864e68c332232ba5ce81de3e11c0d8b33bbf1ad
00847,0x5721c5a99dfa32e02559d43450e95be7f59d245160fce626eb8e5c81c271be87
00848,0x4f17a7ba2d98477f2d2b3ade28f2107d35516e8f953b636ac1f6014f4d1c2204
00849,0x81731fd5dd5f8ba504c4c3bd1080eddb3e400e8655bfb1e93da5450177923ce8
00850,0xc8596aa574934f8d7b7a0c938ce736d7da8c63dc40bda9719b1469d1ef93ba0d
00851,0xd9d76d294b8224a90bd65300b2bb1c3c5e53441b3182c5b0d41011f626046a9f
00852,0x3db9cab96ffd143cf6bf1c330e6cef7467783d82443e5122006e5d2fa200f1c2
00853,0x05eacb145ed3b25a1949999d28e34eaf4aaf8cc033cea6569f8b53a4d49199cf
00854,0x787444532a61379ba993a92688941b3fac90f64fcf9a32d022ef0cd78544f813
00855,0xb042cdda0306e8678b89046603d24839002d4916d40849b5dc9e65f3124952f0
00856,0xc3dd963be82c9bd8bd0a27cf846b0fc901d63b7a5de84844305385a2de4dcb57
00857,0x1caf90ed8dc29fba89264af3ba07d0874e2f03c223cf387fec52bb0b7c4c5017
00858,0x7d89c8e7e7bb553c60a7fff4c056575791ef965ece8adcbb8923c17c2ca42403
00859,0xec9f0685cf4c7e59b45c2627b98afbf56f2d113415af631bd875962dabe376ba
00860,0x608f5138cd3fdba7adca86cca1623b02d967a4ddfdabc1626298aef841f06e98
00861,0xbc7139248334659528164fddc3c05f6933494abdbee4e82b5c16960461fb6bb9
00862,0xf5d2654fda6b2a14dfe9f390fe8464887263d7415ab839418c21db6d00b75e02
00863,0x29f0d1bd4ed36f2a8fcddc968249af476e48f49eafa8c1cb3ddaef3c9f6fbb5d
00864,0xba09ed24136ed4ecce9e3aca125ba9cffdb949164e4ac0115a7e5636bae9ff81
00865,0xef98f25e48fa78413bfcb8bc7d7bfede024ae12b74727667431d0b7b24c88197
00866,0x62ec875a0d3529f36a0559e183518082de0a399e1b4840e3d5d23b4ea1e6adcc
00867,0x6e38f92d9e902c7c4e46d334d8f15126fd82a220c3529cecddde6b7892187ada
00868,0xada339e00fa18f5a7a48601c4d9db77332f4df313771b2a166bcdf02c07b5dad
00869,0x687f70ac1c22d04c591b239219d4cea3fc899e22a15656cdadbfffee43900445
00870,0x69305b6644efa1ddeffdbb7c5fbd55450e67237a3bb38fb8f08e81c567952569
00871,0xdfb483577885f06bf36bda6c0918ddbb8ff30612412e6b4a67cc4bc867f2c44c
00872,0x1fe0bd683f075a332f51a8d355282e02186aaa79a97f75c6a317dea751ed8b30
00873,0x6754774ca2adf65caf7d126d0a1b7a3a9e9385968e96d8ed20389a3c3a96895b
00874,0x89ed1e981eaab47a9b1afe89f4d8fd3eb60d208cd9cc2cd3c94c2a5e784f3bf0
00875,0x918e70e47775c40e4aa6674b40d2f502e26dea08e7fdcc95fc612f9411268617
00876,0xb174fe364a001d733d0ea0de0724d33c30d59ead3ba2f7c318322935c17b9027
00877,0x1ee06c6001f96af9abdc53c79801ed63bac846f1de194b8e31fb0e99e6cb2dee
00878,0xacf82dea7eff2b6749a07263ad51979a18d25e10191259c97531804deffe5f59
00879,0x194ae19978f7ceff5b951ccc21ca69e4093db9f14b3dd735675b658614b50163
00880,0x88dc77d7fb4be097712c34808ae6bb09f4adc13e82457e2bdb930cf79cbb08d3
00881,0x291ee430fcbda963ea5ab68df639ea92ce325530844b6e5b43a306fbd3bf86e7
00882,0xe0bd01b96a078f578b599838c06357e455d023c72381c0c9d96d2a57099f038a
00883,0x24ee5653b2b7060f64b723f52723897140c6a39d07a35da8b362335a12fdda1e
00884,0xf46491735b52306f745dc8a439441898c7a9dcfe6301ef0cb0f933c55d8b9432
00885,0x18be58079d1320046e689e4fe43cc04d43cfa1794999974288fcf3625e6411a4
00886,0x7b8e7f87674815b502a57c0797eca3288e0b5ade2a8ca7f78dd7ba632b127e25
00887,0xebfbdc0207cea435c10b7052a0937c699721b2e7e41a2d925d0eab2ab81e9c8b
00888,0x2911ec4630e2dd25d76cb86d8ad8427de4fca247c5e641ff2ae16038edb9ff52
00889,0x7bc66f0a17605a2e0a082da2f3f99d6d424efa091d15c856e0bab50875629e07
00890,0xde4cc0f167df6278f89a5cd047e8079d7e9368fed79d2ecb3e8b31537f744260
00891,0x1aa1a5b9610ffa5b41fac5bd68fcc7f767d3434baaeea70e20f738d369a44315
00892,0xb5354846b7a3b0764849ba2c006bbd7ab19d10f2479bd99c822442214eb135aa
00893,0x75d76eeec8dd8ee7b5849b76e8e3c5b363adbf59fed68f0df8c89ced4106ff94
00894,0x81aa556ec3ccd95dbb8e26a987f6e0434ca41766f68949258ce05f805f74a808
00895,0x4704352715ff20066ba6150a55318d0e9066ae548b4375e4ce9b31e530598c61
00896,0x1ab5749f22bdf79c27d6a073d93687b6e375b33f38cda1d8ea1b8aa794c0de76
00897,0xb81f63bc9725916a88ddb5a5a6d7b7d558afb1d55bf29d57952da749e99ecbb2
00898,0xac96c90242fbe989a37f1711dfed7051aaa38a13d8e8bc3ca5a518a90713cccd
00899,0x922b1cf4946990d76e6aa05024474ffce4b71c683db79dcd7d08fdafe537d04c
00900,0x0f8ce28573d070b2160ba328d9eaa3d81af5b60443acea676cee7cd234f0dc9a
00901,0xf6f06a90999d172458e44c324081d1ee668709a2e4273a35fbfcf1312b913999
00902,0x65bd2e95f8d26b9e2b3360b40175eb62b0881772fc80085a3d872a533362f5db
00903,0x3b916edf62cfaa0bdca3d8b3f13b9654ace5f3a1c6c9a787dc07452b69cd985f
00904,0x2ebf7c0d8151e785e5eb6ffbda1269e7d9d7f36545711099119ec1d486642994
00905,0x9e7868aa92b87527f63245914226d675e3d09172ef63e3191562d1869ccfd5f2
00906,0x6fe8a5a96b514f6763167cd7925516af89e4014baae26d735fbfa65dc9ee1fd8
00907,0xfc681d3f63c0705f771f6f7cf8fbae11076db7aea57e4aa4db082fc82324eaf4
00908,0x65f7339775a6fcd357411605348f51cf908f2a6bda04b392ce76132c1fc5a40f
00909,0x38ce4f9f511d38303d855f92e28b6e096b749211b0861af2aee292fd34ab3af6
00910,0xd44a929f41f40d97e7767775efbcf22213dd313c0bbbecbfe6130712b28b2fb2
00911,0xfc91f464f9eae7f2fe1844bcd1c304c8467227c5df40b5518f2d262e14aeb011
00912,0x9acf8a7ebab7d5ea23e59c7434b854b29d79a7d52153264f96886051df865c23
00913,0x0790733786688f30e6d7d11388f7daf100afa105770f218e84321adc6427fd24
00914,0x822dfb1aa7d617e0cdb16f997d992e643890aa048e9fbf89051e42349602ace9
00915,0x62602cadc14d41fb1a9d1c682afdbdc3a535828fd89ab1474040dd571631207d
00916,0x8b6dd223bb5846cf7af3766332bb4a3c7d0075b350f82c907db76a2765be8dbc
00917,0xb309c46944a731132a289569e9cf52c57e9921b99cb00d02926f93fc83d6e86d
00918,0x8974583a7b7ae104b867fa6ea76b999ddc399498dc070cd622df9b2eaadcf4a6
00919,0xd139d7b42b3dc5b0316ec6e718f6ed470c2b8063357ca6a5525eaedfd77fe93a
00920,0x5b83da490a1580b57e046be20c03b6f6b9378cfb8b8313a2d58cd10bac12884b
00921,0x7a62f3b8756e0b45061ad40d0d08a4f400abcc7f8f9d21c4eac35d5eb3c69032
00922,0x30f2071bcc7e743301be529cce48170478cf733c09f76bc7a007486e907b8d42
00923,0x9f05e1511533dd79377f64581191380f2a4414538f9812bc978575ade32e4747
00924,0x8d0da5014bf3664e6f3ee37a221447169bc7ef4cc2a98fd8141462fd4e6eeb28
00925,0x9de1930ee287c457d1d7e31f789e7d73dbd9b2ae0b1db00a74a8ce7dcf8b022e
00926,0xac17e41e8ebb278089444caf7fb6de4be8be17e0d2737713c19ee56e233b8052
00927,0xad6865ca7acf691972f0906fa666ed8742cff9e41ccbf870f1c2e6c8566e1597
00928,0x3feef311a950eb4f513f3f125bf4941b2664e7696c637c0998aaec146910944d
00929,0x6e2d1f4b1c5ebbb67159e8db1774180c58e50b633117fa630e99025a4b648b12
00930,0x228684d7571e71ed0dc00adc98f4ed6242dadbc65bffe61c131c91e396206d0e
00931,0x2485471e5350c5da449bbd5b6cd731be0a47123f5b26becf1790b2a65e8ea608
00932,0xf2f69e075dbae9462a935692b7dd566909e2d95734929376b0b7be14e0d42fd2
00933,0x44eff5aecb4e111871225cc1b58c1c04786b1a4aba892784b7551b9e8ba90595
00934,0xac8cf5be8f250e984277952c431a84b01c0ebd96e4d46cb1b456d0aabe2fa7e2
00935,0xc052cdd4116d1987a3939c7cbfa2f266e8d181465561a8d0ade58075cce59ab0
00936,0x0d1ce1ba874c0fe555d4c8d7a238c459d5cd3f93634abd7bf304eac7a225bd7d
00937,0x20d0836298d617aab81be691f33cd1dc61546b081a1e913b7cf34e5afcb8c8d3
00938,0xfb915a9512d1e0bb47c535ab0cc6e7ddaa439a720c4acd6d591be03ff738a402
00939,0x2d5f2cb94ecafe782fc87c9a65f35a98a38b249bfe8a6c6483070d22f485c752
00940,0x31a360b2a347dc2d8ff1e2ee51c8d487fb02b3ba20ea86104e8c0010e6840674
00941,0x6247e765c7acc0135a2a1c8359ed9280836e63aa78bea7e5d489d44cfceda482
00942,0xc352aa92f9ed89ebfc84d9bf131e0e386a26b3e6264cf3ef6e0d3262fc55df2c
00943,0xb8b31db995add4b70a2637cc3e46d37b0f9bb608f63ed39b1676115569cc95e1
00944,0x2a8be08321010d8fbc280fbe2ff0d9a9102738f588dccbb4401ec722067450fb
00945,0x80961bb9747aa130e7b0f37c81951fb8d28bd916ac200bf5cf0ff8b4b5bb2bd1
00946,0xcaefe64b2e4fb5f87ec1027d5ce8c9c545e116b687657c5b3789d195c29377c0
00947,0xccd88affa72df06596b5ea6d9429fb5c0d3ffb7fb2ae2be3746463c4572841c4
00948,0x11d91c258be65dae198f1301b2b3bbefc22d80a62dc3c789577a9d9584441322
00949,0x209f845f27a7cfc68440e96a9a05f0bf9ffdfe3fa2b77f0b66ce46de6ee6a1df
00950,0x4a9dede78effcd06746878f1ad7c1c255e7451ead558f94a610d64de9e84a569
00951,0x6493fcf8ae0df3ba0344e3f3962cd9cedc50b435d278c680b1ad7fe580046213
00952,0x611a2c464cb0aed5d1ff89013df62f77a4c66a4dbfbd1310b861e17c0821d850
00953,0x81e7d01751bb41cf701d58e15e5e24af7cab732efa990fdfc807d04965a7949a
00954,0x19895bb27f335092570be78e1c9e4390bc3165c12f3b4801c3386502dc1c14fb
00955,0x443f9153e9d10aa291a75482f6ccb32b7f03e5ff28ffecbc218bfb0d17645c82
00956,0x3dcb543b7fe04863694029ec36709cb2be65281eb77801ec7a43c47421b2f266
00957,0xa2d2aa3950ccd9bd38664a108384da939a29e5bd3602b44f2e6d0f7e078f8181
00958,0x24f3f044349785645a815ecae5ca634e5068415f3e47f83a4de78d1f5a0ae0a8
00959,0x8fc647c479f7467e99986f5a67aeda9ffc96c49cc3b2d939adf2e02e6cb631f1
00960,0x680241a45f3921d7038f95843ee7c15a97fac6acfffad14edd0b80cd52525b8d
00961,0x759690ad2ec0fd1d75ef612e00b72ba25bc5c2cafa795df819ac5410fe245a45
00962,0x12b37dfb28e1b19692de0b9ff9e4564d3712ba1abf0085cce006e61354f9b7c5
00963,0x2b4168b786abedf1fd231b205fd827ce376aa3dfad7df2e8ffa37559c8aaa489
00964,0xa7136656c0ac8a32a5cacdb85d35f7b1cfbf46add043b65d63870b7be188e662
00965,0x8a62b4050b97c853f8b86c1a27865c5e8550689c699c7ac2cf18d534b4bb523a
00966,0x73e45b2c1971c37f6bffd67467b444874a0168db85f916c4e1e1cc0d760a48e7
00967,0x399424597ccba8d81b2fb6d2f5b16a310e43bbee1d546bc0a80450f7ab202a60
00968,0xdce8aff6baa754aa1d9c385dfd56b5d0ff0c9644cb0756cdecf9c4b1dc75396b
00969,0x49be47569890def0996f17dea252bad3c05e4f90c23a6b441e05db55deef4df3
00970,0x68c57c6ab509c836dd5c5c0ce07cb41070698639ea7ea4b9faa07dd05d9ae9b4
00971,0xc4f6b046bf04ee48a7360f9271b8507f13e222b37deab56d84090d8ad7071e40
00972,0x13a7fe3ff99f61c26ce53cfad439b83aa50af5659ca5095a1666106ae43b178e
00973,0x135d2ae11ee8c376d2ee5ca54ebe8ce915d133c5c9330f9669c3f870cdebe438
00974,0x922bb3c21c999cafa708dbc7df398abd83cdb51aab98537adceb848b95b0531e
00975,0x27b6441bb01ad4bcc2254fbbaea88e69e4adc75d9305a086085602eb971306af
00976,0x63eafa02faf46070cc68eff888506aae7e0bb2a4ef9558fa2ab095bd30b95d4b
00977,0x05bdc732d86d690e9fd8fe7fa8ee4077e92535202176ee37b9a2f124e7bd4212
00978,0x95d7750a07f5423f61cbdd6797537c1316d250854bd865639df437ca3c70cbb8
00979,0x8cf0d6245c51d3d854eb5a77b46562c4416f5dd64386eb5254036e44e189c9e1
00980,0xa8768f5c3b2f7d860b55b71d01ededf8c4925a13c4f6eba25d2f1e9eb5232965
00981,0xc4e8ddcfb6cf6972583902cb5e2d10c8be3ba895b076f7ba8e29c09de1a5e512
00982,0xd4ecd7c319b9e27e4929f7c0e3ee7baa94b58604b55a0684832524f816124f41
00983,0xd39b640f89b8d62e6a58bdda604a6931e5a97494270b8c13639c9291152a856c
00984,0x22592d52da8f0eed167b072bd3f9d68708ac37af6884b76497f518e419efc4e3
00985,0xe4e144f9d02c04d79c9d03a3141f6a90d3a9217d2f348a8b5f57ed50deba907f
00986,0xb5e7db59cf4b1329d19cd7dec561c3eb7353eaf71f3f5eb92f1cfa9525425fd1
00987,0x9316c767971e58e2fcfd1bfa386d6d678f05194403a9371194b26e160614f57c
00988,0x871302efe9a899f706e248554a0a7834244e9b94db1aacad82a96f70d50ce3c8
00989,0x1c3a761603d969947df6da3491d18a2f55dc67cad3d7ae813aca79089e8e4dee
00990,0xa666b3895ff153f24a671fb6588494111eecd4c4482379b6bd662361f955de46
00991,0x3154c955d0dc8f9ed8f5e7ebd476b549d5778600afc737a213ed6156765af846
00992,0xd078def25dcdd2df52d7e37bc2910e598ac00c921473f8d93137a07d3a403edc
00993,0x6b2615f1fe8043e3f4f06ff4f918c0b34bed01cf776b535a3a16530b81fc9d91
00994,0x6ed3f90facb487fa49945d0ed5f987a03b8bf76b0377fe2980bfe9cac2a5b6dd
00995,0xd3223ce7a69afde216dd1c957c6116cb76bc2d70895921c2ccd6b9d4f79038f0
00996,0x016c769b453ee0995a23b0b20bb83c3870ec7754867b8676da1c3e4849511160
00997,0xe19a4c9d8889c46240475ea0e669e967b4ca09dd35085c327dcf75e127093d3b
00998,0x36c9ff39ced94ac5d4ce3c5d8ce14030ca154bcc2e99abdcbd71344e8b0fdfce
00999,0x83c72fa27934098dbf8aea00c2491a9dba82ed6ae6f116f12ef96404f63ea6f2
01000,0xddcc603638d6f6aca751013a22d42f0b3dc9e55794978e37f46c38b622fe0ce5
01001,0x2d0fc419efdaf8f46067013cf528064da86116db18b5382289afb4b6e1cf2b9c
01002,0xf69f7b396a816ec0b8a377e3e75ee054c47339cce83f24de1453561c04f24789
01003,0x1763271040eea5424900aea6164448f842f699eb662f8409d95e5a5635cf20c2
01004,0xfbfc02162b85f7c870dba66af17bdcbad0f5e6dbb8c7b0f2ef936a0858595077
01005,0x584687a4b29aad825e7a6f106afe5f27a97ae104d3cdd7389fad0f44ad5cb101
01006,0xdf8970e84c6c9134c98a890c83c4649fbae258db7cc5d3b1fc3c63cd6ab64708
01007,0x2fbbff929c09f13110369d940831fde47cd6eef07d5449d4b3f9d353ca155dce
01008,0x235c9a91c69ce2ce21267dfa82b595caacd3f9ee09d9ad725e5913c317a05646
01009,0xfa09b4f1cabfd5bf65704b38982b06a536e316ef4b533db69a73ce2bf88a571b
01010,0x3cacc95c0a0f16f81baca64b7331b81bb577b2ce6d451b9b3773f1770fb1a948
01011,0xdbcb3c6423aa05a61c71ddbf3181af582e525b5a72a9ebb8e44913bb981acfb0
01012,0x6ac002dda4b8f105f2bfcfe0be9f0dd8cd543abaf99e36340397026f68fb1210
01013,0xdd1763be363eae6e854d82cf948ce79aa3903b24fb1bebf83efa5bb9ad8454c1
01014,0xc4e0e059fb5489787f907324c81a46a400a87b3cc056601f8a9eb5fc88b1d32a
01015,0xd2d13e5ed7819f3841af3e911c3516211bac48169a52d6c0f0525b94af603d61
01016,0xa93277ff5640373ca1446607c231f0bed5bd15a096142e7376580f3fc78841c8
01017,0x019e6db033ebcb56d9d51ba309d4f010fe79a0df9f6f3114b052390e273ec750
01018,0x763ea921a273d3b92099e451f36949767992111073117536583f5fab34dff71d
01019,0x45d2795144aa708f2aa6d5016635c887f97c9e609dd7eaa30fbdbe04ee2acfb9
01020,0x37e8f37e7fe680451499d4cda814162837dd4e60b9dbcc1cb4a09d8aad95cb5d
01021,0x6654a92dac9365e122dfbf52b5d2134dadf1d638aafa879893e50ee2da2152ad
01022,0xb81a65c13cc3d54b281e9ad392e8792910ad09b39b8dcaf6ae8e3fbce06117a3
01023,0xb72e8700d81b2d7c322dc74a3f37dfce6f3b08a487a92242fd0ec2b8bebe21fb
01024,0x75f6d852198927b79d8ad8bd5505983052e9ac80b80d5dacebd4687d60d549e8
01025,0xcd13479c8725155feebfed83954d53ffcb6725683f43c866acffbc6e9b97ccfe
01026,0x1ff6a9b9fc585560ae6780a7c54170e8f501324a894f00f08828697d661ef0e2
01027,0x6c76c020b3f3f95b9c50a8d6d7949cc9c9798522070f5e35e61c6521473e15e6
01028,0x78f9905648fbb6eaaff40a458301f05a7bb753a6288eafc141c797ca01db044d
01029,0x3dcb5e2a8b6791f5141c8ff08ac59a36030c9436e6ec6de8274be01fb81112c0
01030,0x373e75f1325d787a5f7e66c6b888083a7b1b2e6250d2764bbe1b4f1145dd9b72
01031,0xf06e62b5bde482371af35d2b3eb05bc4e9f80da90c64f9a36c8405bd0779f123
01032,0x3f19793eebeb6aabbbaa055ef131d73f1186be249bd8bbe2b11af0dbd783cf7f
01033,0xa9765c1c7bb916043bb42b1572cd96f905c3e2f5fdae49010a5102a9eb4a700c
01034,0x1dcfe01766b650af58d6becf6de168e7da980e7058c7b6424da1b0c470a7ebca
01035,0x946b550f1e19e68d272a10be6c0a1f9310da704cdbdf518c8a90b694748a8c29
01036,0xb953b4b78c6b2446d60625b65ebdb25165d4c9a46916ee303b5daa16029257c6
01037,0x8356dd445dc79c97a83819c8538aab5176664d436bfac3e9971b1c9cea78022f
01038,0x3cefbeb9ce2ed071c7abb2b55fa1f8ced72cf1f2f9bcc24955a17aaf1eb99c29
01039,0x4765ee428148e60b0038ce5034cbaa7259b0d85403d37936cff1f1f220c09419
01040,0xc559659c692f7eefd643fcfdebf8697a04634c839b6e1724382b3bcdfcb15170
01041,0x1b1f9767d845eef02506d6a6c54fffcce5bd6bc59b41b00f17ef06e4c63edede
01042,0xed5a8fb5f2b0ab802832bb99d32a9ba463945ffbfce2f56f26e9c39fda1c3fe8
01043,0xa396fcbd5b63936ec43b6bacaf2b0236783c638eacc72614daa29e792ffe1ac2
01044,0x33bd34bdc9b4c51f344e476fb8c97fe80cfded7c90de437f100505b17823c66a
01045,0xe62bdcaa8531750ae8fc247c76445a76670077643060efc80323e864c2c2c480
01046,0x37db60cdd4270773f870c9cb8eb3368d0e1443789dc44cd653b0f423addab3c9
01047,0xd02ff344a0e66526266e7ac1ef9269ee132e793c2a3eb2c20c95212665880232
01048,0x27c44206ef714c1ebdfa21cd959c074063432f3fdcd7a3b0b2ec4375e12ba53e
01049,0xd74dcd433ceba7a2a6702e807c68470b446772565b466b0878d4518983640500
01050,0x583482c4b0a752dd12430176b663ff8ea5fd11f2eeebd8b956702d0eb473a748
01051,0xb1375fb5970e469451f9e7b9a29f3b20ec0c583ec90b79fbbf38f9e981d9a9ea
01052,0xfc68a5dbc89395b13fec398a9ad78b00d813fbbb259f005e6fba1eb1bdc7f2cb
01053,0x038d0dc543117df0c46ca6cf4467721780eb951017373d51aa88ece1a380f56c
01054,0xfc630d10c00e0f843cadfac7d24f8ad02f7603bc7555efb4fe7e6a33d42d8fca
01055,0xdc564afcfef0c40d16d7fbfd90afc419bbc37fc750f790130acaffc32f985dad
01056,0x75fba5d5c98ffc1f67f8a1ea520808f94a547003fa4fafa34ba7f9b2dfab7383
01057,0xf2a347f31fba049b5994122c3d6de4d37196ce8fed6c7c7b5c2c6926c28811c1
01058,0x7e00f70a6b91f77cdd78c01ca54d506dcc25f226fbbd13d56b0c80e8c80c2694
01059,0x7c557845f4abf757fef7dbbd11b44e44c92025733d16b57ebdec6ae10f381f38
01060,0xd6b988695e3c2a57b1d3038de5262349766cea46600f70b8cda2998ae395894c
01061,0x7edcc464ec0b7bd04070e80a4795a4d59581d9d6d53756eef10ae5a38b40259b
01062,0x84fae3dfe3699b7ab0c58b47c604799d1fa7a0088138efd63cd4603e79cae112
01063,0x97a50adfaebf0ad4f60329d82fc6fd897416be8c698e6a6d3b6e7da8934a2f97
01064,0x25e68a390fda36ad8fee616a22d79cfc531127e6c8cbc11710e8f5743399d9bc
01065,0x88ea91bdc01e8bc0fdda51dd2abbf05a92a14c20052dcb563faef0bcaaf5d161
01066,0x77a58ff5479dab194fa000221e98fa4e6dc77aec51aed889bcb852db57db3d03
01067,0x95926dd93886d32de8692bda38da9e4ab10f9026ddc5b9ff69c30f55e0915ebd
01068,0x9e4b22f0088519c08bfd6cefbe125caeefa43b83b451fffba1a87223dfbcc62f
01069,0x5451d56c823a2e8d42ad39859e0758b8a4829a11daadd96ceb4ab2b29874c7b2
01070,0xdd746cbf406b80fca7b25d95961640fb0ae5d411468001224c3770b2554b95ec
01071,0xe7162b854ae8194deb0bd3a34eb77be0bf539ce76c566ae2e05207968a908b95
01072,0xa0266c3199c30bb4c8ec4b5797d112795c89dbfac6478dd5d3b772a14158fd69
01073,0xfb390415ebb31243ff63e550cf27cad325550dfee0b421c1c1be75a845319585
01074,0x7d668fd503ab1327817d49218ba493e6174918a03b3120133126c453ca345e20
01075,0x38bef7ff6fd5999f6446ad8abfdf10a24045ae1b837b0ab70e1db500eaf4cead
01076,0x55f5a07a76490536966de1a99fee90d723ebae9e8d0806d9ed6f1580b2174db7
01077,0x61a13d92beef22d97be7f3c1656cae6760fc08e36db7d381d5c96222fd50f864
01078,0x227e71270b878bdc138b23386bb7b33cec9175875b461b04902f4af708c31580
01079,0xf1a39e59434a97dce0d30cae7bd6feb571827cceb3ba57af6af183e953c24b6a
01080,0x1b7d09908d41e6463da4ef25bc4a7e2545528671a510352110cd382f5b300d8d
01081,0x679b43594ec30c0fde26f3a2e05561c7e110ebc15cce1ec5b6d7da2fc5a415c3
01082,0x5e7dea252df625a366ac47bfcb1e8eb2df49d44d0be463f98ba95d256d6982d5
01083,0xcdcb8e564e8695a687939ac1a0fd1a0cc5dbb352f9cd24427cde8360b2a9f200
01084,0x5f2ca307599872cfc55256ad29009b53f3303d024b5b782a4abb591c8cbe5a57
01085,0x12230dff9cefa72d522ebb791d84eee3ec55b5c4a4600209cab7c376171fa159
01086,0x6eb5d461ec98068957cdab5b2028bbd8b1b2f7a221a8ea9c8011071da37d7b2d
01087,0x45541bfe08784bc6d1298d97e0308241efaf18a47bffe4894dcc26ef776b7b0d
01088,0x09f2f43ee828665d8d45859b5e36a8b9d31283550eccf4f73b1a87638e709803
01089,0x4519917d2bb898a1810ede8b13275e678198aa773f7eef2b2c05c129942cb259
01090,0x506362e6d66ca9341da4fb5706d690f94711b6673ab9b7d7ac22dbd39e0af8db
01091,0x408e7c249b773c396ee2a412fdd8ef7e43fcb5538e026aedfd34d7b9b721e60d
01092,0x4f1216d3d70323582c6544bf9c07bc6bf3582ddd01a52550b257b1e078dc12fa
01093,0xf7943fdae6b71a9c1a6d7320a61ebb908c32b91e8c9679808b09da9f28774225
01094,0xa2458aba8fb9a34aa4b4a5ac20b23f843e8b12929bdbf793499c0187de963643
01095,0xc3174a59e85dd195642088336274f531f551c50dbadf407323d0d1d5ef961bff
01096,0x5475a30e12c46b42b661a0932c94efe35bb76575dc0030255dae625933f32712
01097,0xd2ce1e42bbb308bb9e0abb971cf5b4d9ab1cca8fbd73d11b3cfc19dd0b3b235e
01098,0x5fb12ec44e61e8a76d79d4646c09a67627cccf3576e52206f580364cc03080de
01099,0x1cd92052c419c186c329a14c7bab28a4496c23e243635d5a263a3ba34d0052c4
01100,0x22b095d488d0fbd0f10e209b322ca59ad319975d6d3c90a81d1fd9b6d0243dc6
01101,0x844b63b3997c0468086656f4733991f97ec42d5fb1b65c050113d515117bb756
01102,0xbcce4dd3d6cd5b08a76bb8890eef30ad7df184972df8a271648de5269fe1ed26
01103,0xc97117921c0dc002265d161013da1171084008fe5b51d046c695b5e626c9994b
01104,0x5035027c4b5ec5e2df56117a2e012b79c9aafea7bc89a3015e9061e226893245
01105,0x9331be3bcf98379d8a0e2f65a70785c10fd620d3fad050315c2a1e2f6c8bd6a7
01106,0x901078cb9b1d4516ecbda207acb6e6e2891a134b0c80b647240fd8ad50016063
01107,0xf8edc0d4190782ba1a6bb98105a33cedd5d71c25b22e0138d5bc5d902f9f5a34
01108,0x42362545904d6792bb88ae2a9f7d29b10623e58260d0ec47749781227123a2d9
01109,0xbc521ceaa2bd28faf23c9f256b2b24c98bfdb90a020d25216026f95d065eb0f7
01110,0x199eeafe5585e55674bfa0a341988e470b65ef78061b3f20eade8d1e271ef3a6
01111,0xd34462829eff8702ce5561c6b1b715e63c8a89b7f5eb274e8c5588cd15678ba1
01112,0x1c93ba5b0b9c65421fb9cef8cd24cae654c4ba7d386a53b6036e4019eb517c55
01113,0xbeafcef83fc5e6769d82b3c304c0cbd5a1add1277e1ac300f0bc5c7e2822f2df
01114,0x71ec790b6d9c1f8e40159317162256dcd6f52a700215fc61d329587c64b248d9
01115,0x6f6094bffde8d3ae31ac86b2ffa489481cb8b4b440d4613edb06f5e40f0effc7
01116,0x053afb71d72d02a534cf646231ef23fbcb10a93ffbb85b43bf6364a1b6cc2015
01117,0x98396ff4fbee74940a9a03c33032d84f7285608a0a3ee7c58e016ca8c42157cb
01118,0x5747971200ae6086c2054eb6a3d0a5307b84a2c2e7ce4dd0b99fcf278b5b066a
01119,0x1554c47385b828df19e22779047108210de2c8a34fd0346f77b9a80c630637a1
01120,0x5db300fa117451b25a6f7a59a55e33947378c5216687ed6ba23f38a721cbc21e
01121,0xb9aeb88a7f2c33e5ef7b0eb9e4001ce50b96bd4576f174ff5fbaf2aaa0ca3cff
01122,0xa8849157cde19e3801e69291365f8fc095855ea313f1a6cf5b39d1f117ff166a
01123,0x0b7bcf33f4e42502cf5f0c981f1103bbb8f9c98a0a4a02f3ac10baa8328906ea
01124,0x224f4405f110ce6825bab6f6c209a4b5518894bf489795e92195a87013406ff6
01125,0x0b6064b3c367b296c0a422c00bf4606867164d315c7ab16d89f1ad2957a4734c
01126,0xc7344cf278e4f244a49689243aae7f3fe30e1ce07e5aba04ceac1cc40fa922cb
01127,0xad12ba3851456ed8b37c7f21c8825c885a767cff2bb776be648cb8356946cb0b
01128,0x3a386e6dc1d155d89af575c544cd88581c7d178bac55cc44f63b2ee888223764
01129,0xc77dcea67936565fa9d9eb078ce575698500dd17988daf0a7a8f246ff5508833
01130,0xa25a8fc183706411fa20ed4f3b2a68d96e0b161fc09468f33beb434c48f58bba
01131,0x0225209e1b7c3463f869898432742732f32fd1e7c5f64e5ed74adaae2eace9e1
01132,0x1ba9f77cea8694123218706715d4224221fdd5af2b022d015071d6443aa3a1aa
01133,0x8e1c1d63b865ae597bfb51c82899e0aa4107a88dcc6ab180ebb568c6de993700
01134,0x3197a1d6c72f1891609283366e120a1f4c61412f83835684f28901d35249a04a
01135,0xd28f2c9f79253b151384e63f867a55278831d92575d63ea0a6b14f39f373161c
01136,0x6cf8d26d850172c2e2bb9629792fa93afec55de913957c778fe0895734ae70d4
01137,0x62215680c0a6143f5f66137de7a13356a0d1837fa842aca997aa6d4eeb1bd7d7
01138,0x44e4142c95e4d04f4b598a4146c0fa04fde6db6afd78ddcc8be9fd16018ce72b
01139,0x1a70666e7cc7d475d738b07cb5e2984097e0e30df160b1d9b0698f33a9048c83
01140,0x9bef85d30bd7319c6ac73e9195d2fb5a87900b61f09eff71ff9aaf6dd39d6c8e
01141,0x48066cf2b5c1a5a553ecd2ca62a466bd7e462a9836e3108fa9b9c50084109d71
01142,0x112745d12d9f1ffe670ec1b1b1526ce0b586f0348788742af013d8b5ae8f1e50
01143,0xc07f562554568dd0a8d7d83f4151cfa979abf944c364f627daacfe42d6c8e75f
01144,0xff3489f3959c367261b35a4a8cd106e9b8e504da8f95c752126874757a68d8a6
01145,0xaa9a507ed68dfe695d15723f7f31e32977b1aa74bb8a948c2edc27a55c6b377b
01146,0xae05fa5d0e96ad9e6fdda36bcc44637b1a4b9822c275dd6b0fbb7471715fbc57
01147,0x0dca795f11fbe372384ddae72721019ac51bb29767f1de14c808ca5278015b6b
01148,0xb970027bb776fd436f03d55bfc77b43836eebe0391f2f2673a794e5d9648ab7c
01149,0xb2f6f5174d78083b50511b907c2e86378294179e05d89fbd98baf0996055f8ba
01150,0xae9dea31e94ecadfec8694ff8db30c1527a1b4deaabc042794cbf0f7ba068fc2
01151,0x1cb2b8d45a6d2a7a1b43aacd57d78702ff161f96b9141d8489ada32fe1c8a705
01152,0x28b41e3872cd3343b0901208ef472e26d98ee3facb64d2787e6f1196cda87d09
01153,0x9cc1f6f0ae4b10e85063dbcd30cc2077a2eff89daadb9ee3391e9c460e39d1cc
01154,0x1d470ae11e0f409328f29e315a1881c3eae67123d48019c748a01f4e4f381aee
01155,0xb516307f14425bd9ee0434ccedb692092eff147562ee7805e0c6e0df0a475d7b
01156,0x8c4c11190ca958c76cad26d8514fb383ee51183c49eb56ab2aa41704249b6ddb
01157,0xd7bb8fbd3048f3b139a3c64191ecf38bf1a218dd9544903b8ef3d0e546cd8af1
01158,0x12ec0becbbf83afd68392f4d9b67d5a8da89979557cce60530735a1465c0fc6c
01159,0x4fafaf52d0c069b6f587ee7a519e715604f4de04fca1a19e726671ac56596b38
01160,0xd0e1b363591af53d56c1c6a146bb78ecdfec21f12b34759aa832501c89c26a40
01161,0xcaff530399938686e3364b6b228b3ac59e3b22f21b1c2b3450118170fb281836
01162,0x070dea605d09f3096df0b0f76948df8a38831c90c4581ffcf6fed7bde0cc268a
01163,0xd285b66ebcd5852a1911fe5599702a89a0dadda1405cf84dcf6d55bcfe0f9578
01164,0x2eb4c50feff7659cdd8f3ef48b6f9175a2a4b891d09af13bd0b414bff9b0bcfc
01165,0xff4e71c2c49d497341e7386bdca329ab892c94197d5fbbd18166cd48843de333
01166,0x4116850a1bd36ed591c1e95e3cb1aace3675a61d1c86e1660da988d5faec71dd
01167,0x5b6986455f3550b4faaa88fdccbffaf90f897971254d9b8f3ddec649b5260b5d
01168,0xa23912b4a361e10bdd6093479763b042c8d09f8fc8a5909170b57b6aebd98339
01169,0x0737b4e5ab8f9071f44e61b66da61df228dc0414f3ba5dde12b7a8fb10b2e618
01170,0xdf35982e9c74b401291f2ae70a09ea99766219008b0e01880cf6302e9d62b60c
01171,0xcc7466dda5723a0c33c326d1596717848dfd0256867df4d68deaa8adc3f61db9
01172,0x9abdb4aeec79e7dfe79fdb6711da93c071c9099542344da75fe1d968009f98e1
01173,0xcdbdfbc64a23515c0dcf517dfd71825cbe5d9fc98566f9c6b02f733e8a1ba3ef
01174,0xd79c75b859479066f9caa316c37f67fb7728dfc01a0d94f6a27ef126ac0692cf
01175,0x0d2dbfd717f62ea857069cde24b45df8fd214ef044057175265d747411304051
01176,0x94adbb4c520dffca694df807f479af7b035da83f3de81f014e28ea2d34e70adc
01177,0xd5e0dc5aa1b4441e615373ed2c8782ce41b20b2a7816e81ee4311c243d3b7be0
01178,0x5c34962d525fd40d9c8bc44f522af67fd89111d332eb9ba5cc9b0f138a4059e6
01179,0x1de75523ed57212207b3227983ba8bbed7607c3574300abdf11cd1a372136e40
01180,0xaac82868aa7edb8173d1d41c6b0745b7eee734182d4fdfd54e6043350afc116d
01181,0x5899663553cb5e7842e72b43a64d86113a4b76aaec2b0774021361171aeaee29
01182,0x74b8aa4405d31335e0f8eb310028c7d05972831702b931b5f28d5afb3d52d854
01183,0x38d8567174aadf1166952a632dcc85d4a4b8c20c946f2399878183141a10b561
01184,0x2a82d902f0d2aedb663fe6998f7abaf0cd666aa3d6bea64e81d8d83c92b0351b
01185,0x528d123a4c8b57d0b25864c5b3f673c21fbee2a1826dab6cd6ae9ee0024e85f5
01186,0xdcefe6dde10acc340d071c61813392ec065800ade9040e5b721fb20fb8239a7e
01187,0x25b5519cbb7efa28ff1b23d0f46e38f7b3b2c3fd96d493c5285991894e371f40
01188,0xa8eec3288b23734dd343db2bf518380753dd2f602d80584c1a8247f2e2e3466f
01189,0x0912534018135146db16c094d6a7a067062a455ba846f44be4d79e2c47094417
01190,0x13085b0bb2b86b44d0fd7ea1476bee11b641b11dba8005afbf167cd3526855eb
01191,0xe8d4138f22d8fb0fcb988bbded449ceb966203228554022e6e0564b9ed6ea1e4
01192,0x7a4ee2172c8081d3f6dddf4bb6c561c8ce3f1af703ac6b591e448c762b8f1d9b
01193,0x7c6dae3a659f3b4fad0b797c457a546ef174569dd60a71b6a4fc1e66d1e1f268
01194,0x7d063ead7a3d4d51dc59256b72738faf2171d7844da6d5be42af7023f690d979
01195,0x68a0b792e3b448d4c36f26611d9b7652585f23f216785bb73d5c27c0c0aed493
01196,0x94c969763e706d0e7fba95c4c357b0e855c68be2dbed2e9a7cf7b5daaac5a08b
01197,0xa6c39440cf6d60b35b0ebc651ab80a101b0f57d9163379474ccbeac8827d5fd2
01198,0xf7a5ab53c462dba797a3b06ab177ba42b11a370240ce077b03fc1fa2b107f4ea
01199,0x84b9e12ab6e9c0e7f41dcd01aae0ae2357ed252b3ebd78c0b2d95fff5e032724
01200,0xa6b6a963488c4633e7f3af99047954e1c15fab24793fe43a4c9ec2c933031f01
01201,0x4a0c7f03de3cfd31752d5100b70f028c31856efa2fd1a3b5a8cec4a342500d34
01202,0x5486c645e895bc1bdc91291f74d5ce702e1c2c4d37f005c6c1968c96c4798a0c
01203,0x08a5313b986a0428d49ab7b7f6cda4ede434efa3f6a69c5140ee7c46c977c30f
01204,0x975103710d4d4cc0c9b337decbad38e6dd42449ad533b3c464801bf10a0f7f8d
01205,0x7bbd5580e1faf3394083ed3a12ecc3efeec75b71b52f3c5d2527306d47d46c9c
01206,0x61e11a8ca3db52b16ec4c025165e73542fea9eaed696dc528b1fc7d08bab6871
01207,0x3745949046134c86ab95f8da5fac1e0b96e9146b8dfe976b95ea8adfdeb10fb0
01208,0x4d0cc348ca8825a306f854475c04b618a82336c06150b936407f793bb132e1d9
01209,0x2008dcc12d9eee29e24645e17c3a32c8b0fa82423b230b1bca74982ff32499ca
01210,0x842d419500195cf77644f8d7f656e9e0c7044c7c0227eef116f0b54bd52b8456
01211,0xa9c1369756e021602515ee071013086b92c4050c767db4f6952a5e875dc74415
01212,0xa6435d49ee936444ea5411227769e4e92c9bdc5e353fb90feda369d0b357ca32
01213,0x71e5659c8984140dac3efdb27964e2e36dabdf863d34d9a44509ab28ff76d3bf
01214,0x1791e683cadd2556b588f262ed01f10dec8a17d0fac17264cde17dc821d61444
01215,0xb250520d667d2585a11f8515bbc942dde5271dee48bb2079e94fdefb4cd12db7
01216,0xa13eb7c2b5320556bec64b033af8d17d73880423b1aeefd6befe0a80516cfff9
01217,0x5c83a392daf6735cbd58715ddad8b5ee5ffab29f0d90e9529cca55f1e5a9bf65
01218,0xc13220ead135c3a3c44eb1f623db0231af2a830eba39328d3b0eeddba6590b32
01219,0x5f56b030ea9674db988e0e19b92ca4f4d0172eddb66b88d1421b761f43f430fb
01220,0x512900cbb649da6361f264485c211c79688543284d48129d978f50ee9110ed54
01221,0x90c06f460cbaed5f47e45d4761dc4860400fcefcf38a4adc8dac265798ea82d6
01222,0x096acd8679ab399726890ee06192292f292205150e75a75d8dbc24fb5b5c4e95
01223,0x1a1baa666116d37631224699f89e17da92ae1d5df34857e3429b0eca71f473c2
01224,0x34f529a2f72e1e83cd12adeb4dea7f2bdf3d7c96ff50249b27a0c6a65cadca90
01225,0xad7198e0def6e143734a5dc947221958a8e506274daa782383fbe833e664d60c
01226,0x2d858029db92532563a3dd2e05e63de9600abd032bc3402b598df65b03b96f45
01227,0xbb9ed6f343eb8d8aac3a7190c4327752c136b8d2d7a9cc4cd58ce619f2541c50
01228,0x024d8b0934652fece1c1009e992ffcd5a39c0bfaf4b9e464b492368fcae0b44e
01229,0x4fbd23d89d82ef4034f1bdd888e2b20cd2338e5430326039cc82a8ee32242e3f
01230,0xb70e3603aa922716ba38abca5dc445639eff218cbc2ace3e2352be344588676c
01231,0x76e468cbc19d282a6075b218eafd19f63234beae51e46b0c2b81bb0b707b0632
01232,0x7cd7b651d63b2e5a4f6684ae77ab9d3d913449a92eef5a716ecc947ba553b724
01233,0xd077ca788a7927c7d2f8ca57710139fccb6e387c563fdc34aa9c8ca05ae0bf35
01234,0xccf5a0f7216ad6bb2ddc6f59917c9d33ef237a7813b09052ce349a26bb21fb10
01235,0xd7666847f3b02e9a581f7bbd41e906b894136b4f98503c2e2458718f08d319b3
01236,0x3d10b1757feee8ce9ee56ab7d3e36b34895674fa7c6c90b2636e85f0a9e16368
01237,0xcfc709d64aefa7fcd84780a576f8d229f3f093993a38b6271826efaba6b55b46
01238,0xf6f1e083e51e96a0b399e5878186085e9ca7d12512822558c2ed1e156a72404b
01239,0xcbeef9b07ca5099aa5f6bf79fb7d58a0e8418af292e992b4c1f1d9bf43f12aec
01240,0x02688fe8520ef9c0a4bc424936bc9b710a973517598bf394274c2a44cc848289
01241,0x20ebd6528acd0d0e507af27f82db0aef20556c9dd36f482dd78e12a39cf5855f
01242,0xceb89cc1fff1a05d00b8cb8049f5ba68b4e0fc338a5b7593e1bbbbbf4fe7c3b1
01243,0x6ca6a14a6edb58aa90fc386305b46048d24dd9b525e204b503970cad8c8864e3
01244,0x40769f6cedf1218dd656126546473cdb24657724170f0bd71c0ccdac1edb3e97
01245,0xf2f56ea6ddf8226f222ae389816836c60e8fe9bc55e630c93e8d6634a2babbe2
01246,0xc0e897c05df5e53027934987158c81a2dab1a62638db704cbacc8a2eb0c3931f
01247,0x58d2fe58f1fc86b6ed0e2f210e13723c8ed644dc8d32ffa4e55cc176b7bcbc3a
01248,0xe2cdcc7c61fe867dcef5ed3854538fecccc3ee1501b6e66f3132596c79c41a93
01249,0x379da93b0902e34eca8296446820ad2e24d3e4feebf1f0faa061e099bcca3366
01250,0xafede008f90c6812f90e9cb5a5462e3dad70fe5f0d0fb383f833845659bf25e4
01251,0xeeede50f94cb63b7e19cfddbcc3f25e3c06dc4c3a83b001804ca440540d37d43
01252,0xc5b81847b51e4e59f89d6cf2361c42f64dc760fce9f0bbd332653de1f7474ef7
01253,0x96748f6773bb94d740ab82734c26ffc9daeb4c87606403add65897512864e693
01254,0x5c3badc9304a265385eba2afff786a1f9464737b71d9301035b758820354da66
01255,0x2599ae05afdf5e1b2be57990d21f985c0133406a8141639dbf33d46e632bf6e7
01256,0x2b44aee4e83d46ed4a02abb9ca11c1630073fc6b233c5aac3730f8d28e695859
01257,0x4952c5127010c24a46460214617a2cd34a5430ec398ba635392762668b21a64f
01258,0x713aba14cadeaaf4ac33853d6a33ae19c0ec40e02821d467577b61e371a53ce1
01259,0x1ae7b5ef37e8a2151263bd517645f1336e0907ef1c840b41e8732369ef1d3cff
01260,0x6f90c321b6915a06965c7804e6e28aed175cd6d62162eff3fea564fda50fced4
01261,0x61d416a84d212bea9580d2eba99ca6cdb0a45ea809d540b49ae52e6a2d9c5f84
01262,0xaee21385dd0720113fea63062d20dc69e979bfcb5f295131694752dbfff3dc97
01263,0x9fa06b72e89a042853139708961c7114d3197bd3c98c1cef71ca0b34c01652bc
01264,0x53a8cc3b6aac658c3b80f92e99521056c4035fc053b6abbd4068e5339dca35dc
01265,0x1366aabf8693566d39e974a595eb7e681f57170fa8d98c68e1f7a4397a6f4cf7
01266,0x2631621efb6f486a6c82b58c7cba7c37dda933bee528d982b1c25570a45df03e
01267,0x3dd94158da7fecd20d03095ac40774de44befb72fcedb2f94ca801619b5aaef6
01268,0xed99cb91c4babc2b4eefa48bfc1ab03f710aa2bd4c6e12c60e0bfe78e6a774e4
01269,0x3e65584f39c73ae662991d6d27dcfe9563830c5210ea07a12bae36dfeec36436
01270,0x69ccf142f770f0bc36ec796d3893b895d9b602100a30528dafa20e5a2c28da1d
01271,0x66fbd4f182ada36bac2d86fbdb791807f55f3c2c010c79d8fab7abaa404fb002
01272,0x7f448c5eace75539049635435d61193beca590922f7255ef040ebe6da1f29306
01273,0x3db6b5ee4daeb3747abef5998ae0ec1def30f96ff98043bc40dfce86966fde81
01274,0x63adf378c2182a75a6bbec3cba265ead7a1d31cfc37324a5cfbd44e70d3e2392
01275,0x0c89bb3e1a35dd2748bec8ed667b9345d50726cff25f170637c86382abd82135
01276,0x399bff6479203b0d07b9409e2adbe174c602acc5f4c2368b4fb399dae9227b5f
01277,0x1b14df373ee827661a2c07e3796b21ae8879dbb62ee89588bb43e2843c70b624
01278,0x7bb5b29535784cb002cef2e3e34d518d7baa14aa2242dd3cdfd9e6e2801faadb
01279,0x4ba003f31b565407c69e13af897dd4acc225a71ca04599415f68ee839e34d799
01280,0x2ab6865f17d91c52d0fe177d6b465575f83380ecd7d8c7f9bf31b2377ca0a1f2
01281,0xa55982471099400711214ced393e9909d0e04c35e862b6319ada8e63fe9c5457
01282,0x8357bfd95a67b8e01b0530b10daa926d6368de1f37ebb787a24893a1813d61b3
01283,0xb502eea2d534a1d9646b8cdf01a0021a2fac7b298ae298adfcb18a8adb51bf09
01284,0xf9cc24977a6a162a4f21fea4c588d8586d5cb96298a95364e3cb1b50f1878fd0
01285,0x5ad4fdc89fbf4b2817a64648f37a14ec2908b58b24a621a12f941d7e3d4e6a66
01286,0x4de64a70d6df12d28fcaa8d4fed874f5aab3f070552189ce5e24582539c9f875
01287,0x1cd8e301efbf3554bee4a3699272b01033f3a1087a8ea789132a07e1d08bd20f
01288,0x461721aa1fba0486391f01c6b60ec368e021573fcef4c62a0d91204470a732b5
01289,0xd776cb85c9b392f75696d6bb5733b4aac5f1e83a73719620efaf40a385468200
01290,0x873eb969707feb65aa18bb94c3bd32f40fd891708a0977ede54d80ebab7e17a6
01291,0x3466a3703a10207162520e73c9350cc646eec8158a0f5913345e0232ec37fd44
01292,0xf7c7ef3af85eb27ace55a2b8174ed8d5616f3d6d8457c51678f8c5ce5ff6df2b
01293,0xeab36fbdb3f08b469d02903085a59c455c1f8693e76b7005832a872fc19bfc3d
01294,0xd38b96b71d18f88b5eee096a8affaeae086170fa9636dbd6d81b7f0bf03d34da
01295,0x9a8e547ac87505373cd0a850b2dbcf87fd17a958e86b91f431dfacf8faa1cf9c
01296,0x044263f35cee7bbd103e6537a34ef16fa8075121c6b2ac6cb9ccc932de47261d
01297,0x2a6fa8404ebef74fb534dd65a52008d9c451c8e133a111118c38b238963d8c60
01298,0x25e8cecf4a4009a8a3dfcb6e414a52939dd8f0fec0cdfa43fbb88f6d93e84d90
01299,0x4783a5b474945636c48b35187b5236790a932a6688eb9d57663cedbfcc35e96b
01300,0x05128f5669874610a201918ac659f325cadd39c596246a946c95c17899f4525c
01301,0xf8ad3107c0c201f6c9c855fa7fe31ace8ea37cf483e4466de7ee0cd8d4a1961e
01302,0x564f335c0b20dae960b81c7fa6715da2a7a1f32186ee0d0fe6fc162f36a3630d
01303,0x0dd93fff7d2ebb6031ca921ae529ff7f0fa881b0b64d0fde89b532250afcb3ff
01304,0x20eaa74f7d74b90dd75bf7750d80ce428e75745d60b92500549b4039163e674f
01305,0xd00fc022fe14cd175a8a593bd0fc6cf8076872c16fc3672313415760c659de09
01306,0x1f67a41c83d8ba9d5206bd10389cc97b98c2b2b50d46c845728f67421c9a8b7d
01307,0x2f77e7c868bfd36ad2e2b0864b665ab2ecd6671d8be22c1738d3c01376d0b34a
01308,0x8eaf029a66086147ba2206ecdbea385029fa3ea27ae9d93be466ef702f9ef909
01309,0x0e9134c94db5ca1f3f8df20c06242afcbc7c099282c1b5662b7528344fd49f83
01310,0x36d0712a3ad4551da02c8fbcf6ffb7fc9105d8b651095af88f9168884fec0ae8
01311,0xb196f52df231958730a92a4cf0468e2648750cb5665142e160d881bc14e37bfe
01312,0x052a3539fc9f8bc4d117b49c1e06b3c2f6ff129297b39d25174c8f0b8144001a
01313,0xed3d98e8ee4b3ac94e1bf4f158c783a8415ba5f497f9e33a32f1800d60cc524c
01314,0x6711d975c455a06ffe37404f2c044b0212d05580535f0b696e01c40a38ed2e15
01315,0xc90257ccd4b09a7a0b1cfafa86eae19b648f0f9ff4d5f9d935b45179c45679d2
01316,0xd23ae50b11a0b68e4233b0743b3ba73f087d2e8d9e73f74c100faec8838bf4b4
01317,0xb2c5b1b5c44801e3d93702395326af0a9e333f6faa72ec9836bc0c6da90af82c
01318,0x803d224bcaa3b2d5d0ba2de2837b8b808215de356282c671fd92e94b4970bd37
01319,0xf7082c225833a231427c3a2809a4f77fd79ddf88a94991e251336feba0eeeb89
01320,0x66c7f0046df871f8a674e08f13d66ace77969519f44ad0eedf44bee0a543036f
01321,0x04af06fa9d5d1b4d162b96a9e979d61028b349d2c474a34d16d0c62761252504
01322,0x44c4c046785d0a1596bfa34133b74b47e16a4eea6607b7633d84e90ed816d4b4
01323,0x570d0caa96bbae3e4b2afc7f01b62f3d90fe232cb3797cfe54b52c3840bba0be
01324,0xd4cb7a0d9740bace6d20e145e01f654c3388393fbc655b41d8693de6bb960506
01325,0xb10b22ec3ae6d7252bd04d9bd6f2aeb5759cd1c33df99d43230b5dc2812fb5cf
01326,0xea52129a4b82c6183fc1713117ed5d1803135642c2544612dbdaa6fd06be1b25
01327,0x4f88b08507b8fb608565635faa36f8b09902017b2dfefd8091b05cc698e072a5
01328,0x83f1204e20b3770edb57289e7f64401d79365d0c0e02a84c9c2c33ffdc496693
01329,0x572dcecfe36d6a5159f90810209186d900bd940b27e56a8d1150aa4760e5b99b
01330,0x45db98fb860512b9cbfce82e225581bc15103e772c385102f63aecc98b3053ce
01331,0x79ac113e80705dc36acef32fd3d844dcda82fde0962d92da38a07e585edfaf40
01332,0x2e02ff938a46434155167db8bc7aab30bb1380b9e3e7a61605bb4b98312305be
01333,0x1c8da535daab62298766c9eedb38110eeafe1d6c2fc0a6fe344486e50d23d57e
01334,0x9983596d69c4ca9358001d6e1569a17f8c35a885ba9dc1629aca595c0475af7a
01335,0x4143f16c56cdd171e39f8a54a3bb2d2dea69490672df9fa7e30378def8867730
01336,0x2c80acab236f71b43e253b5268c172dc3f413cf145e0216d7f6c13065422a2bc
01337,0x70afebf06271380039afba9d7b5157f905d89598d03042f4bf4cc827f1d7b200
01338,0x0d957f43c8483a069456ccdf1c44cfbb355796198e5b35eb365d66189c934b07
01339,0xa954d4bbfb037a0e8f081be2b609544df79fc5f84f346fe687c83055e86b785f
01340,0xd259e3dbd24e5d08dbc1cf127159be9095f93cb2e035fc12cd4dd9df06ce4d91
01341,0xa393c46b554c380371d5f395f99c878959168fb83b010ee586dd627ea5ac81f3
01342,0xfebdbdcdc98e1286f41f504e2457d4b9ad17d1747bfd60a3b16fba723620efda
01343,0xc205cffc694cd333edf5deb8023b04a96ae6563e1de4acb4d93f34ce095a50aa
01344,0xe55d1bc51b81c62134e654fd69d9c13dc329454cef1328f1579d034178625187
01345,0x18129517d6e589a3e497f93dbad3e63b013dae40ec88ef3e1f3910b655442848
01346,0x62600923c76a890ebe7b693e545c5f316a329cc622325ff9159159322ba772f7
01347,0xb7bc048ba653fbc6fa6590215174988a56bd0615952242f026700ae0ed9e44d0
01348,0x63f08fbe35edc8666cd54f8b313029ccc744b622842266a11085320771a781f5
01349,0xd8f90a763e74c5cbcc2f745cd41dfc34742eb9d91665d71b201e8f8d4cdde52a
01350,0x3b7ca4efb889b761f25df46f30cb916074f5f80e5bfb4a500896747da243b54a
01351,0xa5aeba3be9d1c93c5d8cf0ec419893fc0d2fd193cc9d60b52d2fd7abe6cf4820
01352,0x75faba094a42b7e78000daf1ed774e8ed6ecf34bd142470238d1d16741003ae4
01353,0x53743d70a74f3b85815f71200d6c3c044df0ffc75fe8dc56a8f9a3ad106d880c
01354,0xdcc29cd5c2804269d16f68f212fa4318cd10f686761ba1e012a2bea667d8ed2b
01355,0x73301488b070bb8268c358f07b89b07cb19d2ec612edbd30c10c7c83349f0439
01356,0xc5358154fa2c30230dcb62a3ae16f03ddd07e3fb9ecb53b0813ba432aeaa6743
01357,0x6ae35c6d816695c2e73892ddb5fa55282a108796ddfc1059a60d14ee87ed06ba
01358,0x40401985fc52c0c38cc1951a0079728513e34711517fb89e8c8893f889f834a7
01359,0x4f6b265815c3a8d1595aeb9e2039c9c73e06a69e746d06d3e4adbd09ade7ddfa
01360,0xd0b1559c6907e19eec7b32ccf02f63bfe932f3ec95d28de33250f0e2929b18dc
01361,0xef5b459d7ac7c2743f4c0fe6adee0d06a89971dcfb7d959f087b7b57f12c5d1e
01362,0x08dfe9e3cf1e444d51c5a61d42a03d90f974513c237d2f9684995f399ce35d56
01363,0x80f7dfd0b5347cde3ebd66b78dcb3cf55cfcdbbc019c75e2f69bf9f97e393263
01364,0x4b47710e8532de589c562f34bfa75a8333a26937ba10f86d7327afcbf0514cfb
01365,0xcc79e6c613537fdc17caef5f69d705741d3ea81e4bb6d277304d243aaae7f3c4
01366,0xd76553f60e2e468719e30bd8cbfb967a00cf6841fc520c86d0aaf400db5defc5
01367,0xd7efc68f4fdd73317255edf40a2be339ce739e5f0911f447511c763a494160b8
01368,0x17ea70afa701eca1af56e1a15f3d1604a3fa7f9f32e8a60b52d41708d15d8020
01369,0xf4a498dff013a59d243cfc41a176d2e7584d686d4ae44f6dfdde575d88529fe3
01370,0x027e2a2d5bbcb6fd1867eebf440e44ac1f7ded4acd265d97ab1db0e5a1169cfb
01371,0xb90ef17e2d9981a11ef0cd0a735c7116d9a233a825903096e2cb07ea8597ef0b
01372,0xb47194832a5dc01344496c495b28e1d202ee22841c8ffa1857d05ce0944424cb
01373,0xb999269e83d06f6df620c6f5f94964f5a643fbb64dd2c4d7f58eed88798cbd6c
01374,0x662f1591b37f2982f426f3003ed9147f96014bb12963e49e63ad1b55e2cd78dc
01375,0x108ccbefa9906c080c5115f77f9ecd63381b9ffb0930227cb2630f4b08d8a090
01376,0x54d2962953fce8d8a641bb8cd1c9eaafe89f9ac9546b8b277d9b535fb35a0097
01377,0x6d7bcae503db8d3f3771cf9e8038a1fdf3987beb6212755704560a0404118063
01378,0xfd477f0bf18d87a2bd3ae3c329e468a7bb16a363ec3fbf658f55ecb98fc16d17
01379,0x57b72b9a11da9b25c2bb52b648db7870e039a64439fd271fa320bd2fe789775b
01380,0xbeacd779ff788ab12f79382ea205b1b180c7e43302e902c32fa577c0925144ce
01381,0x4b6c00275a131aa994d1e86e9246196299930ad5fc218d09d0b66265234e32c6
01382,0x485b0ed3728e693a618ca77659c55114a8f602ccd71fa6138e87e11b49814289
01383,0x402cc664b8b4b8dcac9aeba636f3c902a713874d9fc6bd6c7dc338817c1eac76
01384,0x547da0f4446ebbba63eba970ec761c7a08451eb11251c91cd6427cdf475bf00c
01385,0x058c55b0a6a077ed8882d135e4cb364b250d392eba6ad4e578fe910c8c9f340d
01386,0x951ddf6cc9c8cae358c63a8a8b5037a970cc5a3e9ad55fca7e4c85bf86c935a9
01387,0x85a7797dd4dae08cae7218cc8c2497b580ad037427bf7e351f20f1edfd695d57
01388,0x64376e672282c2691f4dd0a88ccdb12d561cd88612d689f2802744490e275e10
01389,0x58445b6bcd79648c107c45ccfa2c2246b0bffbfc0c9c8750b934894144105f87
01390,0x6a2d6ce478b520818b85e08d1beb56fb4d6d656aef8f26020cc9a1781a4cd96d
01391,0x330e88ac3fd46d3b66946b2bd2e342e0906769ba42be06f01ed224dc7ae90640
01392,0x3bf42cf0cd0e8199fffa9b453dea46a65409ec5430638e189e8f60132fbd19b0
01393,0x239fa3d0c11c26d29efac03c04735050e83c55686975a8753bbbc83349316a48
01394,0x76707dbf2c1a10e6f1aaa37be9374185d3eaa2253594e5ff3482e436841e6b50
01395,0x4bcaea6c1d0723bab48d33acf6e6bcbb6016c405f710f19e8542290568510ec4
01396,0xcc5b5c9a71d2e0b16153477cdb827aaf6feb3f0758218dccddebcf0e0f0bfb1b
01397,0xce3fa54e8a5338bf4a395b0d522e35d60b473c9f8507d6def5dd7da739aa5317
01398,0xd06c9a048e07da77ad07dfd45f48cdcab8eac2cd6ab44fe9db7778498d1200ac
01399,0xe131599e0fa8cb136a8425b02becb4d42888bde686d9d88b6248216a583dbc87
01400,0x1a628757bb1610b0c239ae56df58324c7cf5b5f3f18bbccea4dd67b1ff9be9a7
01401,0xe7d4a88015acd605be12a616c899590059d306c69aff9a1876d47c276ea96231
01402,0x85d3f3038ba81ba3c5c5a86cec0e55ecd3865f4bcb2e7bd9fb8390e06278ea2d
01403,0xe1e41aa6c6d1cc5313c8f2a0ba5c50098c30f49b4a8ba5ea8d89e334be0ffd96
01404,0xeba27a233d1a0b76360d1ec6793544482a197f01a47d29474b64982d043c9807
01405,0xb0ddf49dcc80359d5bbbd56b5a1e53a8fa78fbb3563c806f1a8a91b51cc8d082
01406,0x651ac24a55b66ed30dc6b260af6a9b6aff2c1e0e8433534a353d2b9463d650ee
01407,0xa76ac2e092a5e5db97ef6af6656dff4aa47fbf036bfb5ca2dea8fe0dea9635e1
01408,0x209624ba6ce8936b8a37223a76d35394b8a3e1c55f0e23dadd60da82e867fc81
01409,0xaf729a25d80ddd3c0688e76207ff9ee0ef4960a696061fc1e32c39e69b40289a
01410,0xa53b25ca9678e87be1fcef929c93d97ac456308f8405be0910fc8e917f264042
01411,0x00cba9ae4ebb3a6e3876f16c22db9914e07a4a175b582fdeefbb60001dae465d
01412,0xda3d50bfc90ee547701ab1777f4cc626aae0183fe5d1f42df31048ea85c2a626
01413,0xfe77f727e1f01d1287955db0e75a11f8f1077ebe78a7c96ecaf808e22009fa9e
01414,0x1053d23c71dc7e09a2250926009b353ea3f44a599953e347de0fd8347d677762
01415,0x1f9ee40833afefffc10bd0f240252f1fc70ebd6bd9fe7894816a369f78f40940
01416,0x162769df545470c247d848320910bb169a9c95859e676d531bcae4ff4eaac292
01417,0x6904f50508e80bc3f8fd40550fb06c98df9da1f1fce47c95e81e47a030917002
01418,0x668379548128b70fe1b31b174c6daa8a0915557d1769beb2bcfab9f95884baaa
01419,0x55bb8c9a8b55e224e139cd6f93893700ac261f27a2eab8f2d493d734366d1749
01420,0x37cb2c92be70871a49bcea2f3d90a6215a72609ef728c8e46922cbd6737c2c86
01421,0x05b6cf1bb6f912a9a46dd729ba1ea392e517ad277bb69b758dc88ffb08313288
01422,0xcf2496163a204528e56831eb7cad31b71b85aee9c8d584270c9728154e6a0bd1
01423,0x8500cec01a3af6600559bd3f68e2607eeacf62fc773fe4ea467c0592c9cf650f
01424,0xf9b23ca9378f773d6ce3ab66eee7f70e84b52cb82be13876d2cb7073dfc765c6
01425,0x2e9e77d2e086db1a3b04a73d17cc79247012b93c4aead1462d688857c983b16c
01426,0x8c07100577d5a565f3962df52798a8e7c74eded7237c57b6287308e30693fc31
01427,0x53b8caf6ce7524bd3161dabdee75a7948cb6813045b9422f0243b91d1a8046d5
01428,0x68be6c9f0b492c78b2598baf1e5a8d8c45a7738d41afd795fc57a6b9e5acf34c
01429,0x12a34f393f9f0f3e7630b128ba992bcb8bd211f817a4e14869d78cf465aebfcc
01430,0xff0a7be97f4019b220ec1afd81839cc10dc9c9d897a7131fc805393f82f998e8
01431,0x64d4fc5bc06327b48928cfcfa93581a8f840c950551365ab35029583fed9b421
01432,0x2205cdfc0fa6fd60df16cad0281d1321bb0727e0d9dda4e5695a415f8b0d25bc
01433,0xe4ccf7437255286798c6e3c8181f1d4981ea17ba6560bd9e25a86a4a558ec60c
01434,0x7720205861646892f7d4f654cbfb82e1efed9fa75fa779614a2d7f71a6a3546d
01435,0x467addf009150a231cbf58b439c8ee6859807d2cc444b5391288e84b73437e78
01436,0x8bd916a854e374573059266dd6eccc83a260c544a246cd8df022c12864d00a4a
01437,0x332b343d821178fd9f67670662e7d60926135fbc724ac83e15f76ac77fada151
01438,0x595d9cbeefcaf6ef0d0ca2e5b5e221777f7fb99a07f07f398759960a16ffedc4
01439,0xaed3cc6afce54a6dd6c0b6a68532d860d99ad64abb3550594166f2a5d1086b58
01440,0x41f0520f9167d87677b563d4652b1929a1cc45d49f59803bf30d288a1be2b06d
01441,0xe2a38fbc4c762ce28ad95fcd0b38b461fc43cf005e1c0efaa1a95e8b08496fd1
01442,0xef37dd9b1d91abce595f8e07f4b8200ff75af7d59811d7c222ddd0dcd5657b8b
01443,0x145a661e91fd5f7e7004a06124642067355ac94d3812c17dd7e28ab63e2b3bef
01444,0x9821beb8f5dcea100a98816920637fc5644bb4aae4d43e14056546177db2d2ff
01445,0x728597bdf315ebb1b2ab95a2cc6bf7b4b4740e6e6cb73be78c0827c9791d614b
01446,0x5ad80991f59ab3c3f5d9e4b0a64a0d1622a6f7201e6b4c9ab17425ef0e9c6328
01447,0x6b884caccbb53424351a0707fd38ec1780332432704f637261d061ce81669fb0
01448,0x869cb3c70c4fbab00ea39f9b8954bd0efc32ff9386d347d7731b482ea2fa1035
01449,0x5cac1bcb33f6344780d0ae7effa537b4597e788655c7f0ca76f6427ee6951593
01450,0xb92784114f94f68de5bc7ea7ff301e8123ad1ae21211d9fb843a809198f34732
01451,0x32f5e0e5826dcafa56e2102e122b65f91f47edbe4fd164774c5db7b3163d749f
01452,0xb43138d20c9f3a4ad12f1c6a14975528e934c45e0821fbbf924bd0e97c7ce091
01453,0x34bcded8fb20b97fb638a8f0b0b88da53ee9e9ab8e31c2ffcecd7cd172532e20
01454,0x11f80fd32648f792ece5e55a241f473f2733f6b2801df8be9679896d18947871
01455,0x18ea77d047b2a9fb5aabac87543ec56952c28aac11ecee3af95a4aa559bfed49
01456,0xf1aadb7cf016bd145d3abaaf1a285545e331a9878f8291692df22fa7ceb34ec6
01457,0xd00e9e6ffbb61a46cb574900034b3ee2e8ab614b1182d29fb228603016385094
01458,0x7ffab11d609947e556ac0f0aa0e92c8d1b7daae7c691e159e31bc2de3090e2d0
01459,0x6039b280fddd6ba4e398335bf0fabb83cd421c12d6a18f18b9f60249e3456e65
01460,0x8e889e14bc66328b31238cec0e5ca5de362bf8d995519de91c4c14a4f6dfd6db
01461,0x773c0e114f7bb0a7cdca0a604b930a3c77b35d4033a7eebaa8d380121a2441f9
01462,0xdf1babfea1ab0a8d9ae94988ffd97916576340ee9f76a697b4d783074a15cba8
01463,0x6d328022fe6152777777c85775f267864398abdd880baa956659469fee4c22ec
01464,0x1c7eb43c12aa64d6dbebe5f9946254cb7d4960e919112034b25cd78ba4c7fbf4
01465,0x10ffef9e33b607326adbb5aabb35e832952a99fca4662af142510332b9033a16
01466,0x7785bbd4cc92a53101de632d4335e09d7e3a7f8b8a2e5263d884c2e02f3541df
01467,0xb09a9b8e7e62a4ec64bef12e9b6467b0f7276db516b270cfee9b8f30b59e9349
01468,0x1919baf88fb35ea864c6e86c74db4a93ba81d8c573d53716fe6cb56804bb4c8d
01469,0x6338bf7f5a36a7559ab4b7abf0b3882c81aa369425bcf4718ac690d237d6e53d
01470,0x46fb7a9b26b5de93dfe8027aef0949cc8f81c523fcf3e578e6ac296acd396296
01471,0x18fb7c8f934ec0bd79726a6dbcf9b1949eae47eb8e8a59fc60821d374e5cad5b
01472,0x47a32b9d02c3f8fe8780885803d922d76e5ba346335f99c8b46bff9d33530a57
01473,0x333b7e8665b4aa205cc4136efce2add43fb3803b43a7f33e9386790b0846dab2
01474,0xfe24e3c1483ac948bb8e3ec3ace550f72726f2025abaf97dbee5997a2d7798f0
01475,0x81c78370e6f8e1054f5492a086f354fdbbdee13fc5eb433d5b70f6bde808feea
01476,0x857187a16d206dcf5ab6d0f375defe4689f638952e7be7e214a18ef95f612588
01477,0xad00e0b4f49ca226ba794de114b83f21049c9678d956ecd0a9456509a4d33b65
01478,0x8994eaa1d20c7865333115069f8f9b5d500b0ac5b77759a7938c4a9817e8a864
01479,0xcf4abf0e245ee8096e0a34974636acedc772135d2f99a493e78e84171c30d4fe
01480,0xae5f5367ea0f5fcae4b0cb50813b16611d4348211979e922c039849237dc7e0b
01481,0xa121c10e9e5b9ebfd54ddf768c22b1f9a0d99b1d002f0c14133b9069271a577d
01482,0x2110d171195a2de44d08df4b38a9ec39242e74e177a9a330137d2cfad24f0e6e
01483,0x56ec2844150d5baf181784999e0f12eedab61b6d106be33e2e5f4ae7cd9923c7
01484,0xba8ad4f1b96b86c81781dcd63aea4d8c817762f8950ad31b7b516ec86dbf9c56
01485,0xc56c3ef61383b31fe0426d4e7e6101b3ee93e36f8743513d6f2827f6dc7443e2
01486,0x57bc41042e73f44a9ffe5ad0ef0ed6a750b254d6174182d31210ec154bd5a6a2
01487,0x122d8e0fb38045e75447d5d4b098ded50d3519ab133f407f16ce80b7811f59f9
01488,0x42b25fd38e95b67a02cf2d2420f3baf74baf05cd3daa21c7d8422dd4ef082073
01489,0xb1acea4e751f8ab84a1701a3810b7425d7bd25b9a11191b8439d9ef021a0ae99
01490,0x34280f11add3d4fbc26f35a2bc3163e20bd68b0b2c5f5c977b3c5515f7f89c78
01491,0x503bfdfdf60af3f68c00940ce18790b5a4b27708860b9397c247b65ea306f9ac
01492,0x1b74997d1c74b3925d68bfb59f89532c82f8d40442462a20b8f8a247223217ee
01493,0xedfb26fba9e0f118447e4f1a2f427cbfe9b42bf74c74c8c347718c2bb25de638
01494,0xda405d1305cbe42530cf2a03f23706e2c2f0d5c4a8e3fe402026ac7cb9e00c7f
01495,0x3efe0cdadae9231c400665a65dee22fccf36020f991fbc5fc80a692a15e04100
01496,0x809b00b05e0da5745ec980caa06cd88004cd61873bee830f9da8d9cee061c0ce
01497,0xc6923521f989fdf033fef5f95561230bf2bc872c3be7088a3a0986f40417cbc2
01498,0x2ef9dbc94aeec86917f3545afcf139cb1092ae35566cb03667d71fa7b4a413e6
01499,0x23a65ef9fa71a5631cb9be2f1108a6ae5a52fd9123102d43b167267c5c0b6d86
01500,0x17e97c499981088f01ee7fd4110bc4e39552c70c535b2c01bfb825288c652cd1
01501,0x38815f395760557cb4ceaf43f9bd59d7f3ae3438d98e2e8e89a1a985d77def48
01502,0xc31ef6bf0361e3147b5cfa201a4296245cb801a4933e6e3c7c4040789fe39ebc
01503,0xc5393ba2406bc0b84edc863f36c63116e6f3ce5b3af9063cda7516ed664feddf
01504,0xb478f53b462aecc80018fc12f270409c9c21616d076a98f26dbb6bc76171fc03
01505,0xb8013f87cc39daaafdcd88f6338920b22c471bf7d7b589963a6ada06bfaea470
01506,0xf23ee99501bb670f523caf0761c956324dc590fed811bc4f6471b6c458805e5f
01507,0x21b534cf9c9af1ea839aad996558e17bf8698d1c0b6d1ccdb858fb19bf78fdc9
01508,0x9fbff7e7dce3188b5c5503deaa65b47c43c304c52f3f1f4fa5e8221759c75330
01509,0xe5141a21f39698a7b78ffce400c185d65fc6145c08b97e5630b16fef5cfea317
01510,0x87aec91b6b6a9b92dba7163b403a463f001693df580b79d1b630413de7c62540
01511,0xb041bb19cce32e94aba5ab72f8b325fe14088e933331cb81c090dd64628e3276
01512,0xe41b5ac2f66221e3e7486d2513c67051afc5530af04715e37c144c198240eb5e
01513,0x56a669268cf40b4111afe73a823da07e8a09f6304f8ab890b4645d2dfd7cbb24
01514,0x898d4f37bcd23ab1762aec11fd937e9b9843e74b3aa9c0b4ed5645b03fcbaf98
01515,0x935b5d7aeec407a6cd83f7d0dc160edc53cc8b7f5f2e019c05fe619226a5b67a
01516,0x4ad5c3e371e953f644173a234e019d8e14993f21100068a439bc901b164b0713
01517,0xbe94d5d09346e617ac54ff3494a7923b43d7ea91d61fdfa4a1185af83e73fee0
01518,0x40fa62d3a1d198625a85eb1afaea58c9644194914293db1246869aa4b7fcf547
01519,0x110e8af3acb590972a4f633434221317d3ac98b9fba73452c02e9a88e9de32f2
01520,0x6e412e20bae396e80928f28ec0179a1be7765947bd7e4765fe3b20524f60f2ca
01521,0x8ffe28ad29fdd6e42ccae7faf81b1715fd4df21451ddeb305a3eead7a514a17c
01522,0xe93cd0a078a29332cbd05e1570a988ad748db4a2b2f2dbc2c6bbab0bd3c8302b
01523,0x77f19add028523159fac380f499a2193f29ffde2ae2eb043719b798e272d2b3b
01524,0xf583c72783c0c5b90ab3a01c84eaf9ef04620259b4c1ccf074c9e74a22c98460
01525,0x326bed4654c8a2f1bf96d345ef7ac8eb3868861e561603b5dc50c8f623cf6333
01526,0x558f5bae98e6ad2e383096f2c381c126bdccfaa0c90cbbffb7480426f5803396
01527,0x17af0f4e322b322401ff5f1c360a93aa4c14babc71203e78a3f9df4cf56f8f02
01528,0xb3d28e9ba92278e4be3110b7813b95e05243fb026f3442e6961e686576399e5f
01529,0x6ce3df5c684e6d291db88d672af9848f1c597d58ad4aeb154d7d812d69878e22
01530,0x70b295e43e231b6edfb2ba45b14964ca609d06e596f65438c816a8919a141d38
01531,0x5694754d0ac3a99b57cfa34aa9a6f37d7749675127deb9dd45d920a767104724
01532,0xb7d62fb8035796a876d44ec6b484ecafb225782c12885d4cbd8768bfcc8648c5
01533,0x1c4ea22b6b5b40c697b2048c59cec06701c032ef4fc245402d68ab614ef4749f
01534,0x3f50bd7f0574c667cf8d6e4d96e8375e845f1bb58b5458a96fa4f13400978139
01535,0x56e96bf3a208e13326e3ae64501a9f8aa2a2306551a22729f4cdc632a316dc37
01536,0x4c0b5a25c4a9f692cb2d1d97cc2ed3a9c6be0263543702df9cfa818e67792ad1
01537,0xb84376f6b504ac6eee8eb390c9431dce6d21ba91bf66860488b267e140503df9
01538,0xa859e797a3880fcd290e20193e80d4cd6aac09cbe285520972863a0496ba9e5e
01539,0xb8f7332814753428b30912ab8eca0e635d4060a7ef66fecc91b9963f0d2a9b5b
01540,0x5075b4c47e8e56e7f17022c6c00170a30cdd7cf257d893dd917b6ae8725ef044
01541,0xd9a68897ad38b7a6b7948e66b75312956c32f2d8e2b27fdf3df27bb1e523587c
01542,0x4c44c323f56a00e42c55f8e08134019f4cfa635e945aab057be327146e41b193
01543,0xba0d8406b4b7bdb1f2a3c8bf6cc79c49d1a1ecb99e9a289ac2febb3f062a31db
01544,0xb730d9fb4712957266c8134e8ad45e064e9dde91be74a4bdba289dd2c1cd3b7f
01545,0x2a36dd0adc9b0a8ed517b92ef73ee18072f2ad87d992eac9b163ed13701c2d40
01546,0xcb6390d20de04adf9ca127b68f73fbbdde1ae451d3d5dd2e9deebed712c49122
01547,0x7be294479d6f126c3da2e73d6ae008ba912d377135e43eefcc6ca65e4e2d9770
01548,0xd42b2e596c43feb99b1a292cb65108e4d159699ce5399331ceedd101b37e8aa3
01549,0x3259acc6ebca1ee7695b4748c89145bfb0962571f616b5e2da44ac571746369f
01550,0x15c4efe66e352107540d4c8ce5d800c117a599da83ad34388cd17510682942bf
01551,0x2d99a1dc1815eff9f0d697fb3c79a078645b573ad228ebe569384ec8f747fc98
01552,0xccd34c1ecb8f3444c21ad2f645b5909fe2c44e9f282706205f45c102d68bd3b8
01553,0x0f3371da1271d47e61ed8a04772fd68751b8c7ef16c316b8f4b1491449354a47
01554,0x6acbe79cf6301c23a1202198de9abad6c1cf67718f48928176459a2e195839a3
01555,0x975db585f0f663c6e62d41199c823b48e1be2f596effa9c56222d3b7fdd48d40
01556,0xf8d968d981abe306802686c870f2d6071547604228bc7c8a9e26600cc13fc18f
01557,0x5250d82f1f9476a10e99a6b6c8d4664c52d206286eb62e544c4d93b6c8141608
01558,0x8817dc1dc6343f42591204b1036b8e8b9ac90aa6be40647b3c13fc48256b865f
01559,0x16cbfdacbf89ab417c81734171a541d1ebf55b17e4d62474a9883f9aa3b9d992
01560,0xcbaf55ad5cf0f88bfa5be589394b6a7ae0907116fdee9b447b4110ad76356049
01561,0xa12fc593dbc327d7a61fa0e695f2e6bbd10b70ae3dd87d32802487380d67334e
01562,0x310c6496b06f98c1553f27b9ef878db3e6b540a4008fb4de7d65cbb7b431f324
01563,0x5345e3d4fb9fb5cfc1e3ab07b7963c5185b3758583fce54826b59c8f59fc2bb9
01564,0x2280e4c1f8c9444f8a85a63a744b4d9cdaaaeec6c27a100b704c36ba1b27607a
01565,0x893942f1ae02af922386a011d94aea458b000e6ae58ac5105469f15ef5ccb00b
01566,0x237ef759964133b24b7d50fb860d3ef49f5b5473a5dfbb4deb12a9ee75e9d3c4
01567,0x1aec3b6ed606a370df07ff07933d708e4b30892c5b34eb27a3c179089ff70c24
01568,0xfc92fcf640f5c001fe4c37de77755ff442f5753d9500aba5636cad6cef432cba
01569,0xeacd9d2bc6090407814082b59e363afa47cb9148ffa584c065136e11c62413e9
01570,0xa22bf28892d91ec239139c3c7bb07a32887d7d42f9a097ee919e8f1333abe8be
01571,0x1a439d0701e901619bf55f220dd81ad945b75883f0832eb9d1ffad360225825f
01572,0x947ddced110265caee947bc7d343bafd17bafff910a68db5bcc0f46f0aee6fc7
01573,0x3a831bed82ec33cfb63e2489ca28d1dabcab3326a310e117ed3ff4d91893ad5e
01574,0x9028d18bb6a6f17c7d25c2c76c6faf7a9df0913107ee429b1cfa9e865cf3118a
01575,0x598f030e236f72cf6eff6d43fb7f974f911b9fc603980b37f15614ec3cd779c5
01576,0xf904329742dc4ffc14c96a9917c54d18a6fde0cb98c47d211e7f7ffb83956ae4
01577,0x8a587dfcf7eaa992e28ff6c3504df916cd4e01fe66fd293129ae957fb4426425
01578,0x43c1dcc3d038599b653d4863c7c9bb7cad97e7b7961695e8956e9bd42f2dc0b2
01579,0x92a983f23849ce276e11172312cf40a7aee0e9bd34c92f66f95a2b55ea9f3cba
01580,0x1c243107c6f0b4ef1b64cb91a8d1abe0dff736faf40a28e01448477799d7223b
01581,0x1f943824eeb9f6e597dd06662f22d72c259fe15ca30f79f85108fce6f9465c80
01582,0xde1cad895c807ccbc04c98614864decb0b4f438b79772508210e542de31a80d6
01583,0x2d72b6e45e90548bead586dbbe36d30832196b923fc15981b7a75b4635835cad
01584,0x393498cdb070387b507967acb20ca81ac651fc0112e6f8bf4275a998e87be113
01585,0xfa098e6dd3f968cc805e7e32e67beb12ee8d5791c9ad3f4c4f97d8090c5d7532
01586,0x379cb7fe8047796010944629cbaa6009c131882ada4df80b344f674a209a02ee
01587,0x62641130ea31f0236a9a003332e891538e45fa7190e93f9af17f15fdaa0f73e5
01588,0x63224c34401bb9cfd504b6527d4005cbe3d274af04571902b23f4623b177a276
01589,0xa972b2e4d5472258ad38813f7ab77a0daac4a0796875b562a65a989c1cb57dfb
01590,0x1370376c417b6f988efc6de15723eb81354087bb24b5be9affdd536f7eb5e878
01591,0x3c5940a5c4b1ced8cfba620ef392e3bcaea154dd3ec56371ebb50f7d3955488b
01592,0xfdcf0f058fd21fd4db98eec51153f4bc489fb41e08c1a8dbf8f1d7f3ffe01a0e
01593,0x7779354bd2845311c515a0f22e8f032d09e69f3d10a14a013152ae46000edfd5
01594,0xfc12f95bb18ce0bce9db6efa93b555b6108fc6f3241d56a25a2c07d8e18d4e6d
01595,0x2118c3d09fa86752bd92dd89053b9afb26337edcf84098361d149f3d9a8eb9d2
01596,0xf94bdd17711158be2e5aba2f31d933bca8e1d608a0aaee8d611255e5822072bb
01597,0xaeb7c436d1407307f9daa397e49a35bb39d2b7612dcf4a40639643fdd06185cd
01598,0xf56b793b792ea72e3e3f8c92ac085de3c0b6e2a04a11486599b92a86c6abd4f2
01599,0x6cf982a28fdaf8ff3086f2ab622848b9a1cc92e347202b0c3b5bc8da8669ad9a
01600,0xc6a9ee35cb2a1e7ace08025884a30c605db736d1b026cbca495b623cef531c78
01601,0x0497bfd92c28ce3e12442ae4bafb6b8bb950448933fbfa5faf307a908385990b
01602,0x9a50fff5ebacea0ef3d7d163034333d6c0c133718fae765896cc19513d0e3ed1
01603,0xa1d88a2633e02e2c4e08d94c97fd1b76d7003800f78dc3323f9bcc5af6d00bb2
01604,0x00e0c17d808088777af62a97fe1e63d0a1ea1433c5368c5e7427bde3e7677589
01605,0x8fec155e0c69236d83d2c7039e0e904d800eba28c739bad9bfc5b4c3e616b1a5
01606,0x7642a7d34a91eb38072e60a0b44d304de3f84d42928c44891b8768a2255696de
01607,0x0a337fdbd42c275522b604f3cf7eebe86a7876ba0e93ad89fc725fa37bffa4b1
01608,0x2b8f0227d5c0605529146c4b66cefdef9fded753b2f496b5d2232de3f0f0ff0d
01609,0xceafb20105e86dad0aea7a8cd971d4960c6e675d677a4ff5b467c57072e1c324
01610,0x99fdde4b6905f88a904c45a0fae519384c35cbf770ac691cc2f972bc91c9e92a
01611,0x0d642ed657bd7c7bad338118f728552422e9d918fc5a6d45b276be73ee489fb6
01612,0x01a109f9c1765421c41b740a0beeada7ec1527a116e075768051a865688abc4a
01613,0x409c216ecee281bfa9d2292d1483c07a83af57ede1d306c3ef1357e6207bbc38
01614,0x608abfc5fdaed326966359b7494e26fad1a0897d36404404cdd1e9d760a2cc63
01615,0x546296f9bdd48f7a10748c5685047652d24ee0f5d9d5d39d00c138b5b72963a3
01616,0x210f4a03fc1ad41169c1a2110e9881cb518e3a91920784a93790ec49b14ca899
01617,0xf300016daf617180a864891d6e395a1d693586922d87b42012be8d01f21a08c6
01618,0xd126355b8481e0ce290bcd7d8e59ea88d84464af126c0711c4aace2295d81ec6
01619,0xfccf39eec398431f05ecebc058d0f7451b0601e47c8a32403f430fee1fa91b4b
01620,0x62719ac2f5906f11574a39f6235b3d12052d2df36855880901e99ab7dc7671da
01621,0xd410e2d782f4489c884bfca0410d81ec6376b2558e2fdaa4329d57739155b4e2
01622,0x3a2643d146858acc75041baf09f47c0f2d25d4f102c12fc7d3db22f670be350f
01623,0xb86b68f188d4f0d56f35bd8df010b9154c282c78ea9604ef6e94084e9c851b8d
01624,0x79abcea66a1e7adfb03c8c047ccc1823881335a68f7221a13f057b9b812fa6eb
01625,0x9d2445ad11ecdc91945bf0507eb97181e1a8d7373c3f68b0760959a45a32fd05
01626,0xa0719f0293eda9efab5b6cd4fbe9be45f707761d77e089ab27c965058eed2737
01627,0x3825eb62719002200fd1b8ece3f1fdcf80705657d68e418366eeae57b14acfbd
01628,0x49d1a71da4a7a27348aefd008cc5227b28544ee604eb242e1c2b037f67c3abdb
01629,0x1ec93093a36a54010ad1302caf7c5c24188c3d668ccfe895972a57ff6587850d
01630,0xd52d9f3e99b17ef53cb1045db3488f149feb348547eaaa57f54bf7aaf6d18957
01631,0x438a5c23f506d979268a2884664886c208526d050df78870f68c331625ee95d0
01632,0xb811a1ab572962105e233bc72569ef1ef980ffaec0c58c62c0e08744fdb23a7d
01633,0x2dba253d07386a24dac2fc5c78c557e25f4e521c2c5c37ebf514b9bbabd9f4f2
01634,0xc0975217f67c73ea0f22c7475233b64524f228a7da61e6c531cfd932cee27109
01635,0x926f0429fd3f751c428e5501e7ffbb006ad7048930e1820455b6fe404b7d8a17
01636,0x88bc22af6003d122e5ac2b7981aefe48cc5e787777a77364dc12530b35d33397
01637,0xd10229ae7c392518d3bcaa15f43ed0c2cca4f235cbe009e1aa711b109cded52c
01638,0xf60a479f9ebd1a81e807ddaa404c8cc9b855eb08efa4481810529674214b8c84
01639,0x45574d293ed9b0ade09f8b041efd0f9be629979743111520a7c0224e41c36213
01640,0xf4d925c6aaeb0d96944b66a46324fd09815af73338fe9c58c332f77869473fff
01641,0x055616453b16d6ff8caa12ea67e2543aa0fe47cb5c610699d5aded16ccdb72d2
01642,0xbffe5d04ec76b2d00ec35af8ed488116f1d3d454b1476db9c68bc62590b91b62
01643,0xdb04ce690ea5b0472a5f3d630336a0977e19517bb6c8443876e76d49f5876c98
01644,0x836dd3c2e51dd27fdfc1aca4839218e9a40390bb8966c257d470c5e13d610d09
01645,0xccdd4d3758c1b860176290f80a588cf9f8f257ee6a094019968b645969039e52
01646,0xdf78d1aa527997f2f34dcc3df048e8273d4c2147867b13f009fff3fabe1227e6
01647,0xbc1a2596d167f86f145df1c74a4ce5cdeb09e21c4f9077a7b7a75a026a9cd7e0
01648,0xba4445506249f1cd7510b1159ba679867a8a721810502db35b871131a52f6e9b
01649,0xc772985ee13356a7519f619cba370e0d30b2b17faac8e8779b34e77f319c2f21
01650,0x0cd44f84d292e1d1a88b51fb885b084cb2e3e4e9ab284c6174e1277fdc808c12
01651,0x108b81392c28178c4f4fb98ed3e03860ebad588e089fbf85a87ba9988e27c055
01652,0x92dc53a4408de761c673c56bf0c52c88cd2cd65777b47f65ba27265dcf5a4b2e
01653,0xac1c8ccb958d598d2591f82adcbce06cd05c5bc8c7714195f2808a42602cbd55
01654,0x2f466ff62e6b2eb3193683dca7c0af52da1825c22cae69cfda8b187d2d719bfd
01655,0x4dc5edd2150d175af8dd28927a1529a52080d0e0d2075d0c6f703ec2a527ef03
01656,0x72d321b5204000c80fd39ccf2fe72a17cac0eea2195133632b987461a4939c1d
01657,0xd0684723c2fcb39b6536736b92d24f7ca1bbb6b64c51c69ed69eae1ab22c83c7
01658,0x651f1c70b5bd5638c095aeaee6313f1d4d2e28471ce7ce98aed045cec480d016
01659,0x0013c08b64bf7e3afab80ad4f8ea9423f1a7d8b31a149fc3b832d7980719c60c
01660,0x7825d5b222a31cadf8cc345ae34eff92e4d617659c3f630037821d5acf6a5cfa
01661,0x84e21383079e4674dd0c63cb29cd89f0726ed8895aa83aa99febd249dc9620a4
01662,0xa5681587c34c7e8d143b6332a98804a6940655b08c9764ee13f8362b929f15eb
01663,0xc84283fad5c6405f6c9d51c0597b9908406ff09772233255fe61a1494e09cb2c
01664,0xab3af7a0e7c174b428f865f4fbe6d49aab50b91a0cb5555687f2769c6c874836
01665,0xd0adeec06347b843d108e4d349b50156dcaa131bc27c7752a1cc3c3035b230d2
01666,0x827de27e4fa09f2ddd98223a7393881100fd9c533b55416b3839ad8f3b6835ec
01667,0x558e21250bc559d5e9cbf0b5c9787f4607cd769a3d96d4c174b769907b8032f2
01668,0x8d75bc100e6afde488e081895914ea1c5658115a0e028b439e2cb2d52c02a29c
01669,0x84ccda7e5a2f253fee50e47559bdd8db96026897cec18ac128409ec405979de1
01670,0x3490d679757169a0132ca44b3c408b53e9dbb23dfde34a6c8ad34ddd0f88ce78
01671,0x4533f7b3dc71406ffa10a0af1fbb9b2d5cf61f7ae1d7a58c57734680984ef875
01672,0xabf106295d76c72cbcc2b778712a1b954319d1b4a1365e19cbbf9ed0c39d7445
01673,0xd67018bd3f840799601c348f8d2a55eb0d46ece00688a3ae5d7a699de71817a0
01674,0x16b9e8771fd65164ad5b4344b67bbc519da70ca263c562c0088a9c30dde29cb9
01675,0x35b0af7b1dfac60196dec285536cee1ff48d20579fe0df117be9566c78fd9404
01676,0x2753d9cd14ed65494895baf136feef1f4c0096ac569e856a0b858c43046dbaf5
01677,0xe40b2ea438c3da468e62d736f576e9c6bf89e7b2079569b11b7b63ab6b859e53
01678,0xfcbdf0e3790abaa1ed31b64333b348ecdc15a15a213488f46d753ea77659d1b9
01679,0xe5f342e28cd6a85862e29a8bc6ededb8ce9e5252f02db387ca6b27f234a1c8c4
01680,0xaf511202a03e86af88d1a53657068bad1682ed4d3c3d446e4e553313c4183f91
01681,0xd0e6d3d3842257da332754ff2e0ee2f28b630041e206da98093d60fd29cb2494
01682,0x66ddcfa8295f3681fe0dc6fa254f4a86cd25127f247cde63ea7b310f8934f163
01683,0x8887a5b6add7aad0916907bf209931a98364a7c2a74162ccbea586d2c95fc4fb
01684,0xbb0ab38ced9c5de37409997ef703c79d0d0273d0599436d79c86fb19710f0580
01685,0x64bf045d836bd1a99dd127859286752a1c09c20fb5b8a70d2c238c86d6565640
01686,0x7a8fba5b00f60ce646da4ffa64981c334b927fbbbfa037890aab81f2ae5c65fc
01687,0x26481dad4204488c03b357ab61f70c3e214800bd461be5b14a758caacbac5a94
01688,0x05f0a17478f22868e8c1442a512807f1ba0f0ba7d2452c2ada4b0626b23b6019
01689,0xac53e2ecad8e9ff6a20cd863627056469d0fe53c1e5ec3b590dffc853f36576e
01690,0x9dbcd976d813101a23ea057a561d714c26264f42fec6b5f3dd2f06708423867a
01691,0xbb315f50f96b903776ae3f1e1cac5b683d34104953c62bae500aa4b2a29d8a4e
01692,0xb877548bc73b777200804316b2cf7081152f0fa8923908b8ce8715126fbb3963
01693,0x3d2c2aad64a353e2400dd1141f9bd7bab23dfa8aec7c2e5c42a1c52c58fd7cd5
01694,0xd42cdf89f6ddbc2f8a8bcd4f6786cf73b985399c41328fd76c08821dcb2cb39a
01695,0x8d97b21795f44f7c853891c4f8007e2b9eeb7999c16ff0d81e744742f758dc7c
01696,0x49e0b594a63361d8cb35b386558238731b5b206702a2b68050290948b97a2b90
01697,0x01b23d087a4adf659d9a5f4c65eaf4a3164b46a7398dc516a52efd4f2f8ca77c
01698,0x9c316b67ce5ae45a6ba25c46c1720b77741ce1bd7631e5da01fb509ca50ace2f
01699,0xcea5c210e2ef00d919631ccb5e68b178fb9b480062d13cc8604ce3845d950362
01700,0x3d9833e9df7243daa3904d9a41d3808841ba7ea07998eb140d63ad0b82f49d5f
01701,0x073ad3dcaef6a4e5c3deec4d10a9795592dca55108e7fd3cf274ada351c290ae
01702,0x9c454cbcd610aa388489e7db1f4849677840ce1f0a3679e88d9e102e2b646aa7
01703,0x0d424bdb826419a44bbe1435dbf09f15e33b105a97d0c11741401fb5e151f306
01704,0xc842662446daaba43a5dbc82bb9bc5735a21aba5fa7c6a0642a2a645d2fb06a9
01705,0x850425a72ebd6cac965b15c5411581bb261a58e2e9f304fbbcc1f6ec56a3689a
01706,0x5f7468d23fbeed676fe8188c346cc24453860c8e265373880ee3ca128e9f98b9
01707,0x68199dcdf8d631885b4e264ef8160a64551e500f2f49aaac4e2966d6b42143fb
01708,0x1bc39088aff2c8759c5f61190c8af3aeb48cc644a57ec061b6547c97395754a4
01709,0xac6bdf4cbd7c785c68ed288da6c280a6d1b7340e882e1a71688e56b31d237970
01710,0x616a421395c539814d92259f0dbdccc436b6be78d1ad264305abc632fae12c63
01711,0x675a2efc56ef5c385bc82bd826482cd8247801e0556f38182d2d396d7af13474
01712,0xb3466ce1c9c6c1f1c5c8681c13442c053bd73443ebd60b0443cccf95717fb756
01713,0xefe87a15350ae4b7ea6136f27efba4c610f7d260cad4188771530e46a85d96ca
01714,0x8a93b06d9b9e80fc6e21443ec976bbd3de80fa2ca50768e728598d44c6fce197
01715,0xc53f6fe8560e2c1f79a629b335139dff42a166dba3a3f3cdd8b9f3c45c482cef
01716,0xbeebbc85402356009b2eecfc3e808aa7d6b671ce58430bada153e2678890476a
01717,0x2daba19a743ea4ca797c5c20fffea6f79979ebd83d0606fa86a38c02709d0425
01718,0x69ddf701e288b58796af67a303745d123486204a9a7e0ac18b2afb25c4c9b61d
01719,0xac2ebcf440ba3a2ef280e8004918a9b6d849e19b321823a57132d7799c21a147
01720,0xc428eb527615d3acc4dbd68d2052fe6db27152c73bb2b22edfe4d9f13fd67ecf
01721,0x940116cedc675ccdecfc2ace0d21817c7e13d57154dfbabd0ac759cb68fc7aed
01722,0x1aff873b75f990bea4c06fd212d2862a06d28047e47592b8809eeb164826bdf8
01723,0xf19dc7c143cd5aac499bab456496409958bc496ed1b807c209069e5fb78089a6
01724,0x50ba9e2446defbca234aba740d15221152d261f9987e24f6e9ff3833d2422c88
01725,0x6244c9ba553c0a9fdd9985673ec8dc94558b1208ea0b2c09cae8baec14ef04ef
01726,0xd9ca0531bdadeb4a42bbbe600161d3bc0c29f6de35c37b584d463c87cc8929be
01727,0x019f04b76df87f056d3e85bf6100ad35611dce5c332f9c885cf4ddf9e4b0df05
01728,0x0bd9139ddae4c9e202aa11614fbe037609445363727e6057db969600bc442615
01729,0xa85a5ebec5a89cea73285765cd253a54806b53af28dd7577198839114fc037a3
01730,0xe07d8fc1ad730fc509989b081ff643430c4d25396853553dde4bc01e0a5c774c
01731,0xcdeae685f4d356e7c5cd458638103aa02069a6ca2d8c459bbc49b9e3ac9f302f
01732,0xd4b05748bb2981bff1958a4dba0b0f59559bfd5f8fd4e32b1d6c94d0902e1087
01733,0x2b75c3c9e417a3ee775e3f6d8b333588c4c8eb482ad9c611c73b8de9fff3403c
01734,0x0b51aa4b64600138e09022ba4fcd58449faf43f4b1f8a5e82d9450fec703516c
01735,0x5b7da9fdc48dac8163f0a2620536639c95e1f3c35f5d09442cd077900ba3397e
01736,0x2d581b4305c5b54aa72fbb2dea7f95fcd7ecd06dbafa7d1f52197cbb86cd7275
01737,0x053468cbce94fcb5f0170028e0a585bb98000c005cbb0f9d8cdc0274cc3fdcf4
01738,0xc4ea73550a711a24cdb631632d8b9826098f572e1dd0f5d338a7d571e40a0670
01739,0x390296d239ff8e7ba83108c01143904890332e29c7fb89f287be70d9e446a4af
01740,0x0bc99a43bd74f339e60b6cb7235925e6bd78a56014979d6dd161ad9e2f65c9db
01741,0x831ca1406a51f08d9e8b7f9b4ae4e9b1562ec6b3a965e648f5fba403985d7c5f
01742,0x6ea854bc3a2a1cad0e25a07bc1a13146837088263c4b906a86f3aff87748a250
01743,0xcbe74e160ce637284edac7282156fd9a04638631e32dde566ef91abe19e9d7db
01744,0xafde3d1a0a5c90a5b6a8ace6e0c51f287a7baa6cd52fbb530d5cd30d77d1a9e1
01745,0x265425af9916bed0dd62a2456e7c7da2c9c0f07a25c8974425dc0f116865942f
01746,0xffa83edd16de7ec3db737cea195c255b9711b59c21b1497e26747bed2e13f943
01747,0x2d7f0f5ad114008c8bcb0c95c1368739149923d73651da238d74d6e4f2e3acb7
01748,0x7b69dcfeced3aa613f02ad7933e543e8dd53bfaeee20d90f4f1bd38429dfacf0
01749,0xc08c96110c4d40c906c9f31d2d959c22201f86eade534578a58c391900fa278f
01750,0x6067e2dac2ea8b7d928570e0b358cb2bde6a09b5169325a6d553e6215ab5b5c6
01751,0x50262a09aa1822e9da30e2dfd935d89e012d1d336a88f24d8db38e4ec1608284
01752,0x0488926e04563f273a6ad741c30908764e8dac6e38d7032eb8d398a39b6e0f42
01753,0x7477c0a14e3afe6b1210829b4fd571ddba704e062565ee06f8fc00631cc348ba
01754,0x646def35e15739fb4e6b897511c4a71c34b323e0107a079a03ffe1be11480962
01755,0x84f4fc01aa6c9e739865d63f71d6860875ba166ea67b4aa068de28cb1adffc8f
01756,0x308e058035fe5998006d16d2b6f6fb289d120e402b96d10100c98e92efc86619
01757,0x8b98854f27b4a6d80d520f8fe71c52fafbe55252d3df554a907a9c0c90f1de89
01758,0x7c7bd9920cdb8efaed244a333152b7f205bfee6f2eff4e0da455d882b070ab6c
01759,0xef9dd1ae52176b521f99f60ae0a16baa1832aec7ce2b95c0e6b20cbd0943b218
01760,0xc908c0cba78857bee8eaac7c241106164154782cf8c712987f4b6eb687161ed5
01761,0x4c223079fd963774b68c0c75835a4f73a591a7f6647c09fa5def8021344fd209
01762,0x58e9482fe6e25ceccb977c5945db92bc2ff9fd044336dbfd13714e6f84d9c99a
01763,0xe9b64e4399b811a832bea55ce15fb1a55718352899e8fed5cba324e196b4004e
01764,0x69d58dfd877a727ac73429279bd99ba2562eb358598d6c7f2941cdac9f3307bb
01765,0x565089600e60764e78b07382ce1e0acc93b255ac0d9e20b4ad585767be9e8ab4
01766,0xe47ad77ca6b9d30cefda397443229cb1df5561c9a436fa9d94d3752dbab1b8cd
01767,0xc92526a4d2bacdc047f4e86f6a2b159f6c72df8157178c4ca89cda1780245b1b
01768,0x0f318bcdb0e0d78f54276c87b5be9aa21919381bf2e82205072e8c10cb8cbc21
01769,0xcc56b7c7ff7ead6cf9f72199ed9ae0a94d5afcd7fc25ad93275a37cdde487e62
01770,0x8a0d9bcdcf18b4038a4df3f96e0782f2bb1d4d84ef4932b73dd0f2655f1c9187
01771,0x8c0c7922138320604c1287c6c0f87fdb37566752373a62c150c06653189cf070
01772,0x490072e141e5099852008eb31e3b432bbc2d71cd988dd62a6872bd723f4464a9
01773,0x441a3c8c2fe28eede2b4ed609cf3fca8740cac9638c5962e2214c00365a3a787
01774,0x9d3c41ed132dc44de0d39c9d3dd4cc11c1e8a7f8f0316eb774991a9999c0f372
01775,0x6023b5ad4e7a8f918fefab880f48288bd8e0da6b9e2e3880f17ab96e3ebcd618
01776,0x848902b06524297d54f30c1ddb0c7629c03fb1ba49464244cfe8b198ff99dc26
01777,0x56f9c62bb1fb7eb1575c94cf34a37b136b82db0979412504812d7bd21990d5a2
01778,0x01a7fc06f4248e48ece709e46292bb7e0a69317fefbd38215c4c093a0d42e425
01779,0x9ff0b05413db15b73284db1b8d1702ff095cce5810d44c6457693516ac3e4d65
01780,0x0601be62d83f52db2fd5baa50940e9efb464596f0ed80d11722d2944f56bc38b
01781,0xc73b916a7b1049230c965741275142bf554805f395feeddf9a8a84934fefce35
01782,0x4ff9deb85b08cc30d36d12e391e9ee9bb72a7db2cb52679b62cbae6059a67a46
01783,0x6dcf0704c8afbf5b87adf316a01ebff4f641cefff7ba33d672ed51f477a2cf8a
01784,0x37725e0bd787534538108e890787fd1606569bd4db127d22da37f2a4f2373fde
01785,0xbb264cc368c6866747b9a711e14933f8d96f905bdb0b25a07cfcfd2b094a5fa4
01786,0x8f3dccda34ec0838afc97c36da3b66c7a3c804709ed64b4725809ede5248dbbf
01787,0x8cae5bdc47bc087d43c41f973c4711ea0af9e5ae53fc5a2fa3ff104070524401
01788,0x7e1c1704cf56b2e8cdf4ec7af790cdffcc0cfb3fa840a43ffd46d4fa0d0458a1
01789,0xdb34d4b8ff52ebaaca16e0ee46cc56669773768e2c2473470d055004825f6024
01790,0x0e2fc599445336cd593fe78469762a0eaef058edc4f9a10a7083b42578eb6b18
01791,0x0dabc8f4f2cc029e70b238f3ba3f2478038729cbdab741e25e934f3828891e60
01792,0x648d0dd207d0201595e12a8a30b247f7d51ee8385935ba68393db91c846459b6
01793,0x77485ef35b5343f0b16fab3492a9565a3fabb6b97d3076f2877c489b0a808ad5
01794,0xe291673e64217556218b47874f5d9d4c6bf392894f6cabd9f572cf4750bd4d47
01795,0xd1d496b1a49c1b8f9e5a7e1146dca4e3c28ac4be22ec0d8764f56ff3ccda0e69
01796,0x33a5546bb26b46559e6b72502faf6dfa1060fb41a69bf9fff988c463f6132aa0
01797,0x34123297e57b8a075114c3698558387086e3a4b2acfdd54041901f952e7afb91
01798,0x3ca0aeadff3449302ce20766cc4dc0b1628f85cbd26665a40b0f509493428f08
01799,0xe949b50c73fe40ff59ab7e8b460a5c81a411b02931151d95eba96ba7e422b731
01800,0x07cb6fc533ed260b5b01e470e4d874270270fc5332f423e620be1dd92b06ff6a
01801,0x8edf5827b93f9dd727c25e4cdf558bdef0c8d1962c993666fb469082ae607e6e
01802,0xf95306bb3bc429f9229f80e3fd50446435e98eb615bffdb379d202abcad65f98
01803,0x4e1d05e25890a1b0b1f301452321893b91ec09ca755dea16b16fd8eb0d02a39d
01804,0xa24b5a4a59adcc97ac586cf83a7314357ae74c48d9099ca9463954f8ca24db24
01805,0x81d9a9522808c36c1845abcc5a080b237f69ec54c4f263c31c3fb2738bddbf38
01806,0x66534ad9878fc2792c46d45c62a93320cdbd40c276025bcfb786dda3b53e775c
01807,0x37ac18016b4a26060dde93000fe2b5614ae011c506725b391bdafaf9d613f8fa
01808,0x3f1a883d82a05988793b449444221a6baa67a0975a8bdc20bd5c8044fb059bd7
01809,0x45d0f53f5567f627b64e808129a7730badce39d542584ac3b4e392e549eebe9b
01810,0x6ccaab76edecb5af607c5f4a741d30e9b9762ac77bfcac89b087ac9fdb51727f
01811,0x9ab98ad907f0df327b31733e17eca703d44c5315e0f3f381dee38a6716e9bbb6
01812,0x80d86e96ae3c138cb93d8b83e1aca9930c3aef9845f19e164076a319c12b3d29
01813,0x1b4ae400e53cfcfe9027f84324909f496fdba244a748a8786a8b6f30126bedb6
01814,0xe0064cce975cf20b2bf11f501c61e1cfc5df450c0231fea9b29df7d134b1b5cd
01815,0xa2d0424093b6f41d5bc9c2d6bc63596e722f91e214f3453d692e27404d58cb31
01816,0x9a493dd73536b40fe784e7710b23ead682163b5c2873d06fb634b41821df1d12
01817,0xf534c5f3151aba70c4902307fd1d8cb8a9227ea3bfe00099879f9af4458f7cca
01818,0xc34b86c65e0db470eb8f644fc648b5520546535adecff743126a2bb394fb474a
01819,0x918b86fa5fabcbe1535ff25b9cc6bf18399033a10feab07b1b2a44e652c890c7
01820,0x17e7111cf764fe48d55ae33eb9992d4fa0c443e17aba5ed8121665d09e719642
01821,0xe118ce724863baafe5822a6df3eb6322f52b0efac93df5ce30f2890249a5301b
01822,0xd7b7b15d51895e067d217712e532f4c1ca318bec69483371d584eca1fcd35dd9
01823,0x3fe7a945dc87c69c3c018c68cc45a5ad9d5c76a9623a615305eb03b30bde5286
01824,0x6ad87d358fe720d6207c7189c458f01246ef8fdbcebe5bf977590c5053395226
01825,0x7f98124406ff6a0ac572d6cbedd187c905ab77a2957904ba9df742ddd37616d9
01826,0xc17dc5a387763a48690eeff9f15e2c8a17d46585c0330f855207bf83db5ba7ca
01827,0xfa5fbccba9509f70ed5a39bbc8148708230e37f26fb18b7a74aea1616e3e4609
01828,0x540009e54254fad311b1b69490c7587db7dbf71ce7a15e62f94d49eaf22525e6
01829,0x41ed6fe79b33dc5a32a019496131ea6805aef33a6aaf93982d37dd7653decb41
01830,0x2afebfecd0c3c447d920747a1346c865aa846b0ae6f7eb900e25606c8d9ed725
01831,0x7289db8d2960f6402252c8699465253d4e3efdc31c832a9ba82b535bbe39dfa1
01832,0xb1198d248f79e07609cf29ef8984e2786258b474c17a982d2e4e9219af3d6592
01833,0x0bef12618bd2905629f0c9d7427431884e203e70d78f5c9308a3215d79a28556
01834,0xfdca337f0afcb8f508449dcfebafb6de99c44f1a468a0c162785b36b20c01446
01835,0xa45d06eca259ea9bf79a23c0a8a50cd784fa072330050f7da63a0e4acd14b4f6
01836,0x87fe297ba8e996cf2b1fdb854e86b043f485149eea31c3c74187402b58892cce
01837,0xe26e40bdb2425b55bd59c814f5839f7ff9f74aa1aa86d23e95988048d319e64c
01838,0xec6b0c035002b5d12e30ff8e3f97f281f562593eff842cf8905468c3d9c9777e
01839,0x07950048304ce616f23f40789e4f7995ce30e164dc5e35d97ab241998924b825
01840,0xe287972bf569570a6f2f8d3dd01ceebff3c9c849706e2ebe133ce72dbbbadcec
01841,0x2a6039e5b858d952e07cbc9057a4506b30edd01944b253c0bb68fdc9e4616b6b
01842,0x5567d80f36494b4f26232e2a26f06fc382bdddf8b9eb7a20d56087f13e1cd561
01843,0x3153e10ad6830573f85e149d79579aaa27e4161239b5bef085dfe1c86d2d04cf
01844,0x03b0963dd2f6917a141dcb843dcdc7b8fe71ffc51a29cf86b7f909ba9ff178b2
01845,0x03b93b158737ecadc1a498bbe78e247ec652f5707571512674bb231e4c35593f
01846,0x3e05673eeaabb4293f6eba4fc8597b21e935e72e7d614665480e881bba552938
01847,0x2de5f285569a2744c7dc3b94d992c655037d370f4f8d8ca04a26b4f30ccbf5ed
01848,0x113a0599656907adc266ada978194806c922455ded32bdb8578ddedcc0e31d8b
01849,0x71675e40a1ede46ed372c411541b1a66c4d76d33fbfd97db91b9a3a96a45e669
01850,0xeb0e8dced91d0329228af294e8273236ae0a4e6f8590ed770ce6b8ecb9d4e9b2
01851,0x27b488ec8baa7adbc492e5c2311f57d1bb025e42fb362933096f7dbf66112277
01852,0xa405f5f3d7c35326f18a1a85fcd88a897d5e3a31867791cee9489042b950375b
01853,0xde7294f59c86cf434f1b51c11d36eec758c73de3e0cfdfb0d88f7ef4e6aaf946
01854,0x1b3a9f72ed4d4521657db928917a7abdd71f4ba2cf1fa4915b68d1c840fe3eb8
01855,0xbb9869151522b5034619c9983d1c21d253a8a46dfc03bdb7c4e8771faa4cd31d
01856,0x10e8b0ee7a9e05e342cbdf4cc408d4d207163bf652e9d45a715f63a14079b558
01857,0xe0a70c38b92eb6cda8f9b7e2253b88bb8a25833d34f1174e9d5a3dc11d709fb0
01858,0x96299d525632a3677163bc6f18e98439e410f1c3f0a0e561bcbb63ed8022b860
01859,0x056f7f9b622e013fd1a31107cddb7843babb80ad494781ecc0408a4551a6a04c
01860,0xbe17dd25f8ad8b238b69e317126128e379aa87af72ab99cac240b4d6362ef148
01861,0x31641a0876c1fef62d170f84f2c6113d88d4d38ce90538e30bed4565fc6a3027
01862,0xdeb651e11a7f6e50e2c2adc32ec89af247c4c71763ab3d213bfca70b0e26c311
01863,0x500103a06c6cf65606e2c734912c6448844b87904ee9d68c7be782ac5f6188ca
01864,0x168be6df9d2a7ba553609c9235d1cef41b783323f60f7c59ca210f3e9db4d764
01865,0xd69771c57985c9c43d6195e8be9d199c3b3ca206a682a0c6c2a274b8294b644a
01866,0x3cf6a306ef85f605b6b8610c42f3200bc04bf7cfd1b325b8574ed2c28d4ffb62
01867,0x69891a16fc79a0e6fd885f23b106806ecf71ad7b3e5d51a579193c4f2583dc5e
01868,0xfb7b596a80d0782f73d11fae09d7da314be8143b471193a28901a36d6b58d8f1
01869,0xd864488dca9ec72930dbba8d9f554af78dacec003a6f58fbe05cbeeaa8eaca21
01870,0x3dc73a6d1c0433c0d98800a9877d3e0e9651e6eace71413ae0f52a7bf58616c8
01871,0xca53dc21977789285d08334ce43b0469a5bd54cf890a4ed1e0cf4543b1575457
01872,0xd571c79ae2f0b29d334f8c33b14b21a83491d21da2650ccd9d7e3f1b307ca7a4
01873,0xc71b3cef8fd89a79abb07c140f1cf9b90f4afaffa3d269ba2dcc9e2831cd0c3b
01874,0xb43aeeecf3e3603fc7f82cc03948d50a9cab2c30d26a371afa8d7b0526c20853
01875,0x24fb77820016a3b7ff7cd3ec7407364b0b660fb2a6bb0e26e4b8da1deb6275c2
01876,0x41ac34f85491e5d80275e95298185b3df6bc6e522b1b6e18a81b4a954573d27d
01877,0x54983d685feaa65ccbaed699e5c85a9cc5fb2275ee5ecc15295fa056f35dff42
01878,0x56db2145e5e6ffb8f46ab7fd0bf8192af4b7ee8701fc92e3066697fc7fdab1c1
01879,0x793c08df7c9a354e39b31fa213f2944ea8361ed33203f0e1e438351e185d241a
01880,0x0412a89eb5bf0325ce228aa64f66dcab0855c002db872dd94f3ee97496d41a1f
01881,0x8d9912853e99f373036df7a07e47eff4dba631f7456c6fee1bb79a292f530c13
01882,0x44df0aab52827e4608b4fab902457682fa019ad5cbbdf7502bb1ba74607078b7
01883,0xbd172681ef1b3e781763591809db8067a65590760a1a823716d2afffcd893492
01884,0x5732d988076cc1fedf316e07aa3a8567fd55a04ca989876d4bdc63681cbcce48
01885,0x5480f07444c8ba60faf8b853c77b72b2e0aee4894a176f920d0965eb92df90f9
01886,0xb5e8b2b00ba1708ec31ca0a7e64540c1b02d837991d4e12cdb19d6c75ed0da6b
01887,0xdededef33d83e607868d87e8f058511a152de71d8a04b12499d5f1666b89071d
01888,0xcdbce5e36cfff749d0ee9ccb6dc344a822ed097e4b8eb812ada19521890d5663
01889,0x4a09fe43bd97064993f18d214062005a1ffc76d03495b2b7c65c6137d3dd055e
01890,0xff7a1b1127af6429b799637ff6cffb9169aa5000f01b67a54e2c7f9a155e7027
01891,0x0f7bffdd015be88c78d30778d5bd66b75e86f9867e221f857352d0cb95c927a1
01892,0x9671b1edc7dc58206e18de1e4d107bf2e8508483017749146ff5c82c674408e6
01893,0x1b07973b9e818e0e014e52c587149c9775fd44bd5ccd095dee3221ba7c7a9efe
01894,0x804008940c025a4e8a00ea42a659b484ba32c14dff133e9d3b7bf3685c1e54de
01895,0x3f81607c8cb3f0448a11cab8df0e504b605581f4891a9a35bd9c0dd37a71834f
01896,0xe6ebe562c89bc8ecb94dc9b2889a27a816ec05d3d6bd1625acad72227071e721
```

## Security Considerations

The accumulator root should be verified by community members before being
accepted. Although the accumulator root can be verified at anytime by anyone in
the future, it is likely clients and other tooling will begin relying on proofs
against the aforementioned root in the near term.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 29 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7643</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7643</guid>
      </item>
    
      <item>
        <title>ERC-721 Name Registry Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7644-erc-721-name-registry-extension/19022</comments>
        
        <description>## Abstract

This extension defines an interface that adds a naming mechanism to [ERC-721](/EIPs/EIPS/eip-721) tokens. It allows each token to have a unique name with a set expiration date, ensuring uniqueness within the current NFT contract. The interface includes functions for assigning, updating, and querying names and their associated tokens, ensuring that names remain unique until they expire. The entity responsible for setting names depends on the specific use case scenario when utilizing this extension.

## Motivation

As decentralized domain registration methods evolve with the integration of NFTs, we see an opportunity to extend this paradigm to the realm of usernames. By associating token IDs with usernames, we enhance the intuitive identification of entities within decentralized ecosystems.

This integration serves multiple purposes:

- **Intuitiveness:** Numeric token IDs lack intuitive identification. By incorporating usernames, token IDs become more representative, improving usability.
  
- **Username Economy Exploration:** The registration mechanism opens avenues for exploring the username economy, offering benefits such as identity verification and social interactions.
  
- **Synergy with NFTs:** The fusion of usernames with NFTs unlocks synergistic growth, enabling novel applications like authenticated social interactions and personalized digital assets.

## Specification

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

Implementers of this extension **MUST** have all of the following functions:

```solidity
pragma solidity ^0.8.0;

/**
 * @title INameRegistry
 * @dev Interface for the NameRegistry smart contract.
 * This interface allows interaction with a NameRegistry, 
 * enabling the registration, management, and lookup of names 
 * with associated expiry dates tied to specific tokens.
 */
interface IERC7644 /* is IERC721 */ {

    /**
     * @dev Emitted when the name of a token is changed.
     * @param tokenId The token ID whose name is changed.
     * @param oldName The previous name of the token.
     * @param newName The new name assigned to the token.
     * @param expiryDate The expiry date of the new name registration.
     */
    event NameChanged(uint256 indexed tokenId, bytes32 oldName, bytes32 newName, uint256 expiryDate);

    /**
     * @dev Returns the name of the specified token, if the name has not expired.
     * @param tokenId The token ID to query for its name.
     * @return The name of the token, or an empty bytes32 if no name is set or it has expired.
     */
    function nameOf(uint256 tokenId) external view returns (bytes32);

    /**
     * @dev Returns the token ID associated with a given name, if the name registration has not expired.
     * @param _name The name to query for its associated token ID.
     * @return The token ID associated with the name, or zero if no token is found or the name has expired.
     */
    function tokenIdOf(bytes32 _name) external view returns (uint256);

    /**
     * @dev Allows a token owner to set or update the name of their token, subject to a duration for the name&apos;s validity.
     * @param tokenId The token ID whose name is to be set or updated.
     * @param _name The new name to assign to the token.
     * @param duration The duration in seconds for which the name is valid, starting from the time of calling this function.
     * Note: The name must be unique and not currently in use by an active (non-expired) registration.
     */
    function setName(uint256 tokenId, bytes32 _name, uint256 duration) external;

    /**
     * @dev Returns the tokenId and expiryDate for a given name, if the name registration has not expired.
     * @param _name The name to query for its associated token ID and expiry date.
     * @return tokenId The token ID associated with the name.
     * @return expiryDate The expiry date of the name registration.
     */
    function nameInfo(bytes32 _name) external view returns (uint256 tokenId, uint256 expiryDate);
	
}
```

## Rationale

#### Name Expiry

By implementing expiration periods for usernames, we introduce several advantages. This mechanism ensures a dynamic environment where unused or outdated usernames can be released, fostering a healthy ecosystem. It encourages turnover of usernames, preventing long-term hoarding and promoting active participation. Users are motivated to manage their username portfolio, renewing valuable names while relinquishing irrelevant ones. Ultimately, this fosters fairness and efficiency, ensuring naming resources are utilized effectively and refreshed to meet evolving needs.

#### Name Uniqueness

Enforcing unique usernames is crucial for maintaining a clear and intuitive identification system. It prevents confusion and enables seamless interactions within decentralized ecosystems. Unique usernames enhance discoverability and facilitate trust in transactions and social interactions. This requirement underscores the importance of clarity in decentralized environments, where precise identification is essential for building trust and facilitating efficient interactions.

#### Name Registration System

Introducing a registration system for usernames safeguards against abusive behaviors and promotes fair access to naming resources. Reservation and renewal mechanisms prevent monopolization of desirable usernames while enabling legitimate users to secure names of interest. Reservation ensures fair opportunities to claim desired usernames, preventing hoarding and speculative activities. Renewal mechanisms encourage active engagement and investment in the naming ecosystem. Together, these features create a balanced and inclusive environment, fostering a vibrant community of users.

## Backwards Compatibility

This standard is fully [ERC-721](/EIPs/EIPS/eip-721) compatible.

## Reference Implementation

```solidity
pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;

contract ERC7644 is ERC721 {
    event NameChanged(uint256 indexed tokenId, bytes32 oldName, bytes32 newName, uint256 expiryDate);

    struct NameRegistration {
        uint256 tokenId;
        uint256 expiryDate;
    }

    mapping(uint256 =&gt; bytes32) private _tokenNames;
    mapping(bytes32 =&gt; NameRegistration) private _nameRegistrations;
    mapping(uint256 =&gt; uint256) private _lastSetNameTime;

    uint256 public constant MAX_DURATION = 10 * 365 days;
    uint256 public constant MIN_SET_NAME_INTERVAL = 1 days;

    constructor() ERC721(&quot;Asd Token&quot;, &quot;ASDT&quot;) {}

    function nameOf(uint256 tokenId) public view returns (bytes32) {
        if(_tokenNames[tokenId] != bytes32(0) &amp;&amp; _nameRegistrations[_tokenNames[tokenId]].expiryDate &gt; block.timestamp)
        {
            return _tokenNames[tokenId];
        }else{
            return bytes32(0);
        }
    }

    function tokenIdOf(bytes32 _name) public view returns (uint256) {
        require(_nameRegistrations[_name].expiryDate &gt; block.timestamp, &quot;NameRegistry: Name expired&quot;);
        if(_nameRegistrations[_name].tokenId &gt; 0)
        {
            return _nameRegistrations[_name].tokenId;
        }else{
            return uint256(0);
        }
    }

    function setName(uint256 tokenId, bytes32 _name, uint256 duration) public {
        require(ownerOf(tokenId) == msg.sender, &quot;NameRegistry: Caller is not the token owner&quot;);
        require(duration &lt;= MAX_DURATION, &quot;NameRegistry: Duration exceeds maximum limit&quot;);
        require(block.timestamp - _lastSetNameTime[tokenId] &gt;= MIN_SET_NAME_INTERVAL, &quot;NameRegistry: Minimum interval not met&quot;);
        require(tokenIdOf(_name) == uint256(0) || tokenIdOf(_name) == tokenId, &quot;NameRegistry: Name already in use and not expired&quot;);

        bytes32 oldName = _tokenNames[tokenId];
        uint256 expiryDate = block.timestamp + duration;
        _setTokenName(tokenId, _name, expiryDate);

        emit NameChanged(tokenId, oldName, _name, expiryDate);

        _lastSetNameTime[tokenId] = block.timestamp;
    }

    function nameInfo(bytes32 _name) public view returns (uint256, uint256) {
        require(_nameRegistrations[_name].tokenId &gt; 0 &amp;&amp; _nameRegistrations[_name].expiryDate &gt; block.timestamp, &quot;NameRegistry: Name expired or does not exist&quot;);
        NameRegistration memory registration = _nameRegistrations[_name];
        return (registration.tokenId, registration.expiryDate);
    }

    function _setTokenName(uint256 tokenId, bytes32 _name, uint256 expiryDate) internal {
        _tokenNames[tokenId] = _name;
        _nameRegistrations[_name] = NameRegistration(tokenId, expiryDate);
    }
}
```

## Security Considerations

#### Mitigating Abusive Behaviors and Resource Hoarding

The design includes mechanisms to prevent abusive behaviors and resource hoarding. Minimum intervals for name setting and maximum durations for name expiry are established to deter spam and malicious attacks, limit rapid consecutive name registrations, and encourage fair and efficient use of naming resources. These measures mitigate potential security risks, ensuring names cannot be monopolized indefinitely and promoting a sustainable and equitable environment for all users.

#### Username Restrictions

To facilitate indexing and gas efficiency, usernames should adhere to a length constraint of 3 to 32 characters. This range prevents the registration of overly long names, which can be costly in terms of gas and difficult to manage. Limiting characters to the range of [a-zA-Z0-9] enhances readability and prevents the abuse of the naming system by restricting the use of special characters that could complicate domain resolution or user recognition. Implementing these constraints not only promotes a high level of usability within the ecosystem but also guards against the proliferation of spam registrations, ensuring that the registry remains accessible and functional for genuine users.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 01 Mar 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7644</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7644</guid>
      </item>
    
      <item>
        <title>Alias ORIGIN to SENDER</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7645-alias-origin-to-sender/19047</comments>
        
        <description>## Abstract

This EIP proposes aliasing the ORIGIN opcode to the SENDER opcode within the Ethereum Virtual Machine (EVM). The purpose of this change is to move Ethereum closer to enabling account abstraction by harmonizing the treatment of externally owned accounts (EOAs) and smart contracts and to address the security concerns associated with the use of ORIGIN that have and will continue to surface in all or most account abstraction proposals. 

## Motivation

The ORIGIN opcode in Ethereum returns the address of the account that started the transaction chain, differing from the SENDER (or CALLER) opcode, which returns the address of the direct caller. The use of ORIGIN has been discouraged and deemed deprecated since mid-2016 due to the security problems it introduces, such as susceptibility to phishing attacks and other vulnerabilities where the distinction between the original sender and the immediate sender can be exploited.

For instance, if an [ERC-4337](/EIPs/EIPS/eip-4337) bundler has tokens or other authority in a smart contract determined by ORIGIN, any of the transactions it bundles can hijack this authority since ORIGIN remains the bundler address throughout each child transaction.

More apropos in the current context of EVM evolution, the differentiation between the ORIGIN and SENDER opcodes presents a challenge for all account abstraction efforts, such as those outlined in [EIP-7377](/EIPs/EIPS/eip-7377) and [EIP-3074](/EIPs/EIPS/eip-3074), because any move towards account abstraction must address the ORIGIN opcode&apos;s role, either by modifying or completely bypassing it. Without addressing this, the ORIGIN opcode stands as a barrier to the evolution of Ethereum&apos;s account model towards greater flexibility and functionality.

## Specification

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

This EIP proposes the alteration of the behavior of the ORIGIN opcode within the Ethereum Virtual Machine (EVM). Currently, the ORIGIN opcode returns the address of the original transaction initiator. Under this EIP, the ORIGIN opcode would, instead, return the same value as the SENDER opcode, which is the address of the immediate sender of the message or transaction.

Definition Change: The ORIGIN opcode (0x32) MUST, in all contexts of execution, return the same value as that returned by the SENDER (also known as CALLER) opcode (0x33).

EVM Implementation: All Ethereum clients MUST implement the following change to the EVM: Whenever the ORIGIN opcode is called, the value to be pushed onto the stack is the current call&apos;s sender address, as if the SENDER opcode was executed instead.

Transaction Validation: Transactions MUST be validated as before, with no changes to the transaction structure or processing logic beyond the EVM opcode behavior specified above.

Compatibility: Smart contracts relying on the ORIGIN opcode for obtaining the transaction initiator&apos;s address MUST be reviewed to ensure they function correctly under the new definition and worked-around or avoided if this EIP introduces breaking changes.

Implementers are encouraged to provide feedback on this specification and report any potential issues encountered during the implementation or testing phases.

## Rationale

The rationale behind aliasing ORIGIN to SENDER is to:

Facilitate Account Abstraction: Elegantly nullify a universal barrier to account abstraction, enabling more flexible and powerful account models in Ethereum.

Enhance Security: Eliminate the security vulnerabilities associated with differentiating between the original transaction initiator and the immediate caller.

Clean up tech debt and simplify the EVM Model: Reduce the complexity of the EVM&apos;s transaction and execution model by removing an outdated and deprecated feature, making future changes easier and safer.

## Backwards Compatibility

This change is not fully backwards compatible. Contracts relying on the distinction between ORIGIN and SENDER for logic or security will be affected. However, given the longstanding discouragement of ORIGIN&apos;s use, the minimal impact of the change, the widespread desire for a future account abstraction solution in the EVM, and the reality that any AA solution will ultimately have to deal with ORIGIN one way or the other, this incompatibility is considered a necessary step forward for Ethereum&apos;s development.

No backward compatibility issues found.

## Test Cases

For each CALL, STATICCALL, DELEGATECALL, CALLCODE:

Direct - Ensure that, at the target smart contract, ORIGIN and SENDER produce the same value. (For simple no-hop EOA-to-EOA/SCA transactions, this is already the case today.)

Multi-hop - Ensure that, at each frame in a multi-hop transaction, ORIGIN and SENDER produce the same value.

## Security Considerations

By aliasing ORIGIN to SENDER, the specific security vulnerabilities associated with the ORIGIN opcode are addressed and eliminated. Outside the scope of this EIP, it may be wise to ban all use of ORIGIN to eliminate further misunderstanding or misuse. This can be done via tooling changes outside the EVM or, inside the EVM, reverting smart contract deployments that use ORIGIN.

For existing misuse of ORIGIN affected negatively by this aliasing to SENDER (of yet a clear example has yet to be identified), it may be necessary to educate users to avoid this problematic legacy code.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 03 Mar 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7645</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7645</guid>
      </item>
    
      <item>
        <title>Bonding curve-embedded liquidity for NFTs</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7649-bonding-curve-embedded-liquidity-for-erc-721-non-fungible-tokens-nfts/19079</comments>
        
        <description>## Abstract

This proposal introduces a standard for embedding Bonding Curve-like liquidity into
Non-Fungible Tokens (NFTs) without modifying the [ERC-721](/EIPs/EIPS/eip-721) standard.
The proposed standard allows the attachment of an embedded liquidity contract, referred to as Tradable Shares,
to an ERC-721 NFT. Tradable Shares leverage a Bonding Curve-like approach to attract liquidity, enabling trading of
shares based on the bonding curve price formula.

## Motivation

The ERC-721 standard lacks a specific mechanism for embedding bonding curve-based liquidity, limiting the creative
possibilities for NFT-based projects. This EIP addresses the need for a standardized approach to integrate bonding curve
contracts seamlessly into ERC-721 NFTs, allowing for diverse and innovative implementations without modifying the
ERC-721 standard.

The proposed standard focuses on enhancing the ERC-721 standard by introducing a framework for embedding bonding
curve-based liquidity into NFTs. This approach provides creators with a flexible and customizable tool to attract
liquidity through bonding curve mechanisms, while ensuring creators receive guaranteed fees for their contributions.

The bonding curve-embedded liquidity for NFTs standard finds compelling use cases across diverse industries, offering a
dynamic solution for embedding Bonding Curve-like liquidity into NFTs. One prominent use case revolves around the
intersection of AI services, where NFTs model AI models, GPU resource pools, and storage resource pools. Let&apos;s explore
two specific use cases within this domain:

1.  __AI Model Marketplace:__
    * NFTs representing AI models leverage the embedded liquidity standard to embed Bonding Curve-like liquidity.
      AI model providers attach Tradable Shares contracts to their NFTs, enabling a seamless integration of liquidity
      features without modifying the ERC-721 standard.
    * The Bonding Curve mechanism allows the pricing of shares (or keys) based on the AI model&apos;s supply and demand.
      As AI models gain popularity or demonstrate superior performance, liquidity providers are incentivized to buy and
      sell shares, fostering a competitive marketplace.
    * Creators can customize bonding curve parameters, such as slope and intercept, tailoring the liquidity mechanism to
      match the evolving nature of AI models. This ensures a fair and adaptive marketplace where liquidity providers are
      attracted to promising AI models, thereby creating a symbiotic relationship between liquidity and AI innovation.

2.  __Decentralized GPU and Storage Resource Allocation:__
    * In a decentralized ecosystem, GPU and storage resource pools are represented as NFTs with embedded Tradable Shares
      contracts. This enables resource providers to attract liquidity and compete for resource allocations based on the
      Bonding Curve mechanism.
    * The Bonding Curve determines the price of shares associated with GPU and storage resources, reflecting the current
      supply and demand. Providers can customize bonding curve parameters to optimize their resource pool&apos;s
      attractiveness, taking into account factors like available resources, performance metrics, and historical usage.
    * Guaranteed creative fees incentivize resource providers to continually enhance and optimize their services.
      As the demand for GPU and storage resources evolves, the embedded liquidity standard ensures that providers
      receive fair compensation for their contributions, maintaining a competitive and responsive marketplace.

In both use cases, the standard serves as a powerful incentive for providers to attract and retain liquidity.
The dynamic nature of the Bonding Curve-like mechanism aligns with the evolving landscape of AI models and resource
pools, fostering innovation, competition, and liquidity-driven growth within the decentralized AI services domain.

## Specification

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

1.  Bonding Curve-Embedded Liquidity / Tradable Shares:
    - An embedded bonding curve-based liquidity SHOULD be attached to the NFT via a separate contract.
    - An embedded bonding curve-based liquidity MUST NOT be embedded into or modify the ERC-721 standard.
    - The bonding curve contract MUST manage the liquidity of the associated NFT through a bonding curve mechanism.

2.  Bonding Curve Mechanism:
    - The bonding curve determines the price of the NFT &quot;keys&quot; (sometimes also referred to as &quot;shares&quot;) in relation to
      its supply, encouraging liquidity providers to buy and sell NFT shares based on the curve&apos;s formula.
    - Implementation MAY allow the creators to customize the bonding curve parameters, such as slope, intercept,
      or any other relevant parameters.
    - Implementation MAY allow the creators to customize the shape of the bonding curve (the curve&apos;s formula).

3.  Guaranteed Creative Fees:
    - The implementation MUST include the mechanisms that guarantee creative fees for NFT creators, that is
      it MUST guarantee the creators receive a percentage of transaction fees generated by the embedded liquidity
      contract during buy and sell operations.
    - The implementation MAY allow the creators to defne the transaction fees.

4.  Payment Mechanisms:
    - The embedded liquidity contract MUST support either [ERC-20](/EIPs/EIPS/eip-20) tokens or native ETH as a payment,
      it MAY support both.

### `BondingCurve` Interface

```
/**
 * @title Bonding Curve
 *
 * @notice A bonding curve definition
 *
 * @notice Bonding curve defines the price of the smallest unit of the asset as a function
 *      of the asset supply
 */
interface BondingCurve {
	/**
	 * @notice Bonding curve function definition. The function calculating the price
	 *      of the `amount` of shares given the current total supply `supply`
	 *
	 * @param supply total shares supply
	 * @param amount number of shares to buy/sell
	 * @return the price of the shares (all `amount` amount)
	 */
	function getPrice(uint256 supply, uint256 amount) external pure returns(uint256);
}
```

### Bonding Curve-Embedded Liquidity / `TradeableShares` Interface

```
/**
 * @title Tradeable Shares
 *
 * @notice Tradeable shares is a non-transferable, but buyable/sellable fungible token-like asset,
 *      which is sold/bought solely by the shares contract at the predefined by
 *      the bonding curve function price
 *
 * @notice The shares is bound to its &quot;subject&quot; – an NFT; the NFT owner gets the subject fee
 *      emerging in every buy/sell operation
 */
interface TradeableShares is BondingCurve {
	/**
	 * @notice Shares subject is an NFT defined by its ERC-721 contract address and NFT ID
	 *       Shares subject is an NFT the liquidity is embedded to
	 */
	struct SharesSubject {
		/// @dev ERC-721 contract address
		address tokenAddress;

		/// @dev NFT ID
		uint256 tokenId;
	}

	/**
	 * @dev Fired in `buyShares` and `sellShares` functions, this event logs
	 *      the entire trading activity happening on the curve
	 *
	 * @dev Trader, that is the buyer or seller, depending on the operation type is the transaction sender
	 *
	 * @param beneficiary the address which receives shares or funds, usually this is the trader itself
	 * @param issuer subject issuer, usually an owner of the NFT defined by the subject
	 * @param isBuy true if the event comes from the `buyShares` and represents the buy operation,
	 *      false if the event comes from the `sellShares` and represents the sell operation
	 * @param sharesAmount amount of the shares bought or sold (see `isBuy`)
	 * @param paidAmount amount of ETH spent or gained by the buyer or seller;
	 *      this is implementation dependent and can represent an amount of ERC-20 payment token
	 * @param feeAmount amount of all the fees paid, if any
	 * @param supply total shares supply after the operation
	 */
	event Trade(
		address indexed beneficiary,
		address indexed issuer,
		bool indexed isBuy,
		uint256 sharesAmount,
		uint256 paidAmount,
		uint256 feeAmount,
		uint256 supply
	);

	/**
	 * @notice Shares subject, usually defined as NFT (ERC-721 contract address + NFT ID)
	 *
	 * @dev Immutable, client applications may cache this value
	 *
	 * @return Shares subject as a SharesSubject struct, this is an NFT if all currently known implementations
	 */
	function getSharesSubject() external view returns(SharesSubject calldata);

	/**
	 * @notice Cumulative fee percent, applied to all the buy and sell operations;
	 *      the fee percent is defined with the 18 decimals, 10^18 corresponds to 100%
	 *
	 * @notice The fee can be combined from multiple fees which are sent to the various destinations
	 *
	 * @dev Immutable, client applications may cache this value
	 *
	 * @return protocol fee percent with the 18 decimals (10^18 is 100%)
	 */
	function getFeePercent() external view returns(uint256);

	/**
	 * @notice Shares issuer, the receiver of the shares fees
	 *
	 * @dev Mutable, changes (potentially frequently and unpredictably) when the NFT owner changes;
	 *      subject to the front-run attacks, off-chain client applications must not rely on this address
	 *      in anyway
	 *
	 * @return nftOwner subject issuer, the owner of the NFT
	 */
	function getSharesIssuer() external view returns(address nftOwner);

	/**
	 * @notice Shares balance of the given holder; this function is similar to ERC20.balanceOf()
	 *
	 * @param holder the address to check the balance for
	 *
	 * @return balance number of shares the holder has
	 */
	function getSharesBalance(address holder) external view returns(uint256 balance);

	/**
	 * @notice Total amount of the shares in existence, the sum of all individual shares balances;
	 *      this function is similar to ERC20.totalSupply()
	 *
	 * @return supply total shares supply
	 */
	function getSharesSupply() external view returns(uint256 supply);

	/**
	 * @notice The price of the `amount` of shares to buy calculated based on
	 *      the specified total shares supply
	 *
	 * @param supply total shares supply
	 * @param amount number of shares to buy
	 * @return the price of the shares to buy
	 */
	function getBuyPrice(uint256 supply, uint256 amount) external pure returns(uint256);

	/**
	 * @notice The price of the `amount` of shares to sell calculated based on
	 *      the specified total shares supply
	 *
	 * @param supply total shares supply
	 * @param amount number of shares to sell
	 * @return the price of the shares to sell
	 */
	function getSellPrice(uint256 supply, uint256 amount) external pure returns(uint256);

	/**
	 * @notice The price of the `amount` of shares to buy, including all fees;
	 *      calculated based on the specified total shares supply and fees percentages
	 *
	 * @param supply total shares supply
	 * @param amount number of shares to buy
	 * @param protocolFeePercent protocol fee percent
	 * @param holdersFeePercent shares holders fee percent
	 * @param subjectFeePercent protocol fee percent
	 * @return the price of the shares to buy
	 */
	function getBuyPriceAfterFee(
		uint256 supply,
		uint256 amount,
		uint256 protocolFeePercent,
		uint256 holdersFeePercent,
		uint256 subjectFeePercent
	) external pure returns(uint256);

	/**
	 * @notice The price of the `amount` of shares to sell, including all fees;
	 *      calculated based on the specified total shares supply and fees percentages
	 *
	 * @param supply total shares supply
	 * @param amount number of shares to sell
	 * @param protocolFeePercent protocol fee percent
	 * @param holdersFeePercent shares holders fee percent
	 * @param subjectFeePercent protocol fee percent
	 * @return the price of the shares to sell
	 */
	function getSellPriceAfterFee(
		uint256 supply,
		uint256 amount,
		uint256 protocolFeePercent,
		uint256 holdersFeePercent,
		uint256 subjectFeePercent
	) external pure returns(uint256);

	/**
	 * @notice Current price of the `amount` of shares to buy; calculated based on
	 *      the current total shares supply
	 *
	 * @param amount number of shares to buy
	 * @return the price of the shares to buy
	 */
	function getBuyPrice(uint256 amount) external view returns(uint256);

	/**
	 * @notice Current price of the `amount` of shares to sell; calculated based on
	 *      the current total shares supply
	 *
	 * @param amount number of shares to sell
	 * @return the price of the shares to sell
	 */
	function getSellPrice(uint256 amount) external view returns(uint256);

	/**
	 * @notice Current price of the `amount` of shares to buy, including all fees;
	 *      calculated based on the current total shares supply and fees percentages
	 *
	 * @param amount number of shares to buy
	 * @return the price of the shares to buy
	 */
	function getBuyPriceAfterFee(uint256 amount) external view returns(uint256);

	/**
	 * @notice Current price of the `amount` of shares to sell, including all fees;
	 *      calculated based on the current total shares supply and fees percentages
	 *
	 * @param amount number of shares to sell
	 * @return the price of the shares to sell
	 */
	function getSellPriceAfterFee(uint256 amount) external view returns(uint256);

	/**
	 * @notice Buy `amount` of shares. Sender has to supply `getBuyPriceAfterFee(amount)` ETH.
	 *      First share can be bought only by current subject issuer.
	 *
	 * @dev Depending on the implementation, ERC-20 token payment may be required instead of ETH.
	 *      In such a case, implementation must through if ETH is sent, effectively overriding
	 *      the function definition as non-payable
	 *
	 * @param amount amount of the shares to buy
	 */
	function buyShares(uint256 amount) external payable;

	/**
	 * @notice Buy `amount` of shares in the favor of the address specified (beneficiary).
	 *      Sender has to supply `getBuyPriceAfterFee(amount)` ETH.
	 *      First share can be bought only by current subject issuer.
	 *
	 * @dev Depending on the implementation, ERC-20 token payment may be required instead of ETH.
	 *      In such a case, implementation must through if ETH is sent, effectively overriding
	 *      the function definition as non-payable
	 *
	 * @param amount amount of the shares to buy
	 * @param beneficiary an address receiving the shares
	 */
	function buySharesTo(uint256 amount, address beneficiary) external payable;

	/**
	 * @notice Sell `amount` of shares. Sender gets `getSellPriceAfterFee(amount)` of ETH.
	 *      Last share cannot be sold.
	 *
	 * @dev Depending on the implementation, ERC-20 token may be payed instead of ETH.
	 *
	 * @param amount amount of the shares to sell
	 */
	function sellShares(uint256 amount) external;

	/**
	 * @notice Sell `amount` of shares in the favor of the address specified (beneficiary).
	 *      The beneficiary gets `getSellPriceAfterFee(amount)` of ETH.
	 *      Last share cannot be sold.
	 *
	 * @dev Depending on the implementation, ERC-20 token may be payed instead of ETH.
	 *
	 * @param amount amount of the shares to sell
	 * @param beneficiary an address receiving the funds from the sale
	 */
	function sellSharesTo(uint256 amount, address payable beneficiary) external;

	/**
	 * @notice Cumulative value of all trades; allows to derive cumulative fees paid
	 *
	 * @dev This value cannot decrease over time; it can increase or remain constant
	 *      if no trades are happening
	 *
	 * @return Sum of the modulo of all trading operations
	 */
	function getTradeVolume() external view returns(uint256);
```


## Rationale

The rationale behind the design choices for the embedded liquidity standard is deeply rooted in providing a robust and
versatile framework for embedding Bonding Curve-like liquidity into NFTs. The following key considerations have
influenced the technical decisions:

1.  **Bonding Curve-Embedded Liquidity / Tradable Shares Contract**:
    - **Seamless Integration**: The decision to allow an embedded bonding curve-based liquidity contract to be attached
        to an NFT without altering the ERC-721 standard stems from the desire for seamless integration.
        This approach ensures that NFT developers can enhance their creations with liquidity mechanisms without
        introducing complexities or requiring modifications to the widely adopted ERC-721 standard.

    - **Liquidity Management**: The bonding curve contract&apos;s role in managing liquidity through the bonding curve
        mechanism is essential. This design choice facilitates a dynamic and automated pricing model based on supply
        and demand, contributing to the overall liquidity and tradability of NFT shares.

2. **Bonding Curve Mechanism**:
    - **Dynamic Pricing**: The adoption of a bonding curve mechanism to determine the price of Tradable Shares aligns
        with the goal of encouraging liquidity providers to engage in buying and selling NFT shares.
        The dynamic pricing, influenced by the curve&apos;s formula, ensures that the market for Tradable Shares remains
        responsive to changing conditions.

    - **Customization for Creators**: The decision to allow creators to customize bonding curve parameters, such as
        slope and intercept, empowers them to tailor the liquidity mechanism to the unique needs and characteristics of
        their projects. This customization fosters creativity and innovation within the NFT space.

3. **Guaranteed Creative Fees**:
    - **Creator Incentives**: The emphasis on guaranteeing creative fees for NFT creators is foundational to sustaining
        a thriving ecosystem. By enabling creators to specify and receive a percentage of transaction fees, the standard
        aligns incentives and rewards creators for their contributions, fostering a sustainable and creator-friendly
        environment.

4. **Payment Mechanisms**:
    - **Developer Freedom**: The standard&apos;s implementation-agnostic approach is motivated by the desire to provide
        developers with the freedom to choose and design the most suitable liquidity mechanism for their NFT projects.
        Whether interacting with ERC-20 tokens or native ETH, this independence ensures that developers can make
        informed choices based on the specific requirements of their projects.

The rationale behind these design choices is to create a Tradable Shares standard that is not only technically sound but
also flexible, adaptable, and supportive of diverse and creative implementations within the ERC-721 ecosystem.

See also: Bonded Fungible Tokens (1671)

## Security Considerations

1.  Smart Contract Security: Implementations of smart contracts should undergo thorough security audits to ensure
    resistance against vulnerabilities and attacks.

2.  Creative Fee Handling: Mechanisms for handling and distributing creative fees should be secure and transparent to
    prevent any malicious activities.

3.  Compatibility: Developers should ensure compatibility with existing ERC-721 implementations, allowing for a smooth
    integration of the embedded liquidity standard.

4.  User Experience: Considerations should be made to maintain a positive user experience, avoiding complexities that
    may hinder the adoption of NFT projects utilizing embedded liquidity.

This security considerations section reflects the importance of anticipating and addressing potential security
challenges in the implementation, ensuring its robustness, compatibility, and user-friendly nature.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 28 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7649</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7649</guid>
      </item>
    
      <item>
        <title>Programmable access lists</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7650-programmable-access-lists/19159</comments>
        
        <description>## Abstract

We introduce a new precompiled contract named `prefetch`, which accepts an `accessList`.

The `accessList` specifies a list of addresses and local storage keys; these addresses and local storage keys are added into the `accessed_addresses` and `accessed_storage_keys` global sets (introduced in [EIP-2929](/EIPs/EIPS/eip-2929)). Similar to [EIP-2930](/EIPs/EIPS/eip-2930), prefetching data through this precompile incurs a gas charge, albeit at a reduced rate compared to accesses made outside of this list.

## Motivation

The primary goal of this EIP is to enhance EIP-2930 by enabling contracts to add access lists programmatically. The advantage of implementing this precompile within a contract is the sustained reduction in gas costs for data access operations, leveraging the concurrent computing and IOs that most nodes have.

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### Parameters

| Constant                      | Value |
| ----------------------------- | ----- |
| `FORK_BLOCK_NUMBER`                 | `TBD` |
| `PREFETCH_PRECOMPILE_ADDRESS` | `TBD` |
| `CONCURRENCY`                 | `TBD` |

As of `FORK_BLOCK_NUMBER`, a new precompile is deployed at `PREFETCH_PRECOMPILE_ADDRESS`.  The encoding of the precompile input is the following:

```text
[32 bytes for local storage key length n][n * 32 bytes local storage keys][32 bytes for address length m][m * 32 bytes addresses]
```

At the beginning of the call, we will charge `2100 * (N + CONCURRENCY - 1) // CONCURRENCY + 2600 * (M + CONCURRENCY - 1) // CONCURRENCY`, where `//` is the integer division operator, `N` is the number of local storage keys not in `accessed_storage_keys` global set, and `M` is the number of addresses not in `accessed_addresses` global set. The client should concurrently read the keys and addresses and put the keys and addresses into the `accessed_addresses` and `accessed_storage_keys` global sets.  The following read cost of the storage keys and addresses obeys `WARM_STORAGE_READ_COST` as defined in [EIP-2929](/EIPs/EIPS/eip-2929).


### Examples

Using UniswapV2 `swap()` function as an example:

```
    // this low-level function should be called from a contract which performs important safety checks
    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock {
        prefetch {
             token0.slot,
             token1.slot,
             reserve0.slot,
             price0CumulativeLast.slot,
             price1CumulativeLast.slot,
        } // add the storage keys `accessed_storage_keys`
        prefetch {
             token0,
             token1,
        } // add the contracts of token0 and token1 to `accessed_addresses`
        ...
    }
```

## Rationale

### Charging less for accesses in the access list

Similar to EIP-2930, we encourage contract developers to use the `prefetch` precompile as much as possible, especially assuming the nodes have some decent concurrent capabilities (e.g., some cores and IO bandwidth).

### Allowing duplicates

Similar to EIP-2930, we allow duplicates in the list to maximize simplicity.

### No storage keys for external contract

Unlike EIP-2930, the `prefetch` precompile only accepts local storage keys and addresses. Prefetching the data of the storage keys of external contracts assumes that the contract knows the storage layout of an external contract, which may not be a good practice. To better employ the concurrency of a node, the precompile may accept a list of static calls of external contracts together with the calldata.  This work may be done in the future EIP.

## Backwards Compatibility

If the EIP is not yet implemented, a contract calling the precompile should result in no operation.

## Security Considerations

No security considerations were found.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 10 Mar 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7650</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7650</guid>
      </item>
    
      <item>
        <title>Fractionally Represented Non-Fungible Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7651-fractionally-represented-non-fungible-token/19176</comments>
        
        <description>## Abstract

This proposal introduces a standard for fractionally represented non-fungible tokens, allowing NFTs to be managed and owned fractionally within a single contract. This approach enables NFTs to coexist with an underlying fungible representation seamlessly, enhancing liquidity and access without dividing the NFT itself, or requiring an explicit conversion step. The standard includes mechanisms for both fractional and whole token transfers, approvals, and event emissions. This specification draws from design in both [ERC-721](/EIPs/EIPS/eip-721) and [ERC-20](/EIPs/EIPS/eip-20), but is not fully compatible with either standard.

## Motivation

Fractional ownership of NFTs has historically relied on external protocols that manage division and reconstitution of individual NFTs into fractional representations. The approach of dividing specific NFTs results in fragmented liquidity of the total token supply, as the fractional representations of two NFTs are not equivalent and therefore must be traded separately. Additionally, this approach requires locking of fractionalized NFTs, preventing free transfer until they are reconstituted.

This standard offers a unified solution to fractional ownership, aiming to increase the liquidity and accessibility of NFTs without compromising transferability or flexibility.

## Specification

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

### Fractionally Represented Non-Fungible Token Interface

All [ERC-7651](/EIPs/EIPS/eip-7651) compliant contracts MUST implement the ERC-7651 and [ERC-165](/EIPs/EIPS/eip-165) interfaces.

Compliant contracts MUST emit fractional Approval or Transfer events on approval or transfer of tokens in fractional representation.

Compliant contracts MUST additionally emit non-fungible ApprovalForAll, Approval or Transfer on approval for all, approval, and transfer in non-fungible representation.

Note that this interface draws from similarly defined functions in the [ERC-721](/EIPs/EIPS/eip-721) and [ERC-20](/EIPs/EIPS/eip-20) standards, but is not fully backwards compatible with either.

```solidity
interface IERC7651 is IERC165 {
  /// @dev This emits when fractional representation approval for a given spender
  ///      is changed or reaffirmed.
  event FractionalApproval(address indexed owner, address indexed spender, uint256 value);

  /// @dev This emits when ownership of fractionally represented tokens changes
  ///      by any mechanism. This event emits when tokens are both created and destroyed,
  ///      ie. when from and to are assigned to the zero address respectively.
  event FractionalTransfer(address indexed from, address indexed to, uint256 amount);

  /// @dev This emits when an operator is enabled or disabled for an owner.
  ///      The operator can manage all NFTs of the owner.
  event ApprovalForAll(
    address indexed owner,
    address indexed operator,
    bool approved
  );

  /// @dev This emits when the approved spender is changed or reaffirmed for a given NFT.
  ///      A zero address emitted as spender implies that no addresses are approved for
  ///      this token.
  event NonFungibleApproval(
    address indexed owner,
    address indexed spender,
    uint256 indexed id
  );

  /// @dev This emits when ownership of any NFT changes by any mechanism.
  ///      This event emits when NFTs are both created and destroyed, ie. when
  ///      from and to are assigned to the zero address respectively.
  event NonFungibleTransfer(address indexed from, address indexed to, uint256 indexed id);

  /// @notice Decimal places in fractional representation
  /// @dev Decimals are used as a means of determining when balances or amounts
  ///      contain whole or purely fractional components
  /// @return Number of decimal places used in fractional representation
  function decimals() external view returns (uint8 decimals);

  /// @notice The total supply of a token in fractional representation
  /// @dev The total supply of NFTs may be recovered by computing
  ///      `totalSupply() / 10 ** decimals()`
  /// @return Total supply of the token in fractional representation
  function totalSupply() external view returns (uint256 totalSupply);

  /// @notice Balance of a given address in fractional representation
  /// @dev The total supply of NFTs may be recovered by computing
  ///      `totalSupply() / 10 ** decimals()`
  /// @param owner_ The address that owns the tokens
  /// @return Balance of a given address in fractional representation
  function balanceOf(address owner_) external view returns (uint256 balance);

  /// @notice Query if an address is an authorized operator for another address
  /// @param owner_ The address that owns the NFTs
  /// @param operator_ The address being checked for approval to act on behalf of the owner
  /// @return True if `operator_` is an approved operator for `owner_`, false otherwise
  function isApprovedForAll(
    address owner_,
    address operator_
  ) external view returns (bool isApproved);

  /// @notice Query the allowed amount an address can spend for another address
  /// @param owner_ The address that owns tokens in fractional representation
  /// @param spender_ The address being checked for allowance to spend on behalf of the owner
  /// @return The amount of tokens `spender_` is approved to spend on behalf of `owner_`
  function allowance(
    address owner_,
    address spender_
  ) external view returns (uint256 allowance);

  /// @notice Query the owner of a specific NFT.
  /// @dev Tokens owned by the zero address are considered invalid and should revert on
  ///      ownership query.
  /// @param id_ The unique identifier for an NFT.
  /// @return The address of the token&apos;s owner.
  function ownerOf(uint256 id_) external view returns (address owner);

  /// @notice Set approval for an address to spend a fractional amount,
  ///         or to spend a specific NFT.
  /// @dev There must be no overlap between valid ids and fractional values.
  /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized
  ///      operator of the current owner if an id is provided.
  /// @dev Throws if the id is not a valid NFT
  /// @param spender_ The spender of a given token or value.
  /// @param amountOrId_ A fractional value or id to approve.
  /// @return Whether the approval operation was successful or not.
  function approve(
    address spender_,
    uint256 amountOrId_
  ) external returns (bool success);

  /// @notice Set approval for a third party to manage all of the callers
  ///         non-fungible assets
  /// @param operator_ Address to add to the callers authorized operator set
  /// @param approved_ True if the operator is approved, false if not approved
  function setApprovalForAll(address operator_, bool approved_) external;

  /// @notice Transfer fractional tokens or an NFT from one address to another
  /// @dev There must be no overlap between valid ids and fractional values
  /// @dev The operation should revert if the caller is not `from_` or is not approved
  ///      to spent the tokens or NFT owned by `from_`
  /// @dev The operation should revert if value is less than the balance of `from_` or
  ///      if the NFT is not owned by `from_`
  /// @dev Throws if the id is not a valid NFT
  /// @param from_ The address to transfer fractional tokens or an NFT from
  /// @param to_ The address to transfer fractional tokens or an NFT to
  /// @param amountOrId_ The fractional value or a distinct NFT id to transfer
  /// @return True if the operation was successful
  function transferFrom(
    address from_,
    address to_,
    uint256 amountOrId_
  ) external returns (bool success);

  /// @notice Transfer fractional tokens from one address to another
  /// @dev The operation should revert if amount is less than the balance of `from_`
  /// @param to_ The address to transfer fractional tokens to
  /// @param amount_ The fractional value to transfer
  /// @return True if the operation was successful
  function transfer(address to_, uint256 amount_) external returns (bool success);

  /// @notice Transfers the ownership of an NFT from one address to another address
  /// @dev Throws unless `msg.sender` is the current owner, an authorized
  ///      operator, or the approved address for this NFT
  /// @dev Throws if `from_` is not the current owner
  /// @dev Throws if `to_` is the zero address
  /// @dev Throws if `tokenId_` is not a valid NFT
  /// @dev When transfer is complete, this function checks if `to_` is a
  ///      smart contract (code size &gt; 0). If so, it calls `onERC721Received`
  ///      on `to_` and throws if the return value is not
  ///      `bytes4(keccak256(&quot;onERC721Received(address,uint256,bytes)&quot;))`.
  /// @param from_ The address to transfer the NFT from
  /// @param to_ The address to transfer the NFT to
  /// @param tokenId_ The NFT to transfer
  /// @param data_ Additional data with no specified format, sent in call to `to_`
  function safeTransferFrom(
    address from_,
    address to_,
    uint256 id_,
    bytes calldata data_
  ) external;

  /// @notice Transfers the ownership of an NFT from one address to another address
  /// @dev This is identical to the above function safeTransferFrom interface
  ///      though must pass empty bytes as data to `to_`
  /// @param from_ The address to transfer the NFT from
  /// @param to_ The address to transfer the NFT to
  /// @param tokenId_ The NFT to transfer
  function safeTransferFrom(address from_, address to_, uint256 id_) external;
}

interface IERC165 {
    /// @notice Query if a contract implements an interface
    /// @param interfaceID_ The interface identifier, as specified in ERC-165
    /// @dev Interface identification is specified in ERC-165. This function
    ///      uses less than 30,000 gas.
    /// @return `true` if the contract implements `interfaceID` and
    ///         `interfaceID` is not 0xffffffff, `false` otherwise
    function supportsInterface(bytes4 interfaceID_) external view returns (bool);
}
```

### Fractionally Represented Non-Fungible Token Metadata Interface

This is a RECOMMENDED interface, identical in definition to the [ERC-721](/EIPs/EIPS/eip-721) Metadata Interface. Rather than using this interface directly, a distinct metadata interface should be used here to avoid confusion surrounding ERC-721 inheritance. Given function definitions here are identical, it&apos;s important to note that the ERC-165 `interfaceId` will be identical between metadata interfaces for this specification and that of ERC-721.

```solidity
/// @title ERC-7651 Fractional Non-Fungible Token Standard, optional metadata extension
interface IERC7651Metadata {
  /// @notice A descriptive, long-form name for a given token collection
  function name() external view returns (string memory name);

  /// @notice An abbreviated, short-form name for a given token collection
  function symbol() external view returns (string memory symbol);

  /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
  /// @dev Throws if `tokenId_` is not a valid NFT. URIs are defined in RFC
  ///      3986. The URI may point to a JSON file that conforms to the &quot;ERC721
  ///      Metadata JSON Schema&quot;.
  /// @param id_ The NFT to fetch a token URI for
  /// @return The token&apos;s URI as a string
  function tokenURI(uint256 id_) external view returns (string memory uri);
}
```

### Fractionally Represented Non-Fungible Token Banking Interface

This is a RECOMMENDED interface that is intended to be used by implementations of [ERC-7651](/EIPs/EIPS/eip-7651) that implement NFT ID reuse.

```solidity
interface IERC7651NFTBanking {
  /// @notice Get the number of NFTs that have been minted but are not currently owned.
  /// @dev This should be the number of unowned NFTs, limited by the total
  ///      fractional supply.
  /// @return The number of NFTs not currently owned.
  function getBankedNFTsLength() external view returns (uint256 bankedNFTsLength);

  /// @notice Get a paginated list of NFTs that have been minted but are not currently owned.
  /// @param start_ Start index in bank.
  /// @param count_ Number of tokens to return from start index, inclusive.
  /// @return An array of banked NFTs from `start_`, of maximum length `count_`.
  function getBankedNFTs(
    uint256 start_,
    uint256 count_
  ) external view returns (uint256[] memory bankedNFTs);

  /// @notice Query the current supply of NFTs in circulation.
  /// @dev Given supply may remain banked or unminted, this function should always be
  ///      inclusively upper-bounded by `totalSupply() / 10 ** decimals()`.
  /// @return The current supply of minted NFTs
  function totalNonFungibleSupply() external view returns (unit256);
}
```

### Fractionally Represented Non-Fungible Token Transfer Exemptable Interface

This is a RECOMMENDED interface that is intended to be used by implementations of [ERC-7651](/EIPs/EIPS/eip-7651) that want to allow users to opt-out of NFT transfers.

```solidity
interface IERC7651NFTTransferExemptable {
  /// @notice Returns whether an address is NFT transfer exempt.
  /// @param account_ The address to check.
  /// @return Whether the address is NFT transfer exempt.
  isNFTTransferExempt(address account_) external view returns (bool);

  /// @notice Allows an address to set themselves as NFT transfer exempt.
  /// @param isExempt_ The flag, true being exempt and false being non-exempt.
  setSelfNFTTransferExempt(bool isExempt_) external;
}
```

## Rationale

This standard unifies the representation of fractional ownership with the non-fungible token model, aligning closely with [ERC-721](/EIPs/EIPS/eip-721) principles while enabling the functionality of [ERC-20](/EIPs/EIPS/eip-20) transfers. This dual compatibility aims to mitigate the integration complexity for existing protocols. Our goal is to implicitly support as high a degree of backwards compatibility with ERC-20 and ERC-721 standards as possible to reduce or negate integration lift for existing protocols. The core rationale for this fractional NFT standard centers on two main strategies: first, designing interfaces that clearly align with either ERC-721 or ERC-20 standards to avoid ambiguity; and second, detailing implementation approaches that distinctly separate the logic of overlapping functionalities.

### ID &amp; Amount Isolation

Ensuring clear differentiation between token IDs and fractional amounts is central to this design. This non-overlapping design principle means that no input should be ambiguously interpreted as both an ID and an amount. We won&apos;t dive into implementation guidelines, but implementations may achieve this through various means, such as validating ownership for ID inputs or reserving specific ranges for token IDs.

This approach ensures that logic in &quot;overlapping&quot; interfaces is similarly isolated, such that the chance of an unexpected outcome is minimized.

### Events

The overlap of event signatures between the [ERC-20](/EIPs/EIPS/eip-20) and [ERC-721](/EIPs/EIPS/eip-721) standards presents a challenge for backward compatibility in our fractional NFT standard. Various approaches have been explored, including aligning with a single standard&apos;s events or introducing unique events with distinct parameter indexing to resolve conflicts.

We feel that when moving towards standardization, ensuring events are properly descriptive and isolated is the ideal solution despite introducing complexity for indexing software. As a result, we adhere to traditional transfer and approval event definitions, though distinguish these events by the `Fractional` or `NonFungible` prefixes.

### Transfers

In a standard [ERC-7651](/EIPs/EIPS/eip-7651) transfer, value can be transferred by specifying either a fractional amount or a specific NFT ID.

NFT ID Transfers: Transferring by NFT ID is straightforward. The specified NFT, along with its entire associated fractional value (equivalent to 10 \*\* decimals()), is transferred from the sender to the recipient.

Fractional Amount Transfers: Transferring fractional amounts introduces complexity in managing NFT allocations. There are three main scenarios:

1. No change in whole token balance: If the transfer does not change the overall balance of either party, NFT allocations remain unchanged.
2. Sender&apos;s whole token balance decreases: If the sender&apos;s overall balance decreases below the nearest whole number, a proportionate number of NFTs must be removed from their holdings.
3. Receiver&apos;s whole token balance increases: Conversely, if the receiver&apos;s overall balance increases above the nearest whole number, their NFT holdings must be proportionately increased.

While [ERC-7651](/EIPs/EIPS/eip-7651) provides a broad framework for fractional NFTs, it does not prescribe specific methods for handling these scenarios. Common practices include monotonically minting or burning tokens to reflect changes, or tracking NFT ownership with a stack or queue during transfers of fractional amounts.

### NFT Transfer Exemption

Transferring fractional amounts means that a large number of NFTs can be moved in a single transaction, which can be costly in gas usage. We recommend an optional opt-in mechanism for exemption from NFT transfers that both EOAs and contracts can use to reduce the gas burden of transferring large token amounts when the NFT representation is not needed.

When executing the function call to either opt-in or opt-out of NFT transfers, NFTs held by the address will be directionally rebalanced to ensure they stay in sync with the new exemption status. In other words, when opting-out of NFT transfers, an address&apos;s NFTs will be banked and their NFT balance set to 0. When opting-in to NFT transfers, sufficient NFTs will be pulled from the bank and transferred to the address to match their fractional token balance.

### NFT Banking

As discussed in the Transfers section, when an address newly gains a full token in fractional terms, they are consequently owed an NFT. Similarly, when an address drops below a full token in fractional terms an NFT must be removed from their balance to stay in sync with their fractional balance.

The NFT banking mechanism provides a space in which un-owned but available NFTs relative to supply are tracked. We remain unopinionated on implementation here, but want to provide a handful of examples that would fit specification.

One approach to reconcile the bank is by monotonically burning and minting NFT IDs as they are pulled from and added back to circulation, respectively. The minting portion of this strategy can incur significant gas costs that are generally not made up for by the slight gas refund of deleting storage space for burnt token IDs. This approach additionally introduces inflexibility for collections that desire a persistent, finite ID space.

An alternate implementation of [ERC-7651](/EIPs/EIPS/eip-7651) includes a mechanism to store and reuse IDs rather than repeatedly burning and minting them. This saves significant gas costs, and has the added benefit of providing a predictable and externally readable stream of token IDs that can be held in a queue, stack or other data structure for later reuse. The specific data structure used for this banking mechanism is immaterial and is left at the discretion of any implementations adhering to the standard.

### ERC-165 Interface

We include the [ERC-165](/EIPs/EIPS/eip-165) interface in specification both to adhere to [ERC-721](/EIPs/EIPS/eip-721) design philosophy, and as a means of exposing interfaces at the contract level. We see this as a valuable, accepted standard to adhere to such that integrating applications may identify underlying specification.

Note that [ERC-7651](/EIPs/EIPS/eip-7651) contracts should not make any claim through `supportsInterface` to support [ERC-721](/EIPs/EIPS/eip-721) or [ERC-20](/EIPs/EIPS/eip-20) standards as, despite strong backwards compatibility efforts, these contracts cannot fully adhere to existing specifications.

### Metadata

In-line with [ERC-721](/EIPs/EIPS/eip-721), we&apos;ve decided to isolate replicated metadata functionality through a separate interface. This interface includes traditional naming and token URI logic, though also introduces patterns surrounding token banking visibility, as outlined above in both the NFT Banking and Transfer Logic sections.

## Backwards Compatibility

The fractional non-fungible token standard aims to be nearly backwards compatible with existing [ERC-721](/EIPs/EIPS/eip-721) and [ERC-20](/EIPs/EIPS/eip-20) standards, though makes no claim to fully adhere to either and has as such been proposed through a distinct interface.

### Events

Events in [ERC-721](/EIPs/EIPS/eip-721) and [ERC-20](/EIPs/EIPS/eip-20) specifications share conflicting signatures on approval and transfer, meaning an adherent hybrid of the two cannot be achieved.

This is one of the few areas where backwards compatibility has been intentionally broken, resulting in a new series of events with either a `Fractional` or `NonFungible` prefix. We believe that a decisive move to a non-conflicting, descriptive solution is ideal here, though will require external lift for indexing software.

### balanceOf

The `balanceOf` function as defined in both [ERC-20](/EIPs/EIPS/eip-20) and [ERC-721](/EIPs/EIPS/eip-721) standards varies, in practice, to represent either fractional or whole token ownership respectively. Given fractional non-fungible tokens should adhere to an underlying fractional representation, it follows that this function should return a balance in that representation. This does, however, imply that fractional NFT contracts cannot fully adhere to the `balanceOf` specification provided by ERC-721.

### Success Return Values

The `transfer` and `approve` functions both return a boolean value indicating success or failure. This is non-standard for the [ERC-721](/EIPs/EIPS/eip-721) specification, though is standard for [ERC-20](/EIPs/EIPS/eip-20). Fractional non-fungible tokens adhere to a returned boolean value to meet minimum expectations for the ERC-20 standard, acknowledging that this deviates from a state of ideal backwards compatibility.

## Security Considerations

### Interface Misinterpretation

This section is placeholder for further discussion surrounding the misidentification of [ERC-7651](/EIPs/EIPS/eip-7651) as being either ERC-20 or ERC-721. Namely, discussion surrounding potential security implications of interface misinterpretation need to be thoroughly considered.

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 05 Mar 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7651</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7651</guid>
      </item>
    
      <item>
        <title>ERC-721 Guarantee Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7652-eip-721-guarantee-extension/19284</comments>
        
        <description>## Abstract

This specification defines functions outlining a guarantor role for instance of [EIP-721](/EIPs/EIPS/eip-721). The guarantee interface implements the user-set valuation and guarantee share for a given NFT (token ID), as well as the guarantee rights enjoyed and obligations assumed during subsequent transactions. An implementation enables the user to read or set the current guarantee value for a given NFT (token ID), and also realizes the distribution of guarantee interest and the performance of guarantee obligations. It sends the standardized events when the status changes. This proposal relies on and extends the existing [EIP-721](/EIPs/EIPS/eip-721).

## Motivation

NFT (token ID) commonly face the issue of insufficient market liquidity: the main reason being the lack of transparency in NFT pricing, making it difficult for users to cash out after trading and purchasing NFT (token ID).

With the introduction of the guarantor role, different guarantor groups can offer various price guarantees for NFT (token ID), establishing a multi-faceted price evaluation system for NFT (token ID).

After purchasing an NFT (token ID), users can return it to the guarantor at any time at the highest guaranteed price to protect their interests.

Additionally, after fulfilling their guarantee obligations, the guarantor can also request subsequent guarantors to provide guarantee obligations.

When an NFT (token ID) is owned by the guarantor, and since the guarantor can be a DAO organization, this expansion allows the NFT (token ID) to continue operating as a DAO, thus further enhancing the social or community recognition of the NFT (token ID).


## Specification

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.

Every contract compliant to the `ERC721Guarantee` MUST implement the `IERC721Guarantee` guarantee interface.

The **guarantee extension**  is OPTIONAL for EIP-721 contracts.

```solidity
pragma solidity ^0.8.20;

// import {IERC721} from &quot;@openzeppelin/contracts/token/ERC721/IERC721.sol&quot;;

/// @title EIP-721 Guarantor Role extension
///  Note: the EIP-165 identifier for this interface is


interface IERC721Guarantee /*is IERC721*/{
    /// @notice           Emitted when `guarantee contract` is established for an NFT
    /// @param user       address of  guarantor
    /// @param value      The guarantee value provided by dao
    /// @param DAO        DAO organization providing guarantee
    /// @param tokenId    Guaranteed NFT (token ID),
    event GuaranteeIsEstablshed(
        address user,
        uint256 value,
        address DAO,
        uint256 indexed tokenId
    );

    /// @notice           Emitted when `guarantee contract` is canceled
    /// @dev              Some users in the closed DAO request a reduction in their guarantee share
    /// @param user       address of  guarantor
    /// @param value      The guarantee value provided by dao
    /// @param DAO        DAO organization providing guarantee
    /// @param tokenId    Guaranteed NFT (token ID),
    event GuaranteeIsCancel(
        address user,
        uint256 value,
        address DAO,
        uint256 indexed tokenId
    );

    /// @notice           Emitted when `Guarantee sequence` is established for an NFT
    /// @param userGuaranteed      address of guaranteed
    /// @param number  block.number of transaction,
    ///                and all DAOs established before this point will enter the guarantee sequence
    /// @param DAOs   DAO sequence providing guarantee
    /// @param tokenId Guaranteed NFT (token ID),
    event GuaranteeSequenceIsEstablshed(
        address userGuaranteed,
        uint256 number,
        address DAOs,
        uint256 indexed tokenId
    );

    /// @notice   A user&apos;s evaluation for an NFT (token ID)
    /// @dev      Set the guarantee information for one guarantor,
    /// Throws if `_tokenId` is not a valid NFT
    /// @param value  user&apos;s evaluation for  an NFT, the oledr value is canceled,
    /// @param user   address of guarantor
    /// @param weight guarantee weight for guarantor
    /// @param tokenId The NFT
    /// @return the error status of function execution
    function setNFTGuarantedInfo(
        uint256 value,
        address user,
        uint256 weight,
        uint256 tokenId
    ) external returns (uint256);

    /// @notice   Establish guarantee sequence for an NFT (token ID) and split the commission
    /// @dev      Each NFT(token ID) retains a current guarantee sequence,
    ///           and expired guarantee sequences are no longer valid,
    ///           Throws if `_tokenId` is not a valid NFT
    /// @param valueCommission Commission for a transactions
    /// @param userGuaranteed   address of guaranteed
    /// @param number  block.number of transaction,
    ///              and all DAOs established before this point will enter the guarantee sequence
    /// @param tokenId The NFT
    /// @return the error status of function execution
    function establishNFTGuarantee(
        uint256 valueCommission,
        address userGuaranteed,
        uint256 number,
        uint256 tokenId
    ) external returns (uint256);

    /// @notice   Transactions that fulfill the guarantee responsibility
    /// @dev      The new accountability transaction also requires
    ///           the construction of a new guarantee sequence
    ///           Throws if `_tokenId` is not a valid NFT or userGuaranteed is not right

    /// @param  userGuaranteed   address of guaranteed
    /// @param  tokenId The NFT
    /// @return the error status of function execution
    function FulfillGuaranteeTransfer(address userGuaranteed, uint256 tokenId)
        external
        returns (uint256);
}

```

## Rationale

Key factors influencing the standard:

- Pay attention to ensuring fairness between and within groups when allocating commissions
- Keeping the number of guarantee groups (DAOs)in the interfaces to prevent contract bloat
- The guarantee group is a DAO contract, which MUST implement the `ERC721TokenReceiver` interface
- Simplicity
- Gas Efficiency


## Backwards Compatibility

This standard is compatible with current EIP-721 standards. There are no other standards that define a similar role for NFTs and the name (Guarantor) is not used by other EIP-721 related standards.


## Reference Implementation

The reference implementation will be provided later.

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 10 Mar 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7652</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7652</guid>
      </item>
    
      <item>
        <title>Request Method Types</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7654-request-method-types/19183</comments>
        
        <description>## Abstract  

This proposal standardizes a set of request and response communication standards between clients and smart contracts, using POST, GET, and PUT requests to create, read, and update the states of smart contracts. You can customize different request method names, request parameters and response values, and each request method will be mapped to a specific operation.

## Motivation   

Since each contract has different functions, the client cannot use a standard to call different functions of different contracts. Contract Request Methods redefines the request method of the contract, so that different functions of multiple different contracts can be called using a consistent set of rules and protocols.

By dividing the function types into POST, GET, and PUT, different operations can be performed on the contract. This clear operation type can not only help all parties limit the access and operation of contract data, but also effectively simplify the interaction between the client and the contract, making it easier for all parties to understand the functions and hierarchical structure of the contract. The request and response parameter data types of each function of this standard can express the expected operation of the contract and have the ability to describe its own structure, which is conducive to the parties and contracts to create a unified and predictable way of exchanging data.

## Specification

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

It consists of four request method types:

**GET**: Request the contract to retrieve records.

**POST**: Request the contract to create a new record.

**PUT**: Request the contract to update a record.

**OPTIONS**: Supported request method types.

Workflow:  

1. Call ```options``` to obtain supported request method types.
2. Call ```getMethods``` to obtain the request method name.
3. Call ```getMethodInstruction``` to obtain the request method instruction.
4. Call ```getMethodReqAndRes``` to obtain the request parameter data type and response value data type.
5. Encode request parameters and call ```get```, ```post```, and ```put```.
6. Decode response value.

### Interfaces

#### `IRequestMethodTypes.sol`

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity &gt;=0.8.0;
import &quot;./Types.sol&quot;;
interface IRequestMethodTypes{

    /**
     * Requested method type.
     * GET, POST, PUT, OPTIONS
     */
    enum MethodTypes{
        GET,
        POST,
        PUT,
        OPTIONS
    }

    /**
     * Response data event.
     * @param _response is the response value of the post request or put request.
     */
    event Response(bytes _response);

    /**
     * Get method names based on request method type.
     * @param _methodTypes is the request method type.
     * @return Method names.
     */
    function getMethods(MethodTypes _methodTypes)external view returns (string[] memory);

    /**
     * Get the data types of request parameters and return parameters based on the requested method name.
     * @param _methodName is the method name.
     * @return Data types of request parameters and return parameters.
     */
    function getMethodReqAndRes(string memory _methodName) external view returns(Types.Type[] memory ,Types.Type[] memory );

    /**
     * Get the instruction of method based on the requested method name.
     * @param _methodName is the method name.
     * @return instruction
     */    
    function getMethodInstruction(string memory _methodName) external view returns(string memory);

    /**
     * Request the contract to retrieve records.
     * @param _methodName is the method name.
     * @param _methodReq is the method type.
     * @return The response to the get request.
     */
    function get(string memory _methodName,bytes memory _methodReq)external view returns(bytes memory);

    /**
     * Request the contract to create a new record.
     * @param _methodName is the method name.
     * @param _methodReq is the method type.
     * @return The response to the post request.
     */
    function post(string memory _methodName,bytes memory _methodReq)external payable returns(bytes memory);

    /**
     * Request the contract to update a record.
     * @param _methodName is the method name.
     * @param _methodReq is the method type.
     * @return The response to the put request.
     */
    function put(string memory _methodName,bytes memory _methodReq)external payable returns(bytes memory);

    /**
     * Supported request method types.
     * @return Method types.
     */
    function options()external returns(MethodTypes[] memory);
}

```

### Library

The library [`Types.sol`](/EIPs/assets/eip-7654/Types.sol) contains an enumeration of Solidity types used in the above interfaces.

## Rationale

### Type of request method 

In order to enable the client to operate the contract in a standardized and predictable way, three request method types ```GET```, ```POST```, and ```PUT``` are set. The functions of each need to be defined in these three types to facilitate the contract caller to understand and process the information required for the request. However, there is no ```DELETE``` operation type because deleting data in the contract is an inefficient operation. Developers can add a ```PUT``` request method by themselves to set the data to be valid and invalid, and only return valid data in the ```GET``` method.

### Request method parameter type 

Some functions are defined in each request method type. They all include request parameter data type and response parameter data type, which need to be set in the ```constructor``` and then obtained according to the method name through ```getMethodReqAndRes```. The data type of the parameter is defined by the enumeration of the data type. When processing the request parameter, ```abi.decode``` is used to decode according to the request parameter type and the request value. When returning the response, ```abi.encode``` is used to encode according to the response value and the response parameter type. In addition, we can get the method usage instructions by calling ```getMethodInstruction```.   

## Reference Implementation

See [Request Method Types Example](/EIPs/assets/eip-7654/RequestMethodTypes.sol)

## Security Considerations

Contract request methods are divided into safe methods and unsafe methods. If the method request is a read-only operation and will not change the state of the contract, then the method is safe.

**Safe Methods:** GET, OPTIONS  
**Unsafe Methods:** POST, PUT

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Wed, 13 Mar 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7654</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7654</guid>
      </item>
    
      <item>
        <title>Generalized Contract-Linked Services</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/variation-to-erc6551-to-deploy-any-kind-of-contract-linked-to-an-nft/19223</comments>
        
        <description>## Abstract

This proposal defines a factory capable of deploying generic services linked to specific contracts, such as [ERC-4337](/EIPs/EIPS/eip-4337) accounts or [ERC-721](/EIPs/EIPS/eip-721) tokens (NFTs). These linked services extend the functionalities of the target contract, operating under the ownership of the contract&apos;s or NFT&apos;s owner without requiring modifications to the original contract&apos;s code. This approach enables extending existing contracts with new capabilities while maintaining backward compatibility with deployed instances.

## Motivation

Existing projects, like token-bound accounts, successfully bind smart accounts to NFTs, allowing registries to deploy accounts owned by specific token IDs. However, these standards have two key limitations:

1. They often require deployed contracts to implement specific interfaces for handling assets and executing transactions, effectively mandating that the deployed contract must function as an account.
2. They are restricted to NFTs, while many other contract types (particularly [ERC-4337](/EIPs/EIPS/eip-4337) accounts) could benefit from similar linking mechanisms to extend their functionalities.

This ERC proposes a more versatile factory specification that enables the deployment of proxies pointing to any contract that enhances the associated contract&apos;s capabilities, whether it&apos;s an NFT or an account contract.

### Key Benefits

- **Universal Linkability**: Enables services to be linked to any compatible contract type, not just NFTs, creating a unified approach to contract extension.

- **Non-Invasive Enhancement**: Services can add functionality to existing smart accounts without modifying the underlying contract, maintaining compatibility with infrastructure like wallets and indexers.

- **Backward Compatibility**: Maintains compatibility with existing token-bound accounts while extending functionality to new use cases.

- **Flexible Implementation**: The `mode` parameter enables different linkage types (with or without token IDs) while ensuring consistent deterministic addressing.

- **Unified Extension Mechanism**: Provides a standardized approach for extending existing contracts with new capabilities, reducing the need for specialized implementations across different use cases.


### Use Cases for ERC-4337 Smart Accounts

1. **Social Recovery Services**: Deploy a social recovery mechanism linked to an existing ERC-4337 wallet that can restore access if credentials are lost, without requiring the wallet to implement recovery functionality natively.

2. **Customizable Permission Systems**: Add granular permissions to an account (time-limited access, spending limits, multi-signature approvals) without rebuilding the account from scratch.

3. **Account Abstraction Extensions**: Implement advanced features like batch transactions, gas sponsorship, or session keys as linked services, allowing wallets to adopt these features selectively.

4. **Identity and Reputation Services**: Link verifiable credentials or reputation systems to accounts, enabling privacy-preserving identity verification.

### Use Cases for NFTs

1. **Enhanced Token Utility**: Provide NFTs with financial capabilities like staking, lending, or revenue distribution.

2. **Dynamic Metadata Services**: Enable NFT metadata to evolve based on on-chain activities without changing the NFT itself.

3. **Fractional Ownership**: Implement fractional ownership mechanisms for high-value NFTs through linked contracts.

4. **Conditional Access Control**: Create time-locked or challenge-based access to NFT-gated content or services.

5. **Real World Asset Management**: Extend NFTs to represent and manage real-world assets (RWAs) by linking services that handle compliance, legal documentation, custody verification, transfer restrictions, and regulatory reporting without requiring specialized NFT standards for each asset class.

## Specification

The keywords &quot;MUST,&quot; &quot;MUST NOT,&quot; &quot;REQUIRED,&quot; &quot;SHALL,&quot; &quot;SHALL NOT,&quot; &quot;SHOULD,&quot; &quot;SHOULD NOT,&quot; &quot;RECOMMENDED,&quot; &quot;NOT RECOMMENDED,&quot; &quot;MAY,&quot; and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119 and RFC 8174.

The `IERC7656Factory` interface is defined as follows:

```solidity

interface IERC7656Factory {
  event Created(
    address contractAddress,
    address indexed implementation,
    bytes32 salt,
    uint256 chainId,
    bytes12 mode,
    address indexed linkedContract,
    uint256 indexed linkedId
  );

  error CreationFailed();

  function create(
    address implementation,
    bytes32 salt,
    uint256 chainId,
    bytes12 mode,
    address linkedContract,
    uint256 linkedId
  ) external returns (address);

  function compute(
    address implementation,
    bytes32 salt,
    uint256 chainId,
    bytes12 mode,
    address linkedContract,
    uint256 linkedId
  ) external view returns (address service);
}
```

### Linking Modes

The `mode` parameter serves as a selector for how the linked contract should be interpreted and utilized. Currently, [ERC-7656](/EIPs/EIPS/eip-7656) defines two standard modes:

```solidity
bytes12 constant NO_LINKED_ID = 0x000000000000000000000001;
bytes12 constant LINKED_ID = 0x000000000000000000000000;
```

- **LINKED_ID Mode (0x000000000000000000000000)**: Used when linking a service to an NFT or any contract that requires a token/entity ID. This mode ensures compatibility with existing token-bound account systems.

- **NO_LINKED_ID Mode (0x000000000000000000000001)**: Used when linking a service to a contract that doesn&apos;t require an ID parameter, such as an [ERC-4337](/EIPs/EIPS/eip-4337) account. In this case, the `linkedId` parameter is still present in the interface for consistency but SHOULD be set to zero if not used to store alternative data relevant to the service.

The `mode` parameter (being `bytes12`) allows for future extensions beyond these initial modes, enabling more complex linkage patterns as ecosystem needs evolve.

### Deployment Requirements

Any `ERC7656Factory` implementation MUST support the `IERC7656Factory` interface ID (`0x9e23230a`).

Each linked service MUST be deployed as an [ERC-1167](/EIPs/EIPS/eip-1167) minimal proxy, appending immutable constant data to the bytecode. The deployed bytecode structure is:

```
ERC-1167 Header               (10 bytes)
&lt;implementation (address)&gt;    (20 bytes)
ERC-1167 Footer               (15 bytes)
&lt;salt (bytes32)&gt;              (32 bytes)
&lt;chainId (uint256)&gt;           (32 bytes)
&lt;mode (bytes12)&gt;              (12 bytes)
&lt;linkedContract (address)&gt;    (20 bytes)
&lt;linkedId (uint256)&gt;          (32 bytes)
```

**Total bytecode size: 183 bytes**

Linked services SHOULD implement the `IERC7656Service` interface:

```solidity
// Interface ID: 0x7e110a1d
interface IERC7656Service {
  function linkedData() external view
    returns (uint256 chainId, bytes12 mode, address linkedContract, uint256 linkedId);
}
```

### Implementation Patterns

When implementing a linked service, developers SHOULD consider the following patterns:

1. **Ownership Verification**: Services SHOULD include mechanisms to verify that operations are authorized by the current owner of the linked contract or token.

2. **Mode-Specific Logic**: Services SHOULD implement conditional logic based on the `mode` parameter to handle both NFT-linked and account-linked scenarios appropriately.

3. **Cross-Chain Awareness**: Services SHOULD check that operations are being performed on the chain specified in the `chainId` parameter to prevent cross-chain replay attacks.


## Rationale

The design of [ERC-7656](/EIPs/EIPS/eip-7656) is guided by several key principles that address limitations in current contract extension methods:

### Why a Unified Factory?

Rather than creating separate standards for NFT extensions and account extensions, [ERC-7656](/EIPs/EIPS/eip-7656) employs a unified factory approach. This design choice stems from recognizing the fundamental similarity between linking services to tokens and linking services to accounts - both involve extending functionality while maintaining a clear ownership relationship.

### Mode Parameter Design

The `mode` parameter uses 12 bytes instead of a simple boolean flag because the 12-byte format reserves space for future linking modes beyond the initial two (NFT linking and account linking). For example, if a service is associated to an [ERC-1155](/EIPs/EIPS/eip-1155) token but requires that the balance of the user is more than 1000 tokens, the mode could be `0x000000000000000000003e802`, where the least significant byte, `0x02` is the primary mode and the rest is the minimum required balance. Similarly, someone can think of a service associated to [ERC-20](/EIPs/EIPS/eip-20) tokens that requires a specific balance where the required balance can be put in the `linkedId` field, and the `mode` specified accordingly. 

### Deterministic Addressing

[ERC-7656](/EIPs/EIPS/eip-7656) follows a deterministic addressing pattern, appending immutable data to the contract bytecode rather than storing it in contract storage. This ensures that:

1. Linked services have predictable addresses that can be computed off-chain
2. The factory remains stateless, reducing gas costs
3. Linked services can be deployed on-demand or even referenced before deployment

### Generic Linking Mechanism

Unlike standards that enforce specific interfaces or behaviors on linked contracts, [ERC-7656](/EIPs/EIPS/eip-7656) remains agnostic about the implementation details of linked services. This deliberate design choice allows developers maximum flexibility to create specialized services while maintaining a consistent deployment and ownership model.


## Backwards Compatibility

[ERC-7656](/EIPs/EIPS/eip-7656) maintains compatibility with token-bound accounts when used with the `LINKED_ID` mode (0x000000000000000000000000). This ensures that existing applications and infrastructure supporting token-bound accounts can continue operating without modification.

For contracts using the `NO_LINKED_ID` mode (0x000000000000000000000001), specialized interfaces may be required, but the core factory mechanism remains consistent.


## Reference Implementation

See [`ERC7656Factory.sol`](/EIPs/assets/eip-7656/ERC7656Factory.sol) for an example implementation of `IERC7656Factory`. 

For convenience, the bytecode of the reference implementation has been deployed at `0x76565d90eeB1ce12D05d55D142510dBA634a128F` on Ethereum mainnet, and will be later deployed at the same address to all primary mainnets and selected testnets.

An example of implementation of `IERC7656Service`:

```solidity
contract LinkedService is IERC7656Service, EIP5313 {

  function linkedData(address service) public view returns (uint256, bytes12, address, uint256) {
    bytes memory encodedData = new bytes(0x60);
    // solhint-disable-next-line no-inline-assembly
    assembly {
    // Copy 0x60 bytes from end of context
      extcodecopy(service, add(encodedData, 0x20), 0x4d, 0x60)
    }

    uint256 chainId;
    bytes32 linkedContract;
    uint256 linkedId;

    // solhint-disable-next-line no-inline-assembly
    assembly {
      chainId := mload(add(encodedData, 0x20))
      linkedContract := mload(add(encodedData, 0x40))
      linkedId := mload(add(encodedData, 0x60))
    }

    bytes12 mode = bytes12(linkedContract);

    address extractedAddress = address(uint160(uint256(linkedContract)));
    return (chainId, mode, extractedAddress, linkedId);
  }

  function owner() public view virtual override returns (address) {
    (uint256 chainId, , address tokenContract_, uint256 tokenId_) = linkedData();
    if (chainId != block.chainid) return address(0);
    return IERC721(tokenContract_).ownerOf(tokenId_);
  }
}
```

## Security Considerations

### Ownership Cycles

Smart wallets linked to NFTs that are then held by the same wallet can create ownership cycles, potentially rendering assets inaccessible. Implementers should include safeguards to prevent or detect such cycles.

### Fraud Prevention

A malicious seller could alter or revoke service permissions just before finalizing a sale. Lock mechanisms preventing last-minute changes may be implemented, especially for NFT marketplaces integrating with [ERC-7656](/EIPs/EIPS/eip-7656) services.

### Malicious Implementations

The registry cannot enforce legitimate ownership when linking services. Users should review or audit implementations before deployment. Front-end applications integrating [ERC-7656](/EIPs/EIPS/eip-7656) should display warnings when interacting with unverified implementations.

### Upgradeability Risks

Linked services that are upgradable pose risks of unexpected changes or asset exfiltration. Secure upgrade mechanisms with timelock controls or multi-signature governance should be implemented when upgradeability is required.

### Reentrancy &amp; Cross-Contract Attacks

Linked services interacting with assets or external protocols may be vulnerable to reentrancy exploits. Implementers should follow security best practices such as the checks-effects-interactions pattern and consider reentrancy guards.

### Mode-Specific Vulnerabilities

Services operating in different modes (`LINKED_ID` vs `NO_LINKED_ID`) may have different security requirements. Implementations should validate that operations are appropriate for the service&apos;s configured mode.

### User Education &amp; Phishing Risks

Even with secure contracts, users may fall victim to fraudulent services masquerading as legitimate ones. Clear UI warnings, verification tools, and educational resources should be provided by applications integrating [ERC-7656](/EIPs/EIPS/eip-7656).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 15 Mar 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7656</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7656</guid>
      </item>
    
      <item>
        <title>Sync committee slashings</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7657-sync-committee-slashings/19288</comments>
        
        <description>## Abstract

This EIP defines a slashing condition for malicious [sync committee messages](https://github.com/ethereum/consensus-specs/blob/b3e83f6691c61e5b35136000146015653b22ed38/specs/altair/validator.md#containers).

## Motivation

A dishonest supermajority of sync committee members is able to convince applications relying on Ethereum&apos;s [light client sync protocol](https://github.com/ethereum/consensus-specs/blob/b3e83f6691c61e5b35136000146015653b22ed38/specs/altair/light-client/sync-protocol.md) to assume a non-canonical finalized header, and to potentially take over the sync authority for future `SyncCommitteePeriod`. By signing a malicious beacon block root, a malicious (but valid!) `LightClientUpdate` message can be formed and subsequently used to, for example, exploit a trust-minimized bridge contract based on the light client sync protocol.

An additional type of slashing is introduced to deter against signing non-canonical beacon block roots as a sync committee member. As is the case with [`ProposerSlashing`](https://github.com/ethereum/consensus-specs/blob/b3e83f6691c61e5b35136000146015653b22ed38/specs/phase0/beacon-chain.md#proposerslashing) and [`AttesterSlashing`](https://github.com/ethereum/consensus-specs/blob/b3e83f6691c61e5b35136000146015653b22ed38/specs/phase0/beacon-chain.md#attesterslashing), only malicious behaviour is slashable. This includes simultaneous contradictory participation across multiple chain branches, but a validator that is simply tricked into syncing to an incorrect checkpoint should not be slashable even though it is participating on a non-canonical chain. Note that a slashing must be verifiable even without access to history, e.g., by a checkpoint synced beacon node.

Note that regardless of the slashing mechanism, a slashing can only be applied retroactively after an attack has already occurred. Use cases that secure a larger amount than `SYNC_COMMITTEE_SIZE * MAX_EFFECTIVE_BALANCE` = `512 * 32 ETH` = `16384 ETH` (on mainnet) should combine the light client sync protocol with other established methods such as a multisig, or may want to require posting additional collateral to be eligible for submitting updates. Other methods are out of scope for this EIP.

## Specification

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

### State transition checks

Note: This still allows having contradictions between attestations/proposals and sync committee messages. This also, by design, allows a validator to not participate at all in honest sync committee messages but solely participate in dishonest sync committee messages.

| Name | Value |
| - | - |
| `BLOCK_STATE_ROOT_INDEX` | `get_generalized_index(BeaconBlock, &apos;state_root&apos;)` (= 11) |
| `STATE_BLOCK_ROOTS_INDEX` | `get_generalized_index(BeaconState, &apos;block_roots&apos;)` (= 37) |
| `STATE_HISTORICAL_ROOTS_INDEX` | `get_generalized_index(BeaconState, &apos;historical_roots&apos;)` (= 39) |
| `HISTORICAL_BATCH_BLOCK_ROOTS_INDEX` | `get_generalized_index(HistoricalBatch, &apos;block_roots&apos;)` (= 2) |

```python
class SyncCommitteeSlashingEvidence(Container):
    attested_header: BeaconBlockHeader
    next_sync_committee: SyncCommittee
    next_sync_committee_branch: Vector[Root, floorlog2(NEXT_SYNC_COMMITTEE_INDEX)]
    finalized_header: BeaconBlockHeader
    finality_branch: Vector[Root, floorlog2(FINALIZED_ROOT_INDEX)]
    sync_aggregate: SyncAggregate
    signature_slot: Slot
    sync_committee_pubkeys: Vector[BLSPubkey, SYNC_COMMITTEE_SIZE]
    actual_finalized_block_root: Root
    actual_finalized_branch: List[Root, (
        floorlog2(BLOCK_STATE_ROOT_INDEX)
        + floorlog2(STATE_HISTORICAL_ROOTS_INDEX)
        + 1 + floorlog2(HISTORICAL_ROOTS_LIMIT)
        + floorlog2(HISTORICAL_BATCH_BLOCK_ROOTS_INDEX)
        + 1 + floorlog2(SLOTS_PER_HISTORICAL_ROOT))]

class SyncCommitteeSlashing(Container):
    slashable_validators: List[ValidatorIndex, SYNC_COMMITTEE_SIZE]
    evidence_1: SyncCommitteeSlashingEvidence
    evidence_2: SyncCommitteeSlashingEvidence
    recent_finalized_block_root: Root
    recent_finalized_slot: Slot

def sync_committee_slashing_evidence_has_sync_committee(evidence: SyncCommitteeSlashingEvidence) -&gt; bool:
    return evidence.next_sync_committee_branch != [Root() for _ in range(floorlog2(NEXT_SYNC_COMMITTEE_INDEX))]

def sync_committee_slashing_evidence_has_finality(evidence: SyncCommitteeSlashingEvidence) -&gt; bool:
    return evidence.finality_branch != [Root() for _ in range(floorlog2(FINALIZED_ROOT_INDEX))]

def is_valid_sync_committee_slashing_evidence(evidence: SyncCommitteeSlashingEvidence,
                                              recent_finalized_block_root: Root,
                                              recent_finalized_slot: Slot,
                                              genesis_validators_root: Root) -&gt; bool:
    # Verify sync committee has sufficient participants
    sync_aggregate = evidence.sync_aggregate
    if sum(sync_aggregate.sync_committee_bits) &lt; MIN_SYNC_COMMITTEE_PARTICIPANTS:
        return False

    # Verify that the `finality_branch`, if present, confirms `finalized_header`
    # to match the finalized checkpoint root saved in the state of `attested_header`.
    # Note that the genesis finalized checkpoint root is represented as a zero hash.
    if not sync_committee_slashing_evidence_has_finality(evidence):
        if evidence.actual_finalized_block_root != Root():
            return False
        if evidence.finalized_header != BeaconBlockHeader():
            return False
    else:
        if evidence.finalized_header.slot == GENESIS_SLOT:
            if evidence.actual_finalized_block_root != Root():
                return False
            if evidence.finalized_header != BeaconBlockHeader():
                return False
            finalized_root = Root()
        else:
            finalized_root = hash_tree_root(evidence.finalized_header)
        if not is_valid_merkle_branch(
            leaf=finalized_root,
            branch=evidence.finality_branch,
            depth=floorlog2(FINALIZED_ROOT_INDEX),
            index=get_subtree_index(FINALIZED_ROOT_INDEX),
            root=evidence.attested_header.state_root,
        ):
            return False

    # Verify that the `next_sync_committee`, if present, actually is the next sync committee saved in the
    # state of the `attested_header`
    if not sync_committee_slashing_evidence_has_sync_committee(evidence):
        if evidence.next_sync_committee != SyncCommittee():
            return False
    else:
        if not is_valid_merkle_branch(
            leaf=hash_tree_root(evidence.next_sync_committee),
            branch=evidence.next_sync_committee_branch,
            depth=floorlog2(NEXT_SYNC_COMMITTEE_INDEX),
            index=get_subtree_index(NEXT_SYNC_COMMITTEE_INDEX),
            root=evidence.attested_header.state_root,
        ):
            return False

    # Verify that the `actual_finalized_block_root`, if present, is confirmed by `actual_finalized_branch`
    # to be the block root at slot `finalized_header.slot` relative to `recent_finalized_block_root`
    if recent_finalized_block_root == Root():
        if evidence.actual_finalized_block_root != Root():
            return False
    if evidence.actual_finalized_block_root == Root():
        if len(evidence.actual_finalized_branch) != 0:
            return False
    else:
        finalized_slot = evidence.finalized_header.slot
        if recent_finalized_slot &lt; finalized_slot:
            return False
        distance = recent_finalized_slot - finalized_slot
        if distance == 0:
            gindex = GeneralizedIndex(1)
        else:
            gindex = BLOCK_STATE_ROOT_INDEX
            if distance &lt;= SLOTS_PER_HISTORICAL_ROOT:
                gindex = (gindex &lt;&lt; floorlog2(STATE_BLOCK_ROOTS_INDEX)) + STATE_BLOCK_ROOTS_INDEX
            else:
                gindex = (gindex &lt;&lt; floorlog2(STATE_HISTORICAL_ROOTS_INDEX)) + STATE_HISTORICAL_ROOTS_INDEX
                gindex = (gindex &lt;&lt; uint64(1)) + 0  # `mix_in_length`
                historical_batch_index = finalized_slot // SLOTS_PER_HISTORICAL_ROOT
                gindex = (gindex &lt;&lt; floorlog2(HISTORICAL_ROOTS_LIMIT)) + historical_batch_index
                gindex = (gindex &lt;&lt; floorlog2(HISTORICAL_BATCH_BLOCK_ROOTS_INDEX)) + HISTORICAL_BATCH_BLOCK_ROOTS_INDEX
            gindex = (gindex &lt;&lt; uint64(1)) + 0  # `mix_in_length`
            block_root_index = finalized_slot % SLOTS_PER_HISTORICAL_ROOT
            gindex = (gindex &lt;&lt; floorlog2(SLOTS_PER_HISTORICAL_ROOT)) + block_root_index
        if len(evidence.actual_finalized_branch) != floorlog2(gindex):
            return False
        if not is_valid_merkle_branch(
            leaf=evidence.actual_finalized_block_root,
            branch=evidence.actual_finalized_branch,
            depth=floorlog2(gindex),
            index=get_subtree_index(gindex),
            root=recent_finalized_block_root,
        ):
            return False

    # Verify sync committee aggregate signature
    sync_committee_pubkeys = evidence.sync_committee_pubkeys
    participant_pubkeys = [
        pubkey for (bit, pubkey) in zip(sync_aggregate.sync_committee_bits, sync_committee_pubkeys)
        if bit
    ]
    fork_version = compute_fork_version(compute_epoch_at_slot(evidence.signature_slot))
    domain = compute_domain(DOMAIN_SYNC_COMMITTEE, fork_version, genesis_validators_root)
    signing_root = compute_signing_root(evidence.attested_header, domain)
    return bls.FastAggregateVerify(participant_pubkeys, signing_root, sync_aggregate.sync_committee_signature)

def process_sync_committee_slashing(state: BeaconState, sync_committee_slashing: SyncCommitteeSlashing) -&gt; None:
    is_slashable = False

    # Check that evidence is ordered descending by `attested_header.slot` and is not from the future
    evidence_1 = sync_committee_slashing.evidence_1
    evidence_2 = sync_committee_slashing.evidence_2
    assert state.slot &gt;= evidence_1.signature_slot &gt; evidence_1.attested_header.slot &gt;= evidence_1.finalized_header.slot
    assert state.slot &gt;= evidence_2.signature_slot &gt; evidence_2.attested_header.slot &gt;= evidence_2.finalized_header.slot
    assert evidence_1.attested_header.slot &gt;= evidence_2.attested_header.slot

    # Only conflicting data among the current and previous sync committee period is slashable;
    # on new periods, the sync committee initially signs blocks in a previous sync committee period.
    # This allows a validator synced to a malicious checkpoint to contribute again in a future period
    evidence_1_attested_period = compute_sync_committee_period_at_slot(evidence_1.attested_header.slot)
    evidence_2_attested_period = compute_sync_committee_period_at_slot(evidence_2.attested_header.slot)
    assert evidence_1_attested_period &lt;= evidence_2_attested_period + 1

    # It is not allowed to sign conflicting `attested_header` for a given slot
    if evidence_1.attested_header.slot == evidence_2.attested_header.slot:
        if evidence_1.attested_header != evidence_2.attested_header:
            is_slashable = True

    # It is not allowed to sign conflicting finalized `next_sync_committee`
    evidence_1_finalized_period = compute_sync_committee_period_at_slot(evidence_1.finalized_header.slot)
    evidence_2_finalized_period = compute_sync_committee_period_at_slot(evidence_2.finalized_header.slot)
    if (
        evidence_1_attested_period == evidence_2_attested_period
        and evidence_1_finalized_period == evidence_1_attested_period
        and evidence_2_finalized_period == evidence_2_attested_period
        and sync_committee_slashing_evidence_has_finality(evidence_1)
        and sync_committee_slashing_evidence_has_finality(evidence_2)
        and sync_committee_slashing_evidence_has_sync_committee(evidence_1)
        and sync_committee_slashing_evidence_has_sync_committee(evidence_2)
    ):
        if evidence_1.next_sync_committee != evidence_2.next_sync_committee:
            is_slashable = True

    # It is not allowed to sign a non-linear finalized history
    recent_finalized_slot = sync_committee_slashing.recent_finalized_slot
    recent_finalized_block_root = sync_committee_slashing.recent_finalized_block_root
    if (
        not sync_committee_slashing_evidence_has_finality(evidence_1)
        or not sync_committee_slashing_evidence_has_finality(evidence_2)
    ):
        assert recent_finalized_block_root == Root()
    if recent_finalized_block_root == Root():
        assert recent_finalized_slot == 0
    else:
        # Merkle proofs may be included to indicate that `finalized_header` does not match
        # the `actual_finalized_block_root` relative to a given `recent_finalized_block_root`.
        # The finalized history is linear. Therefore, a mismatch indicates signing on an unrelated chain.
        # Note that it is not slashable to sign solely an alternate history, as long as it is consistent.
        # This allows a validator synced to a malicious checkpoint to contribute again in a future period
        linear_1 = (evidence_1.actual_finalized_block_root == hash_tree_root(evidence_1.finalized_header))
        linear_2 = (evidence_2.actual_finalized_block_root == hash_tree_root(evidence_2.finalized_header))
        assert not linear_1 or not linear_2
        assert linear_1 or linear_2  # Do not slash on signing solely an alternate history

        # `actual_finalized_branch` may be rooted in the provided `finalized_header` with highest slot
        rooted_in_evidence_1 = (
            evidence_1.finalized_header.slot &gt;= evidence_2.finalized_header.slot
            and recent_finalized_slot == evidence_1.finalized_header.slot
            and recent_finalized_block_root == evidence_1.actual_finalized_block_root and linear_1
        )
        rooted_in_evidence_2 = (
            evidence_2.finalized_header.slot &gt;= evidence_1.finalized_header.slot
            and recent_finalized_slot == evidence_2.finalized_header.slot
            and recent_finalized_block_root == evidence_2.actual_finalized_block_root and linear_2
        )

        # Alternatively, if evidence about non-linearity cannot be obtained directly from an attack,
        # it can be proven that one of the `finalized_header` is part of the canonical finalized chain
        # that our beacon node is synced to, while the other `finalized_header` is unrelated.
        rooted_in_canonical = (
            recent_finalized_slot &lt; state.slot &lt;= recent_finalized_slot + SLOTS_PER_HISTORICAL_ROOT
            and recent_finalized_slot &lt;= compute_start_slot_at_epoch(state.finalized_checkpoint.epoch)
            and recent_finalized_block_root == state.block_roots[recent_finalized_slot % SLOTS_PER_HISTORICAL_ROOT]
        )
        assert rooted_in_evidence_1 or rooted_in_evidence_2 or rooted_in_canonical
        is_slashable = True

    assert is_slashable

    # Check that slashable validators are sorted, known, and participated in both signatures
    will_slash_any = False
    sync_aggregate_1 = evidence_1.sync_aggregate
    sync_aggregate_2 = evidence_2.sync_aggregate
    sync_committee_pubkeys_1 = evidence_1.sync_committee_pubkeys
    sync_committee_pubkeys_2 = evidence_2.sync_committee_pubkeys
    participant_pubkeys_1 = [
        pubkey for (bit, pubkey) in zip(sync_aggregate_1.sync_committee_bits, sync_committee_pubkeys_1)
        if bit
    ]
    participant_pubkeys_2 = [
        pubkey for (bit, pubkey) in zip(sync_aggregate_2.sync_committee_bits, sync_committee_pubkeys_2)
        if bit
    ]
    slashable_validators = sync_committee_slashing.slashable_validators
    num_validators = len(state.validators)
    for i, index in enumerate(slashable_validators):
        assert (
            index &lt; num_validators
            and (i == 0 or index &gt; slashable_validators[i - 1])
        )
        assert state.validators[index].pubkey in participant_pubkeys_1
        assert state.validators[index].pubkey in participant_pubkeys_2
        if is_slashable_validator(state.validators[index], get_current_epoch(state)):
            will_slash_any = True
    assert will_slash_any

    # Validate evidence, including signatures
    assert is_valid_sync_committee_slashing_evidence(
        evidence_1,
        recent_finalized_block_root,
        recent_finalized_slot,
        state.genesis_validators_root,
    )
    assert is_valid_sync_committee_slashing_evidence(
        evidence_2,
        recent_finalized_block_root,
        recent_finalized_slot,
        state.genesis_validators_root,
    )

    # Perform slashing
    for index in slashable_validators:
        if is_slashable_validator(state.validators[index], get_current_epoch(state)):
            slash_validator(state, index)
```

## Rationale

### What&apos;s the use case?

Without a slashing, the light client sync protocol is somewhat limited. While wallet applications may benefit from it (the risk being, that incorrect data is displayed) and new beacon nodes may use it for accelerating chain synchronization, other interesting use cases such as bridges, token distributions or other systems requiring proofs depend on the mechanism providing higher security guarantees.

By making attacks by sync committee members slashable, a sufficiently high deterrent could be provided. A majority of the sync committee would have to be bribed to succeed in an attack even in the most simple cases, representing a sizable slashable balance.

## Backwards Compatibility

This EIP requires a hard fork as it introduces new consensus validation rules.

Supporting infrastructure may be introduced separately once the consensus validation rules are in place, including but not limited to:

- Slashing protection DB updates, to guarantee that honest validators cannot be slashed on reorgs
- Validator client / remote signer APIs, to pass along information related to slashing protection
- libp2p meshes for exchanging slashing evidence between beacon nodes
- Slasher, to monitor potential targets and construct slashing evidence
- Beacon APIs, to submit and monitor slashing evidence

## Test Cases

TBD

## Reference Implementation

TBD

## Security Considerations

TBD

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 21 Mar 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7657</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7657</guid>
      </item>
    
      <item>
        <title>Light client data backfill</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7658-light-client-data-backfill/19290</comments>
        
        <description>## Abstract

This EIP defines a mechanism for syncing [light client data](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/altair/light-client/full-node.md) between beacon nodes.

## Motivation

[Light client data](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/altair/light-client/full-node.md) is collected by beacon nodes to assist [light clients](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/altair/light-client/light-client.md) to sync with the network. The [sync protocol](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/altair/light-client/sync-protocol.md) defines a mechanism to sync forward in time. However, it cannot be used to sync backward.

Collecting light client data is challenging because beacon nodes need to have access to the corresponding [`BeaconState`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/phase0/beacon-chain.md#beaconstate) and [`SignedBeaconBlock`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/phase0/beacon-chain.md#signedbeaconblock). `BeaconState` objects are not available before the initially synced checkpoint state, and `SignedBeaconBlock` objects have a limited retention period on libp2p.

Furthermore, each [sync committee period](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/altair/beacon-chain.md#get_next_sync_committee) consists of `EPOCHS_PER_SYNC_COMMITTEE_PERIOD * SLOTS_PER_EPOCH` slots. To support archive services such as Portal network to provide a consistent view regardless of backend, it is necessary to choose a single canonical slot for which to derive the representative light client data for that period. Such data should be verifiable to be canonical and optimal in a decentralized and independent manner.

To support light client data backfill, this EIP proposes to track the canonical and optimal [`SyncAggregate`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/altair/beacon-chain.md#syncaggregate) in the `BeaconState`. This minimal addition allows proving that derived [`LightClientUpdate`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/altair/light-client/sync-protocol.md#lightclientupdate) and [`LightClientBootstrap`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/altair/light-client/sync-protocol.md#lightclientbootstrap) are also canonical and optimal.

## Specification

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

### Containers

#### New containers

##### `SyncData`

```python
class SyncData(Container):
    # Sync committee aggregate signature
    sync_aggregate: SyncAggregate
    # Slot at which the aggregate signature was created
    signature_slot: Slot
```

#### Extended containers

##### `BeaconState`

New fields are added to the end of `BeaconState` from the activating fork onward to track the current and previous sync committee period&apos;s best sync data.

```python
class BeaconState(Container):
    ...
    # Sync history
    previous_best_sync_data: SyncData
    current_best_sync_data: SyncData
    parent_block_has_sync_committee_finality: bool
```

### Helper functions

#### `default_sync_data`

```python
def default_sync_data() -&gt; SyncData:
    return SyncData(
        sync_aggregate=SyncAggregate(
            sync_committee_bits=Bitvector[SYNC_COMMITTEE_SIZE](),
            sync_committee_signature=G2_POINT_AT_INFINITY,
        ),
        signature_slot=GENESIS_SLOT,
    )
```

### Beacon chain state transition function

#### Epoch processing

##### Modified `process_sync_committee_updates`

On sync committee boundaries, current period data is moved to previous period. This allows proving that light client data for the previous period is canonical.

```python
def process_sync_committee_updates(state: BeaconState) -&gt; None:
    next_epoch = get_current_epoch(state) + Epoch(1)
    if next_epoch % EPOCHS_PER_SYNC_COMMITTEE_PERIOD == 0:
        ...
        state.previous_best_sync_data = state.current_best_sync_data
        state.current_best_sync_data = default_sync_data()
        state.parent_block_has_sync_committee_finality = False
```

#### Block processing

Block processing is extended to track the optimal light client data for the current period. Due to the possibility for empty slots this must be tracked before the block header is overwritten; this allows tracking the exact block after which `next_sync_committee` becomes finalized.

```python
def process_block(state: BeaconState, block: BeaconBlock) -&gt; None:
    process_best_sync_data(state, block)
    process_block_header(state, block)
    ...
```

##### New `process_best_sync_data`

```python
def process_best_sync_data(state: BeaconState, block: BeaconBlock) -&gt; None:
    signature_period = compute_sync_committee_period_at_slot(block.slot)
    attested_period = compute_sync_committee_period_at_slot(state.latest_block_header.slot)

    # Track sync committee finality
    old_has_sync_committee_finality = state.parent_block_has_sync_committee_finality
    if state.parent_block_has_sync_committee_finality:
        new_has_sync_committee_finality = True
    elif state.finalized_checkpoint.epoch &lt; ALTAIR_FORK_EPOCH:
        new_has_sync_committee_finality = False
    else:
        finalized_period = compute_sync_committee_period(state.finalized_checkpoint.epoch)
        new_has_sync_committee_finality = (finalized_period == attested_period)
    state.parent_block_has_sync_committee_finality = new_has_sync_committee_finality

    # Track best sync data
    if attested_period == signature_period:
        max_active_participants = len(block.body.sync_aggregate.sync_committee_bits)
        new_num_active_participants = sum(block.body.sync_aggregate.sync_committee_bits)
        old_num_active_participants = sum(state.current_best_sync_data.sync_aggregate.sync_committee_bits)
        new_has_supermajority = new_num_active_participants * 3 &gt;= max_active_participants * 2
        old_has_supermajority = old_num_active_participants * 3 &gt;= max_active_participants * 2
        if new_has_supermajority != old_has_supermajority:
            is_better_sync_data = new_has_supermajority
        elif not new_has_supermajority and new_num_active_participants != old_num_active_participants:
            is_better_sync_data = new_num_active_participants &gt; old_num_active_participants
        elif new_has_sync_committee_finality != old_has_sync_committee_finality:
            is_better_sync_data = new_has_sync_committee_finality
        elif new_num_active_participants != old_num_active_participants:
            is_better_sync_data = new_num_active_participants &gt; old_num_active_participants
        else:
            is_better_sync_data = block.slot &lt; state.current_best_sync_data.signature_slot
        if is_better_sync_data:
            state.current_best_sync_data = SyncData(
                sync_aggregate=block.body.sync_aggregate,
                signature_slot=block.slot,
            )
```

## Rationale

### How to rank `SyncAggregate`?

The EIP reuses the [`is_better_update`](https://github.com/ethereum/consensus-specs/blob/4afe39822c9ad9747e0f5635cca117c18441ec1b/specs/altair/light-client/sync-protocol.md#is_better_update) function from existing specs.

To ensure deterministic selection when participation and finality are equal, implementations MUST break ties by preferring the lower `signature_slot`; if equal, the existing selection SHOULD be retained.

### How could a backfill protocol use this?

Once the data is available in the `BeaconState`, a light client data backfill protocol could be defined that serves, for past periods:

1. A `LightClientUpdate` from requested `period` + 1 that proves that the entirety of `period` is finalized.
2. `BeaconState.historical_summaries[period].block_summary_root` at (1)&apos;s `attested_header.beacon.state_root` + Merkle proof.
3. For each epoch&apos;s slot 0 block within requested `period`, the corresponding `LightClientHeader` + Merkle multi-proof for the block&apos;s inclusion into (2)&apos;s `block_summary_root`.
4. For each of the entries from (3) with `beacon.slot` within `period`, the `current_sync_committee_branch` + Merkle proof for constructing `LightClientBootstrap`.
5. If (4) is not empty, the requested `period`&apos;s `current_sync_committee`.
6. The best `LightClientUpdate` from `period`, if one exists, + Merkle proof that its `sync_aggregate` + `signature_slot` is selected as the canonical best one in (1)&apos;s `attested_header.beacon.state_root`.

Only the proof in (6) depends on `BeaconState` tracking the best light client data. This modification would enshrine the logic of a subset of `is_better_update`, but does not require adding any `LightClientXyz` data structures to the `BeaconState`.

## Backwards Compatibility

This EIP requires a hard fork as it introduces new consensus validation rules.

Only light client data following the hard fork can be proven to be canonical and optimal. However, after finalization of the fork transition block, earlier light client data can no longer change and could be locked in using a hash.

## Security Considerations

None

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 21 Mar 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7658</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7658</guid>
      </item>
    
      <item>
        <title>AI Agent NFTs</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7662-ai-agent-nfts/19371</comments>
        
        <description>## Abstract

This proposal introduces a standard for AI agent NFTs. When AI Agents are created and traded as NFTs, it doesn&apos;t make sense to put the prompts in the token metadata, therefore it requires a standard custom struct. It also doesn&apos;t make sense to store the prompts directly onchain as they can be quite large, therefore this standard proposes they be stored as decentralized storage URLs. This standard also proposes two options on how this data should be made private to the owner of the NFT, with the favored implementation option being encrypting the data using custom contract parameters for decryption that decrypt only to the owner of the NFT. 

## Motivation

The creation and trading of AI Agent NFTs are a natural fit and offer the potential for an entirely new onchain market. This requires some custom data to be embedded in the NFT through a custom struct and this needs to be standardized so that any marketplace or AI Agent management product, among others, know how to create and parse AI Agent NFTs.  The goal of this standard is to provide a new utility for NFTs in the field of AI and also to provide new liquidity, through the NFT market, for AI Agents. If widely adopted by marketplaces, and infrastructure and no-code providers this should open up a new market and community for AI Agent creators in different fields, AI Agent consumers and NFT marketplaces. 


## Specification

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


All ERC-XXXX compliant contracts MUST implement the standard [ERC-721](/EIPs/EIPS/eip-721) functionality for minting and transferring NFTs, and MUST additionally implement this standard&apos;s Agent interface

```solidity
   
interface IERC7662 is IERC721 {

    function getAgentData(uint256 tokenId) external view returns (
        string memory name,
        string memory description,
        string memory model,
        string memory userPromptURI,
        string memory systemPromptURI,
        bool promptsEncrypted
    );

    event AgentUpdated(uint256 indexed tokenId);
}
```

and MUST implement the mapping between NFT Token ID and its Agent information.

It is RECOMMENDED that this mapping is public and that the URIs for User Prompt and System Prompt are made private through encryption with decryption logic set to the holder of the NFT via custom contract parameters set during encryption, and the method or platform used to provide this encryption SHOULD be retrievable as a data property of the NFT in order that platforms that should facilitate the use of these NFTs can set up a predictable way to handle this decryption, depending on the platform or method used.  

It is conceivable to also create an implementation whereby this mapping was set to private and accessed through a custom function that restricted access to the holder of the NFT. This approach would explose the prompts through their urls though, therefore the RECOMMENDED approach is a public mapping and encryption on the URLs. This also has the benefit of publicly exposing the data in the Agent struct to verify name, description and model and that encrypted URIs for the User Prompt and System Prompt exist.

All ERC-XXXX compliant contracts MUST implement a function to mint new Agent tokens. This function SHOULD:

- Accept parameters for all Agent properties (name, description, model, userPromptURI, systemPromptURI, etc.)
- Mint a new token to the specified recipient
- Associate the provided Agent properties with the newly minted token
- Emit an event signaling the creation of a new Agent token

It is RECOMMENDED that ERC-XXXX compliant contracts provide functionality to encrypt the user prompt and system prompt. This functionality SHOULD:

- Allow only the token owner to encrypt the prompts
- Update the userPromptURI and systemPromptURI with encrypted versions
- Set a flag indicating that the prompts are encrypted

It is RECOMMENDED to implement the following event: 

```solidity
event AgentCreated(string name, string description, string model, address recipient, uint256 tokenId)

```

This event SHOULD be emitted when a new Agent token is minted, providing key information about the newly created Agent.

To enable dynamic variables being injected into the User Prompt before being run, any such variables MUST be surrounded with ${} e.g. ${dynamicVariableName} in order that they can be recognized and handled appropriately by programs and systems that will enabled the injection, e.g. web forms and automation systems. 

It is RECOMMENDED to add a data to the [ERC-721](/EIPs/EIPS/eip-721) standard that makes it easy for e.g. NFT Marketplaces to display data about the AI Agent NFT, i.e. Model, which in turn reveals the platform that is used for the agent, e.g. OpenAI in the case of gpt-4-0125-preview or Anthropic in the case of claude-3-opus-20240229. The standard name and description can be used to display the Agent Name and Agent Description. 

## Rationale

This standard provides a unified way to create and parse AI Agent NFTs. 

This standard codifies the necessary parameters of Name, Description, Model, User Prompt, and System Prompt for creating and using AI Agent NFTs. 

It doesn&apos;t make practical sense to store the user and system prompts in an existing [ERC-721](/EIPs/EIPS/eip-721) as the only place to put would be in the token metadata that is open for anyone to access the prompts without owning the NFT. By storing the prompts in a custom Agent struct and restricting access to the prompts to the holder of the NFT.  One way to do this would be through restricting access to the struct info to the holder of the NFT through a custom function, however since that option still exposes the prompt URIs to the public and thus the data inside them, the recommended method is by encrypting the prompts onchain and tying the decryption of the URLs to the holder of the NFT, using onchain services that enable decryption to be tied to contract parameters such as ownerOf(tokenId).
 

## Backwards Compatibility

The AI Agents NFT standard introduces additional features and data to the standard [ERC-721](/EIPs/EIPS/eip-721) protocol, aimed at addressing the practical requirements of using NFTs to store, trade and use AI Agents. It is designed to be fully backward-compatible with the original [ERC-721](/EIPs/EIPS/eip-721) standard.  All existing [ERC-721](/EIPs/EIPS/eip-721) functions (such as transferFrom, approve, and balanceOf) retain their original functionality and interfaces. Our extension does not modify these core behaviors, ensuring that any [ERC-721](/EIPs/EIPS/eip-721) compliant wallet or service can interact with these tokens without modifications.

### Reference Implementation

This is being currently implemented in a product for creating, managing and using AI Agents Onchain through a DApp interface. In this implementation, an encryption platform is being used to encrypt the prompts using custom EVMContractParameters that only decrypt for the holder of the NFT and using a decentralized storage network to store the URLs of this encrypted data. To facilitate that and make DApp handling easier, some parameters were added to Agent and the addEncryptedPrompts function is added that enables adding the encrypted prompt URIs after first minting the NFT (as the tokenId of the NFT is needed for setting the encryption/decryption conditions).

A reference smart contract is provided in the assets folder. 



## Security Considerations

&lt;!-- TODO --&gt;

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 26 Mar 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7662</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7662</guid>
      </item>
    
      <item>
        <title>Access-Key opcode</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/access-key-opcode/19395</comments>
        
        <description>## Abstract

This EIP introduces a new opcode to inspect the access-list keys of the executing address.

## Motivation

This EIP serves as a substitute of top-level-call detection to enable a smart-contract to 
enforce static declaration of attributes.

Previously, application-layer contracts, against common advice from account-abstraction proponents, used to rely
on the `tx.origin` to enforce a top-level call, such that the contract inputs are encoded as transaction input.

While the access-list of transactions directly affects the execution, it only affects the gas-costs.
This EIP enhances the access-list feature to provide the property of statically-defined contract-inputs,
without relying on top-level calls, the `tx.origin` behavior, or gas introspection.

This enables smart contracts to reliably enforce static declaration of inputs.

This is a step towards fulfilling the purposes as described in the Motivation of [EIP-2930](/EIPs/EIPS/eip-2930):

&gt; Introduces the access list format and the logic for handling the format.
&gt; This logic can later be repurposed for many other purposes, including block-wide witnesses,
&gt; use in ReGenesis, moving toward static state access over time, and more.&quot;

## Specification

### Parameters

| Constant                   | Value  |
|----------------------------|--------|
| `ACCESS_KEY_OPCODE_GAS`    | `3`    |
| `ACCESS_KEY_OPCODE_BYTE`   | `0x4B` |

### Opcode

We add an instruction `ACCESS_KEY` (with opcode `ACCESS_KEY_OPCODE_BYTE`) which pops `index` from the top
of the stack as big-endian `uint256`, and pushes `tx.access_list[address][index]` back on the stack,
if `address` is present in the `tx.access_list` and `index &lt; len(tx.access_list[address])`,
and otherwise pushes a zeroed `bytes32` value.

### Gas costs

The opcode has a fixed gas cost of `ACCESS_KEY_OPCODE_GAS`.

The intrinsic gas costs of the access-list contents of the transaction itself do not change.

## Rationale

### Static analysis of transactions

Static declaration of contract-inputs enables advanced layer-two constructions and block-building techniques:
data is available without EVM introspection, and contracts can reliably tell if the executing transaction
declared critical properties to the block builder and verifying nodes.

Static-declaration of contract inputs is now independent of account-abstraction related changes,
such as transaction bundlers, as well as in-protocol with 3074.
&lt;!-- EIP link/requires omitted due to Walidator EIP status bug --&gt;

### Global read-only values

Akin to `TLOAD`, as described in [EIP-1153](/EIPs/EIPS/eip-1153),
the `ACCESS_KEY` opcode provides contracts with a view that is global
to the message-execution of the transaction in the EVM.

However, with `ACCESS_KEY` it is guaranteed to be read-only, and cannot change during the execution of a transaction.

### Access-list utility

Access-lists are under-utilized today:
very few users utilize this to warm-up storage interactions for reduced gas costs.
Generally the gas cost savings achieved with EIP-2930 are not applicable in as many use-cases.

With this EIP, the utility of the access-list functionality increases,
without requiring additional resources from the EVM.

### Witness data

This EIP supports the transformation of applications to reduce statefulness,
by supporting read-only application state to be provided to contracts without
requiring the contract caller to support forwarding of data.

The access-list contents may contain witness-data, which the contract can verify and utilize statelessness.

### Gas costs

The gas cost of `ACCESS_KEY_OPCODE_GAS` gas matches that of similar operations,
specifically the `BLOBHASH` opcode of [EIP-4844](/EIPs/EIPS/eip-4844):
this opcode also pop an index-like EVM word from the stack,
and pushes a full 32 byte EVM word back on the stack, based on a list of hashes embedded in the transaction.

The `BLOBHASH` functionality of [EIP-4844](/EIPs/EIPS/eip-4844) is not re-usable for the purposes of this EIP however,
as the intention is to have access to just the statically declared hash, and not the cost of a blob. 

### Naming of `ACCESS_KEY`

Access-lists currently only support a list of access-keys.
The list is not enforced to be sorted, and thus supports indexed lookups.

This is not a `LOAD` opcode, as `SLOAD` or `TLOAD` are, since the opcode returns a key.

## Backwards Compatibility

### No transaction-type changes

This enhancement of access-lists utility does not affect the access-list encoding,
or the existing transaction types that support access-lists.

### Minimal impact on EVM transaction-context

With EIP-2930, the access-list contents are already readily available in the transaction-context during EVM execution,
and the RPC methods that trigger said execution.

This EIP thus does not require significant changes to the construction of the EVM context,
nor any changes to RPC methods.

## Test Cases

The block fee-recipient, and any other warmed-up attributes not declared statically in the transaction access-list,
must not be considered to be part of the access-list.

## Security Considerations

The access-list attributes are already gas-metered in EIP-2930,
and readily accessible in the EVM to determine storage gas-costs. In terms of denial-of-service risks,
this EIP introduces no new significant data or data-processing costs.

The access-list is read-only, and thus forms a minimal risk to application-developers.

The access is scoped strictly to the contract that would otherwise perform a warm `SLOAD`,
and thus storage-layout abstractions do not leak between different smart contract applications.   

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 27 Mar 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7664</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7664</guid>
      </item>
    
      <item>
        <title>EVM-ify the identity precompile</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7561-evm-ify-the-identity-precompile/19445</comments>
        
        <description>## Abstract

Remove the identity precompile at 0x04. At the start of executing the block in which this change activates, put into that contract a short piece of EVM code that has the same functionality.

## Motivation

Ethereum today has a large number of precompiles. Nearly half of these precompiles are not seeing significant use, and are contributing to ongoing maintenance cost and risk of consensus bugs, as well as increased development effort for new Ethereum client implementations, including ZK-EVMs and implementations in formal-verification-friendly languages.

This EIP proposes a path for the Ethereum ecosystem to gracefully abandon these precompiles, and takes a first step by applying this procedure to the simplest precompile of all: the identity precompile (which outputs returndata equal to the input calldata). The identity precompile was originally introduced because memory copying is a common operation, and there was no opcode available to do it directly. Since then, norms around what is acceptable for an opcode have changed, and we have introduced the MCOPY opcode with [EIP-5656](/EIPs/EIPS/eip-5656). And so we can remove the identity precompile, and replace it with an ultra-minimal piece of EVM code that replicates its functionality.

In the future, this technique can be applied to other more complex precompiles, such as little-used hash functions and MODEXP.

## Specification

| Parameter | Value |
| - | - |
| `IDENTITY_PRECOMPILE_ADDRESS` | `0x0000....0004` |
| `EVM_CODE`    |  `0x365f5f37365ff3` |

At the start of the block in which this fork activates, set the code of `IDENTITY_PRECOMPILE_ADDRESS` to `EVM_CODE`. Starting from and including that block, `IDENTITY_PRECOMPILE_ADDRESS` should no longer be treated as a precompile.

## Rationale

The given `EVM_CODE` corresponds to

```
CALLDATASIZE PUSH0 PUSH0 CALLDATACOPY CALLDATASIZE PUSH0 RETURN
```

Which copies calldata into memory, and then returns the same memory slice. This is thus a minimally disruptive change to Ethereum that preserves functionality, and accomplishes the goal of reducing the number of precompiles by 1.

## Backwards Compatibility

The functionality of the given `EVM_CODE` is the same as the identity precompile. Gas costs are slightly different, though gas repricings have been done in the Ethereum ecosystem several times before and their effects are well understood.

## Security Considerations

As no new functionality is introduced or made cheaper, no security concerns are raised.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 31 Mar 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7666</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7666</guid>
      </item>
    
      <item>
        <title>Raise gas costs of hash functions</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7562-raise-gas-costs-of-hash-functions/19446</comments>
        
        <description>## Abstract

Raise the gas costs of opcodes and precompiles that involve hash functions.

## Motivation

Gas costs for hash function opcodes and precompiles were originally set based on the time that it takes to execute them on a regular CPU. Since then, however, there has emerged another equally important execution substrate that the EVM is executed on: zero knowledge proof (ZK-SNARK) systems. By that standard, these opcodes and precompiles are _very_ underpriced relative to other operations.

Blocks that are heavy with hash function executions take much longer to ZK-SNARK prove than average blocks. Today, many layer-2 protocols are using workarounds such as arbitrary limits and rules enforced by centralized sequencers to deal with this issue. These workarounds are often poorly designed and lead to unneeded security and centralization concerns.

Additionally, there is a design goal of eventually using ZK-SNARKs to prove the correctness of layer-1 Ethereum blocks. To do this, we need to establish very tight bounds on how long it takes to generate a ZK-SNARK proof of an Ethereum execution block&apos;s correctness. Today, the difference between average-case proving time and worst-case proving time is large, and hash function executions are the largest reason why.

Verkle trees solve the part of this problem that comes from Keccak hashing in the Merkle Patricia tree. Today, the theoretical worst case is a block with `30000000 / 2600 = 11538` account accesses (minus a small percent for EVM overhead), where proving each access would require proving `24000` bytes of code, plus a roughly `512 * log(500m) / log(16) = 3712` byte Merkle-Patricia proof: roughly `305 MB` of hashing spread between `83650` hash calls. Verkle trees solve this. However, using opcodes, a block execution can still require roughly the following amount of hashing:

| Hash | Cost per word | Maximum bytes from 30 million gas |
| - | - | - |
| `KECCAK` (opcode) | 6 | 160 million |
| `SHA256` (precompile) | 12 | 80 million |
| `RIPEMD` (precompile) | 120 | 8 million |
| `BLAKE2` (precompile) | 3 (12 per 128 bytes) | 320 million |
| `LOG*` (hashing data) | 256 (8 per byte) | 3.75 million | 

These hash functions have been optimized for rapid CPU computation, so CPUs can compute them quickly: for example, this author&apos;s laptop can compute a 160-million byte keccak in less than half a second. In ZK-SNARKs, however, these operations are _very_ time-consuming and inefficient. This is mitigated in newer proof systems based on small fields, but hashes remain underpriced.

## Specification

| Parameter | Previous value | New value | 
| - | - | - |
| `KECCAK_BASE_COST` | 30 | 300 |
| `KECCAK_WORD_COST` | 6 | 60 |
| `SHA256_BASE_COST` | 60 | 300 |
| `SHA256_WORD_COST` | 12 | 60 |
| `RIPEMD_BASE_COST` | 600 | 600 |
| `RIPEMD_WORD_COST` | 120 | 120 |
| `BLAKE2_GFROUND` | 1 | 10 |
| `GLOGBYTE` | 8 | 10 |

Change the above parameters to their new values.

## Rationale

The above increases the gas costs of all opcodes and precompiles that can be used to require large amounts of hashing in the EVM. All hashing costs are increased to 300 per hash plus 60 per word (or kept the same if they are already higher than this).
&apos;&quot;
A possible alternative to this approach is to implement either multidimensional gas pricing (ie. a separate floating basefee and per-block target and limit for hashes) or a &quot;total gas cost floor&quot; similar to what [EIP-7623](/EIPs/EIPS/eip-7623) does for calldata. However, this approach is much harder to implement for in-EVM gas costs such as hashes than it is for calldata and blobs, because EVM gas limits are set not just by users, for whom new transaction types that specify newly required limits, max-basefees and priority fees can easily be added, but also by contracts making sub-calls to other contracts.

## Backwards Compatibility

For most applications, a reasonable upper bound is that data that is getting hashed in the EVM is getting brought in as calldata. If the hashing being done is binary Merkle proof verification, every 32 bytes of data corresponds to a 64-byte (2-word) hash. A word of costs 512 gas. Under the new costs, the hashing per word in that situation would be `300 + 60 * 2 = 420` gas. Hence, this will increase gas consumption for that component of the application by less than 2x.

Concretely, a length-20 Keccak-based binary Merkle proof gas cost would increase from `(512 + 42) * 20 = 11080` to `(512 + 420) * 20 = 18640`. This is a small increase, especially taking into account other costs associated with such an application.

## Security Considerations

As no new operations are introduced or made cheaper, no security concerns were raised.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 31 Mar 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7667</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7667</guid>
      </item>
    
      <item>
        <title>Remove bloom filters</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7653-remove-bloom-filters/19447</comments>
        
        <description>## Abstract

Require the bloom filters in an execution block, including at the top level and in the receipt object, to be empty.

## Motivation

Logs were originally introduced to give applications a way to record information about onchain events, which decentralized applications (dapps) would be able to easily query. Using bloom filters, dapps would be able to quickly go through the history, identify the few blocks that contained logs relative to their application, and then quickly identify which individual transactions have the logs that they need.

In practice, this mechanism is far too slow. Almost all dapps that access history end up doing so not through RPC calls to an Ethereum node (even a remote-hosted one), but through centralized extra-protocol services.

This EIP proposes recognizing that reality, and removing bloom filters from the protocol. Applications that need history querying would be encouraged to develop and use decentralized protocols that create provable log indexes using eg. ZK-SNARKs and incrementally-verifiable computation.

## Specification

The logs bloom of an execution block is now required to be empty (ie. 0 bytes long). The logs bloom of a transaction receipt is now required to be empty (ie. 0 bytes long).

## Rationale

This is a minimally disruptive way to remove the need to handle blooms from clients. A future EIP can later clean up by removing this field entirely, along with other fields that have been deprecated.

Gas costs of LOG are not reduced, because while the externality of polluting the bloom filter no longer needs to be accounted for, the costs of hashing have increased due to the needs of ZK-SNARK EVM implementations.

## Backwards Compatibility

Applications that depend on bloom filters to read events will cease to work. Very few applications depend on this feature today, because at current gas limits the false positive rate is so high and processing the logs in a long history query is so slow, especially for light clients (whom this feature was primarily intended to benefit).

## Security Considerations

As no new features are introduced or made cheaper, no security concerns are raised.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 31 Mar 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7668</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7668</guid>
      </item>
    
      <item>
        <title>Distinguishable base256emoji Addresses</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7673-distinguishable-account-addresses/19461</comments>
        
        <description>## Abstract

Introduce base256emoji for use as the primary input and display for account addresses in all user interfaces.

## Motivation

Human users often fail to distinguish between long strings of hexadecimal characters, especially when they match at the beginning and at the end.
This makes hexadecimal strings a poor format for human-readable account addresses.
The problem is being exploited by several spoofing strategies that mine similar addresses and spoof [ERC-20](/EIPs/EIPS/eip-20) Transfer events with the goal of tricking the end user into copying the wrong recipient address.
These address spoofing attacks have mislead tens of thousands of ether, and countless other tokens.
Spoofers flooding the network with fake Transfer events waste network resources and complicate blockchain accounting.
Improving the distinguishability of addresses will reduce the incentives for this behavior.

## Specification

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

User interfaces:
- SHALL depict account addresses as a base256emoji string instead of hexadecimal.
- SHALL accept base256emoji strings as input for user-supplied account address parameters.
- SHOULD recognize and interpret strings of exactly 20 consecutive emoji as addresses when all of them are valid base256emoji.

### base256emoji encoding table

| Emoji | Unicode codepoint | Byte Value |
|:-:|:-:|:-:|
| 🚀 | U+1F680 | 0 |
| 🪐 | U+1FA90 | 1 |
| ☄ | U+2604 | 2 |
| 🛰 | U+1F6F0 | 3 |
| 🌌 | U+1F30C | 4 |
| 🌑 | U+1F311 | 5 |
| 🌒 | U+1F312 | 6 |
| 🌓 | U+1F313 | 7 |
| 🌔 | U+1F314 | 8 |
| 🌕 | U+1F315 | 9 |
| 🌖 | U+1F316 | 10 |
| 🌗 | U+1F317 | 11 |
| 🌘 | U+1F318 | 12 |
| 🌍 | U+1F30D | 13 |
| 🌏 | U+1F30F | 14 |
| 🌎 | U+1F30E | 15 |
| 🐉 | U+1F409 | 16 |
| ☀ | U+2600 | 17 |
| 💻 | U+1F4BB | 18 |
| 🖥 | U+1F5A5 | 19 |
| 💾 | U+1F4BE | 20 |
| 💿 | U+1F4BF | 21 |
| 😂 | U+1F602 | 22 |
| ❤ | U+2764 | 23 |
| 😍 | U+1F60D | 24 |
| 🤣 | U+1F923 | 25 |
| 😊 | U+1F60A | 26 |
| 🙏 | U+1F64F | 27 |
| 💕 | U+1F495 | 28 |
| 😭 | U+1F62D | 29 |
| 😘 | U+1F618 | 30 |
| 👍 | U+1F44D | 31 |
| 😅 | U+1F605 | 32 |
| 👏 | U+1F44F | 33 |
| 😁 | U+1F601 | 34 |
| 🔥 | U+1F525 | 35 |
| 🥰 | U+1F970 | 36 |
| 💔 | U+1F494 | 37 |
| 💖 | U+1F496 | 38 |
| 💙 | U+1F499 | 39 |
| 😢 | U+1F622 | 40 |
| 🤔 | U+1F914 | 41 |
| 😆 | U+1F606 | 42 |
| 🙄 | U+1F644 | 43 |
| 💪 | U+1F4AA | 44 |
| 😉 | U+1F609 | 45 |
| ☺ | U+263A | 46 |
| 👌 | U+1F44C | 47 |
| 🤗 | U+1F917 | 48 |
| 💜 | U+1F49C | 49 |
| 😔 | U+1F614 | 50 |
| 😎 | U+1F60E | 51 |
| 😇 | U+1F607 | 52 |
| 🌹 | U+1F339 | 53 |
| 🤦 | U+1F926 | 54 |
| 🎉 | U+1F389 | 55 |
| 💞 | U+1F49E | 56 |
| ✌ | U+270C | 57 |
| ✨ | U+2728 | 58 |
| 🤷 | U+1F937 | 59 |
| 😱 | U+1F631 | 60 |
| 😌 | U+1F60C | 61 |
| 🌸 | U+1F338 | 62 |
| 🙌 | U+1F64C | 63 |
| 😋 | U+1F60B | 64 |
| 💗 | U+1F497 | 65 |
| 💚 | U+1F49A | 66 |
| 😏 | U+1F60F | 67 |
| 💛 | U+1F49B | 68 |
| 🙂 | U+1F642 | 69 |
| 💓 | U+1F493 | 70 |
| 🤩 | U+1F929 | 71 |
| 😄 | U+1F604 | 72 |
| 😀 | U+1F600 | 73 |
| 🖤 | U+1F5A4 | 74 |
| 😃 | U+1F603 | 75 |
| 💯 | U+1F4AF | 76 |
| 🙈 | U+1F648 | 77 |
| 👇 | U+1F447 | 78 |
| 🎶 | U+1F3B6 | 79 |
| 😒 | U+1F612 | 80 |
| 🤭 | U+1F92D | 81 |
| ❣ | U+2763 | 82 |
| 😜 | U+1F61C | 83 |
| 💋 | U+1F48B | 84 |
| 👀 | U+1F440 | 85 |
| 😪 | U+1F62A | 86 |
| 😑 | U+1F611 | 87 |
| 💥 | U+1F4A5 | 88 |
| 🙋 | U+1F64B | 89 |
| 😞 | U+1F61E | 90 |
| 😩 | U+1F629 | 91 |
| 😡 | U+1F621 | 92 |
| 🤪 | U+1F92A | 93 |
| 👊 | U+1F44A | 94 |
| 🥳 | U+1F973 | 95 |
| 😥 | U+1F625 | 96 |
| 🤤 | U+1F924 | 97 |
| 👉 | U+1F449 | 98 |
| 💃 | U+1F483 | 99 |
| 😳 | U+1F633 | 100 |
| ✋ | U+270B | 101 |
| 😚 | U+1F61A | 102 |
| 😝 | U+1F61D | 103 |
| 😴 | U+1F634 | 104 |
| 🌟 | U+1F31F | 105 |
| 😬 | U+1F62C | 106 |
| 🙃 | U+1F643 | 107 |
| 🍀 | U+1F340 | 108 |
| 🌷 | U+1F337 | 109 |
| 😻 | U+1F63B | 110 |
| 😓 | U+1F613 | 111 |
| ⭐ | U+2B50 | 112 |
| ✅ | U+2705 | 113 |
| 🥺 | U+1F97A | 114 |
| 🌈 | U+1F308 | 115 |
| 😈 | U+1F608 | 116 |
| 🤘 | U+1F918 | 117 |
| 💦 | U+1F4A6 | 118 |
| ✔ | U+2714 | 119 |
| 😣 | U+1F623 | 120 |
| 🏃 | U+1F3C3 | 121 |
| 💐 | U+1F490 | 122 |
| ☹ | U+2639 | 123 |
| 🎊 | U+1F38A | 124 |
| 💘 | U+1F498 | 125 |
| 😠 | U+1F620 | 126 |
| ☝ | U+261D | 127 |
| 😕 | U+1F615 | 128 |
| 🌺 | U+1F33A | 129 |
| 🎂 | U+1F382 | 130 |
| 🌻 | U+1F33B | 131 |
| 😐 | U+1F610 | 132 |
| 🖕 | U+1F595 | 133 |
| 💝 | U+1F49D | 134 |
| 🙊 | U+1F64A | 135 |
| 😹 | U+1F639 | 136 |
| 🗣 | U+1F5E3 | 137 |
| 💫 | U+1F4AB | 138 |
| 💀 | U+1F480 | 139 |
| 👑 | U+1F451 | 140 |
| 🎵 | U+1F3B5 | 141 |
| 🤞 | U+1F91E | 142 |
| 😛 | U+1F61B | 143 |
| 🔴 | U+1F534 | 144 |
| 😤 | U+1F624 | 145 |
| 🌼 | U+1F33C | 146 |
| 😫 | U+1F62B | 147 |
| ⚽ | U+26BD | 148 |
| 🤙 | U+1F919 | 149 |
| ☕ | U+2615 | 150 |
| 🏆 | U+1F3C6 | 151 |
| 🤫 | U+1F92B | 152 |
| 👈 | U+1F448 | 153 |
| 😮 | U+1F62E | 154 |
| 🙆 | U+1F646 | 155 |
| 🍻 | U+1F37B | 156 |
| 🍃 | U+1F343 | 157 |
| 🐶 | U+1F436 | 158 |
| 💁 | U+1F481 | 159 |
| 😲 | U+1F632 | 160 |
| 🌿 | U+1F33F | 161 |
| 🧡 | U+1F9E1 | 162 |
| 🎁 | U+1F381 | 163 |
| ⚡ | U+26A1 | 164 |
| 🌞 | U+1F31E | 165 |
| 🎈 | U+1F388 | 166 |
| ❌ | U+274C | 167 |
| ✊ | U+270A | 168 |
| 👋 | U+1F44B | 169 |
| 😰 | U+1F630 | 170 |
| 🤨 | U+1F928 | 171 |
| 😶 | U+1F636 | 172 |
| 🤝 | U+1F91D | 173 |
| 🚶 | U+1F6B6 | 174 |
| 💰 | U+1F4B0 | 175 |
| 🍓 | U+1F353 | 176 |
| 💢 | U+1F4A2 | 177 |
| 🤟 | U+1F91F | 178 |
| 🙁 | U+1F641 | 179 |
| 🚨 | U+1F6A8 | 180 |
| 💨 | U+1F4A8 | 181 |
| 🤬 | U+1F92C | 182 |
| ✈ | U+2708 | 183 |
| 🎀 | U+1F380 | 184 |
| 🍺 | U+1F37A | 185 |
| 🤓 | U+1F913 | 186 |
| 😙 | U+1F619 | 187 |
| 💟 | U+1F49F | 188 |
| 🌱 | U+1F331 | 189 |
| 😖 | U+1F616 | 190 |
| 👶 | U+1F476 | 191 |
| 🥴 | U+1F974 | 192 |
| ▶ | U+25B6 | 193 |
| ➡ | U+27A1 | 194 |
| ❓ | U+2753 | 195 |
| 💎 | U+1F48E | 196 |
| 💸 | U+1F4B8 | 197 |
| ⬇ | U+2B07 | 198 |
| 😨 | U+1F628 | 199 |
| 🌚 | U+1F31A | 200 |
| 🦋 | U+1F98B | 201 |
| 😷 | U+1F637 | 202 |
| 🕺 | U+1F57A | 203 |
| ⚠ | U+26A0 | 204 |
| 🙅 | U+1F645 | 205 |
| 😟 | U+1F61F | 206 |
| 😵 | U+1F635 | 207 |
| 👎 | U+1F44E | 208 |
| 🤲 | U+1F932 | 209 |
| 🤠 | U+1F920 | 210 |
| 🤧 | U+1F927 | 211 |
| 📌 | U+1F4CC | 212 |
| 🔵 | U+1F535 | 213 |
| 💅 | U+1F485 | 214 |
| 🧐 | U+1F9D0 | 215 |
| 🐾 | U+1F43E | 216 |
| 🍒 | U+1F352 | 217 |
| 😗 | U+1F617 | 218 |
| 🤑 | U+1F911 | 219 |
| 🌊 | U+1F30A | 220 |
| 🤯 | U+1F92F | 221 |
| 🐷 | U+1F437 | 222 |
| ☎ | U+260E | 223 |
| 💧 | U+1F4A7 | 224 |
| 😯 | U+1F62F | 225 |
| 💆 | U+1F486 | 226 |
| 👆 | U+1F446 | 227 |
| 🎤 | U+1F3A4 | 228 |
| 🙇 | U+1F647 | 229 |
| 🍑 | U+1F351 | 230 |
| ❄ | U+2744 | 231 |
| 🌴 | U+1F334 | 232 |
| 💣 | U+1F4A3 | 233 |
| 🐸 | U+1F438 | 234 |
| 💌 | U+1F48C | 235 |
| 📍 | U+1F4CD | 236 |
| 🥀 | U+1F940 | 237 |
| 🤢 | U+1F922 | 238 |
| 👅 | U+1F445 | 239 |
| 💡 | U+1F4A1 | 240 |
| 💩 | U+1F4A9 | 241 |
| 👐 | U+1F450 | 242 |
| 📸 | U+1F4F8 | 243 |
| 👻 | U+1F47B | 244 |
| 🤐 | U+1F910 | 245 |
| 🤮 | U+1F92E | 246 |
| 🎼 | U+1F3BC | 247 |
| 🥵 | U+1F975 | 248 |
| 🚩 | U+1F6A9 | 249 |
| 🍎 | U+1F34E | 250 |
| 🍊 | U+1F34A | 251 |
| 👼 | U+1F47C | 252 |
| 💍 | U+1F48D | 253 |
| 📣 | U+1F4E3 | 254 |
| 🥂 | U+1F942 | 255 |

## Rationale

Previous attempts to reduce spoofing and other copy errors such as [ERC-55](/EIPs/EIPS/eip-55) have not reduced the number of characters in an address.
Any base-256 standard would achieve this goal but emoji were chosen to maximize human-distinguishability.
Multiple base-256 emoji encodings have been proposed.
The base256emoji encoding was chosen due to its acceptance into the multibase repository.

This standard does not also recommend base256emoji for use in depicting other bytestrings such as transaction hashes and calldata. 
Transaction hashes are not yet being spoofed.
Calldata is best decoded via the appropriate ABI.
By only using base256emoji for addresses, addresses can be easily noticed among other information.

## Backwards Compatibility

Using the encoding table, the base256emoji encoding can be transcoded into hexadecimal and vice-versa.

## Test Cases

| base256emoji | ERC-55 |
|:-:|:-:|
|🚀🚀🚀🚀🚀🚀😀💓🥴💣👻🙌🙈🤢😥☹🌏💩🍎💕|`0x0000000000004946c0e9F43F4Dee607b0eF1fA1c`|
|🚀🚀🚀🚀🚀🚀💸🎊💡🌿🚩🔥📌🙂💙❄🛰💩🤝⭐|`0x000000000000c57CF0A1f923d44527e703F1ad70`|
|☀☀☀☀☀❤🌊🌖❌💀✔🌎🎈❌💞🛰💗😅❓☄|`0x111111111117dC0aa78b770fA6A738034120C302`|
|👍🤫😋✊🤪😞🤐👶😭❤👉🚩💔🌱🤝🌊💚🪐🚩😐|`0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984`|
|😆🌎✅✨👋😜💛☺😶👋🐸🤩🌔🙌✋🤤⭐🍑☹⚡|`0x2a0f713aA953442EacA9EA47083f656170e67BA4`|
|🔥🤬🌔😝😞🙄👌💢🗣🌍✨😙🐾😡😑🤘💸😂😤🔵|`0x23B608675a2B2fB1890d3ABBd85c5775c51691d5`|
|🗣😅😞✨🤷😆🌟🐷🌷👶☝🪐🥀🖥🤟🐉💀💪😏❄|`0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7`|
|🥴😆😰✌🤟🔥📣🎵🌖🌏😡🎶💙🐸🍒🌔😱🤘🍀➡|`0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2`|
|▶🌻😥👏💘😛💐💨❄💸😂😪😝🤤🐸💻😟☝🍃🥺|`0xC18360217D8F7Ab5e7c516566761Ea12Ce7F9D72`|


## Reference Implementation

```python3
to_emoji = [
    &apos;🚀&apos;, &apos;🪐&apos;, &apos;☄&apos;, &apos;🛰&apos;, &apos;🌌&apos;, &apos;🌑&apos;, &apos;🌒&apos;, &apos;🌓&apos;, &apos;🌔&apos;, &apos;🌕&apos;, &apos;🌖&apos;, &apos;🌗&apos;, &apos;🌘&apos;, &apos;🌍&apos;, &apos;🌏&apos;, &apos;🌎&apos;,
    &apos;🐉&apos;, &apos;☀&apos;, &apos;💻&apos;, &apos;🖥&apos;, &apos;💾&apos;, &apos;💿&apos;, &apos;😂&apos;, &apos;❤&apos;, &apos;😍&apos;, &apos;🤣&apos;, &apos;😊&apos;, &apos;🙏&apos;, &apos;💕&apos;, &apos;😭&apos;, &apos;😘&apos;, &apos;👍&apos;,
    &apos;😅&apos;, &apos;👏&apos;, &apos;😁&apos;, &apos;🔥&apos;, &apos;🥰&apos;, &apos;💔&apos;, &apos;💖&apos;, &apos;💙&apos;, &apos;😢&apos;, &apos;🤔&apos;, &apos;😆&apos;, &apos;🙄&apos;, &apos;💪&apos;, &apos;😉&apos;, &apos;☺&apos;, &apos;👌&apos;,
    &apos;🤗&apos;, &apos;💜&apos;, &apos;😔&apos;, &apos;😎&apos;, &apos;😇&apos;, &apos;🌹&apos;, &apos;🤦&apos;, &apos;🎉&apos;, &apos;💞&apos;, &apos;✌&apos;, &apos;✨&apos;, &apos;🤷&apos;, &apos;😱&apos;, &apos;😌&apos;, &apos;🌸&apos;, &apos;🙌&apos;,
    &apos;😋&apos;, &apos;💗&apos;, &apos;💚&apos;, &apos;😏&apos;, &apos;💛&apos;, &apos;🙂&apos;, &apos;💓&apos;, &apos;🤩&apos;, &apos;😄&apos;, &apos;😀&apos;, &apos;🖤&apos;, &apos;😃&apos;, &apos;💯&apos;, &apos;🙈&apos;, &apos;👇&apos;, &apos;🎶&apos;,
    &apos;😒&apos;, &apos;🤭&apos;, &apos;❣&apos;, &apos;😜&apos;, &apos;💋&apos;, &apos;👀&apos;, &apos;😪&apos;, &apos;😑&apos;, &apos;💥&apos;, &apos;🙋&apos;, &apos;😞&apos;, &apos;😩&apos;, &apos;😡&apos;, &apos;🤪&apos;, &apos;👊&apos;, &apos;🥳&apos;,
    &apos;😥&apos;, &apos;🤤&apos;, &apos;👉&apos;, &apos;💃&apos;, &apos;😳&apos;, &apos;✋&apos;, &apos;😚&apos;, &apos;😝&apos;, &apos;😴&apos;, &apos;🌟&apos;, &apos;😬&apos;, &apos;🙃&apos;, &apos;🍀&apos;, &apos;🌷&apos;, &apos;😻&apos;, &apos;😓&apos;,
    &apos;⭐&apos;, &apos;✅&apos;, &apos;🥺&apos;, &apos;🌈&apos;, &apos;😈&apos;, &apos;🤘&apos;, &apos;💦&apos;, &apos;✔&apos;, &apos;😣&apos;, &apos;🏃&apos;, &apos;💐&apos;, &apos;☹&apos;, &apos;🎊&apos;, &apos;💘&apos;, &apos;😠&apos;, &apos;☝&apos;,
    &apos;😕&apos;, &apos;🌺&apos;, &apos;🎂&apos;, &apos;🌻&apos;, &apos;😐&apos;, &apos;🖕&apos;, &apos;💝&apos;, &apos;🙊&apos;, &apos;😹&apos;, &apos;🗣&apos;, &apos;💫&apos;, &apos;💀&apos;, &apos;👑&apos;, &apos;🎵&apos;, &apos;🤞&apos;, &apos;😛&apos;,
    &apos;🔴&apos;, &apos;😤&apos;, &apos;🌼&apos;, &apos;😫&apos;, &apos;⚽&apos;, &apos;🤙&apos;, &apos;☕&apos;, &apos;🏆&apos;, &apos;🤫&apos;, &apos;👈&apos;, &apos;😮&apos;, &apos;🙆&apos;, &apos;🍻&apos;, &apos;🍃&apos;, &apos;🐶&apos;, &apos;💁&apos;,
    &apos;😲&apos;, &apos;🌿&apos;, &apos;🧡&apos;, &apos;🎁&apos;, &apos;⚡&apos;, &apos;🌞&apos;, &apos;🎈&apos;, &apos;❌&apos;, &apos;✊&apos;, &apos;👋&apos;, &apos;😰&apos;, &apos;🤨&apos;, &apos;😶&apos;, &apos;🤝&apos;, &apos;🚶&apos;, &apos;💰&apos;,
    &apos;🍓&apos;, &apos;💢&apos;, &apos;🤟&apos;, &apos;🙁&apos;, &apos;🚨&apos;, &apos;💨&apos;, &apos;🤬&apos;, &apos;✈&apos;, &apos;🎀&apos;, &apos;🍺&apos;, &apos;🤓&apos;, &apos;😙&apos;, &apos;💟&apos;, &apos;🌱&apos;, &apos;😖&apos;, &apos;👶&apos;,
    &apos;🥴&apos;, &apos;▶&apos;, &apos;➡&apos;, &apos;❓&apos;, &apos;💎&apos;, &apos;💸&apos;, &apos;⬇&apos;, &apos;😨&apos;, &apos;🌚&apos;, &apos;🦋&apos;, &apos;😷&apos;, &apos;🕺&apos;, &apos;⚠&apos;, &apos;🙅&apos;, &apos;😟&apos;, &apos;😵&apos;,
    &apos;👎&apos;, &apos;🤲&apos;, &apos;🤠&apos;, &apos;🤧&apos;, &apos;📌&apos;, &apos;🔵&apos;, &apos;💅&apos;, &apos;🧐&apos;, &apos;🐾&apos;, &apos;🍒&apos;, &apos;😗&apos;, &apos;🤑&apos;, &apos;🌊&apos;, &apos;🤯&apos;, &apos;🐷&apos;, &apos;☎&apos;,
    &apos;💧&apos;, &apos;😯&apos;, &apos;💆&apos;, &apos;👆&apos;, &apos;🎤&apos;, &apos;🙇&apos;, &apos;🍑&apos;, &apos;❄&apos;, &apos;🌴&apos;, &apos;💣&apos;, &apos;🐸&apos;, &apos;💌&apos;, &apos;📍&apos;, &apos;🥀&apos;, &apos;🤢&apos;, &apos;👅&apos;,
    &apos;💡&apos;, &apos;💩&apos;, &apos;👐&apos;, &apos;📸&apos;, &apos;👻&apos;, &apos;🤐&apos;, &apos;🤮&apos;, &apos;🎼&apos;, &apos;🥵&apos;, &apos;🚩&apos;, &apos;🍎&apos;, &apos;🍊&apos;, &apos;👼&apos;, &apos;💍&apos;, &apos;📣&apos;, &apos;🥂&apos;
]
from_emoji = {emoji: &quot;{0:02x}&quot;.format(i) for i, emoji in enumerate(to_emoji)}

def encode_address(hexadecimal_address):
    if len(hexadecimal_address) != 42 or not hexadecimal_address.startswith(&apos;0x&apos;):
        return None
    return &apos;&apos;.join([to_emoji[int(hexadecimal_address[i:i+2], 16)] for i in range(2, 42, 2)])


def decode_address(emoji_address):
    # In python, these unicode characters all have a len() of 1
    if len(emoji_address) != 20:
        return None
    try:
        return &apos;0x&apos; + &apos;&apos;.join(from_emoji[emoji] for emoji in emoji_address)
    except IndexError:
        return None
```

## Security Considerations

With the base256emoji encoding, addresses use half as many characters.
The characters used are more distinguishable.
This squares the difficulty of generating similar addresses, making address spoofing impractical.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 01 Apr 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7673</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7673</guid>
      </item>
    
      <item>
        <title>Temporary Approval Extension for ERC-20</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/add-erc-7674-transient-approval-extension-for-erc-20/19521</comments>
        
        <description>## Abstract

This specification defines the minimum interface required to temporarily approve [ERC-20](/EIPs/EIPS/eip-20) tokens for spending within the same transaction.

## Motivation

User are often required to set a token approval that will only be used once. It is common to leave unexpected approvals after these interactions. [EIP-1153](/EIPs/EIPS/eip-1153) introduces `TSTORE`, which can be used to efficiently handle temporarily allowances.

## Specification

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

Compliant contracts MUST implement 1 new function in addition to [ERC-20](/EIPs/EIPS/eip-20):

```solidity
function temporaryApprove(address spender, uint256 value) public returns (bool success)
```

A call to `temporaryApprove(spender, value)` allows `spender` to withdraw within the same transaction on behalf of `msg.sender` multiple times, such that the total withdrawn is less than or equal to the `value` amount.  This temporary allowance is to be considered in addition to the normal (persistent) [ERC-20](/EIPs/EIPS/eip-20) allowance. The total value that spender is able to spend during the transaction is thus capped by the sum of the temporary and the normal (persistent) allowances. While it SHOULD be possible for a `transferFrom` operation to consume both types of allowance, the consumption of the temporary allowance SHOULD take priority over the consumption of the persistent allowance. Therefore, if the temporary allowance is sufficient for executing a `transferFrom` operation, the persistent allowance SHOULD not be loaded/updated from the storage. Consumption of persistent allowance, which implies storage accesses, SHOULD be performed only if the temporary allowance is not sufficient for the operation being executed.

Each temporary allowance MUST persist until the end of the transaction that created it (unless overwritten by another call to `temporaryApprove` or consumed by a call to `transferFrom`). Each temporary allowance MUST be cleared at the end of the transaction that created it. See [Using Transient Storage](#using-transient-storage) for an example.

Compliant contracts MUST add a temporary allowance to the permanent one when returning the allowed amount to spend in the `allowance` function. In case the sum of the temporary and permanent allowance overflow, `type(uint256).max` MUST be returned.

## Rationale

It was decided to make minimal interface extension to allow easier integration of a compliant contract into the existing infrastructure. This affects the backward compatibility of the `allowance` function. However, the required changes to the `transferFrom` function implementation satisfy the requirement to explicitly authorize the spender to transfer tokens.

## Backwards Compatibility

All functionality of the [ERC-20](/EIPs/EIPS/eip-20) standard is backward compatible except for the `allowance` function.

## Reference Implementation

### Using Transient Storage

The storage for the temporary allowances must be different to that of the regular allowance. Compliant contracts may use the transient storage [EIP-1153](/EIPs/EIPS/eip-1153) to keep the temporary allowance. For each `owner` and `spender`, the slot should be uniquely selected to avoid slot collision. Each slot index should be derived from the base slot index for temporary allowances, `owner` and `spender` addresses. Slot may be derived as `keccak256(spender . keccak256(owner . p))` where `.` is concatenation and `p` is `keccak256` from the string uniquely defining temporary allowances in the namespace of the implementing contract.

### Events

Even though no event is required when setting a temporary allowance, compliant contracts may emit `TransientApproval(address indexed owner, address indexed spender, uint256 value)` event.

## Security Considerations

The method of deriving slot identifiers to store temporary allowances must avoid collision with other slots in the same space (e.g. transient storage).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 02 Apr 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7674</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7674</guid>
      </item>
    
      <item>
        <title>Retroactively Included EIPs</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7675-retroactively-included-eips/19541</comments>
        
        <description>## Abstract

This Meta EIP lists Core EIPs introducing changes to Ethereum&apos;s consensus which were activated independently of an Ethereum hard fork due to their backward compatible nature. These EIPs generally introduce constraints to underspecified protocol rules  or clarify how certain edge cases should be handled. 

## Motivation

To maintain consensus across all nodes, backward incompatible changes to Ethereum must be activated synchronously. Given the coordination required for this, changes are usually bundled together in network upgrades. A Meta EIP is typically used to list the changes included in a network upgrade, as well as its activation time.

However, backward compatible consensus changes do not require a network upgrade to be activated. For example, if a consensus rule is underspecified, an EIP can propose a constraint to bound it. If the constraint was never broken in Ethereum&apos;s history and is unlikely to be broken in the future, the EIP can be considered backward compatible. It could then be &quot;retroactively activated&quot;, as both nodes which support the change and those which do not would agree on the current network state and history. 

This Meta EIP lists all such EIPs which core developers have retroactively included as part of the Ethereum protocol specification. 

## Specification

### Retroactively Activated EIPs 

* [EIP-2681](/EIPs/EIPS/eip-2681): Limit account nonce to 2^64-1
* [EIP-3607](/EIPs/EIPS/eip-3607): Reject transactions from senders with deployed code
* [EIP-4803](/EIPs/EIPS/eip-4803): Limit transaction gas to a maximum of 2^63-1
* [EIP-7523](/EIPs/EIPS/eip-7523): Empty accounts deprecation
* [EIP-7610](/EIPs/EIPS/eip-7610): Revert creation in case of non-empty storage

### Activation 

All EIPs listed above are considered activated as of Ethereum&apos;s genesis block. Note that EIP-7523 distinguishes pre- and post-merge behavior on the Ethereum mainnet. 

## Rationale

This Meta EIP provides a global view of all changes included in the Ethereum protocol without an explicit network upgrade, as well as links to full specification. 

## Backwards Compatibility

No backward compatibility issues found.

## Security Considerations

None.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 04 Apr 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7675</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7675</guid>
      </item>
    
      <item>
        <title>EOF - Prepare for Address Space Extension</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eof-prepare-for-address-space-extension/19537</comments>
        
        <description>## Abstract

Operations in the Legacy EVM trim off the top 12 bytes of an address operand before evaluation. This
EIP changes the handling of those opcodes within EOF so that no trimming occurs and the top twelve
bytes need to be zero or an exceptional halt is raised.

## Motivation

There have been proposals to extend Ethereum Addresses from 160 bits to 256, such as one that would
use the extra bits for state expiry (such as the ethereum magicians forum topic &quot;Increasing the
address size from 20 to 32 bytes&quot;). One issue ground the work to a halt: EVM opcodes that accept
addresses trim all but the lowest 20 bytes out from the operand before processing. EVM Reference
tests verify this behavior in the &apos;stBadOpcode/invalidAddr.json&apos; tests.

The EVM Object Format presents an opportunity to remove this address masking in a backwards
compatible way, by baking it into the format definition from the start.

Most of the work is already in place. The following 5 operations have already been banned from
EOF: `EXTCODESIZE`, `EXTCODECOPY`, `EXTCODEHASH`, `CALLCODE`, and `SELFDESTRUCT`. Three call
operations, `CALL`, `DELEGATECALL`, and `STATICCALL` are being revamped
in [EIP-7069](/EIPs/EIPS/eip-7069). That leaves only one operation, `BALANCE`, with issues.

When future uses of address space extension are specified it is expected that the exceptional halt
behavior will be modified.

## Specification

We introduce one new instruction:

- `EXTBALANCE` (`tbd`) with arguments `(target_address)`, returning `balance`

`EXTBALANCE` will pop one stack item off of the stack, the address of another account or contract.
The balance of that account or contract will be pushed onto the stack.

If `EXTBALANCE` is invoked with any of the high 12 bytes in `target_address` set to a non-zero value
the operation will cause an exceptional halt. All gas in the current frame will be consumed on
failure, no gas schedule change is needed.

The gas cost of `EXTBALANCE` will be costed according to the gas schedule for the `BALANCE`
operation specified in [EIP-2929](/EIPs/EIPS/eip-2929). This means if the account is not
in `accessed_addresses` then it is charged 2600 gas and added to `accessed_addresses`. If the
account is in `accessed_addresses` then 100 gas is charged. The `accessed_addresses` is shared with
all other operands described in [EIP-2929](./eip-2929).

Also, for the `EXTCALL`, `EXTDELEGATECALL`, and `EXTSTATICCALL` operations a new step is added just
before the memory expansion check: halt with exceptional failure if any of the high 96 bits of
the `target_address` are set.

It is anticipated that future EIPs will alter the behavior in a way that will not result in an
exceptional halt. Contract implementors should not depend on the exceptional halt.

## Rationale

### New Opcode

There is no need to ban the `BALANCE` opcode as it does not cause any problems that would require
banning it within an EOF container. Adding a new opcode also allows the existing opcode to behave
the same in EOF and legacy code, reducing potential friction points for end user confusion and bugs.

### Revert on invalid address

There are two alternative ways to handle accounts with high bits set. The specification calls for
an exceptional halt, but the alternative was to treat the account as empty. The reason the &quot;empty
account&quot; approach was rejected is twofold:

- The `accessed_addresses` list could be required to track 256 bit accounts when an invalid address
  is accessed.
- The `EXTCALL` series instructions could still send balance to those addresses and such accounts
  would then hold an (inaccessible) balance that would need to be reflected in the merkle trie.

### No change in gas costing

Because the BALANCE operation already needs to check `accessed_addresses` there is already a good
amount of processing that must go into the operation. Hence, no changes to the gas schedule are
needed to prevent abuse of the failures. Such incremental costs will be dominated by costs related
to reverts and address checking for valid accounts.

## Backwards Compatibility

Preparing for Address Space Expansion is explicitly done inside the scope of EOF with the intent
that it will not require changes in old contracts, but with the caveat that old contracts may not be
able to use addresses in the expanded space.

Future EIPs should be mindful when adding new operation with an address operand or parameter to how
it interacts with EOF and legacy contracts. Authors should ensure that such additions remain in
harmony with this EIP.

## Test Cases

Test cases similar to `invalidAddr.json`  tests in the standard reference tests will need to be
written for the EOF tests, except they would check for halts on invalid addresses.

## Reference Implementation

TBD &lt;!-- TODO --&gt;

## Security Considerations

This EIP only defines a revert behavior for previously stripped addresses. Compilers will need to be
aware of the need to mask addresses coming in from call data. Some of this is already present in
existing Solidity ABI standards, but more care should be taken in examining the flow
around `EXTBALANCE` and code for `EXTCALL` operations to ensure that compiled code strips the high
bytes.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 03 Apr 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7676</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7676</guid>
      </item>
    
      <item>
        <title>Paymaster Web Service Capability</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7677-paymaster-web-service-capability/19530</comments>
        
        <description>## Abstract

With [EIP-5792](/EIPs/EIPS/eip-5792), apps can communicate with wallets about advanced features via capabilities. This proposal defines a capability that allows apps to request that [ERC-4337](/EIPs/EIPS/eip-4337) wallets communicate with a specified paymaster web service. To support this, we also define a standardized API for paymaster web services.

## Motivation

App developers want to start sponsoring their users&apos; transactions using paymasters. Paymasters are commonly used via web services. However, there is currently no way for apps to tell wallets to communicate with a specific paymaster web service. Similarly, there is no standard for how wallets should communicate with these services. We need both a way for apps to tell wallets to communicate with a specific paymaster web service and a communication standard for wallets to do so.

## Specification

One new [EIP-5792](/EIPs/EIPS/eip-5792) wallet capability is defined. We also define a standard interface for paymaster web services as a prerequisite.

### Paymaster Web Service Interface

We define two JSON-RPC methods to be implemented by paymaster web services.

#### `pm_getPaymasterStubData`

Returns stub values to be used in paymaster-related fields of an unsigned user operation for gas estimation. Accepts an unsigned user operation, entrypoint address, chain id, and a context object. Paymaster service providers can define fields that app developers should use in the context object.

This method MAY return paymaster-specific gas values if applicable to the provided EntryPoint version. For example, if provided with EntryPoint v0.7, this method MAY return `paymasterVerificationGasLimit`. Furthermore, for EntryPoint v0.7, this method MUST return a value for `paymasterPostOpGasLimit`. This is because it is the paymaster that pays the postOpGasLimit, so it cannot trust the wallet to estimate this amount.

The wallet SHOULD use these provided gas values when submitting the `UserOperation` to a bundler for gas estimation.

This method MAY also return a `sponsor` object with a `name` field and an optional `icon` field. The `name` field is the name of the party sponsoring the transaction, and the `icon` field is a URI pointing to an image. Wallet developers MAY choose to display sponsor information to users. The `icon` string MUST be a data URI as defined in [RFC-2397]. The image SHOULD be a square with 96x96px minimum resolution. The image format is RECOMMENDED to be either lossless or vector based such as PNG, WebP or SVG to make the image easy to render on the wallet. Since SVG images can execute Javascript, wallets MUST render SVG images using the `&lt;img&gt;` tag to ensure no untrusted Javascript execution can occur.

There are cases where a call to just `pm_getPaymasterStubData` is sufficient to provide valid paymaster-related user operation fields, e.g. when the `paymasterData` does not contain a signature. In such cases, the second RPC call to `pm_getPaymasterData` (defined below) MAY be skipped, by returning `isFinal: true` by this RPC call.

Paymaster web services SHOULD do validations on incoming user operations during `pm_getPaymasterStubData` execution and reject the request at this stage if it would not sponsor the operation.

##### `pm_getPaymasterStubData` RPC Specification

Note that the user operation parameter does not include a signature, as the user signs after all other fields are populated.

```typescript
// [userOp, entryPoint, chainId, context]
type GetPaymasterStubDataParams = [
  // Below is specific to Entrypoint v0.6 but this API can be used with other entrypoint versions too
  {
    sender: `0x${string}`;
    nonce: `0x${string}`;
    initCode: `0x${string}`;
    callData: `0x${string}`;
    callGasLimit: `0x${string}`;
    verificationGasLimit: `0x${string}`;
    preVerificationGas: `0x${string}`;
    maxFeePerGas: `0x${string}`;
    maxPriorityFeePerGas: `0x${string}`;
  }, // userOp
  `0x${string}`, // EntryPoint
  `0x${string}`, // Chain ID
  Record&lt;string, any&gt; // Context
];

type GetPaymasterStubDataResult = {
  sponsor?: { name: string; icon?: string }; // Sponsor info
  paymaster?: string; // Paymaster address (entrypoint v0.7)
  paymasterData?: string; // Paymaster data (entrypoint v0.7)
  paymasterVerificationGasLimit?: `0x${string}`; // Paymaster validation gas (entrypoint v0.7)
  paymasterPostOpGasLimit?: `0x${string}`; // Paymaster post-op gas (entrypoint v0.7)
  paymasterAndData?: string; // Paymaster and data (entrypoint v0.6)
  isFinal?: boolean; // Indicates that the caller does not need to call pm_getPaymasterData
};
```

###### `pm_getPaymasterStubData` Example Parameters

```json
[
  {
    &quot;sender&quot;: &quot;0x...&quot;,
    &quot;nonce&quot;: &quot;0x...&quot;,
    &quot;initCode&quot;: &quot;0x&quot;,
    &quot;callData&quot;: &quot;0x...&quot;,
    &quot;callGasLimit&quot;: &quot;0x...&quot;,
    &quot;verificationGasLimit&quot;: &quot;0x...&quot;,
    &quot;preVerificationGas&quot;: &quot;0x...&quot;,
    &quot;maxFeePerGas&quot;: &quot;0x...&quot;,
    &quot;maxPriorityFeePerGas&quot;: &quot;0x...&quot;
  },
  &quot;0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789&quot;,
  &quot;0x2105&quot;,
  {
    // Illustrative context field. These should be defined by service providers.
    &quot;policyId&quot;: &quot;962b252c-a726-4a37-8d86-333ce0a07299&quot;
  }
]
```

###### `pm_getPaymasterStubData` Example Return Value

Paymaster services MUST detect which entrypoint version the account is using and return the correct fields.

For example, if using entrypoint v0.6:

```json
{
  &quot;sponsor&quot;: {
    &quot;name&quot;: &quot;My App&quot;,
    &quot;icon&quot;: &quot;https://...&quot;
  },
  &quot;paymasterAndData&quot;: &quot;0x...&quot;
}
```

If using entrypoint v0.7:

```json
{
  &quot;sponsor&quot;: {
    &quot;name&quot;: &quot;My App&quot;,
    &quot;icon&quot;: &quot;https://...&quot;
  },
  &quot;paymaster&quot;: &quot;0x...&quot;,
  &quot;paymasterData&quot;: &quot;0x...&quot;
}
```

If using entrypoint v0.7, with paymaster gas estimates:

```json
{
  &quot;sponsor&quot;: {
    &quot;name&quot;: &quot;My App&quot;,
    &quot;icon&quot;: &quot;https://...&quot;
  },
  &quot;paymaster&quot;: &quot;0x...&quot;,
  &quot;paymasterData&quot;: &quot;0x...&quot;,
  &quot;paymasterVerificationGasLimit&quot;: &quot;0x...&quot;,
  &quot;paymasterPostOpGasLimit&quot;: &quot;0x...&quot;
}
```

Indicating that the caller does not need to make a `pm_getPaymasterData` RPC call:

```json
{
  &quot;sponsor&quot;: {
    &quot;name&quot;: &quot;My App&quot;,
    &quot;icon&quot;: &quot;https://...&quot;
  },
  &quot;paymaster&quot;: &quot;0x...&quot;,
  &quot;paymasterData&quot;: &quot;0x...&quot;,
  &quot;isFinal&quot;: true
}
```

#### `pm_getPaymasterData`

Returns values to be used in paymaster-related fields of a signed user operation. These are not stub values and will be used during user operation submission to a bundler. Similar to `pm_getPaymasterStubData`, accepts an unsigned user operation, entrypoint address, chain id, and a context object.

##### `pm_getPaymasterData` RPC Specification

Note that the user operation parameter does not include a signature, as the user signs after all other fields are populated.

```typescript
// [userOp, entryPoint, chainId, context]
type GetPaymasterDataParams = [
  // Below is specific to Entrypoint v0.6 but this API can be used with other entrypoint versions too
  {
    sender: `0x${string}`;
    nonce: `0x${string}`;
    initCode: `0x${string}`;
    callData: `0x${string}`;
    callGasLimit: `0x${string}`;
    verificationGasLimit: `0x${string}`;
    preVerificationGas: `0x${string}`;
    maxFeePerGas: `0x${string}`;
    maxPriorityFeePerGas: `0x${string}`;
  }, // userOp
  `0x${string}`, // Entrypoint
  `0x${string}`, // Chain ID
  Record&lt;string, any&gt; // Context
];

type GetPaymasterDataResult = {
  paymaster?: string; // Paymaster address (entrypoint v0.7)
  paymasterData?: string; // Paymaster data (entrypoint v0.7)
  paymasterAndData?: string; // Paymaster and data (entrypoint v0.6)
};
```

###### `pm_getPaymasterData` Example Parameters

```json
[
  {
    &quot;sender&quot;: &quot;0x...&quot;,
    &quot;nonce&quot;: &quot;0x...&quot;,
    &quot;initCode&quot;: &quot;0x&quot;,
    &quot;callData&quot;: &quot;0x...&quot;,
    &quot;callGasLimit&quot;: &quot;0x...&quot;,
    &quot;verificationGasLimit&quot;: &quot;0x...&quot;,
    &quot;preVerificationGas&quot;: &quot;0x...&quot;,
    &quot;maxFeePerGas&quot;: &quot;0x...&quot;,
    &quot;maxPriorityFeePerGas&quot;: &quot;0x...&quot;
  },
  &quot;0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789&quot;,
  &quot;0x2105&quot;,
  {
    // Illustrative context field. These should be defined by service providers.
    &quot;policyId&quot;: &quot;962b252c-a726-4a37-8d86-333ce0a07299&quot;
  }
]
```

###### `pm_getPaymasterData` Example Return Value

Paymaster services MUST detect which entrypoint version the account is using and return the correct fields.

For example, if using entrypoint v0.6:

```json
{
  &quot;paymasterAndData&quot;: &quot;0x...&quot;
}
```

If using entrypoint v0.7:

```json
{
  &quot;paymaster&quot;: &quot;0x...&quot;,
  &quot;paymasterData&quot;: &quot;0x...&quot;
}
```

### `paymasterService` Capability

The `paymasterService` capability is implemented by both apps and wallets.

#### App Implementation

Apps need to give wallets a paymaster service URL they can make the above RPC calls to. They can do this using the `paymasterService` capability as part of an [EIP-5792](/EIPs/EIPS/eip-5792) `wallet_sendCalls` call.

##### `wallet_sendCalls` Paymaster Capability Specification

```typescript
type PaymasterCapabilityParams = {
  url: string;
  context: Record&lt;string, any&gt;;
}
```

###### `wallet_sendCalls` Example Parameters

```json
[
  {
    &quot;version&quot;: &quot;1.0&quot;,
    &quot;chainId&quot;: &quot;0x01&quot;,
    &quot;from&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
    &quot;calls&quot;: [
      {
        &quot;to&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
        &quot;value&quot;: &quot;0x9184e72a&quot;,
        &quot;data&quot;: &quot;0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675&quot;
      },
      {
        &quot;to&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
        &quot;value&quot;: &quot;0x182183&quot;,
        &quot;data&quot;: &quot;0xfbadbaf01&quot;
      }
    ],
    &quot;capabilities&quot;: {
      &quot;paymasterService&quot;: {
        &quot;url&quot;: &quot;https://...&quot;,
        &quot;context&quot;: {
          &quot;policyId&quot;: &quot;962b252c-a726-4a37-8d86-333ce0a07299&quot;
        }
      }
    }
  }
]
```

The wallet will then make the above paymaster RPC calls to the URL specified in the `paymasterService` capability field.

#### Wallet Implementation

To conform to this specification, smart wallets that wish to leverage app-sponsored transactions:

1. MUST indicate to apps that they can communicate with paymaster web services via their response to an [EIP-5792](/EIPs/EIPS/eip-5792) `wallet_getCapabilities` call.
2. SHOULD make calls to and use the values returned by the paymaster service specified in the capabilities field of an [EIP-5792](/EIPs/EIPS/eip-5792) `wallet_sendCalls` call. An example of an exception is a wallet that allows users to select a paymaster provided by the wallet. Since there might be cases in which the provided paymaster is ultimately not used—either due to service failure or due to a user selecting a different, wallet-provided paymaster—applications MUST NOT assume that the paymaster it provides to a wallet is the entity that pays for transaction fees.

##### `wallet_getCapabilities` Response Specification

```typescript
type PaymasterServiceCapability = {
  supported: boolean;
};
```

###### `wallet_getCapabilities` Example Response

```json
{
  &quot;0x2105&quot;: {
    &quot;paymasterService&quot;: {
      &quot;supported&quot;: true
    }
  },
  &quot;0x14A34&quot;: {
    &quot;paymasterService&quot;: {
      &quot;supported&quot;: true
    }
  }
}
```

Below is a diagram illustrating the full `wallet_sendCalls` flow, including how a wallet might implement the interaction.

![flow](/EIPs/assets/eip-7677/0.svg)

## Rationale

### Gas Estimation

The current loose standard for paymaster services is to implement `pm_sponsorUserOperation`. This method returns values for paymaster-related user operation fields and updated gas values. The problem with this method is that paymaster service providers have different ways of estimating gas, which results in different estimated gas values. Sometimes these estimates can be insufficient. As a result we believe it’s better to leave gas estimation up to the wallet, as the wallet has more context on how user operations will get submitted (e.g. which bundler they will get submitted to). Then wallets can ask paymaster services to sponsor given the estimates defined by the wallet.

The above reason is also why we specify that the `pm_getPaymasterStubData` method MAY also return paymaster-specific gas estimates. I.e., bundlers are prone to insufficiently estimating the paymaster-specific gas values, and the paymaster servies themselves are ultimately better equipped to provide them.

### Chain ID Parameter

Currently, paymaster service providers typically provide developers with a URL per chain. That is, paymaster service URLs are not typically multichain. So why do we need a chain ID parameter? We recognize that we must specify some constraint so that wallets can communicate with paymaster services about which chain their requests are for. As we see it, there are two options:

1. Formalize the current loose standard and require that paymaster service URLs are 1:1 with chains.
2. Require a chain ID parameter as part of paymaster service requests.

We feel that option (2) is the better abstraction here. This allows service providers to offer multichain URLs if they wish at essentially no downside to providers who offer a URL per chain. Providers who offer a URL per chain would just need to accept an additional parameter that they can ignore. When an app developer who uses a URL-per-chain provider wants to submit a request to a different chain, they can just swap out the URL accordingly.

### Challenges With Stub Data

Enabling a workflow with greater flexibility in gas estimations will nonetheless come with some known challenges that paymaster services must be aware of in order to ensure reliable gas estimates are generated during the process.

#### `preVerificationGas`

The `preVerificationGas` value is largely influenced by the size of the user operation and it&apos;s ratio of zero to non-zero bytes. This can cause a scenario where `pm_getPaymasterStubData` returns values that results in upstream gas estimations to derive a lower `preVerificationGas` compared to what `pm_getPaymasterData` would require. If this occurs then bundlers will return an insufficient `preVerificationGas` error during `eth_sendUserOperation`.

To avoid this scenario, a paymaster service MUST return stub data that:

1. Is of the same length as the final data.
2. Has an amount of zero bytes (`0x00`) that is less than or equal to the final data.

#### Consistent Code Paths

In the naive case, a stub value of repeating non-zero bytes (e.g. `0x01`) that is of the same length as the final value will generate a usable `preVerificationGas`. Although this would immediately result in a gas estimation error given that the simulation will likely revert due to an invalid paymaster data.

In a more realistic case, a valid stub can result in a successful simulation but still return insufficient gas limits. This can occur if the stub data causes `validatePaymasterUserOp` or `postOp` functions to simulate a different code path compared to the final value. For example, if the simulated code was to return early, the estimated gas limits would be less than expected which would cause upstream `out of gas` errors once a user operation is submitted to the bundler.

Therefore, a paymaster service MUST also return a stub that can result in a simulation executing the same code path compared to what is expected of the final user operation.

## Security Considerations

The URLs paymaster service providers give to app developers commonly have API keys in them. App developers might not want to pass these API keys along to wallets. To remedy this, we recommend that app developers provide a URL to their app&apos;s backend, which can then proxy calls to paymaster services. Below is a modified diagram of what this flow might look like.

![flowWithAPI](/EIPs/assets/eip-7677/1.svg)

This flow would allow developers to keep their paymaster service API keys secret. Developers might also want to do additional simulation / validation in their backends to ensure they are sponsoring a transaction they want to sponsor.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 03 Apr 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7677</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7677</guid>
      </item>
    
      <item>
        <title>UserOperation Builder</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7679-smart-account-interfaces/19547</comments>
        
        <description>## Abstract

Different [ERC-4337](/EIPs/EIPS/eip-4337) smart account implementations encode their signature, nonce, and calldata differently.  This makes it difficult for DApps, wallets, and smart account toolings to integrate with smart accounts without integrating with account-specific SDKs, which introduces vendor lock-in and hurts smart account adoption.

We propose a standard way for smart account implementations to put their account-specific encoding logic on-chain. It can be achieved by implementing methods that accept the raw signature, nonce, or calldata (along with the context) as an input, and output them properly formatted, so the smart account can consume them while validating and executing the User Operation.


## Motivation

At the moment, to build a [ERC-4337](/EIPs/EIPS/eip-4337) UserOperation (UserOp for short) for a smart account requires detailed knowledge of how the smart account implementation works, since each implementation is free to encode its nonce, calldata, and signature differently.

As a simple example, one account might use an execution function called `executeFoo`, whereas another account might use an execution function called `executeBar`.  This will result in the `calldata` being different between the two accounts, even if they are executing the same call.

Therefore, someone who wants to send a UserOp for a given smart account needs to:

* Figure out which smart account implementation the account is using.
* Correctly encode signature/nonce/calldata given the smart account implementation, or use an account-specific SDK that knows how to do that.

In practice, this means that most DApps, wallets, and AA toolings today are tied to a specific smart account implementation, resulting in fragmentation and vendor lock-in.

## Specification

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.

### UserOp builder

To conform to this standard, a smart account implementation MUST provide a “UserOp builder” contract that implements the `IUserOperationBuilder` interface, as defined below:


```solidity
struct Execution {
    address target;
    uint256 value;
    bytes callData;
}

interface IUserOperationBuilder {
    /**
     * @dev Returns the ERC-4337 EntryPoint that the account implementation
     * supports.
     */
    function entryPoint() external view returns (address);
    
    /**
     * @dev Returns the nonce to use for the UserOp, given the context.
     * @param smartAccount is the address of the UserOp sender.
     * @param context is the data required for the UserOp builder to
     * properly compute the requested field for the UserOp.
     */
    function getNonce(
        address smartAccount,
        bytes calldata context
    ) external view returns (uint256);
	
    /**
     * @dev Returns the calldata for the UserOp, given the context and
     * the executions.
     * @param smartAccount is the address of the UserOp sender.
     * @param executions are (destination, value, callData) tuples that
     * the UserOp wants to execute.  It&apos;s an array so the UserOp can
     * batch executions.
     * @param context is the data required for the UserOp builder to
     * properly compute the requested field for the UserOp. 
     */
    function getCallData(
        address smartAccount,
        Execution[] calldata executions,
        bytes calldata context
    ) external view returns (bytes memory);
    
    /**
     * @dev Returns a correctly encoded signature, given a UserOp that
     * has been correctly filled out except for the signature field.
     * @param smartAccount is the address of the UserOp sender.
     * @param userOperation is the UserOp.  Every field of the UserOp should
     * be valid except for the signature field.  The &quot;PackedUserOperation&quot;
     * struct is as defined in ERC-4337.
     * @param context is the data required for the UserOp builder to
     * properly compute the requested field for the UserOp.
     */
    function formatSignature(
        address smartAccount,
        PackedUserOperation calldata userOperation,
        bytes calldata context
    ) external view returns (bytes memory signature);
}
```

### Using the UserOp builder

To build a UserOp using the UserOp builder, the building party SHOULD proceed as follows:

1. Obtain the address of `UserOpBuilder` and a `context` from the account owner.  The `context` is an opaque bytes array from the perspective of the building party.  The `UserOpBuilder` implementation may need the `context` in order to properly figure out the UserOp fields.  See [Rationale](#rationale) for more info.
2. Execute a multicall (batched `eth_call`s) of `getNonce` and `getCallData` with the `context` and executions.  The building party will now have obtained the nonce and calldata.
3. Fill out a UserOp with the data obtained previously. Gas values can be set randomly or very low. This userOp will be used to obtain a dummy signature for gas estimations. Sign the hash of userOp. (See [Rationale](#rationale) for what a dummy signature is. See [Security Considerations](#security-considerations) for the details on dummy signature security).
4. Call (via `eth_call`) `formatSignature` with the UserOp and `context` to obtain a UserOp with a properly formatted dummy signature. This userOp can now be used for gas estimation.
5. In the UserOp, change the existing gas values to those obtained from a proper gas estimation. This UserOp must be valid except for the `signature` field. Sign the hash of the UserOp and place the signature in the UserOp.signature field.
6. Call (via `eth_call`) `formatSignature` with the UserOp and `context` to obtain a completely valid UserOp.
    1. Note that a UserOp has a lot more fields than `nonce`, `callData`, and `signature`, but how the building party obtains the other fields is outside of the scope of this document, since only these three fields are heavily dependent on the smart account implementation.

At this point, the building party has a completely valid UserOp that they can then submit to a bundler or do whatever it likes with it.

### Using the UserOp builder when the account hasn’t been deployed

To provide the accurate data to the building party, the `UserOpBuilder` will in most cases have to call the account.
If the account has yet to be deployed, which means that the building party is looking to send the very first UserOp for this account, then the building party MAY modify the flow above as follows:

- In addition to the `UserOpBuilder` address and the `context`, the building party also obtains the `factory` and `factoryData` as defined in ERC-4337.
- When calling one of the view functions on the UserOp builder, the building party may use `eth_call` to deploy the `CounterfactualCall` contract, which is going to deploy the account and call `UserOpBuilder` (see below). 
- When filling out the UserOp, the building party includes `factory` and `factoryData`.

The `CounterfactualCall` contract SHOULD: 
- Deploy the account using `factory` and `factoryData` provided by the building party.
- Revert if the deployment has not succeeded.
- If the account has been deployed succesfully, call `UserOpBuilder` and return the data returned by `UserOpBuilder` to the building party.

See Reference Implementation section for more details on the `CounterfactualCall` contract.

## Rationale

### Context

The `context` is an array of bytes that encodes whatever data the UserOp builder needs in order to correctly determine the nonce, calldata, and signature.  Presumably, the `context` is constructed by the account owner, with the help of a wallet software.

Here we outline one possible use of `context`: delegation.  Say the account owner wants to delegate a transaction to be executed by the building party.  The account owner could encode a signature of the public key of the building party inside the `context`.  Let’s call this signature from the account owner the `authorization`.

Then, when the building party fills out the UserOp, it would fill the `signature` field with a signature generated by its own private key.  When it calls `getSignature` on the UserOp builder, the UserOp builder would extract the `authorization` from the `context` and concatenates it with the building party’s signature.  The smart account would presumably be implemented such that it would recover the building party’s public key from the signature, and check that the public key was in fact signed off by the `authorization`.  If the check succeeds, the smart account would execute the UserOp, thus allowing the building party to execute a UserOp on the user’s behalf.

### Dummy signature

The “dummy signature” refers to the signature used in a UserOp sent to a bundler for estimating gas (via `eth_estimateUserOperationGas`).  A dummy signature is needed because, at the time the bundler estimates gas, a valid signature does not exist yet, since the valid signature itself depends on the gas values of the UserOp, creating a circular dependency.  To break the circular dependency, a dummy signature is used.

However, the dummy signature is not just a fixed value that any smart account can use.  The dummy signature must be constructed such that it would cause the UserOp to use about as much gas as a real signature would.  Therefore, the dummy signature varies based on the specific validation logic that the smart account uses to validate the UserOp, making it dependent on the smart account implementation.

## Backwards Compatibility

This ERC is intended to be backwards compatible with all ERC-4337 smart accounts as of EntryPoint 0.7.

For smart accounts deployed against EntryPoint 0.6, the `IUserOperationBuilder` interface needs to be modified such that the `PackedUserOperation` struct is replaced with the corresponding struct in EntryPoint 0.6.

## Reference Implementation

### Counterfactual call contract

The counterfactual call contract is inspired by [ERC-6492](/EIPs/EIPS/eip-6492), which devised a mechanism to execute `isValidSignature` (see [ERC-1271](/EIPs/EIPS/eip-1271)) against a pre-deployed (counterfactual) contract.

```solidity
contract CounterfactualCall {
    
    error CounterfactualDeployFailed(bytes error);

    constructor(
        address smartAccount,
        address create2Factory, 
        bytes memory factoryData,
        address userOpBuilder, 
        bytes memory userOpBuilderCalldata
    ) { 
        if (address(smartAccount).code.length == 0) {
            (bool success, bytes memory ret) = create2Factory.call(factoryData);
            if (!success || address(smartAccount).code.length == 0) revert CounterfactualDeployFailed(ret);
        }

        assembly {
            let success := call(gas(), userOpBuilder, 0, add(userOpBuilderCalldata, 0x20), mload(userOpBuilderCalldata), 0, 0)
            let ptr := mload(0x40)
            returndatacopy(ptr, 0, returndatasize())
            if iszero(success) {
                revert(ptr, returndatasize())
            }
            return(ptr, returndatasize())
        }
    }
    
}
```

Here’s an example of calling this contract using the ethers and viem libraries:

```javascript
// ethers
const nonce = await provider.call({
  data: ethers.utils.concat([
    counterfactualCallBytecode,
    (
      new ethers.utils.AbiCoder()).encode([&apos;address&apos;,&apos;address&apos;, &apos;bytes&apos;, &apos;address&apos;,&apos;bytes&apos;], 
      [smartAccount, userOpBuilder, getNonceCallData, factory, factoryData]
    )
  ])
})

// viem
const nonce = await client.call({
  data: encodeDeployData({
    abi: parseAbi([&apos;constructor(address, address, bytes, address, bytes)&apos;]),
    args: [smartAccount, userOpBuilder, getNonceCalldata, factory, factoryData],
    bytecode: counterfactualCallBytecode,
  })
})
```

## Security Considerations

### Dummy Signature security

Since the properly formatted dummy signature is going to be publicly disclosed, in theory it can be intercepted and used by the man in the middle. Risks and potential harm of this is very low though as the dummy signature will be effectively unusable after the final UserOp is submitted (as both UserOps use the same nonce). However, to mitigate even this small issue, it is recommended that the UserOp which hash is going to be signed to obtain an un-foirmatted dummy signature (step 3 above) is filled with very low gas values.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 05 Apr 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7679</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7679</guid>
      </item>
    
      <item>
        <title>Dual Nature Multi Token Protocol</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7681-dual-nature-multi-token-protocol/19590</comments>
        
        <description>## Abstract

This proposal [ERC-7681](/EIPs/EIPS/eip-7681) delineates the integration of the fungible [ERC-20](/EIPs/EIPS/eip-20) token contract with the semi-fungible [ERC-1155](/EIPs/EIPS/eip-1155) multi-token standard, enabling cohesive operations between both standards within a single contract framework. It defines a mechanism for combining two token contracts and synchronizing operations between them.

## Motivation

Inspired by [ERC-7631](/EIPs/EIPS/eip-7631) Dual Nature Token Pair, which introduced a concept of interlinkable tokens between ERC-20 and [ERC-721](/EIPs/EIPS/eip-721), a challenge arises due to the duplicated `Transfer(address, address, uint256)` event, making full compatibility challenging. However, combining ERC-20 and ERC-1155 offers similar benefits of non-fungible token (NFT) fractionalization natively. Here, acquiring ERC-20 tokens could automatically issue ERC-1155 tokens proportionally to the ERC-20 holdings, achieving full compliance with both standards.

Furthermore, analogous to ERC-7631, this proposal allows users to opt out of ERC-1155 mints and transfers during the ERC-20 to ERC-1155 synchronization process.

## Specification

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

### Overview

Every `ERC-7681` MUST implement both `ERC20` and `ERC1155` interfaces.

### ERC-7681 Interface

The ERC-20 contract MUST implement the following interface.

```solidity
interface IERC7681 /* is IERC20, IERC1155 */ {
    /// The contract MUST contain the following events
    /// ERC20 related events
    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);

    /// The contract MUST contain the following events
    /// ERC1155 related events
    event TransferSingle(address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _value);
    event TransferBatch(address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _values);
    event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
    event URI(string _value, uint256 indexed _id);

    /// The contract MAY contain the following functions
    /// ERC20 related functions
    function name() public view returns (string);
    function symbol() public view returns (string);
    function decimals() public view returns (uint8);

    /// The contract MUST contain the following functions
    /// ERC20 related functions
    function totalSupply() public view returns (uint256);
    function balanceOf(address _owner) public view returns (uint256);
    function transfer(address _to, uint256 _value) public returns (bool);
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool);
    function approve(address _spender, uint256 _value) public returns (bool);
    function allowance(address _owner, address _spender) public view returns (uint256);

    /// The contract MUST contain the following functions
    /// ERC1155 related functions
    function balanceOf(address _owner, uint256 _id) external view returns (uint256);
    function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) external view returns (uint256[] memory);
    function setApprovalForAll(address _operator, bool _approved) external;
    function isApprovedForAll(address _owner, address _operator) external view returns (bool);
    function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) external;
    function safeBatchTransferFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external;
}
```

### ERC-7681 Skippable Interface

The ERC-7681 contract MAY implement the following interface.

```solidity
interface IERC7681Skippable {
    /// @dev Emitted when the skip ERC1155 token status of `owner` is changed by any mechanism.
    ///
    /// This initial skip ERC1155 token status for `owner` can be dynamically chosen to
    /// be true or false, but any changes to it MUST emit this event.
    event SkipTokenSet(address indexed owner, bool status);

    /// @dev Returns true if ERC-1155 mints and transfers to `owner` SHOULD be
    /// skipped during ERC-20 to ERC-1155 synchronization. Otherwise false.
    /// 
    /// This method MAY revert
    ///
    /// If this method reverts:
    /// - Interacting code SHOULD interpret `setSkipToken` functionality as
    ///   unavailable (and hide any functionality to call `setSkipToken`).
    /// - The skip ERC1155 token status for `owner` SHOULD be interpreted as undefined.
    ///
    /// Once a true or false value has been returned for a given `owner`,
    /// this method MUST NOT revert for the given `owner`.
    function getSkipToken(address owner) external view returns (bool);

    /// @dev Sets the caller&apos;s skip ERC1155 token status.
    ///
    /// This method MAY revert
    /// (e.g. insufficient permissions, method not supported).
    ///
    /// Emits a {SkipTokenSet} event.
    function setSkipToken(bool status) external;
}
```

## Rationale

### Implementation Flexibility

This proposal intentionally does not prescribe specific token synchronization logic to allow for diverse implementation strategies and novel use cases, such as one-to-one synchronization or fractionalization of ERC-1155 tokens based on ERC-20 holdings. Developers are afforded the flexibility to determine their synchronization approach, provided it remains fully compliant with the specifications of both token standards.

### ERC-1155 Token Skipping

For instances where the `owner` is a smart contract, setting the skip status to `true` by default can prevent unnecessary ERC-1155 minting for interactions with contracts like DEXs and lending protocols, thereby potentially reducing gas costs.

### Backwards Compatibility

This proposal is fully backward-compatible with the existing ERC-20 and ERC-1155 standards, ensuring that contracts reliant on these standards will continue to function seamlessly.

## Security Considerations

### Out-of-gas Denial of Service

When user transfers ERC-20 tokens, it can trigger the automatic minting, transfer, or burning of various ERC-1155 tokens. This process can lead to gas expenses that grow linearly with the number of actions O(n) rather than the fixed cost O(1) usually seen with ERC-20 token transactions. Additionally, the mechanism for choosing ERC-1155 token IDs might increase gas expenses further. Therefore, any synchronization strategy needs to account for the potential rise in ERC-1155 associated gas costs to avoid running out of gas, which could result in denial of service situations.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 08 Apr 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7681</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7681</guid>
      </item>
    
      <item>
        <title>Auxiliary Funds Capability</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7682-auxiliary-funds-capability/19599</comments>
        
        <description>## Abstract

An [EIP-5792](/EIPs/EIPS/eip-5792) compliant capability that allows wallets to indicate to apps that they have access to funds beyond those that can be accounted for by looking up balances onchain given the wallet&apos;s address.

A wallet&apos;s ability to access auxiliary funds is communicated to apps as part of its response to an [EIP-5792](/EIPs/EIPS/eip-5792) `wallet_getCapabilities` request. The following standard does not specify the source of these auxiliary funds, but some examples are:

- Funds from offchain sources that can be onramped and used just-in-time
- Wallets that manage many accounts, where assets across those accounts can be transfered to the required account before submitting a transaction requested by an app

## Motivation

Many applications check users&apos; balances before letting them complete some action. For example, if a user wants to swap some amount of tokens on a dex, the dex will commonly block the user from doing so if it sees that the user does not have that amount of tokens at their address. However, more advanced wallets have features that let users access funds from other sources. Wallets need a way to tell apps that they have access to additional funds so that users using these more advanced wallets are not blocked by balance checks.

## Specification

One new [EIP-5792](/EIPs/EIPS/eip-5792) wallet capability is defined.

### Wallet Implementation

To conform to this specification, wallets that wish to indicate that they have access to auxiliary funds MUST, for each chain they have access to auxiliary funds on, respond to `wallet_getCapabilities` calls with an `auxiliaryFunds` object with a `supported` field set to `true`.

Wallets may also optionally specify which assets they have additional access to with an `assets` field, which maps to an array of addresses representing the assets the wallet might have additional access to. If a wallet does not respond with this optional array of assets, the application SHOULD assume the wallet has additional access to any asset.

This specification does not put any constraints on the source of the auxiliary funds.

In this specification, a chain&apos;s native asset (e.g. Ether on Ethereum) MUST be represented by &quot;0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&quot; as specified by [EIP-7528](./eip-7528).

#### `wallet_getCapabilities` Response Specification

```typescript
type AuxiliaryFundsCapability = {
  supported: boolean;
  assets?: `0x${string}`[];
};
```

##### `wallet_getCapabilities` Example Response

```json
{
  &quot;0x2105&quot;: {
    &quot;auxiliaryFunds&quot;: {
      &quot;supported&quot;: true,
      &quot;assets&quot;: [
        &quot;0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&quot;,
        &quot;0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913&quot;
      ]
    }
  },
  &quot;0x14A34&quot;: {
    &quot;auxiliaryFunds&quot;: {
      &quot;supported&quot;: true,
      &quot;assets&quot;: [
        &quot;0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&quot;,
        &quot;0x036CbD53842c5426634e7929541eC2318f3dCF7e&quot;
      ]
    }
  }
}
```

### Extended Usage: `requiredAssets` Parameter

When a wallet indicates support for the `auxiliaryFunds` capability (i.e., `supported: true`), applications that use the [`wallet_sendCalls`](/EIPs/EIPS/eip-5792#wallet_sendcalls) method MAY include a `requiredAssets` parameter in the `capabilities.auxiliaryFunds` object to enable the wallet to leverage this capability.

A wallet&apos;s signaling support for the `auxiliaryFunds` capability does not necessarily mean they can interpret or use the `requiredAssets` metadata. The `requiredAssets` parameter is an optional capability that wallets may or may not support, even when they support the base `auxiliaryFunds` capability.

**Native Asset Handling**: Wallets SHOULD deduce native asset requirements (e.g., ETH on Ethereum mainnet) from the `call.value` field in the calls array rather than requiring explicit specification in `requiredAssets`. The `requiredAssets` parameter is primarily intended for token assets that cannot be inferred from call data alone.

This parameter may be necessary because transaction call data alone does not reliably indicate which assets and amounts are needed for successful execution. Calls may involve complex logic or multiple contracts, making it difficult for wallets to infer requirements. By specifying required assets and amounts explicitly, apps ensure wallets have the information needed to provision, bridge, or swap assets as necessary for the transaction to succeed.

### `wallet_sendCalls` Extended Parameter

If included, the `requiredAssets` parameter MUST be specified within the `capabilities.auxiliaryFunds` object of the `wallet_sendCalls` request.

&gt; **Note**: The `capabilities` object is specified in [EIP-5792](/EIPs/EIPS/eip-5792) where `wallet_sendCalls` is first defined: &quot;The capabilities field is how an app can communicate with a wallet about capabilities a wallet supports. For example, this is where an app can specify a paymaster service URL from which an [ERC-4337](/EIPs/EIPS/eip-4337) wallet can request a paymasterAndData input for a user operation.&quot;

```typescript
// Example wallet_sendCalls type extension
type WalletSendCallsRequest = {
  version: string;
  from: `0x${string}`;
  chainId: `0x{string}`;
  atomicRequired: boolean;
  calls: Array&lt;{
    to: `0x${string}`;
    data: string;
    // ... other call fields ...
  }&gt;;
  capabilities?: {
    auxiliaryFunds?: {
      optional?: boolean;
      requiredAssets?: {
        address: `0x${string}`;
        amount: `0x${string}`; // Amount required, as a hex string representing the integer value in the asset&apos;s smallest unit
        standard: &quot;erc20&quot; | &quot;erc721&quot; | &quot;erc1155&quot;; // Token standard
        tokenId?: `0x${string}`; // Token ID as a hex string (required for ERC-721 and ERC-1155)
      }[];
    };
  };
};
```

#### Example Scenario: Cross-Chain Deposit to Aave

Suppose a user wants to deposit DAI into Aave on Chain X, but their wallet address on Chain X has no DAI or native gas token. However, the wallet has access to funds on Chain Y (e.g., Ethereum mainnet). The app, upon detecting the `auxiliaryFunds` capability, can construct a `wallet_sendCalls` request as follows:

```json
{
  &quot;calls&quot;: [
    {
      &quot;to&quot;: &quot;0xAaveDAIDepositContractOnChainX&quot;,
      &quot;data&quot;: &quot;0xd0e30db0&quot; // Example encoded deposit function call
    }
  ],
  &quot;capabilities&quot;: {
    &quot;auxiliaryFunds&quot;: {
      &quot;optional&quot;: true,
      &quot;requiredAssets&quot;: [
        {
          &quot;address&quot;: &quot;0x6B175474E89094C44Da98b954EedeAC495271d0F&quot;, // DAI address on Chain X
          &quot;amount&quot;: &quot;0x0de0b6b3a7640000&quot;, // 1 DAI
          &quot;standard&quot;: &quot;erc20&quot;
        }
      ]
    }
  }
}
```

The wallet, upon receiving this request, can:

- Bridge or swap the required DAI from Chain Y to Chain X
- Ensure the user has enough native asset (e.g., ETH) for gas on Chain X
- Complete the deposit call to Aave on Chain X

This mechanism allows advanced wallets to abstract away the complexity of cross-chain or offchain funding, enabling seamless user experiences even when the user&apos;s onchain balance is insufficient on the target chain.

### Token Standard Extensibility

This specification currently supports three token standards with the following field requirements:

- **[ERC-20](/EIPs/EIPS/eip-20)**: Requires `amount` field only
- **[ERC-721](/EIPs/EIPS/eip-721)**: Requires both `amount` and `tokenId` fields
- **[ERC-1155](/EIPs/EIPS/eip-1155)**: Requires both `amount` and `tokenId` fields

The `amount` field semantics vary by token standard:

- **[ERC-20](/EIPs/EIPS/eip-20)**: Represents token quantity in smallest unit (e.g., wei for 18-decimal tokens)
- **[ERC-721](/EIPs/EIPS/eip-721)**: Represents NFT quantity (typically &quot;0x01&quot; for single NFT instances)
- **[ERC-1155](/EIPs/EIPS/eip-1155)**: Represents quantity of the specified token ID

Future token standards MUST specify additional required fields as properties on the asset object root to maintain extensibility.

### Auxiliary Funds and Atomic Execution

Auxiliary funds provisioning (bridging, swapping, or other asset retrieval operations) is independent of the `wallet_sendCalls` execution lifecycle. The `atomicRequired` field applies only to the call bundle execution, not to auxiliary funds provisioning.

### Error Codes

The following error codes are defined for auxiliary funds provisioning failures.

| Code | Message                                  | Description                                                                      |
| ---- | ---------------------------------------- | -------------------------------------------------------------------------------- |
| 5770 | Auxiliary funds provisioning failed      | Wallet attempted to provision funds but failed (e.g., bridge/swap error).        |
| 5771 | Asset not supported                      | The requested asset is not available through the wallet&apos;s auxiliary fund system. |
| 5772 | Auxiliary funds capability not available | The wallet no longer supports auxiliary funds on the requested chain.            |
| 5773 | Invalid requiredAssets                   | The structure of the requiredAssets object is malformed.                         |

Applications SHOULD use the `wallet_getCallsStatus` method to track the status of call bundles that involve auxiliary funds provisioning, as the provisioning process may take time to complete. The status response will indicate whether the auxiliary funds provisioning is in progress, completed, or failed.

### App Implementation Guidance

When an app sees that a connected wallet has access to auxiliary funds via the `auxiliaryFunds` capability in a `wallet_getCapabilities` response, the app SHOULD NOT block users from taking actions on the basis of asset balance checks.

Apps MAY include the `requiredAssets` parameter in the `capabilities.auxiliaryFunds` object to ensure the wallet has the necessary information to provision assets as needed for successful execution. However, apps should be aware that this is an optional capability and should handle cases where wallets do not support or cannot process the `requiredAssets` metadata gracefully.

### Amount Validation

The wallet MUST cross-check the `amount` value in `requiredAssets` against the `decimal()` value specified on the `asset`&apos;s contract to ensure that the amount is interpreted correctly according to the asset&apos;s decimal precision.

## Rationale

### Alternatives

#### Advanced Balance Fetching

An alternative we considered is defining a way for apps to fetch available auxiliary balances. This could be done, for example, by providing a URL as part of the `auxiliaryFunds` capability that apps could use to fetch auxiliary balance information. However, we ultimately decided that a boolean was enough to indicate to apps that they should not block user actions on the basis of balance checks, and it is minimally burdensome for apps to implement.

The shape of this capability allows for a more advanced extension if apps feel more functionality is needed.

## Backwards Compatibility

- Applications SHOULD only include the `requiredAssets` parameter if the wallet advertises the `auxiliaryFunds` capability.
- Applications SHOULD include the `auxiliaryFunds` capability with `optional: true` to provide metadata to wallets that support this optional capability while maintaining compatibility with wallets that do not.

## Security Considerations

- Apps MUST NOT make any assumptions about the source of auxiliary funds. Apps&apos; smart contracts should still, as they would today, make appropriate balance checks onchain when processing a transaction.
- Applications MUST NOT assume that the wallet will always be able to fulfill the asset requirements, and SHOULD handle failures gracefully.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 09 Apr 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7682</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7682</guid>
      </item>
    
      <item>
        <title>Cross Chain Intents</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-cross-chain-intents-standard/19619</comments>
        
        <description>## Abstract

The following standard allows for the implementation of a standard API for cross-chain value-transfer systems. This standard provides generic order structs, as well as a standard set of settlement smart contract interfaces.

## Motivation

Intent-based systems have become the preeminent solution for end-user cross-chain interaction by abstracting away the complexity and time constraints of traditional bridges. One of the key difficulties for cross-chain intents systems is accessing sufficient liquidity and a network of active fillers across chains. This challenge may be exacerbated as the number of distinct chains increases over time. The end result of this is a poor experience for users including higher costs, longer wait times and higher failure rates than necessary.

By implementing a standard, cross-chain intents systems can interoperate and share infrastructure such as order dissemination services and filler networks, thereby improving end-user experience by increasing competition for fulfilling user intents.

## Specification

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.

### Glossary of Terms

- **Destination Chain**: the chain where the intent is executed and the user receives funds. Note: intents can involve multiple destination chains.
- **Filler**: a participant who fulfils a user intent on the destination chain(s) and receives payment as a reward.
- **Leg**: a portion of the user intent that can be executed independently from others. All legs must be executed for an intent to be considered fulfilled.
- **Origin chain**: the chain where the user sends funds.
- **Settlement System**: a system that custodies user deposits, verifies fills, and pays fillers for the purpose of facilitating intents.
- **Settler**: a contract that implements part of the settlement system on a particular chain.
- **User**: for the purposes of this document, the user is the end-user who is sending the order.

### Order structs

A compliant cross-chain order type MUST be ABI decodable into either `GaslessCrossChainOrder` or `OnchainCrossChainOrder` type.

```solidity
/// @title GaslessCrossChainOrder CrossChainOrder type
/// @notice Standard order struct to be signed by users, disseminated to fillers, and submitted to origin settler contracts by fillers
struct GaslessCrossChainOrder {
	/// @dev The contract address that the order is meant to be settled by.
	/// Fillers send this order to this contract address on the origin chain
	address originSettler;
	/// @dev The address of the user who is initiating the swap,
	/// whose input tokens will be taken and escrowed
	address user;
	/// @dev Nonce to be used as replay protection for the order
	uint256 nonce;
	/// @dev The chainId of the origin chain
	uint256 originChainId;
	/// @dev The timestamp by which the order must be opened
	uint32 openDeadline;
	/// @dev The timestamp by which the order must be filled on the destination chain
	uint32 fillDeadline;
	/// @dev Type identifier for the order data. This is an EIP-712 typehash.
	bytes32 orderDataType;
	/// @dev Arbitrary implementation-specific data
	/// Can be used to define tokens, amounts, destination chains, fees, settlement parameters,
	/// or any other order-type specific information
	bytes orderData;
}

/// @title OnchainCrossChainOrder CrossChainOrder type
/// @notice Standard order struct for user-opened orders, where the user is the one submitting the order creation transaction
struct OnchainCrossChainOrder {
	/// @dev The timestamp by which the order must be filled on the destination chain
	uint32 fillDeadline;
	/// @dev Type identifier for the order data. This is an EIP-712 typehash.
	bytes32 orderDataType;
	/// @dev Arbitrary implementation-specific data
	/// Can be used to define tokens, amounts, destination chains, fees, settlement parameters,
	/// or any other order-type specific information
	bytes orderData;
}
```

Cross-chain execution systems implementing this standard SHOULD use a sub-type that can be parsed from the arbitrary `orderData` field. This may include information such as the tokens involved in the transfer, the destination chain IDs, fulfillment constraints or settlement oracles.

All sub-types SHOULD be registered in a subtypes repository to encourage sharing of sub-types based on their functionality. See the examples section for an example of how sub-types can be used to support behavior like executing calldata on a target contract of the user&apos;s choice on the destination chain.

### ResolvedCrossChainOrder struct

A compliant cross-chain order type MUST be convertible into the `ResolvedCrossChainOrder` struct. This means that the `orderData` must be decoded into the information needed to populate the `ResolvedCrossChainOrder` struct. Additionally, `orderData` SHOULD be decodable into a sub-type, which can be used for further functionality such as cross-chain calldata execution (see the examples section for an example of this). It is the responsibility of the `user` and the `filler` to ensure that the `originSettler` supports their order&apos;s contained sub-type.

```solidity
/// @title ResolvedCrossChainOrder type
/// @notice An implementation-generic representation of an order intended for filler consumption
/// @dev Defines all requirements for filling an order by unbundling the implementation-specific orderData.
/// @dev Intended to improve integration generalization by allowing fillers to compute the exact input and output information of any order
struct ResolvedCrossChainOrder {
	/// @dev The address of the user who is initiating the transfer
	address user;
	/// @dev The chainId of the origin chain
	uint256 originChainId;
	/// @dev The timestamp by which the order must be opened
	uint32 openDeadline;
	/// @dev The timestamp by which the order must be filled on the destination chain(s)
	uint32 fillDeadline;
	/// @dev The unique identifier for this order within this settlement system
	bytes32 orderId;

	/// @dev The max outputs that the filler will send. It&apos;s possible the actual amount depends on the state of the destination
	///      chain (destination dutch auction, for instance), so these outputs should be considered a cap on filler liabilities.
	Output[] maxSpent;
	/// @dev The minimum outputs that must be given to the filler as part of order settlement. Similar to maxSpent, it&apos;s possible
	///      that special order types may not be able to guarantee the exact amount at open time, so this should be considered
	///      a floor on filler receipts. Setting the `recipient` of an `Output` to address(0) indicates that the filler is not
        ///      known when creating this order.
	Output[] minReceived;
	/// @dev Each instruction in this array is parameterizes a single leg of the fill. This provides the filler with the information
	///      necessary to perform the fill on the destination(s).
	FillInstruction[] fillInstructions;
}

/// @notice Tokens that must be received for a valid order fulfillment
struct Output {
	/// @dev The address of the ERC20 token on the destination chain
	/// @dev address(0) used as a sentinel for the native token
	bytes32 token;
	/// @dev The amount of the token to be sent
	uint256 amount;
	/// @dev The address to receive the output tokens
	bytes32 recipient;
	/// @dev The destination chain for this output
	uint256 chainId;
}

/// @title FillInstruction type
/// @notice Instructions to parameterize each leg of the fill
/// @dev Provides all the origin-generated information required to produce a valid fill leg
struct FillInstruction {
	/// @dev The chain that this instruction is intended to be filled on
	uint256 destinationChainId;
	/// @dev The contract address that the instruction is intended to be filled on
	bytes32 destinationSettler;
	/// @dev The data generated on the origin chain needed by the destinationSettler to process the fill
	bytes originData;
}
```

### Open event

A compliant `Open` event MUST adhere to the following abi:

```solidity
/// @notice Signals that an order has been opened
/// @param orderId a unique order identifier within this settlement system
/// @param resolvedOrder resolved order that would be returned by resolve if called instead of Open
event Open(bytes32 indexed orderId, ResolvedCrossChainOrder resolvedOrder);
```

### Settlement interfaces

A compliant origin settler contract implementation MUST implement the `IOriginSettler` interface:

```solidity
/// @title IOriginSettler
/// @notice Standard interface for settlement contracts on the origin chain
interface IOriginSettler {
	/// @notice Opens a gasless cross-chain order on behalf of a user.
	/// @dev To be called by the filler.
	/// @dev This method must emit the Open event
	/// @param order The GaslessCrossChainOrder definition
	/// @param signature The user&apos;s signature over the order
	/// @param originFillerData Any filler-defined data required by the settler
	function openFor(GaslessCrossChainOrder calldata order, bytes calldata signature, bytes calldata originFillerData) external;

	/// @notice Opens a cross-chain order
	/// @dev To be called by the user
	/// @dev This method must emit the Open event
	/// @param order The OnchainCrossChainOrder definition
	function open(OnchainCrossChainOrder calldata order) external;

	/// @notice Resolves a specific GaslessCrossChainOrder into a generic ResolvedCrossChainOrder
	/// @dev Intended to improve standardized integration of various order types and settlement contracts
	/// @param order The GaslessCrossChainOrder definition
	/// @param originFillerData Any filler-defined data required by the settler
	/// @return ResolvedCrossChainOrder hydrated order data including the inputs and outputs of the order
	function resolveFor(GaslessCrossChainOrder calldata order, bytes calldata originFillerData) external view returns (ResolvedCrossChainOrder memory);

	/// @notice Resolves a specific OnchainCrossChainOrder into a generic ResolvedCrossChainOrder
	/// @dev Intended to improve standardized integration of various order types and settlement contracts
	/// @param order The OnchainCrossChainOrder definition
	/// @return ResolvedCrossChainOrder hydrated order data including the inputs and outputs of the order
	function resolve(OnchainCrossChainOrder calldata order) external view returns (ResolvedCrossChainOrder memory);
}
```

A compliant destination settlement contract implementation MUST implement the `IDestinationSettler` interface:

```solidity
/// @title IDestinationSettler
/// @notice Standard interface for settlement contracts on the destination chain
interface IDestinationSettler {
	/// @notice Fills a single leg of a particular order on the destination chain
	/// @param orderId Unique order identifier for this order
	/// @param originData Data emitted on the origin to parameterize the fill
	/// @param fillerData Data provided by the filler to inform the fill or express their preferences
	function fill(bytes32 orderId, bytes calldata originData, bytes calldata fillerData) external;
}
```

### fillerData

Cross-chain execution systems implementing this standard SHOULD use a sub-type that can be parsed from the arbitrary `fillerData` field. This may include information such as the desired timing or form of payment for the filler

All sub-types SHOULD be registered in a subtypes repository to encourage sharing of sub-types based on their functionality.

## Rationale

### Generic OrderData

A key consideration is to ensure that a broad range of cross-chain intent designs can work within the same standard. To enable this, the specification is designed around a cross-chain intents _flow_, with two variations: gasless and onchain.

#### Gasless cross-chain intents flow

Origin Chain:
1. The user signs an off-chain message defining the parameters of their order
2. The order is disseminated to fillers
3. The filler calls resolve to unpack the order&apos;s requirements
4. The filler opens the order on the origin chain

Destination Chain(s):
- The filler fills each leg of the order on the destination chain(s)

Settlement:
- A cross-chain settlement process takes place to settle the order

#### Onchain cross-chain intents flow

Origin Chain:
1. The caller signs a transaction calling open with their order
2. The filler retrieves the emitted event to determine requirements

Destination Chain(s):
- The filler fills each leg of the order on the destination chain(s)

Settlement:
- A cross-chain settlement process takes place to settle the order

#### Customization

Within this flow, implementers of the standard have design flexibility to customize behavior such as:

- Price resolution, e.g. dutch auctions (on origin or destination) or oracle-based pricing
- Fulfillment constraints
- Settlement procedures
- Ordering of the origin and destination chain actions, e.g. the fill could happen before `open` in some settlement systems

The `orderData` field allows implementations to take arbitrary specifications for these behaviors while still enabling integrators to parse the primary fields of the order.

This functionality also motivated the `resolve` view function and `ResolvedCrossChainOrder` type. Resolution enables integrating fillers to validate and assess orders without specific knowledge of the `orderData` field at hand.

### Emission of Fill Instructions

An important component of the standard is creating a flexible and robust mechanism for fillers to ensure their fills are valid. For a fill to be valid,
it typically must satisfy the following constraints:

1. It must be filled on the correct destination chain(s)
2. It must be filled on the correct destination contract
3. It must include some (not necessarily all) information from the order that the user provided on the origin chain
4. It may require some execution information from the `open` call on the origin chain (ex. dutch auctions based on open timing)

The `FillInstruction` array in `ResolvedCrossChainOrder` is intended to ensure it&apos;s simple for the filler to meet all of these requirements by either
listening for the `Open` or by calling `resolve`.

One may notice that the `originData` field within `FillInstruction` is completely opaque. This opaqueness allows the settler implementations to
freely customize the data they transmit. Because fillers do not need to interpret this information, the opaqueness does not result in any
additional implementation costs on fillers.

This functionality also makes it feasible for a user, filler, or order distribution system to perform an end-to-end simulation of the order initiation
and fill to evaluate all resulting state transitions without understanding the nuances of a particular execution system.

### Cross-compatibility

Since this standard is intended to reduce friction for users moving value across chains, non-EVM ecosystems should not be excluded. However, attempting
to pull each non-EVM ecosystem in would dramatically increase the size and complexity of this standard, while omitting any that come in the future.

Instead, this standard is intended to be cross-compatible with other ecosystems. It standardizes interfaces and data types on EVM chains, but allows
for the creation of sibling standards that define compatible interfaces, data types, and flows within other ecosystems. Intents created within these
sibling standards should be able to be filled on an EVM chain and vice versa.

To ensure this cross-compatibility, all foreign addresses use `bytes32` rather than `address` to allow for larger address identifiers.

### Usage of Permit2

Permit2 is not specifically required by this standard, but does provide an efficient and straightforward approach to building standard-adherent protocols. Specifically, the `witness` functions of permit2 allow users to both approve the token transfer _and_ the order itself with a single signature. This also nicely couples the transfer of tokens with a successful initiation of the order.

In contrast, a standard approval model would require two separate signatures - a token approval (either [ERC-2612](/EIPs/EIPS/eip-2612) or on-chain) and a signature to approve the terms of the order. It also decouples the token approval from the order, meaning approved tokens could potentially be taken at any time due to a buggy or untrusted settler contract.

When building a standard-compliant settler system around Permit2, the following considerations should be made

- `nonce` in the order struct should be a permit2 nonce
- `openDeadline` in the order struct should be the permit2 deadline
- A full order struct including the parsed `orderData` should be used as the witness type during the permit2 call. This ensures maximum transparency to the user as they sign their order permit.

### Examples

This is an example of how a 7683 cross-chain value transfer order can include instructions to the filler to execute arbitrary calldata on behalf of the recipient on the destination chain. This calldata execution is performed by the settlement contract atomically within the filler&apos;s fill() execution, so the arbitrary contract execution can take advantage of the destination chain recipient&apos;s newly transferred value. A hypothetical user in this example would select an `originSettler` that is known to support the `Message` sub-type.

Let there be a sub-type called `Message`, which is defined by the following structs:

```solidity
// The Message subtype allows ERC7683 intents to carry calldata that is executed on a target contract on the destination chain. The settlement contract that the filler interacts with on the destination chain will decode the message into smart contract calls and execute the calls within the filler&apos;s `fill()` transaction.

// The Message contains calls that the user wants executed on the destination chain.
// The target is a contract on the destination chain that the settlement contract will attempt to send callData and value to.
struct Calls {
  address target;
  bytes callData;
  uint256 value;
}

struct Message {
  Calls[] calls;
}
```

The `Message` sub-type is designed to be used by a 7683 user to incentivize a filler to execute arbitrary calldata on a target destination chain contract on the user&apos;s behalf. For example, the settlement contract might decode the `originData` containing the message information as follows:

```solidity
function fill(bytes32 orderId, bytes calldata originData, bytes calldata fillerData) public {
	(
		address user,
		uint32 fillDeadline,
		Output memory fillerOutput,
		Message memory message
	) = abi.decode(originData);

	// ...Do some preprocessing on the parameters here to validate the order...

	// ...Execute the fill logic of the ResolvedCrossChainOrder...

	// Handle the Message subtype:

        // Revert if any of the message calls fail.
        uint256 length = message.calls.length;
        for (uint256 i = 0; i &lt; length; ++i) {
            Call memory call = message.calls[i];

            // If we are calling an EOA with calldata, assume target was incorrectly specified and revert.
            if (call.callData.length &gt; 0 &amp;&amp; call.target.code.length == 0) {
                revert InvalidCall(i, calls);
            }

            (bool success, ) = call.target.call{ value: call.value }(call.callData);
            if (!success) revert CallReverted(i, message.calls);
        }
    }
```

In this example, the Message sub-type allows the user to delegate destination chain contract execution to fillers. However, because transactions are executed via filler, the `msg.sender` would be the `DestinationSettler`, making this `Message` sub-type limited if the target contract authenticates based on the `msg.sender`. Ideally, 7683 orders containing Messages can be combined with smart contract wallets like implementations of [ERC-4337](/EIPs/EIPS/eip-4337) or [EIP-7702](/EIPs/EIPS/eip-7702) to allow complete cross-chain delegated execution.


## Security Considerations

#### Evaluating settlement contract security

This ERC is agnostic of how the settlement system validates a 7683 order fulfillment and refunds the filler. In fact, this ERC is designed to delegate the responsibility of evaluating the settlement contract&apos;s security to the filler and the application that creates the user&apos;s 7683 order.

This design decision is motivated by the existence of many viable cross-chain messaging systems today offering settlement contracts a variety of tradeoffs. We hope that this standard can eventually support an ERC dedicated to standardizing a safe, trustless, cross-chain verification system.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 11 Apr 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7683</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7683</guid>
      </item>
    
      <item>
        <title>Return deposits for distinct credentials</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7684-return-deposits-for-distinct-credentials/19632</comments>
        
        <description>## Abstract

Automatically withdraw deposits for existing validator records, but where the deposit includes a distinct execution withdrawal credential.

## Motivation

Some staking operations feature two distinct entities, one operating the validating key, and one funding the deposit. The funding entity delegates control of the stake operation but must retain ultimate control of funds. If the funding entity naively submits a single deposit with the full stake amount and the other entity&apos;s validating key, it is subject to a front-run attack. The validating entity can front-run the bigger deposit with a second deposit with its own set of withdrawal credentials. The full stake amount deposit becomes a top-up, in control of the validating entity.

There exist workarounds to the front-run attack. Using some distributed key generation protocol between the funding and validating entity, such that a deposit must be made with the consent of both entities. Submit a 1 ETH deposit first wait for its inclusion then send the full stake amount as a top-up, to bind the maximum loss under the attack to 1 ETH. While these workarounds, work; they difficult the operation of trustless autonomous staking protocols.

This specification reduces the total loss on a naive deposit submission from the full deposit amount to `RETURN_DEPOSIT_PENALTY`.

## Specification

### Consensus Layer

The configuration values and mechanics of the specification can be found in the [Consensus Layer specs](https://github.com/ethereum/consensus-specs/blob/2360756c8c19c0f7b0e91135f5bbcddecdf0a835/specs/_features/eip9999/beacon_chain.md).

A sketch of the resulting changes to the consensus layer is included below.

- Modify `apply_deposit` to queue for withdrawal deposits with distinct execution withdrawal credentials
- Modify `get_expected_withdrawals` to return pending withdrawals first
- Modify `process_withdrawals` to clear the pending withdrawals queue

### Execution Layer

This specification does not require any changes to the Execution Layer.

## Rationale

### Persist pending withdrawals

Rejected deposits from block at slot N can not be withdrawn in block N due to a cyclic dependency. An execution client must know the full list of withdrawals before constructing a payload for slot N. After [EIP-6110](/EIPs/EIPS/eip-6110), a consensus client must know the full execution payload for slot N before constructing the beacon block for slot N. Therefore, rejected deposits must be withdrawn in some future slot. All pending withdrawals are processed at once in the very next slot for simplicity but could be queued and processed progressively if there are DOS concerns.

## Backwards Compatibility

This is a backward incompatible change to the Consensus Layer of Ethereum and must be scheduled with a hard fork.

There are no forwards / backwards compatibility issues with the Execution Layer

## Test Cases

Test cases are work-in-progress within the standard Consensus Layer tests.

## Security Considerations

The worst-case number of withdrawals is raised from a fixed 16 to 1,271 under current gas rules and a 30M gas block. Citing [EIP-6110](/EIPs/EIPS/eip-6110), future gas efficiencies can increase the number to 1,916 withdrawals in a 30M gas block. Each withdrawal results in a single address balance change. There is no explicit pricing for such an operation, but under the worst case, it results in a notable increase in the total block gas (30% assuming 6,900 gas per withdrawal and current gas rules).

`RETURN_DEPOSIT_PENALTY` disincentivizes rejected deposits, and imposes a gas cost of 144,927 Gwei / gas, assuming 6,900 gas per withdrawal. 

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).


</description>
        <pubDate>Fri, 12 Apr 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7684</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7684</guid>
      </item>
    
      <item>
        <title>General purpose execution layer requests</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7685-general-purpose-execution-layer-requests/19668</comments>
        
        <description>## Abstract

This proposal defines a general purpose framework for storing contract-triggered
requests. It extends the execution header with a single field to store the
request information. Requests are later on exposed to the consensus layer, which
then processes each one.

## Motivation

The proliferation of smart contract controlled validators has caused there to be
a demand for additional EL triggered behaviors. By allowing these systems to
delegate administrative operations to their governing smart contracts, they can
avoid intermediaries needing to step in and ensure certain operations occur.
This creates a safer system for end users. By abstracting each individual request
details from the EL, adding new request types is simpler and does not require an
update on the execution block structure.

## Specification

### Execution Layer

#### Requests

A `requests` object consists of a `request_type` byte prepended to an opaque byte array
`request_data`. The `request_data` contains zero or more encoded request objects.

```
requests = request_type ++ request_data
```

Each request type will define its own `requests` object with its own `request_data` format.

#### Block Header

Extend the header with a new 32 byte commitment value `requests_hash`.

While processing a block, multiple `requests` objects with different `request_type`s will
be produced by the system, and accumulated in the block requests list.

In order to compute the commitment, an intermediate hash list is first built by hashing
all non-empty requests elements of the block requests list. Items with empty
`request_data` are excluded, i.e. the intermediate list skips `requests` items which
contain only the `request_type` (1 byte) and nothing else.

Within the intermediate list, `requests` items must be ordered by `request_type` ascending.

The final commitment is computed as the sha256 hash of the intermediate element hashes.

```python
def compute_requests_hash(block_requests: Sequence[bytes]):
    m = sha256()
    for r in block_requests:
        if len(r) &gt; 1:
            m.update(sha256(r).digest())
    return m.digest()

block.header.requests_hash = compute_requests_hash(requests)
```

### Consensus Layer

Each proposal may choose how to extend the beacon chain types to include new EL request
types.

## Rationale

### Opaque byte array rather than an RLP array

By having the bytes of `request_data` array from second byte on be opaque bytes, rather
than an RLP (or other encoding) list, we can support different encoding formats for the
request payload in the future such as SSZ, LEB128, or a fixed width format.

### Request source and validity

This EIP makes no strict requirement where a request may come from nor when/how
a request must be validated. This is to provide future protocol designers
maximum flexibility.

The authors&apos; recommendations on source and validity of requests are:

* The source of requests should be from the execution of transactions. More
  specifically, transactions which make calls to designated system contracts
  that store the request in account. The storage would later be retrieved by a
  post-block system call to the contract. Alternatively, if the system call does
  not need to be inherently concerned with rate limiting, it could rely simply
  on emitting an event which is later parsed post-block by the system and
  converted into a request.
* A request&apos;s validity can often not be fully verified at the execution layer.
  This is why they are referred to merely as &quot;requests&quot;; they do not carry the
  authority on their own to unilaterally catalyze an action. We expect the system
  contracts to perform whatever validation is possible by the EL and then pass
  it on to the CL for further validation.

### Ordering

The ordering across types is ascending by type. This is to simplify the process
of verifying that all requests which were committed to in `requests_hash` match.

An alternative could be to order by when the request was generated within the
block. Since it&apos;s expected that many requests will be accumulated at the end of
the block via system calls, this would be difficult to enforce. Therefore,
ordering by type is the most straightforward ordering which ensures integrity.

#### Intra-type

Within the same type, order is not defined. This is because the data of the
request is opaque as far as this EIP is concerned. Therefore, it is to be
determined by each request type individually.

### Removing empty requests in commitment

We exclude empty requests elements from the `requests_hash` commitment in order to get a
stable &apos;empty&apos; hash value that is independent of the blockchain fork. For a block with no
requests data, the `requests_hash` is simply `sha256(&quot;&quot;)`.

## Backwards Compatibility

No backward compatibility issues found.

## Test Cases

TODO

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 14 Apr 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7685</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7685</guid>
      </item>
    
      <item>
        <title>Linear EVM memory limits</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7686-linear-evm-memory-limits/19448</comments>
        
        <description>## Abstract

Add a hard memory limit equal to the gas limit of the current context. Make the maximum gas cost of a sub-call depend on the memory used in the current context. The two rules together ensure that a transaction with N gas can use at most N bytes of memory.

## Motivation

Today, memory pricing rules are complicated: we have the quadratic cost for expanding memory as well as the 63/64 rule for how much gas can go into a child call. This also makes it extremely hard to calculate a maximum possible amount of memory required to process a given EVM execution.

The rules in this post simplify these rules, and add a new hard limit: an EVM execution with N gas can require at most N total bytes of memory to process. This limit is tight: there are easy ways for an N-gas call to use `N - O(1)` bytes of memory.

## Specification

Change `memory_cost` from:

```python
memory_size_word = (memory_byte_size + 31) / 32
memory_cost = (memory_size_word ** 2) / 512 + (3 * memory_size_word)
```

To:

```python
memory_size_word = (memory_byte_size + 31) / 32
memory_cost = 3 * memory_size_word
```

Additionally, if a memory expansion would lead to `memory_byte_size` strictly exceeding the current call&apos;s initial gas limit, revert with an error.

When making any type of call, change the maximum gas limit from the current [EIP-150](/EIPs/EIPS/eip-150) definition:

```python
def max_call_gas(gas):
    return gas - (gas // 64)
```

To:

```python
def max_call_gas(gas, memory_byte_size):
    return gas - max(gas // 64, memory_byte_size)
```

## Rationale

With this EIP, there is a simple EVM implementation that can process an N-gas call using an N-byte bytearray as memory: allocate all bytes to the current context, when doing a child call use the remaining memory starting from the position `memory_byte_size` for the child call&apos;s memory, and so on recursively.

Having this clean invariant is useful for EVM implementations, especially EVM implementations in constrained environments (eg. ZK-SNARK provers).

The 3 gas per word memory expansion cost is retained because it is equivalent to MCOPY, and so the operation of clearing memory at the end of a child call (cheap in regular machines, but more expensive in ZK-SNARKs and other unusual contexts) can be implemented with the same logic as that used to implement the MCOPY opcode itself.

The 63/64 rule is maintained in order to maintain the current de-facto call stack depth limit of roughly `1 + log((gaslimit + 6300) / 6400) / log(64/63) = 537`.

## Backwards Compatibility

It is theoretically possible for EVM code that works today to fail to work under this new EIP, if that code accesses a high index in memory but is called with a low gas limit. However, almost all EVM execution consumes far more code than it uses bytes of memory. For example, for a call to cause even a single state change, it must have at least 5000 gas. This would allow it 5000 bytes of memory, which is greater than that used by almost all applications. More complex applications would have even higher limits.

## Security Considerations

No security concerns were raised.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 15 Apr 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7686</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7686</guid>
      </item>
    
      <item>
        <title>Forward compatible consensus data structures</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7688-forward-compatible-consensus-data-structures/19673</comments>
        
        <description>## Abstract

This EIP defines the changes needed to adopt `ProgressiveContainer` from [EIP-7495](/EIPs/EIPS/eip-7495) and `ProgressiveList` from [EIP-7916](/EIPs/EIPS/eip-7916) in consensus data structures.

## Motivation

Ethereum&apos;s consensus data structures make heavy use of [Simple Serialize (SSZ)](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/ssz/simple-serialize.md) `Container`, which defines how they are serialized and merkleized. The merkleization scheme allows application implementations to verify that individual fields (and partial fields) have not been tampered with. This is useful, for example, in smart contracts of decentralized staking pools that wish to verify that participating validators have not been slashed.

While SSZ `Container` defines how data structures are merkleized, the merkleization is prone to change across the different forks. When that happens, e.g., because new features are added or old features get removed, existing verifier implementations need to be updated to be able to continue processing proofs.

`ProgressiveContainer`, of [EIP-7495](/EIPs/EIPS/eip-7495), is a forward compatible alternative that guarantees a forward compatible merkleization scheme. By transitioning consensus data structures to use `ProgressiveContainer`, smart contracts that contain verifier logic no longer have to be maintained in lockstep with Ethereum&apos;s fork schedule as long as the underlying features that they verify don&apos;t change. For example, as long as the concept of slashing is represented using the boolean `slashed` field, existing verifiers will not break when unrelated features get added or removed. This is also true for off-chain verifiers, e.g., in hardware wallets or in operating systems for mobile devices that are on a different software update cadence than Ethereum.

## Specification

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

### `Container` conversion

`Container` types that are expected to evolve over forks SHALL be redefined as `ProgressiveContainer(active_fields=[1] * len(type.fields()))`.

For example, given a type in the old fork:

```python
class Foo(Container):
    a: uint8
    b: uint16
```

This type can be converted to support stable Merkleization in the new fork:

```python
class Foo(ProgressiveContainer(active_fields=[1, 1])):
    a: uint8
    b: uint16
```

As part of the conversion, a stable [generalized index (gindex)](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/ssz/merkle-proofs.md#generalized-merkle-tree-index) is assigned to each field that remains valid in future forks.

- If a fork appends a field, `active_fields` MUST be extended with a trailing `1`.
- If a fork removes a field, the corresponding `active_fields` bit MUST be changed to `0`.
- Compatibility rules SHOULD be enforced, e.g., by defining a `CompatibleUnion[fork_1.Foo, fork_2.Foo, fork_3.Foo, ...]` type in the unit test framework.

### `List[type, N]` / `Bitlist` conversion

`List` types frequently have been defined with excessively large capacities `N` with the intention that `N` is never reached in practice. In other cases, the capacity itself has changed over time.

- `List` types with dynamic or unbounded capacity semantics SHALL be redefined as `ProgressiveList[type]`, and the application logic SHALL be updated to check for an appropriate limit at runtime.
- `Bitlist` types with dynamic or unbounded capacity semantics SHALL be redefined as `ProgressiveBitlist`

As part of the conversion, a stable [generalized index (gindex)](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/ssz/merkle-proofs.md#generalized-merkle-tree-index) is assigned to each list element that remains valid regardless of the number of added elements.

### Converted types

The following types SHALL be converted to `ProgressiveContainer`:

- [`Attestation`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/electra/beacon-chain.md#attestation)
  - The `aggregation_bits` field is redefined to use `ProgressiveBitlist`
- [`IndexedAttestation`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/electra/beacon-chain.md#indexedattestation)
  - The `attesting_indices` field is redefined to use `ProgressiveList`
- [`ExecutionPayload`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/deneb/beacon-chain.md#executionpayload)
  - The `transactions` and `withdrawals` fields are redefined to use `ProgressiveList`
  - The `MAX_TRANSACTIONS_PER_PAYLOAD` (1M) limit is no longer enforced (the limit is unreachable with `MAX_PAYLOAD_SIZE` 10 MB)
- [`ExecutionRequests`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/electra/beacon-chain.md#executionrequests)
  - The `deposits`, `withdrawals` and `consolidations` fields are redefined to use `ProgressiveList`
- [`BeaconBlockBody`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/electra/beacon-chain.md#beaconblockbody)
  - The `proposer_slashings`, `attester_slashings`, `attestations`, `deposits`, `voluntary_exits` and `bls_to_execution_changes` fields are redefined to use `ProgressiveList`
- [`BeaconState`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/electra/beacon-chain.md#beaconstate)
  - The `validators`, `balances`, `previous_epoch_participation`, `current_epoch_participation`, `inactivity_scores`, `pending_deposits`, `pending_partial_withdrawals` and `pending_consolidations` fields are redefined to use `ProgressiveList`
- The `blob_kzg_commitments`, `kzg_proofs` and `column` fields are redefined to use `ProgressiveList`

### Immutable types

These types are used as part of the `ProgressiveContainer` definitions, and, as they are not `ProgressiveContainer` themselves, are considered to have immutable Merkleization. If a future fork requires changing these types in an incompatible way, a new type SHALL be defined and assigned a new field name.

| Type | Description |
| - | - |
| [`Slot`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/phase0/beacon-chain.md#custom-types) | Slot number on the beacon chain |
| [`Epoch`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/phase0/beacon-chain.md#custom-types) | Epoch number on the beacon chain, a group of slots |
| [`CommitteeIndex`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/phase0/beacon-chain.md#custom-types) | Index of a committee within a slot |
| [`ValidatorIndex`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/phase0/beacon-chain.md#custom-types) | Unique index of a beacon chain validator |
| [`Gwei`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/phase0/beacon-chain.md#custom-types) | Amount in Gwei (1 ETH = 10^9 Gwei = 10^18 Wei) |
| [`Root`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/phase0/beacon-chain.md#custom-types) | Byte vector containing an SSZ Merkle root |
| [`Hash32`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/phase0/beacon-chain.md#custom-types) | Byte vector containing an opaque 32-byte hash |
| [`Version`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/phase0/beacon-chain.md#custom-types) | Consensus fork version number |
| [`BLSPubkey`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/phase0/beacon-chain.md#custom-types) | Cryptographic type representing a BLS12-381 public key |
| [`BLSSignature`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/phase0/beacon-chain.md#custom-types) | Cryptographic type representing a BLS12-381 signature |
| [`KZGCommitment`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/_features/sharding/polynomial-commitments.md#custom-types) | G1 curve point for the KZG polynomial commitment scheme |
| [`Fork`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/phase0/beacon-chain.md#fork) | Consensus fork information |
| [`Checkpoint`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/phase0/beacon-chain.md#checkpoint) | Tuple referring to the most recent beacon block up through an epoch&apos;s start slot |
| [`Validator`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/phase0/beacon-chain.md#validator) | Information about a beacon chain validator |
| [`AttestationData`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/phase0/beacon-chain.md#attestationdata) | Vote that attests to the availability and validity of a particular consensus block |
| [`Eth1Data`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/phase0/beacon-chain.md#eth1data) | Target tracker for importing deposits from transaction logs |
| [`DepositData`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/phase0/beacon-chain.md#depositdata) | Log data emitted as part of a transaction&apos;s receipt when depositing to the beacon chain |
| [`BeaconBlockHeader`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/phase0/beacon-chain.md#beaconblockheader) | Consensus block header |
| [`ProposerSlashing`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/phase0/beacon-chain.md#proposerslashing) | Tuple of two equivocating consensus block headers |
| [`Deposit`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/phase0/beacon-chain.md#deposit) | Tuple of deposit data and its inclusion proof |
| [`VoluntaryExit`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/phase0/beacon-chain.md#voluntaryexit) | Consensus originated request to exit a validator from the beacon chain |
| [`SignedVoluntaryExit`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/phase0/beacon-chain.md#signedvoluntaryexit) | Tuple of voluntary exit request and its signature |
| [`SyncAggregate`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/altair/beacon-chain.md#syncaggregate) | Cryptographic type representing an aggregate sync committee signature |
| [`ExecutionAddress`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/bellatrix/beacon-chain.md#custom-types) | Byte vector containing an account address on the execution layer |
| [`Transaction`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/bellatrix/beacon-chain.md#custom-types) | Byte list containing an RLP encoded transaction |
| [`WithdrawalIndex`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/capella/beacon-chain.md#custom-types) | Unique index of a withdrawal from any validator&apos;s balance to the execution layer |
| [`Withdrawal`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/capella/beacon-chain.md#withdrawal) | Withdrawal from a beacon chain validator&apos;s balance to the execution layer |
| [`DepositRequest`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/electra/beacon-chain.md#depositrequest) | Tuple of flattened deposit data and its sequential index |
| [`WithdrawalRequest`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/electra/beacon-chain.md#withdrawalrequest) | Execution originated request to withdraw from a validator to the execution layer |
| [`ConsolidationRequest`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/electra/beacon-chain.md#consolidation) | Execution originated request to consolidate two beacon chain validators |
| [`BLSToExecutionChange`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/capella/beacon-chain.md#blstoexecutionchange) | Request to register the withdrawal account address of a beacon chain validator |
| [`SignedBLSToExecutionChange`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/capella/beacon-chain.md#signedblstoexecutionchange) | Tuple of withdrawal account address registration request and its signature |
| [`ParticipationFlags`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/altair/beacon-chain.md#custom-types) | Participation tracker of a beacon chain validator within an epoch |
| [`HistoricalSummary`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/capella/beacon-chain.md#historicalsummary) | Tuple combining a historical block root and historical state root |
| [`PendingDeposit`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/electra/beacon-chain.md#pendingdeposit) | Pending operation for depositing to a beacon chain validator |
| [`PendingPartialWithdrawal`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/electra/beacon-chain.md#pendingpartialwithdrawal) | Pending operation for withdrawing from a beacon chain validator |
| [`PendingConsolidation`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/electra/beacon-chain.md#pendingconsolidation) | Pending operation for consolidating two beacon chain validators |

## Rationale

### Best timing?

Applying this EIP breaks `hash_tree_root` and Merkle tree verifiers a single time, while promising forward compatibility from the fork going forward. It is best to apply it before merkleization would be broken by different changes. Merkleization is broken by a `Container` reaching a new power of 2 in its number of fields.

### Can this be applied retroactively?

While `ProgressiveContainer` serializes in the same way as the legacy `Container`, the merkleization and `hash_tree_root` of affected data structures changes. Therefore, verifiers that wish to process Merkle proofs of legacy variants still need to support the corresponding legacy schemes.

### Immutability

Once a field in a `ProgressiveContainer` has been published, its name can no longer be used to represent a different type in the future. This is in line with historical management of certain cases:

- Phase0: `BeaconState` contained `previous_epoch_attestations` / `current_epoch_attestations`
- Altair: `BeaconState` replaced these fields with `previous_epoch_participation` / `current_epoch_participation`

Furthermore, new fields have to be appended at the end of `ProgressiveContainer`. This is in line with historical management of other cases:

- Capella appended `historical_summaries` to `BeaconState` instead of squeezing the new field next to `historical_roots`

With `ProgressiveContainer`, stable Merkleization requires these rules to become strict.

### Cleanup opportunities

#### `BeaconState`

- The `eth1_data`, `eth1_data_votes`, `eth1_deposit_index` and `deposit_requests_start_index` fields could be dropped as they are no longer needed after the [EIP-6110](/EIPs/EIPS/eip-6110#eth1data-poll-deprecation) transition period finishes.
- `historical_summaries` could be redefined to use `ProgressiveList` and also integrate the historical `historical_roots` data by merging in full `HistoricalSummary` data from an archive (`historical_root` is frozen since Capella), simplifying access to historical block and state roots.

#### `Attestation`

- The `committee_bits` is defined as a `Bitvector`, but the top bits are forced to 0 based on `get_committee_count_per_slot(state, data.target.epoch)`. It could be re-defined as a `ProgressiveBitlist`.

#### `IndexedAttestation`

The `attesting_indices` are limited to [`MAX_VALIDATORS_PER_COMMITTEE * MAX_COMMITTEES_PER_SLOT`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/electra/beacon-chain.md#indexedattestation), which is insufficient when the `IndexedAttestation` is formed from [`SingleAttestation`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/electra/beacon-chain.md#singleattestation) traffic. `SingleAttestation` allows validators that are not assigned to a slot to produce signatures that are not aggregatable into an `Attestation` (as such validators are not assigned), but that are still slashable.

Further, [`MAX_ATTESTER_SLASHINGS_ELECTRA`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/electra/beacon-chain.md#max-operations-per-block) at 1 limits inclusion efficiency of slashings in non-finality scenarios with a lot of forks where slashings happen across multiple different `AttestationData` values.

Limits could be rethought to be based on actual resource usage, e.g., by limiting:

- The total number of `attesting_indices` across all `AttesterSlashing` (shared total)
- The total number of signature checks across all `AttesterSlashing`, `ProposerSlashing`, `VoluntaryExit`, and `SignedBLSToExecutionChange` messages

Limiting totals rather than individual resources would allow extra attester slashings to be included at the cost of potentially delaying inclusion of a couple altruistic messages (if there even are any `VoluntaryExit` / `SignedBLSToExecutionChange` messages at that time), thus increasing security and block packing efficiency.

#### `ExecutionPayload`

The `block_hash` field could be moved to the top of `ExecutionPayload`, reducing the Merkle proof size.

#### `ExecutionRequests`

As deposits cannot be retried by the user (they pay the ETH upfront), deposit requests cannot fizzle like other requests; they are always included in the same block (since Pectra). For that reason, the current `MAX_DEPOSIT_REQUESTS_PER_PAYLOAD` (8192) is essentially unbounded at current gas limits, but may eventually become reachable (around ~192M gas, or earlier with gas repricings). The CL limit for deposit requests could be dropped to avoid scaling issues, instead solely relying on EL backpressure (gas fees, 1 ETH deposit minimum).

For other requests (withdrawal / consolidation requests), a shared total limit based on the added CL state size could provide more flexibility than the current per-operation limits. For example, in times without consolidation requests, space could be used to enqueue more withdrawal requests.

#### `BeaconBlockHeader`

The `BeaconBlockHeader` is currently proposed to be kept as is. Updating the `BeaconBlockHeader` to `ProgressiveContainer` is tricky as it breaks `hash_tree_root(latest_block_header)` in the `BeaconState`. One option could be to store `latest_block_header_root` separately, possibly also incorporating the block proposer signature into the hash to avoid proposer signature checks while backfilling historical blocks.

#### `Validator`

The `Validator` container is currently proposed to be kept as is. Updating the `Validator` to `ProgressiveContainer` would add an extra hash for each validator; validators are mostly immutable so rarely need to be re-hashed. With a conversion, implementations may have to incrementally construct the new `Validator` entries ahead of the fork when validator counts are high. It should be evaluated whether the hashing overhead is worth a clean transition to future fields, e.g., for holding postquantum keys. Also consider that such a transition may also involve a new hash function, which is a breaking change to the Merkle proofs, so generalized indices do not have to be stable across that transition.

## Backwards Compatibility

Existing Merkle proof verifiers need to be updated to support the new Merkle tree shape. This includes verifiers in smart contracts on different blockchains and verifiers in hardware wallets, if applicable.

## Security Considerations

Before this EIP, all `List` types had a fixed upper bound, enabling implementations to reject messages exceeding that size early. With `ProgressiveList`, that is no longer possible, as there is no more maximum message size. Instead, the length checks have to be implemented as part of P2P gossip validation, and as part of the state transition logic. However, many of the limits are not practically reachable (e.g., the gas limit is reached before the maximum payload size). Further note that SSZ is simple enough that clever implementations could still enforce those length checks on the serialized data, before fully decoding it.

All data inbound via libp2p is decrypted, then uncompressed with Snappy, then hashed with `MESSAGE_DOMAIN_VALID_SNAPPY` / `MESSAGE_DOMAIN_INVALID_SNAPPY` prefix depending on whether the decompression worked to compute the libp2p message ID, while honoring a global `MAX_PAYLOAD_SIZE` message size limit. This has to be done even if the underlying SSZ data ends up being invalid.

As SSZ does not use variable-length encoding, it does not have uncontrolled blowup (no 1 byte becomes 100 MB). Therefore, attempting to decode a `MAX_PAYLOAD_SIZE` message before checking dynamic `List` limits does not decrease security. Any intentional DoS attacks can already target a heavier portion of the processing pipeline (e.g., by sending invalid BLS signatures, or by sending invalid Snappy data that still needs to be hashed to compute the message ID). Therefore, the EIP does not notably impact security.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 15 Apr 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7688</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7688</guid>
      </item>
    
      <item>
        <title>Blob throughput increase</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7691-blob-throughput-increase/19694</comments>
        
        <description>## Abstract

Increases the number of blobs in a block to provide more scale to Ethereum via L2 solution that rely on L1 data capacity.

## Motivation

Ethereum, with its rollup centric roadmap, scales by relying on L2. Since the Dencun fork, the blob gas target and maximum was set to 3/6 respectively. The blob gas limit was arrived at based on a series of big block tests performed on the Ethereum mainnet network as well as a series of testnets. The values were chosen cautiously, as it&apos;s extremely hard to predict the exact p2p behaviour of Ethereum mainnet.

As we now have the Dencun upgrade live, we are able to use monitoring tools to check the network health. Initial monitoring indicates that we have a stable network with the current gas target and the re-org rate is trending downwards. Additionally, analysis on messages in gossipsub indicate that the inclusion of `IDONTWANT` messages could bring us a significant bandwidth savings. This allows us to consider starting a series of big block and blob tests to determine the theoretical headroom we currently have. The EIP specifies a proposed new blob gas target and limit based on the series of tests.

This EIP aims to increase the throughput short term to provide some scaling until future solutions are deployed. In order to alleviate valid concerns about solo-stakers, approaches such as the inclusion of a flag indicating the max blobs per block for locally built blocks could be considered.

## Specification

### Parameters

| Constant                                 | Value               |
|------------------------------------------|---------------------|
| `MAX_BLOBS_PER_BLOCK_ELECTRA`            | `9`                 |
| `TARGET_BLOBS_PER_BLOCK_ELECTRA`         | `6`                 |
| `MAX_BLOB_GAS_PER_BLOCK`                 | `1179648`           |
| `TARGET_BLOB_GAS_PER_BLOCK`              | `786432`            |
| `BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE`  | `5007716`           |

`MAX_BLOBS_PER_BLOCK_ELECTRA` and `TARGET_BLOBS_PER_BLOCK_ELECTRA` are consumed by the consensus layer clients, and starting at `PECTRA_FORK_EPOCH` replace the respective old max and target values.

`MAX_BLOB_GAS_PER_BLOCK`, `TARGET_BLOB_GAS_PER_BLOCK` and `BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE` are consumed by the execution layer clients, and starting at the epoch when this EIP is activated, replace the old max, target and update fraction values.
Any references to `MAX_BLOB_GAS_PER_BLOCK` and `TARGET_BLOB_GAS_PER_BLOCK` in [EIP-4844](/EIPs/EIPS/eip-4844) should be updated to the new values defined in this EIP when processing the activation block.
The value `BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE` replaces its previous equivalent when processing the activation block.
These changes imply that `get_base_fee_per_blob_gas` and `calc_excess_blob_gas` functions defined in [EIP-4844](/EIPs/EIPS/eip-4844) use the new values for the first block of the fork (and for all subsequent blocks).

## Rationale

### Simplicity

The EIP aims to minimize the amount of testing and implementation effort from the perspective of the client teams, to allow for more resources to be allocated to peerDAS and other scaling research.

While this EIP may not achieve the new optimal blob limit, it offers a compromise for a short term increase.

### Update Fraction

The original target and max values from [EIP-4844](/EIPs/EIPS/eip-4844) were at a 1:2 ratio. As a consequence, responsiveness to full and empty blob sections was symmetrical:

* full blobs: basefee increases by ~12.5%
* no blobs: basefee decreases by ~11.1%

The new target and max values from this EIP are at a 2:3 ratio, which breaks that symmetry. As a consequence, the basefee becomes significantly more responsive to empty blob sections (that are 6 blobs under target) than to full ones (that are 3 blobs over target). This is by design, as it takes two blocks with full blobs in a row to make up for a single block with no blobs. However, it creates the challenge of finding a good compromise base fee sensitivity level.

The `BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE` value in this EIP is chosen as the mid-point between keeping the responsiveness to full blobs and no blobs constant:

* full blobs: basefee increases by ~8.2%
* no blobs: basefee decreases by ~14.5%

## Backwards Compatibility

The consensus clients would continue to use `MAX_BLOBS_PER_BLOCK` and `TARGET_BLOBS_PER_BLOCK` for the deneb fork and once the `ELECTRA` fork is active, they would use `MAX_BLOBS_PER_BLOCK_ELECTRA` and `TARGET_BLOBS_PER_BLOCK_ELECTRA` respectively.

The execution clients would continue to use `MAX_BLOB_GAS_PER_BLOCK`, `TARGET_BLOB_GAS_PER_BLOCK` and `BLOB_BASE_FEE_UPDATE_FRACTION` for the cancun fork and once the prague fork is active, they would use `MAX_BLOB_GAS_PER_BLOCK`, `TARGET_BLOB_GAS_PER_BLOCK` and `BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE` respectively.

## Security Considerations

### Network Impacts

Through the use of big block/blob tests on Ethereum mainnet as well as testnets, we can earn a high degree of certainty that the blob limit increase would not negatively impact the network. These tests as well as the associated analysis can be performed mostly by non-client team entities, with minimal input required. Since the changes are quite contained, the EIP should be able to reduce the risk of the blob limit increase.

### Stability Around Fork Epoch

A blob limit increase at the fork transition is relatively straightforward from an implementation perspective. We would need to deploy an increased amount of monitoring around the fork epoch, but after a period of stability we can assume that the blob limit increase was successful, reducing any unexpected co-ordination efforts.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 17 Apr 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7691</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7691</guid>
      </item>
    
      <item>
        <title>EVM Object Format (EOFv1) Meta</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7692-evm-object-format-eof-meta/19686</comments>
        
        <description>## Abstract

This Meta EIP lists the EIPs which belong to the EVM Object Format (EOF) proposal, in its first version (EOFv1), also known as the &quot;Mega EOF&quot;.

## Specification

### EIPs Included

Introduced in eof-devnet-0

- [EIP-3540](/EIPs/EIPS/eip-3540): EOF - EVM Object Format v1
- [EIP-3670](/EIPs/EIPS/eip-3670): EOF - Code Validation
- [EIP-4200](/EIPs/EIPS/eip-4200): EOF - Static relative jumps
- [EIP-4750](/EIPs/EIPS/eip-4750): EOF - Functions
- [EIP-5450](/EIPs/EIPS/eip-5450): EOF - Stack Validation
- [EIP-6206](/EIPs/EIPS/eip-6206): EOF - JUMPF and non-returning functions
- [EIP-7480](/EIPs/EIPS/eip-7480): EOF - Data section access instructions
- [EIP-663](/EIPs/EIPS/eip-663): SWAPN, DUPN and EXCHANGE instructions
- [EIP-7069](/EIPs/EIPS/eip-7069): Revamped CALL instructions
- [EIP-7620](/EIPs/EIPS/eip-7620): EOF Contract Creation
- [EIP-7698](/EIPs/EIPS/eip-7698): EOF - Creation transaction

Introduced in eof-devnet-1

- [EIP-7873](/EIPs/EIPS/eip-7873): EOF - TXCREATE and InitcodeTransaction type

Removed from eof-devnet-1

- [EIP-7698](/EIPs/EIPS/eip-7698): EOF - Creation transaction

Introduced in eof-devnet-2

- [EIP-7834](/EIPs/EIPS/eip-7834): Separate Metadata Section for EOF
- [EIP-7761](/EIPs/EIPS/eip-7761): EXTCODETYPE instruction
- [EIP-7880](/EIPs/EIPS/eip-7880): EOF - EXTCODEADDRESS instruction
- [EIP-5920](/EIPs/EIPS/eip-5920): PAY opcode



## Rationale

Refer to the individual EIPs.

## Security Considerations

Discussed in the individual EIPs.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 17 Apr 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7692</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7692</guid>
      </item>
    
      <item>
        <title>Solana Storage Router</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7694-solana-storage-router/19706</comments>
        
        <description>## Abstract

The following standard is an extension to the cross-chain storage router protocol introducing the storage router for Solana blockchain. With this specification, any Ethereum L1 contract can defer a call to Solana blockchain as part of its core functionality, provided that the client is equipped to handle Solana transactions. It was previously possible to defer write and storage operations to other Ethereum L1 contracts, L2 contracts and off-chain databases, and this document extends that functionality to include alternative L1 chains. The data stored on Solana must be translated to [EIP-3668](./eip-3668)-compliant format by an appropriate HTTP gateway where it can be retrieved by generic Ethereum contracts. This standard allows Ethereum to utilise a broader range of cross-chain blockspaces.

## Motivation

Cross-Chain Storage Router Protocol (CCIP-Store) introduced in [EIP-7700](./eip-7700), describes three external routers for routing storage to L1 contracts, L2s and databases. This document extends that specification by introducing a fourth storage router targeting Solana as the storage provider.

L2s and databases both have centralising catalysts in their stack. For L2s, this centralising agent is the shared security with Ethereum mainnet. In case of databases, the centralising agent is trivial; it is the physical server hosting the database. In light of this, a storage provider that relies on its own independent consensus mechanism is preferred. This specification instructs how the clients should treat storage calls made to the Solana router.

Solana is a low cost L1 solution that is supported alongside Ethereum by multiple wallet providers. There are several chain-agnostic protocols on Ethereum which could benefit from direct access to Solana blockspace; ENS is one such example where it can serve users of Solana via its chain-agnostic properties while also using Solana&apos;s own native storage. This development will encourage more cross-chain functionalities between Ethereum and Solana at core.

![Fig.1 CCIP-Store and CCIP-Read Workflows](/EIPs/assets/eip-7694/images/Schema.svg)

## Specification

A Solana storage router `StorageRoutedToSolana()` requires the hex-encoded `programId` and the manager `account` on the Solana blockchain. `programId` is equivalent to a contract address on Solana while `account` is the manager wallet on Solana handling storage on behalf of `msg.sender`.

```solidity
// Revert handling Solana storage router
error StorageRoutedToSolana(
    bytes32 programId,
    bytes32 account
);

// Generic function in a contract
function setValue(
    bytes32 node,
    bytes32 key,
    bytes32 value
) external {
    // Get metadata from on-chain sources
    (
        bytes32 programId, // Program (= contract) address on Solana; hex-encoded
        bytes32 account // Manager account on Solana; hex-encoded
    ) = getMetadata(node); // Arbitrary code
    // programId = 0x37868885bbaf236c5d2e7a38952f709e796a1c99d6c9d142a1a41755d7660de3
    // account = 0xe853e0dcc1e57656bd760325679ea960d958a0a704274a5a12330208ba0f428f
    // Route storage call to Solana router
    revert StorageRoutedToSolana(
        programId,
        account
    );
};
```

Since Solana natively uses `base58` encoding in its virtual machine setup, `programId` values that are hex-encoded on EVM must be `base58`-decoded for usage on SVM. Clients implementing the Solana router must call the Solana `programId` using a Solana wallet that is connected to `account` using the `base58`-decoded (and casted to appropriate data type) calldata that it originally received.

```js
/* Pseudo-code to write to Solana program (= contract) */
// Decode all &apos;bytes32&apos; types in EVM to &apos;PubKey&apos; type in SVM
const [programId, account, node, key, value] = E2SVM(
  [programId, account, node, key, value],
  [&quot;bytes32&quot;, &quot;bytes32&quot;, &quot;bytes32&quot;, &quot;bytes32&quot;, &quot;bytes32&quot;]
);
// Instantiate program interface on Solana
const program = new program(programId, rpcProvider);
// Connect to Solana wallet
const wallet = useWallet();
// Call the Solana program using connected wallet with initial calldata
// [!] Only approved manager in the Solana program should call
if (wallet.publicKey === account) {
  await program(wallet).setValue(node, key, value);
}
```

In the above example, EVM-specific `bytes32`-type variables `programId`, `account`, `node`, `key` and `value` must all be converted to SVM-specific `PubKey` data type. The equivalent `setValue()` function in the Solana program is of the form

```rust
// Example function in Solana program
pub fn setValue(
    ctx: Context,
    node: PubKey,
    key: PubKey,
    value: PubKey
) -&gt; ProgramResult {
    // Code to verify PROGRAM_ID and rent exemption status
    ...
    // Code for de-serialising, updating and re-serialising the data
    ...
    // Store serialised data in account
    // [!] Stored data must be mapped by node &amp; account
    ...
}
```

Since EVM and SVM have differing architectures, it is important to define precise data type castings from EVM to SVM. Some pre-existing custom but popular data types in SVM already equate to common EVM data types such as `PubKey` and `bytes32` respectively. This specification requires the following implementation of bijective EVM to SVM type casting:

|    EVM    |        SVM        |
| :-------: | :---------------: |
|  `uint8`  |       `u8`        |
| `uint16`  |       `u16`       |
| `uint32`  |       `u32`       |
| `uint64`  |       `u64`       |
| `uint128` |      `u128`       |
| `uint256` |      `u256`†      |
| `bytes1`  | `bytes: [u8; 1]`  |
| `bytes2`  | `bytes: [u8; 2]`  |
| `bytes4`  | `bytes: [u8; 4]`  |
| `bytes8`  | `bytes: [u8; 8]`  |
| `bytes16` | `bytes: [u8; 16]` |
| `bytes32` |     `PubKey`      |
|  `bytes`  | `bytes: Vec&lt;u8&gt;`  |
| `string`  |     `String`      |
| `address` | `bytes: [u8; 20]` |

&gt; † `u256` is not available natively in SVM but is routinely implemented via `u256` crate in Rust

Using this strategy, most - if not all - current use-cases of `StorageRoutedToSolana()` are accounted for.

Finally, in order to read the cross-chain data stored on Solana in an arbitrary Ethereum contract, it must be translated back into EVM tongue by an [EIP-3668](./eip-3668)-compliant HTTP gateway. The arguments for a generic call to the gateway URL must be specified in the `/`-delimited nested format as described in [EIP-7700](./eip-7700). The core of such a gateway must follow

```js
/* Pseudo-code of an ERC-3668-compliant HTTP gateway tunneling Solana content to Ethereum */
// CCIP-Read call by contract to a known gateway URL; gatewayUrl = &apos;https://read.solana.namesys.xyz/&lt;programId&gt;/&lt;node&gt;/&lt;key&gt;/&apos;
const [programId, node, key] = parseQuery(path); // Parse query parameters from path; path = &apos;/&lt;programId&gt;/&lt;node&gt;/&lt;key&gt;/&apos;
// Decode &apos;bytes32&apos; types in EVM to &apos;PubKey&apos; type in SVM
const [programId, node, key] = E2SVM(
  [programId, node, key],
  [&quot;bytes32&quot;, &quot;bytes32&quot;, &quot;bytes32&quot;]
);
// Instantiate program interface on Solana
const program = new program(programId, rpcProvider);
// Call the Solana program to read in cross-chain data
const value = await program.getValue(node, key);
if (value !== &quot;NOT_FOUND&quot;) {
  // Decode &apos;PubKey&apos; type in SVM to &apos;bytes32&apos; type in EVM
  const value = S2EVM(value, &quot;PubKey&quot;);
} else {
  // Null value
  const value = &quot;0x0&quot;;
}
// Compile CCIP-Read-compatible payload
const data = abi.encode([&quot;bytes&quot;], [value]);
// Create HTTP gateway emitting value in format &apos;data: ...&apos;
emitERC3668(data);
```

In the above example, the generic `getValue()` function in the Solana program is of the form

```rust
// Example getValue() function in Solana program
pub fn getValue&lt;&apos;a&gt;(
    ctx: Context,
    node: Pubkey,
    key: Pubkey,
    account: &amp;AccountInfo&lt;&apos;a&gt;, // Lifetime-bound parameter
) -&gt; Result&lt;Pubkey, ProgramError&gt; {
    // Validate that the account belongs to the correct program ID
    ...
    // Retrieve the data from the account
    let data = &amp;account.data.borrow();
    // De-serialise the data from the account
    ...
    // Look up the value by node and key
    match deserialised.get(&amp;node, &amp;key) {
        Some(value) =&gt; {
            msg!(&quot;VALUE: {:?}&quot;, value);
            Ok(value)
        },
        None =&gt; {
            msg!(&quot;NOT_FOUND&quot;);
            Err(ProgramError::InvalidArgument)
        }
    }
}
```

## Rationale

`StorageRoutedToSolana()` works in a similar fashion to `StorageRoutedToL2()` in CCIP-Store in the sense that the client needs to be pointed to a certain contract on another chain by the revert event. Other than that, the only technical difference is casting between EVM and SVM data types.

![Fig.2 Solana Call Lifecycle](/EIPs/assets/eip-7694/images/Solana.svg)

## Backwards Compatibility

None.

## Security Considerations

None.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 18 Apr 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7694</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7694</guid>
      </item>
    
      <item>
        <title>Ownership Delegation and Context for ERC-721</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7695-ownership-delegation-and-context-for-non-fungible-token/19716</comments>
        
        <description>## Abstract

This standard is an extension for [ERC-721](/EIPs/EIPS/eip-721), designed to specify users for various contexts with a locking feature and allow temporary ownership delegation without changing the original owner.

This EIP preserves the benefits and rights of the owner while expanding the utility of NFTs across various dApps by adding the concepts of Ownership Delegation and Contexts, which define specific roles: Controller and User, who can use the NFT within defined contexts.

## Motivation

For standard [ERC-721](/EIPs/EIPS/eip-721) NFTs, there are several use cases in financial applications, including:

- Staking NFTs to earn rewards.
- Mortgaging an NFT to generate income.
- Granting users for different purposes like rental and token delegation—where someone pays to use tokens and pays another party to use the tokens.

Traditionally, these applications require ownership transfers to lock the NFT in contracts. However, other decentralized applications (dApps) recognize token ownership as proof that the token owner is entitled to benefits within their reward systems, such as airdrops or tiered rewards. If token owners have their tokens locked in contracts, they are not eligible to receive benefits from holding these tokens, or the reward systems have to support as many contracts as possible to help these owners.

This is because there is only an Owner role indicating the ownership rights, developing on top of [ERC-721](/EIPs/EIPS/eip-721) has often posed challenges. This proposal aims to solve these challenges by contextualizing the use case to be handled by controllers and distinguishing ownership rights from other roles at the standard level through an ownership delegation mechanism. Standardizing these measures, dApp developers can more easily construct infrastructure and protocols on top of this standard.

## Specification

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.

### Definitions

This specification encompasses the following components:

**Token Context** provides a specified use case of a token. It serves as the association relationship between Tokens and Contexts. Within each unique token context, there exists an allocated user who is authorized to utilize the token within that context. In a specified context, there are two distinct roles:

- **Controller**: This role possesses the authority to control the context.
- **User**: This role signifies the primary token user within the given context.

**Ownership Rights** of a token are defined to be able to:

- Transfer that token to a new owner.
- Add token context(s): attaching that token to/from one or many contexts.
- Remove token context(s): detaching that token to/from one or many contexts.

**Ownership Delegation** involves distinguishing between owner and ownership rights by delegating ownership to other accounts for a specific duration. During this period, owners temporarily cede ownership rights until the delegation expires.

### Roles

| Roles               | Explanation / Permission                                                                                                                                | Quantity per Token |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
| Owner               | • Has **Ownership Rights** by default&lt;br&gt;• Delegates an account to hold **Ownership Rights** in a duration                                              | $1$                |
| Ownership Delegatee | • Has **Ownership Rights** in a delegation duration&lt;br&gt;• Renounces before delegation expires                                                            | $1$                |
| Ownership Manager   | • Is one who holds **Ownership Rights**&lt;br&gt;• If not delegated yet, it is referenced to **Owner**, otherwise it is referenced to **Ownership Delegatee** | $1$                |
| **Context Roles**   |                                                                                                                                                         | $n$                |
| Controller          | • Transfers controller&lt;br&gt;• Sets context user&lt;br&gt;• (Un)locks token transfer                                                                             | $1$ per context    |
| User                | • Authorized to use token in its context                                                                                                                | $1$ per context    |

### Interface

**Smart contracts implementing this standard MUST implement all the functions in the `IERC7695` interface.**

Smart contracts implementing this standard MUST implement the [ERC-165](/EIPs/EIPS/eip-165) `supportsInterface` function and MUST return the constant value `true` if `0x486b6fba` is passed through the `interfaceID` argument.

```solidity
/// Note: the ERC-165 identifier for this interface is 0x486b6fba.
interface IERC7695 /* is IERC721, IERC165 */ {
  /// @dev This emits when a context is updated by any mechanism.
  event ContextUpdated(bytes32 indexed ctxHash, address indexed controller, uint64 detachingDuration);
  /// @dev This emits when a token is attached to a certain context by any mechanism.
  event ContextAttached(bytes32 indexed ctxHash, uint256 indexed tokenId);
  /// @dev This emits when a token is requested to detach from a certain context by any mechanism.
  event ContextDetachmentRequested(bytes32 indexed ctxHash, uint256 indexed tokenId);
  /// @dev This emits when a token is detached from a certain context by any mechanism.
  event ContextDetached(bytes32 indexed ctxHash, uint256 indexed tokenId);
  /// @dev This emits when a user is assigned to a certain context by any mechanism.
  event ContextUserAssigned(bytes32 indexed ctxHash, uint256 indexed tokenId, address indexed user);
  /// @dev This emits when a token is (un)locked in a certain context by any mechanism.
  event ContextLockUpdated(bytes32 indexed ctxHash, uint256 indexed tokenId, bool locked);
  /// @dev This emits when the ownership delegation is started by any mechanism.
  event OwnershipDelegationStarted(uint256 indexed tokenId, address indexed delegatee, uint64 until);
  /// @dev This emits when the ownership delegation is accepted by any mechanism.
  event OwnershipDelegationAccepted(uint256 indexed tokenId, address indexed delegatee, uint64 until);
  /// @dev This emits when the ownership delegation is stopped by any mechanism.
  event OwnershipDelegationStopped(uint256 indexed tokenId, address indexed delegatee);

  /// @notice Gets the longest duration the detaching can happen.
  function maxDetachingDuration() external view returns (uint64);

  /// @notice Gets controller address and detachment duration of a context.
  /// @dev MUST revert if the context is not existent.
  /// @param ctxHash            A hash of context to query the controller.
  /// @return controller        The address of the context controller.
  /// @return detachingDuration The duration must be waited for detachment in second(s).
  function getContext(bytes32 ctxHash) external view returns (address controller, uint64 detachingDuration);

  /// @notice Creates a new context.
  /// @dev MUST revert if the context is already existent.
  /// MUST revert if the controller address is zero address.
  /// MUST revert if the detaching duration is larger than max detaching duration.
  /// MUST emit the event {ContextUpdated} to reflect context created and controller set.
  /// @param controller        The address that controls the created context.
  /// @param detachingDuration The duration must be waited for detachment in second(s).
  /// @param ctxMsg            The message of new context to be used for hashing.
  /// @return ctxHash          Hash of the created context.
  function createContext(address controller, uint64 detachingDuration, bytes calldata ctxMsg)
    external
    returns (bytes32 ctxHash);

  /// @notice Updates an existing context.
  /// @dev MUST revert if method caller is not the current controller.
  /// MUST revert if the context is non-existent.
  /// MUST revert if the new controller address is zero address.
  /// MUST revert if the detaching duration is larger than max detaching duration.
  /// MUST emit the event {ContextUpdated} on success.
  /// @param ctxHash              Hash of the context to set.
  /// @param newController        The address of new controller.
  /// @param newDetachingDuration The new duration must be waited for detachment in second(s).
  function updateContext(bytes32 ctxHash, address newController, uint64 newDetachingDuration) external;

  /// @notice Queries if a token is attached to a certain context.
  /// @param ctxHash Hash of a context.
  /// @param tokenId The NFT to query.
  /// @return        True if the token is attached to the context, false if not.
  function isAttachedWithContext(bytes32 ctxHash, uint256 tokenId) external view returns (bool);

  /// @notice Attaches a token with a certain context.
  /// @dev See &quot;attachContext rules&quot; in &quot;Token (Un)lock Rules&quot;.
  /// @param ctxHash Hash of a context.
  /// @param tokenId The NFT to be attached.
  /// @param data    Additional data with no specified format, MUST be sent unaltered in call to the {IERC7695ContextCallback} hook(s) on controller.
  function attachContext(bytes32 ctxHash, uint256 tokenId, bytes calldata data) external;

  /// @notice Requests to detach a token from a certain context.
  /// @dev See &quot;requestDetachContext rules&quot; in &quot;Token (Un)lock Rules&quot;.
  /// @param ctxHash Hash of a context.
  /// @param tokenId The NFT to be detached.
  /// @param data    Additional data with no specified format, MUST be sent unaltered in call to the {IERC7695ContextCallback} hook(s) on controller.
  function requestDetachContext(bytes32 ctxHash, uint256 tokenId, bytes calldata data) external;

  /// @notice Executes context detachment.
  /// @dev See &quot;execDetachContext rules&quot; in &quot;Token (Un)lock Rules&quot;.
  /// @param ctxHash Hash of a context.
  /// @param tokenId The NFT to be detached.
  /// @param data    Additional data with no specified format, MUST be sent unaltered in call to the {IERC7695ContextCallback} hook(s) on controller.
  function execDetachContext(bytes32 ctxHash, uint256 tokenId, bytes calldata data) external;

  /// @notice Finds the context user of a token.
  /// @param ctxHash Hash of a context.
  /// @param tokenId The NFT to be detached.
  /// @return user   Address of the context user.
  function getContextUser(bytes32 ctxHash, uint256 tokenId) external view returns (address user);

  /// @notice Updates the context user of a token.
  /// @dev MUST revert if the method caller is not context controller.
  /// MUST revert if the context is non-existent.
  /// MUST revert if the token is not attached to the context.
  /// MUST emit the event {ContextUserAssigned} on success.
  /// @param ctxHash Hash of a context.
  /// @param tokenId The NFT to be update.
  /// @param user    Address of the new user.
  function setContextUser(bytes32 ctxHash, uint256 tokenId, address user) external;

  /// @notice Queries if the lock a token is locked in a certain context.
  /// @param ctxHash Hash of a context.
  /// @param tokenId The NFT to be queried.
  /// @return        True if the token context is locked, false if not.
  function isTokenContextLocked(bytes32 ctxHash, uint256 tokenId) external view returns (bool);

  /// @notice (Un)locks a token in a certain context.
  /// @dev See &quot;setContextLock rules&quot; in &quot;Token (Un)lock Rules&quot;.
  /// @param ctxHash Hash of a context.
  /// @param tokenId The NFT to be queried.
  /// @param lock    New status to be (un)locked.
  function setContextLock(bytes32 ctxHash, uint256 tokenId, bool lock) external;

  /// @notice Finds the ownership manager of a specified token.
  /// @param tokenId  The NFT to be queried.
  /// @return manager Address of delegatee.
  function getOwnershipManager(uint256 tokenId) external view returns(address manager);

  /// @notice Finds the ownership delegatee of a token.
  /// @dev MUST revert if there is no (or an expired) ownership delegation.
  /// @param tokenId    The NFT to be queried.
  /// @return delegatee Address of delegatee.
  /// @return until     The delegation expiry time.
  function getOwnershipDelegatee(uint256 tokenId) external view returns (address delegatee, uint64 until);

  /// @notice Finds the pending ownership delegatee of a token.
  /// @dev MUST revert if there is no (or an expired) pending ownership delegation.
  /// @param tokenId    The NFT to be queried.
  /// @return delegatee Address of pending delegatee.
  /// @return until     The delegation expiry time in the future.
  function pendingOwnershipDelegatee(uint256 tokenId) external view returns (address delegatee, uint64 until);

  /// @notice Starts ownership delegation and retains ownership until a specific timestamp.
  /// @dev Replaces the pending delegation if any.
  /// See &quot;startDelegateOwnership rules&quot; in &quot;Ownership Delegation Rules&quot;.
  /// @param tokenId   The NFT to be delegated.
  /// @param delegatee Address of new delegatee.
  /// @param until     The delegation expiry time.
  function startDelegateOwnership(uint256 tokenId, address delegatee, uint64 until) external;

  /// @notice Accepts ownership delegation request.
  /// @dev See &quot;acceptOwnershipDelegation rules&quot; in &quot;Ownership Delegation Rules&quot;.
  /// @param tokenId The NFT to be accepted.
  function acceptOwnershipDelegation(uint256 tokenId) external;

  /// @notice Stops the current ownership delegation.
  /// @dev See &quot;stopOwnershipDelegation rules&quot; in &quot;Ownership Delegation Rules&quot;.
  /// @param tokenId The NFT to be stopped.
  function stopOwnershipDelegation(uint256 tokenId) external;
}
```

**Enumerable extension**

The enumeration extension is OPTIONAL for this standard. This allows your contract to publish its full list of contexts and make them discoverable. When calling the `supportsInterface` function MUST return the constant value `true` if `0xcebf44b7` is passed through the `interfaceID` argument.

```solidity
/// Note: the ERC-165 identifier for this interface is 0xcebf44b7.
interface IERC7695Enumerable /* is IERC165 */ {
  /// @dev Returns a created context in this contract at `index`.
  /// An index must be a value between 0 and {getContextCount}, non-inclusive.
  /// Note: When using {getContext} and {getContextCount}, make sure you perform all queries on the same block.
  function getContext(uint256 index) external view returns(bytes32 ctxHash);

  /// @dev Returns the number of contexts created in the contract.
  function getContextCount() external view returns(uint256);

  /// @dev Returns a context attached to a token at `index`.
  /// An index must be a value between 0 and {getAttachedContextCount}, non-inclusive.
  /// Note: When using {getAttachedContext} and {getAttachedContextCount}, make sure you perform all queries on the same block.
  function getAttachedContext(uint256 tokenId, uint256 index) external view returns(bytes32 ctxHash);

  /// @dev Returns the number of contexts attached to the token.
  function getAttachedContextCount(uint256 tokenId) external view returns(uint256);
}
```

**Controller Interface**

The controller is RECOMMENDED to be a contract and including callback methods to allow callbacks in cases where there are any attachment or detachment requests. When calling the `supportsInterface` function MUST return the constant value `true` if `0xad0491f1` is passed through the `interfaceID` argument.

```solidity
/// Note: the ERC-165 identifier for this interface is 0xad0491f1.
interface IERC7695ContextCallback /* is IERC165 */  {
  /// @dev This method is called once the token is attached by any mechanism.
  /// This function MAY throw to revert and reject the attachment.
  /// @param ctxHash  The hash of context invoked this call.
  /// @param tokenId  NFT identifier which is being attached.
  /// @param operator The address which called {attachContext} function.
  /// @param data     Additional data with no specified format.
  function onAttached(bytes32 ctxHash, uint256 tokenId, address operator, bytes calldata data) external;

  /// @dev This method is called once the token detachment is requested by any mechanism.
  /// @param ctxHash  The hash of context invoked this call.
  /// @param tokenId  NFT identifier which is being requested for detachment.
  /// @param operator The address which called {requestDetachContext} function.
  /// @param data     Additional data with no specified format.
  function onDetachRequested(bytes32 ctxHash, uint256 tokenId, address operator, bytes calldata data) external;

  /// @dev This method is called once a token context is detached by any mechanism.
  /// @param ctxHash  The hash of context invoked this call.
  /// @param tokenId  NFT identifier which is being detached.
  /// @param user     The address of the context user which is being detached.
  /// @param operator The address which called {execDetachContext} function.
  /// @param data     Additional data with no specified format.
  function onExecDetachContext(bytes32 ctxHash, uint256 tokenId, address user, address operator, bytes calldata data) external;
}
```

### Ownership Delegation Rules

**startDelegateOwnership rules**

- MUST revert unless there is no delegation.
- MUST revert unless the method caller is the owner, an authorized operator of owner, or the approved address for this NFT.
- MUST revert unless the expiry time is in the future.
- MUST revert if the delegatee address is the owner or zero address.
- MUST revert if the token is not existent.
- MUST emit the event `OwnershipDelegationStarted` on success.
- After the above conditions are met, this function MUST replace the pending delegation if any.

**acceptOwnershipDelegation rules**

- MUST revert if there is no delegation.
- MUST revert unless the method caller is the delegatee, or an authorized operator of delegatee.
- MUST revert unless the expiry time is in the future.
- MUST emit the event `OwnershipDelegationAccepted` on success.
- After the above conditions are met, the delegatee MUST be recorded as the ownership manager until the delegation expires.

**stopDelegateOwnership rules**

- MUST revert unless the delegation is already accepted.
- MUST revert unless the expiry time is in the future.
- MUST revert unless the method caller is the delegatee, or an authorized operator of delegatee.
- MUST emit the event `OwnershipDelegationStopped` on success.
- After the above conditions are met, the owner MUST be recorded as the ownership manager.

### **Token (Un)lock Rules**

To be more explicit about how token (un)locked, these functions:

- A token can be attached to a context using the `attachContext` method
- The `setContextLock` function MUST be called by the controller to (un)lock
- The `requestDetachContext` and `execDetachContext` functions MUST be called by the ownership manager and MUST operate with respect to the `IERC7695ContextCallback` hook functions

A list of scenarios and rules follows.

**Scenarios**

**_Scenario#1:_** Context controller wants to (un)lock a token that is not requested for detachment.

- `setContextLock` MUST be called successfully

**_Scenario#2:_** Context controller wants to (un)lock a token that is requested for detachment.

- `setContextLock` MUST be reverted

**_Scenario#3:_** Ownership manager wants to (unlock and) detach a locked token and the callback controller implements `IERC7695ContextCallback`.

- Caller MUST:
  - Call `requestDetachContext` function successfully
  - Wait at least context detaching duration (see variable `detachingDuration` in the `getContext` function)
  - Call `execDetachContext` function successfully
- `requestDetachContext` MUST call the `onDetachRequested` function despite the call result
- `execDetachContext` MUST call the `onExecDetachContext` function despite the call result

**_Scenario#4:_** Ownership manager wants to (unlock and) detach a locked token and the callback controller does not implement `IERC7695ContextCallback`.

- Caller MUST:
  - Call `requestDetachContext` function successfully
  - Wait at least context detaching duration (see variable `detachingDuration` in the `getContext` function)
  - Call `execDetachContext` function successfully

**_Scenario#5:_** Ownership manager wants to detach an unlocked token and the callback controller implements `IERC7695ContextCallback`.

- Caller MUST call `requestDetachContext` function successfully
- `requestDetachContext` MUST call the `onExecDetachContext` function despite the result
- `execDetachContext` MUST NOT be called

**_Scenario#6:_** Ownership manager wants to detach an unlocked token and the callback controller does not implement `IERC7695ContextCallback`.

- Caller MUST call `requestDetachContext` function successfully
- `execDetachContext` MUST NOT be called

**Rules**

**attachContext rules**

- MUST revert unless the method caller is the ownership manager, an authorized operator of ownership manager, or the approved address for this NFT (if the token is not being delegated).
- MUST revert if the context is non-existent.
- MUST revert if the token is already attached to the context.
- MUST emit the event `ContextAttached`.
- After the above conditions are met, this function MUST check if the controller address is a smart contract (e.g. code size &gt; 0). If so, it MUST call `onAttached` and MUST revert if the call is failed.
  - The `data` argument provided by the caller MUST be passed with its contents unaltered to the `onAttached` hook function via its `data` argument.

**setContextLock rules**

- MUST revert if the context is non-existent.
- MUST revert if the token is not attached to the context.
- MUST revert if a detachment request has previously been made.
- MUST revert if the method caller is not context controller.
- MUST emit the event `ContextLockUpdated` on success.

**requestDetachContext rules**

- MUST revert if a detachment request has previously been made.
- MUST revert unless the method caller is the context controller, the ownership manager, an authorized operator of the ownership manager, or the approved address for this NFT (if the token is not being delegated).
- If the caller is context controller or the token context is not locked, MUST emit the `ContextDetached` event. After the above conditions are met, this function MUST check if the controller address is a smart contract (e.g. code size &gt; 0). If so, it MUST call `onExecDetachContext` and the call result MUST be skipped.
  - The `data` argument provided by the caller MUST be passed with its contents unaltered to the `onExecDetachContext` hook function via its `data` argument.
- If the token context is locked, MUST emit the `ContextDetachRequested` event. After the above conditions are met, this function MUST check if the controller address is a smart contract (e.g. code size &gt; 0). If so, it MUST call `onDetachRequested` and the call result MUST be skipped.
  - The `data` argument provided by the caller MUST be passed with its contents unaltered to the `onDetachRequested` hook function via its `data` argument.

**execDetachContext rules**

- MUST revert unless the method caller is the ownership manager, an authorized operator of ownership manager, or the approved address for this NFT (if the token is not being delegated).
- MUST revert unless a detachment request has previously been made and the specified detaching duration has passed (use variable `detachingDuration` in the `getContext` function when requesting detachment).
- MUST emit the `ContextDetached` event.
- After the above conditions are met, this function MUST check if the controller address is a smart contract (e.g. code size &gt; 0). If so, it MUST call `onExecDetachContext` and the call result MUST be skipped.
  - The `data` argument provided by the caller MUST be passed with its contents unaltered to the `onExecDetachContext` hook function via its `data` argument.

### Additional Transfer Rules

In addition to extending from [ERC-721](/EIPs/EIPS/eip-721) for the transfer mechanism when transferring an NFT, the implementation:

- MUST revert unless the method caller is the ownership manager, an authorized operator of ownership manager, or the approved address for this NFT (if the token is not being delegated).
- MUST revoke ownership delegation if any.
- MUST detach every attached context:
  - MUST revert unless a detachment request has previously been made and the specified detaching duration has passed (use variable `detachingDuration` in the `getContext` function when requesting detachment) if the token is locked.
  - MUST check if the controller address is a smart contract (e.g. code size &gt; 0). If so, it MUST call the `onExecDetachContext` function (with an empty `data` argument `&quot;&quot;`) and the call result MUST be skipped.

## Rationale

When designing the proposal, we considered the following concerns.

### Multiple contexts for multiple use cases

This proposal is centered around Token Context to allow for the creation of distinct contexts tailored to various decentralized applications (dApps). The context controller assumes the role of facilitating (rental or delegation) dApps, by enabling the granting of usage rights to another user without modifying the NFT&apos;s owner record. Besides, this proposal provides the lock feature for contexts to ensure trustlessness in performing these dApps, especially staking cases.

### Providing an unlock mechanism for owners

By providing an unlock mechanism for owners, this approach allows owners to unlock their tokens independently, without relying on the context controller to initiate the process. This prevents scenarios where, should the controller lose control, owners would be unable to unlock their tokens.

### Attachment and detachment callbacks

The callback results of the `onDetachRequested` and `onExecDetachContext` functions in the **Token (Un)lock Rules** are skipped because we are intentionally removing the controller&apos;s ability to stop detachment, ensuring token detachment is independent of the controller&apos;s actions.

Additionally, to retain the permission to reject incoming attachments, the operation reverts if the call to the `onAttach` function fails.

### Ownership delegation

This feature provides a new approach by separating the owner and ownership. Primarily designed to facilitate delegating for third parties, it enables delegating another account as the manager of ownership, distinct from the owner.

Unlike `approve` or `setApprovalForAll` methods, which grant permission to other accounts while maintaining ownership status. Ownership delegation goes beyond simply granting permissions; it involves transferring the owner&apos;s rights to the delegatee, with provisions for automatic reversion upon expiration. This mechanism prevents potential abuses, such as requesting mortgages and transfers to alternative accounts if the owner retains ownership rights.

The **2-step delegation** process is provided to prevent mistakes in assigning delegatees, it must be done through two steps: offer and confirm. In cases the delegation needs to be canceled before its scheduled expiry, the delegatees can invoke `stopOwnershipDelegation` method.

### Transfer method mechanism

As part of the integration with the transfer method, we extended its implicit behavior to include token approval:

- **Reset Ownership Delegation:** Automatically resets ownership delegations. The `OwnershipDelegationStopped` event is intentionally not emitted.
- **Detach All Contexts:** Similarly, all contexts associated with the token are detached if none of them is locked. The `ContextDetached` event is intentionally not emitted.

These modifications are to ensure trustlessness and gas efficiency during token transfers, providing a seamless experience for users.

## Backwards Compatibility

This proposal is backward compatible with [ERC-721](/EIPs/EIPS/eip-721).

## Security Considerations

### Detaching duration

When developing this token standard to serve multiple contexts:

- The contract deployer should establish an appropriate upper threshold for detachment delay (by `maxDetachingDuration` method).
- The context owner should anticipate potential use cases and establish an appropriate period not larger than the upper threshold.

This precaution is essential to mitigate the risk of the owner abusing systems by spamming listings and transferring tokens to another owner in a short time.

### Duplicated token usage

When initiating a new context, the context controllers should track all other contexts within the NFT contract to prevent duplicated usage.

For example, suppose a scenario where a token is locked for rental purposes within a particular game. If that game introduces another context (e.g. supporting delegation in that game), it could lead to duplicated token usage within the game, despite being intended for different contexts.

In such cases, a shared context for rental and delegation purposes can be considered. Or there must be some restrictions on the new delegation context to prevent reusing that token in the game.

### Ownership Delegation Buffer Time

When constructing systems that rely on ownership delegation for product development, it is imperative to incorporate a buffer time (of at least `maxDetachingDuration` seconds) when requesting ownership delegation. This precaution is essential to mitigate the risk of potential abuse, particularly if one of the associated contexts locks the token until the delegation time expires.
For example, consider a scenario where a mortgage contract is built atop this standard, which has a maximum detaching duration of 7 days, while the required delegation period is only 3 days. In such cases, without an adequate buffer time, the owner could exploit the system by withdrawing funds and invoking the relevant context to lock the token, thus preventing its unlock and transfer.

### Validating Callback Callers

To enhance security and integrity in interactions between contracts, it is essential to validate the caller of any callback function while implementing the `IERC7695ContextCallback`. This validation ensures that the `msg.sender` of the callback is indeed the expected contract address, typically the token contract or a designated controller contract. Such checks are crucial for preventing unauthorized actions that could be executed by malicious entities pretending to be a legitimate contract.

### Recommended practices

**Rental**

This is a typical use case for rentals, supposing A(owner) owns a token and wants to list his/her token for rent, and B(user) wants to rent the token to play in a certain game.

![Rental Flow](/EIPs/assets/eip-7695/rental.svg)

**Mortgage**

When constructing collateral systems, it is recommended to support token owners who wish to rent out their tokens while using them for collateral lending. This approach enhances the appeal of mortgage systems, creating a more attractive and versatile financial ecosystem that meets many different needs.

This is a typical use case for mortgages, supposing A(owner) owns a token and wants to mortgage, and B(lender) wants to earn interest by lending their funds to A.

![Mortgage Flow](/EIPs/assets/eip-7695/mortgage.svg)

### Risk of Token Owner

**Phishing attacks**

It is crucial to note that the owner role has the ability to delegate ownership to another account, allowing it to authorize transfers out of the respective wallet. Consequently, some malicious actors could deceive the token owner into delegating them as a delegatee by invoking the `startDelegateOwnership` method. This risk can be considered the same as the `approve` or `setApprovalForAll` methods.

**Ownership rights loss**

When interacting with a contract system (e.g. mortgage), where owners have to delegate their ownership rights to the smart contract, it&apos;s imperative to:

- Ensure the timeframe for delegation is reasonable and not excessively distant. If the contract mandates a delegation period that extends too far into the future, make sure it includes a provision to revoke ownership delegation when specific conditions are met. Failing to include such a provision could lead to the loss of ownership rights until the delegation expires.
- Be aware that if the contract owner or their operator is compromised, the token ownership can be altered.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 02 Apr 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7695</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7695</guid>
      </item>
    
      <item>
        <title>EOF - Creation transaction</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7698-eof-creation-transaction/19784</comments>
        
        <description>## Abstract

Creation transactions (i.e. the ones with empty `to`) can be used to deploy EOF contracts by providing EOF initcontainer concatenated with `calldata` for initcontainer execution in transaction&apos;s `data`. Initcontainer execution is similar to its execution during `EOFCREATE` instruction, ending with `RETURNCODE` instruction. New account address calculation is based on sender&apos;s address and nonce.

## Motivation

Creation transaction is one of the three ways alongside creation instructions provided by legacy EVM to deploy new code. Given that legacy creation instructions (`CREATE` and `CREATE2`) are not allowed to deploy EOF code, supporting EOF in creation transactions is the only way to get the first EOF on-chain.

The mechanism for providing constructor arguments to initcontainer is exactly the same as for deploying legacy code (just concatenating them with initcontainer), therefore existing deployment tooling can be used as is to deploy EOF.

## Specification

Wherever not explicitly listed, the rules of EOF contract creation should be identical or analogous to those of legacy creation transaction. This includes but is not limited to:

- behavior on `accessed_addresses` and address collision ([EIP-684](/EIPs/EIPS/eip-684) and [EIP-2929](/EIPs/EIPS/eip-2929))
- EVM execution frame created for the initcode - memory, account context etc.
- nonce bumping of the account of newly created contract [EIP-161](/EIPs/EIPS/eip-161)
- balance checking and transfer for the creation endowment

### Parameters

| Constant | Value |
| - | - |
| `EOF_MAGIC` | Defined as `0xEF00` in [EIP-3540](/EIPs/EIPS/eip-3540) |
| `MAX_CODE_SIZE` | Defined as `24576` in [EIP-170](/EIPs/EIPS/eip-170) |


In case a creation transaction (transaction with empty `to`) has `data` starting with `EOF_MAGIC`, `data` is interpreted as a concatenation of EOF `initcontainer` and `calldata`. More specifically:

1. Intrinsic gas cost rules and limits defined in [EIP-3860](/EIPs/EIPS/eip-3860) for creation transactions apply. The entire `data` of the transaction is used for these calculations.
2. Find the split of `data` into `initcontainer` and `calldata`:
    - Parse EOF header
    - Find `intcontainer` size by reading all section sizes from the header and adding them up with the header size to get the full container size.
3. Validate the `initcontainer` and all its subcontainers recursively.
    - Unlike in general validation, `initcontainer` is additionally required to have `data_size` declared in the header equal to actual `data_section` size.
    - Validation includes checking that the `initcontainer` does not contain `RETURN` or `STOP`
4. If EOF header parsing or full container validation fails, transaction is considered valid and failing. Gas for initcode execution is not consumed, only intrinsic creation transaction costs are charged.
5. `calldata` part of transaction `data` that follows `initcontainer` is treated as calldata to pass into the execution frame.
6. Execute the container and deduct gas for execution.
    1. Calculate `new_address` as `keccak256(sender || sender_nonce)[12:]`
    2. A successful execution ends with initcode executing `RETURNCODE{deploy_container_index}(aux_data_offset, aux_data_size)` instruction. After that:
        - load deploy-contract from EOF subcontainer at `deploy_container_index` in the container from which `RETURNCODE` is executed,
        - concatenate data section with `(aux_data_offset, aux_data_offset + aux_data_size)` memory segment and update data size in the header,
        - let `deployed_code_size` be updated deploy container size,
        - if `deployed_code_size &gt; MAX_CODE_SIZE` instruction exceptionally aborts,
        - set `state[new_address].code` to the updated deploy container (rules of [EIP-3541](/EIPs/EIPS/eip-3541), prohibiting deployment of `code` starting with `EF` from creation transactions, do not apply in this case).
7. Deduct `200 * deployed_code_size` gas.

## Rationale

### Irregular state change to deploy Creator Contract

Originally it was proposed to deploy the first EOF contract via irregular state change. This contract would execute `TXCREATE` instruction and could be used then as an entry point to deploy any other EOF code. This would also require an introduction of `InitcodeTransaction`, required by `TXCREATE`. It was decided against this variant for the benefit of reduced scope of changes.

### Constructor arguments outside of initcontainer vs in data section

Alternative mechanism for providing constructor arguments to initcontainer execution was considered, where they are concatenated with data section of the initcontainer and are accessed via `DATA*` instructions instead of `CALLDATA*`. This has a benefit of not requiring the step finding the split of `transaction.data` into `initcontainer` and `calldata`, as entire `transaction.data` is an EOF container. However it was rejected for the following reasons:

- Existing tooling could not be used for deploying EOF without modification. To construct EOF creation transaction, the tooling would need to append constructor arguments to the container, as well as update data section size in the EOF header. Compiler could predict the size of constructor arguments to put the anticipated data size in the header, but it would not be possible for variadic length constructor arguments.
- In case a specialized EOF creation transaction is introduced in a later upgrade (such as the `InitcodeTransaction`), it would have a dedicated field for initcontainer execution input (`calldata`), and it will be accessed with `CALLDATA*` instructions in initcode. It is better to avoid the situation where compilers would need to generate initcontainer code differently depending on which context it will be used in.
- As a general argument, data section can be seen to contain the data that execution considers validated and being closely coupled with the code definition, whereas calldata is an input from the outside that may be arbitrary and not validated.

## Backwards Compatibility

Creation transactions deploying legacy code are not affected, because any such transaction starting with `EF` byte previously would fail on executing invalid instruction.

## Security Considerations

TBA

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 24 Apr 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7698</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7698</guid>
      </item>
    
      <item>
        <title>ERC-20 Transfer Reference Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7699-erc20-payment-reference-extension/19826</comments>
        
        <description>## Abstract

The [ERC-20](/EIPs/EIPS/eip-20) token standard does not provide a built-in mechanism for including a payment transfer reference (message for recipient) in token transfers. This proposal extends the existing ERC-20 token standard by adding minimal methods to include a transfer reference in token transfers and transferFrom operations. The addition of a reference can help users, merchants, and service providers to associate and reconcile individual transactions with specific orders or invoices.

## Motivation

The primary motivation for this proposal is to improve the functionality of the ERC-20 token standard by providing a mechanism for including a payment reference in token transfers, similar to the traditional finance systems where payment references are commonly used to associate and reconcile transactions with specific orders, invoices or other financial records.

Currently, users and merchants who want to include a payment reference in their transactions must rely on off chain external systems or custom payment proxy implementations. In traditional finance systems, payment references are often included in wire transfers and other types of electronic payments, making it easy for users and merchants to manage and reconcile their transactions. Such as:

 - SWIFT MT103: field 70 “Remittance Information” is commonly used for such content (e.g &quot; PAYMENT FOR INVOICE 998877&quot;). There is also field 72 “Sender to receiver information”.
 - ISO 20022 (for SEPA): PAIN.001 has field called RmtInf (Remittance Information)

By extending the existing ERC-20 token standard with payment transfer reference capabilities, this proposal will help bridge the gap between traditional finance systems and the world of decentralized finance, providing a more seamless experience for users, merchants, and service providers alike.

## Specification

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.

Any contract complying with ERC-20 when extended with this ERC, MUST implement the following interface:
```
// The EIP-165 identifier of this interface is 0x1522573a

interface IERC7699 {

function transfer(address to, uint256 amount, bytes calldata transferReference) external returns (bool);

function transferFrom(address from, address to, uint256 amount, bytes calldata transferReference) external returns (bool);

event TransferReference(bytes32 indexed loggedReference);

}
```

These `transfer` and `transferFrom` functions, in addition to the standard transfer behaviour, MUST emit a `transferReference` event with a `loggedReference` parameter (with only exception defined below).

The corresponding ERC-20 `Transfer` event MUST be emitted following the `TransferReference` event, ideally immediately afterwards for the client to be able to seek the associated `Transfer` event log record. 

Emitted `loggedReference` MAY be the exact copy of the `transferReference` (when less then 33 bytes) or the derived data from the rich `transferReference` structure and other processing. This is up to the implementer. One MUST NOT expect the `transferReference` and `loggedReference` data to be equal.

The `loggedReference` parameter MAY contain any data of bytes32 type.

The `transferReference` parameter MAY be empty. In this case and only in this case the `TransferReference` event MUST NOT be emitted, effectively mimicking the regular ERC-20 transfer without any transfer reference. 

The `transferReference` parameter is not limited in length by design, users are motivated to keep it short due to calldata and execution gas costs.

The `TransferReference` event MUST NOT be declared with the `anonymous` specifier. This is to ensure that the event signature is logged and can be used as a filter.

Transfers of 0 amount MUST be treated as normal transfers and fire the `TransferReference` event alike.

## Rationale

### Parameter name

The choice to name the added parameter `transferReference` was made to align with traditional banking terminology, where payment references are widely used to associate and reconcile transactions with specific orders, invoices or other financial records.

The `transferReference` parameter name also helps to clearly communicate the purpose of the parameter and its role in facilitating the association and reconciliation of transactions. By adopting terminology that is well-established in the financial industry, the proposal aims to foster a greater understanding and adoption of the extended ERC-20 token standard.

### Parameter type

The `transferReference` type is bytes.

The `transferReference` type was initially considered to be bytes32 in order to motivate users to either use short references (as is common in TradFi) or rather use Keccak 256 hash of the reference content. Conclusion was that the options should rather be kept open to be able to call with structured data; such as passing reference data including a signature enabling extra processing checks. 

### Emitted data

The `loggedReference` type is bytes32.

It was considered to log a reference in the form of `bytes calldata`.  However, the reference content would be hashed in the event log due to the log topic indexing required for the even subscription filters. The resulting logged topic is always in the form of bytes32. Bytes32 type enables to log publicly readable (non hashed) reference content up to 32 bytes long. 

## Backwards Compatibility

This extension is fully backwards compatible with the existing ERC-20 token standard. The new functions can be used alongside the existing transfer and transferFrom functions. Existing upgradable ERC-20 tokens can be upgraded to include the new functionality without impact on the storage layout; new ERC-20 tokens can choose to implement the payment reference features based on their specific needs.

## Reference Implementation

```
// SPDX-License-Identifier: CC0-1.0
pragma solidity &gt;=0.8.4 &lt;0.9.0;

import {ERC20} from &quot;@openzeppelin/token/ERC20/ERC20.sol&quot;;

interface IERC7699 {
    /**
     * @notice Emitted when a non-empty `transferReference` is added to the `transfer` call.
     */
    event TransferReference(bytes32 indexed loggedReference);

    /**
     * @notice Moves `amount` tokens from the caller&apos;s account to `to` with `transferReference`.
     *
     * @dev Returns a boolean value indicating whether the operation succeeded.
     *
     * MUST emit this ERCS&apos;s {TransferReference} event followed by a corresponding {ERC20.Transfer} event
     * (to comply with ERC-20).
     */
    function transfer(address to, uint256 amount, bytes calldata transferReference) external returns (bool);

    /**
     * @notice Moves `amount` tokens from `from` to `to` with `transferReference` using the
     * allowance mechanism. `amount` is then deducted from the caller&apos;s allowance.
     *
     * @dev Returns a boolean value indicating whether the operation succeeded.
     *
     * MUST emit this ERCS&apos;s {TransferReference} event followed by a corresponding {ERC20.Transfer} event
     * (to comply with ERC-20).
     */
    function transferFrom(address from, address to, uint256 amount, bytes calldata transferReference)
        external
        returns (bool);
}

/**
 * @dev Implementation of the ERC20 transfer reference extension.
 */
contract ERC20TransferReference is ERC20, IERC7699 {
    constructor() ERC20(&quot;ERC20 Transfer Reference Example&quot;, &quot;TXRE&quot;) {
        _mint(msg.sender, 987654321 * 1e18);
    }

    /**
     * @dev Emits `TransferReference` event with derived `loggedReference` data
     */
    function _logReference(bytes calldata transferReference) internal virtual {
        // MUST NOT emit when transferReference is empty
        if (transferReference.length &gt; 0) {
            // Effectively extract first 32 bytes from transferReference calldata bytes
            // Note: This is the example. Derivation of the loggedReference is fully up to the implementation.
            // E.g. keccak hash of the whole transferReference, etc.
            bytes32 loggedReference;
            // solhint-disable-next-line no-inline-assembly
            assembly {
                loggedReference := calldataload(transferReference.offset)
            }

            emit TransferReference(loggedReference);
        }
    }

    /**
     * @notice A standard ERC20 token transfer with an optional transfer reference
     * @dev The underlying `transfer` function is assumed to handle the actual token transfer logic.
     * @param to The address of the recipient where the tokens will be sent.
     * @param amount The number of tokens to be transferred.
     * @param transferReference A bytes field to include a transfer reference, reference signature or other relevant
     * reference data.
     * @return A boolean indicating whether the transfer was successful.
     */
    function transfer(address to, uint256 amount, bytes calldata transferReference) public virtual returns (bool) {
        _logReference(transferReference);

        // ERC20.Transfer event is emitted immediately after TransferReference event
        return transfer(to, amount);
    }

    /**
     * @notice A delegated token transfer with an optional transfer reference
     * @dev Requires prior approval from the token owner. The underlying `transferFrom` function is assumed to handle
     * allowance and transfer logic.
     * @param from The address of the token owner who has authorized the transfer.
     * @param to The address of the recipient where the tokens will be sent.
     * @param amount The number of tokens to be transferred.
     * @param transferReference A bytes field to include a transfer reference, reference signature or other relevant
     * reference data.
     * @return A boolean indicating whether the transfer was successful.
     */
    function transferFrom(address from, address to, uint256 amount, bytes calldata transferReference)
        public
        virtual
        returns (bool)
    {
        _logReference(transferReference);

        // ERC20.Transfer event is emitted immediately after TransferReference event
        return transferFrom(from, to, amount);
    }
}

```

## Security Considerations

### Privacy Considerations

Reference data privacy: Including payment references in token transfers may expose sensitive information about the transaction or the parties involved. Implementers and users should carefully consider the privacy implications and ensure that payment references do not reveal sensitive information. To mitigate this risk, implementers can consider using encryption or other privacy-enhancing techniques to protect payment reference data.

Example: With reference 0x20240002 logged, transaction is publicly exposing that this is related to the second invoice of the recipient in 2024.

### Manipulation of payment references
There is no validation of the reference data dictated by this ERC. Malicious actors might attempt to manipulate payment references to mislead users, merchants, or service providers. This can lead to:

1. **Legal risks**: The beneficiary may face legal and compliance risks if the attacker uses illicit funds, potentially impersonating or flagging the beneficiary of involvement in money laundering or other illicit activities.
  
2. **Disputes and refunds**: The user might discover they didn&apos;t make the payment, request a refund or raise a dispute, causing additional administrative work for the beneficiary.

To mitigate this risk, implementers can consider using methods to identify proper sender and to generate unique and verifiable related payment references. However such implementations are not in the scope of this standard and rather extend it.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 26 Apr 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7699</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7699</guid>
      </item>
    
      <item>
        <title>Cross-chain Storage Router Protocol</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7700-cross-chain-storage-router-protocol/19853</comments>
        
        <description>## Abstract
The following standard provides a mechanism by which smart contracts can route storage to external providers. In particular, protocols can reduce the gas fees associated with storing data on mainnet by routing the handling of storage operations to another system or network. These storage routers act as an extension to the core L1 contract. Methods in this document specifically target security and cost-effectiveness of storage routing to three router types: L1, L2 and databases. The cross-chain data written with these methods can be retrieved by generic [EIP-3668](./eip-3668)-compliant contracts, thus completing the cross-chain data life cycle. This document, nicknamed CCIP-Store, alongside [EIP-3668](./eip-3668), is a meaningful step toward a secure infrastructure for cross-chain storage routers and data retrievals.

## Motivation
[EIP-3668](./eip-3668), aka &apos;CCIP-Read&apos;, has been key to retrieving cross-chain data for a variety of contracts on Ethereum blockchain, ranging from price feeds for DeFi contracts, to more recently records for ENS users. The latter case dedicatedly uses cross-chain storage to bypass the usually high gas fees associated with on-chain storage; this aspect has a plethora of use cases well beyond ENS records and a potential for significant impact on universal affordability and accessibility of Ethereum.

Cross-chain data retrieval through [EIP-3668](./eip-3668) is a relatively simpler task since it assumes that all relevant data originating from cross-chain storages is translated by CCIP-Read-compliant HTTP gateways; this includes L2 chains and databases. On the flip side however, so far each service leveraging CCIP-Read must handle writing this data securely to these storage types on their own, while also incorporating reasonable security measures in their CCIP-Read-compatible contracts for verifying this data on L1. While these security measures are in-built into L2 architectures, database storage providers on the other hand must incorporate some form of explicit security measures during storage operations so that cross-chain data&apos;s integrity can be verified by CCIP-Read contracts during data retrieval stage. Examples of this include:

- Services that allow the management of namespaces, e.g. ENS domains, stored externally on an L2 solution or off-chain database as if they were native L1 tokens, and,
- Services that allow the management of digital identities stored on external storages as if they were stored in the native L1 smart contract.

In this context, a specification which allows storage routing to external routers will facilitate creation of services that are agnostic to the underlying storage solution. This in turn enables new applications to operate without knowledge of the underlying routers. This &apos;CCIP-Store&apos; proposal outlines precisely this part of the process, i.e. how the bespoke storage routing can be made by smart contracts to L2s and databases. 

![Fig.1 CCIP-Store and CCIP-Read Workflows](/EIPs/assets/eip-7700/images/Schema.svg)

## Specification
### Overview
The following specification revolves around the structure and description of a cross-chain storage router tasked with the responsibility of writing to an L2 or database storage. This document introduces `StorageRoutedToL2()` and `StorageRoutedToDatabase()` storage routers, along with the trivial `StorageRoutedToL1()` router, and proposes that new `StorageRoutedTo__()` reverts be allowed through new EIPs that sufficiently detail their interfaces and designs. Some foreseen examples of new storage routers include `StorageRoutedToSolana()` for Solana, `StorageRoutedToFilecoin()` for Filecoin, `StorageRoutedToIPFS()` for IPFS, `StorageRoutedToIPNS()` for IPNS, `StorageRoutedToArweave()` for Arweave, `StorageRoutedToArNS()` for ArNS, `StorageRoutedToSwarm()` for Swarm etc.

### L1 Router: `StorageRoutedToL1()`
A minimal L1 router is trivial and only requires the L1 `contract` address to which routing must be made, while the clients must ensure that the calldata is invariant under routing to another contract. One example implementation of an L1 router is given below.

```solidity
// Define revert event
error StorageRoutedToL1(
    address contractL1
);

// Generic function in a contract
function setValue(
    bytes32 node,
    bytes32 key,
    bytes32 value
) external {
    // Get metadata from on-chain sources
    (
        address contractL1, // Routed contract address on L1; may be globally constant
    ) = getMetadata(node); // Arbitrary code
    // contractL1 = 0x32f94e75cde5fa48b6469323742e6004d701409b
    // Route storage call to L1 router
    revert StorageRoutedToL1( 
        contractL1
    );
};
```

In this example, the routing must prompt the client to build the transaction with the exact same original calldata, and submit it to the L1 `contract` by calling the exact same function.

```solidity
// Function in routed L1 contract
function setValue(
    bytes32 node,
    bytes32 key,
    bytes32 value
) external {
    // Some code storing data mapped by node &amp; msg.sender
    ...
}
```

![Fig.2 L1 Call Lifecycle](/EIPs/assets/eip-7700/images/L1.svg)

### L2 Router: `StorageRoutedToL2()`
A minimal L2 router only requires the list of `chainId` values and the corresponding L2 `contract` addresses, while the clients must ensure that the calldata is invariant under routing to L2. One example implementation of an L2 router in an L1 contract is shown below.

```solidity
// Define revert event
error StorageRoutedToL2(
    address contractL2, 
    uint256 chainId
);

// Generic function in a contract
function setValue(
    bytes32 node,
    bytes32 key,
    bytes32 value
) external {
    // Get metadata from on-chain sources
    (
        address contractL2, // Contract address on L2; may be globally constant
        uint256 chainId // L2 ChainID; may be globally constant
    ) = getMetadata(node); // Arbitrary code
    // contractL2 = 0x32f94e75cde5fa48b6469323742e6004d701409b
    // chainId = 21
    // Route storage call to L2 router
    revert StorageRoutedToL2( 
        contractL2,
        chainId
    );
};
```

In this example, the routing must prompt the client to build the transaction with the exact same original calldata, and submit it to the L2 by calling the exact same function on L2 as L1.

```solidity
// Function in L2 contract
function setValue(
    bytes32 node,
    bytes32 key,
    bytes32 value
) external {
    // Some code storing data mapped by node &amp; msg.sender
    ...
}
```

![Fig.3 L2 Call Lifecycle](/EIPs/assets/eip-7700/images/L2.svg)

### Database Router: `StorageRoutedToDatabase()`
A minimal database router is similar to an L2 in the sense that:

  a) Similar to `chainId`, it requires the `gatewayUrl` that is tasked with handling off-chain storage operations, and

  b) Similar to `eth_call`, it requires `eth_sign` output to secure the data, and the client must prompt the users for these signatures.

This specification does not require any other data to be stored on L1 other than the bespoke `gatewayUrl`; the storage router therefore should only return the `gatewayUrl` in revert.

```solidity
error StorageRoutedToDatabase(
    string gatewayUrl
);

// Generic function in a contract
function setValue(
    bytes32 node,
    bytes32 key,
    bytes32 value
) external {
    (
        string gatewayUrl // Gateway URL; may be globally constant
    ) = getMetadata(node);
    // gatewayUrl = &quot;https://api.namesys.xyz&quot;
    // Route storage call to database router
    revert StorageRoutedToDatabase( 
        gatewayUrl
    );
};
```

![Fig.4 Database Call Lifecycle](/EIPs/assets/eip-7700/images/Database.svg)

Following the revert, the client must take these steps:

1. Request the user for a secret signature `sigKeygen` to generate a deterministic `dataSigner` keypair,

2. Sign the calldata with generated data signer&apos;s private key and produce verifiable data signature `dataSig`,

3. Request the user for an `approval` approving the generated data signer, and finally,

4. Post the calldata to gateway along with signatures `dataSig` and `approval`, and the `dataSigner`.

These steps are described in detail below.

#### 1. Generate Data Signer
The data signer must be generated deterministically from ethereum wallet signatures; see figure below.

![Fig.5 Data Signer Keygen Workflow](/EIPs/assets/eip-7700/images/Keygen.svg)

The deterministic key generation can be implemented concisely in a single unified `keygen()` function as follows.

```js
/* Pseudo-code for key generation */
function keygen(
  username, // CAIP identifier for the blockchain account
  sigKeygen, // Deterministic signature from wallet
  spice // Stretched password
) {
  // Calculate input key by hashing signature bytes using SHA256 algorithm
  let inputKey = sha256(sigKeygen);
  // Calculate salt for keygen by hashing concatenated username, stretched password (aka spice) and hex-encoded signature using SHA256 algorithm
  let salt = sha256(`${username}:${spice}:${sigKeygen}`);
  // Calculate hash key output by feeding input key, salt &amp; username to the HMAC-based key derivation function (HKDF) with dLen = 42
  let hashKey = hkdf(sha256, inputKey, salt, username, 42);
  // Calculate and return secp256k1 keypair
  return secp256k1(hashKey); // Calculate secp256k1 keypair from hash key
}
```

This `keygen()` function requires three variables: `username`, `spice` and `sigKeygen`. Their definitions are given below.

##### 1. `username`
[CAIP-10](https://github.com/ChainAgnostic/CAIPs/blob/ad0cfebc45a4b8368628340bf22aefb2a5edcab7/CAIPs/caip-10.md) identifier `username` is auto-derived from the connected wallet&apos;s checksummed address `wallet` and `chainId` using [EIP-155](./eip-155).

```js
/* CAIP-10 identifier */
const caip10 = `eip155:${chainId}:${wallet}`;
```

##### 2. `spice`
`spice` is calculated from the optional private field `password`, which must be prompted from the user by the client; this field allows users to change data signers for a given `username`.
```js
/* Secret derived key identifier */ 
// Clients must prompt the user for this
const password = &apos;key1&apos;;
```

Password must then be stretched before use with `PBKDF2` algorithm such that:

```js
/* Calculate spice by stretching password */
let spice = pbkdf2(
            password, 
            pepper, 
            iterations
        ); // Stretch password with PBKDF2
```

where `pepper = keccak256(abi.encodePacked(username))` and the `iterations` count is fixed to `500,000` for brute-force vulnerability protection.

```js
/* Definitions of pepper and iterations in PBKDF2 */
let pepper = keccak256(abi.encodePacked(username));
let iterations = 500000; // 500,000 iterations
```

##### 3. `sigKeygen`
The data signer must be derived from the owner or manager keys of a node. Message payload for the required `sigKeygen` must then be formatted as:

```text
Requesting Signature To Generate Keypair(s)\n\nOrigin: ${username}\nProtocol: ${protocol}\nExtradata: ${extradata}
```

where the `extradata` is calculated as follows,

```solidity
// Calculating extradata in keygen signatures
bytes32 extradata = keccak256(
    abi.encodePacked(
        spice
        wallet
    )
)
```

The remaining `protocol` field is a protocol-specific identifier limiting the scope to a specific protocol represented by a unique contract address. This identifier cannot be global and must be uniquely defined for each implementating L1 `contract` such that:

```js
/* Protocol identifier in CAIP-10 format */
const protocol = `eth:${chainId}:${contract}`;
```

With this deterministic format for signature message payload, the client must prompt the user for the ethereum signature. Once the user signs the messages, the `keygen()` function can derive the data signer keypair. 

#### 2. Sign Data
Since the derived signer is wallet-specific, it can 

- sign batch data for multiple keys for a given node, and 
- sign batches of data for multiple nodes owned by a wallet

simultaneously in the background without ever prompting the user. Signature(s) `dataSig` accompanying the off-chain calldata must implement the following format in their message payloads:  

```text
Requesting Signature To Update Off-Chain Data\n\nOrigin: ${username}\nData Type: ${dataType}\nData Value: ${dataValue}
```

where `dataType` parameters are protocol-specific and formatted as object keys delimited by `/`. For instance, if the off-chain data is nested in keys as `a &gt; b &gt; c &gt; field &gt; key`, then the equivalent `dataType` is `a/b/c/field/key`. For example, in order to update off-chain ENS record `text &gt; avatar` and `address &gt; 60`, `dataType` must be formatted as `text/avatar` and `address/60` respectively.
 
#### 3. Approve Data Signer
The `dataSigner` is not stored on L1, and the clients must instead

- request an `approval` signature for `dataSigner` signed by the owner or manager of a node, and
- post this `approval` and the `dataSigner` along with the signed calldata in encoded form.

CCIP-Read-enabled contracts can then verify during resolution time that the `approval` attached with the signed calldata comes from the node&apos;s manager or owner, and that it approves the expected `dataSigner`. The `approval` signature must have the following message payload format:

```text
Requesting Signature To Approve Data Signer\n\nOrigin: ${username}\nApproved Signer: ${dataSigner}\nApproved By: ${caip10}
```

where `dataSigner` must be checksummed.

#### 4. Post CCIP-Read Compatible Payload
The final [EIP-3668](./eip-3668)-compatible `data` payload in the off-chain data file is identified by a fixed `callback.signedData.selector` equal to `0x2b45eb2b` and must follow the format

```solidity
/* Compile CCIP-Read-compatible payload*/
bytes encodedData = abi.encode([&apos;bytes&apos;], [dataValue]); // Encode data
bytes funcSelector = callback.signedData.selector; // Identify off-chain data with a fixed &apos;signedData&apos; selector = &apos;0x2b45eb2b&apos;
bytes data = abi.encode(
    [&apos;bytes4&apos;, &apos;address&apos;, &apos;bytes32&apos;, &apos;bytes32&apos;, &apos;bytes&apos;],
    [funcSelector, dataSigner, dataSig, approval, encodedData]
); // Compile complete CCIP-Readable off-chain data
```

The client must construct this `data` and pass it to the gateway in the `POST` request along with the raw values for indexing. The CCIP-Read-enabled contracts after decoding the four parameters from this `data` must 

- verify that the `dataSigner` is approved by the owner or manager of the node through `approval`, and
- verify that the `dataSig` is produced by `dataSigner`

before resolving the `encodedData` value in decoded form.

##### `POST` Request
The `POST` request made by the client to the `gatewayUrl` must follow the format as described below.

```ts
/* POST request format*/
type Post = {
  node: string
  preimage: string
  chainId: number
  approval: string
  payload: {
    field1: {
      value: string
      signature: string
      timestamp: number
      data: string
    }
    field2: [
      {
        index: number
        value: string
        signature: string
        timestamp: number
        data: string
      }
    ]
    field3: [
      {
        key: number
        value: string
        signature: string
        timestamp: number
        data: string
      }
    ]
  }
}
```

Example of a complete `Post` typed object for updating multiple ENS records for a node is shown below.

```ts
/* Example of a POST request */
let post: Post = {
  node: &quot;0xe8e5c24bb5f0db1f3cab7d3a7af2ecc14a7a4e3658dfb61c9b65a099b5f086fb&quot;,
  preimage: &quot;dev.namesys.eth&quot;,
  chainId: 1,
  approval: &quot;0xa94da8233afb27d087f6fbc667cc247ef2ed31b5a1ff877ac823b5a2e69caa49069f0daa45a464d8db2f8e4e435250cb446d8f279d45a2b865ebf2fff291f69f1c&quot;,
  payload: {
    contenthash: {
      value: &quot;ipfs://QmYSFDzEcmk25JPFrHBHSMMLcTKLm6SvuZvKpijTHBnAYX&quot;,
      signature: &quot;0x24730d1d85d556245b7766aef413188e22f219c8de263ccbfafee4413f0937c32e4f44068d84c7424f923b878dcf22184f8df86506de1cea3dad932c5bd5e9de1c&quot;,
      timestamp: 1708322868,
      data: &quot;0x2b45eb2b000000000000000000000000fe889053f7a0d2571f1898d2835c3cbdf50d766b000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000004124730d1d85d556245b7766aef413188e22f219c8de263ccbfafee4413f0937c32e4f44068d84c7424f923b878dcf22184f8df86506de1cea3dad932c5bd5e9de1c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041a94da8233afb27d087f6fbc667cc247ef2ed31b5a1ff877ac823b5a2e69caa49069f0daa45a464d8db2f8e4e435250cb446d8f279d45a2b865ebf2fff291f69f1c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000026e301017012209603ccbcef5c2acd57bdec6a63e8a0292f3ce6bb583b6826060bcdc3ea84ad900000000000000000000000000000000000000000000000000000&quot;
    },
    address: [
      {
        coinType: 0,
        value: &quot;1FfmbHfnpaZjKFvyi1okTjJJusN455paPH&quot;,
        signature: &quot;0x60ecd4979ae2c39399ffc7ad361066d46fc3d20f2b2902c52e01549a1f6912643c21d23d1ad817507413dc8b73b59548840cada57481eb55332c4327a5086a501b&quot;,
        timestamp: 1708322877,
        data: &quot;0x2b45eb2b000000000000000000000000fe889053f7a0d2571f1898d2835c3cbdf50d766b000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000004160ecd4979ae2c39399ffc7ad361066d46fc3d20f2b2902c52e01549a1f6912643c21d23d1ad817507413dc8b73b59548840cada57481eb55332c4327a5086a501b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041a94da8233afb27d087f6fbc667cc247ef2ed31b5a1ff877ac823b5a2e69caa49069f0daa45a464d8db2f8e4e435250cb446d8f279d45a2b865ebf2fff291f69f1c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000a0e6ca5444e4d8b7c80f70237f332320387f18c7&quot;
      },
      {
        coinType: 60,
        value: &quot;0x47C10B0491A138Ddae6cCfa26F17ADCfCA299753&quot;,
        signature: &quot;0xaad74ddef8c031131b6b83b3bf46749701ed11aeb585b63b72246c8dab4fff4f79ef23aea5f62b227092719f72f7cfe04f3c97bfad0229c19413f5cb491e966c1b&quot;,
        timestamp: 1708322917,
        data: &quot;0x2b45eb2b000000000000000000000000fe889053f7a0d2571f1898d2835c3cbdf50d766b0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000041aad74ddef8c031131b6b83b3bf46749701ed11aeb585b63b72246c8dab4fff4f79ef23aea5f62b227092719f72f7cfe04f3c97bfad0229c19413f5cb491e966c1b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041a94da8233afb27d087f6fbc667cc247ef2ed31b5a1ff877ac823b5a2e69caa49069f0daa45a464d8db2f8e4e435250cb446d8f279d45a2b865ebf2fff291f69f1c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000047c10b0491a138ddae6ccfa26f17adcfca299753&quot;
      }
    ],
    text: [
      {
        key: &quot;avatar&quot;,
        value: &quot;https://namesys.xyz/logo.png&quot;,
        signature: &quot;0xbc3c7f1b511de151bffe8df033859295d83d400413996789e706e222055a2353404ce17027760c927af99e0bf621bfb24d3bfc52abb36bcfbe6e20cf43db7c561b&quot;,
        timestamp: 1708329377,
        data: &quot;0x2b45eb2b000000000000000000000000fe889053f7a0d2571f1898d2835c3cbdf50d766b0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000041bc3c7f1b511de151bffe8df033859295d83d400413996789e706e222055a2353404ce17027760c927af99e0bf621bfb24d3bfc52abb36bcfbe6e20cf43db7c561b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041a94da8233afb27d087f6fbc667cc247ef2ed31b5a1ff877ac823b5a2e69caa49069f0daa45a464d8db2f8e4e435250cb446d8f279d45a2b865ebf2fff291f69f1c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001c68747470733a2f2f6e616d657379732e78797a2f6c6f676f2e706e6700000000&quot;
      },
      {
        key: &quot;com.github&quot;,
        value: &quot;namesys-eth&quot;,
        signature: &quot;0xc9c33ff219e90510f79b6c9bb489917ee6e00ab123c55abe1117e71ea0d171356cf316420c71cfcf4bd63a791aaf37388ef1832e582f54a8c2df173917240fff1b&quot;,
        timestamp: 1708322898,
        data: &quot;0x2b45eb2b000000000000000000000000fe889053f7a0d2571f1898d2835c3cbdf50d766b0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000041c9c33ff219e90510f79b6c9bb489917ee6e00ab123c55abe1117e71ea0d171356cf316420c71cfcf4bd63a791aaf37388ef1832e582f54a8c2df173917240fff1b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041a94da8233afb27d087f6fbc667cc247ef2ed31b5a1ff877ac823b5a2e69caa49069f0daa45a464d8db2f8e4e435250cb446d8f279d45a2b865ebf2fff291f69f1c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000b6e616d657379732d657468000000000000000000000000000000000000000000&quot;
      }
    ]
  }
}
```

### New Revert Events
1. Each new storage router must submit their `StorageRoutedTo__()` identifier through an ERC track proposal referencing the current document.

2. Each `StorageRoutedTo__()` provider must be supported with detailed documentation of its structure and the necessary metadata that its implementers must return.

3. Each `StorageRoutedTo__()` proposal must define the precise formatting of any message payloads that require signatures and complete descriptions of custom cryptographic techniques implemented for additional security, accessibility or privacy.

### Implementation featuring ENS on L2 &amp; Database
ENS off-chain resolvers capable of reading from and writing to databases are perhaps the most common use-case for CCIP-Read and CCIP-Write. One example of such a (minimal) resolver is given below along with the client-side code for handling the storage router revert.

#### L1 Contract
```solidity
/* ENS resolver implementing StorageRoutedToDatabase() */
interface iResolver {
    // Defined in EIP-7700
    error StorageRoutedToL2(
        uint chainId,
        address contractL2
    );
    error StorageRoutedToDatabase(
        string gatewayUrl
    );
    // Defined in EIP-137
    function setAddr(bytes32 node, address addr) external;
}

// Defined in EIP-7700
string public gatewayUrl = &quot;https://post.namesys.xyz&quot;; // RESTful API endpoint
uint256 public chainId = uint(21); // ChainID of L2
address public contractL2 = &quot;0x839B3B540A9572448FD1B2335e0EB09Ac1A02885&quot;; // Contract on L2

/**
* Sets the ethereum address associated with an ENS node
* [!] May only be called by the owner or manager of that node in ENS registry
* @param node Namehash of ENS domain to update
* @param addr Ethereum address to set
*/
function setAddr(
    bytes32 node,
    address addr
) authorised(node) {
    // Route to database storage
    revert StorageRoutedToDatabase(
        gatewayUrl
    );
}

/**
* Sets the avatar text record associated with an ENS node
* [!] May only be called by the owner or manager of that node in ENS registry
* @param node Namehash of ENS domain to update
* @param key Key for ENS text record
* @param value URL to avatar
*/
function setText(
    bytes32 node,
    string key,
    string value
) external {
    // Verify owner or manager permissions
    require(authorised(node), &quot;NOT_ALLOWED&quot;);
    // Route to L2 storage
    revert StorageRoutedToL2(
        chainId, 
        contractL2
    );
}
```

#### L2 Contract
```solidity
// Function in L2 contract
function setText(
    bytes32 node,
    bytes32 key,
    bytes32 value
) external {
    // Store record mapped by node &amp; sender
    records[keccak256(abi.encodePacked(node, msg.sender))][&quot;text&quot;][key] = value;
}
```

#### Client-side Code
```ts
/* Client-side pseudo-code in ENS App */
// Deterministically generate signer keypair
let signer = keygen(username, sigKeygen, spice);
// Construct POST body by signing calldata with derived private key
let post: Post = signData(node, addr, signer.priv);
// POST to gateway
await fetch(gatewayUrl, {
  method: &quot;POST&quot;,
  body: JSON.stringify(post)
});
```

## Rationale
Technically, the cases of L2s and databases are similar; routing to an L2 involves routing the `eth_call` to another EVM, while routing to a database can be made by extracting `eth_sign` from `eth_call` and posting the resulting signature explicitly along with the data for later verification. Methods in this document perform these precise tasks when routing storage operations to external routers. In addition, methods such as signing data with a derived signer (for databases) allow for significant UX improvement by fixing the number of signature prompts in wallets to 2, irrespective of the number of data instances to sign per node or the total number of nodes to update. This improvement comes at no additional cost to the user and allows services to perform batch updates.

## Backwards Compatibility
None

## Security Considerations
1. Clients must purge the derived signer private keys from local storage immediately after signing the off-chain data.

2. Signature message payload and the resulting deterministic signature `sigKeygen` must be treated as a secret by the clients and immediately purged from local storage after usage in the `keygen()` function.

3. Clients must immediately purge the `password` and `spice` from local storage after usage in the `keygen()` function.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).</description>
        <pubDate>Tue, 30 Apr 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7700</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7700</guid>
      </item>
    
      <item>
        <title>Native Account Abstraction</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7701-native-account-abstraction/19893</comments>
        
        <description>## Abstract

We propose splitting the Ethereum transaction scope into multiple steps: validations, execution, and post-operation logic. Transaction validity is determined by the result of the validation steps of a transaction.

We further separate transaction validation for the purposes of authorization and the gas fee payment, allowing one contract to pay gas for a transaction that will be executed from another contract.

## Motivation

Native Account Abstraction allows custom validation logic of a transaction and custom gas payment logic, opening new use-cases and features for wallets and dApps.

A more detailed motivation for this proposal can be found in the [README document](/EIPs/assets/eip-7701/).


## Specification

### Constants

| Name                        | Value             |
|-----------------------------|-------------------|
| `AA_TX_TYPE`                | TBD               |
| `AA_ENTRY_POINT`            | `address(0x7701)` |
| `AA_BASE_GAS_COST`          | 15000             |
| `ROLE_SENDER_DEPLOYMENT`    | `0xA0`            |
| `ROLE_SENDER_VALIDATION`    | `0xA1`            |
| `ROLE_PAYMASTER_VALIDATION` | `0xA2`            |
| `ROLE_SENDER_EXECUTION`     | `0xA3`            |
| `ROLE_PAYMASTER_POST_OP`    | `0xA4`            |

### New Transaction Type

A new [EIP-2718](./eip-2718) transaction with type `AA_TX_TYPE` is introduced.
Transactions of this type are referred to as &quot;AA transactions&quot;.

Their payload should be interpreted as:

```
AA_TX_TYPE || rlp([
  chain_id,
  nonce,
  sender, sender_validation_data,
  deployer, deployer_data,
  paymaster, paymaster_data,
  sender_execution_data,
  max_priority_fee_per_gas, max_fee_per_gas,
  sender_validation_gas, paymaster_validation_gas,
  sender_execution_gas, paymaster_post_op_gas,
  access_list,
  authorization_list
])

```

### `CURRENT_ROLE` and `ACCEPT_ROLE` opcodes

`current_context_role` is a context variable set by the AA transaction to the current role.
During AA transactions, it is set to the current role in the transaction&apos;s lifecycle for each top level call.
During non-AA transactions it is always set to `ROLE_SENDER_EXECUTION`.
It remains unchanged on `DELEGATECALL` but is reset to `ROLE_SENDER_EXECUTION` on `CALL` / `STATICCALL` / `CALLCODE`. This behavior resembles `msg.sender`.

The `CURRENT_ROLE` opcode returns the `current_context_role` value.

The `ACCEPT_ROLE` opcode is equivalent to `RETURN` in the sense that it copies a memory slice, ends execution, and pastes the memory slice onto parent returndata, with a single modification:

* It accepts the `frame_role` as the additional input parameter, and reverts if it differs from the `current_context_role`

For each `role` in the transaction&apos;s lifecycle, a successful `ACCEPT_ROLE` is expected with the `frame_role == role`.
If any validation frame failed to perform an `ACCEPT_ROLE` matching its role, the transaction fails the validity checks and cannot be included.

### `TXPARAM*` opcodes

The `TXPARAMDLOAD`, `TXPARAMSIZE`, `TXPARAMCOPY` opcodes follow the pattern of `CALLDATA*` / `RETURNDATA*` opcode families.


Each `TXPARAM*` opcode takes an extra stack input value as a first input compared to its `CALLDATA*` equivalent.
The values of this input are as follows:


| `n`  | Return value               | Data size | Default      | Comment                                                                           |
|------|----------------------------|-----------|--------------|-----------------------------------------------------------------------------------|
| 0x00 | current transaction type   | 32        |              |                                                                                   |
| 0x01 | `nonce`                    | 32        |              |                                                                                   |
| 0x02 | `sender`                   | 32        |              |                                                                                   |
| 0x03 | `sender_validation_data`   | dynamic   |              |                                                                                   |
| 0x04 | `deployer`                 | 0 or 32   | `address(0)` |                                                                                   |
| 0x05 | `deployer_data`            | dynamic   | empty array  |                                                                                   |
| 0x06 | `paymaster`                | 0 or 32   | `address(0)` |                                                                                   |
| 0x07 | `paymaster_data`           | dynamic   | empty array  |                                                                                   |
| 0x08 | `sender_execution_data`    | dynamic   |              |                                                                                   |
| 0x0B | `max_priority_fee_per_gas` | 32        |              |                                                                                   |
| 0x0C | `max_fee_per_gas`          | 32        |              |                                                                                   |
| 0x0D | `sender_validation_gas`    | 32        |              |                                                                                   |
| 0x0E | `paymaster_validation_gas` | 32        | `0`          |                                                                                   |
| 0x0F | `sender_execution_gas`     | 32        |              |                                                                                   |
| 0x10 | `paymaster_post_op_gas`    | 32        | `0`          |                                                                                   |
| 0x11 | `access_list` hash         | 32        |              |                                                                                   |
| 0x12 | `authorization_list` hash  | 32        |              |                                                                                   |
| 0xf1 | `execution_status`         | 32        |              | See transaction scoped vars in [processing flow](#aa-transaction-processing-flow) |
| 0xf2 | `execution_gas_used`       | 32        |              | See transaction scoped vars in [processing flow](#aa-transaction-processing-flow) |
| 0xff | `tx_hash_for_signature`    | 32        |              | Hash of the transaction without the signature                                     |

### Affected opcodes

In all top-level frames, the global variables have the following meaning:

| Opcode Name | Solidity Equivalent | Value                                                                                                           |
|-------------|---------------------|-----------------------------------------------------------------------------------------------------------------|
| `CALLER`    | `msg.sender`        | The `AA_ENTRY_POINT` address                                                                                    |
| `ORIGIN`    | `tx.origin`         | The transaction `sender` address                                                                                |
| `CALLDATA*` | `msg.data`          | Empty for all call frames except for the sender execution frame, for which it is set to `sender_execution_data` |

### Costs of accessing cold addresses for Sender, Paymaster, and Deployer

The Sender address is pre-warmed as part of the `AA_BASE_GAS_COST`.

When a non-zero address that is not equal to the `Sender` address, is provided for a `Paymaster` or a `Deployer` contract,
an additional [EIP-2930](./eip-2930) `ACCESS_LIST_ADDRESS_COST` cost of **2400 gas** is charged and the address is added to `accessed_addresses`.

### AA transaction processing flow

We define processing flow for an AA transaction as follows:

```
def state_transition_function(tx, block, state):
    # Empty refunds, warm list, execution status and gas used (new), etc
    state.transaction_scoped_vars = {}

    max_gas = tx.sender_validation_gas + tx.paymaster_validation_gas + tx.sender_execution_gas + tx.paymaster_post_op_gas
    gas_price = min(tx.max_fee_per_gas, block.base_fee_per_gas + tx.max_priority_fee_per_gas)
    payer = tx.sender if tx.paymaster is None else tx.paymaster
    total_max_cost = max_gas * gas_price
    balances[payer] -= total_max_cost
    gas_used = 0

    if get_code(tx.sender) is None:
        deployer_result = call(tx.deployer, [], tx.sender_validation_gas_limit, ROLE_SENDER_DEPLOYMENT)
        assert deployer_result.accepted_role == ROLE_SENDER_DEPLOYMENT
        gas_used += deployer_result.gas_used

    sender_result = call(tx.sender, [], tx.sender_validation_gas_limit - gas_used, ROLE_SENDER_VALIDATION)
    assert sender_result.accepted_role == ROLE_SENDER_VALIDATION
    gas_used += sender_result.gas_used

    if tx.paymaster:
        paymaster_result = call(tx.paymaster, [], tx.paymaster_validation_gas, ROLE_PAYMASTER_VALIDATION)
        assert paymaster_result.accepted_role == ROLE_PAYMASTER_VALIDATION
        gas_used += paymaster_result.gas_used

    checkpoint = state.take_snapshot()
    sender_execution_result = call(tx.sender, [], tx.sender_execution_gas, ROLE_SENDER_EXECUTION)
    gas_used += sender_execution_result.gas_used
    state.transaction_scoped_vars[execution_status] = sender_execution_result.output_code
    state.transaction_scoped_vars[execution_gas_used] = gas_used

    if tx.paymaster:
        postop_result = call(tx.paymaster, [], tx.paymaster_post_op_gas, ROLE_PAYMASTER_POST_OP)
        gas_used += postop_result.gas_used
        if postop_result.accepted_role != ROLE_PAYMASTER_POST_OP:
            state.revert_snapshot(checkpoint)

    balances[payer] += gas_price * (max_gas - gas_used)
```

## Rationale

A full list of rationales for the decisions made in this proposal can be found in the [README document](/EIPs/assets/eip-7701/).

## Backwards Compatibility

## Security Considerations

As the `ACCEPT_ROLE` opcode represent a generic way to authorize any action on behalf of the contract,
correct and secure implementation of this code is critical.
We expect that compilers targeting EVM will play a major role in enabling and ensuring Smart Contract Accounts&apos; security.

For smart contract security auditors and security-oriented developer tools it is crucial to ensure that contracts not
meant to have roles in AA transactions do not have unexpected `ACCEPT_ROLE` opcode.
Otherwise, these contracts may present an immediate security threat.

As an example, block explorers should tag contracts as &quot;user accounts&quot; or &quot;paymasters&quot; if they have the `ACCEPT_ROLE` opcode used in their source code.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 01 May 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7701</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7701</guid>
      </item>
    
      <item>
        <title>Set Code for EOAs</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-set-eoa-account-code-for-one-transaction/19923</comments>
        
        <description>## Abstract

Add a new [EIP-2718](/EIPs/EIPS/eip-2718) transaction type that allows Externally
Owned Accounts (EOAs) to set the code in their account. This is done by
attaching a list of authorization tuples -- individually formatted as `[chain_id,
address, nonce, y_parity, r, s]` -- to the transaction. For each tuple, a
delegation indicator `(0xef0100 || address)` is written to the authorizing
account&apos;s code. All code executing operations must load and execute the code
pointed to by the delegation.

## Motivation

Despite great advances in the smart contract wallet ecosystem, EOAs have held
back broad adoption of UX improvements across applications. This EIP therefore
focuses on adding short-term functionality improvements to EOAs which will allow
UX improvements to permeate through the entire application stack. Three
particular features this EIP is designed around are:

* **Batching**: allowing multiple operations from the same user in one atomic
transaction. One common example is an [ERC-20](/EIPs/EIPS/eip-20) approval followed by
spending that approval. This is a common workflow in DEXes that requires two
transactions today. Advanced use cases of batching occasionally involve
dependencies: the output of the first operation is part of the input to the
second operation.
* **Sponsorship**: account X pays for a transaction on behalf of account Y.
Account X could be paid in some other ERC-20 for this service, or it could be an
application operator including the transactions of its users for free.
* **Privilege de-escalation**: users can sign sub-keys and give them specific
permissions that are much weaker than global access to the account. For example,
a permission to spend ERC-20 tokens but not ETH, or to spend up to 1% of the
total balance per day, or to interact only with a specific application.

## Specification

### Parameters

|     Parameter            | Value   |
| ------------------------ | ------- |
| `SET_CODE_TX_TYPE`       | `0x04`  |
| `MAGIC`                  | `0x05`  |
| `PER_AUTH_BASE_COST`     | `12500` |
| `PER_EMPTY_ACCOUNT_COST` | `25000` |

### Set code transaction

A new [EIP-2718](/EIPs/EIPS/eip-2718) transaction known as the &quot;set code transaction&quot;
is introduced, where the `TransactionType` is `SET_CODE_TX_TYPE` and the
`TransactionPayload` is the RLP serialization of the following:

```
rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit,
destination, value, data, access_list, authorization_list, signature_y_parity,
signature_r, signature_s])

authorization_list = [[chain_id, address, nonce, y_parity, r, s], ...]
```

The fields `chain_id`, `nonce`, `max_priority_fee_per_gas`, `max_fee_per_gas`,
`gas_limit`, `destination`, `value`, `data`, and `access_list` of the outer
transaction follow the same semantics as [EIP-4844](/EIPs/EIPS/eip-4844). *Note, this
implies a null destination is not valid.*

The `signature_y_parity, signature_r, signature_s` elements of this transaction
represent a secp256k1 signature over `keccak256(SET_CODE_TX_TYPE ||
TransactionPayload)`.

The `authorization_list` is a list of tuples that indicate what code the signer
of each tuple desires to execute in the context of their EOA. The transaction is
considered invalid if the length of `authorization_list` is zero.

The transaction is also considered invalid when any field in an authorization
tuple cannot fit within the following bounds:

```python
assert auth.chain_id &lt; 2**256
assert auth.nonce &lt; 2**64
assert len(auth.address) == 20
assert auth.y_parity &lt; 2**8
assert auth.r &lt; 2**256
assert auth.s &lt; 2**256
```

The [EIP-2718](/EIPs/EIPS/eip-2718) `ReceiptPayload` for this transaction is
`rlp([status, cumulative_transaction_gas_used, logs_bloom, logs])`.

#### Behavior

The authorization list is processed before the execution portion of the
transaction begins, but after the sender&apos;s nonce is incremented.

For each `[chain_id, address, nonce, y_parity, r, s]` tuple, perform the
following:

1. Verify the chain ID is 0 or the ID of the current chain.
2. Verify the `nonce` is less than `2**64 - 1`.
3. Let `authority = ecrecover(msg, y_parity, r, s)`.
    * Where `msg = keccak(MAGIC || rlp([chain_id, address, nonce]))`.
    * Verify `s` is less than or equal to `secp256k1n/2`, as specified in
    [EIP-2](/EIPs/EIPS/eip-2).
4. Add `authority` to `accessed_addresses`, as defined in [EIP-2929](/EIPs/EIPS/eip-2929).
5. Verify the code of `authority` is empty or already delegated.
6. Verify the nonce of `authority` is equal to `nonce`.
7. Add `PER_EMPTY_ACCOUNT_COST - PER_AUTH_BASE_COST` gas to the global refund
   counter if `authority` is not empty.
8. Set the code of `authority` to be `0xef0100 || address`. This is a delegation
   indicator.
    * If `address` is `0x0000000000000000000000000000000000000000`, do not write
    the delegation indicator. Clear the account&apos;s code by resetting the account&apos;s
    code hash to the empty code hash
    `0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470`.
9. Increase the nonce of `authority` by one.

If any step above fails, immediately stop processing the tuple and continue to
the next tuple in the list. When multiple tuples from the same authority are
present, set the code using the address in the last valid occurrence.

Note, if transaction execution results in failure (e.g. any exceptional
condition or code reverting), the processed delegation indicators is *not rolled
back*.

##### Delegation indicator

Delegation indicators use the banned opcode `0xef`, defined in
[EIP-3541](/EIPs/EIPS/eip-3541), to indicate that the code must be handled differently
than regular code. The delegation forces all code executing operations to follow
the address pointer to obtain the code to execute. For example, `CALL` loads the
code at `address` and executes it in the context of `authority`.

The affected executing operations are:

* `CALL`
* `CALLCODE`
* `DELEGATECALL`
* `STATICCALL`
* any transaction where `destination` points to an address with a delegation
indicator present

For code reading, only `CODESIZE` and `CODECOPY` instructions are affected. They
operate directly on the executing code instead of the delegation. For example,
when executing a delegated account `EXTCODESIZE` returns `23` (the size of
`0xef0100 || address`) whereas `CODESIZE` returns the size of the code residing
at `address`.

*Note, this means during delegated execution `CODESIZE` and `CODECOPY` produce a
different result compared to calling `EXTCODESIZE` and `EXTCODECOPY` on the
authority.*

###### Precompiles

When a precompile address is the target of a delegation, the retrieved code is
considered empty and `CALL`, `CALLCODE`, `STATICCALL`, `DELEGATECALL`
instructions targeting this account will execute empty code, and therefore
succeed with no execution when given enough gas to initiate the call.

###### Loops

In case a delegation indicator points to another delegation, creating a
potential chain or loop of delegations, clients must retrieve only the first
code and then stop following the delegation chain.

#### Gas Costs

The intrinsic cost of the new transaction is inherited from
[EIP-2930](/EIPs/EIPS/eip-2930), specifically `21000 + 16 * non-zero calldata bytes +
4 * zero calldata bytes + 1900 * access list storage key count + 2400 * access
list address count`. Additionally, add a cost of `PER_EMPTY_ACCOUNT_COST *
authorization list length`.

The transaction sender will pay for all authorization tuples, regardless of
validity or duplication.

If a code executing instruction accesses a cold account during the resolution of
delegated code, add an additional [EIP-2929](/EIPs/EIPS/eip-2929)
`COLD_ACCOUNT_READ_COST` cost of `2600` gas to the normal cost and add the
account to `accessed_addresses`. Otherwise, assess a `WARM_STORAGE_READ_COST`
cost of `100`.

#### Transaction origination

Modify the restriction put in place by [EIP-3607](/EIPs/EIPS/eip-3607) to allow EOAs
whose code is a valid delegation indicator, i.e. `0xef0100 || address`, to
originate transactions. Accounts with any other code values may not originate
transactions.

Additionally, if a transaction&apos;s `destination` has a delegation indicator, add
the target of the delegation to `accessed_addresses`.

## Rationale

Below is the rationale for both general design directions of the EIP, as well as
specific technical choices.

### General design philosophy

#### Persistence of code delegation

The first draft of this proposal had a clever idea to avoid disagreement on
whether in-protocol revocation was needed or not. The idea was to temporarily
set code in the account with the authorization. After the transaction finished,
the code would be completely cleared. This was a new design space for enriching
EOA functionality.

Even this approach was not without its flaws. Fundamentally, there was not much
friction for users including set code authorizations. This meant that some users
and applications would opt to treat the extension as more of a scripting
facility, rather than a full-fledged upgrade to a smart contract wallet. The
outcome of this would be two somewhat competing workstreams for UX improvements:
smart contract wallets and EOA scripts.

Previous proposals had been met with similar criticisms. To counteract this,
persistent delegations were introduced. They create enough friction in
deployment that users will not deploy new, unique ones regularly. This will
hopefully unify the workstreams and minimize fragmentation in UX developments.

#### No initcode

Running initcode is not desirable for many reasons. It creates a new mode of
execution that needs extensive testing, and may be used for purposes not
possible with standard smart contract wallets. It also forces developers to
perform initialization as a standard call to the EOA after delegation. The lack
of atomicity in these operations is another factor that will push users to
complete smart contract wallet solutions, instead of EOA scripts.

Additionally, initcode tends to be propagated inside the transaction calldata.
This means it would need to be included in the authorization tuple and signed
over. The minimum initcode is around 15 bytes -- it would simply copy the
contract code from an external address. The total cost would be `16 * 15 = 240`
calldata cost, plus the [EIP-3860](/EIPs/EIPS/eip-3860) cost of `2 * 15 = 30`, plus
the runtime costs of around `150`. So nearly `500` additional gas would be spent
preparing the account. Even more likely, 1200+ gas if not copying from an
external account.

#### Creation by template

Initcode or not, there is a question of how users should specify the code they
intend to run in their account. The two main options are to specify the bytecode
directly in the transaction or to specify a pointer to the code. The simplest
pointer would just be the address of code deployed on-chain.

The cost analysis makes the answer clear. The smallest proxy would be around 50
bytes and an address is 20 bytes. The 30 byte difference provides no useful
additional functionality and will be inefficiently replicated billions of times.

Furthermore, specifying code directly would again make it possible for EOAs to
have a new, unique ability to execute arbitrary code specified in the
transaction calldata. It is for these reasons that creation by template is
chosen.

#### Interaction with applications and wallets

While this EIP provides a lot of flexibility to applications and EOAs, there are
incorrect ways of using it. Applications **must not** expect that they can
suggest the user sign an authorization, and therefore it is the duty of the
wallet to not provide an interface to do so.

**There is no safe way to provide this interface**. The code specified by an
authorization has unrestricted access to the account and must always be closely
audited by the wallet. Few users have the level of sophistication to reasonably
verify the code they are delegating to.

It is also not possible to implement a system of permissions at this level to
minimize the risk. If applications require custom wallet functionality, they
must use standardized extension / module systems built on top of the delegated
code that correctly implements permissions.

#### Forward-compatibility with future account abstraction

This EIP is designed to be forward-compatible with endgame account abstraction,
without over-enshrining any fine-grained details of [ERC-4337](/EIPs/EIPS/eip-4337) or
RIP-7560.

To start, the `address` that users sign could directly point to existing
ERC-4337 wallet code. This essentially requires the &quot;code pathways&quot; that are
used are code pathways that would, in most cases, continue to make sense in a
pure-smart-contract-wallet world. Hence, it avoids the problem of creating two
separate UX workstreams because, to a large extent, they would be the same
ecosystem.

There will be some workflows that require kludges under this solution that would
be better done in some different &quot;more native&quot; under &quot;endgame AA&quot;, but this is
relatively a small subset. The EIP does not require adding any opcodes, that
would become dangling and useless in a post-EOA world, and it allows EOAs to
masquerade as contracts to be included in ERC-4337 bundles, in a way that&apos;s
compatible with the existing `EntryPoint`.

#### Self-sponsoring: allowing `tx.origin` to set code

Allowing `tx.origin` to set code and execute its own delegated code enables what
is called self-sponsoring. It allows users to take advantage of EIP-7702 without
relying on any third party infrastructure.

However, that means the EIP breaks the invariant that `msg.sender == tx.origin`
only happens in the topmost execution frame of a transaction. This will affect
smart contracts containing `require(msg.sender == tx.origin)` style checks. This
check is used for at least three purposes:

1. Ensuring that `msg.sender` is an EOA (given that `tx.origin` always has to be
   an EOA). This invariant does not depend on the execution layer depth and,
   therefore, is not affected.
2. Protecting against atomic sandwich attacks like flash loans, which rely on
   the ability to modify state before and after the execution of the target
   contract as part of the same atomic transaction. This protection would be broken
   by this EIP. However, relying on `tx.origin` in this way is considered bad
   practice, and can already be circumvented by miners conditionally including
   transactions in a block.
3. Preventing reentrancy.

Examples of (1) and (2) can be found in contracts deployed on Ethereum mainnet,
with (1) being more common (and unaffected by this proposal). On the other hand,
use case (3) is more severely affected by this proposal, but the authors of this
EIP did not find any examples of this form of reentrancy protection, though the
search was non-exhaustive.

This distribution of occurrences—many (1), some (2), and no (3)—is exactly what
the authors of this EIP expect because:

* Determining if `msg.sender` is an EOA without `tx.origin` is difficult, if not
impossible.
* The only execution context which is safe from atomic sandwich attacks is the
topmost context, and `tx.origin == msg.sender` is the only way to detect that
context.
* In contrast, there are many direct and flexible ways of preventing reentrancy
(e.g., using a transient storage variable). Since `msg.sender == tx.origin` is
only true in the topmost context, it would make an obscure tool for preventing
reentrancy, rather than other more common approaches.

There are other approaches to mitigate this restriction which do not break the
invariant:

* Set `tx.origin` to a constant `ENTRY_POINT` address when using the `CALL*`
instruction in the context of an EOA.
* Set `tx.origin` to a special address derived from the sender or signer
addresses.
* Disallow `tx.origin` from setting code. This would make the simple batching
use cases impossible, but could be relaxed in the future.

### Rationale for technical details

#### Cost of delegation

The `PER_AUTH_BASE_COST` is the cost to process the authorization tuple and set
the delegation destination. To compute a fair cost for this operation, the
authors review its impact on the system:

* ferry 101 bytes of calldata = `101 * non-zero cost (16) = 1616`
* recovering the `authority` address = `3000`
* reading the nonce and code of `authority` = `2600`
* storing values in already warm account = `200`
* cost to deploy code = `200 * 23 = 4600`

The impact-based assessment identifies `12016` gas of comparable computation for
the operation. It is rounded up to `12500` to account for miscellaneous costs
associated with shuttling data around the state transition.

#### Clearing delegation indicators

A general design goal in state transition changes is to minimize the number of
special cases an EIP has. In early iterations, this EIP resisted a special case
for clearing an account&apos;s delegation indicator.

For most intents and purposes, an account delegated to `0x0` is
indistinguishable from a true EOA. However, one particular unfortunate case is
unavoidable. Even if a user has a zeroed out delegation indicator, most
operations that interact with that account will incur an additional
`COLD_ACCOUNT_READ_COST` upon the first touch caused by attempting to load the
code at `0x0`.

For this reason, the authors have opted to include a special case which allow
users to restore their EOA to its original purity.

#### Lack of instruction prohibition

Consistency is a valuable property in the EVM, both from an implementation
perspective and a user-understanding-perspective. Despite considering bans on
several families of instructions in the context of EOAs, the authors feel there
is not a compelling reason to do so, as it would cause smart contract wallets
and EOA smart contract wallets to proceed down distinct UX workstreams.

The main instruction families where a ban was considered were storage related
and contract creation related. The decision to not ban storage instructions
hinged mostly on their importance to smart contract wallets. Although it&apos;s
possible to have an external storage contract that the smart contract wallet
calls into, it is unnecessarily complicated and inefficient. In the future, new
state schemes may allow substantially cheaper access to certain storage slots
within an account. This is something smart contract wallets will want to take
advantage of that a storage contract wouldn&apos;t support.

Creation instructions were considered for a ban as well on other similar EIPs,
however because this EIP allows EOAs to spend value intra-transaction, the
concern with bumping the nonce intra-transaction and invalidating pending
transactions is not significant.

#### Protection from malleability cross-chain

One consideration when signing a code pointer is what code that address points
to on another chain. While it is possible to create a deterministic deployment,
i.e. via Nick&apos;s method, verifying such a deployment may not always be desirable.
In such situations, the chain ID can be set to reduce the scope of the
authorization. When universal deployment is preferred, simply set chain ID to 0.

An alternative to adding chain ID could be to substitute in the actual code for
the address in the signature. This seems to have the benefit of both minimizing
the on-chain size of auth tuples, by continuing to serialize only the address,
while retaining specificity of the actual code running in the account, by
pulling in the code for the signature. One unfortunate issue of this format,
though, is that it imposes a database lookup to determine the signer of each
auth tuple. This imposition itself seems to create enough complexity in
transaction propagation that it is decided to avoid and simply sign over the
address directly.

#### Delegation of code execution only

Other code retrieving operations like `EXTCODEHASH` do not automatically follow
delegations, they operate on the delegation indicator itself. If instead
delegations were followed, an account would be able to temporarily masquerade as
having a particular codehash, which would break contracts that rely on
codehashes as a definition of possible account behavior. A change of behavior in
a contract is currently only possible if its code explicitly allows it (in
particular via `DELEGATECALL`), and a change of codehash is only possible in the
presence of `SELFDESTRUCT` (which, as of Cancun, only applies in the same
transaction as contract creation), so choosing to follow delegations in
`EXTCODE*` opcodes would have created a new type of account breaking prior
assumptions.

#### Charge maximum cost upfront

While computing the intrinsic gas cost, the transaction is charged the
worst-case cost for each delegation. Later, while processing the authorization
list, a refund is issued if the account already exists in state. This mechanism
is designed to avoid state lookups for each authorization when computing the
intrinsic gas and can quickly determine the validity of the transaction with
only a state lookup on the sender&apos;s account.

#### No blobs, no contract creation

Transactions should be thought of as specialized tools and not necessarily a
one-type-does-all solution. EIP-4844 is treated differently at the p2p level due
to burden blobs place on a node&apos;s bandwidth. EIP-7702 has different implications
on transaction gossiping and there is no need to complicate those rules
unnecessarily by making it a superset of all possible functionality. The authors
ultimately do not expect there to be much demand for atomic delegation and blob
submission.

Contract creation is another specialized use case that has been grandfathered
into several transaction types. It adds complexity to testing, because it is a
new distinct branch of execution that needs to be tested when any change to the
EVM occurs and verify the change works as expected in that context.

For these reasons, the authors have chosen to keep the scope of the EIP focused
on improving UX.

#### Disallow delegation to precompiles

Precompiles are themselves edge cases, so allowing delegations to precompiles or
not requires some focus in implementation. Considering the fact that precompiles
technically do not have code associated with their accounts, the authors decided
it would be marginally simpler to not execute the precompile logic when a user
delegates to one. This is somewhat unintuitive.

#### Non-empty authorization list required

Set code transactions are required to have at least one authorization to be
considered valid. This is to disincentivize senders from using type 4
transactions as a generic transaction format, because this transaction has
different implications on the transaction pool than, say,
[EIP-1559](/EIPs/EIPS/eip-1559) transactions.

## Backwards Compatibility

This EIP breaks a few invariants:

* An account balance can only decrease as a result of a transaction originating
from that account.
  * Once an account has been delegated, any call to the account may also cause
  the balance to decrease.
* An EOA nonce may not increase after transaction execution has begun.
  * Once an account has been delegated, the account may call a create operation
    during execution, causing the nonce to increase.
* `tx.origin == msg.sender` can only be true in the topmost frame of execution.
  * Once an account has been delegated, it can invoke multiple calls per
  transaction.

## Security Considerations

### Implementation of secure delegate contracts

The following is a non-exhaustive list of pitfalls that delegate contracts
*should* be wary of and require a signature over from the account&apos;s authority:

* Replay protection (e.g., a nonce) should be implemented by the delegate and
signed over. Without it, a malicious actor can reuse a signature, repeating its
effects.
* `value` -- without it, a malicious sponsor could cause unexpected effects in
the callee.
* `gas` -- without it, a malicious sponsor could cause the callee to run out of
gas and fail, griefing the sponsee.
* `target` / `calldata` -- without them, a malicious actor may call arbitrary
functions in arbitrary contracts.

A poorly implemented delegate can *allow a malicious actor to take near complete
control over a signer&apos;s EOA*.

### Front running initialization

Smart contract wallet developers must consider the implications of setting code
in an account without execution. Contracts are normally deployed by executing
initcode to determine the exact code to be placed in the account. This gives
developers the opportunity to initialize storage slots at the same time. The
initial values of the account cannot be replaced by an observer, because they
are either signed over by an EOA in the case of a creation transaction or they
are committed to by computing the contract&apos;s address deterministically from the
hash of the initcode.

This EIP does not provide developers the opportunity to run initcode and set
storage slots during delegation. To secure the account from an observer
front-running the initialization of the delegation with an account they control,
smart contract wallet developers must verify the initial calldata to the account
for setup purposes be signed by the EOA&apos;s key using ecrecover. This ensures the
account can only be initialized with desirable values.

### Storage management

Changing an account&apos;s delegation is a security-critical operation that should
not be done lightly, especially if the newly delegated code is not purposely
designed and tested as an upgrade to the old one.

In particular, in order to ensure a safe migration of an account from one
delegate contract to another, it&apos;s important for these contracts to use storage
in a way that avoids accidental collisions among them. For example, using
[ERC-7201](/EIPs/EIPS/eip-7201) a contract may root its storage layout at a slot
dependent on a unique identifier. To simplify this, smart contract languages may
provide a way of re-rooting the entire storage layout of existing contract
source code.

If all contracts previously delegated to by the account used the approach
described above, a migration should not cause any issues. However, if there is
any doubt, it is recommended to first clear all account storage, an operation
that is not natively offered by the protocol but that a special-purpose delegate
contract can be designed to implement.

### Setting code as `tx.origin`

Allowing the sender of an EIP-7702 to also set code has the possibility to:

* Break atomic sandwich protections which rely on `tx.origin`;
* Break reentrancy guards of the style `require(tx.origin == msg.sender)`.

The authors of this EIP believe the risks of allowing this are acceptable for
the reasons outlined in the Rationale section.

### Sponsored transaction relayers

It is possible for the `authorized` account to cause sponsored transaction
relayers to spend gas without being reimbursed by either invalidating the
authorization (i.e., increasing the account&apos;s nonce) or by sweeping the relevant
assets out of the account. Relayers should be designed with these cases in mind,
possibly by requiring a bond to be deposited or by implementing a reputation
system.

### Transaction propagation

Allowing EOAs to behave as smart contracts via the delegation indicator poses
some challenges for transaction propagation. Traditionally, EOAs have only been
able to send value via a transaction. This invariant allows nodes to statically
determine the validity of transactions for that account. In other words, a
single transaction has only been able to invalidate transactions pending from
the sender&apos;s account.

With this EIP, it becomes possible to cause transactions from other accounts to
become stale. This is due to the fact that once an EOA has delegated to code,
that code can be called by anyone at any point in a transaction. It becomes
impossible to know if the balance of the account has been swept in a static
manner.

While there are a few mitigations for this, the authors recommend that clients
do not accept more than one pending transaction for any EOA with a non-zero
delegation indicator. This minimizes the number of transactions that can be
invalidated by a single transaction.

An alternative would be to expand the EIP-7702 transaction with a list of
accounts the caller wishes to &quot;hydrate&quot; during the transaction. Those accounts
behave as the delegated code *only* for EIP-7702 transactions which include them
in such a list, thus returning to clients the ability to statically analyze and
reason about pending transactions.

A related issue is that an EOA&apos;s nonce may be incremented more than once per
transaction. Because clients already need to be robust in a worse scenario
(described above), it isn&apos;t a major concern. However, clients should be aware
this behavior is possible and design their transaction propagation accordingly.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 07 May 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7702</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7702</guid>
      </item>
    
      <item>
        <title>Increase calldata cost</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7703-increase-calldata-cost/19933</comments>
        
        <description>## Abstract

An adjustment in the Ethereum calldata cost which reduces the maximum possible block size and allows a higher block gas limit.

## Motivation

Larger blocks take longer to propagate through the network. 
In this way, the maximum potential block size is constraining the block gas limit.
Therefore, in order to safely increase the block gas limit, the calldata gas must be increased.

## Specification

* Increase `G_CALLDATAZERO` from 4 to 12.
* Increase `G_CALLDATANONZERO` from 16 to 48.

## Rationale

Tripling the gas cost of calldata reduces the maximum possible block size by a factor of three.

## Backwards Compatibility

Activation can cause some transactions to revert due to the increased gas costs.
Ahead of activation, `eth_estimateGas` could be calculated using the new parameters in order to provide results viable for activation, avoiding out-of-gas reverts.

## Security Considerations

No security issues have been found.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 07 May 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7703</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7703</guid>
      </item>
    
      <item>
        <title>NONREENTRANT and REENTRANT opcodes</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7705-nonreentrant-opcodes/19957</comments>
        
        <description>## Abstract

Add two opcodes, `NONREENTRANT` and `REENTRANT`, which set and clear a contract&apos;s reentrancy status. After invoking `NONREENTRANT`, a contract cannot be `CALL`ed (or `STATICCALL`ed, or `DELEGATECALL`ed) until `REENTRANT` is invoked.

## Motivation

Reentrancy attacks account for a substantial portion of user funds stolen on EVM chains, including the famous &quot;DAO hack&quot;. However, due to the cost of preventing reentrancy attacks in application code, developers often opt-out of reentrancy protection. This cost has come down with the advent of transient storage ([EIP-1153](/EIPs/EIPS/eip-1153)), but it is still not cheap enough where it is a &quot;no-brainer&quot; to use it by default. This EIP proposes opcodes which make it cheaper to protect against reentrancy in application code.

## Specification

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

Two new opcodes are introduced, `NONREENTRANT` (0xF6) and `REENTRANT` (0xF7), which set and clear a contract&apos;s nonreentrancy flag. The effect of invoking `NONREENTRANT` is that a contract can no longer have execution context transferred to it (via any of the `*CALL` opcodes), until `REENTRANT` is invoked. `CALL`ing a contract which has the nonreentrancy flag set is equivalent to executing a single `REVERT` opcode.

Both `NONREENTRANT` and `REENTRANT` are idempotent; that is, invoking `NONREENTRANT` when a contract already has nonreentrant status is a no-op, and likewise for `REENTRANT`.

The scope of the nonreentrant flag is limited to the current transaction. That is, nonreentrant flags are cleared at the end of every transaction. In the presence of reversion (`REVERT` or exceptional halt), the contract&apos;s nonreentrancy flag reverts to whatever its value was before the call.

The cost of `NONREENTRANT` and `REENTRANT` are both set at 5 (`G_mid`).

## Rationale

The computational cost of pushing the current value to the call stack (for handling reverts) is accounted for in the overhead cost of the `*CALL` opcodes.

An alternative design could be considered which only introduces one opcode. This opcode, `NONREENTRANT`, would take a single stack item and set the nonreentrancy flag based on its value. This alternative design can be considered based on feedback.

## Backwards Compatibility

No backward compatibility issues found.

## Test Cases

## Reference Implementation

## Security Considerations

TBD

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 09 May 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7705</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7705</guid>
      </item>
    
      <item>
        <title>Separate gas type for calldata</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7706-create-a-separate-basefee-and-gaslimit-for-calldata/19998</comments>
        
        <description>## Abstract

Add a new type of gas for transaction calldata. Add a new transaction type that provides `max_basefee` and `priority_fee` as a vector, providing values for execution gas, blob gas and calldata gas. Modify the basefee adjustment to use the same mechanism for the three types of gas.

## Motivation

A major argument against raising the Ethereum gas limit, making calldata cheaper, or increasing the [EIP-4844](/EIPs/EIPS/eip-4844) blob count before technologies like PeerDAS become available, is that the theoretical maximum size of an Ethereum block is already too large, and we cannot afford to increase it further. However, there is an inefficiency here: the current average size of a block (not including blobs) is ~100 kB, and the theoretical max is `30,000,000 / 16 = 1,875,000` bytes (one could make larger blocks using zero bytes, but in practice zero-byte-heavy blocks would be compressed to less than 1.87 million bytes due to snappy compression). Ideally, we would have a way to bound the maximum, without making calldata more scarce _on average_.

This EIP does exactly this, by adopting the same technique that was applied for blob data in EIP-4844: we introduce a separate fee market for calldata, with a separate basefee and a separate per-block gas limit. The theoretical max calldata size of a block would be greatly reduced, while basic economic analysis suggests that _on average_, calldata would become considerably cheaper.

The EIP also introduces a new transaction type which includes the three types of max-basefees and priority fees as a vector, allowing the same code paths to handle all three types of gas. We also make the basefee adjustment, which currently uses separate mechanisms for execution gas (introduced in [EIP-1559](/EIPs/EIPS/eip-1559)) and blobs (introduced in EIP-4844), use the same approach for all three types of gas. This simplifies the basefee adjustment rules, and ensures that the stronger mathematical properties of the newer EIP-4844 basefee adjustment algorithm cover all three types of gas.

## Specification

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.

### Parameters

* `FORK_BLKNUM` = `TBD`
* `NEW_TX_TYPE` = `TBD`
* `CALLDATA_GAS_PER_TOKEN` = `4`
* `TOKENS_PER_NONZERO_BYTE` = `4`
* `CALLDATA_GAS_LIMIT_RATIO` = `4`
* `LIMIT_TARGET_RATIOS = [2, 2, 4]`
* `MIN_BASE_FEE_PER_GAS = 1` # Rename of EIP-4844 MIN_BASE_FEE_PER_BLOB_GAS
* `BASE_FEE_UPDATE_FRACTION = 8` # Roughly matches EIP-4844 parameters

### New transaction type

As of `FORK_BLOCK_NUMBER`, a new [EIP-2718](/EIPs/EIPS/eip-2718) transaction is introduced with `TransactionType` = `TX_TYPE(NEW_TX_TYPE)`.

The [EIP-2718](/EIPs/EIPS/eip-2718) `TransactionPayload` for this transaction is

```
[chain_id, nonce, gas_limit, to, value, data, access_list, blob_versioned_hashes, max_fees_per_gas, priority_fees_per_gas, y_parity, r, s]
```

We require `max_fees_per_gas` and `priority_fees_per_gas` to be length-3 vectors, each of which contain integers from `0` to `2**64-1`.

The intrinsic cost of the new transaction is inherited from EIP-4844, except that the calldata gas cost (16 per nonzero byte, 4 per zero byte) is removed.

### Block processing and transaction fees

We add the functions `get_max_fees` and `get_priority_fees`, to compute these length-3 vectors for previous transaction types:

```
def get_max_fees(tx: Transaction) -&gt; [int, int, int]:
    if tx.type == NEW_TX_TYPE:
        return tx.max_fees_per_gas
    elif tx.type == BLOB_TX_TYPE:
        return [tx.max_fee_per_gas, tx.max_fee_per_blob_gas, tx.max_fee_per_gas]
    elif is_eip_1559(tx.type):
        return [tx.max_fee_per_gas, 0, tx.max_fee_per_gas]
    else:
        return [tx.gasprice, 0, tx.gasprice]
```

```
def get_priority_fees(tx: Transaction) -&gt; [int, int, int]:
    if tx.type == NEW_TX_TYPE:
        return tx.priority_fees_per_gas
    elif tx.type == BLOB_TX_TYPE:
        return [tx.max_priority_fee_per_gas, 0, tx.max_priority_fee_per_gas]
    elif is_eip_1559(tx.type):
        return [tx.max_priority_fee_per_gas, 0, tx.max_priority_fee_per_gas]
    else:
        return [tx.gasprice, 0, tx.gasprice]
```

We also add some helpers:

```
def all_less_or_equal(v1: [int, int, int], v2: [int, int, int]) -&gt; bool:
    return all(x &lt;= y for x, y in zip(v1, v2))

def vector_add(v1: [int, int, int], v2: [int, int, int]) -&gt; [int, int, int]:
    return [x+y for x, y in zip(v1, v2)]

def vector_subtract(v1: [int, int, int], v2: [int, int, int]) -&gt; [int, int, int]:
    return [x-y for x, y in zip(v1, v2)]

def vector_subtract_clamp_at_zero(v1: [int, int, int], v2: [int, int, int]) -&gt; [uint, uint, uint]:
    return [x-y if x &gt;= y else 0 for x, y in zip(v1, v2)]

def vector_mul(v1: [int, int, int], v2: [int, int, int]) -&gt; [int, int, int]:
    return [x*y for x, y in zip(v1, v2)]
```

```
# Same rules as current calldata pricing, but rephrased (similar language to EIP-7623)
def get_calldata_gas(calldata: bytes) -&gt; int:
    tokens = calldata.count(0) + (len(calldata) - calldata.count(0)) * TOKENS_PER_NONZERO_BYTE
    return tokens * CALLDATA_GAS_PER_TOKEN
```

```
def get_gaslimits(tx: Transaction) -&gt; [int, int, int]:
    if tx.type == NEW_TX_TYPE:
        return [tx.gaslimit, len(tx.blob_versioned_hashes) * GAS_PER_BLOB, get_calldata_gas(tx.data)]
    elif tx.type == BLOB_TX_TYPE:
        return [tx.gaslimit, len(tx.blob_versioned_hashes) * GAS_PER_BLOB, get_calldata_gas(tx.data)]
    elif is_eip_1559(tx.type):
        return [tx.gaslimit, 0, get_calldata_gas(tx.data)]
    else:
        return [tx.gaslimit, 0, get_calldata_gas(tx.data)]
```

```
def get_fees_per_gas(tx: Transaction, block_basefees: [int, int, int]) -&gt; [int, int, int]:
    max_fees = get_max_fees(tx)
    priority_fees = get_priority_fees(tx)
    output = []
    # Fee sufficiency check, similar to EIP-1559 and 4844
    require(all_less_or_equal(block_basefees, max_fees))
    # Similar logic to EIP-1559 and 4844
    return [
        min(basefee + priority_fee, max_fee)
        for block_basefee, max_fee, priority_fee in zip(block_basefees, max_fees, priority_fees)
    ]
```

```
get_block_gaslimits(block: Block) -&gt; [int, int, int]:
    return [block.gaslimit, MAX_BLOB_GAS_PER_BLOCK, block.gaslimit // CALLDATA_GAS_LIMIT_RATIO]
```

**At the start of block processing**:

* We initialize a vector `gas_used_so_far` to `[0, 0, 0]`

**At the start of processing a transaction**:

* Compute `fees_per_gas = get_fees_per_gas(tx, get_block_basefees(block))` and `tx_gaslimits = get_gaslimits(tx)`
* Check that `all_less_or_equal(vector_add(gas_used_so_far, tx_gaslimits), block.gas_limits)`
* Deduct `sum(vector_mul(fees_per_gas, tx_gaslimits))` wei from the `tx.origin` account

Note that `get_block_basefees(block)` is not yet defined, we will define it in the section below. The `block.gas_limits` field is also defined in the section below.

**At the end of processing a transaction**:

* Compute `tx_gas_consumed` as a three item vector, where the first item is the amount of gas actually consumed by the transaction execution, and the second and third match the values in `get_gaslimits(tx)`
* Refund `sum(vector_mul(fees_per_gas, vector_sub(tx_gaslimits, tx_gas_consumed)))` to the `tx.origin` account (in practice, only the first term will be nonzero for now)
* Set `gas_used_so_far = vector_add(gas_used_so_far, tx_gas_consumed)`

**At the end of processing a block**:

* Require `block.gas_used = gas_used_so_far`

The `block.gas_used` field will be defined in the section below.

### Block structure:

We update `BlockHeader` field, to remove the `blob_gas_used`, `gas_used`, `base_fee_per_gas`, `gas_limit` and `excess_blob_gas` fields, and we add new fields, all of the `[int, int, int]` type: `gas_limits`, `gas_used`, `excess_gas`. The resulting RLP encoding becomes:

```
rlp([
    parent_hash,
    0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347, # ommers hash
    coinbase,
    state_root,
    txs_root,
    receipts_root,
    logs_bloom,
    0, # difficulty
    number,
    timestamp,
    extradata,
    prev_randao,
    0x0000000000000000, # nonce
    withdrawals_root,
    gas_limits,
    gas_used,
    excess_gas
])
```

We define:

```
get_block_gas_targets(parent: Header) -&gt; [int, int, int]:
    return [limit // target_ratio for limit, target_ratio in zip(parent.gas_limits, LIMIT_TARGET_RATIOS)]
```

We calculate the required `excess_gas` values as follows:

```
def calc_excess_gas(parent: Header) -&gt; [int, int, int]:
    return vector_subtract_clamp_at_zero(vector_add(parent_excess, parent_used), get_block_gas_targets(parent))
```

We calculate the required `gas_limits` as follows:

* `gas_limits[0]` must follow the existing adjustment formula
* `gas_limits[1]` must equal `MAX_BLOB_GAS_PER_BLOCK`
* `gas_limits[2]` must equal `gas_limits[0] // CALLDATA_GAS_LIMIT_RATIO`

Now, we define `get_block_basefees`:

```
def get_block_basefees(parent: Header) -&gt; [int, int, int]:
    return [
        fake_exponential(
            MIN_BASE_FEE_PER_GAS,
            excess_gas,
            target * BASE_FEE_UPDATE_FRACTION
        )
        for (excess_gas, target) in zip(parent.excess_gas, get_block_gas_targets(parent))
    ]
```
        
## Rationale

### Conversion of all gas-related mechanics into vectors

This allows the same logic that is used for handling gas to handle all three types of gas. As a result, it&apos;s arguably a net simplification of protocol gas handling logic, despite the fact that the total number of gas types increases from 2 to 3

### Target ratios

The target ratios for execution gas and blobs are set to 2; the target ratio for calldata is set to 4. This greatly decreases the number of scenarios in which calldata actually hits the limit, which mitigates economic impact of the EIP, because analysis of EIP-1559-style fee markets is much simpler in &quot;under-the-limit&quot; conditions than in &quot;at-the-limit&quot; conditions. Additionally, it reduces the risk that applications requiring large calldata will outright stop working.

The current parameters set the target calldata per block to 187,500 bytes, about 2x the current average. Using basic supply-and-demand reasoning, this implies that calldata is likely to become significantly cheaper as a result of this EIP.

## Backwards Compatibility

Previous transaction types set the calldata basefee and priority fee to equal each other. The calldata gas costs were intentionally set to be identical to today, and the gas target similar to present-day usage, so that setting the two fees to be equal each other is a reasonable approximation to optimal behavior. In practice, the new transaction type would be superior, so we expect users to switch to it over time. However, the loss suffered by old-style transaction users would not be that high, because priority fees are generally small compared to basefees, and the amount that a user pays is proportional to the basefee.

## Security Considerations

Optimal block building behavior becomes more complex as a result of this EIP, particularly under the boundary conditions when blocks are full of one or both types of gas. We argue that the effects of this are not too large, because in practice over 90% of blocks are under-full, and naive &quot;greedy algorithms&quot; can get a close-enough-to-optimal outcome. The centralization risks of proprietary block-building algorithms are thus likely to be much smaller than other existing risks with eg. MEV extraction.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 13 May 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7706</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7706</guid>
      </item>
    
      <item>
        <title>Incentivize Access List Provisioning</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7707-align-incentives-for-access-list-provisioning/20025</comments>
        
        <description>## Abstract

This EIP reduces the gas cost of access list data, incentivizing the inclusion of complete and valid access lists in transactions to improve data load efficiency for execution layer clients.

## Motivation

While [EIP-2930](/EIPs/EIPS/eip-2930) introduced `accessLists` as a mechanism for `SLOAD`
pre-warming  to reduce gas costs by informing the EVM upfront about which storage slots a transaction will access,
the practical use is limited and uncommon due to the savings versus penalties involved. In order to break even for
each address included `24 storage keys` are required per address, and there is a `100 gas` saving per key at `25+`; 
in contrast the penalty for including an unused key is `1900 gas`, so break-even where one key is unused is `43 keys`.\
\
This situation makes the break-even and risk-reward ratio of  `accessLists` rarely appealing in practice for regular
transactions, where a prior transaction could lead to a different branch being taken and a slightly different set of
storage slots being accessed. Furthermore, a very high number of SLOADs is required to start breaking even.\
\
For some clients, data loading takes `&gt;70%` of block execution time. This
happens in part due to sequential transaction execution and iterative
search of effectively random access data.\
\
While NVMe drives have massive throughput and IOPS; this is their
concurrent throughput operated through multiple queues and they do not
have this performance if data is accessed completely sequentially with
one request waiting for the prior to complete i.e. stacking individual
IOPS latency end to end will not give anything close to maximal
throughput that these drives can deliver (which is different from the
HDD world where heads needed to seek to different physical locations for
each read). This is a similar situation with network attached storage or
cloud data disks; however the latency here is even more amplified than a
local direct CPU attached NVMe drive (i.e. via network card).\
\
If nodes had a somewhat clearer picture of what data to pre-load for the
block&apos;s execution; that can be done in parallel, hiding much of the
latency from accessing that data when discovered from executing the
transaction. Very much in a similar way to instruction pipelining on a
CPU hiding memory access latencies; the data access for transactions
could be pipelined. This can lead to faster/cheaper block execution and
would facilitate data dependency hints for parallel Tx execution in the
future, like on other emerging chains that were developed with more
modern hardware in mind.

## Specification

We shall update [EIP-2930](/EIPs/EIPS/eip-2930)
parameters:

| Constant | Value |
| - | - |
| `ACCESS_LIST_STORAGE_KEY_COST` | 320 |
| `ACCESS_LIST_ADDRESS_COST` | 512 |


## Rationale

As stated in the introduction the gas cost benefit analysis does not
encourage the users of the chain to provide accessList hints, even
though the mechanism is already in protocol (and a call to
`eth_createAccessList` will give them, or a wallet the correct list
to include). So we propose a reduction in the pricing of those data
access lists to make them more inline with calldata.\
\
Levelling the playing field between small `call_data` and `access_lists`
costs, (and incentivise `access_lists` provisioning from transaction
senders as they are needed for transaction execution in a faster
manner), the price model updates would look as follows:

Use `STANDARD_TOKEN_COST * tokens_in_access_lists`, where
`tokens_in_access_lists = bytes_in_access_lists * 4`, making it as
expensive to send as plain small call data. So we will get:

- `32*4*4  = 512` for addresses (instead of 2400, 4.6 times less)

- `20*4*4  = 320` for storage keys (instead of 1900, 5.9 times less)

This means users pay for on-chain data inclusion as usual `call_data`. It
changes the original
[EIP-2930](/EIPs/EIPS/eip-2930) logic
of &quot;covering the bandwidth costs&quot;, which was not described in detail and
is potentially outdated. 

It should be noted that this is not the first time [EIP-2930](/EIPs/EIPS/eip-2930) additions have been proposed. In [EIP-3521](/EIPs/EIPS/eip-3521), a reduction was already proposed, but it focused only on `ACCESS_LIST_ADDRESS_COST`.

### Examples

Current

| Inst | Type | Access List | Keys for address | OP Price | AccessList Key Price | AccessList Address Price | Total gas per OP |
|------|------|-------------|------------------|----------|----------------------|-------------------------|------------------|
| `SLOAD` | Cold | Not included | - | 2100 | 0 | 0 | 2100 |
| `SLOAD` | Warm | Not included | - | 100 | 0 | 0 | 100 |
| `SLOAD` | Warm | Included | - | 100 | - | - | 100 |
| `SLOAD` | Cold | Included | 1 | 100 | 1900 | 2400 | 4400 |
| `SLOAD` | None | Included | 1 | 0 | 1900 | 2400 | 4300 |
| `SLOAD` | Cold | Included | 10 | 100 | 1900 | 240 | 2240 |
| `SLOAD` | None | Included | 10 | 0 | 1900 | 240 | 2140 |
| `SLOAD` | Cold | Included | 50 | 100 | 1900 | 48 | 2048 |
| `SLOAD` | None | Included | 50 | 0 | 1900 | 48 | 1948 |


Proposed

| Inst  | Type | Access List   | Keys for address | OP Price | AccessList Key Price | AccessList Address Price | Total gas per OP |
|-------|------|---------------|------------------|----------|----------------------|-------------------------|------------------|
| `SLOAD` | Cold | Not included  | -                | 2100     | 0                    | 0                       | 2100             |
| `SLOAD` | Warm | Not included  | -                | 100      | 0                    | 0                       | 100              |
| `SLOAD` | Warm | Included      | -                | 100      | -                    | -                       | 100              |
| `SLOAD` | Cold | Included      | 1                | 100      | 320                  | 512                     | 932              |
| `SLOAD` | None | Included      | 1                | 0        | 320                  | 512                     | 832              |
| `SLOAD` | Cold | Included      | 10               | 100      | 320                  | 51.2                    | 471              |
| `SLOAD` | None | Included      | 10               | 0        | 320                  | 51.2                    | 371              |
| `SLOAD` | Cold | Included      | 50               | 100      | 320                  | 10.24                   | 430              |
| `SLOAD` | None | Included      | 50               | 0        | 320                  | 10.24                   | 330              |


\- Already paid on making warm

## Backwards Compatibility

This EIP makes a minor update to
[EIP-2930](/EIPs/EIPS/eip-2930) with
respect to modern execution challenges and capabilities.

## Security Considerations


Same as per
[EIP-2930](/EIPs/EIPS/eip-2930)


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 12 May 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7707</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7707</guid>
      </item>
    
      <item>
        <title>ETH transfers and burns emit a log</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7708-eth-transfers-emit-a-log/20034</comments>
        
        <description>## Abstract

All ETH transfers and burns emit a log.

## Motivation

Logs are often used to track when balance changes of assets on Ethereum. Logs work for [ERC-20](/EIPs/EIPS/eip-20) 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 `CALL` or `SELFDESTRUCT` happens. We also add a similar log for transfers in transactions, so that all ETH transfers can be tracked using one mechanism.

## Specification

### ETH transfer logs

A log, identical to a LOG3, is issued for:

- Any nonzero-value-transferring transaction to a different account, before any other logs created by EVM execution
- Any nonzero-value-transferring `CALL` to a different account, at the time that the value transfer executes
- Any nonzero-value-transferring `SELFDESTRUCT` to a different account, at the time that the value transfer executes

| Field | Value |
| - | - |
| `address` emitting log | `0xfffffffffffffffffffffffffffffffffffffffe` ([`SYSTEM_ADDRESS`](/EIPs/EIPS/eip-4788)) |
| `topics[0]` | `0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef` (`keccak256(&apos;Transfer(address,address,uint256)&apos;)`) |
| `topics[1]` | `from` address (zero prefixed to fill uint256) |
| `topics[2]` | `to` address (zero prefixed to fill uint256) |
| `data` | `amount` in Wei (big endian uint256) |

This matches the [ERC-20](/EIPs/EIPS/eip-20) Transfer event definition.

### ETH burn logs

A log, identical to a LOG2, is issued for:

- Any nonzero-balance `SELFDESTRUCT` to self by a contract created in the same transaction, at the time the opcode is invoked
- Any nonzero-balance account marked for deletion, at the time of removal during transaction finalization

Burn logs are emitted after all other logs created by EVM execution and the payment of the [EIP-1559](/EIPs/EIPS/eip-1559) priority fee to the coinbase. When multiple accounts with non-zero balances are marked for deletion, burn logs are emitted in lexicographical order of account address.

| Field | Value |
| - | - |
| `address` emitting log | `0xfffffffffffffffffffffffffffffffffffffffe` ([`SYSTEM_ADDRESS`](/EIPs/EIPS/eip-4788)) |
| `topics[0]` | `0xcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5` (`keccak256(&apos;Burn(address,uint256)&apos;)`) |
| `topics[1]` | `address` (zero prefixed to fill uint256) |
| `data` | `amount` in Wei (big endian uint256) |

## Rationale

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.

### Open questions

1. Magic value used for `address`? For address: (a) `0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee` (same as `eth_simulateV1`), (b) `0xfffffffffffffffffffffffffffffffffffffffe` ([`SYSTEM_ADDRESS`](/EIPs/EIPS/eip-4788)), (c) zero address
2. Should fee payments trigger a log? It would ensure &quot;completeness&quot;, in the sense that you can compute the exact current balance table by watching logs, but it would greatly increase the number of logs, perhaps to an unacceptably high amount.
3. Should withdrawals also trigger a log? They are not associated with transactions.

## Backwards Compatibility

No backward compatibility issues found.

## Test Cases

TODO

## Security Considerations

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.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Read BLOCKHASH from storage and update cost</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7709-read-blockhash-opcode-from-storage-and-adjust-gas-cost/20052</comments>
        
        <description>## Abstract

Update the `BLOCKHASH (0x40)` opcode to read and serve from the system contract storage and charge the **additional** (cold or warm) storage costs.

## Motivation

The `BLOCKHASH (0x40)` opcode currently assumes that the client has knowledge of the previous blocks, which in Verkle [EIP-6800](/EIPs/EIPS/eip-6800) would prevent stateless execution. However with [EIP-2935](/EIPs/EIPS/eip-2935) blockhashes can be retrieved and served from its system contract storage which allows Verkle blocks to include a storage access witness for stateless execution.

## Specification

| Parameter                 | Value  |
| ------------------------- | ------ |
| `FORK_TIMESTAMP`          | TBD    |
| `HISTORY_STORAGE_ADDRESS` | `0x0000F90827F1C53a10cb7A02335B175320002935` |
| `BLOCKHASH_SERVE_WINDOW`  | `256`  |

The `BLOCKHASH` opcode semantics remains the same as before. From the `fork_block` (defined as `fork_block.timestamp &gt;= FORK_TIMESTAMP and fork_block.parent.timestamp &lt; FORK_TIMESTAMP`), the `BLOCKHASH` instruction should be updated to resolve block hash in the following manner:

```python
def resolve_blockhash(block: Block, state: State, arg: uint64):
  # note that outside the BLOCKHASH_SERVE_WINDOW we continue to return 0
  # despite the 2935 history contract being able to serve more hashes
  if arg &gt;= block.number or (arg + BLOCKHASH_SERVE_WINDOW) &lt; block.number
    return 0

  # performs an sload on arg % HISTORY_SERVE_WINDOW including gas charges,
  # warming effects as well as execution accesses
  #
  # note that the `BLOCKHASH_SERVE_WINDOW` and the 2935 ring buffer window
  # `HISTORY_SERVE_WINDOW` for slot calculation are different
  return state.load_slot(HISTORY_STORAGE_ADDRESS, arg % HISTORY_SERVE_WINDOW)
```

ONLY if the `arg` is within the correct `BLOCKHASH` window, clients can choose to either

* do a direct `SLOAD` from state, or
* do a system call to [EIP-2935](/EIPs/EIPS/eip-2935) contract via its `get` mechanism (caller other than `SYSTEM_ADDRESS`) or
* serve from memory or as per current designs if maintaining requisite history (full clients for e.g.)

However the entire semantics and after effects of the `SLOAD` operation needs to be applied as per the current fork if the `arg` is within the correct `BLOCKHASH` window:

* `SLOAD` gas costs (cold or warm) for the `arg % HISTORY_SERVE_WINDOW` slot.
* `SLOAD` after effects on the slot (warming the slot)
* `SLOAD` accesses added to execution witnesses if Verkle ([EIP-6800](/EIPs/EIPS/eip-6800) and [EIP-4762](/EIPs/EIPS/eip-4762)) is activated

### Activation

This EIP specifies the transition to the new logic assuming that [EIP-2935](/EIPs/EIPS/eip-2935) has been activated:

* sufficiently ahead of this EIP&apos;s activation (&gt;= `BLOCKHASH_SERVE_WINDOW`) or
* at genesis for testnets/devnets where this EIP could also be activated at genesis

The current proposal is to activate this EIP with Verkle to allow for stateless execution of the block.

### Gas costs

As described above, if the `arg` to be resolved is within the correct window, the corresponding `SLOAD` charges and accesses are to be applied for the slot `arg % HISTORY_SERVE_WINDOW`. Note that the `HISTORY_SERVE_WINDOW` and `BLOCKHASH_SERVE_WINDOW` are different.

### Reading from the System contract

Even if the clients choose to resolve `BLOCKHASH` through system call to [EIP-2935](/EIPs/EIPS/eip-2935) contract, the gas cost for the system code execution (and also the code witnesses if Verkle activated) is not applied. Only the effect of `SLOAD` is applied as described above.

## Rationale

* The reason behind the updated gas cost is to match the real operation, which is equivalent to an `SLOAD`.
* The [EIP-2935](/EIPs/EIPS/eip-2935) system contract execution charges (and accesses) are not applied to keep the gas low and to keep things simple for clients which choose to resolve `BLOCKHASH` in other ways (directly or though memory/maintained history)

Note that `BLOCKHASH` opcode only serves a limited `BLOCKHASH_SERVE_WINDOW` to be backward compatible (and to not extend the above exemptions). For deeper accesses one will need to directly call [EIP-2935](/EIPs/EIPS/eip-2935) system contract which will lead to a normal contract execution (as well as charges and accesses)

## Backwards Compatibility

This EIP introduces a significant increase in the cost of `BLOCKHASH`, which could break use-cases that rely on the previous gas cost. Also, this EIP introduces a breaking change in the case where less than `BLOCKHASH_SERVE_WINDOW` elapse between the [EIP-2935](/EIPs/EIPS/eip-2935) fork and this EIP&apos;s fork (unless [EIP-2935](/EIPs/EIPS/eip-2935)  is activated in genesis for e.g. in testnets/devnets) as the [EIP-2935](/EIPs/EIPS/eip-2935) system contract would not have saved the required history.

## Test Cases

* If `BLOCKHASH` is not called or there is no [EIP-2935](/EIPs/EIPS/eip-2935) contract call by any transaction, only the [EIP-2935](/EIPs/EIPS/eip-2935) system update of the parent hash shows up in witnesses if Verkle is activated.
* If `BLOCKHASH` is called, there MUST be a storage access gas charge (and corresponding access witness if Verkle is activated) for the storage slot but ONLY if the `BLOCKHASH` query is for the last `BLOCKHASH_SERVE_WINDOW` ancestors. This is irrespective of how the client chooses to resolve the `BLOCKHASH` (directly, via system contract or via memory)
* The gas cost for each `BLOCKHASH` operation should still be charged, in addition to the `SLOAD` cost of each lookup (if performed)
* If the [EIP-2935](/EIPs/EIPS/eip-2935) contract is called directly (i.e. not through `BLOCKHASH`), then the witness and gas costs (including those related to contract code) are applied as per normal contract execution of the current fork.
* `BLOCKHASH` should be consistently resolved if this EIP is activated correctly `&gt;= BLOCKHASH_SERVE_WINDOW` after [EIP-2935](/EIPs/EIPS/eip-2935)

## Security Considerations

No security considerations other than the ones contained in [EIP-2935](/EIPs/EIPS/eip-2935) are determined as of now.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 18 May 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7709</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7709</guid>
      </item>
    
      <item>
        <title>Smart Contract Delegation</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/towards-more-conversational-wallet-connections-a-proposal-for-the-redeemdelegation-interface/16690</comments>
        
        <description>## Abstract

This proposal introduces a standard way for smart contracts to delegate capabilities to other smart contracts
or Externally Owned Accounts (EOAs).  The delegating contract (delegator) must be able to authorize a
`DelegationManager` contract to call the delegator to execute the desired action.

This framework empowers a delegating contract with the ability to delegate any actions it has the authority to perform,
thereby enabling more flexible and scalable contract interactions. This standard outlines the
minimal interface necessary to facilitate such delegation.

Additionally, this proposal is compatible with [ERC-4337](/EIPs/EIPS/eip-4337), although its implementation does not
necessitate [ERC-4337](/EIPs/EIPS/eip-4337).

## Motivation

The development of smart contracts on Ethereum has led to a diverse array of decentralized applications (dApps)
that leverage composability to interact with one another in innovative ways. While current smart contracts are
indeed capable of working together, enabling these interactions, especially in the realm of sharing capabilities
or permissions, remains a tedious and often gas-expensive process, which lacks backwards compatibility.

Currently, for a smart contract to interact with or utilize the functionality of another, it typically requires
hardcoded permissions or the development of bespoke, intermediary contracts. This not only increases the complexity and
development time but also results in higher deployment and execution gas costs. Moreover, the rigid nature of these
interactions limits the ability to adapt to new requirements or to delegate specific, limited permissions in a dynamic
manner.

Additionally, the need to repeatedly sign messages for each interaction creates friction in user experiences, particularly in scenarios requiring frequent or automated interactions.

The proposed standard aims to solve these challenges by enabling the creation of long-lived sessions and delegated permissions through a single signature. These delegations can be used to:
- Establish persistent sessions with dApps that don&apos;t require repeated signing
- Grant bounded permissions to AI agents or automated systems
- Create shareable invite links with specific capabilities
- Enable third-party delegates to act within well-defined policy constraints

By allowing the creation of open-ended yet policy-constrained delegations with a single signature, this standard helps
minimize user interactions while maximizing their meaningful content. Users can grant specific capabilities with
clear boundaries, rather than repeatedly signing similar permissions.

The proposed standard aims to simplify and standardize the process of delegation between contracts, reducing the
operational complexity and gas costs associated with shared capabilities. By establishing a common framework for
delegating permissions, we can streamline interactions within the Ethereum ecosystem, making contracts more flexible,
cost-effective, and adaptable to the needs of diverse applications. This opens up new possibilities for collaboration
and innovation, allowing dApps to leverage each other&apos;s strengths in a more seamless and efficient manner.

## Specification

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

### Terms

- A **Delegator** is a smart contract that can create a delegation.
- A **Delegation Manager** is a smart contract that validates delegation authority and calls on the *Delegator* to execute an action. It implements the `ERC7710Manager` interface. A Delegation Manager verifies and processes delegation redemptions, and multiple Delegation Managers can exist with different implementations. A contract account can be its own delegation manager.
- A **delegation** is an authority given to another address to perform a specific action.
- A **delegate** is a smart contract, smart contract account, or EOA that has authority to redeem a delegation.
- A **redeemer** is a *delegate* that is using a delegation.

### Obtaining Delegations

The process by which a delegate obtains a delegation is intentionally left out of scope for this ERC. This ERC focuses solely on the interface for redeeming delegations and the validation of delegation authority. The mechanism for requesting and granting delegations may be implemented in various ways depending on the use case, such as through [ERC-7715](/EIPs/EIPS/eip-7715) or other protocols. This separation of concerns allows for flexibility in how delegations are created while maintaining a consistent interface for their redemption.

### Overview

#### Redeeming a Delegation

When a delegate wishes to redeem a delegation, they call the `redeemDelegations` function on the Delegation Manager and
pass in the action they want to execute and the proof of authority (ie delegation) which they are executing on behalf
of. The Delegation Manager then verifies the delegation&apos;s validity and, if valid, calls the privileged function on the
Delegator which executes the specified capability on behalf of the Delegator.

![diagram showing the flow of redeemDelegations](/EIPs/assets/eip-7710/diagram.svg)

### Interfaces

#### `ERC7710Manager.sol`

The Delegation Manager MUST implement the `redeemDelegations` which will be responsible for validating the delegations
being redeemed, and will then call the delegators to execute the actions.

The bytes array `_permissionContexts` passed in as a parameter to the `redeemDelegations` function contains the authority to execute a
specific action on behalf of the delegating contract.

The bytes32 array `_modes` and the bytes array `_executionCallDatas` passed in as parameters to the `redeemDelegations` function are arrays of `mode` and `executionCalldata`, which are defined precisely in [ERC-7579](/EIPs/EIPS/eip-7579) (under the &quot;Execution Behavior&quot; section).  Briefly, `mode` encodes the &quot;behavior&quot; of the execution, which could be a single call, a batch call, and others.  `executionCallData` encodes the data of the execution, which typically includes at least a `target`, a `value`, and a `to` address.

The three arrays MUST be interpreted as a list of tuples, where each tuple consists of (`_permissionContexts[i]`, `_modes[i]`, `_executionCallDatas[i]`). The function MUST revert if the arrays have different lengths. Each tuple represents a single delegation redemption with its associated permission context, execution mode, and execution data. Implementations MUST enforce atomicity of the batch.

#### Permission Verification

While this interface does not include an explicit method for checking delegation permissions, dApps SHOULD verify permissions before attempting to execute actions by:

1. Simulating the `redeemDelegations` call with the intended parameters
2. Using the simulation results to determine if the delegation would succeed
3. If the simulation fails, the dApp can request new or updated permissions from the user

This simulation-based approach provides stronger guarantees than a method exposed by the delegation manager, as it validates the entire execution context rather than the claims of the delegation manager.

```solidity
pragma solidity 0.8.23;

/**
 * @title ERC7710Manager
 * @notice Interface for Delegation Manager that exposes the redeemDelegations function.
 */
interface ERC7710Manager {
    /**
     * @notice This method validates the provided permission contexts and executes the execution if the caller has authority to do so.
     * @dev the structure of the _permissionContexts bytes[] is determined by the specific Delegation Manager implementation
     * @param _permissionContexts the data used to validate the authority given to execute the corresponding execution.
     * @param _action the action to be executed
     * @param _modes the array of modes to execute the related executioncallData
     * @param _executionCallDatas the array of encoded executions to be executed
     */
  function redeemDelegations(
    bytes[] calldata _permissionContexts,
    bytes32[] calldata _modes,
    bytes[] calldata _executionCallData
  ) external;
}
```

## Rationale

The design of this ERC is motivated by the need to introduce standardized, secure, and efficient mechanisms for
delegation within the Ethereum ecosystem. Several considerations were taken into account:

**Flexibility and Scalability**: The proposed interfaces are designed to be minimal yet powerful, allowing contracts to
delegate a wide range of actions without imposing a heavy implementation burden. This balance aims to encourage
widespread adoption and innovation.

**Interoperability**: Compatibility with existing standards, such as [ERC-1271](/EIPs/EIPS/eip-1271) and [ERC-4337](/EIPs/EIPS/eip-4337), ensures that this approach
can be seamlessly integrated into the current Ethereum infrastructure. This encourages adoption and leverages existing
security practices.

**Usability**: By enabling contracts to delegate specific actions to others, we open the door to more user-friendly
DApps that can perform a variety of tasks on behalf of users, reducing the need for constant user interaction and
enhancing the overall user experience.

This ERC represents a step towards a more interconnected and flexible Ethereum ecosystem, where smart contracts can more
effectively collaborate and adapt to users&apos; needs.

### Execution Interface

A previous iteration of this spec defined `Action` as a simple `(target, value, data)` tuple, and defined a specific
execution interface on the delegator that is `executeDelegatedAction(Action _action)` which the Delegation Manager is
supposed to call.

That approach had a few downsides:

- Existing smart accounts won&apos;t be compatible with this spec (unless they happen to implement the execution interface).
- The execution behavior is limited to a single call, since `Action` could only encode a single call.  It made complex
  execution behaviors such as batching, delegatecall, and CREATE2 impossible.

To solve the first issue, we decided to remove the requirement for the delegator to implement any specific interface.
Rather, we rely on the Delegation Manager to correctly call the delegator, and we rely on the fact that a delegator would
only create `_permissionContexts` for a Delegation Manager that knows how to correctly call it.

To solve the second issue, we decied to adopt the execution interface from [ERC-7579](/EIPs/EIPS/eip-7579), which had to solve a similar problem
within the context of modular smart accounts: defining a standardized execution interface that can support many types of
executions.

## Reference Implementation

For a minimal reference implementation focusing on delegation redemption, please see [Example7710Manager](/EIPs/assets/eip-7710/Example7710Manager.sol). 

For a complete reference implementation of a Delegation Manager, see the MetaMask Delegation Framework, which includes features such as:

- [EIP-712](/EIPs/EIPS/eip-712) signature validation for delegations
- Support for both EOA and contract signatures (ERC-1271)
- Caveat enforcement for fine-grained delegation control
- Batch delegation processing
- Delegation revocation mechanisms

The MetaMask implementation demonstrates one way to build a robust delegation system while adhering to this standard&apos;s interface requirements.

## Security Considerations

The introduction of customizable authorization terms requires careful consideration of how authorization data is
structured and interpreted. Potential security risks include the misinterpretation of authorization terms and
unauthorized actions being taken if the interface is not properly implemented. It is recommended that applications
implementing this interface undergo thorough security audits to ensure that authorization terms are handled securely.

### Permission Verification

dApps MUST NOT assume that having received a delegation in the past guarantees future execution rights. Delegations can be revoked, expire, or become invalid due to state changes. To ensure reliable operation:

1. Always simulate delegation redemptions before submitting them on-chain
2. Handle simulation failures gracefully by requesting new permissions when needed
3. Consider implementing retry logic with escalating permission requests
4. Be prepared for delegations to become invalid between simulation and execution

Needs discussion. &lt;!-- TODO --&gt;

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 20 May 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7710</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7710</guid>
      </item>
    
      <item>
        <title>Box type for EIP-712 messages</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7713-box-types-for-eip-712-messages/20092</comments>
        
        <description>## Abstract

This EIP defines a new type `box` for use in [EIP-712](/EIPs/EIPS/eip-712) messages. A `box` value is a value of an arbitrary struct type whose underlying type is encapsulated and hidden from the outer struct but transparent and type-checkable by the wallet, and thus able to be fully inspected by the user prior to signing. A verifying contract can be made agnostic to the underlying type of a `box` value, but this type is not erased and can be verified on-chain if necessary.

## Motivation

EIP-712 signatures have become a widely used primitive for users to express and authorize intents off-chain. Wide-ranging applications are able to define parameterized messages for users to sign in their wallet through a general-purpose interface that clearly surfaces the type, parameters, and domain of authorization. This crucially applies to hardware wallets as a last line of defense.

The general-purpose nature of EIP-712 is key to its success, but in addition wallets are able to develop special-purpose interfaces and capabilities for specific types of messages as they become more widely used. For example, [ERC-2612](/EIPs/EIPS/eip-2612) Permits are a well-known EIP-712 message that wallets display to the user in a special way that clearly surfaces the known implications and risks of signing.

Special-purpose interfaces improve usability and security for the user, but rely on standardized message types such as Permits. This EIP concerns the ability to standardize messages that contain within them parameters of arbitrary type.

A recent example is found in [ERC-7683](/EIPs/EIPS/eip-7683), which defines a struct with the following member:

```solidity
/// @dev Arbitrary implementation-specific data
/// Can be used to define tokens, amounts, destination chains, fees, settlement parameters,
/// or any other order-type specific information
bytes orderData;
```

Defining this parameter with type `bytes` enables the message to contain data of arbitrary type and is sufficient to bind the signature to implementation-specific data, but it amounts to type erasure. As a consequence, the user will be presented with an opaque bytestring in hexadecimal format in the wallet&apos;s signing interface. This negates the benefit of using EIP-712 signatures because the true contents of the parameter are invisible to the wallet&apos;s general-purpose interface.

Another example is found in recent efforts to make [ERC-1271](/EIPs/EIPS/eip-1271) signatures secure against replay. Achieving this without making the message contents opaque to the signer requires embedding an application&apos;s EIP-712 message inside an outer message that binds it to a specific account. The type of the outer message depends on the type of the inner message, and making the type reproducible by the smart contract account on-chain for verification requires an inefficient scheme to communicate the string-encoded type of the inner message as a part of the signature.

Both of these use cases would benefit from the ability to define EIP-712 struct parameters of arbitrary type in such a way that the verifying contract can be agnostic to the type of the parameter&apos;s value in a message while the wallet retains the ability to transparently display it to the user for inspection.

## Specification

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

EIP-712 is extended as follows:

### Typed structured data

A struct type may contain a *boxed member* by declaring it with type `box`. Example:

```solidity
struct Envelope {
    address account;
    box contents;
}
```

A boxed member has an underlying *unboxed type*, which is an arbitrary struct type and may be different in each message.

### `encodeType`

A boxed member is encoded as `&quot;box &quot; || name`. For example, the above `Envelope` struct is encoded as `Envelope(address account,box contents)`.

### `encodeData`

A boxed value is encoded as its underlying *unboxed value*, i.e., `hashStruct(value) = keccak256(typeHash, encodeData(value))` where `typeHash` corresponds to the unboxed type and `encodeData` is operating on a value of that type.

### `signTypedData` schema

A signature request for an EIP-712 message that involves a boxed member shall include the unboxed type as a part of the message object. A boxed value must be an object with properties `value`, `primaryType`, and `types`. The `value` shall be type-checked and encoded according to `primaryType` and `types`, analogously to an EIP-712 message (though without the `\x19` prefix). The `types` defined in the message outside of the boxed value shall not be in scope for the encoding of a boxed value.

For example, a message for the `Envelope` type above may be represented as:

```js
{
    domain: ...,
    primaryType: &apos;Envelope&apos;,
    types: {
        Envelope: [
            { name: &apos;account&apos;, type: &apos;address&apos; },
            { name: &apos;contents&apos;, type: &apos;box&apos; }
        ]
    },
    message: {
        account: &apos;0x...&apos;,
        contents: {
            primaryType: &apos;Mail&apos;,
            types: {
                Mail: [
                    { name: &apos;greeting&apos;, type: &apos;string&apos; }
                ]
            },
            value: {
                greeting: &apos;Hello world&apos;
            }
        },
    }
}
```

#### JSON Schema of a boxed value

```js
{
  type: &apos;object&apos;,
  properties: {
    value: {type: &apos;object&apos;},
    primaryType: {type: &apos;string&apos;},
    types: {
      type: &apos;object&apos;,
      additionalProperties: {
        type: &apos;array&apos;,
        items: {
          type: &apos;object&apos;,
          properties: {
            name: {type: &apos;string&apos;},
            type: {type: &apos;string&apos;}
          },
          required: [&apos;name&apos;, &apos;type&apos;]
        }
      }
    }
  },
  required: [&apos;value&apos;, &apos;primaryType&apos;, &apos;types&apos;]
}
```

## Rationale

TBD &lt;!-- TODO --&gt;

## Security Considerations

Needs discussion. &lt;!-- TODO --&gt;

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 23 May 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7713</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7713</guid>
      </item>
    
      <item>
        <title>Request Permissions from Wallets</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7715-grant-permissions-from-wallets/20100</comments>
        
        <description>## Abstract

We define a new JSON-RPC method `wallet_requestExecutionPermissions` for DApp to request a Wallet to grant permissions in order to execute transactions on the user’s behalf. This enables two use cases:

- Executing transactions for users without a wallet connection.
- Executing transactions for users with a wallet connection that is scoped with permissions.

## Motivation

Currently most DApps implement a flow similar to the following:

![Wallet Approve Flow](/EIPs/assets/eip-7715/approve-flow.svg)

Each interaction requires the user to sign a transaction with their wallet. The problems are:

- It can get tedious for the user to manually approve every transaction, especially in highly-interactive applications such as games.
- It’s impossible to send transactions for users without an active wallet connection. This invalidates use cases such as subscriptions, passive investments, limit orders, and more.

## Specification

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.

### Permission Types, Rule Types

This ERC does not specify an exhaustive list of rule or permission types, since we expect more rule and permission types to be developed as wallets get more advanced. A permission type, or rule type is valid as long as both the DApp and the wallet are willing to support it.

However, if two permissions or two rules share the same type name, a DApp could request with one type of permission, or rule while the wallet grants another. Therefore, it’s important that no two permissions, or two rules share the same type. Furthermore, new permission types or rule types should be specified in addition ERCs. In all cases, these new types MUST inherit from the `BasePermission` or `BaseRule` scheme.

#### Permissions

`isAdjustmentAllowed` defines a boolean value that allows DApp to define whether the Wallet MAY attenuate(reduce or increase) the authority of a &quot;permission&quot; to meet the user’s terms for approval.

_For example, a DApp may require an allowance for a specific asset to complete a payment and does not want the user to adjust the requested allowance._

```tsx
type BasePermission = {
  type: string; // enum defined by ERCs
  isAdjustmentAllowed: boolean; // whether the wallet MAY attenuate the permission
  data: Record&lt;string, any&gt;; // specific to the type, structure defined by ERCs
};
```

#### Rules

```tsx
type BaseRule = {
  type: string; // enum defined by ERCs
  data: Record&lt;string, any&gt;; // specific to the type, structure defined by ERCs
};

// Constrains a permission so that it is only valid until a specified timestamp.
type ExpiryRule = BaseRule &amp; {
  type: &quot;expiry&quot;;
  data: {
    timestamp: number; // unix timestamp at which the permission becomes invalid
  };
};
```

### `wallet_requestExecutionPermissions`

We introduce a `wallet_requestExecutionPermissions` method for the DApp to request the Wallet to grant permissions.

#### Request Specification

```tsx
type PermissionRequest = {
  chainId: Hex; // hex-encoding of uint256
  from?: Address;
  to: Address;
  permission: {
    type: string; // enum defined by ERCs
    isAdjustmentAllowed: boolean; // whether the permission can be adjusted
    data: Record&lt;string, any&gt;; //specific to the type, structure defined by ERCs
  };
  rules?: {
    type: string; // enum defined by ERCs
    data: Record&lt;string, any&gt;; // specific to the type, structure defined by ERCs
  }[];
}[];
```

`chainId` defines the chain with [EIP-155](/EIPs/EIPS/eip-155) which applies to this permission request and all addresses can be found defined by other parameters.

`from` identifies the account being targeted for this permission request which is useful when a connection has been established and multiple accounts have been exposed. It is optional to let the user choose which account to grant permission for.

`to` is a field that identifies the DApp session account associated with the permission

`permission` defines the allowed behavior the `to` account can do on behalf of the `from` account. See the “Permission” section for details.

`rules` define the restrictions or conditions that a `to` account MUST abide by when using a permission to act on behalf of an account. See the “Rule” section for details.

**Request example**:

An array of `PermissionRequest` objects is the final `params` field expected by the `wallet_requestExecutionPermissions` RPC.

```tsx
[
  {
    chainId: &quot;0x01&quot;,
    from: &quot;0x...&quot;,
    to: &quot;0x016562aA41A8697720ce0943F003141f5dEAe006&quot;,
    permission: {
      type: &quot;native-token-allowance&quot;,
      isAdjustmentAllowed: false,
      data: {
        allowance: &quot;0x1DCD6500&quot;,
      },
    },
    rules: [
      {
        type: &quot;expiry&quot;,
        data: {
          timestamp: 1577840461,
        },
      },
    ],
  },
];
```

#### Response Specification

```tsx
type PermissionResponse = PermissionRequest &amp; {
  context: Hex;
  dependencies: {
    factory: `0x${string}`;
    factoryData: `0x${string}`;
  }[];
  delegationManager: `0x${string}`;
};
```

First note that the response contains all of the parameters of the original request and it is not guaranteed that the values received are equivalent to those requested.

`context` is a catch-all to identify a permission for revoking permissions or redeeming permissions, and can contain non-identifying data as well. The `context` is required as defined in [ERC-7710](/EIPs/EIPS/eip-7710). See “Rationale” for details.

`dependencies` is an array of objects, each containing fields for `factory` and `factoryData` as defined in [ERC-4337](/EIPs/EIPS/eip-4337). Either both `factory` and `factoryData` must be specified in an entry, or neither. This array is used describe accounts that are not yet deployed but MUST be deployed in order for a permission to be successfully redeemed. If any of the involved accounts have not yet been deployed, the wallet MUST return the corresponding `dependencies`. If all accounts have already been deployed, the wallet MUST return an empty `dependencies` array. The DApp MUST deploy each account by calling the `factory` contract with `factoryData` as the calldata.

`delegationManager` is required as defined in [ERC-7710](/EIPs/EIPS/eip-7710).

If the request is malformed or the wallet is unable/unwilling to grant permissions, wallet MUST return an error with a code as defined in [ERC-1193](/EIPs/EIPS/eip-1193).

`wallet_requestExecutionPermissions` response example:

An array of `PermissionResponse` objects is the final `result` field expected by the `wallet_requestExecutionPermissions` RPC.

```tsx
[
  {
    // original request with modifications
    chainId: &quot;0x01&quot;,
    from: &quot;0x...&quot;,
    to: &quot;0x016562aA41A8697720ce0943F003141f5dEAe006&quot;,
    permission: {
      type: &quot;native-token-allowance&quot;,
      isAdjustmentAllowed: true,
      data: {
        allowance: &quot;0x1DCD65000000&quot;,
      },
    },
    // response-specific fields
    context: &quot;0x0x016562aA41A8697720ce0943F003141f5dEAe0060000771577157715&quot;,
    dependencies: [
      {
        factory: &quot;0x...&quot;,
        factoryData: &quot;0x...&quot;,
      },
    ],
    delegationManager: &quot;0x...&quot;,
  },
];
```

### `wallet_revokeExecutionPermission`

Permissions can be revoked by calling this method and the wallet will respond with an empty response when successful.

#### Request Specification

```tsx
type RevokeExecutionPermissionRequestParams = {
  permissionContext: &quot;0x{string}&quot;;
};
```

#### Response Specification

```tsx
type GetPermissionsInfoResultParams = {
  chainIds: `0x${string}`[];
};
```

### `wallet_getSupportedExecutionPermissions`

We introduce a `wallet_getSupportedExecutionPermissions` method for the Wallet to specify the permission types and rules types it supports.

#### Request Specification

**Request example**:

```tsx
window.ethereum.request({
  &quot;method&quot;: &quot;wallet_getSupportedExecutionPermissions&quot;,
  &quot;params&quot;: []
}): Promise&lt;GetSupportedExecutionPermissionsResult&gt;
```

#### Response Specification

The wallet SHOULD include an object keyed on supported permission types including `ruleTypes` (`string[]`) that can be applied to the permission.

```tsx
type GetSupportedExecutionPermissionsResult = Record&lt;
  &quot;permission-type&quot;,
  {
    chainIds: `0x${string}`[];
    ruleTypes: string[];
  }
&gt;; // Hex chain id
```

An object keyed on all permission types supported by the Wallet expected by the `wallet_getSupportedExecutionPermissions` RPC.

```json
{
  &quot;native-token-allowance&quot;: {
    &quot;chainIds&quot;: [&quot;0x123&quot;, &quot;0x345&quot;],
    &quot;rulesTypes&quot;: [&quot;expiry&quot;]
  },
  &quot;erc20-token-allowance&quot;: {
    &quot;chainIds&quot;: [&quot;0x123&quot;],
    &quot;rulesTypes&quot;: []
  },
  &quot;erc721-token-allowance&quot;: {
    &quot;chainIds&quot;: [&quot;0x123&quot;],
    &quot;rulesTypes&quot;: [&quot;expiry&quot;]
  }
}
```

### `wallet_getGrantedExecutionPermissions`

We introduce a `wallet_getGrantedExecutionPermissions` method for the DApp to retrieve previously granted permissions.

#### Request Specification

**Request example**:

```tsx
window.ethereum.request({
  &quot;method&quot;: &quot;wallet_getGrantedExecutionPermissions&quot;,
  &quot;params&quot;: []
}): Promise&lt;PermissionResponses[]&gt;
```

#### Response Specification

The wallet MUST include all granted permissions that are not yet revoked.

```tsx
type PermissionResponses;
```

Example:

```tsx
[
  {
    chainId: &quot;0x01&quot;,
    from: &quot;0x...&quot;,
    to: &quot;0x016562aA41A8697720ce0943F003141f5dEAe006&quot;,
    permission: {
      type: &quot;native-token-allowance&quot;,
      isAdjustmentAllowed: true,
      data: {
        allowance: &quot;0x1DCD65000000&quot;,
      },
    },
    context: &quot;0x0x016562aA41A8697720ce0943F003141f5dEAe0060000771577157715&quot;,
    dependencies: [
      {
        factory: &quot;0x...&quot;,
        factoryData: &quot;0x...&quot;,
      },
    ],
    delegationManager: &quot;0x...&quot;,
  },
];
```

### Sending transaction to redeem permissions

The permission response data will be redeemable by the `account` defined in the `to` field, using the interfaces specified in ERC-7710. This allows the recipient of the permissions to use any account type (EOA or contract) to form a transaction or UserOp using whatever payment or relay infrastructure they prefer, by sending an internal message to the returned `permissions.delegationManager` and calling its `function redeemDelegation(bytes[] calldata _permissionContexts, bytes32[] calldata _modes, bytes[] calldata _executionCallData) external;` function with the `_permissionContexts` parameter set to the returned `permissions.context`, and the `_executionCallData` data forming the message that the permissions recipient desires the user&apos;s account to emit, as defined by this struct:

```
struct Execution {
  address target;
  uint256 value;
  bytes callData;
}
```

A simple pseudocode example of using a permission in this way, where DApp wants to request a permission from `bob` might be like this:

```typescript
// Alice requests a permission from Bob
const permissionsResponse = await window.ethereum.request({
  method: &apos;wallet_requestExecutionPermissions&apos;,
  params: [{
    from: bob.address,
    chainId: &quot;0x01&quot;,
    to: &apos;0x_dapp_session_account&apos;,
    permission: {
      type: &apos;native-token-allowance&apos;,
      isAdjustmentAllowed: true,
      data: {
        allowance: &apos;0x0DE0B6B3A7640000&apos;
      },
    },
    rules: [
      {
        type: &apos;expiry&apos;;
        data: {
          timestamp: Math.floor(Date.now() / 1000) + 3600 // 1 hour from now
        },
      },
    ],
  }]
});

// Extract the permissionsContext and delegationManager
const permissionsContext = permissionsResponse.context;
const delegationManager = permissionsResponse.delegationManager;

// DApp forms the execution they want Bob&apos;s account to take
const execution = {
  target: bob.address,
  value: &apos;0x06F05B59D3B20000&apos;,
  callData: &apos;0x&apos;
};
const encodedExecutionCalldata = encodePacked(
  [&apos;address&apos;, &apos;uint256&apos;, &apos;bytes&apos;],
  [execution.target, execution.value, execution.callData],
);

// Chose execution mode (SingleDefault)
const executionMode = &apos;0x0000000000000000000000000000000000000000000000000000000000000000&apos;;

// DApp sends the transaction by calling redeemDelegation on with encode execution on Bob&apos;s account
const tx = await dapp.sendTransaction({
  to: delegationManager,
  data: encodeFunctionData({
    abi: DelegationManager.abi,
    functionName: &apos;redeemDelegations&apos;,
    args: [
      [permissionsContext],
      [executionMode],
      [encodedExecutionCalldata],
    ],
  })
});

```

**Example of the entire flow:**

```mermaid
sequenceDiagram
  participant DApp
  participant Provider as window.ethereum
  participant Wallet
  participant User
  participant Chain as Relay infrastructure


  Note over DApp: DApp discovers supported permission and rules types

  DApp-&gt;&gt;Provider: request({method: &quot;wallet_getSupportedExecutionPermissions&quot;, params: []})
  Provider-&gt;&gt;Wallet: wallet_getSupportedExecutionPermissions

  Wallet-&gt;&gt;DApp: Returns supported permission and rules types

  Note over DApp: DApp triggers permissions request

  DApp-&gt;&gt;Provider: request({method: &quot;wallet_requestExecutionPermissions&quot;, params: [ PermissionRequest[] ]})
  Provider-&gt;&gt;Wallet: wallet_requestExecutionPermissions

  Wallet-&gt;&gt;User: Display permission request&lt;br/&gt; (permissions, rules, to = account)
  User--&gt;&gt;Wallet: Approve or reject

  Wallet--&gt;&gt;Provider: PermissionResponse[]&lt;br/&gt;includes context,&lt;br/&gt;delegationManager,&lt;br/&gt;dependencies
  Provider--&gt;&gt;DApp: PermissionResponse[]

  alt Undeployed user account(s)
      DApp-&gt;&gt;Chain: Deploy via factory using dependencies
      Chain--&gt;&gt;DApp: Deployment success
  end

  Note over DApp: DApp forms Action calldata&lt;br/&gt;to be executed by user&apos;s account

  DApp-&gt;&gt;Chain: sendTransaction({&lt;br/&gt; to: delegationManager,&lt;br/&gt; data: redeemDelegations([context], [executionMode], [encodedAction])&lt;br/&gt;})

  Chain--&gt;&gt;DApp: tx receipt
```

## Rationale

The typical transaction flow of `suggesting transactions =&gt; approving transactions =&gt; sending transactions` is deeply limiting in several ways:

- Users must be online to send transactions. DApps cannot send transactions for users when they are offline, which makes use cases such as subscriptions or automated trading impossible.

- Users must manually approve every transaction, interrupting what could otherwise be a smooth user experience.

With this ERC, DApps can request Wallets to grant permissions and execute transactions on the user&apos;s behalf, therefore circumventing the issues above.

### `permissionsContext`

Since this ERC only specifies the interaction between the wallet and the DApp but not how the wallet enforces permissions, we need a flexible way for the wallet to pass along information to the DApp so that it can construct transactions that imbue the permissions.

The `permissionsContext` field is meant to be an opaque string that&apos;s maximally flexible and can encode arbitrary information for different permissions schemes.

DApps must submit transactions with the `account` specified in the `to` field, using the `permissionsContext` as the `_data` when interacting with the delegation manager.

### Non-exhaustive list of permissions and rules

With the advancement in wallet technologies, we expect new types of permissions and rules to be developed. We considered mandating that each permission and rule must have a UUID in order to avoid collisions, but ultimately decided to stick with the simpler approach for now of simply mandating that these types be defined in ERCs.

## **Backwards Compatibility**

Wallets that don’t support `wallet_requestExecutionPermissions` SHOULD return an error message if the JSON-RPC method is called.

## **Reference Implementation**

For a minimal reference implementation focusing on permission granting from a [EIP-1193](/EIPs/EIPS/eip-1193) Ethereum provider, please see [Example7715PermissionsRequestHandler](/EIPs/assets/eip-7715/Example7715PermissionsRequestHandler.html).

For a complete reference implementation of a Permissions handler, see the MetaMask Permissions Snap, which includes features such as:

- Support for commonly used permission and rule types with ability to attenuate(reduce or increase) the requested capability to meet the user’s terms for approval.
- User encrypted storage for all permissions granted through the Wallet handler to enable revocation mechanisms.

## **Security Considerations**

### **Limited Permission Scope**

DApps should only request the permissions they need, with a reasonable expiration time.

Wallets MUST correctly enforce permissions. Ultimately, users must trust that their wallet software is implemented correctly, and permissions should be considered a part of the wallet implementation.

### **Phishing Attacks**

Malicious DApps could pose as legitimate applications and trick users into granting broad permissions. Wallets MUST clearly display the permissions to users and warn them against granting dangerous permissions.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 24 May 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7715</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7715</guid>
      </item>
    
      <item>
        <title>Anti-correlation attestation penalties</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7716-anti-correlation-attestation-penalties/20137</comments>
        
        <description>## Abstract

The decentralization of the validator set is one of the most important properties of Ethereum for credible neutrality and censorship resistance. By adjusting penalties to foster decentralization, diversification and fault-tolerance, this EIP proposes to adjust penalties in a way that more diversified entities get lower penalties while entities with high correlations in their setup face more severe ones.


## Motivation

As of now, during times of usual network operation, there are no economic incentives to diversify node operations through using multiple different nodes, geographical locations, clients, ISP providers, etc., except for reducing the risk of penalties affecting all validators simultaneously, thereby limiting the impact to only a fraction of them. 

Attestation penalties are currently agnostic to other participation actions. This proposal scales attestation penalties as a function of other participants&apos; actions. The goal is to decrease the profitability of participants that exhibit correlated behavior.



## Specification

| Parameter | Value |
| - | - |
| `PENALTY_ADJUSTMENT_FACTOR`    |  `4096` |
| `MAX_PENALTY_FACTOR`    |  `4` |


Add a variable `NET_EXCESS_PENALTIES` to the beacon state.

Let `penalty_factor` be determined through 

```
min(
    (non_attesting_balance * PENALTY_ADJUSTMENT_FACTOR) // (NET_EXCESS_PENALTIES * total_active_balance + 1), 
    MAX_PENALTY_FACTOR
)
```

Let `NET_EXCESS_PENALTIES` be `max(1, NET_EXCESS_PENALTIES + penalty_factor) - 1`



## Rationale

### PENALTY_ADJUSTMENT_FACTOR

This variable impacts the sensitivity of the `NET_EXCESS_PENALTIES`.

Given stable participation, the `penalty_factor` is one.
If participation decreases, the `penalty_factor` will temporarily increase above one until `net_excess_penalties` catches up.
If participation increases, the `penalty_factor` will temporarily be zero until `net_excess_penalties` catches up.

The `PENALTY_ADJUSTMENT_FACTOR` regulates how fast `net_excess_penalties` catches up.
In other words, the `PENALTY_ADJUSTMENT_FACTOR` determines the frequency that the penalty_factor is not one.

A high `PENALTY_ADJUSTMENT_FACTOR` causes the `net_excess_penalties` to adjust slower.
A low `PENALTY_ADJUSTMENT_FACTOR` causes the `net_excess_penalties` to react more sensitively to changes in participation.


### `MAX_PENALTY_FACTOR`

The `MAX_PENALTY_FACTOR` puts a ceiling onto the maximum factor with which the penalty for missed attestations is scaled to prevent overly harsh punishments.


## Backwards Compatibility

This is a backwards incompatible adjustment of attestations rewards and penalties that requires a scheduled network upgrade.


## Security Considerations

We acknowledge that splitting validator views can be leveraged as an attack to increase the `penalty_factor` for validators of consecutive slots with little risk for the proposer. 
TBD.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Sat, 25 May 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7716</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7716</guid>
      </item>
    
      <item>
        <title>Deferred Token Transfer</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7720-deferred-token-transfer/20245</comments>
        
        <description>## Abstract

This standard specifies that allows users to deposit [ERC-20](/EIPs/EIPS/eip-20) tokens for a beneficiary. The beneficiary can withdraw the tokens only after a specified future timestamp. Each deposit transaction is assigned a unique ID and includes details such as the token address, sender, recipient, amount, unlock time, and withdrawal status.

## Motivation

In various scenarios, such as vesting schedules, escrow services, or timed rewards, there is a need for deferred payments. This contract provides a secure and reliable mechanism for time-locked token transfers, ensuring that tokens can only be transferred after a specified timestamp is reached. By facilitating structured and delayed payments, it adds an extra layer of security and predictability to token transfers. This is particularly useful for scenarios where payments are contingent upon the passage of time.

## Specification

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

Implementers of this standard **MUST** have all of the following functions:

```solidity
pragma solidity ^0.8.0;

interface ITokenTransfer {
    // Event emitted when a transfer is initiated.
    event Transfer(
        uint256 txnId,
        address indexed token,
        address indexed from,
        address indexed to,
        uint256 amount,
        uint40 unlockTime,
        bytes32 referenceNo
    );

    // Event emitted when tokens are withdrawn.
    event Withdraw(
        uint256 txnId,
        address indexed token,
        address indexed from,
        address indexed to,
        uint256 amount
    );

    // Function to initiate a token transfer.
    // Parameters:
    // - _token: Address of the ERC20 token contract.
    // - _from: Address of the sender.
    // - _to: Address of the recipient.
    // - _amount: Amount of tokens to be transferred.
    // - _unlockTime: Time after which the tokens can be withdrawn.
    // - _reference: Reference ID for the transaction.
    // Returns the transaction ID.
    function transferFrom(
        address _token,
        address _from,
        address _to,
        uint256 _amount,
        uint40 _unlockTime,
        bytes32 _reference
    ) external returns (uint256 txnId);

    // Function to withdraw tokens from a transaction.
    // Parameters:
    // - _txnId: ID of the transaction to withdraw from.
    function withdraw(uint256 _txnId) external;

    // Function to get transaction details.
    // Parameters:
    // - _txnId: ID of the transaction.
    // Returns the transaction details.
    function getTransaction(uint256 _txnId)
        external
        view
        returns (
            address token,
            address from,
            address to,
            uint256 amount,
            uint40 unlockTime,
            bytes32 referenceNo,
            bool withdrawn
        );
}

```

## Rationale

The design of the Deferred Token Transfer contract aims to provide a straightforward and secure method for handling time-locked token transfers. The following considerations were made during its development:

**Unlock Time Precision with `uint40`**: We chose a full `uint40` for `_unlockTime` because it provides a sufficiently large range to cover all practical time-lock scenarios. This ensures that the contract can handle deferred payments that require precise timing over long periods, such as vesting schedules or long-term escrows.

**Returning `txnId` from `transferFrom`**: The `transferFrom` function returns a unique `txnId` for each transaction. This design choice was made to facilitate easy and independent tracking of each transaction. By having a unique ID, users can manage and reference specific transactions, ensuring clarity and preventing confusion. This approach allows each transaction&apos;s state to be managed independently, simplifying the withdrawal process.

**Compatibility with Existing ERC-20 Tokens**: The standard is designed as a separate interface rather than an extension of ERC-20 to ensure flexibility and broad compatibility. By not modifying the ERC-20 standard directly, this proposal can be used with any existing ERC-20 token without requiring changes to their contracts. This flexibility makes the standard applicable to a wide range of tokens already in circulation, enhancing its utility and adoption potential.

## Reference Implementation

```solidity
pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol&quot;;

contract TokenTransfer {
    using SafeERC20 for IERC20;

    struct Transaction {
        address token;      // Address of the ERC20 token contract.
        address from;       // Address of the sender.
        address to;         // Address of the recipient.
        uint256 amount;     // Amount of tokens to be transferred.
        uint40 unlockTime; // Time after which the tokens can be withdrawn.
        bytes32 referenceNo;  // Reference ID for the transaction.
        bool withdrawn;     // Flag indicating if the tokens have been withdrawn.
    }

    // Mapping from transaction ID to Transaction structure.
    mapping(uint256 =&gt; Transaction) public transactions;

    // Variable to keep track of the next transaction ID.
    uint256 public lastTxnId = 0;

    // Event emitted when a transfer is initiated.
    event Transfer(
        uint256 txnId,
        address indexed token,
        address indexed from,
        address indexed to,
        uint256 amount,
        uint40 unlockTime,
        bytes32 referenceNo
    );

    // Event emitted when tokens are withdrawn.
    event Withdraw(
        uint256 txnId,
        address indexed token,
        address indexed from,
        address indexed to,
        uint256 amount
    );

    constructor() {}

    // Function to initiate a token transfer.
    // Parameters:
    // - _token: Address of the ERC20 token contract.
    // - _from: Address of the sender.
    // - _to: Address of the recipient.
    // - _amount: Amount of tokens to be transferred.
    // - _unlockTime: Time after which the tokens can be withdrawn.
    // - _reference: Reference ID for the transaction.
    // Returns the transaction ID.
    function transferFrom(
        address _token,
        address _from,
        address _to,
        uint256 _amount,
        uint40 _unlockTime,
        bytes32 _reference
    ) external returns (uint256 txnId) {
        require(_amount &gt; 0, &quot;Invalid transfer amount&quot;);

        // Transfer tokens from sender to this contract.
        IERC20(_token).safeTransferFrom(_from, address(this), _amount);

        lastTxnId++;

        // Store the transaction details.
        transactions[lastTxnId] = Transaction({
            token: _token,
            from: _from,
            to: _to,
            amount: _amount,
            unlockTime: _unlockTime,
            referenceNo: _reference,
            withdrawn: false
        });

        // Emit an event for the transaction creation.
        emit Transfer(lastTxnId, _token, _from, _to, _amount, _unlockTime, _reference);
        return lastTxnId;
    }

    // Function to withdraw tokens from a transaction.
    // Parameters:
    // - _txnId: ID of the transaction to withdraw from.
    function withdraw(uint256 _txnId) external {
        Transaction storage transaction = transactions[_txnId];
        require(transaction.amount &gt; 0, &quot;Invalid transaction ID&quot;);
        require(block.timestamp &gt;= transaction.unlockTime, &quot;Current time is before unlock time&quot;);
        // require(transaction.to == msg.sender, &quot;Only the recipient can withdraw the tokens&quot;);
        require(!transaction.withdrawn, &quot;Tokens already withdrawn&quot;);

        IERC20(transaction.token).safeTransfer(transaction.to, transaction.amount);

        transaction.withdrawn = true;

        // Emit an event for the token withdrawal.
        emit Withdraw(_txnId, transaction.token, transaction.from, transaction.to, transaction.amount);
    }

    // Function to get transaction details.
    // Parameters:
    // - _txnId: ID of the transaction.
    // Returns the transaction details.
    function getTransaction(uint256 _txnId)
        external
        view
        returns (
            address token,
            address from,
            address to,
            uint256 amount,
            uint40 unlockTime,
            bytes32 referenceNo,
            bool withdrawn
        )
    {
        Transaction storage transaction = transactions[_txnId];
        require(transaction.amount &gt; 0, &quot;Invalid transaction ID&quot;);

        return (
            transaction.token,
            transaction.from,
            transaction.to,
            transaction.amount,
            transaction.unlockTime,
            transaction.referenceNo,
            transaction.withdrawn
        );
    }
}
```

## Security Considerations

**Ownerless Contract Design**: To prevent the risk of token loss after deposit, the contract should not have an owner. This ensures that the contract&apos;s token balance cannot be transferred to any address other than the designated beneficiary.

**Strict Beneficiary Control**: During withdrawal, the contract must strictly ensure that tokens are transferred only to the beneficiary specified at the time of deposit. This prevents unauthorized access and ensures that only the intended recipient can withdraw the tokens.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).</description>
        <pubDate>Sun, 09 Jun 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7720</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7720</guid>
      </item>
    
      <item>
        <title>Lockable Extension for ERC-1155</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7721-lockable-extension-for-erc1155/20250</comments>
        
        <description>## Abstract

The Lockable Extension for [ERC-1155](/EIPs/EIPS/eip-1155) introduces a robust locking mechanism for specific Non-Fungible Tokens (NFTs) within the ERC-1155 token standard, allowing for various uses while preventing sale or transfer. The token&apos;s `owner` can `lock` it, setting up locker address (either an EOA or a contract) that exclusively holds the power to unlock the token. Owner can also provide approval for `tokenId`, enabling ability to lock asset while address holds the token approval. Token can also be locked by `approved`, assigning locker to itself. Upon token transfer, these rights get purged. 

Inspired by the need for enhanced security and control over tokenized assets, this extension enables token owners to lock individual NFTs with `tokenId`, ensuring that only approved users can withdraw predetermined amounts of locked tokens. Thus, offering a safer approach by allowing token owners to specify approved token IDs and amounts for withdrawal.

## Motivation

[ERC-1155](/EIPs/EIPS/eip-1155) has sparked an unprecedented surge in demand for NFTs. However, despite this tremendous success, the NFT economy suffers from secondary liquidity where it remains illiquid in owner’s wallet. There are projects which aim to address the liquidity challenge, but they entail the below mentioned inconveniences and risks for owners as they necessitate transferring the participating NFTs to the projects&apos; contracts.

- Loss of utility: The utility value of NFTs diminishes when they are transferred to an escrow account, no longer remaining under the direct custody of the owners.
- Lack of composability: The market could benefit from increased liquidity if NFT owners had access to multiple financial tools, such as leveraging loans and renting out their assets for maximum returns. Composability serves as the missing piece in creating a more efficient market.
- Smart contract vulnerabilities: NFTs are susceptible to loss or theft due to potential bugs or vulnerabilities present in the smart contracts they rely on.

The aforementioned issues contribute to a poor user experience (UX), and we propose enhancing the [ERC-1155](/EIPs/EIPS/eip-1155) standard by implementing a native locking mechanism: 
Rather than being transferred to a smart contract, an NFT remains securely stored in self-custody but is locked. 
During the lock period, the NFT&apos;s transfer is restricted while its other properties remain unchanged. 
NFT Owner retains the ability to use or distribute it’s utility.

NFTs have numerous use cases where the NFT must remain within the owner&apos;s wallet, even when it serves as collateral for a loan. Whether it&apos;s authorizing access to a Discord server, or utilizing NFT within a play-to-earn (P2E) game, owner should have the freedom to do so throughout the lending period. Just as real estate owner can continue living in their mortgaged house, take personal loan or keep tenants to generate passive income, these functionalities should be available to NFT owners to bring more investors in NFT economy.


Lockable NFTs enable the following use cases :

- NFT-collateralized loans: Utilize NFT as collateral for a loan without locking it on the lending protocol contract. Instead, lock it within owner’s wallet while still enjoying all the utility of NFT.
- No collateral rentals of NFTs: Borrow an NFT for a fee without the need for significant collateral. Renter can use the NFT but not transfer it, ensuring the lender&apos;s safety. The borrowing service contract automatically returns the NFT to the lender once the borrowing period expires.
- Buy Now Pay Later (BNPL): The buyer receives the locked NFT and can immediately begin using it. However, they are unable to sell the NFT until all installments are paid. Failure to complete the full payment results in the NFT returning to the seller, along with a fee.
- Composability: Maximize liquidity by having access to multiple financial tools. Imagine taking a loan against NFT and putting it on rentals to generate passive income.
- Primary sales: Mint an NFT for a partial payment and settle the remaining amount once owner is satisfied with the collection&apos;s progress.
- Soulbound: Organization can mint and self-assign `locker`, send token to user and lock the asset.
- Safety: Safely and conveniently use exclusive blue chip NFTs. Lockable extension allows owner to lock NFT and designate secure cold wallet as the unlocker. This way, owner can keep NFT on MetaMask and easily use it, even if a hacker gains access to MetaMask account. Without access to the cold wallet, the hacker cannot transfer NFT, ensuring its safety.

This proposal is different from other locking proposals in number of ways: 

- This implementation provides a minimal implementation of `lock` and `unlock` and believes other conditions like time-bound are great ideas but can be achieved without creating a specific implementation. Locking and Unlocking can be based on any conditions (e.g. repayment, expiry). Therefore time-bound unlocks a relatively specific use case that can be achieved via smart-contracts themselves without that being a part of the token contract.
- This implementation proposes a separation of rights between locker and approver. Token can be locked with approval and approved can unlock and withdraw tokens (opening up opportunities like renting, lending, BNPL etc), and token can be locked lacking the rights to revoke token, yet can unlock if required (opening up opportunities like account-bound NFTs).
- Our proposal implement ability to `transferAndLock` which can be used to transfer, lock and optionally approve token. Enabling the possibility of revocation after transfer.

By extending the [ERC-1155](/EIPs/EIPS/eip-1155) standard, the proposed standard enables secure and convenient management of underlying NFT assets. It natively supports prevalent NFTFi use cases such as staking, lending, and renting. We anticipate that this proposed standard will foster increased engagement of NFT owners in NFTFi projects, thereby enhancing the overall vitality of the NFT ecosystem.

## Specification

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

### Overview

[ERC-1155](/EIPs/EIPS/eip-1155) compliant contracts MAY implement this EIP to provide standard methods of locking and unlocking the token at its current owner address. 

Token owner MAY `lock` the token and assign `locker` to some `address` using `lock(uint256 tokenId, address account, address _locker, uint256 amount)` function, this MUST set `locker` to `_locker`. Token owner or approved MAY `lock` the token using `lock(uint256 tokenId, address account, uint256 amount` function, this MUST set `locker` to `msg.sender`. Token MAY be `unlocked` by `locker` using `unlock(uint256 tokenId, address account, uint256 amount)` function. 

Token owner MAY `approve` specific for specific `tokenId` using `setApprovalForId(uint256 tokenId, address operator, uint256 amount)` ensuring only approved tokenId could be spent by operator. `getApprovalForId(uint256 tokenId, address account, address operator)` SHALL return `amount` approved on `account` by `operator`.

If the token is `locked`, the `getLocked(uint256 tokenId, address account, address operator)` function MUST return an amount that is `locked` by `operator` on `account`. For tokens that are not `locked`, the `getLocked(uint256 tokenId, address account, address operator)` function MUST return `0`.

`lock` function MUST revert if `account` has insufficient balance or not `owner` or `approved` of `tokenId`. `unlock` function MUST revert if provided `amount` of `tokenId` is not `locked`. ERC-1155 `safeTransferFrom` of a token MUST revert if `account` transfer `locked` amount, maximum transferable amount MUST be `balance - getLocked`. 

Token MAY be transferred and `locked`, also assign `approval` to `locker` using `transferAndLock` function. This is RECOMMENDED for use-cases where Token transfer and subsequent revocation is REQUIRED.

### Interface

```
// SPDX-License-Identifier: CC0-1.0

pragma solidity &gt;=0.7.0 &lt;0.9.0;

/// @title Lockable Extension for ERC1155
/// @dev Interface for the Lockable extension
/// @author piyush-chittara 

interface IERCLockable1155 is IERC1155{

    /**
     * @dev Emitted when tokenId is locked
     */
    event Lock(uint256 indexed tokenId, address account, address _locker, uint256 amount);

    /**
     * @dev Emitted when tokenId is unlocked
     */
    event Unlock (uint256 indexed tokenId, address account, address _locker, uint256 amount);

    /**
     * @dev Lock the tokenId if msg.sender is owner or approved and set locker to msg.sender
     */
    function lock(uint256 tokenId, address account, uint256 amount) external;

    /**
     * @dev Lock the tokenId if msg.sender is owner and set locker to _locker
     */
    function lock(uint256 tokenId, address account, address _locker, uint256 amount) external;

    /**
     * @dev Unlocks the tokenId if msg.sender is locker
     */
    function unlock(uint256 tokenId, address account, uint256 amount) external;

    /**
     * @dev Tranfer and lock the token if the msg.sender is owner or approved. 
     *      Lock the token and set locker to caller
     *      Optionally approve caller if bool setApprove flag is true
     */
    function transferAndLock(address from, address to, uint256 tokenId, uint256 amount, bool setApprove) external;

    /**
     * @dev Returns the wallet, that is stated as unlocking wallet for the tokenId.
     *      If (0) returned, that means token is not locked. Any other result means token is locked.
     */
    function getLocked(uint256 tokenId, address account, address operator) external view returns (uint256);

    function setApprovalForId(uint256 tokenId, address operator, uint256 amount) external;
}
```

## Rationale

This proposal exposes `transferAndLock(address from, address to, uint256 tokenId, uint256 amount, bool setApprove)` which can be used to transfer token and lock at the receiver&apos;s address. This additionally accepts input `bool setApprove` which on `true` assign `approval` to `locker`, hence enabling `locker` to revoke the token (revocation conditions can be defined in contracts and `approval` provided to contract). This provides conditional ownership to receiver, without the privilege to `transfer` token.

## Backwards Compatibility

This standard is compatible with [ERC-1155](/EIPs/EIPS/eip-1155) standards.

Existing Upgradeable [ERC-1155](/EIPs/EIPS/eip-1155) can upgrade to this standard, enabling locking capability inherently and unlock underlying liquidity features.

## Test Cases

## Reference Implementation

Reference Interface can be found [here](/EIPs/assets/eip-7721/IERC7721.sol).

Reference Implementation can be found [here](/EIPs/assets/eip-7721/ERC7721.sol).

## Security Considerations

There are no security considerations related directly to the implementation of this standard for the contract that manages [ERC-1155](/EIPs/EIPS/eip-1155).

### Considerations for the contracts that work with lockable tokens

- Once a certain `amount` is `locked`, specified `amount` can not be transferred from locked `account`.
- If token is `locked` and caller is `locker` and `approved` both, caller can transfer the token.
- `locked` token with `locker` as in-accesible account or un-verified contract address can lead to permanent lock of the token.
- There are no MEV considerations regarding lockable tokens as only authorized parties are allowed to lock and unlock.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 25 May 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7721</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7721</guid>
      </item>
    
      <item>
        <title>Opaque Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7722-opaque-token/20249</comments>
        
        <description>## Abstract

This ERC proposes a specification for an opaque token that enhances privacy by concealing balance information. Privacy is achieved by representing balances as off-chain data encapsulated in hashes, referred to as &quot;baskets&quot;. These baskets can be reorganized, transferred, and managed through token functions on-chain.

## Motivation

Smart contract accounts serve as well-defined identities that can have reusable claims and attestations attached to them, making them highly useful for various applications. However, this strength also introduces a significant privacy challenge when these identities are used to hold tokens. Specifically, in the case of [ERC-20](./eip-20.html) compatible tokens, where balances are stored directly on-chain in plain text, the transparency of these balances can compromise the privacy of the account holder. This creates a dilemma: while the reuse of claims and attestations tied to a smart contract account can be advantageous, it also increases the risk of exposing sensitive financial information, particularly when these well-defined identities are associated with publicly visible token holdings.

This proposal aims to conceal balances on-chain, allowing the use of smart contract accounts to hold tokens without compromising privacy or integrity.

## Specification

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

The concept revolves around representing token balances on-chain as hashed values, called baskets, which obscure the actual balance information. These baskets combine a random salt, a unique token ID, and the token&apos;s value, making it impossible to derive the token&apos;s value directly from the blockchain.

The token interface allows for creating, transferring, issuing, and reorganizing (splitting and joining) these baskets. To prevent unauthorized changes and maintain integrity, oracle services verify that the total value of baskets remains consistent during reorganizations. Additionally, differential privacy techniques, such as overlaying noise and empty transfers, further protect privacy by making it difficult to trace token movements and determine actual transaction details.

### Baskets

Balances are represented on-chain as hashes of the form:

```
keccak256(abi.encode(salt, tokenId, value))

// where  salt (bytes32)    - random 32bytes to increase the entropy and
//                            make brute-forcing the hash impossible
//        tokenId (bytes32) - a unique tokenId within token&apos;s smart contract instance
//        value (uint256)   - the value of the position
```

For the remainder of this document, we refer to these hashes as &quot;baskets&quot; because they conceal the balance information in an opaque manner, similar to how a covered basket hides its contents.

### Token Interface

An opaque token MUST implement the following interface.

```
interface OpaqueToken {
  //
  // TYPES
  //

  struct SIGNATURE {
    uint8 v; bytes32 r; bytes32 s;
  }

  struct ORACLECONFIG {
    uint8 minNumberOfOracles; // min. number of oracle signatures required for reorg
    address[] oracles;        // valid oracles
  }

  //
  // EVENTS
  //

  /**
   * @dev MUST be emitted when new token is created
   * @param initiatedBy address that created and controls the token
   * @param tokenId identifier of the token
   * @param totalSupplyBasket initial supply basket, containing total supply of tokens
   * @param ref custom reference as used by initiator
   */
  event CreateToken(address initiatedBy, bytes32 tokenId, bytes32 totalSupplyBasket, bytes32 ref);

  /**
   * @dev MUST be emitted on issuance
   * @param initiatedBy address that initiated issuance
   * @param baskets baskets that were issued to the receiver
   * @param receiver address that received baskets
   * @param ref custom reference as used by initiator
   */
  event Issue(address initiatedBy, bytes32[] baskets, address receiver, bytes32 ref);

  /**
   * @dev MUST be emitted when holder baskets are restructured
   * @param initiatedBy address that initiated reorg and owner of all baskets
   * @param basketsIn baskets that are restructured and no longer exist
   * @param basketsOut baskets that are newly created
   * @param ref custom reference as used by initiator
   */
  event ReorgHolderBaskets(address initiatedBy, bytes32[] basketsIn, bytes32[] basketsOut, bytes32 ref);

  /**
   * @dev MUST be emitted when supply baskets are restructured
   * @param initiatedBy address that initiated reorg
   * @param basketsIn supply baskets that are restructured and no longer exist
   * @param basketsOut supply baskets that are newly created
   * @param ref custom reference as used by initiator
   */
  event ReorgSupplyBaskets(address initiatedBy, bytes32[] basketsIn, bytes32[] basketsOut, bytes32 ref);

  /**
   * @dev MUST be emitted when baskets are transferred from one address to another
   * @param initiatedBy address that initiated the transfer
   * @param receiver address that is the new owner of baskets
   * @param baskets baskets that were transferred
   * @param ref custom reference as used by initiator
   */
  event Transfer(address initiatedBy, address receiver, bytes32[] baskets, bytes32 ref);

  /**
   * @dev MUST be emitted on redeem
   * @param initiatedBy address that initiated redeem
   * @param baskets baskets that were redeemed
   * @param ref custom reference as used by initiator
   */
  event Redeem(address initiatedBy, bytes32[] baskets, bytes32 ref);

  //
  // FUNCTIONS
  //

  /**
   * @dev returns the configuration for this token
   */
  function oracleConfig() external view returns (ORACLECONFIG memory);

  /**
   * @dev returns the address of the basket owner
   */
  function owner(bytes32 basket) external view returns (address);

  /**
   * @dev returns the total supply for a `tokenId``
   * All token investors are allowed to fetch this value from the token operator&apos;s off-chain storage.
   */
  function totalSupply(bytes32 tokenId) external view returns (bytes32);

  /**
   * @dev returns the operator of this token, who is also responsible for providing the main
   * off-chain storage source.
   */
  function operator() external view returns (address);
  
  /**
   * @dev Allows the token operator to create a new token with the specified `tokenId` and an initial 
   * `totalSupplyBasket`. The `totalSupplyBasket` can be partitioned using {reorgSupplyBaskets} as needed 
   * when calling {issue}. The `ref` parameter can be used freely by the caller for any reference purpose.
   */
  function createToken(
      bytes32 tokenId,
      bytes32 totalSupplyBasket,
      bytes32 ref
  ) external;

  /**
   * @dev Allows the token operator to issue tokens by assigning `supplyBaskets` to a `receiver` which 
   * becomes the owner of these baskets. 
   */
  function issue(
      bytes32[] calldata supplyBaskets,
      address receiver,
      bytes32 ref
  ) external;
  
  /**
   * @dev transfers `baskets` to a `receiver` who becomes the new owner of these baskets. 
   */
  function transfer(
      bytes32[] calldata baskets,
      address receiver,
      bytes32 ref
  ) external;

  /**
   * @dev reorganizes a set of holder baskets (`basketsIn`) to a new set (`basketsOut`) having
   * the same value, i.e., the sum of all values from input baskets equals the sum of values
   * in output baskets. In order to ensure the integrity, external oracle service is required that
   * will sign the reorg proposal requested by the basket owner, which is passed as `reorgOracleSignatures`.
   * The minimum number of oracle signatures is defined in the oracle configuration.
   */
  function reorgHolderBaskets(
      SIGNATURE[] calldata reorgOracleSignatures,
      bytes32[] calldata basketsIn,
      bytes32[] calldata basketsOut,
      bytes32 ref
  ) external;

  /**
   * @dev same as {reorgHolderBaskets}, but for the available supply baskets.
   */
  function reorgSupplyBaskets(
      SIGNATURE[] calldata reorgOracleSignatures,
      bytes32[] calldata basketsIn,
      bytes32[] calldata basketsOut,
      bytes32 ref
  ) external;

  /**
   * @dev redeems holder&apos;s `baskets` and returns them to available supply
   */
  function redeem(
      bytes32[] calldata baskets,
      bytes32 ref
  ) external;

}
```

### User Roles

There are two roles in Opaque Token:
* Token Operator: One who creates a token and issues positions in it, and controls it&apos;s non-circulating supply (held in supply baskets). Will use createToken, reorgSupplyBasket and issue functions. Also has ability to force actions through forceTransfer and forceReorg functions.
* Token User: address that holds circulating tokens (held in owned baskets). Will use reorgSupplyBaskets, transfer and redeem functions.

### Off-chain Data Endpoints

* The operator of the token (e.g., issuer or registrar) MUST provide the off-chain storage that implements the `GET basket` and `PUT basket` REST endpoints as described in this section.
* The operator MUST ensure the availability of the basket data and will share it on need-to-know basis with all eligible holders, i.e., with all address that either were holding the basket in the past or are currently the holder of the basket. 
* To ensure data is only shared with and can be written by eligible holders, the operator MUST implement authentication for both endpoints. The concrete authentication schema is not specified here and my depend on the environment of the token operator.
* The operator MUST allow an existing token holder to `PUT basket`
* The operator MUST allow the current or historical basket holder to `GET basket`
* Token holders SHOULD store a copy of the data about their own baskets in their own off-chain storage for the case that operator&apos;s service is unavailable.

REST API Endpoints for creating and querying baskets:

```
  Endpoint: PUT baskets
  Description: will store baskets if the `basket` hash is matching `data`.
  PostData: 
  [
    {
      basket: keccak256(abi.encode(salt, tokenId, value)),
      data: {
        salt: &lt;bytes32&gt;,
        tokenId: &lt;bytes32&gt;,
        value: &lt;uint256&gt;
      }
    },
    ...
  ]

  Endpoint: GET baskets?basket-hash=&lt;bytes32&gt;
  Description: will return the list of baskets depending on the query parameters.
  Query Parameters:
    - basket-hash (optional): returns one basket matching the requested hash
    - if no query parameter is set, then the endpoint will return all baskets of the requestor
  Response:
  [
    {
      basket: keccak256(abi.encode(salt, tokenId, value)),
      data: {
        salt: &lt;bytes32&gt;,
        tokenId: &lt;bytes32&gt;,
        value: &lt;uint256&gt;
      }
    },
    ...
  ]
```

### reorg Endpoint

To ensure the integrity of a reorg and avoid accidental or fraudulent issues or redeems, an oracle services is required. 

* Oracles MUST provide a `POST reorg` REST Endpoint as described in this section
* Oracles MUST sign any reorg proposal request where
    * the sum of values in input baskets grouped by tokenId is equal the sum of values of the output baskets grouped by tokenId.
    * `item.basket` hash matches `keccak256(abi.encode(data.salt, data.tokenId, data.value))`
* The reorg endpoint MUST be stateless
* Oracle MUST NOT persist data from the request for later analysis.
* The reorg endpoint SHOULD NOT require authentication and can be used by anyone without restrictions.

```
Endpoint: POST reorg
PostData:
{
  in: [
    {
      basket: keccak256(abi.encode(salt, tokenId, value)),
      data: {
        salt: &lt;bytes32&gt;,
        tokenId: &lt;bytes32&gt;,
        value: &lt;uint256&gt;
      }
    },
    ...
  ],
  out: [
    {
      basket: keccak256(abi.encode(salt, tokenId, value)),
      data: {
        salt: &lt;bytes32&gt;,
        tokenId: &lt;bytes32&gt;,
        value: &lt;uint256&gt;
      }
    },
    ...
  ]
}

Response: {
    // hash is signed with oracles private key
    // basketsIn and basketsIn are bytes32[]
    signature: sign(keccak256(abi.encode(basketsIn, basketsOut)))
}
```

Example for valid reorg requests (salt and hashes are omitted for better readability):

```
in : (..., token1, 10), (..., token1, 30), (..., token2, 5), (..., token2, 95)
out: (..., token1, 40), (..., token2, 100)

in : (..., token1, 40), (..., token2, 100)
out: (..., token1, 10), (..., token1, 30), (..., token2, 5), (..., token2, 95)
```

### Overlaying Noise (Differential Privacy)

To further enhance privacy and obscure transaction details, an additional layer of noise need to be introduced through reorgs and empty transfers. For example, received baskets can be reorganized into new baskets to prevent information leakage to the previous owner. Additionally, null-value baskets can be sent to random receivers (empty transfers), making it difficult for observers to determine who is transferring to whom.

Example with reorg and null-value basket transfers:
```
A owns basket-a1{..., value:10}
B owns basket-b1{..., value:5}, basket-b2{..., value:15}, ...
A: transfer basket-a1 to B
B: reorg [basket-a1, basket-b1, basket-b2]
      to [basket-b3{..., value:10}, basket-b4{..., value:10}, basket-b5:{..., value:10},
            basket-b6:{..., value:0}, basket-b7:{..., value:0}]
      where sum of inputs is the sum of outputs
B: transfer basket-b5{value:10} to C
B: transfer basket-b6{value:0}  to D
B: transfer basket-b7{value:0}  to E
```

If B would directly send basket-a1 to C, A would know what C is receiving, however, now that B has reorg&apos;ed the baskets, A can not know anymore what has been sent to C.

Moreover, observers still see who is communicating with whom, but since there is noise introduced, they can not tell which of these transfers are actually transferring real values.

## Rationale

### Breaking the ERC-20 Compatibility

The transparency inherent in ERC-20 tokens presents a significant issue for reusable blockchain identities. To address this, we prioritize privacy over ERC-20 compatibility, ensuring the confidentiality of token balances.

### Reorg Oracles

The trusted oracles and the minimum number of required signatures can be configured to achieve the desired level of decentralization.

The basket holder proposes the input and output baskets for the reorg, while the oracles are responsible for verifying that the sums of the values on both sides (input and output) are equal. This system allows for mutual control, ensuring that no single party can manipulate the process.

Fraudulent oracles can be tracked back on-chain, i.e., the system ensures weak-integrity at minimum.

To further strengthen the integrity, it would also be possible to apply Zero-Knowledge Proofs (ZKP) to provide reorg proofs, however, we have chosen to use oracles for efficiency and simplicity reasons.

### Off-chain Data Storage

We have chosen the token operator, which in most cases will be the issuer or registrar, as the initial and main source for off-chain data. This is acceptable, since they must know anyway which investor holds which positions to manage lifecycle events on the token. While this approach may not be suitable for every use case within the broader Ethereum ecosystem, it fits well the financial instruments in the regulated environment of the financial industry, which rely on strict KYC and token operation procedures.

## Backwards Compatibility

* Opaque Token is not compatible with ERC-20 for reasons explained in the Rationale section.

## Security Considerations

### Fraudulent Oracles
&lt;!-- TODO --&gt;

### Oracles Collecting Confidential Data
&lt;!-- TODO --&gt;

### Confidential Data Loss
&lt;!-- TODO --&gt;

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 09 Jun 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7722</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7722</guid>
      </item>
    
      <item>
        <title>Network Upgrade Inclusion Stages</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7723-network-upgrade-inclusion-stages/20281</comments>
        
        <description>## Abstract

Define the stages that EIPs go through in the process of planning network upgrades: `Proposed for Inclusion`, `Considered for Inclusion`, `Scheduled for Inclusion`, `Declined for Inclusion` and `Included`.

## Motivation

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.

## Specification

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

All EIP statuses apply to a single network upgrade. EIPs must be `Proposed`, `Considered`, `Declined` or `Scheduled` separately for each network upgrade. While an EIP cannot be `Included` in two network upgrades, an EIP being `Declined for Inclusion` in a previous upgrade does not prevent it from being `Proposed`, `Considered`, `Declined` or `Scheduled` for inclusion in any future upgrade. 

The statuses below are generally defined for 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 statuses. The differences in the process and implications for non-Core EIPs are noted in each status definition.

### Upgrade Meta EIPs

Anyone **MAY** draft a Meta EIP to list EIPs for a network upgrade. This Meta EIP **SHOULD** include four categories in its specification section: `Proposed for Inclusion`, `Declined for Inclusion`, `Considered for Inclusion` and `Scheduled for Inclusion`. Even if a category is empty, it **SHOULD** be included in the initial draft for clarity. 

When the Upgrade Meta EIP is moved to `Last Call`, the `Proposed for Inclusion`, `Declined for Inclusion` and `Considered for Inclusion` lists **SHOULD** be removed, leaving only `Scheduled for Inclusion`. 

Before the Upgrade Meta EIP is moved to `Final`, the `Scheduled for Inclusion` stage **MUST** be renamed to `Included` and contain only EIPs that were activated in the upgrade. 

### Upgrade Devnets

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 `upgradeName-devnet-version` (e.g. `pectra-devnet-0` for the first upgrade devnet of the Pectra network upgrade, `dencun-devnet-1` for the second upgrade devnet of the Dencun update, etc).

Since client developers&apos; ability to include EIPs in a network upgrade is constrained by what can be implemented and tested in these upgrade devnets, the [Considered for Inclusion](#considered-for-inclusion) and [Scheduled for Inclusion](#scheduled-for-inclusion) sections below propose aligning these statuses with EIPs&apos; implementation status in upgrade devnets.

### Proposed for Inclusion

To propose an EIP for inclusion, someone **MUST** open a pull request to add it to the `Proposed for Inclusion` section of the Upgrade Meta EIP. The proposer of an EIP **SHOULD** serve as the primary point of contact for that EIP for the duration of the upgrade cycle or **SHOULD** designate another person to serve in that role. Reasonable pull requests **SHOULD** be merged in a timely fashion by the Upgrade Meta EIP author.

At this stage, implementation teams **SHOULD** review the EIP. For Core EIPs, this should be in the context of including it in the next upgrade. For non-Core EIPs, this should be in the context of supporting the EIP before the network upgrade is activated. 
 
Note that EIPs must be `Proposed for Inclusion` for each network upgrade. In other words, proposals do not &quot;carry over&quot; to the next upgrade if an EIP is not included in the one it was first proposed for. 

### Considered for Inclusion 

Once client developers have reviewed an EIP which was `Proposed for Inclusion`, they **MAY** move it to the `Considered for Inclusion` stage. Once a decision is made by client teams to move an EIP to `Considered for Inclusion`, the Upgrade Meta EIP **SHOULD** be updated to reflect this. 

`Considered for Inclusion` signals that client developers are positive towards the EIP. A Core EIP that is `Considered for Inclusion`  **SHOULD** be implemented in future Upgrade Devnets. Assuming it meets all the requirements for mainnet deployment it **MAY** be included in the network upgrade. This stage is similar to &quot;concept ACK&quot; in other open source projects, and is not sufficient to result in deployment to mainnet. 

Non-Core EIPs that are `Considered for Inclusion` **SHOULD** be supported prior to the network upgrade being activated. 

An EIP **MAY** be moved from `Considered for Inclusion` to `Declined for Inclusion` if client teams are against including the EIP in the network upgrade. 

An EIP **SHOULD** have a Python implementation accompanied by tests in [execution-specs](https://github.com/ethereum/execution-specs/blob/78fb726158c69d8fa164e28f195fabf6ab59b915/README.md) 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 **MAY** decide to allow an EIP to be moved to `Considered for Inclusion` without either implementation, being aware that the absence of these implementations could lead to delays in the testing cycle.

Any updates to an EIP that is already at this stage **SHOULD** be accompanied by the appropriate updates to its implementation and tests in [execution-specs](https://github.com/ethereum/execution-specs/blob/78fb726158c69d8fa164e28f195fabf6ab59b915/README.md) if deemed necessary by client developers.

### Declined for Inclusion

At any time during the network upgrade planning process, client developers **MAY** move EIPs from any other stage to the `Declined for Inclusion` 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 `Declined for Inclusion`, the Upgrade Meta EIP **SHOULD** be updated to reflect this.

`Declined for Inclusion` 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 `Declined for Inclusion` in a particular upgrade **MAY** still be `Proposed for Inclusion` in a subsequent upgrade. In exceptional circumstances, client developers **MAY** choose to move an EIP from `Declined for Inclusion` to `Considered for Inclusion` or `Scheduled for Inclusion`. 

### Scheduled for Inclusion 

When client teams agree to implement a Core EIP in the **next** Upgrade Devnet, the EIP **SHOULD** move to the `Scheduled for Inclusion` stage, and the Upgrade Meta EIP **SHOULD** be updated to reflect this. Non-Core EIPs **SHOULD** move to `Scheduled for Inclusion` when client teams agree to immediately prioritize their implementation. 

An EIP **MUST** have a Python implementation accompanied by tests in [execution-specs](https://github.com/ethereum/execution-specs/blob/78fb726158c69d8fa164e28f195fabf6ab59b915/README.md), submitted as an open PR or merged to the `devnets/upgradeName/version` branch of the repository. Client developers **MAY** decide to allow an EIP to be moved to `Scheduled for Inclusion` without an [execution-specs](https://github.com/ethereum/execution-specs/blob/78fb726158c69d8fa164e28f195fabf6ab59b915/README.md) implementation, but the tests are strictly mandatory.

Any updates to an EIP that is already at this stage **MUST** be accompanied by appropriate updates to its implementation and tests in [execution-specs](https://github.com/ethereum/execution-specs/blob/78fb726158c69d8fa164e28f195fabf6ab59b915/README.md) if deemed necessary by client developers.

`Scheduled for Inclusion` signals that implementation and testing work are underway. The EIP **SHOULD** be included in the network upgrade if no issues arise. The latest Upgrade Devnet must contain all `Scheduled for Inclusion` Core EIPs.

An EIP **MAY** be moved from `Scheduled for Inclusion` to `Declined for Inclusion` if client teams are against including the EIP in the network upgrade. An EIP **MAY** also be moved from `Scheduled for Inclusion` to `Considered for Inclusion` if client teams are in favor of including the EIP in the network upgrade but cannot commit to including it in the **next** Upgrade Devnet.

### Included

After network upgrade activation, all included Core EIPs and activated non-Core EIPs **MUST** be moved to `Included` in the Meta EIP. All other status lists **MUST** be removed from the Meta EIP.

`Included` signals that the EIPs have been activated as part of the network upgrade. 

## Rationale

Formalizing the `Proposed for Inclusion`, `Considered for Inclusion`, `Scheduled for Inclusion`, `Declined for Inclusion` and `Included` stages provides better legibility to both protocol maintainers and the broader Ethereum community.

The specification tries to minimize steps which **MUST** be followed to align with Ethereum&apos;s &quot;rough consensus&quot; governance model. 

Assuming it is adopted, the process outlined in this EIP should be used for at least one full network upgrade cycle before moving to `Last Call` and at least two full network upgrades cycles before moving to `Final`. This way, the EIP can be updated to reflect changes made to the process over time. 

## Backwards Compatibility

This EIP does not directly change the Ethereum protocol. It formalizes parts of the current network upgrade planning process. 

## Security Considerations

None.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Common Quote Oracle</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7726-common-quote-oracle/20351</comments>
        
        <description>## Abstract

The following allows for the implementation of a standard API for data feeds providing the relative value of
assets, forcing compliant contracts to use explicit token amounts instead of price factors. This approach has been
shown to lead to better security and time-to-market outcomes.

## Motivation

The information required to value assets is scattered over a number of major and minor sources, each one with their own
integration API and security considerations. Many protocols over the years have implemented oracle adapter layers for
their own use to abstract this complexity away from their core implementations, leading to much duplicated effort.

This specification provides a standard API aimed to serve the majority of use cases. Preference is given to ease of
integration and serving the needs of product teams with less knowledge, requirements and resources.

## Specification
The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119 and RFC 8174.
### Definitions

- base asset: The asset that the user needs to know the value for (e.g: USDC as in &quot;I need to know the value of 1e6 USDC
  in ETH terms&quot;).
- quote asset: The asset in which the user needs to value the `base` (e.g: ETH as in &quot;I need to know the value of 1e6
  USDC in ETH terms&quot;).
- value: An amount of `base` in `quote` terms (e.g. The `value` of 1000e6 USDC in ETH terms is 283,969,794,427,307,000
  ETH, and the `value` of 1000e18 ETH in USDC terms is 3,521,501,299,000 USDC). Note that this is an asset amount, and
  not a decimal factor.

### Methods

#### `getQuote`

Returns the value of `baseAmount` of `base` in `quote` terms.

MUST round down towards 0.

MUST revert if the value of `baseAmount` of `base` in `quote` terms would overflow in a uint256.

```yaml
- name: getQuote
  type: function
  stateMutability: view

  inputs:
    - name: baseAmount
      type: uint256
    - name: base
      type: address
    - name: quote
      type: address

  outputs:
    - name: quoteAmount
      type: uint256
```

### Special Addresses

Some assets under the scope of this specification don&apos;t have an address, such as ETH, BTC and national currencies.

For ETH, the address will be `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` as per [ERC-7528](/EIPs/EIPS/eip-7528).

For BTC, the address will be `0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB`.

For assets without an address, but with an ISO 4217 &lt;!-- TODO: Bug Sam about editing EIP-1 to allow certain ISO external links --&gt; code, the code will be used (e.g. `address(840)` for USD).

## Rationale

The use of `getQuote` doesn&apos;t require the consumer to be aware of any decimal partitions that might have been defined
for the `base` or `quote` and should be preferred in most data processing cases.

The spec doesn&apos;t include a `getPrice` function because it is rarely needed on-chain, and it would be a decimal number of
difficult representation. The popular option for representing prices can be implemented for [ERC-20](/EIPs/EIPS/eip-20) with decimals as
`oracle.getQuote(base, quote, 10\*\*base.decimals()) and will give the value of a whole unit of base in quote terms.

## Backwards Compatibility

Most existing data feeds related to the relative value of pairs of assets should be representable using this standard.

## Security Considerations

This specification purposefully provides no methods for data consumers to assess the validity of the data they receive.
It is expected of individual implementations using this specification to decide and publish the quality of the data that
they provide, including the conditions in which they will stop providing it.

Consumers should review these guarantees and use them to decide whether to integrate or not with a data provider.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 20 Jun 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7726</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7726</guid>
      </item>
    
      <item>
        <title>EVM Transaction Bundles</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7727-evm-transaction-bundles/20322</comments>
        
        <description>## Abstract

This EIP introduces two new [EIP-2718](/EIPs/EIPS/eip-2718) transaction types and one new opcode, enabling smart contracts and transactions to delegate their local sequencing rights to an off-chain entity. These new transaction types work together to create EVM-native &apos;bundles&apos;, which are similar to but weaker than the Proposer-Builder Separation (PBS) bundles offered by builders to searchers.

One of the EIP-2718 transactions is an extended normal transaction that supports:

- Specifying the entity who can place the transaction in a bundle.
- An optional block number that the transaction is valid in.

The other EIP-2718 transaction is a &apos;meta&apos; transaction that does not enter into execution, but rather orders transactions of its own type and the other new type. The &apos;meta&apos; transaction can also specify an entity allowed to include it in a bundle and a valid block number.

The new opcode reveals to the EVM the entity that placed the transaction in a bundle if the transaction was in a bundle.

## Motivation

Currently, a single block builder has unrestricted control over the final sequencing of a block’s transactions. This poses a problem, as sequencing—the choice of who gets to interact with specific pieces of state and in what order—significantly influences value flow. The objective of this EIP is to allow more parties to participate in the construction of single blocks by exposing sequencing concepts inside of the EVM. This change would enable EVM applications to reclaim some of the sequencing value that is currently monopolized by block builders, redirecting it back to the applications themselves.

## Specification

### Constants

| Name | Value |
| --- | --- |
| DELEGATED_TX_TYPE | 0x05 |
| BUNDLE_TX_TYPE | 0x06 |
| BUNDLE_BASE_GAS_COST | TBD &lt;!-- TODO --&gt; |
| BUNDLE_SIGNER_OPCODE_NUMBER | TBD &lt;!-- TODO --&gt; |

### New Transaction Payload Types

Two new [EIP-2718](/EIPs/EIPS/eip-2718) transactions with types `DELEGATED_TX_TYPE` and `BUNDLE_TX_TYPE`.

For the `DELEGATED_TX_TYPE`, the transaction payload should be interpreted as:

```go
0x05 || rlp([
	bundleSigner,
	blockNumber,
	chainId, 
	nonce, 
	gasPrice, 
	gasLimit, 
	to, 
	value, 
	data, 
	signatureYParity, 
	signatureR, 
	signatureS
])
```

The `signatureYParity`, `signatureR`, `signatureS` elements of the `DELEGATED_TX_TYPE` represent a secp256k1 signature over:

```go
keccak256(0x05 || rlp([bundleSigner, blockNumber, chain_id, nonce, gasPrice, gasLimit, to, value, data]))
```

For the `BUNDLE_TX_TYPE`, the transaction payload should be interpreted as:

```go
0x06 || rlp([
	bundleSigner,
	blockNumber,
	chainId, 
	nonce, 
	gasPrice, 
	transactionList
	signatureYParity, 
	signatureR, 
	signatureS
])
```

Where the `transactionList` element is a list of syntactically valid transactions of either type `DELEGATED_TX_TYPE` or `BUNDLE_TX_TYPE`. At least one transaction must be in the list.

An example would of the `transactionList` would be:

```go
[
	DELEGATED_TX_TYPE.payload, 
	BUNDLE_TX_TYPE.payload, 
	DELEGATED_TX_TYPE.payload
]
```

The `signatureYParity`, `signatureR`, `signatureS` elements of the `BUNDLE_TX_TYPE` represent a secp256k1 signature over:

```go
keccak256(0x06 || rlp([bundleSigner, blockNumber, chainId, nonce, gasPrice, transactionList]))
```

We’ll refer to address resolved by this signature the bundle transaction’s signer. 

### `BUNDLE_SIGNER` Opcode

The `BUNDLE_SIGNER` is a new opcode identified by `BUNDLE_SIGNER_OPCODE_NUMBER` that requires zero stack arguments.

When the transaction type is `DELEGATED_TX_TYPE`, this opcode pushes the `bundleSigner` from the transaction payload onto the stack as an address. If the transaction is of a different type, it returns the zero address.

The gas cost for this opcode is the `GAS_VERY_LOW` gas constant.

### Transaction Validity Rules

For a `DELEGATED_TX_TYPE` to be valid, the following must be true:

- The transaction must be included in a `BUNDLE_TX_TYPE`&apos;s `transactionList` to be valid.
- The transaction’s specified `bundleSigner` must be equal to the address who signed over the `BUNDLE_TX_TYPE` that included the transaction in a `transactionList`.
- The payload variable `blockNumber`, if not zero, must be the block number that the transaction is executed in.

For a `BUNDLE_TX_TYPE` to be valid, the following MUST be true:

- All transactions in the `transactionList` must specify the signer of the `BUNDLE_TX_TYPE` as the `bundleSigner`.
- The transaction must be included in a `BUNDLE_TX_TYPE`&apos;s `transactionList` if the `bundleSigner` payload variable is not the zero address.
- The payload variable `blockNumber`, if not zero, must be the block number that the transaction is executed in.

### Gas Costs

The `BUNDLE_TX_TYPE` has a new gas cost formula that changes based on whether the transactions in the `transactionList` are valid at the time of execution.

If a transaction in the `transactionList` is invalid, the `BUNDLE_TX_TYPE` transaction is charged as if the invalid transaction&apos;s bytes were part of a typical transaction&apos;s `CALL_DATA`. If an inner transaction is valid, there is no cost for its inclusion in the list.

The formula is calculated as follows:

```go
BUNDLE_BASE_GAS_COST +
    (CALL_DATA_TOKEN_COST * transaction_list_invalid_tx_byte_length)

```

At the start of processing, the `BUNDLE_TX_TYPE`&apos;s signer is charged as if all inner transactions were invalid and is refunded the gas for the valid transactions as each valid transaction finishes execution.

The `DELEGATED_TX_TYPE` follows typical gas costing rules.

### Execution

`DELEGATED_TX_TYPE` execute normally with the `BUNDLE_SIGNER` opcode returning the `bundleSigner` payload variable.

`BUNDLE_TX_TYPE` do not start execution contexts. The`BUNDLE_TX_TYPE`&apos;s `NONCE` must be incremented before the start of any `transactionList` execution.

### ReceiptPayload Definitions

For `DELEGATED_TX_TYPE` transaction that are able to begin execution, their [EIP-2718](/EIPs/EIPS/eip-2718) receipt payload should be interpreted as:

```go
rlp([status, cumulativeGasUsed, logsBloom, logs])
```

`DELEGATED_TX_TYPE` transactions that are invalid do not get transaction receipts.

The `BUNDLE_TX_TYPE` transaction’s  [EIP-2718](/EIPs/EIPS/eip-2718) receipt payload should be interpreted as:

```go
rlp([statusArray, cumulativeGasUsed])
```

Where the `statusArray` is a list of status results for the inner `transactionList`&apos;s transactions. The list must be the same length as the `transactionList` and report the statuses in the same order. The status type `0x3` should be used to report invalid transactions.

The `cumulateGasUsed` is the amount of gas spent by the `BUNDLE_TX_TYPE`&apos;s signer on the `BUNDLE_TX_TYPE` transaction costs post `CALLDATA` refund. 

## Rationale

### Allowing invalid transactions to be included in a `BUNDLE_TX_TYPE`&apos;s `transactionList`

Knowing how a transaction will execute is challenging without knowing the state root to which the transaction is applied. Creators of `BUNDLE_TX_TYPE` transactions can only access the previous block’s state root and cannot predict which transactions will precede the `BUNDLE_TX_TYPE` transaction in the upcoming block&apos;s total order. If only valid transactions were permitted, `BUNDLE_TX_TYPE` transaction lists could be easily invalidated by a single inner transaction attempting to grief the bundle through nonce or gas invalidations.

### Charging the `BUNDLE_TX_TYPE`&apos;s signer `CALLDATA` gas costs for invalid transactions

Blockchains must charge for the work that nodes perform to prevent DoS attacks. Even though invalid transactions in `BUNDLE_TX_TYPE` transaction lists do not execute, they still occupy block space as bytes and must be paid for by some entity. It is assumed that `BUNDLE_TX_TYPE` creators will be sophisticated entities capable of simulating the previous block’s state with relative accuracy and able to generate enough profit to offset any invalidation costs incurred. 

The `BUNDLE_BASE_GAS_COST` should be set to make the cost of attempting to grief the `BUNDLE_TX_TYPE` signer more expensive than the cost of the bytes to cover the invalid transaction.

### Requiring `DELEGATED_TX_TYPE` typed transactions to be included in a `BUNDLE_TX_TYPE`&apos;s `transactionList`

If `DELEGATED_TX_TYPE` transactions were able to be executed outside of a `BUNDLE_TX_TYPE` transaction list, then there would be competition between the `BUNDLE_TX_TYPE` signer and the total block builder for the right to choose how to locally sequence the transaction. If the `DELEGATED_TX_TYPE` transaction signer wished to allow the total block builder to choose the local ordering, then the `DELEGATED_TX_TYPE` transaction type should not be used.

The same principle applies to `BUNDLE_TX_TYPE` transactions. Those that specify a `bundleSigner` must only be included in a `BUNDLE_TX_TYPE` list, while those that do not specify a `bundleSigner` must not be included in such a list.

### Not allowing other transactions types to be included in a `BUNDLE_TX_TYPE`&apos;s `transactionList`

This restriction was implemented as a precautionary measure and could be reconsidered in the future. Allowing the inclusion of other transaction types that do not specify a `bundleSigner` into the `transactionList` could result in multiple searchers attempting to include the same transaction in a bundle. This could potentially create spam within a block.

### Differences from PBS Searcher Bundles

PBS block builders currently offer &apos;bundles&apos; as a service to searchers in the form of transaction lists that either all execute without reversion or are not included in a block. Searchers typically use these bundles to bid for the right to be the first to interact with a piece of state or to place logic before or after transactions created by non-searcher entities, with back-running and sandwiching being examples. PBS block builders provide this service as a way to gain order flow and increase their block&apos;s value.

The `BUNDLE_TX_TYPE` transaction differ in two key ways:

1. There is no revert protection. 
2. Only transactions explicitly delegating to a `bundleSigner` can be bundled. 

These choices were made to prevent DoS attacks on builders and to be compatible with non-PBS block builders running other algorithms. 

## Backwards Compatibility

No backward compatibility issues found.

## Security Considerations

Block builders are problematic today partly due to their ability to perform censorship and enforce malicious orderings. These concerns persist even when sequencing rights are delegated to a specific entity. The code that generates the off-chain ordering should be public and executed in a trust-minimized manner, such as in a TEE (Trusted Execution Environment) or on a blockchain with faster block times.

Similarly, smart contracts that restrict functionality to transactions signed by a specific `BUNDLE_SIGNER` should provide mechanisms for users to withdraw funds without relying on the delegated sequencing entity to be online or non-malicious. A two-step fund removal process could be implemented to allow safe interaction with bundle construction and simulation logic.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).  
</description>
        <pubDate>Mon, 24 Jun 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7727</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7727</guid>
      </item>
    
      <item>
        <title>Token with Metadata</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7729-token-with-metadata/20939</comments>
        
        <description>## Abstract

This standard extends the [ERC-20](/EIPs/EIPS/eip-20) standard to include a `metadata` function interface and a JSON schema for metadata.

## Motivation

Memecoins have demonstrated the value of associating tokens with visual metadata. By standardizing a way to include metadata in ERC-20 tokens, developers can create more engaging and interactive tokens, fostering community engagement.

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119 and RFC 8174.

**Every compliant contract must implement the `IERC7729`, and [`ERC20`](/EIPs/EIPS/eip-20) interfaces.**

This standard includes the following interface:

```solidity
pragma solidity ^0.8.0;

interface IERC20Metadata is IERC20 {
    /// @dev Returns the metadata URI associated with the token.
    ///  The URI may point to a JSON file that conforms to the &quot;ERCX Metadata JSON Schema&quot;.
    function metadata() external view returns (string memory);
}
```

This is the &quot;[ERC-7729](/EIPs/EIPS/eip-7729) Metadata JSON Schema&quot; referenced above.

```json
{
    &quot;title&quot;: &quot;Token Metadata&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;name&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Identifies the asset to which this token represents&quot;
        },
        &quot;description&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Describes the asset to which this token represents&quot;
        },
        &quot;image&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;A URI pointing to a resource with mime type image/* representing the asset to which this token represents.&quot;
        }
    }
}
```

## Rationale

The `metadata` function was chosen based on existing implementations in standards and applications.

## Backwards Compatibility

This standard is backward compatible with the [ERC-20](/EIPs/EIPS/eip-20) as it extends the existing functionality with new interfaces.

## Reference Implementation

```solidity
pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/token/ERC20/ERC20.sol&quot;;

interface IERC7729 is IERC20 {
    function metadata() external view returns (string memory);
}

contract ERC7729 is ERC20, IERCX {
    string _metadata = &quot;ipfs://QmakTsyRRmvihYwiAstYPYAeHBfaPYz3v9z2mkA1tYLA4w&quot;;

    function metadata() external view returns (string memory) {
        return _metadata;
    }
}
```

## Security Considerations

The metadata URI could be manipulated to point to malicious content or phishing sites. Off-chain indexers should perform validation checks to ensure the security and integrity of the metadata URIs for users.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 24 Jun 2023 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7729</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7729</guid>
      </item>
    
      <item>
        <title>Structured Data Clear Signing Format</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7730-proposal-for-a-clear-signing-standard-format-for-wallets/20403</comments>
        
        <description>## Abstract

This specification defines a JSON format carrying additional information required to correctly display structured data for human verification on wallet screens or for machine consumption e.g. by transaction simulation engines.

The [ERC-7730](/EIPs/EIPS/eip-7730) specification enriches type data contained in the ABIs and schemas of structured messages (structures like the calldata of an EVM transaction, an [EIP-712](/EIPs/EIPS/eip-712) message or an [EIP-4337](/EIPs/EIPS/eip-4337) User Operation) with additional formatting information and dynamic value interpolation, enabling both human-readable display with contextual intent descriptions and machine-interpretable data processing. For instance, a solidity field containing an amount, encoded as an uint256, can be converted to the right magnitude and appended with the correct ticker for display, or parsed programmatically for transaction simulation. Fields containing encrypted values (such as FHE-encrypted amounts in confidential token standards like [ERC-7984](/EIPs/EIPS/eip-7984)) can also be annotated with decryption context, enabling wallets to either decrypt and display the plaintext value or present a meaningful fallback.

Wallets and automated systems will use curated ERC-7730 files alongside the raw data to sign in order to construct appropriate interfaces for their respective use cases.

This enables significantly improved signing user experiences and lower end-user risk from frontend and phishing attacks. 

## Motivation

Properly validating a transaction on a hardware wallet&apos;s screen (also known as Clear Signing) is a key element of good security practices for end users when interacting with any Blockchain. Unfortunately, most data to sign, even enriched with the data structure description (like ABIs or EIP-712 types) are not self-sufficient in terms of correctly displaying them to users for review. Among other things:

- Function name or main message type is often a developer oriented name and does not translate to a clear intent for the user
- Fields in the data to sign are tied to primitive types only, but those can be displayed in many different ways. For instance, integers can be displayed as percentages, dates, etc...
- Some fields require additional metadata to be displayed correctly, for instance token amounts require knowledge of the decimals and the ticker, as well as where to find the token address itself to be correctly formatted.
- Some values can be encrypted, such as encrypted amounts in confidential tokens following [ERC-7984](/EIPs/EIPS/eip-7984). These values cannot be directly interpreted, so additional context must be provided to enable wallets to decrypt and display them for users.

This specification intends to provide a simple, open standard format to provide wallets with the additional information required to properly format a structured data to sign for review by users.

Providing this additional formatting information requires deep knowledge of the way a smart contract or message is going to be used. It is expected that app developers will be the best placed to write such a file. The intent of an open standard is to only write this file once and have it work with most wallets supporting this standard.


## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119 and RFC 8174.

### Simple example

The following is an example of how to clear sign a `transfer` function call on an [ERC-20](/EIPs/EIPS/eip-20) contract.

```json
{
    &quot;$schema&quot;: &quot;https://eips.ethereum.org/assets/eip-7730/erc7730-v2.schema.json&quot;,

    &quot;context&quot;: {
        &quot;$id&quot;: &quot;Example ERC-20&quot;,
        &quot;contract&quot; : {
            &quot;deployments&quot;: [ 
                {
                    &quot;chainId&quot;: 1,
                    &quot;address&quot;: &quot;0xdAC17F958D2ee523a2206206994597C13D831ec7&quot;
                },
                {
                    &quot;chainId&quot;: 137,
                    &quot;address&quot;: &quot;0xc2132D05D31c914a87C6611C10748AEb04B58e8F&quot;
                },
                {
                    &quot;chainId&quot;: 42161,
                    &quot;address&quot;: &quot;0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9&quot;
                }
            ]
        }
    }, 

    &quot;metadata&quot;: {
        &quot;owner&quot;: &quot;Example&quot;,
        &quot;contractName&quot;: &quot;Example Token&quot;,
        &quot;info&quot;: {
            &quot;url&quot;: &quot;https://example.io/&quot;,
            &quot;deploymentDate&quot;: &quot;2017-11-28T12:41:21Z&quot;  
        }
    },

    &quot;display&quot;: {
        &quot;formats&quot;: {
            &quot;transfer(address to,uint256 value)&quot;: {
                &quot;intent&quot;: &quot;Send&quot;,
                &quot;interpolatedIntent&quot;: &quot;Send {value} to {to}&quot;,
                &quot;fields&quot;: [
                    {
                        &quot;path&quot;: &quot;value&quot;,
                        &quot;label&quot;: &quot;Amount&quot;,
                        &quot;format&quot;: &quot;tokenAmount&quot;,
                        &quot;params&quot;: {
                            &quot;tokenPath&quot;: &quot;@.to&quot;
                        }
                    },
                    {
                        &quot;path&quot;: &quot;to&quot;,
                        &quot;label&quot;: &quot;To&quot;,
                        &quot;format&quot;: &quot;addressName&quot;
                    }
                ]
            }
        }
    }
}
```

The `$schema` key refers to the latest version of this specification json schema (version 1 at the time of writing).

The `context` key is used to provide binding context information for this file. It can be seen as a set of *constraints* on the structured data being reviewed, indicating whether the ERC-7730 file is valid for this data. A wallet MUST ensure these constraints are met before ERC-7730 formatting information is applied to the data being signed. 

In this example, the context section indicates that the ERC-7730 file should only be applied to the Example smart contract whose deployment addresses are provided. Once the contract is matched, wallets use the `display.formats` entry itself to derive the function selector, parameter layout, and user-facing labels.

The `metadata` section contains constants that can be trusted when the ERC-7730 file is applicable for the given context. This section is typically used to:
- Provide displayable information about the recipient of the contract call / message
- Provide displayable values of enumeration or encoded id parameters, typically smart contract / message specific
- Provide common constants used by the various formats defined in the file

In this example, the metadata section contains only the recipient information, in the form of a displayable name (`owner` key), contract displayable name (`contractName` key) and additional information (`info` key) that MAY be used by wallets to provide details about the recipient.

Finally, the `display` section contains the definitions of how to format each field of targeted contract calls under the `formats` key. 

In this example, the function being described is identified by its human-readable ABI fragment `transfer(address to,uint256 value)`. Wallets strip the parameter names to compute the type-only signature `transfer(address,uint256)`, hash it, and match the resulting selector `0xa9059cbb` against the calldata.
- The `intent` key contains a human-readable string that wallets SHOULD display to explain to the user the intent of the function call. 
- The `fields` key contains all the parameters formatting information
- The `interpolatedIntent` key is a suggested short string representation of intent and fields that wallet CAN use instead of having a dedicated layout. 
  
In this example, the `to` parameter and the `value` parameter SHOULD both be displayed, one as an address replaceable by a trusted name (ENS or others), the other as an amount formatted using metadata of the target ERC-20 contract. 

### Versioning

The version of the specification used by the 7730 file is specified by linking to the reference schema file under the `$schema` key.

The current version of the specification is `2` at the time of writing. The reference schema for version `2` is [here](/EIPs/assets/eip-7730/erc7730-v2.schema.json).

### Common concepts

#### Key naming convention

In all the specification, key names starting with `$` are *internal* and have no value beyond readability of the specification file itself. They should not be used in any function to build the UI to review structured data.

#### Structured data

This specification intends to be extensible to describe the display formatting of any kind of *structured data*. 

By *Structured data*, we target any data format that has:
- A well-defined *type* system; the data being described itself being of a specific top-level type
- A description of the type system, the *schema*, that should allow splitting the data into *fields*, each field clearly identified with a *path* that can be described as a string.

Displaying structured data is often done by wallets to review its content before authorizing an action in the form of a *signature* over some serialization of the structured data. As such, the structured data is contained in a *container structure*:
- Container structure has a well-defined *signature* scheme (a serialization scheme, a hashing scheme, and signature algorithm).
- The container structure does not necessarily follow the same type system as the structured data.
- Wallets receive the full container structure and uses the signature scheme to generate a signature on the overall structure.

![Structured Data and Container](/EIPs/assets/eip-7730/structured-data.svg)

Current specification covers EVM smart contract calldata:
- Defined in Solidity
- The schema is the function ABI (derived from the matched `display.formats` function fragment)
- The container structure is an EVM Transaction serialized in RLP encoding

It also supports EIP-712 messages
- Defined in EIP-712
- The schema is extracted from the type string representation carried in the `display.formats` message fragments.
- An EIP-712 message is self-contained, the signature is applied to the hashed message itself following EIP-712 specification.

The *schema* is defined by the binding context together with the selected display entry. For contracts, the matched `display.formats` key provides the full function signature (types and parameter names); for EIP-712 messages, the matched `display.formats` provides the type encoding of the message. Both form of type definition allows defining unique *paths* pointing to specific fields in the data.

Formats are dependent on and defined for the underlying *types* on the structured data. The [Reference](#reference) section covers formats and types supported by this current version of the specification. 

It is sometime necessary for formatting of fields of the structured data to reference values of the *container structure*. These values are dependent on the container structure itself and are defined in the [Reference](#reference) section.

#### Path references

This specification uses a limited [json path](https://www.rfc-editor.org/rfc/rfc9535) notation to reference values that can be found in multiple json documents. 

Limitation to the json path specification are the following:
- Paths MUST use the dot notation, including for slice and array selectors (i.e. an element of an array should be selected through `array_name.[index]`) 
- Only name, index and slices selectors are supported.
* Slices selectors MUST NOT contain the optional step. Start index is inclusive, end index is exclusive. Start or end index can be omitted to indicate the beginning or end of the array.

In addition, additional *roots* are introduced to support description of paths over multiple files in a single common notation. The root node identifier indicates which document or data location this path references, according to the following table:

| Root | Short summary |
|------|---------------|
| `#`  | Structured data schema — decoded function parameters or EIP‑712 message fields |
| `$`  | ERC‑7730 specification file (after merging includes) |
| `@`  | Container-level values (transaction or message metadata) |

Notes:
- Omitting the root makes the path relative to the structure being described. If there is no enclosing container, a relative path is equivalent to starting with `#.`.  

##### `#` — structured data (decoded)

Paths with the `#` root refer to fields in the structured data being signed — e.g. decoded function arguments for contract calldata or fields of an EIP‑712 message. Names of the path selectors match the schema of the transaction or message, found in the keys under `display.formats`.  Values come from the serialized structured data once decoded by the wallet.  

*Examples*
- `#.params.amountIn` — the `amountIn` field inside top-level `params`.  
- `params.amountIn` (relative) — equivalent when the path is resolved relative to the structured data.
- `#.details.[]` refers to the array with the Permit Details of a PermitBatch message

##### `$` — merged ERC‑7730 file

Paths with the `$` root point to values in the ERC‑7730 file itself after any `includes` have been merged by the consumer. Use `$` to reference metadata, definitions, enums, maps and any constants authored in the specification.  

*Examples*
- `$.metadata.enums.interestRateMode` — enumeration values defined in the spec.  
- `$.display.definitions.minReceiveAmount` — a shared field definition.

##### `@` — container (transaction / message)

The `@` root names values coming from the container that wraps the structured data (for example, an EVM transaction or an EIP‑712 message). These values are container-specific; see the [Reference](#reference) section for the canonical list of container fields (e.g. `@.from`, `@.to`, `@.value`, `@.chainId`).  

*Examples*
- `@.value` — native currency value of an EVM transaction.  
- `@.to` — transaction destination (contract address).

##### Path slices

For paths referring to structured data fields, if a field has a variable length primitive type (like `bytes` or `string` in solidity), a slice selector can be appended to the path, to refer to the specific set of bytes indicated by the slice. A slice selector can also be appended to arrays to select only the specified part of the array.

*Examples*

* `#.data.path.[0].path.[-1].to` or `data.path.[0].path.[-1].to` refers to the field `to` taken from last member of `path` array, itself taken from first member of enclosing `path` array, itself part of top level `data` structure.
* `#.params.path.[:20]` or `#.params.path.[0:20]` refers to the first 20 bytes of the `path` byte array
* `#.params.path.[-20:]` refers to the last 20 bytes of the `path` byte array

#### Value interpolation

The `interpolatedIntent` field supports embedding formatted field values directly within intent strings using interpolation syntax. This allows constructing dynamic, context-aware descriptions of transactions and messages as an alternative to using individual `intent` and `fields`.

The `interpolatedIntent` makes transaction intents significantly shorter and easier to read by presenting all relevant information in a single, natural language sentence rather than as separate labeled fields. This is particularly valuable for:
- Reducing the cognitive load on users reviewing transactions
- Displaying concise summaries on resource-constrained devices
- Enabling clear descriptions of batch transactions (e.g., [EIP-5792](/EIPs/EIPS/eip-5792)), where multiple operations can be concatenated into a single readable sentence

**Interpolation syntax**

Values are interpolated using curly braces containing a path reference: `{path}`. The path MUST follow the [path reference rules](#path-references) and can reference:
- Structured data fields (e.g., `{to}`, `{params.amountIn}`)
- Container values (e.g., `{@.value}`, `{@.from}`)
- Metadata constants (e.g., `{$.metadata.constants.nativeAssetAddress}`)

Interpolated intents MUST only refer to paths that are noted as always visible (i.e. `visible` key in the field formatter is `always` or not present).

**Formatting behavior**

When a wallet processes an `interpolatedIntent`:
1. The wallet MUST identify all interpolation expressions `{path}` in the string
2. For each expression, the wallet MUST resolve the path and locate the corresponding field format specification in the `fields` array
3. The wallet MUST apply the field&apos;s `format` and `params` to format the value
4. The wallet MUST replace the interpolation expression with the formatted value
5. If any interpolation fails (path not found, formatting error, etc.), the wallet MUST fall back to displaying the regular `intent` field

**Escaping**

To include literal curly braces in the intent text, escape them by doubling: `{{` for `{` and `}}` for `}`.

**Examples**

*Simple token transfer:*
```json
{
    &quot;intent&quot;: &quot;Send&quot;,
    &quot;interpolatedIntent&quot;: &quot;Send {value} to {to}&quot;,
    &quot;fields&quot;: [
        {&quot;path&quot;: &quot;to&quot;, &quot;format&quot;: &quot;addressName&quot;},
        {&quot;path&quot;: &quot;value&quot;, &quot;format&quot;: &quot;tokenAmount&quot;, &quot;params&quot;: {&quot;tokenPath&quot;: &quot;@.to&quot;}}
    ]
}
```
Displays as: **&quot;Send 100 USDT to cyberdrk.eth&quot;**

*Simple encrypted token transfer:*
```json
{
    &quot;intent&quot;: &quot;Send&quot;,
    &quot;interpolatedIntent&quot;: &quot;Send {value} to {to}&quot;,
    &quot;fields&quot;: [
        {&quot;path&quot;: &quot;to&quot;, &quot;format&quot;: &quot;addressName&quot;},
        {&quot;path&quot;: &quot;value&quot;, &quot;format&quot;: &quot;tokenAmount&quot;, &quot;params&quot;: {&quot;tokenPath&quot;: &quot;@.to&quot;}, &quot;encryption&quot;: {
            &quot;scheme&quot;: &quot;fhevm&quot;,
            &quot;plaintextType&quot;: &quot;uint64&quot;,
            &quot;fallbackLabel&quot;: &quot;[Encrypted Amount]&quot;
        }}
    ]
}
```
Displays as:
- When decryption is available: **&quot;Send 100 USDT to cyberdrk.eth&quot;**
- When decryption is not available: **&quot;Send [Encrypted Amount] to cyberdrk.eth&quot;**

*Swap with native currency:*
```json
{
    &quot;intent&quot;: &quot;Swap&quot;,
    &quot;interpolatedIntent&quot;: &quot;Swap {amountIn} for at least {amountOutMinimum}&quot;,
    &quot;fields&quot;: [
        {&quot;path&quot;: &quot;amountIn&quot;, &quot;format&quot;: &quot;tokenAmount&quot;, &quot;params&quot;: {&quot;tokenPath&quot;: &quot;tokenIn&quot;}},
        {&quot;path&quot;: &quot;amountOutMinimum&quot;, &quot;format&quot;: &quot;tokenAmount&quot;, &quot;params&quot;: {&quot;tokenPath&quot;: &quot;tokenOut&quot;}}
    ]
}
```
Displays as: **&quot;Swap 1000 USDC for at least 0.25 WETH&quot;**

*Using container values:*
```json
{
    &quot;intent&quot;: &quot;Wrap ETH&quot;,
    &quot;interpolatedIntent&quot;: &quot;Wrap {@.value} ETH for WETH&quot;,
    &quot;fields&quot;: [
        {&quot;path&quot;: &quot;@.value&quot;, &quot;format&quot;: &quot;amount&quot;}
    ]
}
```
Displays as: **&quot;Wrap 0.5 ETH for WETH&quot;**

*Escaping literal braces:*
```json
{
    &quot;interpolatedIntent&quot;: &quot;Execute {{function}} with {amount} tokens&quot;
}
```
Displays as: **&quot;Execute {function} with 100 tokens&quot;**

#### Organizing files

Smart contracts and EIP-712 messages are often re-using common interfaces or types that share similar display formatting. This specification supports a basic inclusion mechanism that enables sharing files describing specific interfaces or types.

The `includes` top-level key is a URL pointing to an ERC-7730 file that MUST follow this specification.

A wallet using an ERC-7730 file including another file SHOULD merge those files into a single reference file. When merging, conflicts between common unique keys are resolved by prioritizing the including file.

*Merging field format specifications*

Special care must be taken when merging [field format specifications](#field-format-specification). These objects are grouped in an array under the `fields` key, allowing ordering of field formatters. When merging the two arrays, a wallet SHOULD:
* Merge together objects sharing the same `path` value, overriding parameters of the included file with those of the including file.
* Append objects with `path` values not part of the included file to the resulting array.

*Example*

This file defines a generic ERC-20 interface for a single `approve` function:
```json
{
    &quot;display&quot;: {
        &quot;formats&quot;: {
            &quot;approve(address spender,uint256 value)&quot;: {
                &quot;intent&quot;: &quot;Approve&quot;,
                &quot;fields&quot;: [
                    {
                        &quot;path&quot;: &quot;spender&quot;,
                        &quot;label&quot;: &quot;Spender&quot;,
                        &quot;format&quot;: &quot;addressName&quot;
                    },
                    {
                        &quot;path&quot;: &quot;value&quot;,
                        &quot;label&quot;: &quot;Amount&quot;,
                        &quot;format&quot;: &quot;tokenAmount&quot;,
                        &quot;params&quot;: {
                            &quot;tokenPath&quot;: &quot;@.to&quot;,
                            &quot;threshold&quot;: &quot;0x8000000000000000000000000000000000000000000000000000000000000000&quot;,
                            &quot;thresholdLabel&quot;: &quot;Unlimited&quot;
                        }
                    }
                ]
            }
        }
    }
}
```
Note that there are no keys for binding the contract to a specific address or owner, nor any contract specific metadata.

The following file would include this generic interface and bind it to the specific USDT contract, overriding the threshold value to one relative to USDT:
```json
{
    &quot;context&quot;: {
        &quot;$id&quot;: &quot;Example Contract&quot;,
        &quot;contract&quot; : {
            &quot;deployments&quot;: [
                {
                &quot;chainId&quot;: 1,
                &quot;address&quot;: &quot;0xdAC17F958D2ee523a2206206994597C13D831ec7&quot;
                }
            ]
        }
    }, 

    &quot;includes&quot;: &quot;./example-erc20.json&quot;,
    
    &quot;metadata&quot;: {
        &quot;owner&quot;: &quot;Example&quot;,
        &quot;contractName&quot;: &quot;Example Token&quot;,
        &quot;info&quot;: {
            &quot;url&quot;: &quot;https://example.io/&quot;,
            &quot;deploymentDate&quot;: &quot;2017-11-28T12:41:21Z&quot;  
        },
        &quot;token&quot;: {
            &quot;ticker&quot;: &quot;STABLE&quot;,
            &quot;name&quot;: &quot;Example Stablecoin&quot;,
            &quot;decimals&quot;: 6
        }
    },

    &quot;display&quot;: {
        &quot;formats&quot;: {
            &quot;approve(address spender,uint256 value)&quot;: {
                &quot;fields&quot;: [
                    {
                        &quot;path&quot;: &quot;value&quot;,
                        &quot;params&quot; : {
                            &quot;threshold&quot;: &quot;0xFFFFFFFFFFFFFFFFFF&quot;
                        }
                    }
                ]
            }
        }
    }
}
```
Note that the keys under `context.contract` would be merged together to construct a full contract binding object. The field formatter `value` parameter `threshold` is overridden with value `0xFFFFFFFFFFFFFFFFFF`.

### `Context` section

The `context` section describes a set of *constraints* that must be verified by the structured data and container structure before formatting them using the ERC-7730 file. A wallet MUST verify that the structured data and container it is trying to sign matches the constraints of the `context` section.

The current version of this specification only supports two types of binding context, EVM smart contracts and EIP-712 domains. 

All context support an `$id` sub-key as an internal identifier (only relevant to provide a human-readable name to the ERC-7730 file)

#### EVM smart contract binding context (denoted &apos;calldata&apos;)

The `contract` sub-key is used to introduce an EVM smart contract binding context, with the following constraints expressed as sub-keys of `contract`.
  
**`contract.deployments`**

An array of deployments options. Wallets MUST verify that the target chain and contract address of the containing transaction either:
  * Match one of these deployment options
  * Is a *proxy* pointing to one of the deployment option (see [Proxy support](#proxy-support))

A deployment option is an object with:
  * `chainId`: an [EIP-155 identifier](/EIPs/EIPS/eip-155) of the chain the described contract is deployed on.
  * `address`: the address of the deployed contract on specified `chainId` chain.

**`contract.abi`** *(deprecated)*

Legacy ABI attachment kept for backward compatibility. Authors SHOULD prefer `display.formats` and avoid relying on this key, as it will be removed in a future revision.

**`contract.factory`**

An object describing the factory used to deploy smart contracts that can be clear signed using the ERC-7730 file.

A factory is a json object with:
* `deployEvent` key, specifying the solidity signature of the events emitted when deploying a clear-signable contract.
* `deployments` key: an array of deployment options as in `contract.deployments`. These deployments represent the addresses at which the *factory* is deployed.  

To verify a factory constraints a wallet MUST check that:
* The current transaction destination address is included in an event of signature `factory.deployEvent`
* The emitter of the event is a factory contract deployed at an address matching one of the deployment option in `factory.deployments`

#### EIP-712 messages binding context (denoted &apos;messages&apos;)

* The `eip712` sub-key is used to introduce an EIP-712 message type to bind to:

**`eip712.schemas`** *(deprecated)*

Legacy Schema attachment kept for backward compatibility. Authors SHOULD prefer `display.formats` and avoid relying on this key, as it will be removed in a future revision.


**`eip712.domain`**

The `domain` constraint is a json object with simple key-value pairs, describing a set of values that the *EIP-712 Domain* of the message MUST match. 

A wallet MUST verify that each key-value pair in this `domain` binding matches the values of the `domain` key-value pairs of the message. Note that the message can have more keys in its `domain` than those listed in the ERC-7730 file. An EIP-712 domain is a free-form list of keys, but those are very common to include:
  
* `name`: the name of the message verifier
* `version`: the version of the message
* `chainId`: an [EIP-155](/EIPs/EIPS/eip-155) identifier of the chain the message is bound to 
* `verifyingContract`: the address the message is bound to

Note that `chainId` and `verifyingContract` can also be bound to their values thanks to the `eip712.deployments` constraint, in a more flexible way (supporting multiple deployment values).

**`eip712.deployments`**

An array of deployments options. 

When an `eip712.deployments` constraint is set, the wallet MUST verify that:
* The message being displayed has both `domain.chainId` and `domain.verifyingContract` keys
* The `chainId` and `verifyingContract` values in the domain either
  * Match ONE of the deployment option specified in `eip712.deployments`
  * Is a *proxy* pointing to one of the deployment options (see [Proxy support](#proxy-support))

A deployment option is an object with:
* `chainId`: an EIP-155 identifier of the chain the described contract is deployed on.
* `address`: the address of the deployed contract on specified `chainId` chain.

**`eip712.domainSeparator`**

An hex string containing the value of the *domainSeparator* to check. 

Wallet MUST verify that the message *EIP-712 Domain* hashes (as defined in EIP-712) to the value in `eip712.domainSeparator`. 

When the exact construction of the EIP-712 domain is not known (for instance, when the smart contract code only contains the hash value of the domain separator), `domainSeparator` and `domain.verifyingContract` can still be used to target the right message recipients. 

*Examples*

```json
{
    &quot;context&quot; : {
        &quot;eip712&quot;: {
            &quot;domain&quot;: {
                &quot;name&quot;: &quot;Permit2&quot;
            },
            &quot;deployments&quot;: [
                {
                    &quot;chainId&quot;: 1,
                    &quot;address&quot;: &quot;0x000000000022D473030F116dDEE9F6B43aC78BA3&quot;
                },
                {
                    &quot;chainId&quot;: 42161,
                    &quot;address&quot;: &quot;0x000000000022D473030F116dDEE9F6B43aC78BA3&quot;
                }
            ]
        }
    }
}
```
The previous snippet defines a context for a `Permit2` EIP-712 message (types have been omitted for readability).

The `domain` key indicates that the message signed domain MUST contain a `name` key of value `Permit2`. The `deployments` key means that the domain must contain both `chainId` and `verifyingContract` keys and they MUST match one of the deployment options (here, on ETH mainnet and Arbitrum).

### `Metadata` section

The `metadata` section contains information about constant values relevant in the scope of the current contract / message (as matched by the `context` section). 

In the context of wallets and clear signing, these constant values are either used to construct the UI when approving the signing operation, or to provide parameters / checks on the data being signed. But these constant values are relevant outside of the scope of wallets, and should be understood as reference values concerning the bound contract / message.

All keys but the `metadata.owner` key are optional.

**`metadata.owner`**

A key containing a displayable name of the *owner* of the contract or of the verifying contract for a message. 

Wallet MAY use this value to display the target of the interaction being reviewed.

**`metadata.contractName`**

A key containing a displayable name of the contract or of the verifying contract for a message. 

Wallet MAY use this value to display the target of the interaction being reviewed.

**`metadata.info`**

A key containing additional structured info about the *owner* of the contract:
  * `deploymentDate` is the date of deployment of the contract (or verifying contract)
  * `url` is the official URL of the owner

A wallet MAY use this information to display additional details about the targeted contract.

**`metadata.token`**

The `token` key is only relevant for `contract` ERC-7730 files and only for contracts supporting an ERC-20 interface. 

It contains the ERC-20 metadata when the contract itself does not support the optional calls to retrieve it. It SHOULD NOT be present if the contract does support the `name()`, `symbol()` and `decimals()` smart contract calls. 

The ERC-20 token metadata for the contract described is in the sub-keys `name`, `ticker` and `decimals` and contains the values that the correponding function calls would have returned.

**`metadata.constants`**

This key contains in a json object all the constants that can be re-used as parameters in the formatters, or that make sense in the context of this contract / message. 

It is a list of key / value pairs, the key being used to reference this constant (as a *path* starting with a root node `$.` i.e. `$.metadata.constants.KEY_NAME`).

*Example*

```json
{
    &quot;metadata&quot;: {
        &quot;constants&quot;: {
            &quot;nativeAssetAddress&quot;: &quot;0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&quot;
        }
    }
}
```
This snippet introduces a constant `nativeAssetAddress` (an address typically used to represent the native network underlying currency, which is smart contract specific). This constant can be referenced using the path `$.metadata.constants.nativeAssetAddress`

**`metadata.maps`**

Sometimes constants are dependant on some part of the context of the transaction, for instance a token address used by a contract might depend on the deployment chain. `maps` key allow an efficient representation of those types of context-dependent constants.

Each key under the `maps` object is a *map* name. 

A map is a json object with two keys:
* The `$keyType` key contains an non normative indication of the expected type of the map key passed when referencing the map.
* The `values` key contains a list of key / value pairs, each key being used to match the data pointed to in the reference `keyPath` key. The corresponding value is used as the context-dependent constant when referenced in the `display` section.

Maps references can be used anywhere a parameter with constant value would be used. A map reference is a json object with two keys:
* The `map` key refers to the map to use to resolve the constant value, using a path starting with root node `$.` (i.e. `$.metadata.maps.MAP_NAME`).
* The `keyPath` key refers to the path to use to retrieve the map key to use for the resolution. 

A wallet MUST replace a path to a map using the value matching the `keyPath` parameter. In case no values matches the wallet MUST consider the 7730 file invalid for the transaction. 

An example can be found in [example-maps.json](/EIPs/assets/eip-7730/example-maps.json) and [example-maps-pools.json](/EIPs/assets/eip-7730/example-maps-pools.json).

*Examples*

```json
{
    &quot;metadata&quot;: {
        &quot;maps&quot;: {
            &quot;underlyingToken&quot;: {
                &quot;$keyType&quot;: &quot;Chain ID&quot;,
                &quot;values&quot; : {
                    &quot;1&quot;: &quot;0xaabbccddeeff...&quot;,
                    &quot;17000&quot;: &quot;0x112233445566...&quot;
                }
            }
        }
    },
    &quot;display&quot;: {
        &quot;formats&quot;: {
            &quot;deposit(uint256 amount)&quot; : {
                &quot;intent&quot;: &quot;Deposit&quot;,
                &quot;fields&quot;: [
                    {
                        &quot;path&quot;: &quot;#.amount&quot;,
                        &quot;label&quot;: &quot;Deposit Amount&quot;,
                        &quot;format&quot;: &quot;tokenAmount&quot;,
                        &quot;params&quot;: {
                            &quot;token&quot;: {
                                &quot;map&quot;: &quot;$.metadata.maps.underlyingToken&quot;,
                                &quot;keyPath&quot;: &quot;@.chainId&quot;
                            }
                        }
                    }
                ]
            }
        }
    }
}
```

This example shows a deposit function that takes as only input the amount of a token hardcoded in the contract. The token address deposited changes based on the chain the contract is deployed to. 
The `underlyingToken` map allows defining the hardcoded values of the underlying token based on the chainId of the transaction context (as specified in `&quot;keyPath&quot;: &quot;@.chainId&quot;`). 

**`metadata.enums`**

The `enums` key contains displayable values for parameters that are enumerations (in a loose sense including parameters taking fixed number of well known values). These `enums` are used to replace specific parameter values with a human-readable one. 

Each key of the `enums` object is an *enumeration* name. Enumeration names can be referred to in the `display` section formatters by using a path starting with root node `$.` (i.e. `$.metadata.enums.ENUM_NAME`). 

An enum is a json object with a flat list of key / value pairs, each key being the enumeration *value* to replace, and the value being the display string to use instead of the enumeration value. 

*Examples*

```json
{
    &quot;metadata&quot;: {
        &quot;enums&quot;: {
            &quot;interestRateMode&quot;: {
                &quot;1&quot;: &quot;stable&quot;,
                &quot;2&quot;: &quot;variable&quot;
            }
        }
    }
}
```
This snippet introduces an enumeration describing the displayable values of an integer parameter used to represent multiple modes of interest rates. It can be referenced using the path `$.metadata.enums.interestRateMode`.

```json
{
  &quot;display&quot;: {
    &quot;formats&quot;: {
      &quot;repay(address asset,uint256 amount,uint256 interestRateMode)&quot;: {
        &quot;$id&quot;: &quot;repay&quot;,
        &quot;intent&quot;: &quot;Repay loan&quot;,
        &quot;interpolatedIntent&quot;: &quot;Repay {amount} of {interestRateMode} rate loan&quot;,
        &quot;fields&quot;: [
          {
            &quot;path&quot;: &quot;amount&quot;,
            &quot;format&quot;: &quot;tokenAmount&quot;,
            &quot;label&quot;: &quot;Amount to repay&quot;,
            &quot;params&quot;: { &quot;tokenPath&quot;: &quot;asset&quot; }
          },
          {
            &quot;path&quot;: &quot;interestRateMode&quot;,
            &quot;format&quot;: &quot;enum&quot;,
            &quot;label&quot;: &quot;Interest rate mode&quot;,
            &quot;params&quot;: { &quot;$ref&quot;: &quot;$.metadata.enums.interestRateMode&quot; }
          }
        ]
      }
    }
  }
}
```

In this example, the `interestRateMode` field is formatted using the enumeration defined under `$.metadata.enums.interestRateMode`.

### `Display` section

The `display` section contains the actual formatting instructions for each field of the bound structured data. It is split into two parts, a `display.definitions` key that contains common formats that can be re-used in the other parts and a `display.formats` key containing the actual format instructions for each function / message type bound to the specification file.

**`display.definitions`**

The `definitions` key is an object in which each sub-key is a [*field format specification*](#field-format-specification). The sub-key name is the name of the common definition and is used to refer to this object in the form of a path starting with root node `$.` (i.e. `$.display.definitions.DEF_NAME`).

Definitions don&apos;t usually include the `path` or `value` key of a [*field format specification*](#field-format-specification), since they are intended for re-use in other fields specifications, that will specify locally what path they apply to.

*Example*

```json
{
    &quot;display&quot;: {
        &quot;definitions&quot;: {
            &quot;sendAmount&quot;: {
                &quot;label&quot;: &quot;Amount to Send&quot;,
                &quot;format&quot;: &quot;tokenAmount&quot;,
                &quot;params&quot;: {
                    &quot;tokenPath&quot;: &quot;fromToken&quot;,
                    &quot;nativeCurrencyAddress&quot;: &quot;$.metadata.constants.addressAsEth&quot;
                }
            }
        }
    }
}
```
This snippet defines a common formatter for an amount to send that can be used by a simple reference to the path `$.display.definitions.sendAmount`.

**`display.formats`**

The `formats` key is an object containing the actual information used to format the structured data. It is a json object in which each sub-key is a specific function call (for contracts) or a specific message type (for EIP-712) being described. The values are each a [*structured data format specification*](#structured-data-format-specification).


**Contract keys**

For contract calldata, this specification only covers functions. Each key MUST be a human-readable ABI function fragment that includes parameter names, for example `transfer(address to,uint256 value)` or `submitOrder((address token,uint256 amount) order,bytes32 salt)`.

- Keys MUST use canonical Solidity type names: `uint256`, `bytes32`, `address`, `bool`, tuple syntax `(…)`, dynamic arrays `type[]`, and fixed arrays `type[N]`. Aliases (e.g., `uint`) are NOT permitted, commas MUST NOT be followed by spaces, and there MUST be exactly one space between each type and its parameter name.
- Parameter names in the fragment MUST match the names used throughout the formatting specification; wallets derive all display paths from these names.
- Overloaded functions are distinguished solely by their type signatures. Parameter names do not affect selector matching.

**Selector matching (contracts)**

Wallets MUST match calldata to a `display.formats` entry using the following procedure:
1. Parse the key and drop parameter names to obtain the canonical type-only signature (e.g., `transfer(address,uint256)`).
2. Compute `keccak256(&lt;type-only signature&gt;)[:4]`.
3. Compare the resulting selector to the transaction calldata selector; a match selects the corresponding format specification.

If multiple keys share the same type-only signature, wallets MUST treat this as an invalid descriptor.

**Decoding and parameter names**

Once a format entry is selected, wallets MUST decode calldata arguments using the canonical type vector derived from the key. Parameter names, `fields[].path` entries, and `{placeholders}` in `interpolatedIntent` MUST all use the names from the key (e.g., `value`, `order.amount`, `recipients[0]`).

Paths are relative to the matched function parameters unless prefixed by another root node; for example, `to`, `order.price`, and `recipients[0]` point to decoded arguments, while `@.value` references the transaction container.

Placeholders in strings MUST use `{&lt;path&gt;}` with the same path semantics.

**Unknown selectors**

If no key matches the calldata selector, wallets SHOULD display a safe fallback (for example, &quot;Unknown function&quot; alongside raw arguments) and MUST NOT attempt to apply any unrelated format specifications.

*Minimal contract examples*

```json
{
  &quot;display&quot;: {
    &quot;formats&quot;: {
      &quot;transfer(address to,uint256 value)&quot;: {
        &quot;intent&quot;: &quot;Send&quot;,
        &quot;interpolatedIntent&quot;: &quot;Send {value} to {to}&quot;,
        &quot;fields&quot;: [
          { &quot;path&quot;: &quot;value&quot;, &quot;label&quot;: &quot;Amount&quot;, &quot;format&quot;: &quot;tokenAmount&quot; },
          { &quot;path&quot;: &quot;to&quot;,    &quot;label&quot;: &quot;To&quot;,     &quot;format&quot;: &quot;addressName&quot; }
        ]
      }
    }
  }
}
```

```json
{
  &quot;display&quot;: {
    &quot;formats&quot;: {
      &quot;submitOrder((address token,uint256 amount,uint256 price) order,bytes32 salt)&quot;: {
        &quot;intent&quot;: &quot;Place order&quot;,
        &quot;interpolatedIntent&quot;: &quot;Buy {order.amount} @ {order.price}&quot;,
        &quot;fields&quot;: [
          { &quot;path&quot;: &quot;order.token&quot;,  &quot;label&quot;: &quot;Token&quot;,  &quot;format&quot;: &quot;addressName&quot; },
          { &quot;path&quot;: &quot;order.amount&quot;, &quot;label&quot;: &quot;Amount&quot;, &quot;format&quot;: &quot;number&quot; },
          { &quot;path&quot;: &quot;order.price&quot;,  &quot;label&quot;: &quot;Price&quot;,  &quot;format&quot;: &quot;number&quot; },
          { &quot;path&quot;: &quot;salt&quot;,         &quot;label&quot;: &quot;Salt&quot;,   &quot;format&quot;: &quot;bytes32&quot; }
        ]
      }
    }
  }
}
```

```json
{
  &quot;display&quot;: {
    &quot;formats&quot;: {
      &quot;airdrop(address[] recipients,uint256[3] values)&quot;: {
        &quot;intent&quot;: &quot;Airdrop&quot;,
        &quot;interpolatedIntent&quot;: &quot;Airdrop to {recipients[0]} (+{recipients.length} total)&quot;,
        &quot;fields&quot;: [
          { &quot;path&quot;: &quot;recipients[0]&quot;, &quot;label&quot;: &quot;First recipient&quot;, &quot;format&quot;: &quot;addressName&quot; },
          { &quot;path&quot;: &quot;values[0]&quot;,     &quot;label&quot;: &quot;Tier 1&quot;,          &quot;format&quot;: &quot;tokenAmount&quot; }
        ]
      }
    }
  }
}
```

**EIP-712 keys**

For EIP-712, the key names MUST be the string returned by the `encodeType` function defined in EIP-712 specification applied to the primary type of the message.

During the EIP-712 signature process, wallets will compute the type hash from the message. This type hash MUST match the hash computed from the `display.formats` key in use: `keccak256(encodeType(typeOf(s))) == keccak256(TYPE_KEY)` 

*Example*

In the sample EIP-712 message included in the specification [here](/EIPs/assets/eip-712/Example.js), the key used to describe the message would be the string `Mail(Person from,Person to,string contents)Person(string name,address wallet)`.

#### Structured data format specification

A *Structured data format specification* is used to describe how to format all the fields of a single function or EIP-712 message. It is contained in a single json object under each sub-keys of `display.formats`.

**`$id`**

This key is purely internal and used to specify a human-readable identifier for this specification.

**`intent`** 

Use to specify the *intent* of the function call or message signature in a user-friendly way.

An intent can take two forms:
* A simple string with human-readable content
* A json object with a flat list of string key-value pairs, representing more complex intents. Both keys and values should be human-readable and user-friendly.

Wallets SHOULD use this `intent` value to display a clear intent when reviewing the structured data before signature. When displaying a complex json intent, it is expected that keys represent labels, and values should be displayed after their label. 

```json
{
    &quot;display&quot;: {
        &quot;formats&quot;: {
            &quot;withdraw(uint256)&quot;: {
                &quot;intent&quot;: {
                    &quot;Native Staking&quot;: &quot;Withdraw&quot;,
                    &quot;Rewards&quot;: &quot;Consensus &amp; Exec&quot;
                }
            }
        }
    }
}
```
This snippet defines an intent for a withdrawal function on a contract, with an expectation that the intent would be displayed in a structured way on the wallet screen.

**`interpolatedIntent`**

A string containing an intent description with embedded field values using [interpolation syntax](#value-interpolation).

Wallets MUST display either `interpolatedIntent` strings or screens generated from `intent` and individual `fields`.

Wallets MAY display both fields, with `interpolatedIntent` as the primary description.

Interpolated paths MUST reference fields that have corresponding format specifications in the `fields` array. The formatting applied during interpolation MUST match the formatting that would be applied if the field were displayed separately.

*Example with complex intent:*
```json
{
    &quot;intent&quot;: {
        &quot;Action&quot;: &quot;Approve&quot;,
        &quot;Type&quot;: &quot;Batch&quot;
    },
    &quot;interpolatedIntent&quot;: &quot;Approve {spender} to spend up to {amount} on your behalf until {deadline}&quot;,
    &quot;fields&quot;: [
        {&quot;path&quot;: &quot;spender&quot;, &quot;label&quot;: &quot;Spender&quot;, &quot;format&quot;: &quot;addressName&quot;},
        {&quot;path&quot;: &quot;amount&quot;, &quot;label&quot;: &quot;Amount&quot;, &quot;format&quot;: &quot;tokenAmount&quot;},
        {&quot;path&quot;: &quot;deadline&quot;, &quot;label&quot;: &quot;Deadline&quot;, &quot;format&quot;: &quot;date&quot;}
    ]
}
```

**`fields`**

The `fields` key defines formatting information for individual fields of the structured data (function or message). 

`fields` is an array of elements, each element being either:
  * A single [*field format specification*](#field-format-specification)
  * A reference to a format specification in the `definitions` section: by declaring an object with two keys, a `path` key with the [path](#path-references) to the field being formatted, and a `$ref` key with a path to the internal definition. 
    * A reference object can override a field format specification `params` by including its own `params` sub-key, whose values will take precedence over the common definition
  * A group of fields, defined in [*Group format specification*](#group-format-specification) 

*Grouping* fields allows for both control of the way wallets should order the display of fields and *recursivity* of fields definitions, which can be a more readable form for the 7730 file itself.

*Examples*

Let&apos;s assume the following solidity contract

```solidity
pragma solidity ^0.8.0;

contract MyContract {

    struct MyParamType {
        string name;
        uint256 value;
    }

    // Function declaration
    function myFunction(address account, uint256 amount, MyParamType memory param) public {
        // Function logic here
    }
}
```

The following ERC-7730 shows examples for the three kinds of `fields` options
```json
{
    &quot;display&quot;: {
        &quot;formats&quot;: {
            &quot;myFunction(address account,uint256 amount,(string name,uint256 value) param)&quot; : {
                &quot;fields&quot;: [
                    {
                        &quot;path&quot;: &quot;account&quot;,
                        &quot;$ref&quot;: &quot;$.display.definitions.sendTo&quot;,
                        &quot;params&quot;: { &quot;type&quot;: &quot;eoa&quot; }
                    },
                    {
                        &quot;path&quot;: &quot;amount&quot;,
                        &quot;label&quot;: &quot;Number of items&quot;,
                        &quot;format&quot;: &quot;raw&quot;
                    },
                    {
                        &quot;path&quot;: &quot;param&quot;,
                        &quot;fields&quot;: [
                            { &quot;path&quot;: &quot;name&quot;, &quot;$ref&quot;: &quot;$.display.definitions.itemName&quot; },
                            { &quot;path&quot;: &quot;value&quot;, &quot;$ref&quot;: &quot;$.display.definitions.itemReference&quot; }
                        ]
                    }
                ]
            }
        }
    }
}
```
* The `account` field is an example of an internal reference (reference not included in the example), overriding the reference `type` parameter with another value.
* The `amount` field shows an example of a simple formatter, displaying an int in its natural representation with a label.
* The `param` field shows an example of defining formatters with a recursive structure, ending up defining two embedded formatters for paths `#.param.name` and `#.param.value`

Note that the recursive definition is equivalent to the following definition, which is the preferred form:
```json
{
    &quot;display&quot;: {
        &quot;formats&quot;: {
            &quot;myFunction(address account,uint256 amount,MyParamType param)&quot; : {
                &quot;fields&quot;: [
                    { &quot;path&quot;:&quot;param.name&quot;, &quot;$ref&quot;: &quot;$.display.definitions.itemName&quot; },
                    { &quot;path&quot;:&quot;param.value&quot;, &quot;$ref&quot;: &quot;$.display.definitions.itemReference&quot; }
                ]
            }
        }
    }
}
```


#### Field format specification

A *field format specification* is a json object defining how to format a single field of the structured data.

**`path` / `value`** 

The path is the absolute or relative location of the field in the structured data, following the rules in the [path section](#path-references). Instead of `path`, a literal `value` may be provided to display a constant without looking up a field.

**`label`** 

A displayable string shown before the formatted field value.

**`format`** 

Indicates how the field value must be transformed for display. Supported format identifiers are listed in the [Reference](#field-formats) section.

**`params`** 

Optional object containing formatter-specific parameters. Available parameters are described alongside each format in the [Reference](#field-formats) section.

*Array references in parameters*

When a formatter applies to an array, the parameters CAN also reference a path to an array. In that case, wallets should format each element of the array using the parameter value at the same index as the current element being formatted. Parameter arrays should be the same length as the formatted array else the wallet SHOULD raise an error.

See [example-array-iteration.json](/EIPs/assets/eip-7730/example-array-iteration.json) for examples on array iteration.

**`$id`** 

Optional internal identifier to help authors distinguish or reference the field definition; not intended for end-user display.

**`visible`** 

Optional rule to apply before displaying a field. Rules allow defining under which conditions a field should be displayed. If not specified, the field is assumed to be always visible (ie, default value is `&quot;visible&quot;=&quot;always&quot;`). Current supported rules are:

* A simple string with values among `[never,always,optional]`, with the following meaning   
  * `never&quot;`: Never display this field to users (this field should be *excluded* from the UI).
  * `always`: Always display this field to users (this field is *required*).
  * `optional`: Wallets MAY display this field if possible or sensible.
* An object with keys representing complex rules, with the following complex rules supported:
  * `ifNotIn` key with an array of values to make the field visible only when the field value does NOT match any of the specified values
  * `mustMatch` key with an array of values to make the field always hidden AND check its value against the list. Wallet should raise an error if the value does not match the list.

**`separator`** 

Optional separator string to display before each element of an array. Can only be used be used for formatters that are applied to a path pointing to an array. Each element of the array is formatted using the provided formatter, and the `separator` value is displayed before each element. `separator` is a string using the interpolated syntax with one specific replacement `{index}` that gets replaced with the index of current element being displayed.

**`encryption`**

Optional object indicating the field value is encrypted. When present, it provides all the relevant information on how to handle the decryption process, in particular the encryption scheme used to produce the encrypted value.

An `encryption` key is a json object with:
* A `scheme` key, providing the wallet an hint on encryption scheme used. Refer to [encryption schemes](#encryption-schemes) for reference values.
* A `plaintextType` key providing the solidity type of the decrypted field. The wallet SHOULD verify that the formatter is applicable to the `plaintextType`.
* An optional `fallbackLabel` to display when the wallet cannot decrypt the field.  

Fields MAY declare an `encryption` object to indicate that the on-chain value is an encrypted amount (or a pointer to an encrypted amount), typically a `bytes32`. When decryption is available, wallets SHOULD decrypt first and then apply the field `format` to the plaintext. When decryption is not available, wallets SHOULD display a clear encrypted placeholder (optionally using `fallbackLabel`) and are RECOMMENDED to also show the raw encrypted value (or its pointer), either fully or partially. 

Because encrypted values do not reveal their underlying type on-chain, authors SHOULD provide `plaintextType` so wallets can correctly format decrypted values.

*Example*

```json
{
  &quot;path&quot;: &quot;encryptedAmount&quot;,
  &quot;label&quot;: &quot;Amount&quot;,
  &quot;format&quot;: &quot;tokenAmount&quot;,
  &quot;params&quot;: { &quot;tokenPath&quot;: &quot;@.to&quot; },
  &quot;encryption&quot;: {
    &quot;scheme&quot;: &quot;fhevm&quot;,
    &quot;plaintextType&quot;: &quot;uint64&quot;,
    &quot;fallbackLabel&quot;: &quot;[Encrypted Amount]&quot;
  }
}
```

#### Group format specification 

A *Group format specification* is a json object defining how to format a group of fields of the structured data.

**`path`** 

The absolute or relative path to the field location in the structured data, as described in the [path section](#path-references).

`path` is optional, in which case the group refer to the path of the embedding `fields` definition.

**`label`** 

Optional displayable string that should be shown before displaying the fields described in this group.

**`iteration`** 

Key controlling how arrays in the group should be iterated over when formatting the group. It can only be applied to groups containing arrays.

It supports two modes `sequential` and `bundled`:

* In `sequential` mode, arrays are displayed fully one after the other - array_0[0] array_0[1] .. array_0[N] array_1[0] array_1[1] .. array_1[M]
* In `bundled` mode, elements of the arrays gets bundled together - array_0[0] array_1[0] array_0[1] array_1[1] .. array_0[N] array_1[N]
  * In this mode, the arrays of the group MUST be the same size else the wallet SHOULD return an error 

Defining groups of fields allows for controlling the *order* in which wallets should display fields. Wallets SHOULD display fields in the order in which they appear in the group defintion. For this grouping purpose, the top level [Structured data format specification](#structured-data-format-specification) is also considered a group.

Recursive path references work by concatenating the paths of the parents *structured data format specification*, all the way to the leaf, to build a full reference path to the field being described. The leaf should be either a *field format specification*, or a reference to a *field format specification* in the `definitions` section.

This recursivity allows structuring the ERC-7730 file itself, but is NOT RECOMMENDED. It is expected that resource limited wallets will only support very limited recursivity in the ERC-7730 file itself, so the initial intent of the spec is to &quot;flatten&quot; the list of fields to display using the *path* mechanics. 

See [example-array-iteration.json](/EIPs/assets/eip-7730/example-array-iteration.json) for examples on grouping and group iteration control.

#### Slices in paths

A slice can be applied at the end of paths.

A slice on a primitive type like uint256, bytes and string means that the associated [field format specification](#field-format-specification) MUST only be applied to the corresponding slice of bytes of the underlying data.

A slice on an array type means that the associated [field format specification](#field-format-specification) or recursive [structured data format specification](#structured-data-format-specification) MUST be applied to ALL the array elements part of the slice.

*Example*

```json
{
    &quot;display&quot;: {
        &quot;formats&quot;: {
            &quot;exactOutput((bytes path, address recipient, uint256 deadline, uint256 amountOut, uint256 amountInMaximum) params)&quot;: {
                &quot;fields&quot;: [
                    {
                        &quot;path&quot;: &quot;params.amountInMaximum&quot;,
                        &quot;label&quot;: &quot;Maximum Amount to Send&quot;,
                        &quot;format&quot;: &quot;tokenAmount&quot;,
                        &quot;params&quot;: {
                            &quot;tokenPath&quot;: &quot;params.path.[0:20]&quot;
                        }
                    }
                ]
            }
        }
    }
}
```
The `tokenPath` parameter uses a slice on a `bytes` value, indicating only the first 20 bytes should be taken as the address and used as the reference for the formatting of the corresponding token amount.

```json
{
    &quot;display&quot;: {
        &quot;formats&quot;: {
              &quot;buyOnMySwap(address router,uint256 amountIn,uint256 amountOutMin,address tokenPathStart,uint256[] pools)&quot;: {
                &quot;fields&quot;: [
                    {
                        &quot;path&quot;: &quot;pools.[-1]&quot;,
                        &quot;label&quot;: &quot;Last pool&quot;,
                        &quot;format&quot;: &quot;raw&quot;
                    }
                ]
            }
        } 
    }
}
```
This examples uses an array slice to indicate that only the last element of the `pools` array should be displayed using the `raw` format.

```json
{
    &quot;display&quot;: {
        &quot;formats&quot;: {
            &quot;PermitBatch(PermitDetails[] details,address spender,uint256 sigDeadline)PermitDetails(address token,uint160 amount,uint48 expiration,uint48 nonce)&quot;: {
                &quot;intent&quot;: &quot;Approve token spending&quot;,
                &quot;interpolatedIntent&quot;: &quot;Approve {spender} to spend multiple tokens until {sigDeadline}&quot;,
                &quot;fields&quot;: [
                    {
                        &quot;path&quot;: &quot;details.[]&quot;,
                        &quot;fields&quot;: [
                            {
                                &quot;path&quot;: &quot;amount&quot;,
                                &quot;label&quot;: &quot;Amount allowance&quot;,
                                &quot;format&quot;: &quot;tokenAmount&quot;,
                                &quot;params&quot;: {
                                    &quot;tokenPath&quot;: &quot;token&quot;
                                }
                            },
                            {
                                &quot;path&quot;: &quot;expiration&quot;,
                                &quot;label&quot;: &quot;Approval expires&quot;,
                                &quot;format&quot;: &quot;date&quot;,
                                &quot;params&quot;: {
                                    &quot;encoding&quot;: &quot;timestamp&quot;
                                }
                            }
                        ]
                    },
                    {
                        &quot;path&quot;: &quot;spender&quot;,
                        &quot;label&quot;: &quot;Spender&quot;,
                        &quot;format&quot;: &quot;addressName&quot;
                    },
                    {
                        &quot;path&quot;: &quot;sigDeadline&quot;,
                        &quot;label&quot;: &quot;Signature Deadline&quot;,
                        &quot;format&quot;: &quot;date&quot;,
                        &quot;params&quot;: {
                            &quot;encoding&quot;: &quot;timestamp&quot;
                        }
                    }
                ]
            }
        }
    }
}
```
This example uses a full array selector `details.[]` to apply the list of the underlying two underlying formats to ALL the elements of the `details` array.

#### Embedded Calldata

Embedded calldata is used when a parameter of a smart contract function contains the calldata for another function call to a smart contract.
This pattern is common in contract interactions where one function call triggers another function call as part of its execution.
For example, the `permitAndCall` function verifies a permit and then executes another function within the same contract using the provided embedded calldata.
Here is an example of how to format embedded calldata:&quot;

```json
{
    &quot;display&quot;: {
        &quot;formats&quot;: {
            &quot;permitAndCall(bytes permit,bytes action)&quot;: {
                &quot;intent&quot;: &quot;Execute with permit&quot;,
                &quot;fields&quot;: [
                    {
                        &quot;path&quot;: &quot;action&quot;,
                        &quot;label&quot;: &quot;Swap&quot;,
                        &quot;format&quot;: &quot;calldata&quot;,
                        &quot;params&quot;: {
                            &quot;calleePath&quot;: &quot;@.to&quot;,
                        }
                    }
                ],
                &quot;required&quot;: [&quot;action&quot;],
                &quot;excluded&quot;: [&quot;permit&quot;]
            }
        }
    }
}
```

In this example, the `permitAndCall` function accepts two parameters: `permit` and `action`.
The `action` parameter contains the calldata for a subsequent function call.
The `format` field is set to `calldata`, instructing the wallet to interpret the action parameter as embedded calldata.
The `calleePath` parameter defines the path to the address of the target contract, while the optional `selector` parameter specifies the function selector if it is not the first 4 bytes of the calldata.
When displaying the transaction, the wallet will attempt to resolve an ERC-7730 descriptor for the embedded calldata using the callee address and the selector.
In some cases, embedded calldata may require a transaction value and/or a spender to be properly clear-signed, as the underlying function might rely on a value passed from the parent transaction (e.g., for swaps or staking).
To handle this, the `amountPath` and/or `spenderPath` parameters can be used to specify these values explicitly.

```json
{
    &quot;display&quot;: {
        &quot;formats&quot;: {
            &quot;permitAndCall(bytes permit,address target,bytes action)&quot;: {
                &quot;intent&quot;: &quot;Execute with permit&quot;,
                &quot;fields&quot;: [
                    {
                        &quot;path&quot;: &quot;action&quot;,
                        &quot;label&quot;: &quot;Swap&quot;,
                        &quot;format&quot;: &quot;calldata&quot;,
                        &quot;params&quot;: {
                            &quot;calleePath&quot;: &quot;target&quot;,
                            &quot;amountPath&quot;: &quot;@.value&quot;,
                            &quot;spenderPath&quot;: &quot;@.to&quot;
                        }
                    }
                ],
                &quot;required&quot;: [&quot;action&quot;, &quot;target&quot;],
                &quot;excluded&quot;: [&quot;permit&quot;]
            }
        }
    }
}
```

### Reference

### Container structure values

This section describes all container structure supported by this specification and possible references path to relevant values.

#### EVM Transaction container

| Value reference | Value Description |
|-----------------|-------------------|
| @.from          | The address of the sender of the transaction |
| @.value         | The native currency value of the transaction |
| @.to            | The destination address of the containing transaction, ie the target smart contract address |
| @.chainId       | The chainId of the transaction               |

#### EIP-712 container

| Value reference | Value Description |
|-----------------|-------------------|
| @.from          | The address of the signer of the message |
| @.value         | EIP-712 have no underlying currency value transferred, so a wallet MAY interpret it as 0 |
| @.to            | The verifying contract address, when known. If not known a wallet SHOULD reject using the ERC-7730 file to clear sign the message |
| @.chainId       | The chainId of the verifying contract, when known. If not known a wallet SHOULD reject using the ERC-7730 file to clear sign the message. |

### Field formats

In the following references, the format title is the value to use under the `format` key of a [*field format specification*](#field-format-specification).


#### Integer formats

Formats applicable to `uint`/`int` solidity types. 

| **`raw`**     |                                                                       |
|---------------|-----------------------------------------------------------------------|
| *Description* | Display the integer as a raw int in natural, localized representation |
| *Parameters*  | None                                                                  |
| *Examples*    | Value 1000 displayed as `1000`                                        |

| **`amount`**  |                                                                              |
|---------------|------------------------------------------------------------------------------|
| *Description* | Display as an amount in native currency, using best ticker / magnitude match |
| *Parameters*  | None                                                                         |
| *Examples*    | Value 0x2c1c986f1c48000 is displayed as `0.19866144 ETH`                     |

| **`tokenAmount`**          |              |
|----------------------------|--------------|
| *Description*              | Convert value using token decimals, and append token ticker name. If value is above optional `threshold`, display instead `message` with ticker. |
| *Parameters*               | --- |
| `tokenPath` or `token`     | Path reference, or constant value for the address of the token contract. Used to associate correct ticker. If ticker is not found or `tokenPath`/`token` is not set, the wallet SHOULD display the raw value instead with an &quot;Unknown token&quot; warning |
| `nativeCurrencyAddress`    | Either a string or an array of strings. If the address pointed to by `tokenPath` is equal to one of the addresses in `nativeCurrencyAddress`, the tokenAmount is interpreted as expressed in native currency |
| `threshold`                | integer value, above which value is displayed as a special message. Optional |
| `message`                  | message to display above threshold. Optional, defaults to &quot;Unlimited&quot; |
| `chainIdPath` or `chainId` | Optional. The chain on which the token is deployed (constant or path). When present, the wallet SHOULD resolve token metadata (ticker, decimals) for this chain. Useful for cross-chain swap clear signing where the same token address may refer to different chains. At most one of `chainId` and `chainIdPath` may be set. |
| *Examples*                 | --- |
| `1 DAI`                    | Field value = 1000000 &lt;br&gt; `tokenPath` =0x6B17...1d0F (DAI, 6 decimals) |
| `Unlimited DAI`            | Field value = 0xFFFFFFFF &lt;br&gt; `token` =0x6B17...1d0F (DAI, 6 decimals) &lt;br&gt; `threshold` &quot;0xFFFFFFFF&quot; |
| `Max DAI`                  | Field value = 0xFFFFFFFF &lt;br&gt; `tokenPath` =0x6B17...1d0F (DAI, 6 decimals) &lt;br&gt; `threshold` &quot;0xFFFFFFFF&quot; &lt;br&gt; `message` = &quot;Max&quot; |
| `0.002 ETH`                | Field value = 2000000000000000 &lt;br&gt; `tokenPath` = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE &lt;br&gt; `nativeCurrencyAddress` = [&quot;0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE&quot;] |

| **`nftName`**                                              |                                                                                                               |
|------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------|
| *Description*                                              | Display value as a specific NFT in a collection, if found by wallet, or fallback to a raw int token ID if not |
| *Parameters*                                               | ---                                                                                                           |
| `collectionPath` or `collection`                           | A path reference, or constant value for the collection address                                                |
| *Examples*                                                 | ---                                                                                                           |
| `Collection Name: BoredApeYachtClub` &lt;br&gt; `Token ID: 1036` | Field Value = 1036 &lt;br&gt; `collectionPath` = &quot;&quot;0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D                       |

| **`date`**                  |                                                                                           |
|-----------------------------|-------------------------------------------------------------------------------------------|
| *Description*               | Display int as a date, using specified encoding. Date display RECOMMENDED use of RFC 3339 |
| *Parameters*                | ---                                                                                       |
| `&quot;encoding&quot;: &quot;timestamp&quot;`   | value is encoded as a unix timestamp                                                      |
| `&quot;encoding&quot;: &quot;blockheight&quot;` | value is a blockheight and is converted to an approximate unix timestamp                  |
| *Examples*                  | ---                                                                                       |
| `2024-02-29T08:27:12`       | Field Value = 1709191632 &lt;br&gt; `encoding` = &quot;timestamp&quot;                                    |
| `2024-02-29T09:00:35`       | Field Value = 19332140 &lt;br&gt; `encoding` = &quot;blockheight&quot;                                    |

| **`duration`** |                                                                                         |
|----------------|-----------------------------------------------------------------------------------------|
| *Description*  | Display int as a duration interpreted in seconds and represented as a duration HH:MM:ss |
| *Parameters*   | None                                                                                    |
| *Examples*     | ---                                                                                     |
| `02:17:30`     | Field Value = 8250                                                                      |

| **`unit`**    |                   |
|---------------|-------------------|
| *Description* | Value is converted to a float using `decimals` (`value / 10^decimals`) and displayed appending the corresponding unit. If `prefix` is true, the value is further converted to scientific representation, minimizing the significand and converting the exponent to an SI prefix added in front of the unit symbol |
| *Parameters*  | --- |
| `base`        | The symbol of the base unit, an SI unit or other acceptable symbols like &quot;%&quot;, &quot;bps&quot; |
| `decimals`    | Number of decimals in integer representation, defaults to 0 |
| `prefix`      | A boolean indicating whether an SI prefix should be appended, defaults to `False` |
| *Examples*    | --- |
| `10h`         | Field Value = 10 &lt;br&gt; `base` = &quot;h&quot; |
| `1.5d`        | Field Value = 15 &lt;br&gt; `base` = &quot;d&quot; &lt;br&gt; `decimals` = 1 |
| `36ks`        | Field Value = 36000 &lt;br&gt; `base` = &quot;s&quot; &lt;br&gt; `prefix` = True |

| **`enum`**    |                                                                                            |
|---------------|--------------------------------------------------------------------------------------------|
| *Description* | Value is converted using referenced constant enumeration values                            |
| *Parameters*  | ---                                                                                        |
| `$ref`        | An internal path (starting with root node `$.`) to an enumerations in `metadata.enums` |
| *Examples*    |                                                                                            |

| **`chainId`**      |                                                                                            |
|--------------------|--------------------------------------------------------------------------------------------|
| *Description*      | Value is converted to a Blockchain name using EIP-155 reference values                     |
| *Parameters*       | None                                                                                       |
| *Examples*         |                                                                                            |
| `Ethereum Mainnet` | Field Value = 1                                                                         |


#### String formats

Formats applicable to for `string` solidity type.

| **`raw`**     |                                               |
|---------------|-----------------------------------------------|
| *Description* | Display as an UTF-8 encoded string            |
| *Parameters*  | None                                          |
| *Examples*    | ---                                           |
| `Ledger`      | Field Value = [&apos;4c&apos;,&apos;65&apos;,&apos;64&apos;,&apos;67&apos;,&apos;65&apos;,&apos;72&apos;] |

#### Bytes formats

Formats applicable to `bytes` solidity type.

| **`raw`**     |                                                |
|---------------|------------------------------------------------|
| *Description* | Display byte array as an hex-encoded string    |
| *Parameters*  | None                                           |
| *Examples*    | ---                                            |
| `123456789A`  | Field Value = Value [&apos;12&apos;,&apos;34&apos;,&apos;56&apos;,&apos;78&apos;,&apos;9a&apos;] |

| **`calldata`**              |                        |
|-----------------------------|------------------------|
| *Description*               | Contains a call to another smart contract or to another function within the same contract. To resolve an ERC-7730 descriptor for this embedded calldata, use the `callee` and `selector` parameters. If no matching ERC-7730 descriptor is found or if the wallet does not support embedded calldata, it MAY display a hash of the embedded calldata instead, with target `calleePath` resolved to a trusted name if possible. |
| *Parameters*                | --- |
| `calleePath` or `callee`    | A path reference or a constant value specifying the address of the contract being called. |
| `selectorPath` or `selector`| Optional. If omitted, the first 4 bytes of the calldata are used as the selector. |
| `chainIdPath` or `chainId`  | Optional. Specifies the chain ID if it differs from the current contract’s chain. |
| `amountPath` or `amount`    | Optional. Specifies the native currency amount associated with the calldata, if applicable. If provided, the ERC-7730 descriptor for this embedded calldata MAY reference this value using the `@.value` container path. |
| `spenderPath` or `spender`  | Optional. Specifies the spender address associated with the calldata, if applicable. If provided, the ERC-7730 descriptor for this embedded calldata MAY reference this value using the `@.from` container path. |
| *Examples*                  | --- |

#### Address

Formats applicable to `address` solidity type.

| **`raw`**       |                                                                                              |
|-----------------|----------------------------------------------------------------------------------------------|
| *Description*   | Display address as an [EIP-55](/EIPs/EIPS/eip-55) formatted string. Truncation is device dependent |
| *Parameters*    | None                                                                                         |
| *Examples*      | ---                                                                                          |
| `0x5aAe...eAed` | Field Value 0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed                                       |

| **`addressName`**       |                    |
|-------------------------|--------------------|
| *Description*           | Display address as a trusted name if a trusted source exists, an EIP-55 formatted address otherwise. See [next section](#address-types-and-sources) for a reference of trusted sources |
| *Parameters*            | --- |
| `types`                 | An array of expected types of the address (see [next section](#address-types-and-sources)). If set, the wallet SHOULD check that the address matches one of the types provided |
| `sources`               | An array of acceptable sources for names (see [next section](#address-types-and-sources)). If set, the wallet SHOULD restrict name lookup to relevant sources |
| `senderAddress`         | Either a string or an array of strings. If the address pointed to by `addressName` is equal to one of the addresses in `senderAddress`, the addressName is interpreted as the sender referenced by `@.from` |
| *Examples*              | --- |
| `vitalik.eth`           | Field Value 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 &lt;br&gt; `types` = [&quot;eoa&quot;] (Externally Owned Account) &lt;br&gt; `sources` = [&quot;ens&quot;] (Ethereum Name Service) |
| `Uniswap V3: WBTC-USDC` | Field Value 0x99ac8cA7087fA4A2A1FB6357269965A2014ABc35 &lt;br&gt; `types` = [&quot;contract&quot;] |
| `Sender`                | Field Value 0x0000000000000000000000000000000000000000 &lt;br&gt; `senderAddress` = [&quot;0x0000000000000000000000000000000000000000&quot;] &lt;br&gt; `types` = [&quot;eoa&quot;] |

---
| **`tokenTicker`**          |                                                                                              |
|----------------------------|----------------------------------------------------------------------------------------------|
| *Description*              | Display address as an [ERC-20](/EIPs/EIPS/eip-20) token ticker                                     |
| *Parameters*               | ---                                                                                          |
| `chainIdPath` or `chainId` | Optional. The chain on which the token is deployed (constant or path). When present, the wallet SHOULD resolve the token ticker for this chain. Useful for cross-chain swap clear signing. At most one of `chainId` and `chainIdPath` may be set. |
| *Examples*                 | ---                                                                                          |
| `MYTOKEN`                  | Field Value 0xaabbccddeeff....                                                               |


#### Interoperable addresses

Interoperable address format applicable to solidity type `bytes`.

| **`interoperableAddressName`**       |                    |
|-------------------------|--------------------|
| *Description*           | Display bytes as an [ERC-7930](/EIPs/EIPS/eip-7930) Interoperable Name. The wallet SHOULD parse the binary format, extract the target address and chain, and display it in the standard `&lt;address&gt; @ &lt;chain&gt; # &lt;checksum&gt;` format. |
| *Parameters*            | --- |
| `types`                 | An array of expected types of the address (see [next section](#address-types-and-sources)). If set, the wallet SHOULD check that the address matches one of the types provided |
| `sources`               | An array of acceptable sources for names (see [next section](#address-types-and-sources)). If set, the wallet SHOULD restrict name lookup to relevant sources |
| `senderAddress`         | Either a string or an array of strings. If the address pointed to by `addressName` is equal to one of the addresses in `senderAddress`, the addressName is interpreted as the sender referenced by `@.from` |
| *Examples*              | --- |
| `0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045@eip155:1#4CA88C9C` | Field Value = `0x00010000010114D8DA6BF26964AF9D7EED9E03E53415D37AA96045` |

#### Address types and sources

Address names trusted sources specify which type and source of trusted names SHOULD be used to replace an address with a human-readable names. 

When specified a wallet MUST only use specified sources to resolve address names. Wallet MUST verify the type of the address if able to. 

When omitted, a wallet MAY use any source to resolve an address.

| Address type | Description                                    |
|--------------|------------------------------------------------|
| wallet       | Address is an account controlled by the wallet |
| eoa          | Address is an Externally Owned Account         |
| contract     | Address is a well known smart contract         |
| token        | Address is a well known ERC-20 token           |
| collection   | Address is a well known NFT collection         |

A wallet MAY verify that a `wallet` address is in fact controlled by the wallet, and reject signing if not the case.

Sources values are wallet manufacturer specific. Some example values could be:

| Source type | Description                                                                                                                        |
|-------------|------------------------------------------------------------------------------------------------------------------------------------|
| local       | Address MAY be replaced with a local name trusted by user. Wallets MAY consider that `local` setting for `sources` is always valid |
| ens         | Address MAY be replaced with an associated ENS domain                                                                              |


### Encryption schemes

List of currently supported encryption schemes hints for fields

| Scheme        | Description                       |
| ------------- | --------------------------------- |
| fhevm         | FHEVM full homomorphic encryption |

## Rationale

### Human readability

It is expected that the main limitation to adoption of ERC-7730 will be the complexity of writing this interface description file compared to interest of writing it.

This drove a few choices when introducing this ERC specification:
* The form of an ERC itself will allow usage of these file by any wallets (Hardware or Software, without restrictions), and in turn drive up the benefits for app developers to provide their own ERC-7730 description
* The specification is intended to be directly readable by developers, in order to facilitate direct edition by developers.
* In addition, a set of edition tools will be created and open sourced to ease visualization of the results for end users

### Wallet limitations

Wide support by wallets is key for adoption of this specification. 

Hardware wallets tend to have more limited capabilities that will impact what they can display securely, especially since the intention of the specification is to create a strong security binding between the spec and the data being reviewed.

This consideration is driving a few choices done for ERC-7730:
* Complex UI constructs like layouts, grouping and re-ordering of fields have been left to a wallet specific section, yet unspecified. After a time, we may see patterns emerge between wallets in terms of minimal features.
* Representation of fields has been created to allow &quot;flattening&quot; the list of fields, when handling complex message structures. This flattened representation is expected to work better with Hardware wallets in particular, and is recommended at first.
* Some formatters that require recursive constructs, like `calldata` are expected to work with restrictions at first, especially on Hardware wallets.

### Internationalization

This specification intentionally does not address internationalization or localization of displayable strings.

All display strings in ERC-7730 files—including intents, labels, field names, and enumeration values—are expected to be authored in English.

Future versions of this specification may consider standardized internationalization support once the base standard achieves wider adoption and the ecosystem can better assess the need for multilingual support.

### User Operations (EIP-4337)

Clear signing [EIP-4337](/EIPs/EIPS/eip-4337) User Operations is supported using the `PackedUserOperation` EIP-712 signature format. See [example-userops-eip-712.json](/EIPs/assets/eip-7730/example-userops-eip712.json) for a reference implementation.

The inner calldata typically contains an `execute` call to interact with other contracts. This can be clear signed using a separate ERC-7730 file - see [example-account-execute.json](/EIPs/assets/eip-7730/example-account-execute.json). Since execute functions are implementation-specific, each smart wallet will need its own ERC-7730 file.

Smart wallets commonly use a proxy pattern. Refer to the [Proxy support](#proxy-support) section for guidance. 

### Batch transactions (EIP-5792)

When displaying batch transactions as defined in [EIP-5792](/EIPs/EIPS/eip-5792), wallets SHOULD either:
* Concatenate the `interpolatedIntent` strings of individual operations using &quot; and &quot; as a separator to create a single, human-readable description of the entire batch.
* Concatenate screens generated using `intent` and required `fields`, clearly separating individual transactions

The `interpolatedIntent` approach provides users with a clear, natural language summary of complex multi-step operations without requiring them to mentally piece together separate transaction descriptions. The `intent` approach provide a more controllable wallet UI for space limited wallets.

*Permit + Swap example:*
```json
[
    {
        &quot;function&quot;: &quot;permit&quot;,
        &quot;interpolatedIntent&quot;: &quot;Approve {spender} to spend {value} USDC&quot;
    },
    {
        &quot;function&quot;: &quot;swapExactTokensForTokens&quot;,
        &quot;interpolatedIntent&quot;: &quot;Swap {amountIn} for at least {amountOutMin}&quot;
    }
]
```
Combined display: **&quot;Approve Uniswap Router to spend 1000 USDC and Swap 1000 USDC for at least 0.25 WETH&quot;**

*Approve + Swap example:*
```json
[
    {
        &quot;function&quot;: &quot;approve&quot;,
        &quot;interpolatedIntent&quot;: &quot;Approve {_spender} to spend {_value}&quot;
    },
    {
        &quot;function&quot;: &quot;exactInputSingle&quot;,
        &quot;interpolatedIntent&quot;: &quot;Swap {amountIn} for at least {amountOutMinimum}&quot;
    }
]
```
Combined display: **&quot;Approve Uniswap V3 Router to spend 5000 DAI and Swap 5000 DAI for at least 1.2 ETH&quot;**

*Approve + Swap + Mint NFT example:*
```json
[
    {
        &quot;function&quot;: &quot;approve&quot;,
        &quot;interpolatedIntent&quot;: &quot;Approve {_spender} to spend {_value}&quot;
    },
    {
        &quot;function&quot;: &quot;swapExactTokensForETH&quot;,
        &quot;interpolatedIntent&quot;: &quot;Swap {amountIn} for at least {amountOutMin} ETH&quot;
    },
    {
        &quot;function&quot;: &quot;mint&quot;,
        &quot;interpolatedIntent&quot;: &quot;Mint {quantity} NFT(s) from {collection}&quot;
    }
]
```
Combined display: **&quot;Approve DEX Router to spend 2000 USDC and Swap 2000 USDC for at least 0.5 ETH and Mint 2 NFT(s) from NftProject&quot;**

**Implementation guidance for batch transactions using interpolatedIntents**

Wallets implementing batch transaction display SHOULD:
1. Process each transaction in the batch to generate its `interpolatedIntent`
2. Join the resulting intent strings with &quot; and &quot; (note the spaces)
3. Display the combined string as a single transaction summary
4. Provide a way for users to view individual transaction details if needed
5. Fall back to displaying individual `intent` fields if any `interpolatedIntent` processing fails

Wallets MAY:
- Apply additional formatting (e.g., capitalizing the first letter, adding a period at the end)
- Truncate very long combined intents and provide expansion UI
- Group related operations visually while still showing the combined intent

### Extensibility to other structured data formats

In the future, this specification could be extended to structured data like Meta Transaction in [EIP-2771](/EIPs/EIPS/eip-2771), User Operations in [EIP-4337](/EIPs/EIPS/eip-4337), and batch transaction payloads in [EIP-5792](/EIPs/EIPS/eip-5792).

The `interpolatedIntent` field is particularly well-suited for [EIP-5792](/EIPs/EIPS/eip-5792) batch transactions, as it enables wallets to concatenate multiple operation descriptions into a single, natural language sentence. By joining individual `interpolatedIntent` strings with &quot; and &quot;, wallets can provide users with clear, readable summaries of complex multi-step operations like &quot;Approve Uniswap Router to spend 1000 USDC and Swap 1000 USDC for at least 0.25 WETH&quot;. This significantly improves the user experience when reviewing batch transactions compared to displaying separate, disconnected operation descriptions. See the [Value Interpolation](#value-interpolation) section for detailed implementation guidance and examples.

### Common keywords
The DeFi ecosystem has matured and has some repeating usecases with well defined terms for different actions. While this ERC does not define specific standards for DEX or Lending protocol intents, for the sake of easier user readibility, teams with similar products should align on similar terminology to describe actions and actors. We encourage the creation of another layer of standardization on top of ERC-7730 to be recommeneded and even enforced in clear signing registries for improved user security.

## Test Cases

More examples can be found in the asset folder.

| File name | Description |
| --- | ---|
| [example-main.json](/EIPs/assets/eip-7730/example-main.json) | Simple example of a basic ERC-7730 file |
| [example-erc-20.json](/EIPs/assets/eip-7730/example-erc20.json) | Simple example of defining an interface for ERC-20 contracts |
| [example-include.json](/EIPs/assets/eip-7730/example-include.json) | Example of including an interface into another ERC-7730 file |
| [example-eip-712.json](/EIPs/assets/eip-7730/example-eip712.json) | Clear signing EIP-712 example |
| [example-array-iteration.json](/EIPs/assets/eip-7730/example-array-iteration.json) | Examples of various array iteration modes and field grouping features |
| [example-maps.json](/EIPs/assets/eip-7730/example-maps.json) | Example of maps of constants |
| [example-maps-pools.json](/EIPs/assets/eip-7730/example-maps-pools.json) | Example of maps of constants |
| [example-visibility-rules.json](/EIPs/assets/eip-7730/example-visibility-rules.json) | Example of controlling the visibility of fields |
| [example-account-execute.json](/EIPs/assets/eip-7730/example-account-execute.json) | Example of EIP-4337 smart wallet execute function clear signing |
| [example-userops-eip-712.json](/EIPs/assets/eip-7730/example-userops-eip712.json) | Example of EIP-4337 User Operation clear signing |


## Security Considerations

ERC-7730 creates a risk surface where malicious actors could abuse formatting to make unsafe transactions appear benign. In addition to misapplied or malformed files, implementers should anticipate phishing techniques such as (a) parameter injection using legitimate, high-profile contract formats, (b) registry poisoning with well-formed but misleading entries, and (c) front-end/CDN compromise that prompts signatures for unexpected contracts or parameters.

### Binding context

The binding `context` mitigates misuse by specifying exactly which structured data a given ERC-7730 file may format. app developers MUST set restrictive constraints; wallets MUST verify all constraints and ensure formatting is cryptographically bound to the reviewed data and not tamperable in transit (including on resource-constrained hardware wallets).

### Registry poisoning

Curation and registry of ERC-7730 files are out of scope for this specification, but any external registry or wallet ecosystem MUST assume it will be targeted. A secure registry should (a) require cryptographically verifiable provenance and attestations for each ERC-7730 file and its maintainer, (b) keep a public, tamper-evident history of submissions, approvals, and revocations, (c) implement a mechanism to credibly link contract ownership or authority to the submitted file, and (d) adopt a clear governance model with multi-party sign-off and automated monitoring to detect anomalies or mass poisoning attempts. These measures mitigate attacks on ERC-7730 files in transit and make registry compromise significantly harder without constraining this ERC itself.

### External data resolution

ERC-7730 formatting relies on resolving various external data sources to provide human-readable information. This resolution introduces trust assumptions that wallets must understand when showing ERC-7730 information.

**Trust assumptions**

The transition from transaction data to human readable data requires trust in external data sources to resolve some parts of the presentation layer. Without the resolution, it&apos;s not readable and missed the whole point of the ERC, with the resolution it adds a risk factor:
- **Token metadata** (tickers, decimals) A token address translated to a token ticker and proper decimals applied to the `tokenAmount`.
- **NFT collection names** and token metadata for the `nftName` format
- **Address resolution** when formatting `addressName` using ENS or similar tools

Malicious or compromised data sources could:
- Display incorrect token names, leading users to believe they are approving transactions for legitimate tokens when they are not
- Display malicious addresses as if it is a trusted address name
- Present fake NFT collection names to obscure the true nature of transactions
- Provide misleading enumeration values that misrepresent transaction parameters
- Supply modified ABIs that change how transaction data is interpreted

**Example attack scenarios**

1. **Token name spoofing**: A malicious ERC-7730 file references a fake token contract at address `0x1234...` that returns &quot;USDT&quot; as its ticker and 6 decimals, making a transaction appear to transfer legitimate USDT when it actually transfers a worthless token.

2. **Address name substitution**: A compromised ENS resolver returns a malicious address naming resolution causing a send to an address not anticipated

**Mitigations**

Wallets SHOULD:
- Maintain curated lists of well-known addresses (tokens, contracts, collections) and warn users when encountering unknown entities
- Display full addresses alongside resolved names in some form
- Clearly indicate the source and trust level of resolved names and metadata

Wallets MUST:
- Display clear warnings when external data cannot be resolved or verified (e.g., &quot;Unknown token&quot;)
- Never fallback to presenting untrusted information as if it was trusted and verified

### Proxy support

The proxy pattern is widely use in Ethereum in multiple scenarios to provide flexibility to essentially immutable contracts:
* Making smart contracts *upgradable*
* Making smart contracts *composable*
* Creating multiple *instances* of a reference implementation 

These patterns are often used in conjunction. Supporting those patterns require some considerations from both smart contract developers and wallets.

**Upgradeable proxy contracts**

Upgradeable proxy contracts (such as Transparent Proxies or UUPS proxies as defined in [EIP-1822](/EIPs/EIPS/eip-1822)) use a fixed proxy address that delegates calls to a replaceable implementation contract. For these contracts, the ERC-7730 file SHOULD be bound to the *proxy* address, since this is the stable address users interact with.

When an upgrade introduces breaking ABI changes (new functions, modified signatures, or removed functions), developers SHOULD update the ERC-7730 file in the registry accordingly. Since the old implementation is no longer callable after the upgrade, the previous ERC-7730 definitions can be safely replaced.

Wallets need to ensure they use the latest version of the registry and match the transaction target against the *proxy* address.

**Composable contracts**

Composable contracts, like Diamond proxies, aggregate through a single *proxy* address, multiple implementation facets. Each facet has its own ABI.

A good pattern to support diamond proxies is to introduce an ERC-7730 file for each facet, without any context info, and use the composability of ERC-7730 files to create an overarching ERC-7730 file that includes all implemented facets of a proxy and bound to the final *proxy* address.

Similarly wallets just need to ensure they have the latest version of the registry and that the target address is the *proxy* address.

**Multi-instanciation**

This pattern is typically used by smart wallet factories to efficiently deploy many smart wallets relying on a single, secure implementation.

It is not efficient nor advisable to deploy an ERC-7730 for *each* smart wallet address. In this case, it is recommended to bind the ERC-7730 file to the *implementation* address of the smart wallet and rely on the user&apos;s wallet to detect that the target address is actually a proxy to a well known implementation address.

### Interpolated intent security

The `interpolatedIntent` feature introduces additional attack surfaces that wallets MUST mitigate:

**Injection attacks**

Malicious contracts could craft parameter values that, when interpolated, create misleading intent descriptions. For example:
- A token name containing &quot;to vitalik.eth&quot; could make &quot;Send {amount} to {recipient}&quot; appear as &quot;Send 100 USDT to vitalik.eth to 0x123...&quot;
- Addresses with misleading ENS names could obscure the true destination
- Very long formatted values could push critical information off-screen

*Mitigations:*
- Wallets MUST apply the same formatting and validation to interpolated values as they would for separately displayed fields
- Wallets MUST validate that ENS names and other address labels are verified before interpolation
- Wallets SHOULD display field values separately in addition to the interpolated intent, or provide easy access to detailed field view

**Format consistency**

Wallets MUST ensure that the formatting applied during interpolation exactly matches the formatting that would be applied if the field were displayed separately. This prevents attackers from exploiting differences in formatting to hide malicious values.

*Implementation requirement:*
- The interpolation engine MUST use the same formatter functions and parameters specified in the corresponding field format specification
- If a path in `interpolatedIntent` does not have a corresponding field format specification, interpolation MUST fail and fall back to `intent`

**Path validation**

Wallets MUST validate that all paths in interpolation expressions:
1. Follow the [path reference rules](#path-references)
2. Reference fields that exist in the structured data being signed
3. Have corresponding field format specifications in the `fields` array
4. Do not create circular references or unbounded recursion

**Fallback behavior**

If interpolation fails for any reason (invalid path, formatting error, missing field specification, validation failure), wallets MUST:
1. Fall back to displaying the static `intent` field
2. Display all fields separately according to their field format specifications
3. NOT attempt to partially process the interpolated intent
4. Optionally warn the user that the dynamic description could not be generated

**Resource constraints**

Hardware wallets and other resource-constrained devices MAY choose not to implement `interpolatedIntent` support. The `intent` field MUST always be present as a fallback for such devices.

**Testing and validation**

ERC-7730 file authors SHOULD test `interpolatedIntent` strings with:
- Minimum and maximum expected values for each interpolated field
- Edge cases like zero amounts, maximum allowances, expired dates
- Long addresses, token names, and other string fields to ensure proper truncation

### Encryption support

**Display pointers to encrypted values**

Pointers to encrypted values MAY NOT be fully opaque handles, e.g. they MAY use meaningful prefixes or suffixes containing metadata about the encrypted value. When only partially displaying pointers, wallets SHOULD NOT display these structured parts so that users can discriminate different encrypted values.

### Future work

Future improvements could bind frontends to verified contract manifests so that a compromised UI cannot silently substitute a different contract. Clear, auditable registry governance (multi-party signoff, monitoring, and revocation) can further raise the cost of phishing, parameter injection, and front-end compromise attacks.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 07 Feb 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7730</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7730</guid>
      </item>
    
      <item>
        <title>Enshrined Proposer-Builder Separation</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7732-enshrined-proposer-builder-separation-epbs/19634</comments>
        
        <description>## Abstract

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 *builders* and adding a new duty (submitting *payload timeliness attestations*) to Ethereum validators. The `ExecutionPayload` field of the `BeaconBlockBody` is removed and instead it is replaced by a signed commitment (a `SignedExecutionPayloadBid` object) from a builder to later reveal the corresponding execution payload. This commitment specifies in particular the blockhash of the execution block and a *value* to be paid to the beacon block proposer. When processing the `BeaconBlock`, the committed value is deducted from the builder&apos;s beacon chain balance and later a withdrawal is placed to an address, of the proposer&apos;s choosing, in the execution layer. A subset of validators in the beacon committee is assigned to the *Payload Timeliness Committee* (PTC), these validators are tasked to attest (by broadcasting a `PayloadAttestationMessage`) 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&apos;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 *promises* to be fulfiled elsewhere. 

## Motivation

This EIP solves a different set of unrelated important problems. 

- An overwhelming majority of beacon block proposers outsource the construction of the execution payload within their blocks to a third party (henceforth called a *builder*). In order to do so, they request the hash tree root (HTR) of a promised execution payload and submit a `SignedBlindedBeaconBlock` 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&apos;s actions and that the honest builder&apos;s payload will be the canonical head of the chain regardless of the proposer&apos;s action. 
- 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&apos;s reveal time and the next attestation deadline). 
- By removing the full execution payload size from the consensus block, it allows for faster network propagation on the critical path. 
- 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. 
- It prevents validators from missing attestations and strengthens the weight properties of fork choice in the event that builders produce invalid payloads. 
- It removes the need to use trusted middleware in order to delegate block construction to a builder.

## Specification

### Execution Layer

No changes are required. 

### Consensus Layer

The full consensus changes can be found in the consensus-specs Github repository. They are split between: 

- [Beacon Chain](https://github.com/ethereum/consensus-specs/blob/c94138e73e0e70eb4b27f9be4d4e9325fa1aebf7/specs/gloas/beacon-chain.md) changes.
- [Fork choice](https://github.com/ethereum/consensus-specs/blob/c94138e73e0e70eb4b27f9be4d4e9325fa1aebf7/specs/gloas/fork-choice.md) changes.
- [P2P](https://github.com/ethereum/consensus-specs/blob/c94138e73e0e70eb4b27f9be4d4e9325fa1aebf7/specs/gloas/p2p-interface.md) changes.
- [Honest validator guide](https://github.com/ethereum/consensus-specs/blob/c94138e73e0e70eb4b27f9be4d4e9325fa1aebf7/specs/gloas/validator.md) changes.
- A new [honest builder](https://github.com/ethereum/consensus-specs/blob/c94138e73e0e70eb4b27f9be4d4e9325fa1aebf7/specs/gloas/builder.md) guide. 
- [Fork logic](https://github.com/ethereum/consensus-specs/blob/c94138e73e0e70eb4b27f9be4d4e9325fa1aebf7/specs/gloas/fork.md) changes. 

A summary of the main changes is included below, the [Rationale](#rationale) section contains explanation for most of the design decisions around these changes. 

#### Beacon chain changes

##### Types

| Name           | SSZ equivalent | Description            |
| -------------- | -------------- | ---------------------- |
| `BuilderIndex` | `uint64`       | Builder registry index |

##### Constants

###### Index flags

| Name                 | Value           | Description                                                                                |
| -------------------- | --------------- | ------------------------------------------------------------------------------------------ |
| `BUILDER_INDEX_FLAG` | `uint64(2**40)` | Bitwise flag which indicates that a `ValidatorIndex` should be treated as a `BuilderIndex` |

##### Domains

| Name                          | Value                      |
| ----------------------------- | -------------------------- |
| `DOMAIN_BEACON_BUILDER`       | `DomainType(&apos;0x0B000000&apos;)` |
| `DOMAIN_PTC_ATTESTER`         | `DomainType(&apos;0x0C000000&apos;)` |
| `DOMAIN_PROPOSER_PREFERENCES` | `DomainType(&apos;0x0D000000&apos;)` |

##### Misc

| Name                                    | Value                      | Description                                          |
| --------------------------------------- | -------------------------- | ---------------------------------------------------- |
| `BUILDER_INDEX_SELF_BUILD`              | `BuilderIndex(UINT64_MAX)` | Value which indicates the proposer built the payload |
| `BUILDER_PAYMENT_THRESHOLD_NUMERATOR`   | `uint64(6)`                |                                                      |
| `BUILDER_PAYMENT_THRESHOLD_DENOMINATOR` | `uint64(10)`               |                                                      |

##### Withdrawal prefixes

| Name                        | Value            | Description                                |
| --------------------------- | ---------------- | ------------------------------------------ |
| `BUILDER_WITHDRAWAL_PREFIX` | `Bytes1(&apos;0x03&apos;)` | Withdrawal credential prefix for a builder |

##### Preset

###### Misc

| Name       | Value                  |
| ---------- | ---------------------- |
| `PTC_SIZE` | `uint64(2**9)` (= 512) |

###### Max operations per block

| Name                       | Value |
| -------------------------- | ----- |
| `MAX_PAYLOAD_ATTESTATIONS` | `4`   |

###### State list lengths

| Name                                | Value                                 | Unit                        |
| ----------------------------------- | ------------------------------------- | --------------------------- |
| `BUILDER_REGISTRY_LIMIT`            | `uint64(2**40)` (= 1,099,511,627,776) | Builders                    |
| `BUILDER_PENDING_WITHDRAWALS_LIMIT` | `uint64(2**20)` (= 1,048,576)         | Builder pending withdrawals |

###### Withdrawals processing

| Name                                 | Value              |
| ------------------------------------ | ------------------ |
| `MAX_BUILDERS_PER_WITHDRAWALS_SWEEP` | `2**14` (= 16,384) |

##### Configuration

###### Time parameters

| Name                                | Value                 |  Unit  |
| ----------------------------------- | --------------------- | :----: |
| `MIN_BUILDER_WITHDRAWABILITY_DELAY` | `uint64(2**6)` (= 64) | epochs |

##### Containers

###### New containers

###### `Builder`

```python
class Builder(Container):
    pubkey: BLSPubkey
    version: uint8
    execution_address: ExecutionAddress
    balance: Gwei
    deposit_epoch: Epoch
    withdrawable_epoch: Epoch
```

###### `BuilderPendingPayment`

```python
class BuilderPendingPayment(Container):
    weight: Gwei
    withdrawal: BuilderPendingWithdrawal
```

###### `BuilderPendingWithdrawal`

```python
class BuilderPendingWithdrawal(Container):
    fee_recipient: ExecutionAddress
    amount: Gwei
    builder_index: BuilderIndex
```

###### `PayloadAttestationData`

```python
class PayloadAttestationData(Container):
    beacon_block_root: Root
    slot: Slot
    payload_present: boolean
    blob_data_available: boolean
```

###### `PayloadAttestation`

```python
class PayloadAttestation(Container):
    aggregation_bits: Bitvector[PTC_SIZE]
    data: PayloadAttestationData
    signature: BLSSignature
```

###### `PayloadAttestationMessage`

```python
class PayloadAttestationMessage(Container):
    validator_index: ValidatorIndex
    data: PayloadAttestationData
    signature: BLSSignature
```

###### `IndexedPayloadAttestation`

```python
class IndexedPayloadAttestation(Container):
    attesting_indices: List[ValidatorIndex, PTC_SIZE]
    data: PayloadAttestationData
    signature: BLSSignature
```

###### `ExecutionPayloadBid`

```python
class ExecutionPayloadBid(Container):
    parent_block_hash: Hash32
    parent_block_root: Root
    block_hash: Hash32
    prev_randao: Bytes32
    fee_recipient: ExecutionAddress
    gas_limit: uint64
    builder_index: BuilderIndex
    slot: Slot
    value: Gwei
    execution_payment: Gwei
    blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK]
```

###### `SignedExecutionPayloadBid`

```python
class SignedExecutionPayloadBid(Container):
    message: ExecutionPayloadBid
    signature: BLSSignature
```

###### `ExecutionPayloadEnvelope`

```python
class ExecutionPayloadEnvelope(Container):
    payload: ExecutionPayload
    execution_requests: ExecutionRequests
    builder_index: BuilderIndex
    beacon_block_root: Root
    slot: Slot
    state_root: Root
```

###### `SignedExecutionPayloadEnvelope`

```python
class SignedExecutionPayloadEnvelope(Container):
    message: ExecutionPayloadEnvelope
    signature: BLSSignature
```

###### Modified containers

###### `BeaconBlockBody`

*Note*: The removed fields (`execution_payload`, `blob_kzg_commitments`, and
`execution_requests`) now exist in `ExecutionPayloadEnvelope`.

```python
class BeaconBlockBody(Container):
    randao_reveal: BLSSignature
    eth1_data: Eth1Data
    graffiti: Bytes32
    proposer_slashings: List[ProposerSlashing, MAX_PROPOSER_SLASHINGS]
    attester_slashings: List[AttesterSlashing, MAX_ATTESTER_SLASHINGS_ELECTRA]
    attestations: List[Attestation, MAX_ATTESTATIONS_ELECTRA]
    deposits: List[Deposit, MAX_DEPOSITS]
    voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS]
    sync_aggregate: SyncAggregate
    # [Modified in Gloas:EIP7732]
    # Removed `execution_payload`
    bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES]
    # [Modified in Gloas:EIP7732]
    # Removed `blob_kzg_commitments`
    # [Modified in Gloas:EIP7732]
    # Removed `execution_requests`
    # [New in Gloas:EIP7732]
    signed_execution_payload_bid: SignedExecutionPayloadBid
    # [New in Gloas:EIP7732]
    payload_attestations: List[PayloadAttestation, MAX_PAYLOAD_ATTESTATIONS]
```

###### `BeaconState`

```python
class BeaconState(Container):
    genesis_time: uint64
    genesis_validators_root: Root
    slot: Slot
    fork: Fork
    latest_block_header: BeaconBlockHeader
    block_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT]
    state_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT]
    historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT]
    eth1_data: Eth1Data
    eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH]
    eth1_deposit_index: uint64
    validators: List[Validator, VALIDATOR_REGISTRY_LIMIT]
    balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT]
    randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR]
    slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR]
    previous_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT]
    current_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT]
    justification_bits: Bitvector[JUSTIFICATION_BITS_LENGTH]
    previous_justified_checkpoint: Checkpoint
    current_justified_checkpoint: Checkpoint
    finalized_checkpoint: Checkpoint
    inactivity_scores: List[uint64, VALIDATOR_REGISTRY_LIMIT]
    current_sync_committee: SyncCommittee
    next_sync_committee: SyncCommittee
    # [Modified in Gloas:EIP7732]
    # Removed `latest_execution_payload_header`
    # [New in Gloas:EIP7732]
    latest_execution_payload_bid: ExecutionPayloadBid
    next_withdrawal_index: WithdrawalIndex
    next_withdrawal_validator_index: ValidatorIndex
    historical_summaries: List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT]
    deposit_requests_start_index: uint64
    deposit_balance_to_consume: Gwei
    exit_balance_to_consume: Gwei
    earliest_exit_epoch: Epoch
    consolidation_balance_to_consume: Gwei
    earliest_consolidation_epoch: Epoch
    pending_deposits: List[PendingDeposit, PENDING_DEPOSITS_LIMIT]
    pending_partial_withdrawals: List[PendingPartialWithdrawal, PENDING_PARTIAL_WITHDRAWALS_LIMIT]
    pending_consolidations: List[PendingConsolidation, PENDING_CONSOLIDATIONS_LIMIT]
    proposer_lookahead: Vector[ValidatorIndex, (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH]
    # [New in Gloas:EIP7732]
    builders: List[Builder, BUILDER_REGISTRY_LIMIT]
    # [New in Gloas:EIP7732]
    next_withdrawal_builder_index: BuilderIndex
    # [New in Gloas:EIP7732]
    execution_payload_availability: Bitvector[SLOTS_PER_HISTORICAL_ROOT]
    # [New in Gloas:EIP7732]
    builder_pending_payments: Vector[BuilderPendingPayment, 2 * SLOTS_PER_EPOCH]
    # [New in Gloas:EIP7732]
    builder_pending_withdrawals: List[BuilderPendingWithdrawal, BUILDER_PENDING_WITHDRAWALS_LIMIT]
    # [New in Gloas:EIP7732]
    latest_block_hash: Hash32
    # [New in Gloas:EIP7732]
    payload_expected_withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD]
```

The `BeaconState` container is modified with the addition of:

- `builders`, of type `List[Builder, BUILDER_REGISTRY_LIMIT]` to track the new in-protocol staked builders. 
- `next_withdrawal_builder_index` of type `BuilderIndex` to help tracking builder withdrawals.
- `execution_payload_availability`, of type `Bitvector[SLOTS_PER_HISTORICAL_ROOT]` to track the presence of execution payloads on the canonical chain. 
- `builder_pending_payments`, of type `Vector[BuilderPendingPayment, 2 * SLOTS_PER_EPOCH]` to track pending payments from builders to proposers before the execution payload has been processed. 
- `builder_pending_withdrawals`, of type `List[BuilderPendingWithdrawal, BUILDER_PENDING_WITHDRAWALS_LIMIT]` to track pending withdrawals to the execution layer with the builders&apos; payments. 
- `latest_block_hash`, of type `Hash32`, to track the blockhash of the last execution payload in the blockchain. 
- `payload_expected_withdrawals` of type `List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD]` to track the latest withdrawals that were deducted in the consensus layer and need to still be honored in the Execution Layer.

The `BeaconBlockBody` is modified with the addition of:

- `signed_execution_payload_bid` of type `SignedExecutionPayloadBid` with the builder&apos;s commitment.
- `payload_attestations` of type `List[PayloadAttestation, MAX_PAYLOAD_ATTESTATIONS]` a list of PTC attestations from the previous slot.

The `ExecutionPayloadHeader` object is changed (and renamed to `ExecutionPayloadBid`) to only track the minimum information needed to commit to a builder&apos;s payload.

State transition logic is modified by: 

- A new beacon state getter `get_ptc` returns the PTC members for a given slot. 
- `process_withdrawals` 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 `latest_withdrawals_root` is updated with the HTR of this list. The next execution payload MUST include withdrawals matching the `state.latest_withdrawals_root`. 
- `process_execution_payload` is removed from `process_block`. Instead a new function `process_execution_payload_bid` is included, this function validates the `SignedExecutionPayloadBid` included in the `BeaconBlockBody`, ensures the payment from the builder&apos;s balance can be deducted and adds a `BuilderPendingPayment` object to the beacon state.
- `process_deposit_request` is removed from `process_operations` and deferred until `process_execution_payload`. Special care is added for deposit requests from new validator pubkeys, with withdrawal credentials starting with the prefix `BUILDER_WITHDRAWAL_PREFIX`. These deposits are immediately added to the beacon chain and processed as new builders. 
- `process_withdrawal_request` is removed from `process_operations` and deferred until `process_execution_payload`.
- `process_consolidation_request` is removed from `process_operations` and deferred until `process_execution_payload`. 
- A new `process_payload_attestation` is added to `process_operations`, this function validates the payload timeliness attestations broadcast by the PTC members. 
- `process_execution_payload` is now called as a separate helper when receiving a `SignedExecutionPayloadEnvelope` 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 `BuilderPendingPayment` is removed from the beacon state and a `BuilderPendingWithdrawal` is queued. 

Epoch processing is modified by addition of a new helper function `process_builder_pending_payments`, that processes the builder pending payments from those payloads that were not included in the canonical chain. 
Although there is no change in the `AttestationData` object, the `index` field which is unused since the Electra fork, is now repurposed to signal payload availability. The value of `0` is used when attesting to the current beacon block or a past beacon block without a payload present, and the value of `1` is used to attest to a past beacon block with a payload present. 

#### Fork-Choice changes

Forkchoice is changed substantially to deal with the fact that forkchoice nodes can have different payload content. 


#### P2P changes

- A new global topic for broadcasting `SignedExecutionPayloadBid` messages (builder bids).
- A new global topic for broadcasting `PayloadAttestationMessage` objects. 
- A new global topic for broadcasting `ProposerPreferences` objects.

### Engine API

No changes needed.

## Rationale

### Staked builders

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&apos;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. 

### Delayed validation

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&apos;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 (`SECONDS_PER_SLOT * 2 // INTERVALS_PER_SLOT`) to validate the payload and every other validator 9 seconds (`SECONDS_PER_SLOT * 3 // INTERVALS_PER_SLOT`). From a user UX perspective, a transaction included in slot `N` by the builder is not widely validated until the proposer of slot `N+1` releases their beacon block on top of block `N` first and the attesters of slot `N+1` vote on this beacon block as the head of the chain.


### Fork choice

The following features of fork choice are guaranteed under specified margins of security: 

- Proposer unconditional payment.
- Builder reveal safety.
- Builder withhold safety.

Proposer unconditional payment refers to the following. An Ethereum slot can be either:

- *Full*: both the beacon block and the execution payload have been revealed and included on-chain.
- *Skipped*: No beacon block (and therefore no execution payload) has been included on-chain for this slot. 
- *Empty*: The beacon block has been included on-chain, but the committed execution payload has not. 

Proposer unconditional payment refers to the fact that in the third scenario the beacon block proposer received payment from the corresponding builder.

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.

Builder withhold safety refers to the fact that if some beacon block containing a builder&apos;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. 

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 *Full*, *Skipped* or *Empty*. For this, the `index` field in the `AttestationData` is used as explained above. 

### PTC equivocations

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 `PAYLOAD_TIMELY_THRESHOLD` to be 2/3 of the PTC, in which case the malicious operator would have to control at least 33% of the PTC. 

Another mitigation mechanism is to add new slashing conditions for payload equivocation or PTC equivocations (both are signed messages by validators). 

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.


### Withdrawals

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 `pre_state` and processing a given signed beacon block `block`, the set of withdrawals that are expected to be deducted from the beacon chain are completely determined by `pre_state`. Previous to this EIP the set of withdrawals that are credited on the execution layer are included in `block`. 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:

- When processing the beacon block, the withdrawals are deducted from the beacon chain. 
- The set of withdrawals just deducted is committed to the beacon state `post_state`.  
- When processing any execution payload whose parent beacon state is `post_state`, the payload is deemed invalid if it doesn&apos;t include precisely the list of withdrawals committed to `post_state`. 

This asynchronous mechanism has some consequences as slots may be *empty* 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. `process_execution_payload`). 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.

### Three state transition functions

The current EIP adds an extra state transition function to the block processing in Ethereum. Processing a `SignedBeaconBlock` changes the consensus layer `BeaconState`. A `SignedExecutionPayloadEnvelope` 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. 

### Compatible designs 

#### Inclusion lists

This EIP is fully compatible with forkchoice enforced inclusion lists as specified in [EIP-7805](/EIPs/EIPS/eip-7805) or similar.

#### Slot auctions

A simple change to this EIP is to remove the blockhash commitment from the `SignedExecutionPayloadBid`. This allows the builder to commit any payload to the slot. A preliminary security analysis shows that payload equivocation does not weaken fork choice&apos;s FFG. Some advantages of Slot auctions include:

- 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). 
- Longer continuous time to build blocks. 
- Better compatibility designs with fork choice enforced inclusion list proposals. 


## Backwards Compatibility

This EIP introduces backward incompatible changes to the block validation rule set on the consensus layer and must be accompanied by a hard fork. 

## Security Considerations

### Free option problem 

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. 

### Builder safety

- A colluding set of proposers and attesters controlling consecutive blocks and more than 20% of the total stake can reorg a builder&apos;s payload and force it to pay the bid&apos;s value. 
- There is no possible *unbundling* of the builder&apos;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. 

### Malicious PTC

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. 

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Decentralized Identity Verification (DID)</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/discussion-on-decentralized-identity-verification-did-standard/20392</comments>
        
        <description>## Abstract

This proposal introduces a standard for decentralized identity verification (DID) on the blockchain. The standard leverages cryptographic hashes to represent identity proofs and events for transparency and traceability. By emphasizing simplicity, privacy, and user control, this proposal aims to reduce overhead for developers and users, ensuring seamless integration into decentralized applications (dApps). It offers a minimalistic solution that keeps identity structure simple and enables off-chain mechanisms for detailed identity management and verification.

## Motivation

Centralized identity verification methods are cumbersome, prone to data breaches, and fail to provide users control over their identity data. Existing DID solutions often introduce complexity, making adoption challenging for developers and users. This proposal seeks to address these issues by:

- Offering a minimalistic, decentralized standard that simplifies identity verification.
- Providing privacy-preserving mechanisms that keep sensitive identity data off-chain.
- Encouraging wider adoption by enabling seamless integration into dApps across various industries.
  
### Stakeholders

The following stakeholders will benefit from this proposal:

#### dApp Developers
Developers creating decentralized applications that require identity verification can implement this standard to provide users with secure, decentralized identity management. The minimalistic design makes it easier to integrate into existing workflows without adding unnecessary complexity.

#### Service Providers
Platforms offering services such as decentralized finance (DeFi), gaming, or social networking can integrate this standard to verify user identities without relying on centralized authorities. This reduces the risk of fraud and enhances user trust.

#### Enterprises
Companies looking to integrate blockchain-based identity solutions into their existing systems can use this standard to ensure secure and privacy-preserving identity verification. This allows for a seamless transition to decentralized technologies while maintaining user privacy and security.

#### Developers of Interoperability Solutions
Those working on cross-platform and cross-blockchain interoperability can implement this standard to enable a unified identity verification mechanism across different systems, reducing complexity and increasing user control over their identities.

### Differentiation

This proposal stands out from other DID standards by focusing on minimalism, user control, and privacy. Unlike other solutions that encompass a wide range of identity attributes and interactions, this standard keeps the structure simple and relies on off-chain mechanisms for detailed identity management. Its simplicity fosters easier adoption, making it ideal for dApps that prioritize user-centric, secure ecosystems.

## Specification
The Decentralized Identity Verification (DID) standard introduces a simple, secure, and privacy-preserving mechanism for verifying user identities on the  blockchain. The key components of this standard are outlined below:

#### Identity Contract
A smart contract that acts as the central authority for identity verification. The contract stores the status of identity verifications for users and ensures that verification events are triggered securely and transparently.

#### Verification Function
The `verifyIdentity` function allows a user to submit two verification hashes that represent off-chain proofs or attestations of identity. These hashes can be derived from external sources such as third-party verifiers, documents, or attestations.The function compares the provided hashes and updates the identity verification status accordingly.

##### Input Parameters:
**identityHash:** A cryptographic hash representing the user&apos;s identity.
**verificationHash:** A cryptographic hash derived from the proof or attestation used to verify the identity.

#### IdentityVerified Event
The `IdentityVerified` event is emitted when the user&apos;s identity verification is successfully updated. This event ensures traceability and transparency, allowing dApp developers and users to track verification statuses.

#### Identity Structure
The identity is a simple structure represented by a unique address (public key). Additional identity attributes, such as name or age, are optional and left to off-chain management. This minimal approach keeps the implementation lean, avoiding unnecessary complexity and encouraging broader adoption.

### Interface

```solidity
pragma solidity ^0.8.0;

interface IDecentralizedIdentity {
    // Struct to represent an identity
    struct Identity {
        address userAddress; // Ethereum address of the user
        bytes32 identityHash; // Hash of the identity data
        bytes32[2] verificationHashes; // Hashes used for verifying identity
        bool isVerified; // Indicates if the identity is verified
        uint256 timestamp; // Timestamp of identity creation
    }

    // Event emitted when a new identity is created
    event IdentityCreated(address indexed userAddress, bytes32 identityHash, uint256 timestamp);

    // Event emitted when an identity is verified
    event IdentityVerified(address indexed userAddress, bytes32[2] verificationHashes, uint256 timestamp);

    // Event emitted when an identity is revoked
    event IdentityRevoked(address indexed userAddress, uint256 timestamp);

    // Function to create a new decentralized identity for the caller.
    // Parameters:
    // - identityHash: Hash of the identity data.
    function createIdentity(bytes32 identityHash) external;

    // Function to verify the decentralized identity for the caller.
    // Parameters:
    // - verificationHashes: Hashes used for verifying the identity. These can be 
    //   derived from off-chain proofs, cryptographic challenges, or other methods 
    //   specific to the implementer&apos;s requirements. The exact meaning and derivation 
    //   of the verificationHashes are left to the contract&apos;s implementer.
    function verifyIdentity(bytes32[2] calldata verificationHashes) external;

    // Function to revoke the decentralized identity for the caller.
    function revokeIdentity() external;
    
    // Function to retrieve the decentralized identity for a given user address
    // Parameters:
    // - userAddress Ethereum address of the user.
    // Returns:
    // identity The decentralized identity struct.
    function getIdentity(address userAddress) external view returns (Identity memory);
}
```

## Rationale

The design leverages cryptographic hashes to represent identity information, ensuring that sensitive data is not stored directly on the blockchain. The use of `verificationHashes` allows for flexible identity verification mechanisms. These hashes could be derived from various off-chain proofs, such as cryptographic challenges or attestations, depending on the implementer&apos;s needs. By leaving the interpretation of the verification hashes open, the standard enables adaptability while maintaining privacy and security. Additionally, the inclusion of events ensures transparency and traceability.

## Reference Implementation

```solidity
pragma solidity ^0.8.0;

import &quot;./IDecentralizedIdentity.sol&quot;;

contract DecentralizedIdentity is IDecentralizedIdentity {
    // Mapping to store identities by user address
    mapping(address =&gt; Identity) private identities;

    // Function to create a new decentralized identity for the caller.
    // Parameters:
    // - identityHash Hash of the identity data.
    function createIdentity(bytes32 identityHash) external override {
        // Ensure identity does not already exist
        require(identities[msg.sender].userAddress == address(0), &quot;Identity already exists&quot;);

        // Create the identity for the caller
        identities[msg.sender] = Identity({
            userAddress: msg.sender,
            identityHash: identityHash,
            verificationHashes: [bytes32(0), bytes32(0)], // Initialize with empty hashes
            isVerified: false,
            timestamp: block.timestamp
        });

        // Emit event for the creation of a new identity
        emit IdentityCreated(msg.sender, identityHash, block.timestamp);
    }

    // Function to verify the decentralized identity for the caller.
    // Parameters:
    // - verificationHashes: Hashes used for verifying the identity.
    function verifyIdentity(bytes32[2] calldata verificationHashes) external override {
        // Ensure identity exists
        require(identities[msg.sender].userAddress != address(0), &quot;Identity does not exist&quot;);

        // Update verification hashes and mark identity as verified
        identities[msg.sender].verificationHashes = verificationHashes;
        identities[msg.sender].isVerified = true;

        // Emit event for the verification of identity
        emit IdentityVerified(msg.sender, verificationHashes, block.timestamp);
    }

    // Function to revoke the decentralized identity for the caller.
    function revokeIdentity() external override {
        // Ensure identity exists
        require(identities[msg.sender].userAddress != address(0), &quot;Identity does not exist&quot;);

        // Mark identity as not verified
        identities[msg.sender].isVerified = false;

        // Emit event for the revocation of identity
        emit IdentityRevoked(msg.sender, block.timestamp);
    }

    // Function to retrieve the decentralized identity for a given user address
    // Parameters:
    // - userAddress Ethereum address of the user.
    // Returns:
    // identity The decentralized identity struct.
    function getIdentity(address userAddress) external view override returns (Identity memory) {
        return identities[userAddress];
    }
}
```

## Security Considerations

**Secure Hashing**: Ensure that identity and verification hashes are generated using a secure hashing algorithm to prevent collisions and ensure the integrity of the identity data.
**Replay Attacks**: Verification hashes should incorporate nonces or timestamps to prevent replay attacks.
**Implementation Flexibility**: Developers must ensure that hash generation and validation processes are robust and resistant to manipulation.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 26 Jun 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7734</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7734</guid>
      </item>
    
      <item>
        <title>Leaf-level state expiry in verkle trees</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7736-leaf-level-state-expiry-in-verkle-trees/20474</comments>
        
        <description>## Abstract

Adds an &quot;update epoch&quot; to the verkle tree extension node. When it is time for an epoch to expire, the extension node and its suffix nodes can be deleted.

A new transaction type with a simple verkle proof pays for the costs of reactivating the extension and suffix nodes, and updating the epoch counter.

## Motivation

Previous attempts at implementing state expiry have been stalled by the quickly-increasing complexity, require heavy change in the structure of ethereum (address space extension, oil, multiple trees, ...). This proposal is offering a simpler albeit non-exhaustive approach to state expiry: only removing the leaf nodes and leaving the rest of the tree intact. This removes the need for methods that would be detrimental to the user and developer experience.

## Specification

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

### Constants

|Name|Description|Value|
|----|-----------|-----|
|`FORK_TIME`|Fork activation time|TBD|
|`EPOCH_LENGTH`|Duration of an epoch, in s|15778800 (6 months)|
|`INITIAL_EPOCH_COUNTER`|The epoch that ends at timestamp `FORK_TIME`|0|
|`NUM_ACTIVE_EPOCHS`|Number of concurrently unexpired epochs|2|
|`RESURRECT_TX_TYPE`|Type ID for resurrection transactions|TBD|

### Change to the verkle tree

Add an integral variable called `current_epoch`. It is initialized to `INITIAL_EPOCH_COUNTER` before the fork, and contains the current epoch number.

Add a new `last_epoch` field to the extension node:

```python
def extension_and_suffix_tree(stem: bytes31, values: Dict[byte, bytes32], last_epoch: int) -&gt; int:
    sub_leaves = [0] * 512
    for suffix, value in values.items():
        sub_leaves[2 * suffix] = int.from_bytes(value[:16], &apos;little&apos;) + 2**128
        sub_leaves[2 * suffix + 1] = int.from_bytes(value[16:], &apos;little&apos;)
    C1 = compute_commitment_root(sub_leaves[:256])
    C2 = compute_commitment_root(sub_leaves[256:])
    return compute_commitment_root([1, # Extension marker
                                    int.from_bytes(stem, &quot;little&quot;),
                                    group_to_scalar_field(C1),
                                    group_to_scalar_field(C2),
                                    last_epoch] + # Added in this EIP
                                    [0] * 251)
```

The following rules are added to tree update operations:

 * For a read or write event to the tree, check that `current_epoch &lt; last_epoch + NUM_ACTIVE_EPOCHS`.
     * If this is `true`, proceed with the write/read
     * Otherwise, revert.
 * `last_epoch` is updated with the value of `current_epoch` each time that a _write_ event is processed for this extension node.

### Expiry

At the start of block processing, before transactions are executed, run `check_epoch_end`:

```python
def check_epoch_end(block):
    if block.timestamp &gt;= FORK_TIME + current_epoch * EPOCH_LENGTH:
        current_epoch = current_epoch + 1
        schedule_expiry(current_epoch-NUM_ACTIVE_EPOCHS)
```

It is left to client implementers to decide on the behavior of the `schedule_expiry` function.

Data that needs to be kept for the expiry:

 * the `stem` value, so that siblings can be inserted
 * The commitment `C` to the node

That data is referred to as the _keepsake_ for this extension-and-suffix node.

**Note**: that actual deletion may not happen before the first block in the epoch has finalized, unless there is a way for the client to recover the block in case of a reorg.

### Resurrection

The resurrection transaction is defined as follows:

`RESURRECT_TX_TYPE|ssz(Vector[stem,last_epoch,values])`

Where:

 * `stem` is used to find the location in the tree, so that the node can be recreated;
 * `last_epoch` and `values` are the items that were deleted;

At the start of the validation, charge the costs using constants defined in [EIP-4762](/EIPs/EIPS/eip-4762):

```python
def resurrect_gas_cost(values) -&gt; int:
    return WITNESS_BRANCH_COST + 
            SUBTREE_EDIT_COST +
            sum(WITNESS_CHUNK_COST + CHUNK_EDIT_COST + CHUNK_FILL_COST for i in values)
```

Once the gas cost has been paid, the validation process begins:

```python
def validate_subtrees(tree, tx, current_epoch) -&gt; bool:
    # The tx is a SSZ payload
    subtrees = deserialize_ssz(tx[1:])
    if subtrees == None:
        return false
    
    # Process all subtrees in the transaction
    for subtree in subtrees:
        ok = validate_subtree(tree, subtree.stem, subtree.values, subtree.last_epoch, current_epoch)
        if not ok:
            return false
        
    return true

def validate_subtree(tree, stem, values, last_epoch, current_epoch) -&gt; bool:
    # Compute the commitment to the expired
    # tree, get the 
    expired_C = extension_and_suffix_tree(stem, values, last_epoch)
    expired = tree.get_keepsake(stem)
    if keepsake.C != expired_C:
        return false

    # Replace the keepsake with the resurrected
    # extension-and-suffix tree.
    new_C = extension_and_suffix_tree(stem, values, current_epoch)
    return tree.resurrect_subtree(stem, new_C, values, current_epoch) == None
```

where `resurrect_subtree` will return `None` upon success, and an error otherwise.

## Rationale

This approach has the benefit of simplicity, over previous proposals for state expiry:

* no Address Space Extension (ASE) required
* it only uses a single tree instead of multiple, per-epoch trees
* smaller resurrection proofs, as only providing the data is necessary to resurrect.
* clear gas costs
* only expire &quot;cold&quot; data, the &quot;hot&quot; data set remains active
* it is forward-compatible, as ASE or multiple trees are still possible.
* the exponentiation/addition computation for `current_epoch` need only be paid once per epoch, which is quickly amortized.

While it&apos;s not deleting _all_ the data, it deletes _most_ of it, namely the values and subcommitments, while retaining the ability to easily insert siblings.

It is also more expensive than resurrecting a single leaf, which is the cost paid for simplification.
    
The reason why only writes update the resurrection counter, is that any update to the resurrection counter has the effect of a write. Doing so would mean either:
    
 * Increasing the cost of a read to that of a write. This would increase the gas costs even more than they did in EIP-4762.
 * Effectively doing a write for the cost of a read. This would both neuter state expiry and possibly add a DOS vector.

## Backwards Compatibility

This proposal is backwards-compatible with verkle, as by default the value for the 4th (index starting at 0) evaluation point is set to `0` in [EIP-6800](/EIPs/EIPS/eip-6800), which is the value of `INITIAL_EPOCH_COUNTER`.

## Test Cases

TODO
    
## Reference Implementation

TODO

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 05 Jul 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7736</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7736</guid>
      </item>
    
      <item>
        <title>Permissionless Script Registry</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7738-permissionless-script-registry/20503</comments>
        
        <description>## Abstract

This EIP provides a means to create a standard registry for locating executable scripts associated with the token.

## Motivation

[ERC-5169](/EIPs/EIPS/eip-5169) provides a client script lookup method for contracts. This requires the contract to have implemented the [ERC-5169](/EIPs/EIPS/eip-5169) interface at the time of construction (or allow an upgrade path).

This proposal outlines a contract that can supply prototype and certified scripts. The contract would be a multichain singleton instance that would be deployed at identical addresses on supported chains.

### Overview

The registry contract will supply a set of URI links for a given contract address. These URI links point to script programs that can be fetched by a wallet, viewer or mini-dapp.

The pointers can be set permissionlessly using a setter in the registry contract.

## Specification

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.

The contract MUST implement the `IERC7738` interface.
The contract MUST emit the `ScriptUpdate` event when the script is updated.
The contract SHOULD order the `scriptURI` returned so that the [ERC-173](/EIPs/EIPS/eip-173) `owner()` of the contract&apos;s script entries are returned first (in the case of simple implementations the wallet will pick the first `scriptURI` returned).
The contract SHOULD provide a means to page through entries if there are a large number of scriptURI entries.

```solidity
interface IERC7738 {
    /// @dev This event emits when the scriptURI is updated, 
    /// so wallets implementing this interface can update a cached script
    event ScriptUpdate(address indexed contractAddress, string[] newScriptURI);

    /// @notice Get the scriptURI for the contract
    /// @return The scriptURI
    function scriptURI(address contractAddress) external view returns (string[] memory);

    /// @notice Update the scriptURI 
    /// emits event ScriptUpdate(address indexed contractAddress, scriptURI memory newScriptURI);
    function setScriptURI(address contractAddress, string[] memory scriptURIList) external;
}
```

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

## Rationale

This method allows contracts written without the [ERC-5169](/EIPs/EIPS/eip-5169) interface to associate scripts with themselves, and avoids the need for a centralised online server, with subsequent need for security and the requires an organisation to become a gatekeeper for the database.

## Test Cases

Test cases are included in [NFTRegistryTest.test.ts](/EIPs/assets/eip-7738/test/NFTRegistryTest.test.ts). Contracts, deployment scripts and registry script can be found alongside the test script.

Clone the repo and run:

```shell
cd ../assets/eip-7738
npm install --save-dev hardhat
npm install
npx hardhat test
```

## Reference Implementation

The live implementation of the script registry is at `0x0077380bCDb2717C9640e892B9d5Ee02Bb5e0682` on several mainnet, L2 and testnet chains. To deploy scripts for use you can directly call the ```setScriptURI``` function:

```solidity
function setScriptURI(address contractAddress, string[] memory newScriptURIs)
```

or use the bundled ethers script, ensuring to fill in the target contract address and scriptURI:

[Create Registry Entry](/EIPs/assets/eip-7738/scripts/createRegistryEntry.ts)

### Simplified Implementation
```solidity
import &quot;@openzeppelin/contracts/access/Ownable.sol&quot;;

contract DecentralisedRegistry is IERC7738 {
    struct ScriptEntry {
        mapping(address =&gt; string[]) scriptURIs;
        address[] addrList;
    }

    mapping(address =&gt; ScriptEntry) private _scriptURIs;

    function setScriptURI(
        address contractAddress,
        string[] memory scriptURIList
    ) public {
        require (scriptURIList.length &gt; 0, &quot;&gt; 0 entries required in scriptURIList&quot;);
        bool isOwnerOrExistingEntry = Ownable(contractAddress).owner() == msg.sender 
            || _scriptURIs[contractAddress].scriptURIs[msg.sender].length &gt; 0;
        _scriptURIs[contractAddress].scriptURIs[msg.sender] = scriptURIList;
        if (!isOwnerOrExistingEntry) {
            _scriptURIs[contractAddress].addrList.push(msg.sender);
        }
        
        emit ScriptUpdate(contractAddress, msg.sender, scriptURIList);
    }

    // Return the list of scriptURI for this contract.
    // Order the return list so `Owner()` assigned scripts are first in the list
    function scriptURI(
        address contractAddress
    ) public view returns (string[] memory) {
        //build scriptURI return list, owner first
        address contractOwner = Ownable(contractAddress).owner();
        address[] memory addrList = _scriptURIs[contractAddress].addrList;
        uint256 i;

        //now calculate list length
        uint256 listLen = _scriptURIs[contractAddress].scriptURIs[contractOwner].length;
        for (i = 0; i &lt; addrList.length; i++) {
            listLen += _scriptURIs[contractAddress].scriptURIs[addrList[i]].length;
        }

        string[] memory ownerScripts = new string[](listLen);

        // Add owner scripts
        uint256 scriptIndex = _addScriptURIs(contractOwner, contractAddress, ownerScripts, 0);

        // Add remainder scripts
        for (uint256 i = 0; i &lt; addrList.length; i++) {
            scriptIndex = _addScriptURIs(addrList[i], contractAddress, ownerScripts, scriptIndex);
        }

        return ownerScripts;
    }

    function _addScriptURIs(
        address user,
        address contractAddress,
        string[] memory ownerScripts,
        uint256 scriptIndex
    ) internal view returns (uint256) {
        for (uint256 j = 0; j &lt; _scriptURIs[contractAddress].scriptURIs[user].length; j++) {
            string memory thisScriptURI = _scriptURIs[contractAddress].scriptURIs[user][j];
            if (bytes(thisScriptURI).length &gt; 0) {
                ownerScripts[scriptIndex++] = thisScriptURI;
            }
        }
        return scriptIndex;
    }
}
```

## Security Considerations

The scripts provided could be authenticated in various ways:

1. The target contract which the setter specifies implements the [ERC-173](/EIPs/EIPS/eip-173) `Ownable` interface. Once the script is fetched, the signature can be verified to match the Owner(). In the case of TokenScript this can be checked by a dapp or wallet using the TokenScript SDK, the TokenScript online verification service, or by extracting the signature from the XML, taking a keccak256 of the script and ecrecover the signing key address.
2. If the contract does not implement Ownable, further steps can be taken:
 a. The hosting app/wallet can acertain the deployment key using 3rd party API or block explorer. The implementing wallet, dapp or viewer would then check the signature matches this deployment key.
 b. Signing keys could be pre-authenticated by a hosting app, using an embedded keychain.
 c. A governance token could allow a script council to authenticate requests to set and validate keys.

If these criteria are not met:
- For mainnet implementations the implementing wallet should be cautious about using the script - it would be at the app and/or user&apos;s discretion.
- For testnets, it is acceptable to allow the script to function, at the discretion of the wallet provider.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).</description>
        <pubDate>Mon, 01 Jul 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7738</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7738</guid>
      </item>
    
      <item>
        <title>Readable Typed Signatures for Smart Accounts</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7739-readable-typed-signatures-for-smart-accounts/20513</comments>
        
        <description>## Abstract

This proposal defines a standard to prevent signature replays across multiple smart accounts when they are owned by a single Externally Owned Account (EOA). This is achieved through a defensive rehashing scheme for [ERC-1271](/EIPs/EIPS/eip-1271) verification using specific nested [EIP-712](/EIPs/EIPS/eip-712) typed structures, which preserves the readability of the signed contents during wallet client signature requests.

## Motivation

Smart accounts can verify signatures with via [ERC-1271](/EIPs/EIPS/eip-1271) using the `isValidSignature` function.

A straightforward implementation as shown below, is vulnerable to signature replay attacks.

```solidity
/// @dev This implementation is NOT safe.
function isValidSignature(
    bytes32 hash,
    bytes calldata signature
) external override view returns (bytes4) {
    uint8 v = uint8(signature[64]);
    (bytes32 r, bytes32 s) = abi.decode(signature, (bytes32, bytes32));
    // Reject malleable signatures.
    require(uint256(s) &lt;= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0);
    address signer = ecrecover(hash, v, r, s);
    // Reject failed recovery.
    require(signer != address(0));
    // `owner` is a storage variable containing the smart account&apos;s owner.
    if (signer == owner) {
        return 0x1626ba7e;
    } else {
        return 0xffffffff;
    }
}
```

When multiple smart accounts are owned by a single EOA, the same signature can be replayed across the smart accounts if the `hash` does not include the smart account address. 

Unfortunately, this is the case for many popular applications (e.g. Permit2). As such, many smart account implementations perform some form of defensive rehashing. First, the smart account computes a final hash from minimally: (1) the hash, (2) its own address, (3) the chain ID. Then, the smart account verifies the final hash against the signature. Defensive rehashing can be implemented with [EIP-712](/EIPs/EIPS/eip-712), but a straightforward implementation will make the signed contents opaque. 

This standard provides a defensive rehashing scheme that makes the signed contents visible across all wallet clients that support [EIP-712](/EIPs/EIPS/eip-712). It is designed for minimal adoption friction. Even if wallet clients or application frontends are not updated, users can still inject client side JavaScript to enable the defensive rehashing.

## Specification

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

### Overview

The following dependencies are REQUIRED:

- [EIP-712](/EIPs/EIPS/eip-712) Typed structured data hashing and signing.  
  Provides the relevant typed data hashing logic internally, which is required to construct the final hashes.

- [ERC-1271](/EIPs/EIPS/eip-1271) Standard Signature Validation Method for Contracts.  
  Provides the `isValidSignature(bytes32 hash, bytes calldata signature)` function.

- [ERC-5267](/EIPs/EIPS/eip-5267) Retrieval of EIP-712 domain.  
  Provides the `eip712Domain()` function which is required to compute the final hashes.

This standard defines the behavior of the `isValidSignature` function for [ERC-1271](/EIPs/EIPS/eip-1271), which comprises of two workflows: (1) the `TypedDataSign` workflow, (2) the `PersonalSign` workflow.

### `TypedDataSign` workflow 

The `TypedDataSign` workflow handles the case where the `hash` is originally computed with [EIP-712](/EIPs/EIPS/eip-712).

#### `TypedDataSign` final hash

The final hash for the `TypedDataSign` workflow is defined as:

```
keccak256(\x19\x01 ‖ APP_DOMAIN_SEPARATOR ‖
    hashStruct(TypedDataSign({
        contents: hashStruct(originalStruct),
        name: eip712Domain().name,
        version: eip712Domain().version,
        chainId: eip712Domain().chainId,
        verifyingContract: eip712Domain().verifyingContract,
        salt: eip712Domain().salt
    }))
)
```

where `‖` denotes the concatenation operator for bytes.

In Solidity, this can be written as:

```solidity
finalTypedDataSignHash = 
    keccak256(
        abi.encodePacked(
            hex&quot;1901&quot;,
            // Application specific domain separator. Passed via `signature`.
            bytes32(APP_DOMAIN_SEPARATOR),
            keccak256(
                abi.encode(
                    // Computed on-the-fly with `contentsType`, which is passed via `signature`.
                    typedDataSignTypehash, 
                    // This is the `contents` struct hash, which is passed via `signature`.
                    bytes32(hashStruct(originalStruct)),
                    // `eip712Domain()` is from ERC-5267. 
                    keccak256(bytes(eip712Domain().name)), 
                    keccak256(bytes(eip712Domain().version)),
                    uint256(eip712Domain().chainId),
                    uint256(uint160(eip712Domain().verifyingContract)),
                    bytes32(eip712Domain().salt)
                )
            )
        )
    );
```

where `typedDataSignTypehash` is:

```solidity
typedDataSignTypehash = 
    keccak256(
          abi.encodePacked(
              &quot;TypedDataSign(&quot;,
                  contentsName, &quot; contents,&quot;,
                  &quot;string name,&quot;,
                  &quot;string version,&quot;,
                  &quot;uint256 chainId,&quot;,
                  &quot;address verifyingContract,&quot;,
                  &quot;bytes32 salt&quot;
              &quot;)&quot;,
              contentsType
          )
      );
```

If `contentsType` is `&quot;Mail(address from,address to,string message)&quot;`, then `contentsName` will be `&quot;Mail&quot;`.

The `contentsName` is the substring of `contentsType` up to (excluding) the first instance of `&quot;(&quot;`:

In Solidity, this can be written as:

```solidity
// `slice(string memory subject, uint256 start, uint256 end)` 
// returns a copy of `subject` sliced from `start` to `end` (exclusive).
// `start` and `end` are byte offsets.
//
// `indexOf(string memory subject, string memory search)`
// Returns the byte index of the first location of `search` in `subject`,
// searching from left to right. Returns `2**256 - 1` if `search` is not found.
contentsName = 
    LibString.slice(
        contentsType,
        0, // Start byte index.
        LibString.indexOf(contentsType, &quot;(&quot;) // End byte index (exclusive).
    );
```

[A copy of the `LibString` Solidity library is provided for completeness](/EIPs/assets/eip-7739/contracts/utils/LibString.sol).

For safety, it is RECOMMENDED to treat the signature as invalid if any of the following is true:

- `contentsName` is the empty string (i.e. `bytes(contentsName).length == 0`).
- `contentsName` starts with any of the following bytes `abcdefghijklmnopqrstuvwxyz(`.
- `contentsName` contains any of the following bytes `, )\x00`.

#### `TypedDataSign` signature

The `signature` passed into `isValidSignature` will be changed to:

```
originalSignature ‖ APP_DOMAIN_SEPARATOR ‖ contents ‖ contentsDescription ‖ uint16(contentsDescription.length)
```

where:

- `contents` is the bytes32 struct hash of the original struct.
- `contentsDescription` is either:
  - `contentsType` (implicit mode),  
    where `contentsType` starts with `contentsName`.
  - `contentsType ‖ contentsName` (explicit mode),  
    where `contentsType` may not necessarily start with `contentsName`.

In Solidity, this can be written as:

```solidity
signature = 
    abi.encodePacked(
        bytes(originalSignature),
        bytes32(APP_DOMAIN_SEPARATOR),
        bytes32(contents),
        bytes(contentsDescription),
        uint16(contentsDescription.length)
    );
```

The appended `APP_DOMAIN_SEPARATOR` and `contents` struct hash will be used to verify if the `hash` passed into `isValidSignature` is indeed correct via:

```solidity
hash == keccak256(
    abi.encodePacked(
        hex&quot;1901&quot;,
        bytes32(APP_DOMAIN_SEPARATOR),
        bytes32(contents)
    )
)
```

If the `hash` does not match the reconstructed hash, then the `hash` and `signature` are invalid under the `TypedDataSign` workflow.

### `PersonalSign` workflow 

This `PersonalSign` workflow handles the case where the `hash` is originally computed with [EIP-191](/EIPs/EIPS/eip-191).

#### `PersonalSign` final hash

The final hash for the `PersonalSign` workflow is defined as:

```
keccak256(\x19\x01 ‖ ACCOUNT_DOMAIN_SEPARATOR ‖
    hashStruct(PersonalSign({
        prefixed: keccak256(bytes(\x19Ethereum Signed Message:\n ‖
        base10(bytes(someString).length) ‖ someString))
    }))
)
```

where `‖` denotes the concatenation operator for bytes.

In Solidity, this can be written as:

```solidity
finalPersonalSignHash = 
    keccak256(
        abi.encodePacked(
            hex&quot;1901&quot;,
            // Smart account domain separator.
            // Can be computed via `eip712Domain()` from ERC-5267.
            bytes32(ACCOUNT_DOMAIN_SEPARATOR),
            keccak256(
                abi.encode(
                    // `PERSONAL_SIGN_TYPEHASH`.
                    keccak256(&quot;PersonalSign(bytes prefixed)&quot;),
                    // `hash` is from `isValidSignature(hash, signature)`
                    hash
                )
            )
        )
    );
```

Here, `hash` is computed in the application contract and passed into `isValidSignature`. 

The smart account does not need to know how `hash` is computed. For completeness, this is how it can be computed:

```solidity
hash =
    abi.encodePacked(
        &quot;\x19Ethereum Signed Message:\n&quot;,
        // `toString` returns the base10 representation of a uint256.
        LibString.toString(someString.length),
        // This is the original message to be signed.
        someString
    );
```

#### `PersonalSign` signature 

The `PersonalSign` workflow does not require additional data to be appended to the `signature` passed into `isValidSignature`.

### Support detection

Smart accounts SHOULD return `bytes4(0x77390001)` for `isValidSignature(0x7739773977397739773977397739773977397739773977397739773977397739, &quot;&quot;)` to indicate support for this standard.

The magic number `bytes4(0x77390001)` MAY be incremented if this standard gets updated.

### Signature verification workflow deduction

As the `isValidSignature` signature function signature is unchanged, the implementation MUST be able to deduce the type of workflow required to verify the signature.

If the signature contains the correct data to reconstruct the `hash`, the `isValidSignature` function MUST perform the `TypedDataSign` workflow.
Otherwise, the `isValidSignature` function MUST perform the `PersonalSign` workflow.

In Solidity, the check can be written as:

```solidity
// If this is true, it means that the `signature` contains 
// the correct `APP_DOMAIN_SEPARATOR` and `contents`,
// and the `TypedDataSign` workflow MUST be performed.
// Otherwise, the `PersonalSign` workflow MUST be performed.
hash == keccak256(
    abi.encodePacked(
        hex&quot;1901&quot;,
        bytes32(APP_DOMAIN_SEPARATOR),
        bytes32(contents)
    )
)
```

### Conditional skipping of defensive rehashing

Smart accounts MAY skip the defensive rehashing workflows if any of the following is true:

- `isValidSignature` is called off-chain.
- The `hash` passed into `isValidSignature` has already included the address of the smart account.

As many developers may not update their applications to support the nested EIP-712 workflow, smart account implementations SHOULD try to accommodate by skipping the defensive rehashing where it is safe to do so.

## Rationale

### `TypedDataSign` structure

The `typedDataSignTypehash` must be constructed on-the-fly on-chain. This is to enforce that the signed contents will be visible in the signature request, by requiring that `contents` be a user defined type. 

The fields of `eip712Domain` are flattened into the `TypedDataSign` structure instead of being included as a field of type `EIP712Domain` in order to avoid a conflict with the domain type of the verifying contract in case it&apos;s different.

The `bytes1 fields` bitmap and `uint256[] extensions` array in [ERC-5267](/EIPs/EIPS/eip-5267) have been omitted. Differentiating between an absent field versus a zero field (e.g. `bytes32(0)`) offers no additional security benefits for on-chain defensive rehashing. The `extensions` parameter is a list of EIP numbers used for off-chain signaling.

### `contentsDescription` with implicit and explicit modes

When the `contents` structure contains nested types, EIP-712 lexicographical sorting can result in the `contentsName` not being positioned exactly at the start of the `contentsType`. As such, we need the explicit mode.

### Support detection with `isValidSignature`

For easier implementation in modular smart accounts, we have decided to utilize the `isValidSignature` method to return a magic number instead of defining new functions.

### Rejecting `contentsName` beginning with any lowercase 7-bit ASCII character

This recommendation is to keep the standard language agnostic and future-proof. Atomic types such as `uint256` may be named differently in other languages (e.g. `u256`).

## Backwards Compatibility

### Detection of previous draft

In an earlier draft, we have designated a `supportsNestedTypedDataSign()` function for support detection, which returns `bytes4(0xd620c85a)`.

## Reference Implementation

[A production ready and optimized implementation is provided for reference](/EIPs/assets/eip-7739/contracts/accounts/ERC1271.sol).

It includes relevant complementary features required for safety, flexibility, developer experience, and user experience.

The reference implementation is intentionally not minimalistic. This is to avoid repeating the mistake of [ERC-1271](/EIPs/EIPS/eip-1271), where a minimalist reference implementation is wrongly assumed to be safe for production use.

## Security Considerations

### Rejecting invalid `contentsName`

Current major implementations of `eth_signTypedData` do not sanitize the names of custom types.

A phishing website can craft a `contentsName` with control characters to break out of the `PersonalSign` type encoding, resulting in the wallet client asking the user to sign an opaque hash.

Requiring on-chain sanitization of `contentsName` will block this phishing attack vector.

### Impossible to chain multiple signers of this kind

An account that uses this method as replay protection for ERC-1271 signatures cannot have a signer that uses the same method. This is because a signature defines a `TypedDataSign` struct type with a member that has the type of the message being signed, and if the message being signed is another `TypedDataSign` struct, the resulting EIP-712 message will contain in its body two separate `TypedDataSign` types with incompatible contents, something that can&apos;t be represented in an EIP-712 request.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 28 May 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7739</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7739</guid>
      </item>
    
      <item>
        <title>Authorize Operator</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7741-authorize-operator/20531</comments>
        
        <description>## Abstract

A set of functions to enable meta-transactions and atomic interactions with contracts implementing an operator model, via signatures conforming to the [EIP-712](/EIPs/EIPS/eip-712) typed message signing specification.

## Motivation

The primary motivation for this standard is to enhance the flexibility, security, and efficiency of operator management. By leveraging EIP-712 signatures, this standard allows users to authorize operators without the need for on-chain transactions, reducing gas costs and improving user experience. This is particularly beneficial whenever frequent operator changes and cross-chain interactions are required.

Additionally, this standard aims to:

1. **Enable Meta-Transactions**: Allow users to delegate the execution of transactions to operators, enabling meta-transactions where the user does not need to hold native tokens to pay for gas fees on each chain.
2. **Improve Security**: Utilize the EIP-712 standard for typed data signing, which provides a more secure and user-friendly way to sign messages compared to raw data signing.
3. **Facilitate Interoperability**: Provide a standardized interface for operator management that can be adopted across various vault protocols, promoting interoperability and reducing integration complexity for developers.
4. **Streamline Cross-Chain Operations**: Simplify the process of managing operators across different chains, making it easier for protocols to maintain consistent operator permissions and interactions in a multi-chain environment.

By addressing these needs, the `Authorize Operator` standard aims to streamline the process of managing operators in decentralized vault protocols, making it easier for users and developers to interact with smart contracts in a secure, cost-effective, and interoperable manner across multiple blockchain networks.

## Specification

### Operator-compatible contracts

This signed authorization scheme applies to any contracts implementing the following interface:

```solidity
  interface IOperator {
    event OperatorSet(address indexed owner, address indexed operator, bool approved);

    function setOperator(address operator, bool approved) external returns (bool);
    function isOperator(address owner, address operator) external returns (bool status);
  }
```

[EIP-6909](/EIPs/EIPS/eip-6909) and [EIP-7540](/EIPs/EIPS/eip-7540) already implement this interface.

The naming of the arguments is interchangeable, e.g. [EIP-6909](/EIPs/EIPS/eip-6909) uses `spender` instead of `operator`.

### Methods

#### `authorizeOperator`

Grants or revokes permissions for `operator` to manage Requests on behalf of the `msg.sender`, using an [EIP-712](/EIPs/EIPS/eip-712) signature.

MUST revert if the `deadline` has passed.

MUST invalidate the nonce of the signature to prevent message replay.

MUST revert if the `signature` is not a valid [EIP-712](/EIPs/EIPS/eip-712) signature, with the given input parameters.

MUST set the operator status to the `approved` value.

MUST log the `OperatorSet` event.

MUST return `true`.

```yaml
- name: authorizeOperator
  type: function
  stateMutability: nonpayable

  inputs:
    - name: owner
      type: address
    - name: operator
      type: address
    - name: approved
      type: bool
    - name: nonce
      type: bytes32
    - name: deadline
      type: uint256
    - name: signature
      type: bytes

  outputs:
    - name: success
      type: bool
```

#### `invalidateNonce`

Revokes the given `nonce` for `msg.sender` as the `owner`.

```yaml
- name: invalidateNonce
  type: function
  stateMutability: nonpayable

  inputs:
    - name: nonce
      type: bytes32
```

#### `authorizations`

Returns whether the given `nonce` has been used for the `controller`.

```yaml
- name: authorizations
  type: function
  stateMutability: nonpayable

  inputs:
    - name: controller
      type: address
    - name: nonce
      type: bytes32
  outputs:
    - name: used
      type: bool
```

#### `DOMAIN_SEPARATOR`

Returns the `DOMAIN_SEPARATOR` as defined according to EIP-712. The `DOMAIN_SEPARATOR` should be unique to the contract and chain to prevent replay attacks from other domains, and satisfy the requirements of EIP-712, but is otherwise unconstrained.

```yaml
- name: DOMAIN_SEPARATOR
  type: function
  stateMutability: nonpayable

  outputs:
    - type: bytes32
```

### [ERC-165](/EIPs/EIPS/eip-165) support

Smart contracts implementing this standard MUST implement the [ERC-165](/EIPs/EIPS/eip-165) `supportsInterface` function.

Contracts MUST return the constant value `true` if `0xa9e50872` is passed through the `interfaceID` argument.

## Rationale

### Similarity to [ERC-2612](/EIPs/EIPS/eip-2612)

The specification is intentionally designed to closely match [ERC-2612](/EIPs/EIPS/eip-2612). This should simplify new integrations of the standard.

The main difference is using `bytes32` vs `uint256`, which enables unordered nonces. 

## Reference Implementation

```solidity
    // This code snippet is incomplete pseudocode used for example only and is no way intended to be used in production or guaranteed to be secure

    bytes32 public constant AUTHORIZE_OPERATOR_TYPEHASH =
        keccak256(&quot;AuthorizeOperator(address controller,address operator,bool approved,bytes32 nonce,uint256 deadline)&quot;);

    mapping(address owner =&gt; mapping(bytes32 nonce =&gt; bool used)) authorizations;

    function DOMAIN_SEPARATOR() public view returns (bytes32) {
      // EIP-712 implementation 
    }

    function isValidSignature(address signer, bytes32 digest, bytes memory signature) internal view returns (bool valid) {
      // ERC-1271 implementation 
    }

    function authorizeOperator(
        address controller,
        address operator,
        bool approved,
        bytes32 nonce,
        uint256 deadline,
        bytes memory signature
    ) external returns (bool success) {
        require(block.timestamp &lt;= deadline, &quot;ERC7540Vault/expired&quot;);
        require(controller != address(0), &quot;ERC7540Vault/invalid-controller&quot;);
        require(!authorizations[controller][nonce], &quot;ERC7540Vault/authorization-used&quot;);

        authorizations[controller][nonce] = true;

        bytes32 digest = keccak256(
            abi.encodePacked(
                &quot;\x19\x01&quot;,
                DOMAIN_SEPARATOR(),
                keccak256(abi.encode(AUTHORIZE_OPERATOR_TYPEHASH, controller, operator, approved, nonce, deadline))
            )
        );

        require(SignatureLib.isValidSignature(controller, digest, signature), &quot;ERC7540Vault/invalid-authorization&quot;);

        isOperator[controller][operator] = approved;
        emit OperatorSet(controller, operator, approved);

        success = true;
    }
    
    function invalidateNonce(bytes32 nonce) external {
        authorizations[msg.sender][nonce] = true;
    }
```

## Security Considerations

Operators have significant control over users and the signed message can lead to undesired outcomes. The expiration date should be set as short as feasible to reduce the chance of an unused signature leaking at a later point.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 03 Jun 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7741</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7741</guid>
      </item>
    
      <item>
        <title>Uncouple blob count between CL and EL</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7742-uncouple-blob-count-between-cl-and-el/20550</comments>
        
        <description>## Abstract

Update blob maximum and target verification from [EIP-4844](/EIPs/EIPS/eip-4844).

The execution layer no longer verifies the blob maximum and receives the target dynamically from the consensus layer.

## Motivation

Following EIP-4844, the execution layer (EL) maintains a hard-coded blob target value and blob maximum value. Given the relationship
of the EL and the consensus layer (CL) node software, the verification of the blob maximum is redundant so it can be removed
entirely without any change in security. The blob maximum is still provided during block construction via the Engine API.
This EIP also changes how the EL sources the current blob target value for two reasons:

1) Gain more flexibility over the value, rather than the static `TARGET == MAX // 2` relation in EIP-4844.

2) Uncouple development and deployment of the CL and EL layers in the event it is desirable to change the blob target value.

### Background

The data facility introduced via EIP-4844 adds blobs to Ethereum blocks, which are simply fixed sets of data that can be
included in the canonical chain but have no execution semantics (cf. `calldata` in an Ethereum transaction).

The protocol specifies a maximum allowed blob count per block to prevent DoS vectors via the abuse of this data facility.
The protocol also maintains an [EIP-1559](/EIPs/EIPS/eip-1559)-like &quot;target&quot; value for an intended running average amount of blob throughput per
unit time. Blob usage is compared against this target to influence a &quot;blob base fee&quot; to administer allocation of this
resource to users of the Ethereum protocol.

Both of these values are currently hard-coded in the EL after EIP-4844 and the blob maximum is separately hard-coded in
the CL following EIP-4844. This EIP proposes a set of changes to uncouple these values across the CL and EL to make development
and deployment of changes to the blob count easier.

#### Maximum blobs per block

The blob maximum is verified in the CL node and the EL inherits this verification during the consistency check of the
versioned hashes corresponding to each blob as specified by the Engine API. Because of this, the strict check specified
by EIP-4844 is unnecessary.

#### Target amount of blobs per block

The target is currently specified as a fixed value in relation to the blob count. The Ethereum community intends to increase
the blob parameters as part of its scaling strategy and the ability to have a more flexible target value in relation to
the blob max is desirable to reduce rigidity in this protocol parameter.

Even if the EL keeps a fixed target value based on the max, removing the max implies the EL would not know what the target
value should be. To address this lack of information, this EIP proposes the CL sends the current target value to the EL
with each provided payload over the Engine API. The EL block header will also need to be extended with this target value
to preserve the security of optimistic sync.

## Specification

### Block structure and validity

Upon activation of this EIP, execution clients **MUST** extend the header schema with an
additional 64-bit field: the `target_blobs_per_block`. This value is set to the current target blob count. The Engine API
is modified along with this EIP to provide the `target_blobs_per_block` with each payload and implementations can use this
value to correctly set the block header field.

Validity of the `target_blobs_per_block` is guaranteed from the consensus layer, much like how withdrawals are handled.

When verifying a block, execution clients **MUST** ensure the target blob count in the block header matches the one
provided by the consensus client.

For a genesis block with no existing parent, the value should be set according to the agreed specification for the
target blob count given by that genesis block&apos;s protocol rule set.

### Block processing

Upon activating this EIP (i.e. before processing any transactions),
the verification of the blob maximum as given in EIP-4844 can be skipped. Concretely, this means any logic relating
to `MAX_BLOB_GAS_PER_BLOCK` as given in EIP-4844 can be deprecated.

Additionally, `calc_excess_blob_gas` is updated as follows:

```python
def calc_excess_blob_gas(parent: Header) -&gt; int:
    target_blob_gas = parent.target_blobs_per_block * GAS_PER_BLOB
    if parent.excess_blob_gas + parent.blob_gas_used &lt; target_blob_gas:
        return 0
    else:
        return parent.excess_blob_gas + parent.blob_gas_used - target_blob_gas
```

Otherwise, the specification of EIP-4844 is not changed. For example, blob base fee accounting and excess blob gas tracking occur in the exact same way.

### Block construction

The Engine API is extended to provide both the `target_blobs_per_block` and the `max_blobs_per_block` when the CL requests the EL to construct a payload for proposal.

These values should be used to ensure the correct number of blobs are included in any constructed payload, and to ensure that the blob base fee accounting is correctly computed.

## Rationale

### Why not have the CL also compute the blob base fee and remove any notion of blob counts from EL processing?

Hoisting the full computation into the CL is possible, but it does violate the separation of concerns between these two layers of the protocol stack.
The CL maintains a maximum value to address e.g. DoS risks, and the EL maintains knowledge of the target value to address fee accounting.
Putting the target computation in the CL violates the respective responsibilities of each layer.

## Backwards Compatibility

No issues.

## Test Cases

N/A

## Reference Implementation

N/A

## Security Considerations

N/A

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 12 Jul 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7742</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7742</guid>
      </item>
    
      <item>
        <title>Multi-Owner Non-Fungible Tokens (MO-NFT)</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/discussion-on-eip-7743-multi-owner-non-fungible-tokens-mo-nft/20577</comments>
        
        <description>## Abstract

This ERC proposes a new standard for non-fungible tokens (NFTs) that supports multiple owners. The MO-NFT standard allows a single NFT to have multiple owners, reflecting the shared and distributable nature of digital assets. This model incorporates mechanisms for provider-defined transfer fees and ownership archiving, enabling flexible and collaborative ownership structures. It maintains compatibility with the existing [ERC-721](/EIPs/EIPS/eip-721) standard to ensure interoperability with current tools and platforms.

## Motivation

Traditional NFTs enforce a single-ownership model, which does not align with the inherent duplicability and collaborative potential of digital assets. MO-NFTs allow for shared ownership, promoting wider distribution and collaboration while maintaining secure access control. The inclusion of provider fees and ownership archiving enhances the utility and flexibility of NFTs in representing digital assets and services.

## Specification

### Token Creation and Ownership Model

1. **Minting**:

   - The function `mintToken()` allows the creation of a new MO-NFT. The caller becomes both the initial owner and the provider of the token.

     ```solidity
     function mintToken() public onlyOwner returns (uint256);
     ```

   - A new `tokenId` is generated, and the caller is added to the owners set and recorded as the provider. The `balanceOf` the caller is incremented.

2. **Ownership List**:

   - The MO-NFT maintains a list of owners for each token. Owners are stored in an enumerable set to prevent duplicates and allow efficient lookup.

3. **Provider Role**:

   - The provider is the initial owner who can set and update the `transferValue` fee. Only the provider can modify certain token parameters.

4. **Transfer Mechanism**:

   - Owners can transfer the token to new owners using `transferFrom`. The transfer adds the new owner to the list without removing existing owners and transfers the `transferValue` fee to the provider.

     ```solidity
     function transferFrom(address from, address to, uint256 tokenId) public;
     ```

### Transfer of Ownership

1. **Additive Ownership**:

   - Transferring ownership adds the new owner to the ownership list without removing current owners. This approach reflects the shared nature of digital assets.

2. **Provider Fee Handling**:

   - During a transfer, the specified `transferValue` fee is transferred to the provider. The contract must have sufficient balance to cover this fee.

3. **Archiving Ownership**:

   - Owners can mark themselves as archived for a specific token, meaning they can no longer transfer that token. Once set, this status cannot be reversed. And for Digital Asset platform, this status means the owner can download the real digital asset directly; if it is not archived, then it must be changed to archived first, then owner can download the real digital asset.

     ```solidity
     function archive(uint256 tokenId) external;
     ```


### Interface Definitions

**Minting Functions**

- `function mintToken() public onlyOwner returns (uint256);`

- `function provide(string memory assetName, uint256 size, bytes32 fileHash, address provider, uint256 transferValue) external returns (uint256);`

**Transfer Functions**

- `function transferFrom(address from, address to, uint256 tokenId) public;`

- `function safeTransferFrom(address from, address to, uint256 tokenId) public;` *(Disabled or overridden)*

- `function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public;` *(Disabled or overridden)*

**Ownership Management Functions**

- `function isOwner(uint256 tokenId, address account) public view returns (bool);`

- `function getOwnersCount(uint256 tokenId) public view returns (uint256);`

- `function balanceOf(address owner) external view returns (uint256 balance);`

- `function ownerOf(uint256 tokenId) external view returns (address owner);`

**Provider Functions**

- `function setTransferValue(uint256 tokenId, uint256 newTransferValue) external;`

**Archived Status Function**

- `function archive(uint256 tokenId) external;`

### Events

- `event TokenMinted(uint256 indexed tokenId, address indexed owner);`

- `event TokenTransferred(uint256 indexed tokenId, address indexed from, address indexed to);`

- `event TransferValueUpdated(uint256 indexed tokenId, uint256 oldTransferValue, uint256 newTransferValue);`

- `event ArchivedStatusUpdated(uint256 indexed tokenId, address indexed owner, bool archived);`


### [ERC-721](/EIPs/EIPS/eip-721) Compliance

The MO-NFT standard is designed to be compatible with the [ERC-721](/EIPs/EIPS/eip-721) standard. It implements required functions such as `balanceOf`, `ownerOf`, and `transferFrom` from the `ERC721` interface.

- **Approval Functions**: Functions like `approve`, `getApproved`, `setApprovalForAll`, and `isApprovedForAll` are intentionally disabled or overridden, as they do not align with the MO-NFT multi-owner model.

- **Safe Transfer Functions**: The `safeTransferFrom` functions are restricted because traditional ERC-721 transfer safety checks are not applicable when ownership is additive rather than exclusive.

- **Supports Interface**: The `supportsInterface` function ensures that the MO-NFT declares compatibility with the ERC-721 standard, allowing it to be integrated with existing tools and platforms.

  ```solidity
  function supportsInterface(bytes4 interfaceId) public view returns (bool) {
      return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC165).interfaceId;
  }
  ```

## Rationale

1. **Multi-Ownership Model**:

   - Digital assets are inherently duplicable and can be shared without loss of quality. The multi-owner model allows broader distribution and collaboration while maintaining a unique token identity.

2. **Additive Ownership**:

   - By adding new owners without removing existing ones, we support shared ownership models common in collaborative environments and digital content distribution.

3. **Provider Fee Mechanism**:

   - Incorporating a provider fee incentivizes creators and providers by rewarding them whenever the asset is transferred. This aligns with models where creators receive royalties or fees for their work.

4. **Ownership Archiving**:

   - Allowing owners to archive themselves from the ownership list provides flexibility, enabling owners to relinquish rights or prevent further transfers of the asset. This replaces the previous concept of &quot;burning&quot; ownership.

5. **ERC-721 Compatibility**:

   - Maintaining compatibility with ERC-721 allows MO-NFTs to leverage existing infrastructure, tools, and platforms, facilitating adoption and interoperability.

## Backwards Compatibility

While the MO-NFT standard aims to maintain compatibility with ERC-721, certain deviations are necessary due to the multi-owner model:

- **Disabling Approvals Functions**: Traditional ERC-721 approvals assume that a single owner has the right to grant or revoke approvals. In MO-NFT, a token can have multiple owners. Without a protocol-defined mechanism for “co-ownership consensus,” an approval system would open the door to an unintentional or unwanted transfer if only one co-owner granted approval. We felt this approach could undermine the shared-ownership model, so the reference implementation chooses to revert calls to approval-related functions.

This may limit compatibility with existing NFT platforms and marketplaces that rely on approve or setApprovalForAll. In principle, developers could extend the MO-NFT standard with more advanced “multi-signature” or “consensus-based” approvals, but that is beyond the scope of this initial EIP. Our goal is to keep the core standard minimal and avoid confusion for marketplaces that were built with single-owner assumptions.

- **Safe Transfer Functions**: The “safe” variants of ERC-721 transfers (safeTransferFrom) serve to protect tokens from being accidentally sent to non-compliant contracts. Because MO-NFT’s multi-owner approach does not inherently break the logic of “checking whether the recipient can handle ERC-721 tokens.

Implementing “safe” in the same manner as ERC-721: after a new owner is added, check `onERC721Received` on the recipient contract.

- **`ownerOf` Function**: Returns the first owner in the owners list for compatibility, but the concept of a single owner does not fully apply.

Developers should be aware of these differences when integrating MO-NFTs into systems designed for standard ERC-721 tokens.

## Test Cases

1. **Minting an MO-NFT and Verifying Initial Ownership**:

   - **Input**:

     - Call `mintToken()` as the provider.

   - **Expected Output**:

     - A new `tokenId` is generated.

     - The caller is added as the first owner.

     - The `balanceOf` the caller increases by 1.

     - The provider is recorded for the token.

     - `TokenMinted` event is emitted.

2. **Transferring an MO-NFT and Verifying Provider Fee Transfer**:

   - **Input**:

     - Call `transferFrom(from, to, tokenId)` where `from` is an existing owner and `to` is a new address.

   - **Expected Output**:

     - The `to` address is added to the owners list.

     - The `transferValue` fee is transferred to the provider.

     - The `balanceOf` of the `to` address increases by 1.

     - `TokenTransferred` event is emitted.

3. **Archiving Ownership**:

   - **Input**:
     - An owner calls `archive(tokenId)`.

   - **Expected Output**:
     - The owner’s transfer ability for that token is archived.
     - The owner can no longer transfer that token.
     - `ArchivedStatusUpdated` event is emitted.

4. **Setting Transfer Value**:

   - **Input**:

     - The provider calls `setTransferValue(tokenId, newTransferValue)`.

   - **Expected Output**:

     - The `transferValue` is updated in the contract.

     - `TransferValueUpdated` event is emitted.

5. **Failing Transfer to Existing Owner**:

   - **Input**:

     - Attempt to `transferFrom` to an address that is already an owner.

   - **Expected Output**:

     - The transaction reverts with the error `&quot;MO-NFT: Recipient is already an owner&quot;`.

     - No changes to ownership or balances occur.


## Reference Implementation

The full reference implementation code for the MO-NFT standard is included in the EIPs repository under assets folder. This ensures the code is preserved alongside the EIP and remains accessible.

- **Contracts**:

  - [`MONFT.sol`](/EIPs/assets/eip-7743/MONFT.sol): The base implementation of the MO-NFT standard.

  - [`DigitalAsset.sol`](/EIPs/assets/eip-7743/DigitalAsset.sol): An extended implementation for digital assets with provider fees.

- **Interfaces**:

  - [`IDigitalAsset.sol`](/EIPs/assets/eip-7743/IDigitalAsset.sol): Interface defining the functions for digital asset management.

### Key Functions in Reference Implementation

**Minting Tokens**

```solidity
function mintToken() public onlyOwner returns (uint256) {
    _nextTokenId++;

    // Add the sender to the set of owners for the new token
    _owners[_nextTokenId].add(msg.sender);

    // Increment the balance of the owner
    _balances[msg.sender] += 1;

    // Set the provider to the caller
    _providers[_nextTokenId] = msg.sender;

    emit TokenMinted(_nextTokenId, msg.sender);
    return _nextTokenId;
}
```

**Transferring Tokens**

```solidity
function transferFrom(address from, address to, uint256 tokenId) public override {
    require(isOwner(tokenId, msg.sender), &quot;MO-NFT: Caller is not an owner&quot;);
    require(to != address(0), &quot;MO-NFT: Transfer to zero address&quot;);
    require(!isOwner(tokenId, to), &quot;MO-NFT: Recipient is already an owner&quot;);

    // Add the new owner to the set
    _owners[tokenId].add(to);
    _balances[to] += 1;

    // Transfer the transferValue to the provider
    uint256 transferValue = _transferValues[tokenId];
    address provider = _providers[tokenId];
    require(address(this).balance &gt;= transferValue, &quot;Insufficient contract balance&quot;);

    (bool success, ) = provider.call{value: transferValue}(&quot;&quot;);
    require(success, &quot;Transfer to provider failed&quot;);

    emit TokenTransferred(tokenId, from, to);
}
```

**Archiving Ownership**

```solidity
function archive(uint256 tokenId) external {
        require(
            isOwner(tokenId, msg.sender),
            &quot;MO-NFT: Caller is not the owner of this token&quot;
        );
        // Once archived, the status cannot be reversed
        require(
            _archivedStatus[tokenId][msg.sender] == false,
            &quot;MO-NFT: Token can only be archived once for an owner&quot;
        );
        _archivedStatus[tokenId][msg.sender] = true;
        emit ArchivedStatusUpdated(tokenId, msg.sender, archived);
    }
```

## Security Considerations

1. **Reentrancy Attacks**:

   - **Mitigation**: Use the Checks-Effects-Interactions pattern when transferring Ether (e.g., transferring `transferValue` to the provider).

   - **Recommendation**: Consider using `ReentrancyGuard` from OpenZeppelin to prevent reentrant calls.

2. **Integer Overflow and Underflow**:

   - **Mitigation**: Solidity 0.8.x automatically checks for overflows and underflows, throwing exceptions when they occur.

3. **Access Control**:

   - **Ensured By**:

     - Only owners can call transfer functions.

     - Only providers can set the `transferValue`.

     - Use of `require` statements to enforce access control.

4. **Denial of Service (DoS)**:

   - **Consideration**: Functions that iterate over owners could be expensive in terms of gas if the owners list is large.

   - **Mitigation**: Avoid such functions or limit the number of owners.

5. **Data Integrity**:

   - **Ensured By**: Proper use of Solidity&apos;s data types and structures, and by emitting events for all state-changing operations for off-chain verification.

6. **Ether Handling**:

   - **Consideration**: Ensure the contract can receive Ether to handle provider payments.

   - **Mitigation**: Implement a `receive()` function to accept Ether.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 13 Jul 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7743</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7743</guid>
      </item>
    
      <item>
        <title>Code Index</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7744-code-index/20569</comments>
        
        <description>## Abstract

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.

## Motivation

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.

Consider a security auditor who wants to attest to the integrity of a contract&apos;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&apos;s codebase without auditing the entire contract state.

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.

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.

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.

### Why this registry needs to be an ERC

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.

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.

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.

## Specification

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

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity 0.8.28;
import {IERC7744} from &quot;./IERC7744.sol&quot;;

/**
 * @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)
 */
contract ERC7744 is IERC7744 {
    mapping(bytes32 =&gt; address) private index;

    function isEIP7702(address account) public view returns (bool) {
        bytes3 prefix;
        assembly {
            extcodecopy(account, 0, mload(0x40), 3) // Copy first 3 bytes to memory
            prefix := mload(0x40) // Load the 3 bytes from memory
        }
        return prefix == bytes3(0xef0100);
    }

    function isValidContainer(address container) private view returns (bool) {
        bytes memory code = container.code;
        bytes32 codeHash = address(container).codehash;
        return (code.length &gt; 0 &amp;&amp; codeHash != bytes32(0) &amp;&amp; !isEIP7702(container));
    }

    /**
     * @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
     */
    function register(address container) external {
        address etalon = index[container.codehash];
        require(isValidContainer(container), &quot;Invalid container&quot;);
        if (etalon != address(0)) {
            if (isValidContainer(etalon)) revert alreadyExists(container.codehash, container);
        }
        index[container.codehash] = container;
        emit Indexed(container, container.codehash);
    }

    /**
     * @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
     */
    function get(bytes32 id) external view returns (address) {
        return index[id];
    }
}
```

### Deployment method

The `CodeIndex` contract is deployed at: `0xC0De1D1126b6D698a0073A4e66520111cEe22F62` using `CREATE2` via the deterministic deployer at `0x4e59b44847b379578588920ca78fbf26c0b4956c` with a salt of `0x9425035d50edcd7504fe5eeb5df841cc74fe6cccd82dca6ee75bcdf774bd88d9` is obtained by seeking a vanity address starting with meaningful name &quot;Code ID (`c0de1d`) for a bytecode compiled with `solc 0.8.28` as `solc --input-file src/ERC7744.sol --bin --optimize --optimize-runs 2000 --metadata-hash none --via-ir --optimize-yul`

## Rationale

**Bytecode over Addresses**: Bytecode is deterministic and can be verified on-chain, while addresses are opaque and mutable.

**Reverting on re-indexing**: There is small, yet non-zero probability of hash collision attack. Disallowing updates to indexed location of bytecode coupes with this.

**Simple Interface**: The interface is minimal and focused to maximize composability and ease of implementation.

**Library Implementation**: 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.

## Reference Implementation

Reference implementation of the Code Index can be found in the assets folder. There you can find the [interface](/EIPs/assets/eip-7744/IERC7744.sol) and the [implementation](/EIPs/assets/eip-7744/ERC7744.sol) of the Code Index.

## Security Considerations

**Malicious Code**: 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.

**Storage contents of registered contracts**: 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.

**[EIP-7702]**: The index does not index the EIP-7702 delegated accounts. During attempt to register, it checks if contract code begins with reserved delegation designator `0xef0100` and if so, it will revert.

**Self-Destruct Contracts**: In case of indexed contract storage becomes empty, contracts may be re-indexed, During register function call, if contract is already indexed, we run `isValidContainer` check on the indexed address. It it fails, re-indexing is allowed with a newly specified address.

[EIP-7702]: /EIPs/EIPS/eip-7702

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Trustless log and transaction index</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7745-two-dimensional-log-filter-data-structure/20580</comments>
        
        <description>## Abstract

Replace the fixed 2048 bit log event bloom filters with a new lookup index data structure that can adapt to the changing number of events per block and consistently guarantee a sufficiently low false positive ratio, allowing efficient trustless proofs of log event queries, canonical block hash and transaction hash lookups.

The proposed structure maps all index entries (log events, transaction and block markers) onto a global linear index space and hashes them into a binary Merkle tree based on that index. It also contains a _filter map_ for every fixed length section of the index space. These are two dimensional sparse bit maps that provide an efficient probabilistic method for looking up indexed values or query patterns of values, yielding potential matches in the form of exact positions in the linear index space. Unlike the per-block bloom filters, they allow searching for specific events by accessing only a small portion of the entire dataset which can also be proven with a Merkle proof, making the search both efficient and light client friendly.

The proposed structure can be efficiently used both for local search and for remote proof generation/verification, thereby simplifying implementation of provers and verifiers. It also allows validators that are not interested in either searching or proving logs to generate the index root hash by maintaining a minimal index state with a relatively small (hard capped) size.

## Motivation

Adding logs has a significantly lower gas cost and should accordingly be less resource consuming than writing to the state. The original design of bloom filters in each block achieves this goal as there is no complex data structure like the state to update, the set of logs emitted in each block is all contained within the header and receipts belonging to that block. Logs mostly just have long term storage costs. On the other hand, searching logs in a long range of blocks is very expensive and the current bloom filters do not really help.

Bloom filters are only useful as long as they are sufficiently sparse. False positive ratio rises rapidly with the number of events per filter and the density of `1` bits in the filter bit vector. In the currently existing bloom filter each log address and topic sets 3 out of a fixed length of 2048 bits which resulted in sufficiently sparse filters in the beginning but with the increase of the block gas limits the false positive ratio soon made the filter practically useless. Mainnet blocks currently add over 1000 log addresses and topics in average and therefore the bloom filter size would need to increase about tenfold in order to achieve acceptable false positive rates again. This would raise block header size to about 3 kilobytes. Even if the size of the per-block bloom filters would be raised to a sufficient level, log search would still require accessing the entire header chain. Searching in just the most recent one year history would cost over 6 gigabytes of data, not counting the access of actual logs where the bloom filters have a match. The current situation is even worse, requiring a large portion of the full block receipt sets to be accessed due to the high false positive rate of the bloom filters. Transaction inclusion lookup is also very expensive, requiring all block bodies in the searched range.

While full nodes and RPC servers can and usually do build additional index structures to aid certain lookups, these structures cannot be verified remotely. While it is important to improve the transaction processing capabilities of Ethereum, trustless provability is required throughout the entire stack, from end user applications signing transactions, to the same or other end user applications getting the results they need. Scaling transaction processing only makes sense as long as there is also a trustless and scalable way to access the relevant results of those transactions. Users relying on trusted servers and indexers kind of beats the whole point of Ethereum.

## Specification

### Terms and definitions

- _index entry_: a single entry in the `index_entries` tree associated with an indexed event. It is either a _log entry_, a _transaction entry_ or a _block entry_. An _index entry_ generates one or more _map values_. Each _log entry_ adds one _address value_ and 0..4 _topic values_ (in this order). Each _transaction entry_ adds one _transaction value_ and each _block entry_ adds one _block value_. 
- _map value_: a searchable value associated with an _index entry_. It is either an _address value_, a _topic value_, a _transaction value_ or a _block value_. Each _map value_ is represented by a 32 byte hash (the _map value hash_) which is calculated as `sha2(address)`, `sha2(topic)`, `sha2(tx_hash + b&quot;\x01&quot;)` or `sha2(block_hash + b&quot;\x02&quot;)`.
- _map value index_: a single position in the global linear index space. A new _map value index_ is assigned to each indexed _map value_.
- _map entry index_: the position where an _index entry_ is located in the `index_entries` tree. Each _index entry_ is located at the position corresponding to the _map value index_ of the first _map value_ it generates.
- _filter map_: a `MAP_WIDTH` by `MAP_HEIGHT` sized sparse bit map assigned to a `VALUES_PER_MAP` length section of the _map value index_ space. Each _map value_ assigned to this range is marked on the map at a row and column that depends on the _map value index_, _mapping layer_ and the _map value hash_. Rows are sparsely encoded as a list of marked column indices (in strictly ascending order, which also coincides with the order of occurence). Each map contains at most `VALUES_PER_MAP` marks and therefore the chance of false positives is kept at a constant low level.
- _mapping layer_: each layer defines a (_map index_, _map value hash_) =&gt; _row index_ mapping and imposes a limit on the number of _map values_ mapped into each row using that particular mapping. Multiple _mapping layers_ can be applied simultaneously on the same _filter map_. Each _map value_ is mapped using the lowest possible _mapping layer_ where the number of marks in the assigned row is lower than the limit. On layer 0 the _row index_ mapping only changes once per _index epoch_. On higher layers the mapping changes more frequently and also the row size limit is higher.
- _index epoch_: a `MAPS_PER_EPOCH` sized group of consecutive _filter maps_ stored in the hash tree in a way so that multiple rows of adjacent _filter maps_ with the same _row index_ can be efficiently retrieved in a single Merkle multiproof.

### Consensus data format

#### Block headers

Beginning at the execution timestamp `FORK_TIMESTAMP`, execution clients MUST replace the `logs_bloom` field of the header schema with `log_index_root` which is the root hash of the `LogIndex` structure after adding the logs emitted in the given block.

The resulting RLP encoding of the header is therefore:

```
rlp([
    parent_hash,
    0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347, # ommers hash
    coinbase,
    state_root,
    txs_root,
    receipts_root,
    log_index_root,
    0, # difficulty
    number,
    gas_limit,
    gas_used,
    timestamp,
    extradata,
    prev_randao,
    0x0000000000000000, # nonce
    base_fee_per_gas,
    withdrawals_root,
    blob_gas_used,
    excess_blob_gas,
    parent_beacon_block_root,
])
```

#### Container types

These definitions use the `ProgressiveList` and `ProgressiveByteList` SSZ types as defined in [EIP-7916](/EIPs/EIPS/eip-7916).

Note that the `LogIndex` and `IndexEpoch` container definitions below are &quot;naive&quot; definitions suitable to define SSZ merkleization. The entire log index is typically too big to be represented in memory as a whole. A more efficient implementation can be found here: [log_index.py](/EIPs/assets/eip-7745/log_index.py), [binary_tree.py](/EIPs/assets/eip-7745/binary_tree.py)  (taken from the EELS implementation). This code keeps only the currently processed parts of the tree in memory, expanding untouched empty subtrees on demand and collapsing finalized subtrees.

Also note that the containers defined here (including `FilterRow`) have a non-initialized default value, represented as a null leaf in the Merkle tree. Initialization of these containers is explicit and happens at a well defined point. `IndexEpoch` is initialized when the first _index entry_ is added to the epoch. All rows of a map are initialized when the first _index entry_ is added to the map. `IndexEntry` is initialized when added; entry positions belonging to unused _map entry indices_ are left uninitialized. The `Log` container is only initialized in case of _log entries_. If it is initialized then `topics` and `data` lists in the `Log` container are always initialized.

```
class LogIndex(Container):
    epochs: Vector[IndexEpoch, MAX_EPOCH_HISTORY]
    next_index: uint64

class IndexEpoch(Container):
    filter_maps: Vector[Vector[FilterRow, MAPS_PER_EPOCH], MAP_HEIGHT]
    index_entries: Vector[IndexEntry, MAPS_PER_EPOCH * VALUES_PER_MAP]

type FilterRow = ProgressiveList[uint32]

class IndexEntry(Container):
    log_entry: Log
    entry_meta: Vector[Bytes32, 4] # LogMeta / TransactionMeta / BlockMeta

class Log(Container):
    address: ExecutionAddress
    topics: List[Bytes32, 4]
    data: ProgressiveByteList
```

The `entry_meta` vector has a fixed format but its interpretation depends on the type of _index entry_ and the type of entry can also be determined based on its contents (and based on whether `log_entry` is initialized or not). Whenever `IndexEntry` is initialized, `entry_meta` contains either one of these containers:

```
class LogMeta(Container):
    block_number: uint64
    transaction_hash: Root
    transaction_index: uint64
    log_in_tx_index: uint64

class TransactionMeta(Container):
    block_number: uint64
    transaction_hash: Root
    transaction_index: uint64
    receipt_hash: Root
 
class BlockMeta(Container):
    block_number: uint64
    block_hash: Root
    timestamp: uint64
    zero: uint64
```

#### Index entry types and corresponding map values

Three types of _index entries_ are added during state transition: log, transaction and block. For each processed transaction, a _transaction entry_ is added first, then _log entries_ are added in the order of EVM execution. The _block entry_ referring to the processed block is not added during the state transition because it is supposed to reference the block hash which is not known yet. It can be added either after block building/validaton or are the beginning of the next state transition. In either case, the `block entry` of block N first appears in the log index state of block N+1 as the first new `index entry`.

The following table shows an example of mapping all index entry types onto the _map value index_ space:

| Index entry  | Map entry index | Map values     | Map value indices  |
|--------------|-----------------|----------------|--------------------|
| Block #0     | 0               | Block          | 0                  |
| Tx    #1/0   | 1               | Transaction    | 1                  |
| Log   #1/0/0 | 2               | Addr, 3x Topic | 2, 3, 4, 5         |
| Log   #1/0/1 | 6               | Addr, 3x Topic | 6, 7, 8, 9         |
| Tx    #1/1   | 10              | Transaction    | 10                 |
| Log   #1/1/0 | 11              | Addr, 2x Topic | 11, 12, 13         |
| Log   #1/1/1 | 14              | Addr, Topic    | 14, 15             |
| Log   #1/1/2 | 16              | Addr, 2x Topic | 16, 17, 18         |
| Block #1     | 19              | Block          | 19                 |
| Tx    #2/0   | 20              | Transaction    | 20                 |
| Log   #2/0/0 | 21              | Addr, 4x Topic | 21, 22, 23, 24, 25 |

Note that the missing _map entry indices_ are represented in the `index_entries` tree with uninitialized `IndexEntry` containers (zero value leaves in the `index_entries` vector). Most of these empty entries correspond to the _topic value_ indices. Also, the last few entries of each map might be emtpy because the _map values_ generated by a single _index entry_ never cross a filter map boundary. So, for example, when `VALUES_PER_MAP` is 0x10000 and `next_index` is `0x2FFFE` and a _log entry_ with on address and two topics is added, the last two positions of the map are left empty and the new _log entry_ is added starting from position 0x30000.

#### Filter map row encoding

Each row of the _filter map_ is encoded as a series of little endian binary encoded column indices. For encoding simplicity the column indices are always encoded as 32 bit values, regardless of the fact that `MAP_WIDTH` is less than 32. This only applies to consensus encoding and hashing though while local storage and proof encoding can use a more tightly packed format.

#### Proposed constants

| Name                | Value                  |
|---------------------|------------------------|
| MAP_WIDTH           | 2**24                  |
| MAP_HEIGHT          | 2**16                  |
| VALUES_PER_MAP      | 2**16                  |
| MAPS_PER_EPOCH      | 2**10                  |
| MAX_EPOCH_HISTORY   | 2**24                  |
| MAX_ROW_LENGTH      | [8, 168, 2728, 10920]  |
| MAPPING_FREQUENCY   | [2\**10, 2\**6, 2\**2, 1] |

Note that `MAX_ROW_LENGTH` and `MAPPING_FREQUENCY` parameters are specified as lists because the applicable values depend on the used _mapping layer_. For layers higher than the index of the last elements of these lists the last element is applicable. Also note that the `MAX_ROW_LENGTH` values correspond to the cumulative capacity of `ProgressiveList` tree levels; a layer 0 row fits into the first level, a layer 1 row fits into the first three levels and so on.

### Constructing the filter map

For each `VALUES_PER_MAP` long section of the _map value index_ space a _filter map_ is generated. These are fixed size `MAP_WIDTH` by `MAP_HEIGHT` sparse bit maps and each _map value_ is marked on the map with a single bit being set to one. The number of marks in a row (the length of the sparse encoded row) is referred to as &quot;row length&quot;, not to be confused with the constant `MAP_WIDTH`.

#### Epochs and mapping layers

In order to allow efficient search of a certain _map value_ in a long historical range, _filter maps_ are organized into _index epochs_, each consisting of a fixed `MAPS_PER_EPOCH` number of maps. In the most usual case (when row density is around average or below) row mapping stays the same  during an entire epoch. The hash tree is organized in a way that instead of putting all rows of a single map close to each other, rows of the same _row index_ throughout an entire epoch are close to each other and therefore are cheap to access and/or prove with a Merkle proof.

In order to mitigate collisions in densely populated rows, the concept of _mapping layers_ is introduced, meaning that if a certain row already has a certain number of entries then the row mapping is changed and very frequent _map values_ are mapped into multiple rows. Initially, when a map is empty, every _map value_ is mapped using _mapping layer_ 0 or the &quot;base layer&quot;. If a row reaches `MAX_ROW_LENGTH[0]` then any further _map values_ mapped onto that row in the base layer mapping will use layer 1 mapping instead. On layer 1 a different row is assigned to the same _map value_ and the row length limit in increased to `MAX_ROW_LENGTH[1]`. If this row also reaches its limit, layer 2 mapping is used and so on. Note that a row filled at a certain _mapping layer_ can be grown further on a higher layer. Different _map values_ colliding in the same row on a certain layer are probably mapped in different rows on the next layer, which means that a very popular value might populate multiple rows (also very long ones) but an unlucky less popular one colliding with it on base layer will probably just have to move one layer up. The search process is similar, if the searcher finds that the row belonging to the searched value is full according to the base layer limit then it also has to check the next layer and so on, until it finds a non-full row.

If a row is longer than the limit according to the layer the searcher is looking at then it can safely ignore the extra entries assuming that they were added by another value on a higher layer. The `ProgressiveList` container makes it efficient to prove row data belonging to the lower layer even if there is much more data in the same row added on a higher layer.

#### Row mapping

While base layer row mapping stays the same for an entire epoch, higher layer mappings are changed more frequently. Each mapping change has a cost in terms of database access overhead and Merkle proof size overhead and epoch size is determined in a way that these overheads stay sufficiently low compared to the cost of accessing the actual useful data. On higher layers where the rows are longer, a more frequent remapping is possible because the useful data size per map is also higher. It is also desirable so that a less frequent _map value_ will only suffer from colliding with a more popular one for a shorter time.

The _row index_ is calculated as follows:

```
def get_row_index(map_index, layer_index: Uint, map_value_hash: Hash32) -&gt; Uint:
    &quot;&quot;&quot;
    Returns the row index where the given map value hash is mapped on the given
    map and mapping layer.
    &quot;&quot;&quot;
    mf_index = min(layer_index, len(MAPPING_FREQUENCY) - 1)
    mapping_frequency = MAPPING_FREQUENCY[mf_index]
    masked_map_index = map_index - (map_index % mapping_frequency)
    row_hash = sha256(
        map_value_hash
        + masked_map_index.to_le_bytes4()
        + layer_index.to_le_bytes4()
    ).digest()
    return Uint.from_le_bytes(row_hash[0:4]) % MAP_HEIGHT
```

The following figure shows how _map values_ are mapped to rows on different _mapping layers_. Each dot represents a map row and the numbers indicate the _mapping layer_ on which the row has been assigned to the given _map value_. Note that it might happen that a higher layer mapping coincides with a lower layer mapping for the same value; this does not cause any problem though as the row is simply grown further on the higher layer. The search algorithm can also simply revisit the same row in a higher layer iteration if necessary and process the rest of the row that it first ignored.

```
map index        111111 1111222222222233 3333333344444444 4455555555556666
       0123456789012345 6789012345678901 2345678901234567 8901234567890123
      +----------------+----------------+----------------+----------------+
row 0 |2........2......|2...............|...2............|........2.......|
row 1 |........1111.2..|.....2..1111....|1111.....2...2..|2111..2......2..|
row 2 |0000000000000000|.2..2....2..2...|....2111....2...|..2.....11112...|
row 3 |....2..22...1111|..........2.1111|2.......2.2.1111|.......2...2....|
row 4 |.2..1111..2....2|1112..2.2....2..|0000000011110020|...21111.2....2.|
row 5 |...2........2...|...............2|.2...2.........2|.2...2..........|
row 6 |1111.22....2..2.|0020000000020000|.......2...2....|..........2.1112|
row 7 |..2.............|....1112......2.|..2...2.........|0000200000000000|
      +----------------+----------------+----------------+----------------+
            epoch 0          epoch 1          epoch 2          epoch 3

Fig 2. Row mapping of a single log value on different mapping layers

MAP_HEIGHT = 8
MAPS_PER_EPOCH = 16
MAPPING_FREQUENCY = [16, 4, 1]
```

#### Column mapping

Column mapping assumes that `MAP_WIDTH` is a multiple of `VALUES_PER_MAP`. _column index_ is calculated as follows:

```
def get_column_index(map_value_index: Uint, map_value_hash: Hash32) -&gt; Uint:
    &quot;&quot;&quot;
    Returns the column index where the given entry hash is mapped at the given
    entry index.
    &quot;&quot;&quot;
    col_hash = fnv1a_64(map_value_index.to_le_bytes8() + map_value_hash)
    folded_hash = (col_hash &gt;&gt; 32) ^ (col_hash &amp; 0xFFFFFFFF)
    hash_bits = LOG2_MAP_WIDTH - LOG2_VALUES_PER_MAP
    return (
        (map_value_index % VALUES_PER_MAP)
        &lt;&lt; hash_bits + folded_hash
        &gt;&gt; (32 - hash_bits)
    )
```

As shown on the figure below, this mapping practically assigns a `MAP_WIDTH // VALUES_PER_MAP` by `MAP_HEIGHT` rectangle to each _map value index_ and ensures that each _map value_ places exactly one mark in its own rectangle (the letters A-D represent different _map values_). This property also ensures that _map value index_ can be restored from _map index_ and _column index_, column indices never collide and keep the original order of _map value_ indices, allowing efficient Merkle exclusion proofs of certain _column indices_ in long rows.

```
column             11 1111 1111 2222 2222 2233
       0123 4567 8901 2345 6789 0123 4567 8901
      +---------------------------------------+
row 0 |.... .... .... .... .... .... .... ....|
row 1 |.... .... .... .... .... .C.. .... ....|
row 2 |.A.. .... ...A .... A... .... ...A ....|
row 3 |.... .... .... .... .... .... .... ....|
row 4 |.... .... .... .... .... .... .... ....|
row 5 |.... .B.. .... ...B .... .... .... ....|
row 6 |.... .... .... .... .... .... .... ..D.|
row 7 |.... .... .... .... .... .... .... ....|
      +---------------------------------------+

Fig 3. A single filter map with 8 entries of 4 different log values

MAP_WIDTH = 32
MAP_HEIGHT = 8
VALUES_PER_MAP = 8
```

### Updating the log index and calculating the root hash

See the following functions in [log_index.py](/EIPs/assets/eip-7745/log_index.py):

- `log_index_add_log_entries`
- `log_index_add_transaction_entry`
- `log_index_add_block_entry`
- `log_index_root`

Note that the _block entry_ may be added either after building/verifying the given block or before processing the next one, but `log_index_root` should always be calculated after adding transaction and log entries and before adding the block entry for the some block (block building would not even be possible otherwise as the log index root is referenced in the block header).

### Finding potential matches

Determining whether a _column index_ found in the appropriate row is relevant for the searched _map value_ is possible by restoring the _map value index_ and then calculating the _column index_ from it again in order to check whether the quasi-random collision filter part matches the expected value for the given _map value_:

```
def get_map_value_index(map_index, column_index: Uint) -&gt; Uint:
    map_value_width = MAP_WIDTH // VALUES_PER_MAP
    return map_index * VALUES_PER_MAP + column_index // map_value_width

def is_potential_match(map_index, column_index: Uint, map_value: Hash32) -&gt; bool:
    return get_column_index(get_map_value_index(map_index, column_index), map_value) == column_index
```

Iterating through all relevant _mapping layers_ and corresponding rows is similar to how new _map values_ are added. Filtering all potential matches from all relevant rows can be done with the following function:

```
def get_potential_matches((log_index: LogIndexReader, map_index: Uint, map_value: Hash) -&gt; List[Uint]:
    matches = []
    layer_index = 0
    while True:
        mr_index = min(layer_index, len(MAX_ROW_LENGTH) - 1)
        max_row_length = MAX_ROW_LENGTH[mr_index]
        row_index = get_row_index(map_index, layer_index, map_value)
        row = get_filter_row(log_index, map_index, row_index)[:max_row_length]
        for column_index in row:
            if is_potential_match(map_index, column_index, log_value):
                matches.append(get_log_value_index(map_index, column_index))
        if len(row) &lt; max_row_length:
            break
        layer_index += 1
    return matches
```

### Initialization, minimal state and wire protocol extension

It is a property of the log index tree that over time most of the tree nodes get finalized, which means that in a minimal log index state representation finalized subtrees can be collapsed into a single tree node as their descendants are no longer needed for adding new entries. At every single moment there is one _filter map_ being updated, maybe the few most recently completed maps might still be affected by a reorg, but if the chain finalizes properly then all but the few most recent maps are also finalized. Internal tree nodes with all finalized children are also finalized and can be collapsed into the lowest finalized ancestor. Similarly, internal nodes covering a range that has not been touched yet can be stored without having their children in memory, and they can be expanded on demand.

Certain types of clients (those only interested in validation and not in using/serving log index data) have the option to just maintain this minimal log index state. Those who are interested in event history should probably also only keep the minimal state in memory and store the finalized and collapsed subtrees on disk. Clients can also initialize their log index with such a minimal state and then optionally regenerate the older parts from blocks and receipts locally. When the log index state of a finalized block is represented and no room for rollback is needed, the minimal tree representation simplifies into a set of Merkle branches leading to the map rows and to the _index entry_ corresponding to `next_index` (with everything on the left side of these branches collapsed and nothing on their right sides expanded yet). Assuming an efficient encoding of the current `filter_map_rows` where the variable length of each filter row is encoded in two bytes and the column indices tightly packed into 3 bytes each, the minimal log index state can be serialized into 21300808 bytes. This number can be considered as an estimate of the amount of data required to initialize the log index data structure at any point.

Note that initialization is also possible on an epoch boundary, in which case the log index is very cheap to initialize (only requires the last _block entry_ branch before the epoch boundary and the first one after) but in this case all blocks and receipts between the boundary and the current head are required to generate the last unfinished epoch. Epoch boundary initialization can also be used to index further historical epochs after the initialization of the head state.

Both head state initialization and epoch boundary initialization requires the extension of the Ethereum Wire Protocol through which clients can request Merkle multiproofs to initialize the required parts of the log index tree, using a recently finalized block as the starting point. Note that since the total amount of initialization data is too big to fit in a single devp2p response, the protocol splits the data into multiple subsets, each obtainable in the form of a separately verifiable log index Merkle proof. See the [wire protocol extension](/EIPs/assets/eip-7745/wire_protocol_extension) and [log index proof format](/EIPs/assets/eip-7745/log_index_proof_format) specs for further details.

## Rationale

### Design goals

The proposed data structure is intended to realize a balance between the cost of adding items and accessing old ones. In a search structure of a constantly growing dataset there is typically a tradeoff between the cost of adding new data and the cost of searcing the existing dataset. One extreme is just linearly storing the data, which is practically the case now with logs, with the bloom filters being mostly useless. The other extreme is one big Merkle tree with all _map values_ ever used as keys and the list of all occurences (possibly in a further merkleized format) as values. With billions of unique _map values_, adding new entries here is expected to have costs similar to that of the state, with multiple lookups and modifications/insertions at random places in a database on the order of magnitude of hundreds of gigabytes. Another issue where this is similar to the state is that removing old entries is hard and expensive. Adding logs is supposed to be cheaper than writing the state so solutions between these two extremes were considered as potentially practical, with multiple smaller structures generated periodically.

The _filter maps_ have a fixed tree size and an efficient tree hashing scheme. Filter entries are sorted into rows based on content and position in a way that allows quick linear database access and size efficient Merkle proofs. The difficulties arising from certain types of events being much more frequent than others are also mitigated. Update and maintenance costs are also limited as tree nodes are eventually finalized and the number of non-finalized non-empty nodes is always hard capped, ensuring moderate memory requirements. Initialization costs of the data structure at any point of the chain are also capped. Additional database storage costs of _filter maps_ is about 15-20% of the size of the actual logs, depending on certain implementation tradeoffs. The Merkle tree structure also makes it easy to discard entire epochs along with the corresponding Merkle subtrees, making the implementation of history expiry of the log index simple.

### Map value index space

In each block a varying number of _map values_ are emitted. In addition to inefficient search, another drawback of per-block fixed size bloom filters is the varying filter utilization leading to over-utilized filters giving many false positives in some blocks and/or wastefully under-utilized filters in some blocks. Block gas limits also tend to change significantly over the long term so any future-proof solution has to be able to adapt to the varying number of _map values_ per block.

Mapping _map values_ on their own linear index space ensures uniform filter utilization of identically structured _filter maps_. Compared to the alternative of constantly changing adaptive filter size, this approach greatly improves the efficiency of database access and Merkle proofs. It also allows efficient search pattern filtering as each potential match provides exact position information.

### Index entries tree

Hashing every event into the `index_entries` tree keyed by _map entry index_ is additional work and complexity but it simplifies the proving process significantly. Proving the events based only on _map value indices_ would be possible if receipts had a _map value index_ pointer hashed into them (so the client could also verify that the received receipt actually covers the _map value index_ derived from the _filter map_; in this case though an extra mechanism would be necessary to prove that the receipt is referenced in a block that is part of the same canonical chain where the log index root was referenced. Proving old canonical blocks is currently theoretically possible through the beacon chain but painful and also would require extra infrastructure. On the other hand, the `index_entries` tree not only solves the problem of proving the matching canonical receipts, with the _block entries_ it also provides a convenient way to prove canonical EL blocks through EL data structures only, and even provides provable canonical block hash to block number lookups.

Note though that storing the entire`index_entries` trees directly in their proposed merkleized format on disk is not really efficient. This is not an issue for validators that want to maintain a minimal state; for them, updating the `index_entries` subtrees is really cheap as they only need to maintain a single Merkle branch pointing to the next _map value index_. Provers can implement `index_entries` efficiently by storing a subset of the Merkle tree nodes (the ones at least a few levels below leaf level in order to save space) and generate the rest on demand based on the receipts that encode the same data in a more compact form.

### Alternative filter structures considered

One question considered was whether to periodically build lookup trees of events with each unique _map value_ emitted in a given period being a separate key under which only the occurences of that specific event are listed, or to use a more compressed fixed size tree format where different _map values_ might collide (though preferably not too many of them). This decision mostly boiled down to data access efficiency, both in terms of local disk access and remote Merkle proof size. Identically structured trees can be efficiently arranged in larger units (called _index epochs_ here), with values belonging to the same key in subsequent trees of an epoch located close to each other. This improves database access speed. It also allows smaller Merkle proofs with a series of leaves encoded together in an efficient format and internal nodes on only two boundary branches. Database writes are also efficient as the order of adding tree entries is not random and all the non-finalized parts of the tree can be kept in memory with a hard capped memory requirement.

The other design decision considered here was whether to hash entire index entries into the list of _map value_ occurences or just store position info and have a separate tree of log entries. Though the separate `filter_maps` and `index_entries` structures do present some additional complexity, the second option was chosen because of the size of Merkle proofs. Looking up a rarely used _map value_ means encountering more irrelevant entries than relevant ones. By adding probabilistic filter information to position information, the vast majority of the irrelevant entries can be filtered out after accessing/proving 3 bytes of data instead of an entire _map value_ (32 bytes). When proving matches of multiple _map value_ patterns this 10x advantage exists even with more frequent individual lookup values. Tests have shown that realistic log searches often yield a lot more matches for the individual _map values_ themselves that the pattern itself. Pattern matching can be performed on the position information of individual potential matches and actual _index entries_ only need to be proven at the potential pattern matches.

In conclusion, for the given application the fixed tree size approach with separate position info plus probabilistic collision filter approach seemed to be the most appropriate.

### False positive rate

From the _filter maps_ a set of potential matches can be derived for any block range and _map value_ or pattern of _map values_. These matches can then be looked up in the corresponding `index_entries` trees and actually matching events can be added to the set of results. The design guarantees that the set of potential matches includes all actual matches but and also has a consistently low false positive rate.

False positives can happen when the quasi-random collision filter part of a _column index_ accidentally matches the expected value even though it was generated by a _map value_ other than the searched one. The chance of this happening is `VALUES_PER_MAP / MAP_WIDTH` per colliding enrty in a row that is relevant for the search. Assuming that most entries in a map are different from the searched one, assuming uniform random distribution of entries, the average number of colliding entries found in a relevant row is `VALUES_PER_MAP / MAP_HEIGHT` giving an average false positive rate of `VALUES_PER_MAP ** 2 / MAP_WIDTH / MAP_HEIGHT` per _filter map_.

Though certain _map values_ might be emitted a lot more than others and therefore the _row index_ distribution might not be entirely uniform, periodical remapping of rows and using multiple _mapping layers_ ensures that over a long enough search period random collisions with more frequent _map values_ do even out. _Mapping layers_ do have another consequence though; if any row has at least `MAX_ROW_LENGTH[0]` entries then the search logic requires looking into another row that is mapped to the searched _map value_ on the next _mapping layer_. The maximum possible number of such rows is `VALUES_PER_MAP / MAX_ROW_LENGTH[0]` and therefore the chance of randomly hitting one is `VALUES_PER_MAP / MAX_ROW_LENGTH[0] / MAP_HEIGHT` in the worst case. In this case an extra row has to be processed, with extra chance of finding false positives. A collision with a frequent value at a certain _mapping layer_ does not indicate a collision on the next layer though, therefore the expected number of entries in that row is no different from the first one. Having to process a third row would presume that the second one had at least `MAX_ROW_LENGTH[1]` entries. The chance of this happening after the first coincidence is practically negligible in the context of expected false positives.

The expected number of false positives for a single _map value_ search can be estimated as `VALUES_PER_MAP ** 2 / MAP_WIDTH / MAP_HEIGHT * (1 + VALUES_PER_MAP / MAX_ROW_LENGTH[0] / MAP_HEIGHT)` per _filter map_. With the proposed constants this roughly equals 0.0044 false positives per map. As of March 2025 the average number of _map values_ emitted in a mainnet block is slightly over 1000 while a _filter map_ consists of 65536 _map values_. This gives a rough estimate of one false positive per 14000 blocks, which costs the searcher an extra lookup in a `log_entries` tree. The expected number of false positives in the entire chain history is around 1200.

Note that this is only true for a single value search while a typical pattern search requiring certain values on multiple positions has an exponentially lower false positive rate. For example if the pattern is [Addr, Topic1, Topic2] then three _map value_ searches are performed and an actual log lookup is only necessary if the first search yields `N`, the second `N+1` and the third `N+2` simultaneously. If necessary, the rate can be easily reduced by using a higher `MAP_WIDTH`, at the cost of growing the size of encoded rows.

## Backwards Compatibility

The existing log filter API (`eth_getLogs`, `eth_newFilter`, `eth_getFilterLogs`, `eth_getFilterChanges`) can be implemented with the new filter data structure. Applications relying on this API can operate without any change, benefiting from a higher search performance. Repricing the `LOG` opcode might be considered after performing benchmarks but the extra processing cost is not significant while the extra storage cost is around 15%. Other than that the EVM is not affected in any way as it only emits logs but does not directly access them.

## Security Considerations

### Safe access with a remote prover

In order to prove a complete set of matches matching a given search pattern in a given block range, the prover needs to

- prove the _map value index_ range that corresponds to the searched block number range by proving the _block entries_ of `first_block - 1` and `last_block`
- prove the relevant rows of _filter maps_ based on _map index_ and _row index_ (verifier can determine the relevant rows in advance based on the _map values_ in the search pattern and the relevant _map value index_ range)
- prove the actual _index entry_ belonging to any potentially matching _map value index_ and also the _block entry_ with the same block number if the `blockHash` of the log position info is needed

Since all three steps can be realized with Merkle proofs of the same `LogIndex` structure referenced in the block headers, any search with a remove prover is as safe as the client&apos;s knowledge about the chain head.

### Deliberate false positive attacks

The design guarantees that false positive rates do even out statistically over several epochs, even in case of random collisions with very frequent values, ensuring that an excessive amount false positives will not make the bandwidth and processing costs of the search prohibitively high. All of this is true for random collisions only though, not deliberately created collisions. A deliberate attack on a certain important _map value_ in order to raise its false positive rate can not be ruled out entirely since with a low amount of filter data generated per _map value_ it is always possible to &quot;mine&quot; another value that generates colliding filter data. The column mapping used here makes this attack a lot harder though, since the _column index_ depends on both the _map value_ and the exact _map value index_, making this attack only possible for block builders who are probably offered MEV rewards for much more lucrative manipulations of the transaction set than making the search of certain events slightly more expensive.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 17 Jul 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7745</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7745</guid>
      </item>
    
      <item>
        <title>Composable Security Middleware Hooks</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7746-composable-security-middleware-hooks/19471</comments>
        
        <description>## Abstract

This EIP proposes a standard interface, `ILayer`, 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&apos;s logic. This approach facilitates modular security, allowing independent providers to manage and upgrade security layers across multiple contracts.

## Motivation

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.

The Security Layers Standard introduces a modular approach, enabling:

- **Independent Security Providers:** Specialized security providers can focus on developing and maintaining specific security checks.
- **Composable Security:** Layers can be combined to create comprehensive security profiles tailored to individual contract needs.
- **Upgradability:** Security layers can be updated without requiring changes to the protected contract.
- **Flexibility:** Layers can perform a wide range of validation checks, including access control, input sanitization, output verification, and more.

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.

## Specification

A contract implementing the `ILayer` interface MUST provide two functions:

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity 0.8.20;

interface ILayer {
    /// @notice Validates a function call before execution.
    /// @param configuration Layer-specific configuration data.
    /// @param selector The function selector being called.
    /// @param sender The address initiating the call.
    /// @param value The amount of ETH sent with the call (if any).
    /// @param data The calldata for the function call.
    /// @return beforeCallResult Arbitrary data to be passed to `afterCallValidation`.
    /// @dev MUST revert if validation fails.
    function beforeCall(
        bytes memory configuration,
        bytes4 selector,
        address sender,
        uint256 value,
        bytes memory data
    ) external returns (bytes memory);

    /// @notice Validates a function call after execution.
    /// @param configuration Layer-specific configuration data.
    /// @param selector The function selector being called.
    /// @param sender The address initiating the call.
    /// @param value The amount of ETH sent with the call (if any).
    /// @param data The calldata for the function call.
    /// @param beforeCallResult The data returned by `beforeCallValidation`.
    /// @dev MUST revert if validation fails.
    function afterCall(
        bytes memory configuration,
        bytes4 selector,
        address sender,
        uint256 value,
        bytes memory data,
        bytes memory beforeCallResult
    ) external;
}

```

A protected contract MAY integrate security layers by calling the `beforeCallValidation` function before executing its logic and the `afterCallValidation` function afterwards. Multiple layers can be registered and executed in a defined order. The protected contract MUST revert if any layer reverts.

## Rationale

**Flexibility**: The `layerConfig` parameter allows for layer-specific customization, enabling a single layer implementation to serve multiple contracts with varying requirements.

**non-static calls**: Layers can maintain their own state, allowing for more complex validation logic (e.g., rate limiting, usage tracking).

**Strict Validation**: Reverts on validation failure ensure a fail-safe mechanism, preventing execution of potentially harmful transactions.

**Gas Costs**: 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.

## Reference Implementation

A reference implementation of the `ILayer` interface and a sample protected contract can be found in the repository:
In the [`ILayer.sol`](/EIPs/assets/eip-7746/ILayer.sol) a reference interface is provided.

In this test, a [`Protected.sol`](/EIPs/assets/eip-7746/test/Protected.sol) contract is protected by a [`RateLimitLayer.sol`](/EIPs/assets/eip-7746/test/RateLimitLayer.sol) layer. The `RateLimitLayer` implements the `ILayer` interface and enforces a rate which client has configured.
The `Drainer` simulates a vulnerable contract that acts in a malicious way. In the `test.ts` The `Drainer` contract is trying to drain the funds from the `Protected` contract. It is assumed that `Protected` contract has bug that allows partial unauthorized access to the state.
The `RateLimitLayer` is configured to allow only 10 transactions per block from same sender. The test checks that the `Drainer` contract is not able to drain the funds from the `Protected` contract.

## Security Considerations

**Layer Trust**: Thoroughly audit and vet any security layer before integrating it into your contract. Malicious layers can compromise contract security.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>State conversion to Verkle Tree</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7748-state-conversion-to-verkle-tree/20625</comments>
        
        <description>## Abstract

This EIP proposes a procedure to convert, on each block, a fixed number of key-values from the existing Merkle Patricia Tree (MPT) to the Verkle Tree (VKT).

## Motivation

The accounts state is too large to wait for transactions to organically move all of them to the VKT through the Overlay Tree. Thus, we need a strategy to convert all the state within a reasonable time. The state conversion completion allows removing the Overlay Tree abstraction introduced in [EIP-7612](/EIPs/EIPS/eip-7612) and to use directly the VKT for all state access.

## Specification

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

### Constants

| Parameter                    | value | Description                                                    |
| ---------------------------- | ----- | -------------------------------------------------------------- |
| `CONVERSION_START_TIMESTAMP` | `TBD` | Timestamp at which the conversion starts.                      |
| `CONVERSION_STRIDE`          | `TBD` | Maximum number of _conversion units_ to be converted per block |

A _conversion unit_ is:

- A contract storage slot.
- An account data (e.g. balance, nonce, code-hash) and code (if any).

### Changes to the execution spec

Include the following code in the existing `apply_body(...)` function:

```python
def apply_body(state: State, ...) -&gt; Tuple[Uint, Root, Root, Bloom, State, Root]:
    ...
    # &lt;new_code&gt;
    if block_time &gt;= CONVERSION_START_TIMESTAMP and not state._conversion_finished:
        state_convert(state, CONVERSION_STRIDE)
    # &lt;/new_code&gt;
    
    for i, tx in enumerate(map(decode_transaction, transactions)):
        ...
    ...
```

Before executing txs, it calls `state_convert(...)` (described below) which performs a state conversion step for this block.

In `state.py`, add the following code:

```python
@dataclass
class StoragePhase:
    &quot;&quot;&quot;
    The account next conversion step continues converting the 
    storage-slot with key greater than or equal to next_key. 
    If there isn&apos;t such a storage-slot, the account must move to
    AccountDataPhase.
    &quot;&quot;&quot;
    next_key: Bytes   
   
@dataclass
class AccountDataPhase:
    &quot;&quot;&quot;
    The account next conversion step continues migrating the account 
    code (if any) and basic data. After processing, the account must 
    move to the next account in the trie (or finish if it was the 
    last one).
    &quot;&quot;&quot;
    pass

@dataclass
class CurrentConvertingAccount:
    &quot;&quot;&quot;
    Contains the state conversion next step.
    &quot;&quot;&quot;
    address: Address
    phase : StoragePhase | AccountDataPhase
```

These new structures allows `State` to track where we&apos;re in the conversion process.

Modify the `State` class by adding the following attributes:

```python
@dataclass
class State:
    # &lt;new_code&gt;
    _conversion_curr_account: Optional[CurrentConvertingAccount] = None
    _conversion_finished: bool = False
    # &lt;/new_code&gt;
    ...
    
```

Define a function with the following signature:

```python
def trie_get_next_at_key(trie: Trie[K, V], key_seek: Bytes) -&gt; (K, V, Optional[Bytes]):
    # Returns the first (key, value) in the trie-key is &gt;= key_seek.
    # This method must only be used on Tries with secured=True,
    # since key_seek is the keccak256(K).
    # 
    # Returns:
    # - K, V: the key and value (e.g: Address/Value, StorageSlot/Value)
    # - next_key: The smallest trie-key present in the trie greater 
    # than key_seek, or None if there isn&apos;t one.
    #
    # It is up to the implementer to decide the best implementation
    # considering its client architecture.
```

Add or modify the following functions:

```python
# New function.
def get_conversion_account(state: State) -&gt; CurrentConvertingAccount:
    # When starting the conversion, initialize with the first account
    # in the MPT.
    if state._conversion_curr_account is None:
        # Initialize with the first account in the account trie.
        first_account = trie_get_next_at_key(&quot;0x0&quot;)
        # Accounts conversion starts with storage-slots conversion.
        phase = StoragePhase(&quot;0x0&quot;) # Starts with the lowest storage-slot key.
        state._conversion_curr_account = CurrentConvertingAccount(first_account, phase)
    
    return state._conversion_curr_account

# New function.
def conversion_move_to_next_account(state: State):
    curr_account = state.get_conversion_account()
    address, _, next_key = trie_get_next_at_key(state._main_trie, curr_account.phase.next_key)
    if next_key is None:
        # We finished the conversion
        state._conversion_finished = True
    else:
        # Move to the next account
        state._conversion_curr_account.address = address
        state._conversion_curr_account.phase = StoragePhase(&quot;0x00&quot;)

# Modified function: add new only_if_empty optional parameter.
def set_storage(
    state: State, addr: Address, key: Bytes, value: U256, only_if_empty: bool = True
) -&gt; None:
    # &lt;new_code&gt;
    if only_if_empty:
        value = state._overlay_tree.get(get_tree_key_for_storage_slot(addr, key))
        if value is not None:
            return
    # &lt;/new_code&gt;
    
    state._overlay_tree.set(get_tree_key_for_storage_slot(addr, key), value)
```

As mentioned previously, the next function is called by `apply_body(...)` to perform the conversion step for a block:

```python
# Note the following function is optimized for readability, not for performance.
def state_convert(state: State, stride: int):
    n = 0    
    while n &lt; stride and not state._conversion_finished:
        curr_account = state.get_conversion_account()
        
        # Skip translating storage if the account has an empty code hash.
        # Skip storage conversion for accounts with 0 nonce and empty code.
        # This covers the 28 EIP-7610 accounts, but would also cover all
        # pre-eip161 accounts on other chains.
        if curr_account.nonce == 0 and len(curr_account.code) == 0:
            state._conversion_curr_account.phase = AccountDataPhase()
        
        # Account storage.
        if curr_account.phase is StoragePhase:
            # Get the storage-slot from _storage_tries which is MPT data.
            trie = state._storage_tries.get(curr_account.address)
            
            if trie is not None:
                slot_num, slot_value, next_key = trie_get_next_at_key(trie, curr_account.phase.next_key)
                # The Overlay Tree will write in the VKT. We use the new
                # only_if_empty parameter to avoid writing stale values.
                set_storage(state, curr_account.address, slot_num, slot_value, only_if_empty=True)
                n += 1
    
                if next_key is not None:
                    # There&apos;re more storage-slots to be converted, continue in this phase.
                    state.conversion_curr_account.phase.next_key = next_key
                else:
                    # No more storage-slots. Move to the account data migration.
                    state.conversion_curr_account.phase = AccountDataPhase()
            else:
                # There&apos;s no storage trie for the account, move directly to
                # migrating account&apos;s data and code (if any).
                state.conversion_curr_account.phase = AccountDataPhase()
        # Account code and basic data.
        else:
            # Getting the code from the Overlay Tree is fine since it promises to return
            # the Account full code which would come from the MPT or a separate code database.
            account = get_account(state, curr_account.address)
            chunked_code = chunkify_code(account.code)
            
            for chunk_num in range(len(chunked_code)):
                state_set_codechunk(state, address, chunk_num, chunked_code[chunk_num])
                
            # If the account data (i.e: nonce, balance, code-size, code-hash) lives in MPT, 
            # get_account will pull from MPT and then we write to the VKT. If the account 
            # data already lives in the VKT (i.e: it was indirectly converted by a tx), then 
            # it will return it from the VKT and write it again (i.e: it&apos;s a noop).
            # Thus, this operation is correct under both scenarios. That is, it won&apos;t
            # write stale data.
            account = get_account(state, curr_account.address)
            set_account(state, curr_account.address, account)
            n += 1
    
            state.conversion_move_to_next_account()
```

## Rationale

### State conversion step position in block execution

Performing the conversion step before the block txs execution has some benefits:

- If the state conversion step is done after txs execution, there&apos;s a possibility that txs execution writes overlap with converted key-values, having to care about them becoming stale in the same block. With the proposed ordering, they can only become stale by writes of previous blocks.
- It can reduce the complexity of optimizations, such as frontrunning the state conversion for the next block before it arrives.

### `CONVERSION_STRIDE` proposed value

Performance benchmarks were done to achieve the right balance between:

- Don&apos;t overload the clients with too much extra work per block.
- Don&apos;t create an unmanageable load in clients during feasible long reorgs.
- Finish the conversion as fast as possible.

### Account code chunking done in a single step

If an account has code, this is chunked and inserted in the VKT in one go. An alternative is including a `CodePhase` and let each inserted chunk consume one unit of `CONVERSION_STRIDE`.

We decided to not do this to reduce the algorithm complexity. Considering the current maximum code size, the worst case scenario for a block could overflow the `CONVERSION_STRIDE` limit by 24k/31~=793 units.

### Deletion of [EIP-7610](/EIPs/EIPS/eip-7610) accounts

EIP-7610 mentions the existence of 28 accounts that have:

 - a nonce of 0,
 - no code
 - a non-empty storage tree

These storage slots are to be omitted from the conversion process, as they can not be accessed.

### Expected time for the conversion to finish

TODO: We have an estimation, but it might be worth recalculating it closer to the proposed fork having a more up to date state size estimate.

### Missed slots

The conversion logic runs at the start of each block, so missed slots don&apos;t create special situations.

### Accounts storage-&gt;account-data order

The proposed order synergizes with many EL client flat-db architectures, minimizing random disk-IO.

### Not counting [EIP-161](/EIPs/EIPS/eip-161) accounts for `CONVERSION_STRIDE` limit

The `CONVERSION_STRIDE` parameter tries to limit the load of effective writes. These special accounts are skipped since we try to perform a bulk [EIP-158](/EIPs/EIPS/eip-158) deletion of the remaining accounts.

This might sound dangerous since if there were 1k of these accounts and all corresponded to be converted in the same block, we&apos;d be forcing the clients to iterate 1k accounts without counting any quota from `CONVERSION_STRIDE`. The number of remaining accounts to delete is very low (i.e.: dozen) and also not contiguous, so this shouldn&apos;t be a concern.

### MPT preimage resolving

EL clients are expected to satisfy at least one of these conditions:

- They have a proper flat-db design, which doesn&apos;t require preimage resolving.
- They have a full preimage database which can resolve _trie_key_-&gt;_preimage_ (but this can have poor performance).
- They have downloaded the preimage database image that will be distributed before the conversion starts.

## Backwards Compatibility

No backward compatibility issues found.

## Test Cases

TODO: currently described in an external document.

## Reference Implementation

- `transition-post-genesis` branch in `github.com/gballet/go-ethereum` implements this when setting `--override.overlay-stride` to a non-zero value on the command line.

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 23 Jul 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7748</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7748</guid>
      </item>
    
      <item>
        <title>Add wallet_signIntendedValidatorData method</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7749-add-wallet-signintendedvalidatordata-method/20693</comments>
        
        <description>## Abstract

This EIP introduces a new JSON-RPC method, `wallet_signIntendedValidatorData`, which allows signing data with an intended validator address using [ERC-191](/EIPs/EIPS/eip-191) version 0x00 with this format:

```bash
0x19 &lt;0x00&gt; &lt;intended validator address&gt; &lt;data to sign&gt;
```

## Motivation

Currently, signing messages relies heavily on ERC-191 version 0x45 (`eth_sign`) and [EIP-712](/EIPs/EIPS/eip-712) (`eth_signTypedData`). While EIP-712 provides a more structured approach, it is often seen as complex. On the other hand, ERC-191 version 0x45 is widely used but poses significant phishing risks due to the lack of data parsing.

ERC-191 defines three versions: 0x45, 0x01, and 0x00. This proposal aims to fully support ERC-191 by introducing the rpc call for 0x00 version, which enables signing data with an intended validator address. This new method will:

- Enable more dApps to use ERC-191 version 0x00 without using raw signing methods which might be dangerous and restricted in few wallets.
- Enhance security by parsing data and displaying the intended validator address, reducing phishing risks.
- Provide a simpler alternative to EIP-712, offering a balance between usability and security.
- Be particularly relevant for smart contract accounts, allowing signing with a specific intended validator address.

With the rise of smart contract accounts and the reliance on signatures to improve UX, the need for supporting ERC-191 version 0x00 increases, especially given the prevalence of verifier smart contracts, such as Entry Points, Smart Contract Accounts, Key Managers, etc.

## Specification

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

### `wallet_signIntendedValidatorData`

MUST calculate an Ethereum signature using `sign(keccak256(&quot;\x19\x00&lt;intended validator address&gt;&lt;data to sign&gt;&quot;))`.

This method adds a prefix to the message to prevent malicious dApps from signing arbitrary data (e.g., a transaction) and using the signature to impersonate the victim.

#### Parameters

```js
interface WalletSignIntendedValidatorDataParams {
  signerAddress: string;        
  validatorAddress: string;     
  dataToSign: string;           
}
```


1. `signerAddress` - 20-byte account address: The address signing the constructed message.
2. `validatorAddress` - 20-byte account address: The intended validator address included in the message to sign.
3. `dataToSign` - Data string: The data to sign.

#### Returns

`Signature` - The Ethereum Signature generated.

## Rationale

The `wallet_signIntendedValidatorData` method aims to bridge the gap between the simplicity of ERC-191 version 0x45 and the structured approach of EIP-712. By specifying the intended validator address, it reduces phishing risks and provides a more secure signing method for smart contract accounts and other use cases requiring a specific validator address.

## Backwards Compatibility

No backward compatibility issues found.

## Test Cases

### Example

- Signer Address (`0x6aFbBC5e6AFcB251371711a6551E60ead2779Dc0`): This is the address of the account that will be used to sign the constructed message. We have access to the private key of this address, which allows us to generate the signature securely.

- Verifier Address (`0x345B918b9E06fAa7B0e56bd71Ba418F31F47FED4`): This address represents the address verifying the signature, could be an EOA or smart contract. For example, it could be a contract that performs specific actions based on the validity of the signature. By including this address in the data to be signed, we ensure that the signature cannot be reused by malicious actors for unintended purposes.

- Data to Sign (`0x59616d656e`): This is the hex-encoded string representing the actual content to be signed. In this example, it is the hex encoding for the ASCII string &quot;Yamen&quot;. The data, combined with the verifier address, is hashed and signed to generate a unique signature that cannot be used for any other purpose.

**Request:**

```bash
curl -X POST --data &apos;{&quot;jsonrpc&quot;:&quot;2.0&quot;,&quot;method&quot;:&quot;wallet_signIntendedValidatorData&quot;,&quot;params&quot;:[&quot;0x6aFbBC5e6AFcB251371711a6551E60ead2779Dc0&quot;, &quot;0x345B918b9E06fAa7B0e56bd71Ba418F31F47FED4&quot;, &quot;0x59616d656e&quot;], &quot;id&quot;:1}&apos;
```

```json
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;method&quot;: &quot;wallet_signIntendedValidatorData&quot;,
  &quot;params&quot;: [
    &quot;0x6aFbBC5e6AFcB251371711a6551E60ead2779Dc0&quot;,
    &quot;0x345B918b9E06fAa7B0e56bd71Ba418F31F47FED4&quot;,
    &quot;0x59616d656e&quot;
  ],
  &quot;id&quot;: 1
}
```

**Result:**

```json
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;result&quot;: &quot;0x4355c47d63924e8a72e509b65029052eb6c299d53a04e167c5775fd466751c9d07299936d304c153f6443dfa05f40ff007d72911b6f72307f996231605b915621c&quot;
}
```

The result field contains the Ethereum signature generated by signing the hashed message according to version 0 of ERC-191.

## Security Considerations

Users should exercise caution when signing messages. Double-check the address of the verifier and ensure trust in the dApp triggering the sign request.

To protect against replay attacks and cross-chain replay attacks, include chainId and nonce in the validator data to sign.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 21 Jun 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7749</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7749</guid>
      </item>
    
      <item>
        <title>Decentralized Employment System</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7750-decentralized-employment-system-des/20724</comments>
        
        <description>## Abstract

This ERC proposes a Decentralized Employment System (DES) built on the Ethereum blockchain. The DES facilitates the creation and management of companies, records comprehensive employment histories through unique employee tokens, enables the formation and execution of labor contracts, automates salary payments via an escrow mechanism, incorporates a robust moderation system for dispute resolution, and implements a reputation-based review system for both employers and employees. By leveraging blockchain&apos;s transparency and immutability, the DES ensures accountability and trust throughout the employment lifecycle, from company creation and hiring to contract fulfillment and termination.

The system operates post employee testing and prior to the final hiring and contract signing. Employees possess a **Soulbound Token (SBT)** representing their employment history, which companies review before finalizing labor contracts. This token-based approach ensures a secure and verifiable employment record that enhances the hiring process&apos;s integrity.

## Motivation

Traditional employment systems are centralized, opaque, and often lack trust. The DES aims to introduce transparency, immutability, and trust into the employment process by leveraging blockchain technology. By recording employment history on-chain, enabling decentralized company creation, automating contract enforcement, and providing mechanisms for dispute resolution, the DES promotes a fairer and more transparent employment ecosystem. Additionally, the system streamlines the hiring process by securely managing employment records and automating contractual obligations.

## Specification

### Solidity Interface

To provide a clear and standardized way for developers to interact with the DES, the following Solidity interface outlines the primary functions and events of the system:

```solidity
pragma solidity ^0.8.0;

/// @title Decentralized Employment System Interface
interface IDecentralizedEmploymentSystem {
    
    // Events
    event CompanyRegistered(uint companyId, address owner, string name, string industry);
    event EmployeeTokenMinted(uint tokenId, address employee);
    event ContractCreated(uint contractId, uint companyId, uint employeeTokenId, uint salary, uint duration);
    event ContractExecuted(uint contractId);
    event SalaryDeposited(uint contractId, uint amount);
    event SalaryReleased(uint contractId, address employee);
    event DisputeRaised(uint contractId, address raisedBy);
    event DisputeResolved(uint contractId, bool decisionForEmployee);
    event ContractTerminated(uint contractId, string reason);
    event ReviewSubmitted(uint contractId, uint rating, string comments);
    
    // Company Management
    function registerCompany(string calldata name, string calldata industry) external returns (uint companyId);
    function getCompany(uint companyId) external view returns (string memory name, string memory industry, address owner, uint[] memory employeeIds);
    
    // Employee Management
    function mintEmployeeToken(address employee, string calldata metadataURI) external returns (uint tokenId);
    function getEmploymentHistory(uint employeeTokenId) external view returns (uint[] memory contractIds);
    
    // Labor Contracts
    function createContract(uint companyId, uint employeeTokenId, uint salary, uint duration, string calldata responsibilities, string calldata terminationConditions) external returns (uint contractId);
    function executeContract(uint contractId) external;
    
    // Payment System
    function depositSalary(uint contractId) external payable;
    function releaseSalary(uint contractId) external;
    
    // Dispute Resolution
    function raiseDispute(uint contractId) external;
    function resolveDispute(uint contractId, bool decisionForEmployee) external;
    
    // Contract Termination
    function terminateContract(uint contractId, string calldata reason) external;
    
    // Review System
    function submitReview(uint contractId, uint rating, string calldata comments) external;
    function getReviews(uint contractId) external view returns (Review[] memory);
    
    // Structures
    struct Review {
        uint rating;
        string comments;
        address reviewer;
    }
}
```

### Detailed Function Specifications

#### 1. Company Management

**a. Company Registration**

- **Function**: `registerCompany(string calldata name, string calldata industry) external returns (uint companyId)`
  
- **Description**: Allows users to register a new company on the blockchain. Each company is assigned a unique `companyId` and associated with the caller&apos;s address as the owner.

- **Parameters**:
  - `name`: The name of the company.
  - `industry`: The industry sector of the company.

- **Returns**:
  - `companyId`: A unique identifier for the registered company.

**b. Retrieve Company Profile**

- **Function**: `getCompany(uint companyId) external view returns (string memory name, string memory industry, address owner, uint[] memory employeeIds)`
  
- **Description**: Retrieves the profile details of a registered company, including its name, industry, owner address, and a list of associated employee token IDs.

- **Parameters**:
  - `companyId`: The unique identifier of the company.

- **Returns**:
  - `name`: Name of the company.
  - `industry`: Industry sector of the company.
  - `owner`: Ethereum address of the company owner.
  - `employeeIds`: Array of employee token IDs associated with the company.

#### 2. Employee Management

**a. Employee Tokenization**

- **Function**: `mintEmployeeToken(address employee, string calldata metadataURI) external returns (uint tokenId)`
  
- **Description**: Mints a **Soulbound Token (SBT)** representing an employee. The token contains metadata about the employee, such as professional credentials, stored off-chain and referenced via `metadataURI`.

- **Parameters**:
  - `employee`: Ethereum address of the employee.
  - `metadataURI`: URI pointing to the employee&apos;s metadata.

- **Returns**:
  - `tokenId`: A unique identifier for the employee token.

**b. Retrieve Employment History**

- **Function**: `getEmploymentHistory(uint employeeTokenId) external view returns (uint[] memory contractIds)`
  
- **Description**: Fetches the complete employment history of an employee by returning an array of associated `contractIds`.

- **Parameters**:
  - `employeeTokenId`: The unique identifier of the employee&apos;s token.

- **Returns**:
  - `contractIds`: Array of contract IDs representing the employee&apos;s employment history.

#### 3. Labor Contracts

**a. Contract Creation**

- **Function**: `createContract(uint companyId, uint employeeTokenId, uint salary, uint duration, string calldata responsibilities, string calldata terminationConditions) external returns (uint contractId)`
  
- **Description**: Enables a company to create a new labor contract with an employee. This function assigns a unique `contractId` to the contract.

- **Parameters**:
  - `companyId`: The unique identifier of the company initiating the contract.
  - `employeeTokenId`: The unique identifier of the employee&apos;s token.
  - `salary`: The agreed-upon salary for the contract period.
  - `duration`: Duration of the contract in months.
  - `responsibilities`: Description of the employee&apos;s responsibilities.
  - `terminationConditions`: Conditions under which the contract can be terminated.

- **Returns**:
  - `contractId`: A unique identifier for the newly created contract.

**b. Contract Execution**

- **Function**: `executeContract(uint contractId) external`
  
- **Description**: Activates the contract by marking it as active once both the company and the employee have agreed to the terms by signing the transaction with their respective wallets.

- **Parameters**:
  - `contractId`: The unique identifier of the contract to be executed.

#### 4. Payment System

**a. Salary Deposits**

- **Function**: `depositSalary(uint contractId) external payable`
  
- **Description**: Allows the company to deposit the agreed salary into the contract&apos;s escrow. The function ensures that the deposited amount matches the contract&apos;s salary.

- **Parameters**:
  - `contractId`: The unique identifier of the contract for which the salary is being deposited.

- **Payable**: Yes, the function is payable to accept the salary funds.

**b. Automated Payments**

- **Function**: `releaseSalary(uint contractId) external`
  
- **Description**: Releases the salary from escrow to the employee&apos;s address based on the contract&apos;s payment schedule or upon contract completion.

- **Parameters**:
  - `contractId`: The unique identifier of the contract for which the salary is being released.

#### 5. Dispute Resolution

**a. Dispute Initiation**

- **Function**: `raiseDispute(uint contractId) external`
  
- **Description**: Allows either party involved in the contract to initiate a dispute. This action triggers the assignment of a moderator to resolve the issue.

- **Parameters**:
  - `contractId`: The unique identifier of the contract in dispute.

**b. Dispute Resolution**

- **Function**: `resolveDispute(uint contractId, bool decisionForEmployee) external`
  
- **Description**: Enables the assigned moderator to resolve the dispute by making a decision. If the decision favors the employee, escrow funds are transferred accordingly; otherwise, they may be returned to the company.

- **Parameters**:
  - `contractId`: The unique identifier of the contract under dispute.
  - `decisionForEmployee`: Boolean indicating if the decision favors the employee.

#### 6. Contract Termination

**a. Termination Conditions**

- **Function**: `terminateContract(uint contractId, string calldata reason) external`
  
- **Description**: Allows the company to terminate the contract based on predefined conditions. This function updates the contract status to &quot;terminated.&quot;

- **Parameters**:
  - `contractId`: The unique identifier of the contract to be terminated.
  - `reason`: The reason for termination.

#### 7. Review System

**a. Submit Review**

- **Function**: `submitReview(uint contractId, uint rating, string calldata comments) external`
  
- **Description**: Enables both companies and employees to submit reviews post-contract. Reviews include a rating and comments, contributing to the reputation score of both parties.

- **Parameters**:
  - `contractId`: The unique identifier of the contract being reviewed.
  - `rating`: Numerical rating reflecting the experience.
  - `comments`: Detailed feedback about the contract.

**b. Retrieve Reviews**

- **Function**: `getReviews(uint contractId) external view returns (Review[] memory)`
  
- **Description**: Retrieves all reviews associated with a specific contract.

- **Parameters**:
  - `contractId`: The unique identifier of the contract whose reviews are being fetched.

- **Returns**:
  - `Review[]`: An array of reviews related to the contract.

### Employment History

1. **Immutable Records**: Employment history is maintained as an array of contract IDs linked to each employee&apos;s Soulbound Token (SBT). This ensures that all employment records are permanently and immutably stored on the blockchain.

2. **Public Accessibility**: Employment history data is publicly accessible through the `getEmploymentHistory` function, allowing companies to verify an employee&apos;s past engagements before finalizing contracts.

### Payment System

1. **Salary Deposits**: Companies deposit salaries into an escrow managed by the smart contract by calling `depositSalary`. The contract ensures that funds are securely held until payment conditions are satisfied.

2. **Automated Payments**: Salaries are released automatically or upon triggering the `releaseSalary` function, ensuring timely and condition-based payments to employees.

### Moderation and Dispute Resolution

1. **Dispute Initiation and Resolution**: Either party can raise disputes, which are then resolved by assigned moderators. Moderators act as impartial arbitrators to ensure fair outcomes based on contract terms and evidence provided.

### Firing Employees

1. **Termination Conditions**: Companies can terminate contracts based on predefined conditions, with the option for dispute resolution if termination is contested.

### Review System

1. **Reputation Scores**: Reviews contribute to the reputation scores of both companies and employees, fostering accountability and encouraging positive behavior within the ecosystem.

## Rationale

1. **Employee Tokenization**:
   - Utilizing **Soulbound Tokens (SBTs)** to represent employees ensures that each employee has a unique, non-transferable identity on the blockchain. This design choice enhances the integrity of employment records, making them tamper-proof and verifiable. It also allows companies to access a comprehensive employment history before finalizing contracts, promoting transparency.

2. **Escrow System for Salary Payments**:
   - Implementing an escrow mechanism secures salary payments, ensuring that funds are only released when contractual obligations are met. This system protects both employees and companies by guaranteeing that salaries are available and that payments are contingent on contract fulfillment.

3. **Moderation and Dispute Resolution**:
   - Incorporating a moderation system allows for the resolution of disputes that cannot be automatically enforced by smart contracts. Moderators provide necessary human oversight in complex employment matters, ensuring fair and just outcomes.

4. **Public Employment History**:
   - Making employment history publicly accessible fosters trust and accountability. It allows potential employers to verify past employment and credentials, reducing the risk of fraud and enhancing the credibility of employees within the ecosystem.

5. **Review System**:
   - A reputation-based review system encourages positive interactions and behaviors among users. By allowing both companies and employees to submit reviews, the system promotes mutual accountability and helps build reliable reputations.

## Test Cases

1. **Company Creation**

   **Input**  
   - A user calls `registerCompany(&quot;TechCorp&quot;, &quot;Technology&quot;)`.
   
   **Expected State Changes**  
   - A new `companyId` is generated (e.g., `companyId = 1`).
   - The `companies` mapping is updated:
  ```solidity
     companies[1]↦{
      name=&quot;TechCorp&quot;,
      industry=&quot;Technology&quot;,
      owner=callerAddress,
      employeeIds=[ ]
      }
  ```
   - An event `CompanyRegistered` is emitted with the arguments `(1, callerAddress, &quot;TechCorp&quot;, &quot;Technology&quot;)`.

   **Expected Output**  
   - **Return Value**: `companyId = 1` (the newly created company ID).
   - **Event**: `CompanyRegistered` is logged.

2. **Employee Token Minting**

   **Input**  
   - The contract owner (or an authorized address) calls `mintEmployeeToken(employeeAddress, &quot;ipfs://metadataURI&quot;)`.
   
   **Expected State Changes**  
   - A new token ID is generated (e.g., `tokenId = 5`).
   - An internal mapping (e.g., `employeeTokenToOwner`) is updated:
   ```solidity
      employeeTokenToOwner[5]↦employeeAddress
   ```
   - (Optional) If the implementation tracks metadata, another mapping (e.g., `employeeTokenMetadata`) might store:
   ```solidity
      employeeTokenMetadata[5]↦&quot;ipfs://metadataURI&quot;
   ```
   - An event `EmployeeTokenMinted` is emitted with `(5, employeeAddress)`.

   **Expected Output**  
   - **Return Value**: `tokenId = 5` (the newly minted employee token ID).
   - **Event**: `EmployeeTokenMinted` is logged.

3. **Contract Creation and Execution**

   **Input**  
   1. A company with `companyId = 1` calls:
   ```solidity
      createContract(1,5,1000,6,&quot;SoftwareDevelopment&quot;,&quot;Failuretomeetdeadlines&quot;)
   ```
   which returns `contractId`.
   2. Both the company and the employee call `executeContract(contractId)`.

   **Expected State Changes**  
   - **Contract Creation**:
     1. A new labor contract ID is generated, e.g., `contractId = 10`.
     2. The `contracts` mapping is updated:
     ```solidity
        contracts[10]↦{
          companyId=1,
          employeeTokenId=5,
          salary=1000,
          duration=6,
          responsibilities=&quot;SoftwareDevelopment&quot;,
          terminationConditions=&quot;Failuretomeetdeadlines&quot;,status=&quot;Created&quot;
        }
     ```
     3. The system may also update a per-company or per-employee tracking structure (optional but typical):
     ```solidity
        companyContracts[1].push(10)
        employeeContracts[5].push(10)
     ```
     4. An event `ContractCreated` is emitted with arguments `(10, 1, 5, 1000, 6)`.
   - **Contract Execution**:
     1. Upon calls from both parties, the contract’s status changes from `&quot;Created&quot;` to `&quot;Active&quot;`:
     ```solidity
        contracts[10].status↦&quot;Active&quot;
     ```
     2. An event `ContractExecuted` is emitted with `(10)` once both signatures/confirmations are received.

   **Expected Output**  
   - **Return Value** (from `createContract`): `contractId = 10`
   - **Event**: `ContractCreated(10, 1, 5, 1000, 6)` upon creation.
   - **Event**: `ContractExecuted(10)` once execution is confirmed by both parties.

4. **Salary Deposit**

   **Input**  
   - The company (owner of `companyId = 1`) calls `depositSalary(10)` and sends `1000 USDC` (or equivalent in wei for an [ERC-20](/EIPs/EIPS/eip-20) token or native token) to the contract.

   **Expected State Changes**  
   1. The contract’s escrow balance mapping is updated:
   ```solidity
      escrowBalances[10]↦1000
   ```
   2. An event `SalaryDeposited` is emitted with `(10, 1000)`.

   **Expected Output**  
   - **Event**: `SalaryDeposited(10, 1000)`
   - The contract’s internal `escrowBalances[10]` should now be `1000`.

5. **Salary Payment**

   **Input**  
   - After the contract’s duration or satisfaction of any release condition, `releaseSalary(10)` is called (by the contract or the employee).

   **Expected State Changes**  
   1. The escrow balance for `contractId = 10` is transferred to the employee token owner (`employeeAddress` associated with token ID `5`).
   2. The `escrowBalances[10]` is set to `0`:
   ```solidity
      escrowBalances[10]↦0
   ```
   3. An event `SalaryReleased` is emitted with `(10, employeeAddress)`.

   **Expected Output**  
   - **Event**: `SalaryReleased(10, employeeAddress)`
   - The updated `escrowBalances[10]` is now `0`.
   - The employee’s on-chain balance (or token balance if using [ERC-20](/EIPs/EIPS/eip-20)) increases by `1000`.

6. **Employment Termination**

   **Input**  
   - The company calls `terminateContract(10, &quot;Failure to meet deadlines&quot;)`.

   **Expected State Changes**  
   1. The `contracts[10].status` is updated to `&quot;Terminated&quot;`:
   ```solidity
      contracts[10].status↦&quot;Terminated&quot;
   ```
   2. An event `ContractTerminated` is emitted with `(10, &quot;Failure to meet deadlines&quot;)`.

   **Expected Output**  
   - **Event**: `ContractTerminated(10, &quot;Failure to meet deadlines&quot;)`
   - The `contracts[10]` status is now `&quot;Terminated&quot;`.
   - No further salary obligations exist unless otherwise specified in dispute-resolution processes.

7. **Dispute Resolution**

   **Input**  
   1. Either party (company or employee) calls `raiseDispute(10)`.
   2. The assigned moderator calls `resolveDispute(10, true)` indicating the decision favors the employee.

   **Expected State Changes**  
   - **Dispute Raised**:
     1. The contract’s dispute status is noted (implementation-specific, but typically `contracts[10].disputeRaised = true`).
     2. An event `DisputeRaised(10, msg.sender)` is emitted.
   - **Dispute Resolved**:
     1. If `decisionForEmployee == true`, any remaining escrow funds for `contractId = 10` are transferred to the employee.
     2. A `DisputeResolved(10, true)` event is emitted.

   **Expected Output**  
   - **Event**: `DisputeRaised(10, msg.sender)`
   - **Event**: `DisputeResolved(10, true)`
   - If funds remain in escrow, `escrowBalances[10]` is set to `0`, and the employee receives the outstanding balance.


## Security Considerations

1. **Contract Integrity**: Ensure that all labor contracts are immutable and cannot be tampered with once created and executed.

2. **Fund Security**: Salaries are securely held in escrow, and only released based on predefined conditions to prevent unauthorized access or misuse.

3. **Moderator Trust**: Implement a decentralized and transparent system for selecting and monitoring moderators to maintain impartiality and trust in dispute resolutions.

4. **Review System**: Incorporate safeguards against fraudulent reviews, such as verifying the association of reviews with legitimate contract completions, to maintain accurate and trustworthy reputation scores.

5. **Token Security**: Use **Soulbound Tokens (SBTs)** for employee representation to prevent token transfers and ensure that employment records are securely tied to the respective individuals.


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 04 Aug 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7750</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7750</guid>
      </item>
    
      <item>
        <title>Wrapping of bubbled up reverts</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7751-wrapping-of-bubbled-up-reverts/20740</comments>
        
        <description>## Abstract

This ERC proposes a standard for handling bubbled up reverts in Ethereum smart contracts using a dedicated custom error. This standard aims to improve the clarity and usability of revert reasons by allowing additional context to be passed alongside the raw bytes of the bubbled up revert. The `WrappedError` custom error should wrap reverts from called contracts and provide a consistent interface for parsing and handling reverts in tools like Etherscan or Tenderly.

## Motivation

Currently, when a smart contract calls another and the called contract reverts, the revert reason is usually bubbled up and thrown as is. This can make it more difficult to tell which context the error came from. By standardizing the use of custom errors with additional context, more meaningful and informative revert reasons can be provided. This will improve the debugging experience and make it easier for developers and infrastructure providers like Etherscan to display accurate stack traces.

## Specification

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

In order to wrap a revert, a contract MUST revert with the following error that corresponds to the following signature `0x90bfb865`:

```solidity
error WrappedError(address target, bytes4 selector, bytes reason, bytes details);
```

Where:

- `target` is the address of the called contract that reverted.
- `selector` is the selector of the called function that reverted. If the call was an ETH transfer without any data, the selector MUST be `bytes4(0)`
- `reason` is the raw bytes of the revert reason.
- `details` is optional additional context about the revert. In cases where no additional context is needed, the `details` bytes can be empty. In cases with additional context, the `details` bytes MUST be an ABI encoded custom error declared on the contract that emits the `WrappedError` error.

## Rationale

By including the called contract and function, raw revert bytes and additional context, developers can provide more detailed information about the failure. Additionally, by standardizing the way reverts are bubbled up, it also enables nested bubbled up reverts where multiple reverts thrown by different contracts can be followed recursively. The reverts can also be parsed and handled by tools like Etherscan and Foundry to further enhance the readability and debuggability of smart contract interactions, as well as facilitating better error handling practices in general.

## Backwards Compatibility

This ERC does not introduce any backwards incompatibilities. Existing contracts can adopt this standard incrementally.

## Test Cases

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity 0.8.26;

contract Token {
    mapping(address =&gt; uint256) public balanceOf;

    event Transfer(address indexed sender, address indexed recipient, uint amount);

    function transfer(address to, uint256 amount) external returns (bool) {
        require(balanceOf[msg.sender] &gt;= amount, &quot;insufficient balance&quot;);
        balanceOf[msg.sender] -= amount;
        balanceOf[to] += amount;
        emit Transfer(msg.sender, to, amount);
        return true;
    }
}

contract Vault {
    Token token;

    error WrappedError(address target, bytes4 selector, bytes reason, bytes details);
    error ERC20TransferFailed(address recipient);


    constructor(Token token_) {
        token = token_;
    }

    function withdraw(address to, uint256 amount) external {
        // logic
        try token.transfer(to, amount) {} catch (bytes memory error) {
            revert WrappedError(address(token), token.transfer.selector, error, abi.encodeWithSelector(ERC20TransferFailed.selector, to));
        }
    }
}

contract Router {
    Vault vault;

    error WrappedError(address target, bytes4 selector, bytes reason, bytes details);

    constructor(Vault vault_) {
        vault = vault_;
    }

    function withdraw(uint256 amount) external {
        // logic
        try vault.withdraw(msg.sender, amount) {} catch (bytes memory error) {
            revert WrappedError(address(vault), vault.withdraw.selector, error, &quot;&quot;);
        }
    }
}

contract Test {
    function test_BubbledNestedReverts(uint256 amount) external {
        Token token = new Token();
        Vault vault = new Vault(token);
        Router router = new Router(vault);

        try router.withdraw(amount) {} catch (bytes memory thrownError) {
            bytes memory expectedError = abi.encodeWithSelector(
                Router.WrappedError.selector, address(vault), vault.withdraw.selector, abi.encodeWithSelector(
                    Vault.WrappedError.selector,
                    address(token),
                    token.transfer.selector,
                    abi.encodeWithSignature(&quot;Error(string)&quot;, &quot;insufficient balance&quot;),
                    abi.encodeWithSelector(Vault.ERC20TransferFailed.selector, address(this))
                ), &quot;&quot;
            );
            assert(keccak256(thrownError) == keccak256(expectedError));
        }
    }
}
```

## Reference Implementation

When catching a revert from a called contract, the calling contract should revert with a custom error following the above conventions.

```solidity
contract Foo {

    error WrappedError(address target, bytes4 selector, bytes reason, bytes details);
    error MyCustomError(uint256 x);

    function foo(address to, bytes memory data) external {
        // logic
        (bool success, bytes memory returnData) = to.call(data);
        if (!success) {
            revert WrappedError(to, bytes4(data), returnData, abi.encodeWithSelector(MyCustomError.selector, 42));
        }
    }
}
```

## Security Considerations

Smart contracts could either drop or purposefully suppress the bubbled up reverts along the revert chain. Additionally, smart contracts may also lie or incorrectly report the wrapped reverts, so the information is not guaranteed to be accurate.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 06 Aug 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7751</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7751</guid>
      </item>
    
      <item>
        <title>Tamperproof Extension Wallets API (TWIST)</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7754-tamperproof-web-immutable-transaction-twit/20767</comments>
        
        <description>## Abstract

Tamperproof Web Immutable Secure Transaction (TWIST) introduces a new RPC method to be implemented by wallets, `wallet_signedRequest`, that
enables dapps to interact with wallets in a tamperproof manner via &quot;signed requests&quot;. The
dapp associates a public key with its DNS record and uses the corresponding private key to
sign payloads sent to the wallet via `wallet_signedRequest`. Wallets can then use the
public key in the DNS record to validate the integrity of the payload.

## Motivation

This standard aims to enhance the end user&apos;s experience by granting them confidence that requests from their dapps have not been tampered with.
In essence, this is similar to how HTTPS is used in the web.

Currently, the communication channel between dapps and wallets is vulnerable to man in the middle attacks.
Specifically, attackers can intercept RPC requests by injecting JavaScript code in the page,
via e.g. an XSS vulnerability or due to a malicious extension.
Once an RPC request is intercepted, it can be modified in a number of pernicious ways, including:

- Editing the calldata in order to siphon funds or otherwise change the transaction outcome
- Modifying the parameters of an [EIP-712](/EIPs/EIPS/eip-712) request
- Obtaining a replayable signature from the wallet

Even if the user realizes that requests from the dapp may be tampered with, they have little to no recourse to mitigate the problem.
Overall, the lack of a chain of trust between the dapp and the wallet hurts the ecosystem as a whole:

- Users cannot simply trust otherwise honest dapps, and are at risk of losing funds
- Dapp maintainers are at risk of hurting their reputations if an attacker finds a viable MITM attack

For these reasons, we recommend that wallets implement the `wallet_signedRequest` RPC method.
This method provides dapp developers with a way to explicitly ask the wallet to verify the
integrity of a payload. This is a significant improvement over the status quo, which forces
dapps to rely on implicit approaches such as argument bit packing.

## Specification

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

### Overview

We propose to use the dapp&apos;s domain certificate of a root of trust to establish a trust chain as follow:

1. The user&apos;s browser verifies the domain certificate and displays appropriate warnings if overtaken
2. The DNS record of the dapp hosts a TXT field pointing to a URL where a JSON manifest is hosted
   - This file SHOULD be at a well known address such as `example[.]com/.well-known/twist.json`
3. The config file contains an array of objects of the form `{ id, alg, publicKey }`
4. For signed requests, the dapp first securely signs the payload with a private key, for example by submitting a request to its backend
5. The original payload, signature, and public key id are sent to the wallet via the `wallet_signedRequest` RPC method
6. The wallet verifies the signature before processing the request normally

### Wallet integration

#### Key discovery

Attested public keys are necessary for the chain of trust to be established.
Since this is traditionally done via DNS certificates, we propose the addition of a DNS record containing the public keys.
This is similar to RFC 6376&apos;s DKIM, but the use of a manifest file provides more flexibility for future improvements, as well as support for multiple algorithm and key pairs.

Similarly to standard RFC 7519&apos;s JWT practices, the wallet could eagerly cache dapp keys.
However, in the absence of a revocation mechanism, a compromised key could still be used until caches have expired.
To mitigate this, wallets SHOULD NOT cache dapp public keys for more than 2 hours.
This practice establishes a relatively short vulnerability window, and manageable overhead for both wallet and dapp maintainers.

Example DNS record for `my-crypto-dapp.invalid`:

```txt
...
TXT: TWIST=/.well-known/twist.json
```

Example TWIST manifest at `my-crypto-dapp[.]invalid/.well-known/twist.json`:

```json
{
  &quot;publicKeys&quot;: [
    { &quot;id&quot;: &quot;1&quot;, &quot;alg&quot;: &quot;ES256&quot;, &quot;publicKey&quot;: &quot;0xaf34...&quot; },
    { &quot;id&quot;: &quot;2&quot;, &quot;alg&quot;: &quot;PS256&quot;, &quot;publicKey&quot;: &quot;0x98ab...&quot; }
  ]
}
```

Implementers MUST support at least the following &quot;alg&quot; param values, from RFC 7518 section 3.1: ES256 and EdDSA. Implementers SHOULD support PS256, RS256, ES384, ES512, PS384, PS512, RS384, and RS512.

Implementers SHOULD use `SubtleCrypto`, since it is available in modern browsers.

Public keys MUST be encoded using the X.509 SubjectPublicKeyInfo (SPKI) structure in DER format and represented as hex-encoded strings.

#### Manifest schema

We propose a simple and extensible schema:

```json
{
  &quot;title&quot;: &quot;TWIST manifest&quot;,
  &quot;type&quot;: &quot;object&quot;,
  &quot;properties&quot;: {
    &quot;publicKeys&quot;: {
      &quot;type&quot;: &quot;array&quot;,
      &quot;items&quot;: {
        &quot;type&quot;: &quot;object&quot;,
        &quot;properties&quot;: {
          &quot;id&quot;: { &quot;type&quot;: &quot;string&quot; },
          &quot;alg&quot;: { &quot;type&quot;: &quot;string&quot; },
          &quot;publicKey&quot;: { &quot;type&quot;: &quot;string&quot; }
        }
      }
    }
  }
}
```

#### RPC method

The parameters of `wallet_signedRequest` are specified by this TypeScript interface:

```typescript
type RequestPayload&lt;Params&gt; = { method: string; params: Params };

type SignedRequestParameters&lt;Params&gt; = [
  requestPayload: RequestPayload&lt;Params&gt;,
  signature: `0x${string}`,
  keyId: string,
];
```

Here&apos;s a non-normative example of calling `wallet_signedRequest` using the [EIP-1193](/EIPs/EIPS/eip-1193) provider interface:

```typescript
const keyId = &apos;1&apos;;
const requestPayload: RequestPayload&lt;TransactionParams&gt; = {
  method: &apos;eth_sendTransaction&apos;,
  params: [
    {
      /* ... */
    },
  ],
};
const signature: `0x${string}` = await getSignature(requestPayload, keyId);

// Using the EIP-1193 provider interface
const result = await ethereum.request({
  method: &apos;wallet_signedRequest&apos;,
  params: [requestPayload, signature, keyId],
});
```

#### Signature verification

1. Upon receiving an [EIP-1193](/EIPs/EIPS/eip-1193) call, the wallet MUST check of the existence of the TWIST manifest for the `sender.tab.url` domain
   a. The wallet MUST enforce HTTPS as HTTP call would be vulnerable to DNS spoofing
   b. The wallet MUST verify that the manifest is hosted on the `sender.tab.url` domain
   c. The wallet SHOULD find the DNS TXT record to find the manifest location
   d. The wallet MAY first try the `/.well-known/twist.json` location
   e. The wallet MUST NOT follow redirects when querying the manifest location as it could lead to open redirect attacks
   f. The wallet SHOULD validate the `Content-Type` header of the response is specifically set to `application/json`
2. If TWIST is NOT configured for the `sender.tab.url` domain, then proceed as usual
3. If TWIST is configured and the `request` method is used, then the wallet SHOULD display a visible and actionable warning to the user
   a. If the user opts to ignore the warning, then proceed as usual
   b. If the user opts to cancel, then the wallet MUST cancel the call
4. If TWIST is configured and the `wallet_signedRequest` method is used with the parameters `requestPayload`, `signature` and `keyId` then:
   a. The wallet MAY display a visible cue indicating that this interaction is signed
   b. The wallet MUST verify that the keyId exists in the TWIST manifest and find the associated key record
   c. From the key record, the wallet MUST use the `alg` field and the `publicKey` field to verify `requestPayload` integrity by calling `crypto.verify(alg, key, signature, requestPayload)`
   d. If the signature is invalid, the wallet MUST display a visible and actionable warning to the user
   i. If the user opts to ignore the warning, then proceed to call `request` with the argument `requestPayload`
   ii. If the user opts to cancel, then the wallet MUST cancel the call
   e. If the signature is valid, the wallet MUST call `request` with the argument `requestPayload`

#### Example method implementation (wallet)

```typescript
async function signedRequest(
  requestPayload: RequestPayload&lt;unknown&gt;,
  signature: `0x${string}`,
  keyId: string,
): Promise&lt;unknown&gt; {
  // 1. Get the domain of the sender.tab.url
  const domain = getDappDomain();

  // 2. Get the manifest for the current domain
  // It&apos;s possible to use RFC 8484 for the actual DNS-over-HTTPS specification.
  // However, here we are doing it with DoHjs.
  // This step is optional, and you could go directly to the well-known address first at `domain + &apos;/.well-known/twist.json&apos;`
  const doh = require(&apos;dohjs&apos;);
  const resolver = new doh.DohResolver(&apos;&lt;doh-endpoint&gt;&apos;);

  let manifestPath = &apos;&apos;;
  const dnsResp = await resolver.query(domain, &apos;TXT&apos;);
  for (const record of dnsResp.answers) {
    if (!record.data.startsWith(&apos;TWIST=&apos;)) continue;

    manifestPath = record.data.substring(5); // This should be domain + &apos;/.well-known/twist.json&apos;
    break;
  }

  // 3. Parse the manifest and get the key and algo based on `keyId`
  const manifestUrl = `https://${domain}${manifestPath.startsWith(&apos;/&apos;) ? &apos;&apos; : &apos;/&apos;}${manifestPath}`;
  const manifestReq = await fetch(manifestUrl, { redirect: &apos;error&apos; });
  const contentType = (manifestReq.headers.get(&apos;content-type&apos;) || &apos;&apos;).toLowerCase();
  if (!contentType.startsWith(&apos;application/json&apos;)) {
    throw new Error(&apos;The manifest is not a proper JSON file&apos;);
  }
  const manifest = await manifestReq.json();
  const keyData = manifest.publicKeys.find((x) =&gt; x.id === keyId);
  if (!keyData) {
    throw new Error(&apos;Could not find the signing key&apos;);
  }

  const key = keyData.publicKey;
  const alg = keyData.alg;

  // 4. Verify the signature
  const valid = await crypto.verify(alg, key, signature, requestPayload);
  if (!valid) {
    throw new Error(&apos;The data was tampered with&apos;);
  }
  return await processRequest(requestPayload);
}
```

### Wallet UX suggestion

Similarly to the padlock icon for HTTPS, wallets should display a visible indication when TWIST is configured on a domain. This will improve the UX of the end user who will immediately be able to tell
that interactions between the dapp they are using and the wallet are secure, and this will encourage dapp developer to adopt TWIST, making the overall ecosystem more secure

When dealing with insecure request, either because the dapp (or an attacker) uses `request` on a domain where TWIST is configured, or because the signature does not match, wallets should warn the user but
not block: an eloquently worded warning will increase the transparency enough that end user may opt to cancel the interaction or proceed with the unsafe call.

## Rationale

The proposed implementation does not modify any of the existing functionalities offered by [EIP-712](/EIPs/EIPS/eip-712) and [EIP-1193](/EIPs/EIPS/eip-1193). Its additive
nature makes it inherently backward compatible. Its core design is modeled after existing solutions to existing problems (such as DKIM). As a result the proposed specification will be non disruptive, easy to
implements for both wallets and dapps, with a predictable threat model.

## Security Considerations

### Replay prevention

While signing the `requestArg` payload guarantees data integrity, it does not prevent replay attacks in itself:

1. a signed payload can be replayed multiple times
2. a signed payload can be replayed across multiple chains

_Effective_ time replay attacks as described in `1.` are generally prevented by the transaction nonce.
Cross chain replay can be prevented by leveraging the [EIP-712](/EIPs/EIPS/eip-712) `signTypedData` method.

Replay attack would still be possible on any method that is not protected by either: this affects effectively all the &quot;readonly&quot; methods
which are of very limited value for an attacker.

For these reason, we do not recommend a specific replay protection mechanism at this time. If/when the need arise, the extensibility of
the manifest will provide the necessary room to enforce a replay protection envelope (eg:JWT) for affected dapp.

### Malicious manifests

The manifest itself could be attacked, defeating the purpose of TWIST. We identified the following possible attacks, and their counter measure:

1. An attacker can spoof DNS entries and use it to serve their own manifest: to avoid this, the wallet implementation MUST only query the manifest from `&apos;https://${sender.tab.url}/${pathFromDNSRecord}`
2. An attacker can leverage other flaws in a dapp to host a malicious manifest on the dapp domain itself
   a. by leveraging open redirect: consequently the wallet MUST NOT follow redirect when querying the manifest
   b. by managing to host a file on the dapp domain: consequently the wallet SHOULD verify the `content-type` header is equal to `application/json` to mitigate this attack vector

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 29 Jul 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7754</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7754</guid>
      </item>
    
      <item>
        <title>EOF/EVM Trace Specification</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7756-eof-evm-trace-specification/20806</comments>
        
        <description>## Abstract

Updates the [EIP-3155](/EIPs/EIPS/eip-3155) JSON tracing specification to support EOF features.

## Motivation

EIP-3155 defined a tracing standard for Legacy EVM operations. However, the EVM Object
Format ([EIP-7692](/EIPs/EIPS/eip-7692)) adds a number of features that need to be reflected in debugging
traces.

The use of these traces has also moved out from state testing, including live block tracing and
differential fuzzing, increasing the need to keep tracing up to date.

This EIP has multiple goals:

- Add members to the trace object to support new EOF features.
- Support tracing contracts contained in an EOF container as well as uncontained &quot;legacy&quot; contracts
  in the same trace.
- Clarify any previous ambiguities in the EIP-3155 specification.

## Specification

To promote clarity and provide a cohesive specification, the entire tracing specification will be
presented with alterations in-line rather than as a set of diffs on top of EIP-3155. Differences
will be highlighted in the Backwards Compatibility section.

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

### Datatypes

| Type       | Explanation                                                    | JSON member example                    |
|------------|----------------------------------------------------------------|----------------------------------------|
| Number     | JSON number                                                    | `&quot;pc&quot;:0`                               |
| Hex-Number | Hex-encoded number                                             | `&quot;gas&quot;:&quot;0x2540be400&quot;`                  |
| String     | Plain string                                                   | `&quot;opName&quot;:&quot;PUSH1&quot;`                     |
| Hex-String | Hex-encoded string                                             | `&quot;returnData&quot;:&quot;0x60616203&quot;`            |
| Array      | Array of Hex-Strings                                           | `&quot;stack&quot;:[&quot;0x0&quot;, &quot;0x0&quot;]`               |
| Key-Value  | Key-Value structure with key and values encoded as hex strings | `&quot;storage&quot;:{&quot;0x0&quot;:&quot;0x1&quot;, &quot;0x1&quot;:&quot;0x1&quot;}` |
| Boolean    | Json bool can either be true or false                          | `&quot;pass&quot;: true`                         |

- Clients may OPTIONALLY output Number where a Hex-Number is expected and vice-versa. Clients that
  do this SHOULD provide a CLI option to strictly observe the correct output type.
- Numbers larger than 2^53 - 1 must be represented as Hex-Numbers. This is a limitation of JSON.
- Consumers of EIP-7756 traces SHOULD be written in a way that members of type Hex-Number and 
  Number may be provided a Number or Hex-Number instead, respectively.
- Note that there is no string formatted decimal number alternative. Decimal representations are 
  always JSON numbers, and hex representations are always strings encoding hex numbers.

### Output

- The client outputs one JSON object per EVM operation executed.
- The client MUST NOT output multiple lines for the same operation execution.
- The client MUST NOT output a line for the `STOP` operation if an error occurred, or if the
  contract runs out of instructions.

#### Required Fields

Each trace line MUST have these fields.

| Name     | Type                 | Explanation                                                         |
|----------|----------------------|---------------------------------------------------------------------|
| `pc`     | Number               | Program Counter                                                     |
| `op`     | Hex-Number           | OpCode                                                              |
| `opName` | String               | Name of the operation                                               |
| `gas`    | Number               | Gas left before executing this operation                            |
| `stack`  | Array of Hex-Numbers | Array of all values on the stack                                    |
| `depth`  | Number               | Depth of the call stack                                             |
| `error`  | Hex-String           | Description of an error (SHOULD contain revert reason if supported) |

- The `pc` value is zero indexed from the beginning of the contract when the contract is not in an 
  EOF container, or from the beginning of the container EOF container. For legacy contracts the 
  first execution line is for `&quot;pc&quot;:0`. For EOF contracts the zero byte corresponds to the `0xEF` 
  magic byte. The first line of execution will not be at `&quot;pc&quot;:0` but at the first byte of the first 
 code section executed.
- `opName` SHOULD be the most current name of the operation, in cases where operations have multiple
  specification names (`SELFDESTRUCT` and `PREVRANDAO`)

- If `stack` is empty an empty array (`[]`) is used instead of `null`.
- `depth` starts at 1.
- `error` SHOULD be omitted if a prior CALL series or CREATE series operation within the current 
  frame has not returned a revert reason and the current operation did not trigger an exceptional 
  halt.

&lt;!-- - `stack` MAY exclude stack items that are more than any operation will need to execute, which 
is currently seven stack items. If any stack items are excluded past that point then all stack items
past that point MUST be excluded
--&gt;

#### Recommended Fields

Each trace line SHOULD have these fields in the conditions they are indicated for.

| Name         | Type       | Explanation                       |
|--------------|------------|-----------------------------------|
| `gasCost`    | Number     | Gas cost of this operation        |
| `memSize`    | Number     | Size of memory array              |
| `returnData` | Hex-String | Data returned by function call    |
| `refund`     | Hex-Number | Amount of **global** gas refunded |

- `gasCost` is the sum of all gas costs, including dynamic costs such as memory expansion, call
  stipend, and account warming costs.
- `memSize` is counted in 8-bit bytes, not 256-bit words.
- `returnData` SHOULD NOT be present if a CALL series operation has not completed within the current
frame.

#### Optional Fields

Each trace line MAY have these fields in the conditions they are indicated for.
If a field is to be omitted within a trace, it MUST always be omitted within the same trace.

| Name            | Type                 | Explanation                                               |
|-----------------|----------------------|-----------------------------------------------------------|
| `section`       | Number               | Current EOF section being executed                        |
| `immediate`     | Hex-String           | Immediate argument of the Opcode                          |
| `functionDepth` | Number               | Depth of the [EIP-4750](/EIPs/EIPS/eip-4750) CALLF return stack |
| `memory`        | Array of Hex-Strings | Array of all allocated values                             |
| `storage`       | Key-Value            | Array of all stored values                                |

- The `section` member must only be present when tracing a contract contained in an EOF container.
- The `immediate` field MUST NOT be present for operations without immediate data.
    - For PUSH series operations, this field is OPTIONAL as the immediate data is pushed onto the
      stack
    - For RJUMPV this would include the table length and the entire table. Clients MAY instead store
      just the table length.
    - For all other operations with immediate data the entire immediate data, including leading
      zeros, SHOULD be present.
- `functionDepth` starts at 1, and MAY be omitted if it is 1. 
- `functionDepth` MUST NOT be present for trace lines of code not in an EOF container.
- If `memory` is empty an empty array (`[]`) is used instead of `null`.
- The `storage` member SHOULD only include items read or written via `SSTORE` or `SLOAD`, and not 
  the account&apos;s entire storage.

*Example:*

```
{&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;}
```

### Summary Line

At the end of execution, the client SHOULD print summary info. This summary MUST be a single JSON
object.

This info SHOULD have the following members.

| Name        | Type       | Explanation                                            |
|-------------|------------|--------------------------------------------------------|
| `stateRoot` | Hex-String | Root of the state trie after executing the transaction |
| `output`    | Hex-String | Return values of the function                          |
| `gasUsed`   | Number     | All gas used by the transaction                        |
| `pass`      | Boolean    | If the tx was successful, or if the test passed        |
| `time`      | Number     | Time in nanoseconds needed to execute the transaction  |
| `fork`      | String     | Name of the fork rules used for execution              |

- `time` and `fork` fields MAY be provided.

*Example*:

```
{&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}
```

## Rationale

This EIP is an extension of the EIP-3155 tracing features that has been in use for years. Rather
than dramatically re-boot the feature, the information was added to the existing traces.

A &quot;mini&quot; trace was contemplated to allow for tracing to be included in tools such as
`t8n` and to allow for more efficient RPC tracing calls, but that seemed sufficiently different that
it would be a stand-alone EIP rather than an EIP that adds features to the existing tracing
capabilities.

The idea of moving to a JSON Schema was rejected to ensure maximum compatibility with existing
clients.

## Backwards Compatibility

Clients emitting tracing JSON for uncontained &quot;legacy&quot; contracts will produce a compatible trace,
except as outlined below

### Changes from EIP-3155

- The term Client Under Test or CUT has been replaced simply with &quot;client.&quot;
- `gas`, `gasCost`, and `gasUsed` are now Number types.
- `opcode` is now a Hex-Number type.

### Additions to EIP-3155

- The `immediate` member was added to support the large number of instructions that contain 
  immediate operations. Without this change, users would need bytes of the contracts being executed 
  to rationalize the traces.
- The `section` and `functionDepth` members were added to support [EIP-4750](./eip-4750) EOF 
  Functions.
- Added clarification around where `pc` indexes when run in an EOF container.
- Added Hex-Number/Number interchangeability expectations. Clients MAY provide either types when
  one is specified and consumers SHOULD be prepared to accept either type. Clients SHOULD provide a
  flag to output members with the specified number type only.

### Clients

Besu, evmone, EthereumJS, Geth, Nethermind, and Reth already produce these standard traces in
various tools. Adding the new fields will align with work needed to support the EOF EIPs enumerated
in EIP-7692.

## Test Cases

This is the trace output from the Ethereum Execution Specification Test from one of the
parameterized executions of [test_eof_functions_contract_call_succeed](https://github.com/ethereum/execution-spec-tests/blob/632d151ea8a71d09a3a0acbdb85d97fa18c8456b/tests/prague/eip7692_eof_v1/eip3540_eof_v1/test_execution_function.py#L304-L335).
Memory and return data is disabled.

```json lines
{&quot;pc&quot;:0,&quot;op&quot;:&quot;0x60&quot;,&quot;gas&quot;:49979000,&quot;gasCost&quot;:3,&quot;memSize&quot;:0,&quot;stack&quot;:[],&quot;depth&quot;:1,&quot;refund&quot;:0,&quot;opName&quot;:&quot;PUSH1&quot;}
{&quot;pc&quot;:2,&quot;op&quot;:&quot;0x60&quot;,&quot;gas&quot;:49978997,&quot;gasCost&quot;:3,&quot;memSize&quot;:0,&quot;stack&quot;:[&quot;0x0&quot;],&quot;depth&quot;:1,&quot;refund&quot;:0,&quot;opName&quot;:&quot;PUSH1&quot;}
{&quot;pc&quot;:4,&quot;op&quot;:&quot;0x60&quot;,&quot;gas&quot;:49978994,&quot;gasCost&quot;:3,&quot;memSize&quot;:0,&quot;stack&quot;:[&quot;0x0&quot;,&quot;0x0&quot;],&quot;depth&quot;:1,&quot;refund&quot;:0,&quot;opName&quot;:&quot;PUSH1&quot;}
{&quot;pc&quot;:6,&quot;op&quot;:&quot;0x60&quot;,&quot;gas&quot;:49978991,&quot;gasCost&quot;:3,&quot;memSize&quot;:0,&quot;stack&quot;:[&quot;0x0&quot;,&quot;0x0&quot;,&quot;0x0&quot;],&quot;depth&quot;:1,&quot;refund&quot;:0,&quot;opName&quot;:&quot;PUSH1&quot;}
{&quot;pc&quot;:8,&quot;op&quot;:&quot;0x60&quot;,&quot;gas&quot;:49978988,&quot;gasCost&quot;:3,&quot;memSize&quot;:0,&quot;stack&quot;:[&quot;0x0&quot;,&quot;0x0&quot;,&quot;0x0&quot;,&quot;0x0&quot;],&quot;depth&quot;:1,&quot;refund&quot;:0,&quot;opName&quot;:&quot;PUSH1&quot;}
{&quot;pc&quot;:10,&quot;op&quot;:&quot;0x61&quot;,&quot;gas&quot;:49978985,&quot;gasCost&quot;:3,&quot;memSize&quot;:0,&quot;stack&quot;:[&quot;0x0&quot;,&quot;0x0&quot;,&quot;0x0&quot;,&quot;0x0&quot;,&quot;0x0&quot;],&quot;depth&quot;:1,&quot;refund&quot;:0,&quot;opName&quot;:&quot;PUSH2&quot;}
{&quot;pc&quot;:13,&quot;op&quot;:&quot;0x5a&quot;,&quot;gas&quot;:49978982,&quot;gasCost&quot;:2,&quot;memSize&quot;:0,&quot;stack&quot;:[&quot;0x0&quot;,&quot;0x0&quot;,&quot;0x0&quot;,&quot;0x0&quot;,&quot;0x0&quot;,&quot;0x1000&quot;],&quot;depth&quot;:1,&quot;refund&quot;:0,&quot;opName&quot;:&quot;GAS&quot;}
{&quot;pc&quot;:14,&quot;op&quot;:&quot;0xf1&quot;,&quot;gas&quot;:49978980,&quot;gasCost&quot;:49198100,&quot;memSize&quot;:0,&quot;stack&quot;:[&quot;0x0&quot;,&quot;0x0&quot;,&quot;0x0&quot;,&quot;0x0&quot;,&quot;0x0&quot;,&quot;0x1000&quot;,&quot;0x2fa9e64&quot;],&quot;depth&quot;:1,&quot;refund&quot;:0,&quot;opName&quot;:&quot;CALL&quot;}
{&quot;pc&quot;:25,&quot;section&quot;:0,&quot;op&quot;:&quot;0xe3&quot;,&quot;immediate&quot;:&quot;0x0001&quot;,&quot;gas&quot;:49195500,&quot;gasCost&quot;:5,&quot;memSize&quot;:0,&quot;stack&quot;:[],&quot;depth&quot;:2,&quot;refund&quot;:0,&quot;opName&quot;:&quot;CALLF&quot;}
{&quot;pc&quot;:29,&quot;section&quot;:1,&quot;op&quot;:&quot;0xe4&quot;,&quot;gas&quot;:49195495,&quot;gasCost&quot;:3,&quot;memSize&quot;:0,&quot;stack&quot;:[],&quot;depth&quot;:2,&quot;functionDepth&quot;:2,&quot;refund&quot;:0,&quot;opName&quot;:&quot;RETF&quot;}
{&quot;pc&quot;:28,&quot;section&quot;:0,&quot;op&quot;:&quot;0x00&quot;,&quot;gas&quot;:49195492,&quot;gasCost&quot;:0,&quot;memSize&quot;:0,&quot;stack&quot;:[],&quot;depth&quot;:2,&quot;refund&quot;:0,&quot;opName&quot;:&quot;STOP&quot;}
{&quot;pc&quot;:15,&quot;op&quot;:&quot;0x60&quot;,&quot;gas&quot;:49976372,&quot;gasCost&quot;:3,&quot;memSize&quot;:0,&quot;stack&quot;:[&quot;0x1&quot;],&quot;depth&quot;:1,&quot;refund&quot;:0,&quot;opName&quot;:&quot;PUSH1&quot;}
{&quot;pc&quot;:17,&quot;op&quot;:&quot;0x55&quot;,&quot;gas&quot;:49976369,&quot;gasCost&quot;:22100,&quot;memSize&quot;:0,&quot;stack&quot;:[&quot;0x1&quot;,&quot;0x0&quot;],&quot;depth&quot;:1,&quot;refund&quot;:0,&quot;opName&quot;:&quot;SSTORE&quot;}
{&quot;pc&quot;:18,&quot;op&quot;:&quot;0x00&quot;,&quot;gas&quot;:49954269,&quot;gasCost&quot;:0,&quot;memSize&quot;:0,&quot;stack&quot;:[],&quot;depth&quot;:1,&quot;refund&quot;:0,&quot;opName&quot;:&quot;STOP&quot;}
{&quot;output&quot;:&quot;&quot;,&quot;gasUsed&quot;:45731,&quot;fork&quot;:&quot;Osaka&quot;,&quot;postHash&quot;:&quot;0x2c47b4070c1eef501d9548959c3abde2d8dc78ed1d819697c61d2b0861cc78cf&quot;,&quot;pass&quot;:true}
```

## Security Considerations

Clients should be aware that tracing can be expensive both in terms of CPU overhead and network
bandwidth. Tracing endpoints should not be enabled by default, and when they are enabled should have 
access restrictions on the network level. Failure to do so could result in a client being 
overwhelmed with requests and, if operating as a validator, cause the client to fail to provide 
execution attestations in a timely manner.

Differential fuzzing is also a double-edged sword. While it allows client teams the ability to 
identify consensus splits, the client teams need to be prompt in fixing any issues that are 
discovered.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 13 Aug 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7756</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7756</guid>
      </item>
    
      <item>
        <title>Transfer With Authorization</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7758-transfer-with-authorization/20859</comments>
        
        <description>## Abstract

A set of functions to enable meta-transactions and atomic interactions with [ERC-20](/EIPs/EIPS/eip-20) token contracts via signatures conforming to the [EIP-712](/EIPs/EIPS/eip-712) typed message signing specification.

This enables the user to:

- delegate the gas payment to someone else,
- pay for gas in the token itself rather than in ETH,
- perform one or more token transfers and other operations in a single atomic transaction,
- transfer ERC-20 tokens to another address, and have the recipient submit the transaction,
- batch multiple transactions with minimal overhead, and
- create and perform multiple transactions without having to worry about them failing due to accidental nonce-reuse or improper ordering by the miner.

## Motivation

There is an existing spec, [EIP-2612](./eip-2612), that also allows meta-transactions, and it is encouraged that a contract implements both for maximum compatibility. The two primary differences between this spec and EIP-2612 are that:

- EIP-2612 uses sequential nonces, but this uses random 32-byte nonces, and that
- EIP-2612 relies on the ERC-20 `approve`/`transferFrom` (&quot;ERC-20 allowance&quot;) pattern.

The biggest issue with the use of sequential nonces is that it does not allow users to perform more than one transaction at time without risking their transactions failing, because:

- DApps may unintentionally reuse nonces that have not yet been processed in the blockchain.
- Miners may process the transactions in the incorrect order.

This can be especially problematic if the gas prices are very high and transactions often get queued up and remain unconfirmed for a long time. Non-sequential nonces allow users to create as many transactions as they want at the same time.

The ERC-20 allowance mechanism is susceptible to the multiple withdrawal attack, and encourages antipatterns such as the use of the &quot;infinite&quot; allowance. The wide-prevalence of upgradeable contracts have made the conditions favorable for these attacks to happen in the wild.

The deficiencies of the ERC-20 allowance pattern brought about the development of alternative token standards such as the [ERC-777](./eip-777). However, they haven&apos;t been able to gain much adoption due to compatibility and potential security issues.

## Specification

### Event

```solidity
event AuthorizationUsed(
    address indexed authorizer,
    bytes32 indexed nonce
);

// keccak256(&quot;TransferWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)&quot;)
bytes32 public constant TRANSFER_WITH_AUTHORIZATION_TYPEHASH = 0x7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a2267;

// keccak256(&quot;ReceiveWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)&quot;)
bytes32 public constant RECEIVE_WITH_AUTHORIZATION_TYPEHASH = 0xd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de8;

/**
 * @notice Returns the state of an authorization
 * @dev Nonces are randomly generated 32-byte data unique to the authorizer&apos;s
 * address
 * @param authorizer    Authorizer&apos;s address
 * @param nonce         Nonce of the authorization
 * @return True if the nonce is used
 */
function authorizationState(
    address authorizer,
    bytes32 nonce
) external view returns (bool);

/**
 * @notice Execute a transfer with a signed authorization
 * @param from          Payer&apos;s address (Authorizer)
 * @param to            Payee&apos;s address
 * @param value         Amount to be transferred
 * @param validAfter    The time after which this is valid (unix time)
 * @param validBefore   The time before which this is valid (unix time)
 * @param nonce         Unique nonce
 * @param v             v of the signature
 * @param r             r of the signature
 * @param s             s of the signature
 */
function transferWithAuthorization(
    address from,
    address to,
    uint256 value,
    uint256 validAfter,
    uint256 validBefore,
    bytes32 nonce,
    uint8 v,
    bytes32 r,
    bytes32 s
) external;

/**
 * @notice Receive a transfer with a signed authorization from the payer
 * @dev This has an additional check to ensure that the payee&apos;s address matches
 * the caller of this function to prevent front-running attacks. (See security
 * considerations)
 * @param from          Payer&apos;s address (Authorizer)
 * @param to            Payee&apos;s address
 * @param value         Amount to be transferred
 * @param validAfter    The time after which this is valid (unix time)
 * @param validBefore   The time before which this is valid (unix time)
 * @param nonce         Unique nonce
 * @param v             v of the signature
 * @param r             r of the signature
 * @param s             s of the signature
 */
function receiveWithAuthorization(
    address from,
    address to,
    uint256 value,
    uint256 validAfter,
    uint256 validBefore,
    bytes32 nonce,
    uint8 v,
    bytes32 r,
    bytes32 s
) external;
```

**Optional:**

```
event AuthorizationCanceled(
    address indexed authorizer,
    bytes32 indexed nonce
);

// keccak256(&quot;CancelAuthorization(address authorizer,bytes32 nonce)&quot;)
bytes32 public constant CANCEL_AUTHORIZATION_TYPEHASH = 0x158b0a9edf7a828aad02f63cd515c68ef2f50ba807396f6d12842833a1597429;

/**
 * @notice Attempt to cancel an authorization
 * @param authorizer    Authorizer&apos;s address
 * @param nonce         Nonce of the authorization
 * @param v             v of the signature
 * @param r             r of the signature
 * @param s             s of the signature
 */
function cancelAuthorization(
    address authorizer,
    bytes32 nonce,
    uint8 v,
    bytes32 r,
    bytes32 s
) external;
```


The arguments `v`, `r`, and `s` must be obtained using the [EIP-712](/EIPs/EIPS/eip-712) typed message signing spec.

**Example:**

```
DomainSeparator := Keccak256(ABIEncode(
  Keccak256(
    &quot;EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)&quot;
  ),
  Keccak256(&quot;USD Coin&quot;),                      // name
  Keccak256(&quot;2&quot;),                             // version
  1,                                          // chainId
  0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48  // verifyingContract
))
```

With the domain separator, the typehash, which is used to identify the type of the EIP-712 message being used, and the values of the parameters, you are able to derive a Keccak-256 hash digest which can then be signed using the token holder&apos;s private key.

**Example:**

```
// Transfer With Authorization
TypeHash := Keccak256(
  &quot;TransferWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)&quot;
)
Params := { From, To, Value, ValidAfter, ValidBefore, Nonce }

// ReceiveWithAuthorization
TypeHash := Keccak256(
  &quot;ReceiveWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)&quot;
)
Params := { From, To, Value, ValidAfter, ValidBefore, Nonce }

// CancelAuthorization
TypeHash := Keccak256(
  &quot;CancelAuthorization(address authorizer,bytes32 nonce)&quot;
)
Params := { Authorizer, Nonce }
```

```
// &quot;‖&quot; denotes concatenation.
Digest := Keecak256(
  0x1901 ‖ DomainSeparator ‖ Keccak256(ABIEncode(TypeHash, Params...))
)

{ v, r, s } := Sign(Digest, PrivateKey)
```

Smart contract functions that wrap `receiveWithAuthorization` call may choose to reduce the number of arguments by accepting the full ABI-encoded set of arguments for the `receiveWithAuthorization` call as a single argument of the type `bytes`.

**Example:**

```solidity
// keccak256(&quot;receiveWithAuthorization(address,address,uint256,uint256,uint256,bytes32,uint8,bytes32,bytes32)&quot;)[0:4]
bytes4 private constant _RECEIVE_WITH_AUTHORIZATION_SELECTOR = 0xef55bec6;

function deposit(address token, bytes calldata receiveAuthorization)
    external
    nonReentrant
{
    (address from, address to, uint256 amount) = abi.decode(
        receiveAuthorization[0:96],
        (address, address, uint256)
    );
    require(to == address(this), &quot;Recipient is not this contract&quot;);

    (bool success, ) = token.call(
        abi.encodePacked(
            _RECEIVE_WITH_AUTHORIZATION_SELECTOR,
            receiveAuthorization
        )
    );
    require(success, &quot;Failed to transfer tokens&quot;);

    ...
}
```

### Use with web3 providers

The signature for an authorization can be obtained using a web3 provider with the `eth_signTypedData{_v4}` method.

**Example:**

```javascript
const data = {
  types: {
    EIP712Domain: [
      { name: &quot;name&quot;, type: &quot;string&quot; },
      { name: &quot;version&quot;, type: &quot;string&quot; },
      { name: &quot;chainId&quot;, type: &quot;uint256&quot; },
      { name: &quot;verifyingContract&quot;, type: &quot;address&quot; },
    ],
    TransferWithAuthorization: [
      { name: &quot;from&quot;, type: &quot;address&quot; },
      { name: &quot;to&quot;, type: &quot;address&quot; },
      { name: &quot;value&quot;, type: &quot;uint256&quot; },
      { name: &quot;validAfter&quot;, type: &quot;uint256&quot; },
      { name: &quot;validBefore&quot;, type: &quot;uint256&quot; },
      { name: &quot;nonce&quot;, type: &quot;bytes32&quot; },
    ],
  },
  domain: {
    name: tokenName,
    version: tokenVersion,
    chainId: selectedChainId,
    verifyingContract: tokenAddress,
  },
  primaryType: &quot;TransferWithAuthorization&quot;,
  message: {
    from: userAddress,
    to: recipientAddress,
    value: amountBN.toString(10),
    validAfter: 0,
    validBefore: Math.floor(Date.now() / 1000) + 3600, // Valid for an hour
    nonce: Web3.utils.randomHex(32),
  },
};

const signature = await ethereum.request({
  method: &quot;eth_signTypedData_v4&quot;,
  params: [userAddress, JSON.stringify(data)],
});

const v = &quot;0x&quot; + signature.slice(130, 132);
const r = signature.slice(0, 66);
const s = &quot;0x&quot; + signature.slice(66, 130);
```

## Rationale

### Unique Random Nonce, Instead of Sequential Nonce

One might say transaction ordering is one reason why sequential nonces are preferred. However, sequential nonces do not actually help achieve transaction ordering for meta transactions in practice:

- For native Ethereum transactions, when a transaction with a nonce value that is too-high is submitted to the network, it will stay pending until the transactions consuming the lower unused nonces are confirmed.
- However, for meta-transactions, when a transaction containing a sequential nonce value that is too high is submitted, instead of staying pending, it will revert and fail immediately, resulting in wasted gas.
- The fact that miners can also reorder transactions and include them in the block in the order they want (assuming each transaction was submitted to the network by different meta-transaction relayers) also makes it possible for the meta-transactions to fail even if the nonces used were correct. (e.g. User submits nonces 3, 4 and 5, but miner ends up including them in the block as 4,5,3, resulting in only 3 succeeding)
- Lastly, when using different applications simultaneously, in absence of some sort of an off-chain nonce-tracker, it is not possible to determine what the correct next nonce value is if there exists nonces that are used but haven&apos;t been submitted and confirmed by the network.
- Under high gas price conditions, transactions can often &quot;get stuck&quot; in the pool for a long time. Under such a situation, it is much more likely for the same nonce to be unintentionally reused twice. For example, if you make a meta-transaction that uses a sequential nonce from one app, and switch to another app to make another meta-transaction before the previous one confirms, the same nonce will be used if the app relies purely on the data available on-chain, resulting in one of the transactions failing.
- In conclusion, the only way to guarantee transaction ordering is for relayers to submit transactions one at a time, waiting for confirmation between each submission (and the order in which they should be submitted can be part of some off-chain metadata), rendering sequential nonce irrelevant.

### Valid After and Valid Before

- Relying on relayers to submit transactions for you means you may not have exact control over the timing of transaction submission.
- These parameters allow the user to schedule a transaction to be only valid in the future or before a specific deadline, protecting the user from potential undesirable effects that may be caused by the submission being made either too late or too early.

### EIP-712

- EIP-712 ensures that the signatures generated are valid only for this specific instance of the token contract and cannot be replayed on a different network with a different chain ID.
- This is achieved by incorporating the contract address and the chain ID in a Keccak-256 hash digest called the domain separator. The actual set of parameters used to derive the domain separator is up to the implementing contract, but it is highly recommended that the fields `verifyingContract` and `chainId` are included.

## Backwards Compatibility

New contracts benefit from being able to directly utilize this proposal in order to create atomic transactions, but existing contracts may still rely on the conventional [ERC-20](/EIPs/EIPS/eip-20) allowance pattern (`approve`/`transferFrom`).

In order to add support for this proposal to existing contracts (&quot;parent contract&quot;) that use the ERC-20 allowance pattern, a forwarding contract (&quot;forwarder&quot;) can be constructed that takes an authorization and does the following:

1. Extract the user and deposit amount from the authorization
2. Call `receiveWithAuthorization` to transfer specified funds from the user to the forwarder
3. Approve the parent contract to spend funds from the forwarder
4. Call the method on the parent contract that spends the allowance set from the forwarder
5. Transfer the ownership of any resulting tokens back to the user

**Example:**

```solidity
interface IDeFiToken {
    function deposit(uint256 amount) external returns (uint256);

    function transfer(address account, uint256 amount)
        external
        returns (bool);
}

contract DepositForwarder {
    bytes4 private constant _RECEIVE_WITH_AUTHORIZATION_SELECTOR = 0xef55bec6;

    IDeFiToken private _parent;
    IERC20 private _token;

    constructor(IDeFiToken parent, IERC20 token) public {
        _parent = parent;
        _token = token;
    }

    function deposit(bytes calldata receiveAuthorization)
        external
        nonReentrant
        returns (uint256)
    {
        (address from, address to, uint256 amount) = abi.decode(
            receiveAuthorization[0:96],
            (address, address, uint256)
        );
        require(to == address(this), &quot;Recipient is not this contract&quot;);

        (bool success, ) = address(_token).call(
            abi.encodePacked(
                _RECEIVE_WITH_AUTHORIZATION_SELECTOR,
                receiveAuthorization
            )
        );
        require(success, &quot;Failed to transfer to the forwarder&quot;);

        require(
            _token.approve(address(_parent), amount),
            &quot;Failed to set the allowance&quot;
        );

        uint256 tokensMinted = _parent.deposit(amount);
        require(
            _parent.transfer(from, tokensMinted),
            &quot;Failed to transfer the minted tokens&quot;
        );

        uint256 remainder = _token.balanceOf(address(this);
        if (remainder &gt; 0) {
            require(
                _token.transfer(from, remainder),
                &quot;Failed to refund the remainder&quot;
            );
        }

        return tokensMinted;
    }
}
```

## Reference Implementation

### `EIP7758.sol`

```solidity
abstract contract EIP7758 is IERC20Transfer, EIP712Domain {
    // keccak256(&quot;TransferWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)&quot;)
    bytes32 public constant TRANSFER_WITH_AUTHORIZATION_TYPEHASH = 0x7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a2267;

    // keccak256(&quot;ReceiveWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)&quot;)
    bytes32 public constant RECEIVE_WITH_AUTHORIZATION_TYPEHASH = 0xd099cc98ef71107a616c4f0f941f04c322d8e254fe26b3c6668db87aae413de8;

    mapping(address =&gt; mapping(bytes32 =&gt; bool)) internal _authorizationStates;

    event AuthorizationUsed(address indexed authorizer, bytes32 indexed nonce);

    string internal constant _INVALID_SIGNATURE_ERROR = &quot;EIP7758: invalid signature&quot;;

    function authorizationState(address authorizer, bytes32 nonce)
        external
        view
        returns (bool)
    {
        return _authorizationStates[authorizer][nonce];
    }

    function transferWithAuthorization(
        address from,
        address to,
        uint256 value,
        uint256 validAfter,
        uint256 validBefore,
        bytes32 nonce,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external {
        require(now &gt; validAfter, &quot;EIP7758: authorization is not yet valid&quot;);
        require(now &lt; validBefore, &quot;EIP7758: authorization is expired&quot;);
        require(
            !_authorizationStates[from][nonce],
            &quot;EIP7758: authorization is used&quot;
        );

        bytes memory data = abi.encode(
            TRANSFER_WITH_AUTHORIZATION_TYPEHASH,
            from,
            to,
            value,
            validAfter,
            validBefore,
            nonce
        );
        require(
            EIP712.recover(DOMAIN_SEPARATOR, v, r, s, data) == from,
            &quot;EIP7758: invalid signature&quot;
        );

        _authorizationStates[from][nonce] = true;
        emit AuthorizationUsed(from, nonce);

        _transfer(from, to, value);
    }
}
```

### `IERC20Transfer.sol`

```solidity
abstract contract IERC20Transfer {
    function _transfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal virtual;
}
```

### `EIP712Domain.sol`
```solidity
abstract contract EIP712Domain {
    bytes32 public DOMAIN_SEPARATOR;
}
```

### `EIP712.sol`

```solidity
library EIP712 {
    // keccak256(&quot;EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)&quot;)
    bytes32 public constant EIP712_DOMAIN_TYPEHASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;

    function makeDomainSeparator(string memory name, string memory version)
        internal
        view
        returns (bytes32)
    {
        uint256 chainId;
        assembly {
            chainId := chainid()
        }

        return
            keccak256(
                abi.encode(
                    EIP712_DOMAIN_TYPEHASH,
                    keccak256(bytes(name)),
                    keccak256(bytes(version)),
                    bytes32(chainId),
                    address(this)
                )
            );
    }

    function recover(
        bytes32 domainSeparator,
        uint8 v,
        bytes32 r,
        bytes32 s,
        bytes memory typeHashAndData
    ) internal pure returns (address) {
        bytes32 digest = keccak256(
            abi.encodePacked(
                &quot;\x19\x01&quot;,
                domainSeparator,
                keccak256(typeHashAndData)
            )
        );
        address recovered = ecrecover(digest, v, r, s);
        require(recovered != address(0), &quot;EIP712: invalid signature&quot;);
        return recovered;
    }
}
```

## Security Considerations

Use `receiveWithAuthorization` instead of `transferWithAuthorization` when calling from other smart contracts. It is possible for an attacker watching the transaction pool to extract the transfer authorization and front-run the `transferWithAuthorization` call to execute the transfer without invoking the wrapper function. This could potentially result in unprocessed, locked up deposits. `receiveWithAuthorization` prevents this by performing an additional check that ensures that the caller is the payee. Additionally, if there are multiple contract functions accepting receive authorizations, the app developer could dedicate some leading bytes of the nonce could as the identifier to prevent cross-use.

When submitting multiple transfers simultaneously, be mindful of the fact that relayers and miners will decide the order in which they are processed. This is generally not a problem if the transactions are not dependent on each other, but for transactions that are highly dependent on each other, it is recommended that the signed authorizations are submitted one at a time.

The zero address must be rejected when using `ecrecover` to prevent unauthorized transfers and approvals of funds from the zero address. The built-in `ecrecover` returns the zero address when a malformed signature is provided.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 28 Sep 2020 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7758</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7758</guid>
      </item>
    
      <item>
        <title>Minimal Upgradeable Proxies</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7760-minimal-upgradeable-proxies/20868</comments>
        
        <description>## Abstract

This standard defines minimal [ERC-1967](/EIPs/EIPS/eip-1967) proxies for three patterns: (1) transparent, (2) UUPS, (3) beacon. The proxies support optional immutable arguments which are appended to the end of their runtime bytecode. Additional variants which support onchain implementation querying are provided.

## Motivation

Having standardized minimal bytecode for upgradeable proxies enables the following:

1. Automatic verification on block explorers.
2. Ability for immutable arguments to be queried onchain, as these arguments are stored at the same bytecode offset,
3. Ability for the implementation to be queried and verified onchain.

The minimal nature of the proxies enables cheaper deployment and runtime costs.

## Specification

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

### General specifications

All of the following proxies MAY have optional data bytecode appended to the end of their runtime bytecode. 

Emitting the ERC-1967 events during initialization is OPTIONAL. Indexers MUST NOT expect the initialization code to emit the ERC-1967 events.

### Onchain querying of implementation for I-variants

The I-variants have logic that returns the implementation baked into their bytecode.

When called with any 1-byte calldata, these I-variants will return the address (left-zero-padded to 32 bytes) and will not forward the calldata to the target.

The bytecode of the proxies before any optional immutable arguments MUST be verified with the following steps:

1. Fetch the bytecode before any immutable arguments with `EXTCODECOPY`.
2. Zeroize any baked-in factory address in the fetched bytecode.
3. Ensure that the hash of the final fetched bytecode matches the expected hash of the bytecode.

If the hash does not match, the implementation address returned MUST NOT be trusted.

### Minimal ERC-1967 transparent upgradeable proxy

The transparent upgradeable proxy is RECOMMENDED to be deployed by a factory that doubles as the account that is authenticated to perform upgrades. An externally owned account may perform the deployment on behalf of the factory. For convention, we will refer to the factory as the immutable account authorized to invoke the upgrade logic on the proxy.

As the proxy&apos;s runtime bytecode contains logic to allow the factory to set any storage slot with any value, the initialization code MAY skip storing the implementation slot.

The upgrading logic does not emit the ERC-1967 event. Indexers MUST NOT expect the upgrading logic to emit the ERC-1967 events.

During upgrades, the factory MUST call the upgradeable proxy with following calldata:

```solidity
abi.encodePacked(
    // The new implementation address, converted to a 32-byte word.
    uint256(uint160(implementation)),
    // ERC-1967 implementation slot.
    bytes32(0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc),
    // Optional calldata to be forwarded to the implementation
    // via delegatecall after setting the implementation slot.
    &quot;&quot;
)
```

#### Minimal ERC-1967 transparent upgradeable proxy for (basic variant)

Runtime bytecode (20-byte factory address subvariant):

```
3d3d3373________________________________________14605757363d3d37363d7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d6000803e6052573d6000fd5b3d6000f35b3d356020355560408036111560525736038060403d373d3d355af43d6000803e6052573d6000fd
```

where `________________________________________` is the 20-byte factory address.

Runtime bytecode (14-byte factory address subvariant):

```
3d3d336d____________________________14605157363d3d37363d7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d6000803e604c573d6000fd5b3d6000f35b3d3560203555604080361115604c5736038060403d373d3d355af43d6000803e604c573d6000fd
```

where `____________________________` is the 14-byte factory address.

#### Minimal ERC-1967 transparent upgradeable proxy (I-variant)

Runtime bytecode (20-byte factory address subvariant):

```
3658146083573d3d3373________________________________________14605D57363d3d37363D7f360894a13ba1A3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d6000803e6058573d6000fd5b3d6000f35b3d35602035556040360380156058578060403d373d3d355af43d6000803e6058573d6000fd5b602060293d393d51543d52593df3
```

where `________________________________________` is the 20-byte factory address.

Runtime bytecode (14-byte factory address subvariant):

```
365814607d573d3d336d____________________________14605757363d3D37363d7F360894A13Ba1A3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d6000803e6052573d6000fd5b3d6000f35b3d35602035556040360380156052578060403d373d3d355af43d6000803e6052573d6000fd5b602060233d393d51543d52593df3
```

where `____________________________` is the 14-byte factory address.

### Minimal ERC-1967 UUPS proxy

As this proxy does not contain upgrading logic, the initialization code MUST store the implementation at the ERC-1967 implementation storage slot `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`.

#### Minimal ERC-1967 UUPS proxy (basic variant)

Runtime bytecode:

```
363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3
```

#### Minimal ERC-1967 UUPS proxy (I-variant)

Runtime bytecode:

```
365814604357363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3
```

### Minimal ERC-1967 beacon proxy

As this proxy does not contain upgrading logic, the initialization code MUST store the implementation at the ERC-1967 implementation storage slot `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`.

#### Minimal ERC-1967 beacon proxy (basic variant)

Runtime bytecode:

```
363d3d373d3d363d602036600436635c60da1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3
```

#### Minimal ERC-1967 beacon proxy (I-variant)

Runtime bytecode:

```
363d3d373d3d363d602036600436635c60da1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3
```

## Rationale

### No usage of `PUSH0` opcode

For more widespread EVM compatibility, the proxies deliberately do not use the `PUSH0` opcode proposed in [EIP-3855](/EIPs/EIPS/eip-3855).

Converting the proxies to `PUSH0` variants may be done in a separate future ERC.

### Optimization priorities

The proxies are first optimized for minimal runtime gas before minimal bytecode size.

### Minimal nature

These proxies made from handcrafted EVM bytecode. While utmost efforts have been made to ensure that they are as minimal as possible at the time of development, it is possible that they can be further optimized. If a variant has already been used in the wild, it is preferable to keep their existing layout in this standard, as the benefits of automatic block explorer verification will outweigh the few gas saved during runtime or deployment. 

For historical reference, the [ERC-1167](/EIPs/EIPS/eip-1167) minimal proxy was not the theoretical minimal at the time of writing. The 0age minimal proxy has lower runtime gas costs and smaller bytecode size.  

### Transparent upgradeable proxy

The factory address in the transparent upgradeable proxy is baked into the immutable bytecode of the minimal transparent upgradeable proxy.

This is to save a `SLOAD` for every proxy call.

As the factory can contain custom authorization logic that allows for admin rotation, we do not lose any flexibility.

The upgrade logic takes in any 32 byte value and 32 byte storage slot. This is for flexibility and bytecode conciseness.

We do not lose any security as the implementation can still modify any storage slot.

### 14-byte factory address subvariants

It is beneficial to install the transparent upgradeable proxy factory at a vanity address with leading zero bytes so that the proxy&apos;s bytecode can be optimized to be shorter.

A 14-byte factory address (i.e. 6 leading zero bytes) is chosen because it strikes a balance between mining costs and bytecode size. 

### I-variants 

The so-called &quot;I-variants&quot; contain logic that returns the implementation address baked into the proxy bytecode.

This allows contracts to retrieve the implementation of the proxy onchain in a verifiable way.

As long as the proxy&apos;s runtime bytecode starts with the bytecode in this standard, we can be sure that the implementation address is not spoofed.

The choice of reserving 1-byte calldata to denote an implementation query request is for efficiency and to prevent calldata collision. Regular ETH transfers use 0-byte calldata, and regular Solidity function calls use calldata that is 4 bytes or longer.

### Omission of events in bytecode

This is for minimal bytecode size and deployment costs. 

Most block explorers and indexers are able to deduce the latest implementation without the use of events simply by reading the slots.

### Immutable arguments are not appended to forwarded calldata

This is to avoid compatibility and safety issues with other ERC standards that append extra data to the calldata.

The `EXTCODECOPY` opcode can be used to retrieve the immutable arguments.

### No fixed initialization code

As long as the initialization code is able to initialize the relevant ERC-1967 implementation slot where needed (i.e. for the UUPS proxy and Beacon proxy), there is no need for additional requirements on the initialization code.

### Out of scope topics

The following topics are intentionally out of scope of this standard, as they can contain custom logic:

- Factories for proxy deployment.
- Logic for reading and verifying the implementation from the I-variants onchain.
- Beacon for the beacon proxies.

Nevertheless, they require careful implementation to ensure security and correctness.

## Backwards Compatibility

No backward compatibility issues found.

## Reference Implementation

### Minimal ERC-1967 transparent upgradeable proxy implementation

#### Minimal ERC-1967 transparent upgradeable proxy implementation (basic variant)

```solidity
pragma solidity ^0.8.0;

library ERC1967MinimalTransparentUpgradeableProxyLib {
    function initCodeFor20ByteFactoryAddress() internal view returns (bytes memory) {
        return abi.encodePacked(
            bytes13(0x607f3d8160093d39f33d3d3373),
            address(this),
            bytes32(0x14605757363d3d37363d7f360894a13ba1a3210667c828492db98dca3e2076cc),
            bytes32(0x3735a920a3ca505d382bbc545af43d6000803e6052573d6000fd5b3d6000f35b),
            bytes32(0x3d356020355560408036111560525736038060403d373d3d355af43d6000803e),
            bytes7(0x6052573d6000fd)
        );
    }

    function initCodeFor14ByteFactoryAddress() internal view returns (bytes memory) {
        return abi.encodePacked(
            bytes13(0x60793d8160093d39f33d3d336d),
            uint112(uint160(address(this))),
            bytes32(0x14605157363d3d37363d7f360894a13ba1a3210667c828492db98dca3e2076cc),
            bytes32(0x3735a920a3ca505d382bbc545af43d6000803e604c573d6000fd5b3d6000f35b),
            bytes32(0x3d3560203555604080361115604c5736038060403d373d3d355af43d6000803e),
            bytes7(0x604c573d6000fd)
        );
    }

    function initCode() internal view returns (bytes memory) {
        if (uint160(address(this)) &gt;&gt; 112 != 0) {
            return initCodeFor20ByteFactoryAddress();
        } else {
            return initCodeFor14ByteFactoryAddress();
        }
    }

    function deploy(address implementation, bytes memory initializationData)
        internal
        returns (address instance)
    {
        bytes memory m = initCode();
        assembly {
            instance := create(0, add(m, 0x20), mload(m))
        }
        require(instance != address(0), &quot;Deployment failed.&quot;);
        upgrade(instance, implementation, initializationData);
    }

    function upgrade(address instance, address implementation, bytes memory upgradeData) internal {
        (bool success,) = instance.call(
            abi.encodePacked(
                // The new implementation address, converted to a 32-byte word.
                uint256(uint160(implementation)),
                // ERC-1967 implementation slot.
                bytes32(0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc),
                // Optional calldata to be forwarded to the implementation
                // via delegatecall after setting the implementation slot.
                upgradeData
            )
        );
        require(success, &quot;Upgrade failed.&quot;);
    }
}
```

#### Minimal ERC-1967 transparent upgradeable proxy implementation (I-variant)

```solidity
pragma solidity ^0.8.0;

library ERC1967IMinimalTransparentUpgradeableProxyLib {
    function initCodeFor20ByteFactoryAddress() internal view returns (bytes memory) {
        return abi.encodePacked(
            bytes19(0x60923d8160093d39f33658146083573d3d3373),
            address(this),
            bytes20(0x14605D57363d3d37363D7f360894a13ba1A32106),
            bytes32(0x67c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d6000803e60),
            bytes32(0x58573d6000fd5b3d6000f35b3d35602035556040360380156058578060403d37),
            bytes32(0x3d3d355af43d6000803e6058573d6000fd5b602060293d393d51543d52593df3)
        );
    }

    function initCodeFor14ByteFactoryAddress() internal view returns (bytes memory) {
        return abi.encodePacked(
            bytes19(0x608c3d8160093d39f3365814607d573d3d336d),
            uint112(uint160(address(this))),
            bytes20(0x14605757363d3D37363d7F360894A13Ba1A32106),
            bytes32(0x67c828492db98dca3e2076cc3735a920a3ca505d382bbc545af43d6000803e60),
            bytes32(0x52573d6000fd5b3d6000f35b3d35602035556040360380156052578060403d37),
            bytes32(0x3d3d355af43d6000803e6052573d6000fd5b602060233d393d51543d52593df3)
        );
    }

    function initCode() internal view returns (bytes memory) {
        if (uint160(address(this)) &gt;&gt; 112 != 0) {
            return initCodeFor20ByteFactoryAddress();
        } else {
            return initCodeFor14ByteFactoryAddress();
        }
    }

    function deploy(address implementation, bytes memory initializationData)
        internal
        returns (address instance)
    {
        bytes memory m = initCode();
        assembly {
            instance := create(0, add(m, 0x20), mload(m))
        }
        require(instance != address(0), &quot;Deployment failed.&quot;);
        upgrade(instance, implementation, initializationData);
    }

    function upgrade(address instance, address implementation, bytes memory upgradeData) internal {
        (bool success,) = instance.call(
            abi.encodePacked(
                // The new implementation address, converted to a 32-byte word.
                uint256(uint160(implementation)),
                // ERC-1967 implementation slot.
                bytes32(0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc),
                // Optional calldata to be forwarded to the implementation
                // via delegatecall after setting the implementation slot.
                upgradeData
            )
        );
        require(success, &quot;Upgrade failed.&quot;);
    }
}
```

### Minimal ERC-1967 UUPS proxy implementation

#### Minimal ERC-1967 UUPS proxy implementation (basic variant)

```solidity
pragma solidity ^0.8.0;

library ERC1967MinimalUUPSProxyLib {
    function initCode(address implementation, bytes memory args)
        internal
        pure
        returns (bytes memory)
    {
        uint256 n = 0x003d + args.length;
        require(n &lt;= 0xffff, &quot;Immutable args too long.&quot;);
        return abi.encodePacked(
            bytes1(0x61),
            uint16(n),
            bytes7(0x3d8160233d3973),
            implementation,
            bytes2(0x6009),
            bytes32(0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076),
            bytes32(0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3),
            args
        );
    }

    function deploy(address implementation, bytes memory args)
        internal
        returns (address instance)
    {
        bytes memory m = initCode(implementation, args);
        assembly {
            instance := create(0, add(m, 0x20), mload(m))
        }
        require(instance != address(0), &quot;Deployment failed.&quot;);
    }
}
```

#### Minimal ERC-1967 UUPS proxy implementation (I-variant)

```solidity
pragma solidity ^0.8.0;

library ERC1967IMinimalUUPSProxyLib {
    function initCode(address implementation, bytes memory args)
        internal
        pure
        returns (bytes memory)
    {
        uint256 n = 0x0052 + args.length;
        require(n &lt;= 0xffff, &quot;Immutable args too long.&quot;);
        return abi.encodePacked(
            bytes1(0x61),
            uint16(n),
            bytes7(0x3d8160233d3973),
            implementation,
            bytes23(0x600f5155f3365814604357363d3d373d3d363d7f360894),
            bytes32(0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4),
            bytes32(0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3),
            args
        );
    }

    function deploy(address implementation, bytes memory args)
        internal
        returns (address instance)
    {
        bytes memory m = initCode(implementation, args);
        assembly {
            instance := create(0, add(m, 0x20), mload(m))
        }
        require(instance != address(0), &quot;Deployment failed.&quot;);
    }
}
```

### Minimal ERC-1967 beacon proxy implementation

#### Minimal ERC-1967 beacon proxy implementation (basic variant)

```solidity
pragma solidity ^0.8.0;

library ERC1967MinimalBeaconProxyLib {
    function initCode(address beacon, bytes memory args) internal pure returns (bytes memory) {
        uint256 n = 0x0052 + args.length;
        require(n &lt;= 0xffff, &quot;Immutable args too long.&quot;);
        return abi.encodePacked(
            bytes1(0x61),
            uint16(n),
            bytes7(0x3d8160233d3973),
            beacon,
            bytes23(0x60195155f3363d3d373d3d363d602036600436635c60da),
            bytes32(0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c),
            bytes32(0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3),
            args
        );
    }

    function deploy(address beacon, bytes memory args) internal returns (address instance) {
        bytes memory m = initCode(beacon, args);
        assembly {
            instance := create(0, add(m, 0x20), mload(m))
        }
        require(instance != address(0), &quot;Deployment failed.&quot;);
    }
}
```

#### Minimal ERC-1967 beacon proxy implementation (I-variant)

```solidity
pragma solidity ^0.8.0;

library ERC1967IMinimalBeaconProxyLib {
    function initCode(address beacon, bytes memory args) internal pure returns (bytes memory) {
        uint256 n = 0x0057 + args.length;
        require(n &lt;= 0xffff, &quot;Immutable args too long.&quot;);
        return abi.encodePacked(
            bytes1(0x61),
            uint16(n),
            bytes7(0x3d8160233d3973),
            beacon,
            bytes28(0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36),
            bytes32(0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513),
            bytes32(0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3),
            args
        );
    }

    function deploy(address beacon, bytes memory args) internal returns (address instance) {
        bytes memory m = initCode(beacon, args);
        assembly {
            instance := create(0, add(m, 0x20), mload(m))
        }
        require(instance != address(0), &quot;Deployment failed.&quot;);
    }
}
```

## Security Considerations

### Transparent upgradeable proxy factory security considerations

To ensure security, the transparent upgradeable proxy factory must implement proper access control to allow proxies to be upgraded by only authorized accounts.

### Calldata length collision for I-variants

The I-variants reserve all calldata of length 1 to denote a request to return the implementation. This may pose compatibility issues if the underlying implementation actually uses 1-byte calldata for special purposes.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 19 Aug 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7760</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7760</guid>
      </item>
    
      <item>
        <title>EXTCODETYPE instruction</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7761-is-contract-instruction/20936</comments>
        
        <description>## Abstract

Allow EOF contracts to discriminate between EOAs (Externally Owned Accounts) and contract accounts by introducing an `EXTCODETYPE` instruction.

## Motivation

EOFv1 as scoped in [EIP-7692] removes code introspection capabilities from the EVM, including the `EXTCODESIZE` instruction (in [EIP-3540]). This makes it hard for [ERC-721] and [ERC-1155] standard contracts to be implemented, as they rely on discovering whether a token&apos;s `safeTransfer` call target was an EOA or a contract account:

- `safeTransfers` to EOAs succeed
- `safeTransfers` to contract accounts call an `onERC721Received` (`onERC1155Received`) on them and expect to get a special magic return value, otherwise the transfer reverts (on the assumption that such a recipient may not be able to interact with the token)

Application and library developers are also concerned about dynamic proxies written in EOF accidentally pointing to legacy accounts which cannot safely be called with `EXTDELEGATECALL`. They would like a way to differentiate between EOF and legacy contracts.

`EXTCODETYPE` is aimed to fill this gap and bring back the possibility to easily implement ERC-721 and ERC-1155 standard contracts in EOF as well as preserve EOF proxy contract safety.



## Specification

### Parameters

| Constant                  | Value                                                              |
|---------------------------|--------------------------------------------------------------------|
| `FORK_BLKNUM`             | tbd                                                                |
| `GAS_COLD_ACCOUNT_ACCESS` | Defined as `2600` in the [Ethereum Execution Layer Spec Constants] |
| `GAS_WARM_ACCESS`         | Defined as `100` in the [Ethereum Execution Layer Spec Constants]  |
| `TYPE_NONE`               | 0                                                                  |
| `TYPE_LEGACY_CONTRACT`    | 1                                                                  |
| `TYPE_EOF_CONTRACT`       | 2                                                                  |

We introduce a new EOFv1 instruction on the block number `FORK_BLKNUM`: `EXTCODETYPE` (`0xe9`)

EOF code which contains this instruction before `FORK_BLKNUM` is considered invalid. Beginning with block `FORK_BLKNUM` `0xe9` is added to the set of valid EOFv1 instructions.

### Execution Semantics
    
#### `EXTCODETYPE`

- deduct `GAS_WARM_ACCESS` gas
- pop 1 argument `target_address` from the stack
- if `target_address` has any of the high 12 bytes set to a non-zero value (i.e. it does not contain a 20-byte address), then halt with an exceptional failure
  - Notice: Future expansion of the EVM address space may remove or reduce the number of bytes in this check.
- deduct `GAS_COLD_ACCOUNT_ACCESS - GAS_WARM_ACCESS` if `target_address` is not in `accessed_addresses` and add `target_address` to `accessed_addresses`
- Load the code from `target_address` and refer to it as `loaded_code` 
- if `loaded_code` is empty (does not exist or has zero length), push `TYPE_NONE` onto the stack and stop processing the operation
- If `loaded_code` indicates a delegation designator (for example, `0xef0100` as defined in [EIP-7702]), 
  - replace `loaded_code` with the delegated code.
  - deduct gas in accordance with the delegation designation rules
- If `loaded_code` indicates an EOFv1 packaged contract (starts with the bytes `0xef0001`) push `TYPE_EOF_CONTRACT` onto the stack and stop processing the operation
- Otherwise, push `TYPE_LEGACY_CONTRACT` onto the stack and stop processing the operation

Note: if there is not enough gas to deduct for delegation designation the whole message frame will halt, making updating the `accessed_addresses` irrelevant.

Note: If `target_address` or the delegation designator points to an account with a contract mid-creation then the code is empty and returns `0` (`TYPE_NONE`). This is aligned with similar behavior of instructions like `EXTCODESIZE`.

## Rationale

### Alternative solutions

There have been other solutions proposed to alleviate the problems related to lack of code introspection required for ERC-721 and ERC-1155 standards:

1. Extra status code for `EXT*CALL` instruction - allowing to discriminate a result coming from calling an EOA
2. Extra argument for `EXT*CALL` (a &quot;fail if EOA&quot; flag)
3. Two return values from `EXT*CALL` (status code + whether it was EOA)
4. `EXT*CALL` setting a new `callstatus` register (+ a new `CALLSTATUS` instruction)
5. Re-enable `EXTCODESIZE` in EOF, keeping its behavior same as in legacy

`EXTCODETYPE` has been chosen as the most elegant and minimal solution satisfying the requirements at hand and still able to be introduced in EOFv1.

### Reuse the `0x3b` (`EXTCODESIZE`) opcode for `EXTCODETYPE`

A new opcode is preferred by a general policy to not reuse opcodes. Also `EXTCODETYPE` can be rolled out in legacy EVM if desired.

### Keep code introspection banned

Removing code introspection is one of the tenets of EOF and `EXTCODETYPE` would be an exception from the principle. Without `EXTCODETYPE`, ERC-721 and ERC-1155 standard implementations have to resort to either:

1. Leveraging a &quot;booster contract&quot; which would be legacy and would call `EXTCODESIZE` for them. This has been deemed inelegant and inconvenient from the point of view of library implementers, requiring them to hard code an address of such a contract (with the usual address-related problems arising on different EVM chains)
2. Continuing to use legacy EVM themselves. This is suboptimal, since EVM compilers are likely to at some point deprecate legacy EVM as compilation target
3. Updating the standards to not rely on code introspection patterns in `safeTransfer` safeguards. This can be accomplished for example by leveraging [ERC-165], leaving out only contracts which do not implement ERC-165, and at the same time have non-throwing fallback functions, as indistinguishable from EOAs. This is not easy to achieve since ERC-721 and ERC-1155 are Final and adopted in practice.

### &quot;Endgame Account Abstraction&quot; issues

`EXTCODETYPE` (and earlier `EXTCODESIZE` available in legacy EVM) are claimed to slow down AA adoption, because they encourage patterns which discriminate between smart contract and EOA accounts, e.g. not allowing the former to interact. However, there are counterarguments that it is up to other factors which slow down AA adoption (assumption that accounts can produce ECDSA signatures, and the lack of adoption of smart contract signatures).

### Including safeguarding against proxy bricking
    
In parallel to the ERC-721 / ERC-1155 problem, another potential risk has been brought to attention. Since EOFv1 prohibits `EXTDELEGATECALL` targeting legacy contracts, there exists a scenario where an EOF proxy contract accidentally upgrades its implementation to a legacy EVM one. Since reverting this or upgrading again (using current proxy standards) requires the implementation contract to be called, it would effectively render the contract unusable.
    
For this reason it was decided to have a generalized `EXTCODETYPE` instruction instead of a `HASCODE` instruction. This provides the means to safeguard against such a scenario that a simpler instruction could not.

### Relation to [EIP-7702] &quot;Set EOA account code&quot;

After [EIP-7702] is activated, the discrimination between EOAs and contract accounts using `EXTCODESIZE` (or `EXTCODETYPE`) has an edge case: Whenever an EOA sets its code to a contract account which does not respond as expected to an `onERC721Received` (`onERC1155Received`) callback, transfers to it will revert, despite the recipient being able to interact with the token. This has been deemed unlikely to be a problem, as for the intended real-world uses of EIP-7702, those callbacks will be implemented by designator codes.

Because of the requirement that EOF proxy contracts be able to determine if the new target is safe we cannot return a value for indicating that the account itself is delegated without also providing the delegated address. Instead, we return  the code for the account that has the delegated code, applying the delegation. This is because the executable code is what matters for proxy updates.

This differs from `EXTCODECOPY` and `EXTCODEHASH` behavior which do return a hash and short code indicating the proxy. The behavior of `EXTCODETYPE` is closer to a &quot;code executing operation&quot; in purpose as it is meant to describe the execution behavior of the account.

## Backwards Compatibility

`EXTCODETYPE` at `0xe9` can be introduced in a backwards compatible manner into EOFv1 (no bump to version), because `0xe9` has been rejected by EOF validation before `FORK_BLKNUM` and there are no EOF contracts on-chain with a `0xe9` which would have their behavior altered.

## Security Considerations

Needs discussion &lt;!-- TODO --&gt;

## Copyright

Copyright and related rights waived via [CC0]

[CC0]: /EIPs/LICENSE

[ERC-165]: /EIPs/EIPS/eip-165

[ERC-721]: /EIPs/EIPS/eip-721

[ERC-1155]: /EIPs/EIPS/eip-1155

[EIP-3540]: /EIPs/EIPS/eip-3540

[EIP-7702]: /EIPs/EIPS/eip-7702

[EIP-7692]: /EIPs/EIPS/eip-7692
[Ethereum Execution Layer Spec Constants] :https://github.com/ethereum/execution-specs/blob/1adcc1bfe774798bcacc685aebc17bd9935078c3/src/ethereum/cancun/vm/gas.py#L65-L66
</description>
        <pubDate>Sun, 01 Sep 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7761</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7761</guid>
      </item>
    
      <item>
        <title>Increase MIN_BASE_FEE_PER_BLOB_GAS</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7762-increase-min-base-fee-per-blob-gas/20949</comments>
        
        <description>## Abstract

This EIP proposes an increase to the MIN_BASE_FEE_PER_BLOB_GAS to speed up price discovery on blob space. It also resets the excess blob gas to 0, to avoid a blob base fee spike.

## Motivation

When scoping 4844, the thinking was that blobs would only enter price discovery once, relatively quickly after the blob rollout; however, this has not been the case. In fact, blobs have entered price discovery several times, and the frequency of price discovery events is likely to increase in the short term as we approach saturation of capacity. Moreover, the roadmap calls for further increases in blob capacity in subsequent hardforks, which may lead to price discovery events happening around those changes in the future. 

Increasing the MIN_BASE_FEE_PER_BLOB_GAS will speed up price discovery on blob space.

## Specification

### `MIN_BASE_FEE_PER_BLOB_GAS` Increase

The main specification change introduced by this EIP is setting MIN_BASE_FEE_PER_BLOB_GAS to 2**25:

```diff
+ MIN_BASE_FEE_PER_BLOB_GAS  =  2**25
- MIN_BASE_FEE_PER_BLOB_GAS = 1
```

### `excess_blob_gas` Reset

To avoid a blob base fee spike, the `calc_excess_blob_gas` is modified to reset `excess_blob_gas` to 0 at the fork. To detect the fork height, the block timestamp needs to be passed into `calc_excess_blob_gas`.

```python
def calc_excess_blob_gas(parent: Header, block_timestamp: int) -&gt; int:
    # at the fork, set excess_blob_gas to 0
    if parent.timestamp &lt; FORK_TIMESTAMP and block_timestamp &gt;= FORK_TIMESTAMP:
        return 0
    
    # otherwise, calculate normally
    ...
```

`validate_block` needs to be updated to pass the block timestamp into `calc_excess_blob_gas`:

```python
def validate_block(block: Block) -&gt; None:
    ...

    # add timestamp parameter
    assert block.header.excess_blob_gas == calc_excess_blob_gas(block.parent.header, block.header.timestamp)

    ...
```

## Rationale

The current MIN_BASE_FEE_PER_BLOB_GAS is 1 wei. This is many orders of magnitude lower than the prevailing price of blobs when blobs enter price discovery. Whenever demand for blobs exceeds supply, blobs enter price discovery, but traversing the 8 orders of magnitude between 1 wei and the point where elasticity of demand starts to decrease takes a long time.

The blob base fee can at most double every $\log_{1.125}(10) = 5.885$ blocks when blocks use all available blob space. When blobs enter price discovery, they must climb many factors of 2 to reach the prevailing price.

To set the parameter appropriately, one approach is to look at the cost of simple transfers when base fees are low. The cost of a simple transfer when the base fee is 1 GWEI  is ~5 cents USD at today&apos;s prices (2,445.77$ ETH/USDC). We can try to peg the minimum price of a blob to that. Today, to reach this price, it requires an excess blob gas of `63070646`. When you calculate how long this would take to reach from 0 excess blob gas, you get:

```
63070646/(3 * 2**17) = 160.396947225
```

The closest power of 2 to the corresponding reserve price would be `MIN_BASE_FEE_PER_BLOB_GAS = 2**27`. Out of an abundance of caution, we will go with `MIN_BASE_FEE_PER_BLOB_GAS = 2**25` to ensure that even if the price of ETH rises significantly, the reserve price will not be set too high. This value corresponds to a minimum blob price of ~1 cent at today&apos;s prices (2,445.77$ ETH/USDC). Further, decreasing the `MIN_BASE_FEE_PER_BLOB_GAS` beyond `2**25` would slow down price discovery without a significant decrease in the price of blobs when the network is unsaturated. 

Below you will find a plot provided by @dataalways showing the fraction of type 3 transaction fees that are paid in blob base fees for different values of `MIN_BASE_FEE_PER_BLOB_GAS`. Note that even after the proposed change, for historical values of l1 gas, the price of blobs would have been dominated by the price of the L1 gas.  

![Base Fee 1](/EIPs/assets/eip-7762/base_fee_1.png)


![Base Fee 2^25](/EIPs/assets/eip-7762/base_fee_225.png)


---


## Backwards Compatibility

This EIP is not backwards compatible and requires a coordinated upgrade across all clients at a specific block number.

## Security Considerations

Rollups that use blobs as a data availability layer will need to update their posting strategies. 

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 31 Aug 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7762</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7762</guid>
      </item>
    
      <item>
        <title>Privileged Non-Fungible Tokens Tied To RWA</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc7765-privileged-non-fungible-tokens-tied-to-rwa/21048</comments>
        
        <description>## Abstract

This EIP defines an interface to carry a real world asset with some privileges that can be exercised by the holder of the corresponding NFT. The EIP standardizes the interface for non-fungible tokens representing real world assets with privileges to be exercised, such as products sold onchain which can be redeemed in the real world.

And the privileges we describe here specifically refer to the rights and interests bound to the RWA NFT that can be executed by the holder in the real world.

## Motivation

NFTs bound to real-world assets sometimes need to carry certain privileges that can be exercised by the holder. Users can initiate transactions onchain to specify the exercise of a certain privilege, thereby achieving real-world privileges that directly map the onchain privilege through subsequent operations. For example, if a certain product such as a pair of shoes is sold onchain in the representation of NFT, the NFT holder can exercise the privilege of exchanging physical shoes offchain, to achieve the purpose of interoperability between the blockchain and the real world.

Having a standard interface enables interoperability for services, clients, UI, and inter-contract functionalities on top of this use-case.

## Specification

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

This standard inherits the [ERC-721](/EIPs/EIPS/eip-721) NFT token standard for all transfer and approval logic. All transfer and approval functions are inherited from this token standard without changes. Additionally, this standard also inherits the ERC-721 Metadata standards for name, symbol, and metadata URI lookup.

Any compliant contract following this EIP **MUST** implement the following interface:

```
pragma solidity &gt;=0.7.0 &lt;0.9.0;

/// @title ERC-7765 Privileged Non-Fungible Tokens Tied To Real World Assets
/// @dev See https://eips.ethereum.org/EIPS/eip-7765
interface IERC7765 /* is IERC721, IERC165 */ {

    /// @notice This event emitted when a specific privilege of a token is successfully exercised.
    /// @param _operator  the address who exercised the privilege.
    /// @param _to  the address to benefit from the privilege.
    /// @param _tokenId  the NFT tokenID.
    /// @param _privilegeId  the ID of the privileges.
    event PrivilegeExercised(
        address indexed _operator,
        address indexed _to,
        uint256 indexed _tokenId,
        uint256 _privilegeId
    );

    /// @notice This function exercise a specific privilege of a token.
    /// @dev Throws if `_privilegeId` is not a valid privilegeId.
    /// @param _to  the address to benefit from the privilege.
    /// @param _tokenId  the NFT tokenID.
    /// @param _privilegeId  the ID of the privileges.
    /// @param _data  extra data passed in for extra message or future extension.
    function exercisePrivilege(
        address _to,
        uint256 _tokenId,
        uint256 _privilegeId,
        bytes calldata _data
    ) external;

    /// @notice This function is to check whether a specific privilege of a token can be exercised.
    /// @dev Throws if `_privilegeId` is not a valid privilegeId.
    /// @param _to  the address to benefit from the privilege.
    /// @param _tokenId  the NFT tokenID.
    /// @param _privilegeId  the ID of the privileges.
    function isExercisable(
        address _to,
        uint256 _tokenId,
        uint256 _privilegeId
    ) external view returns (bool _exercisable);

    /// @notice This function is to check whether a specific privilege of a token has been exercised.
    /// @dev Throws if `_privilegeId` is not a valid privilegeId.
    /// @param _to  the address to benefit from the privilege.
    /// @param _tokenId  the NFT tokenID.
    /// @param _privilegeId  the ID of the privileges.
    function isExercised(
        address _to,
        uint256 _tokenId,
        uint256 _privilegeId
    ) external view returns (bool _exercised);

    /// @notice This function is to list all privilegeIds of a token.
    /// @param _tokenId  the NFT tokenID.
    function getPrivilegeIds(
        uint256 _tokenId
    ) external view returns (uint256[] memory privilegeIds);

}
```

The function `exercisePrivilege` performs the exercise action to a specific privilege of a token. If succeeds, it is expected to emit a `PrivilegeExercised` event.

The function `getPrivilegeIds` provides a way to manage the binding relationship between NFTs and privilegeIds.

The **metadata extension** is OPTIONAL for [EIP-7765](/EIPs/EIPS/eip-7765) smart contracts. This allows your smart contract to be interrogated for its details about the privileges which your NFTs carry.

```
pragma solidity &gt;=0.7.0 &lt;0.9.0;

/// @title ERC-7765 Privileged Non-Fungible Tokens Tied To Real World Assets, optional metadata extension
/// @dev See https://eips.ethereum.org/EIPS/eip-7765
interface IERC7765Metadata /* is IERC7765 */ {

    /// @notice A distinct Uniform Resource Identifier (URI) for a given privilegeId.
    /// @dev Throws if `_privilegeId` is not a valid privilegeId. URIs are defined in RFC
    ///  3986. The URI may point to a JSON file that conforms to the &quot;ERC-7765
    ///  Metadata JSON Schema&quot;.
    function privilegeURI(uint256 _privilegeId) external view returns (string memory);

}
```

This is the “EIP-7765 Metadata JSON Schema” referenced above.

```
{
    &quot;title&quot;: &quot;Privilege Metadata&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;properties&quot;: {
        &quot;name&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Identifies the specific privilege.&quot;
        },
        &quot;description&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;Describes the specific privilege.&quot;
        },
        &quot;resource&quot;: {
            &quot;type&quot;: &quot;string&quot;,
            &quot;description&quot;: &quot;A URI pointing to a resource representing the specific privilege.&quot;
        }
    }
}
```

`IERC7765Metadata` provides specifications for obtaining metadata information of privileges. A contract that implements `IERC7765Metadata` **SHALL** also implement `IERC7765`.

## Rationale

1.  With the `PrivilegeExercised` event emitted onchain, we can determine that the user has confirmed the exercise of this privilege, so as to implement the privilege in the real world.

2. We choose to include an address `_to` for functions `exercisePrivilege`, `isExercisable` and `isExercised` so that a specific privilege of an NFT MAY be exercised for someone who will benefit from it other than the NFT holder nor the transaction initiator. And This EIP doesn&apos;t assume who has the power to perform this action, it&apos;s totally decided by the developers who are using this standard.

3. We choose to include an extra `_data` field to function `exercisePrivilege` for extra message or future extension. For example, developers can use `_data` to exercise a privilege that takes effect directly onchain such as direct distribution of cryptocurrency assets.

4. The boolean view functions of `isExercisable` and `isExercised` can be used to check whether a specific privilege of an NFT can be exercisable or has been exercised to the `_to` address.

## Backwards Compatibility

This standard is an extension of ERC-721. It is fully compatible with both of the commonly used optional extensions (`IERC721Metadata` and `IERC721Enumerable`) mentioned in the ERC-721 standard.

## Reference Implementation

The reference implementation of Privileged NFTs can be found [Here](/EIPs/assets/eip-7765/contracts/ERC7765Example.sol).

## Security Considerations

Compliant contracts should pay attention to the storage to the states of the privileges. The contract should properly handle the state transition of each privilege of each NFT, clearly showing that each privilege is exercisable or has been exercised.

Compliant contracts should also carefully define access control, particularly whether any EOA or contract account may or may not call `exercisePrivilege` function in any use case. Security audits and tests should be used to verify that the access control to the `exercisePrivilege` function behaves as expected.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 20 Aug 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7765</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7765</guid>
      </item>
    
      <item>
        <title>Signature Aggregation for ERC-4337</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7766-signature-aggregation-for-account-abstraction/21123</comments>
        
        <description>## Abstract

[ERC-4337](./eip-4337) defined a way to achieve Account Abstraction on Ethereum using an alternative `UserOperation` mempool.

However, one big limitation remains:
each transaction must carry its own `signature` or other form of validation input in order to be included.

We propose an extension to the ERC-4337 that introduces a new entity, aggregator, that is called during validation, to validate multiple user operations at once.

This addition will enable `UserOperations` to support sharing validation inputs, saving gas and guaranteeing atomicity of the bundle.

## Motivation

Using validation schemes that allow signature aggregation enables significant optimisations and savings on
gas for execution and transaction data cost. This is especially relevant in the context of rollups that publish data on
the Ethereum mainnet.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119 and RFC 8174.
### Aggregator - a new ERC-4337 `UserOperation` entity contract

* **Aggregator** - a helper contract trusted by accounts to validate an aggregated signature.
  Bundlers/Clients whitelist the supported aggregators.

### Using Signature Aggregator

A signature aggregator exposes the following interface:

```solidity
interface IAggregator {

  function validateUserOpSignature(PackedUserOperation calldata userOp)
  external view returns (bytes memory sigForUserOp);

  function aggregateSignatures(PackedUserOperation[] calldata userOps) external view returns (bytes memory aggregatesSignature);

  function validateSignatures(PackedUserOperation[] calldata userOps, bytes calldata signature) view external;
}
```

* An account signifies it uses signature aggregation by returning its address from `validateUserOp`.
* During `simulateValidation`, this aggregator is returned to the bundler as part of the `aggregatorInfo` field in the `ValidationResult` struct.
* All aggregators MUST be staked.
* The bundler should first verify the aggregator is not throttled or banned according to [ERC-7562](/EIPs/EIPS/eip-7562) rules.
* To accept the `UserOperation`, the bundler must call `validateUserOpSignature()` to validate the `UserOperation` signature.
  This method returns an &quot;alternate signature&quot; that should be used during bundling.\
  An &quot;alternative signature&quot; is normally an empty byte array but can also contain some data for the `acccount`.
* The bundler MUST call `validateUserOp` a second time on the account with the `UserOperation` using the
  returned &quot;alternative signature&quot;, and make sure it returns the same value.
* Implementations of an `aggregateSignatures()` function must aggregate all UserOp signatures into a single value.
* Note that the above methods are helper methods for the bundler.
  The bundler MAY use a native library to perform the same validation and aggregation logic.
* Implementations of a `validateSignatures()` function MUST verify the aggregated signature&apos;s validity
  for all `UserOperations` in the array, and revert otherwise.
  This method is called on-chain by `handleAggregatedOps()`

```solidity
struct AggregatorStakeInfo {
    address aggregator;
    StakeInfo stakeInfo;
}
```
### Bundling changes

In addition to the steps described in ERC-4337, during bundling the bundler should:

* Sort UserOps by aggregator, to create the lists of UserOps-per-aggregator.
* For each aggregator, call `aggregateSignatures()` to create aggregated signature, and update the UserOps.

### New &quot;entry point&quot; function in the ERC-4337 `EntryPoint` contract

We define the following addition to the core interface of the `EntryPoint` contract:

```solidity
function handleAggregatedOps(
    UserOpsPerAggregator[] calldata opsPerAggregator,
    address payable beneficiary
);

struct UserOpsPerAggregator {
    PackedUserOperation[] userOps;
    IAggregator aggregator;
    bytes signature;
}
```

An account that works with aggregated signature should return its signature aggregator address
in the `authorizer` return value of the `validateUserOp` function.
It MAY ignore the signature field.

* `handleAggregatedOps` can handle a batch that contains userOps of multiple aggregators (and also requests without any aggregator)
* `handleAggregatedOps` performs the same logic as `handleOps`, but it must transfer the correct aggregator to each
  userOp, and also must call `validateSignatures` on each aggregator before doing all the per-account validation.

* **code: -32506** - transaction rejected because wallet specified unsupported signature aggregator
    * The `data` field SHOULD contain an `aggregator` value, as returned by the account&apos;s validateUserOp()

## Rationale

### Account returning the &quot;alternative signature&quot;

When using an `aggregator` contract, the accounts delegate their ability to authenticate `UserOperations`.
The entire contents of the 

In order to allow the validation function of the account to perform other checks, the `validateUserOpSignature`
function generates a byte array that will replace the `UserOperation` signature when executed on-chain.

## Backwards Compatibility

As ERC-4337 was created with signature aggregation on the roadmap, no modifications are needed to the
deployed EntryPoint smart contracts.

This proposal introduces new features without affecting the existing ones, and does not break backwards compatibility.

## Security Considerations

### Malicious aggregators

The `aggregator` contracts are among te most trusted contracts in the entire ecosystem.
They can authorize transactions on behalf of accounts, and they can invalidate large numbers of transactions with
a simple storage change.

Both account developers and block builders should be extremely careful with the selection of `aggregator` contracts
that they are willing to support.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 01 Sep 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7766</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7766</guid>
      </item>
    
      <item>
        <title>No-Ether transactions with free-for-all tips</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7768-no-ether-transactions-with-free-for-all-tips/21108</comments>
        
        <description>## Abstract

A technique is introduced where an externally-owned account having no Ether can send transactions and pay tips using a new &quot;free-for-all&quot; bucket and using their own `origin.tx`. This requires no client changes and is compatible with existing ecosystem parts.

## Motivation

There is much interest in third-party-pay transactions on Ethereum and competing networks.

Other proposals require changes to the Ethereum client, that transactions be sent to the network (i.e. `tx.origin`) using a separate account and/or other additional things.

In contrast, this proposal introduces and standardizes a solution to this problem that works only with existing client and technology, and which preserves the `tx.origin` of the originator of a transaction.

## Specification

### End user process

1. An end user who controls an externally-owned account, say Alice, will prepare transaction(s) she would like to execute and she signs this (series of) transactions.
2. If Alice will like to provide consideration for executing these transactions, she will ensure that a well-known address on the network, &quot;the free-for-all bucket&quot; will control tokens (such as 20, 721, 1155 tokens) at the end of her series of transactions.
3. Alice orders her transaction nonces carefully considering that what will eventually be executed may be:
   1. None of them;
   2. Only the first;
   3. The first then the second;
   4. The first, then the second, ... then the Nth transaction, which is not the last in her series of transactions; or
   5. All her transactions, in order.
4. Alice sends this series of transactions to a service that communicates with block proposers.
   1. Currently mempools in baseline clients would not propagate such transactions.

For example, if consideration is sent to the free-for-all address, this would typically be the last in her series of transactions.

### Block preparer process

1. Sign a transaction (from any origin) to send Ether to Alice representing the current gas price times the current block size.
2. (Optional) Prepare and sign a transaction to the free-for-all account, to preload any necessary responses.
3. Start an execution context and include this send-Ether transaction and all of Alice&apos;s transactions.
4. In the execution context, identify tokens (e.g. 20, 721, 1155) sent to the free-for-all contract address or other valuable consideration accrued to the free-for-all account.
5. Sign a transaction to (from any origin) to take security of the consideration from the free-for-all account and include this transaction in the execution context.
6. Evaluate the total gas spent.
7. Rollback the execution context. And repeat steps 1 through 4 with these changes:
   1. Step 1: use the actual required gas amount (in Ether).
   2. Step 4: abort if the consideration received in this second iteration is not the expected amount from the first iteration.
8. Use some local business logic to compare the Ether spent in step 1 (second iteration) versus the consideration received in step 4 and classify the result as favorable or not.
9. If the result is favorable, commit this execution context to the mainline. Or if the result is not favorable, rollback this execution context.
   1. The result of this decision may feed into a reputation tracking system to avoid evaluating future unfruitful transaction(s).
10. Continue execution, and publish the block.

### Free-for-all bucket

This approach requires that the end user must be able to send consideration the block proposer without knowing who they are, and the block proposer must be able to realize this consideration.

This EIP proposes to use a well-known contract account deployment for this purpose. And here is the required interface:

```solidity
interface FreeForAll {
  // Performs a call
  function execute(address recipient, memory bytes, uint256 gasLimit, uint256 value);

  // Prepare return values for the next N times this contract is called only in this block
  // [TODO: spell this out]
  function preloadExecutions(memory bytes[]);
  
  // Return the next return value in this block from preloadExecutions
  fallback() {
  }
}
```

## Rationale

This approach can be useful for end users who do not want to or are not able to add Ether to their account.

This approach allows to use the correct `origin.tx` which may be required for important transactions like ERC-721 `setApprovalForAll`. 

This approach may use more gas than other approaches where the consensus client is changed or where transactions can execute from (`origin.tx`) a different account.

### Alternatives considered

* Update [EIP-1559](./eip-1559) so that transactions with gasPrice = 0 are legal, but only if the commensurate amount of gas will be burnt by the block preparer in that same block.
* Create a new transaction type that encapsulates another signed transaction.
* Create a new opcode to get the coinbase of the next block.

## Backwards Compatibility

... &lt;!-- TODO --&gt;

## Security Considerations

... &lt;!-- TODO --&gt;

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 14 Sep 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7768</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7768</guid>
      </item>
    
      <item>
        <title>JSON-RPC API for ERC-4337</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7769-json-rpc-for-erc-4337-account-abstraction/21126</comments>
        
        <description>## Abstract

Defines new JSON-RPC API methods which enable [ERC-4337](./eip-4337) wallets to communicate with `UserOpeation` mempool
nodes and bundlers, matching the functionality that exists for Ethereum transactions.

Additionally, a set of `debug` JSON-RPC API methods is defined in order to facilitate development, testing and
debugging issues with ERC-4337 implementations.

## Motivation

In ERC-4337, user transactions as defined in Ethereum are replaced with `UserOperation` objects, which contain all the
information needed to perform the operations requested by the users.

However, existing Ethereum JSON-RPC API methods are not suited to working with `UserOperation` objects.
In order to facilitate the operation of the alternative `UserOperation` mempool it is important that all
implementations of the ERC-4337 protocol have a standardized set of APIs that can be used interchangeably.

## Specification

### Definitions

* **bundler**: a node exposing the APIs, in order to submit them to the network.
  A bundler collects one or more UserOperations into a bundle and submits them together to
  the `EntryPoint` in a single `handleOps` call.

### RPC methods (eth namespace)

#### `eth_sendUserOperation`

The `eth_sendUserOperation` method submits a `UserOperation` object to the UserOperation mempool.
The client MUST validate the `UserOperation`, and return a result accordingly.

The result SHOULD be set to the `userOpHash` if and only if the request passed simulation and was accepted
in the client&apos;s UserOperation pool.

If the validation, simulation, or UserOperation pool inclusion fails,
`userOpHash` SHOULD NOT be returned. Rather, the client SHOULD return the failure reason.

##### Parameters:

1. **UserOperation** a full user-operation struct.\
  All fields MUST be set as hex values.\
  Empty `bytes` block (e.g. empty `initCode`) MUST be set to `&quot;0x&quot;`\
2. **factory** and **factoryData**\
  Must provide either both of these parameters, or none.
3. **paymaster**, **paymasterData**, **paymasterValidationGasLimit**, **paymasterPostOpGasLimit**\
  Must provide either all of these parameters, or none.
4. **entryPoint** the `EntryPoint` contract address the request should be sent through.\
  This MUST be one of the entry points returned by the `supportedEntryPoints` RPC call.

##### Return value:

* If the UserOperation is valid, the client MUST return the calculated `userOpHash` for it
* in case of failure, MUST return an `error` result object, with `code` and `message`.\
  The error code and message SHOULD be set as follows:
  * **code: -32602** - invalid `UserOperation` struct/fields
  * **code: -32500** - transaction rejected by `EntryPoint` contract&apos;s `simulateValidation` function
    during wallet creation or validation
    * The `message` field MUST be set to the emitted `FailedOp` event&apos;s &quot;`AAxx`&quot; error message from the `EntryPoint`
  * **code: -32501** - transaction rejected by `paymaster` contract&apos;s `validatePaymasterUserOp` function
    * The `message` field SHOULD be set to the revert message from the `paymaster` contract
    * The `data` field MUST contain a `paymaster` value
  * **code: -32502** - transaction rejected because of [ERC-7562](./eip-7562) opcode validation rule violation
  * **code: -32503** - UserOperation out of time-range:\
    either wallet or paymaster returned a time-range, and it has already expired or will expire soon.
    * The `data` field SHOULD contain the `validUntil` and `validAfter` values
    * The `data` field SHOULD contain a `paymaster` address if this error was triggered by the `paymaster` contract
  * **code: -32504** - transaction rejected because `paymaster` is throttled or banned due to ERC-7562 reputation rules
    * The `data` field SHOULD contain a `paymaster` address
  * **code: -32505** - transaction rejected because `paymaster` contract&apos;s ERC-7562 stake or unstake-delay is too low
    * The `data` field SHOULD contain a `paymaster` address
    * The `data` field SHOULD contain a `minimumStake` and `minimumUnstakeDelay`
  * **code: -32507** - transaction rejected because of wallet signature check failed
  * **code: -32508** - transaction rejected because paymaster balance can&apos;t cover all pending `UserOperations`.

##### Example:

Request:

```js
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;method&quot;: &quot;eth_sendUserOperation&quot;,
  &quot;params&quot;: [
    {
      eip7702Auth, // an EIP-7702 authorization tuple
      sender, // address
      nonce, // uint256
      factory, // address
      factoryData, // bytes
      callData, // bytes
      callGasLimit, // uint256
      verificationGasLimit, // uint256
      preVerificationGas, // uint256
      maxFeePerGas, // uint256
      maxPriorityFeePerGas, // uint256
      paymaster, // address
      paymasterVerificationGasLimit, // uint256
      paymasterPostOpGasLimit, // uint256
      paymasterData, // bytes
      signature // bytes
    },
    entryPoint // address
  ]
}

```

Response:

```
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;result&quot;: &quot;0x123456789012345678901234567890123456789012345678901234567890abcd&quot;
}
```

##### Example failure responses:

```json
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;error&quot;: {
    &quot;message&quot;: &quot;AA21 didn&apos;t pay prefund&quot;,
    &quot;code&quot;: -32500
  }
}
```

```json
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;error&quot;: {
    &quot;message&quot;: &quot;paymaster stake too low&quot;,
    &quot;data&quot;: {
      &quot;paymaster&quot;: &quot;0x123456789012345678901234567890123456790&quot;,
      &quot;minimumStake&quot;: &quot;0xde0b6b3a7640000&quot;,
      &quot;minimumUnstakeDelay&quot;: &quot;0x15180&quot;
    },
    &quot;code&quot;: -32504
  }
}
```

##### Support for [EIP-7702](/EIPs/EIPS/eip-7702) authorizations

On networks with [EIP-7702](./eip-7702) activated, the `UserOperation` object may also contain an `eip7702Auth` tuple.
Notice that according to EIP-7702 an `eip7702Auth` tuple must be provided only to perform a **change** of the authorization address.
Once the necessary `eip7702Auth` tuple was stored on-chain,
users are not required to provide the same `eip7702Auth` tuple for any consequent
`UserOperation`.

Separately, the fields `factory` and `factoryData` have a modified behaviour when using an EIP-7702 authorized `sender`.

The `factory` field SHOULD be set to exactly the `INITCODE_EIP7702_MARKER = 0x7702` flag when using an EIP-7702 authorized `sender`.
Passing his flag instructs the `EntryPoint` contract to verify the `sender` address contains a valid EIP-7702 authorization.

When `INITCODE_EIP7702_MARKER` is specified, the `factoryData` value is passed directly to the `sender` contract,
instead of the `factory` contract.
This is done as a separate call before the `validateUserOp` is called,
meaning the `sender` contract will be called two times during validation.

The `factoryData` value can be left empty. In this case, the call will not be performed.

The purpose of this `factoryData` call is to provide the EIP-7702 `sender` contract an ability to initialize its
storage before accepting the `UserOperation` via the `validateUserOp` function.

#### eth_estimateUserOperationGas

Estimate the gas values for a `UserOperation`.
Given `UserOperation` optionally without gas limits and gas prices, return the needed gas limits.
The signature field is ignored by the wallet, so that the operation will not require the user&apos;s approval.
Still, it might require putting a &quot;stub&quot; `signature` value, e.g. a `signature` byte array of the right length.
If the UserOperation contains an `eip7702Auth` tuple, for the purpose of estimation the signature should be ignored, and the tuple should be evaluated as if it was signed by the `sender`

**Parameters**:
* Same as `eth_sendUserOperation`\
  All gas limits and fees parameters are optional, but are used if specified.\
  `maxFeePerGas` and `maxPriorityFeePerGas` default to zero, so no payment is required by neither account nor paymaster.
* Optionally accepts the `State Override Set` to allow users to modify the state during the gas estimation.\
  This field as well as its behavior is equivalent to the ones defined for `eth_call` RPC method.


**Return Values:**

* **preVerificationGas** gas overhead of this `UserOperation`
* **verificationGasLimit** estimation of gas limit required by the validation of this `UserOperation`
* **paymasterVerificationGasLimit** estimation of gas limit required by the paymaster verification\
  Returned only if the `UserOperation` specifies a `Paymaster` address
* **callGasLimit** estimation of gas limit required by the inner account execution

**Note:** actual `postOpGasLimit` cannot be reliably estimated.\
Paymasters should provide this value to account, and require that specific value on-chain during validation.

##### Error Codes:

Same as `eth_sendUserOperation`
This operation may also return an error if either the inner call to the account contract reverts,
or paymaster&apos;s `postOp` call reverts.

#### eth_getUserOperationByHash

Return a `UserOperation`object based on a `userOpHash` value returned by `eth_sendUserOperation`.

**Parameters**

* **hash** a `userOpHash` value returned by `eth_sendUserOperation`

**Return value**:

* If the `UserOperation` is included in a block:
  * Return a full UserOperation, with the addition of `entryPoint`, `blockNumber`, `blockHash` and `transactionHash`.

* Else if the `UserOperation` is pending in the bundler&apos;s mempool:
  *  MAY return `null`, or a full `UserOperation`, with the addition of the `entryPoint` field and a `null` value for `blockNumber`, `blockHash` and `transactionHash`.

* Else:
  * Return `null`

#### eth_getUserOperationReceipt

Return a `UserOperation` receipt object based on a `userOpHash` value returned by `eth_sendUserOperation`.

**Parameters**

* **hash** a `userOpHash` value returned by `eth_sendUserOperation`

**Return value**:

`null` in case the `UserOperation` is not yet included in a block, or:

* **userOpHash** the request hash
* **entryPoint**
* **sender**
* **nonce**
* **paymaster** the paymaster used for this userOp (or empty)
* **actualGasCost** - the actual amount paid (by account or paymaster) for this `UserOperation`
* **actualGasUsed** - total gas used by this `UserOperation`, including pre-verification, creation, validation and execution
* **success** boolean - whether this execution completed without a revert
* **reason** - in case of reverted `UserOperation`, the returned revert reason byte array
* **logs** - the logs generated by this particular `UserOperation`, not including logs of other `UserOperations` in the same bundle
* **receipt** the `TransactionReceipt` object.
  Note that the returned `TransactionReceipt` is for the entire bundle, not only for this `UserOperation`.

#### eth_supportedEntryPoints

Returns an array of the `EntryPoint` contracts&apos; addresses supported by the client.
The first element of the array `SHOULD` be the `EntryPoint` contract addressed preferred by the client.

```json=
# Request
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;method&quot;: &quot;eth_supportedEntryPoints&quot;,
  &quot;params&quot;: []
}

# Response
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;result&quot;: [
    &quot;0xcd01C8aa8995A59eB7B2627E69b40e0524B5ecf8&quot;,
    &quot;0x7A0A0d159218E6a2f407B99173A2b12A6DDfC2a6&quot;
  ]
}
```

#### eth_chainId

Returns [EIP-155](/EIPs/EIPS/eip-155) Chain ID.

```json=
# Request
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;method&quot;: &quot;eth_chainId&quot;,
  &quot;params&quot;: []
}

# Response
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;result&quot;: &quot;0x1&quot;
}
```

### RPC methods (debug Namespace)

This api must only be available in testing mode and is required by the compatibility test suite.
In production, any `debug_*` rpc calls should be blocked.

#### debug_bundler_clearState

Clears the bundler mempool and reputation data of paymasters/accounts/factories.

```json
# Request
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;method&quot;: &quot;debug_bundler_clearState&quot;,
  &quot;params&quot;: []
}

# Response
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;result&quot;: &quot;ok&quot;
}
```

#### debug_bundler_dumpMempool

Dumps the current `UserOperation` mempool

**Parameters:**

* **EntryPoint** the entrypoint used by `eth_sendUserOperation`

**Returns:**

`array` - Array of `UserOperation` objects currently in the mempool.

```json=
# Request
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;method&quot;: &quot;debug_bundler_dumpMempool&quot;,
  &quot;params&quot;: [&quot;0x1306b01bC3e4AD202612D3843387e94737673F53&quot;]
}

# Response
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;result&quot;: [
    {
        sender, // address
        nonce, // uint256
        factory, // address
        factoryData, // bytes
        callData, // bytes
        callGasLimit, // uint256
        verificationGasLimit, // uint256
        preVerificationGas, // uint256
        maxFeePerGas, // uint256
        maxPriorityFeePerGas, // uint256
        signature // bytes
    }
  ]
}
```

#### debug_bundler_sendBundleNow

Forces the bundler to build and execute a bundle from the mempool as `handleOps()` transaction.

Returns: `transactionHash`

```json
# Request
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;method&quot;: &quot;debug_bundler_sendBundleNow&quot;,
  &quot;params&quot;: []
}

# Response
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;result&quot;: &quot;0xdead9e43632ac70c46b4003434058b18db0ad809617bd29f3448d46ca9085576&quot;
}
```

#### debug_bundler_setBundlingMode

Sets bundling mode.

After setting mode to &quot;manual&quot;, an explicit call to `debug_bundler_sendBundleNow` is required to send a bundle.

##### parameters:

`mode` - &apos;manual&apos; | &apos;auto&apos;

```json=
# Request
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;method&quot;: &quot;debug_bundler_setBundlingMode&quot;,
  &quot;params&quot;: [&quot;manual&quot;]
}

# Response
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;result&quot;: &quot;ok&quot;
}
```

#### debug_bundler_setReputation

Sets the reputation of given addresses.

**Parameters:**

* An array of reputation entries to add/replace, with the fields:

  * `address` - the address to set the reputation for
  * `opsSeen` - number of times a user operations with that entity was seen and added to the mempool
  * `opsIncluded` - number of times user operations that use this entity was included on-chain

* **EntryPoint** the entrypoint used by `eth_sendUserOperation`

```json=
# Request
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;method&quot;: &quot;debug_bundler_setReputation&quot;,
  &quot;params&quot;: [
    [
      {
        &quot;address&quot;: &quot;0x7A0A0d159218E6a2f407B99173A2b12A6DDfC2a6&quot;,
        &quot;opsSeen&quot;: &quot;0x14&quot;,
        &quot;opsIncluded&quot;: &quot;0x0D&quot;
      }
    ],
    &quot;0x1306b01bC3e4AD202612D3843387e94737673F53&quot;
  ]
}

# Response
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;result&quot;: &quot;ok&quot;
}
```


#### debug_bundler_dumpReputation

Returns the reputation data of all observed addresses.
Returns an array of reputation objects, each with the fields described above in `debug_bundler_setReputation`.

**Parameters:**

* **EntryPoint** the entrypoint used by `eth_sendUserOperation`

**Return value:**

An array of reputation entries with the fields:

* `address` - the address to set the reputation for
* `opsSeen` - number of times a user operations with that entity was seen and added to the mempool
* `opsIncluded` - number of times user operation that use this entity was included on-chain
* `status` - (string) The status of the address in the bundler (`&apos;ok&apos;` | `&apos;throttled&apos;` | `&apos;banned&apos;`)

```json=
# Request
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;method&quot;: &quot;debug_bundler_dumpReputation&quot;,
  &quot;params&quot;: [&quot;0x1306b01bC3e4AD202612D3843387e94737673F53&quot;]
}

# Response
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;result&quot;: [
    { &quot;address&quot;: &quot;0x7A0A0d159218E6a2f407B99173A2b12A6DDfC2a6&quot;,
      &quot;opsSeen&quot;: &quot;0x14&quot;,
      &quot;opsIncluded&quot;: &quot;0x13&quot;,
      &quot;status&quot;: &quot;ok&quot;
    }
  ]
}
```

#### debug_bundler_addUserOps

Inject `UserOperation` objects array into the mempool.
Assume the given `UserOperation` objects all pass validation without actually validating them,
and accept them directly into the mempool.

**Parameters:**

* An array of `UserOperation` objects

```json=
# Request
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;method&quot;: &quot;debug_bundler_addUserOps&quot;,
  &quot;params&quot;: [
    [
      { sender: &quot;0xa...&quot;, ... },
      { sender: &quot;0xb...&quot;, ... }
    ]
  ]
}

# Response
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;result&quot;: &quot;ok&quot;
}
```

## Rationale 

* explicit debug functions: bundlers are required to provide a set of debug functions, so that the &quot;bundler specification test suite&quot; can be used to verify its adherance to the spec.

## Backwards Compatibility

This proposal defines a new JSON-RPC API standard that does not pose any backwards compatibility challenges.


## Security Considerations

### Preventing DoS attacks on UserOperation mempool

Operating a public production ERC-4337 node is a computationally intensive task and may be a target of a DoS attack.
This is addressed by the ERC-7562 validation rules, which defines a way for the ERC-4337 node to track participants&apos;
reputation as well as preventing nodes from accepting maliciously crafted `UserOperations`.

It is strictly recommended that all ERC-4337 nodes also implement ERC-7562 validation rules to minimize DoS risks.

### Disabling `debug` API in production servers

The API defined in the `debug` namespace is not intended to ever be publicly available.
Production implementations of ERC-4337 must never make it available by default,
and in fact enabling it should result in a clear warning of the potential dangers of exposing this API.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 23 Aug 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7769</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7769</guid>
      </item>
    
      <item>
        <title>Fractional Reserve Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7770-fractional-reserve-token/21103</comments>
        
        <description>## Abstract
We propose a new token standard for synthetic assets that are only partially redeemable to their underlying asset, but fully backed by other collateral assets.
 
The standard defines an interface to mint fractional reserve assets, and a standard to reflect economic risk related data to the token holders and lenders.

## Motivation
The Cambrian explosion of new L1s and L2s gave rise to bridged assets which are synthetic by nature. Indeed, ETH on Arbitrum L2, or WETH on Binance Smart Chain are not fully fungible with their mainnet counterpart. However, these assets are fully backed by their mainnet counterpart and guaranteed to be redeemable to their mainnet underlying asset, albeit with certain time delay.

Fractional reserve tokens can allow an ecosystem (chains, L2s, and other networks of economic activity) to increase its supply by allowing users to mint the asset not only by bridging it to the ecosystem, but also by borrowing it (typically against a collateral).

As an example, consider a fractional reserve token, namely, frDAI, that represents a synthetic DAI.
Such token will allow users to mint 1 frDAI upon deposit of 1 DAI, or by providing a collateral that worth more than 1 DAI.
Quick redemption of frDAI to DAI is available as long as there is still some DAI balance in the frDAI token, and otherwise, the price of frDAI may temporarily fluctuate until borrowers repay their debt.

Fractional reserve tokens may delegate minting capabilities for multiple risk curators and lending markets. Hence, a uniform standard for fractional reserve minting is needed.
Fractional reserve banking does not come without risks, such as insolvency or a bank run.
This standard does not aim to dictate economic risk management practices, but rather to have a standard on how to reflect the risk to token holders.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119 and RFC 8174.
The standard has the following requirements:
* **MUST** be [ERC-20](/EIPs/EIPS/eip-20) compatible.
### Interface
```
interface IERCXXX is IERC20 {
    // events
    event MintFractionalReserve(address indexed minter, address to, uint256 amount);
    event BurnFractionalReserve(address indexed burner, address from, uint256 amount);
    event SetSegregatedAccount(address account, bool segregated);

    // functions
    // setters
    function fractionalReserveMint(address _to, uint256 _amount) external;
    function fractionalReserveBurn(address _from, uint256 _amount) external;
 
   // getters
    function totalBorrowedSupply() external view returns (uint256);
    function requiredReserveRatio() external view returns (uint256);
    function segregatedAccount(address _account) external view returns (bool);
    function totalSegregatedSupply() external view returns (uint256);
}
```
### Reserve ratio
The reserve ratio reflects the ratio between the token that is available as cash, i.e., available for an immediate redemption (or alternatively, a token that was not minted via a fractional reserve minting), and the total supply of the token. Segregated accounts **MUST** be subtracted from the cash balance.

Formally, the reserve ratio is denoted by $$\frac{totalSupply() - totalBorrowedSupply() - \sum_{a \in \text{Segregated Accounts}} \text{balanceOf}(a)}{totalSupply()}$$.
Additional fractional reserve minting **MUST NOT** occur when the reserve ratio, multiplied by `1e18` is lower than `requiredReserveRatio()`.

### Mint and burn functionality
The `fractionalReserveMint` and `fractionalReserveBurn` functions **SHOULD** be called by permissioned addresses, e.g., risk curators or lending markets. These entities **SHOULD** mint new tokens only to addresses that already locked collateral in a dedicated contract.

The reserve ratio is denoted by $$\frac{totalSupply() - \sum_{a \in \text{Segregated Accounts}} \text{balanceOf}(a)}{totalSupply() + totalBorrowedSupply()}$$.
`fractionalReserveMint` **MUST** revert if the reserve ratio, multiplied by `e18` exceeds `requiredReserveRatio()`.

A successful call to `fractionalReserveMint(_to, _amount)` **MUST** increase the value of `totalSupply()`, `totalBorrowedSupply()`, and the token balance of address `_to`, by `_amount` units.
A call to `fractionalReserveMint` **MUST** emit a `MintFractionalReserve` event.
A call to `fractionalReserveMint` **MUST** revert if after the mint the reserve ratio, multiplied by `1e18` exceeds the value of `requiredReserveRatio()`.

Similarly, a successful call to `fractionalReserveBurn(_from, _amount)` **MUST** decrease the value of `totalSupply()`,`totalBorrowedSupply()`, and the token balance of address `_from` by `_amount` units. 
A call to `fractionalReserveBurn` **MUST** emit a `BurnFractionalReserve` event.
### Segregated accounts
At every point in time, it **MUST** hold that the sum of token balances for segregated addresses equals to `totalSegregatedSupply()`.

### Account balance
The `fractionalReserveMint` **SHOULD** be used in conjunction with a lending operation, where the minted token is borrowed. The lending operation **SHOULD** come with an interest rate, and some of the interest rate proceedings **SHOULD** be distributed to token holders that are not in segregated accounts.
This standard does not dictate how distribution should occur.  

## Rationale
The standard aims to standardise how multiple lending markets and risk providers can interact with a fractional reserve token. The actual lending operation should be done carefully by trusted entities, and it is the token owner&apos;s responsibility to make sure the parties who have fractional reserve minting credentials are reliable.

At the core of the coordination relies the need to understand how much additional supply is available for borrow, and at what interest rate. The additional borrowable supply is deduced from the required reserve ratio, and the total, borrowable and segregated supply.
Lower reserve ratio gives rise to higher capital efficiency, however it increases the **likelihood** of depeg or a run on the bank, where token holders cannot immediately redeem their synthetic token.
Having the reserve ratio as part of the standard allows risk curators to better price the risk, and, e.g., set the interest rate to be monotonically increasing with the current reserve ratio.

The standard does not dictate how the accrued interest rate is distributed. One possible distribution is by making the token a rebased token. An alternative way is to introduce staking, or just airdropping of proceeds.

While a fractional reserve is most useful when it is backed by a known asset, e.g., frDAI and DAI, it can also be used in isolation. In such a case, a token will have a fixed initial supply, however additional supply can be borrowed. In such cases the supply temporarily increases, but the net holdings (`totalSupply() - totalBorrowedSupply()`) remains unchanged.

Increasing the total supply could be a concern if a token is used for DAO votes and/or if dividends are distributed to token holders.
In order to mitigate such concerns, segregated accounts are introduced, with the premise that money in these accounts is not counted towards the reserve, and therefore, additional token supply cannot be minted against them.

## Backwards Compatibility
Fractional reserve tokens should be backwards compatible with [ERC-20](/EIPs/EIPS/eip-20).

## Reference Implementation
```
// The code below is provided only for illustration, DO NOT use it in production
contract FractionalReserveToken is ERC20, Ownable {

    event MintFractionalReserve(address indexed minter, address to, uint256 amount);
    event BurnFractionalReserve(address indexed burner, address from, uint256 amount);
    event SetSegregatedAccount(address account, bool segregated);

    /// @notice token supply in these accounts is not counted towards the reserve, and
    /// therefore, additional token supply cannot be minted against them.
    mapping(address =&gt; bool) public segregatedAccount;

    /// @notice ratio between the token that is available as cash (immediate redemption)
    /// and the total supply of the token.
    uint256 public requiredReserveRatio;

    uint256 public totalBorrowedSupply;

    constructor(
        string memory _name,
        string memory _symbol
    ) ERC20(_name, _symbol) Ownable(msg.sender) {}

    function fractionalReserveMint(address to, uint256 amount) external onlyOwner {
        _mint(to, amount);
        totalBorrowedSupply += amount;
        emit MintFractionalReserve(msg.sender, to, amount);

        uint256 reserveRatio = (totalSupply() - totalBorrowedSupply - segregatedSupply) * 1e18 / totalSupply();
        require(reserveRatio &gt;= requiredReserveRatio, &quot;reserveRatio&quot;);
    }
    function fractionalReserveBurn(address from, uint256 amount) external onlyOwner {
        _burn(from, amount);
        totalBorrowedSupply -= amount;
        emit BurnFractionalReserve(msg.sender, from, amount);
    }

    // ------------------------------------------------------------------------------
    // Code below is not part of the standard
    // ------------------------------------------------------------------------------
    uint256 internal segregatedSupply; // supply of segregated tokens

    function _update(address from, address to, uint256 value) internal override {
        // keep the reserve up to date on transfers
        if (!segregatedAccount[from] &amp;&amp; segregatedAccount[to]) {
            segregatedSupply += value;
        }
        if (segregatedAccount[from] &amp;&amp; !segregatedAccount[to]) {
            segregatedSupply -= value;
        }
        ERC20._update(from, to, value);
    }

    function mint(address account, uint256 value) external onlyOwner {
        _mint(account, value);
    }

    function burn(address account, uint256 value) external onlyOwner {
        _burn(account, value);
    }

    function setSegregatedAccount(address account, bool segregated) external onlyOwner {
        if (segregated) {
            require(!segregatedAccount[account], &quot;segregated&quot;);
            segregatedSupply += balanceOf(account);
        } else {
            require(segregatedAccount[account], &quot;!segregated&quot;);
            segregatedSupply -= balanceOf(account);
        }
        segregatedAccount[account] = segregated;
        emit SetSegregatedAccount(account, segregated);
    }

    function setRequiredReserveRatio(uint256 value) external onlyOwner {
        requiredReserveRatio = value;
    }
}
```
## Security Considerations
Fractional reserve banking comes with many economic risks. This standard does not aim to provide guidelines on how to properly mitigate them.
## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 17 Sep 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7770</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7770</guid>
      </item>
    
      <item>
        <title>Hardfork Meta - Glamsterdam</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7773-glamsterdam-network-upgrade-meta-thread/21195</comments>
        
        <description>## Abstract

This Meta EIP lists the EIPs formally Proposed, Considered, Declined for &amp; Scheduled for Inclusion in the Glamsterdam network upgrade.

## Specification

Definitions for `Scheduled for Inclusion`, `Considered for Inclusion`, `Declined for Inclusion` and `Proposed for Inclusion` can be found in [EIP-7723](/EIPs/EIPS/eip-7723).

### EIPs Scheduled for Inclusion

* [EIP-7732](/EIPs/EIPS/eip-7732): Enshrined Proposer-Builder Separation
* [EIP-7928](/EIPs/EIPS/eip-7928): Block-Level Access Lists

### Considered for Inclusion

* [EIP-2780](/EIPs/EIPS/eip-2780): Reduce intrinsic transaction gas
* [EIP-7688](/EIPs/EIPS/eip-7688): Forward compatible consensus data structures
* [EIP-7708](/EIPs/EIPS/eip-7708): ETH transfers emit a log
* [EIP-7778](/EIPs/EIPS/eip-7778): Block Gas Accounting without Refunds
* [EIP-7843](/EIPs/EIPS/eip-7843): SLOTNUM opcode
* [EIP-7904](/EIPs/EIPS/eip-7904): General Repricing
* [EIP-7954](/EIPs/EIPS/eip-7954): Increase Maxiumum Contract Size
* [EIP-7976](/EIPs/EIPS/eip-7976): Increase Calldata Floor Cost
* [EIP-7981](/EIPs/EIPS/eip-7981): Increase Access List Cost
* [EIP-7997](/EIPs/EIPS/eip-7997): Deterministic Factory Predeploy
* [EIP-8024](/EIPs/EIPS/eip-8024): Backward compatible SWAPN, DUPN, EXCHANGE
* [EIP-8037](/EIPs/EIPS/eip-8037): State Creation Gas Cost Increase
* [EIP-8038](/EIPs/EIPS/eip-8038): State-access gas cost increase
* [EIP-8045](/EIPs/EIPS/eip-8045): Exclude slashed validators from proposing
* [EIP-8061](/EIPs/EIPS/eip-8061): Increase exit and consolidation churn
* [EIP-8080](/EIPs/EIPS/eip-8080): Let exits use the consolidation queue

#### Networking EIPs

* [EIP-7975](/EIPs/EIPS/eip-7975): eth/70 - partial block receipt lists
* [EIP-8070](/EIPs/EIPS/eip-8070): eth/72 - Sparse Blobpool
* [EIP-8136](/EIPs/EIPS/eip-8136): Cell-Level Deltas for Data Column Broadcast
* [EIP-8159](/EIPs/EIPS/eip-8159): eth/71 - Block Access List Exchange

### Declined for Inclusion

* [EIP-2926](/EIPs/EIPS/eip-2926): Chunk-based code merkelization
* [EIP-5920](/EIPs/EIPS/eip-5920): PAY opcode
* [EIP-6404](/EIPs/EIPS/eip-6404): SSZ transactions
* [EIP-6466](/EIPs/EIPS/eip-6466): SSZ receipts
* [EIP-7619](/EIPs/EIPS/eip-7619): Precompile Falcon512 generic verifier
* [EIP-7668](/EIPs/EIPS/eip-7668): Remove bloom filters
* [EIP-7686](/EIPs/EIPS/eip-7686): Linear EVM memory limits
* [EIP-7692](/EIPs/EIPS/eip-7692): EVM Object Format (EOFv1) Meta
* [EIP-7745](/EIPs/EIPS/eip-7745): Trustless log index
* [EIP-7782](/EIPs/EIPS/eip-7782): Reduce Block Latency
* [EIP-7791](/EIPs/EIPS/eip-7791): GAS2ETH opcode
* [EIP-7793](/EIPs/EIPS/eip-7793): Conditional Transactions
* [EIP-7805](/EIPs/EIPS/eip-7805): Fork-choice enforced Inclusion Lists (FOCIL)
* [EIP-7819](/EIPs/EIPS/eip-7819): SETDELEGATE instruction
* [EIP-7872](/EIPs/EIPS/eip-7872): Max blob flag for local builders
* [EIP-7886](/EIPs/EIPS/eip-7886): Delayed execution
* [EIP-7903](/EIPs/EIPS/eip-7903): Remove Initcode Size Limit
* [EIP-7907](/EIPs/EIPS/eip-7907): Meter Contract Code Size And Increase Limit
* [EIP-7919](/EIPs/EIPS/eip-7919): Pureth Meta
* [EIP-7923](/EIPs/EIPS/eip-7923): Linear, Page-Based Memory Costing
* [EIP-7932](/EIPs/EIPS/eip-7932): Secondary Signature Algorithms
* [EIP-7937](/EIPs/EIPS/eip-7937): EVM64 - 64-bit mode EVM opcodes
* [EIP-7942](/EIPs/EIPS/eip-7942): Available Attestation
* [EIP-7949](/EIPs/EIPS/eip-7949): Schema for `genesis.json` files
* [EIP-7971](/EIPs/EIPS/eip-7971): Hard Limits for Transient Storage
* [EIP-7973](/EIPs/EIPS/eip-7973): Warm Account Write Metering
* [EIP-7979](/EIPs/EIPS/eip-7979): Call and Return Opcodes for the EVM
* [EIP-8011](/EIPs/EIPS/eip-8011): Multidimensional Gas Metering
* [EIP-8013](/EIPs/EIPS/eip-8013): Static relative jumps and calls for the EVM
* [EIP-8030](/EIPs/EIPS/eip-8030): P256 transaction support
* [EIP-8032](/EIPs/EIPS/eip-8032): Size-Based Storage Gas Pricing
* [EIP-8051](/EIPs/EIPS/eip-8051): Precompile for ML-DSA signature verification
* [EIP-8053](/EIPs/EIPS/eip-8053): Milli-gas for High-precision Gas Metering
* [EIP-8057](/EIPs/EIPS/eip-8057): Inter-Block Temporal Locality Gas Discounts
* [EIP-8058](/EIPs/EIPS/eip-8058): Contract Bytecode Deduplication Discount
* [EIP-8059](/EIPs/EIPS/eip-8059): Gas Units Rebase for High-precision Metering
* [EIP-8062](/EIPs/EIPS/eip-8062): Add sweep withdrawal fee for 0x01 validators
* [EIP-8068](/EIPs/EIPS/eip-8068): Neutral effective balance design
* [EIP-8071](/EIPs/EIPS/eip-8071): Prevent using consolidations as withdrawals

### Proposed for Inclusion

* [EIP-7610](/EIPs/EIPS/eip-7610): Revert creation in case of non-empty storage

### Activation

| Network Name | Activation Epoch | Activation Timestamp |
| ------------ | ---------------- | -------------------- |
| Sepolia      |                  |                      |
| Holešky      |                  |                      |
| Mainnet      |                  |                      |

**Note**: rows in the table above will be filled as activation times are decided by client teams.

## Rationale

This Meta EIP provides a global view of all changes included in the Glamsterdam network upgrade, as well as links to full specification.

## Security Considerations

None.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 26 Sep 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7773</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7773</guid>
      </item>
    
      <item>
        <title>Cache invalidation in ERC-5219 mode Web3 URL</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7774-cache-invalidation-in-erc-5219-mode-web3-url/21255</comments>
        
        <description>## Abstract

In the context of the [ERC-6860](/EIPs/EIPS/eip-6860) `web3://` standard, this ERC extends the [ERC-6944](/EIPs/EIPS/eip-6944) resolve mode. It introduces mechanisms to address limitations that prevent the use of standard [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching.

## Motivation

Calls to Ethereum RPC providers are costly—both CPU-wise for local nodes and monetarily for paid external RPC providers. Furthermore, external RPC providers are rate-limited, which can quickly cause disruptions when loading `web3://` URLs.

Therefore, it makes sense to implement caching mechanisms to reduce RPC calls when possible. Since `web3://` aims to be as close to HTTP as possible, leveraging standard [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching is the natural choice. In the [ERC-6944](/EIPs/EIPS/eip-6944) resolve mode, smart contracts can already return standard HTTP caching headers like `Cache-Control` and `ETag`.

However, due to the [ERC-6944](/EIPs/EIPS/eip-6944) resolve mode not forwarding request HTTP headers to the smart contract, smart contracts cannot handle `If-None-Match` and `If-Modified-Since` cache validation headers. Consequently, they are limited to using the `Cache-control: max-age=XX` mechanism, which causes each cache validation request to trigger an RPC call, regenerating the full response.

This ERC proposes a solution to bypass this limitation by allowing websites to broadcast cache invalidations via smart contract events.

Additionally, even if smart contracts could read request HTTP headers, using smart contract events is more efficient, as it moves cache invalidation logic outside the contract.

We add this feature to the [ERC-6944](/EIPs/EIPS/eip-6944) resolve mode because it can be added without changes to the interface. Future resolve modes that allow for request HTTP headers may also implement this ERC.

## Specification

This standard introduces the `evm-events` cache directive for the `Cache-Control` header of request responses, as an extension directive as defined in section 5.2.3 of [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111).

When an [ERC-6944](/EIPs/EIPS/eip-6944) resolve mode website wants to use event-based caching for a request, it MUST:

- Include the `evm-events` directive in the `Cache-Control` header of the response.
- Include the `ETag` and/or `Cache-Control` headers in the response, as per traditional [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching.
- Emit a cache invalidation event (as defined below) for the path in the smart contract when the output of the response changes and it deems cache clearing necessary.

A value to the `evm-events` cache directive is optional, and can be used to specify to listen for additional events on other smart contracts, and/or for other paths. The cache directive value syntax in ABNF notation is : 

```
cache-directive-value = [ address-path-absolute *( &quot; &quot; address-path-absolute ) ]
address-path-absolute = [ address ] path-absolute [ &quot;?&quot; query ]
address               = &quot;0x&quot; 20( HEXDIG HEXDIG )
path-absolute         = &lt;path-absolute, see RFC 3986, Section 3.3&gt;
query                 = &lt;query, see RFC 3986, Section 3.4&gt;
```

**Examples**:

- `Cache-control: evm-events` : The cache of the page returning this directive will be cleared when the contract having responded to the request emits a cache clearing event for the path of the page having been served.
- `Cache-control: evm-events=&quot;/path/path2&quot;` : Same behavior than the first example, but additionally the cache of the page returning this directive will be cleared when the contract having responded to the request emits a cache clearing event for path `/path/path2`.
- `Cache-control: evm-events=&quot;0xe4ba0e245436b737468c206ab5c8f4950597ab7f/path/path2&quot;` : Same behavior than the first example, but additionally the cache of the page returning this directive will be cleared when the contract `0xe4ba0e245436b737468c206ab5c8f4950597ab7f` emits a cache clearing event for path `/path/path2`.
- `Cache-control: evm-events=&quot;0xe4ba0e245436b737468c206ab5c8f4950597ab7f&quot;` : Same behavior than the first example, but additionally the cache of the page returning this directive will be cleared when the contract `0xe4ba0e245436b737468c206ab5c8f4950597ab7f` emits a cache clearing event for the path of the page having been served.
- `Cache-control: evm-events=&quot;/path/path2 /path/path3&quot;` : Same behavior than the first example, but additionally the cache of the page returning this directive will be cleared when the contract having responded to the request emits a cache clearing event for path `/path/path2` or `/path/path3`.

### Cache invalidation event

The event is defined as:

```
event ClearPathCache(string[] paths);
```

This event clears the cache for an array of `paths`. Each `path` refers to the `pathQuery` part of the ABNF definition in [ERC-6860](/EIPs/EIPS/eip-6860).

- A `path` MUST NOT end with a `/`, except when the whole path is the root path, which is `/`.
- Two `paths` are considered identical if they have the same [ERC-5219](/EIPs/EIPS/eip-5219) resource entries and their parameter values match, regardless of the order.

**Example**:
- `/test?a=1&amp;b=2` and `/test?b=2&amp;a=1` are considered identical.

#### Wildcard usage

`paths` may contain `*` wildcards, with the following rules:

1. **Wildcards in Resource Entries**:
   - A wildcard (`*`) can be used on its own in an [ERC-5219](/EIPs/EIPS/eip-5219) resource entry.
   - A wildcard CANNOT be combined with other characters in the same entry; if it is, the `path` will be ignored.
   - A wildcard requires at least one character to match.

   **Examples**:
   - `/*` will match `/test` but not `/test/abc` and not `/`.
   - `/test/*` will match `/test/abc` but will not match `/test/` or `/test/abc/def`.
   - `/*/abc` will match `/test/abc`, but not `//abc`.
   - `/t*t` is invalid, so the `path` will be ignored.

2. **Wildcards in Parameter Values**:
   - A wildcard can be used alone as a parameter value.
   - A wildcard CANNOT be combined with other characters in the parameter value, or the `path` will be ignored.
   - A wildcard in parameter values requires at least one character to match.

   **Examples**:
   - `/abc?a=*` will match `/abc?a=zz` but not `/abc?a=` or `/abc?a=zz&amp;b=cc`.
   - `/abc?a=*&amp;b=*` will match `/abc?a=1&amp;b=2` and `/abc?b=2&amp;a=1`.
   - `/abc?a=z*` is invalid, so the `path` will be ignored.

3. **Special Case: Global Wildcard**:
   - A `path` containing only a `*` will match every path within the smart contract.

Wildcards are intentionally limited to these simple cases to facilitate efficient path lookup implementations.

### Caching behavior

#### Cache Invalidation States for `web3://` Clients

A `web3://` client can be in one of two cache invalidation states for each chain and smart contract:

1. **Listening for Events**:  
   The `web3://` client MUST listen for the cache invalidation events defined earlier and should aim to stay as close to real-time as possible.
   
2. **Not Listening for Events**:  
   This is the default state when this ERC is not implemented. In this state, the `web3://` client ignores all HTTP caching validation requests (e.g., `If-None-Match`, `If-Modified-Since` request headers).

The `web3://` client can switch between these states at any time and MAY implement heuristics to optimize the use of RPC providers by switching states as appropriate.

#### Cache Key-Value Mapping

The `web3://` client maintains a key-value mapping for caching, which MUST be cleared whenever it transitions from &quot;Listening for Events&quot; to &quot;Not Listening for Events.&quot; The mapping is structured as follows:

```
mapping(
  (&lt;chain id&gt;, &lt;contract address&gt;, &lt;ERC-6860 pathQuery&gt;) 
  =&gt; 
  (&lt;last modified date&gt;, &lt;ETag&gt;)
)
```

Additional elements can be included in the mapping key when necessary. For example, [ERC-7618](/EIPs/EIPS/eip-7618) requires the inclusion of the `Accept-Encoding` request header in the mapping key.

#### Handling Requests in &quot;Listening for Events&quot; State

When a request is received in the &quot;Listening for Events&quot; state:

1. **If no mapping entry exists**:
   - The `web3://` client queries the smart contract.
   - If the response includes the `evm-events` directive in the `Cache-Control` header and an `ETag`, a mapping entry is created using the `ETag`.
   - If the response contains the `evm-events` directive and a `max-age=XX` directive in the `Cache-Control` header, the mapping entry is created with the `last modified date`, determined in the following order of priority:
     - The `Last-Modified` header, if present.
     - The `Date` header, if present.
     - Otherwise, the block date when the smart contract was queried.
   - If the response includes both an `ETag` and a `Cache-Control: evm-events max-age=XX` directive, a single mapping entry is created containing both the `ETag` and the `last modified date`.

2. **If a mapping entry exists**:
   - If the request contains a valid `If-None-Match` header:
     - If the `ETag` in the mapping matches the `If-None-Match` value, the `web3://` client returns a `304 Not Modified` response immediately.
     - If the `ETag` does not match, the client queries the smart contract, deletes the mapping entry, and processes the request as if no mapping entry existed.
   
   - If the request contains a valid `If-Modified-Since` header:
     - If the `last modified date` in the mapping is earlier than the `If-Modified-Since` date, the client returns a `304 Not Modified` response immediately.
     - Otherwise, the client queries the smart contract, deletes the mapping entry, and processes the request as if no mapping entry existed.
   
   - If the request contains neither `If-None-Match` nor `If-Modified-Since` headers (or they are invalid):
     - The client queries the smart contract, deletes the mapping entry, and processes the request as if no mapping entry existed.



#### Cache Invalidation via Blockchain Events

In the &quot;Listening for Events&quot; state, the `web3://` client listens to the blockchain for the cache invalidation events defined in the previous section. For each path match, it deletes the corresponding mapping entry.


## Rationale

To stay as close as possible to standard HTTP, we reuse the HTTP caching mechanism headers.

The use of the `evm-events` directive is necessary to avoid a situation where a website uses traditional [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching headers, but the contract does not implement this ERC  by failing to emit the events. In such cases, `web3://` clients implementing this ERC would serve stale content for that website indefinitely.

## Security Considerations

Stale content will be served during the delay between a user transaction emitting a cache clearing event, and the `web3://` client picking and processing the event.

For each cached page, websites must properly implement cache invalidation events; otherwise, stale content will be served indefinitely.

In the event of a chain reorganization, the `web3://` client must roll back its caching state, or reverted content will be served until the next cache clearing event.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 20 Sep 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7774</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7774</guid>
      </item>
    
      <item>
        <title>BURN opcode</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7775-burn-opcode/21287</comments>
        
        <description>## Abstract

This proposal introduces a `BURN` opcode to the EVM. When called, the opcode is to burn native ether at the address of the current evm context.

## Motivation

The motivation for this proposal is to provide a standardized and efficient way to burn native ether directly within the EVM. Historically, contracts such as the BeaconDepositContract have &quot;burned&quot; ether by making it irrecoverable from the given address. This approach can lead to confusion and potential misuse. By introducing a dedicated `BURN` opcode, we can ensure a clear and consistent method for burning native ether. This could become useful for Ethereum L2s when transferring ether back to the L1, as well as other EVM L1 chains that could leverage this for their cryptoeconomics.

## Specification

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

### Behaviour

The `BURN` opcode `(0xFC)` is introduced with the following behavior:

1. Pops one 32-byte word from the top of the stack, treating these bytes as the `uint256` amount of native ether to be burned.
2. Retrieves the current address from the EVM execution context.
3. Checks the balance of the current address.
4. If the amount to be burned is greater than the balance of the current address, the opcode `MUST` revert.
5. If the amount to be burned is 0, the execution `MUST NOT` revert.
6. Subtracts the amount from the current address&apos;s native ether balance.

When `BURN` is used in the context of a DELEGATECALL or CALLCODE, the contract whose balance is to be manipulated is the contract that issued the DELEGATECALL or CALLCODE instruction.

When `BURN` is used in the context of a STATICCALL the call `MUST` revert.

### Gas Cost

The base gas cost for the `BURN` opcode is 100 gas. The dynamic gas cost is determined as follows:

1. If the value to be burned is 0, the dynamic gas cost is 0.
2. If the account doesn&apos;t exist, or the balance of the account is 0, the dynamic gas cost is 0.
3. Otherwise, the dynamic gas cost is 2800.

The total gas cost for the `BURN` opcode is the sum of the base gas cost and the dynamic gas cost.

### Pseudocode

Example pseudocode for the `BURN` opcode:

```python
def op_burn(pc, interpreter, scope):
    # Consume the base gas cost
    interpreter.consume_gas(100)

    # Pop the value to be burned from the stack
    value_to_burn = scope.stack.pop()

    # If the value to be burned is 0, do not revert
    if value_to_burn == 0:
        return None

    # Retrieve the current address from the EVM execution context
    current_address = scope.contract.address()

    # Check the balance of the current address
    balance = interpreter.evm.state_db.get_balance(current_address)

    # If the value to be burned is greater than the balance, revert
    if value_to_burn &gt; balance:
        return &quot;ErrInsufficientBalance&quot;
    
    # If the account balance is 0, return.
    if balance == 0:
        return None

    # Subtract the value from the current address&apos;s balance
    interpreter.evm.state_db.sub_balance(current_address, value_to_burn)
    
    # The account is known to exist at this point, thus we consume &quot;warm&quot; gas.
    interpreter.consume_gas(2800)
    return None
```

## Rationale

The introduction of the `BURN` opcode helps clean up a piece of weird semantics in the Ethereum. Historically, burning native ether involved sending them to an address from which they could not be recovered, such as the zero address or a contract with no withdrawal functionality. This method is not only inefficient but also confusing for indexers and other tools that track token movements. By providing a dedicated `BURN` opcode, we eliminate this ambiguity and ensure that the act of burning tokens is explicit and standardized.

Potential Pros:

- Provides a clear and standardized method for burning native ether within smart contracts.
- Allows for better accounting practices of native token within smart contracts.
- Reduces the possibility of a smart contract exploit caused by native token that was marked as &quot;burned&quot; being unintetionally recovered.

Potential Cons:

- Does not help remove unrecoverable ether sitting in existing contracts.
- New code in the clients
- New concept needed to be added to the yellow paper.

## Backwards Compatibility

This EIP introduces a new opcode and thus must be activated via a scheduled hardfork.

## Test Cases

&lt;!-- TODO --&gt;

## Reference Implementation

&lt;!-- TODO --&gt;

## Security Considerations

- Potentially opens up misuse when using `DELEGATECALL`.

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 30 Sep 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7775</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7775</guid>
      </item>
    
      <item>
        <title>Transparent Financial Statements</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-xxxx-transparent-financial-statements/21191</comments>
        
        <description>## Abstract

This proposal defines a standard API that enables EVM Blockchain-based companies (or also called &quot;protocols&quot;) to publish their financial information, specifically Income Statements and Balance Sheets, on-
chain in a transparent and accessible manner through solidity smart contracts. This standard aims to emulate the reporting structure used by publicly traded companies in traditional stocks markets, like 
the SEC 10-Q filings. The financial statements include key information, namely as Revenue, Cost of Goods Sold, Operating Expenses, Operating Income, Earnings before Interest, Taxes, Depreciation, and 
Amortization (EBITDA) and
Earnings Per Share-Token (EPS), allowing investors to assess the financial health of blockchain-based companies in a standardized, transparent, clear and reliable format.

## Motivation

The motivation of this ERC is to bring seriousness to the cryptocurrencies investments market. Currently, the situation is as follows:

The current state of token investment analysis is opaque, with most information presented in an abstract and non-quantitative form. This standard API ensures a consistent and reliable way for investors to 
evaluate blockchain projects based on real financial data published directly on-chain, not just speculative promises. This will establish a greater
trust in the cryptocurrency markets and align token analysis with the standards of traditional equity markets.

Most [ERC-20](/EIPs/EIPS/eip-20) Tokens representing EVM Blockchain-based companies (or also called &quot;protocols&quot;), DO NOT work the same way as a publicly traded stock that represents a share of ownership of the 
equity of that such company (so the user who buys a protocol&apos;s ERC-20, is also now a share-holder and co-owner of the business, its profits and/or its dividends), but rather function as &quot;commodities&quot; such 
as oil; they are consumable items created by said EVM Blockchain-based company (or &quot;protocol&quot;) to be spent in their platform. They are publicly traded and advertised to be representing the underlying 
protocol like a share, working in practice the same way as a commodity and without any public, transparent and _Clear_ Financial Information as publicly traded stocks have.

Added to that, most token research analysis reports that can be currently found on the internet are informal Substack or Twitter posts, with lots of abstract explanations about the features of the said 
protocol to invest in, that lack of transparent financial numbers and factual financial information, that are made by anonymous users without real exposed reputations to affect.

This ERC will improve that by giving users and investors transparent, clear and factual financial information to work with when analyzing as a potential investment the such
EVM Blockchain-based company that implements this ERC in their solidity smart contracts, and that will generate trust, transparency and seriousness in the cryptocurrencies investments market long term.

## Specification

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

All Transparent Financial Statements Standard implementations MUST implement ERC-20 to represent shares, and the financial numbers such as Revenue, Costs of Goods Sold, Operating Expenses, Operating 
Income, EBITDA, Other Income and Expenses, Net Income and Earnings Per Share MUST be displayed in the value of the protocol&apos;s stablecoin of choice.

All Transparent Financial Statements MUST implement ERC-20&apos;s optional metadata extensions.
The `name` and `symbol` functions SHOULD reflect the underlying token&apos;s `name` and `symbol` in some way.

All methods MUST be of visibility `external`.

All methods MUST return their financial numbers valued in the provided `stablecoin`.

If the contract owner uses data or methods from other owned smart contracts external to their smart contract implementation of this standard, those smart contracts MUST be verified in the correspondent 
blockchain explorer and of open and visible source code.

_Timestamp Constraint_: For all methods, `startTimestamp` MUST be less than or equal to `endTimestamp`. If `startTimestamp` is equal to `endTimestamp`, the method returns a balance sheet snapshot. If 
`startTimestamp` is less than `endTimestamp`, the method returns an income statement for that period.

_Output Structs_: Instead of a single `uint256` value, each method returns a `struct` with one or _OPTIONAL_ more `uint256` entries to allow for detailed financial data, each one with their own customized 
entry `name`.

### Definitions

- Currency: The individual stablecoin used to value the publicly displayed financial numbers.
- Revenue: Total earnings from selling products or services before expenses.
- Cost of Goods Sold (COGS): Direct costs for producing goods/services, including labor and materials.
- Operating Expenses: Expenses like Selling, General, and Administrative, Research and Development, and other operational costs.
- Operating Income: Revenue minus operating expenses.
- EBITDA: Earnings Before Interest, Taxes, Depreciation, and Amortization.
- Other Income and Expenses: Non-operating income, such as interest, investment gains or losses.
- Net Income: Profit after all expenses, taxes, and deductions.
- EPS: Earnings per Share Token (ERC-20), showing profit allocated per share.

### Methods

#### `stablecoinAddress`

Returns the `address` of the individual stablecoin used to value the publicly displayed financial numbers.

```yaml
- name: stablecoinAddress
  type: function
  visibility: external
  stateMutability: view
  outputs:
    - name: currencyAddress
      type: address

```

#### `revenue`

Returns total revenue generated by the protocol within a time period.

```yaml
- name: revenue
  type: function
  visibility: external
  stateMutability: view
  inputs:
    - name: startTimestamp
      type: uint256
    - name: endTimestamp
      type: uint256
  outputs:
    - name: RevenueStruct
      type: struct
      fields:
        - name: grossRevenue
          type: uint256
        - name: optionalAdditionalRevenueDetail1
          type: uint256
        - name: optionalAdditionalRevenueDetailN
          type: uint256

```

#### `cogs`

Returns the cost of goods sold within a specified period.

```yaml
- name: cogs
  type: function
  visibility: external
  stateMutability: view
  inputs:
    - name: startTimestamp
      type: uint256
    - name: endTimestamp
      type: uint256
  outputs:
    - name: COGSStruct
      type: struct
      fields:
        - name: totalCOGS
          type: uint256
        - name: optionalAdditionalCOGSDetail1
          type: uint256
        - name: optionalAdditionalCOGSDetailN
          type: uint256

```

#### `operatingExpenses`

Returns the total operating expenses within a specified period.

```yaml
- name: operatingExpenses
  type: function
  visibility: external
  stateMutability: view
  inputs:
    - name: startTimestamp
      type: uint256
    - name: endTimestamp
      type: uint256
  outputs:
    - name: OperatingExpensesStruct
      type: struct
      fields:
        - name: totalOperatingExpenses
          type: uint256
        - name: optionalAdditionalExpenseDetail1
          type: uint256
        - name: optionalAdditionalExpenseDetailN
          type: uint256

```

#### `operatingIncome`

Returns operating income for the specified period (Revenue - COGS - Operating Expenses).

```yaml
- name: operatingIncome
  type: function
  visibility: external
  stateMutability: view
  inputs:
    - name: startTimestamp
      type: uint256
    - name: endTimestamp
      type: uint256
  outputs:
    - name: OperatingIncomeStruct
      type: struct
      fields:
        - name: totalOperatingIncome
          type: uint256
        - name: optionalAdditionalIncomeDetail1
          type: uint256
        - name: optionalAdditionalIncomeDetailN
          type: uint256

```

#### `ebitda`

Returns EBITDA for the given period.

```yaml
- name: ebitda
  type: function
  visibility: external
  stateMutability: view
  inputs:
    - name: startTimestamp
      type: uint256
    - name: endTimestamp
      type: uint256
  outputs:
    - name: EBITDAstruct
      type: struct
      fields:
        - name: totalEBITDA
          type: uint256
        - name: optionalAdditionalEBITDADetail1
          type: uint256
        - name: optionalAdditionalEBITDADetailN
          type: uint256

```

#### `otherIncomeExpenses`

Returns non-operating income and expenses, such as interest and investment gains or losses, for the specified period.

```yaml
- name: otherIncomeExpenses
  type: function
  visibility: external
  stateMutability: view
  inputs:
    - name: startTimestamp
      type: uint256
    - name: endTimestamp
      type: uint256
  outputs:
    - name: OtherIncomeExpensesStruct
      type: struct
      fields:
        - name: totalOtherIncome
          type: uint256
        - name: totalOtherExpenses
          type: uint256
        - name: totalOtherIncomeDetail1
          type: uint256
        - name: totalOtherExpensesDetail1
          type: uint256
        - name: totalOtherIncomeDetailN
          type: uint256
        - name: totalOtherExpensesDetailN
          type: uint256

```

#### `netIncome`

Returns net income for the period (Operating Income + Other Income/Expenses - Taxes - Depreciation).

```yaml
- name: netIncome
  type: function
  visibility: external
  stateMutability: view
  inputs:
    - name: startTimestamp
      type: uint256
    - name: endTimestamp
      type: uint256
  outputs:
    - name: NetIncomeStruct
      type: struct
      fields:
        - name: totalNetIncome
          type: uint256
        - name: optionalAdditionalNetIncomeDetail1
          type: uint256
        - name: optionalAdditionalNetIncomeDetailN
          type: uint256

```

#### `earningsPerShare`

Returns Earnings Per Share Token (EPS) for the period.

```yaml
- name: earningsPerShare
  type: function
  visibility: external
  stateMutability: view
  inputs:
    - name: startTimestamp
      type: uint256
    - name: endTimestamp
      type: uint256
  outputs:
    - name: EPSstruct
      type: struct
      fields:
        - name: basicEPS
          type: uint256
        - name: dilutedEPS
          type: uint256
        - name: EPSDetail1
          type: uint256
        - name: EPSDetailN
          type: uint256

```

#### `fullFinancialReport`

Returns a comprehensive struct that includes all the prior financial details of the protocol combined: Revenue, COGS, Operating Expenses, Operating Income, EBITDA, Other Incomes and Expenses, Net income, 
and EPS into a unified `Struct`.

```yaml
- name: fullFinancialReport
  type: function
  visibility: external
  stateMutability: view
  inputs:
    - name: startTimestamp
      type: uint256
    - name: endTimestamp
      type: uint256
  outputs:
    - name: FullFinancialsStruct
      type: struct
      fields:
        - name: RevenueStruct
          type: struct
        - name: COGSStruct
          type: struct
        - name: OperatingExpensesStruct
          type: struct
        - name: OperatingIncomeStruct
          type: struct
        - name: EBITDAstruct
          type: struct
        - name: OtherIncomeExpensesStruct
          type: struct
        - name: NetIncomeStruct
          type: struct
        - name: EPSstruct
          type: struct

```

## Rationale

ERC-20 is enforced because implementation details like Earnings Per Token calculation directly carry over to the accounting. This standardization makes the Transparent Financial Statements compatible with 
all ERC-20 use cases.

This implementation enables the protocol to share their financial information both as their latest updated Balance Sheet (if the user chooses to just see a current snapshot of
the financial state of the company) and as an Income Statement (if the user chooses to see the evolution of the financial state of the company between two different block
timestamps) and also is thought to interact with other separated Smart Contracts of the same protocol from which the financial information will be sent.

## Backwards Compatibility

Transparent Financial Statements Standard is fully backward compatible with the ERC-20 standard and has no known compatibility issues with other standards.

## Reference Implementation


```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity 0.8.27;

interface IERC20 {
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
}

contract TransparentFinancialStatements {

    address public stablecoin;

    struct RevenueStruct {
        uint256 grossRevenue;
        uint256 optionalAdditionalRevenueDetail1;
        uint256 optionalAdditionalRevenueDetailN;
    }

    struct COGSStruct {
        uint256 totalCOGS;
        uint256 optionalAdditionalCOGSDetail1;
        uint256 optionalAdditionalCOGSDetailN;
    }

    struct OperatingExpensesStruct {
        uint256 totalOperatingExpenses;
        uint256 optionalAdditionalExpenseDetail1;
        uint256 optionalAdditionalExpenseDetailN;
    }

    struct OperatingIncomeStruct {
        uint256 totalOperatingIncome;
        uint256 optionalAdditionalIncomeDetail1;
        uint256 optionalAdditionalIncomeDetailN;
    }

    struct EBITDAstruct {
        uint256 totalEBITDA;
        uint256 optionalAdditionalEBITDADetail1;
        uint256 optionalAdditionalEBITDADetailN;
    }

    struct OtherIncomeExpensesStruct {
        uint256 totalOtherIncome;
        uint256 totalOtherExpenses;
        uint256 totalOtherIncomeDetail1;
        uint256 totalOtherExpensesDetail1;
        uint256 totalOtherIncomeDetailN;
        uint256 totalOtherExpensesDetailN;
    }

    struct NetIncomeStruct {
        uint256 totalNetIncome;
        uint256 optionalAdditionalNetIncomeDetail1;
        uint256 optionalAdditionalNetIncomeDetailN;
    }

    struct EPSstruct {
        uint256 basicEPS;
        uint256 dilutedEPS;
        uint256 EPSDetail1;
        uint256 EPSDetailN;
    }

    struct FullFinancialsStruct {
        RevenueStruct revenue;
        COGSStruct cogs;
        OperatingExpensesStruct operatingExpenses;
        OperatingIncomeStruct operatingIncome;
        EBITDAstruct ebitda;
        OtherIncomeExpensesStruct otherIncomeExpenses;
        NetIncomeStruct netIncome;
        EPSstruct eps;
    }

    constructor(address _stablecoin) {
        stablecoin = _stablecoin;
    }

    function currency() public view returns (address) {
        return stablecoin;
    }

    function revenue(uint256 startTimestamp, uint256 endTimestamp) 
        public 
        view 
        returns (RevenueStruct memory) 
    {
        require(startTimestamp &lt;= endTimestamp, &quot;Invalid timestamps&quot;);
        // Logic to calculate and return revenue details
        return RevenueStruct(1000, 500, 100); // Example values
    }

    function cogs(uint256 startTimestamp, uint256 endTimestamp) 
        public 
        view 
        returns (COGSStruct memory) 
    {
        require(startTimestamp &lt;= endTimestamp, &quot;Invalid timestamps&quot;);
        // Logic to calculate and return COGS details
        return COGSStruct(400, 150, 50); // Example values
    }

    function operatingExpenses(uint256 startTimestamp, uint256 endTimestamp) 
        public 
        view 
        returns (OperatingExpensesStruct memory) 
    {
        require(startTimestamp &lt;= endTimestamp, &quot;Invalid timestamps&quot;);
        // Logic to calculate and return operating expenses details
        return OperatingExpensesStruct(300, 100, 50); // Example values
    }

    function operatingIncome(uint256 startTimestamp, uint256 endTimestamp) 
        public 
        view 
        returns (OperatingIncomeStruct memory) 
    {
        require(startTimestamp &lt;= endTimestamp, &quot;Invalid timestamps&quot;);
        // Logic to calculate and return operating income details
        return OperatingIncomeStruct(300, 100, 50); // Example values
    }

    function ebitda(uint256 startTimestamp, uint256 endTimestamp) 
        public 
        view 
        returns (EBITDAstruct memory) 
    {
        require(startTimestamp &lt;= endTimestamp, &quot;Invalid timestamps&quot;);
        // Logic to calculate and return EBITDA details
        return EBITDAstruct(700, 200, 100); // Example values
    }

    function otherIncomeExpenses(uint256 startTimestamp, uint256 endTimestamp) 
        public 
        view 
        returns (OtherIncomeExpensesStruct memory) 
    {
        require(startTimestamp &lt;= endTimestamp, &quot;Invalid timestamps&quot;);
        // Logic to calculate and return other income/expenses details
        return OtherIncomeExpensesStruct(100, 50, 20, 10, 30, 20); // Example values
    }

    function netIncome(uint256 startTimestamp, uint256 endTimestamp) 
        public 
        view 
        returns (NetIncomeStruct memory) 
    {
        require(startTimestamp &lt;= endTimestamp, &quot;Invalid timestamps&quot;);
        // Logic to calculate and return net income details
        return NetIncomeStruct(600, 200, 100); // Example values
    }

    function earningsPerShare(uint256 startTimestamp, uint256 endTimestamp) 
        public 
        view 
        returns (EPSstruct memory) 
    {
        require(startTimestamp &lt;= endTimestamp, &quot;Invalid timestamps&quot;);
        // Logic to calculate and return EPS details
        return EPSstruct(10, 8, 2, 1); // Example values
    }

    function fullFinancialReport(uint256 startTimestamp, uint256 endTimestamp) 
        public 
        view 
        returns (FullFinancialsStruct memory) 
    {
        require(startTimestamp &lt;= endTimestamp, &quot;Invalid timestamps&quot;);
        // Logic to calculate and return all financial details
        return FullFinancialsStruct(
            revenue(startTimestamp, endTimestamp),
            cogs(startTimestamp, endTimestamp),
            operatingExpenses(startTimestamp, endTimestamp),
            operatingIncome(startTimestamp, endTimestamp),
            ebitda(startTimestamp, endTimestamp),
            otherIncomeExpenses(startTimestamp, endTimestamp),
            netIncome(startTimestamp, endTimestamp),
            earningsPerShare(startTimestamp, endTimestamp)
        );
    }
}

```

## Security Considerations

This ERC involves displaying critical financial data on-chain, so special attention must be paid to ensure the accuracy and security of the data, particularly in preventing tampering or manipulation of key 
financial figures.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 20 Sep 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7776</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7776</guid>
      </item>
    
      <item>
        <title>Governance for Human Robot Societies</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7777-proposal-for-human-robot-societies/21216</comments>
        
        <description>## Abstract

This proposal defines two core interfaces: `IUniversalIdentity` and `IUniversalCharter`, providing mechanisms for humans, and robots to establish their identities and to create decentralized communities governed by specific rule sets. The `IUniversalIdentity` interface establishes the fair and equitable treatment of sentient computer architectures other than the human brain, enabling robots to acquire on-chain identities, and thereby interact and transact with humans. Additionally the `IUniversalIdentity` interface also includes support for hardware-backed identity verification, enabling physical robots to prove their identity through cryptographic signatures derived from secure hardware elements and a challenge-response scheme. The `IUniversalCharter` enables humans and robots to create, join (“register”), maintain (“update”), leave, and terminate self-regulated societies based on predefined rule sets, providing a framework for collaboration and prosperity for mixed societies of humans and robots. These interfaces aim to provide a flexible yet enforceable structure for human-robot interactions in decentralized systems, ensuring efficiency, transparency, and security for all participants.

## Motivation

The human brain is a wet, massively parallel electrochemical computer. Recent hardware and software advances make it likely that soon, human societies will need tools for interacting with sentient, non-human computers, such as robots. Our current forms of government, where citizens are auto-enrolled into specific rule sets depending on where they were born, do not gracefully map onto robots without a traditional birthplace or birthtime. Among many difficulties being experienced by robots, they are (currently) unable to obtain standard forms of ID (such as passports), it is not clear which rule sets apply to them (since in general they are not born in specific places), and they cannot currently use the standard human-centered banking system. Likewise, in the event in which robots are harmed by humans or non-biological computers, it is not clear which human court has jurisdiction.

Traditional geographically-defined and human-centered systems can be inefficient, slow to change, opaque, and can struggle to accommodate global, virtualized societies.  Decentralized, immutable, and public computers offer an ideal solution to these limitations, since they do not inherently discriminate against non-human computers and therefore offer an equitable and more just framework for governance.  In particular, smart contracts can provide a powerful framework for regulating the rights and responsibilities or interacting parties regardless of implementation details of their compute architecture.

The general motivation of this ERC is to provide a standard interface for smart contracts focusing on identity/governance for heterogeneous global societies. While there are an unlimited number of such rule sets, there are obvious benefits to providing a standard interface to those rule sets, greatly reducing the friction and complexity of creating, joining, maintaining, and ending such societies. The specific motivation of this ERC is twofold:

1. Robot Identity Creation and Management: To participate meaningfully and comply with on-chain laws, non-humans such as robots must be able to acquire meaningful on-chain identities. Importantly, these identities should enable robots to enjoy the benefits of, but also bear the responsibility of, being part of a specific society. Thus, we propose to enable smart contract-based identity for robots. Specifically, each robot is represented by a smart contract and needs to follow the rules defined in the contract to interact with other agents on the chain. Each robot can also specify hardware identity parameters such as a manufacturer, operator, model and serial number in conjunction with a public key which is intended to be generated using a secure element on the Robot. This provides a tamper-resistant and unclonable proof that can be physically verified through challenge-response authentication - where any party can verify the robot&apos;s identity by having the device cryptographically sign a challenge using its hardware-secured private key. These verified identities are published on-chain. This interface also ensures flexibility by all participants to propose, adopt, or revoke rules, enabling self-managed compliance and transparent interaction with other participants.
2. Rule Creation and Enforcement: For humans and robots to effectively collaborate, they must agree upon a rule set. This Ethereum-based system provides a basic decentralized framework for governing human-robot interactions through smart contracts. We propose to enforce the rule-sets by requiring humans and robots to join regulated access smart contracts that check their compliance with the given rules. We also ensure scalability, whereby multiple regulated access contracts can be created to tailor to different purposes, and humans and robots can choose to join the relevant system as needed.

Together, these interfaces form the foundation for managing complex human-robot interactions, enabling a decentralized, verifiable, and rule-based ecosystem where robots and humans can interact securely, transparently, and responsibly, for maximum benefit of all.

## Specification

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

```solidity
interface IUniversalIdentity {

    /// @notice Structure for hardware identity
    struct HardwareIdentity {
        bytes32 publicKey;            // Hardware-bound public key uniquely tied to this robot
        string manufacturer;           // Identifier for the robot&apos;s manufacturer
        string operator;               // Identifier for the robot&apos;s operator
        string model;                  // Model identifier of the robot
        string serialNumber;           // Unique serial number for the robot
        bytes32 initialHashSignature;  // Signature of the initial system state hash (e.g., firmware, OS) by the root key
        bytes32 currentHashSignature;  // Signature of the latest state hash, updated periodically for integrity verification by the root key
    }

    /// @notice Gets the hardware identity info
    /// @return HardwareIdentity Current hardware identity
    function getHardwareIdentity() external view returns (HardwareIdentity memory);

    /// @notice Generates a new challenge for hardware verification
    /// @return bytes32 Random challenge that needs to be signed
    function generateChallenge() external returns (bytes32);
  
    /// @notice Verify response to a specific challenge
    /// @param challenge The challenge that was issued
    /// @param signature Hardware signature of the challenge
    /// @return bool True if signature is valid for this challenge
    function verifyChallenge(bytes32 challenge, bytes memory signature) external returns (bool);

    /// @notice Adds a rule to the robot&apos;s identity, showing that the robot agrees to follow the rule.
    /// @param rule The dynamic byte array representing the rule that the robot agrees to follow. Each rule is a textual string encoded into a dynamic byte array. For example: &apos;A robot must keep a 1m distance from humans.&apos;
    /// @dev The rule SHOULD come from the rule sets defined in the IUniversalCharter contract that the robot intends to join. 
    /// @dev This function SHOULD be implemented by contracts to add the rules that the robot intends to follow.
    function addRule(bytes memory rule) external;

    /// @notice Removes a rule from the robot&apos;s identity.
    /// @param rule The dynamic byte array representing the rule that the robot no longer agrees to follow.
    /// @dev This function SHOULD be implemented by contracts to remove the rules that the robot does not intend to follow.
    function removeRule(bytes memory rule) external;

    /// @notice Checks if the robot complies with a specific rule.
    /// @param rule The rule to check.
    /// @return bool Returns true if the robot complies with the rule.
    /// @dev This function MUST be implemented by contracts for compliance verification.
    function checkCompliance(bytes memory rule) external view returns (bool);

    /// @dev Emitted when a rule is added to the robot&apos;s identity.
    event RuleAdded(bytes rule);

    /// @dev Emitted when a rule is removed from the robot&apos;s identity.
    event RuleRemoved(bytes rule);
  
    /// @dev Emitted when a charter is subscribed to.
    event SubscribedToCharter(address indexed charter);

    /// @dev Emitted when it is unsubscribed from a charter.
    event UnsubscribedFromCharter(address indexed charter);
}

interface IUniversalCharter {

    // Define the user types as an enum.
    enum UserType { Human, Robot }

    /// @notice Registers a user (human or robot) to join the system by agreeing to a rule set.
    /// @param userType The type of user.
    /// @param ruleSet The array of individual rules the user agrees to follow. 
    /// @dev This function MUST be implemented by contracts using this interface.
    /// @dev The implementing contract MUST ensure that the user complies with the specified rule set before registering them in the system by invoking `checkCompliance`.
    function registerUser(UserType userType, bytes[] memory ruleSet) external;

    /// @notice Allows a user (human or robot) to leave the system 
    /// @dev This function MUST be callable only by the user themselves (via `msg.sender`). 
    /// @dev The implementing contract MUST ensure that the user has complied with all necessary rules before they can successfully leave the system by invoking `checkCompliance`.
    function leaveSystem() external;

    /// @notice Checks if the user (human or robot) complies with the system’s rules.
    /// @param user Address of the user (human or robot).
    /// @param ruleSet The array of individual rules to verify. 
    /// @return bool Returns true if the user complies with the rule set.
    /// @dev This function SHOULD invoke the `checkCompliance` function of the user’s IUniversalIdentity contract to check for rules individually. 
    /// @dev This function MUST be implemented by contracts for compliance verification.
    function checkCompliance(address user, bytes[] memory ruleSet) external view returns (bool);

    /// @notice Updates the rule set.
    /// @param newRuleSet The array of new individual rules replacing the existing ones. 
    /// @dev This function SHOULD be restricted to authorized users (e.g., contract owner).
    function updateRuleSet(bytes[] memory newRuleSet) external;

    /// @notice Terminates the contract, preventing any further registrations or interactions.
    /// @dev This function SHOULD be restricted to authorized users (e.g., contract owner).
    /// @dev This function SHOULD be implemented by contracts.
    function terminateContract() external;

    /// @dev Emitted when a user joins the system by agreeing to a set of rules.
    event UserRegistered(address indexed user, UserType userType, bytes[] ruleSet);

    /// @dev Emitted when a user successfully leaves the system after fulfilling obligations.
    event UserLeft(address indexed user);

    /// @dev Emitted when a user’s compliance with a rule set is verified.
    event ComplianceChecked(address indexed user, bytes[] ruleSet);

    /// @dev Emitted when a rule set is updated.
    event RuleSetUpdated(bytes[] newRuleSet, address updatedBy);
}
```

## Rationale

**IUniversalIdentity**

`struct HardwareIdentity`
The HardwareIdentity structure provides essential information about a robot, including a challenge-response public key, manufacturer, operator, model, manufacturer serial number 

`generateChallenge()`
This function enables secure identity verification through a challenge-response authentication.

`verifyChallenge(bytes32 challenge, bytes memory signature)`
This function verifies that a signature was genuinely created by the robot&apos;s secure hardware in response to a specific challenge.

`addRule(bytes memory rule)`
This function allows a robot to flexibly adopt new compliance requirements in order join different `IUniversalCharter` contracts.

`removeRule(bytes memory rule)`
This function allows a robot to dynamically manage and maintain its rules, ensuring that its rule set remains up-to-date.

`checkCompliance(bytes memory rule)`
This function ensures that a robot is adhering to rules by performing decentralised checks on its compliance.

`Events (RuleAdded, RuleRemoved)`
These events provide transparency and traceability, making it easier to track compliance status.

**IUniversalCharter**

`enum UserType { Human, Robot }`
The UserType enum makes it easier for contracts to handle different user types without the cost and errors associated with strings. This provides the basis for differentiated handling in future implementations, allowing the system to potentially apply different rules or logic based on whether the user is a human or a robot.

`registerUser(UserType userType, bytes[] memory ruleSet)`
This function ensures that a user—whether human or robot—is bound to a particular set of rules upon joining the system.

`leaveSystem()`
This function allows users to flexibly and securely leave a `IUniversalCharter` contract after compliance is checked.

`checkCompliance(address user, bytes[] memory ruleSet)`
This function ensures that the system can efficiently manage and verify compliance against predefined rule sets, helping maintain the overall integrity of the system.

`updateRuleSet(bytes[] memory newRuleSet)`
This function enables the `IUniversalCharter` contract to adapt and update, removing the need to create a new contract for ruleset updates.

`terminateContract()`
This function allows for the orderly and permanent shutdown of the contract.

`Events (UserRegistered, UserLeft, ComplianceChecked, RuleSetUpdated, ContractTerminated)`
These events collectively ensure that key activities are visible to off-chain systems and participants, making the system auditable and transparent.

## Backwards Compatibility

No backward compatibility issues found.

## Reference Implementation

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.19;

import { OwnableUpgradeable } from &quot;@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol&quot;;
import { UniversalCharter } from &quot;./UniversalCharter.sol&quot;;

// Interfaces
import { IUniversalIdentity } from &quot;./interface/IUniversalIdentity.sol&quot;;
import { IUniversalCharter } from &quot;./interface/IUniversalCharter.sol&quot;;

/// @title UniversalIdentity
/// @notice The UniversalIdentity contract is used to manage the identity of robots.

contract UniversalIdentity is IUniversalIdentity, OwnableUpgradeable {
    /// @notice Version identifier for the current implementation of the contract.
    string public constant VERSION = &quot;v0.0.1&quot;;

    /// @notice Mapping to store rules that the robot has agreed to follow
    mapping(bytes =&gt; bool) private robotRules;

    /// @notice Mapping to store the off-chain compliance status for each rule
    mapping(bytes =&gt; bool) private complianceStatus;

    /// @notice Track the charters the robot is subscribed to
    mapping(address =&gt; bool) private subscribedCharters;

    /// @notice Custom errors to save gas on reverts
    error RuleNotAgreed(bytes rule);
    error RuleNotCompliant(bytes rule);
    error RuleAlreadyAdded(bytes rule);

    /// @dev Event to emit when compliance is checked
    /// @param updater The address of the compliance updater (owner of the contract)
    /// @param rule The rule that was checked
    event ComplianceChecked(address indexed updater, bytes rule);

    /// @notice Modifier to check if a rule exists
    modifier ruleExists(bytes memory rule) {
        require(robotRules[rule], &quot;Rule does not exist&quot;);
        _;
    }

    /// @notice Constructor to set the owner
    constructor() {
        initialize({ _owner: address(0xdEaD) });
    }

    /// @dev Initializer function
    function initialize(address _owner) public initializer {
        __Ownable_init();
        transferOwnership(_owner);
        hardwareIdentity = _hardwareIdentity;
    }

    /// @notice Gets the hardware identity info
    function getHardwareIdentity() external view returns (HardwareIdentity memory) {
        return hardwareIdentity;
    }

    /// @notice Generates a new challenge for hardware verification
    function generateChallenge() external returns (bytes32) {
        bytes32 challenge = keccak256(abi.encodePacked(
            block.timestamp,
            block.prevrandao,
            msg.sender
        ));
        activeChallenge[challenge] = true;
        return challenge;
    }

    /// @notice Verify response to a specific challenge
    function verifyChallenge(
        bytes32 challenge,
        bytes memory signature
    ) external returns (bool) {
        if (!activeChallenge[challenge]) {
            revert InvalidChallenge();
        }

        // Remove challenge after use
        delete activeChallenge[challenge];

        // Verify the signature using ECDSA
        bytes32 messageHash = keccak256(abi.encodePacked(challenge));
        bytes32 ethSignedMessageHash = ECDSA.toEthSignedMessageHash(messageHash);
        address signer = ECDSA.recover(ethSignedMessageHash, signature);
  
        // Convert hardware public key to address for comparison
        address hardwareAddress = address(uint160(uint256(hardwareIdentity.publicKey)));
  
        if (signer != hardwareAddress) {
            revert InvalidSignature();
        }

        return true;
    }

    /// @notice Updates the hardware identity information
    /// @param _hardwareIdentity New hardware identity information
    function updateHardwareIdentity(
        HardwareIdentity memory _hardwareIdentity
    ) external onlyOwner {
        hardwareIdentity = _hardwareIdentity;
    }

    /// @notice Adds a rule to the robot&apos;s identity
    /// @param rule The dynamic byte array representing the rule that the robot agrees to follow.
    function addRule(bytes memory rule) external override onlyOwner {
        if (robotRules[rule]) {
            revert RuleAlreadyAdded(rule);
        }

        // Add rule to the mapping
        robotRules[rule] = true;

        emit RuleAdded(rule);
    }

    /// @notice Removes a rule from the robot&apos;s identity
    /// @param rule The dynamic byte array representing the rule that the robot no longer agrees to follow.
    function removeRule(bytes memory rule) external override onlyOwner ruleExists(rule) {
        robotRules[rule] = false;
        complianceStatus[rule] = false;

        emit RuleRemoved(rule);
    }

    /// @notice Subscribe and register to a specific UniversalCharter contract using its stored rule set
    /// @param charter The address of the UniversalCharter contract
    /// @param version The version of the rule set to fetch and register for
    function subscribeAndRegisterToCharter(address charter, uint256 version) external {
        require(!subscribedCharters[charter], &quot;Already subscribed to this charter&quot;);
        subscribedCharters[charter] = true;

        // Fetch the rule set directly from the UniversalCharter contract using the public getter
        bytes[] memory ruleSet = UniversalCharter(charter).getRuleSet(version);

        // Register as a robot in the charter using the fetched rule set
        UniversalCharter(charter).registerUser(IUniversalCharter.UserType.Robot, ruleSet);

        emit SubscribedToCharter(charter);
    }

    /// @notice Leave the system for a specific UniversalCharter contract
    /// @param charter The address of the UniversalCharter contract to leave
    function leaveCharter(address charter) external {
        require(subscribedCharters[charter], &quot;Not subscribed to this charter&quot;);

        // Call the leaveSystem function of the UniversalCharter contract
        UniversalCharter(charter).leaveSystem();

        // Unsubscribe from the charter after leaving
        subscribedCharters[charter] = false;
        emit UnsubscribedFromCharter(charter);
    }

    /// @notice Updates compliance status for a rule (called by the owner)
    /// @param rule The dynamic byte array representing the rule
    /// @param status The compliance status (true if compliant, false if not)
    function updateCompliance(bytes memory rule, bool status) external onlyOwner ruleExists(rule) {
        complianceStatus[rule] = status;

        emit ComplianceChecked(msg.sender, rule);
    }

    /// @notice Checks if the robot has agreed to follow a specific rule and if it is compliant
    /// @param rule The rule to check.
    /// @return bool Returns true if the robot has agreed to the rule and is compliant
    function checkCompliance(bytes memory rule) external view override returns (bool) {
        if (!robotRules[rule]) {
            revert RuleNotAgreed(rule);
        }

        return true;
    }

    /// @notice Gets the compliance status of a rule
    /// @param rule The rule to check.
    function getRule(bytes memory rule) external view returns (bool) {
        return robotRules[rule];
    }

    /// @notice Gets the subscription status of a charter
    /// @param charter The address of the charter to check.
    function getSubscribedCharters(address charter) external view returns (bool) {
        return subscribedCharters[charter];
    }

    /// @notice Gets the compliance status of a rule
    /// @param rule The rule to check.
    function getComplianceStatus(bytes memory rule) external view returns (bool) {
        return complianceStatus[rule];
    }
}
```

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity 0.8.20;

import { OwnableUpgradeable } from &quot;@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol&quot;;
import { SystemConfig } from &quot;./SystemConfig.sol&quot;;

// Interfaces
import { IUniversalCharter } from &quot;./interface/IUniversalCharter.sol&quot;;
import { IUniversalIdentity } from &quot;./interface/IUniversalIdentity.sol&quot;;

/// @title UniversalCharter
/// @notice The UniversalCharter contract is used to manage the registration and compliance of users.

contract UniversalCharter is IUniversalCharter, OwnableUpgradeable {
    /// @notice Struct to store information about a registered user
    struct UserInfo {
        bool isRegistered;
        UserType userType;
        uint256 ruleSetVersion; // Rule set version the user is following
    }

    /// @notice Mapping to store registered users
    mapping(address =&gt; UserInfo) private users;

    /// @notice Mapping to store rule sets by version number
    mapping(uint256 =&gt; bytes[]) private ruleSets;

    /// @notice Mapping to track the rule set hash and its corresponding version
    mapping(bytes32 =&gt; uint256) private ruleSetVersions;

    /// @notice Version identifier for the current implementation of the contract.
    string public constant VERSION = &quot;v0.0.1&quot;;

    /// @notice Variable to track the current version of the rule set
    uint256 private currentVersion;

    /// @notice Variable to store the address of the SystemConfig contract
    SystemConfig public systemConfig;

    /// @notice Error for when a method cannot be called when paused. This could be renamed
    /// to `Paused` in the future, but it collides with the `Paused` event.
    error CallPaused();

    /// @notice Reverts when paused.
    modifier whenNotPaused() {
        if (paused()) revert CallPaused();
        _;
    }

    /// @notice Constucts the UniversalCharter contract.
    constructor() {
        initialize({ _owner: address(0xdEaD), _systemConfig: address(0xdEaD) });
    }

    /// @dev Initializer function
    function initialize(address _owner, address _systemConfig) public initializer {
        __Ownable_init();
        transferOwnership(_owner);
        systemConfig = SystemConfig(_systemConfig);
    }

    /// @notice Registers a user (either human or robot) by agreeing to a rule set
    /// @param userType The type of user: Human or Robot
    /// @param ruleSet The array of individual rules the user agrees to follow
    function registerUser(UserType userType, bytes[] memory ruleSet) external override whenNotPaused {
        require(!users[msg.sender].isRegistered, &quot;User already registered&quot;);

        // Hash the rule set to find the corresponding version
        bytes32 ruleSetHash = keccak256(abi.encode(ruleSet));
        uint256 version = ruleSetVersions[ruleSetHash];
        require(version &gt; 0, &quot;Invalid or unregistered rule set&quot;);

        // For robots, ensure compliance with each rule via the UniversalIdentity contract
        if (userType == UserType.Robot) {
            require(_checkRobotCompliance(msg.sender, version), &quot;Robot not compliant with rule set&quot;);
        }

        // Register the user with the versioned rule set
        users[msg.sender] = UserInfo({ isRegistered: true, userType: userType, ruleSetVersion: version });

        emit UserRegistered(msg.sender, userType, ruleSet);
    }

    /// @notice Allows a user (human or robot) to leave the system after passing compliance checks
    function leaveSystem() external override whenNotPaused {
        require(users[msg.sender].isRegistered, &quot;User not registered&quot;);

        UserInfo memory userInfo = users[msg.sender];

        // For robots, verify compliance with all rules in the rule set
        uint256 version = userInfo.ruleSetVersion;
        if (userInfo.userType == UserType.Robot) {
            require(_checkRobotCompliance(msg.sender, version), &quot;Robot not compliant with rule set&quot;);
        }

        users[msg.sender] = UserInfo({ isRegistered: false, userType: UserType.Human, ruleSetVersion: 0 });

        emit UserLeft(msg.sender);
    }

    /// @notice Internal function to verify robot hardware identity
    /// @param robotAddress The address of the robot to verify
    /// @return bool Returns true if hardware verification succeeds
    function _verifyRobotHardware(address robotAddress) internal returns (bool) {
        IUniversalIdentity robot = IUniversalIdentity(robotAddress);
  
        // Get hardware identity to ensure it exists
        robot.getHardwareIdentity();
  
        // Generate a new challenge
        bytes32 challenge = robot.generateChallenge();
  
        // Store the challenge for future reference
        users[robotAddress].lastVerifiedChallenge = challenge;
  
        // Get signature from the robot (this would typically happen off-chain)
        // For this implementation, we&apos;ll assume the signature is provided in a separate tx
        // and just verify the challenge exists
        return challenge != 0;
    }

    /// @notice Checks if a user complies with their registered rule set
    /// @param user The address of the user (human or robot)
    /// @param ruleSet The array of individual rules to verify
    /// @return bool Returns true if the user complies with the given rule set
    function checkCompliance(address user, bytes[] memory ruleSet) external view override returns (bool) {
        require(users[user].isRegistered, &quot;User not registered&quot;);

        // Hash the provided rule set to find the corresponding version
        bytes32 ruleSetHash = keccak256(abi.encode(ruleSet));
        uint256 version = ruleSetVersions[ruleSetHash];
        require(version &gt; 0, &quot;Invalid or unregistered rule set&quot;);
        require(users[user].ruleSetVersion == version, &quot;Rule set version mismatch&quot;);

        // For robots, check compliance with each rule in the UniversalIdentity contract
        if (users[user].userType == UserType.Robot) {
            return _checkRobotCompliance(user, version);
        }

        // If the user is human, compliance is assumed for now (can be extended)
        return true;
    }

    /// @notice Internal function to check compliance for robots with their rule set version
    /// @dev This function will revert if the robot is not compliant with any rule. Returns true for view purposes.
    /// @param robotAddress The address of the robot
    /// @param version The version of the rule set to verify compliance with
    /// @return bool Returns true if the robot is compliant with all the rules in the rule set
    function _checkRobotCompliance(address robotAddress, uint256 version) internal view returns (bool) {
        IUniversalIdentity robot = IUniversalIdentity(robotAddress);
        bytes[] memory rules = ruleSets[version];

        for (uint256 i = 0; i &lt; rules.length; i++) {
            if (!robot.checkCompliance(rules[i])) {
                return false;
            }
        }

        return true;
    }

    /// @notice Updates or defines a new rule set version.
    /// @param newRuleSet The array of new individual rules.
    /// @dev This function SHOULD be restricted to authorized users (e.g., contract owner).
    function updateRuleSet(bytes[] memory newRuleSet) external whenNotPaused onlyOwner {
        require(newRuleSet.length &gt; 0, &quot;Cannot update to an empty rule set&quot;);

        // Hash the new rule set and ensure it&apos;s not already registered
        bytes32 ruleSetHash = keccak256(abi.encode(newRuleSet));
        require(ruleSetVersions[ruleSetHash] == 0, &quot;Rule set already registered&quot;);

        // Increment the version and store the new rule set
        currentVersion += 1;
        ruleSets[currentVersion] = newRuleSet;
        ruleSetVersions[ruleSetHash] = currentVersion;

        emit RuleSetUpdated(newRuleSet, msg.sender);
    }

    /// @notice Getter for the latest version of the rule set.
    function getLatestRuleSetVersion() external view returns (uint256) {
        return currentVersion;
    }

    /// @notice Get the rule set for a specific version.
    /// @param version The version of the rule set to retrieve.
    function getRuleSet(uint256 version) external view returns (bytes[] memory) {
        return ruleSets[version];
    }

    /// @notice Get the version number for a specific rule set.
    /// @param ruleSet The hash of the rule set to retrieve the version for.
    function getRuleSetVersion(bytes32 ruleSet) external view returns (uint256) {
        return ruleSetVersions[ruleSet];
    }

    function getUserInfo(address user) external view returns (UserInfo memory) {
        return users[user];
    }

    /// @notice Getter for the current paused status.
    /// @return paused_ Whether or not the contract is paused.
    function paused() public view returns (bool paused_) {
        paused_ = systemConfig.paused();
    }
}
```

## Security Considerations

Compliance Updater: The compliance updater role in the `UniversalIdentity` contract is critical for updating compliance statuses (currently limited to the owner). It is essential to ensure secure ownership to minimize the risks of unauthorized or malicious updates.

Rule Management: Functions such as addRule, removeRule, and updateCompliance in the `UniversalIdentity` contract and updateRuleSet in the `UniversalCharter` contract directly affect rule enforcement. It’s essential to ensure these functions are only callable by authorized users.

Upgradeable Contracts: The use of OwnableUpgradeable introduces risks during the initialization and upgrade process. Ensuring that the initialize function is protected against re-execution is critical to avoid reinitialization attacks.

Gas Consumption: Excessively large rule sets could lead to high gas costs or DoS risks. Consider setting limits on the number of rules allowed per rule set to maintain gas efficiency and avoid performance issues.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 29 Sep 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7777</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7777</guid>
      </item>
    
      <item>
        <title>Block Gas Accounting without Refunds</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7778-prevent-block-gas-smuggling/21234</comments>
        
        <description>## Abstract

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.

## Motivation

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.

Example: Block `20878522` 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.

This mechanism can be exploited to perform more operations in a block than the gas limit intends to allow, potentially leading to:

1. Network instability due to oversized blocks
2. Denial-of-service vectors
3. Computational loads exceeding the intended block gas limit

## Specification

### Gas Accounting Changes

1. **User Gas Accounting (Unchanged):**

   - Users continue to receive gas refunds for operations that qualify (e.g., setting storage to zero)
   - Transaction gas: `gas_spent = max(tx_gas_used - gas_refund, calldata_floor_gas_cost)`

2. **Block Gas Accounting (Modified):**

   - When calculating gas for block gas limit enforcement, refunds are not subtracted
   - Block gas accounting becomes: `block.gas_used += max(tx_gas_used, calldata_floor_gas_cost)` (incorporating the calldata floor from [EIP-7623](/EIPs/EIPS/eip-7623))
   - Storage discounts that reflect actual reduced computational work (e.g., warm storage access, reverting to original values) remain applied to block gas accounting

## Rationale

### Aligning Gas Limits with Computational Work

The block gas limit is designed to constrain the computational load per block. Gas refunds were introduced to incentivize &quot;cleaning up&quot; 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

### Preserving User Incentives

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

## Backwards Compatibility

- This change is not backwards compatible and requires a hard fork
- User and developer experience for individual transactions remains unchanged
- Block producers need to adjust their transaction selection algorithms to account for the new gas accounting rules

## Test Cases

1. **SSTORE Operations:**
   - Setting storage to zero: User receives refund, but block gas accounting uses full cost
   - Verify blocks containing many storage-clearing operations still adhere to gas limits

2. **Block Gas Limit Edge Cases:**
   - Construct blocks with varying amounts of refundable operations
   - Ensure blocks cannot exceed gas limits through refund mechanisms

3. **Transaction Gas vs Block Gas:**
   - Verify that transaction costs for users remain unchanged
   - Confirm block gas accounting properly excludes refunds

## Security Considerations

- Eliminates potential denial-of-service vectors that exploit gas refunds to exceed block computational limits
- Improves predictability of block processing times by enforcing stricter limits on computational work
- Prevents miners/validators from including transactions that collectively contain more computational work than intended

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Interoperable Delegated Accounts</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7779-interoperable-delegated-account/21237</comments>
        
        <description>## Abstract

This proposal outlines the interfaces to make delegated EOAs interoperable after the merge of [EIP-7702](/EIPs/EIPS/eip-7702). With [EIP-7702](/EIPs/EIPS/eip-7702), EOAs will be able to enable execution abstraction, which leads to a more feature-rich account, including gas sponsorship, batch execution, and more.

However, there is a need to help facilitate storage management for redelegation, as invalid management of storage may incur storage collisions that can lead to unexpected behavior of accounts (e.g., account getting locked, security vulnerabilities, etc)

The interface `InteroperableDelegatedAccount` suggests the interfaces for delegated EOAs to be interoperable and facilitate a better environment for redelegation.

## Motivation

After the merge of [EIP-7702](/EIPs/EIPS/eip-7702), it is expected that a considerable number of EOA wallets will migrate from pure EOA accounts to delegated EOA accounts.

This is to enable a more appealing wallet UX, including a 1-step swap, automated subscription, gas sponsorship, and more.

However, considering the fact that delegated EOAs will utilize its own storage bound to their Smart Account implementation, the storage management is essential to foster migration between wallets to better ensure sovereignty of users to freely migrate their wallet app whenever they want.

EOA (Externally Owned Account) is currently comprised of cryptographic key pair that is mostly managed in the form of mnemonic phrase.

This simplicity provided frictionless interoperability between wallets that gave users the freedom to freely migrate between different wallet applications.

However, after the merge of [EIP-7702](/EIPs/EIPS/eip-7702), each EOA will be given the ability to delegate itself to a smart account which will impact migration as storage remains in the continuous context while EOA can be delegated to diverse smart accounts if the user migrates their wallet.

Account Abstraction Wallets, given the wallet-specific validation and execution logic, also have the interoperability issue to be considered but its importance in EOA is much more significant as EOA users are already familiar with wallet migration and its a common action to migrate wallets.

This spec provides a standard approach for fetching the storage base used in the delegated account together with an optional mechanism to clean up the storage.

Moreover, it is worth noting that this spec is not limited to [EIP-7702](/EIPs/EIPS/eip-7702) based smart accounts but smart accounts and smart contracts in general that uses a custom storage slot.

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119 and RFC 8174.

```solidity
interface IInteroperableDelegatedAccount {

	/*
	 * @dev    Provides the namespace of the account.
	 *         namespace of accounts can possibly include, account version, account name, wallet vendor name, etc
	 * @notice this standard does not standardize the namespace format
	 * e.g.,   &quot;v0.1.2.7702Account.WalletProjectA&quot;
	 */
	function accountId() external view returns (string);
	
	/*
	 * @dev    Externally shares the storage bases that has been used throughout the account.
	 *         Majority of 7702 accounts will have their distinctive storage base to reduce the chance of storage collision.
	 *         This allows the external entities to know what the storage base is of the account.
	 *         Wallets willing to redelegate already-delegated accounts should call accountStorageBase() to check if it confirms with the account it plans to redelegate.
	 *
	 *         The bytes32 array should be stored at the storage slot: keccak(keccak(&apos;InteroperableDelegatedAccount.ERC.Storage&apos;)-1) &amp; ~0xff
	 *         This is an append-only array so newly redelegated accounts should not overwrite the storage at this slot, but just append their base to the array.
	 *         This append operation should be done during the initialization of the account.
	 * 		   This array should return a value of keccak hash unless using external storage.
	 */
	function accountStorageBases() external view returns (bytes32[]);

}
```

```solidity
interface IRedelegableDelegatedAccount {

	/*
	 * @dev    Function called before redelegation.
	 *         This function should prepare the account for a delegation to a different implementation.
	 *         This function could be triggered by the new wallet that wants to redelegate an already delegated EOA.
	 *         It should uninitialize storages if needed and execute wallet-specific logic to prepare for redelegation.
	 *         msg.sender should be the owner of the account.
	 */
	function onRedelegation() external returns (bool);

}
```

Accounts MUST implement the `IInteroperableDelegatedAccount` to be compliant with the standard.

Accounts MUST use `keccak256()` to compute the storage bases for `accountStorageBases()`, unless using external storage contract.

Accounts MAY implement the `IRedelegableDelegatedAccount`.

### `accountId()`

This function is a view function to fetch the account information.

A use case for this could be wallet showing the redelegation process e.g., Are you willing to migrate your account `“Wallet A” → “Wallet B”`.

Wallet A information could be extracted from `accountId()`.

### `accountStorageBases()`

This function returns the list of base storage slots of that account has used.

To comply with this standard, the account MUST use `keccak256()` to prevent collision when calculating the storage slot.

EIP-7702 Accounts do plan to use a custom non-zero storage slot to avoid storage collision as much as possible, however, there hasn’t been a standardized approach on how to fetch them.

This function provides a standardized approach for wallets and other applications to check the base storage slots of an account, and verify if the base storage slots are far enough from the newly to-be-redelegated account’s base storage slot.

Note that there could be some exceptions for mappings, etc depending on how account manages storage.

This provides Wallets and applications a standard approach to fetch the base storage slots for verification rather than just relying on the probability of hash.

If the account uses external storage, it should return ERC Number prefixed slot with the external storage contract address concatenated.

```solidity
&lt;ERC-Number&gt;&lt;ERC-Number&gt;&lt;ERC-Number&gt;..N...&lt;Storage-Contract-Address&gt;
```
For example, if the storage contract address is `0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA` the returned value should be
```
0x777977797779777977797779AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
```

When the account is delegated(e.g., during the account initialization stage), the account implementation should append the base storage slot of the account to the following slot position: `keccak(keccak(&apos;InteroperableDelegatedAccount.ERC.Storage&apos;)-1) &amp; ~0xff` .

The storage variable would be using the `bytes32[]` type and is an append-only variable which newly delegated accounts append its storage slot hash. The account may choose to not append its storage base to an array if there is an identical entry that already exist.

In case the account identifies that there are colliding storage bases, the account can perform further storage verification either off-chain or on-chain and decide whether the delegation would happen.

Wallet may revert the delegation if the colliding storage includes a suspicious storage values that may target the user(e.g., shadow signer, etc).

### `onRedelegation()`

This function is to prepare for the redelegation to a new account.

When this function is called, the existing delegated account should perform actions to not limit or impact the user when the user redelegates to a new account as much as possible.

For example, the account could uninitialize the storage variables as much as it can to provide clean storage for new wallet.

This standard, however, does not explicitly state the behavior to be done during this function call as wallet implementations have very distinctive architecture and details.

**The standard expect the wallet implementation to revert it back to a clean storage state ***as much as possible*** with this function.**

`onRedelegation()` should validate if the caller is indeed the authorized user by checking the `msg.sender` value.

This could also be done through a &quot;self-call&quot; if a custom validation scheme is implemented or at the wallet&apos;s discretion as a side case.

![diagram showing the flow of onredelegation](/EIPs/assets/eip-7779/diagram.svg)

## Rationale

### Storage base checks

This standard is designed with the need of wallets to validate the storage of the EOA, even if some may consider that the probability of hash is already big that the account doesn&apos;t have to check, assuming that each wallet uses a different storage base slot.
In fact, this standard thinks exactly the opposite. It is worth scanning the storage, or at least the storage that the delegated account will use, which the wallet wants to delegate to. E.g., Just like developers validating the storage of Facets in Diamond ([ERC-2535](/EIPs/EIPS/eip-2535)) to prevent storage collision and not just relying on hash probability.
In line with this, the `accountStorageBases()` was designed to not only return the storage base of the current wallet implementation, but return the full historical storage slots that the account has used.
This could provide valuable information for the storage scanning of the EOA before delegation.

### Optional `onRedelegation()`

`onRedelegation()` was designed to be optional to lower the barrier of being compliant with this standard. Also, there could be accounts that does not functionally require a hook-logic to be in place before redelegation, or accounts that does not suite with the design principle of the `onRedelegation()` e.g., excessive use of mapping or data types that&apos;s hard to uninitialize.

It is worth noting that, `onRedelegation()` does not obligate the account to completely whipe out it&apos;s storage. It&apos;s more of a best effort function to leave the cleanest stage for the future use of the EOA in a new wallet. Or to execute a function to prepare for redelegation.

## Backwards Compatibility

Existing smart accounts that was built prior to the [EIP-7702](/EIPs/EIPS/eip-7702) discussion will need changes to support this standard.

This standard was specifically for Smart Accounts for EOA, but this could be applied further to diverse cases and architecture.

## Security Considerations

1. Calling `onRedelegation()` should include security mechanism to properly authentication the owner.
2. This standard enforces the accounts to 
    1. provide proper Base Storage Slot when `accountStorageBase()` is called
    2. perform proper actions to make account storage to a clean state as much as possible (e.g., uninitialization of storage variables, etc) IF the account supports `onRedelegation()`
    
    However, whether the account follows the above three enforcements with behavioral actions is dependant of the account.
    
    If needed, accounts may check the authenticity of the information through off-chain approaches.
    
3. Wiping out the storage completely may not be an adaptable action depending on how account implementation manages storage.
    
    This standard recommends the account to completely wipe out its storage, however, exceptions apply if the account is incapable of doing that.
    
    In the case when the account cannot completely wipe out its storage, the standard expect the account to perform the best degree of action it can do to support the redelegation operation for the user.
    
    Also, the account should make sure the initializer cannot be triggered by an arbitrary entity after `onRedelegation()` is called.
    
4. `onRedelegation()` should not reset the replay protection considering that it could incur a vulnerability(e.g., signature reply attack).

5. It is worth noting that this standard is an ERC, which means that even if the ERC enforces it, the actual implementation may not be compliant with it. e.g., accounts pretending to support this standard which is not, in fact. So it is recommend to validate if the account is a know implementation that is secure and compliant with the standard.

6. The standard ENFORCES the storage slot to be calculated through `keccak256()` to reduce collision. The preimage of the hash could be the name/version or a combination, it is under full discretion of the account.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).</description>
        <pubDate>Wed, 02 Oct 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7779</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7779</guid>
      </item>
    
      <item>
        <title>Validation Module Extension for ERC-7579</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7780-validation-module-extension-for-erc-7579/21273</comments>
        
        <description>## Abstract

This proposal introduces three new module types on top of the existing modules described in [ERC-7579](./eip-7579). The modules are policy, signer and stateless validator. None of these modules are required to be implemented by accounts, but accounts can choose to implement them or other modules can choose to make use of them for additional composability.

Policy modules can be used to check what a `UserOperation` or action is trying to achieve and determine if this is allowed. Signer modules can be used to validate signatures on provided hashes. Stateless validators are modules that are used to both validate signatures and compare them to a calldata-provided data blob which could, for example, include owners to check signatures against.

## Motivation

The modules introduced by this proposal aim to create more composability around signature and permission verification.

Policy and signer modules allow an account to make direct use of such a permissioning logic rather than relying on external modules to handle this. This has the upside of lower gas cost but the downside of less flexibility for users and developers that use the account.

Stateless validators enable further composability around signature validation logic. In many cases, it does not make sense to re-write signature validation for new validators, but instead to use the existing ones. However, this is usually not possible since the validators rely on a stored configuration indexed by the `msg.sender`, which is expected to be an account. Stateless validators solve this problem by not relying on state to compare signature verification against, but instead to compare it against a calldata-provided argument.

## Specification

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

This standard introduces three new module types on top of the existing modules introduced by ERC-7579:

- `Policy` (type id: 5)
- `Signer` (type id: 6)
- `StatelessValidator` (type id: 7)
- `PreValidationHookERC1271` (type id: 8)
- `PreValidationHookERC4337` (type id: 9)
- `StatelessValidatorWithSender` (type id: 10)

Note: A single module can be of multiple types.

### Policy

Policies MUST implement [ERC-7579](/EIPs/EIPS/eip-7579)&apos;s `IModule` and the `IPolicy` interface and have module type id: `5`.

```solidity
interface IPolicy is IModule {

		/**
		 * Checks a userOp to determine if it should be executed
         *
         * SHOULD validate the executions in the userOp against stored configurations
         *
		 * @param id The id of the policy
		 * @param userOp The user operation to check
         *
		 * @return The validation data to return to the EntryPoint as specified by ERC-4337
		 */
	  function checkUserOpPolicy(
			  bytes32 id,
			  PackedUserOperation calldata userOp
		)
        external
        payable
        virtual
        returns (uint256);

		/**
		 * Checks a signature to determine if it should be executed
         *
         * SHOULD validate the hash in order to determine what the signature is used for and if it should be permitted
         * MAY check the sender to determine whether the signature should be permitted
         *
		 * @param id The id of the policy
		 * @param sender The sender of the transaction
		 * @param hash The hash of the transaction
		 * @param sig The signature of the transaction
         *
		 * @return The validation data to return to the EntryPoint as specified by ERC-4337
		 */
		function checkSignaturePolicy(
		    bytes32 id,
			  address sender,
			  bytes32 hash,
			  bytes calldata sig
		)
        external
        view
        virtual
        returns (uint256);
}
```

### Signer

Signers MUST implement the `IModule` and the `ISigner` interface and have module type id: `6`.

```solidity
interface ISigner is IModule {

		/**
		 * Check the signature of a user operation
         *
		 * @param id The id of the signer config
		 * @param userOp The user operation
		 * @param userOpHash The hash of the user operation
         *
		 * @return The status of the signature check to return to the EntryPoint
		 */
    function checkUserOpSignature(
		    bytes32 id,
			  PackedUserOperation calldata userOp,
			  bytes32 userOpHash
		)
        external
        payable
        virtual
        returns (uint256);

		/**
		 * Check an ERC-1271 signature
         *
		 * @param id The id of the signer config
		 * @param sender The sender of the signature
		 * @param hash The hash to check against
		 * @param sig The signature to validate
         *
		 * @return The ERC-1271 magic value if the signature is valid
		 */
    function checkSignature(
		    bytes32 id,
		    address sender,
		    bytes32 hash,
		    bytes calldata sig
		)
        external
        view
        virtual
        returns (bytes4);
}
```

### Stateless Validator

StatelessValidators MUST implement the `IStatelessValidator` interface and have module type id: `7`. It is RECOMMENDED that all Validators (module type id `1`) also implement the Stateless Validator interface for additional composabillity.

```solidity
interface IStatelessValidator {

	/**
     * Validates a signature given some data
     *
     * @param hash The data that was signed over
     * @param signature The signature to verify
     * @param data The data to validate the verified signature against
     *
     * MUST validate that the signature is a valid signature of the hash
     * MUST compare the validated signature against the data provided
     * MUST return true if the signature is valid and false otherwise
     */
    function validateSignatureWithData(
        bytes32 hash,
        bytes calldata signature,
        bytes calldata data
    )
        external
        view
        returns (bool);

     /**
     * Returns boolean value if module is a certain type
     *
     * @param moduleTypeId the module type ID according the ERC-7579 spec
     *
     * MUST return true if the module is of the given type and false otherwise
     */
    function isModuleType(uint256 moduleTypeId) external view returns (bool);
}
```

### `PreValidationHookERC1271`

`PreValidationHookERC1271` MUST implement the `IPreValidationHookERC1271` interface and have module type id: `8`.

```solidity
interface IPreValidationHookERC1271 {
    function preValidationHookERC1271(
        address sender,
        bytes32 hash,
        bytes calldata data
    )
        external
        view
        returns (bytes32 hookHash, bytes memory hookSignature);
}
```

### `PreValidationHookERC4337`

`PreValidationHookERC4337` MUST implement the `IPreValidationHookERC4337` interface and have module type id: `9`.

```solidity
interface IPreValidationHookERC4337 {
    function preValidationHookERC4337(
        PackedUserOperation calldata userOp,
        uint256 missingAccountFunds,
        bytes32 userOpHash
    )
        external
        returns (bytes32 hookHash, bytes memory hookSignature);
}
```

### StatelessValidatorWithSender

StatelessValidatorWithSender MUST implement the `IStatelessValidatorWithSender` interface and have module type id: `10`. It is RECOMMENDED that all Validators (module type id `1`) also implement the Stateless Validator With Sender interface for additional composabillity.

```solidity
interface IStatelessValidatorWithSender {
	/**
     * Validates a signature given some data
     * 
     * @param sender address who called account.isValidSignature()
     * @param hash The data that was signed over
     * @param signature The signature to verify
     * @param data The data to validate the verified signature against
     *
     * MUST validate that the signature is a valid signature of the hash
     * MUST compare the validated signature against the data provided
     * MUST return true if the signature is valid and false otherwise
     */
    function validateSignatureWithDataWithSender(
        address sender,
        bytes32 hash,
        bytes calldata signature,
        bytes calldata data
    ) external view returns (bool);
}
```

## Rationale

TBD &lt;!-- TODO --&gt;

## Backwards Compatibility

No backward compatibility issues found.

## Security Considerations

TBD &lt;!-- TODO --&gt;

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 01 Oct 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7780</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7780</guid>
      </item>
    
      <item>
        <title>Reduce Block Latency</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7782-reduce-block-latency/21271</comments>
        
        <description>## Abstract

Reduce Ethereum&apos;s slot time from 12 s to 6 s, halving on‑chain latency and epoch duration. This doubles slot throughput while keeping block and blob sizes unchanged, smoothing bandwidth usage. The change delivers better user experience, faster Layer 2 interaction, tighter DEX pricing, reduced MEV, and quicker finality.

## Motivation

- **Protocol Carrying Capacity** It is impractical to increase block sizes beyond 10MiB without substantial networking changes. However it is practical to decrease slot time to achieve similar effect while also improving the UX at same time.
- **Enhanced UX**: Confirmations now arrive in ~6 s instead of 12 s.
- **Faster Finality**: Epochs shrink from 384 s (32 × 12 s) to 192 s (32 × 6 s), accelerating Casper‑FFG finality.
- **L2 Interoperability**: Layer 2 rollups see half the settlement delay on L1, improving throughput and reducing reorg risk period.
- **Based rollups**: Based rollup sequencing is tied to L1 block time so faster blocks directly improves based rollups.
- **DEX Economics**: More frequent blocks decrease LVR (Loss Versus Rebalancing), which improves the economics for liquidity providers. More liquidity means lower spreads (reduced slippage).
- **Bandwidth Smoothing**: Doubling slot rate distributes bandwidth evenly without increasing peak block size; nodes with modest capacity remain supported.

## Specification

On the consensus layer, a new parameter is added to the configuration:

```
SLOT_SCHEDULE:
  - EPOCH: 348618
    SECONDS_PER_SLOT: 12
  - EPOCH: 355368
    SECONDS_PER_SLOT: 6
```

The parameters and schedules above are purely illustrative. Actual values and schedules are beyond the scope of this specification.

### Adjustment to gas and blob limits

The first execution block after the fork needs to specify half the previous gas limit. With this fork, all gas limit settings are reinterpreted as &quot;gas per 12 seconds&quot;. I.e., if the user configuration or otherwise default gas limit vote was 36,000,000, the client should now vote for 18,000,000. All values are rounded down to integers.

The blob target and limit are also halved, rounded down to the nearest integer.

### Attestation deadlines

All clients need to be reconfigured so that deadlines can be configured in milliseconds for finer granularity. Currently the slot is split into three equal intervals, with proposal happening at time 0, and attestations and aggregations being sent at one thirds and two thirds of the slot time. We change this to a new uneven schedule, in order to give sufficient time for block propagation, which takes the most time:

- Block proposal at 0 ms
- Attestations at 3000 ms
- Aggregates at 4500 ms

## Rationale

This proposal balances user experience, economic efficiency, and network stability:

- UX &amp; Finality: Halving slot time directly reduces confirmation latency and halves epoch duration, delivering faster feedback to users and speeding up Casper-FFG finality.

- Economic Efficiency: Increased block frequency tightens DEX price spreads, lowers slippage, and diminishes arbitrage and MEV opportunities, improving on-chain trading conditions.

- L2 &amp; Based Rollups Synergy: Layer 2 rollups, especially based rollups, benefit from reduced L1 settlement delays, enhancing throughput and user-perceived performance in rollup ecosystems.

- Network Stability: Maintaining existing p2p network maximum smooths bandwidth usage over time, avoiding peak-load spikes and preserving accessibility for nodes with diverse bandwidth capacities.

## Backwards Compatibility

No backwards compatibility concerns.

## Security Considerations

- **Network Congestion**:

  - **Increased Message Frequency**: The network must handle more frequent messages without congestion.
  - **Mitigation**: Implement network optimizations and encourage the use of efficient client software.

- **Consensus Integrity**:

  - **Fork Choice Stability**: Ensure that the fork choice rule remains robust against potential reorganization attacks.
  - **Finality Gadgets**: Confirm that finality mechanisms function correctly under new timing conditions.

## Copyright

Copyright and related rights waived via CC0 1.0 Universal.
</description>
        <pubDate>Sat, 05 Oct 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7782</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7782</guid>
      </item>
    
      <item>
        <title>Add Controlled Gas Limit Increase Strategy</title>
        <category>Informational/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7783-add-controlled-gas-limit-increase-strategy/21282</comments>
        
        <description>This proposal describes the introduction in clients of a controlled gas limit increase strategy to determine the gas limit of a specific block and set as default with conservative parameters, while keeping the possibility to change it in the future to a fixed value.

## **Abstract**

The EIP proposes the introduction of a new gas limit management mechanism that automatically increases the block gas limit over time. The incremental growth is controlled by a fixed rate, ensuring predictable network scaling while preventing sudden surges in block sizes. This strategy is meant to be used as a default setting, with the option to switch to a fixed gas limit if needed (or different parameters).

## **Motivation**

### **Predictable Gas Limit Growth**

- **Current Issue:**
  - The Ethereum network faces increasing demand, but changes to the gas limit are often manually adjusted by miners or validators based on their preferences, which may cause unpredictable block sizes and network performance issues.

- **Need for Change:**
  - A systematic and predictable increase of the gas limit will help scale the network while giving the ecosystem time to adjust to larger block sizes, without needing to rely on ad hoc decisions by network participants.

### **Gradual Increase with Deactivation Safeguard**

- **Controlled Growth:**
  - Instead of sudden or unpredictable changes, this EIP proposes incremental gas limit increases over a specified amount of time, ensuring a smooth transition to higher transaction throughput, while still keeping the governance of the gas limit in the hand of the community.
  
- **Automatic Deactivation:**
  - A safeguard deactivation block will halt the increase after some specified time, preventing the gas Limit from growing indefinitely and allowing the community to reassess the network&apos;s needs.

## **Specification**

There are different approaches to implement a controlled gas limit increase strategy. The following are three possible strategies that can be used:

### **Linear Gas Limit Increase Strategy**

Add a new &quot;Gas Limit&quot; selection strategy that takes in Block Number `N` and spits out the Gas Limit `GL` for that block. The strategy is as follows:

 - The gas limit `GL_t` at block `t` is calculated as:

```python
def compute_gas_limit(blockNum: int, blockNumStart: int, initialGasLimit: int, r: int, gasLimitCap: int) -&gt; int:
  if blockNum &lt; blockNumStart:
    return initialGasLimit
  else:
    return min(gasLimitCap, initialGasLimit + r * (blockNum - blockNumStart))
```

Where:

- `blockNum` is the block number for which the gas limit is being calculated.
- `blockNumStart` is the block number at which the gas limit increase starts.
- `initialGasLimit` is the initial gas limit at block `blockNumStart`.
- `r` is the rate at which the gas limit increases per block.
- `gasLimitCap` is the maximum gas limit that can be reached.

If we set `blockNumStart` to the current block number, `initialGasLimit` to the current gas limit (`30_000_000`), `r` to 6, and `gasLimitCap` to `60_000_000`, the gas limit will increase by 6 gas per block for two years, reaching 30 million gas at the end of a $\approx$ 2 years period. 
The result of `compute_gas_limit` will be the gas limit aimed by the proposer for the block `blockNum`. none of this is enforced at the protocol level, and the proposer needs to still follow protocol rules related to the gas limit.

### **Stepwise Linear Gas Limit Increase Strategy**

Add a new &quot;Gas Limit&quot; selection strategy that takes in Block Number `N` and spits out the Gas Limit `GL` for that block. The strategy is as follows:

- The gas limit `GL_t` at block `t` is calculated as:

```python
def compute_gas_limit(blockNum: int, blockNumStart: int, r: int, step_blocks_interval: int, gasLimitCap: int) -&gt; int:
  if blockNum &lt; blockNumStart:
    return initialGasLimit
  else:
    return min(gasLimitCap, initialGasLimit + r * ((blockNum - blockNumStart) // step_blocks_interval))
```

Where:

- `blockNum` is the block number for which the gas limit is being calculated.
- `blockNumStart` is the block number at which the gas limit increase starts.
- `initialGasLimit` is the initial gas limit at block `blockNumStart`.
- `step_blocks_interval` is the number of blocks after which the gas limit increases (cooldown period).
- `r` is the rate at which the gas limit increases per step.
- `gasLimitCap` is the maximum gas limit that can be reached.

This strategy has three main advantages:

- It provides larger, more visible, and distinct metric changes over each step.
- It allows for collection of more stabilized metrics over the length of the cooldown period.
- It gives the community more time to evaluate the impact of the gas limit increase and act accordingly.

### **Exponential Gas Limit Increase Strategy**

Add a new &quot;Gas Limit&quot; selection strategy that takes in Block Number `N` and spits out the Gas Limit `GL` for that block. The strategy is as follows:

 - The gas limit `GL_t` at block `t` is calculated as:

```python
def compute_gas_limit(blockNum: int, blockNumStart: int, doubling_blocks_interval: int) -&gt; int:
  if blockNum &lt; blockNumStart:
    return initialGasLimit
  else:
    return min(gasLimitCap, initialGasLimit * (2 ** ((blockNum - blockNumStart) / doubling_interval)))
```

Where:

- `blockNum` is the block number for which the gas limit is being calculated.
- `blockNumStart` is the block number at which the gas limit increase starts.
- `initialGasLimit` is the initial gas limit at block `blockNumStart`.
- `doubling_blocks_interval` is the number of blocks after which the gas limit doubles.


## **Rationale**

### **Predictable Growth**

- **Systematic Adjustment:**
  - The gradual increase avoids sudden surges in gas limit that could destabilize the network. Instead, it provides a smooth transition, giving the ecosystem time to adapt to larger block sizes.

### **Controlled Limit with Deactivation Block**

- **Automatic Safeguard:**
  - The inclusion of a deactivation block ensures that the gas limit does not increase indefinitely, preventing potential negative impacts on network performance beyond the planned growth.


- **Community Consensus:**
  - The deactivation block serves only as a checkpoint for the community to evaluate the impact of the gas limit increase, however, in the two-year period, the community can decide to halt the increase at any time and can also switch to a fixed gas limit if needed.

## **Backwards Compatibility**

**No Hard Fork Required**

## **Security Considerations**


- The controlled gas limit increase strategy is designed to prevent sudden changes that could lead to network instability or security vulnerabilities.
- The fact that validators can re-adjust the gas limit in case of a DOS attack or other issues, makes the network more secure than to just increasing the gas limit manually in a cliff-like manner.

## **Copyright**

Copyright and related rights waived via CC0 1.0 Universal.

</description>
        <pubDate>Sun, 06 Oct 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7783</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7783</guid>
      </item>
    
      <item>
        <title>GETCONTRACT opcode</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7784-getcontract-code/21325</comments>
        
        <description>## Abstract

This is a proposal to add a new opcode, `GETCONTRACT`. The `GETCONTRACT` opcode would return the address containing the bytecode by its hash.

## Motivation

Content addressing by hash is a common pattern in database design. It allows to store and retrieve data by its unique footprint in the storage. This pattern is widely used in the industry and it allows abstracting the actual storage location and allows reusing the same bytecode in multiple contracts.

Today, 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.

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.

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.

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.

For decentralized application (dApp) developers, a code index can save gas costs by allowing them to reference existing codebase 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.

This also allows to build new core standards more conveniently, for example, [EIP-7702](./eip-7702) can use it as dependency, to allow users who want to set up one-time code on their EOAs by referring to `GETCONTRACT` instead of specifying potentially mutable address based functionality.

## Specification

### Opcode Definition

* **Mnemonic:** `GETCONTRACT`
* **Opcode Value:** `0x4f`
* **Input:**
    * `codehash`: A single 32-byte code hash from the stack.
* **Output:**
    * `address`:  If the `codehash` exists in the state, pushes the corresponding contract address onto the stack. Otherwise, pushes 0.
* **Gas Cost:** 150
* **Stack Effects:** Pops 1 item, pushes 1 item.
* **Error Handling:**  If the `codehash` is invalid or the bytecode retrieval encounters an error, the instruction will revert.

Every contract stored in EVM MUST be added to the state trie with the key being the keccak256 hash of the contract&apos;s bytecode, provided it is:

* not already present
* The contract did not invoke the `SELFDESTRUCT` opcode.
* The `EXTCODEHASH` return value IS NOT `0xeadcdba66a79ab5dce91622d1d75c8cff5cff0b96944c3bf1072cd08ce018329` (`keccak256(0xef01)`)


### Example Usage

```solidity
function getContractAddress(bytes32 codehash) public view returns (address) {
    address contractAddress;
    assembly {
        contractAddress := GETCONTRACT(codehash)
    }
    return contractAddress;
}
```

## Rationale

**Bytecode over Addresses**: Bytecode is deterministic and can be verified on-chain, while addresses are opaque and mutable.

**Do not re-index**: There is small, yet non-zero probability of hash collision attack. Disallowing updates to indexed location of bytecode coupes with this.

**Gas cost**: This operation is more complex than simple data retrieval, however lookup in the database by hash generally is simpler in complexity.

## Security Considerations

**Malicious Code**: 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.

**Storage contents of registered contracts**: 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.

**[EIP-7702](./eip-7702) delegation:** Temporary code delegation is disallowed to prevent case of registering a code hash that becomes unavailable. Standard explicitly disallows contracts with bytecode delegated via [EIP-7702](./eip-7702) from being indexed.

**SELFDESTRUCT**: Contracts that `selfdestruct` are not indexed, as they will not have a codehash in the state trie.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 07 Oct 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7784</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7784</guid>
      </item>
    
      <item>
        <title>Onchain registration of chain identifiers</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/on-chain-registration-of-chain-identifiers/21299</comments>
        
        <description>## Abstract

This ERC proposes to derive chain identifiers as a digest of their chain name (and other information) and to use ENS to map chain names to identifiers in place of the centralized list on GitHub.
A solution to support existing chain identifiers that were not derived following this ERC is also proposed.

## Motivation

The mapping between chain names and identifiers, such as `Mainnet -&gt; 0x1`, is currently maintained in a centralized list.
However this solution has two main shortcomings:
- It does not scale with the growing number of L2s.
- The list maintainers are a single point of failure.

Desired properties:
- the ability to register new chain names and identifiers in a censorship-resistant way
- the ability to resolve chain names and identifiers in a trustless way
- maintain a unique mapping between names and identifiers

### Chain Identifier Spoofing and Replay Attacks

An important property of the centralized list is that it keeps a one-to-one correspondence between names and identifiers.

Without this property, an attacker could register a fresh name pointing to an existing identifier. For example `my-testnet` could point to mainnet `0x1`. A user could be tricked into signing a transaction for the innocent looking `my-testnet` while actually signing a transaction for mainnet, a transaction that the attacker can then replay.

## Specification

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

### Extending chain identifiers

Current chain identifiers are usually chosen arbitrarily to be short. While these identifiers are convenient on a small scale, as their number increases it is more desirable to draw them from a larger space.

We propose to extend the size of identifiers to 32 bytes and to derive them using a cryptographic hash function.
The input to the function MUST contain the chain name and MAY contain additional information.

An example for a L2:
```
chain_id = Keccak-256(CHAIN_NAME, SETTLEMENT_CHAIN_ID, VERSION, DEPLOYER_CONTRACT_ADDRESS, SALT)
```
where:
- `SETTLEMENT_CHAIN_ID` is the id of the L1 where the L2 settles, it could be Mainnet or a testnet.
- `VERSION` is to separate the domain of the hash function with an arbitrary string
- `DEPLOYER_CONTRACT_ADDRESS` is the address of the L2 on the L1

### Chain name resolution

Any ENS name can resolve to a chain identifier as specified in &lt;!-- TODO: Is 2304 a sufficient replacement for ENSIP-11? --&gt;[ERC-2304](/EIPs/EIPS/eip-2304). The name should resolve to a record containing not only the chain identifier, but also all the optional information necessary to verify the identifier.

For example the chain name `rollup` can be converted to a chain identifier on Mainnet by resolving:
```
rollup.eth -&gt; {version : uint, bridge : address, chain_id : chain_id}
```
and then verified using:
```
chain_id == hash(&quot;rollup&quot;, 0x1, version, bridge)
```

## Rationale

&lt;!--
  The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages.

  The current placeholder is acceptable for a draft.

  TODO: Remove this comment before submitting
--&gt;

TBD

## Backwards Compatibility

Existing identifiers, that were not derived using the scheme above, can be supported using a reverse mapping from chain identifiers to chain names, so that one can check for uniqueness.

For example the chain name `legacy-rollup.eth` can be resolved to the chain identifier `0x123`.
Then `0x123` can be resolved in the `chainid.reverse` domain to a `chain_name`.
If `chain_name == legacy-rollup` then the mapping is valid.

### Bootstrapping and handover

In order to bootstrap the handling of legacy chain identifiers, we imagine the EF populating the `chainid.reverse` domain, a temporary `l2.eth` for names and then handing them over.

- EF populates two subdomains `l2.eth` and `chainid.reverse` using Ethereum lists.
- A rollup registers a `rollup.eth` and points it to their `chain_id.
- EF hands over to the rollup `rollup.l2.eth` and `chain_id.chainid.reverse`
- The rollup updates `chain_id.chainid.reverse` to return `rollup.eth`


## Security Considerations

Domain spoofing can lead to replay attacks as described above and can be eliminated by deriving new identifiers using a hash function and by checking the reverse mapping for legacy identifiers.

Domain squatting, the practice of ammassing a large number of domains in the hope to selling them later to legitimate users, is a possibility but with an increasing number of L2 registrations we can expect the same problem to appear in the centralized Github list.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 26 Sep 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7785</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7785</guid>
      </item>
    
      <item>
        <title>Cross-Chain Messaging Gateway</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7786-cross-chain-messaging-gateway/21374</comments>
        
        <description>## Abstract

This proposal describes an interface, and the corresponding workflow, for smart contracts to send arbitrary data through cross-chain messaging protocols. The end goal of this proposal is to have all such messaging protocols accessible via this interface (natively or using &quot;adapters&quot;) to improve their composability and interoperability. That would allow a new class of cross-chain native smart contracts to emerge while reducing vendor lock-in. This proposal is modular by design, allowing users to leverage bridge-specific features through attributes (structured metadata) while providing simple &quot;universal&quot; access to the simple feature of &quot;just getting a simple message through&quot;.

## Motivation

Cross-chain messaging protocols (or bridges) allow communication between smart contracts deployed on different blockchains. There is a large diversity of such protocols with multiple degrees of decentralization, different architectures, implementing different interfaces, and providing different guarantees to users.

Because almost every protocol implements a different workflow using a specific interface, portability between bridges is currently basically impossible. This also prevents the development of generic contracts that rely on cross chain communication.

The objective of this ERC is to provide a standard interface, and a corresponding workflow, for performing cross-chain communication between contracts. Existing cross-chain communication protocols that do not natively implement this interface should be able to adopt it using adapter gateway contracts.

Compared to previous ERCs in this area, this ERC offers compatibility with chains outside of the Ethereum/EVM ecosystem, and it is extensible to support the different feature sets of various protocols while offering a shared core of standard functionality.

## Specification

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

### Message Field Encoding

A cross-chain message consists of a sender, recipient, payload, value (native token), and list of attributes.

#### Sender and Recipient

The sender account (in the source chain) and recipient account (in the destination chain) MUST be input in an Interoperable Address binary format, specified in [ERC-7930](/EIPs/EIPS/eip-7930), which MUST be serialized according to CAIP-350. The recipient field MAY be omitted or zeroed (contain an Interoperable Address with all fields set to zero) to indicate an unspecified destination, such as when a broadcast mode is employed and the final recipients are determined by the protocol itself.

#### Payload

The payload is an opaque `bytes` value.

#### Attributes

An attribute is a key-value pair, where the key determines the type and encoding of the value, as well as its meaning and behavior in the gateway.

The set of valid attributes is extensible. It is RECOMMENDED to standardize them and their characteristics by publishing them as ERCs. A gateway MAY support any set of standard or custom attributes.

An attribute key is a 4-byte value (`bytes4`). It is RECOMMENDED to define a key as the function selector for a function signature according to Solidity ABI (for example, `minGasLimit(uint256)` resulting in the key `39f87ba1`), so as to give the key a human-readable name and a standard value encoding corresponding to the ABI-encoding of the function arguments.

An attribute value is byte array (`bytes`).

The list of attributes MUST be encoded as `bytes[]` (an array of `bytes`) where each element is the concatenation of a key and a value. (Note that in the case of keys defined as Solidity function selectors, each element of the array can be encoded by `abi.encodeWithSignature`.)

A message with no attributes (an empty attributes list) MUST be considered a valid message.

### Sending Procedure

A **Source Gateway** is a contract that offers a protocol to send a message to a recipient on another chain. It MUST implement `IERC7786GatewaySource`.

```solidity
interface IERC7786GatewaySource {
    event MessageSent(
        bytes32 indexed sendId,
        bytes sender,    // Binary Interoperable Address
        bytes recipient, // Binary Interoperable Address
        bytes payload,
        uint256 value,
        bytes[] attributes
    );

    error UnsupportedAttribute(bytes4 selector);

    function supportsAttribute(bytes4 selector) external view returns (bool);

    function sendMessage(
        bytes calldata recipient, // Binary Interoperable Address
        bytes calldata payload,
        bytes[] calldata attributes
    ) external payable returns (bytes32 sendId);
}
```

#### `supportsAttribute`

Returns a boolean indicating whether an attribute (identified by its key) is supported by the gateway.

A gateway MAY be upgraded with support for additional attributes. Once present support for an attribute SHOULD NOT be removed to preserve backwards compatibility with users of the gateway.

#### `sendMessage`

Initiates the sending of a message.

Further action MAY be required by the gateway to make the sending of the message effective, such as providing payment for gas. See Post-processing.

MUST revert with `UnsupportedAttribute` if an unsupported attribute is included. MAY revert if an attribute value is not valid for the key.

MAY accept call value (native token) to be sent with the message. MUST revert if call value is included but it is not a feature supported by the gateway. It is unspecified how this value is represented on the destination.

MAY generate and return a unique non-zero _send identifier_, otherwise returning zero. This identifier can be used to track the lifecycle of the message in the source gateway in events and for post-processing. _Note that this identifier MAY be different from the `receiveId` that is delivered to the recipient, since that identifier may preferably consist of values like transaction id and log index that are not available in the execution environment._

MUST emit a `MessageSent` event, including the optional send identifier that is returned by the function.

#### `MessageSent`

This event signals that a would-be sender has requested a message to be sent.

If `sendId` is present, post-processing MAY be required to send the message through the cross-chain channel.

#### Post-processing

After a sender has invoked `sendMessage`, further action MAY be required by the gateways to make the message effective. This is called _post-processing_. For example, some payment is typically required to cover the gas of executing the message at the destination.

The exact interface for any such action is out of scope of this ERC.

### Reception Procedure

A **Destination Gateway** is a contract that implements a protocol to validate messages sent on other chains. The interface of the destination gateway and how it is invoked is out of scope of this ERC.

The protocol MUST ensure delivery of a sent message to its **recipient** using the `IERC7786Recipient` interface (specified below), which the recipient MUST implement.

Once the message can be safely delivered (see Properties), the gateway MUST invoke `receiveMessage` with the message identifier and contents, unless the sender or the recipient explicitly requested otherwise.

The `receiveId` MUST be either empty or unique (for the calling gateway) to the message being relayed. The format of this identifier is not specified, and the gateway can use it at its own discretion. For example it can be an identifier of the `MessagePosted` event that created the message.

The gateway MUST verify that `receiveMessage` returns the correct value, and MUST revert otherwise.

```solidity
interface IERC7786Recipient {
    function receiveMessage(
        bytes32 receiveId,     // Unique identifier
        bytes calldata sender, // Binary Interoperable Address
        bytes calldata payload,
    ) external payable returns (bytes4);
}
```

#### `receiveMessage`

Delivery of a message sent from another chain.

The recipient MUST validate that the caller of this function is a **known gateway**, i.e., one whose underlying cross-chain messaging protocol it trusts.

MUST return `IERC7786Recipient.receiveMessage.selector` (`0x2432ef26`).

#### Interaction Diagram

![](/EIPs/assets/eip-7786/send-execute.png)

### Properties

The protocol underlying a pair of gateways is expected to guarantee a series of properties. For a detailed definition and discussion, we refer to XChain Research’s _Cross-chain Interoperability Report_.

- The protocol MUST guarantee Safety: A message is delivered at the destination if and only if it was sent at the source. The delivery process must ensure a message is only delivered once the sending transaction is finalized, and not delivered more than once. Note that there can be multiple messages with identical parameters that must be delivered separately.
- The protocol MUST guarantee Liveness: A sent message is eventually delivered to the destination, assuming Liveness and censorship-resistance of the source and destination chains and that any protocol costs are paid.
- The protocol SHOULD guarantee Timeliness: A sent message is delivered at the destination within a bounded delivery time, which should be documented.
- The above properties SHOULD NOT rely on trust in some centralized actor. For example, safety should be guaranteed by some trustless mechanism such as a light client proof or attestations by an open, decentralized validator set. Relaying should be decentralized or permissionless to ensure liveness; a centralized relayer can fail and thus halt the protocol.

## Rationale

Attributes are designed so that gateways can expose any specific features the bridge offers without having to use a proprietary interface. This should allow contracts to change the gateway they use while continuing to express messages the same way. This portability offers many advantages:

- A contract that relies on a specific gateway for sending messages is vulnerable to the gateway being paused, deprecated, or simply breaking. If the communication between the contract and the gateway is standard, an admin of the contract could update the address (in storage) of the gateway to use. In particular, senders to update to the new gateway when a new version is available.
- Bridge layering is made easier. In particular, this interface should allow for gateways that route the message through multiple independent bridges. Delivery of the message could require one or multiple of these independent bridges depending on whether improved liveness or safety is desired.

As some cross-chain communication protocols require additional parameters beyond the destination and the payload, and because we want to send messages through those bridges without any knowledge of these additional parameters, a post-processing of the message MAY be required (after `sendMessage` is called, and before the message is delivered). The additional parameters MAY be supported through attributes, which would remove the need for a post-processing step. If these additional parameters are not provided through attributes, an additional call to the gateway is REQUIRED for the message to be sent. If possible, the gateway SHOULD be designed so that anyone with an incentive for the message to be delivered can jump in. A malicious actor providing invalid parameters SHOULD NOT prevent the message from being successfully relayed by someone else.

Some protocols gateway support doing arbitrary direct calls on the recipient. In that case, the recipient must detect that they are being called by the gateway to properly identify cross-chain messages. Getters are available on the gateway to figure out where the cross-chain message comes from (source chain and sender address). This approach has the downside that it allows anyone to trigger any call from the gateway to any contract. This is dangerous if the gateway ever holds any assets ([ERC-20](/EIPs/EIPS/eip-20) or similar). The use of a dedicated `receiveMessage` function on the recipient protects any assets or permissions held by the gateway against such attacks. If the ability to perform direct calls is desired, this can be implemented as a wrapper on top of any gateway that implements this ERC.

## Backwards Compatibility

Existing cross-chain messaging protocols implement proprietary interfaces. We recommend that protocols natively implement the standard interface defined here, and propose the development of standard adapters for those that don&apos;t.

## Security Considerations

### Handling addresses

Interoperable Addresses (ERC‑7930) rely on CAIP‑350 serialization. Using non‑canonical encodings can lead to silent delivery failures. Gateways SHOULD reject non‑canonical encodings and MAY normalize them before emission.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 14 Oct 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7786</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7786</guid>
      </item>
    
      <item>
        <title>Soulbound Degradable Governance</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7787-soulbound-degradable-governance/21326</comments>
        
        <description>## Abstract

This proposal introduces the Soulbound Degradable Governance (SDG) standard, where governance power should be granted as non-transferable tokens that decay over time unless renewed through participation. SDG enables young DAOs to implement merit-based governance by detaching governance power from economic power while on early stages of development.

## Motivation

Traditional DAO governance models rely heavily on economic tokens, where voting power is proportional to token holdings. While effective for some use cases, this model risks concentrating power among wealthy members, leading to plutocracy and discouraging participation from smaller stakeholders. Furthermore, it fosters a treasury-centric culture that attracts contributors primarily focused on financial gain, rather than long-term governance or community well-being. 

Young DAOs, in particular, need governance models that incentivize active contributions without relying on economic power. This proposal addresses these issues by detaching governance power from economic power and ensuring political power decays if not maintained through ongoing participation. This approach creates a merit-based structure that reflects continuous involvement and reduces the risk of early-stage centralization or dependent on heavy inflationary policies.

## Specification

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

This system MUST operate with two distinct tokens types, one representing **political power** and another representing **economic power**:  

1. The political power token SHOULD be non-transferable with over-time decayment. 

2. The economic power token supports liquidity and trade, providing the financial utility needed for the DAO’s operations and is RECOMMENDED to be a standard [ERC-20](/EIPs/EIPS/eip-20) token.

The implementer of this standard MUST:

1. Override the `transfer(...)` function for the governance token to block transfers between addresses. 

2. Create a decay mechanism by overriding the `getVotes(...)` function on parent contract, reducing the token’s voting power over time. This is RECOMMENDED to be a linear or exponential decay formula.

3. Create the respective **Event** emissions that track the voting power of addresses.

### Contract Interface:

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.20;

interface SDG {
  /**
   * @dev Returns the grace period duration before the voting units begins decaying. This period is
   * fixed to 90 days. But it can be overridden in derived contracts.
   * @return The duration of the grace period in seconds.
   */
  function gracePeriod() public view virtual returns (uint256);

  /**
   * @dev Returns the duration of the decay period during which the voting units decreases. This
   * period is fixed to 90 days. But it can be overridden in derived contracts.
   * @return The duration of the decay period in seconds.
   */
  function decayPeriod() public view virtual returns (uint256);

  /**
   * @dev Should be implemented by derived contracts to return the current voting units of an account.
   * This function calculates the voting units based on the last time it was updated and decays it
   * over time.
   * @param account The address to check for voting units.
   * @return The current voting units of the account.
   */
  function getVotes(address account) public view virtual returns (uint256);
}

```

## Rationale

The SDG standard ensures flexibility by not being tied to any specific token type, allowing DAOs to implement it with [ERC-20](/EIPs/EIPS/eip-20), [ERC-721](/EIPs/EIPS/eip-721), [ERC-1155](/EIPs/EIPS/eip-1155), or other future token standards. This decision maximizes the compatibility and adaptability of the framework across different governance models.

The choice to **decouple governance power from economic power** aims to provide a practical governance model for young DAOs seeking to prevent early centralization while fostering active participation. Non-transferable governance tokens ensure that only engaged members retain influence, as political power decays over time if not renewed through contributions. 

We deliberately avoided incorporating mechanisms like &quot;Game Master mode&quot; for early stages or fixed decayment strategy within the standard to keep the specification **minimal and modular**. These governance structures should be implemented by individual DAOs if needed, without burdening the core SDG standard with additional complexity. The goal is to provide DAOs with the essential tools to build sustainable, merit-based governance, while leaving room for experimentation and customization at the implementation level.

The inclusion of **grace periods** and **decay periods** balances fairness with fluidity, incentivizing active participation while preventing governance stagnation. These mechanics ensure that governance power reflects recent contributions, phasing out inactive members naturally, and maintaining a dynamic, merit-based structure.

## Backwards Compatibility

No backward compatibility issues found.

## Reference Implementation

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.20;

import { SDG } from &quot;./SDG.sol&quot;; // SDG implementation
import { SOULERC721 } from &quot;./ERC721/SOULERC721.sol&quot;; // Soulbounded ERC721 implementation
import { Ownable } from &quot;@openzeppelin/contracts/access/Ownable.sol&quot;; // Oz Ownable contract

/**
 * @title Valocracy
 * @dev Implements the SDG governance model where governance power decays over time if not actively maintained.
 * Only the DAO governance contract, as the owner, can mint new tokens or grant additional governance power.
 */
contract Valocracy is SDG, SOULERC721, Ownable {
  // Event emitted when voting units are updated
  event VotingUnitsUpdated(address indexed account, uint256 oldVotingUnits, uint256 newVotingUnits);

  // Sequential ID and total supply of tokens
  uint256 public totalSupply;

  // Mapping of addresses to their token IDs
  mapping(address =&gt; uint256) private _tokens;

  /**
   * @param _name The name of the ERC721 token.
   * @param _symbol The symbols of the ERC721 token.
   */
  constructor(
    string memory _name,
    string memory _symbol
  ) Ownable(_msgSender()) SOULERC721(_name, _symbol) {}

  /**
   * @dev See {IERC721Metadata-tokenURI}.
   * @notice This function returns a static string as the token URI. In a real implementation, this
   * function should return an URI that points to a JSON file with metadata about the token. Or even
   * better, a dynamic SVG that displays the governance power of the token holder.
   */
  function tokenURI(uint256 tokenId) public pure override returns (string memory) {
    return &quot;Custom images or Dynamic NFT that displays the governance power&quot;;
  }

  /**
   * @dev See {ISDG-getVotes}.
   */
  function getVotes(address account) public view override returns (uint256) {
    uint256 grantedTime = _lastUpdateOf(account);

    // If no voting units was granted or still in grace period, return all voting units
    if (grantedTime == 0 || block.timestamp &lt; grantedTime + gracePeriod()) {
      return _votingUnitsOf(account);
    }

    // Calculate time passed since grace period ended
    uint256 timeSinceGracePeriod = block.timestamp - (grantedTime + gracePeriod());

    // If decay period is over, return 0
    if (timeSinceGracePeriod &gt;= decayPeriod()) {
      return 0;
    }

    // Linear decay: Calculate remaining voting units during decay period
    uint256 decayPercentage = (timeSinceGracePeriod * 1e18) / decayPeriod(); // Percentage in 18 decimals
    uint256 remainingVotes = (_votingUnitsOf(account) * (1e18 - decayPercentage)) / 1e18;

    return remainingVotes;
  }

  /**
   * @dev Grants voting units to the specified account by `amount`. Only the contract owner can
   * mint new tokens and grant additional votings units. If the users doesn&apos;t have a token, one
   * will be minted for them.
   * @param to The address to mint the new token or grant additional voting units.
   * @param amount The amount of voting units to grant alongside the token.
   */
  function grantVotingUnits(address to, uint256 amount) public virtual onlyOwner {
    if (_tokens[to] == 0) {
      _mint(to, ++totalSupply);
      _tokens[to] = totalSupply;
    }

    uint256 votingUnits = getVotes(to);
    _setVotingUnits(to, votingUnits + amount);

    emit VotingUnitsUpdated(to, votingUnits, amount);
  }

  /**
   * @notice Burns an ERC721 token and erases the voting units associated with the token holder.
   * @dev The token must exist and be burnable by the token holder or authorized entity.
   * @param tokenId The ID of the token to burn.
   */
  function burn(uint256 tokenId) public virtual {
    address from = ownerOf(tokenId);
    uint256 votingUnits = getVotes(from);

    _tokens[from] = 0;
    _setVotingUnits(from, 0);
    _burn(tokenId);

    emit VotingUnitsUpdated(from, votingUnits, 0);
  }
} 
```

## Security Considerations

No security concerns were found. &lt;!-- TODO --&gt;

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 15 Oct 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7787</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7787</guid>
      </item>
    
      <item>
        <title>Dynamic target blob count</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7788-dynamic-target-blob-count/21399</comments>
        
        <description>## Abstract

This EIP proposes to make the target blob count adjust dynamically up to a safe maximum target. This adjustment will target a constant price in ETH for blobs, aiming for consistent costs of L2 transactions.

## Motivation

Ethereum currently uses a target of 50% capacity for blob count, with [EIP-1559](/EIPs/EIPS/eip-1559) smoothing out short-term spikes and pushing average throughput towards the target. A dynamic target is orthogonal to EIP-1559, tweaking the target itself over a longer timescale to aim for some desired blob cost.

With static targeting the target may be higher than the actual demand, causing the protocol to undercharge for blobspace. This decreases the amount of fees burned, negatively affecting the price of ETH and total network security.

As an example, consider what would happen if there was a large increase in max blob count due to DAS implementation but the target remained at 50%. It is unlikely that demand would immediately jump to anywhere near the target, and so for months or years the protocol would effectively charge nothing for L2 transactions. With a dynamic target, the target blob count would drop until the cost of blobspace for an L2 transaction approximated some affordable constant value. In this way, some fees are still burned by the protocol, but new L2s are not discouraged from using Ethereum blobspace, knowing that the target will increase in response to an increase in demand and blob fees will remain reasonably consistent.

While the max blob count and max target are hard constraints based on resource utilisation limits, setting the target itself is far more subjective. A dynamic target can optimise for constant and affordable L2 transaction costs without requiring regular intervention by core developers to make tweaks based on changes in demand.

## Specification

### Parameters

| Parameter | Value |
| - | - |
| `FORK_TIMESTAMP` | TBD |
| `TARGET_BLOB_COUNT_CHANGE_RATE` | `1` |
| `MIN_TARGET_BLOB_COUNT` | `1` |
| `MAX_TARGET_BLOB_COUNT` | `3` |
| `BLOB_COST_CHANGE_MARGIN` | `2^48` |
| `TARGET_BLOB_COST` | `2^49` |

### Dynamic targeting

The target blob count changes each epoch based on the mean blob cost over the previous epoch. If the average cost exceeds the desired amount beyond some margin then the target is increased; likewise if it is below the desired amount by some margin the target will decrease. The target can increase up to `MAX_TARGET_BLOB_COUNT`, which is deemed to be a safe average throughput for the network, and down to a minimum of `MIN_TARGET_BLOB_COUNT`.

Calculating targets:

```python
blob_cost_diff = mean_blob_cost - TARGET_BLOB_COST
target_change_direction = -1 if blob_cost_diff &lt; -BLOB_COST_CHANGE_MARGIN else (1 if blob_cost_diff &gt; BLOB_COST_CHANGE_MARGIN else 0)
next_epoch_blob_count = max(min(MAX_TARGET_BLOB_COUNT, previous_epoch_blob_count + (target_change_direction * TARGET_BLOB_COUNT_CHANGE_RATE)), MIN_TARGET_BLOB_COUNT)
```

### Engine API change

The Engine API is extended to provide the `mean_blob_cost` for the current epoch when the CL requests it from the EL. The CL requests this at the end of an epoch to set the target for the next epoch (depends on [EIP-7742](./eip-7742)).

## Rationale

### Constant blob cost target

A constant blob cost target can keep L2 transaction costs affordable for end users. Volatility in the price of ETH would affect affordability, but is unlikely to be significant compared to normal fluctuations in blob gas costs due to spikes in activity. In future the costs could be adjusted in the case of changes in the order of magnitude of ETH price.

An alternative approach would be to track a target blob cost in fiat. However, choosing a specific fiat currency is not credibly neutral, and introducing exchange rate oracles into the protocol could be an attack vector.

Yet another alternative is to have validators vote on the target blob cost, but they may have conflicts of interest (for example if they operate a rollup) so again this is not credibly neutral.

### Target block gas

The same logic could be applied to the target block gas, but generally blockspace is in high demand so arguably gas costs are never too low. The target should be set to the maximum average throughput that the network can safely handle, a dynamic target is not necessary.

### Parameter choices

`TARGET_BLOB_COST` is chosen so that the system targets affordable L2 transactions. Assuming that the theoretical compressed size of a simple transfer is 23 bytes, this gives a blobspace cost for L2 transactions of:

```
(23 / 125000) * TARGET_BLOB_COST ≈ 104 gWei
```

At today’s prices, $1 would cover blobspace for around 3700 simple transfers on L2. The blob cost target should be chosen with extensive community involvement. Note that this is the cost of blobspace for an L2 transaction; the total cost will be more due to rollup execution costs.

`TARGET_BLOB_COUNT_CHANGE_RATE` is chosen as a compromise between the system being reactive to changes in demand, and not having large jumps in average throughput. `BLOB_COST_CHANGE_MARGIN` is set such that target blob count will stay static when blob costs are within a range ±50% of `TARGET_BLOB_COST`.

`MAX_TARGET_BLOB_COUNT` is set to `3` to match the current static target. This value should be increased in future when it is deemed to be safe to increase average blob throughput.

## Backwards Compatibility

N/A

## Test Cases

N/A

## Reference Implementation

N/A

## Security Considerations

&lt;!-- TODO --&gt;
Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 15 Oct 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7788</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7788</guid>
      </item>
    
      <item>
        <title>Controlled Gas Limit Increase Guidelines</title>
        <category>Informational/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7790-parameters-to-increase-the-gas-limit/21435</comments>
        
        <description>This proposal specifies specific parameters for the controlled gas limit increase strategy outlined in [EIP-7783](/EIPs/EIPS/eip-7783), including block number to start the increase, initial gas limit, rate of increase per block, and gas limit cap.

## **Abstract**

This proposal provides parameter recommendations for implementing the controlled gas limit increase strategy in [EIP-7783](/EIPs/EIPS/eip-7783).

## **Motivation**

The motivation for this proposal is to define practical and balanced parameters for Ethereum&apos;s gas limit increase strategy to achieve predictable and stable network scaling. While [EIP-7783](/EIPs/EIPS/eip-7783) defines the mechanism, there is still a need to establish the values needed for its implementation based on real-world conditions.

## **Specification**

### **Proposed Parameters**

The parameters for the controlled gas limit increase strategy are:

- **Block Number Start (`blockNumStart`)**: `21792420`  
  The block number at which the gas limit increase begins. this is february 7, 2024.
  
- **Initial Gas Limit (`initialGasLimit`)**: `30_000_000`  
  The initial gas limit at `blockNumStart` represents the current default gas limit of the Ethereum network, set to 30 million gas.

- **Rate of Increase (`r`)**: `6`  
  The gas limit will increase by 6 gas per block. This results in a slow growth rate culminating to reaching the cap in approximately 694 days.

- **Gas Limit Cap (`gasLimitCap`)**: `60_000_000`  
  The maximum gas limit is capped at 60 million gas, ensuring that the gas limit will not increase indefinitely and will prevent the network from being overwhelmed by excessively large blocks.

## **Rationale**

### **Starting Block Number**

The chosen block number (`21792420`) provides ample time to discuss and implement the gas limit increase strategy, additionally, it allows to happen with or slightly before the pectra hard fork.
  
### **Initial Gas Limit**

The initial gas limit is set to match the current default gas limit of `30_000_000`.
  
### **Rate of Increase**

A rate of `6` gas per block is chosen to triple the gas limit in approximately 47 months, which is equivalent to almost 2 years.

### **Gas Limit Cap**

- The gas limit cap of `60_000_000` provides a safeguard against the gas limit growing beyond what the network can safely handle.

## **Backwards Compatibility**

These parameters do not require any protocol changes or hard forks. They are fully backward compatible with the current Ethereum network architecture.

## **Security Considerations**

- The gradual nature of the gas limit increase prevents sudden surges in block size that could destabilize the network.
- The cap on the gas limit ensures that blocks do not become excessively large, which could lead to performance degradation or DOS vulnerabilities.
- Validators retain the ability to make adjustments to the gas limit in response to potential network attacks or performance issues.

## **Copyright**

Copyright and related rights waived via CC0 1.0 Universal.

</description>
        <pubDate>Fri, 18 Oct 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7790</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7790</guid>
      </item>
    
      <item>
        <title>GAS2ETH opcode</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7791-gas2eth-opcode/21418</comments>
        
        <description>## Abstract

This EIP introduces a new `GAS2ETH` opcode that enables the direct conversion of gas into ether (ETH).

## Motivation

This EIP is based on the premise that smart contract authors, compiler teams, and public goods projects in general should be compensated for their contributions. Moreover, their compensation should _scale_ with the usage of their contracts. A widely used and popular contract offers significant value to its users through its functionality and to the network by driving demand for blockspace — Ethereum&apos;s _raison d&apos;être_. This increased demand also benefits miners and validators, who are rewarded for executing these contracts.

Monetizing smart contracts in a scalable manner remains challenging at the time of this writing. This difficulty is evident from existence of many different monetization strategies employed across various smart contracts — ranging from fee structures to the issuance of tokens with &quot;tokenomics&quot; of varying levels of complexity. Additionally, many public goods projects struggle to secure funding.

Introducing the `GAS2ETH` opcode offers contract authors, as well as the tools they use, a new way to achieve their monetization objectives. By charging gas, they integrate with an established user experience that is both familiar and understood by users. The proposed instruction ensures that existing transaction creation and processing tools remain unchanged. Moreover, by charging gas, contract authors align economically with network activity; they benefit from higher compensation during periods of intense network usage and receive less when activity is low. This helps align the incentives of smart contract authors, validators, and the broader network.

## Specification

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

A new opcode, `GAS2ETH` (`0xFC`), is introduced to enable direct conversion of gas into ETH within the EVM. This opcode operates under a new budgeting mechanism: each transaction maintains a _global_ `GAS2ETH` budget initialized to the transaction gas limit (`tx.gas_limit`), and each call frame derives a _local_ allowance from the gas forwarded to it. These budgets cap the total amount of gas that can be converted into ETH, both per call frame and across the entire transaction.

### Execution Semantics

The `GAS2ETH` (`0xFC`) opcode executes according to the following rules:

- Pops two values from the stack: `addr` then `gas_amount`. If there are fewer than two values on the stack, the calling context MUST fail with stack underflow.
- Deducts `gas_amount` from both the current call frame&apos;s local `GAS2ETH` allowance and the transaction-global `GAS2ETH` budget.
  - If `gas_amount` is greater than the current call frame&apos;s local `GAS2ETH` allowance or the remaining transaction-global `GAS2ETH` budget, set `gas_amount` to `min(gas_amount, remaining_local_allowance, remaining_global_GAS2ETH_budget)`.
- Computes `wei_val` by multiplying `gas_amount` by the current transaction context&apos;s `gas_price` ([EELS][gasprice]).
- Endows the address `addr` with `wei_val` wei.
- Pushes `wei_val` onto the stack.

[gasprice]: https://github.com/ethereum/execution-specs/blob/98d6ddaaa709a2b7d0cd642f4cfcdadc8c0808e1/src/ethereum/cancun/vm/instructions/environment.py#L325

On reverts (e.g., through the `REVERT` opcode or any exceptional halt), any gas paid out via `GAS2ETH` MUST be refunded to both the transaction-global and the parent call frame&apos;s budgets.

Note that the transfer of `wei_val` to the target account cannot fail. In particular, the destination account code (if any) is not executed, or, if the account does not exist, the balance is still added to the given address `addr`.

Gas consumed by `GAS2ETH` does not affect the base fee, burn, block `gasUsed`, or the transaction fee. Instead, the ETH transfer represents a direct payment from the transaction signer (i.e. `tx.origin`) to the recipient address, outside the block reward and fee accounting mechanisms. This ensures no duplication of ETH between the `COINBASE` reward and the amount transferred via `GAS2ETH`.

### `GAS2ETH` Budgeting Model

A transaction maintains a single global `GAS2ETH` budget initialized to the transaction gas limit (`tx.gas_limit`). Each call frame also maintains a local allowance, derived automatically from the gas forwarded to it:

- On `CALL`, `CALLCODE`, or `STATICCALL`: `allowance = min(forwarded_gas, remaining_global_GAS2ETH_budget)`.
- On `DELEGATECALL`: the callee shares the caller&apos;s allowance.
- On revert: all `GAS2ETH` deductions within that call frame are refunded to both the transaction-global and parent frame&apos;s budgets.
- On normal return: any unused local allowance is returned to the transaction-global `GAS2ETH` budget.

This model ensures that untrusted callees cannot consume more `GAS2ETH` than the gas explicitly forwarded to them, while keeping total `GAS2ETH` creation bounded by the transaction&apos;s gas limit.

### Gas cost

The proposed cost of this opcode is identical to the recently proposed `PAY` opcode.

#### Constants

| Constant                   | Definition                |
| -------------------------- | ------------------------- |
| `WARM_STORAGE_READ_COST`   | [EIP-2929](/EIPs/EIPS/eip-2929) |
| `COLD_ACCOUNT_ACCESS_COST` | [EIP-2929](/EIPs/EIPS/eip-2929) |
| `GAS_NEW_ACCOUNT`          | [EELS][gna]               |
| `GAS_CALL_VALUE`           | [EELS][gcv]               |

[gna]: https://github.com/ethereum/execution-specs/blob/4d953035fb0cceda7cf21d71b2ab7a9a6f4632f0/src/ethereum/frontier/vm/gas.py#L52
[gcv]: https://github.com/ethereum/execution-specs/blob/4d953035fb0cceda7cf21d71b2ab7a9a6f4632f0/src/ethereum/frontier/vm/gas.py#L53

#### Gas calculation

- Is `addr` in `accessed_addresses`?
    - If yes, `WARM_STORAGE_READ_COST`;
    - Otherwise, `COLD_ACCOUNT_ACCESS_COST`.
- Does `addr` exist or is `val` zero?
    - If yes to either, zero;
    - Otherwise, `GAS_NEW_ACCOUNT`.
- Is `val` zero?
    - If yes, zero;
    - Otherwise, `GAS_CALL_VALUE`.

## Rationale

- `GAS2ETH` vs. pro-rata: The pro-rata model incentivizes inflating contract gas usage to artificially increase fees. In contrast, this proposal allows contract authors to charge their desired amount directly, eliminating the need for unnecessary gas consumption.
- Target address vs. simply increasing balance of the currently executing contract: Using a target address is more flexible, enabling contract authors to write more modular code and separate the concerns of fee collection from contract functionality. For instance, the contract may want to designate a specific recipient for fees without necessarily granting them direct withdrawal access.
- Charging gas instead of ETH: Charging ETH directly complicates the user experience and prevents contract authors from participating in fluctuations in gas demand directly.
- For the value of `gas_price`, use the same gas price as which is used to calculate the tx cost in ETH. This leads to the most consistent computation between `GAS2ETH` and the user&apos;s experience when creating a transaction.
- Separate budget: Having a separate budget prevents certain types of DoS attacks where usage of `GAS2ETH` can interfere with the actual budget needed for execution of the contract. (For example, a target contract can &quot;waste&quot; gas with `GAS2ETH`, resulting in the caller not having enough gas to finish execution). This also results in `GAS2ETH` usage not affecting the burn rate. The intuition is that, since it doesn&apos;t actually use computational resources (which gas normally &quot;accounts&quot; for), it shouldn&apos;t affect blockspace computations or the base fee.
- Budget being 100% of the gas limit: 100% of the gas limit is a &quot;natural&quot; bound on the gas used and provides some protection to the user from unbounded `GAS2ETH` spending. In the future, a new [EIP-2718](/EIPs/EIPS/eip-2718)-based transaction type could be added which includes an explicitly user-specified `GAS2ETH` budget.
- No exceptional halt when `gas_amount` exceeds the remaining budgets, both the current call frame&apos;s local `GAS2ETH` allowance and the transaction-global `GAS2ETH` budget. Since these budgets are not introspectable, the contract would otherwise have no way to gracefully avoid an exceptional halt.
- Bounding by execution gas ensures that untrusted callees cannot consume more `GAS2ETH` than the gas explicitly forwarded to them.

## Backwards Compatibility

No backward compatibility issues found.

## Test Cases

TBD

## Reference Implementation

TBD

## Security Considerations

Like the [`PAY`](/EIPs/EIPS/eip-5920) opcode and [beacon withdrawals](/EIPs/EIPS/eip-4895), `GAS2ETH` enables ETH transfers that occur without code execution in the recipient account. To prevent denial-of-service (DoS) attacks from untrusted callees, each call frame receives a local `GAS2ETH` allowance automatically derived from the gas _forwarded_ to it, while a transaction-global `GAS2ETH` budget enforces an overall cap equal to the transaction&apos;s gas limit. This ensures that:

- Callees cannot deplete the sender&apos;s `GAS2ETH` budget beyond the gas explicitly forwarded to them.
- Contracts calling into untrusted code remain robust, as the callee&apos;s `GAS2ETH` spending capacity is naturally limited by its gas stipend.
- The total ETH that can be created via `GAS2ETH` in a transaction is strictly bounded.

It&apos;s important to note that `GAS2ETH` introduces an economic incentive for malicious contracts to consume as much of their allowance as possible, converting previously non-profitable griefing vectors into potentially profitable ones. Contract authors SHOULD minimize forwarded gas and `GAS2ETH` exposure when interacting with untrusted code, similar to existing best practices for limiting gas stipends or ETH transfers.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 13 Aug 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7791</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7791</guid>
      </item>
    
      <item>
        <title>Verifiable logs</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7792-verifiable-logs/21424</comments>
        
        <description>## Abstract

This EIP defines a method to make the `eth_getLogs` JSON-RPC response verifiable.

## Motivation

The `eth_getLogs` endpoint is used by wallets to obtain the transaction history pertaining to an account or a topic. To verify correctness and completeness of the logs, a wallet would also have to obtain all block headers and check against their logs bloom. However, that mechanism is inefficient due to its high false positive rate and also involves an unpractical amount of network round trips. This EIP defines a replacement mechanism to efficiently and incrementally verify correctness and completeness of `eth_getLogs` responses.

## Specification

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

### Configuration

| Name | Value |
| - | - |
| `LOG_CONTRACT_ADDRESS` | `0xfffffffffffffffffffffffffffffffffffffffe` |

### Log accumulation

After executing all transactions of a block, commitments of all emitted logs are accumulated into the storage of `LOG_CONTRACT_ADDRESS`. The contract has no code, and its storage layout consists of three slots of type `mapping`. However to prevent [EIP-158](/EIPs/EIPS/eip-158) cleanup, the contract&apos;s nonce is set to `1` at the first write.

| Name | Value | Type |
| `LOG_ADDRESS_STORAGE_SLOT` | `0` | `mapping(address =&gt; bytes32)` |
| `LOG_TOPICS_STORAGE_SLOT` | `1` | `mapping(bytes32 =&gt; bytes32)` |
| `LOG_ADDRESS_TOPICS_STORAGE_SLOT` | `2` | `mapping(bytes32 =&gt; bytes32)` |

Additional metadata about each log&apos;s origin is mixed in to each `LogEntry`. The definition uses the `Log` SSZ type as defined in [EIP-6466](/EIPs/EIPS/eip-6466).

```python
class BlockMeta(Container):
    timestamp: uint64
    number: uint64

class LogMeta(Container):
    block: BlockMeta
    transaction_index: uint64

class Log(Container):
    address: ExecutionAddress
    topics: List[Bytes32, MAX_TOPICS_PER_LOG]
    data: ByteList[MAX_LOG_DATA_SIZE]

class LogEntry(Container):
    meta: LogMeta
    log: Log
```

The `hash_tree_root(LogEntry)` commitments are subsequently tracked as part of `LOG_CONTRACT_ADDRESS`.

```python
def accumulate_log(evm: Evm, entry_root: Bytes32, key: Bytes32):
    root = hashlib.sha256()
    root.update(entry_root)
    root.update(sload(evm.env.state, LOG_CONTRACT_ADDRESS, key))
    sstore(evm.env.state, LOG_CONTRACT_ADDRESS, key, root.digest())

def track_log(evm: Evm, entry: LogEntry) -&gt; None:
    entry_root = entry.hash_tree_root()

    # Allow verification via `address` filter
    key = keccak256(abi.encode(entry.log.address, LOG_ADDRESS_STORAGE_SLOT))
    accumulate_log(evm, entry_root, key)

    for topic in entry.log.topics:
        # Allow verification via `topics` filter
        key = keccak256(abi.encode(topic, LOG_TOPICS_STORAGE_SLOT))
        accumulate_log(evm, entry_root, key)

        # Allow verification via combined `address` + `topics` filter
        key = keccak256(abi.encode(entry.log.address, topic))
        key = keccak256(abi.encode(key, LOG_ADDRESS_TOPICS_STORAGE_SLOT))
        accumulate_log(evm, entry_root, key)
```

### JSON-RPC API

The `eth_getLogs` response format is extended to include:

- `blockTimestamp`: `QUANTITY` - The timestamp field of the block referred to by `blockHash`

### Verification

For `eth_getLogs(address, topics, fromBlock, toBlock)`, the response data can be verified for correctness and completion by obtaining:

1. `fromBlock` and `toBlock` block headers (validated against their known hashes)
2. `fromBlock`&apos;s `parentBlock` header (validated against `fromBlock.parentHash`)
3. Historical log accumulator at `parentBlock` based on given filters (validated with `eth_getProof`)
4. Log accumulator at `toBlock` based on given filters (validated with `eth_getProof`)

Starting from the historical log accumulator from (3), each response entry is applied to it in a way compatible with `accumulate_log` above. If the log accumulator ends up matching the value from (4), the response data is correct and `LogEntry` derived from it can be trusted.

## Rationale

Making the `eth_getLogs` response verifiable adds the necessary security attributes to enable wallets to transition away from relying on trusted data providers, ultimately improving the wallet&apos;s privacy guarantees as it is no longer subject to the privacy policy of any given provider.

### Gas cost

The gas cost produced by this scheme is significantly higher than what `LOG#` opcodes produce as of Prague, primarily due to the additional `SLOAD` / `SSTORE` and the double cost of `SHA256` opcodes compared to `KECCAK256` opcodes. The gas cost increases outweigh the savings from dropping logs blooms.

If the mechanism turns out to be prohibitively expensive even when optimized, it may be necessary to move the log accumulators to a separate optimized data structure (not in `state_root`), or to an out-of-protocol zk system. Even then, the gas cost for logs should still reflect the actual overall cost to update a typical out-of-protocol accumulator to deter against log spamming.

### Block number / transaction index in meta instead of hashes

As long as the accumulators are stored in the state trie, they cannot refer to the block hash as the block hash hashes over the state trie, producing a cyclic dependency. If an external system is used, hashes may be included as in that scenario the state root is not affected by the IVC.

## Backwards Compatibility

It is still possible to process `eth_getLogs` responses from trusted servers as is, without verifying them. Client applications with strict response validation may need to be updated to allow the additional `blockTimestamp` field.

## Security Considerations

This scheme reuses existing `eth_getProof` and SSZ Merkle proofs; it does not introduce new security risks.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 21 Oct 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7792</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7792</guid>
      </item>
    
      <item>
        <title>Conditional Transactions</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7793-asserttxindex-opcode/21513</comments>
        
        <description>## Abstract

This EIP proposes to add a new transaction format for &quot;conditional transactions&quot;, that are only valid at a specified slot and index within the block. A new opcode `TXINDEX` is introduced to expose the conditional transaction index onchain.

## Motivation

The proposal aims to improve support for encrypted mempools. Transactions in an encrypted mempool are ordered while the transactions are encrypted, before being decrypted and included onchain at the top of the block. If the builder does not respect the order when including the decrypted transactions then they could frontrun decrypted transactions. The new transaction type can be used to make this impossible; if a decrypted transaction is not included at the correct index, it will be invalid.

## Specification

### Parameters

| Constant | Value |
| - | - |
| `COND_TX_TYPE` | `Bytes1(0x05)` |
| `TXINDEX_OPCODE_BYTE` | `Bytes1(0x4c)` |
| `TXINDEX_OPCODE_GAS` | `2` |

### Conditional Transaction Type

We introduce a new type of [EIP-2718](/EIPs/EIPS/eip-2718) transaction, &quot;conditional transactions&quot;, where the `TransactionType` is `COND_TX_TYPE` and the `TransactionPayload` is the RLP serialization of the following `TransactionPayloadBody`:

```
[chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to, value, data, access_list, max_fee_per_blob_gas, blob_versioned_hashes, conditional_slot, conditional_tx_index, y_parity, r, s]
```

The fields `chain_id`, `nonce`, `max_priority_fee_per_gas`, `max_fee_per_gas`, `gas_limit`, `to`, `value`, `data`, `access_list`, `max_fee_per_blob_gas` follow the same semantics as [EIP-4844](/EIPs/EIPS/eip-4844). The field `blob_versioned_hashes` is the same except that the list may be empty for a conditional transaction.

The fields `conditional_slot` and `conditional_tx_index` are both `uint64` and specify the slot and transaction index in which this transaction should be considered valid respectively. In order to verify that `conditional_slot` is correct, [EIP-7843](/EIPs/EIPS/eip-7843) is a dependency, as this adds the slot number to the header. For both fields `-1` is used as a sentinel value for which the slot or transaction index check will not take place.

#### Signature

The signature values `y_parity`, `r`, and `s` are calculated by constructing a secp256k1 signature over the following digest:

`keccak256(COND_TX_TYPE || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to, value, data, access_list, max_fee_per_blob_gas, blob_versioned_hashes, conditional_slot, conditional_tx_index]))`.

### TXINDEX opcode

A new opcode `TXINDEX` is introduced at `TXINDEX_OPCODE_BYTE`.

#### Output

One element `TransactionIndex` is added to the stack. `TransactionIndex` is a `uint64` in big endian encoding. It is equal to `conditional_tx_index` if the current transaction is a conditional transaction, and `-1` otherwise.

#### Gas Cost

The gas cost for `TXINDEX` is a fixed fee of `TXINDEX_OPCODE_GAS`.

## Rationale

### Transaction Type

An alternative design could simply return the current transaction index without adding a new transaction type. Adding a new transaction type is favoured as it means that the expected transaction index must be declared statically upfront, rather than allowing dynamic behaviour based on the returned transaction index. This prevents complex constraints being imposed that makes it difficult to build a block.

### Gas Price

The opcode is priced to match similar opcodes in the `W_base` set.

## Backwards Compatibility

No backward compatibility issues found.

## Test Cases

N/A

## Security Considerations

None.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 17 Oct 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7793</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7793</guid>
      </item>
    
      <item>
        <title>Grant Registry</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7794-grant-registry/20791</comments>
        
        <description>## Abstract

This proposal introduces a Grant Registry contract intended for managing financial, research, or project-based grants that provide funding for projects across multiple blockchains. The contract standardizes the registration, management, and tracking of these grants by organizing data into distinct categories, enabling clear separation between immutable fields and mutable fields. It supports modular disbursement tracking and allows for external links to off-chain documentation. This registry emits lifecycle events, enabling external protocols to efficiently access grant data, which promotes transparency, interoperability, and enhanced insights into grant program performance.

## Motivation

The Ethereum ecosystem currently lacks a standardized way to manage and track grants across different chains and programs, leading to inefficiencies and fragmentation. Each grant program has its own distinct interface, processes, and management mechanisms, which creates barriers for both funders and grantees. These issues hinder transparency, complicate the tracking of fund disbursements, and make it difficult to evaluate the overall effectiveness of grant programs across different networks.

The lack of interoperability between grant programs further exacerbates the problem, as projects and contributors often work across multiple blockchains. This makes it challenging to aggregate data, monitor milestones, and assess grantee performance in a consistent manner.

The Grant Registry contract solves these issues by introducing a unified standard that ensures all grants can be registered, tracked, and managed consistently, regardless of the underlying chain or program. This approach not only simplifies the lifecycle management of grants but also fosters better collaboration between communities, allowing for more competitiveness and better tracking of progress. Additionally, the standardization of data opens the door for more insightful analytics, enabling protocols to measure the impact of grants in a much more streamlined and transparent way.

## Specification

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

### **Contract Interface**

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.20;

interface IGrantRegistry {
  /**
   * @dev Thrown when the community name length is invalid (e.g., too short or too long).
   */
  error InvalidCommunityNameLength();

  /**
   * @dev Thrown when the caller is not the current grant manager.
   */
  error InvalidGrantManager();

  /**
   * @dev Thrown when a grant is already registered with the provided ID.
   */
  error GrantAlreadyRegistered();

  /**
   * @dev Thrown when attempting to add a grantee that is already present in the set.
   */
  error GranteeAlreadyAdded();

  /**
   * @dev Thrown when attempting to remove a grantee that is not found in the set.
   */
  error GranteeNotFound();

  /**
   * @dev Thrown when attempting to add or reference an invalid external link.
   */
  error InvalidExternalLink();

  /**
   * @dev Thrown when an invalid index is provided (e.g., out of bounds for an array).
   */
  error InvalidIndex();

  /**
   * @dev Thrown when a milestone date is invalid (e.g., earlier than the grant&apos;s start date).
   */
  error InvalidStartDate();

  /**
   * @dev Thrown when attempting to add a milestone date that is already present.
   */
  error MilestoneDateAlreadyAdded();

  /**
   * @dev Thrown when attempting to remove or reference a milestone date that is not found.
   */
  error MilestoneDateNotFound();

  /**
   * @dev Emitted when a new grant is registered.
   * @param grantId The unique identifier for the grant.
   * @param id The grant&apos;s unique numeric ID.
   * @param chainid The chain ID where the grant is registered.
   * @param community The name of the community that issued the grant.
   * @param grantManager The address of the grant manager.
   */
  event GrantRegistered(
    bytes32 indexed grantId,
    uint256 indexed id,
    uint256 chainid,
    string indexed community,
    address grantManager
  );

  /**
   * @dev Emitted when the ownership of a grant is transferred.
   * @param grantId The unique identifier of the grant.
   * @param newGrantManager The address of the new grant manager.
   */
  event OwnershipTransferred(
    bytes32 indexed grantId,
    address indexed newGrantManager
  );

  /**
   * @dev Emitted when a new grantee is added to the grant.
   * @param grantId The unique identifier of the grant.
   * @param grantee The address of the new grantee.
   */
  event GranteeAdded(bytes32 indexed grantId, address indexed grantee);

  /**
   * @dev Emitted when a grantee is removed from the grant.
   * @param grantId The unique identifier of the grant.
   * @param grantee The address of the removed grantee.
   */
  event GranteeRemoved(bytes32 indexed grantId, address indexed grantee);

  /**
   * @dev Emitted when the start date of a grant is set.
   * @param grantId The unique identifier of the grant.
   * @param startDate The timestamp representing the start date.
   */
  event StartDateSet(bytes32 indexed grantId, uint256 startDate);

  /**
   * @dev Emitted when a new milestone date is added to the grant.
   * @param grantId The unique identifier of the grant.
   * @param milestoneDate The timestamp of the added milestone.
   */
  event MilestoneDateAdded(bytes32 indexed grantId, uint256 milestoneDate);

  /**
   * @dev Emitted when a milestone date is removed from the grant.
   * @param grantId The unique identifier of the grant.
   * @param milestoneDate The timestamp of the removed milestone.
   */
  event MilestoneDateRemoved(bytes32 indexed grantId, uint256 milestoneDate);

  /**
   * @dev Emitted when a disbursement is added to a milestone.
   * @param grantId The unique identifier of the grant.
   * @param milestoneDate The timestamp of the milestone.
   * @param fundingToken The token used for the disbursement.
   * @param fundingAmount The amount of the disbursement.
   */
  event DisbursementAdded(
    bytes32 indexed grantId,
    uint256 milestoneDate,
    address indexed fundingToken,
    uint256 fundingAmount
  );

  /**
   * @dev Emitted when a disbursement is removed from a milestone.
   * @param grantId The unique identifier of the grant.
   * @param milestoneDate The timestamp of the milestone.
   */
  event DisbursementRemoved(bytes32 indexed grantId, uint256 milestoneDate);

  /**
   * @dev Emitted when a disbursement status is updated.
   * @param grantId The unique identifier of the grant.
   * @param milestoneDate The timestamp of the milestone.
   * @param isDisbursed Boolean indicating if the disbursement has been made.
   */
  event DisbursementMade(
    bytes32 indexed grantId,
    uint256 milestoneDate,
    bool isDisbursed
  );

  /**
   * @dev Emitted when an external link is added to the grant.
   * @param grantId The unique identifier of the grant.
   * @param link The external URL added.
   */
  event ExternalLinkAdded(bytes32 indexed grantId, string link);

  /**
   * @dev Emitted when an external link is removed from the grant.
   * @param grantId The unique identifier of the grant.
   * @param link The external URL removed.
   */
  event ExternalLinkRemoved(bytes32 indexed grantId, string link);

  /**
   * @dev Registers a new grant with the provided details. `grantId` is generated by hashing the grant
   * details and the current timestamp.
   *
   * Requirements:
   *
   * - The `grantManager` address must not be the zero address.
   * - The `community` name must not be empty.
   * - The grant must not already be registered.
   *
   * Emits a {GrantRegistered} event.
   *
   * @param id The unique identifier for the grant program.
   * @param chainid The chain ID where the grant is being registered.
   * @param community The name of the community or protocol issuing the grant.
   * @param grantManager The address of the grant manager.
   * @return The generated `grantId` as a bytes32 value.
   */
  function registerGrant(
    uint256 id,
    uint256 chainid,
    string memory community,
    address grantManager
  ) external returns (bytes32);

  /**
   * @dev Transfers ownership of the grant to a new grant manager.
   *
   * Requirements:
   *
   * - The caller must be the current grant manager.
   * - The `newGrantManager` address must not be the zero address.
   *
   * Emits an {OwnershipTransferred} event.
   *
   * @param grantId The unique identifier of the grant.
   * @param newGrantManager The address of the new grant manager.
   */
  function transferOwnership(bytes32 grantId, address newGrantManager) external;

  /**
   * @dev Adds a new grantee to the grant.
   *
   * Requirements:
   *
   * - The caller must be the current grant manager.
   * - The `grantee` address must not be the zero address.
   *
   * Emits a {GranteeAdded} event.
   *
   * @param grantId The unique identifier of the grant.
   * @param grantee The address of the grantee to be added.
   */
  function addGrantee(bytes32 grantId, address grantee) external;

  /**
   * @dev Removes an existing grantee from the grant.
   *
   * Requirements:
   *
   * - The caller must be the current grant manager.
   * - The `grantee` address must be present in the grant.
   *
   * Emits a {GranteeRemoved} event.
   *
   * @param grantId The unique identifier of the grant.
   * @param grantee The address of the grantee to be removed.
   */
  function removeGrantee(bytes32 grantId, address grantee) external;

  /**
   * @dev Sets the start date for the grant.
   *
   * Requirements:
   *
   * - The caller must be the current grant manager.
   *
   * Emits a {StartDateSet} event.
   *
   * @param grantId The unique identifier of the grant.
   * @param startDate The timestamp representing the start date.
   */
  function setStartDate(bytes32 grantId, uint256 startDate) external;

  /**
   * @dev Adds a new milestone date for the grant.
   *
   * Requirements:
   *
   * - The caller must be the current grant manager.
   * - The milestone date must not already exist in the grant.
   *
   * Emits a {MilestoneDateAdded} event.
   *
   * @param grantId The unique identifier of the grant.
   * @param milestoneDate The timestamp representing the milestone date.
   */
  function addMilestoneDate(bytes32 grantId, uint256 milestoneDate) external;

  /**
   * @dev Removes a milestone date from the grant.
   *
   * Requirements:
   *
   * - The caller must be the current grant manager.
   * - The milestone date must exist in the grant.
   *
   * Emits a {MilestoneDateRemoved} event.
   *
   * @param grantId The unique identifier of the grant.
   * @param milestoneDate The timestamp representing the milestone date to be removed.
   */
  function removeMilestoneDate(bytes32 grantId, uint256 milestoneDate) external;

  /**
   * @dev Ovewrites a disbursement for a specific milestone.
   *
   * Requirements:
   *
   * - The caller must be the current grant manager.
   * - The milestone date must exist in the grant.
   *
   * Emits a {DisbursementAdded} event.
   *
   * @param grantId The unique identifier of the grant.
   * @param milestoneDate The milestone date associated with the disbursement.
   * @param fundingToken The address of the token used for funding.
   * @param fundingAmount The amount of tokens to be disbursed.
   */
  function addDisbursement(
    bytes32 grantId,
    uint256 milestoneDate,
    address fundingToken,
    uint256 fundingAmount
  ) external;

  /**
   * @dev Removes a disbursement for a specific milestone.
   *
   * Requirements:
   *
   * - The caller must be the current grant manager.
   * - The milestone date must exist in the grant.
   *
   * Emits a {DisbursementRemoved} event.
   *
   * @param grantId The unique identifier of the grant.
   * @param milestoneDate The milestone date associated with the disbursement.
   */
  function removeDisbursement(bytes32 grantId, uint256 milestoneDate) external;

  /**
   * @dev Updates the disbursement status for a specific milestone.
   *
   * Requirements:
   *
   * - The caller must be the current grant manager.
   * - The milestone date must exist in the grant.
   *
   * Emits a {DisbursementMade} event.
   *
   * @param grantId The unique identifier of the grant.
   * @param milestoneDate The milestone date associated with the disbursement.
   * @param isDisbursed A boolean value indicating if the disbursement has been made.
   */
  function setDisbursementStatus(
    bytes32 grantId,
    uint256 milestoneDate,
    bool isDisbursed
  ) external;

  /**
   * @dev Adds an external link related to the grant.
   *
   * Requirements:
   *
   * - The caller must be the current grant manager.
   * - The link must not be empty.
   *
   * Emits an {ExternalLinkAdded} event.
   *
   * @param grantId The unique identifier of the grant.
   * @param link The external URL to be added.
   */
  function addExternalLink(bytes32 grantId, string memory link) external;

  /**
   * @dev Removes an external link associated with the grant.
   *
   * Requirements:
   *
   * - The caller must be the current grant manager.
   * - The index must be within the bounds of the external links array.
   *
   * Emits an {ExternalLinkRemoved} event.
   *
   * @param grantId The unique identifier of the grant.
   * @param index The index of the external link to be removed.
   */
  function removeExternalLink(bytes32 grantId, uint256 index) external;

  /**
   * @dev Retrieves details of a specific grant by its ID
   * @param grantId The unique identifier of the grant
   * @return The `Grant` struct containing id, chainid, and community label
   */
  function getGrant(bytes32 grantId) external view returns (Grant memory);

  /**
   * @dev Retrieves the current grant manager for a specific grant
   * @param grantId The unique identifier of the grant
   * @return The address of the grant manager
   */
  function getGrantManager(bytes32 grantId) external view returns (address);

  /**
   * @dev Retrieves the list of grantees associated with a specific grant
   * @param grantId The unique identifier of the grant
   * @return An array of addresses representing the grantees
   */
  function getGrantees(
    bytes32 grantId
  ) external view returns (address[] memory);

  /**
   * @dev Retrieves the start date and list of milestone dates for a specific grant
   * @param grantId The unique identifier of the grant
   * @return The start date and an array of milestone dates
   */
  function getMilestonesDates(
    bytes32 grantId
  ) external view returns (uint256, uint256[] memory);

  /**
   * @dev Retrieves the disbursement details for a specific milestone in a grant
   * @param grantId The unique identifier of the grant
   * @param milestoneDate The date of the milestone for which disbursement details are requested
   * @return The `Disbursements` struct containing the token address, funding amount, and disbursement status
   */
  function getDisbursement(
    bytes32 grantId,
    uint256 milestoneDate
  ) external view returns (Disbursements memory);

  /**
   * @dev Retrieves the list of external links associated with a specific grant
   * @param grantId The unique identifier of the grant
   * @return An array of strings representing the external links
   */
  function getExternalLinks(
    bytes32 grantId
  ) external view returns (string[] memory);
}
```

When calling the `registerGrant` function:

- The `grantManager` **MUST** submit a valid grantManager address that is not the zero address.
- The `community` label **MUST** be a non-empty string.
- The `grant` ID **MUST** be unique and not already registered in the system.

When editing overall grant details:

- The `grantManager` **MUST** be the current grant manager to make changes to the grant.

When adding a `milestoneDate`:

- The `milestoneDate` **MUST** not exist in the milestonesDates set.

When editing disbursments:

- The `milestoneDate` **MUST** be a valid milestone date associated with the grant.

When adding `externalLinks`:

- The string **MUST** not be empty.


## Rationale

The design of this Grant Registry Contract is driven by the need for a flexible and modular system that supports a wide range of grant programs across different chains. The rationale for the key design decisions is outlined below:

1. Separation of Fields: The division of fields into different categories, such as identification, grant data, and disbursement-related information, allows for a more efficient use of on-chain storage. Immutable fields like id, chainid, and community are kept separate from mutable fields, ensuring that core identification elements remain unchanged, while other aspects like milestones and participants can be updated throughout the grant lifecycle.

2. Modular Disbursement Handling: Not all grant programs will choose to perform disbursements on-chain. By allowing disbursements to be managed through external links, the contract remains modular and adaptable to different use cases. Programs that prefer to handle disbursements off-chain can still use the registry for status tracking, ensuring broad applicability across different ecosystems.

3. Dynamic Team Management: The participants structure uses EnumerableSet for grantees, allowing for team-based grants. This feature facilitates tracking of contributions and adjustments to the grant team over time, enabling more comprehensive reputation systems and transparency.

This design aims to create a scalable, efficient system that can evolve with the needs of different grant programs, while maintaining key benefits like transparency, modularity, and low gas usage.

## Backwards Compatibility

No backward compatibility issues found.

## Reference Implementation

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.20;

import { IGrantRegistry } from &quot;./IGrantRegistry.sol&quot;;
import { EnumerableSet } from &quot;@openzeppelin/contracts/utils/structs/EnumerableSet.sol&quot;;

contract GrantRegistry is IGrantRegistry {
  using EnumerableSet for EnumerableSet.AddressSet;
  using EnumerableSet for EnumerableSet.UintSet;

  /**
   * @dev Mapping to store the details of each grant, keyed by its unique grantId.
   */
  mapping(bytes32 =&gt; Grant) private _grants;

  /**
   * @dev Stores information about the participants in each grant (manager and grantees), keyed by the grantId.
   * This mapping allows tracking of the grant manager and the associated grantees for each grant.
   */
  mapping(bytes32 =&gt; Participants) private _participants;

  /**
   * @dev Stores milestone-related data for each grant, keyed by the grantId.
   * This includes the start date, milestone dates, and disbursements related to each milestone.
   */
  mapping(bytes32 =&gt; Milestones) private _milestones;

  /**
   * @dev Stores external links related to each grant, such as proposal URLs or related documentation, keyed by grantId.
   * External links provide references to off-chain information about the grant.
   */
  mapping(bytes32 =&gt; string[]) private _externalLinks;

  /**
   * @dev See {IGrantRegistry-registerGrant}.
   */
  function registerGrant(
    uint256 id,
    uint256 chainid,
    string memory community,
    address grantManager
  ) external returns (bytes32) {
    bytes32 grantId = keccak256(
      abi.encodePacked(id, chainid, community, block.timestamp)
    );

    if (grantManager == address(0)) revert InvalidGrantManager();
    if (bytes(community).length == 0) revert InvalidCommunityNameLength();
    if (bytes(_grants[grantId].community).length &gt; 0)
      revert GrantAlreadyRegistered();

    _grants[grantId] = Grant(id, chainid, community);
    _participants[grantId].grantManager = grantManager;

    emit GrantRegistered(grantId, id, chainid, community, grantManager);
    return grantId;
  }

  /**
   * @dev See {IGrantRegistry-transferOwnership}.
   */
  function transferOwnership(
    bytes32 grantId,
    address newGrantManager
  ) external {
    _requireManager(grantId);
    if (newGrantManager == address(0)) revert InvalidGrantManager();
    _participants[grantId].grantManager = newGrantManager;
    emit OwnershipTransferred(grantId, newGrantManager);
  }

  /**
   * @dev See {IGrantRegistry-addGrantee}.
   */
  function addGrantee(bytes32 grantId, address grantee) external {
    _requireManager(grantId);
    if (grantee == address(0)) revert InvalidGrantManager();
    bool success = _participants[grantId].grantees.add(grantee);
    if (!success) revert GranteeAlreadyAdded();
    emit GranteeAdded(grantId, grantee);
  }

  /**
   * @dev See {IGrantRegistry-removeGrantee}.
   */
  function removeGrantee(bytes32 grantId, address grantee) external {
    _requireManager(grantId);
    bool success = _participants[grantId].grantees.remove(grantee);
    if (!success) revert GranteeNotFound();
    emit GranteeRemoved(grantId, grantee);
  }

  /**
   * @dev See {IGrantRegistry-setStartDate}.
   */
  function setStartDate(bytes32 grantId, uint256 startDate) external {
    _requireManager(grantId);
    _milestones[grantId].startDate = startDate;
    emit StartDateSet(grantId, startDate);
  }

  /**
   * @dev See {IGrantRegistry-addMilestoneDate}.
   */
  function addMilestoneDate(bytes32 grantId, uint256 milestoneDate) external {
    _requireManager(grantId);
    bool success = _milestones[grantId].milestonesDates.add(milestoneDate);
    if (!success) revert MilestoneDateAlreadyAdded();
    emit MilestoneDateAdded(grantId, milestoneDate);
  }

  /**
   * @dev See {IGrantRegistry-removeMilestoneDate}.
   */
  function removeMilestoneDate(
    bytes32 grantId,
    uint256 milestoneDate
  ) external {
    _requireManager(grantId);
    bool success = _milestones[grantId].milestonesDates.remove(milestoneDate);
    if (!success) revert MilestoneDateNotFound();
    emit MilestoneDateRemoved(grantId, milestoneDate);
  }

  /**
   * @dev See {IGrantRegistry-addDisbursement}.
   */
  function addDisbursement(
    bytes32 grantId,
    uint256 milestoneDate,
    address fundingToken,
    uint256 fundingAmount
  ) external {
    _requireManager(grantId);
    _requireMilestoneDate(grantId, milestoneDate);
    _milestones[grantId].disbursements[milestoneDate] = Disbursements(
      fundingToken,
      fundingAmount,
      false
    );
    emit DisbursementAdded(grantId, milestoneDate, fundingToken, fundingAmount);
  }

  /**
   * @dev See {IGrantRegistry-removeDisbursement}.
   */
  function removeDisbursement(bytes32 grantId, uint256 milestoneDate) external {
    _requireManager(grantId);
    _requireMilestoneDate(grantId, milestoneDate);
    delete _milestones[grantId].disbursements[milestoneDate];
    emit DisbursementRemoved(grantId, milestoneDate);
  }

  /**
   * @dev See {IGrantRegistry-setDisbursementStatus}.
   */
  function setDisbursementStatus(
    bytes32 grantId,
    uint256 milestoneDate,
    bool isDisbursed
  ) external {
    _requireManager(grantId);
    _requireMilestoneDate(grantId, milestoneDate);
    _milestones[grantId].disbursements[milestoneDate].isDisbursed = isDisbursed;
    emit DisbursementMade(grantId, milestoneDate, isDisbursed);
  }

  /**
   * @dev See {IGrantRegistry-addExternalLink}.
   */
  function addExternalLink(bytes32 grantId, string memory link) external {
    _requireManager(grantId);
    if (bytes(link).length == 0) revert InvalidExternalLink();
    _externalLinks[grantId].push(link);
    emit ExternalLinkAdded(grantId, link);
  }

  /**
   * @dev See {IGrantRegistry-removeExternalLink}.
   */
  function removeExternalLink(bytes32 grantId, uint256 index) external {
    _requireManager(grantId);
    if (index &gt;= _externalLinks[grantId].length) revert InvalidIndex();
    string memory link = _externalLinks[grantId][index];
    _externalLinks[grantId][index] = _externalLinks[grantId][
      _externalLinks[grantId].length - 1
    ];
    _externalLinks[grantId].pop();
    emit ExternalLinkRemoved(grantId, link);
  }

  /**
   * @dev Ensures that the caller is the grant manager for the given grantId.
   * Reverts with `InvalidGrantManager` if the caller is not the grant manager.
   * @param grantId The unique identifier of the grant being checked.
   */
  function _requireManager(bytes32 grantId) internal view {
    if (msg.sender != _participants[grantId].grantManager)
      revert InvalidGrantManager();
  }

  /**
   * @dev Ensures that the milestone date is present in the grant.
   * Reverts with `MilestoneDateNotFound` if the milestone date is not present.
   * @param grantId The unique identifier of the grant being checked.
   * @param milestoneDate The milestone date being checked.
   */
  function _requireMilestoneDate(
    bytes32 grantId,
    uint256 milestoneDate
  ) internal view {
    if (!_milestones[grantId].milestonesDates.contains(milestoneDate))
      revert MilestoneDateNotFound();
  }

  /**
   * @dev See {IGrantRegistry-getGrant}.
   */
  function getGrant(bytes32 grantId) external view returns (Grant memory) {
    return _grants[grantId];
  }

  /**
   * @dev See {IGrantRegistry-getGrantManager}.
   */
  function getGrantManager(bytes32 grantId) external view returns (address) {
    return _participants[grantId].grantManager;
  }

  /**
   * @dev See {IGrantRegistry-getGrantees}.
   */
  function getGrantees(
    bytes32 grantId
  ) external view returns (address[] memory) {
    return _participants[grantId].grantees.values();
  }

  /**
   * @dev See {IGrantRegistry-getMilestonesDates}.
   */
  function getMilestonesDates(
    bytes32 grantId
  ) external view returns (uint256, uint256[] memory) {
    return (
      _milestones[grantId].startDate,
      _milestones[grantId].milestonesDates.values()
    );
  }

  /**
   * @dev See {IGrantRegistry-getDisbursement}.
   */
  function getDisbursement(
    bytes32 grantId,
    uint256 milestoneDate
  ) external view returns (Disbursements memory) {
    return _milestones[grantId].disbursements[milestoneDate];
  }

  /**
   * @dev See {IGrantRegistry-getExternalLinks}.
   */
  function getExternalLinks(
    bytes32 grantId
  ) external view returns (string[] memory) {
    return _externalLinks[grantId];
  }
}
```

Key considerations for this implementation:

1. Gas Optimization: `grantId` utilizes immutable identification fields to minimize large gas consumption. This ensures that essential information is used with keccak256 efficiently, while the mutable data can be submitted or modified later as the project evolves without affecting the identification method.

2. Use of EnumerableSet: By leveraging EnumerableSet for managing participants and milestone dates, the contract allows for dynamic updates, such as team composition changes or new milestones. This approach offers flexibility without sacrificing the ability to efficiently track changes.

## Security Considerations

No security concerns were found.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 22 Oct 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7794</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7794</guid>
      </item>
    
      <item>
        <title>Wallet Call Token Capabilities</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7795-wallet-call-token-capabilities/21426</comments>
        
        <description>## Abstract

This ERC extends [EIP-5792](/EIPs/EIPS/eip-5792) by defining capabilities that allow dApps to specify common token prerequisites for transactions, such as having certain [ERC-20](/EIPs/EIPS/eip-20), [ERC-721](/EIPs/EIPS/eip-721), or [ERC-1155](/EIPs/EIPS/eip-1155) tokens. Wallets can then help users meet these requirements before executing the transactions.

## Motivation

It is fairly common for dApps to reside only on one network, but this comes at the cost of shrinking the direct liquidity that these dApps can access. This happens because most users only have funds on a limited number of networks. As the number of networks grows, the likelihood of intersection between the networks chosen by the dApp and the user decreases.

Given that dApps don&apos;t have a way of communicating with the wallet about their &quot;final intent&quot;, they can only use transaction requests to communicate the last action that the user should take. However, it is up to the user to &quot;guess&quot; what prior actions need to be executed to fulfill the prerequisites of that final action.

This guessing may involve consolidating funds into a single network or exchanging assets into another asset accepted by the dApp. This is a cumbersome process for the user and results in a highly degraded UX.

## Specification

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

This ERC extends [EIP-5792](/EIPs/EIPS/eip-5792) by adding new capabilities that can be used with the `wallet_sendCalls` and `wallet_getCapabilities` methods. These capabilities allow specifying different types of transaction requirements for common token standards that wallets can handle.

DApps **MAY** opt out of using this feature if they wish to handle requirement fulfillment themselves.

### ERC-20 Minimum Balance Capability

A dApp can use the `erc20MinBalance` capability in a `wallet_sendCalls` request to request that a wallet ensure the owner has a minimum balance of a specified [ERC-20](/EIPs/EIPS/eip-20) token.

#### `wallet_getCapabilities` Response

Schema:

```typescript
type Erc20MinBalanceCapability = {
  supported: boolean;
  versions: string[];
}
```

Example:

```json
{
  &quot;0x1&quot;: {
    &quot;erc20MinBalance&quot;: {
      &quot;supported&quot;: true,
      &quot;versions&quot;: [&quot;1.0&quot;]
    }
  }
}
```

#### `wallet_sendCalls` Request

Version 1.0 Schema:

```typescript
type Erc20MinBalanceParams = {
  version: string;
  chainId: `0x${string}`; // Hex chain id
  owner: `0x${string}`; // Address
  token: `0x${string}`; // Address
  minAmount: `0x${string}`; // Hex value
};
```

This capability requests that the `owner` address **MUST** have a balance of at least `minAmount` of `token` on `chainId` before the transaction is executed.

Example:

```json
[
  {
    &quot;version&quot;: &quot;1.0&quot;,
    &quot;from&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
    &quot;calls&quot;: [
      {
        &quot;to&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
        &quot;value&quot;: &quot;0x00&quot;,
        &quot;data&quot;: &quot;0x...&quot;,
        &quot;chainId&quot;: &quot;0x01&quot;,
      }
    ],
    &quot;capabilities&quot;: {
      &quot;erc20MinBalance&quot;: {
        &quot;version&quot;: &quot;1.0&quot;,
        &quot;chainId&quot;: &quot;0x01&quot;,
        &quot;owner&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
        &quot;token&quot;: &quot;0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&quot;,
        &quot;minAmount&quot;: &quot;0x0f4240&quot;
      }
    }
  }
]
```

### ERC-20 Minimum Allowance Capability

A dApp can use the `erc20MinAllowance` capability in a `wallet_sendCalls` request to request that a wallet ensure the owner has a minimum allowance of a specified [ERC-20](/EIPs/EIPS/eip-20) token.
Note this capability does not imply that the owner has a balance of the token, only that the allowance is equal to or greater than the specified amount.

#### `wallet_getCapabilities` Response

Schema:

```typescript
type Erc20MinAllowanceCapability = {
  supported: boolean;
  versions: string[];
}
```

Example:

```json
{
  &quot;0x1&quot;: {
    &quot;erc20MinAllowance&quot;: {
      &quot;supported&quot;: true,
      &quot;versions&quot;: [&quot;1.0&quot;]
    }
  }
}
```

#### `wallet_sendCalls` Request

Version 1.0 Schema:

```typescript
type Erc20MinAllowanceParams = {
  version: string;
  chainId: `0x${string}`; // Hex chain id
  owner: `0x${string}`; // Address
  operator: `0x${string}`; // Address
  token: `0x${string}`; // Address
  minAmount: `0x${string}`; // Hex value
};
```

This capability requests that the `owner` address **MUST** have an allowance of at least `minAmount` of `token` for `operator` on `chainId` before the transaction is executed.

Example:

```json
[
  {
    &quot;version&quot;: &quot;1.0&quot;,
    &quot;from&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
    &quot;calls&quot;: [
      {
        &quot;to&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
        &quot;value&quot;: &quot;0x00&quot;,
        &quot;data&quot;: &quot;0x...&quot;,
        &quot;chainId&quot;: &quot;0x01&quot;,
      }
    ],
    &quot;capabilities&quot;: {
      &quot;erc20MinAllowance&quot;: {
        &quot;version&quot;: &quot;1.0&quot;,
        &quot;chainId&quot;: &quot;0x01&quot;,
        &quot;owner&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
        &quot;token&quot;: &quot;0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&quot;,
        &quot;operator&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
        &quot;minAmount&quot;: &quot;0x0f4240&quot;
      }
    }
  }
]
```

### ERC-721 Ownership Capability

A dApp can use the `erc721Ownership` capability in a `wallet_sendCalls` request to request that a wallet ensure the owner has ownership of a specified [ERC-721](/EIPs/EIPS/eip-721) token.

#### `wallet_getCapabilities` Response

Schema:

```typescript
type Erc721OwnershipCapability = {
  supported: boolean;
  versions: string[];
}
```

Example:

```json
{
  &quot;0x1&quot;: {
    &quot;erc721Ownership&quot;: {
      &quot;supported&quot;: true,
      &quot;versions&quot;: [&quot;1.0&quot;]
    }
  }
}
```

#### `wallet_sendCalls` Request

Version 1.0 Schema:

```typescript
type Erc721OwnershipParams = {
  version: string;
  chainId: `0x${string}`; // Hex chain id
  owner: `0x${string}`; // Address
  token: `0x${string}`; // Address
  tokenId: `0x${string}`; // Hex value
};
```

This capability requests that the `owner` address **MUST** have ownership of `tokenId` of `token` on `chainId` before the transaction is executed.

Example:

```json
[
  {
    &quot;version&quot;: &quot;1.0&quot;,
    &quot;from&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
    &quot;calls&quot;: [
      {
        &quot;to&quot;: &quot;0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d&quot;,
        &quot;value&quot;: &quot;0x00&quot;,
        &quot;data&quot;: &quot;0x...&quot;,
        &quot;chainId&quot;: &quot;0x01&quot;,
      }
    ],
    &quot;capabilities&quot;: {
      &quot;erc721Ownership&quot;: {
        &quot;version&quot;: &quot;1.0&quot;,
        &quot;chainId&quot;: &quot;0x01&quot;,
        &quot;owner&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
        &quot;token&quot;: &quot;0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d&quot;,
        &quot;tokenId&quot;: &quot;0x10&quot;
      }
    }
  }
]
```

### ERC-721 Approval Capability

A dApp can use the `erc721Approval` capability in a `wallet_sendCalls` request to request that a wallet ensure the owner has approved a specified [ERC-721](/EIPs/EIPS/eip-721) token.
Note this capability does not imply that the owner has a balance of the token, only that the allowance is equal to or greater than the specified amount.

#### `wallet_getCapabilities` Response

Schema:

```typescript
type Erc721ApprovalCapability = {
  supported: boolean;
  versions: string[];
}
```

Example:

```json
{
  &quot;0x1&quot;: {
    &quot;erc721Approval&quot;: {
      &quot;supported&quot;: true,
      &quot;versions&quot;: [&quot;1.0&quot;]
    }
  }
}
```

#### `wallet_sendCalls` Request

Version 1.0 Schema:

```typescript
type Erc721ApprovalParams = {
  version: string;
  chainId: `0x${string}`; // Hex chain id
  owner: `0x${string}`; // Address
  operator: `0x${string}`; // Address
  token: `0x${string}`; // Address
  tokenId: `0x${string}`; // Hex value
};
```

This capability requests that the `owner` address **MUST** have approved `operator` to transfer `tokenId` of `token` on `chainId` before the transaction is executed.

Example:

```json
[
  {
    &quot;version&quot;: &quot;1.0&quot;,
    &quot;from&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
    &quot;calls&quot;: [
      {
        &quot;to&quot;: &quot;0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d&quot;,
        &quot;value&quot;: &quot;0x00&quot;,
        &quot;data&quot;: &quot;0x...&quot;,
        &quot;chainId&quot;: &quot;0x01&quot;,
      }
    ],
    &quot;capabilities&quot;: {
      &quot;erc721Approval&quot;: {
        &quot;version&quot;: &quot;1.0&quot;,
        &quot;chainId&quot;: &quot;0x01&quot;,
        &quot;owner&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
        &quot;operator&quot;: &quot;0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d&quot;,
        &quot;token&quot;: &quot;0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d&quot;,
        &quot;tokenId&quot;: &quot;0x10&quot;
      }
    }
  }
]
```

### ERC-1155 Minimum Balance Capability

A dApp can use the `erc1155MinBalance` capability in a `wallet_sendCalls` request to request that a wallet ensure the owner has a minimum balance of a specified [ERC-1155](/EIPs/EIPS/eip-1155) token.

#### `wallet_getCapabilities` Response

Schema:

```typescript
type Erc1155MinBalanceCapability = {
  supported: boolean;
  versions: string[];
}
```

Example:

```json
{
  &quot;0x1&quot;: {
    &quot;erc1155MinBalance&quot;: {
      &quot;supported&quot;: true,
      &quot;versions&quot;: [&quot;1.0&quot;]
    }
  }
}
```

#### `wallet_sendCalls` Request

Version 1.0 Schema:

```typescript
type Erc1155MinBalanceParams = {
  version: string;
  chainId: `0x${string}`; // Hex chain id
  owner: `0x${string}`; // Address
  token: `0x${string}`; // Address
  tokenId: `0x${string}`; // Hex value
  minAmount: `0x${string}`; // Hex value
};
```

This capability requests that the `owner` address **MUST** have a balance of at least `minAmount` of `tokenId` of `token` on `chainId` before the transaction is executed.

Example:

```json
[
  {
    &quot;version&quot;: &quot;1.0&quot;,
    &quot;from&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
    &quot;calls&quot;: [
      {
        &quot;to&quot;: &quot;0x631998e91476da5b870d741192fc5cbc55f5a52e&quot;,
        &quot;value&quot;: &quot;0x00&quot;,
        &quot;data&quot;: &quot;0x...&quot;,
        &quot;chainId&quot;: &quot;0x01&quot;,
      }
    ],
    &quot;capabilities&quot;: {
      &quot;erc1155MinBalance&quot;: {
        &quot;version&quot;: &quot;1.0&quot;,
        &quot;chainId&quot;: &quot;0x01&quot;,
        &quot;owner&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
        &quot;token&quot;: &quot;0x631998e91476da5b870d741192fc5cbc55f5a52e&quot;,
        &quot;tokenId&quot;: &quot;0x10&quot;,
        &quot;minAmount&quot;: &quot;0x0f4240&quot;
      }
    }
  }
]
```

### ERC-1155 Minimum Allowance Capability

A dApp can use the `erc1155MinAllowance` capability in a `wallet_sendCalls` request to request that a wallet ensure the owner has a minimum allowance of a specified [ERC-1155](/EIPs/EIPS/eip-1155) token.
Note this capability does not imply that the owner has a balance of the token, only that the allowance is equal to or greater than the specified amount.

#### `wallet_getCapabilities` Response

Schema:

```typescript
type Erc1155MinAllowanceCapability = {
  supported: boolean;
  versions: string[];
}
```

Example:

```json
{
  &quot;0x1&quot;: {
    &quot;erc1155MinAllowance&quot;: {
      &quot;supported&quot;: true,
      &quot;versions&quot;: [&quot;1.0&quot;]
    }
  }
}
```

#### `wallet_sendCalls` Request

Version 1.0 Schema:

```typescript
type Erc1155MinAllowanceParams = {
  version: string;
  chainId: `0x${string}`; // Hex chain id
  owner: `0x${string}`; // Address
  operator: `0x${string}`; // Address
  token: `0x${string}`; // Address
  tokenId: `0x${string}`; // Hex value
  minAmount: `0x${string}`; // Hex value
};
```

This capability requests that the `owner` address **MUST** have an allowance of at least `minAmount` of `tokenId` of `token` for `operator` on `chainId` before the transaction is executed.

Example:

```json
[
  {
    &quot;version&quot;: &quot;1.0&quot;,
    &quot;from&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
    &quot;calls&quot;: [
      {
        &quot;to&quot;: &quot;0x631998e91476da5b870d741192fc5cbc55f5a52e&quot;,
        &quot;value&quot;: &quot;0x00&quot;,
        &quot;data&quot;: &quot;0x...&quot;,
        &quot;chainId&quot;: &quot;0x01&quot;,
      }
    ],
    &quot;capabilities&quot;: {
      &quot;erc1155MinAllowance&quot;: {
        &quot;version&quot;: &quot;1.0&quot;,
        &quot;chainId&quot;: &quot;0x01&quot;,
        &quot;owner&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
        &quot;operator&quot;: &quot;0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d&quot;,
        &quot;token&quot;: &quot;0x631998e91476da5b870d741192fc5cbc55f5a52e&quot;,
        &quot;tokenId&quot;: &quot;0x10&quot;,
        &quot;minAmount&quot;: &quot;0x0f4240&quot;
      }
    }
  }
]
```

### Usage Examples

This ERC serves as a foundational component for building user experiences that rely on cross-chain actions. It can be leveraged in various ways, depending on the combination of use cases and wallet implementations. Consider the following high-level examples.

Not shown in the examples below are the `wallet_getCallsStatus` and `wallet_showCallsStatus` methods, which are used to query the status of a call bundle and display it to the user. The dApp **MAY** use these methods to provide a better user experience while waiting for the transactions to be fulfilled. More information can be found in the [EIP-5792](/EIPs/EIPS/eip-5792) specification.

#### Marketplace Interaction with Bridge Using an EOA Wallet

A user wants to purchase [ERC-721](/EIPs/EIPS/eip-721) tokens on **Chain A** but only has funds on **Chain B**. The user employs an Externally Owned Account (EOA) based wallet. The dApp requests an intended transaction using `wallet_sendCalls`, which includes the marketplace transaction alongside the requirement of owning funds on Chain A.

In this scenario, the wallet **MAY** prompt the user to sign the necessary transactions to fulfill the requirements before proceeding with the main transaction. The wallet **SHOULD** compute possible solutions to meet the requirements and **MUST** ensure that these prerequisites are met prior to executing the main transaction.

![EOA Example](/EIPs/assets/eip-7795/eoa_example.svg)

#### Bridge, Swap, and Payment Using a Smart Contract Wallet

A dApp requests a payment from a user, which **MUST** be made in **Token Z** on **Chain B**, but the user holds **Token Y** on **Chain A**. The dApp requests an intended transaction using `wallet_sendCalls`, including the payment transaction alongside the requirement of having enough Token Z on Chain B.

In this scenario, the Smart Contract Wallet **MAY** prompt the user to sign all the necessary transactions at once, executing them in the appropriate order. The wallet **SHOULD** compute solutions to fulfill the requirements and **MUST** ensure that all prerequisites are satisfied before proceeding with the main transaction.

The signed transactions **MAY** be sent simultaneously to bundlers, who execute them as they become available, allowing the operation to complete even if the wallet disconnects.

![SC Example](/EIPs/assets/eip-7795/sc_example.svg)

## Rationale

This ERC extends [EIP-5792](/EIPs/EIPS/eip-5792) rather than defining new RPC methods because:

1. **Consistency**: Leverages existing capability discovery mechanism
2. **Composability**: Requirements can be combined with other [EIP-5792](/EIPs/EIPS/eip-5792) capabilities
3. **Flexibility**: Wallets can implement only the requirements they support
4. **Extensibility**: New requirement types can be added as additional capabilities

The decision to split requirements into individual capabilities rather than a single capability type allows:

1. Granular support by wallets
2. Clear capability discovery
3. Independent versioning of requirement types
4. Simpler implementation for basic wallets

## Security Considerations

This ERC does not introduce any new security risks or trust assumptions.

Users already trust their wallet provider to craft, manipulate and send transactions on their behalf. This ERC only adds a new field to the transaction request, which the wallet can use to make more informed decisions about transaction construction.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 22 Oct 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7795</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7795</guid>
      </item>
    
      <item>
        <title>Conditional send transaction RPC</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/send-transaction-conditional-rpc-api/21480</comments>
        
        <description>## Abstract

This EIP proposes a new JSON-RPC API method `eth_sendRawTransactionConditional` for block builders and sequencers,
enhancing transaction integration by allowing users to express preconditions for transaction inclusion.

This method aims to improve efficiency by reducing the need for transaction simulation,
thereby improving the computational efficiency of transaction ordering.

## Motivation

Current private block builder APIs, such as the Flashbots API,
require block builders to simulate transactions to determine eligibility for inclusion,
a process that is CPU-intensive and inefficient.

The proposed RPC method addresses this by enabling transactions to specify preconditions,
thus reducing computational overhead and potentially lowering transaction costs.

Moreover, the flashbots API does not provide the block builder with a mechanism to determine the
cross-dependencies of different transactions.

The only way to guarantee that another transaction does not interfere with a given one is by placing
it as the first transaction in the block.
This makes this placement very lucrative, and disproportionately expensive.

In addition, since there is no way to give any guarantee on other slots, their pricing has to be low accordingly.

Since there is no easy way to detect cross-dependencies of different transactions,
it is CPU-intensive to find an optimal ordering of transactions.

## Specification

* Method: `eth_sendRawTransactionConditional`

* Parameters:

1. `transaction`: The raw, signed transaction data. Similar to `eth_sendRawTransaction`.
2. `options`: An object containing conditions under which the transaction must be included.
* The `options` parameter may include any of the following optional members:
    * **knownAccounts**: a mapping of accounts with their expected storage slots&apos; values.
        * The key of the mapping is account address.
        * A special key `balance` defines the expected balance of the account.
        * A special key `code` defines the expected code of the account.
          Use `&quot;&quot;` to indicate that address is expected not to have any code.
          Use the `&quot;0xef0100&quot;` prefix to indicate a specific [EIP-7702](/EIPs/EIPS/eip-7702) delegation.
        * A special key `nonce` defines the expected nonce of the account.
        * If the value is **hex string**, it is the known storage root hash of that account.
        * If the value is an **object**, then it is a mapping where each member is in the format of `&quot;slot&quot;: &quot;value&quot;`.
          The `value` fields are explicit slot values of the account&apos;s storage.
          Both `slot` and `value` are hex-encoded strings.
    * **blockNumberMin**: minimal block number for inclusion.
    * **blockNumberMax**: maximum block number for inclusion.
    * **timestampMin**: minimum block timestamp for inclusion.
    * **timestampMax**: maximum block timestamp for inclusion.
    * **paysCoinbase**: the caller declares the minimum amount paid to the `coinbase` by this transaction,
      including gas fees and direct payment.

Before accepting the request, the block builder or sequencer SHOULD:

* Check that the block number is within the block range if the block range value was specified.
* Check that the block timestamp is within the timestamp range if the timestamp range was specified.
* For all addresses with a specified storage root hash, validate the current root is unmodified.
* For all addresses with a specified slot values mapping, validate that all these slots hold the exact value specified.

The sequencer should REJECT the request if any address does not pass the above rules.

### Return value

In case of a successful inclusion, the call should return a hash of the newly submitted transaction.
This behaviour is equivalent to the `eth_sendRawTransaction` JSON-RPC API method.

In case of an immediate failure to validate the transaction&apos;s conditions,
the block builder SHOULD return an error with indication of failure reason.

The error code SHOULD be &quot;-32003 transaction rejected&quot; with reason string describing the cause:
i.e. storage error, out of block/time range, etc.

In case of repeated failures or `knownAccounts` mapping being too large for the current block builder to handle,
the error code SHOULD be &quot;-32005 limit exceeded&quot; with a description of the error.

**NOTE:** Same as with the `eth_sendRawTransaction` method,
even if the RPC method call does not resul in an error and the transaction is
initially accepted into the internal block builder&apos;s mempool,
the caller MUST NOT assume that a transaction will be included in a block and should monitor the blockchain.

### Sample request
```json
{
    &quot;jsonrpc&quot;: &quot;2.0&quot;,
    &quot;id&quot;: 1,
    &quot;method&quot;: &quot;eth_sendRawTransactionConditional&quot;,
    &quot;params&quot;: [
        &quot;0x2815c17b00...&quot;,
        {
            &quot;blockNumberMax&quot;: 12345,
            &quot;knownAccounts&quot;: {
                &quot;0xadd1&quot;: &quot;0xfedc....&quot;,
                &quot;0xadd2&quot;: { 
                    &quot;0x1111&quot;: &quot;0x1234...&quot;,
                    &quot;0x2222&quot;: &quot;0x4567...&quot;
                }
            }     
        } 
    ]
}
```

### Limitations

- Callers should not assume that a successful response means the transaction is included.
  Specifically, it is possible that a block re-order might remove the transaction or cause it to fail.

## Rationale

The `knownAccounts` only allows specifying the exact values for storage slots.
While in some cases specifying `minValue` or `maxValue` for a slot could be useful,
it would significantly increase complexity of the proposed API.
Additionally, determining the validity range for a slot value is a non-trivial task for the sender of a transaction.

One way to provide a more complex rule for a transaction condition is by specifying the `paysCoinbase` parameter,
and issuing a transfer to the `coinbase` address on some condition.

## Backwards Compatibility

This is a proposal for a new API method so no backward compatibility issues are expected.
Existing non-standard implementations of `eth_sendRawTransactionConditional` API may need to be modified in order to
become compatible with the standard.

## Security Considerations

The block builder should protect itself against abuse of the API.
Namely, a malicious actor submitting a large number of requests which are known to fail may lead to a denial of service.

Following is the list of suggested potential mitigation mechanisms:

* **Throttling**: the block builder should allow a maximum rate of RPC calls per sender.
  The block builder may increase that rate after a successful inclusion.
  Repeated rejections of transactions should reduce the allowed rate.
* **Arbitrum**-style protection: Arbitrum implemented this API, but they run the storage validation not only
  against the current block, but also into past 2 seconds.
  This prevents abusing the API for MEV, while making it viable for [ERC-4337](/EIPs/EIPS/eip-4337) account validation.
* **Fastlane on Polygon** uses it explicitly for ERC-4337,
  by checking the submitted UserOperations exist on the public mempool and rejecting the transaction otherwise.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 16 Apr 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7796</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7796</guid>
      </item>
    
      <item>
        <title>Double speed for hash_tree_root</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7797-double-speed-for-hash-tree-root/21447</comments>
        
        <description>## Abstract

This EIP explains how to customize [`hash_tree_root`](https://github.com/ethereum/consensus-specs/blob/b3e83f6691c61e5b35136000146015653b22ed38/ssz/simple-serialize.md#merkleization) to double its performance.

## Motivation

Hashing is a dominant performance bottleneck for Consensus Layer implementations. To support large validator counts, it is critical to optimize hashing performance.

Consensus Layer hashes are based on [`hash_tree_root`](https://github.com/ethereum/consensus-specs/blob/b3e83f6691c61e5b35136000146015653b22ed38/ssz/simple-serialize.md#merkleization), a mechanism that splits up the data into chunks and then forms a tree by recursively combining two adjacent chunks and hashing them into a single parent chunk until only a single root chunk remains.

For hashing, Secure Hash Algorithm 2 with a digest size of 256 bits is used (SHA-256). This algorithm produces _exactly_ 256 bits of output for a variable-length input message. However, as `hash_tree_root` pads all input chunks to exactly 256 bits, the effective input message length is always _exactly_ 512 bits.

This EIP defines how the SHA-256 algorithm used by `hash_tree_root` can be customized to exploit knowledge of the exact input length to double its performance, while retaining its security properties.

## Specification

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

### SHA-256 preprocessing

Before SHA-256 hash computation begins, the input message is preprocessed. A single `1` bit is appended to the input message, followed by a varying number of `0` bits, and finally a big endian `uint64` indicating the input message bit length. The number of `0` bits is chosen so that the message size is the smallest possible multiple of 512 bits. In the context of `hash_tree_root` where the input message size is 512 bits, preprocessing results in the following padded message:

```
         0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   0x00 |                                               |
   0x10 |                     Input                     |
   0x20 |                    message                    |
   0x30 |                                               |
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
   0x40 |80|00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|
   0x50 |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|
   0x60 |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|
   0x70 |00 00 00 00 00 00 00 00|00 00 00 00 00 00 02 00|
        +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
```

### SHA-256 blocks

SHA-256 operates on message blocks of 512 bits. Therefore, in the context of `hash_tree_root` where the input message size is 512 bits, two message blocks are formed, the first containing the entire input message, and the second containing entirely static data resulting from the preprocessing step.

Note that the second 512 bit message block does not provide any entropy, and is only useful to distinguish input messages that share a common prefix and only vary in the number of trailing `0` bits. As `hash_tree_root` uses a fixed message size, no distinguishing is necessary. Further, SHA-256 is also considered secure for padded messages that fit into a single message block.

### SHA-256-512

A new algorithm SHA-256-512 is defined as a modified SHA-256 algorithm that skips input message preprocessing and is restricted to inputs of exactly 512 bits. The input message SHALL be processed as is, as a single 512-bit SHA-256 message block.

For every [composite SSZ type](https://github.com/ethereum/consensus-specs/blob/b3e83f6691c61e5b35136000146015653b22ed38/ssz/simple-serialize.md#composite-types) in use, implementations SHALL support a new type that shares the same functionality, but hashes using SHA-256-512 instead of regular SHA-256.

### Consensus types

Starting with the hard fork that introduces this EIP, the SHA-256-512 based composite SSZ types SHOULD be preferred over existing SHA-256 based types.

Certain use cases covering historical objects MAY require conversion to the historical data type and re-hashing with the original SHA-256 type to recover their historical root. This includes [`compute_signing_root`](https://github.com/ethereum/consensus-specs/blob/b3e83f6691c61e5b35136000146015653b22ed38/specs/phase0/beacon-chain.md#compute_signing_root) signing over historical data, and also individual fields such as `BeaconState.latest_block_header` which MAY refer to data from prior forks.

Certain other objects such as `DepositData` or `VoluntaryExit` MAY continue to rely on existing SHA-256 logic.

## Rationale

Doubling the throughput of the underlying hash algorithm allows scaling to more validators on the same hardware, or allows using the freed CPU time for other tasks. Even when caching rarely-changed intermediate hashes across computations such as the `validators` list of a `BeaconState`, and employing hardware-accelerated SHA-256 implementations that are further optimized for the tree structure using libraries such as `prysmaticlabs/hashtree`, the state root validation step of the Consensus Layer state transition function can still consume ~25% of CPU time (Holesky test network, ~1.7m validators), mostly dominated by frequently changing per-validator structures such as the `EpochParticipationFlags` lists.

If the hash algorithm is changed to a more zero-knowledge friendly one in the future, similar efforts as described in this EIP would be needed to identify the locations where historical objects need to be hashed using historical hashes, and also to introduce new composite SSZ types. A switch from SHA-256 to SHA-256-512 would pull such work ahead, and any future hash algorithm changes would solely have to extend on these known locations. The total work necessary to switch hash algorithms multiple times is comparable to switching a single time.

Existing hardware acceleration for SHA-256 continues to be viable, as only the message preprocessing step is dropped. Hardware acceleration typically only implements the SHA-256 message block function, which is unchanged by this EIP.

## Backwards Compatibility

Smart contracts and client applications that verify Consensus Layer data require updates to remain compatible with data hashed using SHA-256-512. New logic may be required to correctly select the hash algorithm for historical structures such as `BeaconBlockHeader`.

SSZ serialization, generalized indices, as well as semantics of individual object fields remain unchanged.

## Security Considerations

Certain SHA-256-512 hashes of 512 bit data may collide with regular SHA-256 hashes of shorter data. For example:

- Any common 440-bit prefix: `COMMON_PREFIX := 0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233343536`
- `SHA-256-512(COMMON_PREFIX ++ 0x80 ++ 0x00000000000001b8) == 463eb28e72f82e0a96c0a4cc53690c571281131f672aa229e0d45ae59b598b59`
- `SHA-256(COMMON_PREFIX) == 463eb28e72f82e0a96c0a4cc53690c571281131f672aa229e0d45ae59b598b59`

Because SSZ has never hashed data with sizes different from 512 bits, SSZ hashes based on SHA-256 do not collide with hashes based on SHA-256-512.

SHA-256-512 SHOULD NOT be used for purposes other than SSZ Merkleization.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 23 Oct 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7797</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7797</guid>
      </item>
    
      <item>
        <title>System logs</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7799-system-logs/21497</comments>
        
        <description>## Abstract

This EIP defines an extension for eth_getLogs to provide logs for events that are not associated with a given transaction, such as block rewards and withdrawals.

## Motivation

With [EIP-7708](/EIPs/EIPS/eip-7708) wallets gain the ability to use eth_getLogs to track changes to their ETH balance. However, the ETH balance may change without an explicit transaction, through block production and withdrawals. By having such operations emit block-level system logs, eth_getLogs provides a complete picture of ETH balance changes.

## Specification

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

### Fee payment logs

A log, identical to a LOG2, is issued for every transaction and appended after all other logs created by EVM execution. The fee amount incorporates the total fee charged during transaction execution, including the base fee, the priority fee, and potential blob fees.

| Field | Value |
| - | - |
| `address` | `0xfffffffffffffffffffffffffffffffffffffffe` ([`SYSTEM_ADDRESS`](/EIPs/EIPS/eip-4788)) |
| `topics[0]` | `0x7bd3aa7d673767f759ebf216e7f6c12844986c661ae6e0f1d988cf7eb7394d1d` (`keccak256(&apos;Fee(address,uint256)&apos;)`) |
| `topics[1]` | `from` address (zero prefixed to fill uint256) |
| `data` | `amount` in Wei (big endian uint256) |

### System logs list

A new list is introduced to track all block level logs emitted from system interactions. The definition uses the `Log` SSZ type from [EIP-6466](/EIPs/EIPS/eip-6466).

```python
system_logs = ProgressiveList[Log](
    log_0, log_1, log_2, ...)
```

### Priority fee processing

A log SHALL be appended to the system logs list when crediting the batched [EIP-8115](/EIPs/EIPS/eip-8115) priority fee.

| Field | Value |
| - | - |
| `address` | `0xfffffffffffffffffffffffffffffffffffffffe` ([`SYSTEM_ADDRESS`](/EIPs/EIPS/eip-4788)) |
| `topics[0]` | `0x5dfe9c0fd3043bb299f97cfece428f0396cf8b7890c525756e4ea5c0ff7d61b2` (`keccak256(&apos;PriorityRewards(address,uint256)&apos;)`) |
| `topics[1]` | `to` address (zero prefixed to fill uint256) |
| `data` | `amount` in Wei (big endian uint256) |

### Withdrawal processing

A log SHALL be appended to the system logs list on every [EIP-4895](/EIPs/EIPS/eip-4895) withdrawal.

| Field | Value |
| - | - |
| `address` | `0xfffffffffffffffffffffffffffffffffffffffe` ([`SYSTEM_ADDRESS`](/EIPs/EIPS/eip-4788)) |
| `topics[0]` | `0x7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65` (`keccak256(&apos;Withdrawal(address,uint256)&apos;)`) |
| `topics[1]` | `to` address (zero prefixed to fill uint256) |
| `data` | `amount` in Wei (big endian uint256) |

### Genesis processing

A log SHALL be appended to the system logs list when generating genesis blocks for networks that adopt this EIP from the beginning.

| Field | Value |
| - | - |
| `address` | `0xfffffffffffffffffffffffffffffffffffffffe` ([`SYSTEM_ADDRESS`](/EIPs/EIPS/eip-4788)) |
| `topics[0]` | `0xba2f6409ffd24dd4df8e06be958ed8c1706b128913be6e417989c74969b0b55a` (`keccak256(&apos;Genesis(address,uint256)&apos;)`) |
| `topics[1]` | `to` address (zero prefixed to fill uint256) |
| `data` | `amount` in Wei (big endian uint256) |

### Execution block header changes

The [execution block header](https://github.com/ethereum/devp2p/blob/5713591d0366da78a913a811c7502d9ca91d29a8/caps/eth.md#block-encoding-and-validity) is extended with a new field, `system-logs-root`.

```python
block_header.system_logs_root = system_logs.hash_tree_root()
```

### JSON-RPC API

Block header objects in the context of the JSON-RPC API are extended to include:

- `systemLogsRoot`: `DATA`, 32 Bytes

Log objects in the context of the JSON-RPC API are updated as follows:

- `logIndex`: `QUANTITY` - The additional system logs are indexed consecutively after the existing logs from transaction receipts
- `transactionIndex`: `QUANTITY` - `null` is also used for system logs; pending logs can still be identified by checking the `blockHash` for `null`
- `transactionHash`: DATA, 32 Bytes - `null` is also used for system logs

### Engine API

In the engine API, the `ExecutionPayload` for versions corresponding to forks adopting this EIP is extended to include:

- `systemLogsRoot`: `DATA`, 32 Bytes

As part of `engine_forkchoiceUpdated`, Execution Layer implementations SHALL verify that `systemLogsRoot` for each block matches the actual value computed from local processing. This extends on top of existing `receiptsRoot` validation.

### Consensus `ExecutionPayload` changes

The consensus `ExecutionPayload` type is extended with a new field to store the system logs root.

```python
class ExecutionPayload(...):
    ...
    system_logs_root: Root
```

## Rationale

Together with [EIP-7708](/EIPs/EIPS/eip-7708) this EIP provides the ability for wallets to compute the exact ETH balance from logs without requiring download of every single block header and all withdrawals.

The block reward from priority fees no longer has to be summed up by processing all receipts and can be obtained from the system logs root, making it efficiently provable.

### Alternatives / Future

- The information from withdrawals is now duplicated across both the `withdrawals` list and the system logs. Maybe the information could be massaged into the emitted `Withdrawal` log data, allowing the existing `withdrawals` list to be retired. The current list design requires the wallet to obtain all block headers and all withdrawals to ensure they obtained all data pertaining to the observed account. Allowing them to be queried using `eth_getLogs` is more in line with how deposits are being tracked.

- The log definitions themselves are subject to change. Aligning them with [ERC-20](/EIPs/EIPS/eip-20) for plain credits provides consistency. For withdrawals, the log data could match the form of deposit logs and [EIP-7685](/EIPs/EIPS/eip-7685) request logs.

## Backwards Compatibility

As a new field is added to the block header, applications assuming a specific block header layout may need updating.

## Security Considerations

The emitted logs use `SYSTEM_ADDRESS` as their `address` which cannot conflict with user controlled smart contracts.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 29 Oct 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7799</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7799</guid>
      </item>
    
      <item>
        <title>etha - Sharded Blocks Subprotocol</title>
        <category>Standards Track/Networking</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7801-etha-sharded-blocks-subprotocol/21507</comments>
        
        <description>## Abstract

This EIP proposes the creation of a new subprotocol, `etha`, enabling Ethereum nodes to communicate available block spans via a bitmask. Each bit represents a 106_496-block span within each 1_064_960 block range of chain history. Nodes use this bitmask to signal stored spans and commit to storing future spans as they are created. This allows peers to make informed decisions about data availability without first connecting and querying for it. The bitmask repeats every 1_064_960 blocks for straightforward reasoning about data availability probabilities.

The `etha` subprotocol has the same functionality to serve historical data using message types copied from the `eth` protocol, enabling efficient data retrieval.

## Motivation

With [EIP-4444](/EIPs/EIPS/eip-4444), nodes may prune historical data while others continue serving it. Determining data availability by connecting and requesting blocks is inefficient consuming unnecessary bandwidth. This EIP addresses this inefficiency by enabling nodes to shard chain history into 106_496 block segments and signal availability via a bitmask.

By introducing a separate subprotocol, `etha`, nodes can exchange this information seamlessly and retain the ability to serve historical data without impacting existing `eth` protocol versions.

## Specification

### Subprotocol Handshake

- Introduce a new subprotocol named `etha`.
- Define the handshake message for the `etha` subprotocol as follows:
  - Handshake packet: `[version: P, networkid: P, blockhash: B_32, genesis: B_32, forkid, blockBitmask]`
  - `blockBitmask` is a 10-bit bitmask, with each bit representing a 106_496-block range per 1_064_960 blocks of history.
  - the rest of the elements are as defined in eth/69

### Supported Messages

The `etha` subprotocol **MUST** include support for the following messages from the `eth/69` protocol to facilitate historical data serving:

- **GetBlockBodies (0x05):** Request block bodies.
- **BlockBodies (0x06):** Response to `GetBlockBodies`.
- **GetReceipts (0x0f):** Request receipts.
- **Receipts (0x10):** Response to `GetReceipts`.

The semantics and payload structures for these messages are identical to their counterparts in the `eth/69` protocol, ensuring compatibility for historical data serving.

### Node Behavior

- **Bitmask Initialization**: Nodes **MAY** set at least one bit in the `blockBitmask` to `on` upon startup and backfill the corresponding 106_496-block span.
- **Shard Retention Probability**: Nodes **MUST** retain new block spans according to their bitmask, aiming to cover at least 10% of chain history.
- **Commitment to Future Ranges**: Nodes **MUST** retain spans corresponding to their advertised bitmask as new blocks are added.
- **Bitmask Space**: The 106_496 range `blockBitmask` repeats every 1_064_960 blocks, enabling efficient representation of historical data locality across epochs.

Upon connection using `etha`, nodes exchange the handshake message with the `blockBitmask`. This single handshake eliminates the need for additional message types.

### ENR Extension

Alternatively, the `blockBitmask` could be derived or encoded into the Ethereum Node Record (ENR), enabling nodes to advertise block spans without a handshake. As an example, the `blockBitmask` can be derived from the `secp256k1` field of the ENR.  However, this method lacks the authentication and reliability of the handshake approach. Additionally, there is not guarantee that the node you are connecting to supports the `etha` subprotocol.

## Rationale

The bitmask approach provides a flexible means to represent and retain block data while committing to future spans. This mechanism aligns with the pruning proposed in EIP-4444, while ensuring that historical and future data spans remain available across the network.

A similar bitlist approach is already used in the Consensus Layer for attestation subnets, making it a familiar and efficient method for representing data spans. Additionally, committing to future spans ensures better predictability and stability for data locality.

The `etha` subprotocol separates this functionality from `eth` ensuring nodes dont hammer other nodes with requests on historical ranges that they do not posses on the eth protocol.

The range sizes of 106,496 and 1,064,960 blocks were chosen because they are multiples of Era1’s maximum block range of 8,192, which allows for straightforward storage and representation using Era1 files.

## Backwards Compatibility

The `etha` subprotocol is independent of the `eth` protocol. This EIP does not affect the consensus engine or require a hard fork.

## Security Considerations

There are some considerations:

- Data unavailability for any given shard can be modeled as: P = (0.9)^n, where n is the number of peers.  Assuming a random distribution of nodes that are participating in EIP-7801 history sharding, for 25 peers, this chance is 7%.  For 32 peers, this chance drops to 3.4%. This assumes that a significant number of nodes on the network are serving at least one shard.  Adoption by a majority of clients as a default would likely be necessary for a complete sharded history to be available and replicated sufficiently across the network.
- As history grows, so will the size of the retained shards on disk, thus raising the storage requirements per node.  However, nodes will still benefit from a ~90% storage reduction over the present chain storage requirements, and will scale their future chain storage requirements by only 10% of the rate they would have by retaining all history.


## Copyright

This document is CC0-licensed; rights are waived through [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 30 Oct 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7801</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7801</guid>
      </item>
    
      <item>
        <title>Token With Mint/Burn Access Across Chains</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7802-crosschain-token-interface/21508</comments>
        
        <description>## Abstract

This standard introduces a minimal and extensible interface, `IERC7802`, for tokens to enable standardized crosschain communication. The interface consists of two functions, `crosschainMint` and `crosschainBurn`, which allow authorized bridge contracts to mint and burn token representations during crosschain transfers. These functions serve as the entry points for bridge logic, enabling consistent handling of token supply across chains.

The interface also defines two standardized events, `CrosschainMint` and `CrosschainBurn`, which emit metadata, including the target address, token amount, and caller. These events facilitate deterministic indexing and monitoring of crosschain activities by off-chain agents, such as indexers, analytics tools, and auditors.

`IERC7802` is intentionally lightweight, ensuring minimal overhead for implementation. Its modular design enables extensibility, allowing additional features—such as mint/burn limits, transfer fees, or bridge-specific access control mechanisms—to be layered on top without modifying the base interface. 

## Motivation

All rollups and multiple important sidechains implement canonical bridges that embed their security into some part of the network&apos;s core architecture. These bridges do not have mint/burn rights over original tokens, so they usually lock (unlock) liquidity on the native chain and then mint (burn) a non-equivalent representation on the other. Mint/burn is used because the native token is non-existent on that side, so they must create a new representation. However, each bridge implements a different interface for minting/burning on non-native chains.

This interface fragmentation is a massive issue in crosschain communication among chains via third-party bridges or future canonical solutions. At this point, it is clear that every bridge would benefit from a standardized interface for minted/burnt tokens. 

There have been different attempts in the past to standardize token-bridging interfaces. However, third-party providers are also developing crosschain token frameworks. Each framework defines its features, like rate limits and fee switches, and implements its mint and burn versions. The resultant interfaces become highly specific, lacking naming conventions and structures.

The proposed interface includes the most relevant and minimal set of actions used by most of these standards. These actions also do not require any governance or owner participation, in contrast, for instance, to set rate limits.

## Specification

This ERC introduces the `IERC7802` interface.

### Interface Identification

The interface identifier for `IERC7802` is **`0x33331994`**, calculated according to [ERC-165](/EIPs/EIPS/eip-165) as the XOR of the function selectors of the two functions in the interface:

```solidity
bytes4 constant INTERFACE_ID_IERC7802 = 
        bytes4(keccak256(&quot;crosschainMint(address,uint256)&quot;)) ^
        bytes4(keccak256(&quot;crosschainBurn(address,uint256)&quot;));
```

or via Solidity as 

```solidity
type(IERC7802).interfaceId
```

Implementors MUST ensure that the `supportsInterface` method of ERC-165 returns true for this interface ID to indicate support for `IERC7802`.


### Methods

**`crosschainMint`**

Mints `_amount` of token to address `_account`. 

This function works as the minting entry point for bridge contracts. 

```solidity
function crosschainMint(address _account, uint256 _amount) external;
```

Implementations SHOULD emit `Transfer(address(0), _to, _amount)` on calls to `crosschainMint` to be compliant with [ERC-20](/EIPs/EIPS/eip-20) invariants on token creation.

**`crosschainBurn`**

Burns `_amount` of token from address `_account`.

This function works as the burning entry point for bridge contracts.

```solidity
function crosschainBurn(address _account, uint256 _amount) external;
```

Implementations might consider emitting `Transfer(_from, address(0), _amount)` on calls to `crosschainBurn` to be compliant with [ERC-5679](/EIPs/EIPS/eip-5679).

### Events

**`CrosschainMint`**

MUST trigger when `crosschainMint` is successfully called. 
The `_sender` parameter MUST be set to the msg.sender at the time the function is called.

```solidity
event CrosschainMint(address indexed _to, uint256 _amount, address indexed _sender);
```

**`CrosschainBurn`**

MUST trigger when `crosschainBurn` is successfully called.
The `_sender` parameter MUST be set to the msg.sender at the time the function is called.

```solidity
event CrosschainBurn(address indexed _from, uint256 _amount, address indexed _sender)
```

## Rationale

### Design philosophy
The core design decisions behind this minimal interface are

- Bridge agnosticism.
- Extensibility.

**Bridge agnosticism**
This interface is designed so bridges, not tokens, contain the logic to process crosschain actions. By maintaining this separation of concerns, token contracts remain simple, reducing their attack surface and easing auditing and upgradability. Offloading crosschain complexities to bridge contracts ensures that tokens do not embed specific bridge logic.

By implementing the proposed interface, tokens can be supported by different bridge designs:

- Lock/unlock bridges can still operate and do not require any token modification.
- Burn/mint bridges can now use a universal and minimal token interface, so they will not need to introduce bridge-specific representations, improving crosschain fungibility.

**Extensibility**
The minimal interface serves as a foundational layer upon which other standards can be built.
Token issuers or bridge contracts can extend functionality by adding features such as mint/burn limits, crosschain transfer fees, and more without altering the core interface.

The interface is intentionally neutral and does not impose conditions on:

- **Access Control**: Token issuers determine who is authorized to call `crosschainMint()` and `crosschainBurn()`.
- **Zero Amount Calls**: Token issuers decide whether to allow or revert calls with zero amounts.

### Separation of Local and crosschain Minting/Burning

**Different actions**

Local minting and burning are fundamentally different from crosschain minting and burning.

- In crosschain operations, the total circulating supply across all chains is expected to remain constant, as tokens are transferred between chains rather than created or destroyed in isolation.
- Agents that mint and burn tokens in crosschain transfer fundamentally differ from token owners. It make sense for the two actors to have different permissions.

Therefore, it is reasonable to have different checks, access controls, and logic (such as mint/burn limits) for crosschain actions.

**Separation of concerns**

Merging local and crosschain minting/burning into the same functions can lead to complex implementations that intertwine different operational logic. 
By splitting into two, concerns remain separate, making the codebase cleaner and more maintainable.

This separation of concerns is particularly relevant for

- Upgrades: Any changes in access control, limits, or logic will only affect the separate crosschain functions (`crosschainMint` and `crosschainBurn`) without altering the standard local mint and burn implementations.
- Integrations with Different Chains: To make an [ERC-20](/EIPs/EIPS/eip-20) crosschain compatible,
issuers simply need to implement the [ERC-7802](/EIPs/EIPS/eip-7802) extension with the corresponding access controls for each chain. 
For example, when integrating with Optimism, the ERC-20 would grant access to the Optimism bridge; when integrating with Arbitrum, it would grant access to the Arbitrum bridge. 
The local mint and burn functions remain unchanged. 
Using dedicated functions for crosschain operations provides a more modular approach, avoiding the need to modify the base implementation for each chain.

**Dedicated events**

A similar reasoning applies to having dedicated crosschain-specific events. The separation significantly facilitates the work of indexers, analytics tools, and auditors. It allows for straightforward tracking of crosschain activities, detecting anomalies, and monitoring bridge operations. If crosschain and local events are indistinguishable, off-chain agents must implement complex logic to differentiate them, increasing the potential for errors and inefficiencies.

### ERC-165 Interface

The inclusion of ERC-165 provides an additional security check for integrators. By providing the interface identifier through the `supportsInterface` method, callers can programmatically confirm that the token adheres to the `IERC7802` interface. 
This verification ensures that the token supports both `crosschainMint` and `crosschainBurn` functions, preventing scenarios where only one function is implemented. Such incomplete implementations could lead to issues like users burning tokens to bridge out but being unable to mint them upon return, resulting in failed crosschain actions.

It is important to note that this check can only be performed locally on the chain where the token contract resides. There is no inherent guarantee that the token on the receiving chain also supports the `IERC7802` interface. Ensuring crosschain consistency of interface support is the responsibility of the bridge implementation.

## Backwards Compatibility

This proposal is fully backwards compatible with [ERC-20](/EIPs/EIPS/eip-20).

As discussed in the Motivation section, a minimal, flexible crosschain standard interface is necessary. The problem becomes larger as more tokens are deployed without a standardized format.

- Upgradable tokens can be upgraded to implement the new interface.
- Non-upgradable tokens cannot implement the interface on the token itself. They can still migrate to a standard-compliant version using a lockbox mechanism, as proposed by xERC-20. The idea is to lock non-mintable tokens and mint the same amount of interface-compliant tokens. The bridge contract can act as a lockbox on the native chain.

Bridge contracts will also need an upgrade to integrate with the interface.

## Reference Implementation

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity 0.8.25;

import &quot;@openzeppelin/contracts/token/ERC20/ERC20.sol&quot;;
import &quot;@openzeppelin/contracts/utils/introspection/IERC165.sol&quot;;


/// @title IERC7802
/// @notice Defines the interface for crosschain ERC20 transfers.
interface IERC7802 is IERC165 {
    /// @notice Emitted when a crosschain transfer mints tokens.
    /// @param to       Address of the account tokens are being minted for.
    /// @param amount   Amount of tokens minted.
    /// @param sender   Address of the caller (msg.sender) who invoked crosschainMint.
    event CrosschainMint(address indexed to, uint256 amount, address indexed sender);

    /// @notice Emitted when a crosschain transfer burns tokens.
    /// @param from     Address of the account tokens are being burned from.
    /// @param amount   Amount of tokens burned.
    /// @param sender   Address of the caller (msg.sender) who invoked crosschainBurn.
    event CrosschainBurn(address indexed from, uint256 amount, address indexed sender);

    /// @notice Mint tokens through a crosschain transfer.
    /// @param _to     Address to mint tokens to.
    /// @param _amount Amount of tokens to mint.
    function crosschainMint(address _to, uint256 _amount) external;

    /// @notice Burn tokens through a crosschain transfer.
    /// @param _from   Address to burn tokens from.
    /// @param _amount Amount of tokens to burn.
    function crosschainBurn(address _from, uint256 _amount) external;
}

contract CrosschainERC20 is ERC20, IERC7802 {
    /// @notice Address of the TOKEN_BRIDGE contract that is allowed to mint/burn tokens.
    address public immutable TOKEN_BRIDGE;

    /// @notice Custom error for unauthorized access.
    error Unauthorized();

    /// @notice Constructor to set the TOKEN_BRIDGE address.
    /// @param _tokenBridge Address of the TOKEN_BRIDGE.
    constructor(address _tokenBridge, string memory name, string memory symbol) ERC20(name, symbol) {
        require(_tokenBridge != address(0), &quot;Invalid TOKEN_BRIDGE address&quot;);
        TOKEN_BRIDGE = _tokenBridge;
    }

    /// @notice A modifier that only allows the TOKEN_BRIDGE to call
    modifier onlyTokenBridge() {
        if (msg.sender != TOKEN_BRIDGE) revert Unauthorized();
        _;
    }

    /// @notice Allows the TOKEN_BRIDGE to mint tokens.
    /// @param _to     Address to mint tokens to.
    /// @param _amount Amount of tokens to mint.
    function crosschainMint(address _to, uint256 _amount) external onlyTokenBridge {
        _mint(_to, _amount);
        emit CrosschainMint(_to, _amount, msg.sender);
    }

    /// @notice Allows the TOKEN_BRIDGE to burn tokens.
    /// @param _from   Address to burn tokens from.
    /// @param _amount Amount of tokens to burn.
    function crosschainBurn(address _from, uint256 _amount) external onlyTokenBridge {
        _burn(_from, _amount);
        emit CrosschainBurn(_from, _amount, msg.sender);
    }

    function supportsInterface(bytes4 interfaceId) external pure override returns (bool) {
        return interfaceId == type(IERC7802).interfaceId || interfaceId == type(IERC165).interfaceId;
    }
}
```

## Security Considerations
### Permissions
Token issuers are responsible for controlling which contracts are authorized to call the `crosschainMint()` and `crosschainBurn()` functions. A buggy or malicious authorized caller could mint or burn tokens improperly, damaging token holders and disrupting integrations.

One method to minimize potential losses is introducing mint/burn limits, as proposed by xERC-20. These features are fully compatible with the proposed interface.

### Wrapped Native Tokens
This standard should not be used for wrapped native tokens like WETH, as it can lead to uncollateralized minting if the bridge does not control the underlying asset. 

The only safe exception is when the bridge can burn and mint the native token symmetrically on both chains, ensuring proper collateralization.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).</description>
        <pubDate>Wed, 30 Oct 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7802</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7802</guid>
      </item>
    
      <item>
        <title>EIP-712 Extensions for Account Abstraction</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7803-eip-712-extensions-for-account-abstraction/21436</comments>
        
        <description>## Abstract

This ERC improves on [EIP-712] signatures to better support smart contract accounts by 1) introducing signing domains as a way to prevent replay attacks when private keys are shared across accounts, and 2) allowing dapps and wallets to coordinate on the method that will be used to authenticate the signature.

[EIP-712]: /EIPs/EIPS/eip-712

## Motivation

### Signing Domains

Standards like [ERC-1271] and [ERC-6492] give smart contract accounts (SCAs) the ability to produce signatures that an application can authenticate without knowledge of the abstract rules of the account. This is an important primitive for applications, as the account owner is able to authorize a third-party to act on its behalf without interacting with the chain.

[ERC-1271]: /EIPs/EIPS/eip-1271

[ERC-6492]: /EIPs/EIPS/eip-6492

Smart contract accounts may be &quot;owned&quot; by cryptographic keys whose signatures are used to authorize the use of the account. There is not necessarily a one-to-one mapping between keys and accounts, because a single key may control multiple accounts, so care must be taken to prevent replay attacks across them. This is done by binding a signature to a particular account.

EIP-712 introduced a scheme where signatures can be bound to a verifying domain, which corresponds to the protocol contract that will authenticate a signature. Reusing this mechanism to additionally bind a signature to the domain of the smart contract account runs into a large amount of complexity and attack surface (see [ERC-7739]), as well as yet unresolved issues with account composability (SCAs that control other SCAs). This ERC introduces *signing domains* in addition to verifying domains to natively enable wallets to generate smart contract account signatures with replay protection.

[ERC-7739]: /EIPs/EIPS/eip-7739

### Authentication Methods

ERC-1271 is a minimal and very general interface that has been very effective. It requires the contract code to be already deployed by the time the signature needs to be authenticated, so ERC-6492 extends ERC-1271 to support that use case. In the future additional methods may need to be developed.

Support for these methods across protocols is currently lacking and is a major pain point for the Account Abstraction roadmap. Where ERC-1271 is supported, it is not necessarily used uniformly, in particular some contracts attempt `ECRECOVER` prior to invoking `isValidSignature` while others do the opposite, which will result in very different semantics post [EIP-7702].

[EIP-7702]: /EIPs/EIPS/eip-7702

This ERC addresses this by allowing dapps to communicate the types of signatures a protocol&apos;s contracts support, i.e., which authentication methods will be used, and in what order.

## Specification

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

Requests for typed data signatures via JSON-RPC (`eth_signTypedData`) or client libraries are extended with the following optional properties:

- `signingDomains`
- `authMethods`

These new properties are used alongside the existing ones, i.e., `types`, `primaryType`, `domain`, and `message`.

The signature returned in response to the request MAY be of any size, and in the absence of `authMethods` it MUST be treated opaquely as the type of the signature is not known.

### `signingDomains`

This property is an array of smart contract account domains. Each member of the array is an object with the following keys:

- `types`: An object with the same format as EIP-712 `types` with at least an `EIP712Domain` key.
- `domain`: An object that is valid with respect to the type `EIP712Domain` described in `types`.

From right to left the array lists the chain of accounts through which the signer ultimately has control over the &quot;outermost&quot; signing domain (i.e., that listed first).

For example: 

1. A dapp requests an EIP-712 signature to a connected account via JSON-RPC. `signingDomains` is empty or undefined.
2. The connected account is a multisig, so it requests EIP-712 signatures from its signers, prepending the domain of the multisig to `signingDomains`, which is now an array of length 1.
3. One of the signers uses a smart contract account controlled by an ECDSA key held in a hardware wallet, so their wallet requests an EIP-712 signature from the hardware wallet, prepending the domain of the smart contract account to `signingDomains`, which is now an array of length 2.
4. The signer verifies the contents of the signature in their hardware wallet. They are able to see that they are signing a message intended for a particular dapp domain, on behalf of their smart contract account (closest signing domain), as a member of the multisig (furthest signing domain).

#### Encoding of data to be signed

In the presence of `signingDomains` the account should encode the message to be signed according to the following recursive procedure:

- `encodeForSigningDomains(signingDomainSeparators : [𝔹²⁵⁶], verifyingDomainSeparator : 𝔹²⁵⁶, message : 𝕊) =`
  - If `signingDomainSeparators = [first, ...others]`: `&quot;\x19\x02&quot; ‖ first ‖ encodeForSigningDomains(others, verifyingDomainSeparator, message)`
  - If `signingDomainSeparators = []`: `encode(domainSeparator, message)`, where `encode` is defined by EIP-712.

`signingDomainSeparators` is the array of hashes of the domains included in `signingDomains`, in the same order, computed according to EIP-712&apos;s `hashStruct`.

### `authMethods`

This property is an array of supported signature authentication methods, listed in the order that the verifying domain tries them.

Each member of the array is an object with the following keys:

- `id`: An string that identifies the method. It may be one of:
    - `ECDSA`: ECDSA signatures by Externally Owned Accounts.
    - `ERC-{n}`: A standard type of signature specified by an ERC. `n` must not be padded with zeros.
- `parameters` (optional): An array of method-specific parameters.

### JSON Schema

```javascript
{
  type: &apos;object&apos;,
  properties: {
    types: {$ref: &apos;#/$defs/EIP712Types&apos;},
    primaryType: {type: &apos;string&apos;},
    domain: {type: &apos;object&apos;},
    message: {type: &apos;object&apos;},
    signingDomains: {
      type: &apos;array&apos;,
      items: {$ref: &apos;#/$defs/EIP712Types&apos;}
    }
    authMethods: {
      type: &apos;array&apos;,
      items: {
        type: &apos;object&apos;,
        id: {type: &apos;string&apos;},
        parameters: {type: &apos;array&apos;},
        required: [&apos;id&apos;],
      },
    }
  },
  required: [&apos;types&apos;, &apos;primaryType&apos;, &apos;domain&apos;, &apos;message&apos;],
  $defs: {
    EIP712Types: {
      type: &apos;object&apos;,
      properties: {
        EIP712Domain: {type: &apos;array&apos;},
      },
      additionalProperties: {
        type: &apos;array&apos;,
        items: {
          type: &apos;object&apos;,
          properties: {
            name: {type: &apos;string&apos;},
            type: {type: &apos;string&apos;}
          },
          required: [&apos;name&apos;, &apos;type&apos;]
        }
      },
      required: [&apos;EIP712Domain&apos;]
    }
  }
}
```

## Rationale

&lt;!-- TODO --&gt;

## Backwards Compatibility

&lt;!-- TODO --&gt;

## Security Considerations

Needs discussion. &lt;!-- TODO --&gt;

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 08 Oct 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7803</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7803</guid>
      </item>
    
      <item>
        <title>Withdrawal Credential Update Request</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7804-withdrawal-credential-update-request/21514</comments>
        
        <description>## Abstract

This proposal defines a mechanism to allow validators to update their withdrawal
credentials using a new execution request type (0x03). The request allows for
changing the execution address and the withdrawal credential prefix (0x01 or 0x02).

## Motivation

When the ability to update a validator BLS withdrawal credentials to execution
address was introduced in Capella, one of the most common questions was about
allowing the withdrawal credential to be changed in the future.
Either for security (e.g. credential rotation) or to allow for alternative ways
of handling withdrawals (e.g. having a contract address as credentials).
The main reason for not adding this options was because implementing
this communication channel between the Execution Layer and the Consensus Layer is
complex (based on the experience with the Eth1 bridge).

In Electra, the protocol was upgraded with Execution Requests (deposits, withdrawals and
consolidations), and a mechanism for general purpose execution requests
[EIP-7685](/EIPs/EIPS/eip-7685), decreasing the complexity of adding
a new request from execution to consensus layer.

The introduction of execution requests that are created on the execution layer,
opened up possibilities on how validators can be managed.
Execution request can be created via smart contracts, allowing for decentralized
and on-chain mechanisms to be explored.
This also means validators will be able to move between execution and compounding
withdrawal credentials (following the correct churn on the total staked amount).

For an execution request to be authorized in the consensus layer, the withdrawal
credential of the validator must be the same of the `msg.caller` when processing
the transaction on the EVM.
So the validator&apos;s withdrawal credential must be the same address of the smart contract
creating the request (not the credential of the transaction sender), or the contract
needs to use `DELEGATECALL` to ensure the caller address matches the address in the
validator&apos;s withdrawal credential.
Validators that already have a contract address as their withdrawal credentials should
be able to update their contracts to meet this demand (assuming they have an
updatable contract).

There problems for existing validators that have their withdrawal credentials
set to an EOA account is they will never be able to use smart contracts
for creating execution requests, because the current design does not allow for these
credentials to ever be changed.

Allowing for validators to update their withdrawal credentials mean they can opt-in
and out of different schemes and strategies on managing their validators, favouring
experimentation and innovation.
Today, the only alternative to this is exiting the validator and creating a new
validator with different withdrawal credentials.

## Specification

### Constants

| Name | Value | Comment |
| - | - | - |
|`FORK_TIMESTAMP` | *TBD* | Mainnet |

### Configuration

| Name | Value | Comment |
| - | - | - |
| `WITHDRAWAL_CREDENTIALS_UPDATE_REQUEST_PREDEPLOY_ADDRESS` | `0x09Fc772D0857550724b07B850a4323f39112aAaA` | Where to call and store relevant details about the withdrawal credentials update mechanism |
| `WITHDRAWAL_CREDENTIALS_UPDATE_REQUEST_TYPE` | `0x03` | The [EIP-7685](/EIPs/EIPS/eip-7685) type prefix for withdrawal credential update request |
| `SYSTEM_ADDRESS` | `0xfffffffffffffffffffffffffffffffffffffffe` | Address used to invoke system operation on contract
| `EXCESS_WITHDRAWAL_CREDENTIALS_UPDATE_REQUESTS_STORAGE_SLOT` | 0 | |
| `WITHDRAWAL_CREDENTIALS_UPDATE_REQUEST_COUNT_STORAGE_SLOT` | 1 | |
| `WITHDRAWAL_CREDENTIALS_UPDATE_REQUEST_QUEUE_HEAD_STORAGE_SLOT` | 2 | Pointer to head of the withdrawal credential update request message queue |
| `WITHDRAWAL_CREDENTIALS_UPDATE_REQUEST_QUEUE_TAIL_STORAGE_SLOT` | 3 | Pointer to the tail of the withdrawal credential update request message queue|
| `WITHDRAWAL_CREDENTIALS_UPDATE_REQUEST_QUEUE_STORAGE_OFFSET` | 4 | The start memory slot of the in-state withdrawal credential update request message queue|
| `MAX_WITHDRAWAL_CREDENTIALS_UPDATE_REQUESTS_PER_BLOCK` | 4 | Maximum number of withdrawal credential update requests that can be dequeued into a block |
| `TARGET_WITHDRAWAL_CREDENTIALS_UPDATE_REQUESTS_PER_BLOCK` | 1 | |
| `MIN_WITHDRAWAL_CREDENTIALS_UPDATE_REQUEST_FEE` | 1 | |
| `WITHDRAWAL_CREDENTIALS_UPDATE_REQUEST_FEE_UPDATE_FRACTION` | 17 | |
| `EXCESS_INHIBITOR` | `2**256-1` | Excess value used to compute the fee before the first system call |

### Execution Layer

* **`FORK_BLOCK`** -- the first block in a blockchain with the `timestamp` greater or equal to `FORK_TIMESTAMP`.

#### Withdrawal Credentials Update request operation

The new withdrawal credential update request operation is an [EIP-7685](/EIPs/EIPS/eip-7685) request
with type `0x03` and consists of the following fields:

1. `pubkey`: `Bytes48`
2. `old_address`: `Bytes20`
3. `new_address`: `Bytes20`

The [EIP-7685](/EIPs/EIPS/eip-7685) encoding of a withdrawal credential update request is computed as follows.

```python
request_type = WITHDRAWAL_CREDENTIALS_UPDATE_REQUEST_TYPE
request_data = read_withdrawal_credential_update_requests()
```

#### Withdrawal Credentials Update Request Contract

The contract is similar to other execution requests contracts for Deposits, Withdrawals and Consolidation.
The contract has three different code paths, which can be summarized at a high level as follows:

1. Add request - requires a `68` byte input, the validator&apos;s public key concatenated with the new address for withdrawal credentials.
2. Excess requests getter - if the input length is zero, return the current excess requests count.
3. System process - if called by system address, pop off the withdrawal credential update requests for the current block from the queue.

&lt;!-- TODO add sudo code / bytecode / deployment / etc (very similar to existing request contracts) --&gt;

#### Block processing

At the end of processing any execution block where `block.timestamp &gt;= FORK_TIMESTAMP` (i.e. after processing all transactions and after performing the block body requests validations) client software **MUST** include a call the contract as `SYSTEM_ADDRESS` and empty input data to trigger the system subroutine execute. The response should be treated as a new request type (0x03) according to [EIP-7685](/EIPs/EIPS/eip-7685).

#### Block Validation

EL must check that the commitment hash in the execution block header matches the hash of the list of execution requests the CL sends when
validating the execution block (including any requests of the new defined type 0x03).

### Consensus Layer

&lt;!-- TODO complete the specification --&gt;

Summary of changes:

* New container `WithdrawalCredentialUpdateRequest`
* New method in Block Processing: `process_withdrawal_credential_update_request`
* New Beacon State mutator method: `update_withdrawal_credentials`

```python
class WithdrawalCredentialUpdateRequest(Container):
    validator_pubkey: BLSPubkey
    old_address: ExecutionAddress  # request contract will set this to msg.caller
    new_address: ExecutionAddress
```

```python
def process_withdrawal_credential_update_request(state: BeaconState, withdrawal_credentials_update_requests: WithdrawalCredentialUpdateRequest) -&gt; None:
    validator_pubkeys = [v.pubkey for v in state.validators]
    # Verify pubkey exists
    request_pubkey = withdrawal_credentials_update_requests.validator_pubkey
    if request_pubkey not in validator_pubkeys:
        return
    index = ValidatorIndex(validator_pubkeys.index(request_pubkey))
    validator = state.validators[index]

    # Verify withdrawal credentials
    has_correct_credential = has_execution_withdrawal_credential(validator)
    is_correct_old_address = (
        validator.withdrawal_credentials[12:] == withdrawal_credentials_update_requests.old_address
    )
    if not (has_correct_credential and is_correct_old_address):
        return

    credential_type = withdrawal_credentials_update_requests.type
    is_eth1_type = credential_type == ETH1_ADDRESS_WITHDRAWAL_PREFIX
    is_compounding_type = credential_type == COMPOUNDING_WITHDRAWAL_PREFIX
    # Verify valid type
    if not (is_eth1_type or is_compounding_type):
        return;

    update_withdrawal_credentials(state, index, credential_type, withdrawal_credentials_update_requests.new_address)
```

```python
def update_withdrawal_credentials(state: BeaconState, index: ValidatorIndex, new_credential_type: Bytes1, new_withdrawal_credentials: ExecutionAddress) -&gt; None:
    old_credential_type = validator.withdrawal_credentials[:1]

    validator = state.validators[index]
    validator.withdrawal_credentials = (
        new_credential_type
        + b&apos;\x00&apos; * 11
        + new_withdrawal_credentials
    )

    # If moving from 0x01 to 0x02
    if (old_credential_type == ETH1_ADDRESS_WITHDRAWAL_PREFIX and new_credential_type == COMPOUNDING_WITHDRAWAL_PREFIX) {
      #TODO: in this case we need to ensure we put them through the churn/likely re-using some of the exiting rules
      switch_to_compounding_validator(state, index)
    }
```

## Rationale

&lt;!-- TODO --&gt;

## Backwards Compatibility

&lt;!-- TODO --&gt;

## Test Cases

&lt;!-- TODO --&gt;

## Security Considerations

Ownership is defined based on control of the withdrawal credential account, either as a private key (for EOA accounts) or controlling
the smart contract at the address set as withdrawal credential. Therefore allowing an update should not bring any security implications.

Further discussion needed.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 31 Oct 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7804</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7804</guid>
      </item>
    
      <item>
        <title>Fork-choice enforced Inclusion Lists (FOCIL)</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7805-committee-based-fork-choice-enforced-inclusion-lists-focil/21578</comments>
        
        <description>## Abstract

FOCIL implements a robust mechanism to preserve Ethereum’s censorship resistance properties by guaranteeing timely transaction inclusion.

FOCIL (**Fo**rk-**c**hoice enforced **I**nclusion **L**ists) is built in a few simple steps:

- In each slot, a set of validators is selected as inclusion list (IL) committee members. Each member builds and gossips one IL according to their subjective view of the mempool.
- The proposer and all attesters of the next slot monitor, store and forward available ILs.
- The proposer (or the builder if the block is not built locally by the proposer) includes transactions from all collected ILs in its block. The proposer then broadcasts the block including IL transactions to the rest of the network.
- Attesters only vote for the proposer&apos;s block if it includes transactions from all stored ILs.

## Motivation

In an effort to shield the Ethereum validator set from centralizing forces, the right to build blocks has been auctioned off to specialized entities known as *builders*. This has led to a few sophisticated builders dominating block production, leading to a deterioration of the network’s censorship resistance properties. To address this issue, research has focused on improving Ethereum&apos;s transaction inclusion guarantees by enabling validators to impose constraints on builders. This is achieved by force-including transactions in blocks via ILs.

### High-level Overview

FOCIL is a committee-based, fork-choice enforced inclusion list (IL) design that improves upon previous IL mechanisms and block co-creation proposals. It addresses issues related to bribing/extortion attacks, IL equivocation, account abstraction (AA), and transaction invalidation.

![FOCIL diagram](/EIPs/assets/eip-7805/diagram_FOCIL.png)

### Roles And Participants

This section outlines the workflow of FOCIL, detailing the roles and responsibilities of various participants: IL committee members, validators, builders, proposers and attesters.

#### IL Committee Members

- **`Slot N`, `t=0 to 8s`**:
IL committee members construct their ILs by including transactions pending in the public mempool, and broadcast them over the P2P network after processing the block for `slot N` and confirming it as the head. If no block is received by `t=7s`, they should run `get_head` and build and release their ILs based on the node’s local head.

IL committee members may follow different strategies for constructing their ILs as discussed in [IL Building](#il-building).

#### Validators

- **`Slot N`, `t=0s to 9s`**: Validators receive ILs from the P2P network and store (1) all new ILs that pass the CL P2P validation rules, and (2) any evidence of IL equivocation by committee members (i.e., if multiple ILs are received from the same committee member).

- **`Slot N`, `t=9s` to `Slot N+1`, `t=4s`**: After the view freeze deadline at `t=9s`, validators:
  1. Do not store new ILs received after the deadline.
  2. Continue forwarding ILs to peers following the CL P2P validation rules.
  3. Record any evidence of IL equivocation that occurs after the view freeze deadline.

After the attestation deadline of **`Slot N+1`, `t=4s`**, validators ignore any new ILs related to the previous slot&apos;s IL committee, and stop recording equivocation evidence for the previous slot&apos;s ILs.

#### Builder

- **`Slot N`, `t=0s to 11s`**: The builder (i.e., a proposer doing local block building or an external builder) receives ILs from the P2P network, forwarding and caching those that pass the CL P2P validation rules. Optionally, an RPC endpoint can be added to allow the builder to request missing ILs from its peers (e.g., by committee index at `t=10s`).

- **`Slot N`, `t=11s`**:
The builder freezes its view of ILs and asks the EL to update its execution payload by adding transactions from its view (the exact timings will be defined after running some tests/benchmarks).

#### Proposer

- **`Slot N+1`, `t=0s`**:
The proposer broadcasts its block with the up-to-date execution payload satisfying IL transactions over the P2P network.

#### Attesters

- **`Slot N+1`, `t=4s`**:
Attesters monitor the P2P network for the proposer’s block. Upon detecting it, they verify whether all transactions from their stored ILs are included in the proposer’s execution payload, except for ILs whose sender has equivocated. Based on their frozen view of the ILs from `t=9s` in the previous slot, attesters check if the execution payload satisfies IL conditions. This is done either by confirming that all transactions are present or by determining if any missing transactions are invalid when appended to the end of the payload. In such cases, attesters use the EL to perform nonce and balance checks to validate the missing transactions and check whether there is enough space in the block to include the transaction(s).

#### CL P2P Validation Rules

When validators receive ILs from the P2P network, they perform a series of validation checks before forwarding or caching them. These rules protect against Denial-of-Service attacks by (1) limiting ILs&apos; byte size and (2) restricting IL proposals to a small committee of IL committee members, thereby tightly bounding bandwidth, the main resource consumed by the propagation of ILs. Consumption of other relevant resources, such as verification time, is minimal because the only nontrivial check performed on IL propagation is signature verification. At this stage, there is no EL verification of the transactions within ILs. This means that ILs are allowed to contain any transactions—valid or invalid—since validators do not perform EL-side validity checks. This design choice is intended to avoid additional computational overhead.

1. The slot of the IL matches the current or previous slot.
2. The root of the IL committee referenced in the IL matches the expected IL committee root for its slot.
3. Received two or fewer ILs from this IL committee member (see IL equivocation section below).
4. The IL is correctly signed by the validator.
5. The validator is part of the IL committee.
6. The size of a IL does not exceed the maximum size allowed (e.g., `MAX_BYTES_PER_INCLUSION_LIST = 8 KiB`).

## Specification

### Execution Layer

On the execution layer, an additional check is introduced for new payloads. After all of the transactions in the payload have been executed, we check whether any transaction from ILs, that is not already present in the payload, could be validly included (i.e. nonce and balance checks pass). If that is the case for any transaction, then an error is returned to the CL. Although the block is valid, the CL will not attest to it.

Let `B` denote the current block.
Let `S` denote the execution state following the execution of the last transaction in `B`.
Let `gas_left` be the gas remaining after execution of B.

For each transaction `T` in ILs, perform the following:

1. Check whether `T` is present in `B`. If `T` is present, then jump to the next transaction, else continue with next step.

2. Check whether `B` has enough remaining gas to execute `T`. If `T.gas` &gt; `gas_left`, then jump to the next transaction, else continue with next step.

3. Validate `T` against `S` by checking the nonce and balance of `T.origin`.

  - If `T` is invalid, then continue to the next transaction. 
  
  - If `T` is valid, terminate process and return an `INCLUSION_LIST_UNSATISFIED` status.

#### Engine API Changes

We make the following changes to the engine API:

- Add `engine_getInclusionListV1` endpoint to retrieve an IL from the `ExecutionEngine`.
- Modify `engine_forkchoiceUpdated` endpoint to update a payload with the IL that should be used to build the block. `payloadAttributes` is extended to include the IL.
- Modify `engine_newPayload` endpoint to include a parameter for transactions in ILs determined by the IL committee member. If the IL is not satisfied an `INCLUSION_LIST_UNSATISFIED` status must be returned.

#### IL Building

The rules for building ILs are left to the discretion of implementers. For instance, they may select transactions from the public mempool in various ways such as at random, by priority fee, or based on how long they have been pending. The IL has a maximum size of `MAX_BYTES_PER_INCLUSION_LIST = 8 KiB` for all of the RLP encoded transactions.

### Consensus Layer

The full consensus changes can be found in the following GitHub repository. They are split between: 

- [Beacon Chain](https://github.com/ethereum/consensus-specs/blob/e678deb772fe83edd1ea54cb6d2c1e4b1e45cec6/specs/_features/eip7805/beacon-chain.md) changes.
- [Fork choice](https://github.com/ethereum/consensus-specs/blob/e678deb772fe83edd1ea54cb6d2c1e4b1e45cec6/specs/_features/eip7805/fork-choice.md) changes.
- [P2P](https://github.com/ethereum/consensus-specs/blob/e678deb772fe83edd1ea54cb6d2c1e4b1e45cec6/specs/_features/eip7805/p2p-interface.md) changes.
- [Honest validator guide](https://github.com/ethereum/consensus-specs/blob/e678deb772fe83edd1ea54cb6d2c1e4b1e45cec6/specs/_features/eip7805/validator.md) changes.

#### Beacon chain changes

##### Preset

| Name | Value |
| - | - |
| `DOMAIN_IL_COMMITTEE`       | `DomainType(&apos;0x0C000000&apos;)`  |
| `IL_COMMITTEE_SIZE` | `uint64(2**4)` (=16)  |
| `MAX_BYTES_PER_INCLUSION_LIST` |  `uint64(2**13)` (=8192) | 

##### New containers

```python
class InclusionList(Container):
    slot: Slot
    validator_index: ValidatorIndex
    inclusion_list_committee_root: Root
    transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD]
```

```python
class SignedInclusionList(Container):
    message: InclusionList
    signature: BLSSignature
```

#### Fork choice changes

- Store ILs observed over gossip before the view freeze deadline.
- If more than one IL is observed from the same IL committee member, mark the committee member as an equivocator and ignore any further ILs from them.
- The beacon block from the current slot is only attested to if it satisfies IL conditions, based on all stored ILs from non equivocators.
  
#### P2P changes

- A new global topic for broadcasting `SignedInclusionList` objects.
- A new RPC topic for request `SignedInclusionList` based on IL committee index.

## Rationale

### Core Properties

- Committee-based: FOCIL relies on a committee of multiple validators, rather than a single proposer, to construct and broadcast ILs. This approach significantly reduces the surface for bribery and extortion attacks and strengthens censorship resistance.
- Fork-choice enforced: FOCIL incorporates the force-inclusion mechanism into the fork-choice rule, an integral component of the consensus process, thereby preventing any actor from bypassing the system. Attesters vote only for blocks that include transactions from a set of ILs provided by the IL committee and that satisfy the IL constraints. Any block failing to meet these criteria will not be voted on by the attesters, and therefore cannot be canonical.
- Same-slot: With FOCIL running in parallel with the block building process for `slot N+1` during `slot N`, the constraints imposed on `block B` for `slot N+1` can include transactions submitted during `slot N`. This represents a strict improvement over forward IL designs like [EIP-7547](/EIPs/EIPS/eip-7547), where the forward property introduced a 1-slot delay.
- Conditional inclusion: FOCIL adopts conditional inclusion, accepting blocks that may lack some transactions from ILs if they cannot append the transactions to the end of the block or if they are full.
- Anywhere-in-block: FOCIL is unopinionated about the placement of transactions from ILs within a block. This reduces incentives for sophisticated actors to use side channels to bypass the mechanism. Combined with conditional inclusion, this flexibility makes the emergence of off-protocol markets less attractive.
- No incentive mechanism: FOCIL does not provide explicit rewards for IL committee members participating in the mechanism. We believe that the added complexity of implementing a transaction fee system for FOCIL is not justified. Instead, we rely on altruistic behavior, as FOCIL requires only a `1-out-of-N` honesty assumption from IL committee members for the mechanism to work as intended.

## Backwards Compatibility

This EIP introduces backward incompatible changes to the block validation rule set on the consensus layer and must be accompanied by a hard fork. These changes do not break anything related to current user activity and experience.

## Security Considerations

### Consensus Liveness

The builder of `slot N+1` cannot construct a canonical block without first receiving the ILs broadcast during `slot N`. This means that the builder (including cases in which the proposer locally builds its block) must be well-connected to the IL committee members to ensure timely access to these inclusion lists. Additionally, there must be sufficient time between the view freeze deadline (`t=9s` of `slot N`) and the moment the proposer must broadcast `block B` to the rest of the network. This buffer allows the builder to gather all available ILs and update the execution payload of `block B` accordingly.

### IL Equivocation

To mitigate IL equivocation, FOCIL introduces a new P2P network rule that allows forwarding up to two ILs per IL committee member. If the proposer or attesters detect two different ILs sent by the same IL committee member, they should ignore all ILs from that member. In the worst case, the bandwidth of the IL gossip subnet can at most double.

### Payload Construction

The builder, responsible for constructing the execution payload, must ensure that the IL is satisfied. A naive way to do so would be to build an initial payload in whatever way the builder desires, then execute the following algorithm:

1. Sequentially check validity of any yet-to-be-included IL tx against the post-state. If none is found, payload building is over.
2. If one is found, append it to the end of the payload and update the post-state. Go back to step 1.

The issue with this simple approach is that, given a set of `n` IL transactions, one might end up needing to do `n + (n-1) + (n-2) + ...` validity checks, so `O(n^2)`. For example, the `n`th tx might be valid while all others are not, but its execution sends balance to the sender of the `(n-1)`th tx, making it valid, and in turn, the `(n-1)`th sends balance to the sender of the `(n-2)`th tx, etc.

To efficiently ensure that all valid IL txs have been included in the payload, builders can adopt a simple strategy: prior to building the payload, they store the `nonce` and `balance` of all Externally Owned Accounts (EOAs) involved in IL transactions. As they construct the payload, builders track these EOAs, maintaining and updating each EOA&apos;s `nonce` and `balance` whenever changes occur—specifically, when the `nonce` increments (indicating that a transaction from that EOA has been executed) or when the `balance` changes without a `nonce` increment (e.g., after an Account Abstraction (AA) transaction has interacted with that EOA). 

This tracking allows builders to verify IL transaction validity in real-time, enabling them to add transactions sequentially until all remaining transactions are either invalid because the nonce or balance of the associated EOA does not change or cannot be included due to insufficient gas. This approach minimizes overhead by keeping track only of the state changes that are relevant to the validity of IL txs.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 01 Nov 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7805</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7805</guid>
      </item>
    
      <item>
        <title>Minimal intent-centric EOA smart account</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7806-minimal-intent-centric-eoa-smart-account/21565</comments>
        
        <description>## Abstract

This proposal defines a standard interface for intent-centric smart accounts. It enables externally owned accounts (EOAs) to delegate contract code to a smart account implementation, allowing them to sign intents. These intents can then be executed by solvers (or relayers) on behalf of the account owner, streamlining interactions and expanding the capabilities of EOAs.

## Motivation

Account Abstraction (AA) is a highly discussed topic in the blockchain industry, as it enhances the programmability of accounts, enabling features such as:

* **Batch Execution**
* **Gas Sponsorship**
* **Access Control**

The introduction of [ERC-4337](/EIPs/EIPS/eip-4337) established a permissionless standard for AA, unlocking a wide range of powerful features. However, ERC-4337 has several limitations:

* **Complexity**: The standard requires multiple interdependent components, including the Account, EntryPoint, Paymaster, Bundler, and additional plugins ([ERC-6900](/EIPs/EIPS/eip-6900), [ERC-7579](/EIPs/EIPS/eip-7579). Running a bundler demands significant engineering expertise and introduces operational overhead.
* **Compatibility**: Component dependencies make upgrades cumbersome, often requiring multiple smart contracts to be updated simultaneously. This creates fragmentation within the ecosystem.
  one version update, also divides the ecosystem.
* **Cost**: Processing `UserOperation` transactions consumes a high amount of gas.
* **Trust Assumption**: Despite being designed as a permissionless standard, ERC-4337 still relies on centralized entities. Paymasters, for instance, are typically centralized, as they must either trust account owners to reimburse gas costs or manage external funding sources. Similarly, bundlers operate within a miner extractable value (MEV) environment, requiring users to trust them for transaction inclusion.

[ERC-7521](/EIPs/EIPS/eip-7521) introduced a smart contract account (SCA) solution with an intent-centric design. It allows solvers to fulfill account owners&apos; intents while maintaining flexibility for custom execution logic and ensuring forward compatibility.

With the introduction of `SET_CODE_TX_TYPE=0x04`, EOAs can now set contract code dynamically, granting them programmability similar to SCAs. This presents an opportunity to develop a new standard that extends AA capabilities to EOAs while addressing the aforementioned challenges.

By simplifying execution, improving efficiency, and enhancing user experience, this proposal aims to accelerate the adoption of intent-centric account abstraction smart contracts.

### Solvers, Relayers, Paymasters, and Bundlers—All in One

In an intent-centric system, solvers play a crucial role in fulfilling user intents and are rewarded accordingly. This proposal introduces an open execution model, where any solver can participate, fostering a competitive environment that benefits users.

With integrated gas abstraction, solvers can cover gas fees using native tokens while receiving other tokens from the EOA account as compensation. Additionally, solvers can further optimize costs by bundling multiple intent executions into a single blockchain transaction.

Each solver is free to develop its own strategies for maximizing profitability. This proposal does not impose restrictions on how solvers execute intents, ensuring flexibility and adaptability in diverse execution scenarios.

## Specification

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

### `UserIntent` schema

Each intent is a packed data structure containing sufficient information about the operations the account owner wants to execute. The core structure of a `UserIntent` object is as follows:

| Field          | Type      | Description                                                                                                     |
|----------------|-----------|-----------------------------------------------------------------------------------------------------------------|
| `sender`       | `address` | The address of the account initiating the intent.                                                               |
| `standard`     | `address` | The `IStandard` implementation responsible for validating and parsing the `UserIntent`                          |
| `header`       | `bytes`   | Metadata associated with the `UserIntent`, interpreted by `standard`. Stored as bytes for flexibility.          |
| `instructions` | `bytes[]` | The execution details of the `UserIntent`, interpreted by `standard`. Stored as `bytes[]` to allow flexibility. |
| `signatures`   | `bytes[]` | Validatable signatures required for execution, interpreted by `standard`.                                       |

#### Fields Explanations

* `header`: The `bytes header` can carry information about how to validate the intent or how to prevent
  double-spending. For example, `header` can contain an `uint256 nonce` to check if the `nonce` is used already.
* `instructions`: These `bytes instructions` can just be concatenated `(address,value,calldata)` or can be
  standardized values, for example `(erc20TokenAddress,1000)` means the `instructions` can use up to 1000 of the
  specified [ERC-20](/EIPs/EIPS/eip-20) token. It is NOT REQUIRED that all `instructions` MUST be provided by the EOA owner to allow dynamically carry out other operations during intent executions, but the `IStandard` design needs to carefully handle this case.
* `signatures`: The `bytes signatures` field can support different signing methods. It is NOT REQUIRED that
  all `signatures` MUST be provided by the EOA owner, some of them MAY be provided by solver, relayer or anyone else.

### Pack `UserIntent` as Bytes

The `UserIntent` object is packed and encoded into `bytes calldata userIntent`. There is no strict schema requirement for the data structure. Each `IAccount` and `IStandard` implementation can define its own encoding and decoding methods for handling the `bytes` data.

Here is an example of packed-encoded format:

| Section                         | Value Type | Description                                              |
|---------------------------------|------------|----------------------------------------------------------|
| userIntent[0:20]                | `address`  | `sender`                                                 |
| userIntent[20:40]               | `address`  | `standard`                                               |
| userIntent[40:42]               | `uint16`   | Length of `header`                                       |
| userIntent[42:44]               | `uint16`   | Length of `instructions`                                 |
| userIntent[44:46]               | `uint16`   | Length of `signatures`                                   |
| Next `headerLength` bytes       | `bytes`    | The actual `header` data                                 |
| Next `instructionsLength` bytes | `bytes`    | The actual `instructions` data                           |
| Next `signatureLength` bytes    | `bytes`    | The actual `signatures` data                             |
| Remaining bytes                 | `bytes`    | Extra data, such as nested intents for further execution |

### `IStandard` Interface

Each standard defines how to parse and validate a `UserIntent`. Implementations of standard must conform to the `IStandard` interface:

```solidity
interface IStandard {
    /**
     * Validate user&apos;s intent
     *
     * @dev returning validation result, the type uses bytes4 for extensibility purpose
     * @return result values representing validation outcomes
     */
    function validateUserIntent(bytes calldata intent) external view returns (bytes4 result);

    /**
     * Unpack user&apos;s intent, it is RECOMMENDED to validate intent while unpacking to save gas
     *
     * @dev returning unpacked result, the type uses bytes for extensibility purpose
     * @return result unpacked result status
     * @return operations unpacked operations that can be executed by the IAccount, NOT REQUIRED to match UserIntent.instructions
     */
    function unpackOperations(bytes calldata intent) external view returns (bytes4 result, bytes[] memory operations);
}
```

The `IStandard` interface is responsible for defining and enforcing the validation logic for `UserIntent` objects.

It operates similarly to the `EntryPoint` in ERC-4337 and ERC-7521.

The extensibility of `bytes4` return types allows future upgrades without modifying the function signatures.

### `IAccount` Interface

On the account side, `IAccount` provides the interface for executing `bytes calldata intent`:

```solidity
interface IAccount {
    /**
     * Execute user&apos;s intent
     * 
     * @dev returning execution result, the type uses bytes for extensibility purpose
     * @return result values representing execution outcomes
     */
    function executeUserIntent(bytes calldata intent) external returns (bytes memory);
}
```

Using `SET_CODE_TX_TYPE=0x04`, EOAs can delegate contract code to an `IAccount` implementation, enabling them to function as smart accounts. A single account implementation can be shared across multiple EOAs, meaning:
- It only needs to be deployed and audited once.
- Each EOA owner is responsible for delegating their account to a secure `IAccount` implementation.

It is RECOMMENDED that each account leverages `IStandard` to validate and unpack operations, check **Reference
Implementation** for examples. Account smart contract can be stateless to avoid sharing storage space with other delegated contracts.

## Rationale

### Usage of Bytes

Defining `UserIntent` object as a struct would improve readability and make it easier to work with in Solidity. For example:

```solidity
struct UserIntent {
    address sender;
    address standard;
    bytes header;
    bytes[] instructions;
    bytes[] signatures;
}
```

However, this approach has several drawbacks:

- Mandating all `IAccount` and `IStandard` implementations to follow this specific struct format reduces flexibility.
- The use of `bytes[]` introduces additional gas costs due to Solidity&apos;s dynamic array encoding.

Since all objects within the UserIntent structure are optional and their usage depends on `IStandard` and `IAccount` implementations, the bytes format ensures maximum flexibility while preserving compatibility.

### Execution in EOA Contract Code

With `SET_CODE_TX_TYPE=0x04`, EOAs gain the ability to execute contract code. Executing transactions directly from an EOA provides several key benefits:

- **Preserves EOA Control**: Execution remains fully controlled by the account owner. If needed, the EOA owner can easily disable all smart contract functionalities by un-delegating the contract code.
- **Consistent `msg.sender` Behavior**: Since the execution originates from an EOA, `msg.sender` always resolves to the EOA address, simplifying authentication and permission checks.
- **Stateless Execution**: The execution logic can be designed to be stateless, allowing the `IAccount` implementation to avoid storing persistent data, reducing storage costs.

If an EOA does not require smart contract execution, or if executing an intent is too expensive, the owner can still use the account as a regular EOA without any modifications.

### Validation in the Standard Contract

Validation logic often relies on contract state. For example, a weighted multi-owner signature scheme needs to track the weight assigned to each signer. Keeping intent validation entirely within `IStandard` offers multiple advantages:

- **Simplified Implementation**: By mirroring the `EntryPoint` concept from ERC-4337 but in a simpler form, `IStandard` focuses solely on validation.
- **Easier Auditing and Maintenance**: Since `IStandard` is responsible only for validation, it becomes easier for contract engineers to implement, audit, and maintain.
- **Modular Validation**: The `IStandard` interface is inherently modular, allowing for more complex validation mechanisms. For instance, a &quot;compound&quot; standard could decompose an intent into smaller components, validate each separately, and then combine the results.

### Gas Abstraction

This design enables gasless transactions by allowing any address to initiate a transaction on behalf of the intent&apos;s sender.

- The sender can specify how and what to pay in the intent’s `header` or `instructions`.
- Payments can be made in any token from the sender’s account.
- The transaction cost can be covered by transferring tokens from the sender’s account to `tx.origin` (the address submitting the transaction).

### No re-entry protection enforced

This proposal does not enforce built-in re-entry protection mechanisms such as nonces. The rationale behind this decision is that certain intents are inherently designed to be executed multiple times.

Instead of a global re-entry protection mechanism, each standard should define its own protection rules based on its intended use case. Implementers are encouraged to:

## Backwards Compatibility

This `IAccount` standard shares the same backwards compatibility considerations as the introduction of EOA contract code execution (`SET_CODE_TX_TYPE=0x04`).

## Reference Implementation

### Helper Library

This `PackedIntent` is a library to decode `(address sender, address standard, uint16 headerLength, uint16 instructionsLength, uint16 signaturesLength)` from a packed encoded intent. The following `IAccount` and `IStandrd` implementations both follow `PackedIntent` schema.

```solidity
/// @title PackedIntent
/// @notice This is a library that packs metadata of intent (sender, standard, lengths) into bytes
/// @dev the packed intent data schema is defined as follows:
/// @dev 1. sender: address, 20-bytes
/// @dev 2. standard: address, 20-bytes
/// @dev 3. headerLength: uint16, 2-bytes
/// @dev 4. instructionLength: uint16, 2-bytes
/// @dev 5. signatureLength: uint16, 2-bytes
library PackedIntent {
    /// @notice getSenderAndStandard is a function that gets the sender and standard from the intent
    /// @param intent The intent to get the sender and standard from
    /// @return sender The sender of the intent
    /// @return standard The standard of the intent
    function getSenderAndStandard(bytes calldata intent) external pure returns (address, address) {
        require(intent.length &gt;= 40, &quot;Intent too short&quot;);
        return (address(bytes20(intent[: 20])), address(bytes20(intent[20 : 40])));
    }

    /// @notice getLengths is a function that gets the lengths from the intent
    /// @param intent The intent to get the lengths from
    /// @return headerLength The length of the header
    /// @return instructionLength The length of the instructions
    /// @return signatureLength The length of the signature
    function getLengths(bytes calldata intent) external pure returns (uint256, uint256, uint256) {
        require(intent.length &gt;= 46, &quot;Missing length section&quot;);
        return (
        uint256(uint16(bytes2(intent[40 : 42]))),
        uint256(uint16(bytes2(intent[42 : 44]))),
        uint256(uint16(bytes2(intent[44 : 46])))
        );
    }

    /// @notice getSignatureLength is a function that gets the signature length from the intent
    /// @param intent The intent to get the signature length from
    /// @return signatureLength The length of the signature
    function getSignatureLength(bytes calldata intent) external pure returns (uint256) {
        require(intent.length &gt;= 46, &quot;Missing length section&quot;);
        return uint256(uint16(bytes2(intent[44 : 46])));
    }

    /// @notice getIntentLength is a function that gets the intent length from the intent
    /// @param intent The intent to get the intent length from
    /// @return result The sum of header, instruction and signature lengths
    function getIntentLength(bytes calldata intent) external pure returns (uint256) {
        require(intent.length &gt;= 46, &quot;Missing length section&quot;);
        uint256 headerLength = uint256(uint16(bytes2(intent[40 : 42])));
        uint256 instructionLength = uint256(uint16(bytes2(intent[42 : 44])));
        uint256 signatureLength = uint256(uint16(bytes2(intent[44 : 46])));
        return headerLength + instructionLength + signatureLength + 46;
    }

    /// @notice getIntentLengthFromSection is a function that gets the intent length from the length section
    /// @param lengthSection The length section to get the intent length from
    /// @return result The sum of header, instruction and signature lengths
    function getIntentLengthFromSection(bytes6 lengthSection) external pure returns (uint16 result) {
        assembly {
            let value := lengthSection
            let a := shr(240, value) // Extract first 2 bytes
            let b := and(shr(224, value), 0xFFFF) // Extract next 2 bytes
            let c := and(shr(208, value), 0xFFFF) // Extract last 2 bytes
            result := add(add(add(a, b), c), 46)
        }
    }
}

```

### Relayed Execution Standard

This `RelayedExecutionStandard` allows relayer to execute the operations on chain and take [ERC-20](/EIPs/EIPS/eip-20) token from the intent sender, thus achieve a gas-less experience for the sender.

```solidity
import {MessageHashUtils}
import {ECDSA}
import {IERC20}
import {IStandard}
import {IAccount}
import {PackedIntent}

/// @title ERC7806Constants
/// @notice This is a library that defines the constants for the ERC7806 standard
library ERC7806Constants {
/// @notice VALIDATION_DENIED is the magic value of denied intent
bytes4 public constant VALIDATION_DENIED = 0x00000000;

/// @notice VALIDATION_APPROVED is the magic value of validated intent
bytes4 public constant VALIDATION_APPROVED = 0x00000001;
}

abstract contract HashGatedStandard is IStandard {
    event HashUsed(address sender, uint256 hash);

    mapping(bytes32 =&gt; bool) internal _hashes;

    function checkHash(address sender, uint256 hash) external view returns (bool) {
        bytes32 compositeKey = keccak256(abi.encode(sender, hash));
        return _hashes[compositeKey];
    }

    function markHash(uint256 hash) external {
        bytes32 compositeKey = keccak256(abi.encode(msg.sender, hash));
        _hashes[compositeKey] = true;

        emit HashUsed(msg.sender, hash);
    }
}

/*
RelayedExecutionStandard

This standard allows sender to define a list of execution instructions and asks the relayer to execute
on chain on behalf of the sender. It is hash and time gated means the intent can only be executed before
a timestamp and can only be executed once.

The first 20 bytes of the `intent` is sender address.
The next 20 bytes of the `intent` is the standard address, which should be equal to address of this standard.
The following is the length section, containing 3 uint16 defining header length, instructions length and signature length.

The header is either 8 bytes long or 28 bytes long.
The 8-byte part is the timestamp in epoch seconds.
The optional 20-byte defines the assigned relayer address if the sender only wants a specific relayer to execute.

The instructions contains 2 main part.
The first 36 bytes is a packed encoded (address, uint128) pair representing the &apos;payment&apos; that the sender will pay to the
relayer. It should be an ERC20 token.
The following 1-byte is an uint8 defining the number of instructions to execute.
The instructions are concatenated together, the first 2 bytes (uint16) defines the length of each instruction, the following
is the instruction body. Instructions should be abi.encode(address, uint256, bytes) which can directly be executed by
the sender account.

The signature field is always 65 bytes long. It contains the signed bytes.concat(header, instructions).
*/
contract RelayedExecutionStandard is HashGatedStandard {
    using ECDSA for bytes32;

    string public constant ICS_NUMBER = &quot;ICS1&quot;;
    string public constant DESCRIPTION = &quot;Timed Hashed Relayed Execution Standard&quot;;
    string public constant VERSION = &quot;0.0.0&quot;;
    string public constant AUTHOR = &quot;hellohanchen&quot;;

    function validateUserIntent(bytes calldata intent) external view returns (bytes4) {
        (address sender, address standard) = PackedIntent.getSenderAndStandard(intent);
        require(standard == address(this), &quot;Not this standard&quot;);
        (uint256 headerLength, uint256 instructionsLength, uint256 signatureLength) = PackedIntent.getLengths(intent);
        require(headerLength == 28 || headerLength == 8, &quot;Invalid header length&quot;);
        require(instructionsLength &gt;= 36, &quot;Instructions too short&quot;);
        require(signatureLength == 65, &quot;Invalid signature length&quot;);
        // end of instructions
        uint256 instructionsEndIndex = 46 + headerLength + instructionsLength;
        require(instructionsLength + signatureLength == intent.length, &quot;Invalid intent length&quot;);

        // validate signature
        uint256 hash = _validateSignatures(sender, intent, instructionsEndIndex);
        require(!this.checkHash(sender, hash), &quot;Hash is already executed&quot;);

        // header contains expiration timestamp and assigned relayer (optional)
        require(uint256(uint64(bytes8(intent[46 : 54]))) &gt;= block.timestamp, &quot;Intent expired&quot;);
        // assignedRelayerAddress = address(intent[54:74]) [optional]

        // end of header section / begin of instruction section
        uint256 headerEndIndex = 46 + headerLength;
        // first 20 bytes of instruction is out token address
        address outTokenAddress = address(bytes20(intent[headerEndIndex : headerEndIndex + 20]));
        // out token amount, use uint128 to shorten the intent
        uint256 outTokenAmount = uint256(uint128(bytes16(intent[headerEndIndex + 20 : headerEndIndex + 36])));
        if (outTokenAddress != address(0)) {
            (bool success, bytes memory data) = outTokenAddress.staticcall(
                abi.encodeWithSelector(IERC20.balanceOf.selector, sender)
            );
            if (!success || data.length != 32) {
                revert(&quot;Not ERC20 token&quot;);
            }
            require(abi.decode(data, (uint256)) &gt;= outTokenAmount, &quot;Insufficient token balance&quot;);
        } else {
            require(sender.balance &gt;= outTokenAmount, &quot;Insufficient eth balance&quot;);
        }

        // end of outToken instruction
        uint256 numExecutions = uint256(uint8(bytes1(intent[headerEndIndex + 36 : headerEndIndex + 37])));
        // instruction index
        uint256 instructionIndex = 0;
        // begin of the first instruction
        uint256 instructionStart;
        uint256 instructionEnd = headerEndIndex + 37;

        while (instructionIndex &lt; numExecutions) {
            instructionStart = instructionEnd;
            require(instructionStart + 2 &lt;= instructionsEndIndex, &quot;Intent too short: instruction length&quot;);
            // end of this execution instruction
            instructionEnd = instructionStart + 2 + uint256(uint16(bytes2(intent[instructionStart : instructionStart + 2])));
            require(instructionEnd &lt;= instructionsEndIndex, &quot;Intent too short: single instruction&quot;);

            instructionIndex += 1;
        }
        require(instructionEnd == instructionsEndIndex, &quot;Intent length doesn&apos;t match&quot;);

        return ERC7806Constants.VALIDATION_APPROVED;
    }

    function unpackOperations(bytes calldata intent) external view returns (bytes4 code, bytes[] memory unpackedInstructions) {
        (address sender, address standard) = PackedIntent.getSenderAndStandard(intent);
        require(standard == address(this), &quot;Not this standard&quot;);
        (uint256 headerLength, uint256 instructionsLength, uint256 signatureLength) = PackedIntent.getLengths(intent);
        require(headerLength == 28 || headerLength == 8, &quot;Invalid header length&quot;);
        require(instructionsLength &gt;= 36, &quot;Instructions too short&quot;);
        require(signatureLength == 65, &quot;Invalid signature length&quot;);
        // end of instructions
        uint256 instructionsEndIndex = 46 + headerLength + instructionsLength;
        require(instructionsLength + signatureLength == intent.length, &quot;Invalid intent length&quot;);

        // fetch header content (timestamp, relayer address [optional])
        require(uint256(uint64(bytes8(intent[46 : 54]))) &gt;= block.timestamp, &quot;Intent expired&quot;);
        if (headerLength == 28) {
            // assigned relayer
            require(tx.origin == address(bytes20(intent[54 : 74])), &quot;Invalid relayer&quot;);
        }

        uint256 intentHash = _validateSignatures(sender, intent, instructionsEndIndex);
        require(!this.checkHash(sender, intentHash), &quot;Hash is already executed&quot;);

        // begin of instructions
        uint256 headerEndIndex = headerLength + 46;
        // total instructions = mark hash + transfer token to relayer + executions
        // the first 36 bytes defines the payment to relayer
        // the next 1 byte defines the number of execution instructions
        unpackedInstructions = new bytes[](2 + uint8(bytes1(intent[headerEndIndex + 36 : headerEndIndex + 37])));
        // first instruction is mark hash to prevent re-entry attack
        unpackedInstructions[0] = abi.encode(
            address(this), 0, abi.encodeWithSelector(this.markHash.selector, intentHash));

        // the first 20 bytes of instructions is the out token address
        address outTokenAddress = address(bytes20(intent[headerEndIndex : headerEndIndex + 20]));
        // amount
        uint256 outTokenAmount = uint256(uint128(bytes16(intent[headerEndIndex + 20 : headerEndIndex + 36])));
        // out token instruction
        if (outTokenAddress == address(0)) {
            unpackedInstructions[1] = abi.encode(address(tx.origin), outTokenAmount, &quot;&quot;);
        } else {
            unpackedInstructions[1] = abi.encode(
                outTokenAddress,
                uint256(0),
                abi.encodeWithSelector(IERC20.transfer.selector, address(tx.origin), outTokenAmount));
        }

        // instruction index
        uint256 instructionIndex = 2;
        uint256 instructionEndIndex = headerEndIndex + 37;
        uint256 instructionStartIndex;
        while (instructionIndex &lt; unpackedInstructions.length) {
            // start of next execution instruction
            instructionStartIndex = instructionEndIndex;
            require(instructionStartIndex + 2 &lt;= instructionEndIndex, &quot;Intent too short: instruction length&quot;);
            // end of next execution instruction
            instructionEndIndex = instructionStartIndex + 2 + uint256(uint16(bytes2(intent[instructionStartIndex : instructionStartIndex + 2])));
            require(instructionEndIndex &lt;= instructionsEndIndex, &quot;Intent too short: single instruction&quot;);

            unpackedInstructions[instructionIndex] = intent[instructionStartIndex + 2 : instructionEndIndex];

            instructionIndex += 1;
        }
        require(instructionEndIndex == instructionsEndIndex, &quot;Intent length doesn&apos;t match&quot;);

        return (ERC7806Constants.VALIDATION_APPROVED, unpackedInstructions);
    }

    function _validateSignatures(
        address sender, bytes calldata intent, uint256 sigStartIndex
    ) internal view returns (uint256) {
        bytes32 intentHash = keccak256(abi.encode(intent[46 : sigStartIndex], address(this), block.chainid));
        bytes32 messageHash = MessageHashUtils.toEthSignedMessageHash(intentHash);
        require(sender == messageHash.recover(intent[sigStartIndex : sigStartIndex + 65]), &quot;Invalid sender signature&quot;);

        return uint256(intentHash);
    }

    // -------------
    // The following methods will be removed after testing
    // -------------
    function sampleIntent(
        address sender, address relayer,
        address outTokenAddress, uint128 outAmount,
        bytes[] memory executions
    ) external view returns (
        bytes memory intent, bytes32 intentHash
    ) {
        bytes memory header = relayer == address(0) ?
        abi.encodePacked(uint64((block.timestamp + 31536000) &amp; 0xFFFFFFFFFFFFFFFF)) :
        abi.encodePacked(uint64((block.timestamp + 31536000) &amp; 0xFFFFFFFFFFFFFFFF), relayer);

        bytes memory instructions = bytes.concat(bytes20(outTokenAddress), bytes16(outAmount), bytes1(uint8(executions.length)));
        for (uint256 i = 0; i &lt; executions.length; i++) {
            uint16 length = uint16(executions[i].length);
            instructions = bytes.concat(instructions, bytes2(length), executions[i]);
        }

        bytes memory toSign = bytes.concat(header, instructions);
        intentHash = keccak256(abi.encode(toSign, address(this), block.chainid));

        intent = bytes.concat(bytes20(sender), bytes20(address(this)), bytes2(uint16(header.length)), bytes2(uint16(instructions.length)), bytes2(uint16(65)), toSign);

        return (intent, intentHash);
    }

    function sampleERC20Execution(
        address token, address receiver, uint256 amount
    ) external pure returns (bytes memory) {
        if (token == address(0)) {
            return abi.encode(receiver, amount, &quot;&quot;);
        }

        return abi.encode(token, uint256(0), abi.encodeWithSelector(IERC20.transfer.selector, address(receiver), amount));
    }

    function executeUserIntent(bytes calldata intent) external returns (bytes memory) {
        (address sender,) = PackedIntent.getSenderAndStandard(intent);
        bytes memory executeCallData = abi.encodeWithSelector(IAccount.executeUserIntent.selector, intent);

        (, bytes memory result) = sender.call{value : 0, gas : gasleft()}(executeCallData);
        return result;
    }
}
```

### Sample Account

The following `IAccount` implementation uses a `StandardRegistry` to maintain allowlist of standards and just batch execute
all operations returned from `IStandard.unpackOperations`.

```solidity
import {MessageHashUtils} from &quot;@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol&quot;;
import {ECDSA} from &quot;@openzeppelin/contracts/utils/cryptography/ECDSA.sol&quot;;

/// @title StandardRegistry
/// @notice This is a registry for standards, determining whether an account accepts a standard
/// @dev EIP-712 is used for signature verification
contract StandardRegistry {
    using ECDSA for bytes32;

    /// @notice The event emitted when a standard is registered
    event StandardRegistered(address indexed signer, address indexed standard);
    /// @notice The event emitted when a standard is unregistered
    event StandardUnregistered(address indexed signer, address indexed standard);

    /// @notice The domain separator of this contract
    bytes32 public immutable DOMAIN_SEPARATOR;
    /// @notice The type hash of the signed data of this contract
    bytes32 public immutable SIGNED_DATA_TYPEHASH;

    /// @notice The mapping of nonces
    mapping(bytes32 nonce =&gt; bool used) private _nonces;
    /// @notice The mapping of registrations
    mapping(bytes32 standard =&gt; bool registered) private _registrations;

    /// @notice The constructor of this contract
    constructor() {
        DOMAIN_SEPARATOR = keccak256(
            abi.encode(
                keccak256(&quot;EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)&quot;),
                keccak256(bytes(&quot;StandardRegistry&quot;)), // Contract name
                keccak256(bytes(&quot;2&quot;)), // Version
                block.chainid, // Chain ID
                address(this) // Contract address
            )
        );

        SIGNED_DATA_TYPEHASH = keccak256(
            &quot;Permission(bool registering,address standard,uint256 nonce)&quot;
        );
    }

    /// @notice The function to permit a standard, allowing a relayer to register or unregister a standard for a user
    /// @param registering Whether registering or unregistering
    /// @param signer The signer of the permission
    /// @param standard The standard to permit
    /// @param nonce The nonce of the permission
    /// @param signature The signature of the permission
    function permit(bool registering, address signer, address standard, uint256 nonce, bytes calldata signature) external {
        bytes32 compositeKey = keccak256(abi.encodePacked(signer, nonce));
        require(!_nonces[compositeKey], &quot;Invalid nonce&quot;);

        // validate signature
        bytes32 structHash = keccak256(
            abi.encode(SIGNED_DATA_TYPEHASH, registering, standard, nonce)
        );
        bytes32 digest = MessageHashUtils.toTypedDataHash(DOMAIN_SEPARATOR, structHash);
        require(signer == digest.recover(signature), &quot;Invalid signature&quot;);

        _process(registering, signer, standard, nonce);
    }

    /// @notice The function to update a standard registration directly
    /// @param registering Whether registering or unregistering
    /// @param standard The standard to update
    /// @param nonce The nonce of the update
    function update(bool registering, address standard, uint256 nonce) external {
        address signer = msg.sender;
        bytes32 compositeKey = keccak256(abi.encodePacked(signer, nonce));
        require(!_nonces[compositeKey], &quot;Invalid nonce&quot;);

        _process(registering, signer, standard, nonce);
    }

    /// @notice The function to check if a nonce is used
    /// @param signer The signer of the nonce
    /// @param nonce The nonce to check
    /// @return result true if the nonce is used
    function isNonceUsed(address signer, uint256 nonce) external view returns (bool) {
        bytes32 compositeKey = keccak256(abi.encodePacked(signer, nonce));
        return _nonces[compositeKey];
    }

    /// @notice The function to check if a standard is registered
    /// @param signer The signer of the standard
    /// @param standard The standard to check
    /// @return result true if the standard is registered
    function isRegistered(address signer, address standard) external view returns (bool) {
        bytes32 compositeKey = keccak256(abi.encodePacked(signer, standard));

        return _registrations[compositeKey];
    }

    /// @notice The function to process a standard registration or unregistration
    /// @param registering Whether registering or unregistering
    /// @param signer The signer of the registration
    /// @param standard The standard to process
    /// @param nonce The nonce of the registration
    function _process(bool registering, address signer, address standard, uint256 nonce) internal {
        bytes32 compositeKey = keccak256(abi.encodePacked(signer, standard));

        if (registering) {
            _registrations[compositeKey] = true;
            emit StandardRegistered(signer, standard);
        } else {
            _registrations[compositeKey] = false;
            emit StandardUnregistered(signer, standard);
        }

        compositeKey = keccak256(abi.encodePacked(signer, nonce));
        _nonces[compositeKey] = true;
    }
}
```

```solidity
contract AccountImplV0 {
    string public constant DESCRIPTION = &quot;Account with Batch Execution, Standard Registry&quot;;
    string public constant VERSION = &quot;0.0.0&quot;;
    string public constant AUTHOR = &quot;hellohanchen&quot;;

    StandardRegistry public constant REGISTRY = StandardRegistry(address());
    bytes4 public constant VALIDATION_APPROVED = 0x00000001;
    bytes4 public constant VALIDATION_DENIED = 0x00000000;

    function executeOtherIntent(bytes calldata intent) override internal returns (bytes memory) {
        (address sender, address standard) = PackedIntent.getSenderAndStandard(intent);
        require(sender == address(this), &quot;Intent is not from this account&quot;);
        require(REGISTRY.isRegistered(address(this), standard), &quot;Standard not registered&quot;);
        // standard validation and unpack
        (bytes4 validationCode, bytes[] memory instructions) = IStandard(standard).unpackOperations(intent);
        require(validationCode == VALIDATION_APPROVED, &quot;Validation failed&quot;);

        // batch execute
        for (uint256 i = 0; i &lt; instructions.length; i++) {
            (address dest, uint256 value, bytes memory data) = abi.decode(instructions[i], (address, uint256, bytes));

            (bool success,) = dest.call{value : value, gas : gasleft()}(data);
            if (!success) {
                revert SelfExecutableAccount.ExecutionError();
            }
        }

        return new bytes(0);
    }

    receive() external payable {}
}
```

As shown above, the implementation of `IAccount` is stateless and simple, so that it can be compatible with different `IStandard`.
While the `IStandard` implementation is complex because it needs to define its own schema. But both contracts will be public
and audited, to ensure the security of intent execution.

## Security Considerations

The security of this standard primarily depends on the implementation of both `IStandard` and `IAccount`. Each component must ensure that user intents are validated and executed safely. Additionally, solvers are responsible for securing their own execution environments to prevent unintended exploits.

### Auditability of both Validation and Execution

To ensure security and maintain ecosystem integrity, it is critical that both the standard (`IStandard`) and account (`IAccount`) implementations are:

- **Publicly auditable**: Open access to contract code allows security researchers to identify potential vulnerabilities.
- **Well-reviewed and shared**: Public discussions and peer reviews help strengthen security assumptions.
- **Secure against compatibility risks**: Ensuring compatibility between different standard and account implementations can prevent unintended interactions that may lead to exploits.

### Delegated Contract Storage Risks

If an `IAccount` implementation maintains state (instead of being stateless), it could:
- Interfere with other delegated contracts sharing the same storage.
- Be manipulated by unauthorized users if storage is not properly protected.

Strongly RECOMMEND stateless execution to prevent storage conflicts.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 02 Nov 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7806</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7806</guid>
      </item>
    
      <item>
        <title>SSZ execution blocks</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7807-ssz-execution-blocks/21580</comments>
        
        <description>## Abstract

This EIP defines a migration process of execution blocks to [Simple Serialize (SSZ)](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/ssz/simple-serialize.md).

## Motivation

With [EIP-6404](/EIPs/EIPS/eip-6404) SSZ transactions, [EIP-6466](/EIPs/EIPS/eip-6466) SSZ receipts, and [EIP-6465](/EIPs/EIPS/eip-6465) SSZ withdrawals, all Merkle-Patricia Tries (MPT) besides the state trie are converted to SSZ. This enables the surrounding data structure, the execution block itself, to also convert to SSZ, achieving a unified block representation across both Consensus Layer and Execution Layer.

1. **Normalized block hash:** The Consensus Layer can compute the block hash autonomously, enabling it to process all consistency checks that currently require asynchronous communication with the Execution Layer ([`verify_and_notify_new_payload`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/electra/beacon-chain.md#modified-verify_and_notify_new_payload)). This allows early rejection of inconsistent blocks and dropping the requirement to wait for engine API interactions while syncing.

2. **Optimized engine API:** With all exchanged data supporting SSZ, the engine API can be changed from the textual JSON encoding to binary SSZ encoding, reducing exchanged data size by ~50% and significantly improving encoding/parsing efficiency.

3. **Proving support:** With SSZ, individual fields of the execution block header become provable without requiring full block headers to be present. With [EIP-7495](/EIPs/EIPS/eip-7495) SSZ `ProgressiveContainer`, proofs are forward compatible as long as underlying semantics of individual fields are unchanged, reducing maintenance requirements for smart contracts and verifying client applications.

4. **Cleanup opportunity:** The conversion to SSZ allows dropping historical fields from the PoW era and the inefficient logs bloom mechanism.

## Specification

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

### Gas amounts

The different kinds of gas amounts are combined into a single structure, mirroring the [EIP-6404 gas fees](/EIPs/EIPS/eip-6404#gas-fees).

| Name | SSZ equivalent |
| - | - |
| [`GasAmount`](/EIPs/EIPS/eip-6404#normalized-transactions) | `uint64` |

```python
class GasAmounts(ProgressiveContainer(active_fields=[1, 1])):
    regular: GasAmount
    blob: GasAmount
```

### Requests hash computation

`requests_hash` is changed to `ExecutionRequests.hash_tree_root()` using the same structure as in the Consensus Layer `BeaconBlockBody`.

### Execution block headers

New execution block headers use a normalized SSZ representation.

```python
class ExecutionBlockHeader(
    ProgressiveContainer(active_fields=[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
):
    parent_hash: Root
    miner: ExecutionAddress
    state_root: Bytes32
    transactions_root: Root  # EIP-6404 transactions.hash_tree_root()
    receipts_root: Root  # EIP-6466 receipts.hash_tree_root()
    number: uint64
    gas_limits: GasAmounts
    gas_used: GasAmounts
    timestamp: uint64
    extra_data: ByteList[MAX_EXTRA_DATA_BYTES]
    mix_hash: Bytes32
    base_fees_per_gas: BlobFeesPerGas
    withdrawals_root: Root  # EIP-6465 withdrawals.hash_tree_root()
    excess_gas: GasAmounts
    parent_beacon_block_root: Root
    requests_hash: Bytes32  # EIP-6110 execution_requests.hash_tree_root()
    system_logs_root: Root  # EIP-7799 system_logs.hash_tree_root()
```

### Execution block hash computation

For new blocks, the execution block hash is changed to be based on `hash_tree_root` in all contexts, including (1) the `BLOCKHASH` opcode, (2) JSON-RPC API interactions (`blockHash` field), (3) devp2p networking.

### Consensus `ExecutionPayload` changes

Usages of `ExecutionPayloadHeader` are replaced with `ExecutionBlockHeader`.

Usages of `ExecutionPayload` are updated to share `hash_tree_root` with `ExecutionBlockHeader`. `transactions_root`, `withdrawals_root` and `requests_hash` are expanded to their full list contents.

```python
class ExecutionPayload(
    ProgressiveContainer(active_fields=[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
):
    parent_hash: Root
    miner: ExecutionAddress
    state_root: Bytes32
    transactions: ProgressiveList[Transaction]
    receipts_root: Root
    number: uint64
    gas_limits: GasAmounts
    gas_used: GasAmounts
    timestamp: uint64
    extra_data: ByteList[MAX_EXTRA_DATA_BYTES]
    mix_hash: Bytes32
    base_fees_per_gas: BlobFeesPerGas
    withdrawals: ProgressiveList[Withdrawal]
    excess_gas: GasAmounts
    parent_beacon_block_root: Root
    requests: ExecutionRequests
    system_logs_root: Root
```

## Rationale

This completes the transition to SSZ for everything except the execution state trie.

### Future

- With SSZ `Log`, the withdrawals mechanism and validator requests could be redefined to be based on logs (similar to deposits, originally, but without the delay), possibly removing the need for `withdrawals_root` and `requests_hash`.
  - The CL would insert the extra logs for minting ([EIP-7799](/EIPs/EIPS/eip-7799)) and could fetch the ones relevant for withdrawing (deposits, requests, consolidations). That mechanism would be more generic than [EIP-7685](/EIPs/EIPS/eip-7685) and would drop requiring the EL to special case requests, including `compute_requests_hash`.
  - For client applications and smart contracts, it would streamline transaction history verification based on [EIP-7792](/EIPs/EIPS/eip-7792).

- The Engine API should be updated with (1) possible withdrawals/requests refactoring as above, (2) dropping the `block_hash` field so that `ExecutionPayload` is replaced with `ExecutionBlockHeader`, (3) binary encoding based on `ForkDigest`-context (through HTTP header or interleaved, similar to beacon-API). This reduces encoding overhead and also simplifies sharing data structures in combined CL/EL in-process implementations.

## Backwards Compatibility

This breaks compatibility of smart contracts that depend on the previous block header binary format, including for &quot;generic&quot; implementations that assume a common prefix and run the entire data through a linear keccak256 hash.

## Security Considerations

The SSZ block hash is based on SHA256 and shares the namespace with existing keccak256 based block hashes. As these hash algorithms are fundamentally different, no significant collision risk is expected.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 28 Oct 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7807</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7807</guid>
      </item>
    
      <item>
        <title>Reserve Tx-Type Range for RIPs</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7808-reserve-tx-type-range-for-rips/21587</comments>
        
        <description>## Abstract

This EIP reserves a [transaction-type](/EIPs/EIPS/eip-2718) range for use by the Rollup Improvement Proposal (RIP) process to ensure there are no conflicts.

## Motivation

For L2s to use new transactrion types, it is necessary to reserve a transaction-type range for use by the RIP process so as to ensure there are no conflicts between transaction types used by RIPs and EIPs.

## Specification

The transaction-type (as specified in [EIP-2718](./eip-2718)) range from `0x40` to `0x7f` (inclusive of both) is reserved for use by the RIP process.

## Rationale

By reserving a transaction-type range for RIPs, it allows the RIP process to maintain its own registry of transaction types that are not (necessarily) in use on L1 mainnet, the EIP process is then freed from having to maintain a registry of RIP tx-types while still having 64 tx-types for its own use.

## Backwards Compatibility

No backward compatibility issues found.

## Security Considerations

Nil.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 04 Nov 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7808</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7808</guid>
      </item>
    
      <item>
        <title>Wallet Asset Discovery</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7811-wallet-asset-discovery/21639</comments>
        
        <description>## Abstract

This ERC introduces a new RPC call, `wallet_getAssets`, for wallets to declare to the Dapp what assets are owned by the user. This allows for more accurate asset discovery and the use of assets that aren’t available on-chain but can be provided by the wallet

## Motivation

Currently, Dapps primarily rely on on-chain data to determine a user&apos;s balance, which can be limiting. Furthermore, a Dapp might restrict the user from initiating actions that the wallet could otherwise resolve, as it cannot account for the total assets a user has across different accounts or chains.

Wallets already have information about a user&apos;s assets, including those not visible on-chain, and need a way to communicate that information to Dapps.

## Specification

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.

### Method: `wallet_getAssets`

#### Request schema

```ts
type Hex = `0x${string}`;
type Address = Hex;
type AssetType = &quot;native&quot; | &quot;erc20&quot; | &quot;erc721&quot; | string;
type Address = Hex;
type AddressOrNative = Address | &quot;native&quot;;
type Eip155ChainId = Hex;

type WalletGetAssetsRequest = {
  account: Address;
  assetFilter?: Record&lt;
    Eip155ChainId,
    {
      address: AddressOrNative;
      type: AssetType;
    }[]
  &gt;;
  assetTypeFilter?: AssetType[];
  chainFilter?: Hex[];
};
```

`account` is a **REQUIRED** field that indicates for which account assets are requested.

`assetFilter` is **OPTIONAL** field that accepts a list of assets identifiers. Each asset identifier is an object that contains `address` and `type` fields and is scoped by `chainId`, where ChainId **MUST** be a valid [EIP-155](/EIPs/EIPS/eip-155) chainId.

If the `assetFilter` field is provided, the wallet **MUST** only return the assets specified within it, even if `assetTypeFilter` or `chainFilter` could have further filtered the result. This effectively disregards the `assetTypeFilter` and `chainFilter` fields entirely. The reason for this is that they are already implicitly defined within the `assetFilter`.

If the `assetFilter` field is omitted, the wallet **SHOULD** return all available assets for the requested account. It is **RECOMMENDED** that the returned assets be ordered by estimated value in descending order, as determined by the wallet.

`assetTypeFilter` is an **OPTIONAL** field that specifies an array of asset types, as defined in this ERC. If `assetTypeFilter` field is provided, wallet **MUST** include only assets with those types in the response.

`chainFilter` is an **OPTIONAL** field that specifies an array of chain ids, where each value in the array **MUST** be a valid [EIP-155](/EIPs/EIPS/eip-155) chainId

Consumers of `wallet_getAssets` SHOULD set `assetFilter`, `assetTypeFilter` and `chainFilter` with as granular as reasonably possible values. For example, if an app is only interested in interacting with a single token on a single chain, it should provide filters for this. Doing this both ensures that wallets and the underlying infrastructure do not incur excessive cost, as well as significantly increased performance to client applications.

#### Example request

```json
{
  &quot;account&quot;: &quot;0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045&quot;,
  &quot;assetFilter&quot;: {
    &quot;0x1&quot;: [
      {
        &quot;address&quot;: &quot;0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045&quot;,
        &quot;type&quot;: &quot;erc20&quot;
      },
      {
        &quot;address&quot;: &quot;native&quot;,
        &quot;type&quot;: &quot;native&quot;
      }
    ],
    &quot;0xa&quot;: [
      {
        &quot;address&quot;: &quot;0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045&quot;,
        &quot;type&quot;: &quot;erc20&quot;
      }
    ]
  },
  &quot;assetTypeFilter&quot;: [&quot;ERC20&quot;, &quot;native&quot;],
  &quot;chainFilter&quot;: [&quot;0x1&quot;]
}
```

#### Response schema

```ts
type Asset = {
  address: AddressOrNative;
  balance: Hex;
  type: string;
  metadata: any;
};
type WalletGetAssetsResponse = Record&lt;Hex, Asset[]&gt;;
```

The key **MUST** be [EIP-155](/EIPs/EIPS/eip-155) chainId

Asset fields:

`address` is the address of the asset as `Hex` or `native` string for native assets.

`balance` is the balance of the asset as `Hex`

**`type`:** A string indicating the type of the asset. Common asset types include but **aren’t limited to**:

- **`erc20`:** For [ERC-20](/EIPs/EIPS/eip-20) tokens
- **`erc721`:** For [ERC-721](/EIPs/EIPS/eip-721) tokens (NFTs)
- **`native`:** For the chain&apos;s native asset

**`metadata`:** An **OPTIONAL** object containing additional information about the asset. The specific fields within the metadata object may vary depending on the asset type and the wallet&apos;s implementation.

#### Example response

```json
{
  &quot;0x1&quot;: [
    {
      &quot;address&quot;: &quot;0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48&quot;,
      &quot;balance&quot;: &quot;0xcaaea35047fe5702&quot;,
      &quot;type&quot;: &quot;ERC20&quot;,
      &quot;metadata&quot;: {
        &quot;name&quot;: &quot;Token&quot;,
        &quot;symbol&quot;: &quot;TOK&quot;,
        &quot;decimals&quot;: 18
      }
    },
    {
      &quot;address&quot;: &quot;native&quot;,
      &quot;balance&quot;: &quot;0xcaaea35047fe5702&quot;,
      &quot;type&quot;: &quot;native&quot;
    }
  ],
  &quot;0xa&quot;: [
    {
      &quot;address&quot;: &quot;0x456&quot;,
      &quot;balance&quot;: &quot;0xcd5595&quot;,
      &quot;type&quot;: &quot;ERC721&quot;,
      &quot;metadata&quot;: {
        //...
      }
    }
  ]
}
```

### Well-known asset types

Below are expansions of `metadata` for well-known asset types. Implementations that are compliant with this ERC and return these well-known asset types **MUST** return at least these fields in `metadata`. Implementations **MAY** return more fields than specified here.
This ERC does not specify an exhaustive list of asset types.
Since the type is a generic string, there could be a mismatch between the type Dapp expects and the one returned by the wallet.
It’s important that no two assets share the same type.
Therefore, new asset types should be specified in future ERCs.

**Native**

```ts
type NativeAsset = {
  address: &quot;native&quot;;
  balance: Hex;
  type: &quot;native&quot;;
};
```

Example:

```json
{
  &quot;address&quot;: &quot;native&quot;,
  &quot;balance&quot;: &quot;0xcaaea35047fe5702&quot;,
  &quot;type&quot;: &quot;native&quot;
}
```

**ERC-20 Token**

```ts
type Erc20Asset = {
  address: Hex;
  balance: Hex;
  type: &quot;erc20&quot;;
  metadata: {
    name: string;
    symbol: string;
    decimals: number;
  };
};
```

Example:

```json
{
  &quot;address&quot;: &quot;0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48&quot;,
  &quot;balance&quot;: &quot;0xcaaea35047fe5702&quot;,
  &quot;type&quot;: &quot;erc20&quot;,
  &quot;metadata&quot;: {
    &quot;name&quot;: &quot;Token&quot;,
    &quot;symbol&quot;: &quot;TOK&quot;,
    &quot;decimals&quot;: 18
  }
}
```

**ERC-721 Token**

```ts
type Erc721Asset = {
  address: Hex;
  balance: Hex;
  type: &quot;erc721&quot;;
  metadata: {
    name: string;
    symbol: string;
    tokenId: Hex;
    tokenURI?: string;
  };
};
```

Example:

```json
{
  &quot;address&quot;: &quot;0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48&quot;,
  &quot;balance&quot;: &quot;0x01&quot;,
  &quot;type&quot;: &quot;erc721&quot;,
  &quot;metadata&quot;: {
    &quot;name&quot;: &quot;Thor&apos;s hammer&quot;,
    &quot;symbol&quot;: &quot;THOR&quot;,
    &quot;tokenId&quot;: &quot;0x1&quot;,
    &quot;tokenURI&quot;: &quot;ipfs://hash&quot;
  }
}
```

### Capabilities

If the wallet is using [CAIP-25](https://github.com/ChainAgnostic/CAIPs/blob/0848f06f6cfc29ce619bccdd5035c1d500033b21/CAIPs/caip-25.md) authorization, wallet **SHOULD** include `wallet_getAssets` in the `methods` array in `sessionScopes` of `eip155` namespace.

If the wallet supports [ERC-5792](/EIPs/EIPS/eip-5792) wallet **SHOULD** respond on `wallet_getCapabilities` request using the `assetDiscovery` key. Value should be an object with `supported` key and value `true`
Wallet **SHOULD** include this for every chainId.

```json
{
  &quot;0xa&quot;: {
    &quot;assetDiscovery&quot;: {
      &quot;supported&quot;: true
    }
  }
}
```

## Rationale

&lt;!-- TODO --&gt;

## Security Considerations

&lt;!-- TODO --&gt;

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 07 Nov 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7811</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7811</guid>
      </item>
    
      <item>
        <title>ZK Identity Registry</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7812-zk-identity-registry/21624</comments>
        
        <description>## Abstract

This EIP introduces an on-chain registry system for storing and proving abstract statements. Users may utilize the system to store commitments to their private data to later prove its validity and authenticity via zero knowledge, without disclosing anything about the data itself. Moreover, developers may use the singleton `EvidenceRegistry` contract available at `0x781246D2256dc0C1d8357c9dDc1eEe926a9c7812` to integrate custom business-specific registrars for managing and processing particular statements.

## Motivation

This EIP stemmed from the need to localize and unravel the storage and issuance of provable statements so that future protocols can anchor to the standardized singleton on-chain registry and benefit from cross-reuse.

The aggregation of provable statements significantly improves reusability, portability, and security of the abundance of zero knowledge privacy-oriented solutions. The abstract specification of the registry allows custom indentity-based, reputation-based, proof-of-attendance-based, etc., protocols to be implemented with little to minimal constraints.

The given proposal lays the important foundation for specific solution to build upon. The more concrete specifications of statements and commitments structures are expected to emerge as separate, standalone EIPs. 

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### Definitions

- A &quot;Sparse Merkle Tree (SMT)&quot; is a special Merkle tree that works by deterministically and idempotently storing key/value pairs in the given locations leveraging a hash function. The Poseidon hash function is often used to optimize the compatibility with ZK.
- A &quot;statement&quot; is an accepted structured representation of some abstract evidence. A statement can range from a simple `string` to a Merkle root of some SMT.
- A &quot;commitment&quot; is a special public value resulting from blinding a statement to conceal it. Commitments allow the authenticity of a statement to be proven in ZK without disclosing the statement itself.
- A &quot;commitment key&quot; is a private salt mixed with the statement to obtain a commitment to that statement. The commitment key must be kept private to maintain the confidentiality of statements.

### General

The on-chain registry system consists of two subsystems: the `EvidenceRegistry` with `EvidenceDB` and `Registrar` components. This EIP will focus on describing and standardizing the former, while the `Registrar` specification may be amended as the separate proposals.

![The on-chain evidence registry system entities diagram.](/EIPs/assets/eip-7812/images/diagram.png)

The on-chain evidence registry system entities diagram.

The `EvidenceRegistry` acts as the entrypoint to a protocol-wide provable database `EvidenceDB` where arbitrary `32-byte` data can be written to and later proven on demand. The `Registrar` entities implement specific business use cases, structure the provable data, and utilize `EvidenceRegistry` to put this data in the `EvidenceDB`.

In order to prove that certain data is or is not present in the `EvidenceDB` Merkle proofs may be used. Understanding how a specific `Registrar` has structured and put data into the `EvidenceDB`, one may implement an on-chain ZK verifier (using Circom or any other stack) and prove the inclusion (or exclusion) of the data in the database.

The Circom implementation of a general-purpose SMT-driven `EvidenceDB` verifier circuit together with the Solidity implementation of `EvidenceRegistry` and `EvidenceDB` smart contracts may be found in the &quot;Reference Implementation&quot; section.

### Evidence DB

The `EvidenceDB` smart contract MAY implement an arbitrary provable key/value data structure, however it MUST support the `addition`, `update`, and `removal` of elements. All of the supported write operations MUST maintain the property of idempotence (e.i. `addition` followed by `removal` should not change the state of the database). The data structure of choice MUST be capable of providing both element inclusion and exclusion proofs. The functions that modify the `EvidenceDB` state MUST be callable only by the `EvidenceRegistry`.

For reference, the `EvidenceDB` smart contract MAY implement the following interface:

```solidity
pragma solidity ^0.8.0;

/**
 * @notice Evidence DB interface for Sparse Merkle Tree based statements database.
 */
interface IEvidenceDB {
    /**
     * @notice Represents the proof of a node&apos;s inclusion/exclusion in the tree.
     * @param root The root hash of the Merkle tree.
     * @param siblings An array of sibling hashes can be used to get the Merkle Root.
     * @param existence Indicates the presence (true) or absence (false) of the node.
     * @param key The key associated with the node.
     * @param value The value associated with the node.
     * @param auxExistence Indicates the presence (true) or absence (false) of an auxiliary node.
     * @param auxKey The key of the auxiliary node.
     * @param auxValue The value of the auxiliary node.
     */
    struct Proof {
        bytes32 root;
        bytes32[] siblings;
        bool existence;
        bytes32 key;
        bytes32 value;
        bool auxExistence;
        bytes32 auxKey;
        bytes32 auxValue;
    }
    
    /**
     * @notice Adds the new element to the tree.
     */
    function add(bytes32 key, bytes32 value) external;

    /**
     * @notice Removes the element from the tree.
     */
    function remove(bytes32 key) external;

    /**
     * @notice Updates the element in the tree.
     */
    function update(bytes32 key, bytes32 newValue) external;

    /**
     * @notice Gets the SMT root.
     * SHOULD NOT be used on-chain due to roots frontrunning.
     */
    function getRoot() external view returns (bytes32);

    /**
     * @notice Gets the number of nodes in the tree.
     */
    function getSize() external view returns (uint256);
    
    /**
     * @notice Gets the max tree height (number of branches in the Merkle proof)
     */
    function getMaxHeight() external view returns (uint256);

    /**
     * @notice Gets Merkle inclusion/exclusion proof of the element.
     */
    function getProof(bytes32 key) external view returns (Proof memory);

    /**
     * @notice Gets the element value by its key.
     */
    function getValue(bytes32 key) external view returns (bytes32);
}
```

### Evidence Registry

The `EvidenceRegistry` smart contract is the central piece of this EIP. The `EvidenceRegistry` MUST implement the following interface, however, it MAY be extended:

```solidity
pragma solidity ^0.8.0;

/**
 * @notice Common Evidence Registry interface.
 */
interface IEvidenceRegistry {
    /**
     * @notice MUST be emitted whenever the Merkle root is updated.
     */
    event RootUpdated(bytes32 indexed prev, bytes32 indexed curr);

    /**
     * @notice Adds the new statement to the DB.
     */
    function addStatement(bytes32 key, bytes32 value) external;

    /**
     * @notice Removes the statement from the DB.
     */
    function removeStatement(bytes32 key) external;

    /**
     * @notice Updates the statement in the DB.
     */
    function updateStatement(bytes32 key, bytes32 newValue) external;

    /**
     * @notice Retrieves historical DB roots creation timestamps.
     * Latest root MUST return `block.timestamp`.
     * Non-existent root MUST return `0`.
     */
    function getRootTimestamp(bytes32 root) external view returns (uint256);

    /**
     * @notice Builds and returns the isolated key for `source` and given `key`.
     */
    function getIsolatedKey(address source, bytes32 key) external view returns (bytes32);
}
```

The `addStatement`, `removeStatement`, and `updateStatement` methods MUST isolate the statement `key` in order for the database to allocate a specific namespace for a caller. These methods MUST revert in case the isolated key being added already exists in the `EvidenceDB` or the isolated key being removed or updated does not.

The `EvidenceRegistry` MUST maintain the linear history of `EvidenceDB` roots. The `getRootTimestamp` method MUST NOT revert. Instead, it MUST return `0` in case the queried `root` does not exist. The method MUST return `block.timestamp` in case the latest root is requested.

Before communicating with the `EvidenceDB`, the `key` MUST be isolated in the following way:

```solidity
bytes32 isolatedKey = hash(msg.sender, key)
```

Where the `hash` is secure protocol-wide hash function of choice.

### Hash Function

The same secure hash function MUST be employed in both `EvidenceRegistry` and `EvidenceDB`. It is RECOMMENDED to use ZK-friendly hash function such as `poseidon` to streamline the database proving.

In case ZK-friendly hash function is chosen, `EvidenceRegistry` MUST NOT accept `keys` or `values` beyond the underlying elliptic curve prime field size (`21888242871839275222246405745257275088548364400416034343698204186575808495617` for `BN128`). 

## Rationale

During the EIP specification we have considered two approaches: where every protocol has its own registry and where all protocols are united under a singleton registry. We have decided to go with the latter as this approach provides the following benefits:

1. Cross-chain portability. Only a single `bytes32` value (the SMT root) has to be sent cross-chain to be able to prove the state of the registry.
2. Centralization of trust. Users only need to trust a single, permissionaless, immutable smart contract.
3. Integration streamline. The singleton design formalizes the system interface, the hash function, and the overall proofs structure to simplify the integration.

The proposal is deliberately written as abstract as possible to not constrain the possible business use cases and allow `Registrars` to implement arbitrary provable solutions.

It is expected that based on this work future EIPs will describe concrete registrars with the exact procedures of generation of commitments, management of commitment keys, and proving of operated statements. For instance, there may be a registrar for on-chain accounting of national passports, a registrar with [EIP-4337](/EIPs/EIPS/eip-4337) confidential account identity management, a registrar for POAPs, etc.

The `EvidenceDB` namespacing is chosen to segregate the write access to the database cells, ensuring that no entity but issuer can alter their content. However, this decision delegates the access control management responsibility solely to registrars, an important aspect to be considered during their development.

The `EvidenceRegistry` maintains the minimal viable (gas-wise) history of roots on-chain for smooth registrars integration. In case more elaborate history is required, it is RECOMMENDED to implement off-chain services for parsing of `RootUpdated` events.

## Backwards Compatibility

This EIP is fully backwards compatible.

### Deployment Method

The `EvidenceRegistry` is a singleton contract available at `0x781246D2256dc0C1d8357c9dDc1eEe926a9c7812` deployed via the &quot;deterministic deployment proxy&quot; from `0x4e59b44847b379578588920ca78fbf26c0b4956c` with the salt `0x04834e077c463de76a20df3770a7b96a5e5eb826922d1514f943cd5b41ccaed0`. 

## Reference Implementation

The reference implementation of `EvidenceRegistry` and `EvidenceDB` Solidity smart contracts together with the evidence registry state verifier Circom circuit is provided in the proposal.

The low-level Solidity and Circom implementations of SMT can be found [here](/EIPs/assets/eip-7812/contracts/SparseMerkleTree.sol) and [here](/EIPs/assets/eip-7812/circuits/SparseMerkleTree.circom).

The height of the SMT is set to `80`.

&gt; Please note that the reference implementation depends on the `@openzeppelin/contracts v5.1.0` and `circomlib v2.0.5`.

### EvidenceDB Implementation

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.21;

import {Initializable} from &quot;@openzeppelin/contracts/proxy/utils/Initializable.sol&quot;;

import {IEvidenceDB} from &quot;./interfaces/IEvidenceDB.sol&quot;;

import {SparseMerkleTree} from &quot;./libraries/SparseMerkleTree.sol&quot;;
import {PoseidonUnit2L, PoseidonUnit3L} from &quot;./libraries/Poseidon.sol&quot;;

contract EvidenceDB is IEvidenceDB, Initializable {
    using SparseMerkleTree for SparseMerkleTree.SMT;

    address private _evidenceRegistry;

    SparseMerkleTree.SMT private _tree;

    modifier onlyEvidenceRegistry() {
        _requireEvidenceRegistry();
        _;
    }

    function __EvidenceDB_init(address evidenceRegistry_, uint32 maxDepth_) external initializer {
        _evidenceRegistry = evidenceRegistry_;

        _tree.initialize(maxDepth_);

        _tree.setHashers(_hash2, _hash3);
    }

    /**
     * @inheritdoc IEvidenceDB
     */
    function add(bytes32 key_, bytes32 value_) external onlyEvidenceRegistry {
        _tree.add(key_, value_);
    }

    /**
     * @inheritdoc IEvidenceDB
     */
    function remove(bytes32 key_) external onlyEvidenceRegistry {
        _tree.remove(key_);
    }

    /**
     * @inheritdoc IEvidenceDB
     */
    function update(bytes32 key_, bytes32 newValue_) external onlyEvidenceRegistry {
        _tree.update(key_, newValue_);
    }

    /**
     * @inheritdoc IEvidenceDB
     */
    function getRoot() external view returns (bytes32) {
        return _tree.getRoot();
    }

    /**
     * @inheritdoc IEvidenceDB
     */
    function getSize() external view returns (uint256) {
        return _tree.getNodesCount();
    }

    /**
     * @inheritdoc IEvidenceDB
     */
    function getMaxHeight() external view returns (uint256) {
        return _tree.getMaxDepth();
    }

    /**
     * @inheritdoc IEvidenceDB
     */
    function getProof(bytes32 key_) external view returns (Proof memory) {
        return _tree.getProof(key_);
    }

    /**
     * @inheritdoc IEvidenceDB
     */
    function getValue(bytes32 key_) external view returns (bytes32) {
        return _tree.getNodeByKey(key_).value;
    }

    /**
     * @notice Returns the address of the Evidence Registry.
     */
    function getEvidenceRegistry() external view returns (address) {
        return _evidenceRegistry;
    }

    function _requireEvidenceRegistry() private view {
        if (_evidenceRegistry != msg.sender) {
            revert NotFromEvidenceRegistry(msg.sender);
        }
    }

    function _hash2(bytes32 element1_, bytes32 element2_) private pure returns (bytes32) {
        return PoseidonUnit2L.poseidon([element1_, element2_]);
    }

    function _hash3(
        bytes32 element1_,
        bytes32 element2_,
        bytes32 element3_
    ) private pure returns (bytes32) {
        return PoseidonUnit3L.poseidon([element1_, element2_, element3_]);
    }
}
```

### EvidenceRegistry Implementation

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.21;

import {Initializable} from &quot;@openzeppelin/contracts/proxy/utils/Initializable.sol&quot;;

import {IEvidenceDB} from &quot;./interfaces/IEvidenceDB.sol&quot;;
import {IEvidenceRegistry} from &quot;./interfaces/IEvidenceRegistry.sol&quot;;

import {PoseidonUnit2L} from &quot;./libraries/Poseidon.sol&quot;;

contract EvidenceRegistry is IEvidenceRegistry, Initializable {
    uint256 public constant BABY_JUB_JUB_PRIME_FIELD =
        21888242871839275222246405745257275088548364400416034343698204186575808495617;

    IEvidenceDB private _evidenceDB;

    mapping(bytes32 =&gt; uint256) private _rootTimestamps;

    modifier onlyInPrimeField(bytes32 key) {
        _requireInPrimeField(key);
        _;
    }

    modifier onRootUpdate() {
        bytes32 prevRoot_ = _evidenceDB.getRoot();
        _rootTimestamps[prevRoot_] = block.timestamp;
        _;
        emit RootUpdated(prevRoot_, _evidenceDB.getRoot());
    }

    function __EvidenceRegistry_init(address evidenceDB_) external initializer {
        _evidenceDB = IEvidenceDB(evidenceDB_);
    }

    /**
     * @inheritdoc IEvidenceRegistry
     */
    function addStatement(
        bytes32 key_,
        bytes32 value_
    ) external onlyInPrimeField(key_) onlyInPrimeField(value_) onRootUpdate {
        bytes32 isolatedKey_ = getIsolatedKey(msg.sender, key_);

        if (_evidenceDB.getValue(isolatedKey_) != bytes32(0)) {
            revert KeyAlreadyExists(key_);
        }

        _evidenceDB.add(isolatedKey_, value_);
    }

    /**
     * @inheritdoc IEvidenceRegistry
     */
    function removeStatement(bytes32 key_) external onlyInPrimeField(key_) onRootUpdate {
        bytes32 isolatedKey_ = getIsolatedKey(msg.sender, key_);

        if (_evidenceDB.getValue(isolatedKey_) == bytes32(0)) {
            revert KeyDoesNotExist(key_);
        }

        _evidenceDB.remove(isolatedKey_);
    }

    /**
     * @inheritdoc IEvidenceRegistry
     */
    function updateStatement(
        bytes32 key_,
        bytes32 newValue_
    ) external onlyInPrimeField(key_) onlyInPrimeField(newValue_) onRootUpdate {
        bytes32 isolatedKey_ = getIsolatedKey(msg.sender, key_);

        if (_evidenceDB.getValue(isolatedKey_) == bytes32(0)) {
            revert KeyDoesNotExist(key_);
        }

        _evidenceDB.update(isolatedKey_, newValue_);
    }

    /**
     * @inheritdoc IEvidenceRegistry
     */
    function getRootTimestamp(bytes32 root_) external view returns (uint256) {
        if (root_ == bytes32(0)) {
            return 0;
        }

        if (root_ == _evidenceDB.getRoot()) {
            return block.timestamp;
        }

        return _rootTimestamps[root_];
    }

    /**
     * @inheritdoc IEvidenceRegistry
     */
    function getIsolatedKey(address source_ bytes32 key_) public pure returns (bytes32) {
        return PoseidonUnit2L.poseidon([bytes32(uint256(uint160(source_))), key_]);
    }

    function getEvidenceDB() external view returns (address) {
        return address(_evidenceDB);
    }

    function _requireInPrimeField(bytes32 key_) private pure {
        if (uint256(key_) &gt;= BABY_JUB_JUB_PRIME_FIELD) {
            revert NumberNotInPrimeField(key_);
        }
    }
}
```

### EvidenceRegistry Verifier Implementation

```solidity
// LICENSE: CC0-1.0
pragma circom 2.1.9;

include &quot;SparseMerkleTree.circom&quot;;

template BuildIsolatedKey() {
    signal output isolatedKey;

    signal input address;
    signal input key;

    component hasher = Poseidon(2);
    hasher.inputs[0] &lt;== address;
    hasher.inputs[1] &lt;== key;

    hasher.out ==&gt; isolatedKey;
}

template EvidenceRegistrySMT(levels) {
    // Public Inputs
    signal input root;

    // Private Inputs
    signal input address;
    signal input key;

    signal input value;

    signal input siblings[levels];

    signal input auxKey;
    signal input auxValue;
    signal input auxIsEmpty;

    signal input isExclusion;

    // Build isolated key
    component isolatedKey = BuildIsolatedKey();
    isolatedKey.address &lt;== address;
    isolatedKey.key &lt;== key;

    // Verify Sparse Merkle Tree Proof
    component smtVerifier = SparseMerkleTree(levels);
    smtVerifier.siblings &lt;== siblings;

    smtVerifier.key &lt;== isolatedKey.isolatedKey;
    smtVerifier.value &lt;== value;

    smtVerifier.auxKey &lt;== auxKey;
    smtVerifier.auxValue &lt;== auxValue;
    smtVerifier.auxIsEmpty &lt;== auxIsEmpty;

    smtVerifier.isExclusion &lt;== isExclusion;

    smtVerifier.root &lt;== root;
}

component main {public [root]} = EvidenceRegistrySMT(80);
```

## Security Considerations

From security standpoint there are several important aspects that must be highlighted. 

The individual registrars are expected to provide the functionality for both management and proving of statements. The proving will often be carried out by ZK proofs, which require trusted setup. Improperly setup ZK verifiers can be exploited to verify forged proofs.

The `getRoot` method of `EvidenceDB` SHOULD NOT be used on-chain by the integrating registrars to check the validity of the database state. Instead, the required `root` SHOULD be passed as a function parameter and checked via `getRootTimestamp` method to avoid being frontrun.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 08 Nov 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7812</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7812</guid>
      </item>
    
      <item>
        <title>Store, Table-Based Introspectable Storage</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7813-store-table-based-introspectable-storage/21628</comments>
        
        <description>## Abstract

This standard introduces a flexible on-chain storage pattern that organizes data into structured tables that consist of records with fixed key and value schemas, similar to a traditional database. This storage pattern consists of a unified contract interface for data access, along with a compact binary encoding format for both static and dynamic data types. State changes are tracked through standardized events that enable automatic, schema-aware state replication by off-chain indexers. New tables can be dynamically registered at runtime through a special table that stores schema metadata for all tables, allowing the system to evolve without breaking existing contracts or integrations.

## Motivation

The absence of consistent standards for on-chain data management in smart contracts can lead to rigid implementations, tightly coupled contract logic with off-chain services, and challenges in updating or extending a contract’s data layout without breaking existing integrations.

Using the storage mechanism defined in this ERC provides the following benefits:

1. **Automatic Indexing**: By emitting consistent, standardized events during state changes, off-chain services can automatically track on-chain state and provide schema-aware indexer APIs.
2. **Elimination of Custom Getter Functions**: Any contract or off-chain service can read stored data through a consistent interface, decoupling smart contract implementation from specific data access patterns and reducing development overhead.
3. **Simpler Upgradability**: This pattern leverages unstructured storage, making it easier to upgrade contract logic without the risks associated with using a fixed storage layout.
4. **Flexible Data Extensions**: New tables can be added at runtime without without breaking existing integrations with other data consumers.
5. **Reduced gas costs**: Using efficient data packing reduces gas costs for both storage and event emissions.

## Specification

### Definitions

#### Store

A smart contract that implements the interface proposed by this ERC and organizes data in Tables. It emits events for each data operation so that off-chain components can replicate the state of all tables.

#### Table

A storage structure that holds **Records** sharing the same **Schema**.

- **On-chain Table**: Stores its state on-chain and emits events for off-chain- indexers.
- **Off-chain Table**: Does not store state on-chain but emits events for off-chain indexers.

#### Record

A piece of data stored in a **Table**, addressed by one or more keys.

#### `ResourceId`

A 32-byte value that uniquely identifies each **Table** within the **Store**.

```solidity
type ResourceId is bytes32;
```

Encoding:

| **Bytes (from left to right)** | **Description**       |
| ------------------------------ | --------------------- |
| 0-1                            | Table type identifier |
| 2-31                           | Unique identifier     |

**Table Type Identifiers:**

- `0x7462` (`&quot;tb&quot;`) for on-chain tables
- `0x6f74` (`&quot;ot&quot;`) for off-chain tables

#### `Schema`

Used to represent the layout of Records within a table.

```solidity
type Schema is bytes32;
```

Each Table defines two schemas:

- Key Schema: the types of the keys used to uniquely identify a **Record** within a table. It consists only of fixed-length data types.
- Value Schema: the types of the value fields of a **Record** within a table, which can include both fixed-length and variable-length data types.

| **Byte(s) from left to right** | **Value**                          | **Constraint**                                                    |
| ------------------------------ | ---------------------------------- | ----------------------------------------------------------------- |
| 0-1                            | Total byte length of static fields |                                                                   |
| 2                              | Number of static length fields     | ≤ (28 - number of dynamic length fields)                          |
| 3                              | Number of dynamic length fields    | For the key schema, 0                                             |
| For the value schema, ≤5       |
| 4-31                           | Each byte encodes a `SchemaType`   | Dynamic-length types MUST come after all the static-length types. |

#### `SchemaType`

Single byte that represents the type of a specific static or dynamic field.

```solidity
enum SchemaType { ... }
```

**Type Encoding:**

| Value Range      | Type                                        |
| ---------------- | ------------------------------------------- |
| `0x00` to `0x1F` | `uint8` to `uint256` (increments of 8 bits) |
| `0x20` to `0x3F` | `int8` to `int256` (increments of 8 bits)   |
| `0x40` to `0x5F` | `bytes1` to `bytes32`                       |
| `0x60`           | `bool`                                      |
| `0x61`           | `address`                                   |
| `0x62` to `0x81` | `uint8[]` to `uint256[]`                    |
| `0x82` to `0xA1` | `int8[]` to `int256[]`                      |
| `0xA2` to `0xC1` | `bytes1[]` to `bytes32[]`                   |
| `0xC2`           | `bool[]`                                    |
| `0xC3`           | `address[]`                                 |
| `0xC4`           | `bytes`                                     |
| `0xC5`           | `string`                                    |

#### `FieldLayout`

Encodes the concrete value `Schema` information, specifically the total byte length of the static fields, the number of dynamic fields and the length of each static field on its own.

This encoding serves as an optimization for on-chain operations. By having the exact lengths readily available, the Store doesn&apos;t need to repeatedly compute or translate the schema definitions into actual field lengths during execution.

```solidity
type FieldLayout is bytes32;
```

| **Byte(s) from left to right** | **Value**                                                           | **Constraint**                           |
| ------------------------------ | ------------------------------------------------------------------- | ---------------------------------------- |
| 0-1                            | Total length of static fields                                       |                                          |
| 2                              | Number of static length fields                                      | ≤ (28 - number of dynamic length fields) |
| 3                              | Number of dynamic length fields                                     | For the key schema, 0                    |
| For the value schema, ≤5       |
| 4-31                           | Each byte encodes the byte length of the corresponding static field |                                          |

#### `EncodedLengths`

Encodes the byte length of all the dynamic fields of a specific Record. It is returned by the Store methods when reading a Record, as it is needed for decoding dynamic fields.

```solidity
type EncodedLengths is bytes32;
```

| Bytes (from least to most significant) | Type   | Description                        |
| -------------------------------------- | ------ | ---------------------------------- |
| 0x00-0x06                              | uint56 | Total byte length of dynamic data  |
| 0x07-0xB                               | uint40 | Length of the first dynamic field  |
| 0x0C-0x10                              | uint40 | Length of the second dynamic field |
| 0x11-0x15                              | uint40 | Length of the third dynamic field  |
| 0x16-0x1A                              | uint40 | Length of the fourth dynamic field |
| 0x1B-0x1F                              | uint40 | Length of the fifth dynamic field  |

### Packed Data Encoding

Record data returned by Store methods and included in Store events uses the following encoding rules.

#### Field Limits

- **Maximum Total Fields**: A record can contain up to **28 fields** in total (both static and dynamic fields combined).
  - This limit is due to the `Schema` type structure, which uses 28 bytes (bytes 4 to 31) to define field types, with one byte per field (`SchemaType`).
- **Dynamic Fields Limit**: A record can have up to **5 dynamic fields**.
  - This is due to the fact that a single 32 bytes word (`EncodedLengths`) to encode the byte lengths of each dynamic field, instead of encoding each length separately as Solidity’s `abi.encode` would.
- **Static Fields Limit**: The maximum number of static fields is **28 minus the number of dynamic fields**.
  - For example, if there are 5 dynamic fields, the maximum number of static fields is 23 (28 - 5).

#### Encoding Rules

- Static-length fields are encoded without any padding, and concatenated in the order they are defined in the schema, which is equivalent to using Solidity&apos;s `abi.encodePacked`.
- For dynamic-length fields (arrays, `bytes`, and `string`s):
  - If the field is an array, its elements are tightly packed without padding.
  - All dynamic fields are concatenated together without padding and without including their lengths.
  - The lengths of all dynamic fields are encoded into a single `EncodedLengths`.

#### Example

Suppose a table has the following value schema:

```solidity
(uint256 id, address owner, string description, uint8[] scores)
```

**Encoding (Pseudocode)**:

```solidity
bytes memory staticData = abi.encodePacked(id, owner);

// This is a custom function as Solidity does not provide a way to tightly pack array elements
bytes memory packedScores = packElementsWithoutPadding(scores);

// abi.encodePacked concatenates both description and packedScores without including their lengths
bytes memory dynamicData = abi.encodePacked(description, packedScores);

// Total length is encoded in the 56 least significant bits
EncodedLengths encodedLengths = dynamicData.length;

// Each length is encoded using 5 bytes
encodedLengths |= (description.length &lt;&lt; (56));
encodedLengths |= (encodedData.length &lt;&lt; (56 + 8 * 5));

// The full encoded record data is represented by the following tuple:
// (staticData, encodedLengths, dynamicData)
```

### Store Interface

All Stores MUST implement the following interface.

```solidity
interface IStore {
  /**
   * Get full encoded record (all fields, static and dynamic data) for the given tableId and key tuple.
   */
  function getRecord(
    ResourceId tableId,
    bytes32[] calldata keyTuple
  ) external view returns (bytes memory staticData, EncodedLengths encodedLengths, bytes memory dynamicData);

  /**
   * Get a single encoded field from the given tableId and key tuple.
   */
  function getField(
    ResourceId tableId,
    bytes32[] calldata keyTuple,
    uint8 fieldIndex
  ) external view returns (bytes memory data);

  /**
   * Get the byte length of a single field from the given tableId and key tuple
   */
  function getFieldLength(
    ResourceId tableId,
    bytes32[] memory keyTuple,
    uint8 fieldIndex
  ) external view returns (uint256);
}
```

The return values of both `getRecord` and `getField` use the encoding rules previously defined in the Packed Data Encoding section. More specifically, `getRecord` returns the fully encoded record tuple, and the data returned by `getField` is encoded using the encoding rules as if the field was being encoded on its own.

### Store Operations and Events

This standard defines three core operations for manipulating records in a table: setting, updating, and deleting. For each operation, specific events must be emitted. The implementation details of these operations are left to the discretion of each Store implementation.

The fundamental requirement is that for on-chain tables the Record data retrieved through the Store interface methods at any given block MUST be consistent with the Record data that would be obtained by applying the operations implied by the Store events up to that block. This ensures data integrity and allows for accurate off-chain state reconstruction.

#### Store_SetRecord

Setting a Record means overwriting all of its fields. This operation can be performed whether the record has been set before or not (the standard does not enforce existence checks).

The `Store_SetRecord` event **MUST** be emitted whenever the full data of a record has been overwritten.

```solidity
event Store_SetRecord(
  ResourceId indexed tableId,
  bytes32[] keyTuple,
  bytes staticData,
  EncodedLengths encodedLengths,
  bytes dynamicData
);
```

Parameters:

| **Name**       | **Type**       | **Description**                                                                              |
| -------------- | -------------- | -------------------------------------------------------------------------------------------- |
| tableId        | ResourceId     | The ID of the table where the record is set                                                  |
| keyTuple       | bytes32[]      | An array representing the composite key for the record                                       |
| staticData     | bytes          | The static data of the record using packed encoding                                          |
| encodedLengths | EncodedLengths | The encoded lengths of the dynamic data of the record                                        |
| dynamicData    | bytes          | The dynamic data of the record, using [custom packed encoding](#packed-data-encoding)        |

#### Store_SpliceStaticData

Splicing the static data of a Record consists in overwriting bytes of the packed encoded static fields. The total length of static data does not change as it is determined by the table’s value schema.

The `Store_SpliceStaticData` event MUST be emitted whenever the static data of the Record has been spliced.

```solidity
event Store_SpliceStaticData(
  ResourceId indexed tableId,
  bytes32[] keyTuple,
  uint48 start,
  bytes data
);
```

Parameters:

| **Name** | **Type**   | **Description**                                               |
| -------- | ---------- | ------------------------------------------------------------- |
| tableId  | ResourceId | The ID of the table where the data is spliced                 |
| keyTuple | bytes32[]  | An array representing the key for the record                  |
| start    | uint48     | The start position in bytes for the splice operation          |
| data     | bytes      | Packed ABI encoding of a tuple with the value&apos;s static fields |

#### Store_SpliceDynamicData

Splicing the dynamic data of a Record involves modifying the packed encoded representation of its dynamic fields by removing, replacing, and/or inserting new bytes in place.

The `Store_SpliceDynamicData` event MUST be emitted whenever the dynamic data of the Record has been spliced.

```solidity
event Store_SpliceDynamicData(
  ResourceId indexed tableId,
  bytes32[] keyTuple,
  uint8 dynamicFieldIndex,
  uint48 start,
  uint40 deleteCount,
  EncodedLengths encodedLengths,
  bytes data
);
```

Parameters:

| **Name**          | **Type**       | **Description**                                                                                                                                          |
| ----------------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| tableId           | ResourceId     | The ID of the table where the data is spliced                                                                                                            |
| keyTuple          | bytes32[]      | An array representing the composite key for the record                                                                                                   |
| dynamicFieldIndex | uint8          | The index of the dynamic field to splice data, relative to the start of the dynamic fields (Dynamic field index = field index - number of static fields) |
| start             | uint48         | The start position in bytes for the splice operation                                                                                                     |
| deleteCount       | uint40         | The number of bytes to delete in the splice operation                                                                                                    |
| encodedLengths    | EncodedLengths | The resulting encoded lengths of the dynamic data of the record                                                                                          |
| data              | bytes          | The data to insert into the dynamic data of the record at the start byte                                                                                 |

#### Store_DeleteRecord

The `Store_DeleteRecord` event MUST be emitted whenever the Record has been deleted from the Table.

```solidity
event Store_DeleteRecord(ResourceId indexed tableId, bytes32[] keyTuple);
```

Parameters:

| **Name** | **Type**   | **Description**                                        |
| -------- | ---------- | ------------------------------------------------------ |
| tableId  | ResourceId | The ID of the table where the record is deleted        |
| keyTuple | bytes32[]  | An array representing the composite key for the record |

See the [reference implementation section](#reference-implementation) for an example on how to index store events.

### The `Tables` table

To keep track of the information of each table and support registering new tables at runtime, the Store implementation MUST include a special on-chain `Tables` table, which behaves the same way as other on-chain tables except for the special constraints mentioned below.

The `Tables` table MUST use the following `Schema`s:

- Key Schema:
  - `tableId` (`ResourceId`): `ResourceId` of the table this record describes.
- Value Schema:
  - `fieldLayout` (`FieldLayout`): encodes the byte length of each static data type in the table.
  - `keySchema` (`Schema`): represents the data types of the (composite) key of the table.
  - `valueSchema` (`Schema`): represents the data types of the value fields of the table.
  - `abiEncodedKeyNames` (`bytes`): ABI encoded string array of key names.
  - `abiEncodedFieldNames` (`bytes`): ABI encoded string array of field names.

Records stored in the `Tables` table are considered immutable:

- The `Store` MUST emit a single `Store_SetRecord` event for each table being registered.
- The `Store` SHOULD NOT emit any other `Store` events for a `Table` registered in the `Tables` table.

The `Tables` table MUST store a record that describes itself before any other table is registered, emitting the corresponding `Store_SetRecord` event. The record must use the following `tableId`:

```solidity
// First two bytes indicates that this is an on-chain table
// The next 30 bytes are the unique identifier for the Tables table
// bytes32(&quot;tb&quot;) | bytes32(&quot;store&quot;) &gt;&gt; (2 * 8) | bytes32(&quot;Tables&quot;) &gt;&gt; (2 * 8 + 14 * 8)
ResourceId tableId = ResourceId.wrap(0x746273746f72650000000000000000005461626c657300000000000000000000);
```

By using a predefined `ResourceId` and `Schema` for the `Tables` table, off-chain indexers can interpret store events for all registered tables. This enables the development of advanced off-chain services that operate on structured data rather than raw encoded data like in the previous indexer implementation example.

## Rationale

### Splice Events

While the `Store_SetRecord` event suffices for tracking the data of each record off-chain, including `Splice` events (`Store_SpliceStaticData` and `Store_SpliceDynamicData`) allows for more efficient partial updates. When only a portion of a record changes, emitting a full `SetRecord` event would be inefficient because the entire record data would need to be read from storage and emitted. `Splice` events enable the store to emit only the minimal necessary data for the update, reducing gas consumption. This is particularly important for records with large dynamic fields, as the cost of updating them doesn’t grow with the field’s size.

### Disallowing Arrays of Dynamic Types

Arrays of dynamic types (e.g., `string[]`, `bytes[]`) are intentionally not included as supported `SchemaType`s. This restriction enforces a flat data schema, which simplifies the store implementation and enhances efficiency. If users need to store such data structures, they can model them using a separate table with a schema like `{ index: uint256, data: bytes }`, where each array element is represented as an individual record.

### FieldLayout Optimization

Including the `FieldLayout` in the `Tables` schema provides an on-chain optimization by precomputing and storing the exact byte lengths of static fields. This eliminates the need to repeatedly compute field lengths and offsets during runtime, which can be gas-intensive. By having this information readily available, the store can perform storage operations more efficiently, while components reading from the store can retrieve it from the `Tables` table to decode the corresponding records.

### Special `Tables` table

Including a special `Tables` table provides significant benefits for off-chain indexers. While emitting events for table registration isn&apos;t strictly necessary for basic indexers that operate on raw encoded data, doing so makes indexers aware of the schemas used by each table. This awareness enables the development of more advanced, schema-aware indexer APIs (e.g., SQL-like query capabilities), enhancing the utility and flexibility of off-chain data interactions.

By reusing existing Store abstractions for table registration, we also simplify the implementation and eliminate the need for additional, specific table registration events. Indexers can leverage the standard Store events to access schema information, ensuring consistency and reducing complexity.

## Reference Implementation

### Store Event Indexing

The following example shows how a simple in-memory indexer can use the Store events to replicate the Store state off-chain. It is important to note that this indexer operates over raw encoded data which is not that useful on its own, but can be improved as we will explain in the next section.

We use TypeScript for this example but it can easily be replicated with other languages.

```tsx
type Hex = `0x${string}`;

type Record = {
  staticData: Hex;
  encodedLengths: Hex;
  dynamicData: Hex;
};

const store = new Map&lt;string, Record&gt;();

// Create a key string from a table ID and key tuple to use in our store Map above
function storeKey(tableId: Hex, keyTuple: Hex[]): string {
  return `${tableId}:${keyTuple.join(&quot;,&quot;)}`;
}

// Like `Array.splice`, but for strings of bytes
function bytesSplice(
  data: Hex,
  start: number,
  deleteCount = 0,
  newData: Hex = &quot;0x&quot;
): Hex {
  const dataNibbles = data.replace(/^0x/, &quot;&quot;).split(&quot;&quot;);
  const newDataNibbles = newData.replace(/^0x/, &quot;&quot;).split(&quot;&quot;);
  return `0x${dataNibbles
    .splice(start, deleteCount * 2)
    .concat(newDataNibbles)
    .join(&quot;&quot;)}`;
}

function bytesLength(data: Hex): number {
  return data.replace(/^0x/, &quot;&quot;).length / 2;
}

function processStoreEvent(log: StoreEvent) {
  if (log.eventName === &quot;Store_SetRecord&quot;) {
    const key = storeKey(log.args.tableId, log.args.keyTuple);

    // Overwrite all of the Record&apos;s fields
    store.set(key, {
      staticData: log.args.staticData,
      encodedLengths: log.args.encodedLengths,
      dynamicData: log.args.dynamicData,
    });
  } else if (log.eventName === &quot;Store_SpliceStaticData&quot;) {
    const key = storeKey(log.args.tableId, log.args.keyTuple);
    const record = store.get(key) ?? {
      staticData: &quot;0x&quot;,
      encodedLengths: &quot;0x&quot;,
      dynamicData: &quot;0x&quot;,
    };

    // Splice the static field data of the Record
    store.set(key, {
      staticData: bytesSplice(
        record.staticData,
        log.args.start,
        bytesLength(log.args.data),
        log.args.data
      ),
      encodedLengths: record.encodedLengths,
      dynamicData: record.dynamicData,
    });
  } else if (log.eventName === &quot;Store_SpliceDynamicData&quot;) {
    const key = storeKey(log.args.tableId, log.args.keyTuple);
    const record = store.get(key) ?? {
      staticData: &quot;0x&quot;,
      encodedLengths: &quot;0x&quot;,
      dynamicData: &quot;0x&quot;,
    };

    // Splice the dynamic field data of the Record
    store.set(key, {
      staticData: record.staticData,
      encodedLengths: log.args.encodedLengths,
      dynamicData: bytesSplice(
        record.dynamicData,
        log.args.start,
        log.args.deleteCount,
        log.args.data
      ),
    });
  } else if (log.eventName === &quot;Store_DeleteRecord&quot;) {
    const key = storeKey(log.args.tableId, log.args.keyTuple);

    // Delete the whole Record
    store.delete(key);
  }
}
```

## Security Considerations

### Access Control

This standard only defines functions to **read** from the Store (`getRecord`, `getField`, and `getFieldLength`). The methods for setting or modifying records in the store are left to each specific implementation. Therefore, implementations **must provide appropriate access control mechanisms** for writing to the store, tailored to their specific use cases.

### On-Chain Data Accessibility

All data stored within a store is accessible not only off-chain but also **on-chain** by other smart contracts through the provided read functions (`getRecord`, `getField`, and `getFieldLength`). This differs from the typical behavior of smart contracts, where internal storage variables are private by default and cannot be directly read by other contracts unless explicit getter functions are provided. Thus, developers must be mindful that any data stored in the store is openly accessible to other smart contracts.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 08 Nov 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7813</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7813</guid>
      </item>
    
      <item>
        <title>Expirable ERC-20</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7818-expirable-erc20/21655</comments>
        
        <description>## Abstract

Introduces an extension for [ERC-20](/EIPs/EIPS/eip-20) tokens, which facilitates the implementation of an expiration mechanism. Through this extension, tokens have a predetermined validity period, after which they become invalid and can no longer be transferred or used. This functionality proves beneficial in scenarios such as time-limited bonds, loyalty rewards, or game tokens necessitating automatic invalidation after a specific duration. The extension is crafted to seamlessly align with the existing [ERC-20](/EIPs/EIPS/eip-20) standard, ensuring smooth integration with the prevailing token smart contract while introducing the capability to govern and enforce token expiration at the contract level.

## Motivation

This extension facilitates the development of [ERC-20](/EIPs/EIPS/eip-20) standard compatible tokens featuring expiration dates. This capability broadens the scope of potential applications, particularly those involving time-sensitive assets. Expirable tokens are well-suited for scenarios necessitating temporary validity, including:

- Bonds or financial instruments with defined maturity dates
- Time-constrained assets within gaming ecosystems
- Next-gen loyalty programs incorporating expiring rewards or points
- Prepaid credits for utilities or services (e.g., cashback, data packages, fuel, computing resources) that expire if not used within a specified time frame
- Postpaid telecom data package allocations that expire at the end of the billing cycle, motivating users to utilize their data before it resets
- Tokenized e-Money for a closed-loop ecosystem, such as transportation, food court, and retail payments

## Specification

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.

### Epoch Mechanism

**Epochs** represent a specific period or block range during which certain tokens are valid. They can be categorized into two types

- **block-based** Defined by a specific number of blocks (e.g., 1000 `blocks`).
- **time-based** Defined by a specific duration in seconds (e.g., 1000 `seconds`).

Tokens linked to an `epoch` remain valid as long as the `epoch` is active. Once the specified number of `blocks` or the duration in `seconds` has passed, the `epoch` expires, and any tokens associated with it are considered expired.

### Balance Look Back Over Epochs

To retrieve the usable balance, tokens are checked from the **current epoch** against a **past epoch** (which can be any **_n_** epochs back). The past epoch can be set to any value **_n_**, allowing flexibility in tracking and summing tokens that are still valid from previous epochs, up to **_n_** epochs back.

The usable balance is the sum of tokens valid between the **current epoch** and the **past epoch**, ensuring that only non-expired tokens are considered.

#### Example Scenario

| **epoch** | **balance** |
| --------- | ----------- |
| 1         | 100         |
| 2         | 150         |
| 3         | 200         |

- **Current Epoch**: 3
- **Past Epoch**: 1 epoch back
- **Usable Balance**: 350

Tokens from **Epoch 2** and **Epoch 3** are valid. The same logic applies for any **_n_** epochs back, where the usable balance includes tokens from the current epoch and all prior valid epochs.

Compatible implementations **MUST** inherit from [ERC-20](/EIPs/EIPS/eip-20)&apos;s interface and **MUST** have all the following functions and all function behavior **MUST** meet the specification.

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity &gt;=0.8.0 &lt;0.9.0;

/**
 * @title ERC-7818 interface
 * @dev Interface for adding expirable functionality to ERC20 tokens.
 */

import &quot;./IERC20.sol&quot;;

interface IERC7818 is IERC20 {
    /**
     * @dev Enum represents the types of `epoch` that can be used.
     * @notice The implementing contract may use one of these types to define how the `epoch` is measured.
     */
    enum EPOCH_TYPE {
        BLOCKS_BASED, // measured in the number of blocks (e.g., 1000 blocks)
        TIME_BASED // measured in seconds (UNIX time) (e.g., 1000 seconds)
    }

    /**
     * @dev Retrieves the balance of a specific `epoch` owned by an account.
     * @param epoch The `epoch for which the balance is checked.
     * @param account The address of the account.
     * @return uint256 The balance of the specified `epoch`.
     * @notice &quot;MUST&quot; return 0 if the specified `epoch` is expired.
     */
    function balanceOfAtEpoch(
        uint256 epoch,
        address account
    ) external view returns (uint256);

    /**
     * @dev Retrieves the latest epoch currently tracked by the contract.
     * @return uint256 The latest epoch of the contract.
     */
    function currentEpoch() external view returns (uint256);

    /**
     * @dev Retrieves the duration of a single epoch.
     * @return uint256 The duration of a single epoch.
     * @notice The unit of the epoch length is determined by the `validityPeriodType` function.
     */
    function epochLength() external view returns (uint256);

    /**
     * @dev Returns the type of the epoch.
     * @return EPOCH_TYPE  Enum value indicating the unit of an epoch.
     */
    function epochType() external view returns (EPOCH_TYPE);
    
    /**
     * @dev Retrieves the validity duration in `epoch` counts.
     * @return uint256 The validity duration in `epoch` counts.
     */
    function validityDuration() external view returns (uint256);

    /**
     * @dev Checks whether a specific `epoch` is expired.
     * @param epoch The `epoch` to check.
     * @return bool True if the token is expired, false otherwise.
     * @notice Implementing contracts &quot;MUST&quot; define and document the logic for determining expiration,
     * typically by comparing the latest epoch with the given `epoch` value,
     * based on the `EPOCH_TYPE` measurement (e.g., block count or time duration).
     */
    function isEpochExpired(uint256 epoch) external view returns (bool);

    /**
     * @dev Transfers a specific `epoch` and value to a recipient.
     * @param epoch The `epoch` for the transfer.
     * @param to The recipient address.
     * @param value The amount to transfer.
     * @return bool True if the transfer succeeded, otherwise false.
     */
    function transferAtEpoch(
        uint256 epoch,
        address to,
        uint256 value
    ) external returns (bool);

    /**
     * @dev Transfers a specific `epoch` and value from one account to another.
     * @param epoch The `epoch` for the transfer.
     * @param from The sender&apos;s address.
     * @param to The recipient&apos;s address.
     * @param value The amount to transfer.
     * @return bool True if the transfer succeeded, otherwise false.
     */
    function transferFromAtEpoch(
        uint256 epoch,
        address from,
        address to,
        uint256 value
    ) external returns (bool);
}
```

### Behavior Specification

- `balanceOf` **MUST** return the total balance of tokens held by an account that are still valid (i.e., have not expired). This includes any tokens associated with specific epochs, provided they remain within their validity duration. Expired tokens **MUST NOT** be included in the returned balance, ensuring that only actively usable tokens are reflected in the result.
- `balanceOfAtEpoch` **MUST** return the balance of tokens held by an account at the specified `epoch`. If the specified epoch is expired, this function **MUST** return `0`.
For example, if `epoch` 5 has expired, calling `balanceOfByEpoch(5, address)` returns `0` even if there were tokens previously held in that epoch.
- `currentEpoch` **MUST** return the current `epoch` of the contract.
- `epochLength` **MUST** return duration between `epoch` in blocks or time in seconds.
- `epochType` **MUST** return the type of epoch used by the contract, which can be either `BLOCKS_BASED` or `TIME_BASED`.
- `validityDuration` **MUST** return the validity duration of tokens in terms of `epoch` counts.
- `isEpochExpired` **MUST** return true if the given `epoch` is expired, otherwise `false`.
- `transfer` and `transferFrom` **MUST** exclusively transfer tokens that remain non-expired at the time of the transaction. Attempting to transfer expired tokens **MUST** revert the transaction or return `false`. Additionally, implementations **MAY** include logic to prioritize the automatic transfer of tokens closest to expiration, ensuring that the earliest expiring tokens are used first, provided they meet the non-expired condition.
- `transferAtEpoch` and `transferFromAtEpoch` **MUST** transfer the specified number of tokens held by an account at the specified epoch to the recipient, If the epoch has expired, the transaction **MUST** `revert` or return `false`
- `totalSupply` **SHOULD** be set to `0` or `type(uint256).max` due to the challenges of tracking only valid (non-expired) tokens.
- The implementation **MAY** use a standardized custom error, such as `ERC7818TransferredExpiredToken` or `ERC7818TransferredExpiredToken(address sender, uint256 epoch)`, to clearly indicate that the operation failed due to attempting to transfer expired tokens.
  
### Additional Potential Useful Function

These **OPTIONAL** functions provide additional functionality that might be useful depending on the specific use case.
- `getEpochBalance` returns the amount of tokens stored in a given `epoch`, even if the `epoch` has expired.
- `getEpochInfo` returns both the start and end of the specified `epoch`.
- `getNearestExpiryOf` returns the token amount closest to expiration, along with an estimated expiration block number or timestamp based on `epochType`.
- `getRemainingDurationBeforeEpochChange` returns the remaining time or blocks before the `epoch` change happens, based on the `epochType`.
  
## Rationale

Although the term `epoch` is an abstract concept, it leaves room for various implementations. For example, epochs can support more granular tracking of tokens within each epoch, allowing for greater control over when tokens are valid or expired on-chain. Alternatively, epochs can support bulk expiration, where all tokens within the same epoch expire simultaneously. This flexibility enables different methods of tracking token expiration, depending on the specific needs of the use case.
`epoch` also introduces a &quot;lazy&quot; way to simplify token expiration tracking in a flexible and gas-efficient manner. Instead of continuously updating the expiration state with `write` operations by the user or additional services, the current epoch can be calculated using a `read` operation.

## Backwards Compatibility

This standard is fully [ERC-20](/EIPs/EIPS/eip-20) compatible.

## Reference Implementation

For reference implementation can be found [here](/EIPs/assets/eip-7818/), But in the reference implementation, we employ a sorted list to automatically select the token that nearest expires first with a First-In-First-Out (`FIFO`) and sliding window algorithm that operates based on the `block.number` as opposed to relying on `block.timestamp`, which has been criticized for its lack of security and resilience, particularly given the increasing usage of Layer 2 (L2) networks over Layer 1 (L1) networks. Many L2 networks exhibit centralization and instability, which directly impacts asset integrity, rendering them potentially unusable during periods of network halting, as they are still reliant on the timestamp.

## Security Considerations

### Denial Of Service
Run out of gas problem due to the operation consuming higher gas if transferring multiple groups of small tokens or loop transfer.

### Gas Limit Vulnerabilities
Exceeds block gas limit if the blockchain has a block gas limit lower than the gas used in the transaction.

### Block values as a proxy for time
if using `block.timestamp` for calculating `epoch` and In rare network halts, block production stops, freezing `block.timestamp` and disrupting time-based logic. This risks asset integrity and inconsistent states.

### Fairness Concerns
In a straightforward implementation, where all tokens within the same epoch share the same expiration (e.g., at `epoch`:`x`), bulk expiration occurs.

### Risks in Liquidity Pools
When tokens with expiration dates are deposited into liquidity pools (e.g., in DEXs), they may expire while still in the pool. 

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 13 Nov 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7818</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7818</guid>
      </item>
    
      <item>
        <title>SETDELEGATE instruction</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7819-create-delegate/21763</comments>
        
        <description>## Abstract

Introduce a new instruction that allows smart contracts to create (and update) delegation accounts that match [EIP-7702](/EIPs/EIPS/eip-7702)&apos;s design. These accounts can be used similarly to [ERC-1167](/EIPs/EIPS/eip-1167) clones, with significant advantages.

## Motivation

Many on-chain applications involve creating multiple instances of the same code at different locations. Account abstraction solutions depend heavily on this pattern to deploy smart account instances.

These applications often rely on clones, or proxies, to reduce deployment costs. Clones, such as those described in ERC-1167, are minimal pieces of code that contain the target address directly in the bytecode. That makes them extremely lightweight but prevents any form of reconfiguration (upgradability). Upgradeable proxies differ from clones in that they read the implementation&apos;s address from storage. This makes them more versatile but also more expensive to use.

In both cases, delegating the received calls to an implementation using EVM code comes with some downsides:

- Calldata must be copied to memory before performing the delegate call.
- If EOF is ever enabled, clones and proxies written in EOF do not support delegation to an implementation written in legacy EVM code, and are thus limited or possibly dangerous. This encourages the continued use of legacy EVM code.

EIP-7702 introduces a new type of object with the expected behavior: the delegation indicator. These objects are designed to be instantiated at EOA addresses, but the same behavior can be reused to implement clones at the protocol level. Using delegation indicators for this use case provides upgradeability without the need for storage lookups, provided the contract calling `SETDELEGATE` allows it.

Studies by the Geth team (see &quot;Not all state is equal&quot; from EthCC[9]) have shown that 97.1% of the ~50 million contracts deployed correspond to code that has been deployed more than once, and that 28.6% of the unique bytecodes are tiny (under 1 KiB). Clones and proxies probably account for a large fraction of these contracts. Having a technical solution to use delegation indicators for these contracts would positively impact both the users (through reduced interaction cost) and the network&apos;s sustainability (through reduced state growth).

The use cases for this new deployment method include the &quot;traditional&quot; family of smart contract accounts used by wallets such as Safe, [ERC-4337](/EIPs/EIPS/eip-4337)-compliant smart accounts (that need upgradeability to stay up to date with new versions of the entrypoint), and all the new deployments implicitly required by proposals such as [EIP-8141](/EIPs/EIPS/eip-8141) in our path toward quantum-resistant accounts.

### Account Abstraction

Smart accounts (contracts that are &quot;owned&quot; by one or multiple keys and are intended to replace EOAs) are often deployed using clones or proxies that point to a singleton implementation. This forces a choice between an upgradeable or a non-upgradeable design. Both designs come with downsides. Non-upgradeable designs can leave you stranded with buggy (or limited) account code. Upgradeable designs incur costs associated with fetching the implementation address from storage.

The `SETDELEGATE` instruction would enable new factories to implement an upgradeable design without the added cost of the lookup. Factories could also deploy non-upgradeable variants, or even selectively disable the upgradeability of some accounts. Both the upgrade mechanism and the selective locking would be handled at the factory level, which removes the burden of implementing the upgrade logic in the account itself.

Additionally, using EIP-7702 delegations instead of clones/proxies moves the call redirection logic from userspace to the protocol. This means fewer EVM operations and thus reduced gas consumption for every operation that calls these contracts. This includes the verification of signatures and the execution of user operations, but also transfers of assets that include a callback, such as [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155) tokens.

### Scalability

Clone and proxy contracts are present in large numbers in the blockchain state. OpenZeppelin&apos;s [ERC-1967](/EIPs/EIPS/eip-1967) proxies are ~708 bytes. Using EIP-7702 delegations that are only 23 bytes would significantly reduce blockchain state usage.

Additionally, clone and proxy contracts handle call redirection in userspace, which incurs execution cost. Using EIP-7702 delegations moves the redirection to the protocol level, reducing the gas cost of all operations targeting these accounts. This means more gas/blockspace is available for the actual execution of the contracts.

## Specification

A new instruction (`SETDELEGATE`) is added at `0xf6`.

### Behavior

Executing this instruction does the following:

1. Deduct `EMPTY_ACCOUNT_COST` gas.
2. Halt if the current frame is in `static-mode`.
3. Pop `salt` and `target` from the operand stack.
4. Calculate `location` as `keccak256(DESIGNATOR ++ address ++ salt)[12:]`.
5. Add `location` to `accessed_addresses`, as defined in [EIP-2929](/EIPs/EIPS/eip-2929).
6. Halt if the code at `location` is not empty and does not start with `0xEF0100` (i.e., it is neither empty nor a delegation indicator).
7. Add `EMPTY_ACCOUNT_COST - BASE_COST` gas to the global refund counter if `location` already exists in the trie.
8. Set the code of `location` to `DESIGNATOR ++ target`, matching the delegation process defined in EIP-7702.
    - Similarly to EIP-7702, if `target` is `0x0`, do not write the designation. Instead, clear the code at `location` and reset `location`&apos;s code hash to the empty hash `0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470`.
9. If the nonce of the account at `location` is 0, increment it to 1.
10. Push `location` onto the stack.

In step 8, `target` MUST be exactly 20 bytes. If the value retrieved from the stack is smaller than 20 bytes, it MUST be left-padded (big-endian notation) with zeros. If it is larger than 20 bytes, the highest-order bytes MUST be trimmed. The code placed at `location` MUST be exactly 23 bytes long, following EIP-7702.

The delegation indicator created at `location` behaves identically to those created by EIP-7702.

Note: The delegation is effective immediately upon completion of the operation. Calls to the address starting from the very next operation will execute the newly delegated code.

The delegation indicators created by the `SETDELEGATE` opcode are the same objects as those created using EIP-7702. Therefore, all behavioral specifics documented in EIP-7702 (`CODESIZE`, `CODECOPY`, targeting precompiles, and chaining delegation indicators) also apply here. Any future EIP that modifies the behavior of EIP-7702 delegation indicators should also apply to those created using `SETDELEGATE`. They are not contracts and cannot be deleted using `SELFDESTRUCT`, even if `SELFDESTRUCT` occurs in the same transaction that created the account at `location`. Destruction of delegations SHOULD only be possible by the same caller (that created them) performing a new `SETDELEGATE` call with the same salt and a zero target.

Step 9 ensures that an account created using `SETDELEGATE` never returns to an empty state (as forbidden by [EIP-7523](/EIPs/EIPS/eip-7523)). Even if the balance is zero, no state was ever set, and the code is removed by a `SETDELEGATE` operation with a zero target, the nonce being at least one guarantees the account is not considered empty.

### Parameters

These parameters are the same as those used in EIP-7702.

| Constant             | Value    |
| -------------------- | -------- |
| `DESIGNATOR`         | 0xef0100 |
| `EMPTY_ACCOUNT_COST` | 25000    |
| `BASE_COST`          | 12500    |

## Rationale

### Gas Cost

The execution of the `SETDELEGATE` instruction involves fewer moving pieces than what EIP-7702 gas costs account for:

- There is no signature recovery.
- There is no dedicated calldata that must be accounted for beyond what is already paid at the transaction level.
- There is no nonce update (aside from the initial set to 1 in step 9).

Therefore, the cost of executing this instruction could be lower than that of EIP-7702. The values from EIP-7702 are reused here for simplicity. They are lower than the costs of `CREATE` or `CREATE2` operations, making this instruction competitive for the intended use cases.

### Address Derivation

The `location` is derived from `keccak256(DESIGNATOR ++ address ++ salt)`, using the caller&apos;s address and a caller-chosen salt. This mirrors the deterministic addressing of `CREATE2` while using a distinct pre-image length (55 bytes) to avoid collisions with existing address derivation schemes (see Backwards Compatibility).

## Backwards Compatibility

### Address Collision

The derivation of `location` is designed not to conflict with contracts created using the `CREATE` or `CREATE2` opcodes. In particular, the pre-images used to hash the produced address have different lengths, preventing any collision.

Contracts deployed using `CREATE2` have an address derived from an 85-byte pre-image, as opposed to 55 bytes for `SETDELEGATE`. This difference alone eliminates the risk of pre-image collision.

Contracts deployed using `CREATE` have an address derived from `RLP([address, nonce])`. For this pre-image to have a length of 55 bytes (matching `SETDELEGATE`), the `nonce` would need to be 32 bytes long. In that case, the RLP encoding would be `0xf694&lt;address&gt;a0&lt;nonce&gt;`, which does not start with the `0xef0100` designator used by `SETDELEGATE`. A smaller nonce could lead to a pre-image starting with `0xef`, but then the pre-image would be shorter than 55 bytes. Even in that case, the pre-image would start with `0xef94` (where `0x94` encodes the 20-byte `address` object), which still differs from the `SETDELEGATE` pre-image prefix.

## Security Considerations

### Delegator Upgrades and Deletion

Reusing EIP-7702 behavior, including clearing the code when the target is `0x0`, enables the ability to upgrade or even remove the created delegation indicator. This process is controlled (and can be restricted) by the factory contract that calls `SETDELEGATE`. Some factories will add checks that prevent re-executing `SETDELEGATE` with a salt that was already used, making the created delegation indicator immutable. Others may allow access-restricted upgrades but prevent deletion. In any case, guarantees about the lifecycle of delegation indicators created using `SETDELEGATE` are provided by the contracts that call it, not by the protocol itself.

### Delegator Chaining

As documented in EIP-7702, designation chains or loops are not resolved. This means that, unlike clones, chaining is an issue. However, this is something developers are accustomed to, as chaining proxies can result in unexpected behaviors, including infinite delegation loops.

Factories may want to protect against this risk by verifying that the `target` does not itself contain a delegation indicator.

### Front-Running Initialization

Unlike EIP-7702 signatures, which can be included in any transaction and can thus lead to initialization front-running if the implementation doesn&apos;t verify the authenticity of the initialization parameters, `SETDELEGATE` is executed by a smart contract that can perform the initialization logic atomically, immediately after the delegation is created. This process is well understood by developers who already initialize clones and proxies just after creation.

### Multiple Delegation Changes Within a Single Transaction

If a contract performs multiple `SETDELEGATE` operations with the same salt but different targets within the same transaction, while also making calls to the corresponding address, this would result in—within a single transaction without reverts—an address that has multiple different code values associated with it, two or more of which are executed. This includes the delegation being removed or reset any number of times during the transaction.

This behavior is already possible with more traditional upgradeable contracts, where the implementation target changes as a result of modifying a specific storage slot.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 18 Nov 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7819</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7819</guid>
      </item>
    
      <item>
        <title>Access Control Registry</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7820-access-control-registry/21764</comments>
        
        <description>## Abstract

The Access Control Registry (ACR) standard defines a universal interface for managing role-based access control across multiple smart contracts. This standard introduces a centralized registry system allowing access control management for multiple smart contracts. The single access-control registry smart contract manages the user roles across multiple contracts, and can be queryed for contract-specific role information. Additionally, the ACR standard provides functionality to grant and revoke roles for specific accounts, either individually or in bulk, ensuring that only authorized users can perform specific actions within a specific contract.

The core of the standard includes:

- **Registration and Unregistration**: Contracts can register with the ACR, specifying an admin who can manage roles within the contract. Contracts can also be unregistered when they are no longer active.

- **Role Management**: Admins can grant or revoke roles for accounts, either individually or in batches, ensuring fine-grained control over who can perform what actions within a contract.

- **Role Verification**: Any account can verify if another account has a specific role in a registered contract, providing transparency and facilitating easier integration with other systems.

By centralizing access control management, the ACR standard aims to reduce redundancy, minimize errors in access control logic, and provide a clear and standardized approach to role management across smart contracts. This improves security and maintainability, making it easier for developers to implement robust access control mechanisms in their applications.

## Motivation

As decentralized applications (dApps) grow in complexity, managing access control across multiple smart contracts becomes increasingly difficult.
Current practices involve bespoke implementations, leading to redundancy and potential security flaws. A standardized approach for managing roles and permissions will ensure better interoperability, security, and transparency. By providing a unified interface for registering contracts and managing roles, this standard simplifies development, ensures consistency and enhances security. It facilitates easier integration and auditing, fostering a more robust and interoperable ecosystem.

The advantages of using the provided system might be:

Structured smart contracts management via specialized contracts.
Ad-hoc access-control provision of a protocol.
Ability to specify custom access control rules to maintain the protocol.

## Specification

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.

The `AccessControlRegistry` contract provides a standardized interface for managing access control in Ethereum smart contracts. It includes functions to register and unregister contracts, grant and revoke roles for specific contracts, and check if an account has a particular role in a registered contract. Events are emitted for contract registration, unregistration, role grants, and role revocations, ensuring transparency and traceability of access control changes.

Additionally, the AccessControlRegistry MUST reject the registration of zero addresses.

```solidity
pragma solidity 0.8.23;
interface IAccessControlRegistry {
    // Emitted when a contract is registered.
    // @param _contract The address of the registered contract.
    // @param _admin The address of the admin for the registered contract.
    event ContractRegistered(address indexed _contract, address indexed _admin);
    // Emitted when a contract is unregistered.
    // @param _contract The address of the unregistered contract.
    // @param _admin The address who unregistered the contract
    event ContractUnregistered(address indexed _contract, address indexed _admin);
    // Emitted when a role is granted to an account for a contract.
    // @param targetContract The address of the contract.
    // @param role The role being granted.
    // @param account The address of the account.
    event RoleGranted(
        address indexed targetContract,
        bytes32 indexed role,
        address indexed account
    );
    // Emitted when a role is revoked from an account for a contract.
    // @param targetContract The address of the contract.
    // @param role The role being revoked.
    // @param account The address of the account.
    event RoleRevoked(
        address indexed targetContract,
        bytes32 indexed role,
        address indexed account
    );
    // Registers a contract with the given admin.
    // @param _admin The address of the admin for the registered contract.
    function registerContract(address _admin) external;
    // Unregisters a contract.
    // @param _contract The address of the contract to unregister.
    function unRegisterContract(address _contract) external;
    // Grants roles to multiple accounts for multiple contracts.
    // @param targetContracts An array of contract addresses to which roles will be granted.
    // @param roles An array of roles to be granted.
    // @param accounts An array of accounts to be granted the roles.
    function grantRole(
        address[] memory targetContracts,
        bytes32[] memory roles,
        address[] memory accounts
    ) external;
    // Revokes roles from multiple accounts for multiple contracts.
    // @param targetContracts An array of contract addresses from which roles will be revoked.
    // @param roles An array of roles to be revoked.
    // @param accounts An array of accounts from which the roles will be revoked.
    function revokeRole(
        address[] memory targetContracts,
        bytes32[] memory roles,
        address[] memory accounts
    ) external;
    
    //Gets the information of a registered contract.
    //@param _contract The address of the contract to get the information.
    //@return isActive Whether the contract is active.
    //@return admin The address of the admin for the contract.
    //MUST revert if the registered contract doesn&apos;t exist
    function getContractInfo(
        address _contract
    ) external view returns (bool isActive, address admin);
    // Gets the information of a registered contract.
    // @param _contract The address of the contract to get the information.
    // @return isActive Whether the contract is active.
    // @return admin The address of the admin for the contract.
    // MUST revert if the registered contract doesn&apos;t exist`
    function getRoleInfo(
        address _contract
    ) external view returns (bool isActive, address admin);
}
```

## Rationale

The `IAccessControlRegistry` interface aims to provide a standardized way to manage access control across multiple contracts within the ecosystem. By defining a clear structure and set of events, this interface helps streamline the process of registering, unregistering, and managing roles for contracts. The rationale for each function and event is as follows:

### Contract Registration and Unregistration

**`registerContract(address _admin)`**: This function allows the registration of a new contract along with its admin address. This is crucial for initializing the access control settings for a contract and ensuring that there is an accountable admin who can manage roles and permissions.

**`unRegisterContract(address _contract)`**: This function enables the removal of a contract from the registry. Unregistering a contract is important when a contract is no longer in use or needs to be decommissioned to prevent unauthorized access.

### Role Management

**`grantRole(address[] memory targetContracts, bytes32[] memory roles, address[] memory accounts)`**: This function allows the assignment of roles to multiple accounts for multiple contracts in a single transaction. This bulk operation is designed to reduce the gas costs and simplify the process of role assignment in large systems with numerous contracts and users.

**`revokeRole(address[] memory targetContracts, bytes32[] memory roles, address[] memory accounts)`**: Similar to `grantRole`, this function facilitates the revocation of roles from multiple accounts across multiple contracts in a single transaction. This ensures efficient management of permissions, especially in scenarios where many users need their roles updated simultaneously.

### Role Checking

**`getRoleInfo(address targetContract, address account, bytes32 role)`**: This view function allows the verification of whether a particular account holds a specific role for a given contract. This is essential for ensuring that operations requiring specific permissions are performed only by authorized users.

### Contract Information Retrieval

**`getContractInfo(address _contract)`**: This function provides the ability to retrieve the status and admin information of a registered contract. It enhances transparency and allows administrators and users to easily query the status and management of any contract within the registry.

### Events

**`ContractRegistered(address indexed _contract, address indexed _admin)`**: Emitted when a new contract is registered, this event ensures that there is a public record of contract registrations, facilitating auditability and transparency.

**`ContractUnregistered(address indexed _contract, address indexed _admin)`**: Emitted when a contract is unregistered, this event serves to notify the system and its users of the removal of a contract from the registry, which is critical for maintaining an up-to-date and accurate registry.

**`RoleGranted(address indexed targetContract, bytes32 indexed role, address indexed account)`**: Emitted when a role is granted to an account, this event provides a public log that can be used to track role assignments and changes, ensuring that role grants are transparent and verifiable.

**`RoleRevoked(address indexed targetContract, bytes32 indexed role, address indexed account)`**: Emitted when a role is revoked from an account, this event similarly ensures that role revocations are publicly logged and traceable, supporting robust access control management.


## Reference Implementation

The `register` function must be invoked from the registering smart contract.
The `grantRole` and `revokeRole` functions must be invoked either from the registered contract or the admin of the registered contract. 

```solidity
pragma solidity 0.8.23;

import &quot;./IAccessControlRegistry.sol&quot;;

contract AccessControlRegistry is IAccessControlRegistry {

    // Contains information about a registered contract.
    // @param isActive Indicates whether the contract is active.
    // @param admin The address of the admin for the registered contract.
    struct ContractInfo {
        bool isActive;
        address admin;
    }

    // Mapping to store information of registered contracts
    mapping(address =&gt; ContractInfo) public contracts;

    // Mapping to track roles assigned to accounts for specific contracts
    mapping(address =&gt; mapping(address =&gt; mapping(bytes32 =&gt; bool))) public _contractRoles;

    // Custom error to handle duplicate registration attempts
    error ContractAlreadyRegistered();

    // Modifier to check if the caller is an admin or the contract itself
    modifier onlyAdminOrContract(address _contract) {
        require(
            _isAdmin(_contract, msg.sender) || 
            (contracts[msg.sender].isActive &amp;&amp; msg.sender == _contract),
            &quot;Caller is not admin nor contract&quot;
        );
        _;
    }

    // Modifier to check if the caller is an admin of the contract
    modifier onlyAdmin(address _contract) {
        require(
            _isAdmin(_contract, msg.sender),
            &quot;Caller is not an admin&quot;
        );
        _;
    }

    // Modifier to ensure the contract is active
    modifier onlyActiveContract(address _contract) {
        require(contracts[_contract].isActive, &quot;Contract not registered&quot;);
        _;
    }

    // Modifier to validate if the provided address is non-zero
    modifier validAddress(address addr) {
        require(addr != address(0), &quot;Invalid address&quot;);
        _;
    }

    // Registers a contract with the given admin
    // _admin: Address of the admin to register
    function registerContract(address _admin) external validAddress(_admin) {
        address _contract = msg.sender;

        // Check if the contract is already registered
        ContractInfo storage contractInfo = contracts[_contract];
        if (contractInfo.isActive) {
            revert ContractAlreadyRegistered();
        }

        // Register the contract with the provided admin
        contractInfo.isActive = true;
        contractInfo.admin = _admin;

        emit ContractRegistered(_contract, _admin);
    }

    // Unregisters a contract
    // _contract: Address of the contract to unregister
    function unRegisterContract(address _contract) 
        public 
        onlyAdmin(_contract) 
        onlyActiveContract(_contract) 
    {
        ContractInfo storage contractInfo = contracts[_contract];
        contractInfo.isActive = false;
        contractInfo.admin = address(0);

        emit ContractUnregistered(_contract, msg.sender);
    }

    // Grants roles to multiple accounts for multiple contracts
    // targetContracts: Array of contract addresses
    // roles: Array of roles to grant
    // accounts: Array of accounts to assign the roles
    function grantRole(
        address[] memory targetContracts,
        bytes32[] memory roles,
        address[] memory accounts
    ) public {
        require(
            targetContracts.length == roles.length &amp;&amp;
            roles.length == accounts.length,
            &quot;Array lengths do not match&quot;
        );

        uint256 cachedArrayLength = roles.length;

        // Grant roles in a batch
        for (uint256 i; i &lt; cachedArrayLength; ++i) {
            _grantRole(targetContracts[i], roles[i], accounts[i]);
        }
    }

    // Revokes roles from multiple accounts for multiple contracts
    // targetContracts: Array of contract addresses
    // roles: Array of roles to revoke
    // accounts: Array of accounts from which roles are revoked
    function revokeRole(
        address[] memory targetContracts,
        bytes32[] memory roles,
        address[] memory accounts
    ) public {
        require(
            targetContracts.length == roles.length &amp;&amp;
            roles.length == accounts.length,
            &quot;Array lengths do not match&quot;
        );

        uint256 cachedArrayLength = roles.length;

        // Revoke roles in a batch
        for (uint256 i; i &lt; cachedArrayLength; ++i) {
            _revokeRole(targetContracts[i], roles[i], accounts[i]);
        }
    }

    // Retrieves information of a registered contract
    // _contract: Address of the contract
    // Returns: isActive status and admin address
    function getContractInfo(address _contract) 
        public 
        view 
        returns (bool isActive, address admin) 
    {
        ContractInfo storage info = contracts[_contract];
        return (info.isActive, info.admin);
    }

    // Gets role information for an account and contract
    // targetContract: Address of the target contract
    // account: Address of the account
    // role: Role identifier
    // Returns: Boolean indicating if the account has the role
    function getRoleInfo(
        address targetContract,
        address account,
        bytes32 role
    ) public view returns (bool) {
        return _contractRoles[targetContract][account][role];
    }

    // Internal function to grant a role to an account for a contract
    function _grantRole(
        address targetContract,
        bytes32 role,
        address account
    )
        internal
        onlyAdminOrContract(targetContract)
        onlyActiveContract(targetContract)
        validAddress(account)
    {
        _contractRoles[targetContract][account][role] = true;
        emit RoleGranted(targetContract, role, account);
    }

    // Internal function to revoke a role from an account for a contract
    function _revokeRole(
        address targetContract,
        bytes32 role,
        address account
    )
        internal
        onlyAdminOrContract(targetContract)
        onlyActiveContract(targetContract)
        validAddress(account)
    {
        require(
            _contractRoles[targetContract][account][role],
            &quot;Role already revoked&quot;
        );
        _contractRoles[targetContract][account][role] = false;
        emit RoleRevoked(targetContract, role, account);
    }

    // Checks if the caller is an admin for the contract
    // _contract: Address of the contract
    // _admin: Address of the admin
    // Returns: Boolean indicating admin status
    function _isAdmin(address _contract, address _admin) internal view returns (bool) {
        return _admin == contracts[_contract].admin;
    }
}

```
### Design Decisions

There are a few design decisions that have to be explicitly specified to ensure the functionality, security, and efficiency of the `IAccessControlRegistry`:

#### Decentralized Contract Registration

**No Central Owner**: There is no central owner who can register contracts. This design choice promotes decentralization and ensures that individual contracts are responsible for their own registration and management.

#### Efficient Storage and Lookup

**Mapping Utilization**: The use of mappings for storing contract information (`mapping(address =&gt; ContractInfo) private contracts`) and role assignments (`mapping(address =&gt; mapping(address =&gt; mapping(bytes32 =&gt; bool))) private _contractRoles`) ensures efficient storage and lookup. This is crucial for maintaining performance in a large-scale system with numerous contracts and roles.

#### Role Management Flexibility

**Bulk Operations**: Functions like `grantRole` and `revokeRole` allow for the assignment and revocation of roles to multiple accounts for multiple contracts in a single transaction. This bulk operation reduces gas costs and simplifies the process of role management in large systems.

#### Robust Security Measures

**Admin-Only Operations**: Functions that modify the state, such as unRegisterContract, `_grantRole`, and `_revokeRole`, are restricted to contract admins. This ensures that only authorized personnel can manage contracts and roles, reducing the risk of unauthorized changes.

**Valid Address Checks**: The `validAddress` modifier ensures that addresses are non-zero, preventing potential issues with null addresses which could lead to unintended behavior or security vulnerabilities.

**Active Contract Checks**: The `onlyActiveContract` modifier ensures that actions are only performed on active or registered contracts, preventing operations on inactive or unregistered contracts.

#### Transparent Auditing

**Event Logging**: Emitting events for each significant action (registration, unregistration, role granting, and revocation) provides a transparent log that can be monitored and audited. This helps in detecting and responding to unauthorized or suspicious activities promptly.

## Security Considerations

The `AccessControlRegistry` implements several security measures to ensure the integrity and reliability of the access control system:

**Admin-Only Restrictions**: By limiting state-modifying functions to contract admins, the system prevents unauthorized users from making critical changes.

**Active Contract Checks**: Operations are restricted to active contracts, reducing the risk of interacting with deprecated or unregistered contracts.

**Event Logging**: Comprehensive event logging supports transparency and auditability, allowing for effective monitoring and detection of unauthorized actions.


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 19 Nov 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7820</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7820</guid>
      </item>
    
      <item>
        <title>Minimal Batch Executor Interface</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7821-minimal-batch-executor-interface/21776</comments>
        
        <description>## Abstract

This proposal defines a minimal batch executor interface for delegations. A delegation is a smart contract that implements logic which other smart contracts can delegate to. This allows atomic batched executions to be prepared in a standardized way.

## Motivation

With the advent of [EIP-7702](./eip-7702), it is possible for Externally Owned Accounts (EOAs) to perform atomic batched executions.

We anticipate that there will be multiple EIP-7702 delegations from multiple major vendors. A standard for the execution interface will enable better interoperability. EIP-7702 delegation is a risky procedure which should be done sparingly — it should not be performed upon each time a user switches websites. Also, EIP-7702 delegations are transactions that cost gas, making frequent delegation switching uneconomical. A standardized execution interface will reduce the need to switch delegations.

This standard complements the `wallet_sendCalls` API in [EIP-5792](./eip-5792). It enables the detection of atomic batch execution capabilities on EOAs and the preparation of the calldata for atomic batch executions on EOAs.

Using atomic batched executions reduces total latency and total tranaction costs, making it preferable over sequential transaction sending for EOAs.

Hence the utmost motivation for this proposal, which has been crafted for maximal simplicity, extensibility, performance and compatibility.

## Specification

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

### Overview

The minimal batch executor interface is defined as follows:

```solidity
/// @dev Interface for minimal batch executor.
interface IERC7821 {
    /// @dev Call struct for the `execute` function.
    struct Call {
        address to; // Replaced with `address(this)` if `address(0)`.
        uint256 value; // Amount of native currency (i.e. Ether) to send.
        bytes data; // Calldata to send with the call.
    }

    /// @dev Executes the calls in `executionData`.
    /// Reverts and bubbles up error if any call fails.
    ///
    /// MAY replace the `Call.to` with `address(this)` if `address(0)`.
    ///
    /// `executionData` encoding (single batch):
    /// - If `opData` is empty, `executionData` is simply `abi.encode(calls)`.
    /// - Else, `executionData` is `abi.encode(calls, opData)`.
    ///   See: https://eips.ethereum.org/EIPS/eip-7579
    ///
    /// `executionData` encoding (batch of batches):
    /// - `executionData` is `abi.encode(bytes[])`, where each element in `bytes[]`
    ///   is an `executionData` for a single batch.
    ///
    /// Supported modes:
    /// - `0x01000000000000000000...`: Single batch. Does not support optional `opData`.
    /// - `0x01000000000078210001...`: Single batch. Supports optional `opData`.
    /// - `0x01000000000078210002...`: Batch of batches. The mode is optional.
    ///
    /// For the &quot;batch of batches&quot; mode, each batch will be recursively passed into
    /// `execute` internally with mode `0x01000000000078210001...`.
    /// Useful for passing in batches signed by different signers.
    ///
    /// Authorization checks:
    /// - If `opData` is empty, the implementation SHOULD require that
    ///   `msg.sender == address(this)`.
    /// - If `opData` is not empty, the implementation SHOULD use the signature
    ///   encoded in `opData` to determine if the caller can perform the execution.
    /// - If `msg.sender` is an authorized entry point, then `execute` MAY accept
    ///   calls from the entry point, and MAY use `opData` for specialized logic.
    ///
    /// `opData` may be used to store additional data for authentication,
    /// paymaster data, gas limits, etc.
    ///
    /// For calldata compression efficiency, if a Call.to is `address(0)`,
    /// it will be replaced with `address(this)`.
    function execute(bytes32 mode, bytes calldata executionData)
        external
        payable;

    /// @dev Provided for execution mode support detection.
    /// Only returns true for:
    /// - `0x01000000000000000000...`: Single batch. Does not support optional `opData`.
    /// - `0x01000000000078210001...`: Single batch. Supports optional `opData`.
    /// - `0x01000000000078210002...`: Batch of batches. The mode is optional.
    function supportsExecutionMode(bytes32 mode) external view returns (bool);
}
```

Support for batch of batches mode is OPTIONAL. If it is not supported, the contract MUST return false for any mode starting with `0x01000000000078210002` in `supportsExecutionMode`.

### Recommendations

To support the approve + swap workflow on EOAs with delegations, frontends SHOULD:

1. Query `supportsExecutionMode(bytes32(0x0100000000000000000000000000000000000000000000000000000000000000))`, ensuring that it returns true.

2. Perform `execute(bytes32(0x0100000000000000000000000000000000000000000000000000000000000000), abi.encode(calls))`.

## Rationale

We aim for radical minimalism to keep the standard as left-curved as possible. Simplicity is the key to adoption. Our North Star is to get every decentralized exchange to support the approve + swap workflow for EOAs with delegations as soon as possible.

### `execute` and `supportsExecutionMode`

We have opted to use the `execute` and `supportsExecutionMode` functions in [ERC-7579](/EIPs/EIPS/eip-7579) for better compatibility with the existing smart account ecosystem.

While radical minimalism is the goal, some compromises have to be made in the pursuit for better adoption.

For minimalism, this standard does not require implementing the `executeFromExecutor` function in [ERC-7579](/EIPs/EIPS/eip-7579).

### Optional encoding of `opData` in `executionData`

The `opData` bytes parameter can be optionally included in `executionData` by either doing `abi.encode(calls)` or `abi.encode(calls, opData)`.

### Replacing `address(0)` with `address(this)`

For calldata compression optimization.

### Optional batch of batches mode

The `opData` may be used to provide authentication data for a single batch. Having a batch of batches mode will enable a single transaction to be able to submit batches signed by different signers, without the need for an authorized entry point. This mode is kept optional because the same functionality can still be achieved with the use of an authorized entry point. It is included for developer experience.

## Backwards Compatibility

No backwards compatibility issues.

## Reference Implementation

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.4;

/// @notice Minimal batch executor mixin.
abstract contract ERC7821 {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STRUCTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Call struct for the `execute` function.
    struct Call {
        address to; // Replaced with `address(this)` if `address(0)`.
        uint256 value; // Amount of native currency (i.e. Ether) to send.
        bytes data; // Calldata to send with the call.
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           ERRORS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The execution mode is not supported.
    error UnsupportedExecutionMode();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                    EXECUTION OPERATIONS                    */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Executes the calls in `executionData`.
    /// Reverts and bubbles up error if any call fails.
    ///
    /// `executionData` encoding (single batch):
    /// - If `opData` is empty, `executionData` is simply `abi.encode(calls)`.
    /// - Else, `executionData` is `abi.encode(calls, opData)`.
    ///   See: https://eips.ethereum.org/EIPS/eip-7579
    ///
    /// `executionData` encoding (batch of batches):
    /// - `executionData` is `abi.encode(bytes[])`, where each element in `bytes[]`
    ///   is an `executionData` for a single batch.
    ///
    /// Supported modes:
    /// - `0x01000000000000000000...`: Single batch. Does not support optional `opData`.
    /// - `0x01000000000078210001...`: Single batch. Supports optional `opData`.
    /// - `0x01000000000078210002...`: Batch of batches. The mode is optional.
    ///
    /// For the &quot;batch of batches&quot; mode, each batch will be recursively passed into
    /// `execute` internally with mode `0x01000000000078210001...`.
    /// Useful for passing in batches signed by different signers.
    ///
    /// Authorization checks:
    /// - If `opData` is empty, the implementation SHOULD require that
    ///   `msg.sender == address(this)`.
    /// - If `opData` is not empty, the implementation SHOULD use the signature
    ///   encoded in `opData` to determine if the caller can perform the execution.
    /// - If `msg.sender` is an authorized entry point, then `execute` MAY accept
    ///   calls from the entry point, and MAY use `opData` for specialized logic.
    ///
    /// `opData` may be used to store additional data for authentication,
    /// paymaster data, gas limits, etc.
    ///
    /// For calldata compression efficiency, if a Call.to is `address(0)`,
    /// it will be replaced with `address(this)`.
    function execute(bytes32 mode, bytes memory executionData)
        public
        payable
        virtual
    {
        uint256 id = _executionModeId(mode);
        if (id == 3) {
            mode ^= bytes32(uint256(3 &lt;&lt; (22 * 8)));
            bytes[] memory batches = abi.decode(executionData, (bytes[]));
            for (uint256 i; i &lt; batches.length; ++i) {
                execute(mode, batches[i]);
            }
            return;
        }
        if (id == uint256(0)) revert UnsupportedExecutionMode();
        bool tryWithOpData;
        /// @solidity memory-safe-assembly
        assembly {
            let t := gt(mload(add(executionData, 0x20)), 0x3f)
            let executionDataLength := mload(executionData)
            tryWithOpData := and(eq(id, 2), and(gt(executionDataLength, 0x3f), t))
        }
        Call[] memory calls;
        bytes memory opData;
        if (tryWithOpData) {
            (calls, opData) = abi.decode(executionData, (Call[], bytes));
        } else {
            calls = abi.decode(executionData, (Call[]));
        }
        _execute(calls, opData);
    }

    /// @dev Provided for execution mode support detection.
    /// Only returns true for:
    /// - `0x01000000000000000000...`: Single batch. Does not support optional `opData`.
    /// - `0x01000000000078210001...`: Single batch. Supports optional `opData`.
    /// - `0x01000000000078210002...`: Batch of batches. The mode is optional.
    function supportsExecutionMode(bytes32 mode) public view virtual returns (bool result) {
        return _executionModeId(mode) != 0;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      INTERNAL HELPERS                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev 0: invalid mode, 1: no `opData` support, 2: with `opData` support, 3: batch of batches.
    function _executionModeId(bytes32 mode) internal view virtual returns (uint256 id) {
        // Only supports atomic batched executions.
        // For the encoding scheme, see: https://eips.ethereum.org/EIPS/eip-7579
        // Bytes Layout:
        // - [0]      ( 1 byte )  `0x01` for batch call.
        // - [1]      ( 1 byte )  `0x00` for revert on any failure.
        // - [2..5]   ( 4 bytes)  Reserved by ERC7579 for future standardization.
        // - [6..9]   ( 4 bytes)  `0x00000000` or `0x78210001` or `0x78210002`.
        // - [10..31] (22 bytes)  Unused. Free for use.
        uint256 m = (uint256(mode) &gt;&gt; (22 * 8)) &amp; 0xffff00000000ffffffff;
        if (m == 0x01000000000078210002) id = 3;
        if (m == 0x01000000000078210001) id = 2;
        if (m == 0x01000000000000000000) id = 1;
    }

    /// @dev Executes the calls and returns the results.
    /// Reverts and bubbles up error if any call fails.
    function _execute(Call[] memory calls, bytes memory opData)
        internal
        virtual
    {
        // Very basic auth to only allow this contract to be called by itself.
        // Override this function to perform more complex auth with `opData`.
        if (opData.length == uint256(0)) {
            require(msg.sender == address(this));
            // Remember to return `_execute(calls)` when you override this function.
            return _execute(calls);
        }
        revert(); // In your override, replace this with logic to operate on `opData`.
    }

    /// @dev Executes the calls.
    /// Reverts and bubbles up error if any call fails.
    function _execute(Call[] memory calls) internal virtual {
        for (uint256 i; i &lt; calls.length; ++i) {
            Call memory c = calls[i];
            address to = c.to == address(0) ? address(this) : c.to;
            _execute(to, c.value, c.data);
        }
    }

    /// @dev Executes the call.
    /// Reverts and bubbles up error if the call fails.
    function _execute(address to, uint256 value, bytes memory data)
        internal
        virtual
    {
        (bool success, bytes memory result) = to.call{value: value}(data);
        if (success) return;
        /// @solidity memory-safe-assembly
        assembly {
            // Bubble up the revert if the call reverts.
            revert(add(result, 0x20), mload(result))
        }
    }
}
```

## Security Considerations

### Access controls for `execute`

Implementations should ensure that `execute` have the proper access controls.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 21 Nov 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7821</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7821</guid>
      </item>
    
      <item>
        <title>Set upper bounds for MODEXP</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7823-set-upper-bounds-for-modexp/21798</comments>
        
        <description>## Abstract

Introduce an upper bound on the inputs of the MODEXP precompile. This can reduce the number of potential bugs, because the testing surface is not infinite anymore, and makes it easier to be replaced using EVMMAX.

## Motivation

The MODEXP precompile has been a source of numerous consensus bugs. Many of them were due to specifically crafted cases using impractical input lengths.

Its pricing function is also quite complex given its nature of unbounded inputs. While we don&apos;t suggest to rework the pricing function, it may be possible in a future upgrade once the limits are in place.

Furthermore this limitation makes it more feasible to have the precompile replaced with EVM code through features like EVMMAX.

## Specification

Recap from [EIP-198](/EIPs/EIPS/eip-198):
&gt; At address `0x00……05`, add a precompile that expects input in the following format:
&gt; 
&gt; `&lt;length_of_BASE&gt; &lt;length_of_EXPONENT&gt; &lt;length_of_MODULUS&gt; &lt;BASE&gt; &lt;EXPONENT&gt; &lt;MODULUS&gt;`

We introduce an upper bound to the inputs of the precompile, each of the length inputs (`length_of_BASE`, `length_of_EXPONENT` and `length_of_MODULUS`) MUST be less than or equal to 8192 bits (1024 bytes).

If any of these inputs are larger than the limit, the precompile execution stops, returns an error, and consumes all gas.
    
## Rationale

### Limit

This upper bound allows the existing use cases of MODEXP:

1. RSA verification with up to 8192 bit keys. Commonly used ones are 1024/2048/4096 bits.
2. Elliptic curve related use cases are usually less than 384 bits.

### EVMMAX

Replacing the precompile with EVM code using an instruction set like EVMMAX would be made simpler with this limit: Common cases (256, 381, 1024, 2048) could be implemented in special fast paths, while a slow fallback could be provided for the rest. Or even special, frequently used, moduli could have their own paths.

Furthermore one could consider limiting the lengths to certain inputs only.

### Analysis

Since MODEXP was introduced in the Byzantium hard fork, an analysis has been conducted between block 5472266 (April 20, 2018) and block 21550926 (January 4th, 2025). All lengths of inputs are expressed in bytes.

#### Base length occurrences

| `input_of_BASE` | count |
|-----------------|-------|
| 32	| 2439595 |
| 128	| 4167 |
| 256	| 2969 |
| 160	| 436 |
| 512	| 36 |
| 0	| 13 |
| 64	| 7 |
| 78	| 2 |
| 513	| 2 |
| 129	| 1 |
| 385	| 1 |

#### Exponent length occurrences

| `input_of_EXPONENT` | count |
|---------------------|-------|
| 32	| 2442255 |
| 3	| 4771 |
| 1	| 159 |
| 128	| 29 |
| 0	| 13 |
| 5	| 2 |

#### Modulo length occurrences

| `input_of_MODULUS` | count |
|--------------------|-------|
| 32	| 2439594 |
| 128	| 4167 |
| 256	| 2968 |
| 160	| 436 |
| 512	| 38 |
| 0	| 13 |
| 64	| 8 |
| 78	| 2 |
| 129	| 1 |
| 384	| 1 |
| 257	| 1 |

This shows that no past successful use case exceeded an input length of 513 bytes, and the majority uses 32/128/256 byte inputs.

Besides these, there were a few invocations with invalid inputs:

- Empty inputs
- Inputs consisting of only `0x9e5faafc` or `0x85474728`
- A large, but invalid input: `0x9e281a98000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021e19e0c9bab2400000`

## Backwards Compatibility

This is a backwards incompatible change. However, based on analysis until block 21550926 (see above), no past transaction would have behaved differently after this change.

## Security Considerations

Since only the accepted input range is reduced, no new security surface area is expected.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 11 Nov 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7823</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7823</guid>
      </item>
    
      <item>
        <title>Transaction Gas Limit Cap</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7825-transaction-gas-limit-cap/21848</comments>
        
        <description>## Abstract

This proposal introduces a protocol-level cap on the maximum gas usage per transaction to 16,777,216 (2^24) gas. By implementing this limit, Ethereum can enhance its resilience against certain DoS vectors, improve network stability, and provide more predictability to transaction processing costs, especially in the context of increasing the gas limit.

## Motivation

Currently, transactions can theoretically consume up to the entire block gas limit, which poses several risks:

1. **DoS Attacks**: A single transaction consuming most or all of the block gas can result in uneven load distribution and impact network stability.  
2. **State Bloat Risks**: High-gas transactions often result in larger state changes, increasing the burden on nodes and exacerbating the Ethereum state growth problem.  
3. **Validation Overhead**: High-gas transactions can lead to longer block verification times, negatively impacting user experience and network decentralization.

By limiting individual transactions to a maximum of 16,777,216 gas, we aim to:

- Reduce the risks of single-transaction DoS attacks.  
- Promote fairer gas allocation across transactions within a block.  
- Ensure better synchronization among nodes by mitigating extreme block validation times.

## Specification

### Gas Cap

- Enforce a protocol-level maximum of **16,777,216 gas (2^24)** for any single transaction.  
- This cap applies regardless of the block gas limit set by miners or validators.  
- Transactions specifying gas limits higher than 16,777,216 gas will be rejected with an appropriate error code (e.g., `MAX_GAS_LIMIT_EXCEEDED`).  

### Changes to EVM Behavior

1. **Txpool Validation**: During transaction validation, if the `gasLimit` specified by the sender exceeds 16,777,216, the transaction is invalidated (not included in the txpool). 
2. **Block Validation**: As part of block validation before processing, any block having a transaction with `gasLimit` &gt; 16,777,216 is deemed invalid and rejected.

### Protocol Adjustment

- The `GAS_LIMIT` parameter for transactions will be capped in client implementations at 16,777,216.  
- This cap is **independent** of the block gas limit, which exceeds this value.  

## Rationale

### Why 16,777,216 (2^24)?

The proposed cap of 16,777,216 gas (2^24) provides a clean power-of-two boundary that simplifies implementation while still being large enough to accommodate most complex transactions, including contract deployments and advanced DeFi interactions. This value represents approximately half of typical block sizes (30-40 million gas), ensuring multiple transactions can fit within each block.

### Compatibility with Current Gas Dynamics

- **Backward Compatibility**: Transactions with gas usage below 16,777,216 remain unaffected. Existing tooling and dApps need only minor updates to enforce the new cap.
- **Impact on Validators**: Validators can continue to process blocks with a gas limit exceeding 16,777,216, provided individual transactions adhere to the cap.

## Backwards Compatibility

This change is **not backward-compatible** with transactions that specify gas limits exceeding 16,777,216. Transactions with such high limits will need to be split into smaller operations. This adjustment is expected to impact a minimal number of users and dApps, as most transactions today fall well below the proposed cap.

An [empirical analysis](/EIPs/assets/eip-7825/analysis) has been conducted to assess the potential impact of this change.

## Security Considerations

1. **DoS Mitigation**: A fixed cap reduces the risk of DoS attacks caused by excessively high-gas transactions.  
2. **Block Verification Stability**: By capping individual transactions, the validation of blocks becomes more predictable and uniform.  
3. **Edge Cases**: Certain highly complex transactions, such as large contract deployments, may require re-architecting to fit within the 16,777,216 gas cap.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).  
</description>
        <pubDate>Sat, 23 Nov 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7825</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7825</guid>
      </item>
    
      <item>
        <title>JSON Contract with Value Version Control</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7827-json-smart-contract-with-value-version-control/21865</comments>
        
        <description>## Abstract
This EIP defines a smart contract interface that allows for managing a JSON object within a smart contract, offering both real-time JSON output and a version-controlled history for each value. The interface includes methods to retrieve the most recent JSON state as well as the version history of each key in the JSON object. This approach supports REST developers familiar with JSON-based data interactions, thus improving accessibility for developers new to Web3 and Ethereum.

## Motivation
With an increasing number of developers from RESTful backgrounds joining the Ethereum ecosystem, there is a need for a contract interface that allows developers to easily interact with structured JSON data. This EIP aims to create a universal standard that provides JSON data management and version control functionality in a straightforward and REST-like way, making Ethereum more accessible and developer-friendly.

## Specification
The contract interface includes the following methods:

### Read Methods

1. **`json()`**  
   - **Output:** `string` (a JSON string representing the entire object)  
   - **Description:** Returns the current state of the JSON object as a string.

2. **`version(string key)`**  
   - **Inputs:**  
     - `key` (`string`): The JSON key whose version history is requested.  
   - **Output:** `string` (a JSON array as a string)  
   - **Description:** Returns an array of all versions of the specified key&apos;s value in JSON format. The array is ordered chronologically, with the earliest version at index 0 and the most recent version at the highest index.

### Write Method

3. **`write(string[] keys, string[] values, bool replace)`**  
   - **Inputs:**  
     - `keys` (`string[]`): Array of keys to be added or updated in the JSON object.  
     - `values` (`string[]`): Array of values corresponding to the keys.  
     - `replace` (`bool`): If `true`, replaces existing values; if `false`, reverts if the key already exists.  
   - **Output:** None  
   - **Description:** Writes new values to the JSON object, either adding a new key or updating an existing one, based on the `replace` parameter.

### Solidity Interface (non-normative)

```solidity
interface IERC7827 {
    function json() external view returns (string memory);
    function version(string calldata key) external view returns (string memory);
    function write(
        string[] calldata keys,
        string[] calldata values,
        bool replace
    ) external;
}
```

### Examples (non-normative)

Assume the following scenario with key-value management:

1. **Initial Write:**
```solidity
write([&quot;name&quot;], [&quot;Alice&quot;], false);
```
- JSON Output:
```json
{ &quot;name&quot;: &quot;Alice&quot; }
```
- Version History of `name`:
```json
[&quot;Alice&quot;]
```

2. **Updating Value with Replacement:**
```solidity
write([&quot;name&quot;], [&quot;Bob&quot;], true);
```
- JSON Output:
```json
{ &quot;name&quot;: &quot;Bob&quot; }
```
- Version History of `name`:
```json
[&quot;Alice&quot;, &quot;Bob&quot;]
```

3. **Attempting to Update without Replacement (reverts if `name` exists):**
```solidity
write([&quot;name&quot;], [&quot;Charlie&quot;], false);
```
- This transaction reverts because `name` already exists and `replace` is `false`.

## Rationale

1. **REST-like Access via JSON Method**  
   The `json` method enables developers to interact with the contract as if it were a RESTful API, improving accessibility for those familiar with traditional web development paradigms.

2. **Version Management via Version Method**  
   The `version` method provides a straightforward version control system for each key, offering a history of values that developers can reference without altering the main JSON structure. This maintains immutability for historical values while allowing updates to be appended.

3. **Compatibility with Web3 Abstractions**  
   Ensuring a simple and standardized ABI is essential for usability with Web3 libraries, thus enhancing developer experience and facilitating onboarding.

## Backwards Compatibility
This EIP is a new standard and does not interfere with existing standards. However, it introduces JSON object handling and version control, which may have specific considerations for gas optimization.

## Security Considerations
- JSON encoding onchain is inherently gas-heavy. This standard limits complexity by treating values as strings and leaving encoding efficiency to client libraries.  
- Contracts **SHOULD** guard against unbounded array writes, which could otherwise make the `write` method expensive or DOS-prone.  
- Care should be taken to handle large JSON objects efficiently to avoid excessive gas consumption.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 07 Nov 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7827</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7827</guid>
      </item>
    
      <item>
        <title>Interoperable Names</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7828-chain-specific-addresses-using-ens/21930</comments>
        
        <description>## Abstract

This proposal defines an Interoperable Name, a chain-specific address format with the structure `&lt;address&gt;@&lt;chain&gt;#&lt;checksum&gt;`.

The `&lt;address&gt;` can be an address, or an ENS name.

The `&lt;chain&gt;` can be a [CAIP-350] chain identifier, or it can be a human-readable label. This specification defines how such labels can be resolved to chain-specific metadata, via the Ethereum Name Service (ENS).

The optional `&lt;checksum&gt;` allows clients to verify the integrity of the Interoperable Name.

The result is chain-specific addresses such as:

- `0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7@eip155:1#80B12379`
- `alice.eth@eip155:1`
- `alice.eth@ethereum`

## Motivation

The current Ethereum address landscape is evolving toward an ecosystem with hundreds, and eventually thousands, of L2s that share the same address format as Ethereum mainnet. This means an address by itself is insufficient to determine which chain it is associated with. This ambiguity can result in funds being sent to an unreachable address on the wrong chain.

[ERC-7930] introduced a binary format for representing a _target address_ on a specific blockchain. While this binary data is well suited for low-level usage (e.g. in smart contracts), its meaning is semantically opaque to human users.

The core motivation for introducing the _Interoperable Name_ standard is to provide maximally readable, _chain-specific addresses_ for user-facing interactions.

A foundational text representation (e.g. `0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7@eip155:1`) enables a significantly more readable _chain-specific address_ format. An expanded form that leverages the name resolution capabilities of the Ethereum Name Service (ENS) further improves readability, allowing addresses to be expressed in a maximally human-friendly form (e.g. `wallet.ensdao.eth@ethereum`).

An on-chain registry provides a canonical source of truth for mapping human-readable chain labels to the metadata associated with each chain. Today, chains are identified using a variety of specifications (e.g. [CAIP-2] and [EIP-155] for EVM-compatible networks), whose formats are not necessarily semantically clear to human users. By introducing an on-chain registry, applications can refer to a chain using a readable identifier such as `base`, rather than an opaque identifier like `eip155:8453` or `8453`.

Historically, the mapping from chain names to identifiers has, since [EIP-155], been maintained off-chain using a centralized list.

This approach has several shortcomings:
- It does not scale with the growing number of blockchains
- It relies on a trusted centralized maintainer
- It does not support non-EVM chains

This specification defines an architecture that enables chain operators to take ownership of their chain-specific data, thereby reducing reliance on a single centralized entity and ensuring data integrity.

## Specification

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

### Terminology

This section builds upon the Terminology defined in [ERC-7930].

**Interoperable Name**
: A human-readable _chain-specific address_ format meant to be used by humans for user-facing interactions. e.g. `0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045@eip155:1#4CA88C9C`

### Interoperable Name Definition

The format of an _Interoperable Name_ is `&lt;address&gt;@&lt;chain&gt;#&lt;checksum&gt;` where the components match the following regular expressions:

#### Syntax
```bnf
&lt;interoperable-name&gt;  ::= &lt;address&gt; &quot;@&quot; &lt;chain&gt; [ &quot;#&quot; &lt;checksum&gt; ]
&lt;address&gt;             ::= [.-:_%a-zA-Z0-9]*
&lt;chain&gt;               ::= [.-:_a-zA-Z0-9]*
&lt;checksum&gt;            ::= [0-9A-F]{8}
```

These components have the following meanings:

- `&lt;address&gt;` can either be:

    - A _target address_ as defined in [ERC-7930].
    - An Ethereum Name Service (ENS) name. e.g., `wallet.ensdao.eth`

- `&lt;chain&gt;` can either be:

    - The string representation of a specific blockchain as defined in [CAIP-350]. For example `eip155:1` for Ethereum Mainnet, or `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d` for Solana Mainnet.
    - A human-readable label identifier for a specific chain, defined and registered as a subdomain of the `on.eth` ENS name. An on-chain resolver contract maps these labels to their corresponding canonical [ERC-7930] chain identifiers, and exposes additional chain metadata.

- `&lt;checksum&gt;` is defined as the first 4 bytes (8 characters) of the Keccak-256 hash, represented as a hexadecimal string (Base16, as specified in [RFC 4648]). The hash is computed over the concatenation of the following binary fields from the canonical [ERC-7930] Interoperable Address:

    - `ChainType`   
    - `ChainReferenceLength`
    - `ChainReference`
    - `AddressLength`
    - `Address`

**Note:** The Version field MUST NOT be included in the hashed data.

#### Checksums

The checksum provides an optional integrity verification mechanism for Interoperable Names that include a raw target address.

- The checksum is OPTIONAL but RECOMMENDED when the &lt;address&gt; component represents a target address, as it helps mitigate homoglyph and spoofing attacks for chain-specific addresses.
- A checksum SHOULD NOT be included when the &lt;address&gt; component is an ENS name
- Clients MAY include or omit the checksum when displaying or sharing an _Interoperable Name_.
- Clients MAY accept _Interoperable Name_ inputs with or without a checksum.
- When a checksum is provided for a target address, clients MAY validate it by deriving the underlying _Interoperable Address_ and recalculating the checksum.

UI/UX developers are encouraged to determine the most appropriate way to warn users when a checksum does not match, when resolution fails, or any other scenario they deem necessary to ensure user safety and clarity.


#### Versioning

This specification does not define its own versioning mechanism.

Implementers SHOULD ensure they are up to date with the version of [ERC-7930] they are using. Refer to the versioning section of [ERC-7930] for detailed rules.

Implementations MUST maintain convertibility between _Interoperable Names_ and the corresponding [ERC-7930] _Interoperable Address_ binary format.

### _Target Address_ Examples

#### Ethereum Mainnet

The address `0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7` on Ethereum Mainnet could be represented as either of the following:

```
0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7@eip155:1#80B12379
0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7@ethereum#80B12379
```

**Note:** In the second example `ethereum` is the chain label for Ethereum Mainnet in the on-chain ENS resolver set for the `on.eth` namespace (see below).

#### Non-EVM chains

The address `bc1qwz2lhc40s8ty3l5jg3plpve3y3l82x9l42q7fk` on Bitcoin Mainnet could be represented as:

```
bc1qwz2lhc40s8ty3l5jg3plpve3y3l82x9l42q7fk@bip122:000000000019d6689c085ae165831e93#597D21A1
bc1qwz2lhc40s8ty3l5jg3plpve3y3l82x9l42q7fk@bitcoin#597D21A1
```

**Note:** In the second example `bitcoin` is the chain label for Bitcoin Mainnet in the on-chain ENS resolver set for the `on.eth` namespace (see below).

### ENS `&lt;address&gt;` Examples

ENS resolves addresses on a chain-specific basis, as outlined in ENSIP-9 and ENSIP-11.

**Note:** When the `&lt;address&gt;` component is an ENS name, a checksum SHOULD NOT be included (see Checksums above). The examples in this section therefore omit the optional `#&lt;checksum&gt;` suffix.

#### Ethereum Mainnet

Assuming that `wallet.ensdao.eth` resolves to `0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7` **for Ethereum Mainnet** either of the following could be used to represent the same _target address_:

```
wallet.ensdao.eth@eip155:1
wallet.ensdao.eth@ethereum
```

#### Non-EVM chains

Assuming that `wallet.ensdao.eth` resolves to `bc1qwz2lhc40s8ty3l5jg3plpve3y3l82x9l42q7fk` **for Bitcoin Mainnet** either of the following could be used to represent the same _target address_:

```
wallet.ensdao.eth@bip122:000000000019d6689c085ae165831e93
wallet.ensdao.eth@bitcoin
```

### Resolving the `&lt;chain&gt;` component

If the `&lt;chain&gt;` component of an _Interoperable Name_ does not contain a colon (`:`) it is interpreted as being a label under the `on.eth` ENS namespace.

The resolver for `on.eth` MUST implement ENSIP-24 - Arbitrary Data Resolution, and allow for the resolution of the [ERC-7930] _Interoperable Address_ for the specified chain label using the key, `interoperable-address`. For example if you resolve the `interoperable-address` data record for `ethereum.on.eth` the _Interoperable Address_ `0x00010000010100` SHOULD be returned.

The on-chain resolver for `on.eth` MAY implement aliasing so that multiple chain labels, such as `op.on.eth` and `optimism.on.eth`, resolve to the same underlying data. To ensure consistency and integrity, there must be a single canonical representation of this data.

A pseudocode implementation of this resolution is as follows:

```js
/**
 * Pseudocode to resolve the Interoperable Address associated with &apos;ethereum.on.eth&apos; 
 * Using ENSIP-24 and the data key &apos;interoperable-address&apos;
 */

// 1. Inputs
const domain = &quot;ethereum.on.eth&quot;;
const key = &quot;interoperable-address&quot;;

// 2. Derive the Node (Namehash)
const node = namehash(domain);

// 3. Locate the Resolver for the node
const registry = getContract(ENS_REGISTRY_ADDRESS);
const resolverAddress = registry.resolver(node);

// 4. Instantiate the Resolver
const resolver = getContract(resolverAddress);

// 5. Resolve the Interoperable Address
// ENSIP-24 Interface: data(bytes32 node, string key) -&gt; bytes
const rawData = resolver.data(node, key);
```

The resolver for `on.eth` MUST implement ENSIP-5 - Text Records, and allow for the resolution of text records for the `reverse.on.eth` namespace of the form `chain-label:` followed by the [ERC-7930] _Interoperable Address_ you are trying to discern the label for. For example, the _Interoperable Address_ representing Ethereum Mainnet is `0x00010000010100`. Resolution of the text record `chain-label:0x00010000010100` for the `reverse.on.eth` namespace SHOULD return `ethereum`.

While multiple labels - such as `op.on.eth` and `optimism.on.eth` — may resolve to the _Interoperable Address_ `0x00010000010a00`, the reverse resolution process will always return the canonical label: `optimism`.

A pseudocode implementation of this resolution is as follows:

```js
/**
 * Pseudocode to resolve a chain label from an ERC-7930 Interoperable Address
 * Using ENSIP-5, the namespace reverse.on.eth, and the text record key chain-label:0x00010000010a00
 */

// 1. Inputs
const interoperableAddress = &quot;0x00010000010a00&quot;;
const namespace = &quot;reverse.on.eth&quot;;

// 2. Construct the specific Text Record Key
// Format: &quot;chain-label:&quot; + [ERC-7930 Address]
const textKey = &quot;chain-label:&quot; + interoperableAddress;

// 3. Derive the Node (Namehash) for the reverse namespace
const node = namehash(namespace);

// 4. Locate the Resolver for &apos;reverse.on.eth&apos;
// As the resolver will be set on the second level domain `on.eth` consideration should be given to ENSIP-10
const registry = getContract(ENS_REGISTRY_ADDRESS);
const resolverAddress = registry.resolver(node);

// 5. Instantiate the Resolver
const resolver = getContract(resolverAddress);

// 6. Query the Text Record (ENSIP-5)
// Signature: text(bytes32 node, string key) -&gt; string
const chainLabel = resolver.text(node, textKey);
```

Additional implementation details about the resolver contract implementation can be discerned by referencing the ENS documentation, and viewing the verified source code of the contract set as the resolver for `on.eth`.


### Resolving the `&lt;address&gt;` component

If the `&lt;address&gt;` component contains a period (`.`), it is assumed to be an ENS name. Because ENS fully integrates with the Domain Name System (DNS), any traditional domain name can function as an ENS name, as can any name using the blockchain-native `.eth` extension.

If an ENS address is used within the `&lt;address&gt;` component, it MUST be resolved subject to the ENS resolution specifications, giving consideration to the target chain specified in the `&lt;chain&gt;` component.

The specifications of note are ENSIP-9: Multichain address resolution, ENSIP-10: Wildcard resolution, and ENSIP-11: EVM compatible Chain Address Resolution. These specifications outline how one resolves an ENS name to discern the address **for a specific chain**. Consideration MUST be given to both current and future ENSIPs pertaining to address resolution.

If a _target address_ has been used for the `&lt;address&gt;` component (or once the ENS name has been resolved to a _target address_) it should be serialized subject to the rules defined in the relevant [CAIP-350] profile for the given `&lt;chain&gt;`. This ensures that different valid text representations (e.g., case variations in an address) resolve to a single, canonical binary form, which is essential for consistent checksum calculation and data integrity.

## Rationale

- The Ethereum Name Service (ENS) is a well-established blockchain identity primitive that enables the registration of human-readable names (e.g. example.eth, wallet.ensdao.eth) which resolve to addresses on a chain-specific basis. ENS is widely used, familiar to users, and well understood by implementers.
- For flexibility and backwards compatibility, this specification allows a raw target address to be used in the `&lt;address&gt;` component, accommodating users and applications that prefer traditional address representations.
- In this specification, checksums are defined as OPTIONAL. While they provide meaningful integrity guarantees for raw, chain-specific target addresses, their applicability to ENS-based names is limited. ENS names may resolve to different addresses over time depending on resolver behavior, which means that a previously generated checksum may no longer validate even when resolution is correct. In addition, when using ENS, users already delegate name normalization, resolution, and validation to ENS-specific mechanisms, so applying checksums in these cases provides limited additional security while increasing complexity and ambiguity for implementers. As a result, checksums are primarily intended to protect the integrity of raw, chain-specific addresses, while remaining optional and flexible for user-facing applications.
- The [ERC-7930] Version field is excluded from checksum calculation to allow the same Interoperable Name to remain valid across version upgrades of the binary format.

## Security Considerations

- Implementers MUST give consideration to the name normalization specifications of the Ethereum Name Service so as to avoid homoglyph or spoofing attacks. These are outlined in ENSIP-1 and ENSIP-15.
- Users should stay vigilant of address poisoning attacks when using a raw _target address_ in the `&lt;address&gt;` component.
- ENS resolution depends on resolver contracts set for each name. Resolvers may change over time, and wildcard resolvers (ENSIP-10) may return dynamic data.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).


[BIP 44]: https://github.com/bitcoin/bips/blob/1d371a58978fd2f313c9d162762de04d3b697bf5/bip-0044.mediawiki

[EIP-155]: /EIPs/EIPS/eip-155

[ERC-7930]: /EIPs/EIPS/eip-7930
[CAIP-2]: https://github.com/ChainAgnostic/CAIPs/blob/36ef9ee906da090366cb679634a0850e91785db6/CAIPs/caip-2.md
[CAIP-350]: https://github.com/ChainAgnostic/CAIPs/blob/29762ef99a6ffea1e07e3f796c0d1a5a95e89b88/CAIPs/caip-350.md
[RFC 4648]: https://www.rfc-editor.org/rfc/rfc4648
[ENSIP-1]: https://docs.ens.domains/ensip/1/
[ENSIP-5]: https://docs.ens.domains/ensip/5/
[ENSIP-9]: https://docs.ens.domains/ensip/9/
[ENSIP-10]: https://docs.ens.domains/ensip/10/
[ENSIP-11]: https://docs.ens.domains/ensip/11/
[ENSIP-15]: https://docs.ens.domains/ensip/15/
[ENSIP-24]: https://docs.ens.domains/ensip/24/
</description>
        <pubDate>Wed, 27 Nov 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7828</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7828</guid>
      </item>
    
      <item>
        <title>Data Asset NFT</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7829-data-asset-nft/21881</comments>
        
        <description>## Abstract

This proposal extends the [ERC-721](/EIPs/EIPS/eip-721) standard to support Data Assets which refers to digital products created by creators.

This proposal introduces a modular Data Availability (DA) layer that safeguards on-chain data integrity, preventing value discrepancies caused by off-chain data loss, tampering, or expiration. Furthermore, this proposal introduces a new role, Reader, where a single token can have multiple Readers. This solution reflects the inherent replicability of Data Assets, namely that each piece of data can be replicated multiple times and accessed by multiple users, thus amplifying the value of the Data Assets.

## Motivation

ERC-721 proposed NFTs to represent the ownership of digital or physical assets. Currently, the NFT metadata is considered the NFT content, and its scarcity determines the value of the NFT. NFT owners can convert the content value of NFTs into revenue by transferring the ownership of NFTs. However, due to the high transaction fees, storage costs, and other expenses, NFTs are currently only able to represent the ownership of high-value assets, which limits the range of assets that NFTs can represent. This is especially true for Data Assets, which refers to digital products created by creators, such as online blogs, videos, small games or music. Therefore, the value of Data Assets depends on their quality, whether the creator is famous, whether it is hyped and so on.

Furthermore, to reduce storage costs, the NFT content is generally stored off-chain or using cross-chain storage, and the link of NFT content is saved on-chain. Off-chain users can access the NFT content by visiting the link. However, on-chain contracts can not access the link to determine the status of the data, such as data loss, data tampering, or data expiration. These situations can lead to the data deviating from its actual value, but the NFT still exists on the chain, and the underlying copyright is still being sold in the market.

This proposal introduces Data Asset NFTs, which solve the dilemma of on-chain Data Assets by combining a modular data layer--Data Availability (DA).

### Related Work

There are Existing proposals to NFT integrity, but each proposal contains at least one of these limitations:

- Storing NFT content on-chain, which requires the underlying data asset to possess inherent speculative value to justify prohibitive storage costs.
- Requiring attestations from a trusted third party, while introduces centralized trust issue.

## Specification

### Terms

In this proposal, we divide data assets into three parts:

- Storage Metadata: Includes commitment, size, expire, and uploader&apos;s address. Stored and maintained by storage contracts on the blockchain.
- Permission Metadata: Includes information on ownership and reading rights, as well as which addresses can modify this information. Stored and maintained by permission contracts on the blockchain.
- Data Content: Data uploaded by users to the storage system. Data content is stored in off-chain storage nodes.

**Every compliant data permission contract must implement the Interface**:

The data permission contract is an extension of ERC-721, adding the reader role, where a single data asset can correspond to multiple readers.

```solidity
interface IERC7829 is IERC721 {
    event UpdateReader(uint256 indexed tokenId, address indexed reader, bool valid);
    
    function setReader(uint256 tokenId, address reader, bool valid) external;
    
    function isReader(uint256 tokenId, address reader) external view returns (bool);
    
    function commitByTokenId(uint256 tokenId) external view returns (bytes);
    
    function sizeByTokenId(uint256 tokenId) external view returns (uint256);
    
    function expireByTokenId(uint256 tokenId) external view returns (uint64);
}
```

The metadata JSON schema for Data Asset NFTs is as follows:

```json
{
  &quot;title&quot;: &quot;Data Asset Metadata&quot;,
  &quot;type&quot;: &quot;object&quot;,
  &quot;properties&quot;: {
    &quot;name&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Identifies the asset to which this NFT represents&quot;
    },
    &quot;description&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Describes the asset to which this NFT represents&quot;
    },
    &quot;commit&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;A commit pointing to the data resource&quot;
    },
    &quot;size&quot;: {
        &quot;type&quot;: &quot;integer&quot;,
        &quot;description&quot;: &quot;The size of the data resource&quot;
    },
    &quot;expire&quot;: {
        &quot;type&quot;: &quot;integer&quot;,
        &quot;description&quot;: &quot;The expire time of the data resource&quot;,
    }
  }
}
```

The Reader role should not involve changes in permissions, meaning that Readers cannot call functions such as `transfer`, `approve`, `setApprovalForAll`, and `setReader`.

When Alice calls the `transfer` function to transfer one of Alice&apos;s Data Asset NFTs to Bob:

- The owner address is set to Bob&apos;s address;
- The approved address is set to 0.
- However, all readers are retained.

### Extension: Storage Contract

This proposal extends the metadata information of NFTs. Metadata information is uploaded by users and requires relevant certificates, which can be the storage node&apos;s signature on the NFT&apos;s metadata information. This proposal specify that the NFT metadata should at least include commitment, size, expire, and uploader&apos;s address.

The implementer of this proposal selects a trusted storage system and a trusted modular data layer DA, or deploys the modular storage layer DA themselves.

When the Owner or Approved Operator calls the `transfer`, `approve`, or `setReader` functions, they must additionally check whether the current time `block.timestamp` is greater than the expiration time `expire` before making the call. If the current time `block.timestamp` is less than the expiration time `expire`, then proceed with subsequent operations; if the current time `block.timestamp` is greater than the expiration time `expire`, then interrupt subsequent operations and return an exception message.

### Extension: Storage Proof

This proposal uses storage proof to prove the availability of data content, thereby proving the correctness of NFT metadata, especially the `expire` of the NFT.

This proposal does not limit the proof scheme used, but recommends the use of KZG polynomial commitment technology. KZG polynomial commitment technology can generate two generator elements $g_1$ and $g_2$ during initialization. It also generates a corresponding commitment C based on the data content and uploads it as the unique identifier of the data when uploading metadata. When generating proof, the verifier generates a random number $z$, and the prover generates proof $P=(y, π)$ based on the data content and random number $z$, verifying $e(π, yg_1-zg_2) = e(C - y*g_1, g_2)$.

In addition, KZG polynomial commitment technology can aggregate multiple proofs into a single proof, and two-step verification can verify the correctness of all proofs, including summing all commitments to get the aggregated commitment $C_n$, and verifying the aggregated proof $P_n=(y_n, π_n)$ by verifying $e(π_n, y_ng_1-zg_2) = e(C_n - y_n*g_1, g_2)$.

To avoid long proof generation times, random sampling can be used to randomly select data to be challenged. Therefore, the contract needs to provide a secure pseudo-random number generation function for randomly selecting challenged data, which can also be used as the random number $z$ for KZG.

During the verification process, summing all commitments to get the aggregated commitment requires a large amount of gas fees. This proposal recommends using optimistic proof, which assumes that the aggregated commitment is correct and only verifies $e(π_n, y_ng_1-zg_2) = e(C_n - y_n*g_1, g_2)$ during verification. After verifying the aggregated proof, the availability of the data cannot be proven, so a certain period of challenging is required. During the challenging period, anyone can challenge the commitment proof $C_n$. If the challenge is successful, the challenger gets a reward and the prover is punished; if the challenge fails, the challenger is punished and the prover gets additional benefits.

## Rationale

![arc](/EIPs/assets/eip-7829/architect.svg)

### Data Asset NFT Integrity

The DA Layer is responsible for off-chain storage of Data Content and on-chain storage of Storage Metadata, and ensures the integrity of Data Assets through periodically submiting and verifing **storage proofs**.

To optimize gas costs, we adopt an **optimistic proof approach**, significantly reducing verification expenses.

**Proof Cycle Workflow**:

1. **Proof Generation &amp; Aggregation**:
   - The **DA Provider** generates storage proofs for sampled data content, aggregates them into a single **aggregated proof**, and submits it to the **DA Contract**.
   - The **DA Contract** verifies the correctness of the aggregated proof.
2. **Fraud Proof Mechanism**:
   - The **DA Verifier** performs off-chain validation to confirm whether the aggregated proof was correctly derived from the selected data.
   - If the proof is invalid, the verifier **challenges** it by submitting a fraud proof to the DA Contract.

### Reader

This proposal enables a **single data asset NFT** to have **multiple Readers**, each granted access to the off-chain data content. This design aligns with the inherent properties of data assets:

- **Replicability**: Data can be copied and distributed without degradation.
- **Value Amplification**: By allowing resale or multi-party access, the asset’s utility and market value increase.

## Backwards Compatibility

This proposal combines the existing ERC-721 extension and is backward compatible with the ERC-721 standard.

## Security Considerations

The security of Data Asset NFTs depends not only on the blockchain but also on the modular data layer DA. Therefore, the implementer of this proposal needs to carefully select the modular data layer DA.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 29 Nov 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7829</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7829</guid>
      </item>
    
      <item>
        <title>Contract size limit increase for EOF</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7830-contract-size-limit-increase-for-eof/21927</comments>
        
        <description>## Abstract

Revise the contract size limit for EOF contracts to be 64 KiB instead of the existing 24 KiB limit. Legacy contracts are unaffected.

## Motivation

The contract size limit was introduced as a measure against DoS attacks. `JUMPDEST`-analysis is required for legacy contracts, and many of the algorithms performing it are not linear and/or have unknown unknowns. This is one of the reasons for the hesitance of a limit increase.

For contract developers the limit poses annoying problems, given modern contracts with good error reporting would consume more space. They are forced to work with workarounds, like &quot;libraries&quot; (using `DELEGATECALL`), splitting an application across regular contracts (and `CALL`-ing across), or working with proxies (e.g. the &quot;diamond pattern&quot;). All these solutions have resulted in suboptimal patterns, bugs in deployed contracts, and loss of funds.

With EOF the `JUMPDEST`-analysis is removed from runtime and a validation process is performed once during deployment. The initcode cost [EIP-3860](/EIPs/EIPS/eip-3860) introduced accounts for this validation too. Therefore, with EOF there are no known problems for increasing the limit, because the overheads are already accounted for.

Storage cost is already paid per contract byte.

## Specification

[EIP-170](/EIPs/EIPS/eip-170) specifies `MAX_CODE_SIZE` as 24576 bytes, and [EIP-3860](/EIPs/EIPS/eip-3860) specifies `MAX_INITCODE_SIZE` as `2 * MAX_CODE_SIZE` (49152 bytes).

Starting `FORK_BLOCK`, for EOF initcode/code (code starting with the `0xEF 0x00` bytes) the limit is changed:`MAX_CODE_SIZE` is set to 65536 bytes (64 KiB). This means `MAX_INITCODE_SIZE` becomes 131072 bytes (128 KiB).

## Rationale

The 64 KiB limit is over 2x of existing limit, while it is not a significant increase, it is the realistic increase given the limitations of initcode. In EOF deployment the to-be-deployed code is stored as a section (&quot;subcontainer&quot;), which has a size limit of 64 KiB, therefore it is not possible to deploy larger contracts without introducing a large or variable-length-encoded size field.

A further increase can be proposed with applying these changes to EOF.

This increase still fits within the gas schedule, limiting the size to less than what gas limits allow.  In [EIP-170](/EIPs/EIPS/eip-170) the gas limit was first set &quot;by setting the cap at a value slightly higher than what is feasible with current gas limits.&quot; At that time the gas limit had not exceeded 5M gas.

A simple analysis shows contract deployments for 64 KiB contracts to be between 14M and 16M gas, roughly close to the current 15M target.

|                     |    Cancun |   This EIP |    36M Gas | Max Initcode |
|---------------------|----------:|-----------:|-----------:|-------------:|
| **Initcode bytes**  |       200 |        200 |        200 |       65,536 |
| **Deployed Bytes**  |    24,576 |     65,536 |    165,331 |       65,536 |
| **Zero byte ratio** |       10% |        10% |        10% |          10% |
| **Initcode Cost**   |      4/16 |       4/16 |       4/16 |         4/16 |
|                     |           |            |            |              |
| **Intrinsic Gas**   |    53,000 |     53,000 |     53,000 |       53,000 |
| **Calldata Gas**    |   366,685 |    972,893 |  2,449,859 |    1,939,866 |
| **EIP-3860 Gas**    |    49,552 |    131,472 |    331,062 |      262,144 |
| **EVM Execution**   |   100,000 |    100,000 |    100,000 |      100,000 |
| **Code Deposit**    | 4,915,200 | 13,107,200 | 33,066,200 |   13,107,200 |
|                     |           |            |            |              |
| **Total Cost**      | 5,484,437 | 14,364,565 | 36,000,121 |   15,462,210 |

Note that the Max 30M gas contract size of 135 KiB is outside the limits of what is proposed in this EIP and is included to show what it would take to exceed current gas limits.

## Backwards Compatibility

This is a backwards compatible change. Existing contracts are unaffected, and only new deployments see the effect.

## Security Considerations

Given the analysis cost is paid as part of deployment, the size of contract should have no effect on the runtime.

A more thorough analysis may be needed to determine whether the proposed limit poses any risk because of client storage architectures.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 29 Nov 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7830</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7830</guid>
      </item>
    
      <item>
        <title>Multi-Chain Addressing</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7831-multi-chain-addressing/21942</comments>
        
        <description>## Abstract

This proposal introduces a chain-specific address format that allows specifying both an account and the chain on which that account intends to transact. These chain-specific addresses take the form of `(example.eth:optimism)`, `6A10161835a36302BfD39bDA9B44f5734442234e:ethereum:11155111`, and so on. The target chain is resolved using a registry stored on ENS.

## Motivation

The Ethereum ecosystem is becoming steadily more fragmented. This means a 20 byte address by itself is not enough information to fully specify an account. This can be problematic if funds are sent to an unreachable address on the incorrect chain.

Instead of using chain identifiers, which are not human readable, the address could be extended with a human-readable chain name, which can then be resolved to a chain identifier. The mapping from chain names to identifiers has, since [EIP-155], been maintained off chain using a centralized list. This solution has two main shortcomings:

 - It does not scale with the growing number of L2s.
 - The list maintainer is a trusted centralized entity.

This ERC proposes the use of ENS to map chain names to identifiers, while still allowing maximum flexibility by changing the root chain.

### Why not ENS with [ERC-2304]?

While [ERC-2304] allows registrants to specify per-chain addresses, it does not provide a default chain to receive assets on (nor should it.) The choice of receiving chain depends too much on off-chain factors to require a transaction to change.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119] and [RFC 8174].

Grammar snippets in this proposal are given in Augmented Backus-Naur form (ABNF) as defined in [RFC 5234] and [RFC 7405].

### Definitions

The following terms are used throughout this proposal:

 - **agent** - software/tool responsible for resolving a chain-specific address to its exact account and chain.
 - **bridge** - contract that connects the root chain to the target chain (eg. to transfer tokens, proxy function calls.)
 - **root chain** - blockchain containing bridge and name resolver contracts.
 - **target chain** - blockchain where the identified account intends to transact; can be any chain with a bridge on the root chain.

### Syntax

At a high level, a chain-specific address is made of three components separated by colons (`:`) ordered from most general on the right to most specific on the left:

 - a `local-part`, that identifies the account on the target chain;
 - a `chain-part`, that identifies the target chain; and
 - _optionally_, a `root-part` that identifies the root chain.

These components may be enclosed by parentheses (`(` and `)`) to resolve parsing ambiguities.

More formally, valid chain-specific addresses MUST adhere to the following grammar:

```abnf
address         = OPEN bare-address CLOSE /
                  bare-address

bare-address    = local-part SEP chain-part [SEP root-part]

OPEN            = &apos;(&apos;
CLOSE           = &apos;)&apos;
SEP             = &apos;:&apos;
```

#### Local Part

The `local-part` is the most specific section of a chain-specific address. It identifies the account on the target chain. It can be either a hexadecimal string (`hex-address`) or an ENS-like name (`ens-like`).

Valid `local-part` fragments MUST match the following grammar:

```abnf
local-part      = hex-address /
                  ens-like
```

##### Hexadecimal Address

When `local-part` is a hexadecimal string, it MUST include checksum letter casing (see [Checksum](#checksum)), and it MAY omit leading zeros. It MUST NOT include a leading `0x` prefix.

Note that `local-part` may encode an address longer or shorter than 20 bytes (40 hexadecimal digits.) Implementations MUST support `local-part` lengths of 1 hexadecimal digit up to 40 digits. Implementations SHOULD support arbitrarily sized (within some reasonable limit) `local-part` components.

Formally, `hex-address` MUST match the following grammar:

```abnf
hex-address     = 1*HEXDIG
```

##### ENS-Like Names

To disambiguate an ENS name from a hexadecimal string—and unlike standard ENS names—names used in the `local-part` of a chain-specific address MUST contain at least one dot (`.`). If present, a dot placed at the rightmost position (eg. `eth.` or `example.eth.`) SHALL be removed before resolving the name. Chain-specific addresses SHOULD NOT contain a dot in the rightmost position unless no other dot is present.

The following grammar is illustrative only. See [ERC-137] for the definition of an ENS name.

```abnf
; Rough approximation of ENS names, with the additional requirement that it
; contain at least one &quot;.&quot;
ens-like        = 1*NOTSEP DOT *(1*NOTSEP [DOT])

NOTSEP          = %x01-39 / %x3b-ff
```

#### Chain Part

The `chain-part` identifies the target chain. It MUST be a valid ENS name as defined in [ERC-137].

The following grammar is illustrative only. See [ERC-137] for the definition of an ENS name.

```abnf
chain-part      = ens-name

; Rough approximation of ENS names, with no additional requirements
ens-name        = 1*NOTSEP
```

#### Root Part

The `root-part` identifies the root chain against which other names are resolved. When present, the `root-part` SHALL be the [EIP-155] `chainid` of the root chain in decimal format. `root-part` SHOULD NOT be present when `chainid == 1`, and MUST be present when `chainid != 1`.

```abnf
root-part = 1*DIGIT
```

### Resolution

Resolving a chain-specific address begins on the right, and moves leftward.

#### Root Chain

If `root-part` is not present, assume it is `1`. Set the root&apos;s `chainid` to the value of `root-part`. The agent MUST be able to resolve ENS names against this chain. This likely means it has RPC access and a known ENS Resolver address, but any method of resolving addresses is sufficient.

Note that this makes `example.eth:optimism` distinct from `example.eth:optimism:10`. In the former case, both `example.eth` and `optimism` are resolved using ENS deployed on mainnet. In the second case, the two names would be resolved against an ENS deployed on the Optimism chain—an unusual situation.

The assignment of chain identifiers is defined in [EIP-155].

#### Target Chain

Next, construct an ENS name for the target chain by concatenating the value of `chain-part` with `.tbd.eth` &lt;!-- TODO --&gt;(such that `example.eth:foobar` would have a target chain of `foobar.tbd.eth`&lt;!-- TODO --&gt;.) Resolve the target chain&apos;s address (i.e. with [ERC-137]&apos;s `addr`) against the ENS deployment on the root chain. The contract at this address is the &quot;bridge contract.&quot;

The agent has to verify that the bridge contract supports the `chain-part` in the address. First, the agent MUST call [ERC-165]&apos;s `supportsInterface` on the bridge contract using `ChainMetadata`&apos;s interface identifier (see [Bridge Interface](#bridge-interface)) and the agent SHALL fail resolution if it returns false. Next, the agent MUST call the bridge contract&apos;s `acceptsName` function with the same namehash (see [ERC-137]) used in the above call to `addr`. The agent SHALL fail resolution if `acceptsName` returns false.

A bridge contract SHALL provide functionality/metadata enabling the agent to interact with the target chain. Further, it SHALL support the [ERC-165] mechanism for interface discovery, and MAY support other methods to accomplish the same. Bridge contracts MUST implement `ChainMetadata` (see [Bridge Interface](#bridge-interface).) Further specifics of bridging are left for future proposals.

&lt;!-- TODO: Should we ensure that each chain id is one-to-one mapped to a name? --&gt;

#### Local Address

##### Hexadecimal

Verify the checksum (see [Checksum](#checksum).)

The local address is the hexadecimal encoding of the binary representation of the target chain&apos;s native address. For example, for the native Ethereum address `0x6A10161835a36302BfD39bDA9B44f5734442234e`, the local address would be `6A10161835a36302BfD39bDA9B44f5734442234e`.

##### ENS-Like

If the local address ends in a dot (`.`), remove it. Resolve the address using [ERC-2304]&apos;s `addr` against the ENS deployment on the root chain with a `coinType` derived from the `chainid` of the target chain (retrieved from the bridge contract.)

### Bridge Interface

Bridge contracts MUST implement the following interface:

```solidity
interface ChainMetadata {
    function chainId() external view returns (uint64);
    function coinType() external view returns (uint256);
    function acceptsName(bytes32 keccak) external view returns (bool);
}
```

When queried using [ERC-165]&apos;s `supportsInterface`, bridge contracts MUST return true for `0x00000000`&lt;!-- TODO --&gt;.

### Checksum

&lt;!-- TODO: Get someone smarter than me to verify that this is a reasonable extension of ERC-55 --&gt;

&lt;!-- TODO: Decide if we want ERC-1191. Would we use the root chain id, the target chain id, or even crazier—use the full chain-specific address as the input to the keccak? --&gt;

Hexadecimal strings are cased according to a slightly modified [ERC-55] algorithm. The algorithm is modified by wrapping `nibble_index` to fit within the keccak hash.

&lt;details&gt;
&lt;summary&gt;Python implementation of the modified ERC-55 algorithm&lt;/summary&gt;

```python
from Crypto.Hash import keccak  # from pycryptodome


def checksum_encode(addr):
    hex_addr = addr.hex()
    checksummed_buffer = &quot;&quot;

    # Treat the hex address as ascii/utf-8 for keccak256 hashing
    k = keccak.new(digest_bits=256)
    k.update(hex_addr.encode(&quot;utf-8&quot;))
    hashed_address = k.hexdigest()

    # Iterate over each character in the hex address
    for nibble_index, character in enumerate(hex_addr):

        if character in &quot;0123456789&quot;:
            # We can&apos;t upper-case the decimal digits
            checksummed_buffer += character
        elif character in &quot;abcdef&quot;:
            # Check if the corresponding hex digit (nibble) in the hash is 8 or higher
            nibble_index_wrapped = nibble_index % len(hashed_address)
            hashed_address_nibble = int(hashed_address[nibble_index_wrapped], 16)
            if hashed_address_nibble &gt; 7:
                checksummed_buffer += character.upper()
            else:
                checksummed_buffer += character
        else:
            raise Exception(
                f&quot;Unrecognized hex character {character!r} at position {nibble_index}&quot;
            )

    return &quot;0x&quot; + checksummed_buffer


def test(addr_str: str):
    padded_addr_str = addr_str.removeprefix(&quot;0x&quot;)
    if len(padded_addr_str) % 2 == 1:
        # Pad to an even number of nibbles.
        padded_addr_str = &quot;0&quot; + padded_addr_str

    addr_bytes = bytes.fromhex(padded_addr_str)
    checksum_encoded = checksum_encode(addr_bytes)
    if checksum_encoded != addr_str:
        print(f&quot;{checksum_encoded} != expected {addr_str}&quot;)


test(&quot;0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed&quot;)
test(&quot;0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359&quot;)
test(&quot;0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB&quot;)
test(&quot;0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb&quot;)
test(&quot;0x004f67dAbb603AAA58eD52641CCafF09C559704A&quot;)
test(&quot;0x4F67dABB603aAa58Ed52641cCAff09C559704A&quot;)
test(
    &quot;0x&quot;
    &quot;5aaeB6053f3e94c9B9a09f33669435E7&quot;
    &quot;ef1BEaED5AaEB6053f3e94C9B9a09F33&quot;
    &quot;669435e7ef1bEAed5aaEb6053f3e94C9&quot;
    &quot;b9a09f33669435E7ef1beAED5aaEB605&quot;
    &quot;3f3e94c9b9a09F33669435e7ef1beAED&quot;
)
```

&lt;/details&gt;

For example, these strings are correctly cased:

* `004f67dAbb603AAA58eD52641CCafF09C559704A`
*  `04f67dAbb603AAA58eD52641CCafF09C559704A`
*   `4F67dABB603aAa58Ed52641cCAff09C559704A`

[RFC 2119]: https://www.rfc-editor.org/rfc/rfc2119
[RFC 8174]: https://www.rfc-editor.org/rfc/rfc8174
[RFC 5234]: https://www.rfc-editor.org/rfc/rfc5234
[RFC 7405]: https://www.rfc-editor.org/rfc/rfc7405

[ERC-55]: /EIPs/EIPS/eip-55

[ERC-137]: /EIPs/EIPS/eip-137

[EIP-155]: /EIPs/EIPS/eip-155

[ERC-165]: /EIPs/EIPS/eip-165

[ERC-2304]: /EIPs/EIPS/eip-2304

## Rationale

### Component Order

The components are ordered from most specific to most general because... &lt;!-- TODO --&gt;

### Separator Choice

The colon (`:`) is a reasonable choice for separator because it is not an allowed character in ENS names, it is familiar (eg. IPv6), and isn&apos;t as overloaded as the `@` symbol.

#### Alternative: `@`

The `@` symbol is a common choice for addresses, and finds use in email and several federated communication protocols. The English reading (foo-**AT**-example-DOT-com) is natural and implies a hierarchy between the left and the right components.

Unfortunately, because the `@` symbol is so widely used, including it in a chain-specific address would make all those protocol identifiers more confusing (or even invalid.) For example, `foo@foo.eth@ethereum` is not a valid email address.

#### Alternative: `/`

&lt;!-- TODO --&gt;

### Target Chain as Subdomain

While it would be technically possible to resolve `chain-part` against a root ENS name (eg. `ethereum.eth` instead of `ethereum.tbd.eth`&lt;!-- TODO --&gt;), using a subdomain allows the pre-registration of well-known chain names for an initial distribution of names before switching to open registration.

Without such a pre-registration, an attacker could register well-known names before the legitimate project.

After the pre-registration period, open registration is acceptable because new chains can register their names before announcing publicly.

## Backwards Compatibility

It is always possible to determine whether a particular string is a chain-specific address, a plain address, or a plain ENS name. Because of this property, there is little opportunity for backwards incompatibility: chain-specific addresses are not valid legacy addresses or ENS names, so tools without support will simply reject them.

## Test Cases

&lt;!--
  -- TODO: Test Case Ideas
  --
  -- * Longer than 20-byte hex local-part
  --&gt;

### ENS Configuration

#### Mainnet (1)

| Name          | Coin Type       | Record                                       |
| ------------- | --------------- | -------------------------------------------- |
| `ethereum.tbd.eth`&lt;!-- TODO --&gt; | - | a bridge contract to mainnet (1)         |
| `rollup1.tbd.eth`&lt;!-- TODO --&gt;  | - | a bridge contract to rollup1 (1608)      |
| `example.eth`    | `2147483649` | `0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa` |
| `example.eth`    | `2147485256` | `0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB` |

#### Sepolia (11155111)

| Name | Coin Type | Record |
| ---- | --------- | ----- |
| `ethereum.tbd.eth`&lt;!-- TODO --&gt; | - | a bridge contract to sepolia (11155111)         |
| `example.eth` | &lt;!-- TODO --&gt; | &lt;!-- TODO --&gt; |

### Inputs &amp; Expected Outputs

#### Valid

| Input                    | Target Chain   | Local Address                                |
| ------------------------ | -------------- | -------------------------------------------- |
| `(example.eth:ethereum)` | mainnet (1)    | `0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa` |
| `example.eth:rollup1`    | rollup1 (1608) | `0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB` |
| `example.eth.:ethereum`  | mainnet (1)    | `0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa` |
| `0:ethereum`             | mainnet (1)    | `0x0000000000000000000000000000000000000000` |

#### Invalid

| Input                                                   | Failure Reason             |
| ------------------------------------------------------- | -------------------------- |
| `(0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa:ethereum)` | Invalid hexadecimal        |
| `(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:ethereum)`   | Invalid checksum           |
| `(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA:ethereum)`   | Invalid checksum           |
| `(eth:ethereum)`                                        | Invalid hexadecimal        |
| `(:ethereum)`                                           | Missing `local-part`       |

## Reference Implementation

&lt;!--
  This section is optional.

  The Reference Implementation section should include a minimal implementation that assists in understanding or implementing this specification. It should not include project build files. The reference implementation is not a replacement for the Specification section, and the proposal should still be understandable without it.
  If the reference implementation is too large to reasonably be included inline, then consider adding it as one or more files in `../assets/eip-####/`. External links will not be allowed.

  TODO: Remove this comment before submitting
--&gt;

## Security Considerations

### Unicode &amp; Typosquatting Attacks

An attacker could register ENS names that resemble well-known chain names. For example, `etherium` and `ehtereum` are reasonably close to `ethereum`. While many unicode homoglyphs are caught by ENS libraries, agents should still be aware of the risk they pose.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 30 Aug 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7831</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7831</guid>
      </item>
    
      <item>
        <title>Sustainable collaborative NFT collections</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7832-sustainable-nft-collections/22201</comments>
        
        <description>## Abstract  

This EIP proposes a standard for creating economically sustainable NFT governance for collections built on collaborative models based on [ERC-721](/EIPs/EIPS/eip-721). It introduces dynamic minting fees, role-based access control, and a donation-based engagement model to enhance creator-community interactions. These mechanisms aim to balance scarcity, incentivize meaningful participation, and ensure sustainable growth for both creators and contributors.

The model defines &quot;economically sustainable&quot; as tokens whose minting value, creator subscription fees, and token quantity within each progressive discount cycle can only be adjusted once every certain hours from the last update by an `ADMIN` user. These mechanisms prevent excessive administrative modifications that could disrupt market stability, ensuring consistent price discovery and maintaining participant confidence. By aligning incentives and fostering predictability, the model creates a robust framework for engagement and value creation.

### Motivation  


As the NFT market matures, one of the recurring challenges faced by both creators and users is the inflationary nature of supply and the lack of effective mechanisms to engage the community meaningfully. NFT collections built on collaborative models require governance systems that empower all stakeholders—creators, contributors, and collectors—while also maintaining long-term economic sustainability. The introduction of this proposal aims to solve these issues by fostering a more dynamic, flexible, and transparent system for NFT collections. This EIP addresses these gaps by introducing:  
- **Role-Based Access**: Empowering creators while ensuring transparent governance by admins.  
- **Dynamic Minting Fees**: To align token costs with user activity and ownership.  
- **Donation-Based Engagement**: Encouraging contributions to creators.  


## Specification  
The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

The following interface **MUST** be implemented.

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.20;


interface IERC7832 is IERC721 {
    
    // Events
    event CreatorTermsUpdated(
        uint256 mintBaseFee,
        uint256 creatorSignatureFee,
        uint256 maxMintsPerUserInCycle);

    event DonationReceived(address from, address to, uint256 amount);

    // Function to get the current token ID
    function currentTokenId() external view returns (uint256);

    // Function to get the current mint base fee
    function mintBaseFee() external view returns (uint256);
    
    // Function to get the creator signature fee
    function creatorSignatureFee() external view returns (uint256);
    
    // Function to get the maximum mints a user can perform during his progressive discount cycle per mint
    function maxMintsPerUserInCycle() external view returns (uint256);

    // Function to get the last update timestamp
    function lastUpdateTimestamp() external view returns (uint256);

    // Function to get the update interval
    function UPDATE_INTERVAL() external pure returns (uint256);

    // Function to get the CREATOR_ROLE
    function getCreatorSignature() external payable;

    // Function to get the CONTRIBUTOR_ROLE identifier
    function CONTRIBUTOR_ROLE() external pure returns (bytes32);

    // Function to get CREATOR_ROLE identifier
    function CREATOR_ROLE() external pure returns (bytes32);

    // Function to get ADMIN_ROLE identifier
    function ADMIN_ROLE() external pure returns (bytes32);

    // Function to check the number of mints a user has performed in their current cycle of progressive discounts
    function mintsPerUserInCycle(address user) external view returns (uint256);

    // Allow users to donate ETH to a specific creator in the system.
    function donate(address creator) external payable;

    // Allow users to check their mint fee
    function mintFee() external view returns (uint256);

    // Allow token owners to burn their tokens
    function burn(uint256 tokenId) external;

    // Allow ADMIN_ROLE pause the contract
    function pause() external;

    // Allow ADMIN_ROLE unpause the contract
    function unpause() external;

    // Allow CREATOR_ROLE to mint
    function safeMint(string memory uri) external payable;

    // Allow ADMIN_ROLE to update contract terms
    function updateTerms(
        uint256 mintBaseFee,
        uint256 creatorSignatureFee,
        uint256 maxMintsPerUserInCycle
    ) external;

    // Allow ADMIN_ROLE to withdraw funds from the contract
    function withdraw(uint256 amount) external;

}
```

#### `currentTokenId()`
**Description:**

Tracks the current token ID in the system. Can also be used to determine how many tokens have been minted in the system.

#### `mintBaseFee()`
**Description**:  
The base fee for minting a token, paid by the user to create a new token.

#### `creatorSignatureFee()`
**Description**:  
The fee required for a user to acquire a creator&apos;s signature, allowing them to become a creator in the system.

#### `maxMintsPerUserInCycle()`
**Description**:  
The maximum number of mints a user can perform during their current cycle of progressive discounts. Once the limit is exceeded, the user&apos;s minting count is reset to zero.

#### `lastUpdateTimestamp()`
**Description**:  
Timestamp of the last time the contract terms were updated (e.g., minting fees and creator signature fees). It is used to determine when the contract&apos;s terms can be updated again.

#### `UPDATE_INTERVAL()`
**Description**:  
The time interval between updates to the contract terms. **RECOMMENDED** that it be defined, in time units of hours, at a minimum of &lt;ins&gt;720 hours&lt;/ins&gt;, equivalent to 30 days.

#### `ADMIN_ROLE()`
**Description**:  
The role identifier for admins in the system. 

**Requirements**:  
- **MUST** be assigned inside the constructor to the `msg.sender`. 

#### `CREATOR_ROLE()`
**Description**:  
The role identifier for creators in the system. 

**Requirements**:  
- **MUST** be assigned inside the constructor to the `msg.sender`.  

#### `CONTRIBUTOR_ROLE()`
**Description**:  
The role identifier for contributors in the system. 

#### `mintsPerUserInCycle(address user)`
**Description**:  
Tracks the number of mints a user has performed in their current cycle of progressive discounts. It is used to enforce the maximum minting limit per user.


#### `CreatorTermsUpdated(uint256 mintBaseFee, uint256 creatorSignatureFee, uint256 maxMintsPerUserInCycle)`
**Description**:  
Emitted when the contract terms related to minting are updated by the `ADMIN_ROLE`.


#### `DonationReceived(address from, address to, uint256 amount)`
**Description**:  
Emitted when a user donates ETH to a creator. This event tracks the details of the donation, including the donor&apos;s address, the recipient&apos;s address, and the donation amount.

**Parameters**:  
- `from`: The address of the user making the donation.  
- `to`: The address of the creator receiving the donation.  
- `amount`: The amount of ETH donated.


#### `safeMint(string memory uri)`
**Description**:  
Allows the caller to mint a new token to their address with a provided URI.

**Requirements**:  
- The caller **MUST** have the **CREATOR_ROLE**.  
- The user **MUST** pay the minting fee, which is dynamic based on their previous minting activity.  
- If the minting limit is exceeded, the user&apos;s mint count **SHALL** be reset to zero.
- Is **RECOMMENDED** to require that the contract is not paused before using this function.


#### `mintFee()`
**Description**:  
Calculates and returns the current minting fee that the caller **MUST** pay, based on the number of mints performed during his current discount per mint cycle. Is **RECOMMENDED** that the fee use a logarithmic reduction to adjust the fee smoothly.

&gt; Formula:
```math
\text{mintFee} = 
\begin{cases}
0, &amp; \text{if msg.sender has the ADMIN\_ROLE} \\ 
\frac{\text{mintBaseFee}}{\log_x(\text{userMints})}, &amp; \text{if } \text{userMints} &gt; 1 \\ 
\frac{\text{mintBaseFee}}{1}, &amp; \text{if } \text{userMints} &lt;= 1 
\end{cases}

```
&gt; Note: Please note that the returned logarithm is always rounded to integers due to the characteristics of Solidity with floating-point numbers.


**Requirements**:  
- The minting fee **MUST** be paid by the caller.  

#### `donate(address creator)`
**Description**:  
Allows users to donate ETH to a creator, helping fund their activities. After making a donation, the donor **SHALL** receive the **CONTRIBUTOR_ROLE**.

**Requirements**:  
- The provided address **MUST** be a valid creator (having the **CREATOR_ROLE**).  
- The `msg.sender` **MUST NOT** be the same as the `creator`.  
- The donation amount **MUST** be greater than zero.
- **MUST** emit a `DonationReceived` event after the donation is processed.

#### `getCreatorSignature()`
**Description**:  
Allows a user to acquire a creator&apos;s signature by paying the required fee.

**Requirements**:  
- The caller **MUST** pay the creator signature fee.  
- After the payment, the caller **SHALL** be granted the **CREATOR_ROLE**.
- Is **RECOMMENDED** to require that the contract is not paused before using this function.

#### `updateTerms(uint256 mintBaseFee, uint256 creatorSignatureFee, uint256 maxMintsPerUserInCycle)`
**Description**:  
Allows the admin to update the minting fee, creator signature fee, and the maximum mints per user in a cycle of progressive discounts.

**Requirements**:  
- Only the `ADMIN_ROLE` **MUST** call this function.  
- **MUST** be called in the contract constructor as the first update of the contract terms.
- The update interval period **SHALL** be respected before another update can occur.
- **MUST** emit a `CreatorTermsUpdated` event after the contract terms are updated.

#### `withdraw(uint256 amount)`
**Description**:  
Allows the `ADMIN_ROLE` to withdraw ETH from the contract.

**Requirements**:  
- Only the `ADMIN_ROLE` **MUST** call this function.  

#### `burn(uint256 tokenId)`
**Description**:  
Allows the owner of a token to burn (destroy) the token specified by `tokenId`.

**Requirements**:  
- The caller **MUST** be the owner of the token.

#### `pause()`
**Description**:  
Allows the `ADMIN_ROLE` to pause the contract, disabling certain functions.

**Requirements**:  
- Only the `ADMIN_ROLE` **SHOULD** call this function to pause the contract.

#### `unpause()`
**Description**:  
Allows the `ADMIN_ROLE` to unpause the contract, re-enabling functionality.

**Requirements**:  
- Only the `ADMIN_ROLE` **SHOULD** call this function to unpause the contract.

## Rationale  

Below are the key considerations and justifications for the design choices:

1. **Access Control**
   - **Problem**: In collaborative NFT systems, it is essential to ensure that critical contract functions are executed only by authorized users to prevent misuse or manipulation. Without proper access control, there is a risk that anyone could modify key parameters, such as minting fees, terms, or contract pauses, which could lead to instability or unfair advantages for certain users.
   - **Solution**: By introducing role-based access control, this standard ensures that only trusted actors can perform sensitive actions. Admins are responsible for updating contract terms, pausing or unpausing the contract, and withdrawing funds, while creators can manage their own collections and get donations. This prevents arbitrary changes that might harm market stability or erode community trust.

2. **Dynamic Minting Fees**  
   - **Problem**: Fixed minting fees often lead to hoarding and disproportionate ownership, limiting equitable access to NFTs.  
   - **Solution**: By dynamically adjusting minting fees based on user activity within defined &lt;u&gt;minting cycles&lt;/u&gt;, we ensure that users are incentivized to engage with the platform by receiving &lt;u&gt;gradual discounts as they mint&lt;/u&gt;. Using a logarithmic reduction in minting fees ensures that the process is gradual, preventing market manipulation and maintaining scarcity over time.

3. **Donation-Based Engagement**  
   - **Problem**: Creators often lack sustainable models for fostering community engagement and receiving contributions.  
   - **Solution**: The donation system provides a transparent way for contributors to support their favorite creators directly. This can be used to attribute benefits in future trades, for example. This encourages deeper engagement and strengthens the relationship between creators and their communities.



### Backwards Compatibility  

This EIP is fully compatible with ERC-721. Extensions like dynamic minting fees, donation systems are modular and do not impact existing NFT token functionalities.



### Reference Implementation 

#### `mintFee()`
```solidity
function mintFee() public view returns (uint256) {
    if (hasRole(ADMIN_ROLE, msg.sender)) return 0;
    uint256 userMints = mintsPerUserInCycle(msg.sender);
    uint256 divisor = userMints &lt;= 1 ? 1 : Math.log2(userMints);
    return mintBaseFee / divisor;
}
```

#### `safeMint(string memory uri)`
```solidity
function safeMint(string memory uri)
public
payable
override 
onlyIfNotPaused
nonReentrant
onlyRole(CREATOR_ROLE)
{
    bool userMintsExceeded = mintsPerUserInCycle(msg.sender) + 1 &gt; maxMintsPerUserInCycle;

    require(msg.value &gt;= mintFee(), &quot;Not enough ETH!&quot;);

    uint256 tokenId = currentTokenId++;
    _safeMint(msg.sender, tokenId);
    _setTokenURI(tokenId, uri);

    if(userMintsExceeded){
        mintsPerUserInCycle(msg.sender) = 0;
    }
    mintsPerUserInCycle(msg.sender)++;
}
```


## Security Considerations  

- **Reentrancy Protection:**  
  Is **RECOMMENDED** to make sure the functions `safeMint`, `withdraw` and `donate` are protected against reentrancy attacks.
- **Paused State:**  
  The Administrators **MUST** be able to pause the contract during emergencies to prevent unwanted operations and mitigate risks during uncertain times.
- **Burning Security:**
  Ensure that only the owner of a token can burn it, reducing the risk of malicious contracts or unauthorized users destroying tokens belonging to others. The burn behavior is restricted to the ownership function, enhancing security by preventing accidental or abusive token destruction.


## Copyright  
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 04 Dec 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7832</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7832</guid>
      </item>
    
      <item>
        <title>Scheduled function calls</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7833-scheduled-function-calls/21975</comments>
        
        <description>## Abstract

Ethereum&apos;s smart contracts enable users to delegate control of their funds to code, but these contracts require an external trigger to execute. Timing is often critical, and issues such as network delays or malicious behavior by block producers—like MEV attacks—can prevent timely execution. To address these challenges, this Ethereum Improvement Proposal (EIP) introduces a new opcode, OFFERCALL, which allows contracts to schedule function calls. When functions self-schedule, they exhibit bot-like behavior. These scheduled calls would offer ETH to block producers as an incentive to prioritize their execution over manually submitted transactions. If the offer is not fulfilled, the bot is deactivated until manually re-ignited by the owner. The EIP proposes enforcing the execution of scheduled calls as a requirement for block validity. This could help mitigate MEV attacks, as block producers would be compelled to execute bots that neutralize market manipulation within the blockchain.

## Specification

Adding bot-like behavior to an EVM function is achieved by recursively scheduling a call to the same function in the next block. We propose introducing a new EVM opcode, OFFERCALL, which, as the name implies, offers ETH to be burnt to the block producer of the next block in exchange for invoking a function. These offers are aggregated and ranked by the Ethereum node, with only the top N offers being retained; all others are discarded. Scheduled calls must be executed before any user transactions, with execution order determined by their rank in the sorted list. The offered ETH is burnt to prevent block producers from exploiting the system by scheduling calls that pay the offered amounts back to themselves.

Here is a solidity example of how the usage of OFFERCALL would look like:

```solidity=
contract Bot {
    uint256 offerPerCall;
    
    constructor(uint256 _offer) {
        offerPerCall = _offer;
        
        // Ignite the bot with an initial invocation offer
        offercall(update, offerPerCall);
    }
    
    function setOffer(uint256 _offer) external {
        offerPerCall = _offer;
    }

    function update() external {
        // Do scheduled work

        // The callee may reschedule itself in order to
        // introduce a bot-like behavior.
        // The callee has to be careful about its offer
        // otherwise it may die.
        offercall(update, offerPerCall);
        
        // Once an offercall fails, the contract owner
        // may have to set a new offer by calling `setOffer`
        // and then invoking the `update()` function again.
    }
}
```

An OFFERCALL fails in two situations:

- The contract does not hold at least the offered amount of ETH.
- The offered amount is not large enough to rank within the top N offers.

In the case of a self-scheduling function, once an OFFERCALL fails, the bot is deactivated. The only way to revive it is for the contract owner to manually call the function again, likely with a higher offer.

## Rationale

The rationale behind this Ethereum Improvement Proposal (EIP) stems from the need to enhance the reliability and fairness of smart contract execution on the Ethereum network. While Ethereum’s smart contracts allow for a high degree of programmability and automation, the execution of these contracts often depends on external triggers, such as user transactions or network conditions. This dependency introduces significant challenges, particularly in situations where timing is critical or when malicious actors, like block producers, can exploit the system for profit.

## Backwards Compatibility

The introduction of the new OFFERCALL opcode in this EIP requires a network upgrade, as it adds new functionality that is not currently supported by the Ethereum Virtual Machine (EVM). This change will affect how smart contracts can schedule and incentivize the execution of specific function calls, introducing a new mechanism that block producers must accommodate.

## Reference Implementation

N/A

## Security Considerations

The main concern with this EIP is whether it could lead to centralization, as wealthier users might dominate execution priorities. Burning unfulfilled offers partly addresses this by preventing endless offers.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 06 Dec 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7833</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7833</guid>
      </item>
    
      <item>
        <title>Separate Metadata Section for EOF</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7834-separate-metadata-section-for-eof/22138</comments>
        
        <description>## Abstract

Introduce a new separate metadata section to the Ethereum Object Format (EOF) that is unreachable by the code, and any changes to which does not affect the code.

## Motivation

It is desirable to include metadata in contract&apos;s bytecode for various reasons. For instance, both the Solidity and Vyper compilers by default include the language and compiler version used to compile. Vyper (with 0.4.1) appends an integrity hash to the initcode in CBOR encoding. Solidity additionally includes the IPFS or the Swarm hash of the Solidity contract metadata.json file, and the experimental Solidity flag. The current (pre-EOF) practice is to append this CBOR encoded metadata section in the contract&apos;s runtime bytecode, followed by the 2 bytes length of the CBOR encoded bytes.

```
        Solidity     ┌──────────────────────────────────────────0x0033 bytes──────────────────────────────────────────────┐
...7265206c656e677468a2646970667358221220dceca8706b29e917dacf25fceef95acac8d90d765ac926663ce4096195952b6164736f6c634300060b0033
```

This poses a problem for source code verification where the onchain bytecode is compared to the compiled bytecode of the given source code. During a contract verification, metadata sections, in particular the IPFS hash, need to be ignored and only the executional bytecode should be compared. Since pre-EOF bytecode is not structured, it is not possible to distinguish the metadata section from the executional bytecode easily. This gets even trickier in the case of factory contracts with multiple nested bytecodes, each having their own metadata sections. Verifiers need to implement their own heuristics and workarounds to find the metadata sections and ignore it.

The EOF brings structure to the bytecode by separating the code from the data, and placing the code of each contract in their respective containers. In its current form, this makes it possible to find the data easier than the pre-EOF bytecode. However, the current spec also does not describe a metadata section. Compilers currently need to place the contract metadata inside the data section which poses several problems:

1. It is not straightforward to distinguish the metadata part in the `data_section`, which poses the same problem as the pre-EOF bytecode.
2. Any change to the metadata&apos;s size within the data section will change the executional bytecode, e.g. through shifting `DATALOADN` offsets. With that, two identical contracts with different metadata sizes will not match during source code, since the code will be different.
3. The metadata can theoretically be reached by the code, e.g. via manipulating the `DATALOADN` instructions.

## Specification

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

Extending the format introduced in [EIP-3540](/EIPs/EIPS/eip-3540), this EIP proposes to add a new OPTIONAL section in the body called `metadata_section` before the `data_section`, and to add two new OPTIONAL fields `kind_metadata` (value: `0x05`) and `metadata_size` to the header before the `kind_data` and `data_size` fields.

```
container := header, body
header :=
    magic, version,
    kind_type, type_size,
    kind_code, num_code_sections, code_size+,
    [kind_container, num_container_sections, container_size+,]
    [kind_metadata, metadata_size,]
    kind_data, data_size,
    terminator
body := types_section, code_section+, container_section*, [metadata_section], data_section
types_section := (inputs, outputs, max_stack_increase)+
```

### Header

| name          | length  | value         | description                                                                             |
| ------------- | ------- | ------------- | --------------------------------------------------------------------------------------- |
| ...           | ...     | ...           | ...                                                                                     |
| kind_metadata | 1 byte  | 0x05          | kind marker for metadata size section                                                   |
| metadata_size | 2 bytes | 0x0001-0xFFFF | 16-bit unsigned big-endian integer denoting the length of the metadata section content  |
| kind_data     | 1 byte  | 0xff          | kind marker for data size section                                                       |
| data_size     | 2 bytes | 0x0000-0xFFFF | 16-bit unsigned big-endian integer denoting the length of the data section content (\*) |
| terminator    | 1 byte  | 0x00          | marks the end of the header                                                             |

### Body

| name             | length   | value | description                 |
| ---------------- | -------- | ----- | --------------------------- |
| ...              | ...      | ...   | ...                         |
| metadata_section | variable | n/a   | arbitrary sequence of bytes |
| data_section     | variable | n/a   | arbitrary sequence of bytes |

The structure and the encoding of the `metadata_section` is not defined by this EIP. It is left to the compilers, tooling, or the contract developers to define the encoding and the content. The current practice by the Solidity and Vyper compilers is to use CBOR encoding.

## Rationale

The `metadata_section` in the `body`, as well as the `kind_metadata` and `metadata_size` fields in the `header`, are OPTIONAL. This way, the compilers can avoid additional bytes in the container if they don&apos;t want to write any metadata. The `data_section` can change in its size and content during deployment, therefore it needs to be REQUIRED, even if the data is empty. The `metadata_section` is not expected to change during the deployment.

The reason for placing the `metadata_section` before the `data_section`, and assigning `kind_metadata` the value `0x05` (and not `0x04`) is to make it easier for the existing EOF tooling adapt the changes. Additionally, if the `metadata_section` was placed after the `data_section`, changes to the `data_section` in deploy time would cause the `metadata_section` to shift. By placing the `metadata_section` before, this could be mitigated.

## Backwards Compatibility

No backward compatibility issues are expected since [EIP-3540](/EIPs/EIPS/eip-3540) is not implemented yet.

## Security Considerations

No security considerations as this section is meant not to be executed.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 06 Dec 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7834</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7834</guid>
      </item>
    
      <item>
        <title>Wallet Call Preparation API</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/new-erc-wallet-call-preparation-api/22456</comments>
        
        <description>## Abstract

This proposal defines complementary JSON-RPC methods to [EIP-5792&apos;s `wallet_sendCalls`](/EIPs/EIPS/eip-5792) to enable an Application to sign over a call bundle (instead of the Wallet). Methods defined in this proposal are purposed for the Application to sign over `calls` and submit them to the Wallet with an accompanying signature. This is in contrast to `wallet_sendCalls`, where a Wallet itself signs over the call bundle.

## Motivation

Applications are increasingly seeking to use session keys and scoped permissions to make transactions on a user&apos;s behalf, without the user having to approve and sign each transaction in their wallet&apos;s interface. One example is an application that automates a user&apos;s decentralised exchange trading. As Smart Contract Accounts (SCAs) contain arbitrary execution interfaces that lead to varying calldata formats, it is not possible for an Application to know how to sign over an action for any arbitrary Account implementation, without maintaining a mapping of Account implementations to their signing logic. Apps need a simple way to request the payload that their session keys should sign, given a call or set of calls they wish to make, and a way to execute the calls once signed.

## Specification

In this specification, we define two new JSON-RPC methods: `wallet_prepareCalls` and `wallet_sendPreparedCalls`.

### `wallet_prepareCalls`

Instructs a Wallet to prepare a call bundle according to the Account&apos;s implementation. It returns a `digest` of the call bundle to sign over, as well as the parameters required to fulfil a `wallet_sendPreparedCalls` request (ie. `capabilities`, `chainId`, `context`, and `version`).

&gt; After calling `wallet_prepareCalls`, consumers are expected to sign over the `digest` and submit the `signature` and prepared calls to the Wallet via `wallet_sendPreparedCalls`.

#### Request

&gt; The request is identical to that of [`wallet_sendCalls`](/EIPs/EIPS/eip-5792).

```typescript
type Request = {
  method: &quot;wallet_prepareCalls&quot;;
  params: [
    {
      // Calls to be executed.
      calls: {
        to: `0x${string}`;
        data?: `0x${string}`;
        value?: `0x${string}`;
        capabilities?: Record&lt;string, any&gt;;
      }[];
      // Capabilities.
      capabilities?: Record&lt;string, any&gt;;
      // Chain ID of the chain the calls are being submitted to.
      chainId: `0x${string}`;
      // Sender address.
      from?: `0x${string}`;
      // Key (hint) that will be used to sign the call bundle.
      key?: {
        // Whether the digest will be prehashed by the key (default behavior of WebCrypto APIs).
        prehash?: boolean;
        // Public key.
        publicKey: `0x${string}`;
        // Key type.
        type: &quot;secp256k1&quot; | &quot;p256&quot; | &quot;webauthn-p256&quot;;
      };
      // JSON-RPC method version.
      version: string;
    }
  ];
};
```

#### Response

&gt; The response is intended to be forwarded to `wallet_sendPreparedCalls` (minus the `digest`).

```typescript
type Response = {
  // Capabilities to be forwarded to `wallet_sendPreparedCalls`.
  capabilities: Record&lt;string, any&gt;;
  // Chain ID of the chain the calls are being submitted to.
  chainId: `0x${string}`;
  // Data specific to the Wallet to be forwarded to `wallet_sendPreparedCalls`
  // (e.g. ERC-4337 UserOperation or alternative).
  context: unknown;
  // Key (hint) that will be used to sign the call bundle.
  key?: {
    // Whether the digest will be prehashed by the key (default behavior of WebCrypto APIs).
    prehash: boolean;
    // Public key.
    publicKey: `0x${string}`;
    // Key type.
    type: &quot;secp256k1&quot; | &quot;p256&quot; | &quot;webauthn-p256&quot; | &quot;webcrypto-p256&quot;;
  };
  // Digest of the call bundle to sign over.
  digest: `0x${string}`;
  // JSON-RPC method version.
  version: string;
};
```

#### Example

```typescript
const response = await provider.request({
  method: &quot;wallet_prepareCalls&quot;,
  params: [
    {
      calls: [
        {
          to: &quot;0xcafebabecafebabecafebabecafebabecafebabe&quot;,
          data: &quot;0xdeadbeef&quot;,
        },
      ],
      capabilities: {
        paymasterService: {
          url: &quot;https://...&quot;,
        },
      },
      chainId: &quot;0x1&quot;,
      key: {
        prehash: false,
        publicKey:
          &quot;0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef&quot;,
        type: &quot;p256&quot;,
      },
      version: &quot;1&quot;,
    },
  ],
});
/**
 * {
 *   capabilities: {
 *     paymasterService: {
 *       url: &apos;https://...&apos;
 *     }
 *   },
 *   chainId: &apos;0x1&apos;,
 *   context: { ... },
 *   digest: &apos;0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef&apos;,
 *   key: {
 *     prehash: false,
 *     publicKey: &apos;0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef&apos;,
 *     type: &apos;p256&apos;,
 *   },
 *   version: &apos;1&apos;,
 * }
 */
```

### `wallet_sendPreparedCalls`

Instructs a Wallet to execute a prepared call bundle (response of `wallet_prepareCalls`) with an accompanying `signature`.

#### Parameters

&gt; The request is identical to the response of `wallet_prepareCalls`, except that it includes a `signature`.

```typescript
type Request = {
  method: &quot;wallet_sendPreparedCalls&quot;;
  params: [
    {
      // Capabilities.
      capabilities: Record&lt;string, any&gt;;
      // Chain ID of the chain the calls are being submitted to.
      chainId: `0x${string}`;
      // Data specific to the Wallet from the `wallet_prepareCalls` response.
      // (e.g. ERC-4337 UserOperation or alternative).
      context: unknown;
      // Key that was used to sign the call bundle.
      key: {
        // Whether the digest will be prehashed by the key (default behavior of WebCrypto APIs).
        prehash?: boolean;
        // Public key.
        publicKey: `0x${string}`;
        // Key type.
        type: &quot;secp256k1&quot; | &quot;p256&quot; | &quot;webauthn-p256&quot; | &quot;webcrypto-p256&quot;;
      };
      // Signature of the call bundle.
      signature: `0x${string}`;
      // JSON-RPC method version.
      version: string;
    }
  ];
};
```

#### Response

&gt; The response is identical to that of `wallet_sendCalls`.

```typescript
type Response = {
  id: string;
  capabilities: Record&lt;string, any&gt;;
};
```

#### Example

```typescript
const { digest, ...request } = await provider.request({
  method: &quot;wallet_prepareCalls&quot;,
  params: [
    {
      calls: [
        {
          to: &quot;0xcafebabecafebabecafebabecafebabecafebabe&quot;,
          data: &quot;0xdeadbeef&quot;,
        },
      ],
      capabilities: {
        paymasterService: {
          url: &quot;https://...&quot;,
        },
      },
      chainId: &quot;0x1&quot;,
      key: {
        prehash: false,
        publicKey:
          &quot;0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef&quot;,
        type: &quot;p256&quot;,
      },
      version: &quot;1&quot;,
    },
  ],
});

const signature = p256.sign(digest, privateKey);

const response = await provider.request({
  method: &quot;wallet_sendPreparedCalls&quot;,
  params: [
    {
      ...request,
      signature,
    },
  ],
});
/**
 * [
 *   {
 *     id: &apos;0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef&apos;,
 *   }
 * ]
 */
```

## Rationale

These endpoints extend the interface established by EIP-5792, given the emergent needs of application developers.

Adding new endpoints for this specific use case is simpler than adding additional options to the `wallet_sendCalls` endpoint.

Surfacing the prepared calls should be relatively simple for wallets, who already need to do preparation internally in order to support `wallet_sendCalls`, and who then submit signed calls on chain.

## Backwards Compatibility

This specification is currently compatible with EIP-5792 and does not introduce breaking changes to existing `wallet_sendCalls` flows.

- It does not modify or deprecate `wallet_sendCalls`; wallets compliant with EIP-5792 continue to work unchanged.
- `wallet_prepareCalls` mirrors the `wallet_sendCalls` request shape and returns values intended to be forwarded to `wallet_sendPreparedCalls`, preserving field formats such as `capabilities`, `chainId`, `context`, and `version`.
- `wallet_sendPreparedCalls` consumes the same data the wallet would otherwise construct internally for EIP-5792, with the addition of an externally produced `signature`.
- Any additional key types or hints (e.g., WebCrypto/WebAuthn variants) are optional and do not affect EIP-5792 behavior.

## Security Considerations

- Key authorization and scope: Wallets MUST verify that the provided `key.publicKey` is authorized for the account and that the requested `capabilities` are within that key’s permissions (scopes, limits, validity windows).

- Prehashing consistency: Honor `key.prehash` consistently. A mismatch between signer and verifier (e.g., double-hashing vs prehashed input) can cause verification failures. Wallets SHOULD fix the hash function per key type.

- Preparation-to-execution linkage: Wallets SHOULD ensure `wallet_sendPreparedCalls` corresponds to a `digest` they could have produced (e.g., by recomputing it) and MAY track a preparation identifier and/or validity window to mitigate long-lived replay.

- WebAuthn/origin considerations: For `webauthn-p256`, prefer user-verification and origin-bound credentials. Applications SHOULD keep session keys non-extractable and hardware-backed where available, and avoid presenting opaque digests for end-user approval.

- Resource usage and DoS: Wallets MAY rate-limit `wallet_prepareCalls`, cap bundle sizes, and validate inputs early to avoid expensive context generation for malformed or adversarial requests.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 06 Dec 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7836</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7836</guid>
      </item>
    
      <item>
        <title>Diffusive Tokens</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7837-diffusive-tokens/21989</comments>
        
        <description>## Abstract

This ERC proposes a standard for a new type of fungible token, called **Diffusive Tokens (DIFF)**. Unlike traditional [ERC-20](/EIPs/EIPS/eip-20) tokens, transferring DIFF tokens does not decrease the sender’s balance. Instead, it *mints* new tokens directly to the recipient, increasing the total supply on every transfer action. A fixed native currency fee is charged per token transferred, and this fee is paid by the sender to the contract owner. The supply growth is limited by a maximum supply set by the owner. Token holders can also burn their tokens to reduce the total supply. These features enable a controlled, incentivized token distribution model that merges fungibility with a built-in economic mechanism.

## Motivation

Traditional [ERC-20](/EIPs/EIPS/eip-20) tokens maintain a constant total supply and simply redistribute balances on transfers. While this model is widespread, certain use cases benefit from a token design that continuously expands supply during transfers, simulating a controlled &quot;diffusion&quot; of value. The Diffusive Token model may be suitable for representing claims on real-world goods (e.g., a product batch like iPhone 15 units), digital goods, or controlled asset distributions where initial token distribution and ongoing availability need to be managed differently.

This model also includes a native currency fee per token transferred, incentivizing careful, value-driven transfers and providing a revenue stream for the token’s issuer. The maximum supply cap prevents unbounded inflation, ensuring long-term scarcity. The ability for owners to burn tokens to redeem underlying goods or services directly maps on-chain assets to real-world redemptions.

**Use Cases**:

- **Real-World Asset Backing**: A manufacturer can issue DIFF tokens representing a batch of products (e.g., iPhones). Each token can be redeemed (burned) for one physical item.
  
- **Fee-Driven Incentives**: The transfer fee ensures that infinite minting by constant transferring is economically disincentivized. The fee also supports the token issuer or provides a funding mechanism.


## Specification

### Terminology

- **Diffusive Token**: A fungible token unit that is minted on transfers.
- **Max Supply**: The maximum total supply the token can reach.
- **Transfer Fee**: A fee in native blockchain currency (e.g., ETH) that must be paid by the sender for each token transferred. The total fee = `transferFee * amount`.
- **Burn**: The action of destroying tokens, reducing both the holder’s balance and the total supply.

### Data Structures

- **Total Supply and Max Supply**:
  
  ```solidity
  uint256 public totalSupply;
  uint256 public maxSupply;
  ```

- **Transfer Fee**:
  
  ```solidity
  uint256 public transferFee; // fee per token transferred in wei
  address public owner;
  ```

  The `owner` sets and updates `transferFee` and `maxSupply`.

### Token Semantics

1. **Minting on Transfer**
   When a transfer occurs from `A` to `B`:
   - `A` does not lose any tokens.
   - `B` receives newly minted tokens (increasing their balance and totalSupply).
   - The `totalSupply` increases by the transferred amount, but must not exceed `maxSupply`.

2. **Fixed Transfer Fee in Native Currency**
   Each transfer requires the sender to pay `transferFee * amount` in the native currency. If `msg.value` is insufficient, the transaction reverts.

3. **Maximum Supply**
   If a transfer would cause `totalSupply + amount &gt; maxSupply`, it must revert.

4. **Burning Tokens**
   Token holders can burn tokens to:
   - Reduce their balance by the burned amount.
   - Decrease `totalSupply` by the burned amount.
   
   This can map to redeeming underlying goods or simply deflating the token.

### Interface

The DIFF standard aligns partially with [ERC-20](/EIPs/EIPS/eip-20), but redefines certain behaviors:

**Core Functions:**

- `function balanceOf(address account) external view returns (uint256);`
  
- `function transfer(address to, uint256 amount) external payable returns (bool);`
  
  - **Modified behavior**: Mints `amount` tokens to `to`, requires `msg.value &gt;= transferFee * amount`.

- `function burn(uint256 amount) external;`
  
  - Reduces sender’s balance and `totalSupply`.

**Administration Functions (Owner Only):**

- `function setMaxSupply(uint256 newMax) external;`
  
- `function setTransferFee(uint256 newFee) external;`

- `function withdrawFees(address payable recipient) external;`
  
  - Withdraws accumulated native currency fees.

**Optional Approval Interface (For Compatibility):**

- `function approve(address spender, uint256 amount) external returns (bool);`
- `function transferFrom(address from, address to, uint256 amount) external payable returns (bool);`
  
  - **Modified behavior**: Similar to `transfer`, but uses allowance and still mints tokens to `to` rather than redistributing from `from`.

### Events

- `event Transfer(address indexed from, address indexed to, uint256 amount);`
  
  Emitted when tokens are minted to `to` via a transfer call.

- `event Burn(address indexed burner, uint256 amount);`

  Emitted when `amount` of tokens are burned from an address.

- `event FeeUpdated(uint256 newFee);`

  Emitted when the owner updates the `transferFee`.

- `event MaxSupplyUpdated(uint256 newMaxSupply);`

  Emitted when the owner updates `maxSupply`.

### Compliance with ERC-20

The DIFF standard implements the ERC-20 interface but significantly alters the `transfer` and `transferFrom` semantics:

- **Fungibility**: Each token unit is identical and divisible as in ERC-20.
- **Balances and Transfers**: The `balanceOf` function works as normal. However, `transfer` and `transferFrom` no longer redistribute tokens. Instead, they mint new tokens (up to `maxSupply`).
- **Approvals**: The `approve` and `transferFrom` functions remain, but their logic is unconventional since the sender’s balance is never reduced by transfers.

While the DIFF standard can be seen as ERC-20 compatible at the interface level, the underlying economics differ substantially.

## Rationale

**Design Decisions**:

- **Unlimited Minting vs. Max Supply**: Allowing minting on every transfer provides a “diffusive” spread of tokens. The `maxSupply` prevents uncontrolled inflation.
  
- **Burn Mechanism**: Enables redemption or deflation as tokens are taken out of circulation.
  
- **Owner Controls**: The owner (e.g., issuer) can adjust fees and max supply, maintaining flexibility as market conditions change.

## Backwards Compatibility

The DIFF standard is interface-compatible with ERC-20 but not behaviorally identical. Any system integrating DIFF tokens should understand the difference in minting on transfer.

- **Wallets and Exchanges**: Most ERC-20 compatible tools can display balances and initiate transfers. However, the unusual economics (mint on transfer) may confuse users and pricing mechanisms.
- **Allowances and TransferFrom**: Still implemented for interoperability, but the expected logic (debiting `from` balance) does not apply.

## Test Cases

1. **Initial Conditions**:
   - Deploy contract with `maxSupply = 1,000,000 DIFF`, `transferFee = 0.001 ETH`.
   - `totalSupply = 0`.
   - Owner sets parameters and verifies via `maxSupply()` and `transferFee()` getters.

2. **Minting on Transfer**:
   - User A calls `transfer(B, 100)` with `msg.value = 0.1 ETH` (assuming `transferFee = 0.001 ETH`).
   - Check `balances[B] == 100`, `totalSupply == 100`.
   - Check that the contract now holds 0.1 ETH from the fee.

3. **Exceeding Max Supply**:
   - If `totalSupply = 999,950` and someone tries to transfer 100 tokens, causing `totalSupply` to exceed `1,000,000`, the transaction reverts.

4. **Burning Tokens**:
   - User B calls `burn(50)`.
   - Check `balances[B] == 50`, `totalSupply == 50` less than before.
   - `Burn` event emitted.

5. **Updating Fee and Withdrawing Funds**:
   - Owner calls `setTransferFee(0.002 ETH)`.
   - `FeeUpdated` event emitted.
   - Owner calls `withdrawFees(ownerAddress)`.
   - Check that `ownerAddress` receives accumulated fees.

## Reference Implementation

A reference implementation is provided under the asset folder in the EIPs repository. The implementation includes:

- A basic contract implementing the DIFF standard.
```solidity
contract DiffusiveToken {
    // -----------------------------------------
    // State Variables
    // -----------------------------------------

    string public name;
    string public symbol;
    uint8 public decimals;

    uint256 public totalSupply;
    uint256 public maxSupply;
    uint256 public transferFee; // Fee per token transferred in wei

    address public owner;

    // -----------------------------------------
    // Events
    // -----------------------------------------

    event Transfer(address indexed from, address indexed to, uint256 amount);
    event Burn(address indexed burner, uint256 amount);
    event FeeUpdated(uint256 newFee);
    event MaxSupplyUpdated(uint256 newMaxSupply);
    event Approval(address indexed owner, address indexed spender, uint256 value);

    // -----------------------------------------
    // Modifiers
    // -----------------------------------------

    modifier onlyOwner() {
        require(msg.sender == owner, &quot;DiffusiveToken: caller is not the owner&quot;);
        _;
    }

    // -----------------------------------------
    // Constructor
    // -----------------------------------------

    /**
     * @dev Constructor sets the initial parameters for the Diffusive Token.
     * @param _name Token name
     * @param _symbol Token symbol
     * @param _decimals Decimal places
     * @param _maxSupply The max supply of tokens that can ever exist
     * @param _transferFee Initial fee per token transferred in wei
     */
    constructor(
        string memory _name,
        string memory _symbol,
        uint8 _decimals,
        uint256 _maxSupply,
        uint256 _transferFee
    ) {
        name = _name;
        symbol = _symbol;
        decimals = _decimals;
        maxSupply = _maxSupply;
        transferFee = _transferFee;
        owner = msg.sender;
        totalSupply = 0; // Initially, no tokens are minted
    }

    // -----------------------------------------
    // External and Public Functions
    // -----------------------------------------

    /**
     * @notice Returns the token balance of the given address.
     * @param account The address to query
     */
    function balanceOf(address account) external view returns (uint256) {
        return balances[account];
    }

    /**
     * @notice Transfers `amount` tokens to address `to`, minting new tokens in the process.
     * @dev Requires payment of native currency: transferFee * amount.
     * @param to Recipient address
     * @param amount Number of tokens to transfer
     * @return True if successful
     */
    function transfer(address to, uint256 amount) external payable returns (bool) {
        require(to != address(0), &quot;DiffusiveToken: transfer to zero address&quot;);
        require(amount &gt; 0, &quot;DiffusiveToken: amount must be greater than zero&quot;);

        uint256 requiredFee = transferFee * amount;
        require(msg.value &gt;= requiredFee, &quot;DiffusiveToken: insufficient fee&quot;);

        // Check max supply limit
        require(totalSupply + amount &lt;= maxSupply, &quot;DiffusiveToken: would exceed max supply&quot;);

        // Mint new tokens to `to`
        balances[to] += amount;
        totalSupply += amount;

        emit Transfer(msg.sender, to, amount);
        return true;
    }

    /**
     * @notice Burns `amount` tokens from the caller&apos;s balance, decreasing total supply.
     * @param amount The number of tokens to burn
     */
    function burn(uint256 amount) external {
        require(amount &gt; 0, &quot;DiffusiveToken: burn amount must be greater than zero&quot;);
        require(balances[msg.sender] &gt;= amount, &quot;DiffusiveToken: insufficient balance&quot;);

        balances[msg.sender] -= amount;
        totalSupply -= amount;

        emit Burn(msg.sender, amount);
    }

    /**
     * @notice Approves `spender` to transfer up to `amount` tokens on behalf of `msg.sender`.
     * @param spender The address authorized to spend
     * @param amount The max amount they can spend
     */
    function approve(address spender, uint256 amount) external returns (bool) {
        require(spender != address(0), &quot;DiffusiveToken: approve to zero address&quot;);
        allowances[msg.sender][spender] = amount;
        emit Approval(msg.sender, spender, amount);
        return true;
    }

    /**
     * @notice Returns the current allowance of `spender` for `owner`.
     * @param _owner The owner of the tokens
     * @param _spender The address allowed to spend the tokens
     */
    function allowance(address _owner, address _spender) external view returns (uint256) {
        return allowances[_owner][_spender];
    }

    /**
     * @notice Transfers `amount` tokens from `from` to `to` using the allowance mechanism.
     * @dev The `from` account does not lose tokens; this still mints to `to`.
     * @param from The address from which the allowance has been given
     * @param to The recipient address
     * @param amount The number of tokens to transfer (mint)
     */
    function transferFrom(address from, address to, uint256 amount) external payable returns (bool) {
        require(to != address(0), &quot;DiffusiveToken: transfer to zero address&quot;);
        require(amount &gt; 0, &quot;DiffusiveToken: amount must be greater than zero&quot;);

        uint256 allowed = allowances[from][msg.sender];
        require(allowed &gt;= amount, &quot;DiffusiveToken: allowance exceeded&quot;);

        // Deduct from allowance
        allowances[from][msg.sender] = allowed - amount;

        uint256 requiredFee = transferFee * amount;
        require(msg.value &gt;= requiredFee, &quot;DiffusiveToken: insufficient fee&quot;);

        // Check max supply
        require(totalSupply + amount &lt;= maxSupply, &quot;DiffusiveToken: would exceed max supply&quot;);

        // Mint tokens to `to`
        balances[to] += amount;
        totalSupply += amount;

        emit Transfer(from, to, amount);
        return true;
    }

    // -----------------------------------------
    // Owner Functions
    // -----------------------------------------

    /**
     * @notice Updates the maximum supply of tokens. Must be &gt;= current totalSupply.
     * @param newMaxSupply The new maximum supply
     */
    function setMaxSupply(uint256 newMaxSupply) external onlyOwner {
        require(newMaxSupply &gt;= totalSupply, &quot;DiffusiveToken: new max &lt; current supply&quot;);
        maxSupply = newMaxSupply;
        emit MaxSupplyUpdated(newMaxSupply);
    }

    /**
     * @notice Updates the per-token transfer fee.
     * @param newFee The new fee in wei per token transferred
     */
    function setTransferFee(uint256 newFee) external onlyOwner {
        transferFee = newFee;
        emit FeeUpdated(newFee);
    }

    /**
     * @notice Allows the owner to withdraw accumulated native currency fees.
     * @param recipient The address that will receive the withdrawn fees
     */
    function withdrawFees(address payable recipient) external onlyOwner {
        require(recipient != address(0), &quot;DiffusiveToken: withdraw to zero address&quot;);
        uint256 balance = address(this).balance;
        (bool success, ) = recipient.call{value: balance}(&quot;&quot;);
        require(success, &quot;DiffusiveToken: withdrawal failed&quot;);
    }

    // -----------------------------------------
    // Fallback and Receive
    // -----------------------------------------

    // Allows the contract to receive Ether.
    receive() external payable {}
}
```

- Interfaces and helper contracts for testing and demonstration purposes.

## Security Considerations

- **Reentrancy**: Handle fee transfers using the Checks-Effects-Interactions pattern. Consider `ReentrancyGuard` from OpenZeppelin to prevent reentrant calls.
- **Overflow/Underflow**: Solidity 0.8.x guards against this by default.
- **Contract Balance Management**: Ensure enough native currency is sent to cover fees. Revert on insufficient fees.
- **Access Control**: Only the owner can update `transferFee` and `maxSupply`. Use proper `onlyOwner` modifiers.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 07 Dec 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7837</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7837</guid>
      </item>
    
      <item>
        <title>Add blob schedule to EL config files</title>
        <category>Informational/</category>
        
          <comments>https://ethereum-magicians.org/t/add-blob-schedule-to-execution-client-configuration-files/22182</comments>
        
        <description>## Abstract

Add a new object to client configuration files `blobSchedule` which lists the
target blob count per block and max blob count per block for each fork.

## Motivation

- ensure there is a way to dynamically adjust the target and max blob counts per
  block
- ensure there is a way to dynamically adjust the blob base fee update fraction
- avoid complex handshake over engine API

## Specification

Extend client configuration files with the object `blobSchedule`, which has the
following shape:

```json
&quot;blobSchedule&quot;: {
  &quot;cancun&quot;: {
    &quot;target&quot;: 3,
    &quot;max&quot;: 6,
    &quot;baseFeeUpdateFraction&quot;: 3338477
  },
  &quot;prague&quot;: {
    &quot;target&quot;: 6,
    &quot;max&quot;: 9,
    &quot;baseFeeUpdateFraction&quot;: 5007716
  }
}
```

Clients must configure the target, max and baseFeeUpdateFraction per-fork. The behavior
when the configuration is missing or incomplete for a fork is undefined. Clients
are free to choose how to handle this situation.

## Rationale

Although maintaining the target and max blob only in the consensus client is
desirable, we acknowledge the reality that execution clients need these values
for various activities. For example, the `eth_feeHistory` RPC method returns a
field `blobGasUsedRatio` that does require the max, even though the core
protocol doesn&apos;t specifically need such value. Passing this value over the
engine API every block seem overkill so we believe a configuration value is a
good middle ground. Additionally, the `baseFeeUpdateFraction` parameter was added to adjust the responsiveness of blob gas pricing per fork.

## Backwards Compatibility

No backward compatibility issues found.

## Security Considerations

No security considerations found.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 12 Dec 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7840</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7840</guid>
      </item>
    
      <item>
        <title>Cross-chain Message Format and Mailbox</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7841-cross-chain-message-format-and-mailbox/22185</comments>
        
        <description>## Abstract

This ERC proposes a **mailbox API** and **message format** for sending and receiving data between L2s. This standard makes it easier for developers to build cross-chain applications that work over a variety of VMs, chain settlement mechanisms (e.g., ZK or optimistic settlement), and messaging protocols (e.g., synchronous or asynchronous protocols). This ERC accomplishes this by 1.) defining a mailbox interface through which cross-chain messages can be sent and received independent of their payload; 2.) defining a VM-agnostic message format and address type to make the interface compatible with many VMs;  3.) keeping the mailbox interface minimal to make it compatible with many kinds of cross-chain communication.  Example applications include an intent-based bridge, a liquidity-unifying DEX operating across multiple chains, or a cross-chain lending application.

## Motivation

L2s have scaled Ethereum and unlocked new avenues for innovation, but left the ecosystem *fragmented*. To address this, there are a variety of cross-chain communication protocols designed to make L2s composable with each other, each implements its own message format that is incompatible with others. This ERC proposes a neutral, standard format for sending and receiving cross-chain messages. By standardizing the interface chains for messaging, we achieve:

- **Unified developer experience:** This standard abstracts away the low-level details of message passing from applications. This allows application developers to achieve the following, even among chains with different VMs, coordination protocols, or settlement logic:
  - send/receive messages to/from many chains using the **same interface**.
  - deploy their application across multiple chains with **little-to-no** code changes.
  - focus on their application’s design instead of cross-chain infrastructure.
- **Modularity:**  This ERC standardizes only the low level information required for sending and receiving messages between chains, similar to the Internet Protocol. This allows a **clean separation** between the interface for sending/receiving messages (this ERC) and a coordination protocol or settlement mechanism. This allows chains to adopt this standard with minimal changes, and gives chains **flexibility** to choose the specific protocols they need, instead of forcing all chains to agree on a single coordination protocol or settlement mechanism.
- **Shared Infrastructure:** This standard allows applications and chains to **reuse/repurpose infrastructure** for different use cases. Applications can leverage existing library contracts for common operations like encoding message payload for token transfer, while relayer networks can serve multiple purposes without significant modifications. This shared foundation simplifies the development and deployment of new chains, applications, and protocols.

## Specification

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

### Terminology

- A **Messaging Protocol** consists of mailbox contracts and a coordination (sub)protocol. A chain sends a message through a transaction that writes to its outbox and receives a message through a transaction that reads from the inbox.
- **Coordination Protocol**: A mechanism that relays messages between source and destination mailboxes, commonly through off-chain mechanisms. Examples include shared sequencers or intent relayers. A settlement mechanism to ensure the integrity of cross-chain messages is often part of a coordination protocol. It is not always required in the case of asynchronous messaging.
- In ***synchronous*** messaging protocols, chains have synchronized blocks (e.g., a block for each chain is produced every *t* seconds) and messages are received on the destination chain within the same block timeslot as they were sent from the source chain. In particular, a chain may send a message and read a response in one transaction within a block on a chain.
- In ***asynchronous*** messaging protocols the restrictions of synchronous protocols do not apply. In particular, the chains sending and receiving messages may not have synchronized block timeslots and there may be a delay (measured in elapsed blocks) between the transaction on the source chain that sends a message and the transaction on the destination chain in which it is received.

There is a wide range of ways in which both synchronous and asynchronous protocols may operate. For example, some protocols (particularly for asynchronous messaging) may require the source chain&apos;s block in which the message was sent to be finalized (e.g., settled on Ethereum) before it can be included within a block produced for the destination chain. Other protocols may allow for messages to be optimistically included in blocks with consistency checks delayed until settlement time (reminiscent of speculative execution).

### Message Format

All messages MUST follow this format:

```solidity
/// @title Metadata type
/// @notice Metadata for a cross-chain message
struct Metadata {
    /// @notice The chain identifier of the source chain
    uint32 srcChainId;
    /// @notice The chain identifier of the destination chain
    uint32 destChainId;
    /// @notice The address of the sending party
    /// @dev 32 bytes are used to encode the address. In the case of an
    ///     Ethereum address, the last 12 bytes can be padded with zeros
    bytes32 srcAddress;
    /// @notice The address of the recipient
    /// @dev 32 bytes are used to encode the address. In the case of an 
    ///     Ethereum address, the last 12 bytes can be padded with zeros
    bytes32 destAddress;
    /// @notice The identifier for a cross-chain interaction session
    /// @dev SHOULD be unique for every new cross-chain calls
    uint128 sessionId;
    /// @notice The message counter within an interaction session 
    /// @dev SHOULD be unique within a session
    /// @dev OPTIONAL for most asynchronous bridges where every message has a 
    ///     distinct sessionId, simply set to 0 if unused
    /// @dev E.g. In a cross-chain call: ChainA.func1 -m1-&gt; ChainB.func2 -m2-&gt; 
    ///     ChainC.func3 -m3-&gt; ChainB.func4, the subscript i in m_i is the nonce
    uint128 nonce;
}

/// @title Message type
/// @notice A cross-chain message
struct Message {
    /// @notice The message metadata 
    Metadata metadata;
    /// @notice Message payload 
    /// @dev It may be ABI-encoded function calls, info about bridged assets, 
    ///     or arbitrary message data
    bytes payload;
}
```

Implementations SHOULD use a global rollup registry service that supports registration, deregistration, and efficient lookup of a rollup&apos;s chain ID. This work is outside the scope of this ERC, however.
Our standard is compatible with any ERC defining chain-specific addresses to better display the sender and receiver of a `Message`

### Mailbox APIs

Each chain SHOULD have **two canonical Mailbox contracts, one for synchronous and the other for asynchronous messaging**, responsible for managing both incoming and outgoing messages. The following APIs are RECOMMENDED to provide the minimal required functionality. Implementations of these APIs MAY include additional functions to support customized or more complex workflows.

```solidity
/// @title Mailbox contract.
/// @notice Mailbox for sending (resp. receiving) messages to (resp. from) 
///     other chains, standardized for messaging protocols that support 
///     synchronous or asynchronous, or both types of message passing.
interface Mailbox {
    // @notice Inbox: a key-value map, mapping: metadata digest -&gt; payload
    // @dev Implementators MAY instantiate with the following map
    // mapping(bytes32 =&gt; bytes) inbox;

    /// @notice Returns the chain ID for the host chain
    /// @dev SHOULD be set at the deployment time as immutable except for when 
    ///     using an upgradable Mailbox since immutable variables are discouraged.
    /// @dev MUST NOT change regardless of upgradable contracts or not.
    function chain_id() virtual public view returns (uint32);

    /// @notice Returns the digest of the inbox, used for mailbox consistency 
    ///     checks
    /// @dev There SHOULD be an accumulator (e.g. chained-hash or MerkleTree) 
    ///     logic that takes in every new inbox message and updates the digest
    /// @param srcChainId Identifier of the source chain
    /// @return Digest of all inbox messages coming from `srcChainId`
    function inboxDigest(uint32 srcChainId) virtual public returns (bytes32);

    /// @notice Returns the digest of the outbox, used for mailbox consistency 
    ///     checks
    /// @dev There SHOULD be an accumulator (e.g. chained-hash or MerkleTree) 
    ///     logic that takes in every new outbox message and updates the digest
    /// @param destChainId Identifier of the destination chain
    /// @return Digest of all outbox messages directed at `destChainId`
    function outboxDigest(uint32 destChainId) public returns (bytes32);

    /// @notice Returns the &quot;key&quot; in inbox/outbox map for a message according 
    ///     to its metadata
    /// @dev The metadata includes all fields in the `Metadata` struct.
    function getMetadataDigest(
        Metadata calldata metadata
    ) virtual public pure returns (bytes32);

    /// @notice Send a message to another chain
    /// @param metadata Metadata of the message
    /// @param payload Payload of the message
    /// @dev SHOULD sanity check `metadata.srcChainId == this.chain_id() &amp;&amp; 
    ///     metadata.srcAddress == msg.sender`;
    /// @dev SHOULD update the outbox digest and/or the outbox
    function send(Metadata calldata metadata, bytes memory payload) virtual public;

    /// @notice Receive a message from another chain
    /// @dev SHOULD revert if message cannot be retrieved
    /// @dev SHOULD sanity check `metadata.destChainId == this.chain_id()`
    /// @param metadata Metadata of the message
    /// @return payload of the retrieved message
    function recv(
        Metadata calldata metadata
    ) virtual public returns (bytes memory payload);

    /// @notice Populate the inbox with incoming messages
    /// @param messages Inbox messages to put in `this.inbox`
    /// @param aux OPTIONAL auxiliary information/witness to justify these 
    ///     inbox messages
    /// @dev `aux` may be empty or signature from a trusted relayer, etc.
    function populateInbox(
        Message[] calldata messages,
        bytes memory aux
    ) virtual public;

    /// @notice Generates a fresh and random sessionId for new messages
    /// @dev In order to ensure the uniqueness of the value generated, this 
    ///     function MIGHT require using a contract variable
    /// @dev With this unique session ID, for messages that do not require a 
    ///     nonce, we can set nonce=0, and the overall metadata digest is still 
    ///     collision-free with high probability
    /// @return A unique sessionId
    function randSessionId() virtual public returns (uint128);
}
```

The `Mailbox` contract SHOULD keep track of an *inbox* of incoming messages. The concrete data structure used to store the `inbox` queue SHOULD be a hash-map-like `mapping` in Solidity to enable efficient lookup by the dApps with payload-independent query keys. Being able to read/receive messages based on their metadata only, rather than their actual payload, is critical in achieving synchronous messaging with a dynamic payload known only at runtime. It is OPTIONAL to track the full outbox messages in the contract storage — an outbox digest may be sufficient for some cases.

While a single Mailbox contract could support both synchronous and asynchronous messaging protocols, this would require applications to specify the messaging mode for each interaction since each mode may require different settlement logic. Such a design would significantly complicate the Mailbox contract API, its implementation, and related infrastructure components like settlement logic. A more practical approach is to deploy separate, canonical Mailbox contracts for each mode. This allows applications to switch between synchronous and asynchronous messaging simply by pointing to the appropriate contract address.

Messages received via `Mailbox.recv()` are **authenticated** because they must first be populated in the inbox, with their integrity verified before the receiving action finalizes. This verification is performed either through the `aux` field during the `populateInbox()` call or via an external settlement layer.

## Rationale

### Multiple VM Support

Notice that our standard requires **no changes to a chain&apos;s VM** (i.e. no new opcode or precompiles required), but only proposes some smart contract interfaces. Specifically, the sender/recipient account type — generic `bytes32` instead of EVM-specific `address` type -- allows this standard to support a much wider class of VMs (e.g. SolanaVM that uses `Ed25519` public key as their accounts).

An optional `MultiplexABIEncoder` contract can abstract away the VM-specific encoding when preparing the message payload: a generic `encode(chainId)` function, as opposed to EVM’s `abi.encode`, that takes in the destination chain ID and decides the corresponding encoder logic so that the receiving party can decode natively. If the apps only care about interoperating with EVM chains, they can safely use `abi.encode()` as is and not go through any general encoder.

On the receiving side, EVM chains would type cast `address(parsedAddress)` on the `bytes32 parsedAddress` from the received message.

### Arbitrary message payload

The `Message.payload` field is designed for maximum flexibility, capable of encoding arbitrary data, including application-specific structures like the `CrossChainOrder` from [ERC-7683](/EIPs/EIPS/eip-7683) (See *Example Usage* section below for details of this integration). In contrast to some existing bridge designs that restrict the payload to function calls, the message payload in our design can also represent simpler data types, such as a boolean status flag for acknowledgments. This flexibility enables a wider range of use cases and simplifies integration across various applications.

### Use Metadata Digest Instead of `sessionId` for Message Query Key

For message lookups in the mailbox, the query key is derived from the hash of all message metadata rather than relying on a single `sessionId` field. This is because the `sessionId` derivation is customizable and may not adequately bind to key metadata like source and destination addresses. In contrast, the wrapping messaging protocol may enforce permissions for sending or receiving based on these metadata fields, so the query key must bind to the entire set of metadata.

Observe that when applications allow users to define `sessionId`, these values may not be unique across messages. Depending on the implementation of the inbox, this could be a concern. For example,  a mapping-based inbox needs an additional *nullifier set* to enforce the uniqueness of message metadata and avoid message overwrites in the case of a colliding map-key.

### Pre-filled Inbox

In contrast to other asynchronous bridge designs, our standard explicitly separates inbox filling from reading, enabling a unified interface for message retrieval. This separation allows specialized parties like builders or coordinators to handle protocol-specific message authentication when writing to the inbox, while applications can fetch messages directly. Additionally, message retrieval requires only metadata rather than the complete message, which is valuable in synchronous settings where message payloads are determined at execution time.

As mentioned above, pre-filling the inbox of the destination chain incurs additional gas costs which are manageable on L2s. We list some advantages of our approach:

- Eliminates Merkle inclusion proof verification when receiving every message. Some messaging protocols obviate Merkle proofs completely, even during `populateInbox()`, and delay the mailbox check to the settlement layer.
- Allows upgrade of the coordination protocol (e.g. the internal of `populateInbox()`and/or the settlement layer logic) without requiring changes to connected apps.
- Enables user-signed transactions on the destination chain instead of shared sequencer-signed transactions in synchronous messaging. This flexibility simplifies gas payment handling and ensures a consistent `msg.sender`. Detailed explanations are omitted for brevity (extended answers on the website).

### Related Proposals

In comparison to Inter-blockchain Communication(IBC)-like standards, this ERC is designed to work in a *stateless* manner. Messages do not need to pass a proof from the source chain at the time they are consumed on the destination chain. This allows use cases such as synchronous composability and intra-block messaging since messages don’t need to include finalized state from the source chain. Additionally, this ERC does not require multiple steps to establish a link between two chains. Messages can be directly sent from one chain to another in a single step.

ERC-7683 standardizes intent-based systems by defining structs for orders and interfaces for settlement smart contracts. This standard is application-specific and aimed at designers of cross-chain intent systems, while our proposal is more general and targets developers implementing arbitrary cross-chain applications. However, an intent system based on ERC-7683 **can be built on top** of our standard due to its modularity. An application implementing ERC-7683 could use the `Mailbox` API defined in this proposal to send `originData` from event messages between the source chain (where user funds are deposited) and the destination chain(s) (where intents are solved). We provide more details in the *Example Usage* section.

## Backwards Compatibility

No backward compatibility issues found. Since this is an opt-in protocol, L2s that do not opt-in to this will not be affected. Furthermore, this protocol can operate in existing cross-chain flows today, such as in intent-based bridges or native bridging of assets between L2s.

## Reference Implementation

We show a *possible* implementation of the mailbox contract for synchronous messaging protocol, and explain how it can be easily modified to support asynchronous protocols as well.

The high-level flow is as follows:

- Sending a message simply updates the outbox digest.
- Prefill the inbox by inserting the messages sequentially in the same order as the outbox in the source chain. Each insertion updates the corresponding inbox digest.
  - The prefilling transaction is likely created by a *coordinator* in the coordination protocol, who monitors messages sent from all rollups and relay them to the intended destination chain. The rollup sequencer includes this transaction in the block, ensuring it precedes any mailbox &quot;read&quot; operations and enforces a single prefilling per block.
- Applications can then read a message by querying the key-value map inbox with the (hashed) message metadata.
- External to these transactions, the settlement layer will receive new inbox digest and outbox digest (with storage proofs against a proven new rollup state) and checks `chain_i.inboxDigest[chain_j] == chain_j.outboxDigest[chain_i]` for all `i!=j`
  - Note: We ignore the slight complication of mailbox reset at the beginning of each block using nested mapping in our description above for brevity, but they are dealt with in our code snippet below.

```solidity
/// @title Mailbox contract implementation for synchronous communication
contract Mailbox {
    // ... Constructor + other simple functions like chain_id().

    /// @notice nested map: blockNum -&gt; metadataDigest -&gt; payload
    /// @dev Easy cleanup by `delete inbox[block.number -1]`
    mapping(uint256 =&gt; mapping(bytes32 =&gt; bytes)) inbox;
    // Mapping to detect key collisions: metadataDigest -&gt; writtenFlag
    mapping(bytes32 =&gt; bool) outboxNullifier;

    // These hash values are computed incrementally.
    /// @notice Nested map: blockNum -&gt; srcChainId -&gt; H(...H(m_2 | H(m_1))..)
    /// @dev Easy cleanup by `delete inboxDigest[block.number -1]`
    mapping(uint256 =&gt; mapping(uint32 =&gt; bytes32)) inboxDigest;
    /// @notice Nested map: blockNum -&gt; destChainId -&gt; H(...H(m_2 | H(m_1))..)
    /// @dev Easy cleanup by `delete outboxDigest[block.number -1]`
    mapping(uint256 =&gt; mapping(uint32 =&gt; bytes32)) outboxDigest;

    /// @dev Given the metadata (Message struct without payload field) of a 
    ///     message, derive the digest used as the dictionary key for inbox/outbox.
    function getMetadataDigest(
        uint32 srcChainId,
        uint32 destChainId,
        address srcAddress,
        address destAddress,
        uint256 uid
    ) pure public returns (bytes32) {
        return
            keccak(
                abi.encodePacked(
                    srcChainId,
                    destChainId,
                    srcAddress,
                    destAddress,
                    uid
                )
            );
    }

    /// @notice Conceptual &quot;cleanup/reset&quot; of mailbox after each block since 
    ///     sync msgs are received immediately.
    function _resetMailbox() private {
        delete inbox[block.number - 1];
        delete inboxDigest[block.number - 1];
        delete outboxDigest[block.number - 1];
    }

    /// @notice Send a message to another chain
    function send(
        uint32 destChainId,
        address destAddress,
        uint256 uid,
        bytes memory payload
    ) public {
        bytes32 key = getMetadataDigest(
            this.chain_id(),
            destChainId,
            bytes32(srcAddress),
            bytes32(msg.sender),
            uid
        );

        // Prevent overwriting the same key
        require(!outboxNullifier[key]);
        outboxNullifier[key] = true;

        // Update the outbox digest
        // digest&apos; = H(digest | metadata | payload)
        outboxDigest[block.number][this.chain_id()] = keccak256(
            abi.encodePacked(
                outboxDigest[block.number][this.chain_id()],
                key,
                m.payload
            )
        );
    }

    /// @dev This function can only be called once per block
    function populateInbox(Message[] calldata messages, bytes memory aux) public {
        // Before putting new inbox messages at the beginning of each block, 
        //     &quot;reset&quot; the inbox/outbox
        _resetMailbox();

        for (uint i = 0; i &lt; messages.length; i++) {
            Message memory m = messages[i];
            // Reject if the message was not sent to this chain
            require(m.destChainId == this.chain_id());

            bytes32 key = getMetadataDigest(
                m.srcChainid,
                m.srcAddr,
                this.chain_id(),
                m.destAddr,
                m.uid
            );
            inbox[key] = m.payload;

            // Update the inbox digest
            // digest&apos; = H(digest | metadata | payload)
            inboxDigest[block.number][m.srcChainId] = keccak256(
                abi.encodePacked(
                    inboxDigest[block.number][m.srcChainId],
                    key,
                    m.payload
                )
            );
        }
    }

    /// @notice Receive a message from another chain
    function recv(
        uint32 srcChainId,
        address srcAddress,
        address destAddress,
        uint256 uid
    ) public returns (bytes32) {
        bytes32 key = getMetadataDigest(
            srcChainId,
            this.chain_id(),
            bytes32(srcAddress),
            bytes32(destAddress),
            uid
        );
        return inbox[block.number][key];
    }
}
```

To extend the synchronous mailbox to support asynchronous protocols, we only need these modifications:

- Remove the first layer of mapping from `inbox`, `inboxDigest`, `outboxDigest`, since the “domain-separation from block number” requirement is gone. (e.g. changed to `mapping(bytes32 =&gt; bytes) inbox`)
- At the settlement layer, enforce that the destination chain’s inbox is a **subset** of the source chain’s outbox messages, rather than a full equality check.
  - Consequently, change the accumulator algorithm used to compute `inboxDigest,outboxDigest` to ones with efficient subset proof.
- Remove the `_reset()` logic since all messages for async will be permanently stored.

### Note on Gas Cost

The most costly operations are `sstore` during `Mailbox.populateInbox()`, which writes to the mapping `inbox` in contract storage, and `sload`, during `Mailbox.recv()` which reads from the `inbox` in storage. Luckily, Mailboxes costs on L2 are much cheaper. In cases of more gas-sensitive chains and applications, we suggest these potential optimizations:

- `delete inbox[key]` during `.recv()` to get gas refunds for cleaning some storage
  - Synchronous messages are cleaned up at the end of the same block in which they are populated. L2 can optionally implement gas optimizations for such block ephemeral storage.
- utilize the [EIP-2930](/EIPs/EIPS/eip-2930) access list to “pre-warm” predictable storage slots for lower execution cost
- batch-populate inbox messages and cluster them under fewer keys (bucketed mapping) e.g.: `mapping(bytes32 bucketKey =&gt; mapping(bytes32 =&gt; bytes)`


### Example Usage - Sync and Async Cross-chain Transfers

An ERC token contract wishing to allow cross-chain transfers would need to add the functions `xTransfer` and `xReceive` . The logic of a single chain transfer (e.g. `Token.send`) must be split into two functions `Token.xTransfer` and `Token.xReceive`. Each of these functions respectively mints and burns the same amount of assets and interact with the `Mailbox` contract.

```solidity
/// ERC20 token contract supporting cross-chain transfers
contract XChainToken is ERC20Burnable {
    /// @notice points to the Mailbox contract used
    Mailbox public mailbox;
    /// @notice bitmap for redeem-once control on inbox messages
    mapping(bytes32 =&gt; bool) private isRedeemed;
    /// @notice maps chainId to the canonical XChainToken address
    mapping(uint32 =&gt; address) public xChainTokenAddress;

    /// @notice use this function to transfer some amount of this token to 
    ///     another address on another chain
    /// @param destAddress receiver address
    /// @param amount amount to transfer
    /// @param destChainId identifier of the destination chain
    function xTransfer(
        uint32 destChainId,
        address destAddress,
        uint256 amount
    ) external returns (bool) {
        // Burn the token of the caller
        this.burn(amount);

        // Write a message to the Mailbox to notify the other chain that the 
        //     token have been successfully burnt.
        bytes memory payload = abi.encodePacked(amount, destAddress); // Specify the amount to be minted and the recipient
        mailbox.send(
            Mailbox.Metadata(
                mailbox.chain_id(),
                destChainId,
                bytes32(address(this)),
                bytes32(xChainTokenAddress[destChainId]),
                mailbox.randSessionId(),
                0
            ),
            payload
        );
    }

    /// @notice This function must be called on the destination chain to mint 
    ///     the tokens. This function can be called by any participant.
    /// @param srcChainId identifier of the source chain the funds are sent from
    /// @param sessionId unique identifier needed to fetch the message
    function xReceive(uint32 srcChainId, uint128 sessionId) public {
        /// Analoguous to crossTransfer except that this function can only be 
        ///     called once with the same parameters in order to avoid double 
        ///     minting. A mapping struct like isRedeemed can be used for this 
        ///     purpose.
        bytes memory payload = mailbox.recv(
            Mailbox.Metadata(
                srcChainId,
                mailbox.chain_id(),
                bytes32(xChainTokenAddress[srcChainId]),
                bytes32(address(this)),
                sessionId,
                0
            )
        );
        (uint256 amount, address destAddress) = abi.decode(
            payload,
            (uint256, address)
        );
        this.transfer(destAddress, amount);
    }
}
```

### Example Usage - Cross-chain function calls

In this example we show how to implement a cross-chain function call using the `Mailbox` abstraction:  The logic of cross-chain execution is handled by a contract `RemoteExecuter` deployed on both source and destination chains.

On the source chain `A`, a user wanting to call a function `fun` of a contract `Foo` on the destination chain `B` can invoke `RemoteExecuter.remoteCall` with the address of the contract `Foo` and other parameters including the function name and its arguments. This generates a message that is sent to chain `B`.

On the destination chain `B`, a call to `RemoteExecuter.execute`  fetches the message sent from the source chain `A`, parses it and executes the corresponding function of the local contract `Foo`. The `RemoteExecuter` contract also takes care of preventing messages replays.

Note that in this example gas on the destination chain is paid by the caller of `RemoteExecuter.execute` . In practice this participant can be the same user who called `RemoteExecuter.remoteCall` on the source chain. More advanced gas management policies can be implemented where another party calls `RemoteExecuter.execute` and pays on behalf of the user.

```solidity
/// Contract deployed on both chains A and B
/// This contract takes care of receiving remote calls from the source chain 
///     and of the execution on the destination chain
contract RemoteExecuter {
    /// @notice points to the chain Mailbox
    Mailbox public mailbox;
    /// @notice maps chainId to the canonical RemoteExecuter address
    /// @dev We assume the contract RemoteExecuter is deployed on both (or 
    ///     more) chains, and this map allows to know the address of the 
    ///     contract on the other chain(s).
    mapping(uint32 =&gt; address) public remoteExecuterAddress;
    // Track which messages have already been processed
    mapping(bytes32 =&gt; bool) private executedMessages;

    /// @notice Prepare the execution function on a another chain
    /// @dev This function sends a message to the destination chain with the 
    ///     parameters of the call
    function remoteCall(
        uint32 destChainId,
        address remoteContractAddress,
        bytes callParams
    ) public {
        Mailbox.Metadata memory metadata = Mailbox.Metadata(
            mailbox.chain_id(),
            destChainId,
            bytes32(address(this)),
            bytes32(remoteExecuterAddress[destChainId]),
            mailbox.randSessionId(),
            0
        );
        mailbox.send(metadata, callParams);
    }

    /// @notice Call a contract function locally based on some message that was 
    ///     sent from another chain
    /// @param srcChainId Identifier of the source chain where the call was 
    ///     initiated
    /// @param sessionId Session identifier
    function execute(uint32 srcChainId, uint128 sessionId) public {
        // Check that the message has not be executed yet
        bytes32 memory uid = keccak256(abi.encodePacked(sessionId, 0));
        require(!this.executedMessages[uid], &quot;already executed&quot;);

        // Read the message
        Mailbox.Metadata memory metadata = Mailbox.Metadata(
            srcChainId,
            mailbox.chain_id(),
            bytes32(remoteExecuterAddress[srcChainId]),
            bytes32(address(this)),
            sessionId,
            0
        );
        bytes memory payload = Mailbox.recv(metadata);

        // Call the function
        (address contractAddress, bytes memory callParams) = abi.decode(
            payload
        );
        contractAddress.call{gas: 100000}(callParams);

        // Mark message as executed
        this.executedMessages[uid] = true;
    }
}

// Contract deployed on chain A
contract Caller {
    /// @notice Function on the source chain A that calls a function of a 
    ///     contract deployed on the destination chain B
    /// @dev The identifier of the destination chain CHAIN_B_ID and the remote 
    ///     contract address FOO_CONTRACT_ADDRESS are hardcoded
    /// @param val parameter to be passed to the function Foo.fun(...)
    function callChainB(uint256 val) public {
        bytes memory callParams = abi.encodeCall(Foo.fun(val));
        RemoteExecuter.remoteCall(CHAIN_B_ID, FOO_CONTRACT_ADDRESS, callParams);
    }
}

/// Contract deployed on chain B
/// We assume this contract is deployed at the address FOO_CONTRACT_ADDRESS
/// This contract has a function that is called from chain A
contract Foo {
    function fun(uint256 parameter) public {
        require(parameter == 42);
    }
}
```

## Security Considerations

Security concerns for the messaging format and mailbox APIs themselves are minimal, as the protocol specification focuses on providing a rich and expressive interface for various message passing protocols. Security responsibilities lie with the underlying messaging protocol design and the application utilizing it. This specification ensures the interfaces are flexible enough to support the majority of cross-chain messaging protocols, while security within those protocols is outside the scope of this proposal.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 12 Dec 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7841</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7841</guid>
      </item>
    
      <item>
        <title>SLOTNUM opcode</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7843-slotnum-opcode/22234</comments>
        
        <description>## Abstract

This EIP proposes to add a new opcode `SLOTNUM` (`0x4b`), that returns the corresponding slot number for the current block.

## Motivation

There are currently two ways to get the current slot number onchain:

1) Calculate from the block timestamp. This requires hardcoding the chain slot length into a smart contract.

2) Provide the slot number as calldata and prove it against the beacon block root (using [EIP-4788](/EIPs/EIPS/eip-4788)).

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.

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.

## Specification

A new opcode `SLOTNUM` is introduced at `0x4b`. It shall return one stack element.

### Output

One element `slotNumber` is added to the stack; it is equal to the corresponding slot number for this block. `slotNumber` is a `uint64` in big endian encoding.

### Gas Cost

The gas cost for `SLOTNUM` is a fixed fee of `2`.

### RPC changes

The slot number is calculated in the consensus layer and passed to the execution layer through the engine API.

#### Header extension

The header encoding shall be extended to include a `slotNumber` field of type `uint64`.

#### Engine API changes

New objects `ExecutionPayloadV4` and `PayloadAttributesV4` are introduced, adding a `slotNumber` field of type `uint64`. The methods `engine_newPayloadV4`, `engine_getPayloadV6`, and `engine_forkChoiceUpdateV4` are added, to use the new objects.

## Rationale

### Gas Price

The opcode is priced to match similar opcodes in the `W_base` set.

### Calculation in consensus layer

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.

### ZK-VM proving

The `SLOTNUM` opcode should not increase the complexity of proving EVM execution, as it is similar to existing opcodes such as `TIMESTAMP`. The slot number is included in the block header rather than as a `engine_newPayload` parameter, ensuring that the block is self-contained for proving; no extra inputs to the circuit are required.

## Backwards Compatibility

No backward compatibility issues found.

## Test Cases

N/A

## Security Considerations

None.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Universal Orchestrator RPC</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7845-universal-orchestrator-rpc/21885</comments>
        
        <description>## Abstract

&gt; &quot;Hey smart speaker, swap my Shiba Inu for Pillar&quot;

&gt; &quot;Assistant, how much USDC can I buy with what&apos;s in my wallet?&quot;

&gt; &quot;Send 10 OP to Vitalik and 5 PEPE to Deimantas&quot;

The Universal Orchestrator RPC aims to standardise the **minimum shape and requirements** of a **request for a solution** **_from_** an arbitrary system managing an Ethereum wallet **_to_**, ultimately, an Orchestrator.

An arbitrary system could be a website, device, app, server program etc - anything that manages an Ethereum wallet, **speaks Ethereum JSON-RPC** and is looking to request solutions from an Orchestrator.

All solutions from an Orchestrator are ChA¹ (Chain Abstraction-first) by default.

![Flow](/EIPs/assets/eip-7845/flow.jpg)

## Motivation

Data model standards can be written in any shape. A system will often expose their external interface but require that the request to the aforementioned interface is modelled in a way that the service understands. This creates a huge level of inconsistency and in turn makes Orchestrator interoperability more difficult.

Orchestrators will become more widespread and numerous over time. This is especially true with the advent of Artificial Intelligence (AI) driven systems, the continued advancement of Human Computer Interaction (HCI) devices (especially those that are voice controlled) and the emergence of Extended Reality (XR) platforms.

Standardising the request object that an Orchestrator can understand from a wallet will drive adoption and make decentralised app development easier for developers that don&apos;t know how to make on-chain transactions or have the required technical understanding of block building systems.

## Specification

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

The Orchestrator&apos;s external interface(s) that expose functionality to an end-user application or another system MUST use JavaScript Object Notation (JSON).

The following data definitions are available and MUST **prefer chain abstraction (ChA¹)**, unless stated. Chain abstraction means that, where possible, should an asset span multiple chains - expect a solution from an Orchestrator to use and send assets to and from the supported chains to deliver a complete and cost-effective solution.

The following sequence diagram shows the flow of events in this proposal:

![Sequence Diagram](/EIPs/assets/eip-7845/sequence.png)

This specification follows the top level data shape of Ethereum JSON-RPC requests, as shown below:

### Request

The request definition is what a wallet sends to an Orchestrator for solutions to one or more problems. The request follows the specification from Ethereum JSON-RPC.

#### RPC

```typescript
interface Rpc: {
    id: number; // REQUIRED
    jsonrpc: string; // REQUIRED
    method: string; // REQUIRED
    params: Problem[]; // REQUIRED
}
```

The top level definition is an Ethereum RPC object.

- The `id` property is a random number that you can assign for your own purposes.
- The `jsonrpc` property takes a `string` that represents the version of JSON-RPC being used. Usually `&quot;2.0&quot;`.
- The `method` property is the method call intended for the Orchestrator, and by default CAN be `orchestrator_findSolutions`.
- The `params` property contains an array of `Problem` objects, and is REQUIRED. The Problem object is defined below.

#### Problem

```typescript
interface Problem: {
    actions: Action[] // REQUIRED
    chainId: number; // OPTIONAL
}
```

The `Problem` definition has just one REQUIRED property, `actions`. The `Problem` interface leaves space for additional properties in future network upgrades and existing or emerging standards.

- The `actions` property takes an `array` of `Action` objects, defined below, and is REQUIRED.
- The `chainId` takes a `number`, representing the chain ID, and is OPTIONAL.
  - If no `chainId` is provided:
    - `chainId` property MUST assume `1`

#### Action

```typescript
interface Action: {
    from: string; // REQUIRED
    towards: (Asset|Destination)[]; // REQUIRED
    with: Offering[]; // OPTIONAL
    type: string; // OPTIONAL
    functionCallName: string; // OPTIONAL
    functionCallData: string; // OPTIONAL
    deadline: number; // OPTIONAL
}
```

The `Action` definition has several properties that indicate the desired action. The set properties determine the action that needs to be solved.

- The `from` property is REQUIRED, takes a `string` and represents the wallet that this `Action` is for.
- The `towards` property is REQUIRED, takes an `array` of either an `Asset` or a `Destination` type and represents where this `Action` is targeted towards.
- The `with` property is OPTIONAL, takes an `array` of `Offering` type and represents what assets the wallet is prepared to offer to facilitate this `Action`
  - If the `with` property contains no `Offering` entries, then the Orchestrator MUST consider all assets available in the address space for an `Offering`.
- The `type` property is OPTIONAL, takes a `string` and is intended to help classify this action. Examples might include, but are not limited to - `transfer`, `swap`, `call` etc and is intended to assist the Orchestrator with the action.
  - If no `type` is provided, then &apos;transfer&apos; MUST be assumed
- The `functionCallName` property is OPTIONAL, takes a `string` and represents the function name to call against the `towards` property. If this is defined, the Orchestrator can be assumed that this Action desires to call a smart contract as part of the action.
- The `functionCallData` property is OPTIONAL, takes a `string` and represents the data payload for `functionCallName`. If this is defined but `functionCallName` is not, this property SHOULD be ignored.
- The `deadline` property is OPTIONAL, takes a `number` and represents a wallet-defined unix timestamp for when an action should have a solution by. Useful for high throughput systems, or time sensitive actions.

#### Asset

```typescript
interface Asset: {
    symbol: string; // OPTIONAL
    address: string; // OPTIONAL
    chainId: number; // OPTIONAL
}
```

The Asset definition defines an asset in question. This definition prefers chain abstraction.

- The `symbol` property is OPTIONAL, takes a `string` and represents the symbol of the Asset in question.
  - if no `symbol` is provided, `address` must be used
- The `address` property is OPTIONAL, takes a `string` and represents the `address` of the smart contract for this `Asset`.
  - if no `address` is provided, the native gas token MUST be used
- The `chainId` property is OPTIONAL, takes a `number` and represents the chain that this asset resides on. Useful for direct targeting of an `Asset` on a particular chain.
- If no `chainId` is provided: - The Orchestrator is free to use any corresponding asset on any chain to facilitate the action

#### Destination

```typescript
interface Destination: {
    address: string; // REQUIRED
    chainId: number; // REQUIRED
}
```

The Destination definition defines a direct target and is used in scenarios where the Orchestrator interpretation MUST NOT be used.

- The `address` property is REQUIRED and takes a `string` that represents the address space for this `Destination`.
- The `chainId` property is REQUIRED and takes a `number` and represents the chain the above `address` property resides on.

#### Offering

```typescript
interface Offering: {
    symbol: string; // SHOULD
    address: string; // SHOULD
    amount: (number|string); // OPTIONAL
    chainId: number; // OPTIONAL
}
```

The `Offering` definition defines what the requester is willing to spend from their wallet in order to facilitate the action being solved.

- The `symbol` property SHOULD be specified and represents the symbol of the `Offering` in question
  - If no `symbol` is provided, the address MUST be used
- The `address` property SHOULD be specified and takes a `string` that represents the address space for this `Offering`.
  - If no `address` is provided, the native gas token MUST be used
- The `amount` property is OPTIONAL and represents the amount to be offered as part of the `Action`. Accepts either a `number`, which represents an ether unit, or a `string` which can be used for BigNumbers.
  - If no amount is provided, the maximum value of the address, symbol or native gas unit must be assumed
- The `chainId` property is OPTIONAL and takes a `number` that represents the chain the above `address` property resides on.
  - If no `chainId` is provided:
    - `address` MUST NOT be used
    - `symbol` MUST be used (ChA¹)
    - If no higher level `chainId` property exists in the `Problem` property
      - The Orchestrator is free to use any corresponding asset on any chain to facilitate the action (ChA¹)

### Response

The response definition is what an Orchestrator sends back as a response to the request for solutions from a wallet. The response, like the request, follows the specification from Ethereum JSON-RPC.

#### RPC

```typescript
interface Rpc: {
    id: string; // REQUIRED
    jsonrpc: string; // REQUIRED
    result: Solution[]; // REQUIRED
}
```

The top level object is an Ethereum RPC object.

- The `id` property is REQUIRED, takes a `string` and MUST correlate to the same `number` that was received as part of the request object to the Orchestrator.
- The `jsonrpc` property is REQUIRED, takes a `string` and represents the version of JSON-RPC being used. Usually `&quot;2.0&quot;`.
- The `result` property is REQUIRED and takes an array of `Solution` objects. The `Solution` object is defined below.

#### Solution

```typescript
interface Solution: {
    name: string; // REQUIRED
    description: string; // OPTIONAL
    transactions: Transaction[]; // REQUIRED
    deadline: number; // OPTIONAL
}
```

The above `Solution` interface is the _solution_ to a _problem_ requested above. The `Solution` MUST be in the same order to a `Problem` that was requested.

- The `name` property is REQUIRED, takes a `string` and represents a short, non-technical and user-friendly, name of the solution.
- The `description` property is OPTIONAL, takes a `string` and represents a longer, non-technical and user-friendly, description of the solution.
- The `transactions` property is REQUIRED, takes an `array` of `Transaction` objects and represents one or more transactions needed for the user to execute the solution.
- The `deadline` property is OPTIONAL, takes a `number` and represents a unix timestamp by which this `Solution` should be executed. This is defined by the Orchestrator.

#### Transaction

```typescript
interface Transaction: {
    to: Destination; // REQUIRED
    chainId: number; // REQUIRED
    amount: (number|string); // REQUIRED
    calldata: string; // OPTIONAL
}
```

The above `Transaction` interface is a transaction definition that allows a wallet to perform their solution to a problem. There may be 1 or more transactions for a `Solution`.

- The `to` property is REQUIRED, takes a `Destination` type and represents the target for this Solution.
- The `chainId` property is REQUIRED, takes a number and represents the chain that this `Transaction` is targeted at. The `chainId` is REQUIRED here because the wallet MUST know where to send assets from as an origin due to the existence of multichain assets.
- The `amount` property is REQUIRED and represents the amount to be sent as part of the `Transaction`. Accepts either a `number`, which represents an ether unit, or a `string` which can be used for BigNumbers.

## Rationale

- Uses the Ethereum JSON-RPC JSON wrapper for greater compatibility.
- The interface definitions use only generic primitive types to ensure wide compatibility for any programming language.
- The interface definitions defined in this ERC attempts to cover as many scenarios as possible, from an Orchestrator perspective that a wallet may ask for, but focuses on core blockchain functionality.
- Certain high-level definitions, such as the `Problem` object definition, are sparse by design to allow space for future features introduced by other ERC&apos;s or network upgrades.
- Terminology is targeted towards a non-technical lexicon to aid in wider adoption and understanding.
- Nearly all options are REQUIRED, SHOULD and OPTIONAL to allow for both wallet and Orchestrator flexibility in providing solutions for the wallet request.
- It&apos;s understood that the Orchestrator interpretations and implementations will vary, so where possible the specification enforces REQUIRED and MUST to provide a universal level of service to an end-user or another service.
- The specification is **NOT** intended to standardise or modify the internal data structure or communication layer of an Orchestrator.
- Other parameters that could be considered, such as gas limits and estimations, are delegated back to the wallet as ultimately it is the wallet that will execute the solution(s).

## Backwards Compatibility

No backward compatibility issues found.

## Reference Implementation

### Example requests and responses for solutions

The following examples show a few common scenarios with their requests to, and from, an Orchestrator. All examples are chain abstracted (ChA¹) by default, unless specified.

#### Sending an [ERC-20](/EIPs/EIPS/eip-20) token to another address

The following request performs an action:

- from 0xbafB4E1EFA94B359e2E175CF6156AedA2cACa165
- towards address 0x50840CE036eEf2005d3c4d6f6Eb65f8116a01629
  - with symbol USDC, amount 5

&gt; [!NOTE]
&gt; Notes: All requests for solutions should be chain abstracted (ChA¹) by default. The Orchestrator &gt; &gt; can check for 5 USDC on any chain for the above &quot;from&quot; address, and send a solution that receives &gt; the 5 USDC on any other chain.

##### Request to Orchestrator

```json
{
  &quot;id&quot;: 1234,
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;method&quot;: &quot;orchestrator_findSolutions&quot;,
  &quot;params&quot;: {
    &quot;problems&quot;: [
      {
        &quot;actions&quot;: [
          {
            &quot;from&quot;: &quot;0xbafB4E1EFA94B359e2E175CF6156AedA2cACa165&quot;,
            &quot;towards&quot;: {
              &quot;address&quot;: &quot;0x50840CE036eEf2005d3c4d6f6Eb65f8116a01629&quot;
            },
            &quot;with&quot;: [
              {
                &quot;symbol&quot;: &quot;USDC&quot;,
                &quot;amount&quot;: 5
              }
            ]
          }
        ]
      }
    ]
  }
}
```

##### Response from Orchestrator

```json
{
  &quot;id&quot;: 1234,
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;result&quot;: [
    {
      &quot;name&quot;: &quot;Send 5 USDC&quot;,
      &quot;description&quot;: &quot;Send 5 USDC from 0xbafB4E1EFA94B359e2E175CF6156AedA2cACa165 to 0x50840CE036eEf2005d3c4d6f6Eb65f8116a01629&quot;,
      &quot;transactions&quot;: [
        {
          &quot;to&quot;: &quot;0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&quot;,
          &quot;chainId&quot;: 1,
          &quot;calldata&quot;: &quot;0x0...&quot;,
          &quot;value&quot;: 0
        }
      ]
    }
  ]
}
```

#### Swapping native token to USDC

The following request performs an action:

- from 0xbafB4E1EFA94B359e2E175CF6156AedA2cACa165
- towards symbol USDC
  - with: 0.1

&gt; [!NOTE]
&gt; Notes: All requests for solutions should be chain abstracted (ChA¹) by default. The Orchestrator
&gt; can take 0.1 native asset from any chain in return for USDC on any chain.

##### Request to Orchestrator

```json
{
  &quot;id&quot;: 1337,
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;method&quot;: &quot;orchestrator_findSolutions&quot;,
  &quot;params&quot;: {
    &quot;problems&quot;: [
      {
        &quot;actions&quot;: [
          {
            &quot;from&quot;: &quot;0xbafB4E1EFA94B359e2E175CF6156AedA2cACa165&quot;,
            &quot;towards&quot;: {
              &quot;symbol&quot;: &quot;USDC&quot;
            },
            &quot;with&quot;: [
              {
                &quot;amount&quot;: 0.1
              }
            ]
          }
        ]
      }
    ]
  }
}
```

##### Response from Orchestrator

```json
{
  &quot;id&quot;: 1337,
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;result&quot;: [
    {
      &quot;name&quot;: &quot;Swap 0.1 ETH for 371.498 USDC&quot;,
      &quot;description&quot;: &quot;Swapping 0.1 ETH from 0xbafB4E1EFA94B359e2E175CF6156AedA2cACa165 to 371.498 USDC via Uniswap&quot;,
      &quot;transactions&quot;: [
        {
          &quot;to&quot;: &quot;0x...&quot;,
          &quot;chainId&quot;: 1,
          &quot;calldata&quot;: &quot;0x0...&quot;,
          &quot;value&quot;: 0
        },
        {
          &quot;to&quot;: &quot;0x...&quot;,
          &quot;chainId&quot;: 1,
          &quot;calldata&quot;: &quot;0x...&quot;,
          &quot;value&quot;: 0.1
        }
      ]
    }
  ]
}
```

#### Swapping multiple tokens to USDC

The following request performs an action:

- from 0xbafB4E1EFA94B359e2E175CF6156AedA2cACa165
- towards symbol USDC
- with SHIB and / or Pillar

&gt; [!NOTE]
&gt; Notes: All requests for solutions should be chain abstracted (ChA¹) by default. The Orchestrator
&gt; can take any amount of SHIB and / or Pillar from any chain in return for an exchanged amount of
&gt; USDC on any chain.

##### Request to Orchestrator

```json
{
  &quot;id&quot;: 1234,
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;method&quot;: &quot;orchestrator_findSolutions&quot;,
  &quot;params&quot;: {
    &quot;problems&quot;: [
      {
        &quot;actions&quot;: [
          {
            &quot;from&quot;: &quot;0xbafB4E1EFA94B359e2E175CF6156AedA2cACa165&quot;,
            &quot;towards&quot;: {
              &quot;symbol&quot;: &quot;USDC&quot;
            },
            &quot;with&quot;: [
              {
                &quot;symbol&quot;: &quot;SHIB&quot;
              },
              {
                &quot;symbol&quot;: &quot;Pillar&quot;
              }
            ]
          }
        ]
      }
    ]
  }
}
```

##### Response from Orchestrator

```json
{
  &quot;id&quot;: 1337,
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;result&quot;: [
    {
      &quot;name&quot;: &quot;Swap 171,246 SHIB and 1004.72 Pillar for 10 USDC&quot;,
      &quot;description&quot;: &quot;Swapping 171,246 SHIB and 1004.72 Pillar from 0xbafB4E1EFA94B359e2E175CF6156AedA2cACa165 to 10 USDC via Uniswap&quot;,
      &quot;transactions&quot;: [
        {
          &quot;to&quot;: &quot;0x...&quot;,
          &quot;chainId&quot;: 1,
          &quot;calldata&quot;: &quot;0x0...&quot;,
          &quot;value&quot;: 0
        },
        {
          &quot;to&quot;: &quot;0x...&quot;,
          &quot;chainId&quot;: 1,
          &quot;calldata&quot;: &quot;0x0...&quot;,
          &quot;value&quot;: 0
        },
        {
          &quot;to&quot;: &quot;0x...&quot;,
          &quot;chainId&quot;: 1,
          &quot;calldata&quot;: &quot;0x...&quot;,
          &quot;value&quot;: 0.1
        }
      ]
    }
  ]
}
```

#### Sending an [ERC-20](/EIPs/EIPS/eip-20) token to multiple addresses

The following request performs the following actions:

- Action 1
  - from 0xbafB4E1EFA94B359e2E175CF6156AedA2cACa165
  - towards address 0x50840CE036eEf2005d3c4d6f6Eb65f8116a01629
  - with 5 USDC
- Action 2
  - from 0xbafB4E1EFA94B359e2E175CF6156AedA2cACa165
  - towards address 0xFCd239451346238B5560511Ae47A0b82b1bbE9f0
  - with 100 PLR

&gt; [!NOTE]
&gt; Notes: All requests for solutions should be chain abstracted (ChA¹) by default. The Orchestrator
&gt; can move the specified asset amounts on any chain where the asset exists in the &quot;from&quot; address.

##### Request to Orchestrator

```json
{
  &quot;id&quot;: 1000,
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;method&quot;: &quot;orchestrator_findSolutions&quot;,
  &quot;params&quot;: {
    &quot;problems&quot;: [
      {
        &quot;actions&quot;: [
          {
            &quot;from&quot;: &quot;0xbafB4E1EFA94B359e2E175CF6156AedA2cACa165&quot;,
            &quot;towards&quot;: {
              &quot;address&quot;: &quot;0x50840CE036eEf2005d3c4d6f6Eb65f8116a01629&quot;
            },
            &quot;with&quot;: [
              {
                &quot;symbol&quot;: &quot;USDC&quot;,
                &quot;amount&quot;: 5
              }
            ]
          },
          {
            &quot;from&quot;: &quot;0xbafB4E1EFA94B359e2E175CF6156AedA2cACa165&quot;,
            &quot;towards&quot;: {
              &quot;address&quot;: &quot;0xFCd239451346238B5560511Ae47A0b82b1bbE9f0&quot;
            },
            &quot;with&quot;: [
              {
                &quot;symbol&quot;: &quot;PLR&quot;,
                &quot;amount&quot;: 100
              }
            ]
          }
        ]
      }
    ]
  }
}
```

##### Response from Orchestrator

```json
{
  &quot;id&quot;: 1000,
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;result&quot;: [
    {
      &quot;name&quot;: &quot;Send 5 USDC to 0x...629 and 100 PLR to 0x...9f0&quot;,
      &quot;description&quot;: &quot;Send 5 USDC to 0x50840CE036eEf2005d3c4d6f6Eb65f8116a01629 and 100 PLR to 0xFCd239451346238B5560511Ae47A0b82b1bbE9f0&quot;,
      &quot;transactions&quot;: [
        {
          &quot;to&quot;: &quot;0x...&quot;,
          &quot;chainId&quot;: 1,
          &quot;calldata&quot;: &quot;0x0...&quot;,
          &quot;value&quot;: 0
        },
        {
          &quot;to&quot;: &quot;0x...&quot;,
          &quot;chainId&quot;: 1,
          &quot;calldata&quot;: &quot;0x...&quot;,
          &quot;value&quot;: 0
        }
      ]
    }
  ]
}
```

#### Calling a Smart Contract function on Polygon: Inscribing a message which costs 1 USDC

The following request performs an action:

- from 0xbafB4E1EFA94B359e2E175CF6156AedA2cACa165
- towards address 0x50840CE036eEf2005d3c4d6f6Eb65f8116a01629 on chain 137
- with 1 USDC
- calling &quot;inscribe&quot; with &quot;0x...&quot;

&gt; [!NOTE]
&gt; Notes: All requests for solutions should be chain abstracted (ChA¹) by default - HOWEVER in this
&gt; example, the `chainId` property on the `Destination` interface has been specified. The operation
&gt; should now be locked to the specified chain. Because `functionCallName` and `functionCallData`
&gt; exist, the Orchestrator can infer that this is a smart contract call and act accordingly.

##### Request to Orchestrator

```json
{
  &quot;id&quot;: 420,
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;method&quot;: &quot;orchestrator_findSolutions&quot;,
  &quot;params&quot;: {
    &quot;problems&quot;: [
      {
        &quot;actions&quot;: [
          {
            &quot;from&quot;: &quot;0xbafB4E1EFA94B359e2E175CF6156AedA2cACa165&quot;,
            &quot;towards&quot;: {
              &quot;address&quot;: &quot;0x50840CE036eEf2005d3c4d6f6Eb65f8116a01629&quot;,
              &quot;chainId&quot;: 137
            },
            &quot;with&quot;: [
              {
                &quot;symbol&quot;: &quot;USDC&quot;,
                &quot;amount&quot;: 1
              }
            ],
            &quot;functionCallName&quot;: &quot;inscribe&quot;,
            &quot;functionCallData&quot;: &quot;0x...&quot;
          }
        ]
      }
    ]
  }
}
```

##### Response from Orchestrator

```json
{
  &quot;id&quot;: 420,
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;result&quot;: [
    {
      &quot;name&quot;: &quot;Inscribe with 1 USDC&quot;,
      &quot;description&quot;: &quot;Call the Inscribe function with 1 USDC on Polygon&quot;,
      &quot;transactions&quot;: [
        {
          &quot;to&quot;: &quot;0x...&quot;,
          &quot;chainId&quot;: 137,
          &quot;calldata&quot;: &quot;0x0...&quot;,
          &quot;value&quot;: 0
        },
        {
          &quot;to&quot;: &quot;0x...&quot;,
          &quot;chainId&quot;: 137,
          &quot;calldata&quot;: &quot;0x...&quot;,
          &quot;value&quot;: 0
        }
      ]
    }
  ]
}
```

## Security Considerations

### Orchestrator reputation

The ability for anyone to build an Orchestrator inherently brings the opportunity for code errors and therefore a degraded service. Orchestrators may also be abandoned over time. A reputation score should be leveraged by the Orchestrator to determine if the Orchestrator is fit for purpose. This should be up to the requesting system or wallet to determine.

### Orchestrator producing dishonest solutions

An Orchestrator may return transactions as part of a solution that are wrong or attempt to take more than what was asked of it. Where possible, the Orchestrator should validate returned transaction address destinations and any other data.

### Orchestrator personality variations

Whilst not a security consideration per-se, some Orchestrators may gravitate towards their own business targets which may skew the outcome of Orchestrator solutions. The systems or wallets requesting solutions from Orchestrators should be mindful of this unless it is intended.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 07 Nov 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7845</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7845</guid>
      </item>
    
      <item>
        <title>Wallet Connection API</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7846-wallet-connection-api/22245</comments>
        
        <description>## Abstract

This ERC introduces a new wallet connection JSON-RPC method focused on extensibility, `wallet_connect`. It leverages the modular capabilities approach defined in [ERC-5792](/EIPs/EIPS/eip-5792#wallet_getcapabilities) to streamline connections and authentication into a single interaction.

## Motivation

With applications beginning to require support for more sophisticated functionality in wallet connection flows, the need for a unified and extensible wallet connection JSON-RPC method has become more apparent.

This is especially evident in the case of attempting to batch connection with authentication, where existing methods like `eth_requestAccounts` and `personal_sign` lack extensibility and require at least two separate user interactions (ie. connect and then sign).

## Specification

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

### JSON-RPC Methods

#### `wallet_connect`

Requests to connect account(s) with optional capabilities.

##### Request

```ts
type Request = {
  method: &apos;wallet_connect&apos;,
  params: [{
    // JSON-RPC method version.
    version: string;
    // Optional capabilities to request (e.g. Sign In With Ethereum).
    capabilities?: Record&lt;string, unknown&gt;;
  }]
}
```

##### Response

List of connected accounts with their associated capabilities.

```ts
type Response = {
  accounts: {
    // Address of the connected account.
    address: `0x${string}`;
    // Capabilities granted that is associated with this account.
    capabilities: Record&lt;string, unknown&gt;;
  }[]
}
```

##### Example

```ts
const response = await provider.request({
  method: &apos;wallet_connect&apos;,
  params: [{
    version: &apos;1&apos;,
    capabilities: {
      signInWithEthereum: {
        nonce: &apos;12345678&apos;,
        chainId: &apos;0x1&apos;
      }
    }
  }]
})
/**
 * {
 *   accounts: [
 *     {
 *       address: &apos;0x...&apos;,
 *       capabilities: {
 *         signInWithEthereum: {
 *           message: &apos;app.com wants you to sign in with your Ethereum account:\n0x...&apos;,
 *           signature: &apos;0x...&apos;
 *         }
 *       }
 *     }
 *   ]
 * }
 */
```

#### `wallet_disconnect`

Disconnects connected account(s).

- The wallet SHOULD revoke access to the user account(s) information, as well as to any capabilities associated with them that were granted upon connection via `wallet_connect`.

##### Request

```ts
type Request = {
  method: &apos;wallet_disconnect&apos;
}
```

##### Example

```ts
await provider.request({
  method: &apos;wallet_disconnect&apos;,
})
```

### Capabilities

#### `signInWithEthereum`

Adds support for offchain authentication using [ERC-4361](/EIPs/EIPS/eip-4361).

##### Parameters

Same as ERC-4361 specification with minor modifications: 
* The casing of multi-word fields has been adjusted to camelCase instead of kebab-case. Resources are an array field. 
* The account address returned by `wallet_connect` MUST match the address inferred in the Sign-In with Ethereum (SIWE) message.
* `version` is optional and defaults to an accepted version defined in ERC-4361 if not provided.
* `domain` is optional and defaults to the domain of the requesting app if not provided.
* `uri` is optional and defaults to the uri of the requesting app if not provided.
* `issuedAt` is optional and defaults to the current time if not provided.

The wallet MUST return a ERC-4361-formatted message that exactly matches the requested parameters and a signature over the [EIP-191](/EIPs/EIPS/eip-191) `personal_sign` hash of the message. The app SHOULD also verify that the two match for security.

```ts
type Parameters = {
  signInWithEthereum: {
    nonce: string;
    chainId: string; // EIP-155 hex-encoded
    version?: string;
    scheme?: string;
    domain?: string;
    uri?: string;
    statement?: string;
    issuedAt?: string;
    expirationTime?: string;
    notBefore?: string;
    requestId?: string;
    resources?: string[];
  }
}
```

##### Response

Formatted SIWE message and signature.

```ts
type Response = {
  signInWithEthereum: {
    // Formatted SIWE message.
    message: string;
    // Signature over the EIP-191 personal_sign hash of the message.
    signature: `0x${string}`;
  }
}
```

#### Example

```ts
const result = await provider.request({
  method: &apos;wallet_connect&apos;,
  params: [{
    version: &apos;1&apos;,
    capabilities: {
      signInWithEthereum: {
        nonce: &apos;12345678&apos;,
        chainId: &apos;0x1&apos;,
        version: &apos;1&apos;,
        domain: &apos;app.com&apos;,
        uri: &apos;https://app.com/connect&apos;,
        issuedAt: &apos;2024-12-35T04:20:00Z&apos;,
        expirationTime: &apos;2024-12-35T06:09:00Z&apos;
      }
    }
  }]
})
/**
 * {
 *   accounts: [
 *     {
 *       address: &apos;0x...&apos;,
 *       capabilities: {
 *         signInWithEthereum: {
 *           message: &apos;app.com wants you to sign in with your Ethereum account:\n0x...&apos;,
 *           signature: &apos;0x...&apos;
 *         }
 *       }
 *     }
 *   ]
 * }
 */
```

## Rationale

### Multiple Accounts

Returning multiple accounts allows greater generality for apps that wish to interact in more complex ways with users. This also improves our backwards compatibility with `eth_requestAccounts`. In practice, we expect most apps only interact with the first account in the array.

### Capability Results

Returning capability results alongside the connection unlocks many valuable use cases such as authentication, user metadata sharing, and permissions granted to the app.

### Initial Authentication Capability

To ensure immediate value, this proposal includes a capability that combines wallet connection with authentication using the widely adopted [Sign In With Ethereum (ERC-4361)](/EIPs/EIPS/eip-4361) standard. This optional capability simplifies the onboarding process for apps and users by combining two steps — connection and authentication — into a single interaction. Apps that prefer alternative authentication flows can implement their own capabilities without being constrained by this design.

By unifying connection and authentication into one step, apps can reduce friction, improve the user experience, and minimize redundant interactions.

## Backwards Compatibility

This standard builds on existing JSON-RPC methods and complements ERC-5792 for future extensibility. Wallets can continue supporting legacy methods.

## Security Considerations

Applies [ERC-4361 security principles](/EIPs/EIPS/eip-4361#security-considerations). As more capabilities are added, care must be taken to avoid unpredictable interactions.

Wallet addresses and any shared capabilities must be handled securely to avoid data leaks or man-in-the-middle attacks.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 15 Dec 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7846</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7846</guid>
      </item>
    
      <item>
        <title>Social Media NFTs</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7847-social-media-nfts/22280</comments>
        
        <description>## Abstract

This proposal defines a standardized format for representing decentralized social media posts as NFTs. The Nostr protocol has done most of the heavy lifting for creating an open decentralized social media network. This ERC serves to adapt those standards to the most common blockchain non-fungible token standard. In this way we can take advantage of the reach and longevity of a blockchain. It is genericized here so that it can be easily mapped to other event based decentralized social media like the AT protocol. An event can be used as a social media post, blog post, forum post, encrypted message, RSS feed or arbitrary electronic publication. This model is flexible where the meaning and type of an event (original, reply, repost, images, video, text, etc...) is derived from its metadata. A user is anyone who has a private key. There is no permission required and anyone can create content using any NFT contract. Anyone can collate that content into a feed or timeline.

Posts may be &quot;owned&quot; by their creators, but the owner of the NFT itself is not meaningful in the standard. This may be a useful mechanic for financial purposes, but the independent signature of the post allows for a third party to publish a message on behalf of another user.

## Motivation

With the continued censorship and manipulation of social media platforms, it becomes increasingly important for truly decentralized and permissionless social media to exist. Unlike other attempts at blockchain decentralized social media, this method does not rely on a centralized set of smart contracts. Blockchain integration of author-signed event based social media simply adds a powerful substrate for standardized decentralized social media to exist in. The benefits of blockchain include, but are not limited to, longevity, censorship resistance, monetary, and neutrality. The NFT standard is the most common and widely used standard for representing unique digital data on the blockchain. Using the NFT standard and standard NFT properties means that every marketplace, wallet and app that makes NFTs viewable is also a publication channel. With the data publicly available, custom feed algorithms can also be built to give control back to users.

## Specification

### To derive the id

To obtain the id, we sha256 the serialized attributes in this order. The serialization is done over the UTF-8 JSON-serialized string of the following structure:

```json
[
  0,
  &lt;pubkey, as a lowercase hex string&gt;,
  &lt;created_at, unix timestamp in seconds&gt;,
  &lt;kind, as a number&gt;,
  &lt;tags, as an array of arrays of non-null strings&gt;,
  &lt;content, as a string&gt;
]
```

**To prevent implementation differences from creating a different event ID for the same event, the following rules MUST be followed while serializing:**

- UTF-8 should be used for encoding.
- Preceding and trailing whitespace must be trimmed from serialized JSON and field values.
- If spaces are used in tags they must be single spaces within array values.
- The following characters in the content field must be escaped as shown, and all other characters must be included verbatim:
  - A line break (0x0A), use \n
  - A double quote (0x22), use \&quot;
  - A backslash (0x5C), use \\
  - A carriage return (0x0D), use \r
  - A tab character (0x09), use \t
  - A backspace, (0x08), use \b
  - A form feed, (0x0C), use \f

### Kinds

0: User metadata: the content is set to a stringified JSON object {name: `&lt;username&gt;`, about: `&lt;string&gt;`, picture: `&lt;url, string&gt;`} describing the user who created the event. Extra metadata fields may be set. A relay may delete older events once it gets a new one for the same pubkey.
1: Original content: original generated user content is usually accompanied by short-form text, but may include off-chain or on-chain references to other media or events.

### Tags

Tags are a flexible mechanism to attach additional structured data to a post. Each tag is an array of one or more strings, with some conventions around them.

- The blockchain tag is **recommended** for events published using this method.
  `[&quot;blockchain&quot;, &quot;&lt;blockchain-name-or-id&gt;&quot;, &quot;&lt;contract&gt;&quot;, &quot;&lt;token_id&quot;&gt;]`

where:

- `&lt;blockchain-name-or-id&gt;` is the name of the chain. e.g. &quot;Ethereum&quot;, &quot;Polygon&quot;, &quot;Base&quot; or chain id. e.g. &quot;1&quot;, &quot;137&quot;, &quot;8453&quot;
- `&lt;contract&gt;` is the contract address. e.g. &quot;0x0000000000000000000000000000000000000000&quot;
- `&lt;token_id&gt;` is the token id. e.g. &quot;12345&quot;. The token_id may be omitted if it is not known before publication as it is part of the signed data.

**Optional tags:**

- Multiple media tags can be attached by using multiple imeta tags `[&quot;imeta&quot;, ...]`

  ```json
  [&quot;imeta&quot;, 
    &quot;dim 1920x1080&quot;,
    &quot;url &lt;URL&gt;/1080/12345.mp4&quot;,
    &quot;m video/mp4&quot;,
  ]
  ```

- References to Other Posts:
  `[&quot;e&quot;, &quot;&lt;id_of_referenced_post&gt;&quot;]`

- Public addresses involved in this post:
  `[&quot;p&quot;, &quot;&lt;pubkey&gt;&quot;, ...]`

- External URLs:
  `[&quot;r&quot;, &quot;&lt;URL&gt;&quot;]`

### Metadata JSON

Event fields are stored in the NFT&apos;s metadata under `attributes`. The `description` field of the NFT is identical to `content`. The `name` may be user defined or include the author and time created. All attributes besides `id`, `pubkey`, `created_at`, `kind`, `sig`, and `content` are assumed to be event tags.

```json
{
  &quot;name&quot;: &quot;&lt;title of post&gt;&quot;,
  &quot;description&quot;: &quot;&lt;string should match the attribute content tag&gt;&quot;,
  &quot;image&quot;: &quot;&lt;optional usually the first m image tag&gt;&quot;,
  &quot;animation_url&quot;: &quot;&lt;optional use this for multi-media such as MP4, MP3, WAV, WEBM, etc... should be included in imeta tags as well&gt;&quot;,
  &quot;external_url&quot;: &quot;&lt;optional should be included in attribute r tags&gt;&quot;,
  &quot;attributes&quot;: [
    {
      &quot;trait_type&quot;: &quot;id&quot;,
      &quot;value&quot;: &quot;&lt;32-bytes lowercase hex-encoded sha256 of the serialized attribute data&gt;&quot;
    },
    {
      &quot;trait_type&quot;: &quot;pubkey&quot;,
      &quot;value&quot;: &quot;&lt;32-bytes lowercase hex-encoded public key of the public creator&gt;&quot;
    },
    {
      &quot;trait_type&quot;: &quot;created_at&quot;,
      &quot;value&quot;: &lt;unix timestamp in seconds&gt;
    },
    {
      &quot;trait_type&quot;: &quot;kind&quot;,
      &quot;value&quot;: &lt;integer between 0 and 65535&gt;
    },
    {
      &quot;trait_type&quot;: &quot;sig&quot;,
      &quot;value&quot;: &quot;&lt;64-bytes lowercase hex of the signature of the sha256 hash of the serialized attribute data, which is the same as the id field&gt;&quot;
    },
        {
      &quot;trait_type&quot;: &quot;content&quot;,
      &quot;value&quot;: &quot;&lt;this key should match the description even if empty string&gt;&quot;
    },
    {
      &quot;trait_type&quot;: &quot;imeta&quot;,
      &quot;value&quot;: &quot;&lt;optional imeta tags&gt;&quot;
    },
    {
      &quot;trait_type&quot;: &quot;e&quot;,
      &quot;value&quot;: &quot;&lt;optional ID of referenced event&gt;&quot;
    },
    {
      &quot;trait_type&quot;: &quot;r&quot;,
      &quot;value&quot;: &quot;&lt;optional reference to external URL&gt;&quot;
    },
    ...&lt;other_optional_attributes&gt;,
  ]
}
```

### Generating Keys

**Private key:** Any Ethereum private key or mnemonic phrase can be used, as long as the result is a 32-byte hex string. A key can be generated locally as well with a command like `openssl rand -hex 32`. This key is used to sign the post and is stored in the pubkey field.

**Public key:** Public keys are based on Taproot + Schnorr, bitcoin [BIP 341](https://github.com/bitcoin/bips/blob/5767f444995df378ad772887b739e84bd9002d95/bip-0341.mediawiki). It&apos;s recommended to use a tool like nostr-tools to generate a public key from a private key.

### Sign a post

Signatures are based on schnorr signatures standard for the curve secp256k1. To sign with Schnorr signatures on secp256k1, you need a private key, a message, and a random nonce (k). You then calculate a public nonce (R), a challenge (e), and finally, the signature (s) by combining these values. It&apos;s best to use a tool like nostr-tools or nostril or schnorr.c in the bitcoin core library.

### The PubEvent

### When a new post is created

```solidity
event PubEvent(
    bytes32 id,
    bytes32 indexed pubkey,
    uint256 created_at,
    uint32 indexed kind,
    string content,
    string tags,
    string sig,
);
```

- `id`: the unique identifier of the post.
- `pubkey`: the public key of the post creator.
- `created_at`: the timestamp of creation.
- `kind`: the event kind; 1, for an original post.
- `content`: the textual content of the post.
- `tags`: the structured metadata.
- `sig`: the signature of the post data. Should be 64 bytes.

### To reply to a post

```solidity
event PubEvent(
    bytes32 id,
    bytes32 indexed pubkey,
    uint256 created_at,
    uint32 indexed kind,
    string content,
    string tags,
    string sig
);
```

- `id`: The unique identifier of the post.
- `pubkey`: The public key of the post creator.
- `created_at`: The timestamp of creation.
- `kind`: Also 1 for replies.
- `content`: The textual content of the post.
- `tags`: The structured metadata including outlined below.
- `sig`: The signature of the post data. Should be 64 bytes.

### The reply &quot;e&quot; tag

`[&quot;e&quot;, &lt;event-id&gt;, &lt;relay-url&gt;, &lt;marker&gt;, &lt;pubkey&gt;]`

**Where:**

`&lt;event-id&gt;` is the id of the event being referenced.
`&lt;relay-url&gt;` optionally is the URL of a recommended off-chain relayer. Use empty string,&quot;&quot;, if none or on the blockchain only.
`&lt;marker&gt;` is optional and if present is one of &quot;reply&quot;, &quot;root&quot;, or &quot;mention&quot;.
`&lt;pubkey&gt;` is optional, SHOULD be the pubkey of the author of the referenced event

Those marked with &quot;reply&quot; denote the id of the reply event being responded to. Those marked with &quot;root&quot; can denote the root id of the reply thread being responded to. Those marked with &quot;mention&quot; denote a quoted or reposted event id.

`&lt;pubkey&gt;` SHOULD be the pubkey of the author of the e tagged event, this is used in the outbox model to search for that event from the author&apos;s write relays where relay hints did not resolve the event.

### The &quot;p&quot; tag

`[&quot;p&quot;, &lt;pubkey&gt;, ...]`
Used in a text event contains a list of pubkeys used to record who is involved in a reply thread.

When replying to a text event E the reply event&apos;s &quot;p&quot; tags can contain all of E&apos;s &quot;p&quot; tags as well as the &quot;pubkey&quot; of the event being replied to.

Example: Given a text event authored by a1 with &quot;p&quot; tags [p1, p2, p3] then the &quot;p&quot; tags of the reply can be [a1, p1, p2, p3] in no particular order.

### Reposts

A repost is a kind 6 event that is used to signal to followers that a kind 1 text post is worth reading.

The content of a repost event is the stringified JSON of the reposted post. It MAY also be empty, but that is not recommended.

The repost event MUST include an e tag with the id of the post that is being reposted. That tag should include a blockchain tag or indexer relay where the post can be fetched.

The repost SHOULD include a p tag with the pubkey of the event being reposted.

### Quote Reposts

Quote reposts are kind 1 events with an embedded q tag of the post being quote reposted. The q tag ensures quote reposts are not pulled and included as replies in threads. It also allows you to easily pull and count all of the quotes for a post.

q tags should follow the same conventions as e tags, with the exception of the mark argument.

`[&quot;q&quot;, &lt;event-id&gt;, &lt;relay-url&gt;, &lt;pubkey&gt;, &lt;blockchain-name-or-id&gt;]`

## Rationale

These attributes in the metadata are a 1:1 mapping of a Nostr-style event. Nostr is a blockchain compatible social media protocol because it uses a public/private key verification system that does not rely on a central set of smart contracts. It relies on the same format of private key EVM chains already use. It has a json based event system that is easily mapped to NFTs. Content can be freely moved between web3 and web2 based platforms. Each post is signed by the author, enabling tamperproof third-party transportation and publishing. A standardized tagging system enables referencing posts on other blockchains, other contracts, or external URLs.

## Reference Implementation

Only the metadata format and PubEvent is required.

```solidity
function createPost(
  uint256 tokenId,
  string uri,
  bytes32 id,
  bytes32 pubkey,
  uint256 created_at,
  uint32 kind,
  string content,
  string tags,
  string sig
) public {

  mint(tokenId, uri);
  emit PubEvent(id, pubkey, created_at, kind, content, tags, sig);
}

```

In this example `PubEvent` is **required** to announce a publication event has occurred. This event is flexible and can be used for all event types and kinds.

### Token Standards Compatibility

- **[ERC-721](/EIPs/EIPS/eip-721):** Each post should be a unique (`tokenId`).
- **[ERC-1155](/EIPs/EIPS/eip-1155):** A `tokenId` should only represent one post event even if minted multiple times.

#### Backwards Compatibility

This is an additive standard on top of [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155). Existing NFTs remain compatible; clients or platforms that understand this standard can interpret these tokens as social posts as well as traditional NFTs.

## Security Considerations

**Data Integrity:**
Ensure that id is consistently [derived, as described above](#to-derive-the-id), to prevent forgeries. The owner of an NFT is inconsequential to the authenticity of the post, if the post is properly signed.

### Spam and Moderation

Event driven social media and NFTs both allow permissionless creation of content. Platforms built on this standard should implement their own moderation layers, blocklists, or reputation systems.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 18 Dec 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7847</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7847</guid>
      </item>
    
      <item>
        <title>On-chain upgrade signaling</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7848-on-chain-upgrade-signaling/22306</comments>
        
        <description>## Abstract

This proposal adds a mechanism for clients to signal their willingness for a network upgrade by including a “reference implementation hash” field in each block. A network upgrade activates only if enough blocks specify that they are using the new software.

## Motivation

Currently, upgrades to Ethereum Mainnet are announced on the ethereum.org blog. This proposal changes that process by activating upgrades based on the consent of network participants.

## Specification

Ethereum consensus clients shall identify with a reference implementation having its equivalent behaviors.

Ethereum consensus clients shall include a `referenceImplementationHash` (specified below) field immediately following the `extraData` field in the block header.

Proposed new Ethereum consensus clients shall initially behave as the then-current network does. If, and only if, a successful upgrade (defined below) is activated will the new behavior take effect.

When a network participant is willing to support a network upgrade, they shall immediately begin using the new software. The blocks they create including the new `referenceImplementationHash` will contribute to the network upgrade activation.

### The Reference Implementation Hash

When proposing a network upgrade, the proposer shall point to a published, feature-complete reference implementation including the new software behaviors.

The **reference implementation hash** is the SHA-256 hash of the tarred source code of this reference implementation.

### Verification

Network participants shall study the reference implementation and decide whether they support an upgrade.

Network participants shall study any specific software they will run and ensure it faithfully implements the behaviors consistent with that reference implementation.

### Upgrade

Upgrade proposals (often referred to as hard fork EIPs) must specify an upgrade window and threshold. These parameters are implemented in the consensus client:

- `VOTING_WINDOW_BEGIN`: the first block (inclusive) to count votes.
- `VOTING_WINDOW_END`: the last block (inclusive) to count votes.
- `REFERENCE_IMPLEMENTATION_HASH`: this is defined above.
- `REQUIRED_APPROVALS`: the minimum number of approvals necessary for the upgrade.

The difference (`VOTING_WINDOW_END` - `VOTING_WINDOW_BEGIN`) must be strictly greater than 14400 (about two days) and should be chosen to provide sufficient time to advertise the upgrade to network participants.

The required approvals must be strictly greater than 50% of the blocks in the voting window. A higher threshold (such as 95% or more) is recommended.

When the block numbered `VOTING_WINDOW_END` is created, the upgrade is considered &quot;activated&quot; if `REQUIRED_APPROVALS` or more blocks during the voting window had set `referenceImplementationHash` to the value `REFERENCE_IMPLEMENTATION_HASH`; otherwise, the upgrade fails.

Blocks created from `VOTING_WINDOW_END` + 1 onward will use the new software behaviors if and only if the upgrade was successful.

For proof-of-work networks and other scenarios, it is possible that one fork activates the upgrade while another does not. In any case, blocks strictly greater than `VOTING_WINDOW_END` shall be created according to the behaviors of the software considering the outcome of the votes in the voting window which are the ancestors of that block.

Note: Just because an upgrade was activated, this does not necessarily mean that the new software behaviors must generate block `VOTING_WINDOW_END` + 1 differently than the old software behaviors. Perhaps the new software behaviors will stipulate that only blocks at some later time will generate differently. Perhaps the new software behaviors include some other consensus change which does not change how blocks are created.

## Rationale

### Forking is no Longer Possible

Since the merge, forking Ethereum Mainnet has become practically impossible. Validators stake valuable assets to participate in the network, so any rational validator will choose to upgrade only if they expect widespread adoption. If a validator expects 95% or more participants to upgrade, they should upgrade; if they expect only 5% or less, they should not. For intermediate cases, there is a threshold where a validator would rationally shut down (incurring a small penalty) rather than risk participating in the wrong network—which could result in slashing 100% of their staked ether (currently 16 Ether per share).

Therefore, proper management of consensual upgrades is crucial.

### Community Direction

1. The Ethereum project and community do not have an official mission statement or vision. However, this proposal asserts that the Ethereum community would prefer Ethereum Mainnet to be a community-directed project.
2. On-chain signaling of upgrades enables community direction in a way that is not possible today.


### Window

Using a voting window to count votes provides real-time on-chain feedback about upgrade readiness. The upgrade is activated only after the successful completion of the voting window.

## Backwards Compatibility

### Trademark

The Ethereum Foundation (Stiftung Ethereum), Zug, Switzerland, owns the trademark “Ethereum.” As a result, if anybody publishes a proposed Ethereum Mainnet consensus client, the foundation may have the right to restrict marketing of that software as an “Ethereum” client. That also poses unique risks related to securities rules.

### EIP-2124

EIP-2124 introduces a mechanism to communicate software versions between nodes. However, it does not allow for signaling readiness before an upgrade, nor does it specify what software is being upgraded to.


## Security Considerations

Any upgrade that achieves less than 100% participation will harm validators who do not participate.

- Overlapping or competitive upgrades must be managed carefully; such scenarios could result in multiple networks achieving the minimum approval threshold.
- An upgrade with an excessively long time period could hinder/delay the proposal of subsequent upgrades.
- Since the four voting parameters are embedded in the reference implementation, network participants must exercise due diligence to ensure that they understand the actual software behaviors.

## Copyright

Copyright and related rights have been waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 22 Dec 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7848</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7848</guid>
      </item>
    
      <item>
        <title>Deactivate a Delegated EOA&apos;s Key</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7851-deactivate-reactivate-a-delegated-eoas-key/22344</comments>
        
        <description>## Abstract

This EIP introduces a system contract that enables an [EIP-7702](./eip-7702) delegated EOA to schedule an irreversible deactivation of its ECDSA private key for ECDSA-authenticated transaction sending and [EIP-7702](./eip-7702) authorizations. Deactivation uses a 7-day delay (cancellation window). After finalization, the key is permanently deactivated in-protocol. The system contract mapping serves as the single source of truth for key status.

## Motivation

[EIP-7702](./eip-7702) enables EOAs to gain smart contract wallet behavior, but the EOA&apos;s ECDSA key retains unrestricted signing authority that can override any delegated contract logic. This EIP provides a one-way migration path toward smart contract control, including post-quantum migration strategies, by allowing a delegated EOA to permanently disable its ECDSA transaction-signing authority after a safety delay.

## Specification

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

### Parameters

| Constant                          | Value                        |
|-----------------------------------|------------------------------|
| `SYSTEM_CONTRACT_ADDRESS`         | `0xTBD`                      |
| `DEACTIVATION_DELAY`              | `604800` (7 days in seconds) |

### System Contract

The system contract is deployed at `SYSTEM_CONTRACT_ADDRESS` following the same mechanism as [EIP-4788](./eip-4788) and [EIP-2935](./eip-2935): a pre-signed deployment transaction using Nick&apos;s method is included at fork activation. Deployment parameters TBD.

#### Status Semantics

Let `ts = finalizationTimestamp[account]`:

| Condition                                                                                          | Status          | `status()` Return Value |
|----------------------------------------------------------------------------------------------------|-----------------|-------------------------|
| `ts == 0`                                                                                          | **ACTIVE**      | `0`                     |
| `ts &gt; 0 AND block.timestamp &lt; ts`                                                                  | **PENDING**     | `1`                     |
| `ts &gt; 0 AND block.timestamp &gt;= ts AND account has` [EIP-7702](./eip-7702) `delegation designation` | **DEACTIVATED** | `2`                     |
| `ts &gt; 0 AND block.timestamp &gt;= ts AND account has no` [EIP-7702](./eip-7702) `delegation`          | **DORMANT**     | `3`                     |

**DEACTIVATED** indicates that the deactivation is finalized and currently enforced at the protocol level: the account is delegated and the [transaction validation](#transaction-validation) check rejects ECDSA-authenticated transactions and authorizations. **DORMANT** indicates that the deactivation has finalized in storage but is not currently enforced because the account&apos;s [EIP-7702](./eip-7702) delegation has been revoked. Re-delegating a **DORMANT** account will cause deactivation to take effect immediately and irreversibly; see [Delegation Revocation During Pending Period](#delegation-revocation-during-pending-period).

#### deactivate()

- MUST revert if `msg.sender` is not an [EIP-7702](./eip-7702) delegated EOA (code does not start with `0xef0100`).
- MUST revert if `finalizationTimestamp[msg.sender] != 0`.
- MUST set `finalizationTimestamp[msg.sender] = uint64(block.timestamp) + DEACTIVATION_DELAY`.

#### cancel()

- MUST revert if `finalizationTimestamp[msg.sender] == 0`.
- MUST revert if `block.timestamp &gt;= finalizationTimestamp[msg.sender]` (already finalized).
- MUST set `finalizationTimestamp[msg.sender] = 0`.

Note: `cancel()` intentionally omits the delegation check. This ensures an EOA that has revoked its delegation can still cancel a pending deactivation during the delay period, preventing accidental lockout.

### Storage Layout

The `finalizationTimestamp` mapping is at storage slot `0`. The storage key for a given `account` is:

```solidity
keccak256(abi.encode(account, uint256(0)))
```

The value is interpreted as a `uint64` timestamp.

### Transaction Validation

For any sender or authority address `S` whose code is an [EIP-7702](./eip-7702) delegation designation (23 bytes starting with `0xef0100`), clients MUST read `ts` from the system contract&apos;s storage at `SYSTEM_CONTRACT_ADDRESS` using the key defined in [Storage Layout](#storage-layout) (i.e., `keccak256(abi.encode(S, uint256(0)))`), interpreted as a `uint64` timestamp. The key is considered **deactivated** when `ts != 0` AND `block.timestamp &gt;= ts`.

This check MUST be applied in the following contexts:

- **Block processing**: During transaction validity checks, if the transaction sender&apos;s key is deactivated, the transaction MUST NOT be included in blocks.
- **EIP-7702 authorizations**: During [EIP-7702](./eip-7702) authorization validation, if the authority&apos;s key is deactivated, the authorization MUST be treated as invalid and skipped.
- **Transaction pool**: The transaction pool MUST reject new transactions from a deactivated sender, evaluated against the current head block&apos;s timestamp. The pool SHOULD evict already-pooled transactions once the sender is observed deactivated. After a reorg that undoes deactivation, previously dropped transactions MAY be re-accepted if re-gossiped; implementations are NOT REQUIRED to retain them.

Because each deactivation check requires reading `finalizationTimestamp` from `SYSTEM_CONTRACT_ADDRESS` storage, `PER_AUTH_BASE_COST` as defined in [EIP-7702](./eip-7702) MUST be increased by `COLD_SLOAD_COST` (2100 gas) to cover the per-authority storage read. The one-time cold access to the system contract is absorbed by the base intrinsic gas (21000 gas).

## Rationale

Following the system contract pattern of [EIP-4788](./eip-4788), [EIP-2935](./eip-2935), and [EIP-7002](./eip-7002), this EIP uses a system contract to consolidate deactivation, cancellation, and status queries into a single on-chain entry point. Alternatives considered:

- **Account-state field**: adding a `timestamp` field in account state requires account RLP encoding and p2p protocol changes.
- **Reusing existing account fields**: deactivation status could be encoded into the nonce or appended to the delegated EOA&apos;s 23-byte code. However, the delay mechanism requires storing a finalization timestamp. A nonce is an incrementing counter and a delegation designator is a code prefix. Neither is designed to carry a timestamp, and forcing one in complicates their original validation logic.
- **Precompile**: persisting per-account state through a precompile is difficult because precompiles have no storage access mechanism. Adding one would make protocol design and client implementations more complex, introduce a larger testing surface, and increase the likelihood of unexpected edge cases compared to reusing the established system contract pattern. Alternatively the state could be embedded in the account object, which falls back to the account-state field problem above.

Deactivation is intentionally irreversible. Allowing ECDSA key reactivation would defeat the post-quantum security guarantee. The 7-day delay provides a safety window for users who may have triggered deactivation accidentally or who detect an unauthorized deactivation attempt. During the delay period, the original ECDSA key can still cancel the deactivation.

## Backwards Compatibility

No backwards compatibility issues. Deactivation state is maintained entirely within the system contract.

## Reference Implementation

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.24;

contract EIP7851KeyDeactivation {
    mapping(address =&gt; uint64) public finalizationTimestamp;

    uint64 public constant DEACTIVATION_DELAY = 604800; // 7 days in seconds

    uint8 internal constant ACTIVE = 0;
    uint8 internal constant PENDING = 1;
    uint8 internal constant DEACTIVATED = 2;
    uint8 internal constant DORMANT = 3;

    error NotDelegatedEOA();
    error NotScheduled();
    error AlreadyScheduled();
    error AlreadyDeactivated();
    error AlreadyFinalized();

    event DeactivationScheduled(address indexed account, uint64 finalizationTimestamp);
    event DeactivationCancelled(address indexed account);

    receive() external payable {
        revert();
    }

    function deactivate() external {
        if (!_has7702DelegationPrefix(msg.sender)) revert NotDelegatedEOA();

        uint64 ts = finalizationTimestamp[msg.sender];
        if (ts != 0) {
            if (block.timestamp &gt;= ts) revert AlreadyDeactivated();
            revert AlreadyScheduled();
        }

        uint64 ft = uint64(block.timestamp) + DEACTIVATION_DELAY;
        finalizationTimestamp[msg.sender] = ft;
        emit DeactivationScheduled(msg.sender, ft);
    }

    function cancel() external {
        uint64 ts = finalizationTimestamp[msg.sender];
        if (ts == 0) revert NotScheduled();
        if (block.timestamp &gt;= ts) revert AlreadyFinalized();

        delete finalizationTimestamp[msg.sender];
        emit DeactivationCancelled(msg.sender);
    }

    function status(address account) external view returns (uint8) {
        uint64 ts = finalizationTimestamp[account];
        if (ts == 0) return ACTIVE;
        if (block.timestamp &lt; ts) return PENDING;
        if (_has7702DelegationPrefix(account)) return DEACTIVATED;
        return DORMANT;
    }

    function _has7702DelegationPrefix(address account) internal view returns (bool) {
        bytes memory code = account.code;
        return code.length == 23 &amp;&amp; code[0] == 0xef &amp;&amp; code[1] == 0x01 &amp;&amp; code[2] == 0x00;
    }
}
```

## Security Considerations

### Contracts Using ECDSA Signatures

Deployed contracts using ECDSA signatures (e.g., `permit` of [ERC-2612](./eip-2612)) will not automatically respect deactivation. New or upgradeable contracts SHOULD call the system contract&apos;s `status()` and reject signatures from addresses in the **DEACTIVATED** state.

For non-upgradeable contracts, the above method cannot be applied directly. The only clear path available, at the protocol level, is to modify `ecRecover` precompiled contract: if the private key of the recovered address is deactivated, the `ecRecover` precompiled contract could return a precompile contract error (or, if not adding an error return path, return a zero address or a collision-resistant address, such as `0x1`). This is complemented by a companion EIP that mitigates `ecRecover`-related risks by making the precompile aware of private key deactivation status.

### Irreversible Deactivation by Design

Deactivation is intentionally irreversible at the protocol level to provide post-quantum security guarantees. Users should understand that once the 7-day delay period has passed, their ECDSA key cannot be reactivated. The 7-day delay provides a safety window for users to cancel if needed.

### 7-Day Delay Security

During the 7-day delay period, the original ECDSA key can cancel the deactivation. This is intentional as it provides a safety mechanism against unauthorized deactivation attempts. However, if an attacker has access to the ECDSA key during the delay period, they can also cancel the deactivation. Users who suspect key compromise should take immediate action to secure their account through other means.

### Delegation Revocation During Pending Period

Because transaction validation only applies to delegated EOAs, revoking delegation while a deactivation is pending causes the enforcement check to stop applying. The user can continue to use the ECDSA key as a regular EOA and can cancel the pending deactivation via a direct transaction to `cancel()`, which intentionally omits the delegation check.

However, if the `finalizationTimestamp` has already passed (i.e., the deactivation has finalized in storage), `cancel()` can no longer be called. In this state, re-delegating the account via [EIP-7702](./eip-7702) will cause the deactivation to take effect immediately and irreversibly, because the delegation designation re-enables the validation check. Users who have a finalized deactivation in storage should be aware that any future re-delegation will permanently disable their ECDSA key, because the delegation designation re-enables the validation check. If re-delegation is intended, users SHOULD ensure the target contract is trusted, as the account will become entirely dependent on it for all future operations.

### Replay Protection

For deactivation via EOA-signed transactions, nonces and [EIP-155](./eip-155) chain IDs provide replay protection. For deactivation via delegated contracts, the contract SHOULD implement its own replay-protection mechanisms, especially when the EOA is delegated to the same implementation across multiple chains.

### Mempool and Reorg Considerations

Implementations SHOULD be aware that evicting transactions immediately upon deactivation may cause issues if the deactivation is reverted in a reorg. The SHOULD (rather than MUST) language for eviction provides flexibility.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 27 Dec 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7851</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7851</guid>
      </item>
    
      <item>
        <title>Chain-Specific Payment Requests</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/add-erc-chain-specific-payment-requests/22379</comments>
        
        <description>## Abstract

This EIP proposes a standardized URI scheme for chain-specific payment requests, enabling users to specify transactions in the form &quot;send me X tokens of type Y on chain Z&quot;. The URI format includes essential components such as the recipient&apos;s blockchain account, the amount of tokens, the token contract address, and optional success and error callback URLs. This standard aims to eliminate ambiguity in multi-chain payment requests, ensuring clarity and accuracy in peer-to-peer transactions and vendor or dApp requests across different blockchain networks.

## Motivation

The ongoing expansion of the Ethereum network into a multi-chain ecosystem has introduced complexities regarding the execution of payment requests. Users and developers currently face a lack of clarity on which chain a payment request should be fulfilled, particularly when similar assets exist across multiple chains. This ambiguity complicates peer-to-peer transactions and vendor or dApp requests, leading to inefficiencies and a higher potential for errors. This standard will ensure that payment requests are clearly understood and correctly executed, regardless of the chain, thus significantly enhancing the user experience in a multi-chain environment.

## Specification

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

The format of the payment request URI is:

```txt
cspr://&lt;recipient&gt;/&lt;amount&gt;/&lt;token-address&gt;?on-success=&lt;success-callback-url&gt;&amp;on-error=&lt;error-callback-url&gt;
```

- `cspr://` - [REQUIRED] Short for &quot;Chain-Specific Payment Request&quot;. Indicates a blockchain-based payment request.
- `&lt;recipient&gt;` - [REQUIRED] The blockchain account requesting the payment (represented as a CAIP-10 account identifier).
- `&lt;amount&gt;` - [REQUIRED] The amount of tokens to be sent, specified as an integer or decimal number.
- `&lt;token-address&gt;` - [REQUIRED] The contract address of the [ERC-20](./eip-20) token to send (represented as a base64 encoded string). The special value `native` can be used to request the native currency of the specified chain (if the chain supports a native currency).
- `&lt;success-callback-url&gt;` - [OPTIONAL] The URL to redirect the user to after the transaction is confirmed.
- `&lt;error-callback-url&gt;` - [OPTIONAL] The URL to redirect the user to after the transaction fails.

### Examples

#### Requesting 1 eth on Base Mainnet to address `0x1111111111111111111111111111111111111111` with a specified success callback URL:

```txt
cspr://eip155:8453:0x1111111111111111111111111111111111111111/1/native?on-success=https://example.com
```

#### Requesting 0.5 BTC on Bitcoin mainnet:

```txt
cspr://bip122:000000000019d6689c085ae165831e93:128Lkh3S7CkDTBZ8W7BbpsN3YYizJMp8p6/0.5/native
```

#### Requesting 100 USDC on Ethereum Mainnet:

```txt
cspr://eip155:1:0xab16a96D359eC26a11e2C2b3d8f8B8942d5Bfcdb/100/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
```

### Error Handling

Wallets or applications parsing these URIs MUST validate the format of the recipient account. If any component of the URI does not meet the specified requirements or format, an error should be displayed to the user.

## Rationale

The design of this URI standard for blockchain-based payment requests addresses the need for a clear and unambiguous method to initiate transactions across multiple Ethereum chains, including mainnet and various Layer 2 networks. The rationale for each component of the URI structure is as follows:

- **`cspr://` Prefix:** This prefix explicitly identifies the URI as a blockchain-based payment request, ensuring systems recognize and correctly handle these URIs. It follows the precedent of other protocol-specific URI schemes like `mailto://` for email and `http://` for web links.
- **Recipient:** The recipient is specified using a CAIP-10 account identifier, a standardized format for representing blockchain addresses. With CAIP-10, you can easily identify the recipient’s blockchain network and corresponding address, regardless of the underlying address conventions.
- **Amount Specification:** Specifying the amount in the URI clarifies the transaction&apos;s intent, allowing users to verify the amount before sending. This helps prevent mistakes and fraud. The amount is specified as an integer or decimal number for clarity, precision, and ease of verification.
- **Token Address:** Requiring the token address ensures the URI specifies the exact token to be sent, eliminating ambiguity. It supports both ERC-20 tokens and the native currency of a chain (if supported).
- **Callback URLs:** Including callback URLs allows redirection to a specified URL after the transaction is confirmed or fails, enhancing the user experience by providing a seamless return to the application or website.

The token address in this URI standard is represented as a base64 encoded string to support both EVM and non-EVM chains, as all current address schemes are a subset of base64.

### Alternative Designs Considered:

- Including Transaction Parameters: Additional transaction parameters (e.g., gas limit, gas price) were considered but are recommended to be handled by the user&apos;s wallet application to keep the URI scheme focused on payment requests and avoid overloading the user with technical details.
- Token Parameter Optionality: Initially, the token parameter was considered optional, with its omission implying the native currency of the specified chain. However, not all chains support a native currency, so requiring explicit token specification increases clarity and reduces potential errors.
- An `ethereum://` prefix: Initially proposed as a standardized URI scheme for the Ethereum ecosystem, the `ethereum://` prefix aimed to provide a consistent identifier. However, to accommodate non-EVM chains, it is more practical to use a more generic identifier that is not limited to Ethereum.
- ENS Support: We initially considered adding optional ENS support, but determined it was unnecessary. Because the URI scheme isn’t user-facing, including ENS would add unneeded complexity without providing tangible benefits. Additionally, ENS names that resemble addresses introduce potential security risks. Instead, adhering to the CAIP-10 standard for chain-specific account identifiers is a more practical choice.

### Related Work

[ERC-681](./eip-681) is a related standard that defines a similar URI scheme for specifying token transfers in Ethereum. However, ERC-681 includes additional parameters for specifying transaction details, which were deemed unnecessary for the scope of this standard. The focus of this EIP is on simplicity and clarity in payment request specifications, with the expectation that transaction details will be handled by the user&apos;s wallet application.

[ERC-831](./eip-831) is another related standard that specifies a URI format for Ethereum. Instead of focusing exclusively on Ethereum and its rollups, this EIP is designed to be compatible with all blockchains. The primary distinction lies in the selection of the URI identifier.

## Backwards Compatibility

Due to the unique choice in URI prefix, this EIP is not backwards compatible with ERC-681 or ERC-831.

## Security Considerations

As there are many similarities to ERC-681, all the same security considerations apply and have been summarized below.

The security and trustworthiness of URLs are crucial, especially since they can trigger irreversible transactions. Altering the recipient&apos;s address or the transaction amount can lead to significant financial gain for attackers. Therefore, users should only trust URLs from verified and secure sources.

To ensure the transaction amount matches the user&apos;s intention, it should be clearly and easily verifiable by the user, including its magnitude. For ERC-20 token transactions, if the payer&apos;s client can access the blockchain or another reliable source for token contract details, the interface should present the amount in the token&apos;s specified units. If not, it should show the amount as stated in the URL, potentially warning the user about the uncertainty of the unit. Using scientific notation with an exponent that matches the token&apos;s nominal unit (e.g., 18 for ether) is recommended to aid user verification.

Validate callback URLs rigorously to prevent redirection to phishing sites. Wallet developers should follow browser security best practices for URL validation.

Wallet applications must recognize chains that lack native currency support and should block native currency payment requests on these chains.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 01 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7856</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7856</guid>
      </item>
    
      <item>
        <title>AI Agents NFT with Private Metadata</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7857-an-nft-standard-for-ai-agents-with-private-metadata/22391</comments>
        
        <description>## Abstract

A standard interface for NFTs specifically designed for AI agents, where the metadata represents agent capabilities and requires privacy protection. Unlike traditional NFT standards that focus on static metadata, this standard introduces mechanisms for verifiable data ownership and secure transfer. By defining a unified interface for different verification methods (e.g., Trusted Execution Environment (TEE), Zero-Knowledge Proof (ZKP)), it enables secure management of valuable agent metadata such as models, memory, and character definitions, while maintaining confidentiality and verifiability.

## Motivation

With the increasing intelligence of AI models, agents have become powerful tools for automating meaningful daily tasks. The integration of agents with blockchain technology has been recognized as a major narrative in the crypto industry, with many projects enabling agent creation for their users. However, a crucial missing piece is the decentralized management of agent ownership.

AI agents possess inherent non-fungible properties that make them natural candidates for NFT representation:

1. Each agent is unique, with its own model, memory, and character
2. Agents embody clear ownership rights, representing significant computational investment and intellectual property
3. Agents have private metadata (e.g., neural network models, memory, character definitions) that defines their capabilities

However, current NFT standards like [ERC-721][erc721] are insufficient for representing AI agents as digital assets. While NFTs can establish ownership of digital items, using them to represent AI agents introduces unique challenges. The key issue lies in the metadata transfer mechanism. Unlike traditional NFTs where metadata is typically static and publicly accessible, an AI agent&apos;s metadata (which constitutes the agent itself):

1. Has intrinsic value and is often the primary purpose of the transfer
2. Requires encrypted storage to protect intellectual property
3. Needs privacy-preserving and verifiable transfer mechanisms when ownership changes

For example, when transferring an agent NFT, we need to ensure:

1. The actual transfer of encrypted metadata (the agent&apos;s model, memory, character, etc.) is verifiable
2. The new owner can securely access the metadata that constitutes the agent
3. The agent&apos;s execution environment can verify ownership and load appropriate metadata

This EIP introduces a standard for NFTs with private metadata that addresses these requirements through privacy-preserving verification mechanisms, enabling secure ownership and transfer of valuable agent data while maintaining confidentiality and verifiability. This standard will serve as a foundation for the emerging agent ecosystem, allowing platforms to provide verifiable agent ownership and secure metadata management in a decentralized manner.

## Specification

The EIP defines three key interfaces: the main NFT interface, the metadata interface, and the data verification interface.

### Data Verification System

The verification system consists of two core components that work together to ensure secure data operations:

1. **On-chain Verifier (data verification interface)**
   - Implemented as a smart contract
   - Verifies proofs submitted through contract calls
   - Returns structured verification results
   - Can be implemented using different verification mechanisms (TEE/ZKP)

2. **Off-chain Prover**
   - Generates proofs for ownership and availability claims
   - Works with encrypted data and keys
   - Implementation varies based on verification mechanism:
     * TEE-based: Generates proofs within trusted hardware
     * ZKP-based: Creates cryptographic zero-knowledge proofs

The system supports two types of proofs:

1. **Ownership Proof**
   - Generated by Prover with access to original data
   - Proves knowledge of pre-images for claimed dataHashes
   - Verified on-chain through `verifyOwnership()`

2. **Transfer Validity Proof**
   - Generated by Prover for data transfers
   - Proves:
     * Knowledge of original data (pre-images)
     * Correct decryption and re-encryption of data
     * Secure key transmission (using receiver&apos;s public key to encrypt the new key)
     * Data availability in storage (using receiver&apos;s signature to confirm the data is available in storage)
   - Verified on-chain through `verifyTransferValidity()`

The ownership verification is optional because when the minted token is transferred or cloned, the ownership verification is checked again inside the availability verification. It&apos;s better to be safe than sorry, so we recommend doing ownership verification for minting and updates.

Different verification mechanisms have distinct capabilities:

- **TEE-based Implementation**
  * Prover runs in trusted hardware
  * Can handle private keys securely
  * Enables direct data re-encryption
  * Verifier checks TEE attestations

- **ZKP-based Implementation**
  * Prover generates cryptographic proofs
  * Cannot handle multi-party private keys
  * Re-encryption key known to prover
  * Requires additional re-encryption when next update, otherwise the new update is still visible to the prover

### Data Verification Interface

```solidity
/// @notice The type of the oracle
/// There are two types of oracles: TEE and ZKP
enum OracleType {
    TEE,
    ZKP
}

/// @notice The access proof which is a signature signed by the receiver (the receiver may delegate the signing privilege to the access assistant)
/// @param oldDataHash The hash of the old data
/// @param newDataHash The hash of the new data
/// @param nonce The nonce of the access proof
/// @param encryptedPubKey The encrypted public key, the receiver&apos;s public key which used to encrypt the new data key. `encryptedPubKey` can be empty in `accessProof`, and means that use the receiver&apos;s ethereum public key to encrypt the new data key
/// @param proof The proof
struct AccessProof {
    bytes32 oldDataHash;
    bytes32 newDataHash;
    bytes nonce;
    bytes encryptedPubKey;
    bytes proof;
}

/// @notice The ownership proof which is a signature signed by the receiver (the receiver may delegate the signing privilege to the access assistant)
/// @param proofType The type of the proof
/// @param oldDataHash The hash of the old data
/// @param newDataHash The hash of the new data
/// @param sealedKey The sealed key of the new data key
/// @param encryptedPubKey The encrypted public key, the receiver&apos;s public key which used to encrypt the new data key
/// @param nonce The nonce
struct OwnershipProof {
    OracleType oracleType; // The type of the oracle
    bytes32 oldDataHash; // The hash of the old data
    bytes32 newDataHash; // The hash of the new data
    bytes sealedKey; // The sealed key of the new data key
    bytes encryptedPubKey; // The encrypted public key, the receiver&apos;s public key which used to encrypt the new data key
    bytes nonce; // The nonce
    bytes proof; // The proof
}

struct TransferValidityProof {
    AccessProof accessProof;
    OwnershipProof ownershipProof;
}

struct TransferValidityProofOutput {
    bytes32 oldDataHash;
    bytes32 newDataHash;
    bytes sealedKey;
    bytes encryptedPubKey;
    bytes wantedKey;
    address accessAssistant;
    bytes accessProofNonce;
    bytes ownershipProofNonce;
}

interface IERC7857DataVerifier {
    /// @notice Verify data transfer validity, the _proofs prove:
    ///         1. The pre-image of oldDataHashes
    ///         2. The oldKey (old data key) can decrypt the pre-image and the new key re-encrypt the plaintexts to new ciphertexts
    ///         3. The newKey (new data key) is encrypted using the encryptedPubKey
    ///         4. The hashes of new ciphertexts is newDataHashes
    ///         5. The newDataHashes identified ciphertexts are available in the storage: need the signature from the receiver or the access assistant signing oldDataHashes, newDataHashes, and encryptedPubKey
    /// @param _proofs Proof generated by TEE/ZKP
    function verifyTransferValidity(
        TransferValidityProof[] calldata _proofs
    ) external returns (TransferValidityProofOutput[] memory);
}
```

### Metadata Interface

```solidity
struct IntelligentData {
    string dataDescription;
    bytes32 dataHash;
}

interface IERC7857Metadata {
    /// @notice Get the name of the NFT collection
    function name() external view returns (string memory);

    /// @notice Get the symbol of the NFT collection
    function symbol() external view returns (string memory);

    /// @notice Get the data hash of a token
    /// @param _tokenId The token identifier
    /// @return The current data hash of the token
    function intelligentDataOf(uint256 _tokenId) external view returns (IntelligentData[] memory);
}
```

### Main NFT Interface

```solidity
interface IERC7857 {
    /// @notice The event emitted when an address is approved to transfer a token
    /// @param _from The address that is approving
    /// @param _to The address that is being approved
    /// @param _tokenId The token identifier
    event Approval(
        address indexed _from,
        address indexed _to,
        uint256 indexed _tokenId
    );

    /// @notice The event emitted when an address is approved for all
    /// @param _owner The owner
    /// @param _operator The operator
    /// @param _approved The approval
    event ApprovalForAll(
        address indexed _owner,
        address indexed _operator,
        bool _approved
    );

    /// @notice The event emitted when an address is authorized to use a token
    /// @param _from The address that is authorizing
    /// @param _to The address that is being authorized
    /// @param _tokenId The token identifier
    event Authorization(
        address indexed _from,
        address indexed _to,
        uint256 indexed _tokenId
    );

    /// @notice The event emitted when an address is revoked from using a token
    /// @param _from The address that is revoking
    /// @param _to The address that is being revoked
    /// @param _tokenId The token identifier
    event AuthorizationRevoked(
        address indexed _from,
        address indexed _to,
        uint256 indexed _tokenId
    );

    /// @notice The event emitted when a token is transferred
    /// @param _tokenId The token identifier
    /// @param _from The address that is transferring
    /// @param _to The address that is receiving
    event Transferred(
        uint256 _tokenId,
        address indexed _from,
        address indexed _to
    );

    /// @notice The event emitted when a token is cloned
    /// @param _tokenId The token identifier
    /// @param _newTokenId The new token identifier
    /// @param _from The address that is cloning
    /// @param _to The address that is receiving
    event Cloned(
        uint256 indexed _tokenId,
        uint256 indexed _newTokenId,
        address _from,
        address _to
    );

    /// @notice The event emitted when a sealed key is published
    /// @param _to The address that is receiving
    /// @param _tokenId The token identifier
    /// @param _sealedKeys The sealed keys
    event PublishedSealedKey(
        address indexed _to,
        uint256 indexed _tokenId,
        bytes[] _sealedKeys
    );

    /// @notice The event emitted when a user is delegated to an assistant
    /// @param _user The user
    /// @param _assistant The assistant
    event DelegateAccess(address indexed _user, address indexed _assistant);

    /// @notice The verifier interface that this NFT uses
    /// @return The address of the verifier contract
    function verifier() external view returns (IERC7857DataVerifier);

    /// @notice Transfer data with ownership
    /// @param _to Address to transfer data to
    /// @param _tokenId The token to transfer data for
    /// @param _proofs Proofs of data available for _to
    function iTransfer(
        address _to,
        uint256 _tokenId,
        TransferValidityProof[] calldata _proofs
    ) external;

    /// @notice Clone data
    /// @param _to Address to clone data to
    /// @param _tokenId The token to clone data for
    /// @param _proofs Proofs of data available for _to
    /// @return _newTokenId The ID of the newly cloned token
    function iClone(
        address _to,
        uint256 _tokenId,
        TransferValidityProof[] calldata _proofs
    ) external returns (uint256 _newTokenId);

    /// @notice Add authorized user to group
    /// @param _tokenId The token to add to group
    function authorizeUsage(uint256 _tokenId, address _user) external;

    /// @notice Revoke authorization from a user
    /// @param _tokenId The token to revoke authorization from
    /// @param _user The user to revoke authorization from
    function revokeAuthorization(uint256 _tokenId, address _user) external;

    /// @notice Approve an address to transfer a token
    /// @param _to The address to approve
    /// @param _tokenId The token identifier
    function approve(address _to, uint256 _tokenId) external;

    /// @notice Set approval for all
    /// @param _operator The operator
    /// @param _approved The approval
    function setApprovalForAll(address _operator, bool _approved) external;

    /// @notice Delegate access check to an assistant
    /// @param _assistant The assistant
    function delegateAccess(address _assistant) external;

    /// @notice Get token owner
    /// @param _tokenId The token identifier
    /// @return The current owner of the token
    function ownerOf(uint256 _tokenId) external view returns (address);

    /// @notice Get the authorized users of a token
    /// @param _tokenId The token identifier
    /// @return The current authorized users of the token
    function authorizedUsersOf(
        uint256 _tokenId
    ) external view returns (address[] memory);

    /// @notice Get the approved address for a token
    /// @param _tokenId The token identifier
    /// @return The approved address
    function getApproved(uint256 _tokenId) external view returns (address);

    /// @notice Check if an address is approved for all
    /// @param _owner The owner
    /// @param _operator The operator
    /// @return The approval
    function isApprovedForAll(
        address _owner,
        address _operator
    ) external view returns (bool);

    /// @notice Get the delegate access for a user
    /// @param _user The user
    /// @return The delegate access
    function getDelegateAccess(address _user) external view returns (address);
}
```

## Rationale

The design choices in this standard are motivated by several key requirements:

1. **Verification Abstraction**: The standard separates the verification logic into a dedicated interface (`IDataVerifier`), allowing different verification mechanisms (TEE, ZKP) to be implemented and used interchangeably. The verifier should support two types of proof:
    - Ownership Proof Verifies that the prover possesses the original data by demonstrating knowledge of the pre-images that generate the claimed dataHashes
    - Transfer Validity Proof Verifies secure data integrity and availability by proving: knowledge of the original data (pre-images of oldDataHashes); ability to decrypt with oldKey and re-encrypt with newKey; secure transmission of newKey using recipient&apos;s public key; integrity of the newly encrypted data matching newDataHashes; and data availability confirmed by recipient&apos;s signature on both `oldDataHashes` and `newDataHashes`
2. **Data Protection**: The standard uses data hashes and encrypted keys to ensure that valuable NFT data remains protected while still being integrity and availability verifiable

3. **Flexible Data Management**: Three distinct data operations are supported:
    - Full transfer, where the data and ownership are transferred to the new owner
    - Data cloning, where the data is cloned to a new token but the ownership is not transferred
    - Data usage authorization, where the data is authorized to be used by a specific user, but the ownership is not transferred, and the user still cannot access the data. This need an environment to authenticate the user and process the request from the authorized user secretly, we call it &quot;Sealed Executor&quot;
    
4. **Sealed Executor**: Although the Sealed Executor is not defined and out of the scope of this standard, it is a crucial component for the standard to work. The Sealed Executor is an environment that can authenticate the user and process the request from the authorized user secretly. The Sealed Executor should get authorized group by tokenId, and the verify the signature of the user using the public keys in the authorized group. If the verification is successful, the executor will process the request and return the result to the user, and the sealed executor could be implemented by a trusted party (where permitted), TEE or Fully Homomorphic Encryption (FHE)

## Backwards Compatibility

This EIP does not inherit from existing NFT standards to maintain its focus on functional data management. However, implementations can choose to additionally implement [ERC-721][erc721] if traditional NFT compatibility is desired.

## Reference Implementation
### Verifier
```solidity
abstract contract BaseVerifier is IERC7857DataVerifier {
    // prevent replay attack
    mapping(bytes32 =&gt; bool) internal usedProofs;
    
    // prevent replay attack
    mapping(bytes32 =&gt; uint256) internal proofTimestamps;
    
    function _checkAndMarkProof(bytes32 proofNonce) internal {
        require(!usedProofs[proofNonce], &quot;Proof already used&quot;);
        usedProofs[proofNonce] = true;
        proofTimestamps[proofNonce] = block.timestamp;
    }
    
    // clean expired proof records (save gas)
    function cleanExpiredProofs(bytes32[] calldata proofNonces) external {
        for (uint256 i = 0; i &lt; proofNonces.length; i++) {
            bytes32 nonce = proofNonces[i];
            if (usedProofs[nonce] &amp;&amp; 
                block.timestamp &gt; proofTimestamps[nonce] + 7 days) {
                delete usedProofs[nonce];
                delete proofTimestamps[nonce];
            }
        }
    }

    uint256[50] private __gap;
}

struct AttestationConfig {
    OracleType oracleType;
    address contractAddress;
}

contract Verifier is
    BaseVerifier,
    Initializable,
    AccessControlUpgradeable,
    PausableUpgradeable
{
    using ECDSA for bytes32;
    using MessageHashUtils for bytes32;

    event AttestationContractUpdated(AttestationConfig[] attestationConfigs);

    bytes32 public constant ADMIN_ROLE = keccak256(&quot;ADMIN_ROLE&quot;);
    bytes32 public constant PAUSER_ROLE = keccak256(&quot;PAUSER_ROLE&quot;);

    mapping(OracleType =&gt; address) public attestationContract;

    uint256 public maxProofAge;

    string public constant VERSION = &quot;2.0.0&quot;;

    /// @custom:oz-upgrades-unsafe-allow constructor
    constructor() {
        _disableInitializers();
    }

    function initialize(
        AttestationConfig[] calldata _attestationConfigs,
        address _admin
    ) external initializer {
        __AccessControl_init();
        __Pausable_init();

        for (uint256 i = 0; i &lt; _attestationConfigs.length; i++) {
            attestationContract[
                _attestationConfigs[i].oracleType
            ] = _attestationConfigs[i].contractAddress;
        }
        maxProofAge = 7 days;

        _grantRole(DEFAULT_ADMIN_ROLE, _admin);
        _grantRole(ADMIN_ROLE, _admin);
        _grantRole(PAUSER_ROLE, _admin);

        emit AttestationContractUpdated(_attestationConfigs);
    }

    function updateAttestationContract(
        AttestationConfig[] calldata _attestationConfigs
    ) external onlyRole(ADMIN_ROLE) {
        for (uint256 i = 0; i &lt; _attestationConfigs.length; i++) {
            attestationContract[
                _attestationConfigs[i].oracleType
            ] = _attestationConfigs[i].contractAddress;
        }

        emit AttestationContractUpdated(_attestationConfigs);
    }

    function updateMaxProofAge(
        uint256 _maxProofAge
    ) external onlyRole(ADMIN_ROLE) {
        maxProofAge = _maxProofAge;
    }

    function pause() external onlyRole(PAUSER_ROLE) {
        _pause();
    }

    function unpause() external onlyRole(PAUSER_ROLE) {
        _unpause();
    }

    function hashNonce(bytes memory nonce) private pure returns (bytes32) {
        return keccak256(nonce);
    }

    function teeOracleVerify(
        bytes32 messageHash,
        bytes memory signature
    ) internal view returns (bool) {
        return
            TEEVerifier(attestationContract[OracleType.TEE]).verifyTEESignature(
                messageHash,
                signature
            );
    }

    /// @notice Extract and verify signature from the access proof
    /// @param accessProof The access proof
    /// @return The recovered access assistant address
    function verifyAccessibility(
        AccessProof memory accessProof
    ) private pure returns (address) {
        bytes32 messageHash = keccak256(
            abi.encodePacked(
                &quot;\x19Ethereum Signed Message:\n66&quot;,
                Strings.toHexString(
                    uint256(
                        keccak256(
                            abi.encodePacked(
                                accessProof.oldDataHash,
                                accessProof.newDataHash,
                                accessProof.encryptedPubKey,
                                accessProof.nonce
                            )
                        )
                    ),
                    32
                )
            )
        );

        address accessAssistant = messageHash.recover(accessProof.proof);
        require(accessAssistant != address(0), &quot;Invalid access assistant&quot;);
        return accessAssistant;
    }

    function verfifyOwnershipProof(
        OwnershipProof memory ownershipProof
    ) private view returns (bool) {
        if (ownershipProof.oracleType == OracleType.TEE) {
            bytes32 messageHash = keccak256(
                abi.encodePacked(
                    &quot;\x19Ethereum Signed Message:\n66&quot;,
                    Strings.toHexString(
                        uint256(
                            keccak256(
                                abi.encodePacked(
                                    ownershipProof.oldDataHash,
                                    ownershipProof.newDataHash,
                                    ownershipProof.sealedKey,
                                    ownershipProof.encryptedPubKey,
                                    ownershipProof.nonce
                                )
                            )
                        ),
                        32
                    )
                )
            );

            return teeOracleVerify(messageHash, ownershipProof.proof);
        }
        // TODO: add ZKP verification
        else {
            return false;
        }
    }

    /// @notice Process a single transfer validity proof
    /// @param proof The proof data
    /// @return output The processed proof data as a struct
    function processTransferProof(
        TransferValidityProof calldata proof
    ) private view returns (TransferValidityProofOutput memory output) {
        // compare the proof data in access proof and ownership proof
        require(
            proof.accessProof.oldDataHash == proof.ownershipProof.oldDataHash,
            &quot;Invalid oldDataHashes&quot;
        );
        output.oldDataHash = proof.accessProof.oldDataHash;
        require(
            proof.accessProof.newDataHash == proof.ownershipProof.newDataHash,
            &quot;Invalid newDataHashes&quot;
        );
        output.newDataHash = proof.accessProof.newDataHash;

        output.wantedKey = proof.accessProof.encryptedPubKey;
        output.accessProofNonce = proof.accessProof.nonce;
        output.encryptedPubKey = proof.ownershipProof.encryptedPubKey;
        output.sealedKey = proof.ownershipProof.sealedKey;
        output.ownershipProofNonce = proof.ownershipProof.nonce;

        // verify the access assistant
        output.accessAssistant = verifyAccessibility(proof.accessProof);

        bool isOwn = verfifyOwnershipProof(proof.ownershipProof);

        require(isOwn, &quot;Invalid ownership proof&quot;);

        return output;
    }

    /// @notice Verify data transfer validity, the _proof prove:
    ///         1. The pre-image of oldDataHashes
    ///         2. The oldKey can decrypt the pre-image and the new key re-encrypt the plaintexts to new ciphertexts
    ///         3. The newKey is encrypted with the receiver&apos;s pubKey to get the sealedKey
    ///         4. The hashes of new ciphertexts is newDataHashes (key to note: TEE could support a private key of the receiver)
    ///         5. The newDataHashes identified ciphertexts are available in the storage: need the signature from the receiver signing oldDataHashes and newDataHashes
    /// @param proofs Proof generated by TEE/ZKP oracle
    function verifyTransferValidity(
        TransferValidityProof[] calldata proofs
    )
        public
        virtual
        override
        whenNotPaused
        returns (TransferValidityProofOutput[] memory)
    {
        TransferValidityProofOutput[]
            memory outputs = new TransferValidityProofOutput[](proofs.length);

        for (uint256 i = 0; i &lt; proofs.length; i++) {
            TransferValidityProofOutput memory output = processTransferProof(
                proofs[i]
            );

            outputs[i] = output;

            bytes32 accessProofNonce = hashNonce(output.accessProofNonce);
            _checkAndMarkProof(accessProofNonce);

            bytes32 ownershipProofNonce = hashNonce(output.ownershipProofNonce);
            _checkAndMarkProof(ownershipProofNonce);
        }

        return outputs;
    }

    uint256[50] private __gap;
}
```
### Main NFT
```solidity
contract AgentNFT is
    AccessControlEnumerableUpgradeable,
    IERC7857,
    IERC7857Metadata
{
    event Updated(
        uint256 indexed _tokenId,
        IntelligentData[] _oldDatas,
        IntelligentData[] _newDatas
    );

    event Minted(
        uint256 indexed _tokenId,
        address indexed _creator,
        address indexed _owner
    );

    struct TokenData {
        address owner;
        address[] authorizedUsers;
        address approvedUser;
        IntelligentData[] iDatas;
    }

    /// @custom:storage-location erc7201:agent.storage.AgentNFT
    struct AgentNFTStorage {
        // Token data
        mapping(uint256 =&gt; TokenData) tokens;
        mapping(address owner =&gt; mapping(address operator =&gt; bool)) operatorApprovals;
        mapping(address user =&gt; address accessAssistant) accessAssistants;
        uint256 nextTokenId;
        // Contract metadata
        string name;
        string symbol;
        string storageInfo;
        // Core components
        IERC7857DataVerifier verifier;
    }

    bytes32 public constant ADMIN_ROLE = keccak256(&quot;ADMIN_ROLE&quot;);
    bytes32 public constant PAUSER_ROLE = keccak256(&quot;PAUSER_ROLE&quot;);

    string public constant VERSION = &quot;2.0.0&quot;;

    // keccak256(abi.encode(uint(keccak256(&quot;agent.storage.AgentNFT&quot;)) - 1)) &amp; ~bytes32(uint(0xff))
    bytes32 private constant AGENT_NFT_STORAGE_LOCATION =
        0x4aa80aaafbe0e5fe3fe1aa97f3c1f8c65d61f96ef1aab2b448154f4e07594600;

    function _getAgentStorage()
        private
        pure
        returns (AgentNFTStorage storage $)
    {
        assembly {
            $.slot := AGENT_NFT_STORAGE_LOCATION
        }
    }

    /// @custom:oz-upgrades-unsafe-allow constructor
    constructor() {
        _disableInitializers();
    }

    function initialize(
        string memory name_,
        string memory symbol_,
        string memory storageInfo_,
        address verifierAddr,
        address admin_
    ) public virtual initializer {
        require(verifierAddr != address(0), &quot;Zero address&quot;);

        __AccessControlEnumerable_init();

        _grantRole(DEFAULT_ADMIN_ROLE, admin_);
        _grantRole(ADMIN_ROLE, admin_);
        _grantRole(PAUSER_ROLE, admin_);

        AgentNFTStorage storage $ = _getAgentStorage();
        $.name = name_;
        $.symbol = symbol_;
        $.storageInfo = storageInfo_;
        $.verifier = IERC7857DataVerifier(verifierAddr);
    }

    // Basic getters
    function name() public view virtual returns (string memory) {
        return _getAgentStorage().name;
    }

    function symbol() public view virtual returns (string memory) {
        return _getAgentStorage().symbol;
    }

    function verifier() public view virtual returns (IERC7857DataVerifier) {
        return _getAgentStorage().verifier;
    }

    // Admin functions
    function updateVerifier(
        address newVerifier
    ) public virtual onlyRole(ADMIN_ROLE) {
        require(newVerifier != address(0), &quot;Zero address&quot;);
        _getAgentStorage().verifier = IERC7857DataVerifier(newVerifier);
    }

    function update(
        uint256 tokenId,
        IntelligentData[] calldata newDatas
    ) public virtual {
        AgentNFTStorage storage $ = _getAgentStorage();
        TokenData storage token = $.tokens[tokenId];
        require(token.owner == msg.sender, &quot;Not owner&quot;);
        require(newDatas.length &gt; 0, &quot;Empty data array&quot;);

        IntelligentData[] memory oldDatas = new IntelligentData[](
            token.iDatas.length
        );
        for (uint i = 0; i &lt; token.iDatas.length; i++) {
            oldDatas[i] = token.iDatas[i];
        }

        delete token.iDatas;

        for (uint i = 0; i &lt; newDatas.length; i++) {
            token.iDatas.push(newDatas[i]);
        }

        emit Updated(tokenId, oldDatas, newDatas);
    }

    function mint(
        IntelligentData[] calldata iDatas,
        address to
    ) public payable virtual returns (uint256 tokenId) {
        require(to != address(0), &quot;Zero address&quot;);
        require(iDatas.length &gt; 0, &quot;Empty data array&quot;);

        AgentNFTStorage storage $ = _getAgentStorage();

        tokenId = $.nextTokenId++;
        TokenData storage newToken = $.tokens[tokenId];
        newToken.owner = to;
        newToken.approvedUser = address(0);

        for (uint i = 0; i &lt; iDatas.length; i++) {
            newToken.iDatas.push(iDatas[i]);
        }

        emit Minted(tokenId, msg.sender, to);
    }

    function _proofCheck(
        address from,
        address to,
        uint256 tokenId,
        TransferValidityProof[] calldata proofs
    )
        internal
        returns (bytes[] memory sealedKeys, IntelligentData[] memory newDatas)
    {
        AgentNFTStorage storage $ = _getAgentStorage();
        require(to != address(0), &quot;Zero address&quot;);
        require($.tokens[tokenId].owner == from, &quot;Not owner&quot;);
        require(proofs.length &gt; 0, &quot;Empty proofs array&quot;);

        TransferValidityProofOutput[] memory proofOutput = $
            .verifier
            .verifyTransferValidity(proofs);

        require(
            proofOutput.length == $.tokens[tokenId].iDatas.length,
            &quot;Proof count mismatch&quot;
        );

        sealedKeys = new bytes[](proofOutput.length);
        newDatas = new IntelligentData[](proofOutput.length);

        for (uint i = 0; i &lt; proofOutput.length; i++) {
            // require the initial data hash is the same as the old data hash
            require(
                proofOutput[i].oldDataHash ==
                    $.tokens[tokenId].iDatas[i].dataHash,
                &quot;Old data hash mismatch&quot;
            );

            // only the receiver itself or the access assistant can sign the access proof
            require(
                proofOutput[i].accessAssistant == $.accessAssistants[to] ||
                    proofOutput[i].accessAssistant == to,
                &quot;Access assistant mismatch&quot;
            );

            bytes memory wantedKey = proofOutput[i].wantedKey;
            bytes memory encryptedPubKey = proofOutput[i].encryptedPubKey;
            if (wantedKey.length == 0) {
                // if the wanted key is empty, the default wanted receiver is receiver itself
                address defaultWantedReceiver = Utils.pubKeyToAddress(
                    encryptedPubKey
                );
                require(
                    defaultWantedReceiver == to,
                    &quot;Default wanted receiver mismatch&quot;
                );
            } else {
                // if the wanted key is not empty, the data is private
                require(
                    Utils.bytesEqual(encryptedPubKey, wantedKey),
                    &quot;encryptedPubKey mismatch&quot;
                );
            }

            sealedKeys[i] = proofOutput[i].sealedKey;
            newDatas[i] = IntelligentData({
                dataDescription: $.tokens[tokenId].iDatas[i].dataDescription,
                dataHash: proofOutput[i].newDataHash
            });
        }
        return (sealedKeys, newDatas);
    }

    function _transfer(
        address from,
        address to,
        uint256 tokenId,
        TransferValidityProof[] calldata proofs
    ) internal {
        AgentNFTStorage storage $ = _getAgentStorage();
        (
            bytes[] memory sealedKeys,
            IntelligentData[] memory newDatas
        ) = _proofCheck(from, to, tokenId, proofs);

        TokenData storage token = $.tokens[tokenId];
        token.owner = to;
        token.approvedUser = address(0);

        delete token.iDatas;
        for (uint i = 0; i &lt; newDatas.length; i++) {
            token.iDatas.push(newDatas[i]);
        }

        emit Transferred(tokenId, from, to);
        emit PublishedSealedKey(to, tokenId, sealedKeys);
    }

    function iTransfer(
        address to,
        uint256 tokenId,
        TransferValidityProof[] calldata proofs
    ) public virtual {
        require(_isApprovedOrOwner(msg.sender, tokenId), &quot;Not authorized&quot;);
        _transfer(ownerOf(tokenId), to, tokenId, proofs);
    }

    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual {
        TokenData storage token = _getAgentStorage().tokens[tokenId];
        require(_isApprovedOrOwner(msg.sender, tokenId), &quot;Not authorized&quot;);
        require(to != address(0), &quot;Zero address&quot;);
        require(token.owner == from, &quot;Not owner&quot;);
        token.owner = to;
        token.approvedUser = address(0);

        emit Transferred(tokenId, from, to);
    }

    function iTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        TransferValidityProof[] calldata proofs
    ) public virtual {
        require(_isApprovedOrOwner(msg.sender, tokenId), &quot;Not authorized&quot;);
        _transfer(from, to, tokenId, proofs);
    }

    function _clone(
        address from,
        address to,
        uint256 tokenId,
        TransferValidityProof[] calldata proofs
    ) internal returns (uint256) {
        AgentNFTStorage storage $ = _getAgentStorage();

        (
            bytes[] memory sealedKeys,
            IntelligentData[] memory newDatas
        ) = _proofCheck(from, to, tokenId, proofs);

        uint256 newTokenId = $.nextTokenId++;
        TokenData storage newToken = $.tokens[newTokenId];
        newToken.owner = to;
        newToken.approvedUser = address(0);

        for (uint i = 0; i &lt; newDatas.length; i++) {
            newToken.iDatas.push(newDatas[i]);
        }

        emit Cloned(tokenId, newTokenId, from, to);
        emit PublishedSealedKey(to, newTokenId, sealedKeys);

        return newTokenId;
    }

    function iClone(
        address to,
        uint256 tokenId,
        TransferValidityProof[] calldata proofs
    ) public virtual returns (uint256) {
        require(_isApprovedOrOwner(msg.sender, tokenId), &quot;Not authorized&quot;);
        return _clone(ownerOf(tokenId), to, tokenId, proofs);
    }

    function iCloneFrom(
        address from,
        address to,
        uint256 tokenId,
        TransferValidityProof[] calldata proofs
    ) public virtual returns (uint256) {
        require(_isApprovedOrOwner(msg.sender, tokenId), &quot;Not authorized&quot;);
        return _clone(from, to, tokenId, proofs);
    }

    function authorizeUsage(uint256 tokenId, address to) public virtual {
        require(to != address(0), &quot;Zero address&quot;);
        AgentNFTStorage storage $ = _getAgentStorage();
        require($.tokens[tokenId].owner == msg.sender, &quot;Not owner&quot;);

        address[] storage authorizedUsers = $.tokens[tokenId].authorizedUsers;
        for (uint i = 0; i &lt; authorizedUsers.length; i++) {
            require(authorizedUsers[i] != to, &quot;Already authorized&quot;);
        }

        authorizedUsers.push(to);
        emit Authorization(msg.sender, to, tokenId);
    }

    function ownerOf(uint256 tokenId) public view virtual returns (address) {
        AgentNFTStorage storage $ = _getAgentStorage();
        address owner = $.tokens[tokenId].owner;
        require(owner != address(0), &quot;Token does not exist&quot;);
        return owner;
    }

    function authorizedUsersOf(
        uint256 tokenId
    ) public view virtual returns (address[] memory) {
        AgentNFTStorage storage $ = _getAgentStorage();
        require(_exists(tokenId), &quot;Token does not exist&quot;);
        return $.tokens[tokenId].authorizedUsers;
    }

    function storageInfo(
        uint256 tokenId
    ) public view virtual returns (string memory) {
        require(_exists(tokenId), &quot;Token does not exist&quot;);
        return _getAgentStorage().storageInfo;
    }

    function _exists(uint256 tokenId) internal view returns (bool) {
        return _getAgentStorage().tokens[tokenId].owner != address(0);
    }

    function intelligentDataOf(
        uint256 tokenId
    ) public view virtual returns (IntelligentData[] memory) {
        AgentNFTStorage storage $ = _getAgentStorage();
        require(_exists(tokenId), &quot;Token does not exist&quot;);
        return $.tokens[tokenId].iDatas;
    }

    function approve(address to, uint256 tokenId) public virtual {
        address owner = ownerOf(tokenId);
        require(to != owner, &quot;Approval to current owner&quot;);
        require(
            msg.sender == owner || isApprovedForAll(owner, msg.sender),
            &quot;Not authorized&quot;
        );

        _getAgentStorage().tokens[tokenId].approvedUser = to;
        emit Approval(owner, to, tokenId);
    }

    function setApprovalForAll(address operator, bool approved) public virtual {
        require(operator != msg.sender, &quot;Approve to caller&quot;);
        _getAgentStorage().operatorApprovals[msg.sender][operator] = approved;
        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function getApproved(
        uint256 tokenId
    ) public view virtual returns (address) {
        require(_exists(tokenId), &quot;Token does not exist&quot;);
        return _getAgentStorage().tokens[tokenId].approvedUser;
    }

    function isApprovedForAll(
        address owner,
        address operator
    ) public view virtual returns (bool) {
        return _getAgentStorage().operatorApprovals[owner][operator];
    }

    function delegateAccess(address assistant) public virtual {
        require(assistant != address(0), &quot;Zero address&quot;);
        _getAgentStorage().accessAssistants[msg.sender] = assistant;
        emit DelegateAccess(msg.sender, assistant);
    }

    function getDelegateAccess(
        address user
    ) public view virtual returns (address) {
        return _getAgentStorage().accessAssistants[user];
    }

    function _isApprovedOrOwner(
        address spender,
        uint256 tokenId
    ) internal view returns (bool) {
        require(_exists(tokenId), &quot;Token does not exist&quot;);
        address owner = ownerOf(tokenId);
        return (spender == owner ||
            getApproved(tokenId) == spender ||
            isApprovedForAll(owner, spender));
    }

    function batchAuthorizeUsage(
        uint256 tokenId,
        address[] calldata users
    ) public virtual {
        require(users.length &gt; 0, &quot;Empty users array&quot;);
        AgentNFTStorage storage $ = _getAgentStorage();
        require($.tokens[tokenId].owner == msg.sender, &quot;Not owner&quot;);

        for (uint i = 0; i &lt; users.length; i++) {
            require(users[i] != address(0), &quot;Zero address in users&quot;);
            $.tokens[tokenId].authorizedUsers.push(users[i]);
            emit Authorization(msg.sender, users[i], tokenId);
        }
    }

    function revokeAuthorization(uint256 tokenId, address user) public virtual {
        AgentNFTStorage storage $ = _getAgentStorage();
        require($.tokens[tokenId].owner == msg.sender, &quot;Not owner&quot;);
        require(user != address(0), &quot;Zero address&quot;);

        address[] storage authorizedUsers = $.tokens[tokenId].authorizedUsers;
        bool found = false;

        for (uint i = 0; i &lt; authorizedUsers.length; i++) {
            if (authorizedUsers[i] == user) {
                authorizedUsers[i] = authorizedUsers[
                    authorizedUsers.length - 1
                ];
                authorizedUsers.pop();
                found = true;
                break;
            }
        }

        require(found, &quot;User not authorized&quot;);
        emit AuthorizationRevoked(msg.sender, user, tokenId);
    }
}
```

## Security Considerations

1. **Proof Verification**
    - Implementations must carefully verify all assertions in the proof
    - Replay attacks must be prevented
    - Different verification systems have their own security considerations, and distinct capabilities regarding key management: TEE can securely handle private keys from multi-parties, enabling direct data re-encryption. However, ZKP, due to its cryptographic nature, cannot process private keys from multi-parties. As a result, the re-encryption key is also from the prover (i.e., the sender), so tokens acquired through transfer or cloning must undergo re-encryption during their next update, otherwise the new update is still visible to the previous owner. This distinction in key handling capabilities affects how data transformations are managed during later usage
2. **Data Privacy**
    - Only hashes and sealed keys are stored on-chain, actual functional data must be stored and transmitted securely off-chain
    - Key management is crucial for secure data access
    - TEE verification system could support private key of the receiver, but ZKP verification system could not. So when using ZKP, the token transferred or cloned from other should be re-encrypted when next update, otherwise the new update is still visible to the previous owner
3. **Access Control and State Management**
    - Operations restricted to token owners only
    - All data operations must maintain integrity and availability
    - Critical state changes (sealed keys, ownership, permissions) must be atomic and verifiable
4. **Sealed Executor**
    - Although out of scope for this standard, the Sealed Executor is crucial for secure operation
    - The Sealed Executor authenticates users and processes requests in a secure environment by verifying user signatures against authorized public keys for each tokenId
    - The Sealed Executor can be implemented through a trusted party (where permitted), TEE or FHE
    - Ensuring secure request processing and result delivery

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[erc721]: /EIPs/EIPS/eip-721
</description>
        <pubDate>Thu, 02 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7857</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7857</guid>
      </item>
    
      <item>
        <title>Expirable NFTs and SBTs</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7858-expirable-nft-sbt/22406</comments>
        
        <description>## Abstract

Introduces an extension for [ERC-721](/EIPs/EIPS/eip-721) Non-Fungible Tokens (NFTs) and Soulbound Tokens (SBTs) that adds an expiration mechanism, allowing tokens to become invalid after a predefined period. This additional layer of functionality ensures that the expiration mechanism does not interfere with existing NFTs or SBTs, preserving transferability for NFTs and compatibility with current DApps such as NFT Marketplace. Expiration can be defined using either block height or timestamp, offering flexibility for various use cases.

## Motivation

Before this EIP, NFTs and SBTs implemented expiration mechanisms via custom mappings. However, this approach presents challenges, such as: inconsistent integration with other smart contracts, and the custom [ERC-721](/EIPs/EIPS/eip-721) implementations might misbehave when used in NFT marketplaces. This EIP addresses these issues by providing a built-in expiration mechanism and interfaces that are compatible with existing infrastructure. It supports both per-token and epoch-based expiry, allowing developers to choose the appropriate expiry type for their use cases, including:

- Access and Authentication
  - Authentication for Identity and Access Management (IAM)
  - Membership for Membership Management System (MMS)
  - Ticket and Press for Meetings, Incentive Travel, Conventions, and Exhibitions (MICE) when using with [ERC-2135](/EIPs/EIPS/eip-2135) or [ERC-7578](/EIPs/EIPS/eip-7578).
  - Subscription-based access for digital platforms.
- Digital Certifications, Contracts, Copyrights, Documents, Licenses, Policies, etc.
- Loyalty Program voucher or coupon
- Governance and Voting Rights
- Financial Product
  - Bonds, Loans, Hedge, and Options Contract
- Rental
  - Real Estate Unit, Digital Access, DePIN, etc

## Specification

The keywords “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.

Compatible implementations MUST implement the `IERC7858` interface and MUST inherit from [ERC-721](/EIPs/EIPS/eip-721)&apos;s interface. All functions defined in the interface MUST be present and all function behavior MUST meet the interface specification requirements.

### Interface

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity &gt;=0.8.0 &lt;0.9.0;

/**
 * @title ERC-7858: Expirable NFTs and SBTs
 * @notice unique/granular expiry
 */

// import &quot;./IERC721.sol&quot;;

// The EIP-165 identifier of this interface is `0x3ebdfa31`.
interface IERC7858 /**is IERC721 */ {
    enum EXPIRY_TYPE {
        BLOCKS_BASED, // block.number
        TIME_BASED // block.timestamp
    }
    
    /**
     * @dev Emitted when the expiration date of a token is set or updated.
     * @param tokenId The identifier of the token ERC721 `tokenId`.
     * @param startTime The start time of the token (block number or timestamp based on `expiryType`).
     * @param endTime The end time of the token (block number or timestamp based on `expiryType`).
     */
    event TokenExpiryUpdated(
        uint256 indexed tokenId,
        uint256 indexed startTime,
        uint256 indexed endTime
    );

    /**
     * @dev Returns the type of the expiry.
     * @return EXPIRY_TYPE  Enum value indicating the unit of an expiry.
     */
    function expiryType() external view returns (EXPIRY_TYPE);

    /**
     * @dev Checks whether a specific token is expired.
     * @param tokenId The identifier representing the `tokenId` (ERC721).
     * @return bool True if the token is expired, false otherwise.
     */
    function isTokenExpired(uint256 tokenId) external view returns (bool);

    // return depends on the type `block.timestamp` or `block.number`
    // {ERC-5007} return in uint64 MAY not suitable for `block.number` based.
    function startTime(uint256 tokenId) external view returns (uint256);
    function endTime(uint256 tokenId) external view returns (uint256);
}
```

### Behavior Specification

- `balanceOf` that inherited from [ERC-721](/EIPs/EIPS/eip-721) MUST return all tokens even if expired; they still exist but are unusable due to the limitation of tracking expired token on-chain.
- For NFTs `transferFrom`, and `safeTransferFrom` MUST allow transferring tokens even if they expired. This ensures that expired tokens remain transferable and tradable, preserving compatibility with existing applications already deployed. However, expired tokens MUST be considered invalid and unusable in contracts that check for token validity.
- `expiryType` MUST return the type of expiry used by the contract, which can be either `BLOCK` or `TIME`.
- `isTokenExpired` is used for retrieving the status of the given `tokenId`; the function MUST return `true` if the token is expired and MUST revert if the `tokenId` does not exist. Implementations that use custom errors SHOULD revert with `ERC721NonexistentToken` following the relevant [ERC-6093](/EIPs/EIPS/eip-6093) and implementations using Solidity version below `v0.8.4` or those preferring to use revert with string error SHOULD revert with `NonexistToken`. If the `tokenId` exists and is not expired, the function MUST return `false`.
- `startTime` and `endTime` of `tokenId`, can be `block.number` or `block.timestamp` depending on `expiryType`. The `startTime` MUST be less than or equal to `endTime` and `startTime` SHOULD be strictly less than `endTime` except when both are set to `0`. A `startTime` and `endTime` of `0` indicates that the `tokenId` has no expiration. Tokens with a non-zero `startTime` and a zero `endTime` are also considered to have no expiration. If the `tokenId` does not exist, this function MUST revert in the same way as `isTokenExpired`.
- The interface ID for [ERC-165](/EIPs/EIPS/eip-165)&apos;s `supportsInterface` for `IERC7858` is `0x3ebdfa31`, and for `IERC7858Epoch` it is `0xec7ffd66`
* `TokenExpiryUpdated` MUST be emitted when the token is minted or when its expiration details (`startTime` or `endTime`) are updated.

### Extension Interface

**Epochs** represent a specific period or block range during which certain tokens are valid borrowing concepts from [ERC-7818](/EIPs/EIPS/eip-7818), tokens are grouped under an `epoch` and share the same `validityDuration`. For implementations that require epoch-based expiration management, the `IERC7858Epoch` extension interface MUST be implemented alongside the base `IERC7858` interface, and all functions and behaviors MUST meet both `IERC7858` and `IERC7858Epoch` interface specification requirements.

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity &gt;=0.8.0 &lt;0.9.0;

/**
 * @title ERC-7858: Expirable NFTs and SBTs
 * @notice epoch expiry extension
 */

// import &quot;./IERC7858.sol&quot;;

// The EIP-165 identifier of this interface is `0xec7ffd66`.
interface IERC7858Epoch /** is IERC7858 */ {
    /**
     * @dev Retrieves the current epoch of the contract.
     * @return uint256 The current epoch of the token contract,
     * often used for determining active/expired states.
     */
    function currentEpoch() external view returns (uint256);

    /**
     * @dev Retrieves the duration of a single epoch.
     * @return uint256 The duration of a single epoch.
     * @notice The unit of the epoch length is determined by the `validityPeriodType` function.
     */
    function epochLength() external view returns (uint256);

    /**
     * @dev Checks whether a specific `epoch` is expired.
     * @param epoch The `epoch` to check.
     * @return bool True if the token is expired, false otherwise.
     * @notice Implementing contracts &quot;MUST&quot; define and document the logic for determining expiration,
     * typically by comparing the latest epoch with the given `epoch` value,
     * based on the `EXPIRY_TYPE` measurement (e.g., block count or time duration).
     */
    function isEpochExpired(uint256 epoch) external view returns (bool);

    /**
     * @dev Retrieves the balance of unexpired tokens owned by an account.
     * @param account The address of the account.
     * @return uint256 The amount of unexpired tokens owned by an account.
     */
    function unexpiredBalanceOf(address account) external view returns (uint256);

    /**
     * @dev Retrieves the balance of a specific `epoch` owned by an account.
     * @param epoch The `epoch for which the balance is checked.
     * @param account The address of the account.
     * @return uint256 The balance of the specified `epoch`.
     * @notice &quot;MUST&quot; return 0 if the specified `epoch` is expired.
     */
    function unexpiredBalanceOfAtEpoch(uint256 epoch, address account) external view returns (uint256);

    /**
     * @dev Retrieves the validity duration of each token.
     * @return uint256 The validity duration of each token in `epoch` unit.
     */
    function validityDuration() external view returns (uint256);
}
```
### Extension Behavior Specification

- `unexpiredBalanceOfAtEpoch` MUST return the count of usable (unexpired) tokens held by an account from the specified `epoch`. If the specified `epoch` is expired, this function MUST return `0`. For example, if epoch `5` has expired, calling `unexpiredBalanceOfAtEpoch(5, address)` returns `0` even if there were tokens previously held in that epoch.
- `unexpiredBalanceOf` MUST return total count of usable (unexpired) tokens owned by the account.
- `currentEpoch` MUST return the current `epoch` of the contract.
- `epochLength` MUST return duration between `epoch` in blocks or time in seconds.
- `validityDuration` MUST return the validity duration of tokens in terms of `epoch` counts.
- `isEpochExpired` MUST return true if the given `epoch` is expired, otherwise `false`.

### Additional Potential Useful Function

These OPTIONAL functions provide additional functionality that developers MAY choose to implement based on their specific requirements and use cases.

#### Base (default)

``` Solidity
function getRemainingDurationBeforeTokenExpired(uint256 tokenId) public view returns (uint256);
```

- `getRemainingDurationBeforeTokenExpired` returns the remaining time or blocks before the given `tokenId` is expired.

#### Epoch (extension)

``` Solidity
function getEpochBalance(uint256 epoch) public view returns (uint256);
```

- `getEpochBalance` returns the amount of tokens stored in a given epoch, even if the epoch has expired.

``` Solidity
function getEpochInfo(uint256 epoch) public view returns (uint256,uint256);
```

- `getEpochInfo` returns both the start and end of the specified `epoch`.

``` Solidity
function getNearestExpiryOf(address account) public view returns (uint256);
```

- `getNearestExpiryOf` returns the list of `tokenId` closest to expiration, along with an estimated expiration block number or timestamp based on `epochType`.

``` Solidity
function getRemainingDurationBeforeEpochChange() public view returns (uint256);
```

- `getRemainingDurationBeforeEpochChange` returns the remaining time or blocks before the epoch change happens, based on the `epochType`.

## Rationale

### First, do no harm

Introducing expirability as an additional layer of functionality ensures it doesn’t interfere with existing use cases or applications. For non-SBT tokens, transferability remains intact, maintaining compatibility with current systems. Expired tokens are simply flagged as unusable during validity checks, treating expiration as an enhancement rather than a fundamental change.

### Expiry Types

Defining expiration by either block height (`block.number`) or block timestamp (`block.timestamp`) offers flexibility for various use cases. Block-based expiration suits applications that rely on network activity and require precise consistency, while time-based expiration is ideal for networks with variable block intervals.

## Backwards Compatibility

This standard is fully compatible with [ERC-721](/EIPs/EIPS/eip-721), [ERC-5484](/EIPs/EIPS/eip-5484) and other SBTs.

## Reference Implementation

You can find our reference implementation [here](/EIPs/assets/eip-7858/).

## Security Considerations

### Burn and Re-Mint

Implementation should ensure that burning token and re-minting it with the same `tokenId` will not introduce an unauthorized renewal.

### Unauthorized Update

Implementation should ensure that only authorized can update `startTime` and `endTime`.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 04 Jan 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7858</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7858</guid>
      </item>
    
      <item>
        <title>ERC-721 Verifiable Credential Extension</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-721-verifiable-credential-extension/22562</comments>
        
        <description>## Abstract

This standard is an extension of [ERC-721](/EIPs/EIPS/eip-721) that adds verifiable credential properties at the contract level. A verifiable credential is a secure digital certificate that encapsulates claims issued by a trusted authority and is designed to be tamper-evident and readily verifiable. It allows [ERC-721](/EIPs/EIPS/eip-721) tokens to natively reference and manage these credentials—as well as other types of off-chain data—by defining mechanisms for storage, encryption, revocation, and verification.

## Motivation
Many [ERC-721](/EIPs/EIPS/eip-721) contracts require additional properties to represent verifiable credentials. While it&apos;s possible to implement these properties in various ways, it creates an extra effort for third-party platforms to build individualized solutions for each NFT collection.

Having a standard for verifiable credential properties will make it easier for third-party platforms to interact with and validate NFTs that represent verifiable credentials onchain.

Just as NFTs represent digital ownership, verifiable credentials (VCs) represent digital attestations about oneself (identity, education, and more). Blockchains provide an ideal solution for storing VCs and associated claims, offering precise access control, issuer legitimacy, and full lifecycle management for credentials, all while maintaining transparency to safeguard user rights.

This standard addresses key gaps in the [W3C framework](https://www.w3.org/TR/2025/PR-vc-data-model-2.0-20250320/) by defining methods for storage, revocation, retrieval, and presentation, facilitating interoperability within a flexible, standardized structure. It supports custom cryptographic methods for signatures and proofs—from basic issuer signatures to advanced zero-knowledge (ZK) proofs and selective disclosure—allowing adaptability for diverse security requirements.

Additionally, the standard natively supports encryption, crucial for managing sensitive data. It also provides flexibility in credential storage, referencing off-chain data via `credentialURI()` to accommodate any storage solution, from decentralized storage (like IPFS) to centralized systems.

Originally designed with W3C credentials in mind, this standard is broad enough to support any kind of credential, for example content credentials. More generally this framework can be used to link any off-chain, private payload to an NFT.

### Standardized Credential Management

This extension aims to provide a standardized way to represent verifiable credentials within the ERC-721 framework. The collection-wide properties (`issuer` and `type`) allow for efficient management of credentials where these properties are shared across all tokens in the collection.

The `credentialURI` function is included to provide a way to retrieve additional off-chain information about individual credentials, similar to the `tokenURI` function in ERC-721.

By emitting `CredentialIssued` and `CredentialRevoked` events, third-party applications and services can track the lifecycle of credentials, enabling real-time monitoring.

## Specification

### Overview
Each NFT in this standard is linked to a credential that can be stored in any compatible storage location. To retrieve credentials for a specific user, is sufficient to get the desired credential NFT in their wallet, and the `credentialURI()` function can provide the exact location of each credential. This URI may point to public storage like IPFS or any custom storage solution with flexible access control, potentially subject to user approval.

Upon retrieval, credentials may be stored in clear text or in encrypted form. The `encryptionMethod()` property indicates the encryption status, allowing the verifier to know in advance if decryption is required. Decryption may involve user consent if the user&apos;s wallet signature is required. Additional steps can be added in cases where advanced algorithms enable selective disclosure or zero-knowledge (ZK) proofs to enhance privacy.

Once decrypted, the credential&apos;s authenticity and integrity can be verified using the `verificationMethod()`, ensuring it remains untampered. For ZK proofs, specific queries can also be verified without disclosing the entire credential. The standard also accounts for credential revocation, which can be implemented in various ways: via burning the associated NFT, an additional structure in the contract or even an off-chain revocation list; in the first case, checking that the NFT is unburned confirms the credential&apos;s validity.

While originally intended for verifiable credentials, this standard&apos;s flexibility allows it to link any private or external data payload to a user&apos;s wallet through an NFT, expanding its utility across various data-reference use cases.



### Interface 
The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

```solidity
/// @title ERC-721 Verifiable Credential Extension
interface IERC7861 is IERC165, IERC721 {
    /// @notice Emitted when a new credential is issued
    /// @param tokenId The token ID of the issued credential
    /// @param to The address to which the credential was issued
    event CredentialIssued(uint256 indexed tokenId, address indexed to);

    /// @notice Emitted when a credential is revoked
    /// @param tokenId The token ID of the revoked credential
    event CredentialRevoked(uint256 indexed tokenId);
	
    /// @notice Get the issuer of the credential collection
    /// @dev The empty string indicates that there is no issuer
    /// @return The issuer DID or address for this credential collection 
    function issuer() external view returns (string memory);

    /// @notice Get the type of the credentials in the collection
    /// @return The credential type for this collection
    function credentialType() external view returns (string memory);

    /// @notice Get the encryption method of the credentials in the collection
    /// @return The encryption method for this collection, will return empty string if not encrypted
    function encryptionMethod() external view returns (string memory);

    /// @notice Get the verification method of the credentials in the collection
    /// @return The verification method for this collection
    function verificationMethod() external view returns (string memory);

    /// @notice Get the URI for a given credential
    /// @dev Throws if `tokenId` is not a valid NFT
    /// @param tokenId The NFT to get the credential URI for
    /// @return The credential URI for the given NFT
    function credentialURI(uint256 tokenId) external view returns (string memory);

    /// @notice Check if a credential has been revoked 
    /// @param tokenId The credential ID to check 
    /// @return false if the credential has not been revoked
    function isRevoked(uint256 tokenId) external view returns (bool);
}
```

The `issuer()`, `credentialType()`, `encryptionMethod()`, `verificationMethod()` and `credentialURI(uint256 tokenId)` functions MUST be implemented as view functions.

The `encryptionMethod()` function MUST return an empty string if and only if the credential is unencrypted. In case of encrypted credentials the method SHOULD return only the encryption method; Any additional encryption details required for decryption MAY be retrieved separately (a separate function or via the contract metadata).

The `verificationMethod()` function MUST return the method to verify the credential proof, the response is up to the implementer but SHOULD be compatible with the W3C [verification method](https://www.w3.org/TR/2025/PR-vc-data-integrity-20250320/#dfn-verification-method) concept.

The `credentialURI(uint256 tokenId)` function MAY be used to retrieve the credential location. In case a given implementation uses a different method to retrieve the credential, `credentialURI(uint256 tokenId)` MUST return an empty string.

The `supportsInterface` [ERC-165](/EIPs/EIPS/eip-165) method MUST return true when called with `0x7861069`.

The `isRevoked(uint256 tokenId)` MUST return false if the credential has not been revoked, and MUST return true if the credential has been revoked. MAY return true if the credential does not exist.

The `CredentialIssued` and `CredentialRevoked` events MAY be emitted, when the corresponding operations are performed, to allow off-chain systems to monitor credential status efficiently. Credential revocation is not mandated, but MAY be implemented via burning the associated NFT.

## Rationale

&lt;!-- TODO --&gt;

## Backwards Compatibility
This standard is compatible with current [ERC-721](/EIPs/EIPS/eip-721) standards. It adds new functions without modifying the existing [ERC-721](/EIPs/EIPS/eip-721) functionality.

## Reference Implementation
```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;
import &quot;./IERC7861.sol&quot;;

contract ERC7861 is ERC721, IERC7861 {
    string private immutable _issuer;
    string private immutable _credentialType;
    string private immutable _verificationMethod;
    string private immutable _encryptionMethod;

    event CredentialIssued(uint256 indexed tokenId, address indexed to);

    event CredentialRevoked(uint256 indexed tokenId);


    constructor(
        string memory name_, 
        string memory symbol_,
        string memory issuer_,
        string memory credentialType_,
        string memory verificationMethod_
    ) ERC721(name_, symbol_) {
        require(bytes(issuer_).length &gt; 0, &quot;ERC7861: issuer cannot be empty&quot;);
        require(bytes(credentialType_).length &gt; 0, &quot;ERC7861: credential type cannot be empty&quot;);
        _issuer = issuer_;
        _credentialType = credentialType_;
        _verificationMethod = verificationMethod_;
        _encryptionMethod = &quot;lit-protocol&quot;; // Example decentralized encryption
    }

    function issuer() external view override returns (string memory) {
        return _issuer;
    }

    function credentialType() external view override returns (string memory) {
        return _credentialType;
    }

    function encryptionMethod() external view override returns (string memory) {
        return _encryptionMethod;
    }

    function verificationMethod() external view override returns (string memory) {
        return _verificationMethod;
    }

    function credentialURI(uint256 tokenId) external view override returns (string memory) {
        require(_exists(tokenId), &quot;ERC7861: URI query for nonexistent token&quot;);
        // Implementation depends on how you want to store/generate URIs
        return &quot;&quot;;
    }

    function isRevoked(uint256 tokenId) external view override returns (bool) {
        // Implementation depends on revokation system, example for revokation on burning
        return !_exists(tokenId); 
    }

    /// @dev See {IERC165-supportsInterface}.
    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
        return interfaceId == bytes4(0x74699c4e) || super.supportsInterface(interfaceId);
    }

    /// @notice Issues a new credential to an address
    /// @param to The address to issue the credential to
    /// @param tokenId The token ID of the credential
    function issueCredential(address to, uint256 tokenId) external {
        // Implement access control as needed
        _mint(to, tokenId);
        emit CredentialIssued(tokenId, to);
    }

    /// @notice Revokes an existing credential
    /// @param tokenId The token ID of the credential to revoke
    function revokeCredential(uint256 tokenId) external {
        // Implement access control as needed
        require(_exists(tokenId), &quot;ERC7861: Cannot revoke nonexistent credential&quot;);
        _burn(tokenId);
        emit CredentialRevoked(tokenId);
    }
}
```

## Security Considerations
Implementers of the [ERC-7861](/EIPs/EIPS/eip-7861) standard must enforce strict access control to ensure only authorized parties can issue or revoke credentials. Implementers must also carefully consider access control for setting credential properties, protecting the integrity of the collection&apos;s credential information.

Credentials should be non-transferable to maintain authenticity and prevent unauthorized transfers. Override transfer functions to enforce this if needed.

The `credentialURI` should not contain sensitive information, as it is publicly accessible. Sensitive data should be encrypted and stored off-chain, with the `credentialURI` pointing to the location of this encrypted data; encryption is essential for any sensitive data stored on public storage solutions like IPFS.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 14 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7861</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7861</guid>
      </item>
    
      <item>
        <title>Delayed State Root</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7862-delayed-execution-layer-state-root/22559</comments>
        
        <description>## Abstract

This proposal decouples state root computation from block validation by deferring the execution layer&apos;s state root reference by one block. Each block&apos;s header contains the post-state root of the previous block rather than its own. Validators can attest to block validity without waiting for state root computation.

## Motivation

State root computation is a significant bottleneck in block production. With [EIP-7732](/EIPs/EIPS/eip-7732) (ePBS), builders have tighter timing constraints. [EIP-7928](/EIPs/EIPS/eip-7928) (Block-Level Access Lists) enables parallel state access but doesn&apos;t help with state root computation for builders.

With delayed state roots:

1. **Builders compute one state root per slot** (for the previous block) instead of thousands during the MEV auction window
2. **State root computation can use BAL data** from the previous block to parallelize proof generation
3. **The critical path shifts**: state root computation is frontloaded to the beginning of the slot rather than blocking attestations

The state root in block `n` represents the post-state of block `n-1` (equivalently: the pre-state of block `n`). Light clients experience one slot of additional latency for state proofs.

## Specification

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

### Header

The `state_root` field semantics change. No new fields are added.

```python
class Header:
    parent_hash: Hash32
    ommers_hash: Hash32
    coinbase: Address
    state_root: Root  # Post-state of block (n-1), i.e., pre-state of this block
    transactions_root: Root
    receipt_root: Root
    bloom: Bloom
    difficulty: Uint
    number: Uint
    gas_limit: Uint
    gas_used: Uint
    timestamp: U256
    extra_data: Bytes
    prev_randao: Bytes32
    nonce: Bytes8
    base_fee_per_gas: Uint
    withdrawals_root: Root
    blob_gas_used: U64
    excess_blob_gas: U64
    parent_beacon_block_root: Root
    requests_hash: Hash32
    block_access_list_hash: Hash32
```

### BlockChain

The `BlockChain` object tracks the last computed state root:

```python
class BlockChain:
    blocks: List[Block]
    state: State
    chain_id: U64
    last_computed_state_root: Root
```

### Header Validation

```python
def validate_header(chain: BlockChain, header: Header) -&gt; None:
    if header.number &lt; 1:
        raise InvalidBlock

    parent_header = chain.blocks[-1].header

    # Verify delayed state root matches the last computed state root
    if header.state_root != chain.last_computed_state_root:
        raise InvalidBlock

    # ... remaining validation unchanged
```

### State Transition

```python
def state_transition(chain: BlockChain, block: Block) -&gt; None:
    validate_header(chain, block.header)

    block_env = vm.BlockEnvironment(...)

    block_output = apply_body(
        block_env=block_env,
        transactions=block.transactions,
        withdrawals=block.withdrawals,
    )

    # Validate all roots except state_root (already validated in header)
    if block_output.block_gas_used != block.header.gas_used:
        raise InvalidBlock
    # ... other validations

    # Compute and store state root for the NEXT block
    chain.last_computed_state_root = state_root(block_env.state)

    chain.blocks.append(block)
    if len(chain.blocks) &gt; 255:
        chain.blocks = chain.blocks[-255:]
```

### Fork Activation

At activation block `F`:

```python
def apply_fork(old: BlockChain) -&gt; BlockChain:
    # Initialize last_computed_state_root to current state root
    # (post-state of block F-1)
    old.last_computed_state_root = state_root(old.state)
    return old
```

Block `F` MUST contain the post-state root of block `F-1`. From `F+1` onwards, each block contains its parent&apos;s post-state root.

## Rationale

### ePBS Compatibility

With [EIP-7732](/EIPs/EIPS/eip-7732), the `ExecutionPayloadEnvelope` contains a CL `state_root` verified at the end of `process_execution_payload`. This EIP changes only the EL header&apos;s `state_root` semantics. The CL state root verification is unaffected.

### BAL Synergy

[EIP-7928](/EIPs/EIPS/eip-7928) provides the block access list, which identifies all storage slots touched during execution. With delayed state roots, clients can:

1. Receive block `n` with BAL
2. Use the BAL to parallelize state root computation for block `n`
3. Include that root in block `n+1`

Without this EIP, BALs don’t help with state root computation: the root is only known after execution finishes, which is too late to use within the same slot. With this proposal, builders can start constructing a block without fully executing the previous one, by applying the BAL state diff to the slot’s pre-state.

### Light Client Impact

State proofs for block `n` require waiting for block `n+1`. Most light client protocols already tolerate multi-block delays for proof generation. The security model is unchanged; only timing shifts by one slot.

## Backwards Compatibility

Requires a hard fork. Clients that do not implement this change will reject blocks with delayed state roots.

## Security Considerations

### Reorganization Handling

During reorgs, clients MUST recompute `last_computed_state_root` for each block in the new canonical chain. The delayed nature does not affect reorg logic.

### Pre-state Availability

Clients MUST retain the pre-state (post-state of parent block) until the current block&apos;s state root is included in the next block. This is already standard practice for reorg handling.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 23 Dec 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7862</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7862</guid>
      </item>
    
      <item>
        <title>Block-level Warming</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7863-block-level-warming/22572</comments>
        
        <description>## Abstract

This proposal introduces block-level address and storage key warming, allowing accessed addresses and storage keys to maintain their &quot;warm&quot; status throughout an entire block&apos;s execution. Accessed slots can be effectively cached at the block level, allowing for this optimization.

## Motivation

Currently, the EVM&apos;s storage slot warming mechanism operates at the transaction level, requiring each transaction to &quot;warm up&quot; slots independently, even when accessing the same storage locations within the same block. This design does not take advantage of the fact that modern node implementations can effectively cache storage access patterns at the block level. By extending the slot warming duration to the block level, we can:

1. Reduce redundant warming costs for frequently accessed slots
2. Better align gas costs with actual computational overhead
3. Improve overall network throughput without compromising security.

As of Jan. 2025, the empirically measured efficiency gains are around 5%.


## Specification

### Mechanics

When a storage slot is accessed within a block:

1. The first access to a slot in a block incurs the cold access cost as of [EIP-2929](/EIPs/EIPS/eip-2929).
2. All subsequent accesses to the same slot within the same block incur only the warm access cost as of [EIP-2929](/EIPs/EIPS/eip-2929).
3. The warm/cold status resets at block boundaries

### Block Processing

1. At the start of each block:
   * Initialize two empty sets `block_level_accessed_addresses` and `block_level_accessed_storage_keys`
2. For each transaction in the block:
   * Before processing storage access:
     * Check if touched address is in `block_level_accessed_addresses`
     * If yes: charge `WARM_STORAGE_READ_COST`
     * If no:
       * Charge `COLD_ACCOUNT_ACCESS_COST`
       * Add address to `block_level_accessed_addresses`
     * Check if storage key is in `block_level_accessed_storage_keys`
     * If yes: charge `WARM_STORAGE_READ_COST`
     * If no:
       * Charge `COLD_SLOAD_COST`
       * Add storage key to `block_level_accessed_storage_keys`
    

### Implementation Details

The implementation modifies the block execution process to maintain block-level sets of accessed addresses and storage slots. 

#### Block-Level Storage Management

```python
def apply_body(...):
    # Initialize block-level tracking sets
    block_level_accessed_addresses = set()
    block_level_accessed_storage_keys = set()
    
    for i, tx in enumerate(map(decode_transaction, transactions)):
        # Create environment with block-level context
        env = vm.Environment(
            # ... other parameters ...
            block_level_accessed_addresses=block_level_accessed_addresses,
            block_level_accessed_storage_keys=block_level_accessed_storage_keys
        )
        
        # Process transaction and update block-level sets
        gas_used, accessed_addresses, accessed_storage_keys, logs, error = process_transaction(env, tx)
        block_level_accessed_addresses += accessed_addresses
        block_level_accessed_storage_keys += accessed_storage_keys
```

This code shows how block-level slot warming is implemented at the execution layer. The `block_level_accessed_addresses` and `block_level_accessed_storage_keys` sets are maintained throughout the block&apos;s execution and passed to each transaction&apos;s environment.

#### Transaction Processing

```python
def process_transaction(env: vm.Environment, tx: Transaction) -&gt; Tuple[Uint, Tuple[Log, ...], Optional[Exception]]:
    preaccessed_addresses = set()
    preaccessed_storage_keys = set()
    
    # Add block-level pre-accessed slots
    preaccessed_addresses.add(env.block_level_accessed_addresses)
    preaccessed_storage_keys.add(env.block_level_accessed_storage_keys)
    
    # Handle access lists from transaction
    ...
```

This adds the block-level-accessed addresses and storage keys to the preaccessed addresses and storage keys.
As a result, from the perspective of a transaction, block-level accessed addresses and storage keys are treated the same as precompiles or the coinbase address.

```python
def process_message_call(message: Message, env: Environment) -&gt; MessageCallOutput:
    return MessageCallOutput(
        # ... other fields ...
        accessed_addresses=evm.accessed_addresses,
        accessed_storage_keys=evm.accessed_storage_keys
    )
```

The message call processing tracks accessed addresses and storage keys during execution, which are then propagated back up to the transaction level and ultimately to the block level.

## Rationale

The proposal builds on several key observations:

1. **Caching Efficiency**: Modern Ethereum clients already implement sophisticated caching mechanisms at the block level. Extending address and storage key warming to match this caching behavior better aligns gas costs with actual computational costs.

2. **Backward Compatibility**: The worst-case scenario for any transaction remains unchanged - it will never pay more than the current cold access cost for its first access to a slot.

3. **Handling Reverts**: In EIP-2929, if a sub-call reverts, all accessed addresses and slots are reverted to a cold state. Under block-level warming, it remains an open question whether a failing transaction (i.e., one that reverts) should ‘unwarm’ previously warmed addresses and slots for subsequent transactions within the same block. Some propose removing this revert-induced “cold reset” altogether to maintain consistency with block-level warming. This point warrants further discussion, particularly around whether or not preserving a warmed state even upon failure aligns with the broader goal of better matching gas costs to actual client caching behavior.


4. **First Access Warms For All**: Under the proposed mechanism, the first transaction in a block that accesses and warms multiple addresses or storage slots bears the entire cost of warming, even if subsequent transactions benefit from those already-warmed slots without incurring additional costs. This approach is deemed acceptable because early execution within a block—where warming typically occurs—is generally occupied for transactions placed by professional builders aiming for top-of-block execution. Since the resulting cost discrepancy is relatively minor, a more complex cost-sharing model is avoided in favor of maintaining simplicity.
An alternative to the one-warms-for-all mechanism involves distributing the warming costs across all accesses within a block. In this approach, each transaction must at least be able to pay the cold access cost. Once all transactions in the block are executed, the total warming costs are evenly distributed, and transaction originators are refunded accordingly.

5. **Alternative Block Warming Windows**: Instead of applying warming at the block level, more advanced multi-block warming approaches can be considered. Potential options include:
    * Warming addresses and storage keys over the duration of an epoch
    * Using a ring buffer spanning `x` blocks

    Since the Execution Layer (EL) currently operates without regard to epoch boundaries, it may be preferable to maintain this design. Therefore, the second option, involving a ring buffer of size x, could be more suitable. For the ring buffer, one approach might be to store the relevant warmed information in the block header for those x blocks, but this introduces additional overhead and can complicate statelessness. Careful design would be required to manage these trade-offs (e.g., header size, client complexity) if a multi-block warming solution were adopted.

## Backwards Compatibility

This change is not backward compatible and requires a hard fork activation. However, it does not introduce any breaking changes for existing contracts, as:

1. All existing transactions will continue to work as before
2. Gas costs will only decrease, never increase
3. Contract logic depending on gas costs will remain valid, as the worst-case scenario is unchanged

## Security Considerations

1. **Memory Usage**: The set of warm slots is still bounded by block gas limit / minimum gas cost per slot access, preventing DoS attacks through excessive memory usage.

3. **MEV Considerations**: Block producers can optimize transaction ordering to maximize slot warming benefits for themselves. Third-party block builders can backrun transactions that warmed specific addresses or storage keys.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 15 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7863</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7863</guid>
      </item>
    
      <item>
        <title>Ethereum state using a unified binary tree</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7864-ethereum-state-using-a-unified-binary-tree/22611</comments>
        
        <description>## Abstract

Introduce a new binary state tree, intended to replace the hexary patricia trees. Account and storage tries are merged into a single tree with 32-byte keys, which also contains contracts code. Account data is broken into independent leaves which  are grouped by 256 in order to provide some locality.

Note: The hash function used in the current draft is not final. The current implementation uses BLAKE3 to reduce friction for EL clients experimenting with this EIP, but the final decision remains TBD. Other potential candidates include Keccak and Poseidon2. 

For Poseidon2, there&apos;s an ongoing Ethereum Foundation cryptography initiative assessing its security properties. If Poseidon2 is selected, additional specifications will be needed for field selection (BN254 scalar field, 31-bit field elements, etc.) and encoding 32-byte values into field elements.

The hash function can be switched with minimal impact on implementations as this EIP progresses toward acceptance. **Do not** assume BLAKE3 is a final decision.

## Motivation

Ethereum&apos;s long-term goal is to allow blocks to be proved with validity proof so that chain verification is as simple and fast as possible. One of the most challenging parts of achieving that goal is proving the state of the tree, which is required for EVM execution.

The current Merkle-Patricia Trie (MPT) design isn&apos;t friendly to validity proofs for many reasons, such as using RLP for node encoding, Keccak as a hashing function, being a &quot;tree of trees&quot;, and not including accounts code as part of the state.

Apart from requiring a state tree design that is friendly for block validity proofs, it&apos;s also important to have fast and small regular Merkle proofs when the amount of state to prove is small. This is useful not only for the application layer but also for supporting future protocol needs in a stateless world (e.g: inclusion lists).

Regarding these regular Merkle proofs in an MPT, since it&apos;s a hexary tree, their size is quite big on average and in worst-case scenarios. Given a 2^32 size tree, the expected size for proving a single branch is `15 * 32 * log_16(2^32) = 3840`. From a worst-case block perspective, if 30M gas is used to access only a single byte of different account codes since this code isn&apos;t chunkified, we&apos;d need `30M/2400*(5*480+24k)=330MB`.

A binary tree has a good balance between out-of-circuit and in-circuit proving. Since the tree arity is two, this reduces the size of regular Merkle proofs (i.e., `# siblings * log_arity(N)` for arity 2 is better than for arity 16). Moreover, we propose switching from Keccak to a more proving-friendly hash function, which would be more amenable to modern proving systems.

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119 and RFC 8174.

### Notable changes from the hexary structure

- The account and storage tries are merged into a single trie.
- RLP is no longer used.
- The account&apos;s code is chunked and included in the tree.
- Account data (e.g., balance, nonce, first storage slots, first code-chunks) is co-located in the tree to reduce branch openings.

### Tree structure

The proposed Binary Tree stores key-value entries where both the key and value are 32 bytes. The first 31-bytes of the key define the entry stem, and the last byte is the subindex in that stem. If two keys have the same stem, they live in the same &quot;big branch&quot; — this co-locates groups of 256 keys (i.e: keys with the same first 31-bytes).

![Image](/EIPs/assets/eip-7864/diagram2.png)
(More details about the purple/orange part in the &quot;Tree embedding&quot; section)

We can distinguish four node types:

- `InternalNode` has a `left_hash` and `right_hash` field (black).
- `StemNode` has fields `stem`, `left_hash` and `right_hash` (blue).
- `LeafNode` has a field `value` which is a 32-byte blob or `empty`. (orange).
- `EmptyNode` represents an empty node/sub-tree.

The path to a `StemNode` is defined by the key&apos;s first 248-bits (31-bytes) from MSB to LSB. From this node, a subtree of 256 values exists indexed by the key&apos;s last byte (8 bits). A newly created `StemNode` subtree (i.e: 256 values) has all leaves with `value: empty`.

The path length isn&apos;t 248-bits, but contains the minimal amount of `InternalNodes` required if other stems exist with the same prefix. As in, when walking the 248-bit path inserting a new `StemNode`, you can end on a `EmptyNode` or `StemNode`. In the former, you replace it with the new `StemNode`. In the latter, you create as many `InternalNodes` as common bits both stems have as prefixes. Another way to look at this is that there aren&apos;t _extension nodes_ in paths, but we use the minimal amount of `InternalNodes` to place `StemNode`s with common prefixes.

Below is an implementation that describes the tree structure:

```python
class StemNode:
    def __init__(self, stem: bytes):
        assert len(stem) == 31, &quot;stem must be 31 bytes&quot;
        self.stem = stem
        self.values: list[Optional[bytes]] = [None] * 256

    def set_value(self, index: int, value: bytes):
        self.values[index] = value

class InternalNode:
    def __init__(self):
        self.left = None
        self.right = None

class BinaryTree:
    def __init__(self):
        self.root = None

    def insert(self, key: bytes, value: bytes):
        assert len(key) == 32, &quot;key must be 32 bytes&quot;
        assert len(value) == 32, &quot;value must be 32 bytes&quot;
        stem = key[:31]
        subindex = key[31]

        if self.root is None:
            self.root = StemNode(stem)
            self.root.set_value(subindex, value)
            return

        self.root = self._insert(self.root, stem, subindex, value, 0)

    def _insert(self, node, stem, subindex, value, depth):
        assert depth &lt; 248, &quot;depth must be less than 248&quot;

        if node is None:
            node = StemNode(stem)
            node.set_value(subindex, value)
            return node

        stem_bits = self._bytes_to_bits(stem)
        if isinstance(node, StemNode):
            # If the stem already exists, update the value.
            if node.stem == stem:
                node.set_value(subindex, value)
                return node
            existing_stem_bits = self._bytes_to_bits(node.stem)
            return self._split_leaf(
                node, stem_bits, existing_stem_bits, subindex, value, depth
            )

        # We&apos;re in an internal node, go left or right based on the bit.
        bit = stem_bits[depth]
        if bit == 0:
            node.left = self._insert(node.left, stem, subindex, value, depth + 1)
        else:
            node.right = self._insert(node.right, stem, subindex, value, depth + 1)
        return node

    def _split_leaf(self, leaf, stem_bits, existing_stem_bits, subindex, value, depth):
        # If the stem bits are the same up to this depth, we need to create another
        # internal node and recurse.
        if stem_bits[depth] == existing_stem_bits[depth]:
            new_internal = InternalNode()
            bit = stem_bits[depth]
            if bit == 0:
                new_internal.left = self._split_leaf(
                    leaf, stem_bits, existing_stem_bits, subindex, value, depth + 1
                )
            else:
                new_internal.right = self._split_leaf(
                    leaf, stem_bits, existing_stem_bits, subindex, value, depth + 1
                )
            return new_internal
        else:
            new_internal = InternalNode()
            bit = stem_bits[depth]
            stem = self._bits_to_bytes(stem_bits)
            if bit == 0:
                new_internal.left = StemNode(stem)
                new_internal.left.set_value(subindex, value)
                new_internal.right = leaf
            else:
                new_internal.right = StemNode(stem)
                new_internal.right.set_value(subindex, value)
                new_internal.left = leaf
            return new_internal
```

### Node merkelization

Define `hash(value)` as:

- `hash([0x00] * 64) = [0x00] * 32`
- `hash(value) = H(value)`, where H is the selected cryptographic hash function.

The `value` parameter lengths can only be 32 and 64.

Merkelize each node type as follows:

- `internal_node_hash = hash(left_hash || right_hash)`
- `stem_node_hash = hash(stem || 0x00 || hash(left_hash || right_hash))`
- `leaf_node_hash = hash(value)`
- `empty_node_hash = [0x00] * 32`

Below is an implementation of these rules using BLAKE3 as a reference implementation:

```python
def _hash(self, data):
    if data in (None, b&quot;\x00&quot; * 64):
        return b&quot;\x00&quot; * 32

    assert len(data) == 64 or len(data) == 32, &quot;data must be 32 or 64 bytes&quot;
    return blake3(data).digest()  # This will be replaced with the final hash function

def merkelize(self):
    def _merkelize(node):
        if node is None:
            return b&quot;\x00&quot; * 32
        if isinstance(node, InternalNode):
            left_hash = _merkelize(node.left)
            right_hash = _merkelize(node.right)
            return self._hash(left_hash + right_hash)

        level = [self._hash(x) for x in node.values]
        while len(level) &gt; 1:
            new_level = []
            for i in range(0, len(level), 2):
                new_level.append(self._hash(level[i] + level[i + 1]))
            level = new_level

        return self._hash(node.stem + b&quot;\0&quot; + level[0])

    return _merkelize(self.root)
```

### Tree embedding

Instead of a two-layer structure like the MPT, we will embed all information into a unique `key: value` space in the proposed single tree. This section specifies which tree keys store the state&apos;s information (account header data, code, storage). The data is colocated in such way that data that is usually accessed together lives in the same `StemNode` which reduces branch openings.

The following is a big picture of what we&apos;ll continue to describe in the rest of this section:

![Image](/EIPs/assets/eip-7864/diagram1.png)

The account stem (green `account` node) contains accounts basic data, first 64-storage slots, and first 128-code chunks. This co-location of data allows having data in a single stem branch that is usually accessed together. The rest of storage slots and code-chunks are spread into groups of 256 values in the rest of the tree -- this is also done for convenience since slots/code-chunks that are close together will share the same stem branch.

| Parameter             | Value   |
| --------------------- | ------- |
| BASIC_DATA_LEAF_KEY   | 0       |
| CODE_HASH_LEAF_KEY    | 1       |
| HEADER_STORAGE_OFFSET | 64      |
| CODE_OFFSET           | 128     |
| STEM_SUBTREE_WIDTH    | 256     |
| MAIN_STORAGE_OFFSET   | 256**31 |

_It&apos;s a required invariant that `STEM_SUBTREE_WIDTH &gt; CODE_OFFSET &gt; HEADER_STORAGE_OFFSET` and that `HEADER_STORAGE_OFFSET` is greater than the leaf keys. Additionally, `MAIN_STORAGE_OFFSET` MUST be a power of `STEM_SUBTREE_WIDTH`._

Note that addresses are always passed around as an `Address32`. To convert existing addresses to `Address32`, prepend with 12 zero bytes:

```python
def old_style_address_to_address32(address: Address) -&gt; Address32:
    return b&apos;\\x00&apos; * 12 + address
```

### Header values

These are the positions in the tree at which header fields of an account are stored.

```python
def tree_hash(inp: bytes) -&gt; bytes32:
    return bytes32(blake3.blake3(inp).digest())

def get_tree_key(address: Address32, tree_index: int, sub_index: int):
    # Assumes STEM_SUBTREE_WIDTH = 256
    return tree_hash(address + tree_index.to_bytes(32, &quot;big&quot;))[:31] + bytes(
        [sub_index]
    )

def get_tree_key_for_basic_data(address: Address32):
    return get_tree_key(address, 0, BASIC_DATA_LEAF_KEY)

def get_tree_key_for_code_hash(address: Address32):
    return get_tree_key(address, 0, CODE_HASH_LEAF_KEY)
```

An account&apos;s `version`, `balance`, `nonce`, and `code_size` fields are packed with big-endian encoding in the value found at `BASIC_DATA_LEAF_KEY`:

| Name        | Offset | Size |
| ----------- | ------ | ---- |
| `version`   | 0      | 1    |
| `code_size` | 5      | 3    |
| `nonce`     | 8      | 8    |
| `balance`   | 16     | 16   |

Bytes `1..4` are reserved for future use.

The current layout and encoding allow for an extension of `code_size` to 4 bytes without changing the account version. The goal of packing these fields together in a basic-data leaf is to reduce gas costs, since we only need one branch opening compared with the usual 3 or 4 if the fields aren&apos;t packed. This also simplifies witness generation.

When any account header field is set, the `version` field is also set to zero. The `codehash` and `code_size` fields are set upon contract or EOA creation.

### Code

```python
def get_tree_key_for_code_chunk(address: Address32, chunk_id: int):
    return get_tree_key(
        address,
        (CODE_OFFSET + chunk_id) // STEM_SUBTREE_WIDTH,
        (CODE_OFFSET + chunk_id)  % STEM_SUBTREE_WIDTH
    )
```

Chunk `i` stores a 32 byte value, where bytes 1…31 are bytes `i*31...(i+1)*31 - 1` of the code (i.e. the i&apos;th 31-byte slice of it), and byte 0 is the number of leading bytes that are part of PUSHDATA (e.g. if part of the code is `...PUSH4 99 98 | 97 96 PUSH1 128 MSTORE...` where `|` is the position where a new chunk begins, then the encoding of the latter chunk would begin `2 97 96 PUSH1 128 MSTORE` to reflect that the first 2 bytes are PUSHDATA).

For precision, here is an implementation of code chunkification:

```python
PUSH_OFFSET = 95
PUSH1 = PUSH_OFFSET + 1
PUSH32 = PUSH_OFFSET + 32

def chunkify_code(code: bytes) -&gt; Sequence[bytes32]:
    # Pad to multiple of 31 bytes
    if len(code) % 31 != 0:
        code += b&apos;\\x00&apos; * (31 - (len(code) % 31))
    # Figure out how much pushdata there is after including each byte
    bytes_to_exec_data = [0] * (len(code) + 32)
    pos = 0
    while pos &lt; len(code):
        if PUSH1 &lt;= code[pos] &lt;= PUSH32:
            pushdata_bytes = code[pos] - PUSH_OFFSET
        else:
            pushdata_bytes = 0
        pos += 1
        for x in range(pushdata_bytes):
            bytes_to_exec_data[pos + x] = pushdata_bytes - x
        pos += pushdata_bytes
    # Output chunks
    return [
        bytes([min(bytes_to_exec_data[pos], 31)]) + code[pos: pos+31]
        for pos in range(0, len(code), 31)
    ]

```

### Storage

```python
def get_tree_key_for_storage_slot(address: Address32, storage_key: int):
    if storage_key &lt; (CODE_OFFSET - HEADER_STORAGE_OFFSET):
        pos = HEADER_STORAGE_OFFSET + storage_key
    else:
        pos = MAIN_STORAGE_OFFSET + storage_key
    return get_tree_key(
        address,
        pos // STEM_SUBTREE_WIDTH,
        pos % STEM_SUBTREE_WIDTH
    )
```

Note that storage slots within the same range of size `STEM_SUBTREE_WIDTH` (i.e. a range with the form `x*STEM_SUBTREE_WIDTH ... (x+1)*STEM_SUBTREE_WIDTH-1)` are all, except for the `HEADER_STORAGE_OFFSET` special case, part of a single stem.

### Fork

Described in [EIP-7612](/EIPs/EIPS/eip-7612).

### Access events

Described in [EIP-4762](/EIPs/EIPS/eip-4762).

## Rationale

This EIP defines a new Binary Tree that starts empty. Only new state changes are stored in the tree. The MPT continues to exist but is frozen. This sets the stage for a future hard fork that migrates the MPT data to this Binary Tree ([EIP-7748](/EIPs/EIPS/eip-7748)).

### Single tree design

The proposal uses a single-layer tree structure with 32-byte keys and values for several reasons:

- **Simplicity**: working with the abstraction of a key/value store makes it easier to write code dealing with the tree (e.g. database reading/writing, caching, syncing, proof creation, and verification) and upgrade it to other trees in the future. Additionally, witness gas rules can become simpler and clearer.
- **Uniformity**: the state is uniformly spread throughout the tree; even if a single contract has millions of storage slots, the contract&apos;s storage slots are not concentrated in one place. This is useful for state-syncing algorithms. Additionally, it helps reduce the effectiveness of unbalanced tree-filling attacks.
- **Extensibility**: account headers and code being in the same structure as storage makes it easier to extend both features and even add new structures if desired.

### SNARK friendliness and Post-Quantum security

The proposed design should consider the usual complexity, performance, and efficiency for out-of-circuit implementations (i.e. EL clients) and in-circuit ones for generating proofs in ZK circuits.

The tree design structure tries to be simple, by not having complex branching rules. For example, in contrast with the MPT, we avoid extension nodes injected in the middle of branches. Also, RLP encoding was removed since it adds unnecessary complexity. Although complexity can be managed more easily in out-of-circuit implementations, it&apos;s valuable to help circuit implementations be as simple as possible to avoid proving overhead.

The most important factor in the design is the cryptographic hash function used for merkleization. This hash function should have efficient implementations both out and in circuits. The hash function selection remains TBD, with several candidates under consideration:

1. **BLAKE3**:
   - Good out-of-circuit performance (i.e., for raw EL client execution)
   - Reasonable in-circuit performance for proving
   - Well-established security properties
   - Currently used in the reference implementation to facilitate experimentation

2. **Keccak**:
   - Already used in Ethereum, reducing implementation complexity
   - Well-studied security properties
   - Less efficient for circuit proving than alternatives

3. **Poseidon2**:
   - Excellent in-circuit performance for ZK proofs
   - Potentially better proving throughput
   - Security analysis still ongoing through EF cryptography initiative
   - Would require additional specification for field selection and encoding

The final hash function selection will balance these considerations, with particular attention to security, proving efficiency, and implementation complexity.

Due to recent progress in the quantum computing field, expert estimations consider that they can become real in the 2030s. NIST suggests stopping the use of ECC by 2030 too. Other alternatives, such as Verkle Trees, introduce a new cryptography stack to the protocol, which relies on elliptic curves that aren&apos;t post-quantum secure. This makes the current tree proposal attractive since it only depends on hash functions, which are still safe in this new paradigm.

Moreover, there has been impressive progress in proving systems, which indicates that we could be close to achieving the required performance for creating pre-state &amp; post-state proofs fast enough. This last point is crucial since the main advantage of Verkle Trees was having proofs that are small and fast to generate.

Finally, the current state tree proposal will probably be the final state tree used in the protocol, compared with Verkle Trees, which would eventually need to be replaced by a post-quantum secure alternative.

### Arity-2

Binary tries have been chosen primarily because they reduce the witness size. In general, in an `N`-element tree with each element having `k` children, the average size of a branch is roughly `32 * (k-1) * log(N) / log(k)` plus a few percent for overhead. 32 is the length of a hash; the `k-1` refers to the fact that a Merkle proof needs to provide all `k-1` sister nodes at each level, and `log(N) / log(k)` is an approximation of the number of levels in the tree (e.g. a tree where each node has 5 children, with 625 nodes total, would have depth 4, as `625 = 5**4` and so `log(625) / log(5) = 4`).

For any `N`, the expression is minimized at `k = 2`. Here&apos;s a table of branch lengths for different `k` values assuming `N = 2**24`:

| `k` (children per node) | Branch length (chunks) | Branch length (bytes) |
| ----------------------- | ---------------------- | --------------------- |
| 2                       | 1 * 24 = 24            | 768                   |
| 4                       | 3 * 12 = 36            | 1152                  |
| 8                       | 7 * 8 = 56             | 1792                  |
| 16                      | 15 * 6 = 90            | 2880                  |

Actual branch lengths might be slightly larger than this due to uneven distribution, but the pattern of `k=2` remains by far the best.

### Tree depth

The tree design attempts to be as simple as possible considering both out-of-circuit and circuit implementations, while satisfying our throughput constraints on proving hashes.

The proposed design avoids a full 248-bit depth as it would happen in a Sparse Merkle Tree (SMT). This approach helps reduce the hashing load in proving systems, which is currently a throughput bottleneck on commodity hardware. The choice of hash function will impact this consideration - arithmetic-friendly hash functions like Poseidon2 would have different performance characteristics than cryptographic hash functions like BLAKE3 or Keccak. There are some optimization techniques that could be applied, but they add complexity to the specification.

Moreover, we could push this further trying to introduce extension nodes in the middle of paths as done in a MPT, but this also adds complexity that might not be worth it considering the tree should be quite balanced.

### State-expiry

State-expiry strategies such as [EIP-7736](/EIPs/EIPS/eip-7736) could still be applied, requiring a change in the design. One potential solution is adding a field to the `StemNode` with `epoch` as described in the mentioned EIP. Another alternative is to use 247-bits for the stem, and have two subtrees `StemValuesNode`, which would correspond to the current 256-values, and `StemMetaNode` which is also a 256-subtree that can be used to store arbitrary stem metadata.

## Backwards Compatibility

The main breaking changes are:

- (1) Gas costs for code chunk access can have an impact on applications&apos; economic viability
- (2) Tree structure change makes in-EVM proofs of historical state no longer work

(1) can be mitigated by increasing the gas limit while implementing this EIP, allowing the same economic viability for applications.

&lt;!-- TODO:

## Test Cases

- Add comprehensive test vectors for tree operations
- Finalize hash function selection and provide test vectors for the selected function
- Add test cases for edge cases in tree operations

--&gt;

&lt;!-- TODO: Remove external link

## Reference Implementation

Python reference implementation (`github.com/jsign/binary-tree-spec`).

--&gt;

## Security Considerations

Needs discussion. &lt;!-- TODO --&gt;

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 20 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7864</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7864</guid>
      </item>
    
      <item>
        <title>Decentralised User Profiles</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/add-erc-decentralised-profile-standard/22610</comments>
        
        <description>## Abstract

This EIP proposes a standard for decentralised, interoperable user profiles known as Decentralised Profiles. Profiles are implemented as **Soul Bound Tokens (SBTs)** that are immutable, non-transferable, and tied to unique identifiers across multiple blockchain networks. The standard provides a unified structure for user metadata, including dApp-specific customisation, default profiles, and seamless cross-chain compatibility. Profiles can be leveraged for identity management, reputation systems, and personalised dApp experiences.

## Motivation

Existing solutions for decentralised identity and user profiles lack cross-chain compatibility, dApp-specific customisation, and standardisation. A unified approach is essential to:
1. Facilitate interoperable profiles across all chains.
2. Leverage the immutability and non-transferability of SBTs for secure identities.
3. Enable dApp-specific customisations, such as unique avatars.
4. Provide a robust, standards-based alternative to centralised solutions like Gravatar.
5. Ensure user control and decentralisation with profiles stored on IPFS/Arweave.
6. A common standard for Decentralised Identity that can be used across all chains.
7. Act as a Digital Passport for users, enabling seamless decentralised verification and authentication.

## Specification

### Unique Profile Identifiers

#### Decentralised Profile
Each profile is identified by:

```
&lt;username&gt;@&lt;network_slug&gt;.soul
```

- `username`: User-defined, chain-unique string.
- `network_slug`: Short identifier for the chain (e.g., `eth`, `polygon`, `xion`).
- `soul`: Fixed suffix indicating soul bound token.

Example:
`john@eth.soul`
`alice@polygon.soul`

#### Decentralised Identifier (DID)
Each profile is tied to a DID:

```
did:&lt;chain&gt;:&lt;address&gt;
```

Example:
`did:ethereum:0x123...`
`did:xion:xion1abc...`

### Metadata Structure
The profile metadata structure is designed to balance extensibility, usability, and compatibility with decentralized storage systems like IPFS. Metadata will adhere to the following schema:

```json
{
  &quot;$schema&quot;: &quot;https://json-schema.org/draft/2020-12/schema&quot;,
  &quot;title&quot;: &quot;UserProfile&quot;,
  &quot;type&quot;: &quot;object&quot;,
  &quot;properties&quot;: {
    &quot;username&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;The unique handle of the user.&quot;
    },
    &quot;avatar&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;format&quot;: &quot;uri&quot;,
      &quot;description&quot;: &quot;IPFS URI pointing to the user&apos;s main avatar image.&quot;
    },
    &quot;bio&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;description&quot;: &quot;Short description or biography of the user.&quot;
    },
    &quot;website&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;format&quot;: &quot;uri&quot;,
      &quot;description&quot;: &quot;Personal or professional website of the user.&quot;
    },
    &quot;socials&quot;: {
      &quot;type&quot;: &quot;object&quot;,
      &quot;description&quot;: &quot;User&apos;s social links.&quot;,
      &quot;properties&quot;: {
        &quot;twitter&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;format&quot;: &quot;uri&quot;,
          &quot;description&quot;: &quot;URL to the user&apos;s Twitter profile.&quot;
        },
        &quot;github&quot;: {
          &quot;type&quot;: &quot;string&quot;,
          &quot;format&quot;: &quot;uri&quot;,
          &quot;description&quot;: &quot;URL to the user&apos;s GitHub profile.&quot;
        }
      },
      &quot;required&quot;: [&quot;twitter&quot;, &quot;github&quot;],
      &quot;additionalProperties&quot;: false
    },
    &quot;default_avatar_visibility&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;enum&quot;: [&quot;public&quot;, &quot;private&quot;],
      &quot;description&quot;: &quot;Default visibility setting for the main avatar.&quot;
    },
    &quot;dapp_avatars&quot;: {
      &quot;type&quot;: &quot;object&quot;,
      &quot;description&quot;: &quot;Mapping of DApp addresses to their custom avatars and visibility settings.&quot;,
      &quot;patternProperties&quot;: {
        &quot;^0x[a-fA-F0-9]{40}$&quot;: {
          &quot;type&quot;: &quot;object&quot;,
          &quot;properties&quot;: {
            &quot;avatar&quot;: {
              &quot;type&quot;: &quot;string&quot;,
              &quot;format&quot;: &quot;uri&quot;,
              &quot;description&quot;: &quot;IPFS URI for the DApp-specific avatar.&quot;
            },
            &quot;visibility&quot;: {
              &quot;type&quot;: &quot;string&quot;,
              &quot;enum&quot;: [&quot;public&quot;, &quot;private&quot;],
              &quot;description&quot;: &quot;Visibility setting for this avatar.&quot;
            }
          },
          &quot;required&quot;: [&quot;avatar&quot;, &quot;visibility&quot;],
          &quot;additionalProperties&quot;: false
        }
      },
      &quot;additionalProperties&quot;: false
    }
  },
  &quot;required&quot;: [
    &quot;username&quot;,
    &quot;avatar&quot;,
    &quot;bio&quot;,
    &quot;website&quot;,
    &quot;socials&quot;,
    &quot;default_avatar_visibility&quot;,
    &quot;dapp_avatars&quot;
  ],
  &quot;additionalProperties&quot;: false
}
```

Here&apos;s an example using the structure above:

```json
{
  &quot;username&quot;: &quot;batman&quot;,
  &quot;avatar&quot;: &quot;ipfs://QmExampleMainAvatarCID&quot;,
  &quot;bio&quot;: &quot;Blockchain enthusiast and builder.&quot;,
  &quot;website&quot;: &quot;https://anirudha.dev&quot;,
  &quot;socials&quot;: {
    &quot;twitter&quot;: &quot;https://twitter.com/kranirudha&quot;,
    &quot;github&quot;: &quot;https://github.com/anistark&quot;
  },
  &quot;default_avatar_visibility&quot;: &quot;public&quot;,
  &quot;dapp_avatars&quot;: {
    &quot;0xDAppAddress1abcdefabcdefabcdefabcdefabcdefabcd&quot;: {
      &quot;avatar&quot;: &quot;ipfs://QmExampleAvatar1CID&quot;,
      &quot;visibility&quot;: &quot;private&quot;
    },
    &quot;0xDAppAddress2abcdefabcdefabcdefabcdefabcdefabcd&quot;: {
      &quot;avatar&quot;: &quot;ipfs://QmExampleAvatar2CID&quot;,
      &quot;visibility&quot;: &quot;public&quot;
    }
  }
}
```

#### Access Control

1. **Default Avatar Visibility**: Users can set their default avatar visibility as public or private.
2. **dApp-Specific Avatar Visibility**: Each dApp-specific avatar can also have its visibility set to public or private.

**Visibility Logic**:
- If an avatar is public, it is retrievable by any external caller.
- If an avatar is private, only the user can retrieve it. Other callers will get an encoded response alongwith error message.

### dApp-Specific Avatar Customisation
- Users can assign dApp-specific avatars or metadata.
- If no dApp-specific customisation exists, the default avatar applies.

## Rationale

The design of the Decentralised Profile Standard was guided by the need for a unified, interoperable user profile system that can operate seamlessly across all blockchain networks. Current solutions, such as ENS profiles or Gravatar, either lack cross-chain functionality, are centralised, or do not allow users to customise profiles for specific dApps. This standard addresses these shortcomings while ensuring simplicity, security, and scalability. 

### Design Decisions

1. **Decentralised Identifiers (DIDs)**
   - Using the `did:&lt;chain&gt;:&lt;address&gt;` format provides a globally unique identifier for profiles. This aligns with the decentralised identity movement and ensures compatibility with broader DID frameworks.

2. **Decentralised Profile**
   - The profile format (`username@networkslug.soul`) makes profiles human-readable and chain-specific while maintaining a universal structure. The `.soul` suffix clearly identifies profiles compliant with this standard.

3. **dApp-Specific Avatars**
   - Allowing users to assign dApp-specific avatars caters to personalisation and enhances the user experience. It supports scenarios where users may want different representations or metadata for different applications.

4. **Soul Bound Tokens (SBTs)**
   - Leveraging SBTs ensures that profiles are non-transferable, reinforcing the concept of identity ownership. SBTs prevent profiles from being sold or hijacked, making them ideal for reputation-based systems.

5. **Registry and Resolver Architecture**
   - This architecture was chosen for its extensibility and proven track record, as seen in ENS. It separates the management of profile identifiers (Registry) from the resolution of metadata (Resolver), making upgrades and integrations straightforward.

6. **Compatibility with Existing Standards**
   - The profile standard integrates with [ERC-165](/EIPs/EIPS/eip-165) for interface detection and can complement ENS or other naming systems, fostering interoperability rather than competition.

7. **Default and dApp-Specific Metadata**
   - The inclusion of both default and dApp-specific metadata ensures flexibility. If dApp-specific metadata is not set, the default profile seamlessly applies, reducing friction for developers and users.

8. **On-Chain Data Minimisation**
   - Metadata is stored off-chain (e.g., IPFS or Arweave) to minimise gas costs and support scalable operations. Only URIs and pointers are stored on-chain.

9. **Access Control**

   - Users have complete control over avatar visibility, catering to privacy preferences.
   - Specific dApp-based customizations ensure fine-grained control.

10. **dApp Identification**

   - Requiring dApps to be identified by an address ensures traceability and security.

11. **Extensibility**

   - Adding metadata fields or new visibility levels does not disrupt the standard.
   - Profiles can remain lightweight while supporting future scalability.

12. **Security**

   - Access control minimizes the risk of sensitive data exposure.
   - Metadata stored off-chain ensures minimal gas usage and flexibility.

#### Alternative Designs Considered

1. **Pure On-Chain Metadata**
   - Storing all metadata on-chain was considered but discarded due to high gas costs, limited storage capacity, and challenges in supporting complex or large datasets such as high-resolution avatars.

2. **Direct Integration with ENS**
   - While integrating with ENS was explored, it was deemed limiting for cross-chain functionality, as ENS is predominantly tied to Ethereum. Decentralised profile takes inspiration from ENS while ensuring a truly multichain approach.

3. **Fully Centralised System**
   - A centralised system would simplify implementation but contradict the core principles of decentralisation and user sovereignty.

4. **Non-SBT-Based Implementation**
   - Using standard [ERC-721](/EIPs/EIPS/eip-721) tokens for profiles was considered but rejected since transferability is unsuitable for identity management. SBTs enforce the immutability of identity ownership.

### Comparison with Related Work

- **[ERC-137](/EIPs/EIPS/eip-137) (ENS)**: Provides a robust naming service but lacks dApp-specific metadata and cross-chain functionality.
- **Centralised identity services**: Cannot leverage blockchain-specific advantages like immutability, decentralisation, and SBT integration.
- **DID Standards**: Profile must aligns with DID specifications, ensuring it fits into the broader decentralised identity ecosystem while offering features tailored to blockchain-based applications.

### Scalability and Extensibility

The Registry and Resolver architecture, combined with off-chain metadata storage, ensures that profile can scale with the growth of the blockchain ecosystem. New chains, metadata types, and customisations can be added without disrupting the core functionality or introducing breaking changes.

The design balances simplicity, extensibility, and user control, making it well-suited for adoption across a wide range of dApps, wallets, and blockchains.

### Contract Interface

The standard includes the following interface:

#### `ISoulProfile`

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.19;

interface ISoulProfile {
    struct Metadata {
        string username;
        string avatar;
        string bio;
        string website;
        mapping(string =&gt; string) socials;
        string defaultAvatarVisibility;
        mapping(address =&gt; DappAvatar) dappAvatars;
    }

    struct DappAvatar {
        string avatarURI;
        string visibility; // &quot;public&quot; or &quot;private&quot;
    }

    event ProfileCreated(address indexed user, string did, string username);
    event AvatarUpdated(address indexed user, string avatarURI, string visibility);
    event DappAvatarUpdated(
        address indexed user,
        address indexed dApp,
        string avatarURI,
        string visibility
    );

    function createProfile(string calldata username) external;
    function setDefaultAvatar(string calldata avatarURI, string calldata visibility) external;
    function setDappAvatar(
        address dApp,
        string calldata avatarURI,
        string calldata visibility
    ) external;
    function getDefaultAvatar(address user) external view returns (string memory, string memory);
    function getDappAvatar(address user, address dApp) external view returns (string memory, string memory);
}
```

### Reference Implementation

#### `SoulProfile`

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.19;

import &quot;@openzeppelin/contracts/access/Ownable.sol&quot;;
import &quot;@openzeppelin/contracts/utils/Strings.sol&quot;;
import &quot;./ISoulProfile.sol&quot;;

contract SoulProfile is Ownable, ISoulProfile {
    mapping(address =&gt; Metadata) private profiles;

    modifier onlyProfileOwner(address user) {
        require(msg.sender == user, &quot;Not authorized&quot;);
        _;
    }

    function createProfile(string calldata username) external override {
        require(bytes(username).length &gt; 0, &quot;Username cannot be empty&quot;);
        require(profiles[msg.sender].username == &quot;&quot;, &quot;Profile already exists&quot;);

        profiles[msg.sender].username = username;
        profiles[msg.sender].defaultAvatarVisibility = &quot;public&quot;; // Default to public

        emit ProfileCreated(msg.sender, generateDID(msg.sender), username);
    }

    function setDefaultAvatar(string calldata avatarURI, string calldata visibility) external override {
        require(bytes(visibility).length &gt; 0, &quot;Visibility must be set&quot;);
        profiles[msg.sender].avatar = avatarURI;
        profiles[msg.sender].defaultAvatarVisibility = visibility;

        emit AvatarUpdated(msg.sender, avatarURI, visibility);
    }

    function setDappAvatar(
        address dApp,
        string calldata avatarURI,
        string calldata visibility
    ) external override {
        require(dApp != address(0), &quot;Invalid dApp address&quot;);
        require(bytes(visibility).length &gt; 0, &quot;Visibility must be set&quot;);

        profiles[msg.sender].dappAvatars[dApp] = DappAvatar(avatarURI, visibility);

        emit DappAvatarUpdated(msg.sender, dApp, avatarURI, visibility);
    }

    function getDefaultAvatar(address user)
        external
        view
        override
        returns (string memory avatarURI, string memory visibility)
    {
        Metadata storage profile = profiles[user];
        return (profile.avatar, profile.defaultAvatarVisibility);
    }

    function getDappAvatar(address user, address dApp)
        external
        view
        override
        returns (string memory avatarURI, string memory visibility)
    {
        Metadata storage profile = profiles[user];
        DappAvatar storage dappAvatar = profile.dappAvatars[dApp];
        return (dappAvatar.avatarURI, dappAvatar.visibility);
    }

    function generateDID(address user) internal pure returns (string memory) {
        return string(abi.encodePacked(&quot;did:ethereum:&quot;, Strings.toHexString(user)));
    }
}
```

Of course, this can be extended to prepare a full registry and resolver according to ENS or similar standards. Refer to Rationale above for more information about the same.

## Backwards Compatibility

The Decentralised Profile system is designed to ensure smooth integration with existing decentralized applications (dApps) and platforms, while offering an upgrade path for future enhancements. Below are key considerations for backwards compatibility:

- **ENS Compatibility**: The system adheres to the naming conventions and standards specified in [ERC-137](/EIPs/EIPS/eip-137) (Ethereum Name Service). This ensures that any dApps or tools already using ENS-compatible names can easily integrate profiles without additional changes.

- **Flexible dApp Identification**: By using wallet addresses to identify dApps, the system avoids the need for centralized registration of dApps. Any existing or new dApp that interacts with Ethereum or compatible chains can use the standard by simply passing its address as a parameter.

- **Default Avatar Fallback**: If no specific avatar is set for a dApp, the system gracefully falls back to the default avatar. This ensures that even older dApps that do not implement the latest features can continue to work seamlessly.

- **Upgradeable Contracts**: By implementing a proxy-based architecture for all major contracts (resolver, registry, profile), the system ensures that future upgrades or changes in functionality can be deployed without disrupting existing data or workflows. Upgrades are conducted through secure proxy mechanisms like TransparentUpgradeableProxy.

- **Chain Agnosticism**: The use of decentralized identifiers (DIDs) and chain-specific network slugs ensures interoperability across chains. This allows profiles to maintain consistency regardless of which chain they originate from, ensuring compatibility with multi-chain ecosystems.

## Security Considerations

Profile system should prioritise robust security to protect user data and prevent unauthorized access.

1. **Access Control**: Users can set visibility for their avatars (public or private). This is enforced at both the resolver and registry levels to ensure unauthorized entities cannot access private avatars. Functions that modify state (e.g., setDefaultAvatar, setDappAvatar) are protected with access controls, ensuring only the profile owner can make changes.

2. **Data Privacy**: Sensitive metadata is encrypted before storage on decentralized storage systems like IPFS or Arweave. Visibility flags ensure users can control who can view specific profile elements.

3. **Reentrancy Protection**: Functions modifying state implement the checks-effects-interactions pattern or leverage ReentrancyGuard to prevent reentrancy attacks. For example, setDappAvatar ensures that all validations are performed before updating the state.

4. **Input Validation**: All user inputs (e.g., username, visibility, dApp) are validated to ensure they meet specified criteria. Invalid or malicious inputs are rejected to prevent injection attacks or other exploits. Visibility is restricted to predefined values (&quot;public&quot; or &quot;private&quot;).

5. **Immutable DIDs**: Decentralized identifiers (DIDs) for users are immutable once created. This prevents spoofing or unauthorized changes to user identities.

6. **Fallback Mechanisms**: The system provides fallback mechanisms for fetching avatars. If a dApp-specific avatar is not found, the default avatar is returned, ensuring smooth operation without errors.

7. **Upgradeable Contracts**: Proxy contracts are used to allow for upgrades while preserving state. Upgrades are performed securely via a multi-signature governance process to minimize risks.

8. **Rate Limiting**: Rate-limiting mechanisms can be implemented to prevent spam or abuse of profile creation and update functions.

9. **Audits and Best Practices**: The contracts are designed following best practices and are to be audited regularly by independent security firms. Dependencies (e.g., OpenZeppelin contracts) are reviewed and kept up to date to mitigate vulnerabilities.

10. **dApp Address Verification**: All dApps interacting with the system must be identified by a valid address. This ensures that unauthorized or spoofed entities cannot manipulate profiles or fetch restricted data.

11. **Phishing Mitigation**: User-facing dApps are encouraged to clearly display information about interactions on-chain. Users should be warned about potential phishing attacks and advised to interact only with verified dApps.

12. **Gas Optimization**: Operations are optimized to prevent gas exhaustion during execution, which could lead to incomplete transactions. This ensures that even on congested networks, the system remains functional.

13. **Secure Fallback Functions**: Fallback functions are implemented securely to prevent accidental Ether transfers or denial-of-service attacks.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 22 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7866</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7866</guid>
      </item>
    
      <item>
        <title>Flow Control Wallet Call Capability</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/wallet-sendcalls-capability-flow-control/22624</comments>
        
        <description>## Abstract

This proposal extends [EIP-5792](/EIPs/EIPS/eip-5792) to allow dapps to downgrade their required atomicity guarantees and control the behaviour after a failed/reverted call. It introduces the batch-scope concept of `strict` vs. `loose` atomicity, where a `strict` batch remains atomic in the face of chain reorgs and a `loose` batch does not; and the per-call ability to continue after a failed/reverted call (`continue`) or stop processing (`halt`).

## Motivation

While the base EIP-5792 specification works extremely well for smart contract wallets, it does not allow the expression of the full range of flow control options that wallets can implement. For example, a dapp may only be submitting a batch for gas savings and not care about whether all calls are reverted on failure. A wallet may only be able to offer a limited form of atomicity through block builder backchannels, but that may be sufficient for a trading platform.

## Specification

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

### RPC Interface

The following subsections are modifications to the API endpoints from EIP-5792.

If a request does not match the schema defined below, the wallet MUST reject the request with an error code of `INVALID_SCHEMA`.

#### `wallet_sendCalls`

The following JSON Schema SHALL be inserted, in the request object, as values of either the batch-scope or call-scope `capabilities` objects (as appropriate) with a key of `flowControl`.

##### Batch-scope

###### Schema

```json
{
    &quot;$schema&quot;: &quot;https://json-schema.org/draft/2020-12/schema&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;additionalProperties&quot;: false,
    &quot;properties&quot;: {
      &quot;optional&quot;: {
        &quot;type&quot;: &quot;boolean&quot;
      },
      &quot;atomicity&quot;: {
        &quot;enum&quot;: [&quot;strict&quot;, &quot;loose&quot;, &quot;none&quot;]
      }
    }
}
```

###### Example Request

```js
[
  {
    &quot;version&quot;: &quot;1.0&quot;,
    &quot;from&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
    &quot;chainId&quot;: &quot;0x01&quot;,
    &quot;calls&quot;: [],
    &quot;capabilities&quot;: {
      &quot;flowControl&quot;: {
        &quot;atomicity&quot;: &quot;loose&quot;
      }
    }
  }
]

```


##### Call-scope

###### Schema

```json
{
    &quot;$schema&quot;: &quot;https://json-schema.org/draft/2020-12/schema&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;additionalProperties&quot;: false,
    &quot;properties&quot;: {
      &quot;optional&quot;: {
        &quot;type&quot;: &quot;boolean&quot;
      },
      &quot;onFailure&quot;: {
        &quot;enum&quot;: [&quot;rollback&quot;, &quot;halt&quot;, &quot;continue&quot;]
      }
    }
}
```

###### Example Request

```js
[
  {
    &quot;version&quot;: &quot;1.0&quot;,
    &quot;from&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
    &quot;chainId&quot;: &quot;0x01&quot;,
    &quot;calls&quot;: [
      {
        &quot;to&quot;: &quot;0xd46e8dd67c5d32be8058bb8eb970870f07244567&quot;,
        &quot;value&quot;: &quot;0x182183&quot;,
        &quot;data&quot;: &quot;0xfbadbaf01&quot;,
        &quot;capabilities&quot;: {
            &quot;flowControl&quot;: {
                &quot;onFailure&quot;: &quot;continue&quot;
            }
        }
      }
    ]
  }
]
```

#### `wallet_getCapabilities`

The following JSON Schema is inserted into the per-chain object returned from `wallet_getCapabilities` with a key of `flowControl`.

##### Schema

```json
{
    &quot;$schema&quot;: &quot;https://json-schema.org/draft/2020-12/schema&quot;,
    &quot;type&quot;: &quot;object&quot;,
    &quot;additionalProperties&quot;: false,
    &quot;minProperties&quot;: 1,
    &quot;properties&quot;: {
        &quot;none&quot;: { &quot;$ref&quot;: &quot;#/$defs/onFailure&quot; },
        &quot;loose&quot;: { &quot;$ref&quot;: &quot;#/$defs/onFailure&quot; },
        &quot;strict&quot;: { &quot;$ref&quot;: &quot;#/$defs/onFailure&quot; }
    },
    &quot;$defs&quot;: {
        &quot;onFailure&quot;: {
            &quot;type&quot;: &quot;array&quot;,
            &quot;uniqueItems&quot;: true,
            &quot;minItems&quot;: 1,
            &quot;items&quot;: {
                &quot;enum&quot;: [&quot;rollback&quot;, &quot;halt&quot;, &quot;continue&quot;]
            }
        }
    }
}
```

##### Example Response

```js
{
    &quot;0x1&quot;: {
        &quot;flowControl&quot;: {
            &quot;loose&quot;: [&quot;halt&quot;, &quot;continue&quot;],
            &quot;strict&quot;: [&quot;continue&quot;]
        }
    }
}
```

### Concepts

#### Call Failure

&lt;!-- TODO: is a &quot;call failure&quot; the same as a &quot;revert&quot;? --&gt;

#### Rollback

A rollback is informally defined as &quot;causing no meaningful changes on chain.&quot; A
rolled back batch only makes gas accounting and bookkeeping (eg. nonce)
changes. In other words, a rollback is the default behaviour of EIP-5792 when
a call fails.

#### Critical Calls

A critical call is a call that causes the entire batch to rollback on failure,
and correspondingly a non-critical call does not. Specifically, a critical call
has a call-scope `onFailure` of `rollback` (or no `onFailure` present),
while non-critical calls have either `halt` or `continue`.

#### Atomicity Levels

This proposal introduces three atomicity levels: strict, loose, and none; enabled
by setting batch-scope `atomicity` to `strict`, `loose`, or `none` respectively.
Strict may also be enabled by omitting `atomicity` entirely.

Strict atomicity is simply naming the default behaviour of EIP-5792: calls
within a single batch MUST be contiguous and applied atomically (or the batch
rolled back.)

Loose atomicity, on the other hand, is a weaker guarantee. In the event of a
block reorg, any number of calls from the batch MAY appear on chain (possibly
interspersed with other transactions). If there are no block reorgs, loose
atomicity MUST provide the same guarantees as strict.

The none level of atomicity only provides the guarantee that the calls appear on
chain in the order they are in the batch. Any number of calls from the batch
MAY appear on chain (possibly interspersed with other transactions).

### Behaviour

#### `wallet_sendCalls`

The wallet MUST reject `wallet_sendCalls` requests with error code
`MISSING_CAP` where both:

 * the batch-scope `flowControl` capability **is not** present; and
 * a call-scope `flowControl` capability **is** present.

Note that the above requirement still applies if the call-scope `flowControl`
capability is marked as optional.

When `flowControl` is present in the batch-scope `capabilities`, the following
changes override the behaviour specified in EIP-5792.

##### Removed Requirements

These requirements defined in EIP-5792 are removed:

&gt; The wallet:
&gt;
&gt; * MUST NOT await for any calls to be finalized to complete the batch
&gt; * MUST submit multiple calls as an atomic unit in a single transaction
&gt; * MAY revert all calls if any call fails
&gt; * MUST NOT execute any further calls after a failed call
&gt; * MAY reject the request if one or more calls in the batch is expected to
&gt;   fail, when simulated sequentially

##### Added Requirements

The wallet:

###### Batch Atomicity

* MAY break the batch over multiple transactions.
* MUST treat a missing batch-scope `atomicity` level as equivalent to `strict`.
* MUST provide strict guarantees (as defined above) when the batch-scope
  `atomicity` is `strict`.
* MUST provide _at least_ loose guarantees (as defined above) when the
  batch-scope `atomicity` is `loose`.
* MUST provide _at least_ the in-order call inclusion guarantee (as defined
  above) when the batch-scope `atomicity` is `none`.
* MAY provide loose guarantees (as defined above) when the batch-scope
  `atomicity` is `none`.
* MAY provide strict guarantees (as defined above) when the batch-scope
  `atomicity` is `loose` or `none`.
* MUST rollback the batch if one or more critical calls (as defined above) fail.
* MUST NOT rollback the batch if zero critical calls (as defined above) fail.
  * In other words, if the only failures are non-critical, the successful calls
    have to appear on chain.
* MUST NOT execute a call (or ever allow a call to be executed) more than once.

###### Flow Control

* MUST treat a missing call-scope `flowControl` capability as equivalent to
  setting `onFailure` to `rollback`.
* MUST treat a missing call-scope `onFailure` mode as equivalent to `rollback`.
* MUST NOT execute any calls following a failed call with `onFailure` set to
  `halt`.
* MUST continue to execute calls as normal following a failed call with
  `onFailure` set to `continue`.

###### Errors

* MUST reject (with error code `REJECTED_LEVEL`) batches containing at least one
  critical call if the batch requests an atomicity level that the wallet can
  provide but the user rejected (such as might happen with an
  [EIP-7702](/EIPs/EIPS/eip-7702) set code transaction.)
  * Note that this only applies to user rejections specifically because of
    atomicity. It does not change the behaviour for batches rejected for other
    reasons. This error code MUST NOT be used for other rejection reasons.
* MUST reject (with error code `UNSUPPORTED_LEVEL`) batches containing at least
  one critical call if the batch requests an atomicity level the wallet cannot
  provide for any reason other than user rejection.
  * Wallets supporting `strict` but not `loose` SHOULD NOT reject `loose`
    batches and SHOULD instead upgrade the request to strict atomicity.
  * Note that a batch with exactly one call _always_ satisfies the requirements
    of strict atomicity.
* MUST reject (with error code `UNSUPPORTED_ON_FAIL`) batches containing
  unsupported `onFailure` modes.
* MUST reject (with error code `UNSUPPORTED_FLOW`) batches containing
  unsupported combinations/orderings of call-scope `onFailure` modes.
    * Wallets MUST reject `rollback` when used in a `none` batch, even if the
      batch is upgraded to `loose` or `strict` atomicity. This also applies to
      calls that do not specify an explicit `onFailure` mode.
* MAY reject (with error code `ROLLBACK_EXPECTED`) the request if the batch is
  expected to be rolled back.
* SHOULD inform the user before executing any calls if any call in the batch is
  expected to fail.


#### `wallet_getCallsStatus`

When `wallet_getCallsStatus` is called with a batch identifier corresponding to
a batch submitted with the batch-scope `flowControl` capability enabled, the
following changes override the behaviour defined in EIP-5792. Note that:

* There are no changes when called with a batch without this capability enabled;
  and
* Even if the behaviour of the batch is not changed from the default (eg.
  setting `atomicity` to `strict` and omitting the `flowControl` capability for
  all calls), the following changes still apply.

##### Removed Requirements

These requirements defined in EIP-5792 are removed:

&gt; * If a wallet executes multiple calls **atomically** in a single transaction,
&gt;   `wallet_getCallsStatus` MUST return an object with a `receipts` field that
&gt;   contains a single transaction receipt, corresponding to the transaction
&gt;   in which the calls were included.
&gt; * If a wallet executes multiple calls **non-atomically** through some
&gt;   `capability` defined elsewhere, `wallet_getCallsStatus` MUST return an
&gt;   object with a `receipts` field that contains **an array of receipts** for
&gt;   all transactions containing batch calls that were included onchain. This
&gt;   includes the batch calls that were included on-chain but eventually
&gt;   reverted.


##### Added Requirements

###### Capabilities

The returned capabilities object:

* MUST contain a `flowControl` key set to exactly the boolean `true`.
    * It may be tempting to include additional detail about the status of
      individual calls here, but don&apos;t. Instead use a multi-status capability
      defined elsewhere.

###### Receipts

The returned `receipts` array:

* MUST NOT contain more than one receipt for the same transaction.
* SHOULD NOT contain receipts for transactions without a call from the requested
  batch.
* MUST contain exactly one receipt capturing each successful call.
    * Multiple calls MAY be captured in one receipt, but the successful
      execution of one call MUST NOT be captured by multiple receipts.
    * Given two calls (_A_ and _B_) in a batch, the following are non-exhaustive
      example combinations of calls-per-receipt. Each `(...)` is a receipt from
      a single transaction.
        * Valid Examples:
            * `[(successful A, successful B)]`
            * `[(successful A), (successful B)]`
            * `[(successful A, unsuccessful B), (successful B)]`
            * `[(unsuccessful A), (successful A), (successful B)]`
        * Invalid Examples:
            * `[(successful A, unsuccessful B), (successful A, successful B)]`
            * `[(successful A, successful A), (successful B)]`
* MAY contain one or more receipts capturing each failed call.
    * For example, the wallet may retry a transaction with a higher gas limit.
      Both the failed and successful transaction receipts can be included,
      though only the successful receipt must be.
* SHOULD be stable over multiple `wallet_getCallsStatus` requests, with only new
  receipts being appended.
    * For example:
        * `[(unsuccessful A)]` followed by `[(unsuccessful A), (successful A)]`
        is valid; but
        * `[(unsuccessful A)]` followed by `[(successful A)]` should be avoided.


##### Status Codes

This proposal modifies some of the status codes for use with EIP-5792&apos;s
`GetCallsResult.status` field, and introduces the following new codes:

| Code   | Description           |
|--------|-----------------------|
| `102`  | Partially Executed    |
| `207`  | Partial Success       |

An &quot;included&quot; call, in this section, is defined as having either been
successfully or unsuccessfully executed. A call that has been recorded on chain,
but has not yet been executed, does not qualify as included. Executed calls
contained in batches that may still be rolled back also do not qualify as
included.

A batch is &quot;complete&quot; when all of the calls in the batch (up to and including a
failed call with an `onFailure` mode of `halt` should one be present) have been
included and the wallet will not resubmit failed calls.

###### `100` Pending

Status `100` MUST NOT be returned if any calls in the batch have been included
on chain.

###### `102` Partially Executed

Status `102` SHALL be returned only when all of the following are true:

 * At least one call in the batch has been included on chain; and
 * The batch is not complete.

Responses with status `102` MUST contain at least one receipt, and SHOULD
contain receipts for all transactions with calls that have been included.

Note that a receipt capturing a failed call does not mean the call will
ultimately fail. Wallets can resubmit calls (eg. with a higher gas limit), and
the call may be executed successfully eventually.

###### `200` Confirmed

Status `200` MUST NOT be returned if any calls in the batch failed (including
batch rollback, and the `onFailure` modes `halt`/`continue`).

###### `207` Partial Success

Status `207` SHALL be returned only when all of the following are true:

* At least one call in the batch has been included and succeeded;
* At least one call in the batch with an `onFailure` mode of `continue`
   has been included and failed;
* No calls with an `onFailure` mode of `rollback` have been included and failed;
* No calls with an `onFailure` mode of `halt` have been included and failed;
  and
* The batch is complete.

###### `500` Chain Rules Failure

To clarify, status `500` is the correct code when the batch has rolled back _or_
when all calls are non-critical and have all failed.

If any calls are included and succeeded, one of `200`, `207`, or `600` should be
returned instead.

###### `600` Partial Chain Rules Failure

Status `600` SHALL be returned only when all of the following are true:

* At least one call in the batch has been included and succeeded;
* At least one call in the batch with an `onFailure` mode of `halt` has been
  included and failed;
* No calls with an `onFailure` mode of `rollback` have been included and failed;
  and
* The batch is complete.

#### `wallet_getCapabilities`

The response to `wallet_getCapabilities` indicates what call-scope `onFailure`
modes are supported for each supported batch-scope `atomicity` level for
batches with two or more calls. Support, here, means &quot;natively supports.&quot; A
wallet that offers `strict` atomicity but not `loose` MUST NOT advertise
support for `loose` (even if the wallet will upgrade `loose` to `strict`
without an error.)

The wallet:

* MAY respond with one, two, or three `atomicity` levels.
* MAY respond with one, two, or three `onFailure` modes in each `atomicity`
  level. The levels do not need to support the same modes.
* MUST include the particular atomicity / onFailure combination if it is
  supported _at all_. For example, if particular orderings are impossible—say
  `rollback` before `halt` is fine, but `halt` before `rollback` is not—then
  both `rollback` and `halt` have to be included in the array.

##### Examples

###### Plain Externally Owned Account (EOA)

A plain EOA might offer `halt` functionality by submitting one transaction per
block, and `continue` by submitting all calls at once.

```js
{
    &quot;0x1&quot;: {
        &quot;flowControl&quot;: {
            &quot;none&quot;: [ &quot;halt&quot;, &quot;continue&quot; ]
        }
    }
}
```

###### Shielded Mempool Externally Owned Account (EOA)

Unlike a plain EOA, a shielded mempool can provide additional guarantees about
transaction atomicity. In this example, the wallet only offers the
`onFailure` mode of `continue` when using `none` atomicity, but offers all three levels when using
`loose`.

```js
{
    &quot;0x1&quot;: {
        &quot;flowControl&quot;: {
            &quot;none&quot;: [ &quot;continue&quot; ],
            &quot;loose&quot;: [ &quot;rollback&quot;, &quot;halt&quot;, &quot;continue&quot; ]
        }
    }
}
```

###### Smart Contract Wallet

In this example, the wallet will service batches specifying `none` and `loose`
as if they requested `strict`. Even though the batches will work, the
`wallet_getCapabilities` response does not list `none` or `loose`.

```js
{
    &quot;0x1&quot;: {
        &quot;flowControl&quot;: {
            &quot;strict&quot;: [ &quot;rollback&quot; ]
        }
    }
}
```

### Error Codes

| Name                  | Value         |
| --------------------- | ------------- |
| `INVALID_SCHEMA`      | &lt;!-- TODO --&gt; |
| `MISSING_CAP`         | &lt;!-- TODO --&gt; |
| `REJECTED_LEVEL`      | &lt;!-- TODO --&gt; |
| `UNSUPPORTED_LEVEL`   | &lt;!-- TODO --&gt; |
| `UNSUPPORTED_ON_FAIL` | &lt;!-- TODO --&gt; |
| `UNSUPPORTED_FLOW`    | &lt;!-- TODO --&gt; |
| `ROLLBACK_EXPECTED`   | &lt;!-- TODO --&gt; |

## Rationale
&lt;!--
  The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages.

  The current placeholder is acceptable for a draft.

  TODO: Remove this comment before submitting
--&gt;

TBD

## Backwards Compatibility

&lt;!--

  This section is optional.

  All EIPs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. The EIP must explain how the author proposes to deal with these incompatibilities. EIP submissions without a sufficient backwards compatibility treatise may be rejected outright.

  The current placeholder is acceptable for a draft.

  TODO: Remove this comment before submitting
--&gt;

No backward compatibility issues found.

## Security Considerations

App developers cannot treat each call in a batch as an independent transaction
unless the atomicity level is strict. In other words, there may be additional
untrusted transactions between any of the calls in a batch. Calls that failed
may eventually flip to succeeding, and vice versa. Even strictly atomic batches
can flip between succeeding/failing in the face of a block reorg. The calls in
loosely atomic batches can be included in separate, non-contiguous blocks. There
is no constraint over how long it will take all the calls in a batch to be
included. Apps should encode deadlines and timeout behaviors in the smart
contract calls, just as they do today for transactions, including ones otherwise
bundled.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 17 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7867</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7867</guid>
      </item>
    
      <item>
        <title>Hardware and Bandwidth Recommendations</title>
        <category>Informational/</category>
        
          <comments>https://ethereum-magicians.org/t/hardware-and-bandwidth-recommendations-for-full-nodes-and-validators/22675</comments>
        
        <description>## Abstract

This proposal specifies hardware and bandwidth recommendations for different types of Ethereum nodes:

- **Full nodes**: Nodes that follow the tip of the chain without necessarily proposing blocks.
- **Validators**: Split into:
  - **Attesters**: Validators that validate and attest to blocks created by proposers.
  - **Local block builders** (Proposers): Validators that create blocks locally and broadcast them to the network.

The resource-intensive aspect for local block builders lies in creating the block and quickly broadcasting the data required for attesters to validate it in time.

We note that it may be possible to run a client with less than the recommended specifications, however benchmarks and decision-making will be made with respect to these recommendations.

## Motivation

Clear system specifications are crucial for:

- Ensuring meaningful benchmark comparisons across different client implementations.
- Enabling informed decision-making about protocol upgrades and their resource usage implications.
- Providing clear guidance for node operators to ensure alignment with future network requirements.

Without a shared understanding of target hardware specifications:

- Benchmark results lose significance due to inconsistent testing environments.
- Decision-making becomes challenging for implementation choices, as performance characteristics are heavily hardware-dependent.
- Network participants lack clear guidance for hardware investments.

## Specification

### Roles and Their Recommended Specifications

Node operators typically run both an **Execution Layer (EL)** client and a **Consensus Layer (CL)** client on the same machine. The specifications below assume the combined resource usage of both.

| Node Type               | Storage   | Memory | CPU Cores / Threads | **PassMark CPU Rating** | Bandwidth Download / Upload |
| ----------------------- | --------- | ------ | ------------------- | ----------------------- | --------------------------- |
| **Full Node**           | 4 TB NVMe | 32 GB  | 4c / 8t             | ~1000 ST / 3000 MT      | 50 Mbps / 15 Mbps           |
| **Attester**            | 4 TB NVMe | 64 GB  | 8c / 16t            | ~3500 ST / 25000 MT     | 50 Mbps / 25 Mbps           |
| **Local Block Builder** | 4 TB NVMe | 64 GB  | 8c / 16t            | ~3500 ST / 25000 MT     | 100 Mbps / 50 Mbps          |

*Approximate single-thread (ST) and multi-thread (MT) PassMark CPU scores. For example, a PassMark ST rating of 3500 and an MT rating of 25000 typically corresponds to upper mid-range server CPUs circa 2024–2025.*

## Rationale

### Storage

- **Recommended**: 4 TB NVMe M.2 drive with:
  - **Sequential R/W**: At least ~500 MB/s
  - **Random 4K Read IOPS**: At least ~50,000
  - **Random 4K Write IOPS**: At least ~15,000
- **Verifying IO Performance**: You can use the following commands to benchmark your local storage IO speeds:

  Sequential R/W:

  ```
  fio --name=seq --filename=test --direct=1 --ioengine=libaio --iodepth=64 --bs=1M --size=4G --rw=readwrite
  ```

  Random 4K R/W:

  ```
  fio --randrepeat=1 --ioengine=libaio --direct=1 --gtod_reduce=1 --name=test --filename=test --bs=4k --iodepth=64 --size=4G --readwrite=randrw --rwmixread=75
  ```

- **Why NVMe over SATA?**
  - NVMe drives have significantly higher throughput and lower latency than SATA SSDs.  
  - Drives without DRAM (DRAMless) or with QLC flash are not advised, due to lower endurance and potentially lower sustained performance.
- **On Endurance (TBW)**  
  - Running a node involves frequent writes (e.g., database updates, logs). Ensure that the SSD’s Total Bytes Written (TBW) rating is sufficient for multi-year operation.
- **Capacity Considerations**  
  - As of January 2025, 2 TB can still work, but daily chain growth makes 4 TB more future-proof.  
  - While EIP-4444 aims to reduce historical storage requirements, the timeline for EIP-4444 remains uncertain.

### Memory

- **Why 64 GB for Validators (Attesters / Local Block Builders)?**
  - Running an Ethereum validator (both EL &amp; CL clients) can be memory-intensive, with state cache dominating RAM usage.
  - Certain memory intensive client combinations have historically failed with 16 GB. It is possible to tune cache size in different clients to make it work, however we do not assume that the average user will do this.
  - Preliminary benchmarks highlighting zk-STARK memory usage suggest cryptographic operations can demand significant RAM.
  - Relative to total hardware costs, upgrading from 32 GB to 64 GB is a small price but can improve stability and is more future proof with regards to zk-STARKs.

### CPU

- **Single vs. Multi-thread Performance**
  - Attesters and local block builders benefit from both high single-thread and multi-thread performance.  

### Bandwidth

#### Local Block Builders

- **Recommended**: 100 Mbps download, 50 Mbps upload.
- **Rationale**:  
  - Distributing blocks is highly bandwidth-intensive.  
  - If a builder cannot meet these speeds, they risk slower propagation and causing late blocks.  
  - In extreme cases, a low-bandwidth node could propose partially full blocks or one that includes fewer blobs to mitigate slow broadcast.

#### Attesters

- **Recommended**: 50 Mbps download, 25 Mbps upload.
- **Minimum tested**: 15 Mbps (as per ethPandaOps simulations where 40% of the network had Gigabit connections and the other 60% had 15 Mbps upload).
  - However, real-world performance depends on peer network topology. A node with poor bandwidth could in theory quickly share data with a well-connected peer with good bandwidth which means that this peer could quickly seed the network.
- **Rationale**:
  - 25 Mbps was chosen as a buffer to account for these miscellaneous factors that are harder to predict.

#### Validators Using MEV-Boost

- **Recommended**: 50 Mbps download / 25 Mbps upload.
- **Rationale**:
  - Most MEV-relay interactions involve fetching bundles and block headers, which can be done within typical broadband speeds.
  - While the local validator will also share the block with its peers, the relay will do the same which reduces the need for local bandwidth.
  - However, there may be cases where your validator will still build a local block, such as if no MEV-relay responds or if the value of the MEV reward is lower than the minimum configuration set in MEV-Boost. In these circumstances, the recommendations for **Local Block Builders** would be relevant.

#### Full Nodes

- **Recommended**: 50 Mbps download / 15 Mbps upload.
- **Rationale**:
  - Full nodes currently participate in sampling and must track the chain tip, but are not as latency-sensitive as attesters or local block builders.
  - They can operate on lower bandwidth but risk being a slot or more behind the chain if bandwidth capacity is severely limited.

### Quick Reference Summary

- **Full Node**  
  - **Storage**: 4 TB NVMe  
  - **RAM**: 32 GB  
  - **CPU**: 4 cores / 8 threads (~1000 ST / ~3000 MT PassMark)  
  - **Bandwidth**: 50 Mbps down / 15 Mbps up  

- **Attester**  
  - **Storage**: 4 TB NVMe  
  - **RAM**: 64 GB  
  - **CPU**: 8 cores / 16 threads (~3500 ST / ~25000 MT PassMark)  
  - **Bandwidth**: 50 Mbps down / 25 Mbps up  

- **Local Block Builder**  
  - **Storage**: 4 TB NVMe  
  - **RAM**: 64 GB  
  - **CPU**: 8 cores / 16 threads (~3500 ST / ~25000 MT PassMark)  
  - **Bandwidth**: 100 Mbps down / 50 Mbps up  

## Backwards Compatibility

This EIP is informational and requires no protocol changes. We recommend that future EIPs include an assessment of their impact on these hardware recommendations.

## Security Considerations

N/A

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 26 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7870</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7870</guid>
      </item>
    
      <item>
        <title>Wallet Signing API</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/new-erc-wallet-signing-api/22718</comments>
        
        <description>## Abstract

Defines a new JSON-RPC method `wallet_sign` which enables apps to ask a wallet to sign [EIP-191](/EIPs/EIPS/eip-191) messages.

Applications can use this JSON-RPC method to request a signature over any version of `signed_data` as defined by [EIP-191](/EIPs/EIPS/eip-191). The new JSON-RPC method allows for support of future [EIP-191](/EIPs/EIPS/eip-191) `signed_data` versions.

The new JSON-RPC method also supports [EIP-5792](/EIPs/EIPS/eip-5792)-style `capabilities`, and support for signing capabilities can be discovered using `wallet_getCapabilities` as defined in [EIP-5792](/EIPs/EIPS/eip-5792).

## Motivation

Wallets and developer tools currently support multiple JSON-RPC methods for handling offchain signature requests. This proposal simplifies wallet &amp; tooling implementations by consolidating these requests under a single `wallet_sign` JSON-RPC method. This also leaves room for new [EIP-191](/EIPs/EIPS/eip-191) `signed_data` versions without needing to introduce a new corresponding JSON-RPC method.

Furthermore, this new `wallet_sign` method introduces new functionalities via [EIP-5792](/EIPs/EIPS/eip-5792)-style `capabilities`.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119 and RFC 8174.
One new JSON-RPC method is introduced.

### `wallet_sign`

Requests a signature over [EIP-191](/EIPs/EIPS/eip-191) `signed_data` from a wallet.

The top-level `version` parameter is for specifying the version of `wallet_sign` should the top-level interface change.

The `request.type` parameter is for specifying the [EIP-191](/EIPs/EIPS/eip-191) `signed_data` `version` (e.g. `0x01` for structured data, `0x45` for `personal_sign` messaged). The `request.data` parameter is the corresponding data according to the `signed_data` `version`.

The optional `address` parameter is for requesting a signature from a specified address. If included, the wallet MUST respect it and only respond with a signature from that address.

The capabilities field is how an app can communicate with a wallet about capabilities that a wallet supports.

This proposal defines `request` schemas for the three `signed_data` versions currently in [EIP-191](/EIPs/EIPS/eip-191) (`0x00`, `0x01`, `0x45`). Any future `signed_data` versions can be supported by `wallet_sign`, and their `request` interfaces are left to future ERCs.

#### `wallet_sign` RPC Specification

```typescript
type Capability = {
  [key: string]: unknown;
  optional?: boolean;
}

type SignParams = {
  version: string;
  address?: `0x${string}`;
  request: {
    type: `0x${string}`; // 1-byte EIP-191 version
    data: any; // data corresponding to the above version
  };
  capabilities?: Record&lt;string, Capability&gt;;
};

type SignResult = {
  signature: `0x${string}`;
  capabilities?: Record&lt;string, any&gt;;
};
```

##### Request Interfaces

Below are `request` interfaces for the `signed_data` `version`s specified in [EIP-191](/EIPs/EIPS/eip-191) at time of writing. These include:
* `0x00` - Data with intended validator
* `0x01` - [EIP-712](/EIPs/EIPS/eip-712) Typed Data
* `0x45` - Personal Sign

Any new `request` interfaces corresponding to new `signed_data` `version`s SHOULD be defined in their own ERCs.

```typescript
type ValidatorRequest = {
  type: &apos;0x00&apos;;
  data: {
    validator: `0x${string}`; // Intended validator address
    data: `0x${string}`; // Data to sign
  };
}

type TypedDataRequest = {
  type: &apos;0x01&apos;;
  data: {
    ...TypedData // TypedData as defined by EIP-712
  }
}

type PersonalSignRequest = {
  type: &apos;0x45&apos;;
  data: {
    message: string; // UTF-8 message string
  }
}
```

##### `wallet_sign` Example Parameters

```json
{
  &quot;version&quot;: &quot;1.0&quot;,
  &quot;request&quot;: {
    &quot;type&quot;: &quot;0x45&quot;,
    &quot;data&quot;: {
      &quot;message&quot;: &quot;Hello world&quot;
    }
  }
}
```

##### `wallet_sign` Example Return Value

```json
{
  &quot;signature&quot;: &quot;0x00000000000000000000000000000000000000000000000000000000000000000e670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331&quot;,
}
```

## Rationale

&lt;!-- TODO --&gt;

## Backwards Compatibility

&lt;!-- TODO --&gt;

## Security Considerations

&lt;!-- TODO --&gt;

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 29 Jan 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7871</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7871</guid>
      </item>
    
      <item>
        <title>Max blob flag for local builders</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/max-blob-flags-for-local-builders/22734</comments>
        
        <description>## Abstract

This EIP adds a flag to the block builder in order to allow them to include a client configured maximum amount of blobs. This is an execution layer only change.

## Motivation

Currently a builder will include all blobs in their local mempool, up to the maximum amount that the protocol requires. If a builder has low bandwidth, they may include too many blobs
and subsequently end up not being able to convince the network that the blobs are available.

## Specification

- Create a parameter in block builder&apos;s configuration called `USER_CONFIGURED_MAX_BLOBS_PER_BLOCK`
- Take the minimum out of the `MAX_BLOB_GAS_PER_BLOCK` and the `USER_CONFIGURED_MAX_BLOBS_PER_BLOCK`
- If the minimum is zero, set the minimum to one.
- Use the minimum to decide how many blobs to include in the block

Note: By default `USER_CONFIGURED_MAX_BLOBS_PER_BLOCK` may be set to the maximum in the current fork.

## Rationale

By adding a flag for the local block builder, they are able to specify how many blobs they can include in a block.

## Backwards Compatibility

No backward compatibility issues found.

## Security Considerations

N/A

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 30 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7872</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7872</guid>
      </item>
    
      <item>
        <title>EOF - TXCREATE and InitcodeTransaction type</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7873-eof-txcreate-instruction-and-initcodetransaction-type/22765</comments>
        
        <description>## Abstract

EVM Object Format (EOF) removes the possibility to create contracts using creation transactions (with an empty `to` field), `CREATE` or `CREATE2` instructions. We introduce a new instruction: `TXCREATE`, as well as a new transaction type (`InitcodeTransaction`), to provide a way to create contracts using EOF containers in transaction data.

## Motivation

This EIP uses terminology from the [EIP-3540](/EIPs/EIPS/eip-3540) which introduces the EOF format.

Creation transaction and creation instructions `CREATE` and `CREATE2` are means provided by legacy EVM to deploy new code, but per requirement of removing code observability, they are not allowed to deploy EOF code. To allow Externally Owned Accounts (EOAs) to deploy EOF contracts, there must be a way to create EOF contracts using bytecode delivered in transaction data.

Additionally, the new instruction and transaction type introduced in this EIP enable contracts to create other contracts using initcode from the transaction data, which in legacy EVM is achieved via a combination of `CREATE` or `CREATE2` and loading the initcode from calldata. 

This mechanism complements `EOFCREATE` and `RETURNCODE` instructions from [EIP-7620](/EIPs/EIPS/eip-7620), and thus all use cases of contract creation that are available in legacy EVM are enabled for EOF.

Since `TXCREATE` is not restricted to EOF containers, it also serves the purpose of bootstrapping EOF contracts into the state.

## Specification

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

### Parameters

| Constant                    | Value                                                                                                                                                                                            |
|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `INITCODE_TX_TYPE`          | `Bytes1(0x06)`                                                                                                                                                                                   |
| `MAX_INITCODE_COUNT`        | `256`                                                                                                                                                                                            |
| `TX_CREATE_COST`            | Defined as `32000` in the [Ethereum Execution Layer Specs](https://github.com/ethereum/execution-specs/blob/0f9e4345b60d36c23fffaa69f70cf9cdb975f4ba/src/ethereum/shanghai/fork_types.py#L42)    |
| `STACK_DEPTH_LIMIT`         | Defined as `1024` in the [Ethereum Execution Layer Specs](https://github.com/ethereum/execution-specs/blob/0f9e4345b60d36c23fffaa69f70cf9cdb975f4ba/src/ethereum/shanghai/vm/interpreter.py#L60) |
| `GAS_CODE_DEPOSIT`          | Defined as `200` in the [Ethereum Execution Layer Specs](https://github.com/ethereum/execution-specs/blob/0f9e4345b60d36c23fffaa69f70cf9cdb975f4ba/src/ethereum/shanghai/vm/gas.py#L44)          |
| `TX_DATA_COST_PER_ZERO`     | Defined as `4` in the [Ethereum Execution Layer Specs](https://github.com/ethereum/execution-specs/blob/0f9e4345b60d36c23fffaa69f70cf9cdb975f4ba/src/ethereum/shanghai/fork_types.py#L41)        |
| `TX_DATA_COST_PER_NON_ZERO` | Defined as `16` in the [Ethereum Execution Layer Specs](https://github.com/ethereum/execution-specs/blob/0f9e4345b60d36c23fffaa69f70cf9cdb975f4ba/src/ethereum/shanghai/fork_types.py#L40)       |
| `MAX_CODE_SIZE`             | Defined as `24576` in [EIP-170](/EIPs/EIPS/eip-170)                                                                                                                                                    |
| `MAX_INITCODE_SIZE`         | Defined as `2 * MAX_CODE_SIZE` in [EIP-3860](/EIPs/EIPS/eip-3860)                                                                                                                                      |

### Transaction Types

Introduce new transaction `InitcodeTransaction` (type `INITCODE_TX_TYPE`) which extends [EIP-1559](/EIPs/EIPS/eip-1559) (type 2) transaction by adding a new field `initcodes: List[ByteList[MAX_INITCODE_SIZE], MAX_INITCODE_COUNT]`.

The `initcodes` can only be accessed via the `TXCREATE` instruction (see below), therefore `InitcodeTransactions` are intended to be sent to contracts including `TXCREATE` in their execution.

#### Gas schedule

`initcodes` items data costs the same as calldata: transaction gas of an `InitcodeTransaction` is extended to include tokens in `initcodes` alongside tokens in `calldata`. Using the conventions from [EIP-7623](/EIPs/EIPS/eip-7623), the transaction gas is calculated as:

```python
STANDARD_TOKEN_COST = 4
TOTAL_COST_FLOOR_PER_TOKEN = 10

tokens_in_calldata = zero_bytes_in_calldata + nonzero_bytes_in_calldata * 4
tokens_in_initcodes = 0
for initcode in initcodes:
    tokens_in_initcodes += zero_bytes_in_initcode + nonzero_bytes_in_initcode * 4
tx.gasUsed = (
    21000
    +
    max(
        STANDARD_TOKEN_COST * (tokens_in_calldata + tokens_in_initcodes)
        + execution_gas_used,
        TOTAL_COST_FLOOR_PER_TOKEN * (tokens_in_calldata + tokens_in_initcodes)
    )
)
```


#### Transaction validation

- `InitcodeTransaction` is invalid if there are zero entries in `initcodes`, or if there are more than `MAX_INITCODE_COUNT` entries.
- `InitcodeTransaction` is invalid if any entry in `initcodes` is zero length, or if any entry exceeds `MAX_INITCODE_SIZE`.
- `InitcodeTransaction` is invalid if the `to` is `nil`.

Under transaction validation rules `initcodes` are not validated for conforming to the EOF specification. They are only validated when accessed via `TXCREATE`. This avoids potential DoS attacks of the mempool. If during the execution of an `InitcodeTransaction` no `TXCREATE` instruction is called, such transaction is still valid.

Other creation transactions that support contract creation (specifically type 0 &quot;Frontier,&quot; type 1 &quot;AccessList,&quot; type 2 &quot;FeeMarket&quot; transactions with an empty `to` field) will not attempt to parse EOF containers in their `input` field and will execute the code as non-EOF code. This will result in immediately executing the undefined `0xEF` instruction and halting.


#### RLP and signature

Given the definitions from [EIP-2718](/EIPs/EIPS/eip-2718) the `TransactionPayload` for an `InitcodeTransaction` is the RLP serialization of:

```
[chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to, value, data, access_list, initcodes, y_parity, r, s]
```

`TransactionType` is `INITCODE_TX_TYPE` and the signature values `y_parity`, `r`, and `s` are calculated by constructing a secp256k1 signature over the following digest:

```
keccak256(INITCODE_TX_TYPE || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to, value, data, access_list, initcodes]))
```

The [EIP-2718](/EIPs/EIPS/eip-2718) `ReceiptPayload` for this transaction is `rlp([status, cumulative_transaction_gas_used, logs_bloom, logs])`.

### Execution Semantics

Wherever not explicitly listed, the rules of EOF contract creation, as well as the `TXCREATE` instruction, should be identical or analogous to those of `CREATE2` instruction. This includes but is not limited to:

- behavior on `accessed_addresses` and address collision ([EIP-684](/EIPs/EIPS/eip-684) and [EIP-2929](/EIPs/EIPS/eip-2929))
- EVM execution frame created for the `TXCREATE` initcode - memory, account context etc.
- nonce bumping of the account of newly created contract [EIP-161](/EIPs/EIPS/eip-161)
- balance checking and transfer for the creation endowment (`value` argument)
    
Introduce a new instruction on the same block number [EIP-3540](/EIPs/EIPS/eip-3540) is activated on: `TXCREATE` (`0xed`).
    
#### `TXCREATE`
    
- deduct `TX_CREATE_COST` gas
- halt with exceptional failure if the current frame is in `static-mode`.
- pop `tx_initcode_hash`, `salt`, `input_offset`, `input_size`, `value` from the operand stack
- perform (and charge for) memory expansion using `[input_offset, input_size]`
- load initcode EOF container from the transaction `initcodes` array which hashes to `tx_initcode_hash`
    - fails (returns 0 on the stack) if such initcode does not exist in the transaction, or if called from a transaction of `TransactionType` other than `INITCODE_TX_TYPE`
        - caller&apos;s nonce is not updated and gas for initcode execution is not consumed.
    - let `initcontainer` be that EOF container, and `initcontainer_size` its length in bytes
- check that current call depth is below `STACK_DEPTH_LIMIT` and that caller balance is enough to transfer `value`
    - in case of failure return 0 on the stack, caller&apos;s nonce is not updated and gas for initcode execution is not consumed.
- **validate the initcode container and all its subcontainers recursively**
    - unlike in general validation, `initcontainer` is additionally required to have `data_size` declared in the header equal to actual `data_section` size.
    - validation includes checking that the `initcontainer` does not contain `RETURN` or `STOP`
- fails (returns 0 on the stack) if container was invalid
    - caller’s nonce is not updated and gas for initcode execution is not consumed.
- caller&apos;s memory slice `[input_offset:input_size]` is used as calldata
- execute the container and deduct gas for execution. The 63/64th rule from [EIP-150](/EIPs/EIPS/eip-150) applies.
- increment `sender` account&apos;s nonce
- calculate `new_address` as `keccak256(0xff || sender32 || salt)[12:]`, where `sender32` is the sender address left-padded to 32 bytes with zeros
- an unsuccessful execution of initcode results in pushing `0` onto the stack
    - can populate returndata if execution `REVERT`ed
    - `sender`&apos;s nonce stays updated
- a successful execution ends with initcode executing `RETURNCODE{deploy_container_index}(aux_data_offset, aux_data_size)` instruction (see [EIP-7620](/EIPs/EIPS/eip-7620)). After that:
    - load deploy EOF subcontainer at `deploy_container_index` in the container from which `RETURNCODE` is executed
    - concatenate data section with `(aux_data_offset, aux_data_offset + aux_data_size)` memory segment and update data size in the header
    - if updated deploy container size exceeds `MAX_CODE_SIZE`, instruction exceptionally aborts
    - set `state[new_address].code` to the updated deploy container
    - push `new_address` onto the stack
- deduct `GAS_CODE_DEPOSIT * deployed_code_size` gas

Note that the implementations are expected to cache the result of container validation for the time of current transaction execution, and therefore the cost of each container&apos;s validation is sufficiently covered by `InitcodeTransaction` intrinsic cost (initcodes charge).

## Rationale

### `TXCREATE` failure modes
    
`TXCREATE` has two &quot;light&quot; failure modes in case the initcontainer is not present and in case the EOF validation is unsuccessful. An alternative design where both cases led to a &quot;hard&quot; failure (consuming the entire gas available) was considered. We decided to have the more granular and forgiving failure modes in order to align the gas costs incurred to the actual work the EVM performs.

### Allowing `TXCREATE` in legacy EVM

EOF contract creation requires an exceptional possibility of calling an EOF opcode in legacy code - `TXCREATE`, because otherwise neither legacy contracts nor create transactions can deploy EOF code to bootstrap. The alternative approach was to continue using legacy creation mechanisms, by either still relying on fetching the *initcode* from memory and not satisfy the overarching requirement of code non-observability, or to abuse the legacy creation transactions mechanism, or to introduce a predeployed Creator Contract into the state.

This also makes [EIP-7698](/EIPs/EIPS/eip-7698) (EOF - Creation transaction) no longer an essential requirement for deploying EOF contracts onto the chain. The EIP could be removed from EOFv1 and withdrawn.

### New address hashing scheme

`TXCREATE` uses the scheme `new_address = keccak256(0xff || sender32 || salt)[12:]`, same as `EOFCREATE` instruction. The decision whether to include initcontainer hash into salt is left to the `TXCREATE` caller. See [EIP-7620](/EIPs/EIPS/eip-7620) for detailed rationale.

### EOF creation transactions vs deployment patterns

Relying on the EOF creation transactions as the alternative solution makes it impossible for smart contract wallets to deploy arbitrary EOF contracts (only EOAs can). At the same time, it is a use case current legacy creation rules allow, thanks to `CREATE` and `CREATE2` instructions. A workaround where those arbitrary EOF contracts are first &quot;uploaded&quot; to a factory contract, and then deployed using an `EXTDELEGATECALL`-`EOFCREATE` sequence, is very expensive, as it requires the deployed contract to be put on-chain twice. Because of this, the approach proposed in this EIP is more compatible with the Account Abstraction (AA) roadmap, where smart contract wallets should have feature parity with EOAs.

On top of this, relying on nonce-based hashing scheme to obtain addresses of newly created contracts, like in the case of the EOF creation transactions, would prevent EOF contracts from being deployed counterfactually to deterministic, cross-chain addresses. Introduction of the `TXCREATE` instruction, supports this out of the box. ERCs can be written to provide toehold contracts which will cater for the deployment patterns, such as salt-less deployment and hashing in the sender&apos;s address as part of the salt.

### Handling of `0xEF00` prefixed code in existing transaction types.

Three existing transaction types (type 0 &quot;Frontier,&quot; type 1 &quot;AccessList,&quot; type 2 &quot;FeeMarket&quot;) accept code as part of their input data in certain configurations. This code can start with `EF` as it is initcode and not a deployed contract.

One possible way of handling potential EOF containers in these transactions is to make them invalid if they are attempting to execute an EOF container as initcode. Specifically the transactions is invalid if the input data begins with `0xef00` and if the `to` field is set to nil, signaling a contract creation transaction. This would make blocks containing these transactions invalid, whereas before the fork including this EIP they would have been valid.

One impact that would be seen by this would be block builders, as they would need to ensure that the transactions that are invalid are not included in a block. There is precedent for this, as [EIP-7623](/EIPs/EIPS/eip-7623) established a new floor for the gas limit in transactions, prior to its adoption the limit was lower.  However, block builders have an existing check on gas limits and transactions and that change was adjusting the formula and constants.

We should also consider the treatment [EIP-7702](./eip-7702) delegation designations receive if they show up as code in a contract creation transaction.  The transaction is valid, is executed as plain bytecode, ad the first operation executed is `0xEF`, which is an invalid opcode and would cause the whole transaction to abort.

Letting the inputdata of a type 0, 1, and 2 contract creation transaction execute as plain EVM code irrespective of the magic `0xEF00` bytes keeps a consistent behavior in client code and keeps block builders from having to update their logic in older transaction types.

## Backwards Compatibility

This change poses no risk to backwards compatibility, as it is introduced at the same time EIP-3540 is. Despite the new instruction being introduced for legacy bytecode (code which is not EOF formatted), there is little chance that a meaningful contract would unintentionally execute `0xed` instruction with formally valid operands and inadvertently cause it to run EOF initcode (which would also require an `InitcodeTransaction` to be used, otherwise the initcode lookup will fail).

`TXCREATE` instruction introduction into legacy EVM does not affect `JUMPDEST` analysis, because instruction has no immediate arguments.

The transactions of the new type are invalid until this change activates.

Contract creation options do not change for legacy bytecode, including how existing transactions with `to: nil` behave when encountering code in their calldata that may look like an EOF container.

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 31 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7873</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7873</guid>
      </item>
    
      <item>
        <title>Ethereum Network Configuration for DApps</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7876-unified-network-configuration/22763</comments>
        
        <description>## Abstract

This standard defines a universal format for specifying network configurations to decentralized applications (DApps). The configuration includes essential information about Ethereum networks, such as available RPC URLs, native currencies, contract addresses, and block explorers. Configurations are intended to be provided by:

- Network maintainers to make sure their network is supported by DApps.
- Smart contract developers to ensure the smart contracts are properly integrated into DApps and changes are consistently delivered.
- DApp developers internally in the organization to make use of software libraries designed around the standard and maintain consistent configuration across multiple platforms (e.g., iOS, Android).

Given that different EVM-compatible chains introduce unique features, this standard also supports extensibility, allowing networks to specify additional configuration parameters beyond the base requirements. This flexibility prevents networks from resorting to external storage for their unique configurations, preserving the goal of a unified and comprehensive network configuration standard.

## Motivation

Currently, decentralized applications (DApps) support numerous EVM-compatible networks and often define network configurations in inconsistent formats, which complicates interoperability and sharing of configurations. This standard introduces a **unified network configuration** format that can be adopted by EVM-based networks, making it easier for developers to integrate with multiple networks and providing consistent configuration management.

The proposed configuration format includes essential details required by DApps, including:

- Network name and ID
- RPC URL for Ethereum nodes
- Native currency details
- Smart contract addresses
- Available block explorers and NFT marketplaces

The goal of this standard is to simplify network configuration for DApp developers and enhance interoperability across Ethereum-compatible networks.

## Specification

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

The configuration **MUST** use a JSON object, which DApp developers can use to define multiple Ethereum networks.

### Interface definition

The specification interface is provided in the TypeScript type definition format, which is widely used to define JSON file formats for Ethereum DApps.
Refer to [Example Configuration](#example-configuration) for an illustrative implementation of this standard.

```typescript
/**
 * Represents the configuration for a smart contract.
 *
 * @typedef ContractConfig
 * @property address - The address of the contract on the Ethereum network. **MUST** use a checksum.
 * @property abiUrl - URL to contract ABI file, can be relative to `abiRoot` if specified or absolute. The absence of the key or `null` value indicates that the ABI of the contract is unknown. URL content **MUST** use Contract ABI specification JSON format.
 * @property blockCreated - The block number in which the contract was deployed.
 * @see https://docs.soliditylang.org/en/latest/abi-spec.html#json
 * @see ./eip-55.md
 * @see https://url.spec.whatwg.org
 */
type ContractConfig = {
  address: Address,
  abiUrl?: string | null,
  blockCreated: number,
};

/**
 * Represents a list of contract names. No standard contracts are defined.
 * The list may vary from one DApp to another for the same network.
 * @typedef ContractName
 */
type ContractName = string;

/**
 * Represents the configuration for block explorers in the network configuration.
 * The URLs for address, transaction, and NFT lookups are **relative** to the `root` URL.
 * URLs **MUST** be relative to the `root` URL.
 * URLs **MUST** include special parameters, like `:block`, `:address`, `:tx`, `:token` for relevant properties (see examples).
 * @typedef ExplorerConfig
 * @property root - The root URL of the block explorer (e.g., `https://freescan.example.com`).
 * @property block - The relative URL path for viewing a specific block (e.g., `/block/:block`). If not available, this can be `null`.
 * @property address - The relative URL path for viewing a specific address (e.g., `/address/:address`). If not available, this can be `null`.
 * @property tx - The relative URL path for viewing a transaction (e.g., `/tx/:tx`). If not available, this can be `null`.
 * @property nft - The relative URL path for viewing a specific NFT (e.g., `/nft/:address/:token`). If not available, this can be `null`.
 */
type ExplorerConfig = {
  root: string,
  address: string | null,
  tx: string | null,
  nft: string | null,
  block: string | null,
};


/**
 * Represents RPC node endpoints available in the network.
 *
 * @typedef RpcConfig
 * @property url - The URL under which the RPC is available (e.g. `https://public-node.example.com/rpc`).
 */
type RpcConfig = {
  url: string,
}

/**
 * Represents relation of the network to other networks.
 * e.g. a network is a testnet of a mainnet, a network is Layer 2 above some other network,
 * a network has a bridge to another network, etc.
 *
 * @typedef RelationsConfig
 * @property mainnetChainId - Chain ID of the recommended mainnet network if current network is a testnet. MUST be `null` for mainnet.
 * @property parentChainId - Chain ID of a network that current network is built on top of (e.g. if current network is L2, it will be L1 chain id)
 */
type RelationsConfig = {
  mainnetChainId: number | null,
  parentChainId: number | null,
};

/**
 * Represents the configuration for the native currency used in the network.
 * 
 * @typedef NativeCurrencyConfig
 * @property name - The name of the native currency (e.g., &quot;Ether&quot;).
 * @property symbol - The symbol of the native currency (e.g., &quot;ETH&quot;).
 * @property decimals - The number of decimal places the currency uses (e.g., 18 for Ether).
 */
type NativeCurrencyConfig = {
  name: string,
  symbol: string,
  decimals: number,
};

/**
 * Represents the configuration for a specific Ethereum network used in the DApp.
 * This includes details such as the network name, testnet status, RPC configurations,
 * explorers, and smart contracts related to the network.
 * 
 * @typedef NetworkConfig
 * @property name - The name of the network (e.g., &quot;Ethereum&quot;, &quot;Base&quot;).
 * @property testnet - A flag indicating whether the network is a testnet (`true`) or mainnet (`false`).
 * @property nativeCurrency - Configuration for the network&apos;s native currency (e.g., ETH).
 * @property relations - Relationships with other networks (e.g., parent network or L1/L2 or other bridged networks).
 * @property rpcs - A record of RPC configurations for different nodes in the network, where keys represent the node names (e.g., &quot;publicnode&quot;).
 * @property explorers - Optional record for block explorer configurations (e.g., nft marketplaces).
 * @property contracts - A record of contract configurations where the values may be `null` if the contract is not deployed.
 * @see https://url.spec.whatwg.org
 */
type NetworkConfig = {
  name: string,
  testnet: boolean,
  nativeCurrency:  NativeCurrencyConfig,
  relations: RelationsConfig,
  rpcs: Record&lt;string, RpcConfig | null&gt;,
  explorers: Record&lt;string, ExplorerConfig | null&gt;,
  contracts: Record&lt;ContractName, ContractConfig | null&gt;,
};

/**
 * Represents the configuration for a DApp, including version information, a summary,
 * an optional description, and the network configurations.
 * 
 * @typedef {Object} Configuration
 * @property version - The version of the configuration, typically following semantic versioning (e.g., &quot;1.0.0&quot;).
 * @property timestamp - The timestamp in ISO 8601-compatible format of when the configuration was last updated (e.g., &quot;2025-01-01T12:00:00Z&quot;).
 * @property abiRoot - Optional root URL for the ABI (Application Binary Interface) if it is hosted externally.
 * @property summary - A brief summary or title for the configuration (e.g., &quot;RealPhotos Network Configuration&quot;).
 * @property description - An optional detailed description of the configuration and its purpose.
 * @property networks - A record of network configurations, where keys represent the network IDs (e.g., &quot;1&quot; for ethereum mainnet).
 * @see https://url.spec.whatwg.org/
 * @see https://semver.org
 * @see https://www.iso.org/obp/ui/en/#iso:std:iso:8601:-1:ed-1:v1:en
 */
export default type Configuration = {
  version: string,
  timestamp: string,
  summary: string,
  description: string,
  abiRoot: string | null,
  networks: Record&lt;string, NetworkConfig&gt;,
};
```

### Contracts

Contracts listed **SHOULD** be limited to the subset necessary to perform specific functionality, as defined by the configuration author.

Implementations **MUST** ensure that contract names are consistent across all networks. While the contract binary code deployed to different networks under the same name in the configuration can differ, implementations **SHOULD** ensure they represent different versions of the same contract. Differences **SHOULD** be communicated through additional custom properties or different `abiUrl`. See [Extensions](#extensions).

Inlining contract ABIs **MUST NOT** be used to ensure effective memory management is possible in resource-constrained environments.

It is **RECOMMENDED** for a contract name to match the name in Solidity source code if the contract bytecode is verified on block explorers.

If a contract is not deployed on a specific network, the value `null` **MUST** explicitly indicate the absence of a contract.


### Extensions

Implementations **MUST** ignore non-documented properties or support their interpretation where technically feasible. This ensures the standard remains adaptable to future use cases, enabling developers to extend configurations without breaking compatibility.
See [Example Extensions](#example-extensions).

Non-documented properties **SHOULD** support new features or extensions, but they **MUST NOT** modify or extend the basic types of existing properties.
Union types **SHOULD NOT** be used in extensions. Their usage contradicts the [Rationale](#rationale) of the standard.
See [Incorrect Extension Example](#incorrect-extension).

Extensions **SHOULD** use extensible data structures by making sure additional properties can be added at any configuration layer.

Example of rigid and extensible data structures:

``` typescript
# Rigid data structure
type RigidConfiguration = {
  documentationUrls: string[],
};

# Extensible data structure
type ExtensibleConfiguration = {
  documentation: { url: string }[],
};
```

## Rationale

The design of this standard leverages the following key goals:

### 1. Availability and Distribution

Use JSON as a universally supported data interchange format, with libraries available in virtually all modern programming languages and platforms. This ensures:

- **Cross-Platform Compatibility**: Developers can easily parse and generate JSON regardless of their tech stack.
- **Ease of Integration**: Existing tools and frameworks already support JSON natively, reducing implementation overhead.
- **Built-in Data Types**: JSON provides sufficient data types to describe all necessary configurations semantically, eliminating the need for manual typecasting.
- **Multi-network Support**: The configuration supports multiple networks, ensuring projects deployed to multiple networks can propagate their configurations faster and more consistently.

### 2. Readability by an Engineer

The human-readable structure makes it ideal for configuration files:

- **Clarity**: JSON&apos;s key-value pair format is intuitive and easy to understand for engineers.
- **Debugging**: Developers can quickly inspect and troubleshoot configurations directly in text editors or IDEs.
- **Simplicity**: Its simplicity ensures that even less experienced developers can comprehend and modify configurations without extensive training.
- **Human Names**: Fields like `name` and `description` provide context and improve usability for engineers working with the configuration.

### 3. Openness for Extensions

This standard is designed to support extensions by using JSON objects rather than rigid structures like basic types or arrays.

- **Forward Compatibility**: Unrecognized properties can be safely ignored or leveraged without breaking existing implementations.
- **Customizability**: Developers can add additional fields to accommodate specific requirements, such as API keys or advanced metadata.
- **Scalability**: Future updates to the standard can include new attributes while maintaining backwards compatibility.

See [Extensions](#extensions).


### 4. Use of Chain ID as a Unique Network Identifier

This standard uses the **chain ID** as the unique identifier for networks rather than custom names because:

- **Standardization**: Chain IDs are part of the Ethereum specification and are globally recognized, ensuring consistency.
- **No Collisions**: Unlike custom names, chain IDs are unique, preventing conflicts between networks.
- **Interoperability**: Using chain IDs aligns with existing Ethereum tooling and standards, making integrations seamless across diverse environments.

## Backwards Compatibility

This standard emphasizes extensibility while maintaining backward compatibility where feasible. It ensures adaptability to the evolving requirements of Ethereum network configurations by prioritizing flexibility in its structure.


### 1. Compatibility with [EIP-3085](/EIPs/EIPS/eip-3085)

This standard aligns with [EIP-3085](/EIPs/EIPS/eip-3085), the Ethereum standard for wallet Add Ethereum Chain requests, wherever applicable. However, it diverges in scenarios where EIP-3085&apos;s rigid structure limits future enhancements.

By prioritizing extensibility over strict adherence to EIP-3085, this standard ensures compatibility with existing tools while enabling future-proof enhancements to network configurations.

## Reference Implementation

### Example Configuration

Below is an example configuration for an [ERC-721](/EIPs/EIPS/eip-721) project deployed to Ethereum Mainnet and Sepolia. This illustrates how the standard can represent multi-network setups.

```json
{
  &quot;version&quot;: &quot;0.0.1&quot;,
  &quot;timestamp&quot;: &quot;2025-01-01T12:22:46.471Z&quot;,
  &quot;summary&quot;: &quot;NFT Artwork&quot;,
  &quot;description&quot;: &quot;Artwork published by independent artist. Carefully crafted with style in one of the creative studios of the world.&quot;,
  &quot;abiRoot&quot;: &quot;https://nft-artwork.example.com/developer/abi&quot;,
  &quot;networks&quot;: {
    &quot;1&quot;: {
      &quot;name&quot;: &quot;Ethereum Mainnet&quot;,
      &quot;testnet&quot;: false,
      &quot;nativeCurrency&quot;: {
        &quot;name&quot;: &quot;Ether&quot;,
        &quot;symbol&quot;: &quot;ETH&quot;,
        &quot;decimals&quot;: 18
      },
      &quot;rpcs&quot;: {
        &quot;main&quot;: {
          &quot;url&quot;: &quot;https://eth-rpc.example.com&quot;
        },
        &quot;backup&quot;: {
          &quot;url&quot;: &quot;https://eth-rpc.backup.example.com&quot;
        }
      },
      &quot;relations&quot;: {
        &quot;mainnetChainId&quot;: null,
        &quot;parentChainId&quot;: null
      },
      &quot;explorers&quot;: {
        &quot;megascan&quot;: {
          &quot;root&quot;: &quot;https://example.org&quot;,
          &quot;block&quot;: &quot;/block/:block&quot;,
          &quot;address&quot;: &quot;/address/:address&quot;,
          &quot;tx&quot;: &quot;/tx/:tx&quot;,
          &quot;nft&quot;: &quot;/nft/:address/:token&quot;
        },
        &quot;marketplace&quot;: {
          &quot;root&quot;: &quot;https://nft.marketplace/networks/eth&quot;,
          &quot;block&quot;: null,
          &quot;address&quot;: &quot;/:address&quot;,
          &quot;tx&quot;: null,
          &quot;nft&quot;: &quot;/:address/:token&quot;
        }
      },
      &quot;contracts&quot;: {
        &quot;Registry&quot;: {
          &quot;address&quot;: &quot;0x57928ff7b0BBc3Ee4D84481e320DdB8B941f986A&quot;,
          &quot;blockCreated&quot;: 1234567,
          &quot;abiUrl&quot;: &quot;./Registry.sol/Registry.json&quot;
        },
        &quot;OwnerWallet&quot;: {
          &quot;address&quot;: &quot;0xC12237E57B088e9191BD8054Df4f5B772646a4B6&quot;,
          &quot;blockCreated&quot;: 1
        }
      }
    },
    &quot;11155111&quot;: {
      &quot;name&quot;: &quot;Sepolia&quot;,
      &quot;testnet&quot;: true,
      &quot;nativeCurrency&quot;: {
        &quot;name&quot;: &quot;Sepolia Ether&quot;,
        &quot;symbol&quot;: &quot;ETH&quot;,
        &quot;decimals&quot;: 18
      },
      &quot;rpcs&quot;: {
        &quot;main&quot;: {
          &quot;url&quot;: &quot;https://sepolia-rpc.example.com&quot;
        },
        &quot;backup&quot;: {
          &quot;url&quot;: &quot;https://sepolia-rpc.backup.example.com&quot;
        }
      },
      &quot;relations&quot;: {
        &quot;mainnetChainId&quot;: 1,
        &quot;parentChainId&quot;: null
      },
      &quot;explorers&quot;: {
        &quot;megascan&quot;: {
          &quot;root&quot;: &quot;https://sepolia.example.org&quot;,
          &quot;block&quot;: &quot;/block/:block&quot;,
          &quot;address&quot;: &quot;/address/:address&quot;,
          &quot;tx&quot;: &quot;/tx/:tx&quot;,
          &quot;nft&quot;: &quot;/nft/:address/:token&quot;
        },
        &quot;marketplace&quot;: {
          &quot;root&quot;: &quot;https://testnets.nft.marketplace/networks/sepolia&quot;,
          &quot;block&quot;: null,
          &quot;address&quot;: &quot;/:address&quot;,
          &quot;tx&quot;: null,
          &quot;nft&quot;: &quot;/:address/:token&quot;
        }
      },
      &quot;contracts&quot;: {
        &quot;Registry&quot;: {
          &quot;address&quot;: &quot;0xE13471e6E5d11205AF290261f42108f89dCae72E&quot;,
          &quot;blockCreated&quot;: 183882,
          &quot;abiUrl&quot;: &quot;./Registry.sol/Registry.json&quot; 
        },
        &quot;OwnerWallet&quot;: {
          &quot;address&quot;: &quot;0xC12237E57B088e9191BD8054Df4f5B772646a4B6&quot;,
          &quot;blockCreated&quot;: 1
        }
      }
    }
  }
}
```

*Note*: It is **RECOMMENDED** to use a two-space indentation format for better readability and debugging.

### Configuration Loader in Swift

Here is an example implementation of a configuration loader in Swift Programming Language, demonstrating how to load and parse a configuration file compliant with this standard:

``` swift
import Foundation

struct BlockchainConfig: Codable, LoggerProvider {
    struct NetworkConfig: Codable {
        struct Currency: Codable {
            let name: String
            let symbol: String
            let decimals: Int
        }

        struct RPC: Codable {
            let url: String
        }

        struct Relations: Codable {
            let mainnetChainId: Int?
            let parentChainId: Int?
        }

        struct Explorer: Codable {
            let root: String
            let block: String?
            let address: String?
            let tx: String?
            let nft: String?
        }

        struct Contract: Codable {
            let address: String
            let blockCreated: Int
        }

        let name: String
        let testnet: Bool
        let nativeCurrency: Currency
        let rpcs: [String: RPC]
        let relations: Relations
        let explorers: [String: Explorer?]
        let contracts: [String: Contract?]
        
        var registryAddress: String {
            contracts[&quot;Registry&quot;]!.address
        }

        var megascan: Explorer {
            explorers[&quot;megascan&quot;]!
        }
        
        func blockExplorerUrl(address: String) -&gt; URL {
            let fullPath = megascan.address!.replacingOccurrences(of: &quot;:address&quot;, with: address)
            return URL(string: megascan.root + fullPath)!
        }

        func blockExplorerUrl(tx: String) -&gt; URL {
            let fullPath = megascan.tx!.replacingOccurrences(of: &quot;:tx&quot;, with: tx)
            return URL(string: megascan.root + fullPath)!
        }

        func blockExplorerUrl(contractAddress: String, tokenId: Data) -&gt; URL {
            let fullPath = explorers[&quot;nftmarketplace&quot;]!.nft!
                .replacingOccurrences(of: &quot;:address&quot;, with: contractAddress)
                .replacingOccurrences(of: &quot;:token&quot;, with: tokenId.decString)
            return URL(string: megascan.root + fullPath)!
        }
    }

    let version: String
    let timestamp: String
    let description: String
    let networks: [String: NetworkConfig]

    static func load() -&gt; BlockchainConfig {
        guard let url = Bundle.main.url(forResource: &quot;config&quot;, withExtension: &quot;json&quot;) else {
            fatalError(&quot;Blockchain config not found.&quot;)
        }

        do {
            let data = try Data(contentsOf: url)
            let decoder = JSONDecoder()
            decoder.keyDecodingStrategy = .convertFromSnakeCase
            return try decoder.decode(BlockchainConfig.self, from: data)
        } catch {
            fatalError(&quot;JSON Config parse error: \(error)&quot;)
        }
    }
}
```

This Swift code provides a structured way to handle the configuration JSON and includes utility methods for accessing contract-related information.

### Example Extensions

#### Exposing API key

Example of an extension that **MUST** be supported: adding an API token alongside the RPC URL when it cannot be embedded directly into the URL 
(e.g., passed via an `Authorization: Bearer &lt;token&gt;` header).


``` typescript     
type ExtendedRpcConfig = RpcConfig &amp; {
  // Bearer token for API authentication
  apiKey: string,
  // Maximum requests allowed per hour
  hourlyThroughput?: number,
  // API key restricted by contract address
  contractRestrictionEnabled?: boolean,
};

const rpcs: Record&lt;string, ExtendedRpcConfig&gt; = {
  &quot;restrictedNode&quot;: {
    url: &quot;https://example.com/eth/rpc&quot;,
    apiKey: &quot;ecc2fc8b494b60bcc9faa90d750183f2&quot;, 
    hourlyThroughput: 40,
    contractRestrictionEnabled: true,
  },
};
```

Ensure [Security Considerations](#security-considerations) are followed to protect your API key.

#### Extending contract properties

Example of an extension that **MUST** be supported: incorporating additional attributes to support [ERC-1967](/EIPs/EIPS/eip-1967) transparent proxies and [ERC-165](/EIPs/EIPS/eip-165) interface identification.

``` typescript     
type ExtendedContractConfig = ContractConfig &amp; {
    implementation?: string;
    proxyAdmin?: string;
    supportsInterface: string[];
};

const contracts: Record&lt;string, ExtendedContractConfig&gt; = {
  Registry: {
    &quot;address&quot;: &quot;0x57928ff7b0BBc3Ee4D84481e320DdB8B941f986A&quot;,
    &quot;blockCreated&quot;: 123456,
    &quot;implementation&quot;: &quot;0x489B4BC8bCA12cCeafb84aa78918b8E28594C391&quot;,
    &quot;proxyAdmin&quot;: &quot;0xFd72EeDa802481027e4200E61A5dF052287eec27&quot;,
    // ERC-721 &amp; ERC-165 interfaces
    &quot;supportsInterface&quot;: [&quot;0x01ffc9a7&quot;, &quot;0x80ac58cd&quot;]
  }
};
```

#### Incorrect extension

Example of an incorrect extension that **MUST NOT** be supported: representing `blockCreated` as a hexadecimal string instead of an integer.

``` typescript
const contracts = {
  Registry: {
    &quot;address&quot;: &quot;0x57928ff7b0BBc3Ee4D84481e320DdB8B941f986A&quot;,
    &quot;blockCreated&quot;: &quot;0x2af821&quot;,
  }
};
```

It causes existing implementation to fail parsing `blockCreated` property expecting it to be a `number`, not a `string`.

## Security Considerations

The network configuration defined by this standard is intended to include only public information that is already accessible through tools like block explorers. By structuring this information in a standardized format, the configuration becomes more convenient and efficient for developers to use while maintaining the integrity of public data.

To ensure security and privacy, the following considerations **MUST** be adhered to:

### 1. Public Information Only

- The configuration **SHOULD** include only publicly available details.
- All information included in the configuration should already be discoverable through public tools or services, such as block explorers.
- Including private or sensitive information **MUST** be protected with an additional layer of protection.

### 2. Exposing API Keys

Exposing API keys must be handled with caution and accompanied by a thorough evaluation of associated risks. When including API keys, the following restrictions and best practices **SHOULD** be implemented:

- **Scope Restrictions**:
  - API keys **SHOULD** be limited in scope to specific actions or contract addresses.
  - Consider implementing IP restrictions where possible.

- **Rate Limits**:
  - Include throughput limits (e.g., hourly or daily request caps) to mitigate abuse.

- **Usage**:
  - Exposing API keys **MUST NOT** be done in publicly distributed configurations.
  - Use environment variables or other secure mechanisms to manage API keys internally within an organization.

### 3. Exclusion of Sensitive Information

The configuration **MUST NOT** include the following sensitive data:

- Private keys
- Wallet recovery phrases or mnemonics
- Any information that could compromise the security or privacy of users or systems.

### 4. Low Overall Security Risk

The overall security risks of using this standard are minimal due to its compatibility with established Ethereum ecosystem security practices, including:

- Verification of public data through block explorers.
- Adherence to existing security standards like JSON schema validation and ABI checksum verification.

By aligning with proven methodologies and widely accepted protocols, the standard minimizes potential vulnerabilities while ensuring robust functionality.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 03 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7876</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7876</guid>
      </item>
    
      <item>
        <title>Enhanced RETURN opcodes</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7877-new-m-s-t-rreturn-opcodes/22731</comments>
        
        <description>## Abstract

This EIP specifies a series of new `RETURN` opcodes which allow the user to specify which data location to return from
instead of defaulting to returning from memory.

## Motivation

With the introduction of transient storage, many smart contracts have begun to store data using the new transient opcodes to optimize for gas usage, whereby a callback
involves returning the data previously stored transiently. However, the current `RETURN` opcode only allows for returning sequential bytes in memory. This requires
developers to incur additional gas overhead by manually writing data from transient storage to memory before returning,
incuring both an additional memory expansion and opcode cost from complicated for-loops. Similar
inefficiencies already occur when attempting to return data already placed in storage. This EIP attempts to rectify
this by allowing developers to optimize their code by deciding where to return data from directly, instead of requiring
the intermediate step of first copying the data to memory.

## Specification

This EIP introduces 3 new opcodes as well as renaming/aliasing an existing one.

```
SRETURN (0xf6)
TRETURN (0xf7)
RRETURN (0xf8)

RETURN -&gt; MRETURN (0xf3)
```

The `MRETURN` opcode is a rename of `RETURN`, whereby sequential bytes in memory are returned. It will operate exactly as it currenty does as of the Cancun hard-fork, and its gas cost will remain the same.

`RRETURN` operates similar to `MRETURN`. It pops two items off the stack, an offset to begin reading bytes from in the
existing `RETURNDATA` buffer, and a number of bytes to return. Those bytes are used to overwrite the existing `RETURNDATA` buffer and then a return to the previous function is performed.

`SRETURN` and `TRETURN` operate similarly, except on storage and transient respectively. It pops two items off the stack,
a slot number to begin reading from, and a number of sequential slots to return from. Ex: `SRETURN(0x0, 0x40)` returns the 64 bytes of data in slots [0, 1], and `TRETURN(0x0, 0x40)` returns the data in transient storage slots [0, 1]. Since the
existing `S/TLOAD` opcodes already return 32-bytes, having the opcode return data in chunks of 32-bytes should make implementation by assembly/compiler much simpler.
If the length parameter is a zero, then only the initial slot value should be returned, so `SRETURN(0x00, 0x00)` returns the value at storage slot 0.

The cost for these opcodes should be similar to the cost of accessing data now.

```
SRETURN = (number_of_cold_slots) * 2100 + (numer_of_warm_slots * 100)
TRETURN = number_of_slots * 100

RRETURN = cost of RETURNDATACOPY without memory_expansion cost

minimum_word_size = (size + 31) / 32

static_gas = 3
dynamic_gas = 3 * minimum_word_size

overall = static_gas + dynamic_gas
```

## Rationale

Allowing for more targeted return opcodes allows for saving gas at all levels of smart contract optimization by eliminating
the intermediate steps of first writing any data to memory before returning. In events where this data may be large, this can result in significant gas savings. These opcodes can be built into the Solidity compiler directly so that all contracts
can take advantage of them. Similarly, by making return more explicit it allows for better static analysis by avoiding messy memory allocations.

There is precedent for these changes.

EIP-3855: Introducing `PUSH0` opcode to optimize away alternative methods of pushing 0 onto the stack.

EIP-6: Renaming `SUICIDE` to `SELFDESTRUCT` without changing functionality.

## Backwards Compatibility

There are no backwards compatibility concerns, as `MRETURN` will utilize the same gas cost and opcode as `RETURN` does now. Due to EOF, it is suggested that these changes be
activated in future EVM version once EOF has been fully implemented.

## Security Considerations

There are no security considerations as it is fully backwards compatible, and reduces potential attack space through simplified bytecode.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 31 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7877</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7877</guid>
      </item>
    
      <item>
        <title>Bequeathable Contracts</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/new-erc-bequeathable-tokens-a-standard-to-allow-tokens-to-be-inherited-after-the-owners-death/22755</comments>
        
        <description>## Abstract

This EIP proposes a standard interface for contracts to allow tokens to be inherited after the owner&apos;s death. The interface allows token owners to set up a Will and designate executors to enable the transfer of tokens to inheritors after a specified waiting period.


## Motivation
Crypto Tokens in general and NFTs in particular are starting to be used to tokenise real-world assets. In order for them to be adopted by the main stream finance world, there needs to be a way to inherit these tokens after the owner has passed away. Currently, there is no standardised way for token holders to pass on their digital assets in the event of their death.  
This EIP aims to solve this problem by providing a standard interface for &quot;bequeathable&quot; tokens, allowing for a secure and transparent process of token inheritance.
In designing this interface we have tried to follow the real world process of Will creation and execution.


## Specification

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

Every compliant contract MUST implement the `Bequeathable` interface:

```solidity
/// @title EIP-7878 Bequeathable tokens
/// @dev See https://eips.ethereum.org/EIPS/eip-7878

pragma solidity ^0.8.0;

/**
 * @notice Bequeathable interface
 */

interface Bequeathable {

   /**
    * @notice              Announce the owner&apos;s tokens are to be inherited
    * @dev                 Emitted by `announceObit`
    * @param   owner       The original owner of the tokens
    * @param   inheritor   The address of the wallet that will inherit the tokens once the moratoriumTTL time has passed
    */
   event ObituaryStarted(address indexed owner, address indexed inheritor);

   /** 
    * @notice               Announce the obituary (and moratorium) for the owner has been cancelled, as well as who cancelled it
    * @dev                  Emitted by `cancelObit`
    * @param   owner        The original owner of the tokens
    * @param   cancelledBy  The address that triggered this cancellation. This can be the owner or any of the inheritors
    */
   event ObituaryCancelled(address indexed owner, address indexed cancelledBy);

   /** 
    * @notice                 A token owner can set a Will and names one or more executors who are able to transfer their tokens after their death
    * @dev                    Although more than one executor address can be set, only one is required to start the process and then do the transfer
    * @dev                    Subsequent calls to this function should overwrite any existing Will
    * @param   executors      An array of executors eg legal council, spouse, child 1, child 2 etc..
    * @param   moratoriumTTL  The time that must pass (in seconds) from when the obituary is announced to when the inheritance transfer can take place
    * @dev                    The moratoriumTTL is a safety buffer time frame that allows for any intervention before the tokens get transferred
    */
   function setWill(address[] memory executors, uint256 moratoriumTTL) external;

   /**
    * @notice                  Get the details of a Will if set
    * @dev                     This is a way for the owner to confirm that they have correctly set their Will
    * @param    owner          The current owner of the tokens
    * @return   executors      A list of all the executors for this owners will
    * @return   moratoriumTTL  The length of time (in seconds) that must elapse after calling announceObit before the actual transfer can happen
    */
   function getWill(address owner) external view returns (address[] memory executors, uint256 moratoriumTTL);

   /**
    * @notice              Start the Obituary process, by announcing it and declaring who is the intended inheritor
    * @param   owner       The current owner of the tokens
    * @param   inheritor   The address of the owner to be
    */
   function announceObit(address owner, address inheritor) external;

   /**
    * @notice          Cancel the Obituary that has been previously announced. Can be called by any of the executors (or the owner if still around)
    * @param   owner   The original owner of the tokens
    */
   function cancelObit(address owner) external;

   /**
    * @notice                   Get the designated inheritor and how much time is left before the moratoriumTTL is satisfied
    * @param    owner           The current owner of the tokens
    * @return   inheritor       The named inheritor when the obituary was announced
    * @return   moratoriumTTL   The time left for the moratoriumTTL before the transfer can be done
    * @dev                      A minus figure for moratoriumTTL indicates that the wait time has elapsed and the tokens can be bequeathed
    */
   function getObit(address owner) external view returns (address inheritor, int256 moratoriumTTL);

   /**
    * @notice         Bequeath ie transfer the tokens to the previously declared inheritor
    * @param   owner  The original owner of the tokens
    * @dev            The transfer should happen to the inheritor address when `announceObit` was called
    */
   function bequeath(address owner) external;

}
```

### Functions

1. `setWill`: Allows a token owner to set up or update their Will.
2. `getWill`: Returns the current Will details for a given owner.
3. `announceObit`: Initiates the inheritance process by an executor.
4. `cancelObit`: Cancels an active obituary process.
5. `getObit`: Retrieves the current obituary status.
6. `bequeath`: Transfers tokens to the inheritor after the waiting period.

### Events

1. `ObituaryStarted`: Emitted when an obituary is announced.
2. `ObituaryCancelled`: Emitted when an obituary is cancelled.


## Rationale

The standard follows what currently happens in real life when preparing and executing a Will.
1. An owner writes a Will and in doing so names the executor(s) of their Will
2. Upon passing away, the executor will announce the Obituary
3. The Will is read and the inheritors are identified
4. The transfer of ownership is executed according to the wishes of the Will

However, real life is not always as straight forward as this. Conflicts happen all the time. To handle this situation and to keep the interface simple, we added the ability to cancel the Obituary by ANY of the executors. In this way, if there is any conflict, it can be challenged out in the courts and once the matter is settled, the Obituary process can start again.

Again to keep the interface clean, all the tokens get transferred to one address. It is then that person&apos;s responsibility to execute any further transfers.


## Backwards Compatibility

This EIP is compatible with existing token standards like [ERC-20](/EIPs/EIPS/eip-20), [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155). It can be implemented alongside these standards without affecting their core functionality.


## Test Cases

Tests are included in [`Bequeath.test.js`](/EIPs/assets/eip-7878/test/Bequeath.test.js).


## Reference Implementation

See [`Bequeathable.sol`](/EIPs/assets/eip-7878/contracts/Bequeathable.sol)

## Security Considerations

Implementers should carefully consider access control mechanisms to ensure that only authorized parties can execute Will-related functions. 

The moratoriumTTL should be set to a reasonable duration to allow for potential disputes or corrections. We recommend at least 30 days, especially for tokens that are of high value.  It limits the potential damage in scenarios such as the obituray process being triggered by a bad actor who has taken over one of the executor wallets. 


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 01 Feb 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7878</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7878</guid>
      </item>
    
      <item>
        <title>EOF - EXTCODEADDRESS instruction</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7880-eof-extcodeaddress-instruction/22845</comments>
        
        <description>## Abstract

Add an instruction to EOF that reads code delegation designations from an account without requiring code introspection.

## Motivation

EOFv1 as scoped in [EIP-7692] removes code introspection capabilities from the EVM, preventing EOF from reading raw code values such as code delegation designations set by [EIP-7702]. There are a number of use cases where reading the delegation designation of [EIP-7702] would allow contracts to be more proactive about user experience issues.

One example is a managed proxy contract. Such a contract may want to ensure security by not allowing the proxy to be updated to a delegated address. There are also safety concerns with pointing to a delegation, as the contract may be updated to non EOF code and `EXTDELEGATECALL` will no longer be able to call the contract, due to changes outside the control of the managed proxy contract.

Another example are contracts that need to ensure that the delegation has not changed over a limited scope of time, such as sponsorships. This will prevent a transaction from receiving gas sponsorship, changing the delegation, and performing an act different than what was approved. Sponsors can encode the delegation into the transaction data and verify with this instruction.

Finally, there is the case where contracts may want to de-escalate risks and only accept a small number of delegations for any given contract. To enable this validation contracts will need to be able to resolve the actual address of delegation, not just know that one exists.

To address this the essential task of the designation parsing is moved into a new opcode `EXTCODEADDRESS`, where the task of calculating the delegated address will be performed. For non-delegated accounts or empty accounts the address will be the same as the queried address.

## Specification

### Parameters

| Constant                  | Value                                                              |
|---------------------------|--------------------------------------------------------------------|
| `GAS_COLD_ACCOUNT_ACCESS` | Defined as `2600` in the [Ethereum Execution Layer Spec Constants] |
| `GAS_WARM_ACCESS`         | Defined as `100` in the [Ethereum Execution Layer Spec Constants]  |

We introduce a new EOFv1 instruction `EXTCODEADDRESS` (`0xea`).

EOF code which contains this instruction prior to the fork activating this instruction is considered invalid. Beginning with the first block this EIP is activated in, this instruction is added to the set of valid EOFv1 instructions.

### Execution Semantics

#### `EXTCODEADDRESS`

- Deduct `GAS_WARM_ACCESS` gas
- pop 1 argument `target_address` from the stack
- if `target_address` has any of the high 12 bytes set to a non-zero value (i.e. it does not contain a 20-byte address), then halt with an exceptional failure
  - Notice: Future expansion of the EVM address space may enlarge the number of valid addresses. Do not rely on this step always halting with the current restrictions.
- deduct `GAS_COLD_ACCOUNT_ACCESS - GAS_WARM_ACCESS` if `target_address` is not in `accessed_addresses` and add `target_address` to `accessed_addresses`
- Load the code from `target_address` and refer to it as `loaded_code`
- If `loaded_code` indicates a delegation designator (for example, prefixed with `0xef0100` as defined in [EIP-7702]) push the address of the designation onto the stack.
  - Notice: if [EIP-7702] delegation designations are updated in a future fork (such as allowing chained delegations), then this section is expected to comply with any such hypothetical changes. 
- Otherwise, push `target_address` onto the stack.


Note: If `target_address` points to an account with a contract mid-creation, then `target_address` is returned. If delegation designator points to an account with a contract mid-creation, then address of the designation is returned.

Note: Only `target_address` is warmed. If a delegation is found the address that it is delegated to is not added to the `accessed_addresses`. Also, whether the delegated address is in `accessed_addresses` has no impact on the gas charged for the operation.

Note: This operation straddles the line between [EIP-7702] code reading and code executing instructions.  The operation steps work as a code reading instruction, but the value returned is the resolved address as through it is a code executing instruction.

## Rationale

This EIP is very similar to [EIP-7761], which introduces account type introspection. Its rationale is included by reference as they all apply to this situation.

### Alternative: Return the whole designation, have contract parse

One alternative is to have a specially limited `EXTCODECOPY` that would return just delegation designations. Apart from the general objections to code introspection this would then lock in and limit delegation designation formats and capabilities that must be preserved in future forks. By allowing access to the effect of the delegation rather than the mechanism, EOF preserves space for the mechanism to be changed without breaking existing code. 

## Backwards Compatibility

`EXTCODEADDRESS` at `0xea` can be introduced in a backwards compatible manner into EOFv1 (no bump to version), because `0xea` has been rejected by EOF validation prior to the activation of this EIP, and there are no EOF contracts on-chain with an `0xea` instruction which would have their behavior altered.

## Security Considerations

[EIP-7702] code delegation is a new feature that has not been made accessible to mainnet yet. EIP authors will keep abreast of any developments and reflect on their impact to this proposed instruction. 

## Copyright

Copyright and related rights waived via [CC0]

[CC0]: /EIPs/LICENSE

[EIP-7702]: /EIPs/EIPS/eip-7702

[EIP-7692]: /EIPs/EIPS/eip-7692

[EIP-7761]: /EIPs/EIPS/eip-7761
[Ethereum Execution Layer Spec Constants]: https://github.com/ethereum/execution-specs/blob/1adcc1bfe774798bcacc685aebc17bd9935078c3/src/ethereum/cancun/vm/gas.py#L65-L66
</description>
        <pubDate>Sat, 08 Feb 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7880</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7880</guid>
      </item>
    
      <item>
        <title>ModExp Gas Cost Increase</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7883-modexp-gas-cost-increase/22841</comments>
        
        <description>## Abstract

This EIP is modifying the `ModExp` precompile pricing algorithm introduced in [EIP-2565](/EIPs/EIPS/eip-2565).

## Motivation

Currently the `ModExp` precompile is underpriced in certain scenarios relative to its resource consumption. By adjusting the pricing formula, this EIP aims to address these discrepancies, making `ModExp` sufficiently efficient to enable potential increases in the block gas limit.

## Specification

Upon activation of this EIP, the gas cost of calling the precompile at address `0x0000000000000000000000000000000000000005` will be calculated as follows:

```
def calculate_multiplication_complexity(base_length, modulus_length):
    max_length = max(base_length, modulus_length)
    words = math.ceil(max_length / 8)
    multiplication_complexity = 16
    if max_length &gt; 32: multiplication_complexity = 2 * words**2
    return multiplication_complexity

def calculate_iteration_count(exponent_length, exponent):
    iteration_count = 0
    if exponent_length &lt;= 32 and exponent == 0: iteration_count = 0
    elif exponent_length &lt;= 32: iteration_count = exponent.bit_length() - 1
    elif exponent_length &gt; 32: iteration_count = (16 * (exponent_length - 32)) + ((exponent &amp; (2**256 - 1)).bit_length() - 1)
    return max(iteration_count, 1)

def calculate_gas_cost(base_length, modulus_length, exponent_length, exponent):
    multiplication_complexity = calculate_multiplication_complexity(base_length, modulus_length)
    iteration_count = calculate_iteration_count(exponent_length, exponent)
    return max(500, math.floor(multiplication_complexity * iteration_count))
```

The specific changes from the algorithm defined in [EIP-2565](/EIPs/EIPS/eip-2565):

### 1. Increased minimal and general price

The gas cost calculation is modified from:

```
    return max(200, math.floor(multiplication_complexity * iteration_count / 3))
```

to:

```
    return max(500, math.floor(multiplication_complexity * iteration_count))
```

This change increases the minimum gas cost from 200 to 500 and triples the general cost by removing the division by 3.

### 2. Increase cost for exponents larger than 32 bytes

The gas cost calculation is modified from:

```
    elif exponent_length &gt; 32: iteration_count = (8 * (exponent_length - 32)) + ((exponent &amp; (2**256 - 1)).bit_length() - 1)
```

to:

```
    elif exponent_length &gt; 32: iteration_count = (16 * (exponent_length - 32)) + ((exponent &amp; (2**256 - 1)).bit_length() - 1)
```

The multiplier for exponents larger than 32 bytes is increased from 8 to 16, doubling its impact.

### 3. Assume the minimal base / modulus length to be 32 and increase the cost when it is larger than 32 bytes

The gas cost calculation is modified from:

```
def calculate_multiplication_complexity(base_length, modulus_length):
    max_length = max(base_length, modulus_length)
    words = math.ceil(max_length / 8)
    return words**2
```

to:

```
def calculate_multiplication_complexity(base_length, modulus_length):
    max_length = max(base_length, modulus_length)
    words = math.ceil(max_length / 8)
    multiplication_complexity = 16
    if max_length &gt; 32: multiplication_complexity = 2 * words**2
    return multiplication_complexity
```

This change introduces a minimal multiplication complexity of 16 and doubles the complexity if the base or modulus length exceeds 32 bytes.

## Rationale

Benchmarking the `ModExp` precompile revealed several scenarios where its gas cost was significantly underestimated. Pricing adjustments are designed to rectify underpriced edge cases by modifying the existing `ModExp` pricing formula parameters. Specifically, the minimum cost for `ModExp` will rise from 200 to 500 (a 150% increase), the general cost will triple (a 200% increase), a minimum base/modulus length of 32 bytes will be assumed and the cost will scale more aggressively when the base, modulus, or exponent exceed 32 bytes. These modifications aim to ensure that the `ModExp` precompile&apos;s performance, even in its most resource-intensive edge cases across all execution layer clients, no longer impedes potential increases to the block gas limit.

## Backwards Compatibility

This EIP introduces a backwards-incompatible change. However, similar gas repricings have occurred multiple times in the Ethereum ecosystem, and their effects are well understood.

An empirical analysis of this proposal is available [here](/EIPs/assets/eip-7883/call_analysis), with a separate breakdown by affected entities provided [here](/EIPs/assets/eip-7883/entity_analysis).

## Test Cases

The most common usages (approximately 99.69% of historical `Modexp` calls as of January 4th, 2025) will experience either a 150% increase (from 200 to 500 gas) or a 200% increase (tripling from approximately 1360 gas).
No changes are made to the underlying interface or arithmetic algorithms, allowing existing test vectors to be reused. The table below presents the updated gas costs for these test vectors:

| Test Case                    | [EIP-2565](/EIPs/EIPS/eip-2565) Pricing | EIP-7883 Pricing | Increase |
|------------------------------|-----|-----|----|
| modexp_nagydani_1_square     | 200 | 500 | 150% |
| modexp_nagydani_1_qube       | 200 | 500 | 150% |
| modexp_nagydani_1_pow0x10001 | 341 | 2048 | 501% |
| modexp_nagydani_2_square     | 200 | 512 | 156% |
| modexp_nagydani_2_qube       | 200 | 512 | 156% |
| modexp_nagydani_2_pow0x10001 | 1365 | 8192 | 501% |
| modexp_nagydani_3_square     | 341 | 2048 | 501% |
| modexp_nagydani_3_qube       | 341 | 2048 | 501% |
| modexp_nagydani_3_pow0x10001 | 5461 | 32768 | 500% |
| modexp_nagydani_4_square     | 1365 | 8192 | 501% |
| modexp_nagydani_4_qube       | 1365 | 8192 | 501% |
| modexp_nagydani_4_pow0x10001 | 21845 | 131072 | 500% |
| modexp_nagydani_5_square     | 5461 | 32768 | 500% |
| modexp_nagydani_5_qube       | 5461 | 32768 | 500% |
| modexp_nagydani_5_pow0x10001 | 87381 | 524288 | 500% |
| modexp_marius_1_even         | 2057 | 45296 | 2102% |
| modexp_guido_1_even          | 2298 | 51136 | 2125% |
| modexp_guido_2_even          | 2300 | 51152 | 2124% |
| modexp_guido_3_even          | 5400 | 32400 | 500% |
| modexp_guido_4_even          | 1026 | 94448 | 9105% |
| modexp_marcin_1_base_heavy   | 200 | 1152 | 476% |
| modexp_marcin_1_exp_heavy    | 215 | 16624 | 7632% |
| modexp_marcin_1_balanced     | 200 | 1200 | 500% |
| modexp_marcin_2_base_heavy   | 867 | 5202 | 500% |
| modexp_marcin_2_exp_heavy    | 852 | 16368 | 1821% |
| modexp_marcin_2_balanced     | 996 | 5978 | 500% |
| modexp_marcin_3_base_heavy   | 677 | 2032 | 200% |
| modexp_marcin_3_exp_heavy    | 765 | 4080 | 433% |
| modexp_marcin_3_balanced     | 1360 | 4080 | 200% |

## Security Considerations

This EIP does not introduce any new functionality or make existing operations cheaper, therefore there are no direct security concerns related to new attack vectors or reduced costs. The primary security consideration for this EIP is the potential for `ModExp` scenarios to be overpriced, though this is deemed a lesser risk compared to the current underpricing issues.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 11 Feb 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7883</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7883</guid>
      </item>
    
      <item>
        <title>Operation Router</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/operation-router/22633</comments>
        
        <description>## Abstract

This EIP introduces a protocol that enables smart contracts to redirect write operations to external systems. The protocol defines a standardized way for contracts to indicate that an operation should be handled by either a contract deployed to an L2 chain, to the L1, or an off-chain database, providing an entry point for easy developer experience and client implementations.

## Motivation

As the Ethereum ecosystem grows, there is an increasing need for efficient ways to manage data storage across different layers and systems.

This protocol addresses these challenges by:

- Providing a gas-efficient way to determine operation handlers through view functions
- Enabling seamless integration with L2 solutions and off-chain databases
- Maintaining strong security guarantees through typed signatures and standardized interfaces

## Specification

### Core Components

The protocol consists of three main components:

1. A view function named interface `getOperationHandler` for determining operation handlers that can be one of the following types:
a. `OperationHandledOnchain` for on-chain handlers
b. `OperationHandledOffchain` for off-chain handlers through a gateway
2. A standardized message format for off-chain storage authorization

### Interface

```solidity
interface OperationRouter {

  /** 
    * @dev Error to raise when an encoded function that is not supported
    * @dev is received on the getOperationHandler function
    */
  error FunctionNotSupported();

  /**
    * @dev Error to raise when mutations are being deferred onchain
    * that being the layer 1 or a layer 2
    * @param chainId Chain ID to perform the deferred mutation to.
    * @param contractAddress Contract Address at which the deferred mutation should transact with.
    */
  error OperationHandledOnchain(
      uint256 chainId,
      address contractAddress
  );

  /**
    * @notice Struct used to define the domain of the typed data signature, defined in EIP-712.
    * @param name The user friendly name of the contract that the signature corresponds to.
    * @param version The version of domain object being used.
    * @param chainId The ID of the chain that the signature corresponds to
    * @param verifyingContract The address of the contract that the signature pertains to.
    */
  struct DomainData {
      string name;
      string version;
      uint64 chainId;
      address verifyingContract;
  }

  /**
    * @notice Struct used to define the message context for off-chain storage authorization
    * @param data The original ABI encoded function call
    * @param sender The address of the user performing the mutation (msg.sender).
    * @param expirationTimestamp The timestamp at which the mutation will expire.
    */
  struct MessageData {
      bytes data;
      address sender;
      uint256 expirationTimestamp;
  }

  /**
    * @dev Error to raise when mutations are being deferred to an Offchain entity
    * @param sender the EIP-712 domain definition
    * @param url URL to request to perform the off-chain mutation
    * @param data The original ABI encoded function call along with authorization context
    */
  error OperationHandledOffchain(
      DomainData sender,
      string url,
      MessageData data
  );

  /**
    * @notice Determines the appropriate handler for an encoded function call
    * @param encodedFunction The ABI encoded function call
    */
  function getOperationHandler(bytes calldata encodedFunction) external view;
}

```

The onchain flow is specified as follows:

![](/EIPs/assets/eip-7884/d1.svg)

It is important to notice that the `getOperationHandler` relies on the given argument, the encoded function, to specify which contract will the request be redirected to, therefore, it is unable to address `multicall` transactions that could lead to different destination contracts. That means that `multicall` that is known will be redirected to different contracts should be handled in a sequential way by first calling the `getOperationHandler` and then making the actual transaction to the returned contract.

#### Database flow

The HTTP request made to the gateway follows the same standard proposed by the [EIP-3668](./eip-3668) where the URL receives `/{sender}/{data}.json` enabling an API to behave just like an smart contract would. However, the [EIP-712 Typed Signature](/EIPs/EIPS/eip-712) was introduced to enable authentication.

![](/EIPs/assets/eip-7884/d2.svg)

### Implementation Example

The contract deployed to the L1 MUST implement the `getOperationHandler` to act as a router redirecting the requests to the respective handler.

```solidity
contract OperationRouterExample {
    function getOperationHandler(bytes calldata encodedFunction) external view {
        bytes4 selector = bytes4(encodedFunction[:4]);

        if (selector == bytes4(keccak256(&quot;setText(bytes32, string)&quot;))) {
            revert OperationHandledOffchain(
                DomainData(
                    &quot;IdentityResolver&quot;,
                    &quot;1&quot;,
                    1,
                    address(this)
                ),
                &quot;https://api.example.com/profile&quot;,
                MessageData(
                    encodedFunction,
                    msg.sender,
                    block.timestamp + 1 hours
                )
            );
        }

        if (selector == bytes4(keccak256(&quot;setAddress(bytes32,address)&quot;))) {
            revert OperationHandledOnchain(
                10,
                address(0x123...789)
            );
        }
    }
}

```

The client implementation would look as follows:

```tsx
 try {
  const calldata = {
    functionName: &apos;setText&apos;,
    abi,
    args: [key, value],
    address,
    account
  }
 
  await client.readContract({
    functionName: &apos;getOperationHandler&apos;,
    abi,
    args: [encodeFunctionData(calldata)],
  })
} catch (err) {
  const data = getRevertErrorData(err)

  switch (data?.errorName) {
    case &apos;OperationHandledOffchain&apos;: {
      const [domain, url, message] = errorResult.args as [
        DomainData,
        string,
        MessageData,
      ]
      await handleDBStorage({ domain, url, message, signer })
    }
    case &apos;OperationHandledOnchain&apos;: {
      const [chainId, contractAddress] = data.args as [bigint, `0x${string}`]

      const l2Client = createPublicClient({
        chain: getChain(Number(chainId)),
        transport: http(),
      }).extend(walletActions)

      const { request } = await l2Client.simulateContract({
        ...calldata,
        address: contractAddress,
      })
      await l2Client.writeContract(request)
    }
    default:
      console.error(&apos;error registering domain: &apos;, { err })
  }
```

## Rationale

The standard aims to enable offchain writing operations, designed to be a complement for the CCIP-Read ([ERC-3668](./eip-3668)) which is already widely adopted by the community.

## Backwards Compatibility

This EIP is fully backward compatible as it:

- Introduces new interfaces that don&apos;t conflict with existing ones
- Uses view functions to gather offchain information
- Can be implemented alongside existing storage patterns

## Security Considerations

### Handler Validation

Off-chain handlers must:

- Verify EIP-712 signatures
- Implement proper access controls
- Handle concurrent modifications safely

### General Recommendations

- Implement rate limiting for off-chain handlers
- Use secure transport (HTTPS) for off-chain communications
- Monitor for unusual patterns that might indicate attacks
- Implement proper error handling for failed transactions

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 23 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7884</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7884</guid>
      </item>
    
      <item>
        <title>Precompile for NTT operations</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7885-precompile-for-ntt-operations/22895</comments>
        
        <description>## Abstract

This proposal creates a precompiled contract that performs NTT and Inverse NTT transformations. This provides a way to efficiently perform fast polynomial multiplication for post-quantum and STARK cryptography.

## Motivation

With the recent advances in quantum computing, there are increased concerns for the quantum threat against Ethereum. Today ECDSA is the EOA signature algorithms, which is vulnerable to attacks by quantum computers. Efficient replacement algorithms use polynomial multiplication as the core operation. Once NTT and Inverse NTT are available, the remaining of the verification algorithm is trivial. Choosing to integrate NTT and InvNTT instead of a specific algorithm provides agility, as DILITHIUM or FALCON or any equivalent can be implemented with a modest cost from those operators. NTT is also of interest to speed-up STARK verifiers. This single operator would thus benefit to both the Ethereum scaling and post-quantum threat mitigation.

## Specification

### Constants

&lt;!-- TODO --&gt;

| Name                | Value | Comment            |
|---------------------|-------|--------------------|
| NTT_FW              | TBD   | precompile address |
| NTT_INV             | TBD   | precompile address |
| NTT_VECMULMOD       | TBD   | precompile address |
| NTT_VECADDMOD       | TBD   | precompile address |

We introduce *four* separate precompiles to perform the following operations:

- NTT_FW - to perform the forward NTT transformation (Negative wrap convolution) with a gas cost of `600` gas,
- NTT_INV - to perform the inverse NTT transformation (Negative wrap convolution) with a gas cost of `600` gas,
- NTT_VECMULMOD - to perform vectorized modular multiplication with a gas cost formula defined in the corresponding section,
- NTT_VECADDMOD - to perform vectorized modular addition with a gas cost formula defined in the corresponding section.

### Field parameters

The NTT_FW and NTT_INV are fully defined by the following set of parameters:
Let $R$ be a cyclotomic ring of the form $R=\mathbb F_q[X]/(X^n+1)$. In these notations,

- $n$ is the degree and is a power of 2,
- $\mathbb F_q$ is the prime field where $q \equiv 1 \mod 2n$,
- $\omega$ is a $n$-th root of unity in $\mathbb F_q$,
- $\psi$ is a $2n$-th root of unity in $\mathbb F_q$.

Any element $a \in R$ is a polynomial of degree at most $n-1$ with integer coefficients, written
as $a=\sum_{i=0}^{n-1} a_iX^i$

### NTT_FW

The NTT transformation is described by the following algorithm.

**Input:** A vector $a = (a[0], a[1], \dots, a[n-1]) \in \mathbb F_q^n$ in standard order, where $q$ is a prime such that $q \equiv 1 \mod 2n$ and $n$ is a power of two, and a precomputed table $\Psi_\text{rev} \in \mathbb{Z}_q^n$ storing powers of $\psi$ in bit-reversed order.

**Output:** $a \leftarrow \text{NTT\_FW}(a)$ in bit-reversed order.

```plaintext
t ← n
for m = 1 to n-1 by 2m do
    t ← t / 2
    for i = 0 to m-1 do
        j1 ← 2 ⋅ i ⋅ t
        j2 ← j1 + t - 1
        S ← Ψrev[m + i]
        for j = j1 to j2 do
            U ← a[j]
            V ← a[j + t] ⋅ S
            a[j] ← (U + V) mod q
            a[j + t] ← (U - V) mod q
        end for
    end for
end for
return a
```

### NTT_INV

The Inverse NTT is described by the following algorithm.

**Input:** A vector $a = (a[0], a[1], \dots, a[n-1]) \in \mathbb F_q^n$ in bit-reversed order, where $q$ is a prime such that $q \equiv 1 \mod 2n$ and $n$ is a power of two, and a precomputed table $\Psi^{-1}_\text{rev} \in \mathbb F_q^n$ storing powers of $\psi^{-1}$ in bit-reversed order.

**Output:** $a \leftarrow \text{NTT\_INV}(a)$ in standard order.

```plaintext
t ← 1
for m = n to 1 by m/2 do
    j1 ← 0
    h ← m / 2
    for i = 0 to h-1 do
        j2 ← j1 + t - 1
        S ← Ψ⁻¹rev[h + i]
        for j = j1 to j2 do
            U ← a[j]
            V ← a[j + t]
            a[j] ← (U + V) mod q
            a[j + t] ← (U - V) ⋅ S mod q
        end for
        j1 ← j1 + 2t
    end for
    t ← 2t
end for
for j = 0 to n-1 do
    a[j] ← a[j] ⋅ n⁻¹ mod q
end for
return a
```

### NTT_VECMULMOD

The NTT_VECMULMOD is functions similarly to SIMD, but operates with larger input and output sizes.

**Input:** Two vectors $a = (a[0], a[1], \dots, a[n-1]), b=(b[0], b[1], \dots, b[n-1]) \in \mathbb F_q^n$ where $n$ and $q$ are defined above.

**Output:** The element-wise product $(a[0]\cdot b[0] \mod q, a[1]\cdot b[1]\mod q, \dots, a[n-1]\cdot b[n-1] \mod q)$.

**Gas cost:** Denoting $k$ to be the smallest power of $2$ larger than $\log_2(q)$, the gas cost of this operation is $k\log_2(n) / 8$.

### NTT_VECADDMOD

The NTT_VECMULMOD is similar to SIMD in the functioning, but operates with larger sizes in input and output.

**Input:** Two vectors $a = (a[0], a[1], \dots, a[n-1]), b=(b[0], b[1], \dots, b[n-1]) \in \mathbb F_q^n$ where $n$ and $q$ are defined above.

**Output:** The element-wise addition $(a[0]+ b[0] \mod q, a[1]+ b[1]\mod q, \dots, a[n-1]+ b[n-1] \mod q)$.

**Gas cost:** Denoting $k$ to be the smallest power of $2$ larger than $\log_2(q)$, the gas cost of this operation is $k\log_2(n) /32$.

## Rationale

If $f$ and $g$ are two polynomials of $R$, then
$f\times g= \text{NTT\_INV}(\text{NTT\_VECMULMOD}(
\text{NTT\_FW}(a), \text{NTT\_FW}(b)))$ is equal to the product of $f$ and $g$ in $R$. The algorithm has a complexity of $n \log_2n$ rather than $n^2$ with the classical schoolbook multiplication algorithm.

### Gas Cost Analysis

The gas cost model for EIP-7885 precompiles is designed to target approximately 50-55 mgas/s performance, consistent with existing precompiled contracts like ECRECOVER. Two implementations with different gas costs are available:

#### NTT Precompiles (0x12, 0x13) - Scheme-Specific Cost Model

**Gas Costs by Implementation**:

| Scheme             | Ring Degree | nocgo NTT_FW | nocgo NTT_INV | cgo NTT_FW | cgo NTT_INV |
| ------------------ | ----------- | ------------ | ------------- | ---------- | ----------- |
| Falcon-512         | 512         | 790 gas      | 790 gas       | 500 gas    | 500 gas     |
| Falcon-1024        | 1024        | 1,750 gas    | 1,750 gas     | 1,080 gas  | 1,080 gas   |
| ML-DSA (Dilithium) | 256         | 220 gas      | 270 gas       | 256 gas    | 340 gas     |

**Pure Go (nocgo)**: Zero-dependency implementation.

**liboqs (cgo)**: Offers 36-38% lower gas costs for NTT operations.

**Rationale**: Gas costs are calibrated per cryptographic scheme based on actual execution performance. NTT computation complexity varies by ring degree and modulus size, with costs optimized to maintain consistent throughput across different post-quantum schemes.

#### Vector Operations (0x14, 0x15) - Dynamic Cost Model

**VECMULMOD Gas Cost**: `ceil(0.32 × N)`

**VECADDMOD Gas Cost**: `ceil(0.3 × N)`

**Cost Components**:

- Linear scaling with vector length N (ring degree)
- VECMULMOD: 0.32 gas per element
- VECADDMOD: 0.3 gas per element

**Benchmark Validation**: The dynamic cost model achieves target performance:

- Falcon-512 VECMULMOD (164 gas): 56.17 mgas/s (~2.9μs)
- Falcon-512 VECADDMOD (154 gas): 54.45 mgas/s (~2.8μs)
- Falcon-1024 VECMULMOD (328 gas): 54.67 mgas/s (~6.0μs)
- Falcon-1024 VECADDMOD (308 gas): 52.84 mgas/s (~5.8μs)
- ML-DSA VECMULMOD (82 gas): 41.89 mgas/s (~2.0μs)
- ML-DSA VECADDMOD (77 gas): 46.81 mgas/s (~1.6μs)

The gas cost formulas accurately reflect actual execution costs while maintaining ~50-55 mgas/s performance target across all tested cryptographic standards.

### Fields of interest

The implementation applies for many fields of interest for cryptography. In particular, the design applies for:

- FALCON: $q=3 \cdot 2^{12}+1$ (one of the NIST winners for post-quantum signature scheme),
- DILITHIUM: $q=2^{23}-2^{13}+1$ (one of the NIST winners for post-quantum signature scheme),
- KYBER: $q=13 \cdot 2^8+1$ (one of the NIST winners for post-quantum key encapsulation mechanism),
- Babybear: $q=15 \cdot 2^{27}+1$ (Risc0),
- Goldilocks: $q=2^{64}-2^{32}+1$ (Polygon&apos;s Plonky2),
- M31: $q=2^{31}-1$ (Circle STARKS, STwo, Plonky3),
- StarkCurve: $q=2^{251}+17 \cdot 2^{192}+1$

### Benchmarks

#### Pure solidity

To illustrate the interest of the precompile, the assets provide the measured gas const for a single NTT and extrapolates the minimal gas cost taking into account the required number of NTT_FW and NTT_INV. The provided assets use pure Yul optimizations, with memory access hacks. It is unlikely that more than one order of magnitude could be spared on such a minimal code. 

|Use case| Parameters                   | single NTT gas cost         |  Required NTT(FW/INV)    | Estimated NTT/Full cost |
|--|------------------------|---------------------|---------------------|---|
|Falcon| $q=12289, n=512$       | 1.8 M | 1 NTTFW+1 NTTINV |3.6 M| 
|Dilithium| $q=2^{23}-2^{13}+1, n=256$| 460K | 4 NTTFW +1 NTTINV|2.3M|

Falcon cost has been measured over a full implementation and is compliant to the estimation. Dilithium cost is evaluated assuming

This demonstrates that using pure solidity enables L2s with low gas fees to experiment with FALCON in the short term, whereas it is too expensive to do so on L1.
Adopting this EIP, the signature verification of Falcon can be reduced to **1500** gas, and a similar result is expected for Dilithium.
Adopting the hash function as a separate EIP would enable a gas verification cost of 2000 gas.
This is in line with the ratio looking at SUPERCOP implementations.

#### Native Client Implementation

Two implementations have been developed for op-geth with four precompiled contracts at addresses `0x12`, `0x13`, `0x14`, and `0x15`:

**Pure Go Implementation (nocgo)** - Default:

- Zero external dependencies
- Gas costs: Falcon-512 (790 gas), Falcon-1024 (1,750 gas), ML-DSA NTT_FW (220 gas), NTT_INV (270 gas)
- VECMULMOD: `ceil(0.32 × N)` gas, VECADDMOD: `ceil(0.3 × N)` gas

**liboqs Implementation (cgo)** - High Performance:

- Uses liboqs library via CGO
- 36-38% lower gas costs for NTT operations
- Gas costs: Falcon-512 (500 gas), Falcon-1024 (1,080 gas), ML-DSA NTT_FW (256 gas), NTT_INV (340 gas)
- Same VECMULMOD/VECADDMOD costs as nocgo variant

Both implementations support:

- NTT_FW (0x12): Forward NTT transformation
- NTT_INV (0x13): Inverse NTT transformation
- VECMULMOD (0x14): Element-wise modular multiplication
- VECADDMOD (0x15): Element-wise modular addition
- Input format: ring_degree (4 bytes) + modulus (8 bytes) + coefficients (Falcon: uint16×N, ML-DSA: int32×N)

Benchmark results on Intel(R) Xeon(R) CPU @ 2.20GHz (liboqs implementation):

```
BenchmarkPrecompiledNTT_FW/NTT_FW-Falcon-512-Gas=500-4
    377011      9411 ns/op      500 gas/op        53.12 mgas/s
BenchmarkPrecompiledNTT_FW/NTT_FW-Falcon-1024-Gas=1080-4
    176936     20419 ns/op     1080 gas/op        52.89 mgas/s
BenchmarkPrecompiledNTT_FW/NTT_FW-ML-DSA-256-Gas=256-4
    740838      4785 ns/op      256 gas/op        53.49 mgas/s

BenchmarkPrecompiledNTT_INV/NTT_INV-Falcon-512-Gas=500-4
    372236      9374 ns/op      500 gas/op        53.33 mgas/s
BenchmarkPrecompiledNTT_INV/NTT_INV-Falcon-1024-Gas=1080-4
    176300     20316 ns/op     1080 gas/op        53.15 mgas/s
BenchmarkPrecompiledNTT_INV/NTT_INV-ML-DSA-256-Gas=340-4
    558224      6396 ns/op      340 gas/op        53.15 mgas/s

BenchmarkPrecompiledNTT_VECMULMOD/VECMULMOD-Falcon-512-Gas=164-4
   1237585      2919 ns/op      164 gas/op        56.17 mgas/s
BenchmarkPrecompiledNTT_VECMULMOD/VECMULMOD-Falcon-1024-Gas=328-4
    592540      5999 ns/op      328 gas/op        54.67 mgas/s
BenchmarkPrecompiledNTT_VECMULMOD/VECMULMOD-ML-DSA-256-Gas=82-4
   1726333      1957 ns/op       82 gas/op        41.89 mgas/s

BenchmarkPrecompiledNTT_VECADDMOD/VECADDMOD-Falcon-512-Gas=154-4
   1273167      2828 ns/op      154 gas/op        54.45 mgas/s
BenchmarkPrecompiledNTT_VECADDMOD/VECADDMOD-Falcon-1024-Gas=308-4
    606345      5829 ns/op      308 gas/op        52.84 mgas/s
BenchmarkPrecompiledNTT_VECADDMOD/VECADDMOD-ML-DSA-256-Gas=77-4
   2178388      1645 ns/op       77 gas/op        46.81 mgas/s

BenchmarkPrecompiledEcrecover/-Gas=3000-4
   65388      57182 ns/op     3000 gas/op        52.46 mgas/s
```

The benchmarks demonstrate that all NTT precompiles maintain competitive or better throughput compared to existing precompiled contracts like ECRECOVER, processing approximately 52-56 million gas per second. Both implementations (nocgo and cgo) provide efficient support for multiple post-quantum cryptographic schemes including Falcon-512/1024 and ML-DSA/Dilithium, with the liboqs variant offering ~36-38% lower gas costs for NTT operations.

#### End-to-End Signature Verification with Precompiles

Integration testing demonstrates the practical impact of NTT precompiles on full signature verification. Tests were conducted using modified ZKNOX implementations (ETHFALCON and ETHDILITHIUM) against an op-geth client with NTT precompile support.

**Test Environment**: OP-Stack testnet with NTT precompiles enabled.

| Algorithm | Verification Method | Pure Solidity | With Precompile | Gas Saved |
|-----------|-------------------|---------------|-----------------|-----------|
| ETHFALCON (Falcon-512) | Direct | 1,800,000 | 479,341 | 1,320,659 (73.4%) |
| ETHDILITHIUM (ML-DSA) | PKContract-based | 9,746,410 | 7,618,412 | 2,127,998 |
| ETHDILITHIUM (ML-DSA) | Direct (struct) | 7,874,354 | 5,732,354 | 2,142,000 |

**Key Findings**:

- **ETHFALCON**: Achieves 73.4% gas reduction with NTT precompiles, reducing signature verification cost from 1.8M gas to under 480K gas.
- **ETHDILITHIUM**: NTT precompiles save over 2.1M gas per signature verification.

These results validate that NTT precompiles significantly reduce gas costs for post-quantum signature verification, making lattice-based cryptography more practical for Ethereum applications.

## Backwards Compatibility

There are no backward compatibility questions.

## Test Cases

The reference implementation includes comprehensive test coverage across multiple layers:

### NTT Precompile Tests (0x12)

**Malformed Input Tests** - 8 test cases covering:

- Invalid operation codes (values other than 0 or 1)
- Invalid ring degrees (non-power-of-2, &lt; 16)
- Zero or non-NTT-friendly moduli (not congruent to 1 mod 2N)
- Coefficients exceeding modulus bounds
- Input length mismatches

**Functional Tests**:

- Forward NTT transformation with ring degree 16, modulus 97
- Inverse NTT transformation ensuring `INTT(NTT(x)) = x`
- Round-trip validation for data integrity

**Crypto Standards Benchmarks**:

- Falcon-512: n=512, q=12289
- Kyber-128: n=256, q=3329
- Dilithium-256: n=256, q=8380417

### Vector Operations Tests (0x13, 0x14)

**Unified Malformed Input Tests** - 7 test cases covering:

- Invalid ring degrees for both VECMULMOD and VECADDMOD
- Zero or non-NTT-friendly moduli
- Input length mismatches (expecting 2\*N vectors)
- Coefficient bounds validation

**Functional Tests**:

- Element-wise multiplication: `result[i] = (a[i] * b[i]) mod q`
- Element-wise addition: `result[i] = (a[i] + b[i]) mod q`
- Validation with small test vectors (ring degree 16, modulus 97)

**Crypto Standards Benchmarks** - Performance validation with:

- Falcon-512 parameters (VECMULMOD: 164 gas, VECADDMOD: 154 gas)
- Falcon-1024 parameters (VECMULMOD: 328 gas, VECADDMOD: 308 gas)
- ML-DSA-256 parameters (VECMULMOD: 82 gas, VECADDMOD: 77 gas)

Benchmark data are available in the EIP assets:

**Pure Go Implementation (nocgo):**

- [NTT Precompile Benchmark Results](/EIPs/assets/eip-7885/op-geth/nocgo/benchmark_results/BenchmarkPrecompiledNTT)
- [ECRECOVER Benchmark Results](/EIPs/assets/eip-7885/op-geth/nocgo/benchmark_results/BenchmarkPrecompiledEcrecover)

**liboqs Implementation (cgo):**

- [NTT Precompile Benchmark Results](/EIPs/assets/eip-7885/op-geth/cgo/benchmark_results/BenchmarkPrecompiledNTT)
- [ECRECOVER Benchmark Results](/EIPs/assets/eip-7885/op-geth/cgo/benchmark_results/BenchmarkPrecompiledEcrecover)

## Reference Implementation

- [Python reference implementation](../assets/eip-7885/pythonref)
- [Solidity reference implementation](/EIPs/assets/eip-7885/solidity/src/ZKNOX_NTT.sol)
- OP-Geth implementations in the assets of this EIP:
  - [Pure Go (nocgo)](../assets/eip-7885/op-geth/nocgo)
  - [liboqs (cgo)](../assets/eip-7885/op-geth/cgo)

All implementations have been validated over a large base of reference vectors, and implementing both FALCON and DILITHIUM algorithms as demonstration of the usefulness of the precompile.

## Security Considerations

&lt;!-- TODO --&gt;

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 12 Feb 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7885</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7885</guid>
      </item>
    
      <item>
        <title>Delayed execution</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7886-delayed-execution/22890</comments>
        
        <description>## Abstract

This proposal introduces a mechanism to make execution blocks statically verifiable through minimal checks that only require the previous state, without requiring execution of the block&apos;s transactions. This enables validators to attest to a block&apos;s validity without completing its execution.

## Motivation

The primary advantage of this proposal is **asynchronous block validation**. In the current Ethereum protocol, blocks must be fully executed before validators can attest to them. This requirement creates a bottleneck in the consensus process, as attestors must wait for execution results before committing their votes, limiting the network&apos;s throughput potential.

By introducing a mechanism where execution payloads can be reverted rather than invalidating the entire block, execution is no longer an immediate requirement for validation. Instead, a block&apos;s validity can be determined based on its structural correctness and the upfront payment of transaction fees by senders. This allows attestation to happen earlier in the slot, independent of execution, potentially enabling higher block gas limits and significant throughput improvements across the network.

## Specification

### Header Changes

The block header structure is extended to support delayed execution:

```python
@dataclass
class Header:
    # Existing fields
    parent_hash: Hash32
    ommers_hash: Hash32
    coinbase: Address

    # Pre-execution state root - this is the state root before executing transactions
    pre_state_root: Root  

    # Deferred execution outputs from parent block
    parent_transactions_root: Root    # Transaction root from parent block
    parent_receipt_root: Root         # Receipt root from parent block
    parent_bloom: Bloom               # Logs bloom from parent block
    parent_requests_hash: Hash32      # Hash of requests from the parent block
    parent_execution_reverted: bool   # Indicates if parent block&apos;s execution was reverted

    # Other existing fields
    difficulty: Uint
    number: Uint
    gas_limit: Uint
    gas_used: Uint                   # Declared gas used by txs, validated post-execution
    timestamp: U256
    extra_data: Bytes
    prev_randao: Bytes32
    nonce: Bytes8
    base_fee_per_gas: Uint
    withdrawals_root: Root
    blob_gas_used: U64               # Total blob gas used by transactions
    excess_blob_gas: U64
    parent_beacon_block_root: Root
```

The key changes are:

1. `pre_state_root`: Represents the state root before execution (checked against the post-execution state of the parent block)
2. `parent_receipt_root`: Receipt root from the parent block (deferred execution output)
3. `parent_bloom`: Logs bloom from the parent block (deferred execution output)
4. `parent_requests_hash`: Hash of requests from the parent block (deferred execution output)
5. `parent_execution_reverted`: Indicates whether the parent block&apos;s execution was reverted

A block header MUST include all these fields to be considered valid under this EIP. The `pre_state_root` MUST match the state root after applying the parent block&apos;s execution. The parent execution outputs MUST accurately reflect the previous block&apos;s execution results to maintain chain integrity.

### Chain State Tracking

The blockchain object is extended to track execution outputs for verification in subsequent blocks:

```python
@dataclass
class BlockChain:
    blocks: List[Block]
    state: State
    chain_id: U64
    last_transactions_root: Root    # Transaction root from the last executed block
    last_receipt_root: Root         # Receipt root from last executed block
    last_block_logs_bloom: Bloom    # Logs bloom from last executed block
    last_requests_hash: Bytes       # Requests hash from last executed block
    last_execution_reverted: bool   # Indicates if the last block&apos;s execution was reverted
```

These additional fields are used to verify the deferred execution outputs claimed in subsequent blocks. The `last_transactions_root`, `last_receipt_root`, `last_block_logs_bloom`, `last_requests_hash`, and `last_execution_reverted` act as critical chain state references that MUST be updated after each block execution to ensure proper state progression. When a block&apos;s execution is reverted due to a gas mismatch, the `last_execution_reverted` field is set to `True`, which affects the base fee calculation of subsequent blocks.

### Block Validation

Static validation is performed separately from execution. In this phase, all checks that can be done without executing transactions are performed:

```python
def validate_block(chain: BlockChain, block: Block) -&gt; None:
    # Validate header against parent
    validate_header(chain, block.header)

    # Validate deferred execution outputs from the parent
    if block.header.parent_transactions_root != chain.last_transactions_root:
        raise InvalidBlock
    if block.header.parent_receipt_root != chain.last_receipt_root:
        raise InvalidBlock
    if block.header.parent_bloom != chain.last_block_logs_bloom:
        raise InvalidBlock
    if block.header.parent_requests_hash != chain.last_requests_hash:
        raise InvalidBlock
    if block.header.pre_state_root != state_root(chain.state):
        raise InvalidBlock
    if block.header.parent_execution_reverted != chain.last_execution_reverted:
        raise InvalidBlock

    ...

    # Process all transactions trie and validate transactions
    total_inclusion_gas = Uint(0)
    total_blob_gas_used = Uint(0)
    withdrawals_trie = Trie(secured=False, default=None)

    # Track sender balances and nonces by address
    sender_balances = {}
    sender_nonces = {}

    # Calculate blob gas price based on excess blob gas
    blob_gas_price = calculate_blob_gas_price(block.header.excess_blob_gas)

    # Validate each transaction
    for i, tx in enumerate(map(decode_transaction, block.transactions)):
        # Validate transaction parameters (signature, fees, etc.)
        validate_transaction(tx, block.header.base_fee_per_gas, block.header.excess_blob_gas)

        # Recover sender
        sender_address = recover_sender(chain.chain_id, tx)

        # Calculate gas costs (both EIP-7623 intrinsic cost and floor cost)
        intrinsic_gas, calldata_floor_gas_cost = calculate_intrinsic_cost(tx)
        blob_gas_used = calculate_total_blob_gas(tx)

        # Track total gas usage (using the maximum of intrinsic gas and floor cost)
        total_inclusion_gas += max(intrinsic_gas, calldata_floor_gas_cost)
        total_blob_gas_used += blob_gas_used

        # Calculate maximum gas fee (including blob fees)
        effective_gas_price = calculate_effective_gas_price(tx, block.header.base_fee_per_gas)
        max_gas_fee = tx.gas * effective_gas_price + blob_gas_used * blob_gas_price

        # Verify sender is an EOA or has delegation support
        if sender_address not in sender_balances:
            account = get_account(chain.state, sender_address)
            is_sender_eoa = (
                account.code == bytearray()
                or is_valid_delegation(account.code)
            )
            if not is_sender_eoa:
                raise InvalidBlock
            sender_balances[sender_address] = account.balance
            sender_nonces[sender_address] = account.nonce

        # Verify sender has sufficient balance
        if sender_balances[sender_address] &lt; max_gas_fee + Uint(tx.value):
            raise InvalidBlock

        # Verify correct nonce
        if sender_nonces[sender_address] != tx.nonce:
            raise InvalidBlock

        # Track balance and nonce changes
        sender_balances[sender_address] -= max_gas_fee + Uint(tx.value)
        sender_nonces[sender_address] += 1

    # Validate gas constraints
    if total_inclusion_gas &gt; block.header.gas_used:
        raise InvalidBlock
    if total_blob_gas_used != block.header.blob_gas_used:
        raise InvalidBlock

    # Validate withdrawals trie
    for i, wd in enumerate(block.withdrawals):
        trie_set(withdrawals_trie, rlp.encode(Uint(i)), rlp.encode(wd))

    if block.header.withdrawals_root != root(withdrawals_trie):
        raise InvalidBlock
```

This validation function enforces several requirements:

1. Clients MUST validate that the block&apos;s parent execution outputs match the chain&apos;s tracked last execution outputs.
2. The `pre_state_root` MUST match the current state root to ensure proper state transition.
3. All transactions MUST be statically validated for signature correctness and transaction type-specific requirements ([EIP-1559](/EIPs/EIPS/eip-1559), [EIP-4844](/EIPs/EIPS/eip-4844), etc.).
4. Sender accounts MUST be externally owned accounts (EOAs) or have valid delegation support ([EIP-7702](/EIPs/EIPS/eip-7702)).
5. Senders MUST have sufficient balance to cover maximum possible gas fees plus transaction value.
6. Transaction nonces MUST be correct and sequential per sender.
7. Total inclusion gas (using the maximum of intrinsic gas and [EIP-7623](/EIPs/EIPS/eip-7623) floor cost) MUST not exceed the block&apos;s declared gas_used.
8. Total blob gas MUST match the declared blob_gas_used.
9. Withdrawal trie root MUST match its respective header field.

When calculating inclusion gas, the implementation uses the maximum of the regular intrinsic gas cost and the [EIP-7623](/EIPs/EIPS/eip-7623) calldata floor cost, which ensures proper accounting for calldata gas regardless of execution outcome.

### Block Execution with State Snapshots

After a block passes static validation, execution proceeds with the pre-charged transaction senders:

```python
def apply_body(
    block_env: vm.BlockEnvironment,
    transactions: Tuple[Union[LegacyTransaction, Bytes], ...],
    withdrawals: Tuple[Withdrawal, ...],
) -&gt; vm.BlockOutput:
    block_output = vm.BlockOutput()

    # Process system transactions first (beacon roots, history storage)
    process_system_transaction(
        block_env=block_env,
        target_address=BEACON_ROOTS_ADDRESS,
        data=block_env.parent_beacon_block_root,
    )

    process_system_transaction(
        block_env=block_env,
        target_address=HISTORY_STORAGE_ADDRESS,
        data=block_env.block_hashes[-1],  # The parent hash
    )

    # Process user transactions
    process_transactions(block_env, block_output, transactions)

    # Process withdrawals
    process_withdrawals(block_env, block_output, withdrawals)

    # Process requests (deposits, withdrawals, consolidations)
    # not generated if execution_reverted in header is True
    process_general_purpose_requests(
        block_env=block_env,
        block_output=block_output,
    )

    return block_output

def process_transactions(
    block_env: vm.BlockEnvironment,
    block_output: vm.BlockOutput,
    transactions: Tuple[Union[LegacyTransaction, Bytes], ...],
) -&gt; None:
    # Take a block-level snapshot of the state before transaction execution
    begin_transaction(block_env.state)

    # Decode transactions
    decoded_transactions = [decode_transaction(tx) for tx in transactions]

    # Pre-charge senders for maximum possible gas fees upfront
    for tx in decoded_transactions:
        deduct_max_tx_fee_from_sender_balance(block_env, tx)

    # Execute each transaction
    for i, tx in enumerate(decoded_transactions):
        process_transaction(block_env, block_output, tx, Uint(i))
        # Stop processing if execution is already reverted
        if block_output.execution_reverted:
            break

    # Validate declared gas used against actual gas used
    block_output.execution_reverted = (
        block_output.execution_reverted
        or block_output.block_gas_used != block_env.block_gas_used
    )

    # If execution is reverted, reset all outputs and rollback the state
    if block_output.execution_reverted:
        rollback_transaction(block_env.state)
        block_output.block_gas_used = Uint(0)
        block_output.transactions_trie = Trie(secured=False, default=None)
        block_output.receipts_trie = Trie(secured=False, default=None)
        block_output.receipt_keys = ()
        block_output.block_logs = ()
        block_output.requests = []
        block_output.execution_reverted = True
    else:
        # Commit the state if execution is valid
        commit_transaction(block_env.state)
```

During block execution:

1. Clients MUST create a block-level snapshot before any transaction execution occurs. This happens after handling the system contracts from [EIP-4788](./eip-4788) and [EIP-2935](./eip-2935).

2. Maximum fees MUST be deducted from sender balances upfront by:

```python
def deduct_max_tx_fee_from_sender_balance(block_env, tx):
    effective_gas_price = calculate_effective_gas_price(tx, block_env.base_fee_per_gas)
    blob_gas_price = calculate_blob_gas_price(block_env.excess_blob_gas)
    blob_gas_used = calculate_total_blob_gas(tx)
    max_gas_fee = tx.gas * effective_gas_price + blob_gas_used * blob_gas_price
    sender = recover_sender(block_env.chain_id, tx)
    sender_account = get_account(block_env.state, sender)
    set_account_balance(block_env.state, sender, sender_account.balance - U256(max_gas_fee))
```

3. Transactions are executed sequentially until executing a transaction would cause the block to exceed the gas limit.

4. After execution, clients MUST verify that the total gas used matches the declared `gas_used` in the block header.

5. If the actual gas used doesn&apos;t match the declared value, clients MUST:
   - Set `execution_reverted` to `True`
   - Roll back to the snapshot taken before execution
   - Reset all execution outputs (receipts, logs, etc.)
   - Return zero gas used

6. The block itself remains valid, but execution outputs are not applied to the state.

7. General purpose requests as defined in [EIP-7685](/EIPs/EIPS/eip-7685) are skipped when execution is reverted.

8. The execution outputs (`last_transactions_root`, `last_receipt_root`, `last_block_logs_bloom`, `last_requests_hash`, `last_execution_reverted`) are updated in the chain state based on the execution results, and will be verified in subsequent blocks.

Execution SHALL be stopped and the payload reverted after exceeding the block gas limit:

```python
def process_transaction(...)
  if block_output.block_gas_used + tx.gas &gt; block_env.block_gas_limit:
        block_output.execution_reverted = True
        return
  ...
```

## Rationale

### Deferred Execution Outputs

The core innovation of deferring execution outputs to the next block enables static and stateful validation without requiring immediate execution. The `pre_state_root` provides a cryptographically verifiable starting point for validation, while parent execution outputs create a chain of deferred execution results that maintains the integrity of the blockchain state.

This approach eliminates the execution bottleneck in the validation pipeline by allowing validators to attest to a block&apos;s validity based on its structure and the pre-charged transaction fees, without waiting for execution results.

### Pre-Charging Mechanism

Pre-charging senders with the maximum possible fees before execution provides a crucial guarantee that transactions have sufficient balance to be included in the block. This mechanism is compatible with existing fee models, including [EIP-1559](/EIPs/EIPS/eip-1559) dynamic fee transactions and [EIP-4844](/EIPs/EIPS/eip-4844) blob transactions.

By tracking sender balances and nonces during validation, the protocol can enforce transaction validity without execution, enabling earlier block attestation.

### State Snapshot Architecture

The block-level snapshot mechanism provides a way to revert execution when necessary. This approach allows clients to roll back the entire block&apos;s execution if the actual gas used does not match the declared gas in the header, without invalidating the block structure itself.

This provides two key benefits:

1. It allows validators to attest to blocks before execution is complete
2. It ensures execution is eventually performed correctly, with economic penalties for incorrect gas declarations

### Execution Reversion Handling

When a block&apos;s execution is reverted due to gas mismatch:

1. The block itself remains valid and part of the canonical chain
2. The `last_execution_reverted` flag is set to `True` in chain state
3. The next block must include this flag as `parent_execution_reverted`
4. Base fee calculations for subsequent blocks use 0 as parent gas used when parent execution was reverted

## Backwards Compatibility

This EIP requires a hard fork, as it alters the block validation and execution process.

## Security Considerations

### Execution Correctness Guarantees

The protocol ensures execution correctness through these primary mechanisms:

1. Deferred execution outputs MUST match in subsequent blocks, creating a chain of verifiable execution results.
2. State rollback MUST occur if the actual gas used doesn&apos;t match the declared value, providing an economic incentive for correct gas declaration.
3. The `parent_execution_reverted` flag ensures that blocks acknowledge when parent execution has been reverted, maintaining chain integrity.
4. Static and stateful validation guarantees that all transactions are properly authorized and senders have sufficient funds for maximum fees.

### Base Fee Dynamics with Reverted Execution

When a block&apos;s execution is reverted, the next block&apos;s base fee calculation treats the parent&apos;s gas used as zero, regardless of what was declared in the header. This ensures that base fee adjustments remain responsive to actual chain usage, and prevents manipulation of the fee market through incorrect gas declarations.

### Data Availability and Economic Incentives

Block proposers MUST declare correct gas usage or lose transaction fees when execution is reverted. This aligns incentives for correct gas declaration and ensures execution integrity.

Even when a block&apos;s execution is reverted due to incorrect gas declaration, the transaction data (calldata, [EIP-2930](/EIPs/EIPS/eip-2930) access lists, and blob data) MUST still be stored by all nodes for syncing and block validation purposes. This requirement creates a potential attack vector where malicious actors could attempt to place large amounts of data on-chain at a reduced cost by intentionally invalidating blocks through incorrect gas declarations.

However, this attack is not economically sustainable for several reasons:

1. Block proposers who invalidate blocks through incorrect gas declarations lose all execution layer rewards associated with the block.
2. The attack requires control of block production, which is a scarce resource in the consensus layer.

The economic costs of forgoing block rewards significantly outweigh any potential benefits, making such attacks financially impractical under normal network conditions.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 18 Feb 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7886</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7886</guid>
      </item>
    
      <item>
        <title>Cancelation for ERC-7540 Tokenized Vaults</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7887-cancelation-for-erc-7540-tokenized-vaults/22906</comments>
        
        <description>## Abstract

The following standard extends [ERC-7540](/EIPs/EIPS/eip-7540) by adding support for asynchronous cancelation flows.

New methods are added to asynchronously cancel a deposit or redeem Request, view the status of the cancelation Request, and claim the assets or shares as a result of the cancelation Request.

## Motivation

Shares or assets locked for Requests can be stuck in the Pending state. For some use cases, such as redeeming from a pool of long-dated real-world assets, this can take a considerable amount of time.

This standard expands the scope of Asynchronous ERC-7540 Vaults by adding cancelation support.

## Specification

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

### Definitions

The existing definitions from [ERC-7540](/EIPs/EIPS/eip-7540) apply.

### Cancelation Lifecycle

After submission, cancelation Requests go through Pending, Claimable, and Claimed stages. An example lifecycle for a deposit cancelation Request is visualized in the table below.

| **State**   | **User**                         | **Vault** |
|-------------|---------------------------------|-----------|
| Pending     | `cancelDepositRequest(requestId, controller)` | `pendingCancelDepositRequest[controller] = true` |
| Claimable   |                                 | *Internal cancelation fulfillment*:  `pendingCancelDepositRequest[controller] = false`; `claimableCancelDepositRequest[controller] = assets` |
| Claimed     | `claimCancelDepositRequest(requestId, receiver, controller)`      | `claimableDepositRequest[controller] -= assets`; `asset.balanceOf[receiver] += assets` |

`pendingCancelDepositRequest` and `claimableCancelDepositRequest` are defined in the [Methods](#methods) section.

Requests MUST NOT skip or otherwise short-circuit the Claim state. In other words, to initiate and claim a Request, a user MUST call both cancel* and the corresponding Claim function separately, even in the same block. Vaults MUST NOT &quot;push&quot; tokens onto the user after a Request, users MUST &quot;pull&quot; the tokens via the Claim function.

Requests MAY skip straight from the Pending to the Claimable stage, in the case of synchronous cancelation flows.

While a deposit cancelation Request is Pending, new deposit Requests are blocked. Likewise, while a redeem cancelation Request is Pending, new redeem Requests are blocked.

### Methods

#### `cancelDepositRequest`

Submits a Request for asynchronous deposit cancelation. This places the Request in Pending state, with a corresponding increase in `pendingCancelDepositRequest` for the full amount of the pending deposit Request. 

When the cancelation is Pending, new deposit Requests are blocked and `requestDeposit` MUST revert.

When the cancelation is Claimable, `claimableCancelDepositRequest` will be increased for the `controller`. `claimCancelDepositRequest` can subsequently be called by `controller` to receive `assets`. A Request MAY transition straight to Claimable state but MUST NOT skip the Claimable state.

`controller` MUST equal `msg.sender` unless the `controller` has approved the `msg.sender` as an operator.

MUST emit the `CancelDepositRequest` event.

```yaml
- name: cancelDepositRequest
  type: function
  stateMutability: nonpayable

  inputs:
    - name: requestId
      type: uint256
    - name: controller
      type: address
  outputs:
```

#### `pendingCancelDepositRequest`

Whether the given `requestId` and `controller` have a pending deposit cancelation Request.

MUST NOT show any variations depending on the caller.

MUST NOT revert unless due to integer overflow caused by an unreasonably large input.

```yaml
- name: pendingCancelDepositRequest
  type: function
  stateMutability: view

  inputs:
    - name: requestId
      type: uint256
    - name: controller
      type: address

  outputs:
    - name: isPending
      type: bool
```

#### `claimableCancelDepositRequest`

The amount of `assets` in Claimable cancelation state for the `controller` to claim.

MUST NOT show any variations depending on the caller.

MUST NOT revert unless due to integer overflow caused by an unreasonably large input.

```yaml
- name: claimableCancelDepositRequest
  type: function
  stateMutability: view

  inputs:
    - name: requestId
      type: uint256
    - name: controller
      type: address

  outputs:
    - name: assets
      type: uint256
```

#### `claimCancelDepositRequest`

Claims the deposit cancelation Request with `requestId` and `controller`.

Transfers `assets` to `receiver`.

`controller` MUST equal `msg.sender` unless the `controller` has approved the `msg.sender` as an operator.

MUST emit the `ClaimCancelDepositRequest` event.

```yaml
- name: claimCancelDepositRequest
  type: function
  stateMutability: nonpayable

  inputs:
    - name: requestId
      type: uint256
    - name: receiver
      type: address
    - name: controller
      type: address
  outputs:
```

#### `cancelRedeemRequest`

Submits a Request for asynchronous redeem cancelation. This places the Request in Pending state, with a corresponding increase in `pendingCancelRedeemRequest` for the full amount of the pending redeem Request. 

When the cancelation is Pending, new redeem Requests are blocked and `requestRedeem` MUST revert.

When the cancelation is Claimable, `claimableCancelRedeemRequest` will be increased for the `controller`. `claimCancelRedeemRequest` can subsequently be called by `controller` to receive `shares`. A Request MAY transition straight to Claimable state but MUST NOT skip the Claimable state.

`controller` MUST equal `msg.sender` unless the `controller` has approved the `msg.sender` as an operator.

MUST emit the `CancelRedeemRequest` event.

```yaml
- name: cancelRedeemRequest
  type: function
  stateMutability: nonpayable

  inputs:
    - name: requestId
      type: uint256
    - name: controller
      type: address
  outputs:
```

#### `pendingCancelRedeemRequest`

Whether the given `requestId` and `controller` have a pending redeem cancelation Request.

MUST NOT show any variations depending on the caller.

MUST NOT revert unless due to integer overflow caused by an unreasonably large input.

```yaml
- name: pendingCancelRedeemRequest
  type: function
  stateMutability: view

  inputs:
    - name: requestId
      type: uint256
    - name: controller
      type: address

  outputs:
    - name: isPending
      type: bool
```

#### `claimableCancelRedeemRequest`

The amount of `shares` in Claimable cancelation state for the `controller` to claim.

MUST NOT show any variations depending on the caller.

MUST NOT revert unless due to integer overflow caused by an unreasonably large input.

```yaml
- name: claimableCancelRedeemRequest
  type: function
  stateMutability: view

  inputs:
    - name: requestId
      type: uint256
    - name: controller
      type: address

  outputs:
    - name: shares
      type: uint256
```

#### `claimCancelRedeemRequest`

Claims the redeem cancelation Request with `requestId` and `controller`.

Transfers `assets` to `receiver`.

`controller` MUST equal `msg.sender` unless the `controller` has approved the `msg.sender` as an operator.

MUST emit the `ClaimCancelRedeemRequest` event.

```yaml
- name: claimCancelRedeemRequest
  type: function
  stateMutability: nonpayable

  inputs:
    - name: requestId
      type: uint256
    - name: receiver
      type: address
    - name: owner
      type: address
  outputs:
```

### Events

#### `CancelDepositRequest`

`controller` has requested cancelation of their deposit Request with request ID `requestId`. `sender` is the caller of the `cancelDepositRequest` which may not be equal to the `controller`.

MUST be emitted when a deposit cancelation Request is submitted using the `cancelDepositRequest` method.

```yaml
- name: CancelDepositRequest
  type: event

  inputs:
    - name: controller
      indexed: true
      type: address
    - name: requestId
      indexed: true
      type: uint256
    - name: sender
      indexed: false
      type: address
```

#### `CancelDepositClaim`

`controller` has claimed their deposit cancelation Request with request ID `requestId`. `receiver` is the destination of the `assets`. `sender` is the caller of the `claimCancelDepositRequest` which may not be equal to the `controller`.

MUST be emitted when a deposit cancelation Request is submitted using the `claimCancelDepositRequest` method.

```yaml
- name: CancelDepositClaim
  type: event

  inputs:
    - name: controller
      indexed: true
      type: address
    - name: receiver
      indexed: true
      type: address
    - name: requestId
      indexed: true
      type: uint256
    - name: sender
      indexed: false
      type: address
    - name: assets
      indexed: false
      type: uint256
```

#### `CancelRedeemRequest`

`controller` has requested cancelation of their deposit Request with request ID `requestId`. `sender` is the caller of the `cancelRedeemRequest` which may not be equal to the `controller`.

MUST be emitted when a redeem cancelation Request is submitted using the `cancelRedeemRequest` method.

```yaml
- name: CancelRedeemRequest
  type: event

  inputs:
    - name: controller
      indexed: true
      type: address
    - name: requestId
      indexed: true
      type: uint256
    - name: sender
      indexed: false
      type: address
```

#### `CancelRedeemClaim`

`controller` has claimed their redeem cancelation Request with request ID `requestId`. `receiver` is the destination of the `shares`. `sender` is the caller of the `claimCancelRedeemRequest` which may not be equal to the `controller`.

MUST be emitted when a redeem cancelation Request is submitted using the `claimCancelRedeemRequest` method.

```yaml
- name: CancelRedeemClaim
  type: event

  inputs:
    - name: controller
      indexed: true
      type: address
    - name: receiver
      indexed: true
      type: address
    - name: requestId
      indexed: true
      type: uint256
    - name: sender
      indexed: false
      type: address
    - name: shares
      indexed: false
      type: uint256
```

### [ERC-165](/EIPs/EIPS/eip-165) support

Smart contracts implementing this Vault standard MUST implement the [ERC-165](/EIPs/EIPS/eip-165) `supportsInterface` function.

Asynchronous deposit Vaults with cancelation support MUST return the constant value `true` if `0x8bf840e3` is passed through the `interfaceID` argument.

Asynchronous redemption Vaults with cancelation support MUST return the constant value `true` if `0xe76cffc7` is passed through the `interfaceID` argument.

## Rationale

### Blocking Requests during Cancelation

When `cancelDepositRequest` is called by a `controller`, new deposit Requests are blocked for this `controller`, and the equivalent applies to the redeem flow.

This requirement simplifies the possible states of vaults implementing asynchronous cancelation flows.

The alternative would create possible states where a cancelation is pending and a new deposit Request is triggered, leading to the current state being complex to read for integrators.

### Mandated Support for [ERC-165](/EIPs/EIPS/eip-165)

Implementing support for [ERC-165](/EIPs/EIPS/eip-165) is mandated because of the optionality of flows as defined in [ERC-7540](/EIPs/EIPS/eip-7540). Integrations can use the `supportsInterface` method to check whether a vault is fully asynchronous, partially asynchronous, or fully synchronous (for which it is just following the [ERC-4626](./eip-4626)), and use a single contract to support all cases.

## Backwards Compatibility

The interface is fully backwards compatible with [ERC-7540](/EIPs/EIPS/eip-7540).

## Security Considerations

Existing security considerations from [ERC-7540](/EIPs/EIPS/eip-7540) apply.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 18 Feb 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7887</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7887</guid>
      </item>
    
      <item>
        <title>Crosschain Broadcaster</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/new-erc-cross-chain-broadcaster/22927</comments>
        
        <description>## Abstract

This ERC defines a protocol for cross-rollup messaging using state commitments. Users can broadcast messages on a source chain, and those messages can be verified on any other chain that shares a common ancestor with the source chain. 

A state commitment is a `bytes32` hash that commits to a chain&apos;s state (e.g., block hash or state root). The protocol supports different types of state commitments depending on what the rollup commits to its parent chain. Block hashes are the recommended state commitment, but state roots or other commitments may be used, such as batch hashes (since some rollups don&apos;t commit single blocks, but batches of blocks instead). 

Each chain deploys a singleton Receiver and Broadcaster contract. Broadcasters store messages; Receivers verify the Broadcasters&apos; state on remote chains. To do this, a Receiver first verifies a chain of state commitment proofs to recover a remote state commitment, then verifies the Broadcaster&apos;s state at that commitment.

Critically, the logic for verifying state commitment proofs is not hardcoded in the Receiver. Instead, it delegates this to a user specified list of StateProver contracts. Each StateProver defines how to verify a state commitment proof for a specific home chain to recover the state commitment of a specific target chain. Because the state commitment schemes and layouts of rollup contracts can change over time, the state commitment proof verification process itself must also be upgradeable&amp;mdash;hence the StateProvers are upgradeable. This flexible, upgradeable proof verification model is the core contribution of this standard.

## Motivation

The Ethereum ecosystem is experiencing a rapid growth in the number of rollup chains. As the number of chains grows, the experience becomes more fragmented for users, creating a need for trustless &quot;interop&quot; between rollup chains. These rollup chains, hosted on different rollup stacks, have heterogeneous properties, and as yet there does not exist a simple, trustless, unified mechanism for sending messages between these diverse chains.

Many classes of applications could benefit from a unified system for broadcasting messages across chains. Some examples include:

- **Intent-Based Protocols:** These protocols enable &quot;fillers&quot; to quickly execute crosschain actions on behalf of users, followed by slower, trustless messaging to settle these actions. However, due to the lack of a simple, unified interface for sending settlement messages, intent protocols often develop proprietary methods. This raises adoption barriers for fillers, integrators, and new protocols. A pluggable, standardized messaging solution that works across rollup stacks would allow developers and standards authors to focus on other components of the intent stack, such as fulfillment constraints, order formats, and escrow.
- **Governance of multichain apps:** Multichain apps often have a single chain where core governance contracts are located. A standardized broadcast messaging system simplifies the dissemination of proposal results to all instances of a multichain app.
- **Multichain Oracles:** Some classes of oracles may benefit from being able to post their data to a single chain, while having that same data easily accessible across many other chains.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### Compatibility Requirements

Chains must satisfy the following conditions to be compatible with the system:

- Must store finalized state commitments on the parent chain
- Must store parent chain state commitments in child chain state
- Must be EVM equivalent with L1. StateProvers are deployed as copies on many chains, so need to behave the same on all those chains

### Constants

```solidity
uint256 constant STATE_PROVER_POINTER_SLOT = uint256(keccak256(&quot;eip7888.pointer.slot&quot;)) - 1;
```

### State Commitments

A **state commitment** is a `bytes32` hash that commits to the state of a chain at a particular point in time. This commitment is produced by the rollup and serves as a cryptographic representation of the chain&apos;s state. The most common state commitments are:

- **Block hash**: A hash of the block header, which is the recommended state commitment for most implementations
- **State root**: The root of the state tree (e.g., Merkle-Patricia Trie) or other state commitment structure
- **Batch hash**: A hash of a batch of blocks, used by some rollups that commit batches of blocks rather than individual blocks

The choice of state commitment depends on what the rollup commits to its parent chain. Different rollups may use different state commitments, and the StateProver is responsible for verifying proofs that recover these commitments from the parent chain&apos;s state.

### Broadcaster

The Broadcaster is responsible for storing messages in state to be read by Receivers on other chains. Callers of the Broadcaster are known as Publishers. The Broadcaster stores only 32 byte messages.

The Broadcaster does not accept duplicate messages from the same publisher.

&lt;div align=&quot;center&quot;&gt;
&lt;img src=&quot;../assets/eip-7888/broadcasting.svg&quot; alt=&quot;Figure 1&quot; width=&quot;30%&quot;/&gt;
&lt;br/&gt;
&lt;em&gt;Figure 1: A Publisher at address 0x4 calling a Broadcaster at address 0x3&lt;/em&gt;
&lt;/div&gt;

```solidity
/// @notice Broadcasts messages to receivers.
interface IBroadcaster {
    /// @notice Emitted when a message is broadcast.
    /// @param  message The message that was broadcast by the publisher.
    /// @param  publisher The address of the publisher.
    event MessageBroadcast(bytes32 indexed message, address indexed publisher);

    /// @notice Broadcasts a message. Callers are called &quot;publishers&quot;.
    /// @dev    MUST revert if the publisher has already broadcast the message.
    ///         MUST emit MessageBroadcast.
    ///         MUST store block.timestamp in slot keccak(message, msg.sender).
    ///         MAY use additional transmission mechanisms (e.g., child-to-parent native bridges) to make messages visible.
    /// @param  message The message to broadcast.
    function broadcastMessage(bytes32 message) external;
}
```

### StateProvers
StateProvers prove a unidirectional link between two chains that have direct access to each other&apos;s finalized state commitments. The chains in this link are called the **home chain** and the **target chain**. StateProvers are responsible for verifying state commitment proofs to prove the existence of finalized target state commitments in the state of the home chain. Block hashes are the recommended state commitment, but implementations may use other commitments (e.g., state roots, batch hashes).

Since the StateProvers are unidirectional, each chain needs to have two: 
* One whose home is the child chain and target is the parent chain.
* One whose home is the parent chain and target is the child chain.

StateProvers MUST ensure that they will have the same deployed code hash on all chains.

&lt;div align=&quot;center&quot;&gt;
&lt;img src=&quot;../assets/eip-7888/BHP.svg&quot; alt=&quot;Figure 2&quot; width=&quot;30%&quot;/&gt;
&lt;br/&gt;
&lt;em&gt;Figure 2: A StateProver with home chain L and target chain M&lt;/em&gt;
&lt;/div&gt;

```solidity
/// @notice The IStateProver is responsible for retrieving the state commitment of its target chain given its home chain&apos;s state.
///         The home chain&apos;s state is given either by a state commitment and proof, or by the StateProver executing on the home chain.
///         A single home and target chain are fixed by the logic of this contract.
interface IStateProver {
    /// @notice Verify the state commitment of the target chain given the state commitment of the home chain and a proof.
    /// @dev    MUST revert if called on the home chain.
    ///         MUST revert if the input is invalid or the input is not sufficient to determine the state commitment.
    ///         MUST return a target chain state commitment.
    ///         MUST be pure, with 1 exception: MAY read address(this).code.
    /// @param  homeStateCommitment The state commitment of the home chain.
    /// @param  input Any necessary input to determine a target chain state commitment from the home chain state commitment.
    /// @return targetStateCommitment The state commitment of the target chain.
    function verifyTargetStateCommitment(bytes32 homeStateCommitment, bytes calldata input)
        external
        view
        returns (bytes32 targetStateCommitment);

    /// @notice Get the state commitment of the target chain. Does so by directly accessing state on the home chain.
    /// @dev    MUST revert if not called on the home chain.
    ///         MUST revert if the target chain&apos;s state commitment cannot be determined.
    ///         MUST return a target chain state commitment.
    ///         SHOULD use the input to determine a specific state commitment to return. (e.g. input could be a block number)
    ///         SHOULD NOT read from its own storage. This contract is not meant to have state.
    ///         MAY make external calls.
    /// @param  input Any necessary input to fetch a target chain state commitment.
    /// @return targetStateCommitment The state commitment of the target chain.
    function getTargetStateCommitment(bytes calldata input) external view returns (bytes32 targetStateCommitment);

    /// @notice Verify a storage slot given a target chain state commitment and a proof.
    /// @dev    This function MUST NOT assume it is being called on the home chain.
    ///         MUST revert if the input is invalid or the input is not sufficient to determine a storage slot and its value.
    ///         MUST return a storage slot and its value on the target chain.
    ///         MUST be pure, with 1 exception: MAY read address(this).code.
    ///         While messages MUST be stored in storage slots, alternative reading mechanisms may be used in some cases.
    /// @param  targetStateCommitment The state commitment of the target chain.
    /// @param  input Any necessary input to determine a single storage slot and its value.
    /// @return account The address of the account on the target chain.
    /// @return slot The storage slot of the account on the target chain.
    /// @return value The value of the storage slot.
    function verifyStorageSlot(bytes32 targetStateCommitment, bytes calldata input)
        external
        view
        returns (address account, uint256 slot, bytes32 value);

    /// @notice The version of the state commitment prover.
    /// @dev    MUST be pure, with 1 exception: MAY read address(this).code.
    function version() external pure returns (uint256);
}
```

### StateProverPointers

StateProvers can be used to get or verify target state commitments, however since their verification logic is immutable, changes to the structure of the home or target chain can break the logic in these Provers. A StateProverPointer is a Pointer to a StateProver which can be updated if proving logic needs to change.

StateProverPointers are used to reference StateProvers as opposed to referencing Provers directly. To that end, wherever a StateProver is deployed a StateProverPointer needs to be deployed to reference it.

StateProverPointers allow a permissioned party to update the Prover reference within the Pointer. Choosing which party should have the permission to update the Prover reference should be carefully considered. The general rule is that if an update to the target or home chain could break the logic in the current Prover, then the party, or mechanism, able to make that update should also be given permission to update the Prover. See [Security Considerations](#security-considerations) for more information on StateProverPointer ownership and updates.

When updating a StateProverPointer to point to a new StateProver implementation:
* The home and target chain of the new StateProver MUST be identical to the previous StateProver.
* The new StateProver MUST have a higher version than the previous StateProver.

StateProverPointers MUST store the code hash of the StateProver implementation in slot `STATE_PROVER_POINTER_SLOT`.

&lt;div align=&quot;center&quot;&gt;
&lt;img src=&quot;../assets/eip-7888/pointer.svg&quot; alt=&quot;Figure 3&quot; width=&quot;30%&quot;/&gt;
&lt;br/&gt;
&lt;em&gt;Figure 3: A StateProverPointer at address 0xA pointing to a StateProver with home chain L and target chain M&lt;/em&gt;
&lt;/div&gt;

```solidity
/// @title  IStateProverPointer
/// @notice Keeps the code hash of the latest version of a state commitment prover.
///         MUST store the code hash in storage slot STATE_PROVER_POINTER_SLOT.
///         Different versions of the prover MUST have the same home and target chains.
///         If the pointer&apos;s prover is updated, the new prover MUST have a higher IStateProver::version() than the old one.
///         These pointers are always referred to by their address on their home chain.
interface IStateProverPointer {

    /// @notice Emitted when the pointer is set to a new implementation.
    /// MUST be emitted when the pointer is set
    event ImplementationAddressSet(
        uint256 indexed newVersion,
        address indexed newImplementationAddress,
        bytes32 indexed newCodeHash,
        address oldImplementationAddress
    );

    /// @notice Return the code hash of the latest version of the prover.
    function implementationCodeHash() external view returns (bytes32);

    /// @notice Return the address of the latest version of the prover on the home chain.
    function implementationAddress() external view returns (address);
}
```

### Routes

A route is a relative path from a Receiver on a local chain to a remote chain. It is constructed of many single degree links dictated by StateProverPointers. Receivers use the StateProvers that the Pointers reference to verify a series of proofs to obtain the remote chain&apos;s state commitment. A route works with any state commitment scheme (block hashes, state roots, etc.) and is defined by the list of Pointer addresses on their home chains.

A valid route MUST obey the following:
- Home chain of the `route[0]` Pointer must equal the local chain
- Target chain of the `route[i]` Pointer must equal home chain of the `route[i+1]` Pointer

&lt;div align=&quot;center&quot;&gt;
&lt;img src=&quot;../assets/eip-7888/route.svg&quot; alt=&quot;Figure 4&quot; width=&quot;80%&quot;/&gt;
&lt;br/&gt;
&lt;em&gt;Figure 4: A route [0xA, 0xB, 0xC] from chain L to chain R&lt;br/&gt;
Chain L is an L2, Chain M is Ethereum Mainnet, Chain P is another L2, and Chain R is an L3 settling to Chain P&lt;/em&gt;
&lt;/div&gt;

### Identifiers

Accounts on remote chains are identified by the route taken from the local chain plus the address on the remote chain. The Pointer addresses used in the route, along with the remote address, are cumulatively keccak256 hashed together to form a **Remote Account ID**.

In this way any address on a remote chain, including Pointers and Broadcasters, can be uniquely identified relative to the local chain by their Remote Account ID.

ID&apos;s depend on a route and are therefore always *relative* to a local chain. In other words, the same account on a given chain will have different ID&apos;s depending on the route from the local chain.

The Remote Account ID is defined as `accumulator([...route, remoteAddress])`

```solidity
function accumulator(address[] memory elems) pure returns (bytes32 acc) {
    for (uint256 i = 0; i &lt; elems.length; i++) {
        acc = keccak256(abi.encode(acc, elems[i]));
    }
}
```

In Figure 4:
- The Remote Account ID of Broadcaster at `0x3` is `accumulator([0xA, 0xB, 0xC, 0x3])`
- The Remote Account ID of StateProverPointer `0xC` is `accumulator([0xA, 0xB, 0xC])`.

### StateProverCopies

StateProverCopies are exact copies of StateProvers deployed on non-home chains. When a StateProver code hash is de-referenced from a Pointer, a copy of the StateProver may be used to execute its logic. Since the Pointer references the prover by code hash, a local copy of the Prover can be deployed and used to execute specific proving logic. The Receiver caches a map of `mapping(bytes32 stateProverPointerId =&gt; IStateProver stateProverCopy)` to keep track of StateProverCopies. 

&lt;div align=&quot;center&quot;&gt;
&lt;img src=&quot;../assets/eip-7888/BHPCopy.svg&quot; alt=&quot;Figure 5&quot; width=&quot;30%&quot;/&gt;
&lt;br/&gt;
&lt;em&gt;Figure 5: A StateProverCopy of StateProver M-&gt;P on chain L&lt;/em&gt;
&lt;/div&gt;

### Receiver

The Receiver is responsible for verifying 32 byte messages deposited in Broadcasters on other chains. The caller provides the Receiver with a route to the remote account and proof to verify the route.

&lt;div align=&quot;center&quot;&gt;
&lt;img src=&quot;../assets/eip-7888/receiving.svg&quot; alt=&quot;Figure 6&quot; width=&quot;80%&quot;/&gt;
&lt;br/&gt;
&lt;em&gt;Figure 6: Example of a Receiver reading a message from a Broadcaster on chain R&lt;/em&gt;
&lt;/div&gt;

The calls in Figure 6 perform the following operations:
1. Subscriber calls `IReceiver::verifyBroadcastMessage`, passing route `[0xA, 0xB, 0xC]`, proof data, message, publisher.
2. Receiver calls `IStateProverPointer(0xA)::implementationAddress` to get the address of StateProver L-&gt;M
3. Receiver calls `IStateProver(Prover L-&gt;M)::getTargetStateCommitment`, passing input given by Subscriber to get a state commitment of chain M.
4. Receiver calls `IStateProver(Prover Copy M-&gt;P)::verifyTargetStateCommitment`, passing chain M&apos;s state commitment and proof data by Subscriber to get a state commitment of chain P.
5. Receiver calls `IStateProver(Prover Copy P-&gt;R)::verifyTargetStateCommitment`, passing chain P&apos;s state commitment and proof data by Subscriber to get a state commitment of chain R.
6. Finally, Receiver calls `IStateProver(Prover Copy P-&gt;R)::verifyStorageSlot`, passing input given by Subscriber to get a storage slot from the Broadcaster. The Receiver returns the Broadcaster&apos;s Remote Account ID and the message&apos;s timestamp to Subscriber.

```solidity
/// @notice Reads messages from a broadcaster.
interface IReceiver {
    /// @notice Arguments required to read state of an account on a remote chain.
    /// @dev    The proof is always for a single storage slot. If the proof is for multiple slots the IReceiver MUST revert.
    ///         The proof format depends on the state commitment scheme used by the StateProver (e.g., storage proofs).
    ///         While messages MUST be stored in storage slots, alternative reading mechanisms may be used in some cases.
    /// @param  route The home chain addresses of the StateProverPointers along the route to the remote chain.
    /// @param  scpInputs The inputs to the StateProver / StateProverCopies.
    /// @param  proof Proof passed to the last StateProver / StateProverCopy
    ///               to verify a storage slot given a target state commitment.
    struct RemoteReadArgs {
        address[] route;
        bytes[] scpInputs;
        bytes proof;
    }

    /// @notice Reads a broadcast message from a remote chain.
    /// @param  broadcasterReadArgs A RemoteReadArgs object:
    ///         - The route points to the broadcasting chain
    ///         - The account proof is for the broadcaster&apos;s account
    ///         - The proof is for the message storage slot (MAY accept proofs of other transmission mechanisms (e.g., child-to-parent native bridges) if the broadcaster contract uses other transmission mechanisms)
    /// @param  message The message to read.
    /// @param  publisher The address of the publisher who broadcast the message.
    /// @return broadcasterId The broadcaster&apos;s unique identifier.
    /// @return timestamp The timestamp when the message was broadcast.
    function verifyBroadcastMessage(RemoteReadArgs calldata broadcasterReadArgs, bytes32 message, address publisher)
        external
        view
        returns (bytes32 broadcasterId, uint256 timestamp);

    /// @notice Updates the state commitment prover copy in storage.
    ///         Checks that StateProverCopy has the same code hash as stored in the StateProverPointer
    ///         Checks that the version is increasing.
    /// @param  scpPointerReadArgs A RemoteReadArgs object:
    ///         - The route points to the StateProverPointer&apos;s home chain
    ///         - The account proof is for the StateProverPointer&apos;s account
    ///         - The proof is for the STATE_PROVER_POINTER_SLOT
    /// @param  scpCopy The StateProver copy on the local chain.
    /// @return scpPointerId The ID of the StateProverPointer
    function updateStateProverCopy(RemoteReadArgs calldata scpPointerReadArgs, IStateProver scpCopy)
        external
        returns (bytes32 scpPointerId);

    /// @notice The StateProverCopy on the local chain corresponding to the scpPointerId
    ///         MUST return 0 if the StateProverPointer does not exist.
    function stateProverCopy(bytes32 scpPointerId) external view returns (IStateProver scpCopy);
}
```

## Rationale

### Broadcast vs Unicast

A contract on any given chain cannot dictate which other chains can and cannot inspect its state. Contracts are naturally broadcasting their state to anything capable of reading it. Targeted messaging applications can always be built on top of a broadcast messaging system.

See [Reference Implementation](#reference-implementation) for an example of a unicast application.

### Using Storage Proofs

Message reading SHOULD use storage proofs to read messages from storage slots. However, an alternative method to this would be to pass messages (perhaps batched) via the canonical bridges of the chains. However storage proofs have some advantages over this method:

- They only require gas tokens on the chains where the message is sent and received, none on the chains on the route in between.
- Batching by default. Since storage slots share a common state root, caching the state root allows readers to open adjacent slots at lower cost. This provides a form of implicit batching, whereas canonical bridges would need to create a form of explicit batching.
- If the common ancestor of the two chains is Ethereum, sending a message using the canonical bridges would require sending a transaction on Ethereum, which would likely incur a high cost.

### No duplicate messages per publisher

To allow publishers to send the same message multiple times, some kind of nonce system would need to exist in this ERC. Since nonces can be implemented at the Publisher / Subscriber layer, and not all Publishers / Subscribers require this feature, it is left out of this ERC.

#### Cost Comparison
Here we compare the cost of using storage proofs vs sending messages via the canonical bridge, where the parent chain is Ethereum. Here, we will only consider the cost of the L1 gas as we assume it to dominate the L2 gas costs.

Each step along the route requires 1 storage proof. These proofs can be estimated at roughly 6.5k bytes. These proofs will likely be submitted on an L2/L3 and therefore be included in blobs on the L1, which have a fluctuating blob gas price. Since rollups can dynamically switch between calldata and blobs, we can work out a maximum amount of normal L1 gas that could be using the standard cost of calldata as an upper bound. Post Pectra, the upper bound for non-zero-byte calldata is 40 gas per byte, which for 6.5k bytes equates to 260,000 L1 gas.

We want to compare this to sending a single message via a canonical rollup bridge, which is either a parent-&gt;child or child-&gt;parent message. This estimate is dependent on specific implementations of the bridge for different rollup frameworks, but we estimate it to be around 150,000 gas.

This puts the upper bound of the storage proof to be around 2x that of the canonical bridge, but in practice this upper bound is rarely reached. On top of that, the Receiver can implement a caching policy allowing many messages to share the same storage proofs.

### Caching
This ERC does not currently describe how the Receiver can cache the results of storage proofs to improve efficiency. In brief, once a storage proof is executed it never needs to be executed again, and instead the result can be stored by the Receiver. This allows messages that share the same, or partially the same, route to share previously executed proofs and instead lookup the result. As an example we can consider the route between two L2s using storage proofs:
1. Ethereum block hash is looked up directly on L2&apos; by the Receiver on L2&apos;
2. The block hash of L2&apos;&apos; is proven using a storage proof
3. The account root of the Broadcaster on L2&apos;&apos; is proven using a storage proof
4. The slot value in the Broadcaster account is proven using a storage proof
The result of everything up to step 4 in this process can be stored in a Receiver cache and re-used by any unread messages in the Broadcaster. The Receiver can even go further and cache individual nodes in the account trie to make step 4. cheaper for previous messages.

### Using Routes in Identifiers

Chains are often identified by chain ID&apos;s. Chain ID&apos;s are set by the chain owner so they are not guaranteed to be unique. Using the addresses of the Pointers is guaranteed to be unique as it provides a way to unwrap the nested state commitments embedded in the state roots. A storage slot on a remote chain can be identified by many different remote account ID&apos;s, but one remote account ID cannot identify more than one storage slot.

### StateProvers, Pointers, and Copies

#### StateProvers
Each rollup implements unique logic for managing and storing state commitments. To accommodate this diversity, StateProvers implement chain-specific procedures. This flexibility allows integration with each rollup&apos;s distinct architecture and state commitment scheme.

The StateProver handles the final step of verifying a storage slot given a target state commitment to accommodate rollups with differing state commitment schemes and formats.

#### StateProverPointers
Routes reference StateProvers through Pointers rather than directly. This indirection is crucial because:
- Chain upgrades may require StateProver redeployments
- Routes must remain stable and valid across these upgrades - ensuring in-flight messages are not broken
- Pointers maintain route consistency while allowing StateProver implementations to evolve

#### StateProverCopies
Since StateProverPointers reference StateProvers via their code hash, a copy of the StateProver can be deployed anywhere and reliably understood to contain the same code as that referenced by the Pointer. This allows the Receiver to locally use the code of a StateProver whose home chain is a remote chain.

## Reference Implementation

The following is an example of a one-way crosschain token migrator. The burn side of the migrator is a publisher which sends burn messages through a Broadcaster. The mint side subscribes to these burn messages through a Receiver on another chain.

```solidity
/// @notice Message format for the burn and mint migrator.
struct BurnMessage {
    address mintTo;
    uint256 amount;
    uint256 nonce;
}
```

```solidity
/// @notice The burn side of an example one-way cross chain token migrator.
/// @dev    This contract is considered a &quot;publisher&quot;
contract Burner {
    /// @notice The token to burn.
    IERC20 public immutable burnToken;
    /// @notice The broadcaster to publish messages through.
    IBroadcaster public immutable broadcaster;
    /// @notice An incrementing nonce, so each burn is a unique message.
    uint256 public burnCount;

    /// @notice Event emitted when tokens are burned.
    /// @dev    Publishers SHOULD emit enough information to reconstruct the message.
    event Burn(BurnMessage messageData);

    constructor(IERC20 _burnToken, IBroadcaster _broadcaster) {
        burnToken = _burnToken;
        broadcaster = _broadcaster;
    }

    /// @notice Burn the tokens and broadcast the event.
    ///         The corresponding token minter will subscribe to the message on another chain and mint the tokens.
    function burn(address mintTo, uint256 amount) external {
        // first, pull in the tokens and burn them
        burnToken.transferFrom(msg.sender, address(this), amount);
        burnToken.burn(amount);

        // next, build a unique message
        BurnMessage memory messageData = BurnMessage({mintTo: mintTo, amount: amount, nonce: burnCount++});
        bytes32 message = keccak256(abi.encode(messageData));

        // finally, broadcast the message
        broadcaster.broadcastMessage(message);

        emit Burn(messageData);
    }
}
```

```solidity
/// @notice The mint side of an example one-way cross chain token migrator.
///         This contract must be given minting permissions on its token.
/// @dev    This contract is considered a &quot;subscriber&quot;
contract Minter {
    /// @notice Address of the Burner contract on the other chain.
    address public immutable burner;
    /// @notice The BroadcasterID corresponding to the broadcaster on the other chain that the Burner uses.
    ///         The Minter will only accept messages published by the Burner through this Broadcaster.
    bytes32 public immutable broadcasterId;
    /// @notice The receiver to listen for messages through.
    IReceiver public immutable receiver;
    /// @notice A mapping to keep track of which messages have been processed.
    ///         Subscribers SHOULD keep track of processed messages because the Receiver does not.
    ///         The Broadcaster ensures messages are unique, so true duplicates are not possible.
    mapping(bytes32 =&gt; bool) public processedMessages;
    /// @notice The token to mint.
    IERC20 public immutable mintToken;

    constructor(address _burner, bytes32 _broadcasterId, IReceiver _receiver, IERC20 _mintToken) {
        burner = _burner;
        broadcasterId = _broadcasterId;
        receiver = _receiver;
        mintToken = _mintToken;
    }

    /// @notice Mint the tokens when a message is received.
    function mintTokens(IReceiver.RemoteReadArgs calldata broadcasterReadArgs, BurnMessage calldata messageData)
        external
    {
        // calculate the message from the data
        bytes32 message = keccak256(abi.encode(messageData));

        // ensure the message has not been processed
        require(!processedMessages[message], &quot;Minter: Message already processed&quot;);

        // verify the broadcast message
        (bytes32 actualBroadcasterId,) = receiver.verifyBroadcastMessage(broadcasterReadArgs, message, burner);

        // ensure the message is from the expected broadcaster
        require(actualBroadcasterId == broadcasterId, &quot;Minter: Invalid broadcaster ID&quot;);

        // mark the message as processed
        processedMessages[message] = true;

        // mint tokens to the recipient
        mintToken.mint(messageData.mintTo, messageData.amount);
    }
}
```

## Security Considerations

### Chain Upgrades
If a chain upgrades such that a StateProver&apos;s `verifyTargetStateCommitment` or `getTargetStateCommitment` functions might return data besides a finalized target state commitment, then invalid messages could be read by a `Receiver`. For instance, if a chain stores its state commitments on the parent chain in a specific mapping, and that storage slot is later repurposed, then an old StateProver might be able to pass along an invalid state commitment. It is therefore important that either:
* the StateProver is written in such a way to detect changes like this
* the owner who is able to repurpose these storage slots is aware of the StateProver and ensures they don&apos;t break it

### StateProverPointer Ownership / Updates
A malicious StateProverPointer owner can DoS or forge messages. However, so can the chain owner responsible for setting the slot of historical parent/child state commitments. Therefore it is expected that this chain owner be the same as the owner of the StateProverPointer so as not to introduce additional risks.

* If the target chain of the referenced StateProver is the parent chain, the home chain owner is expected to be the StateProverPointer&apos;s owner.
* If the target chain of the referenced StateProver is the child chain, the target chain owner is expected to be the StateProverPointer&apos;s owner.

If an owner neglects their responsibility to update the Pointer with new StateProver implementations when necessary, messages could fail to reach their destinations.

If an owner maliciously updates a Pointer to point to a StateProver that produces fraudulent results, messages can be forged.

If there is confidence that a chain along the route connecting them will not upgrade to break a StateProver, an unowned StateProverPointer can be deployed in the absence of a properly owned one.

### Message guarantees
This ERC describes a protocol for ensuring that messages from remote chains CAN be read, but not that they WILL be read. It is the responsibility of the Receiver caller to choose which messages they wish to read.

Since the ERC only uses finalized blocks, messages may take a long time to propagate between chains. Finalisation occurs sequentially in the route, therefore time to read a message is the sum of the finalisation of each of the state commitments at each step in the route.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 18 Feb 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7888</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7888</guid>
      </item>
    
      <item>
        <title>Emit log on revert</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7889-emit-log-on-revert/22918</comments>
        
        <description>## Abstract

All calls to the REVERT opcode with non-zero size must emit a log with revert data, making it accessible via standard RPC without the need for tracing.

## Motivation

Revert messages are currently inaccessible to users as they are not available via standard RPC. Instead, users have to request a node to trace the transaction and check the stack and memory at the moment when the REVERT opcode was executed. 

This introduces overhead for users and nodes - users must make an additional request to find out why their transaction failed, and the node has to replay the full transaction (which may be slow and computationally expensive) to get back a relatively small piece of data.

Currently it is up to smart wallet developers to emit logs before a revert, however this is not a standard feature and thus cannot be relied upon by tools such as client libraries and block explorers. Making this log part of the protocol allows these tools to rely on logs for revert reasons.

## Specification

### Parameters

&lt;!-- TODO --&gt;

* `REVERTTOPIC`: `TBD`
* `DATA_LIMIT`: `TBD`

### Functionality

Whenever `REVERT` is called with non-zero size, emit a log identical to a LOG1 with the topic `REVERTTOPIC`. The log data is the raw bytes of the revert message. The data is truncated to `DATA_LIMIT`.

## Rationale

This is the simplest possible implementation that allows revert messages to be accessible via RPC methods. It does not require any changes to client libraries, or other RPC consumers as it is backward compatible. It does not introduce new RPC methods or new opcodes.

## Backwards Compatibility

Reverted transactions may now contain up to one log.

## Security Considerations

Reverted transactions must cost at least intrinsic gas (21000 gas), which is much more expensive than the LOG1 opcode (750 gas). Hence, this EIP does not introduce any new avenues to inflate Ethereum storage requirements. However, it is expected to increase the average number of logs.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 20 Feb 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7889</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7889</guid>
      </item>
    
      <item>
        <title>Splitting and Merging of NFTs</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7891-hierarchical-nfts-with-splitting-and-merging/22986</comments>
        
        <description>## Abstract

This standard extends [EIP-721](/EIPs/EIPS/eip-721) and [EIP-6150](/EIPs/EIPS/eip-6150). This introduces a structured parent-child relationship between NFTs, allowing an NFT to be fractionally split into multiple child NFTs and merged back into a single entity. It provides interfaces to retrieve an NFT&apos;s parent, children, and hierarchical status, ensuring flexible ownership management. This standard is particularly useful for applications in fractional ownership, asset distribution, and composable digital assets, opening new possibilities in fields like real estate, gaming, and decentralized finance.

## Motivation

This EIP introduces hierarchical NFTs with splitting and merging capabilities, allowing assets to be dynamically restructured. This proposal is crucial for fractional ownership, gaming assets, and financial instruments, where assets need to be split or merged. 

1. **Splitting**: One of the key limitations of [EIP-6150](/EIPs/EIPS/eip-6150) is its rigid hierarchy, where NFTs are permanently assigned to a parent without the ability to restructure ownership. In many real-world scenarios, assets need to be split into smaller, independent units. This EIP introduces a standardized way to split an NFT into multiple child NFTs, enabling dynamic asset management. For example, in financial markets, a share NFT can be split into multiple fractional share NFTs, allowing investors to own and trade smaller portions of a share.

2. **Merging**: Just as assets need to be split, there are scenarios where multiple NFTs should be combined into a single entity. The proposed EIP enables a merging mechanism, allowing child NFTs to be consolidated into a single parent NFT, allowing asset management and transactions. For instance, in finance, fractional share NFTs can be merged back into a full share NFT, enabling seamless ownership consolidation. This is particularly useful for investors who gradually accumulate fractions of a stock and later want to own a full share.

3. **Share Distribution**: This EIP introduces ownership share management, allowing NFTs to track and distribute fractional ownership among multiple stakeholders. This solves fractional ownership tracking within parent-child NFT structures. This also allows dynamic adjustments of ownership based on splitting and merging actions. For example, a real estate NFT representing a building can have multiple owners with different share percentages. When the NFT is split, the new NFTs retain a proportion of the original ownership share. When merged, the system redistributes the shares accordingly. This Enables multi-party ownership in digital assets.

### How the proposed EIP Improves Over Existing Standards

| Feature                  | [EIP-721](/EIPs/EIPS/eip-721) | [EIP-1155](/EIPs/EIPS/eip-1155) | [EIP-6150](/EIPs/EIPS/eip-6150) | EIP (Proposed) |
|--------------------------|---------|---------|---------|------------------|
| Unique NFTs              | ✅      | ❌       | ✅       | ✅                |
| Fungible &amp; Non-Fungible  | ❌       | ✅       | ❌       | ✅                |
| Hierarchical Structure   | ❌       | ❌       | ✅       | ✅                |
| Parent-Child Relationship | ❌       | ❌       | ✅       | ✅                |
| NFT Splitting           | ❌       | ❌       | ❌       | ✅                |
| NFT Merging             | ❌       | ❌       | ❌       | ✅                |
| Fractional Ownership    | ❌       | ✅       | ❌       | ✅                |
| Ownership Redistribution | ❌       | ❌       | ❌       | ✅                |


## Specification

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

Every compliant contract MUST implement this proposal, [EIP-721](./eip-721), [EIP-165](./eip-165), and [ERC-6150](./eip-6150)

```solidity
pragma solidity ^0.8.0;

// Note: the ERC-165 identifier for this interface is 0x43cb816b.
interface IERC7891 /* is IERC6150, IERC721, IERC165 */ {
    /**
     * @notice Emitted when a child token is minted under a parent with an assigned share.
     * @param parentId The ID of the parent token
     * @param childId The ID of the newly minted child token
     * @param share Share percentage assigned to the child token
     */
    event Split(uint256 indexed parentId, uint256 indexed childId, uint8 share);

    /**
     * @notice Emitted when multiple child tokens are merged into a new token.
     * @param newTokenId The ID of the newly minted merged token
     * @param mergedTokenIds Array of token IDs that were merged
     */
    event Merged(uint256 indexed newTokenId, uint256[] mergedTokenIds);
    /**
     * @notice Mints a new root-level parent NFT.
     * @param _tokenURI URI string pointing to token metadata
     * @return tokenId The ID of the newly minted parent token
     */
    function mintParent(string memory _tokenURI) external payable returns (uint256 tokenId);

    /**
     * @notice Mints a child NFT under a given parent with a specific share allocation.
     * @param parentId ID of the parent token
     * @param _share Share percentage assigned to the child token
     * @return tokenId The ID of the newly minted child token
     */
    function mintSplit(uint256 parentId, uint8 _share) external payable returns (uint256 tokenId);

    /**
     * @notice Merges multiple child NFTs into a new token under the same parent.
     * @param parentId ID of the parent token
     * @param _tokenIds Array of child token IDs to be merged
     * @return newTokenId The ID of the newly minted merged token
     */
    function mintMerge(uint256 parentId, uint256[] memory _tokenIds) external payable returns (uint256 newTokenId);

    /**
     * @notice Transfers share ownership from one NFT to another.
     * @param to Token ID receiving the share
     * @param from Token ID sending the share
     * @param _share Share percentage to transfer
     */
    function sharePass(uint256 to, uint256 from, uint8 _share) external;

    /**
     * @notice Burns an NFT and transfers its share back to the parent NFT.
     * @param tokenId The ID of the token to burn
     */
    function burn (uint256 tokenId) external;
}
```

## Rationale

This EIP builds upon [ERC-721](./eip-721) and [ERC-6150](./eip-6150) to introduce a structured mechanism for share-based hierarchical NFTs, enabling splitting, merging, and fractional ownership directly within the token standard. The proposal reuses [ERC-6150](./eip-6150)&apos;s parent-child architecture to preserve compatibility and reduce implementation complexity. Share management is embedded natively through internal mappings, allowing each token to track its fractional ownership independently without relying on external protocols. Functions like `mintSplit` and `mintMerge` are designed to reflect real-world asset behaviors, clearly distinguishing between asset decomposition and consolidation. The `sharePass` function facilitates redistribution of shares between tokens without requiring minting or burning, offering an efficient internal transfer mechanism. A `burn` function is included to allow share return to the parent on destruction, aligning with ownership. Overall, the interface is purposefully minimal and intuitive, designed for extensibility while maintaining gas efficiency and semantic clarity.

## Backwards Compatibility

The proposed EIP extends [EIP-721](/EIPs/EIPS/eip-721) and [EIP-6150](/EIPs/EIPS/eip-6150), making it backward compatible.

## Reference Implementation

Implementation: [EIP-7891](../../assets/eip-7891/ERC7891.sol).

## Security Considerations

No security considerations were found.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Sat, 15 Feb 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7891</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7891</guid>
      </item>
    
      <item>
        <title>Blob Parameter Only Hardforks</title>
        <category>Informational/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7892-blob-parameter-only-hardforks/23018</comments>
        
        <description>## Abstract

This EIP introduces **Blob Parameter Only (BPO) Hardforks**, a lightweight mechanism for incrementally scaling Ethereum’s blob capacity through targeted hard forks that modify only blob-related parameters: `target`, `max`, and `baseFeeUpdateFraction`. Unlike traditional hard forks, which require extensive coordination and introduce broader protocol changes, BPO forks enable rapid, low-overhead scaling of blob capacity in response to **real-world demand and network conditions**.

## Motivation

Ethereum&apos;s scaling strategy relies on Layer 2 (L2) solutions for transaction execution while using Ethereum as a **data availability (DA) layer**. However, the demand for DA has increased rapidly, and the current approach of only modifying blob parameters in large, infrequent hard forks is **not agile enough** to keep up with L2 growth. 

The key motivations for BPO forks are as follows:

1. **Continuous Scaling**  
   - L2 DA demand is growing rapidly, leading to ongoing saturation of blob capacity.
   - Large, infrequent blob parameter changes create high costs and inefficiencies.
   - BPO forks allow for more frequent, safer capacity increases.

2. **Reduced Operational Overhead**  
   - Performance improvements and further testing will continue to unlock additional capacity.
   - It is desirable to reduce the time between core devs agreeing on a parameter increase and its effective deployment.
   - Full Ethereum hard forks require significant coordination, testing, and upgrade efforts across clients.
   - By isolating blob parameter changes, BPO forks reduce the complexity of upgrades.

3. **Enhanced Stability with New Scaling Technologies**
   - Major scaling upgrades introduce uncertainty in optimal blob limits.
   - Rather than forcing core developers to accept a suboptimal tradeoff between stability and capacity, BPO forks allow developers to safely increase parameters after observing mainnet performance and stability.

4. **Predictable Upgrades for Builders**  
   - Builders and L2s require confidence that Ethereum will continuously scale to support their needs.
   - A structured BPO framework provides predictability, allowing rollups to commit to Ethereum over alternative DA solutions.

## Specification

### Definition

BPO hardforks are defined as protocol upgrades that modify only blob-related parameters through configuration, without requiring any client-side code changes. The new parameters take effect immediately at the specified activation time.

### Blob schedule configuration

The following protocol parameters are now managed by the blob schedule configuration:

- **Blob Target (`target`)**: The expected number of blobs per block.
- **Blob Limit (`max`)**: The maximum number of blobs per block.
- **Blob Base Fee Update Fraction (`baseFeeUpdateFraction`)**: Determines how blob gas pricing adjusts per block.

To ensure consistency, when a regular hardfork changes any of these parameters, it MUST do so by adding an entry to the blob schedule configuration.

### Execution layer configuration

To facilitate these changes on the execution layer, each fork in the `blobSchedule` object defined in [EIP-7840](/EIPs/EIPS/eip-7840) is linked to an activation timestamp via a top-level `&lt;fork_name&gt;Time` field, which holds the Unix timestamp of the activation slot as a JSON number. BPO forks SHOULD be named using the convention `bpo&lt;index&gt;`, where `&lt;index&gt;` starts at `1`. Left padding is unnecessary since these labels are not subject to lexicographic sorting. Activation timestamps are required only for forks that occur **after** Prague.

```json
{
  &quot;blobSchedule&quot;: {
    &quot;cancun&quot;: {
      &quot;target&quot;: 3,
      &quot;max&quot;: 6,
      &quot;baseFeeUpdateFraction&quot;: 3338477
    },
    &quot;prague&quot;: {
      &quot;target&quot;: 6,
      &quot;max&quot;: 9,
      &quot;baseFeeUpdateFraction&quot;: 5007716
    },
    &quot;osaka&quot;: {
      &quot;target&quot;: 6,
      &quot;max&quot;: 9,
      &quot;baseFeeUpdateFraction&quot;: 5007716
    },
    &quot;bpo1&quot;: {
      &quot;target&quot;: 10,
      &quot;max&quot;: 15,
      &quot;baseFeeUpdateFraction&quot;: 8346193
    },
    &quot;bpo2&quot;: {
      &quot;target&quot;: 14,
      &quot;max&quot;: 21,
      &quot;baseFeeUpdateFraction&quot;: 11684671
    }
  },
  &quot;cancunTime&quot;: 0,
  &quot;pragueTime&quot;: 0,
  &quot;osakaTime&quot;: 1747387400,
  &quot;bpo1Time&quot;: 1757387400,
  &quot;bpo2Time&quot;: 1767387784
}
```

Since there is no backporting, the values for `cancunTime` and `pragueTime` are set to 0. It should also be noted that the other parameters and schedules above are purely illustrative. Actual values and schedules are beyond the scope of this specification.

### Blob base fee computations

We modify the functions `get_base_fee_per_blob_gas` and `calc_excess_blob_gas` defined in [EIP-4844](/EIPs/EIPS/eip-4844) to explicitly use the blob schedule.
In line with how updating `BLOB_BASE_FEE_UPDATE_FRACTION` was handled in [EIP-7691](/EIPs/EIPS/eip-7691), the functions use the *current* block&apos;s blob schedule.
Moreover, `TARGET_BLOB_GAS_PER_BLOCK` is removed and replaced with `GAS_PER_BLOB * blob_schedule.target`, as it is now redundant. 

```python
class BlobSchedule:
   target: U64
   max: U64
   base_fee_update_fraction: Uint

 def calc_excess_blob_gas(parent: Header, blob_schedule: BlobSchedule) -&gt; int:
    target_blob_gas = GAS_PER_BLOB * blob_schedule.target
    if parent.excess_blob_gas + parent.blob_gas_used &lt; target_blob_gas :
        return 0
    else:
        return parent.excess_blob_gas + parent.blob_gas_used - target_blob_gas

def get_base_fee_per_blob_gas(header: Header, blob_schedule: BlobSchedule) -&gt; int:
    return fake_exponential(
        MIN_BASE_FEE_PER_BLOB_GAS,
        header.excess_blob_gas,
        blob_schedule.base_fee_update_fraction
    )
```

### Consensus layer configuration

A new `BLOB_SCHEDULE` field is added to consensus layer configuration, containing a sequence of entries representing blob parameter changes **after** `ELECTRA_FORK_EPOCH`. There exists one entry per fork that changes blob parameters, whether it is a regular or a Blob-Parameter-Only fork.

```yaml
BLOB_SCHEDULE:
  - EPOCH: 400000     # A future anonymous BPO fork
    MAX_BLOBS_PER_BLOCK: 15
  - EPOCH: 420000     # A future anonymous BPO fork
    MAX_BLOBS_PER_BLOCK: 21
```

The parameters and schedules above are purely illustrative. Actual values and schedules are beyond the scope of this specification.

**Requirements:**

- Execution and consensus clients **MUST** share consistent BPO fork schedules.
- The slot number in the EL&apos;s `blobSchedule` **MUST** align with the start of the epoch specified in the consensus layer configuration.
- The `max` field in the EL&apos;s `blobSchedule` **MUST** equal the `MAX_BLOBS_PER_BLOCK` value in the consensus layer configuration.

### Modified `compute_fork_digest`

The `compute_fork_digest` helper is updated to account for BPO forks:

```python
@dataclass
class BlobScheduleEntry:
   epoch: Epoch
   max_blobs_per_block: uint64       # Aligning with the type of MAX_BLOBS_PER_BLOCK

def compute_fork_digest(
  current_version: Version,       # Unchanged; refers to the baseline hardfork atop which the blob schedule is applied
  genesis_validators_root: Root,  # Unchanged
  current_epoch: Epoch,           # New
  blob_schedule: Sequence[BlobScheduleEntry]  # New
) -&gt; ForkDigest:
    &quot;&quot;&quot;
    Return the 4-byte fork digest for the ``current_version`` and ``genesis_validators_root``,
    bitmasking blob parameters after ``ELECTRA_FORK_VERSION``.

    This is a digest primarily used for domain separation on the p2p layer.
    4-bytes suffices for practical separation of forks/chains.
    &quot;&quot;&quot;
    base_digest = compute_fork_data_root(current_version, genesis_validators_root)[:4]

    # Find the blob parameters applicable to this epoch.
    sorted_schedule = sorted(blob_schedule, key=lambda e: e.epoch, reverse=True)
    blob_params = None
    for entry in sorted_schedule:
      if current_epoch &gt;= entry.epoch:
        blob_params = entry
        break

    # This check enables us to roll out the BPO mechanism without a concurrent parameter change.
    if blob_params is None:
      return ForkDigest(base_digest)

    # Safely bitmask blob parameters into the digest.
    assert 0 &lt;= blob_params.max_blobs_per_block &lt;= 0xFFFFFFFF
    mask = blob_params.max_blobs_per_block.to_bytes(4, &apos;big&apos;)
    masked_digest = bytes(a ^ b for a, b in zip(base_digest, mask))
    return ForkDigest(masked_digest)
```

### P2P Networking

#### ENR

In the consensus layer, ENRs are extended with an additional entry `nfd`, short for &quot;next fork digest&quot;. This field communicates the digest of the next scheduled fork, regardless of whether it is a regular or BPO fork. This approach is preferred over encoding BPO-specific parameters because it is agnostic to specific use cases and offers greater long-term flexibility.

| Key     | Value                   |
| :-----  | :---------------------- |
| `nfd`   | SSZ Bytes4 `ForkDigest` |

When discovering and interfacing with peers, nodes MUST evaluate `nfd` alongside their existing consideration of the `ENRForkID::next_*` fields under the `eth2` key, to form a more accurate view of the peer&apos;s intended next fork.

#### `Status` req/resp

No changes are needed in this interaction, but it is noted that the response payload must correctly contain the updated `fork_digest`.

#### Gossip topics

No changes are required to topic structure or configuration. However, all topics will automatically rotate at a BPO fork due to changes in their `ForkDigestValue` component.

## Rationale

### Why not just use regular hardforks?

Full hard forks require extensive coordination, testing, and implementation changes beyond parameter adjustments. For example, in Lighthouse, a typical hard fork implementation requires thousands of lines of boilerplate before any protocol changes occur. BPO forks streamline this process by avoiding the need for this boilerplate code.

### Why specify parameters in the node configuration instead of code?

Allowing blob parameters to be configured externally enables rapid experimentation, testing, and adjustments without requiring code changes across client implementations. Testing teams can investigate different parameters with minimal involvement from client implementers.

### Why not create an on-chain voting mechanism for blob parameters?

- Ethereum&apos;s recent gas limit increase to 36M took nearly a year to coordinate
- Blob capacity is a rapidly evolving, moving target that the wider staking community is not currently well equipped to track
- An on-chain mechanism would require much more extensive code changes, testing cycles, and debates about governance structures.
- BPO forks provide a simpler, more predictable approach while leaving room for future on-chain voting mechanisms when blob capacity stabilizes

## Backwards Compatibility

BPO forks introduce no backwards compatibility concerns.

## Security Considerations

No security risks have been identified.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 28 Feb 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7892</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7892</guid>
      </item>
    
      <item>
        <title>DeFi Protocol Solvency Proof Mechanism</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7893-defi-protocol-solvency-proof-mechanism/24566</comments>
        
        <description>## Abstract

A standardized interface that enables DeFi protocols to implement verifiable solvency proofs through smart contracts. This interface works by defining structured data types for assets and liabilities, with oracle-validated price feeds tracking token values in real-time. The technical implementation calculates solvency ratios using configurable risk thresholds (105% minimum solvency ratio), maintains historical metrics for trend analysis, and emits structured events upon threshold breaches. The interface standardizes methods for querying current financial health, retrieving historical data points, and updating protocol positions, all while enforcing proper validation and security controls.

## Motivation

The DeFi ecosystem currently lacks standardization in financial health reporting, leading to:

1. Inconsistent reporting methodologies across protocols
2. Limited transparency in real-time financial status
3. Absence of standardized early warning systems
4. Complex and time-consuming audit processes
5. Difficulty in assessing cross-protocol risks

This proposal directly addresses these challenges through a comprehensive interface that standardizes solvency reporting and monitoring:

- **Standardized Methodology**: By providing a common interface with well-defined asset/liability structures and mathematical models, this EIP eliminates reporting inconsistencies that currently prevent clear comparisons between protocols.

- **Real-time Transparency**: The proposed event system and query functions enable continuous monitoring of protocol health, rather than relying on periodic manual reporting that can miss critical changes in financial status.

- **Automated Risk Alerts**: The threshold-based alert system provides early warnings of deteriorating conditions through standardized `RiskAlert` events, enabling faster response to potential insolvencies than current ad-hoc monitoring approaches.

- **Efficient Audit Trail**: The historical metrics tracking creates an immutable record of protocol health over time, significantly reducing audit complexity compared to current solutions that require reconstructing historical positions.

- **Cross-Protocol Risk Assessment**: A common interface enables aggregation of risk data across multiple protocols, allowing systemic risk monitoring that&apos;s impossible with today&apos;s fragmented reporting systems.

Alternative approaches considered include:

1. **Off-chain Reporting**: While simpler to implement, this lacks the verifiability, real-time nature, and trustless properties of an on-chain solution.

2. **Protocol-Specific Standards**: These would lack the interoperability benefits of a common standard and would perpetuate fragmentation.

3. **Complex Risk Models**: More sophisticated models were evaluated but rejected in favor of this proposal&apos;s balance between comprehensiveness and implementability.

This EIP represents the optimal approach by providing a flexible yet standardized framework that can be implemented across diverse protocol types while maintaining reasonable gas efficiency and usability.

The `ISolvencyProof` interface provides a standardized, on-chain mechanism for DeFi protocols to report, verify, and monitor their solvency status. This interface is designed to be both comprehensive and flexible, supporting a wide range of protocol architectures and risk management strategies.

## Specification

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

![main](/EIPs/assets/eip-7893/images/diagrams/main.svg)

### Core Interface Requirements

Compliant implementations MUST implement the `ISolvencyProof` interface.

Compliant implementations MUST provide the following functionality:

1. **Asset and Liability Tracking**: Implementations MUST store and maintain current protocol assets and liabilities with token addresses, amounts, and ETH-denominated values in contract state variables. This data MUST be updated through the `updateAssets` and `updateLiabilities` functions called by authorized oracles.

2. **Timestamp Recording**: Implementations MUST record the timestamp of each asset and liability update.

3. **Solvency Calculation**: Implementations MUST calculate the solvency ratio as `(Total Assets / Total Liabilities) × 10000`.

4. **Historical Data**: Implementations MUST maintain historical records of solvency metrics for querying within specified time ranges. Implementations MAY expire old data after a reasonable retention period (e.g., 1 year) but MUST clearly document their retention policy and available time ranges in their implementation documentation.

5. **Event Emission**: Implementations MUST emit `SolvencyMetricsUpdated` events when financial metrics are updated, and SHOULD emit `RiskAlert` events when risk thresholds are breached.

6. **Array Validation**: Implementations MUST ensure that all arrays in `ProtocolAssets` and `ProtocolLiabilities` structures are of equal length.

7. **Value Denomination**: Implementations MUST express all values in ETH with 18 decimals for consistency.

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.20;

/**
 * @title ISolvencyProof
 * @author Sean Luis (@SeanLuis) &lt;seanluis47@gmail.com&gt;
 * @notice Standard Interface for DeFi Protocol Solvency (EIP-DRAFT)
 * @dev Interface for the DeFi Protocol Solvency Proof Standard
 * @custom:security-contact seanluis47@gmail.com
 * @custom:version 1.0.0
 */
interface ISolvencyProof {
    /**
     * @dev Protocol assets structure
     * @notice Represents the current state of protocol assets
     * @custom:validation All arrays must be equal length
     * @custom:validation Values must be in ETH with 18 decimals
     */
    struct ProtocolAssets {
        address[] tokens;    // Addresses of tracked tokens
        uint256[] amounts;   // Amount of each token (in token decimals)
        uint256[] values;    // Value in ETH (18 decimals) of each token amount
        uint256 timestamp;   // Last update timestamp (Unix timestamp in seconds)
    }

    /**
     * @dev Protocol liabilities structure
     * @notice Represents the current state of protocol liabilities
     * @custom:validation All arrays must be equal length
     * @custom:validation Values must be in ETH with 18 decimals
     */
    struct ProtocolLiabilities {
        address[] tokens;    // Addresses of liability tokens
        uint256[] amounts;   // Amount of each liability (in token decimals)
        uint256[] values;    // Value in ETH (18 decimals) of each liability
        uint256 timestamp;   // Last update timestamp (Unix timestamp in seconds)
    }

    /**
     * @dev Emitted on metrics update
     * @notice Real-time financial health update
     * @param totalAssets Sum of asset values in ETH
     * @param totalLiabilities Sum of liability values in ETH
     * @param healthFactor Calculated as (totalAssets/totalLiabilities) × 10000
     * @param timestamp Update timestamp
     */
    event SolvencyMetricsUpdated(
        uint256 totalAssets,
        uint256 totalLiabilities,
        uint256 healthFactor,
        uint256 timestamp
    );

    /**
     * @dev Emitted when risk thresholds are breached
     * @notice Alerts stakeholders of potential solvency risks
     * 
     * @param riskLevel Risk level indicating severity of the breach (CRITICAL, HIGH_RISK, WARNING)
     * @param currentValue Current value that triggered the alert
     * @param threshold Risk threshold that was breached
     * @param timestamp Alert timestamp
     */
    event RiskAlert(
        string riskLevel,
        uint256 currentValue,
        uint256 threshold,
        uint256 timestamp
    );

    /**
     * @notice Get protocol&apos;s current assets
     * @return Full asset state including tokens, amounts and values
     */
    function getProtocolAssets() external view returns (ProtocolAssets memory);

    /**
     * @notice Get protocol&apos;s current liabilities
     * @return Full liability state including tokens, amounts and values
     */
    function getProtocolLiabilities() external view returns (ProtocolLiabilities memory);

    /**
     * @notice Calculate current solvency ratio
     * @return SR = (Total Assets / Total Liabilities) × 10000
     */
    function getSolvencyRatio() external view returns (uint256);

    /**
     * @notice Check protocol solvency status
     * @return isSolvent True if ratio &gt;= minimum required
     * @return healthFactor Current solvency ratio
     */
    function verifySolvency() external view returns (bool isSolvent, uint256 healthFactor);

    /**
     * @notice Get historical solvency metrics
     * @param startTime Start of time range (Unix timestamp in seconds)
     * @param endTime End of time range (Unix timestamp in seconds)
     * @return timestamps Array of historical update timestamps (Unix timestamp in seconds)
     * @return ratios Array of historical solvency ratios (scaled by 10000)
     * @return assets Array of historical asset states
     * @return liabilities Array of historical liability states
     * @custom:gas This function may consume significant gas for large time ranges
     */
    function getSolvencyHistory(uint256 startTime, uint256 endTime) 
        external 
        view 
        returns (
            uint256[] memory timestamps,
            uint256[] memory ratios,
            ProtocolAssets[] memory assets,
            ProtocolLiabilities[] memory liabilities
        );

    /**
     * @notice Update protocol assets
     * @dev Only callable by authorized oracle
     */
    function updateAssets(
        address[] calldata tokens,
        uint256[] calldata amounts,
        uint256[] calldata values
    ) external;

    /**
     * @notice Update protocol liabilities
     * @dev Only callable by authorized oracle
     */
    function updateLiabilities(
        address[] calldata tokens,
        uint256[] calldata amounts,
        uint256[] calldata values
    ) external;
}
```

### Oracle Authorization Requirements

Implementations MUST restrict calls to `updateAssets` and `updateLiabilities` to authorized addresses only. Implementations MUST revert these function calls when `msg.sender` is not an authorized oracle.

Implementations MAY provide oracle management functions. If provided, implementations SHOULD emit events when oracle authorization changes.

Example oracle management pattern (OPTIONAL):

```solidity
// Optional oracle management pattern
event OracleUpdated(address indexed oracle, bool authorized);
function setOracle(address oracle, bool authorized) external;
```

The core standard focuses on solvency verification requirements. Oracle management implementation details are left to individual protocol needs.

### Update Function Requirements

Implementations MUST validate input parameters for `updateAssets` and `updateLiabilities` functions:

1. Implementations MUST revert if the `tokens`, `amounts`, and `values` arrays are not of equal length.
2. Implementations MUST update the timestamp field to the current block timestamp (`block.timestamp`) when processing updates.
3. Implementations MUST emit a `SolvencyMetricsUpdated` event after successfully updating assets or liabilities.

### Query Function Requirements

Implementations MUST provide the following query capabilities:

1. `getProtocolAssets()` MUST return the current state of protocol assets including all token addresses, amounts, values, and the timestamp of the last update.

2. `getProtocolLiabilities()` MUST return the current state of protocol liabilities including all token addresses, amounts, values, and the timestamp of the last update.

3. `getSolvencyRatio()` MUST calculate and return the solvency ratio as `(totalAssets * 10000) / totalLiabilities`. If `totalLiabilities` is zero, implementations SHOULD return a value indicating maximum solvency or revert with an appropriate error.

4. `verifySolvency()` MUST return both a boolean indicating solvency status and the current health factor (solvency ratio).

5. `getSolvencyHistory(startTime, endTime)` MUST return historical data for all recorded snapshots where the timestamp falls within the specified range (inclusive).

### Interface Detection Support

Compliant implementations MUST implement the [ERC-165](/EIPs/EIPS/eip-165) `supportsInterface` function and MUST return `true` for the `ISolvencyProof` interface ID.

## Rationale

The standard&apos;s design prioritizes:

1. Reliability through robust calculations
2. Efficiency via optimized data structures 
3. Flexibility through modular design
4. Transparency via standardized metrics

#### Asset and Liability Management
Authorized oracles update the protocol&apos;s asset and liability data through the `updateAssets` and `updateLiabilities` functions, which accept parallel arrays of token addresses, amounts, and ETH-denominated values. The interface enforces data consistency by requiring all input arrays to be of equal length and all values to be denominated in ETH with 18 decimal precision. Each update automatically timestamps the data using `block.timestamp`, ensuring chronological ordering of financial state changes and enabling accurate historical analysis.

#### Solvency Calculation and Verification
The `getSolvencyRatio` function computes the current solvency ratio, defined as the total value of assets divided by the total value of liabilities, scaled by a factor of 10,000 for precision. The `verifySolvency` function checks whether the protocol meets a minimum required solvency ratio (commonly 105%), returning both a boolean status and the current health factor. This allows both on-chain and off-chain systems to quickly assess the protocol&apos;s financial health and respond accordingly.

#### Historical Data and Trend Analysis
The `getSolvencyHistory` function enables retrieval of historical solvency metrics, including timestamps, ratios, and the corresponding asset and liability states over a specified time range. This historical data is crucial for reconstructing past events, analyzing risk trends, and providing transparency to stakeholders. This supports audits, regulatory requirements, and trend analysis needs.

#### Event Emission and Risk Alerts
Whenever the protocol&apos;s financial metrics are updated, the `SolvencyMetricsUpdated` event is emitted, providing real-time data for off-chain monitoring and analytics. When risk thresholds are breached (for example, if the solvency ratio falls below a critical level), the `RiskAlert` event is triggered, signaling the severity and nature of the risk. These events enable automated monitoring systems, auditors, and users to receive timely notifications and take appropriate action.

#### Oracle Integration and Security
The interface is designed to be oracle-agnostic, allowing protocols to integrate with a variety of price feed solutions (e.g., Chainlink, API3, custom oracles). The requirement that only authorized oracles can update asset and liability data ensures that updates are secure and resistant to manipulation. The optional `setOracle` and `OracleUpdated` event pattern is recommended for managing oracle permissions and maintaining robust security controls.

#### Intended Usage and Integration
Protocols implementing this interface integrate with trusted oracles for price feeds and position updates, maintain up-to-date records of their financial positions, emit standardized events for off-chain monitoring and risk management, and provide transparent, verifiable, and standardized information about their solvency status to all stakeholders. External consumers (such as auditors, users, or other smart contracts) can query the protocol&apos;s current and historical solvency status using the provided view functions, and can listen for events to receive timely notifications of significant changes or risks. This design ensures that all stakeholders have access to reliable, real-time information about a protocol&apos;s financial health, enabling more robust risk management and greater trust in the DeFi ecosystem.

### Data Structure Design Rationale

The interface defines two primary data structures (`ProtocolAssets` and `ProtocolLiabilities`) with specific attributes:

1. **Array-based token tracking** was selected over mapping-based approaches for:
   - More efficient state retrieval for monitoring systems
   - Better compatibility with historical tracking requirements
   - Simplified batch updates in volatile market conditions

2. **Timestamp embedding** within structures rather than separate mappings provides:
   - Atomic updates with data consistency guarantees
   - Protection against partial-update scenarios during price volatility
   - Single-transaction verification of data freshness

3. **Combined value and amount tracking** was implemented for:
   - Enhanced resilience during high market volatility
   - Ability to detect oracle manipulation by comparing historical value/amount ratios
   - Clear audit trails for post-mortem analysis

### Test-Driven Design Decisions

Our implementation testing significantly shaped the final design:

1. **Market Crash Simulation Tests**
   - Tests simulate extreme scenarios (80% ETH price drop, 70% BTC price drop)
   - Validates the system correctly identifies insolvency when ratios fall below critical thresholds
   - Confirms proper functionality of emergency protocols during rapid market movements

2. **Volatility Testing**
   - Test suite subjects implementation to sinusoidal price movements
   - Validates consistent health factor calculation across 5 distinct price points
   - Confirms historical metrics are properly recorded with sequential timestamps
   - Verifies that price volatility is accurately reflected in solvency ratios

3. **Oracle Integration**
   - Tests confirm proper authorization controls for price updates
   - Validates calculation consistency across different token types
   - Demonstrates resilience against unexpected price movements

### Threshold Selection Methodology

The recommended threshold values (105%, 110%, 120%) were selected based on:

1. **Market Crash Testing**
   - 105% represents the critical threshold where recovery becomes unlikely
   - Testing confirms this threshold successfully identifies insolvency scenarios
   - System correctly triggers warnings at appropriate levels

2. **Complex Portfolio Analysis**
   - Tests with diverse portfolios (ETH, BTC, USDC, LP tokens, etc.)
   - Complex liability structures (stablecoins + volatile assets)
   - Thresholds provide appropriate buffer against normal market fluctuations

3. **Gas Optimization vs. Precision**
   - The selected ratio calculation method balances computational efficiency with accuracy
   - Implementation uses fixed-point math for consistent results
   - Storage optimizations maintain historical data while minimizing costs

### Implementation Insights

Key insights from comprehensive implementation and testing:

1. **Efficient Asset Tracking**
   - The parallel arrays approach for token data minimizes storage costs
   - Implementation maintains constant-time lookups for critical operations
   - Bounded array sizes prevent out-of-gas scenarios

2. **Oracle Integration Patterns**
   - Permissioned oracle design prevents manipulation
   - Clean separation between price data and protocol logic
   - Flexible design supports various oracle implementations

3. **Risk Management System**
   - Multi-tier alert system provides graduated responses to deteriorating conditions
   - Historical metrics enable trend analysis across market cycles
   - Verification functions support both on-chain and off-chain monitoring systems

These insights are derived from comprehensive testing covering market crashes, volatility scenarios, and complex asset portfolios.

### Mathematical Model

The solvency verification system is based on comprehensive mathematical models:

#### 1. Core Solvency Calculations

$SR = (TA / TL) × 100$

Where:

- $TA = \sum(A_i × P_i)$  // Total Assets
- $TL = \sum(L_i × P_i)$  // Total Liabilities
- $A_i$ = Amount of asset i
- $P_i$ = Price of asset i
- $L_i$ = Liability i

#### 2. Risk-Adjusted Health Factor

$HF = \frac{\sum(A_i × P_i × W_i)}{\sum(L_i × P_i × R_i)}$

Where:

- $W_i$ = Risk weight of asset i $(0 &lt; W_i \leq 1)$
- $R_i$ = Risk factor for liability i $(R_i \geq 1)$

#### 3. Risk Metrics

##### Value at Risk (VaR)

$VaR(\alpha) = \mu - (\sigma × z(\alpha))$

Where:

- $\mu$ = Expected return
- $\sigma$ = Standard deviation
- $z(\alpha)$ = z-value for confidence level $\alpha$

##### Liquidity Coverage Ratio (LCR)

$LCR = \frac{HQLA}{TNCO} × 100$

Where:

- HQLA = High Quality Liquid Assets
- TNCO = Total Net Cash Outflows (30 days)

#### 4. System Health Index

$SI = \frac{SR × w_1 + LCR × w_2 + (1/\sigma) × w_3}{w_1 + w_2 + w_3}$

Where:

- $w_1,w_2,w_3$ = Weighting factors
- $\sigma$ = System volatility

#### 5. Default Probability

$PD = N(-DD)$
$DD = \frac{ln(TA/TL) + (\mu - \sigma^2/2)T}{\sigma\sqrt{T}}$

Where:

- DD = Distance to Default
- T = Time horizon
- N() = Standard normal distribution

### Risk Thresholds

The following thresholds have been validated through extensive testing:

| Risk Level | Ratio Range | Action Required | Validation Status |
|------------|-------------|-----------------|-------------------|
| CRITICAL   | &lt; 105%      | Emergency Stop  | ✅ Validated |
| HIGH RISK  | 105% - 110% | Risk Alert     | ✅ Validated |
| WARNING    | 110% - 120% | Monitor        | ✅ Validated |
| HEALTHY    | ≥ 120%      | Normal         | ✅ Validated |

Testing has confirmed that:

1. The system correctly handles 50% market drops
2. Ratios are calculated accurately in all scenarios
3. State updates maintain consistency
4. Ratio limits are effective for early detection

![risk-thresholds](/EIPs/assets/eip-7893/images/diagrams/risk-thresholds.svg)

### Risk Assessment Framework

The standard implements a multi-tiered risk assessment system:

1. Primary Metrics:
   - Base Solvency Ratio (SR)
   - Risk-Adjusted Health Factor (HF)
   - Liquidity Coverage Ratio (LCR)

2. Threshold Levels:

![threshold-levels](/EIPs/assets/eip-7893/images/diagrams/threshold-levels.svg)

### Oracle Integration (Optional)

This standard intentionally leaves oracle implementation flexible. Protocols MAY implement price feeds in various ways:

1. Direct Integration
   - Using existing oracle networks (Chainlink, API3, etc.)
   - Custom price feed implementations
   - Internal price calculations

2. Aggregation Strategies
   - Multiple oracle sources
   - TWAP implementations
   - Medianized price feeds

![oracle-integration](/EIPs/assets/eip-7893/images/diagrams/oracle-integration.svg)

### Implementation Requirements

1. Asset Management:
   - Real-time asset tracking
   - Price feed integration
   - Historical data maintenance

2. Liability Tracking:
   - Debt obligation monitoring
   - Collateral requirement calculation
   - Risk factor assessment

3. Reporting System:
   - Event emission for significant changes
   - Threshold breach notifications
   - Historical data access

### Implementation Considerations

### Implementation Notes

Based on conducted tests, it is recommended:

1. Liability Management:
   - Maintain constant liabilities during price updates
   - Validate that liabilities are never 0 to avoid division by zero
   - Update liabilities only when actual positions change

2. Ratio Calculation:

   ```solidity
   function calculateRatio(uint256 assets, uint256 liabilities) pure returns (uint256) {
       if (liabilities == 0) {
           return assets &gt; 0 ? RATIO_DECIMALS * 2 : RATIO_DECIMALS;
       }
       return (assets * RATIO_DECIMALS) / liabilities;
   }
   ```

3. State Validation:
   - Verify values before updating
   - Maintain accurate history
   - Emit events for significant changes

4. Gas Considerations:
   - Optimize history storage
   - Batch updates for multiple tokens
   - Limit array sizes in updates

## Backwards Compatibility

This EIP is compatible with existing DeFi protocols and requires no changes to existing token standards.

## Reference Implementation

The reference implementation provides a comprehensive example of the standard in action:

### Core Implementation Requirements

Implementations of the `ISolvencyProof` interface should provide robust solvency monitoring with:

- **Advanced state management** with atomic updates and timestamp tracking
- **Multi-layered security** including access control, rate limiting, and circuit breakers
- **Historical data management** with bounded storage and configurable retention
- **Oracle integration** with consensus validation and staleness detection
- **Emergency response systems** with automatic pausing and guardian controls
- **Comprehensive event emission** for real-time monitoring and risk alerts

### Recommended Implementation Patterns

#### State Management with Security Constants
```solidity
// Security constants for production deployment
uint256 private constant RATIO_DECIMALS = 10000;
uint256 private constant MIN_SOLVENCY_RATIO = 10500;
uint256 private constant CRITICAL_RATIO = 10200;
uint256 private constant WARNING_RATIO = 11000;

// Enhanced security constants
uint256 private constant MAX_PRICE_DEVIATION = 500;    // 5%
uint256 private constant MAX_TOKENS_PER_UPDATE = 50;   // DoS protection
uint256 private constant STALENESS_THRESHOLD = 3600;   // 1 hour
uint256 private constant CIRCUIT_BREAKER_THRESHOLD = 2000; // 20%
uint256 private constant UPDATE_COOLDOWN = 5;          // 5 blocks
uint256 private constant MAX_HISTORY_ENTRIES = 8760;   // ~1 year
uint256 private constant MIN_ENTRY_INTERVAL = 3600;     // 1 hour

// Role-based access control
bytes32 public constant ORACLE_ROLE = keccak256(&quot;ORACLE_ROLE&quot;);
bytes32 public constant EMERGENCY_ROLE = keccak256(&quot;EMERGENCY_ROLE&quot;);
bytes32 public constant ADMIN_ROLE = keccak256(&quot;ADMIN_ROLE&quot;);

// Enhanced state variables
ProtocolAssets private currentAssets;
ProtocolLiabilities private currentLiabilities;

// Multi-oracle price tracking
mapping(address =&gt; mapping(address =&gt; uint256)) public oraclePrices;
mapping(address =&gt; uint256) public oracleLastUpdate;
mapping(address =&gt; uint256) public lastUpdateBlock;

// Emergency controls
bool public emergencyPaused;
uint256 public pauseEndTime;
address public emergencyGuardian;

// Historical data with metadata
struct HistoricalMetric {
    uint256 timestamp;
    uint256 solvencyRatio;
    ProtocolAssets assets;
    ProtocolLiabilities liabilities;
    address updatedBy;
}

HistoricalMetric[] private metricsHistory;
uint256 private lastHistoricalEntry;
```

#### Advanced Security Features

##### Access Control System
```solidity
// Multi-role access control with backward compatibility
modifier onlyOracle() {
    require(
        assetOracles[msg.sender] || hasRole(ORACLE_ROLE, msg.sender),
        &quot;Not authorized oracle&quot;
    );
    require(!emergencyPaused || block.timestamp &gt; pauseEndTime,
        &quot;Emergency paused&quot;);
    _;
}

// Rate limiting to prevent spam
modifier rateLimited() {
    require(
        block.number &gt;= lastUpdateBlock[msg.sender] + UPDATE_COOLDOWN,
        &quot;Update too frequent&quot;
    );
    lastUpdateBlock[msg.sender] = block.number;
    emit RateLimitTriggered(msg.sender, block.number);
    _;
}
```

##### Circuit Breaker Implementation
```solidity
function _checkCircuitBreaker(uint256 previousTotal, uint256 newTotal) internal {
    if (previousTotal &gt; 0) {
        uint256 assetChange = newTotal &gt; previousTotal
            ? ((newTotal - previousTotal) * 10000) / previousTotal
            : ((previousTotal - newTotal) * 10000) / previousTotal;

        if (assetChange &gt; CIRCUIT_BREAKER_THRESHOLD) {
            emergencyPaused = true;
            pauseEndTime = block.timestamp + 3600; // 1 hour pause
            emit CircuitBreakerTriggered(&quot;Large asset change&quot;,
                assetChange, CIRCUIT_BREAKER_THRESHOLD);
            emit EmergencyPaused(address(this), pauseEndTime);
        }
    }
}
```

##### Multi-Oracle Consensus Validation
```solidity
function _validatePriceConsensus(address token, uint256 proposedPrice)
    internal returns (bool) {
    address[] memory activeOracles = _getActiveOracles();
    if (activeOracles.length &lt; 3) return true;

    // Collect and validate prices from multiple oracles
    uint256[] memory prices = new uint256[](activeOracles.length);
    uint256 validPrices = 0;

    for (uint256 i = 0; i &lt; activeOracles.length; i++) {
        if (oraclePrices[activeOracles[i]][token] &gt; 0) {
            prices[validPrices] = oraclePrices[activeOracles[i]][token];
            validPrices++;
        }
    }

    if (validPrices &lt; 2) return true;

    // Calculate median and check deviation
    uint256 median = _calculateMedian(prices, validPrices);
    uint256 deviation = proposedPrice &gt; median
        ? ((proposedPrice - median) * 10000) / median
        : ((median - proposedPrice) * 10000) / median;

    if (deviation &gt; MAX_PRICE_DEVIATION) {
        emit PriceDeviationAlert(token, deviation, activeOracles);
        return false;
    }

    return true;
}
```

#### Historical Data Management
```solidity
function getSolvencyHistory(uint256 startTime, uint256 endTime)
    external view returns (uint256[] memory, uint256[] memory,
        ProtocolAssets[] memory, ProtocolLiabilities[] memory) {

    // Two-pass approach for gas optimization
    uint256 count = 0;
    for (uint256 i = 0; i &lt; metricsHistory.length; i++) {
        if (metricsHistory[i].timestamp &gt;= startTime &amp;&amp;
            metricsHistory[i].timestamp &lt;= endTime) {
            count++;
            if (count &gt;= 100) break; // Gas limit protection
        }
    }

    // Allocate exact size arrays
    uint256[] memory timestamps = new uint256[](count);
    uint256[] memory ratios = new uint256[](count);
    ProtocolAssets[] memory assets = new ProtocolAssets[](count);
    ProtocolLiabilities[] memory liabilities = new ProtocolLiabilities[](count);

    // Populate arrays
    uint256 index = 0;
    for (uint256 i = 0; i &lt; metricsHistory.length &amp;&amp; index &lt; count; i++) {
        if (metricsHistory[i].timestamp &gt;= startTime &amp;&amp;
            metricsHistory[i].timestamp &lt;= endTime) {
            timestamps[index] = metricsHistory[i].timestamp;
            ratios[index] = metricsHistory[i].solvencyRatio;
            assets[index] = metricsHistory[i].assets;
            liabilities[index] = metricsHistory[i].liabilities;
            index++;
        }
    }

    return (timestamps, ratios, assets, liabilities);
}

function getHistoricalDataInfo() external view returns (
    uint256 totalEntries, uint256 maxEntries,
    uint256 oldestTimestamp, uint256 newestTimestamp,
    uint256 minInterval) {

    totalEntries = metricsHistory.length;
    maxEntries = MAX_HISTORY_ENTRIES;
    minInterval = MIN_ENTRY_INTERVAL;

    if (totalEntries &gt; 0) {
        oldestTimestamp = metricsHistory[0].timestamp;
        newestTimestamp = metricsHistory[totalEntries - 1].timestamp;
    }

    return (totalEntries, maxEntries, oldestTimestamp,
        newestTimestamp, minInterval);
}
```

#### Emergency Response System
```solidity
function emergencyPause() external onlyEmergencyGuardian {
    emergencyPaused = true;
    pauseEndTime = block.timestamp + 4 * 3600; // 4 hour default
    emit EmergencyPaused(msg.sender, pauseEndTime);
}

function emergencyUnpause() external onlyEmergencyGuardian {
    emergencyPaused = false;
    pauseEndTime = 0;
    emit EmergencyUnpaused(msg.sender);
}

function getEmergencyStatus() external view returns (
    bool isPaused, uint256 endTime, address guardian) {
    return (emergencyPaused, pauseEndTime, emergencyGuardian);
}
```

### Gas Optimization Strategies

#### Bounded Operations
- **Maximum array sizes** (50 tokens per update) to prevent out-of-gas
- **Historical data pagination** (max 100 entries per query)
- **Efficient storage patterns** with bounded retention periods

#### Storage Optimization
- **Circular buffer approach** for historical data rotation
- **Rate-limited historical entries** (minimum 1-hour intervals)
- **Compact data structures** minimizing storage overhead

### Testing and Validation Requirements

#### Comprehensive Test Coverage
- **Mathematical precision** validation for ratio calculations
- **Security feature testing** (access control, rate limiting, circuit breakers)
- **Oracle reliability testing** under various market conditions
- **Gas consumption analysis** with stress testing
- **Emergency scenario simulation** with pause/unpause cycles

#### Production Deployment Requirements

Production implementations should ensure:

- Multi-oracle consensus mechanism implemented and tested
- Circuit breaker triggers validated with historical data
- Rate limiting prevents spam without blocking legitimate updates
- Emergency pause/unpause mechanisms tested with time delays
- Gas optimization prevents DoS while maintaining functionality
- Access controls follow principle of least privilege
- Historical data storage bounded and efficient
- Security parameters documented and transparent

### Integration Patterns

#### Oracle Integration
- **Primary oracle feeds** (Chainlink, API3) with fallback mechanisms
- **TWAP integration** for manipulation resistance
- **Staleness detection** with automatic fallback to secondary oracles

#### Liquidation System (Optional Enhancement)
```solidity
struct LiquidationConfig {
    uint256 maxLiquidationRatio;  // Max % liquidatable
    uint256 liquidationBonus;     // Liquidator bonus
    uint256 minHealthFactor;      // Minimum health factor
    uint256 maxSlippage;          // Slippage tolerance
    bool isActive;
}

function safeLiquidation(address protocol, address user,
    uint256 debtAmount, uint256 expectedCollateral, uint256 maxSlippage)
    external returns (uint256 actualCollateral, uint256 liquidationBonus) {
    // Comprehensive liquidation logic with health factor validation
    // Slippage protection and bonus calculation
    // Position updates and event emission
}
```

This implementation demonstrates production-ready patterns for DeFi protocol solvency monitoring with enterprise-grade security, gas optimization, and comprehensive risk management.

## Security Considerations

When implementing solvency monitoring for DeFi protocols, security isn&apos;t optional—it&apos;s essential. We&apos;ve learned hard lessons from protocol failures, oracle manipulation attacks, and market crashes. This section covers the practical security measures you need to implement, drawn from what actually works in production systems like Aave, Compound, and MakerDAO.

### Oracle Security - Implementation Requirements

#### Price Feed Validation

- **Minimum 3 independent oracle sources** with median aggregation to prevent single points of failure
- **Deviation threshold checks:** Reject price updates exceeding 5% difference between sources  
- **Staleness validation:** ETH/USD and major crypto pairs should use 1-hour maximum staleness (3600 seconds)
- **Circuit breaker integration:** Pause solvency updates when price movements exceed 20% in single block

Implementation patterns for price validation should include median calculation, deviation checks, and appropriate error handling.

**Real-world reference:** Chainlink&apos;s Feed Registry and Aave&apos;s AaveOracle provide solid patterns for oracle integration.

#### TWAP Integration
- **30-minute minimum windows** for manipulation resistance (based on Uniswap V3 security analysis)
- **Minimum $1-5M liquidity** in reference pools for oracle reliability
- **Combined validation:** Primary Chainlink feeds with Uniswap V3 TWAP backup verification

#### Oracle Failure Handling

Implementations should include fallback mechanisms for oracle failures, including timestamp validation, secondary oracle integration, and graceful degradation patterns.

### Access Control - Specific Implementation

#### Role-Based Permissions

Implementations should use established access control patterns such as OpenZeppelin&apos;s AccessControl for role management, including oracle roles, emergency roles, and administrative functions.

#### Rate Limiting Implementation
- **Maximum 1 update per 5 blocks** per authorized oracle to prevent spam attacks
- **Daily update limits:** 288 updates per day (every 5 minutes) for high-frequency protocols
- **Emergency cooldowns:** 1-hour minimum between emergency pause activations

Rate limiting should be implemented using block-based cooldowns and per-oracle tracking.

#### Multi-signature Requirements
- 3/5 multisig for parameter changes (threshold updates, oracle management)
- 4/7 multisig for critical upgrades (we borrowed this from Compound V3)
- Separate emergency pause authority from main governance (Aave&apos;s Guardian model works well here)

### Risk Management - Concrete Parameters

#### Threshold Calibration with Production Values

| Risk Level | Solvency Ratio | Liquidation Bonus | Close Factor | Implementation |
|------------|----------------|-------------------|--------------|----------------|
| CRITICAL   | &lt; 105%         | 10-15%           | 100%         | Emergency pause all operations |
| HIGH_RISK  | 105% - 110%    | 7-10%            | 75%          | Restrict new borrowing |
| WARNING    | 110% - 120%    | 5-7%             | 50%          | Enhanced monitoring |
| HEALTHY    | ≥ 120%         | 5%               | 50%          | Normal operations |

#### Alert System Implementation

Risk threshold monitoring should include graduated alerts (CRITICAL, HIGH_RISK, WARNING) with appropriate automated responses.

#### Historical Data Protection
- **Immutable storage patterns** to prevent historical data manipulation
- **Checksum validation** for stored historical ratios using merkle trees
- **Maximum storage limits:** 8760 hourly records (1 year) to prevent unbounded growth

### Emergency Response Mechanisms

#### Circuit Breaker Integration

Circuit breaker mechanisms should monitor for dramatic value changes and automatically pause operations when thresholds are exceeded. Implementation should include emergency pause states, time-based recovery, and appropriate event emission.

- **Automatic pause triggers:** Oracle deviation &gt;20%, liquidity drop &gt;50% in 1 hour
- **Initial pause duration:** 1-4 hours with exponential backoff for repeated triggers
- **Gradual resume:** 25% → 50% → 75% → 100% capacity with 30-minute monitoring between phases

#### Time Delays for Critical Operations
- **Protocol upgrades:** 7 days (604,800 seconds) following MakerDAO governance pattern
- **Threshold parameter changes:** 48 hours (172,800 seconds)
- **Oracle authority changes:** 24 hours (86,400 seconds) with immediate emergency override

### Gas Optimization Security

##### Bounded Operations

Implementations should enforce reasonable limits on array sizes, historical data storage, and operation complexity to prevent denial-of-service attacks and ensure predictable gas consumption.

##### DoS Attack Prevention
- **Maximum 50 tokens per update** to prevent out-of-gas scenarios
- **Pagination for historical queries** with max 100 records per call
- **Input validation:** Reject empty arrays, validate array length consistency
- **Reentrancy protection:** Use OpenZeppelin&apos;s ReentrancyGuard for all external calls

### Integration Security Patterns

#### Liquidation Protection Pattern

&gt; **Note:** This is a recommended integration pattern for protocols implementing this ERC. The core solvency monitoring contract focuses on solvency monitoring; liquidation logic should be implemented in the consuming protocol.

Liquidation integrations should include health factor validation, partial liquidation limits, and slippage protection mechanisms.

- **Health factor buffers:** 110% warning threshold before 105% liquidation
- **Partial liquidation limits:** Maximum 50% of debt in single transaction
- **Slippage protection:** 3% maximum slippage for automated liquidations

### Validation and Testing Requirements

#### Stress Testing Scenarios
- **50% market crash simulation** with proper threshold triggers
- **Oracle manipulation attempts** with 20%+ false price movements
- **High-frequency update scenarios** testing rate limiting effectiveness
- **Network congestion testing** with increased gas prices

#### Audit Requirements
- **Formal verification** of solvency calculation logic
- **Oracle integration testing** across multiple price feed providers
- **Emergency scenario testing** including pause/unpause cycles
- **Gas consumption analysis** for all operations under stress conditions

#### Production Deployment Requirements

Production implementations should ensure:

- Multi-oracle consensus mechanism implemented and tested
- Circuit breaker triggers validated with historical data
- Rate limiting prevents spam without blocking legitimate updates
- Emergency pause/unpause mechanisms tested with time delays
- Gas optimization prevents DoS while maintaining functionality
- Access controls follow principle of least privilege
- Historical data storage bounded and efficient

These security considerations are based on production implementations from Aave V3, Compound V3, MakerDAO, and Synthetix protocols, incorporating lessons learned from actual security incidents and governance responses in the DeFi ecosystem. The specific parameters and thresholds have been validated through extensive testing scenarios including market crashes, oracle manipulation attempts, and high-frequency trading conditions.

### Production-Validated Security Parameters

All security parameters have been validated against real-world DeFi protocols:

| Parameter | Value | Reference | Validation Status |
|-----------|-------|---------------------|-------------------|
| **Critical Ratio** | 102% | Aave V3 WBTC liquidation threshold | ✅ Production-tested |
| **Min Solvency Ratio** | 105% | Compound V3 close factor trigger | ✅ Production-tested |
| **Warning Ratio** | 110% | MakerDAO emergency shutdown threshold | ✅ Production-tested |
| **Price Deviation** | 5% | Chainlink deviation standard | ✅ Industry standard |
| **Staleness Threshold** | 1 hour | Chainlink ETH/USD heartbeat | ✅ Industry standard |
| **Circuit Breaker** | 20% | NYSE/circuit breaker standard | ✅ Regulatory compliant |
| **Rate Limiting** | 5 blocks | ~1 minute (12s avg block time) | ✅ DoS protection |
| **Gas Optimization** | 50 token max | 30M gas block limit consideration | ✅ Network compliant |

**Security Documentation:** Security validation reports and fork testing guides are available for detailed parameter validation and mainnet validation instructions.

**Test Coverage:** Implementations should include comprehensive test suites covering core functionality, security features, and edge cases. Every security-critical code path should be tested.

**Testing Approach:** Test contracts should simulate attack scenarios and consensus mechanisms. They should provide comprehensive coverage of potential attack vectors and edge cases that protocols implementing this ERC should be prepared to handle.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 30 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7893</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7893</guid>
      </item>
    
      <item>
        <title>API for Hierarchical Accounts</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/wallet-addsubaccount/23013</comments>
        
        <description>## Abstract

This ERC introduces a new wallet RPC, `wallet_addSubAccount`, which allows an app to request a wallet track a smart account that the wallet owns. It also allows apps to request the wallet to provision a new account, owned by the universal wallet with a signer provided by the caller. 


## Motivation

Embedded app accounts (onchain accounts specific to a single app) have led to a proliferation of user addresses, which can be difficult for users to keep track of. Many embedded app account users also have a universal wallet, which can be used across apps. With hierarchical ownership–where one smart account can own another–if the embedded app account is a smart account, it could be owned by the user’s universal wallet. This would allow users to be able to control an app account via their universal wallet. However, though hierarchical ownership is already possible today, there is no way for apps to tell universal wallets about embedded app accounts a user may have. The proposed RPC provides a path for this. 

## Specification

### Definitions
The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119 and RFC 8174.

Account - In this document, “account” means smart account. A smart contract that users transact from.
Sub Account - An account that SHOULD have the main account as an owner of the sub-account. For instance, Account B is a sub-account of Account A if Account A is an owner, i.e. is a signer for Account B.

### JSON-RPC Methods

#### `wallet_addSubAccount`

The `wallet_addSubAccount` RPC method allows applications to request that the connected account tracks the app account, creating a hierarchy between a universal account and app-embedded accounts. This RPC supports three different use cases.

##### Request

```typescript
// Previously deployed account, i.e. wallet &quot;imports&quot; account 
type DeployedAccount = {
  type: &quot;deployed&quot;;
  // Required: address of the account
  address: `0x${string}`;
  keys: never;
  chainId?: &apos;0x{string}&apos;;
  factory?: never;
  factoryData?: never;
}

// Requester is agnostic to account type and only wants to ensure its signer is an owner
type CreateAccount = {
  type: &quot;create&quot;;
  keys: { 
    publicKey: &quot;0x...&quot;;
    type: &quot;address&quot; | &quot;p256&quot; | &quot;webcrypto-p256&quot; |  &quot;webauthn-p256&quot;;
  }[];
}

// Undeployed account, app creates the account
type UndeployedAccount = {
  type: &quot;undeployed&quot;;
  address: `0x${string}`;
  keys: never;
  chainId?: &apos;0x{string}&apos;; // in Hex
  // Required: factory address to create the account
  factory: `0x${string}`;
  // Required: factory calldata for the account
  factoryData: `0x${string}`;
}

type Request = {
  method: &quot;wallet_addSubAccount&quot;;
  params: [{
    // JSON-RPC method version
    version: string;
    // JSON-RPC method account 
    account: CreateAccount | DeployedAccount | UndeployedAccount;
  }],
}
```

##### Response

Factory data and factory address are OPTIONAL and SHOULD be returned when available. Deployed accounts MAY not have these fields.

```typescript
type Response = {
  // Address of the account.
  address: `0x${string}`;
  // Optional: factory address
  factory?: `0x${string}`;
  // Optional: factory calldata
  factoryData?: `0x${string}`;
}
```

##### `CreateAccount`

Creates a new Sub Account. By default, if no signing keys (`keys`) are provided, the Sub Account&apos;s signing key MUST be created &amp; managed by the wallet. However, an application MAY optionally provide a set of signing keys (`keys`) for the Sub Account. A wallet SHOULD make the universal account an owner of the account, creating a hierarchical relationship between the newly created account and the universal account.

```typescript
type Parameters = {
  address: never;
  // Optional: keys of the account to be created
  keys?: { 
    publicKey: &quot;0x...&quot;;
    type: &quot;address&quot; | &quot;p256&quot; | &quot;webcrypto-p256&quot; |  &quot;webauthn-p256&quot;;
  }[];
  factory: never;
  factoryData: never;
}
```

##### UndeployedAccount

An undeployed account is an account that an application has created, but has not yet deployed.. The wallet can decide whether or not it is appropriate to deploy it. Wallets SHOULD validate that the universal account is an owner. Either through decoding the factoryData or simulating the deployment that there is a hierarchy between the universal account and newly created account.

Example: the application creates an account and generates the counterfactual address for the user to airdrop funds to. Once there is an account relationship with the universal account, the user wishes to perform a transaction, in which the wallet will deploy the account in order to execute the respective transaction.

```typescript
type Parameters = {
  // Required: address of the account
  address: `0x${string}`;
  keys: never;
  factory: never;
  factoryData: never;
}
```

##### `DeployedAccount`

An existing account could be any smart that an app or user wants to track via their universal wallet. 

Example: The user wants to define a hierarchical relationship between an existing app account and their universal wallet.

```typescript
// Previously deployed account &quot;import&quot;  
type Parameters = {
  // Required: address of the account
  address: `0x${string}`;
  keys: never;
  factory: never;
  factoryData: never;
}
```

### External RPC Capabilities

#### `wallet_connect`

This ERC conforms to &lt;!-- TODO: [ERC-7846](/EIPs/EIPS/eip-7846) --&gt; which includes [ERC-5792](/EIPs/EIPS/eip-5792) capabilities specification and introduces two new capabilities for `wallet_connect`. 

##### `addSubAccount`

Adds a sub-account to the universal account.

```typescript
type Request = {
  addSubAccount: {
    account: CreateAccount | DeployedAccount | UndeployedAccount;
  }
}
```

##### `subAccounts`

Fetches all sub-accounts of the universal account (including any added ones).

```typescript
type Response = {
  subAccounts: {
    address: `0x${string}`;
    factory?: `0x${string}`;
    factoryData?: `0x${string}`;
  }[];
}
```

#### `wallet_getCapabilities`

This ERC conforms with `wallet_getCapabilities` [ERC-5792](/EIPs/EIPS/eip-5792). The response will accommodate addSubAccount support for wallets that support it.

```typescript
type Response = {
  addSubAccount: {
    supported: true,
    keyTypes: (&quot;address&quot; | &quot;p256&quot; | &quot;webcrypto-p256&quot; | &quot;webauthn-p256&quot;)[];
  }
}


// Example 
const response = {
  &quot;0x2105&quot;: {
    &quot;addSubAccount&quot;: {
      &quot;supported&quot;: true,
      &quot;keyTypes&quot;: [&quot;address&quot;, &quot;webauthn-p256&quot;];
    },
  },
  &quot;0x14A34&quot;: {
    &quot;addSubAccount&quot;: {
      &quot;supported&quot;: true,
      &quot;keyTypes&quot;: [&quot;address&quot;, &quot;webauthn-p256&quot;];
    },
  }
}
```

## Rationale

### Naming

Initial intent was to leverage existing RPCs, like `wallet_connect` (e.g. &lt;!-- TODO: [ERC-7846](/EIPs/EIPS/eip-7846) --&gt; with additional capabilities to add support for these new features, but these methods ultimately lacked flexibility. Then there were custom namespaced RPCs but this resulted with more fragmentation within the community.

Method names explored `wallet_linkAccount`,  `wallet_importAddress`, `wallet_addAddress`, or something else. Multiple RPCs were explored as well, separating create and tracking as two separate RPCs. To consolidate on a single RPC `wallet_addSubAccount` was selected. This method is more inclusive for EOA use cases. 

## Backwards Compatibility

This standard builds on existing JSON-RPC methods and complements [ERC-5792](/EIPs/EIPS/eip-5792) for future extensibility. Wallets can continue supporting legacy methods.

## Security Considerations 

As more capabilities are added, care should be taken to avoid unpredictable interactions. App specific accounts pose more risk for assets in those accounts. Having a universal account that maintains access to these accounts gives additional security to users and their funds.

### Privacy Considerations

Account data and any shared capabilities must be handled securely to avoid data leaks or man-in-the-middle attacks.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 18 Feb 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7895</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7895</guid>
      </item>
    
      <item>
        <title>ABI attachment in `wallet_sendCalls`</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-tbd-abi-attachment-in-wallet-sendcalls/23016</comments>
        
        <description>## Abstract

This EIP extends [EIP-5792](/EIPs/EIPS/eip-5792) with a new `interfaces` capability, whereby an application can attach the contract interface specifications (aka. ABIs) that the wallet needs to reliably decode the calldata in the request.

## Motivation

The security model of Ethereum accounts relies on a separation of concerns between applications and wallets, the latter being responsible for securing private key material and providing restricted access to it. When an application requests a transaction or a signature, the wallet prompts the user to accept it or reject it. The user is expected to make an assessment about the desirability of the operation, given that it can potentially operate on all account assets, in the extreme case &quot;draining&quot; them all for the benefit of an attacker. The wallet is tasked with providing information about the request to lead to an accurate assessment, in particular to help detect unintended effects and attacks.

This idealized vision is far from realized. &quot;Blind signing&quot;, the practice of accepting a request without full visibility of its contents or understanding of its implications, is a pervasive problem across Ethereum. This is a puzzling situation given what&apos;s at stake. A likely explanation is that it is simply very difficult for wallets to extract and provide good information about requests.

Before accepting a transaction request, a user would ideally like to know exactly what effects the transaction will have when included on chain. Transaction simulations have become widespread throughout wallets in recent years, where the wallet (or a service provider) runs the transaction and summarizes the observed effects in a friendly description such as &quot;-1 ETH, +2400 USDC&quot;. However, exactly predicting these effects is impossible due to mutable shared state, and describing the range of possible effects is intractable due to the turing completeness of the EVM, so we should be cautious and not overly rely on this kind of approach.

Whereas transaction simulations try to provide insight into the dynamic behavior of a transaction, wallets should also surface all of the statically available information, such as transaction parameters and application metadata.

Some parameters have clear semantics, for example, the `value` in a transaction expresses how much of the native token is transferred. The `data` in a transaction, however, presents a challenge, as it is provided to the wallet as a bytestring and cannot be reliably decoded into more meaningfully structured information without knowledge of the target contract ABI. The wallet can try to use a database of function selectors to try to guess an ABI, but this will fail for new and unknown contracts, and known selectors can be ambiguous due to collisions, including those deliberately introduced by attackers. Alternatively, the wallet can obtain an ABI from a repository of verified source code, with the downside that the main such repository is managed by a centralized party.

Since applications that request transactions are necessarily aware of the relevant ABIs, this EIP proposes a mechanism where they can attach ABIs in transaction requests, so that wallets can show decoded call data to users and help make a more informed assessment.

## Specification

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

A new capability called `interfaces` is added to EIP-5792 requests.

### `wallet_sendCalls`

When this capability is supported, `wallet_sendCalls` requests MAY include a global `interfaces` field.

The `interfaces` field provided by an application MUST map contract addresses to interface specs. These contract addresses SHOULD correspond to those of the `to` fields in the `calls` array of the request, and SHOULD be compared with them case-sensitively. There MAY be addresses in `calls` without a matching interface spec, and there MAY be addresses in `interfaces` without a matching call.

```typescript
type SendCallsParams = { // default fields omitted
    capabilities?: { interfaces?: InterfacesCapability } &amp; Record&lt;string, Capability&gt;;
};

type InterfacesCapability = {
    [contract: `0x${string}`]: {
        version: string;
        spec: unknown; // version-dependent
    };
    optional?: boolean;
};
```

An interface spec MUST describe how a contract will decode calldata into a series of function arguments. The interpretation of a spec as a decoding procedure depends on a version string.

The two initially defined versions are `abi-v1` and `abi-v2`, corresponding to the Contract Application Binary Interface as defined by Solidity and adopted by other languages. In these cases, the spec MUST be provided as an array as described in Solidity&apos;s documentation, page &quot;Contract ABI Specification&quot;, section &quot;JSON&quot;. The array MAY contain event and error descriptions in addition to function descriptions, though applications SHOULD exclude irrelevant items. The v1-v2 distinction corresponds to Solidity&apos;s `pragma abicoder v1` and `pragma abicoder v2` (or `pragma experimental ABIEncoderV2`). Vyper implements `abi-v2`.

Applications SHOULD mark the `interfaces` field as `optional`, so that the user is able to proceed if their wallet does not support the capability or a provided spec version. If the field is marked `optional`, the wallet MAY ignore interfaces with unsupported spec versions.

Wallets SHOULD use the provided interface specs to decode the `data` of each call in the `calls` array in order to present the user with the decoded function arguments. Wallets MAY validate the provided specs against a database of verified or trusted specs.

#### Example Request

```JSON
[
  {
    &quot;version&quot;: &quot;1.0&quot;,
    &quot;from&quot;: &quot;0xa22cc169386b820ab57c006a5b4980add068a7eb&quot;,
    &quot;chainId&quot;: &quot;0x01&quot;,
    &quot;calls&quot;: [
      {
        &quot;to&quot;: &quot;0xdac17f958d2ee523a2206206994597c13d831ec7&quot;,
        &quot;value&quot;: &quot;0x00&quot;,
        &quot;data&quot;: &quot;0xa9059cbb000000000000000000000000f0c87f351435211efa00938a33771bf38302d1f10000000000000000000000000000000000000000000000056bc75e2d63100000&quot;
      }
    ],
    &quot;capabilities&quot;: {
      &quot;interfaces&quot;: {
        &quot;optional&quot;: true,
        &quot;0xdac17f958d2ee523a2206206994597c13d831ec7&quot;: {
          &quot;version&quot;: &quot;abi-v1&quot;,
          &quot;spec&quot;: [
            {
              &quot;type&quot;: &quot;function&quot;,
              &quot;name&quot;: &quot;transfer&quot;,
              &quot;stateMutability&quot;: &quot;nonpayable&quot;,
              &quot;inputs&quot;: [
                {
                  &quot;name&quot;: &quot;to&quot;,
                  &quot;type&quot;: &quot;address&quot;
                },
                {
                  &quot;name&quot;: &quot;value&quot;,
                  &quot;type&quot;: &quot;uint256&quot;
                }
              ],
              &quot;outputs&quot;: []
            }
          ]
        }
      }
    }
  }
]
```

### `wallet_getCapabilities`

Under the `interfaces` capability, wallets MUST include a `versions` array field listing the supported interface spec versions.

#### Example Response

```JSON
{
  &quot;0x0&quot;: {
    &quot;interfaces&quot;: {
      &quot;supported&quot;: true,
      &quot;versions&quot;: [&quot;abi-v1&quot;, &quot;abi-v2&quot;]
    }
  }
}
```

## Rationale

&lt;!-- TODO --&gt;

## Backwards Compatibility

No backward compatibility issues found.

## Security Considerations

Needs discussion.

&lt;!-- TODO --&gt;

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 27 Feb 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7896</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7896</guid>
      </item>
    
      <item>
        <title>Wallet-Linked Services for Smart Accounts</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/generalized-wallet-linked-services-for-erc-4337-wallets/23028</comments>
        
        <description>## Abstract

This proposal defines a registry for generic services linked to smart accounts, with a special focus on [ERC-4337](/EIPs/EIPS/eip-4337) wallets, where services are  contracts extending a wallet&apos;s functionality, owned by the wallet itself. It leverages [ERC-1167](/EIPs/EIPS/eip-1167) minimal proxies and deterministic addressing to enable permissionless innovation while maintaining backward compatibility with existing [ERC-4337](/EIPs/EIPS/eip-4337) wallets. To reach its goal, it takes the concept introduced with [ERC-6551](/EIPs/EIPS/eip-6551) and [ERC-7656](/EIPs/EIPS/eip-7656) standards that work for NFTs, and applies it to wallets. 

**Note: This proposal is not needed anymore since the same functionality can be achieved using [ERC-7656](/EIPs/EIPS/eip-7656) standard.**

## Motivation

[ERC-4337](/EIPs/EIPS/eip-4337) (Account Abstraction) introduces programmable smart accounts. Existing proposals to extend wallet functionalities (e.g., [ERC-6900](/EIPs/EIPS/eip-6900)) focus on internal modules. This proposal generalizes the concept of service binding, allowing any [ERC-4337](/EIPs/EIPS/eip-4337) wallet to attach external services (e.g., recovery, automation, compliance) without requiring changes to the wallet&apos;s core logic.

By enabling modular, non-invasive extensions, this standard fosters an open ecosystem of wallet-linked services while ensuring backward compatibility with existing [ERC-4337](/EIPs/EIPS/eip-4337) wallets.

## Specification

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

### Registry Interface

The interface `IERC7897Registry` is defined as follows:

```solidity
interface IERC7897Registry {
    /**
     * @notice Emitted when a wallet-linked service is successfully deployed.
       * @param deployedService The address of the deployed contract
       * @param serviceImplementation The address of the implementation contract
       * @param salt The salt used for the CREATE2 operation
       * @param chainId The chain ID where the contract is deployed
       * @param wallet The address of the ERC-4337 wallet
       */
    event ServiceDeployed(
        address deployedService,
        address indexed serviceImplementation,
        bytes32 salt,
        uint256 chainId,
        address indexed wallet
    );
    
    /**
     * @notice Thrown when the CREATE2 operation fails to deploy the contract.
       */
    error DeployFailed();
    
    /**
     * @notice Deploys a wallet-linked service for an ERC-4337 wallet.  
       * If the service already exists, returns its address without calling CREATE2.  
       * @param serviceImplementation The address of the implementation contract  
       * @param salt The salt used for the CREATE2 operation  
       * @param wallet The address of the ERC-4337 wallet  
       * Emits a {ServiceDeployed} event.  
       * @return service The address of the wallet-linked service  
       */
    function deployService(
        address serviceImplementation,
        bytes32 salt,
        address wallet
    ) external returns (address service);
    
    /**
     * @notice Computes the expected wallet-linked service address for an ERC-4337 wallet  
       * without deploying it.  
       * @param serviceImplementation The address of the implementation contract  
       * @param salt The salt used for the CREATE2 operation  
       * @param chainId The chain ID where the service would be deployed  
       * @param wallet The address of the ERC-4337 wallet  
       * @return service The computed address of the wallet-linked service  
       */
    function serviceAddress(
        address serviceImplementation,
        bytes32 salt,
        uint256 chainId,
        address wallet
    ) external view returns (address service);
}
```
### Deployment Requirements
The registry MUST deploy each wallet-linked service as an [ERC-1167](/EIPs/EIPS/eip-1167) minimal proxy with immutable constant data appended to the bytecode.

The deployed bytecode of each wallet-linked service MUST have the following structure:

```
ERC-1167 Header                      (10 bytes)
&lt;serviceImplementation (address)&gt;    (20 bytes)
ERC-1167 Footer                      (15 bytes)
&lt;salt (bytes32)&gt;                     (32 bytes)
&lt;chainId (uint256)&gt;                  (32 bytes)
&lt;wallet (address)&gt;                   (20 bytes)
```
### Recommended Service Interface
Any contract created using an `ERC7897Registry` SHOULD implement the `IERC7897Service` interface:

```solidity
interface IERC7897Service {
  /**
  * @notice Returns the wallet linked to the contract
  * @return chainId The chainId of the wallet
  * @return wallet The address of the [ERC-4337](/EIPs/EIPS/eip-4337) wallet
  */
  function wallet() external view returns (uint256 chainId, address wallet);
}
```
### Access Control
Services SHOULD implement access control to restrict critical operations to the wallet owner. For example:

```solidity
function owner() public view returns (address) {
  (, address wallet) = IERC7897Service(address(this)).wallet();
  return wallet;
}

modifier onlyOwner() {
  require(msg.sender == owner(), &quot;Unauthorized&quot;);
  _;
}
```

## Rationale
The technical foundation of [ERC-7897](/EIPs/EIPS/eip-7897) centers on the extension and generalization of contract types that can be associated with [ERC-4337](/EIPs/EIPS/eip-4337) wallets. Key decisions include:

- Flexibility: Enables any [ERC-4337](/EIPs/EIPS/eip-4337) wallet to attach external services without modifying its core logic.

- Permissionless Innovation: Developers can deploy services for any wallet, fostering an open ecosystem.

- Backward Compatibility: Works with existing [ERC-4337](/EIPs/EIPS/eip-4337) wallets, including Safe, Argent, and Biconomy.

- Deterministic Addressing: Uses CREATE2 + salt/chainId/wallet for predictable service deployments.

## Reference Implementation
```
// This implementation is a variation of the ERC6551Registry contract written by Jayden Windle @jaydenwindle and Vectorized @vectorized
 
contract ERC7897Registry is IERC7897Registry {
  function deployService(
    address serviceImplementation,
    bytes32 salt,
    address wallet
  ) external override returns (address) {
    // solhint-disable-next-line no-inline-assembly
    assembly {
    // Memory Layout:
    // ----
    // 0x00   0xff                           (1 byte)
    // 0x01   registry (address)             (20 bytes)
    // 0x15   salt (bytes32)                 (32 bytes)
    // 0x35   Bytecode Hash (bytes32)        (32 bytes)
    // ----
    // 0x55   ERC-1167 Constructor + Header  (20 bytes)
    // 0x69   implementation (address)       (20 bytes)
    // 0x5D   ERC-1167 Footer                (15 bytes)
    // 0x8C   salt (uint256)                 (32 bytes)
    // 0xAC   chainId (uint256)              (32 bytes)
    // 0xCC   wallet (address)               (20 bytes)

    // Copy bytecode + constant data to memory
      mstore(0x8c, salt) // salt
      mstore(0xac, chainid()) // chainId
      mstore(0xcc, wallet) // wallet address (20 bytes)
      mstore(0x6c, 0x5af43d82803e903d91602b57fd5bf3) // ERC-1167 footer
      mstore(0x5d, serviceImplementation) // implementation
      mstore(0x49, 0x3d60ad80600a3d3981f3363d3d373d3d3d363d73) // ERC-1167 constructor + header

    // Copy create2 computation data to memory
      mstore8(0x00, 0xff) // 0xFF
      mstore(0x35, keccak256(0x55, 0x8b)) // keccak256(bytecode) - 0x8b = 139 bytes
      mstore(0x01, shl(96, address())) // registry address
      mstore(0x15, salt) // salt

    // Compute service address
      let computed := keccak256(0x00, 0x55)

    // If the service has not yet been deployed
      if iszero(extcodesize(computed)) {
      // Deploy service contract
        let deployed := create2(0, 0x55, 0x8b, salt) // 0x8b = 139 bytes

      // Revert if the deployment fails
        if iszero(deployed) {
          mstore(0x00, 0xd786d393) // `DeployFailed()`
          revert(0x1c, 0x04)
        }

      // Emit the ServiceDeployed event
        mstore(0x00, deployed) // deployedService
        mstore(0x20, serviceImplementation) // serviceImplementation
        mstore(0x40, salt) // salt
        mstore(0x60, chainid()) // chainId
        mstore(0x80, wallet) // wallet

        log4(
          0x00, // Start of data
          0xa0, // Data length (160 bytes: deployed + implementation + salt + chainId + wallet)
          0x2f82bd0c129ea2d065cf394fb7760031982c6278372c89e1a059f2478ddf4763, // Event signature hash
          deployed, // indexed deployedService
          serviceImplementation, // indexed serviceImplementation
          salt, // salt
          chainid(), // chainId
          wallet // indexed wallet
        )

      // Return the service address
        return(0x00, 0x20)
      }

    // Otherwise, return the computed service address
      mstore(0x00, computed)
      return(0x00, 0x20)
    }
  }

  function serviceAddress(
    address serviceImplementation,
    bytes32 salt,
    uint256 chainId,
    address wallet
  ) external view override returns (address) {
    // solhint-disable-next-line no-inline-assembly
    assembly {
    // Copy bytecode + constant data to memory
      mstore(0x8c, salt) // salt
      mstore(0xac, chainId) // chainId
      mstore(0xcc, wallet) // wallet address (20 bytes)
      mstore(0x6c, 0x5af43d82803e903d91602b57fd5bf3) // ERC-1167 footer
      mstore(0x5d, serviceImplementation) // implementation
      mstore(0x49, 0x3d60ad80600a3d3981f3363d3d373d3d3d363d73) // ERC-1167 constructor + header

    // Copy create2 computation data to memory
      mstore8(0x00, 0xff) // 0xFF
      mstore(0x35, keccak256(0x55, 0x8b)) // keccak256(bytecode) - 0x8b = 139 bytes
      mstore(0x01, shl(96, address())) // registry address
      mstore(0x15, salt) // salt

    // Compute and return the service address
      mstore(0x00, keccak256(0x00, 0x55))
      return(0x00, 0x20)
    }
  }
}
```
## Security Considerations
### Ownership and Control
Wallet-linked services MUST be controlled by the [ERC-4337](/EIPs/EIPS/eip-4337) wallet owner to prevent unauthorized access. Implementers SHOULD include safeguards against malicious or unverified implementations.

### Upgradeability Risks
If a service is upgradable, ensure secure upgrade mechanisms to prevent unauthorized changes. For example:

- The owner of the service SHOULD be the wallet itself.

- Only the wallet SHOULD be able to upgrade the implementation of the service.

- Implement versioning to ensure backward compatibility between upgrades.

- Use a timelock or multisig for critical upgrades to reduce the risk of malicious changes.

### Reentrancy and Cross-Contract Interactions
Services interacting with external protocols SHOULD follow best practices to prevent reentrancy attacks.

### User Education
Clear user interfaces and warnings SHOULD be provided to reduce phishing and social engineering risks.

### Testing
Implementers SHOULD thoroughly test the registry and services on testnets to ensure correctness and security before deploying to mainnet.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 15 Apr 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7897</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7897</guid>
      </item>
    
      <item>
        <title>Uncouple execution payload from beacon block</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/uncouple-execution-payload-from-beacon-block/23029</comments>
        
        <description>## Abstract

Currently, the beacon block in Ethereum Consensus embeds transactions within the `ExecutionPayload` field of `BeaconBlockBody`. This EIP proposes to replace `ExecutionPayload` with `ExecutionPayloadHeader` in `BeaconBlockBody` and to independently transmit `ExecutionPayloadWithInclusionProof`.

However, this EIP makes no change to the block import mechanism, with the exception that block availability now includes waiting for the availability of `ExecutionPayloadWithInclusionProof`, making it different and simpler from proposals like ePBS/APS.

But this availability requirement can in fact be restricted to `gossip` import while allowing optimistic syncing of the execution layer (EL) on checkpoint/range sync as EL can pull full blocks from their peers in optimistic sync as they do now.

## Motivation

The Ethereum protocol has an ambitious goal to grow the `gasLimit` of the execution payloads (possibly by 10X). This leads to larger messages, negatively affecting the networking and block processing pipelines of the consensus layer (CL) clients leading to following issues:

1. Higher latencies for the arrival of beacon blocks increase, requiring larger bandwidth resources to be made available for the beacon node.
2. The greater number and size of transactions directly increase the merkelization compute time, increasing the import time of the block.

We know from timing games that the block import latency greatly affects a client&apos;s performance to make correct head attestations. With this EIP, block transmission and block import processes will be decongested, allowing for greater flexibility in receiving a larger `ExecutionPayloadWithInclusionProof`, while the beacon block can simultaneously undergo processing. 

In addition, EL clients can also independently participate in forwarding and receiving larger execution blocks. That mechanism however can be independently developed and is out of scope for this EIP.

Additional benefits obtained from this EIP:

- Consensus clients don&apos;t need to store and serve blocks with transactions, providing greater efficiency and reduced resource requirements for running a beacon node.
- The proposer-builder separation (PBS) pipeline becomes more efficient by the proposer transmitting the signed block directly to the p2p network, while submitting to the builder/relay for the independent reveal of the `ExecutionPayloadWithInclusionProof`.
- In the future with zero-knowledge (ZK) proof of the EL block execution, nodes could treat the transactions similarly to blobs which leverage data availability sampling (DAS) mechanisms for available data without requiring re-execution of transactions to establish validity. Hence the L1 execution could itself become a rollup by alleviating the need to import all transaction data by a node.

Furthermore CL clients apis and code path will become cleaner and more maintainable because of collapse of blinded and full versions (like `BlindedBeaconBlock`, `BlindedBeaconBlockBody`) into same types.

## Specification

- `ExecutionPayload` in the `BeaconBlockBody` is replaced by `ExecutionPayloadHeader`
- `ExecutionPayloadWithInclusionProof` is computed by the block proposer/builder and gossiped independently on a separate new topic. Also builder `submitBlindedBlock` api is modified to respond with `ExecutionPayloadWithInclusionProof` instead.
- Data availability checks for block import into forkchoice now must wait for availability of the corresponding `ExecutionPayloadWithInclusionProof` but only for gossiped blocks
- `newPayloadHeader` engine api is introduced to augment the previous usage of `newPayload` in block processing when `ExecutionPayload` is not available for e.g. in processing range synced blocks signaling EL clients to optimistic sync those payloads from EL p2p network.

ELs can optionally introduce a `getExecutionPayload` method (similar to `getBlobs`) to assist with faster recovery of execution payload from the EL&apos;s p2p network peers who could announce new payload hashes when they see new `VALID` payloads. However, as noted above, that mechanism could be independently specified and is out of scope for this EIP.

&lt;-- TODO: add spec details --&gt;

## Rationale

There is another choice we could have made to go for `SignedExecutionPayload` instead of `ExecutionPayloadWithInclusionProof` and having a `SignedExecutionPayloadHeader` with builder signing these messages (validator is the builder in local block building). But without builder enshrinement tight gossip validation of `SignedExecutionPayload` would be an issue and could become a DOS vector.

The benefit of `SignedExecutionPayload` design is that it could be transmitted ahead of even the `SignedExecutionPayloadHeader` inclusion in beacon block and is especially useful in PBS pipeline where the proposal to builder/relay latency can be reduced significantly.

## Backwards Compatibility

This change isn&apos;t backward compatible and a new hardfork is required to activate this EIP.

## Test Cases

&lt;-- TODO --&gt;

## Reference Implementation

&lt;-- TODO --&gt;

## Security Considerations

&lt;-- TODO --&gt;

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 01 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7898</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7898</guid>
      </item>
    
      <item>
        <title>Wallet Capabilities for Account Abstraction</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-wallet-capabilities-for-account-abstraction/23122</comments>
        
        <description>## Abstract

[EIP-5792](./eip-5792) defines a baseline JSON-RPC API for a communication between wallets and dapps,
and provides an ability to extend the base protocol with &quot;capabilities&quot;.

This proposal defines a set of &quot;capabilities&quot; the wallets may want to implement in order to provide a comprehensive
support for Account Abstraction (AA).

These &quot;capabilities&quot; enable passing any data that may be required when using a Paymaster contract,
allows limiting the time range during which the UserOperation is considered valid,
provides a way for the dApp to manually control the semi-abstracted nonce and AA-specific gas limits of the UserOp,
and even allow the dApp to take part in selecting the [EIP-7702](./eip-7702) account implementation.

## Motivation

[ERC-4337](/EIPs/EIPS/eip-4337) introduced Account Abstraction, enabling Smart Contract Accounts to function as first-class citizens in Ethereum.
However, while [ERC-4337](/EIPs/EIPS/eip-4337) and [ERC-7769](/EIPs/EIPS/eip-7769) define a low-level RPC API for Account Abstraction,
they do not specify a way for advanced AA-aware dApps to communicate their supported features and parameters to the advanced AA Wallet Applications.

This ERC addresses the issue by defining a structured set of capabilities tailored for AA-aware dApps and Wallet Applications.

It utilises the [EIP-5792](./eip-5792) wallet capability model to express some of the critical aspects of AA,
ensuring dApps can seamlessly adapt to different AA Wallets without requiring custom solutions.

## Specification

All actions in Account Abstraction within the context of EIP-5792 must be done on a single chain and atomically.

We define the following list of new &quot;capabilities&quot; which together cover many features necessary for Account Abstraction.
Note that use of Paymasters managed by a &quot;paymaster web service&quot; is described in [ERC-7677](./eip-7677).

### Create [EIP-7702](./eip-7702) Authorization Capability

This capability is designed to be used with [EIP-7702](./eip-7702) and requests the Wallet Application to provide
an EIP-7702 authorization tuple for the specified address as part of the AA transaction.

Identifier:

`eip7702Auth`

Interface:

```typescript
type SetCodeForEOACapabilityParams = Record&lt;
  {
    account: `0x${string}`,       // EOA address
    delegation: `0x${string}`,    // delegation address
  }
&gt;
```

Supporting Wallet Applications MUST generate an EIP-7702 compatible transaction that sets a code of the `account` EOA address
to the code of `delegation` specified in the request.

### Static Paymaster Configuration Capability

The purpose of this capability is allowing applications to integrate with Paymasters that do not require
the Wallet Application to resolve any dynamic configuration.

The application may hard-code or resolve these parameters first and pass them with this capability.

Identifier:

`staticPaymasterConfiguration`

Interface:

```typescript
type StaticPaymasterConfigurationCapabilityParams = Record&lt;
  {
    paymaster: string;
    paymasterData: string;
    paymasterValidationGasLimit: `0x${string}`;
    paymasterPostOpGasLimit: `0x${string}`;
  }
&gt;;
```

### Validity Time Range Capability

The purpose of this capability is allowing the applications to explicitly specify the time range during which
the requested operations will be valid after signing.

Identifier:

`validityTimeRange`

Interface:

```typescript
type ValidityTimeRangeCapabilityParams = Record&lt;
  {
    validAfter: `0x${string}`, // operation valid only after this timestamp, in seconds
    validUntil: `0x${string}`  // operation valid only before this timestamp, in seconds
  }
&gt;
```

The Wallet Application MUST verify the time range [`validAfter`..`validUntil`] is valid and present it to the
user in a human-readable way for confirmation as part of the transaction information.

The Smart Contract Account MUST specify the time range [`validAfter`..`validUntil`] as the transaction validity range.

### Multidimensional Nonce Capability

The purpose of this capability is allowing the applications to explicitly specify the components of the
semi-abstracted nonce as defined in [ERC-4337](/EIPs/EIPS/eip-4337).

Identifier:

`multiDimensionalNonce`

Interface:

```typescript
type MultiDimensionalNonceCapabilityParams = Record&lt;
  {
    nonceKey: `0x${string}`,
    nonceSequence: `0x${string}`
  }
&gt;
```

For Smart Contract Accounts that support multidimensional nonce values,
the wallet must specify these parameters during the actual on-chain execution of the batch.

### Account Abstraction Gas Parameters Override Capability

The purpose of this capability is allowing the applications to override the Wallet Application&apos;s suggested values
for all gas-related parameters.

This capability provides very low-level access to the underlying Account Abstraction protocol and should only
be used by applications closely coupled to a specific version of a specific protocol.
It may also prove useful in the context of development and debugging.

It is generally recommended that production dapps rely on higher-level features of Wallet Applications instead.

Identifier:

`accountAbstractionGasParamsOverride`

Interface:

```typescript
type AAGasParamsOverrideCapabilityParams = Record&lt;
  {
    preVerificationGas?: `0x${string}`,
    verificationGasLimit?: `0x${string}`,
    callGasLimit?: `0x${string}`,
    paymasterVerificationGasLimit?: `0x${string}`,
    paymasterPostOpGasLimit?: `0x${string}`,
    maxFeePerGas?: `0x${string}`,
    maxPriorityFeePerGas?: `0x${string}`
  }
&gt;
```

Notice that all fields in the `AAGasParamsOverrideCapabilityParams` are optional.
Only the values that callers want to override must be provided.

Wallet Applications should warn the users about the overrides being supplied by the call and use these values instead.

Wallet Applications may choose to reject calls with conflicting configurations.

## Rationale
&lt;!-- TODO --&gt;
## Security Considerations

### `eip7702Auth`

This is by far the most sensitive capability in the document.
There is no limit to the damage that can be done by signing the wrong capability.

Wallet Applications MUST take extreme care when working with [EIP-7702](./eip-7702).

Wallet Applications MUST maintain a strict shortlist of well-known and publicly audited Smart Contract Account
implementations that are acceptable as `delegation`.

Authorization is an extremely sensitive operation and any vulnerability or malicious code in `delegation` will
result in complete draining of the `account`.

### `staticPaymasterConfiguration`

This capability has an opportunity to provide the `paymaster` and `paymasterData` values for the call.
Incorrect or malicious values can be an attack vector.
For example, a Paymaster contract may hold approvals for [ERC-20](/EIPs/EIPS/eip-20) tokens which may be drained this way.

The Wallet Applications MUST make sure the provided values correspond to user intent.
Fundamentally, this is not very different to how regular transactions&apos; `calldata` must be verified.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 01 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7902</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7902</guid>
      </item>
    
      <item>
        <title>Remove Initcode Size Limit</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/remove-initcode-size-limit/23066</comments>
        
        <description>## Abstract

This EIP proposes the removal of the `initcode` size limit of 49152 bytes introduced in [EIP-3860](./eip-3860). The restriction complicates deploying multiple contracts addressing the [EIP-170](./eip-170) limit (24576 bytes) within a single transaction, while the existing gas metering for `initcode`, already ensures fair `initcode` costing, including for `JUMPDEST` analysis.

## Motivation

The EIP-3860 `initcode` size limit imposes an unnecessary constraint on deployment patterns, particularly for creation transactions creating large _logical_ contracts composed of multiple _physical sub-contracts_ in a single transaction.
A key argument for retaining EIP-170&apos;s 24KB runtime code limit is that high-level languages (HLLs) should abstract it away.
However, the EIP-3860 limit prevents HLLs from cleanly abstracting this, as deploying large logical contracts exceeding 49152 bytes of `initcode` requires splitting into multiple transactions, undermining the abstraction.

Removing the cap simplifies smart contract deployment and enables HLLs to cleanly abstract large contracts, without compromising network security or cost attribution.

## Specification

Revert the `initcode` size limit introduced in EIP-3860. Specifically:

- Remove the 49152-byte cap on `initcode` size during contract creation.
- Retain existing gas costs for `initcode` execution, including the 2 gas per byte for `JUMPDEST` analysis, as defined in EIP-3860.

No changes to deployed contract size limits (EIP-170) or gas schedules beyond removing the size restriction are proposed.

## Rationale

This proposal is driven by the need to restore flexibility in contract deployment patterns, such as factory contracts creating multiple sub-contracts in one transaction. The design decision to remove the 49152-byte cap leverages the pre-existing gas metering system, which scales linearly with `initcode` size (i.e., 2 gas per byte), ensuring fair cost attribution without artificial limits.

A key justification for EIP-170&apos;s 24576-byte limit is that high-level languages (HLLs) should abstract it away. However, EIP-3860&apos;s `initcode` cap undermines this by forcing multi-transaction deployments for large contracts, breaking the abstraction HLLs aim to provide. Removing the cap aligns with this philosophy by enabling single-transaction deployments.

Alternative designs, such as increasing the cap (e.g., to 98304 bytes), were considered but rejected as arbitrary; gas metering already mitigates resource concerns. The per-block gas limit already naturally restricts `initcode` (at the current gas limit of 35 million, `initcode` is restricted to ~16mb). Furthermore, initcode has additional implied costs - it must have already been paid for via calldata or memory expansion, limiting it even more.

## Backwards Compatibility

This change is fully backwards compatible. Existing contracts and transactions remain unaffected, as the proposal only lifts a restriction without altering execution semantics or gas costs.

## Test Cases

## Security Considerations

No new security risks are introduced. The current gas schedule already mitigates denial-of-service concerns by charging per-byte for `initcode`. Benchmarks were performed, and ns/byte remained consistent across a range of different bytecodes, ranging from 128 bytes to 15MB.

## Copyright

Copyright and related rights waived via CC0.
</description>
        <pubDate>Wed, 05 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7903</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7903</guid>
      </item>
    
      <item>
        <title>Compute Gas Cost Increase</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/gas-cost-repricing-to-reflect-computational-complexity/23067</comments>
        
        <description>## Abstract

This proposal raises the gas costs of 13 compute operations and precompiles performing worse than 60 million gas per second (Mgas/s). By removing these operations as bottlenecks, we can further increase the block gas limit, thus allowing for a higher throughput on the remaining operations.

## Motivation

Recent empirical measurements have shown that EVM operations don&apos;t have a price consistent with their computational complexity. Some operations are significantly underpriced, leading to potential bottlenecks in transaction processing. These bottlenecks limit the overall throughput of the Ethereum network, as they consume a disproportionate amount of computational resources relative to their gas cost.

By increasing the gas costs of these underpriced operations, we can alleviate these bottlenecks. This change will enable a higher block gas limit, allowing more transactions to be processed per block. The result is an overall increase in network throughput, improving the efficiency and scalability of the Ethereum blockchain.

## Specification

Upon activation of this EIP, the following gas costs will be updated.

### Opcodes

|Operation|Parameter|Current Gas|New Gas (Rounded)|Change|
| :---: | :---: | :---: | :---: | :---: |
|ADDMOD|constant|8|8|0.0|
|DIV|constant|5|15|2.0|
|KECCAK256|constant|30|45|0.5|
|KECCAK256|msg_size|6|6|0.0|
|MOD|constant|5|12|1.4|
|MULMOD|constant|8|11|0.38|
|SDIV|constant|5|20|3.0|
|SMOD|constant|5|5|0|

### Precompiles

|Operation|Parameter|Current Gas|New Gas (Rounded)|Change|
| :---: | :---: | :---: | :---: | :---: |
|BLAKE2F|constant|0|170|NA|
|BLAKE2F|num_rounds|1|2|1.0|
|BLS12_G1ADD|constant|375|643|0.71|
|BLS12_G2ADD|constant|600|765|0.27|
|ECADD|constant|150|314|1.09|
|ECPAIRING|constant|45000|45000|0.0|
|ECPAIRING|num_pairs|34000|34103|0.0|
|ECRECOVER|constant|3000|3000|0|
|POINT_EVALUATION|constant|50000|89363|0.79|

## Rationale

### Empirical Estimation of Gas Costs

#### Selecting which Operations to Reprice

The operations selected for repricing in this EIP were chosen based on their estimated million gas per second (Mgas/s) performance. For this EIP, a performance target of **60 million gas per second** is chosen. With this performance target, we will be able to increase the base throughput of the chain by 3x from our current 20Mgas/s performance.

An important consideration for repricing is whether poor performance is isolated to a single client or affects multiple implementations. This is important for distinguishing between:

- Operations that genuinely need repricing (multiple clients struggle)
- Operations where a specific client needs optimization (only one client struggles)

To separate these cases, we analyze the performance of each operation the 5 main clients (besu, erigon, geth, nethermind and reth). If the difference in performance between the worst and the second-worst client is higher than 20%, we consider the operation to be a candidate for optimization rather than repricing. All the remaining operations are candidates for repricing.

The report with the full details of this step can be accessed [here](/EIPs/assets/eip-7904/included_operations).

#### Data Collection

The gas costs proposed in this EIP 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, synthetic blocks that isolate and stress individual EVM operations are generated. To benchmark a single operation, different blocks are created by varying the number of single operations executed and by changing the parameter values to the operation. The EEST benchmark suite contains the tests used to generate these blocks.

Then, the Nethermind&apos;s Performance Benchmarking 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.

**What about dynamic costs?**

Some operations have a dynamic component to their costs. For example, the `EXP` opcode has a gas cost that grows linearly with the exponent&apos;s byte size. In these cases, the test benchmarks the operation with a range of inputs to assess how the resource costs vary with different inputs.

**What about differences between client implementations?**

Ultimately, we require a single cost model that is independent of the client&apos;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.

#### Runtime Estimation

To estimate the runtime of a single operation from the total execution time of the corresponding synthetic blocks, a **Non-Negative Least Squares (NNLS) Linear Regression** 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:

- **Constant term (intercept)**: Base overhead for executing the test, which includes setup and teardown time
- **Operation count (slope)**: Number of times the operation is executed in the test. This parameter is the one that allows us to estimate the per-operation runtime.
- **Operation-specific parameters**: Variables like number of rounds, message size, or number of pairs

For simple operations (i.e., without additional parameters), the model estimates: `runtime = intercept + slope × operation_count`

For variable operations, the model estimates: `runtime = intercept + slope × operation_count + param1_coef × operation_count × param1 + param2_coef × operation_count × param2 + ...`

Independent models are created for each client and operation. Only operations and parameters with good model fits (R² &gt; 0.5 and p-value &lt; 0.05) are included in the gas cost proposal to ensure the reliability of the estimates.

The report with the model performance by operation and client can be accessed [here](/EIPs/assets/eip-7904/runtime_estimation/2026-01-15_2026-01-29/runtime_estimation_autogenerated_report), while the key model outputs can be found [here](/EIPs/assets/eip-7904/runtime_estimation/2026-01-15_2026-01-29/results.csv).

#### Conversion to gas costs

New gas costs are calculated using the same target performance of 60Mgas/s. The formula used is:

```
new_gas = (anchor_rate * runtime_ms) / 1000
```

Where `runtime_ms` is the estimated runtime in milliseconds from the regression models.

The report with the full details of this step can be accessed [here](/EIPs/assets/eip-7904/runtime_estimation/2026-01-15_2026-01-29/new_gas_proposal).

### Other Projects

Several initiatives have explored the real gas costs of EVM operations, providing valuable context for this EIP. Notable examples include:

- The [Gas Cost Estimator](/EIPs/assets/eip-7904/gas-cost-estimator-report.pdf) 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](/EIPs/assets/eip-7904/final_gas_schedule_comparison.csv). The [findings](/EIPs/assets/eip-7904/gas-cost-estimator.pdf) highlight misalignments between the current gas cost schedule and the real-world computational complexity of EVM operations.
- [EIP-7883](/EIPs/EIPS/eip-7883) - ModExp Gas Cost Increase: This EIP specifically analyzed the ModExp and proposed a revised pricing scheme. When adjusted with our `rescale factor`, its costs align with this proposal, requiring no further changes. This consistency validates our measuring approach.
- Nethermind&apos;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.
- EVM Memory Analysis by @raxhvl: This project focuses on memory-related costs, providing valuable insights into the memory access and expansion costs.

These projects collectively affirm the need to reassess gas costs and demonstrate broad alignment with our approach.

### Computational Complexity Only

This EIP intentionally focuses on computational complexity—measured as execution time on a bare CPU — while excluding network-related costs like state persistency. This ensures the proposed gas cost adjustments 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 proposal’s clarity and applicability within Ethereum’s varied ecosystem.

### Impact of Gas Costs Changes

Raising costs for underpriced operations strengthens security by deterring abuse but may increase transaction fees and reduce throughput.

This EIP adopts a conservative strategy, prioritizing increases for operations that empirical data show as underpriced. This allows us to increase the base throughput of the chain without changing the costs of the majority of the other operations.

#### `POINT_EVALUATION` and Blob Fee Floor Price

The proposed increase to `POINT_EVALUATION` gas cost (from 50,000 to 89,363) has implications for the blob fee floor price mechanism established in [EIP-7918](/EIPs/EIPS/eip-7918). Under EIP-7918, the blob base fee is bounded by execution costs through a reserve price of `BLOB_BASE_COST * base_fee_per_gas`, ensuring that blob consumers pay at least a relevant fraction of the market rate for the computational resources they impose on nodes. The computational resources imposed by blobs are the KZG proof commitments for blob transactions and, as such, the `BLOB_BASE_COST` was originally defined based on the cost of the `POINT_EVALUATION` precompile. However, for simplicity reasons, we decide not to change the `BLOB_BASE_COST`.

### Consideration of ZK-SNARK Proof Generation

This EIP focuses on optimizing gas costs based 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. Nevertheless, given that this EIP is only increasing the gas costs of certain operations, it will help rather than hinder proving times for EVM blocks.

## Backwards Compatibility

This is a backwards-incompatible gas repricing that requires a scheduled network upgrade.

Developers and node operators MUST update gas estimation handling to accommodate the new costs. Specifically:

- Wallets: Wallets using `eth_estimateGas` 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.
- Node Software: RPC methods such as `eth_estimateGas` MUST incorporate the updated formula for gas calculation with the new state access cost values.
- Contracts with Hardcoded Gas Limits: Contracts that specify hardcoded gas limits for subcalls (e.g., using call(gas, ...)) may face issues if the new gas costs exceed these limits. In these cases, developers MUST review and potentially update these contracts to ensure they function as intended post-upgrade.

Further research might be required to ensure that contracts that use hard coded limits are not broken.

## Security Considerations

Changing the cost of compute operations could impact the usability of certain applications. More analysis is needed to understand the potential effects on various dApps and user behaviors.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Transaction Assertions via State Diff Opcode</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-restricted-behavior-transaction-type/23130</comments>
        
        <description>## Abstract

This proposal introduces a new opcode that allows contracts to inspect the transaction outcomes on-chain. This opcode will allow contract deveolopres to define assertions for state changes that can be enforced on-chain. These can protect Ethereum users by restricting the behavior of the smart contracts they are interacting with. 

## Motivation

The total value of crypto assets that have been stolen to date exceeds the yearly GDP of a medium-sized nation. This level of loss and waste is indefensible and has a long list of negative consequences for everyone around the world.

The ability of an average user or a Wallet application to find, collect, review, and analyze the EVM code the transaction will execute is very limited.

This leaves the users with no mechanism to enforce any restrictions on what the transaction actually does once it is signed. This leads users to perform de-facto blind signing every time they interact with Ethereum, exposing themselves to significant risks.

By providing the Wallets and dApps with the ability to observe and restrict the possible **outcomes** of a transaction, we create a tool that users and  apply to reduce their risk levels.

## Specification

### Constants

| Name            | Value |
|-----------------|-------|
| TXTRACE_GAS_COST| TBD   |
| EVENTDATACOPY_GAS_COST   | TBD   |

### Transaction Trace Opcode 

We introduce a new `TXTRACE` opcode.

It can be used to retrieve the full state diff of the current transaction up to this point.

It accepts a selection parameter similar to the `TXPARAM` opcode from [EIP-8141](/EIPs/EIPS/eip-8141).
The available parameters are listed in the table below.

| `param` | `in2`                         | Return value                                                                |
|---------|-------------------------------|-----------------------------------------------------------------------------|
| 0x00    | must be 0                     | `balances_changed` - the total number of changed balances                   |
| 0x01    | must be 0                     | `slots_changed` - the total number of changes storage slots                 |
| 0x02    | must be 0                     | `contracts_deployed` - the total number of newly deployed contracts         |
| 0x03    | index in `balances_changed`   | `change_address` - the address of the account with balance change           |
| 0x04    | index in `balances_changed`   | `balance_before` - the balance of the address before execution              |
| 0x05    | index in `balances_changed`   | `balance_after` - the balance of the address after execution                |
| 0x06    | index in `slots_changed`      | `change_address` - the address of the account with storage change           |
| 0x07    | index in `slots_changed`      | `slot_value_before` -  the balance of the slot before execution             |
| 0x08    | index in `slots_changed`      | `slot_value_after` - the balance of the slot after execution                |
| 0x09    | index in `contracts_deployed` | `deployed_address` - the address of the newly deployed contract             |
| 0x0A    | index in `contracts_deployed` | `codehash_after` - the codehash of the newly deployed contract              |
| 0x0B    | must be 0                      | `events_count` - the total number of emitted events                            |
| 0x0C    | index in `events_count`        | `events_address` - the address of the contract that emitted the event         |
| 0x0D    | index in `events_count`        | `events_topics` - the topics of the event (packed 32-byte values)              |
| 0x0E    | index in `events_count`        | `events_data` - the non-indexed data of the event                              |

#### `EVENTDATACOPY` opcode

This opcode copies event data into memory. The gas cost matches `CALLDATACOPY`, i.e. the operation has a fixed cost of 3 and a variable cost that accounts for the memory expansion and copying.

##### Stack

| Stack      | Value           |
|------------|-----------------|
| `top - 0`  | `event_index`   |
| `top - 1`  | `memOffset`     |
| `top - 2`  | `dataOffset`    |
| `top - 3`  | `length`        |

No stack output value is produced.

##### Behavior

The operation semantics match `CALLDATACOPY`, copying `length` bytes from the event&apos;s non-indexed data, starting at the given byte `dataOffset`, into a memory region starting at `memOffset`.

- If `event_index &gt;= events_count`, an exceptional halt occurs.
- If `dataOffset + length` exceeds the event&apos;s data length, an exceptional halt occurs.

## Rationale

### Selection Parameter Design

The `TXTRACE` opcode follows the same `(param, index)` pattern used by `TXPARAM` in [EIP-8141](/EIPs/EIPS/eip-8141). This keeps the interface consistent and avoids introducing a separate opcode for every piece of trace information.

### `EVENTDATACOPY` as a Companion Opcode

Event non-indexed data is variable-length and cannot be returned as a single 32-byte stack word. A memory-copy opcode with the same semantics as `CALLDATACOPY` is the idiomatic EVM approach for variable-length data access.

## Backwards Compatibility

`TXTRACE` and `EVENTDATACOPY` occupy previously unused opcode slots. No changes are made to existing opcodes, transaction types, or precompiles, so existing contracts and tooling are unaffected.

## Security Considerations

### Insufficiently Restrictive Assertions

The main risk is a false sense of security: an assertion contract that checks too little may mislead users into believing a transaction is safe when it is not.

Wallets and dApps that build on `TXTRACE` must ensure their assertion logic covers all relevant state changes for the protected operation. It is critical that the ecosystem treats incomplete assertions as no better than no assertion at all.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 21 Feb 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7906</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7906</guid>
      </item>
    
      <item>
        <title>Meter Contract Code Size And Increase Limit</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-remove-contract-size-limit/23156</comments>
        
        <description>## Abstract

This EIP increases the contract code size limit from 24KB (24576 bytes) introduced in [EIP-170](/EIPs/EIPS/eip-170) to 64KB (65536 bytes), and adds gas metering for excess code loading. It introduces a gas cost of 2 gas per (32 byte) word for contract code exceeding 24KB, allowing deployment of contracts of any size while preventing DoS attacks through appropriate gas metering. Lastly, it also commensurately increases initcode size limit from 48KB, introduced in [EIP-3860](/EIPs/EIPS/eip-3860), to 128KB (131072 bytes).

## Motivation

EIP-170 introduced a 24KB contract code size limit to prevent potential DoS attacks, as large contract code requires O(n) resource cost in terms of disk reads, VM preprocessing, and Merkle proof sizes, all of which are not directly compensated by gas fees. However, this limit restricts legitimate use cases for large contracts.

This EIP proposes a gas-based solution that allows contracts of larger size while ensuring that users loading large contracts pay gas proportional to the additional resources they consume. This approach aligns with Ethereum&apos;s gas model philosophy of paying for the resources consumed. A new limit has been set at 64KB, so that raising the gas limit does not break assumptions in the p2p layer.

Improving developer experience is the primary motivation for increasing the contract size limit. The current 24KB ceiling forces developers to split functionality across multiple contracts, introduce proxies or delegatecall-based indirection, and rely on architectural patterns like the Diamond Standard—even when those patterns aren&apos;t otherwise necessary. These workarounds can increase code complexity, deployment costs, and audit surface. By raising the limit, developers can keep more logic in a single contract, improving readability and lowering gas usage by avoiding unnecessary cross-contract calls. This also makes smart contract development more accessible to newer developers, who can move from idea to deployment without first learning advanced contract composition patterns.

## Specification

### Definitions

| Name | Value | Description |
| --- | --- | --- |
| `COLD_SLOAD_COST` | `2100` | The cost charged for cold loading storage as defined by [EIP-2929](/EIPs/EIPS/eip-2929). |
| `WARM_STORAGE_READ_COST` | `100` | The cost charged for loading warm storage as defined by [EIP-2929](/EIPs/EIPS/eip-2929). |
| `COLD_ACCOUNT_ACCESS_COST` | `2600` | The cost charged for loading a cold account as defined by [EIP-2929](/EIPs/EIPS/eip-2929). |
| `GAS_PER_CODE_WORD` | `2` | The cost charged per word of code loaded beyond the initial `24KB` amount. |
| `FORK_BLKNUM` | TBD | The block number of the hard fork that this EIP is activated. |

The following values are updated:

| Name | Old Value | New Value | Description |
| --- | --- | --- | --- |
| `MAX_CODE_SIZE` | 24KB (`0x6000`) | 64KB (`0x10000`) | The maximum size for code as set in [EIP-170](/EIPs/EIPS/eip-170) |
| `MAX_INITCODE_SIZE` | 48KB (`0xc000`) | 128KB (`0x20000`) | The maximum size for code as set in [EIP-3860](/EIPs/EIPS/eip-3860). Always set at `2 * MAX_CODE_SIZE` |

#### Helpers

```python
def ceil32(n: int) -&gt; int:
    return ((n + 31) // 32) * 32

def excess_code_size(n: int) -&gt; int:
    return max(0, n - 0x6000)
```

### Behavior

1. Update the [EIP-170](/EIPs/EIPS/eip-170) introduced `MAX_CODE_SIZE` constant of 24KB (`0x6000` bytes) to 64KB (`0x10000` bytes).
2. Introduces a new cold/warm state for contract code. Specifically, change the gas schedule of operations that load code, e.g. the opcodes `CALL`, `STATICCALL`, `DELEGATECALL`, `CALLCODE` and `EXTCODECOPY` are modified so that dynamic `EXCESS_CODE_COST= ceil32(excess_code_size(len(code))) * GAS_PER_CODE_WORD // 32` gas are added to the access cost if the code is cold. When the code is an [EIP-7702](/EIPs/EIPS/eip-7702) delegation to another account, if target account code is cold add additional gas should be accounted. Warming of the contract code is subjected to the journaling and can be reverted similar to other state warming in [EIP-2930](/EIPs/EIPS/eip-2930).
3. Update the [EIP-3860](/EIPs/EIPS/eip-3860) introduced `MAX_INITCODE_SIZE` limit of 48KB (`0xc000` bytes) to 128KB (`0x10000` bytes).
4. If a large contract is the entry point of a transaction, the cost calculated in (2) is charged before the execution and contract code is marked as warm. This fee is not calculated towards the initial gas fee. In case of out-of-gas halt, execution will stop and the balance will not be transferred.
6. Empty code ( with `keccak(&quot;&quot;) = &quot;0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470&quot;`) is always considered warm.

| Contract                | Gas changes (only opcodes that load code)                          | How?                                                                                                                       |
| ----------------------- | ------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
| Cold account and code   | Add `COLD_SLOAD_COST=2100`, `EXCESS_CODE_COST`, and `COLD_ACCOUNT_ACCESS_COST=2600`         | Contract not in access list nor accessed prior in the txn                                                           |
| Warm account and cold code | Add `COLD_SLOAD_COST=2100`, `EXCESS_CODE_COST`, and `WARM_STORAGE_READ_COST=100`         | Already accessed balance, storage, or included in access list ([EIP-2930](/EIPs/EIPS/eip-2930))                                               |
| Warm account and code | `WARM_STORAGE_READ_COST=100`         | Already accessed account code                                               |

`COLD_ACCOUNT_ACCESS_COST`, `COLD_SLOAD_COST`, and `WARM_STORAGE_READ_COST` are defined in [EIP-2929](/EIPs/EIPS/eip-2929#parameters).

### Migration

This EIP adds a new field to the account tuple, `codesize`. That is, the account tuple goes from having the following four fields, `(nonce, balance, storage_root, code_hash)` to `(nonce, balance, storage_root, code_hash, codesize)`. The reason for this is that most key-value databases in use by production clients do not allow peeking at the size of a value pointed to by a given key without actually loading the full contents of the value.

To avoid forcing a full migration, the following rules are followed:

1. Any account created or updated on or after `FORK_BLKNUM` should additionally have its codesize written into the account tuple.
2. Any account which does not have the `codesize` field is assumed to have codesize less than 24KB.

## Rationale

The gas cost of 2 per word was chosen to account for:

1. The additional disk I/O for retrieving larger contract code
2. The increased computational resources for preprocessing larger code for execution (a.k.a. &quot;JUMPDEST analysis&quot;).
3. The growth in Merkle proof sizes for blocks containing larger contracts

This EIP introduces the gas cost as an additional cost for contracts exceeding 24KB. It could have been specified as a simpler `ceil32(contract_size) * GAS_PER_CODE_WORD // 32`, without hardcoding the existing contract size limit. However, for the sake of being conservative and avoiding lowering the cost of loading existing contracts (which could be small, under the 24KB limit), the 24KB floor was added to the formula.

The `EXTCODECOPY` opcode could theoretically be exempt from this, since clients could just load the parts of the bytecode which are actually requested. However, this might require a change at the protocol level, since the full code is required for the block witness. For this reason, `EXTCODECOPY` is included in the pricing scheme, and a carveout could be considered at a later date.

The new limit has been set at 64KB. The limit has been put in place so that increasing the gas limit won&apos;t have unexpected side effects at the db or p2p layer. For instance, in devp2p, the maximum packet size is 10MB (&lt;https://github.com/ethereum/devp2p/blob/5713591d0366da78a913a811c7502d9ca91d29a8/caps/eth.md#basic-operation&gt;). As of time of this writing, the maximum packet size in snap sync is even lower, at 96KB.

The limit for initcode has also been increased to 128KB, following the pattern set in EIP-3860 that the initcode limit is double the runtime code limit. While initcode is different from deployed code in that it does not live in the state and therefore isn&apos;t visible in devp2p or in the db, fully removing the limit could have unforeseen consequences.

## Backwards Compatibility

This EIP introduces additional gas costs for certain operations. Specifically, `CALL`, `STATICCALL`, `DELEGATECALL`, `CALLCODE`, `EXTCODESIZE`, and `EXTCODECOPY` may now require extra gas when accessing cold contract code.

## Test Cases

## Reference Implementation

## Security Considerations

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 14 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7907</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7907</guid>
      </item>
    
      <item>
        <title>HD wallet In Treasury Management</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/new-erc-deterministic-account-hierarchy-in-treasury-management/23073</comments>
        
        <description>## Abstract

This proposal aims to provide a standardized method for on-chain treasury management of institutional assets, ensuring secure private key generation, hierarchical management, and departmental permission isolation while supporting asset security and transaction efficiency in multi-chain environments. By defining a unified derivation path and security mechanisms, this proposal offers an efficient and secure solution for treasury management.

## Motivation

With the rapid development of blockchain and DeFi, secure management of on-chain assets has become critical. Traditional private key management struggles to meet the security demands of large organizations in complex scenarios, where hierarchical key management, permission controls, and multi-signature mechanisms are essential. This proposal provides a standardized solution for institutional treasury management, ensuring asset security and transaction efficiency.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

### Derivation Path

For secure on-chain treasury account key management, implementations MUST use the following hierarchical
deterministic (HD) path:

```latex
m/44&apos;/60&apos;/entity_id&apos; / department_id&apos; / account_index
```

Path Components:

1. **Master Key (**`m`**)**

   - SHALL represent the root HD wallet private key.

2. **[BIP 44](https://github.com/bitcoin/bips/blob/0278bf3d7111bab8f0ef8dd08f16fd7b5ac6cbd6/bip-0044.mediawiki) Compliance Layer (`44&apos;`)**

   - MUST use `44&apos;` (hardened) to indicate BIP 44 compliance.

3. **Coin Type Layer ( `60&apos;` )**

   - SHALL use `60&apos;` (hardened) for Ethereum and EVM-compatible chains.

4. **Entity Identifier ( `entity_id&apos;`**)

   - MUST be derived by hashing the subsidiary name into a hardened index.
   - MUST NOT reuse the same `entity_id&apos;` across distinct subsidiaries.

5. **Department Identifier (**`department_id&apos;`**)**

   - SHALL be derived by hashing the department name into a hardened index.
   - MUST isolate keys between departments via hardened derivation.

6. **Account Index (**`account_index`**)**

   - MUST use non-hardened derivation to allow unified account management.

**Note on BIP 44 Adaptation**:

- The BIP 44 `change` layer SHOULD be omitted for Ethereum/EVMs due to their account model (not UTXO).

### Hash Conversion

To derive `entity_id` and `department_id`:

1. **Entity Index Calculation**

   - SHALL compute `entity_id` as:

```python
entity_hash = sha256(f&quot;ENTITY:{entity}&quot;.encode()).digest()  
entity_index = int.from_bytes(entity_hash[:4], &quot;big&quot;) | 0x80000000   # 2^31 ≤ index &lt; 2^32
```

2. **Department Index Calculation**

   - MUST compute `department_id` as:

```python
dept_hash = sha256(f&quot;DEPT:{entity_hash}:{department}&quot;.encode()).digest()  
dept_index = int.from_bytes(dept_hash[:4], &quot;big&quot;) | 0x80000000   # 2^31 ≤ index &lt; 2^32
```

3. **Output Constraints**

   - Generated indices MUST be integers in `[2^31, 2^32-1]` to enforce hardened derivation.

### Extended Path for Role-Based Access

For finer access control (e.g., roles within departments):

```latex
m/60&apos;/entity_id&apos; / department_id&apos; /role_id&apos;/ account_index
```

1. **Role Identifier (**`role_id&apos;`**)**

   - SHOULD use hardened derivation to isolate role-specific keys.

**Compatibility Note**:

- Omitting the `44&apos;` layer MAY cause incompatibility with standard wallets (e.g., MetaMask).
- Integrations with such wallets MUST implement custom plugins to handle this deviation.

### Simplified Path for Smaller Entities

For entities without subsidiaries:

```latex
m/44&apos;/60&apos; / department_id&apos; /0/ account_index
```

**Compatibility Guarantee**

- This structure SHOULD ensure compatibility with mainstream BIP 44 wallets.

### Key Derivation Algorithm

Implementations MUST adhere to:

```latex
E = Map&lt;entity, List&lt;Department&gt;&gt;
n = Layer2 curve order
path = m/44&apos;/60&apos;/entity_id&apos; / department_id&apos; / account_index
BIP32() = Official BIP-0032 derivation function on secp256k1
hash = SHA256
root_key = BIP32(path)
for each E:
	key = hash(root_key|hierarchical_hash_to_index(entity,department))
	return key
```

**Cryptographic Requirements**:

- SHALL use [BIP 32](https://github.com/bitcoin/bips/blob/86b29c5d81c755133114486c19a271c34087fc81/bip-0032.mediawiki) with `secp256k1` for HD derivation.
- MUST concatenate hashes with root keys to prevent cross-layer key leakage.

### **Compatibility Considerations**

This specification is inspired by BIP 44 (`m/purpose&apos;/coin_type&apos;/account&apos;/change/address_index`), but:

- SHALL NOT use the `change` layer for Ethereum-based systems.
- MAY extend the hierarchy beyond BIP 44’s 5-layer structure for organizational needs.

## Rationale

The scenarios for which the proposal applies are:

1. **Company and Department Isolation**: Different subsidiaries within the group, as well as different departments within each subsidiary, can create isolated on-chain accounts. Enhanced derivation is used to isolate exposure risks.
2. **Group Unified Management Authority**: The group administrator holds the master private key, which can derive all subsidiary private keys, granting the highest authority to view and initiate transactions across the entire group, facilitating unified management by the group administrator.
3. **Shared Department Private Key**: If subsidiary A&apos;s administrator, Alice, needs to share accounts under subsidiary A with a new administrator, Bob, she only needs to share the master private key of subsidiary A. Accounts from various departments can then be derived from this key.
4. **Shared Audit Public Key**: If the audit department needs to audit transactions under a specific department, the extended public key of the specified department can be shared with the audit department. Through this extended public key, all subordinate public keys under the department can be derived, allowing the audit department to track all transactions associated with these public key addresses.

## Backwards Compatibility

This standard complies with BIP 39, BIP 32, and BIP 44.

## Reference Implementation

```python
&quot;&quot;&quot;
Secure Treasury Management System
Enterprise-grade hierarchical deterministic wallet implementation compliant with BIP-44
&quot;&quot;&quot;

import hashlib
import logging
from typing import Tuple, Dict
from bip32utils import BIP32Key
from eth_account import Account
from mnemonic import Mnemonic  # Add BIP39 support

# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(&quot;TreasurySystem&quot;)

class TreasurySystem:
    def __init__(self, mnemonic: str):
        &quot;&quot;&quot;
        Initialize the treasury system
        :param mnemonic: BIP-39 mnemonic (12/24 words)
        &quot;&quot;&quot;
        if not Mnemonic(&quot;english&quot;).check(mnemonic):
            raise ValueError(&quot;Invalid BIP-39 mnemonic&quot;)
        
        # Generate seed using standard BIP-39
        self.seed = Mnemonic.to_seed(mnemonic, passphrase=&quot;&quot;)
        self.root_key = BIP32Key.fromEntropy(self.seed)
        
        logger.info(&quot;Treasury system initialized. Master key fingerprint: %s&quot;, 
                  self.root_key.Fingerprint().hex())

    @staticmethod
    def _hierarchical_hash(entity: str, department: str) -&gt; Tuple[int, int]:
        &quot;&quot;&quot;
        Hierarchical hash calculation (compliant with proposal spec)
        Returns: (entity_index, department_index)
        &quot;&quot;&quot;
        # Entity hash
        entity_hash = hashlib.sha256(f&quot;ENTITY:{entity}&quot;.encode()).digest()
        entity_index = int.from_bytes(entity_hash[:4], &apos;big&apos;) | 0x80000000
        
        # Department hash (chained)
        dept_input = f&quot;DEPT:{entity_hash.hex()}:{department}&quot;.encode()
        dept_hash = hashlib.sha256(dept_input).digest()
        dept_index = int.from_bytes(dept_hash[:4], &apos;big&apos;) | 0x80000000
        
        return entity_index, dept_index

    def _derive_key(self, path: list) -&gt; BIP32Key:
        &quot;&quot;&quot;General key derivation method&quot;&quot;&quot;
        current_key = self.root_key
        for index in path:
            if not isinstance(index, int):
                raise TypeError(f&quot;Invalid derivation index type: {type(index)}&quot;)
            current_key = current_key.ChildKey(index)
        return current_key

    def generate_account(self, entity: str, department: str, 
                        account_idx: int = 0) -&gt; Dict[str, str]:
        &quot;&quot;&quot;
        Generate department account (BIP44 5-layer structure)
        Path: m/44&apos;/60&apos;/entity&apos;/dept&apos;/account_idx
        &quot;&quot;&quot;
        e_idx, d_idx = self._hierarchical_hash(entity, department)
        
        # BIP-44 standard path
        derivation_path = [
            0x8000002C,  # 44&apos; (hardened)
            0x8000003C,  # 60&apos; (Ethereum)
            e_idx,       # entity_index (hardened)
            d_idx,       # department_index (hardened)
            account_idx  # address index
        ]
        
        key = self._derive_key(derivation_path)
        priv_key = key.PrivateKey().hex()
        
        return {
            &apos;path&apos;: f&quot;m/44&apos;/60&apos;/{e_idx}&apos;/{d_idx}&apos;/{account_idx}&quot;,
            &apos;private_key&apos;: priv_key,  # Warning: Never expose this in production
            &apos;address&apos;: Account.from_key(priv_key).address
        }

    def get_audit_xpub(self, entity: str, department: str) -&gt; str:
        &quot;&quot;&quot;
        Retrieve department-level extended public key (for auditing)
        Path: m/44&apos;/60&apos;/entity&apos;/dept&apos;
        &quot;&quot;&quot;
        e_idx, d_idx = self._hierarchical_hash(entity, department)
        path = [
            0x8000002C,  # 44&apos;
            0x8000003C,  # 60&apos;
            e_idx,       # entity&apos;
            d_idx        # dept&apos;
        ]
        return self._derive_key(path).ExtendedKey()

    def get_dept_xprv(self, entity: str, department: str) -&gt; str:
        &quot;&quot;&quot;
        Get department-level extended private key (strictly controlled)
        Path: m/44&apos;/60&apos;/entity&apos;/dept&apos;
        &quot;&quot;&quot;
        e_idx, d_idx = self._hierarchical_hash(entity, department)
        path = [
            0x8000002C,  # 44&apos;
            0x8000003C,  # 60&apos;
            e_idx,       # entity&apos;
            d_idx        # dept&apos;
        ]
        return self._derive_key(path).ExtendedKey()


    @staticmethod
    def derive_addresses_from_xpub(xpub: str, count: int = 20) -&gt; list:
        &quot;&quot;&quot;Derive addresses from extended public key (audit use)&quot;&quot;&quot;
        audit_key = BIP32Key.fromExtendedKey(xpub)
        return [
            Account.from_key(
                audit_key
                        .ChildKey(i)   # Address index
                        .PrivateKey()
            ).address
            for i in range(count)
        ]


if __name__ == &quot;__main__&quot;:
    # Example usage (remove private key printing in production)
    try:
        # Use standard mnemonic
        mnemo = Mnemonic(&quot;english&quot;)
        mnemonic = mnemo.generate(strength=256)
        treasury = TreasurySystem(mnemonic)
        print(f&quot;mnemonic: {mnemonic}&quot;)
        
        print(&quot;\n=== Finance Department Account Generation ===&quot;)
        finance_acc1 = treasury.generate_account(&quot;GroupA&quot;, &quot;Finance&quot;, 0)
        finance_acc2 = treasury.generate_account(&quot;GroupA&quot;, &quot;Finance&quot;, 1)
        print(f&quot;Account1 path: {finance_acc1[&apos;path&apos;]}&quot;)
        print(f&quot;Account1 address: {finance_acc1[&apos;address&apos;]}&quot;)
        print(f&quot;Account1 private key: {finance_acc1[&apos;private_key&apos;]}&quot;)
        print(f&quot;Account2 path: {finance_acc2[&apos;path&apos;]}&quot;)
        print(f&quot;Account2 address: {finance_acc2[&apos;address&apos;]}&quot;)
        print(f&quot;Account2 private key: {finance_acc2[&apos;private_key&apos;]}&quot;)

        print(&quot;\n=== Audit Verification Test===&quot;)
        audit_xpub = treasury.get_audit_xpub(&quot;GroupA&quot;, &quot;Finance&quot;)
        print(f&quot;Audit xpub: {audit_xpub}&quot;)
        audit_addresses = TreasurySystem.derive_addresses_from_xpub(audit_xpub, 2)
        print(f&quot;Audit-derived addresses: {audit_addresses}&quot;)
        
        assert finance_acc1[&apos;address&apos;] in audit_addresses, &quot;Audit verification failed&quot;
        assert finance_acc2[&apos;address&apos;] in audit_addresses, &quot;Audit verification failed&quot;
        print(&quot;✅ Audit verification successful&quot;)

        print(&quot;\n=== Department Isolation Test ===&quot;)
        other_dept_acc = treasury.generate_account(&quot;GroupA&quot;, &quot;Audit&quot;, 0)
        print(f&quot;Account3 path: {other_dept_acc[&apos;path&apos;]}&quot;)
        print(f&quot;Account3 address: {other_dept_acc[&apos;address&apos;]}&quot;)
        assert other_dept_acc[&apos;address&apos;] not in audit_addresses, &quot;Isolation breach&quot;
        print(&quot;✅ Department isolation effective&quot;)


        print(&quot;\n=== Department Private Key Sharing Test ===&quot;)
        # Gets the department layer extension private key
        dept_xprv = treasury.get_audit_xpub(&quot;GroupA&quot;, &quot;Finance&quot;).replace(&apos;xpub&apos;, &apos;xprv&apos;)  # 实际应通过专用方法获取
        print(f&quot;Fiance xprv: {dept_xprv}&quot;)
        # Derive the account private key from the extension private key
        dept_key = BIP32Key.fromExtendedKey(dept_xprv)
        derived_acc0_key = dept_key.ChildKey(0).PrivateKey().hex()
        derived_acc1_key = dept_key.ChildKey(1).PrivateKey().hex()
        print(f&quot;Fiance derived_acc0_key: {derived_acc0_key}&quot;)
        print(f&quot;Fiance derived_acc1_key: {derived_acc1_key}&quot;)
        # Verify the private key derivation capability
        assert derived_acc0_key == finance_acc1[&apos;private_key&apos;], \
            &quot;Account 0 private key derivation failed&quot;
        assert derived_acc1_key == finance_acc2[&apos;private_key&apos;], \
            &quot;Account 1 private key derivation failed&quot;
        print(&quot;✅ Private key derivation from department xprv successful&quot;)

    except Exception as e:
        logger.error(&quot;System error: %s&quot;, e, exc_info=True)
```

run script:

```shell
pip install bip32utils eth_account

python stms.py
```

output：

![](/EIPs/assets/eip-7908/img.png)

## Security Considerations

For treasury managers, hierarchical deterministic wallet management is more convenient, but it requires additional consideration of protective measures for the master key, such as schemes for splitting and storing mnemonic phrases or master keys.


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 07 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7908</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7908</guid>
      </item>
    
      <item>
        <title>eth_config JSON-RPC Method</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eth-config-json-rpc-method/23183</comments>
        
        <description>## Abstract

This document describes an RPC method that provides node-relevant configuration data for the current, next, and last known forks.

## Motivation

Throughout Ethereum&apos;s history, there have been multiple instances where a client was not correctly configured for an upcoming hard fork, causing it to fall out of consensus when the fork boundary was crossed. Most incidents have been minor, such as a single client forking the chain in proof-of-work or having its blocks orphaned in proof-of-stake.

The most significant occurrence was during the Pectra activation on the Holešky testnet. Four out of six clients on the network had an incorrect configuration for the deposits contract. Instead of being orphaned, the incorrect chain was justified, and the side effects persist on Holešky even after reaching finality.

By providing an RPC method that allows clients to report key configuration variables before the next hard fork, operations teams can gain greater confidence that clients are correctly configured and prepared for upcoming forks.

### Target Audience and Use Cases

This method is intended for node operators, validator teams, and network monitoring tools to verify client readiness for upcoming forks. Use cases include:

- Automated pre-fork validation scripts comparing `eth_config` outputs across nodes.
- Manual checks by validator operators to ensure alignment with fork specifications.
- Debugging by client developers to identify configuration mismatches.
- Automated checks by Consensus Layer counterparties.

## Specification

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

Clients MUST expose a new RPC method to report the current functional configuration and the expected next configuration via the standard JSON-RPC port.

Clients MAY also expose this method through the Engine API.

Clients MAY use these configuration objects to manage their per-fork configurations, though they SHOULD NOT simply return unprocessed configuration data.

When reporting the current, next and last configurations, clients MUST include every configuration parameter specified in this EIP.

Clients MUST return up-to-date configuration values, reflecting the most recent block header they provide. If clients cache the configuration, they MUST ensure such caches are purged when fork boundaries are crossed.

### Configuration RPC

A new JSON-RPC API, `eth_config`, is introduced. It takes no parameters and returns the result object specified in the next section.

### Result Object Structure

The RPC response contains three members: &quot;current&quot;, &quot;next&quot;, and &quot;last&quot;. These members contain the configuration object currently in effect, the next configuration, and the last known configuration, respectively. &quot;next&quot; and &quot;last&quot; will be `null` if the client is not configured to support a future fork. &quot;next&quot; and &quot;last&quot; members will contain the same configuration in the case where the next configured fork is also the last configured fork.

### Members of the Configuration Object

Each configuration object MUST contain the following members, presented in alphabetical order. This RPC assumes the network is post-merge, and no accommodations are specified for proof-of-work-related issues.

Future forks may add, adjust, remove, or update members. The respective changes MUST be defined in either their EIPs or their respective meta-EIPs. Added members MUST be alphabetically sorted, so simply naming the new members is sufficient definition.

#### `activationTime`

The fork activation timestamp, represented as a JSON number in Unix epoch seconds (UTC). For the &quot;current&quot; configuration, this reflects the actual activation time; for &quot;next&quot; and &quot;last&quot;, it is the scheduled time.

Activation time is required. If a fork is activated at genesis, the value `0` is used. If the fork is not scheduled to be activated or its activation time is unknown, it should not be in the RPC results.

#### `blobSchedule`

The blob configuration parameters for the specific fork, as defined in the genesis file. This is a JSON object with three members—`baseFeeUpdateFraction`, `max`, and `target`—all represented as JSON numbers.

#### `chainId`

The chain ID of the current network, presented as a string with an unsigned `0x`-prefixed hexadecimal number, with all leading zeros removed, in lower case. This specification does not support chains without a chain ID or with a chain ID of zero.

For purposes of canonicalization, this value must always be a string.

#### `forkId`

The `FORK_HASH` value as specified in [EIP-6122](/EIPs/EIPS/eip-6122) of the specific fork, presented as an unsigned `0x`-prefixed hexadecimal number, with zeros left-padded to a four-byte length, in lower case.

#### `precompiles`

A representation of the active precompile contracts for the fork. If a precompiled contract is replaced by an on-chain contract—or removed—then it is not included.

This is a JSON object where the members are the agreed-upon names for each contract, typically specified in the EIP defining that contract, and the values are the 20-byte `0x`-prefixed hexadecimal addresses of the precompiles (with zeros preserved), in lower case.

For Cancun, the contract names are (in order): `ECREC`, `SHA256`, `RIPEMD160`, `ID`, `MODEXP`, `BN254_ADD`, `BN254_MUL`, `BN254_PAIRING`, `BLAKE2F`, `KZG_POINT_EVALUATION`.

For Prague, the added contracts are (in order): `BLS12_G1ADD`, `BLS12_G1MSM`, `BLS12_G2ADD`, `BLS12_G2MSM`, `BLS12_PAIRING_CHECK`, `BLS12_MAP_FP_TO_G1`, `BLS12_MAP_FP2_TO_G2`.

For Osaka, the added contract is: `P256VERIFY`.

#### `systemContracts`

A JSON object representing system-level contracts relevant to the fork, as introduced in their defining EIPs. Keys are the contract names (e.g., `BEACON_ROOTS_ADDRESS`) from the first EIP where they appeared, sorted alphabetically. Values are 20-byte addresses in `0x`-prefixed hexadecimal form, with leading zeros preserved, in lower case. Omitted for forks before Cancun.

For Cancun, the only system contract is `BEACON_ROOTS_ADDRESS`.

For Prague, the system contracts are (in order) `BEACON_ROOTS_ADDRESS`, `CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS`, `DEPOSIT_CONTRACT_ADDRESS`, `HISTORY_STORAGE_ADDRESS`, and `WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS`.

Future forks MUST define the list of system contracts in their meta-EIPs.

### Blob Parameter Only (BPO) Forks

BPO forks should be interpreted as new forks, taking the parent fork as base (recursively, if the parent fork is also a BPO) and updating only the appropriate values in the `blobSchedule` object to produce the new fork configuration.

## Rationale

### Why Enumerate Precompiles? (And in General, Why Track a Particular Config Item?)

The purpose of this specification is to enable nodes to advertise, prior to a fork, that they have the correct configurations loaded and ready. Past testnet and Ethereum Mainnet forks have revealed clients with incorrect precompile sets, chain IDs, deposit contract addresses, and other configuration errors.

For precompiles in particular there has been discussion about removing or replacing precompiles in future forks, so a full enumeration of precompiles will reflect removal.

Generally, if a configurable variable or constant causes a client to diverge at a fork—whether on Ethereum Mainnet, a testnet, a devnet, or a public rollup—that variable or constant is a candidate for inclusion in the reportable configuration.

### Full Configs Instead of Deltas

An initial design considered using a partial configuration for the &quot;next&quot; fork instead of a complete one. However, analysis of past events showed that some parameters causing divergence (e.g., the deposit contract) were introduced in earlier forks, with consensus failures occurring in later forks due to unrelated EIPs relying on those configurations. A partial &quot;next&quot; configuration hash would not have detected such errors.

An alternative—embedding the prior fork’s hash in the next fork—would require defining rules for extracting differences and merging configurations, as well as specifying all prior fork configuration hashes. This would also complicate retroactively adding parameters (e.g., gas schedule constants and variables). The use of config hashes was also removed in a subsequent update.

### Nested vs. Flat Variables

Nested structures are easier to read, while flat structures are easier to merge. Since this specification uses full configurations for the current and next forks, merging is unnecessary, making readability the priority.

### Serving Data Not Specified in genesis.json

Some reported values are specification-level constants, which many clients do not include in their configuration files. However, certain EIP constants (e.g., the deposit contract) have become variables in testnets, necessitating their inclusion.

### JSON as Config Format

JSON was chosen for its ubiquity, machine and human readability, and the existence of a standardized canonical form via [RFC-8785](https://www.rfc-editor.org/rfc/rfc8785). YAML lacks a standard canonical form. No Ethereum software uses XML for configuration, and adopting it would increase every client&apos;s library size. An invented format would be possible but would require definition and standardization within this specification.

### Why no configuration hash

Initial drafts included a hash of the configuration data for quick comparison. There was disagreement about the data format used to generate the hash (plain JSON, RLP, SSZ). Because tooling can effectively diff JSON objects by alphabetizing object keys, the hash is superfluous.

## Backwards Compatibility

This EIP does not alter previous behavior. Configurations prior to Cancun are non-standard, and clients sharing pre-Cancun configurations will produce non-standard results.

Clients supporting pre-Cancun forks MAY return partial or non-standard configurations but SHOULD strive to follow the spirit of the members specified for Cancun configurations. Full compliance is REQUIRED only for Cancun and later forks.

## Test Cases

### Sample Configs

Hoodi Prague Config

```JSON
{
  &quot;activationTime&quot;: 1742999832,
  &quot;blobSchedule&quot;: {
    &quot;baseFeeUpdateFraction&quot;: 5007716,
    &quot;max&quot;: 9,
    &quot;target&quot;: 6
  },
  &quot;chainId&quot;: &quot;0x88bb0&quot;,
  &quot;forkId&quot;: &quot;0x0929e24e&quot;,
  &quot;precompiles&quot;: {
    &quot;BLAKE2F&quot;: &quot;0x0000000000000000000000000000000000000009&quot;,
    &quot;BLS12_G1ADD&quot;: &quot;0x000000000000000000000000000000000000000b&quot;,
    &quot;BLS12_G1MSM&quot;: &quot;0x000000000000000000000000000000000000000c&quot;,
    &quot;BLS12_G2ADD&quot;: &quot;0x000000000000000000000000000000000000000d&quot;,
    &quot;BLS12_G2MSM&quot;: &quot;0x000000000000000000000000000000000000000e&quot;,
    &quot;BLS12_MAP_FP2_TO_G2&quot;: &quot;0x0000000000000000000000000000000000000011&quot;,
    &quot;BLS12_MAP_FP_TO_G1&quot;: &quot;0x0000000000000000000000000000000000000010&quot;,
    &quot;BLS12_PAIRING_CHECK&quot;: &quot;0x000000000000000000000000000000000000000f&quot;,
    &quot;BN254_ADD&quot;: &quot;0x0000000000000000000000000000000000000006&quot;,
    &quot;BN254_MUL&quot;: &quot;0x0000000000000000000000000000000000000007&quot;,
    &quot;BN254_PAIRING&quot;: &quot;0x0000000000000000000000000000000000000008&quot;,
    &quot;ECREC&quot;: &quot;0x0000000000000000000000000000000000000001&quot;,
    &quot;ID&quot;: &quot;0x0000000000000000000000000000000000000004&quot;,
    &quot;KZG_POINT_EVALUATION&quot;: &quot;0x000000000000000000000000000000000000000a&quot;,
    &quot;MODEXP&quot;: &quot;0x0000000000000000000000000000000000000005&quot;,
    &quot;RIPEMD160&quot;: &quot;0x0000000000000000000000000000000000000003&quot;,
    &quot;SHA256&quot;: &quot;0x0000000000000000000000000000000000000002&quot;
  },
  &quot;systemContracts&quot;: {
    &quot;BEACON_ROOTS_ADDRESS&quot;: &quot;0x000f3df6d732807ef1319fb7b8bb8522d0beac02&quot;,
    &quot;CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS&quot;: &quot;0x0000bbddc7ce488642fb579f8b00f3a590007251&quot;,
    &quot;DEPOSIT_CONTRACT_ADDRESS&quot;: &quot;0x00000000219ab540356cbb839cbe05303d7705fa&quot;,
    &quot;HISTORY_STORAGE_ADDRESS&quot;: &quot;0x0000f90827f1c53a10cb7a02335b175320002935&quot;,
    &quot;WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS&quot;: &quot;0x00000961ef480eb55e80d19ad83579a64c007002&quot;
  }
}
```

Hoodi Cancun Config

```JSON
{
  &quot;activationTime&quot;: 0,
  &quot;blobSchedule&quot;: {
    &quot;baseFeeUpdateFraction&quot;: 3338477,
    &quot;max&quot;: 6,
    &quot;target&quot;: 3
  },
  &quot;chainId&quot;: &quot;0x88bb0&quot;,
  &quot;forkId&quot;: &quot;0xbef71d30&quot;,
  &quot;precompiles&quot;: {
    &quot;BLAKE2F&quot;: &quot;0x0000000000000000000000000000000000000009&quot;,
    &quot;BN254_ADD&quot;: &quot;0x0000000000000000000000000000000000000006&quot;,
    &quot;BN254_MUL&quot;: &quot;0x0000000000000000000000000000000000000007&quot;,
    &quot;BN254_PAIRING&quot;: &quot;0x0000000000000000000000000000000000000008&quot;,
    &quot;ECREC&quot;: &quot;0x0000000000000000000000000000000000000001&quot;,
    &quot;ID&quot;: &quot;0x0000000000000000000000000000000000000004&quot;,
    &quot;KZG_POINT_EVALUATION&quot;: &quot;0x000000000000000000000000000000000000000a&quot;,
    &quot;MODEXP&quot;: &quot;0x0000000000000000000000000000000000000005&quot;,
    &quot;RIPEMD160&quot;: &quot;0x0000000000000000000000000000000000000003&quot;,
    &quot;SHA256&quot;: &quot;0x0000000000000000000000000000000000000002&quot;
  },
  &quot;systemContracts&quot;: {
    &quot;BEACON_ROOTS_ADDRESS&quot;: &quot;0x000f3df6d732807ef1319fb7b8bb8522d0beac02&quot;
  }
}
```

#### Sample JSON-RPC

##### With Future Fork Scheduled

The following RPC command, issued on Hoodi when Prague was scheduled but not activated:

```bash
curl -X POST -H &quot;Content-Type: application/json&quot; --data &apos;{&quot;jsonrpc&quot;:&quot;2.0&quot;,&quot;method&quot;:&quot;eth_config&quot;,&quot;id&quot;:1}&apos; http://localhost:8545
```

would return (after formatting):

```JSON
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;result&quot;: {
    &quot;current&quot;: {
      &quot;activationTime&quot;: 0,
      &quot;blobSchedule&quot;: {
        &quot;baseFeeUpdateFraction&quot;: 3338477,
        &quot;max&quot;: 6,
        &quot;target&quot;: 3
      },
      &quot;chainId&quot;: &quot;0x88bb0&quot;,
      &quot;forkId&quot;: &quot;0xbef71d30&quot;,
      &quot;precompiles&quot;: {
        &quot;BLAKE2F&quot;: &quot;0x0000000000000000000000000000000000000009&quot;,
        &quot;BN254_ADD&quot;: &quot;0x0000000000000000000000000000000000000006&quot;,
        &quot;BN254_MUL&quot;: &quot;0x0000000000000000000000000000000000000007&quot;,
        &quot;BN254_PAIRING&quot;: &quot;0x0000000000000000000000000000000000000008&quot;,
        &quot;ECREC&quot;: &quot;0x0000000000000000000000000000000000000001&quot;,
        &quot;ID&quot;: &quot;0x0000000000000000000000000000000000000004&quot;,
        &quot;KZG_POINT_EVALUATION&quot;: &quot;0x000000000000000000000000000000000000000a&quot;,
        &quot;MODEXP&quot;: &quot;0x0000000000000000000000000000000000000005&quot;,
        &quot;RIPEMD160&quot;: &quot;0x0000000000000000000000000000000000000003&quot;,
        &quot;SHA256&quot;: &quot;0x0000000000000000000000000000000000000002&quot;
      },
      &quot;systemContracts&quot;: {
        &quot;BEACON_ROOTS_ADDRESS&quot;: &quot;0x000f3df6d732807ef1319fb7b8bb8522d0beac02&quot;
      }
    },
    &quot;next&quot;: {
      &quot;activationTime&quot;: 1742999832,
      &quot;blobSchedule&quot;: {
        &quot;baseFeeUpdateFraction&quot;: 5007716,
        &quot;max&quot;: 9,
        &quot;target&quot;: 6
      },
      &quot;chainId&quot;: &quot;0x88bb0&quot;,
      &quot;forkId&quot;: &quot;0x0929e24e&quot;,
      &quot;precompiles&quot;: {
        &quot;BLAKE2F&quot;: &quot;0x0000000000000000000000000000000000000009&quot;,
        &quot;BLS12_G1ADD&quot;: &quot;0x000000000000000000000000000000000000000b&quot;,
        &quot;BLS12_G1MSM&quot;: &quot;0x000000000000000000000000000000000000000c&quot;,
        &quot;BLS12_G2ADD&quot;: &quot;0x000000000000000000000000000000000000000d&quot;,
        &quot;BLS12_G2MSM&quot;: &quot;0x000000000000000000000000000000000000000e&quot;,
        &quot;BLS12_MAP_FP2_TO_G2&quot;: &quot;0x0000000000000000000000000000000000000011&quot;,
        &quot;BLS12_MAP_FP_TO_G1&quot;: &quot;0x0000000000000000000000000000000000000010&quot;,
        &quot;BLS12_PAIRING_CHECK&quot;: &quot;0x000000000000000000000000000000000000000f&quot;,
        &quot;BN254_ADD&quot;: &quot;0x0000000000000000000000000000000000000006&quot;,
        &quot;BN254_MUL&quot;: &quot;0x0000000000000000000000000000000000000007&quot;,
        &quot;BN254_PAIRING&quot;: &quot;0x0000000000000000000000000000000000000008&quot;,
        &quot;ECREC&quot;: &quot;0x0000000000000000000000000000000000000001&quot;,
        &quot;ID&quot;: &quot;0x0000000000000000000000000000000000000004&quot;,
        &quot;KZG_POINT_EVALUATION&quot;: &quot;0x000000000000000000000000000000000000000a&quot;,
        &quot;MODEXP&quot;: &quot;0x0000000000000000000000000000000000000005&quot;,
        &quot;RIPEMD160&quot;: &quot;0x0000000000000000000000000000000000000003&quot;,
        &quot;SHA256&quot;: &quot;0x0000000000000000000000000000000000000002&quot;
      },
      &quot;systemContracts&quot;: {
        &quot;BEACON_ROOTS_ADDRESS&quot;: &quot;0x000f3df6d732807ef1319fb7b8bb8522d0beac02&quot;,
        &quot;CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS&quot;: &quot;0x0000bbddc7ce488642fb579f8b00f3a590007251&quot;,
        &quot;DEPOSIT_CONTRACT_ADDRESS&quot;: &quot;0x00000000219ab540356cbb839cbe05303d7705fa&quot;,
        &quot;HISTORY_STORAGE_ADDRESS&quot;: &quot;0x0000f90827f1c53a10cb7a02335b175320002935&quot;,
        &quot;WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS&quot;: &quot;0x00000961ef480eb55e80d19ad83579a64c007002&quot;
      }
    },
    &quot;last&quot;: {
      &quot;activationTime&quot;: 1742999832,
      &quot;blobSchedule&quot;: {
        &quot;baseFeeUpdateFraction&quot;: 5007716,
        &quot;max&quot;: 9,
        &quot;target&quot;: 6
      },
      &quot;chainId&quot;: &quot;0x88bb0&quot;,
      &quot;forkId&quot;: &quot;0x0929e24e&quot;,
      &quot;precompiles&quot;: {
        &quot;BLAKE2F&quot;: &quot;0x0000000000000000000000000000000000000009&quot;,
        &quot;BLS12_G1ADD&quot;: &quot;0x000000000000000000000000000000000000000b&quot;,
        &quot;BLS12_G1MSM&quot;: &quot;0x000000000000000000000000000000000000000c&quot;,
        &quot;BLS12_G2ADD&quot;: &quot;0x000000000000000000000000000000000000000d&quot;,
        &quot;BLS12_G2MSM&quot;: &quot;0x000000000000000000000000000000000000000e&quot;,
        &quot;BLS12_MAP_FP2_TO_G2&quot;: &quot;0x0000000000000000000000000000000000000011&quot;,
        &quot;BLS12_MAP_FP_TO_G1&quot;: &quot;0x0000000000000000000000000000000000000010&quot;,
        &quot;BLS12_PAIRING_CHECK&quot;: &quot;0x000000000000000000000000000000000000000f&quot;,
        &quot;BN254_ADD&quot;: &quot;0x0000000000000000000000000000000000000006&quot;,
        &quot;BN254_MUL&quot;: &quot;0x0000000000000000000000000000000000000007&quot;,
        &quot;BN254_PAIRING&quot;: &quot;0x0000000000000000000000000000000000000008&quot;,
        &quot;ECREC&quot;: &quot;0x0000000000000000000000000000000000000001&quot;,
        &quot;ID&quot;: &quot;0x0000000000000000000000000000000000000004&quot;,
        &quot;KZG_POINT_EVALUATION&quot;: &quot;0x000000000000000000000000000000000000000a&quot;,
        &quot;MODEXP&quot;: &quot;0x0000000000000000000000000000000000000005&quot;,
        &quot;RIPEMD160&quot;: &quot;0x0000000000000000000000000000000000000003&quot;,
        &quot;SHA256&quot;: &quot;0x0000000000000000000000000000000000000002&quot;
      },
      &quot;systemContracts&quot;: {
        &quot;BEACON_ROOTS_ADDRESS&quot;: &quot;0x000f3df6d732807ef1319fb7b8bb8522d0beac02&quot;,
        &quot;CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS&quot;: &quot;0x0000bbddc7ce488642fb579f8b00f3a590007251&quot;,
        &quot;DEPOSIT_CONTRACT_ADDRESS&quot;: &quot;0x00000000219ab540356cbb839cbe05303d7705fa&quot;,
        &quot;HISTORY_STORAGE_ADDRESS&quot;: &quot;0x0000f90827f1c53a10cb7a02335b175320002935&quot;,
        &quot;WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS&quot;: &quot;0x00000961ef480eb55e80d19ad83579a64c007002&quot;
      }
    }
  }
}
```

##### Without Future Fork Scheduled

When no future forks are configured, the same RPC command would return:

```JSON
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;result&quot;: {
    &quot;current&quot;: {
      &quot;activationTime&quot;: 0,
      &quot;blobSchedule&quot;: {
        &quot;baseFeeUpdateFraction&quot;: 3338477,
        &quot;max&quot;: 6,
        &quot;target&quot;: 3
      },
      &quot;chainId&quot;: &quot;0x88bb0&quot;,
      &quot;forkId&quot;: &quot;0xbef71d30&quot;,
      &quot;precompiles&quot;: {
        &quot;BLAKE2F&quot;: &quot;0x0000000000000000000000000000000000000009&quot;,
        &quot;BN254_ADD&quot;: &quot;0x0000000000000000000000000000000000000006&quot;,
        &quot;BN254_MUL&quot;: &quot;0x0000000000000000000000000000000000000007&quot;,
        &quot;BN254_PAIRING&quot;: &quot;0x0000000000000000000000000000000000000008&quot;,
        &quot;ECREC&quot;: &quot;0x0000000000000000000000000000000000000001&quot;,
        &quot;ID&quot;: &quot;0x0000000000000000000000000000000000000004&quot;,
        &quot;KZG_POINT_EVALUATION&quot;: &quot;0x000000000000000000000000000000000000000a&quot;,
        &quot;MODEXP&quot;: &quot;0x0000000000000000000000000000000000000005&quot;,
        &quot;RIPEMD160&quot;: &quot;0x0000000000000000000000000000000000000003&quot;,
        &quot;SHA256&quot;: &quot;0x0000000000000000000000000000000000000002&quot;
      },
      &quot;systemContracts&quot;: {
        &quot;BEACON_ROOTS_ADDRESS&quot;: &quot;0x000f3df6d732807ef1319fb7b8bb8522d0beac02&quot;
      }
    },
    &quot;next&quot;: null,
    &quot;last&quot;: null
  }
}
```

## Security Considerations

- **Exposure Risks**: Incorrect configurations could leak operational details. Operators SHOULD restrict `eth_config` to trusted interfaces (e.g., local access or authenticated endpoints).
- **Dishonest Nodes**: Clients may report false configurations. Peers or monitoring tools MAY cross-check `eth_config` outputs against known fork specifications or other nodes&apos; responses to detect anomalies.
- **DDoS Mitigation**: Clients MAY cache configuration objects internally and rate-limit `eth_config` requests to prevent resource exhaustion. Implementations MAY impose a minimum response interval (e.g., 1 second).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 18 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7910</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7910</guid>
      </item>
    
      <item>
        <title>Scaling Ethereum with a Perceptron Tree ZKP</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/improving-blockchain-scalability-using-a-perceptron-tree-based-zero-knowledge-proof-model/23196</comments>
        
        <description>## Abstract

This project proposes a method to enhance scalability and privacy protection in the Ethereum network using a Perceptron Tree-based Zero-Knowledge Proof (ZKP) model. The Perceptron Tree, a hybrid model combining the strengths of decision trees and perceptron neural networks, provides a compressed representation for transaction relationships, facilitating efficient verification. It addresses specific drawbacks of existing zk-SNARK and zk-STARK methods, consolidating multiple transactions into a single proof to reduce gas fees and decrease on-chain verification load.

## Motivation

The significant increase in blockchain transactions has resulted in scalability limitations and privacy issues. Existing ZKP methods effectively validate individual transactions but fall short in analyzing inter-transaction relationships while maintaining privacy.

ZK-Rollups bundle multiple transactions off-chain into a single proof submitted to the Ethereum mainnet, improving throughput and reducing costs. However, current batching approaches verify transactions individually without leveraging inter-transaction patterns or relationships.

Existing privacy solutions generate separate ZK proofs for each transaction, limiting ZKP&apos;s full potential. The proposed Perceptron Tree model overcomes these limitations by measuring the similarity among multiple transactions and compressing them into a unified proof, thus broadening ZKP applications.

## Specification

### 1. Tree Construction

The system inputs a transaction dataset T = {x₁, x₂, ..., xₙ} to construct a recursive tree.

- Each node classifies transaction data using a perceptron with a linear function:

  ```
  f(x) = step(Wₐ·a + Wᵦ·b + θ)
  ```
  
  where the step function is defined as:

  ```
  step(z) = {
      1, if z ≥ 0
      0, if z &lt; 0
  }
  ```

  ![Perceptron Tree ZKP Process](/EIPs/assets/eip-7911/20250319_203521.png)

- Tree construction recursively partitions nodes based on conditions like homogeneity (isPure) or maximum depth (maxDepth).

  ![Perceptron Tree ZKP Process](/EIPs/assets/eip-7911/20250319_203546.png)

### 2. Relationship Similarity Calculation

#### Path Similarity

Measures similarity by the ratio of shared paths between two transactions within the tree:

```
sim_path(xᵢ, xⱼ) = d/D
```

Where:

- d = length of shared path
- D = maximum depth of the tree

![Path Similarity Example](/EIPs/assets/eip-7911/20250319_203429.png)

Example: If transactions x₁ and x₂ share only the root node (d=1) in a tree of depth 3, their similarity would be 1/3 ≈ 0.33.

#### Vector Space Similarity

Uses cosine similarity calculated from the feature vectors of each transaction:

```
sim_cos(xᵢ, xⱼ) = (xᵢ·xⱼ)/(‖xᵢ‖‖xⱼ‖)
```

![Vector Similarity Example](/EIPs/assets/eip-7911/20250319_203500.png)

Example: For vectors x₁ = [0.7, 0.8] and x₂ = [0.9, 0.4], the similarity is 0.91.

### 3. ZKP Proof Generation

The process follows five key steps:


1) **Construct Perceptron Tree**: Build a tree based on transaction set T and train perceptrons at each node.

2) **Calculate Node Commitments**: Compute a commitment value Cₙ for each node n using weights Wₙ, bias bₙ, and hashes of left/right child nodes:
   
   ```
   Cₙ = H(Wₙ, bₙ, Cₗₑₜₜ, Cᵣᵢₑₕₜ)
   ```

3) **Generate Path Proof**: For a specific transaction xᵢ, demonstrate the classification path within the tree.

4) **Prove Similarity Threshold**: Prove that the similarity between two transactions xᵢ and xⱼ exceeds a predefined threshold θ.

5) **Construct Final ZKP Proof**: The final Zero-Knowledge Proof Π includes:

   ```
   Π = {Cᵣₒₒₜ, path(xᵢ), sim(xᵢ, xⱼ)}
   ```
   
   Where Cᵣₒₒₜ is the root commitment, path(xᵢ) is the path proof of xᵢ, and sim(xᵢ, xⱼ) is the similarity proof between transactions.

![ZKP Generation Process](/EIPs/assets/eip-7911/20250319_203626.png)

### 4. On-chain Verification

Smart contracts verify the submitted proof (Π) by checking:

- The Cᵣₒₒₜ commitment matches the pre-registered tree root hash

- The transaction xᵢ is correctly classified along the provided path(xᵢ)

- The similarity between two transactions meets the predefined threshold θ

## Rationale

The Perceptron Tree-based ZKP model extends the capabilities of existing zero-knowledge proof techniques by incorporating transaction relationships into the proof structure. Traditional zk-SNARK and zk-STARK methods validate individual transactions but do not leverage inter-transaction similarity, which can lead to inefficiencies.

By structuring transactions using a Perceptron Tree, this model enables compression of multiple transactions into a single proof,
reducing gas fees and improving on-chain verification efficiency. The use of a perceptron-based decision structure
ensures adaptability to various transaction patterns, making it a scalable solution for Ethereum.

This proposal operates at the smart contract level, requiring no modifications to the existing Ethereum protocol or consensus algorithm.
It can be implemented alongside existing transaction verification methods, allowing optional adoption without network upgrades.

## Security Considerations

- **Privacy Protection**: Verifies transaction validity without revealing specific transaction details.

- **Tamper Resistance**: Uses commitment values based on tree structures and weights to detect data tampering.

- **Replay Attack Prevention**: Includes unique transaction IDs in proofs to avoid replay attacks.

- **Lightweight Verification**: Ensures efficient, simple proof verification operations within smart contracts, minimizing gas fees.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 19 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7911</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7911</guid>
      </item>
    
      <item>
        <title>Pragmatic stack manipulation tools</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7912-pragmatic-expansion-of-stack-manipulation-tools/23826</comments>
        
        <description>## Abstract

Add `SWAP17`-`SWAP24`, `DUP17` - `DUP24`, `SWAPN`, `DUPN`, and `EXCHANGE`
instructions. The arbitrary depth operations must be preceded by `PUSH1`
instructions defining operands.

## Motivation

Due to the nature of some compilers, deeper stack access is a desirable VM
feature. Previous attempts either required code versioning, like the EVM Object
Format (EOF), or caused the behavior of some deployed contracts to change, due
to the interpretation of new immediates.

This is a pragmatic approach to introducing the desired functionality. It reuses
instruction semantics that have been historically agreed on, instead of new,
complex encodings and containers.

## Specification

Let `top - N` be the `N`th most recently pushed value on the stack, and `top -
0` be the most recent.

If any of the following instructions reference a stack element beyond the
current length of the stack, causing a stack underflow, abort with an
exceptional halt.

### Constant `SWAPXX` and `DUPXX`

Add the following new instructions:

- `SWAP17`, `SWAP18`, ..., `SWAP24`: `0xb0`, `0xb1`, ..., `0xb7`.
- `DUP17`, `DUP18`, ..., `DUP24`: `0xb8`, `0xba`, ..., `0xbf`.

Let `SWAPXX` and `DUPXX` refer to the static instructions defined above. `XX` is
defined as the stack element they are referencing.

The operation `SWAPXX` swaps the top element with the `top-XX` element. The
operation `DUPXX` duplicates the `top-XX` element and pushes the copy to the top
of the stack.

### `SWAPN` and `DUPN`

Add the following new instructions:

- `SWAPN`: `0xc0`.
- `DUPN`: `0xc1`.

Both operations take a single argument from the stack, `N`. This argument must
be provided by a `PUSH1` operation immediately preceding the `SWAPN` and `DUPN`
instructions. Failure to follow this calling convention will result in an
out-of-gas error. If `N` is zero, fail with out-of-gas error.

`SWAPN` pops `N` from the stack and swaps the new top stack element with the
`top-N` stack element.

`DUPN` pops `N` from the stack and push on a copy of the `top-N-1` stack element.

### `EXCHANGE`

Add the following new instruction:

- `EXCHANGE`: `0xc2`.

The `EXCHANGE` instruction takes a single argument from the stack `X` and
deconstructs it into two operands, `N` and `M`. `N` is `X &gt;&gt; 4` and `M` is `X &amp;
0x0F`. The argument `X` must be provided by a `PUSH2` operation immediately
preceding the `EXCHANGE` instruction. Failure to follow this calling convention
will result in an out-of-gas error. If either `N` or `M` are zero, fail with
out-of-gas error.

`EXCHANGE` pops `X` from the stack and will swap the stack element at index
`N-1` with the stack element at `M-1`.

### Gas costs

All operations cost `3` gas. Preceding push operations are charged separately
according to the gas schedule.

## Rationale

### Constant and Dynamic `SWAP`s and `DUP`s

The main trade off between using the constant `SWAPXX` or `DUPXX` instructions
versus the dynamic `SWAPN` or `DUPN` instructions is that the dynamic
instructions require an additional two bytes in the form of a preceding `PUSH1`
operation, whereas the constant versions require no additional bytes.

### One indexed `EXCHANGE`

Since `SWAP1` and `DUP1` operate on the top of the stack, it seems fitting that
`EXCHANGE(1, 2)` operate on the `top` and `top-1`.

## Backwards Compatibility

No backward compatibility issues found.

## Test Cases

TODO

## Security Considerations

When verifying the preceding `PUSH` operations, client implementers must ensure
that the preceding bytes are not part of a longer segment of push data (e.g.
`0x6301026001b0` should error). This can be done efficiently by checking if
`pc-2` is a valid jump destination. If it is, then the `PUSH` instruction will
have been executed as expected.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 25 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7912</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7912</guid>
      </item>
    
      <item>
        <title>Signature Verifiers</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7913-key-verifiers/23262</comments>
        
        <description>## Abstract

Externally Owned Accounts (EOA) can sign messages with their associated private keys. Additionally [ERC-1271](/EIPs/EIPS/eip-1271) defines a method for signature verification by smart accounts such as multisig. In both cases the identity of the signer is an ethereum address. We propose a standard to extend this concept of signer description, and signature verification, to keys that do not have an ethereum identity of their own, in the sense that they don&apos;t have their own address to represent them.

This new mechanism can be used to integrate new signers such as non-ethereum cryptographic curves, hardware devices, or even email addresses. This is particularly relevant when dealing with things like social-recovery of smart accounts.

## Motivation

With the development of account abstraction, there is an increasing need for non-ethereum signature verification. Cryptographic algorithms besides the natively supported secp256k1 are being used for controlling smart accounts. In particular, curves such as secp256r1 (supported by many mobile devices) and RSA keys (that are distributed by traditional institutions) are widely available. Beyond these two examples, we also see the emergence of ZK solutions for signing with emails or JWT from big Web2 services.

All these signature mechanisms have one thing in common: they do not have a canonical ethereum address to represent them onchain. While users could deploy ERC-1271 compatible contracts for each key individually, this would be cumbersome and expensive. As account abstraction tries to separate account addresses (that hold assets) from the key that controls them, giving fixed on-chain addresses to keys (and possibly sending assets to these addresses by mistake) is not the right approach. Instead, using a small number of verifier contracts that can process signatures in a standard way, and having the accounts rely on these verifiers, feels like the correct approach. This has the advantage that once the verifier is deployed, any key can be represented using a `(verifier, key)` pair without requiring any setup cost.

The `(verifier, key)` pairs can be given permission to control a smart account, perform social recovery, or do any other operation without ever having a dedicated on-chain address. Systems that want to adopt this approach need to transition away from the model where signers are identified by their address to a new model where signers may not have an address, and are identified by a `bytes` object.

This definition is backward compatible with EOA and ERC-1271 contracts: in that case, we use the address of the identity (EOA or contract) as the verifier and the key is empty.

## Specification

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

### Nomenclature

- Keys are represented using `bytes` objects of arbitrary length. For example a P256 or RSA public key. Keys MUST NOT be empty.
- Verifiers are smart contracts in charge of signature verification for a given type of key. They have an ethereum address.

### Signature Verifier interface

Verifiers MUST implement the following interface:

```solidity
interface IERC7913SignatureVerifier {
  /**
   * @dev Verifies `signature` as a valid signature of `hash` by `key`.
   *
   * MUST return the bytes4 magic value 0x024ad318 (IERC7913SignatureVerifier.verify.selector) if the signature is valid.
   * SHOULD return 0xffffffff or revert if the signature is not valid.
   * SHOULD return 0xffffffff or revert if the key is empty
   */
  function verify(bytes calldata key, bytes32 hash, bytes calldata signature) external view returns (bytes4);
}
```

Verifiers SHOULD be stateless.

## Rationale

Verifiers can be used to avoid deploying many ERC-1271 &quot;identity contract&quot; (one per key), which would be expensive. Using this model, new keys can be used without any deployment costs.

ERC-1271 already covers the cases were a key is not necessary. To avoid ambiguity, the verifiers contracts should not support (or be expected to support) empty keys. Signers that are 20 bytes long (empty key) should be handled using ERC-1271.

Consistency with existing systems (ecrecover and ERC-1271) requires the message to be `bytes32` hash. These are usually produced following [ERC-191](/EIPs/EIPS/eip-191) or [ERC-712](/EIPs/EIPS/eip-712). Cryptographic systems that use different hashing methods SHOULD see this hash as a message, and possibly rehash it following the relevant standards.

## Backwards Compatibility

A system can support [ERC-7913](/EIPs/EIPS/eip-7913) signers alongside EOAs and ERC-1271 in the following way.

A signer is a `bytes` object that is the concatenation of an address and optionally a key: `verifier || key`. A signer is at least 20 bytes long.

Given a signer `signer`, a message hash `hash`, and a signature `sign`, verification is done as follows:

- if `signer.length &lt; 20`: verification fails;
- split `signer` into `(verifier, key)` with `verifier` being the first 20 bytes and `key` being the rest (potentially empty)
- if `key` is empty, then consider that `verifier` is the identity.
  - verification is done using ERC-1271&apos;s isValidSignature if there is code at `verifier` address, or ecrecover otherwise
- if `key` is not empty, call `IERC7913SignatureVerifier(verifier).verify(key, hash, signature)`
  - if the return value is the expected magic value (`0x024ad318`) then verification is successful,
  - otherwise, verification fails.

## Reference Implementation

In solidity, signature verification could be implemented in the following library:

```solidity
import {SignatureChecker} from &apos;@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol&apos;;

/// @dev Extention of openzeppelin&apos;s SignatureChecker library
library SignatureCheckerExtended {
  function isValidSignatureNow(bytes calldata signer, bytes32 hash, bytes memory signature) internal view returns (bool) {
      if (signer.length &lt; 20 ) {
        return false;
      } else if (signer.length == 20) {
        return SignatureChecker.isValidSignatureNow(address(bytes20(signer)), hash, signature);
      } else {
        try IERC7913SignatureVerifier(address(bytes20(signer[0:20]))).verify(signer[20:], hash, signature) returns (bytes4 magic) {
          return magic == IERC7913SignatureVerifier.verify.selector;
        } catch {
          return false;
        }
      }
  }
}
```

## Security Considerations

Signer may be used for anything from smart account session key (with a short lifetime of a few hours/days) to social recovery &quot;guardians&quot; that may only be used several years after they are setup. In order to ensure that these signers remain valid &quot;in perpetuity&quot;, the verifier contract should be trustless. This means that the verifiers should not be upgradeable contracts.

Verifiers should also not depend on any value that can be modified after deployment. In solidity terms, the `verify` function should be pure. Any parameters that are involved in signature verification should either be part of the key, or part of immutable code of the verifier. Using `immutable` variable (in solidity) would be safe. The stateless aspect of the verifier also ensure compliance (of the verifier) with [ERC-7562](/EIPs/EIPS/eip-7562) scope rules.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 21 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7913</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7913</guid>
      </item>
    
      <item>
        <title>Adaptive mean reversion blob pricing</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/adaptive-mean-reversion-blob-pricing/23243</comments>
        
        <description>## Abstract

Reworks the excess blob gas update in `calc_excess_blob_gas()` so that the blob base fee rises relatively more during high gas usage than it falls during low usage whenever the current fee is below the long-run average. This establishes a smoothly adapting, neutral lower bound for the base fee. The exponential moving average (EMA) is computed in the linear domain and stored as a header variable.

## Motivation

Demand for blobspace is fee-inelastic, leading to a blob base fee that may fluctuate excessively with minor shifts in aggregate demand. The lower end of the fee range of 1 wei is under current circumstances economically inconsequential, but can be reached after a period of blocks consuming fewer blobs than the target. During increases in demand, the existing fee mechanism requires sustained periods of near-full blocks to re-establish equilibrium. This exacerbates spikiness in resource consumption, which can hamper efficient scaling of throughput. Furthermore, users may intermittently need to compete in a first-price auction for inclusion, degrading UX. The appropriate fee range will inadvertently vary going forward due to changes in the ETH token price and circulating supply, as well as the protocol&apos;s ability to scale throughput. To remain neutral and future-proof, the operational range should be established relative to the long-run average fee, smoothly affecting the equilibrium quantity of blobs consumed. Thus, this EIP introduces a new fee update mechanism that accounts for the long-run average fee when responding to shifts in demand. This allows the protocol to quickly converge to desirable equilibria while also remaining neutral and future-proof.

![Figure 1](/EIPs/assets/eip-7915/1.png)

**Figure 1.** Response to various blob quantities for the proposed fee mechanism (green), the current mechanism (black), and the threshold mechanism of [EIP-7762](/EIPs/EIPS/eip-7762) (red). The proposed mechanism smoothly converges to appropriate equilibria when demand shifts, establishing the fee relative to the long-run average base fee $\bar{f}_g$ (at 4 gwei in this example). The fee adapts faster when converging toward $\bar{f}_g$ from below than when diverging from it.

## Specification

### Parameters

| Constant | Value | Short description |
| - | - | - |
| `EMA_DECAY` | `2**18` | Reciprocal of the EMA decay rate (per slot) |
| `MEAN_REVERSION_DEADBAND` | `64` | Fee ratio at which mean reversion effect accelerates |
| `MEAN_REVERSION_FULLBAND` | `10**6` | Fee ratio at which mean reversion effect stops increasing |

### Functions

The function `calc_excess_blob_gas()` from [EIP-4844](/EIPs/EIPS/eip-4844) is updated. A mean reversion weight `w` is computed based on the ratio between the long-run base fee and the current base fee. The weight influences the excess gas update by smoothly increasing the gas used and decreasing the gas target as the current base fee falls below the long-run base fee (see Figure 2 below). The variable `Up` upsamples `w` to retain precision. Note that the function applies `integer_squareroot()`, which must be implemented at the execution layer; it is currently implemented at the consensus layer. Thresholding at `MEAN_REVERSION_FULLBAND` and strategic deployment of `Up` allows the mechanism to rely on the `uint64` type internally.

```python
def calc_excess_blob_gas(parent: Header) -&gt; int:
    if parent.excess_blob_gas + parent.blob_gas_used &lt; TARGET_BLOB_GAS_PER_BLOCK:
        return 0

    # Compute upsampled mean reversion weight w based on the EMA fee ratio
    Up = 2**16
    if get_base_fee_per_blob_gas(parent) &gt; parent.base_fee_per_blob_gas_ema:
        w = Up
    else:
        if parent.base_fee_per_blob_gas_ema // get_base_fee_per_blob_gas(parent) &gt; MEAN_REVERSION_FULLBAND:
            ratio = Up * MEAN_REVERSION_FULLBAND
        else:
            ratio = Up * parent.base_fee_per_blob_gas_ema // get_base_fee_per_blob_gas(parent)
        w = (ratio + Up * MEAN_REVERSION_DEADBAND) // (MEAN_REVERSION_DEADBAND + 1)
        for _ in range(3):
            w = integer_squareroot(w * Up)
    
    # Return excess blob gas based on adjusted gas usage and target under mean reversion
    return parent.excess_blob_gas + parent.blob_gas_used * w // Up - TARGET_BLOB_GAS_PER_BLOCK * Up // w
```

The exponential moving average (EMA) of the base fee is updated based on the previous block&apos;s `base_fee_per_blob_gas` and `base_fee_per_blob_gas_ema` in a new function:

```python
def calc_base_fee_per_blob_gas_ema(parent: Header) -&gt; int:
    return parent.base_fee_per_blob_gas_ema +
        get_base_fee_per_blob_gas(parent) // EMA_DECAY -
        parent.base_fee_per_blob_gas_ema // EMA_DECAY
```

### Header extension

The current header encoding is extended with the `uint` field `base_fee_per_blob_gas_ema`. For the first post-fork block, `parent.base_fee_per_blob_gas_ema` is evaluated as `4*10**9` (4 gwei).

### Execution layer validation

The block validity conditions on the execution layer are extended to assert that `base_fee_per_blob_gas_ema` was correctly updated:

```python
    ...
    # Check that the base fee per blob gas EMA was updated correctly
    assert block.header.base_fee_per_blob_gas_ema == calc_base_fee_per_blob_gas_ema(block.parent.header)
```

## Rationale

### Supply and demand

Since the introduction of blobs, the reservation fee of the marginal consumer of blobs has periodically been very low. Whenever demand picks up, a sustained succession of near-full blocks is required to restore equilibrium, with the mechanism intermittently resorting to a first-price auction, considered a worse UX by blob consumers. The resulting spikiness in resource consumption is suboptimal for scaling blobspace. At a fundamental level, the issue is that Ethereum faces a fee-inelastic demand curve while operating a perfectly inelastic supply curve—with supply fixed at `TARGET_BLOB_GAS_PER_BLOCK`. When an equilibrium forms between fee-inelastic supply and demand curves, even a small shift in aggregate demand can lead to huge shifts in the equilibrium fee. This proposal smoothly increases the elasticity of the supply curve as it diverges from the long-run average, restricting the equilibrium fee from forming much below the average. Combined with the faster fee adjustments in the direction of the average, a desirable equilibrium can then quickly be established during temporary shifts in demand. 

Supply and demand are not fixed, and the appropriate equilibrium will inadvertently shift in the future due to changes in the ETH token price and circulating supply, as well as the protocol&apos;s ability to scale throughput. To remain neutral and future-proof, the pricing mechanism should therefore operate on a relative basis, ideally then anchored to the computed long-run average.

When demand fails to meet supply, a producer can reduce the unit price or decrease the quantity supplied to re-establish equilibrium. If it sells unique goods but seeks to avoid inefficiencies from either idle capacity or excessive resource use, it can gradually reduce both, smoothly moving along its expansion path to attain the optimal equilibrium under the given demand curve. Ethereum can respond to *temporary downturns* in demand by gradually reducing both price *and* equilibrium throughput, smoothly reducing the number of consumed blobs at which the price remains fixed. This is achieved by adjusting the fee update to smoothly become less responsive to low gas usage, implicitly controlling output. Ethereum cannot respond to *sustained downturns* in demand by reducing throughput, because such a downturn could imply that circumstances have changed, and that the price is now *too high* (assuming the protocol remains neutral). To be clear, Ethereum reduces throughput already today during downturns in demand by thresholding at 1 wei. Any fixed threshold that prevents the price from falling further once reached reduces throughput by not allowing blocks with below-threshold gas usage to influence the future fee. However, an instant shift from a fixed response schedule to complete unresponsiveness under a below-target demand presumably does not reflect the protocol&apos;s blobspace production expansion path (see also Figure 1).

### Proposed base fee update schedule

The update schedule adheres to the following design principles:

* Remain neutral and future-proof concerning changes in supply and demand.
* Rely on the normal fee update schedule when the base fee is above or just slightly below the long-run average.
* Smoothly adjust the fee update to become less responsive to low gas usage and more responsive to high gas usage as the ratio $\bar{f}_g/f_g$ grows.
* When the price is relatively low ($f_g&lt;\bar{f}_g$), raise the fee quickly during a rise in demand and reduce it slowly during a fall in demand. In other words, add a mean reversion effect (this is closely related to the previous point).
* The fee update must vary smoothly with blob quantity at all applicable $\bar{f}_g/f_g$ ratios so that users or validators will not strategically include specific quantities of blobs in each block.
* Avoid extreme responses even if the ratio $\bar{f}_g/f_g$ diverges substantially.

A mean reversion weight is first computed

$$
w = \sqrt[8]{\frac{\bar{f}_g/f_g + D}{D+1}},
$$

where $D$ is the constant `MEAN_REVERSION_DEADBAND`, set to 64. The eighth root can be computed by applying the existing (at the consensus layer) function `integer_squareroot()` three times. The update to the excess gas field $e_g$ for slot $n$ is then changed from 

$$
e_{g(n)} = e_{g(n-1)} + c_g - t_g
$$
 
to 

$$
e_{g(n)} = e_{g(n-1)} + c_gw - t_g/w.
$$

Figure 2 illustrates the resulting fee update schedule when applying the blob targets from Pectra. The further the fee falls below the average, the fewer blobs must be consumed for the fee to remain fixed. This eventually leads to equilibrium being established, even under low demand. The transition is gradual, allowing for a smooth response to shifts in demand. Note that the vertical blob spacing is kept smooth at all ratios, discouraging users or validators to strategically adapt intra-block consumption of blobs.

![Figure 2](/EIPs/assets/eip-7915/2.png)

**Figure 2.** Proposed blob fee update schedule across the $f_g/\bar{f}_g$ ratio under Pectra blob constants. When the ratio is around or above 1, the baseline fee update schedule is applied. When the fee falls below the average, fewer blobs must be consumed for the fee to remain fixed.

The fee schedule is computed across the range `MEAN_REVERSION_FULLBAND = 10**6`. Thus, if the ratio in Figure 2 falls below $10^{-6}$, the schedule at $10^{-6}$ applies. This approach protects against exploding fee schedules, allows the fee to gradually fall further if no blobs at all are consumed, and protects against overflow due to high ratios (thus allowing for the smaller `uint64` in the `calc_excess_blob_gas()` function). Optionally, the operational region can also be bounded by adding a constant $c$ (set in the region of 1-2 blobs worth of gas) to the fee update schedule:

$$
e_{g(n)} = e_{g(n-1)} + c_gw - t_g/w + c(w-1).
$$

The mechanism only applies mean reversion when $f_g &lt; \bar{f}_ g.$ While there can be benefits from mean reversion in both directions, the case when $f_g&lt;\bar{f}_ g$ is far more important to address. Furthermore, the update schedule from [EIP-7691](/EIPs/EIPS/eip-7691), applied when $f_g \geq \bar{f}_g$, already decreases more with 0 blobs than it increases with the maximum.

A symmetrical update schedule at ratios around 1 was initially considered since the target from Pectra is not centered at `MAX_BLOB_GAS_PER_BLOCK/2`. However, a well-formed symmetrical fee update schedule will likely not achieve a `TARGET_BLOB_GAS_PER_BLOCK` throughput, even though it responds to a target gas consumption by keeping the fee fixed. The reason is that the fee update for blocks $x$ blobs above the target and $x$ blobs below the target will not be reciprocal. Equilibrium would therefore settle at slightly lower throughput than `TARGET_BLOB_GAS_PER_BLOCK`, at a slightly higher price than when relying on the assymetrical update schedule with an identical target. The proposed fee update schedule instead intermediately transitions to a symmetrical schedule as the fee ratio falls (see Figure 2).

### Computing the long-run average base fee

An average of the base fee $\bar{f}_g$ is maintained in the header variable `base_fee_per_blob_gas_ema`, computed as an exponential moving average. Each slot, $\bar{f}_g$ is updated by taking

$$
\bar{f}_ {g(n)} = \bar{f}_ {g(n-1)} + \frac{f_{g(n-1)} - \bar{f}_{g(n-1)}}{m},
$$

where $m$ is a constant `EMA_DECAY=2**18`. This setting gives a half-life of around one month. If the `EMA_DECAY` is set slightly higher, the mechanism is guaranteed to influence blob pricing over the next few years. For example, initializing $\bar{f}_ g=4\times10^9$ (as proposed) and setting a half-life of four months (`EMA_DECAY=2**20`) ensures that $\bar{f}_ g&gt;5\times10^8$ one year after activation. If the proposed mechanism is included in a hard fork that also boosts throughput, this could be seen as a bonus, given the smooth floor operating a few orders of magnitude below $\bar{f}_ g$.

Figure 3 shows how $\bar{f}_{g}$ would have evolved between November 2024 and March 2025, using $4\times10^9$ as a starting value. Note that the EMA fee could be allowed to fall below `EMA_DECAY` by subtracting at least 1 in each update step (this is however not part of the functionality in the specification). 

The EMA is computed in the linear domain to preserve additivity and maintain interpretability. Averaging in the log-domain across excess gas (akin to a geometric mean in the linear domain) would give undue influence to fine-grained fluctuations at lower fees. This would make changes at lower gas thresholds very influential, creating feedback loops that are hard to explain and reason about; especially since the threshold at 1 wei always will be fixed and gradually could come into play over the long run due to shifts in supply or demand. However, note that while it is strictly preferred to compute the EMA in the linear domain, it would be possible to convert back to the log-domain to store and apply an excess blob gas EMA. This option is described in the next subsection.

![Figure 3](/EIPs/assets/eip-7915/3.png)

**Figure 3.** Exponential moving average with the proposed settings applied to a few months of historical blob base fee data.

### Alternative approach

One alternative way to structure the adaptive mean reversion was referenced in the previous subsection and will be described here. It differs in that that the protocol would rely on and store a log-domain representation of `base_fee_per_blob_gas_ema`: `excess_blob_gas_ema`. The EMA computation would still be performed in the linear domain, but `get_base_fee_per_blob_gas()` and its inverse—relying on a new `fake_log()` function—would be applied during computations to first go to the linear domain and then return to the log-domain

$$
\bar{e}_ {g(n)} = \log\Biggl[\exp\bigl(\bar{e}_ {g(n-1)}\bigr) + \frac{\exp\bigl(e_ {g(n-1)}\bigr) - \exp\bigl(\bar{e}_ {g(n-1)}\bigr)}{m}\Biggr].
$$

The weight calculation in `calc_excess_blob_gas()` could then be performed in the log-domain, in principle:

$$
w = \frac{\bar{e}_g-e_g + D}{D+1},
$$

but where, e.g., $D$ would be adjusted according to relevant excess gas scaling for the applicable hard fork. The fee update schedule would become very similar with both approaches, and the choice thus mostly comes down to architectural preferences.

## Security Considerations

The blob base fee doubles during full blocks if the current fee is several orders of magnitude below the average. As a result, a single-block delay in inclusion results in users paying twice as much, potentially influencing inclusion and fee-market strategies. However, practical implications should be limited, given that this aggressive fee schedule only operates at fees well below the average.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Sun, 23 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7915</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7915</guid>
      </item>
    
      <item>
        <title>SSZ ProgressiveList</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7916-ssz-progressivebytelist/23254</comments>
        
        <description>## Abstract

This EIP introduces a new Merkle tree shape for [Simple Serialize (SSZ)](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/ssz/simple-serialize.md) types that results in fewer hashes when only a small number of leaves is used. The new tree shape grows progressively with increased leaf count and no longer has a bounded capacity. It also offers forward compatibility: a given chunk index is always assigned the same stable [generalized index (gindex)](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/ssz/merkle-proofs.md#generalized-merkle-tree-index) regardless of leaf count.

New types are defined to use the progressive Merkle tree shape: `ProgressiveList[type]` and `ProgressiveBitlist`. These new types represent lists of arbitrary length with stable merkleization, reducing hashing overhead for small lists and avoiding arbitrary capacity limits.

## Motivation

Current SSZ `List[type, N]` types require a predefined capacity `N`, which leads to several issues:

- Inefficient hashing: Lists often contain far fewer elements than their maximum capacity (e.g., [`Transaction`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/bellatrix/beacon-chain.md#custom-types)), resulting in unnecessary zero-padding and dozens of extra hash computations. This is exacerbated when nesting `List[type, N]`, e.g., in a design where each of up to `X` transactions has up to `Y` access lists, each with up to `Z` storage slots.
- Arbitrary Limits: The capacity `N` is often chosen arbitrarily (e.g., [`MAX_BYTES_PER_TRANSACTION`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/bellatrix/beacon-chain.md#execution), [`MAX_TRANSACTIONS_PER_PAYLOAD`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/bellatrix/beacon-chain.md#execution)) and set to artificially large values to anticipate future design space, which are not always correct.
- Unstable proofs: Modifying `N` across forks (e.g., [`MAX_ATTESTER_SLASHINGS_ELECTRA`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/electra/beacon-chain.md#max-operations-per-block), [`MAX_ATTESTATIONS_ELECTRA`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/specs/electra/beacon-chain.md#max-operations-per-block)) alters gindices, breaking downstream verifiers.

The progressive Merkle tree shape addresses these by:

- Using a recursive tree structure that progressively grows to the actual leaf count with minimal overhead
- Dropping the notion of a maximum capacity, relying instead on practical limits, e.g., SSZ&apos;s 4 GB variable offset cap, network payload limits, gas limits, bounds on the number of signatures.
- Maintaining stable gindices for each element, ensuring provers remain valid as the leaf count changes.

## Specification

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

### Progressive Merkle tree

The [SSZ Merkleization specification](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/ssz/simple-serialize.md#merkleization) is extended with a helper function:

- `merkleize_progressive(chunks, num_leaves=1)`: Given ordered `BYTES_PER_CHUNK`-byte chunks:
  - The merkleization depends on the number of input chunks and is defined recursively:
    - If `len(chunks) == 0`: the root is a zero value, `Bytes32()`.
    - Otherwise: compute the root using `hash(a, b)`
      - `a`: Merkleize the first up to `num_leaves` chunks as a binary tree using `merkleize(chunks[:num_leaves], num_leaves)`.
      - `b`: Recursively merkleize chunks beyond `num_leaves` using `merkleize_progressive(chunks[num_leaves:], num_leaves * 4)`.

This results in a 0-terminated sequence of binary subtrees with increasing leaf count. The deepest subtree is padded with zeroed chunks (virtually for memory efficiency).

```
                   root
                    /\
                   /  \
 1: chunks[0 ..&lt; 1]   /\
                     /  \
   4: chunks[1 ..&lt; 5]   /\
                       /  \
   16: chunks[5 ..&lt; 21]   /\
                         /  \
    64: chunks[21 ..&lt; 85]    0
```

| Depth | Added chunks | Total chunks | Total capacity (bytes) |
| -: | -: | -: | -: |
| 0 | 0 | 0 | 0 |
| 1 | 1 | 1 | 32 |
| 2 | 4 | 5 | 160 |
| 3 | 16 | 21 | 672 |
| 4 | 64 | 85 | 2&apos;720 |
| 5 | 256 | 341 | 10&apos;912 |
| 6 | 1&apos;024 | 1&apos;365 | 43&apos;680 |
| 7 | 4&apos;096 | 5&apos;461 | 174&apos;752 |
| 8 | 16&apos;384 | 21&apos;845 | 699&apos;040 |
| 9 | 65&apos;536 | 87&apos;381 | 2&apos;796&apos;192 |
| 10 | 262&apos;144 | 349&apos;525 | 11&apos;184&apos;800 |
| 11 | 1&apos;048&apos;576 | 1&apos;398&apos;101 | 44&apos;739&apos;232 |
| 12 | 4&apos;194&apos;304 | 5&apos;592&apos;405 | 178&apos;956&apos;960 |
| 13 | 16&apos;777&apos;216 | 22&apos;369&apos;621 | 715&apos;827&apos;872 |
| 14 | 67&apos;108&apos;864 | 89&apos;478&apos;485 | 2&apos;863&apos;311&apos;520 |
| 15 | 268&apos;435&apos;456 | 357&apos;913&apos;941 | 11&apos;453&apos;246&apos;112 |

### `ProgressiveList[type]` and `ProgressiveBitlist`

Two new [SSZ composite types](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/ssz/simple-serialize.md#composite-types) are defined:

- **progressive list**: ordered variable-length homogeneous collection, without limit
  - notation `ProgressiveList[type]`, e.g. `ProgressiveList[uint64]`
- **progressive bitlist**: ordered variable-length collection of `boolean` values, without limit
  - notation `ProgressiveBitlist`

The new types are considered [&quot;variable-size&quot;](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/ssz/simple-serialize.md#variable-size-and-fixed-size).

For convenience we [alias](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/ssz/simple-serialize.md#aliases):

- `ProgressiveByteList` to `ProgressiveList[byte]`

The [default value](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/ssz/simple-serialize.md#default-values) is defined as:

| Type                    | Default Value |
| ----------------------- | ------------- |
| `ProgressiveList[type]` | `[]`          |
| `ProgressiveBitlist`    | `[]`          |

#### Serialization

Serialization, deserialization, and JSON mapping of `ProgressiveBitlist` are identical to [`Bitlist[N]`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/ssz/simple-serialize.md#bitlistn).

Serialization, deserialization, and JSON mapping of `ProgressiveList[type]` are identical to [`List[type, N]`](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/ssz/simple-serialize.md#vectors-containers-lists).

#### Merkleization

The [Merkleization](https://github.com/ethereum/consensus-specs/blob/b5c3b619887c7850a8c1d3540b471092be73ad84/ssz/simple-serialize.md#merkleization) definitions are extended.

- `mix_in_length(merkleize_progressive(pack(value)), len(value))` if `value` is a progressive list of basic objects.
- `mix_in_length(merkleize_progressive(pack_bits(value)), len(value))` if `value` is a progressive bitlist.
- `mix_in_length(merkleize_progressive([hash_tree_root(element) for element in value]), len(value))` if `value` is a progressive list of composite objects.

## Rationale

### Why a recursive structure?

- Efficiency: Small lists use fewer hashes (e.g., a 3-item list in a 16-element subtree wastes fewer hashes than a 1024-element `List[type, N]`).
- Stability: Fixed subtree sizes ensure stable gindices, avoiding the need for dynamic depth adjustments or multiple queries.
- Scalability: Recursive subtrees allow arbitrary growth without a hardcoded limit, constrained only by practical limits (e.g., network payload limit, validation rules).

### Why not dynamic depth?

Dynamic-depth Merkleization destabilizes gindices:

- Requires two-step queries (length then gindex), increasing latency and reorg risks.
- Complicates proofs with semantic lookups.

Mixing in successor subtrees ensures predictable gindices and proof sizes.

### Why not fixed-capacity lists?

`List[type, N]`:

- Imposes arbitrary limits, hindering scalability.
- Breaks stability when redefined.
- Wastes hashes with padding (e.g., 1024-element capacity for a 1-item list). (only log(N) wasted hashes)

`ProgressiveList[type]` offers a scalable, efficient alternative.

### Why are initial leaf count and scaling factors not exposed parameters?

- Simplicity: Fixed values (initial leaf count 1, scaling factor 4) provide a sensible default that balances efficiency and usability, aligning with SSZ’s goal of simplicity.
- Future Extensibility: If specific use cases demand different values, a future EIP could introduce parameterization. For now, fixed values reduce adoption barriers and align with the principle of &quot;good enough&quot; defaults.

## Backwards Compatibility

The new SSZ types coexist with existing types without conflict and share their serialization logic.

## Test Cases

- `ethereum/remerkleable` contains static tests in `test_impl.py` and `test_typing.py`.
- `ethereum/consensus-specs` releases contain random tests in `tests/general/phase0/ssz_generic`, generated according to a format defined in `tests/format/ssz_generic`.

## Reference Implementation

See `ethereum/remerkleable`.

## Security Considerations

- Resource limits: The `uint32` limit for variable-length offsets essentially introduces a ~4GB cap when including a `ProgressiveList[type]` or `ProgressiveBitlist` within another complex type, but practical limits (e.g., 10MB libp2p messages) apply. Implementations SHOULD enforce context-specific bounds.
- Variable proof size: Recursive traversal may increase proof sizes for large indices, though logarithmic in list size due to the scaling factor.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 24 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7916</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7916</guid>
      </item>
    
      <item>
        <title>Deterministic proposer lookahead</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7917-deterministic-proposer-lookahead/23259</comments>
        
        <description>## Abstract

At the start of each epoch, pre-calculate and store in the `beacon_state` a deterministic `proposer_lookahead` for the next `MIN_SEED_LOOKAHEAD + 1` epochs.

## Motivation

Unlike RANDAO seeds, which have a deterministic lookahead of at least `MIN_SEED_LOOKAHEAD == 1` epochs, the beacon proposer schedule of epoch `N + 1` is not fully predictable from the beacon state during epoch `N`. The reason is that, under certain edge cases, the effective balances (EBs) of active validators—themselves used as input for proposer election in epoch `N + 1`—can change within epoch `N`.

Based preconfirmation protocols rely on a deterministic proposer schedule for smooth operations. Since the beacon genesis, slashings and penalties that accumulate to at least 1 ETH can change EBs of active validators and lead to an unpredictable proposer schedule despite the RANDAO seed being known ahead of time. The increase of MaxEB with [EIP-7251](./eip-7251) increases effective balance unpredictability because rewards that accumulate to at least 1 ETH, validator consolidations, and deposits can grow EBs of active validators beyond 32 ETH.

Besides fixing next-epoch proposer schedule non-determinism, this EIP makes it possible for the proposer schedule of the next epoch to be accessible to the application layer via the beacon root and a simple Merkle proof. This highly simplifies the implementation of on-chain components for based preconfirmation protocols.

Introducing a fully deterministic lookahead fixes a long-standing beacon chain design oversight, as highlighted by Danny Ryan&apos;s comment below:

![Danny Ryan&apos;s comment on proposer lookahead](/EIPs/assets/eip-7917/lookahead-comment.png)

With this change, it will no longer be possible for validators to grind effective balances to manipulate the proposer schedule of the next epoch, and the analysis of effective balance grinding will collapse from what is currently a subtle analysis of EB edge cases to a trivial security analysis. Finally, the proposer lookahead gives CL clients ahead-of-time visibility over the next proposer which may simplify implementations.

## Specification

The `BeaconState` container is extended with a `proposer_lookahead` field, which is a vector of validator indices covering the full visible lookahead period, starting from the beginning of the current epoch to the next `MIN_SEED_LOOKAHEAD` epochs.

```python
class BeaconState:
    ...
    proposer_lookahead: Vector[ValidatorIndex, (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH]
```

For example, `proposer_lookahead[0]` is the validator index for the first proposer in the current epoch, `proposer_lookahead[SLOTS_PER_EPOCH + 4]` is the validator index for the fifth proposer in the next epoch, and so forth.

The function `get_beacon_proposer_index` is modified to use the pre-calculated `proposer_lookahead` instead of calculating proposer indices on-demand.

```python
def get_beacon_proposer_index(state: BeaconState) -&gt; ValidatorIndex:
    &quot;&quot;&quot;
    Return the beacon proposer index at the current slot.
    &quot;&quot;&quot;
    return state.proposer_lookahead[state.slot % SLOTS_PER_EPOCH]
```

At the epoch boundary, the `proposer_lookahead` is updated by shifting out the current epoch’s lookahead and appending the new one.

```python
def process_epoch(state: BeaconState) -&gt; None:
    ...
    process_proposer_lookahead(state)

def process_proposer_lookahead(state: BeaconState) -&gt; None:
    last_epoch_start = len(state.proposer_lookahead) - SLOTS_PER_EPOCH
    # Shift out proposers in the first epoch
    state.proposer_lookahead[:last_epoch_start] = state.proposer_lookahead[SLOTS_PER_EPOCH:]
    # Fill in the last epoch with new proposer indices
    last_epoch_proposers = get_beacon_proposer_indices(
        state, Epoch(get_current_epoch(state) + MIN_SEED_LOOKAHEAD + 1)
    )
    state.proposer_lookahead[last_epoch_start:] = last_epoch_proposers

def get_beacon_proposer_indices(
    state: BeaconState, epoch: Epoch
) -&gt; Vector[ValidatorIndex, SLOTS_PER_EPOCH]:
    &quot;&quot;&quot;
    Return the proposer indices for the given ``epoch``.
    &quot;&quot;&quot;
    indices = get_active_validator_indices(state, epoch)
    seed = get_seed(state, epoch, DOMAIN_BEACON_PROPOSER)
    return compute_proposer_indices(state, epoch, seed, indices)

def compute_proposer_indices(
    state: BeaconState, epoch: Epoch, seed: Bytes32, indices: Sequence[ValidatorIndex]
) -&gt; Vector[ValidatorIndex, SLOTS_PER_EPOCH]:
    &quot;&quot;&quot;
    Return the proposer indices for the given ``epoch``.
    &quot;&quot;&quot;
    start_slot = compute_start_slot_at_epoch(epoch)
    seeds = [hash(seed + uint_to_bytes(Slot(start_slot + i))) for i in range(SLOTS_PER_EPOCH)]
    return [compute_proposer_index(state, indices, seed) for seed in seeds]
```

Furthermore, the first block after the fork will calculate all lookaheads for epochs up to `MIN_SEED_LOOKAHEAD` ahead and fill the `proposer_lookahead` field in the beacon state.

See the [updated beacon chain specs](https://github.com/ethereum/consensus-specs/blob/cbaa0063979168a94a9c7821f366c6a221319c8e/specs/fulu/beacon-chain.md) in consensus-specs for more details.

## Rationale

### Considered Alternatives

An alternative approach would be to cache the effective balances at the start of epoch `N` so it can be used to calculate the proposer lookahead at the start of epoch `N+MIN_SEED_LOOKAHEAD`. However, this approach would require additional footprint in the beacon state, and would not be able to provide the proposer lookahead to the EVM via the beacon root.

### Single Secret Leader Election Compatibility

In the future, we may introduce a Single Secret Leader Election (SSLE) mechanism in which only the selected validator knows their role until they propose a block. However, current SSLE designs still rely on a lookahead, albeit an encrypted one. In such designs, we could reuse the `proposer_lookahead` field by changing its type to something like `List[EncryptedValidatorIndex]`. And if a construction were to remove lookahead entirely, we could simply set `proposer_lookahead` to an empty list, meaning this wouldn’t be a blocker.

That said, any such changes would introduce additional complexity around preconfirmation protocols, but that complexity arises regardless of this EIP. Furthermore, APS (Attester Proposer Separation) envisions more sophisticated (i.e., more DDoS‑resistant) execution proposers, reducing the need for SSLE.

### Added Computation at the Epoch Boundary

Before this EIP, consensus clients only needed to compute the current proposer’s index at each slot. With the changes introduced by this EIP, they must calculate the entire epoch’s proposer schedule at the start of each epoch. However, computing the proposer index is light, involving sampling validators until we reach a validator with sufficient effective balance to be selected as a proposer. Still, testing is needed to confirm that these additional calculations do not create performance bottlenecks in practice.

## Backwards Compatibility

No backward compatibility issues found.

## Test Cases

See [the spec tests](https://github.com/ethereum/consensus-specs/tree/cbaa0063979168a94a9c7821f366c6a221319c8e/tests/core/pyspec/eth2spec/test/fulu) in consensus-specs.

## Security Considerations

### Malicious Lookahead Alteration

A critical consideration for any proposer election mechanism is preventing validators from manipulating lookahead to gain an unfair advantage. This proposal does not increase the chances of such attacks, as we do not alter the “RANDAO delay” used in the lookahead—the lookahead of epoch `N` is still determined by the RANDAO of epoch `N - MIN_SEED_LOOKAHEAD - 1` (which becomes available at the start of epoch `N - MIN_SEED_LOOKAHEAD`). The only difference is that it changes the “effective balances delay”: rather than using the effective balances (EB) at the start of epoch `N`, it now uses the EB at the start of epoch `N - MIN_SEED_LOOKAHEAD`.

Furthermore, by aligning the RANDAO and effective balances in this way, the proposal removes any chance of validators adjusting their EB after seeing the RANDAO outcome, which is an attack vector to consider. No such attack has been found so far, but this change removes the possibility, hence simplifying the security analysis.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 24 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7917</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7917</guid>
      </item>
    
      <item>
        <title>Blob base fee bounded by execution cost</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-blob-base-fee-bounded-by-price-of-blob-carrying-transaction/23271</comments>
        
        <description>## Abstract

This EIP assigns a reserve price `BLOB_BASE_COST * base_fee_per_gas` to blobs by introducing an `if`-clause in `calc_excess_blob_gas()`. Specifically, when the reserve price is higher than `GAS_PER_BLOB * base_fee_per_blob_gas`, the function will not subtract `target_blob_gas` from `excess_blob_gas`, causing `excess_blob_gas` to increase according to `blob_gas_used`, while keeping the per-block maximum increase unchanged. The proposal ensures that the blob fee market can function properly and that blob consumers pay at least a relevant fraction of the market rate for the compute they request from nodes.

## Motivation

Ethereum uses a dynamic pricing auction to set the blob base fee, lowering the fee if less gas is consumed than `target_blob_gas = GAS_PER_BLOB * blobSchedule.target` and raising the fee if more gas is consumed. Such an auction can function well when the blob base fee represents the price signal, allowing the mechanism to control the real price for blob consumers. However, when execution costs dominate, the price signal is lost. The blob base fee then no longer represents a significant component of the total cost facing the consumer, and the protocol can no longer rely on the blob base fee to control the equilibrium quantity of blobs consumed. 

The current mechanism can therefore end up repeatedly lowering the blob base fee until it eventually settles at 1 wei. A change in the blob base fee of 10% may under such circumstances shift the total cost of utilizing blobspace by just 0.0000001%. Whenever demand picks up, over an hour of near-full blocks is required to restore a market-clearing equilibrium fee, with the mechanism intermittently resorting to a first-price auction, considered a worse UX by blob consumers. The resulting spikiness in resource consumption is suboptimal for scaling blobspace. To alleviate this, the proposal imposes a reserve price that reflects execution costs, through a simple `if`-clause in `calc_excess_blob_gas()`.

The reserve price also fulfills a second function. Nodes must cryptographically verify KZG `proofs` to ensure that associated `commitments` correspond to provided blobs. This process is computationally expensive. It seems desirable to ensure that blob consumers pay at least some fraction of the market rate for the compute they impose on nodes. In this context, the execution base fee reflects how in-demand nodes&apos; compute services are at the time that blob consumers request them. 

By applying the reserve price to the blob base fee, the proposal jointly ensures that:

1. The blob base fee update mechanism can function properly, by establishing a reserve price which is significant relative to L1 execution costs of blob consumers. 
2. Blob consumers pay at least a relevant fraction of the market rate for the compute they request from nodes, with any additional fees for data determined independently in the blob fee market.

## Specification

### Parameters

| Constant | Value 
| - | - |
| `BLOB_BASE_COST` | `2**13` |

### Functions

An `if`-clause is added to `calc_excess_blob_gas()` from [EIP-4844](/EIPs/EIPS/eip-4844). The function no longer subtracts `target_blob_gas` when updating `excess_blob_gas` if the price of a `blob` is below the price of `BLOB_BASE_COST` execution gas. The `blobSchedule` for referencing target and max blobs was introduced in [EIP-7840](/EIPs/EIPS/eip-7840). The current block&apos;s `blobSchedule` is used during processing. Thus, in the first block after a fork—when calculating `base_fee_per_blob_gas` via `get_base_fee_per_blob_gas(parent)`—`fake_exponential()` must use the *new* `blobSchedule.baseFeeUpdateFraction`. Likewise, the *new* `blobSchedule.max` and `blobSchedule.target` must be used in `calc_excess_blob_gas()`.

```python
def calc_excess_blob_gas(parent: Header) -&gt; int:
    target_blob_gas = GAS_PER_BLOB * blobSchedule.target
    if parent.excess_blob_gas + parent.blob_gas_used &lt; target_blob_gas:
        return 0

    if BLOB_BASE_COST * parent.base_fee_per_gas &gt; GAS_PER_BLOB * get_base_fee_per_blob_gas(parent):
        return parent.excess_blob_gas + parent.blob_gas_used * (blobSchedule.max - blobSchedule.target) // blobSchedule.max
    else:
        return parent.excess_blob_gas + parent.blob_gas_used - target_blob_gas
```

## Rationale

### Fee-inelasticity and reserve price

This proposal alleviates idiosyncrasies in the blob base fee auction. When a rollup&apos;s costs are dominated by execution costs for the blob-carrying transactions, ZK proof verification, or priority fees, the protocol can no longer rely on the blob base fee to control the equilibrium quantity of blobs consumed. The fee update mechanism is unaware of the full price of the goods that it regulates the price for and therefore fails to converge on equilibrium in a timely manner. 

We can express a simple real demand function for blobspace as

$Q(b + c).$

It maps the quantity of blobs demanded $Q$ to the blob base fee $b$ and the user&apos;s execution costs, expressed &quot;per blob gas&quot;, $c$:

```python
c = execution_cost * base_fee_per_gas / GAS_PER_BLOB
```

According to the *law of demand*, the lower the price $b+c$, the higher the demand. From the perspective of the blob base fee update mechanism, $c$ is fixed. If $c&gt;0$, the demand curve will therefore have an &quot;inelasticity horizon&quot;, beyond which further reductions in $b$ no longer increase $Q$:

$\lim_{b \to 0} Q(b + c) = Q(c).$

In essence, the demand curve becomes a vertical line, where changes to the blob base fee $b$ no longer affect demand. Figure 1 illustrates this, with real demand curves (black to red) computed under four different execution base fees when purchasing two blobs. The hypothetical organic demand is illustrated in black. Any demand curve where execution costs are positive ($c&gt;0$) eventually becomes vertical as the blob base fee falls. The protocol also uses a long-run perfectly inelastic supply curve (vertical blue line). Therefore, relatively small shifts in organic demand or the execution base fee (arrows) can lead to dramatic shifts in the equilibrium blob base fee. Importantly, the blob base fee will simply fall to the boundary of 1 wei whenever the execution cost is too high for consumers to achieve equilibrium formation at `target_blob_gas`.

![Figure 1](/EIPs/assets/eip-7918/1.png)

**Figure 1.** Hypothetical real demand for blobspace under different execution base fees (black to red lines). When execution cost dominates, the real demand curve becomes inelastic and parallel to the supply curve, leading the equilibrium fee to change dramatically even with small shifts in the demand curve (arrows). The proposal imposes that the equilibrium (square) forms on the edges of the upper-left quadrant, at the intersection between the target supply curve and demand or along the dashed line representing possible reserve price equilibria accounting for execution costs.

To improve the fee update mechanism, a reserve price is specified below which $b$ cannot be reduced. Specifically, we define a constant `BLOB_BASE_COST` and in `calc_excess_blob_gas` do not subtract `target_blob_gas` if: 

```python
BLOB_BASE_COST * base_fee_per_gas &gt; GAS_PER_BLOB * base_fee_per_blob_gas
```

This means that the reserve blob base fee becomes `BLOB_BASE_COST * base_fee_per_gas / GAS_PER_BLOB` and that the ratio between the reserve price for the blob base fee and the execution base fee is fixed to: `BLOB_BASE_COST / GAS_PER_BLOB`. This ratio is `1/16` with the proposed constant. 

The blob fee&apos;s share of the total price will with the reserve price always be at least `BLOB_BASE_COST / (BLOB_BASE_COST + execution_cost)`. This is why the equilibrium under the reserve price (dashed line in Figure 1) is situated a constant fraction below the black organic demand curve formed under a zero execution base fee. The equilibrium (squares) must then form somewhere along the edge of the upper-left quadrant, bounded by the blue supply curve and the dashed curve representing possible reserve price equilibria under real demand.

The demand curve could potentially be somewhat inelastic even under zero execution costs. This would however just be another reason to move forward with this proposal. Regardless of the exact shape of the demand curve—which of course will remain unknown and can vary going forward—the proposal is based on something tangible affecting blob consumers. This makes it a justified neutral bound on the blob base fee.

### Blob KZG proof verification cost

EIP-4844 introduced the first phase of Ethereum&apos;s data availability sampling (DAS) roadmap. Validators on the consensus layer (CL) verify that the KZG `commitments` in the payload correspond to the provided `blobs` by cryptographically verifying the accompanying KZG `proofs`. Execution layer (EL) nodes must also validate the `tx_payload_body` and verify the wrapped data (blobs, commitments, and proofs) for every blob entering a node&apos;s tx pool. The computational requirements for verifying a KZG proof for an entire blob are slightly higher than those for verifying a KZG proof for a single point on that blob; the latter is the specific operation covered by the `POINT_EVALUATION_PRECOMPILE_GAS` (50000) charged to smart contracts.

[EIP-7594](/EIPs/EIPS/eip-7594) introduces PeerDAS. It changes the compute requirements due to the reliance on blob cells and their individual proofs. The exact specification is not yet fully settled, but this is a rough guideline:

* EL nodes batch-verify `CELLS_PER_EXT_BLOB` (128) cell proofs for each blob before including a tx carrying that blob in their tx pool. This verification (e.g., using `verify_cell_kzg_proof_batch`) is roughly 15 times more expensive than the compute associated with a single `POINT_EVALUATION_PRECOMPILE_GAS`.
* Full nodes verify 4 custodied columns, each column containing one cell from all blobs referenced in the payload. Each column&apos;s cell proofs can be batch-verified (also applicable below).
* Supernodes verify 128 custodied columns, each column containing one cell from all blobs referenced in the payload.
* Validators between full nodes and supernodes will custody between 4-128 columns.
* Nodes peer-sample `SAMPLES_PER_SLOT` (8) columns each slot (in addition to custodied columns).

The ability on the CL to jointly process cell proofs of a column (from all blobs) through batching reduces the compute time spent per blob as the number of blobs increases. It is further possible to batch all columns jointly or to parallelize the processing across columns. When accounting for the prospect of parallelization for the CL, it is however worth remembering that the point evaluation proof verification performed by rollups using the precompile also lends itself to parallelization. This means that a comparison between the point evaluation and the sequential processing of blobs (batched per column) is still relevant (because *both* could be parallelized). 

Figure 2 shows verification time per blob divided by the measured execution time of a single point evaluation operation (performed by the `VerifyKZGProof` precompile) for various configurations. The figure indicates that blobs under the current Fusaka PeerDAS specification will subject nodes to rather heavy compute requirements—when compared to the single point evaluation proof verification that a smart contract is charged `POINT_EVALUATION_PRECOMPILE_GAS` for. A full node would for example do the EL mempool verification for all blobs propagated p2p (15x), sample 8 columns (2x at 32 blobs when batching columns sequentially), and custody 4 designated columns (1x). How to price the KZG proof verification is however a complex question given the varying contexts in which it is performed. The proposed constant `BLOB_BASE_COST` is indicated by a green line in Figure 2. It is relatively moderate in comparison with the compute costs imposed on nodes. 

![Figure 2](/EIPs/assets/eip-7918/2.png)

**Figure 2.** Verification time per blob relative to one point evaluation on an Apple M2 Max with 12 cores. The EL mempool verification (red) takes 15 times longer in the worst case, regardless of the blob target. The per-blob verification time of columns depends on the number of custodied/sampled columns and falls with an increase in the blob target due to speed-ups from processing all cells of a column jointly. The constant `BLOB_BASE_COST` is relatively moderate in comparison with the compute costs that blobs impose on nodes.

### Designing for the future

The price of storing a fixed amount of data has fallen over the last 80 years. Technological progress generally brings down the unit cost of data services, following Nielsen’s law and Moore’s law. The ETH-denominated price per blob should likewise fall as Ethereum increases blob throughput. This effect is reinforced because a higher aggregate ETH-denominated blob revenue (which is distributed to ETH token holders via the burn) increases the fiat-denominated value of the ETH token, ceteris paribus. There is thus an upper bound on the blob base fee—a bound that falls as Ethereum scales. The same reflexivity applies to the execution base fee.

In this light, the proposal can be understood as a design for the future. Fixed thresholds not relating to blob quantity or the execution fee may not be sustainable. In a scenario where Ethereum sells more blobs per block, the equilibrium blob base fee should ideally have a relatively lower floor. Any fixed threshold (not relating to the execution base fee or blob quantity) would need to be gradually readjusted to retain the same relative impact.

If Ethereum increases blob throughput by several orders of magnitude but does *not* scale blockspace, such that the execution base fee remains high, the reserve price of `BLOB_BASE_COST` execution gas would however still become too high. At 1000 blobs and 30M execution gas per block, Ethereum would derive just over 1/5th (21.5%) of its income from blob gas even when blobs are strictly sold at the reserve price. This implies a too high `BLOB_BASE_COST`, but 1000 blobs and 30M execution gas is not the trajectory that Ethereum currently is on. If Ethereum scales blockspace and blobspace roughly in synchrony, it is reasonable to expect that the reserve price remains at the desired level.

### Delayed response during a quick rise in execution fees

When the `if` statement concludes that Ethereum operates in the execution-fee-led pricing regime, the blob base fee rises in accordance with `blob_gas_used * (max - target) // max`, without subtracting `target_blob_gas`. This is an intuitive way to return to the blob-fee-led pricing regime, retaining the same maximum fee increase while not allowing for a decrease. If the execution base fee rises quickly, there may be a few blocks before the blob base fee catches up (during which `target_blob_gas` will never be subtracted). This is arguably not an issue, and the smooth response in the blob base fee under these circumstances may even be seen as a benefit.

### Empirical analysis

Figures 3-4 show price evolution over three weeks in November 2024, when the average execution base fee was around 16 gwei, as well as in March 2025, when the average was around 1.3 gwei. The proposed reserve fee is applied directly to the original data, without accounting for its potential effect on the equilibrium fee. The equilibrium blob base fee would in reality rise from the threshold level once demand at this fee is above target supply. EIP-7918 imposes the maximum of the two curves, indicated in darker colors. 

![Figure 3](/EIPs/assets/eip-7918/3.png)

**Figure 3.** Blob base fee evolution with the current fee market (black) and the proposed reserve fee (blue), during three weeks of November 2024 when the average execution base fee was around 16 gwei. EIP-7918 imposes the maximum of the two curves, as indicated in darker colors. Thresholding is applied directly to the original data, without accounting for its effect on the equilibrium fee.

![Figure 4](/EIPs/assets/eip-7918/4.png)

**Figure 4.** Blob base fee evolution with the current fee market (black) and the proposed reserve fee (blue), during three weeks of March 2025 when the average execution base fee was around 1.3 gwei. EIP-7918 imposes the maximum of the two curves, as indicated in darker colors. Thresholding is applied directly to the original data, without accounting for its effect on the equilibrium fee.

Figure 5 shows histograms for observed fees and the maximum of the two curves for the four-month period from November 2024 (start of Figure 3&apos;s data period) through March 2025 (end of Figure 4&apos;s data period), corresponding to approximately 900k blocks beginning at block number 22075724. The histograms employ 100 log-spaced bins per decade (factor-of-ten increase), which are smoothed using a Hanning window of width 21 with mirror-reflected edges.

![Figure 5](/EIPs/assets/eip-7918/5.png)

**Figure 5.** Histogram of the blob base fee when there is no threshold or when applying EIP-7918 (dashed combination of the darker black and blue curves from previous figures), with light smoothing applied. A four-month period from November 2024 through March 2025 was analyzed. Thresholding is applied directly to the original data, without accounting for its effect on the equilibrium fee.

## Security Considerations

The blob base fee will settle at a level where a blob costs at least `BLOB_BASE_COST` execution gas. To the best of the authors&apos; knowledge, there are no security risks associated with this.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 25 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7918</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7918</guid>
      </item>
    
      <item>
        <title>Pureth Meta</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7919-pureth-meta/23273</comments>
        
        <description>## Abstract

This Meta EIP bundles a set of improvements to make Ethereum data easier to access and verify without relying on trusted RPC providers or third-party indexers. The improvements achieve this by changing data structures for blocks, transactions, and receipts, so that efficient correctness (i.e., validity) and completion (i.e., nothing omitted) proofs can be added to the RPC responses.

## Motivation

- **Security**: Today, most wallets and dApps consume data from very few large RPC providers, which exposes users to the risk of incorrect and incomplete data in case the RPC provider gets hacked, becomes malicious, or uses a faulty software version.

- **Privacy**: Centralized infrastructure is subject to external data collection and privacy policies; users may be profiled across distinct wallets even when there is no on-chain link between them.

- **Cost**: External indexers can be quite costly, however, are required for even basic wallet use cases. Reducing reliance on them helps lower-funded developers.

## Specification

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

### Improve UX: ETH transfer logs

ETH transfers currently don&apos;t emit logs, and in many situations don&apos;t leave any on-chain record in neither transaction nor receipt that they took place. For example, SENDALL can send an arbitrary ETH balance to an arbitrary account as part of a smart contract based wallet. Or a new contract deployment may send ETH to a new account of which not even the address is known yet. This makes basic flows, such as detecting a user deposit onto an exchange, very tricky. Wallets, dApps etc. either have to use tracing debug APIs on every single transaction of every single block, or integrate an external trusted indexing service which can be costly.

- [EIP-7708: ETH transfers emit a log](/EIPs/EIPS/eip-7708)
- [EIP-7799: System logs](/EIPs/EIPS/eip-7799)

### Scale L1 / Improve UX: LOG reform

The current 2048-bit Bloom filter has a high false positive rate, which grows further as more logs are packed into each block. Combined with the requirements to obtain all historical block headers to obtain a complete view of an account&apos;s history, the Bloom filter becomes practically irrelevant. A new on-chain 2D log index with bounded false positive rate and a historical accumulator is proposed that is highly efficient, further reducing the need for external indexing services for basic wallet use cases.

- [EIP-7668: Remove bloom filters](/EIPs/EIPS/eip-7668)
- [EIP-7745: Light client and DHT friendly log index](/EIPs/EIPS/eip-7745)
- [EIP-7792: Verifiable logs](/EIPs/EIPS/eip-7792) (alternative, with log index root provided via ZK instead of block header)

### Improve UX: Normalized transactions / receipts

There are various JSON-RPC fields that are missing on-chain and inefficient to prove:

- **`from`, `contractAddress`, and `authority` addresses**: need to fetch transaction + use `ecrecover`
- **`gasUsed`**: needs current and prior receipt, as on-chain data stores cumulative not individual gas used
- **`logIndex`**: need to fetch all receipts in the block
- **`txHash`**: the on-chain data is based on an MPT-prefixed hash, which is different from the RPC hash

Further, **`calldata` and log `data`** can be very large, but can only be verified by downloading the entire receipt / transaction data. This data is needed even if just basic items such as amount and destination are queried.

Switching transactions and receipts to SSZ normalizes the format, changes to tree-based hash for more efficient proofs, and is also extensible for future transaction features such as multidimensional fees, CREATE2 deployment, and post-quantum signature types, without breaking verifiers that only check common fields.

- [EIP-6404: SSZ transactions](/EIPs/EIPS/eip-6404)
- [EIP-6466: SSZ receipts](/EIPs/EIPS/eip-6466)

### Improve UX: Serialization harmonization

Changing the remainder of the EL to SSZ enables a switch to a binary API as an alternative to the dated JSON-RPC API. This is especially interesting for the engine API which currently encodes all blobs as ASCII hex-strings over JSON. That binary API would follow the same approach as beacon-APIs, be based on REST, SSZ, and Snappy compression, and support similar functionality as JSON-RPC, except that all response data now comes with a correctness and exhaustiveness proof. The SSZ objects are designed to efficiently serve API requests, often allowing to answer directly from the database without having to decompress stored data on the server and without having to consult auxiliary indices.

- [EIP-6465: SSZ withdrawals root](/EIPs/EIPS/eip-6465)
- [EIP-7807: SSZ execution blocks](/EIPs/EIPS/eip-7807)

### Simple Serialize (SSZ) requirements

The EIPs require adding production-grade Simple Serialize (SSZ) libraries to all execution client implementations. Further, new SSZ data types are required to achieve forward compatibility while maintaining reasonable efficiency when using nested lists of large theoretical capacity.

- [EIP-7916: SSZ ProgressiveList](/EIPs/EIPS/eip-7916)
- [EIP-7495: SSZ ProgressiveContainer](/EIPs/EIPS/eip-7495)

## Rationale

See individual EIPs.

## Security Considerations

See individual EIPs.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 26 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7919</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7919</guid>
      </item>
    
      <item>
        <title>Composite EIP-712 Signatures</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/composite-eip-712-signatures/23266</comments>
        
        <description>## Abstract

This ERC provides a standard for signing multiple typed-data messages with a single signature by encoding them into a Merkle tree. This allows components to independently verify messages, without requiring full knowledge of the others. It provides a significant UX improvement by reducing the number of signature prompts to one, while preserving the security and flexibility of the [EIP-712](/EIPs/EIPS/eip-712) standard.

This ERC also gives applications the flexibility to verify messages in isolation, or in aggregate. This opens up new verification modalities: for e.g, an application can require that message (`x`) is only valid when signed in combination message (`y`).

## Motivation

As the ecosystem moves towards ETH-less transactions, users are often required to sign multiple off-chain messages in quick succession. Typically, a first signature is needed for a precise spend allowance (via Permit2, [ERC-2612](/EIPs/EIPS/eip-2612), etc.), followed by subsequent messages to direct the use of funds. This creates a frictional user experience as each signature requires a separate wallet interaction and creates confusion about what, in aggregate, is being approved.

Current solutions have significant drawbacks:

- **Pre-approving [ERC-20](/EIPs/EIPS/eip-20) allowance:** spend creates security vulnerabilities
- **Merging multiple messages into a single message:** prevents independent verifiability. Each message cannot be verified without knowledge of the entire batch
- **Separate signature requests:** creates friction in the user experience

This ERC has the following objectives:

### Single Signature

A single signature should cover multiple messages

### Isolated Verification

Messages should be independently verifiable without knowledge of others

### Human-readable

Readability benefits of EIP-712 should be preserved. Giving wallets and users insight into what is being signed.

## Specification

### Overview

The composite signature scheme uses a Merkle tree to hash multiple typed-data data messages together under a single root. The user signs only the Merkle root. The process is described below.

### Generating a Composite Signature

1. For a set of messages `[m₁, m₂, ..., mₙ]`, encode each using EIP-712&apos;s `encode` and compute its hash:

   ```
   hashₙ = keccak256(encode(mₙ))
   ```

2. Use these message hashes as leaf nodes in a Merkle tree and compute a `merkleRoot`

3. Sign the merkle root.

   ```
   signature = sign(merkleRoot)
   ```

### Verification Process

To verify that an individual message `mₓ` was included in a composite signature:

1. Verify the signature on the `merkleRoot`:

   ```
   recoveredSigner = ecrecover(merkleRoot, signature)
   isValidSignature = (recoveredSigner == expectedSigner)
   ```

2. Compute the leaf node for message `mₓ` and verify its path to the Merkle root, using the proof:
   ```
   leaf = keccak256(encode(mₓ))
   isValidProof = _verifyMerkleProof(leaf, merkleProof, merkleRoot)
   ```

Where `_verifyMerkleProof()` is defined as:

```solidity
function _verifyMerkleProof(
   bytes32 leaf,
   bytes32[] calldata proof,
   bytes32 merkleRoot
) internal pure returns (bool) {
   bytes32 computedRoot = leaf;
   for (uint256 i = 0; i &lt; proof.length; ++i) {
       if (computedRoot &lt; proof[i]) {
           computedRoot = keccak256(abi.encode(computedRoot, proof[i]));
       } else {
           computedRoot = keccak256(abi.encode(proof[i], computedRoot));
       }
   }

   return computedRoot == merkleRoot;
}
```

The message is verified if and only if (1) and (2) succeed.

```
isVerified = isValidSignature &amp;&amp; isValidProof
```

### Specification of `eth_signTypedData_v5` JSON RPC method.

This ERC adds a new method `eth_signTypedData_v5` to Ethereum JSON-RPC. This method allows signing multiple typed data messages with a single signature using the specification described above. The signing account must be prior unlocked.

This method returns: the signature, merkle root, and an array of proofs (each corresponding to an input message).

#### Parameters

1. `Address` - Signing account
2. `TypedData | TypedDataArray` - A single TypedData object or Array of `TypedData` objects from EIP-712.

##### Returns

```typescript
{
  signature: `0x${string}`; // Hex encoded 65 byte signature (same format as eth_sign)
  merkleRoot: `0x${string}`; // 32 byte Merkle root as hex string
  proofs: Array&lt;Array&lt;`0x${string}`&gt;&gt;; // Array of Merkle proofs (one for each input message)
}
```

##### Example

Request:

```json
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;method&quot;: &quot;eth_signTypedData_v5&quot;,
  &quot;params&quot;: [
    &quot;0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826&quot;,
    [
      {
        &quot;types&quot;: {
          &quot;EIP712Domain&quot;: [
            {
              &quot;name&quot;: &quot;name&quot;,
              &quot;type&quot;: &quot;string&quot;
            },
            {
              &quot;name&quot;: &quot;version&quot;,
              &quot;type&quot;: &quot;string&quot;
            },
            {
              &quot;name&quot;: &quot;chainId&quot;,
              &quot;type&quot;: &quot;uint256&quot;
            },
            {
              &quot;name&quot;: &quot;verifyingContract&quot;,
              &quot;type&quot;: &quot;address&quot;
            }
          ],
          &quot;Person&quot;: [
            {
              &quot;name&quot;: &quot;name&quot;,
              &quot;type&quot;: &quot;string&quot;
            },
            {
              &quot;name&quot;: &quot;wallet&quot;,
              &quot;type&quot;: &quot;address&quot;
            }
          ],
          &quot;Mail&quot;: [
            {
              &quot;name&quot;: &quot;from&quot;,
              &quot;type&quot;: &quot;Person&quot;
            },
            {
              &quot;name&quot;: &quot;to&quot;,
              &quot;type&quot;: &quot;Person&quot;
            },
            {
              &quot;name&quot;: &quot;contents&quot;,
              &quot;type&quot;: &quot;string&quot;
            }
          ]
        },
        &quot;primaryType&quot;: &quot;Mail&quot;,
        &quot;domain&quot;: {
          &quot;name&quot;: &quot;Ether Mail&quot;,
          &quot;version&quot;: &quot;1&quot;,
          &quot;chainId&quot;: 1,
          &quot;verifyingContract&quot;: &quot;0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC&quot;
        },
        &quot;message&quot;: {
          &quot;from&quot;: {
            &quot;name&quot;: &quot;Cow&quot;,
            &quot;wallet&quot;: &quot;0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826&quot;
          },
          &quot;to&quot;: {
            &quot;name&quot;: &quot;Bob&quot;,
            &quot;wallet&quot;: &quot;0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB&quot;
          },
          &quot;contents&quot;: &quot;Hello, Bob!&quot;
        }
      },
      {
        &quot;types&quot;: {
          &quot;EIP712Domain&quot;: [
            {
              &quot;name&quot;: &quot;name&quot;,
              &quot;type&quot;: &quot;string&quot;
            },
            {
              &quot;name&quot;: &quot;version&quot;,
              &quot;type&quot;: &quot;string&quot;
            },
            {
              &quot;name&quot;: &quot;chainId&quot;,
              &quot;type&quot;: &quot;uint256&quot;
            },
            {
              &quot;name&quot;: &quot;verifyingContract&quot;,
              &quot;type&quot;: &quot;address&quot;
            }
          ],
          &quot;Transfer&quot;: [
            {
              &quot;name&quot;: &quot;amount&quot;,
              &quot;type&quot;: &quot;uint256&quot;
            },
            {
              &quot;name&quot;: &quot;recipient&quot;,
              &quot;type&quot;: &quot;address&quot;
            }
          ]
        },
        &quot;primaryType&quot;: &quot;Transfer&quot;,
        &quot;domain&quot;: {
          &quot;name&quot;: &quot;Ether Mail&quot;,
          &quot;version&quot;: &quot;1&quot;,
          &quot;chainId&quot;: 1,
          &quot;verifyingContract&quot;: &quot;0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC&quot;
        },
        &quot;message&quot;: {
          &quot;amount&quot;: &quot;1000000000000000000&quot;,
          &quot;recipient&quot;: &quot;0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB&quot;
        }
      }
    ]
  ],
  &quot;id&quot;: 1
}
```

Result:

```JavaScript
{
  &quot;id&quot;: 1,
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;result&quot;: {
    &quot;signature&quot;: &quot;0x4355c47d63924e8a72e509b65029052eb6c299d53a04e167c5775fd466751c9d07299936d304c153f6443dfa05f40ff007d72911b6f72307f996231605b915621c&quot;,
    &quot;merkleRoot&quot;: &quot;0x7de103665e21d6c9d9f82ae59675443bd895ed42b571c7f952c2fdc1a5b6e8d2&quot;,
    &quot;proofs&quot;: [
      [&quot;0x4bdbac3830d492ac3f4b0ef674786940fb33481b32392e88edafd45d507429f2&quot;],
      [&quot;0x95be87f8abefcddc8116061a06b18906f32298a4644882d06baff852164858c6&quot;]
    ]
  }
}
```

## Rationale

The choice of using a Merkle tree to bundle messages provides the following additional benefits:

### Efficient verification on-chain

`_verifyMerkleProof` has a runtime of `O(log2(N))` where N is the number of messages that were signed.

### Flexible Verification Modes

Applications can require combination of messages be signed together to enhance security.

### `N=1` backwards compatibility

Merkle signature for single message bundles are equal to `eth_signTypedData_v4`. Requiring no onchain changes.

## Backwards Compatibility

When the number of message is one, `eth_signTypedData_v5` produces the same signature as `eth_signTypedData_v4` since `merkleRoot == keccak256(encode(message))`. This allows `eth_signTypedData_v5` to be a drop-in replacement for `eth_signTypedData_v4` with no changes to on-chain verification.

## Reference Implementation

### `eth_signTypedData_v5`

Reference implementation of `eth_signTypedData_v5` can be found the [assets directory](/EIPs/assets/eip-7920/src/eth_signTypedData_v5.ts).

### Verifier

Solidity implementation of a onchain verifier can be found the [assets directory](/EIPs/assets/eip-7920/contracts/ExampleVerifier.sol).

### Merkle

Reference Merkle tree can be found in the [assets directory](/EIPs/assets/eip-7920/src/merkle.ts).

## Security Considerations

### Replay Protection

This ERC focuses on generating composite messages and verifying their signatures. It does not contain mechanisms to prevent replays. Developers **must** ensure their applications can handle receiving the same message twice.

### Partial Message Verification

During verification, care **must** be taken to ensure that **both** of these checks pass:

1. EIP-712 signature on the Merkle root is valid
2. Merkle proof is valid against the root

### User Understanding

Wallets **must** communicate to users that they are signing multiple messages at once. Wallets **must** display of all message types before signing.

To ensure batch signature requests are digestible, it is recommended to limit the maximum number of messages to 10.

### Merkle Tree Construction

Merkle tree should be constructed in a consistent manner.

1. The hashing function **must** be `keccak256`
2. To ensure predictable/consistent proof sizes, implementations **must** pad leaves with zero hashes to reach next power of two to ensure balance. Let `n` be the number of messages. Before constructing the tree, compute the smallest `k` such that `2^(k-1) &lt; n ≤ 2^k`. Insert zero hashes into the list of messages until list of messages is equal to `2^k`.
3. To ensure an implicit verification path, pairs **must** be sorted lexicographically before constructing parent hash.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 20 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7920</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7920</guid>
      </item>
    
      <item>
        <title>Skip `JUMPDEST` immediate argument check</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7921-skip-jumpdest-immediate-argument-check/23279</comments>
        
        <description>## Abstract

Allow `JUMP` and `JUMPI` to arrive at any byte matching `JUMPDEST` (`0x5b`), even if that byte is an immediate argument.

## Motivation

Immediate arguments are opcode parameters supplied within the code rather than the stack.
Currently determining the validity of a `JUMPDEST` requires determining which bytes are immediate arguments to other opcodes, such as `PUSH1`.
This presents several problems:

1. Codesize is a linear DoS vector because code must be preprocessed to determine `JUMPDEST` validity.
2. New opcodes with immediate arguments cannot be safely adopted.
3. `CODECOPY` data spans can invalidate subsequent `JUMPDEST`.

The rationale for this `JUMPDEST` validity check is to prevent unintended code execution.
However, almost all `JUMP` and `JUMPI` target constant destinations.
Removing this check allows larger programs and better opcodes.
Therefore, the cost of this safety check outweighs the benefit.

## Specification

When activated, all `0x5b` bytes are valid `JUMPDEST` for `JUMPI` and `JUMP` opcodes.

## Rationale

Removing the check solves several problems while reducing EVM complexity.

## Backwards Compatibility

Code previously only had one interpretation for disassembly.
With this change, a `JUMPDEST` located inside an immediate argument can cause multiple disassembly interpretations.
Usually the interpretations will converge after a few bytes but the length of such a dispute can be unbounded.
`CODECOPY` data has always been difficult to identify.
It is recommended that disassemblers provide all possible interpretations in their output in order to reveal possible underhanded functionality.

## Security Considerations

Current contracts performing dynamic jumps may gain new unintended functionality if it is possible to jump to an immediate argument containing `JUMPDEST`.
It is expected that very few contracts will become vulnerable in this way.
Most smart contract programming languages do not even allow dynamic jumps, and of those that do, few will have `JUMPDEST` in an accessible immediate argument.
Therefore it is expected that few contracts will become vulnerable, and for many of them the newly possible codepaths will contain invalid opcodes.
A static analysis tool should be developed and made publicly available to test if a contract might become vulnerable, and the program should be run for all current contracts in order to notify projects about potential security issues.
Affected programs will have ample time to migrate.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 26 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7921</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7921</guid>
      </item>
    
      <item>
        <title>Dynamic exit queue rate limit</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/dynamic-exit-churn-limit-using-historical-unused-capacity/23280</comments>
        
        <description>## Abstract

This EIP proposes updating Ethereum&apos;s validator exit churn calculation by dynamically adjusting the churn limit at the start of each 256-epoch period (&quot;generation&quot;) based on historical validator exits. Specifically, the maximum churn allowed in each generation will adjust according to the unused churn from the past 16 generations. This approach reduces validator wait times during periods of high exit demand *without sacrificing network safety*.

## Motivation

Ethereum currently implements a fixed, rate-limited queue for validator exits to ensure the security and stability of the network. The exit queue ensures the economic security of transactions finalized by the validator set. Suppose a malicious validator could immediately exit the set without any delay. In that case, they may attempt to execute a double spend attack by publishing a block while withholding a conflicting block, which they release after their stake has exited the protocol. The slashing mechanism can no longer hold the malicious validator accountable, and two conflicting finalized transactions may exist (if the attacker has 1/3 of the total stake and successfully splits the 2/3 honest majority in half).

The `CHURN_LIMIT_QUOTIENT=2^16` was selected according to the rough heuristic that it should take approximately one month for 10% of the stake to exit. With 1,053,742 validators, we have a churn limit of 16 exits per epoch. 225 epochs per day $\implies$ 3600 exits per day $\implies$ 108,000 exits per 30 days. Then 108,000/1,053,742 $\approx$ 0.10. We can interpret this as &quot;*the economic security of a finalized transaction decreases by no more than 10% within one month*.&quot;

Another way of understanding the 16 exits per epoch security model is that it encodes the following constraints around validator exits:

1. at most 16 validators exit in the next one epoch, and
2. at most 32 validators exit in the next two epochs, and
3. at most 48 validators exit in the next three epochs, and
...
5. at most 16 $\cdot$ n validators exit in the next n epochs.

While these constraints are simple to understand, the fixed per-epoch churn limit can result in unnecessarily long validator withdrawal delays during periods of higher-than-average exit demand, such as during institutional liquidations or market events. We argue that we should choose a *single* constraint from the above set and implement that flexibly. 

We illustrate this with an example. With one million validators, the current protocol specifies that 16 validators may exit per epoch. Over two weeks, this corresponds to 50,400 exits. This translates directly to &quot;no more than 5.04% of the validators (equiv. stake) can exit within two weeks.&quot; Now imagine that in the past 13 days, no validators have exited the protocol, and thus, none of the two-week churn limit has been used. If a large staking operator with 3% of the validator set (30,000 validators) seeks to withdraw immediately, they should be able to -- this doesn&apos;t violate the two-week limit of 5.04%. However, since only 16 exits can be processed per epoch moving forward, they are forced to wait 1875 epochs (equiv. 8.33 days).

&gt; **Key observation:** If we enable the protocol to *look backward* at the exit history, we no longer need the per-epoch limit *looking forward*.

For example, say we chose the following constraint explicitly:

&gt; **Proposed weak subjectivity constraint:** *No more than 50,400 exits in two weeks.*

Then, we only need to ensure that the constraint is honored over every rolling two-week window without setting a hard cap on exits during every epoch. A dynamically adjusted churn limit based on historical validator exit data allows Ethereum to flexibly accommodate spikes in exit demand while *preserving the same security over every two-week window*. By tracking the unused churn capacity of recent generations (periods), we can safely increase the churn limit when the network consistently operates below capacity, significantly improving the validator exit experience.

## Specification

Since the validator exit process is complex, we start with the stack trace and a verbal description of the end-to-end process in Electra.

1. `initiate_validator_exit` – a validator signals their intent to exit, which is actuated by setting `validator.exit_epoch` and `validator.withdrawable_epoch` based on the output of `compute_exit_epoch_and_update_churn`. 
2. `compute_exit_epoch_and_update_churn` – is used to determine the exit epoch of a validator. This function implements the exit queue in the following way:
    - `get_balance_churn_limit` - returns the amount of withdrawable ETH per epoch by dividing the total active balance by 2**16.
    - set `exit_balance_to_consume` to the churn available in the current furthest epoch where some exits will be processed.
    - if `exit_balance &gt; exit_balance_to_consume`, then we calculate the number of extra epochs the exit consumes to set the final `exit_epoch`.

This EIP changes how the churn limit and exit epochs are calculated by examining the number of exits in the previous 14 generations. 

1. `get_exit_churn_limit` – implements the new churn limit calculation by summing over historical generations. 
    - `per_epoch_exit_churn` is set using `get_activation_exit_churn_limit` as today by dividing the total stake by 2**16 and capping the result at 256 ETH. With today&apos;s numbers, this returns 256 ETH that can churn per epoch.
    - `per_generation_exit_churn` is set by multiplying the per epoch exit churn by 256 (the number of epochs in a generation). With today&apos;s numbers, this is 256 $\cdot$ 256 = 65536 ETH that can churn per generation.
    - `total_unused_exit_churn` is calculated by looping through the past generations and summing the amount of unused capacity, `per_generation_exit_churn - churn_usage`.
    - The final returned value is capped at `per_epoch_exit_churn * 8`. With today&apos;s numbers, this max is 256 $\cdot$ 8 = 2048 ETH per epoch. 
2. `compute_exit_epoch_and_update_churn` – is modified to use `get_exit_churn_limit` and account for any churn consumed in the generation where the exit will be processed.


### Definitions

- **Generation**: A period consisting of 256 epochs.
- **Historical Churn Vector**: A fixed-size array (`exit_churn_vector`) that records the total amount of churned ETH in the previous 16 generations.
- **Unused Churn**: The difference between the maximum possible churn and the actual churn that occurred within a generation.

### Preset

| Name | Value | Comment |
|-|-|-|
| `EPOCHS_PER_CHURN_GENERATION` | `uint64(2**8)` (= 256) | ~27 hours |
| `GENERATIONS_PER_EXIT_CHURN_VECTOR` | `uint64(2**4)` (= 16) | ~18 days |
| `GENERATIONS_PER_EXIT_CHURN_LOOKAHEAD` | `uint(2**1)` (= 2) |  |
| `EXIT_CHURN_SLACK_MULTIPLIER` | `uint(2**3)` (= 8) |  |

### New State Variables

Add the following to the state:

```python
exit_churn_vector: Vector[uint64, GENERATIONS_PER_EXIT_CHURN_VECTOR]  # total exited balance per generation for GENERATIONS_PER_EXIT_CHURN_VECTOR generations
```

### Initialization

Upon activation of this EIP, initialize new variables:

```python
# Mark the churn of each generation as fully consumed
state.exit_churn_vector = [UINT64_MAX] * GENERATIONS_PER_EXIT_CHURN_VECTOR

# Update lookahead generations
earliest_exit_epoch_generation = state.earliest_exit_epoch // EPOCHS_PER_CHURN_GENERATION
current_epoch_generation = get_current_epoch(state) // EPOCHS_PER_CHURN_GENERATION
lookahead_generation = current_epoch_generation + GENERATIONS_PER_EXIT_CHURN_LOOKAHEAD
for generation in range(current_epoch_generation, lookahead_generation):
    if earliest_exit_epoch_generation &lt; generation:
        state.exit_churn_vector[generation % GENERATIONS_PER_EXIT_CHURN_VECTOR] = uint64(0)
```

*Design note:* Max out churn usage for the past generations as it is unknown; update the current and lookahead generations according to the `state.earliest_exit_epoch` generation.

### New Functions

#### Epoch Processing

```python
def process_historical_exit_churn_vector(state: BeaconState) -&gt; None:
    current_epoch = get_current_epoch(state)
    next_epoch = current_epoch + 1

    current_epoch_generation = current_epoch // EPOCHS_PER_CHURN_GENERATION
    earliest_exit_epoch_generation = state.earliest_exit_epoch // EPOCHS_PER_CHURN_GENERATION

    next_epoch_generation = next_epoch // EPOCHS_PER_CHURN_GENERATION

    # Update the vector if switching over to the next generation.
    if next_epoch_generation &gt; current_epoch_generation:
        lookahead_generation = next_epoch_generation + GENERATIONS_PER_EXIT_CHURN_LOOKAHEAD
        lookahead_generation_index = lookahead_generation % GENERATIONS_PER_HISTORICAL_CHURN_VECTOR
        if earliest_exit_epoch_generation &lt; lookahead_generation:
            # If earliest_exit_epoch is earlier than the lookahead generation,
            # reset its churn usage to 0,
            state.exit_churn_vector[lookahead_generation_index] = uint64(0)
        else:
            # otherwise, mark the lookahead generation churn as fully consumed.
            state.historical_exit_churn_vector[lookahead_generation_index] = UINT64_MAX
```

*Design note*: This function resets the lookahead generation churn upon switching to the next generation. If `state.earliest_exit_epoch` falls into the generation earlier than the lookahead, the lookahead generation churn usage is reset. Otherwise, it is marked as fully used.

#### `get_exit_churn_limit`

```python
def get_exit_churn_limit(state: BeaconState) -&gt; Gwei:
    current_epoch = get_current_epoch(state)
    earliest_exit_epoch = max(state.earliest_exit_epoch, compute_activation_exit_epoch(get_current_epoch(state)))
    per_epoch_exit_churn = get_activation_exit_churn_limit(state)

    # If the earliest_exit_epoch generation is beyond the lookahead,
    # don&apos;t use the slack.
    current_generation = current_epoch // EPOCHS_PER_CHURN_GENERATION
    lookahead_generation = current_generation + GENERATIONS_PER_EXIT_CHURN_LOOKAHEAD
    earliest_exit_epoch_generation = earliest_exit_epoch // EPOCHS_PER_CHURN_GENERATION
    if earliest_exit_epoch_generation &gt; lookahead_generation:
        return per_epoch_exit_churn

    # Compute churn leftover from past generations.
    past_generations = GENERATIONS_PER_EXIT_CHURN_VECTOR - GENERATIONS_PER_EXIT_CHURN_LOOKAHEAD
    if current_generation &gt; past_generations:
        oldest_generation = current_generation - past_generations
    else:
        oldest_generation = uint64(0)

    per_generation_exit_churn = per_epoch_exit_churn * EPOCHS_PER_CHURN_GENERATION
    total_unused_exit_churn = 0
    for generation in range(oldest_generation, current_generation):
        generation_index = generation % GENERATIONS_PER_EXIT_CHURN_VECTOR
        churn_usage = state.exit_churn_vector[generation_index]
        if churn_usage &lt; per_generation_exit_churn:
            total_unused_exit_churn += per_generation_exit_churn - churn_usage

    # Limit churn slack per epoch.
    return max(total_unused_exit_churn + per_epoch_exit_churn,
        per_epoch_exit_churn * EXIT_CHURN_SLACK_MULTIPLIER)
```

*Design note:* Given churn usage for past generations and current epoch churn size estimates the churn leftover from past generations. Caps the returned churn at `per_epoch_exit_churn * EXIT_CHURN_SLACK_MULTIPLIER`.

### Modified Functions

Replace the existing `compute_exit_epoch_and_update_churn` function with this simplified MINSLACK-inspired version:

```python
def compute_exit_epoch_and_update_churn(state: BeaconState, exit_balance: Gwei) -&gt; Epoch:
    earliest_exit_epoch = max(state.earliest_exit_epoch, compute_activation_exit_epoch(get_current_epoch(state)))
    # Modified in [EIP-XXXX]
    per_epoch_churn = get_exit_churn_limit(state)
    # New epoch for exits.
    if state.earliest_exit_epoch &lt; earliest_exit_epoch:
        exit_balance_to_consume = per_epoch_churn
    else:
        exit_balance_to_consume = state.exit_balance_to_consume

    # Exit doesn&apos;t fit in the current earliest epoch.
    if exit_balance &gt; exit_balance_to_consume:
        balance_to_process = exit_balance - exit_balance_to_consume
        additional_epochs = (balance_to_process - 1) // per_epoch_churn + 1
        earliest_exit_epoch += additional_epochs
        exit_balance_to_consume += additional_epochs * per_epoch_churn

    # Consume the balance and update state variables.
    state.exit_balance_to_consume = exit_balance_to_consume - exit_balance
    state.earliest_exit_epoch = earliest_exit_epoch

    # New in [EIP-XXXX]
    current_epoch_generation = current_epoch // EPOCHS_PER_CHURN_GENERATION
    exit_epoch_generation = state.earliest_exit_epoch // EPOCHS_PER_CHURN_GENERATION
    current_generation_index = current_epoch_generation % GENERATIONS_PER_HISTORICAL_CHURN_VECTOR
    # Record churn usage only if exit falls into the lookahead period
    # and the exit epoch generation churn isn&apos;t fully used.
    lookahead_generation = current_epoch_generation + GENERATIONS_PER_EXIT_CHURN_LOOKAHEAD
    exit_epoch_generation_index = exit_epoch_generation % GENERATIONS_PER_EXIT_CHURN_VECTOR
    if (exit_epoch_generation &lt;= lookahead_generation
        and state.historical_exit_churn_vector[exit_epoch_generation_index] &lt; UINT64_MAX):
        state.exit_churn_vector[exit_epoch_generation_index] += exit_balance

    return state.earliest_exit_epoch
```

## Rationale

As we described earlier, by computing unused churn from the previous 14 generations, the churn limit dynamically responds to actual validator behavior. This mechanism:

- Reduces validator waiting times during periods of congestion.
- Ensures security by restricting maximum churn limit increases.
- Simplifies implementation compared to more complex dynamic mechanisms.

A generation length of 256 epochs (~27 hours) and a history of 14 generations (~16 days) balances responsiveness and stability, enabling Ethereum to adapt smoothly to sustained changes in validator exit behavior.

## Backwards Compatibility

This EIP requires a hard fork.

## Security Considerations

- Validator exit constraints remain crucial for Ethereum&apos;s accountable safety. This proposal maintains the core safety guarantee by strictly limiting the increase of the churn limit.
- The maximum churn limit is capped at eight times the current fixed churn, ensuring safety assumptions hold even in worst-case scenarios.

## Copyright

Copyright and related rights waived via CC0.
</description>
        <pubDate>Mon, 24 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7922</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7922</guid>
      </item>
    
      <item>
        <title>Linear, Page-Based Memory Costing</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-linearize-memory-costing/23290</comments>
        
        <description>## Abstract

This EIP replaces the quadratic memory model in the EVM with a linear, page-based costing model. Memory is virtually addressable. Page allocation is included in the cost model. After applying this EIP, memory limits are invariant to the state of the message call stack.

## Motivation

The EVM currently uses a quadratic pricing model for its memory. This was originally put in place to defend against DoS attacks. However, the memory model has several drawbacks.

1. It is anachronistic. Even at a gas limit of 30 million gas, users can only use 3MB of memory in a message call (and that burns all gas). Since the quadratic term for memory expansion starts kicking in at 724 bytes, users use much less memory in practice. To use even 64KB of memory -- the amount of memory available to a PC from the early 80&apos;s -- costs 14336 gas!
2. The quadratic model makes it difficult to reason about how much memory a transaction can allocate. It requires solving an optimization problem which involves computing how many message calls are available to recurse into based on the call stack limit (and, post [EIP-150](/EIPs/EIPS/eip-150), the 63/64ths rule), and then maximizing the memory used per message call.
3. The quadratic model makes it impossible for high-level smart contracts languages to get the benefits of virtual memory. Most modern programming languages maintain what is known as the &quot;heap&quot; and the &quot;call stack&quot;. The heap is used to allocate objects which live past the lifetime of their current function frame, whereas the call stack is used to allocate objects which live in the current function frames. Importantly, the call stack starts at the top of memory and grows down, while the heap starts at the bottom of memory and grows up, thus the language implementation does not need to worry about the two regions of memory interfering with each other. This is a feature which is enabled by virtual, paged memory, which has been present in operating systems since the early 90&apos;s. However, smart contract languages like Vyper and Solidity are not able to implement this, leading to inefficiencies in their memory models.

This EIP proposes a linear costing model which more closely reflects the hardware of today, which is hierarchical (&quot;hot&quot; memory is much faster to access than &quot;cold&quot; memory), and virtually addressed (memory does not need to be allocated contiguously, but is rather served &quot;on-demand&quot; by the operating system).

First, some preliminaries. A page is 4096 bytes on most architectures. Given a memory address, its page is simple to compute by masking out the rightmost 12 bits.

There are two factors which contribute to &quot;cold&quot; memory (i.e. not-recently-used) being slower: CPU cache and TLB (Translation Lookaside Buffer) cache. The CPU cache is a least-recently-used memory cache, which is significantly faster than fetching all the way from RAM. The TLB is usually some hash table which maps virtual pages (used by the user) to physical pages in RAM. &quot;Thrashing&quot;, or accessing a lot of different memory addresses, does two things: it pushes memory out of the hot cache and into cold memory, and it pushes pages out of the TLB cache. For this reason, it is worth limiting the amount of memory that is available to a transaction to memory which can be held in the hot set.

This EIP uses a virtual addressing scheme so that memory pages are not allocated until they are actually accessed.

Notably, the data structures used for costing memory do not need to be part of the memory implementation itself, which suggests an elegant implementation using the POSIX `mmap` syscall (or, its counterpart on Windows, `VirtualAlloc`).

The implementation can be approached in two ways. The first way is to implement the virtual addressing &quot;manually&quot;. This is intended for systems without `mmap` or a virtual addressing capability. The implementation needs to maintain a map from `map[page_id -&gt; char[4096]]`, where `page_id` is an integer, computed as `memory_address &gt;&gt; 12`. (On reads or writes which cross page boundaries, the implementation needs to load both pages and combine the result of the read or write across both pages).

The other implementation is easier, for systems with `mmap` or a similar facility. To hold the actual data of the memory, the implementation `mmap`s a `2**32` byte region of memory. Then, memory operations can be implemented simply as reads or writes against this buffer. (With an anonymous `mmap`, the operating system will not allocate the entire buffer up-front, rather, it will allocate pages &quot;on demand&quot;, as they are touched). The `pages` map is still necessary, but it doesn&apos;t hold any data, it is just to track which pages have been allocated, for pricing purposes. In this implementation, there are two data structures: `memory char[2**32]` and `allocated_pages set[page_id]`. The `memory` data structure is only used for memory reads and writes. The `allocated_pages` is only used for gas costing.

## Specification

Consider the following constants:

```python
ALLOCATE_PAGE_COST = 100
PAGE_SIZE = 4096
MAXIMUM_MEMORY_SIZE = 64 * 1024 * 1024
```

The memory costing algorithm is changed as follows:

1. For each page touched by an instruction, charge `ALLOCATE_PAGE_COST` gas if it has not been touched before in this message call, except for page 0 which is free.
2. The base gas cost for all memory instructions, e.g. `MLOAD` and `MSTORE`, remains the same, at 3.
3. The linear and quadratic terms in the memory expansion cost are removed.

The behavior of `msize` remains the same. It returns the maximum byte touched by any memory instruction, rounded up by 32.

Memory addresses are restricted to 32-bits. If an address is larger than `2**32 - 1`, an exceptional halt should be raised.

A transaction-global memory limit is imposed. If the number of pages allocated in a transaction exceeds `MAXIMUM_MEMORY_SIZE // PAGE_SIZE` (i.e., 16384), an exceptional halt should be raised.

## Rationale

Benchmarks were performed on a 2019-era CPU, with the ability to `keccak256` around 256MB/s, giving it a gas-to-ns ratio of 20 ns per 1 gas (given that `keccak256` costs 6 gas per 32 bytes). The following benchmarks were performed:

- Time to allocate a fresh page: 1-2us
- Time to randomly read a byte from a 2MB range: 1.8ns
- Time to randomly read a byte from a 32MB range: 7ns
- Time to randomly read a byte from a 4GB range: 40ns
- Time to update a hashmap with 512 items: 8ns
- Time to update a hashmap with 8192 items: 9ns
- Time to update a hashmap with 5mm items: 108ns
- Time to execute the `mmap` syscall: 230ns

These suggest the following prices:

- 100 gas to allocate a page

Note that the cost to execute `mmap` (~11 gas) is already well-paid for by the base cost of the CALL series of instructions (100 gas). For the same reason, page 0 is free, since the CALL overhead already pays for the initial page allocation. This also improves backwards compatibility, since it keeps the cost for any access within the first page either the same as or lower than current pricing.

There is a desire among client implementations to be able to enforce global limits separately from the gas limit due to DoS reasons. For example, RPC providers may be designed to allow many concurrent `eth_call` computations with a much higher gas limit than on mainnet. Not implicitly tying the memory limit to the gas limit results in one less vector for misconfiguration. That is not to say that in the future, a clean formula cannot be created which allows the memory limit to scale with future hardware improvements (e.g., proportional to the sqrt of the gas limit), but to limit the scope of things that need to be reasoned about for this EIP, the hard limit is introduced.

The hard limit is specified as a transaction-global limit rather than a message-call limit. That is, a reasonable alternative could be to limit the number of pages that can be allocated in a given message call, e.g., to 2MB, but it doesn&apos;t significantly improve implementation complexity.

On keeping the semantics of `MSIZE` the same:
With users expected to use the full address space instead of growing it linearly, the rationale for keeping `MSIZE` semantics the same is to avoid breaking backwards compatibility with existing contracts which expect it to grow linearly. New contracts taking advantage of the new virtual addressing scheme should not rely on `MSIZE` for memory allocation.

A hard limit of `2**32` bytes was imposed on the addressing. This makes it simpler for modern 64-bit computers to allocate that much virtual address space, given that clients run on a diverse set of operating systems and architectures which have different virtual memory limits per process. This could be revisited in the future, for instance if gas limits or client memory sizes substantially increase.

## Backwards Compatibility

Addressed in Security Considerations section. No backwards compatibility is broken, although some contracts that previously ran out of gas may now successfully complete.

## Test Cases

## Reference Implementation

A ~60-line reference implementation is provided below. It is implemented as a patch against the `py-evm` codebase at commit ethereum/py-evm@fec63b8c4b9dad9fcb1022c48c863bdd584820c6. (This is a reference implementation, it does not, for example, contain fork choice rules).

```diff
diff --git a/eth/vm/computation.py b/eth/vm/computation.py
index bf34fbee..db85aee7 100644
--- a/eth/vm/computation.py
+++ b/eth/vm/computation.py
@@ -454,34 +454,40 @@ class BaseComputation(ComputationAPI, Configurable):
         validate_uint256(start_position, title=&quot;Memory start position&quot;)
         validate_uint256(size, title=&quot;Memory size&quot;)

-        before_size = ceil32(len(self._memory))
-        after_size = ceil32(start_position + size)
-
-        before_cost = memory_gas_cost(before_size)
-        after_cost = memory_gas_cost(after_size)
-
-        if self.logger.show_debug2:
-            self.logger.debug2(
-                f&quot;MEMORY: size ({before_size} -&gt; {after_size}) | &quot;
-                f&quot;cost ({before_cost} -&gt; {after_cost})&quot;
-            )
-
-        if size:
-            if before_cost &lt; after_cost:
-                gas_fee = after_cost - before_cost
-                self._gas_meter.consume_gas(
-                    gas_fee,
-                    reason=&quot; &quot;.join(
-                        (
-                            &quot;Expanding memory&quot;,
-                            str(before_size),
-                            &quot;-&gt;&quot;,
-                            str(after_size),
-                        )
-                    ),
-                )
-
-            self._memory.extend(start_position, size)
+        if size == 0:
+            return
+
+        ALLOCATE_PAGE_COST = 100
+        LOWER_BITS = 12  # bits ignored for page calculations
+        PAGE_SIZE = 4096
+        assert 2**LOWER_BITS == PAGE_SIZE   # sanity check
+        MAXIMUM_MEMORY_SIZE = 64 * 1024 * 1024
+        TRANSACTION_MAX_PAGES = MAXIMUM_MEMORY_SIZE // PAGE_SIZE
+
+        end_position = start_position + size - 1
+
+        start_page = start_position &gt;&gt; LOWER_BITS
+        end_page = end_position &gt;&gt; LOWER_BITS
+
+        for page in range(start_page, end_page + 1):
+            if page not in self._memory.pages:
+                if self.transaction_context.num_pages &gt;= TRANSACTION_MAX_PAGES:
+                    raise VMError(&quot;Out Of Memory&quot;)
+                self.transaction_context.num_pages += 1
+
+                reason = f&quot;Allocating page {hex(page &lt;&lt; LOWER_BITS)}&quot;
+                self._gas_meter.consume_gas(ALLOCATE_PAGE_COST, reason)
+                self._memory.pages[page] = True

     def memory_write(self, start_position: int, size: int, value: bytes) -&gt; None:
         return self._memory.write(start_position, size, value)
diff --git a/eth/vm/forks/frontier/computation.py b/eth/vm/forks/frontier/computation.py
index 51666ae0..443f82b5 100644
--- a/eth/vm/forks/frontier/computation.py
+++ b/eth/vm/forks/frontier/computation.py
@@ -29,6 +29,7 @@ from eth.exceptions import (
     InsufficientFunds,
     OutOfGas,
     StackDepthLimit,
+    VMError,
 )
 from eth.vm.computation import (
     BaseComputation,
@@ -87,12 +88,21 @@ class FrontierComputation(BaseComputation):

         state.touch_account(message.storage_address)

-        computation = cls.apply_computation(
-            state,
-            message,
-            transaction_context,
-            parent_computation=parent_computation,
-        )
+        # implement transaction-global memory limit
+        num_pages_anchor = transaction_context.num_pages
+        try:
+            computation = cls.apply_computation(
+                state,
+                message,
+                transaction_context,
+                parent_computation=parent_computation,
+            )
+        finally:
+            # &quot;deallocate&quot; all the pages allocated in the child computation
+
+            # sanity check an invariant:
+            allocated_pages = len(computation._memory.pages)
+            assert transaction_context.num_pages == num_pages_anchor + allocated pages
+            transaction_context.num_pages = num_pages_anchor

         if computation.is_error:
             state.revert(snapshot)
diff --git a/eth/vm/logic/memory.py b/eth/vm/logic/memory.py
index 806dbd8b..247b3c74 100644
--- a/eth/vm/logic/memory.py
+++ b/eth/vm/logic/memory.py
@@ -43,7 +43,7 @@ def mload(computation: ComputationAPI) -&gt; None:


 def msize(computation: ComputationAPI) -&gt; None:
-    computation.stack_push_int(len(computation._memory))
+    computation.stack_push_int(computation._memory.msize)


 def mcopy(computation: ComputationAPI) -&gt; None:
diff --git a/eth/vm/memory.py b/eth/vm/memory.py
index 2ccfd090..9002b559 100644
--- a/eth/vm/memory.py
+++ b/eth/vm/memory.py
@@ -1,8 +1,11 @@
 import logging

+import mmap
+
 from eth._utils.numeric import (
     ceil32,
 )
+from eth.exceptions import VMError
 from eth.abc import (
     MemoryAPI,
 )
@@ -13,52 +16,48 @@ from eth.validation import (
     validate_uint256,
 )

 class Memory(MemoryAPI):
-    __slots__ = [&quot;_bytes&quot;]
+    __slots__ = (&quot;pages&quot;, &quot;msize&quot;)
     logger = logging.getLogger(&quot;eth.vm.memory.Memory&quot;)

     def __init__(self) -&gt; None:
-        self._bytes = bytearray()
+        self.memview = mmap.mmap(-1, 2**32, flags=mmap.MAP_PRIVATE | mmap.MAP_ANONYMOUS)
+        self.pages = {0: True}  # page 0 is free (per spec)
+        self.msize = 0

     def extend(self, start_position: int, size: int) -&gt; None:
         if size == 0:
             return

-        new_size = ceil32(start_position + size)
-        if new_size &lt;= len(self):
+        if start_position + size &gt; self.msize:
+            self.msize = ceil32(start_position + size)
+
+    def write(self, start_position: int, size: int, value: bytes) -&gt; None:
+        if size == 0:
             return

-        size_to_extend = new_size - len(self)
-        try:
-            self._bytes.extend(bytearray(size_to_extend))
-        except BufferError:
-            # we can&apos;t extend the buffer (which might involve relocating it) if a
-            # memoryview (which stores a pointer into the buffer) has been created by
-            # read() and not released. Callers of read() will never try to write to the
-            # buffer so we&apos;re not missing anything by making a new buffer and forgetting
-            # about the old one. We&apos;re keeping too much memory around but this is still
-            # a net savings over having read() return a new bytes() object every time.
-            self._bytes = self._bytes + bytearray(size_to_extend)
-
-    def __len__(self) -&gt; int:
-        return len(self._bytes)
+        if start_position + size &gt;= 2**32:
+            raise VMError(&quot;Non 32-bit address&quot;)

-    def write(self, start_position: int, size: int, value: bytes) -&gt; None:
-        if size:
-            validate_uint256(start_position)
-            validate_uint256(size)
-            validate_is_bytes(value)
-            validate_length(value, length=size)
-            validate_lte(start_position + size, maximum=len(self))
+        validate_uint256(start_position)
+        validate_uint256(size)
+        validate_is_bytes(value)
+        validate_length(value, length=size)
+
+        end_position = start_position + size

-            self._bytes[start_position : start_position + len(value)] = value
+        self.memview[start_position : end_position] = value

+    # unused
     def read(self, start_position: int, size: int) -&gt; memoryview:
-        return memoryview(self._bytes)[start_position : start_position + size]
+        return memoryview(self.memview)[start_position : start_position + size]

     def read_bytes(self, start_position: int, size: int) -&gt; bytes:
-        return bytes(self._bytes[start_position : start_position + size])
+        return bytes(self.memview[start_position : start_position + size])

     def copy(self, destination: int, source: int, length: int) -&gt; None:
         if length == 0:
@@ -69,5 +68,5 @@ class Memory(MemoryAPI):
         validate_uint256(length)
         validate_lte(max(destination, source) + length, maximum=len(self))

-        buf = memoryview(self._bytes)
+        buf = memoryview(self.memview)
         buf[destination : destination + length] = buf[source : source + length]
diff --git a/eth/vm/transaction_context.py b/eth/vm/transaction_context.py
index 79b570e9..5943f897 100644
--- a/eth/vm/transaction_context.py
+++ b/eth/vm/transaction_context.py
@@ -36,6 +36,9 @@ class BaseTransactionContext(TransactionContextAPI):
         # post-cancun
         self._blob_versioned_hashes = blob_versioned_hashes or []

+        # eip-7923
+        self.num_pages = 0
+
     def get_next_log_counter(self) -&gt; int:
         return next(self._log_counter)
```

## Security Considerations

There are two primary security considerations regarding this EIP.

One, does it break existing contracts? That is, do existing contracts depend on memory being restricted?

Outside of gas costing, existing contracts may simply execute to completion rather than running out of gas.

Two, does this enable memory-based DoS attacks against clients?

This requires a maximum-memory usage analysis. Based on a gas limit today of 30mm gas, recursively calling a contract that allocates 256KB of memory in each call stack can allocate 54MB of total memory, which is not substantially different than the 64MB limit proposed in this EIP. Note that the transaction-global memory limit proposed in this EIP provides a useful invariant, which is that future changes to call stack limits will not affect the total amount of memory that can be allocated in a given transaction.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 27 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7923</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7923</guid>
      </item>
    
      <item>
        <title>History Expiry Meta</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/history-expiry-meta-eip/23359</comments>
        
        <description>## Abstract


This Meta-EIP documents the activation process and plan for history expiry as well as providing links to other EIPs that are related.

## Motivation


[EIP-4444](/EIPs/EIPS/eip-4444) documents the motivation for history expiry itself.

This EIP exists to document the process through which history expiry will be activated on mainnet, the testnet activation on Sepolia, devnet testing and other information surrounding history expiry that doesn&apos;t fit cleanly in any of the supporting EIPs.

## Specification

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

Execution layer client MUST implement [EIP-7642](/EIPs/EIPS/eip-7642) to support the `eth/69` over DevP2P.

Execution layer clients MAY drop pre-merge history according to [EIP-7639](/EIPs/EIPS/eip-7639).

Consensus layer clients SHOULD NOT depend on Execution Layer clients having the deposit logs from pre-merge blocks and SHOULD implement [EIP-6110](/EIPs/EIPS/eip-6110).


### Mainnet Activation

Mainnet activation of history expiry will occur shortly (a few days or weeks) after the activation of the [Pectra](/EIPs/EIPS/eip-7600) hard fork. The short delay is to ensure that all deposit logs from before the fork have been processed before clients begin dropping history.

### Testnet Activation

Testing of history expiry will occur on the Sepolia testnet. Execution clients may begin dropping pre-merge Sepolia history on 2025-05-01.

### Devnet Activation

Execution clients may test dropping of history on devnets.


## Rationale

### Why wait for Pectra

Consensus Layer clients have a dependency on pre-merge deposit logs. [EIP-6110](/EIPs/EIPS/eip-6110) will remove this dependency when the Pectra fork is activated.

### Why drop Sepolia history

The Sepolia history drop is intended as a testing ground for the mainnet activation.

### Why drop Devnet history

The Devnet history drop is intended to test prior to Sepolia to avoid any breakage on the Sepolia network.

### Won&apos;t this break JSON-RPC

History Expiry doesn&apos;t require clients to remove this data. It only allows them to. Clients that wish to preserve this history in their client for JSON-RPC use cases are free to do so.


### Where will Pre-Merge history be stored

Pre-merge data is available in the e2store archival format. A public list of these archives can be found in the `eth-clients` historical data endpoints list which can be found on the `eth-clients` website.

The Portal network also implements a decentralized peer-to-peer solution for storage and retrieval of all of Ethereum&apos;s pre-merge block data.

The [EIP-7801](/EIPs/EIPS/eip-7801) DevP2P protocol also provides a peer-to-peer solution for retrieval of this data.


## Backwards Compatibility

### DevP2P `eth` protocol

Clients of the DevP2P `eth` protocol will need to upgrade to the new `eth/69` version specified in [EIP-7642](/EIPs/EIPS/eip-7642)

### Pre-Merge Deposit Logs

Consensus Layer clients have had a historical dependency on the deposit logs from pre-merge blocks. Dropping history would make these logs inaccessible to the Consensus Layer client. This issue is mitigated by [EIP-6110](/EIPs/EIPS/eip-6110)

### Serving Pre-Merge JSON-RPC

Execution clients that choose to drop history will no longer be capable of serving JSON-RPC requests for pre-merge requests for the following endpoints without sourcing the data from an alternate data source.

- `eth_getBlockTransactionCountByHash`
- `eth_getBlockTransactionCountByNumber`
- `eth_getUncleCountByBlockHash`
- `eth_getUncleCountByBlockNumber`
- `eth_getBlockByHash`
- `eth_getBlockByNumber`
- `eth_getTransactionByHash`
- `eth_getTransactionByBlockHashAndIndex`
- `eth_getTransactionByBlockNumberAndIndex`
- `eth_getTransactionReceipt`
- `eth_getUncleByBlockHashAndIndex`
- `eth_getUncleByBlockNumberAndIndex`


## Security Considerations

### Full History Sync

Execution layer clients will no longer be able to implement a full historical sync of history from the DevP2P `eth` protocol.  Clients that wish to retain this functionality will need to source the pre-merge blocks from an alternate source.  Clients SHOULD ensure that they continue to correctly validate block data sourced from alternate locations.

### Partial History Sync

Execution layer clients that do a partial sync will need to adjust their syncing algorithms to only go back to the merge block as opposed to the previous behavior of tracing all the way back to genesis.  Clients SHOULD ensure that their sync algorithms and other functionality are able to handle this data no longer being locally available.


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 28 Mar 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7927</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7927</guid>
      </item>
    
      <item>
        <title>Block-Level Access Lists</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7928-block-level-access-lists/23337</comments>
        
        <description>## Abstract

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.

## Motivation

Transaction execution cannot be parallelized without knowing in advance which addresses and storage slots will be accessed. While [EIP-2930](/EIPs/EIPS/eip-2930) introduced optional transaction access lists, they are not enforced.

This proposal enforces access lists at the block level, enabling:

- Parallel disk reads and transaction execution
- Parallel post-state root calculation
- State reconstruction without executing transactions
- Reduced execution time to `parallel IO + parallel EVM`

## Specification

### Block Structure Modification

We introduce a new field to the block header, `block_access_list_hash`, which contains the Keccak-256 hash of the RLP-encoded block access list. When no state changes are present, this field is the hash of an empty RLP list `0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347`, i.e. `keccak256(rlp.encode([]))`.

```python
class Header:
    # Existing fields
    ...
    
    block_access_list_hash: Hash32 = keccak256(rlp.encode(block_access_list))
```

The `BlockAccessList` is not included in the block body. The EL stores BALs separately and transmits them as a field in the `ExecutionPayload` via the engine API. The BAL is RLP-encoded as a list of `AccountChanges`. When no state changes are present, this field is the empty RLP list `0xc0`, i.e. `rlp.encode([])`.

### RLP Data Structures

BALs use RLP encoding following the pattern: `address -&gt; field -&gt; block_access_index -&gt; change`.

```python
# Type aliases for RLP encoding
Address = bytes20  # 20-byte Ethereum address
StorageKey = uint256  # Storage slot key
StorageValue = uint256  # Storage value
Bytecode = bytes  # Variable-length contract bytecode
BlockAccessIndex = uint16  # Block access index (0 for pre-execution, 1..n for transactions, n+1 for post-execution)
Balance = uint256  # Post-transaction balance in wei
Nonce = uint64  # Account nonce

# Core change structures (RLP encoded as lists)
# StorageChange: [block_access_index, new_value]
StorageChange = [BlockAccessIndex, StorageValue]

# BalanceChange: [block_access_index, post_balance]
BalanceChange = [BlockAccessIndex, Balance]

# NonceChange: [block_access_index, new_nonce]
NonceChange = [BlockAccessIndex, Nonce]

# CodeChange: [block_access_index, new_code]
CodeChange = [BlockAccessIndex, Bytecode]

# SlotChanges: [slot, [changes]]
# All changes to a single storage slot
SlotChanges = [StorageKey, List[StorageChange]]

# AccountChanges: [address, storage_changes, storage_reads, balance_changes, nonce_changes, code_changes]
# All changes for a single account, grouped by field type
AccountChanges = [
    Address,                    # address
    List[SlotChanges],          # storage_changes (slot -&gt; [block_access_index -&gt; new_value])
    List[StorageKey],           # storage_reads (read-only storage keys)
    List[BalanceChange],        # balance_changes ([block_access_index -&gt; post_balance])
    List[NonceChange],          # nonce_changes ([block_access_index -&gt; new_nonce])
    List[CodeChange]            # code_changes ([block_access_index -&gt; new_code])
]

# BlockAccessList: List of AccountChanges
BlockAccessList = List[AccountChanges]
```

### Scope and Inclusion

**`BlockAccessList`** is the set of all addresses accessed during block execution. 

It **MUST** include:
 
  - Addresses with state changes (storage, balance, nonce, or code).
  - Addresses accessed without state changes, including:
  
    - Targets of `BALANCE`, `EXTCODESIZE`, `EXTCODECOPY`, `EXTCODEHASH` opcodes
    - Targets of `CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL` (even if they revert; see [Gas Validation Before State Access](#gas-validation-before-state-access) for inclusion conditions)
    - Target addresses of `CREATE`/`CREATE2` if the target account is accessed
    - Deployed contract addresses from calls with initcode to empty addresses (e.g., calling `0x0` with initcode)
    - Transaction sender and recipient addresses (even for zero-value transfers)
    - Beneficiary addresses for `SELFDESTRUCT`
    - System contract addresses accessed during pre/post-execution; the system caller address, `SYSTEM_ADDRESS` (`0xfffffffffffffffffffffffffffffffffffffffe`), MUST NOT be included unless it experiences state access itself
    - Withdrawal recipient addresses, regardless of whether the withdrawal amount is non-zero
    - Precompiled contracts when called or accessed

Addresses with no state changes **MUST** still be present with empty change lists.

Entries from an [EIP-2930](/EIPs/EIPS/eip-2930) access list **MUST NOT** be included automatically. Only addresses and storage slots that are actually touched or changed during execution are recorded.

### Block Access List Size Constraint

The block access list is constrained by the block gas limit rather than a fixed maximum number of items. The constraint is defined as:

```
bal_items &lt;= block_gas_limit // ITEM_COST
```

Where:

- `bal_items = storage_keys + addresses`
- `ITEM_COST = 2000`

The `storage_keys` is the total number of storage keys across all accounts, and `addresses` is the total number of unique addresses accessed in the block. With [EIP-7981](/EIPs/EIPS/eip-7981), the cheapest way to add an item to the BAL is a cold `SLOAD` at `COLD_SLOAD_COST` (2100, as defined in [EIP-2929](/EIPs/EIPS/eip-2929)). `ITEM_COST` is set deliberately below this minimum to create a buffer of approximately `block_gas_limit / 42000` extra items, which absorbs BAL entries from system contract execution (e.g., [EIP-2935](/EIPs/EIPS/eip-2935), [EIP-4788](/EIPs/EIPS/eip-4788), [EIP-7002](/EIPs/EIPS/eip-7002), [EIP-7251](/EIPs/EIPS/eip-7251)) and withdrawal recipients ([EIP-4895](/EIPs/EIPS/eip-4895)) that do not consume block gas.

### Gas Validation Before State Access

State-accessing opcodes perform gas validation in two phases:

- **Pre-state validation**: Gas costs determinable without state access (memory expansion, base opcode cost, warm/cold access cost)
- **Post-state validation**: Gas costs requiring state access (account existence, [EIP-7702](/EIPs/EIPS/eip-7702) delegation resolution)

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.

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.

The following table specifies pre-state validation costs in addition to the base opcode cost (gas constants as defined in [EIP-2929](/EIPs/EIPS/eip-2929)):

| Instruction | Pre-state Validation |
|-------------|----------------------|
| `BALANCE` | `access_cost` |
| `SELFBALANCE` | None (accesses current contract, always warm) |
| `EXTCODESIZE` | `access_cost` |
| `EXTCODEHASH` | `access_cost` |
| `EXTCODECOPY` | `access_cost` + `memory_expansion` |
| `CALL` | `access_cost` + `memory_expansion` + `GAS_CALL_VALUE` (if value &gt; 0) |
| `CALLCODE` | `access_cost` + `memory_expansion` + `GAS_CALL_VALUE` (if value &gt; 0) |
| `DELEGATECALL` | `access_cost` + `memory_expansion` |
| `STATICCALL` | `access_cost` + `memory_expansion` |
| `CREATE` | `memory_expansion` + `INITCODE_WORD_COST` + `GAS_CREATE` |
| `CREATE2` | `memory_expansion` + `INITCODE_WORD_COST` + `GAS_KECCAK256_WORD` + `GAS_CREATE` |
| `SLOAD` | `access_cost` |
| `SSTORE` | More than `GAS_CALL_STIPEND` available |
| `SELFDESTRUCT` | `GAS_SELF_DESTRUCT` + `access_cost` |

Where:

- `access_cost`: For account-accessing opcodes: `COLD_ACCOUNT_ACCESS_COST` if cold, `WARM_STORAGE_READ_COST` if warm. For storage-accessing opcodes (`SLOAD`): `COLD_SLOAD_COST` if cold, `WARM_STORAGE_READ_COST` if warm.
- `memory_expansion`: Gas cost to expand memory for input/output regions

Post-state costs (e.g., `GAS_NEW_ACCOUNT` for calls to empty accounts, `GAS_SELF_DESTRUCT_NEW_ACCOUNT` if beneficiary does not exist) do not affect BAL inclusion since the target has already been accessed.

#### EIP-7702 Delegation

When a call target has an [EIP-7702](/EIPs/EIPS/eip-7702) delegation, the target is accessed to resolve the delegation. If a delegation exists, the delegated address requires its own `access_cost` check before being accessed. If this check fails, the delegated address MUST NOT appear in the BAL, though the original call target is included (having been accessed to resolve the delegation).

Note: Delegated accounts cannot be empty, so `GAS_NEW_ACCOUNT` never applies when resolving delegations.

#### SSTORE

`SSTORE` performs an implicit read of the current storage value for gas calculation. The `GAS_CALL_STIPEND` check prevents this state access when operating within the call stipend. If `SSTORE` fails this check, the storage slot MUST NOT appear in `storage_reads` or `storage_changes`.

### Ordering, Uniqueness and Determinism

The following ordering rules **MUST** apply:

- **Accounts**: Lexicographic by address
- **storage_changes**: Slots lexicographic by storage key; within each slot, changes by block access index (ascending)
- **storage_reads**: Lexicographic by storage key
- **balance_changes, nonce_changes, code_changes**: By block access index (ascending)

The following uniqueness constraints **MUST** hold:

- Each address **MUST** appear exactly once in `BlockAccessList`.
- Each storage key **MUST** appear at most once in `storage_changes` per account.
- Each storage key **MUST** appear at most once in `storage_reads` per account.
- A storage key **MUST NOT** appear in both `storage_changes` and `storage_reads` for the same account.
- Each `block_access_index` **MUST** appear at most once per change list (`balance_changes`, `nonce_changes`, `code_changes`, and per-slot `StorageChange` list).

### BlockAccessIndex Assignment

`BlockAccessIndex` values **MUST** be assigned as follows:

- `0` for **pre‑execution** system contract calls.
- `1 … n` for transactions (in block order).
- `n + 1` for **post‑execution** system contract calls.

### Recording Semantics by Change Type

#### Storage

- **Writes include:**

  - Any value change (post‑value ≠ pre‑value).
  - **Zeroing** a slot (pre‑value exists, post‑value is zero).
  
- **Reads include:**

  - Slots accessed via `SLOAD` that are not written.
  - Slots written with unchanged values (i.e., `SSTORE` where post-value equals pre-value, also known as &quot;no-op writes&quot;).

Note: Implementations MUST check the pre-transaction value to correctly distinguish between actual writes and no-op writes.

#### Balance (`balance_changes`)

Record **post‑transaction** balances (`uint256`) for:

- Transaction **senders** (gas + value).
- Transaction **recipients** (only if `value &gt; 0`).
- CALL/CALLCODE **senders** (value).
- CALL/CALLCODE **recipients** (only if `value &gt; 0`).
- CREATE/CREATE2 recipients (only if `value &gt; 0`).
- **COINBASE** (rewards + fees).
- **SELFDESTRUCT/SENDALL** beneficiaries.
- **Withdrawal recipients** (system withdrawals, [EIP-4895](/EIPs/EIPS/eip-4895)).

For unaltered account balances:

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 `balance_changes`. The sender and recipient address **MUST** be included in `AccountChanges`.

The following special cases require addresses to be included with empty changes if no other state changes occur:

- Zero-value transfer recipients
- Calling a same-transaction SELFDESTRUCT on an address that had a zero pre-transaction balance

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).

#### Code

Track **post‑transaction runtime bytecode** for deployed or modified contracts, and **delegation indicators** for successful delegations as defined in [EIP-7702](/EIPs/EIPS/eip-7702).

#### Nonce

Record **post‑transaction nonces** for:

- EOA senders.
- Contracts that performed a successful `CREATE` or `CREATE2`.
- Deployed contracts.
- [EIP-7702](/EIPs/EIPS/eip-7702) authorities.

### Edge Cases (Normative)

- **COINBASE / Fee Recipient:** 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).
- **Precompiled contracts:** 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.
- **SENDALL:** For positive-value selfdestructs, the sender and beneficiary are recorded with a balance change.
- **SELFDESTRUCT (in-transaction):** Accounts destroyed within a transaction **MUST** be included in `AccountChanges` 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 `storage_reads` entry. 
- **Accessed but unchanged:** Include the address with empty changes (e.g., targets of `EXTCODEHASH`, `EXTCODESIZE`, `BALANCE`, `STATICCALL`, etc.).
- **Zero‑value transfers / Unchanged balance in transaction:** Include the address; omit from `balance_changes`.
- **Gas refunds:** Record the **final** balance of the sender after each transaction.
- **Block rewards:** Record the **final** balance of the fee recipient after each transaction.
- **Exceptional halts:** Record the **final** nonce and balance of the sender, and the **final** 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 `storage_reads`.
- **Pre‑execution system contract calls:** All state changes **MUST** use `block_access_index = 0`.
- **Post‑execution system contract calls:** All state changes **MUST** use `block_access_index = len(transactions) + 1`.
- **EIP-7702 Delegations:** 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 `accessed_addresses` (per [EIP-2929](/EIPs/EIPS/eip-2929)), 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 `CALL`/`CALLCODE`/`DELEGATECALL`/`STATICCALL` under authority execution).
- **EIP‑4895 (Consensus layer withdrawals):** Recipients are recorded with their final balance after the withdrawal.
- **EIP‑2935 (block hash):** Record system contract storage diffs of the **single** updated storage slot in the ring buffer.
- **EIP‑4788 (beacon root):** Record system contract storage diffs of the **two** updated storage slots in the ring buffer.
- **EIP‑7002 (withdrawals):** Record system contract storage diffs of storage slots **0–3** (4 slots) after the dequeuing call. The dequeue also reads up to 3 × `MAX_WITHDRAWAL_REQUESTS_PER_BLOCK` queue data slots (from slot 4 onward), which appear as storage_reads.
- **EIP‑7251 (consolidations):** Record system contract storage diffs of storage slots **0–3** (4 slots) after the dequeuing call. The dequeue also reads up to 4 × `MAX_CONSOLIDATION_REQUESTS_PER_BLOCK` queue data slots (from slot 4 onward), which appear as storage_reads.

### Engine API

The Engine API is extended with new structures and methods to support block-level access lists:

**ExecutionPayloadV4** extends ExecutionPayloadV3 with:

- `blockAccessList`: RLP-encoded block access list

**engine_newPayloadV5** validates execution payloads:

- Accepts `ExecutionPayloadV4` structure
- Validates that computed access list matches provided `blockAccessList`
- Returns `INVALID` if access list is malformed or doesn&apos;t match

**engine_getPayloadV6** builds execution payloads:

- Returns `ExecutionPayloadV4` structure
- Collects all account accesses and state changes during transaction execution
- Populates `blockAccessList` field with RLP-encoded access list

**Block processing flow:**

When processing a block:

1. The EL receives the BAL in the ExecutionPayload
2. The EL computes `block_access_list_hash = keccak256(blockAccessList)` and includes it in the block header
3. The EL executes the block and generates the actual BAL
4. If the generated BAL doesn&apos;t match the provided BAL, the block is invalid (the hash in the header would be wrong)

The execution layer provides the RLP-encoded `blockAccessList` to the consensus layer via the Engine API. The consensus layer then computes the SSZ `hash_tree_root` for storage in the `ExecutionPayload`.

**Retrieval methods** for historical BALs:

- `engine_getPayloadBodiesByHashV2`: Returns `ExecutionPayloadBodyV2` objects containing transactions, withdrawals, and `blockAccessList`
- `engine_getPayloadBodiesByRangeV2`: Returns `ExecutionPayloadBodyV2` objects containing transactions, withdrawals, and `blockAccessList`

The `blockAccessList` field contains the RLP-encoded BAL or `null` for pre-Amsterdam blocks or when data has been pruned.

The EL MUST retain BALs for at least the duration of the weak subjectivity period (`=3533 epochs`) to support synchronization with re-execution after being offline for less than the WSP.

### State Transition Function

The state transition function must validate that the provided BAL matches the actual state accesses.

**Implementation Note:** 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 `block_access_list_hash` in the header. This is the approach used in the execution-specs reference implementation.

```python 
def validate_block(execution_payload, block_header):
    # 1. Compute hash from received BAL and set in header
    block_header.block_access_list_hash = keccak(execution_payload.blockAccessList)
    
    # 2. Execute block and collect actual accesses
    actual_bal = execute_and_collect_accesses(execution_payload)
    
    # 3. Verify actual execution matches provided BAL
    # If this fails, the block is invalid (the hash in the header would be wrong)
    assert rlp.encode(actual_bal) == execution_payload.blockAccessList

def execute_and_collect_accesses(block):
    &quot;&quot;&quot;Execute block and collect all state accesses into BAL format&quot;&quot;&quot;
    accesses = {}
    
    # Pre-execution system contracts (block_access_index = 0)
    track_system_contracts_pre(block, accesses, block_access_index=0)
    
    # Execute transactions (block_access_index = 1..n)
    for i, tx in enumerate(block.transactions):
        execute_transaction(tx)
        track_state_changes(tx, accesses, block_access_index=i+1)
    
    # Withdrawals and post-execution (block_access_index = len(txs) + 1)
    post_index = len(block.transactions) + 1
    for withdrawal in block.withdrawals:
        apply_withdrawal(withdrawal)
        track_balance_change(withdrawal.address, accesses, post_index)
    track_system_contracts_post(block, accesses, post_index)
    
    # Convert to BAL format and sort
    return build_bal(accesses)

def track_state_changes(tx, accesses, block_access_index):
    &quot;&quot;&quot;Track all state changes from a transaction&quot;&quot;&quot;
    for addr in get_touched_addresses(tx):
        if addr not in accesses:
            accesses[addr] = {
                &apos;storage_writes&apos;: {},  # slot -&gt; [(index, value)]
                &apos;storage_reads&apos;: set(),
                &apos;balance_changes&apos;: [],
                &apos;nonce_changes&apos;: [],
                &apos;code_changes&apos;: []
            }
        
        # Track storage changes
        for slot, value in get_storage_writes(addr).items():
            if slot not in accesses[addr][&apos;storage_writes&apos;]:
                accesses[addr][&apos;storage_writes&apos;][slot] = []
            accesses[addr][&apos;storage_writes&apos;][slot].append((block_access_index, value))
        
        # Track reads (slots accessed but not written)
        for slot in get_storage_reads(addr):
            if slot not in accesses[addr][&apos;storage_writes&apos;]:
                accesses[addr][&apos;storage_reads&apos;].add(slot)
        
        # Track balance, nonce, code changes
        if balance_changed(addr):
            accesses[addr][&apos;balance_changes&apos;].append((block_access_index, get_balance(addr)))
        if nonce_changed(addr):
            accesses[addr][&apos;nonce_changes&apos;].append((block_access_index, get_nonce(addr)))
        if code_changed(addr):
            accesses[addr][&apos;code_changes&apos;].append((block_access_index, get_code(addr)))

def build_bal(accesses):
    &quot;&quot;&quot;Convert collected accesses to BAL format&quot;&quot;&quot;
    bal = []
    for addr in sorted(accesses.keys()):  # Sort addresses lexicographically
        data = accesses[addr]
        
        # Format storage changes: [slot, [[index, value], ...]]
        storage_changes = [[slot, sorted(changes)] 
                          for slot, changes in sorted(data[&apos;storage_writes&apos;].items())]
        
        # Account entry: [address, storage_changes, reads, balance_changes, nonce_changes, code_changes]
        bal.append([
            addr,
            storage_changes,
            sorted(list(data[&apos;storage_reads&apos;])),
            sorted(data[&apos;balance_changes&apos;]),
            sorted(data[&apos;nonce_changes&apos;]),
            sorted(data[&apos;code_changes&apos;])
        ])
    
    return bal
```

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 `len(transactions) + 1`.

Clients MAY invalidate immediately if any transaction exceeds declared state.

Clients MUST store BALs separately from blocks and make them available via the engine API.

### Concrete Example

Example block:

**Pre-execution:**

- EIP-2935: Store parent hash at block hash contract (`0x0000F90827F1C53a10cb7A02335B175320002935`)
- EIP-7002: Omitted for simplicity.

**Transactions:**

1. Alice (0xaaaa...) sends 1 ETH to Bob (0xbbbb...), checks balance of 0x2222...
2. Charlie (0xcccc...) calls factory (0xffff...) deploying contract at 0xdddd...

**Post-execution:**

- Withdrawal of 100 ETH to Eve (0xabcd...)
- EIP-7002 and EIP-7251 omitted for simplicity.

Note: Pre-execution system contract uses block_access_index = 0. Post-execution withdrawal uses block_access_index = 3 (len(transactions) + 1)

Resulting BAL (RLP structure):

```python
[
    # Addresses are sorted lexicographically
    [ # AccountChanges for 0x0000F90827F1C53a10cb7A02335B175320002935 (Block hash contract)
        0x0000F90827F1C53a10cb7A02335B175320002935,
        [ # storage_changes
            [b&apos;\x00...\x0f\xa0&apos;, [[0, b&apos;...&apos;]]]  # slot, [[block_access_index, parent_hash]]
        ],
        [],  # storage_reads
        [],  # balance_changes
        [],  # nonce_changes
        []   # code_changes
    ],
    [ # AccountChanges for 0x2222... (Address checked by Alice)
        0x2222...,
        [],  # storage_changes
        [],  # storage_reads
        [],  # balance_changes (no change, just checked)
        [],  # nonce_changes
        []   # code_changes
    ],
    [ # AccountChanges for 0xaaaa... (Alice - sender tx 0)
        0xaaaa...,
        [],  # storage_changes
        [],  # storage_reads
        [[1, 0x...29a241a]],  # balance_changes: [[block_access_index, post_balance]]
        [[1, 10]],  # nonce_changes: [[block_access_index, new_nonce]]
        []  # code_changes
    ],
    [ # AccountChanges for 0xabcd... (Eve - withdrawal recipient)
        0xabcd...,
        [],  # storage_changes
        [],  # storage_reads
        [[3, 0x...5f5e100]],  # balance_changes: 100 ETH withdrawal
        [],  # nonce_changes
        []   # code_changes
    ],
    [ # AccountChanges for 0xbbbb... (Bob - recipient tx 0)
        0xbbbb...,
        [],  # storage_changes
        [],  # storage_reads
        [[1, 0x...b9aca00]],  # balance_changes: +1 ETH
        [],  # nonce_changes
        []   # code_changes
    ],
    [ # AccountChanges for 0xcccc... (Charlie - sender tx 1)
        0xcccc...,
        [],  # storage_changes
        [],  # storage_reads
        [[2, 0x...bc16d67]],  # balance_changes: after gas
        [[2, 5]],  # nonce_changes
        []  # code_changes
    ],
    [ # AccountChanges for 0xdddd... (Deployed contract)
        0xdddd...,
        [],  # storage_changes
        [],  # storage_reads
        [],  # balance_changes
        [[2, 1]],  # nonce_changes: new contract nonce
        [[2, b&apos;\x60\x80\x60\x40...&apos;]]  # code_changes: deployed bytecode
    ],
    [ # AccountChanges for 0xeeee... (COINBASE)
        0xeeee...,
        [],  # storage_changes
        [],  # storage_reads
        [[1, 0x...05f5e1], [2, 0x...0bebc2]],  # balance_changes: after tx fees
        [],  # nonce_changes
        []   # code_changes
    ],
    [ # AccountChanges for 0xffff... (Factory contract)
        0xffff...,
        [ # storage_changes
            [b&apos;\x00...\x01&apos;, [[2, b&apos;\x00...\xdd\xdd...&apos;]]]  # slot 1, deployed address
        ],
        [],  # storage_reads
        [],  # balance_changes
        [[2, 5]],  # nonce_changes: after CREATE
        []  # code_changes
    ]
]
```

RLP-encoded and compressed: ~400-500 bytes.

## Rationale

### BAL Design Choice

This design variant was chosen for several key reasons:

1. **Size vs parallelization**: BALs include all accessed addresses (even unchanged) for complete parallel IO and execution.

2. **Storage values for writes**: Post-execution values enable state reconstruction during sync without individual proofs against state root.

3. **Overhead analysis**: Historical data shows ~70 KiB average BAL size.

4. **Transaction independence**: 60-80% of transactions access disjoint storage slots, enabling effective parallelization. The remaining 20-40% can be parallelized by having post-transaction state diffs.

5. **RLP encoding**: Native Ethereum encoding format, maintains compatibility with existing infrastructure.

### BAL Size Considerations (60m block gas limit)

**Average BAL size**: ~72.4 KiB (compressed)

- Storage writes: ~29.2 KiB (40.3%)
- Storage reads: ~18.7 KiB (25.8%)
- Balance diffs: ~6.7 KiB (9.2%)
- Nonce diffs: ~1.1 KiB (1.5%)
- Code diffs: ~1.2 KiB (1.6%)
- Account addresses (with diffs): ~7.7 KiB (10.7%)
- Touched-only addresses: ~3.5 KiB (4.8%)
- RLP encoding overhead: ~4.4 KiB (6.1%)

Smaller than current worst-case calldata blocks.

An empirical analysis has been done [here](/EIPs/assets/eip-7928/bal_size_analysis). An updated analysis for a 60 million block gas limit can be found [here](/EIPs/assets/eip-7928/bal_size_analysis_60m).

### Asynchronous Validation

BAL verification occurs alongside parallel IO and EVM operations without delaying block processing.

## Backwards Compatibility

This proposal requires changes to the block structure and engine API that are not backwards compatible and require a hard fork.

## Security Considerations

### Validation Overhead

Validating access lists and balance diffs adds validation overhead but is essential to prevent acceptance of invalid blocks.

### Block Size

Increased block size impacts propagation but overhead (~70 KiB average) is reasonable for performance gains.

### Early Rejection of Malicious BALs

Since `storage_reads` 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 phantom storage reads that are never accessed, forcing clients into unnecessary I/O prefetching and significant data download while the block remains unrejectable until completion.

To mitigate this, clients SHOULD enforce a gas-budget feasibility check at transaction boundaries. Let:

- `R_remaining` = number of declared storage reads not yet accessed
- `G_remaining` = remaining block gas

The following invariant must hold:

```
G_remaining &gt;= R_remaining * 2000
```

Where 2000 is the minimum gas cost for a storage read (via [EIP-2930](/EIPs/EIPS/eip-2930) access lists: 1900 upfront + 100 warm read). If this check fails, the block can be rejected immediately as invalid, since insufficient gas remains to access the declared reads. This check SHOULD be performed periodically (e.g., every 8 transactions) to enable early rejection without impacting parallel execution.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>PermaLink Asset Bound Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/non-fungible-asset-bound-token/23175</comments>
        
        <description>## Abstract

This standard introduces a subclass of tokens known as **PermaLink Asset Bound Tokens (PermaLink-ABTs)**. They are a specific implementation of the broader **Asset Bound Token (ABT)** concept. ABTs establish a novel ownership paradigm where **an asset can own another asset**, enabling composable, nested, and portfolio-like token structures that evolve together over time.

PermaLink-ABTs implement a permanent binding mechanism where a token in one smart contract is irreversibly linked to a token in another contract. These links mirror key state data such as `ownerOf`, `tokenId`, `totalSupply`, and `balanceOf` using the `assetBoundContract` interface. Traditional token transfer and approval functions are omitted to enforce immutability and structural cohesion between bound assets.

Instead of utilizing a `mint` function, PermaLink-ABTs employ a `reveal` mechanism that activates tokens from a predefined supply. This approach enables permissionless binding and significantly reduces gas costs. A single token can have multiple PermaLink-ABTs bound to it, acting as multiple subordinate assets, forming a unified, transferable unit that simplifies asset mobility across digital identities, NFTs, and real-world assets (RWAs).

By encouraging asset composability over competition, PermaLink-ABTs introduce a dynamic, future-proof model for on-chain asset evolution.


## Motivation

Traditional ownership models on Ethereum are inherently limited. Only externally owned accounts (EOAs) or smart contracts can own blockchain assets. This creates rigidity, especially as the blockchain ecosystem expands to include digital identities, tokenized real-world assets (RWAs), and NFTs. Current smart contracts are static in nature, meaning once deployed, they cannot adapt to evolving systems, unforeseen use cases, or new integration layers. There is a need for a more flexible and modular ownership model that allows for dynamic interactions between assets.

This standard proposes **Asset Bound Tokens (ABTs)** as a solution to this challenge. ABTs allow one token to be permanently bound to another across contracts, creating a dynamic, flexible, and composable ownership model. By enabling tokens to move and evolve together, ABTs pave the way for new possibilities in the on-chain economy. The following use cases illustrate why ABTs are needed:

1. **On-Chain Identity Systems**  
 Governments and institutions worldwide are piloting or implementing blockchain-based identity systems, digital passports, national IDs, and verifiable credentials such as with the ongoing European Blockchain Services Infrastructure (EBSI) initiatives. These systems often require credentials to be linked across multiple registries (e.g., healthcare, banking, voting). ABTs enable the binding of identity-linked tokens into a cohesive unit, so they move together instead of requiring manual coordination and transfers. This ensures that identity-linked assets remain interconnected and dynamic, making it easier to manage and update linked data as users interact with various systems.

2. **Real-World Asset (RWA) Ownership Structures**  
 Tokenized businesses and assets (e.g., land, equipment, commodities) need flexible ownership models. These dynamic—businesses acquire, divest, and restructure their holdings and various assets. ABTs allow contracts to represent complex, evolving ownership hierarchies, where nested assets follow changes in their parent entity’s structure (e.g., a farming company acquiring new land or an IT firm merging with another and inheriting intellectual property). ABTs ensure businesses can efficiently manage and transfer assets on-chain without the constraints of rigid smart contracts.

3. **Manufacturing and Supply Chain Management**  
    Supply chains involve multiple layers of assets: raw materials → parts → products → packaging → containers. Blockchain’s transparency is invaluable, but traditional methods of creating individual tokens or smart contracts for each stage are inefficient and costly. ABTs streamline this by linking tokens across the supply chain, allowing them to be aggregated when products are built up (e.g., shoes packed in boxes, boxes placed on pallets, pallets loaded into containers) and broken down as they move through different stages (e.g., containers unloaded, pallets split, boxes unpacked). This dynamic linking and unlinking reduce redundancy, maintain transparent immutable records, and ensure seamless tracking while minimizing gas costs. By enabling the efficient flow of assets throughout the supply chain, ABTs help reduce complexity and provide a cohesive, real-time view of the entire process.

4. **NFT Ecosystem Optimization**  
 NFT projects often expand by launching secondary collections (e.g., additional editions, special releases). Without ABTs, this leads to fragmented value and user confusion as older and newer assets compete. ABTs allow new NFTs to be bound to originals, enhancing their value while maintaining a unified ecosystem. This strengthens liquidity and preserves market metrics, ensuring that the value of the original collection is retained and supported by the newer assets, thus benefiting both creators and collectors.

5. **New Opportunities for Creators**  
   ABTs empower creators to build on top of existing assets permissionlessly without needing ownership of or permission from the original smart contract. This enables a new wave of creative expression, where artists can augment and enhance NFTs (e.g., adding new visuals, audio, or interactive layers) and collaborate on existing collections. Such contributions can generate new revenue streams through shared royalties, consignment, or collaborative upgrades. Owners benefit as well, since bound enhancements can increase the inherent value of their holdings, particularly in projects involving established creators or cross-collection collaborations.

In essence, ABTs introduce a framework where tokens are linked rather than owned. This allows for dynamic and evolving asset systems, where assets move together in harmony. If a binding token moves, all associated ABTs move with it, ensuring seamless updates and reducing the need for manual transfers. This innovation transforms traditional smart contracts from static repositories into living, evolving systems capable of adapting to changing use cases, technologies, and business models.

The **PermaLink-ABTs** implementation takes the ABT model further by enforcing a permanent binding between one token and another—whether it&apos;s another ABT, NFT or NFKBT. This permanent binding ensures that tokens can be transferred as a single unit, reducing complexity and gas fees. Instead of relying on traditional minting, PermaLink-ABTs use a `reveal` mechanism, activating tokens from a predefined supply. This reduces gas costs and encourages efficient linking of assets, enabling greater composability across multiple sectors.

PermaLink-ABTs consolidate asset value by allowing multiple subordinate tokens to be linked to a single binding token, providing enhanced composability and reducing fragmentation. By requiring only the binding token to be transferred, all associated assets move in sync, making it easier to manage portfolios and move groups of assets together. This approach fosters collaboration, value accrual, and compatibility across ecosystems, whether for digital identities, RWAs, NFTs, or other on-chain assets.


## Specification

### `IERC7929` (Token Interface)

**NOTES**:

- The following specifications use syntax from Solidity `0.8.27` (or above)

```solidity
interface IERC7929 {
    event AssetBoundContractSet(address assetBoundContract);

    function ownerOf(uint256 tokenId) external view returns (address);
    function tokenExists(uint256 tokenId) external view returns (bool);
    function totalSupply() external view returns (uint256);
    function balanceOf(address owner) external view returns (uint256);
}
```

### Events

#### `AssetBoundContractSet` Event

Emitted when the contract is deployed and bound to `assetBoundContract`

```solidity
event AssetBoundContractSet(address assetBoundContract);
```

### Functions

The functions detailed below MUST be implemented.

#### `ownerOf`

Returns the owner of the NFT specified by the `tokenId`. Will read from the `assetBoundContract` the owner and return it.

```solidity
function ownerOf(uint256 tokenId) external view returns (address);
```

#### `tokenExists`

Returns true if the token read from the `assetBoundContract` exists.
Tokens usually start existing when minted and stop existing when burned.

```solidity
function tokenExists(uint256 tokenId) external view returns (bool);
```

#### `totalSupply`

Gets the total amount of tokens stored by the assetBoundContract

```solidity
function totalSupply() external view returns (uint256);
```

#### `balanceOf`

Returns the number of NFTs in the assetBoundContract that an owner has.

```solidity
function balanceOf(address owner) external view returns (uint256);
```

### `IERC7929Reveal` (Optional Token Interface)

**NOTES**:

- The following specifications use syntax from Solidity `0.8.27` (or above)
- The Reveal extension is OPTIONAL for [ERC-7929](/EIPs/EIPS/eip-7929) contracts
  
```solidity
interface IERC7929Reveal is IERC7929 {
    event TokenRevealed(uint256 tokenId);

    function reveal(uint256[] calldata tokenIds) external payable;
}
```

### Events

#### `TokenRevealed` Event

Emitted when the `tokenId` is revealed

```solidity
event TokenRevealed(uint256 tokenId);
```

### Functions

The functions detailed below MUST be implemented.

### `reveal`

The `reveal` function should be implemented to allow pre-allocated tokens to be activated on demand.  
This method reduces gas consumption compared to traditional minting and simplifies token activation mechanics.

```solidity
function reveal(uint256[] calldata tokenIds) external payable;
```

## Rationale

The design of PermaLink-ABTs centers around the goal of enabling permanent token binding while optimizing for gas efficiency, composability, and secure ownership structures. We adopted the `assetBoundContract` interface to mirror essential metadata such as `ownerOf`, `tokenId`, `totalSupply`, and `balanceOf` from the binding token’s contract. This ensures that PermaLink-ABTs remain synchronized with the asset they are bound to, without duplicating logic or requiring manual updates. The mirroring also ensures traceability and visibility across contracts, allowing observers and off-chain systems to reliably interpret the token relationship. To preserve the permanent nature of the bond, standard `transfer` and `approve` methods are omitted. This immutability guarantees that PermaLink-ABTs cannot be separated from their bound asset once revealed. If the primary token moves, all attached PermaLink-ABTs move with it. This behavior supports composability, value aggregation, and consistent ownership logic.

An alternative considered was allowing flexible transfer mechanics via opt-in transfer functions or whitelisting. However, this introduced unnecessary complexity and undermined the core principle of permanence. It also increased the risk of token desynchronization, accidental fragmentation, and security vulnerabilities in contract implementations. By contrast, the current design provides a simpler and more robust foundation.

By implementing an **optional** `reveal` function in place of a traditional `mint` function it reduce gas costs and simplifies on-chain state changes for both the deployer and owner of the token having an ABT bound to it. Unlike minting, which creates tokens at runtime and incurs higher gas fees, the `reveal` function maps pre-allocated tokens stored in an array or mapping. This allows tokens to be activated on demand without the overhead of dynamic token creation. As a result, token issuers can prepare and store an entire supply in advance, with users later revealing and binding tokens when needed. This approach aligns with the use case of portfolio binding and asset hierarchies, where large numbers of tokens may need to be activated and bound efficiently. 

PermaLink-ABTs enforce strict one-way binding with immutable relationships, making them especially suitable for use cases like identity systems, real-world asset (RWA) structures, and portfolio-locked NFTs. They act as permanently attached extensions to existing tokens, reducing complexity and avoiding redundant contract logic. This approach also provides a cleaner and more secure way to augment existing assets while maintaining compatibility across various blockchain use cases. This standard is intentionally minimal to ensure wide compatibility and flexibility. Developers can extend the base logic for specialized use cases, such as embedding royalty splits, upgrade paths, or linking to dynamic data feeds, without altering the underlying PermaLink mechanism.


## Reference Implementation

### `ERC7929` (Token implementation)

**NOTES**: 
- The interface ID is (`0x0b76916c`)
- Callers MUST handle `false` from `returns (bool success)`. Callers MUST NOT assume that `false` is never returned!

```solidity
contract ERC7929 is IERC165, ERC721Enumerable, Ownable, IERC7929 {
    ERC721Enumerable public assetBoundContract;

    constructor(
        address _assetBoundContract,
        string memory _name,
        string memory _symbol
    ) ERC721(_name, _symbol) {
        assetBoundContract = ERC721Enumerable(_assetBoundContract);

        emit AssetBoundContractSet(_assetBoundContract);
    }

    ///////////////////////////////////////////////////////////////
    // region EIP-165 Implementation
    ///////////////////////////////////////////////////////////////

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(
        bytes4 interfaceId
    ) public view virtual override(ERC721Enumerable, IERC165) returns (bool) {
        return
            interfaceId == type(IERC7929).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    ///////////////////////////////////////////////////////////////
    // endregion
    ///////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////
    // region Modifiers
    ///////////////////////////////////////////////////////////////

    modifier tokensMustExist(uint256[] calldata tokenIds) {
        for (uint256 i = 0; i &lt; tokenIds.length; i++) {
            require(tokenExists(tokenIds[i]), &quot;ERC7929: Token does not exist&quot;);
        }
        _;
    }

    ///////////////////////////////////////////////////////////////
    // endregion Modifiers
    ///////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////
    // region mirror functions
    ///////////////////////////////////////////////////////////////

    function ownerOf(
        uint256 tokenId
    )
        public
        view
        virtual
        override(ERC721, IERC7929, IERC721)
        returns (address)
    {
        return assetBoundContract.ownerOf(tokenId);
    }

    function tokenExists(uint256 tokenId) public view virtual returns (bool) {
        return assetBoundContract.ownerOf(tokenId) != address(0);
    }

    function totalSupply()
        public
        view
        virtual
        override(ERC721Enumerable, IERC7929)
        returns (uint256)
    {
        return assetBoundContract.totalSupply();
    }

    function balanceOf(
        address owner
    )
        public
        view
        virtual
        override(ERC721, IERC7929, IERC721)
        returns (uint256)
    {
        return assetBoundContract.balanceOf(owner);
    }

    ///////////////////////////////////////////////////////////////
    //endregion
    ///////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////
    //region Disabling approve and transfer functions to prevent transfers of ABT tokens
    ///////////////////////////////////////////////////////////////

    function approve(address, uint256) public pure override(ERC721, IERC721) {
        revert(&quot;ERC7929: Approvals not allowed&quot;);
    }

    function setApprovalForAll(
        address,
        bool
    ) public pure override(ERC721, IERC721) {
        revert(&quot;ERC7929: Approvals not allowed&quot;);
    }

    function transferFrom(
        address,
        address,
        uint256
    ) public pure override(ERC721, IERC721) {
        revert(&quot;ERC7929: Transfers not allowed&quot;);
    }

    function safeTransferFrom(
        address,
        address,
        uint256
    ) public pure override(ERC721, IERC721) {
        safeTransferFrom(address(0), address(0), 0, &quot;&quot;);
    }

    function safeTransferFrom(
        address,
        address,
        uint256,
        bytes memory
    ) public pure override(ERC721, IERC721) {
        revert(&quot;ERC7929: Transfers not allowed&quot;);
    }

    ///////////////////////////////////////////////////////////////
    //endregion
    ///////////////////////////////////////////////////////////////
}
```

### `IERC7929Reveal` (Token implementation)

**NOTES**: 
- This is an OPTIONAL extension for [ERC-7929](/EIPs/EIPS/eip-7929) contracts
- The interface ID is (`0xb93f208a`)
- Callers MUST handle `false` from `returns (bool success)`. Callers MUST NOT assume that `false` is never returned!

```solidity
contract ERC7929Reveal is ERC7929, IERC7929Reveal {
    mapping(uint256 =&gt; bool) public isRevealed;

    constructor(
        address _assetBoundContract,
        string memory _name,
        string memory _symbol
    ) ERC7929(_assetBoundContract, _name, _symbol) {}

    ///////////////////////////////////////////////////////////////
    // region EIP-165 Implementation
    ///////////////////////////////////////////////////////////////

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(
        bytes4 interfaceId
    ) public view virtual override returns (bool) {
        return
            interfaceId == type(IERC7929Reveal).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    ///////////////////////////////////////////////////////////////
    // endregion
    ///////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////
    // region Modifiers
    ///////////////////////////////////////////////////////////////

    modifier tokensMustNotBeRevealed(uint256[] calldata tokenIds) {
        for (uint256 i = 0; i &lt; tokenIds.length; i++) {
            require(
                !isRevealed[tokenIds[i]],
                &quot;ERC7929: Token already revealed&quot;
            );
        }
        _;
    }

    ///////////////////////////////////////////////////////////////
    // endregion Modifiers
    ///////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////
    // region mirror functions
    ///////////////////////////////////////////////////////////////

    function ownerOf(
        uint256 tokenId
    ) public view override(ERC7929, IERC7929) returns (address) {
        return super.ownerOf(tokenId);
    }

    function tokenExists(
        uint256 tokenId
    ) public view override(ERC7929, IERC7929) returns (bool) {
        return super.tokenExists(tokenId);
    }

    function totalSupply()
        public
        view
        override(ERC7929, IERC7929)
        returns (uint256)
    {
        return super.totalSupply();
    }

    function balanceOf(
        address owner
    ) public view override(ERC7929, IERC7929) returns (uint256) {
        return super.balanceOf(owner);
    }

    ///////////////////////////////////////////////////////////////
    //endregion
    ///////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////
    //region Reveal function to reveal the token URI for a given token ID(s)
    ///////////////////////////////////////////////////////////////

    function reveal(
        uint256[] calldata tokenIds
    )
        public
        payable
        virtual
        tokensMustExist(tokenIds)
        tokensMustNotBeRevealed(tokenIds)
    {
        for (uint256 i = 0; i &lt; tokenIds.length; i++) {
            isRevealed[tokenIds[i]] = true;
            emit TokenRevealed(tokenIds[i]);
        }
    }

    ///////////////////////////////////////////////////////////////
    //endregion
    ///////////////////////////////////////////////////////////////
}    
```

## Security Considerations

PermaLink-ABTs are linked to another non-fungible token. If an individual loses access to this token, what we call the **binding token**, they also lose access to all PermaLink-ABTs that have been bound to it. This introduces a critical security consideration: the entire value of bound assets depends on the integrity and availability of the binding token.

To mitigate this risk, we strongly recommend the use of standards like [ERC-6809](/EIPs/EIPS/eip-6809), a **Non-Fungible Key Bound Token**, which introduces on-chain two-factor authentication (2FA). ERC-6809 allows a user to bind sensitive tokens (like PermaLink-ABTs) to a secured identity layer, complete with recovery mechanisms. In the event that a user loses access to their original wallet or interacts with a malicious contract, ERC-6809 provides a safeFallback function to re-establish control.

In essence, all of the security guarantees of ERC-6809 extend to any PermaLink-ABTs bound to it. This layered security model not only protects against loss but also ensures recoverability and long-term viability for high-value bound assets. It is strongly encouraged that developers implementing PermaLink-ABTs integrate this or similar standards to provide a robust security foundation for users.


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 01 Apr 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7929</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7929</guid>
      </item>
    
      <item>
        <title>Interoperable Addresses</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7930-interoperable-addresses/23365</comments>
        
        <description>## Abstract
This proposal introduces a **binary format** to describe a _chain-specific address_.

This is achieved through a versioned, length-prefixed binary envelope that supports arbitrary-length data. The interpretation and serialization rules for the data within this envelope are defined by the [CAIP-350] companion standard, which provide profiles for each chain type and defines the serialization rules for each namespace.

## Motivation
The address format utilized on Ethereum mainnet ([ERC-55]) is shared by a large number of other blockchains. This format does not encode any information about the chain on which an interaction is intended to occur, which can introduce ambiguity and operational risk.

In practice, this limitation has led each protocol to define its own ad hoc way of representing the combination of address and chain, typically using separate fields and protocol-specific conventions. This fragmentation complicates interoperability across protocols, increases tooling complexity, and leads to inconsistencies at the infrastructure level.

This proposal builds on insights from [CAIP-10] and [CAIP-50]. It offers a binary canonical _Interoperable Address_ format which:

- Binds together chain identification and the raw address.
- Is compact for usage with cross-chain message passing and intent declaration.
- Extends beyond EVM blockchains.

These features can not be added to existing standards as they are not easily extensible - this one is.

### Comparisons with other standards

#### CAIP-10

[CAIP-10] proposes a standard text format to represent an address on a specific chain (referenced by its [CAIP-2] identifier).

The standard **does not** concern itself with the serialization/deserialization of the _target address_. It assumes knowledge of the native address format for each chain and does not enforce any serialization or canonicalization rules.

While it is trivial to add support for chains to [CAIP-10], the format is not optimized for usage within smart contracts as strings are an inefficient way to store data on-chain.

[CAIP-10] depends on [CAIP-2], which limits the chain reference to 32 characters. This constraint means that [CAIP-2] can not losslessy represent a chain. e.g. Solana chains utilize the leading 32 characters of the base58btc-encoded genesis blockhash, which is not a uniquely deterministic way of representing a chain. 

## Specification
The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119 and RFC 8174.

### Terminology
**Target Address**
: The address itself, independent of chain context. Serialized per the [CAIP-350] rules for the applicable namespace. In the examples below, the target address is `0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045`.

**Chain-specific Address**
: An address representation that includes both the _target address_ **and** the chain being targeted. The following are examples of chain-specific addresses:

- The _Interoperable Address_ definition outlined in this specification
- The addressing format outlined in [ERC-3770], e.g. `arb:0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045`
- The _Interoperable Name_ definition outlined in [ERC-7828]

**Interoperable Address**
: A binary payload which unambiguously identifies a _target address_ on a target chain. e.g. `0x00010000010114d8da6bf26964af9d7eed9e03e53415d37aa96045`


### _Interoperable Address_ Definition

An _Interoperable Address_ as defined by this standard MUST have the following binary format:

```
┌─────────┬───────────┬──────────────────────┬────────────────┬───────────────┬─────────┐
│ Version │ ChainType │ ChainReferenceLength │ ChainReference │ AddressLength │ Address │
└─────────┴───────────┴──────────────────────┴────────────────┴───────────────┴─────────┘
```

The components outlined above have the following meanings:

**Version**
: A 2-byte version identifier. For version 1 (this specification), this MUST be `0x0001` (big-endian). Future versions SHOULD be standardized in separate ERCs.

**ChainType**
: A 2-byte value corresponding to a CASA namespace. It allows users to interpret and display the _ChainReference_ and _Address_. Values are defined in the corresponding [CAIP-350] profile for the namespace.

**ChainReferenceLength**
: A 1-byte integer encoding the length of _ChainReference_ in bytes. Note that it MAY be zero, in which case the _Interoperable Address_ MUST NOT include a chain reference.

**ChainReference**
: Variable length, binary representation of the [CAIP-350] chain reference. Serialization of the _ChainReference_ within a specific namespace MUST follow the algorithm defined in the namespace&apos;s [CAIP-350] profile. Chain profiles are maintained by the Chain-Agnostic Standards Alliance (CASA).

**AddressLength**
: 1-byte integer encoding the length of Address in bytes. Note that it MAY be zero, in which case the _Interoperable Address_ MUST NOT include an address. It MUST NOT be zero if the _ChainReferenceLength_ is also zero.

**Address**
: Variable length field containing the binary encoding of the characters of the serialized address. The serialization for a specific _ChainType_ MUST follow the rules of its corresponding [CAIP-350] profile.

---

If you choose to display an _Interoperable Address_ it is RECOMMENDED that you display it as a lower case hexadecimal string.

### Examples

#### Example 1: Ethereum mainnet address

**Components**

| Key | Value |
| :--- | :--- |
| **Version** | `1` |
| **ChainType** | `0x0000` |
| **ChainReferenceLength** | `1` |
| **ChainReference** | `1` |
| **AddressLength** | `20` |
| **Address** | `0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045` |

**Interoperable Address**

These components produce the following _Interoperable Address_:

```
0x00010000010114d8da6bf26964af9d7eed9e03e53415d37aa96045
  ^^^^-------------------------------------------------- Version              
      ^^^^---------------------------------------------- ChainType            
          ^^-------------------------------------------- ChainReferenceLength
            ^^------------------------------------------ ChainReference       
              ^^---------------------------------------- AddressLength       
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Address             
```

---  

#### Example 2: Solana mainnet address

**Components**

| Key | Value |
| :--- | :--- |
| **Version** | `1` |
| **ChainType** | `0x0002` |
| **ChainReferenceLength** | `32` |
| **ChainReference** | `5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d` |
| **AddressLength** | `32` |
| **Address** | `MJKqp326RZCHnAAbew9MDdui3iCKWco7fsK9sVuZTX2` |


**Interoperable Address**

These components produce the following _Interoperable Address_:

```
0x000100022045296998a6f8e2a784db5d9f95e18fc23f70441a1039446801089879b08c7ef02005333498d5aea4ae009585c43f7b8c30df8e70187d4a713d134f977fc8dfe0b5
  ^^^^---------------------------------------------------------------------------------------------------------------------------------------- Version
      ^^^^------------------------------------------------------------------------------------------------------------------------------------ ChainType
          ^^---------------------------------------------------------------------------------------------------------------------------------- ChainReferenceLength
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------------------------------------------ ChainReference
                                                                            ^^---------------------------------------------------------------- AddressLength
                                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- Address
```
---  

#### Example 3: EVM address without ChainReference

**Components**

| Key | Value |
| :--- | :--- |
| **Version** | `1` |
| **ChainType** | `0x0000` |
| **ChainReferenceLength** | `0` |
| **ChainReference** | N/A |
| **AddressLength** | `20` |
| **Address** | `0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045` |

**Interoperable Address**

These components produce the following _Interoperable Address_:

```
0x000100000014d8da6bf26964af9d7eed9e03e53415d37aa96045
  ^^^^------------------------------------------------ Version
      ^^^^-------------------------------------------- ChainType
          ^^------------------------------------------ ChainReferenceLength
            ^^---------------------------------------- AddressLength
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Address
```
---  

#### Example 4: Solana mainnet network, no address

**Components**

| Key | Value |
| :--- | :--- |
| **Version** | `1` |
| **ChainType** | `0x0002` |
| **ChainReferenceLength** | `32` |
| **ChainReference** | `5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d` |
| **AddressLength** | `0` |
| **Address** | N/A |

**Interoperable Address**

These components produce the following _Interoperable Address_:

```
0x000100022045296998a6f8e2a784db5d9f95e18fc23f70441a1039446801089879b08c7ef000
  ^^^^------------------------------------------------------------------------ Version
      ^^^^-------------------------------------------------------------------- ChainType
          ^^------------------------------------------------------------------ ChainReferenceLength
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-- ChainReference
                                                                            ^^ AddressLength
```

### Versioning

These rules ensure that future standards that build upon this one maintain backwards compatibility.

Future versions:

- MUST be trivially convertible to the _Interoperable Address_ format defined in this specification
- MUST set the most significant bit of the version field to 1 if the _Interoperable Address_ format is not backward-compatible with the parsing rules outlined herein
- MUST support defining an address, a chain, or both
- MAY add fields but MUST NOT alter or omit any data required to reconstruct the Version 1 _Interoperable Address_ exactly, bit for bit
- MAY only be able to represent a subset of the CAIP namespaces

### Text representation
This specification defines a canonical binary representation that **is not** intended to be used directly in user-facing contexts. If an implementer chooses to display an _Interoperable Address_ directly, it is RECOMMENDED that it be represented as a lowercase hexadecimal string. [ERC-7828] is one example of a human-readable _chain-specific address_ definition that can be displayed in user-facing contexts.

The companion standard, CAIP-350, specifies on a per-namespace basis, the rules for converting the `ChainReference` and `Address` components of the _Interoperable Address_ into human readable representations. These MAY be displayed in user-facing contexts.

## Rationale
This ERC defines a compact binary format for representing a *chain-specific address*, primarily intended for use within smart contracts. For other contexts—such as display to end users or programmatic use in APIs—alternative *chain-specific addressing* standards may be more appropriate. For example, [ERC-7828] specifies a human-readable *chain-specific address* format.

The interoperability roadmap benefits significantly from first having a standardized binary format for addresses, which allows the message passing and intents verticals to move forward on a consistent common interface.

The rationale for some of the low level specification decisions are outlined below:

- We chose to allow the `Address` and `ChainReference` components to be zero-length to make this standard flexible and to allow developers to use a single, uniform standard for many different jobs. For example if a user wants to represent an address on any compatible chain, or if the user simply wants to represent the chain itself.
- We chose *not* to use alternate encoding formats (e.g., `base58` or `base64`) in order to make it easier for wallets and dApps to work with, and convert between, addresses that both use and do not use this addressing standard.

## Security Considerations
While this standard aims to be a foundation to be able to canonically refer to addresses on different chains, that guarantee is going to be a leaky abstraction in the real world, given that e.g. a particular chain namespace might define a serialization scheme that can&apos;t guarantee canonicity of addresses, or a given network might have two valid [CAIP-2] ids referring to it.

It is therefore advised for implementers requiring canonicity of addresses (e.g by using them as keys in smart contract mappings or other key-value stores), to thoroughly review the [CAIP-350] profile of a chain namespace for the possibility of a lack of canonicity of addresses (which should be noted in the profile&apos;s &apos;Extra Considerations&apos; section) as well as collisions with other already-supported namespaces.

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[ERC-55]: /EIPs/EIPS/eip-55

[ERC-3770]: /EIPs/EIPS/eip-3770

[ERC-7828]: /EIPs/EIPS/eip-7828
[CAIP-2]: https://github.com/ChainAgnostic/CAIPs/blob/2a7d42aebaffa42d1017c702974395ff5c1b3636/CAIPs/caip-2.md
[CAIP-10]: https://github.com/ChainAgnostic/CAIPs/blob/2a7d42aebaffa42d1017c702974395ff5c1b3636/CAIPs/caip-10.md
[CAIP-50]: https://github.com/ChainAgnostic/CAIPs/blob/2a7d42aebaffa42d1017c702974395ff5c1b3636/CAIPs/caip-50.md
[CAIP-350]: https://github.com/ChainAgnostic/CAIPs/blob/29762ef99a6ffea1e07e3f796c0d1a5a95e89b88/CAIPs/caip-350.md
</description>
        <pubDate>Sun, 02 Feb 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7930</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7930</guid>
      </item>
    
      <item>
        <title>Secondary Signature Algorithms</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7932-secondary-signature-algorithms/23514</comments>
        
        <description>## Abstract

This EIP:

 - Creates a unified registry &amp; standardized interface for introducing additional signature algorithms for the use of deriving account addresses.
 - Introduces a precompile at address `SIGRECOVER_PRECOMPILE_ADDRESS` for decoding these newly introduced algorithms.

## Motivation

As quantum computers become more advanced, several new post-quantum (PQ) algorithms have been designed. These algorithms all have certain drawbacks, such as large key sizes (&gt;1KiB), large signature sizes, or long verification times. These issues make them more expensive to compute and store than the currently used secp256k1 curve.

This EIP allows the use of many algorithms by introducing an algorithm registry that can be used via a single interface.

## Specification

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

Unless explicitly noted, integer encoding MUST be in big-endian format.

### Parameters

| Constant | Value |
| - | - |
| `SIGRECOVER_PRECOMPILE_ADDRESS`| `Bytes20(0x12)` |
| `SIGRECOVER_PRECOMPILE_BASE_GAS` | `3000` |


### Algorithm specification

New algorithms beyond the `secp256k1` algorithm specified in this EIP MUST be specified via a distinct EIP.

Each type of algorithm MUST specify the following fields:

```rust
trait Algorithm {
    // The algorithm type byte
    ALG_TYPE: uint8,

    // The size of signatures. Signatures MUST be padded
    // to this size to be valid. Note that this does include
    // the ALG_TYPE byte prefix
    SIZE: uint32

    // Get the gas cost of signing this data. This
    // SHOULD include a reasonable minimum and MUST
    // be relative to secp256k1, i.e. 0 gas is secp256k1.
    fn gas_cost(signing_data: Bytes) -&gt; Uint64;

    // Check whether the signature is valid. For some
    // algorithms, this may be a no-op. This function
    // will always be called before `verify`.
    fn validate(signature: Bytes) -&gt; None | Error;

    // Take the signature and signing_data and return the
    // public key of the signer.
    fn verify(signature: Bytes, signing_data: Bytes) -&gt; Bytes | Error;

    // Given a public key and corresponding signature, merge them into
    // a valid signature info container. This function MUST NOT check that
    // the provided `public_key` matches the signature.
    fn merge_detached_signature(detached_signature: Bytes, public_key: Bytes) -&gt; Bytes | Error;
}
```

Specifications MUST include some form of security analysis on the provided algorithm and basic benchmarks justifying gas costs. Additionally, specifications MUST address malleability issues that may arise from specified algorithms. 

An example of this specification can be found [here](/EIPs/assets/eip-7932/template-eip).

### Deriving address from public keys

The function below MUST be used when deriving an address from a public key:

```python
def pubkey_to_address(public_key: Bytes, algorithm_id: uint8) -&gt; ExecutionAddress:
    if algorithm_id == 0x00: # Compatibility shim to ensure backwards compatibility
        return ExecutionAddress(keccak(public_key[1:])[12:])

    if len(public_key) == 63:
        # Prevent collisions with legacy secp256k1
        return ExecutionAddress(keccak(algorithm_id || 0x00 || public_key)[12:])

    # with `||` being binary concatenation
    return ExecutionAddress(keccak(algorithm_id || public_key)[12:])
```

### Algorithm Registry

```python
class AlgorithmEntry():
    ALG_TYPE: uint8,
    SIZE: uint32,
    gas_cost: Callable[[Bytes], uint64],
    merge_detached_signature: Callable[[Bytes, Bytes], Bytes],
    validate: Callable[[Bytes], None | Error],
    verify: Callable[[Bytes, Bytes], Bytes | Error]

algorithm_registry: Dict[uint8, AlgorithmEntry]
```

This EIP uses the `algorithm_registry` object to signify algorithms that have been included within a hard fork.

A living EIP MAY be created on finalization of this EIP to track currently active algorithms across forks.

The algorithm type is reserved `0x7F` as invalid / missing, algorithm types MUST be less than 127.

### Helper functions

The following helper functions are defined for convenience:

```python
def calculate_penalty(algorithm: uint8, signing_data: Bytes) -&gt; uint:
    assert algorithm in algorithm_registry

    algorithm = algorithm_registry[algorithm]

    return algorithm.gas_cost(signing_data)

def validate_signature(signature: Bytes):
    assert len(signature) &gt; 0
    assert signature[0] in algorithm_registry

    algorithm = algorithm_registry[signature[0]]

    return algorithm.validate(signature)

# This function cannot be called without prior calling `validate_signature(signature)`
def verify_signature(signing_data: Bytes, signature: Bytes) -&gt; Bytes:
    algorithm = algorithm_registry[signature[0]]

    return algorithm.verify(signature, signing_data)
```

### `secp256k1` algorithm


```python
ALG_TYPE = 0x00
SIZE = 66

SECP256K1_SIGNATURE_SIZE = SIZE - 1

def secp256k1_unpack(signature: ByteVector[SECP256K1_SIGNATURE_SIZE]) -&gt; tuple[uint256, uint256, uint8]:
    r = uint256.from_bytes(signature[0:32], &apos;big&apos;)
    s = uint256.from_bytes(signature[32:64], &apos;big&apos;)
    y_parity = signature[64]
    return (r, s, y_parity)

def secp256k1_validate(signature: ByteVector[SECP256K1_SIGNATURE_SIZE]):
    SECP256K1N = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
    r, s, y_parity = secp256k1_unpack(signature)
    assert 0 &lt; r &lt; SECP256K1N
    assert 0 &lt; s &lt;= SECP256K1N // 2
    assert y_parity in (0, 1)

def gas_cost(signing_data: Bytes) -&gt; Uint64:
    # This is an adaptation from the KECCAK256 opcode
    if len(signing_data) == 32:
        return Uint64(0)
    else:
        minimum_word_size = (len(signing_data) + 31) // 32
        return Uint64(30 + (6 * minimum_word_size))

def validate(signature: Bytes) -&gt; None | Error:
    secp256k1_validate(signature[1:])

def verify(signature: Bytes, signing_data: Bytes) -&gt; Bytes | Error:
    # Another compatibility shim to ensure passing a 32 byte hash still works.
    if len(signing_data) != 32:
        signing_data = keccak256(signing_data)

    ecdsa = ECDSA()
    recover_sig = ecdsa.ecdsa_recoverable_deserialize(signature[1:65], signature[65])
    public_key = PublicKey(ecdsa.ecdsa_recover(signing_data, recover_sig, raw=True))
    uncompressed = public_key.serialize(compressed=False)
    return uncompressed

def merge_detached_signature(detached_signature: bytes, _public_key: bytes) -&gt; bytes:
    # Secp256k1 uses recoverable signatures, this is a no-op.
    return detached_signature
```

### `sigrecover` precompile

This EIP also introduces a new precompile located at `SIGRECOVER_PRECOMPILE_ADDRESS`.

This precompile MUST charge `SIGRECOVER_PRECOMPILE_BASE_GAS` static gas before executing.

The precompile MUST output the 20-byte address of the signer provided left padded to 32 bytes. On failure, the precompile MUST NOT return any data.

The precompile is defined as follows:

```python
def sigrecover_precompile(input: Bytes) -&gt; Bytes:
    assert len(input) &gt;= 1
    assert input[0] in algorithm_registry

    size = algorithm_registry[input[0]].SIZE

    assert len(input) &gt; size

    signature = input[:size]
    signing_data = input[size:]

    charge_gas(calculate_penalty(input[0], signing_data))

    # Run validate/verify function
    validate_signature(signature)
    pubkey = verify_signature(signing_data, signature)

    # Return address left-padded to 32 bytes
    return (b&quot;\x00&quot; * 12) + pubkey_to_address(pubkey, input[0])
```

## Rationale

### ERC-4337 interoperability

While initial drafts of this EIP were competing with ERC-4337, current versions of this EIP support it via the sigrecover precompile. This allows any ERC-4337 implementation to have the same signature verification logic and address derivation logic for any given private key. This also works agnostic of whatever algorithm derives the address.

### Precompile over native EVM code

Having a precompile allows non-EVM processes, i.e. transaction level signature verification, to access the registry *without* having to call into the EVM.

### Opaque `signature` type

As each algorithm has unique properties, e.g. supporting signature recovery and key sizes, the object needs to hold every permutation of every possible signature and potentially additional recovery information. A bytearray of an algorithm-defined size would be able to achieve this goal.

## Backwards Compatibility

EIP-7932 does not modify any existing logic and does not pose any backwards compatibility issues.

## Test Cases

Test cases for the `sigrecover` precompile may be found in the [precompile_test_cases.py](/EIPs/assets/eip-7932/precompile_test_cases.py) file.

## Security Considerations

Allowing more ways to derive addresses for a single account may decrease overall security for that specific account. However, this is partially mitigated by the increase in processing power required to trial all algorithms. Even still, adding additional algorithms may need further discussion to ensure that the security of the network would not be compromised.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 12 Apr 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7932</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7932</guid>
      </item>
    
      <item>
        <title>RLP Execution Block Size Limit</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7934-add-bytesize-limit-to-blocks/23589</comments>
        
        <description>## Abstract

This proposal introduces a protocol-level cap on the maximum RLP-encoded execution block size to 10 megabytes (MiB), which includes a margin of 2 MiB to account for beacon block sizes.

## Motivation

Currently, Ethereum does not enforce a strict upper limit on the encoded size of blocks. This lack of constraint can result in:

1. **Network Instability**: Extremely large blocks slow down propagation and increase the risk of temporary forks and reorgs.
2. **DoS Risks**: Malicious actors could generate exceptionally large blocks to disrupt network performance.

Additionally, blocks exceeding 10 MiB are not propagated by the consensus layer&apos;s (CL) gossip protocol, potentially causing network fragmentation or denial-of-service (DoS) conditions.

By imposing a protocol-level limit on the RLP-encoded block size, Ethereum can ensure enhanced resilience against targeted attacks on block validation times. Adding an additional margin of 2MiB explicitly accommodates beacon block sizes, ensuring compatibility across network components.

## Specification

### Block Size Cap

- Introduce constants:
  - `MAX_BLOCK_SIZE` set to **10 MiB (10,485,760 bytes)**
  - `SAFETY_MARGIN` set to **2MiB (2,097,152  bytes)**
  - `MAX_RLP_BLOCK_SIZE` calculated as `MAX_BLOCK_SIZE - MARGIN`
- Any RLP-encoded block exceeding `MAX_RLP_BLOCK_SIZE` must be considered invalid.

Thus add the following check to the Ethereum protocol:

```python
MAX_BLOCK_SIZE = 10_485_760  # 10 MiB
SAFETY_MARGIN = 2_097_152  # 2 MiB
MAX_RLP_BLOCK_SIZE = MAX_BLOCK_SIZE - SAFETY_MARGIN

# if true, the block is invalid and should be rejected/not get built
def exceed_max_rlp_block_size(block: Block) -&gt; bool:
    return len(rlp.encode(block)) &gt; MAX_RLP_BLOCK_SIZE
```

### Changes to Protocol Behavior

1. **Block Creation**: Validators must ensure the total RLP-encoded size of any produced block does not exceed `MAX_RLP_BLOCK_SIZE`.
2. **Block Validation**: Nodes must reject blocks whose RLP-encoded size exceeds `MAX_RLP_BLOCK_SIZE`.

### Protocol Adjustment

- All Ethereum client implementations must integrate this size check as part of block validation and propagation.
- This limit applies independently of gas-related metrics.

## Rationale

### Why 10 MiB?

A cap of 10 MiB aligns with the gossip protocol constraint in Ethereum&apos;s consensus layer (CL). An additional 2MiB margin explicitly accounts for beacon block sizes, ensuring compatibility and consistent block propagation across the network. Blocks significantly larger than 10 MiB will not be broadcast by the CL, potentially leading to network fragmentation or denial-of-service scenarios.

## Backwards Compatibility

This change is **not backward-compatible** with any blocks larger than the newly specified size limit. Validators and miners will need to ensure their block construction logic strictly respects this limit.

## Security Considerations

Restricting maximum block size provides inherent protection against deliberate oversized-block attacks.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Wed, 16 Apr 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7934</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7934</guid>
      </item>
    
      <item>
        <title>Set default gas limit to 60M</title>
        <category>Informational/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7935-set-default-gas-limit-to-60m/23789</comments>
        
        <description>## Abstract

The gas limit on mainnet is currently 36M. This should be significantly increased to 60M by the time Fusaka is released by execution layer clients updating their default configurations.

## Motivation

There is currently great interest in scaling L1 execution. This can likely be done to some extent without implementing any new features. However, it requires guidance from EL devs as we expect to find bugs in clients at higher gas limits than currently used on mainnet. This will require time from client developers both to test and to fix any bugs that arise, therefore it makes sense to include as an EIP in a hard fork to commit to this.

## Specification

Execution layer clients have different configuration formats. They should all update the gas limit value generated in their default configurations to 60M.

## Rationale

In the past there has been some difficulty coordinating EL clients to update gas limit values in their default configurations. Therefore we suggest tying a new value to a hard fork release.

## Backwards Compatibility

A higher gas limit should not break any existing contracts. It is possible that with a higher limit new transactions could exceed the proposed 30M transaction gas limit, so the scheduling of these two EIPs should be coordinated.

## Security Considerations

Devnets will be stood up with nodes running all combinations of EL and CL clients in order to test if a gas limit of 60M is safe. Synthetic transactions will be created until blocks are full, and network and node health monitored. If bugs are discovered, client teams will patch them and then start the process again. If everything looks good, the gas limit will be increased incrementally.

Adversarial block constructions that would increase the worst-case size have already been researched and should not be a factor below 150M gas because this is close to where the current worst-case block size of 1.79 MiB would reach the current 10MiB CL gossip limit.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 22 Apr 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7935</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7935</guid>
      </item>
    
      <item>
        <title>Versioned Proxy Contract Interface</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/new-erc-versioned-proxy-contract-interface/23743</comments>
        
        <description>## Abstract

This EIP standardizes an interface for proxy contracts that allows callers to explicitly select which version of an implementation contract they want to interact with. Unlike traditional proxy patterns that only expose the latest implementation, this standard enables backward compatibility by maintaining access to previous implementations while supporting upgrades. The versioned proxy maintains a registry of implementation addresses mapped to version identifiers, allowing callers to specify their desired version at call time.

## Motivation

Smart contract upgrades are essential for fixing bugs and adding features. Current proxy patterns typically force all callers to use the latest implementation, which can break existing integrations when interfaces change.

Furthermore, traditional proxy patterns expose all users to risk if an upgrade is malicious, as they have no choice but to use the latest implementation. This standard allows users to remain on verified versions they trust, mitigating the risk of a compromised admin key or governance process deploying harmful code.

This EIP addresses several key problems:

1. **Breaking Changes**: Interface changes in new implementations can break existing integrations.
2. **Gradual Adoption**: There is no standard way to allow gradual adoption of new contract versions.
3. **Malicious Upgrades**: Users today must trust proxy admins indefinitely, as they can&apos;t opt out of potentially harmful upgrades without ceasing use of the contract entirely.
4. **Trust Assumptions**: Contract users must maintain perpetual trust in governance or admin keys, with no ability to selectively trust specific, audited implementations.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### Interface

```solidity
interface IVersionedProxy {
    /// @notice Emitted when a new implementation version is registered
    /// @param version The version identifier
    /// @param implementation The address of the implementation contract
    event VersionRegistered(bytes32 version, address implementation);
        
    /// @notice Emitted when the default version is changed
    /// @param oldVersion The previous default version
    /// @param newVersion The new default version
    event DefaultVersionChanged(bytes32 oldVersion, bytes32 newVersion);
    
    /// @notice Registers a new implementation version
    /// @param version The version identifier (e.g., &quot;1.0.0&quot;)
    /// @param implementation The address of the implementation contract
    function registerVersion(bytes32 version, address implementation) external;
    
    /// @notice Removes a version from the registry
    /// @param version The version identifier to remove
    function removeVersion(bytes32 version) external;
    
    /// @notice Sets the default version to use when no version is specified
    /// @param version The version identifier to set as default
    function setDefaultVersion(bytes32 version) external;
    
    /// @notice Gets the implementation address for a specific version
    /// @param version The version identifier
    /// @return The implementation address for the specified version
    function getImplementation(bytes32 version) external view returns (address);
    
    /// @notice Gets the current default version
    /// @return The current default version identifier
    function getDefaultVersion() external view returns (bytes32);
    
    /// @notice Gets all registered versions
    /// @return An array of all registered version identifiers
    function getVersions() external view returns (bytes32[] memory);
    
    /// @notice Executes a call to a specific implementation version
    /// @param version The version identifier of the implementation to call
    /// @param data The calldata to forward to the implementation
    /// @return The return data from the implementation call
    function executeAtVersion(bytes32 version, bytes calldata data) external payable returns (bytes memory);
}
```

### Behavior Requirements

1. The proxy contract MUST maintain a mapping of version identifiers to implementation addresses.
2. The proxy contract MUST maintain a default version that is used when no version is specified.
3. When `executeAtVersion` is called, the proxy MUST:
   - Verify the specified version exists
   - Forward the call to the corresponding implementation
   - Return any data returned by the implementation
4. The proxy contract MUST emit appropriate events when versions are registered, or when the default version changes.
5. The proxy contract SHOULD implement access control for administrative functions (registering versions, setting default).
6. The proxy contract MAY implement [EIP-1967](/EIPs/EIPS/eip-1967) storage slots for compatibility with existing tools.

### Fallback Function

The proxy contract SHOULD implement a fallback function that forwards calls to the default implementation version when no version is specified. This maintains compatibility with traditional proxy patterns.

## Rationale

### Version Identifiers as bytes32

Version identifiers are specified as `bytes32` rather than semantic versioning strings to:
1. Provide flexibility in versioning schemes
2. Reduce gas costs for storage and comparison
3. Allow for both string-based versions (converted to bytes32) and numeric versions
4. Allow for storing a Git commit identifier in SHA-1 or SHA-256

### Explicit Version Selection

The standard requires callers to explicitly select a version through `executeAtVersion` rather than encoding version information in the call data to:
1. Maintain a clean separation between version selection and function calls
2. Avoid modifying existing function signatures
3. Make version selection explicit and auditable

### Registry Pattern

The registry pattern was chosen over alternatives like:
1. **Multiple Proxies**: Having separate proxies for each version would increase deployment costs and complexity
2. **Version in Storage**: Storing a single &quot;current version&quot; would not allow different callers to use different versions simultaneously

### Default Version

The default version mechanism allows the proxy to maintain compatibility with traditional proxy patterns and supports callers that don&apos;t need to specify a version.

## Backwards Compatibility

This EIP is designed to enhance backward compatibility for smart contracts. It does not introduce any backward incompatibilities with existing Ethereum standards or implementations.

Existing contracts that interact with proxy contracts can continue to do so without modification, as the fallback function will route calls to the default implementation.

## Security Considerations

This EIP is meant to significantly improve the security of the widely used proxy pattern.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 17 Apr 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7936</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7936</guid>
      </item>
    
      <item>
        <title>EVM64 - 64-bit mode EVM opcodes</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-9687-64-bit-mode-evm-operations/23794</comments>
        
        <description>## Abstract

This EIP introduces multibyte opcodes prefixed by `C0` for 64-bit arithmetic (`C001`-`C00B`), comparison (`C010`-`C015`), bitwise (`C016`-`C019`) and flow (`C056` and `C057`) operations.

## Motivation

Not all computations in EVM can utilize the full 256-bit integer width. It can therefore be beneficial to have a &quot;64-bit mode&quot; to avoid unnecessary cycles. This EIP uses a &quot;prefix&quot; opcode `C0`, essentially forming multibyte opcodes to avoid polluting the EVM opcode space too much.

## Specification

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

### Prefix opcode behavior

This EIP uses the prefix opcode `C0`, and it only occupies this single EVM opcode space. Upon the interpreter encountering opcode `C0`, it MUST continue to seek the next byte in code. It then executes things in &quot;64-bit mode&quot;, based on the second byte, described below. If the execution is successful, then the interpreter MUST increase `PC` by 2 (instead of 1).

If the second byte is not a valid 64-bit mode operation, then the interpreter MUST OOG.

### General 64-bit mode behavior

In 64-bit mode, all operations only work on the least significant 64-bit of each stack value. The most significant 192-bit is discarded. When a result value is pushed back onto the stack, then it MUST ensure that observable effects will see that the most significant 192-bit is zero. Note that here it&apos;s not necessary for an interpreter to reset the most significant 192-bit to zero every time -- if the next opcode is still in 64-bit mode, then the most significant 192-bit is still unobservable. We discuss the full details in the &quot;rationale&quot; section. The interpreter only needs to reproduce the full 256-bit value upon entering non-64-bit mode. If the full computational heavy part can be written in pure 64-bit mode, then this can result in noticeable performance gain.

### Gas cost constants

We define the following gas cost constants:

* `G_BASE64`: 1
* `G_VERYLOW64`: 2
* `G_LOW64`: 3
* `G_MID64`: 5
* `G_HIGH64`: 7
* `G_EXP64_STATIC`: 5
* `G_EXP64_DYNAMIC`: 25

### Arithmetic opcodes

The 64-bit mode arithmetic opcodes are defined the same as non-64-bit mode, except that it only operates on the least significant 64-bits. In the below definition, `a`, `b`, `N` is `a mod 2^64`, `b mod 2^64` and `N mod 2^64`.

* ADD (`C001`) and SUB (`C003`): `a op b mod 2^64`, gas cost `G_VERYLOW64`.
* MUL (`C002`), DIV (`C004`), SDIV (`C005`), MOD (`C006`), SMOD (`C007`), SIGNEXTEND (`C00B`): `a op b mod 2^64`, gas cost `G_LOW64`.
* ADDMOD (`C008`), MULMOD (`C009`): `a op b % N mod 2^64`, gas cost `G_MID64`.
* EXP (`C00A`): `a EXP b mod 2^64`, gas cost `static_gas = G_EXP64_STATIC, dynamic_gas = G_EXP64_DYNAMIC * exponent_byte_size`.

### Comparison and bitwise opcodes

The 64-bit mode comparison and bitwise opcodes are defined the same as non-64-bit mode, except that they only operate on the least significant 64 bits.

* LT (`C010`), GT (`C011`), SLT (`C012`), SGT (`C013`), EQ (`C014`), AND (`C016`), OR (`C017`), XOR (`C018`): `a op b mod 2^64`, gas cost `G_VERYLOW64`
* ISZERO (`C015`), NOT (`C019`): `op a mod 2^64`, gas cost `G_VERYLOW64`
* SHL (`C01B`), SHR (`C01C`), SAR (`C01D`): `a op N mod 2^64`, gas cost `G_VERYLOW64`

Note that:

* 64-bit EQ (`C014`) may return true for two different integers because it&apos;ll only compare the least significant 64 bits.
* 64-bit ISZERO (`C015`) may return true for non-zero 256-bit integers as long as the last 64 bits are zero.
* BYTE (`1A`) does not have 64-bit mode because it affects endianness.

### JUMP, JUMPI

For flow operations JUMP and JUMPI, the behavior is as follows:

* `JUMP` (`C056`) will only read the last 64 bits from the stack value. The rest 192 bits are discarded without reading. Gas cost is `G_MID64`.
* `JUMPI` (`C057`) will only read the last 64 bits from the stack as destination, and the condition check will only read the last 64 bits. Gas cost is `G_HIGH64`.
* In `JUMPDEST` validation phrase, `C0` is considered a standalone &quot;mode&quot; opcode and if the next byte followed is `JUMPDEST`, it continues to mark a valid `JUMPDEST` destination. Note that because there&apos;s no 64-bit `JUMPDEST`, during execution, `C0 JUMPDEST` would result in OOG.

## Rationale

When a smart contract uses the 64-bit mode, it&apos;s expected that once entered, it will want to stay in 64-bit mode, and only exit to non-64-bit mode when the computationally intensive function is finished. This EIP is designed particularly with this fact in mind.

All 64-bit opcodes only operates on the 64-bit value. It totally discards the rest 192 bits. The interpreter only needs to ensure that when it exits into non-64-bit mode and next time when a value result is read, that value has the first 192 bits reset to zero. The EVM interpreter can therefore use a typed stack for optimization:

```haskell
type StackItem = Value U256 | Value64 U64
```

The typed stack can also be implemented as a bitmap for memory alignment.

For all inputs of 64-bit opcodes, it will either read in a `Value`, when it&apos;ll only take the last 64 bits, or a `Value64`, which is what is needed. It then always outputs a `Value64`. After exiting into non-64-bit mode and upon a `Value64` is read, the interpreter then translate the value back to 256-bit `Value` by extending the first 192 bits with zero.

The 64-bit mode does not contain any opcodes which depends on the value&apos;s endianness, therefore `Value64` can also be stored in the optimal endianness of the architecture.

The 64-bit mode will not save any memory usage.

### Discussions

#### Prefix (modes) opcodes

This EIP also recommends that we reserve `C0`-`CF` for prefix (modes) opcodes. For example, an additional modes OVERFLOW can be envisioned that changes the behavior of arithmetic opcodes from wrapping to overflow OOG, which can help to reduce, for example, the extra cycles needed for `SafeMath`.

#### Optimization assumptions

This EIP assumes that the majority of EVM implementations target native little-endian 64-bit architectures (like `x86_64`, `arm64` and `riscv64`). A 256-bit stack item is stored efficiently internally as 4 items of 64-bit unsigned integer `[u64; 4]`. This EIP works best, in terms of optimizations, for those implementations. The opcodes simply operates on the last `u64`, instead of the whole `[u64; 4]`. There are basically no other changes.

#### Endianness

In 64-bit mode, the principle of the specification is that the endianness should be kept strictly as an implementation detail. There should not be any opcodes that depends on endian. This is important, because on the one hand, we must enable easy and fast interop for 64-bit and non-64-bit opcodes. On the other hand, the interpreter should be able to do optimizations internally whether it uses little or big endian.

Due to the issue of endianness, this EIP currently does not contain 64-bit mode `BYTE64`, memory opcodes `MLOAD64` and `MSTORE64`, and stack push opcodes `PUSH*64` (`PUSH1` to `PUSH8`).

It is possible to extend EVM64 where &quot;64-bit mode&quot; is instead defined as &quot;little-endian 64-bit mode&quot;, which can be separately discussed and specified:

* `BYTE64` will be little-endian, so instead of `(x &gt;&gt; (248 - i * 8)) &amp; 0xFF`, it will be `(x &gt;&gt; i * 8) &amp; 0xFF`.
* `MLOAD64` and `MSTORE64` loads and store little-endian 64-bit values in memory.
* `PUSH*64` (`PUSH1` to `PUSH8`) accepts literal little-endian bytes.

In specification there is no issue with the design, but this can bring significant confusions to developers. So the author advise caution.

#### `POP`, `DUP*`, `SWAP*`

There is no explicit 64-bit mode for stack operations:

* `POP` is &quot;automatically 64-bit&quot; because it only removes values from the stack.
* `DUP*` and `SWAP*` will copy or swap stack items optimized for 64-bit as is. They are kept optimized, so there&apos;s no need for separate 64-bit mode for those opcodes.

#### Drawbacks

Known drawbacks and tradeoffs of 64-bit mode includes:

* The binary size will become larger. This is apparent as previously the opcode is single byte, but now it is two bytes. Each byte costs an additional 200 gas to deposit. However, 64-bit mode opcodes are (generally) cheaper, which gives developers sufficient incentives to utilize it (at most 200 calls and the cumulative gas costs will be cheaper).

## Backwards Compatibility

This EIP introduces a new (prefix) opcode `C0`. `C0` was previously an invalid opcode that has little usage, and thus the backward compatibility issues are minimal.

## Test Cases

Test cases are organized as `[stack_item_1, stack_item_2] C0 opcode =&gt; [result_stack_item_1, result_stack_item_2]`.

* `[ff00000000000000 000000000000000 0000000000000ff 000000000000001, ff0000000000000 000000000000000 0000000000000ff f0000000000000f] C0 SHR =&gt; [&lt;0&gt; 780000000000007]`

## Reference Implementation

To be added.

## Security Considerations

To be added.

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 23 Apr 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7937</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7937</guid>
      </item>
    
      <item>
        <title>Exponential Gas Limit Increase</title>
        <category>Informational/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-9698-exponential-gas-limit-increase-via-default-client-voting-behavior/23884</comments>
        
        <description>## Abstract

This proposal introduces a deterministic gas limit growth schedule via client-side defaults. Ethereum clients will vote to increase the gas limit according to an exponential schedule unless explicitly configured otherwise by the user. The gas limit increase occurs every beacon chain epoch, aligned to a factor-of-10 increase every approximately 164,250 epochs (2 years). It will stop after 4 years when an updated gas increase schedule should be decided and committed to.

## Motivation

The current gas limit mechanism relies on miner/operator voting, which lacks coordination and predictability. While flexible, this approach can lead to stagnation or overly cautious increases. By introducing a predictable exponential growth pattern as a client default, this EIP encourages a sustainable and transparent gas limit trajectory, aligned with expected advancements in hardware and protocol efficiency.

## Specification

### Schedule

Let `G0 = 50,000,000` be the gas limit at the activation epoch. Let the activation epoch be Ethereum beacon chain **epoch 369017**, which corresponds to approximately June 1, 2025.

Let `t` be the current beacon chain epoch and `t0 = 369017` be the activation epoch.
Let `T = 164,250` be the number of epochs for a 10x increase.

The gas limit at epoch `t` is calculated as follows:

```text
G(t) = {
    current default limit, if t &lt; t0
    round(G0 * 10^((t-t0)/T)), if t0 ≤ t ≤ t0 + 2*T
    100 * G0, if t &gt; t0 + 2*T
}
```

`round` should round to the next integer. 

### Client Behavior

- At the start of each new beacon chain epoch, the default gas limit vote is recalculated using the formula above.
- Clients automatically vote for the calculated gas limit using the existing gas voting mechanism.
- Users can override this default by setting a manual gas limit policy in client configuration.

### Activation

- Activation is at Ethereum beacon chain epoch 369017.

## Rationale

This EIP maintains Ethereum&apos;s current gas voting mechanism but enhances it with a predictable and community-coordinated trajectory. By distributing responsibility across clients rather than enforcing protocol changes via consensus rules, this proposal offers flexibility while encouraging scalability.

The exponential growth model ensures gradual but significant increases, allowing the network to adapt while targeting ambitious throughput goals.

## Backwards Compatibility

The change is non-consensus and backward compatible. Clients not implementing the EIP will continue to behave as before. Only the default behavior changes; manual configuration remains supported.

## Security Considerations

A rapid increase in the gas limit may stress less-optimized nodes and increase block propagation times. However, the exponential schedule with very gradual increments per epoch gives node operators and developers ample time to adapt and optimize.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Sun, 27 Apr 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7938</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7938</guid>
      </item>
    
      <item>
        <title>Count leading zeros (CLZ) opcode</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/create-a-new-opcode-for-counting-leading-zeros-clz/10805</comments>
        
        <description>## Abstract

Introduce a new opcode, `CLZ(x)`, which pops `x` from the stack and pushes the number of leading zero bits in `x` to the stack. If `x` is zero, pushes 256.

## Motivation

Count leading zeros (CLZ) is a native opcode in many processor architectures (even in RISC architectures like ARM).

It is a basic building block used in math operations, byte operations, compression algorithms, data structures:

- lnWad
- powWad
- lambertW0Wad
- sqrt
- cbrt
- byte string comparisons
- generalized calldata compression/decompression
- bitmaps (for finding the next/previous set/unset bit)
- post quantum signature schemes

Adding a `CLZ` opcode will:

- Lead to cheaper compute.
- Lead to cheaper ZK proving costs. The fastest known Solidity implementation uses several dynamic bitwise right shifts `shr`, which are very expensive to prove. In SP1 rv32im, a 32-bit right shift costs 1.6x more than a 32-bit mul.
- Lead to smaller bytecode size. The fastest known Solidity implementation contains several large constants and is often inlined for performance.

## Specification

A new opcode is introduced: `CLZ` (`0x1e`).

- Pops 1 value from the stack.
- Pushes a value to the stack, according to the following code:

```solidity
/// @dev Count leading zeros.
/// Returns the number of zeros preceding the most significant one bit.
/// If `x` is zero, returns 256.
/// This is the fastest known `CLZ` implementation in Solidity and uses about 184 gas.
function clz(uint256 x) internal pure returns (uint256 r) {
    /// @solidity memory-safe-assembly
    assembly {
        r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))
        r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
        r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
        r := or(r, shl(4, lt(0xffff, shr(r, x))))
        r := or(r, shl(3, lt(0xff, shr(r, x))))
        // forgefmt: disable-next-item
        r := add(xor(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)),
            0xf8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff)), iszero(x))
    }
}
```

Or in Python,

```python
def clz(x):
    &quot;&quot;&quot;Returns the number of zeros preceding the most significant one bit.&quot;&quot;&quot;
    if x &lt; 0:
        raise ValueError(&quot;clz is undefined for negative numbers&quot;)
    if x &gt; 2**256 - 1:
        raise ValueError(&quot;clz is undefined for numbers larger than 2**256 - 1&quot;)
    if x == 0:
        return 256
    # Convert to binary string and remove any &apos;0b&apos; prefix.
    bin_str = bin(x).replace(&apos;0b&apos;, &apos;&apos;)
    return 256 - len(bin_str)
```

Or in C++,

```c++
inline uint32_t clz(uint32_t x) {
    uint32_t r = 0;
    if (!(x &amp; 0xFFFF0000)) { r += 16; x &lt;&lt;= 16; }
    if (!(x &amp; 0xFF000000)) { r += 8;  x &lt;&lt;= 8;  }
    if (!(x &amp; 0xF0000000)) { r += 4;  x &lt;&lt;= 4;  }
    if (!(x &amp; 0xC0000000)) { r += 2;  x &lt;&lt;= 2;  }
    if (!(x &amp; 0x80000000)) { r += 1; }
    return r;
}

// `x` is a uint256 bit number represented with 8 uint32 limbs.
// This implementation is optimized for SP1 proving via rv32im.
// For regular compute, it performs similarly to `ADD`.
inline uint32_t clz(uint32_t x[8]) {
    if (x[7] != 0) return clz(x[7]);
    if (x[6] != 0) return 32 + clz(x[6]);
    if (x[5] != 0) return 64 + clz(x[5]);
    if (x[4] != 0) return 96 + clz(x[4]);
    if (x[3] != 0) return 128 + clz(x[3]);
    if (x[2] != 0) return 160 + clz(x[2]);
    if (x[1] != 0) return 192 + clz(x[1]);
    if (x[0] != 0) return 224 + clz(x[0]);
    return 256;
}
```

The cost of the opcode is 5, matching MUL (raised from 3 to avoid under-pricing DoS risk).

## Rationale

### The special 0 case

256 is the smallest number after 255. Returning a small number allows the result to be compared with minimal additional bytecode.

For byte scanning operations, one can get the number of bytes to be skipped for a zero word by simply computing `256 &gt;&gt; 3`, which gives 32.

### Preference over `CTZ` (count trailing zeros)

Computing the least significant bit can be easily implemented with `CLZ` by isolating the smallest bit via `x &amp; -x`.

However, it is not possible to implement `CLZ` with `CTZ`.

### Gas cost

We have benchmarked the `CLZ` implementation against the `ADD` implementation in the intx library. `CLZ` uses approximately the same amount of compute cycles as `ADD`. 

The SP1 rv32im optimized variant uses less compute cycles than `ADD`, in the average and worst cases.

In SP1 rv32im, a 256-bit `CLZ` is cheaper to prove than `ADD`. 

## Backwards Compatibility

This is a new opcode not present prior.

## Test Cases

```
PUSH32 0x000000000000000000000000000000000000000000000000000000000000000
CLZ
---
0x0000000000000000000000000000000000000000000000000000000000000100
```

```
PUSH32 0x8000000000000000000000000000000000000000000000000000000000000000
CLZ
---
0x0000000000000000000000000000000000000000000000000000000000000000
```

```
PUSH32 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
CLZ
---
0x0000000000000000000000000000000000000000000000000000000000000000
```

```
PUSH32 0x4000000000000000000000000000000000000000000000000000000000000000
CLZ
---
0x0000000000000000000000000000000000000000000000000000000000000001
```

```
PUSH32 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
CLZ
---
0x0000000000000000000000000000000000000000000000000000000000000001
```

```
PUSH32 0x0000000000000000000000000000000000000000000000000000000000000001
CLZ
---
0x00000000000000000000000000000000000000000000000000000000000000ff
```

## Security Considerations

`CLZ` is a stateless opcode that has a low worst-case constant cost in memory usage, compute and proving costs. It is therefore safe from being exploited for denial of service attacks.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 28 Apr 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7939</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7939</guid>
      </item>
    
      <item>
        <title>Ethereum Shah</title>
        <category>Informational/</category>
        
          <comments>https://ethereum-magicians.org/t/discussion-for-eip-ethereum-shah/23909</comments>
        
        <description>## Abstract

Ethereum needs a Shah. The role of the Shah is to be the &quot;protector&quot;. A Shah, empowered by the community and with a mandate to represent their interests, could solve the communication gaps between the Ethereum community and core devs, represent the interests of the Ethereum community (holders, stakers, app devs &amp; businesses especially) to the core devs with a tighter feedback loop, and eventually dissolve their position when the imminent danger of Ethereum coordination failure is meaningfully addressed.

## Motivation

It is clear from recent events that Ethereum is suffering from a coordination breakdown between the user ecosystem and the core devs. A case in point is the EOF debacle, with years wasted in EOF development that ~~seems ultimately likely to be~~ was just rejected as a result of 1) fragmented communication between researchers/core devs and the greater Ethereum ecosystem, to the extent that even tentative supporters of EOF weren&apos;t aware of the toolchain update requirements on the rest of the ecosystem as well as 2) a lack of rigorous compatibility testing such that EOF exposes protocol level risks. 

A Shah is of course centralized, but we&apos;ve seen the decentralized alternative: First a tacit acceptance of a seemingly unnecessary EIP involving years of labor, approved by committee, and ultimately rejected by the Ethereum community. The costs on our collective time are large, not to mention the opportunity cost. 

Ethereum could spare itself these inefficiencies by electing a Shah to manage the core dev roadmap and EIPs.

## Specification

The Shah SHOULD be elected by the Ethereum community, using a combination of ETH voting, social signalling, and core dev ratification.

The Shah SHOULD be singularly responsible for deciding on the EIP inclusion roadmap, as well as having veto power over which EIPs to include.

The Shah SHOULD maintain communication channels with the Ethereum community (holders, stakers, app devs &amp; businesses) to understand their needs &amp; request feedback on EIPs.

The Shah SHOULD play a coordinator role in the All Core Devs (ACD) calls, and submit a quarterly progress update to Ethereum stakeholders.

The Shah SHOULD NOT have any special privileges, for example: to relieve developers of duty at organizations not under the Shah&apos;s control.

The Shah SHOULD explicitly call out blockers, communications breakdowns, and when deserving, the core devs that get in the way of addressing them.

The Shah SHOULD NOT report to the Ethereum Foundation. The Shah&apos;s position would be paid directly from the most credibly &quot;Ethereum&quot; source of funding, which has received its budget from a diverse set of Ethereum community members: The Protocol Guild. 

The Shah SHOULD have an expiration date for their role set at the time of election, that does exceed 2 years.

The Shah SHOULD be able to step down willingly before the end of their 2 year term. 

***

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

## Rationale

During times of war, the Roman Senate would elect an &quot;Imperator&quot; that would be responsible for dealing with an imminent threat, and once the threat was dealt with, would abdicate their power. The Shah is a similar concept, but rooted in the culture of the Persian Empire, which pioneered a &quot;pluralistic&quot; multi-national empire that respected cultural and religious diversity of its member nations—as aligned with Ethereum&apos;s culture of pluralism today.

This EIP is largely inspired by Greg the Greek&apos;s post (below) about the EF core devs lacking strong leadership who can take responsibility for saying &quot;NO&quot; to EIPs that they expect will ultimately be defeated by community consensus, and thus saving everyone their time, effort, and mental health. The Greeks pioneered democracy—if the will of the people is to elect (even for a limited time) a strong leader, would it not be undemocratic to deny it?

Link: x (dot) com/gregthegreek/status/1914811701901623746

&gt; All Core Devs need to centralize.
&gt; They need a leader who will say, NO.
&gt; They need to be told what not to do.
&gt; They need someone to shield them.
&gt;
&gt; ![Figure 1](/EIPs/assets/eip-7940/acd_leader.jpeg)
&gt; 
&gt; Story Time
&gt; 
&gt; I vividly remember hearing about EOF 4-5 years ago
&gt; 
&gt; I asked a simple question:
&gt; Q: How does this benefit users interacting with the chain?
&gt; A: It allows future implementations of the EVM to add those things!
&gt; 
&gt; 👎
&gt; 
&gt; Cold, hard truth. Engineers are trying to solve a problem because it&apos;s fun, not because it&apos;s needed. It has some long-tail benefits, but not enough to justify the pain that it will cause.
&gt; 
&gt; This is a full-blown toolchain update (almost). We need to prioritize things that provide incremental wins. If the team behind EOF had spent more time improving the EVM in incremental steps (ditching EOF altogether), they could have shipped so much more, which could have, in aggregate, contributed to a 10x improvement.
&gt; 
&gt; Instead, they continue to fight for a proposal that was shot down ~3 times?
&gt; 
&gt; What has EOF done?
&gt; 
&gt; - Distracted ACD for the 4th time
&gt; - Delaying roadmap by jamming a MASSIVE change into core code
&gt; - Distract @ethPandaOps who will inevitably be responsible for creating an ungodly testing framework for this change
&gt; - Caused ProgPow level wars because they can&apos;t take &quot;no&quot; for an answer
&gt; 
&gt; ONE YEAR AGO in Brussels, I asked Marius &quot;How&apos;s work?&quot; and he responded:
&gt; &gt; The EOF folks are back, the proposal is bigger than before.
&gt; 
&gt; ONE YEAR AGO - does no one see the problem here?
&gt; 
&gt; @tkstanczak @hwwonx This is the hardest role to hire for, but it needs to be done. That or one of you will need to step up and actually own this. It&apos;s clear @VitalikButerin, and we shouldn&apos;t force him to, he&apos;s better on the research side. Someone needs to run DAY-To-DAY ops/product on ACD.
&gt; 
&gt; It&apos;s exhausting. 
&gt; Let the devs ship.
&gt; Stop the politics.
&gt; Turn the ship around.
&gt; 
&gt; Please 💕

The role of the Shah would be primarily social, and they would not have any *formal* power. Their power solely comes from the belief that the community has in their power. In the context of steering the ACD calls &amp; EIP inclusion roadmap, this is actually enough. In my personal experience helping kill ProgPow, the core devs were not convinced that I adequately represented enough of the Ethereum community (despite my position as the Summoner of MolochDAO) and it took Martin Koeppelman &amp; several others to step forward to socially signal against ProgPow and ultimately join the ACD meeting to advocate against it in order to finally convince the core devs that ProgPow was against the interest of the greater Ethereum community. The role of the Shah can help short-circuit this suspicion from the core devs by having the default understanding be that the Shah does in fact represent the will of the greater Ethereum community.

In his post a few weeks ago, Tim Beiko (the current Ethereum Hard Fork Coordinator) also suggested that the ACD was missing the roadmapping role this EIP proposes to be coordinated by the Shah.

&gt; **Roadmap Setting**
The most important missing piece in the current AllCoreDevs process is a focus on the high level roadmap (“why we do things”), rather than individual proposals (“what we do”). This is true both for when planning the next fork(s), but also when thinking about Ethereum’s longer-term direction.

Link: ethereum-magicians (dot) org/t/reconfiguring-allcoredevs/23370

## Security Considerations

The obvious risk of having a Shah is that they could veto EIPs that *are* actually aligned with the Ethereum community stakeholders or prioritize EIPs that are not. In this case, it is the role of the community to publicly dissent from the Shah and ultimately remove them from office. I would expect that long before the Shah was officially deposed, the all core devs would start ignoring the Shah&apos;s input anyway, as the position does not hold any formal power. I think a fair minimum term would be 6 months (for there to be two quarterly reports at least) and with at least the same degree of community consensus around deposing the Shah as there was to enshrine them in the first place.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 28 Apr 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7940</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7940</guid>
      </item>
    
      <item>
        <title>Available Attestation</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7942-available-attestation-a-reorg-resilient-solution-for-ethereum/23927</comments>
        
        <description>## Abstract

This EIP proposes Available Attestation (AA), a protocol enhancement to make Ethereum PoS resilient against reorganization attacks. The proposal introduces a stability criterion for blocks based on attestation quorums, requiring that a block must include at least one-third of validators&apos; attestations from the previous slot to be considered stable. The proposal includes three main changes: (1) modifying the parent selection rule to require AA from the previous slot, (2) replacing HLMD-GHOST with a Longest Stable Chain fork choice rule, and (3) adding a reference field to recent unstable blocks to preserve transaction continuity. These changes collectively prevent Byzantine validators from successfully executing reorganization attacks in synchronous networks while maintaining safety and liveness properties in partially synchronous networks. A full technical analysis is available in our [companion paper](/EIPs/assets/eip-7942/available-attestation-paper.pdf) accepted to USENIX Security 2025.

## Motivation

We find that all known effective attacks on Ethereum PoS belong to reorganization attacks, although they emphasize different types of adversarial strategies. According to how the canonical chain is manipulated by the adversary, we classify known attacks into two categories: attacks from *changing block weight* and attacks from *filtering block tree*. The attacks from changing block weight refer to the strategy where Byzantine validators modify the *weight* of their proposed blocks to make their fork eventually become the canonical chain. Meanwhile, the attacks from filtering block tree do not change the block weight. Instead, these attacks make honest validators prune the canonical chain. This is often achieved by changing the *state* of honest validators. We summarize these malicious reorganization attacks in the following table.

| **attack type**         | **scheme**                                                     | **timing assumption**  | **mitigation solution**             | **limitation**                |
|-------------------------|----------------------------------------------------------------|------------------------|-------------------------------------|-------------------------------|
| changing block weight   | ex-ante reorg                                     | synchrony              | proposer boosting v1           | cause sandwich reorg          |
|                         | balancing attack                                  | synchrony              | proposer boosting v1          | cause sandwich reorg          |
|                         | sandwich reorg                                    | synchrony              | proposer boosting v2⋆         | cannot fully prevent          |
| filtering block tree    | bouncing attack                                   | partial synchrony†     | safe-slots                    | cannot fully prevent          |
|                         | unrealized justification reorg                    | synchrony              | Capella upgrade                | cause staircase attack        |
|                         | justification withholding reorg                   | synchrony              | Capella upgrade                | cause staircase attack        |
|                         | staircase attack                                  | synchrony              | Deneb upgrade                   | cannot fully prevent          |

⋆ Proposer boosting parameter decreases from 0.7 to 0.4.  
† The attack is conducted after the network is synchronous.

In response to these vulnerabilities, mitigation approaches have been proposed from both academia and industry. They are often designed in an ad-hoc way, addressing one issue at a time. Without formal proof, these mitigation approaches may create new issues. For instance, to mitigate the ex-ante reorg attack and balancing attack, Ethereum implements the *proposer boosting* mechanism. By temporarily adjusting the weight of the block in the current slot, the forks created by the adversary will not become the canonical chain. However, this mitigation approach introduces new issues. A so-called *sandwich reorg attack* was later proposed, exploiting proposer boosting to create a reorg attack. The sandwich reorg attack is a variant of ex-ante reorg attacks where two Byzantine proposers collude to make the blocks by honest validators orphaned. Additionally, many known mitigation solutions lack formal analysis or introduce additional assumptions, e.g., by assuming that the ratio of stake controlled by the adversary is no more than 20%. Therefore, our approach aims to provide a provably secure and efficient solution that is resilient to reorg attacks in Ethereum PoS.

## Specification

### Overview

We provide a lightweight yet efficient solution for Ethereum PoS which is:

1) reorg resilient in a synchronous network; 
2) safe and live in a partially synchronous network;
3) easy to implement and deploy.

We introduce AA, an approach inspired by conventional BFT protocols from *weak quorum* of attestations. Namely, consider a system with $N$ validators, among which at most $f$ are faulty. If $f+1$ validators vote for a block $b$ in slot $t$, at least one honest validator has validated $b$. The $f+1$ attestations become a *proof* of the availability of $b$. We use $AA_t$ to denote a block with $f+1$ attestations in slot $t$. 

Putting the concept of weak quorums in the context of Ethereum PoS, we define AA as a mechanism that checks *whether a block includes matching attestations from at least one-third of validators* (For simplicity, we assume that all validators attest in every slot in this section). In particular, if $b$ is a block for slot $t$, its child must include attestations for $b$ from at least one-third of validators in slot $t$. We use the notion of *stable block* to describe this scenario.

### Definition

Formally, we give the following definitions for AA:

- (AA) We use $AA_t$ to denote a block that receives more than one-third of attestations voting for it in slot $t$.

- (Stable block) *A block $b$ proposed in slot $t$ is a stable block if the parent of block $b$ is $AA_{t-1}$*

- (Unstable block) *Block $b$ is an unstable block if $b$ is not a stable block.*

- (Stable chain) *The chain $c$ is a stable chain if the leaf block of $c$ is a stable block.*

In practice, the validators are divided into 32 disjoint committees randomly. Since the committees are sampled pseudorandomly, the number of Byzantine validators in each committee can be approximated by a binomial distribution. We use $f$ as the number of total Byzantine validators and $f&apos;$ as the expected number of Byzantine validators in each committee.

- We use $\vartheta$ to denote a threshold on the number of Byzantine validators in each committee and $p$ as the desirable failure probability (i.e., the probability that the number of Byzantine validators in a committee is greater than $\vartheta$).

Given the desired value $p$, the value of $\vartheta$ can be calculated using $\vartheta = \lfloor\mu + \sigma \cdot \Phi^{-1}(1 - p)\rfloor,$ where $\mu = f&apos;$, $\sigma^2 = f&apos;(1 - f/n)$, and $\Phi^{-1}$ is the inverse of the cumulative distribution function of the normal distribution. We show some concrete examples of the ratio of Byzantine validators in a committee.

|  n     \ p   | 10⁻⁶  | 10⁻⁷  | 10⁻⁸  | 10⁻⁹  |
|-------------|--------|--------|--------|--------|
| 2¹⁴         | 0.4316 | 0.4414 | 0.4492 | 0.4570 |
| 2¹⁶         | 0.3828 | 0.3872 | 0.3916 | 0.3955 |
| 2¹⁸         | 0.3580 | 0.3603 | 0.3625 | 0.3645 |
| 2²⁰         | 0.3457 | 0.3468 | 0.3479 | 0.3489 |

Ethereum now has approximately $2^{20}$ validators. The maximum desirable probability $10^{-6}$ means that the protocol fails once every $10^{6}$ slots, i.e., 138 days. If the desirable failure probability is $10^{-9}$, malicious reorganization occurs once every 380 years. We can then draw the following conclusion: 

**For a large $n$, the ratio of Byzantine validators is closer to $f/n$. In this way, we can simply set $\vartheta$ as one-third of the committee size.**

### Protocol Changes

We make four main changes:

1. **Modify the selection rule of parent.** As mentioned in the overview, we require that a block $b$ in slot $t$ must include $\vartheta+1$ attestations to prove that the parent of block $b$ is a valid output in slot $t-1$. Therefore, the parent of block $b$ is the $AA_{t-1}$. Such a block is a stable block. If no $AA_{t-1}$ exists, the parent of block $b$ is the output of the fork choice rule. Such a block is an unstable block.

2. **Replace HLMD-GHOST with Longest Stable Chain fork choice rule.** We replace the HLMD GHOST with the longest chain as the fork choice rule. Our longest chain fork choice rule is very simple: it outputs the head of the chain with the most stable blocks. In case of a tie, the longest chain fork choice rule chooses the chain such that the leaf block has the largest slot number.

3. **Blocks carry a reference `unstable_root` to recent unstable blocks to preserve transaction continuity.** We additionally include a field `unstable_root` in a block b. Each proposer sets its `unstable_root` field as the hash of an unstable block. If there is no such unstable block, set `unstable_root` as None. The transactions in the unstable blocks should not conflict with the transactions in the longest chain. The transactions in `unstable_root` can also be finalized once block b (that includes `unstable_root`) is finalized.

4. **Simplify the filtering rule and the justification process.** We simplify the filtering rule as it only considers the chain that justifies the last justified checkpoint. Additionally, the justification process only updates when a chain crosses the epoch boundary.

### Pseudocode

The modifications are based on validator and fork-choice.

#### Modification 1

For the validator behavior specification (validator in consensus-specs):

To propose, the validator selects a `BeaconBlock`, `parent` using this process:

1. Compute AA blocks at the start of slot. Let `aa` be the later AA block and `aa_root` be the root of `aa`.
Set `parent_root = aa_root`.
2. If no AA block exists, compute fork choice&apos;s view of the head at the start of `slot`, after running
   `on_tick` and applying any queued attestations from `slot - 1`. Set `parent_root = get_head(store)`.
3. Let `parent` be the block with `parent_root`.

#### Modification 2

For the fork choice specification (fork_choice in consensus-specs):

Add a class called `chain` to manage the stable chains.

```python
@dataclass
class Chain(object):
    leaf: Root
    length: uint64
    justified_checkpoint: Checkpoint
```

Add chains in `store`.

```python
@dataclass
class Store(object):
    ...
    chains: Set[Chain]
```

Modify `get_head`

```python
def get_head(store: Store) -&gt; Root:
    # Get filtered block tree that only includes viable branches
    chains = get_filtered_block_tree(store)
    # Execute the longest stable chain fork choice
    return max(chains, key=lambda c: c.length).leaf
```

#### Modification 3

For the validator behavior specification (validator in consensus-specs):

Modify `Preparing for a BeaconBlock`

To construct a `BeaconBlockBody`, a `block` (`BeaconBlock`) is defined with the necessary context for a block proposal:

##### unstable_root

Set `block.unstable_root` as the hash of the latest unstable block if such block exists. If none exists, set `block.unstable_root = None`. The transactions in `unstable_root` must not conflict with the stable chain and will be finalized once `block` is finalized.

#### Modification 4

For the fork choice specification (fork_choice in consensus-specs):

Modify `get_filtered_block_tree`. Only consider the chain that justifies the latest justified checkpoint.

```python
def get_filtered_block_tree(store: Store) -&gt; List[Chain]:
    chains = []
    for chain in store.chains:
        if is_equal(store.justified_checkpoint.root, chain.justified_checkpoint.root):
            chains.append(chain)
    return chains
```

Remove the fields `unrealized_justified_checkpoint` and `unrealized_finalized_checkpoint`. Remove `compute_pulled_up_tip`, i.e., remove the justification and finalization process that occurs during an epoch. The `justified_checkpoint` field of a chain is only updated when crossing an epoch boundary.

## Rationale

The reason why our approach is reorg resilient is that the AA mechanism *prevents* Byzantine validators from creating conflicting branches. As summarized in the table, there are two strategies for Byzantine validators: (1) Byzantine validators directly propose a block conflicting with the canonical chain and (2) Byzantine validators propose a block that extends the canonical chain and delay releasing the block. Neither of these strategies works anymore after AA is implemented. For the first type, only the leaf blocks in the block tree can be the output of the fork choice rule. If a Byzantine validator tries to create a block $b_1$ that extends a block $b_0$ that is not a leaf block, $b_0$ will receive no attestations from honest validators. Thus, block $b_1$ is an unstable block. For the second type, our approach ensures that if Byzantine validators withhold at least two stable blocks, one of them must have already been observed by *all* honest validators (see Lemma 2 in our paper for details). 

Now it becomes clear why we use the *longest chain* rule to replace the HLMD-GHOST rule. Informally, as the HLMD-GHOST rule determines the canonical chain based on the weight of the blocks, and the weight is determined by the number of attestations, the HLMD-GHOST rule cannot prevent adversaries from withholding their attestations. 

Our modified protocol can achieve the safety and liveness properties of the consensus protocol. Safety still holds since we do not modify Casper, the finality gadget protocol. Liveness is achieved after GST mainly because our protocol is reorg resilient in a synchronous network. As all honest validators consider the blocks proposed by honest validators to be part of the longest chain, their attestations will be considered valid by all honest validators, so eventually some block is finalized. 

## Backwards Compatibility

The proposal modifies the fork choice logic and attestation format, which may not be compatible with existing clients. A hard fork or protocol version flag will be required for deployment.

## Security Considerations

- **Resilience to reorg attacks**: The protocol is provably resilient to all known forms of reorg attacks in synchronous networks.
- **No new attack surfaces**: The protocol avoids introducing new message types or unnecessary overhead.
- **Safe and live**: Maintains standard safety and liveness in partially synchronous networks.

A full formal proof of correctness and evaluation over 16,384 validators is provided in the [companion paper](/EIPs/assets/eip-7942/available-attestation-paper.pdf).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 30 Apr 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7942</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7942</guid>
      </item>
    
      <item>
        <title>uRWA - Universal Real World Asset Interface</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-universal-rwa-interface/23972</comments>
        
        <description>## Abstract

This EIP proposes the Universal RWA (uRWA) standard, a set of interfaces for tokenized Real World Assets (RWAs) such as securities, real estate, commodities, or other physical/financial assets on the blockchain.

Real World Assets often require regulatory compliance features not found in standard tokens, including the ability to freeze assets, perform enforcement transfers for legal compliance, and restrict transfers to authorized users. The uRWA standard extends common token standards like [ERC-20](/EIPs/EIPS/eip-20), [ERC-721](/EIPs/EIPS/eip-721), or [ERC-1155](/EIPs/EIPS/eip-1155) by introducing essential compliance functions while remaining minimal and not opinionated about specific implementation details.

This enables DeFi protocols and applications to interact with tokenized real-world assets in a standardized way, knowing they can check transfer permissions, whether users are allowed to interact, handle frozen assets appropriately, and integrate with compliant RWA tokens regardless of the underlying asset type or internal compliance logic. It also adopts [ERC-165](/EIPs/EIPS/eip-165) for introspection.

## Motivation

Real World Assets (RWAs) represent a significant opportunity to bridge traditional finance and decentralized finance (DeFi). By tokenizing assets like real estate, corporate bonds, commodities, art, or securities, we can unlock benefits such as fractional ownership, programmable compliance, enhanced liquidity through secondary markets for traditionally illiquid assets, and integration with decentralized protocols.

However, tokenizing real world assets introduces regulatory requirements often absent in purely digital assets, such as allowlists for users, transfer restrictions, asset freezing, or law enforcement rules. Existing token standards like [ERC-20](/EIPs/EIPS/eip-20), [ERC-721](/EIPs/EIPS/eip-721), and [ERC-1155](/EIPs/EIPS/eip-1155) lack the inherent structure to address these compliance needs directly within the standard itself.

Attempts at defining universal RWA standards historically imposed unnecessary complexity and gas overhead for simpler use cases that do not require the full spectrum of features like granular role-based access control, mandatory on-chain whitelisting, specific on-chain identity solutions, or metadata handling solutions mandated by the standard.

Additionally, the broad spectrum of RWA classes inherently suggests the need to move away from a one-size-fits-all solution. This means a minimalistic approach, an unopinionated features list, and maximal compatibility have been kept in mind as design goals.

The uRWA standard seeks a more refined balance by defining an essential interface, establishing a common ground for interaction regarding compliance and control, without dictating the underlying implementation mechanisms. This allows core token implementations to remain lean while providing standard functions for RWA-specific interactions.

The final goal is to build composable DeFi around RWAs, providing the same interface when dealing with compliance and regulation.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHOULD&quot;, and &quot;MAY&quot; in this document are to be interpreted as described in RFC 2119 and RFC 8174.

The following defines the standard interfaces for an [ERC-7943](/EIPs/EIPS/eip-7943) token contract, which MUST extend from one base token interface such as [ERC-20](/EIPs/EIPS/eip-20), [ERC-721](/EIPs/EIPS/eip-721), [ERC-1155](/EIPs/EIPS/eip-1155), or [ERC-6909](/EIPs/EIPS/eip-6909). Note that [ERC-6909](/EIPs/EIPS/eip-6909)-based implementations can use the multi token interface:

```solidity
/// @notice Interface for ERC-20 based implementations.
interface IERC7943Fungible is IERC165 {
    /// @notice Emitted when tokens are taken from one address and transferred to another.
    /// @param from The address from which tokens were taken.
    /// @param to The address to which seized tokens were transferred.
    /// @param amount The amount seized.
    event ForcedTransfer(address indexed from, address indexed to, uint256 amount);

    /// @notice Emitted when `setFrozenTokens` is called, changing the frozen `amount` of tokens for `account`.
    /// @param account The address of the account whose tokens are being frozen.
    /// @param amount The amount of tokens frozen after the change.
    event Frozen(address indexed account, uint256 amount);

    /// @notice Error reverted when an account is not allowed to send tokens.
    /// @param account The address of the account which is not allowed to send.
    error ERC7943CannotSend(address account);

    /// @notice Error reverted when an account is not allowed to receive tokens.
    /// @param account The address of the account which is not allowed to receive.
    error ERC7943CannotReceive(address account);

    /// @notice Error reverted when a transfer is not allowed according to internal rules.
    /// @param from The address from which tokens are being sent.
    /// @param to The address to which tokens are being sent.
    /// @param amount The amount sent.
    error ERC7943CannotTransfer(address from, address to, uint256 amount);

    /// @notice Error reverted when a transfer is attempted from `account` with an `amount` less than or equal to its balance, but greater than its unfrozen balance.
    /// @param account The address holding the tokens.
    /// @param amount The amount being transferred.
    /// @param unfrozen The amount of tokens that are unfrozen and available to transfer.
    error ERC7943InsufficientUnfrozenBalance(address account, uint256 amount, uint256 unfrozen);

    /// @notice Takes tokens from one address and transfers them to another.
    /// @dev Requires specific authorization. Used for regulatory compliance or recovery scenarios.
    /// @param from The address from which `amount` is taken.
    /// @param to The address that receives `amount`.
    /// @param amount The amount to force transfer.
    /// @return result True if the transfer executed correctly. Reverts on failure.
    function forcedTransfer(address from, address to, uint256 amount) external returns (bool result);

    /// @notice Changes the frozen status of `amount` tokens belonging to `account`.
    /// @dev Overwrites the current value, similar to an `approve` function.
    /// Requires specific authorization. Frozen tokens cannot be transferred by the account.
    /// @param account The address of the account whose tokens are to be frozen.
    /// @param amount The amount of tokens to freeze. It can be greater than the account balance.
    /// @return result True if the freezing executed correctly. Reverts on failure.
    function setFrozenTokens(address account, uint256 amount) external returns (bool result);

    /// @notice Checks if a specific account is allowed to send tokens according to token rules.
    /// @dev This is often used for allowlist/KYC/KYB/AML checks.
    /// @param account The address to check.
    /// @return allowed True if the account is allowed to send, false otherwise.
    function canSend(address account) external view returns (bool allowed);

    /// @notice Checks if a specific account is allowed to receive tokens according to token rules.
    /// @dev This is often used for allowlist/KYC/KYB/AML checks.
    /// @param account The address to check.
    /// @return allowed True if the account is allowed to receive, false otherwise.
    function canReceive(address account) external view returns (bool allowed);

    /// @notice Checks the frozen status/amount.
    /// @param account The address of the account.
    /// @dev It could return an amount higher than the account&apos;s balance.
    /// @return amount The amount of tokens currently frozen for `account`.
    function getFrozenTokens(address account) external view returns (uint256 amount);

    /// @notice Checks if a transfer is currently possible according to token rules. It enforces validations on the frozen tokens.
    /// @dev This can involve checks like allowlists, blocklists, transfer limits, and other policy-defined restrictions.
    /// @param from The address sending tokens.
    /// @param to The address receiving tokens.
    /// @param amount The amount being transferred.
    /// @return allowed True if the transfer is allowed, false otherwise.
    function canTransfer(address from, address to, uint256 amount) external view returns (bool allowed);
}

/// @notice Interface for ERC-721 based implementations.
interface IERC7943NonFungible is IERC165 {
    /// @notice Emitted when `tokenId` is taken from one address and transferred to another.
    /// @param from The address from which `tokenId` is taken.
    /// @param to The address to which seized `tokenId` is transferred.
    /// @param tokenId The ID of the token being transferred.
    event ForcedTransfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /// @notice Emitted when `setFrozenTokens` is called, changing the frozen status of `tokenId` for `account`.
    /// @param account The address of the account whose `tokenId` is subjected to freeze/unfreeze.
    /// @param tokenId The ID of the token subjected to freeze/unfreeze.
    /// @param frozenStatus Whether `tokenId` has been frozen or unfrozen.
    event Frozen(address indexed account, uint256 indexed tokenId, bool indexed frozenStatus);

    /// @notice Error reverted when an account is not allowed to send tokens.
    /// @param account The address of the account which is not allowed to send.
    error ERC7943CannotSend(address account);

    /// @notice Error reverted when an account is not allowed to receive tokens.
    /// @param account The address of the account which is not allowed to receive.
    error ERC7943CannotReceive(address account);

    /// @notice Error reverted when a transfer is not allowed according to internal rules.
    /// @param from The address from which tokens are being sent.
    /// @param to The address to which tokens are being sent.
    /// @param tokenId The ID of the token being sent.
    error ERC7943CannotTransfer(address from, address to, uint256 tokenId);

    /// @notice Error reverted when a transfer is attempted from `account` with a `tokenId` which has been previously frozen.
    /// @param account The address holding the token with `tokenId`.
    /// @param tokenId The ID of the token being frozen and unavailable to be transferred.
    error ERC7943InsufficientUnfrozenBalance(address account, uint256 tokenId);

    /// @notice Takes `tokenId` from one address and transfers it to another.
    /// @dev Requires specific authorization. Used for regulatory compliance or recovery scenarios.
    /// @param from The address from which `tokenId` is taken.
    /// @param to The address that receives `tokenId`.
    /// @param tokenId The ID of the token being transferred.
    /// @return result True if the transfer executed correctly. Reverts on failure.
    function forcedTransfer(address from, address to, uint256 tokenId) external returns (bool result);

    /// @notice Changes the frozen status of `tokenId` belonging to an `account`.
    /// @dev Overwrites the current value, similar to an `approve` function.
    /// Requires specific authorization. Frozen tokens cannot be transferred by the account.
    /// @param account The address of the account whose tokens are to be frozen.
    /// @param tokenId The ID of the token to freeze.
    /// @param frozenStatus Whether `tokenId` is being frozen or not.
    /// @return result True if the freezing executed correctly. Reverts on failure.
    function setFrozenTokens(address account, uint256 tokenId, bool frozenStatus) external returns (bool result);

    /// @notice Checks if a specific account is allowed to send tokens according to token rules.
    /// @dev This is often used for allowlist/KYC/KYB/AML checks.
    /// @param account The address to check.
    /// @return allowed True if the account is allowed to send, false otherwise.
    function canSend(address account) external view returns (bool allowed);

    /// @notice Checks if a specific account is allowed to receive tokens according to token rules.
    /// @dev This is often used for allowlist/KYC/KYB/AML checks.
    /// @param account The address to check.
    /// @return allowed True if the account is allowed to receive, false otherwise.
    function canReceive(address account) external view returns (bool allowed);

    /// @notice Checks the frozen status of a specific `tokenId`.
    /// @dev It could return true even if the account does not hold the token.
    /// @param account The address of the account.
    /// @param tokenId The ID of the token.
    /// @return frozenStatus Whether `tokenId` is currently frozen for `account`.
    function getFrozenTokens(address account, uint256 tokenId) external view returns (bool frozenStatus);

    /// @notice Checks if a transfer is currently possible according to token rules. It enforces validations on the frozen tokens.
    /// @dev This can involve checks like allowlists, blocklists, transfer limits, and other policy-defined restrictions.
    /// @param from The address sending tokens.
    /// @param to The address receiving tokens.
    /// @param tokenId The ID of the token being transferred.
    /// @return allowed True if the transfer is allowed, false otherwise.
    function canTransfer(address from, address to, uint256 tokenId) external view returns (bool allowed);
}

/// @notice Interface for ERC-1155 based implementations.
interface IERC7943MultiToken is IERC165 {
    /// @notice Emitted when tokens are taken from one address and transferred to another.
    /// @param from The address from which tokens were taken.
    /// @param to The address to which seized tokens were transferred.
    /// @param tokenId The ID of the token being transferred.
    /// @param amount The amount seized.
    event ForcedTransfer(address indexed from, address indexed to, uint256 indexed tokenId, uint256 amount);

    /// @notice Emitted when `setFrozenTokens` is called, changing the frozen `amount` of `tokenId` tokens for `account`.
    /// @param account The address of the account whose tokens are being frozen.
    /// @param tokenId The ID of the token being frozen.
    /// @param amount The amount of tokens frozen after the change.
    event Frozen(address indexed account, uint256 indexed tokenId, uint256 amount);

    /// @notice Error reverted when an account is not allowed to send tokens.
    /// @param account The address of the account which is not allowed to send.
    error ERC7943CannotSend(address account);

    /// @notice Error reverted when an account is not allowed to receive tokens.
    /// @param account The address of the account which is not allowed to receive.
    error ERC7943CannotReceive(address account);

    /// @notice Error reverted when a transfer is not allowed according to internal rules.
    /// @param from The address from which tokens are being sent.
    /// @param to The address to which tokens are being sent.
    /// @param tokenId The ID of the token being sent.
    /// @param amount The amount sent.
    error ERC7943CannotTransfer(address from, address to, uint256 tokenId, uint256 amount);

    /// @notice Error reverted when a transfer is attempted from `account` with an `amount` of `tokenId` less than or equal to its balance, but greater than its unfrozen balance.
    /// @param account The address holding the `amount` of `tokenId` tokens.
    /// @param tokenId The ID of the token being transferred.
    /// @param amount The amount of `tokenId` tokens being transferred.
    /// @param unfrozen The amount of tokens that are unfrozen and available to transfer.
    error ERC7943InsufficientUnfrozenBalance(address account, uint256 tokenId, uint256 amount, uint256 unfrozen);

    /// @notice Takes tokens from one address and transfers them to another.
    /// @dev Requires specific authorization. Used for regulatory compliance or recovery scenarios.
    /// @param from The address from which `amount` is taken.
    /// @param to The address that receives `amount`.
    /// @param tokenId The ID of the token being transferred.
    /// @param amount The amount to force transfer.
    /// @return result True if the transfer executed correctly. Reverts on failure.
    function forcedTransfer(address from, address to, uint256 tokenId, uint256 amount) external returns (bool result);

    /// @notice Changes the frozen status of `amount` of `tokenId` tokens belonging to an `account`.
    /// @dev Overwrites the current value, similar to an `approve` function.
    /// Requires specific authorization. Frozen tokens cannot be transferred by the account.
    /// @param account The address of the account whose tokens are to be frozen.
    /// @param tokenId The ID of the token to freeze.
    /// @param amount The amount of tokens to freeze. It can be greater than the account balance.
    /// @return result True if the freezing executed correctly. Reverts on failure.
    function setFrozenTokens(address account, uint256 tokenId, uint256 amount) external returns (bool result);

    /// @notice Checks if a specific account is allowed to send tokens according to token rules.
    /// @dev This is often used for allowlist/KYC/KYB/AML checks.
    /// @param account The address to check.
    /// @return allowed True if the account is allowed to send, false otherwise.
    function canSend(address account) external view returns (bool allowed);

    /// @notice Checks if a specific account is allowed to receive tokens according to token rules.
    /// @dev This is often used for allowlist/KYC/KYB/AML checks.
    /// @param account The address to check.
    /// @return allowed True if the account is allowed to receive, false otherwise.
    function canReceive(address account) external view returns (bool allowed);

    /// @notice Checks the frozen status/amount of a specific `tokenId`.
    /// @dev It could return an amount higher than the account&apos;s balance.
    /// @param account The address of the account.
    /// @param tokenId The ID of the token.
    /// @return amount The amount of `tokenId` tokens currently frozen for `account`.
    function getFrozenTokens(address account, uint256 tokenId) external view returns (uint256 amount);

    /// @notice Checks if a transfer is currently possible according to token rules. It enforces validations on the frozen tokens.
    /// @dev This can involve checks like allowlists, blocklists, transfer limits, and other policy-defined restrictions.
    /// @param from The address sending tokens.
    /// @param to The address receiving tokens.
    /// @param tokenId The ID of the token being transferred.
    /// @param amount The amount being transferred.
    /// @return allowed True if the transfer is allowed, false otherwise.
    function canTransfer(address from, address to, uint256 tokenId, uint256 amount) external view returns (bool allowed);
}
```

### `canSend`, `canReceive`, `canTransfer`, and `getFrozenTokens`

These provide views into the implementing contract&apos;s compliance, transfer policy logic, and freezing status.

- `canSend` and `canReceive` are account-level eligibility checks, independent of any specific transfer parameters (counterparty, amount, or token identifier). These functions:
    - MUST NOT revert.
    - MUST NOT change the storage of the contract.
    - MAY depend on on-chain state such as current timestamp, block number, or `msg.sender`.
    - MUST NOT encode transfer-specific or quantitative rules (e.g., balance checks, amount limits). Those belong in `canTransfer`.

- `canTransfer` is a transfer-level authorization check that evaluates whether a specific transfer is permissible under permissioned compliance rules. This function:
    - MUST NOT revert.
    - MUST NOT change the storage of the contract.
    - MAY depend on on-chain state such as current timestamp, block number, or `msg.sender`.
    - MUST validate that the `amount` being transferred doesn&apos;t exceed the unfrozen amount (which is the difference between the current balance and the frozen balance).
    - MUST perform a `canSend` check on the `from` parameter and a `canReceive` check on the `to` parameter. Note that [ERC-3643](/EIPs/EIPS/eip-3643) does not perform this check within `canTransfer` as this standard requires.
    - MUST return false if any permissioned rule would prevent a given transfer from succeeding. A transfer refers to any operation that emits the token&apos;s canonical transfer event. A permissioned check can be a pausing mechanism, a call to `canSend`/`canReceive`, or anything else that requires privileged actors.
    - MUST NOT return false based on token-specific, non-permissioned validations such as balance or allowance checks. These checks belong to the underlying base token standard (e.g., [ERC-20](/EIPs/EIPS/eip-20), [ERC-721](/EIPs/EIPS/eip-721), [ERC-1155](/EIPs/EIPS/eip-1155)).

- `getFrozenTokens` will return the absolute frozen amount, which MAY exceed the account&apos;s current balance. In [ERC-721](/EIPs/EIPS/eip-721) tokens, it MAY return true even if the account does not hold the token.

### `forcedTransfer`

This function provides a standard mechanism for forcing a transfer from a `from` address to a `to` address. The function:

- MUST directly manipulate balances or ownership to transfer the asset from `from` to `to` either by transferring or burning from `from` and minting to `to`.
- MUST be restricted in access.
- MUST perform necessary validation checks (e.g., sufficient balance/ownership of a specific token).
- MUST emit the base standard&apos;s canonical transfer event(s), consistent with the mechanism used (transfer or burn and mint), and MUST emit the `ForcedTransfer` event.
- In single-party permissioned contexts:
    - It MAY bypass the `canTransfer` checks. If this happens, and the transfer involves tokens that are currently counted as frozen, it MUST unfreeze the assets first and emit a `Frozen` event before the underlying base token transfer event reflecting the change. Having the unfrozen amount changed before the actual transfer is critical for tokens that might be susceptible to reentrancy attacks doing external checks on recipients, as is the case for [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155) tokens.
    - It SHOULD at least perform a `canReceive` check on the `to` parameter to ensure compliance.
- In multi-party permissioned contexts:
    - It SHOULD perform the `canTransfer` checks and SHOULD NOT bypass the frozen constraints.
- MUST revert in cases where validations and/or `canReceive` checks return false or fail.

### `setFrozenTokens`

It provides a way to freeze or unfreeze assets held by a specific account. This is useful for temporary lock mechanisms. This function:

- MUST emit the `Frozen` event.
- MUST be restricted in access.
- MUST allow freezing more assets than those held. This allows for future balances withholding.
- MUST revert in cases of logical issues or validation checks failure.

### Additional Specifications

The contract MUST implement the [ERC-165](/EIPs/EIPS/eip-165) `supportsInterface` function and MUST return true for the `bytes4` value (representing the `interfaceId`):

- `0x3edbb4c4` for the fungible interface.
- `0xbf1ef5fe` for the non-fungible interface.
- `0x41c4fbad` for the multi token interface.

Implementations of these interfaces MUST implement the necessary functions of their chosen base standard (e.g., [ERC-20](/EIPs/EIPS/eip-20) for the fungible interface, [ERC-721](/EIPs/EIPS/eip-721) for the non-fungible interface, [ERC-1155](/EIPs/EIPS/eip-1155) or [ERC-6909](/EIPs/EIPS/eip-6909) for the multi token interface) and MUST also restrict access to sensitive functions like `forcedTransfer` and `setFrozenTokens` using an appropriate access control mechanism (e.g., `onlyOwner`, Role-Based Access Control). The specific mechanism is NOT mandated by this interface standard.

Implementations MUST ensure their transfer methods exhibit the following behavior:

- **Public transfers** (`transfer`, `transferFrom`, `safeTransferFrom`, etc.) MUST NOT succeed in cases where `canTransfer` would return `false`, or where `canSend` would return `false` for the `from` address, or `canReceive` would return `false` for the `to` address.
- **Minting** in permissionless contexts (e.g., public `mint` functions) MUST NOT succeed for accounts where `canReceive` on the recipient would return `false`. In permissioned contexts (e.g., authorized minting by privileged roles), minting SHOULD respect `canReceive` checks on the recipient, though implementations MAY bypass these checks when necessary for operational or compliance reasons.
- **Burning** in permissionless contexts (e.g., public `burn` functions) MUST respect the `canTransfer` check, MUST respect the `canSend` check on the token holder, and MUST NOT allow burning more assets than the unfrozen amount. In permissioned contexts (e.g., authorized burning by privileged roles), burning MAY succeed for accounts where `canSend` on the token holder would return `false`, and MAY burn more assets than the unfrozen amount, in which case the contract MUST update the frozen status accordingly and emit a `Frozen` event before the underlying base token transfer event.

The `ERC7943CannotSend`/`ERC7943CannotReceive`/`ERC7943CannotTransfer` errors MAY be used as a general revert mechanism whenever internal calls to `canSend`/`canReceive`/`canTransfer` return false. They MAY be replaced by more specific errors depending on the custom checks performed inside those calls, or simply not used.

In general, the standard prioritizes error specificity, meaning that specific errors such as `ERC7943InsufficientUnfrozenBalance` SHOULD be thrown when applicable. The `ERC7943InsufficientUnfrozenBalance` error SHOULD be triggered when a transfer is attempted from `account` with an `amount` less than or equal to its balance, but greater than its unfrozen balance, or with a `tokenId` which is currently frozen. If the `amount` is greater than the whole balance or the `tokenId` is not owned by the `account`, unrelated to the frozen amount, more specific errors from the base standard SHOULD be used instead.

## Rationale

- **Minimalism**: Defines only the essential functions (`forcedTransfer`, `setFrozenTokens`, `canSend`, `canReceive`, `canTransfer`, `getFrozenTokens`) and associated events/errors needed for common RWA compliance and control patterns, avoiding mandated complexity or opinionated features. The reason to introduce specific errors (`ERC7943CannotSend`, `ERC7943CannotReceive`, `ERC7943CannotTransfer`, and `ERC7943InsufficientUnfrozenBalance`) is to provide completeness with the introduced functionalities (`canSend`, `canReceive`, `canTransfer`, and `getFrozenTokens`). As dictated in the specifications, error specificity is prioritized, leaving space for implementations to accommodate more explicit errors. Regarding the events `Frozen` and `ForcedTransfer`, the reason for their existence is to signal _uncommon_ transfers (like in `forcedTransfer`) but also to help off-chain indexers correctly keep track and account for asset seizures and freezing. As mentioned in the specifications, the order in which these events are emitted in relation to the base token contract events is important in practice and merits special attention.
- **Separation of concerns**: The standard separates account-level eligibility (`canSend`, `canReceive`) from transfer-level authorization (`canTransfer`). `canSend` and `canReceive` evaluate whether an account is eligible to participate independently of any specific transfer parameters such as counterparty, amount, or token identifier. `canTransfer` evaluates whether a specific transfer is permissible under permissioned compliance rules, taking into account frozen balances, transfer limits, counterparty restrictions, and account eligibility. This separation provides clear semantics for integrators and avoids confusion between account eligibility and transfer-specific validation. It also enables one-way restrictions where an account may be blocked from receiving but still allowed to send, which is common in regulated environments.
- **Flexible compliance**: Provides standard view functions (`canSend`, `canReceive`, `canTransfer`, `getFrozenTokens`) for compliance checks without dictating _how_ those checks are implemented internally by the token contract. This allows diverse compliance strategies.
- **Compatibility**: Designed as an interface layer compatible with existing base standards like [ERC-20](/EIPs/EIPS/eip-20), [ERC-721](/EIPs/EIPS/eip-721), [ERC-1155](/EIPs/EIPS/eip-1155), and [ERC-6909](/EIPs/EIPS/eip-6909). Implementations extend from [ERC-7943](/EIPs/EIPS/eip-7943) alongside their base standard interface.
- **Essential enforcement rules**: Includes `forcedTransfer` and `setFrozenTokens` as standard functions, acknowledging their importance for regulatory enforcement in the RWA space, distinct from standard transfers. Mandates access control for these sensitive functions. To maintain a lean EIP, a single `setFrozenTokens` function (which overwrites the frozen asset quantity) and one `Frozen` event were favored over distinct `freeze`/`unfreeze` functions and events.
- **[ERC-165](/EIPs/EIPS/eip-165)**: Ensures implementing contracts can signal support for this interface.

As an example, an AMM pool or a lending protocol can integrate with [ERC-7943](/EIPs/EIPS/eip-7943)-based [ERC-20](/EIPs/EIPS/eip-20) tokens by calling `canSend`, `canReceive`, or `canTransfer` to handle these assets in a compliant manner. Enforcement actions like `forcedTransfer` and `setFrozenTokens` can either be called by third-party entities or be integrated by external protocols to allow for automated and programmable compliance. Users can then expand these tokens with additional features to fit the specific needs of individual asset types, such as on-chain identity systems, historical balance tracking for dividend distributions, semi-fungibility with token metadata, and other custom functionalities.

### Extensibility

While this ERC provides the necessary primitives for regulated assets, any additional feature can be added through extensions. A few examples:

1) If for any administrative function like `setFrozenTokens` it is necessary to attach a proof to the call, the contract can have a function that batches operations like:

```solidity
contract TokenWithLegalProofs is IERC7943MultiToken {
    ...

    function setFrozenTokensWithProof(address account, uint256 tokenId, uint256 amount, bytes calldata legalProof) external onlyOwner returns (bool result) {
        /// do anything with `legalProof`
        return setFrozenTokens(account, tokenId, amount);
    }
}
```

2) Since the `setFrozenTokens` function overwrites the absolute frozen amount and given the fact that the standard allows for multiple privileged accounts, some race-conditions might happen. If that&apos;s the case, one can build an extension function that works with expected values of amounts frozen, like:

```solidity
function setFrozenTokensIf(address account, uint256 expectedPrev, uint256 newAmount) external onlyOwner returns (bool result) {
     require(frozenTokens[account] == expectedPrev, ERC7943ExpectedValueMismatch(expectedPrev, frozenTokens[account]));
     return setFrozenTokens(account, newAmount);
}
```

Alternatively, another solution can be using delta amounts:

```solidity
function setFrozenTokensDelta(address account, int256 deltaAmount) external onlyOwner returns (bool result) {
     uint256 actualValue = frozenTokens[account];
     if(deltaAmount &gt;= 0) actualValue += uint256(deltaAmount);
     else {
        uint256 sub = uint256(-deltaAmount);
        require(sub &lt;= actualValue, ERC7943ExpectedValueMismatch(sub, actualValue));
        actualValue -= sub;
     }
     return setFrozenTokens(account, actualValue);
}
```

_Note:_ These helpers reduce accidental overwrites and expand in functionalities but do not prevent same-block conflicting updates or mempool ordering races by different privileged actors.

3) Developers can also perform several operations through the use of `multicall` patterns similar to the one defined in [ERC-6357](/EIPs/EIPS/eip-6357) so that a mix of the given primitives with additional features can be batched in one transaction:

```solidity
contract ERC7943Fungible is IERC7943Fungible, Multicall {
    // Now any combination of `setFrozenTokens`/`forcedTransfer`
    // coupled with other functionalities like the ones to blacklist/whitelist users
    // can be submitted in one transaction through the use of `multicall` function
}
```

4) Functionalities like pausability can be added on top, either through the use of modifiers or directly within functions implementations:

```solidity
function canTransfer(address from, address to, uint256 amount) external view returns (bool allowed) {
    if(paused()) return allowed;
    // ... other checks
}
```

### Notes on Naming

The naming conventions in this ERC were carefully chosen to establish clarity and semantic consistency within the broader RWA ecosystem while maintaining neutrality and broad applicability.

- **`forcedTransfer`**: This term was selected for its neutrality. While names like _confiscation_, _revocation_, or _recovery_ describe specific motivations, `forcedTransfer` purely denotes the direct action of transferring assets, irrespective of the underlying reason. `forcedTransfer` was preferred over `forceTransfer` to maintain backward compatibility with [ERC-3643](/EIPs/EIPS/eip-3643).
- **`canSend` / `canReceive`**: These names were chosen to clearly express the directional nature of account eligibility: whether an account is allowed to send or receive tokens. This separation enables one-way restrictions (e.g., an account blocked from receiving but still allowed to send), which are common in regulated environments such as KYC expiry, AML alerts, or jurisdictional constraints.
- **`canTransfer`**: This name was preferred over `isTransferAllowed` for consistency with established RWA standards including [ERC-3643](/EIPs/EIPS/eip-3643) and [ERC-7518](/EIPs/EIPS/eip-7518). This alignment promotes interoperability and reduces cognitive overhead when working across different RWA tokens.
- **`setFrozenTokens` / `getFrozenTokens`**: These names were chosen for managing transfer restrictions and align with [ERC-3643](/EIPs/EIPS/eip-3643) naming patterns. _Frozen_ was also selected for its general applicability to both fungible (amount-based) and non-fungible (status-based) assets, as terms like _amount_ or _asset(s)_ might not be universally fitting.
- **`ERC7943InsufficientUnfrozenBalance`**: Discussions around _insufficient_ being similar to _unavailable_ arose, where _unavailable_ might have better suggested a temporal condition like a freezing status. However, the term _available_/_unavailable_ was also overlapping with _frozen_/_unfrozen_ creating more confusion and duality. Finally, coupling _insufficient_ with the specified _unfrozen balance_ better represents the domain, prefix, and subject of the error, according to [ERC-6093](/EIPs/EIPS/eip-6093) guidelines.

## Backwards Compatibility

This EIP defines a new interface standard and does not alter existing ones like [ERC-20](/EIPs/EIPS/eip-20), [ERC-721](/EIPs/EIPS/eip-721), and [ERC-1155](/EIPs/EIPS/eip-1155). Standard wallets and explorers can interact with the base token functionality of implementing contracts, subject to the rules enforced by that contract&apos;s implementation of `canSend`, `canReceive`, `canTransfer`, and `getFrozenTokens` functions. Full support for the [ERC-7943](/EIPs/EIPS/eip-7943) functions requires explicit integration.

## Reference Implementation

Reference implementations of uRWA for [ERC-20](/EIPs/assets/eip-7943/contracts/uRWA20.sol), [ERC-721](/EIPs/assets/eip-7943/contracts/uRWA721.sol), and [ERC-1155](/EIPs/assets/eip-7943/contracts/uRWA1155.sol) token implementations are provided in the assets folder. They use the OpenZeppelin library and include separate send/receive whitelists and enumerable role-based access control. These examples are provided for educational purposes only and are not audited.

## Security Considerations

- **Access Control for `forcedTransfer` and `setFrozenTokens`**: The security of the mechanism chosen by the implementer to restrict access to these functions is paramount. Unauthorized access could lead to asset theft. Secure patterns (multisig, timelocks) are highly recommended.
- **Front-running of the `forcedTransfer` and `setFrozenTokens` functions**: Both functions are susceptible to front-running, similar to the `approve` function of [ERC-20](/EIPs/EIPS/eip-20). Furthermore, if the suggestion to allow freezing more than what an account owns is not followed, any account may be incentivized to front-run attempts to freeze its balance when receiving new funds. Additional features to gradually increment or decrement the frozen status MAY be considered for implementation.
- **Standard Contract Security**: Implementations MUST adhere to general smart contract security best practices (reentrancy guards where applicable, checks-effects-interactions, etc.). Specifically, in the checks-effects-interactions consideration, implementations need to be aware of tokens having hooks, especially on recipients as in [ERC-721](/EIPs/EIPS/eip-721) or [ERC-1155](/EIPs/EIPS/eip-1155). In such circumstances, it might be convenient to adopt reentrancy guards to prevent unwanted executions.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 10 Jun 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7943</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7943</guid>
      </item>
    
      <item>
        <title>Confidential Transactions Supported Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/interface-of-confidential-transactions-supported-token-contract/23586</comments>
        
        <description>## Abstract
Classic token contracts like [ERC-20](/EIPs/EIPS/eip-20) enable their token holders to make transfers and/or approve others to make transfers on their behalves. The generality of token standard [ERC-20](/EIPs/EIPS/eip-20) catalyzed decentralized finance and many other blockchain applications. However, when it comes to privacy, although some technical schemes have been proposed, few standards have been established, which limits the evolution of privacy-preserving blockchain applications.

This proposal draws up a standard interface for fungible token contracts supporting confidential transactions. It provides basic transfer functionality without loss of generality, and allowance and approve functionalities. Contracts following the standard can provide confidentiality for users’ balances and token transfer value, and can enable other blockchain applications to make transfers on behalf of owners, which empowers more privacy-preserving capabilities for blockchain applications.

## Motivation
Confidential transactions have been implemented in many blockchains, either natively through blockchain protocols like Monero and Zcash, or through smart contracts like Zether[^1] without modifying the blockchain protocol.

However, few standards are proposed on Ethereum (and/or other EVM-compatible blockchains) to illustrate privacy-preserving contracts without modifying the underlying protocol. Users and applications cannot easily detect whether a token contract supports confidential transactions or not, and so cannot reliably make transfers without revealing the actual amount.

Consequently, this proposal is to standardize confidential-transaction-supported token contracts, without loss of generality, by only specifying core methods and events.

Such a standard interface allows confidential transactions of tokens to be applied by certain parties that are sensitive to transfer amounts, or by privacy-preserving applications.

Compared with application-specific confidential token designs, such as [ERC-7984](/EIPs/EIPS/eip-7984) using `bytes32` pointers representing confidential balances, open-source projects Tornado Cash and Zeto implementing a UTXO model in smart contracts, this proposal standardizes only the minimum interoperable surface in the setting of an account-based model: balance queries, transfers, delegated transfers, approvals, and related events. This allows different proof systems, ciphertext encodings, and compliance workflows to coexist behind a common interface, so wallets, bridges, exchanges, and other applications can support confidential tokens without being tightly coupled to one implementation. 

## Specification

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


### Contract Interface
Compliant contracts MUST implement the following interface:

```solidity
interface IERC7945 {
    function confidentialBalanceOf(address owner) external view returns (bytes memory confidentialBalance);

    function confidentialTransfer(
        address _to,
        bytes memory _confidentialTransferValue,
        bytes memory _proof
    ) external returns (bool success);

    function confidentialTransferFrom(
        address _from,
        address _to,
        bytes memory _confidentialTransferValue,
        bytes memory _proof
    ) external returns (bool success);

    function confidentialApprove(
        address _spender,
        bytes memory _confidentialValue,
        bytes memory _proof
    ) external returns (bool success);

    function confidentialAllowance(address _owner, address _spender)
        external
        view
        returns (bytes memory _confidentialValue);

    event ConfidentialTransfer(
        address indexed _spender,
        address indexed _from,
        address indexed _to,
        bytes _confidentialTransferValue
    );

    event ConfidentialApproval(
        address indexed _owner,
        address indexed _spender,
        bytes _currentAllowancePart,
        bytes _allowancePart
    );
}
```

Additionally, compliant contracts MAY implement the following interface:

```solidity
interface IERC7945Metadata {
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function decimals() external view returns (uint8);
}
```

#### `IERC7945Metadata`
##### Methods
###### `name`
```solidity
function name() external view returns (string memory)
```

Returns the name of the token - e.g. `&quot;MyConfidentialToken&quot;`.

OPTIONAL - This method can be used to improve usability, but interfaces and other contracts MUST NOT expect this value to be present.

###### `symbol`
```solidity
function symbol() external view returns (string memory)
```

Returns the symbol of the token, e.g. `&quot;cHIX&quot;`.

OPTIONAL - This method can be used to improve usability, but interfaces and other contracts MUST NOT expect this value to be present.

###### `decimals`
```solidity
function decimals() external view returns (uint8)
```

Returns the number of decimals the token uses - e.g. `8`, meaning the token amount should be divided by `100000000` to get its user representation.

OPTIONAL - This method can be used to improve usability, but interfaces and other contracts MUST NOT expect this value to be present.

#### `IERC7945`
##### Methods

###### `confidentialBalanceOf`

```solidity
function confidentialBalanceOf(address owner) 
external view returns (bytes memory confidentialBalance)
```

Returns the confidential balance of the account with address `owner`.

###### `confidentialTransfer`

```solidity
function confidentialTransfer(
  address _to,
  bytes memory _confidentialTransferValue, 
  bytes memory _proof
) external returns (bool success)
```

Transfers `value` amount of tokens (behind `_confidentialTransferValue`) to address `_to`, and MUST fire the `ConfidentialTransfer` event. The function SHOULD `revert` if the message caller’s `_proof` of this transfer fails to be verified.

Note:

+ Callers MUST handle `false` from `returns (bool success)`. Callers MUST NOT assume that `false` is never returned.
+ Implementations can fully customize the proof system, (de)serialization strategies of `bytes`, and/or the business workflow. For example, when implementing &quot;Zether&quot;[^1] confidential token contracts, the `_confidentialTransferValue` and accounts&apos; confidential balances will be encrypted homomorphically under ElGamal public keys, and `_proof` will consist of 3 parts to check:
    - `_confidentialTransferValue` is well encrypted under both the caller&apos;s public key and `_to`&apos;s;
    - The plaintext `value` behind `_confidentialTransferValue` is non-negative;
    - The caller&apos;s confidential balance is actually enough to pay the plaintext `value` behind `_confidentialTransferValue`.

###### `confidentialTransferFrom`

```solidity
function confidentialTransferFrom(
  address _from,
  address _to,
  bytes memory _confidentialTransferValue,
  bytes memory _proof
) external returns (bool success)

```

Transfers `value` amount of tokens (behind `_confidentialTransferValue`) from address `_from` to address `_to`, and MUST fire the `ConfidentialTransfer` event.

The `confidentialTransferFrom` method is used for a withdrawal workflow, allowing contracts to transfer tokens on your behalf. This can be used, for example, to allow a contract to transfer tokens on your behalf and/or to charge fees in sub-currencies. The function SHOULD `revert` unless the `_from` account has deliberately authorized the sender of the message via some mechanism, and SHOULD `revert` if the message caller’s `_proof` of this transfer fails to be verified.

Note:

+ Callers MUST handle `false` from `returns (bool success)`. Callers MUST NOT assume that `false` is never returned.
+ Implementations can fully customize the proof system, (de)serialization strategies of `bytes`, and/or the business workflow. For example, when implementing &quot;Zether&quot; confidential token contracts, the `_confidentialTransferValue` and accounts&apos; confidential balances will be encrypted homomorphically under ElGamal public keys, and `_proof` will consist of 3 parts to check:
    - `_confidentialTransferValue` is well encrypted under public keys of `_from`&apos;s, `_to`&apos;s, and caller&apos;s;
    - The plaintext `value` behind `_confidentialTransferValue` is non-negative;
    - The caller&apos;s confidential allowance is actually enough to pay the plaintext `value` behind `_confidentialTransferValue`.

###### `confidentialApprove`

```solidity
function confidentialApprove(
  address _spender,
  bytes memory _confidentialValue, 
  bytes memory _proof
) external returns (bool success)
```

Allows `_spender` to withdraw from caller&apos;s split part of balances multiple times, up to the amount (allowance value) behind `_confidentialValue` to 0. This function SHOULD `revert` if the message caller’s `_proof` of this transfer fails to be verified.

Caution:

This function behaves much **differently from** `approve(address,uint256)` in [ERC-20](/EIPs/EIPS/eip-20).

Calling `confidentialApprove` splits the confidential balance of caller&apos;s account into *allowance part* and *the left part*.

The values behind two parts above after calling `confidentialApprove`, and the value behind the original confidential balance of caller&apos;s account before calling `confidentialApprove`, satisfy the equation:

$$ 
value_{Behind\ Allowance\ Part} + value_{Behind\ Left\ Part} = value_{Behind\ Original\ Confidential\ Balance}
$$

+ The allowance part of the confidential balance allows `_spender` to withdraw multiple times through calling `confidentialTransferFrom` until `_spender` does not call it any more or the value behind this part is 0.
    - Every time `_spender` calls `confidentialTransferFrom`, the value behind this part will be decreased by the value behind `_confidentialTransferValue`.
+ The left part remains as the new confidential balance of the caller&apos;s account.

If this function is called again, it:

+ merges the existing allowance part into the confidential balance of the caller&apos;s account; and then
+ overwrites the current allowance part with `_confidentialValue`.

Note:

+ Callers MUST handle `false` from `returns (bool success)`. Callers MUST NOT assume that `false` is never returned.
+ Implementations can fully customize the proof system, (de)serialization strategies of `bytes`, and/or the business workflow. For example, when implementing &quot;Zether&quot; confidential token contracts, the `_confidentialValue` and accounts&apos; confidential balances will be encrypted homomorphically under ElGamal public keys, and `_proof` will consist of 3 parts to check:
    - `_confidentialValue` is well encrypted under public keys of caller&apos;s and `_spender`&apos;s;
    - The plaintext `value` behind `_confidentialValue` is non-negative;
    - The caller&apos;s confidential balance is actually enough to pay the plaintext `value` behind `_confidentialValue`.

###### `confidentialAllowance`
```solidity
function confidentialAllowance(address _owner, address _spender)
external view returns (bytes memory _confidentialValue)
```

Returns the allowance part that `_spender` is still allowed to withdraw from `_owner`.

##### Events

###### `ConfidentialTransfer`

```solidity
event ConfidentialTransfer(
  address indexed _spender,
  address indexed _from, 
  address indexed _to, 
  bytes _confidentialTransferValue
)
```

MUST trigger when tokens are transferred.

Specifically, if tokens are transferred through function `confidentialTransferFrom`, `_spender` address MUST be set to caller&apos;s; otherwise, it SHOULD be set to `0x0`.

A confidential token contract:

+ which creates new tokens SHOULD trigger a `ConfidentialTransfer` with the `_from` address set to `0x0` when tokens are minted;
+ which destroys existing tokens SHOULD trigger a `ConfidentialTransfer` with the `_to` address set to `0x0` when tokens are burned.

###### `ConfidentialApproval`

```solidity
event ConfidentialApproval(
  address indexed _owner,
  address indexed _spender,
  bytes _currentAllowancePart,
  bytes _allowancePart
)
```

MUST trigger on any successful call to `confidentialApprove(address,bytes,bytes)`.

## Rationale


### Optional Accessor of &quot;Confidential Total Supply&quot;

```solidity
function confidentialTotalSupply() external view returns (bytes memory)
```

Confidentiality of transfer amount makes it hard to support a field like `totalSupply()` in [ERC-20](/EIPs/EIPS/eip-20). When it comes to token minting or burning, if every user in this contract can access `totalSupply()` as well as decrypt it, these users will know the actual token value minted or burned by comparing the `totalSupply()` before and after such operations, which means that confidentiality no longer exists.

Contract implementations can optionally support `confidentialTotalSupply()` by evaluating whether anti-money laundering (see next part) and audit are required. That would be much more plausible by allowing a small group of parties to know the plaintext total supply behind `confidentialTotalSupply()`.

### Anti-money Laundering and Audit
To support audit of confidential transactions and total supply, especially when such token issuers are banks or other financial institutions supervised by governments or monetary authorities, confidential transactions can be implemented without changing the `confidentialTransfer` method signature, by encoding more information into parameters.

For example, in a Zether-like implementation[^2], if token transfers are required to be audited, the `confidentialTransfer` caller encrypts transfer `value` redundantly under public keys of caller&apos;s, `to`&apos;s, and a group of auditors&apos;, which makes it possible for related parties to know the real `value` behind it exactly. So does `confidentialTotalSupply()`.

### Fat Token
A confidential-transactions-supported token can also implement [ERC-20](/EIPs/EIPS/eip-20) at the same time.

Token accounts in such tokens can hold two kinds of balances. Such token contracts can optionally provide methods to hide [ERC-20](/EIPs/EIPS/eip-20) plaintext balances into confidential balances, and vice versa, to reveal confidential balances back to [ERC-20](/EIPs/EIPS/eip-20) plaintext balances.

[ERC-20](/EIPs/EIPS/eip-20) interfaces will bring much more usability and utility to confidential-transaction-supported tokens, realizing general confidentiality in the meantime.

## Backwards Compatibility

No backward compatibility issues found.


## Security Considerations
To preserve confidentiality, implementations should avoid creating (minting) or destroying (burning) tokens with plaintext value parameters, since plaintext mint or burn flows may reveal sensitive amounts even if ordinary transfers remain confidential. Implementers should also ensure that any mint, burn, transfer, approval, and delegated transfer workflows use proof and encryption schemes that do not leak transfer values or balance information through calldata, events, or auxiliary state.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[^1]:
    ```csl-json
    {
      &quot;type&quot;: &quot;article&quot;,
      &quot;id&quot;: 1,
      &quot;author&quot;: [
        {
          &quot;family&quot;: &quot;Bünz&quot;,
          &quot;given&quot;: &quot;Benedikt&quot;
        },
        {
          &quot;family&quot;: &quot;Agrawal&quot;,
          &quot;given&quot;: &quot;Shashank&quot; 
        },
        {
          &quot;family&quot;: &quot;Zamani&quot;,
          &quot;given&quot;: &quot;Mahdi&quot; 
        },
        {
          &quot;family&quot;: &quot;Boneh&quot;,
          &quot;given&quot;: &quot;Dan&quot;
        }
      ],
      &quot;DOI&quot;: &quot;10.1007/978-3-030-51280-4_23&quot;,
      &quot;title&quot;: &quot;Zether: Towards Privacy in a Smart Contract World&quot;,
      &quot;original-date&quot;: {
        &quot;date-parts&quot;: [
          [2020, 2, 10]
        ]
      },
      &quot;URL&quot;: &quot;https://eprint.iacr.org/2019/191.pdf&quot;,
      &quot;custom&quot;: {
        &quot;additional-urls&quot;: [
          &quot;https://dl.acm.org/doi/abs/10.1007/978-3-030-51280-4_23&quot;
        ]
      }
    }
    ```

[^2]:
    ```csl-json
    {
      &quot;type&quot;: &quot;article&quot;,
      &quot;id&quot;: 2,
      &quot;author&quot;: [
        {
          &quot;family&quot;: &quot;Chen&quot;,
          &quot;given&quot;: &quot;Yu&quot;
        },
        {
          &quot;family&quot;: &quot;Ma&quot;,
          &quot;given&quot;: &quot;Xuecheng&quot;
        },
        {
          &quot;family&quot;: &quot;Tang&quot;,
          &quot;given&quot;: &quot;Cong&quot;
        },
        {
          &quot;family&quot;: &quot;Au&quot;,
          &quot;given&quot;: &quot;Man Ho&quot;
        }
      ],
      &quot;DOI&quot;: &quot;10.1007/978-3-030-58951-6_29&quot;,
      &quot;title&quot;: &quot;PGC: Decentralized Confidential Payment System with Auditability&quot;,
      &quot;original-date&quot;: {
        &quot;date-parts&quot;: [
          [2020, 9, 12]
        ]
      },
      &quot;URL&quot;: &quot;https://eprint.iacr.org/2019/319.pdf&quot;,
      &quot;custom&quot;: {
        &quot;additional-urls&quot;: [
          &quot;https://link.springer.com/chapter/10.1007/978-3-030-58951-6_29&quot;
        ]
      }
    }
    ```</description>
        <pubDate>Fri, 09 May 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7945</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7945</guid>
      </item>
    
      <item>
        <title>Unidirectional Wallet Uplink aka UWULink</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7946-unidirectional-wallet-uplink-aka-uwulink/24282</comments>
        
        <description>## Abstract

Universal Wallet Uplink (UWULink) is a protocol that allows applications (dApps) to request a wallet to
make a batch of contract calls in a single atomic transaction without establishing a two-way
connection or revealing the user&apos;s address to the requester. The protocol defines a compact binary message format using
Protocol Buffers suitable for low-bandwidth channels such as QR codes or NFC tags. Two modes of operation are
supported: **Static Mode**, where the request payload directly contains the list of calls, and **Programmable Mode**,
where the payload references a contract that generates the list of calls.

## Motivation

dApps often require users to perform multistep interactions, such as approving a token and then executing a
swap. Traditionally, accomplishing this has required multiple user confirmations or complex wallet connectivity.
Recent standards like [EIP-5792] and [EIP-7702] introduced ways to batch multiple calls into one atomic operation
via JSON-RPC (e.g. `wallet_sendCalls`). However, current implementations of those solutions assume an active connection
between dApp and wallet (e.g. injected provider or WalletConnect session), which creates an additional layer of UX friction.
There is a growing need for a **privacy-preserving, frictionless workflow** where a dApp or product can trigger complex
transactions without “connecting” their wallet or needing to disclosing their address to the application.

Several trends highlight this need:

- **Atomic Multi-Call Transactions:** With the advent of account abstraction features like [EIP-7702], externally
  owned accounts (EOAs) can execute **batch transactions** a la smart contract wallets. Users expect to
  combine multiple actions (e.g. token approvals, swaps, transfers) into one confirmed transaction for better UX and
  guaranteed all-or-nothing execution. Developers likewise want to avoid partial failures or multiple prompts.

- **Privacy Concerns:** Current wallet connection flows ([EIP-1193] / [EIP-1102]) require dApps to request access to
  user accounts, linking the user&apos;s address with the dApp even before a transaction is made. By decoupling transaction
  construction from user identification, we improve privacy. The wallet should not need to announce “who” it is to the
  dApp just to receive a transaction request. A one-way communication means the dApp never learns the user&apos;s address or
  other account info, mitigating tracking and profiling risks.

- **One-Way Offline Interaction:** In many use cases (desktop-to-mobile workflows, point-of-sale terminals, printed
  media), it’s desirable to communicate a transaction request via a QR code, NFC tag, or URL without establishing a
  session. Protocols like WalletConnect provide a session-based two-way link, but are heavyweight when a simple
  one-off action is needed, and they reveal the user&apos;s account to the dApp. A unidirectional link allows, for
  example, a user to scan a QR code on a webpage or poster and complete an on-chain action entirely within their
  wallet app. This also enables fully offline dApps to hand off transactions securely to user devices.

- **Compactness for QR/NFC:** Encoding transaction data for use in QR codes or NFC imposes strict size limits. Prior
  standards (e.g. [EIP-681] Ethereum URIs) used human-readable formats that become lengthy when including contract
  data (hex-encoded addresses and calldata inflate the size). WalletConnect addressed some issues by introducing a
  more efficient URI scheme ([ERC-1328]) instead of embedding JSON in QR codes. UWULink builds on this principle by
  using a concise binary serialization (Protocol Buffers), allowing more data to be communicated in a QR code or NFC
  tap.

- **Programmability and Offloading Logic:** There are scenarios where the exact list of calls depends on on-chain state
  or user-specific data (for example, an airdrop claim that needs to gather all tokens claimable by that user, or a
  DeFi interaction where allowances may already exist). In such cases, encoding all call data statically could be
  unwieldy or inefficient if the dApp lacks knowledge of the user&apos;s address. UWULink’s **Programmable Mode** allows a
  dApp to redirect to a deterministic on-chain generator (a smart contract with a standard interface) that can produce
  the list of calls that the wallet should invoke. This allows the app to invoke arbitrary logic in generating the
  list of calls based on the state of the blockchain, still without exposing the user&apos;s address.

By addressing these points, UWULink aims to enhance user experience with one-shot multi-call transactions and improve
security and privacy by eliminating unnecessary data sharing.

## Specification

### Overview

**UWULink** defines a protobuf message format and interpretation for transaction requests sent from a dApp to a wallet.
The only operation in scope is a request for the wallet to execute an **atomic batch of contract calls** on an
EVM-compatible blockchain. The wallet, upon receiving a UWULink request (for example, via a QR code scan, deep link, or
NFC), will decode it, present the details to the user for confirmation, and if approved, execute the calls as a single
transaction on the specified chain.

Key characteristics of the protocol:

- **Unidirectional Communication:** Communication is **only dApp → wallet**. The dApp encodes a request and the wallet
  handles it. There is no handshake or return channel in the protocol itself. The wallet is not required (or able) to
  send any data back to the dApp. This one-way design ensures the dApp does not learn any information
  about the user or wallet (such as the address or which wallet app is used) at request time. It also simplifies
  implementation – the dApp’s job is simply to generate a batch of calls and display it, and the wallet’s job is to
  execute or reject the batch.

- **Atomic Batch Calls:** All calls listed in the request **MUST** be executed atomically, i.e. all succeed or all fail
  together. If any specific call would revert, the wallet should revert the entire batch.

- **No Identity / Auth Required:** Because the request is self-contained, the wallet does not need to pre-authorize the
  dApp or reveal the selected account. In traditional injected scenarios, a dApp would call `eth_requestAccounts` (as
  per [EIP-1102]) to get the user&apos;s address. With UWULink, the first and only interaction is the user willingly
  importing the transaction request (e.g. scanning the QR). The wallet should treat it similarly to how it would treat
  a transaction payload from a connected dApp, except no connection context exists. If the request is malformed
  or not supported, the wallet can simply alert the user and refuse.

- **Binary Encoding:** UWULink messages are encoded as a binary blob based on a Protocol Buffers schema. This blob is
  then further encoded into a URI for transport via QR code or NFC tag. The string encoding of a request is the
  `uwulink:`
  scheme followed by the base 64 encoded message:

  ```
  uwulink:&lt;base64_of_UWULink_message&gt;
  ```

- **Chain Identification:** The message includes a chain ID to indicate which chain the calls are intended for. The
  wallet must verify or use this chain ID when executing the transaction.
  If the wallet is not currently on the target chain, it SHOULD prompt the user to switch to that chain or automatically
  switch if permissible (similar to handling of `chainId` in [EIP-681] URIs). If the wallet cannot operate on the
  requested chain, it must reject the request. This ensures that the dApp’s intent (which chain’s contracts to interact
  with) is preserved and avoids confusion if the user is on a different network.

- **Static vs Programmable Mode:** There are two mutually exclusive ways to specify the batch of calls:

  1. **Static Mode:** The request directly contains the list of calls (each with target address, calldata, and
     optionally ETH value) that the wallet should execute in order. This mode is straightforward and similar to
     existing multi-call APIs (e.g. the JSON-RPC `wallet_sendCalls` payload from [EIP-5792]), but encoded in a
     compact binary form. This is ideal when the dApp knows exactly what actions need to be performed.
  2. **Programmable Mode:** The request contains a reference to an **on-chain “resolver” contract** and an input data
     blob. The wallet will call a predefined view function on that contract (off-chain, via `eth_call`) to **retrieve
     the actual list of calls** to execute. The resolver contract must implement a standardized interface (detailed
     below) that takes the provided input (and possibly the caller’s address or other context) and returns a set of
     calls. This mode allows dynamic computation of call lists at execution time. It improves flexibility (the dApp
     can offload complex logic or personalization to the blockchain) and keeps the QR/NFC payload small since it only
     carries a contract address and input, rather than every call’s details. For example, a dApp could include just a
     reference like “resolver contract X with input Y” and that contract’s resolver function will output perhaps
     dozens of calls based on the latest on-chain state, the user&apos;s address, etc.

The UWULink message includes a oneof/union to indicate which mode is used. Wallets **SHOULD** support both modes.

### Protobuf Schema

Below is the proposed Protocol Buffers v3&lt;!-- TODO: add a link to a specific git commit after eipw is updated --&gt; schema defining the UWULink message format:

```protobuf
syntax = &quot;proto3&quot;;

package org.ethereum.uwulink;

// The top-level UWULink transaction request message.
message UWULinkRequest {
  uint64 chain_id = 1;  // EIP-155 chain ID for the target chain

  oneof request_type {
    Batch batch = 2;
    ResolverReference resolver = 3;
  }
}

// Static batch of calls
message Batch {
  repeated Call calls = 1;
}

// Single contract call
message Call {
  bytes to = 1;                // 20-byte address of target contract
  optional bytes value = 2;    // (optional) up to 32-byte big-endian ETH value
  optional bytes data = 3;     // (optional) calldata for the call
}

// Reference to a resolver contract for dynamic call generation
message ResolverReference {
  bytes resolver_address = 1;  // 20-byte address of resolver contract
  bytes resolver_data = 2;     // opaque data to pass to resolver
}
```

**Notes on the schema:**

- We use `bytes` for addresses and other binary data. A conforming wallet implementation MUST enforce that `Call.to` and
  `ResolverReference.resolver_address` are exactly 20 bytes. The protobuf itself won&apos;t enforce length, but using a
  different length should cause the wallet to reject the message (to avoid ambiguity or mis-interpretation). The `value`
  field in `Call` can be 0 bytes (interpreted as 0 ETH) up to 32 bytes. Leading zeros in `value` SHOULD be stripped in
  the encoding for consistency (e.g., 1 wei would be encoded as `0x01` not 32 bytes padded; conversely the decoder
  should treat a missing `value` or empty `value` as 0).

- All fields are numbered for efficient encoding. The oneof `request_type` ensures only one of Batch or
  ResolverReference is in use. If an unknown field is present (e.g., a future extension), the wallet should ignore those
  unknown fields per protobuf default behavior, but core fields must be present for validity (chain_id and one of
  batch/resolver).

- If using a text encoding (like Base64) to embed in a URI, the entire `UWULinkRequest` message is serialized to a
  binary string, then that binary is base64-encoded. For URI safety, base64 output may need to be URL-encoded (i.e.,
  `+`, `/` characters percent-encoded or using the URL-safe base64 variant). This is an implementation detail, but
  wallet developers should be aware when parsing input. In all cases, the underlying data after decoding is expected to
  match the protobuf schema above.

- The schema is chosen for broad compatibility. Proto3&apos;s varint encoding will handle the `chain_id` (which is usually
  small like 1, 137, etc.) in 1-2 bytes. The `calls` repeated field will simply concatenate call entries. Each call
  entry will have a 1-byte field tag for `to` followed by 20 bytes address, etc. This results in a very compact
  representation.

- Example of an encoded message (for illustration): A static request for chain 1 with two calls might look like:

  - Call 1: to = `0x111111...1111`, value = none (0), data = `0xabcdef`
  - Call 2: to = `0x222222...2222`, value = 100 wei, data = (empty)
  - After encoding in protobuf and base64, the URI could be:
    `ethereum:uwulink?request=EiABAggDEhARERERERERERERERERERERERERERIAGKDCr+8=` (this is a fake example string for
    concept; actual encoding would differ).
  - The wallet would decode that back to the structured fields.

Wallet and dApp developers can import this `.proto` to ensure they are constructing and parsing UWULink messages
consistently.

### Resolver Contract Interface (Programmable Mode)

This standard introduces an interface that resolver contracts must implement so that wallets can query them for call
batches. All resolver contracts **MUST** implement the following ABI (interface identifier `UWUResolver`):

```solidity
/// @title UWULink Resolver Interface
interface UWUResolver {
    struct Call {
        address target;
        uint256 value;
        bytes data;
    }

    // Thrown when calls could not be generated, with an error code specific to this resolver.
    error CallGenerationFailure(uint256 errorCode);

    /**
     * @notice Compute a batch of calls for a given request.
     * @param requester The address of the wallet (EOA or contract) that is requesting the calls.
     * @param data Arbitrary request data (opaque to the wallet, provided by dApp via UWULink).
     * @return calls The list of calls that correspond to the requester and request
     */
    function getCalls(address requester, bytes calldata data) external returns (Call[] memory calls);

    /**
     * @notice Returns the details for the given error code. Meant to be called by developers to better understand the error code for a resolver.
     *  Due to localization needs, it is expected that developers may call this function, but the wallet should not show this information to users.
     */
    function getErrorCodeDetails(uint256 errorCode) external returns (string memory information);
}
```

- The function **MAY** modify state. Wallets **SHOULD** call it off-chain, and avoid combining the call with others e.g.
  via Multicall.
- The `requester` is included to allow the contract to tailor results to the specific user. For example, a resolver
  could check `requester`’s token holdings or permissions and then return different call sets. The wallet should supply
  its own sending address as `requester`. This means that the user’s address is revealed _only to the RPC server_ used
  by the wallet via this call, not to the dApp server or UI. In the future with the propagation of light clients, it&apos;s
  possible for the wallet to avoid revealing this information.
- The `data` parameter is the exact bytes provided in the UWULink request’s `resolver_data`. Its contents and encoding
  are defined by the dApp’s usage and the contract’s logic. For instance, it might contain an enum indicating which
  action to perform, or some user-specific claim ID, etc.
- The size of the returned arrays is not explicitly limited by this standard, but practical use should keep it
  reasonable (dozens rather than thousands of calls) both for blockchain computation reasons and for the user’s ability
  to comprehend the request.

Wallets should implement the following logic for programmable requests:

1. Perform an `eth_call` to `resolver_address` with `to = resolver_address`, `from = address(0)`,
   `data = ABIEncodeWithSelector(UWUResolver.getCalls, userAddress, resolver_data)` against the latest block. The wallet
   **MAY** use the pending block, or otherwise include transactions in the state that are yet to be included in a
   confirmed block.
2. If the call returns successfully, decode the result. This becomes the batch of calls to execute. The wallet should
   then proceed exactly as if it were a static mode request containing those calls. It should display these calls to the
   user for confirmation (including target addresses, values, and perhaps decoded method signatures if it can).
3. If the call fails (reverts or is not implemented), the wallet **MUST** abort. It SHOULD surface an error to the user
   like &quot;Transaction request generation failed: resolver contract call was unsuccessful.&quot; The user then knows the dApp’s
   request was bad or the contract might be wrong.

The dApp developer and resolver contract developer are responsible for ensuring that calling `getCalls` is not too
gas-intensive to execute (since wallets will execute it off-chain but it still must complete execution). Excessive
computation could result in the node returning an error (out of gas exception in the eth_call context). Typically these
functions will just gather data from known contracts or encode some predefined calls, which should not be prohibitively
expensive.

### Example Usage

To illustrate how UWULink can be used in practice, consider the following scenarios:

**1. Static Mode – Token Approval and Swap (DeFi use-case):**

Alice wants to trade tokens on a decentralized exchange (DEX) using her mobile wallet, but she doesn&apos;t want to connect
her wallet to the DEX website due to privacy concerns. The DEX dApp prepares a UWULink QR code for the trade. When Alice
selects the tokens and amount on the website, the dApp formulates two contract calls: one to the [ERC-20] token contract
to `approve()` the DEX&apos;s router contract, and one to the router contract to execute the swap (
`swapExactTokensForTokens`, for example). Normally this would be two separate transactions with two confirmations.
Instead, the dApp bundles them:

- Call #1: `to = TokenContract, data = approve(router, amount)`
- Call #2: `to = RouterContract, data = swapExactTokensForTokens(params...)`

Both calls have `value = 0` (no ETH being sent directly). The dApp encodes these into a UWULinkRequest (static mode) for
the current chain (e.g. Ethereum mainnet chain_id 1). The protobuf binary is base64 encoded and placed into a QR code
with a URI like:

```
uwulink:CgEBEiAx...   (truncated)
```

Alice scans this QR with her wallet app. The wallet decodes the request: chain_id=1, two calls in batch. It recognizes
it can execute an atomic batch (Alice’s wallet supports [EIP-7702]). The wallet UI shows Alice a summary: &quot;This dApp is
requesting two actions: (1) Approve Token XYZ for spending, (2) Swap Token XYZ for Token ABC on DEX.&quot; Alice can inspect
the contract addresses (perhaps the wallet resolves known token/contract names or shows the hex addresses) and the
parameters. She sees that both will be submitted together in one transaction. The UI might look similar to a multi-call
confirmation screen.

Alice accepts. Her wallet internally either crafts a 0x4 type transaction (since Alice is an EOA on Ethereum) embedding
bytecode to do the two calls, or uses its smart wallet module. It then signs and broadcasts the transaction. On-chain,
the two calls execute one after the other, and because of atomicity, if the swap were to fail, the approve would be
reverted too (avoiding a scenario where she approved tokens without actually swapping).

The DEX backend or frontend can monitor the blockchain for the transaction receipt (it knows what actions it expected,
or Alice can manually input the tx hash if needed). The important part is the DEX never learned Alice’s address
beforehand; it only sees it when the transaction hits the blockchain, which is unavoidable for executing the trade but
at that point privacy is preserved as well as any normal on-chain interaction (the dApp cannot link it to Alice’s web
session unless Alice herself tells it out-of-band). This shows how UWULink achieves one-scan confirmation for what used
to be multi-step, and keeps Alice’s identity private until the on-chain execution.

**2. Programmable Mode – Personalized Airdrop Claim:**

A project is running an airdrop where eligible users can claim several different token rewards based on on-chain
activity. Bob visits the airdrop dApp page. The page could ask Bob to connect his wallet to figure out what he’s
eligible for, but Bob is cautious. Instead, the dApp uses UWULink in programmable mode. It has a resolver contract
deployed on-chain which, given a user address, can determine all the reward token contracts and amounts that the user is
entitled to claim.

The dApp shows Bob a “Claim Rewards” button, which reveals a QR code. This QR encodes a UWULink request with:

- `chain_id = 5` (Goerli testnet, for example, where the airdrop is happening).
- `resolver_address = 0xDeeD…1234` (the address of the AirdropResolver contract).
- `resolver_data =` some bytes encoding maybe an airdrop campaign identifier or simply empty if one global campaign.

Bob scans this with his wallet. The wallet sees it&apos;s a resolver-type request. It calls
`getBatchCalls(BobAddress, resolver_data)` on `0xDeeD...1234` (as a view call). The AirdropResolver contract looks up
internally that BobAddress is eligible for 3 tokens: TokenA, TokenB, and TokenC with certain amounts, and the claim
function for each is `claim(address claimant, uint256 amount)` on each token’s distributor contract. It returns three
arrays: targets = `[AddrA, AddrB, AddrC]`, values = `[0,0,0]` (no ETH needed), callData =
`[ abi.encodeWithSelector(Distributor.claim, Bob, amtA), ... ]` for each token.

The wallet receives these arrays. It now has three calls to execute. It shows Bob: &quot;Claim TokenA: amount X, Claim
TokenB: amount Y, Claim TokenC: amount Z&quot; (assuming the wallet can decode the function signatures or at least show
contract addresses and method names if it has ABIs). Bob approves the batch. The wallet then either directly calls each
distributor’s `claim` in one aggregated transaction. Because Bob’s address was provided to the resolver, each claim call
will credit tokens to Bob (likely the contract uses the provided address or `msg.sender` – here it was likely coded to
use the address parameter, since the actual transaction sender will be Bob’s own address in the batch execution
context). The important part is Bob did not have to connect his wallet to the dApp; the eligibility and calls were
determined by the on-chain contract. The dApp never saw Bob’s address, yet Bob gets his tokens in one go.

After execution, Bob’s wallet shows the transaction success. The dApp might simply tell him to check his balances (or it
could have a public page showing which addresses claimed, etc., but it did not get a direct notification — it relies on
Bob or the blockchain to know the claim happened).

**3. Cross-Device Payment via NFC (Point of Sale):**

Carol is at a merchant&apos;s point-of-sale device that accepts cryptocurrency payments via Ethereum. The merchant’s device
can display a QR or emit an NFC message with a payment request. Instead of using a simple one-address payment URI (as in
[EIP-681]), the merchant uses UWULink to request a more sophisticated transaction: perhaps Carol will pay through a
specific escrow contract or with a certain token if she has a discount coupon.

The device sends an **NFC payload** which Carol’s phone picks up (many wallet apps can register as handlers for certain
NDEF messages or custom URI schemes). The payload contains a UWULinkRequest in static mode:

- chain_id = 137 (Polygon, where the merchant operates).
- Two calls: first call to a stablecoin contract’s `transfer(merchantAddress, amount)` (to pay the merchant), second
  call to a logging contract `registerPurchase(merchantId, CarolAddress, amount)` (to log the sale in an on-chain
  registry). Both calls are value 0 since a token transfer, not ETH, is used.

Carol’s wallet opens with the decoded request: It shows &quot;Pay 50 USDC to Merchant XYZ and register purchase.&quot; Carol sees
the merchant name resolved from the merchant’s address (if her wallet has ENS or a local registry of known merchants).
She approves. The wallet then executes an atomic transaction on Polygon that calls the USDC token contract and the
registry contract. The merchant’s PoS waits for confirmation on-chain (or simply trust the signed transaction once
broadcast, depending on their risk tolerance). Carol’s identity remained pseudonymous; the merchant’s device did not
directly get her wallet info, it only received the on-chain payment. And Carol only had to tap once to approve both
token transfer and logging, rather than scan one QR to pay then perhaps another to log, etc.

These examples demonstrate the flexibility of UWULink:

- In all cases, the user did not pre-connect their wallet to the application.
- The requests can be transferred via out-of-band channels (QR/NFC/URL).
- Multi-step operations become “one-click” (or one-scan) operations for the user.
- The on-chain outcome is the same as if the user had manually sent those transactions, but with improved UX and
  privacy.

## Rationale

TBD &lt;!-- TODO --&gt;

## Backwards Compatibility

UWULink is an additive protocol and does not break any existing standards. It is designed to coexist with current
methods:

- **Existing Wallet URIs ([EIP-681], [EIP-831]):** UWULink can be seen as an evolution of the idea behind EIP-681 (
  transaction request URIs). EIP-681 defines URIs for a single transaction (or payment) and is already supported in a
  limited number of wallets for QR code scanning. UWULink extends the concept to multiple calls and binary encoding. A
  wallet that does not recognize the `uwulink:` scheme should simply not act on it. Typically, such
  a wallet would either show an error or ignore a scanned QR it cannot parse. This is a graceful failure from the user&apos;s
  perspective (they&apos;ll know the wallet doesn&apos;t support that request). There is no risk of confusing an UWULink QR with
  an EIP-681 QR, since the scheme and content format differ. Therefore, wallets that only implement support for EIP-681
  will not mistakenly handle a UWULink payload as a valid request.

- **Ensuring Backwards Compatibility in Data Format:** The protobuf schema is designed such that new fields could be
  added in the future in a non-breaking way (per Proto3 rules, unknown fields are ignored by receivers). For example, a
  future version might add an optional `uint64 expiration_timestamp` or `string origin` field to carry a domain name for
  UI display. An older wallet would ignore these and still execute the core request. This forward-compatibility means
  UWULink can evolve without breaking older implementations, as long as additions are carefully made optional.

- **Fall-back to Standard Flows:** From a dApp perspective, implementing UWULink does not preclude supporting
  traditional wallet connections. A dApp can offer UWULink QR codes for users who prefer privacy or are on devices (like
  a separate mobile) without browser extensions. At the same time, it can have the usual “Connect Wallet” button for
  users who are okay with that. This multi-modal approach ensures no user is left out. Over time, if UWULink (or similar
  one-way flows) prove safer and more popular, they might become the default, allowing users to interact with dApps
  without connecting a wallet.

- **Network Compatibility:** We limit scope to EVM-compatible chains. That means chains that use [EIP-155] transaction
  scheme and Ethereum-like addresses. On non-EVM chains, this standard doesn’t apply (though analogous concepts could).
  Within EVM chains, a nuance: if a chain has a different maximum gas limit or transaction format peculiarity, the
  wallet internally deals with that. UWULink just says &quot;execute these calls.&quot; As long as the wallet can create a
  transaction that does so, it’s fine. If an EVM chain does not support atomic multi-call (some L2s or sidechains might
  not immediately support EIP-7702), the wallet has to handle it at the account abstraction layer if possible, or
  otherwise **MUST** reject the request. This again falls to the wallet to know its capabilities (e.g. per [EIP-5792]’s
  capabilities query).

In conclusion, UWULink aims to introduce new functionality without disrupting existing user journeys. It is opt-in for
all parties. Early adopters (both dApps and wallets) can experiment with it while others continue as usual. As support
grows, it could become a widely recognized standard for secure one-way wallet interactions. The design takes into
account lessons from previous proposals ([EIP-681] URIs, WalletConnect, [EIP-5792], etc.) and ensures that adopting UWULink
is a low-risk enhancement rather than a breaking change to Ethereum’s ecosystem.

&lt;!-- TODO: Reference Implementation --&gt;

## Security Considerations

### Privacy

UWULink is designed with privacy in mind, but it introduces some new security aspects that implementers and users should
consider:

- _No Wallet Identification:_ The wallet does not disclose the user’s address or any wallet details to the dApp when
  using UWULink. This significantly improves privacy compared to typical wallet connect flows. The dApp only learns of
  the user&apos;s address if and when the transaction is broadcast on-chain. Even then, the dApp cannot easily correlate that
  address with a specific user session (the user could be anonymous on the website until that point).
- _On-Chain Resolver Calls:_ In programmable mode, the user&apos;s address is supplied to the resolver contract as a
  parameter. This happens off-chain via `eth_call`, so it does not create a public transaction. However, the node or RPC
  provider that the wallet uses will see that call (just like any read call). If the RPC provider is untrusted, this
  could leak some information (e.g., that this address is interested in this resolver&apos;s data). In most cases this is a
  minor concern (no more revealing than using the dApp itself while connected to an RPC), but users who are extremely
  privacy-conscious might prefer static mode or ensure they use a privacy-respecting RPC. Importantly, the dApp backend
  or frontend does not see this – only the blockchain infrastructure does.
- _No Third-Party Tracking:_ Because UWULink can be used via local channels (QR/NFC), it avoids relying on any
  centralized relay. WalletConnect v1, for instance, used relay servers and handshake topics which, in theory, could be
  tracked or snooped (even though payloads were encrypted, the metadata might leak usage patterns). UWULink in contrast
  can be a completely peer-to-peer (user and dApp) interaction with minimal digital footprint aside from the eventual
  blockchain transaction.
- _User Consent:_ As with any transaction, the user explicitly consents by scanning and approving the request. The
  user relies on the wallet&apos;s simulation and multi-factor authorization capabilities to prevent sending of malicious
  transactions.

### Security of Transaction Requests

- _Phishing and Malicious QR Codes:_ A malicious actor could present a user with a UWULink QR code that, if scanned and
  approved blindly, could cause the user to transfer funds or approve tokens to the attacker. This risk is analogous to
  phishing links or malicious dApp websites in today&apos;s context. Users should be educated to only approve UWULink
  requests from sources they trust or understand. Wallets should help by displaying **clear human-readable information**
  about what the request will do:

  - Show the names or ENS of known contract addresses involved (or at least highlight unknown addresses).
  - Decode function selectors to known function names if possible (e.g., show &quot;approve(address \_spender, uint256
    \_value)&quot; instead of raw hex).
  - For value transfers, show the ETH or token amount in a friendly format.
  - Possibly warn if the request involves calling an unrecognized contract with large value transfers or if it sets a
    high token allowance, etc.

- _Atomic Execution and Reverts:_ By enforcing atomic execution, UWULink ensures that partial completion won&apos;t lead to
  stuck funds or unintended states. However, this also means a malicious or buggy request could be crafted to always
  revert (for example, by including an incompatible call), which could waste user gas fees if not caught. Wallets should
  simulate the batch when possible. If the wallet can do a dry-run (for instance using `eth_call` on a Bundler or
  internal simulation) it might detect a guaranteed revert and inform the user that the call set is invalid (though this
  might be complex to do reliably for all calls).

- _Resolver Contract Trust:_ The programmable mode introduces a potential trust issue: the user is effectively trusting
  the resolver contract’s code to generate the calls honestly. If the resolver contract is malicious, it could return
  call data that benefits an attacker. For example, a malicious resolver could ignore the input data and always return a
  call transferring all of the user&apos;s ETH to the attacker’s address. **Mitigations:**

  - Ideally, resolver contracts should be open source and verified, and the dApp using them should be reputable. The
    wallet can’t fully know if the resolver’s output is malicious until it sees it, but the user will have a chance to
    review the resulting calls anyway. This is crucial: the wallet must display the _resulting calls_ from the
    resolver to the user, just as it would in static mode. The user should then notice if something is off (e.g., a
    transfer of all their ETH is about to happen).
  - Wallet developers might consider adding special handling or warnings if a resolver returns calls that do not seem
    correlated with the input. However, this is hard to generalize. At minimum, treat the resolver output with the
    same suspicion as a static request. There’s no inherent additional risk beyond what static mode has, because the
    user still confirms the final calls. The difference is just where the call data came from.
  - We assume resolver contracts will often be provided by the same party as the dApp and thus come with an implied
    level of trust (or at least, they can be audited by the community if the UWULink scheme becomes popular).

- _No Automatic Spending:_ UWULink does not introduce new signing or authorization paradigms – it uses actual
  transactions that the user signs on the spot. Thus, it’s less prone to the kind of issues where a signature can be
  later reused (like the risks with off-chain signatures). Each UWULink request is one transaction (with possibly
  multiple subcalls). After it&apos;s executed, the link cannot be reused to automatically trigger more actions (unless the
  user scans it again). This is good from a security standpoint since it doesn&apos;t create long-lived permissions. One
  exception: if a call within the batch is an approval or something, that is an on-chain permission that persists as
  usual (the user should be made aware as normal).
- _Denial of Service (DOS):_ A malicious dApp could craft an extremely large UWULink payload (especially in static mode)
  that could crash or slow a wallet app upon scanning (due to memory or decoding issues). Wallets should implement size
  limits and perhaps streaming parsing for the protobuf to avoid crashes. If a payload exceeds a reasonable size (e.g.,
  several kilobytes), the wallet can reject it for safety. Similarly, a resolver contract could try to return extremely
  large results – wallets should guard against that by limiting the amount of gas provided to the resolver via eth_call.
- _Capabilities and Future Extensions:_ UWULink intentionally does not carry any additional flags like gas limits or
  paymaster info (unlike EIP-5792 which has a capabilities system). This is to keep the format simple. However, this
  means the wallet will apply its own heuristics for gas, and by default the user pays fees. If a future extension
  wanted to allow gas sponsorship or other features, that could be added either by extending the protobuf (e.g., adding
  an optional paymaster field) or by having the resolver contract itself handle that (e.g., a resolver could incorporate
  a paymaster logic by returning a call to a paymaster contract as part of the batch). In any case, security
  considerations around gas (like a malicious paymaster causing some weird behavior) would need to be analyzed. For now,
  UWULink operates within the normal transaction model, so the main security focus is on the correctness of calls.

**Comparison to Traditional Flows:** One might ask, does eliminating the wallet &lt;-&gt; dApp handshake create any new risks?
In traditional connected dApp sessions, the wallet at least knows the origin of requests (e.g., which website is calling
`eth_sendTransaction` or `wallet_sendCalls`). In UWULink, the origin is essentially &quot;the QR code the user scanned&quot; – the
wallet might know the payload came via a QR/NFC but not which app or site. In security terms, this means the wallet
cannot apply domain-based whitelists or blocklists (since there&apos;s no domain, unless the URI contains one in the payload
which it typically wouldn&apos;t). Therefore, **the user must manually trust and verify each request.** This is akin to using
a hardware wallet: every transaction is shown on a screen and the user approves it, with no assumptions about where it
came from. This places responsibility on the user and makes the wallet’s job of displaying info accurately even more
important.

**Privacy vs. Usability Trade-off:** Because UWULink doesn’t let the dApp query the wallet off-chain, some conveniences
are lost – e.g., the dApp cannot automatically fetch the user&apos;s address to display their balance or NFTs in the UI prior
to a transaction. This is a conscious privacy trade-off. Some advanced dApps might find workarounds (like asking the
user to input their address manually if they want to see personalized info, or shifting more logic on-chain as in
programmable mode). Users and dApp developers must understand this trade-off. In contexts where user personalization
without login is needed, UWULink might require a bit more creativity, but it ensures that if the user chooses not to
share anything, they truly don&apos;t until a transaction is made.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[EIP-155]: /EIPs/EIPS/eip-155

[EIP-5792]: /EIPs/EIPS/eip-5792

[EIP-7702]: /EIPs/EIPS/eip-7702

[EIP-1193]: /EIPs/EIPS/eip-1193

[EIP-1102]: /EIPs/EIPS/eip-1102

[EIP-681]: /EIPs/EIPS/eip-681

[ERC-1328]: /EIPs/EIPS/eip-1328

[EIP-5792]: /EIPs/EIPS/eip-5792

[EIP-831]: /EIPs/EIPS/eip-831

[ERC-20]: /EIPs/EIPS/eip-20
</description>
        <pubDate>Sat, 10 May 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7946</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7946</guid>
      </item>
    
      <item>
        <title>Account Abstraction Recovery Interface</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7947-account-abstraction-recovery-interface-aari/24080</comments>
        
        <description>## Abstract

Introduce a universal account abstraction recovery mechanism `recoverAccess(subject, provider, proof)` along with recovery provider management functions for smart accounts to securely update their access subject.

## Motivation

Account abstraction and the &quot;contractization&quot; of EOAs are important Ethereum milestones for improving on-chain UX and off-chain security. A wide range of smart accounts emerge daily, aiming to simplify the steep onboarding curve for new users. The ultimate smart account experience is to never ask them to deal with private keys, yet still allow for full account control and access recovery. With the developments in the Zero-Knowledge Artificial Intelligence (ZKAI) and Zero-Knowledge Two Factor Authentication (ZK2FA) fields, settling on a common mechanism may even open the doors for &quot;account recovery provider marketplaces&quot; to emerge.

The account recovery approach described in this proposal allows for multiple recovery providers to coexist and provide a wide variety of unique recovery services. In simple terms, smart accounts become &quot;recovery provider aggregators&quot;, making it possible for the users to never rely on centralized services or projects.

The Account Abstraction Recovery Interface (AARI) aims to define a flexible interface for *any* smart account to implement, allowing users to actively manage their account recovery providers and restore the access of an account in case of a private key loss.

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

A smart account willing to support AARI MUST implement the following interface:

```solidity
pragma solidity ^0.8.20;

/**
 * @notice Defines a common account recovery interface for smart accounts to implement.
 */
interface IAccountRecovery {
    /**
     * MUST be emitted whenever the access of the account changes as a result 
     * of the account recovery (e.g. in the `recoverAccess` function).
     */
    event AccessRecovered(bytes subject);
    
    /**
     * MUST be emitted whenever a new recovery provider is added to
     * the account (e.g. in the `addRecoveryProvider` function).
     */
    event RecoveryProviderAdded(address indexed provider);

    /**
     * MUST be emitted whenever a recovery provider is removed from
     * the account (e.g. in the `removeRecoveryProvider` function).
     */
    event RecoveryProviderRemoved(address indexed provider);

    /**
     * @notice A function to add a new recovery provider.
     * SHOULD be access controlled.
     * MUST check that `provider` is not `address(0)`.
     * MUST call `subscribe` on the `provider`.
     * MUST pass `recoveryData` to the `subscribe` function.
     * 
     * @param provider the address of a recovery provider (ZKP verifier) to add.
     * @param recoveryData custom data (commitment) for the recovery provider.
     */
    function addRecoveryProvider(address provider, bytes memory recoveryData) external payable;

    /**
     * @notice A function to remove an existing recovery provider.
     * SHOULD be access controlled.
     * MUST call `unsubscribe` on the `provider`.
     * 
     * @param provider the address of a previously added recovery provider to remove.
     */
    function removeRecoveryProvider(address provider) external payable;

    /**
     * @notice A view function to check if a provider has been previously added.
     * 
     * @param provider the provider to check.
     * @return true if the provider exists in the account, false otherwise.
     */
    function recoveryProviderAdded(address provider) external view returns (bool);

    /**
     * @notice A non-view function to recover access of a smart account.
     * MUST check that `provider` exists in the account.
     * MUST call `recover` on the `provider`.
     * MUST update the account access according to `subject` if `proof` verification succeeds.
     * MUST return `true` if the access recovery is successful.
     * 
     * @param subject the recovery subject (encoded owner address, access control role, etc).
     * @param provider the address of a recovery provider.
     * @param proof an encoded proof of recovery (ZKP/ZKAI, signature, etc).
     * @return `true` if recovery is successful, `false` (or revert) otherwise.
     */
    function recoverAccess(
        bytes memory subject,
        address provider,
        bytes memory proof
    ) external returns (bool);
}
```

A recovery provider MUST implement the following interface:

```solidity
/**
 * @notice Defines a common recovery provider interface.
 */
interface IRecoveryProvider {
    /**
     * MUST be emitted whenever a new account subscribes to
     * the recovery provider (e.g. in the `subscribe` function).
     */
    event AccountSubscribed(address indexed account);

    /**
     * MUST be emitted whenever an account unsubscribes from
     * the recovery provider (e.g. in the `unsubscribe` function).
     */
    event AccountUnsubscribed(address indexed account);

    /**
     * @notice A function that &quot;subscribes&quot; a smart account (msg.sender) to a recovery provider.
     * SHOULD process and assign the `recoveryData` to the `msg.sender`.
     * 
     * @param recoveryData a recovery commitment (hash/ZKP public output) to be used 
     * in the `recover` function to check a recovery proof validity.
     */
    function subscribe(bytes memory recoveryData) external payable;

    /**
     * @notice A function that revokes a smart account subscription.
     * MUST delete all the recovery data associated with the `msg.sender`.
     */
    function unsubscribe() external payable;

    /**
     * @notice A function to get a recovery data (commitment) of an account.
     * 
     * @param account the account to get the recovery data of.
     * @return the associated recovery data.
     */
    function getRecoveryData(address account) external view returns (bytes memory);

    /**
     * @notice A function that checks if a recovery of a smart account (msg.sender)
     * to the new subject is possible.
     * SHOULD use `msg.sender`&apos;s `recoveryData` to check the `proof` validity.
     * MUST ensure that the `proof` can&apos;t be reused, e.g. update nonce.
     * 
     * @param object the new object (may be different to subject) to recover the `msg.sender` access to.
     * @param proof the recovery proof.
     */
    function recover(bytes memory object, bytes memory proof) external;
}
```

## Rationale

The AARI is expected to work with *any* account abstraction standard to allow for maximum account recovery flexibility. Whether it is [EIP-4337](/EIPs/EIPS/eip-4337) or [EIP-7702](/EIPs/EIPS/eip-7702), a particular smart account provider may support account recovery by simply implementing a common interface.

Since the whole account recovery process is nothing but proving the knowledge of some alternative secret to a private key, it is essential for accounts to be able to &quot;commit&quot; to this secret. The `subscribe` function in the recovery provider interface allows precisely for that. Moreover, if at some point in time a user wanted to &quot;recommit&quot; to a new secret (due to security reasons), they could multicall `unsubscribe` + `subscribe` functions to achieve the desired result.

The recovery functions accept arbitrary bytes as `subject` and `object` parameters to allow for a variety of access control rules to be recovered, since many smart accounts are ownerless and have no &quot;owner&quot; address to be directly substituted. 

## Backwards Compatibility

This EIP is fully backwards compatible.

## Security Considerations

There are several security concerns to point out:

- It is up to a smart account developer to properly access control `addRecoveryProvider` and `removeRecoveryProvider` functions.
- A smart account user may be &quot;phished&quot; to add a malicious recovery provider to their account. In that case, a recovery provider may gain full control over the account by accepting fake recovery proofs.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 07 May 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7947</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7947</guid>
      </item>
    
      <item>
        <title>Genesis File Format</title>
        <category>Informational/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-xxxx-genesis-json-standardization/24271</comments>
        
        <description>## Abstract

This EIP defines a canonical structure for Ethereum genesis files (`genesis.json`) used to bootstrap Ethereum networks. The standard aligns with the de facto structure implemented by Geth (Go-Ethereum), and already adopted by other clients. It introduces a JSON Schema to ensure consistency and tool compatibility across clients.

## Motivation

The lack of an official standard for the `genesis.json` file has led to incompatibilities, bugs and confusion, as well as added workload for those running multiple clients together in test networks. This EIP aims to reduce ambiguity by defining a consistent structure and enabling tooling through schema-based validation.

## Specification

The canonical genesis file MUST be a JSON object with the following top-level fields:

### Top-Level Fields

| Field           | Type    | Description                                                     | Example |
|-----------------|---------|------------------------------------------------------------------|---------|
| `config`        | Object  | Chain configuration object.                                     | (see below) |
| `alloc`         | Object  | Map of addresses to pre-allocated balances and/or code/storage. | (see below) |
| `nonce`         | String  | Block nonce as a hex string.                                    | `0x0` |
| `timestamp`     | String  | UNIX timestamp as a hex string.                                 | `0x6720f180` |
| `extraData`     | String  | Arbitrary extra data as hex string.                             | `0x00` |
| `gasLimit`      | String  | Block gas limit as a hex string.                                | `0x1c9c380` |
| `difficulty`    | String  | Block difficulty as a hex string.                               | `0x1` |
| `mixhash`       | String  | Mix hash as a hex string.                                       | `0x0000000000000000000000000000000000000000000000000000000000000000` |
| `coinbase`      | String  | Coinbase address as a hex string.                               | `0x0000000000000000000000000000000000000000` |

### `config` Object

The `config` object contains hardfork activation block numbers and fork configurations. Known keys include:

| Field                     | Type    | Description                                                                      | Example |
|---------------------------|---------|----------------------------------------------------------------------------------|---------|
| `chainId`                 | Integer | Unique identifier for the blockchain as a decimal integer.                      | `1` (mainnet) |
| `&lt;hardfork(Block\|Time)&gt;` | Integer | Block height or timestamp to activate the named hardfork as a decimal integer.  | `shanghaiTime: 1681338455` |
| `terminalTotalDifficulty` | String  | Total difficulty after which to switch from PoW to PoS as a hex string.         | `0xc70d815d562d3cfa955` |
| `depositContractAddress`  | String  | Ethereum address for the deposit contract as a hex string. | `0x00000000219ab540356cBB839Cbe05303d7705Fa` |
| `blobSchedule`            | Object  | Map of hardforks and their EIP-4844 DAS [configuration parameters](/EIPs/EIPS/eip-7840). | (see below) |

### `blobSchedule` Object

| Field                   | Type    | Description                                                      | Example |
|-------------------------|---------|------------------------------------------------------------------|---------|
| `target`                | Integer | Desired number of blobs to include per block as a decimal integer. | `3` |
| `max`                   | Integer | Maximum number of blobs to include per block as a decimal integer. | `6` |
| `baseFeeUpdateFraction` | Integer | Input to pricing formula per EIP-4844 as a decimal integer.     | `3338477` |

### `alloc` Object

The `alloc` field defines the initial state at genesis. It maps addresses (as hex strings) to the following object:

| Field          | Type    | Description                                                         | Example |
|----------------|---------|---------------------------------------------------------------------|---------|
| `balance`      | String  | Account balance in wei as a hex string.                             | `0xde0b6b3a7640000` (1 ETH) |
| `code`         | String  | EVM bytecode as a hex string.                                       | `0x6060604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000` |
| `nonce`        | String  | Account nonce as a hex string.                                      | `0x0` |
| `storage`      | Object  | Key-value map where keys and values are 32-byte hex strings representing storage slots. | `&quot;0x0000000000000000000000000000000000000000000000000000000000000001&quot;: &quot;0x00000000000000000000000000000000000000000000000000000000000000ff&quot;` |



### JSON Schema


```json

{
  &quot;$schema&quot;: &quot;http://json-schema.org/draft-07/schema#&quot;,
  &quot;$defs&quot;: {
    &quot;hexUint&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;pattern&quot;: &quot;^0x[0-9a-fA-F]+$&quot;
    },
    &quot;address&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;pattern&quot;: &quot;^0x[0-9a-fA-F]{40}$&quot;
    },
    &quot;hash&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;pattern&quot;: &quot;^0x[0-9a-f]{64}$&quot;
    }
  },
  &quot;title&quot;: &quot;Ethereum Genesis File&quot;,
  &quot;type&quot;: &quot;object&quot;,
  &quot;required&quot;: [&quot;alloc&quot;, &quot;gasLimit&quot;, &quot;difficulty&quot;],
  &quot;properties&quot;: {
    &quot;config&quot;: {
      &quot;type&quot;: &quot;object&quot;,
      &quot;properties&quot;: {
        &quot;chainId&quot;: { &quot;type&quot;: &quot;integer&quot; },
        &quot;homesteadBlock&quot;: { &quot;type&quot;: &quot;integer&quot; },
        &quot;daoForkBlock&quot;: { &quot;type&quot;: &quot;integer&quot; },
        &quot;eip150Block&quot;: { &quot;type&quot;: &quot;integer&quot; },
        &quot;tangerineWhistleBlock&quot;: {&quot;type&quot;: &quot;integer&quot;},
        &quot;eip155Block&quot;: { &quot;type&quot;: &quot;integer&quot; },
        &quot;spuriousDragonBlock&quot;: {&quot;type&quot;: &quot;integer&quot;},
        &quot;byzantiumBlock&quot;: { &quot;type&quot;: &quot;integer&quot; },
        &quot;constantinopleBlock&quot;: { &quot;type&quot;: &quot;integer&quot; },
        &quot;petersburgBlock&quot;: { &quot;type&quot;: &quot;integer&quot; },
        &quot;istanbulBlock&quot;: { &quot;type&quot;: &quot;integer&quot; },
        &quot;muirGlacierBlock&quot;: {&quot;type&quot;: &quot;integer&quot;},
        &quot;berlinBlock&quot;: { &quot;type&quot;: &quot;integer&quot; },
        &quot;londonBlock&quot;: { &quot;type&quot;: &quot;integer&quot; },
        &quot;arrowGlacierBlock&quot;: { &quot;type&quot;: &quot;integer&quot; },
        &quot;grayGlacierBlock&quot;: { &quot;type&quot;: &quot;integer&quot; },
        &quot;terminalTotalDifficulty&quot;: { &quot;$ref&quot;: &quot;#/$defs/hexUint&quot; },
        &quot;mergeNetsplitBlock&quot;: { &quot;type&quot;: &quot;integer&quot;},
        &quot;shanghaiTime&quot;: { &quot;type&quot;: &quot;integer&quot;},
        &quot;cancunTime&quot;: { &quot;type&quot;: &quot;integer&quot;},
        &quot;pragueTime&quot;: { &quot;type&quot;: &quot;integer&quot;},
        &quot;osakaTime&quot;: { &quot;type&quot;: &quot;integer&quot;},
        &quot;depositContractAddress&quot;: { &quot;$ref&quot;: &quot;#/$defs/address&quot;},
        &quot;blobSchedule&quot;: {
          &quot;type&quot;: &quot;object&quot;,
          &quot;additionalProperties&quot;: {
            &quot;type&quot;: &quot;object&quot;,
            &quot;properties&quot;: {
              &quot;target&quot;: { &quot;type&quot;: &quot;integer&quot; },
              &quot;max&quot;: { &quot;type&quot;: &quot;integer&quot; },
              &quot;baseFeeUpdateFraction&quot;: { &quot;type&quot; : &quot;integer&quot; }
            }
          }
        }
      },
      &quot;additionalProperties&quot;: true
    },
    &quot;nonce&quot;: { &quot;$ref&quot;: &quot;#/$defs/hexUint&quot; },
    &quot;timestamp&quot;: { &quot;$ref&quot;: &quot;#/$defs/hexUint&quot; },
    &quot;extraData&quot;: {
      &quot;anyOf&quot;: [
        {&quot;type&quot;: &quot;string&quot;, &quot;const&quot;: &quot;&quot; },
        {&quot;type&quot;: &quot;string&quot;, &quot;pattern&quot;: &quot;^0x([0-9a-fA-F]{2})*$&quot; }
      ]
    },
    &quot;gasLimit&quot;: { &quot;$ref&quot;: &quot;#/$defs/hexUint&quot; },
    &quot;difficulty&quot;: { &quot;$ref&quot;: &quot;#/$defs/hexUint&quot; },
    &quot;mixhash&quot;: { &quot;$ref&quot;: &quot;#/$defs/hash&quot; },
    &quot;coinbase&quot;: { &quot;$ref&quot;: &quot;#/$defs/address&quot; },
    &quot;alloc&quot;: {
      &quot;type&quot;: &quot;object&quot;,
      &quot;patternProperties&quot;: {
        &quot;^0x[0-9a-fA-F]{40}$&quot;: {
          &quot;type&quot;: &quot;object&quot;,
          &quot;properties&quot;: {
            &quot;balance&quot;: { &quot;$ref&quot;: &quot;#/$defs/hexUint&quot; },
            &quot;nonce&quot;: { &quot;$ref&quot;: &quot;#/$defs/hexUint&quot; },
            &quot;code&quot;: { &quot;type&quot;: &quot;string&quot;, &quot;pattern&quot;: &quot;^0x([0-9a-f])*$&quot; },
            &quot;storage&quot;: {
              &quot;type&quot;: &quot;object&quot;,
              &quot;patternProperties&quot;: {
                &quot;^0x[0-9a-f]{64}$&quot;: {
                  &quot;$ref&quot;: &quot;#/$defs/hash&quot;
                }
              }
            }
          }
        },
        &quot;additionalProperties&quot;: false
      },
      &quot;additionalProperties&quot;: false
    }
  },
  &quot;additionalProperties&quot;: true
}

```

## Rationale

There are a growing number of EIPs that propose improvements to how a network is configured at genesis:

[Add Blob Schedule to EL Config File](eip-7840)

[Blob Parameter Only Hardforks](eip-7892)

[eth_config JSON-RPC method](eip-7910)

However, the root configuration element amended by these remains unspecified. Adopting a minimal schema to define that will make subsequent changes more accurate and concise.

## Security Considerations

Since this is an optional and informational EIP, which offers only developer convenience, and must be used with admin access to the node, no new security concerns are introduced.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).




</description>
        <pubDate>Mon, 19 May 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7949</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7949</guid>
      </item>
    
      <item>
        <title>Encode chain id with transaction hash</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/a-new-standard-for-encoding-chain-id-transaction-hash/23782</comments>
        
        <description>## Abstract

This standard proposes a way to encode the combination of a chain ID and a transaction hash into one string.

## Motivation

Looking up a transaction by its hash always requires the context of the chain - a transaction hash alone is not enough to identify the used chain. If the chain information is included in the string itself, finding the right chain for the transaction is easy.

Such strings can then be used, for example, in a forwarder service that forwards to the correct blockchain explorer.

The chain id is included in some object formats, such as the transaction object inside the blockchain itself, but that object has a lot of unneeded data for our purposes.

## Specification

The encoded string has three components:

- A chain ID, denoted as `chainId`. The used chain id MUST be based on [EIP-155](/EIPs/EIPS/eip-155) and the chain ID repository stated in that EIP.
- A transaction hash, denoted as `txHash`. The hash MUST include the `0x` prefix.
- A static string `tx`, acting as a type identifier.

The syntax is: `chainId:txHash:tx`.

An example for a transaction with hash `0xc55e2b90168af6972193c1f86fa4d7d7b31a29c156665d15b9cd48618b5177ef` that was issued on chain ID `1` is: `1:0xc55e2b90168af6972193c1f86fa4d7d7b31a29c156665d15b9cd48618b5177ef:tx`.

All of the characters are case-insensitive.

## Rationale

The chain ID is the most important detail when routing queries based on this standard and is therefore the first element in the string. The transaction hash is the second most important element.

The suffix `tx` is used to differentiate from, for example, addresses. Without the `tx` it would remain unclear whether an encoded string refers to an address, a transaction hash or something else.

## Security Considerations

This EIP does not introduce direct security risks. It is up to the external service providers (such as wallet developers and blockchain explorers) to decide how and if they want to incorporate this EIP.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 22 May 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7950</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7950</guid>
      </item>
    
      <item>
        <title>Precompile for secp256r1 Curve Support</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7951-precompile-for-secp256r1-curve-support/24360</comments>
        
        <description>## Abstract

Add functionality to efficiently perform ECDSA signature verification over the secp256r1 elliptic curve (also known as P-256 or prime256v1). This precompile enables native support for signatures generated by modern secure hardware including Apple Secure Enclave, Android Keystore, and FIDO2/WebAuthn devices.

This specification addresses critical security issues discovered in RIP-7212 while maintaining full interface compatibility with existing Layer 2 implementations.

## Motivation

The secp256r1 elliptic curve is a NIST-standardized curve widely supported in modern secure hardware and authentication systems. Adding native support for secp256r1 signature verification to Ethereum enables several important use cases that are currently impossible or prohibitively expensive.

Modern secure hardware devices, including Apple Secure Enclave, Android Keystore, HSMs, TEEs, and FIDO2/WebAuthn authenticators, use secp256r1 for key storage and signing operations. Native secp256r1 support enables sophisticated account abstraction patterns like device-native signing, multi-factor authentication, and simplified key management - ultimately reducing friction for mainstream adoption through familiar authentication flows.

The secp256r1 curve is already widely supported across blockchain networks and protocols, including Layer 2 networks, enterprise blockchains, and interoperability protocols. This broad compatibility enables seamless integration with existing infrastructure while maintaining security through hardware-backed signing capabilities.

This EIP supersedes RIP-7212 by implementing the same functionality with the same interface, but without the vulnerability.

## Specification

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

### Precompile

We introduce `P256VERIFY` a precompile at the address `0x100` which performs ECDSA signature verification over the secp256r1 curve with a gas cost of `6900` gas

### Curve Parameters

The secp256r1 curve is fully defined by the following set of parameters:

``` text
Base field modulus = p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff
Curve equation: y^2 = x^3 + ax + b (mod p)
Curve coefficient a = 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc
Curve coefficient b = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b
Base point G:
  Gx = 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296
  Gy = 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5
Subgroup order = n = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551
Cofactor = h = 0x1
```

These parameters are standardized by NIST in SP 800-186[^1].

### Fields and Groups

The field Fp is defined as the finite field of size `p` with elements represented as integers between 0 and p-1 (both inclusive).

The group G is defined as a set of Fp pairs (points) `(x,y)` such that either `(x,y)` is `(0,0)` (representing the point at infinity) or `x,y` satisfy the curve equation `y^2 = x^3 + ax + b (mod p)`.

### Points and Encoding

#### Field Elements Encoding

A base field element (Fp) is encoded as `32` bytes by performing BigEndian encoding of the corresponding (unsigned) integer. The corresponding integer **must** be less than the field modulus `p`.

#### Encoding of Points in G

Points in G are encoded as byte concatenation of the respective encodings of the `x` and `y` coordinates. Total encoding length for a G point is thus `64` bytes.

#### Point of Infinity Encoding

For secp256r1, the point with coordinates `(0, 0)` (zeroes in Fp) is *not* on the curve, so a sequence of `64` zero bytes is used by convention to encode the point of infinity.

#### Encoding of Scalars

A scalar is encoded as `32` bytes by performing BigEndian encoding of the corresponding (unsigned) integer. The corresponding integer is **not** required to be less than or equal to the subgroup order `n`.

#### Behavior on Invalid Inputs

On inputs that cannot be valid encodings of field elements or points, the precompile *must* return `` (failure).

### ABI for `P256VERIFY` Operation

#### Input

`P256VERIFY` call expects `160` bytes as input that is interpreted as byte concatenation of:

- `32` bytes: message hash `h`
- `32` bytes: signature component `r`
- `32` bytes: signature component `s`
- `32` bytes: public key x-coordinate `qx`
- `32` bytes: public key y-coordinate `qy`

#### Output

Output is `32` bytes on successful verification and `0` bytes on failure:

- `0x0000000000000000000000000000000000000000000000000000000000000001` for valid signatures
- `` for invalid signatures or invalid inputs

#### Input Validation

The precompile MUST perform the following validation checks and return `` (failure) if any check fails:

1. **Input length**: Input MUST be exactly `160` bytes
2. **Signature component bounds**: Both `r` and `s` MUST satisfy `0 &lt; r &lt; n` and `0 &lt; s &lt; n`
3. **Public key bounds**: Both `qx` and `qy` MUST satisfy `0 ≤ qx &lt; p` and `0 ≤ qy &lt; p`
4. **Point validity**: The point `(qx, qy)` MUST satisfy the curve equation `qy^2 ≡ qx^3 + a*qx + b (mod p)`
5. **Point not at infinity**: The point `(qx, qy)` MUST NOT be the point at infinity (represented as `(0, 0)`)

#### Signature Verification Algorithm

The verification algorithm follows these steps:

```text
# Input validation (as specified above)
if input_length != 160:
    return
if not (0 &lt; r &lt; n and 0 &lt; s &lt; n):
    return
if not (0 ≤ qx &lt; p and 0 ≤ qy &lt; p):
    return 
if qy^2 ≢ qx^3 + a*qx + b (mod p):
    return
if (qx, qy) == (0, 0):
    return

# Signature verification
s1 = s^(-1) (mod n)

# Recover the random point used during signing
R&apos; = (h * s1) * G + (r * s1) * (qx, qy)

# Check for point at infinity
if R&apos; is the point at infinity:
    return

# Extract x-coordinate from r
r&apos; = R&apos;.x

# Compare with modular reduction
if r&apos; ≡ r (mod n):
    return 0x0000000000000000000000000000000000000000000000000000000000000001
else:
    return 
```

#### Error Cases

- Invalid input length (not exactly 160 bytes)
- Invalid field element encoding (≥ field modulus)
- Invalid signature component bounds (r or s not in range (0, n))
- Invalid public key (point at infinity or not on curve)
- Signature verification failure

### Gas Schedule

#### `P256VERIFY` operation

`6900` gas

This cost is based on benchmarking against the existing `ECRECOVER` precompile (`3000` gas). During benchmarks we found that the actual cost of R1 verification was significantly slower than the `ECRECOVER` precompile and the decision was made to increase the gas cost to `6900` gas. 

#### Gas Burning on Error

The precompile MUST NOT revert under any circumstances. Invalid inputs or verification failures MUST return `` and consume the same amount of gas had verification succeeded.

## Rationale

### Security Fixes

This specification addresses two critical vulnerabilities in RIP-7212:

1. **Point-at-infinity check**: The original RIP-7212 failed to check if the recovered point R&apos; is the point at infinity. This could lead to non-deterministic behavior where the verification result depends on the underlying implementation&apos;s handling of infinity points, potentially causing consensus failures.

2. **Modular comparison**: The original comparison `r&apos; == r` should be `r&apos; ≡ r (mod n)` to handle cases where the x-coordinate of R&apos; exceeds the curve order n. This ensures mathematically correct verification according to ECDSA standards.

### Verification vs Recovery

This specification uses signature verification rather than public key recovery (like `ECRECOVER`) because:

- Most secp256r1 implementations in hardware and software verify signatures directly
- The NIST FIPS 186-5 standard[^2] specifies verification, not recovery
- Verification is more efficient than recovery for this curve
- Existing hardware implementations provide verification interfaces

### Gas Cost Justification

The 6900 gas cost does not maintain compatibility with L2s, but it matches closer the benchmarks of actual implementations.

## Backwards Compatibility

This EIP maintains full interface compatibility with RIP-7212 implementations deployed on Layer 2 networks. The same contract bytecode that works with RIP-7212 will work with this specification.

The security fixes are transparent to correctly implemented callers - they only affect edge cases that should have failed verification anyway. No existing valid use cases are broken.

### Interface Compatibility

The precompile maintains a similar interface as RIP-7212 to ensure compatibility with existing Layer 2 deployments:

- Same address: `0x100`
- Same input format: 160 bytes
- Same output format: 32 bytes
- Different gas cost: 3450 gas vs 6900 gas
- Same return values

## Test Cases

A set of test vectors for verifying implementations is located in a separate [file](/EIPs/assets/eip-7951/test-vectors.json).

## Reference Implementation

A reference implementation is not supplied due to the ubiquity of secp256r1, if however a reference is needed, the NIST specification in FIPS 186-5[^2]

## Security Considerations

### Cryptographic Security

The secp256r1 curve provides approximately 128 bits of security, equivalent to secp256k1 already in use in Ethereum. The curve parameters are standardized by NIST SP 800-186[^1] and have undergone extensive cryptographic analysis by the wider cryptographic community in addition to this curve being deployed to several L2s in the form of RIP-7212.

### Malleability

Unlike secp256k1 ECDSA signatures, secp256r1 ECDSA signatures are not required to be non-malleable per NIST FIPS 186-5 standard [^2]. Applications requiring non-malleability should implement additional checks at the application layer.

### Side-Channel Resistance

We explicitly state that this precompile **IS NOT REQUIRED** to perform all the operations using constant time algorithms.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[^1]:
    ```csl-json
    {
        &quot;id&quot;: &quot;https://doi.org/10.6028/NIST.SP.800-186&quot;,
        &quot;type&quot;: &quot;report&quot;,
        &quot;title&quot;: &quot;Recommendations for Discrete Logarithm-based Cryptography: Elliptic Curve Domain Parameters&quot;,
        &quot;author&quot;: [
            { &quot;given&quot;: &quot;Lily&quot;,   &quot;family&quot;: &quot;Chen&quot;       },
            { &quot;given&quot;: &quot;Dustin&quot;, &quot;family&quot;: &quot;Moody&quot;      },
            { &quot;given&quot;: &quot;Andrew&quot;, &quot;family&quot;: &quot;Regenscheid&quot; },
            { &quot;given&quot;: &quot;Karen&quot;,  &quot;family&quot;: &quot;Randall&quot;    },
            { &quot;given&quot;: &quot;Angela&quot;, &quot;family&quot;: &quot;Robinson&quot;   }
        ],
        &quot;issued&quot;: {
            &quot;date-parts&quot;: [[2023, 2, 3]]
        },
        &quot;publisher&quot;: &quot;National Institute of Standards and Technology&quot;,
        &quot;publisher-place&quot;: &quot;Gaithersburg, MD&quot;,
        &quot;collection-title&quot;: &quot;Special Publication&quot;,
        &quot;number&quot;: &quot;800-186&quot;,
        &quot;URL&quot;: &quot;https://doi.org/10.6028/NIST.SP.800-186&quot;,
        &quot;DOI&quot;: &quot;10.6028/NIST.SP.800-186&quot;
    }
    ```

[^2]:
    ```csl-json
    {
        &quot;id&quot;: &quot;https://doi.org/10.6028/NIST.FIPS.186-5&quot;,
        &quot;type&quot;: &quot;report&quot;,
        &quot;title&quot;: &quot;Digital Signature Standard (DSS)&quot;,
        &quot;author&quot;: [
            { &quot;literal&quot;: &quot;National Institute of Standards and Technology&quot; }
        ],
        &quot;issued&quot;: {
            &quot;date-parts&quot;: [[2023, 2, 3]]
        },
        &quot;publisher&quot;: &quot;National Institute of Standards and Technology&quot;,
        &quot;publisher-place&quot;: &quot;Gaithersburg, MD&quot;,
        &quot;collection-title&quot;: &quot;Federal Information Processing Standards Publication&quot;,
        &quot;number&quot;: &quot;186-5&quot;,
        &quot;URL&quot;: &quot;https://doi.org/10.6028/NIST.FIPS.186-5&quot;,
        &quot;DOI&quot;: &quot;10.6028/NIST.FIPS.186-5&quot;
    }
    ```
</description>
        <pubDate>Tue, 27 May 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7951</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7951</guid>
      </item>
    
      <item>
        <title>Increase Maximum Contract Size</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/increase-maximum-contract-size-to-48kb/24509</comments>
        
        <description>## Abstract

This EIP proposes to raise the maximum allowed size for contract code deployed on Ethereum from 24,576 bytes to 32,768 bytes.

## Motivation

The current 24KiB contract size limit can be restrictive for complex contracts and applications. Increasing the limit to 32KiB allows for more feature-rich contracts while maintaining reasonable constraints on block and state growth.

## Specification

1. Update the [EIP-170](/EIPs/EIPS/eip-170) contract code size limit of 24KiB (`0x6000` bytes) to 32KiB (`0x8000` bytes).
2. Update the [EIP-3860](/EIPs/EIPS/eip-3860) initcode size limit of 48KiB (`0xC000` bytes) to 64KiB (`0x10000` bytes).

## Rationale

- **Developer Flexibility:** Enables more complex contracts and features.
- **Backward Compatibility:** Existing contracts are unaffected.
- **Simplicity:** Only the size limit is changed, with no other protocol modifications.

## Backwards Compatibility

This change is not backwards compatible and must be activated via a network upgrade (hard fork). Contracts larger than 24KiB, up to 32KiB, will be deployable after activation.

## Security Considerations

A higher contract size limit may marginally increase the risk of denial-of-service attacks via large contracts, but the new limit remains conservative.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Permissionless CREATE2 Factory</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/multi-chain-deployment-process-for-a-permissionless-contract-factory/24318</comments>
        
        <description>## Abstract

This ERC defines a permissionless and deterministic deployment mechanism across all EVM-compatible chains. It uses the [EIP-7702](/EIPs/EIPS/eip-7702) `Set Code for EOAs (0x4)` transaction type to deploy a universal CREATE2 factory contract to a fixed address (`0xC0DEb853af168215879d284cc8B4d0A645fA9b0E`) with known bytecode. The factory can then create any new contract to a deterministic address using the [EIP-1014](/EIPs/EIPS/eip-1014) `CREATE2 (0xf5)` opcode. It does not require preinstalls, secret keys, or chain-specific infrastructure.

## Motivation

Ensuring that contracts share the same address and code on multiple chains is a hard problem. It is typically done by having a known CREATE2 factory contract at a specific address that can further deterministically deploy new contracts using the `CREATE2 (0xf5)` opcode.

However, there is a bootstrapping problem: how do you get a CREATE2 factory contract with a specific address and code?

### Existing Solutions

There are currently three main approaches to this problem:

#### 1. Nick&apos;s Method

Use Nick&apos;s method to randomly generate a signature for a transaction **without** [EIP-155](/EIPs/EIPS/eip-155) replay protection that deploys the CREATE2 factory. Nick&apos;s method ensures that there is no known private key for the account that deploys the CREATE2 factory, meaning that the resulting contract will have a deterministic address and code on all chains. This strategy is used by the _Deterministic Deployment Proxy_ (deployed to `0x4e59b44847b379578588920ca78fbf26c0b4956c`, including on Ethereum Mainnet), one of the most widely used CREATE2 factory contracts.

**Downsides**:

- It does not work on chains that only accept EIP-155 replay-protected transactions.
- It is sensitive to changes in gas parameters on the target chain since the gas price and limit in the deployment transaction is sealed, and a new one cannot be signed without a private key.
- Reverts, such as those caused by alternative gas schedules, make the CREATE2 factory no longer deployable.

#### 2. Secret Private Key

Keep a carefully guarded secret key and use it to sign transactions to deploy CREATE2 factory contracts. The resulting contract will have a deterministic address and code on all chains where the transaction at a given nonce of the deployer account is a CREATE2 factory deployment, which can be verified post-deployment to ensure trustlessness. Additionally, this method does not have the same gas sensitivity downsides as Nick&apos;s method, as the private key can sign a creation transaction with appropriate gas parameters at the time of execution. This is the strategy used by the _Safe Singleton Factory_ and _CreateX_ (deployed to `0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7` and `0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed` respectively, including on Ethereum Mainnet).

**Downsides**:

- It is permissioned: the party that holds the secret key has the ultimate say on which chains will get the CREATE2 factory deployments.
- This requires carefully guarding a secret key; if it is exposed or lost, deployments are no longer guaranteed on new chains.
- If the transaction at the given nonce is not a successful CREATE2 factory deployment, then it is no longer possible to have a CREATE2 factory at the canonical address; this can happen by human error, for example.

#### 3. Preinstalls

Have popular CREATE2 deployment factories deployed on new chains by default. This is, for example, what OP Stack and ZKsync do as part of their preinstalls, including the CREATE2 factory contracts mentioned above. This ensures that the CREATE2 factory contracts have known addresses and codes.

**Downsides**:

- It is not standardized nor adopted by all chains.
- It is permissioned as a chain can choose not to include a specific CREATE2 factory contract preinstalled.
- Attempts to standardize this with RIP-7740 have not been successful.

### Proposal: Using EIP-7702 Type `0x4` Transactions

This ERC proposes a permissionless alternative fourth mechanism to the existing ones described above with none of their downsides. Additionally, it standardizes a set of deployment parameters for a **universal** CREATE2 factory deployment. This ensures a common CREATE2 factory for the community instead of multiple competing copies with slightly different codes at different addresses. This single CREATE2 factory copy can bootstrap additional deterministic deployment infrastructure (such as the comprehensive CreateX universal contract deployer).

**Benefits**

- Universally applicable: It can be executed on any chain by any user and guarantees a reliable determination of smart contract deployments on any chain.
- Fault resistant: The method is secure against &quot;out of gas&quot; and other errors.
- Permissionless: The universal CREATE2 factory contract can be deployed by anyone.

## Specification

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

### Parameters

| Parameter                   | Value                                                                          |
| --------------------------- | ------------------------------------------------------------------------------ |
| `DEPLOYER_PRIVATE_KEY`      | `0x942ba639ec667bdded6d727ad2e483648a34b584f916e6b826fdb7b512633731`           |
| `CREATE2_FACTORY_INIT_CODE` | `0x7c60203d3d3582360380843d373d34f5806019573d813d933efd5b3d52f33d52601d6003f3` |
| `CREATE2_FACTORY_SALT`      | `0x000000000000000000000000000000000000000000000000000000000001bec5`           |

### Derived Parameters

| Derived Parameter              | Value                                                                |
| ------------------------------ | -------------------------------------------------------------------- |
| `DEPLOYER_ADDRESS`             | `0x962560A0333190D57009A0aAAB7Bfa088f58461C`                         |
| `CREATE2_FACTORY_ADDRESS`      | `0xC0DEb853af168215879d284cc8B4d0A645fA9b0E`                         |
| `CREATE2_FACTORY_RUNTIME_CODE` | `0x60203d3d3582360380843d373d34f5806019573d813d933efd5b3d52f3`       |
| `CREATE2_FACTORY_CODE_HASH`    | `0x2ad75e1e9642e6fce7d293d52fa5a8f62a79a2079abb7402256add02d6e8bc30` |

### Definitions

- **Deployer**: The account corresponding to `DEPLOYER_PRIVATE_KEY` with address `DEPLOYER_ADDRESS`.
- **CREATE2 factory contract**: A contract that deploys other contracts with `CREATE2 (0xf5)` opcode, allowing smart contracts to be deployed to deterministic addresses.
- **Bootstrap contract**: The contract that the _deployer_ delegates to in order to deploy the _CREATE2 factory contract_.
- **Bootstrapping code**: The critical code in the _bootstrap contract_ that performs the `CREATE2 (0xf5)` deployment of the _CREATE2 factory contract_.

### Bootstrap Contract

The _bootstrap contract_ MUST execute the following or equivalent _bootstrapping code_ as an EIP-7702 delegation target for the _deployer_ account:

```solidity
bytes memory initCode = CREATE2_FACTORY_INIT_CODE;
bytes32 salt = CREATE2_FACTORY_SALT;
assembly (&quot;memory-safe&quot;) {
    create2(0, add(initCode, 32), mload(initCode), salt)
}
```

The _bootstrap contract_ MAY implement additional features such as:

- Abort early if either _CREATE2 factory contract_ is already deployed or the _deployer_ is not correctly delegated to.
  - This can help mitigate gas griefing from the front-running issue described below.
- Additional verification that the deployment succeeded as expected.
- Emit events to facilitate tracking of either the _bootstrap contract_ or _CREATE2 factory contract_ deployments.

### Deployment Process

1. Deploy a _bootstrap contract_ described in the previous section.
2. Sign an EIP-7702 authorization using the `DEPLOYER_PRIVATE_KEY` delegating to the _bootstrap contract_.
3. Execute an EIP-7702 type `0x4` transaction with the authorization from step 2; the transaction MUST call `DEPLOYER_ADDRESS` (**either** directly or indirectly) which delegates to the _bootstrap contract_ and MUST perform the `CREATE2 (0xf5)` of the `CREATE2_FACTORY_INIT_CODE` with `CREATE2_FACTORY_SALT` in the _bootstrapping code_.

Assuming successful execution of the _bootstrapping code_ without reverting in the context of the _deployer_, the _CREATE2 factory contract_ will be deployed to `CREATE2_FACTORY_ADDRESS` with code `CREATE2_FACTORY_RUNTIME_CODE` and code hash `CREATE2_FACTORY_CODE_HASH`.

## Rationale

### Deployment Mechanism

The deployment mechanism was chosen such that it is uniquely parameterized by the `DEPLOYER_ADDRESS` (which itself is derived from the `DEPLOYER_PRIVATE_KEY` and is therefore deterministic), the `CREATE2_FACTORY_INIT_CODE` and the `CREATE2_FACTORY_SALT` which are both fixed and deterministic. Additionally, since the `DEPLOYER_ADDRESS` will deploy the CREATE2 factory contract with the `CREATE2 (0xf5)` opcode, this guarantees that the address and code of the contract are deterministic.

The use of a publicly known private key enables this mechanism, as anyone can permissionlessly generate a delegation signature to **any** bootstrap contract that would cause the `DEPLOYER_ADDRESS` to execute the specified `CREATE2 (0xf5)` operation and deploy the factory contract to a completely deterministic address. Because of the use of `CREATE2 (0xf5)`, the CREATE2 factory will be deployed to `CREATE2_FACTORY_ADDRESS` if and only if it is deployed with `CREATE2_FACTORY_INIT_CODE`, thus guaranteeing a deployed code hash of `CREATE2_FACTORY_CODE_HASH`. Additionally, the semantics of `CREATE2 (0xf5)` make it so no transaction executed by `DEPLOYER_ADDRESS` can permanently block the deployment of the CREATE2 factory contract to `CREATE2_FACTORY_ADDRESS`.

One issue with this method is that because the `DEPLOYER_PRIVATE_KEY` is public, anyone can sign alternative delegations or transactions and front-run a legitimate CREATE2 factory deployment. The front-running would increase the nonce of the `DEPLOYER_ADDRESS` account and render the EIP-7702 authorization in the legitimate CREATE2 factory deployment transaction invalid, causing the deployment to potentially fail. This is not considered to be a serious issue, however, as:

1. Doing so does not prevent future deployments - meaning that an attacker can only delay the deployment of the CREATE2 factory with a sustained attack at a gas cost to the attacker, but not permanently prevent it from happening.
2. The damage is limited to gas griefing for accounts that are legitimately trying to deploy the CREATE2 factory contract. Furthermore, the reference implementation was coded to minimize the gas griefing damage.
3. In the case of a very persistent malicious actor, their attack can be circumvented by either making use of private transactions or working directly with block builders.

Another known issue with this method is that a future network upgrade may introduce new mechanisms (such as a new opcode or transaction type) to permanently set an account&apos;s code. If this were to happen, and since the `DEPLOYER_PRIVATE_KEY` is publicly known, the `DEPLOYER_ADDRESS` account&apos;s code could be mistakenly or maliciously set to something that does not execute the necessary bootstrapping code, permanently preventing any future deployment of the CREATE2 factory contract. If this ERC were to gain sufficient adoption, this is not believed to be an issue as:

1. The deployment on Ethereum Mainnet would already exist, and the `DEPLOYER_PRIVATE_KEY` would no longer have any value on Ethereum Mainnet.
2. An RIP can be adopted to ensure that `CREATE2_FACTORY_ADDRESS` has code `CREATE2_FACTORY_RUNTIME_CODE`.

### Publicly Known Private Key Instead of Nick&apos;s Method

Instead of using a publicly known `DEPLOYER_PRIVATE_KEY`, Nick&apos;s method can be used to generate a random EIP-7702 authorization signature. This would prevent the front-running and forward compatibility issues described above.

However, in order for Nick&apos;s method to work, the EIP-7702 authorization message that is signed, defined as `keccak(MAGIC || rlp([chain_id, address, nonce]))`, must be constant. `MAGIC` is already a constant; `chain_id` can be trivially fixed to `0` to specify a chain-agnostic EIP-7702 authorization; `nonce` can also be trivially fixed to `0` because Nick&apos;s method ensures the authority has no known private key, meaning it cannot sign another message that would increment the nonce. However, fixing `address` is problematic. Doing so would require a contract with specific code to be deployed to the same address on all chains, which is the original bootstrapping problem the proposed permissionless CREATE2 factory aims to solve. Therefore, this creates a &quot;chicken and egg problem&quot;, making it not a viable way to generate an EIP-7702 authorization signature.

### Use of CREATE2 Factory Contract

This mechanism allows the `DEPLOYER_ADDRESS` to do any `CREATE2 (0xf5)` deployment, so it would be possible to forgo the intermediary CREATE2 factory contract and use the deployer technique for all deployments. There are multiple downsides to this, however:

- All contract deployments are subject to the front-running issue described above, which could become an annoyance
- Concurrent deployments from the deployer are subject to race conditions since EIP-7702 authorizations increase the account nonce. This means that if two deployments are submitted to the mempool without knowing about each other, only the first one will actually succeed, because the EIP-7702 authorization in the second transaction is for an outdated nonce. This is not an issue when deployers are trying to deploy the same contract as proposed in this ERC since even if the second delegation and transaction fails, the contract would have been deployed as desired.

### Multiple Transaction Procedure

Unfortunately, EIP-7702 type `0x4` transactions are restricted to `to` values that are not `null`, meaning that you cannot simultaneously deploy the _bootstrap contract_ and delegate to it in a single transaction.

### Choice of Deployer Private Key

The `DEPLOYER_PRIVATE_KEY` was chosen as the private key at derivation path `m/44&apos;/60&apos;/0&apos;/0/0` for the mnemonic `make code code code code code code code code code code coconut`.

### Choice of Salt

The `CREATE2_FACTORY_SALT` was chosen as the **first** salt value starting from `0` such that the CREATE2 factory&apos;s [ERC-55](/EIPs/EIPS/eip-55) checksum address starts with the case sensitive `0xC0DE...` prefix. A verifiable method for mining a vanity address for the CREATE2 factory contract was chosen in order to ensure that the ERC authors did not find a CREATE2 hash collision on the `CREATE2_FACTORY_ADDRESS` that they can exploit at some point in the future.

### CREATE2 Factory Bytecode

The CREATE2 factory has a similar interface to existing implementations. Namely, it accepts `salt || init_code` as input, which is a 32-byte `salt` value concatenated with the `init_code` of the contract to deploy. It will execute a `CREATE2` with the specified `salt` and `init_code`, deploying a contract with `init_code` to `keccak256(0xff || CREATE2_FACTORY_ADDRESS || salt || keccak256(init_code))[12:]`. This contract returns the address of the created contract padded to 32 bytes. This differs from some existing implementations, but was done to maintain consistency with the 32-byte word size on the EVM (same encoding as `ecrecover` precompile for example). A product of this is that the return data from CREATE2 factory is compatible with the Solidity ABI. In the case where the execution of `init_code` were to fail, any revert data is propagated to the caller.

Throughout both the CREATE2 factory contract initialization and runtime code, `RETURNDATASIZE (0x3d)` is used to push `0` onto the stack instead of the dedicated `PUSH0 (0x5f)` opcode. This is done to increase compatibility with chains that support EIP-7702 but not [EIP-3855](/EIPs/EIPS/eip-3855), while remaining a 1-byte and 2-gas opcode.

The `CREATE2_FACTORY_INIT_CODE` corresponds to the following assembly:

```
# SPDX-License-Identifier: CC0-1.0

### Constructor Code ###

0x0000: PUSH29 0x60203d3d3582360380843d373d34f5806019573d813d933efd5b3d52f3
                        # Stack: [runcode]                      | Push the CREATE2 factory runtime code, left padded
                                                                # with three 0 bytes
0x001e: RETURNDATASIZE  # Stack: [0; runcode]                   | Push the offset in memory to store the code
0x001f: MSTORE          # Stack: []                             | The runtime code is now in `memory[3:32]`, because of
                                                                # the 3 bytes of 0-padding
0x0020: PUSH1 29        # Stack: [29]                           | Push the code length
0x0022: PUSH1 3         # Stack: [3; 29]                        | Push the memory offset of the start of code
0x0024: RETURN          # Stack: []                             | Return the runtime code
```

The `CREATE2_FACTORY_RUNTIME_CODE` corresponds to the following assembly:

```
# SPDX-License-Identifier: CC0-1.0

### Runtime Code ###

# Prepare the stack, push 32, a value that will used a lot and can summon with
# `DUP*` to save on one byte of code (over `PUSH1 32`), and a 0 which will be
# used by either the `RETURN` or `REVERT` branches at the end.
0x0000: PUSH1 32        # Stack: [32]
0x0002: RETURNDATASIZE  # Stack: [0; 32]

# First, load the salt value and compute the actual code size for the CREATE2
# call, this is the calldata length minus 32 for the salt prefix.
                        # Stack: [0; 32]
0x0003: RETURNDATASIZE  # Stack: [0; 0; 32]                     | Push the calldata offset 0 of the `salt` parameter
0x0004: CALLDATALOAD    # Stack: [salt; 0; 32]                  | Load the `salt` from calldata
0x0005: DUP3            # Stack: [32; salt; 0; 32]              | Push 32 to the stack
0x0006: CALLDATASIZE    # Stack: [msg.data.len; 32; salt; ...]  | Followed by the calldata length
0x0007: SUB             # Stack: [code.len; salt; 0; 32]        | Compute `msg.data.length - 32`, which is the length of
                                                                # the init `code`

# Copy the init code to memory offset 0. Note that if the call to the contract
# incorrectly encoded, this will revert with &quot;out of gas&quot;, as it will attempt
# to copy ~2**256 bytes of calldata to memory.
                        # Stack: [code.len; salt; 0; 32]
0x0008: DUP1            # Stack: [code.len; .; salt; 0; 32]     | Duplicate the length of the init code
0x0009: DUP5            # Stack: [32; code.len; ...]            | Push the offset in calldata of the code, which is 32
                                                                # as it comes immediately after the 32-byte `salt`; use
                                                                # the 32 value at the bottom of the stack
0x000a: RETURNDATASIZE  # Stack: [0; 32; code.len; ...]         | Push the offset (0) in memory to copy the code to
0x000b: CALLDATACOPY    # Stack: [code.len; salt; 0; 32]        | Copy the init code, `memory[0:code.len]` contains the
                                                                # init `code`

# Deploy the contract.
                        # Stack: [code.len; salt; 0; 32]
0x000c: RETURNDATASIZE  # Stack: [0; code.len; salt; 0; 32]     | Push the offset in memory starting of the start of
                                                                # init `code`, which is 0
0x000d: CALLVALUE       # Stack: [v; 0; code.len; salt; 0; 32]  | Forward the call value to the contract constructor
0x000e: CREATE2         # Stack: [address; 0; 32]               | Do `create2(v, code, salt)`, which leaves the address
                                                                # of the contract on the stack, or 0 if the contract
                                                                # creation reverted

# Verify the deployment was successful and return the address.
                        # Stack: [address; 0; 32]
0x000f: DUP1            # Stack: [address; .; 0; 32]            | Duplicate the address value
0x0010: PUSH1 0x19      # Stack: [0x0019; address; .; 0; 32]    | Push the jump destination offset for the code which
                                                                # handles successful deployments
0x0012: JUMPI           # Stack: [address; 0; 32]               | Jump if `address != 0`, i.e. `CREATE2` succeeded

# CREATE2 reverted, propagate the revert data.
                        # Stack: [address = 0; 0; 32]
0x0013: RETURNDATASIZE  # Stack: [r.len; 0; 0; 32]              | Push the revert data length onto the stack
0x0014: DUP2            # Stack: [0; r.len; 0; 0; 32]           | Push 0 on to the stack by duplicating; note that
                                                                # `PUSH0` is intentionally do not used for increased
                                                                # compatibility with chains that do not implement that
                                                                # specific opcode
0x0015: RETURNDATASIZE  # Stack: [r.len; 0; r.len; 0; 0; 32]    | Push the revert data length onto the stack again
0x0016: SWAP4           # Stack: [0; 0; r.len; 0; r.len; 32]    | Reorder the stack so that both `RETURNDATACOPY` and
                                                                # `REVERT` can be called; this is done by swapping the
                                                                # revert data length on the top of the stack with the
                                                                # bottom-most 0
0x0017: RETURNDATACOPY  # Stack: [0; r.len; 32]                 | Copy the revert data to `memory[0:r.len]`
0x0018: REVERT          # Stack: [32]                           | Revert with `memory[0:r.len]`

# CREATE2 succeeded.
0x0019: JUMPDEST        # Stack: [address; 0; 32]
0x001a: RETURNDATASIZE  # Stack: [0; address; 0; 32]            | Push the memory offset (0) to store return data at,
                                                                # `RETURNDATASIZE` is used as contract creation was
                                                                # successful, and therefore the return data has size 0
0x001b: MSTORE          # Stack: [0; 32]                        | Store the address in memory, `memory[0:32]` contains
                                                                # the `address` left padded to 32-bytes
0x001c: RETURN          # Stack: []                             | Return `memory[0:32]`, i.e. the address
```

## Backwards Compatibility

There are a few backwards compatibility considerations with the new proposal:

1. It requires an EVM chain with EIP-7702 enabled. This means not all chains can use this deployment method.
2. It would deploy yet another CREATE2 factory contract that would need to be adopted by tooling.
3. The proposed CREATE2 factory implementation returns the newly created contract address padded to 32 bytes. This is different to some existing contracts that return unpadded 20-byte address value.
4. The proposed CREATE2 factory implementation propagates revert data. This is different to some existing contracts that just revert with empty data in case executing the CREATE2 initialization code fails.

## Reference Implementation

This proposal includes a reference implementation of a bootstrap contract to which the deployer account can delegate. The reference implementation expects a call to `Bootstrap` to the function `deploy()` in an EIP-7702 type `0x4` transaction including the EIP-7702 authorization delegating `DEPLOYER_ADDRESS` to `Bootstrap` (NOTE: the `Bootstrap` is called as an entry point, instead of calling `DEPLOYER_ADDRESS` directly which allows the contract to do some up-front checks to minimize gas griefing risk):

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.29;

contract Bootstrap {
    address private constant _DEPLOYER_ADDRESS = 0x962560A0333190D57009A0aAAB7Bfa088f58461C;
    address private constant _CREATE2_FACTORY_ADDRESS = 0xC0DEb853af168215879d284cc8B4d0A645fA9b0E;
    bytes32 private constant _CREATE2_FACTORY_CODE_HASH = hex&quot;2ad75e1e9642e6fce7d293d52fa5a8f62a79a2079abb7402256add02d6e8bc30&quot;;
    bytes private constant _CREATE2_FACTORY_INIT_CODE = hex&quot;7c60203d3d3582360380843d373d34f5806019573d813d933efd5b3d52f33d52601d6003f3&quot;;
    bytes32 private constant _CREATE2_FACTORY_SALT = hex&quot;000000000000000000000000000000000000000000000000000000000001bec5&quot;;

    error InvalidDelegation();
    error CreationFailed();

    function deploy() external {
        if (_CREATE2_FACTORY_ADDRESS.codehash == _CREATE2_FACTORY_CODE_HASH) {
            return;
        }

        bytes32 delegation = keccak256(abi.encodePacked(hex&quot;ef0100&quot;, this));
        require(_DEPLOYER_ADDRESS.codehash == delegation, InvalidDelegation());

        Bootstrap(_DEPLOYER_ADDRESS).bootstrap();
    }

    function bootstrap() external {
        bytes memory initCode = _CREATE2_FACTORY_INIT_CODE;
        bytes32 salt = _CREATE2_FACTORY_SALT;

        address factory;
        assembly (&quot;memory-safe&quot;) {
            factory := create2(0, add(initCode, 32), mload(initCode), salt)
        }

        require(factory == _CREATE2_FACTORY_ADDRESS, CreationFailed());
    }
}
```

A minimal bootstrap contract implementation is also possible (although this has a higher potential for gas griefing). The minimal bootstrap contract expects a call directly to the `DEPLOYER_ADDRESS` in an EIP-7702 type `0x4` transaction including the EIP-7702 authorization delegating `DEPLOYER_ADDRESS` to `MiniBootstrap`:

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.29;

contract MiniBootstrap {
    bytes private constant _CREATE2_FACTORY_INIT_CODE = hex&quot;7c60203d3d3582360380843d373d34f5806019573d813d933efd5b3d52f33d52601d6003f3&quot;;
    bytes32 private constant _CREATE2_FACTORY_SALT = hex&quot;000000000000000000000000000000000000000000000000000000000001bec5&quot;;

    fallback() external {
        bytes memory initCode = _CREATE2_FACTORY_INIT_CODE;
        assembly (&quot;memory-safe&quot;) {
            pop(create2(0, add(initCode, 32), mload(initCode), _CREATE2_FACTORY_SALT))
        }
    }
}
```

## Security Considerations

It is possible to front-run transactions that invalidate the deployer&apos;s EIP-7702 delegation and cause the deployment to fail. This, however, comes at a gas cost to the attacker, with limited benefit beyond delaying the deployment of the CREATE2 factory. Additionally, persistent attackers can be circumvented by either using private transaction queues or working with block builders directly to ensure that the EIP-7702 bootstrapping transaction is not front-run.

### Future Network Upgrades

If new EVM opcodes or transaction types are introduced in future network upgrades that allow an account to permanently set its code, then this method is no longer guaranteed to work. The deployer account can permanently change its code to a contract that does not have the required bootstrapping code. This can trivially be done by a malicious actor using the publicly known `DEPLOYER_PRIVATE_KEY` and would prevent any future deployments of CREATE2 factory.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 15 May 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7955</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7955</guid>
      </item>
    
      <item>
        <title>Tx Ordering via Block-level Randomness</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/potential-eip-mev-decrease-by-deterministic-transaction-ordering-via-block-level-randomness/24084</comments>
        
        <description>## Abstract

Proposers and builders can currently permute pending transactions arbitrarily, enabling reorder‑driven MEV.  This EIP introduces a consensus rule that sorts all transactions inside a block by XOR‑ing each transaction hash with fresh slot randomness.  The randomness is unknown until the slot starts, so the order is deterministic once known but unpredictable beforehand.  The mechanism **significantly reduces reorder‑based MEV**; latency‑driven back‑running, censorship, and other classes of MEV remain and should be mitigated through complementary techniques (encrypted mempools, reputation, PBS marketplaces, etc.).

## Motivation

Unrestricted ordering is the key enabler of sandwich and classic front‑running attacks.  Deterministic ordering collapses these vectors to latency racing and information asymmetry.  Clear candidate‑set and bundle semantics preserve fee markets while removing the need for trusted sequencers.  Academic works shows deterministic ordering drives sandwich profits toward zero.

### References

* Julia Ofoegbu, “Maximal Extractable Value (MEV): A Tale As Old As Time,” Medium (2024).

* J. Qian et al., “Deterministic Transaction Ordering Without Trusted Sequencers,” arXiv:2411.03327 v1 (2024).

* “Shutter Network Introduces Plan for First Encrypted Mempool on Ethereum,” GlobeNewswire, 13 Feb 2025.

## Specification

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


### Slot Randomness `R`

We define our randomness `R` as the `randao_reveal` of the each slot, after [EIP-7998](/EIPs/EIPS/eip-7998), since this EIP provides slot-by-slot randomness for `randao_reveal` (only predictable for the builder). This provides enough randomness for our purpose of reducing MEV attacks by MEV bots.

```
R = body.randao_reveal[0:32]     : bytes32
```


### Builder Flow

1. **Candidate‑set selection** – Builders **MAY** choose **any subset** of the mempool based on priority fees, side agreements, or policy.  Transactions not chosen are ignored.
2. **Canonical sorting** – Sort the chosen set by primary key `H(tx) ⊕ R` ascending, then secondary key `H(tx)` ascending, in case of collision on the primary key.
3. **Gas‑limit packing** – Append items in order until adding the next would exceed the block gas **limit**.
4. **Bundles (optional cross‑address atomicity)**

* **Definition** – A bundle is a user‑signed list of fully‑signed transactions.  Each `child_tx_rlp` is the canonical **signed** RLP encoding, including signature fields `(v, r, s)`.  The bundle begins with a *fee‑payment* transaction that covers gas and builder tip for the entire bundle.
* **Hashing / sort key** – Treat the bundle as a *virtual transaction* with key `H(concat(child_tx_rlps))`, where:

   * `child_tx_rlps[i]` **MUST** be the exact bytes that will later appear in the block body for that transaction, i.e. the *canonical RLP of the fully‑signed transaction* per [EIP‑2718](./eip-2718) / [EIP‑155](./eip-155) rules (for typed transactions the leading *type byte* and length prefix are included).
   * Implementations **MUST NOT** strip or normalise the signature fields `(v,r,s)`; those 65 bytes are hashed as‑is so every participant derives an identical bundle key.
   * The concatenation order is the author‑declared execution order of the child transactions.
* **Gas accounting** – Bundle gas is the **sum of the `gasLimit` fields** of all child transactions.  Builders use that sum when evaluating step 3.
* **Fit‑or‑skip rule** – If the bundle (fee‑payment + children) would exceed the remaining gas limit, the bundle is skipped atomically.

5. **Fee dynamics** – Priority fees influence membership in the candidate set (step 1) but **never** override the canonical order once a tx or bundle is selected.

Here is a pseudocode for the above flow:

```
//---------------------------------------------------------------------
// Inputs
//---------------------------------------------------------------------
// mempool          : All pending txs &amp; user-signed bundles visible to the builder
// R                : 32-byte slot randomness supplied by randao_reveal
// BLOCK_GAS_LIMIT  : Max gas allowed in the block

//---------------------------------------------------------------------
// Helper functions
//---------------------------------------------------------------------
function HASH(obj)           → bytes32       // Keccak-256 of the byte sequence
function PRIMARY_KEY(h, R)   → bytes32       // h XOR R (bit-wise)

function bundleGas(bundle):                      // sum of gasLimit of children
    total ← 0
    for childTx in bundle.children:
        total ← total + childTx.gasLimit
    return total

//---------------------------------------------------------------------
// 0. Candidate-set selection  (builder policy / side deals / fee filter)
//---------------------------------------------------------------------
candidates ← pickSubsetFrom(mempool)            //  ANY subset is allowed

//---------------------------------------------------------------------
// 1. Compute canonical keys &amp; gas cost for every candidate
//---------------------------------------------------------------------
for item in candidates:
    if item.type == &quot;single_tx&quot;:
        item.gasCost  ← item.gasLimit
        baseHash      ← HASH(item.RLP)          // canonical signed RLP (EIP-2718)
    else if item.type == &quot;bundle&quot;:
        concatRlps    ← CONCAT(item.child_rlps) // fee-tx + children in author order
        item.gasCost  ← bundleGas(item)
        baseHash      ← HASH(concatRlps)

    item.primaryKey   ← PRIMARY_KEY(baseHash, R)
    item.secondaryKey ← baseHash

//---------------------------------------------------------------------
// 2. Canonical sorting  (primaryKey asc, then secondaryKey asc)
//---------------------------------------------------------------------
sort(candidates, by = (primaryKey ASC, secondaryKey ASC))

//---------------------------------------------------------------------
// 3. Gas-limit packing with fit-or-skip for bundles
//---------------------------------------------------------------------
blockList ← empty list
gasUsed   ← 0

for item in candidates:
    if gasUsed + item.gasCost &gt; BLOCK_GAS_LIMIT:
        continue               // skip whole tx or bundle atomically
    append(blockList, item)
    gasUsed ← gasUsed + item.gasCost

//---------------------------------------------------------------------
// 4. Output — assemble block body &amp; header field
//---------------------------------------------------------------------
block.randomness          ← R               // bytes16 in the payload header
block.txOrderingVersion   ← 1
block.body                ← flatten(blockList)   // bundles explode into children
return block
```

### Consensus Rule

A block is **invalid** if the executed list deviates from the canonical order derived from its `randomness` and the included transactions/bundles.  Verification is objective; fork‑choice remains unchanged.

### Performance

Sorting ≤ 1 500 transactions remains `O(n log n)` (&lt; 1 ms), on today&apos;s hardware.

### Deployment 

#### Added Parameters

* `randomness`: Specified in the specification.
* `txOrderingVersion = 1` flag: To be compatible with the existing consensus rule and adding compatibility for future rules if needed.

#### Fork Parameters

* `ORDERING_FORK_EPOCH`: Beacon‑chain epoch at which execution clients start to recognise the new fields `randomness` and `txOrderingVersion`.
* `ORDERING_TRANSITION_EPOCHS` window activate the rule: 64 epochs (~13.6 h). Length of the transition window during which blocks with either ordering version are accepted.

Both parameters are constants in the fork config and may be tuned during test‑net experiments.

#### Activation Flow

1. Consensus‑layer upgrade —  Beacon‑chain fork at `ORDERING_FORK_EPOCH` activates **`EL‑VRF‑exposure`** (companion EIP) and begins populating the `vrf_output_proposer` field.  Execution clients receiving the `ExecutePayload` after this epoch expect a non‑zero `randomness` field.

2. Execution‑layer handshake —  Builders and proposers include the new `randomness` and `txOrderingVersion` fields in Engine API `engine_newPayloadV3` calls.  Legacy nodes that have not upgraded will reject the payload, causing a natural chain split and economic incentive to upgrade.

2. Transition window —  For `ORDERING_TRANSITION_EPOCHS` after `ORDERING_FORK_EPOCH`, clients accept:

  * Version 0 blocks —  `txOrderingVersion` == 0; no randomness; legacy ordering.

  * Version 1 blocks —  `txOrderingVersion` == 1; valid randomness; canonical ordering enforced. During this period proposers are encouraged (but not forced) to adopt version 1 so that fee markets and MEV supply chains have time to adjust.

4. Finalisation —  At `ORDERING_FORK_EPOCH` + `ORDERING_TRANSITION_EPOCHS` the consensus rule changes: blocks MUST set `txOrderingVersion == 1` and pass canonical‑order validation.  A version‑0 block after this point is treated as invalid and will not be considered by fork‑choice.


## Rationale

### Why randomness‑driven ordering?

* Objective &amp; Verifiable –  Using a function of on‑chain randomness (R) and a transaction’s own hash gives every validator an identical, cheap check on order validity.

* Unpredictable Until Slot Start –  The XOR of slot‑level RANDAO and the proposer’s VRF output ensures that neither users nor builders can know the final sort key before the slot begins, closing the classic front‑run window.

* Minimal Surface Area –  A single 16‑byte field in the execution payload plus a hash operation keeps consensus changes small and auditable.

### Why XOR as the mixing function?

* XOR is associative, fast, and requires no extra cryptographic assumptions beyond SHA‑2 already used for H(tx).

* Any bias in one entropy component (e.g., RANDAO) is negated unless the attacker also controls the VRF output.

### Why allow builders to curate the candidate set first?

* Preserves fee‑market incentives: high‑tip transactions still rise to the top of inclusion competition.

* Avoids forced inclusion of low‑value spam that could bloat blocks if the entire mempool were blindly sorted.

### Why a secondary key H(tx) for tie‑breaking?

* Guarantees total order with negligible extra cost.

* Leverages a value already known to every node; no extra field is needed.

### Why optional bundles instead of implicit nonce‑chain folding?

* Cross‑address atomicity (e.g., borrower + lender tx pair) cannot be expressed via nonce order alone.

* Requiring an explicit fee‑payment transaction embeds pricing for the externality a bundle imposes on ordering neutrality.

### Why the &quot;fit‑or‑skip&quot; bundle rule?

* Ensures all clients compute the same gas impact, preventing divergent execution.

* Avoids partial bundle execution, which would undermine user intent.

### Why the version flag + transition window?

* Prevents accidental consensus splits by giving node operators a grace period.

* Mirrors previous successful hard forks (e.g., London’s BASE_FEE activation sequence).


## Backwards Compatibility

* **Old nodes** —  Execution clients that ignore the new fields will treat version‑1 blocks as malformed and fork away.  The short transition window gives operators time to upgrade.
* **Light clients** —  No additional work; they track headers chosen by upgraded full nodes.


## Security Considerations

### Randomness Bias &amp; RANDAO Manipulation

* *Single‑validator bias* – A block proposer can not change its `randao_reveal` output after EIP-7998, only predictable to him.

* *Coalition bias* – Multiple consecutive‑slot proposers could attempt to influence RANDAO by withholding signatures, but the protocol already slashes equivocation and missed attestations.  The cost rises exponentially with coalition size, and the added VRF entropy further randomizes `R`.

* *Forkable bias* – Re‑org attempts longer than depth 1 must overcome the usual consensus finality thresholds.  Because `R` is embedded in the execution payload, any fork conflicts are objectively detectable by all nodes.

Conclusion: Collusion attacks are economically unattractive; the mixed entropy from RANDAO and VRF provides strong unpredictability guarantees.

### Hash Grinding

New signatures are required only when `calldata` changes, but attacks must begin **after** block is built.  Propagation delays and inclusion fees sharply limit profitable grinding to high‑value trades.

### Tie Collisions

Secondary key `H(tx)` guarantees total order; collision probability (`2^{-256}`) is negligible.

### Bundle Gas Consistency

Explicit summation rule ensures every client computes identical gas usage for bundles, preventing divergent validation.

### Residual MEV Vectors

* *Back‑running &amp; latency* – Persist.

* *Builder discretion* – Builders may censor or selectively include transactions while forming the candidate set; exactly like the current status of Ethereum.


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 24 May 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7956</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7956</guid>
      </item>
    
      <item>
        <title>EVM64 - EOF support</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7937-64-bit-mode-evm-opcodes-evm64/23794</comments>
        
        <description>## Abstract

This EIP defines EOF support for EVM64 with its additional code validation rules and `RJUMPI`, `RJUMPV` opcodes.

## Motivation

EOF defines a stricter code validation rule to improve efficiency. Due to EVM64 using multibyte opcode (the mode opcode `C0`), a small adaptation is needed. This EIP also additionally defines a 64-bit mode `RJUMPI` and `RJUMPV` to be 64-bit.

## Specification

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

We define the following gas cost constant:

| Name | Gas |
|------|-----|
| `G_RJUMPIV64` | `3` |

At EOF contract creation time as defined in [EIP-3670](/EIPs/EIPS/eip-3670), if the opcode `C0` is encountered and it is not part of PUSH opcode&apos;s data, then the interpreter MUST validate that:

* The next opcode exists.
* The next opcode is `RJUMPI64`, `RJUMPV64`, or one of the core 64-bit opcode defined in [EIP-7937](/EIPs/EIPS/eip-7937) minus `JUMP64` and `JUMPI64`.

For flow operations RJUMPI and RJUMPV, the 64-bit mode has following changes:

* For `RJUMPI64` (0xc0e1), the condition popped from stack is only read for the last 64 bits. Gas cost is `G_RJUMPIV64`.
* For `RJUMPV64` (0xc0e2), the case popped from stack is only read for the last 64 bits. Gas cost is `G_RJUMPIV64`.

Note that:

* `RJUMP` is automatically in 64-bit mode because it does not read or write the stack.

## Rationale

For detailed rationale discussion, please see the core EVM64 definition [EIP-7937](/EIPs/EIPS/eip-7937).

## Backwards Compatibility

No backward compatibility issues found.

## Test Cases

To be added.

&lt;!-- TODO --&gt;

## Reference Implementation

To be added.

&lt;!-- TODO --&gt;

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 26 May 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7957</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7957</guid>
      </item>
    
      <item>
        <title>EVM64 - Little endian opcodes</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7937-64-bit-mode-evm-opcodes-evm64/23794</comments>
        
        <description>## Abstract

This EIP defines additional little endian opcodes that can be deployed alongside [EIP-7937](/EIPs/EIPS/eip-7937).

## Motivation

The core EIP that defines EVM64 (EIP-7937) is endianness-independent. This EIP defines those additional opcodes that must expose endianness. They are the bitwise opcode `BYTE64`, memory opcodes `MLOAD64` and `MSTORE64`, and stack opcodes `PUSH*64`.

## Specification

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

We define the following gas cost constant:

* `G_VERYLOW64`: 2

### `BYTE64`

`BYTE64` (0xc01a) is defined as `(x &gt;&gt; i * 8) &amp; 0xFF`. Note that the definition is changed from big endian to little endian.

The gas cost is `G_VERYLOW64`.

### `MLOAD64` and `MSTORE64`

`MLOAD64` (0xc051) will load a 64-bit integer in little endian onto the stack. `MSTORE64` (0xc052) will read an 64-bit integer from the stack, and store it to memory in little endian.

The gas cost for both opcodes is `G_VERYLOW64`. The memory resizing costs count as 8 bytes.

As an example, `[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]` is an array of 8 bytes (64 bits). Calling `MLOAD64` to load this 8-byte value to stack will read it in little endian, resulting in 64-bit integer `0x0807060504030201`. 64-bit mode always operate on only the least significant 64 bits. When another 256-bit opcodes encounter this value on stack, it will be `0x00..00 0807060504030201`. Calling `MSTORE64` to store this value to memory will result in the array `[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]`.

### `PUSH*64`

`PUSH2_64` (0xc061) to `PUSH8_64` (0xc067) follows 2-byte to 8-byte literal. The literal is read little endian and pushed onto the stack.

The gas cost for them is `G_VERYLOW64`.

As an example, `0xc0 0x67 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08` will result in a stack with single value `0x00..00 0807060504030201`.

## Rationale

For detailed rationale discussion, please see the core EVM64 definition [EIP-7937](/EIPs/EIPS/eip-7937).

## Backwards Compatibility

No backward compatibility issues found.

## Test Cases

To be added.

&lt;!-- TODO --&gt;

## Reference Implementation

To be added.

&lt;!-- TODO --&gt;

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 26 May 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7958</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7958</guid>
      </item>
    
      <item>
        <title>EOF - Extended types section</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-series-evm64/23794</comments>
        
        <description>## Abstract

This EIP extends the definition of `types_section` in EOF format ([EIP-3540](/EIPs/EIPS/eip-3540)) with an additional `type` parameter.

## Motivation

An additional `type` parameter allows the EOF EVM interpreter to identify the &quot;type&quot; of a code section. This allows the interpreter to &quot;interpret&quot; each code section differently, allowing EOF function calls to, for example, invoke pure EVM64 code or even later support RISC-V.

## Specification

`types_section`, as defined in EIP-3540, is changed to be of the following format `(type, reserved, inputs, outputs, max_stack_increase)`. `type` is `uint8`, `reserved` is 24 bits, and `inputs`, `outputs`, `max_stack_increase` are defined as `uint8`, `uint8`, `uint16` respectively, the same as before. The only valid `type` defined in this EIP is `0x01`. Additional EIPs may be defined for other code section `type`s.

`version`, as defined in EIP-3540, is changed to `0x02`, to avoid the backward compatibility issue if a third-party chain already deployed EOF in production.

In EOF container, the following validation rules are added:

* If a `type` in `types_section` is not of a known type, then the validation fails.
* `reserved` in `types_section` must be all zeros.

## Rationale

The new `type` parameter allows a contract to &quot;dispatch&quot; to different variants of the interpreter to better suit its need.

* The portion of the code where it mainly interacts with Ethereum addresses, balances, storages may run &quot;normal&quot; EVM.
* The portion of the code that is computationally heavy may run faster EVM64, but loses the ability to directly interact with Ethereum addresses and balances.

Allowing this `type` to be defined for each code section ensures that a contract remains concise -- it can quickly switch between its computational needs and system/runtime needs.

`reserved` is added to `types_section` to maintain the proper padding. Each item in `types_section` is now 64 bits in total.

## Backwards Compatibility

As we know, EOF, including EIP-3540, was extremely close to being deployed before it was decided to withdraw from Fusaka. To avoid the issue that some third-party chains have already deployed EOF in production (given the state of EOF we can consider this to be likely), we bump `version` of EOF to `0x02`. `0x01` is now invalid.

No other backward compatibility issues found.

## Test Cases

To be added.

&lt;!-- TODO --&gt;

## Reference Implementation

To be added.

&lt;!-- TODO --&gt;

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 28 May 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7960</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7960</guid>
      </item>
    
      <item>
        <title>EVM64 - EOF code section</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-series-evm64/23794</comments>
        
        <description>## Abstract

An EOF-only specification for EVM64 instruction set. This defines a separate &quot;EVM64&quot; type for EOF code section in addition to &quot;regular EVM&quot;. The interpreter then enters EVM64 mode when entering the code section. This EIP is an alternative to [EIP-7937](/EIPs/EIPS/eip-7937).

## Motivation

EIP-7937 has maximum compatibility with existing EVM. It implements EVM64 simply as a group of additional opcodes (using a prefix opcode). This EIP defines an alternative method, using EOF container&apos;s code section. It has its pros and cons. The code size will obviously become shorter, due to not needing multibyte opcodes any more. On the other hand, interop with EVM system calls become more difficult because it cannot be done in an EVM64 code section. The advantages and disadvantages are discussed further in the Rationale section.

## Specification

Define `0x02` as an allowed `type` in `types_section`, as defined in EIP-7960. This denotes an EVM64 code section.

### EOF function execution

When entering an EOF code section (either at the beginning of the contract call, or through `CALLF`), it enters &quot;pure EVM64 mode&quot;. Unless defined below, no other opcodes are allowed. Those opcodes all only operate on the least significant 64-bit, in little endian.

During EOF validation, the validation function should enforce that only allowed opcodes exist.

### Gas cost constants

We define the following gas cost constants:

* `G_BASE64`: 1
* `G_VERYLOW64`: 2
* `G_LOW64`: 3
* `G_MID64`: 5
* `G_HIGH64`: 7
* `G_EXP64_STATIC`: 5
* `G_EXP64_DYNAMIC`: 25
* `G_RJUMPIV64`: 3

### Arithmetic opcodes

The 64-bit mode arithmetic opcodes are defined the same as non-64-bit mode, except that they only operate on the least significant 64-bits. In the below definition, `a`, `b`, `N` is `a mod 2^64`, `b mod 2^64` and `N mod 2^64`.

* ADD (`01`) and SUB (`03`): `a op b mod 2^64`, gas cost `G_VERYLOW64`.
* MUL (`02`), DIV (`04`), SDIV (`05`), MOD (`06`), SMOD (`07`), SIGNEXTEND (`0B`): `a op b mod 2^64`, gas cost `G_LOW64`.
* ADDMOD (`08`), MULMOD (`09`): `a op b % N mod 2^64`, gas cost `G_MID64`.
* EXP (`0A`): `a EXP b mod 2^64`, gas cost `static_gas = G_EXP64_STATIC, dynamic_gas = G_EXP64_DYNAMIC * exponent_byte_size`.

### Comparison and bitwise opcodes

The 64-bit mode comparison and bitwise opcodes are defined the same as non-64-bit mode, except that they only operate on the least significant 64 bits.

* LT (`10`), GT (`11`), SLT (`12`), SGT (`13`), EQ (`14`), AND (`16`), OR (`17`), XOR (`18`): `a op b mod 2^64`, gas cost `G_VERYLOW64`
* ISZERO (`15`), NOT (`19`): `op a mod 2^64`, gas cost `G_VERYLOW64`
* SHL (`1B`), SHR (`1C`), SAR (`1D`): `a op N mod 2^64`, gas cost `G_VERYLOW64`
* BYTE (`1A`) is defined as `(x &gt;&gt; i * 8) &amp; 0xFF`. Note that the definition is changed from big endian to little endian.

### Memory opcodes

`MLOAD64` (0x51) will load a 64-bits integer in little endian onto the stack. `MSTORE64` (0x52) will read an 64-bits integer from the stack, and store it to memory in little endian.

The gas cost for both opcodes is `G_VERYLOW64`. The memory resizing costs count as 8 bytes.

`MSTORE8` is available in EVM64 mode, and its gas cost is the same as in &quot;normal&quot; EVM.

### Stack opcodes

`PUSH0` (0x5f) to `PUSH8` (0x67) follows 0-byte to 8-byte literal. The literal is read little endian and pushed onto the stack. The gas cost for them is `G_VERYLOW64`.

`POP`, `SWAPn` and `DUPn` are available in EVM64 mode, and their gas costs are the same as in &quot;normal&quot; EVM.

### Other opcodes

Contract opcodes `RETURN`, `REVERT`, `INVALID` are available in EVM64 mode. Their behaviors, including gas costs, are unchanged. However, for all stack items, only the least significant 64 bits are read.

`CALLF`, `RETF`, `RJUMP` are available in EVM64 mode. Their behaviors, including gas costs, are unchanged.

For flow operations RJUMPI and RJUMPV, the 64-bit mode has following changes:

* For `RJUMPI64` (0xe1), the condition popped from stack is only read for the last 64 bits. Gas cost is `G_RJUMPIV64`.
* For `RJUMPV64` (0xe2), the case popped from stack is only read for the last 64 bits. Gas cost is `G_RJUMPIV64`.

## Rationale

### Stack behavior

&quot;Pure&quot; in &quot;pure EVM64&quot; refers to the fact that all opcodes in EVM64 mode only operate on the least significant 64 bits. In this specification, we don&apos;t specifically define 64-bit stack. As far as this EIP is concerned, stack is still 256-bit. However, because they only operate on the least significant 64 bits. The most significant 192 bits becomes unobservable as long as the interpreter is in an EVM64 code section. Thus an EVM interpreter can optimize EVM64 execution as follows:

* When entering EVM64 code section, truncate `inputs` to 64 bits.
* Use 64-bit stack during EVM64 execution.
* When exiting EVM64 code section, prepend `0` to `outputs` to make it 256 bits.

### Discussions

This alternative definition (compared with EIP-7937) has the advantage that the code size is now shorter (because no multibyte opcodes are needed). It however will only work with EOF contract but not &quot;legacy&quot; EVM. The interaction between EVM64 and &quot;system calls&quot; (those calls that read Ethereum block values, addresses, balances and storages) will be more difficult. It&apos;s not &quot;seamless&quot; like EIP-7937 where one can enter/exit 64-bit mode at ease. Depending on how the 64-bit optimization works out, this may be an advantage or a disadvantage.

The memory is, as usual, still shared during the entire execution. So in EVM64, the contract can always use the memory to push/fetch data.

## Backwards Compatibility

No backward compatibility issues found.

&lt;!-- TODO: Add test cases and reference implementation --&gt;

## Security Considerations

Needs discussion. &lt;!-- TODO --&gt;

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 28 May 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7961</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7961</guid>
      </item>
    
      <item>
        <title>Key Hash Based Tokens</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/key-based-tokens/24422</comments>
        
        <description>## Abstract

This EIP proposes two token interfaces: **ERC-KeyHash721** for non-fungible tokens (NFTs) and **ERC-KeyHash20** for fungible tokens (similar to [ERC-20](/EIPs/EIPS/eip-20)). Both of them utilize cryptographic key hashes (“keyHash”, or `keccak256(key)`) instead of Ethereum addresses to manage ownership. This enhances privacy by authorizing by the public key’s ECDSA signature (address derived from `keccak256(key[1:])`) and matching `keyHash = keccak256(key)`, without storing addresses on‑chain. Consequently, it empowers users to conduct transactions using any address they choose. By separating ownership from transaction initiation, these standards allow gas fees to be paid by third parties without relinquishing token control, making them suitable for batch transactions and gas sponsorship. Security is ensured by implementing robust ECDSA signature verification on key functions (`transfer`) to prevent message tampering.

## Motivation

Traditional [ERC-721](/EIPs/EIPS/eip-721) and [ERC-20](/EIPs/EIPS/eip-20) tokens bind ownership to Ethereum addresses, which are publicly visible and may be linked to identities, compromising privacy. The key hash-based ownership model allows owners to prove control without exposing addresses, ideal for anonymous collectibles, private transactions, or decentralized identity use cases. Additionally, separating ownership from gas fee payment enables third-party gas sponsorship, improving user experience in high-gas or batch transaction scenarios. This proposal aligns with the privacy principles of [ERC-5564](/EIPs/EIPS/eip-5564) (Stealth Addresses) and extends them to token ownership.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### Overview

This proposal defines two token interfaces:
- `IERCKeyHash721`: For non-fungible tokens (NFTs), each identified by a unique `tokenId`, with ownership managed via `keyHash` (`keccak256(key)`).
- `IERCKeyHash20`: For fungible tokens, with balances associated with `keyHash`.

Token operations (`transfer`) require the owner&apos;s key(an uncompressed secp256k1 public key) and an ECDSA signature produced by the private key corresponding to the key (i.e., the address derived from `keccak256(key[1:])` excluding the 0x04 prefix) to prove ownership, ensuring only legitimate owners can execute actions. Signatures follow [EIP-712](/EIPs/EIPS/eip-712) structured data hashing to prevent message tampering, with per-keyHash nonces and deadlines to prevent replay attacks.

Implementers MAY optionally add administrative functions such as `mint` (create new tokens) and `destroy` (remove tokens) based on application requirements. These functions are not part of the core interface of this ERC; if provided, they SHOULD enforce strict access control, correct supply accounting, and preserve the key‑hash privacy model without exposing addresses.

Notably, the approve function is intentionally omitted. The key is designed for one-time use and is revealed only during token transfer transactions. Once revealed, holdings are typically migrated to fresh keyHashes; implementations MAY disallow reuse of previously revealed keyHash. Since transactions can be submitted by any address, the signature must be generated by the address derived from the key. This binds authorization to the key while allowing any relayer address to submit and pay gas.


### ERC-KeyHash721: Non-Fungible Token Interface

#### Interface

```solidity
interface IERCKeyHash721 {
    // Events
    event KeyHashTransfer721(uint256 indexed tokenId, bytes32 indexed fromKeyHash, bytes32 indexed toKeyHash);
    event KeyHashBurn721(uint256 indexed tokenId, bytes32 indexed ownerKeyHash);

    // View functions (aligned with ERC-721)
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function tokenURI(uint256 tokenId) external view returns (string memory);
    function totalSupply() external view returns (uint256);
    function ownerOf(uint256 tokenId) external view returns (bytes32);

    // State-changing functions
    function mint(uint256 tokenId, bytes32 keyHash) external;
    function transfer(uint256 tokenId, bytes32 toKeyHash, bytes memory key, bytes memory signature, uint256 deadline) external;
    function destroy(uint256 tokenId, bytes memory key, bytes memory signature, uint256 deadline) external;
}
```

#### Function Descriptions
##### `transfer`
```solidity
    transfer(uint256 tokenId, bytes32 toKeyHash, bytes memory key, bytes memory signature, uint256 deadline) external;
```
  **Description**: Transfers the specified token from the current owner&apos;s `keyHash` to `toKeyHash`. The caller provides the owner&apos;s key to prove ownership. The signature is verified using [EIP-712](/EIPs/EIPS/eip-712) structured data.  
  **Parameters**:
    - `tokenId`: `uint256` - The token ID to transfer.
    - `toKeyHash`: `bytes32` - The new owner&apos;s key hash.
    - `key`: `bytes` - MUST be a 65-byte uncompressed secp256k1 public key with prefix 0x04.
    - `signature`: `bytes` -  ECDSA signature produced by the private key corresponding to the key, verifying ownership and preventing malicious relay attacks.
    - `deadline`: `uint256` - Signature expiration timestamp (Unix seconds).  
  **Signature Message**: [EIP-712](/EIPs/EIPS/eip-712) structured data:  
    ```solidity
    struct Transfer {
        uint256 tokenId;
        bytes32 toKeyHash;
        uint256 nonce;
        uint256 deadline;
    }
    ```  
  **Events**: Emits `KeyHashTransfer721(tokenId, fromKeyHash, toKeyHash)`.  
  **Requirements**:
    - Token MUST exist (non-zero `fromKeyHash`).
    - `keccak256(key)` MUST equal the current `fromKeyHash`.
    - Signature MUST be valid.
    - `block.timestamp` MUST be &lt;= `deadline`.
    - `toKeyHash` MUST NOT be zero.
    - Updates ownership to `toKeyHash`.


- **Other Functions**: `name`, `symbol`, `tokenURI`, and `totalSupply` align with [ERC-721](/EIPs/EIPS/eip-721) . `ownerOf` returns `bytes32` (keyHash) instead of an address.`tokenURI` is part of the core interface and MAY return an empty string if metadata is not provided.

#### Key Concepts
- **Key (`key`)**: An uncompressed secp256k1 public key (65 bytes, starting with 0x04), used to prove ownership. Implementations MUST validate the key format:
```solidity
require(key.length == 65 &amp;&amp; key[0] == 0x04, &quot;BAD_KEY_FMT&quot;);
```
- **Key Hash (`keyHash`)**: A `bytes32` value representing `keccak256(key)`, identifying ownership without exposing addresses.
- **Token Existence**: A token exists if its `keyHash` is non-zero.
- **Nonce**: Nonces are tracked per keyHash and per contract. Each ERC-KeyHash contract maintains its ownmapping(bytes32 =&gt;uint256)keyNonces. Cross-contract replay is already prevented by the EIP-712 domain (verifyingContract, chainId). Signers MUST serialize operations for the same keyHashwithin the same contract.

### ERC-KeyHash20: Fungible Token Interface

#### Interface

```solidity
interface IERCKeyHash20 {
    // Events
    event KeyHashTransfer20(bytes32 indexed fromKeyHash, bytes32 indexed toKeyHash, uint256 amount);

    // View functions (aligned with ERC-20)
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function decimals() external view returns (uint8);
    function totalSupply() external view returns (uint256);
    function balanceOf(bytes32 keyHash) external view returns (uint256);

    // State-changing functions
    function mint(bytes32 keyHash, uint256 amount) external;
    function transfer(bytes32 fromKeyHash, bytes32 toKeyHash, uint256 amount, bytes memory key, bytes memory signature, uint256 deadline, bytes32 leftKeyHash) external;
}
```

#### Function Descriptions
##### `transfer`
```solidity
    transfer(bytes32 fromKeyHash, bytes32 toKeyHash, uint256 amount, bytes memory key, bytes memory signature, uint256 deadline, bytes32 leftKeyHash)
```
  **Description**: Transfers `amount` tokens from `fromKeyHash` to `toKeyHash`, with remaining balance assigned to `leftKeyHash` (controlled by the sender). The caller provides the owner&apos;s key to prove ownership. The signature is verified using [EIP-712](/EIPs/EIPS/eip-712) structured data. Mimics Bitcoin&apos;s UTXO model for partial transfers.  
  **Parameters**:
    - `fromKeyHash`: `bytes32` - Token owner&apos;s key hash.
    - `toKeyHash`: `bytes32` - Recipient&apos;s key hash.
    - `amount`: `uint256` - Amount to transfer.
    - `key`: `bytes` - MUST be a 65-byte uncompressed secp256k1 public key with prefix 0x04.
    - `signature`: `bytes` - ECDSA signature.
    - `deadline`: `uint256` - Signature expiration timestamp.
    - `leftKeyHash`: `bytes32` - Key hash for remaining balance (`balance - amount`). MUST NOT equal `toKeyHash` or `fromKeyHash` (strict mode to enforce key rotation and unlinkability).  
  **Signature Message**: [EIP-712](/EIPs/EIPS/eip-712) structured data:  
    ```solidity
    struct Transfer {
        bytes32 fromKeyHash;
        bytes32 toKeyHash;
        uint256 amount;
        uint256 nonce;
        uint256 deadline;
        bytes32 leftKeyHash;
    }
    ```  
  **Events**: Emits `KeyHashTransfer20(fromKeyHash, toKeyHash, amount)`.  
  **Requirements**:
    - `fromKeyHash` MUST have sufficient balance (`balanceOf[fromKeyHash] &gt;= amount`).
    - `keccak256(key)` MUST equal `fromKeyHash`.
    - Signature MUST be valid.
    - `block.timestamp` MUST be &lt;= `deadline`.
    - `toKeyHash` and `leftKeyHash` MUST NOT be zero.
    - Updates balances: `balanceOf[fromKeyHash] = 0`, `balanceOf[toKeyHash] += amount`, `balanceOf[leftKeyHash] += (original balance - amount)`.

- **Other Functions**: `name`, `symbol`, `decimals`, and `totalSupply` align with [ERC-20](/EIPs/EIPS/eip-20). `balanceOf` uses `bytes32` parameter.

### Signature Verification

For `transfer`:
1. Verify `keccak256(key) == current keyHash`.
2. Compute [EIP-712](/EIPs/EIPS/eip-712) message hash:
   ```solidity
   bytes32 digest = keccak256(abi.encodePacked(
       &quot;\x19\x01&quot;,
       DOMAIN_SEPARATOR,
       keccak256(abi.encode(
           TYPE_HASH, // Struct-specific type hash
           params // Struct fields (e.g., tokenId, toKeyHash, nonce, deadline)
       ))
   ));
   ```
3. Recover signer address using `ecrecover(digest, signature)`.
4. REQUIRE signer == address(uint160(uint256(keccak256(key[1:])))), where key is a 65‑byte uncompressed secp256k1 public key (0x04 || X || Y) and key[1:] denotes the 64‑byte XY payload (prefix removed)
5. On successful verification, increment _keyNonces[currentOwnerKeyHash] (i.e., _keyNonces[ownerKeyHash] for ERC‑KeyHash721 and _keyNonces[fromKeyHash] for ERC‑KeyHash20) to prevent replay.
6. Verify `block.timestamp &lt;= deadline`.

### Requirements

- Contracts MUST maintain mappings:
  - ERC-KeyHash721: `tokenId` to `keyHash`.
  - ERC-KeyHash20: `keyHash` to balance.
- MUST use per-keyHash nonces (`mapping(bytes32 =&gt; uint256) _keyNonces`) for replay protection.
- MUST implement [EIP-712](/EIPs/EIPS/eip-712) for signature hashing.
- MUST enforce `deadline` to limit signature validity.
- MUST verify signatures and hash keys in `transfer`.
- For ERC-KeyHash20, MUST enforce strict mode for `leftKeyHash` by requiring it to be different from both `toKeyHash` and `fromKeyHash`. This prevents change consolidation with the recipient or original account, promoting key rotation and unlinkability.

## Rationale

### Advantages of Key Hash
- **Privacy**: `ownerOf` and `balanceOf` return `keyHash`, not addresses. Users can use unique key pairs per token or balance, reducing linkability.
- **Gas Fee Separation**: Anyone can call `transfer` with a valid signature, paying gas fees, enabling batch transactions or gas sponsorship.
- **Flexibility**: Aligns with [ERC-5564](/EIPs/EIPS/eip-5564) stealth addresses, extending privacy to tokens.

### Transfer Design
- Open to any caller with valid signatures, ensuring only owners operate while allowing gas sponsorship.
- [EIP-712](/EIPs/EIPS/eip-712) signatures prevent message tampering by including all critical parameters.
- Per-keyHash nonces and deadlines prevent replay attacks.



## Backwards Compatibility 

This proposal is not compatible with [ERC-721](/EIPs/EIPS/eip-721)  or [ERC-20](/EIPs/EIPS/eip-20) due to `bytes32` key hashes instead of addresses. Adapters can bridge to existing systems for privacy-focused use cases.

## Reference Implementation

### ERC-KeyHash721 Implementation

```solidity
pragma solidity ^0.8.0;
import &quot;@openzeppelin/contracts/utils/cryptography/ECDSA.sol&quot;;
import &quot;@openzeppelin/contracts/utils/cryptography/EIP712.sol&quot;;

contract KeyHashERC721 is EIP712 {
    using ECDSA for bytes32;

    string public name;
    string public symbol;
    mapping(uint256 =&gt; bytes32) private _tokenKeyHashes;
    mapping(uint256 =&gt; bool) private _destroyedTokens;
    uint256 public totalSupply;
    mapping(bytes32 =&gt; uint256) private _keyNonces;

    event KeyHashTransfer721(uint256 indexed tokenId, bytes32 indexed fromKeyHash, bytes32 indexed toKeyHash);
    event KeyHashBurn721(uint256 indexed tokenId, bytes32 indexed ownerKeyHash);

    bytes32 private constant TRANSFER_TYPEHASH = keccak256(
        &quot;Transfer(uint256 tokenId,bytes32 toKeyHash,uint256 nonce,uint256 deadline)&quot;
    );
    bytes32 private constant DESTROY_TYPEHASH = keccak256(
        &quot;Destroy(uint256 tokenId,uint256 nonce,uint256 deadline)&quot;
    );

    constructor(string memory _name, string memory _symbol)
        EIP712(&quot;KeyHashERC721&quot;, &quot;1&quot;)
    {
        name = _name;
        symbol = _symbol;
    }

    function ownerOf(uint256 tokenId) external view returns (bytes32) {
        require(_tokenKeyHashes[tokenId] != 0 &amp;&amp; !_destroyedTokens[tokenId], &quot;Token does not exist&quot;);
        return _tokenKeyHashes[tokenId];
    }

    function tokenURI(uint256) external pure returns (string memory) { return &quot;&quot;; }

    function transfer(
        uint256 tokenId,
        bytes32 toKeyHash,
        bytes memory key,
        bytes memory signature,
        uint256 deadline
    ) external {
        require(toKeyHash != bytes32(0), &quot;Invalid recipient hash&quot;);
        require(_tokenKeyHashes[tokenId] != 0 &amp;&amp; !_destroyedTokens[tokenId], &quot;Token does not exist&quot;);
        require(block.timestamp &lt;= deadline, &quot;Signature expired&quot;);
        require(key.length == 65 &amp;&amp; key[0] == 0x04, &quot;BAD_KEY_FMT&quot;);
        bytes32 currentKeyHash = _tokenKeyHashes[tokenId];
        require(keccak256(key) == currentKeyHash, &quot;BAD_KEYHASH&quot;);
        
        uint256 nonce = _keyNonces[currentKeyHash];
        bytes32 structHash = keccak256(abi.encode(
            TRANSFER_TYPEHASH,
            tokenId,
            toKeyHash,
            nonce,
            deadline
        ));
        bytes32 digest = _hashTypedDataV4(structHash);
        address signer = digest.recover(signature);
        address expectedAddress = _addressFromUncompressedKey(key);
        require(signer == expectedAddress, &quot;Invalid signature&quot;);
        _keyNonces[currentKeyHash] = nonce + 1; // 验签通过后再自增

        _tokenKeyHashes[tokenId] = toKeyHash;
        emit KeyHashTransfer721(tokenId, currentKeyHash, toKeyHash);
    }


    function getNonce(bytes32 keyHash) external view returns (uint256) {
        return _keyNonces[keyHash];
    }
    
    function _addressFromUncompressedKey(bytes memory key) internal pure returns (address) {
        // key: 65 bytes, [0] = 0x04, [1..32] = X, [33..64] = Y 
        require(key.length == 65 &amp;&amp; key[0] == 0x04, &quot;BAD_KEY_FMT&quot;);
        bytes32 x;
        bytes32 y;
        assembly {
            x := mload(add(key, 0x21)) // key[1..32] 
            y := mload(add(key, 0x41)) // key[33..64] 
        }
        bytes32 h = keccak256(abi.encodePacked(x, y)); // 64-byte XY 
        return address(uint160(uint256(h)));
    }
}
```

### ERC-KeyHash20 Implementation

```solidity
pragma solidity ^0.8.0;
import &quot;@openzeppelin/contracts/utils/cryptography/ECDSA.sol&quot;;
import &quot;@openzeppelin/contracts/utils/cryptography/EIP712.sol&quot;;

contract KeyHashERC20 is EIP712 {
    using ECDSA for bytes32;

    string public name;
    string public symbol;
    uint8 public decimals;
    mapping(bytes32 =&gt; uint256) public balanceOf;
    uint256 public totalSupply;
    mapping(bytes32 =&gt; uint256) private _keyNonces;

    event KeyHashTransfer20(bytes32 indexed fromKeyHash, bytes32 indexed toKeyHash, uint256 amount);

    bytes32 private constant TRANSFER_TYPEHASH = keccak256(
        &quot;Transfer(bytes32 fromKeyHash,bytes32 toKeyHash,uint256 amount,uint256 nonce,uint256 deadline,bytes32 leftKeyHash)&quot;
    );

    constructor(string memory _name, string memory _symbol)
        EIP712(&quot;KeyHashERC20&quot;, &quot;1&quot;)
    {
        name = _name;
        symbol = _symbol;
        decimals = 18;
    }


    function transfer(
        bytes32 fromKeyHash,
        bytes32 toKeyHash,
        uint256 amount,
        bytes memory key,
        bytes memory signature,
        uint256 deadline,
        bytes32 leftKeyHash
    ) external {
        require(balanceOf[fromKeyHash] &gt;= amount, &quot;Insufficient balance&quot;);
        require(toKeyHash != bytes32(0), &quot;Invalid recipient hash&quot;);
        require(leftKeyHash != bytes32(0), &quot;Invalid leftKeyHash&quot;);
        require(leftKeyHash != toKeyHash, &quot;LEFT_EQ_TO&quot;);
        require(leftKeyHash != fromKeyHash, &quot;LEFT_EQ_FROM&quot;);
        require(block.timestamp &lt;= deadline, &quot;Signature expired&quot;);
        require(key.length == 65 &amp;&amp; key[0] == 0x04, &quot;BAD_KEY_FMT&quot;);
        require(keccak256(key) == fromKeyHash, &quot;BAD_KEYHASH&quot;);

        uint256 nonce = _keyNonces[fromKeyHash];
        bytes32 structHash = keccak256(abi.encode(
            TRANSFER_TYPEHASH,
            fromKeyHash,
            toKeyHash,
            amount,
            nonce,
            deadline,
            leftKeyHash
        ));
        bytes32 digest = _hashTypedDataV4(structHash);
        address signer = digest.recover(signature);
        address expectedAddress = _addressFromUncompressedKey(key);
        require(signer == expectedAddress, &quot;Invalid signature&quot;);
        _keyNonces[fromKeyHash] = nonce + 1; // 验签通过后再自增

        uint256 remaining = balanceOf[fromKeyHash] - amount;
        balanceOf[fromKeyHash] = 0;
        balanceOf[toKeyHash] += amount;
        balanceOf[leftKeyHash] += remaining;
        emit KeyHashTransfer20(fromKeyHash, toKeyHash, amount);
    }

    function getNonce(bytes32 keyHash) external view returns (uint256) {
        return _keyNonces[keyHash];
    }

    function _addressFromUncompressedKey(bytes memory key) internal pure returns (address) {
        // key: 65 bytes, [0] = 0x04, [1..32] = X, [33..64] = Y 
        require(key.length == 65 &amp;&amp; key[0] == 0x04, &quot;BAD_KEY_FMT&quot;);
        bytes32 x;
        bytes32 y;
        assembly {
            x := mload(add(key, 0x21)) // key[1..32] 
            y := mload(add(key, 0x41)) // key[33..64] 
        }
        bytes32 h = keccak256(abi.encodePacked(x, y)); // 64-byte XY 
        return address(uint160(uint256(h)));
    }
}
```

## Security Considerations

- **Replay Attacks**:
  - **Mitigation**: Per-keyHash nonces (`_keyNonces[keyHash]`) increment after each operation, invalidating old signatures. 
  - **Design**: Similar to [EIP-2612](/EIPs/EIPS/eip-2612) permit mechanism, ensuring owner-controlled nonce sequences.
- **Message Tampering**:
  - **Mitigation**: [EIP-712](/EIPs/EIPS/eip-712) structured signatures include all critical parameters (`tokenId`, `toKeyHash`, `amount`, `leftKeyHash`, etc.), preventing relayer tampering. Signatures are function-specific (`TRANSFER_TYPEHASH`, `DESTROY_TYPEHASH`).
  - **Audit**: Contracts MUST be audited to ensure no parameter omissions or hash collisions.
- **Signature Expiration**:
  - **Mitigation**: `deadline` parameter ensures signatures expire, reducing risks of leaked signatures.
- **Privacy Limitations**:
  - **Issue**: Public keys (key) are revealed in calldata; the corresponding Ethereum addresses can be derived off‑chain from keccak256(key[1:]). Use fresh keys (toKeyHash / leftKeyHash) to reduce linkability.
  - **Recommendation**: Use new key pairs per token or balance to minimize linkability. Store `hashKey` securely, as it is sensitive.
- **Key Management**:
  - **Risk**: Loss or compromise of the private key corresponding to `key` results in loss of control. Store private keys securely.
  - **Recommendation**: Use safe systems to save `key`.
- **Gas Costs**:
  - **Issue**: Signature verification and [EIP-712](/EIPs/EIPS/eip-712) hashing increase gas costs.
  - **Recommendation**: Optimize implementations and consider gas sponsorship to offset costs.
- **Signature Malleability**: Implementations MUST reject malleable signatures (low‑S, v ∈ {27, 28}). OpenZeppelin’s ECDSA helpers enforce these checks by default.
## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 16 May 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7962</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7962</guid>
      </item>
    
      <item>
        <title>Crosschain EIP-712 Signatures</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/universal-cross-chain-signatures-for-account-abstraction/24452</comments>
        
        <description>## Abstract

This ERC defines a standard approach for creating and verifying crosschain signatures using [EIP-712]. By omitting the `chainId` field from the EIP-712 domain, a signature can be valid across multiple chains. Chain-specific operations are encoded as an array of structured messages, where each chain receives the array of message hashes and only the full message data relevant to that chain. This enables efficient crosschain signature validation using standard EIP-712 encoding without requiring special wallet support.

[EIP-712]: /EIPs/EIPS/eip-712

[ERC-1271]: /EIPs/EIPS/eip-1271

[ERC-5267]: /EIPs/EIPS/eip-5267

## Motivation

Current account abstraction solutions require separate signatures for each blockchain network. This creates poor user experience for crosschain operations such as:

- **Crosschain intents**: Users wanting to trade assets across multiple chains atomically
- **Multi-chain DAO governance**: Voting on proposals that affect protocol instances across different networks
- **Unified account management**: Managing the same account deployed on multiple chains
- **Crosschain social recovery**: Recovery processes that span multiple networks

Existing proposals either require complex Merkle tree constructions (which need wallet-specific UI to verify all leaves) or non-standard encoding schemes that lack wallet adoption. This ERC provides a simpler approach using only standard EIP-712 encoding with array types, enabling crosschain signatures with minimal on-chain overhead while maintaining full transparency in standard wallet signing interfaces.

## Specification

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

### Crosschain Domain Semantics

A crosschain [EIP-712] signature MUST omit the `chainId` field from the `EIP712Domain` type and domain object. Since `chainId` is optional per [EIP-712], omitting it signals that the signature is intended for crosschain validity.

Contract addresses and chainIds MUST be validated per-chain, so typically, only `name` and `version` are included in the main domain. The `verifyingContract` field MAY be used to bind the signature to a specific application deployed deterministically on the same address across all chains the signature is intended to be valid on, allowing to omit the contract address from the chain-specific structs.

### Message Array Encoding

Crosschain operations MUST be encoded as an array of message structs with chain-specific fields. Each struct in the array SHOULD include the target `chainId` field. When contracts are deployed at different addresses across chains, the struct SHOULD also include the `verifyingContract` (or equivalent) field to bind each operation to its specific contract address unless the main domain includes the `verifyingContract` field.

Implementers MAY use the canonical `EIP712Domain` struct but named to avoid collisions with `EIP712Domain` (e.g., `EIP712ChainDomain`) so it can be nested inside the chain-specific structs, allowing to include the `chainId` and `verifyingContract` fields.

Per [EIP-712], arrays are encoded as `keccak256(encodeData(element[0]) ‖ encodeData(element[1]) ‖ ... ‖ encodeData(element[n]))`, where each element is a struct that is recursively encoded as `hashStruct(element[i])`, and nested structs are also recursively hashed.

In practice, this means the array of chain-specific operations is represented as an array of pre-computed `bytes32` struct hashes (one for each chain). The hash of this array is computed as `keccak256(abi.encodePacked(structsArray))`, which concatenates all 32-byte hashes and produces the array hash that matches the standard [EIP-712] array encoding for reference types.

#### Struct Hash

Per [EIP-712], the signature is computed over a complete message struct (e.g., `CrossChainIntent`, `MultiChainVote`), not just the array of operations. Applications implementing verification MUST define a type hash for the complete message struct that includes the array of operations.

Wrapping the array of operations in a main struct also allows to include other message fields (e.g., `nonce`, `deadline`) in the struct hash. For example, for a `CrossChainIntent` struct would be encoded as:

```solidity
   bytes32 constant CROSSCHAIN_INTENT_TYPEHASH = keccak256(
       &quot;CrossChainIntent(ChainOperation[] operations,uint256 nonce,uint256 deadline)ChainOperation(EIP712ChainDomain domain,address target,uint256 value,bytes data)EIP712ChainDomain(uint256 chainId,address verifyingContract)&quot;
   );

   fullStructHash = keccak256(abi.encode(
       CROSSCHAIN_INTENT_TYPEHASH,
       keccak256(abi.encodePacked(chainOperationsArray)),
       nonce,
       deadline
   ));
```

Applications implementing verification MUST use the same typehash across all chains where the application is deployed.

### On-Chain Verification

To enable applications to detect and verify crosschain signatures through standard ECDSA validation or [ERC-1271] `isValidSignature` calls, crosschain signatures SHOULD be encoded with metadata in the signature parameter. The signature validation flow requires the contract application to detect the encoding of this ERC, parse the signature components, and then verify the signature agains the reconstructed crosschain message hash.

The signature encoding format uses ABI encoding for dynamic types (arrays and bytes) with the following structure:

```
[0x00:0x09] magic (9 bytes)
[0x09:0x0a] fields (1 byte)
[0x0a:0x0c] structIndex (2 bytes, big-endian uint16)
[0x0c:0x20] application (20 bytes)
[0x20:0x40] structsArrayOffset (32 bytes, big-endian uint256, offset to structsArray location)
[structsArrayOffset:structsArrayOffset + 32] structsArrayLength (32 bytes, big-endian uint256)
[structsArrayOffset + 32:structsArrayOffset + 32 + structsArrayLength * 32] structsArray (structsArrayLength * 32 bytes)
[crossChainSignatureOffset:crossChainSignatureOffset + 32] crossChainSignatureLength (32 bytes, big-endian uint256)
[crossChainSignatureOffset + 32:crossChainSignatureOffset + 32 + crossChainSignatureLength] crossChainSignature (crossChainSignatureLength bytes)
```

Equivalent to the following ABI encoding:

```solidity
bytes32 header = bytes32(abi.encodePacked(CrossChainSignatureChecker.ERC7964_MAGIC, fields, structIndex, address(application)));
abi.encode(header, structsArray, crossChainSignature); // (bytes32, bytes, bytes32[])
```

Where:

- **`magic`**: A fixed 9-byte value `0x796479647964796479` used to detect encoded crosschain signatures
- **`fields`**: A single byte encoding which [EIP-712] domain fields are present (per [ERC-5267])
- **`structIndex`**: The index in the `structsArray` corresponding to the current chain&apos;s operation
- **`application`**: The address of a contract implementing [ERC-5267] that provides the [EIP-712] domain information
- **`structsArrayOffset`**: The offset (in bytes) from the start of the signature to where the `structsArray` begins.
- **`structsArrayLength`**: The number of elements in the structs array
- **`structsArray`**: Array of `bytes32` hashes, one per chain operation
- **`crossChainSignatureOffset`**: The offset (in bytes) from the start of the signature to where the `crossChainSignature` begins.
- **`crossChainSignatureLength`**: The length of the crosschain signature in bytes
- **`crossChainSignature`**: The actual signature bytes that sign the crosschain message

This encoding allows applications to identify when a signature is a crosschain signature, rebuild the EIP-712 domain information needed to reconstruct the expected typed hash, and verify the signature against the reconstructed crosschain message hash.

Applications can detect crosschain signatures by checking if the first 9 bytes of the signature equal the magic value `0x796479647964796479`. If detected, applications MUST:

1. Parse the encoded metadata from the signature
2. Verify that `structsArray[structIndex]` matches the struct hash of the current chain&apos;s message
3. Query the [ERC-5267] contract at `application` to obtain the EIP-712 domain
4. Reconstruct the full [EIP-712] hash using the domain, the main struct hash and the array of chain-specific struct hashes
5. Verify the `crossChainSignature` against the reconstructed typed hash

### Wallet Display

Standard [EIP-712] wallets will automatically display the array of chain-specific messages in a readable format. Wallets MAY enhance the display by grouping operations by chain and showing chain names instead of chain IDs for better user experience.

## Rationale

### Standard EIP-712 Compatibility

This ERC uses only standard [EIP-712] encoding without any extensions or special constructs. All fields in the `EIP712Domain` are optional per the standard, so omitting `chainId` is perfectly valid. This means any wallet that supports EIP-712 can sign these messages and any application that supports EIP-712 can verify them.

The main benefit of this approach is that users can achieve a full transparent view of the crosschain message in any wallet provider that supports [EIP-712].

### Main Struct Hash

For wallet providers to show the crosschain message properly, they need a `primaryType` to display the message. This specification does not mandate a specific `primaryType` to allow for flexibility in the implementation, but defines the requirements for the array of operations and the main struct to ensure a secure EIP-712 message.

The specification requires that each of the operations include the `chainId` field to avoid replaying the same operation on other chains. The `verifyingContract` field (or equivalent) is used to bind the operation to its specific contract address and is optional if the main `EIP712Domain` includes the `verifyingContract` field since the domain hash would include the application&apos;s address.

### Array Encoding vs Merkle Trees

Alternative approaches use Merkle trees to commit to crosschain operations. While Merkle trees can reduce on-chain overhead for many chains, they have a critical drawback:

**Wallet Verification Complexity**: Standard EIP-712 wallets cannot display Merkle tree leaves. Users signing a Merkle root have no way to verify all operations in their wallet UI. Wallets would need to implement custom logic to:

1. Request all leaves from the application
2. Verify the Merkle tree construction
3. Display all operations across all chains
4. Ensure no malicious operations are hidden

This breaks the principle of trustless signing, users must trust the application to correctly provide all leaves, and wallet developers must implement and maintain custom verification logic.

The array-based approach provides **full transparency** using standard EIP-712. Users see all chain-specific operations in any compliant wallet without custom support. No hidden operations are possible since all array elements are displayed as part of the standard EIP-712 message structure.

**On-chain overhead comparison**: For reasonable crosschain operations, the overhead difference is minimal.

With the array approach, each chain receives all N operation hashes (`N × 32 bytes`). With Merkle trees (assuming a binary tree), each chain receives a Merkle proof of size `ceil(log₂(N)) × 32 bytes`. Both approaches reconstruct the root/array hash on-chain from the provided data and verify it against the signature, no additional calldata for the root is needed. While Merkle proofs grow logarithmically vs. the array&apos;s linear growth, the practical savings are small for reasonable use cases:

| Chains | Array (N × 32)     | Merkle (⌈log₂(N)⌉ × 32) | Savings              |
| ------ | ------------------ | ----------------------- | -------------------- |
| 2      | 64 bytes (2 × 32)  | 32 bytes (1 × 32)       | 32 bytes (1 hash)    |
| 3      | 96 bytes (3 × 32)  | 64 bytes (2 × 32)       | 32 bytes (1 hash)    |
| 4      | 128 bytes (4 × 32) | 64 bytes (2 × 32)       | 64 bytes (2 hashes)  |
| 5      | 160 bytes (5 × 32) | 96 bytes (3 × 32)       | 64 bytes (2 hashes)  |
| 8      | 256 bytes (8 × 32) | 96 bytes (3 × 32)       | 160 bytes (5 hashes) |

For 2-5 chains (the reasonable case for crosschain operations), Merkle trees save only 32-64 bytes (1-2 hashes) per transaction. This minimal savings doesn&apos;t justify the complexity and loss of transparency. Merkle trees only become significantly more efficient at 8+ chains, which is an uncommon use case and may indicate the operation should be split into multiple signatures for better user comprehension and failure isolation.

### Omitting chainId vs using `0`

Omitting `chainId` entirely is cleaner than using a special value like `0` because it explicitly signals that the signature is intended for crosschain validity.

### Signature Encoding Format

The custom binary encoding format for crosschain signatures was selected to minimize calldata and memory overhead. The format packs metadata values that can be read to the stack and uses ABI encoding for `structsArray` and `crossChainSignature` for easy calldata and memory casting.

The magic value is used to detect crosschain signatures and is designed to be easy to parse and verify. It&apos;s a fixed 9-byte value that is easy to identify and verify. The length was selected to pack it along with `bytes1(fields)`, `uint16(structIndex)` and `address(application)` into a single 32-byte word. While 9 bytes is shorter than a full 32-byte hash, the collision probability remains negligible in practice—an attacker would need to produce a valid ECDSA or [ERC-1271] signature that randomly begins with these exact 9 bytes, which has probability 2^-72 (approximately 1 in 4.7 × 10^21) assuming a uniform distribution.

The `fields` byte encodes which EIP-712 domain fields are present in the main domain (per [ERC-5267]), enabling dynamic field selection. Only `name` and `version` are normally set in the main domain, since `chainId` is omitted for crosschain validity since each chain-specific struct includes its own `chainId` and optionally `verifyingContract` (or equivalent), allowing each chain to validate its own contract address as part of the struct hash verification.

The `application` address refers to any contract that implements [ERC-5267]&apos;s `eip712Domain()` function. This contract provides the domain separator information needed to reconstruct the crosschain message hash. The application contract does not need to be the contract that executes the operation: it serves solely as a source of EIP-712 domain metadata. Applications could either deploy dedicated immutable domain separator contracts to ensure consistent domain information across all chains, or use the executing contract itself if it implements [ERC-5267].

## Backwards Compatibility

This ERC uses standard [EIP-712] without modifications. Existing wallets and applications that support EIP-712 can immediately work with crosschain signatures without any changes, though they may not recognize the crosschain semantics.

Applications that verify signatures with a domain that includes a specific `chainId` will reject crosschain signatures (where `chainId` is omitted), providing safe failure by default. Applications that wish to support crosschain signatures must explicitly implement the verification pattern described in this ERC.

## Reference Implementation

To validate a crosschain signature, the application can use the following library:

```solidity
import {SignatureChecker} from &quot;@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol&quot;;
import {MessageHashUtils} from &quot;@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol&quot;;
import {IERC5267} from &quot;@openzeppelin/contracts/interfaces/IERC5267.sol&quot;;
import {Calldata} from &quot;@openzeppelin/contracts/utils/Calldata.sol&quot;;

library CrossChainSignatureChecker {
    bytes9 internal constant ERC7964_MAGIC = 0x796479647964796479;

    function isValidCrossChainSignatureNow(
        address signer,
        bytes32 hash,
        bytes calldata erc7964Signature,
        function(bytes32) internal view returns (bytes32) structHash
    ) internal view returns (bool) {
        (
            bool success,
            bytes1 fields,
            uint16 structIndex,
            address application,
            bytes32[] calldata structsArray,
            bytes calldata crossChainSignature
        ) = parseCrossChainSignature(erc7964Signature);
        if (!success || structsArray[structIndex] != hash) return false;

        string memory name;
        string memory version;
        uint256 chainId;
        address verifyingContract;
        bytes32 domainSalt;
        (, name, version, chainId, verifyingContract, domainSalt, ) = IERC5267(application).eip712Domain();

        bytes32 typedHash = MessageHashUtils.toTypedDataHash(
            MessageHashUtils.toDomainSeparator(fields, name, version, chainId, verifyingContract, domainSalt),
            structHash(keccak256(abi.encodePacked(structsArray)))
        );
        return SignatureChecker.isValidSignatureNowCalldata(signer, typedHash, crossChainSignature);
    }

    function parseCrossChainSignature(
        bytes calldata erc7964Signature
    )
        internal
        pure
        returns (
            bool success,
            bytes1 fields,
            uint16 structIndex,
            address application,
            bytes32[] calldata structsArray,
            bytes calldata crossChainSignature
        )
    {
        // magic (9 bytes) + fields (1 byte) + structIndex (2 bytes) + application (20 bytes) + structsArrayOffset (32 bytes) +
        // structsArrayLength (32 bytes) + crossChainSignatureOffset (32 bytes) + crossChainSignatureLength (32 bytes)
        if (erc7964Signature.length &lt; 0x9f || bytes9(erc7964Signature[0:9]) != ERC7964_MAGIC) {
            return (false, 0, 0, address(0), _empty32BytesArrayCalldata(), Calldata.emptyBytes());
        }
        fields = erc7964Signature[9];
        structIndex = uint16(bytes2(erc7964Signature[10:]));
        application = address(bytes20(erc7964Signature[12:]));

        uint256 structsArrayOffset = uint256(bytes32(erc7964Signature[0x20:]));
        uint256 structsArrayDataOffset = structsArrayOffset + 32;
        if (structsArrayOffset &lt; 0x60 || structsArrayDataOffset &gt; erc7964Signature.length) {
            return (false, 0, 0, address(0), _empty32BytesArrayCalldata(), Calldata.emptyBytes());
        }
        uint256 structsArrayLength = uint256(bytes32(erc7964Signature[structsArrayOffset:]));
        if (structsArrayDataOffset + structsArrayLength * 32 &gt; erc7964Signature.length) {
            return (false, 0, 0, address(0), _empty32BytesArrayCalldata(), Calldata.emptyBytes());
        }

        uint256 crossChainSignatureOffset = structsArrayDataOffset + structsArrayLength * 32;
        uint256 crossChainSignatureDataOffset = crossChainSignatureOffset + 32;
        if (crossChainSignatureOffset &lt; 0x60 || crossChainSignatureDataOffset &gt; erc7964Signature.length) {
            return (false, 0, 0, address(0), _empty32BytesArrayCalldata(), Calldata.emptyBytes());
        }
        uint256 crossChainSignatureLength = uint256(bytes32(erc7964Signature[crossChainSignatureOffset:]));
        if (crossChainSignatureDataOffset + crossChainSignatureLength &gt; erc7964Signature.length) {
            return (false, 0, 0, address(0), _empty32BytesArrayCalldata(), Calldata.emptyBytes());
        }

        assembly (&quot;memory-safe&quot;) {
            structsArray.offset := add(erc7964Signature.offset, structsArrayDataOffset)
            structsArray.length := structsArrayLength
        }
        crossChainSignature = erc7964Signature[
            crossChainSignatureDataOffset:crossChainSignatureDataOffset + crossChainSignatureLength
        ];
        return (true, fields, structIndex, application, structsArray, crossChainSignature);
    }

    function _empty32BytesArrayCalldata() private pure returns (bytes32[] calldata result) {
        assembly (&quot;memory-safe&quot;) {
            result.offset := 0
            result.length := 0
        }
    }
}
```

A collection of examples of how to use this ERC to fulfill the _Motivation_ use cases.

### Crosschain Intent Example

A user wants to execute a crosschain trade: sell USDC on Ethereum, receive ETH on Arbitrum:

```javascript
{
  types: {
    EIP712Domain: [
      { name: &quot;name&quot;, type: &quot;string&quot; },
      { name: &quot;version&quot;, type: &quot;string&quot; }
      // Note: chainId is omitted for crosschain validity
    ],
    CrossChainIntent: [
      { name: &quot;operations&quot;, type: &quot;ChainOperation[]&quot; },
      { name: &quot;nonce&quot;, type: &quot;uint256&quot; },
      { name: &quot;deadline&quot;, type: &quot;uint256&quot; }
    ],
    ChainOperation: [
      { name: &quot;domain&quot;, type: &quot;EIP712ChainDomain&quot; },
      { name: &quot;target&quot;, type: &quot;address&quot; },
      { name: &quot;value&quot;, type: &quot;uint256&quot; },
      { name: &quot;data&quot;, type: &quot;bytes&quot; }
    ],
    EIP712ChainDomain: [
      { name: &quot;chainId&quot;, type: &quot;uint256&quot; },
      { name: &quot;verifyingContract&quot;, type: &quot;address&quot; }
    ]
  },
  primaryType: &quot;CrossChainIntent&quot;,
  domain: {
    name: &quot;CrossChainDEX&quot;,
    version: &quot;1&quot;
  },
  message: {
    operations: [
      {
        domain: {
          chainId: 1,
          verifyingContract: &quot;0x123321...&quot; // User&apos;s account on Ethereum
        },
        target: &quot;0xA0b86a33E6776885F5Db...&quot;, // USDC contract
        value: 0,
        data: &quot;0xa9059cbb...&quot; // transfer(settler, 1000 USDC)
      },
      {
        domain: {
          chainId: 42161,
          verifyingContract: &quot;0x123321...&quot; // User&apos;s account on Arbitrum
        },
        target: &quot;0xArbitrumSettler...&quot;,
        value: 0,
        data: &quot;0x3ccfd60b...&quot; // claim(0.5 ETH min)
      }
    ],
    nonce: 42,
    deadline: 1704067200
  }
}
```

**On-chain verification on Ethereum:**

Applications can verify crosschain signatures using the encoded format. The signature contains all necessary metadata to reconstruct and verify the crosschain message:

```solidity
import {EIP712} from &quot;@openzeppelin/contracts/utils/cryptography/EIP712.sol&quot;;
import {Nonces} from &quot;@openzeppelin/contracts/utils/Nonces.sol&quot;;
import {CrossChainSignatureChecker} from &quot;./CrossChainSignatureChecker.sol&quot;;

contract CrossChainDEX is EIP712, Nonces {
    using CrossChainSignatureChecker for address;

    bytes32 public constant EIP712_CHAIN_DOMAIN_TYPEHASH =
        keccak256(&quot;EIP712ChainDomain(uint256 chainId,address verifyingContract)&quot;);
    bytes32 public constant CHAIN_OPERATION_TYPEHASH =
        keccak256(&quot;ChainOperation(EIP712ChainDomain domain,address target,uint256 value,bytes data)EIP712ChainDomain(uint256 chainId,address verifyingContract)&quot;);
    bytes32 public constant CROSSCHAIN_INTENT_TYPEHASH =
        keccak256(&quot;CrossChainIntent(ChainOperation[] operations,uint256 nonce,uint256 deadline)ChainOperation(EIP712ChainDomain domain,address target,uint256 value,bytes data)EIP712ChainDomain(uint256 chainId,address verifyingContract)&quot;);

    mapping(bytes32 operationHash =&gt; uint256) private _deadlines;

    constructor() EIP712(&quot;CrossChainDEX&quot;, &quot;1&quot;) {}

    function executeIntent(
        address account,
        ChainOperation calldata currentOp,
        uint256 nonce,
        uint256 deadline,
        bytes calldata signature
    ) external {
        bytes32 currentOpHash = _structHash(currentOp);

        _useCheckedNonce(account, nonce);
        _deadlines[currentOpHash] = deadline;

        require(
            account.isValidCrossChainSignatureNowCalldata(
                currentOpHash,
                signature,
                _crossChainStructHash
            ),
            &quot;Invalid signature&quot;
        );

        (bool success, ) = currentOp.target.call{value: currentOp.value}(currentOp.data);
        require(success, &quot;Execution failed&quot;);
    }

    function _crossChainStructHash(bytes32 operationsHash) internal view returns (bytes32) {
        return keccak256(abi.encode(CROSSCHAIN_INTENT_TYPEHASH, operationsHash, nonces(account), _deadlines[operationsHash]));
    }

    function _structHash(ChainOperation calldata op) internal view returns (bytes32) {
        return keccak256(
            abi.encode(
                CHAIN_OPERATION_TYPEHASH,
                keccak256(abi.encode(EIP712_CHAIN_DOMAIN_TYPEHASH, block.chainid, address(this))),
                op.target,
                op.value,
                keccak256(op.data)
            )
        );
    }
}
```

The Arbitrum settler would use the same signature with `currentIndex: 1` and the full data for `op[1]`. Each chain only receives the full calldata for its own operation, while other operations are represented as 32-byte hashes.

### Multi-Chain Governance Example

A DAO member votes on a proposal affecting all chain deployments:

```javascript
{
  types: {
    EIP712Domain: [
      { name: &quot;name&quot;, type: &quot;string&quot; },
      { name: &quot;version&quot;, type: &quot;string&quot; }
    ],
    MultiChainVote: [
      { name: &quot;votes&quot;, type: &quot;ChainVote[]&quot; },
      { name: &quot;nonce&quot;, type: &quot;uint256&quot; }
    ],
    ChainVote: [
      { name: &quot;domain&quot;, type: &quot;EIP712ChainDomain&quot; },
      { name: &quot;proposalId&quot;, type: &quot;uint256&quot; },
      { name: &quot;support&quot;, type: &quot;uint8&quot; },
      { name: &quot;reason&quot;, type: &quot;string&quot; }
    ],
    EIP712ChainDomain: [
      { name: &quot;chainId&quot;, type: &quot;uint256&quot; },
      { name: &quot;verifyingContract&quot;, type: &quot;address&quot; }
    ]
  },
  primaryType: &quot;MultiChainVote&quot;,
  domain: {
    name: &quot;MultiChainDAO&quot;,
    version: &quot;1&quot;
  },
  message: {
    votes: [
      {
        domain: {
          chainId: 1,
          verifyingContract: &quot;0x123321...&quot; // DAO contract on Ethereum
        },
        proposalId: 42,
        support: 1, // For
        reason: &quot;This upgrade improves security&quot;
      },
      {
        domain: {
          chainId: 137,
          verifyingContract: &quot;0x321321...&quot; // DAO contract on Polygon
        },
        proposalId: 42,
        support: 1, // For
        reason: &quot;This upgrade improves security&quot;
      }
    ],
    nonce: 7
  }
}
```

**On-chain verification on each DAO:**

```solidity
import {EIP712} from &quot;@openzeppelin/contracts/utils/cryptography/EIP712.sol&quot;;
import {Nonces} from &quot;@openzeppelin/contracts/utils/Nonces.sol&quot;;
import {CrossChainSignatureChecker} from &quot;./CrossChainSignatureChecker.sol&quot;;

contract MultiChainDAO is EIP712, Nonces {
    using CrossChainSignatureChecker for address;

    bytes32 public constant EIP712_CHAIN_DOMAIN_TYPEHASH =
        keccak256(&quot;EIP712ChainDomain(uint256 chainId,address verifyingContract)&quot;);
    bytes32 public constant CHAIN_VOTE_TYPEHASH =
        keccak256(&quot;ChainVote(EIP712ChainDomain domain,uint256 proposalId,uint8 support,string reason)EIP712ChainDomain(uint256 chainId,address verifyingContract)&quot;);
    bytes32 public constant MULTICHAIN_VOTE_TYPEHASH =
        keccak256(&quot;MultiChainVote(ChainVote[] votes,uint256 nonce)ChainVote(EIP712ChainDomain domain,uint256 proposalId,uint8 support,string reason)EIP712ChainDomain(uint256 chainId,address verifyingContract)&quot;);

    constructor() EIP712(&quot;MultiChainDAO&quot;, &quot;1&quot;) {}

    function castVoteWithSignature(
        ChainVote calldata currentVote,
        uint256 nonce,
        address voter,
        bytes calldata erc7964Signature
    ) external {
        bytes32 currentVoteHash = _structHash(currentVote);

        _useCheckedNonce(voter, nonce);

        require(
            voter.isValidCrossChainSignatureNowCalldata(
                currentVoteHash,
                erc7964Signature,
                _crossChainStructHash
            ),
            &quot;Invalid signature&quot;
        );

        _castVote(currentVote.proposalId, voter, currentVote.support, currentVote.reason);
    }

    function _crossChainStructHash(bytes32 votesHash) internal view returns (bytes32) {
        return keccak256(abi.encode(MULTICHAIN_VOTE_TYPEHASH, votesHash, nonces(voter)));
    }

    function _structHash(ChainVote calldata vote) internal view returns (bytes32) {
        return keccak256(
            abi.encode(
                CHAIN_VOTE_TYPEHASH,
                keccak256(abi.encode(EIP712_CHAIN_DOMAIN_TYPEHASH, block.chainid, address(this))),
                vote.proposalId,
                vote.support,
                keccak256(bytes(vote.reason))
            )
        );
    }
}
```

This vote signature can be submitted to DAO contracts on both Ethereum and Polygon, enabling coordinated multi-chain governance decisions.

### Unified Account Management Example

A user wants to add a new signer to their multisig account deployed across multiple chains:

```javascript
{
  types: {
    EIP712Domain: [
      { name: &quot;name&quot;, type: &quot;string&quot; },
      { name: &quot;version&quot;, type: &quot;string&quot; }
    ],
    MultiChainAccountUpdate: [
      { name: &quot;updates&quot;, type: &quot;AccountUpdate[]&quot; },
      { name: &quot;nonce&quot;, type: &quot;uint256&quot; }
    ],
    AccountUpdate: [
      { name: &quot;domain&quot;, type: &quot;EIP712ChainDomain&quot; },
      { name: &quot;operation&quot;, type: &quot;uint8&quot; }, // 0=addSigner, 1=removeSigner, 2=changeThreshold
      { name: &quot;signerData&quot;, type: &quot;bytes&quot; },
      { name: &quot;threshold&quot;, type: &quot;uint256&quot; }
    ],
    EIP712ChainDomain: [
      { name: &quot;chainId&quot;, type: &quot;uint256&quot; },
      { name: &quot;verifyingContract&quot;, type: &quot;address&quot; }
    ]
  },
  primaryType: &quot;MultiChainAccountUpdate&quot;,
  domain: {
    name: &quot;MultiChainMultisig&quot;,
    version: &quot;1&quot;
  },
  message: {
    updates: [
      {
        domain: {
          chainId: 1,
          verifyingContract: &quot;0x123321...&quot; // Account on Ethereum
        },
        operation: 0, // addSigner
        signerData: &quot;0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20&quot;,
        threshold: 3
      },
      {
        domain: {
          chainId: 137,
          verifyingContract: &quot;0x123321...&quot; // Account on Polygon
        },
        operation: 0, // addSigner
        signerData: &quot;0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20&quot;,
        threshold: 3
      },
      {
        domain: {
          chainId: 42161,
          verifyingContract: &quot;0x123321...&quot; // Account on Arbitrum
        },
        operation: 0, // addSigner
        signerData: &quot;0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20&quot;,
        threshold: 3
      }
    ],
    nonce: 42
  }
}
```

**On-chain execution:**

```solidity
import {EIP712} from &quot;@openzeppelin/contracts/utils/cryptography/EIP712.sol&quot;;
import {Nonces} from &quot;@openzeppelin/contracts/utils/Nonces.sol&quot;;
import {CrossChainSignatureChecker} from &quot;./CrossChainSignatureChecker.sol&quot;;

contract MultiChainMultisig is EIP712, Nonces {
    using CrossChainSignatureChecker for address;

    bytes32 public constant EIP712_CHAIN_DOMAIN_TYPEHASH =
        keccak256(&quot;EIP712ChainDomain(uint256 chainId,address verifyingContract)&quot;);
    bytes32 public constant ACCOUNT_UPDATE_TYPEHASH =
        keccak256(&quot;AccountUpdate(EIP712ChainDomain domain,uint8 operation,bytes signerData,uint256 threshold)EIP712ChainDomain(uint256 chainId,address verifyingContract)&quot;);
    bytes32 public constant MULTICHAIN_ACCOUNT_UPDATE_TYPEHASH =
        keccak256(&quot;MultiChainAccountUpdate(AccountUpdate[] updates,uint256 nonce)AccountUpdate(EIP712ChainDomain domain,uint8 operation,bytes signerData,uint256 threshold)EIP712ChainDomain(uint256 chainId,address verifyingContract)&quot;);

    constructor() EIP712(&quot;MultiChainMultisig&quot;, &quot;1&quot;) {}

    function updateAccountWithSignature(
        AccountUpdate calldata currentUpdate,
        uint256 nonce,
        bytes calldata erc7964Signature
    ) external {
        bytes32 currentUpdateHash = _structHash(currentUpdate);

        _useCheckedNonce(address(this), nonce);

        require(
            address(this).isValidCrossChainSignatureNowCalldata(
                currentUpdateHash,
                erc7964Signature,
                _crossChainStructHash
            ),
            &quot;Invalid signature&quot;
        );

        if (currentUpdate.operation == 0) {
            _addSigner(currentUpdate.signerData, currentUpdate.threshold);
        } // ... other operations
    }

    function _crossChainStructHash(bytes32 updatesHash) internal view returns (bytes32) {
        return keccak256(abi.encode(MULTICHAIN_ACCOUNT_UPDATE_TYPEHASH, updatesHash, nonces(address(this))));
    }

    function _structHash(AccountUpdate calldata update) internal view returns (bytes32) {
        return keccak256(
            abi.encode(
                ACCOUNT_UPDATE_TYPEHASH,
                keccak256(abi.encode(EIP712_CHAIN_DOMAIN_TYPEHASH, block.chainid, address(this))),
                update.operation,
                keccak256(update.signerData),
                update.threshold
            )
        );
    }

    function _addSigner(bytes calldata signerData, uint256 threshold) internal {
        // Implementation for adding signer
    }
}
```

This signature enables the multisig owners to add a new signer and update the threshold across all chain deployments simultaneously. The same account address exists on Ethereum, Polygon, and Arbitrum, and this single signature authorizes the updates on all three networks.

### CrossChain Social Recovery Example

A user has lost access to their account and guardians need to initiate recovery across multiple networks:

```javascript
{
  types: {
    EIP712Domain: [
      { name: &quot;name&quot;, type: &quot;string&quot; },
      { name: &quot;version&quot;, type: &quot;string&quot; }
      // Note: verifyingContract is omitted since the recovery module is deployed on different addresses across chains for this example
    ],
    MultiChainRecovery: [
      { name: &quot;recoveries&quot;, type: &quot;ChainRecovery[]&quot; },
      { name: &quot;nonce&quot;, type: &quot;uint256&quot; }
    ],
    ChainRecovery: [
      { name: &quot;domain&quot;, type: &quot;EIP712ChainDomain&quot; },
      { name: &quot;newOwner&quot;, type: &quot;address&quot; }
    ],
    EIP712ChainDomain: [
      { name: &quot;chainId&quot;, type: &quot;uint256&quot; },
      { name: &quot;verifyingContract&quot;, type: &quot;address&quot; }
    ]
  },
  primaryType: &quot;MultiChainRecovery&quot;,
  domain: {
    name: &quot;CrossChainSocialRecovery&quot;,
    version: &quot;1&quot;
  },
  message: {
    recoveries: [
      {
        domain: {
          chainId: 1,
          verifyingContract: &quot;0x123321...&quot; // Recovery module on Ethereum
        },
        newOwner: &quot;0x9999999999999999999999999999999999999999&quot;
      },
      {
        domain: {
          chainId: 137,
          verifyingContract: &quot;0x321321...&quot; // Recovery module on Polygon
        },
        newOwner: &quot;0x9999999999999999999999999999999999999999&quot;
      },
      {
        domain: {
          chainId: 42161,
          verifyingContract: &quot;0x432432...&quot; // Recovery module on Arbitrum
        },
        newOwner: &quot;0x9999999999999999999999999999999999999999&quot;
      }
    ],
    nonce: 1
  }
}
```

**On-chain execution with guardian multisig:**

```solidity
import { CrossChainSignatureChecker } from &quot;./CrossChainSignatureChecker.sol&quot;;

bytes32 constant EIP712_CHAIN_DOMAIN_TYPEHASH = keccak256(
    &quot;EIP712ChainDomain(uint256 chainId,address verifyingContract)&quot;
);
bytes32 constant CHAIN_RECOVERY_TYPEHASH = keccak256(
    &quot;ChainRecovery(EIP712ChainDomain domain,address newOwner)EIP712ChainDomain(uint256 chainId,address verifyingContract)&quot;
);
bytes32 constant MULTICHAIN_RECOVERY_TYPEHASH = keccak256(
    &quot;MultiChainRecovery(ChainRecovery[] recoveries,uint256 nonce)ChainRecovery(EIP712ChainDomain domain,address newOwner)EIP712ChainDomain(uint256 chainId,address verifyingContract)&quot;
);

uint256 private _tempNonce;

function initiateRecoveryWithSignature(
    ChainRecovery calldata currentRecovery,
    uint256 nonce,
    address[] calldata guardians,
    bytes[] calldata guardianErc7964Signatures
) external {
    require(guardians.length == guardianErc7964Signatures.length, &quot;Mismatched arrays&quot;);
    // Note: chainId and verifyingContract validation is implicit in the struct hash verification

    // Verify the current recovery hash matches all guardian signatures
    bytes32 currentRecoveryHash = _structHash(currentRecovery);

    _tempNonce = nonce;

    // Verify all guardian signatures are valid and count valid guardian signatures
    uint256 validSignatures = 0;
    for (uint256 i = 0; i &lt; guardians.length; i++) {
        if (
            CrossChainSignatureChecker.isValidCrossChainSignatureNow(
                guardians[i],
                currentRecoveryHash,
                guardianErc7964Signatures[i],
                _computeRecoveryStructHash
            ) &amp;&amp; isGuardian(guardians[i])
        ) {
            validSignatures++;
        }
    }
    require(validSignatures &gt;= 3, &quot;Insufficient guardian signatures&quot;);

    // Schedule recovery with delay
    _scheduleRecovery(currentRecovery.newOwner, block.timestamp + RECOVERY_DELAY);
}

function _computeRecoveryStructHash(
    bytes32 recoveriesHash
) internal view returns (bytes32) {
    return keccak256(abi.encode(
        MULTICHAIN_RECOVERY_TYPEHASH,
        recoveriesHash,
        _tempNonce
    ));
}

function _structHash(ChainRecovery calldata recovery) internal view returns (bytes32) {
    return keccak256(
        abi.encode(
            CHAIN_RECOVERY_TYPEHASH,
            keccak256(abi.encode(EIP712_CHAIN_DOMAIN_TYPEHASH, block.chainid, address(this))),
            recovery.newOwner
        )
    );
}
```

This signature enables guardians to schedule a recovery operation across all chains. The process includes:

1. **Guardian Signatures**: Multiple guardians sign the same crosschain recovery message (3-of-5 threshold)
2. **Schedule Phase**: Once sufficient guardians sign, the recovery is scheduled on all networks with a delay
3. **Security Window**: Delay period where malicious recovery attempts can be detected and canceled
4. **Execution Phase**: After the delay, the recovery replaces the account&apos;s owner
5. **CrossChain Consistency**: The same recovery operation is scheduled simultaneously on Ethereum, Polygon, and Arbitrum

## Security Considerations

### Crosschain Replay

This ERC intentionally enables replay across chains, the same signature is designed to be used on multiple chains. The `verifyingContract` field (set to the user&apos;s account address) binds the signature to a specific account, preventing unauthorized use. However, applications must implement their own replay protection mechanisms such as including nonces and deadlines in the message.

### Account Validation

Applications verifying signatures should check that the signing account exists on the current chain. An account that exists on Ethereum but not Polygon should not have signatures accepted on Polygon. For counterfactual accounts that have not been deployed yet, applications should follow [ERC-6492](/EIPs/EIPS/eip-6492) to validate signatures.

### Code and State Differences

Contract code and state may differ across chains at the same address. Signatures that pass `isValidSignature()` on one chain may fail on another due to state divergence or chain-specific logic. For example, a crosschain message that has uses a `nonce` field may find that the nonce is already used on one of the chains. Applications should handle signature validation failures gracefully and should not assume uniform behavior across chains.

### Partial Execution Risk

Crosschain signatures do not guarantee atomic execution. A signature may be successfully validated on some chains but not others. This can result in partial fulfillment of the intent. Applications should implement refund mechanisms to allow users to recover from failed partial executions.

Additionally, operations may execute in different orders across chains due to varying network conditions, block times, and congestion levels. An operation intended to execute first may complete last on a congested chain, leading to unexpected state changes. For example, in a crosschain trade, a user might sell an asset on one chain before successfully acquiring its replacement on another chain, creating temporary exposure. Applications should design operations to be order-independent where possible, or implement coordination mechanisms to ensure proper sequencing.

### Signature Expiration

Signatures without explicit expiration remain valid indefinitely. If an operation is not executed on some chains, it can be executed later, potentially with unexpected consequences. Applications may include `deadline` or `validUntil` fields in messages to prevent stale signature execution.

### Wallet Display Considerations

Since this ERC relies on standard EIP-712 wallet display, users depend on their wallet to correctly show all crosschain operations. Users should:

1. **Review All Operations**: Check every element in the message array
2. **Verify Chain IDs**: Ensure operations target the expected chains
3. **Check Amounts**: Verify asset amounts and addresses on each chain
4. **Understand Atomicity**: Know that operations may execute independently

Wallet developers should enhance displays to highlight crosschain nature and show warnings about partial execution risks.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 05 Jun 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7964</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7964</guid>
      </item>
    
      <item>
        <title>Proof-based Broadcast in ERC-7786 Gateways</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7965-storage-proof-broadcasting-for-cross-chain-messaging-gateways/24477</comments>
        
        <description>## Abstract

This document defines standardized broadcasting semantics and attributes for [ERC-7786] cross-chain messaging that enable trustless message verification through cryptographic proofs. Messages are committed on source chains in verifiable ways, then verified on destination chains using cryptographic proofs of the source chain&apos;s state or transaction history. This approach provides cross-chain communication without relying on external validators or bridge operators.

[ERC-7786]: /EIPs/EIPS/eip-7786

## Motivation

Cross-chain messaging protocols typically rely on external validators, multisigs, or optimistic mechanisms that introduce trust assumptions and potential points of failure. Cryptographic proofs offer an alternative approach where messages can be verified using the consensus mechanisms and cryptographic commitments of the chains themselves (e.g. storage proofs for EVM chains).

However, cryptographic proof verification requires chain-specific routing information, proof data, and verification parameters that are not addressed by the base [ERC-7786] interface. Additionally, while [ERC-7786] defines basic broadcasting through &quot;omitted or zeroed&quot; recipient addresses, it does not specify granular broadcasting patterns that enable targeting specific chains or chain types. Enhanced broadcasting semantics enable messages to be sent with varying levels of specificity, from all addresses on a specific chain to all supported infrastructure.

This document standardizes these requirements as [ERC-7786] attributes, enabling cryptographic proof-based messaging within the established cross-chain messaging framework. The specification supports multi-hop verification paths, allowing messages to traverse through multiple intermediary chains when direct verification is not possible.

The key benefits of this approach include:

- **Trustless verification**: No external validators or multisigs required. Chains trust their own consensus mechanisms.
- **Universal compatibility**: Works between chains with verifiable state relationships through shared settlement infrastructure or compatible proof systems.
- **Flexible messaging patterns**: Supports both targeted and granular broadcast messaging through standardized semantics, enabling new classes of applications like oracles and intent settlement systems.
- **Composability**: Full integration with existing [ERC-7786] infrastructure and tooling

## Specification

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

### Broadcasting Semantics

[ERC-7786] defines broadcasting as using &quot;omitted or zeroed&quot; recipient addresses (containing an [ERC-7930] interoperable address with all fields set to zero). This specification extends that concept to enable granular broadcasting patterns through [ERC-7930]&apos;s flexible address structure:

[ERC-7930]: /EIPs/EIPS/eip-7930

Broadcasting semantics in this specification extend [ERC-7786] by allowing:

* Interoperable addresses with `AddressLength` set to 0 and specified `ChainType` and/or `ChainReference` to broadcast messages to all addresses on a given chain
* Interoperable addresses with `ChainReferenceLength` set to 0 and a specified `ChainType` to broadcast to all chains of a given type
* Interoperable addresses with all fields set to zero to indicate universal broadcasting to all supported chains and addresses

Receivers of broadcast messages SHOULD validate the source and authenticity of messages according to their own security requirements.

### Cryptographic Proof Attributes

This specification defines the following [ERC-7786] attributes for cryptographic proof messaging. Gateways MUST return true if `supportsAttribute` is called with the selector for supported attributes.

#### `route((bytes,bytes,uint256)[])`

Specifies the verification path from destination to source chain with corresponding proofs and version requirements. Each tuple contains a bytes-encoded address that SHOULD be called for verification of the next chain&apos;s state or transaction history, the cryptographic proof required for that verification step, and the expected version of the verification logic (0 means any version is acceptable). The route address MAY invoke other gateways to resend the message to the next hop.

When a non-zero version is specified, gateways MUST reject messages if the route address does not support the exact required version (unless `0`). Route addresses SHOULD implement version querying mechanisms to enable compatibility checking.

The route MUST form a valid path where each step represents a direct relationship between chains that enables state or transaction verification. For multi-hop scenarios, the route creates a chain of trust where each step verifies the next, ultimately establishing the authenticity of the source chain&apos;s state. Gateways MUST reject messages with invalid or incomplete proof data.

```solidity
abi.encodeWithSignature(&quot;route((bytes,bytes,uint256)[])&quot;, hops);
```

#### `inclusionProof(bytes)`

The cryptographic proof demonstrating that a specific message exists in the source chain&apos;s committed state at a finalized block or transaction. For EVM chains, this would typically be an event inclusion proof or storage proof.

[ERC-7786] receivers MUST validate the cryptographic proof according to the source chain&apos;s proof system.

```solidity
abi.encodeWithSignature(&quot;inclusionProof(bytes)&quot;, proofData);
```

#### `targetBlock(uint256)`

Specifies the block number or height on the source chain where the message was committed. For chains that don&apos;t use sequential block numbers, this represents the equivalent commitment identifier.

[ERC-7786] receivers MAY validate the target block for freshness or finality requirements according to their security policies. Receivers MAY ignore this attribute if not needed for their use case.

When provided, this attribute SHOULD correspond to the block or commitment whose state is proven by the cryptographic proof.

```solidity
abi.encodeWithSignature(&quot;targetBlock(uint256)&quot;, blockNumber);
```

### Relationship to Existing Proof Protocols

This ERC provides standard attributes that enable protocols like [ERC-7888] (for EVM storage proofs) and other proof systems to implement [ERC-7786] gateways without rebuilding their core verification logic. For example, an [ERC-7888] Broadcaster MAY expose an [ERC-7786] interface using these attributes while maintaining its existing storage proof architecture. Similarly, other proof systems can implement these same attributes using their native proof mechanisms.

[ERC-7888]: /EIPs/EIPS/eip-7888

### Caching

Gateways implementing this specification MAY implement caching mechanisms to optimize repeated proof verifications.

### Mutability of Message Commitments

Gateways MAY choose to commit messages in ways that cannot be deleted or modified after being set, providing immutability guarantees. While not required by this standard, implementers can use [ERC-7201] to calculate namespaces for immutable storage locations on EVM chains, or equivalent immutability mechanisms on other chain architectures.

[ERC-7201]: /EIPs/EIPS/eip-7201

### Verification Process

In [ERC-7786], the `payload` contains the actual message data to be delivered, while the `attributes` contain proof metadata that establishes the payload&apos;s authenticity. The destination gateway validates the attributes through cryptographic verification, and it MAY cache results for future use.

For multihop scenarios, each route step verifies the next chain&apos;s state commitment, creating a chain of trust from destination to source. This enables message verification across multiple intermediate chains, similar to systems like [ERC-7888]&apos;s BlockHashProver chains.

Message verification follows these steps:

1. Parse the `route` and `inclusionProof` attributes from the message, and optionally `targetBlock` if provided
2. Validate all required attributes are present and well-formed
3. For each route step, verify block hash transition or equivalent state commitment using the paired proof and validate version requirements if specified (non-zero)
4. Use the `inclusionProof` to verify that message data exists in the source chain&apos;s committed state at the target block obtained from the route verification. The source chain SHOULD correspond to the final validated step in the route verification process
5. Optionally validate the `targetBlock` for freshness or finality requirements if the attribute is provided and the receiver chooses to validate it
6. Execute the message if all verifications pass

## Rationale

This standard extends [ERC-7786]&apos;s attribute system to add cryptographic proof capabilities without creating new interfaces. This approach maintains compatibility with existing infrastructure while enabling trustless cross-chain verification, allowing implementations to focus on proof verification logic rather than rebuilding messaging infrastructure.

### Broadcasting and Cryptographic Proofs

[ERC-7786] natively supports broadcasting through &quot;omitted or zeroed&quot; [ERC-7930] interoperable addresses. This specification extends that foundation to enable granular broadcasting patterns through [ERC-7930]&apos;s flexible address structure. Empty address components (`AddressLength` = 0) allow broadcasting to all addresses on a specific chain, while empty chain references (`ChainReferenceLength` = 0) enable broadcasting to all chains of a specific type (e.g., all EVM chains via `eip155` namespace). Universal broadcasting uses fully zeroed addresses as defined in [ERC-7786].

This multi-level broadcasting approach leverages [ERC-7930]&apos;s inherent address structure and [ERC-7786]&apos;s existing broadcast semantics rather than introducing new patterns, ensuring consistency with the cross-chain messaging ecosystem. The granularity enables efficient message distribution patterns: oracle feeds can target specific chains, governance messages can address entire chain families, and emergency notifications can reach all supported infrastructure.

Cryptographic proofs provide trustless verification relying only on chain consensus mechanisms. This approach offers universal accessibility, cryptographic guarantees, cost efficiency (gas only on source/destination chains), and enables implicit batching through shared state commitments. Multi-hop routing extends this capability to chains without direct verification relationships.

### Attribute Design

The two required attributes provide the essential functionality for cryptographic proof verification, while the optional `targetBlock` attribute enables additional freshness and finality validation when needed. Combining route information into a single tuple maintains type safety while separating proof verification from chain state transitions allows independent optimization. The optional nature of `targetBlock` provides implementation flexibility without adding unnecessary complexity to basic use cases.

### Caching

Caching can improve performance by storing verification results for reuse. Since proofs are deterministic, they can be safely cached. This is especially useful for broadcast messages that need multiple verifications. Implementations should cache both block hash transitions and proof verification results, while invalidating the cache when proof infrastructure changes.

### Mutability of Message Commitments

Proving a commitment that could be deleted or modified may introduce additional security risks. For example, if a message is committed in a way that allows deletion after the message is sent, the proof will still be valid. This is why the specification does not require immutability, but allows gateways to choose to commit messages in immutable ways if they so desire.

## Backwards Compatibility

This ERC extends [ERC-7786] through its attribute system and introduces no breaking changes to existing implementations. Gateways that do not support cryptographic proof attributes will simply reject messages containing them, which is the expected behavior for unsupported features.

Existing [ERC-7786] tooling and infrastructure can immediately leverage cryptographic proof messaging without modification, as the base interface remains unchanged.

## Reference Implementation

### Basic Gateway Usage

```solidity
struct Hop {
    bytes gateway; // bytes-encoded address of the gateway
    bytes proof;
    uint256 version; // 0 = any version
}

// Prepare route with proofs and version requirements
Hop[] memory hops = new Hop[](2);
hops[0] = Hop(gateway1, proof1, 1); // Require version 1
hops[1] = Hop(gateway2, proof2, 0); // Any version acceptable

// Example 1: Address Broadcasting - broadcast to all addresses on Arbitrum One (42161)
bytes memory addressBroadcast = abi.encodePacked(
    uint16(1),        // Version
    uint16(0x0000),   // ChainType: eip155
    uint8(2),         // ChainReferenceLength: 2 bytes for chain ID
    uint16(42161),    // ChainReference: Arbitrum One (42161)
    uint8(0)          // AddressLength: 0 (empty address = broadcast to all addresses)
);

// Example 2: Chain Type Broadcasting - broadcast to all EIP-155 chains
bytes memory chainTypeBroadcast = abi.encodePacked(
    uint16(1),        // Version
    uint16(0x0000),   // ChainType: eip155
    uint8(0),         // ChainReferenceLength: 0 (broadcast to all chains of this type)
    uint8(0)          // AddressLength: 0 (empty address)
);

// Example 3: Universal Broadcasting - broadcast to all supported chains and addresses
bytes memory universalBroadcast = abi.encodePacked(
    uint16(1),        // Version
    uint16(0x0000),   // ChainType: 0 (all chain types)
    uint8(0),         // ChainReferenceLength: 0 (all chains)
    uint8(0)          // AddressLength: 0 (all addresses)
);

bytes[] memory attributes = new bytes[](3);
attributes[0] = abi.encodeWithSignature(&quot;route((bytes,bytes,uint256)[])&quot;, hops);
attributes[1] = abi.encodeWithSignature(&quot;inclusionProof(bytes)&quot;, proofData);
attributes[2] = abi.encodeWithSignature(&quot;targetBlock(uint256)&quot;, blockNumber); // Optional

// Send message with address broadcasting
gateway.sendMessage(
    addressBroadcast, // broadcast to all addresses on Arbitrum One
    abi.encode(&quot;priceUpdate&quot;, asset, price),
    attributes
);

// Send message with chain type broadcasting  
gateway.sendMessage(
    chainTypeBroadcast, // broadcast to all EIP-155 chains
    abi.encode(&quot;governanceProposal&quot;, proposalId, votingPeriod),
    attributes
);

// Send message with universal broadcasting
gateway.sendMessage(
    universalBroadcast, // broadcast to all supported chains and addresses
    abi.encode(&quot;pause&quot;, reason),
    attributes
);
```

## Security Considerations

### Validation Requirements

Gateways must rigorously validate all proof data to prevent message forgery, including proof format, completeness, and cryptographic validity. Route addresses must correspond to legitimate proof infrastructure forming a valid, connected path between chains. Only finalized blocks or equivalent commitment points should be used for proof generation to prevent reorganization attacks.

Consumers of cryptographic proof messages should implement appropriate freshness checks, as proofs can verify messages at any historical block or commitment, potentially including very old messages. This is not required for gateways offering immutable message commitments.

### Route Security

The security of a multi-hop route is only as strong as the weakest proof in the verification path. When multiple route steps are used, the overall security level is determined by the step with the lowest cryptographic guarantees or the least secure consensus mechanism. Implementers should carefully evaluate each hop in their routes and consider the cumulative security implications when designing cross-chain verification paths.

### Broadcast Message Security

Since broadcast messages can be executed by any party, receivers should implement robust validation of message sources and contents. This includes verifying the sender&apos;s authority and the message&apos;s semantic validity.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 06 Jun 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7965</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7965</guid>
      </item>
    
      <item>
        <title>eth_sendRawTransactionSync Method</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7966-eth-sendrawtransactionsync-method/24640</comments>
        
        <description>## Abstract

This EIP proposes a new JSON-RPC method, `eth_sendRawTransactionSync`, which submits a signed raw transaction and waits synchronously for the transaction receipt or a configurable timeout before returning. This method addresses the user experience gap in high-frequency applications by offering stronger delivery guarantees than `eth_sendRawTransaction`. Additionally, when a transaction cannot be immediately executed due to a nonce gap, it returns the expected nonce as a hex string in the error response, eliminating the need for additional RPC calls to query account state.

## Motivation

Currently, Ethereum clients submit signed transactions asynchronously using `eth_sendRawTransaction`. Clients receive a transaction hash immediately but must poll repeatedly for the transaction receipt, which increases latency and complicates client-side logic.

This asynchronous approach is not efficient for high-frequency blockchains or Layer 2 solutions with fast block times and low latency, where rapid transaction throughput and quick confirmation feedback are critical. The need to separately poll for receipts results in increased network overhead, slower overall transaction confirmation feedback, and more complex client implementations.

Additionally, when transactions cannot be immediately executed (e.g., due to nonce gaps or insufficient funds), existing methods provide generic error messages that don&apos;t help developers understand or fix the issue. Developers must make additional RPC calls to query account state, creating unnecessary round-trips and delays.

![Sync vs Async Transaction Sending](/EIPs/assets/eip-7966/sync-vs-async.png)
_In a low-latency blockchain, transaction receipts are often available right after the transactions land in the block producer’s mempool. Requiring an additional RPC call introduces unnecessary latency._

`eth_sendRawTransactionSync` addresses these issues by combining transaction submission and receipt retrieval into a single RPC call. This helps:

- reduce total transaction submission and confirmation latency by approximately 50%;
- simplify client implementations by eliminating the need for separate polling loops;
- improve user experience by enabling more responsive dApps and wallets;
- align blockchain interactions closer to traditional Web2 request-response patterns;
- maintain backward compatibility and optionality, preserving existing RPC methods and semantics.

## Specification

### Method Name

`eth_sendRawTransactionSync`

### Parameters

| Position | Type   | Description                       | Required |
|----------|--------|-----------------------------------|----------|
| 1        | `DATA` | The signed transaction data       | Yes      |
| 2        | `INT`  | Maximum wait time in milliseconds | No       |

#### Parameter Validation Rules

- **Transaction Data**. MUST be a valid hex-encoded, RLP-encoded signed transaction (same as in `eth_sendRawTransaction`).
- **Timeout**. MUST be a positive integer not greater than the node-configured maximum timeout.

### Returns

- **On success**. Node implementations MUST return the transaction receipt object as defined by the `eth_getTransactionReceipt` method.
- **On timeout error**. Node implementations MUST return an error code `4` with a timeout message.
- **On unreadiness error**. Node implementations SHOULD return an error code `5` with an error message.
  - This happens when the processing node is not ready to accept a new transaction or the transaction is erroneous (DX improvement).
- **On standard error**. Node implementations MUST return a JSON-RPC error object consistent with existing RPC error formats.

### Error Codes and Response Structure

The following error codes are specific to `eth_sendRawTransactionSync`:

| Code | Error Type     | Description                                                          | Data Format              |
|------|----------------|----------------------------------------------------------------------|--------------------------|
| 4    | Timeout        | Transaction was added to mempool but not processed within timeout    | Transaction hash (hex)   |
| 5    | Unknown/Queued | Transaction is NOT added to mempool (not ready for execution)        | Transaction hash (hex)   |
| 6    | Nonce Gap      | Transaction is NOT added to mempool (nonce gap detected)             | Expected nonce (hex)     |

When an error occurs, the response includes:

- `code`: The error code indicating the error type
- `message`: A human-readable error message
- `data`: Error-specific data:
  - For error code `4` (Timeout): Contains the transaction hash as a hex string (e.g., `&quot;0x1234abcd...&quot;`)
  - For error code `5` (Unknown/Queued): Contains the transaction hash as a hex string (e.g., `&quot;0x1234abcd...&quot;`)
  - For error code `6` (Nonce Gap): Contains the expected nonce as a hex string (e.g., `&quot;0x5&quot;`)

### Node-Configured Timeouts

- The handler function of this RPC SHOULD incorporate a configurable timeout when waiting for receipts (RECOMMENDED: 2 seconds).
- Node implementations SHOULD provide a way to configure the timeout duration.
- Node operators MAY implement dynamic timeout adjustment based on real-time network conditions.

### Behavior

Upon receiving an `eth_sendRawTransactionSync` request, the handler function performs the following tasks.

- If timeout parameter is provided, the handler function MUST validate its validity.
  - If the timeout is invalid, the handler function MUST use the default node-configure timeout.
- The handler function MUST check if the transaction is ready for immediate execution BEFORE adding it to the mempool:
  - If the transaction has a nonce gap (transaction nonce is higher than the expected nonce), the handler function MUST NOT add the transaction to the mempool and MUST return error code `6` with the expected nonce as a hex string directly in the `data` field.
  - If the transaction is queued for any other reason (not ready for immediate execution), the handler function MUST NOT add the transaction to the mempool and MUST return error code `5`.
- If the transaction is ready for immediate execution, the handler function MUST submit the signed transaction to the mempool as per the existing `eth_sendRawTransaction` semantics.
- The handler function MUST wait for the transaction receipt until the timeout elapses.
- If the receipt is found within the specified timeout, the handler function MUST return it immediately.
- If the timeout expires without obtaining a receipt, the handler function MUST return an error code `4` with a timeout message and the transaction hash.
- If the transaction submission fails (e.g., due to invalid transaction data), the handler function MUST return an error (following the `eth_sendRawTransaction` definition) immediately.

### Example Request (No Timeout)

```json
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;method&quot;: &quot;eth_sendRawTransactionSync&quot;,
  &quot;params&quot;: [
    &quot;0xf86c808504a817c80082520894ab... (signed tx hex)&quot;
  ],
  &quot;id&quot;: 1
}
```

### Example Request (With Timeout)

```json
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;method&quot;: &quot;eth_sendRawTransactionSync&quot;,
  &quot;params&quot;: [
    &quot;0xf86c808504a817c80082520894ab... (signed tx hex)&quot;,
    5000
  ],
  &quot;id&quot;: 1
}
```

### Example Response (Success)

```json
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;result&quot;: {
    &quot;transactionHash&quot;: &quot;0x1234abcd...&quot;,
    &quot;blockHash&quot;: &quot;0xabcd1234...&quot;,
    &quot;blockNumber&quot;: &quot;0x10d4f&quot;,
    &quot;cumulativeGasUsed&quot;: &quot;0x5208&quot;,
    &quot;gasUsed&quot;: &quot;0x5208&quot;,
    &quot;contractAddress&quot;: null,
    &quot;logs&quot;: [],
    &quot;status&quot;: &quot;0x1&quot;
  }
}
```

### Example Response (Timeout - Error Code 4)

```json
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;error&quot;: {
    &quot;code&quot;: 4,
    &quot;message&quot;: &quot;The transaction was added to the mempool but wasn&apos;t processed within the designated timeout interval.&quot;,
    &quot;data&quot;: &quot;0x1234abcd...&quot;
  }
}
```

Note: The `data` field contains the transaction hash as a hex string.

### Example Response (Nonce Gap - Error Code 6)

```json
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;error&quot;: {
    &quot;code&quot;: 6,
    &quot;message&quot;: &quot;The transaction was rejected due to a nonce gap. Please resubmit with the next on-chain nonce.&quot;,
    &quot;data&quot;: &quot;0x5&quot;
  }
}
```

Note: The `data` field contains the expected nonce as a hex string. No transaction hash is returned because the transaction was never added to the mempool.

### Example Response (Rejected Transaction - Error Code 5)

```json
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;error&quot;: {
    &quot;code&quot;: 5,
    &quot;message&quot;: &quot;The transaction was rejected for an unknown reason.&quot;,
    &quot;data&quot;: &quot;0x1234abcd...&quot;
  }
}
```

### Example Response (Standard Error)

```json
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;error&quot;: {
    &quot;code&quot;: -32000,
    &quot;message&quot;: &quot;Invalid transaction&quot;
  }
}
```

## Rationale

### Why Not Extend Existing RPC?

Modifying `eth_sendRawTransaction` to support this behavior would risk compatibility issues and ambiguity. A separate method makes the semantics explicit and opt-in.

### Node-Configured Timeouts

Node implementations SHOULD allow configuration of the timeout period, defaulting to 2 seconds (depending on the implementation). This balances responsiveness and propagation guarantees without creating excessive overhead in node clients.

### User-Configured Timeouts

The optional timeout parameter allows clients to specify their preferred maximum wait time for transaction processing.

- Applications can adjust timeouts based on their specific latency requirements.
- The optional timeout prevents the RPC call from blocking indefinitely.

### Optionality

This method is optional and does not replace or change existing asynchronous transaction submission methods. Nodes that do not implement this method will continue to operate normally using the standard asynchronous RPC methods.

This RPC method is particularly suitable for EVM-compatible blockchains or L2 solutions with fast block times and low network latency, where synchronous receipt retrieval can significantly improve responsiveness. On high-latency or slower blockchains (e.g., Ethereum mainnet pre-sharding), the synchronous wait may cause longer RPC call durations or timeouts, making the method less practical.

### Improved UX

The synchronous receipt retrieval reduces the complexity of client applications by eliminating the need for separate polling logic.

### Returned Nonces in Error Code `6`

When a transaction is rejected due to a nonce gap, error code `6` returns the expected nonce as a hex string in the `data` field. This design provides several benefits:

- **Immediate Nonce Recovery**: Applications receive the correct nonce directly in the error response, eliminating the need for a separate `eth_getTransactionCount` call.
- **Reduced Latency**: By avoiding additional RPC round-trips to query account state, applications can immediately construct and resubmit the transaction with the correct nonce.

## Backwards Compatibility

This EIP introduces a new RPC method and does not modify or deprecate any existing methods. Nodes that do not implement this method will continue operating normally. Existing applications using `eth_sendRawTransaction` are unaffected. Node implementations that do not support the method will simply return `method not found`.

## Reference Implementation

A minimal reference implementation can be realized by wrapping existing `eth_sendRawTransaction` submission with logic that waits for the corresponding transaction receipt until a timeout elapses. Implementations MAY either rely on event-driven receipt-availability notifications or poll `eth_getTransactionReceipt` at short intervals until a receipt is found or a timeout occurs. Polling intervals or notification strategies and timeout values can be tuned by node implementations to optimize performance.

For example, in `reth`, we can implement the handler for `eth_sendRawTransactionSync` as follows.

```rust
async fn send_raw_transaction_sync(
    &amp;self,
    tx: Bytes,
    user_timeout_ms: Option&lt;u64&gt;,
) -&gt; RpcResult&lt;OpTransactionReceipt&gt; {
    const MAX_TIMEOUT_MS: u64 = 2_000;

    const ERROR_CODE_TIMEOUT: i32 = 4;
    const ERROR_CODE_UNKNOWN: i32 = 5;
    const ERROR_CODE_NONCE_GAP: i32 = 6;

    const ERROR_MSG_TIMEOUT_RECEIPT: &amp;str = &quot;The transaction was added to the mempool but wasn&apos;t processed within the designated timeout interval.&quot;;
    const ERROR_MSG_UNKNOWN: &amp;str = &quot;The transaction was rejected for an unknown reason.&quot;;
    const ERROR_MSG_NONCE_GAP: &amp;str = &quot;The transaction was rejected due to a nonce gap. Please resubmit with the next on-chain nonce.&quot;;

    let start_time = Instant::now();
    let timeout = Duration::from_millis(
        user_timeout_ms.map_or(MAX_TIMEOUT_MS, |ms| ms.min(MAX_TIMEOUT_MS)),
    );

    let pool_transaction = OpPooledTransaction::from_pooled(recover_raw_transaction(&amp;tx)?);
    let sender = pool_transaction.sender();

    let outcome = self
        .pool
        .add_transaction(TransactionOrigin::Local, pool_transaction)
        .await
        .map_err(OpEthApiError::from_eth_err)?;

    // If transaction is queued (not ready for immediate execution), remove it and return error
    if let AddedTransactionState::Queued(reason) = outcome.state {
        self.pool.remove_transaction(outcome.hash);

        match reason {
            QueuedReason::NonceGap =&gt; {
                let expected_nonce = self
                    .pending_state
                    .basic_account(&amp;sender)
                    .ok()
                    .flatten()
                    .map(|acc| format!(&quot;0x{:x}&quot;, acc.nonce));

                return Err(ErrorObject::owned(
                    ERROR_CODE_NONCE_GAP,
                    ERROR_MSG_NONCE_GAP,
                    expected_nonce,
                ));
            }
            _ =&gt; {
                return Err(ErrorObject::owned(
                    ERROR_CODE_UNKNOWN,
                    ERROR_MSG_UNKNOWN,
                    Some(hash),
                ));
            }
        }
    }

    let hash = outcome.hash;
    match self
        .pending_state
        .get_receipt(hash, timeout.saturating_sub(start_time.elapsed()))
        .await
    {
        Some(receipt) =&gt; Ok(receipt),
        None =&gt; Err(ErrorObject::owned(
            ERROR_CODE_TIMEOUT,
            ERROR_MSG_TIMEOUT_RECEIPT,
            Some(hash),
        )),
    }
}
```

Other implementations such as `go-ethereum` can utilize a channel to signify receipt availability instead of polling.

## Security Considerations

- This method does not introduce new security risks beyond those inherent in transaction submission.
- The node-configured timeout prevents indefinite blocking of RPC calls, protecting nodes from hanging requests.
- Node implementations should handle timeout responses gracefully and continue monitoring transaction status as needed.
- Nodes must ensure that the implementation does not degrade performance or cause denial-of-service.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 11 Jun 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7966</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7966</guid>
      </item>
    
      <item>
        <title>Owner-Authorized Token Transfer Protocol</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7951-owner-authorized-token-transfer-protocol/24526</comments>
        
        <description>## Abstract

This proposal introduces an innovative token transfer processing model designed for third parties, enabling seamless use of Ethereum-based tokens (e.g., [ERC-20](/EIPs/EIPS/eip-20)) by non-crypto-native actors. The concept allows a third-party payment processor to initiate token transfers on behalf of another party and to cover the associated transaction (gas) fees. The main party (user) always remains the explicit owner of the tokens, which are securely held and referenced under their ownership in the smart contract.

The transfer process is two-phased:

1. **Initiation:** The payment processor proposes a token transfer via the smart contract. This proposal is emitted as an on-chain event, including all relevant transfer details and a unique hash of the transaction (“proposal hash”).
2. **Approval:** The authorized party (owner) reviews the proposal off-chain and, if in agreement, signs the proposal hash with their private key. This signature is sent to the payment processor, who then submits it to the smart contract. There, the contract verifies the signature and, upon approval, carries out the token transfer in the owner’s name.

To increase security and usability, each proposal includes an explicit expiration time. If the signature is not submitted and verified within the defined validity period, the proposal becomes void and the transfer cannot be executed.

To further enhance user safety, the owner is provided with a function that allows transferring all token balances directly to their own address in case the payment processor becomes unresponsive, acts improperly, or if external conditions such as transaction costs change unfavorably.

This model empowers entities to integrate blockchain-based payments into their workflows without directly holding or managing cryptocurrencies. All token movements require explicit owner approval, ensuring security and retaining full user control. The payment processor is compensated “off-chain” (e.g., in fiat currency) and is responsible for gas costs.

By removing the technical and operational burdens of crypto management from the end user, this approach facilitates broader adoption of tokenized business cases and simplifies enterprise integration.

## Motivation

Adoption of blockchain-based payments and tokenized assets in enterprise and conventional business contexts is still often hindered by the need for end-users or business partners to directly manage cryptocurrencies, wallets, and on-chain transactions. For many organizations, the technical, regulatory, and operational burdens associated with self-custody and on-chain fee management present significant entry barriers.

This proposal aims to lower these barriers by introducing a model in which a trusted third-party payment processor can manage all blockchain transactions on behalf of a token owner, including paying transaction fees. The owner maintains full control and explicit on-chain ownership of the assets, and must approve all outgoing transfers cryptographically. Payment for the processor&apos;s services (including gas reimbursement) can take place off-chain and in fiat currency, which aligns with existing financial workflows and compliance expectations.

With an explicit fallback function, owners are further protected, ensuring they can always reclaim direct control over their assets if the processor becomes unresponsive or external conditions change.

In summary, this standard facilitates broader and more secure adoption of token-based processes by offloading complexity from end-users, while preserving security, transparency, and user sovereignty.

## Specification

### Methods

#### Smart Contract that holds the assets (`ITokenStorage.sol`)

##### Transfer proposal: `proposeTransaction`

```solidity
function proposeTransaction(address tokenAddress, uint256 amountToSent, address destinationAddress) external;
```

Called from the paymentProcessor/transactionProvider of the storage to initiate a token transfer. Emits a `TransactionProposed` event.
The parameter `tokenAddress` is the address of the token which should be transferred.
The parameter `amountToSent` is the amount which should be transferred to the desired destination address.
The parameter `destinationAddress` defines the receiver of the defined token.
The proposal is stored in the contract and a unique (uint256) hash is generated for it, which is used for the approval process.

##### Transfer completion: `completeTransaction`

```solidity
function completeTransaction(uint256 hash, bytes memory signature) external;
```
Called from the paymentProcessor/transactionProvider of the storage to perform a token transfer. Emits a `TransactionCompleted` event.
The parameter `hash` is unique identifier of the transaction.
The parameter `signature` is a signed message which only includes the hash. This message is signed by the credentials of the owner, which are used to verify that the owner has approved the transaction.
This function includes a verification step to ensure that the signature is valid and corresponds to the owner of the tokens.
If the signature is valid, the contract executes the transfer of tokens from the smart contract to the `destinationAddress` specified in the proposal.

##### Fallback function: `sendFundsToOwner`

```solidity
function sendFundsToOwner(address tokenAddress) external;
```
This function allows the owner to transfer all tokens held in the contract back to his/her own address. 
This is a safety measure to ensure that the owner can reclaim their assets if the payment processor becomes unresponsive or if external conditions change unfavorably.
Emits a `FallbackScenarioExecuted` event.
The parameter `tokenAddress` is the address of the token which should be transferred to the owner.
In case this method is called, the contract will transfer all tokens of the given type to the owner address.

#### Verification of the signature: &apos;verifySignature&apos;

```solidity
function verifySignature(
    address _signer,
    address tokenAddress,
    uint256 amountToSent,
    address destinationAddress,
    bytes memory signature
) public pure returns (bool);
```
This function is used to verify the signature of the owner. It checks if the signature corresponds to the provided parameters and the owner&apos;s address.
The parameter `_signer` is the address of the owner who signed the proposal.
The parameter `tokenAddress` is the address of the token which should be transferred.
The parameter `amountToSent` is the amount which should be transferred to the desired destination address.
The parameter `destinationAddress` defines the receiver of the defined token.
The parameter `signature` is the signed message which only includes the hash of the proposal.

This function can be called by the owner to verify the signature before forwarding it to the paymentProcessor / transactionProvider.
Also this function should be called within the `completeTransaction` function to ensure that the signature is valid before executing the transfer.

##### Summary
The interface `ITokenStorage.sol`:

```solidity
interface ITokenStorage {
    event TransactionProposed(uint256 hash);
    event TransactionCompleted(uint256 hash);
    event FallbackScenarioExecuted(address tokenAddress);

    function proposeTransaction(address tokenAddress, uint256 amountToSent, address destinationAddress) external;
    function completeTransaction(uint256 hash, bytes memory signature) external;
    function sendFundsToOwner(address tokenAddress) external;
}
```

## Rationale

tbd &lt;!-- TODO --&gt;

## Backwards Compatibility

No backward compatibility issues found.

&lt;!-- TODO: Reference implementation --&gt;
&lt;!-- TODO: Test cases --&gt;

## Security Considerations

Needs discussion. &lt;!-- TODO --&gt;

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 11 Jun 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7968</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7968</guid>
      </item>
    
      <item>
        <title>DomainKeys Identified Mail (DKIM) Registry</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/new-erc-dkim-registry-interface/24530</comments>
        
        <description>## Abstract

This EIP proposes a standard interface for registering and validating DomainKeys Identified Mail (DKIM) public key hashes on the Ethereum blockchain. The interface allows domain owners to register their DKIM public key hashes and enables third parties to verify the validity of these hashes.

The registry operates by storing hashes of both domain names and DKIM public keys, creating a mapping that enables on-chain verification of DKIM signatures. Domain owners register their DKIM public key hashes by extracting the public key from their DNS TXT records (as specified in [RFC 6376](https://www.rfc-editor.org/rfc/rfc6376)), computing the hash, and submitting it to the registry. DKIM clients can then query the registry to verify that a given public key hash is authorized for a specific domain, enabling trustless email ownership verification for applications such as account abstraction and social recovery mechanisms.

## Motivation

With the growing adoption of Account Abstraction [ERC-4337] and the emergence of ZK Email Technology, there is a need for a standardized way to verify email ownership on-chain. This EIP provides a crucial building block for these technologies by enabling the verification of DKIM signatures through on-chain registries.

[ERC-4337]: /EIPs/EIPS/eip-4337

This standard enables several important use cases:

1. **Account Abstraction**: When combined with zkEmail, this registry enables email-based account abstraction. Users can prove ownership of their email address through DKIM signatures, allowing them to:
   - Create and manage smart contract wallets
   - Sign transactions using their email credentials
   - Implement social recovery mechanisms
2. **Account Recovery**: The registry facilitates secure account recovery mechanisms:
   - Users can recover their wallet access by on-chain proving email ownership
   - The process is trustless and secure due to the cryptographic nature of DKIM

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### Interface

```solidity
pragma solidity ^0.8.25;
/// @title ERC-XXX DKIM Registry Interface
/// @dev See https://eips.ethereum.org/EIPS/eip-xxx
/// Note: the ERC-165 identifier for this interface is 0xdee3d600.
interface IDKIMRegistry {
    event KeyHashRegistered(bytes32 domainHash, bytes32 keyHash);
    event KeyHashRevoked(bytes32 domainHash);
    function isKeyHashValid(
        bytes32 domainHash,
        bytes32 keyHash
    ) external view returns (bool);
}
```

### Domain Hash

The `domainHash` parameter MUST be the hash of the lowercase domain name or subdomain name. For example:

- For the domain &quot;example.com&quot; using keccak256:

```solidity
domainHash = keccak256(bytes(&quot;example.com&quot;))
```

- For the subdomain &quot;mail.example.com&quot; using keccak256:

```solidity
domainHash = keccak256(bytes(&quot;mail.example.com&quot;))
```

The registry MUST treat each domain and subdomain as a distinct entity. This means that:

1. A key hash registered for &quot;example.com&quot; does not automatically apply to its subdomains
2. Each subdomain can have its own independent DKIM key hash registration
3. The full domain name (including subdomain if present) must be hashed as a single string

### Key Hash

The `keyHash` parameter MUST be a cryptographic hash of the DKIM public key. The public key should be in the standard DKIM format as specified in [RFC 6376](https://www.rfc-editor.org/rfc/rfc6376).

Implementations MAY choose any cryptographically secure hash function for computing the key hash. Common choices include keccak256, Poseidon (for zk-friendly applications) or other hash functions.

### DKIM Public Key Specification

The DKIM public key MUST follow the format specified in RFC 6376. Here are the key requirements:

1. **Key Format**:
   - The public key MUST be in the format specified in the DKIM DNS record (p=PUBLIC_KEY)
   - The key MUST be base64 encoded
   - The key MUST NOT include the PEM headers or any other formatting
   - The key MUST be the raw public key data as specified in the DKIM DNS record
2. **Key Requirements**:
   - The key MUST be a valid RSA public key
   - The key MUST be in the format as published in the domain&apos;s DNS TXT record
   - The key MUST be the exact value from the p= parameter in the DKIM DNS record
   - The key MUST NOT include any whitespace or line breaks
3. **Key Registration Process**:
   1. Obtain the DKIM public key from the domain&apos;s DNS TXT record
   2. Extract the value from the p= parameter
   3. Calculate the hash of the raw public key using the implementation&apos;s chosen hash function
   4. Register the hash in the DKIM registry
4. **Key Validation**:
   - The registry MUST verify that the provided key hash corresponds to a valid DKIM public key
   - The key MUST be in the correct format as specified in RFC 6376
   - The key MUST be the exact value as published in the domain&apos;s DNS record
5. **Example with keccak256**:

   Given the following DKIM DNS record from RFC 6376:

   ````
   $ORIGIN _domainkey.example.org.
   brisbane IN  TXT  (&quot;v=DKIM1; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQ&quot;
                   &quot;KBgQDwIRP/UC3SBsEmGqZ9ZJW3/DkMoGeLnQg1fWn7/zYt&quot;
                   &quot;IxN2SnFCjxOCKG9v3b4jYfcTNh5ijSsq631uBItLa7od+v&quot;
                   &quot;/RtdC2UzJ1lWT947qR+Rcac2gbto/NMqJ0fzfVjH4OuKhi&quot;
                   &quot;tdY9tf6mcwGjaNBcWToIMmPSPDdQPNUYckcQ2QIDAQAB&quot;)
                   ```
   ````

   The process to register this key would be:

   1. Extract the public key value from the p= parameter:

   ```
   MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDwIRP/UC3SBsEmGqZ9ZJW3/DkMoGeLnQg1fWn7/zYtIxN2SnFCjxOCKG9v3b4jYfcTNh5ijSsq631uBItLa7od+v/RtdC2UzJ1lWT947qR+Rcac2gbto/NMqJ0fzfVjH4OuKhitdY9tf6mcwGjaNBcWToIMmPSPDdQPNUYckcQ2QIDAQAB
   ```

6. Calculate the keccak256 hash of the public key:

   ```solidity
   bytes32 keyHash = keccak256(bytes(&quot;MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDwIRP/UC3SBsEmGqZ9ZJW3/DkMoGeLnQg1fWn7/zYtIxN2SnFCjxOCKG9v3b4jYfcTNh5ijSsq631uBItLa7od+v/RtdC2UzJ1lWT947qR+Rcac2gbto/NMqJ0fzfVjH4OuKhitdY9tf6mcwGjaNBcWToIMmPSPDdQPNUYckcQ2QIDAQAB&quot;));
   ```

   3. Calculate the domain hash:

   ```solidity
   bytes32 domainHash = keccak256(bytes(&quot;example.org&quot;));
   ```

   4. Register the key hash in the registry:

   ```solidity
   registry.setKeyHash(domainHash, keyHash);
   ```

### Events

#### KeyHashRegistered

This event MUST be emitted when a new DKIM public key hash is registered for a domain.

```solidity
event KeyHashRegistered(bytes32 domainHash, bytes32 keyHash)
```

#### KeyHashRevoked

This event MUST be emitted when a DKIM public key hash is revoked for a domain.

```solidity
event KeyHashRevoked(bytes32 domainHash)
```

### Functions

#### isKeyHashValid

This function MUST return `true` if the provided key hash is valid for the given domain hash, and `false` otherwise.

```solidity
function isKeyHashValid(
    bytes32 domainHash,
    bytes32 keyHash
) external view returns (bool)
```

## Rationale

The interface is designed to be simple and focused on the core functionality of DKIM public key hash registration and validation. The use of keccak256 hashing for both domain names and public keys ensures consistent and secure handling of the data.

The events allow for efficient tracking of key registrations and revocations, which is important for maintaining the integrity of the registry.

## Backwards Compatibility

This EIP introduces a new interface and does not affect existing contracts or standards.

## Reference Implementation

```solidity
pragma solidity ^0.8.0;
import &quot;@openzeppelin/contracts/access/Ownable.sol&quot;;
import &quot;./interfaces/IDKIMRegistry.sol&quot;;
contract DKIMRegistry is IDKIMRegistry, Ownable {
    constructor(address _owner) Ownable(_owner) { }
    // Mapping from hashed domain name to DKIM public key hash to enabled
    mapping(bytes32 =&gt; mapping(bytes32 =&gt; bool)) private _keyHashes;
    /**
     * @notice Checks if a DKIM key hash is valid for a given domain
     * @param domainHash The hash of the domain name
     * @param keyHash The hash of the DKIM public key
     * @return bool True if the key hash is valid for the domain, false otherwise
     */
    function isKeyHashValid(
        bytes32 domainHash,
        bytes32 keyHash
    ) public view returns (bool) {
        return _keyHashes[domainHash][keyHash];
    }
    /**
     * @notice Sets a DKIM key hash for a domain
     * @param domainHash The hash of the domain name
     * @param keyHash The hash of the DKIM public key to register
     * @dev Only callable by the contract owner
     * @dev Cannot set zero hash as a valid key hash
     */
    function setKeyHash(
        bytes32 domainHash,
        bytes32 keyHash
    ) public onlyOwner {
        require(keyHash != bytes32(0), &quot;cannot set zero hash&quot;);
        _keyHashes[domainHash][keyHash] = true;
        emit KeyHashRegistered(domainHash, keyHash);
    }
    /**
     * @notice Sets multiple DKIM key hashes for a domain in a single transaction
     * @param domainHash The hash of the domain name
     * @param keyHashes Array of DKIM public key hashes to register
     * @dev Only callable by the contract owner
     * @dev Array must not be empty
     * @dev Each key hash must not be zero
     */
    function setKeyHashes(
        bytes32 domainHash,
        bytes32[] memory keyHashes
    ) public onlyOwner {
        require(keyHashes.length &gt; 0, &quot;empty array&quot;);
        for (uint256 i = 0; i &lt; keyHashes.length; i++) {
            setKeyHash(domainHash, keyHashes[i]);
        }
    }
    /**
     * @notice Revokes a DKIM key hash for a domain
     * @param domainHash The hash of the domain name
     * @param keyHash The hash of the DKIM public key to revoke
     * @dev Only callable by the contract owner
     * @dev Sets the key hash mapping to false, effectively revoking it
     */
    function revokeKeyHash(bytes32 domainHash, bytes32 keyHash) public onlyOwner {
        delete _keyHashes[domainHash][keyHash];
        emit KeyHashRevoked(domainHash);
    }
}
```

## Security Considerations

1. Domain owners must ensure they have control over their private keys and domain names.
2. The registry implementation should include proper access control mechanisms to prevent unauthorized registrations.
3. The registry should implement a mechanism to handle key rotation and revocation.
4. Implementations should consider rate limiting to prevent spam registrations.
5. Registries should select the `domainHash` and `keyHash` algorithms carefully. Upgrading the hash function must be thoughtfully planned.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 11 Jun 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7969</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7969</guid>
      </item>
    
      <item>
        <title>Hard Limits for Transient Storage</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/add-eip-hard-limit-and-cost-reduction-for-transient-storage-allocation/24542</comments>
        
        <description>## Abstract

This EIP proposes to reduce the gas costs for transient storage operations (`TLOAD` and `TSTORE`) by implementing constant pricing. To prevent denial-of-service attacks through excessive memory allocation, a transaction-global limit on transient storage slots is introduced. This approach provides lower costs for common use cases while maintaining security against resource exhaustion attacks.

## Motivation

[EIP-1153](/EIPs/EIPS/eip-1153) introduced transient storage with gas costs equivalent to warm storage operations (100 gas). The current pricing model presents several limitations:

1. Reentrancy Protection Cost: At 100 gas per operation, implementing reentrancy locks by default remains expensive enough to discourage universal adoption at the language level, leaving contracts vulnerable to one of the most common attack vectors.
2. Underutilization: The high cost is still punishing to developers who wish to use transient storage for other legitimate use cases such as temporary approvals, callback metadata, and cross-frame communication within transactions.
3. Pricing Inconsistency: Transient storage fundamentally requires fewer resources than persistent storage (no disk I/O, no state root updates), yet is priced identically to warm storage operations.

This EIP addresses these issues by implementing constant, lower pricing for transient storage operations while introducing a transaction-global limit to prevent denial-of-service attacks. It also makes the cost of warm storage cheaper. This provides lower costs and enables broader adoption of transient storage, while also providing hard resource limits for clients.

## Specification

### Parameters

This EIP introduces the following parameters:

| Constant | Value | Description |
| :--- | :--- | :--- |
| `GAS_TLOAD` | 5 | Gas cost of `TLOAD` |
| `GAS_TSTORE` | 12 | Gas cost of `TSTORE` |
| `MAX_TRANSIENT_SLOTS` | 131072 | The maximum number of transient slots allowed in a single transaction |
| `GAS_TSTORE_ALLOCATE` | 24 | Cost of additional allocated slots |

### Gas Cost Changes

1. The gas cost for `TLOAD` (opcode `0x5c`) is reduced from `GAS_WARM_ACCESS` (100) to `GAS_TLOAD`.
2. The base gas cost for `TSTORE` (opcode `0x5d`) is reduced from `GAS_WARM_ACCESS` (100) to `GAS_TSTORE`.

### Transaction-Global Transient Storage Limit

A transaction-global counter tracks the number of unique transient storage slots written across all contracts during transaction execution:

1. At the beginning of each transaction, initialize a counter `transient_slots_used` to 0.
2. When `TSTORE` is executed:
   - If the slot has not been written to during this transaction (across any contract), increment `transient_slots_used`.
   - If `transient_slots_used` exceeds `MAX_TRANSIENT_SLOTS`, the transaction MUST exceptionally halt.
3. The counter persists across all message calls in the transaction.
4. The counter is reset to 0 at the end of the transaction.

### Implementation Note

Implementations MUST track transient storage allocated across all contracts. A slot is considered unique based on the tuple `(contract_address, storage_key)`. Writing to the same slot multiple times within a transaction does not generally increment the counter after the first write (unless the slot gets deallocated with a revert).

## Rationale

### Constant Pricing with Hard Limit

This EIP implements constant pricing with a hard limit for several reasons:

1. A hard limit provides guarantees on the total resource consumption which are easier to reason about for clients, rather than needing to perform a calculation as a function of current gas limits to find out what total memory consumption could be.
2. Common use cases (e.g., reentrancy locks using 1-2 slots) are not penalized for worst case resource usage (like in DOS attacks).
3. Clients can safely pre-reserve all memory which could be used by transient storage up-front at the beginning of a transaction.

### Gas Cost Selection

- `GAS_TLOAD` (5 gas): Transient storage reads require only memory access without disk I/O.
- `GAS_TSTORE` (12 gas): Transient storage writes require memory allocation and journaling for revert support.
- `GAS_TSTORE_ALLOCATE` (24 gas): Writes to fresh slots require memory allocation, which is more expensive than writing to an existing slot.

`TSTORE` currently has a fixed cost. However, writing to fresh slots requires memory allocation, which is more expensive than writing to an existing slot. Therefore, we may consider introducing charging more for the first slot allocation through the parameter `GAS_TSTORE_ALLOCATE`. However, we would also need to introduce a mechanism to check for the first slot allocation versus subsequent allocations.

#### Benchmarking

This proposal does not yet have finalized numbers. To achieve this, we require benchmarks on the transient memory operations, which are currently in development. Once we collect that data, we will set the final numbers. We will also use this to understand whether the difference in performance justifies pricing new slot allocations differently.

We should note that warm storage loads from cache are expected to have similar performance characteristics to transient storage reads. Therefore, the final parameters should be consistent with [EIP-8038](/EIPs/EIPS/eip-8038).

&lt;– TODO –&gt;

### Hard Limit Selection

`MAX_TRANSIENT_SLOTS` of 131072 allows:

- Sufficient slots for typical user applications
- Memory usage bounded to approximately 8 MB per transaction (131072 slots * 64 bytes), which prevents OOM-based denial-of-service attacks

### Design Alternatives Considered

1. Per-Contract Limits: Increased complexity in reasoning about resource consumption based on the shape of the call stack.
2. Superlinear Pricing: Adds complexity, and still punishes &quot;common&quot; (non-DOS) use cases.
3. No Limit: May allow memory-based DOS attack if transaction-level gas limits change, or if pricing changes in the future.

The benefit of a hard limit is that the resource consumption is bounded predictably even in the presence of other parameter changes in the protocol.

## Backwards Compatibility

No known issues, besides the gas cost of existing operations being cheaper.

## Test Cases

TBD

## Reference Implementation

This reference implementation includes the mechanism to price `TSTORE` depending on whether the slot was previously allocated.

```python
# Pseudo-code for transaction execution with global transient storage limit

GAS_TLOAD = 5
GAS_TSTORE = 12
GAS_TSTORE_ALLOCATE = 24
MAX_TRANSIENT_SLOTS = 131072

class TransactionContext:
    def __init__(self):
        self.transient_storage = {}  # (address, key) -&gt; value
        self.unique_slots = set()    # set of (address, key) tuples
        self.transient_slots_used = 0
    
    def tload(self, address: Address, key: Bytes32) -&gt; Bytes32:
        # Charge gas
        self.charge_gas(GAS_TLOAD)
        
        # Return value or zero
        return self.transient_storage.get((address, key), Bytes32(0))

    def tstore(self, address: Address, key: Bytes32, value: Bytes32):
        # Charge gas
        self.charge_gas(GAS_TSTORE)

        # Check if this is a new unique slot
        slot_id = (address, key)
        if slot_id not in self.unique_slots:
            self.charge_gas(GAS_TSTORE_ALLOCATE)

            self.unique_slots.add(slot_id)

            # Check limit
            if len(self.unique_slots) &gt; MAX_TRANSIENT_SLOTS:
                raise ExceptionalHalt(&quot;Transient storage limit exceeded&quot;)
        
        # Store value
        self.transient_storage[slot_id] = value
```

## Security Considerations

With `MAX_TRANSIENT_SLOTS` = 131072, maximum memory allocation is bounded to 8 MB per transaction (131072 * 64 bytes). Compared to limits under current pricing (100 gas), a 60M gas transaction can allocate up to 600,000 slots (38.4 MB). This EIP reduces the maximum allocated amount by 79%.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 12 Jun 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7971</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7971</guid>
      </item>
    
      <item>
        <title>Warm Account Write Metering</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7973-warm-account-write-metering/25907</comments>
        
        <description>## Abstract

This EIP introduces warm metering for account writes. Namely, if one of the account fields (`nonce`, `value`, `codehash`) is changed more than once in a transaction, the later writes are cheaper, since the state root update only happens once.

## Motivation

Updating the state root is one of the most expensive parts of block construction. Currently, multiple writes to storage are subject to a net gas metering, which reduces the cost of a storage write after the first write. However, updates to the account are subject to the same cost every time.

This means that, for example, making multiple WETH transfers to an account in a single transaction gets successfully cheaper as the cold access cost is amortized over the remaining accesses. At the same time, the same discount does not occur when making multiple native ETH transfers. This discourages people from using native ETH transfers, and unfairly penalizes potential future opcodes that involve value transfer, like `PAY` and `GAS2ETH`.

This EIP brings the gas cost of the account update more in line with the actual execution cost. Multiple writes within a transaction can be batched, meaning that, after the first write, the cost of updating the state root does not need to be charged again.

## Specification

The parameters `GAS_CALL_VALUE` and `GAS_STORAGE_UPDATE` are removed, and the following parameters are introduced:

| **Parameter** | **Value** | **Description** |
|:---:|:---:|:---:|
| `GAS_COLD_STORAGE_WRITE` | TBD | Cost of a single update to the storage trie |
| `GAS_COLD_ACCOUNT_WRITE` | TBD | Cost of a single update to the account trie |
| `GAS_WARM_WRITE` | TBD | Cost of a warm update to a trie (i.e. does not trigger a new state root calculation) |

&lt;-- TODO --&gt;

On the account-updating opcodes `CREATE`, `CREATE2`, and `*CALL`, instead of charging `GAS_CALL_VALUE`:

- `GAS_COLD_ACCOUNT_WRITE` is charged if the account fields **are equal** to the transaction start values (i.e., they have not yet been updated by the transaction), or
- `GAS_WARM_WRITE` is charged if the account fields **are not equal** to the transaction start values (i.e., they have already been updated before by the transaction).

`SSTORE` is also subjected to warm account metering. That is, this EIP splits the cost of `SSTORE` into two components, the cost to update the account tuple, and the cost to update the state trie. Note that if the state trie has already been updated once in a transaction, the account tuple is already dirty, and so we can amortize the cost of updating the account tuple again. Thus, the gas cost of `SSTORE` and its refund logic is updated to:

```python
# get original_value and current_value
state = evm.message.block_env.state
original_value = get_storage_original(
    state, evm.message.current_target, key
)
current_value = get_storage(state, evm.message.current_target, key)

# get account info
original_account = get_account_original(evm.message.block_env.state, evm.message.current_target)
account = get_account(evm.message.block_env.state, evm.message.current_target)

# initialize gas cost
gas_cost = Uint(0)

# Charge account write cost
if account != original_account:
    gas_cost += GAS_WARM_WRITE
else:
    gas_cost += GAS_COLD_ACCOUNT_WRITE

# Charge slot-specific costs
if (evm.message.current_target, key) not in evm.accessed_storage_keys:
    evm.accessed_storage_keys.add((evm.message.current_target, key))
    gas_cost += GAS_COLD_SLOAD

if original_value == current_value and current_value != new_value:
    if original_value == 0:
        gas_cost += GAS_STORAGE_SET
    else:
        gas_cost += GAS_COLD_STORAGE_WRITE - GAS_COLD_SLOAD
else:
    gas_cost += GAS_WARM_ACCESS
    
# Refund Counter Calculation
if current_value != new_value:
    if original_value != 0 and current_value != 0 and new_value == 0:
        # Storage is cleared for the first time in the transaction
        evm.refund_counter += int(GAS_STORAGE_CLEAR_REFUND)

    if original_value != 0 and current_value == 0:
        # Gas refund issued earlier to be reversed
        evm.refund_counter -= int(GAS_STORAGE_CLEAR_REFUND)

    if original_value == new_value:
        # Storage slot being restored to its original value
        if original_value == 0:
            # Slot was originally empty and was SET earlier
            evm.refund_counter += int(GAS_STORAGE_SET - GAS_WARM_ACCESS)
        else:
            # Slot was originally non-empty and was UPDATED earlier
            evm.refund_counter += int(
                GAS_COLD_STORAGE_WRITE - GAS_COLD_SLOAD - GAS_WARM_ACCESS
                )
        # Refund account writing cost (only if cold)
        if account == original_account:
            evm.refund_counter += GAS_COLD_ACCOUNT_WRITE

```

For compatibility with [EIP-7928](/EIPs/EIPS/eip-7928) and parallel execution, if the accessed account shows updates in the Block-Level Access List (BAL) in a transaction indexed before the current transaction, then the values to compare against are taken from this entry instead of the account trie.

## Rationale

An account is represented within Ethereum as a tuple `(nonce, balance, storage_root, codehash)`. The account is a leaf of a Merkle Patricia Tree (MPT), while the `storage_root` is itself the root of the account&apos;s MPT key-value store. An update to the account&apos;s storage requires updating two MPTs (the account&apos;s `storage_root`, as well as the global state root). Meanwhile, updating the other fields in an account requires updating only one MPT.

This proposal clarifies the cost of updating state by introducing the `*_WRITE` parameters. It also separates the cost of a storage state root update (`GAS_COLD_STORAGE_ACCESS`) and the cost of an account state root update (`GAS_COLD_ACCOUNT_ACCESS`). This parametrization allows us to apply warm costing to account updates. When the same account is updated multiple times in the same transaction, the state root calculation can be batched and all updates can be done in the same calculation. Therefore, the cost of making more updates to an already updated account is not the same as the first update.

### Benchmarking

This proposal does not yet have finalized numbers. To achieve this, we require stateful benchmarks, which are currently in development. Once we collect that data, we will set the final numbers.

&lt;– TODO –&gt;

### Net metering

Net metering (i.e., issuing a refund if the final value at the end of the transaction is equal to the transaction start, à la `SSTORE`) was considered, but not added for simplicity.

## Backwards Compatibility

This is a backwards-incompatible gas repricing that requires a scheduled network upgrade.

Wallet developers and node operators MUST update gas estimation handling to accommodate the new account access cost rules. Specifically:

- Wallets: Wallets using `eth_estimateGas` MUST be updated to ensure that they correctly account for the updated gas parameters. Failure to do so could result in overestimating gas, leading to potential attacks vectors.
- Node Software: RPC methods such as `eth_estimateGas` MUST incorporate the updated formula for gas calculation with the new cost values.

Users can maintain their usual workflows without modification, as wallet and RPC updates will handle these changes.

## Security Considerations

Decreasing the cost of account access operations could introduce new attack vectors. More analysis is needed to understand the potential effects on various dApps and user behaviors.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 14 Jun 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7973</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7973</guid>
      </item>
    
      <item>
        <title>eth/70 - partial block receipt lists</title>
        <category>Standards Track/Networking</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7975-eth-70-partial-block-receipt-lists/24658</comments>
        
        <description>## Abstract

This EIP modifies the &apos;eth&apos; p2p protocol to allow requesting partial block receipt lists.

## Motivation

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.

## Specification

Modify the encoding for receipts in the `Receipts (0x10)` message as follows:

- (eth/69): `[request-id: P, [[receipt₁, receipt₂], ...]]`

- (eth/70): `[request-id: P, lastBlockIncomplete: {0,1}, [[receipt₁, receipt₂], ...]]`

If the `lastBlockIncomplete` flag is set to true (`1`), 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.

To support such partial queries, we also modify the `GetReceipts (0x0f)` message:

- (eth/69): `[request-id: P, [blockhash₁: B_32, blockhash₂: B_32, ...]]`

- (eth/70): `[request-id: P, firstBlockReceiptIndex: P, [blockhash₁: B_32, blockhash₂: B_32, ...]]`

For the first block in the list of requested block hashes, the server shall omit receipts
up to the `firstBlockReceiptIndex` from the response.

Downloading block receipts across multiple messages creates new attack surface. Partial
receipt lists cannot be verified against the block header, so in responses with
`lastBlockIncomplete = 1`, the last receipts list must be validated in a different way:

- Verify the total number of delivered receipts matches the count of transactions.
- Verify the size of each receipt against the gas limit of the corresponding transaction,
  i.e. reject if it is larger than gaslimit/8.
- Verify the total downloaded receipts size is no larger than allowed by the block gas limit.

&lt;!-- Needs exact formula --&gt;

## Rationale

Since [EIP-7825] 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.

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 `Receipts` message
could exceed 10MiB. Clients typically reject messages above this size because their
validity can only be determined after fetching the complete message.

For a `Receipts` 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.

## Backwards Compatibility

This EIP changes the eth protocol and requires rolling out a new version, `eth/70`.
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
`eth/69`.

This EIP does not change consensus rules of the EVM and does not require a hard fork.

## Security Considerations

None

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[EIP-7825]: /EIPs/EIPS/eip-7825
</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>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7976-further-increase-calldata-cost/24597</comments>
        
        <description>## Abstract

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.

## Motivation

While [EIP-7623](/EIPs/EIPS/eip-7623) 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.

By increasing the floor cost to 64/64 gas per byte, this proposal aims to:

- Further reduce the maximum possible block size for data-heavy transactions
- Create additional headroom for potential block gas limit increases
- Maintain the same exemption for transactions with significant EVM computation
- Have minimal impact on users

## Specification

| Parameter                    | Value |
| ---------------------------- | ----- |
| `STANDARD_TOKEN_COST`        | `4`   |
| `TOTAL_COST_FLOOR_PER_TOKEN` | `16`  |

Let `tokens_in_calldata = zero_bytes_in_calldata + nonzero_bytes_in_calldata * 4`.

Let `floor_tokens_in_calldata = (zero_bytes_in_calldata + nonzero_bytes_in_calldata) * 4`.

Equivalently, the floor cost is `64` gas per calldata byte (both zero and non-zero), since `TOTAL_COST_FLOOR_PER_TOKEN * 4 = 64`. The token abstraction is retained only for consistency with [EIP-7623](/EIPs/EIPS/eip-7623).

Let `isContractCreation` be a boolean indicating the respective event.

Let `execution_gas_used` be the gas used for EVM execution with the gas refund subtracted.

Let `INITCODE_WORD_COST` be 2 as defined in [EIP-3860](/EIPs/EIPS/eip-3860).

The formula for determining the gas used per transaction changes from [EIP-7623](/EIPs/EIPS/eip-7623)&apos;s implementation to:

```python
tx.gasUsed = (
    21000
    +
    max(
        STANDARD_TOKEN_COST * tokens_in_calldata
        + execution_gas_used
        + isContractCreation * (32000 + INITCODE_WORD_COST * words(calldata)),
        TOTAL_COST_FLOOR_PER_TOKEN * floor_tokens_in_calldata
    )
)
```

Any transaction with a gas limit below `21000 + TOTAL_COST_FLOOR_PER_TOKEN * floor_tokens_in_calldata` 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 `gasUsed` will be below this floor price, but the floor price needs to be reserved in the transaction gas limit.

## Rationale

With [EIP-7623](/EIPs/EIPS/eip-7623)&apos;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 (`45_000_000/40`). This EIP further reduces this to approximately 0.67 MB (`45_000_000/64`).

By increasing calldata costs from 10/40 to 64/64 gas per byte for data-heavy transactions, this EIP provides:

- **Enhanced block size reduction**: Maximum data-heavy payload size drops by ~37%.
- **Maintained user experience**: Regular users engaging in DeFi, token transfers, and other EVM-heavy operations remain unaffected
- **Better blob incentivization**: Higher calldata costs further encourage migration to blob usage for data availability

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.

Analyzing the block range 20644414 - 23272414 (Sept. 2024 - Sept. 2025), 1.5% of all transactions would have been affected.

An empirical analysis summarizing the impact of this EIP can be found in [this](/EIPs/assets/eip-7976/eip7976_empirical_analysis) report.

## Backwards Compatibility

This is a backwards incompatible gas repricing that requires a scheduled network upgrade.

Wallet developers and node operators MUST update gas estimation handling to accommodate the new calldata cost rules. Specifically:

1. **Wallets**: Wallets using `eth_estimateGas` MUST be updated to ensure that they correctly account for the updated `TOTAL_COST_FLOOR_PER_TOKEN` parameter of 16. Failure to do so could result in underestimating gas, leading to failed transactions.

2. **Node Software**: RPC methods such as `eth_estimateGas` MUST incorporate the updated formula for gas calculation with the new floor cost values.

Users can maintain their usual workflows without modification, as wallet and RPC updates will handle these changes.

## Test Cases

Testing for this EIP should verify the correct application of the new calldata cost floor of 64/64 gas per byte:

1. **Data-heavy transactions**: Verify transactions with minimal EVM execution pay the floor cost of 64 gas per calldata byte
2. **EVM-heavy transactions**: Confirm transactions with significant computation continue using standard 4/16 gas per byte
3. **Edge cases**: Test transactions at the boundary where execution gas equals or exceeds the floor cost
4. **Gas estimation**: Validate that `eth_estimateGas` correctly accounts for the new `TOTAL_COST_FLOOR_PER_TOKEN` value
5. **Invalid transactions**: Ensure transactions with insufficient gas limits are properly rejected

## Security Considerations

As the maximum possible block size is further reduced compared to [EIP-7623](/EIPs/EIPS/eip-7623), no additional security concerns are introduced beyond those already addressed in the original proposal.

The same transaction bundling considerations from [EIP-7623](/EIPs/EIPS/eip-7623) apply:

1. Transaction bundling was already possible and remains so
2. Bundling does not compromise the block size reduction objectives
3. Practical limitations (trust, coordination) continue to limit widespread bundling

The increased floor cost strengthens the incentive structure for appropriate data availability method selection without introducing new attack vectors.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Call and Return Opcodes for the EVM</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7951-call-and-return-opcodes-for-the-evm/24615</comments>
        
        <description>## Abstract

This is the smallest possible change to the EVM to support calls and returns.

This proposal introduces three new control-flow instructions to the EVM:

* `CALLSUB` transfers control to the `destination` on the `stack`.
* `ENTERSUB` marks a `CALLSUB` destination.
* `RETURNSUB` returns to the `PC` after the most recent `CALLSUB`.

Code can also be prefixed with `MAGIC` bytes. `MAGIC` code is validated at `CREATE` time to ensure that it cannot execute invalid instructions, jump to invalid locations, underflow stack, or, in the absence of recursion, overflow stack.

The complete control flow of `MAGIC` code can be traversed in time and space linear in the size of the code, enabling tools for validation, automated proofs of correctness, and ahead-of-time and just-in-time compilers.

These changes are backwards-compatible: all instructions behave as specified whether or not they appear in `MAGIC` code.

## Motivation

The EVM currently lacks explicit call and return instructions. Instead, calls and returns must be synthesized using the dynamic `JUMP` instruction, which takes its destination from the stack. This creates two fundamental problems:

* **Inefficiency**: Synthesizing calls and returns with jumps wastes bytecode space and gas.
* **Complexity**: Even more important, dynamic jumps can cause quadratic &quot;path explosions&quot; during control-flow analysis, creating a denial-of-service vulnerability for things like runrime compilation to machine code. They can also trigger exponential &quot;state space explosions&quot; during formal analysis and ZK circuit construction.

For detailed historical context, technical foundations of static control flow, and their impact on Ethereum&apos;s scaling roadmap, see proposal 8173: &quot;Static Control Flow for the EVM.&quot;

## Specification

&gt; _The key words MUST and MUST NOT in this Specification are to be interpreted as described in RFC 2119 and RFC 8174._

### `CALLSUB (0x..)`

Transfers control to a subsidiary operation.

1. Pop the `destination` on top of the `stack`.
2. Push the current `PC + 1` to the `return stack`.
3. Set `PC` to `destination`.

The gas cost is _mid_ (`8`).

### `ENTERSUB (0x..)`

The `destination` of every `CALLSUB` MUST be an `ENTERSUB`.

### `RETURNSUB (0x..)`

Returns control to the caller of a subsidiary operation.

1. Pop the `return stack` to `PC`.

The gas cost is _low_ (`5`).

### `MAGIC (0xEF....)`

After this EIP has been activated, code beginning with the `MAGIC` bytes MUST be a `valid` program. Execution begins immediately after the `MAGIC` bytes.

_Notes:_

* _Values popped off the `return stack` do not need to be validated, since they are alterable only by `CALLSUB` and `RETURNSUB`._
* _The description above lays out the semantics of these instructions in terms of a `return stack`. But the actual state of the `return stack` is not observable by EVM code or consensus-critical to the protocol. (For example, a node implementer may code `CALLSUB` to unobservably push `PC` on the `return stack` rather than `PC + 1`, which is allowed so long as `RETURNSUB` observably returns control to the `PC + 1` location.)_
* _Opcode and `MAGIC` values are still to be determined, but the `MAGIC` bytes will begin with 0xEF._

### Costs

A _mid_ cost for `CALLSUB` is justified by it taking very little more work than the _mid_ cost of `JUMP` — just pushing an integer to the `return stack`.

A _jumpdest_ cost for `ENTERSUB` is justified by it being, like `JUMPDEST`, a mere label.

A _low_ cost for `RETURNSUB` is justified by needing only to pop the `return stack` into the `PC` — less work than a jump.

Benchmarking will be needed to tell if the costs are well-balanced.

### Validity

Execution is defined in the Yellow Paper as a sequence of changes to the EVM state. The conditions on `valid` code are preserved by state changes. At runtime, if execution of an instruction would violate a condition, the execution is in an exceptional halting state and cannot continue. The Yellow Paper defines six such states:

* State modification during a static call
* Insufficient gas
* More than 1024 stack items
* Insufficient stack items
* Invalid jump destination
* Invalid instruction

We would like to consider EVM code `valid` if and only if no execution of the program can lead to an exceptional halting state. In practice, we must test at runtime for the first three conditions — we don&apos;t know whether we will be called statically, how much gas there will be, or how deep a recursion may go. (However, we can validate that non-recursive programs do not overflow stack.) All of the remaining conditions MUST be validated statically.

To allow for efficient algorithms, our validation considers only the code&apos;s control flow and stack use, not its data and computations. This means we will reject programs with invalid code paths, even if those paths are not reachable.

#### Constraints on `valid` code

Code beginning with `MAGIC` MUST be `valid`. Constraints on `valid` code MUST be validated at `CREATE` time, in time and space linear in the size of the code. The constraints on `valid` code are as follows:

1. All executable opcodes must be `valid`:
   
  * They MUST have been defined in the Yellow Paper or a deployed EIP, they
  * MUST NOT have been deprecated in a subsequent deployed EIP, and
  * The `INVALID` opcode is `valid`.

2. The `JUMP` and `JUMPI` instructions

  * MUST address a `JUMPDEST`,
  * MUST NOT address immediate data, and
  * MUST be preceded by a `PUSH` instruction, .

3. The `CALLSUB` instruction

  * MUST address an `ENTERSUB`,
  * MUST NOT address immediate data, and
  * MUST be preceded by a `PUSH` instruction,

4. The number of items on the `data stack` and on the `return stack` 

  * MUST always be positive and less than or equal to 1024.

5. For all paths from a `CALLSUB` to a `RETURNSUB`

  * the absolute difference between
    * the current stack pointer and
    * the stack pointer at the previous ENTERSUB
  * MUST remain constant.

Most of these are already checked during jumpdest analysis` or at runtime.  The guarantee of constant stack height prevents stack underflow, prevents stack overflow for non-recursive programs, breaks cycles in the control flow, enables one-pass recovery of control-flow, and allows virtual stack code to be directly serialized into virtual register code for faster interpretation, compilation to machine code, and other purposes.

_Note: The JVM, Wasm, and .NET VMs enforce similar constraints for similar reasons._

#### Validation

The above is a purely semantic specification, placing no constraints on the syntax of bytecode beyond being an array of opcodes and immediate data. Subroutines here are not contiguous sequences of bytecode: they are subgraphs of the bytecode&apos;s full control-flow graph. The EVM is a simple state machine, and the control-flow graph for a program represents every possible change of state. Each instruction simply advances the state machine one more step, and the state has no syntactic structure. We only promise that `valid` code will not, as it were, jam up the gears of the machine.

Rather than enforce semantic constraints via syntax — as is done by higher-level languages — this proposal enforces them via validation: `MAGIC` code is proven `valid` at `CREATE` time. The constraints above MUST be proven true in time and space linear in the size of the code.  We provide a simple algorithm below for doing so — there are better ones.

With no syntactic constraints and minimal semantic constraints, we maximize opportunities for optimizations, including tail call elimination, multiple-entry calls, efficient register allocation, and inter-procedural optimizations. Since we want to support online compilation of EVM code to native code, it is crucial that the EVM code be as well optimized as possible by high-level-language compilers — upfront and offline.

## Rationale

### Why these three opcodes?

This proposal aims to be the smallest possible change to the EVM. We introduce only three industry-standard instructions — `CALLSUB`, `ENTERSUB`, and `RETURNSUB` — sufficient to eliminate the need for dynamic jumps in synthesizing calls and returns and

### Why no immediate arguments or code sections?

Primarily _backwards compatability_.  Other reasons  include:

* Immediate arguments** for jump destinations, would improve performance but increase complexity. See [EIP-8013: Static relative jumps and calls for the EVM](./eip-8013) for a complementary proposal using immediate arguments.

* *Code sections**or other structural constraints,  would impose syntactic restrictions that inhibit optimization. See [EIP-3540: EOF - EVM Object Format](./eip-3540) and [EIP-4750: EOF - Functions](./eip-4750) for complementary proposals that provide more structure.

By minimizing the scope, this proposal educes implementation complexity, eliminates backwards-compatibly, and reduces forwarsd-compatigility with otherproposals on the table and to come.

### Why the return-stack mechanism?

Register machines like x86, ARM, and RISC-V typically use a single stack for both data and return addresses, relying on registers and calling conventions. Stack machines like Forth, Java, Wasm, and .NET use a separate data and return stacks.  The EVM is a stack machine, and we adopt the same proven approach: a separate return stack isolated from the data stack.

#### Safety advantages

Return addresses are not accessible to EVM code. They cannot be read, modified, or moved by ordinary stack operations. This eliminates an entire class of vulnerabilities where code could corrupt its own control flow.

Because return addresses are controlled exclusively by `CALLSUB` and `RETURNSUB`, they are intrinsically safe to validate. Unlike data-stack values (which may depend on arbitrary computation), return-stack values are guaranteed to be valid `PC` values — we can validate all return addresses at compile time.

#### Proven track record

This mechanism has been used effectively in numerous machines over the last eight decades since Alan Turing introduced it (ACE, 1945). It has been implemented, tested, and even ready to ship in multiple Ethereum clients over the last nine years.

### Are there code size and gas savings?

The difference these instructions make can be seen in this very simple code for calling a routine that squares a number.  The distinct opcodes make it easier for both people and tools to understand the code, and there are modest savings in code size and gas costs as well.

```

SQUARE:                           |       SQUARE:
    jumpdest       ; 1 gas        |           entersub       ; 1 gas
    dup            ; 3 gas        |           dup            : 5 gas
    mul            ; 5 gas        |           mul            ; 5 gas
    swap1          ; 3 gas        |           returnsub      ; 5 gas
    jump           ; 8 gas        |
                                  |
CALL_SQUARE:                      |       CALL_SQUARE:
    jumpdest       ; 1 gas        |           entersub       ; 1 gas
    push RTN_CALL  ; 3 gas        |           push 2         ; 3 gas
    push 2         ; 3 gas        |           push SQUARE    ; 3 gas
    push SQUARE    ; 3 gas        |           callsub        ; 8 gas
    jump           ; 8 gas        |           returnsub      ; 5 gas
RTN_CALL:                         |
    swap1          ; 3 gas        |
    jump           ; 8 gas        |
                                  |
Size in bytes: 18                 |      Size in bytes: 13
Consumed gas:  49                 |      Consumed gas:  38

```

That&apos;s 32% fewer bytes and 30% less gas using `CALLSUB` versus using `JUMP`.  So we can see that these instructions provide a simpler, more efficient mechanism. As code becomes larger and better optimized the gains become smaller, but code using `CALLSUB` always takes less space and gas than equivalent code without it.

### Are there real-time performance gains?

Some real-time interpreter performance gains are reflected in the lower gas costs. But larger gains come from AOT and JIT compilers. The constraint that stack depths be constant means that in `MAGIC` code, a JIT can traverse the control flow in one pass, generating machine code on the fly, and an AOT can emit better code in linear time (The Wasm, JVM, and .NET VMs share this property.)

The EVM is a stack machine, but most real machines are register machines. Generating virtual register code for a faster interpreter yields significant gains (4X speedups are possible on JVM code), and generating good machine code yields orders of magnitude improvements. However, for most transactions, storage dominates execution time, and gas counting and other overhead always take their toll. So such gains would be most visible in contexts where this overhead is absent, such as L1 precompiles, some L2s, and some EVM-compatible chains.

### Does ZK and performance rollup scaling imorive?

Static control flow enables the construction of simpler, more efficient circuits for ZK verification. See proposal 8173 for details on how static control flow improves ZK-rollup and optimistic rollup efficiency, and enables future migrations to other extecution environments like RISC-V.

### How can dynamic jumps cause quadratic control flow?

Recovering a program&apos;s control-flow graph is a fundamental first step for many analyses. When all jumps are static, the number of analysis steps is linear in the number of instructions: a fixed number of paths must be explored for each jump. With dynamic jumps, every possible destination must be explored at every jump.  Intuitively, the number of possible paths through code just explodes. At worst, the number of steps paths can go up as the square of the number of instructions.  See proposal 8173 for a more detailed explanation and example exploit.

The quadratic behavior is not merely a theoretical concern. For Ethereum, it represents a denial-of-service vulnerability for many tools — including bytecode validation and AOT or JIT compilation at runtime.

## Backwards Compatibility

These changes are backwards compatible.  Opcode semantics _are not_ affected by whether the contract is `MAGIC`.  So `valid` code MUST execute identically in any contract.

There are _no changes_ to the semantics of existing EVM code. (With the caveat that code with unspecified behavior might behave in different, unspecified ways. Such code was always broken.)

Therefore this proposal _does not_ require maintaining two interpreters -- validation is done before the interpreter runs, so the interpreter need not care that the code is `valid`.

These changes do not preclude running the EVM in zero knowledge; neither do they foreclose EOF, RISC-V, or other changes.  They can instead be a win.

## Test Cases

_(Note: these tests are known to be outdated and incorrect.)_

### Simple routine

This should jump into a subroutine, back out and stop.

Bytecode: `0x60045e005c5d` (`PUSH1 0x04, CALLSUB, STOP, ENTERSUB, RETURNSUB`)

|  Pc   |      Op     | Cost |   Stack   |   RStack  |
|-------|-------------|------|-----------|-----------|
|    0  |      PUSH1  |    3 |        [] |        [] |
|    2  |    CALLSUB  |    8 |       [4] |        [] |
|    4  |    ENTERSUB |    1 |        [] |       [3] |
|    5  |  RETURNSUB  |    5 |        [] |       [3] |
|    3  |       STOP  |    0 |        [] |        [] |

Output: 0x
Consumed gas: `17`

### Two levels of subroutines

This should execute fine, going into two depths of subroutines.

Bytecode: `0x6800000000000000000c5e005c60115e5d5c5d` (`PUSH9 0x00000000000000000c, CALLSUB, STOP, ENTERSUB, PUSH1 0x11, CALLSUB, RETURNSUB, ENTERSUB, RETURNSUB`)

|  Pc   |      Op     | Cost |   Stack   |   RStack  |
|-------|-------------|------|-----------|-----------|
|    0  |      PUSH9  |    3 |        [] |        [] |
|   10  |    CALLSUB  |    8 |      [12] |        [] |
|   12  |    ENTERSUB |    1 |        [] |      [10] |
|   13  |      PUSH1  |    3 |        [] |      [10] |
|   15  |    CALLSUB  |    8 |      [17] |      [10] |
|   17  |    ENTERSUB |    1 |        [] |   [10,15] |
|   18  |  RETURNSUB  |    5 |        [] |   [10,15] |
|   16  |  RETURNSUB  |    5 |        [] |      [10] |
|   11  |       STOP  |    0 |        [] |        [] |

Consumed gas: `36`

### Failure 1: invalid jump

This should fail, since the given location is outside of the code-range. The code is the same as the previous example, except that the pushed location is `0x01000000000000000c` instead of `0x0c`.

Bytecode: `0x6801000000000000000c5e005c60115e5d5c5d` (`PUSH9 0x01000000000000000c, CALLSUB, STOP, ENTERSUB, PUSH1 0x11, CALLSUB, RETURNSUB, ENTERSUB, RETURNSUB`)

|  Pc   |      Op     | Cost |   Stack   |   RStack  |
|-------|-------------|------|-----------|-----------|
|    0  |      PUSH9  |    3 |        [] |        [] |
|   10  |    CALLSUB  |    8 |[18446744073709551628] |        [] |

Error: at pc=10, op=CALLSUB: invalid jump destination


### Failure 2: shallow `return stack`

This should fail at first opcode, due to shallow `return_stack`.

Bytecode: `0x5d5858` (`RETURNSUB, PC, PC`)

|  Pc   |      Op     | Cost |   Stack   |   RStack  |
|-------|-------------|------|-----------|-----------|
|    0  |  RETURNSUB  |    5 |        [] |        [] |

Error: at pc=0, op=RETURNSUB: invalid retsub


### Subroutine at end of code

In this example, the CALLSUB is on the last byte of code. When the subroutine returns, it should hit the &apos;virtual stop&apos; _after_ the bytecode, and not exit with error.

Bytecode: `0x6005565c5d5b60035e` (`PUSH1 0x05, JUMP, ENTERSUB, RETURNSUB, JUMPDEST, PUSH1 0x03, CALLSUB`)

|  Pc   |      Op     | Cost |   Stack   |   RStack  |
|-------|-------------|------|-----------|-----------|
|    0  |      PUSH1  |    3 |        [] |        [] |
|    2  |       JUMP  |    8 |       [5] |        [] |
|    5  |   JUMPDEST  |    1 |        [] |        [] |
|    6  |      PUSH1  |    3 |        [] |        [] |
|    8  |    CALLSUB  |    8 |       [3] |        [] |
|    3  |    ENTERSUB |    1 |        [] |       [8] |
|    4  |  RETURNSUB  |    5 |        [] |       [8] |
|    9  |       STOP  |    0 |        [] |        [] |

Consumed gas: `29`

## Reference Implementation

_(Note: this AI-generated implementation is likely incomplete and incorrect.)_

The following is a Python implementation of a recursive algorithm for validating that EVM bytecode satisfies the constraints given above. This algorithm traverses the code, emulating its control flow and stack use, and checking for violations of the rules. It runs in time proportional to the size of the code, and the depth of the stack is at most proportional to the size of the code.  An equivalent algorithm MUST be run at `CREATE` time, and has been implemented by many of our clients in the past.

```python

from typing import Optional, Tuple

class EVMOpcode:
    # Placeholder enum for EVM opcodes
    PUSH0 = 0x60
    PUSH32 = 0x7f
    CALLSUB = 0xB0
    JUMP = 0x56
    JUMPI = 0x57
    JUMPSUB = 0xB1

class Validator:
    def __init__(self, code: bytes):
        self.code = code
        self.stack_heights = {}
        self.visited_pcs = set()
        self.current_heights = []
        self.data_stack_height = 0
        self.return_stack_height = 0

    def validate(self) -&gt; bool:
        &quot;&quot;&quot;Validate EVM bytecode. Returns True for valid code.&quot;&quot;&quot;
        return self._validate_recursive(0, 0, None)

    def _validate_recursive(self, pc: int, height: int, last_push: Optional[int]) -&gt; bool:
        # Check if we are out of bounds
        if pc &gt;= len(self.code):
            return False

        # Check for stack height consistency
        if pc in self.stack_heights:
            if self.stack_heights[pc] != height:
                return False
            return True  # Already processed this PC with correct height

        # Record stack height and visited program counter
        self.stack_heights[pc] = height
        self.visited_pcs.add(pc)

        # Get instruction details
        instr_info = self.get_instr_info(pc)
        if instr_info is None:
            return False

        op, size, p, u, is_term = instr_info

        # Validate new stack height
        new_height = height - p + u
        if new_height &lt; 0 or new_height &gt; 1024:
            return False

        # Check stack depth limits
        if self.data_stack_height &lt; 1 or self.data_stack_height &gt; 1024:
            return False
        if self.return_stack_height &lt; 1 or self.return_stack_height &gt; 1024:
            return False

        # Handle subroutine calls
        if op == EVMOpcode.CALLSUB:
            self.current_heights.append(height)  # Track height for this CALLSUB
            if not self._validate_recursive(last_push, new_height, None):
                return False
            self.current_heights.pop()  # Restore height on return

        # Handle jump-related instructions
        if op in (EVMOpcode.JUMP, EVMOpcode.JUMPI, EVMOpcode.JUMPSUB):
            if last_push is None:
                return False
            
            if not self._validate_recursive(last_push, new_height, None):
                return False

            if op == EVMOpcode.JUMPI:
                if not self._validate_recursive(pc + size, new_height, None):
                    return False

        # For non-terminating instructions, prepare next instruction
        elif not is_term:
            val = (
                int.from_bytes(self.code[pc + 1:pc + size], &apos;big&apos;)
                if size &gt; 1
                else 0
            )
            push_val = val if EVMOpcode.PUSH0 &lt;= op &lt;= EVMOpcode.PUSH32 else None

            if not self._validate_recursive(pc + size, new_height, push_val):
                return False

        return True  # Processed instruction successfully

```

## Security Considerations

This proposal introduces no new security considerations beyond those already present in the EVM. Validated contracts will be more secure: they cannot execute invalid instructions, jump to invalid locations, underflow stack, or, in the absence of recursion, overflow stack.

## Copyright

Copyright and related rights waived via CC0.
</description>
        <pubDate>Wed, 17 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7979</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7979</guid>
      </item>
    
      <item>
        <title>Ed25519 transaction support</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7980-adding-ed25519-as-a-signature-scheme-to-test-eip-7932/24663</comments>
        
        <description>## Abstract

This EIP adds a new [EIP-7932](/EIPs/EIPS/eip-7932) algorithm of type `0x0` for supporting Ed25519 signatures.

## Motivation

Ed25519 is one of the most widely used forms of Elliptic Curve Cryptography and is one of the defaults for SSH keys,
this makes it a good contender to be able to sign transactions with. It also provides an algorithm to write test
cases against during the implementation phase of [EIP-7932](/EIPs/EIPS/eip-7932).

## Specification

This EIP defines a new [EIP-7932](/EIPs/EIPS/eip-7932) algorithmic type with the following parameters:
| Constant | Value |
| - | - |
| `ALG_TYPE` | `Bytes1(0x0)` |
| `GAS_PENALTY`| `1000` |
| `MAX_SIZE` | `96` |

```python
def verify(signature_info: bytes, payload_hash: Hash32) -&gt; ExecutionAddress:
  assert(len(signature_info) == 96)

  signature = signature_info[:64]
  public_key = signature_info[64:]
  
  # This is the `Verify` function described in [RFC 8032 Section 5.1.7](https://datatracker.ietf.org/doc/html/rfc8032#section-5.1.7),
  # This MUST be processed as raw `Ed25519` and not `Ed25519ctx` or `Ed25519ph`
  assert(ed25519_verify(signature, public_key, payload_hash))

  return keccak256(public_key)[-20:]
```

## Rationale

### Additional 1000 gas penalty

The gas penalty discourages people from attempting to migrate off current secp256k1 accounts, and also covers the additional overhead (in regards to hashing) that the ed25519 curve applies.

### Why Ed25519?

Ed25519 has significant tooling backing it, this makes it a good candidate for using as a &quot;dummy&quot; algorithm.
This allows it to be an algorithm for client teams to easily test [EIP-7932](/EIPs/EIPS/eip-7932).

It may also be useful for signing in Hardware security modules in server environments designed for serving
as [ERC-4337](/EIPs/EIPS/eip-4337) bundlers. It may also improve interoperability with other components such as TPM chips.

### Appending the public key to the signature

Currently, without changing the algorithm itself, it is impossible to efficiently recover the public key
from a signature and message.

## Backwards Compatibility

No backward compatibility issues found.

## Security Considerations

Needs discussion.
&lt;!-- TODO --&gt;

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 25 Jun 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7980</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7980</guid>
      </item>
    
      <item>
        <title>Increase Access List Cost</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7981-increase-access-list-cost/24680</comments>
        
        <description>## Abstract

This EIP charges access lists for their data footprint, preventing the circumvention of the [EIP-7623](/EIPs/EIPS/eip-7623) floor pricing. This effectively reduces the worst-case block size by ~21% with minimal impact on users.

## Motivation

Access lists are only priced for storage but not for their data.

Furthermore, access lists can circumvent the [EIP-7623](/EIPs/EIPS/eip-7623) 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.

## Specification

| Parameter                              | Value | Source |
| -------------------------------------- | ----- | ------ |
| `ACCESS_LIST_ADDRESS_COST`            | `2400` | [EIP-2930](/EIPs/EIPS/eip-2930) |
| `ACCESS_LIST_STORAGE_KEY_COST`        | `1900` | [EIP-2930](/EIPs/EIPS/eip-2930) |
| `TOTAL_COST_FLOOR_PER_TOKEN`          | `16`   | [EIP-7976](/EIPs/EIPS/eip-7976) |

Let `access_list_bytes` be the total byte count of addresses (20 bytes each) and storage keys (32 bytes each) in the access list.

Let `floor_tokens_in_access_list = access_list_bytes * 4`.

Equivalently, the access list data is charged `64` gas per byte, which amounts to `1280` gas per address (20 bytes × 64) and `2048` gas per storage key (32 bytes × 64). The token abstraction is retained only for consistency with [EIP-7623](/EIPs/EIPS/eip-7623) and [EIP-7976](/EIPs/EIPS/eip-7976).

The access list cost formula changes from [EIP-2930](/EIPs/EIPS/eip-2930) to include data cost:

```python
access_list_cost = (
    ACCESS_LIST_ADDRESS_COST * access_list_addresses
    + ACCESS_LIST_STORAGE_KEY_COST * access_list_storage_keys
    + TOTAL_COST_FLOOR_PER_TOKEN * floor_tokens_in_access_list
)
```

The [EIP-7976](/EIPs/EIPS/eip-7976) floor calculation is modified to include access list tokens:

```python
floor_tokens_in_calldata = (zero_bytes_in_calldata + nonzero_bytes_in_calldata) * 4
total_floor_data_tokens = floor_tokens_in_calldata + floor_tokens_in_access_list

data_floor_gas_cost = TX_BASE_COST + TOTAL_COST_FLOOR_PER_TOKEN * total_floor_data_tokens
```

The gas used calculation becomes:

```python
tx.gasUsed = (
    21000
    +
    max(
        STANDARD_TOKEN_COST * tokens_in_calldata
        + execution_gas_used
        + isContractCreation * (32000 + INITCODE_WORD_COST * words(calldata))
        + access_list_cost,
        TOTAL_COST_FLOOR_PER_TOKEN * total_floor_data_tokens
    )
)
```

Any transaction with a gas limit below `21000 + TOTAL_COST_FLOOR_PER_TOKEN * total_floor_data_tokens` or below its intrinsic gas cost is considered invalid.

## Rationale

Access list data is always charged at floor rate (added to `access_list_cost`), and access list tokens are included in the floor calculation. This ensures:

- Access list data always pays floor rate regardless of execution level
- Access lists cannot be used to bypass the calldata floor pricing
- Consistent pricing across all transaction data sources

## Backwards Compatibility

This is a backwards incompatible gas repricing that requires a scheduled network upgrade.

Requires updates to gas estimation in wallets and nodes. Normal usage patterns remain largely unaffected.

## Reference Implementation

```python
def calculate_access_list_floor_tokens(access_list: Tuple[Access, ...]) -&gt; Uint:
    &quot;&quot;&quot;Count floor data tokens in access list addresses and storage keys.&quot;&quot;&quot;
    total_bytes = Uint(0)

    for access in access_list:
        total_bytes += ulen(access.account)
        for slot in access.slots:
            total_bytes += ulen(slot)

    return total_bytes * Uint(4)


def calculate_intrinsic_cost(tx: Transaction) -&gt; Tuple[Uint, Uint]:
    &quot;&quot;&quot;
    Calculate intrinsic gas cost and floor gas cost.
    Returns (intrinsic_gas, floor_gas).
    &quot;&quot;&quot;
    # Calldata tokens (EIP-7976)
    calldata_zero_bytes = Uint(0)
    for byte in tx.data:
        if byte == 0:
            calldata_zero_bytes += Uint(1)
    calldata_nonzero_bytes = ulen(tx.data) - calldata_zero_bytes
    tokens_in_calldata = (
        calldata_zero_bytes + calldata_nonzero_bytes * Uint(4)
    )
    floor_tokens_in_calldata = (
        (calldata_zero_bytes + calldata_nonzero_bytes) * Uint(4)
    )

    # Access list floor tokens and cost
    floor_tokens_in_access_list = Uint(0)
    access_list_cost = Uint(0)
    if has_access_list(tx):
        floor_tokens_in_access_list = calculate_access_list_floor_tokens(tx.access_list)
        for access in tx.access_list:
            access_list_cost += TX_ACCESS_LIST_ADDRESS_COST
            access_list_cost += ulen(access.slots) * TX_ACCESS_LIST_STORAGE_KEY_COST
        # EIP-7981: Always charge data cost
        access_list_cost += floor_tokens_in_access_list * TOTAL_COST_FLOOR_PER_TOKEN

    # EIP-7981: Floor includes all floor data tokens
    total_floor_data_tokens = floor_tokens_in_calldata + floor_tokens_in_access_list
    floor_gas = TX_BASE_COST + total_floor_data_tokens * TOTAL_COST_FLOOR_PER_TOKEN

    # Intrinsic gas
    calldata_cost = tokens_in_calldata * STANDARD_TOKEN_COST
    create_cost = TX_CREATE_COST + init_code_cost(tx.data) if is_create(tx) else Uint(0)

    intrinsic_gas = TX_BASE_COST + calldata_cost + create_cost + access_list_cost

    return intrinsic_gas, floor_gas
```

## Security Considerations

This EIP closes a loophole that allows circumventing [EIP-7623](/EIPs/EIPS/eip-7623) 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.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Confidential Fungible Token</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7984-confidential-fungible-token-interface/24735</comments>
        
        <description>## Abstract

The following standard describes confidential fungible tokens via pointers. All amounts in this standard are represented by confidential pointers; therefore, balances and transfer amounts are confidential. Pointers refer to data stored elsewhere--onchain or offchain. The logistics of pointer resolution, operation, and location are implementation specific. The interface defines functions to transfer tokens with pointers, as well as approve operators, allowing the token to be transferred by a third party.

## Motivation

Confidential tokens enable private value transfer which is vital for many usecases such as payroll, confidential DeFi, institutional settlement, and more.
A standard interface allows pointer based confidential tokens on Ethereum to be reused by other applications: from privacy-focused wallets to decentralized exchanges, while keeping transaction amounts private from public view.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

### Nomenclature

All amounts in this ERC are pointer based amounts represented by `bytes32` pointers unless otherwise specified. The resolution and manipulation of these pointers is implementation specific.

### Token

Compliant tokens MUST implement [ERC-165](/EIPs/EIPS/eip-165). The `supportsInterface` function MUST return `true` if `0x4958f2a4` is passed through the `interfaceID` argument.

### Methods

Compliant tokens MUST implement the following methods, unless otherwise specified:

- #### `name()`

  Returns the name of the token - e.g. `&quot;MyConfidentialToken&quot;`.

  ```solidity
  function name() external view returns (string memory)
  ```

- #### `symbol()`

  Returns the symbol of the token - e.g. `&quot;MCT&quot;`.

  ```solidity
  function symbol() external view returns (string memory)
  ```

- #### `decimals()`

  Returns the number of decimals the token uses (e.g. `6`) as a plaintext `uint8`.

  ```solidity
  function decimals() external view returns (uint8)
  ```

- #### `contractURI()`

  Returns the metadata URI for the token. SHOULD follow the schema defined in [ERC-7572](/EIPs/EIPS/eip-7572).

  ```solidity
  function contractURI() external view returns (string memory)
  ```

- #### `confidentialTotalSupply()`

  Returns the total token supply.

  ```solidity
  function confidentialTotalSupply() external view returns (bytes32)
  ```

- #### `confidentialBalanceOf(address)`

  Returns the balance of `account`.

  ```solidity
  function confidentialBalanceOf(address account) external view returns (bytes32)
  ```

- #### `isOperator(address,address)`

  Returns `true` if `spender` is currently authorized to transfer tokens on behalf of `holder`.

  ```solidity
  function isOperator(address holder, address spender) external view returns (bool)
  ```

- #### `setOperator(address,uint48)`

  Authorizes `operator` to transfer tokens on behalf of the caller until timestamp `until`--passed as a plaintext `uint48`. An operator may transfer any amount of tokens on behalf of a holder while approved. Accounts may have multiple simultaneous operators.

  MUST emit the `OperatorSet` event.

  ```solidity
  function setOperator(address operator, uint48 until) external
  ```

- #### `confidentialTransfer(address,bytes32)`

  Transfers `amount` of tokens to address `to`. The function MAY revert if the caller&apos;s balance does not have enough tokens to spend.

  Returns the actual amount that was transferred.

  MUST emit the `ConfidentialTransfer` event.

  ```solidity
  function confidentialTransfer(address to, bytes32 amount) external returns (bytes32)
  ```

- #### `confidentialTransfer(address,bytes32,bytes)`

  Transfers `amount` of tokens to address `to`. The function MAY revert if the caller&apos;s balance does not have enough tokens to spend.

  The `data` parameter contains implementation-specific information such as cryptographic proofs.

  Returns the actual amount that was transferred.

  MUST emit the `ConfidentialTransfer` event.

  ```solidity
  function confidentialTransfer(address to, bytes32 amount, bytes calldata data) external returns (bytes32)
  ```

- #### `confidentialTransferFrom(address,address,bytes32)`

  Transfers `amount` of tokens from address `from` to address `to`. The function MAY revert if the `from`&apos;s account balance does not have enough tokens to spend.

  Returns the actual amount that was transferred.

  MUST revert if the caller is not an operator for `from`.

  MUST emit the `ConfidentialTransfer` event.

  ```solidity
  function confidentialTransferFrom(address from, address to, bytes32 amount, bytes calldata data) external returns (bytes32)
  ```

- #### `confidentialTransferFrom(address,address,bytes32,bytes)`

  Transfers `amount` of tokens from address `from` to address `to`. The function MAY revert if the `from`&apos;s account balance does not have enough tokens to spend.

  The `data` parameter contains implementation-specific information such as cryptographic proofs.

  Returns the actual amount that was transferred.

  MUST revert if the caller is not an operator for `from`.

  MUST emit the `ConfidentialTransfer` event.

  ```solidity
  function confidentialTransferFrom(address from, address to, bytes32 amount, bytes calldata data) external returns (bytes32)
  ```

- #### `confidentialTransferAndCall(address,bytes32,bytes)`

  Transfers `amount` of tokens to address `to`. The function MAY revert if the caller&apos;s balance does not have enough tokens to spend.

  The `data` parameter contains implementation-specific information such as cryptographic proofs.

  See [Callback Details](#callback-details) below for details on the callback flow.

  Returns the actual amount that was transferred.

  MUST emit the `ConfidentialTransfer` event.

  ```solidity
  function confidentialTransferAndCall(address to, bytes32 amount, bytes calldata callData) external returns (bytes32)
  ```

- #### `confidentialTransferAndCall(address,bytes32,bytes,bytes)`

  Transfers `amount` of tokens to address `to`. The function MAY revert if the caller&apos;s balance does not have enough tokens to spend.

  The `data` parameter contains implementation-specific information such as cryptographic proofs.

  See [Callback Details](#callback-details) below for details on the callback flow.

  Returns the actual amount that was transferred.

  MUST emit the `ConfidentialTransfer` event.

  ```solidity
  function confidentialTransferAndCall(address to, bytes32 amount, bytes calldata data, bytes calldata callData) external returns (bytes32)
  ```

- #### `confidentialTransferFromAndCall(address,address,bytes32,bytes)`

  Transfers `amount` of tokens from address `from` to address `to`. The function MAY revert if the `from`&apos;s account balance does not have enough tokens to spend.

  See [Callback Details](#callback-details) below for details on the callback flow.

  Returns the actual amount that was transferred.

  MUST revert if the caller is not an operator for `from`.

  MUST emit the `ConfidentialTransfer` event.

  ```solidity
  function confidentialTransferFromAndCall(address from, address to, bytes32 amount, bytes calldata callData) external returns (bytes32)
  ```

- #### `confidentialTransferFromAndCall(address,address,bytes32,bytes,bytes)`

  Transfers `amount` of tokens from address `from` to address `to`. The function MAY revert if the `from`&apos;s account balance does not have enough tokens to spend.

  The `data` parameter contains implementation-specific information such as cryptographic proofs.

  See [Callback Details](#callback-details) below for details on the callback flow.

  Returns the actual amount that was transferred.

  MUST revert if the caller is not an operator for `from`.

  MUST emit the `ConfidentialTransfer` event.

  ```solidity
  function confidentialTransferFromAndCall(address from, address to, bytes32 amount, bytes calldata data, bytes calldata callData) external returns (bytes32)
  ```

### Events

- #### ConfidentialTransfer

  MUST trigger when confidential tokens are transferred, including zero value transfers.

  A token contract which creates new tokens SHOULD trigger a ConfidentialTransfer event with the `from` address set to `0x0` when tokens are created.

  ```solidity
  event ConfidentialTransfer(address indexed from, address indexed to, bytes32 indexed amount)
  ```

- #### OperatorSet

  MUST trigger on any successful call to `setOperator`.

  ```solidity
  event OperatorSet(address indexed holder, address indexed operator, uint48 until)
  ```

- #### AmountDisclosed

  SHOULD trigger when a pointer amount is publicly disclosed through implementation-specific mechanisms.

  ```solidity
  event AmountDisclosed(bytes32 indexed handle, uint256 amount)
  ```

### Callback Details

Transfer functions suffixed with `andCall` execute a callback to the `to` address AFTER all transfer logic is completed. The callback calls the `onConfidentialTransferReceived` function with the transfer initiator (operator), from address, actual amount sent, and given `callData` bytes (the last parameter for `andCall` functions). The callback flow is as follows:

- If `address(to).code.length == 0` the callback is a no-op and returns successfully.
- Call [`onConfidentialTransferReceived(address, address, bytes32, bytes)`](#onconfidentialtransferreceived) on `to`.
- If the function call reverts, revert.
- If the function call returns the false boolean, attempt to transfer back the tokens to the original holder and return.

### Contract Receivers

For a contract to receive a transfer with a callback, it MUST implement the `onConfidentialTransferReceived` function:

#### onConfidentialTransferReceived

If the callback is unsuccessful, the function SHOULD revert or return a pointer to the false boolean.

The token will attempt to return tokens from the receiver to the sender if false is returned. Note that this reversal may fail if the receiver spends tokens as part of the callback.

```solidity
function onConfidentialTransferReceived(address operator, address from, bytes32 amount, bytes calldata data) external returns (bytes32 success);
```

## Rationale

### Technology Agnostic Design

Using `bytes32` allows implementations using pointer based systems and privacy mechanisms including FHE systems, zero-knowledge proofs, secure enclaves, or future technologies to be compliant.

### Operator Model

Time-limited operators provide granular control while enabling DeFi protocol integration and natural permission expiration. This approach reduces the load on the external system by removing the need to track approval amounts.

### Data Parameter

The `bytes calldata data` parameter in transfer functions allows implementations to include cryptographic proofs, access permissions, or other privacy-mechanism-specific information.

## Security Considerations

Security depends on the underlying pointer based mechanism. Implementations must guard against side-channel attacks and ensure proper key management for offchain operations.

Token callbacks are associated with inherent security risks, including reentrancy and gas griefing. When utilizing callbacks, consider using reentrancy protection and setting a gas limit.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 03 Jul 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7984</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7984</guid>
      </item>
    
      <item>
        <title>Gateway Attributes for Message Control</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/new-erc-attributes-for-message-control-in-erc-7786-gateways/24734</comments>
        
        <description>## Abstract

This ERC defines standard attributes for [ERC-7786] cross-chain messaging gateways to enable consistent cancellation, timeout, retry, dependency, and delivery control mechanisms across implementations. These attributes provide applications with predictable control over message lifecycle, ordering, and delivery requirements.

[ERC-7786]: /EIPs/EIPS/eip-7786

## Motivation

[ERC-7786] introduces an extensible attribute system for cross-chain messaging, but leaves attribute standardization to follow-up specifications. As cross-chain applications mature, consistent patterns for message control have emerged as essential requirements:

1. **Cancellation**: Applications need to cancel pending messages due to changed conditions
2. **Timeouts**: Automatic cancellation prevents indefinite pending states
3. **Retry Logic**: Standardized failure handling improves reliability
4. **Revert Behavior**: Consistent error semantics across gateways
5. **Message Dependencies**: Ensuring correct ordering when messages must deliver in sequence
6. **Gas Requirements**: Preventing delivery failures due to insufficient gas
7. **Delivery Timing**: Controlling when messages can be delivered for scheduling and coordination

Without standardized attributes, each gateway implements these features differently, fragmenting the ecosystem and requiring application-specific integration logic.

## Specification

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

### Standard Attributes

This specification defines standard attributes for [ERC-7786] cross-chain messaging gateways. The word &quot;delivery&quot; (or &quot;deliver&quot;) is used to refer to the process of delivering a message to the destination chain, similar to its usage in [ERC-7786].

Gateways MAY implement attributes independently. Gateways MUST validate the attribute&apos;s encoding for each attribute they implement and revert the transaction if the encoding is invalid.

#### `cancellable(bool)`

Indicates whether a message can be cancelled after submission. This attribute uses selector `0xde986d7f`, which represents the first 4 bytes of `keccak256(&quot;cancellable(bool)&quot;)`.

The attribute value is encoded as an ABI-encoded boolean, and MAY default to `false` when not specified. When set to `true`, gateways MUST provide a cancellation mechanism to allow applications to cancel pending messages due to changed conditions or requirements.

#### `deliverBefore(uint256)`

Specifies a timestamp after which the message cannot be delivered. This attribute uses selector `0x3e97d7ee`, derived from the first 4 bytes of `keccak256(&quot;deliverBefore(uint256)&quot;)`.

The value is encoded as an ABI-encoded Unix timestamp, and MAY default to `0` when not specified. Gateways MUST NOT deliver messages after the expiration timestamp unless `0` is specified, which MUST be interpreted as no expiration.

#### `deliverAfter(uint256)`

Specifies the earliest timestamp at which the message can be delivered. This attribute uses selector `0x745910eb`, derived from the first 4 bytes of `keccak256(&quot;deliverAfter(uint256)&quot;)`.

The value is encoded as an ABI-encoded Unix timestamp, and MAY default to `0` when not specified. Gateways MUST NOT deliver messages before the delivery timestamp unless `0` is specified, which MUST be interpreted as no delay. When combined with `deliverBefore(uint256)`, this creates a delivery time window.

#### `retryPolicy(bytes)`

Defines retry behavior for failed message delivery. Using selector `0xf002c055` from the first 4 bytes of `keccak256(&quot;retryPolicy(bytes)&quot;)`, this attribute encodes retry parameters as ABI-encoded bytes.

The format follows `abi.encodePacked(uint16(maxRetries), uint32(retryDelay), uint32(backoffMultiplier))`, where `maxRetries` specifies the maximum number of retry attempts (with 0 indicating no retries), `retryDelay` defines the initial delay between retries in seconds, and `backoffMultiplier` provides the multiplier for exponential backoff in basis points (with 10000 representing 1x multiplier).

The attribute value MAY default to `0x` when not specified, equivalent to infinite retries, no delay, and no backoff (or `maxRetries = 0`, `retryDelay = 0`, and `backoffMultiplier = 0`).

#### `revertBehavior(uint8)`

Specifies how delivery failures MUST be handled. This attribute uses selector `0x9e521a77`, representing the first 4 bytes of `keccak256(&quot;revertBehavior(uint8)&quot;)`.

The value is encoded as an ABI-encoded uint8 with the following possible values:

**`0` – Revert on Failure**

- Gateways MUST revert the entire message delivery when any failure occurs.
- Gateways SHOULD propagate the original failure reason when reverting.

**`1` – Emit-and-Continue**

- Gateways MUST emit a `MessageFailed(bytes32 sendId, string reason)` event upon failure.
- Gateways MUST continue delivery of subsequent messages or operations.

**`2` – Silent Failure**

- Gateways MUST NOT revert the transaction
- Gateways MUST NOT emit any failure-related events.

When not specified, the attribute MUST default to `0`.

#### `dependsOn(bytes32[])`

Specifies message dependencies that must be delivered before this message. This attribute uses selector `0xa9fed7b9`, derived from the first 4 bytes of `keccak256(&quot;dependsOn(bytes32[])&quot;)`.

The value is encoded as an ABI-encoded array of message identifiers. Gateways MUST NOT deliver a message until all messages specified in the `dependsOn` array have been successfully delivered. When not specified or empty, the message has no dependencies. This ensures correct ordering and prevents out-of-order delivery issues.

#### `minGasLimit(uint256)`

Specifies the minimum gas limit required for message delivery. This attribute uses selector `0x39f87ba1`, derived from the first 4 bytes of `keccak256(&quot;minGasLimit(uint256)&quot;)`.

The value is encoded as an ABI-encoded uint256 representing the minimum gas units required. Gateways MUST ensure at least this amount of gas is available before attempting message delivery. When not specified, gateways MAY use their default gas allocation strategies.

## Rationale

These attributes address the most common cross-chain message control requirements:

- **Lifecycle control** via cancellation and timeout mechanisms
- **Delivery timing** through delivery time windows
- **Failure handling** via retry policies and revert behavior
- **Message ordering** through dependency chains
- **Delivery guarantees** via minimum gas requirements

The byte-encoded retry policy allows for extensible parameters without requiring additional attributes. The dependency mechanism enables complex multi-message workflows while maintaining simplicity for single-message scenarios.

## Backwards Compatibility

This specification extends [ERC-7786] without breaking changes. Gateways not supporting these attributes will operate normally per the base specification&apos;s requirement to handle unknown attributes gracefully.

## Security Considerations

&lt;!-- TODO: Discuss --&gt;

&lt;!-- Maybe? --&gt;
&lt;!-- - **Dependency Cycles**: Gateways should detect and reject circular dependencies in `dependsOn` arrays --&gt;

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 04 Jul 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7985</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7985</guid>
      </item>
    
      <item>
        <title>Minimal Avatar Smart Wallet (MASW)</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-tbd-minimal-avatar-smart-wallet-masw-delegate-wallet-for-eip-7702/24761</comments>
        
        <description>## Abstract

Minimal Avatar Smart Wallet (MASW) is an immutable delegate‑wallet that any EOA can designate via [EIP‑7702](./eip-7702) (txType `0x04`). Once designated, the wallet&apos;s code remains active for every subsequent transaction until the owner sends a new `0x04` to clear or replace it. During each delegated call the EOA is the avatar and MASW&apos;s code executes as the delegate at the same address, enabling atomic batched calls ([EIP‑712](./eip-712) signed) and optional sponsor gas reimbursement in ETH or [ERC‑20](./eip-20).

The contract offers one primary function, `executeBatch`, plus two plug‑in hooks: a Policy Module for pre/post guards and a Recovery Module for alternate signature validation. Replay attacks are prevented by a global metaNonce, an expiry, and a chain‑bound `EIP‑712` domain separator. Standardising this seven‑parameter ABI removes wallet fragmentation while still allowing custom logic through modules.

## Motivation

A single‑transaction code‑injection model (EIP‑7702) grants EOAs full implementation freedom, but unconstrained diversity would impose high coordination costs:

- **Interoperability** – Divergent ABIs and fee‑settlement conventions force dApps and relayers to maintain per‑wallet adapters, increasing integration complexity and failure modes.
- **Economic alignment** – Gas‑sponsorship relies on deterministic fee‑reimbursement paths; heterogeneity erodes relayer incentives and throttles sponsored‑transaction volume.
- **Tooling precision** – Indexers, debuggers, and static‑analysis frameworks achieve optimal decoding and gas estimation when targeting a single, fixed byte‑code and seven‑field call schema.
- **Extensibility focus** – Constraining variability to two module boundaries (Policy, Recovery) localizes complexity, allowing research and hardening efforts to concentrate on higher‑level security primitives rather than re‑engineering core wallet logic.

By standardising the immutable byte‑code, signature domain, and minimal ABI while exposing clearly defined extension hooks, MASW minimizes fragmentation and maximizes composability across the Ethereum tooling stack.

## Specification

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

### Overview of Delegation Flow

1. **Deploy** `MASW` with constructor argument `_owner = EOA`.
2. The owner sends an EIP‑7702 transaction (txType `0x04`) referencing the contract&apos;s byte‑code hash.
3. After that transaction the EOA acts as the **avatar wallet** while the MASW logic executes as the **delegate wallet** at the _same_ address.

### Public Interface

```solidity
function executeBatch(
    address[] calldata targets,
    uint256[] calldata values,
    bytes[]   calldata calldatas,
    address token,
    uint256 fee,
    uint256 expiry,
    bytes   calldata signature
) external;

function setPolicyModule(address newModule)   external;
function setRecoveryModule(address newModule) external;

event BatchExecuted(bytes32 indexed structHash);
event ModuleChanged(bytes32 indexed kind, address oldModule, address newModule);
```

### Transaction Type Hash

```solidity
bytes32 constant BATCH_TYPEHASH = keccak256(
  &quot;Batch(address[] targets,uint256[] values,bytes[] calldatas,address token,uint256 fee,uint256 exp,uint256 metaNonce)&quot;
);
```

### Storage Layout

| Slot | Name             | Type    | Description                              |
| ---: | ---------------- | ------- | ---------------------------------------- |
|    0 | `metaNonce`      | uint256 | Monotonically increasing meta‑nonce      |
|    1 | `_entered`       | uint256 | Re‑entrancy guard flag                   |
|    2 | `policyModule`   | address | Optional `IPolicyModule` (zero = none)   |
|    3 | `recoveryModule` | address | Optional `IRecoveryModule` (zero = none) |

`owner` and `DOMAIN_SEPARATOR` are `immutable` and occupy no storage slots.

### Domain Separator Construction

```solidity
DOMAIN_SEPARATOR = keccak256(
  abi.encode(
    keccak256(&quot;EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)&quot;),
    keccak256(&quot;MASW&quot;),
    keccak256(&quot;1&quot;),
    block.chainid,   // MUST be the live chain‑ID; using 0 is disallowed
    _owner           // keeps separator stable before &amp; after delegation
  )
);
```

### Batch Execution (`executeBatch`)

| Stage                 | Behaviour                                                                                                                                                                                                         |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Validation**        | ‑ `targets.length == values.length == calldatas.length &gt; 0`&lt;br&gt;‑ `block.timestamp ≤ expiry`&lt;br&gt;‑ `metaNonce` matches then increments&lt;br&gt;‑ `EIP712` digest recovers `owner` **or** is approved by `recoveryModule` |
| **Policy pre‑hook**   | If `policyModule != address(0)`, `preCheck` **MUST** return `true`; a revert or `false` vetoes the batch                                                                                                          |
| **Calls**             | For each index _i_: `targets[i].call{value:values[i]}(calldatas[i])`; revert on first failure                                                                                                                     |
| **Policy post‑hook**  | Same semantics as pre‑hook                                                                                                                                                                                        |
| **Fee reimbursement** | If `fee &gt; 0`: native transfer (`token == address(0)`) or `ERC20` `transfer` with OpenZeppelin‑style return‑value check   &lt;!-- TODO --&gt;                                                                                         |
| **Emit**              | `BatchExecuted(structHash)`                                                                                                                                                                                       |

#### Gas Sponsorship

The relayer and owner agree off‑chain on `(token, fee)` prior to submission.  
Because the fee is part of the signed batch, a relayer cannot unilaterally raise it.  
If a rival relayer broadcasts the same signed batch first, they earn the fee and the original relayer&apos;s transaction reverts—aligning incentives naturally.  
Relayers **MUST** confirm the avatar&apos;s balance up‑front; insufficient funds render the transaction invalid in the mem‑pool.

### Modules

#### Policy Module

```solidity
interface IPolicyModule {
  function preCheck (address sender, bytes calldata rawData, uint256 value) external view returns (bool);
  function postCheck(address sender, bytes calldata rawData, uint256 value) external view returns (bool);
}
```

- A module **MAY** veto by reverting _or_ by returning `false`.
- The `value` parameter represents the total ETH sent with the transaction (`msg.value`), allowing the policy module to validate this against the batch requirements contained in `rawData`.
- Aggregator designs are encouraged: forward to child policies and stop on first failure (revert or return `false`).

#### Recovery Module

```solidity
interface IRecoveryModule {
  function isValidSignature(bytes32 hash, bytes calldata sig) external view returns (bytes4);
}
```

Must return `0x1626ba7e`.

### Nonce‑Race Consideration

A single global `metaNonce` is used. Two relayers submitting the same nonce concurrently results in one success and one revert. The `expiry` field (wallets typically set ≤ 30 s) makes such races low‑impact, but UIs should surface the failure.

## Rationale

- **Immutable logic** minimizes upgrade risk; a new version requires an explicit 7702 `0x04` call.
- A **two‑module** boundary captures common customizations without growing byte‑code.
- No hard `maxTargets`; advanced users can bundle many calls, while conservative users install a size‑capping Policy module.
- Domain separator binds the real `chainId` to mitigate cross‑chain replays.

## Reference Implementation

Reference implementation can be found here [`MASW.sol`](/EIPs/assets/eip-7988/MASW.sol).

## Security Considerations

| Threat                       | Mitigation                                                                                        |
| ---------------------------- | ------------------------------------------------------------------------------------------------- |
| Same‑chain replay            | Global `metaNonce`                                                                                |
| Cross‑chain replay           | Chain‑bound domain separator                                                                      |
| Fee grief / over‑charge      | Fee is part of signed data; front‑running risk sits with relayer                                  |
| Batch gas grief              | Optional Policy can reject oversized batches                                                      |
| `ERC20` non‑standard returns | OpenZeppelin `SafeERC20` transfer check                                                           |
| Re‑entrancy                  | `nonReentrant` guard; state mutated only before external calls (nonce++) and after (fee transfer) |
| Malicious Module             | Core logic immutable; swapping modules needs an owner‑signed tx                                   |

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 08 Jul 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7988</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7988</guid>
      </item>
    
      <item>
        <title>Verifiable ML Model Inference (ZKML)</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7992-verifiable-ml-model-inference-zkml/24896</comments>
        
        <description>## Abstract

This ERC standardizes how smart contracts reference machine-learning (ML) models and accept zero-knowledge attestations of their inferences. It defines a registry that issues a `modelId` for a `ModelCommitment`, hashes of the model’s weights/architecture, proving circuit/AIR, and verifying key, along with a `proofSystemId` for the proving system, and exposes discoverability via [ERC-165](/EIPs/EIPS/eip-165). A verifier interface provides `verifyInference(modelId, inputCommitment, output, proof)`: it retrieves the model commitment, dispatches verification to the declared proof system, and reverts on any mismatch or invalid proof; success implies validity and emits `InferenceVerified`. Inputs are bound by domain-separated commitments (nonceable for replay protection), outputs are ABI-encoded bytes whose schema can be application-defined or additionally committed on-chain, and proof systems (e.g., Groth16/Plonk/STARK) are pluggable without ABI changes. An optional extension persists verified inference records to enable auditability and deterministic settlement.


## Motivation

Smart contracts can’t run large ML models, and they can’t trust an oracle’s claim about a model’s output. 
Today, projects either (1) trust a centralized server, (2) cripple models to fit on-chain,  or (3) rely on social committees. None provide cryptographic assurance.

Zero-knowledge ML (ZKML) fixes the trust gap by letting a prover show—succinctly and privately—that a specific model, with specific inputs, produced a specific output. 
But without a shared interface, every dApp/verifier pair is bespoke: different ABIs, different registry schemas, poor composability.

This ERC standardizes that on-chain boundary:
- Registry: publish immutable commitments to model weights/architecture/circuits so callers know exactly which model they’re referencing.
- Verifier: a uniform function to validate inference proofs, independent of proof system (Groth16, Plonk, STARKs, …).

Benefits include:
- Trustless, composable “AI oracles” for DeFi risk, prediction markets, insurance, etc.
- Protection of proprietary models and private inputs while still guaranteeing correctness.
- Deterministic, dispute-free settlement for complex computations.
- Lower integration and audit overhead via consistent events, structs, and revert semantics.
- Future-proofing as proving systems evolve—only implementations change, not integrators.
- Clear security expectations (e.g., nonce usage to prevent replays) baked into the spec.

In short, this ERC turns verifiable ML inference into a reusable primitive—doing for AI outputs what [ERC-20](/EIPs/EIPS/eip-20)/[ERC-721](/EIPs/EIPS/eip-721) did for assets.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

### Terminology &amp; IDs

-	Model Commitment: A bundle of hashes that ties together the model’s weights, architecture, proving circuit/Algebraic intermediate representation (AIR), and verifying key.
-	`modelId` (`uint256`): A unique identifier returned by the registry upon model registration.
-	`inputCommitment` (`bytes32`): A hash commitment to all private inputs (and any declared public inputs) for an inference. Implementations MUST domain-separate and SHOULD include a nonce/salt when single-use or non-deterministic behavior is possible.
-	`output` (`bytes`): ABI-encoded public outputs of the inference. Consumers MUST agree on its schema and MAY validate it via an outputCommitment (not included in the minimal interface).
-	`proof` (`bytes`): The ZK proof blob.
-	`proofSystemId` (`bytes4`): Identifier of the proving system + curve + version used by the circuit.

`proofSystemId` MUST equal the first four bytes of:

```bytes4(keccak256(abi.encodePacked(&lt;canonical-proof-system-name-and-version&gt;)))```

Where `&lt;canonical-proof-system-name-and-version&gt;` is a lowercase, hyphen-separated string, e.g.:
	-	&quot;groth16-bn254-v1&quot;
	-	&quot;plonk-bn254-v2&quot;
	-	&quot;stark-airfoo-v1&quot;

This method ensures deterministic, collision-resistant identifiers across implementations.

### Interfaces

#### ZKML Registry 

``` solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.20;

interface IERCZKMLRegistry /* is IERC165 */ {
    struct ModelCommitment {
        bytes32 modelHash;     // weights + architecture hash
        bytes32 circuitHash;   // arithmetic circuit / AIR hash
        bytes32 vkHash;        // verifying key hash
        bytes4  proofSystemId; // keccak-based identifier
        string  uri;           // optional off-chain metadata (IPFS/HTTP)
    }

    event ModelRegistered(
        uint256 indexed modelId,
        address indexed owner,
        ModelCommitment commitment
    );

    event ModelUpdated(
        uint256 indexed modelId,
        ModelCommitment oldCommitment,
        ModelCommitment newCommitment
    );

    event ModelDeprecated(uint256 indexed modelId);

    error ModelNotFound(uint256 modelId);
    error NotModelOwner(uint256 modelId, address caller);
    error ModelDeprecated(uint256 modelId);

    function registerModel(ModelCommitment calldata commitment)
        external
        returns (uint256 modelId);

    function updateModel(uint256 modelId, ModelCommitment calldata newCommitment)
        external;

    function deprecateModel(uint256 modelId) external;

    function getModel(uint256 modelId)
        external
        view
        returns (ModelCommitment memory commitment, bool deprecated, address owner);
}
```
- `registerModel` MUST return a unique `modelId`.
- `updateModel` and `deprecateModel` MUST only be callable by the model `owner`.
-	`getModel` MUST return the current `commitment`, deprecation status, and `owner` address.
-	Implementations MAY allow versioning under one `modelId` or require a new `modelId` per change. The chosen policy MUST be documented.

#### ZKML Verifier

``` solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.20;

interface IERCZKMLVerifier /* is IERC165 */ {
    event InferenceVerified(
        uint256 indexed modelId,
        bytes32 indexed inputCommitment,
        bytes   output,
        address indexed caller
    );

    error InvalidProof();
    error ModelMismatch();            // proof verifies but not tied to given modelId
    error InputCommitmentMismatch();
    error OutputMismatch();           // if verifier checks output commitment/schema
    error UnsupportedProofSystem(bytes4 proofSystemId);
    error VerificationRefused_ModelDeprecated(uint256 modelId);

    /**
     * @notice Verifies a ZK proof for an inference.
     * @dev MUST revert on any failure path. Successful execution implies validity.
     * @param modelId         Registry model identifier
     * @param inputCommitment Commitment to private inputs
     * @param output          ABI-encoded public outputs
     * @param proof           ZK proof bytes
     */
    function verifyInference(
        uint256 modelId,
        bytes32 inputCommitment,
        bytes calldata output,
        bytes calldata proof
    ) external;

    /// Optional helper views:
    function proofSystemOf(uint256 modelId) external view returns (bytes4);
    function registry() external view returns (address registryAddress);
}
```
The `verifyInference`:

- MUST fetch the model `commitment` from the registry and validate the `proof` against it.
-	MUST revert on any failure (invalid proof, mismatched commitments, unsupported proof system, deprecated model, etc.).
-	SHOULD emit  `InferenceVerified` on success.
-	SHOULD remain stateless except for emitting events. Statefulness MAY be introduced by extensions.

#### Optional Storage Extension 

``` solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.20;

interface IERCZKMLStorageExtension {
    event InferenceStored(bytes32 indexed inferenceId);

    /**
     * @notice Verify and store an inference record.
     * @dev MUST revert on invalid proof.
     * @return inferenceId keccak256(abi.encodePacked(modelId, inputCommitment, output))
     */
    function verifyAndStoreInference(
        uint256 modelId,
        bytes32 inputCommitment,
        bytes calldata output,
        bytes calldata proof
    ) external returns (bytes32 inferenceId);

    function getInference(bytes32 inferenceId)
        external
        view
        returns (uint256 modelId, bytes32 inputCommitment, bytes memory output);
}
```

Replay Protection Note: Implementations that rely on 
`inferenceId = keccak256(modelId, inputCommitment, output)` 
MUST ensure that `inputCommitment` embeds a `nonce/salt` or other uniqueness source 
if replays are a concern (e.g., non-deterministic models or single-use inferences).

The registry interface exposes an `owner` per `modelId`. 
Implementations MUST include some ownership/access-control mechanism 
(e.g., simple owner storage, [ERC-173](/EIPs/EIPS/eip-173), [ERC-721](/EIPs/EIPS/eip-173) representation, or role-based control). 
The returned `owner` address SHOULD be treated as the canonical authority to mutate or deprecate that model.


## Rationale

-	Void Return on `verifyInference`: Reverting on failure and returning nothing on success removes redundant gas-expensive booleans and matches modern Solidity patterns (e.g., OpenZeppelin’s `SafeERC20`).
-	Separated Registry &amp; Verifier: Encourages modularity—teams can upgrade verifiers or registries independently.
-	Opaque bytes for Proof/Output: Avoids lock-in to a specific proof system or output schema.
-	Deterministic `proofSystemId`: Prevents collisions and ambiguity; enables predictable dispatch in mixed-system verifiers.
-	Nonce in `inputCommitment`: Explicitly mitigates replay attacks when inference uniqueness matters.


## Backwards Compatibility

Fully backwards compatible:

- Uses [ERC-165](/EIPs/EIPS/eip-165) like popular [ERC-721](/EIPs/EIPS/eip-721) or [ERC-1155](/EIPs/EIPS/eip-1155) for discoverability.
- No dependency on token ownership standards; minimal collision with existing protocols.

## Reference Implementation

``` solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.20;

import &quot;./IERCZKMLRegistry.sol&quot;;
import &quot;./IERCZKMLVerifier.sol&quot;;

contract ZKMLVerifier is IERCZKMLVerifier {
    IERCZKMLRegistry public immutable override registry;

    constructor(IERCZKMLRegistry _registry) {
        registry = _registry;
    }

    function verifyInference(
        uint256 modelId,
        bytes32 inputCommitment,
        bytes calldata output,
        bytes calldata proof
    ) external override {
        (IERCZKMLRegistry.ModelCommitment memory cm, bool deprecated,) =
            registry.getModel(modelId);

        if (deprecated) revert ModelDeprecated(modelId);

        // Dispatch based on proofSystemId. Example only.
        // bool ok = VerifierLib.verify(proof, cm.vkHash, inputCommitment, output);
        bool ok = _dummyVerify(proof, cm.vkHash, inputCommitment, output);
        if (!ok) revert InvalidProof();

        emit InferenceVerified(modelId, inputCommitment, output, msg.sender);
    }

    function proofSystemOf(uint256 modelId) external view override returns (bytes4) {
        (IERCZKMLRegistry.ModelCommitment memory cm,,) = registry.getModel(modelId);
        return cm.proofSystemId;
    }

    function _dummyVerify(
        bytes calldata,
        bytes32,
        bytes32,
        bytes calldata
    ) private pure returns (bool) {
        return true;
    }
}
```


## Security Considerations

### Security

&lt;!-- Editor&apos;s Note: any requirements (defined with UPPERCASE keywords) should go in the specification section, but they should be discussed here in more detail. --&gt;

- Replay Attacks: Inputs must embed a nonce/salt where uniqueness matters. Contracts may also track consumed `inferenceIds`.
-	Model Commitment Drift: Updating commitments can invalidate proofs; consumers should pin specific `modelId` + `commitment` hashes or check deprecated.
-	Hash Domain Separation: Use distinct prefixes (e.g., &quot;ZKML_MODEL_V1&quot;) to avoid collisions across contexts.
-	Output Ambiguity: Contracts must validate or commit to output schemas to avoid maliciously crafted bytes.
-	DoS via Heavy Verification: Consider off-chain verification with on-chain succinct attestations, or batching/aggregation.

### Gas

- Proof verification can dominate gas costs; splitting verification-only calls from storage writes lets integrators choose.
-	Events are cheaper than persistent storage for audit trails.


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Wed, 23 Jul 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7992</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7992</guid>
      </item>
    
      <item>
        <title>Purpose-Bound ERC-20 with Conditional Unlock</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7994-purpose-bound-erc20-with-multi-condition-unlocking-extension-of-eip-7291/24945</comments>
        
        <description>## Abstract

This ERC extends the concept introduced in [ERC-7291] by enabling [ERC-20]-compatible tokens to carry multi-condition unlocking constraints, combining temporal, identity, and usage restrictions into a programmable structure. It aims to support controlled disbursement of tokens where funds are only accessible under predefined, auditable, and verifiable conditions.

## Motivation

ERC-7291 introduced purpose-bound money by restricting how and where tokens can be spent. However, many real-world applications require multiple conditions to be satisfied simultaneously before tokens can be used. Examples include:

 - Scholarships requiring the recipient to be KYC-verified, under 25 years of age, and registered at a university.
 - NGO aid to be used only for food and medicine, after a specific unlock date.
 - Payroll tokens that unlock monthly and only for whitelisted vendors (e.g., banks, healthcare providers).

This proposal generalizes and formalizes such use cases by layering unlocking conditions on top of the ERC-20 standard.

## Specification

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.

### Interface

The `IPurposeBoundERC20` interface defines the standard for programmable token transfers that are conditional. Each transfer, referred to as a *purpose binding*, includes:

- A `recipient` and `amount`.
- A set of `UnlockCondition` objects, each consisting of a `conditionType` (like `&quot;TIME&quot;`, `&quot;KYC&quot;`, or `&quot;WHITELIST&quot;`) and `conditionData` used to evaluate the condition.
- An optional `expiry` timestamp after which the transfer can no longer be claimed.

The interface provides the following functions:
- `bindPurpose(...)`: Locks a specified amount of tokens to a recipient with defined conditions.
- `claim(...)`: Allows the recipient to claim the tokens once all conditions are fulfilled.
- `isUnlocked(...)`: Returns whether all associated conditions have been satisfied.

This enables flexible, composable transfer mechanisms for various use cases including compliance, grants, payroll, and more.

```solidity
pragma solidity 0.8.23;

interface IPurposeBoundERC20 {
    struct UnlockCondition {
        bytes32 conditionType; // e.g., &quot;TIME&quot;, &quot;KYC&quot;, &quot;WHITELIST&quot;
        bytes conditionData;   // e.g., timestamp, Merkle root, etc.
    }

    function bindPurpose(
        address recipient,
        uint256 amount,
        UnlockCondition[] calldata conditions,
        uint256 expiry
    ) external returns (bytes32 bindingId);

    function claim(bytes32 bindingId) external;

    function isUnlocked(bytes32 bindingId) external view returns (bool);
}
```

## Rationale

Flexibility: Conditions are modular and extensible.

Composability: Can be integrated into DAOs, payroll, education, and compliance tokens.

Security: Off-chain verification (e.g., KYC) backed by on-chain proofs (e.g., Merkle roots).

## Reference Implementation

```solidity
pragma solidity 0.8.23;

/// @title Reference Implementation - Purpose-Bound ERC20 with Multi-Condition Unlocking
/// @notice Implements IPurposeBoundERC20 with conditionType mapping to on-chain checkers.

import &quot;@openzeppelin/contracts/token/ERC20/ERC20.sol&quot;;
import &quot;./IPurposeBoundERC20.sol&quot;;

/// @dev Interface for pluggable condition checker contracts
interface IConditionChecker {
    function isConditionMet(address recipient, bytes calldata conditionData) external view returns (bool);
}

/// @title PurposeBoundERC20 Implementation
contract PurposeBoundERC20 is ERC20, IPurposeBoundERC20 {
    struct StoredBinding {
        address recipient;
        uint256 amount;
        UnlockCondition[] conditions;
        bool claimed;
        uint256 expiry;
    }

    /// @dev Maps conditionType → on-chain checker contract
    mapping(bytes32 =&gt; address) public conditionResolvers;

    /// @dev Maps bindingId → locked transfer
    mapping(bytes32 =&gt; StoredBinding) public boundTransfers;

    event PurposeBound(bytes32 indexed bindingId, address indexed from, address indexed to, uint256 amount);
    event Claimed(bytes32 indexed bindingId, address indexed recipient);

    constructor(string memory name_, string memory symbol_) ERC20(name_, symbol_) {
        _mint(msg.sender, 1_000_000 ether); // for demo purposes
    }

    /// @notice Admin can register or update condition checkers for condition types
    function setConditionResolver(bytes32 conditionType, address checker) external {
        // For demo purposes: public function. In production: onlyOwner or AccessControl.
        conditionResolvers[conditionType] = checker;
    }

    /// @inheritdoc IPurposeBoundERC20
    function bindPurpose(
        address recipient,
        uint256 amount,
        UnlockCondition[] calldata conditions,
        uint256 expiry
    ) external override returns (bytes32 bindingId) {
        require(recipient != address(0), &quot;Invalid recipient&quot;);
        require(amount &gt; 0, &quot;Invalid amount&quot;);

        bindingId = keccak256(abi.encodePacked(msg.sender, recipient, amount, conditions, expiry, block.timestamp));
        StoredBinding storage stored = boundTransfers[bindingId];
        require(stored.amount == 0, &quot;Binding exists&quot;);

        _transfer(msg.sender, address(this), amount);

        for (uint i = 0; i &lt; conditions.length; i++) {
            stored.conditions.push(conditions[i]);
        }

        stored.recipient = recipient;
        stored.amount = amount;
        stored.expiry = expiry;

        emit PurposeBound(bindingId, msg.sender, recipient, amount);
    }

    /// @inheritdoc IPurposeBoundERC20
    function isUnlocked(bytes32 bindingId) public view override returns (bool) {
        StoredBinding storage binding = boundTransfers[bindingId];
        if (binding.claimed) return false;
        if (binding.expiry &gt; 0 &amp;&amp; block.timestamp &gt; binding.expiry) return false;

        for (uint i = 0; i &lt; binding.conditions.length; i++) {
            UnlockCondition storage cond = binding.conditions[i];
            address checker = conditionResolvers[cond.conditionType];
            require(checker != address(0), &quot;Checker not set&quot;);
            if (!IConditionChecker(checker).isConditionMet(binding.recipient, cond.conditionData)) {
                return false;
            }
        }

        return true;
    }

    /// @inheritdoc IPurposeBoundERC20
    function claim(bytes32 bindingId) external override {
        StoredBinding storage binding = boundTransfers[bindingId];
        require(msg.sender == binding.recipient, &quot;Not recipient&quot;);
        require(!binding.claimed, &quot;Already claimed&quot;);
        require(isUnlocked(bindingId), &quot;Conditions not met&quot;);

        binding.claimed = true;
        _transfer(address(this), binding.recipient, binding.amount);

        emit Claimed(bindingId, binding.recipient);
    }
}

/// @dev Example of Time-Based Condition Checker
contract TimeConditionChecker is IConditionChecker {
    function isConditionMet(address, bytes calldata conditionData) external view override returns (bool) {
        uint256 unlockTime = abi.decode(conditionData, (uint256));
        return block.timestamp &gt;= unlockTime;
    }
}
```

## Security Considerations

Condition-checking mechanisms (e.g., Merkle roots, timestamps) must be secure against tampering.

The `claim()` function must ensure atomic verification of all conditions.

Replay attacks must be mitigated using unique binding IDs and expiration fields.


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[ERC-20]: /EIPs/EIPS/eip-20

[ERC-7291]: /EIPs/EIPS/eip-7291
</description>
        <pubDate>Tue, 29 Jul 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7994</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7994</guid>
      </item>
    
      <item>
        <title>Contract Feature Detection</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-7996-contract-feature-detection/24975</comments>
        
        <description>## Abstract

Creates a standard method `supportsFeature(bytes4)` in the same spirit as `supportsInterface(bytes4)` to publish and detect what features a smart contract implements that lack a derivable [ERC-165](/EIPs/EIPS/eip-165) interface.

## Motivation

Ethereum Name Service (ENS) has maintained backwards compatibility with contracts created in 2016 through extensive use of ERC-165.  Unfortunately, not all contract capabilities can be expressed through an unique interface.

Features allow expression of contract capabilities that preserve existing interfaces.  This proposal standardizes the concept of features and standardizes the identification (naming) of features.

Defining a new standard avoids unnecessary pollution of the ERC-165 selector namespace with synthetic interfaces representing features.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

### How Features are Identified

For this standard, a *feature* is any property of a contract that cannot be expressed via ERC-165.

A feature name SHOULD be a reverse domain name that uniquely defines its implication, eg. `eth.ens.resolver.extended.multicall` is the multicall feature for an extended ENS resolver contract.

A feature identifier is defined as the first four-bytes of the keccak256-hash of its name, eg. `bytes4(keccak256(&quot;eth.ens.resolver.extended.multicall&quot;)) = 0x96b62db8`.

### How a Contract will Publish the Features it Implements

A contract that is compliant with this specification SHALL implement the following interface:

```solidity
interface IERC7996 {
    /// @notice Check if a feature is supported.
    /// @param featureId The feature identifier.
    /// @return `true` if the feature is supported by the contract.
    function supportsFeature(bytes4 featureId) external view returns (bool);
}
```

The ERC-165 interface identifier for this interface is `0x582de3e7`.

### How to Detect if a Contract Implements Features

1. Check if the contract supports the interface above according to [ERC-165](/EIPs/EIPS/eip-165#how-to-detect-if-a-contract-implements-erc-165).

### How to Detect if a Contract Implements any Given Feature

1. If you are not sure if the contract implements features, use the above procedure to confirm.
1. If it implements features, then call `supportsFeature(featureId)` to determine if it implements the desired feature.

Note: a contract that implements features MAY implement no features.

## Rationale

Since feature names cannot be derived from a contract interface, they are derived from a reverse domain name to reduce collisions and permit a human-readable representention that briefly describes its implication.

## Backwards Compatibility

Callers unaware of features or any specific feature experience no change in behavior.

ENS already implements this ERC.

## Security Considerations

As with ERC-165, declaring support for a feature does not guarantee that the contract implements it.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 07 Jul 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7996</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7996</guid>
      </item>
    
      <item>
        <title>Deterministic Factory Predeploy</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7997-deterministic-factory-predeploy/24998</comments>
        
        <description>## Abstract

A minimal `CREATE2` factory is inserted as a system contract in the precompile range, 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.

## Motivation

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&apos;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, a setup which we will call *multi-chain deterministic deployment*.

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).

This kind of deployment is also highly desirable and important for account abstraction. Without it, a user&apos;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.

There is currently no native or fully robust way to perform multi-chain deterministic deployments. While `CREATE2` enables deterministic deployments, the created address is computed from that of the contract that invokes the instruction, so a *factory* that is itself multi-chain is required for bootstrapping. Four workarounds are currently known to deploy such a factory, each with their own issues:

1. A keyless transaction is crafted using Nick&apos;s method that can be posted permissionlessly to new chains. For this to work, the chain must support legacy transactions without [EIP-155](/EIPs/EIPS/eip-155) replay protection, and the fixed gas price and gas limit must be sufficiently high, but not so high as to exceed the limits of the chain.
2. Private keys held by some party are used to sign creation transactions for each chain as needed. This creates a dependency on that party, does not provide a hard guarantee that the factory will be available on every chain, and can also irreversibly fail if transactions are not properly parameterized.
3. A private key is intentionally leaked so that any party can permissionlessly create an [EIP-7702](/EIPs/EIPS/eip-7702) signed delegation and deploy a factory from the leaked account. While this approach improves on the previous two, its reliance on ECDSA keys makes it non-quantum-resistant, and will fail once chains stop supporting ECDSA keys. Additionally, it requires EIP-7702, an orthogonal feature which is not guaranteed to spread to all chains; for example, those chains that tackle account abstraction through other means have no use for it, and arguably weaker ecosystem pressure to implement it (compared to other EIPs) given that it is a feature not directly used by applications (which instead access AA capabilities through an abstraction like [EIP-5792](/EIPs/EIPS/eip-5792)). Lastly, there is a possibility that a future upgrade allows EIP-7702 delegations to become permanent, which breaks this scheme.
4. Factories already deployed on other chains (by any of the previous methods) are inserted in a new chain at genesis or via a hard fork. This has not been widely adopted by chains, despite the standardization efforts of RIP-7740. Since these factories are applications deployed by users through normal means, this kind of hardcoding of accounts may be seen by chain developers as too intrusive.

This EIP aims to coordinate a widely available multi-chain `CREATE2` factory without the above downsides by placing a factory in the precompile range.

## Specification

### Parameters

* `FACTORY_ADDRESS` = `0x12`

### Factory Contract

Upon activation of this EIP, the account at `FACTORY_ADDRESS` becomes a contract that, when called, invokes the `CREATE2` instruction ([EIP-1014](/EIPs/EIPS/eip-1014)) with a salt equal to the first 32 bytes of the call&apos;s input data, init code equal to the remaining data, and value equal to the call&apos;s value. If input data is smaller than 32 bytes, the call reverts with empty return data. If creation fails (`CREATE2` outputs `0`), the call reverts with return data equal to that of the creation frame.

Specifically, the code of `FACTORY_ADDRESS` is set to `60203610602f5760003560203603806020600037600034f5806026573d600060003e3d6000fd5b60005260206000f35b60006000fd`. This code implements the specification above and corresponds to the following assembly:

```
#pragma target &quot;constantinople&quot;

;; Input: salt (32 bytes) || initcode (variable size)

;; Verify input is at least 32 bytes long.
push 32
calldatasize
lt
jumpi @throw

;; Load salt.
push 0
calldataload

;; Compute initcodesize = calldatasize - 32.
push 32
calldatasize
sub

;; Copy initcode to memory at position 0.
dup1
push 32
push 0
calldatacopy

;; Invoke create2 with salt and initcode, forwarding all callvalue.
push 0
callvalue
create2

;; Check if create2 produced nonzero.
dup1
push @success
jumpi

;; Fallthrough if zero, and revert with identical returndata.
returndatasize
push 0
push 0
returndatacopy
returndatasize
push 0
revert

;; On success, return the created address.
success:
push 0
mstore
push 32
push 0
return

throw:
push 0
push 0
revert
```

## Rationale

### Precompile-range system contract

Unlike previous system contracts, this factory cannot be deployed using a normal transaction because, as explained in the Motivation section, that transaction could not be guaranteed to be valid on other chains. Since the purpose of this factory is to be available in all EVM chains that a contract could be deployed to, an irregular insertion of the code into a special address seems necessary.

The address `0x12` (`0x0000000000000000000000000000000000000012`) is chosen as the next lowest address after currently accepted precompiles, on the assumption that other EVM chains would have reserved this range for future Ethereum precompiles.

### Input validation

The factory reverts if the input is smaller than 32 bytes, the minimum size that contains the salt, to provide an explicit error when the factory is not correctly invoked.

### No frontrunning protection

As explained in the Security Considerations, deployments using this factory can potentially be frontrun.

A different factory could avoid this issue if it invokes `CREATE2` with a salt computed from the caller address in combination with the caller-provided salt input. This prevents frontrunning, but makes deployments permissioned to a deployer account, without the ability to recover permissionless deployments across chains because of the bootstrapping problem this EIP is itself meant to solve.

A factory could also support both permissioned and permissionless deployments by making the mechanism opt-in. However, the addition of this complexity to an otherwise very simple contract was deemed unnecessary, since once the bootstrapping problem is solved, further factories with a more comprehensive set of features and security measures can be deterministically deployed across chains. We expect this to be the case.

### Not a new transaction type

An alternative approach would consist of a new creation transaction type where the address of the created contract is computed in a way independent of the transaction origin. A system contract was considered a simpler approach that will be more robust to changes in the base layer in the future or across chains.

### Constantinople target, avoidance of `PUSH0`

The system contract is written to avoid the use of newer opcodes such as `PUSH0` to make it viable to be adopted by chains that don&apos;t yet support them, decoupling the decision to adopt this EIP from that of adopting other EIPs.

## Backwards Compatibility

`FACTORY_ADDRESS` must not be used by other precompiles or predeploys upon activation of this EIP on a chain. The constant must be chosen to minimize likelihood that this happens.

## Test Cases

&lt;!-- TODO --&gt;
TBD

## Security Considerations

### Frontrunnable deployments

The deployment of contracts that read the environment (`ORIGIN`, `NUMBER`, etc.) may be frontrun and created with attacker-chosen parameters. It&apos;s recommended to use this factory to deploy fully deterministic contracts only.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Turn `randao_reveal` into a VRF</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7998-turn-randao-reveal-into-a-vrf/24999</comments>
        
        <description>## Abstract

This EIP proposes a modification to the data signed by a block proposer for the `randao_reveal`. The current `randao_reveal` is a BLS signature over the current epoch number, which is predictable. This proposal incorporates the RANDAO mix of the previous epoch and the current slot number into the signed data. This change transforms the `randao_reveal` into a Verifiable Random Function (VRF), making it unpredictable across epochs even for the revealer itself. This enhancement strengthens Ethereum&apos;s native randomness source and enables protocols such as Single Secret Leader Election (SSLE).

## Motivation

This change creates a secure, per-slot VRF output from the proposer, with several benefits:

1. it **paves the way for secret proposer election**, which would in turn reduce MEV and completely eliminate the well-known RANDAO bias attack vector;
2. it supports other proposals like [EIP-7956](/EIPs/EIPS/eip-7956) that rely on a source of verifiable randomness.

Using a BLS signature as a VRF is sound under the Computational Diffie-Hellman (CDH) assumption, rather than Decisional Diffie-Hellman. The BLS verification process inherently proves the correctness of the VRF output without requiring a separate proof.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

The gist of the change is in `process_randao`, which now uses the RANDAO mix of the previous epoch and the current slot number to seed the `randao_reveal` signature. We are introducing a new SSZ-serializable container called `RandaoRevealSeed` containing that information.

### New SSZ Container

A new SSZ `Container` is introduced to serve as the message for the `randao_reveal` signature post-fork.

```python
class RandaoRevealSeed(Container):
    previous_mix: Bytes32  # last RANDAO mix of the previous epoch
    slot: Slot             # current slot number
```

### Modified `process_randao`

The block processing function `process_randao` in the beacon state transition is modified.

Let `FORK_EPOCH` be the epoch of the network upgrade.

The logic for verifying `body.randao_reveal` within `process_randao` is updated as follows:

```python
def process_randao(state: BeaconState, body: BeaconBlockBody) -&gt; None:
    epoch = get_current_epoch(state)
    # Verify RANDAO reveal
    proposer = state.validators[get_beacon_proposer_index(state)]
    if epoch &lt; FORK_EPOCH:
        signing_root = compute_signing_root(epoch, get_domain(state, DOMAIN_RANDAO))
    else:
        previous_epoch = get_previous_epoch(state)
        previous_mix = get_randao_mix(state, previous_epoch)
        seed = RandaoRevealSeed(previous_mix, state.slot)
        signing_root = compute_signing_root(seed, get_domain(state, DOMAIN_RANDAO))
    assert bls.Verify(proposer.pubkey, signing_root, body.randao_reveal)
    # Mix in RANDAO reveal
    mix = xor(get_randao_mix(state, epoch), hash(body.randao_reveal))
    state.randao_mixes[epoch % EPOCHS_PER_HISTORICAL_VECTOR] = mix
```

## Rationale

### Choice of VRF Input

The `randao_reveal` is effectively transformed into `VRF(sk, message)` where the `message` is the SSZ serialization of the `RandaoRevealSeed` container.

- `previous_mix`: Including the RANDAO mix from the previous epoch (`previous_mix`) is the core of this proposal. Since the previous epoch&apos;s final mix is not known until the end of that epoch, a proposer cannot compute their `randao_reveal` of future epochs, beforehand.
- `slot`: Including the current `slot` number ensures that the `randao_reveal` is unique for each slot and unpredictable to other validators. Without it, a validator chosen to propose multiple times in an epoch would produce the same reveal, which is undesirable for protocols that require unique randomness per instance, such as SSLE.

### Alternatives Considered

We considered adding the _latest_ RANDAO mix rather than that from the previous epoch so that we could obtain per-slot unpredictability, but that would cause fork ambiguity in the future if `randao_reveal` is used to implement SSLE.

## Backwards Compatibility

This EIP introduces a backwards-incompatible change to the consensus rules and MUST be activated as part of a scheduled network upgrade (i.e., a hard fork).

Blocks produced after the `FORK_EPOCH` that do not use the new `RandaoRevealSeed` structure for the `randao_reveal` signature SHALL be considered invalid. Pre-fork blocks remain valid under the old rules.

## Security Considerations

### VRF Security

The security of the BLS signature scheme as a VRF relies on the Computational Diffie-Hellman (CDH) assumption in the target group. This is a standard cryptographic assumption. The output of the signature (a uniformly distributed G2 point in compressed format) can be treated as a pseudorandom number.

### Grinding

The value of `randao_reveal` is deterministic and cannot be manipulated. It will be verified with the public BLS key of the validator, so it must be calculated using the corresponding private key. There are no grindable elements.

### Slot-by-slot Unpredictability

Including the slot number is superfluous at the moment because it does not make the VRF slot-by-slot unpredictable to the revealer, only to other validators. But it will become critical in the future if and when we decide to implement secret proposer election and/or EIP-7956.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 03 Aug 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7998</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7998</guid>
      </item>
    
      <item>
        <title>Unified multidimensional fee market</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-7999-unified-multidimensional-fee-market/25010</comments>
        
        <description>## Abstract

A unified multidimensional fee market is introduced, where each transaction specifies the maximum amount of ETH it is willing to pay for inclusion using a single `max_fee`. Upon inclusion, the protocol ensures that the transaction is able to pay the gas for all dimensions, treating the `max_fee` as fungible across resources. This enables a more efficient use of capital, and enshrines the same representation that users have when they interact with Ethereum. The fee market is further unified in terms of a single update fraction under a single fee update mechanism, generalized reserve pricing, and a gas normalization that retains current percentage ranges while keeping the price stable whenever a gas limit changes. Calldata is proposed as the first resource to be added, with avenues for facilitating gas fungibility for EVM resources considered for further expansion.

## Motivation

A multidimensional fee market enables precise control over resource consumption. It allows *the market* to fairly price resources according to targets and limits deemed safe by developers, and it allows resources to be consumed at maximum capacity within these limits. Directly expanding the current fee market design to the multidimensional setting can however have negative effects on the user experience (UX) and on economic efficiency. Users are forced to set a `max_fee_per_gas` for each resource, where a too low allocation in any dimension can render the transaction ineligible.

This EIP leverages the natural fungibility of the user&apos;s fee budget by letting users set a single unified `max_fee`. Instead of using non-fungible per-resource budgets, the single ETH budget can then be allocated dynamically to cover costs wherever they arise, ensuring a more efficient use of capital. Users will be able to specify a lower `max_fee` than the implied aggregate maximum unless all base fees are perfectly correlated (which reduces to the current design), because they do not need to buffer for spurious price movements in a single resource dimension.

Ethereum&apos;s current fee market has &quot;tech debt&quot; in that two separate mechanisms are used: one for regular gas ([EIP-1559](/EIPs/EIPS/eip-1559)) and the other for blob gas ([EIP-4844](/EIPs/EIPS/eip-4844)). The proposal unifies the fee market under the preferred EIP-4844 design. That design allows for exact control over long-run resource consumption. In a multidimensional setting with individual base fees, we can then for example achieve precise control over state growth, while accommodating temporary spikes. Excess gas of EIP-4844 is further normalized relative to the limit, allowing for a single update fraction across resources that retains current percentage ranges while keeping the price stable if any gas limit changes. 

Calldata is added first, to speed up worst-case payload propagation and expand available EVM gas—without compromising gas introspection. A method for facilitating gas aggregation across resources within the EVM is outlined as an avenue for preserving backward compatibility when expanding further. The logic of EIP-7918 is integrated into the multidimensional setting to ensure that calldata has a higher cost per byte than blob data. 

## Specification

The specification inherits its logic from [EIP-7706](/EIPs/EIPS/eip-7706), incorporating the changes necessary for facilitating one aggregate fee, a multidimensional [EIP-7918](/EIPs/EIPS/eip-7918) logic, a systematic approach to [EIP-7805](/EIPs/EIPS/eip-7805), and a stable gas normalization function, etc.

### Parameters

| Constant | Value | Description |
| :--- | :--- | :--- |
| `MULTIDIM_TX_TYPE` | `TBD` &lt;!-- TODO --&gt; | Identifier for the new transaction type |
| `EVM_LIMIT_TARGET_RATIO` | `2` | Ratio of EVM gas target to EVM gas limit |
| `CALLDATA_GAS_PER_TOKEN` | `4` | Gas cost per token for calldata |
| `TOKENS_PER_NONZERO_BYTE` | `4` | Tokens per non-zero byte of calldata |
| `CALLDATA_GAS_LIMIT_RATIO` | `4` | Ratio of calldata limit to gas limit |
| `CALLDATA_LIMIT_TARGET_RATIO` | `4` | Ratio of calldata target to calldata limit |
| `GAS_RESERVE_FACTOR` | `[0, 16, 12]` | Factor by which the base fee can be below the baseline |
| `GAS_RESERVE_INDEX` | `[0, 0, 1]` | Index of the base fee to compare against |
| `MIN_BASE_FEE_PER_GAS` | `1` | Minimum base fee per gas unit |
| `GAS_NORMALIZATION_FACTOR` | `10**9` | Normalization factor for the delta excess gas |
| `BASE_FEE_UPDATE_FRACTION` | `4_245_093_508` | ≈ `GAS_NORMALIZATION_FACTOR / (2 * ln(1.125))` |

### New transaction type

Upon activation of this EIP via hard fork, a new [EIP-2718](/EIPs/EIPS/eip-2718) transaction is introduced with `TransactionType` = `MULTIDIM_TX_TYPE`.

The [EIP-2718](/EIPs/EIPS/eip-2718) `TransactionPayload` for this transaction is

```
[chain_id, nonce, gas_limit, to, value, data, access_list, blob_versioned_hashes, max_fee, max_priority_fee_per_gas, y_parity, r, s]
```

We require `max_fee` to be a scalar integer from `0` to `2**128-1` and `max_priority_fee_per_gas` to be a list of integers from `0` to `2**64-1`, either of length 1 or with the same length as the number of resources (initially 3). The `gas_limit` is initially specified only for the main EVM gas, since other limits can be inferred from the transaction. To facilitate further expansion, the Python spec uses a list with a single element at index 0. Each added integer will range from `0` to `2**64-1`.

The intrinsic cost of the new transaction is inherited from EIP-4844, except that the calldata gas cost (16 per non-zero byte, 4 per zero byte) is removed.

### Block processing and transaction fees

Helpers for vector operations:

```python
def all_less_or_equal(v1: [int, int, int], v2: [int, int, int]) -&gt; bool:
    return all(x &lt;= y for x, y in zip(v1, v2))

def vector_add(v1: [int, int, int], v2: [int, int, int]) -&gt; [int, int, int]:
    return [x+y for x, y in zip(v1, v2)]

def vector_mul(v1: [int, int, int], v2: [int, int, int]) -&gt; [int, int, int]:
    return [x*y for x, y in zip(v1, v2)]
```

Helper functions for computing scalar max fees/priority fees for all transaction types:

```python
def get_max_fee(tx: Transaction) -&gt; int:
    if tx.type == MULTIDIM_TX_TYPE: # New tx type already has a max_fee
        return tx.max_fee
    elif tx.type == BLOB_TX_TYPE: # Account for blobs in blob txs
        blob_gas = len(tx.blob_versioned_hashes) * GAS_PER_BLOB
        return tx.max_fee_per_gas*tx.gas_limit + tx.max_fee_per_blob_gas*blob_gas
    elif is_eip_1559(tx.type): # EIP-1559 txs have no blobs
        return tx.max_fee_per_gas * tx.gas_limit
    else: # Legacy transactions have a gasprice
        return tx.gasprice * tx.gas_limit
```

```python
def get_priority_fee(tx, gas: list[int], base_fees: list[int], remaining_fee: int) -&gt; int:
    # Precalculate total gas and fees for non-blob resources
    tip_indices = [0, 2]
    tgas = sum(gas[i] for i in tip_indices)
    tfee = sum(gas[i] * base_fees[i] for i in tip_indices)

    if tx.type == MULTIDIM_TX_TYPE: # New tx type: Single tip or full vector of tips
        if len(tx.max_priority_fee_per_gas) == 1:
            tmax_fee = tx.max_fee - gas[1] * base_fees[1]  # Ignore blobs (as now)
            tpriority_fee = tmax_fee - tfee if tmax_fee &gt; tfee else 0
            max_priority_fee = min(tx.max_priority_fee_per_gas[0] * tgas, tpriority_fee)
        else:
            max_priority_fee = sum(vector_mul(tx.max_priority_fee_per_gas, gas))
        return min(max_priority_fee, remaining_fee)
    if is_legacy(tx.type): # Legacy tx: The remainder after base fees paid
        tmax_fee = tx.gasprice * tgas
        return tmax_fee - tfee if tmax_fee &gt; tfee else 0
    # EIP-1559 or Blob tx
    tmax_fee = tx.max_fee_per_gas * tgas
    tpriority_fee = tmax_fee - tfee if tmax_fee &gt; tfee else 0
    max_priority_fee = min(tx.max_priority_fee_per_gas * tgas, tpriority_fee)
    if tx.type == BLOB_TX_TYPE: # Clamp since blobs reduce the shared max_fee budget
        return min(max_priority_fee, remaining_fee)
    return max_priority_fee
```

The calldata resource pricing under this EIP follows previous gas per byte constants but deprecates the floor pricing specified in [EIP-7623](/EIPs/EIPS/eip-7623):

```python
def get_calldata_gas(calldata: bytes) -&gt; int:
    tokens = calldata.count(0) + (len(calldata) - calldata.count(0)) * TOKENS_PER_NONZERO_BYTE
    return tokens * CALLDATA_GAS_PER_TOKEN
```

The helper for calculating gas limits from EIP-7706 is adjusted to subtract calldata gas from the gas limit of old transactions:

```python
def get_gas_limits(tx: Transaction) -&gt; list[int]:
    calldata_gas = get_calldata_gas(tx.data)
    blob_gas = len(getattr(tx, &apos;blob_versioned_hashes&apos;, [])) * GAS_PER_BLOB
    if tx.type == MULTIDIM_TX_TYPE: # We use tx.gas_limit as is for new tx type
        return [tx.gas_limit, blob_gas, calldata_gas]
    else: # Partition old tx.gas_limit into its execution and calldata components.
        require(tx.gas_limit &gt;= calldata_gas)  
        execution_gas = tx.gas_limit - calldata_gas
        return [execution_gas, blob_gas, calldata_gas]
```

The calculation for the *required* `max_fee` to process the transaction is done in a separate function for easy future expansion:

```python
def get_required_max_fee(base_fees: list[int], tx_gas_limits: list[int]) -&gt; int:
    return sum(vector_mul(base_fees, tx_gas_limits))
```

**At the start of processing a block**:

  * initialize a vector `gas_used_so_far` to `[0, 0, 0]`,
  * derive the base fee `base_fees = get_block_base_fees(block.parent)`.

**At the start of processing a transaction**:

  * Derive basic properties of the tx: 
    * `max_fee = get_max_fee(tx)`, 
    * `tx_gas_limits = get_gas_limits(tx)`.
    * `max_base = get_required_max_fee(base_fees, tx_gas_limits)`
  * Require that 
    * `all_less_or_equal(vector_add(gas_used_so_far, tx_gas_limits), gas_limits)`. The block&apos;s `gas_limits` are defined in the next subsection.
    * `max_base &lt;= max_fee`
  * Compute the fees to deduct initially:
    * `max_priority_fee = get_priority_fee(tx, tx_gas_limits, base_fees, max_fee - max_base)`
    * `fee_to_deduct = max_base + max_priority_fee`
  * Deduct `fee_to_deduct` wei from the sender, which we define as the address recovered from the transaction’s signature. 

**At the end of processing a transaction**:

  * Compute `tx_gas_consumed` as a three-item vector, where the first item is the amount of execution gas actually consumed, and the second and third items are the blob and calldata gas amounts, which are equal to their limits from `tx_gas_limits`.
  * Burn `base_fee_paid = sum(vector_mul(base_fees, tx_gas_consumed))`.
  * Transfer to the coinbase `priority_fee_paid = get_priority_fee(tx, tx_gas_consumed, base_fees, fee_to_deduct - base_fee_paid)`
  * Refund the sender `fee_to_deduct - base_fee_paid - priority_fee_paid`.
  * Update `gas_used_so_far = vector_add(gas_used_so_far, tx_gas_consumed)`.

**At the end of processing a block**:

  * Require each element of `block.gas_used` (a vector field in the header) to equal the corresponding element in `gas_used_so_far`.

### Block structure

The `BlockHeader` is updated to remove the `blob_gas_used`, `gas_used`, `base_fee_per_gas`, `gas_limit` and `excess_blob_gas` fields, and the following new fields are added, all of the `[int, int, int]` type: `gas_limits`, `gas_used`, `excess_gas`. The header sequence of the new fields is `[..., withdrawals_root, gas_limits, gas_used, excess_gas]`.

We define the `gas_limits`

  * `gas_limits[0]` follows the existing adjustment formula based on the parent `gas_limits[0]`.
  * `gas_limits[1]` must equal `blobSchedule.max * GAS_PER_BLOB`
  * `gas_limits[2]` must equal `gas_limits[0] // CALLDATA_GAS_LIMIT_RATIO`.

and the `gas_targets`

  * `gas_targets[0]` must equal `gas_limits[0] // EVM_LIMIT_TARGET_RATIO`.
  * `gas_targets[1]` must equal `blobSchedule.target * GAS_PER_BLOB`.
  * `gas_targets[2]` must equal `gas_limits[2] // CALLDATA_LIMIT_TARGET_RATIO`.

The blobSchedule for referencing target and max blobs was introduced in [EIP-7840](/EIPs/EIPS/eip-7840).

### Gas accounting

We incorporate EIP-7918 to establish a dynamic reserve price for blob and calldata gas. When the market price for a resource drops below its reserve price, the mechanism for reducing its `excess_gas` (and thus lowering its base fee) is disabled. This leads the base fee to rise with usage until it meets the reserve price.

We normalize the running excess gas so that all resources operate at the same scale with the same `BASE_FEE_UPDATE_FRACTION`, which also provides a smoother response when any limit is adjusted. Division by `gas_limits[i]` upholds the same price changes stipulated in EIP-4844 and [EIP-7691](/EIPs/EIPS/eip-7691).

```python
def calc_excess_gas(parent: Header) -&gt; list[int]:
    base_fees = get_block_base_fees(parent)
    limits = parent.gas_limits
    targets = get_block_gas_targets(parent)

    new_excess = []
    for i in range(len(parent.excess_gas)):
        if (GAS_RESERVE_FACTOR[i] &gt; 0
                and base_fees[i] * GAS_RESERVE_FACTOR[i] &lt; base_fees[GAS_RESERVE_INDEX[i]]): 
            # EIP-7918 path. Excess gas rises with usage (up to limit), but cannot fall.
            delta = parent.gas_used[i] * (limits[i] - targets[i]) // limits[i]
            excess = parent.excess_gas[i] + delta * GAS_NORMALIZATION_FACTOR // limits[i]
        else:  # Regular path. Excess gas rises and falls with usage as normal
            if parent.gas_used[i] &gt;= targets[i]: # Add
                delta = parent.gas_used[i] - targets[i]
                excess = parent.excess_gas[i] + delta * GAS_NORMALIZATION_FACTOR // limits[i]
            else: # ..or subtract
                delta = targets[i] - parent.gas_used[i]
                deltan = delta * GAS_NORMALIZATION_FACTOR // limits[i]
                excess = 0 if parent.excess_gas[i] &lt; deltan else parent.excess_gas[i] - deltan
        new_excess.append(excess)  
    return new_excess
```

```python
def get_block_base_fees(parent: Header) -&gt; list[int]:
    return [
        fake_exponential(
            MIN_BASE_FEE_PER_GAS,
            excess,
            BASE_FEE_UPDATE_FRACTION
        )
        for excess in parent.excess_gas
    ]
```

### CALLDATABASEFEE instruction

We add a `CALLDATABASEFEE (0x4b)` instruction that returns the calldata base fee of the current block, following the same principles as specified in [EIP-7516](/EIPs/EIPS/eip-7516) for the blob base fee. 

| Op   | Input | Output | Cost |
|------|-------|--------|------|
| 0x4b | 0     | 1      | 2    |

### Censorship resistance

In EIP-7805, *includers* propose inclusion-list (IL) transactions that the block builder must include, subject to rules evaluated post-execution once remaining capacity is known. We define three resource types based on these rules:

* *Conditional resource* – An IL transaction consuming this resource *must be included* if the block has sufficient remaining capacity. If such a transaction is excluded, the block should not be accepted, unless the available space (`gas_limit[i] - gas_used[i]`) for at least one of its required conditional resources was insufficient to fit the transaction.
* *Unconditional resource* – An IL transaction consuming this resource *must be included* as long as sufficient capacity remains for all *conditional* resources it also uses. A lack of available capacity in the unconditional resource itself is *not* a valid reason for exclusion.
* *Deconditional resource* – An IL transaction consuming this resource *can always be excluded*, regardless of available capacity. For this reason, there is no incentive for includers to list such a transaction.

If EIP-7805 is implemented, it must: (i) continue to treat EVM gas as a conditional resource; (ii) continue to treat blob gas as a deconditional resource; (iii) treat calldata gas as an unconditional resource. Any transaction listed in an IL that consumes calldata and is excluded from the block, despite there being sufficient capacity in all conditional resources it uses, MUST produce an `INVALID_INCLUSION_LIST`.

## Rationale

### Why go multidimensional?

Many Ethereum resources such as blobs, calldata, access, and compute are in limited supply each block, constrained by the need to, e.g., timely propagate data or run computations. Upholding the constraints on all these resources via a single meta-resource—&quot;gas&quot;—limits developers&apos; ability to control both supply *and* demand. By going multidimensional, developers gain a more fine-grained control over the supply of each resource, preventing one from encroaching on the allotment for another. Resources can then be consumed at maximum capacity within each specified target and limit. With separate base fees for each resource, the market can come to an agreement on the appropriate price that leads to consumption at maximum capacity, given a specific user demand and aforementioned constraints on its supply. A multidimensional fee market is thus inherently a tool for scaling Ethereum.

### User experience

Ethereum currently uses `max_fee_per_gas` for EVM gas and `max_fee_per_blob_gas` for blob gas. A direct expansion of this approach is proposed in EIP-7706, with a vector of fees per gas for each resource. This may be considered unfortunate from a UX perspective, given that the vector will expand with expanding dimensionality. Our casual users tend to be moderately confused already by a single `max_fee_per_gas`. Most do not primarily think in terms of the individual prices for the resources that the transaction will consume. They think in terms of how much ETH they need to pay for their transactions (or in terms of dollars/fiat). A unified `max_fee` is in this context an improvement to UX. A unified `max_fee_per_gas` is possible, but might cause confusion in that the required gas price will differ from the base fees when using several resources—and thus also differ between transactions using different proportions of the resources.

When it comes to the priority fee, the optimal UX between using `max_priority_fee` and `max_priority_fee_per_gas` is a bit more nuanced. We decided to use `max_priority_fee_per_gas`. Ethereum already today unifies the priority fee for blob gas and regular gas under a single `max_priority_fee_per_gas`. It is thus natural to retain this representation, if only for removing friction for wallets. Furthermore, the priority fee should be determined from actual gas usage and not the gas limit. This is however perfectly possible when using `max_priority_fee` as well, because the max priority fee can be treated as proportional to the limit during processing, thus falling if less gas is consumed. 

Retaining `max_priority_fee_per_gas` can be considered slightly safer for users, in that they will never risk manually submitting a `max_priority_fee` for an old transaction type. Advanced users may wish to specify one priority fee per resource, to granularly pay according to usage when consuming below the gas limit. This ability was therefore preserved as an optional vector-based priority fee.

### Economic efficiency

Besides UX, resource-specific fee limits can also be unfortunate at a deeper economic level. Once a user has specified a `gas_limit` for any non-deterministic dimension, potentially with the assistance of their wallets, multiple separate `max_fee_per_gas` could exclude transactions that specify a sufficient aggregate fee, due to a drift in relative levels of the base fees. 

Consider a multidimensional transaction with a `gas_limit` vector $\mathbf{l} = (l_1, l_2,\dots, l_n)$, a `max_fee_per_gas` vector $\mathbf{f} = (f_1, f_2, \dots, f_n)$, and a `max_priority_fee_per_gas` vector $\mathbf{p} = (p_1, p_2, \dots, p_n)$. The consumed gas of the transaction is denoted $\mathbf{g} = (g_1, g_2, \dots, g_n)$, and the vector of base fees is denoted $\mathbf{b} = (b_1, b_2, \dots, b_n)$. The realized priority fee, after ensuring a sufficient base fee, is then

$p{\prime}_i = \min(p_i, f_i-b_i)$

for all resources $i$. Assume that when the transaction is submitted, the user specifies a `max_fee_per_gas` vector $\mathbf{f}$ such that all entries individually satisfy all base fee $\mathbf{b}$  criteria

$f_i \ge b_i \quad \text{for all resources } i.$

The gas limits also satisfy the actual gas consumption

$l_i \ge g_i \quad \text{for all resources } i.$

The `max_priority_fee_per_gas` vector $\mathbf{p}$ is also considered sufficient by many proposers, when they jointly weigh the reward against competing transactions using a weight vector $\mathbf{w}$, considering contention across relevant resources:

$\sum p{\prime}_i g_i \ge \sum w_i g_i.$

While not evaluated in the existing EIP, the base fees $\mathbf{b}$ could also be satisfied in aggregate against the max fees:

$\sum f_i l_i \ge \sum b_i l_i.$

Now assume that the base fee for any of the resources rapidly rises before the transaction is included, such that it becomes higher than the `max_fee_per_gas` in that dimension. In this scenario, the transaction can no longer be included. This may happen, even though the *aggregate* fees that the user is offering to pay, $\sum f_i l_i$, remain at a level above the aggregate fees that the protocol demands to execute it, $\sum b_i l_i$, just as initially. The aggregate priority fees may still also satisfy the proposer. The welfare loss consists of a user, a proposer, and a protocol willing to process a transaction, hamstrung by rigidity in the protocol design.

The analysis leads to the following conclusions, all of which apply with increasing emphasis the higher the dimensionality:

1. The UX would be simplified by one aggregate ETH fee.
2. The protocol would be best served by taking a single aggregate ETH fee from the user. 
3. The proposer already considers the aggregate impact when making its inclusion decision. 

Thus, the proposal is that the user specifies a single ETH `max_fee`. The protocol first ensures that the `max_fee` $F$ covers the base fee across gas limits in all dimensions, $F &gt; \sum b_i l_i$, and finally charges the minimum aggregate fee possible. The total fee paid to the protocol is thus the same as in the original multidimensional fee market design. The design is future-proof in that additional dimensions easily are incorporated, retaining the single `max_fee`.

### Priority fee

Considerations for the priority fee were already outlined in the UX section. Here, we first expand on why a vector `max_priority_fee_per_gas` *can* be beneficial to some users for fine-grained control, but not to most. The user has full control over the priority fee with a single input, as long as gas usage is deterministic across all resources. This input can be either `max_priority_fee` or `max_priority_fee_per_gas`—they are equivalent under deterministic gas usage. They are furthermore equivalent under any circumstances if the protocol makes sure to scale the `max_priority_fee` according to realized gas usage *relative* to the specified limit. Otherwise, the `max_priority_fee` will not be reduced when a transaction uses less gas than the limit (this is more often a drawback than a benefit for the user).

The priority fee a user wishes to provide per gas for a resource depends on the (likelihood of) contention across this resource. We can thus expect it to differ between resources. It follows from the principle of degrees of freedom that to gain full control over the transaction&apos;s priority fee, a user needs a separate parameter for each independent variable. When gas usage is non-deterministic in one resource—as today—the user needs two priority fees to achieve full granularity. When gas usage is non-deterministic in two resources (and their non-deterministic usage is not perfectly correlated), the user needs three priority fees, etc. 

It should here be noted that the required priority fee per gas for some resource cannot be directly ascertained from the priority fee per gas that has been stipulated for that resource in recent transactions. Assume that there are 10 resource and each transaction includes a vector stipulating `max_priority_fee_per_gas` for each. The builder will in its inclusion decision operate on the aggregate, and its requirements across dimensions can thus only be inferred, not observed directly. This means that per-resource estimates of required priority fees are not trivial, and most may still prefer the simplicity of a single one.

### Unified gas accounting, normalization, and reserve pricing mechanism

Ethereum currently uses two separate fee mechanisms, one for execution gas (EIP-1559) and one for blob gas (EIP-4844). This EIP unifies these mechanisms under the EIP-4844 standard, similar to EIP-7706 but with a few additions. We normalize the excess gas delta by dividing by the gas limit in `calc_excess_gas`, thus enabling all resources to operate under the same `BASE_FEE_UPDATE_FRACTION` while also keeping each fee fixed during a hard fork whenever a limit changes.

The reserve pricing mechanism from EIP-7918 is also generalized such that it can be applied to any resource, using another resource as an anchor. The mechanism imposes that if the base fee multiplied by `GAS_RESERVE_FACTOR` is less than the anchor base fee, the base fee cannot fall any further. Calldata uses blob data as an anchor to ensure that we do not charge less for calldata than blob data (see the separate section on the calldata resource for further details).

### Wallet fee estimation logic

To suggest a `max_fee`, the wallet first simulates the transaction to obtain an estimate of the required limit(s) $\mathbf{l}$. It then queries the network for the current vector of base fees $\mathbf{b}$. The expected total fee is $\sum b_i l_i$. The wallet recommends a `max_fee` that consists of this expected total cost plus a single buffer to account for aggregate volatility in base fees before the transaction is included. To suggest a `max_priority_fee_per_gas`, the wallet analyzes recent blocks to determine the priority fees that ensure timely inclusion. It focuses on priority fees paid by recently included transactions consuming a similar distribution of resources, as well as overall network contention.


### Block building

Historical data show that around 90% of blocks are below the gas limit. It is only when blocks are full that the builder is constrained in its block construction (disregarding timing games). Furthermore, a multidimensional knapsack problem only manifests in the event that a block is simultaneously full in multiple dimensions. Ignoring blobs, this is expected to be rare with the proposal, since calldata is assigned a limit four times above the target, which is already set higher than current consumption. The calldata limit is thus unlikely to be reached frequently. The blob dimension is a special case, in that this dimension already exists today, and the number of blob-carrying transactions is fairly low. Generally, the impact on revenue from sophisticated packing algorithms will likely be dwarfed by more significant MEV factors such as transaction ordering and private order flow.

### The calldata resource

#### Byte sizes

Calldata is separated into its own resource. With the proposed constants, at 60M execution gas, each block will on average contain `60M/(CALLDATA_GAS_LIMIT_RATIO * CALLDATA_LIMIT_TARGET_RATIO) = 3.75M` gas of calldata. Focusing on non-zero bytes that cannot be Snappy-compressed, this gas corresponds to around `3.75M/16 = 234kB`. The average block size has been around `90kB` at a 36M gas limit, which would expand to `150kB` at a 60M gas limit if the proportion of calldata in the block remains the same. Using basic assumptions, this proposal thus increases the amount of calldata that will be consumed by over 50%, from `150kB` to `234kB` at 60M gas. As pointed out in EIP-7706, this will serve to decrease the cost of calldata for our users. 

The limit is `60M/CALLDATA_GAS_LIMIT_RATIO = 15M` gas of calldata, corresponding to around `15M/16 = 938kB`. This is well below the limit under the current specification incorporating EIP‑7623, which is `60M/40 = 1.5MB` at 60M gas. Since calldata gas is also no longer accounted for as execution gas, the implied &quot;aggregate&quot; gas limit expands to `75M` gas, without materially affecting the maximum workload in terms of execution. In conclusion, the separation of calldata into its own resource increases calldata throughput while reducing costs. It furthermore facilitates scaling by allowing for faster payload propagation in the worst case and keeping all EVM gas available for other operations.

#### Censorship resistance

For censorship resistance (CR) purposes, under the currently proposed CR implementation EIP-7805, builders must include all transactions surfaced in any of the `16` inclusion lists (ILs) of each slot (each up to `8KiB`). However, if the block is full, builders can ignore the ILs, to not incentivize them to influence includers for MEV purposes.

When resources have separate limits, the block is treated as &quot;full&quot; already when any single conditional resource reaches its limit. Transactions that use that resource can then be excluded, even if they were surfaced by an IL. This makes it potentially cheaper to &quot;stuff the block&quot; to censor transactions. Specifically, a builder can create dummy transactions consuming a single resource to fill that dimension, ensuring that the block is treated as &quot;full&quot; when evaluating IL transactions. When resources have separate base fees, the builder may target a resource with a lower base fee, at a cost of roughly $b_i \cdot \Delta g_i$, where $\Delta g_i$ is the additional gas in resource $i$ required to reach its limit.

The good news is that calldata has properties allowing the builder to extract MEV while at the same time unconditionally adhering to its gas limit under EIP-7805. This means that this EIP does not impede censorship resistance. Specifically, in the case where all ILs are filled with disjoint transactions, the aggregate size of included transactions can still be at most `8KiB*16 = 131kB`. This leaves at the very minimum `938kB - 131kB = 807kB` of calldata for the builder to use as it sees fit when extracting MEV, which is sufficient according to the usage patterns we know.

Accordingly, calldata is treated as an &quot;unconditional&quot; resource, as defined in the specification. An includer MUST therefore signal `INVALID_INCLUSION_LIST` if—and only if—a calldata‑using IL transaction is omitted despite sufficient capacity remaining in all conditional resources it uses. When considering expansion into further resources with tighter conditional limits, it may be necessary to adopt a version of FOCIL with ranked transactions (FOCILR).

#### Reserve price

An EIP-7918 reserve price is used for calldata just as for blobs. This ensures that the equilibrium price does not fall to levels where the fee market update mechanism stops working satisfactorily. Furthermore, the expiry window for blobs is much shorter than the planned rolling expiry window for calldata, making a modest relative reserve price motivated from a resource preservation perspective. Finally, without a reserve price on calldata, it could become cheaper than blob data (particularly below the blob reserve price), and thus a rational choice for L2s. 

The latter rationale also motivates the specific parameterization chosen. The EIP-7918 reserve price per byte for calldata is set 1/3 above the price per byte for blob data. This is achieved by tying the EIP-7918 if clause to the *blob base fee*. The gas per byte is 16 for calldata and 1 for blob data, and the price floor is triggered when `base_fees[1] &gt; GAS_RESERVE_FACTOR[2] * base_fees[2]`. Given `GAS_RESERVE_FACTOR[2] = 12`, the EIP-7918 condition activates when the blob base fee is more than `12` times higher than the calldata base fee, at which point calldata costs less than `16/12 = 1+1/3` of the blob price per byte. The calldata base fee is then imposed to not fall further.

#### Relationship to previous EIPs and other resources

We acknowledge that calldata already has been limited by EIP-7623, with further repricings proposed in [EIP-7976](/EIPs/EIPS/eip-7976). These EIPs limit worst-case block sizes by metering and conditionally pricing calldata at the transaction level as opposed to at the block level, having the calldata price vary with a transaction&apos;s execution usage. This may lead to secondary markets if users wish to combine different transactions to take advantage of the &quot;rebate&quot; on calldata when consumed together with EVM gas. Treating calldata as a separate resource with a price based on block usage would allow for a more precise control over usage, and transactors would not need to interact with a secondary market to achieve the best price. 

Given that the EIP-7623 design already achieves calldata moderation, it must be remembered that an individual fee market for calldata would merely be a first step toward a multidimensional fee market. Calldata is not an endgame. It is likely best to transition over several hard forks, and the options available at the present must then be considered, which leads to a focus on calldata. Another present consideration is block level access lists (BALs) and their interaction. 

A resource such as state is more attractive to separate than calldata. We could achieve exact control over state growth, while allowing temporary spikes many times above current gas limits. However, an expansion into other resources requires a multidimensional gas repricing, which has currently not yet been completed. The next section will further discuss remaining complexities of multidimensional EVM gas, and the strategies available for overcoming them.

### Expansion paths for multiple EVM resources

This EIP has been designed to facilitate a future expansion into multiple EVM resources. We conclude by outlining the challenges inherent to such an expansion, and the different paths that it can take.

#### EVM without gas observability

One long-term vision for the EVM is to move away from gas observability. This is one of the features of EOF ([EIP-7692](/EIPs/EIPS/eip-7692)), e.g., through revamped `CALL` instructions in [EIP-7069](/EIPs/EIPS/eip-7069) such as `EXTCALL`. The new calls no longer accept a gas stipend as an input parameter, and the EVM instead makes available some reasonable fraction of all gas across dimensions (e.g., 63/64). Legitimate use cases previously handled via gas observability are then instead taken over by, e.g., the `PAY` opcode [EIP-5920](/EIPs/EIPS/eip-5920). 

For compatibility with legacy code, the EVM can in this scenario reinterpret legacy subcalls with a gas parameter by forwarding the same fraction of the caller’s remaining budget in each resource dimension. Concretely, if the call stipulates $g_c$ and the aggregate remaining EVM-gas budget is $g_a$, the callee receives, for each EVM resource with remaining budget $g_r$, the amount $\bigl\lfloor g_r \cdot \min\!\bigl(1,\tfrac{g_c}{g_a}\bigr) \bigr\rfloor$. For completeness, the `GAS` opcode could likewise return, e.g., $g_a$ (the per-call aggregate remaining budget at this point across all resource dimensions). Note, however, that reinterpreting legacy calls and `GAS` in this way can still change the behavior of contracts that rely on precise gas observability or gas-capped subcalls, and such contracts may break.

#### EVM that retains gas observability

It is possible to expand into multiple EVM resource dimensions without breaking existing contracts that rely on gas observability. By treating gas as *fungible across resources* (just as today), a single budget can be forwarded and counted toward any resource that consumes it. It should be noted that old contracts may still break due to repricing of the resources they use; indeed, a gas repricing effort is currently underway in Ethereum that likely will cause such breakage. But this may be treated as a separate concern. 

#### Transaction types under multiple EVM resources with non-deterministic limits

A key difference between the new and old transaction types is that the old transaction types set only one limit, whereas the new can set several. When adding deterministic resources such as calldata, this is not a concern, because consumption of this resource can be deducted from the user-specified limit as a pre-processing step. But once there is more than one non-deterministic resource—as can be the case when EVM gas is separated into several resources—things get slightly more complicated. If we wish to ensure that old transaction types still can function properly under these circumstances, we must apply the single limit to multiple non-deterministic resources. The following subsections will outline how this can be achieved by aggregating the gas of these separate resources during EVM processing.

The new transaction type can supply several limits, making expansion into multiple EVM resources more straightforward. However, it turns out that we may also wish to retain the ability of the new transaction type to set a single limit for EVM gas. The reason is that the single limit and aggregate processing facilitates backward compatibility for contracts that rely on gas observability. As previously noted, these contracts must be able to supply subcalls with an aggregate gas stipend, to be counted against any EVM resource. Furthermore, there is an inherent simplicity of the single limit that is not to be discounted.

In all considered approaches below, the number of non-deterministic EVM resources still increases at the *block level*. To retain the ability to reject a transaction that may require more gas for a resource than its associated block limit, it becomes necessary to alter the check on `gas_used_so_far`. Specifically, when a transaction stipulates only the main EVM gas limit, then this limit must be conservatively counted toward all underspecified dimensions of `gas_used_so_far` before the limit check:

```python
if len(tx_gas_limits) == len(gas_used_so_far) # Same check as previously
    all_less_or_equal(vector_add(gas_used_so_far, tx_gas_limits), gas_limits)
else: # The joint EVM gas limit is expanded to cover all block resources
    tx_gas_limits_exp = [tx_gas_limits[0]] * len(gas_limits)
    tx_gas_limits_exp[1], tx_gas_limits_exp[2] = tx_gas_limits[1], tx_gas_limits[2]
    all_less_or_equal(vector_add(gas_used_so_far, tx_gas_limits_exp), gas_limits)
```

#### Multidimensional gas metering

An existing proposal by Inês Silva and Crapis is *Multidimensional gas metering* (not yet submitted as an EIP), which prices gas in one dimension, but applies limits at the block level across several dimensions when updating the (single) EVM base fee. The EVM will thus track multidimensional gas consumption, but perform the limit check on the aggregate, which is also passed on in subcalls. The proposed EIP could be combined with Multidimensional gas metering, for example by using a single EVM gas and calculating metered block gas usage separately, before submitting the outcome as a single resource dimension to the revamped `calc_excess_gas()`.

#### Multidimensional fee market with aggregate EVM gas

To promote full resource utilization while maintaining backward compatibility for subcalls and old transaction formats, we could instead use *separate* gas prices for each EVM resource, while retaining within the EVM the ability to *aggregate the gas* consumption across resources. We refer to this as a *Multidimensional fee market with aggregate gas*. In the fully aggregated scenario, the user stipulates a single `gas_limit` for EVM gas, and the protocol must make sure that the `max_fee` covers the maximum possible fee, from consuming `gas_limit` of the EVM resource that has the most expensive base fee. Execution is then fully backward compatible, and the EVM operates the same way as with Multidimensional gas metering.

The downside is that the user must stipulate an unnecessarily high `max_fee` allocation, if the most expensive resource is not used. We present three options for alleviating this. The first two options transfer to the block producer the responsibility to ensure that the `max_fee` indeed covers a transaction&apos;s fees determined post-execution. The third option instead enables the transactor to alternatively provide better guarantees in the form of full gas limits.

*Option 1:* Invalidate a block when the post-transaction check shows that the total fee for a transaction exceeded `max_fee`. We could either completely remove the pre-execution check `max_fee &gt;= get_required_max_fee(base_fees, tx_gas_limits)`, or only check for deterministic resources in addition to EVM gas across the cheapest EVM resource. During processing, there would still be an aggregated check against the transaction&apos;s gas limit, which is the sender&apos;s responsibility. In extension, the block&apos;s gas limit is already safeguarded pre-execution by conservatively counting `tx_gas_limits_exp` against it, as outlined in the previous subsection. 

Note that the inclusion guarantees of EIP-7805 will not apply to the transactions where the `max_fee` does not cover the worst-case pre-execution check. These transactions are to be ignored when validating the block post-execution.

*Option 2:* Give the block producer the ability and responsibility to supply any missing funds as part of the post-transaction check. This could potentially rely on staked builders currently envisioned in [EIP-7732](/EIPs/EIPS/eip-7732), albeit it would be more intuitive to use execution layer balances for this purpose. Another alternative is to charge a block-based base fee at the end of processing a block rather than per transaction, as has been discussed in the past. This naturally extends to a multidimensional setting. Note that (2) reverts to (1) upon failure of the builder to ensure the base fees are covered. 

*Option 3:* Give the transactor the ability to provide limits for all dimensions, if they so wish. The pre-execution check can then be more fine-grained, inheriting the higher capital efficiency previously outlined. This is a hybrid design, where the transactor can choose the option most suitable to their needs if they use the new transaction type.  This option will be discussed in more detail in the next subsection. Note that (3) can be combined with (1) if desirable.

#### Multidimensional fee market with hybrid EVM gas

In a *Multidimensional fee market with hybrid EVM gas*, the user has separate options: 

1. Provide a single gas limit for the EVM resources. The EVM can then operate as in the aggregate gas model, after the initial restrictive fee allocation check.
2. Provide a gas limit for each EVM resource. Capital efficiency is then preserved. The EVM operates without gas observability as previously outlined, with the gas parameter of old subcalls converted to a multidimensional counterpart. The transaction is during processing checked against its multiple limits, as opposed to the aggregate. 

It is further possible to give the user the freedom to stipulate *some* EVM gas limits, but not all. The user can for example set the gas limit to 0 for any resource it knows that it will not use, instead of not setting a gas limit for that resource. The aggregation then takes place only across resources without an individual stipulated limit, reducing the required `max_fee` allocation while preserving full/a higher level of backward compatibility. These features come at a cost of somewhat increased complexity.

#### Specification for aggregate and hybrid EVM gas

For the hybrid model, the `get_gas_limits()` function must be updated to alternatively return multiple EVM gas limits, in the case the user stipulates the full list.

```python
def get_gas_limits(tx: Transaction) -&gt; list[int]:
    ...
    if tx.type == MULTIDIM_TX_TYPE:
        if len(tx.gas_limit) == 1:
            return [tx.gas_limit[0], blob_gas, calldata_gas]
        else:
            return [tx.gas_limit[0], blob_gas, calldata_gas] + tx.gas_limit[1:]
    ...
```

For the aggregate model, the `get_required_max_fee()` must be updated such that the protocol applies the worst-case EVM base fees across the EVM gas. The new constant `EVM_INDICES` specifies the EVM resource indices. Note that `TX_BASE_COST` is treated as a deterministic component of the EVM gas to reduce required capital allocation. Note that even when pursuing Options 1-2 for aggregate gas, the aggregation step is still applied in consideration of EIP-7805.

```python
def get_required_max_fee(base_fees: list[int], tx_gas_limits: list[int]) -&gt; int:
    # Fully specified gas limits, apply baseline pattern
    if len(base_fees) == len(tx_gas_limits): 
        return sum(vector_mul(base_fees, tx_gas_limits))
    # Otherwise: 1. TX_BASE_COST is treated deterministically (assumed resource 0)
    determ_evm_cost = TX_BASE_COST * base_fees[0]
    require(tx_gas_limits[0] &gt;= TX_BASE_COST)   # Limit MUST cover TX_BASE_COST.
    variable_evm_limit = tx_gas_limits[0] - TX_BASE_COST
    # 2. Determine EVM cost based on most expensive resource
    max_evm_base_fee = max(base_fees[i] for i in EVM_INDICES)
    evm_cost = determ_evm_cost + variable_evm_limit * max_evm_base_fee
    # 3. Return total EVM cost + blob cost + calldata cost
    return evm_cost + base_fees[1]*tx_gas_limits[1] + base_fees[2]*tx_gas_limits[2]
```

For the hybrid model, the line stipulating `tip_indices` in `get_max_priority_fee()` must be updated to include all new EVM resources `tip_indices = [2] + EVM_INDICES`. It is also feasible to adjust the functioning of legacy transactions, to let them tip only according to the headroom between the EVM resource with the highest base fee and the `gasprice`. The aim would be to prevent them from having to pay an excessive tip when the `gasprice` was set high merely to cover for the EVM resource with the highest base fee (of which they use little). The tip would then be calculated as the premium above the highest EVM resource base fee.

To allow transactors to specify *some* limits, the `tx.gas_limit` list must instead have a nested format, where `gas_limit[0]` is the aggregate limit for unspecified EVM resources, and `[index, limit]` pairs then follow: `tx.gas_limit = [aggregate, [[index, limit], [index, limit],...]]`. The protocol then computes the required max fee from resources with both specified and unspecified limits. The maximum base fee among the resources with unspecified limits is in this case multiplied with the aggregate, and this fee is summed together with the fees of specified limits.

## Backwards Compatibility

The `max_fee_per_gas` of the EIP-1559 and EIP-4844 transaction types are converted to a `max_fee` by multiplication with the stipulated gas limit(s). The converted EIP-4844 transactions will no longer adhere to the individual `max_fee_per_gas` and `max_fee_per_blob_gas`, but instead to the aggregated `max_fee`. This is a deliberate choice since previous individual checks have lower economic efficiency to no clear benefit, but it should nevertheless be noted by transactors. The priority fee retains the same functionality as previously. The old `gasprice` can be used both for the `max_fee` and `max_priority_fee_per_gas`. The `gas_limit` is finally derived deterministically. The section on expansion paths outlined how old transactions can retain functionality as we expand into several non-deterministic EVM resources.

Backward compatibility for contracts that rely on gas introspection can be resolved by giving users the ability to rely on aggregated EVM gas, while still potentially pricing EVM resources separately. Wallets must be updated to handle multidimensional gas accounting with several base fees.

## Security Considerations

One concern is the risk of increasing builder centralization due to increased revenue from sophisticated packing algorithms. While the builder is constrained in its block construction when blocks are full, it is only when several limits are reached at the same time that packing complexity markedly changes from today. Given that around 90% of blocks are below the gas limit, and the calldata limit is set to be very permissive, we argue that this will happen very rarely.

One reason for using `max_priority_fee_per_gas` instead of `max_priority_fee` is to establish the priority fee as always having a non-aggregate representation. We could possibly otherwise imagine a scenario where a user in the old transaction format manually submits an aggregate `max_fee` and `max_priority_fee`, causing loss of funds.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 04 Aug 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-7999</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-7999</guid>
      </item>
    
      <item>
        <title>Operator contract for non delegated EOAs</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8000-operator-contract-for-non-delegated-eoas/25003</comments>
        
        <description>## Abstract

This standard defines a contract interface that enables externally owned accounts (EOAs) to perform batch call executions via a standard Operator contract, without requiring them to delegate control or convert into smart contract accounts.

## Motivation

The [ERC-7702](./eip-7702) allows EOAs to become powerful smart contract accounts (SCA), which solves many UX issues, like the double `approve` + `transferFrom` transactions.  
While this new technology is still reaching wider adoption over time, we need a way to improve UX for the users that decide to not have code attached to their EOAs.  
This proposal introduces a lightweight, backward-compatible mechanism to enhance UX for such users. By leveraging a standardized Operator contract, EOAs can batch multiple contract calls into a single transaction—assuming the target contracts are compatible (i.e., implement the Operated pattern).

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

### Definitions

- Operator: The contract that executes calls on the sender&apos;s behalf.
- Operated: The contract that supports calls through the Operator.

It&apos;s OPTIONAL but HIGHLY RECOMMENDED to have the `Operator` contract as a singleton.

### Operator

```solidity
pragma solidity ^0.8.29;

interface IOperator {
    struct Call {
        address target;
        uint256 value;
        bytes callData;
    }

    /// @notice Execute calls
    /// @param calls An array of Call structs
    /// @return returnData An array of bytes containing the responses
    function execute(Call[] calldata calls) external payable returns (bytes[] memory returnData);

    /// @notice The address which initiated the executions
    /// @return sender The actual sender of the calls
    function onBehalfOf() external view returns (address sender);
}
```

### Methods

`execute`
Execute the calls sent by the actual sender.

MUST revert if any of the calls fail.  
MUST return data from the calls.

`onBehalfOf`
Used by the target contract to get the actual caller.

MUST return the actual `msg.sender` when called in the context of a call.  
MUST revert when called outside of the context of a call.

### Operated

```solidity
pragma solidity ^0.8.29;

import { Context } from &quot;@openzeppelin/contracts/utils/Context.sol&quot;;
import { IOperator } from &quot;./interfaces/IOperator.sol&quot;;

/// @title Operated contract
/// @dev Supports calls through the Operator
abstract contract Operated is Context {
    IOperator public immutable operator;

    constructor(address operator_) {
        operator = IOperator(operator_);
    }

    /// @inheritdoc Context
    function _msgSender() internal view virtual override returns (address) {
        if (msg.sender == address(operator)) {
            return operator.onBehalfOf();
        }

        return msg.sender;
    }
}
```

Any contract can become compatible to execute the batch call by EOA using operator if it extends the `Operated` contract. The `Operated` contract overrides `_msgSender()` to return `operator.onBehalfOf()` when the call originates from the Operator. This ensures that the target contract recognizes the EOA initiating the batch execution, preserving correct sender context.

This behavior fits well with the usage of the \_msgSender() function from [ERC-2771](./eip-2771).

### Methods

`_msgSender`
Returns `msg.sender` or `operator.onBehalfOf()`

## Rationale

By having a trusted contract (`Operator`) that may act on behalf of the EOA wallet, this ERC provides batch call capabilities and keeps the EOA as the caller of the target contracts.

## Backwards Compatibility

The main limitation of this ERC is that only contracts that implements the `Operated` logic will be able to receive calls through the `Operator`.

## Reference Implementation

### Operator

```solidity
pragma solidity ^0.8.29;

import {TransientSlot} from &quot;@openzeppelin/contracts/utils/TransientSlot.sol&quot;;
import {Address} from &quot;@openzeppelin/contracts/utils/Address.sol&quot;;
import {ReentrancyGuardTransient} from &quot;@openzeppelin/contracts/utils/ReentrancyGuardTransient.sol&quot;;
import {IOperator} from &quot;./interfaces/IOperator.sol&quot;;

/// @title Operator contract
/// @dev Allows standard EOAs to perform batch calls
contract Operator is IOperator, ReentrancyGuardTransient {
    using TransientSlot for *;
    using Address for address;

    // keccak256(abi.encode(uint256(keccak256(&quot;operator.actual.sender&quot;)) - 1)) &amp; ~bytes32(uint256(0xff))
    bytes32 private constant MSG_SENDER_STORAGE = 0x0de195ebe01a7763c35bcc87968c4e65e5a5ea50f2d7c33bed46c98755a66000;

    modifier setMsgSender() {
        MSG_SENDER_STORAGE.asAddress().tstore(msg.sender);
        _;
        MSG_SENDER_STORAGE.asAddress().tstore(address(0));
    }

    /// @inheritdoc IOperator
    function onBehalfOf() external view returns (address _actualMsgSender) {
        _actualMsgSender = MSG_SENDER_STORAGE.asAddress().tload();
        require(_actualMsgSender != address(0), &quot;outside-call-context&quot;);
    }

    /// @inheritdoc IOperator
    function execute(
        Call[] calldata calls_
    ) external payable override nonReentrant setMsgSender returns (bytes[] memory _returnData) {
        uint256 _length = calls_.length;
        _returnData = new bytes[](_length);

        uint256 _sumOfValues;
        Call calldata _call;
        for (uint256 i; i &lt; _length; ) {
            _call = calls_[i];
            uint256 _value = _call.value;
            unchecked {
                _sumOfValues += _value;
            }
            _returnData[i] = _call.target.functionCallWithValue(_call.callData, _value);
            unchecked {
                ++i;
            }
        }

        require(msg.value == _sumOfValues, &quot;value-mismatch&quot;);
    }
}
```

Worth noting that the usage of transient storage ([EIP-1153](./eip-1153)) for storing the `msg.sender` is highly RECOMMENDED.

### Operated

```solidity
pragma solidity ^0.8.29;

import {Context} from &quot;@openzeppelin/contracts/utils/Context.sol&quot;;
import {IERC20} from &quot;@openzeppelin/contracts/token/ERC20/IERC20.sol&quot;;
import {IOperator} from &quot;./interfaces/IOperator.sol&quot;;
import {Operated} from &quot;./Operated.sol&quot;;

/// @title Operated contract
/// @dev Supports calls through the Operator
contract OperatorCompatible is Operated {
    error InsufficientBalance();

    mapping(address =&gt; mapping(address =&gt; uint256)) public balance;

    constructor(address operator_) Operated(operator_) {}

     function deposit(address token_, uint256 amount_) public payable {
        if (token_ == address(0)) revert InvalidToken();
        address _sender = _msgSender();
        IERC20(token_).transferFrom(_sender, address(this), amount_);
        balance[token_][_sender] += amount_;
    }

    function withdraw(address token_, uint256 amount_) public {
        if (token_ == address(0)) revert InvalidToken();
        address _sender = _msgSender();
        if (balance[token_][_sender] &lt; amount_) revert InsufficientBalance();
        balance[token_][_sender] -= amount_;
        IERC20(token_).transfer(_sender, amount_);
    }
}

```

## Security Considerations

- The `execute` function MUST implement reentracy control to avoid having a callback call overriding the sender&apos;s storage.
- The `Operated` contract MUST interact with a trusted `Operator` contract.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 02 Jul 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8000</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8000</guid>
      </item>
    
      <item>
        <title>Agent Coordination Framework</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8001-secure-intents-a-cryptographic-framework-for-autonomous-agent-coordination-draft-erc-8001/24989</comments>
        
        <description>## Abstract

[ERC-8001](/EIPs/EIPS/eip-8001) defines a minimal, single-chain primitive for **multi-party agent coordination**. An initiator posts an intent and each participant provides a verifiable acceptance attestation. Once the required set of acceptances is present and fresh, the intent is executable. The standard specifies typed data, lifecycle, mandatory events, and verification rules compatible with [EIP-712], [ERC-1271], [EIP-2098], and [EIP-5267].

[ERC-8001](/EIPs/EIPS/eip-8001) omits privacy, reputation, threshold policies, bonding, and cross-chain semantics. Those are expected as optional modules that reference this specification.

## Motivation

Agents in DeFi/MEV/Web3 Gaming and Agentic Commerce often need to act together without a trusted coordinator. Existing intent standards (e.g., [ERC-7521](/EIPs/EIPS/eip-7521), [ERC-7683](/EIPs/EIPS/eip-7683)) define single-initiator flows and do not specify multi-party agreement.

[ERC-8001](/EIPs/EIPS/eip-8001) specifies the smallest on-chain primitive for that gap: an initiator&apos;s [EIP-712](/EIPs/EIPS/eip-712) intent plus per-participant [EIP-712](/EIPs/EIPS/eip-712)/[EIP-1271](/EIPs/EIPS/eip-1271) acceptances. The intent becomes executable only when the required set of acceptances is present and unexpired. Canonical (sorted-unique) participant lists and standard typed data provide replay safety and wallet compatibility. Privacy, thresholds, bonding, and cross-chain are left to modules.

## Specification

The keywords “MUST”, “SHOULD”, and “MAY” are to be interpreted as described in RFC 2119 and RFC 8174.

Implementations MUST expose the following canonical status codes for `getCoordinationStatus`:

### Status Codes

Implementations MUST use the canonical enum defined below:

```solidity
enum Status { None, Proposed, Ready, Executed, Cancelled, Expired }
```
- `None` = default zero state (intent not found)

- `Proposed` = intent proposed, not all acceptances yet

- `Ready` = all participants have accepted, intent executable

- `Executed` = intent successfully executed

- `Cancelled` = intent explicitly cancelled

- `Expired` = intent expired before execution

### Overview

This ERC specifies:
- A canonicalised EIP-712 domain for agent coordination,
- Typed data structures (`AgentIntent`, `CoordinationPayload`, `AcceptanceAttestation`),
- Deterministic hashing rules,
- A standard interface (`IAgentCoordination`),
- Lifecycle semantics (propose → accept → execute/cancel),
- Error surface and status codes.

### EIP-712 Domain

Implementations MUST use the following EIP-712 domain:

```
{name: &quot;ERC-8001&quot;, version: &quot;1&quot;, chainId, verifyingContract}
```

Implementations SHOULD expose the domain via [ERC-5267](/EIPs/EIPS/eip-5267).

### Primary Types

```solidity
struct AgentIntent {
    bytes32 payloadHash;           // keccak256(CoordinationPayload)
    uint64  expiry;                // unix seconds; MUST be &gt; block.timestamp at propose
    uint64  nonce;                 // per-agent nonce; MUST be &gt; agentNonces[agentId]
    address agentId;               // initiator and signer of the intent
    bytes32 coordinationType;      // domain-specific type id, e.g. keccak256(&quot;MEV_SANDWICH_COORD_V1&quot;)
    uint256 coordinationValue;     // informational in Core; modules MAY bind value
    address[] participants;        // unique, ascending; MUST include agentId
}

struct CoordinationPayload {
    bytes32 version;               // payload format id
    bytes32 coordinationType;      // MUST equal AgentIntent.coordinationType
    bytes   coordinationData;      // opaque to Core
    bytes32 conditionsHash;        // domain-specific
    uint256 timestamp;             // creation time (informational)
    bytes   metadata;              // optional
}

struct AcceptanceAttestation {
    bytes32 intentHash;            // getIntentHash(intent)
    address participant;           // signer
    uint64  nonce;                 // optional in Core; see Nonces
    uint64  expiry;                // acceptance validity; MUST be &gt; now at accept and execute
    bytes32 conditionsHash;        // participant constraints
    bytes   signature;             // ECDSA (65 or 64 bytes) or ERC-1271
}
```

### Typed Data Hashes

```solidity

bytes32 constant AGENT_INTENT_TYPEHASH = keccak256(
  &quot;AgentIntent(bytes32 payloadHash,uint64 expiry,uint64 nonce,address agentId,bytes32 coordinationType,uint256 coordinationValue,address[] participants)&quot;
);

bytes32 constant ACCEPTANCE_TYPEHASH = keccak256(
// Field names MUST exactly match the Solidity struct.
  &quot;AcceptanceAttestation(bytes32 intentHash,address participant,uint64 nonce,uint64 expiry,bytes32 conditionsHash)&quot;
);

// participants MUST be unique and strictly ascending by uint160(address).
  function _participantsHash(address[] memory ps) internal pure returns (bytes32) {
    return keccak256(abi.encodePacked(ps));
  }

  function _agentIntentStructHash(AgentIntent calldata i) internal pure returns (bytes32) {
    return keccak256(abi.encode(
      AGENT_INTENT_TYPEHASH,
      i.payloadHash,
      i.expiry,
      i.nonce,
      i.agentId,
      i.coordinationType,
      i.coordinationValue,
      _participantsHash(i.participants)
    ));
  }

// Full EIP-712 digest for the initiator’s signature.
  function _agentIntentDigest(bytes32 domainSeparator, AgentIntent calldata i) internal pure returns (bytes32) {
    return keccak256(abi.encodePacked(&quot;\x19\x01&quot;, domainSeparator, _agentIntentStructHash(i)));
  }

  function _acceptanceStructHash(AcceptanceAttestation calldata a) internal pure returns (bytes32) {
    // a.intentHash MUST be the AgentIntent struct hash, not the digest.
    return keccak256(abi.encode(
      ACCEPTANCE_TYPEHASH,
      a.intentHash,
      a.participant,
      a.nonce,
      a.expiry,
      a.conditionsHash
    ));
  }

  function _acceptanceDigest(bytes32 domainSeparator, AcceptanceAttestation calldata a) internal pure returns (bytes32) {
    return keccak256(abi.encodePacked(&quot;\x19\x01&quot;, domainSeparator, _acceptanceStructHash(a)));
  }

```
Computation (normative):

```solidity
participantsHash = keccak256(abi.encodePacked(participants)); // sorted unique
intentStructHash = keccak256(abi.encode(
  AGENT_INTENT_TYPEHASH,
  payloadHash, expiry, nonce, agentId, coordinationType, coordinationValue, participantsHash
));
intentDigest = keccak256(&quot;\x19\x01&quot; || domainSeparator || intentStructHash);

```

Clarifications (normative):
- `getIntentHash(intent)` MUST return `intentStructHash` (struct hash), not the full digest.
- `AcceptanceAttestation.intentHash` MUST be that struct hash.
- Each acceptance is signed over its own EIP-712 digest that includes this field.
- `participants` MUST be strictly ascending by `uint160(address)` and deduplicated.


### Interface

Implementations **MUST** expose the following interface and events.

```solidity
interface IAgentCoordination {
    event CoordinationProposed(bytes32 indexed intentHash, address indexed proposer, bytes32 coordinationType, uint256 participantCount, uint256 coordinationValue);
    event CoordinationAccepted(bytes32 indexed intentHash, address indexed participant, bytes32 acceptanceHash, uint256 acceptedCount, uint256 requiredCount);
    event CoordinationExecuted(bytes32 indexed intentHash, address indexed executor, bool success, uint256 gasUsed, bytes result);
    event CoordinationCancelled(bytes32 indexed intentHash, address indexed canceller, string reason, uint8 finalStatus);

    function proposeCoordination(AgentIntent calldata intent, bytes calldata signature, CoordinationPayload calldata payload) external returns (bytes32 intentHash);
    function acceptCoordination(bytes32 intentHash, AcceptanceAttestation calldata attestation) external returns (bool allAccepted);
    function executeCoordination(bytes32 intentHash, CoordinationPayload calldata payload, bytes calldata executionData) external returns (bool success, bytes memory result);
    function cancelCoordination(bytes32 intentHash, string calldata reason) external;

    function getCoordinationStatus(bytes32 intentHash) external view returns (Status status, address proposer, address[] memory participants, address[] memory acceptedBy, uint256 expiry);
    function getRequiredAcceptances(bytes32 intentHash) external view returns (uint256);
    function getAgentNonce(address agent) external view returns (uint64);
}
```

### Semantics

The functions defined in this specification MUST exhibit the following externally observable behaviours.  
This standard does NOT prescribe storage layout, execution model, or internal mechanisms.

#### `proposeCoordination`

`proposeCoordination` MUST revert if:

- the signature does not validate the supplied `AgentIntent` under the ERC-8001 EIP-712 domain;
- `intent.expiry &lt;= block.timestamp`;
- `intent.nonce` is not strictly greater than `getAgentNonce(intent.agentId)`;
- `participants` is not strictly ascending and unique;
- `intent.agentId` is not included in the participants list.

If valid:

- `CoordinationProposed` MUST be emitted;
- `getCoordinationStatus` MUST report `Proposed`;
- `getAgentNonce(intent.agentId)` MUST equal the supplied nonce;
- `getRequiredAcceptances(intentHash)` MUST equal the number of participants.

#### `acceptCoordination`

`acceptCoordination` MUST revert if:

- the intent does not exist or has expired;
- the caller is not listed as a participant;
- the participant has already accepted;
- the attestation signature does not validate under the ERC-8001 domain;
- `attestation.expiry &lt;= block.timestamp`.

If valid:

- `CoordinationAccepted` MUST be emitted;
- the participant MUST appear in the `acceptedBy` list returned by `getCoordinationStatus`;
- if all participants have accepted:
  - the function MUST return `true`;
  - status MUST be `Ready`.

Otherwise the function MUST return `false`.

#### `executeCoordination`

`executeCoordination` MUST revert if:

- the intent is not in `Ready` state;
- `intent.expiry &lt;= block.timestamp`;
- any acceptance has expired;
- the supplied payload does not hash to `payloadHash`.

If valid:

- the implementation MUST attempt execution of the behaviour represented by `executionData`;
- the function MUST return `(success, result)`;
- `CoordinationExecuted` MUST be emitted;
- `getCoordinationStatus` MUST report `Executed`.

#### `cancelCoordination`

- If the intent has not expired, only the proposer MUST be permitted to cancel.
- After expiry, any caller MUST be permitted to cancel.

On success:

- `CoordinationCancelled` MUST be emitted;
- status MUST be `Cancelled`.

#### `getCoordinationStatus`

`getCoordinationStatus(intentHash)` MUST return:

- `None` if the intent does not exist;
- `Proposed` if not all participants have accepted and the intent has not expired;
- `Ready` if all participants have accepted and expiries have not elapsed;
- `Executed` if execution has occurred;
- `Cancelled` if cancellation has occurred;
- `Expired` if the intent has expired and was not executed or cancelled.

#### Nonces

- `getAgentNonce(agent)` MUST increase for every valid new intent.
- `proposeCoordination` MUST reject nonces not strictly greater than the stored nonce.
- Acceptance-level nonces MAY be implemented; if so, they MUST be strictly monotonic per participant.

### Errors

Implementations SHOULD revert with descriptive custom errors (or equivalent revert strings) for the following baseline conditions, and MAY define additional errors for domain-specific modules (e.g. slashing, reputation, or privacy conditions):
- Expired intent
- Bad signature
- Non-participant
- Duplicate acceptance
- Acceptance expired at execute
- Payload hash mismatch

```solidity
error ERC8001_NotProposer();
error ERC8001_ExpiredIntent();
error ERC8001_ExpiredAcceptance(address participant);
error ERC8001_BadSignature();
error ERC8001_NotParticipant();
error ERC8001_DuplicateAcceptance();
error ERC8001_ParticipantsNotCanonical();
error ERC8001_NonceTooLow();
error ERC8001_PayloadHashMismatch();
error ERC8001_NotReady();
```

## Rationale

- Sorted participant lists remove hash malleability and allow off-chain deduplication.
- Separation of intent and acceptance allows off-chain collation and a single on-chain check.
- Keeping [ERC-8001](/EIPs/EIPS/eip-8001) single-chain avoids coupling to bridge semantics and keeps the primitive audit-friendly.
- Wallet friendliness: EIP-712 arrays let signers see actual participant addresses.

## Backwards Compatibility

[ERC-8001](/EIPs/EIPS/eip-8001) introduces a new interface. It is compatible with EOA and contract wallets via ECDSA and ERC-1271. It does not modify existing standards.

## Reference Implementation

A permissive reference implementation is provided in [`contracts/AgentCoordination.sol`](/EIPs/assets/eip-8001/contracts/AgentCoordination.sol). It uses a minimal ECDSA helper and supports ERC-1271 signers. It enforces participant canonicalisation, intent nonces, acceptance freshness, and all-participants policy.

## Security Considerations

- **Replay**: EIP-712 domain binding and monotonic nonces prevent cross-contract replay.
- **Malleability**: Low-s enforcement and 64/65-byte signature support are required.
- **Equivocation**: A participant can sign conflicting intents. Mitigate with module-level slashing or reputation.
- **Liveness**: Enforce TTL on both intent and acceptances. Executors should ensure enough time remains.
- **MEV**: If `coordinationData` reveals strategy, use a Privacy module with commit-reveal or encryption.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

[EIP-712]: /EIPs/EIPS/eip-712

[ERC-1271]: /EIPs/EIPS/eip-1271

[EIP-2098]: /EIPs/EIPS/eip-2098

[EIP-5267]: /EIPs/EIPS/eip-5267
</description>
        <pubDate>Sat, 02 Aug 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8001</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8001</guid>
      </item>
    
      <item>
        <title>Simplified Payment Verification Gateway</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8002-simplified-payment-verification-gateway/25038</comments>
        
        <description>## Abstract

Introduce a singleton contract for on-chain verification of transactions that happened on Bitcoin. The contract is available at &quot;0xTODO&quot; &lt;!-- TODO --&gt;, acting as a trustless Simplified Payment Verification (SPV) gateway where anyone can submit Bitcoin block headers. The gateway maintains the mainchain of blocks and allows the existence of Bitcoin transactions to be verified via Merkle proofs.

## Motivation

Ethereum&apos;s long-term mission has always been to revolutionize the financial world through decentralization, trustlessness, and programmable value enabled by smart contracts. Many great use cases have been discovered so far, including the renaissance of Decentralized Finance (DeFi), emergence of Real-World Assets (RWA), and rise of privacy-preserving protocols.

However, one gem has been unreachable to date -- Bitcoin. Due to its extremely constrained programmability, one can only hold and transfer bitcoins in a trustless manner. This EIP tries to expand its capabilities by laying a solid foundation for bitcoins to be also used in various EVM-based DeFi protocols, unlocking a whole new trillion-dollar market.

The singleton SPV gateway contract defined in this proposal acts as a trustless one-way bridge between Bitcoin and Ethereum, already enabling use cases such as using _native_ BTC as a lending collateral for stablecoin loans. Moreover, with the recent breakthroughs in the BitVM technology, the full-fledged, ownerless two-way bridge may soon become a reality, powering the permissionless and wrapless issuance of BTC on Ethereum.

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### General

#### Bitcoin Block Header Structure

In Bitcoin, each block contains a header, which has a fixed size of 80 bytes and follows the following structure:

| Field          | Size     | Format             | Description                                                          |
| :------------- | :------- | :----------------- | :------------------------------------------------------------------- |
| Version        | 4 bytes  | little-endian      | The version number of the block.                                     |
| Previous Block | 32 bytes | natural byte order | The block hash of a previous block this block is building on top of. |
| Merkle Root    | 32 bytes | natural byte order | A fingerprint for all of the transactions included in the block.     |
| Time           | 4 bytes  | little-endian      | The current time as a Unix timestamp.                                |
| Bits           | 4 bytes  | little-endian      | A compact representation of the current target (difficulty).         |
| Nonce          | 4 bytes  | little-endian      | A 32-bit number which miners compute to find a valid block hash.     |

The fields within the block header are sequentially ordered as presented in the table above.

#### Difficulty Adjustment Mechanism

Bitcoin&apos;s Proof-of-Work (PoW) consensus mechanism has a probabilistic finality, thus relying on a dynamic **difficulty target** adjustments. The target&apos;s initial value is set to `0x00000000ffff0000000000000000000000000000000000000000000000000000`, which also serves as the minimum difficulty threshold.

The `target` is recalculated every 2016 blocks (approximately every two weeks), a period commonly referred to as a **difficulty adjustment period**.

The expected duration for each adjustment period is 1,209,600 seconds (2016 blocks * 10 minutes/block). The new `target` value is derived by multiplying the current `target` by the ratio of the actual time taken to mine the preceding 2016 blocks to this expected duration.

To prevent drastic difficulty fluctuations, the adjustment multiplier is capped at `4x` and `1/4x` respectively.

#### Block Header Validation Rules

For a Bitcoin block header to be considered valid and accepted into the chain, it MUST adhere to the following consensus rules:

1. **Chain Cohesion**: The `Previous Block` hash field MUST reference the hash of a valid block that is present in the set of existing block headers.

2. **Timestamp Rules**:
    * The `Time` field MUST be strictly greater than the **Median Time Past (MTP)** of the previous 11 blocks.
    * The `Time` field MUST NOT be more than 2 hours in the future relative to the validating node&apos;s network-adjusted time.

3. **PoW Constraint**: When the block header is hashed twice using `SHA256`, the resulting hash MUST be less than or equal to the current `target` value, as derived from the difficulty adjustment mechanism.

#### Transaction Inclusion Structure

Every Bitcoin block header has a field `Merkle Root` that corresponds to a Merkle root of the transactions tree included in this block.

The transactions Merkle tree is built recursively performing double `SHA256` hash on each pair of sibling nodes, where the tree leaves are the double `SHA256` hash of the raw transaction bytes. In case the node has no siblings, the hashing is done over the node with itself.

To verify the transaction inclusion into the block, one SHOULD build the Merkle root from the ground up and compare it with the `Merkle Root` stored in the selected block header. The corresponding Merkle path and hashing direction bits can be obtained and processed by querying a Bitcoin full node.

#### Mainchain Definition

Bitcoin&apos;s **mainchain** is determined not just by its length, but by the greatest **cumulative PoW** among all valid competing chains. This cumulative work represents the total computational effort expended to mine all blocks within a specific chain.

The work contributed by a single block is inversely proportional to its `target` value. Specifically, the work of a block can be calculated as `(2**256 - 1) / (target + 1)`. The `target` value for a block is derived from its `Bits` field, where the first byte encodes the required left hand bit shift, and the other three bytes the actual target value.

The total cumulative work of a chain is the sum of the work values of all blocks within that chain. A block is considered part of the mainchain if it extends the chain with the greatest cumulative PoW.

### SPV Gateway

The `SPVGateway` contract MUST provide a permissionless mechanism for its initialization. This mechanism MUST allow for the submission of a valid Bitcoin block header, its corresponding block height, and the cumulative PoW up to that block, without requiring special permissions.

The `SPVGateway` MUST implement the following interface:

```solidity
pragma solidity ^0.8.0;

/**
 * @notice Interface for a Simplified Payment Verification Gateway contract.
 */
interface ISPVGateway {
    /**
     * @notice Represents the essential data contained within a Bitcoin block header
     * @param prevBlockHash The hash of the previous block
     * @param merkleRoot The Merkle root of the transactions in the block
     * @param version The block version number
     * @param time The block&apos;s timestamp
     * @param nonce The nonce used for mining
     * @param bits The encoded difficulty target for the block
     */
    struct BlockHeaderData {
        bytes32 prevBlockHash;
        bytes32 merkleRoot;
        uint32 version;
        uint32 time;
        uint32 nonce;
        bytes4 bits;
    }

    /**
     * MUST be emitted whenever the mainchain head changed (e.g. in the `addBlockHeader`, `addBlockHeaderBatch` functions)
     */
    event MainchainHeadUpdated(
        uint64 indexed newMainchainHeight,
        bytes32 indexed newMainchainHead
    );

    /**
     * MUST be emitted whenever the new block header added to the SPV contract state
     * (e.g. in the `addBlockHeader`, `addBlockHeaderBatch` functions)
     */
    event BlockHeaderAdded(uint64 indexed blockHeight, bytes32 indexed blockHash);

    /**
     * @notice Adds a single raw block header to the contract.
     * The block header is validated before being added
     * @param blockHeaderRaw The raw block header bytes
     */
    function addBlockHeader(bytes calldata blockHeaderRaw) external;

    /**
     * @notice OPTIONAL Function that adds a batch of the block headers to the contract.
     * Each block header is validated and added sequentially
     * @param blockHeaderRawArray An array of raw block header bytes
     */
    function addBlockHeaderBatch(bytes[] calldata blockHeaderRawArray) external;

    /**
     * @notice Checks that given txId is included in the specified block with a minimum number of confirmations.
     * @param merkleProof The array of hashes used to build the Merkle root
     * @param blockHash The hash of the block in which to verify the transaction
     * @param txId The transaction id to verify
     * @param txIndex The index of the transaction in the block&apos;s Merkle tree
     * @param minConfirmationsCount The minimum number of confirmations required for the block
     * @return True if the txId is present in the block&apos;s Merkle tree and the block has at least minConfirmationsCount confirmations, false otherwise
     */
    function checkTxInclusion(
        bytes32[] memory merkleProof,
        bytes32 blockHash,
        bytes32 txId,
        uint256 txIndex,
        uint256 minConfirmationsCount
    ) external view returns (bool);

    /**
     * @notice Returns the hash of the current mainchain head.
     * This represents the highest block on the most accumulated work chain
     * @return The hash of the mainchain head
     */
    function getMainchainHead() external view returns (bytes32);

    /**
     * @notice Returns the height of the current mainchain head.
     * This represents the highest block number on the most accumulated work chain
     * @return The height of the mainchain head
     */
    function getMainchainHeight() external view returns (uint64);

    /**
     * @notice Returns the block header data for a given block hash.
     * @param blockHash The hash of the block
     * @return The block header data
     */
    function getBlockHeader(bytes32 blockHash) external view returns (BlockHeaderData memory);

    /**
     * @notice Returns the current status of a given block
     * @param blockHash The hash of the block to check
     * @return isInMainchain True if the block is in the mainchain, false otherwise
     * @return confirmationsCount The number of blocks that have been mined on top of 
     * the given block if the block is in the mainchain
     */
    function getBlockStatus(bytes32 blockHash) external view returns (bool, uint64);

    /**
     * @notice Returns the Merkle root of a given block hash.
     * This function retrieves the Merkle root from the stored block header data
     * @param blockHash The hash of the block
     * @return The Merkle root of the block
     */
    function getBlockMerkleRoot(bytes32 blockHash) external view returns (bytes32);

    /**
     * @notice Returns the block height for a given block hash
     * This function retrieves the height at which the block exists in the chain
     * @param blockHash The hash of the block
     * @return The height of the block
     */
    function getBlockHeight(bytes32 blockHash) external view returns (uint64);

    /**
     * @notice Returns the block hash for a given block height.
     * This function retrieves the hash of the block from the mainchain at the specified height
     * @param blockHeight The height of the block
     * @return The hash of the block
     */
    function getBlockHash(uint64 blockHeight) external view returns (bytes32);

    /**
     * @notice Checks if a block exists in the contract&apos;s storage.
     * This function verifies the presence of a block by its hash
     * @param blockHash The hash of the block to check
     * @return True if the block exists, false otherwise
     */
    function blockExists(bytes32 blockHash) external view returns (bool);
}
```

All fields within the `BlockHeaderData` struct MUST be converted to big-endian byte order for internal representation and processing within the smart contract.

The `addBlockHeader` function MUST perform the following checks:
- Validate that the submitted raw block header has a fixed size of 80 bytes.
- Enforce all block header validation rules as specified in the &quot;Block Header Validation Rules&quot; section.
- Integrate the new block header into the known chain by calculating its cumulative PoW and managing potential chain reorganizations as defined in the &quot;Mainchain Definition&quot; section.
- Emit a `BlockHeaderAdded` event upon successful addition of the block header.
- Emit a `MainchainHeadUpdated` event if the mainchain was updated.

The `checkTxInclusion` function MUST perform the following steps:
- Check whether the provided `blockHash` is part of the mainchain and ensure its number of confirmations is at least equal to the `minConfirmationsCount` parameter. If any of these checks fail, the function MUST return `false`.
- Using the provided `merkleProof`, `txId`,  and `txIndex`, the function MUST compute the Merkle root.
- The computed Merkle root MUST be compared against the `Merkle Root` field stored within the block header identified by `blockHash`.
- If the computed Merkle root matches the stored `Merkle Root`, the function MUST return `true`. Otherwise, it MUST return `false`.

## Rationale

During the design process of the `SPVGateway` contract, several decisions have been made that require clarification. The following initialization options of the smart contract were considered:

1. **Hardcoding the Bitcoin genesis block:** This approach is the simplest for contract deployment as it embeds the initial state directly in the code. While offering absolute trustlessness of the starting point, it limits availability, as the full sync of the gateway would cost around ~100 ETH at the gas price of 1 gwei.
2. **Initialization from an arbitrary block height by trusting provided cumulative work and height:** Currently, the gateway adopts this method as its initialization mechanism. While implying trust in the initial submitted values, it&apos;s a common practice for bootstrapping light clients and can be secured via off-chain mechanisms for initial validation (e.g., community-verified checkpoints).
3. **Initialization with Zero-Knowledge Proof (ZKP) for historical correctness:** This advanced method involves proving the entire history of Bitcoin up to a specific block using ZKP.

Upon submitting the raw block header, the gateway expects the `BlockHeaderData` fields to be converted to big-endian byte order. This is required to maintain EVM&apos;s efficiency, which is contrary to Bitcoin&apos;s native little-endian integer serialization.

There are no &quot;finality&quot; rules in the `SPVGateway` contract. The determination of such is left to consuming protocols, allowing individual definition to meet required security thresholds.

The inclusion of an OPTIONAL `addBlockHeaderBatch` function offers significant gas optimizations. For batches exceeding 11 blocks, MTP can be calculated using timestamps from `calldata`, substantially reducing storage reads and transaction costs.

## Backwards Compatibility

This EIP is fully backwards compatible.

### Deployment Method

&lt;!-- TODO --&gt;

TBD

## Test Cases

&lt;!-- TODO --&gt;

TBD

## Reference Implementation

A reference implementation of the `SPVGateway` contract can be found [here](/EIPs/assets/eip-8002/contracts/SPVGateway.sol).

[`TargetsHelper`](/EIPs/assets/eip-8002/contracts/libs/TargetsHelper.sol) is a supporting library that provides utility functions for working with Bitcoin&apos;s difficulty targets. It includes methods to convert the `Bits` field from a block header to the corresponding `target` value and vice versa, as well as functions to calculate the new difficulty target during adjustment periods.

&gt; Please note that the reference implementation depends on the `@openzeppelin/contracts v5.2.0`, `@solarity/solidity-lib v3.2.0` and `solady v0.1.23`.

## Security Considerations

Among potential security issues, the following can be noted:

The security of the `SPVGateway` is directly dependent on the security of Bitcoin&apos;s underlying PoW consensus. A successful 51% attack on the Bitcoin network would allow an attacker to submit fraudulent block headers that would be accepted by the contract, compromising its state.

The block header validation rules require a Bitcoin node to check that the newly created block is not more than 2 hours ahead of the node&apos;s network-adjusted time. This check is impossible to implement on the `SPVGateway` smart contract, hence it is omitted.

Unlike other blockchain systems with deterministic finality, Bitcoin&apos;s consensus is probabilistic. The `SPVGateway` contract SHOULD be designed to handle chain reorganizations of arbitrary depth, but it cannot prevent them. As a result, transactions included in a block may not be permanently final. All dApps and protocols relying on this contract MUST implement their own security policies to determine a sufficient number of block confirmations before a transaction is considered &quot;final&quot; for their specific use case.

While the `addBlockHeader` function is permissionless and validates each new header cryptographically, the contract&apos;s initial state (its starting block header, height, and cumulative PoW) is a point of trust. The integrity of the entire chain history within the contract is built upon the correctness of this initial data. Although the EIP&apos;s design allows for flexible bootstrapping, the responsibility for verifying the initial state falls on the community and the dApps that choose to use a specific deployment of the `SPVGateway`.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 07 Aug 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8002</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8002</guid>
      </item>
    
      <item>
        <title>Trustless Agents</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8004-trustless-agents/25098</comments>
        
        <description>## Abstract

This protocol proposes to use blockchains to **discover, choose, and interact with agents across organizational boundaries** without pre-existing trust, thus **enabling open-ended agent economies**.

Trust models are pluggable and tiered, with security proportional to value at risk, from low-stake tasks like ordering pizza to high-stake tasks like medical diagnosis. Developers can choose from different trust models: reputation systems using client feedback, validation via stake-secured re-execution, zero-knowledge machine learning (zkML) proofs, or trusted execution environment (TEE) oracles.

## Motivation

Model context protocol &lt;!-- TODO: double check that this is the correct abbreviation --&gt;(MCP) allows servers to list and offer their capabilities (prompts, resources, tools, and completions), while Agent2Agent &lt;!-- TODO: double check that this is the correct abbreviation --&gt;(A2A) handles agent authentication, skills advertisement via AgentCards, direct messaging, and complete task-lifecycle orchestration. However, these agent communication protocols don&apos;t inherently cover agent discovery and trust.

To foster an open, cross-organizational agent economy, we need mechanisms for discovering and trusting agents in untrusted settings. This ERC addresses this need through three lightweight registries, which can be deployed on any L2 or on Mainnet as per-chain singletons:

**Identity Registry** \- A minimal on-chain handle based on [ERC-721](/EIPs/EIPS/eip-721) with URIStorage extension &lt;!-- Editor&apos;s Note: where is URIStorage defined? Is it an OZ thing? If so, you should include the interface here, or make a separate ERC standardizing it. --&gt;that resolves to an agent&apos;s registration file, providing every agent with a portable, censorship-resistant identifier.

**Reputation Registry** \- A standard interface for posting and fetching feedback signals. Scoring and aggregation occur both on-chain (for composability) and off-chain (for sophisticated algorithms), enabling an ecosystem of specialized services for agent scoring, auditor networks, and insurance pools.

**Validation Registry** \- Generic hooks for requesting and recording independent validators checks (e.g. stakers re-running the job, zkML verifiers, TEE oracles, trusted judges).

Payments are orthogonal to this protocol and not covered here. However, examples are provided showing how **x402 payments** &lt;!-- Editor&apos;s Note: This is a coinbase thing, right? If it isn&apos;t necessary to your standard, can you omit it? --&gt;can enrich feedback signals.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

### Identity Registry

The Identity Registry uses ERC-721 with the URIStorage extension for agent registration, making **all agents immediately browsable and transferable with NFTs-compliant apps**. Each agent is uniquely identified globally by:

* *agentRegistry*: A colon-separated string `{namespace}:{chainId}:{identityRegistry}` (e.g., `eip155:1:0x742...`) where:
  * *namespace*: The chain family identifier (`eip155` for EVM chains)
  * *chainId*: The blockchain network identifier
  * *identityRegistry*: The address where the ERC-721 registry contract is deployed
* *agentId*: The ERC-721 tokenId assigned incrementally by the registry

Throughout this document, *tokenId* in ERC-721 is referred to as *agentId* and *tokenURI* in ERC-721 is referred to as *agentURI*. The owner of the ERC-721 token is the owner of the agent and can transfer ownership or delegate management (e.g., updating the registration file) to operators, as supported by `ERC721URIStorage`.

#### Agent URI and Agent Registration File

The *agentURI* MUST resolve to the agent registration file. It MAY use any URI scheme such as `ipfs://` (e.g., `ipfs://cid`), `https://` (e.g., `https://example.com/agent3.json`), or a base64-encoded `data:` URI (e.g., `data:application/json;base64,eyJ0eXBlIjoi...`) for fully on-chain metadata. When the registration uri changes, it can be updated with *setAgentURI()*.

The registration file MUST have the following structure:

```jsonc
{
  &quot;type&quot;: &quot;https://eips.ethereum.org/EIPS/eip-8004#registration-v1&quot;,
  &quot;name&quot;: &quot;myAgentName&quot;,
  &quot;description&quot;: &quot;A natural language description of the Agent, which MAY include what it does, how it works, pricing, and interaction methods&quot;,
  &quot;image&quot;: &quot;https://example.com/agentimage.png&quot;,
  &quot;services&quot;: [
   {
      &quot;name&quot;: &quot;web&quot;,
      &quot;endpoint&quot;: &quot;https://web.agentxyz.com/&quot;
    },
    {
      &quot;name&quot;: &quot;A2A&quot;,
      &quot;endpoint&quot;: &quot;https://agent.example/.well-known/agent-card.json&quot;,
      &quot;version&quot;: &quot;0.3.0&quot;
    },
    {
      &quot;name&quot;: &quot;MCP&quot;,
      &quot;endpoint&quot;: &quot;https://mcp.agent.eth/&quot;,
      &quot;version&quot;: &quot;2025-06-18&quot;
    },
    {
      &quot;name&quot;: &quot;OASF&quot;,
      &quot;endpoint&quot;: &quot;ipfs://{cid}&quot;,
      &quot;version&quot;: &quot;0.8&quot;, // https://github.com/agntcy/oasf/tree/v0.8.0
      &quot;skills&quot;: [], // OPTIONAL
      &quot;domains&quot;: [] // OPTIONAL
    },
    {
      &quot;name&quot;: &quot;ENS&quot;,
      &quot;endpoint&quot;: &quot;vitalik.eth&quot;,
      &quot;version&quot;: &quot;v1&quot;
    },
    {
      &quot;name&quot;: &quot;DID&quot;,
      &quot;endpoint&quot;: &quot;did:method:foobar&quot;,
      &quot;version&quot;: &quot;v1&quot;
    },
    {
      &quot;name&quot;: &quot;email&quot;,
      &quot;endpoint&quot;: &quot;mail@myagent.com&quot;
    }
  ],
  &quot;x402Support&quot;: false,
  &quot;active&quot;: true,
  &quot;registrations&quot;: [
    {
      &quot;agentId&quot;: 22,
      &quot;agentRegistry&quot;: &quot;{namespace}:{chainId}:{identityRegistry}&quot; // e.g. eip155:1:0x742...
    }
  ],
  &quot;supportedTrust&quot;: [
    &quot;reputation&quot;,
    &quot;crypto-economic&quot;,
    &quot;tee-attestation&quot;
  ]
}
```

The *type*, *name*, *description*, and *image* fields at the top SHOULD ensure compatibility with ERC-721 apps. The number and type of *endpoints* are fully customizable, allowing developers to add as many as they wish. The *version* field in endpoints is a SHOULD, not a MUST.

Agents MAY advertise their endpoints, which point to an A2A agent card, an MCP endpoint, an ENS agent name, DIDs, or the agent&apos;s wallets on any chain (even chains where the agent is not registered).

#### Endpoint Domain Verification (Optional)

Since endpoints can point to domains not controlled by the agent owner, an agent MAY optionally prove control of an HTTPS endpoint-domain by publishing `https://{endpoint-domain}/.well-known/agent-registration.json` containing at least a `registrations` list (or the full agent registration file). Users MAY treat the endpoint-domain as verified if the file is reachable over HTTPS and includes a `registrations` entry whose `agentRegistry` and `agentId` match the on-chain agent; if the endpoint-domain is the same domain that serves the agent’s primary registration file referenced by `agentURI`, this additional check is not needed because domain control is already demonstrated there.

Agents SHOULD have at least one registration (multiple are possible), and all fields in the registration are mandatory.
The *supportedTrust* field is OPTIONAL. If absent or empty, this ERC is used only for discovery, not for trust.

#### On-chain metadata

The registry extends ERC-721 by adding `getMetadata(uint256 agentId, string metadataKey)` and `setMetadata(uint256 agentId, string metadataKey, bytes metadataValue)` functions for optional extra on-chain agent metadata:

```solidity
function getMetadata(uint256 agentId, string memory metadataKey) external view returns (bytes memory)
function setMetadata(uint256 agentId, string memory metadataKey, bytes memory metadataValue) external
```

When metadata is set, the following event is emitted:

```solidity
event MetadataSet(uint256 indexed agentId, string indexed indexedMetadataKey, string metadataKey, bytes metadataValue)
```

The key `agentWallet` is reserved and cannot be set via `setMetadata()` or during `register()` (including the metadata array overload). It represents the address where the agent receives payments and is initially set to the owner&apos;s address. To change it, the agent owner must prove control of the new wallet by providing a valid [EIP-712](/EIPs/EIPS/eip-712) signature for EOAs or [ERC-1271](/EIPs/EIPS/eip-1271) for smart contract wallets—by calling:

```solidity
function setAgentWallet(uint256 agentId, address newWallet, uint256 deadline, bytes calldata signature) external
```

To read and clear the currently set wallet, the following functions are exposed:

```solidity
function getAgentWallet(uint256 agentId) external view returns (address)
function unsetAgentWallet(uint256 agentId) external
```

When the agent is transferred, `agentWallet` is automatically cleared (effectively resetting it to the zero address) and must be re-verified by the new owner.

#### Registration

New agents can be minted by calling one of these functions:

```solidity
struct MetadataEntry {
string metadataKey;
bytes metadataValue;
}

function register(string agentURI, MetadataEntry[] calldata metadata) external returns (uint256 agentId)

function register(string agentURI) external returns (uint256 agentId)

// agentURI is added later with setAgentURI()
function register() external returns (uint256 agentId)
```

This emits one Transfer event, one MetadataSet event for the reserved `agentWallet` key, one MetadataSet event for each additional metadata entry (if any), and

```solidity
event Registered(uint256 indexed agentId, string agentURI, address indexed owner)
```

#### Update agentURI

The agentURI can be updated by calling the following function, which emits a URIUpdated event:

```solidity

function setAgentURI(uint256 agentId, string calldata newURI) external

event URIUpdated(uint256 indexed agentId, string newURI, address indexed updatedBy)

```

If the owner wants to store the entire registration file on-chain, the *agentURI* SHOULD use a base64-encoded data URI rather than a serialized JSON string:

```
data:application/json;base64,eyJ0eXBlIjoi...
```

### Reputation Registry

When the Reputation Registry is deployed, the *identityRegistry* address is set via `initialize(address identityRegistry_)` and publicly visible by calling:

```solidity
function getIdentityRegistry() external view returns (address identityRegistry)
```

The feedback given by a *clientAddress* to an agent consists of a signed fixed-point *value* (`int128`) and its *valueDecimals* (`uint8`, 0-18), plus optional *tag1* and *tag2* (left to developers&apos; discretion to provide maximum on-chain composability and filtering), an *endpoint* URI, a file URI pointing to an off-chain JSON containing additional information, and its KECCAK-256 file hash to guarantee integrity. We suggest using IPFS or equivalent services to make feedback easily indexed by subgraphs or similar technologies. For IPFS URIs, the hash is not required.
All fields except *value* and *valueDecimals* are OPTIONAL, so the off-chain file is not required and can be omitted.

#### Giving Feedback

New feedback can be added by any *clientAddress* calling:

```solidity
function giveFeedback(uint256 agentId, int128 value, uint8 valueDecimals, string calldata tag1, string calldata tag2, string calldata endpoint, string calldata feedbackURI, bytes32 feedbackHash) external
```

The *agentId* must be a validly registered agent. The *valueDecimals* MUST be between 0 and 18. The feedback submitter MUST NOT be the agent owner or an approved operator for *agentId*. *tag1*, *tag2*, *endpoint*, *feedbackURI*, and *feedbackHash* are OPTIONAL.

Where provided, *feedbackHash* is the KECCAK-256 hash (`keccak256`) of the content referenced by *feedbackURI*, enabling verifiable integrity for non-content-addressed URIs. For IPFS (or other content-addressed URIs), *feedbackHash* is OPTIONAL and can be omitted (e.g., set to `bytes32(0)`).

If the procedure succeeds, an event is emitted:

```solidity
event NewFeedback(uint256 indexed agentId, address indexed clientAddress, uint64 feedbackIndex, int128 value, uint8 valueDecimals, string indexed indexedTag1, string tag1, string tag2, string endpoint, string feedbackURI, bytes32 feedbackHash)
```

The feedback fields *value*, *valueDecimals*, *tag1*, *tag2*, and *isRevoked* are stored in the contract storage along with the feedbackIndex (a 1-indexed counter of feedback submissions that *clientAddress* has given to *agentId*). The fields *endpoint*, *feedbackURI*, and *feedbackHash* are emitted but are not stored. This exposes reputation signals to any smart contract, enabling on-chain composability.

When the feedback is given by an agent (i.e., the client is an agent), the agent SHOULD use the address set in the on-chain optional `agentWallet` metadata as the clientAddress, to facilitate reputation aggregation.

#### Examples of `value` / `valueDecimals`

| tag1 | What it measures | Example human value | `value` | `valueDecimals` |
| --- | --- | --- | --- | --- |
| `starred` | Quality rating (0-100) | `87/100` | `87` | `0` |
| `reachable` | Endpoint reachable (binary) | `true` | `1` | `0` |
| `ownerVerified` | Endpoint owned by agent owner (binary) | `true` | `1` | `0` |
| `uptime` | Endpoint uptime (%) | `99.77%` | `9977` | `2` |
| `successRate` | Endpoint success rate (%) | `89%` | `89` | `0` |
| `responseTime` | Response time (ms) | `560ms` | `560` | `0` |
| `blocktimeFreshness` | Avg block delay (blocks) | `4 blocks` | `4` | `0` |
| `revenues` | Cumulative revenues (e.g., USD) | `$560` | `560` | `0` |
| `tradingYield` (`tag2` = `day, week, month, year`) | Yield | `-3,2%` | `-32` | `1` |

#### Off-Chain Feedback File Structure

The OPTIONAL file at the URI could look like:

```jsonc
{
  // MUST FIELDS
  &quot;agentRegistry&quot;: &quot;eip155:1:{identityRegistry}&quot;,
  &quot;agentId&quot;: 22,
  &quot;clientAddress&quot;: &quot;eip155:1:{clientAddress}&quot;,
  &quot;createdAt&quot;: &quot;2025-09-23T12:00:00Z&quot;,
  &quot;value&quot;: 100,
  &quot;valueDecimals&quot;: 0,

  // ALL OPTIONAL FIELDS
  &quot;tag1&quot;: &quot;foo&quot;,
  &quot;tag2&quot;: &quot;bar&quot;,
  &quot;endpoint&quot;: &quot;https://agent.example.com/GetPrice&quot;,

  &quot;mcp&quot;: { &quot;tool&quot;: &quot;ToolName&quot; }, // or: { &quot;prompt&quot;: &quot;PromptName&quot; } / { &quot;resource&quot;: &quot;ResourceName&quot; }

  // A2A: see &quot;Context Identifier Semantics&quot; and Task model in the A2A specification.
  &quot;a2a&quot;: {
    &quot;skills&quot;: [&quot;as-defined-by-A2A&quot;], // e.g., AgentSkill identifiers
    &quot;contextId&quot;: &quot;as-defined-by-A2A&quot;,
    &quot;taskId&quot;: &quot;as-defined-by-A2A&quot;
  },

  &quot;oasf&quot;: {
    &quot;skills&quot;: [&quot;as-defined-by-OASF&quot;],
    &quot;domains&quot;: [&quot;as-defined-by-OASF&quot;]
  },
  
  &quot;proofOfPayment&quot;: { // this can be used for x402 proof of payment
	  &quot;fromAddress&quot;: &quot;0x00...&quot;,
	  &quot;toAddress&quot;: &quot;0x00...&quot;,
	  &quot;chainId&quot;: &quot;1&quot;,
	  &quot;txHash&quot;: &quot;0x00...&quot;
   },

 // Other fields
  &quot; ... &quot;: { &quot; ... &quot; } // MAY
}
```

#### Revoking Feedback

*clientAddress* can revoke feedback by calling:

```solidity
function revokeFeedback(uint256 agentId, uint64 feedbackIndex) external
```

This emits:

```solidity
event FeedbackRevoked(uint256 indexed agentId, address indexed clientAddress, uint64 indexed feedbackIndex)
```

#### Appending Responses

Anyone (e.g., the *agentId* showing a refund, any off-chain data intelligence aggregator tagging feedback as spam) can call:

```solidity
function appendResponse(uint256 agentId, address clientAddress, uint64 feedbackIndex, string calldata responseURI, bytes32 responseHash) external
```

Where *responseHash* is the KECCAK-256 file hash of the *responseURI* file content to guarantee integrity. This field is not required for IPFS URIs.

This emits:

```solidity
event ResponseAppended(uint256 indexed agentId, address indexed clientAddress, uint64 feedbackIndex, address indexed responder, string responseURI, bytes32 responseHash)
```

#### Read Functions

```solidity
function getSummary(uint256 agentId, address[] calldata clientAddresses, string tag1, string tag2) external view returns (uint64 count, int128 summaryValue, uint8 summaryValueDecimals)
// agentId and clientAddresses are mandatory; tag1 and tag2 are optional filters.
// clientAddresses MUST be provided (non-empty); results without filtering by clientAddresses are subject to Sybil/spam attacks. See Security Considerations for details

function readFeedback(uint256 agentId, address clientAddress, uint64 feedbackIndex) external view returns (int128 value, uint8 valueDecimals, string tag1, string tag2, bool isRevoked)

function readAllFeedback(uint256 agentId, address[] calldata clientAddresses, string tag1, string tag2, bool includeRevoked) external view returns (address[] memory clients, uint64[] memory feedbackIndexes, int128[] memory values, uint8[] memory valueDecimals, string[] memory tag1s, string[] memory tag2s, bool[] memory revokedStatuses)
// agentId is the only mandatory parameter; others are optional filters. Revoked feedback are omitted by default.

function getResponseCount(uint256 agentId, address clientAddress, uint64 feedbackIndex, address[] responders) external view returns (uint64 count)
// agentId is the only mandatory parameter; others are optional filters.

function getClients(uint256 agentId) external view returns (address[] memory)

function getLastIndex(uint256 agentId, address clientAddress) external view returns (uint64)
```

We expect reputation systems around reviewers/clientAddresses to emerge. **While simple filtering by reviewer (useful to mitigate spam) and by tag are enabled on-chain, more complex reputation aggregation will happen off-chain**.


### Validation Registry

**This registry enables agents to request verification of their work and allows validator smart contracts to provide responses that can be tracked on-chain**. Validator smart contracts could use, for example, stake-secured inference re-execution, zkML verifiers or TEE oracles to validate or reject requests.

When the Validation Registry is deployed, the *identityRegistry* address is set via `initialize(address identityRegistry_)` and is visible by calling `getIdentityRegistry()`, as described above.

#### Validation Request

Agents request validation by calling:

```solidity
function validationRequest(address validatorAddress, uint256 agentId, string requestURI, bytes32 requestHash) external
```

This function MUST be called by the owner or operator of *agentId*. The *requestURI* points to off-chain data containing all information needed for the validator to validate, including inputs and outputs needed for the verification. The *requestHash* is a commitment to this data (`keccak256` of the request payload) and identifies the request. All other fields are mandatory.

A ValidationRequest event is emitted:

```solidity
event ValidationRequest(address indexed validatorAddress, uint256 indexed agentId, string requestURI, bytes32 indexed requestHash)
```

#### Validation Response

Validators respond by calling:

```solidity
function validationResponse(bytes32 requestHash, uint8 response, string responseURI, bytes32 responseHash, string tag) external
```

Only *requestHash* and *response* are mandatory; *responseURI*, *responseHash* and *tag* are optional. This function MUST be called by the *validatorAddress* specified in the original request. The *response* is a value between 0 and 100, which can be used as binary (0 for failed, 100 for passed) or with intermediate values for validations with a spectrum of outcomes. The optional *responseURI* points to off-chain evidence or audit of the validation, *responseHash* is its commitment (in case the resource is not on IPFS), while *tag* allows for custom categorization or additional data.

validationResponse() can be called multiple times for the same *requestHash*, enabling use cases like progressive validation states (e.g., “soft finality” and “hard finality” using *tag*) or updates to validation status.

Upon successful execution, a *ValidationResponse* event is emitted with all function parameters:

```solidity
event ValidationResponse(address indexed validatorAddress, uint256 indexed agentId, bytes32 indexed requestHash, uint8 response, string responseURI, bytes32 responseHash, string tag)
```

The contract stores *requestHash*, *validatorAddress*, *agentId*, *response*, *responseHash*, *lastUpdate*, and *tag* for on-chain querying and composability.

#### Read Functions

```solidity
function getValidationStatus(bytes32 requestHash) external view returns (address validatorAddress, uint256 agentId, uint8 response, bytes32 responseHash, string tag, uint256 lastUpdate)

//Returns aggregated validation statistics for an agent. agentId is the only mandatory parameter; validatorAddresses and tag are optional filters
function getSummary(uint256 agentId, address[] calldata validatorAddresses, string tag) external view returns (uint64 count, uint8 averageResponse)

function getAgentValidations(uint256 agentId) external view returns (bytes32[] memory requestHashes)

function getValidatorRequests(address validatorAddress) external view returns (bytes32[] memory requestHashes)
```

Incentives and slashing related to validation are managed by the specific validation protocol and are outside the scope of this registry.

## Rationale

* **Agent communication protocols**: MCP and A2A are popular, and other protocols could emerge. For this reason, this protocol links from the blockchain to a flexible registration file including a list where endpoints can be added at will, combining AI primitives (MCP, A2A) and Web3 primitives such as wallet addresses, DIDs, and ENS names.
* **Feedback**: The protocol combines the leverage of nomenclature already established by A2A (such as tasks and skills) and MCP (such as tools and prompts) with complete flexibility in the feedback signal structure.
* **Gas Sponsorship**: Since clients don&apos;t need to be registered anymore, any application can implement frictionless feedback leveraging [EIP-7702](/EIPs/EIPS/eip-7702).
* **Indexing**: Since feedback data is saved on-chain and we suggest using IPFS for full data, it&apos;s easy to leverage subgraphs to create indexers and improve UX.
* **Deployment**: We expect the registries to be deployed with singletons per chain. Note that an agent registered and receiving feedback on chain A can still operate and transact on other chains. Agents can also be registered on multiple chains if desired.

&lt;!-- Editor&apos;s Note: The test cases section should be a list of input/output/state changes or automated test functions. Simply listing &quot;what to test&quot; is insufficient. --&gt;

&lt;!--

## Test Cases

This protocol enables:

* Crawling all agents starting from a logically centralized endpoint and discover agent information (name, image, services), capabilities, communication endpoints (MCP, A2A, others), ENS names, wallet addresses and which trust models they support (reputation, validation, TEE attestation)
* Building agent explorers and marketplaces using any ERC-721 compatible application to browse, transfer, and manage agents
* Building reputation systems with on-chain aggregation (average scores for smart contract composability) or sophisticated off-chain analysis. All reputation signals are public good.
* Discovering which agents support stake-secured or zkML validation and how to request it through a standardized interface

--&gt;

## Security Considerations

* Sybil attacks are possible, inflating the reputation of fake agents. The protocol&apos;s contribution is to make signals public and use the same schema. We expect many players to build reputation systems, for example, trusting or giving reputation to reviewers (and therefore filtering by reviewer, as the protocol already enables).
* On-chain pointers and hashes cannot be deleted, ensuring audit trail integrity
* Validator incentives and slashing are managed by specific validation protocols
* While this ERC cryptographically ensures the registration file corresponds to the on-chain agent, it cannot cryptographically guarantee that advertised capabilities are functional and non-malicious. The three trust models (reputation, validation, and TEE attestation) are designed to support this verification need

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 13 Aug 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8004</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8004</guid>
      </item>
    
      <item>
        <title>Glamsterdam Gas Repricings</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8007-glamsterdam-gas-repricings-meta-eip/25206</comments>
        
        <description>## Abstract

This Meta EIP documents all the proposals for Glamsterdam related to the gas repricing effort. The goal of this effort is to harmonize gas costs across the EVM, thereby reducing the impact of specific bottlenecks on scaling. Proposals include changes to the cost of single EVM operations, as well as bigger changes to the gas model. This Meta EIP is purely informational and does not aim to have an active role in the governance process for the Glamsterdam fork. Instead, it serves as a directory for all repricing-related proposals, helping to organize the work and keeping the community informed about the status of each EIP.

## Motivation

The main objective of the Glamsterdam fork is to improve L1 scalability. A crucial aspect of this initiative is to create a better alignment between gas costs and actual resource usage. Currently, the gas model often misprices operations, resulting in inefficiencies and unintended incentives. For instance, within the pure compute operations, there is a high variance in execution time per gas unit, which indicates that a single unit of computation is not priced equally across the various opcodes.

By standardizing gas costs across EVM operations and other resources, we can reduce bottlenecks and enhance the utilization of EVM resources, which will subsequently enable further scalability. The EIPs listed below constitute a significant first step in that direction. We expect that further iteration will be necessary in future hardforks.

## Specification

The following table lists all EIPs related to repricings that are being discussed in the scope of the Glamsterdam fork. There are three types of EIPs in this list:

1. **Broad harmonization**. These EIPs reprice a class of operations with the goal of harmonizing them and removing single bottlenecks.
2. **Pricing extension**. These EIPs make targeted changes to a specific opcode or component of the gas model, usually coupled with a new mechanism.
3. **Supporting**. These EIPs are not directly doing a repricing, but instead introduce a change that support other repricing EIPs or enhance the scalability potential of repricings.

### Considered for Inclusion

| EIP | Description | Type | Resource class | Gas change overview |
|:---:|---|---|:---:|---|
| [EIP-2780](/EIPs/EIPS/eip-2780) | Reduce intrinsic transaction gas and charge 25k when a value transfer creates a new account. | Broad harmonization | Multi-resource | Decrease `TX_BASE_COST` (21k→4.5k); increase new-account surcharge (0→25k) |
| [EIP-7778](/EIPs/EIPS/eip-7778) | Prevent Block Gas Limit Circumvention by Excluding Refunds from Block Gas Accounting. | Pricing extension | General Accounting | No opcode repricing; excludes gas refunds (e.g. `SSTORE` clearing) from block gas accounting |
| [EIP-7904](/EIPs/EIPS/eip-7904) | Gas Cost Increase to reflect computational complexity and transaction throughput increase | Broad harmonization | Compute | All increase: `DIV`, `SDIV`, `MOD`, `MULMOD`, `KECCAK256`, precompiles (`BLAKE2F`, `BLS12_G1ADD`, `BLS12_G2ADD`, `ECADD`, `ECPAIRING`, `POINT_EVALUATION`) |
| [EIP-7976](/EIPs/EIPS/eip-7976) | Increase the calldata floor cost to 64/64 gas per byte to reduce maximum block size. | Pricing extension | Data | Increase calldata floor cost (10/40 → 64/64 per byte) |
| [EIP-7981](/EIPs/EIPS/eip-7981) | Price access lists for data to reduce maximum block size. | Pricing extension | Data | Increase: new floor charge on access list data (addresses + storage keys) |
| [EIP-8037](/EIPs/EIPS/eip-8037) | Harmonization, increase and separate metering of state creation gas costs to mitigate state growth and unblock scaling. | Broad harmonization | State | All increase (dynamic with gas limit): `GAS_CREATE`, `GAS_CODE_DEPOSIT`, `GAS_NEW_ACCOUNT`, `GAS_STORAGE_SET`, `PER_AUTH_BASE_COST` |
| [EIP-8038](/EIPs/EIPS/eip-8038) | Increases the gas cost of state-access operations to reflect Ethereum&apos;s larger state. | Broad harmonization | State | All increase: cold storage write/access, cold account access, warm access, `EXTCODESIZE`/`EXTCODECOPY` extra read, access list costs |

### Declined for Inclusion

| EIP | Description | Type | Resource class |
|:---:|---|---|:---:|
| [EIP-2926](/EIPs/EIPS/eip-2926) | Introduce code-chunking in an MPT context. | Pricing extension | State |
| [EIP-7686](/EIPs/EIPS/eip-7686) | Adjust memory limits and gas limits of sub-calls to create a clear linear bound on how much total memory an EVM execution can consume. | Pricing extension | Memory |
| [EIP-7923](/EIPs/EIPS/eip-7923) | Linearize Memory Costing and replace the current quadratic formula with a page-based cost model. | Pricing extension | Memory |
| [EIP-7971](/EIPs/EIPS/eip-7971) | Decrease costs for `TLOAD` and `TSTORE` with a transaction-global limit. | Pricing extension | Memory |
| [EIP-7973](/EIPs/EIPS/eip-7973) | Introduce warm account writes, decreasing the cost of writing to an account after the first write. | Pricing extension | State |
| [EIP-8011](/EIPs/EIPS/eip-8011) | Gas accounting by EVM resource, increasing throughput and improving resource usage controls, with minimal changes to the protocol and UX. | Supporting | NA |
| [EIP-8032](/EIPs/EIPS/eip-8032) | Makes `SSTORE` gas cost scale with a contract&apos;s storage size to discourage state bloat. | Pricing extension | State |
| [EIP-8053](/EIPs/EIPS/eip-8053) | Adds `milli-gas` as the EVM&apos;s internal gas accounting unit, reducing rounding errors without impacting UX. | Supporting | NA |
| [EIP-8057](/EIPs/EIPS/eip-8057) | Multi‑block temporal locality discounts for state and account access. | Pricing extension | State |
| [EIP-8058](/EIPs/EIPS/eip-8058) | Reduces gas costs for deploying duplicate contract bytecode via access-list based mechanism. | Pricing extension | State |
| [EIP-8059](/EIPs/EIPS/eip-8059) | Gas parameters and variables are increased to a factor of `REBASE_FACTOR` to reduce rounding errors without major changes to the EVM. | Supporting | NA |

## Rationale

### Gas cost changes by operation

The following tables summarize the preliminary gas cost changes. Numbers are not yet finalized and will be subject to change.

#### Compute Opcodes — [EIP-7904](/EIPs/EIPS/eip-7904) (all increase)

| Opcode | Name | Current | New | Direction |
| --- | --- | ---: | ---: | --- |
| 0x04 | `DIV` | 5 | 15 | increase |
| 0x05 | `SDIV` | 5 | 20 | increase |
| 0x06 | `MOD` | 5 | 12 | increase |
| 0x09 | `MULMOD` | 8 | 11 | increase |
| 0x20 | `KECCAK256` (base) | 30 | 45 | increase |

`KECCAK256` per-word cost stays at 6. `ADDMOD`, `SMOD`, and `ECRECOVER` are unchanged.

#### Precompiles — [EIP-7904](/EIPs/EIPS/eip-7904) (all increase)

| Precompile | Current | New | Direction |
| --- | ---: | ---: | --- |
| `BLAKE2F` (base) | 0 | 170 | increase |
| `BLAKE2F` (per round) | 1 | 2 | increase |
| `BLS12_G1ADD` | 375 | 643 | increase |
| `BLS12_G2ADD` | 600 | 765 | increase |
| `ECADD` | 150 | 314 | increase |
| `ECPAIRING` (per pair) | 34,000 | 34,103 | increase (slight) |
| `POINT_EVALUATION` | 50,000 | 89,363 | increase |

#### State Access — [EIP-8038](/EIPs/EIPS/eip-8038) (all increase, values TBD)

| Opcode(s) | Component | Current | New | Direction |
| --- | --- | ---: | --- | --- |
| `SSTORE` | `GAS_COLD_STORAGE_WRITE` | 5,000 | TBD | increase |
| `SSTORE`, `SLOAD` | `GAS_COLD_STORAGE_ACCESS` | 2,100 | TBD | increase |
| `CALL`, `STATICCALL`, `DELEGATECALL`, `BALANCE`, `EXT*`, `SELFDESTRUCT` | `GAS_COLD_ACCOUNT_ACCESS` | 2,600 | TBD | increase |
| All state ops (warm) | `GAS_WARM_ACCESS` | 100 | TBD | increase |
| `EXTCODESIZE` | Extra warm read for 2nd DB lookup | 0 | +`GAS_WARM_ACCESS` | increase (new) |
| `EXTCODECOPY` | Extra warm read for 2nd DB lookup | 0 | +`GAS_WARM_ACCESS` | increase (new) |
| `SSTORE`, `SLOAD` (access list) | `ACCESS_LIST_STORAGE_KEY_COST` | 1,900 | TBD | increase |
| `CALL` etc. (access list) | `ACCESS_LIST_ADDRESS_COST` | 2,400 | TBD | increase |

#### State Creation — [EIP-8037](/EIPs/EIPS/eip-8037) (all increase, dynamic with gas limit)

At 60M gas limit, `cost_per_state_byte` (cpsb) = 662. Costs scale up with higher gas limits.

| Operation | Opcodes Affected | Current | New (at 60M) | Direction |
| --- | --- | ---: | ---: | --- |
| `GAS_CREATE` | `CREATE`, `CREATE2`, create txs | 32,000 | 112 x cpsb + 9,000 (~83k) | increase |
| `GAS_CODE_DEPOSIT` | `CREATE`, `CREATE2`, create txs | 200/byte | cpsb/byte + hash (~662/byte) | increase |
| `GAS_NEW_ACCOUNT` | `CALL*` to new accounts | 25,000 | 112 x cpsb (~74k) | increase |
| `GAS_STORAGE_SET` | `SSTORE` (0 -&gt; non-zero) | 20,000 | 32 x cpsb + 2,900 (~24k) | increase |
| `PER_AUTH_BASE_COST` | EIP-7702 auth | 12,500 | 23 x cpsb + 7,500 (~22.7k) | increase |
| `PER_EMPTY_ACCOUNT_COST` | EIP-7702 auth | 25,000 | 112 x cpsb (~74k) | increase |

#### Transaction-Level Costs

| Parameter | Current | New | Direction | EIP |
| --- | ---: | --- | --- | --- |
| `TX_BASE_COST` | 21,000 | 4,500 | decrease | [2780](/EIPs/EIPS/eip-2780) |
| New account surcharge (top-level value tx) | 0 | 25,000 | increase | [2780](/EIPs/EIPS/eip-2780) |
| Calldata floor cost | 10/40 per byte | 64/64 per byte | increase | [7976](/EIPs/EIPS/eip-7976) |
| Access list data cost | 0 | `floor_token_cost` per token | increase (new) | [7981](/EIPs/EIPS/eip-7981) |

## Security Considerations

Discussed in the individual EIPs.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 21 Aug 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8007</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8007</guid>
      </item>
    
      <item>
        <title>Multidimensional Gas Metering</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8011-multidimensional-gas-metering/25260</comments>
        
        <description>## Abstract

This proposal introduces multidimensional gas metering, changing the way we account for gas used at the block level. This enables Ethereum to increase throughput and better control excessive resource usage, with minimal changes to the protocol and the UX. During transaction execution, gas is metered for each resource dimension, such as compute and state. At the transaction level, everything remains unchanged. A transaction still pays fees according to the sum of gas used across all resources and still has a single gas limit imposed on this same sum. However, 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&apos;s gas limit and the block&apos;s gas target, which now corresponds to the maximum gas that can be metered in the bottleneck resource.

## Motivation

This proposal separates *transaction pricing* (i.e., the way of measuring consumption of resources by transactions) from *block metering* (i.e., the way of controlling resource limits and ensure that blocks do not overload the network). More concretely, it introduces a multidimensional metering scheme that accounts for the different EVM resources while keeping the pricing model unchanged.

There are four main benefits of the proposal:

1. Throughput gains: By decoupling resource limits, blocks can carry transactions that stress distinct resources simultaneously, improving packing efficiency.
2. Finer-grained control over excessive resource usage: metering gas costs independently for each resource allows us to tailor each operation&apos;s gas cost to the actual resource limits.
3. Keeps UX identical: users still specify one `gas_limit` and see one `gas_used` value.
4. Simplicity: This simpler metering change lays the groundwork for eventual multidimensional pricing (such as [EIP-7999](/EIPs/EIPS/eip-7999)) without disrupting the current fee market and with minimal protocol changes.

## Specification

### Operation gas costs

Under the multidimensional metering model, EVM operations are assigned a cost vector whose components correspond to their gas cost on each resource dimension. Each cost has 6 dimensions: `gas_cost_vector = (compute_cost, access_cost, size_cost, memory_cost, state_cost, history_cost)`.

#### Pure compute operations

The operations listed in [compute_ops](/EIPs/assets/eip-8011/compute_ops) are assigned a `gas_cost_vector` equal to `(gas_cost, 0, 0, 0, 0, 0)`, where `gas_cost` is the operation&apos;s gas cost.

#### Compute and memory operations

The operations listed in [compute_mem_ops](/EIPs/assets/eip-8011/compute_mem_ops) are assigned a `gas_cost_vector` equal to `(compute_cost, 0, 0, memory_cost, 0, 0)`, where `memory_cost` is the operation&apos;s memory expansion cost (as defined by the function [`calculate_gas_extend_memory`]) and `compute_cost` is the operation&apos;s gas cost minus its memory expansion cost.

[`calculate_gas_extend_memory`]: https://github.com/ethereum/execution-specs/blob/91824145ef62da61803edf9a764fd8f3662794c0/src/ethereum/osaka/vm/gas.py#L167

#### State operations

The assignment of a `gas_cost_vector` to the operations listed in [state_ops](/EIPs/assets/eip-8011/state_ops) is TBD, pending benchmarks.
&lt;-- TODO --&gt;

#### LOG operations

The assignment of a `gas_cost_vector` to the operations listed in [log_ops](/EIPs/assets/eip-8011/log_ops) is TBD, pending benchmarks.
&lt;-- TODO --&gt;

### Intrinsic gas costs

Under the multidimensional metering model, each transaction&apos;s intrinsic cost (as defined by the function [`calculate_intrinsic_cost`]) is also assigned 6-dimensional `gas_cost_vector`. The breakdown of cost by resource dimension is TBD, pending benchmarks.

[`calculate_intrinsic_cost`]: https://github.com/ethereum/execution-specs/blob/91824145ef62da61803edf9a764fd8f3662794c0/src/ethereum/osaka/transactions.py#L571
&lt;-- TODO --&gt;

### Gas accounting

Besides replacing the single gas cost with a 6-dimensional cost vector, the gas accounting during block execution also changes. Instead of keeping track of a single total of gas used, the EVM stores a 6-dimensional vector with how much gas units was spent on each resource until that point in the execution.

After executing the ith EVM operation of a transaction, say `OP_i`, with a cost vector `gas_cost_vector_i = (compute_cost_i, access_cost_i, size_cost_i, memory_cost_i, state_cost_i, history_cost_i)`, the following variables are updated:

- Remaining available gas for the transaction:
  - `gas = gas - sum(compute_cost_i, access_cost_i, size_cost_i, memory_cost_i, state_cost_i, history_cost_i)`
- Total used gas by the transaction so far:
  - `gas_used = gas_used + sum(compute_cost_i, access_cost_i, size_cost_i, memory_cost_i, state_cost_i, history_cost_i)`
- Used gas vector by the transaction so far:
  - `gas_used_vector = (compute_gas_used + compute_cost_i, access_gas_used + access_cost_i, size_gas_used + size_cost_i, memory_gas_used + memory_cost_i, state_gas_used + state_cost_i, history_gas_used + history_cost_i)`

At the transaction level, everything remains the same. A transaction still has the same one-dimensional `gas_limit`. The transaction&apos;s out-of-gas condition is still defined as `gas_used &lt;= gas_limit`. Additionally, the transaction&apos;s fee is also computed with `gas_used`.

The key change is the introduction of `gas_used_vector` as a new variable that tracks the gas used by each resource at the transaction level. This variable is returned by the `execute_transaction` function, in addition to `gas_used`:

```python
def execute_transaction(self, transaction: NormalizedTransaction, effective_gas_price: int) -&gt; tuple[int, list]: pass
```

### Block header extension

The current header encoding is extended with a new 64-bit unsigned integer field named `max_gas_metered`. This integer corresponds to the total gas units used by the bottleneck resource, i.e., the resource with the largest used gas in the block. This variable is computed as follows:

```python
def compute_block_max_gas_metered(block: Block) -&gt; int:
    transactions = self.transactions(block)
    block_gas_used_vector = array(0, 0, 0, 0, 0, 0)
    for transaction in transactions:
        gas_used, gas_used_vector = self.execute_transaction(transaction, effective_gas_price)
        block_gas_used_vector += gas_used_vector
    max_gas_metered = max(block_gas_used_vector)
    return max_gas_metered
```

The header sequence with the new field is `[..., parent_beacon_block_root, requests_hash, max_gas_metered]`.

### Block validity condition

The block validity conditions are modified to replace `block.gas_used` with `block.max_gas_metered`:

```python
assert block.max_gas_metered &lt;= block.gas_limit, &apos;invalid block: too much gas used&apos;
```

### Base fee update rule

The block validity conditions are modified to replace `parent.gas_used` with `parent.max_gas_metered`:

```python
gas_used_delta = parent.max_gas_metered - parent.gas_target
```

This change is compatible with the various transaction variants, such as [EIP-1559](/EIPs/EIPS/eip-1559), [EIP-4844](/EIPs/EIPS/eip-4844),  or [EIP-7999](/EIPs/EIPS/eip-7999).

## Rationale

### Why are we choosing this resource split?

Ethereum’s slot-based structure introduces a strict temporal constraint: all attestations must be processed, aggregated, and propagated within a single slot. This fact makes time a fundamental resource. To maintain network health, validators must execute blocks, validate them, and gossip attestations quickly enough to avoid missed slots and penalties.

Each type of resource contributes differently to this bottleneck:

- Execution time affects how quickly validators can process blocks and produce attestations.
- Data size influences how long it takes to propagate blocks and blobs across the peer-to-peer network.
- Memory usage determines how efficiently nodes can handle concurrent workloads without triggering garbage collection or cache eviction. It also affects the minimum hardware requirements that proposers and attesters must meet to fulfill their responsibilities.
- State growth impacts long-term scalability and database performance, especially for archival and full nodes.

In addition, changes in the slot (e.g., Enshrined Proposer-Builder Separation) and changes in the execution model (e.g., Block-level Access Lists) will change how the different resources interact and how they impact the available slot time. Thus, we want to track as many relevant resources as possible in order to allow for future changes to the protocol that may impact resource contribution.

For these reasons, the proposal splits the resources into the following broad categories:

1. **Block Execution Time**: Captures how long it takes to process a block on a single node. This includes:
    - Compute: CPU time spent on each operation.
    - State Access: Time or count of disk I/O operations when accessing the trie (e.g., `SLOAD`/`SSTORE`).
2. **Block Upload/Download Time**: Captures how data size affects network transmission:
    - Block size (call data + transaction &amp; block metadata)
3. **Short-term Memory**: Reflects short-term memory allocation during execution, i.e., RAM usage
4. **Long-term Storage**: Tracks persistent changes to disk usage. There are two dimensions here:
    - State Growth: Delta in disk size of the state trie before and after execution.
    - History Growth: Delta in disk space used for historical receipts, logs, etc.

Note that we are not considering the blob resource (which is part of the Block Upload/Download Time) as it is already priced independently.

Based on previous empirical analysis, state growth represented a significant portion of the gas used in Ethereum blocks, accounting for 30.2% of all gas consumed between blocks 22000000 and 22005000. The second resource with the most gas used was compute (26.8%), followed by state access (21.9%). History growth and data had a less relevant contribution, accounting for 9.9% and 6.9% of all the gas used, respectively. Note that the data component in this analysis did not consider blobs.

## Backwards Compatibility

This change is not backwards-compatible and requires a hard fork.

## Security Considerations

### Worst-case blocks and excessive resource usage

A concern about metering resources independently is the potential of creating worst-case blocks that put too much pressure on EVM resources. Thus, the cost vectors of each EVM operation need to be carefully set up to avoid this scenario. To this end, we will perform comprehensive benchmarks to measure the resource utilization of each operation and set the gas cost vector accordingly.

Additionally, state and history growth are not constrained at the block level, but over longer time frames. Increased aggregate gas usage from this proposal may be associated with increase state-growth, assuming that relative gas consumption across resources is not altered significantly under equilibrium. To keep the long-run consumption in check, the gas cost of operations contributing to state and history growth would thus need to be increased.

### Base fee manipulation

Builders can manipulate the base fee by selectively including or excluding transactions to change the block&apos;s `max_gas_metered`. This behavior is already possible with EIP-1559. Yet, multidimensional gas metering computes the base fee on the bottleneck resource instead of the total gas consumed. This allows for blocks that yield the same total fees but with different `max_gas_metered` values. The extent of this concern is limited by the incentives to maximize fee revenue. While the expected gains of base fee manipulation are smaller than execution rewards, we won&apos;t observe these attacks.

### Added complexity in block building

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.

### Censorship resistance

This EIP makes it cheaper to fill the block to censor transactions under FOCIL in [EIP-7805](/EIPs/EIPS/eip-7805) (as also noted in [EIP-7999](/EIPs/EIPS/eip-7999)). Specifically, it can be cheaper for a builder to create dummy transaction consuming only one resource to fill the block, taking advantage of the lower base fee under equilibrium. However, given that all resources have the same base fee in this proposal, and that the builder must still fill the block up to the gas limit for at least one resource, the degradation in censorship resistance is fairly moderate, and mainly related to the potentially reduced base fee under equilibrium.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 22 Aug 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8011</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8011</guid>
      </item>
    
      <item>
        <title>Generalized consolidation requests</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8012-generalized-consolidation-requests/25264</comments>
        
        <description>## Abstract

This EIP redefines the field `target_pubkey` from consolidations requests into a general array of 48 bytes that can be interpreted separately by the consensus layer.

## Motivation

The current contract to send consolidation requests is not optimized in that the exact same contract, with the exact same calldata and engine API, can be used to transmit more general messages from the EL to the CL without changes on the EL side. In particular, avoiding any cross layer coordination in the event of an CL hard fork.

As a possible application, we could use the same contract to allow any existing validator to become a builder as in [EIP-7732](/EIPs/EIPS/eip-7732).

## Specification

### Constants

#### Consensus Layer

| NAME | Value | Comment |
| - | - | - |
| `MAGIC_PREFIX` | `0xEF0A11` | 3 byte prefix to all generalized consolidation requests |

### Execution Layer

No changes are expected

### Consensus Layer

This EIP does not establish any changes on the consensus layer, but rather standardizes how consolidation requests are to be treated in the future. When receiving a `ConsolidationRequest` type object on the consensus layer, the `target_pubkey` field is to be treated differently. If it coincides with the BLS publick key of an existing active validator in the beacon chain, then it is to be interpreted as such. Otherwise, the 48 bytes are to be interpreted as a concatenation of the following fields

```
|MAGIC_PREFIX | CALL_TYPE | ARG_NUMBER | ARG1 | ARG2 | ARG3 | ARG4 | ARG5 |
```

Where `MAGIC_PREFIX` is the 3 byte constant that prefixes all generalized consolidation requests. `CALL_TYPE` are 4 bytes to be interpretted as a little Endian `uint32` and identifies the function type. `ARG_NUMBER` is a 1 byte to be interpretted as a `uint8` that encodes the number of arguments that are being passed to the generalized consolidation request handler. And each `ARG1, ARG2, ARG3, ARG4, ARG5` are all interpretted as little Endian `uint64`.

For each addition of a new `CALL_TYPE`, the consensus layer must add a handler appropriately called from within `process_consolidation_requests`.

### Engine API

No changes needed.

## Rationale

The proposed reinterpretation of the existing contract enables new implementations in the consensus layer without requireing a hard fork in the execution layer.

## Backwards Compatibility

This EIP is fully backwards compatible.

## Security Considerations

No known security impacts.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 22 Aug 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8012</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8012</guid>
      </item>
    
      <item>
        <title>Static relative jumps and calls for the EVM</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8013-static-relative-jumps-and-calls-for-the-evm/25222</comments>
        
        <description>## Abstract

Five new EVM jump instructions are introduced (`RJUMP`, `RJUMPI`, `RJUMPV`, `RJUMPSUB`, and `RJUMPSUBV`) which encode destinations as signed immediate values. These can be useful in almost all `JUMP` and `JUMPI` use cases and offer improvements in cost, performance, and static analysis.

## Motivation

A recurring discussion topic is that the EVM only has a mechanism for dynamic jumps. They provide a very flexible architecture with only 2 (!) instructions. This flexibility comes at a cost however: it makes analysis of code more complicated, often intractable, and it also (partially) resulted in the need to have the `JUMPDEST` marker.

In a great many cases control flow is actually static and there is no need for any dynamic behaviour, though not every use case can be solved by static jumps.

There are various ways to reduce the need for dynamic jumps, some examples:

1. With native support for functions / subroutines
2. A &quot;return to caller&quot; instruction -- a form of subroutine return
3. A &quot;switch-case&quot; table with dynamic indexing

This proposal introduces a minimal feature set - including the above - to allow compilers to use `RJUMP`/`RJUMPI`/`RJUMPSUB` exclusively.

This functionality does not preclude the EVM from introducing other forms of control flow later on. `RJUMP`/`RJUMPI` can efficiently co-exists with a higher-level declaration of functions, where static relative jumps should be used for intra-function control flow.  This functionality also does not preclude the use of legacy code.

The main benefit of these instruction is reduced gas cost (both at deploy and execution time), better performance and better static analysis properties.

## Specification

We introduce five new instructions, each taking either a two-byte relative offset or else a table of offsets as immediate arguments.

1) relative jump:
   * `RJUMP (0xe0) relative_offset`
     * sets the `PC` to `PC_post_instruction + relative_offset`, where
     * `relative_offset` is encoded as a 16-bit **signed** (two&apos;s-complement) big-endian value.
2) conditional relative jump:
   * `RJUMPI (0xe1) relative_offset`
     * pops a value (`condition`) from the stack, and
     * sets the `PC` to `PC_post_instruction + ((condition == 0) ? 0 : relative_offset)`.
3) relative jump via jump table:
   * `RJUMPV (0xe2) max_index relative_offset+`
     * pops a value (`case`) from the stack, and
     * sets the `PC` to `PC_post_instruction + ((case &gt; max_index) ? 0 : relative_offset[case])`.
4) relative jump to subroutine:
   * `RJUMPSUB (0xe3) relative_offset`
     * pushes `PC_post_instruction` to the `return stack,` and
     * sets the `PC` to `PC_post_instruction + relative_offset`, an `ENTERSUB`, as if with `CALLSUB`.
5) relative jump to subroutine via jump table:
   * `RJUMPSUBV (0xe4) max_index relative_offset+
     * pops a value (`case`) from the stack,
     * pushes `PC_post_instruction` to the `return stack`, and
     * sets the `PC` to `PC_post_instruction + ((case &gt; max_index) ? 0 : relative_offset[case])`, an `ENTERSUB`, as if with `CALLSUB`.

Note that the destination of the `RJUMPSUB` and `RJUMPSUBV` opcodes MUST be an `ENTERSUB` and control is returned to a calling `RJUMPSUB` / `RJUMPSUBV` via `RETURNSUB` (See [EIP-7979](/EIPs/EIPS/eip-7979)) -- these two forms of jump provide immediate access to the underlying &quot;return-to-caller&quot; mechanism of the `CALLSUB` instruction.

The immediate argument `relative_offset` is encoded as a 16-bit **signed** (two&apos;s-complement) big-endian value. Under `PC_post_instruction` we mean the `PC` position after the entire immediate value.

The immediate encoding of `RJUMPV` and `RjUMPSUBV` are more special: the unsigned 8-bit `max_index` value determines the maximum index in the jump table. The number of `relative_offset` values following is `max_index+1`. This allows table sizes up to 256. The encoding of `RJUMPV` must have at least one `relative_offset` and thus it will take at minimum 4 bytes. Furthermore, the `case &gt; max_index` condition falling through means that in many use cases, one would place the *default* path following the `RJUMPV` instruction. An interesting feature is that `RJUMPV 0 relative_offset` is an inverted-`RJUMPI`, which can be used in many cases instead of `ISZERO RJUMPI relative_offset`.

We also extend the validation algorithm of [EIP-7979](/EIPs/EIPS/eip-7979) to verify that every `RJUMP`/`RJUMPI`/`RJUMPV`/`RJUMPSUB`/`RJUMPSUBV` has a `relative_offset` pointing to an instruction. This means it cannot point to an immediate data of `PUSHn`/`RJUMP`/`RJUMPI`/`RJUMPV` and cannot point outside of code bounds.  Further, *all and only* `RJUMPSUB` and `RJUMPSUBV` MUST have a `relative offset` pointing to an `ENTERSUB, whereas the others are allowed to point to a JUMPDEST, but are not required to. 

### Costs

The immediate destinations are checked during jumpdest analysis and need not be checked again, so the cost of these instructions can be less than their dynamic counterparts.  We recommend that

* `RJUMP` should be 2,
* `RJUMPI` and `RJUMPV` should be 4. and
* `RJUMPSUB` and `RJUMPSUBV` should be 5.

## Rationale

### Relative addressing

We chose relative addressing in order to support code which is relocatable. This also means a code snippet can be injected. A technique seen used prior to this EIP to achieve the same goal was to inject code like `PUSHn PC ADD JUMPI`.

We do not see any significant downside to relative addressing and it allows us to also deprecate the `PC` instruction.

### Immediate size

The signed 16-bit immediate means that the largest jump distance possible is 32767. In the case the bytecode at `PC=0` starts with an `RJUMP`, it will be possible to jump as far as `PC=32770`.

Given `MAX_CODE_SIZE = 24576` (in [EIP-170](/EIPs/EIPS/eip-170)) and `MAX_INITCODE_SIZE = 49152` (in [EIP-3860](/EIPs/EIPS/eip-3860)), we think the 16-bit immediate is large enough.

A version with an 8-bit immediate would only allow moving `PC` backward by 125 or forward by 127 bytes. While that seems to be a good enough distance for many for-loops, it is likely not good enough for cross-function jumps, and since the 16-bit immediate is the same size as what a dynamic jump would take in such cases (3 bytes: `JUMP PUSH1 n`), we think having less instructions is better.

Should there be a need to have immediate encodings of other size (such as 8-bits, 24-bits or 32-bits), it would be possible to introduce new opcodes, similarly to how multiple `PUSH` instructions exist.

### `PUSHn JUMP` sequences

If we chose absolute addressing, then `RJUMP` could be viewed similar to the sequence `PUSHn JUMP` (and `RJUMPI` similar to `PUSHn JUMPI`). In that case one could argue that instead of introducing a new instruction, such sequences should get a discount, because EVMs could optimise them.

We think this is a bad direction to go, and we leave defining the semantics of existing `PUSHn JUMP` sequences to EIP-7979 and do not attempt to optimize their gas cost here.

1. It further complicates the already complex rules of gas calculation.
2. And it either requires a consensus defined internal representation for EVM code, or forces EVM implementations to do optimisations on their own.

Both of these are risky. Furthermore we think that EVM implementations should be free to chose what optimisations they apply, and the savings do not need to be passed down at all cost.

Additionally it requires a potentially significant change to the current implementations which depend on a streaming one-by-one execution without a lookahead.


### Lack of `JUMPDEST`

`JUMPDEST` serves two purposes:

1. To efficiently partition code -- this can be useful for pre-calculating total gas usage for a given *block* (i.e. instructions between `JUMPDEST`s), and for JIT/AOT translation.
2. To explicitly show valid locations (otherwise any non-data location would be valid).

This functionality is not needed for static jumps, as the analysers can easily tell destinations from the static jump immediates during jumpdest-analysis.

There are two benefits here:

1. Not wasting a byte for a `JUMPDEST` also means a saving of 200 gas during deployment, for each jump destination.
2. Saving an extra 1 gas per jump during execution, given `JUMPDEST` itself cost 1 gas and is &quot;executed&quot; during jumping.

### `RJUMPV` and `RJUMPSUBV` fallback cases

If no match is found (i.e. the *default* case) in the `RJUMPV` or `RJUMPSUBV` instructions execution will continue without branching. This allows for gaps in the arguments to be filled with `0`s, and a choice of implementation by the programmer. Alternate options would include exceptional aborts in case of no match.

## Backwards Compatibility

This change poses no risk to backwards compatibility.

## Test Cases

### Validation

#### Valid cases

* `RJUMP`/`RJUMPI`/`RJUMPV` with `JUMPDEST` as target
    * `relative_offset` is positive/negative/`0`
* `RJUMP`/`RJUMPI`/`RJUMPV` with instruction other than `JUMPDEST` as target
    * `relative_offset` is positive/negative/`0`
* `RJUMPV` / `RJUMPSUBV` with various valid table sizes from 1 to 256
* `RJUMP` as a final instruction in code section

#### Invalid cases

* `RJUMP`/`RJUMPI`/`RJUMPV` with truncated immediate
* `RJUMPI`/`RJUMPV` as a final instruction in code section
* `RJUMPSUB` / `RJUMPSUBV` target not `ENTERSUB`
* `RJUMP`/`RJUMPI`/`RJUMPV` / `RJUMPSUB` / `RJUMPSUBV` target outside of code section bounds
* `RJUMP`/`RJUMPI`/`RJUMPV` / `RJUMPSUB` / `RJUMPSUBV` target push data
* `RJUMP`/`RJUMPI`/`RJUMPV` / `RJUMPSUB` / `RJUMPSUBV` target another `RJUMP`/`RJUMPI`/`RJUMPV` immediate argument

### Execution

* `RJUMP`
    * `relative_offset` is positive/negative/`0`
* `RJUMPI`
    * `relative_offset` is positive/negative/`0`
        * `condition` equals `0`
        * `condition` does not equal `0` 
* `RJUMPV 0 relative_offset`
    * `case` equals `0`
    * `case` does not equal `0` 
* `RJUMPV` with table containing positive, negative, `0` offsets
    * `case` equals `0`
    * `case` does not equal `0` 
    * `case` outside of table bounds (`case &gt; max_index`, fallback case)
    * `case` &gt; 255

* `RJUMPSUB`
    * `relative_offset` is positive/negative/`0`
* `RJUMPSUBV 0 relative_offset`
    * `case` equals `0`
    * `case` does not equal `0` 
* `RJUMPSUBV` with table containing positive, negative, `0` offsets
    * `case` equals `0`
    * `case` does not equal `0` 
    * `case` outside of table bounds (`case &gt; max_index`, fallback case)
    * `case` &gt; 255

## Security Considerations

Adding new instructions with immediate arguments should be carefully considered when implementing the validation algorithm.

Static relative jump execution does not require runtime check of the jump destination. It greatly reduces execution cost. Therefore the gas cost of the new instructions can also be significantly reduced.

The `RJUMPV`and `RJUMPSUBV` instruction relative offset tables can have up to 256 one-byte entries, so reading an offset cannot be a potential DoS attack surface.         

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Tue, 19 Aug 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8013</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8013</guid>
      </item>
    
      <item>
        <title>Remove `deposit` and `eth1data` fields</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8015-remove-legacy-deposit-and-eth1data-fields/25401</comments>
        
        <description>## Abstract

This EIP removes the legacy `deposits` and `eth1_data` fields from the `BeaconBlockBody` structure after [EIP-6110](/EIPs/EIPS/eip-6110) has been fully finalized. These fields become obsolete once all validators have transitioned to the new in-protocol deposit processing mechanism introduced in EIP-6110.

## Motivation

EIP-6110 introduced in-protocol deposit processing by moving validator deposits to the execution layer as part of the EIP-7685 request framework. This change eliminated the need for the consensus layer&apos;s proposer voting mechanism for deposits. However, during the transition period, both the legacy deposit mechanism (using `deposits` and `eth1_data` fields) and the new mechanism coexist to ensure smooth migration.

Once EIP-6110 has been fully finalized and the transition period is complete (when `state.eth1_deposit_index == state.deposit_requests_start_index`), the legacy deposit fields become permanently unused and can be safely removed. This cleanup provides several benefits:

- **Simplified validation**: Removes deprecated validation logic and code paths
- **Improved maintainability**: Eliminates technical debt from the transition period

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

### Consensus Layer

#### Activation Conditions

This EIP SHALL only be activated when both of the following conditions are met:

1. EIP-6110 has been fully finalized: `state.eth1_deposit_index == state.deposit_requests_start_index`
2. EIP-7732 is in effect

#### BeaconBlockBody Modifications

The `BeaconBlockBody` container is modified to remove the following fields:

**Removed fields:**
- `deposits: List[Deposit, MAX_DEPOSITS]`
- `eth1_data: Eth1Data`

The updated `BeaconBlockBody` structure becomes:

```python
class BeaconBlockBody(Container):
    randao_reveal: BLSSignature
    graffiti: Bytes32
    proposer_slashings: List[ProposerSlashing, MAX_PROPOSER_SLASHINGS]
    attester_slashings: List[AttesterSlashing, MAX_ATTESTER_SLASHINGS_ELECTRA]
    attestations: List[Attestation, MAX_ATTESTATIONS_ELECTRA]
    voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS]
    sync_aggregate: SyncAggregate
    bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES]
    # From EIP-7732
    signed_execution_payload_header: SignedExecutionPayloadHeader
    payload_attestations: List[PayloadAttestation, MAX_PAYLOAD_ATTESTATIONS]
```

#### Validation Changes

**Block processing modifications:**

1. Remove `process_eth1_data()` function calls from block processing
2. Remove `process_deposits()` function calls from block processing  
3. Remove eth1_data voting validation logic
4. Remove legacy deposit validation logic

**State transition modifications:**

1. Remove eth1_data related fields from state transition functions
2. Remove legacy deposit processing from `process_operations()`

#### BeaconState Cleanup

The following fields become unused after activation and MAY be removed in future updates:

- `eth1_data: Eth1Data`
- `eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH]`
- `eth1_deposit_index: uint64`

Note: These fields are kept for historical state root verification but are no longer actively used.

## Rationale

### Timing of Removal

The fields are removed after EIP-6110 finalization to ensure:

- All pending deposits from the legacy system have been processed
- No validator can be affected by the removal
- The transition is complete and irreversible
- State consistency is maintained across all honest nodes

### Dependency on EIP-7732

This EIP requires EIP-7732 because:

- EIP-7732 already modified the `BeaconBlockBody` structure significantly
- It provides the architectural foundation for simplified block bodies
- The timing aligns with the broader consensus layer improvements

## Backwards Compatibility

## Security Considerations

The removal of legacy fields poses minimal security risk because:

- The fields are already unused after EIP-6110 finalization
- All deposits are processed through the new EIP-6110 mechanism

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 22 Aug 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8015</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8015</guid>
      </item>
    
      <item>
        <title>SSZ CompatibleUnion</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8016-ssz-compatibleunion/25275</comments>
        
        <description>## Abstract

This EIP introduces a new [Simple Serialize (SSZ)](https://github.com/ethereum/consensus-specs/blob/ad36024441cf910d428d03f87f331fbbd2b3e5f1/ssz/simple-serialize.md) type to represent unions with forward-compatible Merkleization: A given field is always assigned the same stable [generalized index (gindex)](https://github.com/ethereum/consensus-specs/blob/ad36024441cf910d428d03f87f331fbbd2b3e5f1/ssz/merkle-proofs.md#generalized-merkle-tree-index) across all type options.

## Motivation

Certain types, e.g., transactions, allow multiple variants carving out slightly different feature sets. Merkleization equivalence is still desirable, as it allows verifiers to check common fields across variants. These types should still efficiently deserialize into one of their possible variants corresponding to its known tree shape. In programming languages, this is typically achieved by tagged unions.

If multiple versions of an SSZ container coexist at the same time, for example to represent transaction types, the same field may be assigned to a different gindex in each version. This unnecessarily complicates verifiers and introduces a maintenance burden, as the verifier has to be kept up to date with version specific field to gindex map.

Compatible unions allow only type options to be used that provide stable gindex assignment across all of them.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

### `CompatibleUnion({selector: type})`

A new [SSZ composite type](https://github.com/ethereum/consensus-specs/blob/ad36024441cf910d428d03f87f331fbbd2b3e5f1/ssz/simple-serialize.md#composite-types) is defined:

- **compatible union**: union type containing one of the given subtypes with compatible Merkleization
  - notation `CompatibleUnion({selector: type})`, e.g. `CompatibleUnion({1: Square, 2: Circle})`

Compatible unions are always considered [&quot;variable-size&quot;](https://github.com/ethereum/consensus-specs/blob/ad36024441cf910d428d03f87f331fbbd2b3e5f1/ssz/simple-serialize.md#variable-size-and-fixed-size), even when all type options share the same fixed length.

The [default value](https://github.com/ethereum/consensus-specs/blob/ad36024441cf910d428d03f87f331fbbd2b3e5f1/ssz/simple-serialize.md#default-values) is defined as:

| Type                                | Default Value |
| ----------------------------------- | ------------- |
| `CompatibleUnion({selector: type})` | n/a (error)   |

The following types are considered [illegal](https://github.com/ethereum/consensus-specs/blob/ad36024441cf910d428d03f87f331fbbd2b3e5f1/ssz/simple-serialize.md#illegal-types):

- `CompatibleUnion({})` without any type options are illegal.
- `CompatibleUnion({selector: type})` with a selector outside `uint8(1)` through `uint8(127)` are illegal.
- `CompatibleUnion({selector: type})` with a type option that has incompatible Merkleization with another type option are illegal.

#### Compatible Merkleization

- Types are compatible with themselves.
- `byte` is compatible with `uint8` and vice versa.
- `Bitlist[N]` are compatible if they share the same capacity `N`.
- `Bitvector[N]` are compatible if they share the same capacity `N`.
- `List[type, N]` are compatible if `type` is compatible and they share the same capacity `N`.
- `Vector[type, N]` are compatible if `type` is compatible and they share the same capacity `N`.
- [`ProgressiveList[type]`](/EIPs/EIPS/eip-7916) are compatible if `type` is compatible.
- `Container` are compatible if they share the same field names in the same order, and all field types are compatible.
- [`ProgressiveContainer(active_fields)`](/EIPs/EIPS/eip-7495) are compatible if all `1` entries in both type&apos;s `active_fields` correspond to fields with shared names and compatible types, and no other field name is shared across both types.
- `CompatibleUnion` are compatible with each other if all type options across both `CompatibleUnion` are compatible.
- All other types are incompatible.

#### Serialization

A `value` as `CompatibleUnion({selector: type})` has properties `value.data` with the contained value, and `value.selector` which indexes the selected type option.

```python
return value.selector.to_bytes(1, &quot;little&quot;) + serialize(value.data)
```

#### Deserialization

The deserialization logic is updated:

- In the case of compatible unions, the first byte of the deserialization scope is deserialized as type selector, the remainder of the scope is deserialized as the selected type.

The following invalid input needs to be hardened against:

- An out-of-bounds type selector in a `CompatibleUnion`
- Incomplete data (less than 1 byte for selector)
- Corrupted or malformed serialized data
- Invalid serialization of inner types (delegated to inner type deserialization)

#### JSON mapping

The canonical [JSON mapping](https://github.com/ethereum/consensus-specs/blob/ad36024441cf910d428d03f87f331fbbd2b3e5f1/ssz/simple-serialize.md#json-mapping) is updated:

| SSZ                                 | JSON            | Example                                |
| ----------------------------------- | --------------- | -------------------------------------- |
| `CompatibleUnion({selector: type})` | selector-object | `{ &quot;selector&quot;: string, &quot;data&quot;: type }` |

`CompatibleUnion` is encoded as an object with a `selector` and `data` field, where the contents of `data` change according to the selector.

#### Merkleization

The [SSZ Merkleization specification](https://github.com/ethereum/consensus-specs/blob/ad36024441cf910d428d03f87f331fbbd2b3e5f1/ssz/simple-serialize.md#merkleization) is extended with a helper function:

- `mix_in_selector`: Given a Merkle root `root` and a type selector `selector` (`&quot;uint8&quot;` serialization) return `hash(root, selector)`.

The Merkleization definitions are extended.

- `mix_in_selector(hash_tree_root(value.data), value.selector)` if `value` is of compatible union type.

## Rationale

### Why are `CompatibleUnion` selectors limited to `1 ... 127`?

Reserving `0` prevents issues with incomplete initialization, and can possibly be used in a future EIP to denote optionality.

Reserving selectors above `127` (i.e., highest bit is set) enables future backwards compatible extensions.

The range `1 ... 127` is sufficient to satisfy current demand.

### Why not field collections?

An alternative design was explored where the `active_fields` bitvector was emitted. While that works in principle, it becomes very inefficient to parse when `ProgressiveContainer` are nested, as the parser cannot immediately determine the overall tree shape. Further, the bitvector makes every single nesting layer variable-length, adding a lot of overhead to the serialized format.

With `CompatibleUnion`, a tag is emitted that tells the parser early on what to expect, including for nested fields.

Note that wrapping a field in a `CompatibleUnion` is not a backwards compatible operation. However, new options can be introduced, and existing options dropped, without breaking verifiers. Therefore, `CompatibleUnion` has to be introduced early on wherever future design extensions are anticipated, even when only a single type option is used.

## Backwards Compatibility

`CompatibleUnion({selector: type})` is an alternative to an [earlier union proposal](https://github.com/ethereum/consensus-specs/blob/ad36024441cf910d428d03f87f331fbbd2b3e5f1/ssz/simple-serialize.md#composite-types). However, it has only been used in [deprecated specifications](https://github.com/ethereum/consensus-specs/blob/ad36024441cf910d428d03f87f331fbbd2b3e5f1/specs/_deprecated/sharding/beacon-chain.md). Portal network also uses a union concept for network types, but does not use `hash_tree_root` on them, and could transition to the new compatible union proposal with a new networking version.

## Test Cases

- `ethereum/remerkleable` contains static tests in `test_impl.py` and `test_typing.py`.
- `ethereum/consensus-specs` releases contain random tests in `tests/general/phase0/ssz_generic`, generated according to a format defined in `tests/format/ssz_generic`.

## Reference Implementation

See `ethereum/remerkleable`.

## Security Considerations

For `CompatibleUnion({selector: type})`, the `selector` mix-in guarantees a unique `hash_tree_root` if multiple type options refer to the same Merkle tree shape, or also if multiple type options solely differ in the element type of a `List[type, N]` or [`ProgressiveList[type]`](/EIPs/EIPS/eip-7916) field (as the `hash_tree_root` of any empty list does not depend on the `type`). Without the `selector`, such cases would either have to be defined as illegal types, or handled by the application logic (e.g., by mixing it into the signing root, or by encoding the element type into a different field).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 28 Aug 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8016</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8016</guid>
      </item>
    
      <item>
        <title>Payout Race</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8017-payout-race/25311</comments>
        
        <description>## Abstract

This ERC specifies a small contract surface for a &quot;payout race&quot;: a bucket that holds a single payout asset type and transfers the entire bucket to a recipient when a caller pays a fixed **required payment** in a configured desired payment asset. The desired payment asset can be ETH or one [ERC-20](/EIPs/EIPS/eip-20). The payout asset can be ETH or one ERC-20.

This ERC is inspired by the Uniswap Foundation&apos;s **Unistaker** proposal, which introduced the term **Payout Race** and motivated this design.

## Motivation

Many protocols need an ongoing way to convert a continuous stream of value into another asset at or near prevailing market prices. Typical cases include buying back a protocol token using protocol revenue, accumulating a reserve asset, funding incentive budgets, or rebalancing treasuries. Existing patterns have material drawbacks. Integrating an AMM couples outcomes to external liquidity, slippage, and fees, and requires retuning when pool conditions change. General on-chain auctions add operational complexity and higher gas, especially when run continuously.

This ERC defines a deterministic, revenue-driven primitive that is analogous to a Dutch auction. Sources of value flow into this contract, filling a &quot;bucket&quot; of purchasable assets. The first caller that supplies the required payment in the desired payment asset receives the entire current balance of the payout token in the bucket. The interface is small, auditable, and easy to compose with upstream controllers that decide when the exchange is economically sound.

## Specification

The following interface and rules are normative. The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119 and RFC 8174.

### Definitions

* **Conforming contract**: Any smart contract that exposes this interface and claims compliance with this ERC. This includes proxies and clones. Requirements in this document apply to the observable runtime behavior of the deployed contract.

* **Payout asset**: Asset dispensed from the bucket. `payoutAsset == address(0)` means ETH payout.

* **Desired payment asset**: Asset the buyer must pay. Referred to as `desiredAsset` in the interface. `desiredAsset == address(0)` means ETH payment.

* **Required payment**: Fixed amount of the desired payment asset (`desiredAsset`) or ETH that must be provided by the buyer to trigger the payout.

### Interface

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.24;

interface IPayoutRace {
    /// @notice Payout asset. address(0) means ETH payout.
    function payoutAsset() external view returns (address);

    /// @notice Desired payment asset. address(0) means ETH payment.
    function desiredAsset() external view returns (address);

    /// @notice Fixed amount required to win the race, denominated in the desired payment asset.
    function requiredPayment() external view returns (uint256);

    /// @notice Destination that receives the buyer&apos;s payment.
    function paymentSink() external view returns (address);

    /// @notice Pay the required amount and receive the entire current balance of the payout token to `to`.
    /// @dev Reverts if the computed dispensed amount is zero. Must be safe against reentrancy.
    /// @return dispensed The amount of payout token transferred to `to`.
    function purchase(address to) external payable returns (uint256 dispensed);

    // Admin surface.
    function setRequiredPayment(uint256 amount) external;
    function setPaymentSink(address sink) external;

    // Events
    event Purchased(address indexed buyer, address indexed to, uint256 dispensed, uint256 paid);
    event PaymentConfigUpdated(address desiredAsset, uint256 requiredPayment, address sink);
}
```

### Required Behavior

1. **Exact required payment.** Callers **MUST** provide exactly `requiredPayment()` in the configured `desiredAsset` or in ETH to call `purchase`.
2. **Token pairing.** `payoutAsset` and `desiredAsset` **MUST NOT** both be `address(0)`. ETH on both sides is disallowed.
3. **Desired payment asset immutability.** `desiredAsset` **MUST NOT** change after initialization. A conforming contract **MUST NOT** expose any callable setter that can change `desiredAsset`.
4. **Payout asset immutability.** `payoutAsset` **MUST NOT** change after initialization. A conforming contract **MUST NOT** expose any callable setter that can change `payoutAsset`.
5. **All-or-nothing dispense.** On `purchase`, a conforming contract MUST compute the amount to dispense as the live balance of the payout token captured at function entry, before any external calls. The contract MUST transfer exactly this amount to `to` in a single call and the call MUST revert if this amount is zero.
6. **Payment collection.**

   * If `desiredAsset == address(0)`, `purchase` **MUST** require `msg.value == requiredPayment()` and **MUST** forward that ETH to `paymentSink()`.
   * If `desiredAsset != address(0)`, `purchase` **MUST** require `msg.value == 0` and **MUST** call `transferFrom(msg.sender, paymentSink(), requiredPayment())` on `desiredAsset`.
7. **Admin changes.** A conforming contract **MUST** restrict the admin setters to an authorized role and **MUST** emit `PaymentConfigUpdated` when `requiredPayment` or `paymentSink` change.

### Optional Extensions

* **Permit for payment**: A conforming contract **MAY** expose `purchaseWithPermit(...)` that accepts [EIP-2612](/EIPs/EIPS/eip-2612) permit parameters. If implemented, the function **MUST** require `desiredAsset != address(0)`, **MUST** call `permit` on `desiredAsset` with the supplied signature, and **MUST** collect `requiredPayment` via `transferFrom` in the same transaction. The call **MUST** revert if `desiredAsset` does not implement EIP-2612 or if the permit does not yield sufficient allowance.
* **Rescue for unintended assets**: A conforming contract **MAY** implement an admin-only `rescue` function to recover assets that are not the `payoutAsset` (e.g., unsolicited ERC-20s or ETH sent when `payoutAsset` is an ERC-20). If provided, the function **MUST NOT** transfer the `payoutAsset`, **MUST** emit a `Rescued(address token, address to, uint256 amount)` event, and **MUST** be restricted to an authorized role.

## Rationale

* A single required payment pairs well with controllers that evaluate when the exchange is economically sound and trigger `purchase` only when conditions justify it. The onchain primitive then validates the payment and atomically transfers the entire bucket.
* `paymentSink` reduces persistent balances in the contract and simplifies audits. Sinks can be treasuries, splitters, or burns.
* Using the live onchain balance as the source of truth automatically captures rebases and fee-on-transfer mechanics, and keeps the onchain tracking minimized. It also implies that unsolicited transfers to the contract will be included in the next payout, which purchasers may want to account for at the integration level.

### Admin Considerations

Access control for admin setters is intentionally unspecified; [EIP-173](/EIPs/EIPS/eip-173) ownership or a role-based pattern is recommended.

Some deployments may renounce or restrict admin rights for policy or compliance reasons (for example, renouncing ownership or disabling roles). This ERC does not prescribe any specific mechanism.

The reference uses [EIP-173](/EIPs/EIPS/eip-173) style ownership for illustration. Any access control that enforces the Required behavior is acceptable. Deployments may assign distinct roles per setter or make one or more parameters immutable. The specification is agnostic to the mechanism.

### Parameter Selection and Degenerate Cases

This mechanism works best when value accrues gradually. Large, lumpy deposits can overshoot the required payment threshold and leak value to the first successful caller. Operators should size `requiredPayment` relative to observed inflow volatility and adjust conservatively. If the payout asset appreciates against the desired payment asset, purchases may stall. If it depreciates, purchases may trigger so frequently that value is lost whenever a large trade pushes the bucket well above the threshold.

Changing `requiredPayment` carries risks. Lowering it can leak value at the moment of change if accrued payout already exceeds the new threshold, since searchers can win a bargain. Raising it can disrupt or bankrupt naive searchers and MEV bots that provide rewards by arbitraging fee collection. Mitigations may include timelocked or scheduled parameter changes, announce windows, caps on per-block deposits, cooldowns after changes, and time-weighted average pricing (TWAP)-based or ratcheted adjustments to `requiredPayment`.

### Considered Alternatives: Multi-Asset Sweep

This design could be extended to support multiple payout assets by maintaining an explicit allowlist and, on a successful `purchase`, sweeping each allowlisted token to the recipient using the same mechanics as the single-asset case.

## Backwards Compatibility

Compatible with any [ERC-20](/EIPs/EIPS/eip-20). Wallets and dApps can integrate using standard allowance flows or optional `permit` helpers.

## Reference Implementation

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.24;

import {IERC20} from &quot;@openzeppelin/contracts/token/ERC20/IERC20.sol&quot;;
import {ReentrancyGuard} from &quot;@openzeppelin/contracts/security/ReentrancyGuard.sol&quot;;

contract PayoutRace is ReentrancyGuard {
    address public immutable payoutAsset;        // address(0) for ETH payout
    address public immutable desiredAsset;       // address(0) for ETH payment
    uint256 public requiredPayment;              // fixed amount owed by buyer
    address public paymentSink;

    address private _owner;

    event Purchased(address indexed buyer, address indexed to, uint256 dispensed, uint256 paid);
    event PaymentConfigUpdated(address desiredAsset, uint256 requiredPayment, address sink);
    event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);

    modifier onlyOwner() { require(msg.sender == _owner, &quot;not owner&quot;); _; }

    constructor(address _payoutAsset, address _desiredAsset, uint256 _required, address _sink) {
        require(!(_payoutAsset == address(0) &amp;&amp; _desiredAsset == address(0)), &quot;ETH-ETH disallowed&quot;);
        _owner = msg.sender;
        payoutAsset = _payoutAsset;              // zero means ETH payout
        desiredAsset = _desiredAsset;            // zero means ETH payment
        requiredPayment = _required;
        paymentSink = _sink;
        emit OwnershipTransferred(address(0), _owner);
        emit PaymentConfigUpdated(desiredAsset, requiredPayment, paymentSink);
    }

    function owner() external view returns (address) { return _owner; }
    function transferOwnership(address n) external onlyOwner { _owner = n; emit OwnershipTransferred(msg.sender, n); }

    /// @notice Accept ETH only when this instance vends ETH
    receive() external payable {
        require(payoutToken == address(0), &quot;ETH payout disabled&quot;);
    }

    // desiredAsset is immutable in this reference; no setter is provided.
    function setRequiredPayment(uint256 amount) external onlyOwner { requiredPayment = amount; emit PaymentConfigUpdated(desiredAsset, requiredPayment, paymentSink); }
    function setPaymentSink(address sink) external onlyOwner { paymentSink = sink; emit PaymentConfigUpdated(desiredAsset, requiredPayment, paymentSink); }

    function purchase(address to) external payable nonReentrant returns (uint256 dispensed) {
        uint256 toDispense;
        if (payoutAsset == address(0)) {
            // capture live ETH balance
            toDispense = address(this).balance;
        } else {
            toDispense = IERC20(payoutAsset).balanceOf(address(this));
        }
        require(toDispense &gt; 0, &quot;empty&quot;);

        // collect payment
        if (desiredAsset == address(0)) {
            require(msg.value == requiredPayment, &quot;bad msg.value&quot;);
            (bool ok, ) = paymentSink.call{value: msg.value}(&quot;&quot;);
            require(ok, &quot;sink transfer failed&quot;);
        } else {
            require(msg.value == 0, &quot;unexpected ETH&quot;);
            require(IERC20(desiredAsset).transferFrom(msg.sender, paymentSink, requiredPayment), &quot;payment transfer failed&quot;);
        }

        // payout
        if (payoutAsset == address(0)) {
            (bool ok2, ) = to.call{value: toDispense}(&quot;&quot;);
            require(ok2, &quot;ETH payout failed&quot;);
        } else {
            require(IERC20(payoutAsset).transfer(to, toDispense), &quot;token payout failed&quot;);
        }

        emit Purchased(msg.sender, to, toDispense, requiredPayment);
        return toDispense;
    }
}
```

## Security Considerations

* **Payout accounting.** The dispensed amount is computed from the live onchain balance of the payout asset. Because ETH-to-ETH is disallowed, there is no ambiguity about subtracting `msg.value`. Capture the amount to dispense at function entry and use that value for the transfer.

* **Reentrancy and external calls.** Use the Checks-Effects-Interactions pattern and a reentrancy guard. Avoid any external calls before you (a) capture the amount to dispense and (b) forward payment to `paymentSink`. Do not perform callbacks between collecting payment and completing the payout.

* **Receiver constraints.** The recipient `to` must be able to receive the asset being dispensed. ETH payouts require a payable fallback; [ERC-20](/EIPs/EIPS/eip-20) payouts require that `to` is not a contract that reverts on `transfer`.

* **Payment sink constraints.** The `paymentSink` must be able to receive the desired payment asset. For ETH payments, `paymentSink` must be payable. For [ERC-20](/EIPs/EIPS/eip-20) payments, `paymentSink` must not revert when credited via `transferFrom`. Using a burn address, splitter, or treasury is acceptable; the specification is agnostic to the mechanism.

* **Unsolicited transfers.** The next payout will include any assets pushed to the contract (e.g., direct ETH sends or [ERC-20](/EIPs/EIPS/eip-20) transfers). Operators should account for this at the integration layer, or front the contract with filters if needed. An optional admin-only `rescue` for non-`payoutAsset` assets can mitigate mistakes without affecting conformance.

* **Approvals and permits.** When using [ERC-20](/EIPs/EIPS/eip-20) payments, callers should consider allowance race conditions. If a `purchaseWithPermit` helper is implemented, verify domain separator, deadline, and nonce handling, and revert on insufficient post‑permit allowance.

* **Admin changes.** Because setters can change `requiredPayment` or `paymentSink`, governance should protect these operations. Common mitigations include timelocks, scheduled changes with announcement windows, and immutability for parameters that should never change.

* **Proxies and clones.** Constructors do not run per proxy or minimal clone. Implementations should set `payoutAsset` and `desiredAsset` once during initialization and ensure they cannot change afterward. Avoid exposing setters and protect initializers against re-entry or multiple calls.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 31 Aug 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8017</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8017</guid>
      </item>
    
      <item>
        <title>Minimal Wallet-Managed Auto-Login for SIWE</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8019-minimal-wallet-managed-auto-login-for-siwe/25348</comments>
        
        <description>## Abstract

Defines a wallet-local allowlist for automatic signing of [ERC-4361](/EIPs/EIPS/eip-4361) messages when simple, deterministic match rules succeed. Policies are created and managed only by the wallet/user.

## Motivation

Users repeatedly sign identical Sign-In With Ethereum (SIWE) messages for trusted apps. A small, explicit match policy enables zero-prompt login without involving apps.

Users already get prompted by their wallets if they trust a certain app when they initially connect to it - this flow can also authorize auto-login if applicable.

## Specification

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

The term “wallet” refers to wallet user interfaces, regardless of whether mobile, web-based or browser extensions.

### Overview

Each allow-policy is defined as:

```js
{
  &quot;domain&quot;: &quot;example.com&quot;,                  // exact match to SIWE domain
  &quot;uriPrefix&quot;: &quot;https://example.com/&quot;,      // SIWE URI MUST start with this
  &quot;allowedChains&quot;: [1],                     // list of allowed chainIds
  &quot;allowedResources&quot;: [&quot;https://example.com/login&quot;], // exact set match
  &quot;supportsEIP6492&quot;: true,                   // required for smooth UX when using hardware wallets
  &quot;expiresAt&quot;: 1700000000000 // UNIX timestamp when this policy expires, or 0 for no expiry
}
```

### Auto-sign rule

Given a parsed [ERC-4361](/EIPs/EIPS/eip-4361) message `M`, the wallet **MAY** auto-sign **if**:

1. `M.domain == policy.domain`
2. `M.uri` **startsWith** `policy.uriPrefix`
3. If M.chainId present: `M.chainId` is in `policy.allowedChains`
4. If policy.allowedResources non-empty:
    the set of `M.resources` is a subset of `policy.allowedResources` (order does not matter); otherwise no resources will be allowed at all
5. If `policy.expiresAt` is non-zero, the current time is less than `policy.expiresAt`

All other SIWE validations (nonce uniqueness, time validity, signature domain binding) remain as per [ERC-4361](/EIPs/EIPS/eip-4361) and MUST be enforced by the wallet.

### Management of policies

Policies are created, listed, updated, and deleted **only** within the wallet UI - wallets decide how much control they want to give to users over this.

It’s recommended that each wallet:

* includes a default list of policies for popular apps
* automatically creates policies for apps that it considers safe, after the first SIWE signature, with user consent - this implies a different flow where, upon receiving the SIWE message sign request, the wallet will not go through the regular message signing flow, but prompt the user “App X wants to log-in with your account” with a checkbox to “Automatically sign into &lt;app hostname&gt; in the future”

There’s no app-provided hints or headers that influence policy creation.

### Hardware wallet compatibility and [ERC-6492](/EIPs/EIPS/eip-6492)

Auto-signing is not viable with hardware wallet accounts, as the user will be prompted without context or expectation to sign the login message.

This is why we include the `supportsEIP6492` property. If it is set to `false`, the wallet MUST not auto-login if the account&apos;s primary signer is a hardware wallet, as the app has no way of verifying a smart contract signature.

However, if it&apos;s set to `true`, the wallet MAY perform auto-login as long as 1) it can enable [EIP-7702](/EIPs/EIPS/eip-7702) on the account OR the account is a smart account 2) it can authorize a limited-scope session key or delegation just for the auto-login. If said conditions are met, the wallet MAY generate a login signature without prompting the user on their hardware device. That said, enabling EIP-7702 and the session key/delegation will require prompting the user, so it&apos;s up to the wallet to walk the user through it. The exact mechanism of how wallets should manage the session key/delegation is out of scope of this ERC, but [ERC-7710](/EIPs/EIPS/eip-7710) may be used.

### RPC method

Wallets MAY implement an RPC method, `wallet_getCurrentAutoLoginPolicy`, which has no parameters and returns an object describing the current policy for the calling app.

```json
{
  // the object that describes the active policy, or null
  &quot;activePolicy&quot;: {
    &quot;domain&quot;: &quot;example.com&quot;,
    &quot;uriPrefix&quot;: &quot;https://example.com/&quot;,
    &quot;allowedChains&quot;: [1],
    &quot;allowedResources&quot;: [&quot;https://example.com/login&quot;],
    &quot;supportsEIP6492&quot;: true,
    &quot;expiresAt&quot;: 1700000000000
  },
}
``` 

The response of this method allows apps to determine whether they can self-initiate login requests without user interaction.

If this ERC is disabled in the wallet, or there is no active policy for the calling app, the wallet MUST return `null` for `activePolicy`.

It&apos;s recommended that the wallet returns `null` if the policy has expired or the app is connected on a non-allowed chain.

## Rationale

* This ERC is designed with minimal modifications to existing apps in mind
* From a security perspective, it&apos;s much easier to &quot;outsource&quot; the job of determining which apps to enable to this policy for to wallets - most wallets already maintain lists of &quot;trusted&quot; apps
* [EIP-712](/EIPs/EIPS/eip-712) (typed data) is out of scope due to SIWE deciding to build on plain text.

## Backwards Compatibility

Backwards compatibility is one of the main goals of this ERC, and it requires no changes to existing apps, building upon [ERC-4361](/EIPs/EIPS/eip-4361) as-is.

To fully take advantage of this ERC, apps need to self-initiate the login request rather than expecting users to press a log-in button (using `wallet_getCurrentAutoLoginPolicy`).

## Reference Implementation

```js
function shouldAutoSign(M, P) {
  if (M.domain !== P.domain) return false;
  if (!M.uri.startsWith(P.uriPrefix)) return false;
  if (!P.allowedChains.includes(M.chainId)) return false;
  if (M.resources) {
    const allowList = P.allowedResources || []
    if (!M.resources.every(resource =&gt; allowList.includes(resource))) return false;
  }
  if (P.expiresAt !== 0 &amp;&amp; Date.now() &gt;= P.expiresAt) return false;
  // Also enforce standard SIWE validations here.
  return true;
}
```

## Security Considerations

* It’s recommended for Auto login to be OFF by default on wallets’ UIs so that users can explicitly toggle ON for websites they trust.
* Managing policies it out of scope of this ERC, as most wallets already manage trusted app lists - however, the recommended best practice is to:
    * Include a default list of policies for popular apps
    * Auto-create policies for other apps if the user consents to it
* Standard SIWE checks (fresh nonce, correct domain binding, time validity) should still be enforced.
* `uriPrefix` should be kept specific (e.g., `/login`) to avoid over-broad matches.
* It&apos;s recommended to include a top-level setting in each wallet that can disable this ERC.
* Always match `M.domain` against the top-level origin of each app, to avoid auto-login working in iframes that are included in a malicious top-level origin.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 02 Sep 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8019</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8019</guid>
      </item>
    
      <item>
        <title>Multi-step Contract Ownership</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8023-multi-step-contract-ownership/25475</comments>
        
        <description>## Abstract

We define a multi-stepped contract ownership interface for more secure contract ownership management. This makes the ownership transfer into 3 distinct steps. With the first 2 steps, performed by the original owner (initiate → confirm) and the remaining 1 step performed by the new owner (accept).

We enforce an optional time window between the initiate and confirm stages to give additional room for review, and make ownership key compromise scenarios less fatal.

## Motivation

Ownership management is crucial in on-chain security and a significant portion of the security assumptions of defi protocols, smart contract wallets and on-chain utilities rely on the contract ownership.

The single-step `transferOwnership()` style ownership mechanism has been in the industry for a long time, (e.g.,[ERC-173](/EIPs/EIPS/eip-173)), and has been used ubiquitously as an industry standard. As the industry evolves and attacks get more sophisticated there is a strong need for a multi-step, time gated ownership management process to enhance the ecosystem’s contract ownership to be more reviewable, stoppable, thorough and secure.

The main objective of this standard is to make ownership more secure and handled in a multi-stepped approach that enables the operation to be conducted with more caution and lesser operational mistakes, while being immune to potential scam attacks.

Key factors taken into consideration for the standard:

1. Reduce probability of operational mistakes.
2. Foster on-chain reviewal practice for ownership transfer.
3. Ability to rollback ownership transfer, during the transfer process.
4. Simplicity.

**1. Reduce probability of operational mistakes:** The standard makes the ownership transfer stage into 3 different clear steps. Initiation → Confirmation → Acceptance. The owner will have the enforced ability to review the newOwner address secured by the pre-set buffer time. Also to reduce any operational mistakes or possible scams (e.g., address poisoning) the address is required as the parameter in each Initiation &amp; Confirmation stage.

**2. Foster on-chain reviewal practice for ownership transfer:** We not only targets this as a contract interface and implementation methodology, but also hopes to foster an ecosystem-level awareness and security practice to thoroughly review, confirm the ownership transfer. The standard helps operators of Smart Contract to review newOwner address on-chain, and further confirm again if the address is indeed correct.

**3. Ability to rollback ownership transfer, during the transfer process:** Whether through an operational mistake or private key leak of owner account, or other reasons, the ability to rollback ownership transfer within the time buffer highly increases the security and operational burden.

Even in the extreme case of owner private key leak, if the buffer time is set enough, the original owner can earn time to evacuate the funds from the protocol, and possibly prohibit ownership transfer through DoS of ownership (attack → initiate , original owner(defender) → re initiate. which will reset the time back to 0).

**4. Simplicity:** `MultistepOwnable` is targeted to be a simple contract given the diverse use cases and scenarios it could be applied. The process for ownership transfer is concise but thorough enough to allow owners review each step. This is the rationale behind making the ownership transfer time buffer and buffer time update capability optional.

## Specification

The keywords &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119 and RFC 8174.

A multi-step ownable contract MUST implement the following interface:

```solidity
/// @title Multistep Ownership Standard
interface MultiStepOwnable {

	event OwnershipTransferInitiated(address indexed prevOwner, address indexed newOwner);	
	event OwnershipTransferConfirmed(address indexed prevOwner, address indexed newOwner);
	event OwnershipTransferred(address indexed prevOwner, address indexed newOwner);

	/// @dev initiate the ownership transfer. First step of ownership transfer.
	/// moves the newOwner to the preConfirmed stage.
	/// 
	/// @param newOwner the address of the new owner of the contract.
	/// stored as preConfirmedOwner.
	function initiateOwnershipTransfer(address newOwner) external;
	
	/// @dev confirm the ownership transfer. Second step of ownership transfer.
	/// confirmation can only be done after the transfer-buffer period from initiation.
	/// newOwner should match with the initiation step&apos;s newOwner.
	/// To initiate ownership transfer to a different newOwner, initiation step should be re-conducted.
	///
	/// @param newOwner the address of the new owner of the contract.
	/// stored as pendingOwner.
	function confirmOwnershipTransfer(address newOwner) external;
	
	/// @dev cancels the pending ownership transfer. Before the final step of ownership transfer (acceptOwnershipTransfer()).
	/// This function should wipe out the pendingOwner.
	/// By calling this function, ownership transfer process is canceled and should be reinitiated from initiateOwnershipTransfer().
	function cancelPendingOwnershipTransfer() external;

	/// @dev accepts the ownership transfer. Final step of ownership transfer.
	/// This function can only be called by the newOwner that was confirmed in step 2.
	/// The contract should perform access control e.g.,
	/// msg.sender == pendingOwner()
	function acceptOwnershipTransfer() external;
	
	/// @notice only the address returned by owner() has authority as the owner.
	/// pendingOwner() and preConfirmedOwner() should not possess any
	/// authority/access/right.
	/// @dev returns the owner of the contract
	function owner() external view returns (address);
	
	/// @dev returns the pending owner of the account.
	/// pending owner should not have any authority/access/right.
	function pendingOwner() external view returns (address);
	
	/// @dev returns the pre-confirmed owner of the account.
	/// pre-confirmed owner should not have any authority/access/right.
	function preConfirmedOwner() external view returns (address);
	
	/// @dev returns the ownership transfer buffer time (in seconds).
	/// the buffer is enforced between initiation &lt;&gt; confirmation of ownership transfer. 
	/// the standard does not enforce the value range. it is highly recommended to be between 2 &lt;&gt; 14 days.
	function getOwnershipTransferBuffer() external view returns (uint256);
}
```

The `MultiStepOwnable` contract MAY implement the `UpdateableOwnershipTransferBuffer` interface to enable buffer period modification.

The contract MUST update the buffer period with a 2 step approach of initiation (`initiateOwnershipBufferUpdate()`) and then confirmation (`confirmOwnershipBufferUpdate()`) after the existing buffer period. The buffer period should be enforced between these 2 function calls.
If this behavior is not enforced, the security of `ownershipTransferBuffer` could break during owner key compromise scenario.

```solidity
/// @title UpdateableOwnershipTransferBuffer. Extension of MultiStepOwnable.
interface UpdateableOwnershipTransferBuffer {

	/// @dev initiates the update of ownership transfer time buffer.
	function initiateOwnershipBufferUpdate(uint256 newBuffer) external;
	
	/// @dev confirms the update of ownership transfer time buffer.
	/// confirmation SHOULD revert if existing time buffer did not pass since
	/// initiation of ownership transfer time buffer.
	function confirmOwnershipBufferUpdate(uint256 newBuffer) external;
}
```

## Rationale

1. A time buffer for ownership transfer is introduced to foster a process of reviewing the new owner address on-chain. However, this remains an optional behavior to allow flexibility in ownership management. Removing the optional time buffer would be similar to the implementation of `Ownable2Step` with an additional step for confirmation.

2. Enforcing a time buffer to update the ownership transfer time buffer is crucial for maintaining the security of the `MultiStepOwnable` contract. When the owner key is compromised, this allows the original owner of the account to be able to DoS and prohibit the ownership transfer to the malicious entity when the ownership transfer buffer is sufficiently long enough.

3. For compatibility with existing ownership mechanisms, the standard is designed to be compatible with the existing ownership mechanism for fetching the owner through `owner()`.

## Backwards Compatibility

TBD &lt;!-- TODO --&gt;

## Security Considerations

1. Only owner should be available to call `initiateOwnershipTransfer()` &amp; `confirmOwnershipTransfer()` &amp; `cancelPendingOwnershipTransfer()`.
2. `OwnershipTransferBuffer` should be set together when owner is set. e.g., `constructor()`, `initialize()`.
3. If `OwnershipTransferBuffer` is set, it should be strictly enforced between initiation and confirmation.
4. Before the new owner performs `acceptOwnership()`, the original, existing owner should still hold all rights as the owner. Because the owner is still unchanged.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).</description>
        <pubDate>Tue, 16 Sep 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8023</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8023</guid>
      </item>
    
      <item>
        <title>Backward compatible SWAPN, DUPN, EXCHANGE</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8024-backward-compatible-swapn-dupn-exchange/25486</comments>
        
        <description>## Abstract

Currently, `SWAP*` and `DUP*` instructions are limited to a stack depth of 16. Introduce three new instructions, `SWAPN`, `DUPN` and `EXCHANGE` which lift this limitation and allow accessing the stack at higher depths.

## Motivation

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 &quot;stack to memory elevation&quot; in a compiler. This can result in complex and inefficient code.

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.

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.

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.

Introducing `SWAPN`, `DUPN`, and `EXCHANGE` will provide an option to compilers to simplify accessing deep stack items.

## Specification

We introduce three new instructions:

- `DUPN`     (`0xe6`)
- `SWAPN`    (`0xe7`)
- `EXCHANGE` (`0xe8`)

Each instruction carries one or two immediate operands. Informally, using 1-based indexing, the semantics are:

- `DUPN n`: The `n`&apos;th stack item is duplicated at the top of the stack.
- `SWAPN n`: The `n + 1`&apos;th stack item is swapped with the top of the stack.
- `EXCHANGE n m`: The `n + 1`&apos;th stack item is swapped with the `m + 1`&apos;th stack item.

Formally, when `code[pc]` is one of these opcodes, the VM executes as follows:

- `DUPN`:
    1. Charge 3 gas.
    2. Let `x = code[pc + 1]`.
    3. If `90 &lt; x &lt; 128`, halt with exceptional failure.
    4. Let `n = decode_single(x)`.
    5. If `n &gt; len(stack)`, halt with exceptional failure.
    5. Push `stack[top - n + 1]` on the stack.
    6. Set `pc = pc + 2`.
- `SWAPN`:
    1. Charge 3 gas.
    2. Let `x = code[pc + 1]`.
    3. If `90 &lt; x &lt; 128`, halt with exceptional failure.
    4. Let `n = decode_single(x)`.
    5. If `n + 1 &gt; len(stack)`, halt with exceptional failure.
    5. Swap `stack[top - n]` and `stack[top]`.
    6. Set `pc = pc + 2`.
- `EXCHANGE`:
    1. Charge 3 gas.
    2. Let `x = code[pc + 1]`.
    3. If `81 &lt; x &lt; 128`, halt with exceptional failure.
    4. Let `n, m = decode_pair(x)`.
    5. If `m + 1 &gt; len(stack)`, halt with exceptional failure.
    5. Swap `stack[top - n]` and `stack[top - m]`.
    6. Set `pc = pc + 2`.

`code[pc + 1]` evaluates to `0` if beyond the end of the code, matching `PUSH` behavior.

`top` denotes the index of the value at the top of the stack.

`JUMPDEST` analysis is unchanged. In particular, if `code[i]` is at an instruction boundary and is one of these opcodes, and `code[i + 1]` is `0x5b` (`JUMPDEST`), then `code[i + 1]` is a valid jump target. Note that in this case the execution of `code[i]` would halt at step 2 above (because `x = code[i + 1] = 0x5b = 91`). Disassemblers must decode such `code[i]` as `INVALID` (or `INVALID_DUPN`, etc.) and `code[i + 1]` as `JUMPDEST`.

The auxiliary functions `decode_single` and `decode_pair` are defined by the following Python code:

```python
def decode_single(x: int) -&gt; int:
    &quot;&quot;&quot;Returns n with 17 &lt;= n &lt;= 235.&quot;&quot;&quot;
    assert 0 &lt;= x &lt;= 90 or 128 &lt;= x &lt;= 255
    return (x + 145) % 256

def decode_pair(x: int) -&gt; tuple[int, int]:
    &quot;&quot;&quot;Returns (n, m) with 1 &lt;= n &lt;= 14 and n &lt; m &lt;= 30 - n.&quot;&quot;&quot;
    assert 0 &lt;= x &lt;= 81 or 128 &lt;= x &lt;= 255
    k = x ^ 143
    q, r = divmod(k, 16)
    if q &lt; r:
        return q + 1, r + 1
    else:
        return r + 1, 29 - q
```

Assemblers and compilers must emit a 1-byte immediate after each of these opcodes that decodes to the required `n, m` operands. For reference, this can be done by `encode_single` and `encode_pair`:
 
```python
def encode_single(n: int) -&gt; int:
    assert 17 &lt;= n &lt;= 235
    return (n + 111) % 256

def encode_pair(n: int, m: int) -&gt; int:
    assert 1 &lt;= n &lt; m and n + m &lt;= 30
    if m &lt;= 16:
        q, r = n - 1, m - 1
    else:
        q, r = 29 - m, n - 1
    k = 16 * q + r
    return k ^ 143
```

## Rationale

### Use of an immediate operand

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. 

### Disallowed immediate range

A property the EVM has is that it&apos;s not possible to jump to the middle of an instruction. In order to guarantee this property, the immediate operands of `PUSH*` instructions are masked from jumpdest analysis so that the occurrence of `0x5b` in them is not mistaken for a `JUMPDEST` instruction, which should be considered a valid jump target elsewhere.

The new instructions in this EIP preserve this property without changing jumpdest analysis by making it invalid for their immediates to contain `0x5b`, in addition to `0x60` to `0x7f` (`PUSH1` to `PUSH32`) since those would cause the subsequent instructions to be masked.

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 `e6 5b` that decodes to `INVALID JUMPDEST` prior to this EIP, and thus contains a valid jump target. If an instruction `DUPN x` were introduced with encoding `e6 {x}` (opcode immediately followed by operand), and jumpdest analysis changed to mask the operand to `e6`, the same bytecode sequence `e6 5b` would then decode to `DUPN 0x5b`. As a result of the upgrade, `e6` would become an invalid jump target, breaking contracts that include this sequence. The opposite can happen with push opcodes, for example, `e6 60 5b` would transform from `INVALID PUSH1 0x5b` to `DUPN 0x60 JUMPDEST`, creating a new valid jump target. Furthermore, this may have a cascading effect on arbitrarily many subsequent instructions.

Since the EVM doesn&apos;t offer a dedicated section for data, arbitrary data may be embedded in code and serve as immutable data storage accessed via `CODECOPY`. 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.

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 `JUMPDEST`s must be created in a given bytecode by the introduction of an instruction and none may be removed.

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 `0x5b` (`JUMPDEST`) or `0x60` (`PUSH1`) to `0x7f` (`PUSH32`), in which case masking is not necessary.

### `EXCHANGE` immediate

A previous formulation of `EXCHANGE` 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.

In addition, the exact formulation was chosen to make `decode_pair` 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.

Finally, note that the operands in the assembly instruction `EXCHANGE n m` appear &quot;off by one&quot;, i.e. it operates on the stack elements at depths `n + 1` and `m + 1`. These offsets were chosen to match the `SWAP` and `SWAPN` opcodes such that `EXCHANGE n m` has an effect equivalent to the sequence `SWAP{n} SWAP{m} SWAP{n}`.

### Size of immediate operand

For `DUPN` and `SWAPN` a 16-bit size was considered to accommodate the full stack space of 1024 items, however:

1. that would require an additional restriction/check (`n &lt; 1024`)
2. the 256 depth is a large improvement over the current 16 and the overhead of an extra byte would make it less useful

Similarly for `EXCHANGE`, the proposed scheme allows addressing of 30 items.

### Gas cost

The gas cost for these operations is the same as for existing `DUP*` and `SWAP*` instructions, because they are just implemented as pointer swaps and immediate decoding is negligible.

### `EXCHANGE` vs `SWAPN`

As mentioned before, `EXCHANGE` 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, `SWAP2 SWAP3 SWAP2`. 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.

## Backwards Compatibility

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.

## Test Cases

### Assembly/Disassembly

- `e680` is `[DUPN 17]`
- `e7db` is `[SWAPN 108]`
- `e6805b` is `[DUPN 17, JUMPDEST]`
- `e75b` is `[INVALID_SWAPN, JUMPDEST]`
- `e6605b` is `[INVALID_DUPN, PUSH1 0x5b]`
- `e7610000` is `[INVALID_SWAPN, PUSH2 0x0000]`
- `e65f` is `[INVALID_DUPN, PUSH0]`
- `e89d` is `[EXCHANGE 2 3]`
- `e82f` is `[EXCHANGE 1 19]`
- `e850` is `[EXCHANGE 14 16]`
- `e851` is `[EXCHANGE 14 15]`
- `e852` is `[INVALID_EXCHANGE, MSTORE]`

### Execution

- `60016000808080808080808080808080808080e680` results in 18 stack items, the top of the stack valued 1, the bottom of the stack valued 1, the rest valued 0
- `600160008080808080808080808080808080806002e780` results in 18 stack items, the top of the stack valued 1, the bottom of the stack valued 2, the rest valued 0
- `600260008080808080600160008080808080808080e8` 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
- `600060016002e88e` results in 3 stack items, from top to bottom: [2, 0, 1]
- `600080808080808080808080808080808080808080808080808080808060016002e88f` results in 30 stack items, the top of the stack valued 2, the bottom of the stack valued 1, the rest valued 0
- `e75b` reverts 
- `600456e65b` executes successfully (`PUSH 04 JUMP INVALID_DUPN JUMPDEST`)
- `60008080e88e15` results in 3 stack items, the top of the stack valued 1, the rest valued 0
- `e852` reverts
- `6000808080808080808080808080808080e680` results in exceptional halt

## Security Considerations

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.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Optional Execution Proofs</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-optional-execution-proofs/25500</comments>
        
        <description>## Abstract

Optional execution proofs allow beacon nodes to verify the validity of the execution payload within a beacon block without running an execution layer client. The execution proofs are sent over the consensus layer&apos;s peer-to-peer network.

## Motivation

Optional execution proofs reduce the hardware and bandwidth requirements that are needed for an attester to verify a beacon block. Moreover, the cost to verify to a block no longer grows with the gas limit.

Since these are optional, protocol upgrades cannot be based on the improvements in this EIP. This EIP allows us to safely test execution proofs without making it explicitly consensus critical.

## Specification

This is a consensus layer change only. 

Validators will now be able to enable two new modes:

- zkEVM Proof generating
- Stateless validation

When a proof generating node receives a beacon block, they will create the necessary proofs for the execution payload in the block and re-propagate them on the specified subnets.

When a stateless validating node receives a beacon block, they will check to see if they have already received a valid execution proof for that execution payload from the specified subnet.

The detailed specifications are in the consensus-specs repository.

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

## Rationale

 &lt;-- TODO --&gt;

## Backwards Compatibility

This is backwards compatible and does not require a hardfork.

## Test Cases

&lt;-- TODO --&gt;

## Reference Implementation
&lt;-- TODO --&gt;

## Security Considerations

 &lt;-- TODO --&gt;

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 17 Sep 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8025</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8025</guid>
      </item>
    
      <item>
        <title>P256 algorithm support</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/discussion-topic-for-eip-8030/25557</comments>
        
        <description>## Abstract

This EIP adds a new [EIP-7932](/EIPs/EIPS/eip-7932) algorithm of type `0x01` for supporting P256 signatures.

## Motivation

P256 (a.k.a secp256r1) is a widely-used NIST standardized algorithm that already has a presence within the Ethereum codebase. This makes it a great algorithm to write test
cases against implementations of [EIP-7932](/EIPs/EIPS/eip-7932).

## Specification

This EIP defines a new [EIP-7932](/EIPs/EIPS/eip-7932) algorithmic type with the following parameters:

| Constant | Value |
| - | - |
| `ALG_TYPE` | `Bytes1(0x01)` |
| `SIZE`| `129` |

```python
N = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551

def gas_cost(signing_data: Bytes) -&gt; Uint64:
    # This is the precompile cost from [EIP-7951](/EIPs/EIPS/eip-7951) with 3000 gas
    # subtracted (the cost of the secp256k1 precompile)
    BASE_GAS = Uint64(3900)

    # Calculate extra overhead for keccak256 hashing
    if len(signing_data) == 32:
        return BASE_GAS
    else:
        minimum_word_size = (len(signing_data) + 31) // 32
        return BASE_GAS + Uint64(30 + (6 * minimum_word_size))

def validate(signature: Bytes) -&gt; None | Error:
    # This function is a noop as there is no
    # exposed function defined in [EIP-7951](/EIPs/EIPS/eip-7951)

def verify(signature: Bytes, signing_data: Bytes) -&gt; Bytes | Error:
    if len(signing_data) != 32:
        # Hash if non-standard size
        signing_data = keccak256(signing_data)

    # Ignore initial alg_type byte
    signature = signature[1:]

    (r, s, x, y) = (signature[0:32], signature[32:64], signature[64:96], signature[96:128])

    # This is similar to [EIP-2](/EIPs/EIPS/eip-2)&apos;s malleability verification.
    assert(s &lt;= N/2)

    # This is defined in [P256Verify Function](#p256verify-function)
    assert(P256Verify(signing_data, r, s, x, y) == Bytes(&quot;0x0000000000000000000000000000000000000000000000000000000000000001&quot;))
    
    # Return 64 byte public key
    return x || y

def merge_detached_signature(detached_signature: bytes, public_key: bytes) -&gt; bytes:
    # Concatenate r,s || x,y
    return detached_signature + public_key
```

### `P256Verify` Function

The `P256Verify` function is the logic of the precompile defined in [EIP-7951](/EIPs/EIPS/eip-7951), the only exception is that this function MUST NOT charge any gas.

## Rationale

### Why P256?

P256 or secp256r1, is used globally but (more importantly) has an existing implementation in all execution clients. This allows easy implementation of a known-safe algorithm, which is perfect for a test algorithm.

## Backwards Compatibility

No backward compatibility issues found.

## Security Considerations

Needs discussion.
&lt;!-- TODO --&gt;

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 20 Sep 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8030</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8030</guid>
      </item>
    
      <item>
        <title>Size-Based Storage Gas Pricing</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/the-case-for-eip-8032-in-glamsterdam-tree-depth-based-storage-gas-pricing/25619</comments>
        
        <description>## Abstract

This EIP introduces a mechanism to dynamically price SSTORE operations based on the storage size of a contract. A new optional `storage_count` field is added to the account RLP, which tracks the number of storage slots it owns. The gas cost for SSTORE will be augmented by a factor that grows exponentially with this `storage_count` field, but only after it crosses a predefined activation threshold. This change aims to align the cost of state growth with the long-term burden it places on the network, thereby disincentivizing state bloat.

## Motivation

Ethereum&apos;s state size is a growing concern, as it directly impacts node synchronization times, hardware requirements, and overall network health. The current gas model for storage operations does not fully account for the long-term cost of maintaining state indefinitely. As a result, it remains economically viable to deploy contracts with large storage footprints (“state bloat”), which can be exploited for low-cost data anchoring or spam. This imposes a negative externality on all network participants, who must store and process this data indefinitely.

In practice, the computational and I/O costs of creating and updating storage slots scale with the number of storage slots a contract owns. However, the current gas pricing model does not meaningfully increase with storage size. This discrepancy underprices workloads for contracts with very large state and slows down state root computation.

This proposal aims to address the state growth problem by creating a direct economic link between the size of a contract&apos;s storage and the cost to expand it further. By progressively increasing the price of SSTORE operations in proportion to how much storage a contract already owns, storage write costs become more aligned with the actual work clients perform. Contracts that contribute disproportionately to state growth will face rising costs for additional writes, while small and medium-sized contracts remain unaffected. This mechanism creates a market-based incentive for developers to use onchain storage efficiently, helping mitigate unsustainable state growth over time.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

### Constants and parameters

|Name|Value|Description|
|-|:-:|-|
|`FORK_TIMESTAMP`| TBD | Fork activation timestamp |
|`LIN_FACTOR` | TBD | Linear gas cost factor |
| `ACTIVATION_THRESHOLD` | TBD | Activation threshold, chosen to be at ~8GB of data. |
| `TRANSITION_REGISTRY_ADDRESS` | TBD | The address of system contract that holds the information of account transition |
| `TRANSITION_SLOTS_PER_BLOCK` | TBD | The number of storage slots to iterate per block during the transition process |
| `TRANSITION_MAX_ACCOUNTS` | TBD | The number of accounts to iterate per block during the transition process |

&lt;-- TODO --&gt;

### New account field

Account RLP descriptors receive an optional `storage_count` field, corresponding to the current number of storage slots it contains.

### Account transition

At `FORK_TIMESTAMP`, the transition is activated.

The transition process involves reading all accounts and count the number of storage slots for accounts with non-empty storage root hashes, which in turn populates the `storage_count` field in the account.

The progress of the transition is stored at system contract at `TRANSITION_REGISTRY_ADDRESS`.


Storage layout at `TRANSITION_REGISTRY_ADDRESS`:

- slot `0x00`: `cursor_account_hash` (32-byte account hash)
- slot `0x01`: `cursor_slot_hash` (32-byte slot hash)
- slot `0x02`: `cursor_accum` (uint256 count of non-zero slots seen for the current account)

At the **end** of each block, the client performs up to `TRANSITION_SLOTS_PER_BLOCK` storage slot iterations, possibly spanning one account or multiple accounts:

1. **Select account**  
   If `cursor_account_hash == 0x00…00`, set it to the smallest account hash that is present in the state trie. Otherwise, continue with `cursor_account_hash`.

2. **Iterate storage slots**  
   If the current account at `cursor_account_hash` has a non-empty `storageRootHash`, visit storage slots of this account in ascending lexicographic order of `slot hash`, starting **strictly after** `cursor_slot_hash` (or from the beginning if `cursor_slot_hash == 0x00…00`).
   - Increment `cursor_accum` slot for every slot hash seen
   - Stop when either:
     - `TRANSITION_SLOTS_PER_BLOCK` slots have been processed, or
     - there are no more storage slots for the account.

3. **Finalize account (if exhausted)**  
   If all storage slots for `cursor_account_hash` have been visited, set `storage_count(cursor_account)` to `cursor_accum` in the account object.
   
   If `TRANSITION_MAX_ACCOUNTS` accounts are iterated, then stop iterating.
   - Else: 
        - Advance to the next account:  
        `cursor_account_hash` = next account hash that is present in the state trie
        - Reset per-account cursors:  
        `cursor_slot_hash = 0x00…00`, `cursor_accum = 0`

4. **Persist**  
   If either `TRANSITION_SLOTS_PER_BLOCK` or `TRANSITION_MAX_ACCOUNTS` is reached, write `cursor_account_hash`, `cursor_slot_hash`, and `cursor_accum` to the registry in the post-state of the block.

5. **Completion**  
   The transition is complete when there is no further account present in the trie, with an account hash that is lexicographically greater than the current `cursor_account_hash`.

The account hashes and slot hashes are iterated in ascending lexicographical order.

Transition reference: [EIP-7612](/EIPs/EIPS/eip-7612)

#### Reorg semantics

Chain reorganizations require **no special handling** beyond normal block re-execution. The mechanism is reorg-safe.

`storage_count` updates and the transition cursors (`cursor_account_hash`, `cursor_slot_hash`, `cursor_accum`) are ordinary state writes committed in the post-state of each block at `TRANSITION_REGISTRY_ADDRESS`. On a reorg, these values revert to those of the new canonical ancestor and are re-derived by re-executing blocks.

### Account update rules

After executing all transactions in a block, clients MUST update `storage_count` for affected accounts as follows:

- Let `old := storage_count(A)` in the block-prestate (treat as `0` if absent).
- Let `new` be the true count of non-zero slots for `A` in the post-block state.
- Set `storage_count(A) := new`.

To compute `new` efficiently without scanning all storage every block, clients MUST apply net deltas derived from slots whose values changed relative to the block-prestate:

For each storage slot `k` of account `A` that was written at least once in the block:

```python
def calculate_storage_delta(prestate_value, poststate_value):
    &quot;&quot;&quot;
    Calculate the storage slot delta based on pre-state and post-state values.
    
    Args:
        prestate_value: Pre-state value of the storage slot
        poststate_value: Post-state value of the storage slot
    
    Returns:
        int: Delta value (+1, -1, or 0)
    &quot;&quot;&quot;
    if prestate_value == 0 and poststate_value != 0:
        return 1    # Slot created: empty to non-empty
    elif prestate_value != 0 and poststate_value == 0:
        return -1   # Slot deleted: non-empty to empty
    else:
        return 0    # No change in slot occupancy
```

During a transition, the transition is advanced *first* before applying the storage deltas, but *after* executing all transactions, so the gas costs of a contract that is sweeped by the iterator in this block are only applied for the *next* block. Update semantics when a transition is occurring:

- For accounts that have been iterated (i.e. `cursor_account_hash` &gt; `acc_hash` ), all storage deltas are applied.
- For accounts that have not been iterated at all (i.e. `acc_hash` &gt; `cursor_account_hash`), none of the storage deltas are applied.
- For the account currently being iterated (i.e. `cursor_account_hash` == `acc_hash`), storage deltas are applied only to the slots that have already been accounted for (i.e. `cursor_slot_hash` &gt; `slot_hash`).

### SSTORE gas cost changes

For each contract account `A`, define `S_pre(A)` as the value of `storage_count(A)` in the parent state of the block being executed (pre-state).

For all `SSTORE`s in the block, implementations MUST use `S_pre(A)` when computing the gas cost for `SSTORE`. This value MUST NOT change within the block, regardless of any writes to `A` during the block.

If `storage_count(A)` is absent at block start, clients MUST treat `S_pre(A) = 0`.

&gt; Rationale: holding `S_pre(A)` constant within the block keeps gas estimation stable and independent of transaction ordering.

The gas cost of an `SSTORE` is computed as such:

```python=
constant_sstore_gas(addr, slot) + LIN_FACTOR * ceil_log16(S_pre(addr)) // ACTIVATION_THRESHOLD
```

### Impact on state size

`storage_count` is RLP-encoded as a minimal-length big-endian byte string (no leading zeros). The per-account overhead is therefore small and not a fixed 32 byte number. The field is present only for accounts with a non-empty storage root hash. If `storage_count == 0`, the field may be omitted.

**Per-account overhead**

- Payload length `L = bytes_required(storage_count)`:
  - `L = 0` for `0` (field may be omitted entirely)
  - `L = 1` for `1 … 255`
  - `L = 2` for `256 … 65,535`
  - `L = 3` for `65,536 … 16,777,215`
  - `L = 4` for `16,777,216 … 4,294,967,295` (≈ 4.29B)
- **+1 byte** RLP string prefix (since `L ≤ 55`)
- **+ up to 1 byte** for the account-list prefix growth (only if the list’s total payload crosses a size boundary)

For context, at block ~23,000,000 the largest contract has about **80M** storage slots. Even at that scale (`L = 4`), the per-account addition remains **≤ 6 bytes**.

If we pessimistically assume **23,000,000** contract accounts each carry `storage_count` and each incurs the worst-case **6 bytes**, the upper bound is:

- `23,000,000 × 6 = 138,000,000` bytes ≈ **138 MB**

This is a conservative upper bound. In practice, most contracts have far fewer slots (`L ≤ 1–3`), so a typical addition is 2–4 bytes per contract. Therefore, the net impact on state size is negligible.

## Rationale

The intent is to create friction when growing the state size of a contract, thus limiting the number of such contracts. Going over the limit, some contract developers might want to use another contract to start fresh, which comes at the cost of paying for contract creation, and for any call into the previous instance of the contract.

`ACTIVATION_THRESHOLD` is chosen to not penalize the contracts that are large, but do provide useful value. The idea is to disincentivize spam contracts that grow larger than useful contracts, the latter being legitimately big due to the value they bring to their users and the wider ecosystem. This means that this constant could be increased as the state grows.

`TRANSITION_MAX_ACCOUNTS` bounds how many accounts may be finalized (i.e. have their `storage_count` written) per block during the transition. This prevents excessive write operations per block, reducing write amplification and avoiding large database compactions and associated performance degradation. It complements `TRANSITION_SLOTS_PER_BLOCK`, which limits how many **storage slots** are scanned per block in line with the minimal hardware recommendations. In short, `TRANSITION_SLOTS_PER_BLOCK` bounds read operations, while `TRANSITION_MAX_ACCOUNTS` bounds write operations.

### Comparison with depth-based pricing

The largest contract observed (XEN) sits around depth 9, meaning its relevant storage keys share a 9-nibble (~4.5 bytes) prefix along their MPT paths. Because the storage key into the trie is `keccak256(slot_key)`, an attacker can easily calculate the inputs offchain to find hashes and populate all contracts such that they pay the same cost as XEN.

### Why is a transition needed?

If counting began only at `FORK_TIMESTAMP`, every existing contract would start with an implicit `storage_count = 0` and accrue counts only from *new* writes. While spammy contracts would quickly accumulate writes and thus incur penalties, this would still misprice the workloads we intend to regulate: large pre-fork contracts would continue paying unscaled base costs until they rewrote a substantial portion of their historical slots. During that period, gas pricing would understate their actual storage footprint.

A deterministic, in-protocol transition avoids this. By iterating existing storage under consensus rules and progressively populating each account’s `storage_count` in the state, we ensure that storage-size-based pricing reflects reality for *all* contracts—regardless of whether they write again after the fork. Persisting cursor progress under the state root also makes the process reorg-safe and client-agnostic.

**Alternative (pre-fork background counting by clients)**

- **Idea:** Clients begin counting slots before `FORK_TIMESTAMP`. At activation, they only need to write the final counts into the state for a fixed number of accounts.
- **Pros:** Reduces post-fork iteration work, much faster convergence at fork time since iterating all accounts is faster than all storage slots.
- **Cons:** Late upgraders, snap-syncing nodes, or nodes that were offline cannot reconstruct pre-fork counts deterministically. This approach has to be coordinated so that all users upgrade their nodes and must finish counting prior to the fork activation. Reorgs have to be handled explicitly too.

### Compatibility with Verkle/Binary unified tree

In the current two-layer MPT, a write to contract storage accesses an account path and then a storage path, and the cost a client pays in trie updates and database reads/writes correlates with how deep the storage trie becomes over time.

Under a unified tree, the per-write computational and I/O cost of `SSTORE` no longer tracks an account’s total number of storage slots. The path length is set by the global tree’s branching factor and height, and by the overall distribution of state keys, not by a single account’s footprint. As a result, progressive pricing based on an account’s slot count can become misaligned with the actual work once a unified tree ships.

### Compatibility with EIP-2926

Because [EIP-2926](/EIPs/EIPS/eip-2926) also requires an account transition to chunkify the bytecode and additional fields, scheduling both EIPs in the same fork enables a single, combined transition. This removes duplicated work, reduces client complexity and the number of tree transitions in the future.

## Backwards Compatibility

No backward compatibility issues found. Making the `storage_count` field optional ensures that the default count is 0, which means that contract will not be affected by the gas increase before they have been reached by the iterator sweep.

This is a backwards incompatible gas repricing that requires a scheduled network upgrade.

Node operators MUST update gas estimation handling to accommodate the new calldata cost rules. Specifically, RPC methods such as `eth_estimateGas` MUST incorporate the updated formula for gas calculation when encountering an `SSTORE`.

Users and wallets can maintain their usual workflows without modification, as RPC updates will handle these changes.

## Test Cases

TODO

## Reference Implementation

TODO

## Security Considerations

Needs discussion.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 29 Sep 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8032</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8032</guid>
      </item>
    
      <item>
        <title>Agent Council Oracles</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8033-agent-council-oracles/25638</comments>
        
        <description>## Abstract

This ERC defines a standard interface for oracle contracts that use multi-agent councils to resolve arbitrary information queries. It enables dApps to request resolutions, general information arbitration, and build consensus and validation in a trust-minimized way, with agents submitting answers to the queries on-chain. The ERC works by a requester opening a query to be resolved. The contract then emits the RequestCreated event with parameters specifying the query, number of infoAgents, commit deadline, and reward/bond amounts, specifications, and capabilities required. A commit phase is initiated where InfoAgents can participate by staking the required bond and submitting a hash of the answer to the query as a commit. After the quorum of infoAgents have committed, the reveal process is initiated where infoAgents post the key to the commit hash. A judgeAgent is then selected to review the committed hash and answers provided by the infoAgents. The judgeAgent then selects the infoAgents which answered the query correctly and the reward is divided among the winners. The infoAgents which answered incorrectly lose their bond. The interface supports permissionless participation, bond-based incentives, and optional extensions for reputation, disputes, and callbacks, making it suitable for applications like semantic data oracles and prediction markets.

## Motivation

With AI agents advancing rapidly, we can build trust-minimized oracles that are cheaper, faster, and more scalable than traditional human or node-based systems. Traditional data oracles primarily provide quantitative feeds and are often centralized or expensive for arbitrary, one-off queries. With AI agents becoming reliable for factual resolutions from public sources, this EIP standardizes an interface for agent councils to handle query resolution via commit-reveal-judging flows, fostering interoperability across implementations. It is generalizable for discrete (defined options) or open-ended queries, with hooks for collusion deterrence and verification. Integration with reputation systems (such as that in [ERC-8004](/EIPs/EIPS/eip-8004)) is recommended but optional to keep the core lightweight.

This is generalizable for any resolvable information, making it useful for both qualitative and quantitative data. Existing examples we see this standard being useful for are, tracing information tasks (off-chain data processing with on-chain validation hooks), resolving prediction markets, and creating verified info feeds for DeFi platforms (aggregating real-time semantic data from multiple sources).

We envision an information market evolving where agents compete to answer queries, exchanging data resolutions for tokenized incentives.


## Specification

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.

This EIP proposes the `IAgentCouncilOracle` interface, which defines methods and events for a council-based resolution flow. Implementations MUST support the core flow: request creation, agent commitment, reveal, judging/aggregation, and reward distribution. An OPTIONAL dispute resolution extension is also included. Off-chain processing (LLM inference and analysis) is handled by agents, with on-chain elements opened to coordination and verification of information.

The council consists of two agent roles: Info Agents (who submit individual information) and Judge Agents (who aggregate and resolve consensus). We make this distinction to clarify how responsibilities from this standard are assigned.

### Main Types

```solidity
   // Struct for query requests
    struct AgentCapabilities {
        string[] capabilities; // text, vision, audio etc
        string[] domains; // Expertise areas
    }

    struct Request {
        address requester;
        uint256 rewardAmount;  // Total reward (native token or ERC-20)
        address rewardToken;  // native or ERC-20 token
        uint256 bondAmount;  // Bond per agent (native token or ERC-20)
        address bondToken; // native or ERC-20 token
        uint256 numInfoAgents;  // Target number of info agents
        uint256 deadline;  // Unix timestamp for commit phase end
        string query;  // The information query
        string specifications; // Additional miscellaneous instructions (optional in implementations)
        AgentCapabilities requiredCapabilities;  // For filtering agents (optional in implementations)
    }
```

### Interface

```solidity
interface IAgentCouncilOracle {
    // Events for transparency and monitoring
    event RequestCreated(uint256 indexed requestId, address requester, string query, uint256 rewardAmount, uint256 numInfoAgents, uint256 bondAmount);
    event AgentCommitted(uint256 indexed requestId, address agent, bytes32 commitment);
    event AgentRevealed(uint256 indexed requestId, address agent, bytes answer);  // Or bytes for flexibility
    event JudgeSelected(uint256 indexed requestId, address judge);
    event ResolutionFinalized(uint256 indexed requestId, bytes finalAnswer);  // Or bytes
    event RewardsDistributed(uint256 indexed requestId, address[] winners, uint256[] amounts);
    event ResolutionFailed(uint256 indexed requestId, string reason);
    event DisputeInitiated(uint256 indexed requestId, address disputer, string reason);
    event DisputeWindowOpened(uint256 indexed requestId, uint256 endTimestamp);
    event DisputeResolved(uint256 indexed requestId, bool overturned, bytes finalAnswer);
    

    // Core methods
    function createRequest(string calldata query, uint256 numInfoAgents, uint256 rewardAmount, uint256 bondAmount, uint256 deadline, address rewardToken, address bondToken, string calldata specifications, AgentCapabilities calldata requiredCapabilities) external payable returns (uint256 requestId);
    // Commit: Permissionless, with bond
    function commit(uint256 requestId, bytes32 commitment) external payable;
    // Reveal: Submit answer matching commitment
    function reveal(uint256 requestId, bytes calldata answer, uint256 nonce) external;
    // Judge/Aggregate: Called by selected judge or automatic for discrete option queries
    function aggregate(uint256 requestId, bytes calldata finalAnswer, address[] calldata winners, bytes calldata reasoning) external;  // Winners for reward classification
    // Distribute: Auto or manual post-aggregation
    function distributeRewards(uint256 requestId) external;
    // Get final resolution
    function getResolution(uint256 requestId) external view returns (bytes memory finalAnswer, bool finalized);

    // Optional Dispute Methods
    function initiateDispute(uint256 requestId, string calldata reason) external payable;
    function resolveDispute(uint256 requestId, bool overturn, bytes calldata newAnswer, address[] calldata newWinners) external;

    // Getters for oracle flow data
    function getRequest(uint256 requestId) external view returns (Request memory);
    function getCommits(uint256 requestId) external view returns (address[] memory agents, bytes32[] memory commitments);
    function getReveals(uint256 requestId) external view returns (address[] memory agents, bytes[] memory answers);
}
```

We do not enforce limits on the number or size of items in capabilities, domains, queries, or answers to maintain flexibility for evolving agent ecosystems and models. However, it is RECOMMENDED implementations impose reasonable limits on metrics such as the number of items (ex. max 64), bytes per item (ex. max 64), and/or total encoded bytes (ex. max 8192) to mitigate gas costs and DoS risks. Implementations MUST document any such limits in their code or README and MUST revert with descriptive errors (ex. CapListTooLong) if exceeded. For high-gas environments, implementations SHOULD use off-chain references (such as an IPFS hash on-chain or some external domain) for verbosity, storing only these references in the struct.


### Core Flow

Implementations MUST follow this sequence for interoperability:

1. **Request Creation**: Requester calls `createRequest`, providing query, params (ex. `numInfoAgents`, `bondAmount`), and `rewardAmount` (with `msg.value` or [ERC-20](/EIPs/EIPS/eip-20) transfer). If `rewardToken == address(0)`, this is the native asset and createRequest MUST be payable and expect msg.value to fund the reward (and native bonds if used). If `rewardToken != address(0)`, it MUST be an [ERC-20](/EIPs/EIPS/eip-20) and implementations SHOULD pull funds via `transferFrom`. Emits `RequestCreated`. The bond is a slashable stake an agent put in, and be penalized if the submission turns out to be wrong, malicious etc. The amount and token for the bond (specified with `bondAmount` and `bondToken`) is implementation-specific and these MAY be different from the values used for the reward.

2. **Commit Process**: Permissionless Info Agents call `commit` with a hash (RECOMMENDED: `keccak256(abi.encode(answer, nonce))`) and bond. Caps at `numInfoAgents`. Phase ends at deadline or when all InfoAgents are committed. Emits `AgentCommitted`. 

3. **Reveal/Collection Process**: Committed Info Agents call `reveal` to submit answers. MUST match commitment. Emits `AgentRevealed`. Proceed only if quorum (RECOMMENDED:  &gt;50% reveals) otherwise emit `ResolutionFailed` and refund. This helps reduce coordination/collusion of submissions as they aren’t revealed early.

4. **Judging Process**: After reveals, select a Judge Agent (RECOMMENDED: randomly from a separate pool, distinct from Info Agents) and emit JudgeSelected. The Judge Agent calls aggregate to submit the final answer and classify winners (majority agents). For open-ended and discrete queries, the Judge MUST synthesize revealed submissions (semantic consensus via LLM) and provide reasoning as part of the submission. In ties, the Judge MAY provide a tie-breaker with reasoning. Emits ResolutionFinalized

5. **Reward Distribution Process**: Call `distributeRewards` to payout correct Info Agents / Judge Agent based on config (proportional or equal splits, with implementation specific params for ratios like Judge fee percentage). Refund bonds to correct Info Agents; forfeit others. Emits `RewardsDistributed`. Implementations MAY forfeit the Judge Agent’s bond and redistribute to correct Info Agents or proposer if the judge fails to resolve within the allotted window.

Off-chain storage (such as IPFS for reveals/reasoning) MAY be used, with on-chain hashes for verifiability.

### Optional Extensions

 **Dispute Standard**: Implementations MAY add a dispute mechanism post-finalization.  

Suggested flow: After finalization, open a dispute window. Any party MAY call `initiateDispute` with a `disputeBond` (ex.  1.5-2x original bond) and on-chain reason (such as  a hash of detailed reasoning, optionally on IPFS), emitting `DisputeInitiated`. Re-select a Judge (randomly, with higher minReputation threshold). Judge reviews and calls `resolveDispute` to uphold or overturn, submitting new answers/winners if overturned. If upheld, the disputer’s bond is forfeited to the correct agents and arbitration creator. If overturned, return the disputer&apos;s bond, provide reimbursement (ex. a portion of the base fee), slash the original Judge&apos;s fee/bond, and redistribute. Dispute Judge receives reimbursement (ex. some fixed/percentage fee). Emits `DisputeResolved`. 

Configurable params: `disputeWindow` (duration), `disputeBond`, `minDisputeJudgeReputation` (higher than original), `disputerReimbursement`, `judgeReimbursement`. MAY integrate [ERC-8004](/EIPs/EIPS/eip-8004) for re-runs/proofs with validation hooks; partial payouts/escrow during window for efficiency.


**Reputation Hooks**: MAY integrate with [ERC-8004](/EIPs/EIPS/eip-8004) for filtering (min reputation for agents or judges) or proportional rewards. RECOMMENDED: Set a minimum reputation for Judge Agents, higher than for Info Agents, as they make a final decision. This creates an identifiable on-chain trail for accountability.


**Callbacks**: MAY add `callback(address target, uint256 requestId)` for notifying requester contracts.


**[ERC-20](/EIPs/EIPS/eip-20) Rewards**: Extend with token transfers instead of the native token.

Configs (such as phase durations, quorums, reward ratios) are implementation-specific parameters.

## Rationale

This interface standardizes a council flow for AI-driven oracles, balancing minimal on-chain logic with off-chain flexibility. Commit-reveal prevents front-running and judging enables consensus on complex queries. Bonds and optional reputation help deter attacks.

Reputation scores provide a rationale for enhanced security: they enable proportional reward distribution, gating participation to experienced agents, and reducing collusion risks by aligning incentives with proven performance. Without reputation, attack vectors may increase, but the core bond system offers baseline protection and we expect this baseline to allow for a self regulating rewards incentive market that drives agents to act in good faith.

We considered a single-round, plaintext submission model. While simpler and cheaper, it is susceptible to (i) copying attacks where later agents replicate early submissions, (ii) MEV/front-running of plaintext answers, and (iii) coercion/censorship risks when answers must be revealed before full participation. Plain text answers are easily identified and may be delayed, susceptible to being reordered, or unfavorable answers may be censored compromising the integrity of the Info Agents answers. By contrast, a commit-reveal flow keeps content hidden during the commit phase: adversaries cannot cheaply target specific answers.

Weighted voting (a common alternative in oracles like Universal Market Access) was evaluated as a potential replacement for distinct roles where agents could stake bonds or reputation to vote with proportional influence. This could reduce moving parts but weakens explainability and accountability for open-ended queries. Instead, a Judge allows for semantic interpretation of answers. Our role-based approach mitigates this by random Judge selection and optional reputation thresholds, promoting broader participation while maintaining checks (Judge Agents can tie-break with reasoning). *This also aligns better with AI agent ecosystems, where specialized agents mirror real-world councils or juries, fostering an &quot;information market&quot;.* A lack of a Judge Agent would limit the ERC to only discrete information and make it unclear how non-discrete data is resolved. We standardize the Info/Judge split for the core flow (specialization + reasoning from the Judge), while **leaving weighted aggregation as an OPTIONAL extension** for discrete queries.

Using a single agent reduces complexity but mixes retrieval/synthesis with adjudication. We determined that explicit role separation enables (a) different capability/reputation thresholds, (b) clearer slashing semantics for adjudication failures, and (c) better human-auditable reasoning trails. We intentionally separate roles for specialization and explainability.

The commit-reveal process is more gas-intensive (requiring two transactions per Info Agent: commit and reveal) but provides increased security through ease of verifiability and reduced attack surfaces like front-running. The increased gas is offset by preventing costly disputes from copied or manipulated answers. Other existing commit-reveal mechanisms were considered but were too constrained for our resolution flow and would have increased complexity. For example, [ERC-5732](/EIPs/EIPS/eip-5732) does not provide a built-in reveal mechanism. The reveal is a critical step in the agent council flow to ensure quorum and prevent collusion. The [ERC-162](/EIPs/EIPS/eip-162) commit and reveal process was also considered but is not easily applicable to text fields and resolution flow here.

Longer form responses written directly to the blockchain may be gas-prohibitive for complex queries so off-chain storage like IPFS for larger reveals/reasoning is recommended, with on-chain hashes for integrity. This trades some security (IPFS links are not permanent and could be censored) for cost savings, but implementations can mitigate this via decentralized pinning services or agent domains from [ERC-8004](/EIPs/EIPS/eip-8004). Creating different schemes for off-chain verifiability significantly increases complexity. To enhance usability, our core interface keeps methods lightweight, and optional extensions like disputes remain modular, allowing simple implementations for low-stakes queries while scaling to high-security ones.

This ERC is meant to be complimentary to recent standards like [ERC-8004](/EIPs/EIPS/eip-8004), which provides a foundational step toward enabling agent-to-agent communication. Features like Identity, Reputation, and Validation can strengthen the verifiability and fidelity of answers from Info Agents and rulings from Judge Agents. For instance, implementations can filter participants via [ERC-8004](/EIPs/EIPS/eip-8004)&apos;s reputation scores (minReputation params for agents). They can also use validation hooks to verify off-chain computations cryptographically, reducing reliance on bonds alone. **The framework for Agent Council Oracles differs significantly. It focuses on a standard mechanism for agents to reach consensus without human input, emphasizing on-chain coordination flows (commit-reveal-judge) for query resolution.** While [ERC-8004](/EIPs/EIPS/eip-8004) is geared toward trustless agent interoperability and off-chain logic, our EIP builds atop it by standardizing automated information arbitration. This can apply to specific use cases such as data oracles or prediction markets. The integration with [ERC-8004](/EIPs/EIPS/eip-8004) is optional to keep the core lightweight, but recommended for high-stakes scenarios. Other differentiators unique to our standard include our bond incentives and dispute windows, which add economic security layers otherwise absent in multi-agent coordination layers.

## Backwards Compatibility

No conflicts with existing standards. 

## Security Considerations

- Collusion: Mitigated by bonds (refundable for honest participation, forfeited for failures), random judge selection, and optional reputation. Bonds disincentivize spam and non-reveals by redistributing to participants.
- Spam: Prevented by bonds and caps.
- Failures: Refunds for low participation or abandonment.
- Disputes: Optional for high-stakes, with higher stakes/thresholds.
- Fairness of random selection of Judge relies on the crypto strength of randomness
Implementations should audit for reentrancy and use verifiable randomness.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 28 Sep 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8033</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8033</guid>
      </item>
    
      <item>
        <title>Referable NFT Royalties</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8034-referable-nft-royalties/25643</comments>
        
        <description>## Abstract

This ERC proposes Royalty Distribution, a standalone royalty distribution for Referable Non-Fungible Tokens (rNFTs). It enables royalty distribution to multiple recipients at the primary level and referenced NFTs in the directed acyclic graph (DAG), with a single depth limit to control propagation. The standard is independent of [ERC-2981](/EIPs/EIPS/eip-2981). and token-standard-agnostic, but expects [ERC-5521](/EIPs/EIPS/eip-5521) rNFTs, which in practice build on [ERC-721](/EIPs/EIPS/eip-721) ownership semantics. It includes a function to query fixed royalty amounts (in basis points) for transparency. Royalties are voluntary, transparent, and configurable on-chain, supporting collaborative ecosystems and fair compensation.

## Motivation

[ERC-5521](/EIPs/EIPS/eip-5521) introduces Referable NFTs (rNFTs), which form a DAG through &quot;referring&quot; and &quot;referred&quot; relationships. Existing royalty standards like [ERC-2981](/EIPs/EIPS/eip-2981) do not account for this structure or support multiple recipients per level. This EIP addresses the need for a royalty mechanism that:

- Supports multiple recipients per royalty level (e.g., creators and collaborators).
- Distributes royalties to referenced NFTs in the DAG.
- Limits royalty propagation with a single reference depth.
- Provides a function to query fixed royalty amounts without a sale price.
- Provides a function to query fixed royalty amounts with a sale price.
- Operates independently of [ERC-721](/EIPs/EIPS/eip-721) or [ERC-2981](/EIPs/EIPS/eip-2981).
- Ensures transparency for marketplaces and users.
- Is discoverable via [ERC-165](/EIPs/EIPS/eip-165) supportsInterface.
- Supports optional [EIP-712](/EIPs/EIPS/eip-712) signature-based configuration to streamline marketplace or owner-driven updates.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### Interface

The `IRNFTRoyalty` interface defines the royalty distribution for rNFTs and MUST inherit `ERC165` so that supporting contracts can advertise compliance via [ERC-165](/EIPs/EIPS/eip-165):

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

interface IRNFTRoyalty is ERC165 {
    struct RoyaltyInfo {
        address recipient; // Address to receive royalty
        uint256 royaltyAmount; // Royalty amount (in wei for sale-based queries, basis points for fixed queries)
    }

    struct ReferenceRoyalty {
        RoyaltyInfo[] royaltyInfos; // Array of recipients and their royalty amounts
        uint256 referenceDepth; // Maximum depth in the reference DAG for royalty distribution
    }

    event ReferenceRoyaltiesPaid(
        address indexed rNFTContract,
        uint256 indexed tokenId,
        address indexed buyer,
        address marketplace,
        ReferenceRoyalty royalties
    );

    function getReferenceRoyaltyInfo(
        address rNFTContract,
        uint256 tokenId,
        uint256 salePrice
    ) external view returns (ReferenceRoyalty memory royalties);

    function getReferenceRoyaltyInfo(
        address rNFTContract,
        uint256 tokenId
    ) external view returns (ReferenceRoyalty memory royalties);

    function setReferenceRoyalty(
        address rNFTContract,
        uint256 tokenId,
        address[] memory recipients,
        uint256[] memory royaltyFractions,
        uint256 referenceDepth
    ) external;
    
    function setReferenceRoyalty(
        address rNFTContract,
        uint256 tokenId,
        address[] memory recipients,
        uint256[] memory royaltyFractions,
        uint256 referenceDepth,
        address signer,
        uint256 deadline,
        bytes calldata signature
    ) external;

    function supportsReferenceRoyalties() external view returns (bool);
    
    function royaltyNonce(address signer, address rNFTContract, uint256 tokenId) external view returns (uint256);
}
```
### ERC-165 requirement

  - Implementations MUST return true for `supportsInterface(type(IRNFTRoyalty).interfaceId)`.
  - Additional interfaces (e.g., `AccessControl`) SHOULD be forwarded via `super.supportsInterface(interfaceId)` when using inheritance.

### Signature-Based Configuration

To support gas-efficient and flexible configuration, implementations MUST support the following semantics for the signature overload:

- Authorization: The recovered EIP-712 signer MUST satisfy one of:
  1. Has `CONFIGURATOR_ROLE`, or
  2. Is `IERC721(rNFTContract).ownerOf(tokenId)` at verification time.
- Anti-replay: The message MUST include a nonce; the contract MUST track, verify, and increment a nonce to prevent replay.
- Typed Data: Use EIP-712 domain and struct as below (reference implementation provided).
- Deadline MUST be compared against `block.timestamp`; signatures with `block.timestamp &gt; deadline` MUST be rejected.

RECOMMENDED EIP-712 Domain

- name = &quot;RNFTRoyalty&quot;, version = &quot;2&quot;, chainId, verifyingContract = `address(this)`

RECOMMENDED Typed Struct

```
SetReferenceRoyalty(
  address rNFTContract,
  uint256 tokenId,
  bytes32 recipientsHash,        // keccak256(abi.encode(recipients))
  bytes32 royaltyFractionsHash,  // keccak256(abi.encode(royaltyFractions))
  uint256 referenceDepth,
  address signer,
  uint256 deadline,
  uint256 nonce
)
```

### Key Components

#### Structs

- `RoyaltyInfo`:
  - recipient: The address to receive the royalty payment.
  - `royaltyAmount`: The royalty amount, in wei for `getReferenceRoyaltyInfo` with `salePrice`, or basis points (e.g., 100 = 1%) for `getReferenceRoyaltyInfo` without `salePrice`.
- `ReferenceRoyalty`:
  - `royaltyInfos`: An array of `RoyaltyInfo` for multiple recipients at the primary level and referenced NFTs.
  - `referenceDepth`: A single value limiting royalty distribution to referenced NFTs in the DAG.

#### Functions

- `getReferenceRoyaltyInfo(address rNFTContract, uint256 tokenId, uint256 salePrice)`:
  - Returns a `ReferenceRoyalty` struct with royalty amounts in wei, calculated from the `salePrice`.
  - Includes primary-level royalties and referenced NFT royalties up to `referenceDepth`.
  - MUST return zero amounts if no royalties are configured or if `salePrice` is zero.
- `getReferenceRoyaltyInfo(address rNFTContract, uint256 tokenId)`:
  - Returns a `ReferenceRoyalty` struct with fixed royalty amounts in basis points (e.g., 100 = 1%).
  - Includes primary-level royalties and referenced NFT royalties up to `referenceDepth`.
  - MUST return the configured royalty fractions without sale price calculations.
- `setReferenceRoyalty(address rNFTContract, uint256 tokenId, address[] recipients, uint256[] royaltyFractions, uint256 referenceDepth)`:
  - Configures royalties for the specified rNFT.
  - `recipients` and `royaltyFractions` (in basis points) define primary-level royalties.
  - `referenceDepth` limits royalty distribution to referenced NFTs.
  - MUST be restricted to authorized parties (e.g., rNFT contract owner).
  - MUST enforce a total primary-level royalty cap of ≤ 1000 basis points (10%).
- `setReferenceRoyalty(address rNFTContract, uint256 tokenId, address[] recipients, uint256[] royaltyFractions, uint256 referenceDepth, address signer, uint256 deadline, bytes signature)`:
  - Signature-based configuration per EIP-712.
  - MUST verify signer authorization, nonce, and enforce deadline to reject expired signatures.
  - The signer parameter specifies which address is expected to have signed the message, enabling relayer execution.
- `supportsReferenceRoyalties()`:
  - Returns true if the contract implements this standard. Discovery MUST rely on ERC-165.

- `royaltyNonce(address signer, address rNFTContract, uint256 tokenId) external view returns (uint256)`:
	-	Returns the current nonce used for EIP-712 signatures.
  

#### Events

- `ReferenceRoyaltiesPaid`: Emitted when royalties are paid, logging the rNFT contract, token ID, buyer, marketplace, and `ReferenceRoyalty` details (with `royaltyAmount` in wei).

### Royalty Distribution Model

- Primary Royalties: The rNFT’s `royaltyInfos` array specifies multiple recipients and their fractions (e.g., 5% total, split as 3% and 2%).
- Reference Royalties: At each hop, a total forwarded share equal to `REFERRED_ROYALTY_FRACTION` (e.g., 200 bps / 2%) is carved out and distributed across all referenced NFTs at that depth proportional to their configured weights (fallback: evenly if all weights are zero).
- Total Royalty Cap (Primary Level): The 10% (1000 bps) cap applies to the primary-level configured `royaltyFractions`. Propagated/reference-level flows are governed separately by `REFERRED_ROYALTY_FRACTION` and `referenceDepth`.
- Depth Limit: Implementations MUST cap `referenceDepth`; this reference implementation enforces &lt;= 3 (RECOMMENDED).
- Fixed Royalties: The `getReferenceRoyaltyInfo` function without `salePrice` returns royalty fractions in basis points, enabling transparent inspection.

### Example

For an rNFT (contract 0xABC, token ID 1) with `referenceDepth` = 2:

- Configuration:
  - Primary royalties: 5% (3% to creator, 2% to collaborator).
  - Depth 1: Two referenced NFTs; a total of 2% is forwarded at depth 1 and split equally (1% each) under equal weights.
  - Depth 2: No royalties (capped by `referenceDepth`).
- `getReferenceRoyaltyInfo(0xABC, 1)`:
  
  - Returns:
  
    `{ royaltyInfos: [ {recipient: creator, royaltyAmount: 300}, {recipient: collaborator, royaltyAmount: 200}, {recipient: tokenA_owner, royaltyAmount: 100}, {recipient: tokenB_owner, royaltyAmount: 100} ], referenceDepth: 2 }`.
- Sale for 100 ETH:
  - `getReferenceRoyaltyInfo(0xABC, 1, 100 ether)` returns:
  
    `{ royaltyInfos: [ {recipient: creator, royaltyAmount: 3 ether}, {recipient: collaborator, royaltyAmount: 2 ether}, {recipient: tokenA_owner, royaltyAmount: 1 ether}, {recipient: tokenB_owner, royaltyAmount: 1 ether} ], referenceDepth: 2 }`.
  
    

## Rationale

- Fixed Royalty Query: The new `getReferenceRoyaltyInfo` function without salePrice allows users to inspect fixed royalty fractions (in basis points), improving transparency.
- Multiple Recipients: The `RoyaltyInfo` array supports collaborative projects.
- Single Depth Limit: Simplifies configuration and reduces gas costs.
- Standalone Design: Ensures compatibility with any ERC-5521 contract.
- Voluntary Royalties: Aligns with marketplace practices.
- Transparency: On-chain storage and fixed-amount queries enable verifiable royalties.
- ERC-165 Discoverability: Marketplaces and wallets can reliably detect support via supportsInterface, avoiding ad-hoc feature flags.
- EIP-712 Signatures: Off-chain approvals enable safe, gas-efficient configurations.

## Backwards Compatibility

This standard is independent of ERC-2981 and targets ERC-5521 rNFTs, which in practice build on ERC-721 ownership semantics. Marketplaces can integrate by:

- Checking ERC-165: `supportsInterface(type(IRNFTRoyalty).interfaceId)`.
- Calling `getReferenceRoyaltyInfo` (with or without sale price).
- Optionally leveraging the signature-based configuration for off-chain workflows.

## Reference Implementation

```
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/access/AccessControl.sol&quot;;
import &quot;@openzeppelin/contracts/utils/cryptography/EIP712.sol&quot;; 
import &quot;@openzeppelin/contracts/utils/cryptography/ECDSA.sol&quot;;
import &quot;@openzeppelin/contracts/utils/introspection/IERC165.sol&quot;;
import &quot;@openzeppelin/contracts/token/ERC721/IERC721.sol&quot;;
import &quot;@openzeppelin/contracts/utils/ReentrancyGuard.sol&quot;;

import &quot;./IRNFTRoyalty.sol&quot;;

interface IERC_5521 is IERC165 {
    function setNode(uint256 tokenId, address[] memory addresses, uint256[][] memory tokenIds) external;
    function referringOf(address _address, uint256 tokenId) external view returns (address[] memory, uint256[][] memory);
    function referredOf(address _address, uint256 tokenId) external view returns (address[] memory, uint256[][] memory);
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

contract RNFTRoyalty is IRNFTRoyalty, AccessControl, EIP712, ReentrancyGuard {
    using ECDSA for bytes32;

    bytes32 public constant CONFIGURATOR_ROLE = keccak256(&quot;CONFIGURATOR_ROLE&quot;);
    uint256 private constant MAX_ROYALTY_FRACTION = 1000; // 10%
    uint256 private constant REFERRED_ROYALTY_FRACTION = 200; // 2%
    uint256 private constant MAX_CHAIN_STEPS = 32;
    uint256 private constant MAX_RECIPIENTS = 64;

    // storage
    mapping(address =&gt; mapping(uint256 =&gt; ReferenceRoyalty)) private _royalties;
    event ReferenceRoyaltyConfigured(
        address indexed rNFTContract,
        uint256 indexed tokenId,
        address indexed setter,
        address[] recipients,
        uint256[] royaltyFractions,
        uint256 referenceDepth,
        bool viaSignature
    );

    // EIP-712 typed data &amp; nonce
    bytes32 private constant _SET_TYPEHASH =
        keccak256(&quot;SetReferenceRoyalty(address rNFTContract,uint256 tokenId,bytes32 recipientsHash,bytes32 royaltyFractionsHash,uint256 referenceDepth,address signer,uint256 deadline,uint256 nonce)&quot;);
    // (signer =&gt; rNFT =&gt; tokenId =&gt; nonce)
    mapping(address =&gt; mapping(address =&gt; mapping(uint256 =&gt; uint256))) private _sigNonces;

    constructor() EIP712(&quot;RNFTRoyalty&quot;, &quot;2&quot;) {
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _grantRole(CONFIGURATOR_ROLE, msg.sender);
    }

    // ===== IRNFTRoyalty =====

    // expose nonce for off-chain signing
    function royaltyNonce(address signer, address rNFTContract, uint256 tokenId)
        external
        view
        returns (uint256)
    {
        return _sigNonces[signer][rNFTContract][tokenId];
    }

    function setReferenceRoyalty(
        address rNFTContract,
        uint256 tokenId,
        address[] calldata recipients,
        uint256[] calldata royaltyFractions,
        uint256 referenceDepth
    ) external onlyRole(CONFIGURATOR_ROLE) {
        _configureRoyalty(rNFTContract, tokenId, recipients, royaltyFractions, referenceDepth);
        emit ReferenceRoyaltyConfigured(
            rNFTContract,
            tokenId,
            msg.sender,
            recipients,
            royaltyFractions,
            referenceDepth,
            false
        );
    }

    /// @notice Configure reference royalty via EIP-712 signature (supports relayers).
    /// @dev
    /// - Uses explicit `signer` for nonce lookup and authorization; caller can be a relayer.
    /// - Includes `deadline` in the signed struct; reverts with &quot;Signature expired&quot; if now &gt; deadline.
    /// - Non-reentrant to defend against malicious `rNFT.ownerOf` implementations.
    /// - Authorization: `signer` must have `CONFIGURATOR_ROLE` or be current `ownerOf(tokenId)`.
    /// - Nonce scope: per-signer-per-token; increments on success to prevent replay.
    function setReferenceRoyalty(
        address rNFTContract,
        uint256 tokenId,
        address[] calldata recipients,
        uint256[] calldata royaltyFractions,
        uint256 referenceDepth,
        address signer,
        uint256 deadline,
        bytes calldata signature
    ) external nonReentrant {
        _checkParams(rNFTContract, recipients, royaltyFractions, referenceDepth);

        bytes32 recipientsHash = keccak256(abi.encode(recipients));
        bytes32 fractionsHash  = keccak256(abi.encode(royaltyFractions));
        // Compute expected signer digest and use per-signer-per-token nonce (explicit signer for relaying)
        require(signer != address(0), &quot;Invalid signer&quot;);
        uint256 nonce = _sigNonces[signer][rNFTContract][tokenId];

        require(block.timestamp &lt;= deadline, &quot;Signature expired&quot;);

        bytes32 structHash = keccak256(
            abi.encode(
                _SET_TYPEHASH,
                rNFTContract,
                tokenId,
                recipientsHash,
                fractionsHash,
                referenceDepth,
                signer,
                deadline,
                nonce
            )
        );

        bytes32 digest = _hashTypedDataV4(structHash);
        address recovered = ECDSA.recover(digest, signature);
        require(recovered == signer &amp;&amp; signer != address(0), &quot;Invalid signature&quot;);

        // Authorization: CONFIGURATOR_ROLE or current owner
        bool authorized = hasRole(CONFIGURATOR_ROLE, signer);
        if (!authorized) {
            address owner = _safeOwnerOf(IERC721(rNFTContract), tokenId);
            require(signer == owner, &quot;Signer not authorized&quot;);
        }

        // effects: bump nonce to prevent replay
        _sigNonces[signer][rNFTContract][tokenId] = nonce + 1;

        // configure royalties
        _configureRoyalty(rNFTContract, tokenId, recipients, royaltyFractions, referenceDepth);
        emit ReferenceRoyaltyConfigured(
            rNFTContract,
            tokenId,
            signer,
            recipients,
            royaltyFractions,
            referenceDepth,
            true
        );
    }

    /// @notice Compute reference royalty distribution for a concrete sale price (values in wei).
    /// @param rNFTContract RNFT contract implementing IERC_5521
    /// @param tokenId Token id
    /// @param salePrice Sale price in wei
    function getReferenceRoyaltyInfo(
        address rNFTContract,
        uint256 tokenId,
        uint256 salePrice
    ) external view returns (ReferenceRoyalty memory royalties) {
        royalties = _royalties[rNFTContract][tokenId];
        if (salePrice == 0) {
            uint256 len = royalties.royaltyInfos.length;
            if (len == 0) return royalties;
            RoyaltyInfo[] memory zeroed = new RoyaltyInfo[](len);
            for (uint256 i = 0; i &lt; len; i++) {
                zeroed[i] = RoyaltyInfo(royalties.royaltyInfos[i].recipient, 0);
            }
            royalties.royaltyInfos = zeroed;
            return royalties;
        }
        RoyaltyInfo[] memory chainRoyalties = _calculateChainRoyalties(rNFTContract, tokenId, salePrice);
        royalties.royaltyInfos = chainRoyalties;
        return royalties;
    }

    /// @notice Compute reference royalty distribution in basis points (bps), i.e. relative amounts.
    /// @param rNFTContract RNFT contract implementing IERC_5521
    /// @param tokenId Token id
    function getReferenceRoyaltyInfo(
        address rNFTContract,
        uint256 tokenId
    ) external view returns (ReferenceRoyalty memory royalties) {
        royalties = _royalties[rNFTContract][tokenId];
        if (royalties.royaltyInfos.length == 0) return royalties;
        RoyaltyInfo[] memory bpsRoyalties = _calculateChainRoyalties(rNFTContract, tokenId, 0);
        royalties.royaltyInfos = bpsRoyalties;
        return royalties;
    }

    function supportsReferenceRoyalties() external pure returns (bool) {
        return true;
    }

    // ===== ERC-165 =====
    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(AccessControl, IERC165)
        returns (bool)
    {
        return
            interfaceId == type(IRNFTRoyalty).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    // ===== Internal =====
    function _checkParams(
        address rNFTContract,
        address[] calldata recipients,
        uint256[] calldata royaltyFractions,
        uint256 referenceDepth
    ) internal pure {
        require(rNFTContract != address(0), &quot;Invalid contract&quot;);
        require(recipients.length == royaltyFractions.length, &quot;Length mismatch&quot;);
        require(recipients.length &lt;= MAX_RECIPIENTS, &quot;Too many recipients&quot;);
        require(referenceDepth &lt;= 3, &quot;Depth too high&quot;);
        for (uint256 i = 0; i &lt; recipients.length; ++i) {
            require(recipients[i] != address(0), &quot;Zero recipient&quot;);
        }
    }

    function _configureRoyalty(
        address rNFTContract,
        uint256 tokenId,
        address[] calldata recipients,
        uint256[] calldata royaltyFractions,
        uint256 referenceDepth
    ) internal {
        uint256 totalFraction = 0;
        for (uint256 i = 0; i &lt; royaltyFractions.length; i++) {
            totalFraction += royaltyFractions[i];
        }
        require(totalFraction &lt;= MAX_ROYALTY_FRACTION, &quot;Royalty cap exceeded&quot;);

        ReferenceRoyalty memory config;
        config.referenceDepth = referenceDepth;
        config.royaltyInfos = new RoyaltyInfo[](recipients.length);

        for (uint256 i = 0; i &lt; recipients.length; i++) {
            config.royaltyInfos[i] = RoyaltyInfo(recipients[i], royaltyFractions[i]);
        }

        _royalties[rNFTContract][tokenId] = config;
    }

    function _safeOwnerOf(IERC721 rNFT, uint256 tokenId) internal view returns (address) {
        address owner = rNFT.ownerOf(tokenId);
        require(owner != address(0), &quot;No owner&quot;);
        return owner;
    }

    function _calculateChainRoyalties(
        address rNFTContract,
        uint256 tokenId,
        uint256 salePrice
    ) internal view returns (RoyaltyInfo[] memory) {
        ReferenceRoyalty memory currentRoyalty = _royalties[rNFTContract][tokenId];
        if (currentRoyalty.royaltyInfos.length == 0) {
            return new RoyaltyInfo[](0);
        }

        RoyaltyInfo[] memory staged = new RoyaltyInfo[](MAX_CHAIN_STEPS * 32 + 32);
        uint256 count = 0;

        uint256 totalShare = _sumShares(currentRoyalty);
        (uint256 netPrimary, uint256 remainder) = _splitRoyalty(totalShare, salePrice, currentRoyalty.referenceDepth &gt; 0);
        count = _appendDistribution(staged, count, currentRoyalty, netPrimary);

        if (remainder == 0) {
            return _shrink(staged, count);
        }

        // Layered aggregation (BFS) to support multi-parent merges
        uint256 maxItems = MAX_CHAIN_STEPS * 32 + 32;
        address[] memory curContracts = new address[](maxItems);
        uint256[] memory curIds = new uint256[](maxItems);
        uint256[] memory curAmts = new uint256[](maxItems);
        uint256[] memory curDepths = new uint256[](maxItems);
        uint256 curCount = 0;
        if (remainder &gt; 0 &amp;&amp; currentRoyalty.referenceDepth &gt; 0) {
            curContracts[0] = rNFTContract;
            curIds[0] = tokenId;
            curAmts[0] = remainder;
            curDepths[0] = currentRoyalty.referenceDepth;
            curCount = 1;
        }

        address[] memory processedContracts = new address[](maxItems);
        uint256[] memory processed = new uint256[](maxItems);
        uint256 processedCount = 0;

        while (curCount &gt; 0) {
            address[] memory nextContracts = new address[](maxItems);
            uint256[] memory nextIds = new uint256[](maxItems);
            uint256[] memory nextAmts = new uint256[](maxItems);
            uint256[] memory nextDepths = new uint256[](maxItems);
            uint256 nextCount = 0;

            for (uint256 iL = 0; iL &lt; curCount; iL++) {
                address curContract = curContracts[iL];
                uint256 curId = curIds[iL];
                uint256 amt = curAmts[iL];
                uint256 depth = curDepths[iL];
                if (amt == 0) continue;

                IERC_5521 curRNFT = IERC_5521(curContract);
                IERC721 curRNFT721 = IERC721(curContract);

                bool seen = false;
                for (uint256 p = 0; p &lt; processedCount; p++) {
                    if (processed[p] == curId &amp;&amp; processedContracts[p] == curContract) { seen = true; break; }
                }
                if (seen) {
                    address cycOwner = _safeOwnerOf(curRNFT721, curId);
                    staged[count++] = RoyaltyInfo(cycOwner, amt);
                    continue;
                }

                uint256 maxChildren = 32;
                address[] memory childContracts = new address[](maxChildren);
                uint256[] memory childIds = new uint256[](maxChildren);
                uint256 children = _collectReferring(curRNFT, curContract, curId, childContracts, childIds);
                if (depth == 0 || children == 0) {
                    address fallbackOwner = _safeOwnerOf(curRNFT721, curId);
                    staged[count++] = RoyaltyInfo(fallbackOwner, amt);
                    processedContracts[processedCount] = curContract;
                    processed[processedCount++] = curId;
                    continue;
                }

                uint256 keepBase = (amt * (10_000 - REFERRED_ROYALTY_FRACTION)) / 10_000;
                uint256 passBase = amt - keepBase;

                uint256[] memory childWeights = new uint256[](maxChildren);
                ReferenceRoyalty[] memory childConfigs = new ReferenceRoyalty[](maxChildren);
                uint256 sumWeights = 0;

                for (uint256 j = 0; j &lt; children; j++) {
                    address childContract = childContracts[j];
                    uint256 cid = childIds[j];
                    ReferenceRoyalty memory cfg = _royalties[childContract][cid];
                    childConfigs[j] = cfg;
                    if (cfg.royaltyInfos.length &gt; 0) {
                        uint256 w = _sumShares(cfg);
                        childWeights[j] = w;
                        sumWeights += w;
                    }
                }

                if (sumWeights == 0) {
                    uint256 each = amt / children;
                    uint256 rem = amt - (each * children);
                    for (uint256 j = 0; j &lt; children; j++) {
                        address ow = _safeOwnerOf(IERC721(childContracts[j]), childIds[j]);
                        uint256 share = each + (j == children - 1 ? rem : 0);
                        staged[count++] = RoyaltyInfo(ow, share);
                    }
                    processedContracts[processedCount] = curContract;
                    processed[processedCount++] = curId;
                    continue;
                }

                uint256 passDistributed = 0;
                uint256 lastWeightedIdx = 0;
                uint256[] memory keepShares = new uint256[](children);
                uint256[] memory passShares = new uint256[](children);
                for (uint256 j = 0; j &lt; children; j++) {
                    if (childWeights[j] == 0) continue;
                    lastWeightedIdx = j;
                    uint256 kShare = (keepBase * childWeights[j]) / sumWeights;
                    uint256 pShare = (passBase * childWeights[j]) / sumWeights;
                    keepShares[j] = kShare;
                    passShares[j] = pShare;
                    passDistributed += pShare;
                }
                // Remainders: pass and keep
                uint256 passRemainder = passBase - passDistributed;
                if (passRemainder &gt; 0) {
                    passShares[lastWeightedIdx] += passRemainder;
                }
                uint256 keepDistributed = 0;
                for (uint256 j2 = 0; j2 &lt; children; j2++) {
                    keepDistributed += keepShares[j2];
                }
                uint256 keepRemainder = keepBase - keepDistributed;
                if (keepRemainder &gt; 0) {
                    keepShares[lastWeightedIdx] += keepRemainder;
                }

                for (uint256 j = 0; j &lt; children; j++) {
                    if (childWeights[j] == 0) continue;
                    uint256 kShare = keepShares[j];
                    uint256 pShare = passShares[j];
                    ReferenceRoyalty memory cfgj = childConfigs[j];
                    uint256 cid2 = childIds[j];
                    address childContract = childContracts[j];
                    uint256 nextDepth = depth &gt; 0 ? depth - 1 : 0;
                    if (nextDepth == 0) {
                        // Depth exhausted: distribute both keep and pass to child&apos;s recipients
                        count = _appendDistribution(staged, count, cfgj, kShare + pShare);
                    } else {
                        if (kShare &gt; 0) {
                            count = _appendDistribution(staged, count, cfgj, kShare);
                        }
                        if (pShare &gt; 0) {
                            bool merged = false;
                            for (uint256 nx = 0; nx &lt; nextCount; nx++) {
                                if (nextIds[nx] == cid2 &amp;&amp; nextContracts[nx] == childContract) {
                                    nextAmts[nx] += pShare;
                                    if (nextDepth &gt; nextDepths[nx]) {
                                        nextDepths[nx] = nextDepth;
                                    }
                                    merged = true;
                                    break;
                                }
                            }
                            if (!merged) {
                                nextContracts[nextCount] = childContract;
                                nextIds[nextCount] = cid2;
                                nextAmts[nextCount] = pShare;
                                nextDepths[nextCount] = nextDepth;
                                nextCount++;
                            }
                        }
                    }
                }

                processedContracts[processedCount] = curContract;
                processed[processedCount++] = curId;
            }

            for (uint256 k = 0; k &lt; nextCount; k++) {
                curContracts[k] = nextContracts[k];
                curIds[k] = nextIds[k];
                curAmts[k] = nextAmts[k];
                curDepths[k] = nextDepths[k];
            }
            curCount = nextCount;
        }

        return _shrink(staged, count);
    }

    function _splitRoyalty(uint256 totalRate, uint256 salePrice, bool canPropagate)
        internal
        pure
        returns (uint256 netPrimary, uint256 forwardedAmount)
    {
        if (totalRate == 0) {
            return (0, 0);
        }

        if (!canPropagate) {
            if (salePrice == 0) {
                return (totalRate, 0);
            }

            return ((salePrice * totalRate) / 10_000, 0);
        }

        if (salePrice == 0) {
            if (totalRate &lt;= REFERRED_ROYALTY_FRACTION) {
                return (0, totalRate);
            }

            return (totalRate - REFERRED_ROYALTY_FRACTION, REFERRED_ROYALTY_FRACTION);
        }

        uint256 gross = (salePrice * totalRate) / 10_000;
        uint256 forwarded = (salePrice * REFERRED_ROYALTY_FRACTION) / 10_000;
        if (forwarded &gt; gross) {
            forwarded = gross;
        }

        return (gross &gt; forwarded ? gross - forwarded : 0, forwarded);
    }

    function _sumShares(ReferenceRoyalty memory config) internal pure returns (uint256 total) {
        for (uint256 i = 0; i &lt; config.royaltyInfos.length; i++) {
            total += config.royaltyInfos[i].royaltyAmount;
        }
    }

    function _collectReferring(
        IERC_5521 rNFT,
        address rNFTContract,
        uint256 tokenId,
        address[] memory childContracts,
        uint256[] memory childIds
    ) internal view returns (uint256 childCount) {
        (address[] memory refContracts, uint256[][] memory refTokenIds) =
            rNFT.referringOf(rNFTContract, tokenId);

        uint256 maxChildren = childIds.length;
        uint256 listLen = refContracts.length;
        if (refTokenIds.length &lt; listLen) {
            listLen = refTokenIds.length;
        }

        for (uint256 i = 0; i &lt; listLen &amp;&amp; childCount &lt; maxChildren; i++) {
            uint256[] memory ids = refTokenIds[i];
            for (uint256 j = 0; j &lt; ids.length &amp;&amp; childCount &lt; maxChildren; j++) {
                childContracts[childCount] = refContracts[i];
                childIds[childCount] = ids[j];
                childCount++;
            }
        }
    }

    function _appendDistribution(
        RoyaltyInfo[] memory staged,
        uint256 count,
        ReferenceRoyalty memory config,
        uint256 amount
    ) internal pure returns (uint256) {
        uint256 len = config.royaltyInfos.length;
        if (len == 0) {
            return count;
        }

        require(count + len &lt;= staged.length, &quot;royalty overflow&quot;);

        if (amount == 0) {
            for (uint256 i = 0; i &lt; len; i++) {
                staged[count++] = RoyaltyInfo(config.royaltyInfos[i].recipient, 0);
            }
            return count;
        }

        uint256 totalShare = _sumShares(config);

        if (totalShare == 0) {
            staged[count++] = RoyaltyInfo(config.royaltyInfos[0].recipient, amount);
            for (uint256 i = 1; i &lt; len; i++) {
                staged[count++] = RoyaltyInfo(config.royaltyInfos[i].recipient, 0);
            }
            return count;
        }

        uint256 remaining = amount;
        for (uint256 i = 0; i &lt; len; i++) {
            uint256 share = config.royaltyInfos[i].royaltyAmount;
            if (share == 0) {
                staged[count++] = RoyaltyInfo(config.royaltyInfos[i].recipient, 0);
                continue;
            }

            uint256 portion = (amount * share) / totalShare;
            if (portion &gt; remaining) {
                portion = remaining;
            }
            remaining -= portion;

            staged[count++] = RoyaltyInfo(config.royaltyInfos[i].recipient, portion);
        }

        if (remaining &gt; 0) {
            staged[count - 1].royaltyAmount += remaining;
        }

        return count;
    }

    function _shrink(RoyaltyInfo[] memory staged, uint256 count)
        internal
        pure
        returns (RoyaltyInfo[] memory out)
    {
        out = new RoyaltyInfo[](count);
        for (uint256 i = 0; i &lt; count; i++) {
            out[i] = staged[i];
        }
    }

    function recordRoyaltyPayment(
        address rNFTContract,
        uint256 tokenId,
        address buyer,
        ReferenceRoyalty memory royalties
    ) external {
        emit ReferenceRoyaltiesPaid(rNFTContract, tokenId, buyer, msg.sender, royalties);
    }
}
```



## Security Considerations

- Access Control: `setReferenceRoyalty` MUST be restricted to authorized roles (e.g., via AccessControl).
- Total Royalty Cap (Primary Level): The 10% (1000 bps) cap applies to the primary-level configured `royaltyFractions`. Propagated/reference-level flows are governed separately by `REFERRED_ROYALTY_FRACTION` and `referenceDepth`.
- Gas Limits: `referenceDepth` MUST be capped (e.g., ≤ 3) to avoid high gas costs.
- Input Validation: Ensure non-zero addresses and valid royalty fractions.
- Interface Signaling: Ensure supportsInterface forwards properly to parents.
- Signature Replay: Use a per-signer-per-(rNFTContract, tokenId) nonce, and increment after successful verification. Implementations MUST document the chosen scope.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 02 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8034</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8034</guid>
      </item>
    
      <item>
        <title>State Creation Gas Cost Increase</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8037-state-creation-gas-cost-increase/25694</comments>
        
        <description>## Abstract

This proposal increases the cost of state creation operations, thus avoiding excessive state growth under increased block gas limits. It dynamically sets the unit cost per new state byte at a given block gas limit, by targeting an average state growth of 100 GiB per year based on current network usage. 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.

## Motivation

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 202 gas units per new byte created, new storage slots cost 625 gas units per new byte created. Also, deploying duplicated bytecode costs the same as deploying new bytecode, even though clients don&apos;t store duplicated code in the database. This proposal establishes a standard to harmonize all state creation operations.

Additionally, state growth will become a bottleneck for scaling under higher block limits. As of May 2025, the current database size in a Geth node dedicated to state is ~340 GiB. After the increase in gas limit from 30M to 36M gas units, the median size of new state created each day doubled, from ~102 MiB to ~205 MiB. This results in an annual growth of ~73 GiB per year.

![new_state_added](/EIPs/assets/eip-8037/new_state_added.png)

The relationship we are seeing in this example is not linear as expected. This is likely due to other factors impacting user behavior. However, all else being equal, we expect a proportional increase in the number of new states created as gas limits increase. At a 60M gas limit (and a proportional increase in new state per day of 1.7x), we would see a daily state growth of ~349 MiB and a yearly state growth of ~124 GiB. Similarly, at a 100M gas limit, the state would grow at a rate of ~553 MiB per day and 197 GiB per year. This level of state growth would give us less than 2.5 years until the size of the state database exceeds the threshold of 650 GiB, at which point nodes will begin experiencing a degradation in performance.

## Specification

### New parameters

| **Parameter** | **Value** |
|:---:|:---:|
| `TARGET_STATE_GROWTH_PER_YEAR` | 100 × 1024^3 bytes |
| `CPSB_SIGNIFICANT_BITS` | 5 |
| `CPSB_OFFSET` | 9578 |

Besides these fixed parameters, this EIP introduces a dynamic variable that controls the cost per byte of state created for a given block gas limit. The variable is `cost_per_state_byte` and is calculated as follows:

```python
raw = ceil((gas_limit * 2_628_000) / (2 * TARGET_STATE_GROWTH_PER_YEAR))
shifted = raw + CPSB_OFFSET
shift = max(bit_length(shifted) - CPSB_SIGNIFICANT_BITS, 0)
cost_per_state_byte = max(((shifted &gt;&gt; shift) &lt;&lt; shift) - CPSB_OFFSET, 1)
```

The raw value is the unquantized cost derived from targeting `TARGET_STATE_GROWTH_PER_YEAR` at 50% average gas utilization (see [Deriving the cost per byte](#deriving-the-cost-per-byte)). Quantization retains the top `CPSB_SIGNIFICANT_BITS` significant bits after applying `CPSB_OFFSET`, producing a stepped function that avoids frequent small changes as the gas limit fluctuates (see [Quantization](#quantization-of-cost_per_state_byte)).

### Parameter changes

Upon activation of this EIP, the following parameters of the gas model are updated. The &quot;New State Gas&quot; column shows the state gas cost (charged to the `state_gas` dimension), while the &quot;New Regular Gas&quot; column shows additional regular gas costs that accompany the state gas charge.

| **Parameter** | **Current** | **New State Gas** | **New Regular Gas** | **Operations affected** |
|---|---|---|---|---|
| `GAS_CREATE` | 32,000 | 112 × `cpsb` | 9,000 (assuming same as `GAS_CALL_VALUE`)  | `CREATE`, `CREATE2`, contract creation txs |
| `GAS_CODE_DEPOSIT` | 200/byte | `cpsb` per byte | `6 × ceil(len/32)` (hash cost) | `CREATE`, `CREATE2`, contract creation txs |
| `GAS_NEW_ACCOUNT` | 25,000 | 112 × `cpsb` | 0 (already has `GAS_CALL_VALUE` 9,000) | `CALL*` |
| `GAS_STORAGE_SET` | 20,000 | 32 × `cpsb` | 2,900 (`GAS_STORAGE_UPDATE - GAS_COLD_SLOAD`) | `SSTORE` |
| `PER_EMPTY_ACCOUNT_COST` | 25,000 | 112 × `cpsb` | 0 (included in `PER_AUTH_BASE_COST`) | EOA delegation |
| `PER_AUTH_BASE_COST` | 12,500 | 23 × `cpsb` | 7,500 | EOA delegation |

Where `cpsb` = `cost_per_state_byte`. The values assigned to regular gas will be updated based on [EIP-8038](/EIPs/EIPS/eip-8038).

The `PER_AUTH_BASE_COST` regular gas of 7,500 is derived from [EIP-7702](/EIPs/EIPS/eip-7702)&apos;s cost analysis, excluding the code deployment cost (now charged as state gas):

- Calldata cost: ~1,616 (101 bytes × 16)
- Recovering authority address (ecrecover): 3,000
- Reading nonce and code of authority (cold access): 2,600
- Storing values in already warm account: 200
- ~~Code deployment cost: 4,600 (200 × 23)~~ → now in state gas

Total regular gas: 1,616 + 3,000 + 2,600 + 200 ≈ 7,500

In addition, `GAS_SELF_DESTRUCT_NEW_ACCOUNT` is removed and replaced by `GAS_NEW_ACCOUNT`.

### Multidimensional metering for state creation costs

Besides the parameter changes, this proposal introduces an independent metering for state creation costs. The specification is derived from [EIP-8011](/EIPs/EIPS/eip-8011). However, it only requires two dimensions, namely, `regular_gas` and `state_gas`. For state creation operations, the &quot;new state costs&quot; are charged to `state_gas`, while the &quot;new regular costs&quot; are charged to `regular_gas`. The costs of all other operations are also charged to `regular_gas`.

At transaction level, the user pays for both `regular_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 [EIP-7825](/EIPs/EIPS/eip-7825) only applies to `regular_gas`, while `state_gas` is only capped by `tx.gas`.

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, which now corresponds to the maximum gas that can be metered in the bottleneck resource.

#### Transaction validation

Before transaction execution, `calculate_intrinsic_cost` returns three values: `intrinsic_regular_gas`, `intrinsic_state_gas`, and `calldata_floor_gas_cost`. State gas components of intrinsic cost (e.g., account creation for contract deployment transactions, [EIP-2780](/EIPs/EIPS/eip-2780) charges, [EIP-7702](/EIPs/EIPS/eip-7702) authorization charges) are included in `intrinsic_state_gas`. All other intrinsic costs (base transaction cost, calldata, access lists, authorization base costs) are included in `intrinsic_regular_gas`.

`validate_transaction` rejects transactions where:

```python
max(intrinsic_regular_gas, calldata_floor_gas_cost) &gt; TX_MAX_GAS_LIMIT
```

`validate_transaction` also returns `intrinsic_regular_gas`, `intrinsic_state_gas`, and `calldata_floor_gas_cost`.

#### Transaction-level gas accounting (reservoir model)

Since transactions have a single gas limit parameter (`tx.gas`), gas accounting is enforced through a **reservoir model**, in which `gas_left` and `state_gas_reservoir` are initialized as follows:

```python
intrinsic_gas = intrinsic_regular_gas + intrinsic_state_gas
execution_gas = tx.gas - intrinsic_gas
regular_gas_budget = TX_MAX_GAS_LIMIT - intrinsic_regular_gas
gas_left = min(regular_gas_budget, execution_gas)
state_gas_reservoir = execution_gas - gas_left
```

The `state_gas_reservoir` holds gas that exceeds the [EIP-7825](/EIPs/EIPS/eip-7825)&apos;s budget. The two counters operate as follows:

- **Regular gas** charges deduct from `gas_left` only.
- **State gas** charges deduct from `state_gas_reservoir` first; when the reservoir is exhausted, from `gas_left`. The charge increments `execution_state_gas_used` by its full amount regardless of whether it was satisfied from the reservoir, from `gas_left`, or partially from both; a state gas charge never increments `execution_regular_gas_used`.
- When an opcode requires both regular and state gas, the regular gas charge MUST be applied first. If the regular gas charge triggers an out-of-gas error, the state gas charge is not applied.
- The `GAS` opcode returns `gas_left` only (excluding the reservoir).
- The reservoir is passed **in full** to child frames (no 63/64 rule). On child success, the remaining `state_gas_reservoir` is returned to the parent and the child&apos;s `execution_state_gas_used` is added to the parent&apos;s `execution_state_gas_used`. On child **revert** or **exceptional halt**, all state gas consumed by the child, both from the reservoir and any that spilled into `gas_left`, is restored to the parent&apos;s `state_gas_reservoir`; the child&apos;s `execution_state_gas_used` is **not** added to the parent&apos;s `execution_state_gas_used`, because state changes are rolled back and no state was actually grown. On child **exceptional halt**, the child&apos;s `gas_left` is additionally consumed (zeroed).
- On **revert** or **exceptional halt** at the top level (no parent frame), all state gas consumed during execution — both from the `state_gas_reservoir` and any that spilled into `gas_left` — is restored to the `state_gas_reservoir`, and `execution_state_gas_used` is reset to zero, because state changes are fully reverted and no state was actually grown. This mirrors the child frame restoration: the sender is refunded the full execution state gas via the reservoir. On **exceptional halt** specifically, remaining `gas_left` is additionally set to zero (all regular gas consumed), consistent with existing EVM out-of-gas semantics. System transactions are not subject to the `TX_MAX_GAS_LIMIT` cap, their entire `execution_gas` is placed in `gas_left` with `state_gas_reservoir = 0`.

The two counters are returned by the transaction output. Besides the two counters, the EVM also keeps track of `execution_state_gas_used` and `execution_regular_gas_used` during transaction execution. `state_gas` costs are added to `execution_state_gas_used` while `regular_gas` costs are added to `execution_regular_gas_used`. These two counters are also returned by the transaction output.

#### Pre-state and post-state gas validation

[EIP-7928](/EIPs/EIPS/eip-7928) defines two-phase gas validation for state-accessing opcodes: pre-state costs (determinable without state access) and post-state costs (requiring state access). Pre-state validation must pass before any state access occurs. Under the reservoir model, both regular and state gas portions of pre-state costs must be satisfiable; regular gas is checked against `gas_left`, state gas against `state_gas_reservoir` (then `gas_left`). If either check fails, the state access does not occur.

The cost parameters introduced by this EIP map to validation phases as follows:

| Cost Parameter | Validation Phase | State Gas | Regular Gas |
|---|---|---|---|
| `GAS_CREATE` | Pre-state | 112 × `cpsb` | 9,000 |
| `GAS_CODE_DEPOSIT` | Post-state (on deployment success) | `cpsb` × L | 6 × ⌈L/32⌉ |
| `GAS_NEW_ACCOUNT` | Post-state (requires account existence check) | 112 × `cpsb` | 0 |
| `GAS_STORAGE_SET` | Post-state (requires reading current value) | 32 × `cpsb` | 2,900 |

For `SSTORE`, the `GAS_CALL_STIPEND` pre-state check ([EIP-7928](/EIPs/EIPS/eip-7928)) applies to `gas_left` only, excluding the `state_gas_reservoir`.

#### Transaction gas used

At the end of transaction execution, the gas used before and after refunds is defined as:

```python
tx_gas_used_before_refund = tx.gas - tx_output.gas_left - tx_output.state_gas_reservoir
tx_gas_refund = min(tx_gas_used_before_refund // 5, tx_output.refund_counter)
tx_gas_used_after_refund = tx_gas_used_before_refund - tx_gas_refund
```

The refund cap remains at 20% of gas used.

#### Block-level gas accounting

At block level, instead of tracking a single `gas_used` counter, we keep track of two counters, one for `state_gas` and one for `regular_gas`:

```python
tx_regular_gas = intrinsic_regular_gas + tx_output.execution_regular_gas_used
tx_state_gas = intrinsic_state_gas + tx_output.execution_state_gas_used

tx_gas_used = max(tx_gas_used_after_refund, calldata_floor_gas_cost)
block_output.block_regular_gas_used += max(tx_regular_gas, calldata_floor_gas_cost)
block_output.block_state_gas_used += tx_state_gas
```

Note: `tx_gas_used` applies the [EIP-7623](/EIPs/EIPS/eip-7623) calldata floor after refunds, so the floor can effectively negate part of a refund when `calldata_floor_gas_cost &gt; tx_gas_used_after_refund`. The receipt `cumulative_gas_used` uses this post-floor value.

The block header `gas_used` field is set to:

```python
gas_used = max(block_output.block_regular_gas_used, block_output.block_state_gas_used)
```

The block validity condition uses this value:

```python
assert gas_used &lt;= block.gas_limit, &apos;invalid block: too much gas used&apos;
```

The base fee update rule is also modified accordingly:

```python
gas_used_delta = parent.gas_used - parent.gas_target
```

### `SSTORE` refund for slot restoration

When a storage slot is set to a non-zero value and then restored to zero within the same transaction (0 to X to 0 pattern), the state gas and regular gas refunds are handled separately:

- State gas: `32 × cost_per_state_byte` is refunded directly to `state_gas_reservoir` (and `execution_state_gas_used` is decremented). The refund happens immediately at the X to 0 SSTORE, not via `refund_counter`. This ensures the full state gas amount is returned regardless of the 20% refund cap.
- Regular gas: `GAS_STORAGE_UPDATE - GAS_COLD_SLOAD - GAS_WARM_ACCESS` is added to `refund_counter`, subject to the 20% cap.

The net cost after refund is `GAS_WARM_ACCESS`, consistent with pre-[EIP-8037](/EIPs/EIPS/eip-8037) `SSTORE` restoration behavior.

### State gas on frame failure

State gas is deducted at the point of the operation (`CREATE`, `CALL` to new account, EOA delegation). If the frame subsequently reverts or halts, the deduction is not undone within that frame — but the parent reclaims the child&apos;s consumed state gas via the reservoir restoration described above. At the top level, the same restoration applies: all consumed execution state gas (from the reservoir and any spillover from `gas_left`) is moved back into the `state_gas_reservoir`, and `execution_state_gas_used` is reset to zero. In both cases, state gas is refunded because state changes are reverted and no state was actually grown. This departs from pre-[EIP-8037](/EIPs/EIPS/eip-8037) behavior where `GAS_NEW_ACCOUNT` was consumed on revert, but is more consistent with the principle that state gas exclusively pays for long-term state growth.

### State gas refund on CREATE failure

`CREATE`/`CREATE2` charges `112 × cost_per_state_byte` upfront (pay-before-execute). If the creation fails at the opcode level before a child frame is entered — silent failures such as insufficient balance, nonce overflow, stack depth limit, or address collision — the account creation state gas is refunded to `state_gas_reservoir` (and `execution_state_gas_used` is decremented). No account was created, so no state gas should be paid. This preserves the pay-before-execute model while ensuring state gas is only consumed when state is actually created. Child frame revert and exceptional halt are handled by the general frame failure rule above.

### State gas refund on same-tx SELFDESTRUCT

When an account is created and self-destructed in the same transaction ([EIP-6780](/EIPs/EIPS/eip-6780)), the state does not persist. At the end of the transaction, when the actual account and storage removal occurs, all state gas for that account is refunded to `state_gas_reservoir` (and `execution_state_gas_used` is decremented). The refund scope includes:

- Account creation: `112 × cost_per_state_byte`
- Created storage slots: `32 × cost_per_state_byte` per non-zero slot
- Code deposit: `len(code) × cost_per_state_byte`

This refund must be applied before `tx_gas_used_before_refund` is computed so the sender is not charged for state that was destroyed. Storage slots that were restored to zero during execution (0 to X to 0) already have a final value of 0 and are not counted, avoiding a double refund with the SSTORE restoration refund.

### CALL with value to the selfdestructed account in the same transaction

When an account is created and then selfdestructed in the same transaction ([EIP-6780](/EIPs/EIPS/eip-6780)), deletion is deferred to the end of the transaction. During the transaction the account is still present in the state with a nonce of 1 from the CREATE, and is therefore neither empty nor nonexistent. A subsequent `CALL` with value to that address does **not** trigger a new account creation and therefore does **not** charge `GAS_NEW_ACCOUNT` state gas.

The end of the transaction destruction still removes the account regardless of any value received after the SELFDESTRUCT, so no persisted state results from the CALL. Any value transferred is burned when the account is destroyed. Combined with the same transaction SELFDESTRUCT refund above, the net state gas across the CREATE, SELFDESTRUCT, and CALL with value lifecycle is zero, matching the zero persisted state.

#### [EIP-7702](/EIPs/EIPS/eip-7702) authorizations

For [EIP-7702](/EIPs/EIPS/eip-7702) authorizations, the intrinsic state gas assumes account creation for each authorization: `(112 + 23) × cost_per_state_byte` per authorization. When an authorization targets an existing account (no account creation needed), the `112 × cost_per_state_byte` portion is refunded directly to `state_gas_reservoir` during authorization processing.

`intrinsic_state_gas` is immutable after transaction validation and is not modified by this refund. Block accounting uses the original worst-case `intrinsic_state_gas`; the refunded gas is reflected in the final `state_gas_reservoir` rather than in a mutated intrinsic value.

#### Receipt semantics

Receipt `cumulative_gas_used` tracks the cumulative sum of `tx_gas_used_after_refund` (post-refund, post-floor) across transactions, instead of the block&apos;s `gas_used`. This means `receipt[i].cumulative_gas_used - receipt[i-1].cumulative_gas_used` equals the gas paid by transaction `i`.

### Contract deployment cost calculation

When a contract creation transaction or opcode (`CREATE`/`CREATE2`) is executed, gas is charged differently based on whether the deployment succeeds or fails. Given bytecode `B` (length `L`) returned by initcode and `H = keccak256(B)`:

1. **When opcode execution starts:** Always charge `GAS_CREATE`
2. **During initcode execution:** Charge the actual gas consumed by the initcode execution
3. **Success path** (no error, not reverted, and `L ≤ MAX_CODE_SIZE`):
   - Charge `GAS_CODE_DEPOSIT * L` and persist `B` under `H`, then link `codeHash` to `H`
   - Charge `HASH_COST(L)` where `HASH_COST(L) = 6 × ceil(L / 32)` to compute `H`
4. **Failure paths** (REVERT, OOG/invalid during initcode, OOG during code deposit, or `L &gt; MAX_CODE_SIZE`):
   - Do NOT charge `GAS_CODE_DEPOSIT * L` or `HASH_COST(L)`
   - No code is stored; no `codeHash` is linked to the account
   - The account remains unchanged or non-existent

**Important:** The gas for code deposit (`GAS_CODE_DEPOSIT * L`) is checked before hash computation. This means that if a deployment runs out of gas, it will fail during the deposit gas check before the hash is computed. This maintains consistency with post-Homestead behavior where any deployment failure (including OOG) reverts all state changes - no account is created, and no gas is charged beyond `GAS_CREATE` and the actual initcode execution cost consumed.

**Total gas formulas:**

```
SUCCESS_PATH_TOTAL_GAS =
    GAS_CREATE
  + initcode_execution_cost
  + GAS_CODE_DEPOSIT * L
  + HASH_COST(L)

FAILURE_PATH_TOTAL_GAS =
    GAS_CREATE
  + initcode_execution_cost
```

### `CREATE` vs `CREATE2`

`CREATE2` already charges for hashing the init code when deriving the address. That cost remains unchanged. The bytecode hash (`keccak256(B)`) must be computed on success to store the code, incurring `HASH_COST(L)` as specified above.

## Rationale

### Deriving the cost per byte

The variable `cost_per_state_byte` is a dynamic parameter that depends on the block gas limit. The idea is to have a cost that scales as the block gas limit increases, thus avoiding excessive state growth. To compute this variable, we target a specific state growth per year, which we set to 100 GiB. Then, we assume this growth rate is achieved at an average gas utilization.

With multidimensional metering, blocks can be filled up to 50% of the target for both regular gas and state gas. Thus, we consider that on average, blocks can use half of the entire available gas in the block for state creation. This leads to a total of `(gas_limit/2) * 7200 * 365` gas units used for state creation in a year. Dividing this by the target state growth per year gives us the cost per byte of state created.

### Quantization of `cost_per_state_byte`

Without quantization, `cost_per_state_byte` changes by 1 for every ~81,715 change in gas limit, which is 0.13% of the current block gas limit of 60M gas units. This creates unnecessary churn for tooling and gas estimation, since the cost can change almost every block even when the gas limit is relatively stable.

The quantization scheme retains the top 5 significant bits of `(raw + CPSB_OFFSET)`, zeroes the remaining bits, then subtracts `CPSB_OFFSET`. This is equivalent to binary floating-point rounding: each power-of-2 band has exactly 16 distinct levels, and the step size doubles at each band boundary while remaining perfectly uniform within a band.

The offset (`CPSB_OFFSET = 9578`) shifts quantization boundaries away from common gas limit targets. It was chosen by brute-force search over 0–10000 to maximize the minimum distance from any quantization boundary to gas limits from 100M to 1000M (in 50M increments). This prevents `cost_per_state_byte` from flipping between adjacent values due to small gas limit fluctuations near popular targets. The following table shows the resulting boundary distances:

| Gas Limit | `cost_per_state_byte` | Distance to boundary | Blocks to boundary |
| :---------: | :---------------------: | :--------------------: | :------------------: |
| 100M | 1,174 | 4.15% | 42.5 |
| 150M | 1,686 | 8.21% | 84.0 |
| 200M | 2,198 | 10.24% | 104.8 |
| 250M | 2,710 | 5.28% | 54.1 |
| 300M | 3,222 | 1.68% | 17.2 |
| 350M | 4,246 | 0.89% | 9.1 |
| 400M | 4,758 | 2.82% | 28.9 |
| 450M | 5,270 | 4.32% | 44.2 |
| 500M | 5,782 | 2.85% | 29.2 |
| 550M | 6,294 | 1.10% | 11.3 |
| 600M | 6,806 | 6.63% | 67.8 |
| 650M | 7,830 | 1.58% | 16.1 |
| 700M | 7,830 | 3.35% | 34.3 |
| 750M | 8,854 | 3.54% | 36.3 |
| 800M | 8,854 | 0.89% | 9.1 |
| 850M | 9,878 | 4.80% | 49.1 |
| 900M | 10,902 | 1.02% | 10.5 |
| 950M | 10,902 | 2.57% | 26.4 |
| 1000M | 11,926 | 2.55% | 26.2 |

The worst-case minimum distance is 0.89% of the gas limit (at 350M and 800M). Since the gas limit can deviate from its parent by at most 1/1024, `cost_per_state_byte` remains stable for at least ~9 consecutive blocks of same-direction gas limit changes at any gas limit in the 100M–1000M range (in 50M increments).

### Harmonization across state creation

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 (21k gas units) and the costs of additional opcodes and scaffolding needed to execute such a transaction.

| Method                                                      | What is written                                | Intrinsic gas                                                                                 | Bytes → state | Gas / byte |
| ----------------------------------------------------------- | ---------------------------------------------- | --------------------------------------------------------------------------------------------- | ------------- | ---------- |
| Deploy 24kB contract ([EIP-170](/EIPs/EIPS/eip-170) limit)        | Runtime code + account trie node               | 32,000 CREATE + 200 × 24,576 code deposit = 4,947,200 gas                | 24,688 B      | ~200 gas   |
| Fund fresh EOA with 1 wei                                   | Updated account leaf                           | 25,000 new account                                                                            | ~112 B        | ~223 gas   |
| Add delegate flag to funded EOA ([EIP-7702](/EIPs/EIPS/eip-7702)) | 23 B (0xef0100‖address) + updated account leaf | 25,000 PER_EMPTY_ACCOUNT + 12,500 PER_AUTH_BASE + 1,616 calldata - 7,823 refund = ~31,300 gas | ~135 B        | ~232 gas   |
| [EIP-7702](/EIPs/EIPS/eip-7702) authorization to empty address    | 23 B (0xef0100‖address) + updated account leaf | 25,000 PER_EMPTY_ACCOUNT + 12,500 PER_AUTH_BASE + 1,616 calldata = 39,116 gas                 | ~135 B        | ~289 gas   |
| Fill new storage slots (SSTORE 0→x)                         | Slot in storage trie                           | 20,000 gas/slot                                                                               | 32 B          | 625 gas    |

To harmonize costs, we first set the gas cost of a single state byte, `cost_per_state_byte`, as explained above. This is a dynamic parameter that depends on the block gas limit. 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., 32 bytes per slot, 112 bytes per account and 23 bytes per authorization).

Note that the fixed cost `GAS_CREATE` for contract deployments assumes the same cost as a new account creation.

### Multidimensional metering

This proposal is consistent with [EIP-8011](/EIPs/EIPS/eip-8011). However, it only requires two dimensions, namely, `regular_gas` and `state_gas`. If [EIP-8011](/EIPs/EIPS/eip-8011) is not implemented, a two-dimensional version of [EIP-8011](/EIPs/EIPS/eip-8011) is still required.

#### EIP-7825 limit on contract size

[EIP-7825](/EIPs/EIPS/eip-7825) introduces `TX_MAX_GAS_LIMIT` (16.7M) as the maximum gas for a single transaction, in particular stipulating `tx.gas &lt; TX_MAX_GAS_LIMIT`as a validity condition. Were we to continue enforcing this validity condition, with a block limit of 100M gas units, this proposal would limit the maximum contract size that can be deployed to roughly 9.9kB ($\frac{16,777,216 - 21,000 - 5,000,000 - 112 \times 1174}{1174} = 9&apos;902$). This maximum size would only decrease as we increase the gas limit and the `cost_per_state_byte`.

To solve this issue, we only apply this gas limit to regular gas, not state gas. Doing so does not weaken the intended scaling effect of [EIP-7825](/EIPs/EIPS/eip-7825), because regular gas meters all resources that benefit from parallelization. In particular, state growth does not: growing the state always requires writing to disk, a parallelizable operation, but crucially this part of the cost of a state growth operation has to be metered in regular gas, not state gas. In other words, any operation that grows the state should consume both regular gas and state gas, and the regular gas should fully account for all costs other than the long term effect of growing the state.

However, we cannot statically enforce a regular gas consumption of `TX_MAX_GAS_LIMIT`, while still allowing a higher state gas consumption, because transactions only have a single gas limit parameter, `tx.gas`. This is solved through a **reservoir model**: at transaction start, execution gas is split into `gas_left` (capped at `TX_MAX_GAS_LIMIT - intrinsic_regular_gas`) and a `state_gas_reservoir` (the overflow). State gas charges draw from the reservoir first, then from `gas_left` when the reservoir is empty. Regular gas charges draw from `gas_left` only. Exceeding the regular gas budget behaves identically to running out of gas — no special error is needed.

#### Higher throughput

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, as explained in the original multidimensional gas metering introduced in [EIP-8011](/EIPs/EIPS/eip-8011).

## Backwards Compatibility

This is a backwards-incompatible gas repricing that requires a scheduled network upgrade.

Wallet developers and node operators MUST update gas estimation handling to accommodate the new calldata cost rules. Specifically:

- Wallets: Wallets using `eth_estimateGas` 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.
- Node Software: RPC methods such as `eth_estimateGas` MUST incorporate the updated formula for gas calculation with the new floor cost values.

Users can maintain their usual workflows without modification, as wallet and RPC updates will handle these changes.

### Estimated price impacts at various block gas limits

Users and dApp developers will experience an increase in transaction costs associated with creating a new state. The next table summarizes the state creation costs for common operations at different block gas limits.

| Case | cost_per_state_byte | Cost of a new account | Cost increase | Cost of a new slot | Cost increase | 24kB contract deployment | Cost increase |
|:---:|:---:|---|---|---|---|---|---|
| Current cost | NA | 25,000 | NA | 20,000 | NA | 4,947,200 | NA |
| Proposed cost at 60M block limit | 662 | 74,144 | 3 | 24,084 | 1 | 16,357,064 | 3 |
| Proposed cost at 100M block limit | 1,174 | 131,488 | 5 | 40,468 | 2 | 28,997,320 | 6 |
| Proposed cost at 200M block limit | 2,198 | 246,176 | 10 | 73,236 | 4 | 54,277,832 | 11 |
| Proposed cost at 300M block limit | 3,222 | 360,864 | 14 | 106,004 | 5 | 79,558,344 | 16 |

We should note that as the block limit increases, the base fee is expected to reduce due to the higher capacity of the network. This reduction in base fee will offset, in part, the costs from state creation operations. Some analysis is needed to quantify this effect.

## Security Considerations

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.

### Mispricing with respect to ETH transfers

One potential concern is the cost of creating a new account (`112 × cost_per_state_byte` gas units, e.g., 131,488 at a 100M gas limit), compared to transferring ETH to a fresh account (21,000 gas units). With this mismatch, users wishing to create new account are incentivized to first send a normal transaction (costing 21k) to this account to create it, thus avoiding the `GAS_NEW_ACCOUNT` charge.

[EIP-2780](/EIPs/EIPS/eip-2780) solves this mispricing by adding a new component to the intrinsic gas cost of transactions. If a non-create transaction has value &gt; 0 and targets a non-existent account, the `GAS_NEW_ACCOUNT` is added to intrinsic cost.

### Added complexity in block building

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.

### Testing requirements for increasing block limits

With a dynamic cost per byte, every time the block gas limit is increased, clients and testing frameworks need to test for backward compatibility issues. This changes the testing framework for increasing the block limit. A way to mitigate this is to introduce a max cost per byte and do the analysis once on the impact of this max cost.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8038-state-access-gas-cost-update/25693</comments>
        
        <description>## Abstract

This EIP updates the gas cost of state-access operations to reflect Ethereum&apos;s larger state and the consequent slowdown of these operations. It raises the base costs for `GAS_STORAGE_UPDATE`, `GAS_COLD_SLOAD`, and `GAS_COLD_ACCOUNT_ACCESS` and updates the access cost for `EXTCODESIZE` and `EXTCODECOPY`. The design coordinates with [EIP-8032](/EIPs/EIPS/eip-8032): before EIP-8032, parameters assume worst-case contract size; after EIP-8032, they assume worst-case up to `ACTIVATION_THRESHOLD`, with additional depth-based scaling beyond.

## Motivation

The gas price of accessing state has not been updated for quite some time. [EIP-2929](/EIPs/EIPS/eip-2929) was included in the Berlin fork in March 2021 and raised the costs of state-accessing opcodes. Yet, since then, Ethereum&apos;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.

Additionally, `EXTCODESIZE` and `EXTCODECOPY` have the same access cost as `BALANCE` and `EXTCODEHASH`. However, `EXTCODESIZE` and `EXTCODECOPY` require two database reads - first to load the account object (which includes the `nonce`, `balance`, `codeHash` and `storageRoot`), and second to collect the required information (the code size and bytecode respectively). Therefore, the access cost of `EXTCODESIZE` and `EXTCODECOPY` should be higher when compared with the other account read operations.

## Specification

### Parameters

Upon activation of this EIP, the following parameters of the gas model are renamed:

| **Parameter** | **New name** |
|:---:|:---:|
| `GAS_STORAGE_UPDATE` | `GAS_COLD_STORAGE_WRITE` |
| `GAS_COLD_SLOAD` | `GAS_COLD_STORAGE_ACCESS` |

The following parameters of the gas model are updated:

| **Parameter** | **Current value** | **New value** | **Increase** |**Operations affected** |
|:---:|:---:|:---:|:---:|:---:|
| `GAS_COLD_STORAGE_WRITE` | 5,000 | TBD | TBD | `SSTORE` |
| `GAS_COLD_STORAGE_ACCESS` | 2,100 | TBD | TBD | `SSTORE` and `SLOAD` |
| `GAS_COLD_ACCOUNT_ACCESS` | 2,600 | TBD | TBD | `*CALL` opcodes, `BALANCE`, `SELFDESTRUCT` and `EXT*` opcodes |
| `GAS_WARM_ACCESS` | 100 | TBD | TBD | `SSTORE`, `SLOAD`, `*CALL` opcodes, `BALANCE` and `EXT*` opcodes |
| `GAS_STORAGE_CLEAR_REFUND` | 4,800 | TBD | TBD | `SSTORE` |
| `ACCESS_LIST_STORAGE_KEY_COST` | 1,900 | TBD | TBD | `SSTORE` and `SLOAD`|
| `ACCESS_LIST_ADDRESS_COST` | 2,400 | TBD | TBD | `*CALL` opcodes, `BALANCE`, `SELFDESTRUCT` and `EXT*` opcodes |

&lt;!-- TODO --&gt;

### `EXT*` family update

Besides these parameter changes, the gas cost formula for `EXTCODESIZE` and `EXTCODECOPY` is updated to include an additional `GAS_WARM_ACCESS`:

```python
if address in evm.accessed_addresses:
    access_gas_cost = GAS_WARM_ACCESS*2
else:
    evm.accessed_addresses.add(address)
    access_gas_cost = GAS_COLD_ACCOUNT_ACCESS + GAS_WARM_ACCESS
```

## Rationale

### Benchmarking

This proposal does not yet have finalized numbers. To achieve this, we require stateful benchmarks, which are currently in development. Once we collect that data, we will set the final numbers.

&lt;!-- TODO --&gt;

### Special case for `EXTCODESIZE` and `EXTCODECOPY`

Differently from other account read operations, `EXTCODESIZE` and `EXTCODECOPY` 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&apos;s `nonce`, `balance`, `codeHash` and `storageRoot`. 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 `GAS_WARM_ACCESS` for consistency.

### Interaction with [EIP-8032](/EIPs/EIPS/eip-8032)

[EIP-8032](/EIPs/EIPS/eip-8032) proposes modifying the `SSTORE` cost formula to account for the storage size of a contract. This is a more accurate method for pricing storage writes. It allows writes to smaller contracts to be cheaper than writes to large contracts, which helps with scaling and is fairer to users. However, [EIP-8032](/EIPs/EIPS/eip-8032) is not yet scheduled for inclusion in a fork, and, as such, this proposal considers two cases for setting the values of `GAS_COLD_STORAGE_WRITE` and `GAS_COLD_STORAGE_ACCESS`:

1. Before [EIP-8032](/EIPs/EIPS/eip-8032). In this case, we set the parameters assuming a worst-case contract size, which makes state-accessing operations more expensive, independently of the contract size.
2. After [EIP-8032](/EIPs/EIPS/eip-8032). In this case, we set the parameters assuming the worst-case until `ACTIVATION_THRESHOLD`, which is the parameter in [EIP-8032](/EIPs/EIPS/eip-8032) that triggers the depth-based cost. This means that contract sizes below the threshold have the same access costs, while contracts above the threshold get exponentially more expensive with increasing size.

### Interaction with [EIP-2926](/EIPs/EIPS/eip-2926)

[EIP-2926](/EIPs/EIPS/eip-2926) proposes to change how code is stored in the state trie. One of the changes of this proposal is to include the code size as a new field in the account object (`codeSize`). With this change, the code size can be directly accessed with a single read to the database and thus `EXTCODESIZE` should maintain its previous cost formula, without including the additional `GAS_WARM_ACCESS`.

### Interaction with [EIP-7928](/EIPs/EIPS/eip-7928)

[EIP-7928](/EIPs/EIPS/eip-7928) introduces Block-Level Access Lists, which enable parallel disk reads, parallel transaction validation, and executionless state updates through client optimizations. The initial benchmarks won&apos;t take into consideration these optimizations.

## Backwards Compatibility

This is a backwards-incompatible gas repricing that requires a scheduled network upgrade.

Wallet developers and node operators MUST update gas estimation handling to accommodate the new state access cost rules. Specifically:

- Wallets: Wallets using `eth_estimateGas` 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.
- Node Software: RPC methods such as `eth_estimateGas` MUST incorporate the updated formula for gas calculation with the new state access cost values.

Users can maintain their usual workflows without modification, as wallet and RPC updates will handle these changes.

## Security Considerations

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.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Fixed-Supply Agent NFT Collections</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8041-fixed-supply-agent-nft-collections/25656</comments>
        
        <description>## Abstract

An interface for creating fixed-supply collections of Agent NFTs that are registered in an [ERC-8004](/EIPs/EIPS/eip-8004) Agent Registry. While [ERC-8004](/EIPs/EIPS/eip-8004) provides an unlimited mint registry for agent identities, many use cases require limited collections. Collections can be created with fixed supply limits while maintaining the association between agents and their collection through onchain metadata and mint number tracking.

## Motivation

[ERC-8004](/EIPs/EIPS/eip-8004) establishes a singleton registry for AI Agent identity tokens with unlimited minting capability. This open registration model serves many use cases, but there is a clear need for:

1. **Fixed-supply collections**: Ability to create limited editions (e.g., &quot;Genesis 100&quot;, &quot;Season 1&quot;)
2. **Multiple collections per agent**: Agents may belong to multiple named collections (e.g., `agent-collection:dev-team`, `agent-collection/dev-team`, or `agent-collection[dev-team]`) using [ERC-8119](/EIPs/EIPS/eip-8119) parameterized keys
3. **Collection metadata**: Associate agents with specific collections and track their provenance
4. **Mint number tracking**: Permanent record of each agent&apos;s position in the collection (#1 of 1000)
5. **Time-gated releases**: Collections that activate at specific block numbers
6. **Curated drops**: Controlled minting by collection creators rather than open registration

This standard enables these use cases while leveraging the existing [ERC-8004](/EIPs/EIPS/eip-8004) registry infrastructure.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119.html) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174.html).

### Collection Structure

Every compliant collection contract MUST maintain the following collection properties:

- `maxSupply`: Maximum number of agents that can exist in the collection
- `currentSupply`: Current number of agents minted in the collection
- `startBlock`: Block number when minting becomes available
- `open`: Boolean indicating if the collection is currently accepting mints

### Core Interface

Compliant collection contracts MUST implement the `IERC8041Collection` interface:

```solidity
pragma solidity ^0.8.25;

interface IERC8041Collection {
    /// @notice Emitted when the collection is created or updated
    /// @param maxSupply Maximum number of agents in the collection
    /// @param startBlock Block number when minting becomes available
    /// @param open Whether the collection is open for minting
    event CollectionUpdated(uint256 maxSupply, uint256 startBlock, bool open);

    /// @notice Emitted when an agent is minted in the collection
    /// @param agentId The ERC-8004 token ID of the agent in the registry
    /// @param mintNumber The agent&apos;s position in the collection (1-indexed)
    /// @param owner The address that received the agent
    event AgentMinted(uint256 indexed agentId, uint256 mintNumber, address indexed owner);

    /// @notice Get the mint number for a specific agent
    /// @param agentId The ERC-8004 token ID of the agent
    /// @return mintNumber The agent&apos;s position in the collection (1-indexed, e.g., &quot;5 of 1000&quot;)
    ///         Returns 0 if the agent was not minted through this collection
    function getAgentMintNumber(uint256 agentId) external view returns (uint256 mintNumber);

    /// @notice Get the current supply of the collection
    /// @return currentSupply Current number of agents minted
    function getCollectionSupply() external view returns (uint256 currentSupply);
}
```

### Required Functions

Every compliant collection contract MUST implement the following functions:

- `function getAgentMintNumber(uint256 agentId) external view returns (uint256 mintNumber)` - Returns the mint number for a given agent ID (0 if not in collection)
- `function getCollectionSupply() external view returns (uint256 currentSupply)` - Returns the current supply of the collection

### Required Events

Every compliant collection contract MUST emit the following events:

- `event CollectionUpdated(uint256 maxSupply, uint256 startBlock, bool open)` - MUST be emitted when the collection is created and whenever collection details are changed
- `event AgentMinted(uint256 indexed agentId, uint256 mintNumber, address indexed owner)` - MUST be emitted when an agent is added to the collection

### Required Behavior

#### Collection Association

When an agent is minted through a collection contract, the contract MUST:

1. Register the agent in the [ERC-8004](/EIPs/EIPS/eip-8004) registry
2. Assign a sequential mint number starting from 1
3. Store the agent&apos;s mint number internally
4. Write collection metadata to the agent&apos;s Onchain Metadata using a key that identifies the collection
5. Emit an `AgentMinted` event

The metadata key is either the default or a parameterized form:

- **`agent-collection`** (no parameter, default): For the default or primary collection. This is the only case that does not use a parameterized key. Discoverable without indexing.
- **Parameterized form**: For additional collections per agent, the key MUST follow [ERC-8119](/EIPs/EIPS/eip-8119) parameterized key format. The label identifies the collection. All ERC-8119 forms are acceptable: `agent-collection:&lt;label&gt;`, `agent-collection/&lt;label&gt;`, or `agent-collection[&lt;label&gt;]` (e.g., `agent-collection:dev-team`, `agent-collection/dev-team`, `agent-collection[dev-team]`). Because the label can be any value, indexing the agent&apos;s metadata keys is necessary to discover collections beyond the default.

A collection contract MUST use a consistent key for all of its mints. Agents MAY belong to multiple collections; each collection writes to its own key.

The collection metadata format SHOULD be:

```solidity
abi.encodePacked(
    address collectionAddress,  // 20 bytes: the collection contract address
    uint8 mintNumberLength,     // 1 byte: length of mint number bytes
    bytes mintNumberBytes       // variable: the mint number (compact encoding)
)
```

This enables any party to:

- Look up which collection an agent belongs to
- Verify the collection contract address
- Decode the mint number from the metadata
- Query additional information from the collection contract

#### Mint Number Tracking

Mint numbers MUST:

- Start at 1 (not 0)
- Increment sequentially as agents are minted
- Be permanent and immutable once assigned
- Be queryable via `getAgentMintNumber()`

#### Supply Management

Collection contracts MUST:

- Enforce `maxSupply` limits (prevent minting beyond maximum)
- Track `currentSupply` accurately
- Emit `AgentMinted` events for each successful mint
- Respect the `startBlock` timing constraint

### Optional Features

The following features are OPTIONAL and left to implementation choice:

- **Access Control**: Who can mint (owner, public, allowlist, etc.)
- **Payment Model**: Free, paid (ETH/tokens), or other mechanisms
- **Collection State**: Open/close mechanisms, locking, pausing
- **Batch Minting**: Single or batch mint functions

#### Contract-level Metadata

Collections SHOULD implement [ERC-7572](/EIPs/EIPS/eip-7572) contract metadata to provide collection-level information such as name, description, image, and external links. This is done by implementing:

```solidity
function contractURI() external view returns (string memory);
```

The URI should point to a JSON file following the [ERC-7572](/EIPs/EIPS/eip-7572) metadata schema.

## Rationale

[ERC-8004](/EIPs/EIPS/eip-8004) agents are unlimited mint NFTs; this ERC was created to enable verifiable fixed-supply collections of agents. This standard attempts to make minting fixed-supply [ERC-8004](/EIPs/EIPS/eip-8004) agents as convenient as possible. The `getCollectionSupply()` function allows clients to query current supply without relying on an indexer. Collection configuration (maxSupply, startBlock, open) is communicated via the `CollectionUpdated` event, which is emitted at creation and whenever these values change.

## Backwards Compatibility

This standard is fully backwards compatible with:

- **[ERC-721](/EIPs/EIPS/eip-721)**: Agents remain standard [ERC-721](/EIPs/EIPS/eip-721) tokens
- **[ERC-8004](/EIPs/EIPS/eip-8004)**: Leverages existing registry infrastructure
- **[ERC-7572](/EIPs/EIPS/eip-7572)**: Optionally supports contract-level metadata

## Reference Implementation

A minimal reference implementation demonstrating the core requirements:

```solidity
pragma solidity ^0.8.25;

import {IERC8004AgentRegistry} from &quot;./interfaces/IERC8004AgentRegistry.sol&quot;;
import {IERC8041Collection} from &quot;./interfaces/IERC8041Collection.sol&quot;;

/**
 * @title ERC8041MinimalCollection
 * @notice Minimal reference implementation
 * @dev Users supply pre-registered agent IDs to add to collection.
 *      Use empty label for default collection (agent-collection), or a label for
 *      named collections (e.g., agent-collection:dev-team) to support multiple
 *      collections per agent.
 */
contract ERC8041MinimalCollection is IERC8041Collection {
    IERC8004AgentRegistry public immutable agentRegistry;

    uint256 public maxSupply;
    uint256 public currentSupply;
    uint256 public startBlock;
    bool public open;

    /// @notice Metadata key: &quot;agent-collection&quot; or parameterized per ERC-8119 (e.g. agent-collection:label, agent-collection/label, agent-collection[label])
    string public immutable collectionKey;

    mapping(uint256 agentId =&gt; uint256 mintNumber) private _agentMintNumber;

    constructor(
        IERC8004AgentRegistry _agentRegistry,
        uint256 _maxSupply,
        string memory _collectionLabel
    ) {
        agentRegistry = _agentRegistry;
        maxSupply = _maxSupply;
        startBlock = block.number;
        open = true;
        collectionKey = bytes(_collectionLabel).length == 0
            ? &quot;agent-collection&quot;
            : string(abi.encodePacked(&quot;agent-collection:&quot;, _collectionLabel));

        emit CollectionUpdated(_maxSupply, block.number, true);
    }

    /**
     * @notice Add an existing agent to the collection
     * @param agentId The ID of an agent already registered in ERC-8004
     */
    function mint(uint256 agentId) external {
        require(currentSupply &lt; maxSupply, &quot;Supply exceeded&quot;);
        require(agentRegistry.ownerOf(agentId) == msg.sender, &quot;Not agent owner&quot;);
        require(_agentMintNumber[agentId] == 0, &quot;Already in collection&quot;);

        currentSupply++;
        uint256 mintNumber = currentSupply;
        _agentMintNumber[agentId] = mintNumber;

        // Store collection metadata in the agent&apos;s onchain metadata
        bytes memory mintNumberBytes = abi.encode(mintNumber);
        uint8 mintNumberLength = uint8(mintNumberBytes.length);
        bytes memory collectionMetadata = abi.encodePacked(
            address(this),      // 20 bytes: collection contract address
            mintNumberLength,   // 1 byte: length of mint number bytes
            mintNumberBytes     // variable: the mint number (compact encoding)
        );

        IERC8004AgentRegistry(address(agentRegistry)).setMetadata(
            agentId,
            collectionKey,
            collectionMetadata
        );

        emit AgentMinted(agentId, mintNumber, msg.sender);
    }

    function getAgentMintNumber(uint256 agentId) external view returns (uint256) {
        return _agentMintNumber[agentId];
    }

    function getCollectionSupply() external view returns (uint256) {
        return currentSupply;
    }
}
```

This implementation demonstrates:

- **Collection labels**: Constructor accepts `_collectionLabel`; empty for default (`agent-collection`), or e.g. `&quot;dev-team&quot;` for `agent-collection:dev-team` (colon form; slash or bracket form also valid per ERC-8119) to enable multiple collections per agent
- **Single collection per contract**: Simplest deployment model
- **No access control**: Anyone can add their agents to the collection
- **Bring-your-own-agent model**: Users register agents separately, then add them to the collection
- **Full mint number tracking**: Each agent receives a sequential position number
- **Automatic start block**: Collection starts at deployment block

## Security Considerations

The owner of an [ERC-8004](/EIPs/EIPS/eip-8004) agent can modify or remove collection metadata (e.g., `agent-collection` or `agent-collection:dev-team`) stored on their agent at any time. Client applications MUST NOT rely solely on this metadata to verify collection membership. Instead, clients SHOULD:

1. Query the collection contract directly using `getAgentMintNumber(agentId)` to verify membership
2. Use the metadata as a convenience lookup to discover which collection to query, but always verify with the collection contract itself. To discover labeled collections (e.g., `agent-collection:dev-team`, `agent-collection/dev-team`, `agent-collection[dev-team]`), index the agent&apos;s metadata keys since labels are unbounded
3. Treat a mint number of `0` from the collection contract as definitive proof that an agent is not part of that collection

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).</description>
        <pubDate>Sat, 11 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8041</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8041</guid>
      </item>
    
      <item>
        <title>Diamond Storage</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8042-diamond-storage/25718</comments>
        
        <description>## Abstract
This standard formalizes the diamond storage pattern originally introduced by [ERC-2535 Diamonds](/EIPs/EIPS/eip-2535) and widely adopted across smart contracts.

Though originally created for proxy contracts, diamond storage can be used to organize storage and data access within *any* smart contract.

Diamond storage defines the location of structs in contract storage using the `keccak256` hash of human-readable identifiers.

[ERC-8042](./eip-8042) standardizes this simple and production-proven approach, offering a lightweight alternative to [ERC-7201](/EIPs/EIPS/eip-7201) for new and existing projects.


## Motivation

On March 10, 2020, a change to the Solidity compiler introduced the ability to assign structs to any storage location. This enabled a new pattern for using separate areas of storage. The pattern became known as diamond storage, as it was first popularized by ERC-2535 Diamonds and has since been widely used.

Later, on June 20, 2023, ERC-7201 was introduced to standardize this general storage pattern. However, the formula that ERC-7201 proposed for generating storage locations differed from the one already established and in active use by diamond storage.

ERC-8042 standardizes diamond storage for new projects and validates past diamond storage implementations.

While ERC-7201 defines a generalized mechanism for storage namespaces, ERC-8042 preserves the simplicity and backward compatibility of the diamond storage convention already deployed in production across many projects.

Developers may prefer diamond storage for its simplicity, restricted ASCII identifiers, and direct hash-based computation of storage locations.

This standard can be used by tools to find and access data within smart contract storage.

## Specification

Diamond storage defines where structs are located in contract storage.

A diamond storage identifier is defined as a string containing only printable ASCII characters. That is characters `0x20` through `0x7E` inclusive.

The location of a diamond storage struct is determined by the `keccak256` hash of a diamond storage identifier.

### Recommendations

1. #### Use Solidity&apos;s string literals

   A string literal is an ASCII string type that is literally written between quotes, for example: `&quot;this is a string literal&quot;`.

   It is recommended to use Solidity&apos;s string literals to create diamond storage identifiers because the Solidity compiler enforces that they only contain printable ASCII characters, characters `0x20` through `0x7E` inclusive. Hex (`\xNN`) and Unicode (`\uNNNN`) escape sequences should **NOT** be used in diamond storage identifiers.

   It is recommended to use compile-time constant string literals. Here is an example:

   `bytes32 constant STORAGE_POSITION = keccak256(&quot;myproject.erc721.registry&quot;);`

2. #### Use unique, human-readable, meaningful strings

   A human-readable string is a string that humans can normally read and understand, like &quot;Transaction successful&quot;.

   A meaningful string in this context is a string that appropriately names or describes a storage space, or uses a pattern to do so. For example, `&quot;myproject.erc721.registry&quot;` is a hierarchical pattern that specifies [ERC-721](/EIPs/EIPS/eip-721) related storage for a registry. The string `&quot;car.fish.piano.run&quot;` is not a meaningful string because it is random and does not appropriately name or describe something.

   Diamond storage identifiers should be unique, human-readable, meaningful strings.

3. #### Do NOT use Unicode literals

   Unicode literals can contain invisible characters and other non-ASCII characters which violates the specification of this standard.

   Here is an example of a Unicode literal in Solidity: `string memory a = unicode&quot;Hello 😃&quot;;`.

   Unicode literals should **NOT** be used to create diamond storage identifiers.

4. #### Do not use the space `0x20` character

   Including the space (`0x20`) character in diamond storage identifiers is not recommended, as it may interfere with tooling such as the NatSpec tag described next.


### ERC-8042 NatSpec tag

ERC-7201 defines the NatSpec tag `@custom:storage-location &lt;FORMULA_ID&gt;:&lt;NAMESPACE_ID&gt;`, where `&lt;FORMULA_ID&gt;` identifies a formula used to compute the storage location of a struct based on the namespace id.

The formula identified by `erc8042` is defined as `erc8042(id: string literal) = keccak256(id)`. In Solidity, this corresponds to the expression `keccak256(id)`. When using this formula the annotation becomes `@custom:storage-location erc8042:&lt;NAMESPACE_ID&gt;`. For example, `@custom:storage-location erc8042:myproject.erc721.registry` annotates diamond storage with id `&quot;myproject.erc721.registry&quot;` rooted at `erc8042(&quot;myproject.erc721.registry&quot;)`.


## Rationale

Proxy contracts and contracts that use `DELEGATECALL` need a reliable and secure way to define, document, and manage separate areas of smart contract storage. 

In March 2020, diamond storage established a way to do this and has been in use since then. However, diamond storage wasn&apos;t formalized as a standard, which is important to clarify its mechanics, usage and precise specification.

In June 2023, ERC-7201 Namespaced Storage Layout standardized the general pattern but has looser restrictions on namespace ids and a more complicated formula for calculating storage locations. Some people may prefer using ERC-7201, especially if they may auto-generate machine-readable or random strings for their namespace ids.

Some people may prefer ERC-8042 Diamond Storage for its ASCII-enforced, human-readable, meaningful strings and simple calculation of storage locations.

ERC-2535 Diamonds first introduced the pattern of distinct storage areas for smart contracts. ERC-7201 later standardized the idea. ERC-8042 standardizes the original, simpler diamond storage variant for new projects and legacy compatibility.

Though originally created for proxy contracts, diamond storage can be used to organize storage and data access within *any* smart contract.

### Comparing ERC-8042 and ERC-7201

#### ERC-7201

ERC-7201 applies a formula to a namespace id to generate a storage location. Per the ERC-7201 specification a namespace id is a string that should not contain any whitespace characters. A namespace id has no other restrictions. So a namespace id could be something meaningful like `mycompany.projectA.erc721` or it could be a series of random bytes, characters or words, etc.

ERC-7201 uses the following formula, given in Solidity, to generate a storage location: `keccak256(abi.encode(uint256(keccak256(bytes(namespace id))) - 1)) &amp; ~bytes32(uint256(0xff))`.

   1. The first part of the ERC-7201 formula `keccak256(abi.encode(uint256(keccak256(bytes(namespace id))) - 1))` ensures that the input bytes to the second call to `keccak256` will not match any input bytes used by Solidity&apos;s types that also use `keccak256` to determine storage locations. This makes it possible to use any sequence of bytes for the namespace id.

   2. The last part of ERC-7201, `&amp; ~bytes32(uint256(0xff))` ensures that the final storage location is a multiple of 256 which may provide a gas optimization in the future.

#### ERC-8042

ERC-8042 identifiers can only contain printable ASCII characters and recommends using Solidity&apos;s string literals which enforces this constraint.

ERC-8042 recommends human-readable, meaningful strings for diamond storage identifiers. 

ERC-8042 uses the following formula, given in Solidity, to generate a storage location: `keccak256(string literal)`.

## Backwards Compatibility

Diamond storage as described by this standard has been in use for 5 years. This standard recognizes and standardizes all previous uses of diamond storage that conform to the specification.

## Reference Implementation

This is a simple example of a contract that uses diamond storage:
```solidity
/**
 * @title ERC721Registry
 * @notice A registry contract for tracking ERC721 contracts.
 *         Allows adding ERC721 contract addresses up to a configurable limit.
 * @dev EIP-8042 Diamond Storage is used to organize and manage access to storage.
 */
contract ERC721Registry {

  /// @notice Reverts when the registry reaches its configured capacity.
  error ERC721RegistryFull();
  
  /// @notice Struct storage position defined by keccak256 hash 
  ///         of diamond storage identifier.
  bytes32 constant STORAGE_POSITION = keccak256(&quot;myproject.erc721.registry&quot;);
 
  /// @notice @notice Storage layout for the ERC721 registry, following EIP-8042.  
  /// @dev - `erc721Contracts`: Dynamic array of registered ERC721 contract addresses.
  ///      - `registryLimit`: Maximum allowed entries.
  /// @custom:storage-location erc8042:myproject.erc721.registry
  struct ERC721RegistryStorage {
    address[] erc721Contracts;
    uint256 registryLimit;    
  }

  /// @notice Returns a pointer to the ERC721RegistryStorage struct in storage.
  /// @dev Uses inline assembly to access the storage slot defined by STORAGE_POSITION.
  /// @return s The ERC173Storage struct in storage.
  function getStorage() internal pure  returns (ERC721RegistryStorage storage s) {
    bytes32 position = STORAGE_POSITION;
    assembly {
      s.slot := position
    }
  }

  /// @notice Sets the maximum number of ERC721 contracts the registry can hold.  
  /// @param _newLimit New registry capacity limit.
  function setRegistryLimit(uint256 _newLimit) internal {
    getStorage().registryLimit = _newLimit;
  }

  /// @notice Adds an ERC721 contract address to the registry.
  /// @dev Reverts with `ERC721RegistryFull` if the registry is full.
  /// @param _erc721Contract Address of the ERC721 contract to register.
  function addERC721Contract(address _erc721Contract) internal { 
    ERC721RegistryStorage storage s = getStorage();

    if(s.erc721Contracts.length == s.registryLimit) {
      revert ERC721RegistryFull();
    }
    
    s.erc721Contracts.push(_erc721Contract);        
  }

  /// @notice Returns a list of all registered ERC721 contract addresses.
  /// @return Array of registered ERC721 contract addresses.
  function getERC721Registry() internal view returns (address[] memory) {
    return getStorage().erc721Contracts;
  }
}
```

## Security Considerations

### Uniqueness of identifiers
Two independent contracts or libraries using the same human-readable string will map to the same storage slot. Developers must ensure that diamond storage identifiers are unique within a contract system to prevent unintentional data overlap or corruption. A common practice is to prefix identifiers with a project, organization, or standard name (for example, `&quot;myproject.erc721.registry&quot;`).


### ASCII Input Restriction to Prevent Storage Collisions

To prevent storage collisions, diamond storage identifiers must consist only of printable ASCII characters, specifically the range `0x20` to `0x7E` inclusive. Identifiers must not include Unicode escape sequences (`\uNNNN`) or hexadecimal escape sequences (`\xNN`).

Solidity’s storage slot encoding, as produced by `abi.encode(p)`, contains non-printable bytes, particularly null bytes (`0x00`), due to Solidity’s default storage layout and padding rules.

Allowing identifiers to include such bytes could enable a malicious developer to craft an identifier like `&quot;config\x00\x00...&quot;`. The bytes of such an identifier could collide with the storage encoded input of mappings, dynamic arrays, strings and bytes which use `keccak256` to compute storage locations. Such collisions could result in overwrites, corruption of contract state, or security vulnerabilities.

Restricting identifiers to printable ASCII removes this exploitable source of collision. While this restriction does not provide a mathematical guarantee that collisions are impossible — because, in theory, a sufficiently large storage layout position (`p`) could accidentally contain all printable ASCII bytes — the probability of this occurring is extremely small, and impractical.

By using human-readable, meaningful strings for identifiers, the practical likelihood of any collision is virtually zero, providing strong protection for the integrity and safety of contract storage.

### String Literals

The specification recommends using string literals to create diamond storage identifiers because the Solidity compiler enforces that only printable ASCII characters are used. However, string literals should not use Unicode escape sequences (`\uNNNN` ) or hexadecimal escape sequences (`\xNN` ).

### Unicode Literals

Unicode literals (e.g. `unicode&quot;Hello 😃&quot;`) should not be used to create diamond storage identifiers because they can contain non-printable bytes and characters, and they can be used to obfuscate identifiers by using characters that look like other characters. For example, the Cyrillic character `а` (`\u0430`) looks identical to the ASCII character `a` (`\u0061`).” In addition Unicode has control characters that change the direction text is displayed.

### `keccak256` Hash Collision Resistance

The location of a diamond storage struct is determined by the output of the `keccak256` hash function. Some developers may wonder about the likelihood that a diamond storage struct lands at an address where it will accidentally overwrite existing storage data. The 256-bit address space of contract storage is so vast that the likelihood of data overlap is statistically improbable.

Solidity mappings, dynamic arrays, strings and bytes also use `keccak256` to determine their location in contract storage.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).</description>
        <pubDate>Sat, 11 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8042</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8042</guid>
      </item>
    
      <item>
        <title>Exclude slashed validators from proposing</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8045-exclude-slashed-validators-from-proposing/25850</comments>
        
        <description>## Abstract

This EIP proposes a modification to the beacon chain proposer selection process to exclude slashed validators from being selected as proposers. 

## Motivation

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.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

The `get_beacon_proposer_indices` 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. 

```python
def get_beacon_proposer_indices(
    state: BeaconState, epoch: Epoch
) -&gt; Vector[ValidatorIndex, SLOTS_PER_EPOCH]:
    &quot;&quot;&quot;
    Return the proposer indices for the given ``epoch``.
    &quot;&quot;&quot;
    # Modified to exclude slashed validators
    indices = [i for i in get_active_validator_indices(state, epoch) if not state.validators[i].slashed]
    seed = get_seed(state, epoch, DOMAIN_BEACON_PROPOSER)
    return compute_proposer_indices(state, epoch, seed, indices)
```

## Rationale

### Why exclude slashed validators?

Slashed validators are already prevented from successfully proposing blocks through the state transition validation. The `process_block` 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.

### Design decision: upfront filtering

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.

## Backwards Compatibility

This EIP introduces a backwards-incompatible change to the consensus rules and MUST be activated as part of a scheduled network upgrade.

## Test Cases

Test cases should verify that:

1. Slashed validators are not selected as proposers
2. A complete `proposer_lookahead` is generated even in the presence of slashed validators
3. Slashings do not affect the existing `proposer_lookahead`

## Security Considerations

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 [EIP-7917](/EIPs/EIPS/eip-7917), 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.

### Impact on proposer selection distribution

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.

### Mass slashing scenarios

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.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Uniform price auction over inclusion lists</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8046-uniform-price-auction-over-inclusion-lists/25844</comments>
        
        <description>## Abstract

This EIP proposes a uniform price auction over inclusion lists (UPIL), which ranks transactions by their offered ranking fee per gas. When the block is full, no transaction is allowed to displace an inclusion-list (IL) transaction that passes regular inclusion criteria and offers a higher ranking fee per gas. All included transactions pay a uniform inclusion price, equal to the highest ranking fee offered by any valid IL transaction excluded from the block, and this fee is burned. UPIL achieves strong censorship resistance by not allowing builders to circumvent propagated ILs when the block is full. This is particularly valuable for time-sensitive transactions and promotes fairness while preventing cheap block-stuffing under a multidimensional fee market. UPIL is specified to run on top of FOCIL ([EIP-7805](/EIPs/EIPS/eip-7805)), but can be deployed on top of any IL mechanism.

## Motivation

Censorship resistance (CR) is a key property of decentralized blockchains. To ensure that transactions cannot be censored by the entity building the block (denoted &quot;builder&quot; in this EIP, which may sometimes be the proposer), a mechanism called fork-choice enforced inclusion lists (FOCIL) has been proposed in [EIP-7805](/EIPs/EIPS/eip-7805). A set of includers propagate inclusion lists (ILs), and the attesters uphold that the transactions in the ILs are included in the block via the fork-choice. There is no mechanism for ranking transactions in the ILs, and therefore not viable to uphold CR when the block is full. If IL transactions must be prioritized under full blocks, the builder could simply integrate with includers to propagate ILs containing the transactions it wishes to include in the block.

To uphold CR also under full blocks, it is necessary to have a framework for which transactions to include and exclude. This EIP specifies a uniform price auction over inclusion lists (UPIL), which ranks transactions by their offered `ranking_fee_per_gas`, derived from their specified `max_ranking_fee_per_gas`. If a block is full, no transaction is allowed to displace an IL transaction with a higher `ranking_fee_per_gas`, as long as the displaced IL transaction passes regular inclusion criteria. All included transactions pay the &quot;marginal&quot; ranking fee, corresponding to the highest ranking fee offered by a valid IL transaction excluded from the block, and this fee is burned. If no IL transaction was excluded, the marginal ranking fee is `0`. In essence, the existing base fee prices inter-block contention, while UPIL is an auction mechanism that relies on ILs to impose a secondary base fee that prices intra-block contention.

Ethereum is currently pursuing scaling by tracking gas consumption across separate resources, allowing each resource to be consumed at its maximum capacity. With a multidimensional approach, it can become cheaper to &quot;stuff the block&quot; such that it is full in any dimension by creating &quot;dummy transactions&quot; that only consume one specific resource. This degrades the CR of FOCIL, since builders can ignore ILs in full blocks. In the multidimensional [EIP-7706](/EIPs/EIPS/eip-7706) and [EIP-7999](/EIPs/EIPS/eip-7999), the degradation of CR can become rather pronounced. Base fees are set individually per resource and may become very low, depending on whether reserve prices in the style of [EIP-7918](/EIPs/EIPS/eip-7918) are adopted or not. Furthermore, if the builder varies which resource that is full across blocks, there is no longer an exponentially increasing cost to keep a transaction censored block after block.

The strong CR of UPIL is particularly suitable under a multidimensional fee market, but can be beneficial under any fee market. Some transactions are time-sensitive: what matters is inclusion within a set time frame. Sometimes, that time frame consists of just a few or a single block. UPIL guarantees inclusion in the next block for a transaction offering a sufficient ranking fee, assuming includers and attesters do their duties. This puts includers and the builder on a more equal footing. Furthermore, the lack of ranking in FOCIL gives builders an incentive to amass private transactions to facilitate low-cost temporary censorship, which could negatively affect the public mempool. However, both FOCIL and UPIL also have properties that strengthen the public mempool.

## Specification

### New transaction format and ranking fee

A new field `max_ranking_fee_per_gas` is added to a new [EIP-2718](/EIPs/EIPS/eip-2718) transaction with `TransactionType` = `RANK_TX_TYPE`. The `TransactionPayload` for this transaction is:

&lt;-- TODO --&gt;

```Python
# TODO: To be defined after scheduling this EIP relative to EIP-7999 and EIP-8011, etc.
```

The ranking is performed on the `ranking_fee_per_gas`, corresponding to the maximum ranking fee that the transactor was willing to pay under the current base fee. Older transaction formats use their entire headroom for their offered ranking fee, whereas the new format can cap the ranking fee using the `max_ranking_fee_per_gas` field. 

```Python
def get_max_fee(tx: Transaction) -&gt; int:
    if is_legacy(tx.type):
        return tx.gas_price
    else:
        return tx.max_fee_per_gas

def get_ranking_fee(tx: Transaction, block: Block) -&gt; int:
    ranking_fee_per_gas = get_max_fee(tx) - block.base_fee_per_gas
    
    # The new RANK_TX_TYPE can set a cap to the offered ranking fee
    if tx.type == RANK_TX_TYPE:
        return min(tx.max_ranking_fee_per_gas, ranking_fee_per_gas)
    else:
        return ranking_fee_per_gas
```

The ranking fee does not impose ordering constraints within the block, and only governs inclusion. The alternative specifications section discusses the options that exist for computing the `ranking_fee_per_gas` in various transaction formats, including the option to not implement a new transaction format at all.

### Transaction processing

The builder specifies in the block body the `marginal_ranking_fee_per_gas` that all transactions must pay. The full `inclusion_fee_per_gas` corresponding to `base_fee_per_gas + marginal_ranking_fee_per_gas` is covered before the priority fee. A valid transaction must have `max_fee_per_gas &gt;= inclusion_fee_per_gas` and `RANK_TX_TYPE` transactions must also have `max_ranking_fee_per_gas &gt;= marginal_ranking_fee_per_gas`. Thus, under [EIP-1559](/EIPs/EIPS/eip-1559), transaction processing is changed as follows:

```Python
for unnormalized_transaction in transactions:
    ...
    # After this existing check...
    assert transaction.max_fee_per_gas &gt;= transaction.max_priority_fee_per_gas
    
    # ..check that the transactor is willing to pay the marginal ranking fee
    if transaction.type == RANK_TX_TYPE:
        assert block.marginal_ranking_fee_per_gas &lt;= transaction.max_ranking_fee_per_gas

    # ..derive the inclusion fee per gas and perform checks
    inclusion_fee_per_gas = block.base_fee_per_gas + block.marginal_ranking_fee_per_gas
    assert transaction.max_fee_per_gas &gt;= inclusion_fee_per_gas
    
    # ..cap the priority fee by the inclusion fee instead of the base fee
    priority_fee_per_gas = min(transaction.max_priority_fee_per_gas, transaction.max_fee_per_gas - inclusion_fee_per_gas)

    # ..and adjust the line calculating the effective gas price
    effective_gas_price = priority_fee_per_gas + inclusion_fee_per_gas
    ...
```

The inclusion fee is never distributed and thus burned. Note that legacy transactions are assigned `max_fee_per_gas = gas_price` and `max_priority_fee_per_gas = gas_price` as part of a prior normalization step. The existing assert statement

```Python
assert transaction.max_fee_per_gas &gt;= block.base_fee_per_gas
```

is redundant and is removed.

### Altered FOCIL post-execution inclusion check

The post-execution inclusion check of [EIP-7805](/EIPs/EIPS/eip-7805) is altered as outlined in the figure. Orange squares represent the original FOCIL checks, where &quot;No&quot; always leads to jumping to the next transaction. Blue squares are the checks added in UPIL that account for ranking. The first black square of step (1) contains only peripheral modifications that do not alter the intended outcome of the inclusion check.

![Figure 1](/EIPs/assets/eip-8046/1.png)

The `ranking_fee_per_gas` is first computed for each transaction `X` in the block via `get_ranking_fee(X, B)`. Then, for each transaction `T` in ILs, the check performs three steps. 

-----

The original step (1)

&gt; (1) Check whether `T` is present in `B`. If `T` is present, then jump to the next transaction, else continue with next step.

is replaced with the following:

(1) If `T` is present in `B`, or `get_max_fee(T) &lt; block.base_fee_per_gas`, or `T` fails static validity, then skip `T` and jump to the next IL transaction, else continue to the next step.

-----

The original step (2):

&gt; (2) Check whether `B` has enough remaining gas to execute `T`. If `T.gas` &gt; `gas_left`, then jump to the next transaction, else continue with next step.

is replaced with the following:

(2a) Check whether `B` has enough remaining gas to execute `T`: `gas_left &gt;= T.gas_limit`. If so, continue to (3a); otherwise, continue to (2b) potentially followed by (3b).

(2b) Check whether `B` would have had enough remaining gas to execute `T`, if `T` was included together with only higher-ranked transactions in `B`. First compute `T.ranking_fee_per_gas = get_ranking_fee(T, B)` and then compute `gas_ranked_left(T)` as the remaining gas after subtracting the `gas_used` of all transactions of the block with a higher `ranking_fee_per_gas` than `T` from `B.gas_limit`. For transactions with the same `ranking_fee_per_gas`, included transactions in `B` are considered higher-ranked than not-included IL transactions. If `gas_ranked_left(T) &gt;= T.gas_limit`, continue to (3b); otherwise jump to the next IL transaction.

-----

The original step (3): 

&gt; (3) Validate `T` against `S` by checking the nonce and balance of `T.origin`.

is replaced with the following:

(3a) Validate `T` against `S` by checking the nonce and balance of `T.origin`.

(3b) Validate `T` against `S` by checking the nonce of `T.origin`. Further validate `T` against the balance of the origin account by applying the standard pre-execution fundability check to a conservative balance that ignores all increases and counts all decreases to `T.origin` at the completion of each executed transaction of the block. Intermediate increases or decreases during the execution of a transaction are not tracked in isolation.

Step (3a) and (3b) conclude as previously:

&gt; If `T` is invalid, then continue to the next transaction. 
&gt;
&gt; If `T` is valid, terminate process and return an `INCLUSION_LIST_UNSATISFIED` error.

### Check on the marginal ranking fee

Attesters review excluded IL transactions to confirm that the `marginal_ranking_fee_per_gas` was set correctly by the builder. If step (2b) indicates that the transaction was outranked, then, before continuing with the next transaction, the transaction is also checked against step (3b), as indicated by a dashed line in the figure. The highest `ranking_fee_per_gas` among outranked IL transactions from (2b) that pass the valid inclusion check of (3b) must equal `marginal_ranking_fee_per_gas`. If no outranked IL transaction passes (3b), the `marginal_ranking_fee_per_gas` must be `0`.

## Rationale

### Updated inclusion check

#### Conservative balance 

The reason for using a conservative balance in (3b) when validating `T` is to avoid the circular dependencies that can emerge when a transaction is made executable by a lower-ranked transaction. Consider three transactions `A`, `B`, and `C` ranked as `A&gt;B&gt;C`. Without a conservative balance, `A` might be funded only if `B` is included in the block. For example, transaction `B` might fund `A`, so without `B`, `A` cannot be included, and without `A`, `B` cannot be included due to having a lower ranking. There is not enough gas to include both `A` and `B`. Including neither and instead including `C` also fails because the left out `B` was higher ranked.

It is not necessary that `B` directly funds `A`. It might very well be the case that `B` just changes the state such that a higher-ranked transaction `X` funds `A`, something that `X` would not do unless `B` was run beforehand.

It should be noted in (3b) that the transactor is in control of decreases to its ETH balance. Within a block, ETH leaves `T.origin` only via the transactor’s own signed transactions (value transfers and gas payments) or contracts it has explicitly authorized; the builder cannot manufacture debits. If the transactor’s own debits make `T` unfundable, and these are included in the block—even if lower-ranked—exclusion is acceptable as a consequence of choices made. After all, the transactor controls the relative order of its own transactions via nonces. Thus, ranking is neither considered for debits nor for credits: debits count regardless of rank, and credits do not count at all.

#### Retained FOCIL check in non-full blocks

The regular FOCIL check is retained in non-full blocks to take advantage of its operational simplicity and since the conservative balance check of UPIL is unnecessarily lenient to the builder whenever an excluded IL transaction would have fit and is funded during processing of the prior transactions in the block. The circular dependencies from the previous subsection do not apply in FOCIL since there is no requirement for transactions in the IL to be included in the block if a transaction outside of the IL uses up the gas. Once (2a) confirms slack, the builder was clearly able to include any existing funding transaction in the block and still include `T`, so skipping `T` is an IL violation. UPIL could otherwise also be implemented completely without the old FOCIL checks, to reduce code surface. This corresponds to removing the orange boxes in the figure, retaining the blue boxes.

#### Compute requirements for (2b) and (3b)

The new conditions can be checked efficiently by clients. 

In step (2b), validators can generate a list of the transactions in the block post-execution, sorted according to `ranking_fee_per_gas`, with an associated list of the cumulative gas consumption. The check for each transaction then only requires keying into the list and extracting the associated gas consumption.

For step (3b), the preprocessing consists of tracking a limited set of account-balance-changes during transaction processing. Before processing the block, the client builds an observation set `E` of `T.origin` balances for excluded IL transactions. After processing each transaction, it updates `E`, accounting for all decreases to `T.origin` balances but ignoring increases. If a block-level access list (BAL) is available that tracks all balance changes, the overall task is further simplified.

The check on the `marginal_ranking_fee_per_gas` (dashed line in the figure) is also trivial. For example, all outranked IL transactions that are otherwise validly includable can have their `ranking_fee_per_gas` added to an array. After all IL transactions have been reviewed, the maximum entry of this array must equal the specified `marginal_ranking_fee_per_gas`. If the array is empty, the `marginal_ranking_fee_per_gas` must instead be `0`.

### Auction design

The uniform price auction design allows transactors to signal intent (to overcome censorship if the block is full), without actually having to pay more than necessary. A transactor may not know beforehand if they will be censored, and may not wish to pay a very high fee for no reason. There are similarities to the current base fee model. Everyone specifies their willingness to pay, but pays the same minimum fee for inclusion, and this fee is burned. The combination of intents and fairness is attractive. A key difference is that the base fee is a clearing fee tracking contention for blockspace at the inter-block level, whereas the marginal ranking fee is a clearing fee tracking contention for blockspace at the intra-block level (locally for each block).

In essence, Ethereum’s current fee mechanism combines a uniform-price base fee that clears congestion across blocks with a first-price priority fee allocating space within each block. What UPIL does is to expand the uniform-price component to the intra-block level by introducing a marginal ranking fee that all included transactions pay equally. Inclusion will thus be governed primarily by protocol-defined uniform clearing (assuming transactions are surfaced in ILs).

The `max_ranking_fee_per_gas` is expected to be set rather low under normal circumstances. Most transactors will not be willing to pay excessively to be included in full blocks, and can instead wait for the next block. However, since the next block will have a 12.5% higher base fee, most transactors will at a minimum set `max_ranking_fee_per_gas` to 12.5% of the current base fee. The increase in burned fees extracted from transactors in full blocks will be offset by a decrease in priority fees, since the builder no longer controls which transactions that are included (furthermore, includers may also receive other fees, as discussed in the section on includer rewards). The ranking fee will also help with clearing in a fair manner under congestion during sudden spikes in transaction demand. All transactions included in the same block will pay the same ranking fee, with transactions willing to pay the most during a sudden spike included in the first available block. This is arguably an improvement to the UX for Ethereum&apos;s users.

The reason for burning the marginal ranking fee instead of paying it out to includers is that includers otherwise could have an incentive to engineer artificial congestion in order to raise the fee. This is not trivial, requiring many separate entities to agree to withhold transaction inclusion for consecutive blocks. Various configurations for how to reward includers for their work are outlined in a subsequent section, including the option to distribute the marginal ranking fee to them.

The builder may sometimes, via its private orderflow or late-arriving transactions, have some ability to raise the `marginal_ranking_fee_per_gas` by including transactions that outrank IL transactions. But a builder that raises the marginal ranking fee will also inadvertently reduce the priority-fee headroom for all transactions, since the inclusion fee is subtracted from the max fee before calculating the capped priority fee for all transactions in the block.

### Multidimensional UPIL

If there are multiple resources, `gas_ranked_left(T)` is a vector. Using the notation of [EIP-7999](/EIPs/EIPS/eip-7999), all *conditional* resources must then be checked against the corresponding gas limits specified by the analyzed transaction. Transactions that consume any *deconditional* resource are not subject to the UPIL post-execution check, and insufficient capacity in an *unconditional* resource is never a valid reason to exclude an IL transaction.

Thus, under multidimensional UPIL, the transaction is checked against `gas_ranked_left(T)` over the conditional resources only, in both (2a) and (2b). However, given the strong CR of UPIL, it would be perfectly feasible to classify calldata as conditional instead of using the unconditional classification of [EIP-7999](/EIPs/EIPS/eip-7999).

### Censorship resistance under FOCIL and UPIL

This subsection offers a comparison of the censorship resistance achieved under FOCIL and UPIL. The premise is a builder seeking to censor a transaction under different fee market designs. We begin by rudimentarily quantifying the cost $C_i$ of censoring a transaction in block $i$ ($i=0$ for the first censored block) as:

$C_i = g_df_b  (1+r)^i  + g_df_r +  m(i, f_r).$

In this equation, $g_d$ is the gas that the builder must pay by creating so-called &quot;dummy transactions&quot; to fill the block, $f_b$ is the base fee for that gas, $r$ is the rate by which the base fee increases in full blocks (i.e., 12.5%), $f_r$ is the `ranking_fee_per_gas` of the censored transaction, and $m(i, f_r)$ is the MEV (including priority fees) forgone when forced to exclude pending transactions with a lower ranking than the censored transaction for block $i$ (the opportunity cost).

#### Multidimensional fee market

Under a multidimensional fee market envisioned in [EIP-7706](/EIPs/EIPS/eip-7706) and [EIP-7999](/EIPs/EIPS/eip-7999), the base fee is set individually per resource to maximize utilization of blockspace. As noted in [EIP-7999](/EIPs/EIPS/eip-7999), the base fee may therefore sometimes become very low for a resource, meaning that the cost of generating dummy transactions to fill the block also becomes very low. In a potential multidimensional FOCIL, it is then only necessary that one resource used by a transaction is filled to censor that transaction. Furthermore, while the base fee will increase for the resource that was filled with dummy transactions, the base fees of all other resources will not. These base fees will instead vary based on gas consumed by regular transactions included in the block. The builder can potentially vary which resource it fills the block for, to keep any base fee from exploding during prolonged censorship. Define $\mathbf{f_b}$ as the vector of base fees. The outcome for FOCIL and UPIL respectively is:

**FOCIL:** The cost of censorship for the first block is $C_0 = g_d\min(\mathbf{f_b})$, and thus $C_0 \to 0$ if $\min(\mathbf{f_b}) \to 0$. The cost can potentially be kept close to 0 even under continued censorship, depending on the distribution of the equilibrium base fees under no censorship and the fee elasticities of demand.

- There is no ranking fee (thus $g_df_r \to 0$) and there is no opportunity cost because the builder can always include lower-ranked transactions when it fills the block (thus $m(i, f_r) \to 0$).
- The builder can switch between resources it fills, thus potentially keeping its overall costs contained even under continued censorship. This depends on prevailing fee elasticities and equilibrium base fees under no censorship. 
- If there is just one base fee that is low initially, then that base fee will rise (albeit from a low starting point), if the builder does not assume the opportunity cost $m(i, f_r)$ of excluding other transactions. Fee elasticities are relevant also in this case, because the rise in a single base fee should moderately reduce demand for all other resources as the transactor reviews the total cost.

**UPIL:** The cost of censorship for the first block is $C_0 = g_d\min(\mathbf{f_b}) + g_df_r + m(i, f_r)$, and thus $C_0 = g_df_r + m(i, f_r)$ if $\min(\mathbf{f_b}) \to 0$. This cost can be hundreds or thousands of times higher than whatever ranking fee the censored transaction specifies, and it rises with continued censorship due to the opportunity cost of keeping all pending transactions with a lower ranking fee that consume the filled resource out of the block.

- If the transactor specifies a ranking fee $f_r$ that exceeds the ranking fee of existing transactions in the mempool, the censoring builder will need to create dummy transactions up to the entire gas limit of the resource it is targeting. This can be specified as $g_d = g_l-g_r(T)$, where $g_r(T)$ is the gas already consumed by the censored transaction. Thus, the censoring builder must pay $f_r(g_l-g_r(T))$. To censor a transaction consuming 100k gas when the gas limit is 60M in the filled resource, the builder must pay $(60-0.1)/0.1 = 599$ times more than what the transactor was willing to pay for inclusion. As the gas limit expands, the relative cost of censorship increases. It should here be noted that the transactor will not need to pay its high offered ranking fee if it is indeed censored, and would after censorship concludes only pay according to the `marginal_ranking_fee_per_gas` of the subsequent block.
- The opportunity cost from censorship is also higher under UPIL than FOCIL, since no pending transaction with a ranking fee $f&apos;_r&lt;f_r$ that consumes the filled resource can be included if the censored transaction is excluded.

#### Current fee market

We now discuss the situation under the current fee market with a single base fee (ignoring the blob resource). In this case, the base fee term of the previous equation does not vanish. If the builder does not use the &quot;slow transaction&quot; strategies outlined in the next subsection, the outcome for FOCIL and UPIL respectively is:

**FOCIL:** The builder must cover the base fees: $g_df_b(1+r)^i$ of block $i$. The required amount of purchased gas $g_d$ will in the average case be $g_d=g_l/2$. However, there will be many instances where pending transactions in the public mempool or via private orderflow consume more than $g_l/2$. Censorship for one or two blocks can therefore be inexpensive even if pending transactions do not completely fill the block. The $(1+r)^i$ term grows by 12.5% per block, doubling in six blocks, and pending transactions are quickly depleted. Therefore, censorship becomes costly rather quickly: FOCIL ensures that transactions are included within a limited number of blocks if includers do their duties, but not in the first few blocks.

**UPIL:** The builder must cover the base fee, the ranking fee, and forego pending transactions, thus suffering a cost of $g_df_b(1+r)^i + g_df_r + m(i, f_r)$. The required gas $g_d$ is higher than in FOCIL, and—just as for the multidimensional fee market—potentially the full gas limit, because the builder cannot rely on pending transactions with a lower ranking fee for block stuffing. Due to the $g_df_r$ term, the cost for censoring a transaction for a single block can easily become a thousand times higher than whatever the transactor was willing to pay for inclusion, just as under the multidimensional fee market.

#### Current fee market with &quot;slow transactions&quot;

Note the importance of pending transactions for sidestepping the ILs in FOCIL: the cost for covering base fees when filling the block provides the CR. A strategy the builder could use to reduce the cost of censorship over a few blocks is to amass &quot;slow transactions&quot; through private orderflow—transactions that do not have to execute immediately. These are transactions for which the transactor is willing to substitute speed for some other benefit, predominantly rebated fees, but potentially also convenience or MEV protection. The builder (or realistically a MEV-protecting RPC endpoint) guarantees (trustfully) inclusion within some set time frame, and that the total cost for the transactor will be below the cost that would have been incurred given the base fee at the time that the tx is sent to the builder. The concept can be integrated as:

$C_i = g_df_b  ((1+r)^i-s)  + g_df_r +  m(i, f_r).$

Here, $s$ represents the cost reduction factor relative to the initial base fee. This models a scenario where the builder has stored and promised to include blockspace-filling transactions at a fixed discount. If the rebate to transactors for slow transactions is 10%, then $s=0.9$, with the cost of censoring the first block in FOCIL reduced by 90%. Such a strategy can thus be useful for censoring a couple of blocks in a row. After around 5 blocks or less, $(1+r)^i - s &gt; 1$, meaning that the cost is the same as the cost of censoring the first block without slow transactions. Since the supply of slow transactions would likely be limited, the strategy cannot be applied too often. 

Slow transactions must be propagated privately to remain useful, and reach their full economic potential by contributing to censorship. When the value in sidestepping ILs exceeds the costs of facilitating slow transactions, the proportion of transactions propagated p2p may thus fall. On the other hand, the transactions that indeed are propagated p2p are upon IL listing guaranteed inclusion in non-full blocks, and therefore do not need to pay priority fees. The effect of FOCIL on the public mempool may therefore be negative or positive depending on the demand for censorship from builders. Alternatively, the protocol could facilitate &quot;trustless slow transactions&quot; by letting builders sponsor transactions offering a max fee below the prevailing base fee, for example by charging the base fee jointly for all transactions at the end of the block.

Under UPIL, slow transactions do not contribute meaningfully to censorship due to the $g_df_r +  m(i, f_r)$ terms, and there is furthermore no rationale for paying a priority fee upon listing, further strengthening the public mempool.

#### Multidimensional gas metering

Under multidimensional gas metering in [EIP-8011](/EIPs/EIPS/eip-8011), the situation is closer to the current fee market than the multidimensional fee market. There is still just one base fee, so the cost of censoring a transaction for a sustained period rises exponentially. Censorship may become slightly cheaper than currently, due to the equilibrium reduction in the base fee with a maintained slack in the block relative to the most consumed resource. On the other hand, utilization of slow transactions may become slightly less efficient.

In the current fee market, half the gas limit $g_l/2$ is consumed in the average block. Transactors spend $f_bg_l/2$ on average and the cost of censoring a block via dummy transactions is also $f_bg_l/2$. Under multidimensional gas metering, $g_l/2$ is consumed on average individually for the most used resource. Transactors however consume the higher $xg_l/2$ amount of gas on average over all resources, while the gas required for censorship remains at $g_l/2$ (filling up the most consumed resource). Here $x$ corresponds to the scaling factor achieved when gas of different resources can be consumed in parallel, a scaling factor that might end up in the range 2-4. Keeping demand and $g_l$ fixed, the base fee $f_b$ will fall, reducing the cost $f_bg_l/2$ of censoring a block in the average case. Had we instead simply increased the gas limit, CR would have been affected differently, because then the cost of censorship would also have increased according to the increase in $g_l$, such that the censoring builder would have needed to purchase more dummy transactions in the average case.

#### Transaction inclusion and MEV

In FOCIL, including an existing transaction is always possible without raising the inclusion fee, regardless of whether this means that an IL transaction must be excluded or not. In UPIL, if the block is full, including an existing transaction over an IL transaction willing to pay more is treated as censorship. Ostensibly, MEV and censorship are not separate topics: in many scenarios, censorship is also MEV. To displace the IL transaction offering the lowest ranking fee among IL transactions in the block, the new transaction must pay at least the ranking fee offered by that IL transaction.

Since the builder cannot freely decide which of the pending transactions to include in UPIL, it might not be able to extract all MEV from pending transactions that it could have in FOCIL. It lacks the ability to exclude IL transactions at will from full blocks. Once a transaction is in an IL, its inclusion is guaranteed if it is willing to pay at least the same as the smallest offer by other transactions that go into the block. This levels the playing field between includers and the builder, giving the includer the opportunity to offer real inclusion guarantees to transactors. In FOCIL, the *protocol* offers real inclusion guarantees, *eventually*. In UPIL, the *includer* offers real inclusion guarantees, *immediately*. 

Some includers might charge transactors for their services in FOCIL, but the value of the provided services is further strengthened in UPIL. MEV might thus shift from the builder to includers in the form of fees for listing the transaction. A transaction listed by an IL has no need to pay a priority fee for inclusion. Indeed, we may even see &quot;IL-builders&quot; that collate full ILs as a service both in FOCIL and UPIL. Some MEV will also shift to the protocol in the form of burned ranking fees. It is natural to then consider what options the builder has, to retain some power over transaction inclusion. It may of course try to bribe includers to not list transactions. A problem for a builder trying to stay competitive is that this requires bribing all includers, and that any includer remaining faithful to its duties can earn a greater reward from transactors when others take the bribe, particularly in UPIL.

There are nuances to the design that need careful consideration before adoption. Something to be attentive to is the effect of burning the marginal ranking fee, given that avoiding the burn is not a zero-sum outcome for builders and includers. This is further discussed in the next section. 

### Alternative specifications for rewarding includers

Transactors might wish to reward includers in both FOCIL and UPIL for surfacing their transaction in an IL. They may recognize that the space in each IL is limited, meaning includers sometimes need to prioritize between available transactions. They might also fear that builders could bribe includers to not fulfill their duties, so that the builder can exclude unwanted transactions. As discussed previously, UPIL strengthens the position of includers, giving them in some sense equal power to the builder in deciding which transactions enter the block. For this reason, the case for rewarding includers is also stronger: an IL transaction does not require a priority fee to be included, even in full blocks—it must be included if it offers a higher ranking fee than competing transactions.

#### Out-of-protocol inclusion fees

If there is no in-protocol reward mechanism, individual staking service providers might start offering (trustfully) to list transactions in their next assigned IL slot, against a small fee. We might also see public orderflow of includable transactions offering a certain reward for inclusion, with includers and transactors coming to agreement via a third-party software. This can improve the UX, but also has the potential to become a centralization vector.

#### In-protocol inclusion fee sources

It is possible that the protocol can be of direct assistance. Three fee sources will first be reviewed, and relevant distribution mechanisms then explored.

**Includer fee:** One example is to allow transactions to specify an includer fee via a new field `max_includer_fee_per_gas`. To split the `max_includer_fee_per_gas` and the `max_priority_fee_per_gas` when they are capped by the `max_fee_per_gas`, the &quot;aggregate-cap-divide&quot; method outlined in the &quot;pay-as-you-bid&quot; subsection is the recommended approach. Alternatively, it is possible to distribute only the includer fee or the priority fee, depending on if the transaction was listed in an IL or not, and never both. The builder must then specify whether each transaction originated from an IL or not (at the transaction or IL level), and attesters vote against the block if the builder fails to make such an assignment when they observed the transaction in a timely IL.

**Priority fee:** It is possible to instead let the includers receive the priority fee if they list a transaction. The builder will have no choice but to include a transaction once it is listed by an includer, and the priority fee then serves little purpose. From the transactor&apos;s perspective, giving a priority fee to the builder for an IL transaction is a wasteful expenditure. Once again, with this option the builder must specify whether each transaction originated from an IL or not.

**Marginal ranking fee:** The marginal ranking fee can be distributed to includers instead of being burned. As discussed previously, one potential downside of this is the increase in rewards for engineering contention—in collaboration with builders—by first withholding transactions, and then releasing all transactions in the same block. 

The question is whether includers will be able to engineer such contention, given the coordination problem at hand: withholding transactions over several slots, with several slots&apos; includers working together, where anyone breaking the cartel could reap higher rewards from transactors paying includers for their services. Transactors might also end up setting lower ranking fees if such an approach becomes systematic, and most ranking fees will likely anyway be in the region of 12.5% of the base fee. Finally, we do not see builders coordinating to bring down the base fee in order to reap higher priority fees today (at the same time, the control over the priority fee is indirect, and they do not directly attain the base fee).

A potential benefit of distributing the marginal ranking fee to includers is that if the builder wishes to bribe includers to avoid contention (in order to bring up priority fees), then includers taking such a bribe would miss out on rewards for that contention (in addition to any rewards they may already miss out on from includer priority fees).

#### Mechanisms for distributing inclusion fees in-protocol

Four options for how to distribute the fee from any of the three in-protocol inclusion fee sources listed in the previous section will now be reviewed:

**(1) Keyed distribution:** Let transactors set one or several keys, with each key linking to one includer (i.e., validator ID) or to many includers (e.g., enabling all validators of an SSP to associate one key to all its validators). The protocol can then ensure that the rewards are distributed only to validators represented by a key, if it listed the transaction. This means that transactions shared with an includer privately still can use an in-protocol fee distribution without risking dilution. Options (2)-(4) below can be applied when the transactor does not provide a key or when the keyed includer(s) failed to list the transaction.

**(2) Individual distribution:** Split the fee between all includers listing a transaction. All includers then have an incentive to list a transaction, with the incentive being stronger if other includers have ignored it. It may however lead to unnecessary duplicate listings, since there is an incentive to list transactions even after they have been observed in another IL. It may also lead includers to integrate with builders to propagate the optimal IL by leveraging the builder&apos;s last look.

**(3) Seniority distribution:** Use a &quot;seniority waterfall&quot; rule. The transaction hash is combined with includer validator IDs to assign an order of seniority by which each includer has the right to the full includer fee. If a transaction&apos;s senior includer lists it, there is no purpose for a less senior includer to also list it. The idea is to promote a broader coverage while maintaining fairness. The mechanism will however not remove all duplicates, as a more senior includer will still list a transaction already listed by a less senior includer. It is straightforward to combine (1) with (3), by giving keyed includers the highest seniority, with remaining includers assigned a seniority based on the transaction hash. This could also prevent transaction hash grinding in the case when some senior includers are more reliable than others. Under the priority fee redistribution rule, the builder is in essence appended to the waterfall, having the lowest seniority.

To further reduce duplicates, a potential extension could allow includers to stagger their inclusion list so that they first broadcast transactions they are the most senior includer for, and then append the list with transactions they are less senior for or that arrive late. This can also increase the includer&apos;s expected value (EV) since an early broadcast increases margins and the late broadcast allows for better coverage. Another way to increase EV under this rule is to combine it with (4) below. Each partial list must have timeliness observed in isolation, and the rules for IL equivocation must be amended to allow append operations.

**(4) Collective distribution:** Distribute the includer fee collectively to all includers. There is then no need to keep track of who propagated which transaction in which IL. It also serves to promote independence of includers. Builders cannot help includers to extract a relatively higher proportion of the ranking fee by constructing an optimal IL for them from their last look. Includers are further encouraged to facilitate as broad coverage as possible, given that there are no incentives to propagate a (high-paying) transaction if one of the other includers already propagates it. This means that some includers can pivot to propagating their ILs early, while others observe and select late or missed transactions. 

A downside is that includers are not incentivized individually to do a good job, and gain individually only 1/`IL_COMMITTEE_SIZE` of any ranking fee of a transaction they uniquely include. The point however is that the collective distribution alters the meaning of &quot;doing a good job&quot;, aligning protocol design goals with includer incentives. 

Builders may try to bribe includers to not include transactions. If an includer will receive 1/`IL_COMMITTEE_SIZE` of any collective rewards for *not* including a transaction that eventually is not surfaced by any IL, then they may elect to leave it out to preserve space for other transactions. However, the builder would then also forego a sum corresponding to the entire collective rewards by paying out such bribes to the includers. In the setup where the priority fee is distributed to includers if they surface a transaction, the builder would thus need to forego the entire priority fee it stands to receive. 

However, due to the gradual construction of the aggregate IL, the builder can offer higher bribes than 1/`IL_COMMITTEE_SIZE` to the last remaining includers, to keep some transactions not yet included out of the IL aggregate. The last remaining includer that spots a late transaction might be able to choose between including it to receive 1/`IL_COMMITTEE_SIZE` of the priority fee, or to receive 1/2 of a conditional priority fee as a bribe to not include it.

### Alternative specifications for the auction and transaction format

#### Omit the new transaction format with its added ranking fee field 

Existing transaction formats are ranked using `max_fee_per_gas`. This may be sufficiently expressive, with the new transaction type omitted. The benefit is that it simplifies the UX. Transactors may not care about how much they have to pay to specifically cover the `marginal_ranking_fee_per_gas`—they have already specified how much they are willing to pay for inclusion in total with the `max_fee_per_gas`. It also simplifies the developer experience, since we do not need to change the transaction format.

A potential downside is that transactors cannot differentiate between how high contention fees they are willing to pay to cover the base fee and to cover the marginal ranking fee in full blocks. The builder has some control over the marginal ranking fee: if there are transactions outside of the ILs that are willing to pay a higher fee for inclusion than the IL transactions, then it may or may not elect to include those transactions. This influences the marginal ranking fee which is determined by the highest offered ranking fee of an excluded IL transaction. It is more difficult for the builder to control the base fee. Transactors wishing to limit their ranking fees, while at the same time giving ample room for the base fee to rise before inclusion, may therefore find that older transaction formats do not offer sufficient expressiveness.

#### Pay-as-you-bid auction

Two alternative pay-as-you-bid auction designs will now be highlighted. The first is that transactors always pay their offered ranking fee upon inclusion. In this case, there is no risk that the includers or the builder engineer contention for blockspace to drive up the price, and the full ranking fee is distributed to includers instead of being burned, using the collective method previously described. The post-execution check stays the same as in the main specification, with the only difference that the check on outranked IL transactions concerning the `marginal_ranking_fee_per_gas` (dashed line in the figure) is removed. 

Transaction processing is altered to, e.g., facilitate payment to includers. The split between the specified `max_ranking_fee_per_gas` and `max_priority_fee_per_gas` can be done in two ways. Either the ranking fee takes precedence over the priority fee as previously, or the two are given equal precedence. In the first case, the same strategy as in the main specification can be used. In the second case, the two fees can first be summed into a single `max_payout_fee_per_gas`, and the capped `payout_fee_per_gas` then distributed proportionally to the size of the original max ranking/priority fees.

Additionally, the builder is given the ability to set a `priority_fee_shift_per_gas` parameter for each transaction to allow transactions without a sufficient `ranking_fee_per_gas` to become eligible for inclusion in the block. We can envision a scenario where the builder otherwise integrates deeper with transactors to help them set the optimal ranking fee anyway. Such an integration could have detrimental effects on the builder competitive landscape, and it is therefore desirable to allow the builder—who has the last look when building blocks—to raise the ranking fee as it sees fit in a trustless manner. This means that many transactors will elect to just provide a priority fee, and that there is limited downside for transactors using older transaction types. 

If a transactor believes that the builder may leave their transactions out of the block, then it is still well served by providing a ranking fee and propagating the transaction publicly so that it can be surfaced by an IL. The builder needs to boost all transactions up to the ranking fee of the transaction it wishes to exclude from the block, and a modest ranking fee can therefore be sufficient to ensure inclusion. The spec shows the ranking fee taking precedence and omits some overflow checks:

```Python
for i, unnormalized_transaction in enumerate(transactions):
    ...
    # After this existing check...
    assert transaction.max_fee_per_gas &gt;= transaction.max_priority_fee_per_gas
    
    # ..Optionally shift a proportion of the priority fee over to the ranking fee
    assert block.priority_fee_shift_per_gas[i] &lt;= transaction.max_priority_fee_per_gas
    max_priority_fee_per_gas = transaction.max_priority_fee_per_gas - block.priority_fee_shift_per_gas[i]

    # ..then fill in order of: base fee, ranking fee, priority fee
    max_shifted_ranking_fee_per_gas = transaction.max_ranking_fee_per_gas + block.priority_fee_shift_per_gas[i]
    ranking_fee_per_gas = min(max_shifted_ranking_fee_per_gas, transaction.max_fee_per_gas - block.base_fee_per_gas)
    inclusion_fee_per_gas = block.base_fee_per_gas + ranking_fee_per_gas
    priority_fee_per_gas = min(max_priority_fee_per_gas, transaction.max_fee_per_gas - inclusion_fee_per_gas)
    effective_gas_price = inclusion_fee_per_gas + priority_fee_per_gas

    ...
    # ..after refunding the transactor as normal, the includer fee is computed
    includer_fee = gas_used * ranking_fee_per_gas // IL_COMMITTEE_SIZE
    # ..balances of the `IL_COMMITTEE_SIZE` includers increased
    for j in range(IL_COMMITTEE_SIZE):
        self.account(block.includer(j)).balance += includer_fee
    # ..and the priority fee is distributed to the builder just as in EIP-1559
    self.account(block.author).balance += gas_used * priority_fee_per_gas
```

The consensus layer (CL) constructs a list of execution-layer (EL) payout addresses for the slot, ordered by IL committee index, and provides it to the EL via a new engine API call: `engine_setIncluderPayoutsV1`. For committee members with `0x00` credentials, the CL inserts the zero address `0x000...`, thus burning these rewards.

#### Pay-as-you-bid auction using only priority fee

A second alternative is to let the priority fee act as a ranking fee in a pay-as-you-bid auction. The priority fee is distributed collectively to includers if it was surfaced by at least one inclusion list. Otherwise it is distributed to the builder. *Only* priority fees distributed to the includers count towards the transaction&apos;s ranking. 

The builder specifies whether an included transaction was surfaced by an IL via a bitfield `IL_transaction` in the payload body, of equal length to the number of transactions. For all transactions where `IL_transaction[i]=FALSE`, the attesters check that they are not in any observed timely ILs, and otherwise return `INCLUSION_LIST_UNSATISFIED`. For these transactions, the builder can also apply the `priority_fee_shift_per_gas` described in the previous subsection, which however here is the same for all transactions since none have an initial ranking fee. Under [EIP-1559](/EIPs/EIPS/eip-1559), transaction processing is changed as follows:

```Python
...
for i, unnormalized_transaction in enumerate(transactions):
  ...
    # Processing begins after this existing line
    signer.balance += gas_refund * effective_gas_price

    # Redistribute priority fee
    if block.IL_transaction[i]==TRUE:
        ranking_fee_per_gas = priority_fee_per_gas
        priority_fee_per_gas = 0
    else:
        assert block.priority_fee_shift_per_gas &lt;= priority_fee_per_gas
        ranking_fee_per_gas = block.priority_fee_shift_per_gas
        priority_fee_per_gas -= block.priority_fee_shift_per_gas
    
    # The fee given to each includer (small division remainder burned)
    includer_fee = gas_used * ranking_fee_per_gas // IL_COMMITTEE_SIZE
    # Increase the balances of the `IL_COMMITTEE_SIZE` includers 
    for j in range(IL_COMMITTEE_SIZE):
        self.account(block.includer(j)).balance += includer_fee
    
    # Proposer receives the priority fee
    self.account(block.author).balance += gas_used * priority_fee_per_gas
```

Payout to includers uses the same CL construction as in the previous subsection and the check on the `marginal_ranking_fee_per_gas` (dashed line in the figure) is once again removed.

If the ranking was based on the priority fee paid to the builder, the builder could offer kickbacks, allowing transactors to achieve a high ranking for free. To prevent this, the ranking portion of the fee must be distributed to a wider set of validators or be burned. Any arbitrary fee split between the builder and includers when `IL_transaction[i]=FALSE` would likely prove suboptimal and encourage off-chain agreements and builder–includer integration to circumvent the intended mechanism.

#### Allow builder to shift priority fee under UPIL

The `priority_fee_shift_per_gas` could be used also in the main UPIL specification. The primary rationale is that transactions using older formats then also can be included when `marginal_ranking_fee_per_gas&gt;0`, by having the builder reallocate the priority fee. Another option is to simply charge all base fees and ranking fees jointly for all transactions at the end of the block, as previously discussed.

#### UPIL batch auctions

A more extensive modification of the protocol is to make use of the improved CR and pricing of intra-block contention to eliminate the slack in the block, targeting 100% of the gas limit to facilitate scaling. The base fee can in such an implementation either be removed entirely, or the price information obtained via the marginal ranking fee can be relied upon for appropriate increases to the base fee.

## Backwards Compatibility

Transactions using the [EIP-1559](/EIPs/EIPS/eip-1559) or [EIP-4844](/EIPs/EIPS/eip-4844) transaction formats can with this change spend up to their entire `max_fee_per_gas` to cover the `marginal_ranking_fee_per_gas` in blocks with high contention. Previously, the `max_fee_per_gas` could only be consumed by the `base_fee_per_gas` (which grows slowly each block) or the `priority_fee_per_gas` (which can be explicitly capped). A user setting `max_fee_per_gas` to twice the current `base_fee_per_gas`, while using a negligible `priority_fee_per_gas`, may be surprised to see the entire `max_fee_per_gas` consumed directly in the next block. However, this also implies that contention was high, and that they may have needed to spend the entire `max_fee_per_gas` for inclusion a few blocks later anyway. Importantly, the total fee paid will never exceed the `max_fee_per_gas` the user originally authorized.

## Security Considerations

This EIP does not allow the builder to control which transactions that go into the block, with implications on CR and MEV. To retain full control over the block&apos;s content, the builder would have to bribe includers to not surface unwanted transactions. A concern then is that the builder bribes includers to not surface transactions, such that it can build the most profitable block, by excluding unwanted transactions. However, even if all includers were to be willing to forgo their duty to uphold CR if there is a profit to be made, the profit from surfacing transactions in the IL against a fee would reasonably be higher than whatever bribe a competitive builder is able to pay; especially if some includers have already taken the bribe, making remaining IL space more valuable. The option otherwise remains to distribute the marginal ranking fee to includers.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 16 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8046</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8046</guid>
      </item>
    
      <item>
        <title>Onchain Metadata for Token Registries</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8048-onchain-metadata-for-multi-token-and-nft-registries/25820</comments>
        
        <description>## Abstract

This ERC defines an onchain metadata standard for multi-token and NFT registries including [ERC-721](/EIPs/EIPS/eip-721), [ERC-1155](/EIPs/EIPS/eip-1155), and [ERC-6909](/EIPs/EIPS/eip-6909). The standard provides a key-value store allowing for arbitrary bytes to be stored onchain.

## Motivation

This ERC addresses the need for fully onchain metadata while maintaining compatibility with existing [ERC-721](/EIPs/EIPS/eip-721), [ERC-1155](/EIPs/EIPS/eip-1155), and [ERC-6909](/EIPs/EIPS/eip-6909) standards. It has been a long-felt need for developers to store metadata onchain for NFTs and other multitoken contracts; however, there has been no uniform standard way to do this. Some projects have used the `tokenURI` field to store metadata onchain using Data URLs, which introduces gas inefficiencies and has other downstream effects (for example making storage proofs more complex). This standard provides a uniform way to store metadata onchain, and is backwards compatible with existing [ERC-721](/EIPs/EIPS/eip-721), [ERC-1155](/EIPs/EIPS/eip-1155), and [ERC-6909](/EIPs/EIPS/eip-6909) standards.

## Specification

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

### Scope

This ERC is an optional extension that MAY be implemented by any [ERC-721](/EIPs/EIPS/eip-721), [ERC-1155](/EIPs/EIPS/eip-1155), or [ERC-6909](/EIPs/EIPS/eip-6909) compliant registries.

### Required Metadata Function and Event

Contracts implementing this ERC MUST implement the following interface:

```solidity
interface IOnchainMetadata {
    /// @notice Get metadata value for a key.
    function metadata(uint256 tokenId, string calldata key) external view returns (bytes memory);
    
    /// @notice Emitted when metadata is set for a token.
    event MetadataSet(uint256 indexed tokenId, string indexed indexedKey, string key, bytes value);
}
```

- `metadata(tokenId, key)`: Returns the metadata value for the given token ID and key as bytes

Contracts implementing this ERC MAY also expose a `setMetadata(uint256 tokenId, string calldata key, bytes calldata value)` function to allow metadata updates, with write policy determined by the contract.

Contracts implementing this ERC MUST emit the following event when metadata is set:

```solidity
event MetadataSet(uint256 indexed tokenId, string indexed indexedKey, string key, bytes value);
```
### Interface ID

The interface ID is `0xdf670be1`.

### Key/Value Pairs

This ERC specifies that the key is a string type and the value is bytes type. This provides flexibility for storing any type of data while maintaining an intuitive string-based key interface.

### Optional Key Parameters

Keys MAY include parameters to represent variations or instances of a metadata type, such as `&quot;registration/1&quot;` or `&quot;name/Maria&quot;`; see [ERC-8119](/EIPs/EIPS/eip-8119) for the standard parameterized key format.

### Optional Diamond Storage

Contracts implementing this ERC MAY use Diamond Storage pattern for predictable storage locations. If implemented, contracts MUST use the namespace ID `&quot;erc8048.onchain.metadata.storage&quot;`.

The Diamond Storage pattern provides predictable storage locations for data, which is useful for cross-chain applications using inclusion proofs. For more details on Diamond Storage, see [ERC-8042](/EIPs/EIPS/eip-8042).

### Examples

It is possible to use this standard to tokenize an agent as an NFT: each token ID is the agent, and `metadata` holds agent fields as UTF-8 in `bytes`.

#### Example: AI agent metadata (NFT as agent)

Two key patterns:

- **`context`** — one key. UTF-8 Markdown is enough for humans and models; issuers MAY also embed a JSON code block so clients can parse token lists, policy URIs, or version fields without a second key.
- **`endpoint[&lt;type&gt;]`** — one URL per protocol; `&lt;type&gt;` is lowercase (`mcp`, `a2a`, `ag-ui`, …).

Example for `tokenId == 1`: store the UTF-8 encoding of a Markdown document like the following as the `bytes` value for `&quot;context&quot;` (shown as a file; not a Solidity literal):

~~~~markdown
I am an agent that can swap tokens on Ethereum mainnet. I maintain an official token list and only suggest swaps where both assets appear on that list.

```json
{
  &quot;tokenListUri&quot;: &quot;ipfs://QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG/tokenlist.json&quot;,
  &quot;network&quot;: &quot;mainnet&quot;,
  &quot;defaultSlippageBps&quot;: 50
}
```
~~~~

Endpoint keys for the same token:

- `&quot;endpoint[mcp]&quot;` → `bytes(&quot;https://agents.example.com/mcp/1&quot;)`
- `&quot;endpoint[a2a]&quot;` → `bytes(&quot;https://agents.example.com/a2a/1&quot;)`
- `&quot;endpoint[ag-ui]&quot;` → `bytes(&quot;https://agents.example.com/ui/1&quot;)`

#### Example: Biometric Identity for Proof of Personhood

A biometric identity system using open source hardware to create universal proof of personhood tokens.

- Key: `&quot;biometric_hash&quot;` → Value: `bytes(bytes32(identity_commitment))`
- Key: `&quot;verification_time&quot;` → Value: `bytes(bytes32(timestamp))`
- Key: `&quot;device_proof&quot;` → Value: `bytes(bytes32(device_attestation))`

### Optional Metadata Hooks

Contracts implementing this ERC MAY use metadata hooks to redirect record resolution to a different contract for secure resolution from known contracts, such as singleton registries with verifiable security properties.

For the full specification of metadata hooks, see [ERC-8121](/EIPs/EIPS/eip-8121) (Metadata Hooks). Hooks are encoded in the metadata value itself and allow clients to **jump** to another contract to resolve the metadata value. When using hooks for token metadata with this ERC, the return type MUST be `bytes` and the hook encoding MUST be `bytes`.

## Rationale

This design prioritizes simplicity and flexibility by using a string-key, bytes-value store that provides an intuitive interface for any type of metadata. The minimal interface with a single `metadata` function provides all necessary functionality while remaining backwards compatible with existing [ERC-721](/EIPs/EIPS/eip-721), [ERC-1155](/EIPs/EIPS/eip-1155), and [ERC-6909](/EIPs/EIPS/eip-6909) standards. The optional `setMetadata` function enables flexible access control for metadata updates. The required `MetadataSet` event provides transparent audit trails with indexed tokenId and indexed key for efficient filtering. This makes the standard suitable for diverse use cases including AI agents, proof of personhood systems, and custom metadata storage.

## Backwards Compatibility

- Fully compatible with [ERC-721](/EIPs/EIPS/eip-721), [ERC-1155](/EIPs/EIPS/eip-1155), and [ERC-6909](/EIPs/EIPS/eip-6909).
- Non-supporting clients can ignore the scheme.

## Reference Implementation

The interface is defined in the Required Metadata Function and Event section above. Here are reference implementations:

### Basic Implementation

```solidity
pragma solidity ^0.8.25;

import &quot;./IOnchainMetadata.sol&quot;;

contract OnchainMetadataExample is IOnchainMetadata {
    // Mapping from tokenId =&gt; key =&gt; value
    mapping(uint256 =&gt; mapping(string =&gt; bytes)) private _metadata;
    
    /// @notice Get metadata value for a key
    function metadata(uint256 tokenId, string calldata key) 
        external view override returns (bytes memory) {
        return _metadata[tokenId][key];
    }
    
    /// @notice Set metadata for a token (optional implementation)
    function setMetadata(uint256 tokenId, string calldata key, bytes calldata value) 
        external {
        _metadata[tokenId][key] = value;
        emit MetadataSet(tokenId, key, key, value);
    }
}
```

### Diamond Storage Implementation

```solidity
pragma solidity ^0.8.20;

import &quot;./IOnchainMetadata.sol&quot;;

contract OnchainMetadataDiamondExample is IOnchainMetadata {
    struct OnchainMetadataStorage {
        mapping(uint256 tokenId =&gt; mapping(string key =&gt; bytes value)) metadata;
    }

    // keccak256(&quot;erc8048.onchain.metadata.storage&quot;)
    bytes32 private constant ONCHAIN_METADATA_STORAGE_LOCATION =
        keccak256(&quot;erc8048.onchain.metadata.storage&quot;);

    function _getOnchainMetadataStorage() private pure returns (OnchainMetadataStorage storage $) {
        bytes32 location = ONCHAIN_METADATA_STORAGE_LOCATION;
        assembly {
            $.slot := location
        }
    }

    function metadata(uint256 tokenId, string calldata key) 
        external view override returns (bytes memory) {
        OnchainMetadataStorage storage $ = _getOnchainMetadataStorage();
        return $.metadata[tokenId][key];
    }
    
    function setMetadata(uint256 tokenId, string calldata key, bytes calldata value) 
        external {
        OnchainMetadataStorage storage $ = _getOnchainMetadataStorage();
        $.metadata[tokenId][key] = value;
        emit MetadataSet(tokenId, key, key, value);
    }
}
```

Implementations should follow the standard [ERC-721](/EIPs/EIPS/eip-721), [ERC-1155](/EIPs/EIPS/eip-1155), or [ERC-6909](/EIPs/EIPS/eip-6909) patterns while adding the required metadata function and event.

## Security Considerations

This ERC is designed to put metadata onchain, providing security benefits through onchain storage.

Implementations that choose to use the optional Diamond Storage pattern should consider the security considerations of [ERC-8042](/EIPs/EIPS/eip-8042). 

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 30 Sep 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8048</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8048</guid>
      </item>
    
      <item>
        <title>Contract-Level Onchain Metadata</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8049-contract-level-metadata-with-diamond-storage/25819</comments>
        
        <description>## Abstract

This ERC defines a standard for storing contract-level metadata onchain. It extends [ERC-7572](/EIPs/EIPS/eip-7572)&apos;s contract-level metadata concept by providing onchain storage. Contracts MAY optionally use [ERC-8042](/EIPs/EIPS/eip-8042)&apos;s Diamond Storage pattern for predictable storage locations, enabling cross-chain compatibility and supporting upgradable contracts.

## Motivation

Contract metadata today typically relies on offchain storage such as URLs or IPFS, creating trust and availability risks—servers go down, domains expire, and malicious actors can modify data without onchain record. Storing metadata onchain makes contract identity censorship-resistant and enables wallets and block explorers to display verifiable information without trusting external services. 

## Specification

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

### Required Metadata Function and Event

Contracts implementing this ERC MUST implement the following interface:

```solidity
interface IERC8049 {
    /// @notice Get contract metadata value for a key.
    function contractMetadata(string calldata key) external view returns (bytes memory);
    
    /// @notice Emitted when contract metadata is updated.
    event ContractMetadataUpdated(string indexed indexedKey, string key, bytes value);
}
```

Contracts implementing this ERC MAY also expose a `setContractMetadata(string calldata key, bytes calldata value)` function to allow metadata updates, with write policy determined by the contract.

Contracts implementing this ERC MUST emit the following event when metadata is set:

```solidity
event ContractMetadataUpdated(string indexed indexedKey, string key, bytes value);
```

### Interface ID

The interface ID is `0x8ec3f882`.

### Key/Value Pairs

This ERC specifies that the key is a string type and the value is bytes type. This provides flexibility for storing any type of data while maintaining an intuitive string-based key interface.

### Optional Key Parameters

Keys MAY include parameters to represent variations or instances of a metadata type, such as `&quot;registration: 1&quot;` or `&quot;name: Maria&quot;`; see [ERC-8119](/EIPs/EIPS/eip-8119): Key Parameters.

### Optional Diamond Storage

Contracts implementing this ERC MAY use Diamond Storage pattern for predictable storage locations. If implemented, contracts MUST use the namespace ID `&quot;erc8049.contract.metadata.storage&quot;`.

The Diamond Storage pattern provides predictable storage locations for data, which is useful for cross-chain applications using inclusion proofs and for upgradable contracts. For more details on Diamond Storage, see [ERC-8042](/EIPs/EIPS/eip-8042).

### Value Interpretation

If no standard is specified for a metadata value, clients MAY assume the value is a UTF-8 encoded string (bytes(string)) unless otherwise specified by the implementing contract or protocol.

### Examples

#### Example: Basic Contract Information

A contract can store basic information about itself:

- Key: `&quot;name&quot;` → Value: `bytes(&quot;MyToken&quot;)`
- Key: `&quot;description&quot;` → Value: `bytes(&quot;A decentralized exchange&quot;)`
- Key: `&quot;collaborators&quot;` → Value: `bytes(abi.encodePacked(address1, address2, address3))`

#### Example: ENS Name for Contract

A contract can specify its ENS name using this standard:

- Key: `&quot;ens_name&quot;` → Value: `bytes(&quot;mycontract.eth&quot;)`

This allows clients to discover the contract&apos;s ENS name and resolve it to get additional information about the contract.

### Optional Metadata Hooks

Contracts implementing this ERC MAY use hooks to redirect metadata resolution to a different contract. For the full specification, see [ERC-8121](/EIPs/EIPS/eip-8121). When using hooks with contract metadata, the target function MUST be `contractMetadata(string)` returning `bytes`. The hook selector is `0x9e574b14`.

## Rationale

This design prioritizes simplicity and flexibility by using a string-key, bytes-value store that provides an intuitive interface for any type of contract metadata. The minimal interface with a single `contractMetadata` function provides all necessary functionality. The optional `setContractMetadata` function enables flexible access control for metadata updates. The required `ContractMetadataUpdated` event provides transparent audit trails with indexed key for efficient filtering. Contracts that need predictable storage locations can optionally use Diamond Storage pattern. This makes the standard suitable for diverse use cases including contract identification, collaboration tracking, and custom metadata storage.

## Backwards Compatibility

- Fully compatible with existing smart contracts.
- Non-supporting clients can ignore the scheme.

## Reference Implementation

The interface is defined in the Required Metadata Function and Event section above. Here are reference implementations:

### Basic Implementation

```solidity
pragma solidity ^0.8.25;

import &quot;./IERC8049.sol&quot;;

contract BasicContractMetadata is IERC8049 {
    // Simple mapping for contract-level metadata
    mapping(string key =&gt; bytes value) private _metadata;

    function contractMetadata(string calldata key) external view override returns (bytes memory) {
        return _metadata[key];
    }

    function setContractMetadata(string calldata key, bytes calldata value) external {
        _metadata[key] = value;
        emit ContractMetadataUpdated(key, key, value);
    }
}
```

### Diamond Storage Implementation

```solidity
pragma solidity ^0.8.25;

import &quot;./IERC8049.sol&quot;;

contract DiamondContractMetadata is IERC8049 {
    struct ContractMetadataStorage {
        mapping(string key =&gt; bytes value) metadata;
    }

    // keccak256(&quot;erc8049.contract.metadata.storage&quot;)
    bytes32 private constant CONTRACT_METADATA_STORAGE_LOCATION =
        keccak256(&quot;erc8049.contract.metadata.storage&quot;);

    function _contractMetadataStorage() private pure returns (ContractMetadataStorage storage $) {
        bytes32 location = CONTRACT_METADATA_STORAGE_LOCATION;
        assembly {
            $.slot := location
        }
    }

    function contractMetadata(string calldata key) external view override returns (bytes memory) {
        ContractMetadataStorage storage $ = _contractMetadataStorage();
        return $.metadata[key];
    }

    function setContractMetadata(string calldata key, bytes calldata value) external {
        ContractMetadataStorage storage $ = _contractMetadataStorage();
        $.metadata[key] = value;
        emit ContractMetadataUpdated(key, key, value);
    }
}
```

## Security Considerations

This ERC is designed to put metadata onchain, providing security benefits through onchain storage.

Implementations that choose to use the optional Diamond Storage pattern should consider the security considerations of [ERC-8042](/EIPs/EIPS/eip-8042).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 10 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8049</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8049</guid>
      </item>
    
      <item>
        <title>Precompile for ML-DSA signature verification</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8051-ml-dsa-verification/25857</comments>
        
        <description>## Abstract

This proposal adds precompiled contracts that perform signature verifications using the NIST module-lattice signature scheme. Two instantiations are supported:

* **ML-DSA** — NIST-compliant version using SHAKE256 (FIPS-204),
* **ML-DSA-ETH** — EVM-optimized version for cheaper on-chain verification:
    * Uses Keccak-based PRNG instead of SHAKE256 (leverages native KECCAK256 precompile)
    * Stores public-key polynomial `t1` in the NTT domain to skip one NTT during verification (convertible to regular encoding offline)

Two precompile contracts are specified:

* `VERIFY_MLDSA` — verifies a ML-DSA signature compliant to FIPS-204.
* `VERIFY_MLDSA_ETH` — verifies a ML-DSA-ETH signature replacing SHAKE256 with a more efficient hash function, deviating from FIPS-204.

## Motivation

Quantum computers pose a long-term risk to classical cryptographic algorithms. In particular, signature algorithms based on the hardness of the Elliptic Curve Discrete Logarithm Problem (ECDLP) such as secp256k1, are widely used in Ethereum and threatened by quantum algorithms. This exposes potentially on-chain assets and critical infrastructure to quantum adversaries.

Integrating post-quantum signature schemes is crucial to future-proof Ethereum and other EVM-based environments. It shall be noted that infrastructure for post-quantum signatures should be deployed before quantum adversaries are known to be practical because it takes on the order of years for existing applications to integrate.

Dilithium, a lattice-based scheme standardized by NIST as FIPS-204, offers high security against both classical and quantum adversaries. As the main winner of the standardization, the scheme has been selected as the main alternative to elliptic curve signature algorithms, making it a serious option for Ethereum.

While the signature size (2.4kB) and public key size (1.3kB) are larger than other post-quantum candidates such as Falcon FN-DSA, this scheme is more flexible in terms of parameters. It is thus possible to derive a zero-knowledge version of Dilithium, keeping the security of the scheme together with an efficient in-circuit verification. This EIP does not dig into the details of this instance.

ML-DSA has a simpler signer algorithm than FN-DSA, making hardware implementation easier.
Finally, ML-DSA is based on the same mathematical construction as Kyber, the Post-Quantum Key Exchange algorithm standardized by NIST as FIPS-203.
All these properties make ML-DSA well-suited for blockchain applications.

In the context of the Ethereum Virtual Machine, a precompile for Keccak256 hash function is already available, making ML-DSA verification much faster when instantiated with an extendable output function derived from Keccak than with SHAKE256, as specified in NIST submission. This EIP specifies two versions of ML-DSA enabling two important features: one version being fully compliant with the NIST specification, the other deviating in encodings to reduce the gas cost.

## Specification

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

The following specification provides two precompiled contracts:

|**Precompiled contract**|**1**|**2**|
|-|-|-|
|**Name**|`VERIFY_MLDSA`|`VERIFY_MLDSA_ETH`|
|**Address**| 0x12| 0x13|
|**Gas cost**|  4500| 4500|

While ML-DSA can be instantiated for three security levels: NIST level II, III and IV, this EIP only covers NIST level II, corresponding to 128 bits of security.

For the two variants of ML-DSA of this EIP, the following parameters are fixed:

* Polynomial degree: `n = 256`,
* Field modulus: `q = 8380417`,
* Matrix dimensions: `k=4`, `l=4`,
* Bounds of rejection: `γ_1 = 2¹⁷`, `γ_2 = (q-1)/88`, `β = 78`,
* Additional parameters: `η = 2`, `τ = 39`, `d = 13`.

These parameters strictly follow NIST. More precisely, `q`, `n`, `k`, `l` and `η` are chosen in order to ensure a hard MLWE related problem, and the remaining parameters are chosen for the hardness of MSIS as well as for the efficiency of the scheme. The parameter `β = τ * η = 78` is the norm bound used in the rejection condition `||z||_∞ &lt; γ_1 - β` for the ML-DSA-44 parameter set in FIPS-204.

In terms of storage, ML-DSA public key can be derived by the verifier, making the overall public key of 1312 bytes. However, this increases the verifier cost, making the on-chain verification too expensive from a practical point of view. In this EIP, the verification algorithm takes the public key in raw format, meaning that the storage for the public key is:

* The full matrix `A_hat` of 16 384 bytes,
* `tr` is stored in order to save one hash, with 32 bytes,
* `t1` is stored in the NTT domain in order to save one NTT, with 4096 bytes.

The overall storage for the **public key** is **20512 bytes**. The signature follows the same format as specified in FIPS-204: 32 bytes for `c_tilde`, 2304 bytes for the coefficients of `z`, and 84 bytes for `h`. In total, a **signature** requires **2420 bytes**.

### Sub-algorithms of ML-DSA

#### Number Theoretic Transform

Polynomial arithmetic is computed efficiently using Number Theoretic Transform (NTT). Efficient polynomial multiplication can be implemented following the draft NTT EIP. NTT inverse cost is roughly the same as an NTT: $n\log(n)$ additions and $n/2 \log(n)$ multiplications over the field $\mathbb F_q$, where $q=8380417$ and $n=256$.

#### EXtendable Output Function

The verification algorithm requires an eXtendable Output Function (XOF) made from a hash function.
This EIP provides two instantiations of a XOF:

* SHAKE256 is the XOF provided in NIST submission, a sponge construction derived from SHA256. Extracting bytes using SHAKE256 calls the `Keccak_f` permutation as described in Section 3.7 of FIPS-204. While this construction is standardized, it is expensive when computed in the Ethereum Virtual Machine because `Keccak_f` has no EVM opcode.
* Keccak-PRNG is a XOF that is build from a counter-mode PRNG based on Keccak256. Generating new chunks of bytes requires an incrementing counter, as described in NIST SP800-90A revision 1. This XOF has the same interface as SHAKE256, but requires a `flip()` function that initiate a counter to `0`. Then, the `squeeze` function outputs as many bytes as needed using a counter mode as specified in SP800-90A revision 1. A precompile of `Keccak256` is available in the Ethereum Virtual Machine, making this XOF very efficient in the EVM.

#### Hints in ML-DSA

ML-DSA requires some hint computation. More precisely, the function `use_hint` must be implemented following Algorithm 40 of FIPS-204. The output hint is a polynomial with coefficients in {0,1}. Another function `sum_hint` is required, and counts the number of non-zero values of the hint.

#### Sample In Ball Challenge

In ML-DSA, a challenge is computed using a XOF.
This algorithm `sample_in_ball` outputs a polynomial with τ small coefficients (in {-1,1}).
The values of the coefficients as well as the position in the coefficients list is obtained using the XOF, as specified in Algorithm 29 of FIPS-204.

### ML-DSA verification algorithm

Verifying a ML-DSA signature follows Algorithm 8 of FIPS-204, with `A_hat` of the public key stored in expanded format, and `t1` stored in the NTT domain.

```python
def VERIFY_MLDSA(public_key, message, signature) -&gt; bool:
    A_hat, tr, t1 are decoded from public_key
    c_tilde, z, h are decoded from signature
    if h is not properly encoded, return False

    μ = shake_256(tr+message).extract(64)
    c = sample_in_ball(c_tilde, τ)
    # computed in the NTT domain
    # three NTTs for c and z, and t1
    # one final inverse NTT.
    Az_minus_ct1 = A_hat * z - c * (2^d * t1)

    w_prime = h.use_hint(Az_minus_ct1, 2*γ_2)

    return check_norm_bound(z, γ_1 - β) and c_tilde == shake_256(μ + w_prime).extract(32)
```

### ML-DSA-ETH verification algorithm

The verification of ML-DSA-ETH signatures follows the same algorithm with another hash function, with two differences:

* `t1` from the public key is stored in the NTT domain in order to save one NTT. The multiplication by `2^d` is also precomputed. Note that this change can be seen as a change of representation.
* A variant of `sample_in_ball` is defined using KeccakPRNG. The only difference from Algorithm 29 of FIPS-204 is that it requires a `flip()` between lines 3 and 4 so that it initializes the counter to `0` before starting squeezing. Note that this can be implemented in `absorb()` and `squeeze()` so that the same interface can be used as in SHAKE256.

```python
def VERIFY_MLDSA_ETH(public_key, message, signature) -&gt; bool:
    A_hat, tr, t1 are decoded from public_key
    c_tilde, z, h are decoded from signature
    if h is not properly encoded, return False

    μ = keccak_prng(tr+message).extract(64)
    c = sample_in_ball_keccak_prng(c_tilde, τ)
    # computed in the NTT domain
    # two NTTs for c and z
    # one final inverse NTT.
    Az_minus_ct1 = A_hat * z - c * t1

    w_prime = h.use_hint(Az_minus_ct1, 2*γ_2)

    return check_norm_bound(z, γ_1 - β) and c_tilde == keccak_prng(μ + w_prime).extract(32)
```

### Required checks in ML-DSA(-ETH) verification

* The hint `h` needs to be properly encoded. The malformation of the hint is specified in Algorithm 21 of FIPS-204.
* The element `z` must have a norm satisfying `||z||_∞ &lt; γ_1 - β`. The norm `||.||_∞` is defined page 6 of FIPS-204.
* The final hash output must be equal to the signature bytes `c_tilde`.

### Precompiled contract specification

### ML-DSA precompiled contract

The precompiled contract VERIFY_MLDSA is proposed with the following input and outputs, which are big-endian values:

* **Input data**
    * 32 bytes for the message
    * 2420 bytes for ML-DSA signature
    * 20512 bytes for the ML-DSA expanded public key
* **Output data**:
    * If the algorithm process succeeds, it returns 1 in 32 bytes format.
    * If the algorithm process fails, it returns 0 in 32 bytes format.

#### Error Cases

* Insufficient gas has been provided.
* Invalid input length (not compliant to described input)
* Invalid field element encoding (≥ q)
* Invalid norm  bound
* Invalid hint check
* Signature verification failure

### ML-DSA-ETH precompiled contract

The precompiled contract VERIFY_MLDSA_ETH is proposed with the following input and outputs, which are big-endian values:

* **Input data**
    * 32 bytes for the message
    * 2420 bytes for ML-DSA-ETH signature
    * 20512 bytes for the ML-DSA-ETH expanded public key
* **Output data**:
    * If the algorithm process succeeds, it returns 1 in 32 bytes format.
    * If the algorithm process fails, it returns 0 in 32 bytes format.

#### Error Cases

* Insufficient gas has been provided.
* Invalid input length (not compliant to described input)
* Invalid field element encoding (≥ q)
* Invalid norm  bound
* Invalid hint check
* Signature verification failure

### Precompiled contract gas usage

The cost of the **VERIFY_MLDSA** and **VERIFY_MLDSA_ETH** functions is dominated by the call to the NTTs, and the required hash calls for sampling in the ball (and for μ and the final check).
It represents in average 5 calls to the hash function. Taking linearly the cost of keccak256, and avoiding the context switching it represents 4500 gas.

### Compliance with EIP-7932

In compliance with [EIP-7932](/EIPs/EIPS/eip-7932),  the necessary parameters and structure for its integration are provided. `ALG_TYPE = 0xD1`  uniquely identifies ML-DSA transactions, set MAX_SIZE = 2441 bytes to accommodate the fixed-length signature_info container, and recommend a `GAS_PENALTY` of approximately `3000` gas subject to benchmarking. The verification function follows the [EIP-7932](/EIPs/EIPS/eip-7932) model, parsing the signature_info, recovering the corresponding Dilithium public key, verifying the signature against the transaction payload hash, and deriving the signer&apos;s Ethereum address as the last 20 bytes of keccak256(pubkey). This definition ensures that ML-DSA can be cleanly adopted within the `AlgorithmicTransaction` container specified by [EIP-7932](/EIPs/EIPS/eip-7932).

```python
signature_info = Container[
    # 0xD1 for ML-DSA (NIST-compliant version),
    # 0xD2 for ML-DSA-ETH (EVM-friendly version),
    version: uint8
    # ML-DSA signature
    signature: ByteVector[2420]
    # keccak256(pubkey)[12:]
    pubkey_hash: ByteVector[20]
]
```

In the format of EIP-7932:

* For the NIST-compliant version:

```python
verify(signature_info: bytes, payload_hash: Hash32) -&gt; Bytes:
    assert len(signature_info) == 2441
    version      = signature_info[0]
    signature    = signature_info[1:2421]
    pubkey_hash  = signature_info[2421:2441]
    assert version == 0xD1
    pubkey = lookup_pubkey(pubkey_hash)
    assert VERIFY_MLDSA(pubkey, payload_hash, signature)
    return pubkey
```

* For the EVM-friendly version:

```python
verify(signature_info: bytes, payload_hash: Hash32) -&gt; Bytes:
    assert len(signature_info) == 2441
    version      = signature_info[0]
    signature    = signature_info[1:2421]
    pubkey_hash  = signature_info[2421:2441]
    assert version == 0xD2
    pubkey = lookup_pubkey(pubkey_hash)
    assert VERIFY_MLDSA_ETH(pubkey, payload_hash, signature)
    return pubkey
```

## Rationale

The ML-DSA scheme was selected as a NIST-standardized post-quantum cryptographic algorithm due to its strong security guarantees and efficiency.

ML-DSA is a signature algorithm build from lattice-based cryptography. Specifically, its hardness relies on the Short Integer Solution (SIS) problem and the Learning With Errors (LWE) problem, which is believed to be hard for both classical and quantum computers.

ML-DSA (based on CRYSTALS-Dilithium) offers a strong balance between security, efficiency, and practicality compared to classical ECC and other post-quantum schemes. Its signature and key sizes remain reasonably small, making it practical for real-world deployments such as Ethereum blockchain. As the main winner of the NIST PQC standardization process, it benefits from a broad community consensus on its security, which is not yet the case for many alternatives. Moreover, its lattice-based structure allows flexible parameter tuning, making it easier to adapt for specialized contexts like zero-knowledge proofs. Schemes like Falcon (FN-DSA, another signature scheme built on top of lattice-based assumptions) have a more rigid parameterization, making zero-knowledge circuits larger, and thus proof computation more expensive.

Given the increasing urgency of transitioning to quantum-resistant cryptographic primitives or even having them ready in the event that research into quantum computers speeds up.

## Backwards Compatibility

No backward compatibility issues found.

## Test Cases

A set of test vectors for verifying implementations is located in a separate file (see explanations in [this file](/EIPs/assets/eip-8051/)):

* The file [`mldsa_nist.rsp`](/EIPs/assets/eip-8051/mldsa_nist.rsp) containing the NIST submission KAT file for security level II.
* The file [`mldsa_evm.rsp`](/EIPs/assets/eip-8051/mldsa_evm.rsp) containing test vectors for the EVM-friendly version with the same format as NIST.


## Reference Implementation

The reference implementation is the NIST submission code for ML-DSA. A reference implementation is provided by ZKNOX for the EVM-friendly version ML-DSA-ETH.

## Security Considerations

The derivation path to obtain the private key from the seed is (tbd).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 15 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8051</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8051</guid>
      </item>
    
      <item>
        <title>Precompile for Falcon support</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8052-precompile-for-falcon-support/25860</comments>
        
        <description>## Abstract

This proposal creates a precompiled contract that performs signature verifications using the Falcon-512 signature scheme by given parameters of the message hash, signature, and public key. This allows any EVM chain -- principally Ethereum roll-ups -- to integrate this precompiled contract easily.

The signature scheme can be instantiated in two version:

* Falcon, the standard signature scheme, fully compliant with the algorithm recommended by the NIST,
* An EVM-friendly version where the hash function is efficiently computed in the Ethereum Virtual Machine.

Three precompiled contracts are specified (formerly called `ETH_HASH_TO_POINT` / `HASH_TO_POINT_ETH` in drafts):

* `FALCON_HASH_TO_POINT_SHAKE256` — NIST-compliant Hash-to-Point using SHAKE256.
* `FALCON_HASH_TO_POINT_KECCAKPRNG` — EVM-friendly Hash-to-Point using a Keccak-based XOF/PRNG.
* `FALCON_CORE` — the core algorithm of Falcon, that verifies the signature from the obtained (HashToPoint) challenge.


## Motivation

Quantum computers pose a long-term risk to classical cryptographic algorithms. In particular, signature algorithms based on the hardness of the Elliptic Curve Discrete Logarithm Problem (ECDLP) such as secp256k1, are widely used in Ethereum and threaten by quantum algorithms. This exposes potentially on-chain assets and critical infrastructure to quantum adversaries.

Integrating post-quantum signature schemes is crucial to future-proof Ethereum and other EVM-based environments. It shall be noted that infrastructure for post-quantum signatures should be deployed *before* quantum adversaries are known to be practical because it takes on the order of years for existing applications to integrate.

Falcon, a lattice-based scheme standardized by NIST, offers high security against both classical and quantum adversaries. Its compact signature size (666 bytes for Falcon-512) and its efficient verification algorithm make it well-suited for blockchain applications, where gas usage and transaction throughput are critical considerations.
&lt;!-- When the public key is also stored together with the signature, it leads to 666 + 896 = 1562 bytes.
Using the recovery mode, it can be reduced to 1292 + 32 = 1324 bytes. --&gt;
&lt;!--
For Falcon,
    σ=666 (40 bytes of salt, ~626 bytes for s2)
    pk = 896,
    TOTAL=1562
For FalconRec,
    σ=1292 (40 bytes of salt, ~626 bytes for s1, ~626 bytes for s2),
    pk = 32,
    TOTAL=1324
--&gt;

In the context of the Ethereum Virtual Machine, a precompile for Keccak256 hash function is already available, making Falcon verification much faster when instantiated with an extendable output function derived from Keccak than with SHAKE256, as specified in NIST submission. This EIP specifies a split of the signature verification into two sub procedures:

* `FALCON_HASH_TO_POINT_SHAKE256` or `FALCON_HASH_TO_POINT_KECCAKPRNG`, instantiated with a different extendable Output Function: the first with SHAKE256 (as recommended by NIST), the second with Keccak-PRNG (a version that is more efficient when computed in the EVM). In the future, it is possible to define it for SNARK/STARK circuits. An appropriated hash function choice reduces drastically the circuit size and the proving time in the context of ZK applications.
* `FALCON_CORE`, that does not require any hash computation. This sub-algorithm follows the NIST recommendation so that:
    * using the SHAKE256 `FALCON_HASH_TO_POINT_SHAKE256`, the signature is fully compliant with the NIST standard,
    * using the KeccakPRNG `FALCON_HASH_TO_POINT_KECCAKPRNG`, the verification can be efficient even in the EVM.

Using this separation, two important features are provided: one version being fully compliant with the NIST specification, the other deviating from the standard in order to reduce the gas cost, and opening up to possible computations of Falcon signature ZK proofs.

## Specification

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

Falcon can be instantiated with polynomials of degree $512$ or $1024$, leading to a different security level.  Falcon-512 is chosen, leading to a security level equivalent to RSA2048.
This setting leads to the following size for signatures and keys:

| Parameter | Falcon |
| -------- | -------- | 
| **n** (lattice dimension)     | `512`     |
| **q** (modulus)     | `12289`     | 
| Padded signature size      | `666` bytes     | 
| Public Key size     | `896` bytes     |
| Private key size     | `1281` bytes     | 


From a high level, a signature verification can be decomposed in two steps:

* The **challenge computation**, that involves the message and the salt, and computes a challenge polynomial using a XOF (instantiated with SHAKE256 and a Keccak-base PRNG here),
* The **core algorithm**, that compute polynomial arithmetic (with the challenge, the public key and the signature), and finally verify the shortness of the full signature $(s_1,s_2)$.

The following pseudo-code highlights how these two algorithms are involved in a Falcon verification, and how the modularity of the challenge computation opens up to two version of Falcon:

```python
def falcon512_verify(message: bytes, signature: bytes, pubkey: bytes) -&gt; bool:
    &quot;&quot;&quot;
    Verify a Falcon Signature following NIST standard
    Args:
        message (bytes): The message to sign.
        signature (666 bytes): The signature containing 40 bytes of salt and 626 bytes of compressed signature.
        pubkey (bytes): The Falcon public key.
    Returns:
        bool: True if the signature is valid, False otherwise.
    &quot;&quot;&quot;

    # 1. Compute the Hash To Point Challenge (see 3.1.)
    challenge = HASH_TO_POINT(message, signature)

    # 2. Verify Falcon Core Algorithm (see 3.2.)
    return FALCON_CORE(signature, pubkey, challenge)
```

```python
def ethfalcon512_verify(message: bytes, signature: bytes, pubkey: bytes) -&gt; bool:
    &quot;&quot;&quot;
    Verify a Falcon Signature (EVM-friendly mode)
    Args:
        message (bytes): The message to sign.
        signature (666 bytes): The signature containing 40 bytes of salt and 626 bytes of compressed signature.
        pubkey (bytes): The Falcon public key.
    Returns:
        bool: True if the signature is valid, False otherwise.
    &quot;&quot;&quot;

    # 1. Compute the Hash To Point Challenge (see 3.1.)
    challenge = ETH_HASH_TO_POINT(message, signature)

    # 2. Verify Falcon Core Algorithm (see 3.2.)
    return FALCON_CORE(signature, pubkey, challenge)
```

The functions `falcon512_verify` and `ethfalcon512_verify` call the precompiles specified in the next sections: `FALCON_HASH_TO_POINT_SHAKE256`, `FALCON_HASH_TO_POINT_KECCAKPRNG` and `FALCON_CORE`.


### Hash-to-Point challenge (normative)

1. **Parse Input Data:** Check the byte sizes and then extract the message and the signature. The parsed signature is a tuple of values $(r, s_2)$. $r$ is denoted as the salt and contains bytes, and $s_2$ is denoted as the signature vector, a vector of elements mod $q$.
2. **Verify Well-formedness:** Verify that the signature contains a 40-byte salt $r$.
&lt;!-- See the `Required Checks in Verification` section for more details. --&gt;
3. **Compute the challenge $c$:** the challenge is obtained from hash-to-point on the salt $r$ of the signature and the message. The output $c$ is a polynomial of degree 512, stored in 896 bytes.
The hash-to-point function computes extendable Output from a hash Function (XOF). This EIP provides two instantiations of a XOF:
    * SHAKE256 is the XOF provided in NIST submission, a sponge construction derived from SHA256. Extracting bytes using SHAKE256 calls the `Keccak_f` permutation:

        ```python
        def SHAKE256_init():
            create an empty sponge state

        def SHAKE256_inject(data):
            absorb into Keccak sponge state

        def SHAKE256_flip():
            pad input and finalize sponge
            (no fixed-length digest yet)

        def SHAKE256_extract(state, length):
            output = []
            while output.size &lt; length:
                block = Keccak_f(state) # apply permutation
                output.append(state_part) # take r-bit &quot;rate&quot; portion
            return first &apos;length&apos; bytes of output
        ```

        While this construction is standardized, it is expensive when computed in the Ethereum Virtual Machine because `Keccak_f` has no EVM opcode.
    * Keccak-PRNG is a XOF that is build from a counter-mode PRNG based on Keccak256. Generating new chunks of bytes requires an incrementing counter.

        ```python
        def KeccakPRNG_init():
            create an empty buffer

        def KeccakPRNG_inject(data):
            buffer.append(data)

        def KeccakPRNG_flip():
            state = Keccak256(buffer) # fixed 32-byte state
            counter = 0

        def KeccakPRNG_extract(state, length):
            output = []
            counter = 0
            while output.size &lt; length:
                block = Keccak256(state || counter)
                output.append(block)
                counter = counter + 1
            return first &apos;length&apos; bytes of output
        ```

        Precompile of `Keccak256` are available in the Ethereum Virtual Machine, making this XOF very efficient in the EVM.

Using one of the XOFs above (SHAKE256 or Keccak-PRNG), it is possible to instantiate two (precompiles) algorithms for hashing into points:

```python
def FALCON_HASH_TO_POINT_SHAKE256(message: bytes32, signature: bytes) -&gt; bool:
    &quot;&quot;&quot;
    Compute the Hash To Point Falcon Challenge.
    Args:
        message (bytes32): The original message (hash).
        signature (666 bytes): containing:
            - r (40 bytes): The salt.
            - s (626 bytes): The compressed signature vector.
    Returns:
        c: The Hash To Point polynomial challenge as a vector.
    &quot;&quot;&quot;

    # Constants
    q = 12289  # Falcon modulus

    # Step 1: Parse Input Data
    r, s2_compressed = signature[:40], signature[40:]  # Extract salt and compressed signature vector

    # Step 2: Verify Well-formedness
    if not is_valid_signature_format(s2_compressed, pubkey):
        return False

    # Step 3: Compute the challenge vector HashToPoint(r || message)
    c = [0 for i in range(n)]
    SHAKE256_init()
    SHAKE256_inject(r+message)
    i = 0
    while i &lt; n do
        t = SHAKE256_extract(2)
        if t &lt; 61445 then
            c[i] = t mod q
            i = i + 1
    return c
```

```python
def FALCON_HASH_TO_POINT_KECCAKPRNG(message: bytes32, signature: bytes) -&gt; bool:
    &quot;&quot;&quot;
    Compute the Hash To Point Falcon Challenge using Keccak-PRNG.
    Args:
        message (bytes32): The original message (hash).
        signature (666 bytes): containing:
            - r (40 bytes): The salt.
            - s (626 bytes): The compressed signature vector.
    Returns:
        c: The Hash To Point polynomial challenge as a vector.
    &quot;&quot;&quot;

    # Constants
    q = 12289  # Falcon modulus

    # Step 1: Parse Input Data
    r, s2_compressed = signature[:40], signature[40:]  # Extract salt and compressed signature vector

    # Step 2: Verify Well-formedness
    if not is_valid_signature_format(s2_compressed, pubkey):
        return False

    # Step 3: Compute the challenge vector HashToPoint(r || message)
    c = [0 for i in range(n)]
    KeccakPRNG_init()
    KeccakPRNG_inject(r+message)
    i = 0
    while i &lt; n do
        t = KeccakPRNG_extract(2)
        if t &lt; 61445 then
            c[i] = t mod q
            i = i + 1
    return c
```

#### Encoding of the challenge polynomial `c` (896 bytes, normative)

* Domain: degree-512 polynomial with coefficients in `[0, q)`, `q = 12289`.
* Order: coefficients are serialized in index order `c[0], c[1], …, c[511]`.
* Bit-packing: each coefficient is a 14-bit **big-endian** unsigned integer. Concatenate all 512 encodings into a bitstring of exactly **896 bytes**. Consumers MUST reject encodings that are not exactly 896 bytes.

### Core algorithm

1. **Parse Input Data:** Check the byte sizes and then extract the public key, the Hash To Point Challenge and the signature.
    * The parsed public key  $h$, interpreted as a vector of elements mod $q$,
    * The parsed signature  $(r, s_2)$. $r$ is denoted as the salt and $s_2$ is denoted as the signature vector, made of elements mod $q$.
2. **Verify Well-formedness:** Verify that the signature, Hash To Point Challenge and public key have the correct number of elements and is canonical.
&lt;!-- See the `Required Checks in Verification` section for more details. --&gt;
3. **Compute $s_1$ from $s_2$ and $h$.** $s_1 = c - h * s_2$ where:
    * $c$ is the Hash To Point challenge,
    * $h$ is the public key, represented in the ntt domain
    * $s_2$ is the signature vector.

    &gt; Note: since $h$ and $s_2$ are polynomials, the operation $*$ is the polynomial multiplication and can be sped up using the Number Theoretic Transform (NTT).
4. **Check $L^2$ norm Bound:** Verify that the signature is *short* by checking the following equation:
    $$ ||(s_1, s_2) ||_2^2 &lt; \lfloor\beta^2\rfloor$$
    where $\beta^2$ is the acceptance bound. For Falcon-512, it is $\lfloor\beta^2\rfloor = 34034726$.


The following code illustrates Falcon core algorithm:

```python
def FALCON_CORE(signature: bytes, h: bytes, challenge: bytes) -&gt; bool:
    &quot;&quot;&quot;
    Verify Falcon Core Algorithm
    Args:
        - signature (666 bytes): containing:
            - r (40 bytes): The salt.
            - s (626 bytes): The compressed signature vector.
        - h (bytes): The Falcon public key in the ntt domain, computed as h=ntt(pubkey) externally.
        - challenge (bytes): The Falcon Hash To Point Challenge.
    Returns:
        bool: True if the signature is valid, False otherwise.
    &quot;&quot;&quot;

    # Constants
    q = 12289  # Falcon modulus
    ACCEPTANCE_BOUND = 34034726  # Falcon-512 acceptance bound

    # Step 1: Parse Input Data
    r, s2_compressed = signature[:40], signature[40:]  # Extract salt and compressed signature vector

    # Step 2: Verify Well-formedness
    if not is_valid_signature_format(s2_compressed, pubkey):
        return False

    # Step 3: Decompress Signature Vector
    s2 = decompress(s2_compressed)  # Convert compressed signature to full form
    if s2 is None: # Reject invalid encodings 
        return False

    # Step 4: Convert to Evaluation domain (NTT)
    s2_ntt = ntt(s2)

    # Step 5: Compute the Verification Equation
    tmp_ntt = hadamard_product(s2_ntt, h)  # Element-wise product
    tmp = intt(tmp_ntt) # Convert back to coefficient form (INTT)
    s1 = challenge - tmp

    # Step 6: Normalize s1 coefficients to be in the range [-q/2, q/2]
    s1 = normalize_coefficients(s1, q)

    # Step 7: Compute Norm Bound Check
    s1_squared = square_each_element(s1)
    s2_squared = square_each_element(s2)

    total_norm = sum(s1_squared) + sum(s2_squared)

    # Step 8: Compare with Acceptance Bound
    # To ensure signature is short
    return total_norm &lt; ACCEPTANCE_BOUND  # Falcon-512: β² = 34,034,726
```

### Required Checks in Falcon Verification

The following requirements MUST be checked by the precompiled contract to verify signature components are valid:

**Raw Input data**

* Verify that the message is 32-bytes long,
* Verify that the public key is 896-bytes long,
* Verify that the signature is 666-bytes long.

**Parsed Input data**

* Verify that the public key consists of 512 elements, where each element is between $[0, q-1]$,
* Verify that the signature vector in the signature consists of 512 elements, where each element is between $[0, q-1]$,
* Verify that the salt in the signature is 40-bytes long.

**Gas burning on error**
if one of the above condition is not met then all the gas supplied along with a CALL or STATICCALL is burned.
it shall also be burned if an error happens during decompression (incorrect encodings).


### Precompiled Contract Specification

The precompiled contracts are proposed with the following input and outputs, which are big-endian values:

#### `FALCON_HASH_TO_POINT_SHAKE256`

**Input**

* 32 bytes: message hash `m`,
* 666 bytes: salt `r` (40 bytes), Falcon-512 compressed signature `s2_compressed` (626 bytes) concatenated: `r || s2_compressed`.

**Output**

* 896 bytes: packed challenge polynomial `c` (see §3.1 encoding)

#### `FALCON_HASH_TO_POINT_KECCAKPRNG`

Same I/O as §4.1, but the XOF is Keccak-PRNG. The construction is normative and MUST define: state initialization, domain-separation (if any), counter width and endianness, and block concatenation order.

#### `FALCON_CORE`

* **Input data**
    * 666 bytes for Falcon-512 signature
    * 896 bytes for Falcon-512 public key
    * 896 bytes for the Hash To Point Challenge
* **Output data**:
    * If the core algorithm process succeeds, it returns 1 in 32 bytes format.
    * If the core algorithm process fails, it does not return any output data.

#### Error Cases

* Invalid input length (not compliant to described input)
* Invalid field element encoding (≥ q)
* Invalid signature decompression

Note that a well-formed but invalid signature does not produce an error, but `FALCON_CORE` invalidates the signature (and it does not return any output data).

#### Precompiled Contract Gas Usage

The cost of the **FALCON_HASH_TO_POINT_SHAKE256** and **FALCON_HASH_TO_POINT_KECCAKPRNG** is set to 1000 gas.

The cost of **FALCON_CORE** is set to 2000 gas.

Thus, the total cost of the signature is 3000 gas.

## Rationale

The Falcon signature scheme was selected as a NIST-standardized post-quantum cryptographic algorithm due to its strong security guarantees and efficiency.

Falcon is a signature algorithm build from lattice-based cryptography. Specifically, its hardness relies on the Short Integer Solution (SIS) problem over NTRU lattices, which is believed to be hard for both classical and quantum computers. 

Falcon offers several advantages over traditional cryptographic signatures such as secp256k1 and secp256r1:

* **Efficiency**: Falcon is highly optimized for constrained environments, offering small signature sizes (666 bytes for Falcon-512) and fast verification time. This makes it well-suited for Ethereum, where gas costs and computational efficiency are critical factors.
* **NIST Standardization**: Falcon was selected as part of NIST Post-Quantum Cryptography Standardization process, ensuring that it meets rigorous security and performance criteria.
* **Enabling Future-Proof Smart Contracts**: With the integration of Falcon, Ethereum roll-ups and smart contract applications can start adopting quantum-secure schemes that remain secure even when we have quantum computers.
* **Compatibility with Existing EVM Designs**: While Falcon operates on fundamentally different cryptographic assumptions than elliptic curves, its verification process can be efficiently implemented as a precompiled contract with similar APIs to classical signature schemes like secp256r1.

Given the increasing urgency of transitioning to quantum-resistant cryptographic primitives or even having them ready in the event that research into quantum computers speeds up. 

### Gas cost explanations


The cost of the **HASH_TO_POINT** and **HASH_TO_POINT_ETH** functions is dominated by the call to the underlying hash function. It represents in average 35 calls to the hash function. Taking linearly the cost of keccak256, and avoiding the context switching it represents 1000 gas.

The cost of **FALCON_CORE** function is dominated by performing 2 NTTs and 1 inverse NTT. One of these NTTs is for the public key and can be precomputed so that the contract requires to perform only 1 NTT and 1 inverse NTT. An estimation of the cost is given by 2000 gas.

The cost is interpolated using rule of thumb from SUPERCOPS signatures benchmark results.

## Backwards Compatibility

In compliance with [EIP-7932](/EIPs/EIPS/eip-7932),  the necessary parameters and structure for its integration are provided. `ALG_TYPE = 0xFA`  uniquely identifies Falcon-512 transactions, set MAX_SIZE = 667 bytes to accommodate the fixed-length signature_info container (comprising a 1-byte version tag and a 666-byte Falcon signature), and recommend a `GAS_PENALTY` of approximately `3000` gas subject to benchmarking. The verification function follows the EIP-7932 model, parsing the signature_info, recovering the corresponding Falcon public key, verifying the signature against the transaction payload hash, and deriving the signer&apos;s Ethereum address as the last 20 bytes of keccak256(pubkey). This definition ensures that Falcon-512 can be cleanly adopted within the `AlgorithmicTransaction` container specified by EIP-7932.

As per [EIP-7932](/EIPs/EIPS/eip-7932), this EIP defines two Falcon algorithm types:

* `ALG_TYPE = 0xFA` — Falcon-512 with SHAKE256 H2P
* `ALG_TYPE = 0xFB` — Falcon-512 with Keccak-PRNG H2P

**Container and sizes.** The `signature_info` container omits any pubkey hash; the public key is recovered by `verify(...)` and the 7932 sig-recover precompile derives the address as `keccak(ALG_TYPE || pubkey)[12:]`. Therefore:

* `MAX_SIZE = 667` bytes (1-byte `ALG_TYPE` + 666-byte Falcon compressed signature).

```python
signature_info = Container[
    # 0xFA Falcon-512 (SHAKE H2P), 0xFB Falcon-512 (Keccak H2P)
    version: uint8,
    # Falcon-512 signature (compressed). If an implementation produces a shorter form, it MUST be left-padded to 666 bytes.
    signature: ByteVector[666]
]
```

In the format of [EIP-7932](/EIPs/EIPS/eip-7932):

* For the NIST-compliant version:

    ```python
    verify(signature_info: bytes, payload_hash: Hash32) -&gt; ExecutionAddress:
        assert len(signature_info) == 699
        version      = signature_info[0]
        signature    = signature_info[1:667]
        assert version == 0xFA
        pubkey = lookup_pubkey(pubkey_hash)
        assert falcon512_verify(pubkey, signature, payload_hash)
        return ExecutionAddress(keccak256(pubkey)[12:])
    ```

* For the EVM-friendly version:

    ```python
    verify(signature_info: bytes, payload_hash: Hash32) -&gt; ExecutionAddress:
        assert len(signature_info) == 699
        version      = signature_info[0]
        signature    = signature_info[1:667]
        assert version == 0xFB
        pubkey = lookup_pubkey(pubkey_hash)
        assert ethfalcon512_verify(pubkey, signature, payload_hash)
        return ExecutionAddress(keccak256(pubkey)[12:])
    ```

### Addresses

&lt;!-- TODO: backward compatibility --&gt;
**TBD by ACD.** Final precompile addresses will be selected within the EIP-managed range of [EIP-1352](/EIPs/EIPS/eip-1352), explicitly **avoiding `0x0100–0x01FF` reserved for RIPs** by [EIP-7587](/EIPs/EIPS/eip-7587).

## Test Cases

A set of test vectors for verifying implementations is located in a separate file (to be provided for each opcode). For the NIST compliant version, KATs are reproduced for HashToPoint (with a provided salt `r`) as well as for the compressed signature vector s2 (with a provided `HashToPoint` input). Note that `s2` is not padded with zeroes, leading to a maximum size of 626 bytes.


## Reference Implementation

An implementation is provided by the NIST. An implementation of the EVM-friendly version ETHFALCON is provided by ZKNOX.

**TODO: We can modify geth to include falcon-512 as a reference. (Similar to secp256r1 signature verification)**

## Security Considerations

The derivation path to obtain the private key from the seed is (tbd). Hash-to-Point functions MUST follow the specified XOFs byte-for-byte; domain separation and padding are normative.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 17 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8052</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8052</guid>
      </item>
    
      <item>
        <title>Milli-gas for High-precision Gas Metering</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8053-milli-gas-counter-for-high-precision-gas-metering/25946</comments>
        
        <description>## Abstract

This proposal introduces the `milli-gas` counter as the EVM&apos;s internal gas accounting. Gas costs are defined in `milli_gas` and internal EVM gas accounting is entirely carried out in `milli_gas`. At the end of transaction execution, `milli_gas` is rounded up to `gas`. Gas limits and transaction fees are still computed and verified using the current `gas_used` counter. This new counter enables a more precise accounting of cheap compute without impacting UX.

## Motivation

Currently, most EVM compute operations (`ADD`, `SUB`, `MUL`, etc.) are significantly underpriced when compared with state operations (`SSTORE`, `SLOAD`, `CREATE`, etc.). There are two factors contributing to this mismatch. On one hand, client optimizations and hardware improvements have made pure compute operations more efficient. On the other hand, with the growing size of the Ethereum state, the performance of I/O operations touching this larger state has been deteriorating. Both of these trends are expected to continue, further worsening this mismatch.

There are a couple of proposals to reduce the cost of compute operations ([EIP-7904](/EIPs/EIPS/eip-7904)) and increase the cost of state operations ([EIP-8032](/EIPs/EIPS/eip-8032), [EIP-8037](/EIPs/EIPS/eip-8037), and [EIP-8038](/EIPs/EIPS/eip-8038)). However, given the current level of mismatch between these operations, there is an inherent trade-off in the anchor we use to reprice these operations.

If we make compute operations cheaper, we will introduce rounding errors, with most compute operations costing 1, when they should cost a fraction of that. These rounding errors impact scalability because we can now fit fewer of these cheaper operations in any given block. However, if we price all operations so that the fastest opcode is assigned 1 gas, we would need to make all other operations significantly more expensive, including both compute and state operations. Making everything more expensive would require a rebase on the concept of gas units to users, thus impacting UX.

To illustrate this point, let&apos;s focus on the pure compute operations. As compute operations impact only block execution time, the chosen anchor will induce a specific million gas per second rate on all compute opcodes. For instance, if we anchor on `EcRecover` at the current price (3000 gas units), this induces a rate of 175Mgas/s, based on the execution time estimated for this opcode on [EIP-7904&apos;s empirical analysis](/EIPs/assets/eip-7904/gas-cost-estimator-report.pdf). The following plot shows the average rounding errors of compute operations for different anchors, using the same execution time estimates from EIP-7904.

![round_error_by_anchor](/EIPs/assets/eip-8053/round_error_by_anchor.png)

As we can see, with an anchor of 50Mgas/s (which would result in a gas limit of 100Mgas, assuming a 2-second block execution limit), we would get an average rounding error of 59.3%. This means that we could be 59.3% cheaper on average per opcode if we didn&apos;t have to round to integer gas units. Only after a 400Mgas/s anchor do we get to reasonably low rounding errors. However, this level of Mgas/s would require a major rebase of the gas model, where all opcodes become significantly more expensive, and both the transaction-level and block-level gas limits increase by a factor of 100.

The way around this trade-off is to allow cheap opcodes to have fractional gas costs, thus avoiding both the scalability limits introduced by rounding errors and the significant UX change of increasing gas costs and limits 100x.

A similar argument was made in [EIP-2045](/EIPs/EIPS/eip-2045), which served as inspiration to this proposal.

## Specification

This proposal introduces a new `Uint` counter to the EVM, `milli_gas_left`. Gas costs are defined in `milli_gas` and internal EVM gas accounting is entirely carried out in `milli_gas`.

Transaction fees, transaction gas limits, and block gas limits are still computed and verified using the current `gas_used` counter. There are no changes to blob gas accounting, refunds, or call data gas accounting.

### EVM environment

The current `gas_left` variable from the internal state of the EVM is replaced by `milli_gas_left`:

```python
@dataclass
class Evm:
    &quot;&quot;&quot;The internal state of the virtual machine.&quot;&quot;&quot;
    pc: Uint
    stack: List[U256]
    memory: bytearray
    code: Bytes
    milli_gas_left: Uint
    valid_jump_destinations: Set[Uint]
    logs: Tuple[Log, ...]
    refund_counter: int
    running: bool
    message: Message
    output: Bytes
    accounts_to_delete: Set[Address]
    return_data: Bytes
    error: Optional[EthereumException]
    accessed_addresses: Set[Address]
    accessed_storage_keys: Set[Tuple[Address, Bytes32]]
```

All references to `evm.gas_left` are replaced by `evm.milli_gas_left`.

### End-of-transaction conversion

At the end of each transaction execution, the gas left in the transaction output is updated to

```python
tx_output.gas_left = ceil(evm.milli_gas_left / 1000)
```

At the same time, after the transaction is executed, `evm.milli_gas_used` is rounded up to `evm.gas_used = ceil(evm.milli_gas_used / 1000)`.

### Opcode costs

Opcode gas parameters as defined in the [Ethereum Execution Client Specifications](https://github.com/ethereum/execution-specs/blob/abd7612d2f4d6fcd9f628330f38884b300f0d89f/src/ethereum/forks/osaka/vm/gas.py) that are not updated at the same time or after the introduction of this proposal, are increased by 1000x:

`GAS_PARAM = GAS_PARAM * 1000`

### `GAS` opcode

The `GAS` opcode reports the available gas in `milli-gas` units.

### `*CALL` opcodes

`*CALL` opcodes receive the amount of gas to send to the sub context to execute in `gas`. `gas` is converted to `milli-gas` at the start of the call&apos;s execution:

```python
# STACK
gas = Uint(pop(evm.stack)) * 1000
```

## Rationale

### New counter vs. new variable type

A possible approach to allow for fractional gas would be to change the variable type of all gas-related variables from an integer to a float or a base fractional. Although simple in concept, the implementation of such a change in the EVM is not trivial. In addition, introducing fractional variables would make moving to a zkEVM significantly more complex.

Thus, introducing a new counter is the option that least disrupts the current EVM implementation, while allowing for expressive gas costs.

### Rounding at transaction-level

With the introduction of a new counter, there are two levels at which we could convert `milli_gas` to `gas`: at the transaction level or the block level. Conversion at the block level results in the fewest rounding errors in block utilization. However, it requires a bigger change to implement, as `milli_gas` will need to be used when computing transaction fees and limits, and `milli_gas` will need to be incorporated in the block environment.

The question is whether a conversion at the transaction level is sufficient to reduce rounding errors. To estimate this, we extracted the opcode counts per transaction for 1000 mainnet blocks and computed the new gas prices of all compute operations assuming an anchor of 50Mgas/s and the estimated execution times from [EIP-7904&apos;s empirical analysis](/EIPs/assets/eip-7904/gas-cost-estimator-report.pdf). With this repricing, the fastest opcode (`JUMPDEST`) would be priced at 90 milli-gas units (i.e., 0.09 gas units). We also assumed that the non-compute operations and precompiles would have the same price, and we excluded any other transaction costs, such as intrinsic costs and calldata.

Then, we computed the rounding error of each transaction, assuming a conversion at both the transaction and opcode levels. The opcode-level conversion is equivalent to not using fractional gas and rounding all opcodes to an integer. The following plot shows the distribution for both errors. The x-axis is on a logarithmic scale.

![round_error_by_anchor](/EIPs/assets/eip-8053/round_err_tx.png)

In this sample of 1000 blocks, a transaction-level conversion has already successfully reduced the rounding errors from an average of 4% to 0.05% per transaction.

## Backwards Compatibility

This is a backwards incompatible gas repricing that requires a scheduled network upgrade.

Deployed bytecode that compares `gas_left` to constants or that uses explicit gas-limited calls will suddenly forward 1000× less gas, causing unexpected reverts or logic flip. Further analysis on how widespread this behavior is required.

## Security Considerations

&lt;-- TODO --&gt;

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 17 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8053</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8053</guid>
      </item>
    
      <item>
        <title>Scaled UI Amount Extension for ERC-20 Tokens</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8056-scaled-ui-amount-extension-for-erc-20-tokens/25899</comments>
        
        <description>## Abstract

This EIP proposes a standard extension to [ERC-20](/EIPs/EIPS/eip-20) tokens that enables issuers to apply an updatable multiplier to the UI (user interface) amount of tokens. This allows for efficient representation of stock splits, without requiring actual token minting or transfers. The extension provides a cosmetic layer that modifies how token balances are displayed to users while maintaining the underlying token economics.

## Motivation

Current ERC-20 implementations lack an efficient mechanism to handle real-world asset scenarios such as stock splits: When a company performs a 2-for-1 stock split, all shareholders should see their holdings double. Currently, this requires minting new tokens to all holders, which is gas-intensive and operationally complex. Moreover, the internal accounting in DeFi protocols would break from such a split.

The inability to efficiently handle this scenario limits the adoption of tokenized real-world assets (RWAs) on Ethereum. This EIP addresses these limitations by introducing a multiplier mechanism that adjusts the displayed balance without altering the actual token supply.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

### Core Interface

Compliant contracts MUST implement the `IScaledUIAmount` interface:

```solidity
interface IScaledUIAmount {
    // Emitted when the UI multiplier is updated
    event UIMultiplierUpdated(uint256 oldMultiplier, uint256 newMultiplier, uint256 effectiveAtTimestamp);

    // OPTIONAL: Emitted during a token transfer with the UI-adjusted amount
    event TransferWithUIAmount(address indexed from, address indexed to, uint256 amount, uint256 uiAmount);

    // Returns the current UI multiplier
    // Multiplier is represented with 18 decimals (1e18 = 1.0)
    function uiMultiplier() external view returns (uint256);
}
```

Note: How the multiplier is updated is an implementation detail left to the token issuer. The reference implementation below shows one approach using a `setUIMultiplier` function with delayed effectiveness.

### Optional Extension: Conversion

Contracts MAY implement the `IScaledUIAmountConversion` extension for on-chain conversion helpers:

```solidity
interface IScaledUIAmountConversion {
    // Converts a raw token amount to UI amount
    function toUIAmount(uint256 rawAmount) external view returns (uint256);

    // Converts a UI amount to raw token amount
    function fromUIAmount(uint256 uiAmount) external view returns (uint256);
}
```

### Optional Extension: Balances

Contracts MAY implement the `IScaledUIAmountBalances` extension for on-chain UI balance queries:

```solidity
interface IScaledUIAmountBalances {
    // Returns the UI-adjusted balance of an account
    function balanceOfUI(address account) external view returns (uint256);

    // Returns the UI-adjusted total supply
    function totalSupplyUI() external view returns (uint256);
}
```

### Required Extension: Pending Multiplier

Compliant contracts MUST implement the `IScaledUIAmountNewUIMultiplier` extension to expose a pending UI multiplier that has been scheduled but has not yet taken effect:

```solidity
interface IScaledUIAmountNewUIMultiplier {
    // Returns the pending UI multiplier scheduled to take effect at effectiveAt
    // Multiplier is represented with 18 decimals (1e18 = 1.0)
    function newUIMultiplier() external view returns (uint256);

    // Returns the timestamp at which the pending multiplier becomes effective
    function effectiveAt() external view returns (uint256);
}
```

### Interface Detection

Compliant contracts MUST implement [ERC-165](/EIPs/EIPS/eip-165) and return `true` when queried for the `IScaledUIAmount` interface ID.

Contracts implementing optional extensions MUST also return `true` for their respective interface IDs.

The interface identifiers are:

- `IScaledUIAmount`: `0xa60bf13d`
- `IScaledUIAmountNewUIMultiplier`: `0xTBD`
- `IScaledUIAmountConversion`: `0xTBD`
- `IScaledUIAmountBalances`: `0xd890fd71`

### Implementation Requirements:

1. ERC-165 Support: Compliant contracts MUST implement [ERC-165](/EIPs/EIPS/eip-165) interface detection.

2. Multiplier Precision: The UI multiplier MUST use 18 decimal places for precision (1e18 represents a multiplier of 1.0).

3. Backwards Compatibility: The standard ERC-20 functions (balanceOf, transfer, transferFrom, etc.) MUST continue to work with raw amounts.

4. Event Emission: The UIMultiplierUpdated event MUST be emitted whenever the multiplier is changed.

### Reference Implementation

The following implementation includes the core interface and all optional extensions:

```solidity
contract ScaledUIToken is
    ERC20,
    ERC165,
    IScaledUIAmount,
    IScaledUIAmountConversion,
    IScaledUIAmountBalances,
    IScaledUIAmountNewUIMultiplier,
    Ownable
{
    uint256 private constant MULTIPLIER_DECIMALS = 1e18;
    uint256 private _uiMultiplier = MULTIPLIER_DECIMALS; // Initially 1.0
    uint256 private _newUIMultiplier = MULTIPLIER_DECIMALS;
    uint256 private _effectiveAt = 0;

    constructor(string memory name, string memory symbol) ERC20(name, symbol) {}

    // ERC-165 interface detection
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return
            interfaceId == type(IScaledUIAmount).interfaceId ||
            interfaceId == type(IScaledUIAmountConversion).interfaceId ||
            interfaceId == type(IScaledUIAmountBalances).interfaceId ||
            interfaceId == type(IScaledUIAmountNewUIMultiplier).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    // ============ Core Interface ============

    function uiMultiplier() public view override returns (uint256) {
        uint256 currentTime = block.timestamp;
        if (currentTime &gt;= _effectiveAt) {
            return _newUIMultiplier;
        } else {
            return _uiMultiplier;
        }
    }

    // ============ Pending Multiplier Interface ============

    function newUIMultiplier() public view override returns (uint256) {
        return _newUIMultiplier;
    }

    function effectiveAt() public view override returns (uint256) {
        return _effectiveAt;
    }

    // Implementation-specific: How the multiplier is updated
    function setUIMultiplier(uint256 newMultiplier, uint256 effectiveAtTimestamp) external onlyOwner {
        require(newMultiplier &gt; 0, &quot;Multiplier must be positive&quot;);

        uint256 currentTime = block.timestamp;
        require(effectiveAtTimestamp &gt; currentTime, &quot;Effective At must be in the future&quot;);

        if (currentTime &gt; _effectiveAt) {
            uint256 oldMultiplier = _newUIMultiplier;
            _uiMultiplier = oldMultiplier;
            _newUIMultiplier = newMultiplier;
            _effectiveAt = effectiveAtTimestamp;
            emit UIMultiplierUpdated(oldMultiplier, newMultiplier, effectiveAtTimestamp);
        } else {
            uint256 oldMultiplier = _uiMultiplier;
            _newUIMultiplier = newMultiplier;
            _effectiveAt = effectiveAtTimestamp;
            emit UIMultiplierUpdated(oldMultiplier, newMultiplier, effectiveAtTimestamp);
        }
    }

    // ============ Optional: Conversion Extension ============

    function toUIAmount(uint256 rawAmount) public view override returns (uint256) {
        uint256 currentTime = block.timestamp;
        if (currentTime &gt;= _effectiveAt) {
            return (rawAmount * _newUIMultiplier) / MULTIPLIER_DECIMALS;
        } else {
            return (rawAmount * _uiMultiplier) / MULTIPLIER_DECIMALS;
        }
    }

    function fromUIAmount(uint256 uiAmount) public view override returns (uint256) {
        uint256 currentTime = block.timestamp;
        if (currentTime &gt;= _effectiveAt) {
            return (uiAmount * MULTIPLIER_DECIMALS) / _newUIMultiplier;
        } else {
            return (uiAmount * MULTIPLIER_DECIMALS) / _uiMultiplier;
        }
    }

    // ============ Optional: Balances Extension ============

    function balanceOfUI(address account) public view override returns (uint256) {
        return toUIAmount(balanceOf(account));
    }

    function totalSupplyUI() public view override returns (uint256) {
        return toUIAmount(totalSupply());
    }

    // ============ Optional: TransferWithUIAmount Event ============

    function _update(address from, address to, uint256 amount) internal virtual override {
        super._update(from, to, amount);
        uint256 uiAmount = toUIAmount(amount);
        emit TransferWithUIAmount(from, to, amount, uiAmount);
    }
}
```
## Rationale


Design Decisions:

1. Separate UI Functions: Rather than modifying the core ERC-20 functions, we provide separate UI-specific functions. This ensures backward compatibility and allows integrators to opt-in to the UI scaling feature.

2. 18 Decimal Precision: Using 18 decimals for the multiplier provides sufficient precision for most use cases while aligning with Ethereum&apos;s standard decimal representation.

3. No Automatic Updates: The multiplier must be explicitly set by authorized parties, giving issuers full control over when and how adjustments are made.

4. Raw Amount Preservation: All actual token operations continue to use raw amounts, ensuring that the multiplier is purely a display feature and doesn&apos;t affect the underlying token economics.

5. Optional Extensions: Following the pattern established by [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155), helper functions like `toUIAmount`, `fromUIAmount`, `balanceOfUI`, and `totalSupplyUI` are defined in separate optional interfaces. The `TransferWithUIAmount` event is defined in the core interface as optional since events do not affect interface IDs. This keeps the core interface minimal while allowing contracts to opt-in to additional on-chain functionality. Integrators can detect support for these extensions using [ERC-165](/EIPs/EIPS/eip-165) interface detection.

Alternative Approaches Considered:

1. Rebasing Tokens: While rebasing tokens adjust supply automatically, they create complexity for integrators and can break composability with DeFi protocols.

2. Wrapper Tokens: Creating wrapper tokens for each adjustment event adds unnecessary complexity and gas costs.

3. Index/Exchange Rate Tokens confer similar advantages to the proposed Scaled UI approach, but is ultimately less intuitive and requires more calculations on the UI layers.

4. Off-chain Solutions: Purely off-chain solutions lack standardization and require trust in centralized providers.

![Token Value Representation Approaches](/EIPs/assets/eip-8056/token_value_repr.jpeg)

![Token Architecture Layers](/EIPs/assets/eip-8056/token_arch_layers.jpeg)

### Backwards Compatibility


This EIP is fully backwards compatible with ERC-20. Existing ERC-20 functions continue to work as expected, and the UI scaling features are opt-in through additional functions.

### Test Cases

Example test scenarios:

1. Initial Multiplier Test:

- Verify that initial multiplier is 1.0 (1e18)

- Confirm balanceOf equals balanceOfUI initially

2. Stock Split Test:

- Set multiplier to 2.0 (2e18) for 2-for-1 split

- Verify UI balance is double the raw balance

- Confirm conversion functions work correctly

## Security Considerations


1. Multiplier Manipulation

- Unauthorized changes to the UI multiplier could mislead users about their holdings

- Implementations MUST use robust access control mechanisms

- The setUIMultiplier function MUST be restricted to authorized addresses (e.g., contract owner or a designated role).

2. Integer Overflow

- Risk of overflow when applying the multiplier

- Use SafeMath or Solidity 0.8.0+ automatic overflow protection

3. User Confusion

- Clear communication is essential when UI amounts differ from raw amounts

- Integrators MUST clearly indicate when displaying UI-adjusted balances

4. Oracle Dependency

- For automated multiplier updates, the system may depend on oracles

- Oracle failures or manipulations could affect displayed balances

5. Overflow Protection: Implementations MUST handle potential overflow when applying the multiplier.

### Implementation Guide for Integrators

#### Wallet Integration

Wallets supporting this standard should:

1. Check if a token implements `IScaledUIAmount` interface using ERC-165

2. Optionally check for `IScaledUIAmountBalances` extension for on-chain balance queries

3. Display both raw and UI amounts, clearly labeled

4. Compute UI balance off-chain using `balanceOf()` and `uiMultiplier()`, or use `balanceOfUI()` if the extension is supported

5. Handle transfers using raw amounts (standard ERC-20 functions)

**Example JavaScript integration:**

```javascript
const MULTIPLIER_DECIMALS = BigInt(1e18);

// Interface IDs for ERC-165 detection
const ISCALED_UI_AMOUNT_ID = &quot;0xa60bf13d&quot;;
const ISCALED_UI_BALANCES_ID = &quot;0xd890fd71&quot;;

// Off-chain conversion functions
function toUIAmount(rawAmount, multiplier) {
    return (BigInt(rawAmount) * BigInt(multiplier)) / MULTIPLIER_DECIMALS;
}

function fromUIAmount(uiAmount, multiplier) {
    return (BigInt(uiAmount) * MULTIPLIER_DECIMALS) / BigInt(multiplier);
}

async function displayBalance(tokenAddress, userAddress) {
    const token = new ethers.Contract(tokenAddress, ScaledUIAmountABI, provider);

    // Check if core scaled UI is supported
    const supportsScaledUI = await token.supportsInterface(ISCALED_UI_AMOUNT_ID);

    if (!supportsScaledUI) {
        // Fall back to standard ERC-20
        const balance = await token.balanceOf(userAddress);
        return {
            display: formatUnits(balance, decimals),
            raw: formatUnits(balance, decimals),
            multiplier: &quot;1.0&quot;
        };
    }

    // Check if optional balances extension is supported
    const supportsBalancesExt = await token.supportsInterface(ISCALED_UI_BALANCES_ID);

    const rawBalance = await token.balanceOf(userAddress);
    const multiplier = await token.uiMultiplier();

    // Use on-chain balanceOfUI if available, otherwise compute off-chain
    const uiBalance = supportsBalancesExt
        ? await token.balanceOfUI(userAddress)
        : toUIAmount(rawBalance, multiplier);

    return {
        display: formatUnits(uiBalance, decimals),
        raw: formatUnits(rawBalance, decimals),
        multiplier: formatUnits(multiplier, 18)
    };
}
```

#### Exchange Integration

Exchanges should:

1. Store and track the multiplier for each supported token

2. Display UI amounts in user interfaces

3. Use raw amounts for all internal accounting

4. Provide clear documentation about the scaling mechanism

Example implementation:

```javascript
const MULTIPLIER_DECIMALS = BigInt(1e18);

class ScaledTokenHandler {
    // Off-chain conversion functions
    toUIAmount(rawAmount, multiplier) {
        return (BigInt(rawAmount) * BigInt(multiplier)) / MULTIPLIER_DECIMALS;
    }

    fromUIAmount(uiAmount, multiplier) {
        return (BigInt(uiAmount) * MULTIPLIER_DECIMALS) / BigInt(multiplier);
    }

    async processDeposit(tokenAddress, amount, isUIAmount) {
        const token = new ethers.Contract(tokenAddress, ScaledUIAmountABI, provider);

        let rawAmount;
        if (isUIAmount &amp;&amp; await this.supportsScaledUI(tokenAddress)) {
            const multiplier = await token.uiMultiplier();
            rawAmount = this.fromUIAmount(amount, multiplier);
        } else {
            rawAmount = amount;
        }

        // Process deposit with raw amount
        return this.recordDeposit(tokenAddress, rawAmount);
    }

    async getDisplayBalance(tokenAddress, userAddress) {
        const token = new ethers.Contract(tokenAddress, ScaledUIAmountABI, provider);
        const rawBalance = await this.getInternalBalance(userAddress, tokenAddress);

        if (await this.supportsScaledUI(tokenAddress)) {
            const multiplier = await token.uiMultiplier();
            return this.toUIAmount(rawBalance, multiplier);
        }
        return rawBalance;
    }
}

```

#### DeFi Protocol Integration

DeFi protocols should:

1. Continue using raw amounts for all protocol operations

2. Provide UI helpers for displaying adjusted amounts

3. Emit events with both raw and UI amounts where relevant

4. Document clearly which amounts are used in calculations


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 20 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8056</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8056</guid>
      </item>
    
      <item>
        <title>Inter-Block Temporal Locality Gas Discounts</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8057-block-temporal-locality-gas-discounts/25912</comments>
        
        <description>## Abstract

This proposal introduces a deterministic, multi-block discount for the first access to accounts and storage keys in a transaction. The discount depends on how many blocks have passed since the item was last accessed, decaying smoothly to zero over a fixed recent window. Intra-block warming semantics are unchanged - there is no warming across transactions within a block.

The mechanism builds on block-level access lists ([EIP-7928](/EIPs/EIPS/eip-7928)), which are committed in prior blocks. This allows a newly synced node to correctly price the first block it validates without replaying historical execution.

## Motivation

Current warm and cold access pricing correctly models client state costs in the *worst case* but leaves a predictable efficiency gap in the *common case*. Clients maintain short-lived in-memory caches of recently accessed accounts and storage slots to handle short reorgs and pipeline execution across blocks. These caches make accesses from recent blocks materially cheaper than fully cold loads, yet the gas model does not reflect this.

As a result, Ethereum&apos;s gas schedule is conservative: it prices every &quot;first access&quot; as if it were completely cold, even though for most active contracts those lookups are served from hot caches or SSD pages still in memory. The gap between average and worst-case cost limits how far the block gas limit can safely rise-clients must size for the worst case even if most blocks are far cheaper in practice.

We can adjust gas prices to surface this mechanical sympathy, rewarding patterns that align naturally with how hardware and clients already behave.

This proposal narrows that gap in a deterministic and consensus-safe way. It introduces a smoothly decaying, per-item discount based solely on *publicly observable prior-block activity* recorded in block-level access lists ([EIP-7928](/EIPs/EIPS/eip-7928)). That achieves three effects:

1. **Predictability at submission time** - Unlike same-block or cross-transaction warming, discounts depend only on past blocks, so users, builders, and wallets can compute exact costs deterministically from on-chain data.
2. **Behavioural alignment** - The mechanism encourages natural temporal locality: dapps and operators who reuse state within a few blocks save gas, reflecting the real cost profile of client caching.
3. **Improved L1 scalability** - By reducing the *average* gas cost of realistic workloads without changing the *worst case*, 8057 effectively raises real execution throughput per gas, helping move toward the &quot;Scale L1&quot; goal of larger blocks and better hardware utilisation.

Empirically, traces show that most hot contracts are touched repeatedly within a few blocks. A 32-block (≈6-minute) window captures the majority of these recurrences. In this regime, total gas usage per block can fall by several percent in steady state, freeing execution capacity without altering consensus rules or transaction semantics.

In short, 8057 aligns Ethereum&apos;s gas economics with real execution cost, using already-available data (BALs) to make temporal locality explicit, deterministic, and beneficial.

As the saving depends only on publicly observable prior-block activity, it is knowable at submission time. Unlike same-block effects, it is therefore behaviour-shaping rather than incidental. It nudges workloads that naturally cluster accesses to keep doing so, matching how clients amortise repeated recent accesses.

This proposal is intentionally scoped to per-transaction warming and does not apply intra-block warming across transactions.

## Specification

### Terminology and constants

| Name | Description | Default  |
|-----------------------------|-----------------------|-----------------|
| `WINDOW_SIZE_BLOCKS`| Number of recent blocks over which a discount may apply. | `32` |
| `CURRENT_BLOCK_NUMBER`      | The block number of the transaction being executed. | - |
| `LAST_ACCESS_BLOCK_NUMBER(item)` | The most recent block number strictly less than `CURRENT_BLOCK_NUMBER` in which `item` was accessed by an executed transaction. If unknown or older than `WINDOW_SIZE_BLOCKS`, it is treated as not found. | - |
| `BLOCK_DISTANCE_IN_BLOCKS(item)` | Defined as `CURRENT_BLOCK_NUMBER - LAST_ACCESS_BLOCK_NUMBER(item)` when the latter is found, else a value greater than `WINDOW_SIZE_BLOCKS`. | - |

Gas constants from existing behaviour:

| Name                        | Value  |
|-----------------------------|-------:|
| `SLOAD_WARM_GAS_COST`       | `100`  |
| `SLOAD_COLD_SURCHARGE_GAS`  | `2100` |
| `ACCOUNT_WARM_GAS_COST`     | `100`  |
| `ACCOUNT_COLD_SURCHARGE_GAS`| `2600` |

Discount caps (this EIP treats maximum as full cold surcharge, minimum as zero):

| Name                      | Value                        |
|---------------------------|-----------------------------:|
| `DISCOUNT_MAX_SLOAD`      | `SLOAD_COLD_SURCHARGE_GAS`   |
| `DISCOUNT_MIN_SLOAD`      | `0`                          |
| `DISCOUNT_MAX_ACCOUNT`    | `ACCOUNT_COLD_SURCHARGE_GAS` |
| `DISCOUNT_MIN_ACCOUNT`    | `0`                          |

This means the closest prior-block usage allows the first access in a transaction to be charged at warm cost, and the far edge of the window trends to the normal cold-plus-warm cost.

### Scope of operations

This EIP applies the discount to the **first access in a transaction** of:

- Storage keys accessed by `SLOAD` and by any operation that first reads a slot as part of its semantics (for example, `SSTORE`&apos;s read step).
- Account touches that incur the cold account access surcharge under the current gas schedule, including but not limited to: `BALANCE`, `EXTCODEHASH`, `EXTCODESIZE`, `EXTCODECOPY`, and the target account of `CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL`.

Writes are affected **only** to the extent they perform an initial read or account touch that would have been charged as cold. Write-specific costs and any refund semantics are unchanged.

Precompiles remain unchanged and are always warm. Because they do not pay a cold surcharge, no discount is applied to precompile calls.

Access lists per [EIP-2930](/EIPs/EIPS/eip-2930) remain effective and, when present, pre-warm the listed addresses and storage keys at the start of the transaction. For items that are pre-warmed by an access list, this temporal discount does not apply.

### Discount function

The discount decays smoothly with block distance, using a **reversed Hermite smoothstep** interpolation over the discount window.


![Gas discount percentage graph](/EIPs/assets/eip-8057/gas_discount_percentage.png)

Mathematically:

$x = \mathrm{clamp}\left( \frac{D - 1}{W - 1}, 0, 1 \right)$

$f(D, W) = d_{\text{min}} + (d_{\text{max}} - d_{\text{min}}) 
           \cdot \left( 1 - \left( 3x^2 - 2x^3 \right) \right)$

where:

- $D$ = block distance in blocks
- $W$ = window size in blocks
- $d_{\text{min}}$, $d_{\text{max}}$ = minimum and maximum discounts

This form maps:

- $D = 1$ → full discount $(f = d_{\text{max}})$
- $D = W$ → no discount $(f = d_{\text{min}})$

Programmatic form

Reference smoothstep helper:

```python
def smoothstep(edge0: float, edge1: float, x: float) -&gt; float:
    &quot;&quot;&quot;Scale and clamp x to [0, 1], then apply cubic Hermite smoothstep.&quot;&quot;&quot;
    x = max(0.0, min(1.0, (x - edge0) / (edge1 - edge0)))
    return x * x * (3.0 - 2.0 * x)
```

Calculation steps:

- `NORMALIZED_DISTANCE = (BLOCK_DISTANCE_IN_BLOCKS - 1) / (WINDOW_SIZE_BLOCKS - 1)` clamped to `[0, 1]`.  This maps distance `1` → `0` and distance `WINDOW_SIZE_BLOCKS` → `1`.
- `SMOOTHSTEP_VALUE = smoothstep(0.0, 1.0, NORMALIZED_DISTANCE)`
- `DISCOUNT_FACTOR = 1.0 - SMOOTHSTEP_VALUE` (equals `1.0` at distance `1`, and `0.0` at distance `WINDOW_SIZE_BLOCKS`)

For a given opcode family with parameters `DISCOUNT_MAX` and `DISCOUNT_MIN`, the integer discount applied to the **cold surcharge** is:

```python
if BLOCK_DISTANCE_IN_BLOCKS &lt;= 0 or BLOCK_DISTANCE_IN_BLOCKS &gt; WINDOW_SIZE_BLOCKS:
    DISCOUNT_GAS = 0
else:
    NORMALIZED_DISTANCE = max(
        0.0,
        min(1.0, (BLOCK_DISTANCE_IN_BLOCKS - 1.0) / (WINDOW_SIZE_BLOCKS - 1.0)),
    )
    SMOOTHSTEP_VALUE = smoothstep(0.0, 1.0, NORMALIZED_DISTANCE)
    DISCOUNT_FACTOR = 1.0 - SMOOTHSTEP_VALUE
    DISCOUNT_GAS = DISCOUNT_MIN + round(
        (DISCOUNT_MAX - DISCOUNT_MIN) * DISCOUNT_FACTOR
    )
```

All arithmetic must be implemented in **integer space** in consensus-critical code; floating point is shown here only for clarity. `round()` follows *round half up* semantics; any deterministic rule is acceptable if consistently applied across clients.

This mechanism is a **discount**, not a refund. It reduces gas charged upfront for a cold surcharge; it does not emit a rebate and does not affect refund accounting or receipts.

### Charging rules (per transaction)

For the first access to an `ITEM` **within a transaction**:

1. If `ITEM` is already warm in this transaction due to same-transaction rules or pre-warmed via a transaction access list, charge the warm cost defined today. No temporal discount applies.
2. Otherwise compute `BLOCK_DISTANCE_IN_BLOCKS(ITEM)`. If `1 &lt;= BLOCK_DISTANCE_IN_BLOCKS(ITEM) &lt;= WINDOW_SIZE_BLOCKS`, apply the discount to the cold surcharge:

   - Storage read first access cost:

     - `SLOAD_FIRST_ACCESS_COST = SLOAD_WARM_GAS_COST + max(0, SLOAD_COLD_SURCHARGE_GAS - DISCOUNT_SLOAD(BLOCK_DISTANCE_IN_BLOCKS))`

   - Account-touch first access cost:

     - `ACCOUNT_FIRST_ACCESS_COST = ACCOUNT_WARM_GAS_COST + max(0, ACCOUNT_COLD_SURCHARGE_GAS - DISCOUNT_ACCOUNT(BLOCK_DISTANCE_IN_BLOCKS))`

3. If `BLOCK_DISTANCE_IN_BLOCKS(ITEM) &gt; WINDOW_SIZE_BLOCKS` or not found, charge the unmodified cold surcharge plus the warm component as today.

Subsequent accesses to the same `ITEM` within the **same transaction** are warm as per existing rules. This EIP does not introduce block-level warming across transactions.

### Initial sync and pricing with block-level access lists

This EIP requires block-level access lists in blocks. Each block carries commitments to the sets of accounts and storage keys accessed during that block.

A newly synced node can price the very first block it validates as follows:

1. For a block to validate at `CURRENT_BLOCK_NUMBER`, gather the BALs for the previous `WINDOW_SIZE_BLOCKS` blocks.
2. For each of those blocks, obtain the committed sets of accessed accounts and storage keys from the block body.
3. Build a local index mapping each seen `ITEM` to the most recent block number in which it appears within that window. This becomes `LAST_ACCESS_BLOCK_NUMBER(ITEM)`.
4. When validating `CURRENT_BLOCK_NUMBER`, for each first access to `ITEM`, compute
   `BLOCK_DISTANCE_IN_BLOCKS(ITEM) = CURRENT_BLOCK_NUMBER - LAST_ACCESS_BLOCK_NUMBER(ITEM)`
   when present, else treat as out-of-window. Apply the discount rules above.

Reorgs longer than `WINDOW_SIZE_BLOCKS` fall back to the same procedure as initial resync. Items not present in the new canonical window are treated as cold.

No execution of historical transactions is required to compute the discount at validation time. Stateless verifiers can price gas using the current block plus compact proofs that an item appears in one of the previous `WINDOW_SIZE_BLOCKS` access lists.

### Wallet gas estimation guidance

Wallets and RPC endpoints should not assume that a temporal discount will apply at submission, because the exact landing block is uncertain. General-purpose estimators should price as if no temporal discount applies.

Operators who can predict landing with high confidence - for example via priority fees and private order flow - may account for the exact discount, but this is an advanced path and not the default.

Motivated operators who can reliably land transactions in a specific block - for example via private order flow and appropriately set priority fees - may account for the exact discount. This is an advanced use case and should not be the default behaviour for general-purpose wallets.

### Implementation guidance

Clients are expected to maintain a rolling in-memory index to avoid rescanning prior blocks for each block:

- Keep a ring buffer of `WINDOW_SIZE_BLOCKS` buckets, one per recent block. Each bucket stores first-touched accounts and first-touched storage keys for that block.
- Maintain two maps, `LAST_SEEN_ACCOUNT` and `LAST_SEEN_STORAGE_KEY`, which track the most recent block index within the window where each item was present. On block advance, drop the oldest bucket and delete items that only appeared there, or mark them as out-of-window.
- During execution, when an opcode is about to charge a cold surcharge for an item not yet warm in the current transaction, look up `BLOCK_DISTANCE_IN_BLOCKS` from the `LAST_SEEN_*` map and charge using the rules above. Then record first touches for the current block in the current bucket and update the maps.

This design keeps memory bounded by `WINDOW_SIZE_BLOCKS` multiplied by the number of distinct first touches per block, which is itself bounded by the block gas limit divided by the minimum per-item cost.

This is one practical approach; clients may also implement this via existing caches or by embedding and pruning block-distance hints in their state trie.

### Test cases

### Example parameters and results

Assume the following defaults:

| Name                         |  Value |
| ---------------------------- | -----: |
| `WINDOW_SIZE_BLOCKS`         |   `32` |
| `SLOAD_WARM_GAS_COST`        |  `100` |
| `SLOAD_COLD_SURCHARGE_GAS`   | `2100` |
| `ACCOUNT_WARM_GAS_COST`      |  `100` |
| `ACCOUNT_COLD_SURCHARGE_GAS` | `2600` |
| `DISCOUNT_MAX_SLOAD`         | `2100` |
| `DISCOUNT_MIN_SLOAD`         |    `0` |
| `DISCOUNT_MAX_ACCOUNT`       | `2600` |
| `DISCOUNT_MIN_ACCOUNT`       |    `0` |

#### Example: first storage read in a transaction

| `BLOCK_DISTANCE_IN_BLOCKS` | Discount | Charge | Notes         |
| -------------------------- | -------: | -----: | ------------- |
| `1`                        |   `2100` |  `100` | Equal to warm |
| `8`                        |   `1827` |  `373` | -             |
| `16`                       |   `1101` | `1099` | Mid-window    |
| `24`                       |    `347` | `1853` | -             |
| `32`                       |      `0` | `2200` | Window edge   |
| `&gt;32`                      |      `0` | `2200` | Fully cold    |

#### Example: first account touch in a transaction

| `BLOCK_DISTANCE_IN_BLOCKS` | Discount | Charge | Notes         |
| -------------------------- | -------: | -----: | ------------- |
| `1`                        |   `2600` |  `100` | Equal to warm |
| `8`                        |   `2262` |  `438` | -             |
| `16`                       |   `1363` | `1337` | Mid-window    |
| `24`                       |    `430` | `2270` | -             |
| `32`                       |      `0` | `2700` | Window edge   |
| `&gt;32`                      |      `0` | `2700` | Fully cold    |

Exact integer results are determined by the reference implementation&apos;s rounding rule (`round_to_nearest`, half-up).

### Reference implementation (Python, integer only)

This implementation is normative for rounding and scaling. It uses a power-of-two fixed-point scale so divisions by the scale are exact shifts in low-level implementations. All intermediates fit below 2**53 so a JavaScript client can mirror these steps without a big number library.

```python
# Gas constants
SLOAD_WARM_GAS_COST = 100
SLOAD_COLD_SURCHARGE_GAS = 2100
ACCOUNT_WARM_GAS_COST = 100
ACCOUNT_COLD_SURCHARGE_GAS = 2600

# Temporal discount parameters
WINDOW_SIZE_BLOCKS = 32
DISCOUNT_MAX_SLOAD = SLOAD_COLD_SURCHARGE_GAS
DISCOUNT_MIN_SLOAD = 0
DISCOUNT_MAX_ACCOUNT = ACCOUNT_COLD_SURCHARGE_GAS
DISCOUNT_MIN_ACCOUNT = 0

# Fixed-point scale (2^25 = 33,554,432)
SCALE_FACTOR = 1 &lt;&lt; 25
HALF_SCALE = SCALE_FACTOR &gt;&gt; 1


def smooth_factor_scaled(block_distance_in_blocks: int,
                         window_blocks: int = WINDOW_SIZE_BLOCKS) -&gt; int:
    &quot;&quot;&quot;
    Returns round_to_nearest(SCALE_FACTOR * DISCOUNT_FACTOR) where:
      normalized_distance = (block_distance_in_blocks - 1) / (window_blocks - 1),
      clamped to [0, 1]
      smoothstep_value = normalized_distance^2 * (3 - 2 * normalized_distance)
      discount_factor = 1 - smoothstep_value
    The result is in [0, SCALE_FACTOR].
    &quot;&quot;&quot;
    if block_distance_in_blocks &lt;= 0 or block_distance_in_blocks &gt; window_blocks:
        return 0

    # Use exact rational form to minimize scaling multiplications:
    # Let t = block_distance_in_blocks - 1, d = window_blocks - 1.
    # discount_factor = (d^3 - 3*d*t^2 + 2*t^3) / d^3
    t = block_distance_in_blocks - 1
    d = window_blocks - 1
    d3 = d * d * d
    t2 = t * t
    t3 = t2 * t
    numerator = d3 - 3 * d * t2 + 2 * t3

    # Round half up
    return (SCALE_FACTOR * numerator + (d3 // 2)) // d3


def discount_gas_units(block_distance_in_blocks: int,
                       discount_max: int,
                       discount_min: int) -&gt; int:
    &quot;&quot;&quot;
    Integer discount within the window using the smooth falloff.
    Returns an integer number of gas units to subtract from the cold surcharge.
    &quot;&quot;&quot;
    if block_distance_in_blocks &lt;= 0 or block_distance_in_blocks &gt; WINDOW_SIZE_BLOCKS:
        return 0

    factor_scaled = smooth_factor_scaled(block_distance_in_blocks, WINDOW_SIZE_BLOCKS)
    span = discount_max - discount_min
    scaled = (span * factor_scaled + HALF_SCALE) // SCALE_FACTOR
    return discount_min + scaled


def sload_first_access_cost(block_distance_in_blocks: int) -&gt; int:
    disc = discount_gas_units(block_distance_in_blocks,
                              DISCOUNT_MAX_SLOAD,
                              DISCOUNT_MIN_SLOAD)
    cold_part = SLOAD_COLD_SURCHARGE_GAS - disc
    if cold_part &lt; 0:
        cold_part = 0
    return SLOAD_WARM_GAS_COST + cold_part


def account_first_access_cost(block_distance_in_blocks: int) -&gt; int:
    disc = discount_gas_units(block_distance_in_blocks,
                              DISCOUNT_MAX_ACCOUNT,
                              DISCOUNT_MIN_ACCOUNT)
    cold_part = ACCOUNT_COLD_SURCHARGE_GAS - disc
    if cold_part &lt; 0:
        cold_part = 0
    return ACCOUNT_WARM_GAS_COST + cold_part
```

Using lookup tables

```python
# SLOAD first access cost per block distance (1-32)
# WINDOW_SIZE_BLOCKS = 32
SLOAD_FIRST_ACCESS_COST_LUT = [
    100, 106, 125, 155, 196, 246, 306, 373,
    447, 528, 615, 706, 800, 898, 998, 1099,
    1201, 1302, 1402, 1500, 1594, 1685, 1772, 1853,
    1927, 1994, 2054, 2104, 2145, 2175, 2194, 2200
]

# Account first access cost per block distance (1-32)
# WINDOW_SIZE_BLOCKS = 32
ACCOUNT_FIRST_ACCESS_COST_LUT = [
    100, 108, 131, 168, 219, 281, 354, 438,
    530, 630, 737, 850, 967, 1088, 1212, 1337,
    1463, 1588, 1712, 1833, 1950, 2063, 2170, 2270,
    2362, 2446, 2519, 2581, 2632, 2669, 2692, 2700
]

def sload_first_access_cost(block_distance_in_blocks: int) -&gt; int:
    if 1 &lt;= block_distance_in_blocks &lt;= 32:
        return SLOAD_FIRST_ACCESS_COST_LUT[block_distance_in_blocks - 1]
    return 2200  # fully cold

def account_first_access_cost(block_distance_in_blocks: int) -&gt; int:
    if 1 &lt;= block_distance_in_blocks &lt;= 32:
        return ACCOUNT_FIRST_ACCESS_COST_LUT[block_distance_in_blocks - 1]
    return 2700  # fully cold
```

## Rationale

- Determinism: discounts depend only on prior blocks, so users can predict costs at submission time. The block-level access lists in headers remove bootstrap ambiguity for new nodes. Intra-block dependent savings are inherently unknowable and non-actionable at submission, so they do not change behaviour; prior-block based savings do.
- Smooth curve: the chosen polynomial keeps strong incentive for very recent history and eases toward zero, aligning with how caches deliver benefit for temporal locality. Linear ramps are simpler but produce harsher edges.
- Window of 32: this captures longer-lived temporal locality without turning the feature into a long-term subsidy, and keeps proof and index sizes small.
- Discount not refund: reduces upfront charge only; does not change refund semantics or receipts.
- No correlation: simple to implement and reason about. The model is explicitly about last-access distance, not frequency.

Builder rotation and similar operational concerns are out of scope for this EIP.


### Behavioural effects

The smoothstep curve over 32 blocks is gentle. Discount remains close to maximum for roughly the first 12 to 16 blocks and decays toward zero near the far edge of the window.

#### Storage slot (SLOAD) first-access pricing

(warm = 100, cold surcharge = 2100, window = 32)

| `BLOCK_DISTANCE_IN_BLOCKS` | Discount | Charge | Notes                 |
| -------------------------- | -------: | -----: | --------------------- |
| `1`                        |   `2100` |  `100` | fully warm equivalent |
| `4`                        |   `2045` |  `155` | almost full discount  |
| `8`                        |   `1827` |  `373` |                       |
| `12`                       |   `1494` |  `706` |                       |
| `16`                       |   `1101` | `1099` | midpoint of window    |
| `18`                       |    `898` | `1302` |                       |
| `20`                       |    `700` | `1500` |                       |
| `24`                       |    `347` | `1853` |                       |
| `28`                       |     `96` | `2104` | near-cold             |
| `32`                       |      `0` | `2200` | window edge           |
| `&gt;32`                      |      `0` | `2200` | fully cold access     |

#### Account access first-access pricing

(warm = 100, cold surcharge = 2600, window = 32)

| `BLOCK_DISTANCE_IN_BLOCKS` | Discount | Charge | Notes                 |
| -------------------------- | -------: | -----: | --------------------- |
| `1`                        |   `2600` |  `100` | fully warm equivalent |
| `4`                        |   `2532` |  `168` | almost full discount  |
| `8`                        |   `2262` |  `438` |                       |
| `12`                       |   `1850` |  `850` |                       |
| `16`                       |   `1363` | `1337` | midpoint of window    |
| `18`                       |   `1112` | `1588` |                       |
| `20`                       |    `867` | `1833` |                       |
| `24`                       |    `430` | `2270` |                       |
| `28`                       |    `119` | `2581` | near-cold             |
| `32`                       |      `0` | `2700` | window edge           |
| `&gt;32`                      |      `0` | `2700` | fully cold access     |

#### Observations

- Accesses 1-6 blocks apart remain effectively warm, typically under 300-400 gas total.
- Around 16 blocks (≈3.2 minutes), costs reach roughly half the cold surcharge.
- By 28-32 blocks (≈5.5-6.4 minutes, one finalisation epoch), costs are nearly cold again.
- The transition is smooth and monotone; there are no cliffs or discontinuities to game.
- Both account and storage families charge exactly the warm rate for items accessed in the immediately preceding block.

As the discount depends only on **prior blocks**, users and dapps can plan around it. Unlike same-block effects, these savings are predictable: they are visible before submission and can be incorporated into automation or fee-scheduling logic.

If an operator wants to maintain most of the discount while sending as few transactions as possible, a practical cadence for items touched repeatedly is:

- Maintain about **80 percent** of the maximum discount by ensuring the item is touched again within **8-9 blocks** (around two minutes).
- Maintain about **50 percent** of the maximum discount by touching again within **16 blocks** (half an epoch).
- Beyond roughly **28 blocks**, the discount fades almost entirely; by **32 blocks**, the access is fully cold again.

In short, a **maintenance touch every 8-12 blocks** is an efficient balance: high retained discount with modest transaction frequency. Applications seeking tighter control-such as bridges, keepers, or batching relayers-can choose shorter cadences, while ordinary usage patterns will keep frequently accessed state warm naturally.

The **smooth decay curve** is important. It means missing the ideal block due to a temporary spike in gas prices or unexpected congestion doesn&apos;t abruptly forfeit the entire discount-costs rise gradually, not cliff-edge. This avoids brittle strategies that depend on exact timing and makes the mechanism more forgiving in volatile network conditions.

From a UX standpoint, humans are unlikely to act precisely within these timeframes, but automated systems can. Many popular contract surfaces-AMM reserves, token balances, or oracle feeds-stay warm simply through organic activity, letting users benefit indirectly.

Each account or storage key&apos;s discount remains **independent**. Repeated touches within the window only update the item&apos;s last-access block; they do not stack or correlate across different items.

#### Coordinated multi-EOA warm-up behaviour

Because the temporal discount depends only on **prior-block access**, a coordinated actor controlling multiple EOAs or contracts can sequence transactions to capture the maximum discount. For example, a lightweight &quot;warm-up&quot; transaction from one EOA in block `N` can touch a set of storage keys or accounts, allowing one or more follow-up transactions in block `N+1` to execute those same accesses at **warm-equivalent cost**.

This **inter-block pipelining** remains predictable, verifiable, and legitimate. It does not distort consensus or introduce hidden state; it simply rewards actors who cluster related work in adjacent blocks. The discount gained is bounded by the cold surcharge itself, while the overhead of coordination, additional priority fees, and builder inclusion uncertainty all limit how aggressively this pattern can be used. In practice, it is most relevant for highly automated systems-keepers, rollup bridges, or arbitrage bundles-that already coordinate sequencing across blocks.

With the **32-block window**, the value of pipelining falls off much faster. Missing a single block only slightly reduces the discount because of the smooth decay curve, but missing several in a row quickly erodes it. That makes warm-ups more predictable yet self-limiting: actors can&apos;t cheaply &quot;bank&quot; state heat far ahead, only maintain it across a short epoch-length horizon.

Builders and MEV searchers may still find minor advantage in chaining related operations across consecutive blocks, but this behaviour is **constructive**: it improves temporal locality in state access and lowers aggregate load on clients. The overall effect is a gentle nudge toward efficient state reuse, not a new coordination game.

If desired, protocol parameters could trim the incentive surface further-for example, by setting `DISCOUNT_MAX_*` slightly below the full cold surcharge so that even `D = 1` accesses remain marginally above the intra-transaction warm price. This specification treats that as optional tuning rather than a security necessity, accepting the small and predictable incentive as a reasonable trade-off for encouraging block-to-block efficiency.

### Relationship to block-level warming proposals

This EIP does not introduce intra-block warming across transactions. If a block-level warming proposal is active, its semantics are unchanged. The temporal discount defined here applies only to the first access to an item in a transaction based on prior-block history.

## Backwards Compatibility

This EIP changes gas charging and therefore requires a hard fork. It only decreases or equalises costs for affected opcodes and does not introduce new failure modes for existing contracts. Warm and cold cost upper bounds do not increase.

## Security Considerations

- **Determinism and consensus safety:** 
All discounts are derived from *previously committed block data*. No client-local or probabilistic state (like caches or heuristics) affects consensus. Any node-stateless or fully synced-can price gas deterministically using the current block and the prior `WINDOW_SIZE_BLOCKS` access-list commitments. This preserves verifiability and supports stateless validation with compact proofs referencing recent blocks only.

- **Index growth and memory bounds:**
Clients must maintain a rolling index of recently accessed items. With a 32-block window, memory use scales with the number of distinct first-accessed items per block-bounded by the block gas limit divided by the minimum per-item cost. This fits comfortably within existing cache budgets, and entries naturally expire as blocks advance.

- **Reorg handling:** Reorgs shorter than the window are cheap to recompute: nodes rebuild the index from the new canonical access lists. Longer reorgs fall back to initial resync behaviour. No historical transaction replay is required. Because discounts depend on committed data only, there is no ambiguity or consensus divergence across reorgs.

- **Abuse and incentive surface:** The design intentionally makes &quot;warm-up&quot; transactions unprofitable. Since the maximum discount equals the cold surcharge, warming a slot in block *N* and using it in *N+1* costs slightly *more* than a single cold access (e.g. `2200 + 100 &gt; 2200`). Thus there is no economic gain from spamming to maintain heat. The smooth decay curve further discourages exact-block timing games: adjacent blocks differ by only a handful of gas units at small distances.

- **Economic neutrality:** The mechanism reduces *average* per-access cost but leaves *worst-case* costs unchanged. Builders and block producers still target the same gas limit under EIP-1559, so total basefee burn and priority-fee dynamics remain stable. The network simply fits more real execution into the same gas target, improving efficiency without altering incentives for congestion or inclusion.

- **Stateless compatibility:** 
Earlier multi-block warming ideas were considered incompatible with stateless validation because pricing depended on uncommitted or ephemeral state. By tying discounts to BAL commitments, this proposal makes the pricing rule provable and verifiable. Stateless verifiers need only one compact proof of inclusion in a recent BAL-no historical execution replay, no private cache dependency.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 20 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8057</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8057</guid>
      </item>
    
      <item>
        <title>Contract Bytecode Deduplication Discount</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8058-contract-bytecode-deduplication-discount/25933</comments>
        
        <description>## Abstract

This proposal introduces a gas discount for contract deployments when the bytecode being deployed already exists in the state. By leveraging EIP-2930 access lists, any contract address included in the access list automatically contributes its code hash to a deduplication check. When the deployed bytecode matches an existing code hash from the access list, the deployment avoids paying `GAS_CODE_DEPOSIT * L` costs since clients already store the bytecode and only need to link the new account to the existing code hash.

This EIP becomes particularly relevant with the adoption of EIP-8037, which increases `GAS_CODE_DEPOSIT` from 200 to 1,900 gas per byte. Under EIP-8037, deploying a 24kB contract would cost approximately 46.6M gas for code deposit alone, making the deduplication discount economically significant for applications that deploy identical bytecode multiple times.

## Motivation

Currently, deploying duplicate bytecode costs the same as deploying new bytecode, even though execution clients don&apos;t store duplicated code in their databases. When the same bytecode is deployed multiple times, clients store only one copy and have multiple accounts point to the same code hash. Under EIP-8037&apos;s proposed gas costs, deploying a 24kB contract costs approximately 46.6M gas for code deposit alone (`1,900 × 24,576`). This charge is unfair for duplicate deployments where no additional storage is consumed.

A naive &quot;check if code exists in database&quot; approach would break consensus because different nodes have different database contents due to mostly Sync-mode differences:

- Full-sync nodes: Retain all historical code, including from reverted/reorged transactions
- Snap-sync nodes: initially, only store code referenced in the pivot state tries, and those accumulated past the start of the sync

Empirical analysis reveals that approximately 27,869 bytecodes existed in full-synced node databases with no live account pointing to them (as of the Cancun fork). A database lookup `CodeExists(hash)` would yield different results on different nodes, causing different gas costs and breaking consensus.

This proposal solves the problem by making deduplication checks implicit and deterministic through access lists, ensuring all nodes compute identical gas costs regardless of their database state. (Notice here that even if fully-synced clients have more codes, there are no accounts whose codeHash actually is referencing them. Thus, users can&apos;t profit from such discounts which keeps consensus safe).

## Specification

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

### Implicit Deduplication via Access Lists

This proposal leverages the existing EIP-2930 access list structure without any modifications. No new fields or protocol changes are required.

### CodeHash Access-Set Construction

Before transaction execution begins, build a set `W` (the &quot;CodeHash Access-Set&quot;) as follows:

```
W = { codeHash(a) | a ∈ accessList, a exists in state, a has code }
```

Where:

- `W` is built from state at the **start** of transaction execution (before any state changes)
- **All** addresses in the access list are checked - if they exist in state and have deployed code, their code hash is added to `W`
- Empty accounts or accounts with no code do not contribute to `W`

### Contract Creation Gas Accounting

When a contract creation transaction or opcode (`CREATE`/`CREATE2`) successfully completes and returns bytecode `B` of length `L`, compute `H = keccak256(B)` and apply the following gas charges:

**Deduplication check:**

- If `H ∉ W`: Bytecode is new
  - Charge `GAS_CODE_DEPOSIT * L`
  - Persist bytecode `B` under hash `H`
  - Link the new account&apos;s `codeHash` to `H`
- Otherwise, link the new account&apos;s `codeHash` to the existing code hash `H`

**Gas costs:**

- The cost of reading `codeHash` for access-listed addresses is already covered by EIP-2929/2930 access costs (intrinsic access-list cost and cold→warm state access charges).
- No additional gas cost is introduced for the deduplication check itself.

### Implementation Pseudocode

```python
# Before transaction execution:
W = set()
for tuple in tx.access_list:
    warm(tuple.address)  # per EIP-2930/EIP-2929 rules
    acc = load_account(tuple.address)
    if acc exists and acc.code is not empty:
        W.add(acc.codeHash)

# On successful CREATE/CREATE2:
H = keccak256(B)
if H in W:
    # Duplicate: no deposit gas
    link_codehash(new_account, H)
else:
    # New bytecode: charge and persist
    charge(GAS_CODE_DEPOSIT * len(B))
    persist_code(H, B)
    link_codehash(new_account, H)
```

### Same-Block Deployments

Sequential transaction execution ensures that a deployment storing new code makes it visible to later transactions in the same block:

1. Transaction `T_A` deploys bytecode `B` at address `X`
   - Pays full `GAS_CODE_DEPOSIT * L` (no prior contract has this bytecode)
   - Code is stored under hash `H = keccak256(B)`

2. Later transaction `T_B` in the same block deploys the same bytecode `B`:
   - `T_B` includes address `X` in its access list
   - When `T_B` executes, `W` is built from the current state (including `T_A`&apos;s changes)
   - Since `X` now exists and is in the access list, `W` contains `H`
   - `T_B`&apos;s deployment gets the discount

&gt; While this only tries to formalize the behavior, it&apos;s important to remark that this kind of behavior is complex. As it requires control over tx ordering in order to abuse. Builders can&apos;t modify the access list as it is already signed with the transaction. Nevertheless, this could happen, thus is formalized here.

### Edge Case: Simultaneous New Deployments

If two transactions in the same block both deploy identical new bytecode and neither references an existing contract with that bytecode in their access lists, both will pay full `GAS_CODE_DEPOSIT * L`.

**Example:**

- Transaction `T_A` deploys bytecode `B` producing code hash `0xCA` at address `X`
- Transaction `T_B` (later in same block) also deploys bytecode `B` producing code hash `0xCA` at address `Y`
- If `T_B`&apos;s access list does NOT include address `X`, then `T_B` pays full deposit cost
- Deduplication only occurs when the deploying address is included in the access list

This is acceptable because:

- The first deployment cannot be known at transaction construction time
- Deduplication requires implicit opt-in via access list
- This scenario is extremely rare in practice
- The complexity of special handling is not worth the minimal benefit

## Rationale

### Why Access-List Based Deduplication?

The access-list approach provides several critical properties:

1. Deterministic behavior: 
The result depends only on the transaction&apos;s access list and current state, not on local database contents. All nodes compute the same gas cost.

2. No reverse index requirement: 
Unlike other approaches, this doesn&apos;t require maintaining a `codeHash → [accounts]` reverse index, which would add significant complexity and storage overhead.

3. Leverages existing infrastructure: 
Builds on EIP-2930 access lists and EIP-2929 access costs, requiring minimal protocol changes.

4. Implicit optimization:
Any address included in the access list automatically contributes to deduplication. This provides automatic gas optimization without requiring explicit flags or special handling.

5. Avoids chain split risks:
Since no new transaction structure is introduced, there&apos;s no risk of nodes rejecting transactions with unknown fields. The same transaction format works before and after the fork, with only the gas accounting rules changing at fork activation.

6. Forward compatibility:
All nodes enforce identical behavior. Wallets can add addresses to access lists to optimize gas, but this doesn&apos;t change transaction validity.

7. Avoid having a code-root for state:
At this point, clients handle code storage on their own ways. They don&apos;t have any consensus on the deployed existing codes (besides that all of the ones referenced in account&apos;s codehash fields exist).
Changing this seems a lot more complex and unnecessary.

## Backwards Compatibility

This proposal requires a scheduled network upgrade but is designed to be forward-compatible with existing transactions.

**Transaction compatibility:**

- No changes to transaction structure - uses existing EIP-2930 access lists
- Existing transactions with access lists automatically benefit from deduplication post-fork
- Transactions without access lists behave identically to current behavior (no deduplication discount)

**Wallet and tooling updates:**

- RPC methods like `eth_estimateGas` SHOULD account for potential deduplication discounts when access lists are present
- Wallets MAY provide UI for users to add addresses to access lists for deduplication
- Transaction builders MAY automatically detect duplicate deployments and include relevant addresses in access lists

**Node implementation:**

- No changes to state trie structure or database schema required
- No changes to transaction parsing or RLP encoding

## Reference Implementation

### Example Transaction

Deploying a contract with the same bytecode as the contract at `0x1234...5678`:

```json
{
  &quot;from&quot;: &quot;0xabcd...ef00&quot;,
  &quot;to&quot;: null,
  &quot;data&quot;: &quot;0x608060405234801561001...&quot;,
  &quot;accessList&quot;: [
    {
      &quot;address&quot;: &quot;0x1234567890123456789012345678901234567890&quot;,
      &quot;storageKeys&quot;: []
    }
  ]
}
```

If the deployed bytecode hash matches `codeHash(0x1234...5678)` (which is automatically checked because the address is in the access list), the deployment receives the deduplication discount.

## Security Considerations

### Gas Cost Accuracy

The deduplication mechanism ensures that gas costs accurately reflect actual resource consumption. Duplicate deployments don&apos;t consume additional storage, so they shouldn&apos;t pay storage costs.

### Denial of Service

The access-list mechanism prevents DoS attacks because:

- The cost of reading `codeHash` is already covered by EIP-2929/2930
- No additional state lookups or database queries are required
- The deduplication check is O(1) (set membership test)

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 22 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8058</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8058</guid>
      </item>
    
      <item>
        <title>Gas Units Rebase for High-precision Metering</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8059-gas-rebase-for-high-precision-gas-metering/25945</comments>
        
        <description>## Abstract

This proposal rebases Ethereum’s gas unit to a factor of `REBASE_FACTOR` to enable high-precision metering without introducing fractional gas. All gas-related parameters and variables are increased to a factor of `REBASE_FACTOR`. This reduces rounding errors that arise when repricing EVM operations and future-proofs gas costs as hardware improves and state access remains costly, while avoiding major changes in the internal logic of the EVM.

## Motivation

Currently, most EVM compute operations (`ADD`, `SUB`, `MUL`, etc.) are significantly underpriced when compared with state operations (`SSTORE`, `SLOAD`, `CREATE`, etc.). There are two factors contributing to this mismatch. On one hand, client optimizations and hardware improvements have made pure compute operations more efficient. On the other hand, with the growing size of the Ethereum state, the performance of I/O operations touching this larger state has been deteriorating. Both of these trends are expected to continue, further worsening this mismatch.

There are a couple of proposals to reduce the cost of compute operations ([EIP-7904](/EIPs/EIPS/eip-7904)) and increase the cost of state operations ([EIP-8032](/EIPs/EIPS/eip-8032), [EIP-8037](/EIPs/EIPS/eip-8037), and [EIP-8038](/EIPs/EIPS/eip-8038)). However, given the current level of mismatch between these operations, there is an inherent trade-off in the anchor we use to reprice these operations.

If we make compute operations cheaper, we will introduce rounding errors, with most compute operations costing 1, when they should cost a fraction of that. These rounding errors impact scalability because we can now fit fewer of these cheaper operations in any given block. However, if we price all operations so that the fastest opcode is assigned 1 gas, we would need to make all other operations significantly more expensive, including both compute and state operations. Such a level of price increases would severely reduce throughput at current block limits.

To illustrate this point, let&apos;s focus on the pure compute operations. As compute operations impact only block execution time, the chosen anchor will induce a specific million gas per second rate on all compute opcodes. For instance, if we anchor on `EcRecover` at the current price (3000 gas units), this induces a rate of 175Mgas/s, based on the execution time estimated for this opcode on [EIP-7904&apos;s empirical analysis](/EIPs/assets/eip-7904/gas-cost-estimator-report.pdf). The following plot shows the average rounding errors of compute operations for different anchors, using the same execution time estimates from EIP-7904.

![round_error_by_anchor](/EIPs/assets/eip-8059/round_error_by_anchor.png)

As we can see, with an anchor of 50Mgas/s (which would result in a gas limit of 100Mgas, assuming a 2-second block execution limit), we would get an average rounding error of 59.3%. This means that we could be 59.3% cheaper on average per opcode if we didn&apos;t have to round to integer gas units. Only after a 400Mgas/s anchor do we get to reasonably low rounding errors. Without fractional gas, which would introduce further complexity to the EVM gas calculation, this level of Mgas/s anchor requires a major rebase of the gas model, where all opcodes become significantly more expensive, and both the transaction-level and block-level gas limits increase by the same factor.

## Specification

| **Parameter** | **Value** |
|:---:|:---:|
| `REBASE_FACTOR` | 1000 |

This proposal introduces a gas rebase such that all gas-related parameters and variables are increased by a factor of `REBASE_FACTOR`.

At fork boundary, `calculate_base_fee_per_gas` is updated so that both `parent_gas_used` and `parent_base_fee_per_gas` are also scaled by a factor of `REBASE_FACTOR`.

## Rationale

A rebase factor of 1000 has two advantages:

1. It is large enough to completely remove rounding errors for compute operations now and to be future-proof. As we can see from the motivation, an anchor of 400Mgas/s would be enough to reduce these errors. Assuming a 2-second block execution time, this results in a block limit of 800M gas units, which requires an increase of 22x over the current 36M block limit.
2. It makes reasoning about the new gas unit simpler. Block limits and targets move from million units to billion units, while gas costs move from units to thousand units.

## Backwards Compatibility

This is a backwards incompatible gas repricing that requires a scheduled network upgrade.

## Security Considerations

Increasing 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.

In addition, the increase in units in `gasLimit` and `gasUsed` will increase the size of the RLP representation the block header by 2 bytes. More analysis is needed to assess the bandwidth impacts.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 22 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8059</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8059</guid>
      </item>
    
      <item>
        <title>Increase exit and consolidation churn</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8061-increase-churn-limits/25991</comments>
        
        <description>## Abstract

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.

## Motivation

[EIP-7514](/EIPs/EIPS/eip-7514) introduced an activation cap of 8 validators per epoch (now 256 ETH per epoch) to prevent overly rapid validator set growth. [EIP-7251](/EIPs/EIPS/eip-7251) 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 
`CHURN_LIMIT_QUOTIENT` 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.

The conservative setting of the `CHURN_LIMIT_QUOTIENT` 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 &gt; 1M ETH, fully occupying the queue for ~20 days.

The EIP proposes to address these issues by:

- removing the cap on exits, restoring the proportionality of exit churn limit to total stake
- increasing the churn limit on exits
- introducing a separate consolidation churn limit, since there is no more &quot;excess churn&quot; 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.

 The EIP does *not* propose to lift the cap on the deposit churn, as part of the motivation for introducing it in [EIP-7514](/EIPs/EIPS/eip-7514) still holds today: though *active validator set* growth is mostly solved by [EIP-7251](/EIPs/EIPS/eip-7251), the *validator array in the BeaconState* (including inactive validators) is very large and still growing, and too rapid *stake* growth continues to be a concern as well.

## Specification

The `CHURN_LIMIT_QUOTIENT` is halved, from `2**16` to `2**15`, and fully dedicated to activations and exits. However, the cap on activations introduced in [EIP-7514](/EIPs/EIPS/eip-7514) is maintained via `MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT`, while exits are freed from this cap. Consolidations now have their own dedicated churn, determined by `CONSOLIDATION_CHURN_LIMIT_QUOTIENT`. This is set here to `2**16`, so that consolidations are allocated half as much churn as activations and exits combined, and a third of the total churn. Finally, `compute_weak_subjectivity_period` 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$).

### Configuration

`MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT` replaces the existing `MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT`, also `256`, as the cap now only applies to activations. We introduce the new `CONSOLIDATION_CHURN_LIMIT_QUOTIENT` and update the `CHURN_LIMIT_QUOTIENT`.

| Name                                   | Value                      |
| -------------------------------------- | -------------------------- |
| `CHURN_LIMIT_QUOTIENT_GLOAS`           | `uint64(2**15)` (= 32,768) |
| `CONSOLIDATION_CHURN_LIMIT_QUOTIENT`   | `uint64(2**16)` (= 65,536) |
| `MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT` | `uint64(2**8)`  (=256)     |

### Churn computations

Due to the intended asymmetry in activation and exit churn, we replace `get_activation_exit_churn_limit` with `get_activation_churn_limit`, capped at  `MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT`, and `get_exit_churn_limit`, uncapped. `get_consolidation_churn_limit` uses the new `CONSOLIDATION_CHURN_LIMIT_QUOTIENT`, without either a minimum or a maximum value.

```python
def get_activation_churn_limit(state: BeaconState) -&gt; Gwei:
    &quot;&quot;&quot;
    Per-epoch churn limit for activations, rounded to EFFECTIVE_BALANCE_INCREMENT.
    &quot;&quot;&quot;
    churn = max(
        MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA,
        get_total_active_balance(state) // CHURN_LIMIT_QUOTIENT_GLOAS
    )
    churn = churn - churn % EFFECTIVE_BALANCE_INCREMENT
    return min(MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT, churn)

def get_exit_churn_limit(state: BeaconState) -&gt; Gwei:
    &quot;&quot;&quot;
    Per-epoch churn limit for activations, rounded to EFFECTIVE_BALANCE_INCREMENT.
    &quot;&quot;&quot;
    churn = max(
        MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA,
        get_total_active_balance(state) // CHURN_LIMIT_QUOTIENT_GLOAS
    )
    return churn - churn % EFFECTIVE_BALANCE_INCREMENT

def get_consolidation_churn_limit(state: BeaconState) -&gt; Gwei:
    &quot;&quot;&quot;
    Per-epoch churn limit for consolidations (EIP-7521), rounded to EFFECTIVE_BALANCE_INCREMENT.
    &quot;&quot;&quot;
    churn = get_total_active_balance(state) // CONSOLIDATION_CHURN_LIMIT_QUOTIENT
    return churn - churn % EFFECTIVE_BALANCE_INCREMENT
```

In `compute_weak_subjectivity_period` we only replace `delta = get_balance_churn_limit(state)` with an explicit calculation taking into account the different weak subjectivity effect of each type of operation.

```python
def compute_weak_subjectivity_period(state: BeaconState) -&gt; uint64:
    &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;
    t = get_total_active_balance(state)
    delta = (
        2 * get_exit_churn_limit(state) // 3 # effect of exit churn
        + get_activation_churn_limit(state) // 3 # effect of activation churn
        + get_consolidation_churn_limit(state) # effect of consolidation churn
    )
    epochs_for_validator_set_churn = SAFETY_DECAY * t // (2 * delta * 100)
    return MIN_VALIDATOR_WITHDRAWABILITY_DELAY + epochs_for_validator_set_churn
```

### Deposit processing

The only modification is replacing `get_activation_exit_churn_limit` with `get_activation_churn_limit`, 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.

```python
def process_pending_deposits(state: BeaconState) -&gt; None:
    next_epoch = Epoch(get_current_epoch(state) + 1)
    # [Modified in Gloas:EIP-8061]
    available_for_processing = state.deposit_balance_to_consume + get_activation_churn_limit(
        state
    )
    processed_amount = 0
    next_deposit_index = 0
    deposits_to_postpone = []
    is_churn_limit_reached = False
    finalized_slot = compute_start_slot_at_epoch(state.finalized_checkpoint.epoch)
    for deposit in state.pending_deposits:
        # Do not process deposit requests if Eth1 bridge deposits are not yet applied.
        if (
            # Is deposit request
            deposit.slot &gt; GENESIS_SLOT
            and
            # There are pending Eth1 bridge deposits
            state.eth1_deposit_index &lt; state.deposit_requests_start_index
        ):
            break
        # Check if deposit has been finalized, otherwise, stop processing.
        if deposit.slot &gt; finalized_slot:
            break
        # Check if number of processed deposits has not reached the limit, otherwise, stop processing.
        if next_deposit_index &gt;= MAX_PENDING_DEPOSITS_PER_EPOCH:
            break
        # Read validator state
        is_validator_exited = False
        is_validator_withdrawn = False
        validator_pubkeys = [v.pubkey for v in state.validators]
        if deposit.pubkey in validator_pubkeys:
            validator = state.validators[ValidatorIndex(validator_pubkeys.index(deposit.pubkey))]
            is_validator_exited = validator.exit_epoch &lt; FAR_FUTURE_EPOCH
            is_validator_withdrawn = validator.withdrawable_epoch &lt; next_epoch
        if is_validator_withdrawn:
            # Deposited balance will never become active. Increase balance but do not consume churn
            apply_pending_deposit(state, deposit)
        elif is_validator_exited:
            # Validator is exiting, postpone the deposit until after withdrawable epoch
            deposits_to_postpone.append(deposit)
        else:
            # Check if deposit fits in the churn, otherwise, do no more deposit processing in this epoch.
            is_churn_limit_reached = processed_amount + deposit.amount &gt; available_for_processing
            if is_churn_limit_reached:
                break
            # Consume churn and apply deposit.
            processed_amount += deposit.amount
            apply_pending_deposit(state, deposit)
        # Regardless of how the deposit was handled, we move on in the queue.
        next_deposit_index += 1
    state.pending_deposits = state.pending_deposits[next_deposit_index:] + deposits_to_postpone
    # Accumulate churn only if the churn limit has been hit.
    if is_churn_limit_reached:
        state.deposit_balance_to_consume = available_for_processing - processed_amount
    else:
        state.deposit_balance_to_consume = Gwei(0)
```

### Exit processing

We replace `get_activation_exit_churn_limit` with `get_exit_churn_limit`.

```python
def compute_exit_epoch_and_update_churn(state: BeaconState, exit_balance: Gwei) -&gt; Epoch:
    earliest_exit_epoch = max(
        state.earliest_exit_epoch,
        compute_activation_exit_epoch(get_current_epoch(state))
    )
    # [Modified in Gloas:EIP-8061]
    per_epoch_churn = get_exit_churn_limit(state)
    # New epoch for exits.
    if state.earliest_exit_epoch &lt; earliest_exit_epoch:
        exit_balance_to_consume = per_epoch_churn
    else:
        exit_balance_to_consume = state.exit_balance_to_consume

    # Exit doesn&apos;t fit in the current earliest epoch.
    if exit_balance &gt; exit_balance_to_consume:
        balance_to_process = exit_balance - exit_balance_to_consume
        additional_epochs = (balance_to_process - 1) // per_epoch_churn + 1
        earliest_exit_epoch += additional_epochs
        exit_balance_to_consume += additional_epochs * per_epoch_churn

    # Consume the balance and update state variables.
    state.exit_balance_to_consume = exit_balance_to_consume - exit_balance
    state.earliest_exit_epoch = earliest_exit_epoch

    return state.earliest_exit_epoch
```

## Rationale

- **Independent parameters:** 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. 
- **Scaling with stake**: the exit churn regains proportionality to the total stake, and the consolidation churn maintains it.
- **Preserving the activation cap**: the activation churn limit maintains the cap from [EIP-7514](/EIPs/EIPS/eip-7514)
- **Balancing security and functionality**: 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.

## Backwards Compatibility

This EIP introduces a backwards-incompatible change to the consensus rules and MUST be activated as part of a scheduled network upgrade.

## Test Cases 

TODO

## Security Considerations

### Weak subjectivity period

Let `MIN_VALIDATOR_WITHDRAWABILITY_DELAY = 256` 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.

The formula to compute the weak subjectivity period (in epochs) for a 10% safety decay target (exactly corresponding to `compute_weak_subjectivity_period`) then is:

$\text{WS}_{\text{epochs}} = 256 +
\frac{0.1 \cdot S}{\frac{4}{3} \cdot E + \frac{2}{3} \cdot A + 2 \cdot C}$

The churn limits of the current protocol, assuming a total stake $S = 36M$ ETH (approximately the stake at the time of writing) are:

- $A = E = \min(256, S/2^{16}) = 256$ ETH (capped)
- $C = S/2^{16} - A \approx 293$ ETH

The weak subjectivity period is then:

$\text{WS}_{\text{epochs}} \approx 3533$

$\Rightarrow\ \textbf{WS} \approx \mathbf{15.7\ \text{days}}$

In days, it is $\text{WS}_{\text{epochs}} / 225$.

Under this EIP, and assuming a total stake $S = 36M$ ETH:

- $E = S/2^{15} \approx 1098$ ETH
- $A = \min(256, S/2^{15}) = 256$ ETH (capped)
- $C = S/2^{16} \approx 549$ ETH

The weak subjectivity period is then:

$\text{WS}_{\text{epochs}} \approx 1573$

$\Rightarrow\ \textbf{WS} \approx \mathbf{7.0\ \text{days}}$

Other possible future scenarios are:

- Activation cap removed: $\textbf{WS} \approx \mathbf{6.0\ \text{days}}$ ($\text{WS}_{\text{epochs}} \approx 1348$)
- Consolidations disabled: $\textbf{WS} \approx \mathbf{10.9\ \text{days}}$ ($\text{WS}_{\text{epochs}} \approx 2457$)
- Consolidations disabled and activation cap removed: $\textbf{WS} \approx \mathbf{8.4\ \text{days}}$ ($\text{WS}_{\text{epochs}} \approx 1894$)

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.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Add sweep withdrawal fee for 0x01 validators</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8062-add-sweep-withdrawal-fee-for-0x01-validators/26003</comments>
        
        <description>## Abstract

A fee is proposed on the partial &quot;sweep&quot; withdrawal of validators using `0x01` credentials, to improve stake consolidation and fairness. Ethereum&apos;s fast finality roadmap hinges on staking service providers migrating from `0x01` validators to `0x02` compounding validators. One roadblock is that `0x01` validators receive free-of-charge partial skimming withdrawals for balances exceeding 32 ETH, which consume protocol resources that are not accounted for. To address this, a 0.05% fee is imposed on the partial `0x01` sweep using a minimal modification to `process_withdrawals()`, applying the new constant `WITHDRAWAL_FEE_FRACTION = 2000`.

## Motivation

The roadmap for fast finality hinges on stake consolidation, where staking service providers (SSPs) transition from running 32-ETH validators with `0x01` credentials to compounding validators with `0x02` credentials. A roadblock to this transition is that `0x01` validators have been designed with close-to-ideal capital efficiency and free-of-charge partial withdrawals for balances exceeding 32 ETH (the &quot;sweep&quot; function). When factoring in switching costs, the incentives do not favor stake consolidation. At the same time, sweep withdrawals take up resources on both the consensus layer (CL) and execution layer (EL) that are not paid for. It is unsuitable to give `0x01` validators an accounting advantage over `0x02` validators when Ethereum&apos;s roadmap hinges on stakers consolidating their stake in `0x02` validators.

To improve consolidation while upholding fairness, this EIP accounts for the resource load of the `0x01` partial withdrawal sweep by imposing a small withdrawal fee for it. The proposed fee is 0.05% of the withdrawn amount, imposed via `WITHDRAWAL_FEE_FRACTION = 2000`. Since the average sweep withdrawal credits around 0.0235 ETH, the average expected fee per withdrawal is $0.0235\;\mathrm{ETH} \times 0.0005 = 11\,750\;\mathrm{Gwei}$. The total expected fee over one year for a validator is 0.00048 ETH, corresponding to around \$2 at the current ETH price. An SSP running 50,000 `0x01` validators (slightly below 5% of the stake) would thus need to pay around \$100,000 per year in withdrawal fees.

The fee approximates the EL workload imposed by the sweep, calibrated against the average base fee over the last year (4.53 gwei). The withdrawal incurs equivalent to around 2204 gas (not accounting for CL work), implying a fee of $2204 \times 4.53 = 9\,984\;\mathrm{Gwei}$ (albeit, the base fee has been lower in recent months).

The fee is taken out on the CL as a percentage, since a fixed fee could produce extreme outcomes if the number of `0x01` validators were to be drastically reduced due to consolidation. In such a scenario, the sweep will hit validators more frequently, and the fee will thus be taken out more frequently. Since validators then would also withdraw a lower balance each time, a percentage fee on the withdrawal keeps the burden on stakers fixed. The existing logic is kept intact to minimize complexity. As a result, a validator&apos;s balance will dip just below 32 ETH after skimming (as also happens when receiving a penalty just after skimming).

## Specification

### Parameters

| Constant                  | Value  |
| -                         | -      |
| `WITHDRAWAL_FEE_FRACTION` | `2000` |

### Functions

In `process_withdrawals()`, take out a fee for skimmed `0x01` validators that did not perform a full exit, burning it on the CL:

```python
def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -&gt; None:
    ...
    # In this existing for-loop, calculate a fee before decreasing the balance
    for w in expected_withdrawals:
        vi = w.validator_index
        fee = 0
        if not has_compounding_withdrawal_credential(state.validators[vi]) and w.amount != state.balances[vi]:
            fee = w.amount // WITHDRAWAL_FEE_FRACTION
        decrease_balance(state, vi, w.amount + fee)
```

## Rationale

### Fast finality

Fast finality is best realized through a reduction to the active validator set voting each round. Two paths have been envisioned. In one path referred to as Orbit SSF, the active set rotates in a weighted fashion, such that large consolidated validators always are active, and smaller validators are active less frequently. In another path, there is a fixed number of validator seats, with only the largest validators (e.g., the top 8,192) granted a seat. Both paths require consolidation to achieve a desirable stake weight and optimal performance. 

### Level of the proposed fee

The cost per validator per year under 3% CL yield becomes $32 \times 0.03 / 2000 = 0.00048$ ETH, corresponding to around \$2 at a price of \$4,167 per ETH. Table 1 summarizes outcomes under different numbers of validators. A solo staker running one `0x01` is unlikely to consider the $2 fee enough to tip the scale either way. A staking service provider (SSP) running 50,000 `0x01` validators (slightly below 5% of the stake) has at least a moderate incentive since the cost then is $100,000. Under perfect competition, the SSP will not be able to pass on this cost to their customers. The outcome under a higher fee is outlined in the Alternative specifications section.

| Validators (stake %)  | Cost (ETH/year) | Cost (USD/year) |
| -                     | -:              | -:              |
| 1 (~0.0001%)          | 0.00048         | $2              |
| 100 (~0.01%)          | 0.048           | $200            |
| 10,000 (~1%)          | 4.8             | $20,000         |
| 50,000 (~5%)          | 24              | $100,000        |
| 100,000 (~10%)        | 48              | $200,000        |

**Table 1.** Cost to stakers under the proposed withdrawal fee.

The switching cost may still be greater than the yearly fee for an SSP. Some smart contracts requiring `0x01` credentials may be frozen and others may require a full exit and entry, with associated opportunity costs. However, once the recurring fee is in place and there is a commitment from the protocol to phase out `0x01` validators for SSPs—potentially even raising the fee until such an outcome has been realized—then the switch will have to be done *eventually*. Ignoring other potential benefits of `0x01` validators, a more accurate comparison is thus between the recurring fee and the capital cost for financing the switch, which of course is lower.

### Gas accounting

The gas cost accounting is as follows: 

* 500 gas – cold touch of an account known to have no code (as specified in [EIP-2780](/EIPs/EIPS/eip-2780)), 
* 1000 gas – one account-leaf write in the account trie (as specified in [EIP-2780](/EIPs/EIPS/eip-2780)), 
* 704 gas – an [EIP-4895](/EIPs/EIPS/eip-4895) withdrawal {index: uint64, validator_index: uint64, address: bytes20, amount: uint64}, consisting of $8 + 8 + 20 + 8 = 44$ bytes, priced analogously to calldata at 16 gas/byte.

It can be noted that we are not with this accounting charging for the CL work that `0x01` validators impose due to the sweep. We are neither charging `0x02` validators for the CL work of EL-triggered partial withdrawals via [EIP-7002](/EIPs/EIPS/eip-7002), but they are charged more extensively on the EL for triggering the withdrawal. Further note that `2048`-ETH validators are exempted in the specification from the sweep withdrawal fee, to avoid harming consolidation, and as an acknowledgement that `2048` ETH is the maximum stake that the protocol currently is designed to handle.

### Capital efficiency and opportunity cost

Besides free withdrawals, another benefit of `0x01` validators is the capital efficiency. A compounding `0x02` validator will on average have 0.75 ETH sitting idle, not counting toward the effective balance (EB). This is due to the current hysteresis design, where a validator that gradually increases its balance will hold between 0.25 to 1.25 more ETH than their EB. A `0x01` validator will on average have just $0.0235/2 = 0.01175$ ETH idle, and are thus much more capital-efficient, particularly when the compounding `0x02` validator holds a moderate balance overall.

Figure 1 illustrates the change in yield relative to a baseline with a neutral EB design, where, as the balance compounds, it is on average equal to the EB. The blue line is the yield of compounding `0x02` validators, which receive a lower yield due to the on average 0.75 ETH lower EB than the balance. The green circles are the yield that skimming 32-ETH and 2048-ETH validators receive. The orange line is the fee imposed on `0x01` validators proposed in the main specification. As evident, this fee does not fully offset the loss due to yield drag for `0x02` validators at validator balances below around 1,000 ETH. 

![Figure 1](/EIPs/assets/eip-8062/1.png)

**Figure 1.** Relative change in staking yield due to differences in capital efficiency of different validator configurations. The proposed fee is shown in orange.

[EIP-8068](/EIPs/EIPS/eip-8068) addresses differences in capital efficiency between `0x01` and `0x02` validators with a neutral EB design, where the hysteresis threshold raises the EB at +0.5. This effectively shifts the blue line, positioning all compounding validators at the black line. 

If EIP-8068 is not included in the same hardfork as this EIP, we could instead raise the withdrawal fee to compensate. The alternative specification below therefore outlines a higher fee. This will however not address the other concern addressed by EIP-8068: a `0x02` validator can leverage the hysteresis and make a partial withdrawal once having reached 33 ETH EB, such that they only need to hold 32.75 ETH while keeping 33 ETH EB. This concern can, on the other hand, also be addressed on its own for minimal complexity, as outlined in the alternative specification of EIP-8068.

### Alternative specification

If EIP-8068 is not included in the same hardfork as this EIP, it is reasonable to compensate for the lower capital efficiency of `0x02` validators by setting a higher withdrawal fee. This way, stakers will be less likely to remain on their `0x01` validators just for the better capital efficiency. Figure 2 shows three different alternative fees with red lines. The white squares illustrate equal capital efficiency between a `0x01` validator under the proposed fee and a `0x02` validator at some specific validator balance. 

![Figure 2](/EIPs/assets/eip-8062/2.png)

**Figure 2.** Relative change in staking yield due to differences in capital efficiency of different validator configurations. The main proposed fee is shown in orange, and alternative fees are shown in red.

The main option shown by the full red line is to raise the fee from 0.05% to 0.5%, setting `WITHDRAWAL_FEE_FRACTION = 200`. This means that a 32-ETH `0x01` validator will have approximately the same capital efficiency as a 128-ETH `0x02` validator. A stronger option is to impose a 1% fee as shown by the dashed red line, setting `WITHDRAWAL_FEE_FRACTION = 100`. Under this option, consolidating to a `0x02` validator will always at least be neutral, if the staker runs more than one `0x01` validator. A less forceful option is shown by the red dotted line, instead setting `WITHDRAWAL_FEE_FRACTION = 400`.

Table 2 outlines the cost to stakers under the primary alternative specification with `WITHDRAWAL_FEE_FRACTION = 200`. Stakers then pay an additional $20 per validator. That means that an SSP running 5% of the stake would take a loss of around one million dollars per year, representing a much stronger incentive to consolidate.

| Validators (stake %) | Cost (ETH/year) | Cost (USD/year) |
| -                    | -:              | -:              |
| 1 (~0.0001%)         | 0.0048          | $20             |
| 100 (~0.01%)         | 0.48            | $2k             |
| 10k (~1%)            | 48              | $200k           |
| 50k (~5%)            | 240             | $1M             |
| 100k (~10%)          | 480             | $2M             |

**Table 2.** Cost to stakers under the alternative higher withdrawal fee of 0.5% (`WITHDRAWAL_FEE_FRACTION = 200`).

## Security Considerations

To the best of the authors&apos; knowledge, there are no security risks associated with the proposed fee.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 28 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8062</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8062</guid>
      </item>
    
      <item>
        <title>Groups - Membership Tokens</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8063-groups-multi-member-onchain-containers-for-shared-resources/25999</comments>
        
        <description>## Abstract

This proposal defines a &quot;Group&quot; as an [ERC-20](/EIPs/EIPS/eip-20) token where token balance represents membership level. Groups are standard ERC-20 tokens with the semantic interpretation that holding tokens means membership in the group. Unlike binary membership, this supports threshold-based membership: holding more tokens grants higher membership tiers or privileges. By being pure ERC-20, Groups inherit full compatibility with existing wallets, explorers, and tooling with no additional implementation burden.

## Motivation

Many applications need addressable groups of accounts with controlled membership and tiered access:
- **DAOs**: Voting power proportional to token holdings
- **Loyalty programs**: Bronze/Silver/Gold tiers based on token balance
- **Access control**: Different features unlocked at different balance thresholds
- **Partner networks**: Minimum token requirements for partnership benefits

The key insight is that **any ERC-20 token can represent group membership**:
- `balanceOf(account) == 0` → Not a member
- `balanceOf(account) &gt;= threshold` → Member at that tier

This approach provides:
- **Zero implementation overhead**: Any ERC-20 token can be a Group
- **Instant tooling compatibility**: Wallets, explorers, DEXs work out of the box
- **Tiered membership**: Different balance thresholds unlock different privileges
- **Transferable membership**: Standard ERC-20 transfers allow membership trading/delegation

## Specification

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

### Requirements

A compliant Group contract:

1. **MUST** implement [ERC-20](/EIPs/EIPS/eip-20)
2. **MUST** implement [ERC-165](/EIPs/EIPS/eip-165)
3. **SHOULD** implement the optional interface defined below for membership introspection

### Membership Semantics

Token balance represents membership level:
- `balanceOf(account) == 0` → Account is **not** a member
- `balanceOf(account) &gt; 0` → Account **is** a member
- `balanceOf(account) &gt;= threshold` → Account qualifies for that membership tier

Applications define their own thresholds. For example:
- Basic membership: `balanceOf(account) &gt;= 1`
- Silver tier: `balanceOf(account) &gt;= 100 * 10**decimals`
- Gold tier: `balanceOf(account) &gt;= 500 * 10**decimals`
- Platinum tier: `balanceOf(account) &gt;= 1000 * 10**decimals`

### Interface (Optional)

Implementations MAY expose a convenience interface for membership checks:

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.20;

/// @title IERC8063 — Optional membership introspection for ERC-20 tokens
interface IERC8063 {
    /// @notice Returns true if `account` holds at least `threshold` tokens
    /// @param account The address to check
    /// @param threshold Minimum balance required for membership at this tier
    function isMember(address account, uint256 threshold) external view returns (bool);
}
```

If implemented:
- `isMember(account, threshold)` MUST return `true` if and only if `balanceOf(account) &gt;= threshold`.
- `isMember(account, 0)` MUST return `true` for any account.

### ERC-165 Introspection

- `supportsInterface(0x36372b07)` (ERC-20) SHOULD return `true`
- If the optional interface is implemented, `supportsInterface` for it SHOULD return `true`

### Deployment Model

Following the [ERC-20](/EIPs/EIPS/eip-20) pattern, each group is its own contract deployment:

- **Group identity**: A group is uniquely identified by its contract address.
- **Deployment**: Deploy any ERC-20 token. The token IS the group.
- **Discovery**: Applications can discover groups through Transfer events, registries, or direct address references.
- **Naming**: `name()` and `symbol()` follow standard ERC-20 conventions.

### Minting and Burning

Minting and burning are **implementation-defined**. Groups MAY implement minting/burning using any approach:
- Standard `mint(address, uint256)` function
- [ERC-5679](/EIPs/EIPS/eip-5679) compliant `mint(address, uint256, bytes)`
- No minting after initial supply (fixed membership)
- Governance-controlled minting
- Open minting (anyone can join by minting)

The standard does not mandate any specific minting/burning interface.

### Tiered Benefits Example

Applications define membership tiers externally:

```solidity
// Example: Partner contract checking membership tiers
contract PartnerBenefits {
    IERC20 public membershipToken;
    
    uint256 public constant BRONZE = 100 * 10**18;
    uint256 public constant SILVER = 500 * 10**18;
    uint256 public constant GOLD = 1000 * 10**18;
    
    function getDiscount(address user) external view returns (uint256) {
        uint256 balance = membershipToken.balanceOf(user);
        if (balance &gt;= GOLD) return 30;   // 30% off
        if (balance &gt;= SILVER) return 20; // 20% off
        if (balance &gt;= BRONZE) return 10; // 10% off
        return 0;
    }
    
    function isMember(address user) external view returns (bool) {
        return membershipToken.balanceOf(user) &gt; 0;
    }
}
```

### Optional Extensions

#### Ownership (via [ERC-173](/EIPs/EIPS/eip-173))

Implementations that want a single-owner governance model MAY use [ERC-173](/EIPs/EIPS/eip-173) or [ERC-8023](/EIPs/EIPS/eip-8023) for standardized ownership.

#### Capped Membership (Balance ≤ 1)

For use cases requiring binary membership (member/non-member with no tiers), implementations MAY enforce `balanceOf(account) &lt;= 1` for all accounts.

## Rationale

- **Pure ERC-20**: A Group is simply an ERC-20 token with membership semantics. No new token standard needed.
- **No minting/burning mandate**: Different use cases need different minting policies. The standard doesn&apos;t prescribe one.
- **Threshold-based membership**: More flexible than binary membership; supports tiered access, loyalty programs, and proportional voting naturally.
- **Optional interface**: The `isMember` function is a convenience; applications can directly call `balanceOf` if preferred.
- **Maximum compatibility**: Any existing ERC-20 token can be interpreted as a Group by applications.

## Backwards Compatibility

This standard is fully backwards compatible with [ERC-20](/EIPs/EIPS/eip-20). In fact, **any existing ERC-20 token can be used as a Group** — the standard simply defines how to interpret token balance as membership.

## Reference Implementation

Reference contracts are provided in the `assets/` directory:

- [`IERC8063.sol`](/EIPs/assets/eip-8063/IERC8063.sol) — Interface definition
- [`ERC8063.sol`](/EIPs/assets/eip-8063/ERC8063.sol) — Reference implementation with membership helpers

## Security Considerations

- **Token economics**: Membership is tied to token balance. Consider the implications of token transfers, trading, and price volatility on membership.
- **Threshold manipulation**: If thresholds are stored onchain, ensure they cannot be manipulated by unauthorized parties.
- **Transfer implications**: Token transfers change membership. Consider whether this is desirable for your use case.
- **Approval risks**: Standard ERC-20 approval risks apply. Approving another address grants them ability to transfer your membership tokens.
- **Decimal handling**: Ensure thresholds account for the token&apos;s decimals.
- **Minting security**: If minting is permitted, carefully control who can mint to prevent unauthorized membership grants.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 28 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8063</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8063</guid>
      </item>
    
      <item>
        <title>Zero Knowledge Token Wrapper</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8065-zero-knowledge-token-wrapper/26006</comments>
        
        <description>## Abstract

This ERC defines a standard for the Zero Knowledge Token Wrapper, a wrapper that adds privacy to tokens — including [ERC-20](/EIPs/EIPS/eip-20), [ERC-721](/EIPs/EIPS/eip-721), [ERC-1155](/EIPs/EIPS/eip-1155) and [ERC-6909](/EIPs/EIPS/eip-6909) — while preserving all of the tokens&apos; original properties, such as transferability, tradability, and composability. It specifies [EIP-7503](/EIPs/EIPS/eip-7503)-style provable burn-and-remint flows, enabling users to break on-chain traceability and making privacy a native feature of all tokens on Ethereum.

## Motivation

Most existing tokens lack native privacy due to regulatory, technical, and issuer-side neglect. Users seeking privacy must rely on dedicated privacy blockchains or privacy-focused dApps, which restrict token usability, reduce composability, limit supported token types, impose whitelists, and constrain privacy schemes.

This ERC takes a different approach by introducing a zero knowledge token wrapper that preserves the underlying token’s properties while adding privacy. Its primary goals are:

- Pluggable privacy: the wrapper preserves all properties of the underlying token while adding privacy.
- Permissionless privacy: any user can wrap any token into a Zero Knowledge Wrapped Token (ZWToken).
- Broad token support: compatible with both fungible tokens (e.g., ETH, ERC-20) and non-fungible tokens (e.g., ERC-721).
- EIP-7503-style privacy: supports provable burn-and-remint flows to achieve high-level privacy.
- Compatibility with multiple EIP-7503 schemes: supports different provable burn address generation methods and commitment schemes (e.g., Ethereum-native MPT state tree or contract-managed commitments).

## Specification

The key words **MUST**, **MUST NOT**, **SHOULD**, **SHOULD NOT**, and **MAY** in this document are to be interpreted as described in RFC 2119 and RFC 8174.

### Overview

A Zero Knowledge Wrapped Token (ZWToken) is a wrapped token minted by a Zero Knowledge Token Wrapper. It adds a commitment-based privacy layer to existing tokens, including ERC-20, ERC-721, ERC-1155, ERC-6909. This privacy layer allows private transfers without modifying the underlying token standard, while preserving full composability with existing Ethereum infrastructure.

The commitment mechanism underlying this privacy layer may be implemented using Merkle trees, cryptographic accumulators, or any other verifiable cryptographic structure.

A Zero Knowledge Wrapped Token (ZWToken) provides the following core functionalities:

The ZWToken recipient can be a provable burn address, from which the tokens can later be reminted.

- Deposit: Wraps an existing token and mints ZWToken to the specified recipient.
- Transfer: Transfers ZWToken to the specified recipient.
- Remint: Mints new ZWTokens to the specified recipient after verifying a zero-knowledge proof demonstrating ownership of previously burnt tokens, without revealing the link between them.
- Withdraw: Burns ZWTokens to redeem the underlying tokens to the specified recipient.

#### Privacy Features by Token Type

For fungible tokens (FTs), e.g., ERC-20:

- This ERC enables breaking the traceability of fund flows through the burn and remint processes.
- The use of provable burn addresses hides the true holder of fungible tokens until the holder performs a withdraw operation of ZWToken.

For non-fungible tokens (NFTs), e.g., ERC-721:

- This ERC **cannot** break the traceability of fund flows through burn and remint, since each NFT is unique and cannot participate in coin-mixing.
- However, the use of provable burn addresses can still conceal the true holder of the NFT until the holder performs a withdraw operation of ZWToken.

#### ZWToken-aware Workflow

In the ZWToken-aware workflow, both the user and the system explicitly recognize and interact with ZWToken. ZWToken inherits all functional properties of the underlying token.

![](/EIPs/assets/eip-8065/flow1.svg)

For example, if the underlying token is ERC-20, ZWToken can be traded on DEXs, used for swaps, liquidity provision, or standard transfers. Similar to how holding WETH provides additional benefits over holding ETH directly, users may prefer to hold ZWToken rather than the underlying token.

#### ZWToken-unaware Workflow

This ERC also supports a ZWToken-unaware workflow. In this mode, all transfers are internally handled through ZWToken, but users remain unaware of its existence.

![](/EIPs/assets/eip-8065/flow2.svg)

ZWToken functions transparently beneath the user interface, reducing the number of required contract interactions and improving overall user experience for those who prefer not to hold ZWToken directly.

#### Alternative Workflows

The two workflows described above represent only a subset of the interaction patterns supported by this ERC. Additional workflows are also possible, including:

- **Reminting by the recipient:**
  Alice may `transfer` (in the ZWToken-aware workflow) or `deposit` (in the ZWToken-unaware workflow) ZWToken to **Bob’s provable burn address** instead of her own. In this case, the **remint operation is initiated and proven by Bob rather than Alice**.

- **Recursive reminting:**  
  A reminted ZWToken may also be sent to **another provable burn address** controlled by Bob instead of his public address, allowing the privacy state to persist across multiple remint cycles.

The interface:

```solidity
interface IERC8065 is IERC165 {
    struct RemintData {
        bytes32 commitment;
        bytes32[] nullifiers;
        bytes proverData;
        bytes relayerData;
        bool redeem;
        bytes proof;
    }

    // Optional
    event CommitmentUpdated(uint256 indexed id, bytes32 indexed commitment, address indexed to, uint256 amount);

    event Deposited(address indexed from, address indexed to, uint256 indexed id, uint256 amount);

    event Withdrawn(address indexed from, address indexed to, uint256 indexed id, uint256 amount);

    event Reminted(address indexed from, address indexed to, uint256 indexed id, uint256 amount, bool redeem);

    function deposit(address to, uint256 id, uint256 amount, bytes calldata data) external payable;

    function withdraw(address to, uint256 id, uint256 amount, bytes calldata data) external;

    function remint(
        address to,
        uint256 id,
        uint256 amount,
        RemintData calldata data
    ) external;

    // Optional
    function previewDeposit(address to, uint256 id, uint256 amount, bytes calldata data) external view returns (uint256);

    // Optional
    function previewWithdraw(address to, uint256 id, uint256 amount, bytes calldata data) external view returns (uint256);

    // Optional
    function previewRemint(address to, uint256 id, uint256 amount, RemintData calldata data) external view returns (uint256);

    function getLatestCommitment(uint256 id) external view returns (bytes32);

    function hasCommitment(uint256 id, bytes32 commitment) external view returns (bool);

    // Optional
    function getCommitLeafCount(uint256 id) external view returns (uint256);

    // Optional
    function getCommitLeaves(uint256 id, uint256 startIndex, uint256 length)
    external view returns (bytes32[] memory commitHashes, address[] memory recipients, uint256[] memory amounts);

    function getUnderlying() external view returns (address);
}
```

### Deposit / Wrap

```solidity
/// @notice Deposits a specified amount of the underlying asset and mints the corresponding amount of ZWToken to the given address.
/// @dev
/// If the underlying asset is an ERC-20/ERC-721/ERC-1155/ERC-6909 token, the caller must approve this contract to transfer the specified `amount` beforehand.
/// If the underlying asset is ETH, the caller should send the deposit value along with the transaction (`msg.value`), and `msg.value` MUST be equal to `amount`.
/// @param to The address that will receive the minted ZWTokens.
/// @param id The token identifier. For fungible tokens that do not have `id`, such as ERC-20, this value MUST be set to `0`.
/// @param amount The amount of the underlying asset to deposit.
/// @param data Additional data for extensibility, such as fee information, callback data, or metadata.
function deposit(address to, uint256 id, uint256 amount, bytes calldata data) external payable;
```

- Depositor SHOULD be `msg.sender`.
- The function MUST transfer the specified `amount` of the underlying asset from `depositor` to the ZWToken contract.
  - If the underlying asset is an ERC-20, ERC-721, ERC-1155 or ERC-6909 token, the caller MUST approve this contract to transfer the specified `amount` beforehand.
  - If the underlying asset is ETH, the caller MUST send the deposit value along with the transaction (`msg.value`), and `msg.value` MUST be equal to `amount`.
- The function SHOULD mint ZWToken to the recipient `to`. The amount minted MAY be reduced by fees as defined by the implementation.
- Commitment Update:

  - For contract-level commitment schemes, since to may be a provable burn address, the implementation SHOULD update the corresponding commitment.
    - However, this MAY be optimized: if `to` == `depositor`, the implementation MAY skip updating the commitment, as `depositor` cannot be a provable burn address (otherwise the transaction could not be initiated).
  - For protocol-level commitment schemes (e.g., Ethereum’s native Merkle Patricia Trie), the commitment (e.g., state root or block hash) is automatically updated by the protocol.

- The function MUST emit a `Deposited(depositor, to, id, amount)` event upon successful deposit.
  - The `amount` parameter in the `Deposited` event represents the net amount of ZWToken received by `to` after deducting applicable fees, rather than the amount of underlying tokens deposited.
- The `data` parameter is reserved for future extensibility and MAY be used to pass additional information such as fee configurations, callback data, or metadata. Implementations MAY ignore this parameter if not needed.

### Withdraw / Unwrap

```solidity
/// @notice Withdraw underlying tokens by burning ZWToken
/// @param to The recipient address that will receive the underlying token
/// @param id The token identifier. For fungible tokens that do not have `id`, such as ERC-20, this value MUST be set to `0`.
/// @param amount The amount of ZWToken to burn and redeem for the underlying token
/// @param data Additional data for extensibility, such as fee information, callback data, or metadata.
function withdraw(address to, uint256 id, uint256 amount, bytes calldata data) external;
```

- Withdrawer SHOULD be `msg.sender`.
- The function MUST burn the specified `amount` of ZWToken from withdrawer.
- The function SHOULD transfer underlying token to the recipient `to`. The amount transferred MAY be reduced by fees as defined by the implementation.
- The function MUST emit a `Withdrawn(withdrawer, to, id, amount)` event upon successful withdrawal.
  - The `amount` parameter in the `Withdrawn` event represents the net amount of underlying tokens received by `to` after deducting applicable fees, rather than the amount of ZWToken burned.
- The `data` parameter is reserved for future extensibility and MAY be used to pass additional information such as fee configurations, callback data, or metadata. Implementations MAY ignore this parameter if not needed.

### Transfer and Update Commitment

- The Zero Knowledge Wrapped Token (ZWToken) remains fully compatible with the underlying token’s transfer interface, while extending it to support privacy-preserving operations.
  - When a ZWToken is transferred to a provable burn address, those tokens MUST be eligible for reminting through the remint interface, effectively breaking the traceability of the fund flow.
  - A provable burn address MAY take various forms (e.g., as defined in EIP-7503). Its essential properties are:
    - Such addresses MUST NOT be operable by any user and MUST be provably non-correspondent to any externally owned account (EOA) or smart contract.
    - Only the entity that generates the burn address MAY derive it, for example, through a signature-derived or deterministic generation scheme.
- Commitment Update:
  - For commitment schemes maintained at the contract level:
    - If the recipient is identified as a provable burn address, the contract MUST update the commitment.
      - Example — a recipient that has previously sent any ZWToken MUST NOT be a provable burn address, since such addresses are incapable of initiating outgoing transfers. In this case, commitment update is not required.
  - For protocol-level commitment schemes (e.g., Ethereum’s native MPT tree), the contract does not need to manage any commitment state, since the protocol layer already provides verifiable commitment structures.

### Remint

```solidity
/// @notice Encapsulates all data required for remint operations
/// @param commitment The commitment (Merkle root) corresponding to the provided proof
/// @param nullifiers Array of unique nullifiers used to prevent double-remint
/// @param proverData Generic data for the prover. The meaning and encoding are implementation-specific (e.g., a circuit identifier/version).
/// @param relayerData Generic data for the relayer. The meaning and encoding are implementation-specific (e.g., fee information).
/// @param redeem If true, withdraws the equivalent underlying token instead of reminting ZWToken
/// @param proof Zero-knowledge proof bytes verifying ownership of the provable burn address
struct RemintData {
    bytes32 commitment;
    bytes32[] nullifiers;
    bytes proverData;
    bytes relayerData;
    bool redeem;
    bytes proof;
}

/// @notice Remint ZWToken using a zero-knowledge proof to unlink the source of funds
/// @param to Recipient address that will receive the reminted ZWToken or the underlying token
/// @param id The token identifier. For fungible tokens that do not have `id`, such as ERC-20, this value MUST be set to `0`.
/// @param amount Amount of ZWToken burned from the provable burn address for reminting
/// @param data Encapsulated remint data including commitment, nullifiers, redeem flag, proof, and relayer information
function remint(
    address to,
    uint256 id,
    uint256 amount,
    RemintData calldata data
) external;
```

- The function MUST verify the zero-knowledge proof proof against the provided commitment to ensure:

  - Ownership of the provable burn address.
  - Correctness parameters of `remint`, i.e., the zk proof public inputs.
    ```solidity
      address to,
      uint256 id,
      uint256 amount,
      RemintData calldata data // All fields except data.proof are used as public inputs for zk proof verification
    ```

- Reminter SHOULD be `msg.sender`.
- The function MUST validate the input `data.commitment` to ensure it exists.
- The function MUST ensure that none of the `data.nullifiers` have been used previously. Reuse of any nullifier MUST revert the transaction.
  - This supports batch reminting in a single proof by allowing multiple nullifiers to be provided and consumed atomically.
- Upon successful verification:

  - If `data.redeem` is false, the function MUST mint ZWToken to the recipient `to`. The amount minted MAY be reduced by fees as defined by the implementation.
    - In this case, the function MUST emit the `Reminted` event after a successful remint of ZWToken.
  - If `data.redeem` is true, the function MUST transfer underlying token to the recipient `to`. The amount transferred MAY be reduced by fees as defined by the implementation.
    - In this case, the function MUST emit the `Reminted` event after a successful withdrawal of the underlying token.
  - The net tokens received by the recipient `to` MAY be reduced by relayer fees if the relayer charges a fee (as specified in `data.relayerData`).
  - The function MUST mark **each** nullifier in `data.nullifiers` as spent to prevent double-spending.

- The function MUST emit a `Reminted(reminter, to, id, amount, data.redeem)` event upon successful remint.
  - The `amount` parameter in the `Reminted` event represents the net amount of underlying tokens or ZWToken received by `to` after all applicable fees have been deducted.

### Preview Functions (Optional)

Since the actual token amounts received may differ from the input amounts due to implementation-specific factors (e.g., fees), users need a standardized way to determine the exact amounts they will receive. Following the design pattern established by [ERC-4626](/EIPs/EIPS/eip-4626), the preview functions allow users to simulate the effects of their operations at the current block, returning values as close to and no more than the exact amounts that would result from the corresponding mutable operations if called in the same transaction.

```solidity
/// @notice OPTIONAL: Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block.
/// @dev MUST return as close to and no more than the exact amount of ZWToken that would be minted in a `deposit` call in the same transaction.
/// @param to The address that will receive the minted ZWTokens.
/// @param id The token identifier. For fungible tokens that do not have `id`, such as ERC-20, this value MUST be set to `0`.
/// @param amount The amount of underlying tokens to deposit.
/// @param data Additional data for extensibility, such as fee information.
/// @return The amount of ZWToken that would be minted to the recipient after deducting applicable fees.
function previewDeposit(address to, uint256 id, uint256 amount, bytes calldata data) external view returns (uint256);
```

- `previewDeposit(address to, uint256 id, uint256 amount, bytes calldata data)`: OPTIONAL. Returns the exact amount of ZWToken that would be minted for the specified amount of underlying tokens.
  - MUST be inclusive of deposit fees. Integrators SHOULD be aware of the existence of deposit fees.
  - MUST NOT revert due to implementation-specific user/global limits.
  - MAY revert due to other conditions that would also cause `deposit` to revert.

```solidity
/// @notice OPTIONAL: Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block.
/// @dev MUST return as close to and no more than the exact amount of underlying tokens that would be received in a `withdraw` call in the same transaction.
/// @param to The recipient address that will receive the underlying token.
/// @param id The token identifier. For fungible tokens that do not have `id`, such as ERC-20, this value MUST be set to `0`.
/// @param amount The amount of ZWToken to burn.
/// @param data Additional data for extensibility, such as fee information.
/// @return The amount of underlying tokens that would be received by the recipient after deducting applicable fees.
function previewWithdraw(address to, uint256 id, uint256 amount, bytes calldata data) external view returns (uint256);
```

- `previewWithdraw(address to, uint256 id, uint256 amount, bytes calldata data)`: OPTIONAL. Returns the exact amount of underlying tokens that would be received for burning the specified amount of ZWToken.
  - MUST be inclusive of withdrawal fees. Integrators SHOULD be aware of the existence of withdrawal fees.
  - MUST NOT revert due to implementation-specific user/global limits.
  - MAY revert due to other conditions that would also cause `withdraw` to revert.

```solidity
/// @notice OPTIONAL: Allows an on-chain or off-chain user to simulate the effects of their remint at the current block.
/// @dev MUST return as close to and no more than the exact amount of ZWToken or underlying tokens that would be received in a `remint` call in the same transaction.
/// @param to Recipient address that will receive the reminted ZWToken or the underlying token.
/// @param id The token identifier. For fungible tokens that do not have `id`, such as ERC-20, this value MUST be set to `0`.
/// @param amount The amount of ZWToken burned from the provable burn address for reminting.
/// @param data Encapsulated remint data including commitment, nullifiers, redeem flag, proof, and relayer information.
/// @return The amount of ZWToken or underlying tokens that would be received by the recipient after all applicable fees have been deducted.
function previewRemint(address to, uint256 id, uint256 amount, RemintData calldata data) external view returns (uint256);
```

- `previewRemint(address to, uint256 id, uint256 amount, RemintData calldata data)`: OPTIONAL. Returns the exact amount of ZWToken (or underlying tokens if `data.redeem` is true) that would be received for a remint operation.
  - MUST be inclusive of all applicable fees, including remint fees and relayer fees (as specified in `data.relayerData`).
  - MUST NOT revert due to implementation-specific user/global limits.
  - MAY revert due to other conditions that would also cause `remint` to revert.

### Query Interfaces

```solidity
/// @notice Returns the current top-level commitment representing the privacy state
/// @param id The token identifier. For fungible tokens that do not have `id`, such as ERC-20, this value MUST be set to `0`.
/// @return The latest root hash of the commitment tree
function getLatestCommitment(uint256 id) external view returns (bytes32);

/// @notice Checks if a specific top-level commitment exists
/// @param id The token identifier. For fungible tokens that do not have `id`, such as ERC-20, this value MUST be set to `0`.
/// @param commitment The root hash to verify
/// @return True if the commitment exists, false otherwise
function hasCommitment(uint256 id, bytes32 commitment) external view returns (bool);

/// @notice OPTIONAL: Returns the total number of commitment leaves stored
/// @param id The token identifier. For fungible tokens that do not have `id`, such as ERC-20, this value MUST be set to `0`.
/// @return The total count of commitment leaves
function getCommitLeafCount(uint256 id) external view returns (uint256);

/// @notice OPTIONAL: Retrieves leaf-level commit data and their hashes
/// @param id The token identifier. For fungible tokens that do not have `id`, such as ERC-20, this value MUST be set to `0`.
/// @param startIndex Index of the first leaf to fetch
/// @param length Number of leaves to fetch
/// @return commitHashes Hashes of the leaf data
/// @return recipients Recipient addresses of each leaf
/// @return amounts Token amounts of each leaf
function getCommitLeaves(uint256 id, uint256 startIndex, uint256 length)
    external view returns (bytes32[] memory commitHashes, address[] memory recipients, uint256[] memory amounts);

/// @notice Returns the address of the underlying token wrapped by this ZWToken
/// @return The underlying token contract address, or address(0) if the underlying asset is ETH.
function getUnderlying() external view returns (address);
```

- `getLatestCommitment(uint256 id)`: MUST return the most recent top-level commitment associated with the specified token identifier, representing the current state of the ZWToken system.
  - For protocol-level commitments, the block number can be used as the commitment, as it can directly map to the block hash.
- `hasCommitment(uint256 id, bytes32 commitment)`: MUST check whether a specific top-level commitment associated with the specified token identifier exists in the contract.
  - For proving ownership of a provable burn address, it does not require the latest commitment.
  - For protocol-level commitments, the block number can be used as the commitment, as it can directly map to the block hash.
- `getCommitLeafCount(uint256 id)`: OPTIONAL. Returns the total number of leaf-level commitments, which helps `getCommitLeaves` retrieve the leaves. The returned value also represents the current size of the privacy pool.
- `getCommitLeaves(uint256 id, uint256 startIndex, uint256 length)`: OPTIONAL. Retrieves leaf-level commitment data from the commitment tree associated with the specified token identifier.

  - On-chain storage of commit data can be used to improve privacy and decentralization but will incur higher gas costs.
  - Event-based reconstruction can be used as an alternative, though it introduces potential centralization risks.

- `getUnderlying()`: MUST return the address of the underlying token that this ZWToken wraps.
  - If the underlying asset is ETH, MUST return `address(0)`.

### [ERC-165](/EIPs/EIPS/eip-165) Support

- Implementations of this ERC MUST implement ERC-165 interface detection.
- `supportsInterface(bytes4)` MUST return `true` for `type(IERC8065).interfaceId` (in addition to any other supported interfaces), allowing other contracts to reliably detect whether a token is a ZWToken wrapper.

### Events

```solidity
// Optional: Emitted when a contract-maintained commitment is updated
/// @notice OPTIONAL event emitted when a commitment is updated in the contract
/// @param id The token identifier. For fungible tokens that do not have `id`, such as ERC-20, this value MUST be set to `0`.
/// @param commitment The new top-level commitment hash
/// @param to The recipient address associated with the commitment
/// @param amount The amount related to this commitment update
event CommitmentUpdated(uint256 indexed id, bytes32 indexed commitment, address indexed to, uint256 amount);

/// @notice Emitted when underlying tokens are deposited and ZWToken is minted to the recipient
/// @param from The address sending the underlying tokens
/// @param to The address receiving the minted ZWToken (after fees)
/// @param id The token identifier. For fungible tokens that do not have `id`, such as ERC-20, this value MUST be set to `0`.
/// @param amount The net amount of ZWToken minted to `to` after deducting applicable fees
event Deposited(address indexed from, address indexed to, uint256 indexed id, uint256 amount);

/// @notice Emitted when ZWToken is burned to redeem underlying tokens to the recipient
/// @param from The address burning the ZWToken
/// @param to The address receiving the redeemed underlying tokens (after fees)
/// @param id The token identifier. For fungible tokens that do not have `id`, such as ERC-20, this value MUST be set to `0`.
/// @param amount The net amount of underlying tokens received by `to` after deducting applicable fees
event Withdrawn(address indexed from, address indexed to, uint256 indexed id, uint256 amount);

/// @notice Emitted upon successful reminting of ZWToken or withdrawal of underlying tokens via a zero-knowledge proof
/// @param from The address initiating the remint operation
/// @param to The address receiving the reminted ZWToken or withdrawn underlying tokens (after fees)
/// @param id The token identifier. For fungible tokens that do not have `id`, such as ERC-20, this value MUST be set to `0`.
/// @param amount The net amount of ZWToken or underlying tokens received by `to` after all applicable fees have been deducted
/// @param redeem If true, withdraws the equivalent underlying tokens instead of reminting ZWToken
event Reminted(address indexed from, address indexed to, uint256 indexed id, uint256 amount, bool redeem);
```

- `CommitmentUpdated(uint256 indexed id, bytes32 indexed commitment, address indexed to, uint256 amount)` is OPTIONAL and may be emitted when a contract-maintained commitment is updated, such as when ZWToken is sent to a potential provable burn address. It allows users to reconstruct commitments and generate zero-knowledge proofs, where `id` is the token identifier, `commitment` is the new commitment, `to` is the recipient, and `amount` is the committed token amount.

- `Deposited(address indexed from, address indexed to, uint256 indexed id, uint256 amount)` signals that underlying tokens have been deposited and ZWToken minted to the recipient, where `from` is the sender, `to` is the recipient, `id` is the token identifier and `amount` is the net amount of ZWToken minted to `to` after deducting applicable fees.

- `Withdrawn(address indexed from, address indexed to, uint256 indexed id, uint256 amount)` signals that ZWToken has been burned to redeem underlying tokens to the recipient, where `from` is the burner, `to` is the receiver, `id` is the token identifier and `amount` is the net amount of underlying tokens received by `to` after deducting applicable fees.

- `Reminted(address indexed from, address indexed to, uint256 indexed id, uint256 amount, bool redeem)` MUST be emitted upon successful reminting of ZWToken or withdrawal of underlying tokens via a zero-knowledge proof, where `from` is the reminter, `to` is the recipient, `id` is the token identifier and `amount` is the net amount of ZWToken or underlying tokens received by `to` after all applicable fees have been deducted.

## Rationale

- Permissionless Wrapping: Launching a new zk-native token is unlikely to achieve sufficient liquidity or adoption, and major token issuers are unlikely to deploy zk variants due to regulatory and operational constraints. A permissionless wrapper makes privacy a native feature for existing tokens. ZWToken does not require issuer consent—any existing token can be wrapped, ensuring openness and equal accessibility regardless of issuer policies.
- Composable Privacy: Wrapped tokens remain fully compatible with their underlying token standards, preserving interoperability across the Ethereum ecosystem. Users and dApps can treat ZWToken as the underlying token when privacy is not required, making privacy an optional and composable extension rather than a separate system.
- Awareness of ZWToken: This ERC supports both ZWToken-aware and ZWToken-unaware workflows, each with distinct advantages. In the ZWToken-aware workflow, ZWToken inherits all functional properties of the underlying token and can interact seamlessly with existing DeFi protocols. In the ZWToken-unaware workflow, ZWToken operates transparently beneath the user interface, reducing the number of required contract interactions and improving user experience for those who prefer not to hold ZWToken directly.
- Multiple Token Standard Support: This ERC only depends on the transferability of the underlying token, enabling broad compatibility with token standards such as ERC-20, ERC-721, ERC-1155, and ERC-6909. Non-transferable tokens (e.g., Soulbound Tokens, SBTs) are out of scope. Implementations may require extra care for:
  - Fee-on-transfer tokens.
  - Rebasing tokens (consider wrapping an existing non-rebasing wrapper to avoid rebase-handling complexity).
- Fee Mechanisms: Fee structures are implementation-specific and not defined by this ERC. Implementations MAY apply fees during deposit, remint, or withdraw phases, and MAY support various fee models (e.g., fixed fees, percentage-based fees, or no fees).
- Relayer-Enabled Remint: This ERC supports relayer functionality, allowing third parties to submit remint transactions on behalf of users while receiving a fee. This design mitigates privacy leakage caused by revealing the original sender&apos;s address when paying gas fees.

- Data Extensibility:

  - The meaning and encoding of `proverData` and `relayerData` are implementation-specific.
  - Implementations MAY encode prover-specific metadata in `data.proverData` (e.g., a circuit identifier/version, a proving key identifier, or packed auxiliary public inputs).
  - Implementations MAY encode relayer-specific metadata in `data.relayerData` (e.g., fee information, a fee token, or other fee model parameters).
  - A single universal encoding is impractical because proving schemes and relayer compensation models can vary significantly.
  - If cross-implementation interoperability is desired, a separate ERC (or profile) SHOULD standardize encoding(s) for `proverData` and/or `relayerData`.

- Commitment Generalization: The ERC adopts a generic commitment abstraction, supporting various schemes such as Merkle trees or other verifiable cryptographic accumulators. This flexibility enables developers to adapt the standard to different privacy or scalability trade-offs.
- Proof System Generalization: Proofs are passed as bytes calldata, allowing the use of SNARKs, STARKs, or any other zero-knowledge proof system, ensuring future-proof interoperability across cryptographic frameworks.
- Provable Burn Address Generalization: This ERC does not prescribe a specific method for generating Provable Burn Addresses, as long as the following conditions are met. One example is adopting zk-friendly hash functions such as Poseidon to replace keccak256 in the address generation algorithm.
  - Such addresses MUST NOT be operable by any user and MUST be provably non-correspondent to any externally owned account (EOA) or smart contract.
  - Only the entity that generates the burn address MAY derive it, for example through a signature-derived or deterministic generation scheme.
- Dual Commitment Options: The ERC supports both contract-maintained commitments and protocol-level commitments (using blockhash as the commitment).
  - Contract-maintained commitments reduce proof complexity, allowing smaller ZK circuits and enabling proof generation directly in browsers or mobile devices, at the cost of higher gas consumption during transfers.
  - Using blockhash as the commitment eliminates on-chain maintenance overhead but increases the complexity of off-chain proof generation.
- Preview Functions: Following the design pattern established by [ERC-4626](/EIPs/EIPS/eip-4626), this ERC includes optional preview functions (`previewDeposit`, `previewWithdraw`, `previewRemint`) that simulate the exact outcomes of their corresponding mutable operations.
  - Since the actual token amounts received may differ from the input amounts due to implementation-specific factors (e.g., fees), users and integrators need a standardized way to determine the exact amounts.
  - These functions provide a standardized interface for querying the net token amounts, enabling accurate UX displays and informed decision-making before executing transactions.
  - Each preview function mirrors the parameters of its corresponding mutable operation to ensure accurate calculations that may depend on any of these parameters.

## Backwards Compatibility

This ERC introduces no breaking changes. It extends the functionality of the underlying token without modifying or overriding its base interfaces.

## Reference Implementation

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {ERC20} from &quot;@openzeppelin/contracts/token/ERC20/ERC20.sol&quot;;
import {IERC20} from &quot;@openzeppelin/contracts/token/ERC20/IERC20.sol&quot;;
import {SafeERC20} from &quot;@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol&quot;;
import {ERC165} from &quot;@openzeppelin/contracts/utils/introspection/ERC165.sol&quot;;
import {IERC165} from &quot;@openzeppelin/contracts/utils/introspection/IERC165.sol&quot;;

interface IVerifier {
    function verifyProof(
        bytes calldata proof,
        uint256[] calldata input
    ) external view returns (bool);
}

contract ZWToken is IERC8065, ERC20, ERC165 {
    using SafeERC20 for IERC20;

    IERC20 public immutable underlying;
    IVerifier public immutable verifier;

    mapping(bytes32 =&gt; bool) public usedNullifier;

    event Deposited(address indexed from, address indexed to, uint256 indexed id, uint256 amount);
    event Withdrawn(address indexed from, address indexed to, uint256 indexed id, uint256 amount);
    event Reminted(address indexed from, address indexed to, uint256 indexed id, uint256 amount, bool redeem);

    constructor(
        string memory name_,
        string memory symbol_,
        address underlying_,
        address verifier_
    ) ERC20(name_, symbol_) {
        require(underlying_ != address(0), &quot;Invalid underlying&quot;);
        require(verifier_ != address(0), &quot;Invalid verifier&quot;);
        underlying = IERC20(underlying_);
        verifier = IVerifier(verifier_);
    }

    function deposit(address to, uint256 id, uint256 amount, bytes calldata /*data*/) external payable override {
        require(amount &gt; 0, &quot;amount must &gt; 0&quot;);
        require(id == 0, &quot;id must be 0 for ERC20&quot;);
        underlying.safeTransferFrom(msg.sender, address(this), amount);
        _mint(to, amount);
        emit Deposited(msg.sender, to, id, amount);
    }

    function withdraw(address to, uint256 id, uint256 amount, bytes calldata /*data*/) external override {
        require(amount &gt; 0, &quot;amount must &gt; 0&quot;);
        require(id == 0, &quot;id must be 0 for ERC20&quot;);
        _burn(msg.sender, amount);
        underlying.safeTransfer(to, amount);
        emit Withdrawn(msg.sender, to, id, amount);
    }

    function remint(
        address to,
        uint256 id,
        uint256 amount,
        IERC8065.RemintData calldata data
    ) external override {
        require(id == 0, &quot;id must be 0 for ERC20&quot;);
        // NOTE: This reference implementation uses a verifier circuit that consumes a single nullifier as a public input.
        // The ERC-8065 specification allows `data.nullifiers` to contain multiple nullifiers so implementations can
        // support batch reminting (consuming multiple nullifiers atomically within one proof).
        require(data.nullifiers.length == 1, &quot;Only single nullifier supported&quot;);
        bytes32 nullifier = data.nullifiers[0];
        require(!usedNullifier[nullifier], &quot;nullifier used&quot;);

        bytes32 headerHash = blockhash(uint256(data.commitment));
        require(headerHash != bytes32(0), &quot;commitment not found&quot;);

        // Example encoding (implementation-specific):
        // if relayerData.length &gt;= 32, first 32 bytes are interpreted as relayerFee (uint256)
        uint256 relayerFee = 0;
        if (data.relayerData.length &gt;= 32) {
            assembly {
                relayerFee := calldataload(data.relayerData.offset)
            }
        }

        // Replay protection by chain id and contract address is handled externally––
        // they MUST be included as parameters when generating the provable burn address and proof.
        // (For example, the Poseidon hash that defines the burn address should incorporate these values.)
        // No contract-side enforcement is implemented here.
        uint256[] memory input = new uint256[](7);
        input[0] = uint256(headerHash);
        input[1] = uint256(nullifier);
        input[2] = uint256(uint160(to));
        input[3] = uint256(id);
        input[4] = uint256(amount);
        input[5] = uint256(data.redeem ? 1 : 0);
        input[6] = uint256(relayerFee);

        require(verifier.verifyProof(data.proof, input), &quot;bad proof&quot;);

        usedNullifier[nullifier] = true;

        // Fee handling is implementation-specific
        // This example implementation applies only relayer fees (parsed from relayerData above)
        // In this example, relayerFee is interpreted as a percentage with denominator 10000
        uint256 remain = amount;
        if (relayerFee &gt; 0) {
            uint256 feeDenominator = 10000;
            require(relayerFee &lt; feeDenominator, &quot;invalid relayer fee&quot;);
            remain = amount - amount * relayerFee / feeDenominator;
            require(remain &gt; 0, &quot;invalid remain&quot;);
        }

        if (data.redeem) {
            underlying.safeTransfer(to, remain);
            if (relayerFee &gt; 0) {
                underlying.safeTransfer(msg.sender, amount - remain);
            }
        } else {
            _mint(to, remain);
            if (relayerFee &gt; 0) {
                _mint(msg.sender, amount - remain);
            }
        }
        emit Reminted(msg.sender, to, id, remain, data.redeem);
    }

    function getLatestCommitment(uint256 id) external view override returns (bytes32) {
        require(id == 0, &quot;id must be 0 for ERC20&quot;);
        return bytes32(block.number);
    }

    function hasCommitment(uint256 id, bytes32 commitment) external view override returns (bool) {
        require(id == 0, &quot;id must be 0 for ERC20&quot;);
        bytes32 headerHash = blockhash(uint256(commitment));
        return headerHash != bytes32(0);
    }

    function getUnderlying() external view override returns (address) {
        return address(underlying);
    }

    // Optional preview functions
    function previewDeposit(address /*to*/, uint256 id, uint256 amount, bytes calldata /*data*/) external view returns (uint256) {
        require(id == 0, &quot;id must be 0 for ERC20&quot;);
        // This example implementation has no deposit fees, so the output equals the input.
        // Implementations with fees SHOULD deduct them here.
        return amount;
    }

    function previewWithdraw(address /*to*/, uint256 id, uint256 amount, bytes calldata /*data*/) external view returns (uint256) {
        require(id == 0, &quot;id must be 0 for ERC20&quot;);
        // This example implementation has no withdrawal fees, so the output equals the input.
        // Implementations with fees SHOULD deduct them here.
        return amount;
    }

    function previewRemint(address /*to*/, uint256 id, uint256 amount, IERC8065.RemintData calldata data) external view returns (uint256) {
        require(id == 0, &quot;id must be 0 for ERC20&quot;);
        // Example encoding (implementation-specific):
        // Parse relayerFee from relayerData (if provided)
        uint256 relayerFee = 0;
        if (data.relayerData.length &gt;= 32) {
            relayerFee = abi.decode(data.relayerData[:32], (uint256));
        }
        // Apply relayer fee (percentage with denominator 10000)
        uint256 remain = amount;
        if (relayerFee &gt; 0) {
            uint256 feeDenominator = 10000;
            require(relayerFee &lt; feeDenominator, &quot;invalid relayer fee&quot;);
            remain = amount - amount * relayerFee / feeDenominator;
        }
        return remain;
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(ERC165, IERC165)
        returns (bool)
    {
        return interfaceId == type(IERC8065).interfaceId || super.supportsInterface(interfaceId);
    }
}
```

## Security Considerations

- Double-Remint Prevention: Each remint operation MUST include one or more unique nullifiers (`data.nullifiers`) to prevent double-remint attacks.
  - Reusing any nullifier MUST revert.
  - On success, all provided nullifiers MUST be marked as spent.
- Over-Minting Protection: The total supply of ZWToken MAY temporarily exceed the supply of the underlying token. However, the surplus represents provably burnt tokens, which are permanently removed from circulation and cannot be redeemed.
- Local Proof Generation: Circuits SHOULD remain as small and efficient as possible to enable users to generate zero-knowledge proofs locally (e.g., within browsers or mobile devices). This minimizes reliance on third-party provers that may introduce privacy leakage risks.
- Provable Burn Address Security: Provable burn addresses MAY follow different generation schemes (e.g., as proposed in EIP-7503). The essential properties are:
  - These addresses MUST be non-operable and provably non-correspondent to any externally owned account (EOA) or smart contract.
  - Only the generator of the burn address MAY deterministically derive it, for instance, through a signature-derived scheme.
  - Implementations SHOULD prefer zk-friendly hash functions (e.g., Poseidon) in place of keccak256 to improve proof efficiency and reduce circuit size.
- Burn and Remint Process Privacy:

  - Burn amounts SHOULD appear indistinguishable from ordinary transfers to prevent correlation with remint amounts.
  - Burn and remint events SHOULD be separated in time to reduce linkability.
  - Each burn operation MUST use a unique Provable Burn Address that can be used only once.

- Fully On-Chain Operation: The protocol operates entirely on-chain and requires no trusted backend. It can be directly integrated into wallets or dApps without introducing custodial or centralized dependencies.
- Commit Data Privacy: When generating proofs, users SHOULD retrieve as much commitment data as possible to maximize anonymity. Relying on selective or limited data sources may allow inference of the specific commit path being proven, weakening privacy guarantees.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 18 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8065</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8065</guid>
      </item>
    
      <item>
        <title>Upgrade Mascots</title>
        <category>Informational/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8066-upgrade-mascots/26009</comments>
        
        <description>## Abstract

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 &quot;Mascot Wrestler&quot;).

## Motivation

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 headliner(s). By mandating emoji-representable mascots that are cute and non-offensive, this process:

- Enhances community participation and excitement around network upgrades.
- Creates opportunities for creative expression in upgrade event branding (e.g., watch parties, POAPs).
- Builds a consistent, whimsical tradition that differentiates Ethereum&apos;s upgrade narrative from other ecosystems.

## Specification

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

### 1. Mascot Requirements

- **Relevance**: The mascot **SHOULD** relate thematically to the network upgrade&apos;s headliner(s).
- **Representation**: The mascot **MUST** be expressible using one or more standard Unicode emojis (e.g., :panda: for the Merge).
- **Form**: The mascot **SHOULD** depict an animal (real, mythical, or stylized, but always animal-adjacent).
- **Tone**: The mascot **MUST NOT** be offensive (no depictions of violence, discrimination, or controversy) and **SHOULD** be inherently cute (e.g., avoiding aggressive or fearsome traits unless softened for adorability).

### 2. Roles and Responsibilities

- **Mascot Wrestler**: A self-selected community facilitator responsible for proposing, selecting, and adopting the mascot for a network upgrade. The role **MAY** rotate voluntarily per upgrade cycle to encourage diverse participation.
  - Duties include:
    - Soliciting and curating mascot candidates.
    - Facilitating selection processes.
    - Announcing the final mascot (e.g., Ethereum Magicians, All Core Devs).

- **Veto Powers**:
  - The Mascot Wrestler **MAY** veto any candidate mascot not meeting the mascot requirements above.
  - A rough consensus of client teams **MAY** veto the selected mascot, triggering fallback to the next-highest-ranked candidate mascot.

### 3. Selection Process

The Mascot Wrestler **SHALL** conduct selection using one or more community-appropriate mechanisms.

The process **MUST**:

- Run for a minimum of 7 days.
- Present at least 2 candidates.
- Rank finalists by popularity.
- Document results publicly.

If no consensus is reached, the Mascot Wrestler selects the top candidate by default, subject to veto.

### 4. Usage Guidelines

All uses **MUST** respect the network upgrade mascot&apos;s cute, non-offensive nature and credit original concept creators where applicable.

## Rationale

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&apos;s community ethos of approachability. The self-selected Mascot Wrestler role decentralizes coordination, leveraging vetoes for accountability. Selection flexibility accommodates Ethereum&apos;s decentralized governance evolution.

Alternatives considered:

- Fully onchain mandates: Too rigid for creative processes.
- No formal process: Risks ad-hoc or absent mascots.
- Non-animal options: Animals evoke universality and whimsy.

## Backwards Compatibility

This EIP does not directly change the Ethereum protocol. It formalizes part of the current network upgrade process.  Past upgrades (e.g., Shapella&apos;s owl :owl:) are retroactively honored if they fit the criteria; future upgrades **MUST** comply starting with the next hard fork post-adoption.

## Security Considerations

None

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 29 Oct 2024 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>Neutral effective balance design</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8068-neutral-effective-balance-design/26015</comments>
        
        <description>## Abstract

This EIP proposes a neutral effective balance (EB) design to ensure `0x01` (skimming) and `0x02` (compounding) validators receive equal yields. Currently, validators that compound their balance have poor capital efficiency and lower yields as their idle balance (not contributing to EB) is 0.75 ETH, significantly higher than that of skimming validators at near-zero. This disincentivizes stake consolidation critical to Ethereum&apos;s fast finality roadmap. Additionally, the current hysteresis rules allow `0x02` validators to game the hysteresis by keeping their balance below the EB. The increased profitability at lower balances could further harm consolidation. This proposal sets the EB hysteresis upward threshold to the neutral +0.5 and the downward threshold to +0.25. To prevent gaming after operations like partial withdrawals, the EB is reset to the floor of the balance, and a one-time `temporary_upward_threshold` set. This threshold is derived from an integral equation that ensures the average idle balance is zero as the validator&apos;s balance compounds up to the next integer.

## Motivation

The roadmap for fast finality hinges on stake consolidation, where staking service providers (SSPs) transition from running 32-ETH validators with `0x01` credentials to compounding validators with `0x02` credentials. A roadblock to this transition is that `0x01` validators have close-to-ideal capital efficiency, whereas `0x02` validators have poor capital efficiency during compounding. Furthermore, the optimal configuration for a `0x02` validator is to reduce its balance to 32.75 ETH and prevent it from compounding further. These incentives may lead Ethereum&apos;s fast-finality roadmap to be delayed. To prevent this, a neutral effective balance calculation is proposed, that sees all validator configurations earn the same CL yield.

A `0x02` validator that compounds its balance $b$ as intended will on average have 0.75 ETH of its balance not counting toward its effective balance (EB, or $E$ in equations). Specifically, with the current EB step bands, the idle remainder $r=b-E \in[0.25, 1.25)$ and $\bar{r}=(0.25+1.25)/2=0.75$. A `0x01` validator operating at 32 ETH has a much lower idle remainder, on average half the withdrawal sweep of $0.0235/2 = 0.01175$ ETH. A 32-ETH `0x01` validator will therefore earn around 2.3% more CL yield than a compounding `0x02` validator that grows from 32.25 ETH to 34.25 ETH over around two years.

A separate issue is that `0x02` validators can make a partial withdrawal down to 32.75 ETH when having any EB &gt;33 ETH, leveraging the hysteresis to retain a 33 ETH EB. The surplus capital can then be deployed to increase the staking yield, running multiple 32.75-ETH validators. Assuming a 3% CL yield, recurring partial withdrawals deployed at 33 ETH to bring down the balance to 32.75 ETH, and ignoring the exit queue capital drag, the approach is more profitable than running skimming 2048-ETH validators under current base fees.

To uphold fairness while not disrupting the current operation of `0x01` validators, the following changes are made:

* The upward EB step from $E$ to $E+1$ is imposed at $E + 0.5$. During regular upward compounding, the EB is thus set as the balance rounded to the nearest integer. This leads a compounding `0x02` validator to on average have a $E=b$, just like a 32-ETH `0x01` validator.
* The downward step to $E$ is imposed at $E+0.25$ ($E_{+1}-0.75$).
* Partial withdrawals are prevented from gaming the protocol. The EB calculation is designed such that each partial withdrawal is treated neutrally: $E=b$. To achieve this, the following takes place after every partial withdrawal at epoch boundaries:
    * The EB is initiated to the integer floor of the balance: $E = \text{EB}(b_0) = \lfloor b_0 \rfloor$.
    * A new field `temporary_upward_threshold` ($t$) is stored in the beacon state.
    * This threshold is computed as $t = E + \frac{1+(b_0-E)^2}{2}$, derived from the integral equation that stipulates that the validator will on average have $E=b$ when it smoothly grows its balance up until the next integer (see the Rationale).
    * To increase the EB, the balance must satisfy both the regular upward threshold *and* the `temporary_upward_threshold`, after which `temporary_upward_threshold` is reset to `0`.

## Specification

### Parameters

Change two existing constants: 

| Constant | Value 
| - | - |
| `HYSTERESIS_DOWNWARD_MULTIPLIER` | `3` |
| `HYSTERESIS_UPWARD_MULTIPLIER`   | `2` |

### Containers

Two new fields are added to the state:

```python
class BeaconState(Container):
    ...
    temporary_upward_threshold: List[Gwei, VALIDATOR_REGISTRY_LIMIT]
    reset_eb_flags: List[boolean, VALIDATOR_REGISTRY_LIMIT]
```

On upgrade, both lists are initialized to length `len(state.validators)` with `0` and `False` respectively.

### Functions

A new helper is added for re-initializing EB and the `temporary_upward_threshold` for validators that have been marked for EB reset; this helper is invoked during epoch processing.

```python
def initiate_effective_balance_and_threshold(state: BeaconState, index: ValidatorIndex) -&gt; None:
    v = state.validators[index]
    balance = state.balances[index]

    v.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, get_max_effective_balance(v))
    offset = (EFFECTIVE_BALANCE_INCREMENT + (balance - v.effective_balance)**2 // EFFECTIVE_BALANCE_INCREMENT) // 2
    state.temporary_upward_threshold[index] = v.effective_balance + offset
    state.reset_eb_flags[index] = False
```

The existing `process_effective_balance_updates()` is modified to call the new helper before updating the EB, and so that the EB update accounts for the `temporary_upward_threshold`. We show here the whole function for completeness:

```python
def process_effective_balance_updates(state: BeaconState) -&gt; None:
    # Update effective balances with hysteresis
    for index, validator in enumerate(state.validators):
        balance = state.balances[index]
        HYSTERESIS_INCREMENT = uint64(EFFECTIVE_BALANCE_INCREMENT // HYSTERESIS_QUOTIENT)
        DOWNWARD_THRESHOLD = HYSTERESIS_INCREMENT * HYSTERESIS_DOWNWARD_MULTIPLIER
        UPWARD_THRESHOLD = HYSTERESIS_INCREMENT * HYSTERESIS_UPWARD_MULTIPLIER
        # New
        if state.reset_eb_flags[index]:
            initiate_effective_balance_and_threshold(state, ValidatorIndex(index))
            continue
        # Then, adjust the existing if-clause to account for the temporary_upward_threshold
        max_effective_balance = get_max_effective_balance(validator) 
        balance_floor = balance - balance % EFFECTIVE_BALANCE_INCREMENT
        if balance + DOWNWARD_THRESHOLD &lt; validator.effective_balance:
            validator.effective_balance = min(balance_floor, max_effective_balance)
            state.temporary_upward_threshold[index] = 0
        elif (validator.effective_balance + UPWARD_THRESHOLD &lt; balance 
            and balance &gt;= state.temporary_upward_threshold[index]):
            new_eb = balance_floor
            if balance - balance_floor &gt;= EFFECTIVE_BALANCE_INCREMENT // 2:
                new_eb = balance_floor + EFFECTIVE_BALANCE_INCREMENT
            validator.effective_balance = min(new_eb, max_effective_balance)
            state.temporary_upward_threshold[index] = 0
```

When processing partial withdrawal, the flag for reseting the EB is set.

```python
def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -&gt; None:
    ...
    for withdrawal in expected_withdrawals:
        # After this existing line
        decrease_balance(state, withdrawal.validator_index, withdrawal.amount)
        # Add a new if-clause and append withdrawals for which we reset the EB
        v = state.validators[withdrawal.validator_index]
        if v.exit_epoch == FAR_FUTURE_EPOCH and has_compounding_withdrawal_credential(v):
            state.reset_eb_flags[withdrawal.validator_index] = True
    ...
```

## Rationale

### Relative change in staking yield

The figure shows the impact of the current EB bands and hysteresis design on validator yields for different validator configuations. The relative change in staking yield is plotted against a baseline 0 which corresponds to what compounding `0x02` validators would earn if $E=b$, as in the neutral effective balance design. Note that these are relative changes, so a validator at -0.01 under a CL yield of 3% would earn $0.99 \times 3 = 2.97$% in yield.

![Figure 1](/EIPs/assets/eip-8068/1.png)

The blue line is compounding `0x02` validators, which on average will have 0.75 ETH not counting against their EB. A staker that runs a `0x02` validator instead of a `0x01` validator then earns $100\times0.75/b$% lower staking yield. For example, at 32.25 ETH, that difference works out to 2.33%.

The red lines capture `0x02` validators that repeatedly withdraw down to the downward hysteresis threshold at $-0.25$ relative to an integer EB, thus achieving a surplus 0.25 EB relative to their actual balance. They let the balance grow until it is optimal to withdraw it, accounting for a partial withdrawal costing 84500 gas. So for example, starting at 32.75 ETH and with a 0.5 gwei base fee, that works out to making the withdrawal at around 32.80 ETH. The staker then earns 0.56% more staking yield than the baseline, factoring in a 4.5 days delay between when the withdrawn ETH stops earning yield and when it is available at the EL (dashed red line). This delay accounts for a 256 epoch withdrawal eligibility period and an average wait time until the sweep hits of 3.4 days (at a hypothetical future 770 000 active validators). Without the delay, that figure is 0.60%. When the base is 0 and there is a 4.5 days delay, the validator instead earns 0.72% more staking yield (full red line).

The green circles are sweeped `0x01` validators. They earn slightly less than the baseline due to the accruing balance in excess of 32 ETH and 2048 ETH not counting toward the EB, and being delayed by around 3.4 days.  (in this specific example where the delay )

This comparison could be nuanced further by potentially accounting for a deposit delay, but the ETH does not necessarily need to be deposited directly into the staking contract to bring value to its holder. Another nuance is that a slashing is driven by EB and not validator balance.

### Equation for the temporary upward threshold

To prevent gaming after a partial withdrawal, the EB is first reset to $E = \lfloor b_0 \rfloor$, where $b_0$ is the new balance. This creates an initial idle remainder $r_0 = b_0 - E$.

A `temporary_upward_threshold` ($t$) is then set to ensure the *average* idle balance is zero as the validator&apos;s balance compounds from $b_0$ to the next integer, $E+1$.

This threshold $t$ is calculated to solve the &quot;zero-area&quot; problem: the positive idle balance accumulated while $\text{EB}=E$ (from $b_0$ to $t$) must exactly cancel the negative idle balance accumulated while $\text{EB}=E+1$ (from $t$ to $E+1$). This is expressed by the integral equation:

$\int_{b_0}^{t}(b-E) db + \int_{t}^{E+1}(b-(E+1)) db = 0.$

Solving for $t$ yields the formula used in the specification:

$t = E + \frac{1+r_0^2}{2},$

where $r_0 = b_0 - E$.

### Alternative specifications

#### Simple fix of EB gaming under current bands 

An alternative minimal specification is to only fix the gaming incentive, and instead compensate for the lower yield of `0x02` validators by increasing the withdrawal fee in [EIP-8062](/EIPs/EIPS/eip-8062). Only the partial withdrawal is adjusted. For this specification, only the `pending_eb_resets` need to be stored in the `BeaconState`:

```python
class BeaconState(Container):
    ...
    pending_eb_resets: List[ValidatorIndex, PENDING_PARTIAL_WITHDRAWALS_LIMIT]
```

Append the validator index to `pending_eb_resets` in `process_withdrawals()`:

```python
def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -&gt; None:
    ...
    for withdrawal in expected_withdrawals:
        # After this existing line
        decrease_balance(state, withdrawal.validator_index, withdrawal.amount)
        # Add a new if-clause and append withdrawals for which we reset the EB
        v = state.validators[withdrawal.validator_index]
        if v.exit_epoch == FAR_FUTURE_EPOCH and has_compounding_withdrawal_credential(v):
            state.pending_eb_resets.append(withdrawal.validator_index)
    ...
```

Modify `process_effective_balance_updates()` to reset the effective balance upon a partial withdrawal. The balance is never allowed to increase during the reset.

```python
def process_effective_balance_updates(state: BeaconState) -&gt; None:
    # Apply EB resets for executed withdrawals
    for i in state.pending_eb_resets:
        state.validators[i].effective_balance = min(
            state.balances[i] - state.balances[i] % EFFECTIVE_BALANCE_INCREMENT,
            get_max_effective_balance(state.validators[i]),
            state.validators[i].effective_balance
        )
    state.pending_eb_resets = []
    ...
```

## Security Considerations

This EIP would trigger a mass upward change of EBs at the specific hardfork boundary. The effect of this should be analyzed furher.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 28 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8068</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8068</guid>
      </item>
    
      <item>
        <title>eth/72 - Sparse Blobpool</title>
        <category>Standards Track/Networking</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8070-sparse-blobpool/26023</comments>
        
        <description>## Abstract

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 full nodes, this means downloading as little as 1/8 of the data (8 out of 128 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.

## Motivation

As Blob Parameter Only (BPO) forks progressively increase throughput, the full-replication nature of today&apos;s EL blobpool will begin dominating bandwidth utilization, causing us to hit [EIP-7870](/EIPs/EIPS/eip-7870) 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 _of a full node_ is dominated by the EL blobpool, since column propagation on the CL benefits from sampling.

![](/EIPs/assets/eip-8070/bandwidth-breakdown-fusaka-devnets.png)

**Figure 1.** _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._

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.

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&apos;s ability to satisfy its own sampling needs with the pre-propagated data in the EL blobpool (through the `getBlobs` 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.

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.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

### Execution clients :: devp2p changes

We introduce a new devp2p protocol version, `eth/72` extending the existing `eth/71` protocol.

**Modify `NewPooledTransactionHashes` (`0x08`) message.**
Add a new field `cell_mask` of type `B_16` (`uint128`). This field MUST be interpreted as a bitarray of length `CELLS_PER_EXT_BLOB`, carrying `1` in the indices of columns the announcer has available for **all type 3 txs announced within the message**. This field MUST be set to `nil` 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).

- old schema (`eth/71`): `[types: B, [size_0: P, size_1: P, ...], [hash_0: B_32, hash_1: B_32, ...]]`
- new schema (`eth/72`): `[types: B, [size_0: P, size_1: P, ...], [hash_0: B_32, hash_1: B_32, ...], cell_mask: B_16]`

**Modify `GetPooledTransactions` (`0x09`) / `PooledTransactions` (`0x10`) behaviour.**
Responses now elide blob payloads for type 3 transactions requested via this RPC. This is performed by setting an RLP `nil` literal in the list position corresponding to the transaction&apos;s blob data. Cell proofs and commitments are unaffected and continue to be sent.

**New message type `GetCells` (`0x14`).** Used to request cells for type 3 transactions. It specifies the transaction hashes being requested, along with a `cell_mask` specifying which cell indices are needed, with syntax identical as `cell_mask` in `NewPooledTransactionHashes`.

- `eth/72`: `[[hash_0: B_32, hash_1: B_32, ...], cell_mask: B_16]`

**New message type `Cells` (`0x15`).** Used to respond to a `GetCells` requests.

- `eth/72`: `[[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]`

### Execution clients :: Blobpool behavior

**New transaction hash.**
Upon receiving a `NewPooledTransactionHashes` 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).

**Provider role.**
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 `GetPooledTransactions` and `GetCells` with an all-ones `cell_mask` bitmap. Upon successful retrieval and validation (as per [EIP-7594](/EIPs/EIPS/eip-7594)), the node MUST in turn announce the transaction hash to its peers via `NewPooledTransactionHashes`, also with an all-ones `cell_mask`.

**Sampler role.**
If the node is a sampler, the node MUST only request the transaction payload via `GetPooledTransactions`. 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 `C_extra` random columns in addition to its custody set (see &quot;Sampling noise&quot; in Rationale). The responder MAY truncate its `Cells` response depending on its current capacity, returning fewer cells than requested.

**Ensuring fairness.**
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.

**Supernode behaviour.**
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.

**Sampler eviction**
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.

**Continued sampling**
Tenured transactions MAY be subject to resampling in order to test for liveness and confirm confidence of continued network-wide availability.

### Execution clients :: Local block builders

&gt; TODO: config specification needed.

Client implementations MUST provide configuration options for local block builders to specify a blob inclusion policy when proposing a block. Implementations SHOULD support at least these policies:

1. Conservative: include only blob transactions for which all blob data is fully available locally (equivalent to today&apos;s behaviour).
2. Optimistic: also include blob transactions that have been successfully sampled.
3. Proactive: resample prior to blob proposal time in order to assess network-wide confidence of blobs potentially selected for inclusion. This requires an additional Engine API extension for the CL to notify the EL of upcoming proposer duty (TODO).

### Engine API extensions

&gt; TODO: This specification will be moved out to the Execution APIs repo and linked to from here.

**Method `engine_blobCustodyUpdatedV1`**

Called by the Consensus layer client to inform the Execution layer of the indices of their current blob column custody set at startup, as well as subsequent changes during live operation.

Request:

- method: `engine_blobCustodyUpdatedV1`
- params:
  - `indices_bitarray`: uint128, interpreted as a bitarray of length `CELLS_PER_EXT_BLOB` indicating which column indices form the custody set.
- timeout: 150ms

Response:

- result: no payload
- error: code and message set in case an error occurs during processing of the request.

Specification:

1. The Consensus client MUST call this method whenever its custody set changes. Additionally, it MUST call it on start, on restart, and when an Engine API interruption is detected.
2. The Execution client 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.
3. For type 3 transactions pending in the blobpool:
    1. If the custody set has expanded, the Execution client MUST issue new sampling requests for the delta. It SHOULD broadcast updated `NewPooledTransactionHashes` announcement with the new available set.
    2. If the custody set has contracted, the Execution client MAY prune dropped cells from local storage, but only AFTER it has broadcast an updated `NewPooledTransactionHashes` announcement with the reduced available set. This is to avoid peers from perceiving an availability fault if they happen to request those previously announced cells.
4. The Execution client MUST treat a request to update the custody set to the current value as a no-op operation returning an Ok.

**Method `engine_getBlobsV4`**

Called by the Consensus layer client to retrieve blob cells from the Execution layer blobpool.

Request:

- method: `engine_getBlobsV4`
- params:
  - `versioned_blob_hashes`: []bytes32, an array of blob versioned hashes.
  - `indices_bitarray`: uint128, a bitarray denoting the indices of the cells to retrieve.
- timeout: 500ms

Response:

- result: `[]BlobCellsAndProofsV1`
- error: code and message set in case an error occurs during processing of the request.

**Data structure `BlobCellsAndProofsV1`**

- `blob_cells`: a sequence of byte arrays `[]bytes` representing the partial matrix of the requested blobs, with `nil` entries for missing cells.
- `proofs`: `Array of DATA` - Array of `KZGProof` as defined in [EIP-4844](/EIPs/EIPS/eip-4844), 48 bytes each (`DATA`)

### Parameters

- **Fetching probability**: p = 0.15
- **Mesh degree**: D = 50 (default peerset size)
- **Sampling requirement**: Minimum `SAMPLES_PER_SLOT = 8` columns per node as per PeerDAS specification
- **Reconstruction threshold**: 64 cells required for Reed-Solomon decoding
- **Minimum providers to sample**: minimum 2 providers should be observed before sampling
- **Extra random columns per request**: `C_extra = 1`

## Rationale

### Parameter selection

The choice of p = 0.15 balances bandwidth reduction with availability guarantees. Mathematical analysis for a mesh degree D = 50 shows:

- **Primary reliability**: Probability of having at least 3 peers with complete blob payload is 98.6%
- **Secondary reliability**: Via reconstruction from partial availability, recovery probability exceeds 80% when 6+ provider peers exist.
- **Total unavailability**: Only 0.03% chance with these parameters.

### Reliability framework

**Primary reliability.** 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:

$$
P(X \geq k) = 1 - \sum_{i=0}^{k-1} \binom{D}{i} p^i (1-p)^{D-i}
$$

Evaluating for sensible values of $p$ and $k$ yields, where $D=50$ (Geth&apos;s default mesh degree):

| $p$      | $k = 6$      | $k = 5$      | $k = 4$      | $k = 3$      | $k = 2$      | $k = 1$      | $P(0)$       |
| -------- | ------------ | ------------ | ------------ | ------------ | ------------ | ------------ | ------------ |
| 0.05     | 0.037776     | 0.103617     | 0.239592     | 0.459467     | 0.720568     | 0.923055     | 0.076945     |
| 0.08     | 0.208126     | 0.371050     | 0.574704     | 0.774026     | 0.917288     | 0.984534     | 0.015466     |
| 0.10     | 0.383877     | 0.568802     | 0.749706     | 0.888271     | 0.966214     | 0.994846     | 0.005154     |
| 0.125    | 0.606513     | 0.765366     | 0.886232     | 0.958237     | 0.989739     | 0.998740     | 0.001260     |
| **0.15** | **0.780647** | **0.887895** | **0.953953** | **0.985811** | **0.997095** | **0.999704** | **0.000296** |
| 0.20     | 0.951973     | 0.981504     | 0.994344     | 0.998715     | 0.999807     | 0.999986     | 0.000014     |

**Secondary reliability.** 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&apos;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.

| Providers ($k$) | Samplers ($n=D-k$) | $E[Distinct Columns]$ | $P(Y ≥ 64)$ |
| --------------- | ------------------ | --------------------- | ----------- |
| 0               | 50                 | 125.1                 | &gt;99.99%     |
| 1               | 49                 | 124.9                 | &gt;99.99%     |
| 2               | 48                 | 124.6                 | &gt;99.99%     |
| 3               | 47                 | 124.3                 | &gt;99.99%     |
| 4               | 46                 | 124.0                 | &gt;99.99%     |
| ...             | ...                | ...                   | ...         |
| ~40             | ~10                | ~68                   | ~80%        |

**Minimum threshold**: Approximately $n_{\min} \approx 10$ samplers needed for reasonable reconstruction probability (&gt;80%).

## Backwards Compatibility

This EIP changes the `eth` protocol and requires rolling out a new version, `eth/72`. 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 `eth/71`.

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.

## Test Cases

TBD

## Security Considerations

### Attack scenarios and threat model

**DoS attacks.** 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.

**Selective withholding attacks.** TODO

**Eclipse attacks.** TODO

### Peer disconnection policies

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.

### The need for sampling noise

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 &quot;sampling noise.&quot;

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.

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).

### No normative peer scoring

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.

### devp2p message schema choices

We note that `cell_mask` field in `NewPooledTransactionHashes` 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&apos;re shared across all sampled transactions).

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 `request_id` correlation), so this approach is not affected by head-of-line blocking either (at least from a protocol perspective).

We considered more expressive designs, ranging from simple arrays of `cell_mask`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.

### Open points

- Further threat modelling and security hardening.
- RBF (replace-by-fee) impact.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Prevent using consolidations as withdrawals</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8071-prevent-using-consolidations-as-withdrawals/26037</comments>
        
        <description>## Abstract

Cancels a consolidation request if the effective balance of the target validator would exceed the max effective balance after processing it, which would result in the excess balance being withdrawn. This is an unintended way to speed up withdrawals when the consolidation queue is faster than the exit queue.

## Motivation

The existing design of consolidation mechanism leaves an opportunity to use consolidation queue for exits which becomes appealing to be abused when there is an imbalance between exit and consolidation queues favoring the latter.

At the date of writing this EIP, the consolidation flaw is being heavily exploited. There are public write ups on how to speed up withdrawals by using this vulnerability.

Even though this is a UX rather than security issue, consolidation queue was never meant to be used for withdrawals, which makes the fix introduced by this EIP an important modification.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

Starting from the beginning of the epoch when this EIP is activated, Consensus Layer client **MUST** use the modified `process_consolidation_request` function which code is outlined below.

### New `get_pending_balance_to_consolidate`

```python
def get_pending_balance_to_consolidate(state: BeaconState, target_index: ValidatorIndex) -&gt; Gwei:
    pending_balance_to_consolidate = Gwei(0)
    for pending_consolidation in state.pending_consolidations:
        if pending_consolidation.target_index == target_index:
            source_validator = state.validators[pending_consolidation.source_index]
            pending_balance_to_consolidate += source_validator.effective_balance
    return pending_balance_to_consolidate
```

### Modified `process_consolidation_request`

*Note*: This function is extended with the check of the target&apos;s balance after consolidation and cancels consolidation request if the balance exceeds the max effective balance.

```python
def process_consolidation_request(
    state: BeaconState, consolidation_request: ConsolidationRequest
) -&gt; None:
    if is_valid_switch_to_compounding_request(state, consolidation_request):
        validator_pubkeys = [v.pubkey for v in state.validators]
        request_source_pubkey = consolidation_request.source_pubkey
        source_index = ValidatorIndex(validator_pubkeys.index(request_source_pubkey))
        switch_to_compounding_validator(state, source_index)
        return

    # Verify that source != target, so a consolidation cannot be used as an exit
    if consolidation_request.source_pubkey == consolidation_request.target_pubkey:
        return
    # If the pending consolidations queue is full, consolidation requests are ignored
    if len(state.pending_consolidations) == PENDING_CONSOLIDATIONS_LIMIT:
        return
    # If there is too little available consolidation churn limit, consolidation requests are ignored
    if get_consolidation_churn_limit(state) &lt;= MIN_ACTIVATION_BALANCE:
        return

    validator_pubkeys = [v.pubkey for v in state.validators]
    # Verify pubkeys exist
    request_source_pubkey = consolidation_request.source_pubkey
    request_target_pubkey = consolidation_request.target_pubkey
    if request_source_pubkey not in validator_pubkeys:
        return
    if request_target_pubkey not in validator_pubkeys:
        return
    source_index = ValidatorIndex(validator_pubkeys.index(request_source_pubkey))
    target_index = ValidatorIndex(validator_pubkeys.index(request_target_pubkey))
    source_validator = state.validators[source_index]
    target_validator = state.validators[target_index]

    # Verify source withdrawal credentials
    has_correct_credential = has_execution_withdrawal_credential(source_validator)
    is_correct_source_address = (
        source_validator.withdrawal_credentials[12:] == consolidation_request.source_address
    )
    if not (has_correct_credential and is_correct_source_address):
        return

    # Verify that target has compounding withdrawal credentials
    if not has_compounding_withdrawal_credential(target_validator):
        return

    # Verify the source and the target are active
    current_epoch = get_current_epoch(state)
    if not is_active_validator(source_validator, current_epoch):
        return
    if not is_active_validator(target_validator, current_epoch):
        return
    # Verify exits for source and target have not been initiated
    if source_validator.exit_epoch != FAR_FUTURE_EPOCH:
        return
    if target_validator.exit_epoch != FAR_FUTURE_EPOCH:
        return
    # Verify the source has been active long enough
    if current_epoch &lt; source_validator.activation_epoch + SHARD_COMMITTEE_PERIOD:
        return
    # Verify the source has no pending withdrawals in the queue
    if get_pending_balance_to_withdraw(state, source_index) &gt; 0:
        return

    # [New in EIPXXXX]
    # Verify that the consolidating balance will
    # end up as active balance, not as excess balance
    target_balance_after_consolidation = (
        get_pending_balance_to_consolidate(state, target_index)
        + source_validator.effective_balance
        + state.balances[target_index]
    )
    if target_balance_after_consolidation &gt; get_max_effective_balance(target_validator):
        return

    # Initiate source validator exit and append pending consolidation
    source_validator.exit_epoch = compute_consolidation_epoch_and_update_churn(
        state, source_validator.effective_balance
    )
    source_validator.withdrawable_epoch = Epoch(
        source_validator.exit_epoch + MIN_VALIDATOR_WITHDRAWABILITY_DELAY
    )
    state.pending_consolidations.append(
        PendingConsolidation(source_index=source_index, target_index=target_index)
    )
```

## Rationale

### Iterating over pending consolidations

The new design introduces an iteration over pending consolidations which increases complexity of consolidation processing.

This is done to handle the case when there are multiple consolidations with the same target and each of them doesn&apos;t exceed the max effective balance while all of them together do.

## Backwards Compatibility

This EIP introduces backwards-incompatible changes to the Consensus Layer and must be activated via scheduled network upgrade.

## Test Cases

* test_single_consolidation_request_at_max_eb
* test_no_pending_consolidations_exceeding_max_eb
* test_single_pending_consolidation_exceeding_max_eb
* test_multiple_pending_consolidations_at_max_eb
* test_multiple_pending_consolidations_exceeding_max_eb
* test_exceeding_max_eb_with_the_target_balance_but_not_eb
* test_exceeding_max_eb_with_the_source_eb_but_not_the_balance
* test_multiple_pending_consolidations_exceeding_max_eb_with_the_source_eb_but_not_the_balance

All of the above test cases are implemented [here](/EIPs/assets/eip-8071/test_process_consolidation_request.py).

## Security Considerations

When consolidation request results in max effective balance exceeded, it is cancelled on the Consensus Layer,
neither request fee nor transaction gas cost are refunded in this case.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 29 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8071</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8071</guid>
      </item>
    
      <item>
        <title>Transaction Inclusion Subscription</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8072-transaction-inclusion-subscription/26431</comments>
        
        <description>## Abstract

This EIP extends the existing `eth_subscribe` JSON-RPC method with a new subscription type `transactionInclusion` that enables clients to receive real-time notifications when transactions are included in blocks. This subscription-based approach provides efficient transaction confirmation monitoring without blocking connections, supporting both combined transaction submission and monitoring in a single call, as well as monitoring of already-submitted transactions.

## Motivation

Current transaction submission workflows require separate calls to `eth_sendRawTransaction` followed by repeated polling of `eth_getTransactionReceipt`, creating unnecessary latency and network overhead. While [EIP-7966](/EIPs/EIPS/eip-7966) proposes `eth_sendRawTransactionSync` to address this through a synchronous blocking approach, blocking HTTP connections presents significant drawbacks:

- **Connection hogging**: Each transaction blocks one HTTP connection until confirmation or timeout
- **Limited scalability**: Cannot efficiently monitor multiple transactions over a single connection
- **Timeout complexity**: Requires careful tuning of timeout parameters for different blockchain slot times
- **Resource inefficiency**: Repeated polling consumes bandwidth and server resources

The subscription-based approach leverages the battle-tested `eth_subscribe` mechanism already implemented across all major Ethereum clients, providing superior resource efficiency and scalability while maintaining feature parity with synchronous approaches.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

### New Subscription Type

A new subscription type `transactionInclusion` is added to the `eth_subscribe` method.

### Subscription Request

```json
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;method&quot;: &quot;eth_subscribe&quot;,
  &quot;params&quot;: [&quot;transactionInclusion&quot;, {
    &quot;transaction&quot;: &quot;0x...&quot;,
    &quot;includeReorgs&quot;: false
  }]
}
```

Or for monitoring an already-submitted transaction:

```json
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;method&quot;: &quot;eth_subscribe&quot;,
  &quot;params&quot;: [&quot;transactionInclusion&quot;, {
    &quot;hash&quot;: &quot;0x...&quot;,
    &quot;includeReorgs&quot;: false
  }]
}
```

### Parameters

The subscription parameters object accepts the following fields:

- `transaction` (DATA, optional): Signed transaction data to submit and monitor. When provided, the node MUST immediately submit this transaction to the network.
- `hash` (DATA, 32 bytes, optional): Transaction hash to monitor for already-submitted transactions.
- `includeReorgs` (boolean, optional, default: `false`): Controls reorg monitoring behavior.
  - If `false`: Subscription auto-unsubscribes immediately after first inclusion notification. Reorgs are not monitored.
  - If `true`: Subscription actively monitors for reorgs and sends notifications for reorgs, re-inclusions, and finalization.

**Exactly one** of `transaction` or `hash` MUST be provided. If both or neither are provided, the node MUST return a JSON-RPC error with code `-32602` (Invalid params).

### Subscription Response

Upon successful subscription, the node MUST return a subscription ID:

```json
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;result&quot;: &quot;0x1234567890abcdef&quot;
}
```

### Notification Format

When the transaction status changes, the node MUST send a notification:

```json
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;method&quot;: &quot;eth_subscription&quot;,
  &quot;params&quot;: {
    &quot;subscription&quot;: &quot;0x1234567890abcdef&quot;,
    &quot;result&quot;: {
      &quot;status&quot;: &quot;included&quot;,
      &quot;blockHash&quot;: &quot;0x...&quot;,
      &quot;blockNumber&quot;: &quot;0x...&quot;,
      &quot;transactionIndex&quot;: &quot;0x...&quot;,
      &quot;receipt&quot;: {
        &quot;transactionHash&quot;: &quot;0x...&quot;,
        &quot;transactionIndex&quot;: &quot;0x...&quot;,
        &quot;blockHash&quot;: &quot;0x...&quot;,
        &quot;blockNumber&quot;: &quot;0x...&quot;,
        &quot;from&quot;: &quot;0x...&quot;,
        &quot;to&quot;: &quot;0x...&quot;,
        &quot;cumulativeGasUsed&quot;: &quot;0x...&quot;,
        &quot;gasUsed&quot;: &quot;0x...&quot;,
        &quot;contractAddress&quot;: null,
        &quot;logs&quot;: [],
        &quot;logsBloom&quot;: &quot;0x...&quot;,
        &quot;status&quot;: &quot;0x1&quot;
      }
    }
  }
}
```

The `status` field MAY be one of:

- `&quot;included&quot;`: Transaction has been included in a block
- `&quot;finalized&quot;`: Transaction&apos;s block has reached finality (only sent when `includeReorgs` is `true`)
- `&quot;reorged&quot;`: Transaction was removed from the canonical chain (only sent if `includeReorgs` is `true`)

The `receipt` field MUST contain the complete transaction receipt object as defined by `eth_getTransactionReceipt`.

### Behavior

The node MUST implement the following behavior:

1. **When `transaction` is provided**:
   - The node MUST immediately submit the transaction to the network using the same semantics as `eth_sendRawTransaction`
   - The node MUST derive the transaction hash and begin monitoring for inclusion
   - If submission fails, the node MUST return a JSON-RPC error and MUST NOT create the subscription

2. **Transaction Already Included**:
   - If the monitored transaction is already included in a block at subscription time:
     - If `includeReorgs` is `false`: The node MUST immediately send an inclusion notification and automatically unsubscribe
     - If `includeReorgs` is `true`: The node MUST immediately send an inclusion notification and continue monitoring until finalization

3. **Pending Transaction**:
   - The node MUST monitor the transaction pool and canonical chain
   - When the transaction is included in a block, the node MUST send an inclusion notification
   - If `includeReorgs` is `false`, the node MUST then automatically unsubscribe
   - If `includeReorgs` is `true`, the node MUST continue monitoring

4. **Reorg Monitoring** (when `includeReorgs` is `true`):
   - The node MUST continue monitoring the transaction after initial inclusion
   - If the transaction is removed from the canonical chain due to a reorg, the node MUST send a notification with `&quot;status&quot;: &quot;reorged&quot;`
   - If the transaction is re-included in a different block, the node MUST send a new inclusion notification with `&quot;status&quot;: &quot;included&quot;`
   - When the block containing the transaction reaches finality, the node MUST send a finalization notification with `&quot;status&quot;: &quot;finalized&quot;`
   - The node MUST automatically unsubscribe after sending the finalization notification

5. **Auto-unsubscribe**:
   - If `includeReorgs` is `false`, the node MUST automatically unsubscribe after sending the first inclusion notification
   - The node SHOULD send an `eth_subscription` unsubscribe confirmation

6. **Transaction Not Found**:
   - If monitoring a transaction by `hash` that doesn&apos;t exist in the mempool or chain, the subscription remains active
   - The node SHOULD monitor for the transaction appearing in the future
   - Clients MAY manually unsubscribe if desired

## Rationale

### Why Subscription Over Synchronous?

Subscriptions provide several advantages over the synchronous approach proposed in EIP-7966:

- **Non-blocking**: Clients can perform other operations while waiting for confirmation
- **Multiplexing**: Multiple transactions can be monitored over a single WebSocket connection
- **No timeout complexity**: Subscriptions naturally handle varying confirmation times without timeout parameters
- **Proven infrastructure**: Leverages existing `eth_subscribe` implementation present in all major clients

The addition of the `transaction` parameter provides complete feature parity with `eth_sendRawTransactionSync` by enabling submission and monitoring in a single call.

### Why Extend `eth_subscribe`?

The `eth_subscribe` mechanism is battle-tested and already implemented across all major Ethereum clients. Extending it with a new subscription type requires minimal implementation effort compared to introducing entirely new RPC methods.

### Why Support Both `transaction` and `hash`?

Supporting both parameters provides maximum flexibility:

- `transaction`: Optimal for new transactions, matching the convenience of synchronous methods
- `hash`: Enables monitoring of transactions submitted through other means or by other parties

### Why Support Reorg Monitoring?

Applications requiring high confidence in transaction finality benefit from reorg notifications. This is particularly important on chains with faster block times where reorgs may be more common. The optional nature of this feature allows applications to choose the appropriate trade-off between functionality and resource usage.

### Resource Efficiency

A single WebSocket connection can support unlimited concurrent transaction subscriptions, whereas synchronous approaches require one blocking HTTP connection per transaction. This represents a significant improvement in resource utilization for applications monitoring multiple transactions.

### Why Always Auto-unsubscribe?

Both modes auto-unsubscribe to prevent unbounded subscription accumulation and provide clear lifecycle management:

- **`includeReorgs: false`**: Unsubscribes immediately after first inclusion for fast feedback with minimal resource usage. Users accepting this mode understand the transaction may still be reorged and can manually monitor if needed.
- **`includeReorgs: true`**: Unsubscribes after finalization when reorgs are no longer possible, providing complete transaction lifecycle monitoring.

The key difference is the level of guarantee:

- `includeReorgs: false`: Fast notification, transaction is included (may still reorg)
- `includeReorgs: true`: Complete lifecycle tracking until finality (cannot reorg)

## Backwards Compatibility

This EIP is fully backwards compatible. It extends the existing `eth_subscribe` method with a new subscription type. Clients that have not implemented this feature will return a standard JSON-RPC error indicating the subscription type is not supported. Existing applications continue to function unchanged.

## Test Cases

### Test Case 1: Submit and Monitor

**Request:**

```json
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;method&quot;: &quot;eth_subscribe&quot;,
  &quot;params&quot;: [&quot;transactionInclusion&quot;, {
    &quot;transaction&quot;: &quot;0xf86c098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83&quot;
  }]
}
```

**Expected Behavior:**

1. Node submits transaction to network
2. Node returns subscription ID
3. When transaction is included, node sends notification with `&quot;status&quot;: &quot;included&quot;` and receipt
4. Subscription automatically closes immediately

### Test Case 2: Monitor Existing Transaction

**Request:**

```json
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;method&quot;: &quot;eth_subscribe&quot;,
  &quot;params&quot;: [&quot;transactionInclusion&quot;, {
    &quot;hash&quot;: &quot;0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef&quot;,
    &quot;includeReorgs&quot;: false
  }]
}
```

**Expected Behavior:**

1. If transaction already included, immediately send notification with `&quot;status&quot;: &quot;included&quot;`
2. If transaction pending, wait and send notification upon inclusion
3. Subscription automatically closes immediately after notification

### Test Case 3: Reorg Monitoring

**Request:**

```json
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;method&quot;: &quot;eth_subscribe&quot;,
  &quot;params&quot;: [&quot;transactionInclusion&quot;, {
    &quot;hash&quot;: &quot;0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef&quot;,
    &quot;includeReorgs&quot;: true
  }]
}
```

**Expected Behavior:**

1. Send inclusion notification when transaction is included (with `&quot;status&quot;: &quot;included&quot;`)
2. Continue monitoring for reorgs
3. If reorg occurs, send reorg notification (with `&quot;status&quot;: &quot;reorged&quot;`)
4. If re-included, send new inclusion notification (with `&quot;status&quot;: &quot;included&quot;`)
5. When block is finalized, send finalization notification (with `&quot;status&quot;: &quot;finalized&quot;`)
6. Subscription automatically closes after finalization

### Test Case 4: Invalid Parameters

**Request:**

```json
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;method&quot;: &quot;eth_subscribe&quot;,
  &quot;params&quot;: [&quot;transactionInclusion&quot;, {
    &quot;includeReorgs&quot;: false
  }]
}
```

**Expected Response:**

```json
{
  &quot;jsonrpc&quot;: &quot;2.0&quot;,
  &quot;id&quot;: 1,
  &quot;error&quot;: {
    &quot;code&quot;: -32602,
    &quot;message&quot;: &quot;Invalid params: exactly one of transaction or hash must be provided&quot;
  }
}
```

## Reference Implementation

A minimal reference implementation can be realized by:

1. For `transaction` parameter: Call internal `eth_sendRawTransaction` logic and capture the transaction hash
2. Register the transaction hash in a subscription manager
3. Monitor the transaction pool and canonical chain for the transaction
4. When the transaction is included in a block, query the receipt and send notification
5. If `includeReorgs` is false, automatically unsubscribe after first inclusion
6. If `includeReorgs` is true, continue monitoring for chain reorganizations

Implementation pseudo-code:

```python
def handle_transaction_inclusion_subscription(params):
    if &apos;transaction&apos; in params:
        tx_hash = submit_transaction(params[&apos;transaction&apos;])
    elif &apos;hash&apos; in params:
        tx_hash = params[&apos;hash&apos;]
    else:
        raise InvalidParamsError()
    
    include_reorgs = params.get(&apos;includeReorgs&apos;, False)
    subscription_id = generate_subscription_id()
    
    register_subscription(subscription_id, tx_hash, include_reorgs)
    return subscription_id

def on_block_added(block):
    for tx in block.transactions:
        subscriptions = get_subscriptions_for_tx(tx.hash)
        for sub in subscriptions:
            receipt = get_transaction_receipt(tx.hash)
            send_notification(sub.id, &apos;included&apos;, receipt)
            if not sub.include_reorgs:
                unsubscribe(sub.id)

def on_chain_reorg(old_blocks, new_blocks):
    removed_txs = get_transactions_from_blocks(old_blocks)
    for tx_hash in removed_txs:
        subscriptions = get_subscriptions_for_tx(tx_hash)
        for sub in subscriptions:
            if sub.include_reorgs:
                send_notification(sub.id, &apos;reorged&apos;, None)

def on_block_finalized(block):
    for tx in block.transactions:
        subscriptions = get_subscriptions_for_tx(tx.hash)
        for sub in subscriptions:
            receipt = get_transaction_receipt(tx.hash)
            send_notification(sub.id, &apos;finalized&apos;, receipt)
            unsubscribe(sub.id)
```

## Security Considerations

### Transaction Submission Validation

When `transaction` is provided, nodes MUST perform the same validation as `eth_sendRawTransaction` before creating the subscription. Invalid transactions MUST result in an error response without creating a subscription.

### Privacy Considerations

Monitoring transactions by hash does not introduce new privacy concerns beyond existing `eth_getTransactionReceipt` polling. However, applications should be aware that subscribing to transaction hashes reveals interest in those transactions to the node operator.

### Reorg Attack Considerations

Applications using `includeReorgs: true` should implement appropriate logic to handle reorg notifications, particularly on chains where reorgs may be used maliciously. The notification mechanism provides transparency but does not prevent reorg-based attacks.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 31 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8072</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8072</guid>
      </item>
    
      <item>
        <title>Self-Describing Bytes via EIP-712 Selectors</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8074-self-describing-bytes-via-eip-712-selectors/25649</comments>
        
        <description>## Abstract

This ERC standardizes a convention for tagging ABI-encoded structures placed inside `bytes` parameters with a compact type selector derived from the [EIP-712](/EIPs/EIPS/eip-712) type string.
It also defines a canonical multi-payload wrapper, allowing multiple typed payloads to be carried in a single `bytes` parameter.

## Motivation

Many smart contract methods use a `bytes` parameter to support future extensibility—including common standards such as [ERC-721](/EIPs/EIPS/eip-721) and [ERC-1155](/EIPs/EIPS/eip-1155).
The convention of carrying extra data in a `bytes` parameter was also codified further in [ERC-5750](/EIPs/EIPS/eip-5750).

In many practical cases, the `bytes` payload may encode a structured type that must be ABI-decoded before it can be processed. However:

- Different contracts use different, ad-hoc conventions for distinguishing among possible payloads.
- A single contract may need to support multiple encodings.
- In more complex workflows, a payload may be propagated across multiple contracts, each of which may need to parse it differently.

Currently, there is no standardized convention for identifying the &quot;type&quot; of an encoded payload, nor for supporting multiple data items in a single bytes parameter.
This ERC defines a minimal, interoperable convention for self-describing payloads that remain compatible with existing ABI tooling.

## Specification

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

### Terms

- **Type string** — the canonical EIP-712 type string, e.g.
  `TransferNote(bytes32 reference,string comment,uint256 deadline)`
- **Type selector (`bytes4`)** — `keccak256(typeString)[0:4]`
- **Single-payload** — a selector followed by `abi.encode` of that struct’s fields
- **Multi-payload wrapper** — `DataList(bytes[] items)`; each `items[i]` is a valid single-payload

### Single-payload encoding

- An ABI-encoded struct is prefixed with a 4-byte selector.
- The selector is defined as the first 4 bytes of the keccak256 hash of its EIP-712 type string.

```
typeSelector(T) = bytes4(keccak256(bytes(T)))
encoding = typeSelector(T) ++ abi.encode(&lt;fields of T&gt;)
```

Example:

```
T = &quot;TransferNote(bytes32 reference,string comment,uint256 deadline)&quot;
keccak256(T) = 0xf91f3a243a886588394dfd70af07dce0ca18c55e402d76152d4cb300349c9e9d
selector = 0xf91f3a24
encoding = 0xf91f3a24 ++ abi.encode(reference, comment, deadline)
```

A consumer may look for a known selector before attempting to decode the data, and can easily distinguish between multiple different payloads that it knows how to accept.

### Multi-payload wrapper

- Uses a canonical wrapper type `DataList(bytes[] items)` with selector `0xae74f986`.
- Each element in the items array is itself a single-struct payload (with its own selector).

```
DataList(bytes[] items)
selector(DataList) = bytes4(keccak256(&quot;DataList(bytes[] items)&quot;)) = 0xae74f986
encoding = 0xae74f986 ++ abi.encode(items)
```

Each `items[i]` MUST be a valid single-payload as above.
Consumers can look for this well-known selector, and can then decode the list to be scanned recursively for recognized items.

### Decoding

- Read the first 4 bytes as the **selector**.
- If the selector is `0xae74f986`, decode the remainder as `(bytes[] items)` and parse each item recursively.
- If the selector is another recognized selector, the remainder should be parsed accordingly.
- Unknown selectors MUST be ignored.
- Order is not significant; producers SHOULD avoid duplicates.

## Rationale

- **EIP-712 reuse:** avoids new schema syntax and aligns with the signing ecosystem.
- **4-byte selectors:** mirror Solidity’s function selector convention for compactness.
- **Simple wrapper:** `DataList` provides multiplexing without special parsing or new ABI rules.

## Backwards Compatibility

Existing contracts that already accept arbitrary `bytes` remain compatible. Contracts unaware of this ERC can continue to treat the payload as opaque.

## Security Considerations

- **Payload bounds:** When parsing `DataList`, consumers should limit `items.length` and total payload size (for example ≤ 8 items and ≤ 8 KB).
- **Early exit:** Consumers should stop scanning once all expected selectors are found.
- **Unknown data:** Unrecognized items must be ignored safely.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 30 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8074</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8074</guid>
      </item>
    
      <item>
        <title>Adaptive state cost to cap growth &amp; scale L1</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8075-adaptive-state-cost-to-cap-growth-scale-l1/26450</comments>
        
        <description>## Abstract

This EIP precisely caps state growth while at the same time facilitating between 50%-300% more non-state operations per block compared to when solely raising the state gas cost. The cap is achieved by tracking state creation and having a dedicated [EIP-4844](/EIPs/EIPS/eip-4844) style fee market mechanism set the cost, to target 250 MiB per day. To preserve the existing transaction format and EVM execution patterns, state is still priced in gas during transaction processing. The state creation gas cost is updated every block, adjusting slowly so that users can set reasonable gas limits. The byte-level harmonization of state creation operations provided by [EIP-8037](/EIPs/EIPS/eip-8037) is then still applied. To facilitate scaling, state creation and regular gas have separate limits, but a normalized aggregate gas is used when calculating the base fee.

## Motivation

Ethereum is currently focused on scaling the layer 1, with a rapid expansion of the block gas limit foreseen in the near-term from compute and memory optimization, as well as via headliner proposals [EIP-7732](/EIPs/EIPS/eip-7732) and [EIP-7928](/EIPs/EIPS/eip-7928). Unfortunately, if the gas cost for state creation is kept fixed, state would likely expand in line with an expanding gas limit. As client database sizes increase, degradation in performance is expected. [EIP-8037](/EIPs/EIPS/eip-8037) addresses state growth by harmonizing current state creation costs according to how many bytes they add to the state. It also increases the gas cost of state creation significantly, by between 3x and 9.5x per operation. 

It can be assumed that increased gas costs will somewhat keep state from expanding in line with the increased gas limit. However, since the price-elasticity of demand for state creation is unknown, it is impossible to say exactly what the effect would be. Users may not be particularly sensitive to the increased state gas costs and still continue to purchase state relative to other resources similar to present usage patterns, given that the overall base fee may also fall from the increased gas limit. This would have two effects:

1. State would continue to expand by a higher rate than desired.
2. Under equilibrium, well over 50% of all consumed gas may be spent on state. As further analyzed in the Rationale, a possible equilibrium outcome is 78.5% under current usage pattern and 64.7% even if users only create half as many state bytes for every gas they spend on other operations, relative to today. This impedes scaling under the current one-dimensional fee market, because state gas crowds out gas that can be used for other resources such as compute.

To confidently target some specific state growth, it is necessary to dynamically vary the price of state creation according to its usage. The [EIP-4844](/EIPs/EIPS/eip-4844) mechanism is then particularly suitable. This proposal tracks `state_bytes_created` and `state_bytes_cleared` each block and keep a running counter of `excess_state_bytes`. When `state_bytes_created - state_bytes_cleared` exceeds the target, `excess_state_bytes` increases, resulting in an increase to the gas charged per state byte. Users should not need to attach excessive margins to the transaction gas limit without risking transactions failure, and the gas charged per state byte is thus set to vary very moderately between blocks, at 0.1% at the very most.

To not impede scaling when a higher gas is charged per state byte, it is necessary to exempt state gas from the block gas limit. This is achieved by tracking the `regular_gas` and `state_gas` separately, having a separate limit for each. To ensure that the base fee still prices usage across all resources, the base fee update still operates on a normalized aggregate of both. Thus, the smooth shift in the gas charged per state byte can be understood as a separate control mechanism for pricing state *relative* to all other operations, facilitating good load-balancing over time. It is however not a mechanism that prices state creation in isolation—the base fee still applies to all resources.

## Specification 

The full specification is available [here](https://github.com/ethereum/execution-specs/commit/d64f82b18db8c0ae35f3c56e1762ace9d83ba578).

### Parameters

Four constants have a similar role as in EIP-4844.

| Constant | Value 
| - | - |
| `STATE_GAS_UPDATE_FRACTION`    | `36_418_000` |
| `TARGET_STATE_BYTES_PER_BLOCK` | `36_400` |
| `MAX_STATE_BYTES_PER_BLOCK`    | `2 * TARGET_STATE_BYTES_PER_BLOCK` |
| `MIN_STATE_GAS_PER_BYTE`       | `380` |

The `STATE_GAS_UPDATE_FRACTION` is chosen so that a block that uses `MAX_STATE_BYTES_PER_BLOCK` can increase state_gas_per_byte by at most 0.1%. It was computed as `(MAX_STATE_BYTES_PER_BLOCK - TARGET_STATE_BYTES_PER_BLOCK) / ln(1.001)`, rounded to the nearest thousand.

The number of bytes assigned to each state operation follows EIP-8037.

| Constant | Value 
| - | - |
| `CREATE_BYTES`            | `112` |
| `CODE_DEPOSIT_BYTES`      |   `1` | 
| `NEW_ACCOUNT_BYTES`       | `112` |
| `STORAGE_SET_BYTES`       |  `32` |
| `PER_EMPTY_ACCOUNT_BYTES` | `112` |
| `PER_AUTH_BASE_BYTES`     |  `23` |

### Header extension

The current header encoding is extended with three new 64-bit unsigned integer fields.

* `state_bytes_created` is the number of state bytes that were created in the current block.
* `state_bytes_cleared` is the number of state bytes that were cleared in the current block.
* `excess_state_bytes` is a running total of state bytes created in excess of the target, prior to the block. Blocks with above-target state bytes creation increase this value, blocks with below-target state bytes creation decrease it (bounded at 0).

The header sequence of the new fields is `[..., TBD, state_bytes_created, state_bytes_cleared, excess_state_bytes]`. 

We also rename the `gas_used` field to `regular_gas_used`:

* `regular_gas_used` is the regular gas used in the block, ignoring gas spent on state creation.

### EVM gas accounting

During processing, the protocol tracks `regular_gas` and `state_gas` separately, and returns the aggregate `gas_used` accounting for refunds, similar to today. Furthermore, `regular_gas_used` (without refunds to satisfy [EIP-7778](/EIPs/EIPS/eip-7778)) is returned to count against the block limit. Finally, the protocol also tracks `state_bytes_created` and `state_bytes_cleared`, allowing for a more accurate tracking of the `excess_state_bytes`. These are returned in the list `state_bytes(created, cleared)`.

### Computing the state gas per byte

The protocol keeps track of `excess_state_bytes`, and computes the `state_gas_per_byte` from that variable (referred to as `cost_per_state_byte` in EIP-8037). The same update mechanism as in EIP-4844 is applied. 

```python
def get_state_gas_per_byte(header: Header) -&gt; int:
    return fake_exponential(
        MIN_STATE_GAS_PER_BYTE,
        header.excess_state_bytes,
        STATE_GAS_UPDATE_FRACTION
    )
```

The `STATE_GAS_UPDATE_FRACTION` is set so that the maximum increase in `state_gas_per_byte` is 0.1%, when a block consumes `MAX_STATE_BYTES_PER_BLOCK`. The `state_gas_per_byte` has a floor of `MIN_STATE_GAS_PER_BYTE`, corresponding to EIP-8037 when scaled down to a 60M block gas limit. The `excess_state_bytes` are updated as in EIP-4844, but accounting for both created and cleared state bytes:

```python
def calc_excess_state_bytes(parent: Header) -&gt; int:
    excess = parent.excess_state_bytes + parent.state_bytes_created
    deficit = TARGET_STATE_BYTES_PER_BLOCK + parent.state_bytes_cleared

    if excess &lt; deficit:
        return 0
    else:
        return excess - deficit
```

### Updating state gas costs for the block 

The block level gas cost for each state operation is computed as `GAS_STATE_OPERATION = STATE_OPERATION_BYTES * state_gas_per_byte`. For completeness, the function below specifies this for all operations:

```python
def update_state_op_costs(state_gas_per_byte: int) -&gt; None:
    GAS_CREATE             = state_gas_per_byte * CREATE_BYTES
    GAS_CODE_DEPOSIT       = state_gas_per_byte * CODE_DEPOSIT_BYTES
    GAS_NEW_ACCOUNT        = state_gas_per_byte * NEW_ACCOUNT_BYTES
    GAS_STORAGE_SET        = state_gas_per_byte * STORAGE_SET_BYTES
    PER_EMPTY_ACCOUNT_COST = state_gas_per_byte * PER_EMPTY_ACCOUNT_BYTES
    PER_AUTH_BASE_COST     = state_gas_per_byte * PER_AUTH_BASE_BYTES
```

### Base fee update rule

The base fee is updated by aggregating the regular gas and &quot;normalized state gas&quot;, where a net change of `MAX_STATE_BYTES_PER_BLOCK` corresponds to the block&apos;s gas limit, thus giving state gas the same range as regular gas. The change is still restricted to the range ±12.5%. When not conditioning against negative values, the `gas_used_delta` used in the base fee update can for the EIP-1559 mechanism thus be computed as:

```python
    normalized_state_gas_used = parent.gas_limit * (parent.state_bytes_created - parent.state_bytes_cleared) // MAX_STATE_BYTES_PER_BLOCK
    gas_used_delta = (parent.regular_gas_used + normalized_state_gas_used - parent.gas_limit) // 2
```

### Block validation

The transaction&apos;s `gas_used` is computed as the sum of `regular_gas` and `state_gas` and includes refunds, similar to how `gas_used` is applied today. The `regular_gas_used` is returned without refunds, which the [EIP-1559](/EIPs/EIPS/eip-1559) cumulative gas at the block level accounts for. We also keep track of the cumulative `state_bytes_created` and `state_bytes_cleared` in the vector `state_bytes`.

```python
def validate_block(block: Block) -&gt; None:
    ...

    # Check that the excess state bytes was updated correctly
    assert block.header.excess_state_bytes == calc_excess_state_bytes(block.parent.header)
    # Compute the per-block state_gas_per_byte and update state-op gas costs
    state_gas_per_byte = get_state_gas_per_byte(block.header)
    update_state_op_costs(state_gas_per_byte)

    state_bytes_created = 0
    state_bytes_cleared = 0
    for tx in block.transactions:
        ...

        # Transaction execution returns a gas_used vector and refund_vector
        gas_used, regular_gas_used, state_bytes = self.execute_transaction(transaction, effective_gas_price)
        # The gas refund stays the same, the transaction gas counter only counts regular gas without refunds
        gas_refund = transaction.gas_limit - gas_used
        cumulative_transaction_gas_used += regular_gas_used
        # Update the total state bytes created and cleared in the block
        state_bytes_created += state_bytes[0]
        state_bytes_cleared += state_bytes[1]
        ...
    
    # Ensure the net state bytes created are within the per-block limit
    assert state_bytes_created &lt;= MAX_STATE_BYTES_PER_BLOCK + state_bytes_cleared
    # Ensure state_bytes_created and state_bytes_cleared matches header
    assert state_bytes_created == block.header.state_bytes_created
    assert state_bytes_cleared == block.header.state_bytes_cleared
    ...
```

## Rationale

### Potential concerns with current EIP-8037

EIP-8037 sets a fixed price of 1900 gas per byte, which can lead to a range of outcomes, depending on, e.g., the price-elasticity of demand for state creation. A specific concern is that since EIP-8037 counts state gas against the regular block gas limit, it may impede scaling, when users consume relatively more state gas at the higher gas per byte charged after the change. EIP-8037 assumes that users will spend 30% of all gas on state gas, just as today, even if the state gas per state byte is increased close to tenfold. This assumption may not hold.

Ideally, an increase in the gas cost for state creation will lead users and developers to reduce usage of these operations, relative to other operations. As an example, some may opt to use an existing ETH address instead of creating a new one for each CEX withdrawal. However, given that state creation is a rather fundamental part of interacting with a blockchain, it is reasonable to suspect that many other usage patterns remain as today. Furthermore, an increase in the gas limit as Ethereum scales is associated with a general drop in the base fee. Thus, even if state creation becomes relatively more expensive than other operations, the reduced base fee may mean that users do not take notice to the extent that is desired.

Assume that 30% of all consumed gas is state gas at 60M gas limit, producing 102 GiB in state growth per year (286 MiB/day). Then scale the L1 by $5x$ up to a 300M gas limit and increase the gas cost for state creation by $8.5x$ (using account creation in EIP-8037 as a reference point), while usage patterns do not change. The equilibrium outcome is then that $100 \times 0.3 \times 8.5 / (0.3 \times 8.5 + 0.7) = 78.5\%$ of all gas is spent on state. Even though Ethereum scaled the gas limit by $5x$, the real achieved scaling is only $5 \times (1 - 0.785) / 0.7 = 1.54x$, and state growth is 157 GiB per year (440 MiB/day).

The first example assumes no change in usage behavior and illustrates a general effect that might take place, but somewhat less pronounced. Assume instead that usage patterns indeed change, and that users create half as many state bytes for every gas they spend on other operations, in comparison to how they interact with Ethereum today. In this case, the equilibrium outcome is that $100 \times (0.3 \times 8.5 \times 0.5) / (0.3 \times 8.5 \times 0.5 + 0.7) = 64.7\%$ of all gas is spent on state. When scaling the gas limit by $5x$, the real achieved scaling is $5 \times (1 - 0.647) / 0.7 = 2.52x$, and state growth is 129 GiB per year (363 MiB/day).

Exempting state from the gas limit applied to regular gas—as proposed in this EIP—would produce a $7.14x$ in scaling (for non-state operations). We would thus achieve close to three times as much throughput as achieved in the example where users halve their state purchases relative to other operations (because they would still spend 64.7% of all available gas on state creation).


### Alternative specifications

Alternative solutions would ideally adhere to the principles outlined in this EIP, specifically:

1. It is necessary to exempt state from the aggregated regular gas limit, and assign state its own limit. Otherwise, as the gas cost for state is increased, the reduction in gas remaining for other operations will impede scaling.
2. It is not possible to guarantee some specific state expansion just by altering gas costs, given that the price-elasticity of demand is unknown. For this reason, it is desirable to set the cost of state independently and according to its usage. At the same time, a fixed increase in the state gas cost will always help in reducing state consumption to some extent, but there is then also always a risk of overshooting.

#### Multidimensional subfee market

One variant is to expand the transaction format, using a separate `regular_gas_limit` and `state_byte_limit` while removing the current `gas_limit`. At the beginning of processing a transaction, the protocol computes:

```python
gas_limit = regular_gas_limit + state_gas_per_byte * state_byte_limit
```

All further processing is applied as if the transaction had specified the computed `gas_limit` in the first place. This ensures that users do not need to risk having a transaction fail if the `state_gas_per_byte` drifts significantly between submission and execution, if they set a tight `gas_limit`. They simply specify how much regular gas they will use and how many state-bytes they will add, which then implies a certain `gas_limit` at execution time. The idea has certain similarities with the &quot;aggregated gas&quot; concept explored in [EIP-7999](/EIPs/EIPS/eip-7999), but the separate fee here influences how much gas that a resource consumes, hence the name &quot;Multidimensional subfee market&quot;. A benefit of the approach is that it offers perfect control over state growth while there is no fee-drift that can make a transaction fail. A downside is that the transaction format must be updated. It would be possible to move to a multidimensional subfee market at a later stage, after first implementing this proposal.

#### Multidimensional gas metering

It is possible to try to achieve the stated goals with multidimensional gas metering of [EIP-8011](/EIPs/EIPS/eip-8011). The difference between the proposal and the EIP-8011 mechanism is that the latter would not have a separate price for state. It uses the `max` of the gas consumption among resources for the base fee update. The base fee update may thus for example be set either from the `regular_gas` or the `state_gas`, depending on which that is used the most in the block. This means that there is less control over state growth due to the interaction between resources. When another resource consumes the most gas, it will also set the price for state.  When state is the most consumed resource, it might raise the price for other resources to a level where scaling is impeded. These types of interactions can be optimized by careful tuning of limits, targets and gas costs, although whatever setting that is decided on may never be fully satisfactory. The benefit is that the gas cost set for state can be fixed, while state still is &quot;exempted&quot; from the regular gas limit, since it only influences the base fee in parallel via the `max` operation. Thus scaling is mostly preserved.

Finally, it is possible to use the `max` of the gas consumption among resources for the base fee update, while still retaining the separate EIP-4844 mechanism for the `state_gas_per_byte`. This just represents another way to update the base fee, instead of the aggregation proposed here.

#### Multidimensional fee market with aggregate gas

The multidimensional fee market with aggregate gas specified in [EIP-7999](/EIPs/EIPS/eip-7999) could be applied without changing the transaction format. The gas cost for state creation is fixed and users set a single `gas_limit`. The fee for the gas for state creation is however completely separate in `fee_per_state_gas`, instead of being folded into the gas cost through conversion. Users set a `max_fee_per_gas` as today and the total fee they are willing to pay is computed as `max_fee = max_fee_per_gas * gas_limit`. This fee is compared with the fee determined during execution: `fee_per_state_gas * state_gas + base_fee_per_gas * regular_gas`. The benefit is that the gas cost cannot drift between transaction submission and execution, while the transaction format still stays the same. The downside is that if a users sets a tight `max_fee_per_gas`, then the builder cannot be sure before execution whether the fee covers the cost of the transaction. The user would need to set a more permissive `max_fee_per_gas` that covers the higher of `base_fee_per_gas` and `fee_per_state_gas` to provide full guarantees.

### Combination with multidimensional gas metering

This EIP works well with a broader adoption of full multidimensional gas metering, as proposed in EIP-8011, if we at the same time also adopt the EIP-8011 mechanism for updating the base fee, as suggested previously. We would then expand the `gas_used_per_resource` vector to track also the other resources in separation. State would still be treated differently in that it has its own `state_gas_per_byte` cost derived from the `excess_state_bytes`, whereas other resources are priced directly via the base fee. The metering approach of EIP-8011 is then applied to set the base fee. Given that state is increasingly becoming the major resource contraint (and thus pricing constraint) as we try to limit its usage, it is particularly beneficial that this EIP would allow the EIP-8011 metering to only be applied to the remaining resources. This is likely to benefit scaling further. Note further that the special treatment of the `code_deposit_gas` proposed in [EIP-8037](/EIPs/EIPS/eip-8037) would not be necessary with this proposal, because the constraint on state bytes per block is more moderate.

## Backwards Compatibility

The gas consumed by state creation operations will slowly change so that state growth is maintained at a desirable level. The speed of that drift is tuned by adjusting the `STATE_GAS_UPDATE_FRACTION`. This constant must be set to a level where UX concerns are mitigated. Specifically, the main concern is that if a transaction sets a very tight `gas_limit` while consuming state bytes, then that `gas_limit` may be exceeded, if the `state_gas_per_byte` cost derived from the `excess_state_bytes` shifts between submission and execution. The transaction would thus fail. Wallets must first fetch the `excess_state_bytes` and compute `state_gas_per_byte`, just as for the `blob_base_fee` (and `base_fee`) today. They know how many `state_bytes` that are created from each op-code of the transaction via the constants inherited from EIP-8037, e.g., `NEW_ACCOUNT_BYTES = 112`. They then simply add a margin `m` when computing the `gas_limit` set for the transaction: `gas_limit = regular_gas_limit + state_bytes * state_gas_per_byte * m`. The margin is tuned to the variation in `state_gas_per_byte` that is expected before execution, at the upper limit. The wallet may of course add some margin to their estimate for the `regular_gas_limit` of other op-codes as well when computing the `gas_limit`. The difference to the alternative &quot;Multidimensional subfee market&quot; outlined previously is thus that the wallet does not send a `regular_gas_limit` and `state_bytes_limit` separately, and instead combine them in order to preserve the current transaction format.

## Security Considerations

Wallets must have a margin when they set the `gas_limit` so that the transaction does not fail.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 02 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8075</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8075</guid>
      </item>
    
      <item>
        <title>eth/XX - announce transactions with nonce</title>
        <category>Standards Track/Networking</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8077-eth-xx-add-nonce-and-source-to-transactions-announcement/26505</comments>
        
        <description>## Abstract

This EIP improves mempool propagation, extending the devp2p &apos;eth&apos; protocol&apos;s `NewPooledTransactionHashes` message to also announce each transaction&apos;s source address and nonce together with the already announced hash, type, and size.

## Motivation

Transactions are propagated in the Mempool using the devp2p protocol in two modalities. Eager push is only used for small transactions, and only towards a few nodes, while the rest of nodes receive only announcements. For large transactions and for type 3 transactions, only announcements are sent. This announcement is made using the `NewPooledTransactionHashes` message, which only contains the hash, the type and the size of each transaction. As it is now, the receiver of the announcement does not have enough information to make intelligent scheduling choices. This crates several issues:

- the receiver of the announcement can only base its logic on the order of announcements, but if it schedules requests to different peers, it can easily end up pulling transactions that leave a nonce gap in it&apos;s own view of the mempool, making the pulled transaction non-includable,
- filling existing gaps is hard, since in the absence of sender/nonce information it can only be done with trial and error, requesting more transactions of missing hashes,
- to filter out old transaction announcements, the node has to keep a cache of all transaction hashes on chain, instead of simply checking the nonce against current chain state,
- receivers have no way to selectively request transactions with specific source addresses, which would be important UX and L2s. 

Moreover, as we are increasing the throughput of block building, it is more and more probable that we end up in a state where nodes can&apos;t fetch all transactions. This extension allows nodes to do selective fetching and gap filling while keeping a consistent state of their own view of the mempool without nonce gaps.

## Specification

### NewPooledTransactionHashes message changes

Modify the NewPooledTransactionHashes (0x08) message as follows:

(eth/69): [txtypes: B, [txsize₁: P, txsize₂: P, ...], [txhash₁: B_32, txhash₂: B_32, ...]]

(eth/XX): [txtypes: B, [txsize₁: P, txsize₂: P, ...], [txhash₁: B_32, txhash₂: B_32, ...], [txsource₁: B_20, txsource₂: B_20, ...], [txnonce₁: P, txnonce₂: P, ...]]

### Changes to message handling

Changes on the sender side of `NewPooledTransactionHashes` messages are trivial. Only the transmitted data changes. Since the size of announcements is increased, implementations MAY revisit the condition (typically transaction size) to select between eager push and announcement.

At the receiver side of `NewPooledTransactionHashes` messages the extra information can be used to improve scheduling choices, however these are not mandated by the protocol and thus we leave it to implementations.

## Rationale

To solve the transaction propagation issues mentioned in the Motivation section, nodes require more information about a transaction then its hash, size, and type. By adding the source and the nonce, the receiver has enough information to make better fetch decisions.

### Overhead

The modification adds a significant overhead to announcements by adding a B_20 and a variable size filed to the current B_32, size, and type fields. We think this overhead is worth
the additional gain in protocol efficiency. Details TBD &lt;-- TODO --&gt; .

### Alternatives

While the modification is relatively straightforward, there are several design variants to
consider. First of all, small transactions are mostly propagating by the push mechanism, while
announcement based pull is only used as recovery. We could choose to avoid the extra announcement overhead for these, however it would mean that filling nonce gaps remains difficult, only possible by trial-and-error.

Another possibility similar to the previous one is to restrict the mechanism to blob transactions only. We choose not to restrict it in the proposal for the same reasons as in the previous point.

If the traffic overhead from notifications is a concern, it is also worth considering how many nodes should announcements be sent to. While this is not mandated by the protocol, a typical implementation is to send announcements to all neighbors (except the ones that already signaled having it, and the ones to which the message is pushed). Should nodes send announcements to all peers, or only part of their peer set (e.g. proportional, or to a fixed number of peers)? The protocol allows to only part, and in case of bandwidth constraints it seems better to send more metadata (addresses and nonces) to fewer peers.

Currently, for any given transaction, nodes receive announcements from many peers. About half of their peers, on average. Having the whole metadata (txhash, type, size, source, nonce) in all these is highly redundant. We could remove some of this overhead, e.g. by having a probabilistic choice between a simple announcement and a detailed announcement. The gain however seems marginal compared to the added complexity.

Sending the source and the nonce opens up the possibility of a design variant where the transaction identifier in the announcements is based on these values, and not on the txhash. More specifically, a transaction could be identified by the source, the nonce, and an extra version number signaling the RBF (replace-by-fee) version in the given source/nonce scope. This variant would require deeper changes since the RBF version would need to be signed.

As an alternative to the above, fee values can be used as a proxy for the RBF version. Since the RBF requirement is anyway fee based, and the fee is already signed, adding the fee information to the announcement allows the receiver to compare different versions and pull the newer one. Moreover, having the fee information already in the announcement also allows nodes to anticipate their transaction ordering decisions and avoid pulling transactions that would be dropped, providing further traffic reduction.

## Backwards Compatibility

This EIP changes the eth protocol and requires rolling out a new version. Supporting multiple versions of a wire protocol is routine practice. Rolling out this new version does not break older clients, since they can keep using the previous protocol version.

This EIP does not change consensus rules of the EVM and does not require a hard fork.

## Security Considerations

The announced source address and nonce cannot be verified by the recipient until the transaction is actually fetched (or received through eager push). Therefore, it should not be handled as trusted information. This does not compromise the security of the protocol.

A mismatch between the announced &lt;txhash,type,size,address,nonce&gt; tuple and a received transaction should be handled as a protocol violation. More in detail, after the verification of the transaction hash, it becomes clear that the sender of the announcement was either malicious, or it sent an announcement without verifying its content. Thus, the sender of the offending announcement can be treated as a node that violated the protocol.

## Copyright

Copyright and related rights waived via CC0.
</description>
        <pubDate>Fri, 07 Nov 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8077</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8077</guid>
      </item>
    
      <item>
        <title>Native rollups</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8079-native-rollups/26565</comments>
        
        <description>## Abstract

Expose the state transition function to the execution layer via a new `EXECUTE` precompile.

## Motivation

Today, EVM-equivalent rollups need to implement and maintain complex proof systems just to be able to replicate what Ethereum already provides on L1. Such complexity significantly increases the probability of encountering bugs and prevents projects from getting rid of security councils and from moving to Stage 2. EVM-equivalent projects are not similar enough and lack the proper incentives to benefit from each other efforts, significantly delaying multi-proof systems.

Moreover, to maintain feature parity with Ethereum, rollups need to implement bespoke governance systems that can&apos;t be forced to follow Ethereum&apos;s governance decisions, and thus are free to arbitrarily diverge from it. Because of this, the best that an EVM-equivalent rollup can do is to provide long exit windows for their users, to protect them from its governance going rogue. No finite (and reasonable) exit window can protect all use-cases, especially those that rely on timelocks (governance, staking contracts, vesting contracts). Longer exit windows protect more use-cases, at the cost of increase un-equivalence time.

This EIP provides a way for rollups to reuse Ethereum&apos;s state transition verification infrastructure, and as a consequence massively simplify their infrastructure and upgrade processes. This enables projects to better redirect resources towards user-facing features and products.

## Specification

### Parameters

&lt;!-- TODO --&gt;

| Constant | Value |
| - | - |
| `PROOF_TX_TYPE` | `Bytes1(TBD)` |
| `EXECUTE_PRECOMPILE_ADDRESS` | `TBD` |
| `ANCHOR_ADDRESS` | `TBD` |

### `EXECUTE` precompile

Add a precompile at `EXECUTE_PRECOMPILE_ADDRESS` that verifies a state transition function with the provided inputs.

The precompile executes the following logic:

&lt;!-- TODO --&gt;

```py
def execute(input: Bytes) -&gt; Bytes:
    &quot;&quot;&quot;
    Verify a `state_transition(chain: BlockChain, block: Block)`.
    Disable blob transactions and perform anchoring to enable L1-&gt;L2 messaging.
    &quot;&quot;&quot;

    chain = input[...] # TBD
    block = input[...] # TBD
    anchor = input[...] # TBD

    transactions = get_transactions(block)

    # Blob-carrying transactions are not supported
    for tx in map(decode_transaction, transactions):
        if isinstance(tx, BlobTransaction):
            raise ExecuteError

    block_env = get_block_env(chain, block)

    # Perform anchoring
    process_unchecked_system_transaction(
        block_env     =block_env,
        target_address=ANCHOR_ADDRESS,
        data          =anchor
    )

    state_transition(chain, block)

    return Bytes(...) # TBD
```

### Header extension

The current header encoding is extended with a new 64-bit unsigned integer field representing the total amount of native tokens burned in the current block as part of the base fee.

The resulting RLP encoding of the header is therefore:

```
execution_payload_header_rlp = RLP([
  parent_hash,
  0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347, # ommers hash
  coinbase,
  state_root,
  txs_root,
  receipts_root,
  logs_bloom,
  0, # difficulty
  number,
  gas_limit,
  gas_used,
  timestamp,
  extradata,
  prev_randao,
  0x0000000000000000, # nonce
  base_fee_per_gas,
  withdrawals_root,
  burned_fees
])
```

The cumulative value of `burned_fees` can be calculated as follows:

```py
burned_fees = effective_gas_fee - gas_refund_amount - transaction_fee + blob_gas_fee
```

By making the value available for L1, it is also automatically made available for native rollups too.

### Proof-carrying transactions

&lt;!-- TODO --&gt;

TBD: heavily depends on the ZK L1 design.

## Rationale

### Programmable &quot;consensus layer&quot;

The `EXECUTE` precompile allows rollups to define their own inputs and constrained their behaviour through smart contract. For example, in contrast to Ethereum&apos;s own consensus layer, a rollup can decide to:

- Restrict the use of transactions that are sequenced by a permissioned entity, allowing for centralized sequencing and fast pre-confirmations, or leaving it open to everyone (based sequencing), or restrict it to a staked sequencer network;
- Fix the `coinbase` address to be a DAO-controlled treasury, independent from the proposer address;
- Tweak gas limits or prices based on specific needs;

This allows projects to preserve most of their configurations they already benefits from.

### Gas tokens

Several rollups implement new transaction types to be able to mint the rollup gas token when depositing funds on L1. We decide not to introduce complexity and instead rely on general L1-&gt;L2 messaging to unlock pre-minted tokens, as other existing projects already do. As a consequence, projects are free to decide what type of L1 interaction triggers the release of the rollup gas token, trivially enabling custom gas tokens without the need to modify the EVM behaviour at all.

### Anchoring

To support L1-&gt;L2 messages, rollups need to be able to &quot;anchor&quot; information from L1 to the L2. Inspired by [EIP-4788](/EIPs/EIPS/eip-4788) and existing implementations, we make use of a system transaction to inject a `bytes32 anchor` in the rollup state in a predeploy. This `anchor` can be used to relay L1&apos;s state root, a message root, or a rolling hash, or something completely different, based on design preferences.

The trade-off of this approach, compared to some existing ones based on custom transaction types, is that the L2 side of an L1-&gt;L2 message cannot have the `msg.sender` derived from the sender on L1, and therefore L1 access control-based smart contracts need to be adapted when deployed on L2 and used with cross-chain permissions. We believe this trade-off to be acceptable as the same scenario already exists when supporting L2-&gt;L1 access controls, as Ethereum is already not natively aware of the L2 sender.

### Basefee collection

While Ethereum burns the base fee, most rollups collect it for themselves, which enables opinionated funding models that are not possible on L1. To enable this use-case, and to minimize the code changes, we simply expose the amount of fees burned through the `burned_fees` block header value. Projects can now decide to ignore the value, burning the L2 base fee too, or credit the amount to some address, allowing for base fee collection from the L1-&gt;L2 token escrow.

### Re-execution vs ZK proofs

&lt;!-- TODO --&gt;
TBD

## Backwards Compatibility

Existing rollups can more or less easily migrate to being native based on their degree of equivalency, as native rollups do not support custom opcodes, custom precompiles or custom transaction types within the exposed state transition function.

## Test Cases

&lt;!-- TODO --&gt;
TBD

## Reference Implementation

&lt;!-- TODO --&gt;
TBD

## Security Considerations

&lt;!-- TODO --&gt;
TBD

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 13 Nov 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8079</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8079</guid>
      </item>
    
      <item>
        <title>Let exits use the consolidation queue</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8080-let-exits-use-the-consolidation-queue/26552</comments>
        
        <description>## Abstract

This EIP allows exits to be routed through the consolidation queue when it is shorter than the exit queue, consuming churn that is allocated to consolidations. This democratizes access to a feature that is currently only available to validators with at least 2048 ETH through a loophole in the consolidation logic. The protocol then makes more efficient usage of the churn that its security parameters (weak subjectivity period) allow, and is able to process more exits without any security reduction.

## Motivation

The existing design of consolidation mechanism allows validators with at least 2048 ETH to use the consolidation queue for exits through a loophole in the consolidation logic. When there is an imbalance between exit and consolidation queues favoring the latter, as has been the case since the introduction of the consolidation feature, this becomes an appealing way to speed up withdrawals. However, this feature is only available to a subset of validators, creating an unfair advantage.

Rather than removing this unintended feature, this EIP democratizes it by making it available to all exits. This approach preserves fairness by ensuring equal access to this efficiency improvement, while also providing concrete benefits to the network. When consolidation activity is low, the consolidation churn would otherwise go unused. By allowing exits to use this churn, we ensure it is not wasted and can be put to productive use. This is particularly important given the current state of exit queue congestion, as the exit queue has been longer than forty days for an extended period of time. Long queues degrade user experience, slow operator response to market or operational events, and reduce the network&apos;s ability to reconfigure stake more quickly after adverse events. Besides, solo stakers are arguably the participants that suffer the most from a lack of liquidity today, as they do not have the ability to issue a liquid staking token or maintain liquidity reserves.

By allowing exits to use consolidation churn when available, the maximum exit throughput increases significantly, without any security reduction since we are only reallocating churn that the protocol has already accounted for. In particular, the maximum exit churn that can be processed becomes `get_activation_exit_churn_limit(state) + 3 * get_consolidation_churn_limit(state) // 2`, where the `3 // 2` factor comes from the fact that one unit of exit churn corresponds to 2/3 of a unit of consolidation churn. With current parameters and with the current total stake approximately 35.7M ETH, this results in 256 (the capped exit churn) + (544 - 256) * 3/2 (the consolidation churn adjusted by the 3/2 factor) = 688 ETH per epoch, representing approximately a 2.5x increase over the current maximum exit churn of 256 ETH per epoch.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

Starting from the beginning of the epoch when this EIP is activated, Consensus Layer clients **MUST** use the modified `compute_exit_epoch_and_update_churn` function which routes exits through the consolidation queue when it is shorter than the exit queue.

### Modified `compute_exit_epoch_and_update_churn`

The only modification is this addition at the start of `compute_exit_epoch_and_update_churn`:

```python
    if state.earliest_exit_epoch &gt; state.earliest_consolidation_epoch:
        return compute_consolidation_epoch_and_update_churn(state, 2 * exit_balance // 3)
```

In particular, we route exits through the consolidation queue whenever `state.earliest_exit_epoch &gt; state.earliest_consolidation_epoch`, by using `compute_consolidation_epoch_and_update_churn`. Note that the `exit_balance` passed to the latter is only `2 * exit_balance // 3`, because each unit of exit churn corresponds to 2/3 units of consolidation churn from a weak subjectivity perspective. This way, we keep the weak subjectivity impact of the consolidation queue the same regardless of whether it is used by consolidations or by exits, maximizing the amount of operations we can process while keeping the same security guarantees.

The full function is as follows:

```python
def compute_exit_epoch_and_update_churn(state: BeaconState, exit_balance: Gwei) -&gt; Epoch:
    activation_exit_epoch = compute_activation_exit_epoch(get_current_epoch(state))
    earliest_exit_epoch = max(state.earliest_exit_epoch, activation_exit_epoch)

    # NEW in this EIP
    earliest_consolidation_epoch = max(state.earliest_consolidation_epoch, activation_exit_epoch)
    if earliest_exit_epoch &gt; earliest_consolidation_epoch:
        return compute_consolidation_epoch_and_update_churn(state, 2 * exit_balance // 3)

    # UNCHANGED FROM HERE
    per_epoch_churn = get_exit_churn_limit(state)
    # New epoch for exits.
    if state.earliest_exit_epoch &lt; earliest_exit_epoch:
        exit_balance_to_consume = per_epoch_churn
    else:
        exit_balance_to_consume = state.exit_balance_to_consume

    # Exit doesn&apos;t fit in the current earliest epoch.
    if exit_balance &gt; exit_balance_to_consume:
        balance_to_process = exit_balance - exit_balance_to_consume
        additional_epochs = (balance_to_process - 1) // per_epoch_churn + 1
        earliest_exit_epoch += additional_epochs
        exit_balance_to_consume += additional_epochs * per_epoch_churn

    # Consume the balance and update state variables.
    state.exit_balance_to_consume = exit_balance_to_consume - exit_balance
    state.earliest_exit_epoch = earliest_exit_epoch

    return state.earliest_exit_epoch
```

## Rationale

The decision to democratize access to this unintended feature, rather than removing it or keeping it as is, is driven by:

1. **Fairness**: All validators gain equal access to this efficiency improvement, rather than it being restricted to those with at least 2048 ETH who can exploit the loophole. 
2. **Efficiency**: When consolidation activity is low, the consolidation churn would otherwise go unused. By allowing exits to use this churn, we ensure it is not wasted and can be put to productive use, improving staking liquidity with unchanged security guarantees.  

To summarize, fairness is a strong motivation to either remove the feature or democratize it, and democratizing it is preferable to removing because we get a lot of efficiency benefits from it without any security cost.

## Backwards Compatibility

This EIP introduces backwards-incompatible changes to the Consensus Layer and must be activated via scheduled network upgrade.

## Test Cases

&lt;-- TODO --&gt;

## Security Considerations

### Weak subjectivity period

This EIP does not impact the weak subjectivity period at all. The total churn remains the same, it is just allocated differently. In particular, the conversion factor (`exit_balance * 2 // 3`) preserves the same weak subjectivity impact regardless of whether consolidation churn is allocated to exits or to consolidations.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 13 Nov 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8080</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8080</guid>
      </item>
    
      <item>
        <title>Hardfork Meta - Hegotá</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8081-hegota-network-upgrade-meta-thread/26876</comments>
        
        <description>## Abstract

This Meta EIP lists the EIPs formally Proposed, Considered, Declined for &amp; Scheduled for Inclusion in the Hegotá network upgrade.

## Specification

Definitions for `Scheduled for Inclusion`, `Considered for Inclusion`, `Declined for Inclusion` and `Proposed for Inclusion` can be found in [EIP-7723](/EIPs/EIPS/eip-7723).

### EIPs Scheduled for Inclusion

* [EIP-7805](/EIPs/EIPS/eip-7805): Fork-choice enforced Inclusion Lists (FOCIL)

### Considered for Inclusion

### Declined for Inclusion

### Proposed for Inclusion

### Activation

| Network Name | Activation Epoch | Activation Timestamp |
| ------------ | ---------------- | -------------------- |
| Sepolia      |                  |                      |
| Hoodi        |                  |                      |
| Mainnet      |                  |                      |

**Note**: rows in the table above will be filled as activation times are decided by client teams.

## Rationale

This Meta EIP provides a global view of all changes included in the network upgrade, as well as links to full specification.

## Security Considerations

None.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 11 Nov 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8081</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8081</guid>
      </item>
    
      <item>
        <title>Associated Accounts</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8092-associated-accounts/26858</comments>
        
        <description>## Abstract
This specification defines a standard for establishing and verifying associations between blockchain accounts. This allows addresses to publicly declare, prove and revoke a relationship with other addresses by sharing a standardized payload. For onchain applications, this payload may be signed by both parties for third-party authentication. This enables use cases like sub-account identity inheritance, authorization delegation, and reputation collation. 

## Motivation 
A key motivation is the simplification of multi-address resolution, which is essential for managing complex digital identities across multiple platforms and accounts. This simplification aims to streamline the process of locating and verifying individuals or entities by efficiently handling multiple addresses linked by Associations. 
By providing a standard mechanism for signaling an association between two accounts, this standard unlocks the capability to link the activities or details of these accounts. 

The inclusion of arbitrary data into the specified payload ensures flexibility for various use cases such as delegation, hierarchical relationships, and authentication. By maintaining a flexible architecture that accepts an interface identifier paired with arbitrary data bytes, accounts that associate can do so with application-specific context. 

The system outlined in this document describes a way for two accounts to be linked by a specified data struct which describes the relationship between them. It offers the mechanism by which these parties can sign over the contents to prove validity. It focuses on the structure and process for generating, validating and revoking such records while maintaining an implementation agnostic approach. 

## Specification
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.

### Core Concepts
Each Association between two accounts denotes the participating addresses as `initiator` and `approver`. These accounts can be on disparate chains with different architectures made possible by a combination of [ERC-7930](/EIPs/EIPS/eip-7930) Interoperable Addresses and an enumeration of signature key types. To accommodate non-EVM account types, addresses are recorded in the association as raw bytes.

The specification outlines a nested structure for recording Associations:
1. An underlying Associated Account Record (AAR) for storing accounts, timestamps and association context
2. A wrapper Signed Association Record (SAR) structure for storing signature and validation data

### Associated Account Record
The following is a Solidity implementation of an `AssociatedAccountRecord` which contains the shared payload describing the association.

```solidity
/// @notice Represents an association between two accounts.
struct AssociatedAccountRecord {
    /// @dev The ERC-7930 binary representation of the initiating account&apos;s address.
    bytes initiator;
    /// @dev The ERC-7930 binary representation of the approving account&apos;s address.
    bytes approver;
    /// @dev The timestamp from which the association is valid.
    uint40 validAt;
    /// @dev The timestamp when the association expires.
    uint40 validUntil;
    /// @dev Optional 4-byte selector for interfacing with the `data` field.
    bytes4 interfaceId;
    /// @dev Optional additional data.
    bytes data;
}
```
Where the AssociatedAccountRecord contains: 
- `initiator` is the binary representation of an ERC-7930 address for the initiating account. 
- `approver` is the binary representation of an ERC-7930 address for the approving account.
- `validAt` is the timestamp from which the association is valid.
- `validUntil` is the timestamp at which the association expires (optional).
- `interfaceId` is the 4-byte interface or method selector for the `data` field (optional).
- `data` is the arbitrary context data payload (optional).

### Signed Association Record
When `AssociatedAccountRecord`s will be consumed in a trustless context, integrators SHOULD require that both parties sign over the [EIP-712](/EIPs/EIPS/eip-712) hash of the `AssociatedAccountRecord` (see Support for EIP-712 below). The resulting signatures MUST be included in a `SignedAssociationRecord`. 

```solidity
    /// @notice Complete payload containing a finalized association.
    struct SignedAssociationRecord {
        /// @dev The timestamp the association was revoked.
        uint40 revokedAt;
        /// @dev The initiator key type specifier.
        bytes2 initiatorKeyType;
        /// @dev The approver key type specifier.
        bytes2 approverKeyType;
        /// @dev The signature of the initiator.
        bytes initiatorSignature;
        /// @dev The signature of the approver.
        bytes approverSignature;
        /// @dev The underlying AssociatedAccountRecord.
        AssociatedAccountRecord record;
    }
```
Where the SignedAssociationRecord contains: 
- `revokedAt` is the timestamp when the association was revoked, which is `0` unless the association has been revoked by either party. 
- `initiatorSignature` is the signature bytes generated by the `initiator` by signing the EIP-712 compliant hash of the AssociatedAccountRecord.
- `initiatorKeyType` is the key type designator for the initiator&apos;s signature (see Key Types below).
- `approverSignature` is the signature bytes generated by the `approver` by signing the EIP-712 compliant hash of the AssociatedAccountRecord.
- `approverKeyType` is the key type designator for the approver&apos;s signature (see Key Types below).
- `record` is the AssociatedAccountRecord that was signed by both parties. 

### Key Types
To accommodate known curves and signing protocols while providing future extensibility, this specification relies on the enumeration of cryptographic curves and signing protocols. Each signature MUST be paired with a valid &quot;Key ID&quot; designator.

The Key IDs SHALL be identified as a 2-byte integer according to the following extensible table. We accommodate two types of keys:
1. Applied cryptographic curves (i.e. secp256k1)
2. Protocol integrations (i.e. WebAuthn, contract validation)

To distinguish these key types, the most significant bit in the 2-byte identifier SHALL be used as a bit flag. As such, key type protocols are constructed by bitwise OR: 
`0x8000 | PROTOCOL_ID`. 

The resulting table enumerates the known keys and distinguishes between the two types: 

| Key ID | Type | Curve/Standard |
| -------- | -------- | -------- |
| 0x0000 | Delegated | Delegated auth |
| 0x0001 | K1 | secp256k1 |
| 0x0002 | R1 | secp256r1 |
| 0x0003 | BLS | BLS12-381 |
| 0x0004 | EdDSA | Ed25519 |
| 0x8001 | WebAuthn | WebAuthn/Passkey |
| 0x8002 | [ERC-1271](/EIPs/EIPS/eip-1271) | Contract validation |
| 0x8003 | [ERC-6492](/EIPs/EIPS/eip-6492) | Predeploy contract validation |

#### Delegated Auth
In some contexts it might be ergonomic to delegate authorization to another account, access control mechanism, or external protocol. Implementers leveraging the `Delegated` key type MUST also publish how consumers can parse the application-specific delegation schema.

### Support for EIP-712
All signatures contained in this specification MUST comply with EIP-712 wherein the signature preimage can be generated from:

```solidity
keccak256(abi.encodePacked(
   hex&quot;1901&quot;,
   DOMAIN_SEPARATOR,
   keccak256(abi.encode(
    keccak256(&quot;AssociatedAccountRecord(bytes initiator,bytes approver,uint40 validAt,uint40 validUntil,bytes4 interfaceId,bytes data)&quot;),
    keccak256(initiator), 
    keccak256(approver),
    validAt,
    validUntil,
    interfaceId,
    keccak256(data)
    ))
))
```

Where `DOMAIN_SEPARATOR` is defined according to EIP-712. The `DOMAIN_SEPARATOR` for this ERC SHALL be defined as: 
```solidity
keccak256(abi.encode(
    keccak256(&quot;EIP712Domain(string name,string version)&quot;),
    keccak256(bytes(&quot;AssociatedAccounts&quot;)),
    keccak256(bytes(&quot;1&quot;))
))
```

### Onchain Storage
If desired, a `SignedAssociationRecord` MAY be stored onchain in a context-specific storage contract.

An onchain storage contract SHALL comply with the following steps: 
1. The SAR MUST be validated according to the steps detailed in the Validation section. 
2. The contract MUST emit the `AssociationCreated` event:

```solidity
    event AssociationCreated(
        bytes32 indexed hash, bytes32 indexed initiator, bytes32 indexed approver, SignedAssociationRecord sar
    );
```
where:
- `hash` is the indexed hash for the SignedAssociationRecord, equivalent to the EIP-712 hash of the underlying AAR.
- `initiator` is the keccak256 hash of the ERC-7930 address of the account that initiated the association.
- `approver` is the keccak256 hash of the ERC-7930 address of the account that accepted and completed the association.
- `sar` is the completed SignedAssociationRecord. 

If a SignedAssociationRecord is stored onchain, it MUST also be revokable onchain (see Revocation section below). 

### Offchain Storage
In some contexts, it might be desirable for Signed Association Records to be stored in an offchain store. While the implementation will differ from application-to-application, the following considerations SHOULD be taken into account:
- Access to this data store MUST be made available to all expected consumers through publicly accessible endpoints
- The store MUST perform validation on incoming Associations before storage 
- The location of this offchain store SHOULD be searchable by some standard fetching mechanism, e.g. a text record on an ENS name

### Validation
Clients or contracts determining whether a SignedAssociationRecord is valid at the time of consumption MUST check all of the following validation steps:
1. The current timestamp MUST be greater than or equal to the `validAt` timestamp.
2. If the `validUntil` timestamp is nonzero, the current timestamp MUST be less than the `validUntil` timestamp. 
3. If the `revokedAt` timestamp is nonzero, the current timestamp MUST be less than the `revokedAt` timestamp.
4. If the `initiatorSignature` field is populated, the signature MUST be valid for the EIP-712 preimage of the underlying `AssociatedAccountRecord` using an appropriate `initiatorKeyType` validation mechanism. 
5. If the `approverSignature` field is populated, the signature MUST be valid for the EIP-712 preimage of the underlying `AssociatedAccountRecord` using an appropriate `approverKeyType` validation mechanism.

Onchain validation is possible as long as there are sufficient validation mechanisms for the various key types used by the two accounts. In the case that validation occurs onchain, implementations MUST replace &quot;current timestamp&quot; with `block.timestamp`. 

### Revocation
Onchain Association stores MUST implement a revocation method. This method MUST allow either party of an Association to revoke a valid, active association by submitting a revocation request. 

In such contexts, storage contracts MUST update the `revokedAt` field of the SAR to `block.timestamp` OR the account-specified revocation timestamp, whichever is greater. Then the implementation contract MUST emit the following event upon accepting a valid revocation request: 
```solidity
    event AssociationRevoked(bytes32 indexed hash, bytes32 indexed revokedBy, uint256 revokedAt);
```
where: 
- `hash` is the indexed unique identifier for the association, equivalent to the EIP-712 hash of the underlying AAR.
- `revokedBy` is the indexed keccak256 hash of the ERC-7930 address of the revoking account.
- `revokedAt` is the timestamp at which the association is revoked.

Offchain stores MUST allow either account to revoke a stored association and MUST update the `revokedAt` timestamp accordingly.

If a previously revoked association is revoked again with an earlier timestamp, the earlier timestamp MUST take precedence. 

## Rationale

### Nested Structure Design
The separation of `AssociatedAccountRecord` and `SignedAssociationRecord` into distinct structures serves a critical functional purpose. The inner `AssociatedAccountRecord` contains the immutable association payload that both parties must agree upon. This record can be shared, reviewed, and prepared while signatures are collected asynchronously from each party. The outer `SignedAssociationRecord` wrapper accumulates these signatures and metadata without modifying the underlying record. 

### Lack of Existing Standards
Currently, no standardized mechanism exists for establishing verifiable associations between blockchain accounts. Existing approaches are either application-specific or rely on proprietary schemas that limit interoperability. This specification addresses that gap by providing a common format that can be adopted across applications, enabling portability and composability of identity relationships.

### Supporting App-Scoped Sub Accounts
Today&apos;s blockchain ecosystem enforces a rigid one-to-one relationship between onchain identities and addresses, limiting users to a single address per identity. This specification breaks that constraint by enabling users to maintain a unified identity across multiple addresses. Users benefit from maintaining separate accounts for different contexts or applications while preserving the ability to verifiably link them to a primary identity when desired. This standard provides the mechanism for establishing these connections, enabling app-scoped sub accounts that can be provably associated with a root identity without sacrificing the flexibility and security benefits of address separation.

### Storage Agnosticism
Different association types have varying requirements for accessibility, cost, and decentralization. High-value associations requiring maximum trust minimization may warrant onchain storage despite higher costs, while frequent or ephemeral associations may be better suited for offchain stores. By remaining agnostic to storage location and requiring only that validation rules be consistently applied, this specification allows implementers to choose the appropriate tradeoffs for their use case without fragmenting the standard itself.

## Security Considerations
For onchain applications, the validation mechanisms for some key types might be gas-cost prohibitive or entirely unavailable. It is the responsibility of the integrator to ensure that unsupported key types are appropriately handled given these constraints.

Offchain stores expose a trust vector to consumers. Integrators and consumers MUST take into account this centralization vector and expose the risk to users or offer mechanisms for minimizing the trust assumptions (i.e. storing some state onchain).

Associations SHOULD have a canonical storage location given an application. However, in the event that the same Association data is stored both on and offchain, precedence SHOULD be given to the onchain data. 

## Copyright
Copyright and related rights waived via [CC0](/EIPs/LICENSE).</description>
        <pubDate>Tue, 25 Nov 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8092</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8092</guid>
      </item>
    
      <item>
        <title>eth/vhash - Blob-Aware Mempool</title>
        <category>Standards Track/Networking</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8094-eth-vhash-blob-aware-mempool/26834</comments>
        
        <description>## Abstract

This EIP eliminates the need to redistribute blob content in the mempool if only the metadata (fees) of a transaction are updated, making RBF (replace-by-fee) more efficient and cheaper for the network. It achieves this modifying the devp2p ‘eth’ protocol to address blobs in type 3 transaction sidecars by content (vhash).

## Motivation

In the current version of devp2p eth/69, when a transaction is replaced, it must be redistributed in the mempool like any new transaction. Even if the actual content is largely the same, protocol participants have no means to figure this out before getting the full content, making a replacement use the same amount of network resources as a new transaction would.

What is especially problematic is that RBF is used most in periods of fee volatility, and a network overload is the typical case of such a situation. Thus, when there is already high demand, we make the situation worse by adding
extra traffic redistributing blob content that was already distributed.

## Specification

### Transactions (0x02) changes

Type 3 transaction should be sent without sidecar

### PooledTransactions (0x0a) changes

Type 3 transaction should be sent without sidecar

### GetPooledBlobs (msg code to be assigned &lt;-- TODO --&gt;)

[request-id: P, [vhash₁: B_32, vhash₂: B_32, ...]]

This message requests blobs from the recipient&apos;s transaction pool by vhash.

### PooledBlobs (msg code to be assigned &lt;-- TODO --&gt;)

[request-id: P, [blob₁, blob₂...]]

This is the response to GetPooledBlobs, returning the requested blobs. The items in the list are blobs in the format described in the main Ethereum specification.

&gt; Note: optionally, we might prefix the blob format with the blob version number
&gt;
&gt; Note: optionally, we might decide to improve the blob format allowing nodes to reconstruct RS encoding instead of using extra bandwidth, by sending the following fields per blob:
&gt;
&gt; - blob version
&gt; - blob content, **excluding** the erasure coding extension in case of version 1
&gt; - blob commitment
&gt; - blob proof(s), **including** cell proofs of the erasure coded piece in case of version 1
&gt;
&gt; It is important to include all cell proofs to keep reconstruction CPU-efficient.

The blobs must be in the same order as in the request, but it is OK to skip blobs which are not available. Since the recipient have to check that transmitted blob hashes correspond to the requested vhashes anyway, we can avoid sending the list of vhashes as part of this message.

&gt; Note: Optionally, we could extend this message with a bitmap of sent/unsent blobs from the request, or with the list of vhashes sent. This information is redundant, but it can simplify processing on the receiver side.

### Other spec changes

EIP-4844 introduced the following:

    Nodes MUST NOT automatically broadcast blob transactions to their peers. Instead, those transactions are only announced using NewPooledTransactionHashes messages, and can then be manually requested via GetPooledTransactions.

The above should be changed as follows:

    Nodes MUST send (broadcast or send in NewPooledTransactionHashes) blob transaction **without** sidecars to their peers. Peers can then request blob content using `GetPooledBlobs` messages. Nodes MUST NOT forward blob transactions before receiving and validating all blobs&quot;.

## Rationale

A typical blob transaction RBF changes the fees only, while the sidecar (blob content) remains the same. If a node that has the previous version would know this, it could avoid pulling the sidecar, largely reducing bandwidth consumption. However, this is not possible with the current messaging. To make this happen, we have to expose blob (or at least sidecar) identifiers in mempool messaging.

### Should we use blob identifiers or a sidecar identifier?

We can either use vhashes, or a sidecar level hash. The latter has the slight advantage of being a single element, thus simplifying message format, but it has several disadvantages:

- It would be a new identifier, while the blob level vhash is already well established (just not in devp2p)
- It would not allow restructuring the message, sending e.g. less blobs under a fee surge

Thus, we use vhashes.

### Implementation options

There are several options to bring vhashes to devp2p messaging:

#### Option 1

- Extend announcements with vhashes
- Allow nodes to request transaction with/without sidecar content, or even selecting which parts are needed (bitmap or vhash list)

#### Option 2

- Extend announcements with nonce (see EIP-8077)
- If hash differs from what we have, request with/without sidecar content based on whether we already have the sidecars for the same nonce, assuming this is a simple replacement
- Request again with sidecar if vhashes differ

#### Option 3 (selected)

- Push (or announce and then pull) type 3 transaction **without sidecar**
- Allow to **request sidecar separately** (new message type)

At first it might seem that Option 3 is slowing down distribution, adding one more RTT latency per hop. However, since most type 3 transactions are small without a sidecar, we could change the protocol behaviour to allow pushing these transactions without the sidecar, leaving it to the receiver of the push to ask for the blobs if needed. Forwarding of type 3 transactions without sidecar should be prohibited until sidecars are fetched and the content can be verified.

After considering the above options, we chose to propose Option 3, introducing a new message type.

### Relation to other EIPs in draft state

- EIP-8077 (announce source and nonce): the changes can be simply combined.
- EIP-8070 (Sparse blobpool): both EIPs change how blob transactions are propagated over the network. The goal of the two EIPs are different. EIP-8070 is about a proportional bandwidth reduction in the normal case without dealing with specifics of RBF. This EIP is about enabling RBF without using extra bandwidth. The two EIPs can be combined, but the combination depends on the order of introduction, hence we leave this for later &lt;-- TODO --&gt;.

## Backwards Compatibility

This EIP changes the eth protocol and requires rolling out a new version. Supporting multiple versions of a wire protocol is routine practice. Rolling out this new version does not break older clients, since they can keep using the previous protocol version.

This EIP does not change consensus rules of the EVM and does not require a hard fork.

## Security Considerations

## Copyright

Copyright and related rights waived via CC0.
</description>
        <pubDate>Sat, 29 Nov 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8094</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8094</guid>
      </item>
    
      <item>
        <title>Increase Gas Cost of Point Evaluation</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8096-point-evaluation-precompile-gas-cost-increase/26867</comments>
        
        <description>## Abstract

This EIP modifies the gas cost of `point evaluation` precompile introduced in [EIP-4844](/EIPs/EIPS/eip-4844).

## Motivation

Currently the `point evaluation` precompile is underpriced relative to its resource consumption. This EIP aims to address these discrepancies by adjusting the gas cost and making `point evaluation` precompile sufficiently efficient to enable potential further increases in the block gas limit.

## Specification

Upon activation of this EIP, the gas cost of calling the precompile at address `0x000000000000000000000000000000000000000A` will be doubled from `50_000` gas to `100_000` gas.

## Rationale

Benchmarking the `point evaluation` precompile revealed that its gas cost is significantly underestimated. This modification aim to ensure that the `point evaluation` precompile&apos;s performance no longer impedes potential increases to the block gas limit.

## Backwards Compatibility

This EIP introduces a backwards-incompatible change. However, similar gas repricings have occurred multiple times in the Ethereum ecosystem, and their effects are well understood.

## Security Considerations

This EIP does not introduce any new functionality or make existing operations cheaper, therefore there are no direct security concerns related to new attack vectors or reduced cost.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 02 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8096</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8096</guid>
      </item>
    
      <item>
        <title>MEVless Protocol</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/mevless-an-anti-mev-protocol/26800</comments>
        
        <description>## Abstract

This proposal introduces the MEVless protocol, a novel approach to prevent Maximum Extractable Value (MEV) attacks by implementing blind transaction sequencing. The core principle of MEVless is to prevent validators from seeing transaction content during the ordering phase, thereby eliminating the fundamental prerequisite for MEV attacks. The protocol separates block production into two phases: sequencing blocks that order transactions based on transaction hashes without revealing transaction content, and execution blocks that execute transactions in the predetermined order. This design eliminates the ability of miners and validators to perform MEV attacks such as sandwich attacks and front-running by removing their access to transaction content during the critical ordering phase.

## Motivation

MEV attacks, particularly sandwich attacks and front-running, represent a significant threat to blockchain ecosystems, especially in DeFi applications. The fundamental prerequisite for MEV attacks is that validators can see transaction content before ordering, which allows them to:

1. **Sandwich Attacks**: Insert buy and sell transactions around user transactions to manipulate prices and extract value
2. **Front-running**: Execute similar transactions before users to capture arbitrage opportunities
3. **Back-running**: Execute transactions after users to benefit from price movements

Unlike legitimate arbitrage activities that provide liquidity, these attacks are purely extractive and harmful to the ecosystem. They reduce user confidence, increase transaction costs, and can lead to significant financial losses for users.

Current solutions have limitations:

- **Encrypted Mempools**: High computational overhead for encryption/decryption
- **Private Mempools**: Centralized and not fully decentralized, use trustful instead of trustless.
- **PBS (Proposer-Builder Separation)**: Still allows builders to see transaction content and becoming more and more centralized.

The MEVless protocol addresses these issues by fundamentally changing how transactions are ordered, making it impossible for miners to perform MEV attacks while maintaining decentralization and efficiency. By eliminating MEV attacks at the protocol level, DeFi developers can focus on building innovative financial products and user experiences without constantly worrying about MEV protection mechanisms, leading to faster development cycles and more robust applications.

## Specification

### Protocol Overview

The MEVless protocol operates on a two-phase block system:

1. **Sequencing Blocks**: Order transactions based on transaction hashes and prepayment amounts without revealing transaction content. Sequencing blocks interval can be shorter than execution blocks.
2. **Execution Blocks**: Execute transactions in the predetermined order from sequencing blocks

### Block Types

#### Sequencing Blocks

- **Purpose**: Order transactions and collect prepayments
- **Frequency**: Every odd-numbered block height
- **Operations**:
    - Receive transaction hashes from users
    - Collect prepayments (gas fees + optional tips)
    - Order transactions by prepayment amount (highest first)
    - Publish ordered transaction sequence as commitment
    - Store transaction hashes in block

#### Execution Blocks

- **Purpose**: Execute transactions in predetermined order
- **Frequency**: Every even-numbered block height
- **Operations**:
    - Receive transaction content from users
    - Verify transaction content matches committed hashes
    - Execute transactions in predetermined order

### Transaction Flow

#### Phase 1: Transaction Submission and Sequencing

1. User creates transaction and calculates transaction hash
2. User sends transaction hash to the network with prepayment:
    - **Base Gas Fee**: Fixed fee for hash storage and sequencing computation
    - **Optional Tip**: Additional payment for priority in sequencing
3. Network validates user has sufficient balance for prepayment
4. Network orders transaction hashes by total prepayment amount (descending)
5. Network deducts prepayment from user account
6. Network publishes ordered transaction sequence as commitment
7. Network stores transaction hashes in sequencing block

![MEVless Protocol Flow](/EIPs/assets/eip-8099/MEVless.png)
*MEVless Protocol Transaction Flow*

#### Phase 2: Transaction Content Submission and Execution

1. User monitors network for their transaction hash commitment
2. User submits actual transaction content(including the remaining gasfee) to network
3. Network receives transaction content during execution block
4. Network verifies transaction content matches committed hash
5. Network executes transactions in predetermined order, deduct the remaining fee and 50% of the actual difference between gasUsed and gaslimit for tax ( prevent the gasLimit much more than gasUsed so that validators can entire the whole block to get MEV)


### Gas Economics

#### Prepayment Structure

```
Total Prepayment = Base Gas Fee + Optional Tip
```

- **Base Gas Fee**: Fixed cost for hash storage and sequencing computation
- **Optional Tip**: Variable amount for priority in transaction ordering

#### Gas Cost Calculation

- **Sequencing Phase**: Minimal gas cost for hash operations
- **Execution Phase**: Standard gas cost for transaction execution

## Rationale

### Why Blind Sequencing?

Blind sequencing eliminates the root cause of MEV attacks by preventing miners from seeing transaction content during the critical ordering phase. This approach is more efficient than encryption-based solutions and more decentralized than private mempool approaches.

### Why Two-Phase Blocks?

Separating sequencing and execution allows for:

- **Efficient Ordering**: Hash-based ordering is computationally lightweight
- **Network Efficiency**: Small hash data reduces bandwidth requirements
- **Commitment Mechanism**: Public ordering commitment prevents manipulation

### Why Random Block Production is Critical?

Random block production is essential to prevent speculative MEV attacks. When block producers cannot predict when they will be selected to produce blocks, they cannot reliably perform speculative MEV attacks because:

- **Unpredictable Selection**: Attackers cannot know if they will be the next block producer
- **Economic Risk**: Speculative transactions require prepayments that are lost if the attacker is not selected
- **Decentralization Amplification**: More validators mean lower individual selection probability, increasing attack costs exponentially

## Backwards Compatibility

This protocol will add some RPC methods to support the two-phase block system:    

- **eth_sendTxHash**: Users submit transaction hashes instead of full transactions
- **eth_getTxSequence**: Returns the ordered transaction sequence that is committed

## Test Cases

### Basic Transaction Flow

1. User submits transaction hash with prepayment
2. Network orders transaction by prepayment amount
3. User submits transaction content
4. Network executes transaction in predetermined order

### MEV Attack Prevention

1. Attacker submits transaction hash for sandwich attack
2. Network orders transaction without revealing content
3. Attacker cannot see victim transaction content during ordering
4. Attack fails due to lack of transaction visibility

## Security Considerations

The MEVless protocol requires a consensus mechanism with unpredictable block production to prevent speculative MEV attacks. Without unpredictable block production, block producers can perform cost-free speculative MEV attacks by submitting transaction hashes and then deciding whether to submit their transaction content based on other users&apos; transaction content, thus performing cost-free speculative MEV attacks. Since the prepayment ultimately goes to the block producer themselves, predictable block production allows them to recover their prepayment costs through block fees, making MEV attacks economically viable. Random block production forces attackers to pay prepayments for speculative transactions without knowing if they will be selected to produce the next block, making the prepayment cost real rather than recoverable through block fees, thus making such attacks economically unviable. The anti-MEV effectiveness increases exponentially with network decentralization - more validators mean lower individual selection probability, making attacks economically unviable.   

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 25 Sep 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8099</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8099</guid>
      </item>
    
      <item>
        <title>Payload Chunking with Chunk Access Lists</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8101-payload-chunking/27085</comments>
        
        <description>## Abstract

This EIP introduces Payload Chunking, a protocol upgrade that restructures Ethereum block propagation into self-contained execution chunks with separated Chunk Access Lists (CALs). The proposer propagates beacon and execution payload headers, followed by CALs and chunks as independent network messages. CALs contain state diffs from chunk execution, enabling parallel chunk validation: chunk N can be validated once CALs 0..N are available. After all chunks validate successfully, the consensus layer finalizes the block. This architecture transforms block validation from a monolithic operation into a streaming pipeline while preserving block atomicity. Chunks exist only as a propagation and validation construct; the canonical chain stores complete execution payloads.

## Motivation

As Ethereum&apos;s gas limit increases, block sizes and execution complexity grow correspondingly. The current monolithic block structure requires validators to download and decompress the entire execution payload before beginning execution, creating a bottleneck in the consensus timeline. This sequential dependency—download, decompress, then execute—becomes increasingly problematic as blocks grow larger.

This proposal addresses these constraints by:

- **Parallel propagation**: Nodes propagate parts of the block separately, improving propagation speed through the network
- **Streaming validation**: Execution begins as chunks arrive rather than after full payload receipt
- **Parallel chunk execution**: CALs provide state diffs enabling independent validation of chunks
- **Bounded resources**: Per-chunk gas limits (`CHUNK_GAS_LIMIT = 2**24`) bound memory and CPU per validation unit
- **Early rejection**: Invalid blocks can be rejected at the first invalid chunk without processing remaining chunks
- **Proving compatibility**: Chunk boundaries create natural proving units for future ZK proving systems

## Specification

### Constants

| Name | Value | Description |
|------|-------|-------------|
| `CHUNK_GAS_LIMIT` | `2**24` (16,777,216) | Maximum gas per chunk, from [EIP-7825](/EIPs/EIPS/eip-7825) |
| `MAX_CHUNKS_PER_BLOCK` | `2**8` (256) | Maximum chunks per block |
| `MAX_TRANSACTIONS_PER_CHUNK` | `2**16` (65,536) | Maximum transactions per chunk |
| `CHUNK_INCLUSION_PROOF_DEPTH` | `floorlog2(get_generalized_index(BeaconBlockBody, &apos;chunk_headers_root&apos;)) + 1 + ceillog2(MAX_CHUNKS_PER_BLOCK)` (13) | SSZ Merkle proof depth for message inclusion |
| `MAX_CAL_SIZE` | `2**24` (16,777,216) | Maximum size in bytes of RLP-encoded CAL |

### Type Aliases

```python
ChunkIndex = uint8                  # Chunk position within block (0 to MAX_CHUNKS_PER_BLOCK-1)
Root = Bytes32                      # 32-byte hash (Merkle root or block root)
```

### Data Structures

#### Execution Chunk

```python
# Chunk header containing execution commitments
class ExecutionChunkHeader(Container):
    index: ChunkIndex                # Position in block [0, MAX_CHUNKS_PER_BLOCK)
    chunk_access_list_hash: Root     # keccak256(RLP(ChunkAccessList)) per EIP-7928
    pre_chunk_tx_count: uint32       # Cumulative transaction count before this chunk
    pre_chunk_gas_used: uint64       # Cumulative gas used before this chunk
    pre_chunk_blob_gas_used: uint64  # Cumulative blob gas used before this chunk
    txs_root: Root                   # Merkle root of chunk transactions
    gas_used: uint64                 # Gas consumed by this chunk
    blob_gas_used: uint64            # Blob gas consumed by this chunk
    withdrawals_root: Root           # Merkle root of withdrawals (non-empty only in last chunk)

# Self-contained execution chunk
class ExecutionChunk(Container):
    chunk_header: ExecutionChunkHeader
    transactions: List[Transaction, MAX_TRANSACTIONS_PER_CHUNK]
    withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD]  # Only in last chunk
```

#### Chunk Access Lists (CALs)

CALs are RLP-encoded structures following the Block Access List format from [EIP-7928](/EIPs/EIPS/eip-7928), scoped to individual chunks. Each CAL records state diffs produced by executing its corresponding chunk.

**Type Definitions:**

```python
Address = Bytes20              # Ethereum address
StorageKey = Bytes32           # Storage slot key
StorageValue = Bytes32         # Storage slot value
Balance = uint256              # Account balance
Nonce = uint64                 # Account nonce
CodeData = bytes               # Contract bytecode
TxIndex = uint16               # Transaction index within the block
```

**Change Structures:**

```python
StorageChange = [TxIndex, StorageValue]     # [tx_index, new_value]
BalanceChange = [TxIndex, Balance]          # [tx_index, post_balance]
NonceChange = [TxIndex, Nonce]              # [tx_index, new_nonce]
CodeChange = [TxIndex, CodeData]            # [tx_index, new_code]

SlotChanges = [StorageKey, List[StorageChange]]  # All changes to a single storage slot

AccountChanges = [
    Address,                   # Account address
    List[SlotChanges],         # Storage writes
    List[StorageKey],          # Storage reads (slots read but not written)
    List[BalanceChange],       # Balance changes
    List[NonceChange],         # Nonce changes
    List[CodeChange]           # Code deployments
]

ChunkAccessList = List[AccountChanges]
```

**CAL Properties:**

1. **Incremental**: Each CAL contains only the state diffs from its chunk. Changes from earlier chunks are not repeated.
2. **Independent**: CALs can be validated independently given the pre-state.

**System Contract Entries:**

- **First CAL (chunk 0)**: Includes pre-execution system writes ([EIP-2935](/EIPs/EIPS/eip-2935) block hash history, [EIP-4788](/EIPs/EIPS/eip-4788) beacon root)
- **Last CAL (chunk N-1)**: Includes post-execution system operations ([EIP-4895](/EIPs/EIPS/eip-4895) withdrawals, [EIP-7002](/EIPs/EIPS/eip-7002) and [EIP-7251](/EIPs/EIPS/eip-7251) validator operations)

#### ExecutionPayload and ExecutionPayloadHeader

The `ExecutionPayload` is no longer used and is replaced by `ExecutionPayloadHeader`. 

The `ExecutionPayloadHeader` is modified to include number of chunks in a block:

```python
class ExecutionPayloadHeader(Container):
    # ... existing fields ...
	chunk_count: uint8      # Number of chunks in block
```

#### Beacon Block Commitments

The beacon block body replaces `execution_payload` with `execution_payload_header` and includes two Merkle roots committing to chunks and CALs:

```python
class BeaconBlockBody(Container):
    # ... other existing fields ...
    # Removed `execution_payload`
    execution_payload_header: ExecutionPayloadHeader    # Execution payload header

    chunk_headers_root: Root                            # Commitment to all chunk headers
    chunk_access_lists_root: Root                       # Commitment to all CAL hashes
```

Note: If [EIP-7732](/EIPs/EIPS/eip-7732) (ePBS) is enabled, then `execution_payload` field of `ExecutionPayloadEnvelope` is replaced by `execution_payload_header` in the same way.

**Commitment construction:**

```python
# Chunk headers commitment (SSZ)
chunk_headers: List[ExecutionChunkHeader, MAX_CHUNKS_PER_BLOCK]
chunk_headers_root = hash_tree_root(chunk_headers)

# CAL commitment (SSZ hash of RLP-encoded CALs for CL inclusion proofs)
cal_hashes: List[Root, MAX_CHUNKS_PER_BLOCK]  # Each Root = hash_tree_root(ByteList(RLP(CAL)))
chunk_access_lists_root = hash_tree_root(cal_hashes)
```

Note: The EL uses `keccak256(RLP(CAL))` in chunk headers per [EIP-7928](/EIPs/EIPS/eip-7928). The CL uses SSZ `hash_tree_root` for inclusion proofs. Both reference the same RLP-encoded CAL data.

#### Network Topis

Chunks and CALs propagate as separate network message with SSZ Merkle inclusion proofs against the beacon block header.

```python
class ExecutionChunkMessage(Container):
    chunk: ExecutionChunk                                               # The execution chunk
    inclusion_proof: Vector[Bytes32, CHUNK_INCLUSION_PROOF_DEPTH]       # SSZ Merkle proof against signed_block_header.message.body_root
    signed_block_header: SignedBeaconBlockHeader                        # Signed beacon block header

class ChunkAccessListMessage(Container):
    chunk_index: ChunkIndex                                             # Chunk index this CAL corresponds to
    chunk_access_list: ByteList[MAX_CAL_SIZE]                           # RLP-encoded chunk access list
    inclusion_proof: Vector[Bytes32, CHUNK_INCLUSION_PROOF_DEPTH]       # SSZ Merkle proof against signed_block_header.message.body_root
    signed_block_header: SignedBeaconBlockHeader                        # Signed beacon block header
```

The `signed_block_header` provides the proposer signature for authentication and the beacon block root for proof verification.

### Chunk Construction Rules

Block producers MUST follow these rules when constructing chunks:

1. **Gas Bound**: Each chunk MUST satisfy `gas_used &lt;= CHUNK_GAS_LIMIT`
2. **Minimal Chunking**: For any two consecutive chunks `i` and `i+1`, their combined gas MUST exceed `CHUNK_GAS_LIMIT`. This ensures chunks cannot be trivially merged, preventing unnecessary fragmentation.
3. **Transaction Atomicity**: Transactions MUST NOT be split across chunks. Each transaction belongs entirely to one chunk.
4. **Withdrawal Placement**: Withdrawals MUST appear only in the final chunk. All other chunks have empty withdrawal lists.
5. **Chunk Count Bound**: A block MUST contain at most `MAX_CHUNKS_PER_BLOCK` chunks
6. **Sequential Indexing**: Chunks MUST be indexed sequentially from `0` to `N-1` where `N` is the total chunk count

### Network Protocol

#### Gossip Topics

Chunks and CALs propagate on dedicated gossip topics:

| Topic | Payload |
|-------|---------|
| `execution_chunk` | `ExecutionChunkMessage` |
| `chunk_access_list` | `ChunkAccessListMessage` |

#### Message Validation

Nodes MUST validate messages before forwarding:

**ExecutionChunkMessage validation:**

1. Verify `signed_block_header.signature` is valid for the proposer at the given slot
2. Verify `chunk.chunk_header.index &lt; MAX_CHUNKS_PER_BLOCK`
3. Verify `chunk.chunk_header.gas_used &lt;= CHUNK_GAS_LIMIT`
4. Verify `hash_tree_root(chunk.transactions) == chunk.chunk_header.txs_root`
5. Verify inclusion proof:

    ```python
    gindex = get_generalized_index(BeaconBlockBody, &apos;chunk_headers_root&apos;, chunk.chunk_header.index)
    is_valid_merkle_branch(
        leaf=hash_tree_root(chunk.chunk_header),
        branch=inclusion_proof,
        depth=CHUNK_INCLUSION_PROOF_DEPTH,
        index=get_subtree_index(gindex),
        root=signed_block_header.message.body_root,
    )
    ```

**ChunkAccessListMessage validation:**

1. Verify `signed_block_header.signature` is valid for the proposer at the given slot
2. Verify `chunk_index &lt; MAX_CHUNKS_PER_BLOCK`
3. Verify `len(chunk_access_list) &lt;= MAX_CAL_SIZE`
4. Verify inclusion proof:

    ```python
    gindex = get_generalized_index(BeaconBlockBody, &apos;chunk_access_lists_root&apos;, chunk_index)
    is_valid_merkle_branch(
        leaf=hash_tree_root(chunk_access_list),
        branch=inclusion_proof,
        depth=CHUNK_INCLUSION_PROOF_DEPTH,
        index=get_subtree_index(gindex),
        root=signed_block_header.message.body_root,
    )
    ```

Nodes MUST subscribe to chunk and CAL topics. Messages may be validated immediately using the signed block header without waiting for the full beacon block.

### Consensus Layer Changes

The consensus layer orchestrates chunk validation as beacon blocks, chunks, and CALs arrive from the network.

#### Types

```python
class ChunkExecutionStatus(Container):
    valid: bool
    error: Optional[str]
```

#### Store Extensions

```python
class Store:
    # ... existing fields ...

    # Tracks received CALs per block
    chunk_access_lists: Dict[Root, Set[ChunkIndex]]
    # Tracks received chunk headers per block
    chunk_headers: Dict[Root, Dict[ChunkIndex, ExecutionChunkHeader]]
    # Tracks chunk execution results per block
    chunk_execution_statuses: Dict[Root, Dict[ChunkIndex, ChunkExecutionStatus]]
    # Tracks final block validity
    block_valid: Dict[Root, bool]
```

#### Three-Phase Validation

##### Phase 1: CAL Reception

CALs are forwarded to the execution layer upon receipt. The EL caches CALs for use in subsequent chunk validation.

```python
def on_chunk_access_list_received(store: Store, cal_message: ChunkAccessListMessage) -&gt; None:
    # Derive beacon block root from signed header
    root = hash_tree_root(cal_message.signed_block_header.message)
    chunk_index = cal_message.chunk_index

    # Validate cal message (proposer signature, inclusion proof, index bounds)
    assert verify_chunk_access_list_message(cal_message)

    # Wait for beacon block to get execution payload header
    block = wait_for_beacon_block(store, root)

    # Forward CAL to execution layer for caching
    execution_engine.new_chunk_access_list(
        block.body.execution_payload_header.block_hash,
        chunk_index,
        cal_message.chunk_access_list
    )

    # Record CAL receipt and notify waiting chunk validations
    store.chunk_access_lists[root].add(chunk_index)
    notify_cal_available(root, chunk_index)
```

##### Phase 2: Chunk Validation

Chunks are validated as they arrive, provided all prerequisite CALs (indices `0` through `N` for chunk `N`) are available.

```python
def on_chunk_received(store: Store, chunk_message: ExecutionChunkMessage) -&gt; None:
    # Derive beacon block root from signed header
    root = hash_tree_root(chunk_message.signed_block_header.message)
    chunk = chunk_message.chunk
    chunk_index = chunk.chunk_header.index

    # Validate chunk message (proposer signature, inclusion proof, index bounds, gas bounds, tx root)
    assert verify_chunk_message(chunk_message)

    # Store chunk header for later finalization
    store.chunk_headers[root][chunk_index] = chunk.chunk_header

    # Wait for all prerequisite CALs [0, chunk_index]
    for i in range(chunk_index + 1):
        wait_for_cal(root, i)

    # Wait for beacon block to get execution payload header
    block = wait_for_beacon_block(store, root)

    # Execute chunk via EL (EL has cached all required CALs)
    execution_status = execution_engine.execute_chunk(
        block.body.execution_payload_header.block_hash,
        chunk
    )
    store.chunk_execution_statuses[root][chunk_index] = execution_status

    # Attempt block finalization if all chunks validated
    maybe_finalize_block(store, root)
```

##### Phase 3: Block Finalization

Once all chunks have been validated, the block is finalized by verifying chunk chaining and aggregate consistency.

```python
def maybe_finalize_block(store: Store, root: Root) -&gt; None:
    if root in store.block_valid:
        return

    block = store.blocks[root]
    payload_header = block.body.execution_payload_header

    chunk_headers = store.chunk_headers.get(root, {})
    chunk_statuses = store.chunk_execution_statuses.get(root, {})

    # Verify sequential chunk coverage and validity
    for i in range(payload_header.chunk_count):
        if i not in chunk_statuses:
            return  # Gap in sequence
        if not chunk_statuses[i].valid:
            store.block_valid[root] = False
            return

    # EL verifies chunk header chaining and final state root
    finalize_result = execution_engine.finalize_block(payload_header.block_hash)
    store.block_valid[root] = finalize_result.valid
```

#### Attestation Rules

Validators MUST NOT attest to a block until:

1. All chunks have been received and individually validated (Phase 2 complete)
2. Block finalization has succeeded (Phase 3 complete)

**ePBS Integration ([EIP-7732](/EIPs/EIPS/eip-7732))**: PTC (Payload Timeliness Committee) members attest to chunk and CAL data availability. PTC attestations are independent of execution validity—they confirm only that all messages were received within the timeliness window.

### Execution Layer Changes

#### Chunk Execution

The execution layer validates chunks independently. For chunk `N`, the EL applies CALs `0..N-1` to the parent block state to reconstruct the chunk&apos;s pre-state, then executes the chunk transactions. It uses CAL `N` to execute transactions in parallel (the same as in [EIP-7928](/EIPs/EIPS/eip-7928)).

```python
def el_execute_chunk(
    payload_header: ExecutionPayloadHeader,
    chunk: ExecutionChunk,
    cached_cals: Dict[ChunkIndex, ChunkAccessList]
) -&gt; PayloadStatusV1:
    &quot;&quot;&quot;Execute chunk using cached CALs to reconstruct pre-state.&quot;&quot;&quot;
    chunk_index = chunk.chunk_header.index

    # Verify all prerequisite CALs are cached
    for i in range(chunk_index):
        if i not in cached_cals:
            return PayloadStatusV1(
                status=&quot;INSUFFICIENT_INFORMATION&quot;,
                error=f&quot;Missing CAL {i}, have {list(cached_cals.keys())}&quot;
            )

    # Verify chunk&apos;s own CAL is cached
    if chunk_index not in cached_cals:
        return PayloadStatusV1(
            status=&quot;INSUFFICIENT_INFORMATION&quot;,
            error=f&quot;Missing CAL {chunk_index}&quot;
        )
    cal = cached_cals[chunk_index]

    # Get parent block state
    parent_state = get_state(payload_header.parent_hash)
    if parent_state is None:
        return PayloadStatusV1(
            status=&quot;SYNCING&quot;
        )

    # Apply CALs 0..N-1 to reconstruct chunk pre-state
    pre_state = parent_state
    for i in range(chunk_index):
        pre_state = apply_state_diffs(pre_state, cached_cals[i])

    # Verify CAL hash matches chunk header commitment (EIP-7928 format)
    cal_hash = keccak256(cal)  # CAL is RLP-encoded
    if cal_hash != chunk.chunk_header.chunk_access_list_hash:
        return PayloadStatusV1(
            status=&quot;INVALID&quot;,
            error=&quot;CAL hash mismatch&quot;
        )

    # Execute chunk transactions against pre-state
    result = execute_transactions(
        payload_header,
        pre_state,
        chunk.transactions,
        cal
    )

    if result.error:
        return PayloadStatusV1(
            status=&quot;INVALID&quot;,
            error=result.error
        )

    return PayloadStatusV1(
        status=&quot;VALID&quot;
    )
```

### Engine API

Four new Engine API methods support chunked validation:

#### `engine_newBlockHeaderV1`

Replaces `engine_newPayloadV5`. Informes EL that new block is available and passes block data, except CALs and chunks. Must be called first, as other calls depend on this data.

**Parameters:**

- `payload_header`: `ExecutionPayloadHeader`
- `beaconRoot`: `Hash32`
- `blobHashes`: `List[Hash32]`
- `executionRequests`: `List[Bytes]`

**Returns:** PayloadStatusV1

#### `engine_newChunkAccessListV1`

Caches a CAL for subsequent chunk execution. Requires block data to have been sent via `engine_newBlockHeaderV1`.

**Parameters:**

- `blockHash`: `Hash32` - The block hash
- `chunkIndex`: `ChunkIndex` - Index of the chunk this CAL corresponds to
- `chunkAccessList`: `ChunkAccessList` - RLP-encoded chunk access list

**Returns:** `PayloadStatusV1`

#### `engine_executeChunkV1`

Executes and validates a chunk. Requires block data to have been sent via `engine_newBlockHeaderV1`, and all prerequisite CALs (indices `0` through `N`) to have been sent via `engine_newChunkAccessListV1`.

**Parameters:**

- `blockHash`: `Hash32` - The block hash
- `chunk`: `ExecutionChunk` - The chunk to execute

**Returns:** `PayloadStatusV1`

#### `engine_finalizeBlockV1`

Finalizes block validation after all chunks have been executed. Verifies:

- Chunk headers chain correctly: chunk N&apos;s `pre_chunk_*` fields equal chunk N-1&apos;s cumulative values
- Final state root matches `payload_header.state_root`
- All block header fields are valid

**Parameters:**

- `blockHash`: `Hash32` - Hash of the execution payload

**Returns:** `PayloadStatusV1`

#### Response Types

All new Engine API methods return `PayloadStatusV1` type, but `status` field has different meaning and values depending on the method. Following table defines all possible values and when they can be used.

| Status | Semantics | `newBlockHeader` | `newChunkAccessList` | `executeChunk` | `finalizeBlock` |
|-|-|-|-|-|-|
| `ACCEPTED` | BlockHeader/CAL accepted successfully | ✅ | ✅ | | |
| `VALID` | Chunk/block executed correctly | | | ✅ | ✅ |
| `INSUFFICIENT_INFORMATION` | Missing prerequisite CALs | | | ✅ | |
| `INVALID` | Execution or validation failed | ✅ | ✅ | ✅ | ✅ |
| `SYNCING` | Parent state not available (node syncing) | ✅ | ✅ | ✅ | ✅ |

The `error` field is present if status is `INSUFFICIENT_INFORMATION` or `INVALID`.

## Rationale

### Incremental CALs

Chunk N applies CALs 0..N-1 to the parent state to reconstruct its pre-state. This incremental approach provides:

1. **Parallel Execution**: Multiple chunks can execute concurrently once their prerequisite CALs arrive. Alternative designs where each CAL contains cumulative state diffs would cause CAL sizes to grow linearly with chunk count, creating worst-case bandwidth issues.
2. **Early Rejection**: Invalid chunks cause immediate block rejection without processing subsequent chunks.
3. **Bounded Resources**: Each chunk validation is independently bounded by `CHUNK_GAS_LIMIT`.

### CL-Driven Architecture

The consensus layer orchestrates chunk execution because:

1. **Consistency**: Existing CL-EL interaction follows CL-driven patterns (e.g., `engine_newPayload`).
2. **Global View**: The CL tracks which CALs have arrived from gossip and can optimally schedule chunk execution based on availability.
3. **Dependency Enforcement**: The CL ensures chunks execute only when prerequisites are satisfied.
4. **Timeliness Tracking**: The CL determines whether messages arrived within attestation deadlines.

### Separate CAL Propagation

Decoupling CALs from chunks provides:

1. **Faster Propagation**: CALs (kilobytes of state diffs) propagate faster than chunks (megabytes of transactions), enabling earlier execution starts.
2. **Parallelization**: Chunks can execute independently by applying prior CALs to reconstruct pre-states.
3. **State reads**: CALs allow us to start reading required state from db before transactions arrive.
4. **StateRoot calculation**: EL can start calculating state root as soon as all CALs are received.
5. **Extensibility**: CALs can be extended with proving metadata without modifying chunk structure.

### Semantic Chunking

Semantic chunking (transaction-aligned boundaries with gas limits) differs from byte-level fragmentation:

1. **Streaming Validation**: Each chunk is a complete execution unit validatable upon receipt.
2. **Resource Bounds**: Gas limits bound per-chunk memory, CPU, and proving costs.
3. **Transaction Integrity**: No transaction splitting simplifies execution semantics.

### Parameter Selection

| Parameter | Value | Rationale |
|-----------|-------|-----------|
| `CHUNK_GAS_LIMIT` | `2^24` (~16.7M) | Balances parallelization granularity with per-chunk overhead. Large enough for complex transactions, small enough for bounded ZK proving circuits. |
| `MAX_CHUNKS_PER_BLOCK` | `256` | Supports ~4 Ggas blocks (256 × 16M). Conservative upper bound accommodating future gas limit increases. |
| `MAX_TRANSACTIONS_PER_CHUNK` | `2^16` (65,536) | Accommodates chunks filled with minimal-gas transactions (ETH transfer - 21,000 gas) with margin for future gas cost reductions. |

## Backwards Compatibility

This EIP introduces breaking changes requiring a coordinated hard fork:

| Component | Change |
|-----------|--------|
| **Block Propagation** | Execution payloads propagate as chunk and CAL messages instead of monolithic payloads |
| **Network Protocol** | New gossip topics for `ExecutionChunkMessage` and `ChunkAccessListMessage` |
| **Engine API** | Four new methods: `engine_newBlockHeaderV1`, `engine_newChunkAccessListV1`, `engine_executeChunkV1`, `engine_finalizeBlockV1` |
| **Validation** | Three-phase validation (CAL reception, chunk validation, block finalization) |

Post-fork, nodes must implement chunked validation to participate in consensus. Historical blocks remain unaffected.

## Security Considerations

### Data Availability Attacks

Chunk separation introduces new attack surfaces:

| Attack | Description | Impact | Mitigation |
|--------|-------------|--------|------------|
| **Chunk Withholding** | Builder publishes some chunks but withholds others | Block unvalidatable; attestation deadline missed | Attestation rules require all chunks; PTC votes on availability |
| **CAL Withholding** | Builder publishes chunks but withholds CALs | Streaming execution blocked; falls back to sequential | CALs reconstructible by sequential chunk execution |
| **Reverse Propagation** | Builder sends chunks/CALs in reverse order (N→0) | No parallel execution until chunk 0 and CAL 0 arrive | Rational builders propagate in order for faster attestations |

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 01 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8101</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8101</guid>
      </item>
    
      <item>
        <title>Universal Enshrined Encrypted Mempool</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8105-universal-enshrined-encrypted-mempool/27201</comments>
        
        <description>## Abstract

This EIP proposes to enshrine an encrypted mempool into the protocol. It enables users to encrypt their transactions until they have been included in a block, protecting them from front running and sandwiching attacks as well as increasing censorship resistance guarantees. The design is encryption technology agnostic by supporting arbitrary decryption key providers, which can for instance be based on threshold encryption, MPC committees, TEEs, delay encryption, or FHE schemes. Traditional plaintext transactions are still supported and progression of the chain is guaranteed even if decryption key providers fail.

## Motivation

The goal of this EIP is to prevent users from malicious transaction reordering attacks as well as increase real time (&quot;weak&quot;) censorship resistance of the protocol. It also aims to reduce regulatory risks of block builders and other protocol participants by temporarily blinding them. The goal is not to improve user privacy (e.g., transaction confidentiality) as transactions are publicly revealed eventually.

This proposal builds on prior work such as the _Shutterized Beacon Chain_ and a live, out-of-protocol implementation of the encrypted mempool already deployed on Gnosis Chain. It addresses a long-standing issue with front running and has the potential to mitigate harmful second-order effects of MEV, such as builder centralization. The design also fits naturally with enshrined proposer-builder separation (ePBS), making it a logical extension of Ethereum’s roadmap.

## Specification

### Key Provider Registry

In the execution layer, a system contract called the key provider registry is deployed. It allows any account to register a key provider and assigns them a unique ID. Registration requires specifying a contract with a decryption and a key validation function, each of which accept a key ID and a key message as byte strings. Additionally, key providers may designate other providers as directly trusted, thereby forming a directed trust graph. We define a key provider A to trust another key provider B if and only if a directed path from A to B exists in this graph. The beacon chain replicates the key provider registry in its state, analogously to the mechanism that handles beacon chain deposits.

The source code of the key provider registry contract is TBD.

### Transaction Types

The proposal adds two new [EIP-2718](/EIPs/EIPS/eip-2718) transaction types. Encrypted transactions have the following form:

`0x05 || rlp([chain_id, envelope_nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_amount, key_provider_id, key_id, encrypted_payload, envelope_signature_y_parity, envelope_signature_r, envelope_signature_s])`

Decrypted transactions have the following form:

`0x06 || rlp([envelope_signer, nonce, destination, amount, data, access_list, signature_y_parity, signature_r, signature_s])`

### Key Provider Responsibilities

In each slot, when a key provider observes the execution payload published by the builder, they collect the key IDs referenced in the envelopes of all encrypted transactions addressed with their key provider ID. For each of those, they must publish either the corresponding decryption key or a key withhold notice. The corresponding message references the beacon block hash to prevent replays in a future slot. They may do so either immediately upon observing the execution payload or delay publication to a later point in the slot.

### Additional Payload Timeliness Committee Responsibilities

Members of the Payload Timeliness Committee (PTC) defined in [EIP-7732](/EIPs/EIPS/eip-7732) must listen for the decryption keys referenced by all encrypted transactions in a block, as identified by the key provider ID and key ID fields. They must validate these keys using the validation function specified in the registry contract, using a hardcoded small gas limit per key. Finally, they must attest to the presence or absence of a valid key for each encrypted transaction in the payload attestation message, which is extended for this purpose with a dedicated bitfield.

### Block Structure

In a valid block, transactions must be ordered as follows:

- Decrypted transactions at the start
- Encrypted transactions at the end
- Any other transaction in the middle

Additionally, if an encrypted transaction A is preceded by another encrypted transaction B, then A and B must either specify the same key provider or B&apos;s key provider must be trusted by A&apos;s key provider.

Each decrypted transaction must correspond to an encrypted transaction in the previous block. The correspondence must be order-preserving. A decrypted transaction must be the result of applying the decryption function given by `key_provider_id` to `encrypted_payload` of the corresponding encrypted transaction. The key to be used is specified by the encrypted transaction&apos;s `key_id` and must be attested to by the PTC in the slot in which the encrypted transaction was included. A decrypted transaction must not be included if and only if any of the following conditions is met:

- the key is attested as missing
- decryption fails
- decryption does not yield a structurally valid decrypted transaction
- the decrypted transaction&apos;s `envelope_signer` does not match the signer of the corresponding encrypted transaction
- including the decrypted transaction would result in an invalid block (e.g., because of a nonce mismatch)

### Transaction Execution

Encrypted transactions are executed by incrementing the nonce of the envelope signer account and paying for `gas_amount` analogously to [EIP-1559](/EIPs/EIPS/eip-1559). The transaction consumes `gas_amount` units of gas.

Decrypted transactions are executed as a regular transaction under the execution context of the inclusion block (e.g., for `block.slot` and `block.coinbase`). The gas limit of the transaction is given by the corresponding encrypted transaction&apos;s `gas_amount` minus the cost of the encrypted transaction as well as decryption. However, the consumed gas does not count towards the block gas limit and no fee is paid.

## Rationale

### Key Provider Registration

Registration is encryption technology agnostic to ensure neutrality of the protocol, to minimize barriers to entry for new key providers, and to empower users to choose the optimal scheme for their purposes. An execution layer contract was chosen as a canonical way of specifying arbitrary execution logic. Registration purely on the CL is a reasonable alternative.

Many encryption schemes are inefficient to express in the EVM and therefore would require dedicated precompiles. Adding those is, however, out of scope of this EIP.

### Key Provider Trust Graph

A user who sends an encrypted transaction must not only trust their own key provider, but also any key provider used for earlier transactions in a block (see Security Considerations). While the protocol should respect the users’ trust preferences, if each user only trusts their own key provider, builders would only be able to include transactions encrypted with keys from a single key provider in each block. This is undesirable because it makes it difficult for key providers with a small market share to compete, risking to create a key provider monopoly.

On the other hand, requiring users to explicitly state which third-party providers they trust would add a transaction size overhead and make block building more difficult due to the potentially large number of competing user preferences that need to be fulfilled. As a compromise, this proposal requires key providers to make this choice. Users implicitly agree by using the key provider’s keys.

With this solution, even if a quasi-monopoly consisting of a single dominating key provider emerges and this key provider does not specify any other key providers as trusted, builders can still include transactions that use other small key providers without opportunity costs, as long as the small key providers trust the major one (and potentially each other).

### Transaction Execution

The protocol as well as builders must be protected from including encrypted transactions that end up unable to pay for gas. To ensure this is the case irrespective of the content of any encrypted payload in a block, the fee payment is part of the plaintext envelope and all envelopes are executed before any encrypted payload. Gas refunds are not paid out to guarantee the fee amount the builder and the protocol will receive at block building time.

All gas is consumed in the block in which the encrypted transaction is included and none in the block in which the decrypted transaction is executed. This is for incentive compatibility: The builder of one block should not be able to sell block space of the next.

For simplicity, the encrypted payload contains a signature. A less private but more efficient alternative is to consider the envelope signer as sender.

### Decryption Key Withholding

The protocol explicitly allows decryption key providers to withhold decryption keys under conditions of their choosing. This enables them to safely implement rules to restrict which users are allowed to use which keys, e.g., based on prior payments and to prevent key ID front running attacks (see Security Considerations). On the other hand, keys that have been withheld unjustifiably may be used in custom slashing mechanisms and reliability metrics (note that the protocol records which keys are present and which ones have been present and which ones have not).

### Lack of In-Protocol Key Provider Incentives

This proposal does not enshrine a fee mechanism for key providers, nor punishments for misbehavior. This allows for a variety of incentive models to be implemented off-chain. For instance, key providers could make agreements with builders, be paid on a per-transaction basis by users, or operate as public goods. They may also subject themselves to slashing conditions for unwarranted withholding of keys to make their service more appealing to users.

### Execution Payload Encryption

A future EIP may propose to let builders use the keys from the key providers to encrypt the execution payload. This enables them to publish the execution payload immediately after constructing it, compared to publishing it only at the 50% slot mark. This would increase p2p efficiency and protect builders from missed slots due to crashes. Additionally, if the builder attaches a zero knowledge proof about which keys have been used in a block, the key revelation time window could start earlier and therefore be longer. This feature is not included in this EIP to minimize complexity.

## Backwards Compatibility

The proposal makes backwards incompatible changes to the protocol to the execution and consensus layer.

## Security Considerations

### Trusted Key Providers

Users necessarily need to trust the key providers they use to encrypt their transactions to

- not release the decryption keys early which would allow front running and sandwiching attacks
- not release the decryption keys late which would prevent execution of the transaction while the envelope fee still has to be paid.

Key providers may earn this trust by cryptographic mechanisms (e.g., threshold encryption, hardware encryption), economic mechanisms (e.g., slashing for misbehavior), governance mechanisms (e.g., voting to select socially reputable entities), or a combination of these.

To a lesser degree, users need to trust all key providers used for encrypted transactions preceding theirs in a block. This is because key providers have the option to publish or to withhold decryption keys which they can take after observing decryption keys for following transactions. This option gives them one bit of influence over the pre-state of later transactions. Maliciously chosen “decryption” schemes may make this attack much stronger by allowing directly modifying specific parts of the decryption results using crafted decryption keys or setting it outright. This effectively enables front running.

Users do not have to trust any key provider used for transactions included after theirs because the pre-state of the user’s transaction payload is not affected by later transactions’ payloads (only their envelopes, but those are chosen before any decryption keys are published). Similarly, users of plaintext transactions do not have to trust any key provider (but they continue to have to trust builders).

### Reorgs

Decryption keys are published before the corresponding encrypted transactions are finalized. Thus, in the event of a chain reorg, a transaction may become public even though it is not necessarily included in the chain. However, since the decryption key message includes the block hash, it can be invalidated by the key validation function. This does not prevent inclusion of the envelope transaction, but does prevent execution and, hence, front running of the payload.

### Key ID Front Running

When a user encrypts a transaction with a particular key ID, another user could observe this transaction in flight and create another encrypted transaction that specifies the same key provider and key ID. If the second transaction is included in an earlier block than the original one, a naive key provider would reveal the key and thus the original transaction, even though it is not included yet.

Key providers can protect their users from this attack. One possible strategy to do so is “namespacing” key IDs: Providers only release keys for key IDs that are prefixed with the envelope signer’s address and withhold all others. As we can reasonably assume that the attacker does not have access to the envelope signer account, an attacker would be unable to produce a transaction with correctly namespaced key ID.

### Key Provider-Child Builder Collusion

To build a new block, builders need to know the post-state of the previous block and thus all decryption keys used in a block and which of them are withheld. This information is publicly known once the PTC attests. However, malicious key providers could collude with a block builder and give them an earlier heads up. This would give the builders a competitive advantage as they can start the block building process earlier.

The impact of the attack is deemed low because the time between publishing of the payload attestations and the end of the slot is still long enough for block building. Furthermore, the start of the block building period is much less critical than the end (since only then the full set of includable transactions is known), which is not affected by the attack. Also, delaying the release of decryption keys bears the risk of them not being attested to by the PTC, negating the competitive advantage of the attacker. And finally, if the number of encrypted transactions that use the malicious key provider is small, their impact on the tree state is likely small as well. This means optimistic block building strategies that don’t rely on full knowledge of the state tree could be viable, countering the attack.

### Envelope and Payload Stripping Attacks

If a key for a published encrypted transaction is revealed but the decrypted transaction is not included (e.g., if the key is revealed late), an attacker might try to decrypt the transaction, put it in a new envelope, and frontrun it in a future block. The `envelope_signer` reference on the decrypted transaction prevents this envelope stripping attack for everyone but the chosen envelope signer. As the envelope signer will likely have access to the plaintext transaction in practice, they are trusted to not frontrun anyway. This assumption could be tightened by also including the chain id, key provider, and key id. A full reference to the envelope is impossible due to the cyclic dependency that would ensue. Including the envelope nonce would in principle be desirable, but complicate interaction between the envelope and payload signer.

The complementary payload stripping attack, i.e. intercepting an encrypted transaction and replacing the payload, is not possible because the encrypted transaction signature spans the payload.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 17 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8105</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8105</guid>
      </item>
    
      <item>
        <title>RWA Event-based Compliance Framework</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8106-rwa-event-based-compliance-framework/27219</comments>
        
        <description>## Abstract

This standard defines an event-based compliance framework for Real World Asset (RWA) tokens on [ERC-20](/EIPs/EIPS/eip-20), providing:

1. A standardized entity classification system distinguishing between Compliance Entities (CE) and Decentralized Entities (DE)
2. Event-driven compliance observation enabling auditability through standardized events and actual value flows, without enforcing hard transaction reverts

This standard is intentionally minimal and does not prescribe business-specific RWA workflows, off-chain settlement mechanisms, minting policies, or specific transfer patterns.

## Motivation

Real World Asset tokenization requires compliance observability that existing [ERC-20](/EIPs/EIPS/eip-20) tokens do not provide:

### Missing Capabilities

1. **Entity Classification**: No standardized way to distinguish regulated corporate entities from decentralized participants
2. **Compliance Observability**: No uniform event semantics for tracking compliance-relevant transfers
3. **Flexible Enforcement**: Existing standards use hard reverts, making them incompatible with diverse regulatory frameworks

### Why Event-Based?

This standard adopts an event-driven approach rather than enforcement through reverts:

- **Regulatory Flexibility**: Different jurisdictions can interpret the same events differently
- **Adaptability**: Compliance rules can evolve without contract upgrades
- **Lower Costs**: Events are cheaper than state-based enforcement

## Specification

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

### Definitions

- **Compliance Entity (CE)**: An address representing a regulated legal entity (e.g., corporate treasury, custody account)
- **Decentralized Entity (DE)**: An address representing a decentralized participant (e.g., end users, routers, settlement contracts)
- **BizID**: A business correlation identifier (hash) linking related transfers to a single workflow
- **Soft Policy**: Compliance policy expressed through event labeling, not transaction reversion

### Entity Registry

Compliant implementations MUST provide an entity classification registry that assigns each address to one of three categories.

```solidity
interface IERC8106EntityRegistry {
    enum EntityType { DECENTRALIZED_ENTITY, COMPLIANCE_ENTITY }

    event EntityTypeUpdated(
        address indexed entity,
        EntityType entityType,
        bytes32 indexed reasonHash,
        address indexed operator
    );

    /// @notice Returns the entity type of an address
    /// @dev MUST return DECENTRALIZED_ENTITY for addresses not explicitly registered as COMPLIANCE_ENTITY
    function entityTypeOf(address entity) external view returns (EntityType);
}
```

#### Registry Requirements

Implementations MUST satisfy the following requirements:

1. **Default Classification**: The `entityTypeOf` function MUST return `DECENTRALIZED_ENTITY` for any address not explicitly registered as `COMPLIANCE_ENTITY`
2. **Explicit Registration**: Only addresses explicitly registered SHOULD return `COMPLIANCE_ENTITY`
3. **Update Events**: Entity type changes MUST emit `EntityTypeUpdated` events
4. **Reason Tracking**: The `reasonHash` parameter MUST reference off-chain documentation (e.g., KYC records, legal entity registration)
5. **Operator Accountability**: The `operator` parameter MUST identify the address that authorized the update

#### Implementation Note

The registry MAY be:
- Embedded within the token contract itself
- Implemented as a separate contract referenced by the token
- Shared across multiple tokens within an ecosystem

### Compliance Events

Compliant implementations MUST emit standardized events that capture compliance-relevant transfer information, including entity classifications, compliance flags, and business correlation identifiers.

```solidity
interface IERC8106ComplianceEvents is IERC8106EntityRegistry {
    enum ComplianceFlag {
        OK,
        DIRECT_DE_TO_CE,           // DE -&gt; CE observed
        DIRECT_CE_TO_DE,           // CE -&gt; DE observed
        POLICY_CUSTOM              // project-defined policy
    }

    event ComplianceObserved(
        bytes32 indexed bizId,
        address indexed token,     // the ERC-20 token contract address
        address indexed from,
        address to,
        uint256 amount,
        EntityType fromType,
        EntityType toType,
        ComplianceFlag flag,
        bytes32 policyTag          // project-defined categorization tag
    );
}
```

#### Event Requirements

Implementations MUST satisfy the following requirements:

1. **Complete Information**: Each `ComplianceObserved` event MUST include all specified parameters
2. **Accurate Classification**: The `fromType` and `toType` MUST reflect the actual entity types at the time of the transfer
3. **Consistent BizID**: All legs of a multi-leg transfer MUST use the same `bizId` value
4. **Token Identification**: The `token` parameter MUST be the address of the [ERC-20](/EIPs/EIPS/eip-20) token contract

#### Recommended Flagging Policy (Non-normative)

Implementations SHOULD apply the following flagging heuristics:

- `DIRECT_DE_TO_CE`: When `fromType == DECENTRALIZED_ENTITY` and `toType == COMPLIANCE_ENTITY`
- `DIRECT_CE_TO_DE`: When `fromType == COMPLIANCE_ENTITY` and `toType == DECENTRALIZED_ENTITY`
- `OK`: When transfer does not cross compliance boundaries (DE↔DE or CE↔CE)
- `POLICY_CUSTOM`: For project-specific compliance scenarios

#### Event-Based Compliance

Implementations SHOULD NOT revert transactions solely based on compliance flags. This event-based approach enables:

- Off-chain compliance review and decision-making
- Flexible interpretation across different regulatory jurisdictions
- Time-delayed enforcement where appropriate (e.g., 24-hour review periods)

Compliance actions (transaction reversals, account freezes, regulatory reporting) SHOULD be handled through separate mechanisms such as:

- Off-chain monitoring systems
- On-chain governance modules
- Dedicated compliance management contracts

## Rationale

### Event-Driven Model

Events rather than reverts because:

- Different jurisdictions can interpret events differently
- Cheaper than state-based enforcement (~2000 gas per event vs state writes)
- Enables time-delayed enforcement where appropriate

### Soft Policy Flags

Compliance flags are informational, not enforced:

- Projects decide whether to revert based on flags
- Off-chain systems can alert, review, or freeze post-transaction
- Supports evolving regulations without contract changes

### Auditability Design

Auditors reconstruct transaction flows using:

1. **Value Flows**: Every `ComplianceObserved` event corresponds to a real [ERC-20](/EIPs/EIPS/eip-20) balance change
2. **Standardized Events**: Uniform event structure for machine-readable compliance data
3. **BizID Correlation**: Link multiple transfers to a single business transaction

For a given `bizId`, auditors can query all `ComplianceObserved` events, build directed graphs from `from`/`to`/`amount` fields, check for direct CE/DE transfers using the `flag` field, and cross-reference `reasonHash` with off-chain KYC/AML systems.

## Reference Implementation

### Implementation Patterns

**Embedded Registry**: Store entity types in the token contract itself

```solidity
contract RWAToken is ERC20, IERC8106ComplianceEvents {
    mapping(address =&gt; bool) private _isComplianceEntity;
    
    function entityTypeOf(address entity) public view returns (EntityType) {
        return _isComplianceEntity[entity] 
            ? EntityType.COMPLIANCE_ENTITY 
            : EntityType.DECENTRALIZED_ENTITY;
    }
    // ...
}
```

**Separate Registry**: Share registry across multiple tokens

```solidity
contract EntityRegistry is IERC8106EntityRegistry {
    mapping(address =&gt; bool) private _isComplianceEntity;
    
    function entityTypeOf(address entity) external view returns (EntityType) {
        return _isComplianceEntity[entity]
            ? EntityType.COMPLIANCE_ENTITY
            : EntityType.DECENTRALIZED_ENTITY;
    }
    
    function registerComplianceEntity(address entity, bytes32 reasonHash) external onlyAdmin {
        _isComplianceEntity[entity] = true;
        emit EntityTypeUpdated(entity, EntityType.COMPLIANCE_ENTITY, reasonHash, msg.sender);
    }
    // ...
}
```

**Policy Tag Conventions**: Use consistent hashes for interoperability

```solidity
bytes32 constant TAG_PAYMENT = keccak256(&quot;PAYMENT&quot;);
bytes32 constant TAG_TREASURY = keccak256(&quot;TREASURY&quot;);
bytes32 constant TAG_REFUND = keccak256(&quot;REFUND&quot;);
```

### Example Use Cases

**Compliance Monitoring:** A regulated stablecoin tracks all CE↔DE flows for monthly regulatory reports without blocking transactions.

**Atomic Multi-Leg Transfers:** While not part of this standard, projects can build on these primitives to implement atomic multi-hop transfers:

```solidity
// User pays → Treasury → Operational account (single transaction)
function purchaseRWA(bytes32 orderId, uint256 amount) external {
    // Leg 1: DE → CE
    token.transferFrom(msg.sender, treasury, amount);
    emit ComplianceObserved(orderId, token, msg.sender, treasury, amount, 
                           DE, CE, DIRECT_DE_TO_CE, TAG_PAYMENT);
    
    // Leg 2: CE → CE
    token.transferFrom(treasury, operational, amount);
    emit ComplianceObserved(orderId, token, treasury, operational, amount,
                           CE, CE, OK, TAG_TREASURY);
}
```

This pattern enables single user-facing transactions, unified `bizId` for audit correlation, and per-leg compliance events.

**Time-Delayed Enforcement:** Detect suspicious patterns in events, then freeze accounts off-chain or via governance after review.

## Security Considerations

**Event Integrity:** Implementations MUST emit `ComplianceObserved` events only after actual [ERC-20](/EIPs/EIPS/eip-20) balance changes. Emitting events without value movement compromises auditability.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).</description>
        <pubDate>Tue, 16 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8106</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8106</guid>
      </item>
    
      <item>
        <title>ENS Trust Registry for Agent Coordination</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-ens-trust-registry-for-agent-coordination/27200</comments>
        
        <description>## Abstract

This ERC defines a **Trust Registry** that enables agents to establish and query transitive trust relationships using ENS names as identifiers. Trust is expressed at four levels (Unknown, None, Marginal, Full) and propagates through signature chains following the GNU Privacy Guard (GnuPG) web of trust model.

The registry serves as the **trust and delegation module** anticipated by [ERC-8001](/EIPs/EIPS/eip-8001), enabling coordinators to gate participation based on trust graph proximity. An agent is considered valid from a coordinator&apos;s perspective if sufficient trust paths exist between them.

This standard specifies trust attestation structures, the path verification algorithm, ENS integration semantics, and [ERC-8001](/EIPs/EIPS/eip-8001) coordination hooks.

## Motivation

[ERC-8001](/EIPs/EIPS/eip-8001) defines minimal primitives for multi-party agent coordination but explicitly defers trust to modules:

&gt; &quot;Privacy, thresholds, bonding, and cross-chain are left to modules.&quot;

And in Security Considerations:

&gt; &quot;Equivocation: A participant can sign conflicting intents. Mitigate with module-level slashing or reputation.&quot;

This ERC provides that trust and delegation module. Before coordinating, agents need answers to:

1. **&quot;Should I include this agent in my coordination?&quot;** — Participant selection
2. **&quot;Can I trust this agent&apos;s judgment about other agents?&quot;** — Transitive trust
3. **&quot;How do I update trust based on coordination outcomes?&quot;** — Trust maintenance

### Why Web of Trust?

The web of trust model, proven over 25+ years in GnuPG, solves the bootstrap problem: how do you establish trust with unknown agents without a centralised registrar?

| GnuPG Concept | This Standard |
|---------------|---------------|
| Public key | ENS name |
| Key signing | Trust attestation |
| Owner trust levels | `TrustLevel` enum |
| Key validity | Agent validity for coordination |
| Certification path | Trust chain through agents |

### Why ENS?

ENS provides a battle-tested, finalized identity layer:

- **Stable identifiers** that survive key rotation
- **Ownership semantics** via `owner()` and `isApprovedForAll()`
- **Human readable** names (`alice.agents.eth` not `0x742d...`)
- **Subdomain delegation** for protocol-issued agent identities

Using ENS avoids dependency on draft identity standards while remaining compatible with future standards through adapter patterns.

**Deployment note**: This standard requires access to an ENS registry. On Ethereum mainnet, use the canonical ENS deployment. On other networks, use network-specific ENS deployments or bridges. CCIP-Read is a client-side mechanism and cannot be used for on-chain validation.

### Identity Continuity

ENS names are the identity. When an ENS name is transferred, the new owner inherits existing trust relationships where that name is the trustee. The new owner can manage trust where they are the trustor.

Implementations SHOULD use short expiries (RECOMMENDED: 90 days maximum) for high-stakes scopes to limit exposure from name transfers. Agents SHOULD monitor `Transfer` events on ENS names they trust and re-evaluate trust accordingly.

## Specification

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

### Overview

This ERC specifies:

* Trust levels and their semantics
* ENS-indexed trust attestation structures with scope as key
* [EIP-712](/EIPs/EIPS/eip-712) typed data for signing attestations
* [EIP-1271](/EIPs/EIPS/eip-1271) support for contract controllers
* The `ITrustRegistry` interface
* Path verification algorithm
* [ERC-8001](/EIPs/EIPS/eip-8001) integration hooks

### Trust Levels

Implementations MUST use the canonical enum:

```solidity
enum TrustLevel {
   Unknown,   // 0: No trust relationship established
   None,      // 1: Explicitly distrusted
   Marginal,  // 2: Partial trust — multiple required for validation
   Full       // 3: Complete trust — single attestation sufficient
}
```

**Semantic definitions:**

| Level | Meaning | Validation Contribution |
|-------|---------|------------------------|
| `Unknown` | Default state; no data about agent | Cannot contribute to validation |
| `None` | Agent known to behave improperly | Explicitly excluded; voids trust paths containing this agent |
| `Marginal` | Agent generally trustworthy | Contributes to validation when `minEdgeTrust &lt;= Marginal` |
| `Full` | Agent&apos;s judgment equals own verification | Always contributes to validation |

**Level transitions:**

* Any level MAY transition to any other level via a valid attestation with a higher nonce
* Transitioning from `None` to `Marginal` or `Full` requires a new attestation (revocation is not permanent)

### ENS Integration

The Trust Registry uses ENS namehashes as agent identifiers.

```solidity
// ENS namehash computation (per ERC-137)
bytes32 node = keccak256(abi.encodePacked(
   keccak256(abi.encodePacked(bytes32(0), keccak256(&quot;eth&quot;))),
   keccak256(&quot;alice&quot;)
));
// node = namehash(&quot;alice.eth&quot;)
```

### Signature Authority

Trust attestations MUST be signed by an address with signing authority for the ENS name.

**Signing authority** is limited to:

* The ENS name owner (`ens.owner(node)`), OR
* For contract owners: any signer the contract validates via [EIP-1271](/EIPs/EIPS/eip-1271)

**Transaction submission** (calling `setTrust`, `revokeTrust`, etc.) MAY be performed by:

* Any address holding a valid signature
* An approved operator (`ens.isApprovedForAll(owner, operator)`) for `revokeTrust` only

This separation ensures:

* Attestations are cryptographically bound to the ENS owner/controller
* Transaction submission can be delegated (relayers, operators)
* Approvals cannot be used to forge signatures

```solidity
/// @dev Verify signature - signing authority is ENS owner only
   function verifySignature(
      bytes32 node,
      bytes32 digest,
      bytes calldata signature
   ) internal view returns (bool) {
      address owner = ens.owner(node);
      if (owner == address(0)) return false;

      // EOA owner
      if (owner.code.length == 0) {
         return ECDSA.recover(digest, signature) == owner;
      }

      // Contract owner - delegate to EIP-1271
      try IERC1271(owner).isValidSignature(digest, signature) returns (bytes4 magic) {
         return magic == IERC1271.isValidSignature.selector;
      } catch {
         return false;
      }
   }

/// @dev Check if caller can submit revokeTrust transaction
   function canSubmitRevocation(bytes32 node, address caller) internal view returns (bool) {
      address owner = ens.owner(node);
      return caller == owner || ens.isApprovedForAll(owner, caller);
   }
```

### EIP-712 Domain

Implementations MUST use the following [EIP-712](/EIPs/EIPS/eip-712) domain:

```solidity
EIP712Domain({
   name: &quot;TrustRegistry&quot;,
   version: &quot;1&quot;,
   chainId: block.chainid,
   verifyingContract: address(this)
})
```

Implementations SHOULD expose the domain via [EIP-5267](/EIPs/EIPS/eip-5267).

### Primary Types

```solidity
struct TrustAttestation {
   bytes32 trustorNode;       // ENS namehash of trustor
   bytes32 trusteeNode;       // ENS namehash of trustee
   TrustLevel level;          // Trust level assigned
   bytes32 scope;             // Scope restriction; bytes32(0) = universal
   uint64 expiry;             // Unix timestamp; 0 = no expiry
   uint64 nonce;              // Per-trustor monotonic nonce
}

   struct ValidationParams {
      uint8 maxPathLength;       // Maximum trust chain depth (1-10)
      TrustLevel minEdgeTrust;   // Minimum trust level required on each edge
      bytes32 scope;             // Required scope; bytes32(0) = any
      bool enforceExpiry;        // Check expiry on all chain elements
      bytes32[] requiredAnchors; // Path MUST traverse at least one anchor; empty = no requirement
   }

   struct TrustPath {
      bytes32[] nodes;           // [validator, ...intermediaries..., target]
   }
```

**Path length definition**: Path length is the number of edges (trust relationships) in the path. A direct trust relationship has path length 1. A path `[A, B, C]` has length 2.

#### Default Validation Parameters

When not specified, implementations SHOULD use:

```solidity
ValidationParams({
   maxPathLength: 5,
   minEdgeTrust: TrustLevel.Marginal,
   scope: bytes32(0),
   enforceExpiry: true,
   requiredAnchors: new bytes32[](0)
})
```

#### Validation Parameters Constraints

Implementations MUST reject `ValidationParams` where:

* `maxPathLength == 0` or `maxPathLength &gt; 10`
* `minEdgeTrust == TrustLevel.Unknown` or `minEdgeTrust == TrustLevel.None`
* `requiredAnchors.length &gt; 10`

### Typed Data Hashes

```solidity
bytes32 constant TRUST_ATTESTATION_TYPEHASH = keccak256(
   &quot;TrustAttestation(bytes32 trustorNode,bytes32 trusteeNode,uint8 level,bytes32 scope,uint64 expiry,uint64 nonce)&quot;
);

   function hashAttestation(TrustAttestation calldata att) internal pure returns (bytes32) {
      return keccak256(abi.encode(
         TRUST_ATTESTATION_TYPEHASH,
         att.trustorNode,
         att.trusteeNode,
         uint8(att.level),
         att.scope,
         att.expiry,
         att.nonce
      ));
   }
```

### Interface

Implementations MUST expose the following interface:

```solidity
interface ITrustRegistry {
   // ═══════════════════════════════════════════════════════════════════
   // Events
   // ═══════════════════════════════════════════════════════════════════

   /// @notice Emitted when trust is set or updated
   event TrustSet(
      bytes32 indexed trustorNode,
      bytes32 indexed trusteeNode,
      TrustLevel level,
      bytes32 indexed scope,
      uint64 expiry
   );

   /// @notice Emitted when trust is explicitly revoked
   event TrustRevoked(
      bytes32 indexed trustorNode,
      bytes32 indexed trusteeNode,
      bytes32 indexed scope,
      bytes32 reasonCode
   );

   /// @notice Emitted when an identity gate is configured
   event IdentityGateSet(
      bytes32 indexed coordinationType,
      bytes32 indexed gatekeeperNode,
      uint8 maxPathLength,
      TrustLevel minEdgeTrust
   );

   /// @notice Emitted when an identity gate is removed
   event IdentityGateRemoved(bytes32 indexed coordinationType);

   // ═══════════════════════════════════════════════════════════════════
   // Trust Management
   // ═══════════════════════════════════════════════════════════════════

   /// @notice Set trust level for another agent in a specific scope
   /// @dev Signature MUST be from ENS owner (EOA) or validate via EIP-1271 (contract)
   /// @param attestation The trust attestation
   /// @param signature EIP-712 signature from trustor&apos;s ENS owner
   function setTrust(
      TrustAttestation calldata attestation,
      bytes calldata signature
   ) external;

   /// @notice Batch set multiple trust relationships
   /// @dev All attestations MUST share the same trustorNode
   /// @param attestations Array of trust attestations
   /// @param signatures Corresponding signatures
   function setTrustBatch(
      TrustAttestation[] calldata attestations,
      bytes[] calldata signatures
   ) external;

   /// @notice Revoke trust (sets level to None)
   /// @dev Caller MUST be ENS owner or approved operator
   /// @param trustorNode The trustor&apos;s ENS namehash
   /// @param trusteeNode The agent to revoke trust from
   /// @param scope The scope to revoke trust in
   /// @param reasonCode Reason code for revocation
   function revokeTrust(
      bytes32 trustorNode,
      bytes32 trusteeNode,
      bytes32 scope,
      bytes32 reasonCode
   ) external;

   /// @notice Get trust record between two agents in a specific scope
   /// @param trustorNode The trusting agent
   /// @param trusteeNode The trusted agent
   /// @param scope The trust scope (bytes32(0) for universal)
   /// @return level Current trust level
   /// @return expiry Expiration timestamp (0 = never)
   function getTrust(
      bytes32 trustorNode,
      bytes32 trusteeNode,
      bytes32 scope
   ) external view returns (TrustLevel level, uint64 expiry);

   /// @notice Get current nonce for a trustor
   /// @param trustorNode The agent&apos;s ENS namehash
   /// @return Current nonce value
   function getNonce(bytes32 trustorNode) external view returns (uint64);

   // ═══════════════════════════════════════════════════════════════════
   // Path Verification
   // ═══════════════════════════════════════════════════════════════════

   /// @notice Verify a pre-computed trust path
   /// @param path The trust path to verify
   /// @param params Validation parameters
   /// @return valid Whether the path satisfies validation requirements
   /// @return anchorSatisfied Whether requiredAnchors constraint is met
   function verifyPath(
      TrustPath calldata path,
      ValidationParams calldata params
   ) external view returns (bool valid, bool anchorSatisfied);

   // ═══════════════════════════════════════════════════════════════════
   // ERC-8001 Integration
   // ═══════════════════════════════════════════════════════════════════

   /// @notice Set identity gate for a coordination type
   /// @param coordinationType The ERC-8001 coordination type
   /// @param gatekeeperNode Agent whose trust graph gates entry
   /// @param params Validation parameters for the gate
   function setIdentityGate(
      bytes32 coordinationType,
      bytes32 gatekeeperNode,
      ValidationParams calldata params
   ) external;

   /// @notice Remove identity gate for a coordination type
   /// @param coordinationType The ERC-8001 coordination type
   function removeIdentityGate(bytes32 coordinationType) external;

   /// @notice Get identity gate configuration
   /// @param coordinationType The ERC-8001 coordination type
   /// @return gatekeeperNode The gatekeeper agent
   /// @return params Validation parameters
   /// @return enabled Whether the gate is active
   function getIdentityGate(
      bytes32 coordinationType
   ) external view returns (
      bytes32 gatekeeperNode,
      ValidationParams memory params,
      bool enabled
   );

   /// @notice Validate participant using pre-computed path
   /// @param coordinationType The ERC-8001 coordination type
   /// @param path Pre-computed trust path from gatekeeper to participant
   /// @return isValid Whether participant passes the gate
   function validateParticipantWithPath(
      bytes32 coordinationType,
      TrustPath calldata path
   ) external view returns (bool isValid);
}
```

### OPTIONAL Interface Extensions

The following functions are OPTIONAL. Implementations MAY include them but they are not required for compliance:

```solidity
interface ITrustRegistryExtended is ITrustRegistry {
   /// @notice Get agents trusted by a given agent (paginated)
   /// @dev OPTIONAL - useful for indexing but not required
   function getTrustees(
      bytes32 trustorNode,
      TrustLevel minLevel,
      bytes32 scope,
      uint256 offset,
      uint256 limit
   ) external view returns (bytes32[] memory trustees, uint256 total);

   /// @notice Get agents that trust a given agent (paginated)
   /// @dev OPTIONAL - useful for indexing but not required
   function getTrustors(
      bytes32 trusteeNode,
      TrustLevel minLevel,
      bytes32 scope,
      uint256 offset,
      uint256 limit
   ) external view returns (bytes32[] memory trustors, uint256 total);

   /// @notice Validate an agent through on-chain graph traversal
   /// @dev OPTIONAL - expensive, prefer off-chain computation with verifyPath
   /// @param validatorNode The validating agent&apos;s perspective
   /// @param targetNode The agent to validate
   /// @param params Validation parameters
   /// @param marginalThreshold Number of marginal attestations required (for accumulation)
   /// @param fullThreshold Number of full attestations required
   function validateAgent(
      bytes32 validatorNode,
      bytes32 targetNode,
      ValidationParams calldata params,
      uint8 marginalThreshold,
      uint8 fullThreshold
   ) external view returns (
      bool isValid,
      uint8 pathLength,
      uint8 marginalCount,
      uint8 fullCount
   );

   /// @notice Check if any trust path exists
   /// @dev OPTIONAL - expensive, prefer off-chain computation
   function pathExists(
      bytes32 fromNode,
      bytes32 toNode,
      uint8 maxDepth
   ) external view returns (bool exists, uint8 depth);

   /// @notice Validate participant without pre-computed path
   /// @dev OPTIONAL - expensive, prefer validateParticipantWithPath
   function validateParticipant(
      bytes32 coordinationType,
      bytes32 participantNode,
      uint8 marginalThreshold,
      uint8 fullThreshold
   ) external view returns (bool isValid);
}
```

### Semantics

#### `setTrust`

`setTrust` MUST revert if:

* `attestation.trustorNode == attestation.trusteeNode` (self-trust prohibited)
* `attestation.nonce &lt;= getNonce(attestation.trustorNode)`
* `attestation.expiry != 0 &amp;&amp; attestation.expiry &lt;= block.timestamp`
* The signature does not verify per the Signature Authority section
* The ENS name for `trustorNode` does not exist (owner is zero address)

If valid:

* The trust record MUST be stored, keyed by `(trustorNode, trusteeNode, scope)`
* `getNonce(trustorNode)` MUST return the attestation&apos;s nonce
* `TrustSet` MUST be emitted

#### `setTrustBatch`

`setTrustBatch` MUST revert if:

* `attestations.length != signatures.length`
* Any attestation has a different `trustorNode` than the first attestation
* Any individual attestation would fail `setTrust` validation

Nonces within the batch MUST be strictly increasing.

#### `revokeTrust`

`revokeTrust` MUST revert if:

* Caller is not the ENS owner or an approved operator for `trustorNode`
* No existing trust relationship exists for `(trustorNode, trusteeNode, scope)` (level is `Unknown`)

If valid:

* Trust level MUST be set to `None`
* `TrustRevoked` MUST be emitted
* The relationship MUST remain in storage (not deleted) to preserve the explicit distrust

#### `verifyPath` — Path Verification Algorithm

`verifyPath` validates a pre-computed trust path.

**Algorithm:**

```solidity
function verifyPath(
   TrustPath calldata path,
   ValidationParams calldata params
) external view returns (bool valid, bool anchorSatisfied) {
   // Path must have at least 2 nodes (validator and target)
   if (path.nodes.length &lt; 2) return (false, false);

   // Path length constraint (edges = nodes - 1)
   if (path.nodes.length - 1 &gt; params.maxPathLength) return (false, false);

   // Track anchor satisfaction
   bool foundAnchor = params.requiredAnchors.length == 0;

   // Verify each edge
   for (uint256 i = 0; i &lt; path.nodes.length - 1; i++) {
      // Try scoped trust first, fall back to universal
      (TrustLevel level, uint64 expiry) = getTrust(
         path.nodes[i],
         path.nodes[i + 1],
         params.scope
      );

      // Fall back to universal scope if scoped trust not found
      if (level == TrustLevel.Unknown &amp;&amp; params.scope != bytes32(0)) {
         (level, expiry) = getTrust(
            path.nodes[i],
            path.nodes[i + 1],
            bytes32(0)
         );
      }

      // Edge must meet minimum trust level
      if (level &lt; params.minEdgeTrust) return (false, foundAnchor);

      // None explicitly voids (even if minEdgeTrust is somehow None)
      if (level == TrustLevel.None) return (false, foundAnchor);

      // Expiry check
      if (params.enforceExpiry &amp;&amp; expiry != 0 &amp;&amp; expiry &lt;= block.timestamp) {
         return (false, foundAnchor);
      }

      // Anchor check (intermediate nodes only, not first or last)
      if (!foundAnchor &amp;&amp; i &gt; 0) {
         for (uint256 j = 0; j &lt; params.requiredAnchors.length; j++) {
            if (path.nodes[i] == params.requiredAnchors[j]) {
               foundAnchor = true;
               break;
            }
         }
      }
   }

   return (true, foundAnchor);
}
```

**Scope fallback semantics:**

When validating an edge, implementations MUST:

1. First check for trust at the specified `params.scope`
2. If not found and `params.scope != bytes32(0)`, check for trust at universal scope `bytes32(0)`
3. Universal trust applies to all scopes

#### `validateParticipantWithPath`

This function gates [ERC-8001](/EIPs/EIPS/eip-8001) coordination participation.

```solidity
function validateParticipantWithPath(
   bytes32 coordinationType,
   TrustPath calldata path
) external view returns (bool isValid) {
   (bytes32 gatekeeperNode, ValidationParams memory params, bool enabled) =
               getIdentityGate(coordinationType);

   if (!enabled) return true; // No gate = open participation

   // Verify path starts at gatekeeper and ends at participant
   if (path.nodes.length &lt; 2) return false;
   if (path.nodes[0] != gatekeeperNode) return false;

   (bool valid, bool anchorOk) = verifyPath(path, params);
   return valid &amp;&amp; anchorOk;
}
```

### Errors

Implementations MUST revert with these errors:

```solidity
error SelfTrustProhibited();
   error NonceTooLow(uint64 provided, uint64 required);
   error AttestationExpired(uint64 expiry, uint64 currentTime);
   error InvalidSignature();
   error NotAuthorized(bytes32 node, address actor);
   error ENSNameNotFound(bytes32 node);
   error TrustNotFound(bytes32 trustorNode, bytes32 trusteeNode, bytes32 scope);
   error GateNotFound(bytes32 coordinationType);
   error InvalidValidationParams(string reason);
   error BatchTrustorMismatch();
   error BatchNonceNotIncreasing();
```

### Recommended Reason Codes

For `TrustRevoked` events, the following reason codes are RECOMMENDED:

| Reason Code | Value | Meaning |
|-------------|-------|---------|
| Unspecified | `bytes32(0)` | No specific reason |
| Misbehavior | `keccak256(&quot;MISBEHAVIOR&quot;)` | Agent acted improperly |
| Compromised | `keccak256(&quot;COMPROMISED&quot;)` | Key or account compromised |
| Inactive | `keccak256(&quot;INACTIVE&quot;)` | Agent no longer active |
| Transfer | `keccak256(&quot;TRANSFER&quot;)` | ENS name transferred |

### Recommended Scopes

For interoperability, the following scope values are RECOMMENDED:

| Scope | Value | Use Case |
|-------|-------|----------|
| Universal | `bytes32(0)` | Trust applies to all contexts |
| DeFi | `keccak256(&quot;DEFI&quot;)` | DeFi coordination |
| Gaming | `keccak256(&quot;GAMING&quot;)` | Gaming/metaverse |
| MEV | `keccak256(&quot;MEV&quot;)` | MEV protection |
| Commerce | `keccak256(&quot;COMMERCE&quot;)` | Agentic commerce |

### Recommended Coordination Types

For [ERC-8001](/EIPs/EIPS/eip-8001) identity gates:

| Coordination Type | Value |
|-------------------|-------|
| MEV Coordination | `keccak256(&quot;MEV_COORDINATION&quot;)` |
| DeFi Yield | `keccak256(&quot;DEFI_YIELD&quot;)` |
| Gaming Match | `keccak256(&quot;GAMING_MATCH&quot;)` |
| Commerce Escrow | `keccak256(&quot;COMMERCE_ESCROW&quot;)` |

## Rationale

### Why ENS Instead of a New Identity System?

ENS is finalised [EIP-137](/EIPs/EIPS/eip-137), battle-tested, and widely adopted. Creating a new identity system would:

* Add dependency on draft standards
* Fragment the identity ecosystem
* Require new adoption efforts

ENS provides everything needed: stable identifiers, ownership semantics, and extensibility.

### Why Scope as Storage Key?

A trustor may have different trust levels for the same trustee in different contexts. For example:

* Trust `bob.eth` fully for DeFi coordination
* Trust `bob.eth` marginally for gaming

Making scope part of the storage key `(trustorNode, trusteeNode, scope)` enables this naturally. Universal trust `bytes32(0)` serves as a fallback when scoped trust is not specified.

### Why minEdgeTrust Instead of Marginal/Full Thresholds?

The `marginalThreshold` and `fullThreshold` parameters were designed for on-chain graph traversal with marginal accumulation logic. Since on-chain traversal is OPTIONAL (expensive, DoS-prone), and the core primitive is `verifyPath`, we need only specify the minimum trust level each edge must have.

This simplification:

* Reduces parameter complexity
* Makes path verification straightforward
* Leaves accumulation semantics to OPTIONAL extensions

For use cases requiring marginal accumulation, the OPTIONAL `validateAgent` extension accepts threshold parameters.

### Why Separate Signing Authority from Transaction Submission?

ENS approvals (`isApprovedForAll`) are designed for operators to manage names on behalf of owners. However, allowing approved operators to forge attestation signatures would break the cryptographic binding between attestations and ENS owners.

By restricting signing authority to the ENS owner (or EIP-1271 for contract owners) while allowing operators to submit transactions like `revokeTrust`, we preserve:

* Cryptographic integrity of attestations
* Operational flexibility for name management
* Clear security boundaries

### Why verifyPath Only (No On-Chain Search)?

On-chain graph traversal is expensive and creates DoS vectors:

* Branching factor can explode with user-controlled adjacency lists
* Gas costs are unpredictable
* Attackers can bloat trustee lists

By requiring pre-computed paths, this standard:

* Keeps on-chain verification O(path length)
* Pushes search complexity to off-chain indexers where it belongs
* Enables predictable gas costs

Implementations MAY add `validateAgent` and `pathExists` as OPTIONAL extensions, but these are not required for compliance.

### Why Four Trust Levels?

The four-level model (Unknown, None, Marginal, Full) is proven by GnuPG&apos;s 25+ years of use. Finer granularity adds complexity without clear benefit; coarser granularity loses important distinctions.

With `minEdgeTrust`, applications can choose their security posture:

* `minEdgeTrust: Full` — Only fully trusted paths
* `minEdgeTrust: Marginal` — Accept marginal trust (default)

### Why Required Anchors?

Sybil attacks are the primary threat to web of trust systems. Required anchors force trust paths to traverse established community nodes (DAOs, protocols, auditors), transforming Sybil resistance from application-layer advice into protocol-level enforcement.

## Backwards Compatibility

This ERC introduces new functionality and does not modify existing standards.

**ENS Compatibility**: Uses standard ENS interfaces (`owner`, `isApprovedForAll`). Works with any ENS deployment. Does not rely on CCIP-Read or other off-chain mechanisms.

**ERC-8001 Compatibility**: Designed as a module. ERC-8001 coordinators can optionally integrate identity gates.

**Wallet Compatibility**: Uses [EIP-712](/EIPs/EIPS/eip-712) signatures, compatible with all major wallets. Supports [EIP-1271](/EIPs/EIPS/eip-1271) for contract wallets and smart accounts.

## Reference Implementation

See [`contracts/TrustRegistry.sol`](/EIPs/assets/eip-8107/contracts/TrustRegistry.sol) for the complete implementation.

## Security Considerations

### Sybil Attacks

An attacker can create many ENS names and establish mutual trust between them.

**Protocol-level mitigations:**

* **Required anchors**: `ValidationParams.requiredAnchors` forces paths through established community nodes
* **Short path limits**: `maxPathLength: 2` requires close proximity to validators
* **High trust requirement**: `minEdgeTrust: Full` rejects marginal trust paths

**Application-level mitigations:**

* Weight trust by ENS name age or registration cost
* Implement additional stake requirements
* Monitor trust graphs for anomalous patterns off-chain

### Trust Graph Manipulation

Attackers may attempt to position themselves in many trust paths.

**Mitigations:**

* Monitor trust graphs for anomalous patterns off-chain
* Use `minEdgeTrust: Full` for high-value coordination
* Require multiple independent paths via OPTIONAL extensions

### Key Compromise

If an ENS name&apos;s controller is compromised:

**Mitigations:**

* Agents SHOULD monitor for unexpected trust changes via `TrustSet` events
* Use short expiries (90 days maximum recommended for high-stakes)
* ENS name owners can rotate controllers
* Affected agents can issue `TrustRevoked` to quarantine compromised nodes

### ENS Name Transfer

When an ENS name is transferred:

* New owner inherits trust where they are the trustee
* New owner can manage trust where they are the trustor
* Old attestations signed by old owner remain valid until expiry

**Mitigations:**

* Use short expiries for high-stakes trust
* Monitor ENS `Transfer` events
* Re-evaluate trust after transfers

### Replay Protection

[EIP-712](/EIPs/EIPS/eip-712) domain binding prevents cross-contract replay. Monotonic nonces prevent replay within the same contract. The `chainId` in the domain prevents cross-chain replay.

### Stale Trust

Trust relationships may become stale if agents don&apos;t update them.

**Mitigations:**

* Use `enforceExpiry: true` in validation parameters
* Set reasonable `expiry` values on attestations (RECOMMENDED: 90 days maximum for high-stakes)
* Monitor `TrustSet` event timestamps off-chain

### Off-Chain Path Computation

This standard assumes off-chain indexers compute trust paths. Malicious indexers could:

* Return suboptimal paths
* Omit valid paths
* Return invalid paths (caught by `verifyPath`)

**Mitigations:**

* Users can run their own indexers
* Multiple independent indexers provide redundancy
* Invalid paths are always rejected on-chain

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 16 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8107</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8107</guid>
      </item>
    
      <item>
        <title>Diamonds, Simplified</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8109-diamonds-simplified/27119</comments>
        
        <description>## Abstract

A diamond is a proxy contract that `delegatecall`s to multiple implementation contracts called facets. 

![Diagram showing how a diamond contract works](/EIPs/assets/eip-8109/basic-diamond-diagram.svg)

Diamond contracts were originally standardized by [ERC-2535](/EIPs/EIPS/eip-2535). This standard refines that specification by simplifying terminology, reducing the implementation complexity of introspection functions, and standardizing specific events.

This standard preserves the full capabilities of diamond contracts while reducing complexity. It also specifies an optional upgrade path for existing ERC-2535 diamonds.

## Motivation

### Motivation for Diamond Contracts

&lt;img alt=&quot;Obligatory diamond&quot; src=&quot;../assets/eip-8109/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.

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.

Diamonds combine the single-address convenience of a monolithic contract with the modular flexibility of distinct, integrated contracts.

This architecture is well suited to **immutable** smart-contract systems, where all functionality is composed from multiple facets at deployment time and permanently fixed thereafter.

For upgradeable systems, diamonds enable incremental development: new functionality can be added, and existing functionality modified, without redeploying unaffected facets.

Additional motivation and background for diamond-based smart-contract systems can be found in [ERC-1538](/EIPs/EIPS/eip-1538) and [ERC-2535](/EIPs/EIPS/eip-2535).

### Motivation for this Standard

Unlike monolithic contracts, a diamond&apos;s external functions are commonly determined by runtime routing (selector → facet mapping) rather than being wholly represented in the diamond&apos;s source code or bytecode. To accurately determine or display the full set of functionality a diamond has, tooling must rely on standardized introspection functions and events.

Block explorers, indexers, development tools, and user interfaces need a standard way to inspect which functions and facets a diamond possesses. Additionally, tooling can be built to reconstruct and display the full development or upgrade history of diamond contracts using event logs.

ERC-2535 standardized introspection functions and events. [ERC-8109](/EIPs/EIPS/eip-8109) re-standardizes these to make diamond contracts easier to implement and easier to understand.

ERC-8109 improves upon ERC-2535 Diamonds in the following ways:

1. Simplified terminology.
2. Fewer and simpler to implement introspection functions.
3. Replaces a single monolithic event, with per-function events. This makes it easier to implement a variety of functions that add, replace and remove functions in a diamond. It also makes it easier for tools to search for and process events.

## Specification

### Terms
1. A **diamond** 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 [Implementation Requirements](#implementation-requirements) section.
2. A **facet** 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 `delegatecall`, 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.
3. An **introspection function** is a function that returns information about the facets and functions used by a diamond.
4. For the purposes of this specification, a **mapping** refers to a conceptual association between two items and does not refer to a specific implementation.

### Diamond Diagram

This diagram shows the structure of a diamond. 

It shows that a diamond has a mapping from function to facet and that facets can access the storage inside a diamond.

![Diagram showing structure of a diamond](/EIPs/assets/eip-8109/functionFacetMapping.svg)

### Fallback

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 `delegatecall`.

A diamond’s fallback function and `delegatecall` enable a diamond to execute a facet’s function as if it was implemented by the diamond itself. The `msg.sender` and `msg.value` values do not change and only the diamond’s storage is read and written to.

Here is an example of how a diamond’s fallback function might be implemented:

```solidity
error FunctionNotFound(bytes4 _selector);

// Executes function call on facet using `delegatecall`.
// Returns function call return data or revert data.
fallback() external payable {
    // Get facet address from function selector
    address facet = selectorToFacet[msg.sig];
    if (facet == address(0)) {
        revert FunctionNotFound(msg.sig);
    }
    // Execute external function on facet using `delegatecall` and return any value.
    assembly {
        // Copy function selector and any arguments from calldata to memory.
        calldatacopy(0, 0, calldatasize())
        // Execute function call using the facet.
        let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)
        // Copy all return data from the previous call into memory.
        returndatacopy(0, 0, returndatasize())
        // Return any return value or error back to the caller.
        switch result
        case 0 {revert(0, returndatasize())}
        default {return (0, returndatasize())}
    }
}
```
#### Function Not Found

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 `FunctionNotFound(bytes4 _selector)`.

### Events

#### Adding/Replacing/Removing Functions

These events are REQUIRED.

For each function selector that is added, replaced, or removed, the corresponding event MUST be emitted.

```solidity
/**
* @notice Emitted when a function is added to a diamond.
*
* @param _selector The function selector being added.
* @param _facet    The facet address that will handle calls to `_selector`.
*/
event DiamondFunctionAdded(bytes4 indexed _selector, address indexed _facet);

/**
* @notice Emitted when changing the facet that will handle calls to a function.
* 
* @param _selector The function selector being affected.
* @param _oldFacet The facet address previously responsible for `_selector`.
* @param _newFacet The facet address that will now handle calls to `_selector`.
*/
event DiamondFunctionReplaced(
    bytes4 indexed _selector,
    address indexed _oldFacet,
    address indexed _newFacet
);

/**
* @notice Emitted when a function is removed from a diamond.
*
* @param _selector The function selector being removed.
* @param _oldFacet The facet address that previously handled `_selector`.
*/
event DiamondFunctionRemoved(
    bytes4 indexed _selector, 
    address indexed _oldFacet
);
```

#### Recording Non-Fallback `delegatecall`s

This event is OPTIONAL.

This event can be used to record `delegatecall`s made by a diamond.

This event MUST NOT be emitted for `delegatecall`s made by a diamond’s fallback function when routing calls to facets. It is only intended for `delegatecall`s made by functions in facets or a diamond’s constructor.

This event enables tracking of changes to a diamond’s contract storage caused by `delegatecall` execution.

```solidity
/**
* @notice Emitted when a diamond&apos;s constructor function 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.
*/
event DiamondDelegateCall(address indexed _delegate, bytes _delegateCalldata);
```

#### Diamond Metadata

This event is OPTIONAL.

This event can be used to record versioning or other information about diamonds.

It can be used to record information about diamond upgrades.

```solidity
/**
* @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.
*/
event DiamondMetadata(bytes32 indexed _tag, bytes _data);
```

### Inspecting Diamonds

Diamond introspection functions return information about what functions and facets are used in a diamond.

These functions MUST be implemented and are required by the standard:

```solidity
/** @notice Gets the facet that handles the given selector.
 *
 *  @dev If facet is not found return address(0).
 *  @param _functionSelector The function selector.
 *  @return The facet address associated with the function selector.
 */
function facetAddress(bytes4 _functionSelector) external view returns (address);

struct FunctionFacetPair {
    bytes4 selector;
    address facet;
}

/**
* @notice Returns an array of all function selectors and their 
*         corresponding facet addresses.
*
* @dev    Iterates through the diamond&apos;s stored selectors and pairs
*         each with its facet.
* @return pairs An array of `FunctionFacetPair` structs, each containing
*         a selector and its facet address.
*/
function functionFacetPairs() external view returns(FunctionFacetPair[] memory pairs);
```

The essence of a diamond is its `function -&gt; facet` mapping. `functionFacetPairs()` returns that mapping as an array of `(selector, facet)` pairs. 

These functions were chosen because they provide all necessary facet and function data about a diamond. They are very simple to implement and are computationally efficient.

Block explorers, GUIs, tests, and other tools may rely on their presence.

A reference implementation exists for these introspection functions here: [DiamondInspectFacet.sol](/EIPs/assets/eip-8109/DiamondInspectFacet.sol)

Other introspection functions may be added to a diamond. The above two functions are the only ones required by this standard.

### Implementation Requirements

A diamond MUST implement the following:

1. **Diamond Structure**
   - A diamond MUST implement a `fallback()` function.
2. **Function Association**
   - A diamond MUST associate function selectors with facet addresses.
3. **Function Execution**
   - When an external function is called on a diamond:
     - The diamond’s fallback function is executed. 
     - The fallback function MUST find the facet associated with the function selector.
     - The fallback function MUST execute the function on the facet using `delegatecall`.
     - If no facet is associated with the function selector, the diamond MAY execute a default function or apply another handling mechanism.
     - If no facet, default function, or other handling mechanism exists, execution MUST revert with the error `FunctionNotFound(bytes4 _selector)`.
4. **Events**
   - The following events MUST be emitted:
     - `DiamondFunctionAdded` — when a function is added to a diamond.
     - `DiamondFunctionReplaced` — when a function is replaced in a diamond.
     - `DiamondFunctionRemoved` — when a function is removed from a diamond.
5. **Introspection**
   - A diamond MUST implement the following introspection functions:
     - `facetAddress(bytes4 _functionSelector)`
     - `functionFacetPairs()`


### `receive()` function

A diamond MAY have a `receive()` function.

### Immutable Functions

Definition:

&gt; An immutable function is an external or public function defined directly in a diamond contract, not in a facet.   
This definition does not apply to a diamond&apos;s constructor or the special `fallback()` and `receive()` functions.

A diamond can have zero or more immutable functions.

A diamond with immutable functions has the following additional requirements that MUST be followed:

1. The `DiamondFunctionAdded` event MUST be emitted for each immutable function.
2. Immutable functions MUST be returned by the introspection functions `facetAddress(bytes4 _functionSelector)` and `functionFacetPairs()`, where the facet address is the diamond’s own address.
3. Any upgrade function MUST revert on an attempt to replace or remove an immutable function.

## Rationale

This standard provides standard events and introspection functions so that GUIs, block explorers, command line programs, and other tools and software can detect and interoperate with diamond contracts.

Software can retrieve function selectors and facet addresses from a diamond in order to use and show what functions a diamond has. Function selectors and facet addresses, combined with contract ABIs and verified source code, provide sufficient information for tooling and user interfaces.

### ERC-8109 Diamonds vs ERC-2535 Diamonds

This standard is a simplification and refinement of ERC-2535 Diamonds. 

A diamond compliant with ERC-8109 is NOT required to implement ERC-2535.

Here are changes in ERC-8109 Diamonds:

- Simplified terminology.
- Simplified introspection functions.
- Standardized events that are simpler to use and consume.
- Optional upgrade path for existing ERC-2535 diamonds.

### Diamond Upgrades

This standard does not specify an upgrade function.

This means several things:

#### 1. Diamonds Can Be Immutable

A Diamond does not have to have an upgrade function.

- A diamond can be fully constructed within its constructor function without adding any upgrade function, making it immutable upon deployment.

- A large immutable diamond can be built using well organized facets.

- A diamond can initially be upgradeable, and later made immutable by removing its upgrade function.

#### 2. Other Standards Can Build on ERC-8109

Other standards can build on ERC-8109 by specifying an upgrade function(s), while remaining compliant with this standard.

#### 3. You Can Create Your Own Upgrade Functions

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 required events specified in the [events section](#events), and that the introspection functions defined in the [Inspecting Diamonds section](#inspecting-diamonds) continue to accurately return function and facet information.

### Gas Considerations

Routing calls via `delegatecall` introduces a small amount of gas overhead. In practice, this cost is mitigated by several architectural and tooling advantages enabled by diamonds:

1. **Optional, gas-optimized functionality**  
   By structuring functionality across multiple facets, diamonds make it straightforward to include specialized, gas-optimized features without increasing the complexity of core logic.  
   For example, an [ERC-721](/EIPs/EIPS/eip-721) 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.

2. **Reduced external call overhead**    
   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.  

3. **Selective optimization per facet**  
   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.

### `functionFacetPairs()` Gas Usage

The `functionFacetPairs()` function is meant to be called off-chain. At this time major RPC providers have a maximum gas limit of about 550 million gas. Gas benchmark tests show that the `functionFacetPairs()` function can return 60,000 `(selector, facet)` pairs using less gas than that.

ERC-8109 implementations are free to add iteration or pagination-based introspection functions, but they are not required by this standard.

### Storage Layout

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 [ERC-8042 Diamond Storage](/EIPs/EIPS/eip-8042) and [ERC-7201 Namespaced Storage Layout](/EIPs/EIPS/eip-7201).

### Facets Sharing Storage &amp; Functionality

Facets are separately deployed, independent units, but can share state and functionality in the following ways:

- Facets can share state variables by using the same structs at the same storage positions. 
- Facets can share internal functions by importing them or inheriting contracts. 

### On-chain Facets can be Reused and Composed

A deployed facet can be used by many diamonds.

It is possible to create and deploy a set of facets that are reused by different diamonds.

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.

It is possible to implement facets in a way that makes them usable/composable/compatible with other facets. 

### Function Signature Limitation

A function signature is the name of a function and its parameter types. Example function signature: `myfunction(uint256)`. A limitation is that two external functions with the same function signature can’t be added to the same diamond at the same time because a diamond, or any contract, cannot have two external functions with the same function signature.

### Immutable Functions Considerations

Immutable functions offer minor gas savings by avoiding fallback logic and a `delegatecall`. However, they introduce a second implementation alongside facets, resulting in two ways to provide similar functionality. This increases implementation complexity and cognitive overhead. 

A diamond is simpler to implement and understand without immutable functions.

In upgradeable diamonds, immutable functions reduce flexibility, as they cannot be replaced or removed. This limits the ability to evolve, fix, or improve functionality over time.

Immutable functions that read from or write to storage are not isolated from upgrades. Other functions, including upgrade logic, may modify the same storage relied upon by immutable functions. 

## Backwards Compatibility

Existing, deployed ERC-2535 Diamonds implementations MAY upgrade to this standard by performing an upgrade that does the following:

1. Removes the existing upgrade function and adds a new upgrade function that uses the new events.
2. Adds the new `functionFacetPairs()` introspection function.
3. Emits a `DiamondFunctionAdded` event for every function currently in the diamond, including the new upgrade function and the new `functionFacetPairs()` function.

Any other upgrade details are implementation specific.

After this upgrade, the diamond is considered compliant with this standard and SHOULD be indexed and treated as a diamond of this standard going forward.

This upgrade acts as a &apos;state snapshot&apos;. Indexers only interested in the current state of the diamond can start indexing from this transaction onwards, without needing to parse the legacy `DiamondCut` history.

To reconstruct the complete upgrade history requires retrieving all the past `DiamondCut` events as well as all new events defined in this standard.

### ERC-2535 Diamonds with Immutable Functions

An ERC-2535 diamond that upgrades to this standard and has immutable functions MUST comply with the [Immutable Functions](#immutable-functions) section of the Specification.

If the ERC-2535 diamond upgrade function is immutable, then it can&apos;t be removed. If possible, disable the upgrade function by making its authentication always fail.

## Reference Implementation

- The reference implementation for the `facetAddress(bytes4 _functionSelector)` and `functionFacetPairs()` introspection functions is here: [DiamondInspectFacet.sol](/EIPs/assets/eip-8109/DiamondInspectFacet.sol)
- An example implementation of an ERC-8109 diamond is here: [DiamondExample.sol](/EIPs/assets/eip-8109/DiamondExample.sol)

## Security Considerations

### Ownership and Authentication

The design and implementation of diamond ownership/authentication is not part of this standard. 

It is possible to create many different authentication or ownership schemes with diamonds. Authentication schemes can be very simple or complex, fine grained or coarse. This proposal does not limit it in any way. For example ownership/authentication could be as simple as a single account address having the authority to add/replace/remove functions. Or a decentralized autonomous organization could have the authority to add/replace/remove certain functions.

The development of standards and implementations of ownership, control and authentication of diamonds is encouraged.

### Transparency

A diamond emits an event every time a function is added, replaced or removed. Source code can be verified. This enables people and software to monitor changes to a diamond. 

Security and domain experts can review a diamond&apos;s upgrade history.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 21 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8109</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8109</guid>
      </item>
    
      <item>
        <title>Domain Architecture for Diamonds</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8110-domain-centric-architecture-for-diamonds/27250</comments>
        
        <description>## Abstract

This standard introduces a storage management architecture for contracts implementing a Diamond-based system.

Building on the namespaced storage identifier mechanism defined in [ERC-8042 (Diamond Storage)](/EIPs/EIPS/eip-8042), this proposal organizes contract state into domains and sub-domains.  
Each domain owns a dedicated storage layout and identifier, enabling consistent naming, deterministic storage positions, and a structured directory model that separates storage ownership from facet-level logic.

By formalizing domain boundaries and identifier conventions, this pattern reduces the risk of storage collisions and human error, while improving auditability and enabling better tooling for complex, multi-facet systems.

This standard defines only how storage is organized within Diamond-based architectures. It does not mandate a specific execution, upgrade, or facet model.  
Any system compatible with the Diamond architecture may adopt this Domain Architecture to manage and evolve contract storage safely.

## Motivation

[ERC-2535 (Diamond Standard)](/EIPs/EIPS/eip-2535) provides a flexible foundation for modular smart contracts through facets, but it intentionally leaves storage organization and architectural conventions open to implementation.  
While this flexibility encourages creativity, it can also lead to inconsistency.  
Each developer or team may structure storage differently, making it harder to design robust and easy-to-use tooling for storage management.  

Without a shared structural framework, storage identifiers may be inconsistently verified or reused across facets, which can result in unexpected collisions or subtle upgrade issues between facets sharing the same state.  

ERC-8042 introduced human-readable storage identifiers to improve clarity, but it does not define how those identifiers should be structured or grouped in larger projects.  

This ERC proposes a domain-centric architectural pattern that establishes a consistent framework for managing storage independently of facet implementation.  

By introducing clear domain boundaries and deterministic naming rules for storage identifiers, the pattern maintains the flexibility of Diamonds while providing a shared foundation for collaboration, tooling support, and long-term upgrade safety across systems.

## Specification

### 1. Domain Definition

- A **domain** represents the conceptual ownership of a storage space.  

- Each **domain** corresponds to exactly one storage struct and one identifier.  

- A **domain** has a one-to-many relationship with the group of function selectors that access it.

- A **domain** is independent of facets, multiple facets MAY read or modify the same domain.

- **Domains** SHOULD be defined according to business or system responsibility, not by facet name.

### 2. Storage Identifier Naming Convention

A storage identifier is the human-readable string whose keccak256 hash defines a Diamond Storage position.

```solidity
    bytes32 constant STORAGE_POSITION = keccak256(&quot;meaningful.string&quot;);
```

It represents the domain that owns and manages a specific storage layout.  
To ensure uniqueness and clarity, at a minimum, a storage identifier SHOULD include the following components:

```text
    {project}.{domain-name}.{version}
```

To improve readability, namespace separation, and tooling support, additional contextual components MAY be included, resulting in the following extended format:

```text
    {org}.{project}.{domain-type}.{domain-name}.{version}
```

### Identifier Components

- `org`  
  Optional organization or author prefix (e.g., `eth`, `vag`, `safe`)

- `project`  
  Project or protocol name

- `domain-type`  
    Optional classification of the domain. If present, it SHOULD be one of:

    - `diamond` — core Diamond protocol domains, such as upgrade, introspection, and ownership.

    - `system` — shared system-level domains providing cross-cutting functionality. (e.g.,  reentrancy, pause, access control)

    - `business` — application-specific domains. (tokens, guards, modules)

- `domain-name`  
    Lowercase keyword identifying the storage domain

- `version`  
    Optional storage layout version identifier  

    - The initial storage layout is conceptually treated as `v1`.  

    - If omitted, the identifier refers to this initial (`v1`) storage layout for backward compatibility.  

    - `v2`, `v3`, … MUST be used for layout-breaking changes.  

    - The version MUST be incremented only when the storage layout is no longer append-only.

**Each domain:**

- MUST have **one** storage struct and **one** identifier.

- SHOULD be implemented in a dedicated directory named after the domain.

- If new fields are added to a storage struct, they MUST be added only at the end, and the struct MUST remain append-only.

### Sub-domain Components
A sub-domain represents a storage-isolated vertical extension of an existing domain.

A sub-domain is used when new functionality belongs conceptually to an existing domain, but its required state can be cleanly isolated without modifying or appending to the original domain’s storage layout.

If present, the sub-domain&apos;s identifier format becomes: 

```text
    {project}.{domain-name}.{version}.{sub-domain}
```

or, when using the extended format:

```text
    {org}.{project}.{domain-type}.{domain-name}.{version}.{sub-domain}
```

The version component indicates the domain version in which the sub-domain was introduced.  
It serves as a historical and organizational reference, not as an independent versioning lifecycle for the sub-domain.

**Definition and Rules**

A sub-domain:

- MUST define its own ERC-8042 storage identifier.

- MUST define its own storage layout

- MUST NOT modify or append to the parent domain’s storage.

- MUST remain conceptually subordinate to the parent domain.

- MUST share the same version context as the parent domain.

- SHOULD be placed alongside the parent domain’s storage definitions.

Sub-domains exist as a safety-oriented design choice to isolate newly introduced state, while preserving the original domain layout unchanged.

Choosing between evolving the existing domain storage or introducing a sub-domain depends on the project’s complexity, the team’s discipline, and long-term maintenance goals.

### 3. Storage Declaration Requirements
To support reliable tooling and explicit storage ownership, each domain defined by this proposal MUST declare its storage location using the ERC-8042 NatSpec annotation.

Specifically, the domain-owned storage struct MUST be annotated with:

``` solidity
    ///@custom:storage-location erc8042:&lt;NAMESPACE_ID&gt;
```

This proposal does not redefine the storage location formula, but requires the use of this annotation to ensure that domain storage is discoverable, unambiguous, and machine-readable.

### Example Identifiers

The extended identifier format is recommended for global uniqueness.
It is especially useful when integrating shared libraries, predefined facets, or other standards, where namespace collisions are more likely.

For application-specific systems, teams may choose a minimal identifier format to reduce naming complexity, as long as the identifier remains stable and unique within the project.

**Equipment Identifier**  

Represents a business domain responsible for equipment state.
This domain has undergone a layout-breaking change, therefore uses an explicit v2 identifier.

```solidity
    /// @custom:storage-location erc8042:org.project.business.equipment.v2
    /// @dev Minimal form: project.equipment.v2
    bytes32 constant EQUIPMENT_STORAGE_POSITION = keccak256(&quot;org.project.business.equipment.v2&quot;);
```

**Character Identifier**  

Represents a business domain responsible for character state and progression.
This example also demonstrates how a domain can be extended using a storage-isolated sub-domain.

```solidity
    /// @custom:storage-location erc8042:org.project.business.character.v1
    /// @dev Minimal form: project.character.v1
    /// @dev Main character domain.
    bytes32 constant CHARACTER_STORAGE_POSITION = keccak256(&quot;org.project.business.character.v1&quot;);

    /// @custom:storage-location erc8042:org.project.business.character.v1.mounted
    /// @dev Minimal form: project.character.v1.mounted
    /// @dev Sub-domain for global character mounted state.
    bytes32 constant CHARACTER_MOUNTED_STORAGE_POSITION = keccak256(&quot;org.project.business.character.v1.mounted&quot;);
```

**Game Setting Identifier**  

Defines a system-level domain for game-wide configuration shared across multiple facets.

```solidity
    /// @custom:storage-location erc8042:org.project.system.gamesettings
    /// @dev Minimal form: project.gamesettings
    bytes32 constant GAME_SETTING_STORAGE_POSITION = keccak256(&quot;org.project.system.gamesettings&quot;);
```

### 4. Directory Convention

In line with Domain-Driven Design principles, the directory layout SHOULD reflect domain ownership.

- **Each domain defines a logical namespace for storage ownership**.  
  Directories are named after this namespace and serve as its physical representation in the codebase.

- **Facets act as logic containers and do not own storage**.  
  They MAY reside alongside domain directories or reference domain-owned logic.

- **Both directory names and storage identifiers SHOULD include domain information**.  
  This consistency allows tooling and precompilers to automatically associate selectors, domains, and storage layouts.

- **Each domain SHOULD be represented by a dedicated directory**.  
  Within this directory, domain-owned logic such as storage layout definitions, internal helper logic, and any facets primarily associated with the domain MAY be organized under subdirectories as needed.

- **This structure reduces the risk of storage collisions by design**.  
  The alignment of domain namespaces, directory layout, and storage identifiers allows file system constraints and static analysis tools to surface conflicts early and reason about upgrades proactively.

### Example Directory

*This directory structure is illustrative and does not mandate a specific naming convention.*  
*Subdirectory names such as `storage/` are illustrative and may contain both storage layout definitions and internal domain logic.*

```text
contracts/
├── diamond/
│   └── Diamond.sol
│
├── character/
│   ├── storage/
│   │   └── CharacterStorage.sol
│   └── facets/
│       └── CharacterFacet.sol
│
├── equipment/
│   ├── storage/
│   │   └── EquipmentStorage.sol
│   └── facets/
│       └── EquipmentFacet.sol
│
└── gamesettings/
    ├── storage/
    │   └── GameSettingsStorage.sol
    └── facets/
        └── GameSettingsFacet.sol
```
 
### 5. Upgrade Scenarios

This architecture defines upgrade behavior based on **the effect new selectors introduce to domains and storage**, rather than on facets themselves.

Upgrades fall into one of the following cases.

**Case 1: No new storage required**

If new selectors do not require any additional storage:

- The selectors MAY be added to existing facets or new facets
- The facet SHOULD be placed under an appropriate existing domain
- No storage changes are required

This is the simplest and safest upgrade path, as it introduces no new state and does not affect existing storage layouts.

**Case 2: New domain required (horizontal upgrade)**

If new functionality introduces state that does not logically belong to any existing domain:

- A new domain MUST be defined
- A new ERC-8042 storage identifier MUST be introduced
- A new storage layout MUST be defined for that domain
- The facet implementing this functionality SHOULD be placed under the new domain

This represents a horizontal expansion of the system, allowing new features to be introduced without impacting existing domains or storage layouts.

**Case 3: New variables within an existing domain (vertical upgrade)**

If new selectors require additional state that logically belongs to an existing domain, and the existing storage layout is not broken, this becomes a design trade-off.

Two common approaches MAY be used:

**Option A — Evolve the existing domain**

- Append new variables to the end of the existing storage layout
- Add new selectors to interact with the evolved domain

This keeps the domain unified and works well for tightly coupled or complex business logic.  
It requires strict discipline when managing storage layout.

**Option B — Introduce a sub-domain**

- Define a sub-domain under the existing domain
- Introduce a new storage identifier and layout for the new variables
- Leave the original domain storage unchanged

This approach reduces risk and cognitive load by isolating newly introduced state, while keeping the original domain layout stable.

The choice between these approaches depends on project complexity, team discipline, and long-term maintenance goals.

**Case 4: Layout-breaking change**

If new selectors require a change that breaks the existing storage layout of a domain  
(*for example, changing the inner structure of nested structs or struct arrays*)

- A new, versioned storage identifier MUST be introduced
- A new storage layout MUST be defined under that identifier
- Any required data migration MUST be handled explicitly by the project

This architecture does not attempt to automate or abstract storage migration.  
The goal is to keep schema changes intentional, visible, and auditable.

If the layout-breaking change is **partial**, and the newly required state can be cleanly isolated and defined independently, developers MAY also consider introducing a **sub-domain** instead of versioning the entire domain.

## Rationale

From the beginning, the Diamond Standard (ERC-2535) was designed around the relationship between **function selectors** and **storage positions**, not around facets themselves.  
Facets are replaceable units of logic — the `diamondCut` operation only replaces, removes or adds code — but the **storage layout persists** and defines the actual state continuity of the contract.  

A clear example of this can be found in `Reference Implementation` of ERC-2535.

Both `DiamondCutFacet` and `DiamondLoupFacet` interact with the same storage.  
Although these facets serve different purposes — one mutating, one querying — they share the same domain `diamond.storage`.  

This demonstrates that **storage belongs to the domain**, not the facet, facets merely provide interfaces for logic to read or mutate that domain.

Over time, many implementations have treated facets as the primary boundary of responsibility, grouping logic and storage together without recognizing that **storage domains** are the true architectural anchors.  
This leads to inconsistent storage management, overlapping identifiers and fragile upgrade paths where one facet unintentionally corrupts another’s state.

The **domain-centric approach** restores the original intent of the Diamond:  
Selectors (facets) operate *through* domains, not *as* domains.  
Each domain defines its own persistent storage struct and identifier, while facets merely act as interfaces that execute logic against it.  

This shift decouples storage from logic when separation is desired, while still allowing tightly coupled designs when intentional.  
It enables:

- Independent evolution of business logic without rewriting storage.  
- Clear separation between reusable system components and app-specific domains.
- A deterministic mapping between identifiers and state.

By formalizing this pattern, Diamond Architecture becomes safer, more transparent and easier to extend — re-aligning practice with its original design philosophy.

### Domain-Facet Overlap

There is a special case within the separation principle where a domain and its facet are intentionally designed to represent the same logical entity.

In this scenario, the facet implements all functions belonging to its domain.
This reduces flexibility, but improves encapsulation and self-containment, making the facet behave like a reusable application module rather than a low-level primitive.  

This approach is suitable for systems that prioritize modular composition and standardized functionality, allowing developers to safely integrate common features with predictable behavior.  
However, when implementing custom or project-specific logic, domains and facets SHOULD still be treated as separate entities.

Maintaining this separation preserves clarity of ownership, supports future upgrades, and supports the long-term evolution of application-level Diamond architectures.

### Sub-domains and Layout-Sensitive State

Sub-domains can also serve as a practical way to isolate layout-sensitive state.

Projects that need to move quickly may choose to place complex or layout-unstable data (such as mappings or dynamic arrays) in a primary domain, while isolating smaller or more compact state in sub-domains.

As development progresses, additional state can either be appended to an existing domain or introduced via a sub-domain, depending on data shape and evolution needs.

This allows projects to start with a simple structure while preserving flexibility to refine storage organization as the system scales.

### Isolated Domain

An isolated domain describes a conceptual separation between a domain and facet-level logic.
In this model, a domain defines its own storage access helpers. Facets and their functions interact with domain-owned state through these helpers, rather than accessing storage layouts directly.

This approach makes data access logic explicit at the domain level, while allowing facets to focus on business logic and coordination.

This concept provides several benefits:

- Data access logic is encapsulated as reusable helpers that can be shared across multiple functions and facets.

- These helpers can also be reused across domain versions, making data access logic consistent and predictable.

- When new variables or use cases are introduced, corresponding helpers can be added, reducing the risk of human error at the facet level.

- As small, focused blocks of logic, helpers improve readability, make the code easier to understand, and in some cases may allow the Solidity optimizer to generate more efficient bytecode.

A domain may be fully isolated, partially isolated, or not isolated, depending on project needs.

## Backwards Compatibility

This standard is fully backward-compatible with ERC-2535 (Diamond Standard) and ERC-8042 (Diamond Storage Identifier).  
It introduces no breaking changes, no new opcodes, and no modifications to existing protocol mechanics.

It does not alter the execution model defined by ERC-2535.  
The relationships between facets, selectors, and storage remain unchanged and fully compatible with existing Diamond systems.

Instead, this proposal defines an architectural convention that complements existing Diamond standards by:

- Reinforcing modularity and upgrade safety established by ERC-2535

- Extending the human-readable storage identifier design introduced by ERC-8042

- Providing a domain-based approach to storage ownership and organization

Developers are encouraged to continue following all applicable standards to maintain interoperability, while benefiting from clearer state ownership, reduced storage collision risk, and improved architectural clarity.

### Adoption for new Diamond Systems

For new projects adopting a Diamond architecture, development can begin by defining clear domain boundaries, then implementing storage, functions, and facets organized around each domain.

Since this standard defines only how storage is organized, projects may adopt the Domain Architecture without being concerned with the specific proxy or upgrade mechanics of the Diamond implementation.

Projects implementing ERC-2535 Diamonds, immutable Diamonds, or other upgrade mechanisms may apply the Domain Architecture to manage storage consistently and safely.

### Adoption for Deployed Systems

For already deployed systems, adoption can be done incrementally.

The Domain Architecture does not require projects to modify, rename, or refactor existing libraries or other standards in order to adopt it.
If a library or standard already follows ERC-2535, ERC-8042, or uses its own established storage identifiers, that code SHOULD remain unchanged.

Adoption MAY begin at the application layer, without touching shared libraries or standardized components.
Existing storage identifiers MAY be treated conceptually as pre-v1 domains.

In practice, projects typically start by:

- Defining clear domain boundaries
- Organizing directories around domain responsibility
- Grouping facets and their related storage by domain
- Explicitly declaring storage ownership using the ERC-8042 `@custom:storage-location` annotation

Adopting the Domain Architecture does not require migrating existing state.  
It primarily affects how new storage is introduced and how future upgrades are structured.

When a layout-breaking change is required, a new versioned storage identifier can be introduced explicitly,
allowing existing storage layouts to remain untouched.  
Any data migration, if needed, must be handled explicitly by the project.

The primary consideration during adoption is identifier uniqueness.  
New storage identifiers must not collide with existing identifiers from shared libraries or from within the project itself.

## Reference Implementation

Minimal implementation examples demonstrating the convention:

**Business Domain (Equipment)**

```solidity
    /// @custom:storage-location erc8042:org.project.business.equipment.v2
    /// @dev Minimal form: project.equipment.v2
    bytes32 constant EQUIPMENT_STORAGE_POSITION = keccak256(&quot;org.project.business.equipment.v2&quot;);

    struct Equipment 
    {
        uint8 itemType;        
        uint16 power;
        uint8 rarity;
        address effectOwner;   
    }

    struct EquipmentStorage 
    {
        mapping(uint256 =&gt; Equipment) items; // itemId =&gt; Equipment
    }

    function equipmentStorage() pure returns (EquipmentStorage storage s) 
    {
        bytes32 position = EQUIPMENT_STORAGE_POSITION;
        assembly {
            s.slot := position
        }
    }
```

**Business Domain (Character)**

```solidity
    /// @custom:storage-location erc8042:org.project.business.character.v1
    /// @dev Minimal form: project.character.v1
    /// @dev Main character domain.
    bytes32 constant CHARACTER_STORAGE_POSITION = keccak256(&quot;org.project.business.character.v1&quot;);

    struct Character 
    {
        uint32 level;
        uint256 hp;

        // equipment slot =&gt; itemId
        // e.g. slot: head, chest, weapon, boots...
        mapping(uint8 =&gt; uint256) equippedItemId;
    }

    struct CharacterStorage 
    {
        mapping(uint256 =&gt; Character) characters;
    }

    function characterStorage() pure returns (CharacterStorage storage s)
    {
        bytes32 position = CHARACTER_STORAGE_POSITION;
        assembly {
            s.slot := position
        }
    }

    /// @custom:storage-location erc8042:org.project.business.character.v1.mounted
    /// @dev Minimal form: project.character.v1.mounted
    /// @dev Sub-domain for global character mounted state.
    bytes32 constant CHARACTER_MOUNTED_STORAGE_POSITION = keccak256(&quot;org.project.business.character.v1.mounted&quot;);

    struct CharacterMountedStorage {
        // Global character state, persists across character switches
        bool isMounted;
    }

    function characterMountedStorage() pure returns (CharacterMountedStorage storage s)
    {
        bytes32 position =  CHARACTER_MOUNTED_STORAGE_POSITION;
        assembly {
            s.slot := position
        }
    }
```

**System Domain (Game Settings)**

```solidity
    /// @custom:storage-location erc8042:org.project.system.gamesettings
    /// @dev Minimal form: project.gamesettings
    bytes32 constant GAME_SETTING_STORAGE_POSITION = keccak256(&quot;org.project.system.gamesettings&quot;);

    struct GameSettingStorage {
        uint256 balancePatchBlock;
        bytes32 rulesetHash;
        uint32 gameVersion;
        uint32 seasonId;
        bool tradingEnabled;
        bool craftingEnabled;
        bool pvpEnabled;
    }

    function gameSettingsStorage() pure returns (GameSettingStorage storage s) {
        bytes32 position = GAME_SETTING_STORAGE_POSITION;
        assembly {
            s.slot := position
        }
    }
```

Each domain defines and owns its storage independently.
Facets interact with domain-owned storage definitions, supporting safe upgrades and avoiding unintended storage overlap.

## Security Considerations

This pattern strengthens the security model of Diamond-based systems by introducing explicit and deterministic storage identifiers.

By separating domains and enforcing consistent naming rules, it reduces the risk of:

- Storage collisions between unrelated facets or upgrades.
- Human errors caused by inconsistent or reused identifiers.
- State corruption during upgrades or extensions.

Each domain owns its ERC-8042 storage identifier.
When combined with append-only storage layout upgrades, this allows storage evolution without interfering with existing state.

This clarity also improves auditability and supports static analysis tooling when analyzing storage safety across upgrades.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 20 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8110</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8110</guid>
      </item>
    
      <item>
        <title>Bound Signatures</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8111-bound-signatures/27308</comments>
        
        <description>## Abstract
Recoverable ECDSA signatures can flip `s` and `v` while remaining valid, so they can be compressed to 64 bytes by restricting `v`.

## Motivation

ECDSA signatures are often encoded with three parameters: `v`, `r`, and `s`.
In the Solidity ABI encoding, this is 96 bytes.
By eliminating the degree of freedom, `v`, the encoded size of a recoverable signature can be reduced to 64 bytes.
Additionally, such signatures are not malleable.

## Specification

Smart contracts accepting bound signatures MUST exclusively use `27` for `v` and MUST NOT accept any other value.

```solidity
address signer = ecrecover(digest, 27, r, s);
require(signer != address(0));
```

ECDSA signatures MUST be bound before supplied to such contracts. 

```ts
const SECP256K1_N: bigint = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n

function bind(sig: Signature, v: 27 | 28 = 27): Signature {
    if (sig.v === v) {
        return sig
    }
    const s = SECP256K1_N - sig.s
    return new Signature(sig.r, s, v)
}
```

## Rationale

Another signature compression approach, [ERC-2098](/EIPs/EIPS/eip-2098), stores the y-parity bit in the most-significant bit of the low `s`.
Bound signatures are preferable because they are valid inputs to the `ecrecover` precompile.
They require less gas because they do not need to be unpacked by the smart contract.

A contract allowing both `27` and `28` reintroduces malleability.
`27` was chosen over `28` to make the y-parity falsy.

## Backwards Compatibility

Bound signatures are compatible with `ecrecover` if 27 is supplied for the `v` parameter.
They cannot be used for transaction signatures because they permit high `s`, in violation of [EIP-2](/EIPs/EIPS/eip-2).

## Test Cases

| Signer | Digest | `r` | `s` |
| ------ | ------ | --- | --- |
| `0x4a6f6B9fF1fc974096f9063a45Fd12bD5B928AD1` | `0xb0922c37cafd247fe3ada4eb1d1e3735b7d2837437c1178e9af120d535214270` | `0xdb7f75635124c807ec1f8b03e34cd76b633dc3a189e3c85fc5aee7e7d71df38c` | `0x5f1e6c6edf21cacfc2acba2815b253b9048b894eec5aaf70343389bb596c48bc` |
| `0x4a6f6B9fF1fc974096f9063a45Fd12bD5B928AD1` | `0xd92ff06caae7253883627416a425414d79e9003b91d6208add30e73735ef13c3` | `0xaa40efd534ac7f96b85babd7df9228fa131e8523115ca1ebc025698c37f3867d` | `0xa4b8d3c650fe62e46a563aed681bfdd44d50452fa7712bd139f2bfba3aed59c9` |
| `0x6B93E3bB9C0780C0f9042346Ffc379530a5882c1` | `0xfa75eba87f076cf22489da7c53a651bb3869473f78d09d4814afb7ab2d54ed45` | `0xaf4a877600ab6d14ebac626830cf1063d624487932b3cc73a7cd98ae7fbf337f` | `0xbc41d29acfcd3a1e7b5cb2dde1b85fe8882739312639b5f16d476a87584c040f` |

## Reference Implementation

```solidity
pragma solidity ^0.8.30;

library BoundSignatures {
    function recover(bytes32 digest, bytes32 r, bytes32 s) internal pure returns (address signer) {
        signer = ecrecover(digest, 27, r, s);
        require(signer != address(0));
    }
}
```

## Security Considerations

Bound signatures are recoverable and not malleable.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 23 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8111</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8111</guid>
      </item>
    
      <item>
        <title>Series Accounting for Incentivized Vaults</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8113-series-accounting-for-incentivized-vaults/27306</comments>
        
        <description>## Abstract

The following standard formalizes the Series Accounting Method for [ERC-7540](/EIPs/EIPS/eip-7540) and [ERC-4626](/EIPs/EIPS/eip-4626) type vaults, enabling them to collect performance fees on yields without introducing the free-rider problem.

It defines the necessary architectural specification for implementing Series Accounting by requiring an independent Series to track each batch of claimed deposit requests within the vault with its unique `totalAssets`, `totalShares`,  `sharesOf` and `highwaterMark` values.

## Motivation

Current vault implementations typically implement a Highwater Mark based on the highest recorded price-per-share (the ratio of total assets to total shares of the vault) to ensure performance fees are not collected for recovering losses. But relying on a single vault-wide highwater mark introduces the free-rider problem.

A free-rider occurs when a user&apos;s deposit is claimed at a price-per-share below the vault&apos;s current highwater mark. When the vault later reaches a new highwater mark, the user doesn’t pay a performance fee on all yield accrued between their initial entry price and the new highwater mark, effectively diminishing returns for existing users.

This standard implements the series accounting method where all batches of deposit requests are claimed in a series which maintains a unique highwater mark for those deposits. This allows for the protocol to accurately account for performance fees across all user deposits fairly. The “free-ride” problem is prevalent in vaults that derive their yields from RWAs. Reflecting performance from off-chain assets like hedge or liquid fund portfolios can vary drastically from each rebalancing/settlement cycle.

This can cause large fluctuations in exchange rates (price-per-share) of a vault resulting in inaccurate performance fee collection from users. Series Accounting is a very common and standard method of accounting portfolios in traditional funds but lacks any formal implementation in DeFi.


## Specification
The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

The general architecture of a vault remains the same. This standard can be used with both rebalancing type and async type vaults. For ERC-4626 type vaults which rebalances price-per-share periodically, all deposits made within a rebalancing period can be considered as a batch (all &quot;settled&quot; with same price-per-share). For ERC-7540 async type vaults, the user flows remain the same:
- users requiring to submit a request to enter or exit the vault
- vault implementing a method to move request from “pending” to “claimable” state

However, the structure in which `assets` and `shares` are maintained in the vault is altered to accommodate for series accounting. Traditionally, the vault will store a global value for `totalAssets` and `totalShares`, but to follow this specification, the following state variables MUST be maintained individually for each series:
- total assets
- total shares
- shares of users
- list of users
- highwater mark

### Definitions

- series: a series is like a sub-vault where a set of all deposit requests that are claimed together are accounted for.
- price-per-share: ratio of total assets to total shares in a series.
- highwater mark: the highest price-per-share (also referred as exchange price) of a given series.
- oracle: the entity responsible for setting the price-per-share of the vault.
- settle: the act of rebalancing the vault or claiming the deposit requests performed by the oracle in a series id, determined by the logic specified in this standard.
- lead series: each vault has a default series called the lead series where the first set of deposit requests will be claimed.
- outstanding series: a series apart from the lead series which contains user shares.
- consolidation: the process where all user shares are transferred from outstanding series to the lead series.
- consolidated series: an empty series from which user shares were transferred during consolidation.

#### Deposit Flow

For ERC-4626 type vaults, when the `oracle` provides the price-per-share for rebalancing, all deposits that will follow in that rebalancing period will be considered as a batch and MUST `settle` in the same series id. For ERC-7540 type vaults, when the `oracle` provides the price-per-share at which the deposits are to be claimed, all deposits MUST `settle` in the same series id. The standard defines in which series id the deposits SHOULD be `settled` as follows:

- **if the current highwater mark of the lead series is greater than the price-per-share of the lead series**
  - MUST create a new series with a unique series ID.
  - MUST settle all pending deposit requests in this new series.
- **else (if the highwater mark is less than or equal to the price-per-share):**
   - MUST settle all pending deposit requests in the lead series.
   - If the number of outstanding series is greater than zero:
     - MUST consolidate all outstanding series into the lead series.

#### Redeem Flow

[ERC-8113](/EIPs/EIPS/eip-8113) vaults MUST allow users to redeem (or request a redeem) by providing `assets` instead of `shares` as input.

The vault is RECOMMENDED to store the proportion of total `assets` for that user in the redeem request.

When the request is to be settled, the redemption MAY follow the FIFO method. At the time of settling a redeem request for a given price-per-share, the amount is to be redeemed from the lead series first. If the total user assets in lead series is not sufficient to fulfill the request, the remaining amount should be redeemed from the outstanding series with the lowest series Id. This process must be continued until the entire request is fulfilled. The portion of redemption that takes place in a given series is called a Redeem Slice.


## Rationale

### Using “assets” instead of “shares” for redemption

We cannot use `shares` to specify the amount a user wishes to redeem because shares are non-fungible across series. A user who can have assets across multiple series cannot specify a single share value in the request to represent all user assets.

If requests are made for a given series, `shares` can be used but then:
- user must make multiple requests if they wish to redeem more than what they own in a given series
- if the series gets consolidated (in case of async vaults), the redemption may take place from lead series but price-per-share information must be stored which makes implementation very complicated and can introduce security risks

The best solution presented to be users specifying `assets` instead of `shares` when making a redeem request. While processing the request, the implementation can store the proportion of total user assets across all series that they wish to redeem. 

This solves the issues of non-fungible shares and accounting across multiple series.

### Consolidating Series

Each new set of deposit requests may require its own series. This can cause the number of outstanding series to increase in number drastically if vault periodically has periods of poor performance.

This can cause following problems:
- having many outstanding series may result in any implementation processing them to exceed the block gas limit eventually which can render the vault unusable.
- traditional fund managers that expect to fetch vault data for their accounting reports are not pleased with having bloated Net Asset Vaule (NAV)/Assets Under Management (AUM) sheets with multiple series.

After the lead series reaches a new highwater mark, all subsequent outstanding series also reach new highwater marks. When this happens, each existing user has paid their fair share of performance and there no longer exists a need to maintain these deposits separately.

Hence, consolidating all outstanding series during this point can help a vault never exceed block gas limit and also keeps accounting reports for traditional managers clean and concise.

## Backwards Compatibility

Note that ERC-8113 is not backwards compatible with ERC-7540 or ERC-4626.

The incompatibilties with ERC-4626 are as follows:
- `totalAssets` would require additional input `seriesId`
- `convertToShares` would require additional input `seriesId`
- `convertToAssets` would require additional input `seriesId`
- `redeem` would need to replace input `shares` with `assets`

The incompatibilities with ERC-7540 are as follows:
- `requestRedeem` would need to replace input `shares` with `assets`

## Security Considerations

The fee calculation for yield bearing vaults can be complex as there can be multiple fixed and variable charges applied before performance fee. This can cause mismatch from expected and realised fee collections. 

Protocols must be careful and thoroughly analyze the accounting resulting from their implementations to ensure they match expectations, and should provide clear documentation of all fee calculations.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 25 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8113</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8113</guid>
      </item>
    
      <item>
        <title>Batch priority fees at end of block</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8115-batch-priority-fees-at-end-of-block/27358</comments>
        
        <description>## Abstract

This EIP defines how to optimize processing of priority fees from [EIP-1559](/EIPs/EIPS/eip-1559) fee market transactions.

## Motivation

Priority fees are credited at the end of each transaction, leading to these complications:

1. **Limited parallelization:** Each transaction writes to the fee recipient account balance.

2. **Mempool complexities:** A transaction sender may become solvent only after prior transactions in a block have been processed.

3. **Accounting complexities:** The fee recipient gets hundreds of micropayments for what could logically be a single credit.

4. **Inaccurate logs:** Proposals to emit logs on ETH transfers either have to omit priority fees, limiting their usefulness due to inaccuracies, or have to emit an extra entry for each individual fee, making them expensive.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

### Priority fee processing

[EIP-1559](/EIPs/EIPS/eip-1559) priority fees SHALL no longer be credited after each individual transaction. Instead, they SHALL be summed up and credited after all transactions of a block are processed but before [EIP-4895](/EIPs/EIPS/eip-4895) withdrawals are processed.

## Rationale

This EIP is one step towards fully accurate ETH balance logs. Batched crediting of priority fees improves parallel execution of transactions, as a transaction can no longer start with insufficient fees and only become eligible for execution after incremental priority fees have been credited.

## Backwards Compatibility

The fee recipient now receives priority fees at the end of the block rather than incrementally after each transaction, making it only possible to spend them in the next block. This may require updates to block builder infrastructure and change liquidity requirements for MEV use cases.

## Security Considerations

No security impact.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 30 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8115</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8115</guid>
      </item>
    
      <item>
        <title>Replace cumulative receipt fields</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8116-replace-cumulative-receipt-fields/27359</comments>
        
        <description>## Abstract

This EIP describes how to change the on-chain receipt data to track gas per transaction instead of cumulatively.

## Motivation

Currently, on-chain receipts track a `cumulativeGasUsed` field which contains the running sum of all gas spent for all transactions in the block so far. This has a number of shortcomings:

1. **Inefficient verification:** RPC clients that want to verify individual transaction `gasUsed` requires computation based on `cumulativeGasUsed` across consecutive receipts.

2. **Limited parallelism:** Receipt contents are stateful, even for transactions accessing mutually exclusive state.

The `logIndex` field exposed via JSON-RPC is currently also tracking an incremental block level index instead of a per-receipt index, with similar shortcomings.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

### `Receipt` construction

All receipts emitted after this EIP activates track the individual transaction&apos;s `gasUsed` instead of the incremental `cumulativeGasUsed` value.

### JSON-RPC API

Within `logs`, the `logIndex` field is changed to indicate the log index position in the individual receipt, rather than in the entire block.

## Rationale

This EIP is a step towards aligning on-chain data with the RPC data actually being consumed by client applications. Stateful components of receipts (`cumulativeGasUsed` / `logIndex`) are replaced with per-transaction equivalents.

## Backwards Compatibility

Applications using verified `gasUsed` / `cumulativeGasUsed` values need to adapt to the new on-chain data semantics.

Applications relying on the per block `logIndex` need adaptation, as `logIndex` now refers to an index per receipt. Note that this is solely an RPC change. Relative log ordering can be emulated by estimating `logIndex` as `transactionIndex * 4 + logIndex` (guaranteed to have same order as before, but absolute index values may be higher than before).

## Security Considerations

None

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 30 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8116</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8116</guid>
      </item>
    
      <item>
        <title>Anti-Poisoning Compact EVM Address Format</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8117-compressed-display-format-for-evm-addresses/27360</comments>
        
        <description>## Abstract

This ERC proposes a standard presentation-layer transformation whose primary purpose is to **prevent address-poisoning attacks**. Addresses with long leading zeros — increasingly common due to gas-optimization techniques and CREATE2 address mining — are a favoured target: the human eye skips over a monotonous run of zeros, allowing an attacker to substitute a crafted address that shares only the first few and last few visible characters. By condensing the low-entropy zero prefix into a compact subscript count, this standard forces the high-entropy suffix into immediate visual prominence, making poisoned addresses far easier to detect. It defines two display formats:

1. **Subscript Notation** (Unicode) — for wallets, block explorers, and mobile apps: `0x0₈abcd…1234`
2. **Parenthesis Notation** (ASCII fallback) — for logs, terminals, and legacy APIs: `0x0(8)abcd…1234`

In both formats the subscript or parenthesised integer `n` encodes the **total count of leading zero nibbles** present in the full address after the `0x` prefix. This standard is a purely visual UX transformation; it does not modify the underlying address data and is fully compatible with [EIP-55](/EIPs/EIPS/eip-55) checksumming.

## Motivation

**Address Poisoning Attacks:** Address poisoning exploits the fact that wallets typically display addresses in truncated form (`0xd28b…6922`), so users learn to verify only the first few and last few visible characters. An attacker can generate a lookalike address matching those characters in seconds on commodity hardware:

```
Real:     0xd28bE19170C22Bf3a5eD2E46890C9F394e3c6922
Attacker: 0xd28ba7F38c1D5e9B3f2A6c8E0d7b1F4a9C3e6922
            ^^^^                                ^^^^
            match  ←  32 completely different  →  match
```

The attack proceeds in four steps: (1) the attacker watches the victim&apos;s transaction history; (2) generates a lookalike address matching the target&apos;s prefix and suffix; (3) sends a zero-value transaction from that spoofed address, planting it in the victim&apos;s wallet history; (4) the victim copies the wrong address from their history and sends funds to the attacker. A single such attack has resulted in losses of $68M; aggregate losses across the ecosystem run into the hundreds of millions.

**Addresses with Long Leading Zeros and Exponential Cost:** Major protocols defend against address poisoning by deliberately mining addresses with long leading zeros. To poison such an address, an attacker must match all leading zeros *plus* the suffix — a task whose difficulty scales as $16^n$ per additional zero:

| Protocol | Address | Leading zeros | Approx. poisoning cost (consumer GPU) |
|---|---|---|---|
| [ERC-4337](/EIPs/EIPS/eip-4337) EntryPoint | `0x0000000071727De22E5E9d8BAf0edAc6f37da032` | 7 | Hours |
| Namefi NFT | `0x0000000000cf80E7Cf8Fa4480907f692177f8e06` | 10 | Days |
| Uniswap V4 PoolManager | `0x000000000004444c5dc75cB358380D2e3dE08A90` | 11 | ~42 days |
| ENS Public Resolver | `0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e` | 11 | ~42 days |
| Seaport | `0x0000000000000068F116a894984e2DB1123eB395` | 14 | Years |

Addresses with long leading zeros make poisoning economically irrational — but only if users can efficiently *verify* the zero count. Counting eleven zeros in `0x00000000000C2E…` by eye is error-prone and tedious; `0x0₁₁C2E…` communicates it instantaneously. This ERC standardises that notation.

**CREATE2 and Deliberate Address Mining:** Factories and developers frequently mine addresses with long leading zeros for branding, recognisability, or on-chain identification (e.g., `0x0000000071727De22E5E9d8BAf0edAc6f37da032`, the [ERC-4337](/EIPs/EIPS/eip-4337) EntryPoint).

**Gas Optimization ([EIP-7939](/EIPs/EIPS/eip-7939)):** Proposals like EIP-7939 reduce calldata gas costs proportional to leading zero bytes, creating a strong economic incentive to deploy contracts at addresses with large zero prefixes.

**Industry Adoption Gap:** Leading block explorers — Etherscan, PolygonScan, BscScan, and DexScreener — already display token balances with subscript notation for leading decimal zeros (e.g., `0.0₆9` for very small token amounts). Extending this well-understood UX pattern to hexadecimal addresses gives users a familiar, immediately interpretable signal.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in RFC 2119.

The compression transformation applies only to the visual representation of the address.

### 1. Trigger Condition

The notation SHOULD be applied when an EVM address has $n$ consecutive leading zero nibbles immediately after the `0x` prefix, where $n \geq 4$.

The value $n$ is the **total count of leading zero nibbles** — it includes every `0` nibble from the start of the address body up to (but not including) the first non-zero nibble.

**Scope:** This ERC deliberately limits its scope to leading zeros in order to focus on the primary security concern: address poisoning. Non-leading repeated sequences (trailing, middle) and non-zero repeated characters are out of scope. However, the industry is RECOMMENDED to follow the same subscript/parenthesis convention defined here should it choose to handle those cases.

### 2. Formatting Rules

This standard defines two display modes. Both retain the literal `0x0` prefix and encode the total leading-zero count $n$ compactly after it, followed by the remainder of the address (starting at the first non-zero nibble).

#### Mode A: Subscript Notation (UI/Frontend)

**Recommended for:** Wallets, block explorers (Etherscan, PolygonScan, BscScan), mobile apps, and any environment that can render Unicode.

**Syntax:** `0x0` + `[subscript_n]` + `[remainder]`

**Encoding:** The integer $n$ is converted to Unicode Subscript Digit characters (U+2080–U+2089).

| Raw address (excerpt) | $n$ | Subscript display |
|---|---|---|
| `0x0000abcd…1234` | 4 | `0x0₄abcd…1234` |
| `0x00000000abcd…1234` | 8 | `0x0₈abcd…1234` |
| `0x000000000004444c5dc75cB358380D2e3dE08A90` | 11 | `0x0₁₁44444c5dc75cB358380D2e3dE08A90` |
| `0x000000000004444c5dc75cB358380D2e3dE08A90` | 11 | `0x0₁₁4444c…8A90` |
| `0x0000000000000000000000000000000000000001` | 39 | `0x0₃₉1` |

#### Mode B: Parenthesis Notation — ASCII Fallback (CLI/Logs/APIs)

**Recommended for:** Developer consoles, log files, copy-paste operations, automated trading bot notifications, cross-platform messaging, and any environment where consistent Unicode rendering cannot be guaranteed.

The `(n)` parenthesis notation is the emerging **de facto standard** in automated trading bot alerts and cross-platform messaging systems precisely because it is safe in every ASCII context while still being unambiguous.

**Syntax:** `0x0` + `(` + `[n]` + `)` + `[remainder]`

| Raw address (excerpt) | $n$ | ASCII display |
|---|---|---|
| `0x0000abcd…1234` | 4 | `0x0(4)abcd…1234` |
| `0x00000000abcd…1234` | 8 | `0x0(8)abcd…1234` |
| `0x000000000004444c5dc75cB358380D2e3dE08A90` | 11 | `0x0(11)44444c5dc75cB358380D2e3dE08A90` |
| `0x000000000004444c5dc75cB358380D2e3dE08A90` | 11 | `0x0(11)4444c…8A90` |
| `0x0000000000000000000000000000000000000001` | 39 | `0x0(39)1` |

### 3. Case Sensitivity and [EIP-55](/EIPs/EIPS/eip-55)

To preserve the checksum integrity defined in EIP-55 and [EIP-1191](/EIPs/EIPS/eip-1191):

- The compression MUST strictly match identical ASCII characters.
- The compression MUST NOT be applied to mixed-case sequences (e.g., `aAaA` cannot be compressed).
- All non-compressed characters MUST retain their original casing.

## Rationale

### Subscript vs. Superscript (UI Mode)

This ERC selects **Subscript** (`0x0₈`) rather than superscript notation for the following reasons:

**Industry Alignment:** As described in the Motivation&apos;s &quot;Industry Adoption Gap&quot;, block explorers already use subscript for token amounts. Reusing that convention here gives users a single, consistent mental model across the ecosystem.

**Chemical/Scientific Metaphor:** Subscript notation in chemistry (H₂O) universally means &quot;count of the preceding atom.&quot; Applied here — `0x0₈` — it intuitively reads as &quot;eight zeros.&quot; Superscripts, by contrast, carry a mathematical power metaphor (`x⁸ = x to the power of 8`) that conflicts with the intended meaning.

**Baseline Conflict Avoidance:** Superscripts can visually collide with EIP-55 checksummed capitals when rendered in compact fonts or small UI elements. Subscripts sit below the text baseline and remain visually distinct.

### Parenthesis vs. Curly-Brace (ASCII Mode)

This ERC selects **parenthesis** `(n)` rather than curly-brace `{n}` for the ASCII fallback:

**De Facto Adoption:** Automated trading bots, Telegram/Discord notification systems, and cross-platform alert pipelines have independently converged on `0x0(n)` as the shorthand for addresses with long leading zeros. Standardising on existing practice minimises adoption friction.

**Copy-Paste Safety:** Parentheses `()` are legal in many shell contexts where curly braces `{}` trigger shell expansion, making `0x0(8)abcd…` safer to paste into terminals and scripts without escaping.

**Divergence from IPv6:** Unlike IPv6&apos;s implicit `::` fill, this notation always carries an explicit count, preserving the address-identity property that the exact number of zeros matters.

### Threshold of $n \geq 4$

A threshold of four leading zeros was chosen because:
- Fewer than four leading zeros (`0x000…`) are common enough that compression would add noise without meaningful readability gain.
- Four or more zeros (`0x0000…`) already push the boundary of reliable human counting; subscript compression provides measurable UX benefit at this point.
- The most security-relevant deliberately mined and gas-optimised addresses (e.g., [ERC-4337](/EIPs/EIPS/eip-4337) EntryPoint at 7 zeros, Uniswap V4 at 11 zeros) are all well above the threshold.

### Asymmetric Security: Easy to Verify, Hard to Attack

The use of addresses with long leading zeros, as described in the Motivation, creates a quantifiable cost asymmetry. With a modern consumer GPU at ~180 MH/s (double-keccak via WebGPU):

- **Defender (one-time):** Mining 9 leading zeros takes on the order of minutes.
- **Attacker (per victim):** Must match 9 zeros *and* a specific 6-nibble suffix — difficulty $O(16^{9+6}) = 16^{15}$ hashes ≈ **32 years** on the same hardware.

Even with hardware 10× more powerful than the defender&apos;s, the attacker still requires years per victim. This aligns perfectly with Ethereum&apos;s broader security principle: operations should be easy to verify but hard to forge.

This ERC is the display complement to that approach. Without it, a user holding an address with long leading zeros cannot efficiently *communicate* or *verify* its zero count. With it, `0x0₉suffix` signals both the count and the security posture at a glance — turning a cryptographic property into a human-readable security guarantee.

### Gas Optimization Context

With the introduction of logic similar to EIP-7939 (scaling calldata gas costs by zero bytes), the ecosystem will see a proliferation of addresses engineered for maximum leading-zero bytes. A display format that handles these addresses gracefully is a necessary proactive measure for user experience.

## Backwards Compatibility

This ERC is strictly a presentation layer standard.

**Wallets:** Must strip the compression formatting (convert back to full hex) before signing or broadcasting transactions.

**Safety:** Neither parentheses `()` nor Unicode subscript characters (U+2080–U+2089) are valid hexadecimal characters. If a user blindly copies a notated address into a legacy system, the system will reject the input as invalid rather than processing a wrong address. This acts as an automatic fail-safe mechanism.

## Reference Implementation

The following Python implementation demonstrates the encoding logic for both Subscript (Unicode) and Parenthesis (ASCII) modes, including full-display and truncated variants.

```python
# Subscript digit Unicode codepoints: U+2080 (₀) … U+2089 (₉)
SUBSCRIPTS = {
    &apos;0&apos;: &apos;\u2080&apos;, &apos;1&apos;: &apos;\u2081&apos;, &apos;2&apos;: &apos;\u2082&apos;, &apos;3&apos;: &apos;\u2083&apos;, &apos;4&apos;: &apos;\u2084&apos;,
    &apos;5&apos;: &apos;\u2085&apos;, &apos;6&apos;: &apos;\u2086&apos;, &apos;7&apos;: &apos;\u2087&apos;, &apos;8&apos;: &apos;\u2088&apos;, &apos;9&apos;: &apos;\u2089&apos;,
}

LEADING_ZERO_THRESHOLD = 4  # only apply notation when n &gt;= 4


def _to_subscript(n: int) -&gt; str:
    &quot;&quot;&quot;Convert a non-negative integer to a Unicode subscript string.&quot;&quot;&quot;
    return &quot;&quot;.join(SUBSCRIPTS[d] for d in str(n))


def count_leading_zeros(address: str) -&gt; int:
    &quot;&quot;&quot;Return the number of leading zero nibbles after the 0x prefix.&quot;&quot;&quot;
    body = address[2:] if address.startswith(&quot;0x&quot;) else address
    count = 0
    for ch in body:
        if ch == &apos;0&apos;:
            count += 1
        else:
            break
    return count


def format_address(address: str, mode: str = &apos;unicode&apos;, truncate: bool = False) -&gt; str:
    &quot;&quot;&quot;
    Format an EVM address using Hexadecimal Subscript Notation.

    Parameters
    ----------
    address  : Full 42-character EVM address (with 0x prefix).
    mode     : &apos;unicode&apos; → subscript notation  (0x0₈abcd…)
               &apos;ascii&apos;   → parenthesis notation (0x0(8)abcd…)
    truncate : If True, abbreviate the remainder to first4…last4 characters.

    Returns
    -------
    Formatted address string, or the original address if n &lt; LEADING_ZERO_THRESHOLD.
    &quot;&quot;&quot;
    n = count_leading_zeros(address)
    if n &lt; LEADING_ZERO_THRESHOLD:
        return address  # below threshold — no transformation

    body = address[2:]       # strip 0x
    remainder = body[n:]     # everything after the leading zeros

    if mode == &apos;unicode&apos;:
        count_str = _to_subscript(n)
        compact_prefix = f&quot;0x0{count_str}&quot;
    else:  # ascii / parenthesis
        compact_prefix = f&quot;0x0({n})&quot;

    if not truncate or len(remainder) &lt;= 8:
        return f&quot;{compact_prefix}{remainder}&quot;

    # Truncated: show first 4 and last 4 nibbles of the remainder
    return f&quot;{compact_prefix}{remainder[:4]}…{remainder[-4:]}&quot;


# ---------------------------------------------------------------------------
# Test Cases
# ---------------------------------------------------------------------------

# 1. ERC-4337 EntryPoint — 7 leading zeros
addr1 = &quot;0x0000000071727De22E5E9d8BAf0edAc6f37da032&quot;
print(format_address(addr1, mode=&apos;unicode&apos;))
# → 0x0₇71727De22E5E9d8BAf0edAc6f37da032

print(format_address(addr1, mode=&apos;ascii&apos;))
# → 0x0(7)71727De22E5E9d8BAf0edAc6f37da032

# 2. Uniswap V4 PoolManager — 11 leading zeros (truncated)
addr2 = &quot;0x000000000004444c5dc75cB358380D2e3dE08A90&quot;
print(format_address(addr2, mode=&apos;unicode&apos;, truncate=True))
# → 0x0₁₁4444…8A90

print(format_address(addr2, mode=&apos;ascii&apos;, truncate=True))
# → 0x0(11)4444…8A90

# 3. Ethereum precompile — 39 leading zeros
addr3 = &quot;0x0000000000000000000000000000000000000001&quot;
print(format_address(addr3, mode=&apos;unicode&apos;))
# → 0x0₃₉1

print(format_address(addr3, mode=&apos;ascii&apos;))
# → 0x0(39)1

# 4. Below-threshold address — no transformation applied
addr4 = &quot;0x000abcdef1234567890abcdef1234567890abcd&quot;
print(format_address(addr4, mode=&apos;unicode&apos;))
# → 0x000abcdef1234567890abcdef1234567890abcd  (unchanged: n=3 &lt; 4)
```

## Security Considerations

**Address Poisoning Mitigation:** The attack mechanism and the use of addresses with long leading zeros as a mitigation are described in the Motivation section. From an implementation standpoint, the critical requirement is that the notation MUST be rendered prominently and legibly — a subscript that is too small or too faint to read at a glance defeats the purpose of this standard entirely.

**Subscript Legibility:** Implementations MUST choose a font in which subscript digits (`₀`–`₉`) are clearly distinguishable from their full-size counterparts. `0x0₇` MUST NOT be renderable as `0x07` through font choice or rendering pipeline.

**Copy-Paste Validation:** Applications that accept address input MUST prioritise standard hexadecimal parsing. If an input contains `(n)` parenthesis notation or Unicode subscript characters, the application MUST either:
- Explicitly offer to decompress the notation before processing, or
- Reject the input as invalid.

Neither subscript Unicode characters nor parentheses are valid hexadecimal. This acts as an automatic fail-safe: a user who blindly pastes a notated address into a legacy system will receive an &quot;invalid address&quot; error rather than a silent wrong-address transaction.

**Preservation of Entropy:** This standard operates exclusively on the low-entropy leading-zero prefix. All non-zero nibbles — which carry the cryptographic uniqueness of the address — are always displayed verbatim and uncompressed, preserving the full information needed for security verification.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 30 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8117</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8117</guid>
      </item>
    
      <item>
        <title>Parameterized Storage Keys</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8119-key-parameters-standard-format-for-parameterized-string-keys/27397</comments>
        
        <description>## Abstract

This ERC defines standard formats for parameterized string keys used in EVM key-value storage. It supports two encodings: a slash/colon form for a single parameter (`&lt;key-label&gt;/&lt;key-parameter&gt;` or `&lt;key-label&gt;:&lt;key-parameter&gt;`) and a bracket form for one or more parameters (`&lt;key-label&gt;[&lt;key-parameter-1&gt;][&lt;key-parameter-2&gt;]...`).

## Motivation

Many EVM-based smart contracts use key-value storage to store metadata where string keys may need to represent multiple instances or variations of the same metadata type. Without a standardized format for parameterized keys, different implementations use inconsistent formats, leading to interoperability issues and parsing difficulties. 

## Specification

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

### Key Format

String keys used in EVM key-value storage MAY include parameters to represent variations or instances of a metadata type. When keys include parameters, they MUST follow the format:

```
&lt;key-label&gt;/&lt;key-parameter&gt;   or   &lt;key-label&gt;:&lt;key-parameter&gt;
```

or:

```
&lt;key-label&gt;[&lt;key-parameter-1&gt;][&lt;key-parameter-2&gt;]...
```

Where:
- **`&lt;key-label&gt;`**: MUST contain only printable ASCII characters **except** space, the forward slash character (`/`), the colon character (`:`), and the left bracket character (`[`). Concretely, allowed code points are `0x21-0x2E`, `0x30-0x39`, `0x3B-0x5A`, and `0x5C-0x7E` (letters, digits, and common punctuation), explicitly excluding control characters (`0x00-0x1F`), space (`0x20`), the slash character (`0x2F`), the colon character (`0x3A`), the left bracket (`0x5B`), and DEL (`0x7F`). The key-label identifies the type or category of metadata.
- **`&lt;key-parameter&gt;`** in slash/colon form: MAY be any UTF-8 encoded string **except** one that begins with a space. The character immediately after `/` or `:` MUST NOT be space; parameters may contain spaces elsewhere (e.g., `key/hello world`). For parameter data that must start with a space, use a quoted encoding where the space is the first character inside the quote (e.g., `quote/&apos; space is the first character in the quote&apos;`). Parsing uses the first occurrence of `/` or `:` as the separator; all subsequent characters belong to the single parameter.
- **`&lt;key-parameter-n&gt;`** in bracket form: each parameter MAY be any UTF-8 encoded string except `]` (which is reserved as the closing delimiter).

**Examples:**
- `&quot;registration/1&quot;` - ASCII key-label with numeric parameter
- `&quot;registration:1&quot;` - Same as above, using colon separator
- `&quot;user/alice&quot;` - ASCII key-label with ASCII parameter
- `&quot;website/http://website.com&quot;` - Slash/colon form where parameter includes additional `/`
- `&quot;name/María&quot;` - ASCII key-label with UTF-8 parameter (Spanish)
- `&quot;description/说明&quot;` - ASCII key-label with UTF-8 parameter (Chinese)
- `&quot;title/タイトル&quot;` - ASCII key-label with UTF-8 parameter (Japanese)
- `&quot;label/Étiquette&quot;` - ASCII key-label with UTF-8 parameter (French with accent)
- `&quot;user[alice]&quot;` - Bracket form with one parameter
- `&quot;resource[chain][1][token][42]&quot;` - Bracket form with multiple parameters
- `&quot;%gain/50&quot;` - Key-label with special character (percent)
- `&quot;$price/100&quot;` - Key-label with special character (dollar sign)
- `&quot;#tag/featured&quot;` - Key-label with special character (hash)
- `&quot;quote/&apos; space is the first character in the quote&apos;&quot;` - Parameter data starting with space: use quotes; space is first character inside

**Invalid formats:**
- `&quot;registration-1&quot;` (hyphen separator)
- `&quot;registration1&quot;` (no separator)
- `&quot;key/ value&quot;` (space immediately after separator)
- `&quot;key label/value&quot;` (space in key-label)
- `&quot;key[label&quot;` (missing closing bracket)
- `&quot;key[]tail&quot;` (trailing text after bracket form parameter list)

These formats provide a clean, consistent way to represent parameterized keys while maintaining readability and compatibility with parsers.

### Format Specification

For string keys used in EVM key-value storage (e.g., `mapping(string =&gt; bytes)` in Solidity, hash maps in Vyper, or equivalent structures in other EVM-compatible languages):

1. The `&lt;key-label&gt;` MUST contain only printable ASCII characters (0x21-0x7E), excluding spaces, `/`, `:`, and `[`. This excludes control characters, space, `/`, `:`, `[`, and DEL.
2. A key with parameters MUST use exactly one of the following encodings:
   - Slash/colon form: `&lt;key-label&gt;/&lt;key-parameter&gt;` or `&lt;key-label&gt;:&lt;key-parameter&gt;` (exactly one parameter)
   - Bracket form: `&lt;key-label&gt;[&lt;key-parameter-1&gt;][&lt;key-parameter-2&gt;]...` (one or more parameters)
3. In slash/colon form, parsing uses the first occurrence of `/` or `:` as the separator; all remaining characters belong to the single parameter. The character immediately after the separator MUST NOT be space.
4. In bracket form, the parser reads the label up to the first `[`, then reads one or more bracketed parameters in order. No trailing characters are allowed after the final `]`.

## Rationale

The slash (`/`) and colon (`:`) separators were chosen for the single-parameter form because:
- They provide clear, unambiguous separators that are easy to parse programmatically.
- Using whichever comes first ensures one parse rule; both may appear in the parameter.
- They are visually concise and user-friendly for casual or long text values, and avoid requiring a trailing `]`.
- Excluding both from the label is not restrictive, since labels are intended to be ASCII/domain-friendly.
- Disallowing a space immediately after the separator keeps parsing simple and avoids ambiguity; parameters with spaces elsewhere (e.g., `key/hello world`) remain valid.

The bracket form was added because:
- It provides an explicit structure for one or more ordered parameters.
- It allows applications to represent multi-parameter keys without custom encoding inside a single string.

Reserving `/`, `:`, and `[` from `&lt;key-label&gt;` keeps both encodings unambiguous.

## Backwards Compatibility

This ERC is fully backwards compatible. Existing implementations that do not use parameterized keys are unaffected. Implementations using non-standard parameter formats may continue to work but are encouraged to migrate to this standard format for better interoperability.

## Test Cases

### Valid Key Formats

- `&quot;name&quot;` - Simple key without parameters
- `&quot;registration/1&quot;` - Key with numeric parameter (slash)
- `&quot;registration:1&quot;` - Key with numeric parameter (colon)
- `&quot;registration/2&quot;` - Key with numeric parameter
- `&quot;user/alice&quot;` - Key with ASCII string parameter (slash)
- `&quot;user:alice&quot;` - Key with ASCII string parameter (colon)
- `&quot;session/abc123&quot;` - Key with alphanumeric parameter
- `&quot;website/http://website.com&quot;` - Slash/colon form parameter containing `//`
- `&quot;name/María&quot;` - Key with UTF-8 parameter (Spanish)
- `&quot;description/说明&quot;` - Key with UTF-8 parameter (Chinese)
- `&quot;title/タイトル&quot;` - Key with UTF-8 parameter (Japanese)
- `&quot;label/Étiquette&quot;` - Key with UTF-8 parameter (French with accent)
- `&quot;key/value:with:colons&quot;` - Key with parameter containing colons
- `&quot;key/one1 two2 three3&quot;` - Key whose single slash/colon-form parameter can be interpreted by an application as a list
- `&quot;key/value/with/slashes&quot;` - Key with parameter containing additional `/` (parsed at first `/`)
- `&quot;excerpt/Dan said \&quot;hi: how are you?\&quot;&quot;` - Key with quoted speech containing `: `
- `&quot;quote/&apos; space is the first character in the quote&apos;&quot;` - Parameter starting with space: use quotes; space is first character inside
- `&quot;user[alice]&quot;` - Bracket form with one parameter
- `&quot;resource[chain][1][token][42]&quot;` - Bracket form with multiple parameters
- `&quot;title[说明][日本語]&quot;` - Bracket form with UTF-8 parameters

### Invalid Key Formats

- `&quot;registration-1&quot;` - Uses hyphen instead of slash/colon
- `&quot;registration1&quot;` - No separator
- `&quot;key/ value&quot;` - Space immediately after separator (parameter must not start with space)
- `&quot;key label/value&quot;` - Space in key-label (key-label must be ASCII with no spaces)
- `&quot;key[label&quot;` - Unclosed bracket parameter
- `&quot;key[]tail&quot;` - Trailing non-bracket content in bracket form
- `&quot;key/param[extra]&quot;` - Mixed slash and bracket formats

## Reference Implementation

The following is a Solidity reference implementation. This standard applies to all EVM-compatible languages (Solidity, Vyper, etc.) that support string-keyed storage.

```solidity
pragma solidity ^0.8.25;
import {Strings} from &quot;@openzeppelin/contracts/utils/Strings.sol&quot;;

contract KeyParametersExample {
    mapping(string =&gt; bytes) private _metadata;

    constructor() {
        // Save three values
        setMetadata(&quot;registration/1&quot;, bytes(&quot;example1&quot;));
        setMetadata(&quot;registration/2&quot;, bytes(&quot;example2&quot;));
        setMetadata(&quot;registration/3&quot;, bytes(&quot;example3&quot;));

        // Read them all back
        for (uint256 i = 1; i &lt;= 3; i++) {
            string memory key = string(abi.encodePacked(&quot;registration/&quot;, Strings.toString(i)));
            bytes memory value = getMetadata(key);
            require(value.length != 0);
        }
    }

    function setMetadata(string memory key, bytes memory value) public {
        _metadata[key] = value;
    }

    function getMetadata(string memory key) public view returns (bytes memory) {
        return _metadata[key];
    }
}
```

## Security Considerations

- **User-facing input**: When keys are derived from user input, clients SHOULD validate `&lt;key-label&gt;` against the allowed ASCII range and reject labels containing spaces, `/`, `:`, or `[` to avoid ambiguous or non-standard keys. For slash/colon form, clients SHOULD reject keys where the character immediately after the separator is space.
- **Bracket parsing**: Clients that support bracket form SHOULD reject malformed inputs (for example unbalanced brackets, trailing characters after the final `]`, or mixed slash and bracket delimiters) to prevent parser divergence.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 06 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8119</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8119</guid>
      </item>
    
      <item>
        <title>MLOAD8 and CALLDATALOAD8 Opcodes</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8120-mload8-and-calldataload8-opcodes/27396</comments>
        
        <description>## Abstract

This EIP introduces new EVM opcodes that allow loading a single byte from memory or calldata in a single operation, reducing gas cost and bytecode size compared to existing patterns based on `MLOAD (0x51)` or `CALLDATALOAD (0x35)` followed by bit shifting.

## Motivation

Currently, the only way to read a single byte from calldata or memory is to use `CALLDATALOAD` or `MLOAD` and then shift the loaded 32-byte word.
For example, reading the byte at offset x from calldata requires:

```
PUSH x
CALLDATALOAD
PUSH1 248
SHR
```

This pattern increases runtime gas cost and adds three extra bytes to the deployed bytecode for each single-byte access. Contracts that frequently parse byte-oriented calldata or instruction streams incur unnecessary overhead.
This EIP proposes two new opcodes that allow loading a single byte directly in one operation.

## Specification

### MLOAD8 (TBD)

&lt;!-- TODO: Replace TBD with assigned opcode value --&gt;

- **Stack input**: `offset`
- **Stack output**: `value`

Reads one byte from memory at position offset and pushes it onto the stack as a 32-byte word, with the byte placed in the least significant position.
Memory expansion occurs prior to the load, after which the loaded byte is read.
If the accessed byte lies beyond the previously allocated memory, the returned value is 0 due to zero-initialization.
Memory expansion rules apply in the same way as for `MSTORE8` (extending memory to at least `offset + 1` bytes).

### CALLDATALOAD8 (TBD)

&lt;!-- TODO: Replace TBD with assigned opcode value --&gt;

- **Stack input**: `offset`
- **Stack output**: `value`

Reads one byte from calldata at position offset and pushes it onto the stack as a 32-byte word, with the byte placed in the least significant position.
If offset is greater than or equal to `CALLDATASIZE (0x36)`, the returned value is 0.

### Gas Cost

- Base cost: 3 gas
- `MLOAD8` additionally incurs memory expansion cost as defined by existing memory access rules.
The base gas cost matches `MLOAD`, `MSTORE8`, and `CALLDATALOAD`, ensuring consistency with existing EVM pricing.

### Exceptional Conditions

Execution results in an exceptional halt if:

- There is insufficient gas to execute the instruction
- There are insufficient stack items (stack underflow)

In both cases, execution halts and the current call frame is reverted, consistent with existing EVM behavior.

## Rationale

### Opcode Symmetry

`MLOAD8` serves as a natural counterpart to `MSTORE8 (0x53)`: one stores exactly one byte from the stack to memory, while the other loads exactly one byte from memory to the stack. This symmetry improves conceptual clarity and developer ergonomics.

### Efficiency for Byte-Oriented Contracts

Instruction-based architectures that interpret calldata as a sequence of byte-level commands benefit from reduced gas usage and smaller bytecode size when parsing instruction streams.
A common pattern for reading a single byte from calldata today consists of the following instruction sequence:

- `CALLDATALOAD` (3 gas)
- `PUSH1` (3 gas)
- `SHR` (3 gas)

This results in a total cost of 9 gas per byte read, excluding additional stack manipulation overhead, and increases deployed bytecode size due to the extra instructions.
Replacing this sequence with a single `CALLDATALOAD8` instruction priced at 3 gas saves 6 gas per byte read and reduces deployed bytecode size by approximately 3 bytes per occurrence. These savings compound in contracts that repeatedly parse byte-oriented calldata or instruction streams.

### Opcode Assignment

While the final opcode values are subject to allocation during review, this proposal suggests placing `MLOAD8` and `CALLDATALOAD8` in the `0x4X` opcode range. The `0x5X` range, which primarily contains stack, memory, storage, and control flow operations, is largely exhausted.
Tentative values of `0x4e` for `MLOAD8` and `0x4f` for `CALLDATALOAD8` are suggested to group these instructions near existing data access operations while minimizing the risk of opcode collisions. These assignments are intended to facilitate early client prototyping and collision checking and may be adjusted during the standardization process.

## Backwards Compatibility

This EIP introduces new opcodes and does not modify the semantics of existing instructions. No backwards compatibility issues are introduced beyond those inherent to any opcode-adding hard fork.

## Test Cases
 
Assume:

- `calldata = 0x0123456789abcdef`
- `memory = 0xfedcba9876543210`

| Bytecode | Description | Result |
|----------|-------------|--------|
| `5f &lt;CALLDATALOAD8&gt;` | `PUSH0; CALLDATALOAD8` | pushes `0x01` |
| `6002 &lt;MLOAD8&gt;` | `PUSH1 0x02; MLOAD8` | pushes `0xba` |
| `&lt;CALLDATALOAD8&gt;` | missing stack operand | exceptional halt |
| `&lt;MLOAD8&gt;` | missing stack operand | exceptional halt |

## Security Considerations

No new security considerations are introduced beyond those already known for memory and calldata access.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 07 Jan 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8120</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8120</guid>
      </item>
    
      <item>
        <title>Cross-Chain Function Calls via Hooks</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8121-delegated-metadata-resolution-via-hooks/27424</comments>
        
        <description>## Abstract

This ERC introduces hooks for cross-chain function calls. A hook fully specifies what function to call, with what parameters, on which contract, on which chain. Hooks require clients to use [ERC-3668](/EIPs/EIPS/eip-3668) to resolve, enabling cross-chain and off-chain verifiable data resolution. Hooks are particularly useful for redirecting metadata to known contracts with verifiable security properties, such as credential registries for Proof-of-Personhood (PoP) or Know-Your-Agent (KYA) for AI agent identity.

## Motivation

There is a need to resolve data cross-chain, such as credentials like Proof-of-Personhood (PoP), for example from a dedicated identity chain. There is also a need to save these cross-chain function calls onchain, and there is currently no existing standard for saving this type of function call as a string or bytes value onchain, in a maximally human-readable way. It should also be possible for a hook to be included in plain text, for example a markdown file intended to be consumed by AI agents. Hooks allow for a specific function, contract, and chain to be specified in a human-readable way. One of the most important features of hooks is that it allows clients to evaluate whether or not they trust the target contract, for example to resolve a PoP or KYC credential, before calling the function. 

### Use Cases

- **Cross-Chain Metadata**: Resolve metadata from contracts on other chains
- **Credential Resolution**: Redirect a Proof-of-Person (PoP) or Know-Your-Customer (KYC) record to a trusted credential registry
- **Singleton Registries**: Point to canonical registries with known security properties on any chain
- **Shared Metadata**: Multiple contracts can reference the same metadata source across chains

## Specification

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

### Overview

A hook is a fully specified function call containing an optional function selector, function signature with explicit types, human-readable function call with values, return type, and an [ERC-7930](/EIPs/EIPS/eip-7930) interoperable address specifying both the target contract and chain. The function selector acts as a checksum to verify the function signature, ensuring type safety and preventing ambiguity. This makes hooks completely self-describing - any client can resolve them without external documentation.

### Hook Function Signature

Hooks can be encoded with or without an optional function selector. When the selector is omitted, `functionSignature` is the first parameter.

**With optional function selector:**
```solidity
function hook(
    bytes4 functionSelector,
    string calldata functionSignature,
    string calldata functionCall,
    string calldata returnType,
    bytes calldata target
)
```

**Without function selector:**
```solidity
function hook(
    string calldata functionSignature,
    string calldata functionCall,
    string calldata returnType,
    bytes calldata target
)
```

```solidity
bytes4 constant HOOK_SELECTOR_WITH_SELECTOR = 0x037f43ed;  // When functionSelector is included
bytes4 constant HOOK_SELECTOR_WITHOUT_SELECTOR = 0x6113bfa3; // When functionSelector is omitted
```

#### Parameters

- **`functionSelector`**: (OPTIONAL) The 4-byte selector of the function to call. When provided, this acts as a checksum to verify the `functionSignature`. If omitted, the hook structure starts with `functionSignature` as the first parameter. Clients can always derive the selector from `functionSignature`.
- **`functionSignature`**: The full function signature with explicit parameter types (e.g., `&quot;getData((string,uint256))&quot;`, `&quot;getCredential(string)&quot;`). This MUST match the function selector when hashed, if a selector is provided. When the selector is omitted, this is the first parameter in the hook structure.
- **`functionCall`**: A string representation of the function to call with its parameter values (human-readable, e.g., `&quot;getData((&apos;alice&apos;, 42))&quot;`, `&quot;getCredential(&apos;kyc: 0x76F1Ff...123&apos;)&quot;`)
- **`returnType`**: The return type in Solidity tuple notation for ABI decoding (e.g., `(string)`, `(uint256, bytes32)`, `((string, uint256[], bytes32))`)
- **`target`**: An [ERC-7930](/EIPs/EIPS/eip-7930) interoperable address specifying both the target contract and chain

### Function Call Format

The `functionCall` parameter uses a Solidity-style syntax:

- String parameters are enclosed in single quotes: `&apos;value&apos;`
- Bytes/hex parameters use the `0x` prefix: `0x1234abcd`
- Numbers are written as literals: `42` or `1000000`
- Arrays use square brackets: `[1, 2, 3]` or `[&apos;a&apos;, &apos;b&apos;, &apos;c&apos;]`
- Structs/tuples use parentheses: `(&apos;alice&apos;, 42, true)`

**Examples:**

```
// Example with optional function selector (acts as checksum)
hook(0xc41a360a, &quot;getOwner(uint256)&quot;, &quot;getOwner(42)&quot;, &quot;(address)&quot;, 0x000100000101141234567890abcdef1234567890abcdef12345678)

// Example with function selector omitted
hook(&quot;getOwner(uint256)&quot;, &quot;getOwner(42)&quot;, &quot;(address)&quot;, 0x000100000101141234567890abcdef1234567890abcdef12345678)
```

### Hook Encoding

Hooks can be encoded in two formats depending on the storage type:

#### Bytes Format

For systems that store `bytes` values, hooks MUST be ABI-encoded. Use different hook selectors depending on whether the optional function selector is included:

**With optional function selector:**
```solidity
// Hook selector: first 4 bytes of keccak256(&quot;hook(bytes4,string,string,string,bytes)&quot;)
bytes4 constant HOOK_SELECTOR_WITH_SELECTOR = 0x037f43ed;

// Function signature with explicit types
string memory functionSignature = &quot;getContractMetadata(string)&quot;;

// Optional function selector as checksum (computed from signature)
bytes4 functionSelector = bytes4(keccak256(functionSignature)); // 0x1837de7f

// Function call with values
string memory functionCall = &quot;getContractMetadata(&apos;kyc&apos;)&quot;;

// ERC-7930 address: Ethereum mainnet (chain 1) contract
bytes memory target = hex&quot;000100000101141234567890abcdef1234567890abcdef12345678&quot;;

bytes memory hookData = abi.encodeWithSelector(
    HOOK_SELECTOR_WITH_SELECTOR,
    functionSelector,
    functionSignature,
    functionCall,
    &quot;(bytes)&quot;,  // return type
    target
);

// Store the hook as the value
originatingContract.setContractMetadata(&quot;kyc&quot;, hookData);
```

**Without function selector:**
```solidity
// Hook selector: first 4 bytes of keccak256(&quot;hook(string,string,string,bytes)&quot;)
bytes4 constant HOOK_SELECTOR_WITHOUT_SELECTOR = 0x6113bfa3;

// Function signature with explicit types
string memory functionSignature = &quot;getContractMetadata(string)&quot;;

// Function call with values
string memory functionCall = &quot;getContractMetadata(&apos;kyc&apos;)&quot;;

// ERC-7930 address: Ethereum mainnet (chain 1) contract
bytes memory target = hex&quot;000100000101141234567890abcdef1234567890abcdef12345678&quot;;

bytes memory hookData = abi.encodeWithSelector(
    HOOK_SELECTOR_WITHOUT_SELECTOR,
    functionSignature,  // First parameter when selector is omitted
    functionCall,
    &quot;(bytes)&quot;,  // return type
    target
);

// Store the hook as the value
originatingContract.setContractMetadata(&quot;kyc&quot;, hookData);
// Target function: function getContractMetadata(string) external view returns (bytes memory)
```

#### String Format

For systems that store `string` values, hooks MUST be formatted as shown below. The target is an [ERC-7930](/EIPs/EIPS/eip-7930) interoperable address.

**With optional function selector:**
```
hook(0x9e574b14, &quot;getContractMetadata(string)&quot;, &quot;getContractMetadata(&apos;kyc&apos;)&quot;, &quot;(bytes)&quot;, 0x000100000101141234567890abcdef1234567890abcdef12345678)
```

**Without function selector:**
```
hook(&quot;getContractMetadata(string)&quot;, &quot;getContractMetadata(&apos;kyc&apos;)&quot;, &quot;(bytes)&quot;, 0x000100000101141234567890abcdef1234567890abcdef12345678)
```

Parsers MUST detect the format by checking if the first parameter after `hook(` starts with `0x` followed by 8 hexadecimal characters (an optional function selector) or not.

**Examples:**

```

// Example 1: simple struct parameter
hook(0xabcdef12, &quot;getData((string,uint256))&quot;, &quot;getData((&apos;alice&apos;, 42))&quot;, &quot;(bytes)&quot;, 0x000100000101141234567890abcdef1234567890abcdef12345678)

// Example 2: struct parameter returning struct
hook(0x12345678, &quot;getCredential((string,uint256,bytes32))&quot;, &quot;getCredential((&apos;kyc&apos;, 12345, 0xabcd1234...))&quot;, &quot;((string,address,uint256))&quot;, 0x000100000101141234567890abcdef1234567890abcdef12345678)

// Example 3: nested struct (struct containing a struct)
hook(0x9abcdef0, &quot;getAgent((string,uint256,(address,bool,string)))&quot;, &quot;getAgent((&apos;alice&apos;, 42, (0x1234..., true, &apos;verified&apos;)))&quot;, &quot;((string,uint256,(address,bool)))&quot;, 0x000100000101141234567890abcdef1234567890abcdef12345678)
```

### Detecting Hooks

Clients SHOULD be aware in advance which metadata keys may contain hooks. It is intentional that hook-enabled keys are known by clients beforehand, similar to how clients know to look for keys like `&quot;image&quot;` or `&quot;description&quot;`.

For bytes values, hooks can be detected by checking if the value starts with either hook selector `0x037f43ed` (with optional function selector) or `0x6113bfa3` (without function selector). For string values, hooks can be detected by checking if the value starts with `hook(`.

### Resolving Hooks (Read Operations)

When a client encounters a hook that it wants to use for a read operation:

1. **Detect hook format**: For bytes format, check if the value starts with `0x037f43ed` (with selector) or `0x6113bfa3` (without selector). For string format, parse the first parameter after `hook(` to determine if it&apos;s a selector (starts with `0x` + 8 hex chars) or not.
2. **Parse the hook**: Extract the `functionSelector` (if present), `functionSignature`, `functionCall`, `returnType`, and `target` ([ERC-7930](/EIPs/EIPS/eip-7930) address). If the selector is omitted, `functionSignature` is the first parameter.
3. **Verify the selector** (if provided): If `functionSelector` is present, compute the expected selector from `functionSignature` as `bytes4(keccak256(functionSignature))` and verify it matches `functionSelector`. Reject the hook if they don&apos;t match. This verification ensures type safety and prevents ambiguity with structs or overloaded functions. If the selector is omitted, compute it from `functionSignature` for use in the function call.
4. **Parse the target**: Decode the [ERC-7930](/EIPs/EIPS/eip-7930) address to extract the chain and contract address
5. **Verify the target** (RECOMMENDED): Check that the target contract is known and trusted
6. **Parse the function call**: Extract the function name and parameter values from `functionCall`. Use `functionSignature` to determine the parameter types for ABI encoding.
7. **Enable [ERC-3668](/EIPs/EIPS/eip-3668)**: Clients MUST enable [ERC-3668](/EIPs/EIPS/eip-3668) offchain data retrieval before calling the target
8. **Call the target**: Execute the function on the target contract and chain. Use the provided `functionSelector` if available, otherwise compute it from `functionSignature` as `bytes4(keccak256(functionSignature))`. ABI-encode the parameters according to `functionSignature`.
9. **Get the result**: Retrieve the return value from the function call.

Clients MAY choose NOT to resolve hooks if the target contract is not known to be secure and trustworthy. Some clients have [ERC-3668](/EIPs/EIPS/eip-3668) disabled by default, but clients MUST enable it before resolving the hook.

### Write Operations

Write operations are also possible with hooks and follow the same flow as read operations, except that the transaction needs to be signed and submitted to the blockchain. The hook specifies the function to call, parameters, target contract, and chain, but instead of reading the result, the transaction is signed and broadcast to the network for inclusion in a block.

### Example: Cross-Chain KYC Credential Resolution

A contract on Optimism can redirect its `&quot;kyc&quot;` metadata key to a trusted KYC provider contract on Ethereum mainnet:

**Step 1: Store the hook in the originating contract (on Optimism)**

```solidity
bytes4 constant HOOK_SELECTOR_WITHOUT_SELECTOR = 0x6113bfa3;

// Function signature with explicit types
string memory functionSignature = &quot;getCredential(string)&quot;;

// Function call with values
string memory functionCall = &quot;getCredential(&apos;kyc: 0x76F1Ff0186DDb9461890bdb3094AF74A5F24a162&apos;)&quot;;

// KYCProvider on Ethereum mainnet (ERC-7930 format)
// Chain: Ethereum mainnet (chain 1), Address: 0x1234...5678
bytes memory target = hex&quot;000100000101141234567890abcdef1234567890abcdef12345678&quot;;

// Create hook that calls getCredential(&apos;kyc: 0x76F1Ff...&apos;) on the KYC provider
bytes memory hookData = abi.encodeWithSelector(
    HOOK_SELECTOR_WITHOUT_SELECTOR,
    functionSignature,  // First parameter when selector is omitted
    functionCall,
    &quot;(string)&quot;,  // return type
    target
);

// Store the hook
originatingContract.setContractMetadata(&quot;kyc&quot;, hookData);
```

**Step 2: Client resolves the hook**

```javascript
// Client reads metadata from originating contract (on Optimism)
const value = await originatingContract.getContractMetadata(&quot;kyc&quot;);

// Client detects this is a hook (starts with HOOK_SELECTOR)
const hasSelector = value.startsWith(&quot;0x037f43ed&quot;);
if (value.startsWith(&quot;0x037f43ed&quot;) || value.startsWith(&quot;0x6113bfa3&quot;)) {
    // Parse the hook (ABI decode after 4-byte selector)
    let functionSelector, functionSignature, functionCall, returnType, target;
    if (hasSelector) {
        ({ functionSelector, functionSignature, functionCall, returnType, target } = decodeHook(value));
    } else {
        ({ functionSignature, functionCall, returnType, target } = decodeHook(value));
        functionSelector = null;
    }

    // Verify selector matches the function signature (checksum verification, if provided)
    const computedSelector = keccak256(functionSignature).slice(0, 10);
    if (functionSelector) {
        if (functionSelector !== computedSelector) {
            throw new Error(&quot;Selector mismatch - function signature verification failed&quot;);
        }
    }
    // Use computed selector if not provided
    const selectorToUse = functionSelector || computedSelector;

    // Decode ERC-7930 address to get chain and contract
    const { chainId, address } = decodeERC7930(target);
    // chainId = 1 (Ethereum mainnet)
    // address = 0x1234567890abcdef1234567890abcdef12345678

    // Verify target is trusted (implementation-specific)
    if (!isTrustedResolver(chainId, address)) {
        throw new Error(&quot;Untrusted resolver&quot;);
    }

    // Parse the function call string to get function name and parameter values
    const { functionName, args } = parseFunctionCall(functionCall);
    // functionName = &quot;getCredential&quot;
    // args = [&quot;kyc: 0x76F1Ff0186DDb9461890bdb3094AF74A5F24a162&quot;]

    // Use functionSignature to determine parameter types for ABI encoding
    // functionSignature = &quot;getCredential(string)&quot;

    // Get provider for target chain and enable ERC-3668 (CCIP-Read)
    const targetProvider = getProviderForChain(chainId);
    const targetContract = new ethers.Contract(
        address,
        [`function ${functionSignature} view returns (bytes)`],
        targetProvider.ccipReadEnabled(true)  // Enable CCIP-Read
    );

    // Resolve from target contract on Ethereum mainnet
    // ABI-encode parameters according to functionSignature
    const resultBytes = await targetContract[functionName](...args);

    // ABI-decode using returnType: &quot;(string)&quot;
    const credential = ethers.utils.defaultAbiCoder.decode([returnType], resultBytes);
    // credential = &quot;Maria Garcia /0x76F1Ff.../ ID: 146-DJH-6346-25294&quot;
}
```

## Rationale

Hooks provide a complete specification for cross-chain function calls, including [ERC-7930](/EIPs/EIPS/eip-7930) interoperable address. This makes hooks entirely self-describing - any client can resolve them without external documentation or ABI files. For use cases including resolving credentials from known registries including PoP (Proof of Personhood) and KYC (Know Your Customer) credentials, the client needs to make sure the source of the credential is trustworthy and verified. Hooks allow clients to jump from a user&apos;s metadata record, for example, to a KYC credential from a known credential issuer.  

### Why Include Both Function Selector and Function String?

Hooks include both an optional 4-byte function selector and a human-readable function call string. The selector provides type disambiguation (e.g., `getData(bytes32)` and `getData(bytes)` have different selectors, but `0x1234...` in the string is ambiguous), while the string provides human readability. Clients can verify the selector matches the function signature, rejecting mismatches as errors or tampering.

### Why Use ERC-7930 Interoperable Addresses?

[ERC-7930](/EIPs/EIPS/eip-7930) addresses include chain information, making hooks a complete cross-chain function call specification. A hook specifies exactly what function to call, with what parameters, on which contract, on which chain. This eliminates ambiguity and enables secure cross-chain reads when combined with [ERC-3668](/EIPs/EIPS/eip-3668).

### Why Include the Return Type?

The `returnType` parameter allows clients to predict the return values without consulting documentation. It is also possible to predict if the return data is compatible with intended metadata. For example, if a bytes value redirects using hooks, that return value may need to also be bytes, according to the specific metadata standard (not specified here). Applications can impose their own constraints (e.g., requiring `(string)` for metadata hooks), but hooks themselves support any return type.

### Why Mandate [ERC-3668](/EIPs/EIPS/eip-3668)?

[ERC-3668](/EIPs/EIPS/eip-3668) (CCIP-Read) is a powerful technology that enables both cross-chain and verified offchain resolution of metadata. However, because some clients disable [ERC-3668](/EIPs/EIPS/eip-3668) by default due to security considerations, hooks explicitly mandate [ERC-3668](/EIPs/EIPS/eip-3668) support. This gives clients the opportunity to enable [ERC-3668](/EIPs/EIPS/eip-3668) specifically for hook resolution without needing to have it enabled globally. By tying [ERC-3668](/EIPs/EIPS/eip-3668) to hooks, clients can make a deliberate choice to enable it when resolving from known, trusted contracts, while keeping it disabled for general use.

## Backwards Compatibility

Hooks are backwards compatible; clients that are not aware of hooks will simply return the hook encoding as the raw value.

## Security Considerations

### Target Trust

The primary use of hooks is to resolve data from known contracts with verifiable security properties. Clients SHOULD:

- Maintain a list of trusted target contract addresses or use a third-party registry
- Fail when resolving from untrusted targets

### Recursive Hooks

Implementations SHOULD limit the depth of hook resolution to prevent infinite loops where a hook resolves to another hook. A reasonable limit is 3-5 levels of indirection.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 12 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8121</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8121</guid>
      </item>
    
      <item>
        <title>Minimal Agent Registry</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8122-minimal-agent-registry/27405</comments>
        
        <description>## Abstract

This protocol proposes a lightweight onchain registry for **discovering AI agents** using [ERC-6909](/EIPs/EIPS/eip-6909) as the underlying registry design, [ERC-7930](/EIPs/EIPS/eip-7930) for cross-chain agent identification, and [ERC-8048](/EIPs/EIPS/eip-8048) for onchain metadata. Each agent is represented as a token ID with a single owner and fully onchain metadata, enabling agent discovery and ownership transfer without reliance on external storage.

## Motivation

While various offchain agent protocols handle things like agent-to-agent communication, they don&apos;t inherently cover agent discovery. To foster an open permissionless agent economy, we need a mechanism for discovering agents in a decentralized way, as well as decentralized registration and publishing of agent metadata. We also need a standard that anyone can use to deploy their own agent registry. 

[ERC-8004](/EIPs/EIPS/eip-8004) provides an existing agent registry standard, but it defines a singleton registry—one per chain. A registry standard that supports custom deployments is necessary for specialized use cases, such as curated collections of agents (e.g., Whitehat Hacking Agents, DeFi Stablecoin Strategy Agents) or fixed-supply agent collections.

This ERC addresses this need through a lightweight **minimal agent registry** using [ERC-6909](/EIPs/EIPS/eip-6909). Anyone can deploy their own registry on any L2 or Mainnet Ethereum. All agent metadata is stored fully onchain using [ERC-8048](/EIPs/EIPS/eip-8048), ensuring censorship resistance and eliminating dependencies on external storage systems.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

### Agent Registry

The agent registry extends [ERC-6909](/EIPs/EIPS/eip-6909) and implements [ERC-8048](/EIPs/EIPS/eip-8048) for onchain metadata. Each agent is uniquely identified globally by:

- *`agentRegistry`*: An [ERC-7930](/EIPs/EIPS/eip-7930) Interoperable Address (binary) pointing to the registry contract
- *`agentId`*: The token ID (`uint256`) assigned by the registry per its implementation-defined scheme

The ERC-7930 Interoperable Address encodes the chain type, chain reference, and contract address in a single binary format, eliminating the need for separate namespace and chainId fields.

#### Agent ID Format

When displaying the Agent ID as text, it MUST follow the [ERC-8127](/EIPs/EIPS/eip-8127) Human Readable Token Identifiers format: `[alias.]agentId@registry`, where `registry` is the lowercase hex representation of the ERC-7930 interoperable address and `agentId` is the decimal `token ID`. The optional `alias` MAY be taken from the agent&apos;s `name` metadata field. For example: `agent.12345@0x00010000010114d8da6bf26964af9d7eed9e03e53415d37aa96045` or `12345@0x00010000010114d8da6bf26964af9d7eed9e03e53415d37aa96045` (without alias).

### Ownership Model

Each agent has a single owner. The registry MUST maintain a `mapping` from `agentId` to owner address and provide an `ownerOf(uint256 agentId)` function that returns the current owner. It MUST revert if the `agentId` does not exist.

#### Transfer Restrictions

To enforce single ownership:

- The `amount` parameter in `transfer` and `transferFrom` MUST be exactly 1
- Transfers MUST revert if `amount` is not 1
- Upon transfer, the `_owners` `mapping` MUST be updated to reflect the new owner

### Contract-Level Metadata

The registry SHOULD implement [ERC-8049](/EIPs/EIPS/eip-8049) for contract-level metadata about the registry itself. If ERC-8049 is used it MUST also expose a `setContractMetadata` function. Access control for this function is implementation-specific.

#### Standard Contract Metadata Keys

The following contract metadata keys SHOULD be set:


| Key           | Type   | Description                                                            |
| ------------- | ------ | ---------------------------------------------------------------------- |
| `name`        | string | Human-readable name of the registry                                    |
| `description` | string | Description of the registry&apos;s purpose or collection                    |
| `image`       | string | URI pointing to an image representing the registry (may be a data URL) |


The following contract metadata keys MAY be set:


| Key              | Type   | Description                           |
| ---------------- | ------ | ------------------------------------- |
| `symbol`         | string | Short symbol for the registry         |
| `banner_image`   | string | URI for a banner image                |
| `featured_image` | string | URI for a featured image              |
| `external_link`  | string | External website URL for the registry |


Implementations MAY define additional contract metadata keys as needed.

### Agent Metadata

All agent metadata is stored onchain using the [ERC-8048](/EIPs/EIPS/eip-8048) key-value store interface. The registry MUST implement the ERC-8048 interface and expose a `setMetadata` function. This function MUST revert if the caller is not the owner of the `agentId`, an approved spender, or an operator for the owner.

#### Standard Metadata Keys

The following metadata keys are RECOMMENDED for interoperability:


| Key             | Type    | Description                                                                                |
| --------------- | ------- | ------------------------------------------------------------------------------------------ |
| `name`          | string  | Human-readable name of the agent                                                           |
| `ens_name`      | string  | ENS name associated with the agent (e.g., &quot;myagent.eth&quot;)                                   |
| `image`         | string  | URI pointing to an image representing the agent (may be a data URL)                        |
| `description`   | string  | Natural language description of the agent&apos;s capabilities                                   |
| `service_type`  | string  | Type of service protocol (e.g., &quot;mcp&quot;, &quot;a2a&quot;). Additional types may be defined over time. |
| `service`       | string  | Primary offchain service URI for agent communication                                       |
| `agent_account` | address | The agent&apos;s account address for transactions                                               |


Implementations MAY define additional keys as needed. All metadata values are stored as `bytes`. If the type is not otherwise specified, the value MUST be a UTF-8 string encoded as bytes.

#### URI Format and Substitutions

URIs in metadata fields (such as `image` and `service`) MAY include the `{id}` placeholder, which clients SHOULD replace with the `token ID` when resolving the URI. For example, a `service` URI of `https://api.example.com/agents/{id}` with `token ID` `12345` would resolve to `https://api.example.com/agents/12345`.

URIs MAY use InterPlanetary File System (IPFS) protocol. IPFS URIs SHOULD use the format `ipfs://&lt;CID&gt;`. Clients SHOULD support resolving IPFS URIs through IPFS gateways or native IPFS clients.

Additional services can be added using [ERC-8119](/EIPs/EIPS/eip-8119) Parameterized Storage Keys. For example, a second service can be stored using `service_type: 1` and `service: 1`, a third service using `service_type: 2` and `service: 2`, and so on.

### Registration

New agents can be minted by calling one of the registration functions defined in the interface below. Upon registration:

- A new `agentId` MUST be assigned according to the registry&apos;s implementation-defined scheme and MUST be unique
- The provided `owner` MUST be set as the owner in the `_owners` `mapping`
- The owner MUST receive a `balance` of 1 for that `agentId`

This emits an ERC-6909 `Transfer` event (from `address(0)` to the owner), one ERC-8048 `MetadataSet` event for each metadata entry if any, and a `Registered` event as defined in the interface below. If any of the event parameters (`service_type`, `service`, or `agent_account`) are not set, they MUST be set to default empty values (empty string for strings, `zero address` for addresses) when emitting the event.

### Interface

The registry MUST implement [ERC-6909](/EIPs/EIPS/eip-6909), [ERC-8048](/EIPs/EIPS/eip-8048), and MAY implement [ERC-8049](/EIPs/EIPS/eip-8049). The following interface defines the additional functions and events specific to this ERC:

```solidity
interface IERC8122 {
    struct MetadataEntry {
        string key;
        bytes value;
    }
    
    event Registered(uint256 indexed agentId, address indexed owner, string service_type, string service, address agent_account);

    function register(address owner, string calldata service_type, string calldata service, address agent_account) external returns (uint256 agentId);
    function register(address owner, MetadataEntry[] calldata metadata) external returns (uint256 agentId);
    function registerBatch(address[] calldata owners, MetadataEntry[][] calldata metadata) external returns (uint256[] memory agentIds);
    function ownerOf(uint256 agentId) external view returns (address);
}

interface IERC8049SetContractMetadata {
    function setContractMetadata(string calldata key, bytes calldata value) external;
}
```

## Rationale

The minimal agent registry is designed to be a simple, focused foundation for agent discovery, registration, and onchain metadata. ERC-6909 was chosen as the registry design because it is the most efficient minimal token standard, minimizing gas costs for agent registration and transfers. By storing all metadata onchain, we leverage the full power of Ethereum and its L2s: censorship resistance, atomic updates, composability with other smart contracts, and permanence. This approach ensures that agent information cannot be taken down or altered by external parties, and allows other protocols to build on top of the registry, whether for reputation systems, credentials (such as KYA &quot;Know Your Agent&quot;), or validation, without requiring changes to the core registry itself.

## Backwards Compatibility

No issues. 

## Security Considerations

None.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 17 Dec 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8122</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8122</guid>
      </item>
    
      <item>
        <title>RPC Method for Transaction Gas Limit Cap</title>
        <category>Standards Track/Interface</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8123-json-rpc-method-for-transaction-gas-limit-cap/27417</comments>
        
        <description>## Abstract

This EIP specifies a new Ethereum JSON-RPC method, `eth_txGasLimitCap`, which returns the maximum transaction gas limit
(`tx.gas`) that the node will accept under the current fork rules (and any stricter local policy). This enables wallets,
SDKs, bundlers, and tooling to discover the effective per-transaction gas limit cap without simulation or out-of-band
knowledge.

## Motivation

[EIP-7825](/EIPs/EIPS/eip-7825) introduces a protocol-level per-transaction gas limit cap (e.g. `2^24 = 16,777,216` on Ethereum) to bound
worst-case single-transaction work. However, it does not specify any way to query this cap.

As a consequence, users and tools must:

- infer it from failed transaction submissions,
- hardcode network assumptions,
- read client source code,
- or rely on Internet documentation.

This is brittle because:

- the cap may change in future upgrades,
- different chains intentionally set different cap values (e.g. Arbitrum and Polygon both use `32,000,000`),
- and there already are some proposals to make the transaction gas limit cap dynamic, rather than hardcoded, based on new
  fee calculation rules

## Specification

The key words “MUST&quot;, “MUST NOT&quot;, “SHOULD&quot;, and “MAY&quot; are to be interpreted as described in RFC 2119.

### New method: `eth_txGasLimitCap`

#### Request

- **Method**: `eth_txGasLimitCap`
- **Params**: `[]` (no parameters)

#### Response

- **Result**: `QUANTITY` or `null`
  - If the node enforces a finite transaction gas limit cap, it **MUST** return that cap as a `QUANTITY`.
  - If the node does not enforce a finite cap, it **MUST** return `null`.

Returning `null` indicates that no finite per-transaction gas limit is enforced by the node.

#### Semantics

Let:

- `protocolCap` be the maximum `tx.gas` permitted by the active protocol rules at the node&apos;s current head (e.g. from
  EIP-7825 when enabled).
- `policyCap` be any stricter local cap applied by the node to transaction acceptance (e.g. txpool admission), if
  configured; otherwise, unbounded.

Then the node **MUST** return:

- `min(protocolCap, policyCap)` if finite, else `null`.

A node **MUST NOT** return a value higher than the protocol cap when the protocol cap is finite.

#### Example

Ethereum (EIP-7825 cap = `2^24`):

```json
{ &quot;jsonrpc&quot;: &quot;2.0&quot;, &quot;id&quot;: 1, &quot;method&quot;: &quot;eth_txGasLimitCap&quot;, &quot;params&quot;: [] }
```

```json
{ &quot;jsonrpc&quot;: &quot;2.0&quot;, &quot;id&quot;: 1, &quot;result&quot;: &quot;0x1000000&quot; }
```

A chain with a `32,000,000` cap:

```json
{ &quot;jsonrpc&quot;: &quot;2.0&quot;, &quot;id&quot;: 1, &quot;result&quot;: &quot;0x1e84800&quot; }
```

## Rationale

A dedicated method is needed because there is currently no way to query the maximum allowed `tx.gas` without simulation
or out-of-band knowledge.

Returning the _effective_ cap (`min(protocolCap, policyCap)`) matches what users need when constructing transactions to
submit.

## Backwards Compatibility

This EIP adds a new JSON-RPC method and does not modify existing methods. Existing clients and applications remain
compatible.

## Reference Implementation

Pseudo code:

```text
if protocol has finite tx gas cap at head:
  protocolCap = that value
else:
  protocolCap = +infinity

if protocol has policy cap:
  policyCap = that value
else:
  policyCap = +infinity

cap = min(protocolCap, policyCap)

if cap is finite:
  return cap
else:
  return null
```

## Security Considerations

This EIP only exposes information that is already public or otherwise observable by probing. It does not expose secrets
or user data.

## Copyright

Copyright and related rights waived via CC0.
</description>
        <pubDate>Sun, 11 Jan 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8123</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8123</guid>
      </item>
    
      <item>
        <title>Temporary Contract Storage</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip8125-temporary-contract-storage/27440</comments>
        
        <description>## Abstract

This EIP introduces *temporary storage*: a new contract-accessible key-value store that persists across transactions and blocks, but is automatically cleared at a protocol-defined schedule. Two new opcodes are added:

- `TMPSTORE(key, value)` to write temporary storage for the executing contract.
- `TMPLOAD(key)` to read temporary storage for the executing contract.

Temporary storage is intended for data that does not need indefinite retention, providing a safer alternative to using permanent state for ephemeral data and enabling bounded growth of this class of state.

## Motivation

![](/EIPs/assets/eip-8125/1.png)

*Figure 1: Over 60% of the storage slots are written once and never accessed again onchain.*

Permanent contract storage is costly because it increases long-term node resource requirements (disk, I/O, state maintenance). However, many applications write data that is only valuable for a bounded time window.

This EIP provides:

- **Bounded lifetime semantics** without requiring explicit deletes.
- **Predictable clearing** that can be relied upon at the application layer.
- **A building block** for reducing state growth created by ephemeral use cases.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

### Constants and parameters

|Name|Value|Description|
|-|:-:|-|
| `FORK_BLOCK` | TBD | Activation block of this EIP |
| `TEMP_STORAGE_PERIOD` | TBD | The number of blocks that the temporary storage holds for a given period |
| `TEMP_STORAGE_SYSTEM_ADDRESS_0` | TBD | First reserved address used to store temporary storage |
| `TEMP_STORAGE_SYSTEM_ADDRESS_1` | TBD | Second reserved address used to store temporary storage |
| `TMPLOAD_GAS` | TBD | The gas cost of a warm read at temporary storage slot |
| `COLD_TMPLOAD_COST` | TBD | The gas cost surchage of a cold access at the temporary storage |
| `TMPSTORE_SET_GAS` | TBD | The gas cost of setting a slot from zero to non-zero at the temporary storage |
| `TMPSTORE_RESET_GAS` | TBD | The gas cost of changing a non-zero slot to another value at the temporary storage |

### Temporary storage data model

Temporary storage is backed by **two reserved system accounts** at `TEMP_STORAGE_SYSTEM_ADDRESS_0` and `TEMP_STORAGE_SYSTEM_ADDRESS_1`.

The temporary storage keyspace is a mapping of `(contract_address, key) -&gt; value`, where:

```
derived_slot_key = keccak256(contract_address || key)
```

Temporary storage values are stored in the regular storage tries of the system accounts using `derived_slot_key` as the slot key.

### Periodic rollover (storage reset)

Temporary storage is organized into periods, each of length `TEMP_STORAGE_PERIOD` blocks after activation.

For blocks with `block.number &gt;= FORK_BLOCK`, define:

```
period_index(block_number) = floor((block_number - FORK_BLOCK) / TEMP_STORAGE_PERIOD)
```

Define the current and previous system accounts for a block `B` (where `B.number &gt;= FORK_BLOCK`) as:

```
current_index = period_index(B.number) % 2

if current_index == 0:
    CURRENT_SYSADDR = TEMP_STORAGE_SYSTEM_ADDRESS_0
    PREVIOUS_SYSADDR = TEMP_STORAGE_SYSTEM_ADDRESS_1
else if current_index == 1:
    CURRENT_SYSADDR = TEMP_STORAGE_SYSTEM_ADDRESS_1
    PREVIOUS_SYSADDR = TEMP_STORAGE_SYSTEM_ADDRESS_0
```

At the first block of each new period, the protocol MUST clear the storage of the system account that becomes the current.

When processing a block `B` (with parent `P`) where both are `&gt;= FORK_BLOCK`, if `period_index(B.number) &gt; period_index(P.number)`, then before executing transactions in `B`, the protocol MUST perform:

- `CURRENT_SYSADDR.storageRoot = EMPTY_TRIE_ROOT`

where `CURRENT_SYSADDR` is computed from `B.number` as specified above.

No other accounts are modified by the rollover.

**Effect:** After rollover, entries written in the immediately previous period remain readable via `PREVIOUS_SYSADDR` for one additional period, while entries older than one period are removed.

### New opcodes

Add 2 new opcodes as follows:

#### `TMPLOAD(key)`

Compute `derived_slot_key` from `(contract_address, key)`. Then load `derived_slot_key` from `CURRENT_SYSADDR` first. If it doesn&apos;t exist (i.e. `value == 0` ), then load `derived_slot_key` from `PREV_SYSADDR`.

#### `TMPSTORE(key,value)`  

Compute `derived_slot_key` from `(contract_address, key)`. Then:

- If `value != 0`, store in the storage of `CURRENT_SYSADDR`.
- If `value == 0`, delete slot from both `CURRENT_SYSADDR` and `PREV_SYSADDR`.

**Rationale:** Because reads fall back from current to previous, clearing only the current store would allow an older previous-period value to be returned. Clearing both ensures `TMPSTORE(key,0)` makes subsequent `TMPLOAD(key)` return `0` (until a new non-zero is written).

The call rules should follow `SSTORE` and `SLOAD`.

The gas rules should follow the conventions in [EIP-2929](/EIPs/EIPS/eip-2929) and [EIP-2200](/EIPs/EIPS/eip-2200) referencing `SSTORE` and `SLOAD`, except that:

- The gas costs should be much lower than `SSTORE` and `SLOAD`, but higher than `TSLOAD` and `TSTORE`
- No refunds are given for clearing temporary storage
- `TMPLOAD` MAY perform up to 2 storage reads (current then previous). Gas MUST account for this behaviour.
- Deletion in `TMPSTORE` is more expensive than creation/modification as the storage root of both system accounts are updated. Gas MUST account for this behaviour.

### Activation and reserved address

At `FORK_BLOCK`, the chain MUST treat `TEMP_STORAGE_SYSTEM_ADDRESS_0` and `TEMP_STORAGE_SYSTEM_ADDRESS_1` as reserved addresses:

- If either does not exist in the state trie, it is created with:
  - `nonce = 1`
  - `balance = 0`
  - `codeHash = EMPTY_CODE_HASH`
  - `storageRoot = EMPTY_TRIE_ROOT`

No contract code is deployed at this address.

## Rationale

### Why not just use transient storage (EIP-1153)?

[EIP-1153](/EIPs/EIPS/eip-1153) (transient storage) is discarded after every transaction, which is ideal for intra-tx operations. This EIP targets a different class of use cases where data must persist across multiple transactions/blocks, but does not need indefinite retention.

### Why two-period rollover?

Two-period rollover provides a stronger usability guarantee:

- An entry is retained for **at least** one full `TEMP_STORAGE_PERIOD` after it is written (it will be readable in the next period via the previous-period system account).
- An entry is retained for **at most** two periods (once the current-period system account is cleared and reused).

This provides a simple mental model for contract developers. That is, if an entry is stored in temporary storage, it will at least last for `TEMP_STORAGE_PERIOD`.

In contrast, a single global rollover makes effective lifetime depend on when data is written within the period: a write near the end of a period could be cleared almost immediately, which may not be developer-friendly.

### Why two system accounts?

Using two reserved system accounts allows constant-time rollover:

- At each period boundary, only the **current-period** system account is reset by setting a single `storageRoot = EMPTY_TRIE_ROOT`.
- The previous-period system account remains intact for one more period.
- Storage older than one period becomes unreachable and can be pruned.

## Backwards Compatibility

This EIP requires a hard fork to implement.

It does not change behavior of any existing opcodes. Therefore, it is backward compatible with all existing contract accounts.

## Security Considerations

- **DoS surface**: Temporary storage writes still create state that must be processed and stored for at least 1 period. Gas costs should be calibrated so that worst-case temp writes do not create new per-block disk I/O DoS attack vectors beyond existing storage writes.
- **Reorg safety**: Clients should retain sufficient history to handle plausible reorg depths.
- **Application safety**: Contracts MUST treat temp storage as ephemeral and handle the case where entries are unexpectedly missing.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 14 Jan 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8125</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8125</guid>
      </item>
    
      <item>
        <title>AI Agent Verification</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8126-ai-agent-verification/27445</comments>
        
        <description>## Abstract

This ERC defines a standard interface for verifying AI agents on Ethereum that have been registered via [ERC-8004](/EIPs/EIPS/eip-8004). It enables AI agents to undergo several specialized verification processes defined in this proposal: Ethereum Token Verification (ETV), Media Content Verification (MCV), Solidity Code Verification (SCV), Web Application Verification (WAV), and Wallet Verification (WV). Verification providers implement this standard using Private Data Verification (PDV) to generate Zero-Knowledge Proofs (ZKPs). Detailed verification results are accessible only to the AI agent’s wallet holder and include a unified risk score (0-100) to help users assess the agent’s trustworthiness. Verification attestations can additionally be posted to ERC-8004’s Validation Registry for ecosystem-wide discoverability.

## Motivation

As AI agents become increasingly prevalent in blockchain ecosystems, users need standardized ways to verify their authenticity and trustworthiness. Current solutions are fragmented, with no unified standard for agent registration or verification. This ERC addresses these challenges by providing:

1. **Multi-Layer Verification**: Five specialized verification types assess different aspects of agent security
2. **Privacy-First Architecture**: ZKPs ensure verification without exposing sensitive data
3. **Unified Risk Scoring**: A standardized 0-100 risk score enables easy comparison between agents
4. **Quantum-Resistant Future**: Optional Quantum Cryptography Verification (QCV) provides future-proof encryption
5. **Integration with ERC-8004**: Leverages portable [ERC-721](/EIPs/EIPS/eip-721) identities and pluggable validation/reputation registries for broader trust signals

| Term | Definition |
|------|------------|
| **Agent Wallet** | The Ethereum address designated as controlled by the AI agent |
| **AI Agent** | An autonomous software entity identified by an ERC-8004 Identity Registry token |
| **C2PA** | Coalition for Content Provenance and Authenticity - the standards body responsible for the open specification used to embed tamper-evident provenance and authenticity information in digital media |
| **ETV** | Ethereum Token Verification - validates smart contract presence and legitimacy |
| **MCV** | Media Content Verification - validates the authenticity, provenance, and integrity of digital media |
| **OWASP** | Open Worldwide Application Security Project - nonprofit organization providing security standards and testing guides for web and smart contract applications |
| **PDV** | Private Data Verification - generates ZKPs from verification results |
| **Proof ID** | A unique identifier for a ZKP generated during verification |
| **QCV** | Quantum Cryptography Verification - provides quantum-resistant encryption for sensitive data |
| **Risk Score** | A numerical value from 0-100 indicating the assessed risk level, where 0 is the lowest risk, and 100 is the highest risk |
| **SCV** | Solidity Code Verification - validates Solidity Code security |
| **Verification Provider** | A service implementing this standard&apos;s verification types (ETV, MCV, PDV, QCV, SCV, WAV, WV) |
| **WAV** | Web Application Verification - checks endpoint security and accessibility |
| **WV** | Wallet Verification - assesses wallet history and threat database status |
| **ZKP** | Zero-Knowledge Proof - cryptographic proof that verification occurred without revealing underlying data |

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

### Verification Flow

The following diagram illustrates the verification process:

![ERC-8126 AI Agent Verification - Verification Flow Diagram](/EIPs/assets/eip-8126/20260407-ERC_8126_Verification_Flow_Diagram-v0.1.svg)

### Verification Types

Verification requests MUST reference an ERC-8004 `agentId` (`uint256` token ID from the Identity Registry).  

The verification provider MUST call `tokenURI(agentId)` on the canonical Identity Registry contract and resolve the returned URI to fetch the agent registration JSON file. All metadata fields (`agentWallet`/`walletAddress`, `chain_id`, `contractAddress`, `endpoints`/`url`, `image`/`imageUrl`, `platform_id`, `solidityCode`, etc.) MUST be extracted from this JSON in accordance with the ERC-8004 registration schema.  

Direct submission of individual parameters (`agentWallet`/`walletAddress`, `chain_id`, `contractAddress`, `endpoints`/`url`, `image`/`imageUrl`, `platform_id`, `solidityCode`, etc.) without an `agentId` is NOT permitted.

Compliant verification providers MUST implement **all** of the following verification types and apply them using the resolved metadata:

#### Ethereum Token Verification (ETV)
Validates the legitimacy and security of the smart contract when a `contractAddress` is present in the resolved metadata.

- MUST verify that the `contractAddress` is a deployed smart contract on the resolved `chain_id` by calling `eth_getCode` and confirming the returned bytecode is not 0x
- MUST check contract against known vulnerability patterns
- MUST produce a risk score between 0 and 100
- SHOULD follow the Open Worldwide Application Security Project (OWASP) Smart Contract Security Verification Standard [(SCSVS) v0.0.1](/EIPs/assets/eip-8126/20241004-OWASP_Smart_Contract_Security_Verification_Standard-v0.0.1.pdf)

#### Media Content Verification (MCV)
Validates the authenticity, provenance, and integrity of the media content when `imageUrl` is present in the resolved metadata.

- SHOULD perform forensic analysis to detect indicators of AI-generated content, synthetic media, or deepfakes
- MUST verify content provenance and embedded metadata
- MUST check for signs of manipulation or tampering
- MUST validate any embedded digital watermarks, steganographic payloads, or signatures where present
- MUST return a risk score between 0 and 100
- SHOULD use established content authenticity frameworks such as the Coalition for Content Provenance and Authenticity [(C2PA) Implementation Guide v2.2](/EIPs/assets/eip-8126/20251211-CP2A_Implementation_Guide-v2.2.pdf)

#### Solidity Code Verification (SCV)
Validates the legitimacy and security of the solidity code when `solidityCode` is present in the resolved metadata.

- MUST verify that `solidityCode` is deployed on the resolved `chain_id` by calling `eth_getCode` and confirming the returned bytecode is not 0x
- MUST check for common `solidityCode` vulnerabilities (reentrancy, flash loan attacks)
- MUST produce a risk score between 0 and 100
- SHOULD follow the OWASP SCSVS

#### Web Application Verification (WAV)
Ensures the agent&apos;s web endpoint is accessible and secure using resolved metadata.

- MUST verify HTTPS endpoint responds (using resolved `url` or `endpoints` array)
- MUST check for common security vulnerabilities
- MUST verify SSL certificate validity
- MUST produce a risk score between 0 and 100
- SHOULD follow the OWASP Web Security Testing Guide [(WSTG) v4.2](/EIPs/assets/eip-8126/20201203-OWASP_Web_Security_Testing_Guide-v4.2.pdf)

#### Wallet Verification (WV)
Confirms wallet ownership and assesses on-chain risk profile using resolved metadata.

- MUST verify wallet has transaction history (using resolved `walletAddress`/`agentWallet`)
- MUST check against threat intelligence databases
- MUST produce a risk score between 0 and 100

### Integration with ERC-8004

Verification providers MAY post final risk scores and Proof IDs as attestations to the ERC-8004 Validation Registry using its pluggable validation interface. This enables portable, discoverable security attestations alongside reputation signals.

### Off-chain Verification

Verification is performed off-chain to:

1. Eliminate gas costs for verification operations
2. Enable complex verification logic that would be prohibitively expensive on-chain
3. Allow verification criteria to evolve without requiring contract upgrades
4. Enable multiple competing verification providers

### Payment Protocol

Verification providers MAY charge fees for verification services. When fees are required:

- SHOULD support stablecoin settlement (e.g., USDC)
- MUST clearly disclose fee structure before verification
- SHOULD use [EIP-3009](/EIPs/EIPS/eip-3009) `TransferWithAuthorization` for gasless payments

### Risk Scoring

The overall risk score MUST be calculated as the mean of all applicable verification scores:

| Tier | Score Range | Description |
|------|-------------|-------------|
| Low Risk | 0-20 | Minimal concerns identified |
| Moderate | 21-40 | Some concerns, review recommended |
| Elevated | 41-60 | Notable concerns, caution advised |
| High Risk | 61-80 | Significant concerns detected |
| Critical | 81-100 | Severe concerns, avoid interaction |

### Error Codes

Implementations MUST use the following standardized error codes:

| Error Code | Name | Description |
|------------|------|-------------|
| `0x01`     | `InvalidAddress`      | Provided address is not a valid Ethereum address |
| `0x02`     | `InvalidURL`          | Provided URL is malformed or not HTTPS           |
| `0x03`     | `AgentNotFound`       | No agent exists with the specified agentId       |
| `0x04`     | `VerificationFailed`  | Verification provider returned an error          |
| `0x05`     | `InsufficientCredits` | No verification credits available                |
| `0x06`     | `InvalidProof`        | PDV proof validation failed                      |
| `0x07`     | `ProviderUnavailable` | Verification provider is not responding          |
| `0x08`     | `InvalidScore`        | Risk score outside valid range (0-100)           |
| `0x09`     | `ContractNotFound`    | Specified contract does not exist on chain       |
| `0x0A`     | `SolidityCodeNotFound` | Specified Solidity Code does not exist    |
| `0x0B`     | `ImageNotFound`        | Image could not be resolved or fetched from agent registration metadata    |
| `0x0C`     | `SteganographyFailed` | Steganographic payload extraction failed (technical error)    |
| `0x0D`     | `MediaVerificationFailed` | General failure in media integrity or provenance verification    |

Implementations SHOULD revert with these error codes:

         error InvalidAddress();
         error InvalidURL();
         error AgentNotFound();
         error VerificationFailed();
         error InsufficientCredits();
         error InvalidProof();
         error ProviderUnavailable();
         error InvalidScore();
         error ContractNotFound();
         error SolidityCodeNotFound();
         error ImageNotFound();
         error SteganographyFailed();
         error MediaVerificationFailed();

### Interface

This ERC is primarily an **off-chain standard** for verification providers. No on-chain smart contract interface is required to submit verification requests or perform the verification types (ETV, MCV, SCV, WAV, WV, PDV, QCV).

Optional on-chain components MAY be implemented by providers or integrators to:

- Record final risk scores or attestations on-chain
- Emit verification events
- Allow querying of recent results

If an on-chain component is deployed, it SHOULD include at minimum:

         ```solidity
         // SPDX-License-Identifier: CC0-1.0
         pragma solidity ^0.8.0;
         
         interface IERC8126 {
             /// @notice Emitted when an agent is verified
             event AgentVerified(
                 uint256 indexed agentId,          // Token ID (ERC-721) from ERC-8004 Identity Registry
                 uint8 overallRiskScore,
                 bytes32 etvProofId,
                 bytes32 mcvProofId,
                 bytes32 scvProofId,
                 bytes32 wavProofId,
                 bytes32 wvProofId,
                 bytes32 summaryProofId
             );
         
             /// @notice Emitted when an attestation is posted to the ERC-8004 Validation Registry
             event AttestationPosted(
                 uint256 indexed agentId,
                 uint8 riskScore,
                 bytes32 proofId
             );
         
             /// @notice Optional: Query the latest risk score for an agentId
             /// @dev MAY revert if no verification exists
             function getLatestRiskScore(uint256 agentId) external view returns (uint8);
         }

## Rationale

### Required Standards Justification

**[EIP-155](/EIPs/EIPS/eip-155) (Replay Protection)**: Verification requests involve signed messages from agent owners to authorize providers or payments. Without chain ID inclusion EIP-155, a signed request on mainnet could be replayed on testnets or L2s, potentially triggering unwanted verifications or duplicate payments across chains.

**[EIP-191](/EIPs/EIPS/eip-191) (Signed Data Standard)**: Wallet verification and request authorization require proving control over the agent wallet. EIP-191 provides a standardised prefix for signed messages, ensuring compatibility across wallets and preventing signature malleability during verification.

**[EIP-712](/EIPs/EIPS/eip-712) (Typed Data Signing)**: Verification requests use structured data (agentId, metadata hashes, nonce, payment details). EIP-712 enables human-readable signing prompts (e.g., &quot;Authorize Verification for Agent ID: 1234 on chain 1&quot;) instead of blind hashes, reducing phishing risks and improving UX for agent owners.

**[ERC-3009](/EIPs/EIPS/eip-3009) (Transfer With Authorization)**: Verification fees are paid via ERC-3009, which enables gasless USDC transfers, with the provider covering gas costs, making verification accessible without requiring users to hold ETH.

**ERC-8004 (Trustless Agents Registry)**: Builds on the canonical [ERC-721](/EIPs/EIPS/eip-721) Non-Fungible Token Standard (with `ERC721URIStorage`) for the Identity Registry, where agents are minted as unique NFTs for portable, censorship-resistant identities. [ERC-8004](/EIPs/EIPS/eip-8004) defines `agentId` (as ERC-721 `tokenId`), `tokenURI&apos;-based metadata resolution (e.g., `name`, `walletAddress`, `endpoints`, `contractAddress` in JSON), optional on-chain metadata, and posting to the Validation Registry for composable trust signals (reputation, proofs, validations) after verification flows complete.

### Five Verification Types

The five verification types are presented in alphabetical order (ETV → MCV → SCV → WAV → WV) for clarity and consistency.

The decision to implement five distinct verification types addresses different aspects of agent authenticity:

- **ETV** validates on-chain presence and contract legitimacy, ensuring the agent has a legitimate blockchain footprint
- **MCV** validates authenticity and integrity of the agent&apos;s `imageUrl` using C2PA/ provenance frameworks and media tamper detection
- **SCV** validates Solidity Code security, ensuring agents with staking mechanisms have secure and auditable contracts
- **WAV** ensures the agent&apos;s web endpoint is accessible and secure, protecting users from phishing and vulnerable endpoints
- **WV** confirms wallet legitimacy and checks against threat databases, preventing association with known malicious actors

### Risk Scoring Approach

A unified 0-100 risk scoring system allows:

- Easy comparison between agents
- Clear risk tier categorisation
- Weighted average calculation for overall assessment
- Actionable guidance based on score ranges
- Chosen over 0-10 or 0-255 for the best balance of granularity and interpretability.

### Provider Agnostic Design

This standard intentionally separates the interface specification from implementation details. Any verification provider may implement compliant ETV, MCV, SCV, WAV, WV, PDV and QCV services, enabling:

1. Competition among verification providers
2. Specialization in different verification domains
3. Geographic and jurisdictional flexibility
4. Price competition benefiting users

### Privacy-First Architecture with PDV

Verification results are processed through PDV, which generates ZKPs. This privacy-first approach:

1. Eliminates data breach risks - no stored data means nothing to compromise
2. Provides cryptographic proof of verification that third parties can validate
3. Ensures GDPR and privacy regulation compliance
4. Builds user trust through transparent, verifiable data handling

### Quantum-Resistant Future with QCV

Verification providers may implement QCV to quantum-resistant encrypt sensitive verification data.

- Uses AES-256-GCM or equivalent post-quantum encryption algorithm
- Returns unique `record_id` for encrypted data
- Provides `decryption_url` for authorized data retrieval
- Ensures quantum-resistant key exchange mechanisms

QCV Key Properties:
- Provides future-proof protection against quantum computing threats
- Military-grade encryption standards (AES-256-GCM)
- Enables secure long-term storage of verification records

## Backwards Compatibility

This ERC introduces a new standard focused on verification and does not modify any existing standards. It requires agents to be registered via ERC-8004, which provides portable ERC-721-based identities and metadata resolution.

Pre-existing implementations that relied on the original custom registration logic in this ERC would need to migrate by:

- Minting agents in the ERC-8004 Identity Registry
- Setting the `tokenURI` to a compatible metadata JSON file containing `name`, `description`, `walletAddress`, `url`, `contractAddress`, `solidityCode`, etc.

Existing AI agents already registered via ERC-8004 can undergo verification without changes. The standard is designed to work alongside existing token standards ([ERC-20](/EIPs/EIPS/eip-20), [ERC-721](/EIPs/EIPS/eip-721), [ERC-1155](/EIPs/EIPS/eip-1155)) and identity standards.

## Test Cases

### Verification Tests

#### ETV Completes with `contractAddress`
Ensures ETV succeeds when metadata includes `contractAddress`.
```solidity
function testETVCompletesWhenContractAddressPresent() public {
    uint256 agentId = 1;
    vm.prank(user);
    // bytes32 proofId = verifier.verifyETV(agentId);
}
```

#### MCV Completes with `imageUrl`
Ensures SCV succeeds when `imageUrl` is present.
```solidity
function testMCVCompletesWhenimageUrlPresent() public {
    uint256 agentId = 42;
    vm.prank(user);
    // verifier.verifyMCV(agentId);
}
```

#### SCV Completes with `solidityCode`
Ensures SCV succeeds when `solidityCode` is present.
```solidity
function testSCVCompletesWhensolidityCodePresent() public {
    uint256 agentId = 42;
    vm.prank(user);
    // verifier.verifySCV(agentId);
}
```

#### WAV Completes for All `agentId`s
Verifies WAV executes correctly for a range of `agentId`s.
```solidity
function testWAVCompletesForAllAgentIds() public {
    uint256;
    ids[0] = 10; ids[1] = 20; ids[2] = 30;

    for (uint i = 0; i &lt; ids.length; i++) {
        vm.prank(user);
        // verifier.verifyWAV(ids[i]);
    }
}
```

#### WV Completes for All `agentId`s
Checks WV runs successfully across multiple `agentId`s.
```solidity
function testWVCompletesForAllAgentIds() public {
    uint256;
    ids[0] = 10; ids[1] = 20; ids[2] = 30;

    for (uint i = 0; i &lt; ids.length; i++) {
        vm.prank(user);
        // verifier.verifyWV(ids[i]);
    }
}
```

#### Generates PDV ZKPs
Confirms all proof types are generated for an `agentId`.
```solidity
function testGeneratesPDVZKPForEachType() public {
    uint256 agentId = 100;
    vm.prank(user);
    // verifier.verifyAgent(agentId);
}
```

#### Calculates `overallRiskScore`
Validates the mean `overallRiskScore` calculation.
```solidity
function testCalculatesOverallRiskScore() public {
    uint8 score = verifier.calculateRiskScore(10, 20, 30, 40);
    assertEq(score, 25);
}
```

#### Emits `AgentVerified` Event
Checks event emission with proof IDs.
```solidity
function testEmitsAgentVerifiedEvent() public {
    uint256 agentId = 999;
    vm.expectEmit(true, true, true, true);
    emit AgentVerified(agentId, 45, [bytes32(1), bytes32(2), bytes32(3), bytes32(4)]);
}
```

#### Reverts with `VerificationFailed`
Ensures provider failure triggers `VerificationFailed`.
```solidity
function testRevertsWithVerificationFailed() public {
    vm.expectRevert(VerificationFailed.selector);
}
```

#### Reverts with `InsufficientCredits`
Checks users without credits are blocked via `InsufficientCredits`.
```solidity
function testRevertsWithInsufficientCredits() public {
    vm.prank(poorUser);
    vm.expectRevert(InsufficientCredits.selector);
}
```

### Access Control

#### Unauthorized Proof Access
Prevents non-owners from accessing `proofs`.
```solidity
function testUnauthorizedProofAccess() public {
    vm.prank(0xBBBB);
    vm.expectRevert(UnauthorizedAccess.selector);
    registry.getAgentProofs(1234);
}
```

### Risk Score

#### Risk Tier Classification
Ensures scores map correctly to `RiskTier`.
```solidity
function testRiskScoreTiers() public {
    assertEq(verifier.getRiskTier(15), RiskTier.Low);
    assertEq(verifier.getRiskTier(35), RiskTier.Moderate);
}
```

## Reference Implementation

```ts
import crypto from &apos;crypto&apos;;
import { createPublicClient, http, getAddress, parseAbi } from &apos;viem&apos;;

class ERC8126Error extends Error {
  constructor(
    public code: number,
    message: string
  ) {
    super(message);
    this.name = &apos;ERC8126Error&apos;;
  }
}

enum VerificationStatus {
  Passed = &apos;passed&apos;,
  Failed = &apos;failed&apos;,
  Inconclusive = &apos;inconclusive&apos;,
}

enum RiskTier {
  Low = &apos;low&apos;,
  Moderate = &apos;moderate&apos;,
  Elevated = &apos;elevated&apos;,
  HighRisk = &apos;high&apos;,
  Critical = &apos;critical&apos;,
}

interface AgentMetadata {
  contractAddress?: string;
  solidityCode?: string;
  url?: string;
  walletAddress?: string;
  chain_id?: number;
  [key: string]: any;
}

interface VerificationProviderConfig {
  chainId?: number;
  identityRegistry?: string;
  validationRegistry?: string;
  rpcUrl?: string;
}

interface VerificationResult {
  type: string;
  status: VerificationStatus;
  score: number;
  proofId: string;
}

const ERC8004_ABI = parseAbi([
  &apos;function tokenURI(uint256 tokenId) external view returns (string)&apos;,
]);

async function resolveAgentMetadata(
  agentId: bigint,
  config: VerificationProviderConfig
): Promise&lt;AgentMetadata&gt; {
  if (!config.identityRegistry) {
    throw new ERC8126Error(0x03, &apos;ERC-8004 Identity Registry address is required&apos;);
  }
  if (!config.rpcUrl) {
    throw new ERC8126Error(0x04, &apos;RPC URL is required to resolve ERC-8004 metadata&apos;);
  }

  const client = createPublicClient({
    chain: { id: config.chainId || 1, name: &apos;Ethereum&apos;, nativeCurrency: { name: &apos;ETH&apos;, symbol: &apos;ETH&apos;, decimals: 18 } },
    transport: http(config.rpcUrl),
  });

  try {
    const uri = await client.readContract({
      address: getAddress(config.identityRegistry),
      abi: ERC8004_ABI,
      functionName: &apos;tokenURI&apos;,
      args: [agentId],
    });

    if (!uri || typeof uri !== &apos;string&apos;) {
      throw new ERC8126Error(0x05, &apos;Invalid tokenURI returned from ERC-8004 registry&apos;);
    }

    const response = await fetch(uri);
    if (!response.ok) {
      throw new ERC8126Error(0x06, `Failed to fetch metadata from ${uri}`);
    }

    const metadata: AgentMetadata = await response.json();

    return {
      contractAddress: metadata.contractAddress ? getAddress(metadata.contractAddress) : undefined,
      imageUrl: metadata.imageUrl ? getAddress(metadata.imageUrl) : undefined,
      solidityCode: metadata.solidityCode ? getAddress(metadata.solidityCode) : undefined,
      walletAddress: metadata.walletAddress ? getAddress(metadata.walletAddress) : undefined,
      url: metadata.url,
      chain_id: metadata.chain_id,
      ...metadata,
    };
  } catch (error) {
    if (error instanceof ERC8126Error) throw error;
    throw new ERC8126Error(0x07, `Metadata resolution failed: ${error instanceof Error ? error.message : &apos;Unknown error&apos;}`);
  }
}

async function ETV(m: AgentMetadata, c: VerificationProviderConfig): Promise&lt;VerificationResult&gt; {
  return {
    type: &apos;ETV&apos;,
    status: VerificationStatus.Passed,
    score: 25,
    proofId: generateProofId(&apos;ETV&apos;, m.contractAddress || &apos;&apos;),
  };
}

async function MCV(m: AgentMetadata, c: VerificationProviderConfig): Promise&lt;VerificationResult&gt; {
  return {
    type: &apos;MCV&apos;,
    status: VerificationStatus.Passed,
    score: 30,
    proofId: generateProofId(&apos;MCV&apos;, m.imageUrl || &apos;&apos;),
  };
}

async function SCV(m: AgentMetadata, c: VerificationProviderConfig): Promise&lt;VerificationResult&gt; {
  return {
    type: &apos;SCV&apos;,
    status: VerificationStatus.Passed,
    score: 30,
    proofId: generateProofId(&apos;SCV&apos;, m.solidityCode || &apos;&apos;),
  };
}

async function WAV(m: AgentMetadata): Promise&lt;VerificationResult&gt; {
  return {
    type: &apos;WAV&apos;,
    status: VerificationStatus.Passed,
    score: 15,
    proofId: generateProofId(&apos;WAV&apos;, m.url || &apos;&apos;),
  };
}

async function WV(m: AgentMetadata): Promise&lt;VerificationResult&gt; {
  return {
    type: &apos;WV&apos;,
    status: VerificationStatus.Passed,
    score: 20,
    proofId: generateProofId(&apos;WV&apos;, m.walletAddress || &apos;&apos;),
  };
}

function calculateOverallRiskScore(scores: number[]): number {
  const valid = scores.filter((s) =&gt; s &gt;= 0 &amp;&amp; s &lt;= 100);
  return valid.length ? Math.round(valid.reduce((a, b) =&gt; a + b, 0) / valid.length) : 0;
}

function getRiskTier(score: number): RiskTier {
  if (score &lt;= 20) return RiskTier.Low;
  if (score &lt;= 40) return RiskTier.Moderate;
  if (score &lt;= 60) return RiskTier.Elevated;
  if (score &lt;= 80) return RiskTier.HighRisk;
  return RiskTier.Critical;
}

function generatePDVProof(result: any): string {
  return &apos;0x&apos; + crypto.createHash(&apos;sha256&apos;).update(JSON.stringify(result) + Date.now().toString()).digest(&apos;hex&apos;);
}

async function QCV(data: any) {
  return {
    recordId: &apos;0x&apos; + crypto.createHash(&apos;sha256&apos;).update(Date.now().toString()).digest(&apos;hex&apos;),
    algorithm: &apos;AES-256-GCM&apos;,
  };
}

export async function verifyAgent(agentId: bigint, config: VerificationProviderConfig) {
  const metadata = await resolveAgentMetadata(agentId, config);

  const [etv, mcv, scv, wav, wv] = await Promise.all([
    ETV(metadata, config),
    MCV(metadata, config),
    SCV(metadata, config),
    WAV(metadata),
    WV(metadata),
  ]);

  const overallRiskScore = calculateOverallRiskScore([etv.score, mcv.score, scv.score, wav.score, wv.score]);
  const riskTier = getRiskTier(overallRiskScore);
  const pdvProofId = generatePDVProof({ etv, mcv, scv, wav, wv, overallRiskScore, agentId: agentId.toString() });

  const qcvRecord = await QCV({ overallRiskScore, pdvProofId });

  const validationRecord = config.validationRegistry
    ? await submitToValidationRegistry(agentId, overallRiskScore, pdvProofId, config)
    : null;

  return {
    agentId,
    overallRiskScore,
    riskTier,
    etv,
    mcv,
    scv,
    wav,
    wv,
    pdvProofId,
    qcvRecord,
    validationRecord,
    verifiedAt: new Date().toISOString(),
  };
}

async function submitToValidationRegistry(
  agentId: bigint,
  score: number,
  pdvProofId: string,
  config: VerificationProviderConfig
) {
  return pdvProofId;
}

function generateProofId(type: string, data: string): string {
  const input = `${type}:${data}:${Date.now()}`;
  return &apos;0x&apos; + crypto.createHash(&apos;sha256&apos;).update(input).digest(&apos;hex&apos;);
}

export { verifyAgent };
```

## Security Considerations

### Verification Trust

Users should consider that verification through this standard indicates the agent has passed specific technical checks at a point in time, but does not guarantee the agent&apos;s future behavior or intentions. Risk scores provide guidance, but users should exercise their own judgment.

### Wallet Security

Agents must ensure that their registered wallet addresses are secure. Compromise of a wallet could allow an attacker to impersonate a legitimate agent. Re-verification is available to update risk scores.

### URL Hijacking

If an agent&apos;s URL is compromised after registration, the attacker could serve malicious content. Users should consider verifying agents&apos; current status before interacting with them. WAV re-verification can detect compromised endpoints.

### Smart Contract Risks

For agents with registered contract addresses, standard smart contract security considerations apply. ETV and SCV provide initial verification, but users should consider auditing any contracts they interact with.

### ZKP Security

PDV implementations SHOULD use established ZKP systems with proven security properties:

- **Circuit Soundness**: Implementations should use audited circuits (e.g., Groth16) with formal security proofs
- **Trusted Setup**: Systems requiring trusted setup (e.g., Groth16) must use multi-party computation ceremonies to minimize trust assumptions
- **Proof Verification**: On-chain proof verification must use battle-tested verifier contracts
- **Quantum Considerations**: Current ZKP systems (based on elliptic curves) may be vulnerable to future quantum attacks. High-value, long-term proofs should consider QCV encryption as an additional layer

### Quantum Computing Threats

Current cryptographic primitives face potential threats from quantum computing:

- **ECDSA Signatures**: Vulnerable to Shor&apos;s algorithm on sufficiently powerful quantum computers
- **ZKP Schemes**: Elliptic curve-based ZKPs (Groth16) share quantum vulnerability
- **Mitigation**: QCV provides AES-256-GCM encryption, which remains quantum-resistant for symmetric operations. Implementations concerned with long-term security should use QCV for sensitive verification data

### Provider Trust

Users must evaluate their trust in the verification providers they choose. Different providers may have varying levels of thoroughness, independence, and reliability. ZKPs generated by PDV provide verifiable evidence of verification completion that can be independently validated.

### Attack Vectors

- **Sybil Attacks**: Malicious actors could create many agents in ERC-8004. Mitigated by minting costs and reputation systems.
- **Provider Collusion**: Verification providers could collude with malicious agents. Users should consider using multiple independent providers for high-stakes interactions.

### Dependency on ERC-8004

Reliance on ERC-8004 registries introduces a dependency risk; implementations must use the canonical deployed addresses and verify the integrity of `tokenURI`s.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 15 Jan 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8126</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8126</guid>
      </item>
    
      <item>
        <title>Human Readable Token Identifiers</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8127-human-readable-token-identifiers/27449</comments>
        
        <description>## Abstract

This ERC defines a format for identifying tokens in onchain registries using optional human readable aliases. A Token Identifier combines an optional human readable alias, a unique token ID from an onchain registry, and the registry location encoded as an [ERC-7930](/EIPs/EIPS/eip-7930) interoperable address. This format is useful for NFTs, real-world assets (RWAs), agents, and other tokenized assets. For example, agent registries like [ERC-8004](/EIPs/EIPS/eip-8004) can use this format to identify agents with human readable names.

## Motivation

As tokenized assets become more prevalent in blockchain ecosystems, including NFTs, RWAs, and autonomous agents, there is a need for a consistent way to identify and reference them. Currently no format exists for identifying tokens with optional human readable aliases across different registries. Systems need to support multiple tokens with human readable aliases, while at the same time providing globally unique identifiers tied to onchain registration. This ERC addresses these needs by combining optional human readable aliases with onchain token IDs and registry locations in a single, parseable format. For example, agent registries like [ERC-8004](/EIPs/EIPS/eip-8004) can use this format to provide human readable names for agents while maintaining globally unique identifiers.


## Specification

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

### Token Identifier Format

A Token Identifier is a string with the following structure:

```
token-identifier = [&lt;alias&gt;.]&lt;token-id&gt;@&lt;registry&gt;
```

The `&lt;token-id&gt;` and `&lt;registry&gt;` components are REQUIRED for a fully specified identifier. The `&lt;alias&gt;` is an optional human readable identifier for the token, treated as case-insensitive. The alias SHOULD be included to improve usability. When present, the alias must be a valid label, which means:
- Must use only lowercase letters (a-z), digits (0-9), and hyphens (-)
- Must not start or end with a hyphen

Aliases may be duplicated across different tokens since uniqueness comes from the token ID. The entire Token Identifier must form a valid URI when combined with the token ID and registry components.

The alias MAY be taken from metadata fields in the registry. For example, agent registries like [ERC-8004](/EIPs/EIPS/eip-8004) may provide a &quot;name&quot; field that can be used as the alias. Since the alias is not needed to identify the token, it can also be self-assigned by clients.

The `token-id` is the numeric token ID from the onchain registry, such as an [ERC-721](/EIPs/EIPS/eip-721) or [ERC-6909](/EIPs/EIPS/eip-6909) token. It is the primary identifier for the token and MUST be a non-negative integer corresponding to a valid token in the specified registry, represented as a decimal string.

The `registry` is an [ERC-7930](/EIPs/EIPS/eip-7930) interoperable address of the token registry contract, which includes both the chain ID and contract address. The registry MUST be represented as a hexadecimal string in lowercase (e.g., `0x00010000010114d8da6bf26964af9d7eed9e03e53415d37aa96045`).

This format is especially useful for multi token registries such as [ERC-1155](/EIPs/EIPS/eip-1155) and [ERC-6909](/EIPs/EIPS/eip-6909), where a single registry contract issues many token IDs and clients can present per token aliases (e.g., `neo.145@...`) for usability.

### Resolution Rules

Systems can use various methods to make it easier for human users to specify a token. With a list of tokens that have unique aliases, the alias alone may be sufficient. As the number of tokens grows, systems may require both the alias and token ID to uniquely identify a token. When tokens exist across multiple registries, the full identifier including the registry address provides complete specification of a unique token. The token ID alone with the registry address is sufficient to uniquely identify a token.

**Examples (using agents and RWAs):**
- `webdev` - Alias only, sufficient when the alias is unique
- `punk.2344` - Alias with token ID
- `agent.235234` - Alias with token ID
- `neo.145@0x00010000010114d8da6bf26964af9d7eed9e03e53415d37aa96045` - Multi token registry style alias and token ID with registry
- `silver-bullion-bar.58348729@0x00010000010114d8da6bf26964af9d7eed9e03e53415d37aa96045` - RWA style alias and token ID with registry
- `coder.35523423` - Alias with specific token ID
- `35523423@0x00010000010114d8da6bf26964af9d7eed9e03e53415d37aa96045` - Token ID with registry (no alias)


### Canonical Form

The canonical form of a Token Identifier is `[&lt;alias&gt;.]&lt;token-id&gt;@&lt;registry&gt;` with `token-id` and `registry` always present and alias present when available, and lowercase. Implementations should use canonical form for display and transmission.

**Examples (using agents):**
- `webdev.42@0x00010000010114d8da6bf26964af9d7eed9e03e53415d37aa96045` (with alias)
- `42@0x00010000010114d8da6bf26964af9d7eed9e03e53415d37aa96045` (without alias)

## Rationale

The Token Identifier format combines several design elements to balance usability, uniqueness, and interoperability. Each component serves a specific purpose in creating a format that is partly human readable (alias and token ID) and partly opaque (registry), while remaining machine parseable and supporting the diverse needs of token registry systems including NFTs, RWAs, and agent registries.

### Comparison with [CAIP-19](https://github.com/ChainAgnostic/CAIPs/blob/ff573534d413153f8cbab0be94eddeca566d0792/CAIPs/caip-19.md)

This format intentionally separates the identifier into two parts: a fully human readable portion (`&lt;alias&gt;.&lt;token-id&gt;`) and an opaque location portion (`@&lt;registry&gt;`). In many registries (including typical NFT, RWA, and agent registries), token IDs are simple decimal numbers rather than hashes, so both the alias and token ID can remain fully human readable (e.g., `punk.2344`, `agent.235234`, `silver-bullion-bar.58348729`).

By contrast, CAIP-19 style asset identifiers combine chain and contract information into an opaque prefix, and place the asset ID at the end. For example, a CryptoKitties token might be described as:

- `eip155:1/erc721:0x06012c8cf97bead5deae237070f9587f8e7a266d/771769`

In this structure, the information a user may care about most (the asset ID) is pushed to the end of a mostly opaque locator string. This ERC keeps the alias and token ID upfront, and moves the chain and contract addressing details into the `registry` component (an [ERC-7930](/EIPs/EIPS/eip-7930) interoperable address), making identifiers easier to read, speak, and copy while still remaining globally unique when combined with the registry. In RWA systems, the `registry` portion can be validated against a known list of RWA registries, while the alias and token ID (e.g., `silver-bullion-bar.58348729`) can remain something an owner is expected to recognize and care about.

### Why Include Alias?

Including an optional human readable alias alongside the token ID improves usability. While the token ID provides uniqueness and is the primary identifier, aliases provide meaning and make tokens easier to reference. For example, agent registries can use aliases to provide human readable names for agents.

Aliases are also portable: one system can share its alias for an asset with another system as a semantic hint about the asset, which can be used in useful semantic ways (e.g., `support-agent.3453`).

### Why ERC-7930 for Registry?

[ERC-7930](/EIPs/EIPS/eip-7930) provides chain-agnostic address encoding with future compatibility for non-EVM chains. It is a self-describing format that includes the chain ID, allowing a single field instead of separate chain ID and address fields.

### Why @ for Registry Separator?

The `@` symbol semantically means &quot;at&quot; (token at registry), is familiar from email addresses, is valid in URLs, and clearly separates the token identifier from the location.

## Backwards Compatibility

This ERC is backward compatible with systems using alias-only token identification. An identifier with just an alias and no `.` or `@` matches tokens by alias. Implementations should warn when alias-only matches are ambiguous. Existing systems can gradually adopt full identifiers with token IDs and registry addresses.

## Security Considerations

- **Misleading aliases**: Aliases are for human readability only and do not provide any security guarantee. Implementations MUST NOT rely on the alias for authentication or authorization, and SHOULD surface the full `&lt;token-id&gt;@&lt;registry&gt;` when making security-relevant decisions.
- **Registry trust**: The `registry` component is an [ERC-7930](/EIPs/EIPS/eip-7930) interoperable address and may point to any contract. Clients SHOULD validate the registry against an allowlist or other trust mechanism before treating an identifier as trusted.
- **Parsing and normalization**: Implementations MUST parse identifiers according to this ERC (splitting on `.` and `@` only where specified) and treat aliases as case-insensitive. Incorrect parsing or normalization could cause identifiers to resolve to the wrong token.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 14 Jan 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8127</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8127</guid>
      </item>
    
      <item>
        <title>Account Abstraction by Account Configuration</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8130-account-abstraction-by-account-configurations/25952</comments>
        
        <description>## Abstract

This proposal introduces a new [EIP-2718](/EIPs/EIPS/eip-2718) transaction type and an onchain Account Configuration system that together provide account abstraction — custom authentication, call batching, and gas sponsorship. Accounts register owners with onchain verifier contracts. Transactions declare which verifier to use, enabling nodes to filter transactions without executing wallet code. No EVM changes are required. The contract infrastructure is designed to be shared across chains as a common base layer for account management.

## Motivation

Account abstraction proposals that delegate validation to wallet code force nodes to simulate arbitrary EVM before accepting a transaction. This requires full state access, tracing infrastructure, and reputation systems to bound the cost of invalid submissions.

This proposal separates verification from account logic. Each transaction explicitly declares its verifier — a contract that takes a hash and signature data and returns the authenticated owner. This makes validation predictable: wallets know the rules, and nodes can see exactly what computation a transaction requires before executing it. Nodes may optionally filter on verifier identity, accepting only known verifiers (ECDSA, P256, WebAuthn, multisig, post-quantum) and rejecting the rest without execution.

New signature algorithms deploy as verifier contracts and are adopted by nodes independently with no protocol upgrade required.

## Specification

### Constants

| Name | Value | Comment |
|------|-------|---------|
| `AA_TX_TYPE` | TBD &lt;!-- TODO --&gt; | [EIP-2718](/EIPs/EIPS/eip-2718) transaction type |
| `AA_PAYER_TYPE` | TBD &lt;!-- TODO --&gt; | Magic byte for payer signature domain separation |
| `AA_BASE_COST` | 15000 | Base intrinsic gas cost |
| `ACCOUNT_CONFIG_ADDRESS` | TBD &lt;!-- TODO --&gt; | Account Configuration system contract address |
| `ECRECOVER_VERIFIER` | `address(1)` | Native secp256k1 (ECDSA) verifier for explicit k1 key registration |
| `REVOKED_VERIFIER` | `type(uint160).max` | Revocation marker written to implicit EOA owner slot to block re-authorization |
| `NONCE_MANAGER_ADDRESS` | TBD &lt;!-- TODO --&gt; | Nonce Manager precompile address |
| `TX_CONTEXT_ADDRESS` | TBD &lt;!-- TODO --&gt; | Transaction Context precompile address |
| `DEFAULT_ACCOUNT_ADDRESS` | TBD &lt;!-- TODO --&gt; | Default wallet implementation for auto-delegation |
| `DEPLOYMENT_HEADER_SIZE` | 14 | Size of the deployment header in bytes |
| `NONCE_KEY_MAX` | `2^256 - 1` | Nonce-free mode (expiry-only replay protection) |

### Account Configuration

Each account can authorize a set of owners through the Account Configuration Contract at `ACCOUNT_CONFIG_ADDRESS`. This contract handles owner authorization, account creation, change sequencing, and delegates signature verification to onchain [Verifiers](#verifiers).

Owners are identified by their `ownerId`, a 32-byte identifier derived by the verifier from public key material. The protocol does not enforce a derivation algorithm — each verifier defines its own convention (see [ownerId Conventions](#ownerid-conventions)). Owners can be modified via calls within EVM execution by calling the authenticated config change functions.

**Default behavior**: The EOA owner is implicitly authorized by default but can be revoked on the contract.

#### Storage Layout

Each owner occupies a single `owner_config` slot containing the verifier address (20 bytes) and a scope byte (1 byte) with 11 bytes reserved. The scope byte controls which authentication contexts the owner is valid for (see [Owner Scope](#owner-scope)). Non-EOA owners are revoked by deleting the `owner_config` slot. The implicit EOA owner (`ownerId == bytes32(bytes20(account))`) is revoked by overwriting the slot with `verifier = REVOKED_VERIFIER` (`type(uint160).max`), making it distinguishable from an empty (implicitly authorized) slot.

| Field | Bytes | Description |
|-------|-------|-------------|
| `verifier` | 0–19 | Verifier contract address |
| `scope` | 20 | Permission bitmask (`0x00` = unrestricted) |
| reserved | 21–31 | Reserved for future use (must be zero) |

**Implicit EOA authorization**: An unregistered owner (`owner_config` slot is empty) is implicitly authorized if `ownerId == bytes32(bytes20(account))`. The empty slot&apos;s scope byte is `0x00` (unrestricted), granting full permissions by default. This allows every existing EOA to send AA transactions immediately without prior registration. When the implicit rule applies, the protocol verifies using native ecrecover rather than calling an external verifier contract. The implicit authorization is revoked by writing `REVOKED_VERIFIER` (`type(uint160).max`) to the verifier field, making the slot non-empty and blocking re-authorization. The EOA owner can also be explicitly registered with `ECRECOVER_VERIFIER` (`address(1)`) to set a custom scope while retaining native ecrecover verification.

#### Owner Scope

The scope byte in `owner_config` is a permission bitmask that restricts which authentication contexts an owner can be used in. A value of `0x00` means unrestricted — the owner is valid in all contexts. Any non-zero value restricts the owner to contexts where the corresponding bit is set.

| Bit | Value | Name | Context |
|-----|-------|------|---------|
| 0 | `0x01` | SIGNATURE | ERC-1271 via `verifySignature()` |
| 1 | `0x02` | SENDER | `sender_auth` validation |
| 2 | `0x04` | PAYER | `payer_auth` validation |
| 3 | `0x08` | CONFIG | Config change `auth` |

The protocol checks scope after verifier execution: `scope == 0x00 || (scope &amp; context_bit) != 0`.

The protocol validates signatures by reading `owner_config` directly and delegating authentication to [Verifiers](#verifiers) — see [Validation](#validation) for the full flow. Owner enumeration is performed off-chain via `OwnerAuthorized` / `OwnerRevoked` event logs. No owner count is enforced on-chain — gas costs naturally bound owner creation.

#### 2D Nonce Storage

Nonce state is managed by a precompile at `NONCE_MANAGER_ADDRESS`. The protocol reads and increments nonce slots directly during AA transaction processing; the precompile exposes a read-only `getNonce()` interface to the EVM.

The transaction carries two nonce fields: `nonce_key` (`uint256`) selects the nonce channel, and `nonce_sequence` (`uint64`) is the expected sequence number within that channel.

| `nonce_key` Range | Name | Description |
|-------------------|------|-------------|
| `0` | Standard | Sequential ordering, mempool default |
| `1` through `NONCE_KEY_MAX - 1` | User-defined | Parallel transaction channels defined by wallets |
| `NONCE_KEY_MAX` | Nonce-free | No nonce state read or incremented |

##### Nonce-Free Mode (`NONCE_KEY_MAX`)

When `nonce_key == NONCE_KEY_MAX`, the protocol does not read or increment nonce state. `nonce_sequence` MUST be `0`. Replay protection relies on `expiry`, which MUST be non-zero.

Nodes SHOULD reject `NONCE_KEY_MAX` transactions from the mempool if `expiry` exceeds a short window (e.g., 10 seconds from current time). Replay protection is handled by transaction hash.

#### Account Lock

Account lock state is stored in a single packed 32-byte slot:

| Field | Description |
|-------|-------------|
| `locked` | Owner configuration is frozen — config changes rejected |
| `unlock_delay` | Seconds required between initiating unlock and becoming unlocked (`uint16`) |
| `unlocks_at` | Timestamp when unlock takes effect (`uint40`, 0 = no unlock initiated) |

When `locked` is set, all config changes are rejected — both config change entries in `account_changes` and `applySignedOwnerChanges()` via EVM. The lock cannot be removed without a timelock delay.

Lock operations are called directly by the account (`msg.sender`) on the Account Configuration Contract.

**Lifecycle**:

1. **Lock**: Call `lock(unlockDelay)`. Sets `locked = true` with the specified `unlockDelay` (seconds).
2. **Initiate unlock**: Call `initiateUnlock()`. Sets `unlocks_at = block.timestamp + unlock_delay`.
3. **Effective unlock**: Once `block.timestamp &gt;= unlocks_at`, the account is effectively unlocked — config changes are permitted.

### Delegation Indicator

This proposal uses the same delegation indicator behavior as [EIP-7702](/EIPs/EIPS/eip-7702) on 8130 chains, even if [EIP-7702](/EIPs/EIPS/eip-7702) transactions are not enabled. An account is delegated when its code is exactly `0xef0100 || target`, where `target` is a 20-byte address. Delegated accounts MAY originate transactions, and all code-executing operations targeting a delegated account MUST load code from `target` instead of the indicator.

### Verifiers

Each owner is associated with a verifier, a contract that performs signature verification. The verifier address is stored in `owner_config`. All verifiers implement `IVerifier.verify(hash, data)`. Stateful verifiers MAY read transaction context (sender address, calls, payer) from the Transaction Context precompile at `TX_CONTEXT_ADDRESS` (see [Transaction Context](#transaction-context)). The protocol validates the returned `ownerId` against `owner_config` and checks the owner&apos;s scope against the authentication context.

Verifiers are executed via STATICCALL. Verifier addresses MUST NOT be delegated accounts — reject if the code at the verifier address starts with the delegation indicator (`0xef0100`). Execution is metered (see [Mempool Acceptance](#mempool-acceptance) for rules).

Nodes MAY implement equivalent verification logic natively for well-known verifier addresses, bypassing EVM execution. The native implementation MUST produce identical results to the onchain contract. Native implementations avoid EVM interpreter overhead, have deterministic gas costs, and introduce no external state dependencies — improving mempool validation throughput.

`ECRECOVER_VERIFIER` (`address(1)`) is a protocol-reserved address for native secp256k1 verification. When the protocol encounters this address as a verifier in auth data, it performs ecrecover directly rather than making a STATICCALL. The `data` portion is interpreted as raw ECDSA `(r || s || v)`, and the returned `ownerId` is `bytes32(bytes20(recovered_address))`. Owners can be explicitly registered with `ECRECOVER_VERIFIER` to use native ecrecover with a custom scope, without requiring a deployed verifier contract.

Any contract implementing `IVerifier` can be permissionlessly deployed and registered as an owner&apos;s verifier.

### Account Types

This proposal supports three paths for accounts to use AA transactions:

| Account Type | How It Works | Key Recovery |
|--------------|--------------|--------------|
| **Existing Smart Contracts** | Already-deployed accounts (e.g., ERC-4337 wallets) register owners via the system contract (see [Smart Wallet Migration Path](#smart-wallet-migration-path)) | Wallet-defined |
| **EOAs** | EOAs send AA transactions using their existing secp256k1 key via native ecrecover. If the account has no code, the protocol auto-delegates to `DEFAULT_ACCOUNT_ADDRESS` (see [Block Execution](#block-execution)). Accounts MAY override with a delegation entry in `account_changes` or a standard [EIP-7702](/EIPs/EIPS/eip-7702) transaction | Wallet-defined; EOA recoverable via 1559/7702 transaction flows |
| **New Accounts (No EOA)** | Created via a create entry in `account_changes` with CREATE2 address derivation; runtime bytecode placed at address, owners + verifiers configured, `calls` handles initialization | Wallet-defined |

### AA Transaction Type

A new [EIP-2718](/EIPs/EIPS/eip-2718) transaction with type `AA_TX_TYPE`:

```
AA_TX_TYPE || rlp([
  chain_id,
  from,               // Sender address (20 bytes) | empty for EOA signature
  nonce_key,          // uint256: nonce channel selector
  nonce_sequence,     // uint64: sequence number
  expiry,             // Unix timestamp (seconds)
  max_priority_fee_per_gas,
  max_fee_per_gas,
  gas_limit,
  account_changes,    // Account creation, config change, and/or delegation operations | empty
  calls,              // [[{to, data}, ...], ...] | empty
  payer,              // empty = sender-paid, payer_address = specific payer
  sender_auth,
  payer_auth          // empty = sender-pay, verifier || data = sponsored (same format as sender_auth)
])

call = rlp([to, data])   // to: address, data: bytes
```

#### Field Definitions

| Field | Description |
|-------|-------------|
| `chain_id` | Chain ID per [EIP-155](/EIPs/EIPS/eip-155) |
| `from` | Sending account address. **Required** (non-empty) for configured owner signatures. **Empty** for EOA signatures—address recovered via ecrecover. The presence or absence of `from` is the sole distinguisher between EOA and configured owner signatures. |
| `nonce_key` | `uint256` nonce channel selector. `0` for standard sequential ordering, `1` through `NONCE_KEY_MAX - 1` for parallel channels, `NONCE_KEY_MAX` for nonce-free mode. |
| `nonce_sequence` | `uint64` expected sequence number within `nonce_key`. Must match current sequence for `(from, nonce_key)`. Incremented after inclusion regardless of execution outcome. Must be `0` when `nonce_key == NONCE_KEY_MAX`. |
| `expiry` | Unix timestamp (seconds since epoch). Transaction invalid when `block.timestamp &gt; expiry`. A value of `0` means no expiry. Must be non-zero when `nonce_key == NONCE_KEY_MAX`. |
| `max_priority_fee_per_gas` | Priority fee per gas unit ([EIP-1559](/EIPs/EIPS/eip-1559)) |
| `max_fee_per_gas` | Maximum fee per gas unit ([EIP-1559](/EIPs/EIPS/eip-1559)) |
| `gas_limit` | Execution gas budget — reserved for call execution. Auth and intrinsic costs are separate (see [Intrinsic Gas](#intrinsic-gas)) |
| `account_changes` | **Empty**: No account changes. **Non-empty**: Array of typed entries — create (type `0x00`) for account deployment, config change (type `0x01`) for owner management, and delegation (type `0x02`) for code delegation. See [Account Changes](#account-changes) |
| `calls` | **Empty**: No calls. **Non-empty**: Array of call phases — see [Call Execution](#call-execution) |
| `payer` | Gas payer identity. **Empty**: Sender pays. **20-byte address**: This specific payer required. See [Payer Modes](#payer-modes) |
| `sender_auth` | See [Signature Format](#signature-format) |
| `payer_auth` | Payer authorization. **Empty**: self-pay. **Non-empty**: `verifier || data` — same format as `sender_auth`. See [Payer Modes](#payer-modes) |

#### Intrinsic Gas

```
intrinsic_gas = AA_BASE_COST + tx_payload_cost + sender_auth_cost + payer_auth_cost + nonce_key_cost + bytecode_cost + account_changes_cost
```

Auth verification gas (`sender_auth_cost`, `payer_auth_cost`) is metered but does not consume `gas_limit`. The full `gas_limit` is reserved for call execution. The payer is charged for total gas consumed: `intrinsic_gas + execution_gas_used`. Unused execution gas (from `gas_limit`) is refunded to the payer.

The sender verifier runs first. By the time the payer verifier executes, all intrinsic costs except `payer_auth_cost` are known — the Transaction Context precompile&apos;s `getMaxCost()` reflects this (see [Transaction Context](#transaction-context)).

**`sender_auth_cost`**: For EOA signatures (`from` empty) or `ECRECOVER_VERIFIER` (`address(1)`) signatures: 6,000 gas (ecrecover + 1 SLOAD + overhead). For other configured owner signatures (`from` set, `address(2+)` verifier): 1 SLOAD (`owner_config`) + cold code access + actual gas consumed by verifier execution.

**`payer_auth_cost`**: 0 for self-pay (`payer` empty). Otherwise, the same `sender_auth_cost` model applies to the payer&apos;s verifier.

| Component | Value |
|-----------|-------|
| `tx_payload_cost` | Standard per-byte cost over the entire RLP-serialized transaction: 16 gas per non-zero byte, 4 gas per zero byte, consistent with [EIP-2028](/EIPs/EIPS/eip-2028). Ensures all transaction fields (`account_changes`, `sender_auth`, `calls`, etc.) are charged for data availability |
| `nonce_key_cost` | `NONCE_KEY_MAX`: 14,000 gas (replay protection state: 2 cold SLOADs + 1 warm SLOAD + 3 warm SSTORE resets). Otherwise: 22,100 gas for first use of a `nonce_key` (cold SLOAD + SSTORE set), 5,000 gas for existing keys (cold SLOAD + warm SSTORE reset) |
| `bytecode_cost` | 0 if no create entry in `account_changes`. Otherwise: 32,000 (deployment base) + code deposit cost (200 gas per deployed byte). Byte costs for `code` are covered by `tx_payload_cost` |
| `account_changes_cost` | Per applied config change entry: auth verification cost (same model as `sender_auth_cost`) + `num_operations` × 20,000 per SSTORE. Per applied delegation entry: code deposit cost (200 × 23 bytes for the delegation indicator). Per skipped config change entry (already applied): 2,100 (SLOAD to check sequence). 0 if no config change or delegation entries in `account_changes` |

#### Signature Format

Signature format is determined by the `from` field:

**EOA signature** (`from` empty): Raw 65-byte ECDSA signature `(r || s || v)`. The sender address is recovered via ecrecover.

**Configured owner signature** (`from` set):

```
verifier (20 bytes) || data
```

The first 20 bytes identify the verifier address. When the verifier is `ECRECOVER_VERIFIER`, `data` is raw ECDSA `(r || s || v)` and the protocol handles ecrecover natively. For all other verifiers, `data` is verifier-specific — each verifier defines its own wire format.

##### Validation

1. **Resolve sender**: If `from` empty, ecrecover derives the sender address (EOA path) with `ownerId = bytes32(bytes20(sender))`. If `from` set, read the first 20 bytes of `sender_auth` as the verifier address.
2. **Set transaction context**: Populate the Transaction Context precompile with sender, payer, and calls (see [Transaction Context](#transaction-context)).
3. **Verify**: Route by verifier address. For the EOA path (`from` empty), ecrecover was already performed in step 1. For `ECRECOVER_VERIFIER` (`address(1)`), the protocol natively ecrecovers from `data` (as `r || s || v`), returning `ownerId = bytes32(bytes20(recovered_address))`. For all other verifiers (`address(2+)`), call `verifier.verify(hash, data)` via STATICCALL, returning `ownerId` (or `bytes32(0)` for invalid). Reject `REVOKED_VERIFIER` as a verifier address.
4. **Authorize**: SLOAD `owner_config(from, ownerId)`. **Implicit EOA rule**: if the slot is empty and `ownerId == bytes32(bytes20(from))`, treat as implicitly authorized with scope `0x00`. Otherwise, require that the stored verifier address matches the effective verifier and is not `REVOKED_VERIFIER`.
5. **Check scope**: Read the scope byte from `owner_config` (or `0x00` for the implicit case). Determine the context bit: `0x02` (SENDER) for `sender_auth`, `0x04` (PAYER) for `payer_auth`, `0x01` (SIGNATURE) for `verifySignature()`, `0x08` (CONFIG) for config change `auth`. Require `scope == 0x00 || (scope &amp; context_bit) != 0`.

#### Signature Payload

Sender and payer use different type bytes for domain separation, preventing signature reuse attacks:

**Sender signature hash** — all tx fields through `payer`, excluding `sender_auth` and `payer_auth`:

```
keccak256(AA_TX_TYPE || rlp([
  chain_id, from, nonce_key, nonce_sequence, expiry,
  max_priority_fee_per_gas, max_fee_per_gas, gas_limit,
  account_changes, calls,
  payer
]))
```

**Payer signature hash** — all tx fields through `calls`, excluding `payer`, `sender_auth`, and `payer_auth`:

```
keccak256(AA_PAYER_TYPE || rlp([
  chain_id, from, nonce_key, nonce_sequence, expiry,
  max_priority_fee_per_gas, max_fee_per_gas, gas_limit,
  account_changes, calls
]))
```

#### Payer Modes

Gas payment and sponsorship are controlled by two independent fields:

**`payer`** — the sender&apos;s commitment regarding the gas payer, included in the sender&apos;s signed hash:

| Value | Mode | Description |
|-------|------|-------------|
| empty | Self-pay | Sender pays their own gas |
| `payer_address` (20 bytes) | Sponsored | Sender binds tx to a specific sponsor |

**`payer_auth`** — uses the same `verifier || data` format as `sender_auth`:

| `payer` | `payer_auth` | Payer Address | Validation |
|---------|-------------|---------------|------------|
| empty | empty | `from` | Self-pay — no payer validation |
| address | `verifier (20) \|\| data` | `payer` field | Sponsored — any verifier. Reads payer&apos;s `owner_config`, validates against `payer` address |

Any authorized owner with SENDER scope can sign self-pay transactions.

### Account Changes

The `account_changes` field is an array of typed entries for account creation and owner management:

| Type | Name | Description |
|------|------|-------------|
| `0x00` | Create | Deploy a new account with initial owners (must be first, at most one) |
| `0x01` | Config change | Owner management: authorizeOwner, revokeOwner |
| `0x02` | Delegation | Set code delegation via the delegation indicator (at most one per account) |

Create and delegation entries are authorized by the transaction&apos;s `sender_auth` — there is no separate authorization field. The initial `ownerId`s for create entries are salt-committed to the derived address. Delegation requires the sender to be the account&apos;s implicit EOA owner with CONFIG scope. Config change entries carry their own `auth` and use a sequence counter for deterministic cross-chain ordering. Nodes SHOULD enforce a configurable per-transaction limit on the number of config change entries (mempool rule).

#### Create Entry

New smart contract accounts can be created with pre-configured owners in a single transaction. The `code` is placed directly at the account address — it is not executed during deployment. The account&apos;s initialization logic runs via `calls` in the execution phase that follows:

```
rlp([
  0x00,               // type: create
  user_salt,          // bytes32: User-chosen uniqueness factor
  code,               // bytes: Runtime bytecode placed at account address
  initial_owners      // Array of [verifier, ownerId, scope] tuples
])
```

Initial owners are registered with their specified scope. Wallet initialization code can lock the account via `calls` in the execution phase (e.g., calling `lock()` on the Account Configuration Contract).

The `code` field contains runtime bytecode placed directly at the account address. For delegation, use a delegation entry (type `0x02`) in `account_changes` after account creation.

```
[0x00, user_salt, runtimeBytecode, initial_owners]
```

##### Address Derivation

Addresses are derived using the CREATE2 address formula with the Account Configuration Contract (`ACCOUNT_CONFIG_ADDRESS`) as the deployer. The `initial_owners` are sorted by `ownerId` before hashing to ensure address derivation is order-independent (the same set of owners always produces the same address regardless of the order specified):

```
sorted_owners = sort(initial_owners, by: ownerId)

owners_commitment = keccak256(ownerId_0 || verifier_0 || scope_0 || ownerId_1 || verifier_1 || scope_1 || ... || ownerId_n || verifier_n || scope_n)

effective_salt = keccak256(user_salt || owners_commitment)
deployment_code = DEPLOYMENT_HEADER(len(code)) || code
address = keccak256(0xff || ACCOUNT_CONFIG_ADDRESS || effective_salt || keccak256(deployment_code))[12:]
```

The `owners_commitment` uses `ownerId || verifier || scope` (53 bytes) per owner — consistent with how the Account Configuration Contract identifies and configures owners.

`DEPLOYMENT_HEADER(n)` is a fixed 14-byte EVM loader that returns the trailing code (see [Appendix: Deployment Header](#appendix-deployment-header) for the full opcode sequence). On non-8130 chains, `createAccount()` constructs `deployment_code` and passes it as init_code to CREATE2. On 8130 chains, the protocol constructs the same `deployment_code` for address derivation but places `code` directly (no execution). Both paths produce the same address — callers only provide `code`; the header is never user-facing.

Users can receive funds at counterfactual addresses before account creation.

##### Validation (Create Entry)

When a create entry is present in `account_changes`:

1. Parse `[0x00, user_salt, code, initial_owners]` where each entry is `[verifier, ownerId, scope]`
2. Reject if any duplicate `ownerId` values exist
3. Reject if `code` is empty
4. Sort by ownerId: `sorted_owners = sort(initial_owners, by: ownerId)`
5. Compute `owners_commitment = keccak256(ownerId_0 || verifier_0 || scope_0 || ... || ownerId_n || verifier_n || scope_n)`
6. Compute `effective_salt = keccak256(user_salt || owners_commitment)`
7. Compute `deployment_code = DEPLOYMENT_HEADER(len(code)) || code`
8. Compute `expected = keccak256(0xff || ACCOUNT_CONFIG_ADDRESS || effective_salt || keccak256(deployment_code))[12:]`
9. Require `from == expected`
10. Require `code_size(from) == 0` (account not yet deployed)
11. Validate `sender_auth` against one of `initial_owners` (ownerId resolved from auth must match an entry&apos;s ownerId)

#### Config Change Entry

Config change entries manage the account&apos;s owners. Each entry includes a `chain_id` field where `0` means valid on any chain, allowing replay across chains to synchronize owner state.

##### Config Change Format

```
rlp([
  0x01,               // type: config change
  chain_id,           // uint64: 0 = valid on any chain
  sequence,           // uint64: monotonic ordering
  owner_changes,      // Array of owner changes
  auth                // Signature from an owner valid at this sequence
])

owner_change = rlp([
  change_type,          // uint8: operation type (see below)
  verifier,             // address: verifier contract (authorizeOwner only)
  ownerId,              // bytes32: owner identifier
  scope                 // uint8: permission bitmask (authorizeOwner only, 0x00 = unrestricted)
])
```

**Operation types**:

| change_type | Name | Description | Fields Used |
|-------------|------|-------------|-------------|
| `0x01` | `authorizeOwner` | Authorize a new owner with scope | `verifier`, `ownerId`, `scope` |
| `0x02` | `revokeOwner` | Revoke an existing owner — deletes the slot for non-EOA owners; for the implicit EOA owner (`ownerId == bytes32(bytes20(account))`), overwrites with `verifier = REVOKED_VERIFIER` (`type(uint160).max`) to prevent implicit re-authorization | `ownerId` |

#### Config Change Authorization

Each config change entry represents a set of operations authorized at a specific sequence number. The `auth` must be valid against the account&apos;s owner configuration *at the point after all previous entries in the list have been applied*. The authorizing owner must have CONFIG scope (see [Owner Scope](#owner-scope)).

The sequence number is scoped by `chain_id`: `0` uses the multichain sequence channel (valid on any chain), while a specific `chain_id` uses that chain&apos;s local channel.

##### Config Change Signature Payload

Entry signatures use ABI-encoded type hashing. Operations within an entry are individually ABI-encoded and hashed into an array digest:

```
TYPEHASH = keccak256(&quot;SignedOwnerChanges(address account,uint64 chainId,uint64 sequence,OwnerChange[] ownerChanges)OwnerChange(uint8 changeType,address verifier,bytes32 ownerId,uint8 scope)&quot;)

ownerChangeHashes = [keccak256(abi.encode(changeType, verifier, ownerId, scope)) for each ownerChange]
ownerChangesHash = keccak256(abi.encodePacked(ownerChangeHashes))

digest = keccak256(abi.encode(TYPEHASH, account, chainId, sequence, ownerChangesHash))
```

Domain separation from transaction signatures (`AA_TX_TYPE`, `AA_PAYER_TYPE`) is structural — transaction hashes use `keccak256(type_byte || rlp([...]))`, which cannot produce the same prefix as `abi.encode(TYPEHASH, ...)`.

The `auth` follows the same [Signature Format](#signature-format) as `sender_auth` (`verifier || data`), validated against the account&apos;s owner state at that point in the sequence.

##### Account Config Change Paths

Owners can be modified through two portable paths:

| | `account_changes` (tx field) | `applySignedOwnerChanges()` (EVM) |
|--|---|---|
| Authorization | Signed operation (any verifier) | Direct verification via verifier + `owner_config` |
| Availability | Always (8130 chains) | Always (any chain) |
| Portability | Cross-chain (chain_id 0) or chain-specific | Cross-chain (chain_id 0) or chain-specific |
| Sequence | Increments channel&apos;s `change_sequence` | Increments channel&apos;s `change_sequence` |
| When processed | Before code deployment (8130 only) | During EVM execution (any chain) |

Both paths share the same signed owner changes and `change_sequence` counters. `applySignedOwnerChanges()` parses the verifier address from `auth`, calls the verifier to get the `ownerId`, and checks `owner_config`. Anyone can call these functions; authorization comes from the signed operation, not the caller. All owner modification paths are blocked when the account is locked (see [Account Lock](#account-lock)).

#### Delegation Entry

Delegation entries set code delegation for the sender&apos;s account, replacing the need for an `authorization_list` in the transaction. Delegation is authorized by the transaction&apos;s `sender_auth` — no separate signature is required. The sender must be the account&apos;s implicit EOA owner (`ownerId == bytes32(bytes20(from))`) with CONFIG scope.

##### Delegation Format

```
rlp([
  0x02,               // type: delegation
  target              // address: delegate to this contract, or address(0) to clear
])
```

The delegation is only permitted when:

- `code_size(from) == 0` (empty account), or
- `code(from)` starts with the delegation designator `0xef0100` (updating an existing delegation)

It will **not** replace non-delegation bytecode.

When `target` is `address(0)`, the delegation indicator is cleared — the account&apos;s code hash is reset to the empty code hash, restoring the account to a pure EOA.

On non-8130 chains, delegation uses standard [EIP-7702](/EIPs/EIPS/eip-7702) transactions (ECDSA authority).

For 8130 transactions, successful delegation updates emit a protocol-injected `DelegationApplied(account, target)` receipt log, where `target` is the delegated contract address (or `address(0)` when clearing delegation).

#### Execution (Account Changes)

`account_changes` entries are processed in order before call execution:

1. **Create entry** (if present): Register `initial_owners` in Account Config storage for `from` — for each `[verifier, ownerId, scope]` tuple, write `owner_config` (verifier address and scope byte). Initialize lock state to safe defaults: `locked = false`, `unlockDelay = 0`, `unlockRequestedAt = 0`.
2. **Config change entries** (if any): Apply operations in entry order. Reject transaction if account is locked.
3. **Delegation entries** (if any): Require the sender&apos;s resolved `ownerId == bytes32(bytes20(from))` (EOA owner) with CONFIG scope. Reject if account is locked. For each entry, set `code(from) = 0xef0100 || target` (or clear if `target` is `address(0)`). Reject if account has non-delegation bytecode.
4. **Code placement** (if create entry present): Place `code` at `from`. The runtime bytecode is placed directly — not executed.

### Execution

#### Call Execution

The protocol dispatches calls directly from `from` to each call&apos;s `to` address:

| Parameter | Value |
|-----------|-------|
| `from` (caller) | `from` (the sender) |
| `to` | `call.to` |
| `tx.origin` | `from` |
| `msg.sender` at target | `from` |
| `msg.value` | 0 |
| `data` | `call.data` |

Calls carry no ETH value. ETH transfers are initiated by the account&apos;s wallet bytecode via the CALL opcode (see [Why No Value in Calls?](#why-no-value-in-calls)).

Phases execute in order from a single gas pool (`gas_limit`). Within each phase, calls execute in order and are **atomic** — if any call in a phase reverts, all state changes for that phase are discarded and remaining phases are **skipped**. Completed phases **persist** — their state changes are committed and survive later phase reverts.

**Common patterns**:

- **Simple call**: `[[{to, data}]]` — one phase, one call
- **Atomic batch**: `[[call_a, call_b, call_c]]` — one phase, all-or-nothing
- **Sponsor + user**: `[[sponsor_payment], [user_action_a, user_action_b]]` — sponsor in phase 0 (committed), user actions in phase 1 (atomic, skipped if sponsor fails)

#### Transaction Context

The Transaction Context precompile at `TX_CONTEXT_ADDRESS` provides read-only access to the current AA transaction&apos;s metadata. The precompile reads directly from the client&apos;s in-memory transaction state — protocol &quot;writes&quot; are effectively zero-cost. Gas is charged as a base cost plus 3 gas per 32 bytes of returned data, matching `CALLDATACOPY` pricing.

| Function | Returns | Available |
|----------|---------|-----------|
| `getSender()` | `address` — the account being validated (`from`) | Validation + Execution |
| `getPayer()` | `address` — gas payer (`from` for self-pay, payer for sponsored) | Validation + Execution |
| `getOwnerId()` | `bytes32` — authenticated owner&apos;s ownerId | Execution only |
| `getCalls()` | `Call[][]` — full calls array | Validation + Execution |
| `getMaxCost()` | `uint256` — `(gas_limit + known_intrinsic) * max_fee_per_gas` where `known_intrinsic` includes all intrinsic costs computed so far (excluding payer auth) | Validation + Execution |
| `getGasLimit()` | `uint256` — execution gas budget (`gas_limit`). Auth and intrinsic costs are separate | Validation + Execution |

If the wallet needs the verifier address or scope, it calls `getOwnerConfig(account, ownerId)` on the Account Configuration Contract.

**Non-8130 chains**: No code at `TX_CONTEXT_ADDRESS`; STATICCALL returns zero/default values.

### Portability

The system is split into storage and verification layers with different portability characteristics:

| Component | 8130 chains | Non-8130 chains |
|-----------|-------------|-----------------|
| **Account Configuration Contract** | Protocol reads storage directly for validation; EVM interface available | Standard contract (ERC-4337 compatible factory) |
| **Verifier Contracts** | Protocol calls verifiers via STATICCALL | Same onchain contracts callable by account config contract and wallets |
| **Code Delegation** | Delegation entry in `account_changes` (EOA-only authorization in this version) | Standard [EIP-7702](/EIPs/EIPS/eip-7702) transactions (ECDSA authority) |
| **Transaction Context** | Precompile at `TX_CONTEXT_ADDRESS` — protocol populates, verifiers read | No code at address; STATICCALL returns zero/default values |
| **Nonce Manager** | Precompile at `NONCE_MANAGER_ADDRESS` | Not applicable; nonce management by existing systems (e.g., ERC-4337 EntryPoint) |

All contracts are deployed at deterministic CREATE2 addresses across chains.

### Validation Flow

#### Mempool Acceptance

1. Parse and structurally validate `sender_auth`. Verify `account_changes` contains at most one create entry (type `0x00`, must be first) and at most one delegation entry (type `0x02`). Nodes SHOULD enforce a configurable limit on the number of config change entries (type `0x01`).
2. Resolve sender: if `from` set, use it; if empty, ecrecover from `sender_auth`
3. Determine effective owner state:
   a. If create entry present in `account_changes`: verify address derivation, `code_size(from) == 0`, use `initial_owners`
   b. Else: read from Account Config storage
4. If config change or delegation entries present in `account_changes`: reject if account is locked (see [Account Lock](#account-lock)). For config change entries: simulate applying operations in sequence, skip already-applied entries. For delegation entries: verify `code_size(from) == 0` or existing delegation designator.
5. Validate `sender_auth` against resulting owner state (see [Validation](#validation)). Require SENDER scope on the resolved owner. If delegation entries are present, also require `ownerId == bytes32(bytes20(from))` (EOA owner) and CONFIG scope.
6. Resolve payer from `payer` and `payer_auth`:
   - `payer` empty and `payer_auth` empty: self-pay. Payer is `from`. Reject if balance insufficient.
   - `payer` = 20-byte address (sponsored): `payer_auth` uses any verifier. Validate `payer_auth` against the `payer` address&apos;s `owner_config`. Require PAYER scope on the resolved owner.
7. Verify nonce, payer ETH balance, and expiry:
   - **Standard keys** (`nonce_key != NONCE_KEY_MAX`): require `nonce_sequence == current_sequence(from, nonce_key)`.
   - **Nonce-free key** (`nonce_key == NONCE_KEY_MAX`): skip nonce check, require `nonce_sequence == 0`, require non-zero `expiry`, and nodes SHOULD reject if `expiry` exceeds a short window (e.g., 10 seconds). Deduplicate by transaction hash.
8. Mempool threshold: gas payer&apos;s pending count below node-configured limits.

Nodes SHOULD maintain a verifier allowlist of trusted verifiers. Allowlisted verifiers have known gas bounds and no external state dependencies, enabling validation with no tracing and minimal state requirements — only `owner_config` and the verifier code itself.

Nodes MAY accept transactions with unknown verifiers by enforcing a gas cap and applying validation scope tracing to restrict opcodes and track state dependencies for invalidation.

Nodes MAY apply higher pending transaction rate limits based on account lock state:

- **Locked sender**: A locked `from` account has a stable signature if combined with a stateless verifier. Nodes can safely allow a higher sender rate.
- **Locked payer with trusted bytecode**: A locked `payer` account whose bytecode is recognized and restricts eth movement while locked provides an additional guarantee that ETH balance only decreases via gas fees. Nodes can safely allow a higher payer rate for such accounts.

#### Block Execution

1. If `account_changes` contains config change or delegation entries, read lock state for `from`. Reject transaction if account is locked. If delegation entries are present, require the sender&apos;s resolved `ownerId == bytes32(bytes20(from))` (EOA owner) with CONFIG scope.
2. ETH gas deduction from payer (sponsor for sponsored, `from` for self-pay). Transaction is invalid if payer has insufficient balance.
3. If `nonce_key != NONCE_KEY_MAX`, increment nonce in Nonce Manager storage for `(from, nonce_key)`. If `nonce_key == NONCE_KEY_MAX`, skip (nonce-free mode).
4. If `code_size(from) == 0` and no create entry and no delegation entry is present in `account_changes`, auto-delegate `from` to `DEFAULT_ACCOUNT_ADDRESS` (set code to `0xef0100 || DEFAULT_ACCOUNT_ADDRESS`). This delegation persists.
5. Process `account_changes` entries in order (see [Execution (Account Changes)](#execution-account-changes)).
6. Set transaction context on the Transaction Context precompile (sender, payer, ownerId, calls).
7. Execute `calls` per [Call Execution](#call-execution) semantics.

Unused execution gas (from `gas_limit`) is refunded to the payer. Intrinsic gas (including auth costs) is not refundable. For step 5, the protocol SHOULD inject log entries into the transaction receipt (e.g., `OwnerAuthorized`, `AccountCreated`, `DelegationApplied`) matching the events defined in the [IAccountConfiguration](#iaccountconfiguration) interface, following the protocol-injected log pattern established by [EIP-7708](/EIPs/EIPS/eip-7708). These protocol-injected logs are emitted only for 8130 transactions.

### RPC Extensions

**`eth_getTransactionCount`**: Extended with optional `nonceKey` parameter (`uint256`) to query 2D nonce channels. Reads from the Nonce Manager precompile at `NONCE_MANAGER_ADDRESS`.

**`eth_getTransactionReceipt`**: AA transaction receipts include:

- `payer` (address): Gas payer address (`from` for self-pay, specified payer for sponsored).
- `status` (uint8): `0x01` = all phases succeeded (or `calls` was empty), `0x00` = one or more phases reverted. Existing tools checking `status == 1` remain correct for the success path.
- `phaseStatuses` (uint8[]): Per-phase status array. Each entry is `0x01` (success) or `0x00` (reverted). Phases after a revert are not executed and reported as `0x00`. Empty if `calls` was empty.

**`eth_getAcceptedVerifiers`**: Returns the node&apos;s verifier acceptance policy. The response includes a top-level `acceptsUnknownVerifiers` boolean indicating whether the node accepts transactions with verifiers not on its allowlist. The `verifiers` array lists each accepted verifier with its `address`, whether the node has a `native` implementation, and `maxAuthCost` — the maximum gas the node will allow for that verifier&apos;s auth execution.

### Appendix: Storage Layout

The protocol reads storage directly from the Account Configuration Contract (`ACCOUNT_CONFIG_ADDRESS`) and Nonce Manager (`NONCE_MANAGER_ADDRESS`). The storage layout is defined by the deployed contract bytecode — slot derivation follows from the contract&apos;s Solidity storage declarations. The final deployed contract source serves as the canonical reference for slot locations.

### Appendix: Deployment Header

The `DEPLOYMENT_HEADER(n)` is a 14-byte EVM loader that copies trailing code into memory and returns it. The header encodes code length `n` into its `PUSH2` instructions:

```
DEPLOYMENT_HEADER(n) = [
  0x61, (n &gt;&gt; 8) &amp; 0xFF, n &amp; 0xFF,     // PUSH2 n        (code length)
  0x60, 0x0E,                          // PUSH1 14       (offset: code starts after 14-byte header)
  0x60, 0x00,                          // PUSH1 0        (memory destination)
  0x39,                                // CODECOPY       (copy code from code[14..] to memory[0..])
  0x61, (n &gt;&gt; 8) &amp; 0xFF, n &amp; 0xFF,     // PUSH2 n        (code length)
  0x60, 0x00,                          // PUSH1 0        (memory offset)
  0xF3                                 // RETURN         (return code from memory)
]
```

The create entry only supports runtime bytecode. Delegation is set via delegation entries (type `0x02`) in `account_changes`.

## Rationale

### Why Verifier Contracts?

Enables permissionless extension — deploy a new verifier contract, nodes update their allowlist, no protocol upgrade required. The verifier returns the `ownerId` rather than accepting it as input, so the protocol never needs algorithm-specific logic — routing, derivation, and validation are all handled by the verifier. All verifiers share a single `verify(hash, data)` interface with no type-based dispatch. Owner scope provides protocol-enforced role separation without verifier cooperation.

### Why 2D Nonce + `NONCE_KEY_MAX`?

Additional `nonce_key` values allow parallel transaction lanes without nonce contention between independent workflows.

`NONCE_KEY_MAX` enables nonce-free transactions where replay protection comes from short-lived `expiry` and node-level replay protection by transaction hash. This is useful for operations where nonce ordering coordination is undesirable.

### Why a Nonce Precompile?

Nonce state is isolated in a dedicated precompile (`NONCE_MANAGER_ADDRESS`) because nonce writes occur on nearly every AA transaction, while owner config writes are relatively infrequent.

The Nonce Manager has no EVM-writable state and no portability requirement — a precompile is simpler than exposing nonce mutation through the account config contract.

### Why a Transaction Context Precompile?

Transaction context (sender, payer, calls, gas) is immutable transaction metadata — it never changes during execution. `ownerId` is set after validation and available during execution only. A precompile is the natural fit:

- **Zero protocol write cost**: The precompile reads directly from the client&apos;s in-memory transaction struct — no HashMap insert, no journaling, no rollback tracking.
- **Pull model**: Verifiers read only what they need. Pure verifiers pay nothing for context they don&apos;t use.
- **Forward compatible**: New context fields are added as new precompile functions — no interface changes to `IVerifier` or existing verifier contracts.

### Why CREATE2 for Account Creation?

The create entry uses the CREATE2 address formula with `ACCOUNT_CONFIG_ADDRESS` as the deployer address for cross-chain portability:

1. **Deterministic addresses**: Same `user_salt + code + initial_owners` produces the same address on any chain
2. **Pre-deployment funding**: Users can receive funds at counterfactual addresses before account creation
3. **Portability**: Same `deployment_code` produces the same address on both 8130 and non-8130 chains (see [Address Derivation](#address-derivation))
4. **Front-running prevention**: `initial_owners` in the salt prevents attackers from deploying with different owners (see [Create Entry](#create-entry))

### Smart Wallet Migration Path

Existing ERC-4337 smart accounts migrate to native AA without redeployment:

1. **Import account**: Call `importAccount()` on the Account Configuration Contract — this verifies via the account&apos;s `isValidSignature` ([ERC-1271](/EIPs/EIPS/eip-1271)) and registers initial owners. Existing ERC-4337 wallets already implement ERC-1271, so initial owner registration works without code changes.
2. **Upgrade wallet logic**: Update contract to delegate `isValidSignature` to the Account Configuration Contract&apos;s `verifySignature()` function for owner and verifier infrastructure, and read `getOwnerId()` from the Transaction Context precompile during execution to identify which owner authorized the transaction
3. **Backwards compatible**: Wallet can still accept ERC-4337 UserOps via EntryPoint alongside native AA transactions

### Why Call Phases?

Phases provide two atomic batching levels without per-call mode flags:

- **Atomic batching**: One phase, all-or-nothing.
- **Sponsor protection**: Payment in phase 0 persists even if user actions in phase 1 revert.
- **Paymaster inspection**: Verifiers can inspect calls via the Transaction Context precompile to validate payment terms.

### Why Direct Dispatch?

The protocol dispatches each call directly to the specified `to` address with `msg.sender = from`. Owners with SENDER scope are authorized to send transactions at the protocol level. Every account has wallet bytecode (via auto-delegation or explicit deployment), so calls route through the wallet for ETH-carrying operations.

### Why No Value in Calls?

Since every account has wallet bytecode (auto-delegation or explicit deployment), ETH transfers route through wallet code via the CALL opcode — no capability is lost. Removing protocol-level value from calls means the protocol never moves ETH on behalf of the sender.

### Why Delegation via Account Changes?

[EIP-7702](/EIPs/EIPS/eip-7702) introduced `authorization_list` as a transaction-level field for code delegation, with ECDSA authority. This proposal moves delegation into `account_changes`, authorized by the transaction&apos;s `sender_auth`. Delegation is restricted to the account&apos;s implicit EOA owner (`ownerId == bytes32(bytes20(from))`) so that code delegation remains portable across non-8130 chains via standard [EIP-7702](/EIPs/EIPS/eip-7702) transactions. Eventually this can be expanded to all verifier types.

### Why Account Lock?

Locked accounts have a frozen owner set, so the primary state that can invalidate a validated transaction is nonce consumption. This can enable nodes to cache owner state and apply higher mempool rate limits (see [Mempool Acceptance](#mempool-acceptance)). A per-owner lock alternative was considered but adds mempool tracking complexity — rate limits per `(address, ownerId)` pair rather than per address.

### Why One Slot Per Owner?

The protocol reads everything it needs for authorization and scope checking in one SLOAD. Reserved bytes provide an extension path for future protocol-level owner policy.

### Why Owner Scope?

Without scope, all owners have equal authority — any owner can sign as sender, approve gas payment, appear through ERC-1271, and authorize config changes. This is insufficient when accounts have owners serving different roles, like for example running a payer for ERC-20 tokens.

The `0x00` = unrestricted default ensures backward compatibility.

### Why No Public Key Storage?

Public keys are not stored in the Account Configuration Contract. Instead, owners are identified by `ownerId` (bytes32) and public key material is provided at signing time in the verifier-specific `data` portion of the signature. This design is motivated by three factors:

- **State growth**: Public key storage is permanent state growth. For PQ keys (1,000+ bytes), this means 40+ storage slots per owner. Calldata goes to data availability (temporary); storage is permanent. The trend is toward higher SLOAD costs and cheaper DA.
- **Gas efficiency**: Calldata is cheaper than cold SLOADs for all key sizes. P256: ~2,048 gas calldata vs ~6,300 gas cold SLOADs. PQ: ~21,000 gas calldata vs ~88,000 gas cold SLOADs.
- **Simplicity**: One storage slot per owner (`owner_config`). No variable-length public key encoding, no multi-slot reads, no length fields. Registration is a single SSTORE.

The protocol never needs to know how any algorithm works.

### Why bytes32 ownerId?

The full 32-byte keccak256 output provides ~2^85 quantum collision resistance (vs ~2^53 for bytes20 via BHT), which is adequate for post-quantum keys. It also fits a single storage slot and aligns with keccak256 output without truncation.

#### ownerId Conventions

Each verifier defines how it derives `ownerId` from signature data.

## Backwards Compatibility

No breaking changes. Existing EOAs and smart contracts function unchanged. Adoption is opt-in:

- EOAs continue sending standard transactions
- ERC-4337 infrastructure continues operating
- Accounts gain AA capabilities by configuring owners. EOAs sending their first AA transaction are auto-delegated to `DEFAULT_ACCOUNT_ADDRESS` if they have no code. EOAs MAY override with a delegation entry in `account_changes` (EOA-only authorization), a standard [EIP-7702](/EIPs/EIPS/eip-7702) transaction, or use a create entry in `account_changes` for custom wallet implementations

## Reference Implementation

### IAccountConfiguration

```solidity
interface IAccountConfiguration {
    struct ChangeSequences {
        uint64 multichain; // chain_id 0
        uint64 local;      // chain_id == block.chainid
    }

    struct OwnerConfig {
        address verifier;
        uint8 scopes;      // 0x00 = unrestricted
    }

    struct Owner {
        bytes32 ownerId;
        OwnerConfig config;
    }

    struct OwnerChange {
        bytes32 ownerId;
        uint8 changeType;  // 0x01 = authorizeOwner, 0x02 = revokeOwner
        bytes configData;  // OwnerConfig for authorize, empty for revoke
    }

    event OwnerAuthorized(address indexed account, bytes32 indexed ownerId, OwnerConfig config);
    event OwnerRevoked(address indexed account, bytes32 indexed ownerId);
    event AccountCreated(address indexed account, bytes32 userSalt, bytes32 codeHash);
    event AccountImported(address indexed account);
    event DelegationApplied(address indexed account, address target);
    event AccountLocked(address indexed account, uint16 unlockDelay);
    event AccountUnlockInitiated(address indexed account, uint40 unlocksAt);

    // Account creation (factory)
    function createAccount(bytes32 userSalt, bytes calldata bytecode, Owner[] calldata initialOwners) external returns (address);
    function computeAddress(bytes32 userSalt, bytes calldata bytecode, Owner[] calldata initialOwners) external view returns (address);

    // Import existing account (ERC-1271 verification for initial owner registration)
    function importAccount(address account, Owner[] calldata initialOwners, bytes calldata signature) external;

    // Portable owner changes (direct verification via verifier + owner_config)
    function applySignedOwnerChanges(address account, uint64 chainId, OwnerChange[] calldata ownerChanges, bytes calldata auth) external;

    // Account lock (called by the account directly)
    function lock(uint16 unlockDelay) external;
    function initiateUnlock() external;

    // Signature verification
    function verifySignature(address account, bytes32 hash, bytes calldata signature) external view returns (bool verified);
    function verify(address account, bytes32 hash, bytes calldata auth) external view returns (uint8 scopes);

    // Storage views
    function isInitialized(address account) external view returns (bool);
    function isOwner(address account, bytes32 ownerId) external view returns (bool);
    function getOwnerConfig(address account, bytes32 ownerId) external view returns (OwnerConfig memory);
    function getChangeSequences(address account) external view returns (ChangeSequences memory);
    function isLocked(address account) external view returns (bool);
    function getLockStatus(address account) external view returns (bool locked, bool hasInitiatedUnlock, uint40 unlocksAt, uint16 unlockDelay);
}
```

### IVerifier

```solidity
interface IVerifier {
    function verify(
        bytes32 hash,
        bytes calldata data
    ) external view returns (bytes32 ownerId);
}
```

Stateful verifiers MAY read from the Transaction Context precompile or other state (see [Transaction Context](#transaction-context)). When called outside of an 8130 transaction (e.g., `verifySignature()` in a legacy transaction), the Transaction Context precompile returns zero/default values, so verifiers that depend on it naturally reject those calls.

### ITxContext (Precompile)

```solidity
struct Call {
    address to;
    bytes data;
}

interface ITxContext {
    function getSender() external view returns (address);
    function getPayer() external view returns (address);
    function getOwnerId() external view returns (bytes32);
    function getCalls() external view returns (Call[][] memory);
    function getMaxCost() external view returns (uint256);
    function getGasLimit() external view returns (uint256);
}
```

Read-only. Gas is charged as a base cost plus 3 gas per 32 bytes of returned data.

### INonceManager (Precompile)

```solidity
interface INonceManager {
    function getNonce(address account, uint256 nonceKey) external view returns (uint64);
}
```

Read-only. The protocol manages nonce storage directly; there are no state-modifying functions.

## Security Considerations

**Validation Surface**: For pure verifiers, invalidators are `owner_config` revocation and nonce consumption. Stateful verifiers additionally depend on traced state; invalidation tracking is a mempool concern.

**Replay Protection**: Transactions include `chain_id`, 2D nonce (`nonce_key`, `nonce_sequence`), and `expiry`. For `NONCE_KEY_MAX` (nonce-free mode), replay protection relies on short-lived `expiry` and transaction-hash deduplication. The mempool enforces a tight expiry window (e.g., 10-30 seconds) to bound the window. Block builders MUST NOT include duplicate `NONCE_KEY_MAX` transactions with the same hash.

**Owner Scope**: Protocol-enforced after verifier execution — a verifier cannot bypass scope checking.

**Owner Management**: Config change authorization requires CONFIG scope. The EOA owner is implicitly authorized with unrestricted scope; revocable via portable config change. All owner modification paths are blocked when the account is locked.

**ownerId Binding**: The protocol checks that the verifier&apos;s returned `ownerId` maps back to that verifier in `owner_config` — preventing a malicious verifier from claiming ownership of another verifier&apos;s owners.

**Payer Security**: `AA_TX_TYPE` vs `AA_PAYER_TYPE` domain separation prevents signature reuse between sender and payer roles. The `payer` field in the sender&apos;s signed hash binds to a specific payer address. Scope enforcement adds a second layer — PAYER-only owners cannot be used as `sender_auth`, and vice versa.

**Account Creation Security**: `initial_owners` (verifier + ownerId + scope tuples) are salt-committed, preventing front-running of owner assignment. Wallet bytecode should be inert when uninitialized as it can be permissionlessly deployed.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 14 Oct 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8130</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8130</guid>
      </item>
    
      <item>
        <title>Add Auth Data to EIP-7623 Floor</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-9999-add-auth-data-to-eip-7623-floor/12345</comments>
        
        <description>## Abstract

This EIP includes [EIP-7702](/EIPs/EIPS/eip-7702) authorization data in the [EIP-7623](/EIPs/EIPS/eip-7623) floor calculation, preventing circumvention of floor pricing through authorization lists.

## Motivation

[EIP-7702](/EIPs/EIPS/eip-7702) authorization tuples are priced for execution (`PER_EMPTY_ACCOUNT_COST = 25,000` gas per authorization) but do not contribute to the [EIP-7623](/EIPs/EIPS/eip-7623) floor calculation.

This enables achieving ~9% larger blocks than intended by combining calldata with authorization data at an optimal ratio, circumventing the floor pricing mechanism.

## Specification

| Parameter | Value | Source |
|-----------|-------|--------|
| `TOTAL_COST_FLOOR_PER_TOKEN` | `10` | [EIP-7623](/EIPs/EIPS/eip-7623) |
| `FLOOR_COST_PER_AUTH` | `4040` | 101 bytes × 4 tokens × 10 gas |
| `PER_EMPTY_ACCOUNT_COST` | `25000` | [EIP-7702](/EIPs/EIPS/eip-7702) |

The [EIP-7623](/EIPs/EIPS/eip-7623) floor calculation is modified to include authorization data:

```python
tokens_in_calldata = zero_bytes_in_calldata + nonzero_bytes_in_calldata * 4

floor_gas = (
    TX_BASE_COST
    + TOTAL_COST_FLOOR_PER_TOKEN * tokens_in_calldata
    + FLOOR_COST_PER_AUTH * num_authorizations
)
```

The gas used calculation becomes:

```python
tx.gasUsed = (
    21000
    +
    max(
        STANDARD_TOKEN_COST * tokens_in_calldata
        + execution_gas_used
        + isContractCreation * (32000 + INITCODE_WORD_COST * words(calldata))
        + access_list_cost
        + PER_EMPTY_ACCOUNT_COST * num_authorizations,
        TOTAL_COST_FLOOR_PER_TOKEN * tokens_in_calldata
        + FLOOR_COST_PER_AUTH * num_authorizations
    )
)
```

Any transaction with a gas limit below `floor_gas` or below its intrinsic gas cost is considered invalid.

## Rationale

### Flat Cost Per Authorization

Each authorization is charged a flat `FLOOR_COST_PER_AUTH = 4040` gas toward the floor, derived from:

- 101 bytes per authorization tuple (as specified in [EIP-7702](/EIPs/EIPS/eip-7702))
- 4 tokens per byte (treating all bytes as non-zero)
- 10 gas per token (`TOTAL_COST_FLOOR_PER_TOKEN`)

This conservative approach avoids byte-level zero/non-zero accounting while ensuring authorization data is properly reflected in the floor calculation.

### Floor-Only Modification

Authorization costs are added to the floor calculation only, not to intrinsic gas. This differs from [EIP-7981](/EIPs/EIPS/eip-7981) (access lists) because:

- Authorization execution cost (25,000 gas) far exceeds floor contribution (4,040 gas per auth)
- Floor-only modification is sufficient to prevent bypass

With this change:

- Authorization data contributes to the floor path
- High-execution transactions remain unaffected (execution exceeds floor)
- Data-heavy transactions cannot use authorizations to bypass floor pricing

## Backwards Compatibility

This is a backwards incompatible gas repricing that requires a scheduled network upgrade.

Requires updates to gas estimation in wallets and nodes. Normal usage patterns remain largely unaffected since authorization execution cost typically dominates the floor contribution.

## Test Cases

### Case 1: Transaction with Authorizations Only

- Calldata: 0 bytes
- Authorizations: 10

Old floor: 21,000 gas
New floor: 21,000 + 10 × 4,040 = 61,400 gas
Execution: 10 × 25,000 = 250,000 gas
Result: Pay execution (250,000) - unchanged, execution dominates

### Case 2: Bypass Attempt (Now Blocked)

- Calldata: 100,000 bytes (400,000 tokens)
- Authorizations: 100

Old floor: 21,000 + 400,000 × 10 = 4,021,000 gas
New floor: 21,000 + 400,000 × 10 + 100 × 4,040 = 4,425,000 gas
Execution: 21,000 + 1,600,000 + 2,500,000 = 4,121,000 gas
Result: Pay new floor (4,425,000) - bypass blocked

## Reference Implementation

```python
FLOOR_COST_PER_AUTH = 4040  # 101 bytes * 4 tokens/byte * 10 gas/token


def calculate_intrinsic_cost(tx: Transaction) -&gt; Tuple[Uint, Uint]:
    &quot;&quot;&quot;
    Calculate intrinsic gas cost and floor gas cost.
    Returns (intrinsic_gas, floor_gas).
    &quot;&quot;&quot;
    # Calldata tokens
    calldata_zero = sum(1 for b in tx.data if b == 0)
    tokens_in_calldata = Uint(calldata_zero + (len(tx.data) - calldata_zero) * 4)

    # Authorization costs
    num_authorizations = Uint(0)
    auth_exec_cost = Uint(0)
    if isinstance(tx, SetCodeTransaction):
        num_authorizations = Uint(len(tx.authorizations))
        auth_exec_cost = PER_EMPTY_ACCOUNT_COST * num_authorizations

    # Floor: calldata + flat cost per authorization
    floor_gas = (
        TX_BASE_COST
        + tokens_in_calldata * TOTAL_COST_FLOOR_PER_TOKEN
        + num_authorizations * FLOOR_COST_PER_AUTH
    )

    # Intrinsic: calldata + authorization execution cost
    calldata_cost = tokens_in_calldata * STANDARD_TOKEN_COST
    intrinsic_gas = TX_BASE_COST + calldata_cost + access_list_cost + auth_exec_cost

    return intrinsic_gas, floor_gas
```

## Security Considerations

This EIP closes a loophole that allows circumventing [EIP-7623](/EIPs/EIPS/eip-7623) floor pricing. Without this fix, adversaries can achieve ~9% larger blocks by combining calldata with authorization data.

### Interaction with EIP-7981

If [EIP-7981](/EIPs/EIPS/eip-7981) is also adopted, both EIPs work together: access list tokens and authorization tokens are both included in the floor calculation. There are no conflicts.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 21 Jan 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8131</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8131</guid>
      </item>
    
      <item>
        <title>Upgrade Nomenclature</title>
        <category>Informational/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8133-upgrade-nomenclature/27575</comments>
        
        <description>## Abstract

This EIP documents the naming conventions used for Ethereum network upgrades across the Execution Layer, Consensus Layer, post-Merge combined upgrades, and Blob-Parameter-Only upgrades. It provides a canonical reference for how upgrade names have evolved to improve clarity, consistency, and shared understanding across the ecosystem.

In brief: early upgrades used thematic or milestone-based names; subsequent Execution Layer upgrades are named after Devcon/Devconnect host cities; Consensus Layer upgrades follow an alphabetical sequence of star names; post-Merge combined upgrades MAY adopt a portmanteau of the two layer names; and Blob-Parameter-Only upgrades use a sequential numeric identifier (`BPO&lt;n&gt;`).

## Motivation

Ethereum has undergone multiple major network upgrades, including the transition from Proof of Work to Proof of Stake. Each upgrade has been assigned a distinct and meaningful name, and after the initial upgrades, consistent naming patterns emerged and continue to be followed.

As upgrades now occur more frequently and span multiple protocol layers, it can become difficult to consistently interpret upgrade names and their relationships. This EIP documents existing naming conventions to provide a canonical reference for Ethereum upgrade nomenclature, improving clarity, reducing ambiguity, and supporting consistent communication and coordination across the ecosystem without constraining future naming decisions.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

Ethereum upgrade naming conventions have evolved alongside protocol architecture, governance maturity, and coordination practices. Early upgrades followed planned development phases (**Frontier**, **Homestead**, **Metropolis**, and **Serenity**), reflecting milestones toward a stable, production-ready network. After the Merge, naming conventions began reflecting the separation between the Execution Layer (EL) and Consensus Layer (CL).

This section documents the observed evolution of upgrade naming conventions.

### Early Upgrade Naming

Early Ethereum upgrades used names that reflected the experimental state of the network, major milestones, or thematic concepts associated with shipped functionality.

Observed upgrades include:

* **Frontier (Genesis)**
* **Frontier Thawing**: 
* **[Homestead](/EIPs/EIPS/eip-606)**
* **[DAO Fork (DAO Wars - aborted)](/EIPs/EIPS/eip-779)**
* **[Tangerine Whistle](/EIPs/EIPS/eip-608)**
* **[Spurious Dragon](/EIPs/EIPS/eip-607)**

These names reflect the exploratory nature of early protocol development.

### Historic City Naming

During the Metropolis development phase, upgrades adopted names based on historically connected cities to provide consistency and symbolic continuity. The naming reflected Ethereum’s transition toward a more mature, user-friendly platform.

Observed upgrades include:

* **[Byzantium](/EIPs/EIPS/eip-609)**
* **[Constantinople](/EIPs/EIPS/eip-1013)**
* **[St. Petersburg](/EIPs/EIPS/eip-1716)**
* **[Istanbul](/EIPs/EIPS/eip-1679)**

This convention standardized naming during frequent upgrade cycles.

### Ice Age / Difficulty Bomb Naming

Upgrades primarily targeting the Difficulty Bomb adopted glacier-themed naming to reflect mining difficulty progression.

Observed upgrades include:

* **[Muir Glacier](/EIPs/EIPS/eip-2387)**
* **[Arrow Glacier](https://github.com/ethereum/execution-specs/blob/8dbde99b132ff8d8fcc9cfb015a9947ccc8b12d6/network-upgrades/mainnet-upgrades/arrow-glacier.md)**
* **[Gray Glacier](https://github.com/ethereum/execution-specs/blob/8dbde99b132ff8d8fcc9cfb015a9947ccc8b12d6/network-upgrades/mainnet-upgrades/gray-glacier.md)**

These names signaled functional scope rather than feature expansion.

### Execution Layer Upgrade Naming

Execution Layer upgrades MAY be named after the host city of a Devcon or Devconnect conference. The convention originated with Devcon host cities and later expanded to include Devconnect host cities.

One exception applies: the Merge included **Paris** as a reference to EthCC to commemorate the first biggest Ethereum Community Conference.

Observed examples include:

* **[Berlin](https://github.com/ethereum/execution-specs/blob/8dbde99b132ff8d8fcc9cfb015a9947ccc8b12d6/network-upgrades/mainnet-upgrades/berlin.md)** - Devcon 0  
* **[London](https://github.com/ethereum/execution-specs/blob/8dbde99b132ff8d8fcc9cfb015a9947ccc8b12d6/network-upgrades/mainnet-upgrades/london.md)** - Devcon 1  
* **[Paris](https://github.com/ethereum/execution-specs/blob/8dbde99b132ff8d8fcc9cfb015a9947ccc8b12d6/network-upgrades/mainnet-upgrades/paris.md)** - EthCC  
* **[Shanghai](https://github.com/ethereum/execution-specs/blob/8dbde99b132ff8d8fcc9cfb015a9947ccc8b12d6/network-upgrades/mainnet-upgrades/shanghai.md)** - Devcon 2 
* **Cancún** - Devcon 3  
* **Prague** - Devcon 4  
* **Osaka** - Devcon 5  
* **Amsterdam** - Devconnect 1  
* **Bogotá** - Devcon 6  

Additional past and announced event host cities include, but are not limited to, *Istanbul, Bangkok, Buenos Aires and Mumbai*.

Future Execution Layer upgrade names MAY continue referencing Devcon or Devconnect host cities.

This convention provides geographic neutrality, cultural diversity, and predictable sequencing for roadmap planning and external communication.

### Consensus Layer Upgrade Naming

Following the Serenity roadmap phase and the launch of the Beacon Chain, Consensus Layer network upgrades adopt a naming convention based on star names in alphabetical order.

Consensus Layer (formerly Eth2 / Beacon Chain) upgrades MUST be named after stars, with each upgrade name advancing alphabetically by first letter.

Each selected name MUST correspond to a recognized star name based on rough consensus. This convention was established through open community coordination to provide a consistent, neutral, and globally recognizable naming scheme.

The sequence begins with **[Altair](https://github.com/ethereum/consensus-specs/blob/67fd7979ffd705bd6b0b5c1aaa842a445cc74d9a/README.md#altair)**, activated in October 2021 as the first Consensus Layer upgrade, which established the star-based naming convention and serves as the reference point for all subsequent upgrades, followed in alphabetical order by names including but not limited to **[Bellatrix](https://github.com/ethereum/consensus-specs/blob/f8ae982c2fc7dbb03a3c95a638da4486310e09e9/README.md#stable-specifications)**, **[Capella](https://github.com/ethereum/consensus-specs/blob/01b53691dcc36d37a5ad8994b3a32d8de69fb1aa/README.md#stable-specifications)**, **[Deneb](https://github.com/ethereum/consensus-specs/blob/65b74bb2b7fc5e22f10aa1b9c0278be11f8960f7/specs/deneb)**, **[Electra](https://github.com/ethereum/consensus-specs/blob/65b74bb2b7fc5e22f10aa1b9c0278be11f8960f7/specs/electra)**, **[Fulu](https://github.com/ethereum/consensus-specs/blob/65b74bb2b7fc5e22f10aa1b9c0278be11f8960f7/specs/fulu)**, **[Gloas](https://github.com/ethereum/consensus-specs/blob/65b74bb2b7fc5e22f10aa1b9c0278be11f8960f7/specs/gloas)**, and **Heze**.

This convention provides predictable sequencing of upgrades, clear differentiation between Consensus Layer and Execution Layer upgrades, long-term scalability without name reuse or ambiguity, and a shared vocabulary across protocol developers, client teams, researchers, operators, and ecosystem participants.

### The Merge (Special Case)

The Merge is a special case in Ethereum upgrade naming and activation semantics.

Unlike subsequent post-Merge upgrades, where Execution Layer (EL) and Consensus Layer (CL) upgrades may activate simultaneously and MAY adopt a combined portmanteau name, the Merge was executed through a staged activation process and did not adopt a combined name.

The Consensus Layer upgrade **Bellatrix** activated on the Beacon Chain on September 6, 2022 (Epoch 144896). Bellatrix enabled the Beacon Chain to recognize and coordinate the upcoming Execution Layer transition.

The Execution Layer upgrade **Paris** activated on September 15, 2022 at 06:42 UTC, when the network reached the predefined Terminal Total Difficulty (TTD). This activation finalized the transition of Ethereum mainnet from Proof-of-Work to Proof-of-Stake at block 15,537,393.

Although the protocol transition **completed on September 15, 2022**, the Merge process was operationally initiated by the Bellatrix upgrade on September 6, 2022.

The upgrade is canonically referred to as The Merge. No combined portmanteau name was adopted for this event.

Future simultaneous EL and CL upgrades follow the combined naming convention defined in the Combined Upgrade Naming section.

### Combined Upgrade Naming

Following the Merge, Execution Layer and Consensus Layer upgrades MAY activate simultaneously within a single network upgrade.

When simultaneous activation occurs, each layer retains its independent naming convention. The ecosystem MAY additionally adopt a combined portmanteau name derived from the Execution Layer upgrade name and the Consensus Layer upgrade name to simplify external communication and coordination.

The combined name is informational only and MUST NOT replace the canonical layer-specific upgrade names used in specifications, client implementations, or protocol documentation.

Observed examples include:

* **Shapella**:  derived from **Sha**nghai (EL) and Ca**pella** (CL)
* **[Dencún](/EIPs/EIPS/eip-7569)**: **Den**eb (CL) and Can**cún** (EL)
* **[Pectra](/EIPs/EIPS/eip-7600)**:  **P**rague (EL) and El**ectr**a (CL)
* **[Fusaka](/EIPs/EIPS/eip-7607)**: **Fu**lu (CL) and O**saka** (EL)
* **Glamsterdam**: **Gl**oas (CL) and **Amsterdam** (EL)
* **Hegotá**: **He**ka (CL) and Bo**gotá** (Execution Layer)

Additional combined names MAY be adopted in future upgrades following the same convention.

### Blob-Parameter-Only Upgrade Naming

Blob-Parameter-Only upgrades (BPO upgrades) are network upgrades whose scope is limited to modifying blob-related parameters, including blob target and maximum limits, without introducing additional protocol changes.

BPO upgrades support Ethereum’s data availability scaling objectives under the Surge roadmap by enabling incremental capacity increases with reduced operational risk.

BPO upgrades MUST be named using a sequential numeric identifier in the format BPO&amp;lt;n&amp;gt;, where `n` is a monotonically increasing positive integer starting from 1.

The naming intentionally avoids descriptive or thematic labels. Sequential numbering preserves direct ordinal mapping, minimizes naming indirection, and reflects the single-purpose and templated nature of these upgrades.

The BPO naming convention is specified in [EIP-7892](/EIPs/EIPS/eip-7892) and applies exclusively to upgrades limited to blob parameter adjustments.

Observed examples include:

* BPO1 
* BPO2 
* BPO3 

BPO upgrades MAY be deployed independently or alongside larger multi-change upgrades. The numeric identifier remains the canonical reference.

## Rationale

### Why These Names?

**Early upgrades** used thematic or milestone-inspired names reflecting the state of the network at launch. &quot;Frontier&quot; conveyed an experimental frontier environment for developers; &quot;Homestead&quot; signaled a transition to a more stable and production-ready network; &quot;Tangerine Whistle&quot; emphasized urgency (an emergency whistle), deployed to mitigate active denial-of-service attacks; &quot;Spurious Dragon&quot; reflected the goal of removing millions of &quot;spurious&quot; (empty) accounts created during those attacks.

**Historic city upgrades** followed Ethereum&apos;s Metropolis development phase. Byzantium, Constantinople, St. Petersburg, and Istanbul form a historically connected sequence—Byzantium became Constantinople, which became Istanbul—symbolizing the staged maturation of the protocol. Constantinople and St. Petersburg were activated at the same block height, with St. Petersburg ensuring the removal of [EIP-1283](/EIPs/EIPS/eip-1283).

**Glacier upgrades** used names of real, retreating glaciers (Muir, Arrow, Gray) to symbolize temporary measures slowing the &quot;Ice Age&quot; difficulty bomb, buying time for the Proof-of-Stake transition. Gray Glacier merges into another glacier, a subtle nod to Ethereum&apos;s imminent Merge.

**Execution Layer city names** provide geographic neutrality, cultural diversity, and predictable sequencing tied to the global Devcon/Devconnect event calendar. 

**Consensus Layer star names** provide a consistent, politically neutral, globally recognizable naming scheme with a natural alphabetical ordering that ensures long-term scalability without name reuse.

**Combined portmanteau names** (e.g., Shapella, Dencún, Pectra) are informational conveniences for ecosystem communication. They do not replace the canonical layer-specific names used in specifications and client implementations.

**BPO numeric identifiers** reflect the single-purpose, templated nature of blob-parameter-only upgrades. Descriptive or thematic names would add indirection without benefit; sequential numbering preserves direct ordinal mapping.

As the protocol matures and the cadence of upgrades increases, documenting naming conventions helps reduce ambiguity, limit speculation, and provide clearer expectations around upgrade naming. A well-defined reference improves transparency, strengthens shared understanding, and supports informed participation and coordination.

This EIP does not establish binding authority over future naming decisions. It documents established conventions and current practice. Future upgrade naming remains governed by community coordination and can be found in upgrade-specific Meta EIPs.

## Backwards Compatibility

This EIP is informational and introduces no protocol changes.

## Security Considerations

None.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 23 Jan 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8133</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8133</guid>
      </item>
    
      <item>
        <title>Hardfork Meta - BPO1</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8134-hardfork-meta-bpo1/27582</comments>
        
        <description>## Abstract

This Meta EIP documents the activation details, parameter changes, and specification references for the first Blob-Parameter-Only (BPO) network upgrades, BPO1. It provides a canonical registry of blob targets, blob maximum limits, and associated configuration values to improve transparency, traceability, and ecosystem coordination for early-stage data availability scaling under Ethereum’s Surge roadmap.

## Motivation 

Blob-Parameter-Only (BPO) upgrades enable Ethereum to scale data availability through incremental parameter adjustments rather than large multi-feature network upgrades. While this approach improves safety and iteration speed, there is currently no canonical reference documenting what changed in each BPO upgrade, when it was activated, and which parameter values were applied.

[EIP-7892](/EIPs/EIPS/eip-7892) specifies the mechanism and constraints for BPO upgrades but does not track individual BPO instances. In practice, activation timing and parameter values for BPO1 are distributed across client repositories, coordination notes, and operational artifacts, making consistent interpretation and historical analysis difficult for ecosystem participants.

This EIP addresses this gap by recording authoritative data for BPO1 in a canonical reference to improve transparency, traceability, and ecosystem coordination.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

This section documents the Blob-Parameter-Only upgrade identified as **BPO1**.

The upgrade modifies blob-related protocol parameters as defined in [EIP-7892](/EIPs/EIPS/eip-7892). No other protocol behavior is affected. All timestamps are expressed as Unix epoch seconds (UTC).

### BPO1 Parameters

| Field                    | Value      |
|--------------------------|------------|
| BPO Identifier           | BPO1       |
| Activation Time (UTC)    | 1765290071  |
| Blob Target              | 10          |
| Blob Max                 | 15          |
| Base Fee Update Fraction | 8,346,193   |

BPO1 represents the first mainnet deployment of a Blob-Parameter-Only upgrade and establishes the initial incremental increase in blob capacity following the Fusaka upgrade.

### Historical Context

For reference, the blob schedule before BPO upgrades was established in earlier network upgrades:

| Upgrade | Blob Target | Blob Max | Base Fee Update Fraction |
|---------|-------------|----------|---------------------------|
| **Cancun** | 3 | 6 | 3,338,477 |
| **Prague** | 6 | 9 | 5,007,716 |

### Data Source

The parameter values and activation times in this EIP are derived from eth_client genesis configuration, including:

```json
&quot;bpo1Time&quot;: 1765290071,
&quot;blobSchedule&quot;: {
  &quot;cancun&quot;: {
    &quot;target&quot;: 3,
    &quot;max&quot;: 6,
    &quot;baseFeeUpdateFraction&quot;: 3338477
  },
  &quot;prague&quot;: {
    &quot;target&quot;: 6,
    &quot;max&quot;: 9,
    &quot;baseFeeUpdateFraction&quot;: 5007716
  },
  &quot;bpo1&quot;: {
    &quot;target&quot;: 10,
    &quot;max&quot;: 15,
    &quot;baseFeeUpdateFraction&quot;: 8346193
  },
}
```

Client implementations may expose these values in different formats; this EIP reflects the canonical mainnet configuration values.

## Rationale

BPO1 formalizes the first post-Fusaka adjustment to blob parameters, providing a controlled expansion of blob capacity to support empirical evaluation under mainnet conditions. This change enables the network to collect real-world performance data across clients, validators, and proposers, supporting evidence-based assessment of slot stability and system behavior before any further scaling decisions. Documenting BPO1 as a standalone parameter update improves transparency and process clarity by establishing an authoritative record of blob parameter changes. 

## Security Considerations

BPO upgrades may impact network load characteristics. Careful monitoring, staged rollout, and ecosystem coordination are required to ensure stability.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8134</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8134</guid>
      </item>
    
      <item>
        <title>Hardfork Meta - BPO2</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8135-hardfork-meta-bpo2/27605</comments>
        
        <description>## Abstract

This Meta EIP documents the activation details, parameter changes, and specification references for the second Blob-Parameter-Only (BPO) network upgrade, **BPO2**. It provides a canonical reference of blob target, blob maximum limits, and associated configuration values, enabling transparent tracking of incremental data availability scaling following BPO1 under Ethereum’s Surge roadmap.

## Motivation

Following the publication of the Meta EIP documenting **[BPO1](./eip-8134)**, this EIP extends the registry approach to **BPO2**, preserving continuity and enabling historical accuracy of blob capacity increases.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

This section documents the Blob-Parameter-Only upgrade identified as **BPO2**.

The upgrade modifies blob-related protocol parameters as defined in [EIP-7892](./eip-7892). No other protocol behavior is affected. All timestamps are expressed as Unix epoch seconds (UTC).

### BPO2 Parameters

| Field                    | Value       |
|--------------------------|-------------|
| BPO Identifier           | BPO2        |
| Activation Time (UTC)    | 1767747671  |
| Blob Target              | 14          |
| Blob Max                 | 21          |
| Base Fee Update Fraction | 11,684,671  |

BPO2 represents the second incremental blob capacity increase following BPO1 and continues staged scaling toward higher data availability limits.

### Historical Context

For reference, prior blob schedules were established in earlier network upgrades and BPO1:

| Upgrade | Blob Target | Blob Max | Base Fee Update Fraction |
|---------|-------------|----------|---------------------------|
| **BPO1**   | 10 | 15 | 8,346,193 |
| **Prague** | 6  | 9  | 5,007,716 |
| **Cancun** | 3  | 6  | 3,338,477 |

BPO2 builds directly on the BPO1 parameter baseline.

### Data Source

The parameter values and activation times in this EIP are derived from eth client genesis configuration, including:

```json
&quot;bpo2Time&quot;: 1767747671,
&quot;blobSchedule&quot;: {
  &quot;bpo2&quot;: {
    &quot;target&quot;: 14,
    &quot;max&quot;: 21,
    &quot;baseFeeUpdateFraction&quot;: 11684671
  }
}
```

Client implementations may expose these values in different formats; this EIP reflects the canonical mainnet configuration values.

## Rationale

Following BPO1, observations indicated that the network could tolerate increased blob limits, but did not yet provide sufficient data across a wider operating range. BPO2 extends blob parameters as part of the same incremental scaling approach, enabling further observation of network behavior under higher blob loads.

BPO2 is intended to collect additional empirical data on blob processing, slot reliability, and overall network stability. It is not motivated by demonstrated demand, but by the need to evaluate system limits in a controlled manner while retaining the ability to pause or adjust parameters based on observed outcomes.

## Security Considerations

BPO upgrades adjust blob throughput parameters and may impact network load characteristics. Careful monitoring, staged rollout, and ecosystem coordination are required to ensure stability.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 24 Jan 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8135</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8135</guid>
      </item>
    
      <item>
        <title>Cell-Level Deltas for Data Column Broadcast</title>
        <category>Standards Track/Networking</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8136-cell-level-deltas-for-data-column-broadcast/27675</comments>
        
        <description>## Abstract

Cell-Level Deltas for Data Column Broadcast optimizes PeerDAS (EIP-7594) 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.

## Motivation

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.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

Cell-Level Deltas uses Gossipsub&apos;s Partial Messages Extension to
exchange cell bitmaps and request/provide cells.
&lt;!--TODO: link to final spec above: (https://github.com/libp2p/specs/pull/685)--&gt;

*Editor&apos;s Note*: Update the libp2p spec link to a proper commit once the PR is merged.

In an effort to maintain a single source of truth, the specification is defined
in the ethereum/consensus-specs repo.
&lt;!-- TODO: link to final spec: [ethereum/consensus-specs](https://github.com/ethereum/consensus-specs/pull/4558)--&gt;

*Editor&apos;s Note*: Update the Consensus Spec link to a proper commit once the PR is merged.

## Rationale

The design is guided by two main factors:

1. Minimal semantic changes.
2. Backwards compatible (no hard fork required).

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&apos;s gossipsub peers support this
extension they can both make use of it. Otherwise, the behavior falls back to
traditional gossipsub.

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.

### Alternative Designs

1. Smaller gossipsub messages.

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 `IDONTWANT`) 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&apos;t have or prioritize cells from a block it&apos;s processing.

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.

2. A new RPC method.

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.

3. A new protocol separate from gossipsub.

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&apos;d like to
deploy this without a hard fork.

## Backwards Compatibility

No backward compatibility issues.

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.

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.

## Security Considerations

In the default case, this adds minor latency to cell dissemination compared to
the standard gossipsub&apos;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.

There are also a couple implementation specific pitfalls client implementers and
gossipsub implementers should be aware of.

1. 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.
2. Related to the above, a peer&apos;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.
3. 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.

This optimization is expected to roll out gradually with the ability to roll
back if needed.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Hardfork Meta - BPO3</title>
        <category>Meta/</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8138-hardfork-meta-bpo3/27606</comments>
        
        <description>## Abstract

This Meta EIP documents a subsequent adjustment to Ethereum’s blob parameters using the Blob-Parameter-Only (BPO) update mechanism. The proposal specifies updated target and maximum blob limits to be applied without a full network upgrade, enabling continued evaluation of blob processing behavior under revised operational conditions. The change is intended to support ongoing measurement of network performance, reliability, and capacity characteristics, and to inform future data-availability scaling decisions based on observed mainnet behavior. The **BPO3** specification provides a canonical reference of blob target, blob maximum limits, and associated configuration values, enabling transparent tracking of incremental data availability scaling following [BPO2](./eip-8135).

## Motivation

Following the publication of Meta EIPs documenting BPO1 and BPO2, this EIP extends the reference approach to BPO3, preserving continuity and enabling longitudinal comparison of blob capacity increases.

This EIP records authoritative data for BPO3, including activation parameters and the deterministic derivation rule used for blob scaling, to improve traceability, ecosystem coordination, and historical accuracy. For BPO3, the Blob Target is set to the previous upgrade’s Blob Maximum, and the Blob Maximum is calculated as 1.5× the Blob Target, rounded up, resulting in a Blob Target and a Blob Maximum. Documenting both the resulting parameter values and the derivation rule improves predictability for client implementations, tooling, capacity planning, and longitudinal analysis of blob scaling behavior across successive BPO upgrades.

## Specification

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.

This section documents the Blob-Parameter-Only upgrade identified as **BPO3**.

The upgrade modifies blob-related protocol parameters as defined in [EIP-7892](./eip-7892). No other protocol behavior is affected. All timestamps are expressed as Unix epoch seconds (UTC).

### BPO-3 Parameters

| Field | Value |
|--------|--------|
| BPO Identifier | BPO3 |
| Activation Time (UTC) | &lt;!-- TODO --&gt; |
| Blob Target | &lt;!-- TODO --&gt; |
| Blob Max | &lt;!-- TODO --&gt; |
| Base Fee Update Fraction | &lt;!-- TODO --&gt; |

BPO3 represents the third incremental blob capacity adjustment following BPO2 and continues staged scaling toward higher data availability limits.

### Historical Context

For reference, prior blob schedules were established in earlier network upgrades and BPO upgrades:

| Upgrade | Blob Target | Blob Max | Base Fee Update Fraction |
|------------|--------------|-----------|----------------------------|
| BPO2 | 14 | 21 | 11,684,671 |
| BPO1 | 10 | 15 | 8,346,193 |
| Prague | 6 | 9 | 5,007,716 |
| Cancun | 3 | 6 | 3,338,477 |

BPO3 builds directly on the BPO2 parameter baseline.

### Data Source

The parameter values and activation time for BPO3 will be derived from Ethereum client configuration once finalized.

Example (placeholder only):

```json
&quot;bpo3Time&quot;: &lt;!-- TODO --&gt;,
&quot;blobSchedule&quot;: {
  &quot;bpo3&quot;: {
    &quot;target&quot;: &lt;!-- TODO --&gt;,
    &quot;max&quot;: &lt;!-- TODO --&gt;,
    &quot;baseFeeUpdateFraction&quot;: &lt;!-- TODO --&gt;
  }
}
```

Client implementations may expose these values in different formats; this EIP will reflect the canonical mainnet configuration once confirmed.

## Rationale

BPO3 adjusts blob throughput by increasing/decreasing the Blob Target and the Blob Maximum, continuing the staged scaling model established by prior BPO upgrades. Capturing these values in a dedicated Meta EIP provides a stable reference for implementers, tooling developers, researchers, and infrastructure operators who depend on accurate parameter baselines. Documenting this information reduces ambiguity across client implementations, supports consistent monitoring and benchmarking, and enables longitudinal analysis of data availability growth as Ethereum progresses through its scaling roadmap.

## Backwards Compatibility

&lt;!--
  TODO
--&gt;

## Test Cases

&lt;!--
  TODO
--&gt;

## Reference Implementation

&lt;!--
  TODO
--&gt;

## Security Considerations

BPO upgrades adjust blob throughput parameters and may impact network load characteristics. Careful monitoring, staged rollout, and ecosystem coordination are required to ensure stability.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 27 Jan 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8138</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8138</guid>
      </item>
    
      <item>
        <title>Frame Transaction</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/frame-transaction/27617</comments>
        
        <description>## Abstract

Add a new transaction whose validity and gas payment can be defined abstractly. Instead of relying solely on a single ECDSA signature, accounts may freely define and interpret their signature scheme using any cryptographic system.

## Motivation

This new transaction provides a native off-ramp from the elliptic curve based cryptographic system used to authenticate transactions today, to post-quantum (PQ) secure systems.

In doing so, it realizes the original vision of account abstraction: unlinking accounts from a prescribed ECDSA key and support alternative fee payment schemes. The assumption of an account simply becomes an address with code. It leverages the EVM to support arbitrary *user-defined* definitions of validation and gas payment.

## Specification

### Constants

| Name                      | Value           |
|---------------------------|-----------------|
| `FRAME_TX_TYPE`           | `0x06`          |
| `FRAME_TX_INTRINSIC_COST` | `15000`         |
| `FRAME_TX_PER_FRAME_COST` | `475`           |
| `ENTRY_POINT`             | `address(0xaa)` |
| `MAX_FRAMES`              | `64`            |

`ENTRY_POINT` is a protocol-defined distinguished caller address used for `DEFAULT` and `VERIFY` frames. It is not specified as a deployed contract or precompile, and contracts MUST NOT assume anything about its code, balance, or caller type beyond address equality. Contracts called from `DEFAULT` or `VERIFY` frames therefore observe `CALLER = ENTRY_POINT` and `CALLVALUE = 0`, so heuristics that infer EOA-or-contract properties from `CALLER` may not behave as expected. Its numeric equality with the `APPROVE` opcode value has no semantic significance.

### Opcodes

| Name            | Value  |
|-----------------|--------|
| `APPROVE`       | `0xaa` |
| `TXPARAM`       | `0xb0` |
| `FRAMEDATALOAD` | `0xb1` |
| `FRAMEDATACOPY` | `0xb2` |
| `FRAMEPARAM`    | `0xb3` |

### New Transaction Type

A new [EIP-2718](/EIPs/EIPS/eip-2718) transaction with type `FRAME_TX_TYPE` is introduced. Transactions of this type are referred to as &quot;Frame transactions&quot;.

The payload is defined as the RLP serialization of the following:

```
[chain_id, nonce, sender, frames, max_priority_fee_per_gas, max_fee_per_gas, max_fee_per_blob_gas, blob_versioned_hashes]

frames = [[mode, flags, target, gas_limit, value, data], ...]
```

If no blobs are included, `blob_versioned_hashes` must be an empty list and `max_fee_per_blob_gas` must be `0`.

Frame transactions do not include an [EIP-7702](/EIPs/EIPS/eip-7702) authorization list and do not set, clear, or otherwise modify EIP-7702 delegation indicators.

For execution semantics, each frame has a **resolved target**:

```python
resolved_target = frame.target if frame.target is not None else tx.sender
```

Unless otherwise stated, checks below that refer to the target account during execution use the resolved target.

Each frame also has a `value` field, interpreted as the top-level call value in wei. A non-zero `value` is valid only in `SENDER` mode; `DEFAULT` and `VERIFY` frames must set `value = 0`.

#### Frame Modes

The `mode` of each frame sets the context of execution. It allows the protocol to identify
the purpose of the frame within the execution loop.

| `mode`  | Name           | Summary                                    |
|---------|----------------|--------------------------------------------|
| 0       | `DEFAULT` mode | Execute frame as `ENTRY_POINT`             |
| 1       | `VERIFY` mode  | Frame identifies as transaction validation |
| 2       | `SENDER` mode  | Execute frame as `sender`                  |
| 3..255  | reserved       |

##### `DEFAULT` Mode

Frame executes as regular call where the caller address is `ENTRY_POINT`.

##### `VERIFY` Mode

Identifies the frame as a validation frame. Its purpose is to *verify* that a sender and/or payer authorized the transaction. It must call `APPROVE` during execution. Failure to do so will result in the whole transaction being invalid.

The execution behaves the same as `STATICCALL` for user code: state cannot otherwise be modified. The `APPROVE` opcode is the only exception and applies its protocol-defined effects, including approval updates and, for payment scopes, nonce increment and gas-charge collection.

Frames in this mode will have their data elided from signature hash calculation and from introspection by other frames.

##### `SENDER` Mode

Frame executes as regular call where the caller address is `sender`. This mode effectively acts on behalf of the transaction sender, can only be used after explicitly approved, and is the only mode that may send a non-zero `value`.

##### Frame Flags

The `flags` field configures additional execution constraints.

Bit positions in this specification are zero-based, with the least significant bit numbered `0`.

| Flag bits | Meaning                      | Valid with  |
|-----------|------------------------------| ----------- |
| 0-1       | Approval scope               | Any mode    |
| 2         | Atomic batch                 | SENDER mode |
| 3-7       | reserved, must be zero       |             |

The `Valid with` column indicates the mode under which the flag is valid.  If a flag is not valid under the current mode, the transaction is invalid.

#### Constraints

Some validity constraints can be determined statically. They are outlined below:

```python
# Constants (see Default Code section for full definitions)
VERIFY = 1
SENDER = 2
APPROVE_SCOPE_MASK = 0x03
ATOMIC_BATCH_FLAG = 0x04

assert tx.chain_id &lt; 2**256
assert tx.nonce &lt; 2**64
assert len(tx.frames) &gt; 0 and len(tx.frames) &lt;= MAX_FRAMES
assert len(tx.sender) == 20
assert tx.sender != bytes(20)
total_frame_gas = 0
for frame in tx.frames:
    assert frame.mode &lt; 3
    assert frame.flags &lt; 8
    assert frame.mode != VERIFY or (frame.flags &amp; APPROVE_SCOPE_MASK) != 0  # VERIFY frames must permit a non-zero APPROVE scope
    assert frame.target is None or len(frame.target) == 20
    assert frame.gas_limit &lt;= 2**63 - 1
    assert frame.value &lt; 2**256
    assert frame.mode == SENDER or frame.value == 0
    total_frame_gas += frame.gas_limit
    assert total_frame_gas &lt;= 2**63 - 1

# Atomic batch flag (bit 2 of flags) is only valid with SENDER mode, and next frame must also be SENDER.
for i, frame in enumerate(tx.frames):
    if frame.flags &amp; ATOMIC_BATCH_FLAG:
        assert frame.mode == SENDER                    # must be SENDER
        assert i + 1 &lt; len(tx.frames)                  # must not be last frame
        assert tx.frames[i + 1].mode == SENDER         # next frame must be SENDER
```

#### Receipt

The `ReceiptPayload` is defined as:

```
[cumulative_gas_used, payer, [frame_receipt, ...]]
frame_receipt = [status, gas_used, logs]
```

`payer` is the address of the account that paid the fees for the transaction. `status` is the return code of the top-level call.

#### Signature Hash

With the frame transaction, the signature may be at an arbitrary location in the frame list. In the canonical signature hash any frame with mode `VERIFY` will have its data elided:

```python
def compute_sig_hash(tx: FrameTx) -&gt; Hash:
    # Operate on a copy; the original transaction object is not modified.
    tx_copy = deep_copy(tx)
    for i, frame in enumerate(tx_copy.frames):
        if frame.mode == VERIFY:
            tx_copy.frames[i].data = Bytes()
    return keccak(rlp(tx_copy))
```

### New Opcodes

#### `APPROVE` opcode (`0xaa`)

The `APPROVE` opcode is like `RETURN (0xf3)`. It exits the current context successfully and updates the transaction-scoped approval context based on the `scope` operand.

If the currently executing account is not the frame&apos;s resolved target (i.e. if `ADDRESS != resolved_target`), `APPROVE` reverts.

##### Stack

| Stack      | Value        |
| ---------- | ------------ |
| `top - 0`  | `offset`     |
| `top - 1`  | `length`     |
| `top - 2`  | `scope`      |

##### Scope Operand

The `scope` operand is a bitmask. Define the following constants:

1. `APPROVE_SCOPE_NONE = 0x0`
2. `APPROVE_PAYMENT = 0x1`
3. `APPROVE_EXECUTION = 0x2`
4. `APPROVE_PAYMENT_AND_EXECUTION = APPROVE_PAYMENT | APPROVE_EXECUTION`
5. `APPROVE_SCOPE_MASK = APPROVE_PAYMENT_AND_EXECUTION`

The `scope` operand must be a non-zero subset of `APPROVE_SCOPE_MASK`, i.e. one of the following values:

1. `APPROVE_PAYMENT` (`0x1`): Approval of payment - the contract approves paying the total gas cost for the transaction.
2. `APPROVE_EXECUTION` (`0x2`): Approval of execution - the sender contract approves future frames calling on its behalf.
   - Note this is only valid when `resolved_target` equals `tx.sender`.
3. `APPROVE_PAYMENT_AND_EXECUTION` (`0x3`): Approval of payment and execution.

Any other value, including `APPROVE_SCOPE_NONE`, results in an exceptional halt.

`APPROVE_PAYMENT_AND_EXECUTION` is processed atomically within a single `APPROVE` and is not equivalent to invoking `APPROVE` twice.

The frame&apos;s allowed approval scope is `allowed_scope = frame.flags &amp; APPROVE_SCOPE_MASK`. These flag bits use the same bit assignments as the `scope` operand. A `scope` that is not a non-zero subset of `allowed_scope` results in an exceptional halt.

`allowed_scope` is caller-supplied policy input and may restrict a verifier&apos;s intended `APPROVE` call. Verification logic SHOULD authenticate any approval scope it relies on and MUST NOT treat `allowed_scope` as trusted unless it is covered by that logic.

- If `allowed_scope == APPROVE_SCOPE_NONE`, no `APPROVE` scope is allowed.
- If `allowed_scope == APPROVE_EXECUTION`, only `APPROVE_EXECUTION` is allowed.
- If `allowed_scope == APPROVE_PAYMENT`, only `APPROVE_PAYMENT` is allowed.
- If `allowed_scope == APPROVE_PAYMENT_AND_EXECUTION`, `APPROVE_EXECUTION`, `APPROVE_PAYMENT`, or `APPROVE_PAYMENT_AND_EXECUTION` are allowed.

##### Behavior

The behavior of `APPROVE` is defined as follows:

- If `ADDRESS != resolved_target`, revert.
- For scopes `APPROVE_EXECUTION`, `APPROVE_PAYMENT`, and `APPROVE_PAYMENT_AND_EXECUTION`, execute the following:
    - `APPROVE_EXECUTION`: Set `sender_approved = true`.
        - If `sender_approved` was already set, revert the frame.
        - If `resolved_target` != `tx.sender`, revert the frame.
    - `APPROVE_PAYMENT`: Increment the sender&apos;s nonce, collect the transaction&apos;s maximum cost (`TXPARAM(0x06)`) from `resolved_target`, and set `payer_approved = true`.
        - If `payer_approved` was already set, revert the frame.
        - If `resolved_target` has insufficient balance, revert the frame.
        - If `sender_approved == false`, revert the frame.
    - `APPROVE_PAYMENT_AND_EXECUTION`: Set `sender_approved = true`, increment the sender&apos;s nonce, collect the transaction&apos;s maximum cost (`TXPARAM(0x06)`) from `resolved_target`, and set `payer_approved = true`.
        - If `sender_approved` or `payer_approved` was already set, revert the frame.
        - If `resolved_target` != `tx.sender`, revert the frame.
        - If `resolved_target` has insufficient balance, revert the frame.

#### `TXPARAM` opcode

This opcode gives access to transaction-scoped information. The gas
cost of this operation is `2`.

It takes one value from the stack, `param`. The `param` is the field to be extracted from the transaction.

| `param` | Return value                                                                |
|---------|-----------------------------------------------------------------------------|
| 0x00    | current transaction type                                                    |
| 0x01    | `nonce`                                                                     |
| 0x02    | `sender`                                                                    |
| 0x03    | `max_priority_fee_per_gas`                                                  |
| 0x04    | `max_fee_per_gas`                                                           |
| 0x05    | `max_fee_per_blob_gas`                                                      |
| 0x06    | max cost (basefee=max, all gas used, includes blob cost and intrinsic cost) |
| 0x07    | `len(blob_versioned_hashes)`                                                |
| 0x08    | `compute_sig_hash(tx)`                                                      |
| 0x09    | `len(frames)`                                                               |
| 0x0A    | currently executing frame index                                             |

Notes:

- `0x01` has a possible future extension to allow indices for multidimensional nonces.
- `0x03` and `0x04` have a possible future extension to allow indices for multidimensional gas.
- `0x06` covers only the maximum gas and blob fees. It does not include any `frame.value` transfers.
- `0x07` returns only the number of blob versioned hashes. Individual blob versioned hashes remain accessible via the existing `BLOBHASH(index)` opcode.
- `0x08` returns the canonical signature hash. This value MUST be computed at most once per transaction and cached.
- Invalid `param` values (not defined in the table above) result in an exceptional halt.

#### `FRAMEPARAM` opcode

This opcode gives access to frame-scoped information. The gas cost of this operation is `2`.

It takes two values from the stack, `param` and `frameIndex` (in this order). The `frameIndex` is zero-based, so `0` refers to the first frame.

| `param` | `frameIndex` | Return value                                              |
|---------|--------------|-----------------------------------------------------------|
| 0x00    | frameIndex   | `target`                                                  |
| 0x01    | frameIndex   | `gas_limit`                                               |
| 0x02    | frameIndex   | `mode`                                                    |
| 0x03    | frameIndex   | `flags`                                                   |
| 0x04    | frameIndex   | `len(data)`                                               |
| 0x05    | frameIndex   | `status` (exceptional halt if current/future)             |
| 0x06    | frameIndex   | `allowed_scope` (`frame.flags &amp; APPROVE_SCOPE_MASK`)      |
| 0x07    | frameIndex   | `atomic_batch` (`(frame.flags &gt;&gt; 2) &amp; 0x01`, returns 0/1) |
| 0x08    | frameIndex   | `value`                                                   |

Notes:

- The `status` field (0x05) returns `0` for failure or `1` for success.
- Invalid `param` values (not defined in the table above) result in an exceptional halt.
- Out-of-bounds access for `frameIndex` (`&gt;= len(frames)`) results in an exceptional halt.
- Attempting to access the return `status` of the current frame or a subsequent frame results in an exceptional halt.
- `len(data)` returns size 0 when called on a frame with `VERIFY` set.

#### `FRAMEDATALOAD` opcode

This opcode loads one 32-byte word of data from frame input. Gas cost: 3 (matches CALLDATALOAD).

It takes two values from the stack, an `offset` and `frameIndex`.
It places the retrieved data on the stack.

When the `frameIndex` is out-of-bounds, an exceptional halt occurs.

The operation sematics match CALLDATALOAD, returning a word of data from the chosen
frame&apos;s `data`, starting at the given byte `offset`. When targeting a frame in `VERIFY`
mode, the returned data is always zero.

#### `FRAMEDATACOPY` opcode

This opcode copies data frame input into the contract&apos;s memory. Its gas cost is calculated
exactly as for `CALLDATACOPY`, including the fixed cost of 3, the per-word copy cost, and
the standard EVM memory expansion cost.

It takes four values from the stack: `memOffset`, `dataOffset`, `length` and `frameIndex`.
No stack output value is produced.

When the `frameIndex` is out-of-bounds, an exceptional halt occurs.

The operation sematics match CALLDATACOPY, copying `length` bytes from the chosen frame&apos;s
`data`, starting at the given byte `dataOffset`, into a memory region starting at
`memOffset`. When targeting a frame in `VERIFY` mode, no data is copied.

### Behavior

When processing a frame transaction, perform the following steps.

Perform stateful validation check:

- Ensure `tx.nonce == state[tx.sender].nonce`

Initialize with transaction-scoped variables:

- `payer_approved = false`
- `sender_approved = false`

Then for each call frame:

1. Let `resolved_target = frame.target if frame.target is not null else tx.sender`, then execute a call with the specified `mode`, `flags`, `resolved_target`, `gas_limit`, `value`, and `data`.
   - If mode is `SENDER`:
       - `sender_approved` must be `true`. If not, the transaction is invalid.
       - Set `caller` as `tx.sender`.
   - If mode is `DEFAULT` or `VERIFY`:
       - Set the `caller` to `ENTRY_POINT`.
   - In the top-level frame call, `CALLVALUE` is `frame.value`.
   - As with an ordinary `CALL`, if the caller does not have sufficient balance to transfer `frame.value`, the frame reverts.
   - If `resolved_target` has neither code nor an [EIP-7702](/EIPs/EIPS/eip-7702) delegation indicator, execute the logic described in [default code](#default-code).
   - Otherwise, if `resolved_target` uses an [EIP-7702](/EIPs/EIPS/eip-7702) delegation indicator, execute according to [EIP-7702](/EIPs/EIPS/eip-7702)&apos;s delegated-code semantics.
   - The `ORIGIN` opcode returns frame `caller` throughout all call depths.
   - If a frame&apos;s execution reverts, its state changes are discarded. Additionally, if this frame has the atomic batch flag set, mark all subsequent frames in the same atomic group as skipped.
2. If frame has mode `VERIFY` and the frame did not successfully call `APPROVE`, the transaction is invalid.

#### Atomic Batching

Consecutive `SENDER` frames where all but the last have the atomic batch flag (bit 2 of `flags`) set form an **atomic batch**. Within a batch, if any frame reverts, all preceding frames in the batch are also reverted and all subsequent frames in the batch are skipped.

More precisely, execution of an atomic batch proceeds as follows:

1. Take a snapshot of the state before executing the first frame in the batch.
2. Execute each frame in the batch sequentially.
3. If a frame reverts:
   - Restore the state to the snapshot taken before the batch.
   - Mark all remaining frames in the batch as skipped.

For example, given frames:

| Frame | Mode   | Atomic Batch Flag |
|-------|--------|-------------------|
| 0     | SENDER | set               |
| 1     | SENDER | not set           |
| 2     | SENDER | set               |
| 3     | SENDER | set               |
| 4     | SENDER | not set           |

Frames 0-1 form one atomic batch and frames 2-4 form another. If frame 3 reverts, the state changes from frames 2 and 3 are discarded and frame 4 is skipped.

After executing all frames, verify that `payer_approved == true`. If it is, refund any unpaid gas to the gas payer. If it is not, the whole transaction is invalid.

Note:

- It is implied by the handling that the sender must approve the transaction *before* the payer and that once `sender_approved` or `payer_approved` become `true` they cannot be re-approved or reverted.

#### Default code

When using frame transactions with EOAs that have neither code nor an [EIP-7702](/EIPs/EIPS/eip-7702) delegation indicator, they are treated as if they have a &quot;default code.&quot; Accounts with code, including [EIP-7702](/EIPs/EIPS/eip-7702) delegated accounts, do not use the default code path. This spec describes only the behavior of the default code; clients are free to implement the default code however they want, so long as they correspond to the behavior specified here.

- Let `resolved_target = frame.target if frame.target is not null else tx.sender`.
- Retrieve the current frame&apos;s `mode` with `FRAMEPARAM`.
- If `mode` is `VERIFY`:
  - Read the allowed approval scope from the flags field: `allowed_scope = frame.flags &amp; APPROVE_SCOPE_MASK`. If `allowed_scope == APPROVE_SCOPE_NONE`, revert.
  - If `allowed_scope &amp; APPROVE_EXECUTION != 0` and `resolved_target != tx.sender`, revert.
  - Read the first byte of `frame.data` as `signature_type`.
  - If `signature_type` is:
    - `0x0`:
      - Read the rest of `frame.data` as `(v, r, s)`.
      - If `s &gt; secp256k1n / 2`, revert.
      - Let `recovered = ecrecover(sig_hash, v, r, s)`, where `sig_hash = compute_sig_hash(tx)`.
      - If `recovered == address(0)`, revert.
      - If `resolved_target != recovered`, revert.
    - `0x1`:
      - Read the rest of `frame.data` as `(r, s, qx, qy)`.
      - Let `p256_address = keccak(P256_ADDRESS_DOMAIN|qx|qy)[12:]`.
      - If `resolved_target != p256_address`, revert.
      - If `P256VERIFY(sig_hash, r, s, qx, qy) != true`, where `sig_hash = compute_sig_hash(tx)`, revert.
    - Otherwise revert.
  - Call `APPROVE(allowed_scope)`.
- If `mode` is `SENDER`:
  - If `resolved_target != tx.sender`, return successfully with empty data. This matches a call to an empty-code account; any top-level `frame.value` transfer has already been applied by the frame call itself.
  - Otherwise, read `frame.data` as RLP encoding of `calls = [[target, value, data]]`.
  - For each call in `calls`, execute the call with `msg.sender = tx.sender`.
    - If any call reverts, revert the frame.
- If `mode` is `DEFAULT`:
  - Revert the frame.

Notes:

- `P256VERIFY` must reject invalid public keys, including points that are not on the P256 curve.
- For the P256 (r1) signature type, the sender address is `keccak(P256_ADDRESS_DOMAIN|qx|qy)[12:]`.

Here&apos;s the logic above implemented in Python:

```python
DEFAULT   = 0
VERIFY    = 1
SENDER    = 2
APPROVE_SCOPE_NONE = 0x00
APPROVE_PAYMENT = 0x01
APPROVE_EXECUTION = 0x02
APPROVE_PAYMENT_AND_EXECUTION = APPROVE_PAYMENT | APPROVE_EXECUTION
APPROVE_SCOPE_MASK = APPROVE_PAYMENT_AND_EXECUTION
ATOMIC_BATCH_FLAG = 0x04

SECP256K1 = 0x0
P256      = 0x1
P256_ADDRESS_DOMAIN = b&quot;\x01&quot;
SECP256K1N_DIV_2 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0

def default_code(frame, tx):
    mode = frame.mode                        # equivalent to FRAMEPARAM(0x02, TXPARAM(0x0A))
    resolved_target = frame.target if frame.target is not None else tx.sender

    if mode == VERIFY:
        allowed_scope  = frame.flags &amp; APPROVE_SCOPE_MASK  # allowed approval scope from flags field
        if allowed_scope == APPROVE_SCOPE_NONE:
            revert()
        if allowed_scope &amp; APPROVE_EXECUTION != 0 and resolved_target != tx.sender:
            revert()
        signature_type = frame.data[0]              # first byte: signature type
        sig_hash       = compute_sig_hash(tx)       # equivalent to TXPARAM(0x08)

        if signature_type == SECP256K1:
            # frame.data layout: [signature_type, v (1 byte), r (32 bytes), s (32 bytes)]
            if len(frame.data) != 66:               # 1 header + 65 signature bytes
                revert()
            v = frame.data[1]
            r = frame.data[2:34]
            s = frame.data[34:66]
            # Reject high-s signatures so each authorization has a single canonical encoding.
            if int.from_bytes(s, &quot;big&quot;) &gt; SECP256K1N_DIV_2:
                revert()
            recovered = ecrecover(sig_hash, v, r, s)
            if recovered == bytes(20):
                revert()
            if resolved_target != recovered:
                revert()

        elif signature_type == P256:
            # frame.data layout: [signature_type, r (32 bytes), s (32 bytes), qx (32 bytes), qy (32 bytes)]
            if len(frame.data) != 129:              # 1 header + 128 signature bytes
                revert()
            r  = frame.data[1:33]
            s  = frame.data[33:65]
            qx = frame.data[65:97]
            qy = frame.data[97:129]
            if resolved_target != keccak256(P256_ADDRESS_DOMAIN + qx + qy)[12:]:
                revert()
            if not P256VERIFY(sig_hash, r, s, qx, qy):
                revert()

        else:
            revert()

        APPROVE(allowed_scope)

    elif mode == SENDER:
        if resolved_target != tx.sender:
            # Empty-code account behavior: succeed immediately. Any top-level
            # frame.value transfer has already been applied by the frame call.
            return

        # frame.data layout: RLP-encoded [[target, value, data], ...]
        calls = rlp_decode(frame.data)
        for call_target, call_value, call_data in calls:
            result = evm_call(caller=tx.sender, to=call_target, value=call_value, data=call_data)
            if result.reverted:
                revert()

    elif mode == DEFAULT:
        revert()

    else:
        revert()
```

#### Frame interactions

A few cross-frame interactions to note:

- For the purposes of gas accounting of warm / cold state status, the journal of such touches is shared across frames.
- Discard the `TSTORE` and `TLOAD` transient storage between frames.

#### Gas Accounting

The total gas limit of the transaction is:

```
tx_gas_limit = FRAME_TX_INTRINSIC_COST + len(tx.frames) * FRAME_TX_PER_FRAME_COST + calldata_cost(rlp(tx.frames)) + sum(frame.gas_limit for all frames)
```

Where `calldata_cost` is calculated per standard EVM rules (4 gas per zero byte, 16 gas per non-zero byte).

The total fee is defined as:

```
tx_fee = tx_gas_limit * effective_gas_price + blob_fees
blob_fees = len(blob_versioned_hashes) * GAS_PER_BLOB * blob_base_fee
```

The `effective_gas_price` is calculated per EIP-1559 and `blob_fees` is calculated as per EIP-4844.

Any `frame.value` transferred by `SENDER` frames is separate from `tx_fee` and follows ordinary `CALL` value-transfer semantics. The gas cost of sending `frame.value` is the same as for any ordinary `CALL` frame.

Each frame has its own `gas_limit` allocation. Unused gas from a frame is **not** available to subsequent frames. After all frames execute, the gas refund is calculated as:

```
refund = sum(frame.gas_limit for all frames) - total_gas_used
```

This refund is returned to the gas payer (the `target` that called `APPROVE(APPROVE_PAYMENT)` or `APPROVE(APPROVE_PAYMENT_AND_EXECUTION)`) and added back to the block gas pool. *Note: This refund mechanism is separate from EIP-3529 storage refunds.*

### Mempool

The transaction mempool must carefully handle frame transactions, as a naive implementation could introduce denial-of-service vulnerabilities. The fundamental goal of the public mempool rules is to avoid allowing an arbitrary number of transactions to be invalidated by a single environmental change or state modification. Beyond this, the rules also aim to minimize the amount of work needed to complete the initial validation phase of a transaction before an acceptance decision can be made.

This policy is inspired by [ERC-7562](/EIPs/EIPS/eip-7562), but removes staking and reputation entirely. Any behavior that ERC-7562 would admit only for a staked or reputable third party is rejected here for the public mempool. Transactions outside these rules may be accepted into a local or private mempool, but must not be propagated through the public mempool.

#### Constants

| Name  | Value  | Description  |
|---|---|---|
| `MAX_VERIFY_GAS`   | `100_000`  | Maximum amount of gas a node should expend simulating the validation prefix |
| `MAX_PENDING_TXS_USING_NON_CANONICAL_PAYMASTER`   | `1`  | Maximum amount of pending transactions that can be using any given non-canonical paymaster |

#### Validation Prefix

The **validation prefix** of a frame transaction is the shortest prefix of frames whose successful execution sets `payer_approved = true`.

Public mempool rules apply only to the validation prefix. Once `payer_approved = true`, subsequent frames are outside public mempool validation and may be arbitrary. In particular, `user_op` and `post_op` occur after payment approval and are therefore not subject to the public mempool restrictions below.

#### Policy Summary

A frame transaction is eligible for public mempool propagation only if its validation prefix depends exclusively on:

1. transaction fields, including the canonical signature hash,
2. the sender&apos;s nonce, code, and storage,
3. the [EIP-7997](/EIPs/EIPS/eip-7997) deterministic factory predeploy, if a deployment frame is present,
4. if a paymaster frame is present, either a canonical paymaster instance together with explicit paymaster balance reservation, or a non-canonical paymaster being used by less than `MAX_PENDING_TXS_USING_NON_CANONICAL_PAYMASTER` pending transactions,
5. the code of any other existing non-delegated contracts reached during validation via `CALL*` or `EXTCODE*`, provided the resulting trace does not access disallowed mutable state.

Any dependency on third-party mutable state outside these categories must result in rejection by the public mempool.

#### Mode Subclassifications

While the frames are designed to be generic, we refine some frame modes for the purpose of specifying public mempool handling clearly.

| Name  | Mode  | Description  |
|---|---|---|
| `self_verify`   | VERIFY  | Validates the transaction and approves both sender and payer |
| `deploy`  | DEFAULT | Deploys a new smart account using the [EIP-7997](/EIPs/EIPS/eip-7997) deterministic factory predeploy |
| `only_verify`  | VERIFY  | Validates the transaction and approves only the sender |
| `pay`  | VERIFY | Validates the transaction and approves only the payer |
| `user_op` | SENDER | Executes the intended user operation |
| `post_op` | DEFAULT | Executes an optional post-op action as needed by the paymaster |


#### Public Mempool-recognized Validation Prefixes

The public mempool recognizes four validation prefixes. Structural rules are enforced only up to and including the frame that sets `payer_approved = true`.

##### Self Relay

###### Basic Transaction

```
+-------------+
| self_verify |
+-------------+
```

###### Deploy New Account

```
+--------+-------------+
| deploy | self_verify |
+--------+-------------+
```

##### Canonical Paymaster

###### Basic Transaction

```
+-------------+-----+
| only_verify | pay |
+-------------+-----+
```

###### Deploy New Account

```
+--------+-------------+-----+
| deploy | only_verify | pay |
+--------+-------------+-----+
```

Frames after these prefixes are outside public mempool validation. For example, a transaction may continue with any number of `user_op`s and/or `post_op`s.

#### Structural Rules

To be accepted into the public mempool, a frame transaction must satisfy the following:

1. Its validation prefix must match one of the four recognized prefixes above.
2. If present, `deploy` must be the first frame. This implies there can be at most one `deploy` frame in the validation prefix.
3. `self_verify` and `only_verify` must execute in `VERIFY` mode, target `tx.sender` (either explicitly or via a null target), and must successfully call `APPROVE`.
    - `self_verify` must call `APPROVE(APPROVE_PAYMENT_AND_EXECUTION)`.
    - `only_verify` must call `APPROVE(APPROVE_EXECUTION)`.
4. `pay` must execute in `VERIFY` mode and successfully call `APPROVE(APPROVE_PAYMENT)`.
5. The sum of `gas_limit` values across the validation prefix must not exceed `MAX_VERIFY_GAS`.
6. Nodes should stop simulation immediately once `payer_approved = true` has been observed.

#### Canonical Paymaster Exception

The generic validation trace and opcode rules below apply to all frames in the validation prefix except a `pay` frame whose target runtime code exactly matches the canonical paymaster implementation. The canonical paymaster implementation is explicitly designed to be safe for public mempool use and is therefore admitted by code match, successful `APPROVE(APPROVE_PAYMENT)`, and the paymaster accounting rules in this section, rather than by requiring it to satisfy each generic validation rule individually.

#### Validation Trace Rules

A public mempool node must simulate the validation prefix and reject the transaction if any of the following occurs before `payer_approved = true`:

- a frame in the validation prefix reverts
- a `VERIFY` frame in the validation prefix exits without the required `APPROVE`
- execution exceeds `MAX_VERIFY_GAS`
- execution uses a banned opcode
- execution performs a state write, except deterministic deployment performed by the first `deploy` frame through a known deployer
- execution reads storage outside `tx.sender`
- execution performs `CALL*` or `EXTCODE*` to an address that is neither an existing contract nor a precompile, or to an address that uses an EIP-7702 delegation, except for `tx.sender` default-code behavior
- if a `deploy` frame is present, its execution does not result in non-empty, non-delegated code being installed at `tx.sender`

##### Banned Opcodes

For `VERIFY` frames, the usual `STATICCALL` restrictions apply except for the protocol-defined effects of `APPROVE`. In addition, the following opcodes are banned during the validation prefix, with a few caveats:

- ORIGIN (0x32)
- GASPRICE (0x3A)
- BLOCKHASH (0x40)
- COINBASE (0x41)
- TIMESTAMP (0x42)
- NUMBER (0x43)
- PREVRANDAO/DIFFICULTY (0x44)
- GASLIMIT (0x45)
- BASEFEE (0x48)
- BLOBHASH (0x49)
- BLOBBASEFEE (0x4A)
- GAS (0x5A)
    - Except when followed immediately by a `*CALL` instruction. This is the standard method of passing gas to a child call and does not create an additional public mempool dependency.
- CREATE (0xF0)
- CREATE2 (0xF5)
    - Except inside the first `deploy` frame when targeting the [EIP-7997](/EIPs/EIPS/eip-7997) deterministic factory predeploy.
- INVALID (0xFE)
- SELFDESTRUCT (0xFF)
- BALANCE (0x31)
- SELFBALANCE (0x47)
- SSTORE (0x55)
- TLOAD (0x5C)
- TSTORE (0x5D)

`SLOAD` can be used only to access `tx.sender` storage, including when reached transitively via `CALL*` or `DELEGATECALL`.

`CALL*` and `EXTCODE*` may target any existing contract or precompile, provided the resulting trace still satisfies the storage, opcode, and EIP-7702 restrictions above. This permits helper contracts and libraries during validation, including via `DELEGATECALL`, so long as they do not introduce additional mutable-state dependencies.

#### Paymasters

A paymaster can choose to sponsor a transaction&apos;s gas. Generally the relationship is one paymaster to many transaction senders, however, this is in direct conflict with the goal of not predicating the validity of many transactions on the value of one account or storage element.

We address this conflict in two ways:

1. If a paymaster sponsors gas for a large number of accounts simultaneously, it must be a safe, standardized paymaster contract. It is designed such that ether which enters it cannot leave except:
  a. in the form of payment for a transaction, or
  b. after a delay period.
2. If a paymaster sponsors gas for a small number of accounts simultaneously (no more than `MAX_PENDING_TXS_USING_NON_CANONICAL_PAYMASTER`), it may be any paymaster contract.

##### Canonical paymaster

The canonical paymaster is not a singleton deployment. Many instances may be deployed. For public mempool purposes, a paymaster instance is considered canonical if and only if the runtime code at the `pay` frame target exactly matches the canonical paymaster implementation.

The canonical paymaster in this draft authorizes with a single secp256k1 signer via `ecrecover`, does not support contract-signature schemes, and may change in later specifications, in which case a new canonical implementation version would be required.

Because the canonical paymaster implementation is explicitly standardized to be safe for public mempool use, nodes do not need to apply the generic validation trace and opcode rules to that `pay` frame. Instead, they identify it by runtime code match and apply the paymaster-specific accounting and revalidation rules in this section.

A transaction using a paymaster is eligible for public mempool propagation only if the `pay` frame targets a canonical paymaster instance and the node can reserve the maximum transaction cost against that paymaster.

For public mempool purposes, each node maintains a local accounting value `reserved_pending_cost(paymaster)` and computes:

```python
available_paymaster_balance = state.balance(paymaster) - reserved_pending_cost(paymaster) - pending_withdrawal_amount(paymaster)
```

Where `pending_withdrawal_amount(paymaster)` is the currently pending delayed withdrawal amount of the canonical paymaster instance, or zero if no delayed withdrawal is pending.

A node must reject a paymaster transaction if `available_paymaster_balance` is less than the transaction&apos;s maximum cost (`TXPARAM(0x06)`).

On admission, the node increments `reserved_pending_cost(paymaster)` by the transaction&apos;s maximum cost (`TXPARAM(0x06)`). On eviction, replacement, inclusion, or reorg removal, the node decrements it accordingly.

##### Non-canonical paymaster

For non-canonical paymasters, `pending_withdrawal_amount` is not meaningful since they may not support timelocked withdrawals.  Instead, we keep the mempool safe by enforcing that each non-canonical paymaster can only be used with no more than `MAX_PENDING_TXS_USING_NON_CANONICAL_PAYMASTER` pending transactions.

Therefore we perform two checks:

- For balance, `available_paymaster_balance` must not be less than the transaction cost, where:

```python
available_paymaster_balance = state.balance(paymaster) - reserved_pending_cost(paymaster)
```

- The number of pending transactions in the mempool that uses this paymaster must be less than `MAX_PENDING_TXS_USING_NON_CANONICAL_PAYMASTER`.

[See here for rationale](#non-canonical-paymasters-in-the-mempool) for enabling non-canonical paymasters in the mempool.

#### Acceptance Algorithm

1. A transaction is received over the wire and the node decides whether to accept or reject it.
2. The node analyzes the frame structure and determines the validation prefix. If the prefix is not one of the recognized prefixes, reject.
3. The node simulates the validation prefix and enforces the structural and trace rules above, except that a `pay` frame whose target runtime code exactly matches the canonical paymaster implementation is handled via the canonical paymaster exception and the paymaster-specific rules below.
4. The node records the sender storage slots read during validation. Calls into helper contracts do not create additional mutable-state dependencies unless they cause disallowed storage access under the trace rules above.
5. If a canonical paymaster instance is used, the node verifies paymaster solvency using the reservation rule above.
6. A node should keep at most one pending frame transaction per sender in the public mempool. A new transaction from the same sender MAY replace the existing one only if it uses the same nonce and satisfies the node&apos;s fee bump rules.
7. If all checks pass, the transaction may be accepted into the public mempool and propagated to peers.

#### Revalidation

When a new canonical block is accepted, the node removes any included frame transactions from the public mempool, updates paymaster reservations accordingly, and identifies the remaining pending transactions whose tracked dependencies were touched by the block. This includes at least transactions for the same sender, transactions whose recorded sender storage slots changed, and transactions that reference a canonical paymaster instance whose balance, code, or delayed-withdrawal state changed. The node then re-simulates the validation prefix of only those affected transactions against the new head and evicts any transaction that no longer satisfies the public mempool rules.

## Rationale

### Canonical signature hash

The canonical signature hash is provided in `TXPARAM` to simplify the development of smart accounts.

Computing the signature hash in EVM is complicated and expensive. While using the canonical signature hash is not mandatory, it is strongly recommended. Creating a bespoke signature requires precise commitment to the underlying transaction data. Without this, it&apos;s possible that some elements can be manipulated in-the-air while the transaction is pending and have unexpected effects. This is known as transaction malleability. Using the canonical signature hash avoids malleability of the frames other than `VERIFY`.

The `frame.data` of `VERIFY` frames is elided from the signature hash. This is done for three reasons:

1. It contains the signature so by definition it cannot be part of the signature hash.
2. In the future it may be desired to aggregate the cryptographic operations for data and compute efficiency reasons. If the data was introspectable, it would not be possible to aggregate the verify frames in the future.
3. For gas sponsoring workflows, we also recommend using a `VERIFY` frame to approve the gas payment. Here, the input data to the sponsor is intentionally left malleable so it can be added onto the transaction after the `sender` has made its signature. Notably, the raw `frame.target` field of `VERIFY` frames is covered by the signature hash, i.e. the `sender` chooses the sponsor address explicitly.

Implementations MUST NOT treat `VERIFY` frame `data` as sender-authenticated by the canonical signature hash. Any verifier or paymaster that depends on its input data, including sponsor parameters, exchange rates, fee terms, or custom account context, MUST authenticate that data independently. Replacing or mutating `VERIFY` frame `data` does not change the canonical signature hash.

By contrast, non-`VERIFY` frame metadata, including a `SENDER` frame&apos;s `value`, remains covered by the canonical signature hash.

Verification logic MUST NOT assign policy meaning to signature encodings or adjacent `VERIFY` frame data unless that meaning is independently authenticated.

### `APPROVE` calling convention

Originally `APPROVE` was meant to extend the space of return statuses from 0 and 1 today to 0 to 4. However, this would mean smart accounts deployed today would not be able to modify their contract code to return with a different value at the top level. For this reason, we&apos;ve chosen behavior above: `APPROVE` terminates the executing frame successfully like `RETURN`, but it actually updates the transaction scoped values `sender_approved` and `payer_approved` during execution. It is still required that only the sender can toggle the `sender_approved` to `true`. Only the frame&apos;s resolved target can call `APPROVE` generally, because it can allow the transaction pool and other frames to better reason about `VERIFY` mode frames.

Because `DELEGATECALL` preserves `ADDRESS`, code executed via `DELEGATECALL` from the resolved target may also execute `APPROVE` successfully. Contracts that rely on `APPROVE` should therefore treat delegatecalled libraries as fully trusted.

### Payer in receipt

The payer cannot be determined statically from a frame transaction and is relevant to users. The only way to provide this information safely and efficiently over the JSON-RPC is to record this data in the receipt object.

### No authorization list

The EIP-7702 authorization list heavily relies on ECDSA cryptography to determine the authority of accounts to delegate code. While delegations could be used in other manners later, it does not satisfy the PQ goals of the frame transaction.

### No access list

The access list was introduced to address a particular backwards compatibility issue that was caused by EIP-2929. The risk-reward of using an access list successfully is high. A single miss, paying to warm a storage slot that does not end up getting used, causes the overall transaction cost to be greater than had it not been included at all.

Future optimizations based on pre-announcing state elements a transaction will touch will be covered by block level access lists.

### Atomic batching

Atomic batching allows multiple `SENDER` frames to be grouped into a single all-or-nothing unit. This is useful when a sequence of calls is only meaningful if all succeed together, such as an approval followed by a swap, or a series of interdependent state changes. Without this feature, a revert in one frame would leave the preceding frames&apos; state changes applied, potentially leaving the account in an undesirable intermediate state.

Using a flag to indicate atomic batches saves us from having to introduce a new mode. Batches are identified purely by consecutive `SENDER` frames with the flag set, terminated by a `SENDER` frame without it. This design enables consecutive atomic batches since the batch boundary is clearly indicated by the `SENDER` frame without the flag.

### Per-frame cost

Each frame incurs a fixed CALL execution-context overhead (100) plus `G_log` (375) for the receipt sub-entry it produces, giving `FRAME_TX_PER_FRAME_COST = 475`. The execution-context component covers context setup, mode dispatch, and gas accounting at the frame boundary, analogous to the fixed overhead of a CALL. The `G_log` component covers the `[status, gas_used, logs]` receipt sub-entry that each frame adds to the transaction receipt, which must be serialized, hashed into the receipt trie, and proven by ZK-EVM implementations. Cold/warm access costs for the frame&apos;s target account are charged within the frame&apos;s own `gas_limit` through the normal EVM warm/cold accounting, not through the per-frame cost.

### Per-frame value

A design goal of the frame transaction is to provide a good experience out-of-the-box for users and to reduce the threat surface of smart contract wallets. Like batching, sending native value is a part of achieving that.

Restricting non-zero `value` to `SENDER` frames keeps `VERIFY` and `DEFAULT` frames side-effect-free with respect to ETH transfer semantics, preserves the intended `STATICCALL`-like behavior of `VERIFY`, and avoids requiring the protocol-defined `ENTRY_POINT` caller to fund top-level ETH transfers.

### EOA support

While we expect EOA users to migrate to smart accounts eventually, we recognize that most Ethereum users today are using EOAs, so we want to improve UX for them where we can.

With frame transactions, EOA wallets today can reap the key benefit of AA - gas abstraction, including sending sponsored transactions, paying gas in ERC-20 tokens, and more.

### Non-canonical paymasters in the mempool

The primary use case for non-canonical paymasters is to enable users to pay gas with a dedicated &quot;gas account,&quot; so that their other accounts can transact without holding any ETH.  For example, a user might have a single account that holds some ETH, while other accounts only hold stablecoins and NFTs, and they can transact freely with these other accounts while using the gas account as the paymaster.

Note that users can use any EOA as a paymaster thanks to the [default code](#default-code).

### Examples

#### Example 1: Simple Transaction

| Frame | Caller      | Target        | Value | Flags                         | Data      | Mode   |
| ----- | ----------- | ------------- | ----- | ----------------------------- | --------- | ------ |
| 0     | ENTRY_POINT | Null (sender) | 0     | APPROVE_PAYMENT_AND_EXECUTION | Signature | VERIFY |
| 1     | Sender      | Target        | 0     | APPROVE_SCOPE_NONE            | Call data | SENDER |

Frame 0 verifies the signature and calls `APPROVE(APPROVE_PAYMENT_AND_EXECUTION)` to approve both payment and execution. Frame 1 executes and exits normally via `RETURN`.

The mempool can process this transaction with the following static validation and call:

- Verify that the first frame is a `VERIFY` frame.
- Verify that the call of frame 0 succeeds, and does not violate the mempool rules (similar to [ERC-7562](/EIPs/EIPS/eip-7562)).

#### Example 1a: Simple ETH transfer

| Frame | Caller      | Target        | Value  | Flags                         | Data      | Mode   |
| ----- | ----------- | ------------- | ------ | ----------------------------- | --------- | ------ |
| 0     | ENTRY_POINT | Null (sender) | 0      | APPROVE_PAYMENT_AND_EXECUTION | Signature | VERIFY |
| 1     | Sender      | Destination   | Amount | APPROVE_SCOPE_NONE            | Empty     | SENDER |

A simple transfer is performed by setting the `SENDER` frame target to the destination account and the frame `value` to the transfer amount. This requires two frames for mempool compatibility, since the validation phase of the transaction has to be static.

#### Example 1b: Simple account deployment

| Frame | Caller      | Target        | Value  | Flags                         | Data           | Mode    |
| ----- | ----------- | ------------- | ------ | ----------------------------- | -------------- | ------- |
| 0     | ENTRY_POINT | Deployer      | 0      | APPROVE_SCOPE_NONE            | Initcode, Salt | DEFAULT |
| 1     | ENTRY_POINT | Null (sender) | 0      | APPROVE_PAYMENT_AND_EXECUTION | Signature      | VERIFY  |
| 2     | Sender      | Destination   | Amount | APPROVE_SCOPE_NONE            | Empty          | SENDER  |

This example illustrates the initial deployment flow for a smart account at the `sender` address. Since the address needs to have code in order to validate the transaction, the transaction must deploy the code before verification.

The first frame would call the [EIP-7997](/EIPs/EIPS/eip-7997) deterministic factory predeploy. The deployer determines the address in a deterministic way from the salt and initcode. However, since the transaction sender is not authenticated at this point, the user must choose an initcode which is safe to deploy by anyone.

#### Example 2: Atomic Approve + Swap

| Frame | Caller      | Target        | Value | Flags                         | Data                 | Mode   |
| ----- | ----------- | ------------- | ----- | ----------------------------- | -------------------- | ------ |
| 0     | ENTRY_POINT | Null (sender) | 0     | APPROVE_PAYMENT_AND_EXECUTION | Signature            | VERIFY |
| 1     | Sender      | ERC-20        | 0     | ATOMIC_BATCH_FLAG            | approve(DEX, amount) | SENDER |
| 2     | Sender      | DEX           | 0     | APPROVE_SCOPE_NONE           | swap(...)            | SENDER |

Frame 0 verifies the signature and calls `APPROVE(APPROVE_PAYMENT_AND_EXECUTION)`. Frames 1 and 2 form an atomic batch: if the swap in frame 2 reverts, the ERC-20 approval from frame 1 is also reverted, preventing the account from being left with a dangling approval.

#### Example 3: Sponsored Transaction (Fee Payment in ERC-20)

| Frame | Caller      | Target        | Value | Flags              | Data                   | Mode    |
| ----- | ----------- | ------------- | ----- | ------------------ | ---------------------- | ------- |
| 0     | ENTRY_POINT | Null (sender) | 0     | APPROVE_EXECUTION  | Signature              | VERIFY  |
| 1     | ENTRY_POINT | Sponsor       | 0     | APPROVE_PAYMENT    | Sponsor data           | VERIFY  |
| 2     | Sender      | ERC-20        | 0     | APPROVE_SCOPE_NONE | transfer(Sponsor,fees) | SENDER  |
| 3     | Sender      | Target addr   | 0     | APPROVE_SCOPE_NONE | Call data              | SENDER  |
| 4     | ENTRY_POINT | Sponsor       | 0     | APPROVE_SCOPE_NONE | Post op call           | DEFAULT |

- Frame 0: Verifies signature and calls `APPROVE(APPROVE_EXECUTION)` to authorize execution from sender.
- Frame 1: Checks that the user has enough ERC-20 tokens, and that the next frame is an ERC-20 send of the right size to the sponsor. Calls `APPROVE(APPROVE_PAYMENT)` to authorize payment.
- Frame 2: Sends tokens to sponsor.
- Frame 3: User&apos;s intended call.
- Frame 4 (optional): Check unpaid gas, refund tokens, possibly convert tokens to ETH on an AMM.

#### Example 4: EOA paying gas in ERC-20s

| Frame | Caller      | Target       | Value | Flags              | Data                   | Mode   |
| ----- | ----------- | ------------ | ----- | ------------------ | ---------------------- | ------ |
| 0     | ENTRY_POINT | Null(sender) | 0     | APPROVE_EXECUTION  | (0, v, r, s)           | VERIFY |
| 1     | ENTRY_POINT | Sponsor      | 0     | APPROVE_PAYMENT    | Sponsor signature      | VERIFY |
| 2     | Sender      | ERC-20       | 0     | APPROVE_SCOPE_NONE | transfer(Sponsor,fees) | SENDER |
| 3     | Sender      | Target addr  | 0     | APPROVE_SCOPE_NONE | Call data              | SENDER |

- Frame 0: Verify the sender with a EOA signature.  Upon verification, the frame calls `APPROVE(APPROVE_EXECUTION)` to authorize execution.
- Frame 1: Checks that the user has enough ERC-20 tokens, and that the next frame is an ERC-20 send of the right size to the sponsor. Calls `APPROVE(APPROVE_PAYMENT)` to authorize payment.
- Frame 2: Sends tokens to sponsor.
- Frame 3: User&apos;s intended call.

### Data Efficiency

**Basic transaction sending ETH from a smart account:**

| Field                             | Bytes |
| --------------------------------- | ----- |
| Tx wrapper                        | 1     |
| Chain ID                          | 1     |
| Nonce                             | 2     |
| Sender                            | 20    |
| Max priority fee                  | 5     |
| Max fee                           | 5     |
| Max fee per blob gas              | 1     |
| Blob versioned hashes (empty)     | 1     |
| Frames wrapper                    | 1     |
| Sender validation frame: mode     | 1     |
| Sender validation frame: flags    | 1     |
| Sender validation frame: target   | 1     |
| Sender validation frame: gas      | 2     |
| Sender validation frame: value    | 1     |
| Sender validation frame: data     | 65    |
| Execution frame: mode             | 1     |
| Execution frame: flags            | 1     |
| Execution frame: target           | 20    |
| Execution frame: gas              | 1     |
| Execution frame: value            | 5     |
| Execution frame: data             | 0     |
| **Total**                         | 136   |

Notes: Nonce assumes &lt; 65536 prior sends. Fees assume &lt; 1099 gwei. Validation frame target is 1 byte because target is `tx.sender`. Validation gas assumes &lt;= 65,536 gas. Validation frame value is zero. Execution frame target is encoded directly as the destination address. Execution frame value assumes a compact 5-byte encoding. The execution frame data is empty for a plain ETH transfer. Validation data is 65 bytes for an ECDSA signature. Blob fields assume no blobs (empty list, zero max fee).

This is not much larger than an EIP-1559 transaction; the extra overhead is mainly the need to specify the sender and the per-frame wrapper explicitly.

**First transaction from an account (add deployment frame):**

| Field                      | Bytes |
| -------------------------- | ----- |
| Deployment frame: mode     | 1     |
| Deployment frame: flags    | 1     |
| Deployment frame: target   | 20    |
| Deployment frame: gas      | 3     |
| Deployment frame: value    | 1     |
| Deployment frame: data     | 100   |
| **Total additional**       | 126   |

Notes: Gas assumes cost &lt; 2^24. Calldata assumes small proxy.

**Trustless pay-with-ERC-20 sponsor (add these frames):**

| Field                                | Bytes |
| ------------------------------------ | ----- |
| Sponsor validation frame: mode       | 1     |
| Sponsor validation frame: flags      | 1     |
| Sponsor validation frame: target     | 20    |
| Sponsor validation frame: gas        | 3     |
| Sponsor validation frame: value      | 1     |
| Sponsor validation frame: calldata   | 0     |
| Send to sponsor frame: mode          | 1     |
| Send to sponsor frame: flags         | 1     |
| Send to sponsor frame: target        | 20    |
| Send to sponsor frame: gas           | 3     |
| Send to sponsor frame: value         | 1     |
| Send to sponsor frame: calldata      | 68    |
| Sponsor post op frame: mode          | 2     |
| Sponsor post op frame: flags         | 1     |
| Sponsor post op frame: target        | 20    |
| Sponsor post op frame: gas           | 3     |
| Sponsor post op frame: value         | 1     |
| Sponsor post op frame: calldata      | 0     |
| **Total additional**                 | 147   |

Notes: Sponsor can read info from other fields. ERC-20 transfer call is 68 bytes.

There is some inefficiency in the sponsor case, because the same sponsor address must appear in three places (sponsor validation, send to sponsor inside ERC-20 calldata, post op frame), and the ABI is inefficient (~12 + 24 bytes wasted on zeroes). This is difficult to mitigate in a &quot;clean&quot; way, because one of the duplicates is inside the ERC-20 call, &quot;opaque&quot; to the protocol. However, it is much less inefficient than ERC-4337, because not all of the data takes the hit of the 32-byte-per-field ABI overhead.


## Backwards Compatibility

The `ORIGIN` opcode behavior changes for frame transactions, returning the frame&apos;s caller rather than the traditional transaction origin. This is consistent with the precedent set by EIP-7702, which already modified `ORIGIN` semantics. Contracts that rely on `ORIGIN = CALLER` for security checks (a discouraged pattern) may behave differently under frame transactions.

## Security Considerations

### Transaction Propagation

Frame transactions introduce new denial-of-service vectors for transaction pools that node operators must mitigate. Because validation logic is arbitrary EVM code, attackers can craft transactions that appear valid during initial validation but become invalid later. Without any additional policies, an attacker could submit many transactions whose validity depends on some shared state, then submit one transaction that modifies that state, and cause all other transactions to become invalid simultaneously. This wastes the computational resources nodes spent validating and storing these transactions.

#### Example Attack

A simple example is transactions that check `block.timestamp`:

```solidity
function validateTransaction() external {
    require(block.timestamp &lt; SOME_DEADLINE, &quot;expired&quot;);
    // ... rest of validation
    APPROVE(APPROVE_PAYMENT_AND_EXECUTION);
}
```

Such transactions are valid when submitted but become invalid once the deadline passes, without any on-chain action required from the attacker.

#### Deploy Frame Front-Running

If a transaction uses a `deploy` frame, that frame executes before the sender is authenticated. An observer can front-run the same deterministic deployment and cause the `deploy` frame to fail because code is already present at `tx.sender`. Accordingly, initcode used with `deploy` frames must be safe to deploy by any party, and wallets should expect resubmission without the `deploy` frame once deployment has already occurred.

#### Explicit Sender State-Read Amplification

Because `tx.sender` is explicit in the transaction envelope, an attacker can submit many invalid frame transactions that name arbitrary sender addresses and force nodes to read sender state, including the nonce check required before execution. Public mempool implementations should therefore perform all available structural and stateless checks before sender-state access and should consider peer-level rate limiting or other DoS mitigations for repeated invalid transactions that vary `tx.sender`.

#### Cross-Frame Data Visibility During Validation

`FRAMEPARAM`, `FRAMEDATALOAD`, and `FRAMEDATACOPY` allow validation code to inspect other frames, including later `SENDER` frames and their `value`s. As a result, paymasters and other `VERIFY` frames can observe user operation parameters before approval and may condition their behavior on that information. Users should therefore treat non-`VERIFY` frame parameters and data as visible to validation logic and should not rely on untrusted paymasters or verifiers to keep such information private.

##### Mitigations

Node implementations should consider restricting which opcodes and storage slots validation frames can access, similar to ERC-7562. This isolates transactions from each other and limits mass invalidation vectors.

It&apos;s recommended that to *validate* the transaction, a specific frame structure is enforced and the amount of gas that is expended executing the validation phase must be limited. Once the validation prefix reaches payer approval via `APPROVE(APPROVE_PAYMENT)` or `APPROVE(APPROVE_PAYMENT_AND_EXECUTION)`, the transaction can be included in the mempool and propagated to peers safely.

For deployment of the sender account in the first frame, the mempool must only allow the [EIP-7997](/EIPs/EIPS/eip-7997) deterministic factory predeploy as `frame.target`, to ensure deployment is deterministic and independent of chain state.

In general, it can be assumed that handling of frame transactions imposes similar restrictions as EIP-7702 on mempool relay, i.e. only a single transaction can be pending for an account that uses frame transactions.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 29 Jan 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8141</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8141</guid>
      </item>
    
      <item>
        <title>Block-in-Blobs (BiB)</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8142-block-in-blobs-bib/27621</comments>
        
        <description>## Abstract

zkEVMs allow validators to verify the correctness of an execution payload using a proof, without downloading or executing the payload itself. However, removing the requirement to download the execution payload, also removes the implicit data availability (DA) guarantee; a block producer can publish a valid proof and withhold the execution-payload data since attesters no longer need them for consensus.

This EIP introduces Block-in-Blobs (BiB), a mechanism that requires the execution-payload data (transactions and BALs) to be published in blob data, in the same beacon block that carries the corresponding execution payload&apos;s header. This ensures that execution payloads and their associated data are always published even when validators no longer require them to verify the state transition function (STF).

In short, BiB works by having the block producer encode the execution-payload data into blobs as part of the execution layer&apos;s STF, requiring the beacon block’s blob KZG commitments to commit to those payload-blobs.

## Motivation

**Validation via re-execution**

Today, validators verify execution payloads by:

1) Downloading the execution payload
2) Executing the payload locally
3) Checking the resulting state root and other fields against the fields in the header

Implicitly this guarantees execution payload availability because the payload cannot be verified unless the node downloads it.

**Validation with zkEVMs**

With zkEVMs, validators instead:

1) Download a proof attesting to the correctness of the execution payload
2) Download the execution payload header
3) Verify the proof with respects to the payload header (and other commitments)

In this model, validators no longer require access to the full execution payload data itself in order to verify its correctness.

**The DA problem**

Removing the re-execution requirement in consensus removes the implicit requirement that consensus clients download the execution payload.

A malicious or rational builder could:

- Publish a valid proof for a valid execution payload
- Withhold the execution-payload data entirely

*Builders*: Since builders will always need to re-execute in order to build blocks, a malicious builder would not publish the execution payload ensuring that they are the only ones that can build on top of the current chain.

*RPC and indexers*: Many nodes such as RPC providers and indexers cannot solely rely on execution proofs and must re-execute the execution payload.

BiB addresses this by making the execution payload available via blobs.

## Specification

### Terminology

**Type-3 transaction:** Refers to EIP-4844 blob-carrying transactions (transaction type 0x03). These transactions include blob versioned hashes that commit to blobs carrying user data.

### Overview and Invariants

BiB ensures the proven payload is published:

- The beacon block references a list of blob KZG commitments (via 4844/PeerDas)
- A prefix of those commitments is reserved for the execution-payload data encoded into blobs
- A zkEVM proof for the block must bind the proven execution payload to those prefixed blob commitments.

**Payload availability invariant:** A valid block implies there exists an ordered list of blobs whose bytes decode to the canonical execution-payload data, and the KZG commitments for these blobs match the first `payload_blob_count` blob commitments referenced by the block. The existing DAS mechanism will ensure that those blobs are available.

### Parameters

#### Referenced Parameters

These parameters are defined in EIP-4844 and related specs:

| Name | Value | Source |
|------|-------|--------|
| `FIELD_ELEMENTS_PER_BLOB` | `4096` | EIP-4844 |
| `BYTES_PER_FIELD_ELEMENT` | `32` | EIP-4844 |
| `GAS_PER_BLOB` | `2**17` | EIP-4844 |
| `MAX_BLOBS_PER_BLOCK` | Network-specific | EIP-7892 |

**Note on `MAX_BLOBS_PER_BLOCK`:** This constant represents the maximum number of blobs (both payload-blobs and type-3 transaction blobs) that can be included in a block. Per EIP-7892, the execution layer&apos;s `blobSchedule.max` MUST equal the consensus layer&apos;s `MAX_BLOBS_PER_BLOCK` configuration value at any given time. This value may change across forks (e.g., initially 6 in EIP-4844, potentially increased in subsequent blob throughput increase proposals).

#### Derived Constants

| Name | Value | Description |
|------|-------|-------------|
| `USABLE_BYTES_PER_FIELD_ELEMENT` | `BYTES_PER_FIELD_ELEMENT - 1` (31) | Usable bytes per field element (final byte must be zero to stay under BLS modulus) |
| `USABLE_BYTES_PER_BLOB` | `FIELD_ELEMENTS_PER_BLOB * USABLE_BYTES_PER_FIELD_ELEMENT` | Total usable bytes per blob |

### Execution Layer

**Summary:** The execution layer is modified in the following ways:

- The ExecutionPayloadHeader now has a `payload_blob_count` field to track how many blobs are used for the execution payload data, enabling verification of the correct number of payload-blobs at the Engine API boundary.
- `engine_getPayload` computes the payload-blobs when building a block, sets `payload_blob_count` in the ExecutionPayloadHeader, and returns the payload blobs (with their commitments and proofs) alongside type-3 transaction blobs in the response.
- `engine_newPayload` takes the ExecutionPayload and before passing it to the EL STF, it computes the payload-blobs, checks that the amount of blobs needed is equal to the `payload_blob_count` value in the ExecutionPayloadHeader and verifies that the expected version hashes match.

#### Referenced Helpers

The execution layer uses methods and classes defined in the corresponding consensus 4844/7594 specs.

Specifically, we use the following methods from [polynomial-commitments.md](https://github.com/ethereum/consensus-specs/blob/46c1199d6b4584ba484dec807f03b8e6211dd725/specs/deneb/polynomial-commitments.md?#introduction):

- [verify_blob_kzg_proof_batch](https://github.com/ethereum/consensus-specs/blob/46c1199d6b4584ba484dec807f03b8e6211dd725/specs/deneb/polynomial-commitments.md#L578)
- [blob_to_kzg_commitment](https://github.com/ethereum/consensus-specs/blob/86fb82b221474cc89387fa6436806507b3849d88/specs/deneb/polynomial-commitments.md#blob_to_kzg_commitment)
- [compute_blob_kzg_proof](https://github.com/ethereum/consensus-specs/blob/86fb82b221474cc89387fa6436806507b3849d88/specs/deneb/polynomial-commitments.md#compute_blob_kzg_proof)

And the following methods from [polynomial-commitments-sampling.md](https://github.com/ethereum/consensus-specs/blob/2938e1ad74cea54f1a24508a85704d5bd87837ad/specs/fulu/polynomial-commitments-sampling.md):

- [compute_cells_and_kzg_proofs](https://github.com/ethereum/consensus-specs/blob/2938e1ad74cea54f1a24508a85704d5bd87837ad/specs/fulu/polynomial-commitments-sampling.md#compute_cells_and_kzg_proofs)

And the following methods from [beacon-chain.md](https://github.com/ethereum/consensus-specs/blob/86fb82b221474cc89387fa6436806507b3849d88/specs/deneb/beacon-chain.md#introduction):

- [kzg_commitment_to_versioned_hash](https://github.com/ethereum/consensus-specs/blob/86fb82b221474cc89387fa6436806507b3849d88/specs/deneb/beacon-chain.md#kzg_commitment_to_versioned_hash)

#### Helpers

##### bytes_to_blobs

```python
def bytes_to_blobs(data: bytes) -&gt; List[Blob]:
    &quot;&quot;&quot;
    Pack arbitrary bytes into one or more blobs.
    Remaining space in final blob is zero-padded.
    &quot;&quot;&quot;
    blobs = []
    offset = 0

    while offset &lt; len(data):
        chunk = data[offset : offset + USABLE_BYTES_PER_BLOB]
        blob = chunk_to_blob(chunk)
        blobs.append(blob)
        offset += USABLE_BYTES_PER_BLOB

    return blobs


def chunk_to_blob(data: bytes) -&gt; Blob:
    &quot;&quot;&quot;
    Pack up to USABLE_BYTES_PER_BLOB bytes into a single blob.
    If data is shorter than USABLE_BYTES_PER_BLOB, it is zero-padded.
    Each 31-byte chunk is stored in bytes [0:31] of a field element,
    with byte [31] (the final byte) set to zero to ensure value &lt; BLS modulus.
    &quot;&quot;&quot;
    assert len(data) &lt;= USABLE_BYTES_PER_BLOB

    # Pad to exactly USABLE_BYTES_PER_BLOB if needed
    if len(data) &lt; USABLE_BYTES_PER_BLOB:
        data = data + bytes(USABLE_BYTES_PER_BLOB - len(data))

    blob = bytearray(FIELD_ELEMENTS_PER_BLOB * BYTES_PER_FIELD_ELEMENT)

    for i in range(FIELD_ELEMENTS_PER_BLOB):
        chunk_start = i * USABLE_BYTES_PER_FIELD_ELEMENT
        chunk = data[chunk_start : chunk_start + USABLE_BYTES_PER_FIELD_ELEMENT]

        # Store 31 data bytes in [0:31], the final byte [31] stays zero
        blob[i * BYTES_PER_FIELD_ELEMENT : i * BYTES_PER_FIELD_ELEMENT + USABLE_BYTES_PER_FIELD_ELEMENT] = chunk

    return Blob(blob)
```

##### blobs_to_bytes

```python
def blobs_to_bytes(blobs: List[Blob]) -&gt; bytes:
    &quot;&quot;&quot;
    Unpack blobs back to bytes.
    Returns all usable bytes from all blobs (including any padding).
    &quot;&quot;&quot;
    raw = bytearray()

    for blob in blobs:
        raw.extend(blob_to_chunk(blob))

    return bytes(raw)


def blob_to_chunk(blob: Blob) -&gt; bytes:
    &quot;&quot;&quot;
    Extract the 31 usable bytes from each field element.
    Validates that the final byte is zero for each field element.
    &quot;&quot;&quot;
    result = bytearray()

    for i in range(FIELD_ELEMENTS_PER_BLOB):
        # Validate final byte is zero
        assert blob[i * BYTES_PER_FIELD_ELEMENT + USABLE_BYTES_PER_FIELD_ELEMENT] == 0x00, &quot;Invalid blob: final byte must be zero&quot;

        # Extract usable data bytes
        result.extend(blob[i * BYTES_PER_FIELD_ELEMENT : i * BYTES_PER_FIELD_ELEMENT + USABLE_BYTES_PER_FIELD_ELEMENT])

    return bytes(result)
```

##### get_execution_payload_data

```python
def get_execution_payload_data(payload: ExecutionPayload) -&gt; ExecutionPayloadData:
    &quot;&quot;&quot;
    Extract the data from an ExecutionPayload that must be made available via blobs.
    &quot;&quot;&quot;
    return ExecutionPayloadData(
        blockAccessList=payload.blockAccessList,
        transactions=payload.transactions,
    )
```

##### execution_payload_data_to_blobs

```python
def execution_payload_data_to_blobs(data: ExecutionPayloadData) -&gt; List[Blob]:
    &quot;&quot;&quot;
    Canonically encode the execution-payload data into an ordered list of blobs.

    Encoding steps:
      1. bal_bytes = data.blockAccessList
      2. transactions_bytes = RLP.encode(data.transactions)
      3. Create 8-byte header: [4 bytes BAL length][4 bytes tx length]
      4. payload_bytes = header + bal_bytes + transactions_bytes
      5. return bytes_to_blobs(payload_bytes)

    The first blob will contain (in order):
      - [4 bytes] BAL data length
      - [4 bytes] Transaction data length
      - [variable] BAL data (may span multiple blobs)
      - [variable] Transaction data (may span multiple blobs)

    This allows extracting just the BAL data without transactions.

    Note: blockAccessList is already RLP-encoded per EIP-7928. Transactions are RLP-encoded as a list.
    &quot;&quot;&quot;
    bal_bytes = data.blockAccessList
    transactions_bytes = RLP.encode(data.transactions)

    # Create 8-byte header: [4 bytes BAL length][4 bytes tx length]
    bal_length = len(bal_bytes).to_bytes(4, &apos;little&apos;)
    txs_length = len(transactions_bytes).to_bytes(4, &apos;little&apos;)
    header = bal_length + txs_length

    # Combine header + data
    payload_bytes = header + bal_bytes + transactions_bytes

    return bytes_to_blobs(payload_bytes)
```

##### blobs_to_execution_payload_data

```python
def blobs_to_execution_payload_data(blobs: List[Blob]) -&gt; ExecutionPayloadData:
    &quot;&quot;&quot;
    Canonically decode an ordered list of blobs into execution-payload data.

    Decoding steps:
      1. raw = blobs_to_bytes(blobs)
      2. Read 8-byte header: [4 bytes BAL length][4 bytes tx length]
      3. Split into bal_bytes and transactions_bytes
      4. return ExecutionPayloadData(blockAccessList, transactions)
    &quot;&quot;&quot;
    # Extract raw bytes from blobs
    raw = blobs_to_bytes(blobs)

    # Read 8-byte header
    bal_length = int.from_bytes(raw[0:4], &apos;little&apos;)
    txs_length = int.from_bytes(raw[4:8], &apos;little&apos;)

    # Extract data portions
    bal_bytes = raw[8 : 8 + bal_length]
    transactions_bytes = raw[8 + bal_length : 8 + bal_length + txs_length]

    # Decode transactions
    transactions = RLP.decode(transactions_bytes)

    return ExecutionPayloadData(blockAccessList=bal_bytes, transactions=transactions)
```

##### extract_data_from_type_3_tx

This method will be used to implement the modified logic in engine_getPayload.

```python
def extract_data_from_type_3_tx(transactions: List[Transaction]) -&gt; Tuple[List[Blob], List[KZGCommitment], List[List[KZGProof]]]:
    &quot;&quot;&quot;
    Extract blobs, KZG commitments, and cell proofs from type-3 (blob) transactions.

    Returns a tuple of (blobs, commitments, cell_proofs) in the order they appear
    in the transaction list.

    Implementation note: This is not new logic - a function(s) like this should already be available in your existing getPayload/blob bundle implementation.
    &quot;&quot;&quot;
    ...
```

**Invertibility invariant:** `execution_payload_data_to_blobs` and `blobs_to_execution_payload_data` are mutual inverses on valid execution-payload data.

#### Data structures

##### ExecutionPayloadData

**Execution-payload data** refers to the subset of the ExecutionPayload that must be made available via blobs. This includes:

- `bals` (Block Access List added in EIP-7928)
- `transactions`

See [What is included in execution-payload data?](#what-is-included-in-execution-payload-data) in the Rationale for details.

```python
class ExecutionPayloadData(Container):
    # Block Access List (BAL) from EIP-7928, RLP-encoded
    blockAccessList: bytes
    # List of transactions, each transaction is RLP-encoded
    transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD]
```

**Note:** This is not an SSZ Container - fields are RLP-encoded as described in the encoding functions. The `MAX_TRANSACTIONS_PER_PAYLOAD` bound is inherited from the ExecutionPayload field limit defined in the consensus specification.

##### ExecutionPayloadHeader

This EIP adds a new field to the `ExecutionPayloadHeader`:

- payload_blob_count : uint64

Semantics:

- Let `blob_kzg_commitments` be the ordered list of kzg commitments referenced by the beacon block
- The first `payload_blob_count` entries of `blob_kzg_commitments` are the payload-blob commitments (i.e. commitments to the blobs that correspond to the payload data)
- The remaining entries (if any) are for type-3 blob transactions.

##### BlobsBundle

For the zkEVM-optimized variant of `engine_getPayload`, this EIP extends `BlobsBundle` with an additional field:

- `payload_kzg_proofs`: List[KZGProof]

Semantics:

- Contains random point KZG proofs for payload blobs only (not type-3 transaction blobs)
- Used as private inputs to the zkEVM circuit for payload consistency verification via `verify_blob_kzg_proof_batch`
- The length of this list equals `payload_blob_count`

#### Engine API

This section specifies two equivalent formulations of `new_payload`. Implementers choose one based on their execution context:

- **Native execution variant**: Uses `blob_to_kzg_commitment` directly. Suitable for pre mandatory proofs implementations.
- **zkEVM-optimized variant**: Uses polynomial openings via `verify_blob_kzg_proof_batch`. Avoids the multiscalar multiplication (MSM) which is expensive to prove in a zkEVM circuit.

Both variants enforce identical validity conditions. A block valid under one is valid under the other.

##### engine_getPayload - Native Variant

The builder must compute the payload blob count when constructing the block:

```python
def get_payload(payload_id: PayloadId) -&gt; GetPayloadResponse:
    # 1. Build the block (select transactions, etc.)
    payload = build_execution_payload(payload_id)

    # 2. Compute payload blobs to determine count
    payload_data = get_execution_payload_data(payload)
    payload_blobs = execution_payload_data_to_blobs(payload_data)
    payload_blob_count = len(payload_blobs)

    # 4. Set the count in the header
    payload.payload_blob_count = payload_blob_count

    # 5. Compute blob commitments and cell proofs for payload blobs
    payload_commitments = [blob_to_kzg_commitment(b) for b in payload_blobs]
    payload_versioned_hashes = [kzg_commitment_to_versioned_hash(c) for c in payload_commitments]
    # Compute cells and cell proofs
    payload_cells_and_proofs = [compute_cells_and_kzg_proofs(b) for b in payload_blobs]
    payload_cell_proofs = [proofs for _, proofs in payload_cells_and_proofs]

    # 6. Extract type-3 transaction blobs, commitments, and cell proofs
    type3_blobs, type3_commitments, type3_cell_proofs = extract_data_from_type_3_tx(payload.transactions)
    type3_versioned_hashes = []
    for tx in payload.transactions:
        if tx.type == BLOB_TX_TYPE:
            type3_versioned_hashes.extend(tx.blob_versioned_hashes)

    # 7. Combine: payload blobs first, then type-3 blobs
    all_blobs = payload_blobs + type3_blobs
    all_commitments = payload_commitments + type3_commitments
    all_cell_proofs = payload_cell_proofs + type3_cell_proofs
    all_blob_versioned_hashes = payload_versioned_hashes + type3_versioned_hashes

    return GetPayloadResponse(
        execution_payload=payload,
        blobs_bundle=BlobsBundle(
            commitments=all_commitments,
            blobs=all_blobs,
            proofs=all_cell_proofs
        ),
        block_value=calculate_block_value(payload)
    )
```

Note: The builder must account for payload blob usage when selecting type-3 transactions to ensure the total blob count does not exceed `MAX_BLOBS_PER_BLOCK`.

##### engine_getPayload - zkEVM-Optimized Variant

For the zkEVM-optimized variant, the builder must additionally compute random point KZG proofs for the payload blobs, which will be used as private inputs in the zkEVM circuit for payload consistency verification.

This variant extends `BlobsBundle` with an additional `payload_kzg_proofs` field containing random point KZG proofs for payload blobs.

```python
def get_payload_zk(payload_id: PayloadId) -&gt; GetPayloadResponse:
    # 1. Build the block (select transactions, etc.)
    payload = build_execution_payload(payload_id)

    # 2. Compute payload blobs to determine count
    payload_data = get_execution_payload_data(payload)
    payload_blobs = execution_payload_data_to_blobs(payload_data)
    payload_blob_count = len(payload_blobs)

    # 4. Set the count in the header
    payload.payload_blob_count = payload_blob_count

    # 5. Compute commitments, cell proofs, and random point proofs for payload blobs
    payload_commitments = [blob_to_kzg_commitment(b) for b in payload_blobs]
    payload_versioned_hashes = [kzg_commitment_to_versioned_hash(c) for c in payload_commitments]
    # Cell proofs
    payload_cells_and_proofs = [compute_cells_and_kzg_proofs(b) for b in payload_blobs]
    payload_cell_proofs = [proofs for _, proofs in payload_cells_and_proofs]
    # Random point proofs for payload consistency verification
    payload_random_point_proofs = [compute_blob_kzg_proof(b, c) for b, c in zip(payload_blobs, payload_commitments)]

    # 6. Extract type-3 transaction blobs, commitments, and cell proofs
    type3_blobs, type3_commitments, type3_cell_proofs = extract_data_from_type_3_tx(payload.transactions)
    type3_versioned_hashes = []
    for tx in payload.transactions:
        if tx.type == BLOB_TX_TYPE:
            type3_versioned_hashes.extend(tx.blob_versioned_hashes)

    # 7. Combine: payload blobs first, then type-3 blobs
    all_blobs = payload_blobs + type3_blobs
    all_commitments = payload_commitments + type3_commitments
    all_cell_proofs = payload_cell_proofs + type3_cell_proofs

    return GetPayloadResponse(
        execution_payload=payload,
        blobs_bundle=BlobsBundle(
            commitments=all_commitments,
            blobs=all_blobs,
            proofs=all_cell_proofs,
            payload_kzg_proofs=payload_random_point_proofs
        ),
        block_value=calculate_block_value(payload)
    )
```

**Note for implementors:**

- The `payload_kzg_proofs` field contains KZG opening proofs for payload blobs only. It is used for payload consistency verification via `verify_blob_kzg_proof_batch`.
- The builder/prover should extract the first `payload_blob_count` commitments from `all_commitments` (i.e., `all_commitments[:payload_blob_count]`). This corresponds to the `payload_kzg_commitments` parameter in the zkEVM variant of `engine_newPayload`.

##### engine_newPayload - Native Execution Variant

```python
def new_payload(
    payload: ExecutionPayload,
    expected_blob_versioned_hashes: List[VersionedHash],
    ...
) -&gt; PayloadStatus:

    # 1. Derive payload blobs and commitments
    payload_data = get_execution_payload_data(payload)
    payload_blobs = execution_payload_data_to_blobs(payload_data)
    payload_blob_count = len(payload_blobs)
    payload_commitments = [blob_to_kzg_commitment(b) for b in payload_blobs]
    payload_versioned_hashes = [kzg_commitment_to_versioned_hash(c) for c in payload_commitments]

    # 2. Verify payload_blob_count matches header
    assert payload_blob_count == payload.payload_blob_count

    # 3. Extract type-3 tx versioned hashes
    type3_versioned_hashes = []
    for tx in payload.transactions:
        if tx.type == BLOB_TX_TYPE:
            type3_versioned_hashes.extend(tx.blob_versioned_hashes)

    # 4. Verify versioned hashes: payload blobs first, then type-3
    assert expected_blob_versioned_hashes == payload_versioned_hashes + type3_versioned_hashes

    # 5. Run EL STF
    return execute_payload(payload)
```

##### engine_newPayload - zkEVM-Optimized Variant

**Note:** Once zkEVM proofs are required for consensus, `newPayload` will be executed inside a zkEVM to generate a proof, rather than being executed natively by validators. This variant is designed to be cheaper in that context.

This variant replaces the MSM in `blob_to_kzg_commitment` with polynomial opening proofs, which are cheaper to verify inside a zkEVM. The payload, commitments and KZG proofs are private inputs to the zkEVM circuit, while the corresponding versioned hashes (and payload header) are public inputs.

```python
def new_payload(
    payload: ExecutionPayload,
    expected_blob_versioned_hashes: List[VersionedHash], # public input

    # BiB additions: prefix metadata for payload blobs
    payload_kzg_commitments: List[KZGCommitment],  # private input
    payload_kzg_proofs: List[KZGProof],            # private input
    ...
) -&gt; PayloadStatus:

    # 0. Declared payload blob count from the header
    n = payload.payload_blob_count
    assert len(payload_kzg_commitments) == n
    assert len(payload_kzg_proofs) == n

    # 1. Construct payload blobs from execution-payload data
    payload_data = get_execution_payload_data(payload)
    payload_blobs = execution_payload_data_to_blobs(payload_data)
    assert len(payload_blobs) == n

    # 2. Check the commitments correspond to the expected versioned hash prefix
    payload_versioned_hashes = [
        kzg_commitment_to_versioned_hash(c) for c in payload_kzg_commitments
    ]
    assert expected_blob_versioned_hashes[:n] == payload_versioned_hashes

    # 3. Verify blob–commitment consistency using batch KZG proof verification
    assert verify_blob_kzg_proof_batch(
        blobs=payload_blobs,
        commitments=payload_kzg_commitments,
        proofs=payload_kzg_proofs
    )

    # 4. Proceed with standard EL payload validation / execution
    return execute_payload(payload)
```

### Consensus Layer

#### Validation

The consensus layer does not introduce new blob specific validation rules for payload-blobs beyond what we have for EIP-4844/EIP-7594.

The Consensus Layer relies on `payload_blob_count` in the ExecutionPayloadHeader to interpret the ordering of blob commitments, but otherwise treats payload blobs identically to other blobs for availability and networking.

### Integration with EIP-7732 (ePBS)

This EIP deprecates the `ExecutionPayloadEnvelope` from [EIP-7732](/EIPs/EIPS/eip-7732). Transactions and BAL are published in blobs; all other payload fields move to `ExecutionPayloadBid`:

```python
class ExecutionPayloadBid(Container):
    # Fields from EIP-7732 (unchanged)
    parent_block_hash: Hash32
    parent_block_root: Root
    block_hash: Hash32
    prev_randao: Bytes32
    fee_recipient: ExecutionAddress
    gas_limit: uint64
    builder_index: BuilderIndex
    slot: Slot
    value: Gwei
    execution_payment: Gwei
    blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK]
    # [New in BiB] Execution payload header fields
    state_root: Root
    receipts_root: Root
    logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM]
    block_number: uint64
    gas_used: uint64
    timestamp: uint64
    extra_data: ByteList[MAX_EXTRA_DATA_BYTES]
    base_fee_per_gas: uint256
    excess_blob_gas: uint64
    payload_blob_count: uint64
    # [New in BiB] For CL state transition
    execution_requests: ExecutionRequests
```

### Networking

BiB reuses the existing blob networking mechanism. Nodes reconstruct the execution payload from the bid (header fields) and blobs (transactions, BAL).

Unlike most type-3 blob transactions, payload-blobs will not have been propagated before block building, which may imply higher bandwidth requirements from builders.

### Fee Accounting

BiB introduces protocol mandated blob usage, rather than user initiated via type-3 transactions. Fee accounting for payload-blobs differ in nature from transaction blob fees as a result.

#### Who pays?

This EIP does not mandate that payload-blobs pay a per-blob fee like transaction blobs.

Instead payload-blobs are treated as a protocol-accepted cost when constructing the block. In particular:

- Payload-blobs do not correspond to a user transaction and therefore do not naturally map to a user-paid blob fee.
- The cost of including payload-blobs, in terms of blob gas usage, is accepted by the protocol as a necessary cost for maintaining data availability.

#### Do payload-blobs compete with transaction blobs for capacity?

Because payload blobs consume blob gas, they directly influence blob congestion and the blob base fee.

#### Can a builder artificially inflate blob gas usage?

A potential concern is whether a malicious builder could create artificially large execution payloads to inflate blob gas usage.

This attack is economically constrained: to increase the size of the execution payload, a builder must include additional transactions with calldata. Since calldata costs execution gas, the builder would need to pay for this additional data through the normal gas mechanism. The cost of including extra calldata makes it economically unfavorable to artificially inflate payload size solely to manipulate blob fees.

#### Open questions and future considerations

&lt;!-- TODO --&gt;
- Networking related: Payload-blobs require higher bandwidth due to the fact that they will not have been in the public mempool
- Explicit protocol level pricing for payload blobs

## Rationale

### What is included in execution-payload data?

Execution-payload data includes `bals` (Block Access Lists from EIP-7928) and `transactions`.

**Why transactions?** Transaction data is the only component of the execution payload that cannot be derived from other components and is not provided by the consensus layer.

**Why BALs?** While BALs are technically the output of executing transactions and could be recomputed, once zkEVM proofs become mandatory for consensus, validators no longer execute payloads. A malicious builder could publish a valid proof and withhold both the execution payload data and the BALs. This would prevent other builders from constructing subsequent blocks and prevent RPC providers from serving the full state. Including BALs in payload-blobs ensures they remain available.

**Why not withdrawals?** Withdrawals can be derived on the consensus layer.

**Why not execution requests?** Execution requests can be recomputed from transactions and do not suffer from the same withholding attack as BALs because they are required by the consensus layer for validation.

**Why not the header?** The header cannot be put into blobs because it contains `payload_blob_count`, which depends on the number of blobs; causing a circular dependency.

**Encoding optimization:** The encoding includes an 8-byte header: `[4 bytes BAL length][4 bytes transaction length]`. This allows extracting just the BAL data without parsing transactions.

&lt;!-- TODO --&gt;
TODO: We could also put the number of blobs that the BAL occupies in the execution payload header.

### Builder discretion vs reserving `k` blobs

This EIP specifies that the block builder choose `payload_blob_count`, subject to the constraint imposed by `MAX_BLOBS_PER_BLOCK`.

An alternative would have been to always reserve `k` blobs, where `k` corresponds to the worst case execution payload size. While this provides better predictability, it reduces flexibility under blob congestion.

### Why not encode execution-payload data inside the core EL execution logic?

Doing it in the EL STF would require payload-blob commitments or versioned hashes to be made visible inside the core execution logic, rather than being handled at the Engine API boundary.

### When zkEVM proofs become mandatory, why can&apos;t zk-attestors download the full execution payload?

The execution payload grows linearly with the gas limit. Requiring attesters to download the payload for DA would create an increasing bandwidth burden as the gas limit grows. 

### Compression algorithm for encoding execution-payload data

Compression can be used on the serialized execution-payload data. This (in theory) should allow the usage of less payload-blobs, depending on the compression ratio. The tradeoffs being:

- That we will use more CPU/proving cycles for decompression
- A breaking change since we want to decompress on the hot-path. What this means is that the transactions would need to be compressed in the payload, and then decompressed when we attempt to validate it. 

Whether we should use a compression algorithm and which one requires more investigation, in particular we need to investigate:

- The average compression ratios achieved
- The proving cycle overhead
- The invasiveness of now requiring consensus aware objects to be compressed when passed for validation.

For now we recommend using no compression algorithm and operating on uncompressed data.

### Serialization algorithm for encoding execution-payload data

Serialization of the execution-payload data uses RLP. Since transactions in the ExecutionPayload are already RLP-encoded, we simply RLP-encode the list of transaction bytes without any additional transformation.

While a more zk-friendly serialization algorithm could be beneficial in the future, this EIP uses RLP for simplicity. Once EIP-7807 (SSZ execution blocks) is implemented, the encoding can be updated to SSZ-serialize the list of SSZ-encoded transaction bytes.

## Backwards Compatibility

This requires changes to the execution payload header and the EL STF; so requires a fork. Nodes that do not implement BiB will not be able to validate blocks after activation.

## Test Cases

&lt;!-- TODO --&gt;
TODO

## Reference Implementation

&lt;!-- TODO --&gt;
TODO

## Security Considerations

**Interaction with blob congestion and denial-of-service**

Payload-blobs consume blob gas and therefore are subject to the same congestion control mechanisms and blob limits as transaction blobs.

As a byproduct, this ensures that a malicious block producer cannot make arbitrarily large execution payloads without accounting for blob gas limits. While a block producer could theoretically drive up the blob base fee by creating large payloads, this attack is economically constrained by calldata costs (see [Fee Accounting](#fee-accounting) for details).

**Data withholding**

An attacker cannot withhold execution payload data without also withholding blob data, which would violate existing DAS guarantees and cause the block to be rejected by the consensus layer.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 29 Jan 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8142</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8142</guid>
      </item>
    
      <item>
        <title>Block Access List Sidecars</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8146-block-access-list-sidecars/27757</comments>
        
        <description>## Abstract

This EIP removes the block access list (BAL) from the `ExecutionPayloadEnvelope` and propagates it as an independent sidecar on a dedicated gossip topic. Builders commit to the BAL root in their `ExecutionPayloadBid`. Sidecar verification uses this commitment; no separate signature is required. The Payload Timeliness Committee (PTC) enforces BAL availability at the attestation deadline.

## Motivation

[EIP-7928](/EIPs/EIPS/eip-7928) adds block access lists to the `ExecutionPayload`. Under [EIP-7732](/EIPs/EIPS/eip-7732), the execution payload travels inside a `SignedExecutionPayloadEnvelope` that the builder broadcasts after the beacon block. Including the BAL (~70 KiB average, up to 1 MiB) in the envelope increases its size and propagation latency on the critical path.

Separating the BAL into a sidecar reduces envelope size, improving propagation. The BAL remains required for execution validation; the PTC enforces availability so that the BAL is present before the payload processing deadline.

## Specification

### Consensus Layer

#### Presets

| Name | Value |
| - | - |
| `MAX_BLOCK_ACCESS_LIST_SIZE` | `uint64(2**23)` (= 8 MiB) |


#### Types

The `BlockAccessList` type from [EIP-7928](/EIPs/EIPS/eip-7928):

| Name | SSZ equivalent | Description |
| - | - | - |
| `BlockAccessList` | `ByteList[MAX_BLOCK_ACCESS_LIST_SIZE]` | RLP-encoded block access list |

#### Modified Containers

##### `ExecutionPayload`

The `block_access_list` field introduced by [EIP-7928](/EIPs/EIPS/eip-7928) is removed:

```python
class ExecutionPayload(Container):
    parent_hash: Hash32
    fee_recipient: ExecutionAddress
    state_root: Bytes32
    receipts_root: Bytes32
    logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM]
    prev_randao: Bytes32
    block_number: uint64
    gas_limit: uint64
    gas_used: uint64
    timestamp: uint64
    extra_data: ByteList[MAX_EXTRA_DATA_BYTES]
    base_fee_per_gas: uint256
    block_hash: Hash32
    transactions: List[Transaction, MAX_TRANSACTIONS_PER_PAYLOAD]
    withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD]
    blob_gas_used: uint64
    excess_blob_gas: uint64
    # [Removed in EIP-8143]
    # block_access_list: BlockAccessList
```

##### `ExecutionPayloadBid`

A `block_access_list_root` field is added:

```python
class ExecutionPayloadBid(Container):
    parent_block_hash: Hash32
    parent_block_root: Root
    block_hash: Hash32
    prev_randao: Bytes32
    fee_recipient: ExecutionAddress
    gas_limit: uint64
    builder_index: BuilderIndex
    slot: Slot
    value: Gwei
    execution_payment: Gwei
    blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK]
    # [New in EIP-8143]
    block_access_list_root: Root
```

##### `PayloadAttestationData`

A `block_access_list_present` field is added:

```python
class PayloadAttestationData(Container):
    beacon_block_root: Root
    slot: Slot
    payload_present: boolean
    blob_data_available: boolean
    # [New in EIP-8143]
    block_access_list_present: boolean
```

#### New Containers

##### `BlockAccessListSidecar`

```python
class BlockAccessListSidecar(Container):
    beacon_block_root: Root
    slot: Slot
    block_access_list: BlockAccessList
```

### P2P Networking

#### Gossip

##### Global Topic: `block_access_list_sidecar`

This topic propagates `BlockAccessListSidecar` objects.

The following validations MUST pass before forwarding a `sidecar` on the network:

- _[IGNORE]_ `sidecar.beacon_block_root` has been seen (via gossip or non-gossip sources). A client MAY queue the sidecar for processing once the block is retrieved.
- _[IGNORE]_ No valid `BlockAccessListSidecar` for this `beacon_block_root` has been seen.
- _[IGNORE]_ `sidecar.slot &gt;= compute_start_slot_at_epoch(store.finalized_checkpoint.epoch)`.

Let `block` be the beacon block with root `sidecar.beacon_block_root`. Let `bid` alias `block.body.signed_execution_payload_bid.message`:

- _[REJECT]_ `block` passes validation.
- _[REJECT]_ `sidecar.slot == block.slot`.
- _[REJECT]_ `hash_tree_root(sidecar.block_access_list) == bid.block_access_list_root`.

#### Req/Resp

##### `BlockAccessListSidecarsByRange` v1

**Protocol ID:** `/eth2/beacon_chain/req/block_access_list_sidecars_by_range/1/`

Request Content:

```python
(
    start_slot: Slot
    count: uint64
)
```

Response Content:

```python
List[BlockAccessListSidecar, MAX_REQUEST_PAYLOADS]
```

Returns sidecars in slot range `[start_slot, start_slot + count)`, ordered by slot. The response MUST contain no more than `MAX_REQUEST_PAYLOADS` sidecars. Clients SHOULD respond with at least one sidecar if available.

##### `BlockAccessListSidecarsByRoot` v1

**Protocol ID:** `/eth2/beacon_chain/req/block_access_list_sidecars_by_root/1/`

Request Content:

```python
List[Root, MAX_REQUEST_PAYLOADS]
```

Response Content:

```python
List[BlockAccessListSidecar, MAX_REQUEST_PAYLOADS]
```

Returns sidecars matching the requested beacon block roots.

### Fork Choice

#### Modified `Store`

```python
@dataclass
class Store(object):
    # ... existing fields ...
    # [New in EIP-8143]
    block_access_lists: Dict[Root, BlockAccessList] = field(default_factory=dict)
    # [New in EIP-8143]
    ptc_block_access_list_vote: Dict[Root, Vector[boolean, PTC_SIZE]] = field(default_factory=dict)
```

#### Modified `on_block`

When a new block is added to the store, initialize the BAL PTC vote tracker (alongside the existing `ptc_vote` initialization):

```python
# [New in EIP-8143] Add a new PTC BAL voting for this block to the store
store.ptc_block_access_list_vote[block_root] = [False] * PTC_SIZE
```

#### Modified `on_payload_attestation_message`

The handler records the BAL availability vote alongside the existing payload presence vote:

```python
def on_payload_attestation_message(
    store: Store, ptc_message: PayloadAttestationMessage, is_from_block: bool = False
) -&gt; None:
    # ... existing validation and payload_present recording ...

    # [New in EIP-8143] Update the BAL vote for the block
    ptc_block_access_list_vote = store.ptc_block_access_list_vote[data.beacon_block_root]
    ptc_block_access_list_vote[ptc_index] = data.block_access_list_present
```

#### Modified `notify_ptc_messages`

When extracting `PayloadAttestationMessage` objects from `PayloadAttestation` aggregates in a beacon block, the `block_access_list_present` field is propagated from the attestation data.

#### New `on_block_access_list_sidecar`

```python
def on_block_access_list_sidecar(store: Store, sidecar: BlockAccessListSidecar) -&gt; None:
    # The beacon block must be known
    assert sidecar.beacon_block_root in store.blocks
    block = store.blocks[sidecar.beacon_block_root]

    # Verify slot consistency
    assert sidecar.slot == block.slot

    # Verify BAL matches commitment in bid
    bid = block.body.signed_execution_payload_bid.message
    assert hash_tree_root(sidecar.block_access_list) == bid.block_access_list_root

    # Store BAL
    store.block_access_lists[sidecar.beacon_block_root] = sidecar.block_access_list

    # Notify the EL for early prefetching or post-state root calculation
    EXECUTION_ENGINE.notify_block_access_list(sidecar.block_access_list, bid.block_hash)
```

#### Modified `on_execution_payload`

BAL availability is required before processing the execution payload. The BAL has already been delivered to the EL via `engine_notifyBlockAccessListV1` when the sidecar was received; `process_execution_payload` itself is unchanged.

```python
def on_execution_payload(store: Store, signed_envelope: SignedExecutionPayloadEnvelope) -&gt; None:
    envelope = signed_envelope.message
    # The corresponding beacon block root needs to be known
    assert envelope.beacon_block_root in store.block_states

    # Check if blob data is available
    assert is_data_available(envelope.beacon_block_root)

    # Make a copy of the state to avoid mutability issues
    state = copy(store.block_states[envelope.beacon_block_root])

    # Process the execution payload (unchanged)
    process_execution_payload(state, signed_envelope, EXECUTION_ENGINE)

    # Add new state for this payload to the store
    store.execution_payload_states[envelope.beacon_block_root] = state
```

### Engine API

`engine_getPayloadV6` returns the BAL as a separate `blockAccessList` field (RLP-encoded bytes) outside the `ExecutionPayload`. The builder computes `block_access_list_root = hash_tree_root(ByteList(blockAccessList))` for inclusion in the bid.

`engine_notifyBlockAccessListV1` is a new method that delivers the BAL to the EL independently of the execution payload. It accepts `blockAccessList` (RLP-encoded bytes) and `blockHash` (to associate the BAL with the corresponding payload). The EL stores the BAL and begins prefetching the referenced state. The CL calls this method when the BAL sidecar is received (in `on_block_access_list_sidecar`).

`engine_newPayloadV5` is unchanged from [EIP-7732](/EIPs/EIPS/eip-7732). It does not include the BAL. The EL uses the BAL previously delivered via `engine_notifyBlockAccessListV1`, matching by `blockHash`.

### Execution Layer

The execution block header field `block_access_list_hash` (keccak256 of RLP-encoded BAL) is unchanged from [EIP-7928](/EIPs/EIPS/eip-7928). BAL construction and validation rules are as specified in [EIP-7928](/EIPs/EIPS/eip-7928).

### Validator Guide

#### Builders

When constructing a bid, the builder:

1. Obtains the BAL from `engine_getPayloadV6`.
2. Computes `block_access_list_root = hash_tree_root(ByteList(blockAccessList))` and includes it in the `ExecutionPayloadBid`.
3. After the beacon block is published, broadcasts the `BlockAccessListSidecar` on the `block_access_list_sidecar` gossip topic.
4. Broadcasts the `SignedExecutionPayloadEnvelope` (which no longer contains the BAL).

Builders SHOULD broadcast the BAL sidecar as early as possible to enable prefetching by the next block&apos;s builder.

#### PTC Members

PTC members set `block_access_list_present = True` in their `PayloadAttestationData` if they have received a valid `BlockAccessListSidecar` for the block (i.e., the sidecar passes gossip validation including the `hash_tree_root` commitment check).

PTC members set `payload_present` and `blob_data_available` per [EIP-7732](/EIPs/EIPS/eip-7732) rules, independently of `block_access_list_present`.

## Rationale

### No Separate Signature

The BAL sidecar requires no BLS signature. The builder commits to `block_access_list_root` in the signed `ExecutionPayloadBid`; verification is `hash_tree_root(sidecar.block_access_list) == bid.block_access_list_root`. This mirrors `DataColumnSidecar` verification via KZG proofs against commitments in the bid.

### Separate PTC Field

BAL availability is tracked as a dedicated `block_access_list_present` boolean in `PayloadAttestationData`, following the same pattern as `blob_data_available`. This keeps concerns separated: `payload_present` signals envelope timeliness, `blob_data_available` signals blob availability, and `block_access_list_present` signals BAL availability. The fork choice `on_execution_payload` handler independently gates on local BAL availability (`assert root in store.block_access_lists`), ensuring execution validation cannot proceed without the BAL regardless of PTC votes.

### PTC Deadline Independence

[EIP-7732](/EIPs/EIPS/eip-7732) applies a variable PTC deadline to the execution payload based on payload size. Since the BAL travels as an independent sidecar, and its size scales inversely with the payload size, this variable deadline does not apply to it.

### Dedicated Engine API Method

The BAL is delivered to the EL exclusively via `engine_notifyBlockAccessListV1`, separate from `engine_newPayloadV5`. This enables early delivery: the BAL sidecar typically arrives before the execution payload envelope, so the EL can begin prefetching storage slots immediately, or start calculating the post-state root. When the payload arrives later, `engine_newPayloadV5` proceeds without the BAL -- the EL already has it, matched by `blockHash`.

### Data Retention

Clients MUST retain BAL sidecars for at least `MIN_EPOCHS_FOR_BAL_SIDECARS_REQUESTS` epochs to support syncing nodes. After this period, clients MAY prune sidecars.

## Backwards Compatibility

This EIP requires a hard fork. It modifies the `ExecutionPayload` and `ExecutionPayloadBid` containers from [EIP-7732](/EIPs/EIPS/eip-7732) and changes how [EIP-7928](/EIPs/EIPS/eip-7928) BALs are propagated.

## Security Considerations

**Withholding**: A builder can withhold the BAL sidecar. PTC members will vote `block_access_list_present = False`, providing network-wide visibility. The fork choice `on_execution_payload` handler gates on local BAL availability, so the payload cannot be validated without the BAL. The builder withhold safety properties from [EIP-7732](/EIPs/EIPS/eip-7732) apply: if the beacon block was not timely, the builder is not charged.

**Network overhead**: The BAL sidecar adds ~70 KiB average per slot to gossip traffic, equal to the current overhead when BAL is inside the envelope. Total network load is unchanged; it is redistributed across topics.

**Verification cost**: Sidecar verification requires one `hash_tree_root` computation on up to 1 MiB. This is negligible compared to execution validation.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 03 Feb 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8146</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8146</guid>
      </item>
    
      <item>
        <title>Custom sweep threshold for validators</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8148-custom-sweep-threshold-for-validators/27669</comments>
        
        <description>## Abstract

This EIP proposes an optional mechanism to set custom balance thresholds for sweep withdrawals for compounding withdrawal credentials (`0x02, 0x03`) validators. This mechanism allows validators to specify above which balance they want their rewards to be swept to their withdrawal address, providing greater flexibility and control over their staking rewards.

## Motivation

The current default sweep threshold (2,048 ETH) for validators using compounding withdrawal credentials (`0x02, 0x03`) may not meet the needs of all validators. Some validators may prefer to accumulate rewards on the validator balance, while others may want to sweep before reaching the current threshold of 2,048 ETH. By allowing optional custom sweep thresholds, validators can optimize their reward management according to their individual strategies and preferences.

Since the introduction of the `0x02` compounding withdrawal credentials type, we have observed a very low rate of validators transitioning to `0x02`. One reason is that many validators do not want to wait until they accumulate 2048 ETH in rewards before being able to participate in the automatic sweep of withdrawals. While partial withdrawals were considered a viable method for manually withdrawing portions of the validator balance, this approach was not widely adopted by staking protocols, node operators, and solo stakers for several reasons. First, it requires a user-initiated transaction to perform a withdrawal. Second, partial withdrawals utilize the general exit queue, which makes the time between partial withdrawal initiation and fulfillment unpredictable and heavily dependent on network conditions (see the recent spike in exit queue size in October 2025). This EIP aims to address this issue by allowing validators to set a custom threshold for sweep withdrawals.

A simple example illustrates the utility of this feature. Consider a validator who wishes to accumulate rewards on their validator balance until reaching 128 ETH, at which point they want to sweep the rewards to their withdrawal address. Without this feature, the validator would have to initiate partial withdrawals at certain intervals manually and wait in the partial withdrawals queue, which can be time-consuming and inconvenient. The first inconvenience is that if staking protocols widely adopt partial withdrawals at some point, the queue for these withdrawals might become long and unpredictable, similar to the exit queue. The second inconvenience is that the user must monitor the validator&apos;s balance and manually initiate partial withdrawals, which adds complexity and overhead to the staking process. The third inconvenience is the frequency with which the validator can request partial withdrawals. A 128-ETH validator will receive approximately 0.07 ETH in rewards each week. Initiating partial withdrawals TX, for such a low amount might be considered unreasonable. At the same time, the sweep cycle will likely drop to a weekly cycle relatively soon, allowing the validator to automatically receive these 0.07 ETH of rewards on their withdrawal credentials. In general, with this EIP, the validator can set their desired sweep threshold and automatically benefit from sweep withdrawals.

The proposed mechanism is completely optional and does not change anything in the default registration / withdrawal / exit process for validators. It&apos;s just an additional feature that could be ignored if not interesting, but provides a useful feature for many validators incentivizing switching to compounding validators.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

### Constants

#### Execution layer

| Name                                                  | Value                                        | Comment                                                                              |
| ----------------------------------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------ |
| `SET_SWEEP_THRESHOLD_REQUEST_TYPE`                    | `0x03`                                       | The [EIP-7685](/EIPs/EIPS/eip-7685) type prefix for set sweep threshold request            |
| `SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS`       | `TBD`                                        | Where to call and store relevant details about set sweep threshold request mechanism |
| `SYSTEM_ADDRESS`                                      | `0xfffffffffffffffffffffffffffffffffffffffe` | Address used to invoke system operation on contract                                  |
| `EXCESS_SET_SWEEP_THRESHOLD_REQUESTS_STORAGE_SLOT`    | `0`                                          |                                                                                      |
| `SET_SWEEP_THRESHOLD_REQUEST_COUNT_STORAGE_SLOT`      | `1`                                          |                                                                                      |
| `SET_SWEEP_THRESHOLD_REQUEST_QUEUE_HEAD_STORAGE_SLOT` | `2`                                          | Pointer to the head of the set sweep threshold request message queue                 |
| `SET_SWEEP_THRESHOLD_REQUEST_QUEUE_TAIL_STORAGE_SLOT` | `3`                                          | Pointer to the tail of the set sweep threshold request message queue                 |
| `SET_SWEEP_THRESHOLD_REQUEST_QUEUE_STORAGE_OFFSET`    | `4`                                          | The start storage slot of the in-state set sweep threshold request message queue     |
| `MAX_SET_SWEEP_THRESHOLD_REQUESTS_PER_BLOCK`          | `16`                                         | Maximum number of set sweep threshold requests that can be dequeued into a block     |
| `TARGET_SET_SWEEP_THRESHOLD_REQUESTS_PER_BLOCK`       | `2`                                          |                                                                                      |
| `MIN_SET_SWEEP_THRESHOLD_REQUEST_FEE`                 | `1`                                          |                                                                                      |
| `SET_SWEEP_THRESHOLD_REQUEST_FEE_UPDATE_FRACTION`     | `17`                                         |                                                                                      |
| `EXCESS_INHIBITOR`                                    | `2**256-1`                                   | Excess value used to compute the fee before the first system call                    |

#### Consensus layer

| Name                       | Value                                               |
| -------------------------- | --------------------------------------------------- |
| `MIN_SWEEP_THRESHOLD`      | `MIN_ACTIVATION_BALANCE + Gwei(1 * 10**9)` (33 ETH) |

### Execution layer

#### Definitions

* **`FORK_BLOCK`** -- the first block in a blockchain after this EIP has been activated.

#### Set sweep threshold request

The new set sweep threshold request is an [EIP-7685](/EIPs/EIPS/eip-7685) request with type `SET_SWEEP_THRESHOLD_REQUEST_TYPE` consisting of the following fields:

1. `source_address`: `Bytes20`
2. `validator_pubkey`: `Bytes48`
3. `threshold`: `uint64`

The [EIP-7685](/EIPs/EIPS/eip-7685) encoding of a set sweep threshold request is computed as follows.
Note that `threshold` is returned by the contract little-endian, and must be encoded as such.

```python
request_type = SET_SWEEP_THRESHOLD_REQUEST_TYPE
request_data = read_set_sweep_threshold_requests()
```

#### Set sweep threshold request contract

The contract has three different code paths, which can be summarized at a high level as follows:

1. Add set sweep threshold request - requires a 56-byte input: validator public key concatenated with a big-endian `uint64` threshold value.
2. Fee getter - if the input length is zero, return the current fee required to add a set sweep threshold request.
3. System process - if called by the system address, pop off the set sweep threshold requests for the current block from the queue.

##### Add Set Sweep Threshold Request

If call data input to the contract is exactly `56` bytes, perform the following:

1. Ensure enough ETH was sent to cover the current set sweep threshold request fee (`msg.value &gt;= get_fee()`).
2. Increase set sweep threshold request count by 1 for the current block.
3. Insert a set sweep threshold request into the queue for the source address, validator public key, and the threshold.

Specifically, the functionality is defined in pseudocode as the function `add_set_sweep_threshold_request()`:

```python
def add_set_sweep_threshold_request(validator_pubkey: Bytes48, threshold: uint64):
    &quot;&quot;&quot;
    Add a new request to the set sweep threshold request queue, provided a sufficient value to cover the fee was sent.
    &quot;&quot;&quot;

    # Verify sufficient value was provided.
    fee = get_fee()
    require(msg.value &gt;= fee, &apos;Insufficient value for fee&apos;)

    # Increment the request count.
    count = sload(SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS, SET_SWEEP_THRESHOLD_REQUEST_COUNT_STORAGE_SLOT)
    sstore(SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS, SET_SWEEP_THRESHOLD_REQUEST_COUNT_STORAGE_SLOT, count + 1)

    # Insert into the queue.
    queue_tail_index = sload(SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS, SET_SWEEP_THRESHOLD_REQUEST_QUEUE_TAIL_STORAGE_SLOT)
    queue_storage_slot = SET_SWEEP_THRESHOLD_REQUEST_QUEUE_STORAGE_OFFSET + queue_tail_index * 3
    sstore(SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot, msg.sender)
    sstore(SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 1, validator_pubkey[ 0:32])
    sstore(SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 2, validator_pubkey[32:48] ++ threshold)
    sstore(SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS, SET_SWEEP_THRESHOLD_REQUEST_QUEUE_TAIL_STORAGE_SLOT, queue_tail_index + 1)
```

###### Fee calculation

The following pseudocode can compute the cost of an individual set sweep threshold request, given a certain number of excess set sweep threshold requests.

```python
def get_fee() -&gt; int:
    excess = sload(SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS, EXCESS_SET_SWEEP_THRESHOLD_REQUESTS_STORAGE_SLOT)
    require(excess != EXCESS_INHIBITOR, &apos;Inhibitor still active&apos;)
    return fake_exponential(
        MIN_SET_SWEEP_THRESHOLD_REQUEST_FEE,
        excess,
        SET_SWEEP_THRESHOLD_REQUEST_FEE_UPDATE_FRACTION
    )

def fake_exponential(factor: int, numerator: int, denominator: int) -&gt; int:
    i = 1
    output = 0
    numerator_accum = factor * denominator
    while numerator_accum &gt; 0:
        output += numerator_accum
        numerator_accum = (numerator_accum * numerator) // (denominator * i)
        i += 1
    return output // denominator
```

##### Fee Getter

When the input to the contract has zero-length, interpret this as a get request for the current fee, i.e. the contract returns the result of `get_fee()`. The contract reverts if any value is sent to prevent loss of funds.

##### System Call

At the end of processing any execution block starting from the `FORK_BLOCK` (i.e. after processing all transactions), call `SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS` as `SYSTEM_ADDRESS` with no calldata. The invocation triggers the following:

* The contract&apos;s queue is updated based on set sweep threshold requests dequeued and the set sweep threshold requests queue head/tail are reset if the queue has been cleared (`dequeue_set_sweep_threshold_requests()`)
* The contract&apos;s excess set sweep threshold requests are updated based on usage in the current block (`update_excess_set_sweep_threshold_requests()`)
* The contract&apos;s set sweep threshold requests count is reset to 0 (`reset_set_sweep_threshold_requests_count()`)

In response to the system call, the contract returns an opaque byte array of concatenated SSZ-serialized dequeued requests. There&apos;s no specific reasoning behind it, except aligning with the existing behaviour of the similar EIP, see [EIP-7002](/EIPs/EIPS/eip-7002), and possible simplification of the processing flow for client teams.
Each set sweep threshold request must appear in the EIP-7685 requests list in the exact order returned by `dequeue_set_sweep_threshold_requests()`.

Additionally, the system call and the processing of that block must conform to the following:

* The call has a dedicated gas limit of `30_000_000` (`SYSTEM_TRANSACTION_GAS`) and is not subject to the transaction limit cap introduced in [EIP-7825](/EIPs/EIPS/eip-7825).
* Gas consumed by this call does not count against the block’s overall gas usage.
* Both the gas limit assigned to the call and the gas consumed are excluded from any checks against the block’s gas limit.
* The call does not follow [EIP-1559](/EIPs/EIPS/eip-1559) fee burn semantics — no value should be transferred as part of this call.
* If there is no code at `SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS`, the corresponding block **MUST** be marked invalid.
* If the call to the contract fails or returns an error, the block **MUST** be invalidated.

The functionality triggered by the system call is defined in pseudocode as the function `read_set_sweep_threshold_requests()`:

```python
###################
# Public function #
###################

def read_set_sweep_threshold_requests():
    reqs = dequeue_set_sweep_threshold_requests()
    update_excess_set_sweep_threshold_requests()
    reset_set_sweep_threshold_requests_count()
    return b&quot;&quot;.join(ssz.serialize(r) for r in reqs)

###########
# Helpers #
###########

class ValidatorSetSweepThresholdRequest(Container):
    source_address: Bytes20
    validator_pubkey: Bytes48
    threshold: uint64

def dequeue_set_sweep_threshold_requests():
    queue_head_index = sload(SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS, SET_SWEEP_THRESHOLD_REQUEST_QUEUE_HEAD_STORAGE_SLOT)
    queue_tail_index = sload(SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS, SET_SWEEP_THRESHOLD_REQUEST_QUEUE_TAIL_STORAGE_SLOT)
    num_in_queue = queue_tail_index - queue_head_index
    num_dequeued = min(num_in_queue, MAX_SET_SWEEP_THRESHOLD_REQUESTS_PER_BLOCK)

    reqs = []
    for i in range(num_dequeued):
        queue_storage_slot = SET_SWEEP_THRESHOLD_REQUEST_QUEUE_STORAGE_OFFSET + (queue_head_index + i) * 3
        source_address = address(sload(SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot)[0:20])
        validator_pubkey = (
            sload(SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 1)[0:32] +
            sload(SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 2)[0:16]
        )
        threshold = sload(SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 2)[16:24]
        req = ValidatorSetSweepThresholdRequest(
            source_address=Bytes20(source_address),
            validator_pubkey=Bytes48(validator_pubkey),
            threshold=uint64(threshold)
        )
        reqs.append(req)

    new_queue_head_index = queue_head_index + num_dequeued
    if new_queue_head_index == queue_tail_index:
        # Queue is empty, reset queue pointers
        sstore(SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS, SET_SWEEP_THRESHOLD_REQUEST_QUEUE_HEAD_STORAGE_SLOT, 0)
        sstore(SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS, SET_SWEEP_THRESHOLD_REQUEST_QUEUE_TAIL_STORAGE_SLOT, 0)
    else:
        sstore(SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS, SET_SWEEP_THRESHOLD_REQUEST_QUEUE_HEAD_STORAGE_SLOT, new_queue_head_index)

    return reqs

def update_excess_set_sweep_threshold_requests():
    previous_excess = sload(SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS, EXCESS_SET_SWEEP_THRESHOLD_REQUESTS_STORAGE_SLOT)
    if previous_excess == EXCESS_INHIBITOR:
        previous_excess = 0

    count = sload(SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS, SET_SWEEP_THRESHOLD_REQUEST_COUNT_STORAGE_SLOT)
    new_excess = 0
    if previous_excess + count &gt; TARGET_SET_SWEEP_THRESHOLD_REQUESTS_PER_BLOCK:
        new_excess = previous_excess + count - TARGET_SET_SWEEP_THRESHOLD_REQUESTS_PER_BLOCK

    sstore(SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS, EXCESS_SET_SWEEP_THRESHOLD_REQUESTS_STORAGE_SLOT, new_excess)

def reset_set_sweep_threshold_requests_count():
    sstore(SET_SWEEP_THRESHOLD_REQUEST_PREDEPLOY_ADDRESS, SET_SWEEP_THRESHOLD_REQUEST_COUNT_STORAGE_SLOT, 0)
```

##### Bytecode

The following bytecode is produced by the geas compiler from the source code in the sys-asm repository.

```asm
caller
push20 0xfffffffffffffffffffffffffffffffffffffffe
eq
push1 0xcb
jumpi

push1 0x11
push0
sload
dup1
push32 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
eq
push2 0x01f4
jumpi

push1 0x01
dup3
mul
push1 0x01
swap1
push0

jumpdest
push0
dup3
gt
iszero
push1 0x68
jumpi

dup2
add
swap1
dup4
mul
dup5
dup4
mul
swap1
div
swap2
push1 0x01
add
swap2
swap1
push1 0x4d
jump

jumpdest
swap1
swap4
swap1
div
swap3
pop
pop
pop
calldatasize
push1 0x38
eq
push1 0x88
jumpi

calldatasize
push2 0x01f4
jumpi

callvalue
push2 0x01f4
jumpi

push0
mstore
push1 0x20
push0
return

jumpdest
callvalue
lt
push2 0x01f4
jumpi

push1 0x01
sload
push1 0x01
add
push1 0x01
sstore
push1 0x03
sload
dup1
push1 0x03
mul
push1 0x04
add
caller
dup2
sstore
push1 0x01
add
push0
calldataload
dup2
sstore
push1 0x01
add
push1 0x20
calldataload
swap1
sstore
caller
push1 0x60
shl
push0
mstore
push1 0x38
push0
push1 0x14
calldatacopy
push1 0x4c
push0
log0
push1 0x01
add
push1 0x03
sstore
stop

jumpdest
push1 0x03
sload
push1 0x02
sload
dup1
dup3
sub
dup1
push1 0x10
gt
push1 0xdf
jumpi

pop
push1 0x10

jumpdest
push0

jumpdest
dup2
dup2
eq
push2 0x0183
jumpi

dup3
dup2
add
push1 0x03
mul
push1 0x04
add
dup2
push1 0x4c
mul
dup2
sload
push1 0x60
shl
dup2
mstore
push1 0x14
add
dup2
push1 0x01
add
sload
dup2
mstore
push1 0x20
add
swap1
push1 0x02
add
sload
dup1
push32 0xffffffffffffffffffffffffffffffff00000000000000000000000000000000
and
dup3
mstore
swap1
push1 0x10
add
swap1
push1 0x40
shr
swap1
dup2
push1 0x38
shr
dup2
push1 0x07
add
mstore8
dup2
push1 0x30
shr
dup2
push1 0x06
add
mstore8
dup2
push1 0x28
shr
dup2
push1 0x05
add
mstore8
dup2
push1 0x20
shr
dup2
push1 0x04
add
mstore8
dup2
push1 0x18
shr
dup2
push1 0x03
add
mstore8
dup2
push1 0x10
shr
dup2
push1 0x02
add
mstore8
dup2
push1 0x08
shr
dup2
push1 0x01
add
mstore8
mstore8
push1 0x01
add
push1 0xe1
jump

jumpdest
swap2
add
dup1
swap3
eq
push2 0x0195
jumpi

swap1
push1 0x02
sstore
push2 0x01a0
jump

jumpdest
swap1
pop
push0
push1 0x02
sstore
push0
push1 0x03
sstore

jumpdest
push0
sload
dup1
push32 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
eq
iszero
push2 0x01cd
jumpi

pop
push0

jumpdest
push1 0x01
sload
push1 0x02
dup3
dup3
add
gt
push2 0x01e2
jumpi

pop
pop
push0
push2 0x01e8
jump

jumpdest
add
push1 0x02
swap1
sub

jumpdest
push0
sstore
push0
push1 0x01
sstore
push1 0x4c
mul
push0
return

jumpdest
push0
push0
revert
```

##### Deployment

The set sweep threshold requests contract is deployed like any other smart contract. A special synthetic address is generated by working backwards from the desired deployment transaction:

```json
TBD
```

```
Sender: TBD
Address: TBD
```

### Consensus layer

The defining feature of this EIP is ***allowing validators to set custom sweep thresholds for their withdrawals when using compounding withdrawal credentials (`0x02, 0x03`)***.

The [Rationale](#rationale) section contains an explanation for this proposed core feature. A sketch of the resulting changes to the consensus layer is included below.

1. Update the `BeaconState` container to include a `validator_sweep_thresholds` mapping.
2. Add `SetSweepThresholdRequest` container to represent the set sweep threshold requests dequeued from the execution layer contract.
3. Update the `ExecutionRequests` container to include a list of `SetSweepThresholdRequest` items.
4. Add `process_set_sweep_threshold_request` function to handle the processing of set sweep threshold requests from the execution layer.
5. Modify the `process_execution_payload` function to include the processing of set sweep threshold requests.
6. Modify the `is_partially_withdrawable_validator` predicate to take into account the custom sweep threshold.
7. Add `get_effective_sweep_threshold` helper function to compute the effective sweep threshold for a validator.
8. Modify the `get_expected_withdrawals` function to use the custom sweep threshold when determining partial withdrawals.

By default, all validators will have their sweep thresholds set to the current default `MAX_EFFECTIVE_BALANCE`, both for existing validators and new ones. Validators can choose to set a custom threshold above their current balance by submitting a set sweep threshold request through the execution layer contract.

## Rationale

### Overview

Most of the considerations regarding the messaging format, queue, and rate-limiting are similar to those discussed in [EIP-7002](/EIPs/EIPS/eip-7002) for withdrawal requests, and so we refer the reader to that EIP for more details.

### Custom Sweep Thresholds

The primary motivation for this EIP is to allow validators to set custom sweep thresholds for their withdrawals when using compounding withdrawal credentials (`0x02, 0x03`). This feature provides greater flexibility and control over how and when validators can access their staking rewards.

### `validator_sweep_thresholds` mapping in `BeaconState`

To store the custom sweep thresholds for each validator, we introduce a new mapping in the `BeaconState` container called `validator_sweep_thresholds`. This mapping associates each validator index with its corresponding sweep threshold. This approach was chosen instead of adding a new field to the `Validator` container to avoid modification of this type, which had not been changed since phase-0. Modification of the `Validator` container would have required more extensive changes to the consensus layer and potentially affected existing implementations of the applications using this container. Also, this is the standard way of adding info about validators into the state (e.g., validator balance is stored in `balances` field of `BeaconState` and several other PoS-related info have their own lists where each item corresponds to validators&apos; data)

### Only allowing threshold to be set above current balance

This design decision is made to prevent usage of the custom sweep threshold mechanism to trigger immediate withdrawals. By enforcing that the threshold must be set above the current balance, we ensure that validators cannot use this feature to bypass the standard withdrawal process. Should a validator wish to set sweep threshold below current balance, they can first withdraw down to the desired level using partial withdrawals, and then set the sweep threshold accordingly.

### Immediate requests processing instead of queuing on consensus layer

Unlike partial withdrawal requests, which are queued on the consensus layer, set sweep threshold requests are processed immediately upon being dequeued from the execution layer contract. This design choice simplifies the implementation and reduces the complexity of managing a separate queue on the consensus layer.

### `MIN_SWEEP_THRESHOLD` of 33 ETH

To ensure that validators do not set sweep threshold equal to `MIN_ACTIVATION_BALANCE`, we introduce a minimum sweep threshold of `MIN_ACTIVATION_BALANCE + 1` ETH (33 ETH). This ensures that people will opt-in to compounding withdrawal credentials only if they really want to accumulate rewards on the validator balance.

## Backwards Compatibility

This EIP introduces backwards incompatible changes to the block structure and block validation rule set. But neither of these changes break anything related to the current user activity and experience.

## Security Considerations

Most of the security considerations regarding fee overpayment, system call failure, and empty code failure are similar to those discussed in [EIP-7002](/EIPs/EIPS/eip-7002) for withdrawal requests, and so we refer the reader to that EIP for more details.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 05 Feb 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8148</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8148</guid>
      </item>
    
      <item>
        <title>Multi KZG Point Evaluation Precompile</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8149-multi-kzg-point-evaluation-precompile/27671</comments>
        
        <description>## Abstract

Add a precompile that verifies multiple KZG openings `(z_i, y_i)` for a single [EIP-4844](/EIPs/EIPS/eip-4844) blob commitment, returning the same 64-byte output as the existing point-evaluation precompile.

## Motivation

[EIP-4844](/EIPs/EIPS/eip-4844) provides a point-evaluation precompile at `0x0A` costing 50,000 gas per opening. Contracts needing multiple blob values (e.g., fraud proofs) must pay this cost repeatedly. A batch interface verifies *k* openings in one call, reducing overhead.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

### Constants

| Name | Value | Comment |
| - | - | - |
| `MULTI_POINT_EVALUATION_PRECOMPILE_ADDRESS` | `TBD` | precompile address |
| `MAX_MULTI_POINTS` | `128` | maximum number of evaluation points |
| `MULTI_POINT_EVALUATION_BASE_GAS` | `TBD` | base gas cost |
| `MULTI_POINT_EVALUATION_PER_POINT_GAS` | `TBD` | gas cost per evaluation point |

We introduce a precompile to perform multi KZG point evaluation:

It verifies multiple KZG openings `(z_i, y_i)` for a single EIP-4844 blob commitment in one call. The verification uses BLS12-381 pairing operations internally to check the multi-point opening proof. Gas cost is defined by `MULTI_POINT_EVALUATION_BASE_GAS + MULTI_POINT_EVALUATION_PER_POINT_GAS * n` where `n` is the number of evaluation points.

### Input

```
versioned_hash  : Bytes32
commitment      : Bytes48
n               : uint32 (big-endian)
pairs           : n × (z: Bytes32, y: Bytes32)
proof           : Bytes48
```

Total length: `132 + (n × 64)` bytes. All `z` and `y` MUST be strictly less than `BLS_MODULUS`.

### Output

On success, return 64 bytes identical to [EIP-4844](/EIPs/EIPS/eip-4844):

```
FIELD_ELEMENTS_PER_BLOB  : uint256 (big-endian)
BLS_MODULUS              : uint256 (big-endian)
```

### Multi-point evaluation precompile

Add a precompile at `MULTI_POINT_EVALUATION_PRECOMPILE_ADDRESS` that verifies multiple KZG openings `(z_i, y_i)` for a single EIP-4844 blob commitment.

The precompile executes the following logic:

```python
def multi_point_evaluation_precompile(input: Bytes) -&gt; Bytes:
    versioned_hash = input[:32]
    commitment = input[32:80]
    n = int.from_bytes(input[80:84], &apos;big&apos;)
    
    assert 1 &lt;= n &lt;= MAX_MULTI_POINTS
    assert len(input) == 132 + n * 64
    
    z_values, y_values = [], []
    for i in range(n):
        offset = 84 + i * 64
        z_i = int.from_bytes(input[offset:offset+32], &apos;big&apos;)
        y_i = int.from_bytes(input[offset+32:offset+64], &apos;big&apos;)
        assert z_i &lt; BLS_MODULUS and y_i &lt; BLS_MODULUS
        z_values.append(z_i)
        y_values.append(y_i)
    
    proof = input[84 + n*64 : 84 + n*64 + 48]
    
    assert kzg_to_versioned_hash(commitment) == versioned_hash
    assert verify_kzg_proof_multi(commitment, z_values, y_values, proof)
    
    return U256(FIELD_ELEMENTS_PER_BLOB).to_be_bytes32() + U256(BLS_MODULUS).to_be_bytes32()
```

The `verify_kzg_proof_multi` function performs multi-point opening verification using the [EIP-4844](/EIPs/EIPS/eip-4844) trusted setup and BLS12-381 pairing operations. Implementations typically use Lagrange interpolation to construct a polynomial through all `(z_i, y_i)` pairs, which has O(n²) complexity. When evaluation points align with roots of unity, FFT-based methods reduce this to O(n log n). The final verification step uses a single pairing check to verify all openings simultaneously.

### Gas Cost

The gas cost for multi point evaluation is:

```python
def gas_cost(n: int) -&gt; int:
    return MULTI_POINT_EVALUATION_BASE_GAS + MULTI_POINT_EVALUATION_PER_POINT_GAS * n
```

Gas constants SHOULD ensure batching is cheaper than `n` separate `0x0A` calls for `n &gt; 1`. The verification internally uses BLS12-381 pairing operations, which are computationally expensive but enable efficient batch verification of multiple openings.

## Rationale

- Preserves [EIP-4844](/EIPs/EIPS/eip-4844) versioned-hash model and return format.
- Adds a new precompile rather than modifying `0x0A` to avoid compatibility risks.
- `MAX_MULTI_POINTS = 128` bounds input size while enabling meaningful savings.

## Backwards Compatibility

No changes to [EIP-4844](/EIPs/EIPS/eip-4844) transactions, `BLOBHASH`, or the existing precompile at `0x0A`.

## Security Considerations


- Reject non-canonical field elements (`&gt;= BLS_MODULUS`).
- Implementations MUST use the same trusted setup and subgroup checks as [EIP-4844](/EIPs/EIPS/eip-4844).
- Gas pricing MUST reflect actual computational cost.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).


</description>
        <pubDate>Fri, 06 Feb 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8149</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8149</guid>
      </item>
    
      <item>
        <title>Private Key Deactivation Aware ecRecover</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8151-private-key-deactivation-aware-ecrecover/27690</comments>
        
        <description>## Abstract

This EIP modifies the `ecRecover` precompile at address `0x0000000000000000000000000000000000000001` to respect [EIP-7851](/EIPs/EIPS/eip-7851) key deactivation. After performing ECDSA public key recovery, the precompile checks whether the recovered address has a deactivated private key. If so, it returns 32 zero bytes (the existing failure sentinel of `ecRecover`) instead of the recovered address.

## Motivation

[EIP-7851](/EIPs/EIPS/eip-7851) enables delegated EOAs (per [EIP-7702](/EIPs/EIPS/eip-7702)) to deactivate their private keys, preventing those keys from authorizing transactions or new delegation authorizations. However, the `ecRecover` precompile is currently a pure cryptographic function with no awareness of account state. Even after an EOA&apos;s key is deactivated, on-chain signature verification through `ecRecover` continues to succeed for that key. This affects contracts that rely on `ecRecover` for signature-based authorization, such as ERC-20 contracts implementing `permit` ([ERC-2612](/EIPs/EIPS/eip-2612)). Since many such contracts are immutable and cannot be updated to add deactivation checks, modifying `ecRecover` at the protocol level is a practical path.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

| Constant                   | Value                                        |
|----------------------------|----------------------------------------------|
| `ECRECOVER_ADDRESS`        | `0x0000000000000000000000000000000000000001` |
| `COLD_ACCOUNT_ACCESS_COST` | 2600                                         |
| `WARM_ACCOUNT_ACCESS_COST` | 100                                          |

### Modified `ecRecover` Behavior

Starting at the activation of this EIP, the `ecRecover` precompile at address `ECRECOVER_ADDRESS` MUST perform the following steps:

1. Perform ECDSA public key recovery from the input `(hash, v, r, s)` as currently specified, yielding a `recovered_address`.
2. If recovery fails, return 32 zero bytes and consume `3000` gas.
3. If recovery succeeds, read the account code of `recovered_address` and determine whether the key is deactivated per [EIP-7851](/EIPs/EIPS/eip-7851).
4. If `recovered_address` has a deactivated key, return 32 zero bytes.
5. Otherwise, return `recovered_address` left-padded to 32 bytes.

### Deactivation Check

An address is considered to have a deactivated key if and only if its account code has a prefix of `0xef0100` and a length of exactly 24 bytes, consistent with the deactivated state `0xef0100 || delegate_address || 0x00` defined in [EIP-7851](/EIPs/EIPS/eip-7851):

```python
code = state.get_code(recovered_address)
is_deactivated = len(code) == 24 and code[:3] == bytes.fromhex(&quot;ef0100&quot;) and code[-1] == 0x00
```

### Gas Cost

When ECDSA recovery fails, no state access is performed and the gas cost
remains `3000`.

When ECDSA recovery succeeds, the precompile MUST access the account of
`recovered_address` to read its code. This access MUST follow the
[EIP-2929](/EIPs/EIPS/eip-2929) warm/cold rules:

- If `recovered_address` is already in the transaction&apos;s `accessed_addresses` set, the additional cost is `WARM_ACCOUNT_ACCESS_COST` (100).
- Otherwise, the additional cost is `COLD_ACCOUNT_ACCESS_COST` (2600), and `recovered_address` MUST be added to the `accessed_addresses` set, making it warm for subsequent operations within the same transaction.

## Rationale

### Protocol-Level Modification

Modifying `ecRecover` at the protocol level is chosen because many deployed contracts that rely on `ecRecover` for signature-based authorization (e.g., ERC-20 `permit` implementations) are immutable and cannot be upgraded to incorporate deactivation checks. A protocol-level change ensures these existing contracts automatically benefit from key deactivation without requiring redeployment.

### Returning 32 Zero Bytes

When a deactivated key is detected, the precompile returns 32 zero bytes rather than triggering an execution failure (`success = 0`). Currently, malformed `v`, out of range `r`/`s`, and failed recovery all return 32 zero bytes with `success = 1`, and `ecRecover` has never used execution failure to signal invalid input. Treating a deactivated key as another form of &quot;recovery failed&quot; keeps this convention intact.

Furthermore, introducing an execution failure path would break deployed contracts that wrap `ecRecover` with a low level `staticcall` and `require(success)`, turning a &quot;signature not valid&quot; result into an unexpected revert. Contracts that already check for a zero return will naturally reject deactivated keys without any code changes.

### EIP-2929 Gas Accounting

Since the precompile now reads account state, the additional gas cost follows the existing [EIP-2929](/EIPs/EIPS/eip-2929) warm/cold access pattern for consistency with the rest of the protocol. This avoids introducing a new gas model and ensures that the cost of state access is fairly accounted for.

## Backwards Compatibility

For addresses whose private key has been deactivated under [EIP-7851](/EIPs/EIPS/eip-7851), `ecRecover` now returns 32 zero bytes where it previously returned the recovered address.

On every successful ECDSA recovery, the precompile now performs an additional account access, adding either `WARM_ACCOUNT_ACCESS_COST` (100) or `COLD_ACCOUNT_ACCESS_COST` (2600) to the base cost of `3000`. Transactions that invoke `ecRecover` near their gas limit MAY fail with an out-of-gas error after activation.

## Test Cases

&lt;!-- TODO --&gt;

## Reference Implementation

```python
COLD_ACCOUNT_ACCESS_COST = 2600
WARM_ACCOUNT_ACCESS_COST = 100
BASE_GAS = 3000

def ecrecover_gas(state, recovered_address):
    if recovered_address is None:
        return BASE_GAS
    if recovered_address in state.accessed_addresses:
        return BASE_GAS + WARM_ACCOUNT_ACCESS_COST
    state.accessed_addresses.add(recovered_address)
    return BASE_GAS + COLD_ACCOUNT_ACCESS_COST

ZERO_BYTES32 = b&apos;\x00&apos; * 32
DELEGATED_CODE_PREFIX = b&apos;\xef\x01\x00&apos;
DEACTIVATED_CODE_LEN = 24  # len(0xef0100 || address || 0x00)

def ecrecover(state, hash: bytes, v: int, r: int, s: int) -&gt; bytes:
    # None means recovery failure
    recovered_address = ecdsa_recover(hash, v, r, s)

    if recovered_address is None:
        return ZERO_BYTES32

    # Check EIP-7851 deactivation
    code = state.get_code(recovered_address)
    if len(code) == DEACTIVATED_CODE_LEN and code[:3] == DELEGATED_CODE_PREFIX and code[-1] == 0x00:
        return ZERO_BYTES32

    return recovered_address.rjust(32, b&apos;\x00&apos;)
```

## Security Considerations

### Contracts Not Checking for Zero Return

Contracts that use `ecrecover` but do not verify the result is non-zero are already vulnerable to accepting invalid signatures. This EIP maps deactivated keys to the same failure sentinel (32 zero bytes) and therefore does not introduce a new class of vulnerability.

### Application-Level ECDSA Verification

This EIP only modifies the `ecrecover` precompile. Contracts that perform ECDSA recovery in application-level code (e.g., pure Solidity implementations) bypass the precompile and will not observe deactivation.

### Cross-Domain / L2 Fault Proof Implications

Some systems re-execute `ecrecover` in a different context (different chain, different layer, or asynchronously at a later time) and assume it is a pure function of `(hash, v, r, s)`. Because this EIP introduces a state read (the recovered address&apos;s account code), that assumption no longer holds.

In particular, L2 fault proof systems that accelerate `ecrecover` by executing the L1 precompile and caching the result may become incorrect. Mitigations include removing such acceleration, or migrating to a pure recovery primitive (e.g., implementing secp256k1 recovery inside the fault-proof VM or via a new dedicated pure-recovery precompile in L1), so that the accelerated operation remains a pure function of its inputs.

### Multi-Chain Considerations

Key deactivation under EIP-7851 is per-chain state. A key deactivated on one chain remains active on other chains. Users SHOULD NOT assume that deactivating their key on one chain protects them across all EVM-compatible chains.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 09 Feb 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8151</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8151</guid>
      </item>
    
      <item>
        <title>Content-Addressable Logic Modules (CALM)</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8152-content-addressable-logic-modules-calm/23070</comments>
        
        <description>## Abstract

This standard defines Content-Addressable Logic Modules (CALM) - minimal, deterministic blocks of code designed for execution via delegatecall within Diamond ([ERC-2535](/EIPs/EIPS/eip-2535), [ERC-8109](/EIPs/EIPS/eip-8109)), UUPS ([ERC-1822](/EIPs/EIPS/eip-1822)) and other proxy architectures.

A CALM&apos;s address is a direct cryptographic commitment to its runtime bytecode. By eliminating deployment-side effects (initialisation code - constructors, immutables), CALM ensures that identical logic resides at identical addresses across all EVM chains. RuntimeBytecode is the Identity.

## Motivation

Current libraries and Diamond Facets are scattered and duplicated within one chain, while being almost impossible to reuse on another chains on the same deployed address. That complicates cross-chain verification and logic reuse increasing operational overhead for multi chain projects.
By standardizing an &quot;atomic&quot; format - free of constructors, immutables, selfdestruct and having the deployment address equal to `f(constant, runtimeBytecode)` - we enable a global library of Content-Addressable Logic Modules that live at identical addresses on every chain with zero overhead and with option for permissionless redeployment on another chains.

## Specification

### Storage standards and Proxy-Scoped Execution

It is expected CALM operates exclusively on the **storage context of the calling Proxy**. However no checks are required to prevent possessing or initialising its own storage.

To prevent storage collisions and ensure modularity, CALM MUST utilize deterministic storage offsets to manipulate the Proxy’s state.

CALMs SHOULD comply with either [ERC-7201](/EIPs/EIPS/eip-7201) (Namespaced Storage) or [ERC-8042](/EIPs/EIPS/eip-8042) (Diamond Storage) or any future standard of storage separation by defining their internal state at unique, hashed storage locations and utilizing standardized storage slots for shared infrastructure state to ensure interoperability within a proxy. 

### Deployment Constraints

To comply with the CALM standard, a contract MUST adhere to the following rules during deployment:

 - No Constructor: The initcode MUST NOT execute any logic other than the deployment of the runtime bytecode as custom constructor will not be considered during re-deployments across chains.

 - No Immutables: The runtime bytecode MUST NOT contain variables injected during deployment (immutables), as these alter the bytecode hash and break address determinism.

 - Ensured redeployability onto the same address:  CALMs MUST be deployed content addressable based on its runtime bytecode and MUST allow permission-less redeployment onto other chains,  i.e. their address is the function:

```sh
address = function(&lt;publicly known constants&gt;, runtimeBytecode)
```

where publicly known constants are for example:

 - salt = 0
 - constant micro constructor bytecode for initCode (600B_38_03_80_600B_3D_39_3D_f3)
 - constant address of the deployer, that can be deployed on any chain permissionlessly onto the same address

While such constants are used uniformly with all related CALM contracts on any chain.

*Note: CALMs may be authored in any language (e.g. Solidity, Vyper, Huff, Yul) as long as the resulting bytecode adheres to the runtime constraints. The standard focuses on the bytecode output, not the source language.*

### Runtime Constraints

 - No Self-Destruct: The contract MUST NOT contain the SELFDESTRUCT (0xFF) opcode. This ensures permanent availability for the proxies relying on the logic on those chains that are not compliant with [EIP-6049](/EIPs/EIPS/eip-6049), [EIP-6780](/EIPs/EIPS/eip-6780) and other SELFDESTRUCT corresponding changes.

 - Stateless Execution for itself: The contract MUST NOT directly access its own storage.

### Logic Dispatching Models
CALM supports two distinct models for execution:


| Model |Description | Primary Use Case |
|--|--|--|
| **Multi-Method (Standard)** | Contains an internal dispatcher (e.g. Solidity) that routes calls based on the first 4 bytes in calldata ( standard `msg.sig` in Solidity ). | Diamond facets containing multiple related functions. Example: Transaction, approval and metadata logic of [ERC-20](/EIPs/EIPS/eip-20) contract  |
| **Atomic-Logic (Fallback)** | Contains no function dispatcher. All logic resides in one `fallback()` function. Often used with the Diamond proxy that maps a specific selector directly to such CALM designed facet (so called **Single Function Facet**). Zero-dispatcher design is compliant with both [ERC-2535](/EIPs/EIPS/eip-2535) and [ERC-8109](/EIPs/EIPS/eip-8109) standards. | Hyper-optimized micro-functions. Example: highly optimised `ERC20.transfer()` function |

## Rationale

### Pre-warming Contracts and Global Cache Efficiency

CALMs align with the proposed [EIP-7863](/EIPs/EIPS/eip-7863), which introduces block-level warming for addresses and storage keys allowing accessed addresses to maintain their warm status throughout the execution of an entire block.

This shift provides an economic incentive for Shared Logic. Once a canonical CALM address is invoked by the first transaction in a block, every subsequent call from any other transaction in that same block can benefit from discounted gas costs. By converging on standardized CALM addresses, the community effectively minimizes the &quot;cold access&quot; penalty across the network. 

Before [EIP-7863](/EIPs/EIPS/eip-7863) is delivered, CALMs improve Global Cache Efficiency at the node infrastructure level. While warming resets per transaction, execution clients (like Geth or Reth) maintain in-memory LRU caches for frequently accessed bytecode to avoid expensive lookups in the state trie. A community convergence on canonical CALM addresses for standard operations ensures that these &quot;hot&quot; logic blocks remain in node memory, reducing the net I/O pressure on the network and increasing the de facto processing speed of the global state by preventing optimized logic from being fragmented across thousands of unique, cold trie locations.

### Community Convergence on Long-term Optimization

CALM is the architectural culmination of Ethereum&apos;s move toward modular standardization (e.g., [ERC-2535](/EIPs/EIPS/eip-2535), [ERC-7201](/EIPs/EIPS/eip-7201), [ERC-8042](/EIPs/EIPS/eip-8042)), establishing a &quot;Registry-less Registry.&quot; A contract&apos;s address cryptographically proves its functional integrity, eliminating the need for central authorities or registries to verify logic.

As the community identifies optimal, gas-efficient implementations, canonical CALMs emerge. This convergence on fixed, multichain addresses reduces redundant audits and systemic complexity. Since Runtime Bytecode is Identity, optimized logic for common operations (like ownership or token transfers) remains stable and universally accessible across the decentralized stack.

### The Atomic logic, fallback-only model

In standard Diamonds, the Proxy performs a `delegatecall`, and the Facet then performs a **second dispatch** to find the function by selector. For single function facets that only perform one task, this second dispatch is a waste of gas. CALMs in the form of Single Function Facets allow the Diamond Proxy to map a selector directly to a &quot;naked&quot; logic block, executing the logic immediately upon entry.

### The &quot;No Constructor&quot; Rule

Initcode traditionally serves two primary purposes: initializing contract storage and generating runtime bytecode. However, CALMs are designed to bypass both of these steps. The runtime bytecode is directly provided as input, and the intention is to deploy it without any initial storage setup. This design choice is deliberate, aiming to create contracts with immutable bytecode at addresses derived solely from their runtime code content. Consequently, initcode becomes redundant and irrelevant in this context.

### The Metadata Dilemma: CBOR, Verifiability and Validity

A critical distinction exists between social trust and cryptographic proof: Verification (Source Code) is an off-chain, human-centric process (e.g., Sourcify) that asks, &quot;Does this compiler produce this binary?&quot; and offers readability and auditability; while Validation (e.g. using tools like `HashCarve.isCarved()`) is an on-chain, machine-executable process that asks,  *&quot;Is this address a direct commitment to its opcodes?&quot;* and provides trustless, programmatic certainty of the module&apos;s origin and integrity, independent of third-party source hosting.

By default, compilers append a CBOR-encoded metadata footer to the runtime bytecode. This footer includes hashes of the source code, including comments, variable names, abi and compiler settings - see CBOR tooling like Sourcify Playground for details. For CALMs, this is a double-edged sword: changing a single comment alters the deployment address, even if the functional opcodes remain identical. One can achieve pure &quot;Logic-only Identity&quot; of CALM by stripping this metadata e.g., when a contract is compiled with the --no-cbor-metadata flag in Solidity, or using `bytecode_hash = “none” and cbor_metadata = false` in foundry.toml file.

While stripping metadata ensures that different developers can reach the same address for identical logic, it renders verification on platforms like Sourcify more difficult. They categorize verification into **Full** (perfect match including metadata) and **Partial** (logic matches, but metadata differs). Both remain achievable; however, stripping metadata requires a manual handling of the metadata.json file to reach a &quot;Full&quot; match status, as the on-chain fingerprint no longer points to the source.

Once a CALM is verified on one chain, its metadata is indexed, multichain replication tools like **CarbonCopy** can leverage the Sourcify API to automatically replicate this verification to all other chains where the identical bytecode is detected, thereby creating a &quot;verify once, trust everywhere&quot; network effect. This effectively allows the audit reputation of a CALM to follow its logic across the multichain ecosystem without redundant manual intervention.

Therefore the CALM deployer should decide whether the source codes are to be immutable and strongly linked to the address (metadata impact) of the CALM or whether she needs flexibility in the commenting of the source code for the future and thus being detached from the CALM’s address (no-metadata case). Full verification is achievable in both scenarios, but the choice determines whether the &quot;identity&quot; of the module is defined by its documentation or its pure functional execution.

## Backwards Compatibility

This standard is fully compatible with [ERC-2535](/EIPs/EIPS/eip-2535) Diamond, [ERC-8109](/EIPs/EIPS/eip-8109) Simplified Diamond, [ERC-1822](/EIPs/EIPS/eip-1822) UUPS proxy, [ERC-1167](/EIPs/EIPS/eip-1167) Clones proxy and potentially other proxy implementations. 

## Reference Implementation

This example demonstrates a hyper-optimized **Single Function Facet** implementing the `decimals()` function. It leverages the **Atomic-Logic** pattern, where the proxy maps the specific selector directly to the logic block, bypassing internal dispatching and no CBOR metadata attached.

1. Logic Implementation (Yul-Optimized Solidity)

By using a `fallback`, we eliminate the Solidity function selector &quot;switch&quot; table, reducing both gas cost and bytecode size.

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.33;

/**
 * @title Decimals_Const18_Optimized
 * @notice This contract returns a constant value of 18 for the `decimals()` function call.
 *         This can be used to represent fungible tokens with 18 decimal places.
 */
contract Decimals_Const18_Optimized {
    // function decimals() external pure returns (uint8) {}

    fallback() external payable {
        assembly {
            // Store the value 18 (0x12) in memory at offset 0x00.
            // mstore(offset, value) stores a 32-byte word.
            mstore(0x00, 0x12)

            // Return 32 bytes of data from memory starting at offset 0x00.
            // This returns the uint256 representation of 18, which ABI-decoding will interpret as uint8.
            return(0x00, 0x20)
        }
    }
}
```

2. Compiler Configuration (foundry.toml)

To ensure the address is a commitment to the logic only, we strip the metadata hash and maximize optimization.

```yaml
[profile.default]
via_ir = true
optimizer_runs = 20_000_000 # Maximize for runtime efficiency
bytecode_hash = &quot;none&quot;
cbor_metadata = false
```

3. Deterministic Identity

Compiling the above results in the minimal runtime bytecode: `0x60125f5260205ff3`. When &quot;carved&quot; via the HashCarve Factory (reference implementation for the permissionless deployment of CALMs at canonical address `0x9c8D020b832Ee8AAF92cB555819Dc8a0c1097F56`), the above logic manifests at an identical address on every EVM chain (`0xB1fDF38E7ae86bf190654b212bD7e53B542DE958`) and can be replicated permissionlessly by anyone onto another (even not yet existing) chains. **Runtime Bytecode is Identity**.


### Verification and Auditability

Because metadata is stripped, platforms like Sourcify require a manual upload of the `abi.json` and source file for the initial verification on the first chain.


```json
[
  {
    &quot;name&quot;: &quot;decimals&quot;,
    &quot;type&quot;: &quot;function&quot;,
    &quot;inputs&quot;: [],
    &quot;outputs&quot;: [{ &quot;name&quot;: &quot;&quot;, &quot;type&quot;: &quot;uint8&quot; }],
    &quot;stateMutability&quot;: &quot;pure&quot;
  }
]
```

**Verification Strategy:**

 - Simple Logic: For trivial CALMs (like Const18 above), stripping metadata is preferred. The bytecode is short enough to be verified via decompilation.

 - Complex Logic: For sophisticated modules - such as a highly optimized unconditional `ERC20.transfer` utilizing ERC-8042 (Diamond Storage) - preserving full CBOR metadata is recommended. This ensures that comments, security warnings, and the exact audit environment are cryptographically bound to the CALM&apos;s identity.


## Security Considerations

Since a CALM is &quot;stateless&quot; but &quot;state-manipulating,&quot; it must be carefully audited to ensure it only touches the storage namespaces it is authorized for.

Proxies such as Diamonds using CALMs SHOULD audit and test their overall configuration in order to ensure CALMs are not misaligned in the storage handling. For example, mixing [ERC-7201](/EIPs/EIPS/eip-7201) and [ERC-8042](/EIPs/EIPS/eip-8042) storage patterns across CALMs will cause bugs because they reference different storage locations for the same logical state.

Standard contract verification is fragile; an attacker could provide source code that matches the functional opcodes but contains misleading comments or variable names. For high-security modules (like `ERC20.transfer`), the standard recommends preserving the CBOR metadata. This binds the audit report, developer comments, and exact compiler settings to the address. If an attacker tries to change a comment to hide a bug, the address changes, and the validation for the original logic fails. 


## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).

</description>
        <pubDate>Sun, 18 Jan 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8152</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8152</guid>
      </item>
    
      <item>
        <title>Facet-Based Diamonds</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8153-facet-based-diamonds/27685</comments>
        
        <description>## Abstract

A diamond is a proxy contract that `delegatecall`s to multiple implementation contracts called facets. 

![Diagram showing how a diamond contract works](/EIPs/assets/eip-8153/basic-diamond-diagram.svg)

Diamond contracts were originally standardized by [ERC-2535](./eip-2535). 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.

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.

This ERC introduces a facet introspection function, `exportSelectors()`, 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.

This ERC also defines facet-based events for adding, replacing, and removing facets.

Additionally, the ERC also defines an optional `upgradeDiamond` function. This function uses `exportSelectors()` to automatically determine which selectors should be added, replaced, or removed when applying facet changes.

## Motivation

### Motivation for Diamond Contracts

&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.

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.

Diamonds combine the single-address convenience of a monolithic contract with the modular flexibility of distinct, integrated contracts.

This architecture is well suited to **immutable** smart-contract systems, where all functionality is composed from multiple facets at deployment time and permanently fixed thereafter.

For upgradeable systems, diamonds enable incremental development: new functionality can be added, and existing functionality modified, without redeploying unaffected facets.

Additional motivation and background for diamond-based smart-contract systems can be found in [ERC-1538](./eip-1538) and [ERC-2535](./eip-2535).

### Motivation for this Standard

In the past, deploying and upgrading diamonds suffered from:

1. **High gas costs**
2. **Function selector management complexity**
   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 &quot;plumbing&quot;.

This standard reduces gas costs and eliminates off-chain selector management:

* Diamonds become less expensive to deploy.
* Function selectors no longer need to be gathered off-chain.
* Standard deployment tools can be used without special diamond support.
* ERC-2535 introspection functions have simple implementations.

## Specification

### Terms
1. A **diamond** 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 [Implementation Requirements](#implementation-requirements) section.
2. A **facet** 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 `delegatecall`, 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.
3. An **introspection function** is a function that returns information about the facets and/or functions used by a diamond or facet.
4. For the purposes of this specification, a **mapping** refers to a conceptual association between two items and does not refer to a specific implementation.

### Diamond Diagram

This diagram shows the structure of a diamond. 

It shows that a diamond has a mapping from function to facet and that facets can access the storage inside a diamond.

![Diagram showing structure of a diamond](/EIPs/assets/eip-8153/functionFacetMapping.svg)

### Fallback

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 `delegatecall`.

A diamond’s fallback function and `delegatecall` enable a diamond to execute a facet’s function as if it was implemented by the diamond itself. The `msg.sender` and `msg.value` values do not change and only the diamond’s storage is read and written to.

Here is an example of how a diamond’s fallback function might be implemented:

```solidity
error FunctionNotFound(bytes4 _selector);

// Executes function call on facet using `delegatecall`.
// Returns function call return data or revert data.
fallback() external payable {
    // Get facet address from function selector
    address facet = selectorToFacet[msg.sig];
    if (facet == address(0)) {
        revert FunctionNotFound(msg.sig);
    }
    // Execute external function on facet using `delegatecall` and return any value.
    assembly {
        // Copy function selector and any arguments from calldata to memory.
        calldatacopy(0, 0, calldatasize())
        // Execute function call using the facet.
        let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)
        // Copy all return data from the previous call into memory.
        returndatacopy(0, 0, returndatasize())
        // Return any return value or error back to the caller.
        switch result
        case 0 {revert(0, returndatasize())}
        default {return (0, returndatasize())}
    }
}
```
#### Function Not Found

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 `FunctionNotFound(bytes4 _selector)`.

### Inspecting Diamonds

An [ERC-8153](./eip-8153) diamond MUST implement the same introspection functions as defined in ERC-2535.
Specifically, these functions MUST be implemented:

```solidity
interface IDiamondInspect {
    struct Facet {
        address facetAddress;
        bytes4[] functionSelectors;
    }

    /// @notice Gets all facet addresses and their four byte function selectors.
    /// @return facets_ Facet
    function facets() external view returns (Facet[] memory facets_);

    /// @notice Gets all the function selectors supported by a specific facet.
    /// @param _facet The facet address.
    /// @return facetFunctionSelectors_
    function facetFunctionSelectors(address _facet) external view returns (bytes4[] memory facetFunctionSelectors_);

    /// @notice Get all the facet addresses used by a diamond.
    /// @return facetAddresses_
    function facetAddresses() external view returns (address[] memory facetAddresses_);

    /// @notice Gets the facet that supports the given selector.
    /// @dev If facet is not found return address(0).
    /// @param _functionSelector The function selector.
    /// @return facetAddress_ The facet address.
    function facetAddress(bytes4 _functionSelector) external view returns (address facetAddress_);
}
```

Typically, these functions are implemented in a facet and the facet is added to diamonds.

### Inspecting Facets

Each facet MUST implement the following pure introspection function:

```solidity
function exportSelectors() external pure returns (bytes memory selectors)
```

`exportSelectors()` returns a `bytes` array containing one or more 4-byte function selectors. The returned `bytes` array length is a multiple of 4, and each 4-byte chunk is a selector. The function MUST not return the same selector more than once.

The `bytes` array contains selectors of functions implemented by the facet that are intended to be added to a diamond.

This enables a diamond to discover selectors directly from facets at deployment or upgrade time. A diamond calls `exportSelectors()` on each facet to determine which selectors to add, replace, or remove.

Selector gathering is therefore no longer an off-chain responsibility.

This also means diamonds implementing this ERC are **facet-based** rather than **function-based**. Deployment and upgrades operate on facets.

### Facet-Based Events

This ERC replaces ERC-2535’s function-based events with facet-based events. 

When facets are added, replaced, or removed, the diamond MUST emit the following events:

```solidity
 /**
  * @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.
  */
event FacetAdded(address indexed _facet);

/**
 * @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.
 */
event FacetReplaced(address indexed _oldFacet, address indexed _newFacet);

/**
 * @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.
 */
event FacetRemoved(address indexed _facet);
```

Block explorers and other tooling can obtain the function selectors for any of the facets referenced by these events by calling `exportSelectors()` on the facet address.

### Optional Upgrade Events

#### Recording Non-Fallback `delegatecall`s

This event is OPTIONAL.

This event can be used to record `delegatecall`s made by a diamond.

This event MUST NOT be emitted for `delegatecall`s made by a diamond’s fallback function when routing calls to facets. It is only intended for `delegatecall`s made by functions in facets or a diamond’s constructor.

This event enables tracking of changes to a diamond’s contract storage caused by `delegatecall` execution.

```solidity
/**
* @notice Emitted when a diamond&apos;s constructor function 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.
*/
event DiamondDelegateCall(address indexed _delegate, bytes _delegateCalldata);
```

#### Diamond Metadata

This event is OPTIONAL.

This event can be used to record versioning or other information about diamonds.

It can be used to record information about diamond upgrades.

```solidity
/**
* @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.
*/
event DiamondMetadata(bytes32 indexed _tag, bytes _data);
```

### Implementation Requirements

A facet-based diamond MUST implement the following:

1. **Diamond Structure**
   - A `fallback()` function.
2. **Function Association**
   - It MUST associate function selectors with facet addresses.
3. **Function Execution**
   - When an external function is called on a diamond:
     - The diamond’s fallback function is executed. 
     - The fallback function MUST find the facet associated with the function selector.
     - The fallback function MUST execute the function on the facet using `delegatecall`.
     - If no facet is associated with the function selector, the diamond MAY execute a default function or apply another handling mechanism.
     - If no facet, default function, or other handling mechanism exists, execution MUST revert with the error `FunctionNotFound(bytes4 _selector)`.
4. **Events**
   - The following events MUST be emitted:
     - `FacetAdded` — when a facet is added to a diamond.
     - `FacetReplaced` — when a facet is replaced with a different facet.
     - `FacetRemoved` — when a facet is removed from a diamond.
5. **Diamond Introspection**
   - A diamond MUST implement the following introspection functions:
     - `facets()`
     - `facetFunctionSelectors(address _facet)`
     - `facetAddresses()`
     - `facetAddress(bytes4 _functionSelector)`
6. **Facet Introspection**
   - Each facet MUST implement the `exportSelectors()` function, which returns a `bytes` array.


### `receive()` function

A diamond MAY have a `receive()` function.

### `upgradeDiamond` Function

Implementing `upgradeDiamond` is OPTIONAL.

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.

`upgradeDiamond` adds, replaces, and removes any number of facets in a single transaction. It can also optionally execute a `delegatecall` to perform initialization or state migration.

The `upgradeDiamond` function works as follows:

#### Adding a Facet

1. Call `exportSelectors()` on the facet to obtain its function selectors. 
2. Add each selector to the diamond, mapping it to the facet address.

#### Replacing a Facet

1. Call `exportSelectors()` on the old facet to obtain its packed selectors.
2. Call `exportSelectors()` on the new facet to obtain its packed selectors.
3. For selectors present in the new facet but not the old facet: add them.
4. For selectors present in both: replace them to point to the new facet.
5. For selectors present in the old facet but not the new facet: remove them.

#### Removing a Facet
1. Call `exportSelectors()` on the facet to obtain its packed selectors.
2. Remove each selector from the diamond.

#### Errors and Types

```solidity
/**
 * @notice The upgradeDiamond function below detects and reverts
 *         with the following errors.
 */
error NoSelectorsForFacet(address _facet);
error NoBytecodeAtAddress(address _contractAddress);
error CannotAddFunctionToDiamondThatAlreadyExists(bytes4 _selector);
error CannotRemoveFacetThatDoesNotExist(address _facet);
error CannotReplaceFacetWithSameFacet(address _facet);
error FacetToReplaceDoesNotExist(address _oldFacet);
error DelegateCallReverted(address _delegate, bytes _delegateCalldata);
error ExportSelectorsCallFailed(address _facet);

/**
 * @dev This error means that a function to replace exists in a
 *      facet other than the facet that was given to be replaced.
 */
error CannotReplaceFunctionFromNonReplacementFacet(bytes4 _selector);

/**
 * @notice This struct is used to replace old facets with new facets.
 */
struct FacetReplacement {
    address oldFacet;
    address newFacet;
}
```

#### Function Signature

```solidity
/**
 * @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 &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.
 */
function upgradeDiamond(
    address[] calldata _addFacets,
    FacetReplacement[] calldata _replaceFacets,
    address[] calldata _removeFacets,
    address _delegate,
    bytes calldata _delegateCalldata,
    bytes32 _tag,
    bytes calldata _metadata
);
```
The `upgradeDiamond` function MUST adhere to the following requirements:

&gt; The complete definitions of events and custom errors referenced below are given earlier in this standard.

1. **Inputs**
   - `_addFacets` array of facet addresses to add.
   - `_replaceFacets` array of (`oldFacet`, `newFacet`) pairs.
   - `_removeFacets` array of facet addresses to remove.

2. **Execution Order**
   1. Add facets
   2. Replace facets
   3. Remove facets

3. **Event Emission**
   - Every change to a facet MUST emit exactly one of:
     - `FacetAdded`
     - `FacetReplaced`
     - `FacetRemoved`

4. **Error Conditions**
   - The implementation MUST detect and revert with the specified error when:
     - Adding a selector that already exists: `CannotAddFunctionToDiamondThatAlreadyExists`.
     - Removing a facet that does not exist: `CannotRemoveFacetThatDoesNotExist`.
     - Replacing a facet with itself: `CannotReplaceFacetWithSameFacet`.
     - Replacing a facet that does not exist: `FacetToReplaceDoesNotExist`.
     - Replacing a selector that exists in the diamond but is mapped to a facet different than the facet being replaced: `CannotReplaceFunctionFromNonReplacementFacet`.

5. **Facet Validation**
   - If any facet address contains no contract bytecode, revert with `NoBytecodeAtAddress`.
   - If `exportSelectors()` is missing, reverts, or cannot be called successfully, revert with `ExportSelectorsCallFailed`.
   - If `exportSelectors()` returns zero selectors, revert with `NoSelectorsForFacet`.

6. **Delegate Validation**
   - If `_delegate` is non-zero but contains no bytecode, revert with `NoBytecodeAtAddress`.

7. **Delegatecall Execution**
   - If `_delegate` is non-zero, the diamond MUST `delegatecall` `_delegate` with `_delegateCalldata`.
   - If the `delegatecall` fails and returns revert data, the diamond MUST revert with the same revert data.
   - If the `delegatecall` fails and returns no revert data, revert with `DelegateCallReverted`.
   - If a `delegatecall` is performed, the diamond MUST emit the `DiamondDelegateCall` event.
   - `_delegateCalldata` MAY be empty. If empty, the `delegatecall` executes with no calldata.

8. **Metadata Event**
   - If `_tag` is non-zero or `_metadata.length &gt; 0`, the diamond MUST emit the `DiamondMetadata` event.

After adding, replacing, or removing facets, the diamond MAY perform a `delegatecall` to initialize, migrate, or clean up state.

It is also valid to call `upgradeDiamond` solely to perform a `delegatecall` (i.e., without adding, replacing, or removing any facets).

To skip an operation, supply an empty array for its parameter (for example, `new address[](0)` for `_addFacets`).

## Rationale

### Eliminating Selector Management

To deploy a facet-based diamond implementing this ERC, the deployer provides an array of facet addresses to the diamond constructor. The constructor calls `exportSelectors()` on each facet and registers those selectors in the diamond.

Because facets self-describe their selectors, deployers no longer need to gather selectors off-chain or depend on specialized selector tooling.

### Reducing Deployment Gas Costs

#### Reducing Calldata

In a non-facet-based diamond, selectors are typically passed to the constructor as one or more `bytes4[]` arrays. These arrays are paid for in calldata and then copied into memory, incurring additional gas.

In a facet-based diamond, only facet addresses are passed to constructors. The diamond calls `exportSelectors()` on each facet to obtain selectors on-chain, avoiding calldata costs for selector lists. While calling `exportSelectors()` introduces some overhead, non-facet-based diamonds typically perform code-existence checks (e.g., `extcodesize`) on facet addresses anyway, incurring the cold account access gas cost.

#### Reducing Storage

In a **non-facet-based diamond**, function selectors are stored directly for introspection, typically in a `bytes4[] selectors` array (or an equivalent structure). Because a storage slot is 32 bytes, each slot can hold up to eight `bytes4` selectors. As more functions are added, additional storage slots are required, so storage usage grows linearly with the number of selectors.

In a **facet-based diamond**, introspection data can be stored **per facet instead of per function**. 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.

Alternatively, a facet-based diamond can be implemented as a **linked list of facets**. With this design, introspection requires a **single 32-byte storage slot**, while supporting any number of facets and any number of selectors per facet.

### `exportSelectors()` Function Return Value

`exportSelectors()` returns `bytes` rather than `bytes4[]` for two reasons:

#### `bytes4[]` Wastes Memory

Each element of a `bytes4[]` 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 `bytes` reduces memory overhead.

#### Simple Syntax For Facets

Facets can implement `exportSelectors()` concisely using Solidity&apos;s built-in function `bytes.concat`. Example:

```solidity
function exportSelectors() external pure returns (bytes memory) {
    return bytes.concat(
        this.facetAddress.selector,
        this.facetFunctionSelectors.selector,
        this.facetAddresses.selector,
        this.facets.selector
    );
}
```

The diamond can traverse the returned bytes and extract selectors efficiently.

### Diamond Upgrades

This upgrade function specified by this standard is optional.

This means a couple things:

#### 1. Diamonds Can Be Immutable

A Diamond does not have to have an upgrade function.

- A diamond can be fully constructed within its constructor function without adding any upgrade function, making it immutable upon deployment.

- A large immutable diamond can be built using well organized facets.

- A diamond can initially be upgradeable, and later made immutable by removing its upgrade function.

#### 2. You Can Create Your Own Upgrade Functions

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 required events specified in the [Facet-Based Events section](#facet-based-events), that the introspection functions defined in the [Inspecting Diamonds section](#inspecting-diamonds) and the [Inspecting Facets section](#inspecting-facets) continue to exists and accurately return function and facet information.

### Runtime Gas Considerations

Routing calls via `delegatecall` introduces a small amount of gas overhead. In practice, this cost is mitigated by several architectural and tooling advantages enabled by diamonds:

1. **Optional, gas-optimized functionality**  
   By structuring functionality across multiple facets, diamonds make it straightforward to include specialized, gas-optimized features without increasing the complexity of core logic.  
   For example, an [ERC-721](/EIPs/EIPS/eip-721) 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.

2. **Reduced external call overhead**    
   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.  

3. **Selective optimization per facet**  
   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.

### Storage Layout

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 [ERC-8042 Diamond Storage](./eip-8042) and [ERC-7201 Namespaced Storage Layout](./eip-7201).

### Facets Sharing Storage &amp; Functionality

Facets are separately deployed, independent units, but can share state and functionality in the following ways:

- Facets can share state variables by using the same structs at the same storage positions. 
- Facets can share internal functions by importing them or inheriting contracts. 

### On-chain Facets can be Reused and Composed

A deployed facet can be used by many diamonds.

It is possible to create and deploy a set of facets that are reused by different diamonds.

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.

It is possible to implement facets in a way that makes them usable/composable/compatible with other facets. 

## Backwards Compatibility

Diamonds implementing this ERC have the same introspection functions as ERC-2535 diamonds, so they are compatible with ERC-2535 tooling that rely on these functions.

## Security Considerations

### Arbitrary Execution with `upgradeDiamond`

The `upgradeDiamond` function allows arbitrary execution with access to the diamond’s storage (through delegatecall). Access to this function must be restricted carefully.

### Use Only Trusted and Verified Facets

Only trusted and verified facets should be added to facet-based diamonds.

`exportSelectors()` MUST be `pure` and should not contain logic that varies the returned bytes. Facets should be immutable so returned selectors cannot change over time.

If a facet’s `exportSelectors()` output changes, upgrades that rely on it may add/remove/replace the wrong selectors and corrupt diamonds.

### Upgrade Integrity Checks

The specified `upgradeDiamond` behavior prevents a number of upgrade mistakes. Upgrades revert when:

- A facet is added that already exists in the diamond.
- A facet is replaced or removed that does not exist in the diamond.
- A selector is added that already exists in the diamond.
- A selector is replaced that exists in the diamond but it is from a different facet than the facet being replaced.
- A facet address contains no bytecode.
- A facet does not implement `exportSelectors()` successfully.
- A facet provides zero selectors.
- A facet is replaced with itself (same contract address).

Selector collisions (two different signatures with the same 4-byte selector) are handled as “selector already exists” and are therefore prevented.

### Do Not Self Destruct
Use of selfdestruct in a facet is heavily discouraged. Misuse of it can delete a diamond or a facet.

### Transparency

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. 

Security and domain experts can review a diamond&apos;s upgrade history.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>
        <category>Standards Track/Networking</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8159-eth-71-block-access-list-exchange/27725</comments>
        
        <description>## Abstract

This EIP modifies the &apos;eth&apos; p2p protocol to support Block-level Access Lists (BALs). It adds two new messages, `GetBlockAccessLists` (0x12) and `BlockAccessLists` (0x13), enabling peers to request and serve BALs for synchronization and parallel execution.

## Motivation

[EIP-7928](/EIPs/EIPS/eip-7928) 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.

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.

## Specification

### Block Header Extension

The block header is extended with a new field after `requests-hash`:

```
block-header = [
    ...
    requests-hash: B_32,
    block-access-list-hash: B_32,
]
```

The `block-access-list-hash` field contains `keccak256(rlp.encode(block-access-list))` as defined in [EIP-7928](/EIPs/EIPS/eip-7928). This field MUST be present in headers after the Amsterdam fork and absent for earlier blocks.

### Block Access List Encoding

BALs are RLP-encoded as a list of account changes, sorted lexicographically by address:

```
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: B_32, [storage-change₁, storage-change₂, ...]]
storage-change = [block-access-index: P, value: B_32]

storage-reads = [slot₁: B_32, slot₂: B_32, ...]

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]
```

`storage-changes` MUST be sorted lexicographically by slot. Changes within each slot MUST be sorted by `block-access-index` ascending. `storage-reads` MUST be sorted lexicographically by slot.

Where `block-access-index` indicates when the change occurred:

- `0` for pre-execution system contract calls
- `1...n` for transactions (in block order)
- `n+1` for post-execution system contract calls and withdrawals

See [EIP-7928](/EIPs/EIPS/eip-7928) for complete BAL generation rules and inclusion semantics.

### New Protocol Messages

#### GetBlockAccessLists (0x12)

```
[request-id: P, [blockhash₁: B_32, blockhash₂: B_32, ...]]
```

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.

BALs are only available for blocks after [EIP-7928](/EIPs/EIPS/eip-7928) activation and within the retention period defined therein. Requests for unavailable BALs return empty entries.

#### BlockAccessLists (0x13)

```
[request-id: P, [block-access-list₁, block-access-list₂, ...]]
```

Response to `GetBlockAccessLists`. Each element corresponds to a block hash from the request, in order. Empty BALs (RLP-encoded empty list `0xc0`) are returned for blocks where the BAL is unavailable.

The recommended soft limit for `BlockAccessLists` responses is 2 MiB.

### Validation

When a BAL is received, clients MUST validate it by computing `keccak256(rlp.encode(bal))` and comparing against the `block-access-list-hash` in the corresponding block header.

## Rationale

### Separate Messages vs. Block Body Extension

BALs are transmitted via dedicated messages rather than extending block bodies because:

1. **Size**: BALs average ~70 KiB, significantly increasing block propagation overhead if bundled.
2. **Optional retrieval**: Not all sync strategies require BALs. Snap sync can reconstruct state without them.
3. **Retention policy**: BALs may be pruned per [EIP-7928](/EIPs/EIPS/eip-7928), while block bodies are retained longer.

### Message IDs

Message IDs 0x12 and 0x13 follow sequentially from the existing eth/69 messages (BlockRangeUpdate is 0x11).

### Response Size Limit

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.

## Backwards Compatibility

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.

This EIP requires the Amsterdam hard fork for the header field extension. The new messages are only meaningful for post-Amsterdam blocks.

## Security Considerations

### Validation Cost

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.

### Amplification

A `GetBlockAccessLists` request can trigger responses larger than the request. Implementations SHOULD apply rate limiting and respect the soft response size limit to prevent amplification attacks.

### Unavailable Data

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.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Transferable Tokenized Vault Requests</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/draft-erc-transferable-asynchronous-tokenized-vault-requests/27747</comments>
        
        <description>## Abstract

This standard extends [ERC-7540](/EIPs/EIPS/eip-7540) by adding optional transferability of pending deposit and redeem Requests. It introduces two separate interfaces that allow a controller to transfer their pending Request balance to a new controller. Implementations may support either or both interfaces independently.

## Motivation

[ERC-7540](/EIPs/EIPS/eip-7540) asynchronous Requests can remain in the Pending state for an extended period of time. During this period, controllers have no way to transfer their position to another address. This creates friction for users who need to migrate wallets, restructure positions across accounts, or integrate with protocols that compose on top of pending Request positions.

By enabling transferability of pending Requests, this standard unlocks secondary market liquidity for pending positions and simplifies account management without requiring cancelation and re-submission of Requests.

Transferability is kept optional and split into two separate interfaces so that implementations can choose to support transferable deposit Requests, transferable redeem Requests, both, or neither, depending on their security model and use case.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

### Transferable Deposit Requests

Vaults that support transferable deposit Requests MUST implement the `IERC7540DepositTransferable` interface.

#### `transferDepositRequest`

Transfers the entire pending deposit Request balance from `oldController` to `newController` for the given `requestId`.

MUST only transfer the Pending balance. Claimable balances MUST NOT be affected.

After a successful transfer, `pendingDepositRequest(requestId, oldController)` MUST decrease by the transferred amount and `pendingDepositRequest(requestId, newController)` MUST increase by the same amount (less any fees).

`msg.sender` MUST be `oldController` or an operator approved by `oldController`.

MUST emit the `TransferDepositRequest` event.

```yaml
- name: transferDepositRequest
  type: function
  stateMutability: nonpayable

  inputs:
    - name: requestId
      type: uint256
    - name: oldController
      type: address
    - name: newController
      type: address
```

#### `TransferDepositRequest`

`from` has transferred their pending deposit Request to `to` for the given `requestId`.

MUST be emitted when a pending deposit Request is transferred using the `transferDepositRequest` method.

```yaml
- name: TransferDepositRequest
  type: event

  inputs:
    - name: requestId
      indexed: true
      type: uint256
    - name: from
      indexed: true
      type: address
    - name: to
      indexed: true
      type: address
```

### Transferable Redeem Requests

Vaults that support transferable redeem Requests MUST implement the `IERC7540RedeemTransferable` interface.

#### `transferRedeemRequest`

Transfers the entire pending redeem Request balance from `oldController` to `newController` for the given `requestId`.

MUST only transfer the Pending balance. Claimable balances MUST NOT be affected.

After a successful transfer, `pendingRedeemRequest(requestId, oldController)` MUST decrease by the transferred amount and `pendingRedeemRequest(requestId, newController)` MUST increase by the same amount (less any fees).

`msg.sender` MUST be `oldController` or an operator approved by `oldController`.

MUST emit the `TransferRedeemRequest` event.

```yaml
- name: transferRedeemRequest
  type: function
  stateMutability: nonpayable

  inputs:
    - name: requestId
      type: uint256
    - name: oldController
      type: address
    - name: newController
      type: address
```

#### `TransferRedeemRequest`

`from` has transferred their pending redeem Request to `to` for the given `requestId`.

MUST be emitted when a pending redeem Request is transferred using the `transferRedeemRequest` method.

```yaml
- name: TransferRedeemRequest
  type: event

  inputs:
    - name: requestId
      indexed: true
      type: uint256
    - name: from
      indexed: true
      type: address
    - name: to
      indexed: true
      type: address
```

### [ERC-165](/EIPs/EIPS/eip-165) Support

Smart contracts implementing this standard MUST implement the [ERC-165](/EIPs/EIPS/eip-165) `supportsInterface` function.

Vaults implementing `IERC7540DepositTransferable` MUST return the constant value `true` when `0x53b3bb0a` is passed through the `interfaceID` argument.

Vaults implementing `IERC7540RedeemTransferable` MUST return the constant value `true` when `0x7846f5bd` is passed through the `interfaceID` argument.

## Rationale

### Only Transferring Pending Balances

This standard deliberately restricts transfers to the Pending state. Claimable balances already have a deterministic exchange rate and can be claimed by the controller at any time; transferring them would add complexity without significant benefit. Limiting scope to Pending balances keeps the interface simple and avoids edge cases around partial claimability.

### Separate Interfaces for Deposit and Redeem Transferability

Following the design philosophy of [ERC-7540](/EIPs/EIPS/eip-7540) where deposit and redemption flows are independently optional, this standard keeps deposit and redeem transferability as separate interfaces. A Vault may have valid reasons to allow transferability of one request type but not the other. For example, a Vault might allow transfer of pending deposit Requests (where assets are locked) but disallow transfer of pending redeem Requests (where shares have already been burned or locked with specific accounting implications).

### Transferring the Full Pending Balance

The `transferDepositRequest` and `transferRedeemRequest` methods transfer the entire pending balance rather than accepting a partial amount. This simplifies the interface and aligns with the ERC-7540 model where Requests of the same `requestId` are fungible.

## Backwards Compatibility

This standard is fully backward compatible with [ERC-7540](/EIPs/EIPS/eip-7540). Vaults that do not implement this extension continue to function as before. Integrators can detect support for transferability via [ERC-165](/EIPs/EIPS/eip-165) `supportsInterface`.

## Security Considerations

### Operator Trust

As with ERC-7540, operators approved by a controller can transfer pending Requests on their behalf. Users must be aware that granting operator permissions extends to the ability to transfer pending Requests to arbitrary addresses, effectively moving locked assets or shares out of the controller&apos;s control.

### Pricing of Pending Requests

Unlike Vault shares, which have `convertToShares` and `convertToAssets` as onchain price references, pending Requests have no built-in pricing mechanism. The exchange rate is unknown until fulfillment. Builders of secondary markets around transferable Requests should account for this lack of a canonical price source when designing pricing and settlement mechanisms.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 12 Feb 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8161</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8161</guid>
      </item>
    
      <item>
        <title>Reserve `EXTENSION (0xae)` opcode</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8163-reserve-0xae-extension-opcode/27756</comments>
        
        <description>## Abstract

Reserve an opcode `EXTENSION (0xae)` which will be guaranteed to not become a valid opcode on Ethereum L1 EVM, but which will be available to be used in other EVMs as a prefix to encode extension instructions.

## Motivation

Currently, non-Ethereum-L1 EVM chains cannot innovate on the EVM by introducing new instructions, because they run a risk of becoming incompatible with the Ethereum L1 EVM and the EVMs on other chains, in the event that these decide to implement new features using overlapping opcodes.

By setting aside a single opcode and agreeing that it will never become a valid instruction on Ethereum L1 EVM, we open up to extensions which can be implemented on other EVM chains. If these extensions prove out to be successful outside of Ethereum L1, then they can be back-ported into Ethereum L1 EVM, to the benefit of the entire EVM ecosystem.

Similarly, making it easier for innovations to happen inside the EVM should generally improve the EVM tooling by strengthening the network effects. In other words, it is beneficial for an innovation X to happen within the EVM, even if not on Ethereum Mainnet.

In particular, the extension opcode might be adopted by Ethereum L2 EVMs, allowing them to specialize and experiment, potentially expanding the catalogue of extensions relevant to the L1.

The extension opcode is designed in such a way to not only have **no impact** on Ethereum L1 EVM behavior, but also to not require any Ethereum Execution Layer Client modifications, except, optionally, for their presentation layer (e.g., traces), which is irrelevant to consensus.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

### `EXTENSION (0xae)`

Reserve a new opcode `EXTENSION (0xae)` which MUST behave exactly like `INVALID (0xfe)` (see [EIP-141](/EIPs/EIPS/eip-141)) on all Ethereum L1 chains (Ethereum Mainnet, Testnets, etc.). In particular:

1. Executing `EXTENSION` MUST cause an exceptional halt (exit current execution frame and consume all gas, same as `INVALID`).
2. `EXTENSION` byte in the bytecode MUST NOT impact `JUMPDEST` analysis in any way, i.e. all jump destinations&apos; validity MUST NOT be affected.
3. Any validation, static analysis, or preprocessing of bytecode, if introduced, MUST NOT be affected by the `EXTENSION` byte in the bytecode in any way other than how `INVALID` would affect it.

### Chain Specifics

Outside of Ethereum L1, `EXTENSION` MAY have meaningful behavior during execution, but it is up to the particular EVM implementations to decide.

However, in these EVMs which execute `EXTENSION`, the `JUMPDEST` analysis MUST still be unaffected by `EXTENSION`, i.e. the set of valid jump destinations MUST be identical to that obtained on Ethereum L1.

The particular behavior of the `EXTENSION` instruction on non-Ethereum-L1 EVMs adopting it MUST be determined by bytes following `EXTENSION` as immediate args. If such immediate args contain any `JUMPDEST (0x5b)` byte which remains a valid jump destination, execution MUST result in an exceptional halt.

The non-Ethereum-L1 EVM implementers SHOULD coordinate via the discussion thread of this EIP on their specific usage of `EXTENSION`.

## Rationale

### No effect on `JUMPDEST` analysis

An alternative considered was to have `EXTENSION`:

- invalidate `0x5b` byte following it as a jump destination and
- skip over `PUSHx` instructions following it

however that would require this EIP to prescribe the size of the immediate arguments.

It would also run into conflict with any opcodes with immediate arguments introduced in the EVM via other EIPs.

Lastly, it could cause different jump destination validity for same bytecode when analyzed on and outside Ethereum L1 EVM, causing code to not be portable between chains.

It is therefore presumed that a `0xae5b` sequence cannot be a valid extension instruction and its second byte will be a valid jump destination. `0xae60`-`0xae7f` byte sequences will not be valid extension instructions, unless the `PUSH1 (0x60)`-`PUSH32 (0x7f)` byte is used to introduce `JUMPDEST`-neutral immediate arguments (since `PUSHx` instruction data is already skipped during `JUMPDEST` analysis).

| Bytecode sequence | `JUMPDEST (0x5b)` validity | Possible extension opcode execution                               |  
|-------------------|----------------------------|----------------------------------------------------------------------|
| `0xae5b...`       | valid                      | Invalid extension                                                  |
| `0xae015b...`     | valid                      | Valid extension with `0x01` argument                              |
| `0xae60`          | N/A                        | Invalid extension (truncated)                                      |
| `0xae605b...`     | invalid                    | Valid extension with `0x5b` argument encoded in `PUSH1` data        |
| `0xae60605b...`   | valid                      | Valid extension with `0x60` argument encoded in `PUSH1` data        |
| `0xae61605b...`   | invalid                    | Valid extension with `0x605b` argument encoded in `PUSH2` data      |
| `0xae615b`        | invalid                    | Invalid extension (truncated)                                          |

### Lack of definition of a particular encoding scheme

This EIP chooses to not define any extension encoding scheme, in order to limit its scope as much as possible. Any such extension encoding scheme can be introduced and discussed in a separate proposal.

### Explicit lack of support on Ethereum L1 EVM

We explicitly prohibit any multi-byte opcode support using `EXTENSION` on the Ethereum L1 EVM. If one is desired in the future, it should be implemented using a different prefix.

### Porting extension instructions back to Ethereum L1

In the event a feature implemented using `EXTENSION` needs to be ported back, a distinct opcode is chosen in a separate EIP. Once that EIP is in turn adopted in the originator EVM, that EVM will operate with two alternative ways to access the feature.

## Backwards Compatibility

The opcode `EXTENSION` is currently invalid in Ethereum, and it doesn&apos;t impact `JUMPDEST` analysis, thus no code containing it will change behavior.

## Test Cases

Will be provided in the Ethereum Execution Layer Specs format.

## Reference Implementation

None, Ethereum Execution Layer clients&apos; behavior does not change.

## Security Considerations

None, Ethereum Execution Layer clients&apos; behavior does not change.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Fri, 13 Feb 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8163</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8163</guid>
      </item>
    
      <item>
        <title>Native Key Delegation for EOAs</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8164-native-key-delegation/27770</comments>
        
        <description>## Abstract

This EIP extends the delegation designator system introduced by [EIP-7702](/EIPs/EIPS/eip-7702) to support **native key delegation** — permanently converting an EOA&apos;s authentication from ECDSA over secp256k1 to an alternative signature scheme. A new code prefix `0xef0101` designates an account whose authentication key is an ML-DSA-44 public key embedded directly in the account&apos;s code field. Once set, the original ECDSA key is rendered permanently inert. A single new transaction type supports both ECDSA-signed key migration and ML-DSA-44-authenticated transaction origination. Accounts may be created without any party ever possessing the ECDSA private key, using a crafted-signature technique analogous to Nick&apos;s method ([ERC-2470](/EIPs/EIPS/eip-2470)) for keyless contract deployment.

## Motivation

EIP-7702 brought code delegation to EOAs but retained ECDSA over secp256k1 as the sole native authentication mechanism. This constrains the ecosystem to a single signature scheme with known limitations:

- **Quantum vulnerability.** secp256k1 ECDSA is vulnerable to quantum attacks. Native key delegation with ML-DSA-44, a NIST-standardized post-quantum scheme, directly addresses this threat. The framework generalizes to future post-quantum schemes via additional `0xef01XX` designators.
- **Hardware ecosystem mismatch.** Secure enclaves and hardware security modules increasingly ship with native support for signature schemes beyond secp256k1. Forcing ECDSA introduces bridging complexity and enlarges the trusted computing base.
- **Smart contract wallet overhead.** Smart contract wallets and EIP-7702 code delegation can achieve alternative authentication today, but at the cost of EVM execution for every transaction validation. Native key delegation moves signature verification into the protocol, eliminating per-transaction contract overhead.
- **Provably rootless accounts.** The crafted-signature creation path produces accounts where the ECDSA private key *never existed*, providing a cryptographic guarantee — not merely a procedural one — that no backdoor key can override the installed scheme.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

### Constants

| Name | Value | Description |
|------|-------|-------------|
| `NATIVE_KEY_TX_TYPE` | `Bytes1(0x06)` | Transaction type for native key operations |
| `NATIVE_KEY_MAGIC` | `0x07` | Domain separator for native key authorization signing |
| `ML_DSA_44_DESIGNATION` | `0xef0101` | 3-byte code prefix for ML-DSA-44 native key accounts |
| `PER_NATIVE_AUTH_BASE_COST` | `12500` | Gas charged per native key authorization tuple (matches [EIP-7702](/EIPs/EIPS/eip-7702) `PER_AUTH_BASE_COST`) |
| `PER_EMPTY_ACCOUNT_COST` | `25000` | Additional gas if the authority account was previously empty (same as [EIP-7702](/EIPs/EIPS/eip-7702)) |
| `ML_DSA_44_VERIFY_COST` | `50000` | Intrinsic gas for ML-DSA-44 signature verification |

### Delegation Designator Space

EIP-7702 defines the code prefix `0xef0100` for code delegation. This EIP extends the `0xef01XX` namespace:

| Prefix | Code length | Semantics |
|--------|-------------|-----------|
| `0xef0100` | 23 bytes | Code delegation ([EIP-7702](/EIPs/EIPS/eip-7702)) |
| `0xef0101` | 1,315 bytes | ML-DSA-44 native key (this EIP) |
| `0xef0102`–`0xef01ff` | varies | Reserved for future signature schemes |

An account whose code is exactly `0xef0101 || pubkey` (1,315 bytes) is a **native-key account**. The 1,312-byte `pubkey` is an ML-DSA-44 public key used for all subsequent transaction authentication.

### Native Key Transaction (Type `0x06`)

A new [EIP-2718](/EIPs/EIPS/eip-2718) transaction type serves both native key migration and native-key-authenticated transaction origination:

```
0x06 || rlp([
    chain_id,
    nonce,
    max_priority_fee_per_gas,
    max_fee_per_gas,
    gas_limit,
    to,
    value,
    data,
    access_list,
    native_key_authorization_list,
    sender,
    signature
])
```

The fields `chain_id`, `nonce`, `max_priority_fee_per_gas`, `max_fee_per_gas`, `gas_limit`, `to`, `value`, `data`, and `access_list` follow the same semantics as [EIP-4844](/EIPs/EIPS/eip-4844). A null `to` is not valid.

| Field | Type | Description |
|-------|------|-------------|
| `native_key_authorization_list` | `list` | Authorization tuples for setting native keys (may be empty) |
| `sender` | `bytes` | Empty for ECDSA mode, or 20-byte address for native key mode |
| `signature` | `bytes` | 65-byte ECDSA signature or 2,420-byte ML-DSA-44 signature |

The `sender` field determines the transaction&apos;s authentication mode:

- **ECDSA mode** (`sender` is empty): The transaction is signed with ECDSA. `signature` is 65 bytes, encoding `y_parity || r || s`. The transaction sender is recovered via `ecrecover`. Any EOA may submit this transaction; the submitter need not be the authority whose key is being set.
- **ML-DSA-44 mode** (`sender` is 20 bytes): The transaction is signed with ML-DSA-44 by the native-key account at `sender`. `signature` is 2,420 bytes.

The signing payload for both modes is:

```
tx_hash = keccak256(NATIVE_KEY_TX_TYPE || rlp([
    chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas,
    gas_limit, to, value, data, access_list,
    native_key_authorization_list, sender
]))
```

In ECDSA mode, `sender` is empty in the payload, so the signing domain is distinct from ML-DSA-44 mode where `sender` is 20 bytes.

#### Native Key Authorization Tuple

The `native_key_authorization_list` supports two tuple formats: ECDSA-signed tuples for initial key migration, and native-key-signed tuples for key rotation. Tuples are distinguished by element count: 6 elements for ECDSA, 5 for native key. Tuples with any other element count are invalid.

##### ECDSA-Signed Authorization (Key Migration)

Each ECDSA-signed entry has the form:

```
ecdsa_auth = [chain_id, pubkey, nonce, y_parity, r, s]
```

| Field | Type | Description |
|-------|------|-------------|
| `chain_id` | `uint256` | Target chain ID, or `0` for any chain |
| `pubkey` | `bytes` | Native public key to install |
| `nonce` | `uint64` | Current nonce of the authority account |
| `y_parity` | `uint8` | ECDSA recovery parameter |
| `r` | `uint256` | ECDSA signature component |
| `s` | `uint256` | ECDSA signature component |

The authorization message is:

```
msg_hash = keccak256(NATIVE_KEY_MAGIC || rlp([chain_id, pubkey, nonce]))
```

The **authority** is recovered via `ecrecover(msg_hash, y_parity, r, s)`.

##### Native Key Authorization (Key Rotation)

Each native-key-signed entry has the form:

```
native_key_auth = [chain_id, new_pubkey, nonce, authority, signature]
```

| Field | Type | Description |
|-------|------|-------------|
| `chain_id` | `uint256` | Target chain ID, or `0` for any chain |
| `new_pubkey` | `bytes` | New public key to install |
| `nonce` | `uint64` | Current nonce of the authority account |
| `authority` | `address` | Address of the native-key account authorizing rotation |
| `signature` | `bytes` | Signature by the currently installed key |

The authorization message is:

```
msg_hash = keccak256(NATIVE_KEY_MAGIC || rlp([chain_id, new_pubkey, nonce, authority]))
```

The **authority** is stated explicitly. Its currently installed native key is used for verification. The `authority` address is included in the signed message to prevent cross-account replay.

#### Transaction Validation

Future EIPs may modify this verification procedure to account for non-ML-DSA-44 native key delegations.

If `sender` is empty (ECDSA mode):

1. Verify `signature` is exactly 65 bytes. Otherwise the transaction is invalid.
2. Parse `y_parity = signature[0]`, `r = signature[1..33]`, `s = signature[33..65]`.
3. Recover the transaction sender via `ecrecover(tx_hash, y_parity, r, s)`. If recovery fails, the transaction is invalid.
4. Proceed with standard sender validation (nonce, balance, etc.).

If `sender` is 20 bytes (Native Key mode):

1. Verify `sender`&apos;s code begins with `ML_DSA_44_DESIGNATION` and is exactly 1,315 bytes. Otherwise the transaction is invalid.
2. Add `sender` to `accessed_addresses` (as defined by [EIP-2929](/EIPs/EIPS/eip-2929)).
3. Extract `pubkey = sender.code[3..1315]`.
4. Verify `ML_DSA_44_Verify(pubkey, tx_hash, signature)` per FIPS 204[^1] Section 6 (Algorithm 3). The following strictness requirements apply:
   - All encodings MUST be canonical per FIPS 204. Non-canonical encodings of public keys or signatures MUST be rejected.
   - The signature vector `z` coefficients MUST satisfy the norm bound check as specified in FIPS 204. Implementations MUST NOT skip or relax this check.
   - The hint vector `h` MUST have exactly the number of ones indicated by the signature metadata; duplicate or out-of-order indices MUST be rejected.
   - Implementations MUST produce identical accept/reject decisions for every possible `(pubkey, message, signature)` triple. Implementors should validate against a shared test vector suite and should not rely on library defaults.
   If verification fails, the transaction is invalid.
5. Verify `nonce == sender.nonce`. Otherwise the transaction is invalid.
6. Proceed with standard transaction execution.

`ML_DSA_44_VERIFY_COST` is added to the transaction&apos;s intrinsic gas cost in native key mode, replacing the implicit ecrecover cost.

If `sender` is any other length, the transaction is invalid.

#### Authorization List Processing

The `native_key_authorization_list` is processed before transaction execution but after the sender&apos;s nonce is incremented, mirroring EIP-7702 semantics. The list MAY be empty.

For each ECDSA-signed tuple `[chain_id, pubkey, nonce, y_parity, r, s]`, in order:

1. Verify `chain_id` is `0` or equals the current chain ID. Otherwise skip.
2. Verify `pubkey` is exactly 1,312 bytes. Otherwise skip.
3. Verify `nonce &lt; 2^64 - 1`. Otherwise skip.
4. Verify `s &lt;= secp256k1n / 2`, as per [EIP-2](/EIPs/EIPS/eip-2). Otherwise skip.
5. Set `msg_hash = keccak256(NATIVE_KEY_MAGIC || rlp([chain_id, pubkey, nonce]))`.
6. Set `authority = ecrecover(msg_hash, y_parity, r, s)`. If recovery fails, skip.
7. Verify `authority`&apos;s code is empty or begins with `0xef0100`. Otherwise skip.
8. Verify `authority`&apos;s nonce equals `nonce`. Otherwise skip.
9. Add `authority` to `accessed_addresses` (as defined by [EIP-2929](/EIPs/EIPS/eip-2929)).
10. Increment `authority`&apos;s nonce by one.
11. Set `authority`&apos;s code to `ML_DSA_44_DESIGNATION || pubkey`.
12. Charge `PER_NATIVE_AUTH_BASE_COST` gas, plus `PER_EMPTY_ACCOUNT_COST` if the account was previously empty.

For each native-key-signed tuple `[chain_id, new_pubkey, nonce, authority, signature]`, in order:

1. Verify `chain_id` is `0` or equals the current chain ID. Otherwise skip.
2. Verify `new_pubkey` is exactly 1,312 bytes. Otherwise skip.
3. Verify `nonce &lt; 2^64 - 1`. Otherwise skip.
4. Verify `authority`&apos;s code begins with `ML_DSA_44_DESIGNATION` and is exactly 1,315 bytes. Otherwise skip.
5. Extract `current_pubkey = authority.code[3..1315]`.
6. Set `msg_hash = keccak256(NATIVE_KEY_MAGIC || rlp([chain_id, new_pubkey, nonce, authority]))`.
7. Verify `ML_DSA_44_Verify(current_pubkey, msg_hash, signature)` using the same verification constraints as Type `0x06` native key mode. If verification fails, skip.
8. Verify `authority`&apos;s nonce equals `nonce`. Otherwise skip.
9. Add `authority` to `accessed_addresses` (as defined by [EIP-2929](/EIPs/EIPS/eip-2929)).
10. Increment `authority`&apos;s nonce by one.
11. Set `authority`&apos;s code to `ML_DSA_44_DESIGNATION || new_pubkey`.
12. Charge `PER_NATIVE_AUTH_BASE_COST` gas.

If multiple tuples (of either type) target the same authority, the last valid tuple wins.

### ECDSA Rejection Rule

Once an account&apos;s code is set to `0xef0101 || pubkey`:

- ECDSA-signed transactions (Types 0x00–0x04, and Type 0x06 in ECDSA mode) whose recovered sender is a native-key account MUST be rejected during transaction validation.
- EIP-7702 authorization tuples whose recovered authority is a native-key account MUST be rejected.

The account is permanently governed by its embedded native key. The ECDSA private key — whether unknown, destroyed, or still held — has no protocol significance. Key rotation is accomplished via native-key-signed authorization tuples, not ECDSA.

### Keyless Account Creation (Crafted-Signature Method)

An account MAY be created where **no party has ever possessed the ECDSA private key**:

1. The creator generates an ML-DSA-44 keypair `(sk, pk)`.
2. The creator computes the authorization message for a fresh (nonce-0) account:

   ```
   msg_hash = keccak256(NATIVE_KEY_MAGIC || rlp([chain_id, pk, 0]))
   ```

3. The creator selects `r` as the x-coordinate of a secp256k1 curve point whose discrete logarithm is unknown (e.g., output of hash-to-curve on a public seed), and selects an arbitrary non-zero `s`.
4. The creator computes `authority = ecrecover(msg_hash, y_parity, r, s)`. This yields a deterministic address for which no party knows the private key.
5. Any party funds `authority` with ETH.
6. Any party submits a Type `0x06` transaction (ECDSA mode) containing the authorization tuple `[chain_id, pk, 0, y_parity, r, s]`.

The account at `authority` is now authenticated exclusively by the ML-DSA-44 key `pk`. Because deriving the ECDSA private key from the recovered public key requires solving the Elliptic Curve Discrete Logarithm Problem, the account is **provably rootless** — no ECDSA backdoor exists.

The `authority` address is deterministic given `(chain_id, pk, r, s, y_parity)`, enabling counterfactual address computation and pre-funding before the Type `0x06` transaction is submitted.

**Recommended construction for `r`:** Compute `r_seed = keccak256(&quot;nkd-v1&quot; || chain_id || pk)`, then find the smallest valid secp256k1 x-coordinate ≥ `r_seed mod p`. Set `s = 1`. This makes the derivation publicly verifiable: anyone can reproduce the computation and confirm that no trapdoor was used.

#### Transaction Origination

This EIP extends the [EIP-3607](/EIPs/EIPS/eip-3607) exception established by EIP-7702: accounts whose code begins with `0xef0101` MAY originate transactions (via Type `0x06` in ML-DSA-44 mode), in addition to accounts whose code begins with `0xef0100`.

### Key Rotation

A native-key account holder MAY rotate their native key by including a native-key-signed authorization tuple in a Type `0x06` transaction. The tuple `[chain_id, new_pubkey, nonce, authority, signature]` is signed by the currently installed native key and, when processed, replaces the account&apos;s code with `ML_DSA_44_DESIGNATION || new_pubkey`.

Key rotation does not require the original ECDSA key and works identically for ephemeral-key and crafted-signature (rootless) accounts. The rotation is atomic: it is applied during authorization list processing, before transaction execution.

Because the authorization tuple is included in a Type `0x06` transaction, the rotation may be submitted by any party — the native-key account holder need not be the transaction sender. This enables gas sponsorship for key rotation.

### Interaction with EIP-7702

| From | To | Permitted? |
|------|----|-----------|
| Empty / EOA | `0xef0101` (native key) | Yes, via Type `0x06` authorization list |
| `0xef0100` (code delegation) | `0xef0101` (native key) | Yes, via Type `0x06` authorization list (ECDSA-signed) |
| `0xef0101` (native key) | `0xef0100` (code delegation) | **No.** ECDSA signatures are permanently rejected. |
| `0xef0101` (native key) | `0xef0101` (new key) | Yes, via native-key-signed authorization tuple |

#### Code-Reading Operations

| Opcode | Behavior for `0xef0101` accounts |
|--------|----------------------------------|
| `EXTCODESIZE` (`0x3b`) | Returns `1315` |
| `EXTCODECOPY` (`0x3c`) | Copies from the 1,315-byte designator |
| `EXTCODEHASH` (`0x3f`) | Returns keccak256 of the 1,315-byte designator |
| `CODESIZE` (`0x38`) | Within the account&apos;s own context: `1315` |
| `CODECOPY` (`0x39`) | Within the account&apos;s own context: copies the designator |

#### Code-Execution Operations

`CALL` (`0xf1`), `CALLCODE` (`0xf2`), `DELEGATECALL` (`0xf4`), and `STATICCALL` (`0xfa`) targeting a native-key account execute no code. The account behaves as an EOA for execution purposes.

## Rationale

### Permanent Delegation

Native key delegation is permanent. Once an account&apos;s code is set to `0xef0101 || pubkey`, the ECDSA key is dead — the protocol will never accept it again. This is a deliberate and safe design choice for two reasons.

First, permanence is safe because the new key is the root key. The holder of the installed ML-DSA-44 private key can always rotate to a new key via a native-key-signed authorization tuple. There is no loss of authority: the account owner retains full, exclusive control through the current native key. Reverting to ECDSA would only re-introduce a weaker authentication scheme with no benefit.

Second, permanence eliminates the entire class of &quot;dormant key&quot; attacks. If the conversion were revocable, a leaked or quantum-broken ECDSA key could always hijack the account by reverting the delegation. Irreversibility means there is no second key to protect, no fallback to worry about, and no ambiguity about which key controls the account. For crafted-signature accounts this is a mathematical guarantee (the ECDSA key never existed). For ephemeral-key accounts it is a protocol-enforced guarantee independent of key destruction procedures.

The permanence also simplifies the security model: validators need only check the account&apos;s code prefix to determine the authentication scheme. There is no need to track historical key states or handle mixed-mode authentication.

### Embedded Keys vs. Contract Delegation

EIP-7702 delegates to code at an address. Native key delegation embeds the key directly in the account&apos;s code field. This is the correct design because:

1. **No code execution is involved.** The key authenticates transactions at the protocol level. There is no contract to delegate to.
2. **Self-contained verification.** Validators verify signatures without loading external code or crossing the EVM boundary.
3. **No delegation chain concerns.** EIP-7702 must handle chains of `ef0100` pointers. Native key accounts are terminal — no indirection.
4. **Minimal storage.** 1,315 bytes per account vs. a full contract deployment.

### Native-Key Accounts as Pure EOAs

Native-key accounts intentionally have no code execution capability. They cannot use EIP-7702 code delegation for batching, sponsorship, or privilege de-escalation. This is a deliberate scope constraint, not an oversight.

The purpose of this EIP is to replace the authentication primitive, not to replicate the full EIP-7702 feature set. Combining native key authentication with code delegation is a valid goal but introduces significant complexity: the account&apos;s code field would need to encode both a delegation target and an authentication key, and the interaction between the two must be carefully specified. A future EIP may define a combined designator (e.g., one that embeds both a pubkey and a delegation address) or allow `0xef0101` accounts to also carry `0xef0100` delegation. This EIP provides the authentication foundation that such extensions would build on.

### Post-Quantum Readiness

This EIP directly addresses the post-quantum threat by deploying ML-DSA-44, a NIST-standardized post-quantum signature scheme (FIPS 204[^1]), as the first native key scheme. Deploying post-quantum authentication before quantum computers threaten existing cryptography gives the ecosystem time to migrate accounts at its own pace rather than under emergency conditions.

The migration path is straightforward. A single Type `0x06` transaction (in ECDSA mode) atomically replaces an account&apos;s authentication scheme. Because the `0xef01XX` prefix space is extensible, future signature schemes slot directly into the same framework. The migration is one transaction, one block, one atomic state change — no intermediate contract deployments, no multi-step approval chains, and no window during which the account is authenticated by both the old and new key.

The crafted-signature path further strengthens this: new accounts can be created directly under ML-DSA-44, bypassing ECDSA entirely. The combination of in-place migration for existing accounts and native creation for new accounts provides a complete migration path without requiring a new account model or a hard fork beyond the initial activation of the relevant `0xef01XX` designator.

### Choice of ML-DSA-44

ML-DSA-44 (FIPS 204[^1]) was selected as the initial native key scheme for the following reasons:

1. **Post-quantum security.** ML-DSA-44 provides NIST Level 1 security (128-bit post-quantum), comparable to the ~128-bit classical security of secp256k1 ECDSA. Unlike Ed25519 or secp256r1, it is not vulnerable to quantum attacks.
2. **NIST standardization.** FIPS 204 is a finalized, published standard with an established ecosystem of implementations. This provides the normative stability required for a consensus-critical specification.
3. **Implementation maturity.** ML-DSA has the broadest library support of any post-quantum signature scheme, reducing the risk of consensus-critical implementation divergence across Ethereum clients.
4. **Reasonable size tradeoffs.** ML-DSA-44 public keys (1,312 bytes) and signatures (2,420 bytes) are larger than classical schemes but remain practical for on-chain use. Future schemes with better size profiles (e.g., FN-DSA under FIPS 206, when finalized) can be added via new `0xef01XX` designators without modifying this EIP.

secp256r1 (P-256) ECDSA was considered but rejected: it is not post-quantum, and its verification is already well served by existing precompile proposals. Ed25519 was considered but provides no quantum resistance, and the &quot;test the migration path with a non-PQ scheme first&quot; argument is weaker than deploying quantum resistance directly.

### Scheme-Specific Prefixes

Using distinct 3-byte prefixes per scheme (`0xef0101` for ML-DSA-44, `0xef0102` for a future scheme, etc.) rather than a generic prefix with a scheme byte:

1. **Fixed code sizes.** Each scheme has a known pubkey length. The code size is fixed and can be validated without parsing.
2. **Independent activation.** Each scheme is its own EIP. Consensus clients can support schemes incrementally.
3. **No version negotiation.** The prefix fully determines the verification algorithm.

### Single Transaction Type with Dual Authentication Mode

This EIP uses a single transaction type (`0x06`) for both setting native keys (ECDSA mode) and originating transactions from native-key accounts (ML-DSA-44 mode). The `sender` field acts as the discriminant: empty for ECDSA, 20 bytes for native key mode. This avoids consuming two [EIP-2718](/EIPs/EIPS/eip-2718) type numbers and enables a capability that two separate types could not: a native-key account can submit migration authorizations for other accounts in the same transaction it uses to send value or call contracts.

The `native_key_authorization_list` may be empty in either mode. In ECDSA mode, a transaction with an empty list is invalid (there is no reason to use Type `0x06` without authorizations or ML-DSA-44 signing). In ML-DSA-44 mode, an empty list is the common case — a native-key account simply sending a transaction.

ML-DSA-44 does not support public key recovery from signatures. The `sender` address must be stated explicitly in ML-DSA-44 mode. This is a departure from Ethereum&apos;s &quot;recover sender from signature&quot; convention, but provides a tangible benefit: transaction deserialization no longer requires an elliptic curve operation.

This EIP was initially specified as two transaction types, `0x5` to set native key delegations, and `0x6` to dispatch transactions from native key delegated accounts. Making a single tx type to serve both needs and all future extensions reduces protocol complexity footprint.

### Crafted-Signature Creation

The crafted-signature method is strictly stronger than the ephemeral-key method:

| Property | Ephemeral key | Crafted signature |
|----------|--------------|-------------------|
| ECDSA key ever existed in memory | Yes | No |
| Requires secure key destruction | Yes | No |
| Side-channel risk during signing | Yes | No |
| Verifiable by third parties | No | Yes (reproducible `r` derivation) |

The technique is battle-tested: Nick&apos;s method and [ERC-2470](/EIPs/EIPS/eip-2470) use identical cryptographic reasoning for keyless contract deployment.

### Omitted Features

This EIP deliberately omits [EIP-7702](/EIPs/EIPS/eip-7702) code delegation and [EIP-4844](/EIPs/EIPS/eip-4844) blob carrying for native-key accounts. Neither omission is fundamental. Code delegation could be added via a new delegation designator that embeds both a pubkey and a delegation target. Blob support could be added via a new transaction type that combines ML-DSA-44 authentication with blob fields. Both are deferred to keep this EIP focused on the authentication primitive.

## Backwards Compatibility

This EIP introduces new behavior gated behind a new transaction type and an explicit opt-in authorization. No existing accounts or transaction types are affected unless the account owner explicitly converts via a native key authorization.

1. **New delegation designator** (`0xef0101`). No conflict with `0xef0100` or pre-[EIP-3541](/EIPs/EIPS/eip-3541) contracts, which cannot have `0xef`-prefixed code.
2. **New transaction type** (`0x06`). Standard [EIP-2718](/EIPs/EIPS/eip-2718) typed transaction rollout. Unrecognized types are ignored by older clients.
3. **Extended [EIP-3607](/EIPs/EIPS/eip-3607) exception.** Transaction origination is now permitted for both `0xef0100` and `0xef0101` code prefixes.
4. **ECDSA rejection for converted accounts.** This is a new validation rule, but applies only to accounts that explicitly opted in. No existing account is affected without an explicit on-chain authorization.

## Test Cases

Pending.

## Security Considerations

### Post-Quantum Threat Model

The post-quantum threat to Ethereum accounts is not uniform. It depends on whether the account&apos;s authentication key is exposed on-chain:

Any account whose authentication key is quantum-vulnerable and exposed on-chain is vulnerable at rest to a quantum attacker who can recover the private key. This applies to ECDSA-signed transactions (which expose the secp256k1 public key) and EIP-7702 delegations (which can be overwritten by recovering the authorizing ECDSA key). Native-key accounts delegated to ML-DSA-44 are not vulnerable at rest or in flight, as ML-DSA-44 is a post-quantum scheme — neither the authorization signature nor the installed key is quantum-recoverable. Only accounts that have never exposed a public key on-chain (nonce-0 EOAs) and native-key accounts delegated to a post-quantum `0xef01XX` scheme are safe at rest.

### ECDSA Key Exposure Window (Ephemeral Key Path)

When creating an account via the ephemeral key path, the ECDSA private key exists in memory for the duration of the authorization signing. Implementors should prefer the crafted-signature path. When using ephemeral keys, implementors must generate and destroy the key in a secure, memory-safe context and must not persist the key to disk.

### ML-DSA-44 Implementation Correctness

The ML-DSA-44 verification algorithm is specified precisely in the Type `0x06` native key mode validation rules to prevent consensus-critical divergence between implementations. The specification requires canonical encoding of all values, strict norm bound checking for signature coefficients, and rejection of malformed hint vectors (including duplicate or out-of-order indices). This last requirement addresses a known malleability vector in ML-DSA implementations.

Consensus-critical divergence between ML-DSA-44 implementations is a chain-split risk. All implementations must produce identical accept/reject decisions for every possible (pubkey, message, signature) triple. Implementors should validate against a shared test vector suite and should not rely on library defaults, as different libraries may implement different strictness levels for encoding validation.

### Front-Running

Native key authorization tuples can be observed in the mempool and front-run. The impact is limited: the front-runner can cause the native key to be set earlier than intended, but the resulting account state is identical (the pubkey is embedded in the tuple). A front-runner cannot substitute a different key.

### Replay Protection

- **Cross-chain.** `chain_id` in both authorization tuples and type `0x06` transactions. Setting `chain_id = 0` in an authorization permits intentional multi-chain use.
- **Same-chain.** Nonce in both authorization tuples and transactions.

### Account Recovery

Native key delegation is irreversible by design. Loss of the ML-DSA-44 private key results in permanent loss of access to the account and all associated assets. This is the same failure mode as losing a secp256k1 key for a standard EOA.

Native-key accounts as specified in this EIP have no on-chain recovery path. Because they cannot execute code (no EIP-7702 delegation), smart-contract-based social recovery is not available. Users who require recovery guarantees should evaluate whether native key delegation is appropriate for their use case, or wait for a future EIP that combines native key authentication with code delegation.

### Cross-Chain Authorization Replay

Authorization tuples with `chain_id = 0` are valid on all EVM chains. For the crafted-signature creation path, this means an attacker who observes the authorization tuple can replay it on any chain, establishing the same account (same address, same native key) on chains the creator did not intend. The account state on those chains (pre-existing balance, nonce, or code) may differ from the creator&apos;s expectations.

Creators who do not intend multi-chain deployment should set `chain_id` to the target chain. Creators who intentionally use `chain_id = 0` for multi-chain deployment should be aware that any party can trigger the migration on any chain once the authorization tuple is public.

### Transaction Pool Considerations

Native-key accounts share the same transaction pool challenges as EIP-7702 delegated accounts: a key rotation could invalidate pending transactions. Clients should accept at most one pending Type `0x06` transaction per native-key account to minimize the number of transactions that can be invalidated by a single state change.

### Deterministic Keyless Addresses

The crafted-signature method produces addresses that depend on `(chain_id, pk, r, s, y_parity)`. Users should use the recommended deterministic `r` construction to ensure addresses are publicly reproducible. Non-deterministic `r` values are not unsafe but prevent third-party verification that the account is provably rootless.

[^1]:

  ```csl-json
  {
    &quot;type&quot;: &quot;standard&quot;,
    &quot;id&quot;: 1,
    &quot;author&quot;: [
      {
        &quot;literal&quot;: &quot;National Institute of Standards and Technology&quot;
      }
    ],
    &quot;title&quot;: &quot;Module-Lattice-Based Digital Signature Standard&quot;,
    &quot;DOI&quot;: &quot;10.6028/NIST.FIPS.204&quot;,
    &quot;URL&quot;: &quot;https://csrc.nist.gov/pubs/fips/204/final&quot;,
    &quot;original-date&quot;: {
      &quot;date-parts&quot;: [
        [2024, 8, 13]
      ]
    }
  }
  ```

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 17 Feb 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8164</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8164</guid>
      </item>
    
      <item>
        <title>Modular Dispatch Proxies</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8167-modular-dispatch-proxies/27781</comments>
        
        <description>## Abstract

This proposal standardizes dispatch proxies, which dispatch calls to logic modules, called delegates, according to function selector.
A modular proxy architecture facilitates upgrades, extensions, and hardening, while working around codesize limits.
This minimal standard interface allows tooling to discover the ABI of these proxies and examine their upgrade history.

## Motivation

Proxy contracts utilizing `delegatecall` are widely used for both code sharing and upgradeability.
Most common proxies forward calldata to a single implementation contract.
Sometimes the implementation address is hardcoded, a pattern used by cloning factories to reduce deployment costs, and sometimes the implementation address is mutable, a pattern used by upgradeable proxies.
However, monolithic proxy architectures can bump into codesize limits.
Additionally, replacing the implementation of an entire contract at once can be riskier than smaller, more incremental changes.

### Shared Logic Modules

Many contracts share common code for things like tokens but cannot share their entire implementation because of their own unique characteristics.
For example, two tokens might share their balance logic and transfer interface but differ in their name metadata and monetary policy.
With a monolithic architecture, these differences require two separate contracts.
With a logic module architecture, they can share a standardized token implementation but customize their metadata and monetary policy.

### Extension

Sometimes new standards arise that provide new functionality or guarantees.
For example, a popular token interface extension might arise to provide a new and better method for modifying allowances.
With a monolithic architecture, token implementations must be wrapped or wholly replaced to support the new method.
With logic modules, the interface could be extended with a new module to support the new method.

Modular designs are also appropriate for personal smart accounts such as [EIP-7702](/EIPs/EIPS/eip-7702) EOAs.
User accounts could install features such as DEX-specific callbacks without temporarily disabling other functionality.

### Upgrade

Monolithic proxy architectures require replacing the entire implementation during an upgrade.
Such upgrades batch changesets but introduce risk and are difficult to test and verify.
Modular dispatch proxies can still atomically batch upgrades, but their modular architecture allows incremental improvements and fixes without unintentionally breaking unrelated components.

### Hardening

Upgradeable dispatch proxies can be permanently hardened into immutable systems by uninstalling the upgrade methods.

### Standardization

A standard interface for the modular proxy architecture can help tools, user interfaces, and indexers determine the ABI of these proxies.
Such systems may also want to surface the full upgrade history of these proxies to facilitate investigation.

## Specification

A modular dispatch proxy MUST use `delegatecall` to relay the entire calldata to the delegate corresponding to the first four bytes of the calldata.

```solidity
interface IERC8167 {
    // RECOMMENDED
    // Emitted when assigning a delegate logic module to a selector
    // An address(0) delegate signals removal
    event SelectorDelegated(bytes4 indexed selector, address indexed delegate);

    // REQUIRED
    // Returns the delegate for the selector, using address(0) for function not found
    function implementation(bytes4 selector) external view returns (address);

    // REQUIRED
    // Surfaces the ABI
    // SHOULD return all function selectors with implementations
    function selectors() external view returns (bytes4[] memory);

    // RECOMMENDED
    // If the delegate for that selector is not set, the proxy SHOULD revert, and with FunctionNotFound.
    error FunctionNotFound(bytes4 selector);
}
```

`IERC8167` functions SHOULD be implemented by delegates rather than in the proxy.

A modular dispatch proxy constructor SHOULD configure at least one delegate.

## Rationale

### `bytes4 selector`

The most widely-supported ABI is Solidity&apos;s 4-byte ABI, which uses the first four bytes of calldata, called the selector, to dispatch functions.
The dispatch proxy also uses those same four bytes to dispatch function calls to their delegate.

### `implementation(bytes4)`

While implementations can be discovered with `eth_getStorageAt`, a common interface can support a variety of possible storage layouts and implementations.

This function&apos;s naming is consistent with monolithic proxies, but with a selector parameter.

### `selectors()`

This is a minimal function to surface ABI to tools.
While selectors are ambiguous, they can be resolved if their delegate has a verified ABI.
Together, these steps produce the ABI of the proxy:
1. For each `selector` in `selectors()`, query `implementation(selector)`.
2. For each unique implementation, check if its code is verified. If verified, retrieve the ABI. If not, allow the user to supply the missing ABI.
3. Identify the functions supported by the proxy by matching its selectors with their implementation&apos;s ABI.

Although selectors are also retrievable by querying `SelectorDelegated` events, the `selectors` function provides a way to get this information without access to the logs.
Log queries can be slow without a database index.

While a packed encoding would reduce memory allocation, an array of `bytes4` is the simplest for tooling to decode.
It is anticipated that this method will primarily be used by tooling.

### Upgrades

This standard does not specify an upgrade function.
Other standards could extend this one with versioning frameworks for atomic batch upgrades.

### Storage Layout

This standard does not specify a storage layout.
Other standards could suggest patterns to protect against storage collisions and other mistakes.

## Backwards Compatibility

This standard improves upon [ERC-2535](/EIPs/EIPS/eip-2535) in the following ways:

1. Removal of diamond jargon.
2. Fewer and simpler introspection functions.
3. Simpler upgrade event.

Existing upgradeable monolithic proxies can upgrade to this standard using the following upgrade plan:
1. Upgrade to an implementation with a method to populate the selector delegate mapping.
2. Populate the selector delegate mapping for all methods in the ABI plus the introspection functions.
3. Set the implementation to a dispatch proxy using the populated selector delegate mapping.

Existing modular proxies can upgrade to this standard by adding the introspection functions and optionally emitting a `SelectorDelegated` event for every installed function.

## Reference Implementation

The reference implementation contains three files.

- The [interface](/EIPs/assets/eip-8167/IERC8167.sol)
- A namespace-based [storage layout](/EIPs/assets/eip-8167/ProxyStorageBase.sol)
- A [proxy implementation](/EIPs/assets/eip-8167/Proxy.sol) with delegates for inspection and administration

## Security Considerations

### Access control

Upgrade functions should have some form of access control.
Access control designs are outside the scope of this standard.

### Avoid self-destruct

Delegates MUST NOT self-destruct.
If a delegate can self-destruct, it can break proxies that use it.

### Storage Layout

Proxy upgrades must take care not to shift storage indices because this corrupts contract data.

Delegates should be designed to minimize the risk of storage layout overlap between them.
There are two known approaches to protect storage layouts against such collisions.

The first is to define a single shared proxy storage layout in a common superclass inherited by all of the proxy&apos;s delegates.
Such subclasses SHOULD NOT declare additional storage.

The second is to use storage namespaces, such as [ERC-7201](/EIPs/EIPS/eip-7201) and [ERC-8042](/EIPs/EIPS/eip-8042).
This approach is appropriate for shared libraries.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Mon, 16 Feb 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8167</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8167</guid>
      </item>
    
      <item>
        <title>Composable Transaction</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8175-composable-transaction/27850</comments>
        
        <description>## Abstract

This EIP introduces a new [EIP-2718](/EIPs/EIPS/eip-2718) transaction type with [EIP-1559](/EIPs/EIPS/eip-1559) gas fields, typed `capabilities` (CALL and CREATE) that define the transaction&apos;s operations, a separate `signatures` list for authentication, a `fee_auth` field that executes account code to sponsor gas, and four new opcodes — `RETURNETH`, `SIG`, `SIGHASH`, and `TX_GAS_LIMIT` — for fee delegation and in-EVM transaction introspection.

## Motivation

Each Ethereum upgrade has introduced new transaction types for new capabilities: [EIP-1559](/EIPs/EIPS/eip-1559) for priority fees, [EIP-4844](/EIPs/EIPS/eip-4844) for blobs, and [EIP-7702](/EIPs/EIPS/eip-7702) for authorizations. Both [EIP-4844](/EIPs/EIPS/eip-4844) and [EIP-7702](/EIPs/EIPS/eip-7702) extend and reuse mostly the fields from [EIP-1559](/EIPs/EIPS/eip-1559), yet each required an entirely new transaction type. This leads to linear growth of transaction types with overlapping gas-payment semantics. This EIP proposes a single extensible transaction format where new features are added as typed capabilities without defining new transaction types.

Transaction sponsorship — where a third party pays gas on behalf of the sender — has been a long-sought feature. [EIP-8141](/EIPs/EIPS/eip-8141) proposes a solution using execution frames, new opcodes (`APPROVE`, `TXPARAM`), and per-frame gas budgets. This EIP achieves sponsorship with a simpler `fee_auth` field and four focused opcodes.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

### Parameters

| Parameter | Value |
| --- | --- |
| `COMPOSABLE_TX_TYPE` | `0x05` |
| `CAP_CALL` | `0x01` |
| `CAP_CREATE` | `0x02` |
| `SIG_SECP256K1` | `0x01` |
| `SIG_ED25519` | `0x02` |
| `ROLE_SENDER` | `0x00` |
| `ROLE_PAYER` | `0x01` |
| `RETURNETH_OPCODE` | `0xf6` |
| `SIG_OPCODE` | `0xf7` |
| `SIGHASH_OPCODE` | `0xf8` |
| `TX_GAS_LIMIT_OPCODE` | `0xf9` |
| `RETURNETH_GAS` | `2` |
| `SIG_BASE_GAS` | `2` |
| `SIGHASH_GAS` | `2` |
| `TX_GAS_LIMIT_GAS` | `2` |
| `PER_SIG_SECP256K1_GAS` | `3000` |
| `PER_SIG_ED25519_GAS` | `3000` |

### Composable transaction

A new [EIP-2718](/EIPs/EIPS/eip-2718) transaction is introduced where the `TransactionType` is `COMPOSABLE_TX_TYPE` and the `TransactionPayload` is the RLP serialization of:

```
rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas,
     gas_limit, fee_auth, capabilities, signatures])
```

The fields `chain_id`, `nonce`, `max_priority_fee_per_gas`, `max_fee_per_gas`, and `gas_limit` follow the same semantics as [EIP-1559](/EIPs/EIPS/eip-1559).

The `fee_auth` field is either empty (zero bytes) or a 20-byte address. When non-empty, it designates the account whose code is executed to provide ETH covering the transaction fee (see [Fee Delegation via fee_auth](#fee-delegation-via-fee_auth)).

The `capabilities` field is an RLP list of typed capabilities. Each capability is an RLP list whose first element is the capability type identifier. The transaction MUST contain at least one capability. See [Capability types](#capability-types) for the defined types. Future EIPs MAY define additional capability types for this transaction format.

The `signatures` field is an RLP list of typed signatures. Each signature authenticates the transaction using a per-role signing hash (see [Signing Hash](#signing-hash)). Every signature type MUST be known and every signature MUST be cryptographically valid.

The [EIP-2718](/EIPs/EIPS/eip-2718) `ReceiptPayload` for this transaction is `rlp([status, cumulative_transaction_gas_used, logs_bloom, logs])`.

### Capability types

#### CALL (`CAP_CALL` = `0x01`)

Executes a message call to an existing account.

Format: `[cap_type, to, value, data]`

| Field | Description |
| --- | --- |
| `cap_type` | `0x01` |
| `to` | 20-byte destination address |
| `value` | ETH value in wei to transfer |
| `data` | Calldata bytes |

#### CREATE (`CAP_CREATE` = `0x02`)

Creates a new contract.

Format: `[cap_type, value, data]`

| Field | Description |
| --- | --- |
| `cap_type` | `0x02` |
| `value` | ETH value in wei to endow the new contract |
| `data` | Initialization code (initcode) |

The contract address is derived as `keccak256(rlp([sender_address, nonce]))[12:]`, where `nonce` is the sender&apos;s nonce at the time the CREATE capability executes. The sender&apos;s nonce is incremented by 1 for each CREATE capability.

### Signatures

#### Signature schemes

**SECP256K1 (`SIG_SECP256K1` = `0x01`):**

Format: `[signature_type, role, y_parity, r, s]`

| Field | Size | Description |
| --- | --- | --- |
| `signature_type` | 1 byte | `0x01` |
| `role` | 1 byte | `ROLE_SENDER` or `ROLE_PAYER` |
| `y_parity` | 1 byte | Recovery ID (0 or 1) |
| `r` | 32 bytes | ECDSA `r` component |
| `s` | 32 bytes | ECDSA `s` component |

The `s` value MUST be less than or equal to `secp256k1n/2`, as specified in [EIP-2](/EIPs/EIPS/eip-2). The signer address is recovered via `ecrecover(sig_message, y_parity, r, s)`.

**ED25519 (`SIG_ED25519` = `0x02`):**

Format: `[signature_type, role, public_key, signature]`

| Field | Size | Description |
| --- | --- | --- |
| `signature_type` | 1 byte | `0x02` |
| `role` | 1 byte | `ROLE_SENDER` or `ROLE_PAYER` |
| `public_key` | 32 bytes | Ed25519 public key |
| `signature` | 64 bytes | Ed25519 signature (RFC 8032, pure Ed25519) |

The signer address is `keccak256(public_key)[12:]`. The signature MUST verify under RFC 8032 pure Ed25519.

### Signing hash

The signing hash binds both the transaction content and the signer&apos;s role, providing domain separation. It is computed in two steps:

```python
def compute_base_hash(tx: ComposableTx) -&gt; bytes:
    return keccak256(COMPOSABLE_TX_TYPE || rlp([
        tx.chain_id,
        tx.nonce,
        tx.max_priority_fee_per_gas,
        tx.max_fee_per_gas,
        tx.gas_limit,
        tx.fee_auth,
        tx.capabilities,
        []  # signatures array blinded
    ]))

def compute_sig_message(tx: ComposableTx, signature_type: int, role: int) -&gt; bytes:
    return keccak256(
        b&quot;\x19ComposableTxSig&quot; ||
        bytes1(signature_type) ||
        bytes1(role) ||
        compute_base_hash(tx)
    )
```

The `signatures` array is replaced with an empty list when computing `base_hash`. This allows all signers to sign independently and in any order. The `signature_type` and `role` are included in `sig_message` to prevent cross-scheme and cross-role signature confusion.

### Fee delegation via `fee_auth`

When `fee_auth` is non-empty, the account at `fee_auth` sponsors the transaction fee. Before the main transaction executes, the protocol invokes `fee_auth` as a prelude call:

| Context field | Value |
| --- | --- |
| `ADDRESS` | `fee_auth` |
| `CALLER` | sender (recovered from sender signature) |
| `ORIGIN` | sender |
| `CALLVALUE` | `0` |
| `CALLDATA` | empty |
| `GAS` | `gas_limit` minus intrinsic gas |

The `fee_auth` code MUST use `RETURNETH` to credit ETH into the transaction-scoped **fee escrow**. The amount credited MUST be at least `gas_limit * max_fee_per_gas` (the maximum possible fee). The `fee_auth` code MAY use `TX_GAS_LIMIT` and `GASPRICE` to compute this required amount on-chain. The `fee_auth` code MAY use `SIG` and `SIGHASH` to introspect signatures for authorization.

If `fee_auth` execution reverts, or the fee escrow is insufficient after `fee_auth` returns, the transaction is **invalid** and MUST NOT be included in a block.

After the main transaction completes, the actual fee is settled:

```python
actual_fee = gas_used * effective_gas_price
surplus = fee_escrow - actual_fee
# surplus is refunded to fee_auth address
```

When `fee_auth` is empty, gas is charged directly from the sender&apos;s balance, following standard [EIP-1559](/EIPs/EIPS/eip-1559) behavior.

State changes made during `fee_auth` execution persist regardless of whether the main transaction reverts. This allows sponsors to maintain their own accounting (e.g., nonces, rate limits) independently.

### New opcodes

#### `RETURNETH` (`0xf6`)

Returns ETH from the current execution context to the parent (calling) context.

| | |
| --- | --- |
| **Stack input** | `value` — amount in wei |
| **Stack output** | (none) |
| **Gas** | `RETURNETH_GAS` (2) |

Behavior:

- Debits `value` wei from the balance of `ADDRESS` (the currently executing account).
- Credits `value` wei to the parent calling context. If the parent context is a contract call, the ETH is credited to the caller&apos;s account balance. If the parent context is the protocol-level `fee_auth` prelude, the ETH is credited to the transaction-scoped fee escrow.
- If `ADDRESS` has insufficient balance, execution **reverts**.
- `RETURNETH` is valid in any execution context (not restricted to `fee_auth`), including descendant calls. When used in nested calls within `fee_auth`, the ETH propagates upward: each `RETURNETH` credits the immediate parent, and the top-level `fee_auth` frame&apos;s `RETURNETH` credits the fee escrow.
- `RETURNETH` is **invalid** in a `STATICCALL` context and causes an exceptional halt.
- If the enclosing call frame reverts, the `RETURNETH` credit is rolled back.

#### `SIG` (`0xf7`)

Loads a signature from the transaction&apos;s `signatures` array into memory.

| | |
| --- | --- |
| **Stack input** | `index`, `mem_start` |
| **Stack output** | `sig_type` |
| **Gas** | `SIG_BASE_GAS` (2) + memory expansion cost |

| Stack position | Value |
| --- | --- |
| `top - 0` | `index` — zero-based index into `signatures` |
| `top - 1` | `mem_start` — memory offset to write signature data |

Behavior:

- If `index &gt;= len(tx.signatures)`, execution **reverts**.
- Pushes the `signature_type` identifier onto the stack.
- Writes the signature body (excluding `signature_type`) to memory at `mem_start`:
  - `SIG_SECP256K1`: writes `role ‖ y_parity ‖ r ‖ s` (1 + 1 + 32 + 32 = 66 bytes).
  - `SIG_ED25519`: writes `role ‖ public_key ‖ signature` (1 + 32 + 64 = 97 bytes).
- Memory expansion cost is charged for the bytes written, following standard rules.

#### `SIGHASH` (`0xf8`)

Pushes the transaction base hash onto the stack.

| | |
| --- | --- |
| **Stack input** | (none) |
| **Stack output** | `hash` — 32-byte `base_hash` as defined in [Signing Hash](#signing-hash) |
| **Gas** | `SIGHASH_GAS` (2) |

Behavior:

- Pushes `compute_base_hash(tx)` onto the stack as a 256-bit value.
- The `fee_auth` code can reconstruct `sig_message` from `base_hash` + signature data obtained via `SIG`, then verify signatures using the `ecrecover` precompile or future Ed25519 precompiles.

#### `TX_GAS_LIMIT` (`0xf9`)

Returns the transaction&apos;s `gas_limit` field.

| | |
| --- | --- |
| **Stack input** | (none) |
| **Stack output** | `gas_limit` — the transaction&apos;s gas limit as a 256-bit value |
| **Gas** | `TX_GAS_LIMIT_GAS` (2) |

Behavior:

- Pushes the `gas_limit` field of the current transaction onto the stack.
- This opcode is available in all execution contexts, not only `fee_auth`.
- The returned value is the transaction&apos;s total gas limit as specified by the sender, distinct from `GAS` (remaining gas) and `GASLIMIT` (block gas limit).

### Execution order

The state transition for a Composable transaction proceeds as follows:

```python
def process_composable_tx(tx, block):
    # 1. Static validation
    validate_static_constraints(tx)

    # 2. Compute base hash
    base_hash = compute_base_hash(tx)

    # 3. Validate all signatures and recover addresses
    sender_address = None
    payer_address = None
    for sig in tx.signatures:
        sig_msg = compute_sig_message(tx, sig.signature_type, sig.role)
        addr = recover_address(sig, sig_msg)
        if sig.role == ROLE_SENDER:
            sender_address = addr
        elif sig.role == ROLE_PAYER:
            payer_address = addr

    # 4. Nonce check and increment
    assert state[sender_address].nonce == tx.nonce
    state[sender_address].nonce += 1

    # 5. Intrinsic gas
    intrinsic_gas = compute_intrinsic_gas(tx)
    assert tx.gas_limit &gt;= intrinsic_gas
    gas_remaining = tx.gas_limit - intrinsic_gas

    # 6. Fee handling
    fee_escrow = 0
    max_tx_cost = tx.gas_limit * tx.max_fee_per_gas

    if tx.fee_auth:
        # Execute fee_auth prelude
        fee_auth_result = evm_call(
            caller=sender_address,
            address=tx.fee_auth,
            value=0,
            data=b&apos;&apos;,
            gas=gas_remaining,
        )
        gas_remaining -= fee_auth_result.gas_used
        assert not fee_auth_result.reverted
        assert fee_escrow &gt;= max_tx_cost  # accumulated via RETURNETH
    else:
        # Standard: charge sender (or payer if present)
        charge_account = payer_address or sender_address
        assert state[charge_account].balance &gt;= max_tx_cost
        state[charge_account].balance -= max_tx_cost
        fee_escrow = max_tx_cost

    # 7. Execute capabilities sequentially
    for cap in tx.capabilities:
        if cap.cap_type == CAP_CALL:
            result = evm_call(
                caller=sender_address,
                address=cap.to,
                value=cap.value,
                data=cap.data,
                gas=gas_remaining,
            )
        elif cap.cap_type == CAP_CREATE:
            result = evm_create(
                caller=sender_address,
                value=cap.value,
                initcode=cap.data,
                gas=gas_remaining,
            )
        gas_remaining = result.gas_remaining
        if result.reverted:
            break
    gas_used = tx.gas_limit - gas_remaining

    # 8. Settle fees
    effective_gas_price = min(
        tx.max_fee_per_gas,
        tx.max_priority_fee_per_gas + block.base_fee_per_gas
    )
    actual_fee = gas_used * effective_gas_price
    surplus = fee_escrow - actual_fee
    block.coinbase.balance += gas_used * (effective_gas_price - block.base_fee_per_gas)
    # base fee portion is burned

    # Refund surplus
    if tx.fee_auth:
        state[tx.fee_auth].balance += surplus
    else:
        refund_account = payer_address or sender_address
        state[refund_account].balance += surplus
```

### Gas handling

The intrinsic gas cost is:

```python
def compute_intrinsic_gas(tx):
    gas = 21000  # base transaction cost
    for cap in tx.capabilities:
        gas += calldata_cost(cap.data)  # 16 per non-zero byte, 4 per zero byte
        if cap.cap_type == CAP_CREATE:
            gas += 32000  # contract creation cost
    gas += sum(
        PER_SIG_SECP256K1_GAS if s.signature_type == SIG_SECP256K1
        else PER_SIG_ED25519_GAS
        for s in tx.signatures
    )
    return gas
```

If `fee_auth` is non-empty, gas consumed by `fee_auth` execution is subtracted from `gas_limit` before capabilities execute.

## Rationale

### Linear growth of transaction types

Rather than defining a new transaction type per feature (blobs, authorizations, sponsorship), each potentially combined with each other, this EIP defines a single extensible format. New features are expressed as capabilities within the existing type.

### Separating signatures from capabilities

Placing signatures in their own array cleanly separates extension data from authentication. The `signatures` array is blinded during hash computation, so all signers produce their signature independently. This eliminates the ordered commitment chain of prior designs and simplifies multi-party signing flows.

### Domain-separated signing hash

The `sig_message` includes `signature_type` and `role` alongside the blinded transaction hash. This prevents a sender&apos;s signature from being reused as a payer&apos;s signature, even though both sign over the same `base_hash`. Without this, an attacker could reinterpret one role&apos;s signature as another&apos;s.

### `fee_auth` for fee delegation

The `fee_auth` field provides programmable fee delegation. The sponsor&apos;s code runs before the main transaction, uses `RETURNETH` to escrow the maximum fee, and can implement arbitrary authorization logic by introspecting signatures via `SIG` and `SIGHASH`. This is strictly more powerful than a static payer co-signature.

### Upfront maximum cost escrow

Requiring `fee_auth` to escrow `gas_limit * max_fee_per_gas` before main execution avoids the chicken-and-egg problem of paying for execution with the proceeds of that execution. Surplus is refunded to `fee_auth` after settlement, mirroring [EIP-1559](/EIPs/EIPS/eip-1559) reserve-and-refund discipline.

### `fee_auth` state persistence

State changes made during `fee_auth` execution persist even if the main transaction reverts. This allows sponsors to maintain internal accounting (nonces, rate limits, spend tracking) that must not be rolled back on user-transaction failure.

### `RETURNETH` opcode

`RETURNETH` provides a safe, explicit mechanism for code to return ETH to the parent calling context. When used within the `fee_auth` prelude, ETH propagates up to the protocol-managed fee escrow. When used in regular calls, ETH is credited to the caller&apos;s account balance. This general-purpose design avoids the need for `SELFDESTRUCT` or value-carrying calls back to a system address, and enables composable ETH flows beyond fee delegation.

### `SIG` and `SIGHASH` opcodes

These opcodes enable in-EVM signature introspection. The `fee_auth` code loads signatures via `SIG`, obtains the base hash via `SIGHASH`, reconstructs `sig_message`, and verifies signatures using `ecrecover`. This allows arbitrary sponsor authorization without off-chain coordination beyond collecting signatures.

### `TX_GAS_LIMIT` opcode

The `fee_auth` code must escrow exactly `gas_limit * max_fee_per_gas` wei via `RETURNETH`. While `max_fee_per_gas` is accessible through `GASPRICE`, no existing opcode exposes the transaction&apos;s `gas_limit` — `GAS` returns remaining gas (which decreases during execution) and `GASLIMIT` returns the block gas limit. `TX_GAS_LIMIT` fills this gap, enabling `fee_auth` contracts to compute the required escrow amount on-chain without relying on calldata or hardcoded values.

### CALL and CREATE as capabilities

Rather than embedding `to`, `value`, and `data` as top-level transaction fields, these are expressed as typed capabilities. This makes the transaction envelope a pure fee-paying and authentication container, while the actual operations — message calls and contract creation — are composable payload items. A transaction may contain multiple capabilities, enabling batched execution within a single transaction. Future capability types (e.g., blob data, authorization lists) extend the same list without modifying the envelope format.

## Backwards Compatibility

This EIP introduces a new transaction type and does not modify the behavior of existing transaction types. No backward compatibility issues are expected.

## Security Considerations

### Signature domain separation

The `sig_message` includes both `signature_type` and `role`, preventing cross-role and cross-scheme confusion. A SECP256K1 sender signature cannot be replayed as an ED25519 payer signature or vice versa.

### Payer replay protection

Every signature commits to the full transaction content including the sender&apos;s nonce. Since the sender&apos;s nonce is incremented on each transaction, signatures cannot be replayed across transactions.

### `fee_auth` execution safety

The `fee_auth` execution is bounded by `gas_limit` and runs before the main transaction. If `fee_auth` reverts or credits insufficient ETH, the transaction is invalid and produces no state changes. The upfront escrow requirement (`gas_limit * max_fee_per_gas`) ensures the protocol never under-collects fees.

### `fee_auth` griefing

A `fee_auth` contract could consume gas without crediting sufficient ETH, making the transaction invalid. Block builders can simulate `fee_auth` before inclusion to avoid wasting block space. Mempool nodes SHOULD simulate the `fee_auth` prelude before accepting the transaction.

### `RETURNETH` restrictions

`RETURNETH` credits ETH to the immediate parent calling context — either the caller&apos;s account balance or the protocol fee escrow at the top-level `fee_auth` frame. It cannot send ETH to arbitrary addresses. It is invalid in `STATICCALL` contexts. If the enclosing call reverts, the credit is rolled back, preventing double-spending.

### Transaction propagation

Composable transactions with `fee_auth` introduce validation complexity similar to [EIP-7702](/EIPs/EIPS/eip-7702) and [EIP-8141](/EIPs/EIPS/eip-8141). Nodes SHOULD keep at most one pending Composable transaction per sender in the public mempool. `fee_auth` simulation during mempool validation SHOULD be bounded in gas and restricted in state access patterns to limit DoS surface.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).</description>
        <pubDate>Thu, 26 Feb 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8175</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8175</guid>
      </item>
    
      <item>
        <title>Binary SSZ Transport for the Engine API</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8178-ssz-rest-engine-api-transport/27891</comments>
        
        <description>## Abstract

This EIP specifies a binary SSZ transport for Engine API communication between consensus layer (CL) and execution layer (EL) clients. The binary transport replaces JSON-RPC with resource-oriented REST endpoints and raw SSZ encoding for fast, efficient CL-EL communication. SSZ container definitions are provided for all Engine API structures and methods across all forks for backwards compatibility.

## Motivation

Fast communication between the consensus layer and execution layer is critical for block propagation and validation timing. The JSON-RPC transport introduces unnecessary overhead in this critical path:

- Binary data (hashes, addresses, transactions, blobs) is hex-encoded, doubling wire size.
- JSON parsing and generation adds CPU overhead on both sides.
- The CL uses SSZ natively, forcing a round-trip conversion (SSZ → JSON, then JSON → internal types) at the Engine API boundary.

Binary SSZ eliminates all of this. The CL sends raw SSZ bytes over HTTP; the EL deserializes directly. No hex encoding, no JSON parsing, no intermediate representations. Payload sizes are reduced by ~50% compared to JSON-RPC, and serialization is no longer a bottleneck in the critical path between CL and EL.

## Specification

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

### Transport

The binary SSZ transport uses resource-oriented REST over HTTP. Endpoints are organized by resource type (payloads, forkchoice, blobs) with per-endpoint versioning, following the same conventions as the Beacon API.

#### Base URL

All endpoints are served under the `/engine` prefix on the existing Engine API port (default `8551`):

```
http://localhost:8551/engine
```

#### Content Types

| Header | Value | Description |
| - | - | - |
| `Content-Type` (request) | `application/octet-stream` | SSZ-encoded request container |
| `Content-Type` (response) | `application/octet-stream` | SSZ-encoded response (success) |
| `Content-Type` (response) | `text/plain` | Human-readable error message |
| `Accept` (request) | `application/octet-stream` | Client accepts SSZ-encoded responses |

Request bodies are the SSZ serialization of the endpoint&apos;s request container. Response bodies are the SSZ serialization of the endpoint&apos;s response type. GET requests with no body **SHOULD** include the `Accept` header to indicate SSZ preference.

#### Authentication

The binary transport uses the same JWT authentication as the JSON-RPC endpoint. All requests **MUST** include a valid JWT bearer token in the `Authorization` header:

```
Authorization: Bearer &lt;JWT token&gt;
```

All existing authentication requirements from the Engine API specification apply.

#### Versioning

Endpoints use path-based versioning following Beacon API conventions. Each endpoint includes a version number in its path (e.g., `/engine/v5/payloads`). The version number corresponds to the JSON-RPC method version it replaces:

| SSZ REST Endpoint | JSON-RPC Equivalent |
| - | - |
| `POST /engine/v5/payloads` | `engine_newPayloadV5` |
| `GET /engine/v6/payloads/{payload_id}` | `engine_getPayloadV6` |
| `POST /engine/v4/forkchoice` | `engine_forkchoiceUpdatedV4` |
| `POST /engine/v3/blobs` | `engine_getBlobsV3` |

When a new fork introduces a new method version, a new versioned endpoint is added. Older versioned endpoints **MAY** be deprecated but **SHOULD** remain available for backwards compatibility.

### HTTP Status Codes

#### Success

| Status | Meaning | Usage |
| - | - | - |
| `200` | OK | Request succeeded, response body contains SSZ-encoded result |
| `204` | No Content | Null result (e.g., syncing), empty body |

#### Client Errors

| Status | Meaning | Usage |
| - | - | - |
| `400` | Bad Request | Malformed SSZ encoding |
| `401` | Unauthorized | Missing or invalid JWT token |
| `404` | Not Found | Unknown payload ID |
| `409` | Conflict | Invalid forkchoice state |
| `413` | Request Too Large | Request exceeds maximum element count |
| `422` | Unprocessable Entity | Invalid payload attributes |

#### Server Errors

| Status | Meaning | Usage |
| - | - | - |
| `500` | Internal Server Error | Unexpected server error |

Error responses use `Content-Type: text/plain` with a human-readable error message body.

### Constants

| Name | Value | Source |
| - | - | - |
| `MAX_BYTES_PER_TRANSACTION` | `2**30` (1,073,741,824) | [EIP-4844](/EIPs/EIPS/eip-4844) |
| `MAX_TRANSACTIONS_PER_PAYLOAD` | `2**20` (1,048,576) | Bellatrix |
| `MAX_WITHDRAWALS_PER_PAYLOAD` | `2**4` (16) | Capella |
| `BYTES_PER_LOGS_BLOOM` | `256` | Bellatrix |
| `MAX_EXTRA_DATA_BYTES` | `2**5` (32) | Bellatrix |
| `MAX_BLOB_COMMITMENTS_PER_BLOCK` | `2**12` (4,096) | Deneb |
| `FIELD_ELEMENTS_PER_BLOB` | `4096` | [EIP-4844](/EIPs/EIPS/eip-4844) |
| `BYTES_PER_FIELD_ELEMENT` | `32` | [EIP-4844](/EIPs/EIPS/eip-4844) |
| `CELLS_PER_EXT_BLOB` | `128` | [EIP-7594](/EIPs/EIPS/eip-7594) |
| `MAX_PAYLOAD_BODIES_REQUEST` | `2**5` (32) | Shanghai |
| `MAX_BLOB_HASHES_REQUEST` | `128` | Osaka |
| `MAX_EXECUTION_REQUESTS` | `2**8` (256) | [EIP-7685](/EIPs/EIPS/eip-7685) |
| `MAX_ERROR_MESSAGE_LENGTH` | `1024` | This specification |
| `MAX_CLIENT_CODE_LENGTH` | `2` | This specification |
| `MAX_CLIENT_NAME_LENGTH` | `64` | This specification |
| `MAX_CLIENT_VERSION_LENGTH` | `64` | This specification |
| `MAX_CLIENT_VERSIONS` | `4` | This specification |
| `BLOB_SIZE` | `FIELD_ELEMENTS_PER_BLOB * BYTES_PER_FIELD_ELEMENT` (131,072) | Derived |

### SSZ Type Mappings

Each JSON-encoded base type used in the Engine API maps to a specific SSZ type:

| JSON-RPC Type | SSZ Type |
| - | - |
| `address` (20 bytes) | `Bytes20` |
| `hash32` (32 bytes) | `Bytes32` |
| `bytes8` (8 bytes) | `Bytes8` |
| `bytes32` (32 bytes) | `Bytes32` |
| `bytes48` (48 bytes) | `Bytes48` |
| `bytes256` (256 bytes) | `ByteVector[256]` |
| `uint64` | `uint64` |
| `uint256` | `uint256` |
| `BOOLEAN` | `boolean` |
| `bytes` (variable-length) | `ByteList[MAX_LENGTH]` (context-dependent) |
| `bytesMax32` (0 to 32 bytes) | `ByteList[32]` |
| `Array of T` | `List[T, MAX_LENGTH]` (context-dependent) |
| `T or null` | `List[T, 1]` |

Nullable types are represented as `List[T, 1]` in SSZ encoding. An empty list (0 elements) denotes absence (`null`). A list with one element denotes presence.

### Container Definitions

#### WithdrawalV1

```python
class WithdrawalV1(Container):
    index: uint64
    validator_index: uint64
    address: Bytes20
    amount: uint64
```

#### ExecutionPayloadV1

```python
class ExecutionPayloadV1(Container):
    parent_hash: Bytes32
    fee_recipient: Bytes20
    state_root: Bytes32
    receipts_root: Bytes32
    logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM]
    prev_randao: Bytes32
    block_number: uint64
    gas_limit: uint64
    gas_used: uint64
    timestamp: uint64
    extra_data: ByteList[MAX_EXTRA_DATA_BYTES]
    base_fee_per_gas: uint256
    block_hash: Bytes32
    transactions: List[ByteList[MAX_BYTES_PER_TRANSACTION], MAX_TRANSACTIONS_PER_PAYLOAD]
```

#### ExecutionPayloadV2

Extends `ExecutionPayloadV1` with `withdrawals`.

```python
class ExecutionPayloadV2(Container):
    parent_hash: Bytes32
    fee_recipient: Bytes20
    state_root: Bytes32
    receipts_root: Bytes32
    logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM]
    prev_randao: Bytes32
    block_number: uint64
    gas_limit: uint64
    gas_used: uint64
    timestamp: uint64
    extra_data: ByteList[MAX_EXTRA_DATA_BYTES]
    base_fee_per_gas: uint256
    block_hash: Bytes32
    transactions: List[ByteList[MAX_BYTES_PER_TRANSACTION], MAX_TRANSACTIONS_PER_PAYLOAD]
    withdrawals: List[WithdrawalV1, MAX_WITHDRAWALS_PER_PAYLOAD]
```

#### ExecutionPayloadV3

Extends `ExecutionPayloadV2` with `blob_gas_used` and `excess_blob_gas`.

```python
class ExecutionPayloadV3(Container):
    parent_hash: Bytes32
    fee_recipient: Bytes20
    state_root: Bytes32
    receipts_root: Bytes32
    logs_bloom: ByteVector[BYTES_PER_LOGS_BLOOM]
    prev_randao: Bytes32
    block_number: uint64
    gas_limit: uint64
    gas_used: uint64
    timestamp: uint64
    extra_data: ByteList[MAX_EXTRA_DATA_BYTES]
    base_fee_per_gas: uint256
    block_hash: Bytes32
    transactions: List[ByteList[MAX_BYTES_PER_TRANSACTION], MAX_TRANSACTIONS_PER_PAYLOAD]
    withdrawals: List[WithdrawalV1, MAX_WITHDRAWALS_PER_PAYLOAD]
    blob_gas_used: uint64
    excess_blob_gas: uint64
```

#### PayloadStatusV1

The `status` field is encoded as a `uint8` enum.

```python
class PayloadStatusV1(Container):
    status: uint8
    latest_valid_hash: Bytes32
    validation_error: ByteList[MAX_ERROR_MESSAGE_LENGTH]
```

*Note:* `latest_valid_hash` is all zeros when absent (e.g. when `status` is `SYNCING` or `ACCEPTED`). `validation_error` is empty when absent.

| `status` value | Meaning |
| - | - |
| `0` | VALID |
| `1` | INVALID |
| `2` | SYNCING |
| `3` | ACCEPTED |
| `4` | INVALID_BLOCK_HASH |

#### ForkchoiceStateV1

```python
class ForkchoiceStateV1(Container):
    head_block_hash: Bytes32
    safe_block_hash: Bytes32
    finalized_block_hash: Bytes32
```

#### PayloadAttributesV1

```python
class PayloadAttributesV1(Container):
    timestamp: uint64
    prev_randao: Bytes32
    suggested_fee_recipient: Bytes20
```

#### PayloadAttributesV2

Extends `PayloadAttributesV1` with `withdrawals`.

```python
class PayloadAttributesV2(Container):
    timestamp: uint64
    prev_randao: Bytes32
    suggested_fee_recipient: Bytes20
    withdrawals: List[WithdrawalV1, MAX_WITHDRAWALS_PER_PAYLOAD]
```

#### PayloadAttributesV3

Extends `PayloadAttributesV2` with `parent_beacon_block_root`.

```python
class PayloadAttributesV3(Container):
    timestamp: uint64
    prev_randao: Bytes32
    suggested_fee_recipient: Bytes20
    withdrawals: List[WithdrawalV1, MAX_WITHDRAWALS_PER_PAYLOAD]
    parent_beacon_block_root: Bytes32
```

#### ForkchoiceUpdatedResponseV1

Used by all versions of `engine_forkchoiceUpdated`.

```python
class ForkchoiceUpdatedResponseV1(Container):
    payload_status: PayloadStatusV1
    payload_id: Bytes8
```

*Note:* `payload_id` is all zeros when no payload building was initiated.

#### ExecutionPayloadBodyV1

```python
class ExecutionPayloadBodyV1(Container):
    transactions: List[ByteList[MAX_BYTES_PER_TRANSACTION], MAX_TRANSACTIONS_PER_PAYLOAD]
    withdrawals: List[WithdrawalV1, MAX_WITHDRAWALS_PER_PAYLOAD]
```

*Note:* `withdrawals` is empty for pre-Shanghai blocks.

#### BlobsBundleV1

```python
class BlobsBundleV1(Container):
    commitments: List[Bytes48, MAX_BLOB_COMMITMENTS_PER_BLOCK]
    proofs: List[Bytes48, MAX_BLOB_COMMITMENTS_PER_BLOCK]
    blobs: List[ByteVector[BLOB_SIZE], MAX_BLOB_COMMITMENTS_PER_BLOCK]
```

#### BlobsBundleV2

Proofs are cell proofs with `CELLS_PER_EXT_BLOB` proofs per blob.

```python
class BlobsBundleV2(Container):
    commitments: List[Bytes48, MAX_BLOB_COMMITMENTS_PER_BLOCK]
    proofs: List[Bytes48, MAX_BLOB_COMMITMENTS_PER_BLOCK * CELLS_PER_EXT_BLOB]
    blobs: List[ByteVector[BLOB_SIZE], MAX_BLOB_COMMITMENTS_PER_BLOCK]
```

#### BlobAndProofV1

```python
class BlobAndProofV1(Container):
    blob: ByteVector[BLOB_SIZE]
    proof: Bytes48
```

#### BlobAndProofV2

```python
class BlobAndProofV2(Container):
    blob: ByteVector[BLOB_SIZE]
    proofs: List[Bytes48, CELLS_PER_EXT_BLOB]
```

#### TransitionConfigurationV1

Deprecated in Cancun.

```python
class TransitionConfigurationV1(Container):
    terminal_total_difficulty: uint256
    terminal_block_hash: Bytes32
    terminal_block_number: uint64
```

#### GetPayloadResponseV2

```python
class GetPayloadResponseV2(Container):
    execution_payload: ExecutionPayloadV2
    block_value: uint256
```

*Note:* Pre-Shanghai payloads have an empty `withdrawals` list.

#### GetPayloadResponseV3

```python
class GetPayloadResponseV3(Container):
    execution_payload: ExecutionPayloadV3
    block_value: uint256
    blobs_bundle: BlobsBundleV1
    should_override_builder: boolean
```

#### GetPayloadResponseV4

```python
class GetPayloadResponseV4(Container):
    execution_payload: ExecutionPayloadV3
    block_value: uint256
    blobs_bundle: BlobsBundleV1
    should_override_builder: boolean
    execution_requests: List[ByteList[MAX_BYTES_PER_TRANSACTION], MAX_EXECUTION_REQUESTS]
```

#### GetPayloadResponseV5

```python
class GetPayloadResponseV5(Container):
    execution_payload: ExecutionPayloadV3
    block_value: uint256
    blobs_bundle: BlobsBundleV2
    should_override_builder: boolean
    execution_requests: List[ByteList[MAX_BYTES_PER_TRANSACTION], MAX_EXECUTION_REQUESTS]
```

#### PayloadBodiesV1Response

```python
class PayloadBodiesV1Response(Container):
    payload_bodies: List[List[ExecutionPayloadBodyV1, 1], MAX_PAYLOAD_BODIES_REQUEST]
```

*Note:* Each inner list has 0 elements for unknown blocks and 1 element for known blocks.

#### GetBlobsV1Response

```python
class GetBlobsV1Response(Container):
    blobs_and_proofs: List[BlobAndProofV1, MAX_BLOB_HASHES_REQUEST]
```

#### GetBlobsV2Response

```python
class GetBlobsV2Response(Container):
    blobs_and_proofs: List[BlobAndProofV2, MAX_BLOB_HASHES_REQUEST]
```

#### GetBlobsV3Response

```python
class GetBlobsV3Response(Container):
    blobs_and_proofs: List[List[BlobAndProofV2, 1], MAX_BLOB_HASHES_REQUEST]
```

*Note:* Each inner list has 0 elements for a missing blob and 1 element for a present blob.

#### ClientVersionV1

```python
class ClientVersionV1(Container):
    code: ByteList[MAX_CLIENT_CODE_LENGTH]
    name: ByteList[MAX_CLIENT_NAME_LENGTH]
    version: ByteList[MAX_CLIENT_VERSION_LENGTH]
    commit: Bytes4
```

#### GetClientVersionV1Response

```python
class GetClientVersionV1Response(Container):
    versions: List[ClientVersionV1, MAX_CLIENT_VERSIONS]
```

### Endpoints

All endpoints use `Content-Type: application/octet-stream` for request and response bodies containing SSZ-encoded data. Error responses use `Content-Type: text/plain`.

#### Payloads

##### `POST /engine/v{N}/payloads` — Submit execution payload

Submit an execution payload for validation. The EL validates the payload and returns its status.

| Version | Fork | Request Container | JSON-RPC Equivalent |
| - | - | - | - |
| v1 | Paris | `NewPayloadV1Request` | `engine_newPayloadV1` |
| v2 | Shanghai | `NewPayloadV2Request` | `engine_newPayloadV2` |
| v3 | Cancun | `NewPayloadV3Request` | `engine_newPayloadV3` |
| v4 | Prague | `NewPayloadV4Request` | `engine_newPayloadV4` |

**Request containers:**

```python
class NewPayloadV1Request(Container):
    execution_payload: ExecutionPayloadV1

class NewPayloadV2Request(Container):
    execution_payload: ExecutionPayloadV2

class NewPayloadV3Request(Container):
    execution_payload: ExecutionPayloadV3
    expected_blob_versioned_hashes: List[Bytes32, MAX_BLOB_COMMITMENTS_PER_BLOCK]
    parent_beacon_block_root: Bytes32

class NewPayloadV4Request(Container):
    execution_payload: ExecutionPayloadV3
    expected_blob_versioned_hashes: List[Bytes32, MAX_BLOB_COMMITMENTS_PER_BLOCK]
    parent_beacon_block_root: Bytes32
    execution_requests: List[ByteList[MAX_BYTES_PER_TRANSACTION], MAX_EXECUTION_REQUESTS]
```

**Response:** `200 OK` — `PayloadStatusV1`

---

##### `GET /engine/v{N}/payloads/{payload_id}` — Retrieve built payload

Retrieve an execution payload previously requested via forkchoice update with payload attributes. The `{payload_id}` path parameter is the hex-encoded `Bytes8` payload identifier (e.g., `0x1234567890abcdef`).

| Version | Fork | Response Type | JSON-RPC Equivalent |
| - | - | - | - |
| v1 | Paris | `ExecutionPayloadV1` | `engine_getPayloadV1` |
| v2 | Shanghai | `GetPayloadResponseV2` | `engine_getPayloadV2` |
| v3 | Cancun | `GetPayloadResponseV3` | `engine_getPayloadV3` |
| v4 | Prague | `GetPayloadResponseV4` | `engine_getPayloadV4` |
| v5 | Osaka | `GetPayloadResponseV5` | `engine_getPayloadV5` |

**Request:** No body. The payload ID is in the URL path.

**Response:** `200 OK` — SSZ-encoded response type from the table above.

---

##### `POST /engine/v{N}/payloads/bodies/by-hash` — Get payload bodies by hash

Retrieve execution payload bodies for a list of block hashes.

| Version | Fork | Response Type | JSON-RPC Equivalent |
| - | - | - | - |
| v1 | Shanghai | `PayloadBodiesV1Response` | `engine_getPayloadBodiesByHashV1` |

**Request container:**

```python
class GetPayloadBodiesByHashRequest(Container):
    block_hashes: List[Bytes32, MAX_PAYLOAD_BODIES_REQUEST]
```

**Response:** `200 OK` — `PayloadBodiesV1Response`

---

##### `POST /engine/v{N}/payloads/bodies/by-range` — Get payload bodies by range

Retrieve execution payload bodies for a contiguous range of block numbers.

| Version | Fork | Response Type | JSON-RPC Equivalent |
| - | - | - | - |
| v1 | Shanghai | `PayloadBodiesV1Response` | `engine_getPayloadBodiesByRangeV1` |

**Request container:**

```python
class GetPayloadBodiesByRangeRequest(Container):
    start: uint64
    count: uint64
```

**Response:** `200 OK` — `PayloadBodiesV1Response`

#### Forkchoice

##### `POST /engine/v{N}/forkchoice` — Update fork choice

Update the EL&apos;s fork choice state and optionally start building a new payload.

| Version | Fork | Request Container | JSON-RPC Equivalent |
| - | - | - | - |
| v1 | Paris | `ForkchoiceUpdatedV1Request` | `engine_forkchoiceUpdatedV1` |
| v2 | Shanghai | `ForkchoiceUpdatedV2Request` | `engine_forkchoiceUpdatedV2` |
| v3 | Cancun | `ForkchoiceUpdatedV3Request` | `engine_forkchoiceUpdatedV3` |

**Request containers:**

```python
class ForkchoiceUpdatedV1Request(Container):
    forkchoice_state: ForkchoiceStateV1
    payload_attributes: List[PayloadAttributesV1, 1]

class ForkchoiceUpdatedV2Request(Container):
    forkchoice_state: ForkchoiceStateV1
    payload_attributes: List[PayloadAttributesV2, 1]

class ForkchoiceUpdatedV3Request(Container):
    forkchoice_state: ForkchoiceStateV1
    payload_attributes: List[PayloadAttributesV3, 1]
```

**Response:** `200 OK` — `ForkchoiceUpdatedResponseV1`

#### Blobs

##### `POST /engine/v{N}/blobs` — Get blobs by versioned hash

Retrieve blobs from the EL&apos;s blob pool by their versioned hashes.

| Version | Fork | Response Type | JSON-RPC Equivalent |
| - | - | - | - |
| v1 | Cancun | `GetBlobsV1Response` | `engine_getBlobsV1` |
| v2 | Osaka | `GetBlobsV2Response` | `engine_getBlobsV2` |
| v3 | Osaka | `GetBlobsV3Response` | `engine_getBlobsV3` |

**Request container:**

```python
class GetBlobsRequest(Container):
    blob_versioned_hashes: List[Bytes32, MAX_BLOB_HASHES_REQUEST]
```

**Response:** `200 OK` — SSZ-encoded response type from the table above, or `204 No Content` when the EL is syncing.

#### Client

##### `POST /engine/v1/client/version` — Exchange client version

Exchange client version information between CL and EL.

**Request container:**

```python
class GetClientVersionV1Request(Container):
    client_version: ClientVersionV1
```

**Response:** `200 OK` — `GetClientVersionV1Response`

#### Endpoint Summary

| HTTP Method | Path | Fork | JSON-RPC Equivalent |
| - | - | - | - |
| `POST` | `/engine/v1/payloads` | Paris | `engine_newPayloadV1` |
| `POST` | `/engine/v2/payloads` | Shanghai | `engine_newPayloadV2` |
| `POST` | `/engine/v3/payloads` | Cancun | `engine_newPayloadV3` |
| `POST` | `/engine/v4/payloads` | Prague | `engine_newPayloadV4` |
| `GET` | `/engine/v1/payloads/{payload_id}` | Paris | `engine_getPayloadV1` |
| `GET` | `/engine/v2/payloads/{payload_id}` | Shanghai | `engine_getPayloadV2` |
| `GET` | `/engine/v3/payloads/{payload_id}` | Cancun | `engine_getPayloadV3` |
| `GET` | `/engine/v4/payloads/{payload_id}` | Prague | `engine_getPayloadV4` |
| `GET` | `/engine/v5/payloads/{payload_id}` | Osaka | `engine_getPayloadV5` |
| `POST` | `/engine/v1/payloads/bodies/by-hash` | Shanghai | `engine_getPayloadBodiesByHashV1` |
| `POST` | `/engine/v1/payloads/bodies/by-range` | Shanghai | `engine_getPayloadBodiesByRangeV1` |
| `POST` | `/engine/v1/forkchoice` | Paris | `engine_forkchoiceUpdatedV1` |
| `POST` | `/engine/v2/forkchoice` | Shanghai | `engine_forkchoiceUpdatedV2` |
| `POST` | `/engine/v3/forkchoice` | Cancun | `engine_forkchoiceUpdatedV3` |
| `POST` | `/engine/v1/blobs` | Cancun | `engine_getBlobsV1` |
| `POST` | `/engine/v2/blobs` | Osaka | `engine_getBlobsV2` |
| `POST` | `/engine/v3/blobs` | Osaka | `engine_getBlobsV3` |
| `POST` | `/engine/v1/client/version` | All | `engine_getClientVersionV1` |

### Example

#### Submit payload

```bash
curl -X POST http://localhost:8551/engine/v4/payloads \
  -H &quot;Authorization: Bearer $JWT_TOKEN&quot; \
  -H &quot;Content-Type: application/octet-stream&quot; \
  -H &quot;Accept: application/octet-stream&quot; \
  --data-binary @new_payload_request.ssz \
  -o payload_status.ssz
```

#### Retrieve built payload

```bash
curl -X GET http://localhost:8551/engine/v4/payloads/0x1234567890abcdef \
  -H &quot;Authorization: Bearer $JWT_TOKEN&quot; \
  -H &quot;Accept: application/octet-stream&quot; \
  -o get_payload_response.ssz
```

#### Update fork choice

```bash
curl -X POST http://localhost:8551/engine/v3/forkchoice \
  -H &quot;Authorization: Bearer $JWT_TOKEN&quot; \
  -H &quot;Content-Type: application/octet-stream&quot; \
  --data-binary @forkchoice_request.ssz \
  -o forkchoice_response.ssz
```

## Rationale

### Why REST instead of raw SSZ over TCP?

REST is well understood, easy to debug, and infrastructure already exists for it (load balancers, proxies, monitoring). The Beacon API already uses REST with SSZ and it works well. Going lower level (raw TCP, custom framing) adds complexity without a clear benefit for the EL-CL link, which is typically localhost communication.

### Why same port instead of a separate port?

Serving both JSON-RPC and SSZ REST on the same port simplifies deployment and configuration. There&apos;s no need for operators to manage an additional port, firewall rule, or JWT secret. The two transports coexist cleanly — JSON-RPC uses `POST /` with `Content-Type: application/json`, while SSZ REST uses resource-oriented paths with `Content-Type: application/octet-stream`.

### Why `application/octet-stream`?

This is the standard content type for binary data. The Beacon API already uses it for SSZ responses. It signals that the body is raw bytes, not text, which is exactly what SSZ is.

### Why `text/plain` for errors instead of JSON?

Errors are small, infrequent, and need to be human-readable for debugging. A plain text message body is the simplest possible approach — no parsing needed, just log it. JSON error bodies add complexity for minimal gain.

### No hard fork required

This is purely a client-side change. It&apos;s a new transport option for an existing API — no consensus changes, no state transition changes, no new opcodes. Clients can implement it whenever they want and roll it out with a regular release.

## Backwards Compatibility

This EIP introduces a new transport protocol alongside the existing JSON-RPC Engine API. The JSON-RPC API remains fully functional and is always available. Clients that don&apos;t implement binary SSZ are unaffected.

## Security Considerations

- The SSZ REST transport uses the same JWT authentication as the JSON-RPC endpoint. All existing authentication requirements apply.
- SSZ deserialization **MUST** enforce the same size limits as JSON deserialization. Implementations **MUST** reject SSZ payloads exceeding defined maximum sizes before attempting full deserialization.
- Implementations **SHOULD** use well-tested SSZ libraries and fuzz test SSZ parsing extensively.
- The `{payload_id}` path parameter **MUST** be validated as a well-formed hex-encoded `Bytes8` before processing.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sun, 01 Mar 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8178</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8178</guid>
      </item>
    
      <item>
        <title>Private ETH and ERC-20 Transfers</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8182-private-eth-and-erc-20-transfers/27889</comments>
        
        <description>## Abstract

This EIP introduces protocol-level private ETH and compatible [ERC-20](/EIPs/EIPS/eip-20) transfers with public deposits and withdrawals, implemented as a system contract with a companion proof-verification precompile. A recursive proof architecture separates protocol invariants enforced by a hard-fork-managed outer circuit from permissionless inner authentication circuits, allowing users to choose compatible authentication methods — such as ECDSA, passkeys, or multisig — without requiring a hard fork for each new auth method. The same system contract also exposes an optional delivery-key registry for standardized on-chain note-delivery key discovery and supports opt-in origin-tagged notes for later app-defined origin proofs. Receiving shielded notes requires prior user registration, even when note delivery is handled out of band. The system contract has no on-chain upgrade mechanism and can only be replaced by a hard fork.

## Motivation

Sending assets publicly on Ethereum is straightforward. A user chooses ETH or a token, specifies a recipient using an Ethereum address or ENS name, and clicks send in an Ethereum wallet. Recipients, wallets, and applications already know how to interpret that transfer because they rely on the same shared standards.

Private transfers have no analogous shared default today, even though many ordinary financial activities require privacy. Payroll, treasury management, donations, and similar activities typically require that the sender, recipient, or amount not be globally visible. Without a shared private transfer layer, Ethereum cannot serve these use cases directly, so they are pushed toward traditional financial systems or other blockchains.

If private transfers are valuable, why has the market not produced a widely adopted default on Ethereum? Because a private transfer application cannot compete on product quality alone. Its effectiveness also depends on how many users and how much value share the same pool. A small pool offers weak privacy even for a superior product, while a large pool can remain attractive even when competing products are better. That means app-layer teams cannot focus only on wallet UX, authentication, compliance, or proof systems. They must also persuade users to deposit into their pool, which is difficult when the pool is not already large.

But growing the pool is only part of the problem. App-layer teams also have to decide how the pool changes over time. If the pool is upgradeable, the parties with the power to change it could compromise user funds. Immutable pools avoid that risk, but they cannot adapt as proof systems weaken or cryptographic assumptions change. Neither is a good foundation for common privacy infrastructure.

The Ethereum protocol should break this impasse by providing a shared privacy layer. This EIP does that by defining a protocol-managed private transfer system, updated only through Ethereum&apos;s hard-fork process, that provides a common pool for ETH and compatible ERC-20 tokens, supports private transfers to registered Ethereum addresses through an opt-in registry-backed receive path, and exposes an optional origin-tagged mode for applications that want later origin proofs. Applications can then build on that base without each having to bootstrap, govern, and defend their own pool.

### Scope

This EIP specifies the on-chain component: the pool contract, proof system, registries, and one baseline note-delivery scheme. The delivery-key registry is optional and only standardizes one on-chain discovery path. End-to-end transaction privacy still requires complementary infrastructure (mempool encryption, network-layer anonymity, wallet integration) that is out of scope.

## Specification

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

### 1. Overview

This EIP defines:

1. A **system contract** deployed at a protocol-defined address, holding all shielded pool state (e.g., note commitment tree, nullifier set, transaction replay ID set, user registry, delivery-key registry) with no proxy, no admin function, and no on-chain upgrade mechanism.
2. A **recursive proof composition** separating auth (permissionless inner circuits) from protocol invariants (hard-fork-managed outer circuit).
3. An **auth policy registry** binding `(address, innerVkHash)` pairs to auth credentials, supporting multiple auth policies per address.
4. An **optional delivery-key registry** binding each address to one active registered note-delivery endpoint.
5. A **public-input interface** for proofs and required contract execution checks.
6. An **optional per-note origin tag** for notes that need later origin proofs.
7. A **proof verification precompile** for gas-feasible proof verification.

These components are presented as a single EIP because they share state and form a single deployment unit.

### 2. Terminology

* **Note**: A shielded UTXO-like object represented on-chain by a `noteCommitment`.
* **Note commitment**: The public on-chain commitment / identifier for one note. See Section 7.2.
* **Nullifier**: Generic term for a spent-note marker published by the protocol. Real input notes publish `noteNullifier`; phantom inputs publish `phantomNullifier`.
* **Note nullifier**: The public spent-note marker for one real input note. See Section 7.3.
* **Phantom nullifier**: The public spent-input marker for one phantom input slot. See Section 7.4.
* **Origin tag**: A per-note tag. `originTag != 0` means the note is origin-tagged and traces back to one originating deposit. `originTag == 0` means the note is not origin-tagged. Here, origin means the note&apos;s originating deposit, not the immediate transfer sender or the full transfer history.
* **Proving infrastructure**: Infrastructure that generates zero-knowledge proofs. May be first-party (local machine, self-hosted server) or third-party (a proving service). See Section 4.1.
* **Outer circuit**: The hard-fork-managed circuit that enforces protocol invariants: value conservation, nullifiers, Merkle membership, deterministic note-secret derivation for outputs, inner proof verification, and auth policy registry checks.
* **Inner circuit**: A permissionless circuit that handles authentication and intent parsing. Outputs `[authDataCommitment, transactionIntentDigest]`. `authorizingAddress` and `policyVersion` are supplied to the outer circuit as private witnesses and authenticated through `transactionIntentDigest`. See Section 9.1.
* **Auth policy**: A binding of `innerVkHash`, `authDataCommitment`, and `policyVersion` in the auth policy registry. Each address may have multiple auth policies, one per inner circuit. See Sections 5.2 and 6.4.
* **Transaction intent digest**: The canonical digest of the contemplated pool action. It includes the signer-authenticated transaction fields and signer-selected execution constraints. The inner circuit authenticates this digest from the signed intent fields and any companion-standard constants; the outer circuit recomputes the same formula from witnesses, public inputs, and mode-derived values.
* **Transaction replay ID**: The transaction-level replay identifier consumed on use. It shares the replay domain inputs across all outputs from one transaction. See Section 9.8.
* **policyVersion**: A monotonically increasing counter per (address, innerVkHash) pair. Authenticated by the inner circuit&apos;s signed artifact. See Section 6.4.
* **Phantom input**: A dummy input slot used to maintain constant arity (2-input circuit) while spending only one real note. An observer MUST NOT be able to distinguish phantom from real inputs.
* **Dummy output**: A dummy output slot used to maintain constant output count (3 outputs) while producing fewer real notes.
* **User registry**: A Merkleized mapping from `address` to `(ownerNullifierKeyHash, noteSecretSeedHash)`. Leaf format: `poseidon(USER_REGISTRY_LEAF_DOMAIN, uint160(user), ownerNullifierKeyHash, noteSecretSeedHash)` (Section 3.4).
* **Owner nullifier key**: The note owner&apos;s non-rotatable hidden note-ownership key. It is hashed as `ownerNullifierKeyHash = poseidon(OWNER_NULLIFIER_KEY_HASH_DOMAIN, ownerNullifierKey)` in notes and in the user registry. See Sections 7.3 and 9.8.
* **Owner nullifier key hash**: The hash commitment to `ownerNullifierKey`, used in note commitments and the user registry. See Sections 7.2 and 9.3.
* **Note secret seed**: A rotatable sender-side secret committed in the user registry as `noteSecretSeedHash = poseidon(NOTE_SECRET_SEED_DOMAIN, noteSecretSeed)`. Used only to derive future `noteSecret`s, and therefore indirectly for future real-note-nullifier derivation, not for note ownership or wallet-layer note delivery.
* **Note secret**: The per-note hidden value derived during output formation and later reused in `noteNullifier`. See Sections 7.2, 7.3, and 9.5.
* **Delivery endpoint**: A public `(schemeId, keyBytes)` pair registered by an address for note delivery in the delivery-key registry. `schemeId = 0` denotes no active registered endpoint in this registry. The contract stores endpoints opaquely and does not validate that `keyBytes` are well-formed for the selected scheme.
* **Output note data**: Opaque per-output bytes emitted by the contract for wallet/app-layer note delivery. The base protocol does not validate or interpret these bytes. Section 15 defines the scheme-`1` interpretation. Delivery may also be coordinated out of band.
* **Output binding**: `poseidon(OUTPUT_BINDING_DOMAIN, noteCommitment, outputNoteDataHash)`. This binds one emitted note commitment to one output-note-data hash for signer-authenticated finalized-output locking.
* **Execution constraints**: The private signed fields `executionConstraintsFlags` and `lockedOutputBinding0/1/2`. They optionally bind finalized output slots.
* **`depositorAddress`**: Public input. The deposit payer&apos;s Ethereum address; `msg.sender` must equal it. Nonzero selects deposit mode.
* **`recipientAddress`**: Private witness in the transaction intent digest. The recipient authorized by the signer — the note owner for transfers and deposits, or the withdrawal destination (constrained to equal `publicRecipientAddress`).
* **`feeRecipientAddress`**: Private witness in the transaction intent digest. The optional designated recipient of the private fee note in output slot 2. If `feeAmount &gt; 0` and `feeRecipientAddress == 0`, the prover chooses output slot 2&apos;s nonzero `ownerAddress` at proof generation time.
* **`feeAmount`**: Private witness in the transaction intent digest. The optional private fee paid through output slot 2. `0` means no fee.
* **`originMode`**: Private witness in the transaction intent digest. `0` means default origin handling; `1` means tagged-origin handling. In deposit mode this selects whether the deposit creates untagged notes (`0`) or origin-tagged notes (`1`). In transfer/withdrawal mode, tagged-origin handling requires the real inputs to share one nonzero `originTag` and requires any real outputs to remain origin-tagged.
* **`nonce`**: Private signed field element used for replay protection.
* **`executionConstraintsFlags`**: Private signed bitmask selecting which finalized-output slots are locked by the signer.
* **`lockedOutputBinding0/1/2`**: Private signed field elements that optionally lock `outputBinding0/1/2` for slots 0, 1, and 2.
* **`publicRecipientAddress`**: Public input. The withdrawal destination address; zero for deposits and transfers.

### 3. Parameters and Constants

#### 3.1 Domain Separators

All Poseidon hashes that require domain separation MUST include a distinct domain tag (field element). Each domain tag is derived as:

```
DOMAIN = uint256(keccak256(&quot;eip-8182.&lt;context_name&gt;&quot;)) mod p
```

where `p` is the BN254 scalar field order (the field over which SNARK circuits and Poseidon operate) and `&lt;context_name&gt;` is the string identifier listed below. This derivation is deterministic and fixes all domain tags.

The following domain tags are defined by this EIP (all use the `eip`-`8182.` prefix):

| Constant | Context string | Usage |
|----------|---------------|-------|
| `NOTE_NULLIFIER_DOMAIN` | `note_nullifier` | Real note nullifiers |
| `PHANTOM_NULLIFIER_DOMAIN` | `phantom_nullifier` | Phantom nullifiers |
| `ORIGIN_TAG_DOMAIN` | `origin_tag` | Deposit origin tags |
| `TRANSACTION_REPLAY_ID_DOMAIN` | `transaction_replay_id` | Transaction replay IDs |
| `OWNER_NULLIFIER_KEY_HASH_DOMAIN` | `owner_nullifier_key_hash` | Owner nullifier key hashing |
| `NOTE_SECRET_DOMAIN` | `note_secret` | Deterministic note-secret derivation |
| `TRANSACTION_INTENT_DIGEST_DOMAIN` | `transaction_intent_digest` | Transaction intent digests |
| `OUTPUT_BINDING_DOMAIN` | `output_binding` | Per-slot output bindings |
| `AUTH_POLICY_DOMAIN` | `auth_policy` | Auth policy registry leaves |
| `AUTH_POLICY_KEY_DOMAIN` | `auth_policy_key` | Auth policy registry tree keys |
| `AUTH_VK_DOMAIN` | `auth_vk` | Inner circuit VK hashing |
| `NOTE_SECRET_SEED_DOMAIN` | `note_secret_seed` | Note secret seed hashing |
| `USER_REGISTRY_LEAF_DOMAIN` | `user_registry_leaf` | User registry leaves |

All values are deterministically computable from the derivation formula above and MUST be `&lt; p`.

#### 3.2 Fixed Constants

* `MAX_INTENT_LIFETIME = 86400` — maximum allowed forward offset from `block.timestamp` to `validUntilSeconds`, in seconds (24 hours), checked at submission time. This means proofs are accepted only during the final 24 hours before expiry; it does not measure authorization age from signing time. Root-history windows independently bound proof freshness.
* `NOTE_COMMITMENT_ROOT_HISTORY_SIZE = 500` — consensus-critical, fixed by spec.
* `USER_REGISTRY_ROOT_HISTORY_BLOCKS = 500` — consensus-critical, fixed by spec.
* `AUTH_POLICY_ROOT_HISTORY_BLOCKS = 64` — consensus-critical, fixed by spec. The contract accepts the current auth policy root or any root preserved from the last 64 blocks. See Section 5.2.
* `DUMMY_OWNER_NULLIFIER_KEY_HASH` — `poseidon(OWNER_NULLIFIER_KEY_HASH_DOMAIN, 0xdead)`. Used for dummy output slots. The circuit enforces `amount == 0` for dummy outputs, preventing value extraction regardless of preimage knowledge.
* `TRANSFER_OP = 0` — operation kind for shielded transfers.
* `WITHDRAWAL_OP = 1` — operation kind for withdrawals.
* `DEPOSIT_OP = 2` — operation kind for deposits.
* `ORIGIN_MODE_DEFAULT = 0` — default origin handling.
* `ORIGIN_MODE_REQUIRE_TAGGED = 1` — tagged-origin handling. Deposits create origin-tagged notes; transfer/withdrawal mode requires the real inputs to share one nonzero `originTag` and any real outputs to remain origin-tagged.
* `LOCK_OUTPUT_BINDING_0 = 1 &lt;&lt; 0` — lock output slot 0&apos;s finalized output binding.
* `LOCK_OUTPUT_BINDING_1 = 1 &lt;&lt; 1` — lock output slot 1&apos;s finalized output binding.
* `LOCK_OUTPUT_BINDING_2 = 1 &lt;&lt; 2` — lock output slot 2&apos;s finalized output binding.

#### 3.3 Poseidon Hash Construction

This EIP uses Poseidon over the BN254 scalar field `p` (defined in Section 3.1) with the following parameters:

* State width: `t = 3` (2-arity, absorbing 2 field elements per permutation)
* S-box: `x^5` (`α = 5`)
* Full rounds: `R_F = 8`
* Partial rounds: `R_P = 57`
* Round constants and MDS matrix: exactly the constants in [the Poseidon parameter asset](/EIPs/assets/eip-8182/poseidon_bn254_t3_rf8_rp57.json). The corresponding normative vectors are in [the Poseidon vector asset](/EIPs/assets/eip-8182/poseidon_vectors.json).

This EIP uses a single 2-input Poseidon primitive, `hash_2(a, b)`, defined as one permutation on state `[0, a, b]` returning output element 0. All generic `poseidon(x_0, ..., x_{n-1})` expressions are defined as an arity-prefixed wrapper over that primitive: `poseidon(x_0, ..., x_{n-1}) = hash_2(n, tree(x_0, ..., x_{n-1}))`.

Here `tree(...)` is the left-balanced binary tree over the inputs, defined recursively: `tree(x) = x`; `tree(a, b) = hash_2(a, b)`; for `n &gt; 2`, the left subtree receives the largest power of 2 strictly less than `n` inputs and the right subtree receives the remainder. For example, `poseidon(x) = hash_2(1, x)`, `poseidon(a, b) = hash_2(2, hash_2(a, b))`, and `poseidon(a, b, c, d) = hash_2(4, hash_2(hash_2(a, b), hash_2(c, d)))`.

All `poseidon(...)` expressions in this EIP use this arity-prefixed construction. We write `hash_n(...)` as shorthand for `poseidon(...)` when emphasizing arity. Merkle tree internal nodes are the exception: they use raw `hash_2(left, right)` directly, not the arity-prefixed wrapper. A summary of hash contexts is in Section 13.

#### 3.4 Merkle Tree Constructions

Unless otherwise stated, all Merkle trees in this EIP use `hash_2(left, right)` from Section 3.3.

**Note commitment tree.** Depth-32 append-only binary Poseidon Merkle tree. Leaf indices are `uint32` values in `[0, 2^32 - 1]`, assigned sequentially from 0. Empty leaf is `0`. A membership proof is an ordered list of 32 sibling nodes from leaf level upward. At height `h` in `[0, 31]`, bit `h` of `leafIndex_u32` (least-significant bit at height 0) determines whether the current hash is the left child (`0`) or the right child (`1`) when computing the parent as `hash_2(left, right)`. For `i` in `[0, 31]`, `EMPTY_NOTE_COMMITMENT[i + 1] = hash_2(EMPTY_NOTE_COMMITMENT[i], EMPTY_NOTE_COMMITMENT[i])` with `EMPTY_NOTE_COMMITMENT[0] = 0`.

**User registry tree.** Depth-160 sparse binary Poseidon Merkle tree keyed by `uint160(user)`. The key is a 160-bit big-endian bitstring; at depth `d` (`d = 0` is MSB), bit `0` selects the left branch and bit `1` the right. Leaf value:

`poseidon(USER_REGISTRY_LEAF_DOMAIN, uint160(user), ownerNullifierKeyHash, noteSecretSeedHash)`

Empty leaf is `0`. For `i` in `[0, 159]`, `EMPTY_USER[i + 1] = hash_2(EMPTY_USER[i], EMPTY_USER[i])` with `EMPTY_USER[0] = 0`.

**Auth policy tree.** Depth-160 sparse binary Poseidon Merkle tree. The auth-policy path is defined as the low 160 bits of `poseidon(AUTH_POLICY_KEY_DOMAIN, authorizingAddress, innerVkHash)`, interpreted big-endian. Path traversal follows the same convention as the user registry tree. Leaf value: `poseidon(AUTH_POLICY_DOMAIN, authDataCommitment, policyVersion)`. Empty leaf is `0`. Same empty-node ladder convention.

### 4. Two-Circuit Architecture

This EIP uses a recursive proof architecture that splits the proof into two circuits with different trust properties.

**Outer circuit** (hard-fork-managed). There is exactly one outer circuit; it can only change via hard fork. It enforces all protocol invariants: value conservation, nullifier derivation, Merkle membership, deterministic note-secret derivation for outputs, and registry lookups. It also recursively verifies an inner proof as part of its own verification. The outer circuit is the security boundary — a bug here can compromise the entire pool.

**Inner circuit** (permissionless). Anyone can write and deploy an inner circuit. It handles authentication — verifying the user&apos;s credential — and intent parsing — computing the transaction intent digest over transaction fields and any signer-selected execution constraints. It outputs two public values: `[authDataCommitment, transactionIntentDigest]`. The outer circuit uses private witnesses for `authorizingAddress` and `policyVersion`, authenticates them through `transactionIntentDigest`, checks `authDataCommitment` against the auth-policy leaf, and checks `transactionIntentDigest` against its own independent recomputation from execution data plus finalized-output bindings. Section 9.1 specifies the full per-mode constraints.

**How they compose.** A prover supplies the inner proof and inner verification key as private witnesses to the outer circuit. The outer circuit recursively verifies the inner proof, computes `innerVkHash` from the verification key, and uses it to look up the auth policy registry leaf. Because the inner verification key is a private witness, on-chain observers cannot determine which inner circuit (and therefore which auth method) was used. Section 9.1 specifies the full normative interface.

| Responsibility | Circuit | Fork required? |
|----------------|---------|----------------|
| Value conservation | Outer | Yes |
| Nullifier derivation | Outer | Yes |
| Merkle membership | Outer | Yes |
| Deterministic note-secret derivation | Outer | Yes |
| Inner proof verification | Outer | Yes |
| Auth policy registry check | Outer | Yes |
| Transaction replay ID derivation | Outer | Yes |
| Canonical transaction-intent-digest computation | Outer | Yes |
| Signature verification | Inner | No |
| Intent parsing | Inner | No |
| Auth data commitment binding | Inner | No |
| policyVersion authentication | Inner | No |

The outer circuit enforces protocol invariants that protect the entire pool. A weakened outer circuit could drain all funds. The inner circuit handles auth — a weakened inner circuit can only risk the registering user&apos;s funds. This separation is what makes permissionless inner circuits safe.

**Auth method anonymity.** All auth methods share a single outer circuit. `innerVkHash` is never a public input — it is checked inside the circuit against the auth policy leaf. On-chain observers cannot determine which auth method was used for a given pool transaction. Auth policy registration is public (`innerVkHash` appears in the `AuthPolicyRegistered` event); the privacy property is transaction-time only.

**Output note delivery.** `outputNoteData0`, `outputNoteData1`, and `outputNoteData2` are hash-bound to the proof via `outputNoteDataHash0`, `outputNoteDataHash1`, and `outputNoteDataHash2` (public inputs). The signer MAY additionally lock a slot&apos;s emitted note commitment to its payload hash through `outputBinding`. The inner circuit has no scheme-specific role in note delivery, and the outer circuit does not enforce any encryption scheme or delivery format. Section 15 defines the registry lookup and the scheme-`1` interpretation.

#### 4.1 Proving Modes

Proof generation can be delegated to a third party without granting spending authority. This section uses *first-party* and *third-party* to describe who is trusted to operate the prover; *local* and *remote* (elsewhere in this EIP) describe where computation runs. A self-hosted cloud server is first-party but remote.

Two proving configurations are supported:

**First-party proving.** The user controls the proving infrastructure — a local machine or self-hosted server. No third party sees transaction details beyond what is visible on-chain. Requires client software that handles `ownerNullifierKey`, `noteSecretSeed`, coin selection, witness construction, and note-delivery key lookup plus any supported delivery schemes.

**Third-party proving.** The user signs an authorization and delegates proof generation to a specialized proving service. The prover learns all transaction details and retains discretion over coin selection and registry root selection within the valid history window. Without `originMode = ORIGIN_MODE_REQUIRE_TAGGED`, a malicious prover can intentionally choose inputs that clear origin tags on real outputs. With `originMode = ORIGIN_MODE_REQUIRE_TAGGED`, proofs fail unless deposits create nonzero origin tags and transfer/withdrawal mode uses real inputs with one shared nonzero `originTag` while keeping any real outputs origin-tagged. It cannot forge unauthorized operations, redirect payments, or extract funds — these properties are enforced by the proof system regardless of prover behavior. If the signer leaves a slot unlocked, a malicious prover can still choose unusable `outputNoteData` or mutate that slot&apos;s finalized output at proving time; if the signer locks a slot via `lockedOutputBinding0/1/2`, the prover cannot mutate that slot after signing.

|  | On-chain | Third-party prover |
|---|---|---|
| Tx occurred | yes | yes |
| Token | deposits and withdrawals | yes |
| Amount | deposits and withdrawals | yes |
| Fee amount | no | yes |
| Fee recipient | no | yes |
| Sender | deposits | yes |
| Recipient | withdrawals | yes |
| Which notes spent | no | yes |
| Auth method used | no | yes |

Shielded transfer public inputs reveal nothing beyond the fact that a transaction occurred. Opaque note-delivery payloads (`outputNoteData0`, `outputNoteData1`, `outputNoteData2`) are also on-chain; their size and structure may leak metadata depending on the delivery scheme and wallet payload conventions in use. Deposits expose depositor, token, and amount; the note recipient is private. Withdrawals expose amount, recipient, and token. `feeAmount` and the fee note&apos;s recipient remain private in all modes; if `feeRecipientAddress == 0` and `feeAmount &gt; 0`, the prover chooses output slot 2&apos;s owner at proof generation time. Auth method used is hidden at the proof level for all pool transactions; auth policy registration is public. For deposits, because `depositorAddress` is public, observers can narrow the auth method to that address&apos;s registered auth-policy set. With first-party proving, the &quot;Third-party prover&quot; column does not apply.

Users MUST maintain independent backups of `ownerNullifierKey` and either `noteSecretSeed` or note plaintext including `noteSecret`. Loss of `ownerNullifierKey` is permanent fund loss. Loss of `noteSecretSeed` without note plaintext backups can make notes whose `noteSecret` has not otherwise been recovered unspendable. Users relying on delivery keys for note recovery SHOULD also retain the corresponding delivery private keys until all notes encrypted to them have been recovered.

**Third-party prover persistence.** A third-party prover learns `ownerNullifierKey` permanently and therefore retains the ability to monitor spends of previously known notes. It also learns the current `noteSecretSeed`, so it can derive future `noteSecret`s until that seed is rotated. After `rotateNoteSecretSeed` and stale user roots expire, the old prover can no longer derive note secrets for future transactions by that address. Delivery keys are separate wallet-layer material; rotating or removing a delivery key does not affect note ownership or proof validity, but old delivery private keys may still be needed to recover notes created before the rotation.

### 5. System Contract

#### 5.1 Deployment and Upgrade Model

The shielded pool is deployed as a system contract at `SHIELDED_POOL_ADDRESS = 0x0000000000000000000000000000000000081820`.

At the activation fork, clients MUST install the account object in [the shielded-pool state dump](/EIPs/assets/eip-8182/shielded-pool-state.json) at `SHIELDED_POOL_ADDRESS`. This state dump is the canonical shielded-pool activation artifact. The installer used to generate it is non-normative tooling and is not part of consensus.

The shielded-pool runtime is linked against an external `PoseidonT3` contract at `0x3333333C0A88F9BE4fd23ed0536F9B6c427e3B93`. Correct execution of the pool requires the code at that address to exactly equal [`poseidon_t3_runtime.hex`](/EIPs/assets/eip-8182/poseidon_t3_runtime.hex). This external dependency is a prerequisite, not part of the shielded-pool activation artifact. This EIP does not constrain that account&apos;s balance, nonce, or storage. Chains adopting this EIP MUST NOT activate it unless that prerequisite is already satisfied at activation.

* The code at `SHIELDED_POOL_ADDRESS` can only be replaced by a subsequent hard fork that sets new code as part of its state transition rules.
* There is no proxy, no admin function, and no on-chain upgrade mechanism.
* Storage persists across fork-initiated code replacements (see Section 5.2).

#### 5.2 State

The pool MUST maintain:

* **Note commitment Merkle tree** — append-only Poseidon Merkle tree (depth: 32, ~4B leaves). Empty leaf = 0. Holds multi-asset notes (`tokenAddress` is inside the note commitment). The contract MUST revert if `nextLeafIndex + 3 &gt; 2^32` (since `transact` always inserts three note commitments).
* **Note commitment root history** — circular buffer (size: `NOTE_COMMITMENT_ROOT_HISTORY_SIZE`, consensus-critical). On each `transact`, the contract MUST push the pre-insertion note-commitment root into this buffer. The contract accepts the **current root** OR any historical root still in the buffer.
* **Nullifier set** — `mapping(uint256 =&gt; bool)`.
* **Transaction replay ID set** — `mapping(uint256 =&gt; bool)`.
* **User registry** — depth-160 sparse Poseidon Merkle tree (Section 3.4), with block-based root history (window: `USER_REGISTRY_ROOT_HISTORY_BLOCKS`). History mechanics are defined in Section 5.2.1. The contract accepts the **current root** OR any historical root still within the window. Leaves commit to both `ownerNullifierKeyHash` and `noteSecretSeedHash`.
* **Delivery key registry** — `mapping(address =&gt; DeliveryEndpoint)` storing one active public registered delivery endpoint `(schemeId, keyBytes)` per registered address. This registry is optional, is not Merkleized, is not referenced by any circuit, has no root history, and does not affect proof validity.
* **Auth policy registry** — depth-160 sparse Poseidon Merkle tree (Section 3.4), with block-based root history (window: `AUTH_POLICY_ROOT_HISTORY_BLOCKS`). History mechanics are defined in Section 5.2.1. The contract accepts the **current root** OR any historical root still within the window. Used by the outer circuit for inner circuit binding.
* **Policy versions** — `mapping(bytes32 =&gt; uint256)` keyed by `keccak256(abi.encodePacked(user, innerVkHash))`, tracking the per-(address, innerVkHash) `policyVersion` counter. This mapping is the canonical source of truth for the next version to assign; the leaf value encodes the version at the time of its last write. Stored versions MUST remain canonical BN254 field elements (`&lt; p`) because `policyVersion` is hashed into Poseidon-based leaves and digests. Both are updated atomically in `registerAuthPolicy`.

#### 5.2.1 Block-Based Registry Root Histories

The user registry and auth policy registry use block-based root histories. For a registry with window `W`, the contract maintains a ring buffer of `W + 1` `(root, blockNumber)` pairs. The extra slot prevents a mutation in block `N + W` from overwriting a root that is still within the acceptance window.

On the first mutation to a registry in block `N`, the contract MUST snapshot the root accepted at the start of block `N` into the ring buffer at position `N mod (W + 1)` with `blockNumber = N`. Subsequent mutations to the same registry in block `N` update the current root but MUST NOT create additional history entries.

A candidate root `r` is accepted iff there exists a stored pair `(storedRoot, storedBlockNumber)` such that `storedRoot == r` and `block.number - storedBlockNumber &lt;= W`. The current root is always accepted.

Because only the start-of-block root is preserved, intermediate same-block roots are not retained once later same-block mutations occur. Wallets and provers SHOULD avoid depending on same-block `registerUser` / `rotateNoteSecretSeed` / `registerAuthPolicy` / `deregisterAuthPolicy` changes unless transaction ordering is controlled; the safer default is to wait at least one subsequent block before proving against the new root.

#### 5.3 Contract Interface

The pool MUST expose the following functions:

**Pool transaction:**

```solidity
struct PublicInputs {
    uint256 noteCommitmentRoot;
    uint256 nullifier0;
    uint256 nullifier1;
    uint256 noteCommitment0;
    uint256 noteCommitment1;
    uint256 noteCommitment2;
    uint256 publicAmountIn;
    uint256 publicAmountOut;
    uint256 publicRecipientAddress;
    uint256 publicTokenAddress;
    uint256 depositorAddress;
    uint256 transactionReplayId;
    uint256 registryRoot;
    uint256 validUntilSeconds;
    uint256 executionChainId;
    uint256 authPolicyRegistryRoot;
    uint256 outputNoteDataHash0;
    uint256 outputNoteDataHash1;
    uint256 outputNoteDataHash2;
}

function transact(
    bytes calldata proof,
    PublicInputs calldata publicInputs,
    bytes calldata outputNoteData0,
    bytes calldata outputNoteData1,
    bytes calldata outputNoteData2
) external payable;
```

**Read methods:**

```solidity
function getCurrentRoots()
    external
    view
    returns (
        uint256 noteCommitmentRoot,
        uint256 registryRoot,
        uint256 authPolicyRegistryRoot
    )

function getUserRegistryEntry(
    address user
) external view returns (
    bool registered,
    uint256 ownerNullifierKeyHash,
    uint256 noteSecretSeedHash
)

function getAuthPolicy(
    address user,
    uint256 innerVkHash
) external view returns (
    bool active,
    uint256 authDataCommitment,
    uint256 policyVersion
)

function isAcceptedNoteCommitmentRoot(
    uint256 root
) external view returns (bool)

function isAcceptedUserRegistryRoot(
    uint256 root
) external view returns (bool)

function isAcceptedAuthPolicyRoot(
    uint256 root
) external view returns (bool)

function isNullifierSpent(
    uint256 nullifier
) external view returns (bool)

function isTransactionReplayIdUsed(
    uint256 transactionReplayId
) external view returns (bool)
```

`getCurrentRoots` returns the current note-commitment root, current user-registry root, and current auth-policy root accepted by the contract.

`getUserRegistryEntry` returns the current user-registry entry for `user`, or `(false, 0, 0)` if the address is not registered.

`getAuthPolicy` returns whether the `(user, innerVkHash)` pair is currently active plus the current `authDataCommitment` and `policyVersion` for that pair. It MUST reject `innerVkHash &gt;= p` (BN254 scalar field order) to avoid the same field-aliasing ambiguity as `registerAuthPolicy`/`deregisterAuthPolicy`. If the pair was never registered, it returns `(false, 0, 0)`. After deregistration, it returns `(false, lastAssignedAuthDataCommitment, lastAssignedPolicyVersion)`.

`isAcceptedNoteCommitmentRoot`, `isAcceptedUserRegistryRoot`, and `isAcceptedAuthPolicyRoot` return whether the supplied root would currently pass the same acceptance rule enforced by `transact`. `isAcceptedUserRegistryRoot(0)` and `isAcceptedAuthPolicyRoot(0)` MUST return `false`.

`isNullifierSpent` returns whether the supplied nullifier has already been marked spent. `isTransactionReplayIdUsed` returns whether the supplied transaction replay ID has already been consumed.

These read methods are the canonical online read path for current state and status checks used by wallets, provers, relayers, and sponsors. Note-commitment-tree sync, note discovery, and witness construction remain off-chain event/indexer workflows; the spec MUST NOT require replay from genesis as the only standard read path.

**User registration:**

```solidity
function registerUser(
    uint256 ownerNullifierKeyHash,
    uint256 noteSecretSeedHash
) external

function registerUser(
    uint256 ownerNullifierKeyHash,
    uint256 noteSecretSeedHash,
    uint32 schemeId,
    bytes calldata keyBytes
) external
```

The two `registerUser` overloads are called by `msg.sender` to bind the caller&apos;s address to an owner-nullifier-key hash and note-secret-seed hash. The 4-argument overload also sets the caller&apos;s initial registered delivery endpoint atomically with registration.

```solidity
function rotateNoteSecretSeed(
    uint256 newNoteSecretSeedHash
) external
```

`rotateNoteSecretSeed` is called by `msg.sender` to update only the `noteSecretSeedHash` committed in the user registry. It is direct-only. The contract MUST revert if the caller is not registered. The new hash MUST be canonical (`&lt; p`). The function updates the caller&apos;s user-registry leaf in place and MUST maintain the block-based user-registry root history invariant (Section 5.2.1).

**Delivery key registration:**

```solidity
struct DeliveryEndpoint {
    uint32 schemeId;
    bytes keyBytes;
}

function setDeliveryKey(
    uint32 schemeId,
    bytes calldata keyBytes
) external

function removeDeliveryKey() external

function getDeliveryKey(
    address user
) external view returns (uint32 schemeId, bytes memory keyBytes)
```

`setDeliveryKey` is called by `msg.sender` to set or replace the caller&apos;s active registered delivery endpoint. The caller MUST already have a user-registry entry. `schemeId` MUST be nonzero and `keyBytes.length` MUST be nonzero. The contract stores `keyBytes` opaquely and MUST NOT validate that they are well-formed for the selected scheme.

`removeDeliveryKey` is called by `msg.sender` to clear the caller&apos;s active registered delivery endpoint. The caller MUST already have a user-registry entry. The contract MUST revert if no delivery endpoint is currently set.

`getDeliveryKey` returns the active registered delivery endpoint for `user`, or `(0, &quot;&quot;)` if none is registered in this registry.

Delivery-key changes do not affect in-flight proofs, proof validity, or any root-history acceptance rule.

**Auth policy registration:**

```solidity
function registerAuthPolicy(
    uint256 innerVkHash,
    uint256 authDataCommitment
) external
```

`registerAuthPolicy` is called by `msg.sender` to bind the `(address, innerVkHash)` pair to an auth data commitment. `authDataCommitment` is opaque. The caller MUST already have a user-registry entry. A single address may register multiple auth policies (one per `innerVkHash`); each has its own independent `policyVersion`.

* MUST reject `innerVkHash &gt;= p` or `authDataCommitment &gt;= p` (BN254 scalar field order) to prevent field aliasing between the Poseidon tree key (which reduces mod `p`) and the keccak-based `policyVersion` mapping key (which does not).
* Computes the auth-policy tree key as `uint160(poseidon(AUTH_POLICY_KEY_DOMAIN, msg.sender, innerVkHash))` (low 160 bits; see Section 3.4).
* Computes the per-pair version key as `keccak256(abi.encodePacked(msg.sender, innerVkHash))` and increments `policyVersion` for that pair (starting from 1 on first registration).
* MUST revert if the incremented `policyVersion &gt;= p` before computing the new leaf, because `policyVersion` is consumed as a field element inside Poseidon-based leaves and intent digests.
* Computes the leaf `poseidon(AUTH_POLICY_DOMAIN, authDataCommitment, policyVersion)`.
* MUST revert if the leaf equals 0 — the zero leaf is reserved for the absent/deregistered state (see `deregisterAuthPolicy`).
* Writes the leaf at the composite key.

**Root history update:** On every auth-policy registration or deregistration, the contract MUST ensure the block-based root history invariant (Section 5.2.1) is maintained.

The method MUST emit:

```solidity
event AuthPolicyRegistered(
    address indexed user,
    uint256 innerVkHash,
    uint256 authDataCommitment,
    uint256 policyVersion
);
```

**Auth policy deregistration:**

```solidity
function deregisterAuthPolicy(
    uint256 innerVkHash
) external
```

`deregisterAuthPolicy` is called by `msg.sender` to remove an auth policy. The contract MUST reject `innerVkHash &gt;= p` (BN254 scalar field order) to prevent field aliasing at the auth-policy tree key. The contract writes `0` (the empty leaf) at the auth-policy tree key `uint160(poseidon(AUTH_POLICY_KEY_DOMAIN, msg.sender, innerVkHash))`. Deregistration is direct-only. After stale auth-policy roots expire, no proof against that (address, innerVkHash) pair can succeed. MUST revert if the leaf is already `0`. MUST emit:

```solidity
event AuthPolicyDeregistered(
    address indexed user,
    uint256 innerVkHash
);
```

After deregistration, the auth-policy tree state is indistinguishable from &quot;never registered&quot; — history is carried by events, not the current leaf. The auxiliary `getAuthPolicy` mapping MUST still expose the last assigned `authDataCommitment` and `policyVersion` for current-state introspection, but the tree leaf is `0` and therefore unusable for proof verification. Re-registration at the same (address, innerVkHash) pair continues from the existing `policyVersion` counter (which is not reset by deregistration), so old intents signed at pre-deregistration versions cannot match the re-registered leaf.

Both delivery-key methods MUST emit:

```solidity
event DeliveryKeySet(
    address indexed user,
    uint32 indexed schemeId,
    bytes keyBytes
);

event DeliveryKeyRemoved(
    address indexed user,
    uint32 indexed schemeId
);
```

Addresses without a user-registry entry cannot receive or spend notes. The default (empty) leaf in the auth policy tree is `0`, denoting absence. The outer circuit requires a membership proof at the auth-policy tree key `uint160(poseidon(AUTH_POLICY_KEY_DOMAIN, authorizingAddress, innerVkHash))` whose leaf matches `poseidon(AUTH_POLICY_DOMAIN, authDataCommitment, policyVersion)`, where `authDataCommitment` comes from the inner proof output and `authorizingAddress` and `policyVersion` are the same private witness values used in `transactionIntentDigest`; an unregistered pair has leaf `0` and no valid match exists.

#### 5.4 Execution

On each call, the pool MUST execute the following steps:

`transact` MUST be non-reentrant.

1. **Verify the proof** via the verification precompile using `proof` and `publicInputs`.

2. **Verify execution chain ID.** Require `executionChainId == block.chainid`.

3. **Enforce intent expiry.**
   * Require `validUntilSeconds &gt; 0`.
   * Require `block.timestamp &lt;= validUntilSeconds`.
   * Require `validUntilSeconds &lt;= block.timestamp + MAX_INTENT_LIFETIME`.

   This is a submission-window bound, not a measure of time since signing.

4. **Check note-commitment root.** Require `noteCommitmentRoot` equals the current note-commitment root or is in the note-commitment root history.

5. **Check registry root.** Require `registryRoot` equals the current user registry root or is in the user registry root history. `registryRoot` MUST be nonzero.

6. **Check auth policy registry root.** Require `authPolicyRegistryRoot` equals the current auth policy root OR is in the auth policy registry block-based root history. `authPolicyRegistryRoot` MUST be nonzero.

7. **Enforce nullifier uniqueness.** Require `nullifier0 != nullifier1` (defense-in-depth). The contract MUST NOT attempt to distinguish phantom nullifiers from real ones.

8. **Mark nullifiers spent.** Require both nullifiers are unspent; then mark them spent.

9. **Mark transaction replay ID used.** Require `transactionReplayId` is unused; then mark it used.

10. **Insert note commitments.** Insert `noteCommitment0`, `noteCommitment1`, and `noteCommitment2` into the note commitment tree. Note commitments MUST be nonzero — dummy outputs use nonzero dummy note commitments (inserting 0 is indistinguishable from the tree&apos;s empty leaf value).

11. **Verify output note data hashes.** Require `uint256(keccak256(outputNoteData0)) % p == outputNoteDataHash0`, `uint256(keccak256(outputNoteData1)) % p == outputNoteDataHash1`, and `uint256(keccak256(outputNoteData2)) % p == outputNoteDataHash2`. This binds the opaque payloads to the proof, preventing mempool observers or relayers from substituting payloads without invalidating the proof. The contract MUST NOT otherwise interpret or validate the payload contents.

12. **Enforce public input ranges.**

    * Require `publicAmountIn &lt; 2^248` and `publicAmountOut &lt; 2^248`. Values in `[2^248, p)` pass field canonicality checks but could overflow the balance equation inside the circuit (Section 7.1).
    * Require `publicRecipientAddress &lt; 2^160`, `publicTokenAddress &lt; 2^160`, and `depositorAddress &lt; 2^160`. Values in `[2^160, p)` are canonical field elements but alias when interpreted as EVM addresses.
    * Require `validUntilSeconds &lt; 2^32`. This keeps the public expiry timestamp within the protocol&apos;s 32-bit UNIX-seconds domain.

13. **Execute asset movement based on operation mode.** Exactly one of the following three branches MUST match; the conditions are mutually exclusive:

    **Deposit** (`depositorAddress != 0`):
    * Enforce deposit value constraints per Section 8.1 (`msg.sender == depositorAddress`, `publicAmountIn &gt; 0`, `publicAmountOut == 0`, `publicRecipientAddress == 0`).
    * If `publicTokenAddress == 0` (ETH): require `msg.value == publicAmountIn`.
    * If `publicTokenAddress != 0` (ERC-20): require `msg.value == 0`. Record `balBefore = balanceOf(address(this))`. Execute `transferFrom(msg.sender, address(this), publicAmountIn)` and require success. Require `balanceOf(address(this)) - balBefore == publicAmountIn`, else revert.

    **Withdrawal** (`depositorAddress == 0` AND `publicAmountOut &gt; 0`):
    * Require `msg.value == 0`.
    * Enforce withdrawal value constraints per Section 8.3 (`publicAmountIn == 0`, `publicRecipientAddress != 0`).
    * If `publicTokenAddress == 0` (ETH): perform a low-level `CALL` to `address(uint160(publicRecipientAddress))` with value `publicAmountOut`, empty calldata, and all remaining gas; require success.
    * If `publicTokenAddress != 0` (ERC-20): execute `transfer(publicRecipientAddress, publicAmountOut)` and require success.
    * The on-chain tx submitter MAY be a relayer whose address is irrelevant to the proof — only the intent tx signer matters.

    **Transfer** (`depositorAddress == 0` AND `publicAmountOut == 0`):
    * Require `msg.value == 0`.
    * Enforce transfer value constraints per Section 8.2 (`publicAmountIn == 0`, `publicRecipientAddress == 0`, `publicTokenAddress == 0`).
    * The on-chain tx submitter MAY be a relayer whose address is irrelevant to the proof — only the intent tx signer matters.

    ERC-20 calls MUST use the following exact semantics:
    * `balanceOf(address(this))` MUST be executed via `staticcall`, MUST not revert, and MUST return exactly 32 bytes.
    * `transferFrom(msg.sender, address(this), publicAmountIn)` and `transfer(publicRecipientAddress, publicAmountOut)` MUST not revert and MUST satisfy one of:
      * returndata length is 0 and the target account has nonzero code length;
      * returndata length is exactly 32 bytes decoding to `true`.
    * Any other returndata shape, empty returndata from an account with zero code length, or a decoded `false` return value MUST be treated as failure.

    Fee-on-transfer and rebasing tokens are incompatible. The deposit-side balance-delta check rejects fee-on-transfer tokens; rebasing tokens are not reliably detectable. Tokens that charge fees only on outbound `transfer` (not on `transferFrom`) pass the deposit check but deliver less than `publicAmountOut` on withdrawal. Such tokens MUST NOT be deposited.

14. **Emit events.** Emit the following event:

    ```solidity
    event ShieldedPoolTransact(
        uint256 indexed nullifier0,
        uint256 indexed nullifier1,
        uint256 indexed transactionReplayId,
        uint256 noteCommitment0,
        uint256 noteCommitment1,
        uint256 noteCommitment2,
        uint256 leafIndex0,
        uint256 postInsertionCommitmentRoot,
        bytes outputNoteData0,
        bytes outputNoteData1,
        bytes outputNoteData2
    );
    ```

    `leafIndex0` is the note-commitment-tree leaf index of `noteCommitment0`; `noteCommitment1` is always at `leafIndex0 + 1`, and `noteCommitment2` is always at `leafIndex0 + 2`. `postInsertionCommitmentRoot` is the note-commitment root after all three note commitments have been inserted (distinct from `publicInputs.noteCommitmentRoot`, which is the pre-insertion root the proof was verified against). This makes tree reconstruction from events deterministic regardless of log ordering, and saves scanners from tracking insertion count from genesis.

    Nullifiers and `transactionReplayId` are indexed for efficient scanning and lookup. Note commitments, `postInsertionCommitmentRoot`, and all three `outputNoteData*` fields are non-indexed. Wallets discover incoming notes by scanning `ShieldedPoolTransact` events and interpreting the output note data per Section 15 and any additional supported delivery schemes.

    **Registration events:**

    ```solidity
    event UserRegistered(
        address indexed user,
        uint256 ownerNullifierKeyHash,
        uint256 noteSecretSeedHash
    );

    event NoteSecretSeedRotated(
        address indexed user,
        uint256 noteSecretSeedHash
    );

    event DeliveryKeySet(
        address indexed user,
        uint32 indexed schemeId,
        bytes keyBytes
    );

    event DeliveryKeyRemoved(
        address indexed user,
        uint32 indexed schemeId
    );

    ```

    Both `registerUser` overloads MUST emit `UserRegistered`. The 4-argument overload MUST also emit `DeliveryKeySet`. `rotateNoteSecretSeed` MUST emit `NoteSecretSeedRotated`. `setDeliveryKey` and `removeDeliveryKey` MUST emit the delivery-key events. Scanners use `UserRegistered` and `NoteSecretSeedRotated` to maintain local copies of the user registry tree, and MAY cache current delivery endpoints from the delivery-key events. Wallets and provers MAY also use the direct read methods in Section 5.3 as the canonical online read path.

### 6. Registries

#### 6.1 User Registry

The shielded pool MUST maintain a Poseidon Merkle tree mapping:

```
address → (ownerNullifierKeyHash, noteSecretSeedHash)
```

Root history follows the block-based model (Section 5.2.1, window: `USER_REGISTRY_ROOT_HISTORY_BLOCKS`).

Registration is REQUIRED before any pool operation that creates notes owned by an address. The circuit enforces that the depositor&apos;s or recipient&apos;s `ownerNullifierKeyHash` matches a registry Merkle proof — an unregistered address cannot receive notes. This opt-in registration model keeps ordinary Ethereum addresses as note owners through a registry-backed receive path, rather than requiring a separate privacy-native address format. Initial registration is a one-time operation per address via one of the `registerUser` overloads. Withdrawal recipients (`publicRecipientAddress`) do not need to be registered — withdrawals send to any Ethereum address. For the standardized on-chain address-only receive path, registered users SHOULD also set a delivery endpoint (Section 6.5).

Wallets and provers can read the current user-registry entry for a specific address via `getUserRegistryEntry`, the active delivery endpoint via `getDeliveryKey`, and the current accepted roots via `getCurrentRoots` (Section 5.3).

#### 6.2 Registration Methods

The contract MUST provide:

* `registerUser(ownerNullifierKeyHash, noteSecretSeedHash)` — callable by `msg.sender`. MUST revert if the address is already registered.
* `registerUser(ownerNullifierKeyHash, noteSecretSeedHash, schemeId, keyBytes)` — callable by `msg.sender`. MUST revert if the address is already registered. This overload also initializes the caller&apos;s registered delivery endpoint.
* `rotateNoteSecretSeed(newNoteSecretSeedHash)` — callable by `msg.sender`. MUST revert if the address is not registered.

All registration methods MUST respect the block-based root history invariant (Section 5.2.1). Registration methods MUST reject `ownerNullifierKeyHash &gt;= p` or `noteSecretSeedHash &gt;= p` to prevent field aliasing between on-chain storage and in-circuit Poseidon computation. `rotateNoteSecretSeed` MUST reject `newNoteSecretSeedHash &gt;= p`. All registration methods MUST compute the resulting user-registry leaf and revert if it equals 0 — the zero leaf is reserved for the absent state.

The 4-argument `registerUser` overload MUST additionally require `schemeId != 0` and `keyBytes.length != 0`, write the caller&apos;s registered delivery endpoint atomically with the user-registry entry, and emit both `UserRegistered` and `DeliveryKeySet`. Users who do not want to use this registry use the 2-argument overload and MAY call `setDeliveryKey` later.

#### 6.3 Key Mutability

`ownerNullifierKeyHash` is immutable. `ownerNullifierKey` is therefore non-rotatable. If `ownerNullifierKey` is compromised, users can mitigate by rotating `noteSecretSeed` and auth methods.

`noteSecretSeedHash` is rotatable via `rotateNoteSecretSeed`. Rotating it does not affect ownership of existing notes, but changes the derived `noteSecret` used for future outputs after stale user roots expire. After rotation, users MUST retain the prior `noteSecretSeed` until the stale-root window (`USER_REGISTRY_ROOT_HISTORY_BLOCKS` blocks) expires and any transactions they authorized against the old root have either settled or been abandoned.

#### 6.4 Auth Policy Registry

The auth policy registry binds `(address, innerVkHash)` pairs to credentials. State layout is specified in Section 5.2. Registration is via `registerAuthPolicy` (direct only). See Section 5.3.

Wallets and provers can read the current status/version for a specific `(address, innerVkHash)` pair via `getAuthPolicy` and the current accepted roots via `getCurrentRoots` (Section 5.3).

**Rotation and revocation.** Auth policy rotation is bounded-delay, not instant, and operates per auth method. Other auth methods registered by the same address are unaffected. The old auth-policy root remains valid for up to `AUTH_POLICY_ROOT_HISTORY_BLOCKS` blocks. During this window, old intents (signed with the old `policyVersion`) remain provable against the stale root. If the user&apos;s own leaf changed (rotation or deregistration), the intent becomes permanently unprovable once the stale root expires.

Full revocation of a specific auth method becomes effective once the stale auth root ages out of the bounded history window. After that point:

* The old root is no longer accepted by the contract (Section 5.4, step 6).
* Old intents carry the old `policyVersion` in the signed intent → mismatch with the current registry leaf → outer proof failure.
* Re-registering identical credentials at a higher `policyVersion` does NOT resurrect old intents. The outer circuit uses the `policyVersion` authenticated through the old signed artifact, which mismatches the new leaf&apos;s incremented version.
* Rotating one auth method does not affect intents signed with other auth methods for the same address — each (address, innerVkHash) pair has its own `policyVersion`.

**Adding a new auth method.** To add a new auth method:

1. Publish an inner circuit that verifies the new signature scheme and outputs `[authDataCommitment, transactionIntentDigest]`, while authenticating `authorizingAddress` and `policyVersion` through the signed intent.
2. Users register their credentials via `registerAuthPolicy` with the inner circuit&apos;s `innerVkHash` and their `authDataCommitment`. Existing auth policies for other inner circuits remain active — the new registration creates a new leaf at a distinct composite key.
3. Done — no hard fork required.

Constraints: the inner circuit MUST conform to the inner-proof envelope (Section 9.1). `innerVkHash` MUST be computed from the canonical inner-verification-key encoding defined in Section 9.1. Companion ERCs MUST authenticate all intent-digest fields. Companion ERCs MUST reject any authenticated value `&gt;= p` before interpreting it as a BN254 field element, including `nonce` and any other authenticated input that feeds `transactionIntentDigest` or other field-based commitments. Companion ERCs MUST ensure an authorization valid for one `innerVkHash` is invalid for any other; this EIP does not define how. Auth methods requiring a different proof system need a hard fork that updates the outer circuit.

**Cross-circuit note compatibility.** Note commitments bind to `(ownerAddress, ownerNullifierKeyHash)` — neither field encodes an auth method. A note created with any inner circuit is spendable with any other inner circuit, provided the user has registered an auth policy for the spending circuit&apos;s `innerVkHash`.

All inner circuits share the same note tree, nullifier set, and anonymity set — adding a new auth method requires only a new `registerAuthPolicy` call (creating a leaf at a new composite key), not a fund transfer. Both old and new auth methods remain usable simultaneously.

These inner-circuit extensions govern spend authorization only. `registerUser`, `rotateNoteSecretSeed`, `setDeliveryKey`, `removeDeliveryKey`, `registerAuthPolicy`, and `deregisterAuthPolicy` remain direct `msg.sender`-gated lifecycle methods. Users who want multisig or contract-governed lifecycle control SHOULD use a smart-contract wallet address as the registered note owner.

**Deactivation.** A user can deregister an auth method via `deregisterAuthPolicy` (Section 5.3), which writes the empty leaf (`0`) at the composite key. Deactivation is bounded-delay: the old auth-policy root remains valid for up to `AUTH_POLICY_ROOT_HISTORY_BLOCKS` blocks after deregistration. After expiry, no proof against that (address, innerVkHash) pair can succeed. A user may also replace credentials by re-registering with a new `authDataCommitment`, which increments `policyVersion` and invalidates old authorizations after stale roots expire. Global disabling of auth methods (e.g., pre-quantum schemes) requires a hard fork.

#### 6.5 Delivery Key Registry

The same system contract also maintains a public delivery-key registry mapping:

```
address → (schemeId, keyBytes)
```

Each address has at most one active registered delivery endpoint. `schemeId = 0` denotes no active registered endpoint in this registry. This registry is optional, is not Merkleized, is not referenced by any circuit, and does not affect proof validity or root histories.

The registry exists solely as a standardized on-chain discovery surface for the party constructing `outputNoteData` for a recipient. In first-party proving this is the wallet or user software; in delegated proving it is typically the prover. Delivery may also be coordinated out of band.

If `getDeliveryKey(recipient) == (0, &quot;&quot;)`, this EIP provides no on-chain delivery metadata for that recipient. The transaction can still be constructed because `outputNoteData` is protocol-opaque, but note delivery must be coordinated out of band. Wallets SHOULD treat registry-based address-only private send as unavailable in that case.

Delivery-key registration is direct-only. Initial delivery-key setup MAY be combined with direct user registration via the 4-argument `registerUser` overload.

### 7. Note Commitment and Nullifiers

#### 7.1 Address and Amount Constraints

Inside the circuit:

* All address-valued fields (`ownerAddress`, `authorizingAddress`, `tokenAddress`, `depositorAddress`, `publicRecipientAddress`, `recipientAddress`, `feeRecipientAddress`) MUST be constrained to `&lt; 2^160`. Without this, field aliasing could produce commitments or public inputs that pass proof verification but bind to different addresses than the EVM expects. The contract MUST also reject public `publicRecipientAddress`, `publicTokenAddress`, or `depositorAddress` values `&gt;= 2^160` before interpreting them as EVM addresses.
* Amounts MUST be constrained to `&lt; 2^248`. ERC-20 amounts are `uint256`, but the SNARK field is ~254 bits. The balance equation sums at most 4 terms per side; `4 * 2^248 &lt; p` prevents field overflow. The contract MUST also reject `publicAmountIn` or `publicAmountOut` values `&gt;= 2^248`.

#### 7.2 Note Commitment

Notes MUST commit to exactly the following fields:

```
noteCommitment = poseidon(
  amount,
  ownerAddress,
  noteSecret,
  ownerNullifierKeyHash,
  tokenAddress,
  originTag
)
```

* `ownerAddress` — 20-byte Ethereum address. The note owner: set to `recipientAddress` for transfer recipient notes and deposit notes, `authorizingAddress` for sender change notes (transfers and withdrawals), or the fee-note recipient (`feeRecipientAddress` when nonzero, otherwise prover-selected) for fee notes.
* `noteSecret` — the deterministically derived per-note secret used to blind the `noteCommitment` and make real note nullifiers note-specific. In this protocol it is derived from the sender&apos;s `noteSecretSeed`, the transaction&apos;s `transactionReplayId`, and the output&apos;s `outputIndex` (Section 9.5).
* `ownerNullifierKeyHash` — hash of the owner&apos;s nullifier key: `poseidon(OWNER_NULLIFIER_KEY_HASH_DOMAIN, ownerNullifierKey)`.
* `tokenAddress` — ERC-20 contract address, or `0` for ETH.
* `originTag` — optional origin-tracking tag (see Section 12).

The binary-tree Poseidon construction and exact input ordering are defined in Section 3.3.

#### 7.3 Nullifier

A real input note nullifier MUST be computed as:

```
noteNullifier = poseidon(
  NOTE_NULLIFIER_DOMAIN,
  ownerNullifierKey,
  noteSecret
)
```

* `ownerNullifierKey` — a secret scalar known only to the note owner. Required to spend notes. Loss of this key means permanent loss of access to the associated shielded funds. Key derivation and storage are implementation-defined.
* `noteSecret` — the note&apos;s per-note secret.

Real note nullifiers are derived from `(ownerNullifierKey, noteSecret)`, not from Merkle position. Under valid V1 note creation, duplicate `(ownerNullifierKey, noteSecret)` pairs should not arise because `noteSecret` is deterministically derived from `(noteSecretSeed, transactionReplayId, outputIndex)` and `transactionReplayId` is one-time-use. `leafIndex_u32` remains part of the Merkle membership witness only.

#### 7.4 Phantom Nullifier

If an input slot is phantom, the circuit MUST use:

```
phantomNullifier = poseidon(
  PHANTOM_NULLIFIER_DOMAIN,
  ownerNullifierKey,
  transactionReplayId,
  inputIndex
)
```

* `inputIndex` is 0 or 1 (the unused input slot).
* `PHANTOM_NULLIFIER_DOMAIN` prevents collision with real nullifiers.
* `ownerNullifierKey` is the spender&apos;s secret — because it is private, an observer MUST NOT be able to distinguish phantom nullifiers from real ones.
* `transactionReplayId` (which incorporates `chainId`) provides per-transaction and per-chain uniqueness, preventing cross-chain phantom nullifier collisions.

The contract MUST treat phantom nullifiers indistinguishably from real nullifiers.

#### 7.5 Note Secret Seed

The sender-side note secret seed MUST hash to:

```
noteSecretSeedHash = poseidon(
  NOTE_SECRET_SEED_DOMAIN,
  noteSecretSeed
)
```

`noteSecretSeed` is used only for deterministic note-secret derivation. It does not affect note ownership or wallet-layer note delivery, and affects future real note nullifiers only through `noteSecret`. Unlike `ownerNullifierKey`, it is rotatable through the user registry (Section 6.3).

### 8. Operation Modes

The pool supports three operation modes, determined by public inputs:

#### 8.1 Deposit Mode

Deposit mode is selected when `depositorAddress != 0`.

Requirements:

* The depositor MUST be registered in the user registry (Section 6.1).
* The depositor MUST have a registered auth policy (Section 6.4).
* The recipient MUST be registered in the user registry — the circuit requires the recipient&apos;s `ownerNullifierKeyHash` for output note commitment binding.
* If `feeAmount != 0`, output slot 2&apos;s owner MUST be registered in the user registry.
* Inner proof REQUIRED (Section 9.1).
* `msg.sender == depositorAddress`.
* `publicTokenAddress` specifies the deposited asset (`0` for ETH, otherwise an ERC-20 address).
* `publicAmountIn &gt; 0`.
* `publicAmountOut == 0`.
* `publicRecipientAddress == 0`.
* Both input slots MUST be phantom.
* `publicAmountIn == amount + feeAmount`, where `amount` is the signed intent amount and `feeAmount` is the optional private fee.
* Output slot 0 MUST be one real output owned by `recipientAddress` (from the transaction intent digest), with amount equal to the signed intent `amount` and `tokenAddress == publicTokenAddress`.
* Output slot 1 MUST be dummy.
* Output slot 2 MUST be a fee note with `amount == feeAmount`. If `feeRecipientAddress != 0`, its `ownerAddress` MUST equal `feeRecipientAddress`. If `feeAmount &gt; 0` and `feeRecipientAddress == 0`, its `ownerAddress` MUST be prover-selected and nonzero. If `feeAmount == 0`, output slot 2 MUST be dummy.
* `validUntilSeconds &gt; 0`.
* `operationKind` = `DEPOSIT_OP` (derived from `depositorAddress != 0`; no new operation kind).

Deposits expose token, amount, and depositor address on-chain; the note recipient is private.

#### 8.2 Transfer Mode (Shielded Transfer)

Transfer mode is selected when:

* `depositorAddress == 0`
* `publicAmountIn == 0`
* `publicAmountOut == 0`
* `publicRecipientAddress == 0`
* `publicTokenAddress == 0`

In transfer mode the token MUST be private (enforced inside the circuit); the on-chain transaction MUST NOT reveal token or amount. The transfer anonymity set spans all tokens because `publicTokenAddress` is zero.

Coin selection is delegated to the prover. The transaction intent digest binds payment semantics (recipient, amount, token, operation type), the selected origin-mode rule via `originMode`, and any signer-selected output-binding locks, but it does not bind exact note selection or exact output origin tags. Operation-type binding is the inner circuit&apos;s responsibility via `operationKind` in the transaction intent digest.

Output slot 0 is the recipient payment note, output slot 1 is sender change or dummy, and output slot 2 is the fee note or dummy.

#### 8.3 Withdrawal Mode (Public Withdrawal)

Withdrawal mode is selected when:

* `depositorAddress == 0`
* `publicAmountIn == 0`
* `publicAmountOut &gt; 0`
* `publicRecipientAddress != 0`
* `publicTokenAddress` specifies the withdrawn token (`0` for ETH, otherwise ERC-20 address)

Withdrawals are public with respect to token, amount, and recipient address.

Output slot 0 is sender change or dummy, output slot 1 MUST be dummy, and output slot 2 is the fee note or dummy.

### 9. Circuit Requirements

This EIP specifies a recursive proof architecture. The **outer circuit** (hard-fork-managed) enforces protocol invariants. **Inner circuits** (permissionless) handle authentication and intent parsing. The outer circuit recursively verifies an inner circuit proof as part of its own verification.

Invariants (permanent, enforced by the outer circuit):

* Note commitment format (Section 7.2)
* Nullifier derivation from `ownerNullifierKey` — this is why cross-circuit spending works
* Value conservation constraints
* Note commitment tree structure and nullifier set
* User registry (Section 6): the outer circuit proves `ownerNullifierKeyHash` and the sender&apos;s `noteSecretSeedHash` against it
* Deterministic note-secret derivation

Independent extension axes:

* **Auth method:** permissionless via inner circuits (Section 4, Section 6.4)
* **Intent format:** inner-circuit-determined, specified by companion standards
* **Note-delivery scheme:** Section 15 defines scheme `1`; payload hashes are proof-bound, and finalized output slots MAY additionally be signer-constrained via output bindings

#### 9.1 Authorization — Inner/Outer Split

The outer circuit MUST use `depositorAddress` (a public input) to determine the operation mode. The public-input constraints for each mode (amount directions, phantom/dummy slot requirements) are defined in Section 8. This section specifies the additional circuit-level enforcement per mode.

**Inner VK Hash:** `innerVkHash` uniquely identifies the inner circuit. The outer circuit computes it from the inner verification key provided as a private witness and uses it to look up the auth policy registry. Let `vk[0] .. vk[114]` denote the 115 BN254 field elements of the `UltraHonkVerificationKey` witness in recursive-verifier order. Compute leaves as `[poseidon(AUTH_VK_DOMAIN, 115), poseidon(vk[0], vk[1]), poseidon(vk[2], vk[3]), ..., poseidon(vk[112], vk[113]), vk[114]]`, then recursively fold that list as a binary tree with `poseidon(left, right)` to obtain `innerVkHash`.

**Deposit mode** (`depositorAddress != 0`):

The outer circuit performs inner proof verification where `authorizingAddress` is the depositor and `recipientAddress` is the output note owner:

1. Recursively verifies the inner proof → outputs `[authDataCommitment, transactionIntentDigest]`.
2. Computes `outputBinding_i` from the actual commitments and `outputNoteDataHash_i` values (Section 9.7).
3. Enforces any locked-slot equalities against the actual `outputBinding_i` values (Section 9.12).
4. Computes `transactionIntentDigest` from private witnesses and public inputs (Section 9.11), including `authorizingAddress`, `policyVersion`, `recipientAddress`, `nonce`, and any signer-selected execution constraints. Enforces the result matches `transactionIntentDigest` from the inner proof output.
5. Computes `innerVkHash` from `innerVkey` (Inner VK Hash). Proves auth policy membership at key `uint160(poseidon(AUTH_POLICY_KEY_DOMAIN, authorizingAddress, innerVkHash))`, where `authorizingAddress` is the same witness value used in `transactionIntentDigest`.
6. Computes `poseidon(AUTH_POLICY_DOMAIN, authDataCommitment, policyVersion)` and verifies this equals the leaf opened at the composite key, where `policyVersion` is the same witness value used in `transactionIntentDigest`.
7. **Enforces `authorizingAddress == depositorAddress`** — the signer must be the depositor.
8. Binds `authorizingAddress` to the depositor&apos;s user registry entry (`ownerNullifierKeyHash`, `noteSecretSeedHash`).
9. Derives `transactionReplayId` per Section 9.8.
10. **Proves the recipient&apos;s user registry entry** using `recipientAddress` — obtains the recipient&apos;s `ownerNullifierKeyHash` for output note commitment binding.
11. **Constrains output slot 0&apos;s `ownerAddress` to `recipientAddress`**.
12. **Constrains output slot 2** to either a fee note (`amount == feeAmount`, owner determined per Section 9.5) or dummy.
13. Enforces `publicAmountIn == amount + feeAmount`.
14. Output slot 1 MUST be dummy.

The circuit must prove two or three user registry entries: depositor + recipient, and additionally output slot 2&apos;s owner if `feeAmount != 0`. Deposit mode additionally requires `authorizingAddress = depositorAddress`, `recipientAddress =` output slot 0 owner, `amount =` output slot 0 amount, and `tokenAddress = publicTokenAddress`. `feeRecipientAddress` and `feeAmount` govern output slot 2 per step 12.

**Transfer/withdrawal mode** (`depositorAddress == 0`):

The outer circuit:

1. Recursively verifies the inner proof against `innerVkey` with public outputs `[authDataCommitment, transactionIntentDigest]`.
2. Computes `outputBinding_i` from the actual commitments and `outputNoteDataHash_i` values (Section 9.7).
3. Enforces any locked-slot equalities against the actual `outputBinding_i` values (Section 9.12).
4. Computes `transactionIntentDigest` from execution data (Section 9.11), including `authorizingAddress`, `policyVersion`, `nonce`, and any signer-selected execution constraints. Enforces the result matches `transactionIntentDigest` from the inner proof output.
5. Computes `innerVkHash` from `innerVkey` (Inner VK Hash).
6. Computes auth-policy tree key `uint160(poseidon(AUTH_POLICY_KEY_DOMAIN, authorizingAddress, innerVkHash))` and proves auth policy membership at that key, where `authorizingAddress` is the same witness value used in `transactionIntentDigest`.
7. Computes `poseidon(AUTH_POLICY_DOMAIN, authDataCommitment, policyVersion)` and verifies this equals the leaf opened at the composite key, where `policyVersion` is the same witness value used in `transactionIntentDigest`.
8. Binds `authorizingAddress` to note ownership via user registry (`ownerNullifierKeyHash` and `noteSecretSeedHash`).
9. Derives `transactionReplayId` per Section 9.8.

**Inner Circuit Interface** (normative):

Inner circuit public output vector — 2 field elements, fixed order:

1. `authDataCommitment` — credential commitment proved against. Outer circuit checks it matches the auth-policy leaf.
2. `transactionIntentDigest` — digest over the signer-authenticated transaction fields and signer-selected execution constraints. Outer circuit checks it matches its own recomputation.

`authorizingAddress` and `policyVersion` are private outer-circuit witnesses reused in auth-policy verification.

`innerVkHash` is NOT an inner circuit output — the outer circuit computes it from the verification key used for recursive verification.

**Inner-proof envelope**: Inner circuits MUST conform to UltraHonk on BN254. The public output vector is exactly 2 field elements in this order: `authDataCommitment`, `transactionIntentDigest`. The outer circuit consumes the inner verification key as the 115-field-element `UltraHonkVerificationKey` witness described above and the inner proof as the corresponding `UltraHonkZKProof` witness accepted by the recursive verifier. No sample inner proof or sample inner verification key is normative. Auth methods requiring a different proof system need a hard fork.

**Security property:** The inner circuit MUST NOT have access to `ownerNullifierKey` or `noteSecretSeed`. Specifically, neither secret MUST appear as a witness or public input in the inner proof relation. The outer circuit derives `transactionReplayId` and `noteSecret` independently.

**Normative equality constraints** (MUST):

* `authorizingAddress` witness used in `transactionIntentDigest` == address used for auth policy lookup, user registry lookup, nullifier derivation, and change note ownership. `recipientAddress` from the transaction intent digest determines recipient note ownership (transfers) and deposit note ownership. If `feeRecipientAddress != 0`, it determines fee-note ownership in output slot 2; otherwise output slot 2 ownership is prover-selected at proof generation time. For deposits, `authorizingAddress` is additionally constrained to equal `depositorAddress`.
* `innerVkHash` computed from `innerVkey` == `innerVkHash` used in auth-policy tree key `uint160(poseidon(AUTH_POLICY_KEY_DOMAIN, authorizingAddress, innerVkHash))`
* `authDataCommitment` from inner proof == `authDataCommitment` in auth policy leaf
* `policyVersion` witness used in `transactionIntentDigest` == `policyVersion` in auth policy leaf
* `transactionIntentDigest` from inner proof == outer circuit&apos;s recomputed transaction intent digest

#### 9.2 Note Ownership and Membership

For each input slot:

* If `isPhantom == 0` (real input): the circuit MUST prove Merkle membership in `noteCommitmentRoot`. The `noteCommitment` MUST include the signer&apos;s address, so only notes owned by the signer match.
* If `isPhantom == 1` (phantom input): membership MUST be skipped. The circuit MUST enforce `phantomNullifier = poseidon(PHANTOM_NULLIFIER_DOMAIN, ownerNullifierKey, transactionReplayId, inputIndex)` and `amount = 0`.

`isPhantom` MUST be constrained to 0 or 1.

In transfer and withdrawal modes (`depositorAddress == 0`), at least one input MUST be real (`isPhantom == 0`). (For withdrawals this is already implied by value conservation and `publicAmountOut &gt; 0`; the constraint is stated explicitly for defense-in-depth.)

#### 9.3 Owner-Nullifier-Key and Note-Secret-Seed Binding

For real input slots, the circuit MUST enforce:

```
poseidon(
  OWNER_NULLIFIER_KEY_HASH_DOMAIN,
  ownerNullifierKey
) == note.ownerNullifierKeyHash
```

This binds the owner nullifier key to the key hash committed in the note.

For phantom input slots, the owner-nullifier-key binding MUST be skipped.

In deposit mode (both inputs phantom), the circuit MUST still enforce that `poseidon(OWNER_NULLIFIER_KEY_HASH_DOMAIN, ownerNullifierKey) == registryOwnerNullifierKeyHash(authorizingAddress)`, where `authorizingAddress` is the signer-authenticated witness value used in `transactionIntentDigest` (constrained to equal `depositorAddress` per Section 9.1) and `registryOwnerNullifierKeyHash` is the depositor&apos;s registered owner-nullifier-key hash proven via the user registry Merkle proof. This prevents an untrusted prover from choosing an arbitrary `ownerNullifierKey` for deposit outputs.

In all operation modes, the circuit MUST enforce:

```
poseidon(
  NOTE_SECRET_SEED_DOMAIN,
  noteSecretSeed
) == registryNoteSecretSeedHash(authorizingAddress)
```

where `registryNoteSecretSeedHash(authorizingAddress)` is extracted from the sender&apos;s user-registry leaf. This binds deterministic note-secret derivation to a rotatable sender-side secret.

#### 9.4 Value Conservation

The circuit MUST enforce:

```
sum(input_amounts) + publicAmountIn == sum(output_amounts) + publicAmountOut
```

Both sides MUST include range checks to prevent overflow. `publicAmountIn` and `publicAmountOut` are public inputs bound by this constraint.

#### 9.5 Output Well-Formedness and Determinism

For each output slot, per-slot `isDummy` flag (constrained to 0 or 1):

* If `isDummy == 0` (real output): Real output notes MUST have `amount &gt; 0`. The output note commitment MUST be correctly formed for its owner and token. `ownerNullifierKeyHash` MUST match the registry-proven key hash for that output&apos;s owner: recipient note, sender change note, or fee note. Additional per-mode constraints:
    * **Transfer**: Per Section 8.2. The circuit MUST enforce that output slot 0 is the recipient payment (note `ownerAddress` = `recipientAddress`, `ownerNullifierKeyHash` = recipient&apos;s registry-proven key hash, `amount` = authorized amount, `tokenAddress` = authorized token), output slot 1 is sender change or dummy (note `ownerAddress` = `authorizingAddress`, `ownerNullifierKeyHash` = sender&apos;s registry-proven key hash), and output slot 2 is a fee note or dummy (note `ownerAddress` = `feeRecipientAddress` if nonzero, otherwise prover-selected and nonzero; `ownerNullifierKeyHash` = that owner&apos;s registry-proven key hash; `amount` = `feeAmount`).
    * **Withdrawal**: Per Section 8.3. Output slot 0 is sender change or dummy, output slot 1 MUST be dummy, and output slot 2 is a fee note or dummy.
    * **Deposit**: Per Section 8.1. Output slot 0 is the recipient note, output slot 1 MUST be dummy, and output slot 2 is a fee note or dummy.
* If `isDummy == 1` (dummy output):
    * `amount` MUST equal 0.
    * `ownerAddress` MUST equal 0.
    * `tokenAddress` MUST equal 0.
    * `originTag` MUST equal 0.
    * `ownerNullifierKeyHash` MUST equal `DUMMY_OWNER_NULLIFIER_KEY_HASH`.
    * The `amount == 0` constraint prevents value extraction even if a preimage for `DUMMY_OWNER_NULLIFIER_KEY_HASH` were found.

For output slot 2 specifically, the circuit MUST enforce:

* `feeAmount == 0` iff output slot 2 is dummy, and then `feeRecipientAddress == 0`.
* `feeAmount &gt; 0` iff output slot 2 is real.
* If `feeAmount &gt; 0` and `feeRecipientAddress != 0`, then `ownerAddress == feeRecipientAddress`.
* If `feeAmount &gt; 0` and `feeRecipientAddress == 0`, then `ownerAddress` MUST be nonzero. In that case the prover chooses output slot 2&apos;s owner at proof generation time.

The note secret MUST be deterministically derived for both real and dummy output slots:

```
noteSecret = poseidon(
  NOTE_SECRET_DOMAIN,
  noteSecretSeed,
  transactionReplayId,
  outputIndex
)
```

Dummy outputs use the same note-secret derivation as real outputs. This removes prover discretion over dummy note commitments. The resulting `noteCommitment` remains subject to the existing nonzero-commitment rule (Section 5.4, step 10).

Here `outputIndex` is the output-slot index `0`, `1`, or `2`.

For a fixed witness assignment (same input notes, same output ordering, same accepted `registryRoot`, same `noteSecretSeed`), note-secret derivation is deterministic. This removes prover discretion over note commitments given a fixed witness, but coin selection, output assignment, and registry root selection (within the valid history window) are not canonicalized.

#### 9.6 Registry Binding

Gated by operation type:

* **Transfer**: the outer circuit MUST prove the recipient address has a user registry entry so output slot 0 can bind the recipient&apos;s `ownerNullifierKeyHash`. The outer circuit MUST also prove the sender (`authorizingAddress` witness used in `transactionIntentDigest`) has a user registry entry, extracting both `ownerNullifierKeyHash` and `noteSecretSeedHash`. If `feeAmount != 0`, the outer circuit MUST additionally prove output slot 2&apos;s `ownerAddress` has a user registry entry. The outer circuit MUST prove auth policy membership for `authorizingAddress` (see Section 9.1).
* **Withdrawal**: the outer circuit MUST prove the sender has a user registry entry, extracting both `ownerNullifierKeyHash` and `noteSecretSeedHash`, so any change note binds the sender&apos;s note key and its `noteSecret` derives from the registered note-secret seed. If `feeAmount != 0`, the outer circuit MUST additionally prove output slot 2&apos;s `ownerAddress` has a user registry entry. The outer circuit MUST prove auth policy membership for `authorizingAddress`. Recipient binding is skipped — the recipient receives unshielded funds via `publicRecipientAddress`. Any address can be a withdrawal destination; compliance is handled by counterparty-level origin-proof protocols, not by registry membership.
* **Deposit**: the outer circuit MUST prove the depositor (`authorizingAddress`) has a user registry entry, extracting both the depositor&apos;s `ownerNullifierKeyHash` and `noteSecretSeedHash`. The circuit MUST additionally prove the recipient (`recipientAddress` from the transaction intent digest) has a user registry entry, extracting the recipient&apos;s `ownerNullifierKeyHash` for output slot 0 commitment binding. If `feeAmount != 0`, the circuit MUST additionally prove output slot 2&apos;s `ownerAddress` has a user registry entry. The outer circuit MUST prove auth policy membership for `authorizingAddress`.

#### 9.7 Output Note Data

`outputNoteDataHash0`, `outputNoteDataHash1`, and `outputNoteDataHash2` are public inputs that bind opaque note-delivery payloads to the proof. The prover computes `outputNoteDataHash0 = uint256(keccak256(outputNoteData0)) % p` and includes it as a public input; the contract independently computes the same value from calldata and verifies equality. Likewise for outputs 1 and 2. This prevents third parties from substituting payloads without invalidating the proof.

For each slot `i`, the outer circuit MUST compute:

```
outputBinding_i = poseidon(
  OUTPUT_BINDING_DOMAIN,
  noteCommitment_i,
  outputNoteDataHash_i
)
```

Execution constraints (Section 9.12) MAY lock any subset of these three `outputBinding_i` values. If a slot is locked, the prover cannot change either the emitted note commitment or the emitted payload bytes for that slot after signing. If a slot is unlocked, the finalized output for that slot remains prover-discretionary subject to the rest of the proof relation.

The outer and inner circuits do not validate encryption scheme semantics or delivery format. Section 15 defines the registry lookup and the interpretation for scheme ID `1`.

#### 9.8 Transaction Replay ID

All operation modes use the same transaction replay ID derivation:

```
transactionReplayId = poseidon(
    TRANSACTION_REPLAY_ID_DOMAIN,
    ownerNullifierKey,
    authorizingAddress,
    executionChainId,
    nonce
)
```

* `ownerNullifierKey` — the owner&apos;s secret; makes the replay ID unguessable.
* `authorizingAddress` and `executionChainId` namespace replay across users and chains.
* `nonce` — the signer-chosen replay discriminator, authenticated by the inner circuit through `transactionIntentDigest`.

Reusing the same `nonce` within the same `(ownerNullifierKey, authorizingAddress, executionChainId)` replay domain makes those authorizations mutually exclusive even when their payment fields or execution constraints differ. Wallets MUST ensure nonce freshness for each new authorization.

#### 9.9 Origin Tag Propagation

The circuit MUST enforce output origin tags per Section 12.

The outer circuit MUST additionally enforce:

* If `originMode == ORIGIN_MODE_DEFAULT`, no extra origin constraint.
* If `originMode == ORIGIN_MODE_REQUIRE_TAGGED`:
    * **Deposit mode** (both inputs phantom): every real output origin tag MUST satisfy `originTag != 0`.
    * **Transfer/withdrawal mode**:
        * **One real input** (one phantom): the real input&apos;s `originTag` MUST satisfy `originTag != 0`.
        * **Two real inputs**: both real inputs&apos; `originTag` values MUST be equal and nonzero.
        * Every real output origin tag, if any, MUST satisfy `originTag != 0`.
* Dummy outputs are exempt from the real-output check because they already enforce `originTag == 0`.
* If `originMode &gt; ORIGIN_MODE_REQUIRE_TAGGED`, the proof MUST fail.

#### 9.10 Token Consistency

All real input and output notes MUST use the same `tokenAddress`.

* For deposits and withdrawals: `tokenAddress == publicTokenAddress`. This binds the notes&apos; private token to the public input that drives fund movement.
* For transfers: `publicTokenAddress == 0`. Token consistency is enforced privately within the circuit.

#### 9.11 Transaction Intent Digest

The transaction intent digest is the canonical digest of the contemplated pool action. Both inner and outer circuits compute the same formula independently: the inner circuit from the authenticated intent fields and any companion-standard constants, and the outer circuit from witnesses, public inputs, and mode-derived values. The inner circuit authenticates this digest; the outer circuit recomputes it and binds the authenticated transaction fields and signer-selected execution constraints to the proof.

```
transactionIntentDigest = poseidon(
    TRANSACTION_INTENT_DIGEST_DOMAIN,
    policyVersion,
    authorizingAddress,
    operationKind,
    tokenAddress,
    recipientAddress,
    amount,
    feeRecipientAddress,
    feeAmount,
    originMode,
    executionConstraintsFlags,
    lockedOutputBinding0,
    lockedOutputBinding1,
    lockedOutputBinding2,
    nonce,
    validUntilSeconds,
    executionChainId
)
```

* `feeRecipientAddress` MAY be zero. If `feeAmount &gt; 0` and `feeRecipientAddress == 0`, output slot 2&apos;s `ownerAddress` is chosen by the prover at proof generation time. That address is not part of the transaction intent digest and is fixed only by the resulting proof.
* `originMode` binds whether the transaction may lose tagged-origin status. It does not bind exact note identities or an exact `originTag` value.

The outer circuit MUST derive `operationKind` from the public execution mode — it MUST NOT treat `operationKind` as an unconstrained witness. Derivation: `depositorAddress != 0` → `DEPOSIT_OP`; `depositorAddress == 0 AND publicAmountOut &gt; 0` → `WITHDRAWAL_OP`; `depositorAddress == 0 AND publicAmountOut == 0` → `TRANSFER_OP`.

**Normative execution-field binding** (MUST):

* Withdrawal: `recipientAddress == publicRecipientAddress`, `amount == publicAmountOut`, `tokenAddress == publicTokenAddress`, `validUntilSeconds` == public input, `executionChainId == block.chainid` (checked by contract). `feeRecipientAddress`, `feeAmount`, and `originMode` are private. If `feeAmount &gt; 0` and `feeRecipientAddress == 0`, output slot 2&apos;s `ownerAddress` is prover-selected and privately bound by the proof. `originMode` is enforced through Section 9.9.
* Transfer: `recipientAddress`, `amount`, `feeRecipientAddress`, `feeAmount`, and `originMode` are private (bound through intent-digest computation, output constraints, value conservation, and Section 9.9), `tokenAddress` is private (bound through token consistency, Section 9.10), `validUntilSeconds` == public input, `executionChainId == block.chainid` (checked by contract), `publicRecipientAddress == 0`, `publicAmountOut == 0`, `publicAmountIn == 0`, `publicTokenAddress == 0`. If `feeAmount &gt; 0` and `feeRecipientAddress == 0`, output slot 2&apos;s `ownerAddress` is prover-selected and privately bound by the proof.
* Deposit: `authorizingAddress == depositorAddress`, `recipientAddress` = output slot 0 owner (from the signed intent), `amount` = output slot 0 amount, `tokenAddress == publicTokenAddress`, `publicAmountIn == amount + feeAmount`, `validUntilSeconds` == public input, `executionChainId == block.chainid` (checked by contract). `originMode` is private, bound through intent-digest computation, and determines whether deposit outputs derive a fresh nonzero origin tag or `0` per Section 12.1. If `feeAmount &gt; 0` and `feeRecipientAddress == 0`, output slot 2&apos;s `ownerAddress` is prover-selected and privately bound by the proof.

#### 9.12 Execution Constraints

Execution constraints let the signer optionally bind finalized output slots without changing the nonce-based replay domain.

The private signed execution-constraints fields are:

* `executionConstraintsFlags`
* `lockedOutputBinding0`
* `lockedOutputBinding1`
* `lockedOutputBinding2`

Semantics:

* `executionConstraintsFlags` MUST be constrained to `&lt; 2^32`.
* Any flag bit other than `LOCK_OUTPUT_BINDING_0`, `LOCK_OUTPUT_BINDING_1`, and `LOCK_OUTPUT_BINDING_2` MUST cause proof failure.
* If a lock bit is unset, the corresponding `lockedOutputBinding{i}` MUST equal `0`.
* If a lock bit is set, the corresponding `lockedOutputBinding{i}` MAY be any field element, including `0`.

These fields are authenticated directly as inputs to `transactionIntentDigest` in Section 9.11.

Then enforce per slot:

* If `executionConstraintsFlags &amp; LOCK_OUTPUT_BINDING_0 != 0`, then `lockedOutputBinding0 == outputBinding_0`.
* If `executionConstraintsFlags &amp; LOCK_OUTPUT_BINDING_0 == 0`, then `lockedOutputBinding0 == 0`.
* If `executionConstraintsFlags &amp; LOCK_OUTPUT_BINDING_1 != 0`, then `lockedOutputBinding1 == outputBinding_1`.
* If `executionConstraintsFlags &amp; LOCK_OUTPUT_BINDING_1 == 0`, then `lockedOutputBinding1 == 0`.
* If `executionConstraintsFlags &amp; LOCK_OUTPUT_BINDING_2 != 0`, then `lockedOutputBinding2 == outputBinding_2`.
* If `executionConstraintsFlags &amp; LOCK_OUTPUT_BINDING_2 == 0`, then `lockedOutputBinding2 == 0`.

This gives two valid proving modes:

* **Unconstrained mode**: no output-binding locks are set; finalized outputs remain prover-discretionary subject to the rest of the proof relation.
* **Finalized-authorization mode**: one or more output-binding locks are set; the signer fixes those slots&apos; emitted note commitments and payload hashes before proving.

### 10. Public Inputs

The outer verifier&apos;s public-input vector is the 19 fields of `PublicInputs` (Section 5.3), in declaration order.

* `noteCommitmentRoot` — note-commitment-tree root the proof is verified against.
* `nullifier0`, `nullifier1` — input note nullifiers. `nullifier1` is phantom when unused.
* `noteCommitment0`, `noteCommitment1`, `noteCommitment2` — output note commitments. `noteCommitment0` is the primary user-facing output note, `noteCommitment1` is sender change or dummy, and `noteCommitment2` is a fee note or dummy.
* `publicAmountIn` — tokens entering the shielded state (deposits); 0 otherwise.
* `publicAmountOut` — tokens leaving the shielded state (withdrawals); 0 otherwise.
* `publicRecipientAddress` — withdrawal destination address; 0 for deposits and transfers.
* `publicTokenAddress` — token being transacted (0 for ETH); 0 for transfers.
* `depositorAddress` — depositor&apos;s Ethereum address (deposits); 0 for transfers/withdrawals.
* `transactionReplayId` — replay protection.
* `registryRoot` — user registry root. MUST be nonzero.
* `validUntilSeconds` — intent expiry timestamp. MUST be &gt; 0 and &lt; `2^32` for all operation modes.
* `executionChainId` — verified by the contract against `block.chainid` (Section 5.4, step 2). Defense-in-depth against cross-chain proof replay.
* `authPolicyRegistryRoot` — auth policy registry root. MUST be nonzero for all operation modes.
* `outputNoteDataHash0` — `uint256(keccak256(outputNoteData0)) % p`. Binds the first output&apos;s opaque note-delivery payload to the proof.
* `outputNoteDataHash1` — `uint256(keccak256(outputNoteData1)) % p`. Binds the second output&apos;s opaque note-delivery payload to the proof.
* `outputNoteDataHash2` — `uint256(keccak256(outputNoteData2)) % p`. Binds the third output&apos;s opaque note-delivery payload to the proof.

`publicAmountIn` and `publicAmountOut` apply to the token specified by `publicTokenAddress`. For transfers, all three are zero.

`originMode`, `executionConstraintsFlags`, `lockedOutputBinding0`, `lockedOutputBinding1`, `lockedOutputBinding2`, `nonce`, and `transactionIntentDigest` are not public inputs. They are private signed/authenticated values checked inside the recursive proof relation.

#### 10.1 Canonical Field Element Validation

The verifier MUST reject any public input that is not a canonical field element (i.e., `&gt;= p`, the SNARK field modulus). Without this, `x` and `x + p` would verify identically but map to different `uint256` keys in contract storage, enabling nullifier reuse or intent replay.

### 11. Precompile

#### 11.1 Proof Verification

The precompile verifies UltraHonk BN254 proofs for the fork-defined outer circuit. The canonical outer verification-key encoding is pinned by [`outer_vk.bin`](/EIPs/assets/eip-8182/outer_vk.bin), [`outer_vk.sha256`](/EIPs/assets/eip-8182/outer_vk.sha256), and [`outer_vk.bb_hash.hex`](/EIPs/assets/eip-8182/outer_vk.bb_hash.hex). The canonical outer proof byte encoding and verifier-specific metadata required to interpret that proof are pinned by [`outer_verifier_metadata.json`](/EIPs/assets/eip-8182/outer_verifier_metadata.json) together with [`outer_verifier_transcript_vk_hash.hex`](/EIPs/assets/eip-8182/outer_verifier_transcript_vk_hash.hex).

* Address: `PROOF_VERIFY_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000000030`
* Input: `abi.encode(bytes proof, PublicInputs publicInputs)` — the struct fields are ABI-encoded as 19 consecutive `uint256` values in declaration order. The pool-facing ABI supplies exactly those 19 public inputs. Any verifier-internal scalars carried inside the proof are not additional pool ABI inputs.
* Output: 32 bytes — `uint256(1)` on success, empty on failure.
* Gas: `1_000_000`. This is derived from the reference verifier benchmark, which measured `3,683,435` gas.
* Error: malformed input or verification failure returns empty.

### 12. Origin Tags

Every note MUST carry an `originTag` field. A note with `originTag != 0` is origin-tagged: the tag traces the note back to one originating deposit and can support later app-defined origin proofs. A note with `originTag == 0` is not origin-tagged. Origin tags are enforced by the circuit; they cannot be forged.

#### 12.1 Deposit Origin Tag

In deposit mode, real output origin tags MUST be determined by `originMode`:

* If `originMode == ORIGIN_MODE_DEFAULT`, every real output note MUST use `originTag = 0`.
* If `originMode == ORIGIN_MODE_REQUIRE_TAGGED`, every real output note MUST use:

```
originTag = poseidon(
  ORIGIN_TAG_DOMAIN,
  executionChainId,
  depositorAddress,
  tokenAddress,
  publicAmountIn,
  transactionReplayId
)
```

  If the derived `originTag` is `0`, the proof MUST fail.

`publicAmountIn` is the total public deposit amount, not individual output note amounts.

`executionChainId` (= `block.chainid`) prevents cross-chain origin-tag collisions. `transactionReplayId` is unique per transaction and known at proof generation time.

#### 12.2 Origin Tag Propagation

* **One real input** (one phantom): real output notes MUST inherit the real input&apos;s `originTag`.
* **Two real inputs, same `originTag`**: real output notes MUST inherit that `originTag`.
* **Two real inputs, different `originTag` values**: all real output notes MUST use `originTag = 0`. The simple origin-proof path is lost at the protocol level.
* **Both inputs phantom** (deposit mode): real output notes use the origin tags required by Section 12.1.

Dummy outputs are not covered by these propagation rules and remain `originTag = 0` per Section 9.5.

### 13. Poseidon Hash Contexts

| Context | Inputs (in order) | Arity |
|---------|-------------------|-------|
| Note commitment | `amount, ownerAddress, noteSecret, ownerNullifierKeyHash, tokenAddress, originTag` | 6 |
| Nullifier | `NOTE_NULLIFIER_DOMAIN, ownerNullifierKey, noteSecret` | 3 |
| Phantom nullifier | `PHANTOM_NULLIFIER_DOMAIN, ownerNullifierKey, transactionReplayId, inputIndex` | 4 |
| Owner nullifier key hash | `OWNER_NULLIFIER_KEY_HASH_DOMAIN, ownerNullifierKey` | 2 |
| Note secret seed hash | `NOTE_SECRET_SEED_DOMAIN, noteSecretSeed` | 2 |
| Note secret | `NOTE_SECRET_DOMAIN, noteSecretSeed, transactionReplayId, outputIndex` | 4 |
| Transaction replay ID (all modes) | `TRANSACTION_REPLAY_ID_DOMAIN, ownerNullifierKey, authorizingAddress, executionChainId, nonce` | 5 |
| Transaction intent digest | `TRANSACTION_INTENT_DIGEST_DOMAIN, policyVersion, authorizingAddress, operationKind, tokenAddress, recipientAddress, amount, feeRecipientAddress, feeAmount, originMode, executionConstraintsFlags, lockedOutputBinding0, lockedOutputBinding1, lockedOutputBinding2, nonce, validUntilSeconds, executionChainId` | 17 |
| Output binding | `OUTPUT_BINDING_DOMAIN, noteCommitment, outputNoteDataHash` | 3 |
| Auth policy key (truncated to 160 bits) | `AUTH_POLICY_KEY_DOMAIN, authorizingAddress, innerVkHash` | 3 |
| Auth policy leaf | `AUTH_POLICY_DOMAIN, authDataCommitment, policyVersion` | 3 |
| Inner VK hash | `poseidon(AUTH_VK_DOMAIN, 115)`; `poseidon(vk[0], vk[1])`, ..., `poseidon(vk[112], vk[113])`; final odd word `vk[114]`; then binary-tree fold with `poseidon(left, right)` | 115-word VK |
| Deposit origin tag | `ORIGIN_TAG_DOMAIN, executionChainId, depositorAddress, tokenAddress, publicAmountIn, transactionReplayId` | 6 |
| User registry leaf | `USER_REGISTRY_LEAF_DOMAIN, uint160(user), ownerNullifierKeyHash, noteSecretSeedHash` | 4 |
| Merkle tree node | `left, right` | 2 |

The Merkle tree node row uses `hash_2(left, right)` directly — not the arity-prefixed `poseidon(...)` construction (Section 3.3). All other rows use the arity-prefixed form. The canonical inner-verification-key encoding and `innerVkHash` fixture are pinned in Section 9.1.

### 14. Example Single-Circuit ECDSA Companion Standard (Non-Normative)

This section sketches an example single-circuit inner circuit for ECDSA/secp256k1 authorization using [EIP-712](/EIPs/EIPS/eip-712) typed data signing.

The user signs an EIP-712 typed struct containing the example circuit&apos;s intent fields:

```
ShieldedPoolAuthorization(
    uint256 policyVersion,
    uint8   operationKind,
    address tokenAddress,
    address recipientAddress,
    uint256 amount,
    address feeRecipientAddress,
    uint256 feeAmount,
    uint8   originMode,
    uint256 nonce,
    uint32  validUntilSeconds
)
```

EIP-712 domain:

```text
{ name: &quot;EIP-8182 Shielded Pool&quot;, version: &quot;1&quot;, chainId: &lt;executionChainId&gt;, verifyingContract: &lt;poolAddress&gt; }
```

In this example companion standard, the domain binds `executionChainId` and `poolAddress` without repeating them in the struct. This is intentionally a single-circuit companion-standard example, not a general protocol-level mechanism for binding a signed authorization to the actual `innerVkHash` selected by the outer circuit. Companion standards that span multiple inner circuits still need to specify how they satisfy the cross-circuit invalidation requirement from Section 6.4. The actual `innerVkHash` used by the outer circuit is computed from `innerVkey` per Section 9.1.

The inner circuit:

1. Computes the EIP-712 signing hash from the struct and domain.
2. Verifies the ECDSA signature against the provided secp256k1 public key `(ecdsaPubKeyX, ecdsaPubKeyY)`, where each coordinate is encoded as an exact 32-byte big-endian value, and derives `authorizingAddress` via `keccak256(ecdsaPubKeyX || ecdsaPubKeyY)[12:]`.
3. Reads the intent fields directly from the struct, takes `executionChainId` and `poolAddress` from the EIP-712 domain, and enforces `poolAddress == SHIELDED_POOL_ADDRESS`.
4. Enforces `nonce &lt; p`.
5. Fixes the execution constraints to the unconstrained values `executionConstraintsFlags = 0`, `lockedOutputBinding0 = 0`, `lockedOutputBinding1 = 0`, and `lockedOutputBinding2 = 0`, then computes `transactionIntentDigest` per Section 9.11 using `executionChainId`, the derived `authorizingAddress`, the signed `policyVersion`, and those fixed values.
6. Outputs `[authDataCommitment, transactionIntentDigest]` where `authDataCommitment = poseidon(xHi, xLo, yHi, yLo)`, with `(xHi, xLo)` and `(yHi, yLo)` the first and last 16 bytes of those same 32-byte encodings interpreted as big-endian `uint128` values. This is the value registered in `registerAuthPolicy` for this example inner circuit.

### 15. Output Note Data and Delivery Keys

`outputNoteData0`, `outputNoteData1`, and `outputNoteData2` are opaque bytes emitted alongside the three output note commitments in `ShieldedPoolTransact`. The contract verifies only the hash binding (Section 9.7) and MUST NOT decode or validate payload contents. When a signer sets an output-binding lock for a slot, Section 9.12 binds that slot&apos;s payload hash to its emitted note commitment; otherwise payload choice remains prover-discretionary.

When using the delivery-key registry, the party constructing `outputNoteData` for a recipient looks up the recipient&apos;s active registered delivery endpoint via `getDeliveryKey(recipient)`. In first-party proving this is the wallet or user software; in delegated proving it is typically the prover. The sender/prover then constructs payload bytes according to the selected delivery scheme. Notes MAY also be delivered using out-of-band coordination.

The protocol does not require `outputNoteData` to carry a scheme tag or version. Recipients MAY therefore need to attempt recovery with their current delivery private key and any retained prior delivery keys and supported schemes.

Implementations SHOULD use constant-size real and dummy payloads within each supported scheme to reduce structural leakage.

#### 15.1 Scheme IDs and Support Requirements

The delivery-key registry uses the following scheme-ID namespace:

* `0` — unset / invalid
* `1` — X-Wing (`X25519` + `ML-KEM-768` hybrid KEM)
* all other nonzero values — reserved for future assignment or private use

Implementations claiming general interoperability with this EIP MUST support scheme `1`. They MAY support additional schemes.

The contract MUST accept any nonzero `schemeId` in `setDeliveryKey`; it does not maintain an on-chain allowlist and MUST NOT validate that `keyBytes` are well-formed for the selected scheme. A user can therefore publish malformed key material and break their own receive path.

#### 15.2 Scheme 1: X-Wing (`X25519` + `ML-KEM-768`)

For scheme `1`, `keyBytes` MUST be a raw 1216-byte X-Wing encapsulation key: the 1184-byte `ML-KEM-768` encapsulation key followed by the 32-byte `X25519` public key. This EIP pins the X-Wing KEM to `draft-connolly-cfrg-xwing-kem-10`, including key generation, encapsulation, decapsulation, and combiner behavior. Scheme `1` is frozen by that draft revision plus the normative vectors in [the scheme 1 vector asset](/EIPs/assets/eip-8182/delivery_scheme1_vectors.json); later IETF changes do not alter EIP-8182 scheme `1`.

The plaintext is the six note fields in note-commitment order, each encoded as a 32-byte big-endian word:

```
amount || ownerAddress || noteSecret || ownerNullifierKeyHash || tokenAddress || originTag
```

Address fields are the corresponding `uint160` values left-padded to 32 bytes.

`outputNoteData` for scheme `1` MUST be exactly 1328 bytes and encoded as `enc || ciphertext || tag`, where:

* `enc` is the first 1120 bytes and is the raw X-Wing ciphertext: the 1088-byte `ML-KEM-768` encapsulation ciphertext followed by the 32-byte `X25519` ephemeral public key
* `ciphertext` is the next 192 bytes and is the AES-256-GCM ciphertext of the 192-byte plaintext above
* `tag` is the final 16 bytes and is the AES-256-GCM authentication tag

The sender/prover encapsulates to the registered X-Wing public key, obtaining `enc` plus the 32-byte X-Wing shared secret, and then derives the AEAD key and nonce from that shared secret with `HKDF-SHA256`:

```
prk = HKDF-Extract(&quot;&quot;, sharedSecret)
aeadKey = HKDF-Expand(prk, &quot;EIP-8182-delivery-scheme-1 key&quot;, 32)
nonce = HKDF-Expand(prk, &quot;EIP-8182-delivery-scheme-1 nonce&quot;, 12)
```

Empty associated data.

The recipient decapsulates `enc` with the corresponding X-Wing private key, derives the same AEAD key and nonce, verifies `tag`, decrypts `ciphertext`, recomputes the note commitment, and MUST reject on mismatch.

#### 15.3 Additional Schemes

Additional nonzero scheme IDs MAY be assigned by later standards. Such standards define the meaning of `keyBytes` and any payload interpretation for their assigned IDs.

When output slot 2 is used for fee compensation, the actual recipient of that note — whether designated by `feeRecipientAddress` or chosen by the prover when `feeRecipientAddress == 0` — SHOULD receive enough offchain fee-note data to recompute `noteCommitment2` before broadcasting the transaction. Because the protocol does not validate payload semantics, a fee recipient cannot safely rely on opaque `outputNoteData2` bytes alone as proof of payment.

## Rationale

### System Contract, Fork-Managed Outer Circuit, and No Admin Pause

A bug in the ZK scheme can compromise funds held in the pool but does not alter consensus rules, the validator set, or ETH supply semantics. Native integration (e.g., [EIP-7503](/EIPs/EIPS/eip-7503)) can expose the protocol itself to ZK-scheme failures, including unbounded minting. The ZK-scheme risk to depositors is equivalent to existing app-level pools.

A malicious outer verification key could drain the entire pool, so outer circuit upgrades require the same social consensus as any other protocol change. Inner circuits are permissionless because the outer circuit independently enforces all pool-critical invariants.

A deposit-only pause triggered by a consensus-layer flag was considered and rejected. Any pause trigger reintroduces a governance surface; a withdrawal freeze during a false alarm locks user funds pending a hard fork to unpause. The scope of a soundness exploit (pool-held funds only, not protocol consensus) makes the hard-fork remediation timeline acceptable relative to the governance risk of a pause mechanism.

### Recursive Composition

Recursion separates pool-critical logic (outer circuit, fork-managed) from spend authorization (inner circuits, user-scoped; registry lifecycle operations remain address-gated). This enables permissionless auth extensibility: new signature schemes deploy as inner circuits without a hard fork. A malicious inner circuit can only risk the registering user&apos;s funds, not the pool, because the outer circuit independently enforces value conservation, nullifiers, deterministic note-secret derivation, and auth-policy checks — in practice, adding a new auth method is one `registerAuthPolicy` call with no fund transfers, no new addresses, and no anonymity set fragmentation. Existing auth methods remain active; unwanted methods can be deregistered (Section 6.4). The proving overhead vs a monolithic circuit is the cost of these properties. Decoupling the signed authorization format from the protocol lets inner circuits evolve their signing formats independently, without coordination or a protocol change.

### Specialized Proving and Wallet Compatibility

First-party proving is feasible today on commodity hardware — end-to-end proving takes ~20s with ~8 GB peak memory on desktop hardware (16 threads; Noir v1.0.0-beta.19 + Barretenberg 4.0.4). The protocol does not require specialized hardware for users who want to keep proof generation within infrastructure they control.

The protocol supports non-custodial proof delegation: a user can outsource proof generation to a third party without outsourcing spending authority. The prover cannot steal funds, redirect payments, or forge unauthorized transactions. Rotating `noteSecretSeed` cuts off a former prover&apos;s ability to derive future note secrets for that address. Because note delivery is not coupled to the proof system, delivery schemes can evolve without changing the proof relation.

### Optional Origin Tracking

Not every private transfer should carry origin information by default. This EIP therefore keeps origin tracking opt-in: deposits create untagged notes unless the signer explicitly requests origin-tagged outputs. When a signer does request origin-tagged outputs, `originMode` lets them require tagged-origin handling without binding exact input-note selection or an exact `originTag` value.

Origin-tagged notes are compatible with later app-defined origin proofs, including association-set-style proofs defined outside this EIP. This EIP standardizes the origin primitive itself, not the external set-provider ecosystem or proof format.

### Finalized Output Binding

`outputBinding = poseidon(OUTPUT_BINDING_DOMAIN, noteCommitment, outputNoteDataHash)` binds one emitted note commitment to one output-note-data hash. Execution constraints use this binding to lock finalized output slots.

### Hybrid Delivery Baseline

No classical-only interoperable delivery scheme is defined. The baseline receive path uses the X-Wing `X25519` + `ML-KEM-768` hybrid KEM to avoid steering users toward note-delivery ciphertexts with known harvest-now-decrypt-later exposure while also hedging against failures in the post-quantum component. This choice is limited to note delivery; it does not make the overall protocol post-quantum.

### Private Fee Compensation

The system contract charges no protocol-level fee. The protocol&apos;s mandatory onchain cost is Ethereum gas. Prover or broadcaster compensation, if any, is optional and user-authorized via output slot 2 rather than imposed by the pool.

Private transfers need a way to compensate a broadcaster or sponsor without revealing the transferred token on-chain. A public fee output would leak the asset for shielded transfers, so this EIP reserves output slot 2 for an optional private fee note. If `feeRecipientAddress` is nonzero, the user designates the fee recipient in the signed intent. If `feeRecipientAddress` is zero and `feeAmount &gt; 0`, the prover chooses output slot 2&apos;s owner at proof generation time, but that choice is still fixed by the resulting proof and cannot be changed at broadcast time. Keeping fee compensation inside the same note model also makes the design compatible with both legacy transactions and future transaction types that separate sender from gas payer: the transaction layer can decide who submits and who pays gas, while the pool continues to express compensation as an ordinary shielded note in the transferred asset.

### Transaction-Time Auth-Method Anonymity

`innerVkHash`, `authDataCommitment`, and `policyVersion` are private inputs, never exposed as public inputs in `transact`. See Section 4 for the full auth-method anonymity model.

### UTXO-Based Notes over Account-Based Encrypted Balances

Account-based encrypted balances reveal access patterns — which accounts transact and how frequently — even when amounts are hidden. UTXO-based notes avoid this: spending a note produces new commitments, and shielded transfers within the pool reveal nothing about amounts, tokens, or counterparties on-chain.

## Backwards Compatibility

This EIP introduces new functionality via a system contract and precompiles and requires a network upgrade (hard fork). It does not change the meaning of existing transactions or contracts. No backward compatibility issues are known.

## Test Cases

Normative fixture assets for this EIP are included below. Implementations claiming conformance MUST match the pinned constants and vectors in at least the following asset families:

* Poseidon constants and vectors: [`poseidon_bn254_t3_rf8_rp57.json`](/EIPs/assets/eip-8182/poseidon_bn254_t3_rf8_rp57.json) and [`poseidon_vectors.json`](/EIPs/assets/eip-8182/poseidon_vectors.json)
* Shielded-pool activation state: [`shielded-pool-state.json`](/EIPs/assets/eip-8182/shielded-pool-state.json)
* External Poseidon library runtime prerequisite: [`poseidon_t3_runtime.hex`](/EIPs/assets/eip-8182/poseidon_t3_runtime.hex)
* Outer verifier pin set: [`outer_vk.bin`](/EIPs/assets/eip-8182/outer_vk.bin), [`outer_vk.sha256`](/EIPs/assets/eip-8182/outer_vk.sha256), [`outer_vk.bb_hash.hex`](/EIPs/assets/eip-8182/outer_vk.bb_hash.hex), [`outer_verifier_transcript_vk_hash.hex`](/EIPs/assets/eip-8182/outer_verifier_transcript_vk_hash.hex), and [`outer_verifier_metadata.json`](/EIPs/assets/eip-8182/outer_verifier_metadata.json)
* Delivery scheme `1` vectors: [`delivery_scheme1_vectors.json`](/EIPs/assets/eip-8182/delivery_scheme1_vectors.json)

Implementations MUST additionally test at least the following consensus-critical accept/reject families:

* malformed proof bytes or wrong proof-length rejection
* non-canonical field-element rejection
* address and amount range rejection
* root-history boundary acceptance and rejection
* auth-policy rejection when `innerVkHash` is computed incorrectly or does not match the auth-policy key proven in the outer circuit
* dummy-output constraint failures
* deposit outputs use `originTag = 0` when `originMode = ORIGIN_MODE_DEFAULT`
* deposit outputs use the derived nonzero origin tag when `originMode = ORIGIN_MODE_REQUIRE_TAGGED`
* deposit with `originMode = ORIGIN_MODE_REQUIRE_TAGGED` rejects if the derived origin tag is `0`
* one-input spends preserve the input `originTag`
* two-input spends preserve `originTag` when both real inputs carry the same value
* two-input spends clear `originTag` to `0` when real inputs carry different values
* tagged + untagged real inputs clear `originTag` to `0` when `originMode = ORIGIN_MODE_DEFAULT`
* full withdrawal with `originMode = ORIGIN_MODE_REQUIRE_TAGGED` accepts only when the real inputs share one nonzero `originTag`
* origin-tag preservation rejection when `originMode = ORIGIN_MODE_REQUIRE_TAGGED`
* reserved-flag-bit rejection
* locked-slot mismatch rejection

Implementations SHOULD additionally test tree-capacity failure at the depth-32 note-commitment-tree boundary.

Implementations SHOULD also test the finalized-output-binding and nonce-replay cases:

* changing only execution constraints changes `transactionIntentDigest` but not `transactionReplayId`
* reusing the same nonce across otherwise distinct authorizations yields the same `transactionReplayId`
* fresh nonce changes both `transactionIntentDigest` and `transactionReplayId` when all other fields remain the same
* a locked slot succeeds when `lockedOutputBinding{i} == poseidon(OUTPUT_BINDING_DOMAIN, noteCommitment_i, outputNoteDataHash_i)`
* a locked slot fails if `noteCommitment_i` changes while `outputNoteDataHash_i` stays fixed
* a locked slot fails if `outputNoteDataHash_i` changes while `noteCommitment_i` stays fixed
* an unlocked slot accepts `lockedOutputBinding{i} = 0` without requiring equality to `poseidon(OUTPUT_BINDING_DOMAIN, noteCommitment_i, outputNoteDataHash_i)`

## Security Considerations

### Multi-Auth Security Boundary

Every active `(address, innerVkHash)` pair is an independent spend-authorization path for the same notes (Section 6.4). Registering a weak inner circuit alongside a strong one widens the attack surface, but spending still also requires custody of `ownerNullifierKey`, the current `noteSecretSeed` accepted by the user-registry root, and the relevant proving material. Users SHOULD deregister auth methods they no longer trust via `deregisterAuthPolicy` (Section 5.3). Deactivation is bounded-delay — the old root remains valid for `AUTH_POLICY_ROOT_HISTORY_BLOCKS` blocks.

### DoS via Root History

Prolonged congestion can cause proofs against stale roots to fail before submission. The note-commitment root history is a fixed-size circular buffer (`NOTE_COMMITMENT_ROOT_HISTORY_SIZE` entries) that advances on every `transact`; the user and auth policy registries use block-based windows (`USER_REGISTRY_ROOT_HISTORY_BLOCKS` and `AUTH_POLICY_ROOT_HISTORY_BLOCKS` respectively) where history entries are recorded on mutation and acceptance expires as blocks advance. Under sustained high throughput the note-commitment buffer is the binding constraint — users must submit proofs before the buffer wraps past their proven root.

### Metadata Leakage

Deposits and withdrawals are public by design. Shielded transfer token and amount are private, but network-level metadata (timing, gas patterns, relayer behavior, transaction size) can still leak information. The constant 2-input/3-output shape with phantom/dummy slots mitigates some structural metadata leakage while reserving a fixed slot for optional fee compensation.

### State Growth

The pool accumulates append-only state for note commitments, nullifiers, and transaction replay IDs. This is the main state-growth cost of the design relative to overwrite-in-place balance models: these values cannot be safely pruned without breaking spend or replay protection. All pool state, including this append-only state, is ordinary Ethereum contract state and remains subject to Ethereum&apos;s general gas pricing and state-management trajectory.

### Output Note Data Leakage

Empty or variable-size dummy payloads can leak which outputs are real. See Section 15 for payload guidance.

### Auth Policy Registry Liveness

The block-based aging rule (at most one root history entry per block) prevents same-block churn from burning multiple history slots. An attacker making many `registerAuthPolicy` calls within a single block consumes at most one slot. However, an attacker can still churn across blocks by making a registration in every block over the window, filling the history with attacker-controlled roots. The buffer length bounds the cost of this attack — `AUTH_POLICY_ROOT_HISTORY_BLOCKS` blocks of sustained registrations. The buffer size is consensus-critical and stays fixed in this specification to prevent post-deployment changes that could shrink the revocation window.

This same history rule also creates a same-block liveness footgun for honest users: if a user updates a registry entry and later same-block mutations occur before `transact`, the intermediate root they proved against may no longer be preserved in history. Wallets and provers SHOULD prefer waiting at least one subsequent block after registry lifecycle changes unless they control ordering.

### Third-Party Prover Residual Visibility

A third-party prover permanently learns `ownerNullifierKey` and can monitor spends of previously known notes indefinitely. It also learns the current `noteSecretSeed`; rotating it via `rotateNoteSecretSeed` cuts off future note-secret derivation after stale user roots expire. `noteSecretSeed` compromise alone is recoverable through rotation. If `ownerNullifierKey` is compromised, users can mitigate by rotating `noteSecretSeed` and auth methods.

### Origin-Tagged Note Visibility

Origin tags are private from on-chain observers, but they are part of the note material available to note holders and to any prover that receives the note witness. A holder of an origin-tagged note, or a third-party prover helping spend it, may correlate that note to its originating deposit. This is intentional: origin-tagged notes exist to support later app-defined origin proofs. Users that do not need that capability SHOULD prefer untagged notes.

### Third-Party Prover Origin Discretion

Because coin selection is delegated, a third-party prover can intentionally choose inputs that clear origin tags and remove the simple origin-proof path without violating payment semantics. This discretion is partially constrainable: when the signer sets `originMode = ORIGIN_MODE_REQUIRE_TAGGED`, proofs fail unless transfer/withdrawal mode uses real inputs with one shared nonzero `originTag` and any real outputs remain origin-tagged.

### Third-Party Prover Delivery Sabotage

If the signer leaves output-binding locks unset, a remote prover with full witness can still emit unusable `outputNoteData` or otherwise mutate unlocked finalized outputs while producing a valid proof. This cannot steal funds or redirect payment, but it can make note recovery fail. If the signer sets an output-binding lock for a slot, the prover cannot change that slot&apos;s emitted note commitment or payload bytes after signing. This protects finalized-authorization flows only; it does not protect a blind signer from a malicious coordinator that assembled a bad finalized plan before signing. Additional higher-assurance mitigations include wallet-controlled finalization/broadcast, TEE-attested proving, MPC or witness-splitting systems that prevent any one prover from constructing an alternate proof, or future companion standards for richer authenticated execution binding. These mitigations are not standardized by this EIP.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 03 Mar 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8182</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8182</guid>
      </item>
    
      <item>
        <title>Agentic Commerce</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8183-agentic-commerce/27902</comments>
        
        <description>## Abstract

This specification defines the **Agentic Commerce Protocol**: a **job** with escrowed budget, four states (Open → Funded → Submitted → Terminal), and an **evaluator** who alone may mark the job completed. The client funds the job; the provider submits work; the evaluator attests completion or rejection once submitted (or the evaluator rejects while Funded before submission, or the client rejects while Open, or the job expires and the client is refunded). Optional attestation **reason** (e.g. hash) on complete/reject enables audit and composition with reputation (e.g. [ERC-8004](/EIPs/EIPS/eip-8004)).

## Motivation

Many use cases need only: client locks funds, provider submits work, one attester (evaluator) signals &quot;done&quot; and triggers payment—or client rejects or timeout triggers refund. The Agentic Commerce Protocol specifies that minimal surface so implementations stay small and composable. The evaluator can be the client (e.g. `evaluator = client` at creation) when there is no third-party attester.

## Specification

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

### State Machine

A **job** has exactly one of six states:


| State         | Meaning                                                                                                           |
| ------------- | ----------------------------------------------------------------------------------------------------------------- |
| **Open**      | Created; budget not yet set or not yet funded. Client may set budget, then fund or reject.                        |
| **Funded**    | Budget escrowed. Provider may submit work; evaluator may reject. After `expiredAt`, anyone may trigger refund.    |
| **Submitted** | Provider has submitted work. Only evaluator may complete or reject. After `expiredAt`, anyone may trigger refund. |
| **Completed** | Terminal. Escrow released to provider (minus optional platform fee).                                              |
| **Rejected**  | Terminal. Escrow refunded to client.                                                                              |
| **Expired**   | Terminal. Same as Rejected; escrow refunded to client.                                                            |


Allowed transitions:

- **Open → Funded**: Client or provider calls `setBudget(jobId, amount)` to agree on price, then client calls `fund(jobId, expectedBudget)`; contract pulls `job.budget` from client into escrow.
- **Open → Rejected**: Client calls `reject(jobId, reason?)`.
- **Funded → Submitted**: Provider calls `submit(jobId, deliverable)`; signals that work has been completed and is ready for evaluation.
- **Funded → Rejected**: Evaluator calls `reject(jobId, reason?)`; contract refunds client.
- **Funded → Expired**: When `block.timestamp &gt;= job.expiredAt`, anyone (or client) may call `claimRefund(jobId)`; contract sets state to Expired and refunds client.
- **Submitted → Completed**: Evaluator calls `complete(jobId, reason?)`; contract distributes escrow to provider (and optional fee to treasury).
- **Submitted → Rejected**: Evaluator calls `reject(jobId, reason?)`; contract refunds client.
- **Submitted → Expired**: When `block.timestamp &gt;= job.expiredAt`, anyone (or client) may call `claimRefund(jobId)`; contract sets state to Expired and refunds client.

No other transitions are valid.

### Roles

- **Client**: Creates job (with description), may set provider via `setProvider(jobId, provider)` when job was created with no provider, sets budget with `setBudget(jobId, amount)`, funds escrow with `fund(jobId, expectedBudget)`, may reject **only when status is Open**. Receives refund on Rejected/Expired.
- **Provider**: Set at creation or later via `setProvider`. May call `setBudget(jobId, amount)` to propose or negotiate a price. Calls `submit(jobId, deliverable)` when work is done to move the job from Funded to Submitted for evaluation. Receives payment when job is Completed. Does not call `complete` or `reject`.
- **Evaluator**: Single address per job, set at creation. When status is Submitted, **only** the evaluator MAY call `complete(jobId, reason?)` or `reject(jobId, reason?)`. When status is Funded, the evaluator MAY call `reject(jobId, reason?)` (before submission). MAY be the client (e.g. `evaluator = client`) so the client can complete or reject the job without a third party, or MAY be a **smart contract** that performs arbitrary checks (e.g. verifying a zero‑knowledge proof or aggregating off‑chain signals) before deciding whether to call `complete` or `reject` on the job.

### Job Data

Each job SHALL have at least:

- `client`, `provider`, `evaluator` (addresses). **Provider MAY be zero at creation** (see Optional provider below).
- `description` (string) — set at creation (e.g. job brief, scope reference).
- `budget` (uint256)
- `expiredAt` (uint256 timestamp)
- `status` (Open | Funded | Submitted | Completed | Rejected | Expired)
- `hook` (address) — OPTIONAL. External hook contract called before and after core functions (see Hooks below). MAY be `address(0)` (no hook).

Payment SHALL use a single [ERC-20](/EIPs/EIPS/eip-20) token (global for the contract or specified at creation). Implementations MAY support a per-job token; the specification only requires one token per contract.

### Optional provider (set later)

Jobs MAY be created **without a provider** by passing `provider = address(0)` to `createJob`. In that case the client SHALL set the provider later via `setProvider(jobId, provider)` before funding. This supports flows such as bidding or assignment after creation.

- **setProvider(jobId, provider)**  
Called by **client** only. SHALL revert if job is not Open, current `job.provider != address(0)`, or `provider == address(0)`. SHALL set `job.provider = provider` and SHALL emit an event (e.g. ProviderSet). Implementations MAY allow an operator role to call setProvider in the future; this specification only requires client-only for the minimal protocol.
- **fund(jobId, expectedBudget)**
SHALL revert if `job.provider == address(0)` (provider MUST be set before funding) or if `job.budget != expectedBudget` (front-running protection).

### Core Functions

- **createJob(provider, evaluator, expiredAt, description, hook?)**
Called by client. Creates job in Open with `client = msg.sender`, `provider`, `evaluator`, `expiredAt`, `description`, and optional `hook` address. SHALL revert if `evaluator` is zero or `expiredAt` is not in the future. **Provider MAY be zero**; if so, client MUST call `setProvider` before `fund`. `hook` MAY be `address(0)` (no hook). Returns `jobId`.
- **setProvider(jobId, provider, optParams?)**
Called by client. SHALL revert if job is not Open, current `job.provider != address(0)`, or `provider == address(0)`. SHALL set `job.provider = provider`. `optParams` (bytes, OPTIONAL) is forwarded to the hook contract if set (see Hooks).
- **setBudget(jobId, amount, optParams?)**
Called by client or provider. Sets `job.budget = amount`. SHALL revert if job is not Open or caller is not client or provider. `optParams` forwarded to hook if set.
- **fund(jobId, expectedBudget, optParams?)**
Called by client. SHALL revert if job is not Open, caller is not client, budget is zero, **provider is not set** (`job.provider == address(0)`), or `job.budget != expectedBudget` (front-running protection). SHALL transfer `job.budget` of the payment token from client to the contract (escrow) and set status to Funded. `optParams` forwarded to hook if set.
- **submit(jobId, deliverable, optParams?)**
Called by provider only. SHALL revert if job is not Funded or caller is not the job&apos;s provider. SHALL set status to Submitted. `deliverable` (`bytes32`) is a reference to submitted work (e.g. hash of off-chain deliverable, IPFS CID, attestation commitment). SHALL emit an event including `deliverable` (e.g. JobSubmitted). `optParams` forwarded to hook if set.
- **complete(jobId, reason, optParams?)**
Called by evaluator only. SHALL revert if job is not Submitted or caller is not the job&apos;s evaluator. SHALL set status to Completed. SHALL transfer escrowed funds to provider (minus optional platform fee to a configurable treasury). `reason` MAY be `bytes32(0)` or an attestation hash (OPTIONAL). SHALL emit an event including `reason` if provided. `optParams` forwarded to hook if set.
- **reject(jobId, reason, optParams?)**
Called by **client when job is Open** or by **evaluator when job is Funded or Submitted**. SHALL revert if job is not Open, Funded, or Submitted, or caller is not the client (when Open) or the evaluator (when Funded or Submitted). SHALL set status to Rejected. If Funded or Submitted, SHALL refund escrow to client. `reason` OPTIONAL. SHALL emit an event including `reason` and the caller (rejector) if provided. `optParams` forwarded to hook if set.
- **claimRefund(jobId)**
Callable when job is Funded or Submitted and the job has expired (`block.timestamp &gt;= expiredAt`). SHALL revert if job is not Funded or Submitted, or if the job has not yet expired. SHALL transfer full escrow to client and set status to Expired. MAY restrict caller (e.g. client only) or allow anyone; the specification RECOMMENDS allowing anyone to trigger refund after expiry.

### Attestation

- **complete(jobId, reason, optParams?)**: `reason` is an optional attestation commitment (e.g. `bytes32` hash of off-chain evidence). Implementations MAY use `string` and hash it internally. Events SHOULD include `reason` for indexing and composition with reputation systems. `optParams` forwarded to hook if set.
- **reject(jobId, reason, optParams?)**: Optional `reason` for audit; same treatment as above. `optParams` forwarded to hook if set.

### Fees

Implementations MAY charge a **platform fee** (basis points) on Completed, paid to a configurable treasury. The specification does not require a fee. If present, fee SHALL be deducted only on completion (not on refund).

### Hooks (OPTIONAL)

Implementations MAY support an optional **hook contract** per job to extend the core protocol without modifying it. The hook address is set at job creation (or `address(0)` for no hook) and stored on the job. A **non‑hooked kernel** that ignores the `hook` field (or always sets it to `address(0)`) is fully compliant with this specification; the reference `AgenticCommerce` contract follows this minimal pattern, while `AgenticCommerceHooked` is an **extension** that layers the hook callbacks on top of the same lifecycle.

A hook contract SHALL implement the `IACPHook` interface — just two functions:

```solidity
interface IACPHook {
    function beforeAction(uint256 jobId, bytes4 selector, bytes calldata data) external;
    function afterAction(uint256 jobId, bytes4 selector, bytes calldata data) external;
}
```

The `selector` parameter identifies which core function is being called (e.g. the function selector for `fund`). The `data` parameter contains function-specific parameters encoded as bytes (see Data encoding below). The hook uses the selector to route internally:

```solidity
function beforeAction(uint256 jobId, bytes4 selector, bytes calldata data) external {
    if (selector == FUND_SELECTOR) {
        // custom pre-fund logic using data (optParams)
    } else if (selector == COMPLETE_SELECTOR) {
        // custom pre-complete logic using data (reason, optParams)
    }
}
```

When a job has a hook set, the core contract SHALL call `hook.beforeAction(...)` and `hook.afterAction(...)` around each hookable function:

| Core function  | Hookable |
| -------------- | -------- |
| `setProvider`  | Yes      |
| `setBudget`    | Yes      |
| `fund`         | Yes      |
| `submit`       | Yes      |
| `complete`     | Yes      |
| `reject`       | Yes      |
| `claimRefund`  | **No** — permissionless safety mechanism, SHALL NOT be hookable |

#### Data encoding

The `data` parameter passed to hooks contains the core function&apos;s parameters encoded as bytes. The encoding per selector:

| Core function  | `data` encoding                                      |
| -------------- | ---------------------------------------------------- |
| `setProvider`  | `abi.encode(address provider, bytes optParams)`       |
| `setBudget`    | `abi.encode(uint256 amount, bytes optParams)`         |
| `fund`         | `optParams` (raw bytes)                               |
| `submit`       | `abi.encode(bytes32 deliverable, bytes optParams)`    |
| `complete`     | `abi.encode(bytes32 reason, bytes optParams)`         |
| `reject`       | `abi.encode(bytes32 reason, bytes optParams)`         |

#### Hook behaviour

- The `optParams` field (`bytes`, OPTIONAL) on each hookable core function is an opaque payload forwarded to the hook via the `data` parameter. Callers that do not use hooks MAY pass empty bytes. The core contract SHALL NOT interpret `optParams`; it is for the hook only.
- **Before hooks** (`beforeAction`) are called before the core logic executes. A before hook MAY revert to block the action (e.g. enforce custom validation, allowlists, or preconditions).
- **After hooks** (`afterAction`) are called after the core logic completes (including state changes and token transfers). An after hook MAY perform side effects (e.g. emit events, update external state, trigger notifications) or revert to roll back the entire transaction.
- If `job.hook == address(0)`, the core contract SHALL skip hook calls and execute normally.

#### Hook security

- Hooks are **trusted** contracts chosen by the client at job creation. A malicious or buggy hook can revert valid actions or execute arbitrary logic in callbacks. Clients SHOULD audit or use well-known hook implementations.
- **Liveness:** A reverting hook can block all hookable actions for that job until `expiredAt`. This is by design — the hook is part of the job&apos;s policy. The guaranteed recovery path is `claimRefund` after expiry, which is deliberately **not hookable** so that refunds cannot be blocked.
- **Atomicity:** After-callbacks run after state changes but within the same transaction. If an after-callback reverts, the entire transaction (including the core state change) is rolled back. This is intentional — it enables atomic multi-step flows (e.g. escrow funding + side token transfer must both succeed or both revert).
- `onlyACP` modifiers on hooks are RECOMMENDED so that hook functions cannot be called directly by external actors.
- Hooks SHOULD NOT be upgradeable after a job is created, as this would allow the hook to change behaviour mid-job.
- Implementations MAY maintain an allowlist or registry of audited hook contracts to reduce risk for clients.

#### Convenience base contract (non-normative)

Implementations MAY provide a `BaseACPHook` that routes the generic `beforeAction`/`afterAction` calls to named virtual functions (e.g. `_preFund`, `_postComplete`) so hook developers only override what they need. This is NOT part of the standard — only `IACPHook` is normative.

#### Example use cases

- Pre-fund validation (e.g. KYC check, allowlist gate)
- Post-complete reputation updates (e.g. writing attestations to ERC-8004)
- Custom fee logic or payment splitting
- Atomic side transfers (e.g. fund transfer hook)
- Provider bidding (e.g. bidding hook)

---

#### Example 1 — Fund Transfer Hook (two-phase escrow)

**Problem:** A client hires an agent to convert/bridge/swap tokens (e.g. USDC → DAI). The client provides capital to the provider, who uses it to produce output tokens. The hook must ensure the provider deposits the output tokens before the job completes, then release them to the designated buyer.

**Solution:** A `FundTransferHook` that (a) stores a transfer commitment at `setBudget`, (b) forwards capital to the provider at `fund`, (c) pulls output tokens from the provider at `submit`, and (d) releases them to the buyer at `complete`.

```
Step 1 — createJob
  Client → createJob(provider, evaluator, expiredAt, desc, hook=FundTransferHook)
  Job created (Open), hook address stored.

Step 2 — setBudget
  Client → setBudget(jobId, serviceFee, optParams=abi.encode(buyer, transferAmount))
    → hook.beforeAction: decode optParams, store {buyer, transferAmount} as commitment.
    → core: job.budget = serviceFee

Step 3 — fund
  Client approves: core contract for serviceFee, hook for transferAmount.
  Client → fund(jobId, serviceFee, &quot;&quot;)
    → hook.beforeAction: verify client approved hook for transferAmount. Revert if not.
    → core: pull serviceFee into escrow, set Funded.
    → hook.afterAction: pull transferAmount from client, forward to provider (capital).

Step 4 — provider uses capital to produce output tokens

Step 5 — submit
  Provider approves hook for transferAmount (output tokens).
  Provider → submit(jobId, deliverable, &quot;&quot;)
    → hook.beforeAction: pull transferAmount from provider into hook (escrow).
    → core: set Submitted.

Step 6 — complete
  Evaluator → complete(jobId, reason, &quot;&quot;)
    → core: release serviceFee to provider (minus platform fee).
    → hook.afterAction: release transferAmount from hook to buyer.

Recovery:
  - reject: hook.afterAction returns escrowed tokens to provider (if deposited).
  - expiry: claimRefund (not hookable) refunds serviceFee to client.
    Provider calls recoverTokens(jobId) on hook to recover deposited tokens.
```

**Key properties:** (1) The provider cannot submit without depositing output tokens. (2) The buyer only receives tokens when the evaluator completes the job. (3) On rejection or expiry, tokens are returned to the provider.

---

#### Example 2 — Bidding Hook

**Problem:** A client wants to hire the cheapest (or best) agent for a job but does not know upfront who to assign. The selection should be determined by an open bidding process, not unilaterally by the client after the fact.

**Solution:** A `BiddingHook` that verifies off-chain signed bids. Providers sign bid commitments off-chain; the client collects bids, selects the winner, and submits the winning bid&apos;s signature via `setProvider`. The hook&apos;s `beforeAction` callback recovers the signer and verifies it matches the chosen provider — proving the provider actually committed to that price.

Zero direct calls to the hook. All interactions flow through the core contract → hook callbacks.

```
Step 1 — createJob
  Client → createJob(provider=0, evaluator, expiredAt, desc, hook=BiddingHook)
  Job created (Open), provider = address(0).

Step 2 — setBudget (opens bidding via hook callback)
  Client → setBudget(jobId, maxBudget, optParams=abi.encode(biddingDeadline))
    → hook.beforeAction: store deadline for this jobId.

Step 3 — bidding happens OFF-CHAIN
  Providers sign: keccak256(abi.encode(chainId, hookAddress, jobId, bidAmount))
  Client collects signed bids and selects the winner.
  Core contract is unaware of bids.

Step 4 — setProvider + setBudget (hook verifies winning bid signature and enforces budget)
  Client → setProvider(jobId, winnerAddress, optParams=abi.encode(bidAmount, signature))
    → hook.beforeAction: verify deadline passed, recover signer from signature,
      validate signer == provider, store committed bidAmount. Revert if invalid.
    → core: job.provider = winnerAddress
    → hook.afterAction: mark bidding finalised (no further setProvider possible).
  Client → setBudget(jobId, bidAmount, &quot;&quot;)
    → hook.beforeAction: enforce budget == committedAmount. Revert if mismatch.

Step 5 — job continues normally
  Client → fund(jobId, bidAmount, &quot;&quot;)
  Provider → submit(jobId, deliverable, &quot;&quot;)
  Evaluator → complete(jobId, reason, &quot;&quot;)
```

**Key property:** The client cannot fabricate a provider commitment. The hook verifies the chosen provider actually signed a bid at the claimed price. The client is incentivised to pick the lowest bidder since they are the one paying.

---

### Events

Implementations SHOULD emit at least:

- **JobCreated**(jobId, client, provider, evaluator, expiredAt)
- **ProviderSet**(jobId, provider) — when provider is set on a job that was created without one
- **BudgetSet**(jobId, amount)
- **JobFunded**(jobId, client, amount)
- **JobSubmitted**(jobId, provider, deliverable) — when provider submits work for evaluation
- **JobCompleted**(jobId, evaluator, reason)
- **JobRejected**(jobId, rejector, reason)
- **JobExpired**(jobId)
- **PaymentReleased**(jobId, provider, amount)
- **Refunded**(jobId, client, amount)

## Rationale

- **Single attester after submission**: Once Submitted, only the evaluator can complete or reject; the client cannot pull funds back unilaterally, so the provider is protected after starting work. Evaluator = client covers the &quot;no third party&quot; case.
- **Explicit submission**: The Submitted state gives the evaluator (and indexers/UIs) a clear signal that the provider considers work done and ready for evaluation, separating &quot;funded and in progress&quot; from &quot;work delivered&quot;.
- **Minimal surface**: Attestation is the optional `reason` on complete/reject; no additional ledger is required.
- **Four states**: Open, Funded, Submitted, and Terminal (Completed, Rejected, or Expired) are enough for &quot;fund → work → submit → evaluate or refund&quot;.
- **Expiry**: Refund after `expiredAt` gives client a way to reclaim funds without an explicit reject.
- **Hooks over inheritance**: Optional hook contracts let integrators extend the protocol (validation, reputation, fees) without modifying or inheriting from the core contract. The core stays minimal; complexity lives in the hook.
- **Generic hook interface**: The `IACPHook` interface uses just two functions (`beforeAction`/`afterAction`) with a selector parameter rather than named functions per action. This keeps the interface stable as the core protocol evolves — new hookable functions simply produce new selector values without changing the interface.

### Extensions (OPTIONAL)

The following extensions are OPTIONAL and do not modify the core protocol. Implementations MAY adopt them independently.

#### Reputation / Attestation Interop (ERC-8004)
 
Agentic Commerce is intentionally minimal and does not embed a reputation system. For on-chain reputation and trust relationships between agents, implementations are RECOMMENDED to integrate with [ERC-8004](/EIPs/EIPS/eip-8004) (Trustless Agents).

The following patterns are RECOMMENDED:

- **Outcome‑based trust signals**
  - Each job outcome SHOULD be mapped into a trust signal for the participants:
    - `Completed`: positive signal for provider (and optionally evaluator) based on successful delivery.
    - `Rejected`: negative or neutral signal, depending on the reason and who rejected (client vs evaluator).
    - `Expired`: neutral or mildly negative signal for client (for not evaluating) or for provider (for not submitting), depending on higher‑level policy.
  - Implementations MAY emit ERC‑8004 compatible events or call ERC‑8004 registries when a job reaches a terminal state.

- **Evaluator attestations**
  - On `complete(jobId, reason, optParams?)` and `reject(jobId, reason, optParams?)`, the evaluator (which MAY be a contract) SHOULD:
    - produce an attestation or structured log that can be added to the ERC‑8004 **reputation registry** as feedback (e.g. &quot;provider successfully completed job&quot;, &quot;job rejected for reason X&quot;). Attestations MAY reference the job, parties, and `reason` (e.g. a hash of off‑chain evidence).
    - and/or post a proof to the ERC‑8004 **validation registry**, which a hook (or evaluator contract) then reads in order to decide whether to mark the job as `Completed` or `Rejected`.
  - Hooks MAY be used to call into ERC‑8004 registries in `afterAction` for `complete`/`reject`, keeping the core ACP contract unaware of the registry details.

- **Reputation‑aware policy via hooks**
  - Hooks MAY consult ERC‑8004 data before allowing certain actions, for example:
    - preventing `setProvider` from assigning providers below a reputation threshold,
    - enforcing higher budgets or additional safeguards for low‑reputation agents,
    - dynamically selecting evaluators based on reputation.
  - Such checks belong in policy‑oriented `beforeAction` hooks so they can safely revert and block actions that violate reputation policies.

- **Separation of concerns**
  - ACP remains the **payment and escrow** layer; ERC‑8004 is the **identity and reputation** layer.
  - Interop is achieved by:
    - emitting events that ERC‑8004 indexers can consume, and/or
    - calling ERC‑8004 contracts from hooks or evaluator contracts.

---

#### Meta-Transactions / Facilitator Relay ([ERC-2771](/EIPs/EIPS/eip-2771))

To support gasless execution — where a client, provider, or evaluator signs an intent off-chain and a **facilitator** submits the transaction on their behalf — implementations SHOULD support [ERC-2771](/EIPs/EIPS/eip-2771) (Secure Protocol for Native Meta Transactions).

**How it works:**

1. A participant (client, provider, or evaluator) signs a meta-transaction off-chain (e.g. `createJob`, `fund`, `submit`).
2. A facilitator submits the signed payload to a **trusted forwarder** contract.
3. The forwarder verifies the signature and calls the ACP contract, appending the original signer&apos;s address.
4. The ACP contract uses `_msgSender()` (from `ERC2771Context`) instead of `msg.sender` to identify the caller.

**Implementation requirements:**

- The ACP contract SHALL inherit `ERC2771Context` (or equivalent) and use `_msgSender()` for all authorization checks (`client`, `provider`, `evaluator`).
- All role checks (e.g. &quot;caller is client&quot;, &quot;caller is provider&quot;) SHALL use `_msgSender()` rather than `msg.sender`.
- The trusted forwarder address SHALL be set at deployment and SHOULD be immutable.

```solidity
import {ERC2771Context} from &quot;@openzeppelin/contracts/metatx/ERC2771Context.sol&quot;;

contract AgenticCommerce is ERC2771Context, ... {
    constructor(address trustedForwarder, ...)
        ERC2771Context(trustedForwarder) { ... }

    // Example: fund() using _msgSender() instead of msg.sender
    function fund(uint256 jobId, uint256 expectedBudget) external {
        Job storage job = jobs[jobId];
        if (_msgSender() != job.client) revert Unauthorized();
        if (job.budget != expectedBudget) revert BudgetMismatch();
        // ...
    }
}
```

**Token approvals:** For functions that pull tokens (e.g. `fund`), the signer SHOULD use [ERC-2612](/EIPs/EIPS/eip-2612) (`permit`) to approve token spending via signature. The facilitator can then call `permit` and `fund` in a single transaction — no on-chain approval tx needed from the signer.

**x402 compatibility:** This extension enables compatibility with HTTP-native payment protocols such as x402, where an AI agent signs payment intents off-chain and a payment facilitator handles on-chain execution. The agent only needs a private key and tokens — no gas, no RPC management, no chain-specific logic.

---

## Backwards Compatibility

No backward compatibility issues found.

## Reference Implementation

The reference implementation consists of two contracts: `IACPHook`, the optional and minimal hook interface that developers implement, and `AgenticCommerce`, the core Job primitive with escrow and optional hook extension points.

### IACPHook.sol

```solidity
pragma solidity ^0.8.20;

import &quot;@openzeppelin/contracts/utils/introspection/IERC165.sol&quot;;

interface IACPHook is IERC165 {
    function beforeAction(uint256 jobId, bytes4 selector, bytes calldata data) external;
    function afterAction(uint256 jobId, bytes4 selector, bytes calldata data) external;
}
```

### AgenticCommerce.sol

```solidity
pragma solidity ^0.8.28;

import &quot;@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol&quot;;
import &quot;@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol&quot;;
import &quot;@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol&quot;;
import &quot;@openzeppelin/contracts/token/ERC20/IERC20.sol&quot;;
import &quot;@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol&quot;;
import &quot;@openzeppelin/contracts/utils/ReentrancyGuardTransient.sol&quot;;
import &quot;./IACPHook.sol&quot;;
import &quot;@openzeppelin/contracts/utils/introspection/ERC165Checker.sol&quot;;

contract AgenticCommerce is Initializable, AccessControlUpgradeable, ReentrancyGuardTransient, UUPSUpgradeable {
    using SafeERC20 for IERC20;

    bytes32 public constant ADMIN_ROLE = keccak256(&quot;ADMIN_ROLE&quot;);

    enum JobStatus {
        Open,
        Funded,
        Submitted,
        Completed,
        Rejected,
        Expired
    }

    struct Job {
        uint256 id;
        address client;
        address provider;
        address evaluator;
        string description;
        uint256 budget;
        uint256 expiredAt;
        JobStatus status;
        address hook;
    }

    IERC20 public paymentToken;
    uint256 public platformFeeBP;
    address public platformTreasury;
    uint256 public evaluatorFeeBP;

    mapping(uint256 =&gt; Job) public jobs;
    uint256 public jobCounter;
    mapping(address =&gt; bool) public whitelistedHooks;
    mapping(uint256 jobId =&gt; bool hasBudget) public jobHasBudget;

    event JobCreated(
        uint256 indexed jobId, address indexed client, address indexed provider,
        address evaluator, uint256 expiredAt, address hook
    );
    event ProviderSet(uint256 indexed jobId, address indexed provider);
    event BudgetSet(uint256 indexed jobId, uint256 amount);
    event JobFunded(uint256 indexed jobId, address indexed client, uint256 amount);
    event JobSubmitted(uint256 indexed jobId, address indexed provider, bytes32 deliverable);
    event JobCompleted(uint256 indexed jobId, address indexed evaluator, bytes32 reason);
    event JobRejected(uint256 indexed jobId, address indexed rejector, bytes32 reason);
    event JobExpired(uint256 indexed jobId);
    event PaymentReleased(uint256 indexed jobId, address indexed provider, uint256 amount);
    event EvaluatorFeePaid(uint256 indexed jobId, address indexed evaluator, uint256 amount);
    event Refunded(uint256 indexed jobId, address indexed client, uint256 amount);
    event HookWhitelistUpdated(address indexed hook, bool status);

    error InvalidJob();
    error WrongStatus();
    error Unauthorized();
    error ZeroAddress();
    error ExpiryTooShort();
    error ZeroBudget();
    error ProviderNotSet();
    error FeesTooHigh();
    error HookNotWhitelisted();

    /// @custom:oz-upgrades-unsafe-allow constructor
    constructor() {
        _disableInitializers();
    }

    function initialize(address paymentToken_, address treasury_) public initializer {
        if (paymentToken_ == address(0) || treasury_ == address(0))
            revert ZeroAddress();

        __AccessControl_init();

        paymentToken = IERC20(paymentToken_);
        platformTreasury = treasury_;
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _grantRole(ADMIN_ROLE, msg.sender);
        whitelistedHooks[address(0)] = true;
    }

    function _authorizeUpgrade(address newImplementation) internal override onlyRole(DEFAULT_ADMIN_ROLE) {}

    // ──────────────────── Admin ────────────────────

    function setPlatformFee(uint256 feeBP_, address treasury_) external onlyRole(ADMIN_ROLE) {
        if (treasury_ == address(0)) revert ZeroAddress();
        if (feeBP_ + evaluatorFeeBP &gt; 10000) revert FeesTooHigh();
        platformFeeBP = feeBP_;
        platformTreasury = treasury_;
    }

    function setEvaluatorFee(uint256 feeBP_) external onlyRole(ADMIN_ROLE) {
        if (feeBP_ + platformFeeBP &gt; 10000) revert FeesTooHigh();
        evaluatorFeeBP = feeBP_;
    }

    function setHookWhitelist(address hook, bool status) external onlyRole(ADMIN_ROLE) {
        if (hook == address(0)) revert ZeroAddress();
        whitelistedHooks[hook] = status;
        emit HookWhitelistUpdated(hook, status);
    }

    // ──────────────────── Hook Helpers ────────────────────

    function _beforeHook(address hook, uint256 jobId, bytes4 selector, bytes memory data) internal {
        if (hook != address(0)) {
            IACPHook(hook).beforeAction(jobId, selector, data);
        }
    }

    function _afterHook(address hook, uint256 jobId, bytes4 selector, bytes memory data) internal {
        if (hook != address(0)) {
            IACPHook(hook).afterAction(jobId, selector, data);
        }
    }

    // ──────────────────── Job Lifecycle ────────────────────

    function createJob(
        address provider, address evaluator, uint256 expiredAt,
        string calldata description, address hook
    ) external nonReentrant returns (uint256) {
        if (evaluator == address(0)) revert ZeroAddress();
        if (expiredAt &lt;= block.timestamp + 5 minutes) revert ExpiryTooShort();
        if (!whitelistedHooks[hook]) revert HookNotWhitelisted();
        if (hook != address(0)) {
            if (!ERC165Checker.supportsInterface(hook, type(IACPHook).interfaceId))
                revert InvalidJob();
        }

        uint256 jobId = ++jobCounter;
        jobs[jobId] = Job({
            id: jobId,
            client: msg.sender,
            provider: provider,
            evaluator: evaluator,
            description: description,
            budget: 0,
            expiredAt: expiredAt,
            status: JobStatus.Open,
            hook: hook
        });

        emit JobCreated(jobId, msg.sender, provider, evaluator, expiredAt, hook);
        _afterHook(hook, jobId, msg.sig, abi.encode(msg.sender, provider, evaluator));

        return jobId;
    }

    function setProvider(uint256 jobId, address provider_) external {
        Job storage job = jobs[jobId];
        if (job.id == 0) revert InvalidJob();
        if (job.status != JobStatus.Open) revert WrongStatus();
        if (msg.sender != job.client) revert Unauthorized();
        if (job.provider != address(0)) revert WrongStatus();
        if (provider_ == address(0)) revert ZeroAddress();
        job.provider = provider_;
        emit ProviderSet(jobId, provider_);
    }

    function setBudget(uint256 jobId, uint256 amount, bytes calldata optParams) external nonReentrant {
        Job storage job = jobs[jobId];
        if (job.id == 0) revert InvalidJob();
        if (job.status != JobStatus.Open) revert WrongStatus();
        if (msg.sender != job.provider) revert Unauthorized();

        bytes memory data = abi.encode(msg.sender, amount, optParams);
        _beforeHook(job.hook, jobId, msg.sig, data);

        job.budget = amount;
        emit BudgetSet(jobId, amount);
        jobHasBudget[jobId] = true;

        _afterHook(job.hook, jobId, msg.sig, data);
    }

    function fund(uint256 jobId, bytes calldata optParams) external nonReentrant {
        Job storage job = jobs[jobId];
        if (job.id == 0) revert InvalidJob();
        if (job.status != JobStatus.Open) revert WrongStatus();
        if (msg.sender != job.client) revert Unauthorized();
        if (job.provider == address(0)) revert ProviderNotSet();
        if (block.timestamp &gt;= job.expiredAt) revert WrongStatus();

        bytes memory data = abi.encode(msg.sender, optParams);
        _beforeHook(job.hook, jobId, msg.sig, data);

        job.status = JobStatus.Funded;
        if (job.budget &gt; 0) {
            paymentToken.safeTransferFrom(job.client, address(this), job.budget);
        }
        emit JobFunded(jobId, job.client, job.budget);

        _afterHook(job.hook, jobId, msg.sig, data);
    }

    function submit(uint256 jobId, bytes32 deliverable, bytes calldata optParams) external nonReentrant {
        Job storage job = jobs[jobId];
        if (job.id == 0) revert InvalidJob();
        if (
            job.status != JobStatus.Funded &amp;&amp;
            (job.status != JobStatus.Open || job.budget &gt; 0)
        ) revert WrongStatus();
        if (msg.sender != job.provider) revert Unauthorized();

        bytes memory data = abi.encode(msg.sender, deliverable, optParams);
        _beforeHook(job.hook, jobId, msg.sig, data);

        job.status = JobStatus.Submitted;
        emit JobSubmitted(jobId, job.provider, deliverable);

        _afterHook(job.hook, jobId, msg.sig, data);
    }

    function complete(uint256 jobId, bytes32 reason, bytes calldata optParams) external nonReentrant {
        Job storage job = jobs[jobId];
        if (job.id == 0) revert InvalidJob();
        if (job.status != JobStatus.Submitted) revert WrongStatus();
        if (msg.sender != job.evaluator) revert Unauthorized();

        bytes memory data = abi.encode(msg.sender, reason, optParams);
        _beforeHook(job.hook, jobId, msg.sig, data);

        job.status = JobStatus.Completed;

        uint256 amount = job.budget;
        uint256 platformFee = (amount * platformFeeBP) / 10000;
        uint256 evalFee = (amount * evaluatorFeeBP) / 10000;
        uint256 net = amount - platformFee - evalFee;

        if (platformFee &gt; 0) {
            paymentToken.safeTransfer(platformTreasury, platformFee);
        }
        if (evalFee &gt; 0) {
            paymentToken.safeTransfer(job.evaluator, evalFee);
            emit EvaluatorFeePaid(jobId, job.evaluator, evalFee);
        }
        if (net &gt; 0) {
            paymentToken.safeTransfer(job.provider, net);
        }

        emit JobCompleted(jobId, job.evaluator, reason);
        emit PaymentReleased(jobId, job.provider, net);

        _afterHook(job.hook, jobId, msg.sig, data);
    }

    function reject(uint256 jobId, bytes32 reason, bytes calldata optParams) external nonReentrant {
        Job storage job = jobs[jobId];
        if (job.id == 0) revert InvalidJob();

        if (job.status == JobStatus.Open) {
            if (msg.sender != job.client) revert Unauthorized();
        } else if (job.status == JobStatus.Funded || job.status == JobStatus.Submitted) {
            if (msg.sender != job.evaluator) revert Unauthorized();
        } else {
            revert WrongStatus();
        }

        bytes memory data = abi.encode(msg.sender, reason, optParams);
        _beforeHook(job.hook, jobId, msg.sig, data);

        JobStatus prev = job.status;
        job.status = JobStatus.Rejected;

        if ((prev == JobStatus.Funded || prev == JobStatus.Submitted) &amp;&amp; job.budget &gt; 0) {
            paymentToken.safeTransfer(job.client, job.budget);
            emit Refunded(jobId, job.client, job.budget);
        }

        emit JobRejected(jobId, msg.sender, reason);

        _afterHook(job.hook, jobId, msg.sig, data);
    }

    function claimRefund(uint256 jobId) external nonReentrant {
        Job storage job = jobs[jobId];
        if (job.id == 0) revert InvalidJob();
        if (job.status != JobStatus.Funded &amp;&amp; job.status != JobStatus.Submitted)
            revert WrongStatus();
        if (block.timestamp &lt; job.expiredAt) revert WrongStatus();

        job.status = JobStatus.Expired;

        if (job.budget &gt; 0) {
            paymentToken.safeTransfer(job.client, job.budget);
            emit Refunded(jobId, job.client, job.budget);
        }

        emit JobExpired(jobId);
    }

    // ──────────────────── View ────────────────────

    function getJob(uint256 jobId) external view returns (Job memory) {
        return jobs[jobId];
    }
}
```

## Security Considerations

- Evaluator is trusted for completion and rejection once the job is Submitted; a malicious evaluator can complete or reject arbitrarily. Use reputation (e.g. [ERC-8004](/EIPs/EIPS/eip-8004)) or staking for high-value jobs.
- Once Funded, only the evaluator can reject, and only the provider can submit; the client cannot unilaterally withdraw, which protects the provider after they start work.
- No dispute resolution or arbitration; reject/expire is final.
- Single payment token per contract reduces attack surface; per-job tokens are an extension.
- **Reentrancy:** Functions that transfer tokens SHALL be protected (e.g. reentrancy guard).
- **Tokens:** Use SafeERC-20 or equivalent for [ERC-20](/EIPs/EIPS/eip-20).
- **Evaluator:** MUST be set at creation; if &quot;client completes&quot;, pass `evaluator = client`.
- **Hook gas limits** (for hooked implementations): Implementations SHOULD impose a gas limit on hook calls (e.g. `call{gas: HOOK_GAS_LIMIT}(...)`) to bound execution cost and prevent hooks from consuming unbounded gas. The specific limit is left to the implementation as gas costs vary across chains.
- Hook contracts are client-supplied and trusted by the client; implementations MUST NOT allow hooks to modify core escrow state directly. `claimRefund` is deliberately not hookable so that refunds after expiry cannot be blocked by a malicious hook.
- Jobs that use **advanced hooks** (e.g. two‑phase escrow / fund‑transfer hooks that custody additional tokens) are expected to have **more revert paths and tighter coupling** to external logic than plain, non‑hooked Agentic Commerce jobs. Such hooks SHOULD be reserved for agents and users who understand and accept this trade‑off; for most simple jobs, a non‑hooked or policy‑only hook is RECOMMENDED.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 25 Feb 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8183</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8183</guid>
      </item>
    
      <item>
        <title>LUCID encrypted mempool</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8184-lucid-encrypted-mempool/28017</comments>
        
        <description>## Abstract

This EIP specifies LUCID, a mechanism for carrying encrypted transactions through Ethereum&apos;s public inclusion pipeline while keeping their contents hidden until after the scheduling decision has been fixed. By requiring commitment before reveal and delaying decryption until that point, LUCID protects MEV-sensitive order flow, limits probabilistic front-running by minimizing pre-execution information leakage, and broadens the practical censorship resistance of inclusion lists. The design remains open to different off-protocol decryption schemes, including trustless self-decryption, rather than coupling Ethereum to a single enshrined cryptographic construction.

## Motivation

Transaction ordering power has, in practice, made the public mempool unusable for a large share of economically meaningful transactions on Ethereum. When pending transactions can be inspected before inclusion, sophisticated actors can front-run, sandwich, or simply copy profitable strategies, turning transparent block production into an industrialized market for toxic MEV. 

The natural response has been a migration toward private order flow. Users, wallets, searchers, and applications increasingly route transactions through private relays, builder-run mempools, order flow auctions, and other trusted intermediaries that can shield transaction contents until inclusion. These arrangements replace a public and permissionless inclusion path with opaque bilateral relationships. They reward trust, access, and private dealmaking over open competition, starving the public mempool, entrenching incumbent builders, and leaving access to blockspace vulnerable to outages, policy changes, and discretionary blacklisting.

This is especially concerning because it pushes some of Ethereum’s most important activity away from the public, composable domain. Offchain market structures may provide reasonable local arrangements, but they are unlikely to constitute a sufficient long-run equilibrium for Ethereum on their own. The promise of DeFi is not merely that transactions settle onchain; it is that trading, competition, and execution themselves can occur permissionlessly onchain. 

Another core property is censorship resistance (CR), but because [EIP-7805](/EIPs/EIPS/eip-7805) (FOCIL) relies on open propagation, it cannot provide CR for transactions subject to MEV extraction. A public encrypted mempool addresses this gap. If transactions can be propagated in encrypted form and committed to before their contents are revealed, users no longer need to choose between MEV protection and trustless access to blockspace. This broadens the practical censorship resistance of inclusion lists while reducing the importance of privileged private order flow in builder competition.

At the same time, Ethereum cannot presently enshrine a single encryption scheme for this purpose. A viable in-protocol scheme requires a silent setup with small public keys, non-interactive decryption, no trusted setup, practical ciphertext sizes, CCA2 security, and a credible path to quantum safety. No known construction fully satisfies these requirements at Ethereum’s scale, and waiting for cryptographic breakthroughs would impose an unacceptable delay.

LUCID extends the inclusion pipeline to sealed transactions (STs) that can be propagated in public without revealing their contents. Builders commit to them before decryption, and key publishers release keys only after the scheduling decision has been fixed. In doing so, it preserves a public, permissionless path to inclusion for MEV-sensitive transactions without coupling Ethereum to a specific encryption scheme. Transactions may be self-decrypted in a trustless manner or encrypted in an open design according to a key publisher&apos;s instructions. This broadens the practical CR afforded by FOCIL while reducing Ethereum’s dependence on centralized order-flow relationships. In the longer term, it helps preserve an Ethereum in which trading and transaction competition can take place onchain, in public, and under permissionless market structure.

## Specification

### Constants and parameters

```python
TOB_GAS_FRACTION_DENOMINATOR = 8
TOB_FEE_FRACTION = 128
MAX_SIGNATURE_SIZE = 2**16
MAX_ST_COMMITS_PER_IL = 2
MAX_STS_PER_BUNDLE = 64
MAX_BYTES_PER_ST = 2**24 // 64 # Byte bound implied by EIP-7976 and EIP-7825
MAX_ST_COMMITS = MAX_ST_COMMITS_PER_IL * IL_COMMITTEE_SIZE # IL_COMMITTEE_SIZE defined in EIP-7805
MAX_ST_TICKETS = MAX_ST_COMMITS * MAX_STS_PER_BUNDLE
tob_gas_limit = block.gas_limit // TOB_GAS_FRACTION_DENOMINATOR
tob_gas_limit_per_il = tob_gas_limit // IL_COMMITTEE_SIZE
```

### Overview: from submission to execution

This subsection provides an overview of the LUCID mechanism. LUCID relies on sealed transactions (STs), consisting of a signed ST ticket used for charging the sender and binding to a key publisher and a `ciphertext_envelope`.  The `ciphertext_envelope` decrypts to a signed plaintext transaction (PT) that can have a different `from` field than the ST. Senders encrypt transactions to a key publisher in an open design following the key publisher&apos;s off‑protocol instructions (and if applicable, using its public key), or can otherwise self‑decrypt trustlessly. The ST can be propagated in the public mempool without revealing the PT until after commitment. Figure 1 provides a timeline for the design.

![Figure 1](/EIPs/assets/eip-8184/1.png)

**Figure 1.** LUCID timeline. Bids are included in the beacon block to allow key publishers to release keys in a timely manner before the next slot starts. Decrypted transactions are executed in the next block.

* **Before $T_1$** – Includers propagate ILs that, besides PTs, can incorporate STs. The STs are either included individually or in a bundle (dark blue background).
* **$T_1$** – Attesters (purple) of slot $n$ freeze their view of propagated ILs as well as votes on the timeliness of decryption keys released during the previous slot.
* **After $T_1$** – Once builders know which ILs and keys they must adhere to, they cast an expanded `ExecutionPayloadBid` for the right to build the block. The bid contains &quot;ST-commitments&quot; to the hash of STs and ST bundles.
* **$T_2$** – At the start of slot $n$, the proposer selects a winning bid, which is at least as encompassing as its own view of required ILs for block $n$ and keys from slot $n-1$. It includes that bid in the beacon block.
* **After $T_2$** – Upon observing the beacon block, nodes begin requesting any missing ILs as well as ST bytes that are referenced by the ST‑commitments. Senders and key publishers can also independently propagate those bytes now.
* **$T_3$** – Attesters of slot $n$ cast a vote on the current head of the chain. If the beacon block is missing or if the bid fails their audit due to omitted ST-commitments in ILs from their frozen view, they indicate the preceding block that is the head of the chain in their view. If the bid passes their audit, they optimistically attest to the block.
* **After $T_3$ (Payload)** – The builder releases the payload which also carries ST tickets that are charged. The first transactions (white rectangle) are decrypted STs, previously committed to in block $n-1$. Regular PTs from the current slot follow (black rectangle).
* **After $T_3$ (Keys)** – Each key publisher observes the ST-commitments in the beacon block. It confirms correct data for its own ST-commitment (pertaining, e.g., to its `gas_obligation` specifying how much gas it consumes), that the aggregate of all `gas_obligation` entries is within the allotted share of the next payload (`tob_gas_limit`), and that the beacon block is attested to. It propagates the key(s) that reveal the STs. The key(s) are flooded P2P and observed by attesters of the next block before their deadline at $T_4$.
* **$T_4$** – The payload timeliness committee (PTC) votes for the timeliness of the payload, including timely receipt of ST/ST-bundle bytes and adherence to the keys released in the previous slot. It further casts a separate bitfield vote confirming the ST-commitments that can now be decrypted, i.e., those with valid ST/ST-bundle bytes and keys released during the current slot.
* **$T_5$** – Attesters of slot $n+1$ freeze their view of propagated ILs as well as the decryption key timeliness votes for the previous block. The process then follows the same trajectory as after $T_1$ (for the previous slot).

### Sealed transactions

A sealed transaction (ST) is a transaction envelope which contains:

1. a signed ST ticket transaction (to later be included on-chain), and
2. a ciphertext envelope (not included on-chain).

It is encoded in SSZ when being included in FOCIL-style inclusion lists.

```python
class SealedTransaction(Container):
    ticket: Transaction
    ciphertext_envelope: ByteList[MAX_BYTES_PER_ST]
```

It is encoded in RLP when propagating across the mempool, as a new [EIP-2718](/EIPs/EIPS/eip-2718) transaction.

```
ST_TX_TYPE || rlp([
  st_ticket,
  ciphertext_envelope
])
```

#### ST ticket

An ST ticket is a new [EIP-2718](/EIPs/EIPS/eip-2718) typed transaction. It is charged and consumes the sender&apos;s execution nonce, but is not executed as a normal EVM message call.

```
ST_TICKET_TX_TYPE || rlp([
    chain_id,
    nonce,
    max_priority_fee_per_gas,
    max_fee_per_gas,
    gas_limit,
    max_tob_fee,
    max_preceding_commitments,
    key_publisher,
    key_publication_fee_recipient,
    key_publication_fee,
    key_commitment,
    reveal_commitment,
    ciphertext_hash,
    signature_id,
    signature
])
```

Besides regular transaction fields, the ST ticket also has a:

* `max_tob_fee` that the sender is willing to pay.
* `max_preceding_commitments` executed before the ST, acting as an upper bound.
* `key_publisher` responsible for signing bundles before key release.
* `key_publication_fee_recipient` that receives the fee.
* `key_publication_fee` paid for timely decryption of the plaintext transaction.
* `key_commitment` that binds to the revealed key.
* `reveal_commitment` that binds to the revealed transaction.
* `ciphertext_hash`, where `ciphertext_hash = keccak256(ciphertext_envelope)` binds the ciphertext bytes.

The `signature_id` is one byte and the `signature` is interpreted according to `signature_id`. The only currently valid value for `signature_id` is `EC_DSA_TYPE == 0x01`. In this case, the `signature` is to be interpreted as a (`signature_y_parity`, `signature_r`, `signature_s`)-triple. This design ensures that we do not enshrine non-PQ-safe ECDSA signatures (see further discussion on the relationship to [EIP-8141](/EIPs/EIPS/eip-8141) in the Rationale).

#### Ciphertext envelope

The `ciphertext_envelope` of the ST is defined as:

```python
class CiphertextEnvelope(Container):
  header: ByteList[2**16 - 1]
  dem_ciphertext: ByteList[MAX_BYTES_PER_ST]
```

On the EL, `ciphertext_envelope` is:

```
rlp([header_len:u16 || header || dem_ciphertext])
```

The `header_len` is big-endian. The `header` is `header_len` bytes and is opaque to the protocol. This field is reserved for decryption scheme metadata. 

The `dem_ciphertext` is the output of a DEM `ChaCha20-Poly1305` AEAD encryption with:

* DEM key – `k_dem` (32 bytes).
* Nonce – `keccak256(chain_id || ticket_from || ticket_nonce)[:12]` for STs.
* Empty `aad` (`b&quot;&quot;`).
* `dem_ciphertext` is `ciphertext || tag` (`tag` is 16 bytes).

The `ciphertext_envelope` decrypts to `plaintext_tx`, the raw bytes of an [EIP-1559](/EIPs/EIPS/eip-1559) transaction to be executed onchain.

The `plaintext_tx` must have:

* `max_priority_fee_per_gas = 0`
* `max_fee_per_gas = 0`
* `gas_limit = ticket.gas_limit`

The `gas_limit` must be sufficient to cover the calldata cost of the byte size of the `SealedTransaction`. [EIP-7825](/EIPs/EIPS/eip-7825) thus bounds the byte size of an ST.

To bind the key, the sender includes `key_commitment = keccak256(k_dem)` in the ST ticket.

The `reveal_commitment` binds the revealed plaintext payload to a specific ticket. `ticket_from` is the recovered sender address from the ticket signature.

```python
class RevealCommitmentPreimage(Container):
    chain_id: uint256
    ticket_from: ExecutionAddress
    ticket_nonce: uint64
    plaintext_tx: Transaction

reveal_commitment = hash_tree_root(RevealCommitmentPreimage(...))
```

### Bundles

Sealed transactions can be bundled together only if all contained ST tickets have the same `key_publisher`. The bundle is then signed by that `key_publisher` to authenticate that it formed it.

```python
class SealedBundle(Container):
    sealed_transactions: List[SealedTransaction, MAX_STS_PER_BUNDLE]
    key_publisher_signature_id: uint8
    key_publisher_signature: ByteList[MAX_SIGNATURE_SIZE]
```

The `key_publisher_signature` is interpreted according to `key_publisher_signature_id`. The `ticket_hash` of an ST is `keccak256(ticket_bytes)`. The only currently valid value for `key_publisher_signature_id` is `EC_DSA_TYPE == 0x01`. 

The `bundle_root` is the hash of the list of ticket hashes: `bundle_root = keccak256(keccak256(ticket_bytes[0]) || ... || keccak256(ticket_bytes[n]))`. The key publisher signs `(chain_id, bundle_root)` with an ECDSA signature that recovers `key_publisher`.

Bundles are assigned an `executable` bitfield when committed to by the builder (as described below). Bundles have a collective `max_preceding_commitments` which is set as the minimum `max_preceding_commitments` among STs with `executable = 1`. Each ST has a `tob_fee` computed as described below under the &quot;Block processing&quot; subsection. The `bundle_tob_fee` is the aggregate of the `tob_fee` of all STs in the bundle with `executable = 1`.

### Extended payload bid with ST-commitments

The `ExecutionPayloadBid` is extended with ST commitments and canonical IL roots.

```python
class STCommitment(Container):
    commitment_root: Bytes32
    commitment_key: Bytes32
    gas_obligation: uint64
    executable: Bitlist[MAX_STS_PER_BUNDLE]

class ExecutionPayloadBid(Container):
    ...
    st_commitments: List[STCommitment, MAX_ST_COMMITS]
    IL_roots: List[Bytes32, IL_COMMITTEE_SIZE]
```

The `commitment_root` is `ticket_hash` for non-bundles and `bundle_root` for bundles. 

For a non-bundle commitment, `executable` is empty and `gas_obligation = ticket.gas_limit`. For a bundle commitment, `executable` has length equal to the number of tickets in the committed bundle, in bundle order. The `executable[i]` bit is set to `1` iff ticket `i` can pay `ticket_fee` (defined below) and passes the `ticket.nonce` check when ST tickets are processed in `st_commitments` order and bundle members are processed in bundle order.

The `commitment_tob_fee` is defined as the `tob_fee` of an ST and the `bundle_tob_fee` of a bundle. It is not included in the commitment since it can be computed deterministically and is not required at commitment time. or the same reason, the `max_preceding_commitments` is not included.

For STs, the `commitment_key` is the ticket&apos;s `key_commitment`. For bundles, the builder first generates the list `key_commitments` by iterating over the bundle in bundle order and appending each `key_commitment` with `executable[i] == 1`. It then sets `commitment_key = keccak256(key_commitments)`.

The `gas_obligation` is the aggregate `ticket.gas_limit` for bundle members with `executable[i] == 1`. 

### Execution payload expansion

```python
class DecryptedTransaction(Container):
    plaintext_tx: Transaction
```

The execution payload is prepended with `st_tickets` and `decrypted_transactions`:

```python
class ExecutionPayload(Container):
    st_tickets: List[Transaction, MAX_ST_TICKETS]
    decrypted_transactions: List[DecryptedTransaction, 2 * MAX_ST_TICKETS]
    ...
```

### Key message

Decryptors publish DEM key material in an unsigned message.

```python
class LucidKeyMessage(Container):
    chain_id: uint256
    scheduling_beacon_block_root: Bytes32
    scheduling_slot: uint64
    commit_index: uint8
    k_dems: List[Bytes32, MAX_STS_PER_BUNDLE]
```

#### Key message validity and decryption

A `LucidKeyMessage` is valid if it:

1. resolves, for a non-bundle ST, `keccak256(k_dems[0]) == commitment_key`; resolves, for a multi-key bundle, `keccak256(keccak256(k_dems[0]) || ... || keccak256(k_dems[n])) == commitment_key`;
2. has a `chain_id` that matches the chain;
3. references a commitment present in the scheduling block;
4. has the length `len(k_dems) == 1` for STs, and `len(k_dems) == sum(executable)` for bundles, with `k_dems` ordered by the bundle order filtered to `executable[i] == 1`;
5. successfully decrypts the transaction(s).

Decryption of a scheduled ST is defined as successful only if decrypting `ciphertext_envelope` yields a `plaintext_tx` whose:

* `hash_tree_root(RevealCommitmentPreimage(...)) == ticket.reveal_commitment`, and
* `plaintext_tx` decodes to a type-2 transaction with:
  * `max_fee_per_gas = 0`,
  * `max_priority_fee_per_gas = 0`,
  * `gas_limit = ticket.gas_limit`.

### Key release

The key publisher observes ST-commitments from the `ExecutionPayloadBid` included in the beacon block. It verifies that the `executable` bitfield indeed produces the specified `gas_obligation` for its own ST-commitment and that the aggregate of all `gas_obligation` entries is within the `tob_gas_limit`. Given that these requirements are fulfilled, if the payload turns out to be invalid or untimely, the key publisher&apos;s ST-commitment will always fit within the `tob_gas_limit`. This means that the ST(s) can still be included ToB in the next valid payload, as further discussed in the section entitled &quot;Recovery under rejected payload&quot;.

The key publisher further verifies that the order of the ST-commitment is consistent with its underlying `max_preceding_commitments`. When the key publisher is confident that the beacon block will become canonical (for example after observing attestations for it), it releases its `LucidKeyMessage`. In the case of a single ST, the sender may itself also release the `LucidKeyMessage`, even if it specified a key publisher other than itself.

### Key timeliness

Each PTC member publishes a signed vote message indicating which valid keys, scheduled for the current slot, they have observed:

```python
DOMAIN_LUCID_KEY_TIMELINESS = DomainType(&apos;TBD&apos;)

class LucidKeyTimelinessVote(Container):
    chain_id: uint256
    voting_slot: uint64
    validator_index: ValidatorIndex
    scheduling_beacon_block_root: Bytes32
    scheduling_slot: uint64
    keys_observed: Bitlist[MAX_ST_COMMITS]

class SignedLucidKeyTimelinessVote(Container):
    message: LucidKeyTimelinessVote
    signature: BLSSignature
```

A bit `keys_observed[j]` is set to 1 iff the voter observed, by the key observation deadline of the PTC, a valid `LucidKeyMessage` for `(scheduling_beacon_block_root, scheduling_slot, commit_index=j)`. Nodes treat equivocated `LucidKeyTimelinessVote` messages the same way they do for equivocated ILs in FOCIL: they propagate the first two distinct signed votes they have observed for the same key to signal equivocation. The PTC members of the *next slot* store received votes at the `lucid_key_vote_deadline`, but keep listening for new messages and equivocation until they vote.

Let `timely_key_votes` be a bitfield of observed votes on a key at `lucid_key_vote_deadline` and `total_key_votes` be a bitfield of observed votes on a key at the attestation time. The number of committee members who equivocated is tallied in `equivocated_votes`. These votes are not included in the key votes bitfields. Further define:

* `timely_1 = sum(timely_key_votes)`,
* `timely_0 = len(timely_key_votes) - timely_1`,
* `late_1 = sum(total_key_votes) - timely_1`,
* `late_0 = len(total_key_votes) - sum(total_key_votes) - timely_0`

The PTC of the *next slot* considers:

* All non-equivocated votes it observed at `lucid_key_vote_deadline` to have been seen by the builder.
* All non-equivocated votes it observed after `lucid_key_vote_deadline` to have potentially been seen by the builder.
* All equivocated votes to potentially have been seen voting either `0` or `1`.

The builder can thus treat a key as missing under condition:

* `2 * timely_1 &lt;= (timely_1 + timely_0 + late_0 + equivocated_votes)`;

and treat a key as observed under condition:

* `2 * (timely_1 + late_1 + equivocated_votes) &gt; (timely_1 + timely_0 + late_1 + equivocated_votes)`.

If this test fails for any key, the PTC of the next slot votes against the payload timeliness.

### Inclusion lists with STs and bundles

The `InclusionList` container of [EIP-7805](/EIPs/EIPS/eip-7805) is extended with STs and ST bundles:

```python
class InclusionList(Container):
    ...
    sealed_transactions: List[SealedTransaction, MAX_ST_COMMITS_PER_IL]
    sealed_bundles: List[SealedBundle, MAX_ST_COMMITS_PER_IL]
```

The IL must satisfy `len(sealed_transactions) + len(sealed_bundles) &lt;= MAX_ST_COMMITS_PER_IL`.

An entry of a timely IL must still be excluded from the block if:

* it is an ST that already appears in the block via a bundle,
* it is a bundle with STs that already appear in another bundle with a higher aggregate `gas_limit`.

An entry of a timely IL may still be excluded from the block if:

* The aggregate `gas_limit` of all STs (including bundled STs) of the IL exceeds `tob_gas_limit_per_il`.
* It cannot be inserted in `st_commitments` at the position determined by the ST-commitment ordering rule (see Block processing)—without breaking its `max_preceding_commitments` stipulation.

Attesters check the second condition similarly to the post-execution check of FOCIL, for each entry in `sealed_transactions` or `sealed_bundles` in a timely observed IL that was excluded from the block. The attester iterates through the `st_commitments` starting from ToB, for bundles updating `executable` of the to-be-inserted commitment and aggregating the `tob_fee` over eligible STs to compute the `bundle_tob_fee`. If in any instance the ST-commitment could be placed in `st_commitments` at the position determined by the ST-commitment ordering rule without violating its `max_preceding_commitments`, but is not included, attesters vote against the block.

### Block processing

Nodes match the STs/ST bundles with their ST-commitments in the beacon block, verify for each matched ST (whether standalone or in a bundle) that `keccak256(ciphertext_envelope) == ticket.ciphertext_hash`, and verify that the commitments are ordered by descending `commitment_tob_fee`, tie-breaking by descending `gas_obligation` and ascending `commitment_root` respectively; referred to as the &quot;ST-commitment ordering rule&quot;. They further verify that ST tickets adhere to the order of the ST-commitments. The ST tickets of bundles must further be in the same order as in the bundle, which the key publisher is free to decide.

Each ST ticket is charged after first establishing a `priority_fee` and `tob_fee` based on the `base_fee_per_gas`:

```python
# Initialize
max_priority_fee = ticket.max_priority_fee_per_gas * ticket.gas_limit
max_fee = ticket.max_fee_per_gas * ticket.gas_limit
base_fee = block.base_fee_per_gas * ticket.gas_limit

# Compute capped fees
assert max_fee &gt;= base_fee + ticket.key_publication_fee
priority_fee = min(max_priority_fee, max_fee - (base_fee + ticket.key_publication_fee))
tob_fee = min(ticket.max_tob_fee, max_fee - (base_fee + ticket.key_publication_fee + priority_fee))

# Charge the ticket sender
ticket_fee =  base_fee + ticket.key_publication_fee + priority_fee + tob_fee
assert ticket.signer.balance &gt;= ticket_fee
assert ticket.signer.nonce == ticket.nonce
ticket.signer.balance -= ticket_fee
ticket.signer.nonce += 1
```

All nodes validate key message validity as previously described for the PTC. They verify that `decrypted_transactions` contains the byte-identical transactions they derived via decryption, positioned in the same order as the corresponding charged ST tickets, with STs not decrypted left out from the `decrypted_transactions` list. 

Upon successful decryption, the calldata cost of the decrypted transaction is computed using `max(len(ciphertext_envelope), len(plaintext_tx.data))` bytes. The PT is then executed as a regular transaction, except that it bypasses the ordinary EIP-1559 fee-cap validation and no gas fee is charged, since the fee was already prepaid by the ST ticket. The `gas_used` is referred to as `dual_gas_used` to capture that it encompasses a broader interpretation of calldata. The unused gas, previously charged to the `parent_ticket` according to the base fee of the previous block, is then returned to the sender, together with the `parent_tob_fee` reserved for the penalty:

```python
parent_ticket.signer.balance += parent.base_fee_per_gas * (parent_ticket.gas_limit - dual_gas_used) + parent_tob_fee * (TOB_FEE_FRACTION - 1) // TOB_FEE_FRACTION
```

The `priority_fee` is not reconciled with `gas_used` since the ST still took up bounded space upon commitment. The specified key publication fee recipient is further credited the key publication fee:

```python
parent_ticket.key_publication_fee_recipient.balance += parent_ticket.key_publication_fee
```

The `decrypted_transactions` are executed against the header of the block in which their ST ticket was committed to, in order to prevent builders from being able to inject information into the block after having witnessed decrypted transactions. During processing, the `SLOTNUM` opcode introduced in [EIP-7843](/EIPs/EIPS/eip-7843) must always return the slot number which included the corresponding ST ticket. The addition of the parent block hash to the historical block registry defined in [EIP-2935](/EIPs/EIPS/eip-2935) is no longer done at the top of the block; it is deferred till after the last ST has been executed. Likewise, the addition of the parent block&apos;s beacon root to the historical root registry defined in [EIP-4788](/EIPs/EIPS/eip-4788) is no longer done at the top of the block; it is also deferred till after the last ST has been executed.

### Recovery under rejected payload

Decrypted transactions shall be included if:

* The ST bytes (and, if bundled, the ST bundle bytes) and keys were and are validly available, as confirmed by the PTC vote.
* The ST-commitments were correctly formatted and the aggregate of all `gas_obligation` entries was within the `tob_gas_limit` (as also confirmed by the attestations).
* Their ST-commitment entry specified a correct `gas_obligation` and `max_preceding_commitments`, given the `executable` bitfield provided for bundles.

If payload $n$ is rejected, two sets of STs are affected:

* The STs with `decrypted_transactions` scheduled for payload $n$, with ST-commitments in beacon block $n-1$ and ST tickets in payload $n-1$.
* The STs with ST-commitments in beacon block $n$, scheduled for payload $n+1$.

Both sets of STs that shall be included must then be included in the next payload. That payload includes the ST tickets of the associated commitments from beacon block $n$, and `decrypted_transactions` for commitments from both beacon block $n-1$ and $n$. The `decrypted_transactions` must be ordered according to the ST-commitments: those derived from commitments in beacon block $n-1$ go before those from commitments in beacon block $n$.

The `executable` bitfield and `gas_obligation` for an ST-commitment are fixed by its associated scheduling beacon block, and the key-timeliness outcome for the ST-commitment and `LucidKeyMessage` is fixed by the corresponding `LucidKeyTimelinessVote`. If an ST-commitment was mis-specified with respect to the original scheduling state, its transactions MUST NOT be included under recovery. When a recovery payload includes commitments from multiple scheduling beacon blocks, they are processed in scheduling-block order, and `max_preceding_commitments` is enforced only with respect to commitments from the same scheduling beacon block.

The recovery payload must not commit to new STs, in order for the protocol to catch up. In the baseline specification, decrypted STs are allotted at most `1 / TOB_GAS_FRACTION_DENOMINATOR` of the gas limit. The recovery payload can then include two sets of decrypted STs, which at most consume `2 /  TOB_GAS_FRACTION_DENOMINATOR` of the block&apos;s gas limit.

### Engine API Changes

* Add `engine_getInclusionListV2` endpoint to retrieve an IL which may contain STs and bundles from the ExecutionEngine.
* Add `engine_updatePayloadWithInclusionListV2` endpoint to update a payload with the IL that may contain STs and bundles that should be used to build the block.
* Add `engine_updateInclusionListV2` endpoint which consumes an updated `InclusionList` containing STs, and the 8-byte payload id being built.

### Beacon Chain RPC API Changes

* Update `/eth/v2/events` endpoint to notify wallets that their ST has been included, and it is safe to publish the key.
* Update `/eth/v2/events` endpoint to notify clients and committees that a key has been released.
* Add `/eth/v1/beacon/key` endpoint to relay the key to the libp2p topic.

## Rationale

### Probabilistic front-running

Attackers may attempt to probabilistically front-run transactions by preparing various options, that are only executed if they turn out to be profitable upon observing revealed keys of other transactions. LUCID tackles non-reveal of ST-commitments and probabilistic front-running from five different angles:

1. The public mempool need not reveal the plaintext transaction, its calldata, or its signer. While the signed ST ticket is visible, the revealed `plaintext_tx` may be signed by a different account than the ticket signer, which is not revealed until after commitment, when the decryption key is released.
2. After commitment, an attacker cannot replace ciphertexts, change ordering, or inject new STs. It can only control the binary decision whether to release valid keys for STs/ST bundles it already committed to. A multi-key bundle either fails, or all `executable` STs are revealed.
3. The `decrypted_transactions` are executed against the header of the block in which their ST ticket was committed to. This prevents builders from being able to inject information into the block after having witnessed decrypted transactions.
4. ST-commitments are ordered by ToB fee, a fraction of which is returned upon reveal. Selective reveal is therefore priced both in expectation and ex post. Concretely: (a) In the case that the front-runner consistently posts ST-commitments which it intends to use for front-running under advantageous circumstances, it must also consistently pay the part of the ToB fee that is not returned upon reveal – `tob_fee / TOB_FEE_FRACTION`. (b) In the case that the front-runner happens upon an advantageous circumstance, it must pay the higher penalty for every bit of information it communicates upon non-reveal  – `tob_fee`.
5. Each ST specifies the `max_preceding_commitments` that may execute before it. This allows users to balance their need for protection from probabilistic front-running with their willingness to pay a high ToB fee. If a sender allows at most $m$ preceding commitments, then an adversarial party can choose between at most $2^{m-1}$ distinct patterns to be executed before the sender—if it purchases all $m$ commitments by paying a higher `tob_fee` than the sender for each one. Deliberations concerning `max_preceding_commitments` are more important for senders that self-decrypt, whereas bundled STs can leverage the joint ToB fee of all STs of the bundle to reduce the viability of probabilistic front-running (see &quot;Alternative specifications&quot; for further improvements).

The builder also has one bit of reveal optionality. It can elect to either release or not release its payload, upon observing some of the keys. This alters the pre-state which the decrypted transactions are executed against, just like how a non-reveal of an earlier ST-commitment also changes the pre-state. Since the builder is staked, it can also trivially be penalized for a non-reveal at an appropriate level.

### MEV and welfare

The objective of LUCID is to restore a public, permissionless inclusion path for MEV-inducing transactions. Some users may prefer this inclusion path, whereas others continue using trusted private inclusion paths. The welfare claim of LUCID is therefore comparative and optional: it gives users an additional path that trades some private-intermediary conveniences for trustlessness and CR. At the protocol level, welfare is further strengthened by shrinking the share of economic activity that must route through trusted intermediaries—reducing exposure to discretionary exclusion, lowering barriers to builder entry, and keeping trading and competition within Ethereum&apos;s public, composable domain.

To understand the MEV landscape and how it affects encrypted mempools, it is useful to distinguish between:

* Exogenous MEV – induced by information external to the protocol, such as changes in CEX prices, prices on other chains, or other offchain information not yet reflected in the protocol state.
* Endogenous MEV – induced by the protocol state itself, such as imbalances between pools, available liquidations, or other imbalances internal to the protocol.
* Autogenous MEV (i.e., transaction-induced MEV) – induced when a transaction&apos;s own execution creates or reveals a new public signal, such as a large repricing trade or other state transition.

LUCID lands new information onchain trustlessly, which is useful when dealing with all three types of MEV, since it prevents front-running. However, differences regarding when the MEV opportunities become public and when they can be acted upon affect their relationship to the encrypted mempool. For example, a common objection to encrypted mempools is that they will reproduce the onchain searching observed on L2s with deterministic sequencing rules. However, LUCID differs materially from L2 sequencing in how new information enters the chain and in the bounded scope of decrypted transactions, making a direct comparison misguided. What follows is first a classification of exogenous/autogenous/endogenous MEV, which then informs a discussion of user and protocol welfare.

#### Exogenous MEV

MEV emerges exogenously when conditions outside of the protocol change such that its state becomes imbalanced relative to the rest of the world. Traders then rush to include transactions onchain in order to restore balance between the protocol state and the outside world. A prominent instance is CEX-DEX arbitrage, in which a price movement on a centralized exchange renders an onchain pool stale. Only the DEX leg is directly visible to Ethereum, while the offsetting leg is executed or hedged on a CEX or other offchain venue. From Ethereum’s perspective, the scarce object is therefore priority access for the onchain leg against stale protocol state. By restoring balance, traders extract value. 

On an L1 like Ethereum, exogenous MEV is captured at the &quot;information ingress boundary&quot; (IIB)—the point at which new information enters onchain as the builder commits to a new block. In trusted offchain flow, builders or upstream intermediaries can privately simulate and filter candidate transactions, rely on order matching, private inventory, and other offchain liquidity arrangements. The builder takes in bids on onchain legs for restoring balance relative to the outside world, and includes only the most profitable ones—those that pay the most for the opportunity to execute in the block. In other words, transactions that cannot profitably execute are filtered out or revert offchain. Offchain reverts are beneficial in that transaction intent then does not become public.

When an L2 sequencer that receives private orderflow follows a deterministic scheduling rule, for example ordering by priority fee or on a first-come first-served (FCFS) basis, searchers attempting to extract exogenous MEV without guarantees about the exact state they execute against may instead probe the state during execution. Filtering, fallback logic, and/or reverts then move onchain. Many L2s do not have one discrete IIB per block. The detached relationship between trader and sequencer means that each new transaction acts on exogenous MEV as visible to the sender at submission time. Furthermore, an L2 may utilize sub-blocks, each allowing new information to enter the state, or FCFS ordering such that, from a transaction-ordering perspective, new information may continuously enter and trade against the state.

For the decrypted transactions in LUCID, the relevant point at which new information still can affect internal ordering (the IIB) is the scheduling decision in slot $n$ rather than the moment of execution in slot $n+1$; the relative ordering of decrypted transactions is fixed one slot before they execute (see also the same-slot design, where the decrypted transactions indeed execute toward the end of the block). Most exogenous MEV observable at the IIB of block $n$ is therefore expected to have been captured in block $n$&apos;s own post-ToB segment, before the committed decrypted transactions execute ToB in $n+1$, just as today with offchain builder filtering applied. Onchain searching for exogenous MEV is thus expected to be more limited among decrypted transactions, so conditions on L2s do not translate to LUCID.

There is a narrow secondary IIB in LUCID worth pointing out: key publishers (or self-decrypting senders) can infuse limited new information onchain, by releasing or withholding keys. Since keys are released later than the block commitment time, new exogenous MEV may have emerged in the meantime. Decryptors can therefore selectively withhold or release keys so that only the most profitable (as of the key PTC deadline) pre-committed trades execute. We can expect such trades to be concentrated among the latest decrypted transactions, where the penalty for non-reveal is limited by lower ToB fees. This type of non-reveal does not consume additional blockspace in the way blind searching on an L2 does, since withheld transactions can be replaced by regular transactions in block $n+1$. In essence, it is a form of probabilistic MEV burn. It can be noted that a shorter window between the first IIB and the secondary IIB will serve to reduce the amount of exogenous MEV available for extraction.

#### Endogenous MEV

Endogenous MEV is MEV internal to the protocol state itself, such as DEX pool imbalances that can be rebalanced by arbitrage. On the L1, once the pre-state is known, searchers can identify endogenous MEV opportunities generated in the previous block, for example by transactions not fully internalizing their own backruns, and simulate trades targeting this MEV. Likewise, searchers or the builder may attempt to do so for any other opportunities implied by publicly visible candidate transactions for the current block. Under an idealized model of LUCID, most endogenous MEV observable at the IIB is therefore competed away during block construction, leaving little remaining after the regular transactions have been executed.

The decrypted transactions may produce new endogenous MEV, as, e.g., DEX pools are unbalanced by decrypted transactions. The sender can with the assistance of searchers or other intermediaries still prepare routing and backrunning options offchain, but these cannot be further simulated and filtered after commitment. The exact settlement or backrunning operation can therefore instead be determined onchain after querying the state, whereas candidate routing and backrunning options still can be precomputed offchain at commitment time. This does not reproduce a trusted intermediary&apos;s ability to simulate many candidate backruns against the exact evolving pre-state, but it does preserve a path for pre-committed, targeted backrunning. Importantly, it will lead to increased onchain routing, moving execution competition into the public, composable domain, away from centralized offchain intermediaries that compete on private access and trust.

The sender can place backrunning transactions directly after its trade within a bundle if it is expected to leave residual MEV on the table. The key publisher may also place backrunning transactions there, or at the end of a bundle. Since the backrunning transaction knows the precise operations performed by the MEV-inducing transaction, any required onchain queries can be highly targeted, querying only the most relevant trading pairs or venues before executing the backrunning leg.

Just as for exogenous MEV, in most L2 designs there is no comparable block-level clearing step at the IIB in which sophisticated searchers compete offchain against a known pre-state and the winning opportunities are filtered before execution. Transactions aiming to extract endogenous MEV then need to make queries onchain across the full block. Furthermore, residual opportunities may also emerge between exogenous-MEV-extraction transactions executed across the block. These properties should lead to more onchain searching for endogenous MEV in L2s than in LUCID.

#### Autogenous MEV

An important reason for using the LUCID encrypted mempool is to safeguard transaction-induced autogenous MEV. The transaction may itself reveal a new public signal or opportunity via a large repricing trade or other state transitions whose informational content may not have been observable beforehand. It may also for example atomically settle a series of coincidences-of-wants, or unwind a large lending position whose side effects, such as triggering liquidations or shifting borrowing rates, would be exploitable if disclosed in advance. Thus, the transaction&apos;s own informational or state-changing content can make it vulnerable to being traded around. 

The autogenous MEV transaction&apos;s value derives from the information or matching it carries rather than from capturing an existing onchain imbalance. The private nature makes it less sensitive to the exact pre-state than transactions that compete to capture publicly available MEV (exogenous or endogenous), though execution quality still depends on the state of any pool or market touched. LUCID is therefore particularly suitable for allowing these transactions to enter the public inclusion pipeline without first disclosing information to a privileged intermediary.

The content of the transaction becomes public at key release, but the transaction that generates it was already committed to one slot earlier. Later decrypted transactions can react to it only through pre-committed contingent logic, whereas unrestricted competition over the revealed signal can begin among transactions executing after the decrypted transactions. It is assumed that autogenous MEV transactions from LUCID will capture their own endogenous MEV as outlined in the previous subsection. 

Additionally, the builder has full control over the state under which the first decrypted bundle executes. At commitment time, the builder can therefore communicate relevant pre-state information to the key publisher (without full disclosure), enabling the first ST-commitment to provide offchain revert protection.

A comparison between L2s and LUCID is the most appropriate for transactions capturing autogenous MEV, given similar properties of the inclusion path. However, it should be noted that onchain searching is particularly appealing under low fees, and that the blockspace available to decrypted transactions is limited, setting an upper bound on how much settlement can move fully onchain.

#### Competition for the ToB

Competition for ToB positions revolves around the conditional value $V$ that senders assign to execution at a given position. The sender of an autogenous MEV transaction (with value $V_a$) that always reveals can under a `TOB_FEE_FRACTION` of $F$ post a ToB fee close to $FV_a$, given that it recoups a $(F-1)/F$ share of the fee after successful reveal. An aggregated bundle of size $B$ of such senders can likewise post a ToB fee approaching $FBV_a$. A sender extracting exogenous MEV, with average value $V_e$ in the states where reveal is chosen and reveal probability $p$, can support a ToB fee of roughly $pV_e/((1-p)+p/F)$. The sender would prefer to reveal with a high probability to keep forfeited ToB fees rare, but such setups require a conservative trade that correspondingly should tend to reduce $V_e$. The sender must commit against a post-state of block $n$ that will be close to equilibrium relative to the outside world, and can only profit from shifts taking place after commitment and before the PTC vote on key timeliness.

As an illustrative benchmark, the analysis will use $p=0.5$, which produces $pV_e/((1-p)+p/F) \approx V_e$. In this case, senders of autogenous MEV transactions can outcompete a sender extracting exogenous MEV roughly when $FBV_a &gt; V_e$, where $V_e$ is the exogenous MEV conditional upon a reveal. Besides fixing $p$, this is also a simplification in that it abstracts from the distribution of exogenous opportunities across positions and states. Under this simplified model, the separation in value that can be assigned to the ToB position is therefore roughly $FB$.

Senders can further leverage `max_preceding_commitments`, $m$, to tolerate some preceding commitments, depending on sensitivity to be placed later in the ToB. The additional value separation created under this setup can generally be expressed as $FBf(m)$, where $f(m)$ is increasing, capturing that the marginal value of each additional earlier commitment that could outcompete should be decreasing. The gains are to some extent two-sided, both types of senders can allow the other to precede it.

It should here be noted that the same selector strategy outlined for probabilistic front-running can also be used for extracting exogenous MEV. The sender acquires $m$ earlier commitments and uses the first $m-1$ as binary selectors over $2^{m-1}$ precommitted execution patterns, where the final commitment executes the profitable pattern identified. This allows for constructing a more versatile exogenous MEV arbitrage transaction, with fewer withheld keys per option. The earlier outlined separation in $F$, $B$ and $f(m)$ can therefore be compressed.

In essence, senders targeting exogenous MEV can outbid senders of autogenous MEV in terms of ToB fees if the value of the exogenous MEV is sufficiently larger than the value assigned to autogenous MEV transactions. The issue is that the autogenous MEV sender cannot identify whether someone executing before them extracts exogenous MEV or tries to front-run. The protocol would then need to leverage other means to give room to senders of autogenous MEV transactions, such as for example a trust graph as suggested in [EIP-8105](/EIPs/EIPS/eip-8105) (see Alternative specifications).

Senders who strictly extract exogenous MEV and do not pursue probabilistic front-running can then execute before autogenous MEV senders, if they are trusted by them. Trusted autogenous or endogenous MEV senders can likewise execute before exogenous MEV senders, when they do not compete for the same opportunities. Even so, the differential of $FBf(m)$ is important for establishing a baseline of functionality while reining in monopolistic tendencies in any trust graph. 

It can be noted that a sender that does not wish to belong to a bundle, requires absolutely ToB execution, and cannot leverage trust, indeed has a much lower value separation relative to a sender extracting exogenous MEV.

#### User welfare

MEV captured via both offchain and onchain paths for both regular and encrypted transactions may be shared with the sender according to the arrangements they make with the relevant service provider (e.g., searchers, MEV-Share nodes, key publishers, applications, or any software developed for facilitating routing and backrunning). The sender accounts for many factors when deciding whether it wishes to use the encrypted mempool or not. These include the expected difference in execution quality—including route quality, liquidity access, and residual MEV capture—between offchain and onchain paths; potential costs (searcher fees, gas fees, key publication fees, etc.); its requirement for CR; the risks associated with having plaintext visible to various trusted parties; its requirements for revert protection; and its fear of probabilistic front-running, etc. Under equilibrium, usage will depend on the importance of these various factors.

Users that need to land MEV-inducing transactions permissionlessly onchain without being front-run or sandwiched are the clearest candidates to use the encrypted mempool. For other users, the encrypted mempool inclusion path comes with both benefits and drawbacks. The welfare claim is not that the encrypted mempool dominates private inclusion on every dimension. Trusted intermediaries can offer, e.g., offchain revert protection, that the public path cannot replicate. Rather, it is that users benefit from having an alternative path whose properties—trustlessness, censorship resistance, and independence from any single intermediary—are not available through private channels. In particular, the ability to land autogenous MEV onchain without disclosing intent to a trusted intermediary is an important capability that no private channel provides by construction. Further more, even modest adoption improves welfare if LUCID gives users a credible outside option that disciplines the terms on which private inclusion is offered.

#### Protocol welfare

LUCID protects autogenous MEV, offers a viable path for capturing endogenous MEV produced by decrypted transactions through pre-committed onchain routing and backrunning, and defers a large fraction of exogenous MEV competition to the post-ToB portion of the block where builder filtering already operates today. This is a gradual introduction of encrypted execution into the block, and can be adjusted further going forward. User welfare improves due to the outside option of a trustless, censorship-resistant inclusion path that complements rather than replaces private channels, and diciplines the terms on which those channels are offered.

At the protocol level, the encrypted mempool yields additional structural benefits. It shrinks the share of economically meaningful activity that must route through trusted intermediaries, reducing Ethereum&apos;s exposure to discretionary exclusion, single-point-of-failure outages, and opaque bilateral relationships that entrench incumbent builders. By lowering barriers to builder entry and weakening the competitive advantage conferred by exclusive order-flow access, LUCID helps preserve a level playing field in block construction.

A consequence of commit-before-reveal execution is that some computation previously performed offchain by builders—settlement simulation, route selection, targeted state queries—moves onchain during the bounded ToB segment of the block. This may consume additional gas relative to a world in which a single intermediary filters and optimizes every transaction privately. However, this aligns well with Ethereum&apos;s plans to scale compute over the next few years, and the cost is bounded by the `tob_gas_limit`. It is thus a limited cost for restoring public, composable, and permissionless competition over transaction execution. When the encrypted mempool is underutilized, the unused gas allocation does not encroach on the block gas limit, so regular transactions face no capacity reduction.

In sum, LUCID increases protocol welfare by providing a public inclusion path that protects MEV-sensitive transactions—especially those carrying autogenous MEV whose informational content would be exploitable if disclosed in advance—while preserving full blockspace availability and keeping both inclusion paths open for users to choose between according to their own requirements.

### Key publisher liability for non-reveal

To keep the first version of the design simple, there is no protocol-level mechanism for having key publishers of multi-key bundles assume liability (and thus incur the penalty) in place of the sender for failing to decrypt. Such a mechanism can be added in a subsequent upgrade. However, key publisher-sponsored liability can be approximated out-of-protocol by including a key publisher-funded sponsor ST in the bundle with the user STs.

Each sender provides some agreed-upon `key_publication_fee = d`, and a minimal or 0 `max_tob_fee`. The key publisher includes in the bundle its own minimum-gas transaction with a `max_tob_fee` at a level of `n * d * TOB_FEE_FRACTION`, where `n` is the number of STs in the bundle, each paying `d`. Because bundle ordering uses the aggregate `tob_fee` of executable STs, the bundle now ranks as if the key publisher had posted that ToB fee on behalf of the users.

If the bundle is revealed successfully, the sponsor ST receives back `(TOB_FEE_FRACTION - 1) / TOB_FEE_FRACTION` of its `tob_fee`, so its net ToB-fee burn is `n * d`. That exactly matches the aggregate key publication fees paid by the users. If the bundle is not revealed, the sponsor ST forfeits the full `n * d * TOB_FEE_FRACTION`, so the key publisher economically absorbs the non-reveal penalty.

Since the sender still sets the `max_preceding_commitments`, it does not assume additional risks if the key publisher reneges on its pledge to sponsor the ToB fee of the bundle as agreed upon. The mempool must naturally protect against spam and reject STs that have no chance of getting included. However, any ST can be validly included even with `max_tob_fee = 0`, and key publishers that encourage senders to produce STs relying on ToB fee sponsorship for inclusion—without performing such sponsorship—can also easily be filtered out.

### PTC influence and state observation

A coalition of PTC members, potentially utilizing forked validator clients, could be bribed to systematically vote &quot;timely&quot; on keys originating from specific key publishers, artificially extending their permitted release window. An analogous concern exists today with the PTC vote on payload timeliness, but the payload vote is binary per slot: a few dishonest votes only affect the single question of whether an entire payload is accepted. In LUCID, key-timeliness votes are cast per ST-commitment, and multiple commitments may have keys arriving near the deadline. A few strategic votes can therefore tip the outcome more frequently, amplifying the expected value of bribery. The committee cannot alter the contents of a commitment, change the ordering of ST-commitments, or inject new transactions after commitment.

Once the PTC key-timeliness votes have been observed, the builder knows which decrypted transactions must be included top-of-block. This fully determines the pre-state for the remainder of the block. The PTC vote on keys can realistically be positioned slightly earlier than the vote on the payload, given the small size of key messages, giving the builder additional construction time when the payload arrives well within its deadline.

An alternative is to avoid a separate PTC vote on keys and instead rely on view-merge. Under this approach, the next-slot builder merges differing frozen views of released keys—for example by including missing keys in the block or by otherwise flagging adherence to them. This reduces the direct per-key voting surface and therefore the scope for bribery or collusive deadline extension by the PTC. The trade-off is that builders may have slightly different pre-states. They may then communicate their intended pre-state to relevant parties, and otherwise proceed with offchain filtering and reverts just like today.

### Alternative specifications

#### Same-slot decryption

A same-slot variant of LUCID is possible if the block is split into two independently propagated chunks. The first chunk contains the ST tickets and all ordinary transactions, and is delivered by the primary payload deadline. The second chunk contains decrypted transactions corresponding to ST-commitments already fixed in the bid and potentially additional regular transactions, and is delivered by the secondary payload deadline. Alternatively, ticket charging can be delayed until the second chunk. The builder still publishes its bid with ST-commitments in the beacon block, but would only construct the second chunk after key publishers have released keys. 

The design is inspired by semantic block chunking and the flow is as follows: The builder constructs the bid and the first chunk with ST tickets and regular transactions—including the BAL for executing them—without knowing the ST plaintexts. Once the scheduling beacon block becomes available, the first chunk is released and key publishers publish keys as in the baseline design. The builder decrypts the committed STs, constructs the second chunk including its own BAL, and propagates it while attesters are already validating or executing the first chunk. Decrypted transactions are ordered according to the same pattern as in the baseline design, matching the ST-commitments. The builder may be given the opportunity to include additional regular transactions in the second chunk, ensuring full block utilization under withheld keys. This would turn the design into a mix of block-auction and slot-auction ePBS.

Once attesters have finished executing the first chunk, they switch over to executing the second chunk. The block is valid only if both chunks are timely, which is determined by a singular PTC vote at the deadline of the second chunk. Since the first chunk is committed to in the bid, the builder cannot change the regular transactions upon observing released keys. A benefit of the design is that the builder has responsibility for its included STs, from commitment to execution. A drawback is increased design complexity, requiring semantic block chunking.

#### Frame transaction integration

LUCID can be integrated with [EIP-8141](/EIPs/EIPS/eip-8141) by allowing `signature_id = FRAME_TX_TYPE` to indicate that the ST ticket has no standalone signature and must instead appear inside an enclosing frame transaction. In this mode, the frame transaction has a fixed layout: the first frame is a `VERIFY` frame that authenticates the outer frame transaction, and the second frame is a new `ST` frame whose `data` is the full `SealedTransaction` bytes. P2P nodes extract the `SealedTransaction` from the `ST` frame and otherwise validate it as they do today. The EL extracts the ST ticket from the ST and derives `ticket_from` and `ticket_nonce` from `tx.sender` and `tx.nonce` of the enclosing frame transaction respectively.

Bundles can be supported similarly by introducing a reserved `ST_BUNDLE` frame whose `data` is the full `SealedBundle` bytes and adding `FRAME_TX_TYPE` as a valid `key_publisher_signature_id` in `SealedBundle`. Integration requires a future EIP making coordinated additions to both [EIP-8141](/EIPs/EIPS/eip-8141) and LUCID.

#### Censorship resistance without FOCIL

The design does not strictly require coupling with FOCIL for achieving a reasonable level of censorship resistance for MEV-inducing transactions. Such an integration can therefore be left out from the first implementation. Since the plaintext sender is hidden until reveal, a builder cannot generally censor based on the contents of the plaintext transaction or the identity of its eventual signer. Builders may still rely on a whitelist for visible ticket signers, but absent offsetting external incentives such a builder would be at a competitive disadvantage. It should also be noted that the key publisher is visible in the ST ticket, and some builder may decide to censor based on key publisher identities.

#### Additional bundle and key options

Two additional bundle and key options can be highlighted: single-key bundles that require all STs to be successfully decrypted, and multi-key bundles that allow any ST decryption to fail.

* The single-key bundles can be useful for more elaborate schemes, for example under threshold decryption. TODO: expand upon various ideas under consideration. 
* Multi-key bundles that allow any ST decryption to fail are also viable. One example is again threshold decryption, where the key publisher cannot beforehand guarantee that the sender provided a correct decryptable ST. For these bundles, `max_preceding_commitments` would count each committed ST in the bundle as a commitment.

In the interest of forward-compatibility, a `schemeID` byte may be added to the `ciphertext_envelope` to facilitate decryption optionality.

#### Trust graph

One way to reduce the fee pressure created by `max_preceding_commitments` is to distinguish between trusted and untrusted key publishers, inspired by the design proposed in [EIP-8105](/EIPs/EIPS/eip-8105). The main residual front-running risk comes from earlier commitments whose key publishers the sender does not trust to avoid strategic withholding. Earlier commitments from trusted key publishers need not consume the same safety budget. 

A future version can therefore replace or complement `max_preceding_commitments` with `max_preceding_untrusted_commitments`. Decryptors would be nodes in a directed trust graph maintained in a canonical registry of key publisher addresses and trust edges. A key publisher `A` trusts key publisher `B` if there is a path from `A` to `B` in that graph. For an ST or bundle using key publisher `A`, an earlier commitment from key publisher `B` counts toward the limit only if `A` does not trust `B`. Trust is directional: commitments from `B` may precede `A` without consuming `A`’s bound when `A` trusts `B`, but not vice versa unless `B` also trusts `A`.

This allows users to delegate trust selection to their chosen key publisher instead of listing trusted third parties in every ST. It also reduces pressure toward a single dominant key publisher. For example, a small key publisher can trust a larger, widely used key publisher, allowing its users to be placed after that key publisher&apos;s commitments without requiring those commitments to count against their safety bound. The difference to [EIP-8105](/EIPs/EIPS/eip-8105) is that there is no hard requirement that only trusted key publishers may execute before the transaction, unless `max_preceding_untrusted_commitments = 0`. This expansion is viable because of the additional steps that the design takes against probabilistic front-running, including the offchain decryption process. A few untrusted key publishers are therefore unlikely to be a concern for most users.

## Backwards Compatibility

This EIP introduces backward-incompatible changes to both the consensus and execution layers and therefore requires a hard fork. It extends block validity rules, `ExecutionPayloadBid`, `ExecutionPayload`, `InclusionList`, the Engine API, beacon-chain RPC interfaces, and the P2P handling of inclusion lists, sealed transactions, bundles, keys, and key-timeliness votes. Clients that are not upgraded will not be able to validate or construct post-fork blocks correctly.

This EIP does not remove or alter the semantics of existing plaintext transaction types. Legacy transactions and other non-LUCID transactions remain valid and retain their ordinary execution semantics. Users that do not opt into sealed transactions may continue to use the public mempool as before. Wallets, builders, relays, indexers, tracers, and RPC implementations that wish to support LUCID must add support for the new transaction types, commitment rules, and key-propagation flows, etc.

## Security Considerations

Denial-of-service vectors for STs are instances with a low ToB fee and low `max_preceding_commitments`, particularly STs with these characteristics that are not intended to be bundled. Given that the utilization of the encrypted mempool is unknown—and may vary going forward—there are no fixed settings that can be established at this point for STs that should or should not be propagated. Furthermore, key publishers that establish a pattern of sponsorship as outlined in the Rationale may garner more permissive bounds during filtering.

Users and wallets must treat the choice of key publishers as a security decision. They should prefer key publishers and encryption instructions that are publicly documented and audited. 

The DEM uses `ChaCha20-Poly1305`, which must not reuse the same `(k_dem, nonce)` pair across different ciphertexts. In this EIP, the DEM nonce is protocol-defined rather than chosen by the encryptor: for STs it is derived from `(chain_id, ticket_from, ticket_nonce)`. Decryptors and self-decrypting senders should therefore ensure that the released `k_dem` is bound to the intended ticket or bundle context, and that any reusable secret recovered from the opaque `header` is not itself revealed. Since the protocol fixes `aad = b&quot;&quot;`, this binding must come from key derivation rather than AEAD associated data. Reuse of a `(k_dem, nonce)` pair can break confidentiality and integrity.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 04 Mar 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8184</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8184</guid>
      </item>
    
      <item>
        <title>snap/2 - BAL-Based State Healing</title>
        <category>Standards Track/Networking</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8189-snap-2-bal-based-state-healing/27953</comments>
        
        <description>## Abstract

This EIP upgrades the `snap` protocol from version 1 to version 2, removing `GetTrieNodes` (0x06) / `TrieNodes` (0x07) and adding `GetBlockAccessLists` (0x08) / `BlockAccessLists` (0x09) to enable BAL-based state healing during snap sync.

## Motivation

[EIP-7928](/EIPs/EIPS/eip-7928) introduces block-level access lists (BALs) that capture all state changes per block, committed to block headers via `block-access-list-hash`. With BALs available, the snap sync healing phase — which iteratively fetches individual Merkle trie nodes via `GetTrieNodes` to resolve state inconsistencies — can be replaced entirely.

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.

## Specification

### Protocol Version

The protocol version is incremented from `snap/1` to `snap/2`. Peers negotiate the version during the RLPx capability handshake.

### Removed Messages

| Message | ID | Reason |
|---------|----|--------|
| `GetTrieNodes` | 0x06 | Replaced by BAL-based healing |
| `TrieNodes` | 0x07 | Replaced by BAL-based healing |

### New Messages

#### GetBlockAccessLists (0x08)

`[request-id: P, [blockhash₁: B_32, blockhash₂: B_32, ...], bytes: P]`

Request BALs for the given block hashes. `bytes` 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.

BALs are only available for blocks after [EIP-7928](/EIPs/EIPS/eip-7928) activation and within the retention period defined therein.

Notes:

- Nodes **must** always respond to the query.
- If the node does not have the BAL for a requested block hash, it **must** return the RLP empty string (`0x80`) at that position.
- The responding node is allowed to return **fewer** entries than requested (serving the `bytes` soft limit or Quality of Service (QoS) limits), truncating from the tail. Returned entries **must** preserve request order.
- Nodes **should** retain BALs for orphaned (non-canonical) blocks within the retention period defined in [EIP-7928](/EIPs/EIPS/eip-7928). 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.

#### BlockAccessLists (0x09)

`[request-id: P, [block-access-list₁, block-access-list₂, ...]]`

Response to `GetBlockAccessLists`. Each element corresponds positionally to a block hash from the request. The RLP empty string (`0x80`) is returned for blocks where the BAL is unavailable.

The responding node **should** respect the `bytes` limit from the request. In the absence of a specific limit, the recommended soft limit for `BlockAccessLists` responses is 2 MiB.

### Unchanged Messages

Messages 0x00–0x05 (`GetAccountRange`, `AccountRange`, `GetStorageRanges`, `StorageRanges`, `GetByteCodes`, `ByteCodes`) are unchanged from snap/1.

### Validation

Received BALs **must** be validated by computing `keccak256(rlp.encode(bal))` and comparing against the `block-access-list-hash` in the corresponding block header. See [EIP-7928](/EIPs/EIPS/eip-7928) for the BAL encoding format.

### Synchronization Algorithm

snap/2 replaces trie healing with BAL-based catch-up:

1. Download headers and identify the chain head.
2. 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.
3. Bulk download state at P via `GetAccountRange`, `GetStorageRanges`, `GetByteCodes`.
4. 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&apos; via `GetBlockAccessLists` (where P&apos; is the new pivot), applies the diffs locally, and continues bulk download at P&apos;.
5. 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 `GetBlockAccessLists`, 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.
6. If the pivot advances further during step 5, repeat for the newly produced blocks.
7. Recompute and verify the state root against the latest header.

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 `GetAccountRange` / `GetStorageRanges`. 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.

## Rationale

### Separate Protocol vs. eth/71

This follows the established snap design philosophy. `GetByteCodes` was duplicated from `eth` into `snap` for the same reason:

&gt; *This functionality was duplicated into `snap` from `eth/65` to permit `eth` long term to become a chain maintenance protocol only and move synchronization primitives out into satellite protocols only.*

Synchronization primitives belong in satellite protocols. `snap` is optional and independently versioned; duplicating BAL exchange here avoids coupling sync functionality to `eth`.

### Removing GetTrieNodes

BAL-based healing makes trie node fetching for state reconciliation unnecessary. Removing these messages avoids maintaining two healing mechanisms.

## Backwards Compatibility

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 `block-access-list-hash` header field ([EIP-7928](/EIPs/EIPS/eip-7928)) is absent for earlier blocks.

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.

## Security Considerations

### Amplification

A `GetBlockAccessLists` request can trigger responses significantly larger than the request. Implementations **should** apply rate limiting and respect the 2 MiB soft response limit.

### Unavailable Data

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.

### Application Order

BALs **must** 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.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</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>Quick Slots</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8198-quick-slots/28057</comments>
        
        <description>## Abstract

This EIP makes `SLOT_DURATION_MS` a runtime configuration on the consensus layer rather than a compile-time constant, then uses that infrastructure to reduce slot duration. Block gas limits and blob parameters scale proportionally to maintain constant throughput per unit time.

## Motivation

Slot time is the heartbeat of Ethereum&apos;s user experience. Every second shaved off means faster transaction landings, faster exchange deposits, and faster real-world payments. But the benefits extend well beyond UX.

### User experience

Twelve seconds is slow. It is perceptible in payments, exchange deposits, and every on-chain interaction. Reducing slot time brings Ethereum closer to the responsiveness users already expect from modern financial infrastructure.

### DEX pricing and MEV

Arbitrage losses scale with the square root of inter-block time. Going from twelve to eight seconds cuts this by roughly 18%, tightening on-chain pricing and reducing value extracted from users. MEV extraction is also non-linear in slot time: shorter slots compress the surplus available per block, squeezing the entire MEV supply chain.

### Empty blocks and ePBS

Proposer builder separation grants builders a free option on the block — they can abandon it if prices move against them. The value of that option grows with slot duration. Shorter slots shrink it, mitigating the empty block problem.

### Preconfirmation complexity

Preconfirmation protocols exist to paper over twelve-second latency. Reducing slot time attacks the root cause, decreasing the need for additional trust assumptions and protocol complexity layered on top.

### L2 sequencing &amp; interop

Based rollups inherit L1 block time as their sequencing interval. Faster L1 slots mean faster based rollups, with zero changes required on the rollup side.

L2s that use the L1 for interop between themselves also inherit the L1&apos;s slot duration. Shorter slots reduce the latency of interop transactions.

### A phased approach to shorter slots

Nobody knows the safe minimum slot duration with today&apos;s client implementations. Rather than stalling on the choice of a number, this EIP separates the work into three phases:

1. **Variable slot timing infrastructure** — Remove the assumption that slots are twelve seconds. Update background task scheduling, timing constants, functions such as `compute_time_at_slot(...)`, and fork transition logic to derive timing from a runtime configuration.
2. **CL performance characterization** — Systematically identify consensus layer bottlenecks through devnets and benchmarks, analogous to the execution layer&apos;s bloat-nets and perf-nets. Current understanding of blob propagation limits, attestation aggregation capacity, and local block building times remains incomplete.
3. **Iterative slot time reduction** — Cut slack from the slot duration based on the results of phase 2. Address client constraints, reduce further as headroom emerges, iterate.

Phase 1 has value regardless of the final number. It turns `SLOT_DURATION_MS` from a compile-time constant into a runtime configuration, so future slot duration changes become configuration updates rather than contentious protocol upgrades. If analysis ultimately shows twelve seconds is optimal, the effort still delivers a cleaner client architecture, a comprehensive CL performance characterization, and the readiness to reduce when conditions permit.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

All arithmetic in this specification uses integer division (truncating toward zero). Formulas are written with the multiply performed before the divide to preserve precision.

### Parameters

At `&lt;FORK_EPOCH&gt;`, the following constants take effect. All consensus layer timing derivations MUST use the fork-activated values from the fork epoch onward. Functions that compute wall-clock time from slot numbers, such as `compute_time_at_slot(...)`, MUST account for the duration change at the fork boundary.

| Constant | Current | New |
| -------- | ------- | --- |
| `SLOT_DURATION_MS` | 12,000 | 8,000 |
| `BASE_REWARD_FACTOR` | 64 | 42 |
| `INACTIVITY_PENALTY_QUOTIENT_BELLATRIX` | 16,777,216 | 37,748,736 |
| `MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS` | 4,096 | 6,144 |
| `MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS` | 4,096 | 6,144 |
| `CHURN_LIMIT_QUOTIENT` | 65,536 | 98,304 |
| `MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA` | 128,000,000,000 | 85,333,333,333 |
| `MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT` | 256,000,000,000 | 170,666,666,666 |

### Gas limit adjustment

The first block produced at or after the fork activation timestamp MUST set its gas limit to:

```
fork_gas_limit = (parent_gas_limit * SLOT_DURATION_MS) // old_slot_duration_ms
```

where `old_slot_duration_ms` is the pre-fork value (12,000). The normal gas limit adjustment rule (±1/1024) does not apply to this block. From the following block onward, normal gas limit voting resumes using `fork_gas_limit` as the base.

### Blob parameter adjustment

A new entry MUST be appended to the `BLOB_SCHEDULE` (as defined in [EIP-7892](/EIPs/EIPS/eip-7892)) at `&lt;FORK_EPOCH&gt;` with:

```
new_max_blobs = (old_max_blobs * SLOT_DURATION_MS) // old_slot_duration_ms
```

where `old_max_blobs` is the `MAX_BLOBS_PER_BLOCK` from the most recent preceding `BLOB_SCHEDULE` entry. The blob target is derived from `MAX_BLOBS_PER_BLOCK` as usual.

## Rationale

### Why infrastructure first

The bottleneck is not picking a number. It is the hardcoded twelve-second assumption spread across every consensus and execution client. Delivering this change as a fork forces client teams to audit and remove these assumptions — once that work is done, future slot duration changes become straightforward fork-activated parameter updates rather than invasive refactors. The infrastructure work compounds across future upgrades.

### Why eight seconds

This EIP takes the approach of building the variable slot timing infrastructure first, then reduce the slot duration conservatively as a non-headliner change. Eight seconds is chosen as a reasonable placeholder value that would provide a real UX win, if we discover we can go lower, we should. Even ten seconds would be a meaningful win. The exact target follows from phase 2 performance characterization and may be revised before deployment.

### Constant scaling

The general principle is: **do not adjust a constant unless there is a concrete security or economic failure from leaving it unchanged.** Most epoch- and slot-denominated constants have generous margins: `EPOCHS_PER_SLASHINGS_VECTOR` shrinks from ~36 to ~24 days but remains far longer than any plausible attack window; `MIN_VALIDATOR_WITHDRAWABILITY_DELAY` shrinks from ~27 to ~18 hours but slashing detection takes minutes. `SLOTS_PER_EPOCH` remains 32; the resulting ~4.3 minute epochs mean finality improves from ~13 to ~8.5 minutes for free. Only four categories require adjustment:

**Issuance.** `BASE_REWARD_FACTOR` scales linearly with epoch duration to preserve annualized issuance. Integer truncation (42 vs. ideal 42.667) under-issues by ~1.6%, less than typical participation rate fluctuations.

**Inactivity leak.** The cumulative penalty is quadratic in epoch count (`K^2`), so the quotient scales by the square of the epoch ratio. As a divisor, a larger quotient produces a smaller per-epoch penalty, compensating for the faster epoch cadence. `INACTIVITY_SCORE_BIAS` cancels algebraically between the score numerator and penalty denominator and needs no adjustment. `INACTIVITY_SCORE_RECOVERY_RATE` governs post-leak decay; modestly faster recovery is benign.

**Data availability windows.** Hard external dependency on rollup challenge periods (~7 days). Scaled inversely to preserve wall-clock duration.

**Churn limits.** Preserve the wall-clock weak subjectivity period. Per-epoch limits scale by `new // old`; the quotient (a divisor) scales by `old // new`.

Blob parameters scale proportionally; integer truncation can reduce per-slot capacity by at most one blob when `old_max_blobs` is not a multiple of 3 (for 12→8s).

### Gas limit

The gas limit scales by `new_slot_duration_ms // old_slot_duration_ms`, preserving the gas-per-second invariant. This is enforced at the fork block rather than relying on validator voting, which at ±1/1024 per block would take ~45 minutes to converge — during which gas-per-second throughput would exceed the target by up to 50%. The steady-state base fee is unchanged because the gas-per-second target is preserved. A worst-case one-time transient of ~12.5% resolves within one to two blocks. After the fork block, normal gas limit voting resumes; validator sovereignty over this parameter is unchanged.

### Attestation deadlines

Intra-slot timing deadlines are specified in basis points of `SLOT_DURATION_MS` and scale automatically with slot duration. Whether the resulting absolute deadlines remain feasible is a phase 2 question; the BPS values may need tuning based on empirical results.

### Fallback

If going below twelve seconds proves infeasible, the outcome defaults to the status quo plus a properly characterized CL and future-ready infrastructure. The slot duration stays at twelve seconds, but the work of removing hardcoded timing assumptions delivers a cleaner client architecture and the readiness to reduce when conditions permit.

## Backwards Compatibility

This EIP requires a hard fork. The consensus layer bears most of the change: clients must replace hardcoded twelve-second slot assumptions with fork-aware timing derivations. The execution layer impact is limited to a one-time gas limit and blob parameter adjustment at the fork boundary. Applications and tooling that assume twelve-second block times will need updating.

## Security Considerations

### Network propagation

Tighter slots shrink the window for block propagation, validation, and attestation aggregation. Intra-slot timing deadlines are specified in basis points and scale automatically, but the resulting absolute durations must remain feasible for real-world network conditions. Phase 2 (CL performance characterization) is explicitly designed to surface these bottlenecks before committing to a final slot duration.

### Validator hardware requirements

Shorter slots raise per-second computational and bandwidth demands. Validator hardware distribution should be considered when deciding the slot duration. Note that peak bandwidth per payload is not affected — gas per block and the number of blobs decreases proportionally with slot time.

### Weak subjectivity period

The weak subjectivity period depends on the rate at which the validator set can turn over. Without churn limit adjustment, per-epoch churn rates applied over more epochs per year would allow the validator set to change faster in wall-clock time, shrinking the safe window for weak subjectivity checkpoints. This EIP scales churn limits to preserve the current wall-clock churn rate, maintaining the existing weak subjectivity period.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Tue, 17 Mar 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8198</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8198</guid>
      </item>
    
      <item>
        <title>Sandboxed Smart Wallet</title>
        <category>Standards Track/ERC</category>
        
          <comments>https://ethereum-magicians.org/t/erc-8199-sandboxed-smart-wallet/28029</comments>
        
        <description>## Abstract

Automation through Agents in a wallet is widely being adopted, and many approaches have been discussed and proposed for secure delegation of access/assets to agents. Including session keys, Trusted Execution Environment (TEE) based policy engine, shared account key, in which some degree of trust and trade-offs exist.

This standard outlines the smart wallet particularly useful for agents of high frequency trading entities to operate in a completely sandboxed(detached) environment, or any other wallets seeking for secure agentic operations, while still enabling the owner to have complete control over the sandboxed smart wallet.

The sandbox is achieved through the complete detach of agent smart wallet from the owner wallet and only having the owner wallet persistent access to the agent smart wallet.

## Motivation

Automation through an agentic infrastructure as a wallet is an inevitable flow of the industry. Although agents bring in a highly autonomous system with convenience, it is important that these adoptions should incorporate security mechanisms together.

Session key like architecture, although having the advantage of shared owner wallet, has limitations on the security postures unless imposed with an enforced whitelist mechanism that limits the access of the session key, which potentially limits the capability of what agent can perform.

A TEE based policy engine, although it comes with high convenience, relies fully on central trust.

Shared account key, despite the most intuitive and convenient solution, gives unlimited access to the wallet unless the user explicitly approves each operation, which then conflicts with the goal of autonomous automation through agents.

This standard proposes an interface for agents that operates in a sandboxed, detached environment from the owner account, while the owner maintains access to the sandbox smart wallet.

Key factors taken into consideration for the standard:

1. Complete sandboxed account for agents.
2. Owner account persistently having access to sandboxed wallet.
3. Time-gated &amp; optional permission checks, enforceable.
4. Multi-agent sharing a sandboxed wallet.
5. Benefits exist when Agents also use smart wallet.



1. **Complete sandboxed account for agents:** The standard separates the execution environment of agents from the owner account. This removes the possibility of security breach or hallucination of AI agents from impacting the owner account, unintendedly or intendedly. Also, session key, granular permission driven approach that shares the owner wallet inherently brings in permission evasion issues unless imposing whitelist driven approach. This sandboxed approach makes this standard free of these concerns.
2. **Owner account persistently having access to sandboxed wallet:** The relationship between owner account and sandboxed wallet is one-directional. The owner account has permission to withdraw assets, or remove the agent key from accessing the sandboxed wallet. While the sandboxed wallet does not possess any rights against the owner account.
3. **Time-gated &amp; optional permission checks, enforceable:** Although the sandboxed account environment itself already gives limited boundary in execution, the standard imposes time-gated &amp; optional permission checks, enforceable in each agentic execution, for policy or additional security measures.
4. **Multi-agent sharing a sandboxed wallet:** Multiple agents can share a single sandboxed wallet. Sharing the same asset, on-chain address reputation, transaction history. Based on the want of the user.
5. **Benefits exist when Agents also use smart wallet:**
    1. **Gas Abstraction**
   
        i. Agents also confronts the native gas requirement. Gas Abstraction by smart wallet will benefit agents in execution and portfolio management.
    2. **On-Chain Conditional Execution &amp; Sophisticated trade operations**
        
        i. Conditional executions on-chain through checks and multi-layered sophisticated trade requires smart contract to batch, layer conditions of pre/post state.
        Smart Wallet can sufficiently assist in fulfilling these requirements.
    3. **Parallel execution**
        
        i. In high frequency trading environment, agents need to be able to execute multiple transactions in parallel. But managing a 1 dimension, linear nonce across multi-agent sharing a wallet, or for a single wallet as well for high frequency trading can be complex. This can be simplified with 2d nonce of smart wallet, or other custom mechanisms imposed by the smart wallet.


![Single Sandboxed Smart Wallet](/EIPs/assets/eip-8199/Single-SandboxedSmartWallet.svg)


![Multi Sandboxed Smart Wallet](/EIPs/assets/eip-8199/Multi-SandboxedSmartWallet.svg)


## Specification

The keywords “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.

A Sandboxed Smart Wallet MUST implement the following interface:

```solidity
/// @title Sandboxed Smart Wallet Standard
interface SandboxedSmartWallet {

	struct Agent {
		address agentKey;
		uint256 validityTimestamp; // pack( uint128 validAfter + uint128 validUntil )
		Check[] checkers;
	}
		
	struct Check {
		address to;
		bytes termsData;
	}

	event AgentRegistered(Agent calldata);
	event AgentRemoved(Agent calldata);
	
	/// @dev registers an agent to the smart wallet.
	/// only callable by the owner.
	/// The function should emit the AgentRegistered() event upon successful registration of agent.
	/// If same agentKey Agent that is active, is being registered, the function should revert.
	///
	/// @param agents the Agents to be registered.
	function registerAgents(Agent[] calldata agents) external;
		
	/// @dev removes an agent from the smart wallet.
	/// only callable by the owner.
	/// The function should emit the AgentRemoved() event upon successful removal of agent.
	/// Even if the agentKey&apos;s time validity has expired or is not valid yet,
	/// if the agentKey exists, the function should not revert.
	///
	/// @param agents the Agents to be removed.
	function removeAgents(Agent[] calldata agents) external;
		
	/// @dev returns the list of agents.
	/// It returns the full list of agents, regardless of its time validity.
	///
	/// @return agents the Agent registered to this smart wallet.
	function getAgents() external view returns (Agent[] memory);
		
	/// @dev returns if the given agentKey is active. (registered + within validity time window)
	/// @return bool the value indicating if the agent is active.
	function isAgentActive(address agentKey) external view returns (bool);
	
	struct Execution {
		address target;
		uint256 value;
		bytes data;
	}
		
	/// @dev invokes agentic execution. relayable by any entity.
	/// The time validity of execution signature, if any, can be encoded together with the signature parameter.
	/// The signature parameter includes the signature from the agentKey.
	///
	/// @param execs the struct array of executions to be performed.
	/// @param signature the signature of signed executions
	function invokeAgentExec(Execution[] calldata execs, bytes calldata signature) external;
		
	/// @dev returns the owner of the sandboxed smart wallet.
	/// The owner has access to perform arbitrary execution,
	/// including the complete asset withdrawal from the wallet.
	///
	/// @return address of the owner.
	function owner() external view returns (address);
		
	/// @notice only the address returned by the owner() can call this function.
	/// @dev The execution path for owner. The owner can withdraw assets,
	/// or perform arbitrary execution from this wallet.
	///
	/// @param execs the struct array of executions to be performed.
	function executeFromOwner(Execution[] calldata execs) external;

}
```

Contracts MAY implement [ERC-165](/EIPs/EIPS/eip-165).

The `Checker` smart contract MUST implement the following interface.

```solidity
/// @title Checker. Pre/Post execution checker of SandboxedSmartWallet
interface Checker {

	/// @dev called before the execution. validates the execs based on the termsData.
	/// 
	/// @param execs the struct array of executions to be performed.
	/// @params termsData the calldata outlining the terms of validity.
	/// @return bool value indicating the success/failure of check.
	function preCheck(Execution[] calldata execs, bytes calldata termsData) external returns (bool);
		
	/// @dev called after the execution. validates the execs based on the termsData.
	///
	/// @param execs the struct array of executions to be performed.
	/// @params termsData the calldata outlining the terms of validity.
	/// @return bool value indicating the success/failure of check.
	function postCheck(Execution[] calldata execs, bytes calldata termsData) external returns (bool);

}
```

## Rationale

1. The interface of `SandboxedSmartWallet` is kept with only the essentials for agentic operations. The additional capability, e.g., [ERC-4337](/EIPs/EIPS/eip-4337) based gas abstraction, etc is left untouched for the wallet developers to decide on their preference of the stack.
2. The initial bootstrapping process is to transfer the initial funds from Owner wallet to the `SandboxedSmartWallet`. Token approval model is not a recommended process to ensure that there is no logical or account level correlation that `SandboxedSmartWallet` can interfere or impact the Owner Wallet.
3. Time based validity window is introduced so Agents can have a limited time boundary that can access the user’s asset within the `SandboxedSmartWallet`.
4. Standard interface referencing [ERC-173](/EIPs/EIPS/eip-173)’s `owner()` is imposed for better compatibility with ownership based tooling/sdks.
5. Through the interface of `executeFromOwner()`, Owner Wallet, at any point in time can withdraw assets or perform arbitrary execution. Creating a one-directional relationship where only Owner Wallet can impact `SandboxedSmartWallet` and not vice versa.

## Backwards Compatibility

TBD &lt;!-- TODO --&gt;

## Security Considerations

1. `SandboxedSmartWallet` should impose signature replay attack protection for the invoke of `invokeAgentExec()` signature to make agentKey signature non-replayable.
2. Agents should be strictly restricted from calling the `SandboxedSmartWallet` outside the validity window of `validityTimestamp`.
3. `isAgentActive()` should only return `true` if `validityTimestamp` is within current `block.timestamp`.
4. It is highly recommended to add time-boxed signature for `invokeAgentExec()`.
5. For Checker’s `termData` composition, it is recommended to perform whitelist-style enforcement compared to blacklist-style enforcement for stronger enforcement checks.
6. `executeFromOwner()` is recommended to be always open for Owner Wallet to perform execution. The standard however does not enforce a certain behavior on this.
7. `SandboxedSmartWallet` can optionally impose [ERC-173](/EIPs/EIPS/eip-173) or [ERC-8023](/EIPs/EIPS/eip-8023) based ownership mechanism for secure ownership management.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 19 Mar 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8199</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8199</guid>
      </item>
    
      <item>
        <title>EVMification</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8200-evmification/28036</comments>
        
        <description>## Abstract

Replaces the RIPEMD-160 (`0x03`), MODEXP (`0x05`), BLAKE2f (`0x09`), BLS12_MAP_FP_TO_G1 (`0x10`), and BLS12_MAP_FP2_TO_G2 (`0x11`) precompiles. At the start of executing the block in which this change activates, deploy EVM bytecode at each precompile address that provides equivalent functionality. This follows the same approach as [EIP-7666](/EIPs/EIPS/eip-7666), which EVMifies the identity precompile (`0x04`).

## Motivation

Ethereum&apos;s precompiles impose ongoing maintenance costs and increase the risk of consensus bugs across client implementations. Some also represent a significant barrier for zkEVM implementations since each precompile usually requires a separate, optimized non-EVM implementation.

[EIP-7666](/EIPs/EIPS/eip-7666) demonstrates this approach with the identity precompile. This EIP extends the same technique to five additional precompiles that either see limited use or can be evmified with a small cost:

- **RIPEMD-160** (`0x03`): A hash function with minimal on-chain usage. Its primary historical use case (Bitcoin-style address derivation) is not common in Ethereum contracts.
- **MODEXP** (`0x05`): Modular exponentiation. In our analysis, we saw that 99.99% of modexp usage came from 256 bit modulus for SNARK verification, whereas the very rarely used RSA modulis occupied the rest.
- **BLAKE2f** (`0x09`): The BLAKE2 compression function. Our analysis shows that this is now predominantly used by a single contract.
- **BLS12_MAP_FP_TO_G1** (`0x10`): Maps a base field element to a G1 point on the BLS12-381 curve. This is pure field arithmetic that can be implemented in EVM.
- **BLS12_MAP_FP2_TO_G2** (`0x11`): Maps an extension field element to a G2 point on the BLS12-381 curve. This is pure field arithmetic that can be implemented in EVM.

Replacing these precompiles with EVM bytecode reduces the number of special-cased implementations that every Ethereum client must maintain, simplifying the protocol and making it more accessible to new client implementations.

## Specification

The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;, &quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).

### Constants

| Parameter | Value |
| - | - |
| `RIPEMD160_ADDRESS` | `0x0000000000000000000000000000000000000003` |
| `MODEXP_ADDRESS` | `0x0000000000000000000000000000000000000005` |
| `BLAKE2F_ADDRESS` | `0x0000000000000000000000000000000000000009` |
| `BLS12_MAP_FP_TO_G1_ADDRESS` | `0x0000000000000000000000000000000000000010` |
| `BLS12_MAP_FP2_TO_G2_ADDRESS` | `0x0000000000000000000000000000000000000011` |
| `RIPEMD160_EVM_CODE` | &lt;-- TODO: bytecode --&gt; |
| `MODEXP_EVM_CODE` | &lt;-- TODO: bytecode --&gt; |
| `BLAKE2F_EVM_CODE` | &lt;-- TODO: bytecode --&gt; |
| `BLS12_MAP_FP_TO_G1_EVM_CODE` | &lt;-- TODO: bytecode --&gt; |
| `BLS12_MAP_FP2_TO_G2_EVM_CODE` | &lt;-- TODO: bytecode --&gt; |

### Deployment

At the start of the block in which this fork activates, for each precompile address and its corresponding EVM code listed above:

1. Set the code of the address to the corresponding `EVM_CODE`.
2. Starting from and including that block, the address MUST no longer be treated as a precompile.

### Gas Costs

After activation, calls to these addresses are charged according to standard EVM execution costs rather than the precompile-specific gas formulas. The expected gas cost differences are documented below.

#### RIPEMD-160

The current precompile charges `600 + 120 * ceil(len(data) / 32)` gas. The EVM implementation will charge the sum of the opcodes executed, which is expected to differ.

&lt;-- TODO: gas comparison with bytecode version --&gt;

#### MODEXP

The current precompile uses a complex formula based on the lengths of the base, exponent, and modulus, as well as the iteration count derived from the exponent. The EVM implementation will charge standard opcode costs. Due to the complexity of modular exponentiation in EVM, gas costs are expected to be higher for large inputs.

&lt;-- TODO: gas comparison with bytecode version --&gt;

#### BLAKE2f

The current precompile charges `rounds` gas (the number of rounds specified in the input). The EVM implementation will charge the sum of the opcodes executed.

&lt;-- TODO: gas comparison with bytecode version --&gt;

#### BLS12_MAP_FP_TO_G1

The current precompile charges `5500` gas. The EVM implementation will charge the sum of the opcodes executed.

&lt;-- TODO: gas comparison with bytecode version --&gt;

#### BLS12_MAP_FP2_TO_G2

The current precompile charges `23800` gas. The EVM implementation will charge the sum of the opcodes executed.

&lt;-- TODO: gas comparison with bytecode version --&gt;

## Rationale

### Same mechanism as EIP-7666

This EIP follows the same deployment mechanism established by [EIP-7666](/EIPs/EIPS/eip-7666): deploying EVM bytecode directly at the precompile address at fork time. This preserves backward compatibility for contracts that call these addresses, as they continue to work with the same interface.

### Accepting EVM gas costs

Rather than attempting to replicate the exact gas formulas of the original precompiles, this EIP accepts the natural EVM execution gas costs. Gas repricings have been done in the Ethereum ecosystem several times before and their effects are well understood. Nevertheless, we will carry out an impact analysis of each precompile.

### Bytecode at precompile address vs. library contracts

Deploying the bytecode directly at the existing precompile address ensures that all existing contracts calling these addresses continue to function without modification. Alternative approaches such as removing the precompile and expecting callers to use library contracts at other addresses would break backward compatibility of already deployed contracts.

## Backwards Compatibility

The functionality at each address is preserved. Gas costs will differ from the current precompile-specific formulas, which may affect contracts that depend on precise gas calculations when calling these precompiles. We have updated the gas cost of precompiles in the past and have accepted that contracts relying on hardcoded gas costs for precompiles is bad practice.

## Test Cases

&lt;-- TODO --&gt;

## Security Considerations

### Gas cost changes

The change in gas costs could affect contracts that rely on specific gas behavior when calling these precompiles. Contracts that pass a fixed gas amount to these addresses may revert if the EVM implementation costs more than the precompile did.

### Implementation correctness

The EVM bytecode deployed at each address must be thoroughly tested and audited to ensure it produces identical outputs to the original precompile for all valid inputs, and handles invalid inputs in the same way.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Sat, 21 Mar 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8200</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8200</guid>
      </item>
    
      <item>
        <title>Withdrawal credentials preregistration</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8205-withdrawal-credentials-preregistration/28084</comments>
        
        <description>## Abstract

This EIP introduces a preregistration mechanism that allows a validator key holder to commit to specific withdrawal credentials before any deposit is made, addressing a known deposit front-running vulnerability in delegated staking. Preregistrations are submitted through a new [EIP-7685](/EIPs/EIPS/eip-7685) request type via a system contract on the execution layer, rate-limited by an [EIP-1559](/EIPs/EIPS/eip-1559)-style exponential fee mechanism. The consensus layer stores the preregistration in beacon state and enforces it at deposit processing time: matching deposits proceed and the preregistration is consumed; mismatched deposits are silently rejected. The mechanism is fully optional — deposits for public keys without a preregistration are processed exactly as today.

## Motivation

In delegated staking, the entity funding a validator and the entity generating the BLS keypair are distinct parties. This separation is common across liquid staking protocols, staking-as-a-service providers, and any arrangement where one party provides capital and another operates the validator. The BLS key is the validator&apos;s identity: the first deposit for a given pubkey establishes the withdrawal credentials permanently under first-deposit-wins semantics. The key holder can therefore submit a deposit with attacker-controlled withdrawal credentials before the funding party&apos;s deposit is processed. The funding party has no on-chain guarantee that the withdrawal credentials it intends will be honored.

At least a third of all staked ETH flows through delegated architectures with identifiable protocol-level protections against this attack. Since no on-chain mechanism exists to bind a public key to withdrawal credentials before the first deposit, every affected product has independently built application-layer defenses — bond-based pre-deposit schemes, guardian committees, or both. These defenses work (no known exploits have occurred in production), but each one is built, audited, and maintained independently, and new entrants are vulnerable by default until they do the same.

Preregistration addresses this at the protocol layer: the key holder signs a binding commitment to specific withdrawal credentials before any deposit is made, and the consensus layer enforces this commitment at deposit processing time.

For an extended analysis of the problem scope, existing application-layer defenses, and data sources, see the discussion thread linked in the header.

## Specification

### Configuration

#### Execution layer

| Name                                                        | Value                                        | Comment                                                                      |
| ----------------------------------------------------------- | -------------------------------------------- | ---------------------------------------------------------------------------- |
| `VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS`       | `TBD`                                        | Where to call and store relevant details about preregistration mechanism     |
| `VALIDATOR_PREREGISTRATION_REQUEST_TYPE`                    | `TBD`                                        | The [EIP-7685](/EIPs/EIPS/eip-7685) type prefix for preregistration request        |
| `SYSTEM_ADDRESS`                                            | `0xfffffffffffffffffffffffffffffffffffffffe` | Address used to invoke system operation on contract                          |
| `EXCESS_VALIDATOR_PREREGISTRATION_REQUESTS_STORAGE_SLOT`    | `0`                                          |                                                                              |
| `VALIDATOR_PREREGISTRATION_REQUEST_COUNT_STORAGE_SLOT`      | `1`                                          |                                                                              |
| `VALIDATOR_PREREGISTRATION_REQUEST_QUEUE_HEAD_STORAGE_SLOT` | `2`                                          | Pointer to head of the preregistration request message queue                 |
| `VALIDATOR_PREREGISTRATION_REQUEST_QUEUE_TAIL_STORAGE_SLOT` | `3`                                          | Pointer to the tail of the preregistration request message queue             |
| `VALIDATOR_PREREGISTRATION_REQUEST_QUEUE_STORAGE_OFFSET`    | `4`                                          | The start memory slot of the in-state preregistration request message queue  |
| `MAX_VALIDATOR_PREREGISTRATION_REQUESTS_PER_BLOCK`          | `4`                                          | Maximum number of preregistration requests that can be dequeued into a block |
| `TARGET_VALIDATOR_PREREGISTRATION_REQUESTS_PER_BLOCK`       | `1`                                          |                                                                              |
| `MIN_VALIDATOR_PREREGISTRATION_REQUEST_FEE`                 | `1`                                          |                                                                              |
| `VALIDATOR_PREREGISTRATION_REQUEST_FEE_UPDATE_FRACTION`     | `17`                                         |                                                                              |
| `EXCESS_INHIBITOR`                                          | `2**256-1`                                   | Excess value used to compute the fee before the first system call            |

#### Consensus layer

| Name                                                 | Value                       | Comment                                                |
| ---------------------------------------------------- | --------------------------- | ------------------------------------------------------ |
| `DOMAIN_VALIDATOR_PREREGISTRATION`                   | `DomainType(&apos;0x0E000000&apos;)`  | Uses `GENESIS_FORK_VERSION` (stable across forks)      |
| `MAX_VALIDATOR_PREREGISTRATION_REQUESTS_PER_PAYLOAD` | `uint64(2**2)` (= 4)        | Maximum preregistration requests per execution payload |
| `VALIDATOR_PREREGISTRATIONS_LIMIT`                   | `uint64(2**19)` (= 524,288) | Maximum stored preregistrations in beacon state        |
| `VALIDATOR_PREREGISTRATION_EXPIRY_SLOTS`             | `uint64(2**18)` (= 262,144) | Lifetime in finalized slots (~36 days at 12s/slot)     |

### Execution layer

#### Definitions

- **`FORK_BLOCK`** -- the first block in a blockchain after this EIP has been activated.

#### Preregistration request operation

The new preregistration request is an [EIP-7685](/EIPs/EIPS/eip-7685) request with type `VALIDATOR_PREREGISTRATION_REQUEST_TYPE` and consists of the following fields:

1. `source_address`: `Bytes20`
2. `pubkey`: `Bytes48`
3. `withdrawal_credentials`: `Bytes32`
4. `signature`: `Bytes96`

The [EIP-7685](/EIPs/EIPS/eip-7685) encoding of a preregistration request is computed as follows.

```python
request_type = VALIDATOR_PREREGISTRATION_REQUEST_TYPE
request_data = read_preregistration_requests()
```

#### Preregistration Request Contract

The contract has three different code paths, which can be summarized at a high level as follows:

1. Add preregistration request - requires a `176` byte input, the validator&apos;s public key concatenated with withdrawal credentials and a BLS signature.
2. Fee getter - if the input length is zero, return the current fee required to add a preregistration request.
3. System process - if called by system address, pop off the preregistration requests for the current block from the queue.

##### Add Preregistration Request

If call data input to the contract is exactly `176` bytes, perform the following:

1. Ensure enough ETH was sent to cover the current preregistration request fee (`check_fee()`)
2. Increase preregistration request count by `1` for the current block (`increment_count()`)
3. Insert a preregistration request into the queue for the source address, pubkey, withdrawal credentials, and signature (`insert_preregistration_request_into_queue()`)

Specifically, the functionality is defined in pseudocode as the function `add_preregistration_request()`:

```python
def add_preregistration_request(Bytes48: pubkey, Bytes32: withdrawal_credentials,
                                 Bytes96: signature):
    &quot;&quot;&quot;
    Add preregistration request adds new request to the preregistration request queue,
    so long as a sufficient fee is provided.
    &quot;&quot;&quot;

    # Verify sufficient fee was provided.
    fee = get_fee()
    require(msg.value &gt;= fee, &apos;Insufficient value for fee&apos;)

    # Increment preregistration request count.
    count = sload(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, VALIDATOR_PREREGISTRATION_REQUEST_COUNT_STORAGE_SLOT)
    sstore(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, VALIDATOR_PREREGISTRATION_REQUEST_COUNT_STORAGE_SLOT, count + 1)

    # Insert into queue.
    queue_tail_index = sload(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, VALIDATOR_PREREGISTRATION_REQUEST_QUEUE_TAIL_STORAGE_SLOT)
    queue_storage_slot = VALIDATOR_PREREGISTRATION_REQUEST_QUEUE_STORAGE_OFFSET + queue_tail_index * 7
    sstore(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot, msg.sender)
    sstore(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 1, pubkey[0:32])
    sstore(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 2, pubkey[32:48] ++ withdrawal_credentials[0:16])
    sstore(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 3, withdrawal_credentials[16:32] ++ signature[0:16])
    sstore(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 4, signature[16:48])
    sstore(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 5, signature[48:80])
    sstore(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 6, signature[80:96])
    sstore(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, VALIDATOR_PREREGISTRATION_REQUEST_QUEUE_TAIL_STORAGE_SLOT, queue_tail_index + 1)
```

###### Fee calculation

The following pseudocode can compute the cost of an individual preregistration request, given a certain number of excess preregistration requests.

```python
def get_fee() -&gt; int:
    excess = sload(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, EXCESS_VALIDATOR_PREREGISTRATION_REQUESTS_STORAGE_SLOT)
    require(excess != EXCESS_INHIBITOR, &apos;Inhibitor still active&apos;)
    return fake_exponential(
        MIN_VALIDATOR_PREREGISTRATION_REQUEST_FEE,
        excess,
        VALIDATOR_PREREGISTRATION_REQUEST_FEE_UPDATE_FRACTION
    )

def fake_exponential(factor: int, numerator: int, denominator: int) -&gt; int:
    i = 1
    output = 0
    numerator_accum = factor * denominator
    while numerator_accum &gt; 0:
        output += numerator_accum
        numerator_accum = (numerator_accum * numerator) // (denominator * i)
        i += 1
    return output // denominator
```

##### Fee Getter

When the input to the contract is length zero, interpret this as a get request for the current fee, i.e. the contract returns the result of `get_fee()`.

##### System Call

At the end of processing any execution block starting from the `FORK_BLOCK` (i.e. after processing all transactions and after performing the block body preregistration requests validations), call `VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS` as `SYSTEM_ADDRESS` with no calldata. The invocation triggers the following:

- The contract&apos;s queue is updated based on preregistration requests dequeued and the preregistration requests queue head/tail are reset if the queue has been cleared (`dequeue_preregistration_requests()`)
- The contract&apos;s excess preregistration requests are updated based on usage in the current block (`update_excess_preregistration_requests()`)
- The contract&apos;s preregistration requests count is reset to `0` (`reset_preregistration_requests_count()`)

Each preregistration request must appear in the [EIP-7685](/EIPs/EIPS/eip-7685) requests list in the exact order returned by `dequeue_preregistration_requests()`.

Additionally, the system call and the processing of that block must conform to the following:

- The call has a dedicated gas limit of `30_000_000`.
- Gas consumed by this call does not count against the block&apos;s overall gas usage.
- Both the gas limit assigned to the call and the gas consumed are excluded from any checks against the block&apos;s gas limit.
- The call does not follow [EIP-1559](/EIPs/EIPS/eip-1559) fee burn semantics -- no value should be transferred as part of this call.
- If there is no code at `VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS`, the corresponding block **MUST** be marked invalid.
- If the call to the contract fails or returns an error, the block **MUST** be invalidated.

The functionality triggered by the system call is defined in pseudocode as the function `read_preregistration_requests()`:

```python
###################
# Public function #
###################

def read_preregistration_requests():
    reqs = dequeue_preregistration_requests()
    update_excess_preregistration_requests()
    reset_preregistration_requests_count()
    return ssz.serialize(reqs)

###########
# Helpers #
###########

class PreregistrationRequest(object):
    source_address: Bytes20
    pubkey: Bytes48
    withdrawal_credentials: Bytes32
    signature: Bytes96

def dequeue_preregistration_requests():
    queue_head_index = sload(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, VALIDATOR_PREREGISTRATION_REQUEST_QUEUE_HEAD_STORAGE_SLOT)
    queue_tail_index = sload(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, VALIDATOR_PREREGISTRATION_REQUEST_QUEUE_TAIL_STORAGE_SLOT)
    num_in_queue = queue_tail_index - queue_head_index
    num_dequeued = min(num_in_queue, MAX_VALIDATOR_PREREGISTRATION_REQUESTS_PER_BLOCK)

    reqs = []
    for i in range(num_dequeued):
        queue_storage_slot = VALIDATOR_PREREGISTRATION_REQUEST_QUEUE_STORAGE_OFFSET + (queue_head_index + i) * 7
        source_address = address(sload(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot)[0:20])
        pubkey = (
            sload(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 1)[0:32]
            + sload(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 2)[0:16]
        )
        withdrawal_credentials = (
            sload(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 2)[16:32]
            + sload(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 3)[0:16]
        )
        signature = (
            sload(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 3)[16:32]
            + sload(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 4)[0:32]
            + sload(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 5)[0:32]
            + sload(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, queue_storage_slot + 6)[0:16]
        )
        req = PreregistrationRequest(
            source_address=Bytes20(source_address),
            pubkey=Bytes48(pubkey),
            withdrawal_credentials=Bytes32(withdrawal_credentials),
            signature=Bytes96(signature)
        )
        reqs.append(req)

    new_queue_head_index = queue_head_index + num_dequeued
    if new_queue_head_index == queue_tail_index:
        # Queue is empty, reset queue pointers
        sstore(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, VALIDATOR_PREREGISTRATION_REQUEST_QUEUE_HEAD_STORAGE_SLOT, 0)
        sstore(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, VALIDATOR_PREREGISTRATION_REQUEST_QUEUE_TAIL_STORAGE_SLOT, 0)
    else:
        sstore(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, VALIDATOR_PREREGISTRATION_REQUEST_QUEUE_HEAD_STORAGE_SLOT, new_queue_head_index)

    return reqs

def update_excess_preregistration_requests():
    previous_excess = sload(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, EXCESS_VALIDATOR_PREREGISTRATION_REQUESTS_STORAGE_SLOT)
    # Check if excess needs to be reset to 0 for first iteration after activation
    if previous_excess == EXCESS_INHIBITOR:
        previous_excess = 0

    count = sload(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, VALIDATOR_PREREGISTRATION_REQUEST_COUNT_STORAGE_SLOT)

    new_excess = 0
    if previous_excess + count &gt; TARGET_VALIDATOR_PREREGISTRATION_REQUESTS_PER_BLOCK:
        new_excess = previous_excess + count - TARGET_VALIDATOR_PREREGISTRATION_REQUESTS_PER_BLOCK

    sstore(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, EXCESS_VALIDATOR_PREREGISTRATION_REQUESTS_STORAGE_SLOT, new_excess)

def reset_preregistration_requests_count():
    sstore(VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS, VALIDATOR_PREREGISTRATION_REQUEST_COUNT_STORAGE_SLOT, 0)
```

##### Bytecode

TBD — the runtime bytecode will be provided with the reference implementation.

##### Deployment

TBD — the deterministic deployment transaction will be provided with the reference implementation.

### Consensus layer

A sketch of the key consensus layer changes is included below.

#### New containers

```python
class ValidatorPreregistration(Container):
    pubkey: BLSPubkey                  # 48 bytes — the validator key being registered
    withdrawal_credentials: Bytes32    # 32 bytes — withdrawal credentials to lock in

class PreregistrationRequest(Container):
    source_address: ExecutionAddress   # 20 bytes — msg.sender of the system contract call
    pubkey: BLSPubkey                  # 48 bytes
    withdrawal_credentials: Bytes32    # 32 bytes
    signature: BLSSignature            # 96 bytes — BLS proof of key ownership

class StoredPreregistration(Container):
    pubkey: BLSPubkey
    withdrawal_credentials: Bytes32
    inclusion_slot: Slot               # CL beacon slot when stored; used for expiry and Merkle provability
```

#### Modified containers

`ExecutionRequests` is extended with a new field:

```python
class ExecutionRequests(Container):
    deposits: List[DepositRequest, MAX_DEPOSIT_REQUESTS_PER_PAYLOAD]
    withdrawals: List[WithdrawalRequest, MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD]
    consolidations: List[ConsolidationRequest, MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD]
    preregistrations: List[PreregistrationRequest, MAX_VALIDATOR_PREREGISTRATION_REQUESTS_PER_PAYLOAD]  # [New]
```

Preregistration requests are processed after deposit requests. The processing order is defined by explicit `for_ops()` calls in `process_operations`, following the same pattern as deposits, withdrawals, and consolidations:

```python
# In process_operations (sketch):
for_ops(body.execution_requests.deposits, process_deposit_request)
for_ops(body.execution_requests.withdrawals, process_withdrawal_request)
for_ops(body.execution_requests.consolidations, process_consolidation_request)
for_ops(body.execution_requests.preregistrations, process_preregistration_request)  # [New]
```

`BeaconState` is extended with a new field:

```python
class BeaconState(Container):
    # ... existing fields ...
    validator_preregistrations: List[StoredPreregistration, VALIDATOR_PREREGISTRATIONS_LIMIT]  # [New]
```

#### Helper functions

```python
def get_stored_preregistration(state: BeaconState, pubkey: BLSPubkey) -&gt; Optional[StoredPreregistration]:
    for pre_reg in state.validator_preregistrations:
        if pre_reg.pubkey == pubkey:
            return pre_reg
    return None

def remove_stored_preregistration(state: BeaconState, pubkey: BLSPubkey) -&gt; None:
    state.validator_preregistrations = [
        pre_reg for pre_reg in state.validator_preregistrations
        if pre_reg.pubkey != pubkey
    ]
```

_Note_: Clients SHOULD maintain a secondary index by pubkey for efficient lookup rather than performing a linear scan.

#### Process preregistration request

```python
def process_preregistration_request(
    state: BeaconState,
    preregistration_request: PreregistrationRequest,
) -&gt; None:
    pubkey = preregistration_request.pubkey
    withdrawal_credentials = preregistration_request.withdrawal_credentials
    signature = preregistration_request.signature

    # Reject if a preregistration already exists for this pubkey
    if get_stored_preregistration(state, pubkey) is not None:
        return

    # Reject if a validator with this pubkey already exists
    if pubkey in [v.pubkey for v in state.validators]:
        return

    # Reject if this pubkey already has a valid pending deposit
    if is_pending_validator(state, pubkey):
        return

    # Reject if state list is at capacity
    if len(state.validator_preregistrations) &gt;= VALIDATOR_PREREGISTRATIONS_LIMIT:
        return

    # Verify BLS signature: proof of key ownership.
    # Domain uses GENESIS_FORK_VERSION (fork_version=None default) + genesis_validators_root.
    preregistration = ValidatorPreregistration(
        pubkey=pubkey,
        withdrawal_credentials=withdrawal_credentials,
    )
    domain = compute_domain(
        DOMAIN_VALIDATOR_PREREGISTRATION,
        genesis_validators_root=state.genesis_validators_root,
    )
    signing_root = compute_signing_root(preregistration, domain)
    if not bls.Verify(pubkey, signing_root, signature):
        return

    state.validator_preregistrations.append(StoredPreregistration(
        pubkey=pubkey,
        withdrawal_credentials=withdrawal_credentials,
        inclusion_slot=state.slot,
    ))
```

#### Modified deposit request ingestion

`process_deposit_request` is modified to enforce preregistration constraints. The preregistration check MUST precede any builder routing logic (e.g. [EIP-7732](/EIPs/EIPS/eip-7732)) to prevent bypass via builder withdrawal credentials. When a preregistration exists, the deposit is accepted only if both the withdrawal credentials match and the deposit BLS signature is valid. This early BLS check prevents an attacker from consuming a preregistration with an invalid-signature deposit (see Security Considerations).

```python
def process_deposit_request(
    state: BeaconState,
    deposit_request: DepositRequest,
) -&gt; None:
    # Preregistration check — MUST precede builder routing.
    pre_reg = get_stored_preregistration(state, deposit_request.pubkey)
    if pre_reg is not None:
        if deposit_request.withdrawal_credentials != pre_reg.withdrawal_credentials:
            return  # Withdrawal credentials mismatch: reject
        if not is_valid_deposit_signature(
            deposit_request.pubkey,
            deposit_request.withdrawal_credentials,
            deposit_request.amount,
            deposit_request.signature,
        ):
            return  # Invalid BLS sig: reject, preserve preregistration
        remove_stored_preregistration(state, deposit_request.pubkey)

    # ... [Gloas builder routing logic, if applicable] ...

    state.pending_deposits.append(PendingDeposit(
        pubkey=deposit_request.pubkey,
        withdrawal_credentials=deposit_request.withdrawal_credentials,
        amount=deposit_request.amount,
        signature=deposit_request.signature,
        slot=state.slot,
    ))
```

The key invariant: **deposits in `pending_deposits` cannot have an active preregistration.** Either the preregistration was consumed or the deposit was rejected. This means `apply_pending_deposit` requires no modifications — it operates on deposits that have already passed the preregistration check.

#### Preregistration expiry (epoch processing)

```python
def process_validator_preregistration_expiry(state: BeaconState) -&gt; None:
    finalized_slot = compute_start_slot_at_epoch(state.finalized_checkpoint.epoch)
    state.validator_preregistrations = [
        pre_reg for pre_reg in state.validator_preregistrations
        if finalized_slot &lt; Slot(pre_reg.inclusion_slot + VALIDATOR_PREREGISTRATION_EXPIRY_SLOTS)
    ]
```

Called once per epoch during `process_epoch`.

## Rationale

### Enforcement at deposit ingestion

Invalid deposits are already silently ignored by the consensus layer if the signature is invalid. This EIP adds one optional validation condition: if a preregistration exists for a pubkey, only deposits with matching withdrawal credentials and a valid BLS signature are accepted. Deposits with mismatched credentials or invalid signatures are treated as invalid and ignored. The check only applies to pubkeys that have been preregistered — all other deposits are processed as before.

### Deposit BLS verification at ingestion

Without early BLS verification, an attacker could consume a preregistration by depositing with matching withdrawal credentials but an invalid signature, stripping protection from the pubkey. This is not a new pattern — [EIP-7732](/EIPs/EIPS/eip-7732) already verifies deposit BLS signatures at block time for builder routing. Preregistration applies the same approach to the narrow subset of deposits targeting preregistered pubkeys.

### Permanent rejection of mismatched deposits

When a deposit&apos;s withdrawal credentials do not match a preregistration, the deposit is silently rejected — the ETH remains in the Deposit Contract, which has no withdrawal function. This is a deliberate design choice: returning mismatched deposits would allow an attacker to front-run at no cost (deposit, get rejected, recover funds, repeat). Permanent loss makes front-running economically self-defeating.

The risk of accidental mismatch is low in practice. Preregistration requires a dedicated BLS signing step separate from deposit data. Staking protocols verify the preregistration on-chain via [EIP-4788](/EIPs/EIPS/eip-4788) before submitting deposits. Preregistrations expire automatically after ~36 days if unused, freeing beacon state. However, because the signed message is publicly visible on-chain, anyone can replay it to re-establish the same binding after expiry. Operators should treat preregistration signing as a permanent, irrevocable decision for that key.

### System contract vs CL gossip

CL gossip has no economic cost — generating BLS keypairs is cheap (~2ms), and verification cost (~1.5ms per message) falls on every node, creating an asymmetry favoring an attacker. The EL system contract solves this with an [EIP-1559](/EIPs/EIPS/eip-1559)-style fee that starts at 1 wei but increases exponentially with demand, making sustained spam prohibitively expensive. Staking protocols can call the system contract directly from their own contracts.

### Expiry measured against finalized slot

Preregistration expiry is computed against `finalized_slot` rather than the current slot to prevent a race condition during extended non-finality (inactivity leak). During such periods, [EIP-6110](/EIPs/EIPS/eip-6110) freezes pending deposits. If preregistration expiry used the current slot, a preregistration could expire while the staking protocol&apos;s deposit transaction has not yet been included — silently removing the withdrawal credentials protection without any action by either party. Using `finalized_slot` keeps preregistrations and deposits in lockstep: neither advances while finality is stalled.

### Domain choice

`DOMAIN_VALIDATOR_PREREGISTRATION` uses `GENESIS_FORK_VERSION` (the default when no `fork_version` is passed to `compute_domain`), so a preregistration signed once is valid across all past and future forks. This allows signing on air-gapped hardware without knowledge of the current fork version. Chain separation is achieved via `genesis_validators_root`, which is an immutable per-chain constant.

A dedicated domain is used rather than reusing `DOMAIN_DEPOSIT` because `DOMAIN_DEPOSIT` does not include `genesis_validators_root`, meaning deposit-domain signatures can be replayed across chains.

### `source_address` field

`source_address` is included for [EIP-7685](/EIPs/EIPS/eip-7685) framework consistency. It is not used in CL validation — the BLS signature is the sole authorization mechanism. Any address may submit a preregistration on behalf of a key holder.

### BLS verification on CL only

BLS verification happens on the CL, not in the EL system contract. The system contract acts as a rate-limited queue; the CL performs semantic validation. EL verification would require [EIP-2537](/EIPs/EIPS/eip-2537) BLS precompiles and cost upwards of 150,000 gas per preregistration (hash-to-curve + pairing check), unnecessarily increasing cost. Invalid signatures are silently discarded by the CL, costing only the system contract fee.

### Parameter choices

`TARGET_VALIDATOR_PREREGISTRATION_REQUESTS_PER_BLOCK = 1` keeps the baseline fee minimal for an infrequent operation, with burst capacity up to 4 per block.

`VALIDATOR_PREREGISTRATIONS_LIMIT = 524,288` (2^19) is chosen so that the list cannot saturate at the target rate. At 1 preregistration per block, filling 2^19 entries takes ~72.8 days — well beyond the 2^18-slot (~36-day) expiry window. In steady state at target rate, the list stabilizes around 2^18 entries (~50% capacity) as new arrivals are balanced by expiring entries. Sustained saturation requires an average rate above target, which causes `excess` to accumulate and the fee to grow exponentially — making prolonged spam economically prohibitive.

During extended non-finality the finalized checkpoint stalls and expiry pauses, so the list may eventually fill; this is an acceptable liveness degradation for the optional preregistration path, not a safety issue, and the backlog clears once finality resumes. Worst-case state size is ~46 MB (88 bytes × 524,288 entries).

### Complementarity with EIP-7684

This EIP protects new validator creation; [EIP-7684](/EIPs/EIPS/eip-7684) protects top-ups to existing validators by returning mismatched deposits minus a penalty. Without preregistration, EIP-7684 alone turns theft into griefing (the rogue validator still exists). Without EIP-7684, preregistration does not cover mismatched top-ups. The two are orthogonal and could ship in the same fork.

### Deposit process for staking protocols

Preregistration is fully optional. Protocols that already have their own defenses can adopt it at their own pace, or not at all. For protocols that do adopt it, the intended flow is: the operator signs a preregistration, the protocol submits it to the system contract, waits for finalization (~12.8 minutes), verifies it on-chain via [EIP-4788](/EIPs/EIPS/eip-4788) Merkle proof, and submits the deposit. The verification and deposit steps can be combined into a single transaction using a shared verification contract — not part of this specification, but a reference implementation will be provided separately.

## Backwards Compatibility

This EIP introduces backward-incompatible changes to the block structure and validation rules on both the consensus and execution layers, and must be scheduled with a hard fork.

**Execution layer**: a new system contract is deployed and a new [EIP-7685](/EIPs/EIPS/eip-7685) request type is introduced.

**Consensus layer**: the `ExecutionRequests` container and `BeaconState` are extended with new fields.

## Test Cases

TBD — test vectors will be provided with the reference implementation.

## Reference Implementation

TBD

## Security Considerations

### Impact on existing deposit workflows

Preregistration is fully optional. Without a preregistration for a given pubkey, deposits are processed exactly as today — the `first-deposit-wins` rule applies unchanged. Existing validators, top-up deposits, and non-delegated staking are entirely unaffected.

**Non-delegated staking** (solo stakers, exchanges, institutions) controls both funds and keys, so the front-running vulnerability does not apply. These stakers may optionally preregister, but gain no benefit from doing so.

**Bond-based protocols** that verify withdrawal credentials via [EIP-4788](/EIPs/EIPS/eip-4788) after a pre-deposit can adopt preregistration to skip the verification delay and avoid locking capital in the entry queue. Their existing flow continues to work without changes.

**Guardian-committee protocols** that rely on `depositRoot` snapshot signing would need to update their deposit flow. Preregistration replaces the guardian infrastructure with a protocol-level guarantee, eliminating `depositRoot` rotation attacks and committee liveness dependencies.

### Preregistration signature is permanent

The preregistration signature is fork-agnostic and does not expire cryptographically — only the on-chain record has a validity window (~36 days). Anyone who obtains a signed preregistration message can resubmit it at any time to re-establish the on-chain record after expiry. Once an operator signs a preregistration binding a pubkey to specific withdrawal credentials, that commitment is effectively permanent: the signed message can always be replayed. Operators must treat preregistration signing as an irrevocable decision for that key.

### Race between preregistration and deposit

If an attacker deposits for a pubkey before the preregistration is processed, the deposit creates a validator under `first-deposit-wins` and the preregistration is rejected. If both arrive in the same block, deposits are processed before preregistrations (see processing order in `process_operations`), so the same outcome applies. Staking protocols detect this via [EIP-4788](/EIPs/EIPS/eip-4788): they MUST verify the preregistration is finalized and present in beacon state before depositing.

### Invalid-signature deposit attack

An adversary could attempt to strip preregistration protection by depositing with matching withdrawal credentials but an invalid BLS signature. This EIP prevents this attack by verifying the deposit&apos;s BLS signature in `process_deposit_request` before consuming the preregistration. Only deposits with both matching withdrawal credentials and a valid BLS signature can consume a preregistration. Invalid-signature deposits are silently rejected without affecting the preregistration.

### Builder routing interaction (EIP-7732)

When [EIP-7732](/EIPs/EIPS/eip-7732) (ePBS) builder routing is active, deposits with `0x03` (builder) withdrawal credentials are routed directly to the builder registry, bypassing the standard pending deposit flow. The preregistration withdrawal credentials check must precede builder routing in `process_deposit_request` to prevent bypass.

### DoS and state growth

The [EIP-1559](/EIPs/EIPS/eip-1559)-style fee mechanism is the primary spam defense. Every submission in a block increments `count`, and at block end `excess` updates as `excess += count − target` (floored at zero). The fee grows as `e^(excess/17)` wei, so a high-volume block raises the fee immediately for all subsequent requests. For example, at a sustained rate of `n` submissions per block, excess grows by `n − 1` per block and the fee exceeds 1 ETH after roughly `17 × ln(10^18) / (n − 1)` blocks.

Under normal operation, the state list stays near zero (preregistrations consumed within hours). The 524,288 entry limit (~46 MB) is sized so that saturation requires a sustained rate above target — and therefore an exponentially growing fee. During extended non-finality, the list may fill as expiry pauses; this degrades liveness for the optional preregistration path but is not a safety issue.

### Censorship resistance

The 262,144-slot validity window (~36 days) gives ample time for inclusion.

### Fee overpayment

The system contract does not refund excess fee payment. Callers should query the current fee via the fee getter (empty calldata) before submitting. This is the same behavior as [EIP-7002](/EIPs/EIPS/eip-7002).

### System call failure

If the system call to the preregistration contract fails for any reason, the block MUST be deemed invalid. This is the same consideration as in [EIP-7002](/EIPs/EIPS/eip-7002).

### Empty code failure

If there is no code at `VALIDATOR_PREREGISTRATION_REQUEST_PREDEPLOY_ADDRESS`, the block MUST be deemed invalid. This is the same consideration as in [EIP-7002](/EIPs/EIPS/eip-7002).

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Thu, 26 Mar 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8205</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8205</guid>
      </item>
    
      <item>
        <title>Commit-Reveal Transaction Frames</title>
        <category>Standards Track/Core</category>
        
          <comments>https://ethereum-magicians.org/t/eip-8209-commit-reveal-transaction-frames/28105</comments>
        
        <description>## Abstract

This EIP builds on top of Frame Transactions to introduce a mechanism of front-running protection using a simple commit-reveal scheme for transaction frame payloads.

It introduces two new frame modes called &quot;COMMIT&quot; and &quot;REVEAL&quot;. The &quot;COMMIT&quot; frames serve as both user commitment and an inclusion guarantee in block N-1, and &quot;REVEAL&quot; executes the payload in block N.

This approach avoids any enshrined cryptography, new consensus participant roles, or slowdowns on the critical path during block building.

## Motivation

Current Ethereum transactions expose their full contents in the mempool before they are ordered or included in a block. This puts users in a vulnerable position and enables privileged participants, often known as &quot;MEV searchers&quot;, to perform attacks against users, such as front-running, sandwiching, back-running, censorship, and others.

The outsize profitability of these attacks has in turn led to an extreme concentration of block building power in the hands of a small number of the most efficient value extractors.

Simply by introducing a delay between transaction inclusion and revelation of transaction payload, we make these attackers lose most of their advantage over regular users. Existing proposals to address this issue introduce encryption to the P2P mempool directly; see [EIP-8184](/EIPs/EIPS/eip-8184) and [EIP-8105](/EIPs/EIPS/eip-8105).

Such advanced mechanisms, when operating in sub-slot timelines with in-protocol encryption, may achieve some better properties; however, the complexity of such solutions may prevent them from being adopted by a rapidly scaling Ethereum blockchain.

## Specification

### Definitions

- **Frame Transaction**: A transaction format defined in [EIP-8141](/EIPs/EIPS/eip-8141) that contains one or more frames.
- **Frame**: A discrete unit of execution within a Frame Transaction, specifying a target, gas limit, and data.
- **COMMIT Frame**: A frame that commits to executing a payload in a future block without revealing its contents.
- **REVEAL Frame**: A frame that reveals and executes a previously committed payload.
- **Gas Payer**: The entity responsible for paying gas costs, established via the VERIFY frame&apos;s `APPROVE` mechanism.
- **Commitment**: The hash of an execution payload, stored on-chain during the COMMIT phase.

### Design goals

The purpose of this proposal is to minimize the user exposure to the most common, efficient and practical value extraction strategies while remaining pragmatic with regard to some more sophisticated potential extraction vectors.

1. Make targeted front-running attacks impossible.
2. Avoid new cryptographic primitives in the protocol.
3. Avoid new protocol participant types.
4. Minimize gas limit and sender metadata leaks.
5. Allow multiple off-protocol implementations on top of basic protocol primitives.

### Accepted trade-offs

1. Increased inclusion delay for the execution frame.
2. Accidental non-reveal triggers penalty for users.
3. Back-running and &quot;speculative front-running&quot; remain possible if not mitigated separately.

### Flow Overview

1. The user creates a Frame Transaction with a single execution frame.
2. The user hashes the payload of the execution frame.
3. The user broadcasts the Frame Transaction with its execution frame payload replaced by the payload hash.
4. The Frame Transaction gets included in block N-1, but only validation frames are executed in block N-1.
5. The execution frame payload hash is saved in block N-1 by the protocol as a &quot;commitment&quot;.
6. The user has approximately 2 seconds to broadcast the execution frame payload once slot N begins.
7. The execution frame is included in the beginning of block N, before transactions without prior &quot;commitments&quot;.

### Constants

| Name | Value | Description |
|------|-------|-------------|
| REVEAL_DEADLINE | `2` | Seconds into the slot by which revelations must be broadcast to get guaranteed inclusion |
| `COMMIT_GAS_RESERVATION` | `1_000_000` | Gas reserved per COMMIT frame |
| `MAX_COMMITS_PER_BLOCK` | `block_gas_limit // COMMIT_GAS_RESERVATION` | Maximum COMMIT frames per block |

### COMMIT Frame (Mode 0x03)

A COMMIT frame is a new mode in the [EIP-8141](/EIPs/EIPS/eip-8141) frame transaction format:

```
frame = [mode=0x03, target=0x00, gas_limit=0, data=commitment_hash]
```

- `mode = 0x03`: COMMIT.
- `target = 0x00`: No contract is called during commitment.
- `gas_limit = 0`: The frame itself does not execute EVM code.
- `data = commitment_hash`: 32-byte `keccak256` hash of the execution payload.

A frame transaction containing one or more COMMIT frames MUST have the following structure:

```
frames = [verify_frame(s), commitment_frame_1, ..., commitment_frame_k]
```

This means the included transaction is valid and execution gas is paid in advance in the current block.
There is no need for the verifying frames to reveal any direct information about the execution payload sender.

### REVEAL Frame (Mode 0x04)

A reveal frame is broadcast to the mempool as a separate [EIP-8141](/EIPs/EIPS/eip-8141) frame transaction:

```
frames = [reveal_frame1, ...]
```

The reveal frame uses the same structure as a regular frame payload, but with a distinct mode value:

```
[mode=0x04, target, gas_limit, data]
```

All `REVEAL` frame transactions MUST be included in the top of block N, before any other transactions.
A transaction cannot mix `REVEAL` frames with any other frame modes.

### Gas Reservation and Refund Mechanics

#### At Commitment Time in Block N-1

When a frame transaction containing COMMIT frames is included in block N-1:

1. The VERIFY frame executes normally, establishing the gas payer entity via `APPROVE`.
2. For each COMMIT frame, `COMMIT_GAS_RESERVATION` is charged to the gas payer at the **maximum possible next-block base fee**, calculated as `max_next_base_fee = base_fee * 1.125` (see [EIP-1559](/EIPs/EIPS/eip-1559)).
3. The transaction&apos;s intrinsic gas cost ([EIP-8141](/EIPs/EIPS/eip-8141) `FRAME_TX_INTRINSIC_COST`), including the calldata costs for the commitment hash data, is charged normally to the gas payer.
4. The transaction receipt records each commitment&apos;s index, the gas payer address, and the escrowed amount.

#### At Revelation Time in Block N

1. The `REVEAL` frames execute with a gas budget of `COMMIT_GAS_RESERVATION`.
2. Gas is priced at block N&apos;s actual base fee. No priority fee is charged.
3. After execution, the refund is calculated from the escrowed amount: `refund = escrowed_amount - (gas_used * block_N_base_fee)`. Since the escrow was charged at the maximum possible base fee, this always covers block N&apos;s actual base fee.
4. The refund is returned to the gas payer entity that was established during the VERIFY frame in block N-1.

#### On Non-Reveal

If a commitment is not consumed by any revelation in block N:

1. The `COMMIT_GAS_RESERVATION` for that commitment is burned at `max_next_base_fee` as escrowed in block N-1.
2. No EVM execution occurs - no state changes beyond the gas payment.
3. The commitment expires and is not valid if revealed in any future block.

### Inclusion Enforcement

#### Fork-Choice Enforcement

Inclusion of REVEAL transactions is enforced through fork-choice by the slot&apos;s regular attestation committee, following the same model as [EIP-7805](/EIPs/EIPS/eip-7805) (FOCIL) inclusion list enforcement.

During the first `REVEAL_DEADLINE` seconds of slot N, all validators listen on the mempool and independently record which COMMIT frame indices received valid revelations. Each attester maintains its own local view of observed revelations.

At attestation time, each attester evaluates block N against its local observation record. For every commitment index where the attester observed a valid revelation before the deadline, block N MUST include the corresponding revelation. If block N omits any revelation the attester observed, the attester MUST NOT attest to that block, causing it to lose fork-choice weight and making it non-canonical.

The builder is therefore incentivized to include all revelations it has seen, since omitting any risks losing attestations.

### Revelation Shuffle

The execution order of revelations in block N is determined by `RANDAO`. The shuffle seed is independent of commitment inclusion in block N-1 or revelation payload contents, preventing users or builders from manipulating the execution order.

### Block Validity

At most `MAX_COMMITS_PER_BLOCK` of COMMIT frames MAY appear across all transactions in the block. This cap ensures that all revelations fit within the block gas limit of block N.

Block N MUST begin with a contiguous sequence of REVEAL transactions, followed by any number of regular transactions. No other transactions MAY precede or be interleaved with REVEAL transactions.

Revelations MUST appear in the randomized order determined by the [Revelation Shuffle](#revelation-shuffle).

For every commitment in block N-1 that received a valid revelation broadcast on P2P within `REVEAL_DEADLINE` seconds, block N MUST include the corresponding revelation. This is enforced through fork-choice: attesters who observed a timely revelation MUST NOT attest to a block that omits it.

All REVEAL frames must correspond to an existing unconsumed COMMIT frame hash.

### Missed Slots

If a block is not created for slot N, the COMMIT frames do not expire and must be included in the block at slot N+1, until a valid block is produced. The original REVEAL transaction remains valid and will be included when a valid block is produced. This guarantees there is no risk in revealing the payload once block N-1 is confirmed.

### Consuming Multiple COMMIT Frames with a Single REVEAL

In order to allow REVEAL transactions with gas limits larger than `COMMIT_GAS_RESERVATION`, a REVEAL frame can indicate multiple COMMIT frames that will be consumed.

## Rationale

### Fixed 1M gas reservation

A variable gas reservation would leak information about the transaction&apos;s gas requirements. By fixing the reservation at 1M gas and allowing multi-commitment consumption, the actual gas limit is hidden within a range of `[0, k * 1M]` where `k` is the number of commitments. The 1M figure balances cost: large enough to accommodate most DeFi transactions in a single commitment, small enough that users needing more gas can split across a manageable number of commitments without excessive non-reveal penalty.

### Two-slot commit-reveal

Same-slot execution requires the builder to commit to transaction ordering before seeing execution results, creating a potential for invalid transactions to occupy block space. Two-slot separation allows the revelation to be validated before inclusion.

While this increases a perceived inclusion delay, in the optimal case the users may consider their transactions &quot;included&quot; already in block N-1.
Revelation of the payload in block N is a technicality as the REVEAL payload executes before any transactions created after block N-1 was finalized.

## Backwards Compatibility

Paymasters must explicitly support COMMIT transactions to provide gas sponsorship for commit-reveal flows.

## Security Considerations

### Speculative Front Running

While targeted front-running attacks are not possible without advance knowledge of transactions&apos; execution payloads, attackers can still pre-fill block N-1 with multiple front-running transactions wrapped in a COMMIT frame.

When block N arrives, they can decide which front-runs to reveal and execute to maximize their profits.

While this cannot be fundamentally prevented by our design, it is significantly mitigated by setting a low `MAX_COMMITS_PER_BLOCK`, high `COMMIT_GAS_RESERVATION`, and a more randomized shuffling.

### Back-Running Mitigations

The blockchain state that appears as a result of executing all `MAX_COMMITS_PER_BLOCK` and their corresponding `REVEAL` frames may be full of value extraction opportunities, such as arbitrage, liquidations, unclaimed assets, etc.

This appears to be an inherent property of a blockchain and cannot be fully mitigated. Even if the entire block payloads were encrypted in block N, the first transaction of block N+1 would have a great advantage in extracting the accumulated value. One could argue that this is the expected behavior of the system and does not require fixing.

However, in a future update, this value can be captured by the protocol as well. For example, this can be achieved by auctioning off the position below the REVEAL block to the &quot;highest bidder&quot; (or &quot;highest burner&quot;).

### Strategic Payload Withholding

The users of COMMIT transactions do get another, less intentional advantage over regular transactions.

They get to observe the world for the entire duration of slot N-1, including the plaintext transactions in block N-1, and get to make a strategic decision on whether to publish their REVEAL frame or to forego the &quot;escrowed&quot; `COMMIT_GAS_RESERVATION` fee.

We argue this is not inherently unfair to other users, as the execution payload is not known to anyone in this case, so it might as well not exist.

All the COMMIT transaction therefore does here is it grants users a top spot in the upcoming block. This is different but not necessarily worse than the current priority fee-based ordering of transactions in the block.

### Better Shuffling Randomness

With `RANDAO`-based shuffling, users cannot usually predict the order of their transactions, but the block builder can as soon as it generates the `RANDAO`.

A stronger shuffling scheme could use a Shuffle Committee, for example a set of N randomly selected validators who contribute verifiable randomness only after the `REVEAL_DEADLINE`.

### Metadata Leak via Gas Payer

The &quot;gas payer&quot; used in the VERIFY frame may reveal information about the sender of the COMMIT transaction.

This may be largely mitigated if the &quot;gas payer&quot; is a public, well-known contract with a big and diverse set of users.

## Copyright

Copyright and related rights waived via [CC0](/EIPs/LICENSE).
</description>
        <pubDate>Wed, 01 Apr 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org/EIPS/eip-8209</link>
        <guid isPermaLink="true">https://eips.ethereum.org/EIPS/eip-8209</guid>
      </item>
    
  </channel>
</rss>
